Skip to content

Commit fd479a2

Browse files
authored
native: support more assign ops, reduce code duplication (#25283)
1 parent c2e2aac commit fd479a2

2 files changed

Lines changed: 189 additions & 151 deletions

File tree

‎vlib/v/gen/native/amd64.v‎

Lines changed: 107 additions & 151 deletions
Original file line numberDiff line numberDiff line change
@@ -1753,10 +1753,8 @@ fn (mut c Amd64) mov(r Register, val i32) {
17531753
}
17541754
}
17551755

1756-
fn (mut c Amd64) mul_reg(a Amd64Register, b Amd64Register) {
1757-
if a != .rax {
1758-
c.g.n_error('mul always operates on rax')
1759-
}
1756+
// rax times b
1757+
fn (mut c Amd64) mul_reg_rax(b Amd64Register) {
17601758
match b {
17611759
.rax {
17621760
c.g.write8(0x48)
@@ -1799,10 +1797,8 @@ fn (mut c Amd64) imul_reg(r Amd64Register) {
17991797
}
18001798
}
18011799

1802-
fn (mut c Amd64) div_reg(a Amd64Register, b Amd64Register) {
1803-
if a != .rax {
1804-
c.g.n_error('div always operates on rax')
1805-
}
1800+
// rax divided by b
1801+
fn (mut c Amd64) div_reg_rax(b Amd64Register) {
18061802
match b {
18071803
.rax {
18081804
c.g.write8(0x48)
@@ -1831,8 +1827,9 @@ fn (mut c Amd64) div_reg(a Amd64Register, b Amd64Register) {
18311827
c.g.println('div ${b}')
18321828
}
18331829

1834-
fn (mut c Amd64) mod_reg(a Amd64Register, b Amd64Register) {
1835-
c.div_reg(a, b)
1830+
// rax % b
1831+
fn (mut c Amd64) mod_reg_rax(b Amd64Register) {
1832+
c.div_reg_rax(b)
18361833
c.mov_reg(Amd64Register.rdx, Amd64Register.rax)
18371834
}
18381835

@@ -2287,93 +2284,30 @@ fn (mut c Amd64) assign_var(var IdentVar, raw_type ast.Type) {
22872284
// TODO: may have a problem if the literal is bigger than max_i64: needs u64
22882285
fn (mut c Amd64) assign_ident_int_lit(node ast.AssignStmt, i i32, int_lit ast.IntegerLiteral, left ast.Ident) {
22892286
match node.op {
2290-
.plus_assign {
2291-
c.mov_var_to_reg(Amd64Register.rax, left)
2292-
c.mov64(Amd64Register.rdx, i64(int_lit.val.int()))
2293-
c.add_reg(Amd64Register.rax, Amd64Register.rdx)
2294-
c.mov_reg_to_var(left, Amd64Register.rax)
2295-
}
2296-
.minus_assign {
2297-
c.mov_var_to_reg(Amd64Register.rax, left)
2298-
c.mov64(Amd64Register.rdx, i64(int_lit.val.int()))
2299-
c.sub_reg(Amd64Register.rax, Amd64Register.rdx)
2300-
c.mov_reg_to_var(left, Amd64Register.rax)
2301-
}
2302-
.mult_assign {
2303-
c.mov_var_to_reg(Amd64Register.rax, left)
2304-
c.mov64(Amd64Register.rdx, i64(int_lit.val.int()))
2305-
c.mul_reg(.rax, .rdx)
2306-
c.mov_reg_to_var(left, Amd64Register.rax)
2307-
}
2308-
.div_assign {
2309-
c.mov_var_to_reg(Amd64Register.rax, left)
2310-
c.mov64(Amd64Register.rdx, i64(int_lit.val.int()))
2311-
c.div_reg(.rax, .rdx)
2312-
c.mov_reg_to_var(left, Amd64Register.rax)
2313-
}
2314-
.mod_assign {
2315-
c.mov_var_to_reg(Amd64Register.rax, left)
2316-
c.mov64(Amd64Register.rdx, i64(int_lit.val.int()))
2317-
c.mod_reg(.rax, .rdx)
2318-
c.mov_reg_to_var(left, Amd64Register.rax)
2319-
}
23202287
.decl_assign {
23212288
c.allocate_var(left.name, 8, i64(int_lit.val.int()))
23222289
}
23232290
.assign {
23242291
c.mov64(Amd64Register.rax, i64(int_lit.val.int()))
23252292
c.mov_reg_to_var(left, Amd64Register.rax)
23262293
}
2327-
.left_shift_assign {
2328-
c.mov_var_to_reg(Amd64Register.rax, left)
2329-
c.mov64(Amd64Register.rcx, i64(int_lit.val.int()))
2330-
c.shl_reg(.rax, .rcx)
2331-
c.mov_reg_to_var(left, Amd64Register.rax)
2332-
}
2333-
.right_shift_assign {
2334-
c.mov_var_to_reg(Amd64Register.rax, left)
2335-
c.mov64(Amd64Register.rcx, i64(int_lit.val.int()))
2336-
c.sar_reg(.rax, .rcx)
2337-
c.mov_reg_to_var(left, Amd64Register.rax)
2338-
}
2339-
.unsigned_right_shift_assign {
2340-
c.mov_var_to_reg(Amd64Register.rax, left)
2341-
c.mov64(Amd64Register.rcx, i64(int_lit.val.int()))
2342-
c.shr_reg(.rax, .rcx)
2343-
c.mov_reg_to_var(left, Amd64Register.rax)
2344-
}
2345-
.xor_assign {
2346-
c.mov_var_to_reg(Amd64Register.rax, left)
2347-
c.mov64(Amd64Register.rcx, i64(int_lit.val.int()))
2348-
c.bitxor_reg(.rax, .rcx)
2349-
c.mov_reg_to_var(left, Amd64Register.rax)
2350-
}
2351-
.or_assign {
2352-
c.mov_var_to_reg(Amd64Register.rax, left)
2353-
c.mov64(Amd64Register.rcx, i64(int_lit.val.int()))
2354-
c.bitor_reg(.rax, .rcx)
2355-
c.mov_reg_to_var(left, Amd64Register.rax)
2356-
}
2357-
.and_assign {
2358-
c.mov_var_to_reg(Amd64Register.rax, left)
2359-
c.mov64(Amd64Register.rcx, i64(int_lit.val.int()))
2360-
c.bitand_reg(.rax, .rcx)
2361-
c.mov_reg_to_var(left, Amd64Register.rax)
2362-
}
23632294
.boolean_and_assign {
23642295
c.mov_var_to_reg(Amd64Register.rax, left)
2365-
c.mov64(Amd64Register.rcx, i64(int_lit.val.int()))
2366-
c.bitand_reg(.rax, .rcx)
2296+
c.mov64(Amd64Register.rbx, i64(int_lit.val.int()))
2297+
c.bitand_reg(.rax, .rbx)
23672298
c.mov_reg_to_var(left, Amd64Register.rax)
23682299
}
23692300
.boolean_or_assign {
23702301
c.mov_var_to_reg(Amd64Register.rax, left)
2371-
c.mov64(Amd64Register.rcx, i64(int_lit.val.int()))
2372-
c.bitor_reg(.rax, .rcx)
2302+
c.mov64(Amd64Register.rbx, i64(int_lit.val.int()))
2303+
c.bitor_reg(.rax, .rbx)
23732304
c.mov_reg_to_var(left, Amd64Register.rax)
23742305
}
23752306
else {
2376-
c.g.n_error('${@LOCATION} unexpected assignment op ${node.op}')
2307+
c.mov_var_to_reg(Amd64Register.rax, left)
2308+
c.mov64(Amd64Register.rbx, i64(int_lit.val.int()))
2309+
c.apply_op_int(.rax, .rbx, node.op)
2310+
c.mov_reg_to_var(left, Amd64Register.rax)
23772311
}
23782312
}
23792313
}
@@ -2591,19 +2525,26 @@ fn (mut c Amd64) assign_ident_right_expr(node ast.AssignStmt, i i32, right ast.E
25912525

25922526
c.mov_ssereg_to_var(ident, .xmm1)
25932527
} else if left_type.is_int() {
2594-
c.mov_var_to_reg(Amd64Register.rbx, ident)
2595-
2528+
c.mov_reg(Amd64Register.rbx, Amd64Register.rax)
2529+
c.mov_var_to_reg(Amd64Register.rax, ident)
2530+
c.apply_op_int(.rax, .rbx, node.op)
2531+
c.mov_reg_to_var(ident, Amd64Register.rax)
2532+
} else {
25962533
match node.op {
2597-
.plus_assign { c.add_reg(.rbx, .rax) }
2598-
.minus_assign { c.sub_reg(.rbx, .rax) }
2599-
.div_assign { c.div_reg(.rbx, .rax) }
2600-
.mult_assign { c.mul_reg(.rbx, .rax) }
2601-
else { c.g.n_error('${@LOCATION} unexpected assignment operator ${node.op} for i32') }
2534+
.boolean_and_assign {
2535+
c.mov_var_to_reg(Amd64Register.rbx, ident)
2536+
c.bitand_reg(.rbx, .rax)
2537+
c.mov_reg_to_var(ident, Amd64Register.rbx)
2538+
}
2539+
.boolean_or_assign {
2540+
c.mov_var_to_reg(Amd64Register.rbx, ident)
2541+
c.bitor_reg(.rbx, .rax)
2542+
c.mov_reg_to_var(ident, Amd64Register.rbx)
2543+
}
2544+
else {
2545+
c.g.n_error('${@LOCATION} assignment arithmetic not implemented for type ${node.left_types[i]}')
2546+
}
26022547
}
2603-
2604-
c.mov_reg_to_var(ident, Amd64Register.rbx)
2605-
} else {
2606-
c.g.n_error('${@LOCATION} assignment arithmetic not implemented for type ${node.left_types[i]}')
26072548
}
26082549
}
26092550
}
@@ -2631,19 +2572,26 @@ fn (mut c Amd64) assign_ident_right_expr(node ast.AssignStmt, i i32, right ast.E
26312572

26322573
c.mov_ssereg_to_var(ident, .xmm1)
26332574
} else if left_type.is_int() {
2634-
c.mov_var_to_reg(Amd64Register.rbx, ident)
2635-
2575+
c.mov_reg(Amd64Register.rbx, Amd64Register.rax)
2576+
c.mov_var_to_reg(Amd64Register.rax, ident)
2577+
c.apply_op_int(.rax, .rbx, node.op)
2578+
c.mov_reg_to_var(ident, Amd64Register.rax)
2579+
} else {
26362580
match node.op {
2637-
.plus_assign { c.add_reg(.rbx, .rax) }
2638-
.minus_assign { c.sub_reg(.rbx, .rax) }
2639-
.div_assign { c.div_reg(.rbx, .rax) }
2640-
.mult_assign { c.mul_reg(.rbx, .rax) }
2641-
else { c.g.n_error('${@LOCATION} unexpected assignment operator ${node.op} for i32') }
2581+
.boolean_and_assign {
2582+
c.mov_var_to_reg(Amd64Register.rbx, ident)
2583+
c.bitand_reg(.rbx, .rax)
2584+
c.mov_reg_to_var(ident, Amd64Register.rbx)
2585+
}
2586+
.boolean_or_assign {
2587+
c.mov_var_to_reg(Amd64Register.rbx, ident)
2588+
c.bitor_reg(.rbx, .rax)
2589+
c.mov_reg_to_var(ident, Amd64Register.rbx)
2590+
}
2591+
else {
2592+
c.g.n_error('${@LOCATION} assignment arithmetic not implemented for type ${node.left_types[i]}')
2593+
}
26422594
}
2643-
2644-
c.mov_reg_to_var(ident, Amd64Register.rbx)
2645-
} else {
2646-
c.g.n_error('${@LOCATION} assignment arithmetic not implemented for type ${node.left_types[i]}')
26472595
}
26482596
}
26492597
}
@@ -2680,6 +2628,59 @@ fn (mut c Amd64) assign_ident_right_expr(node ast.AssignStmt, i i32, right ast.E
26802628
}*/
26812629
}
26822630

2631+
// /!\ for div, mul, mod the left value should always be .rax
2632+
fn (mut c Amd64) apply_op_int(left_value Amd64Register, right_value Amd64Register, op token.Kind) {
2633+
match op {
2634+
.plus_assign {
2635+
c.add_reg(left_value, right_value)
2636+
}
2637+
.minus_assign {
2638+
c.sub_reg(left_value, right_value)
2639+
}
2640+
.div_assign {
2641+
if left_value != .rax {
2642+
c.g.n_error('@{LOCATION} div always operates on rax')
2643+
}
2644+
c.mov(Amd64Register.rdx, i32(0)) // 64bits IDIV uses RDX:RAX
2645+
c.div_reg_rax(right_value)
2646+
}
2647+
.mult_assign {
2648+
if left_value != .rax {
2649+
c.g.n_error('@{LOCATION} mul always operates on rax')
2650+
}
2651+
c.mul_reg_rax(right_value)
2652+
}
2653+
.xor_assign {
2654+
c.bitxor_reg(left_value, right_value)
2655+
}
2656+
.mod_assign {
2657+
if left_value != .rax {
2658+
c.g.n_error('@{LOCATION} mod always operates on rax')
2659+
}
2660+
c.mov(Amd64Register.rdx, i32(0)) // 64bits IDIV uses RDX:RAX
2661+
c.mod_reg_rax(right_value)
2662+
}
2663+
.or_assign {
2664+
c.bitor_reg(left_value, right_value)
2665+
}
2666+
.and_assign {
2667+
c.bitand_reg(left_value, right_value)
2668+
}
2669+
.right_shift_assign {
2670+
c.shr_reg(left_value, right_value)
2671+
}
2672+
.left_shift_assign {
2673+
c.shl_reg(left_value, right_value)
2674+
}
2675+
.unsigned_right_shift_assign {
2676+
c.sar_reg(left_value, right_value)
2677+
}
2678+
else {
2679+
c.g.n_error('${@LOCATION} unexpected operator ${op} for int')
2680+
}
2681+
}
2682+
}
2683+
26832684
fn (mut c Amd64) gen_type_promotion(from ast.Type, to ast.Type, option Amd64RegisterOption) {
26842685
if !to.is_pure_float() {
26852686
return
@@ -3077,52 +3078,6 @@ fn (mut c Amd64) assign_stmt(node ast.AssignStmt) {
30773078
.decl_assign, .assign {
30783079
c.mov_store(.rbx, .rcx, size)
30793080
}
3080-
.plus_assign {
3081-
c.add_reg(.rax, .rcx)
3082-
c.mov_store(.rbx, .rax, size)
3083-
}
3084-
.minus_assign {
3085-
c.sub_reg(.rax, .rcx)
3086-
c.mov_store(.rbx, .rax, size)
3087-
}
3088-
.and_assign {
3089-
c.bitand_reg(.rax, .rcx)
3090-
c.mov_store(.rbx, .rax, size)
3091-
}
3092-
.mod_assign {
3093-
c.mov(Amd64Register.rdx, i32(0)) // 64bits IDIV uses RDX:RAX
3094-
c.mod_reg(.rax, .rcx)
3095-
c.mov_store(.rbx, .rax, size)
3096-
}
3097-
.mult_assign {
3098-
c.mul_reg(.rax, .rcx)
3099-
c.mov_store(.rbx, .rax, size)
3100-
}
3101-
.div_assign {
3102-
c.mov(Amd64Register.rdx, i32(0)) // 64bits IDIV uses RDX:RAX
3103-
c.div_reg(.rax, .rcx)
3104-
c.mov_store(.rbx, .rax, size)
3105-
}
3106-
.xor_assign {
3107-
c.bitxor_reg(.rax, .rcx)
3108-
c.mov_store(.rbx, .rax, size)
3109-
}
3110-
.or_assign {
3111-
c.bitor_reg(.rax, .rcx)
3112-
c.mov_store(.rbx, .rax, size)
3113-
}
3114-
.right_shift_assign {
3115-
c.shr_reg(.rax, .rcx)
3116-
c.mov_store(.rbx, .rax, size)
3117-
}
3118-
.left_shift_assign {
3119-
c.shl_reg(.rax, .rcx)
3120-
c.mov_store(.rbx, .rax, size)
3121-
}
3122-
.unsigned_right_shift_assign {
3123-
c.sar_reg(.rax, .rcx)
3124-
c.mov_store(.rbx, .rax, size)
3125-
}
31263081
.boolean_and_assign {
31273082
c.bitand_reg(.rax, .rcx)
31283083
c.mov_store(.rbx, .rax, size)
@@ -3132,7 +3087,8 @@ fn (mut c Amd64) assign_stmt(node ast.AssignStmt) {
31323087
c.mov_store(.rbx, .rax, size)
31333088
}
31343089
else {
3135-
c.g.n_error('${@LOCATION} Unsupported assign instruction (${node.op})')
3090+
c.apply_op_int(.rax, .rcx, node.op)
3091+
c.mov_store(.rbx, .rax, size)
31363092
}
31373093
}
31383094
} else if var_type.is_pure_float() {
@@ -4289,7 +4245,7 @@ fn (mut c Amd64) convert_int_to_string(a Register, b Register) {
42894245

42904246
c.mov(Amd64Register.rdx, 0) // upperhalf of the dividend
42914247
c.mov(Amd64Register.rbx, 10)
4292-
c.div_reg(.rax, .rbx) // rax will be the result of the division
4248+
c.div_reg_rax(.rbx) // rax will be the result of the division
42934249
c.add8(.rdx, i32(`0`)) // rdx is the remainder, add 48 to convert it into it's ascii representation
42944250

42954251
c.mov_store(.rdi, .rdx, ._8)

0 commit comments

Comments
 (0)