@@ -532,42 +532,7 @@ fn (mut c Amd64) mov32(reg Amd64Register, val i32) {
532
532
c.g.println ('mov32 ${reg} , ${val} ' )
533
533
}
534
534
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) {
571
536
// see AMD64 Architecture Programmer's Manual Volume 3 about the MOV instruction to have a detailed explanation
572
537
// about the BF (B8+rq) there is an explanation in Table 2-2 (and a bit above in 2.5.2 Opcode Syntax)
573
538
// 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) {
945
910
c.g.println ('${instruction} ${reg} , ${size_str} PTR [rbp-${int(offset).hex2()} ] ; `${var.name} `' )
946
911
}
947
912
GlobalVar {
948
- // TODO
913
+ c.g. n_error ( ' ${@LOCATION} Unsupported GlobalVar' )
949
914
}
950
915
}
951
916
}
@@ -1057,7 +1022,7 @@ fn (mut c Amd64) gen_syscall(node ast.CallExpr) {
1057
1022
ast.StringLiteral {
1058
1023
s := c.g.eval_str_lit_escape_codes (expr.expr)
1059
1024
c.g.allocate_string (s, 2 , .abs64 )
1060
- c.mov64 (ra[i], 1 )
1025
+ c.mov64 (ra[i], i64 ( 1 ) )
1061
1026
done = true
1062
1027
}
1063
1028
else {}
@@ -1074,7 +1039,7 @@ fn (mut c Amd64) gen_syscall(node ast.CallExpr) {
1074
1039
}
1075
1040
s := c.g.eval_str_lit_escape_codes (expr)
1076
1041
c.g.allocate_string (s, 2 , .abs64 )
1077
- c.mov64 (ra[i], 1 )
1042
+ c.mov64 (ra[i], i64 ( 1 ) )
1078
1043
}
1079
1044
else {
1080
1045
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) {
1741
1706
1742
1707
fn (mut c Amd64) mul_store (a Amd64 Register, b Amd64 Register, size Size) {
1743
1708
if size == ._8 {
1709
+ c.g.n_error ('${@LOCATION} Unsupported size' )
1744
1710
} else {
1745
1711
if size == ._16 {
1746
1712
c.g.write8 (0x66 )
@@ -2096,7 +2062,7 @@ fn (mut c Amd64) assign_var(var IdentVar, raw_type ast.Type) {
2096
2062
}
2097
2063
2098
2064
// 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) {
2100
2066
match node.op {
2101
2067
.plus_assign {
2102
2068
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
2121
2087
c.mov_reg_to_var (left, Amd64 Register.rax)
2122
2088
}
2123
2089
.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 ()))
2125
2091
}
2126
2092
.assign {
2127
2093
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) {
2216
2182
fn (mut c Amd64) assign_ident_right_expr (node ast.AssignStmt, i i32 , right ast.Expr, name string , ident ast.Ident) {
2217
2183
match right {
2218
2184
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
2219
2187
left_type := node.left_types[i]
2220
2188
if left_type.is_pure_float () {
2221
2189
c.assign_float (node, i, right, ident)
2222
2190
} 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)
2224
2205
}
2225
2206
}
2226
2207
ast.FloatLiteral {
2227
2208
c.assign_float (node, i, right, ident)
2228
2209
}
2229
2210
ast.StringLiteral {
2230
- dest := c.allocate_var (name, 8 , 0 )
2211
+ dest := c.allocate_var (name, 8 , i64 ( 0 ) )
2231
2212
ie := right as ast.StringLiteral
2232
2213
str := c.g.eval_str_lit_escape_codes (ie)
2233
2214
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
2270
2251
return
2271
2252
}
2272
2253
ast.AtExpr {
2273
- dest := c.allocate_var (name, 8 , 0 )
2254
+ dest := c.allocate_var (name, 8 , i64 ( 0 ) )
2274
2255
c.learel (Amd64 Register.rsi, c.g.allocate_string (c.g.comptime_at (right), 3 ,
2275
2256
.rel32 ))
2276
2257
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) {
2827
2808
}
2828
2809
}
2829
2810
.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
+ }
2832
2823
}
2833
2824
else {
2834
2825
c.g.n_error ('${@LOCATION} Unsupported expression SelectorExpr ${ts.kind} ' )
@@ -2893,7 +2884,7 @@ fn (mut c Amd64) prefix_expr(node ast.PrefixExpr) {
2893
2884
c.g.expr (node.right)
2894
2885
c.cmp_zero (Amd64 Register.rax)
2895
2886
// TODO: mov_extend_reg
2896
- c.mov64 (Amd64 Register.rax, 0 )
2887
+ c.mov64 (Amd64 Register.rax, i64 ( 0 ) )
2897
2888
c.cset (.e)
2898
2889
}
2899
2890
.bit_not {
@@ -2930,7 +2921,7 @@ fn (mut c Amd64) fp_infix_expr(node ast.InfixExpr, left_type ast.Type) {
2930
2921
.gt, .lt, .ge, .le {
2931
2922
c.cmp_sse (.xmm0 , .xmm1 , left_type)
2932
2923
// TODO: mov_extend_reg
2933
- c.mov64 (Amd64 Register.rax, 0 )
2924
+ c.mov64 (Amd64 Register.rax, i64 ( 0 ) )
2934
2925
c.cset (match node.op {
2935
2926
.gt { .a }
2936
2927
.lt { .b }
@@ -3010,7 +3001,7 @@ fn (mut c Amd64) infix_expr(node ast.InfixExpr) {
3010
3001
.eq, .ne, .gt, .lt, .ge, .le {
3011
3002
c.cmp_reg (.rax, .rdx)
3012
3003
// TODO: mov_extend_reg
3013
- c.mov64 (Amd64 Register.rax, 0 )
3004
+ c.mov64 (Amd64 Register.rax, i64 ( 0 ) )
3014
3005
c.cset_op (node.op)
3015
3006
}
3016
3007
.plus {
@@ -3326,7 +3317,7 @@ fn (mut c Amd64) fn_decl(node ast.FnDecl) {
3326
3317
// define defer vars
3327
3318
for i in 0 .. node.defer_stmts.len {
3328
3319
name := '_defer${i} '
3329
- c.allocate_var (name, 8 , 0 )
3320
+ c.allocate_var (name, 8 , i64 ( 0 ) )
3330
3321
}
3331
3322
// body
3332
3323
c.g.stmts (node.stmts)
@@ -3366,13 +3357,12 @@ pub fn (mut c Amd64) builtin_decl(builtin BuiltinFn) {
3366
3357
c.leave ()
3367
3358
}
3368
3359
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 ))
3372
3362
return c.allocate_var (name, 8 , initial_val)
3373
3363
}
3374
3364
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 {
3376
3366
if size > 8 {
3377
3367
return c.allocate_var_two_step (name, size, initial_val)
3378
3368
}
@@ -3387,51 +3377,83 @@ pub fn (mut c Amd64) allocate_var(name string, size i32, initial_val i32) i32 {
3387
3377
// BYTE
3388
3378
c.g.write8 (0xc6 )
3389
3379
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
+ }
3390
3398
}
3391
3399
2 {
3392
3400
// WORD
3393
3401
c.g.write8 (0x66 )
3394
3402
c.g.write8 (0xc7 )
3395
3403
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
+ }
3396
3422
}
3397
3423
4 {
3398
3424
// DWORD
3399
3425
c.g.write8 (0xc7 )
3400
3426
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
+ }
3401
3445
}
3402
3446
8 {
3403
3447
// 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
3421
3449
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 )
3435
3457
}
3436
3458
else {
3437
3459
c.g.n_error ('${@LOCATION} bad size ${int(size)} ' )
0 commit comments