@@ -953,7 +953,7 @@ fn (mut c Amd64) lea_var_to_reg(r Register, var_offset i32) {
953953
954954 is_far_var := var_offset > 0x80 || var_offset < - 0x7f
955955 match reg {
956- .rax, .rbx, .rsi, .rdi {
956+ .rax, .rbx, .rsi, .rdi, .rdx, .rcx {
957957 c.g.write8 (0x48 )
958958 }
959959 else {}
@@ -2753,6 +2753,7 @@ fn (mut c Amd64) gen_type_promotion(from ast.Type, to ast.Type, option Amd64Regi
27532753}
27542754
27552755fn (mut c Amd64) return_stmt (node ast.Return) {
2756+ c.g.println ('; return statement {' )
27562757 mut s := '?' // ${node.exprs[0].val.str()}'
27572758 if node.exprs.len == 1 {
27582759 match node.exprs[0 ] {
@@ -2812,6 +2813,8 @@ fn (mut c Amd64) return_stmt(node ast.Return) {
28122813 c.add (Amd64 Register.rax, size % 8 )
28132814 c.add (Amd64 Register.rdx, size % 8 )
28142815 c.mov_deref (Amd64 Register.rcx, Amd64 Register.rax, ast.i64_ type_idx)
2816+ // TODO: check if it does not write too far as the size of
2817+ // the remaining data is not 64bits
28152818 c.mov_store (.rdx, .rcx, ._64 )
28162819 }
28172820 c.mov_var_to_reg (c.main_reg (), LocalVar{
@@ -2841,7 +2844,14 @@ fn (mut c Amd64) return_stmt(node ast.Return) {
28412844 offset := c.g.structs[typ.idx ()].offsets[i]
28422845 c.g.expr (expr)
28432846 // TODO: expr not on rax
2844- c.mov_reg_to_var (var, Amd64 Register.rax, offset: offset, typ: ts.mr_info ().types[i])
2847+ e_typ := ts.mr_info ().types[i]
2848+ e_ts := c.g.table.sym (e_typ)
2849+ if e_ts.info is ast.Struct {
2850+ c.lea_var_to_reg (Amd64 Register.rdx, var.offset - offset)
2851+ c.move_struct (.rdx, .rax, c.g.get_type_size (e_typ))
2852+ } else {
2853+ c.mov_reg_to_var (var, Amd64 Register.rax, offset: offset, typ: ts.mr_info ().types[i])
2854+ }
28452855 }
28462856 // store the multi return struct value
28472857 c.lea_var_to_reg (Amd64 Register.rax, var.offset)
@@ -2897,6 +2907,7 @@ fn (mut c Amd64) return_stmt(node ast.Return) {
28972907 pos: pos
28982908 }
28992909 c.g.println ('; jump to label ${label }' )
2910+ c.g.println ('; return statement }' )
29002911}
29012912
29022913fn (mut c Amd64) multi_assign_stmt (node ast.AssignStmt) {
@@ -2926,7 +2937,7 @@ fn (mut c Amd64) multi_assign_stmt(node ast.AssignStmt) {
29262937 } else {
29272938 c.g.expr (node.right[0 ])
29282939 }
2929- c.mov_reg (Amd64 Register.rdx, Amd64 Register.rax)
2940+ c.mov_reg (Amd64 Register.rdx, Amd64 Register.rax) // value of right expr(s)
29302941
29312942 mut current_offset := i32 (0 )
29322943 for i, offset in multi_return.offsets {
@@ -2943,7 +2954,7 @@ fn (mut c Amd64) multi_assign_stmt(node ast.AssignStmt) {
29432954 c.add (Amd64 Register.rdx, offset - current_offset)
29442955 current_offset = offset
29452956 }
2946- c.g.gen_left_value (node.left[i])
2957+ c.g.gen_left_value (node.left[i]) // in rax
29472958 left_type := node.left_types[i]
29482959 right_type := node.right_types[i]
29492960 if c.g.is_register_type (right_type) {
@@ -3001,11 +3012,36 @@ fn (mut c Amd64) multi_assign_stmt(node ast.AssignStmt) {
30013012 c.g.println ('movsd [rax], xmm0' )
30023013 }
30033014 } else {
3004- c.g. n_error ( '${@ LOCATION } multi return for struct is not supported yet' )
3015+ c.move_struct (.rax, .rdx, c.g. get_type_size (left_type) )
30053016 }
30063017 }
30073018}
30083019
3020+ // Moves a struct of size `_size` (in bytes) from the address stored in input to the address stored in output
3021+ fn (mut c Amd64) move_struct (output Amd64 Register, input Amd64 Register, _size i32 ) {
3022+ mut size := _size
3023+ for size != 0 {
3024+ c.mov_deref (Amd64 Register.rcx, input, ast.i64_ type_idx)
3025+ // mov_store can only move powers of 2 bytes at once
3026+ // the remainder will then get handled the next iteration for simplicity
3027+ data_size := i32 (match true {
3028+ size < 2 { 1 }
3029+ size < 4 { 2 }
3030+ size < 8 { 4 }
3031+ else { 8 }
3032+ })
3033+ c.mov_store (output, .rcx, match data_size {
3034+ 1 { ._8 }
3035+ 2 { ._16 }
3036+ 4 { ._32 }
3037+ else { ._64 }
3038+ })
3039+ size - = data_size
3040+ c.add (output, data_size)
3041+ c.add (input, data_size)
3042+ }
3043+ }
3044+
30093045fn (mut c Amd64) assign_stmt (node ast.AssignStmt) {
30103046 // `a, b := foo()`
30113047 // `a, b := if cond { 1, 2 } else { 3, 4 }`
0 commit comments