@@ -2179,40 +2179,22 @@ fn airWrapBinOp(self: *Self, inst: Air.Inst.Index, op: Op) InnerError!WValue {
2179
2179
return self .fail ("TODO: Implement wrapping arithmetic for vectors" , .{});
2180
2180
}
2181
2181
2182
- return self .wrapBinOp (lhs , rhs , ty , op );
2182
+ return ( try self .wrapBinOp (lhs , rhs , ty , op )). toLocal ( self , ty );
2183
2183
}
2184
2184
2185
+ /// Performs a wrapping binary operation.
2186
+ /// Asserts rhs is not a stack value when lhs also isn't.
2187
+ /// NOTE: Leaves the result on the stack when its Type is <= 64 bits
2185
2188
fn wrapBinOp (self : * Self , lhs : WValue , rhs : WValue , ty : Type , op : Op ) InnerError ! WValue {
2186
- const bit_size = ty .intInfo (self .target ).bits ;
2187
- var wasm_bits = toWasmBits (bit_size ) orelse {
2188
- return self .fail ("TODO: Implement wrapping arithmetic for integers with bitsize: {d}\n " , .{bit_size });
2189
- };
2190
-
2191
- if (wasm_bits == 128 ) {
2192
- const bin_op = try self .binOpBigInt (lhs , rhs , ty , op );
2193
- return self .wrapOperand (bin_op , ty );
2194
- }
2195
-
2196
- const opcode : wasm.Opcode = buildOpcode (.{
2197
- .op = op ,
2198
- .valtype1 = typeToValtype (ty , self .target ),
2199
- .signedness = if (ty .isSignedInt ()) .signed else .unsigned ,
2200
- });
2201
-
2202
- try self .emitWValue (lhs );
2203
- try self .emitWValue (rhs );
2204
- try self .addTag (Mir .Inst .Tag .fromOpcode (opcode ));
2205
- const bin_local = try self .allocLocal (ty );
2206
- try self .addLabel (.local_set , bin_local .local );
2207
-
2189
+ const bin_local = try self .binOp (lhs , rhs , ty , op );
2208
2190
return self .wrapOperand (bin_local , ty );
2209
2191
}
2210
2192
2211
2193
/// Wraps an operand based on a given type's bitsize.
2212
2194
/// Asserts `Type` is <= 128 bits.
2195
+ /// NOTE: When the Type is <= 64 bits, leaves the value on top of the stack.
2213
2196
fn wrapOperand (self : * Self , operand : WValue , ty : Type ) InnerError ! WValue {
2214
2197
assert (ty .abiSize (self .target ) <= 16 );
2215
- const result_local = try self .allocLocal (ty );
2216
2198
const bitsize = ty .intInfo (self .target ).bits ;
2217
2199
const wasm_bits = toWasmBits (bitsize ) orelse {
2218
2200
return self .fail ("TODO: Implement wrapOperand for bitsize '{d}'" , .{bitsize });
@@ -2246,8 +2228,7 @@ fn wrapOperand(self: *Self, operand: WValue, ty: Type) InnerError!WValue {
2246
2228
try self .addTag (.i64_and );
2247
2229
} else unreachable ;
2248
2230
2249
- try self .addLabel (.local_set , result_local .local );
2250
- return result_local ;
2231
+ return WValue { .stack = {} };
2251
2232
}
2252
2233
2253
2234
fn lowerParentPtr (self : * Self , ptr_val : Value , ptr_child_ty : Type ) InnerError ! WValue {
@@ -3471,11 +3452,11 @@ fn airTrunc(self: *Self, inst: Air.Inst.Index) InnerError!WValue {
3471
3452
return self .fail ("TODO: Implement wasm integer truncation for integer bitsize: {d}" , .{int_info .bits });
3472
3453
}
3473
3454
3474
- const result = try self .intcast (operand , op_ty , wanted_ty );
3455
+ var result = try self .intcast (operand , op_ty , wanted_ty );
3475
3456
const wanted_bits = wanted_ty .intInfo (self .target ).bits ;
3476
3457
const wasm_bits = toWasmBits (wanted_bits ).? ;
3477
3458
if (wasm_bits != wanted_bits ) {
3478
- return self .wrapOperand (result , wanted_ty );
3459
+ result = try self .wrapOperand (result , wanted_ty );
3479
3460
}
3480
3461
return result .toLocal (self , wanted_ty );
3481
3462
}
@@ -3749,11 +3730,8 @@ fn airFloatToInt(self: *Self, inst: Air.Inst.Index) InnerError!WValue {
3749
3730
.signedness = if (dest_ty .isSignedInt ()) .signed else .unsigned ,
3750
3731
});
3751
3732
try self .addTag (Mir .Inst .Tag .fromOpcode (op ));
3752
-
3753
- const result = try self .allocLocal (dest_ty );
3754
- try self .addLabel (.local_set , result .local );
3755
-
3756
- return self .wrapOperand (result , dest_ty );
3733
+ const wrapped = try self .wrapOperand (.{ .stack = {} }, dest_ty );
3734
+ return wrapped .toLocal (self , dest_ty );
3757
3735
}
3758
3736
3759
3737
fn airIntToFloat (self : * Self , inst : Air.Inst.Index ) InnerError ! WValue {
@@ -4339,7 +4317,7 @@ fn airAddSubWithOverflow(self: *Self, inst: Air.Inst.Index, op: Op) InnerError!W
4339
4317
4340
4318
const bin_op = try (try self .binOp (lhs , rhs , lhs_ty , op )).toLocal (self , lhs_ty );
4341
4319
const result = if (wasm_bits != int_info .bits ) blk : {
4342
- break :blk try self .wrapOperand (bin_op , lhs_ty );
4320
+ break :blk try ( try self .wrapOperand (bin_op , lhs_ty )). toLocal ( self , lhs_ty );
4343
4321
} else bin_op ;
4344
4322
4345
4323
const cmp_op : std.math.CompareOperator = if (op == .sub ) .gt else .lt ;
@@ -4438,13 +4416,15 @@ fn airShlWithOverflow(self: *Self, inst: Air.Inst.Index) InnerError!WValue {
4438
4416
4439
4417
const shl = try (try self .binOp (lhs , rhs , lhs_ty , .shl )).toLocal (self , lhs_ty );
4440
4418
const result = if (wasm_bits != int_info .bits ) blk : {
4441
- break :blk try self .wrapOperand (shl , lhs_ty );
4419
+ break :blk try ( try self .wrapOperand (shl , lhs_ty )). toLocal ( self , lhs_ty );
4442
4420
} else shl ;
4443
4421
4444
4422
const overflow_bit = if (wasm_bits != int_info .bits and is_signed ) blk : {
4445
4423
const abs = try self .signAbsValue (shl , lhs_ty );
4424
+ // emit lhs to stack to we can keep 'wrapped' on the stack also
4425
+ try self .emitWValue (lhs );
4446
4426
const wrapped = try self .wrapBinOp (abs , rhs , lhs_ty , .shr );
4447
- break :blk try self .cmp (lhs , wrapped , lhs_ty , .neq );
4427
+ break :blk try self .cmp (.{ . stack = {} } , wrapped , lhs_ty , .neq );
4448
4428
} else blk : {
4449
4429
const shr = try (try self .binOp (result , rhs , lhs_ty , .shr )).toLocal (self , lhs_ty );
4450
4430
break :blk try self .cmp (lhs , shr , lhs_ty , .neq );
@@ -4499,7 +4479,7 @@ fn airMulWithOverflow(self: *Self, inst: Air.Inst.Index) InnerError!WValue {
4499
4479
const wrap = try self .intcast (shr , new_ty , lhs_ty );
4500
4480
_ = try self .cmp (wrap , zero , lhs_ty , .neq );
4501
4481
try self .addLabel (.local_set , overflow_bit .local );
4502
- break :blk try ( try self .intcast (bin_op , new_ty , lhs_ty )). toLocal ( self , lhs_ty );
4482
+ break :blk try self .intcast (bin_op , new_ty , lhs_ty );
4503
4483
} else {
4504
4484
const down_cast = try (try self .intcast (bin_op , new_ty , lhs_ty )).toLocal (self , lhs_ty );
4505
4485
const shr = try (try self .binOp (down_cast , .{ .imm32 = int_info .bits - 1 }, lhs_ty , .shr )).toLocal (self , lhs_ty );
@@ -4529,9 +4509,10 @@ fn airMulWithOverflow(self: *Self, inst: Air.Inst.Index) InnerError!WValue {
4529
4509
try self .addLabel (.local_set , overflow_bit .local );
4530
4510
break :blk try self .wrapOperand (bin_op , lhs_ty );
4531
4511
};
4512
+ const bin_op_local = try bin_op .toLocal (self , lhs_ty );
4532
4513
4533
4514
const result_ptr = try self .allocStack (self .air .typeOfIndex (inst ));
4534
- try self .store (result_ptr , bin_op , lhs_ty , 0 );
4515
+ try self .store (result_ptr , bin_op_local , lhs_ty , 0 );
4535
4516
const offset = @intCast (u32 , lhs_ty .abiSize (self .target ));
4536
4517
try self .store (result_ptr , overflow_bit , Type .initTag (.u1 ), offset );
4537
4518
@@ -4854,29 +4835,29 @@ fn airByteSwap(self: *Self, inst: Air.Inst.Index) InnerError!WValue {
4854
4835
switch (int_info .bits ) {
4855
4836
16 = > {
4856
4837
const shl_res = try self .binOp (operand , .{ .imm32 = 8 }, ty , .shl );
4857
- const lhs = try ( try self .binOp (shl_res , .{ .imm32 = 0xFF00 }, ty , .@"and" )). toLocal ( self , ty );
4858
- const shr_res = try ( try self .binOp (operand , .{ .imm32 = 8 }, ty , .shr )). toLocal ( self , ty );
4838
+ const lhs = try self .binOp (shl_res , .{ .imm32 = 0xFF00 }, ty , .@"and" );
4839
+ const shr_res = try self .binOp (operand , .{ .imm32 = 8 }, ty , .shr );
4859
4840
const res = if (int_info .signedness == .signed ) blk : {
4860
4841
break :blk try self .wrapOperand (shr_res , Type .u8 );
4861
4842
} else shr_res ;
4862
4843
return (try self .binOp (lhs , res , ty , .@"or" )).toLocal (self , ty );
4863
4844
},
4864
4845
24 = > {
4865
- const msb = try self .wrapOperand (operand , Type .u16 );
4866
- const lsb = try self .wrapBinOp (operand , .{ .imm32 = 16 }, Type .u8 , .shr );
4846
+ const msb = try (try self .wrapOperand (operand , Type .u16 )).toLocal (self , Type .u16 );
4867
4847
4868
4848
const shl_res = try self .binOp (msb , .{ .imm32 = 8 }, Type .u16 , .shl );
4869
- const lhs = try ( try self .binOp (shl_res , .{ .imm32 = 0xFF0000 }, Type .u16 , .@"and" )). toLocal ( self , Type . u16 );
4870
- const shr_res = try ( try self .binOp (msb , .{ .imm32 = 8 }, ty , .shr )). toLocal ( self , ty );
4849
+ const lhs = try self .binOp (shl_res , .{ .imm32 = 0xFF0000 }, Type .u16 , .@"and" );
4850
+ const shr_res = try self .binOp (msb , .{ .imm32 = 8 }, ty , .shr );
4871
4851
4872
4852
const res = if (int_info .signedness == .signed ) blk : {
4873
4853
break :blk try self .wrapOperand (shr_res , Type .u8 );
4874
4854
} else shr_res ;
4875
4855
const lhs_tmp = try self .binOp (lhs , res , ty , .@"or" );
4876
- const lhs_result = try ( try self .binOp (lhs_tmp , .{ .imm32 = 8 }, ty , .shr )). toLocal ( self , ty );
4856
+ const lhs_result = try self .binOp (lhs_tmp , .{ .imm32 = 8 }, ty , .shr );
4877
4857
const rhs_wrap = try self .wrapOperand (msb , Type .u8 );
4878
- const rhs_result = try ( try self .binOp (rhs_wrap , .{ .imm32 = 16 }, ty , .shl )). toLocal ( self , ty );
4858
+ const rhs_result = try self .binOp (rhs_wrap , .{ .imm32 = 16 }, ty , .shl );
4879
4859
4860
+ const lsb = try self .wrapBinOp (operand , .{ .imm32 = 16 }, Type .u8 , .shr );
4880
4861
const tmp = try self .binOp (lhs_result , rhs_result , ty , .@"or" );
4881
4862
return (try self .binOp (tmp , lsb , ty , .@"or" )).toLocal (self , ty );
4882
4863
},
@@ -4887,11 +4868,11 @@ fn airByteSwap(self: *Self, inst: Air.Inst.Index) InnerError!WValue {
4887
4868
const rhs = try (try self .binOp (shr_tmp , .{ .imm32 = 0xFF00FF }, ty , .@"and" )).toLocal (self , ty );
4888
4869
const tmp_or = try (try self .binOp (lhs , rhs , ty , .@"or" )).toLocal (self , ty );
4889
4870
4890
- const shr = try (try self .binOp (tmp_or , .{ .imm32 = 16 }, ty , .shr )).toLocal (self , ty );
4871
+ const shl = try self .binOp (tmp_or , .{ .imm32 = 16 }, ty , .shl );
4872
+ const shr = try self .binOp (tmp_or , .{ .imm32 = 16 }, ty , .shr );
4891
4873
const res = if (int_info .signedness == .signed ) blk : {
4892
4874
break :blk try self .wrapOperand (shr , Type .u16 );
4893
4875
} else shr ;
4894
- const shl = try self .binOp (tmp_or , .{ .imm32 = 16 }, ty , .shl );
4895
4876
return (try self .binOp (shl , res , ty , .@"or" )).toLocal (self , ty );
4896
4877
},
4897
4878
else = > return self .fail ("TODO: @byteSwap for integers with bitsize {d}" , .{int_info .bits }),
@@ -5178,7 +5159,7 @@ fn signedSat(self: *Self, lhs_operand: WValue, rhs_operand: WValue, ty: Type, op
5178
5159
_ = try self .cmp (bin_result , min_wvalue , ty , .gt );
5179
5160
try self .addTag (.select );
5180
5161
try self .addLabel (.local_set , bin_result .local ); // re-use local
5181
- return self .wrapOperand (bin_result , ty );
5162
+ return ( try self .wrapOperand (bin_result , ty )). toLocal ( self , ty );
5182
5163
} else {
5183
5164
const zero = switch (wasm_bits ) {
5184
5165
32 = > WValue { .imm32 = 0 },
@@ -5289,11 +5270,11 @@ fn airShlSat(self: *Self, inst: Air.Inst.Index) InnerError!WValue {
5289
5270
_ = try self .cmp (shl_res , shr , ty , .neq );
5290
5271
try self .addTag (.select );
5291
5272
try self .addLabel (.local_set , result .local );
5292
- const shift_result = try ( try self .binOp (result , shift_value , ty , .shr )). toLocal ( self , ty );
5273
+ var shift_result = try self .binOp (result , shift_value , ty , .shr );
5293
5274
if (is_signed ) {
5294
- return self .wrapOperand (shift_result , ty );
5275
+ shift_result = try self .wrapOperand (shift_result , ty );
5295
5276
}
5296
- return shift_result ;
5277
+ return try shift_result . toLocal ( self , ty ) ;
5297
5278
}
5298
5279
}
5299
5280
0 commit comments