diff options
Diffstat (limited to 'src/codegen')
| -rw-r--r-- | src/codegen/llvm.zig | 36 | ||||
| -rw-r--r-- | src/codegen/llvm/bindings.zig | 3 |
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; |
