authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2021-10-26 16:42:44-07:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2021-10-26 16:43:18-07:00
log11a60e87791c13d89d770c7925c744b5fe75e5c4
tree9f3ca78edeb06881760c0e0ffa655b609450cc02
parentf890de62948a0134a8d703dd2f1ee37701ec4c00

stage2 LLVM backend: fix bitcast

Properly handle when the operand type, the result type, or both, are by-ref values.

3 files changed, 33 insertions(+), 9 deletions(-)

src/codegen/llvm.zig+27-3
......@@ -3201,14 +3201,23 @@ pub const FuncGen = struct {
32013201 const operand = try self.resolveInst(ty_op.operand);
32023202 const operand_ty = self.air.typeOf(ty_op.operand);
32033203 const inst_ty = self.air.typeOfIndex(inst);
3204 const operand_is_ref = isByRef(operand_ty);
3205 const result_is_ref = isByRef(inst_ty);
32043206 const llvm_dest_ty = try self.dg.llvmType(inst_ty);
32053207
3208 if (operand_is_ref and result_is_ref) {
3209 // They are both pointers; just do a bitcast on the pointers :)
3210 return self.builder.buildBitCast(operand, llvm_dest_ty.pointerType(0), "");
3211 }
3212
32063213 if (operand_ty.zigTypeTag() == .Int and inst_ty.zigTypeTag() == .Pointer) {
32073214 return self.builder.buildIntToPtr(operand, llvm_dest_ty, "");
3208 } else if (operand_ty.zigTypeTag() == .Vector and inst_ty.zigTypeTag() == .Array) {
3215 }
3216
3217 if (operand_ty.zigTypeTag() == .Vector and inst_ty.zigTypeTag() == .Array) {
32093218 const target = self.dg.module.getTarget();
32103219 const elem_ty = operand_ty.childType();
3211 if (!isByRef(inst_ty)) {
3220 if (!result_is_ref) {
32123221 return self.dg.todo("implement bitcast vector to non-ref array", .{});
32133222 }
32143223 const array_ptr = self.buildAlloca(llvm_dest_ty);
......@@ -3239,7 +3248,7 @@ pub const FuncGen = struct {
32393248 const target = self.dg.module.getTarget();
32403249 const elem_ty = operand_ty.childType();
32413250 const llvm_vector_ty = try self.dg.llvmType(inst_ty);
3242 if (!isByRef(operand_ty)) {
3251 if (!operand_is_ref) {
32433252 return self.dg.todo("implement bitcast non-ref array to vector", .{});
32443253 }
32453254
......@@ -3274,6 +3283,21 @@ pub const FuncGen = struct {
32743283 }
32753284 }
32763285
3286 if (operand_is_ref) {
3287 // Bitcast the operand pointer, then load.
3288 const casted_ptr = self.builder.buildBitCast(operand, llvm_dest_ty.pointerType(0), "");
3289 return self.builder.buildLoad(casted_ptr, "");
3290 }
3291
3292 if (result_is_ref) {
3293 // Bitcast the result pointer, then store.
3294 const result_ptr = self.buildAlloca(llvm_dest_ty);
3295 const operand_llvm_ty = try self.dg.llvmType(operand_ty);
3296 const casted_ptr = self.builder.buildBitCast(result_ptr, operand_llvm_ty.pointerType(0), "");
3297 _ = self.builder.buildStore(operand, casted_ptr);
3298 return result_ptr;
3299 }
3300
32773301 return self.builder.buildBitCast(operand, llvm_dest_ty, "");
32783302 }
32793303
test/behavior/bitcast.zig+6
......@@ -64,3 +64,9 @@ test "bitcast literal [4]u8 param to u32" {
6464 const ip = @bitCast(u32, [_]u8{ 255, 255, 255, 255 });
6565 try expect(ip == maxInt(u32));
6666}
67
68test "bitcast generates a temporary value" {
69 var y = @as(u16, 0x55AA);
70 const x = @bitCast(u16, @bitCast([2]u8, y));
71 try expect(y == x);
72}
test/behavior/bitcast_stage1.zig-6
......@@ -129,9 +129,3 @@ test "triple level result location with bitcast sandwich passed as tuple element
129129 };
130130 try S.foo(.{@as(f64, @bitCast(f32, @as(u32, 0x414570A4)))});
131131}
132
133test "bitcast generates a temporary value" {
134 var y = @as(u16, 0x55AA);
135 const x = @bitCast(u16, @bitCast([2]u8, y));
136 try expectEqual(y, x);
137}