aboutsummaryrefslogtreecommitdiff
path: root/src/codegen
diff options
context:
space:
mode:
Diffstat (limited to 'src/codegen')
-rw-r--r--src/codegen/llvm.zig36
-rw-r--r--src/codegen/llvm/bindings.zig3
2 files changed, 36 insertions, 3 deletions
diff --git a/src/codegen/llvm.zig b/src/codegen/llvm.zig
index e7915e08b3..6a2e346113 100644
--- a/src/codegen/llvm.zig
+++ b/src/codegen/llvm.zig
@@ -3646,6 +3646,24 @@ pub const DeclGen = struct {
},
.Struct => {
const field_ty = parent_ty.structFieldType(field_index);
+ if (parent_ty.containerLayout() == .Packed) {
+ const llvm_usize = dg.context.intType(target.cpu.arch.ptrBitWidth());
+ const base_addr = parent_llvm_ptr.constPtrToInt(llvm_usize);
+ // count bits of fields before this one
+ const prev_bits = b: {
+ var b: usize = 0;
+ for (parent_ty.structFields().values()[0..field_index]) |field| {
+ if (field.is_comptime or !field.ty.hasRuntimeBitsIgnoreComptime()) continue;
+ b += field.ty.bitSize(target);
+ }
+ break :b b;
+ };
+ const byte_offset = llvm_usize.constInt((prev_bits + 7) / 8, .False);
+ const field_addr = base_addr.constAdd(byte_offset);
+ bitcast_needed = false;
+ const final_llvm_ty = (try dg.lowerType(ptr_child_ty)).pointerType(0);
+ break :blk field_addr.constIntToPtr(final_llvm_ty);
+ }
bitcast_needed = !field_ty.eql(ptr_child_ty, dg.module);
var ty_buf: Type.Payload.Pointer = undefined;
@@ -4473,17 +4491,29 @@ pub const FuncGen = struct {
}
return null;
}
+
const abi_ret_ty = try lowerFnRetTy(self.dg, fn_info);
+ const ptr_abi_ty = abi_ret_ty.pointerType(0);
const operand = try self.resolveInst(un_op);
+ const target = self.dg.module.getTarget();
+ const alignment = ret_ty.abiAlignment(target);
+
+ if (isByRef(ret_ty)) {
+ // operand is a pointer however self.ret_ptr is null so that means
+ // we need to return a value.
+ const casted_ptr = self.builder.buildBitCast(operand, ptr_abi_ty, "");
+ const load_inst = self.builder.buildLoad(casted_ptr, "");
+ load_inst.setAlignment(alignment);
+ _ = self.builder.buildRet(load_inst);
+ return null;
+ }
+
const llvm_ret_ty = operand.typeOf();
if (abi_ret_ty == llvm_ret_ty) {
_ = self.builder.buildRet(operand);
return null;
}
- const target = self.dg.module.getTarget();
- const alignment = ret_ty.abiAlignment(target);
- const ptr_abi_ty = abi_ret_ty.pointerType(0);
const rp = self.buildAlloca(llvm_ret_ty);
rp.setAlignment(alignment);
const store_inst = self.builder.buildStore(operand, rp);
diff --git a/src/codegen/llvm/bindings.zig b/src/codegen/llvm/bindings.zig
index 07408f12b9..e4357b8060 100644
--- a/src/codegen/llvm/bindings.zig
+++ b/src/codegen/llvm/bindings.zig
@@ -169,6 +169,9 @@ pub const Value = opaque {
pub const constNot = LLVMConstNot;
extern fn LLVMConstNot(ConstantVal: *const Value) *const Value;
+ pub const constAdd = LLVMConstAdd;
+ extern fn LLVMConstAdd(LHSConstant: *const Value, RHSConstant: *const Value) *const Value;
+
pub const setWeak = LLVMSetWeak;
extern fn LLVMSetWeak(CmpXchgInst: *const Value, IsWeak: Bool) void;