Closed
Description
One can return the functions from structs in one of the following ways. Each one of these except the last one can be made to break,
- Return structs by value - In both LLVM and C backends Handle structs as return type in C and LLVM backends #1288 implements return type of structs by value. And then create a temporary variable to store that struct value into a struct pointer. See my comment Implement List return in LLVM #955 (comment) for more details. This approach will break with structs having array as members. See the example below,
@dataclass
class MatVec:
mat: f64[2, 2]
vec: f64[2]
def create_MatVec_obj() -> MatVec:
mat: f64[2, 2] = empty((2, 2), dtype=float64)
vec: f64[2] = empty(2, dtype=float64)
mat[0, 0] = 0.0
mat[0, 1] = -1.0
mat[1, 0] = 1.0
mat[1, 1] = 0.0
vec[0] = 1.0
vec[1] = 0.0
mat_vec: MatVec = MatVec(mat, vec)
return mat_vec
def test_rotate_by_90():
mat_vec: MatVec = create_MatVec_obj()
Now in create_MatVec_obj
, the backend allocates mat
, vec
on stack (as they are not allocatables). So once call to create_MatVec_obj
completes, mat_vec.mat
and mat_vec.vec
will go out of scope and we will receive segmentation faults.
- Create an ASR to ASR pass - We can convert functions returning structs to subroutines with the struct being returned as
intent(out)
argument. This sounds good but again, it will face the same problem as the above approach when a struct will have arrays as members. In fact we may not have arrays as members directly but say a structA
has another structB
as member andB
is having arrays as members. You can see the modified example from above approach to understand the problem,
Note that this is the code will look like when we apply ASR to ASR pass to convert functions returning structs into subroutines
@dataclass
class Mat:
mat: f64[2, 2]
@dataclass
class Vec:
vec: f64[2]
@dataclass
class MatVec:
mat: Mat
vec: Vec
def create_MatVec_obj(mat_vec: MatVec):
mat: f64[2, 2] = empty((2, 2), dtype=float64)
vec: f64[2] = empty(2, dtype=float64)
mat[0, 0] = 0.0
mat[0, 1] = -1.0
mat[1, 0] = 1.0
mat[1, 1] = 0.0
vec[0] = 1.0
vec[1] = 0.0
mat_s: Mat = Mat(mat)
vec_s: Vec = Vec(vec)
mat_vec.mat = mat_s
mat_vec.vec = vec_s
return mat_vec
def test_rotate_by_90():
mat_vec: MatVec
create_MatVec_obj(mat_vec)
So the problem of array members going out of scope still exists even though we apply the ASR to ASR pass.
- Allocate every array, struct and data structures defined by structs on heap (only for LPython) - I think this is a simple and good approach and we will able to solve the problem of array members of structs going out of scope. NumPy and CPython anyways do this with every object but we will do this only for aggregate types like arrays, structs and data structures.
Metadata
Metadata
Assignees
Labels
No labels