@@ -532,42 +532,7 @@ fn (mut c Amd64) mov32(reg Amd64Register, val i32) {
532532 c.g.println ('mov32 ${reg }, ${val }' )
533533}
534534
535- // moves unsigned 64 bits, explained better in mov64
536- fn (mut c Amd64) mov64u (reg Register, val u64 ) {
537- match reg as Amd64Register {
538- .rax {
539- c.g.write8 (0x48 )
540- c.g.write8 (0xb8 )
541- }
542- .rcx {
543- c.g.write8 (0x48 )
544- c.g.write8 (0xb9 )
545- }
546- .rdx {
547- c.g.write8 (0x48 )
548- c.g.write8 (0xba )
549- }
550- .rbx {
551- c.g.write8 (0x48 )
552- c.g.write8 (0xbb )
553- }
554- .rsi {
555- c.g.write8 (0x48 )
556- c.g.write8 (0xbe )
557- }
558- .rdi {
559- c.g.write8 (0x48 )
560- c.g.write8 (0xbf )
561- }
562- else {
563- eprintln ('unhandled mov64u ${reg }' )
564- }
565- }
566- c.g.write64 (val)
567- c.g.println ('mov64 ${reg }, ${val }' )
568- }
569-
570- fn (mut c Amd64) mov64 (reg Register, val i64 ) {
535+ fn (mut c Amd64) mov64 (reg Register, val Number) {
571536 // see AMD64 Architecture Programmer's Manual Volume 3 about the MOV instruction to have a detailed explanation
572537 // about the BF (B8+rq) there is an explanation in Table 2-2 (and a bit above in 2.5.2 Opcode Syntax)
573538 // in short the 64 mov instruction is 0xB8 and after a 64 bits immediate value
@@ -945,7 +910,7 @@ fn (mut c Amd64) mov_var_to_reg(reg Register, var Var, config VarConfig) {
945910 c.g.println ('${instruction } ${reg }, ${size_str } PTR [rbp-${int (offset ).hex2 ()}] ; `${var .name }`' )
946911 }
947912 GlobalVar {
948- // TODO
913+ c.g. n_error ( '${@ LOCATION } Unsupported GlobalVar' )
949914 }
950915 }
951916}
@@ -1057,7 +1022,7 @@ fn (mut c Amd64) gen_syscall(node ast.CallExpr) {
10571022 ast.StringLiteral {
10581023 s := c.g.eval_str_lit_escape_codes (expr.expr)
10591024 c.g.allocate_string (s, 2 , .abs64 )
1060- c.mov64 (ra[i], 1 )
1025+ c.mov64 (ra[i], i64 ( 1 ) )
10611026 done = true
10621027 }
10631028 else {}
@@ -1074,7 +1039,7 @@ fn (mut c Amd64) gen_syscall(node ast.CallExpr) {
10741039 }
10751040 s := c.g.eval_str_lit_escape_codes (expr)
10761041 c.g.allocate_string (s, 2 , .abs64 )
1077- c.mov64 (ra[i], 1 )
1042+ c.mov64 (ra[i], i64 ( 1 ) )
10781043 }
10791044 else {
10801045 c.g.v_error ('Unknown syscall ${expr .type_name ()} argument type ${expr }' ,
@@ -1741,6 +1706,7 @@ fn (mut c Amd64) sub_store(a Amd64Register, b Amd64Register, size Size) {
17411706
17421707fn (mut c Amd64) mul_store (a Amd64 Register, b Amd64 Register, size Size) {
17431708 if size == ._8 {
1709+ c.g.n_error ('${@LOCATION } Unsupported size' )
17441710 } else {
17451711 if size == ._16 {
17461712 c.g.write8 (0x66 )
@@ -2096,7 +2062,7 @@ fn (mut c Amd64) assign_var(var IdentVar, raw_type ast.Type) {
20962062}
20972063
20982064// Could be nice to have left as an expr to be able to take all int assigns
2099- fn (mut c Amd64) assign_ident_int (node ast.AssignStmt, i i32 , int_lit ast.IntegerLiteral, left ast.Ident) {
2065+ fn (mut c Amd64) assign_ident_int_lit (node ast.AssignStmt, i i32 , int_lit ast.IntegerLiteral, left ast.Ident) {
21002066 match node.op {
21012067 .plus_assign {
21022068 c.mov_var_to_reg (Amd64 Register.rax, left)
@@ -2121,7 +2087,7 @@ fn (mut c Amd64) assign_ident_int(node ast.AssignStmt, i i32, int_lit ast.Intege
21212087 c.mov_reg_to_var (left, Amd64 Register.rax)
21222088 }
21232089 .decl_assign {
2124- c.allocate_var (left.name, 8 , i32 (int_lit.val.int ()))
2090+ c.allocate_var (left.name, 8 , i64 (int_lit.val.int ()))
21252091 }
21262092 .assign {
21272093 c.mov (Amd64 Register.rax, i32 (int_lit.val.int ()))
@@ -2216,18 +2182,33 @@ fn (mut c Amd64) mov_float_xmm0_var(reg Amd64Register, var_type ast.Type) {
22162182fn (mut c Amd64) assign_ident_right_expr (node ast.AssignStmt, i i32 , right ast.Expr, name string , ident ast.Ident) {
22172183 match right {
22182184 ast.IntegerLiteral {
2185+ // a = 230 // no cast, just a int literal
2186+ // TODO: when V changes int (not fixed i32), change the size of the assigns
22192187 left_type := node.left_types[i]
22202188 if left_type.is_pure_float () {
22212189 c.assign_float (node, i, right, ident)
22222190 } else {
2223- c.assign_ident_int (node, i, right, ident)
2191+ c.assign_ident_int_lit (node, i, right, ident)
2192+ }
2193+ }
2194+ ast.EnumVal {
2195+ type_name := c.g.table.get_type_name (right.typ)
2196+ enum_info := c.g.enum_vals[type_name]
2197+ val := enum_info.fields[right.val] or {
2198+ c.g.n_error ('${@LOCATION } enum field not found ${right .val }' )
2199+ }
2200+ if node.op == .decl_assign {
2201+ c.allocate_var (ident.name, enum_info.size, val)
2202+ } else {
2203+ c.mov64 (Amd64 Register.rax, val)
2204+ c.mov_reg_to_var (ident, Amd64 Register.rax)
22242205 }
22252206 }
22262207 ast.FloatLiteral {
22272208 c.assign_float (node, i, right, ident)
22282209 }
22292210 ast.StringLiteral {
2230- dest := c.allocate_var (name, 8 , 0 )
2211+ dest := c.allocate_var (name, 8 , i64 ( 0 ) )
22312212 ie := right as ast.StringLiteral
22322213 str := c.g.eval_str_lit_escape_codes (ie)
22332214 c.learel (Amd64 Register.rsi, c.g.allocate_string (str, 3 , .rel32 ))
@@ -2270,7 +2251,7 @@ fn (mut c Amd64) assign_ident_right_expr(node ast.AssignStmt, i i32, right ast.E
22702251 return
22712252 }
22722253 ast.AtExpr {
2273- dest := c.allocate_var (name, 8 , 0 )
2254+ dest := c.allocate_var (name, 8 , i64 ( 0 ) )
22742255 c.learel (Amd64 Register.rsi, c.g.allocate_string (c.g.comptime_at (right), 3 ,
22752256 .rel32 ))
22762257 c.mov_reg_to_var (LocalVar{dest, ast.u64_ type_idx, name}, Amd64 Register.rsi)
@@ -2827,8 +2808,18 @@ fn (mut c Amd64) assign_stmt(node ast.AssignStmt) {
28272808 }
28282809 }
28292810 .enum {
2830- // TODO: fix sizes
2831- c.mov_store (.rdx, .rax, ._32 )
2811+ size := c.g.get_type_size (var_type)
2812+ if size == 4 {
2813+ c.mov_store (.rdx, .rax, ._32 )
2814+ } else if size == 8 {
2815+ c.mov_store (.rdx, .rax, ._64 )
2816+ } else if size == 2 {
2817+ c.mov_store (.rdx, .rax, ._16 )
2818+ } else if size == 1 {
2819+ c.mov_store (.rdx, .rax, ._8 )
2820+ } else {
2821+ c.g.n_error ('${@LOCATION } Unsupported enum size assignment' )
2822+ }
28322823 }
28332824 else {
28342825 c.g.n_error ('${@LOCATION } Unsupported expression SelectorExpr ${ts .kind }' )
@@ -2893,7 +2884,7 @@ fn (mut c Amd64) prefix_expr(node ast.PrefixExpr) {
28932884 c.g.expr (node.right)
28942885 c.cmp_zero (Amd64 Register.rax)
28952886 // TODO: mov_extend_reg
2896- c.mov64 (Amd64 Register.rax, 0 )
2887+ c.mov64 (Amd64 Register.rax, i64 ( 0 ) )
28972888 c.cset (.e)
28982889 }
28992890 .bit_not {
@@ -2930,7 +2921,7 @@ fn (mut c Amd64) fp_infix_expr(node ast.InfixExpr, left_type ast.Type) {
29302921 .gt, .lt, .ge, .le {
29312922 c.cmp_sse (.xmm0 , .xmm1 , left_type)
29322923 // TODO: mov_extend_reg
2933- c.mov64 (Amd64 Register.rax, 0 )
2924+ c.mov64 (Amd64 Register.rax, i64 ( 0 ) )
29342925 c.cset (match node.op {
29352926 .gt { .a }
29362927 .lt { .b }
@@ -3010,7 +3001,7 @@ fn (mut c Amd64) infix_expr(node ast.InfixExpr) {
30103001 .eq, .ne, .gt, .lt, .ge, .le {
30113002 c.cmp_reg (.rax, .rdx)
30123003 // TODO: mov_extend_reg
3013- c.mov64 (Amd64 Register.rax, 0 )
3004+ c.mov64 (Amd64 Register.rax, i64 ( 0 ) )
30143005 c.cset_op (node.op)
30153006 }
30163007 .plus {
@@ -3326,7 +3317,7 @@ fn (mut c Amd64) fn_decl(node ast.FnDecl) {
33263317 // define defer vars
33273318 for i in 0 .. node.defer_stmts.len {
33283319 name := '_defer${i }'
3329- c.allocate_var (name, 8 , 0 )
3320+ c.allocate_var (name, 8 , i64 ( 0 ) )
33303321 }
33313322 // body
33323323 c.g.stmts (node.stmts)
@@ -3366,13 +3357,12 @@ pub fn (mut c Amd64) builtin_decl(builtin BuiltinFn) {
33663357 c.leave ()
33673358}
33683359
3369- pub fn (mut c Amd64) allocate_var_two_step (name string , size i32 , initial_val i32 ) i32 {
3370- // TODO: replace i32 by i64 or bigger
3371- c.allocate_var (name, size - 8 , 0 )
3360+ pub fn (mut c Amd64) allocate_var_two_step (name string , size i32 , initial_val Number) i32 {
3361+ c.allocate_var (name, size - 8 , i64 (0 ))
33723362 return c.allocate_var (name, 8 , initial_val)
33733363}
33743364
3375- pub fn (mut c Amd64) allocate_var (name string , size i32 , initial_val i 32 ) i32 {
3365+ pub fn (mut c Amd64) allocate_var (name string , size i32 , initial_val Number ) i32 {
33763366 if size > 8 {
33773367 return c.allocate_var_two_step (name, size, initial_val)
33783368 }
@@ -3387,51 +3377,83 @@ pub fn (mut c Amd64) allocate_var(name string, size i32, initial_val i32) i32 {
33873377 // BYTE
33883378 c.g.write8 (0xc6 )
33893379 c.g.write8 (i32 (0x45 ) + far_var_offset)
3380+ // Generate N in `[rbp-N]`
3381+ if is_far_var {
3382+ c.g.write32 (i32 ((0xffffffff - i64 (n) + 1 ) % 0x100000000 ))
3383+ } else {
3384+ c.g.write8 (i32 ((0xff - n + 1 ) % 0x100 ))
3385+ }
3386+ c.g.stack_var_pos + = size + padding
3387+ c.g.var_offset[name] = c.g.stack_var_pos
3388+ c.g.var_alloc_size[name] = size
3389+ // Generate the value assigned to the variable
3390+ match initial_val {
3391+ i64 {
3392+ c.g.write8 (i32 (initial_val as i64 ))
3393+ }
3394+ u64 {
3395+ c.g.write8 (i32 (initial_val as u64 ))
3396+ }
3397+ }
33903398 }
33913399 2 {
33923400 // WORD
33933401 c.g.write8 (0x66 )
33943402 c.g.write8 (0xc7 )
33953403 c.g.write8 (i32 (0x45 ) + far_var_offset)
3404+ // Generate N in `[rbp-N]`
3405+ if is_far_var {
3406+ c.g.write32 (i32 ((0xffffffff - i64 (n) + 1 ) % 0x100000000 ))
3407+ } else {
3408+ c.g.write8 (i32 ((0xff - n + 1 ) % 0x100 ))
3409+ }
3410+ c.g.stack_var_pos + = size + padding
3411+ c.g.var_offset[name] = c.g.stack_var_pos
3412+ c.g.var_alloc_size[name] = size
3413+ // Generate the value assigned to the variable
3414+ match initial_val {
3415+ i64 {
3416+ c.g.write16 (i32 (initial_val as i64 ))
3417+ }
3418+ u64 {
3419+ c.g.write16 (i32 (initial_val as u64 ))
3420+ }
3421+ }
33963422 }
33973423 4 {
33983424 // DWORD
33993425 c.g.write8 (0xc7 )
34003426 c.g.write8 (i32 (0x45 ) + far_var_offset)
3427+ // Generate N in `[rbp-N]`
3428+ if is_far_var {
3429+ c.g.write32 (i32 ((0xffffffff - i64 (n) + 1 ) % 0x100000000 ))
3430+ } else {
3431+ c.g.write8 (i32 ((0xff - n + 1 ) % 0x100 ))
3432+ }
3433+ c.g.stack_var_pos + = size + padding
3434+ c.g.var_offset[name] = c.g.stack_var_pos
3435+ c.g.var_alloc_size[name] = size
3436+ // Generate the value assigned to the variable
3437+ match initial_val {
3438+ i64 {
3439+ c.g.write32 (i32 (initial_val as i64 ))
3440+ }
3441+ u64 {
3442+ c.g.write32 (i32 (initial_val as u64 ))
3443+ }
3444+ }
34013445 }
34023446 8 {
34033447 // QWORD
3404- c.g.write8 (0x48 )
3405- c.g.write8 (0xc7 )
3406- c.g.write8 (i32 (0x45 ) + far_var_offset)
3407- }
3408- else {
3409- c.g.n_error ('${@LOCATION } bad size ${int (size )}' )
3410- }
3411- }
3412- // Generate N in `[rbp-N]`
3413- if is_far_var {
3414- c.g.write32 (i32 ((0xffffffff - i64 (n) + 1 ) % 0x100000000 ))
3415- } else {
3416- c.g.write8 (i32 ((0xff - n + 1 ) % 0x100 ))
3417- }
3418- c.g.stack_var_pos + = size + padding
3419- c.g.var_offset[name] = c.g.stack_var_pos
3420- c.g.var_alloc_size[name] = size
3448+ // Can not move directly an immediate value of 64 bits in a 64 bits register
34213449
3422- // Generate the value assigned to the variable
3423- match size {
3424- 1 {
3425- c.g.write8 (initial_val)
3426- }
3427- 2 {
3428- c.g.write16 (initial_val)
3429- }
3430- 4 {
3431- c.g.write32 (initial_val)
3432- }
3433- 8 {
3434- c.g.write32 (initial_val) // fixme: 64-bit segfaulting
3450+ c.g.stack_var_pos + = size + padding
3451+ c.g.var_offset[name] = c.g.stack_var_pos
3452+ c.g.var_alloc_size[name] = size
3453+
3454+ c.lea_var_to_reg (Amd64 Register.rax, c.g.var_offset[name])
3455+ c.mov64 (Amd64 Register.rdx, initial_val)
3456+ c.mov_store (.rax, .rdx, ._64 )
34353457 }
34363458 else {
34373459 c.g.n_error ('${@LOCATION } bad size ${int (size )}' )
0 commit comments