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 {...@@ -3201,14 +3201,23 @@ pub const FuncGen = struct {
3201 const operand = try self.resolveInst(ty_op.operand);3201 const operand = try self.resolveInst(ty_op.operand);
3202 const operand_ty = self.air.typeOf(ty_op.operand);3202 const operand_ty = self.air.typeOf(ty_op.operand);
3203 const inst_ty = self.air.typeOfIndex(inst);3203 const inst_ty = self.air.typeOfIndex(inst);
3204 const operand_is_ref = isByRef(operand_ty);
3205 const result_is_ref = isByRef(inst_ty);
3204 const llvm_dest_ty = try self.dg.llvmType(inst_ty);3206 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
3206 if (operand_ty.zigTypeTag() == .Int and inst_ty.zigTypeTag() == .Pointer) {3213 if (operand_ty.zigTypeTag() == .Int and inst_ty.zigTypeTag() == .Pointer) {
3207 return self.builder.buildIntToPtr(operand, llvm_dest_ty, "");3214 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) {
3209 const target = self.dg.module.getTarget();3218 const target = self.dg.module.getTarget();
3210 const elem_ty = operand_ty.childType();3219 const elem_ty = operand_ty.childType();
3211 if (!isByRef(inst_ty)) {3220 if (!result_is_ref) {
3212 return self.dg.todo("implement bitcast vector to non-ref array", .{});3221 return self.dg.todo("implement bitcast vector to non-ref array", .{});
3213 }3222 }
3214 const array_ptr = self.buildAlloca(llvm_dest_ty);3223 const array_ptr = self.buildAlloca(llvm_dest_ty);
...@@ -3239,7 +3248,7 @@ pub const FuncGen = struct {...@@ -3239,7 +3248,7 @@ pub const FuncGen = struct {
3239 const target = self.dg.module.getTarget();3248 const target = self.dg.module.getTarget();
3240 const elem_ty = operand_ty.childType();3249 const elem_ty = operand_ty.childType();
3241 const llvm_vector_ty = try self.dg.llvmType(inst_ty);3250 const llvm_vector_ty = try self.dg.llvmType(inst_ty);
3242 if (!isByRef(operand_ty)) {3251 if (!operand_is_ref) {
3243 return self.dg.todo("implement bitcast non-ref array to vector", .{});3252 return self.dg.todo("implement bitcast non-ref array to vector", .{});
3244 }3253 }
32453254
...@@ -3274,6 +3283,21 @@ pub const FuncGen = struct {...@@ -3274,6 +3283,21 @@ pub const FuncGen = struct {
3274 }3283 }
3275 }3284 }
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
3277 return self.builder.buildBitCast(operand, llvm_dest_ty, "");3301 return self.builder.buildBitCast(operand, llvm_dest_ty, "");
3278 }3302 }
32793303
test/behavior/bitcast.zig+6
...@@ -64,3 +64,9 @@ test "bitcast literal [4]u8 param to u32" {...@@ -64,3 +64,9 @@ test "bitcast literal [4]u8 param to u32" {
64 const ip = @bitCast(u32, [_]u8{ 255, 255, 255, 255 });64 const ip = @bitCast(u32, [_]u8{ 255, 255, 255, 255 });
65 try expect(ip == maxInt(u32));65 try expect(ip == maxInt(u32));
66}66}
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...@@ -129,9 +129,3 @@ test "triple level result location with bitcast sandwich passed as tuple element
129 };129 };
130 try S.foo(.{@as(f64, @bitCast(f32, @as(u32, 0x414570A4)))});130 try S.foo(.{@as(f64, @bitCast(f32, @as(u32, 0x414570A4)))});
131}131}
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}