aboutsummaryrefslogtreecommitdiff
path: root/src/codegen/llvm.zig
diff options
context:
space:
mode:
authorAndrew Kelley <andrew@ziglang.org>2021-10-26 16:42:44 -0700
committerAndrew Kelley <andrew@ziglang.org>2021-10-26 16:43:18 -0700
commit11a60e87791c13d89d770c7925c744b5fe75e5c4 (patch)
tree9f3ca78edeb06881760c0e0ffa655b609450cc02 /src/codegen/llvm.zig
parentf890de62948a0134a8d703dd2f1ee37701ec4c00 (diff)
downloadzig-11a60e87791c13d89d770c7925c744b5fe75e5c4.tar.gz
zig-11a60e87791c13d89d770c7925c744b5fe75e5c4.zip
stage2 LLVM backend: fix bitcast
Properly handle when the operand type, the result type, or both, are by-ref values.
Diffstat (limited to 'src/codegen/llvm.zig')
-rw-r--r--src/codegen/llvm.zig30
1 files changed, 27 insertions, 3 deletions
diff --git a/src/codegen/llvm.zig b/src/codegen/llvm.zig
index fd92dec413..9c2fd22df0 100644
--- a/src/codegen/llvm.zig
+++ b/src/codegen/llvm.zig
@@ -3201,14 +3201,23 @@ pub const FuncGen = struct {
const operand = try self.resolveInst(ty_op.operand);
const operand_ty = self.air.typeOf(ty_op.operand);
const inst_ty = self.air.typeOfIndex(inst);
+ const operand_is_ref = isByRef(operand_ty);
+ const result_is_ref = isByRef(inst_ty);
const llvm_dest_ty = try self.dg.llvmType(inst_ty);
+ if (operand_is_ref and result_is_ref) {
+ // They are both pointers; just do a bitcast on the pointers :)
+ return self.builder.buildBitCast(operand, llvm_dest_ty.pointerType(0), "");
+ }
+
if (operand_ty.zigTypeTag() == .Int and inst_ty.zigTypeTag() == .Pointer) {
return self.builder.buildIntToPtr(operand, llvm_dest_ty, "");
- } else if (operand_ty.zigTypeTag() == .Vector and inst_ty.zigTypeTag() == .Array) {
+ }
+
+ if (operand_ty.zigTypeTag() == .Vector and inst_ty.zigTypeTag() == .Array) {
const target = self.dg.module.getTarget();
const elem_ty = operand_ty.childType();
- if (!isByRef(inst_ty)) {
+ if (!result_is_ref) {
return self.dg.todo("implement bitcast vector to non-ref array", .{});
}
const array_ptr = self.buildAlloca(llvm_dest_ty);
@@ -3239,7 +3248,7 @@ pub const FuncGen = struct {
const target = self.dg.module.getTarget();
const elem_ty = operand_ty.childType();
const llvm_vector_ty = try self.dg.llvmType(inst_ty);
- if (!isByRef(operand_ty)) {
+ if (!operand_is_ref) {
return self.dg.todo("implement bitcast non-ref array to vector", .{});
}
@@ -3274,6 +3283,21 @@ pub const FuncGen = struct {
}
}
+ if (operand_is_ref) {
+ // Bitcast the operand pointer, then load.
+ const casted_ptr = self.builder.buildBitCast(operand, llvm_dest_ty.pointerType(0), "");
+ return self.builder.buildLoad(casted_ptr, "");
+ }
+
+ if (result_is_ref) {
+ // Bitcast the result pointer, then store.
+ const result_ptr = self.buildAlloca(llvm_dest_ty);
+ const operand_llvm_ty = try self.dg.llvmType(operand_ty);
+ const casted_ptr = self.builder.buildBitCast(result_ptr, operand_llvm_ty.pointerType(0), "");
+ _ = self.builder.buildStore(operand, casted_ptr);
+ return result_ptr;
+ }
+
return self.builder.buildBitCast(operand, llvm_dest_ty, "");
}