From 70d39123908e29cde9fbfb540869e03ab86694e3 Mon Sep 17 00:00:00 2001 From: Andrew Kelley Date: Sun, 31 Jul 2022 18:10:28 -0700 Subject: update Target, CPU, OS, ABI, etc. to LLVM 15 --- src/codegen/llvm.zig | 24 ++++++++++++++++++++++++ 1 file changed, 24 insertions(+) (limited to 'src/codegen/llvm.zig') diff --git a/src/codegen/llvm.zig b/src/codegen/llvm.zig index 664edb0304..132b5ef7a5 100644 --- a/src/codegen/llvm.zig +++ b/src/codegen/llvm.zig @@ -41,7 +41,10 @@ pub fn targetTriple(allocator: Allocator, target: std.Target) ![:0]u8 { .bpfel => "bpfel", .bpfeb => "bpfeb", .csky => "csky", + .dxil => "dxil", .hexagon => "hexagon", + .loongarch32 => "loongarch32", + .loongarch64 => "loongarch64", .m68k => "m68k", .mips => "mips", .mipsel => "mipsel", @@ -116,6 +119,7 @@ pub fn targetTriple(allocator: Allocator, target: std.Target) ![:0]u8 { .nvcl => "nvcl", .amdhsa => "amdhsa", .ps4 => "ps4", + .ps5 => "ps5", .elfiamcu => "elfiamcu", .mesa3d => "mesa3d", .contiki => "contiki", @@ -129,6 +133,8 @@ pub fn targetTriple(allocator: Allocator, target: std.Target) ![:0]u8 { .ios => "ios", .tvos => "tvos", .watchos => "watchos", + .driverkit => "driverkit", + .shadermodel => "shadermodel", .opencl, .glsl450, .vulkan, @@ -171,6 +177,21 @@ pub fn targetTriple(allocator: Allocator, target: std.Target) ![:0]u8 { .coreclr => "coreclr", .simulator => "simulator", .macabi => "macabi", + .pixel => "pixel", + .vertex => "vertex", + .geometry => "geometry", + .hull => "hull", + .domain => "domain", + .compute => "compute", + .library => "library", + .raygeneration => "raygeneration", + .intersection => "intersection", + .anyhit => "anyhit", + .closesthit => "closesthit", + .miss => "miss", + .callable => "callable", + .mesh => "mesh", + .amplification => "amplification", }; try llvm_triple.appendSlice(llvm_abi); @@ -9030,6 +9051,9 @@ fn initializeLLVMTarget(arch: std.Target.Cpu.Arch) void { .kalimba, .renderscript32, .renderscript64, + .dxil, + .loongarch32, + .loongarch64, => {}, .spu_2 => unreachable, // LLVM does not support this backend -- cgit v1.2.3 From bc2aaf18c86007ffb997513a57af29692777002f Mon Sep 17 00:00:00 2001 From: Andrew Kelley Date: Mon, 1 Aug 2022 20:55:17 -0700 Subject: stage2: LLVM lowering to opaque pointers API --- src/codegen/llvm.zig | 380 ++++++++++++++++++++++++------------------ src/codegen/llvm/bindings.zig | 22 ++- 2 files changed, 235 insertions(+), 167 deletions(-) (limited to 'src/codegen/llvm.zig') diff --git a/src/codegen/llvm.zig b/src/codegen/llvm.zig index 132b5ef7a5..900c98c30d 100644 --- a/src/codegen/llvm.zig +++ b/src/codegen/llvm.zig @@ -841,7 +841,8 @@ pub const Object = struct { args.appendAssumeCapacity(param); } else { const alignment = param_ty.abiAlignment(target); - const load_inst = builder.buildLoad(param, ""); + const param_llvm_ty = try dg.lowerType(param_ty); + const load_inst = builder.buildLoad(param_llvm_ty, param, ""); load_inst.setAlignment(alignment); args.appendAssumeCapacity(load_inst); } @@ -870,7 +871,7 @@ pub const Object = struct { if (isByRef(param_ty)) { args.appendAssumeCapacity(arg_ptr); } else { - const load_inst = builder.buildLoad(arg_ptr, ""); + const load_inst = builder.buildLoad(param_llvm_ty, arg_ptr, ""); load_inst.setAlignment(alignment); args.appendAssumeCapacity(load_inst); } @@ -921,14 +922,14 @@ pub const Object = struct { for (llvm_ints) |_, i_usize| { const i = @intCast(c_uint, i_usize); const param = llvm_func.getParam(i); - const field_ptr = builder.buildStructGEP(casted_ptr, i, ""); + const field_ptr = builder.buildStructGEP(ints_llvm_ty, casted_ptr, i, ""); const store_inst = builder.buildStore(param, field_ptr); store_inst.setAlignment(target.cpu.arch.ptrBitWidth() / 8); } const is_by_ref = isByRef(param_ty); const loaded = if (is_by_ref) arg_ptr else l: { - const load_inst = builder.buildLoad(arg_ptr, ""); + const load_inst = builder.buildLoad(param_llvm_ty, arg_ptr, ""); load_inst.setAlignment(param_alignment); break :l load_inst; }; @@ -3663,7 +3664,8 @@ pub const DeclGen = struct { llvm_u32.constInt(0, .False), llvm_u32.constInt(llvm_pl_index, .False), }; - break :blk parent_llvm_ptr.constInBoundsGEP(&indices, indices.len); + const parent_llvm_ty = try dg.lowerType(parent_ty); + break :blk parent_llvm_ty.constInBoundsGEP(parent_llvm_ptr, &indices, indices.len); }, .Struct => { const field_ty = parent_ty.structFieldType(field_index); @@ -3693,7 +3695,8 @@ pub const DeclGen = struct { llvm_u32.constInt(0, .False), llvm_u32.constInt(llvm_field_index, .False), }; - break :blk parent_llvm_ptr.constInBoundsGEP(&indices, indices.len); + const parent_llvm_ty = try dg.lowerType(parent_ty); + break :blk parent_llvm_ty.constInBoundsGEP(parent_llvm_ptr, &indices, indices.len); }, else => unreachable, } @@ -3707,7 +3710,8 @@ pub const DeclGen = struct { const indices: [1]*const llvm.Value = .{ llvm_usize.constInt(elem_ptr.index, .False), }; - break :blk parent_llvm_ptr.constInBoundsGEP(&indices, indices.len); + const elem_llvm_ty = try dg.lowerType(elem_ptr.elem_ty); + break :blk elem_llvm_ty.constInBoundsGEP(parent_llvm_ptr, &indices, indices.len); }, .opt_payload_ptr => blk: { const opt_payload_ptr = ptr_val.castTag(.opt_payload_ptr).?.data; @@ -3730,7 +3734,8 @@ pub const DeclGen = struct { llvm_u32.constInt(0, .False), llvm_u32.constInt(0, .False), }; - break :blk parent_llvm_ptr.constInBoundsGEP(&indices, indices.len); + const opt_llvm_ty = try dg.lowerType(opt_payload_ptr.container_ty); + break :blk opt_llvm_ty.constInBoundsGEP(parent_llvm_ptr, &indices, indices.len); }, .eu_payload_ptr => blk: { const eu_payload_ptr = ptr_val.castTag(.eu_payload_ptr).?.data; @@ -3751,7 +3756,8 @@ pub const DeclGen = struct { llvm_u32.constInt(0, .False), llvm_u32.constInt(payload_offset, .False), }; - break :blk parent_llvm_ptr.constInBoundsGEP(&indices, indices.len); + const eu_llvm_ty = try dg.lowerType(eu_payload_ptr.container_ty); + break :blk eu_llvm_ty.constInBoundsGEP(parent_llvm_ptr, &indices, indices.len); }, else => unreachable, }; @@ -4303,9 +4309,10 @@ pub const FuncGen = struct { const arg = args[it.zig_index - 1]; const param_ty = self.air.typeOf(arg); const llvm_arg = try self.resolveInst(arg); + const llvm_param_ty = try self.dg.lowerType(param_ty); if (isByRef(param_ty)) { const alignment = param_ty.abiAlignment(target); - const load_inst = self.builder.buildLoad(llvm_arg, ""); + const load_inst = self.builder.buildLoad(llvm_param_ty, llvm_arg, ""); load_inst.setAlignment(alignment); try llvm_args.append(load_inst); } else { @@ -4315,7 +4322,6 @@ pub const FuncGen = struct { // which is always lowered to an LLVM type of `*i8`. // 2. The argument is a global which does act as a pointer, however // a bitcast is needed in order for the LLVM types to match. - const llvm_param_ty = try self.dg.lowerType(param_ty); const casted_ptr = self.builder.buildBitCast(llvm_arg, llvm_param_ty, ""); try llvm_args.append(casted_ptr); } else { @@ -4350,7 +4356,7 @@ pub const FuncGen = struct { if (isByRef(param_ty)) { const alignment = param_ty.abiAlignment(target); const casted_ptr = self.builder.buildBitCast(llvm_arg, int_ptr_llvm_ty, ""); - const load_inst = self.builder.buildLoad(casted_ptr, ""); + const load_inst = self.builder.buildLoad(int_llvm_ty, casted_ptr, ""); load_inst.setAlignment(alignment); try llvm_args.append(load_inst); } else { @@ -4366,7 +4372,7 @@ pub const FuncGen = struct { const casted_ptr = self.builder.buildBitCast(int_ptr, param_llvm_ty.pointerType(0), ""); const store_inst = self.builder.buildStore(llvm_arg, casted_ptr); store_inst.setAlignment(alignment); - const load_inst = self.builder.buildLoad(int_ptr, ""); + const load_inst = self.builder.buildLoad(int_llvm_ty, int_ptr, ""); load_inst.setAlignment(alignment); try llvm_args.append(load_inst); } @@ -4403,8 +4409,8 @@ pub const FuncGen = struct { try llvm_args.ensureUnusedCapacity(it.llvm_types_len); for (llvm_ints) |_, i_usize| { const i = @intCast(c_uint, i_usize); - const field_ptr = self.builder.buildStructGEP(casted_ptr, i, ""); - const load_inst = self.builder.buildLoad(field_ptr, ""); + const field_ptr = self.builder.buildStructGEP(ints_llvm_ty, casted_ptr, i, ""); + const load_inst = self.builder.buildLoad(field_types[i], field_ptr, ""); load_inst.setAlignment(target.cpu.arch.ptrBitWidth() / 8); llvm_args.appendAssumeCapacity(load_inst); } @@ -4418,6 +4424,7 @@ pub const FuncGen = struct { }; const call = self.builder.buildCall( + try self.dg.lowerType(zig_fn_ty), llvm_fn, llvm_args.items.ptr, @intCast(c_uint, llvm_args.items.len), @@ -4443,7 +4450,7 @@ pub const FuncGen = struct { return rp; } else { // our by-ref status disagrees with sret so we must load. - const loaded = self.builder.buildLoad(rp, ""); + const loaded = self.builder.buildLoad(llvm_ret_ty, rp, ""); loaded.setAlignment(return_type.abiAlignment(target)); return loaded; } @@ -4465,7 +4472,7 @@ pub const FuncGen = struct { if (isByRef(return_type)) { return rp; } else { - const load_inst = self.builder.buildLoad(rp, ""); + const load_inst = self.builder.buildLoad(llvm_ret_ty, rp, ""); load_inst.setAlignment(alignment); return load_inst; } @@ -4523,7 +4530,7 @@ pub const FuncGen = struct { // 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, ""); + const load_inst = self.builder.buildLoad(abi_ret_ty, casted_ptr, ""); load_inst.setAlignment(alignment); _ = self.builder.buildRet(load_inst); return null; @@ -4540,7 +4547,7 @@ pub const FuncGen = struct { const store_inst = self.builder.buildStore(operand, rp); store_inst.setAlignment(alignment); const casted_ptr = self.builder.buildBitCast(rp, ptr_abi_ty, ""); - const load_inst = self.builder.buildLoad(casted_ptr, ""); + const load_inst = self.builder.buildLoad(abi_ret_ty, casted_ptr, ""); load_inst.setAlignment(alignment); _ = self.builder.buildRet(load_inst); return null; @@ -4575,7 +4582,7 @@ pub const FuncGen = struct { const ptr_abi_ty = abi_ret_ty.pointerType(0); break :p self.builder.buildBitCast(ptr, ptr_abi_ty, ""); }; - const loaded = self.builder.buildLoad(casted_ptr, ""); + const loaded = self.builder.buildLoad(abi_ret_ty, casted_ptr, ""); loaded.setAlignment(ret_ty.abiAlignment(target)); _ = self.builder.buildRet(loaded); return null; @@ -4615,7 +4622,7 @@ pub const FuncGen = struct { const operand = try self.resolveInst(un_op); const llvm_fn = try self.getCmpLtErrorsLenFunction(); const args: [1]*const llvm.Value = .{operand}; - return self.builder.buildCall(llvm_fn, &args, args.len, .Fast, .Auto, ""); + return self.builder.buildCall(llvm_fn.typeOf(), llvm_fn, &args, args.len, .Fast, .Auto, ""); } fn cmp( @@ -4642,8 +4649,9 @@ pub const FuncGen = struct { // We need to emit instructions to check for equality/inequality // of optionals that are not pointers. const is_by_ref = isByRef(scalar_ty); - const lhs_non_null = self.optIsNonNull(lhs, is_by_ref); - const rhs_non_null = self.optIsNonNull(rhs, is_by_ref); + const opt_llvm_ty = try self.dg.lowerType(scalar_ty); + const lhs_non_null = self.optIsNonNull(opt_llvm_ty, lhs, is_by_ref); + const rhs_non_null = self.optIsNonNull(opt_llvm_ty, rhs, is_by_ref); const llvm_i2 = self.context.intType(2); const lhs_non_null_i2 = self.builder.buildZExt(lhs_non_null, llvm_i2, ""); const rhs_non_null_i2 = self.builder.buildZExt(rhs_non_null, llvm_i2, ""); @@ -4666,8 +4674,8 @@ pub const FuncGen = struct { _ = self.builder.buildBr(end_block); self.builder.positionBuilderAtEnd(both_pl_block); - const lhs_payload = self.optPayloadHandle(lhs, scalar_ty); - const rhs_payload = self.optPayloadHandle(rhs, scalar_ty); + const lhs_payload = self.optPayloadHandle(opt_llvm_ty, lhs, scalar_ty); + const rhs_payload = self.optPayloadHandle(opt_llvm_ty, rhs, scalar_ty); const payload_cmp = try self.cmp(lhs_payload, rhs_payload, payload_ty, op); _ = self.builder.buildBr(end_block); const both_pl_block_end = self.builder.getInsertBlock(); @@ -4832,10 +4840,18 @@ pub const FuncGen = struct { return lowerTry(self, err_union_ptr, body, err_union_ty, true, result_ty); } - fn lowerTry(fg: *FuncGen, err_union: *const llvm.Value, body: []const Air.Inst.Index, err_union_ty: Type, operand_is_ptr: bool, result_ty: Type) !?*const llvm.Value { + fn lowerTry( + fg: *FuncGen, + err_union: *const llvm.Value, + body: []const Air.Inst.Index, + err_union_ty: Type, + operand_is_ptr: bool, + result_ty: Type, + ) !?*const llvm.Value { const payload_ty = err_union_ty.errorUnionPayload(); const payload_has_bits = payload_ty.hasRuntimeBitsIgnoreComptime(); const target = fg.dg.module.getTarget(); + const err_union_llvm_ty = try fg.dg.lowerType(err_union_ty); if (!err_union_ty.errorUnionSet().errorSetIsEmpty()) { const is_err = err: { @@ -4843,14 +4859,17 @@ pub const FuncGen = struct { const zero = err_set_ty.constNull(); if (!payload_has_bits) { // TODO add alignment to this load - const loaded = if (operand_is_ptr) fg.builder.buildLoad(err_union, "") else err_union; + const loaded = if (operand_is_ptr) + fg.builder.buildLoad(err_set_ty, err_union, "") + else + err_union; break :err fg.builder.buildICmp(.NE, loaded, zero, ""); } const err_field_index = errUnionErrorOffset(payload_ty, target); if (operand_is_ptr or isByRef(err_union_ty)) { - const err_field_ptr = fg.builder.buildStructGEP(err_union, err_field_index, ""); + const err_field_ptr = fg.builder.buildStructGEP(err_union_llvm_ty, err_union, err_field_index, ""); // TODO add alignment to this load - const loaded = fg.builder.buildLoad(err_field_ptr, ""); + const loaded = fg.builder.buildLoad(err_set_ty, err_field_ptr, ""); break :err fg.builder.buildICmp(.NE, loaded, zero, ""); } const loaded = fg.builder.buildExtractValue(err_union, err_field_index, ""); @@ -4876,13 +4895,13 @@ pub const FuncGen = struct { } const offset = errUnionPayloadOffset(payload_ty, target); if (operand_is_ptr or isByRef(payload_ty)) { - return fg.builder.buildStructGEP(err_union, offset, ""); + return fg.builder.buildStructGEP(err_union_llvm_ty, err_union, offset, ""); } else if (isByRef(err_union_ty)) { - const payload_ptr = fg.builder.buildStructGEP(err_union, offset, ""); + const payload_ptr = fg.builder.buildStructGEP(err_union_llvm_ty, err_union, offset, ""); if (isByRef(payload_ty)) { return payload_ptr; } - const load_inst = fg.builder.buildLoad(payload_ptr, ""); + const load_inst = fg.builder.buildLoad(payload_ptr.getGEPSourceElementType(), payload_ptr, ""); load_inst.setAlignment(payload_ty.abiAlignment(target)); return load_inst; } @@ -4977,7 +4996,8 @@ pub const FuncGen = struct { const indices: [2]*const llvm.Value = .{ llvm_usize.constNull(), llvm_usize.constNull(), }; - const ptr = self.builder.buildInBoundsGEP(operand, &indices, indices.len, ""); + const elem_llvm_ty = try self.dg.lowerType(array_ty.childType()); + const ptr = self.builder.buildInBoundsGEP(elem_llvm_ty, operand, &indices, indices.len, ""); const partial = self.builder.buildInsertValue(slice_llvm_ty.getUndef(), ptr, 0, ""); return self.builder.buildInsertValue(partial, len, 1, ""); } @@ -5038,7 +5058,7 @@ pub const FuncGen = struct { const libc_fn = self.getLibcFunction(fn_name, ¶m_types, dest_llvm_ty); const params = [1]*const llvm.Value{extended}; - return self.builder.buildCall(libc_fn, ¶ms, params.len, .C, .Auto, ""); + return self.builder.buildCall(libc_fn.typeOf(), libc_fn, ¶ms, params.len, .C, .Auto, ""); } fn airFloatToInt(self: *FuncGen, inst: Air.Inst.Index, want_fast_math: bool) !?*const llvm.Value { @@ -5093,7 +5113,7 @@ pub const FuncGen = struct { const libc_fn = self.getLibcFunction(fn_name, ¶m_types, libc_ret_ty); const params = [1]*const llvm.Value{operand}; - var result = self.builder.buildCall(libc_fn, ¶ms, params.len, .C, .Auto, ""); + var result = self.builder.buildCall(libc_fn.typeOf(), libc_fn, ¶ms, params.len, .C, .Auto, ""); if (libc_ret_ty != ret_ty) result = self.builder.buildBitCast(result, ret_ty, ""); if (ret_ty != dest_llvm_ty) result = self.builder.buildTrunc(result, dest_llvm_ty, ""); @@ -5113,8 +5133,9 @@ pub const FuncGen = struct { const ty_op = self.air.instructions.items(.data)[inst].ty_op; const slice_ptr = try self.resolveInst(ty_op.operand); + const slice_llvm_ty = try self.dg.lowerType(self.air.typeOf(ty_op.operand).childType()); - return self.builder.buildStructGEP(slice_ptr, index, ""); + return self.builder.buildStructGEP(slice_llvm_ty, slice_ptr, index, ""); } fn airSliceElemVal(self: *FuncGen, inst: Air.Inst.Index) !?*const llvm.Value { @@ -5124,7 +5145,10 @@ pub const FuncGen = struct { const slice = try self.resolveInst(bin_op.lhs); const index = try self.resolveInst(bin_op.rhs); - const ptr = self.sliceElemPtr(slice, index); + const llvm_elem_ty = try self.dg.lowerType(slice_ty.childType()); + const base_ptr = self.builder.buildExtractValue(slice, 0, ""); + const indices: [1]*const llvm.Value = .{index}; + const ptr = self.builder.buildInBoundsGEP(llvm_elem_ty, base_ptr, &indices, indices.len, ""); return self.load(ptr, slice_ty); } @@ -5132,10 +5156,14 @@ pub const FuncGen = struct { if (self.liveness.isUnused(inst)) return null; const ty_pl = self.air.instructions.items(.data)[inst].ty_pl; const bin_op = self.air.extraData(Air.Bin, ty_pl.payload).data; + const slice_ty = self.air.typeOf(bin_op.lhs); const slice = try self.resolveInst(bin_op.lhs); const index = try self.resolveInst(bin_op.rhs); - return self.sliceElemPtr(slice, index); + const llvm_elem_ty = try self.dg.lowerType(slice_ty.childType()); + const base_ptr = self.builder.buildExtractValue(slice, 0, ""); + const indices: [1]*const llvm.Value = .{index}; + return self.builder.buildInBoundsGEP(llvm_elem_ty, base_ptr, &indices, indices.len, ""); } fn airArrayElemVal(self: *FuncGen, inst: Air.Inst.Index) !?*const llvm.Value { @@ -5146,13 +5174,14 @@ pub const FuncGen = struct { const array_llvm_val = try self.resolveInst(bin_op.lhs); const rhs = try self.resolveInst(bin_op.rhs); if (isByRef(array_ty)) { - const indices: [2]*const llvm.Value = .{ self.context.intType(32).constNull(), rhs }; - const elem_ptr = self.builder.buildInBoundsGEP(array_llvm_val, &indices, indices.len, ""); const elem_ty = array_ty.childType(); + const elem_llvm_ty = try self.dg.lowerType(elem_ty); + const indices: [2]*const llvm.Value = .{ self.context.intType(32).constNull(), rhs }; + const elem_ptr = self.builder.buildInBoundsGEP(elem_llvm_ty, array_llvm_val, &indices, indices.len, ""); if (isByRef(elem_ty)) { return elem_ptr; } else { - return self.builder.buildLoad(elem_ptr, ""); + return self.builder.buildLoad(elem_llvm_ty, elem_ptr, ""); } } @@ -5165,15 +5194,16 @@ pub const FuncGen = struct { const ptr_ty = self.air.typeOf(bin_op.lhs); if (!ptr_ty.isVolatilePtr() and self.liveness.isUnused(inst)) return null; + const llvm_elem_ty = try self.dg.lowerType(ptr_ty.childType()); const base_ptr = try self.resolveInst(bin_op.lhs); const rhs = try self.resolveInst(bin_op.rhs); const ptr = if (ptr_ty.isSinglePointer()) ptr: { // If this is a single-item pointer to an array, we need another index in the GEP. const indices: [2]*const llvm.Value = .{ self.context.intType(32).constNull(), rhs }; - break :ptr self.builder.buildInBoundsGEP(base_ptr, &indices, indices.len, ""); + break :ptr self.builder.buildInBoundsGEP(llvm_elem_ty, base_ptr, &indices, indices.len, ""); } else ptr: { const indices: [1]*const llvm.Value = .{rhs}; - break :ptr self.builder.buildInBoundsGEP(base_ptr, &indices, indices.len, ""); + break :ptr self.builder.buildInBoundsGEP(llvm_elem_ty, base_ptr, &indices, indices.len, ""); }; return self.load(ptr, ptr_ty); } @@ -5189,13 +5219,14 @@ pub const FuncGen = struct { const base_ptr = try self.resolveInst(bin_op.lhs); const rhs = try self.resolveInst(bin_op.rhs); + const llvm_elem_ty = try self.dg.lowerType(elem_ty); if (ptr_ty.isSinglePointer()) { // If this is a single-item pointer to an array, we need another index in the GEP. const indices: [2]*const llvm.Value = .{ self.context.intType(32).constNull(), rhs }; - return self.builder.buildInBoundsGEP(base_ptr, &indices, indices.len, ""); + return self.builder.buildInBoundsGEP(llvm_elem_ty, base_ptr, &indices, indices.len, ""); } else { const indices: [1]*const llvm.Value = .{rhs}; - return self.builder.buildInBoundsGEP(base_ptr, &indices, indices.len, ""); + return self.builder.buildInBoundsGEP(llvm_elem_ty, base_ptr, &indices, indices.len, ""); } } @@ -5279,20 +5310,22 @@ pub const FuncGen = struct { assert(struct_ty.containerLayout() != .Packed); var ptr_ty_buf: Type.Payload.Pointer = undefined; const llvm_field_index = llvmFieldIndex(struct_ty, field_index, target, &ptr_ty_buf).?; - const field_ptr = self.builder.buildStructGEP(struct_llvm_val, llvm_field_index, ""); + const struct_llvm_ty = try self.dg.lowerType(struct_ty); + const field_ptr = self.builder.buildStructGEP(struct_llvm_ty, struct_llvm_val, llvm_field_index, ""); const field_ptr_ty = Type.initPayload(&ptr_ty_buf.base); return self.load(field_ptr, field_ptr_ty); }, .Union => { - const llvm_field_ty = try self.dg.lowerType(field_ty); + const union_llvm_ty = try self.dg.lowerType(struct_ty); const layout = struct_ty.unionGetLayout(target); const payload_index = @boolToInt(layout.tag_align >= layout.payload_align); - const union_field_ptr = self.builder.buildStructGEP(struct_llvm_val, payload_index, ""); + const union_field_ptr = self.builder.buildStructGEP(union_llvm_ty, struct_llvm_val, payload_index, ""); + const llvm_field_ty = try self.dg.lowerType(field_ty); const field_ptr = self.builder.buildBitCast(union_field_ptr, llvm_field_ty.pointerType(0), ""); if (isByRef(field_ty)) { return field_ptr; } else { - return self.builder.buildLoad(field_ptr, ""); + return self.builder.buildLoad(llvm_field_ty, field_ptr, ""); } }, else => unreachable, @@ -5605,10 +5638,11 @@ pub const FuncGen = struct { llvm_param_types[llvm_param_i] = arg_llvm_value.typeOf(); } else { const alignment = arg_ty.abiAlignment(target); - const load_inst = self.builder.buildLoad(arg_llvm_value, ""); + const arg_llvm_ty = try self.dg.lowerType(arg_ty); + const load_inst = self.builder.buildLoad(arg_llvm_ty, arg_llvm_value, ""); load_inst.setAlignment(alignment); llvm_param_values[llvm_param_i] = load_inst; - llvm_param_types[llvm_param_i] = load_inst.typeOf(); + llvm_param_types[llvm_param_i] = arg_llvm_ty; } } else { if (constraintAllowsRegister(constraint)) { @@ -5769,6 +5803,7 @@ pub const FuncGen = struct { .False, ); const call = self.builder.buildCall( + asm_fn.typeOf(), asm_fn, llvm_param_values.ptr, @intCast(c_uint, param_count), @@ -5819,9 +5854,12 @@ pub const FuncGen = struct { const operand = try self.resolveInst(un_op); const operand_ty = self.air.typeOf(un_op); const optional_ty = if (operand_is_ptr) operand_ty.childType() else operand_ty; + const optional_llvm_ty = try self.dg.lowerType(optional_ty); if (optional_ty.optionalReprIsPayload()) { - const optional_llvm_ty = try self.dg.lowerType(optional_ty); - const loaded = if (operand_is_ptr) self.builder.buildLoad(operand, "") else operand; + const loaded = if (operand_is_ptr) + self.builder.buildLoad(optional_llvm_ty, operand, "") + else + operand; return self.builder.buildICmp(pred, loaded, optional_llvm_ty.constNull(), ""); } @@ -5830,13 +5868,16 @@ pub const FuncGen = struct { var buf: Type.Payload.ElemType = undefined; const payload_ty = optional_ty.optionalChild(&buf); if (!payload_ty.hasRuntimeBitsIgnoreComptime()) { - const loaded = if (operand_is_ptr) self.builder.buildLoad(operand, "") else operand; + const loaded = if (operand_is_ptr) + self.builder.buildLoad(optional_llvm_ty, operand, "") + else + operand; const llvm_i8 = self.dg.context.intType(8); return self.builder.buildICmp(pred, loaded, llvm_i8.constNull(), ""); } const is_by_ref = operand_is_ptr or isByRef(optional_ty); - const non_null_bit = self.optIsNonNull(operand, is_by_ref); + const non_null_bit = self.optIsNonNull(optional_llvm_ty, operand, is_by_ref); if (pred == .EQ) { return self.builder.buildNot(non_null_bit, ""); } else { @@ -5857,7 +5898,7 @@ pub const FuncGen = struct { const operand_ty = self.air.typeOf(un_op); const err_union_ty = if (operand_is_ptr) operand_ty.childType() else operand_ty; const payload_ty = err_union_ty.errorUnionPayload(); - const err_set_ty = try self.dg.lowerType(Type.initTag(.anyerror)); + const err_set_ty = try self.dg.lowerType(Type.anyerror); const zero = err_set_ty.constNull(); if (err_union_ty.errorUnionSet().errorSetIsEmpty()) { @@ -5870,7 +5911,10 @@ pub const FuncGen = struct { } if (!payload_ty.hasRuntimeBitsIgnoreComptime()) { - const loaded = if (operand_is_ptr) self.builder.buildLoad(operand, "") else operand; + const loaded = if (operand_is_ptr) + self.builder.buildLoad(try self.dg.lowerType(err_union_ty), operand, "") + else + operand; return self.builder.buildICmp(op, loaded, zero, ""); } @@ -5878,8 +5922,9 @@ pub const FuncGen = struct { const err_field_index = errUnionErrorOffset(payload_ty, target); if (operand_is_ptr or isByRef(err_union_ty)) { - const err_field_ptr = self.builder.buildStructGEP(operand, err_field_index, ""); - const loaded = self.builder.buildLoad(err_field_ptr, ""); + const err_union_llvm_ty = try self.dg.lowerType(err_union_ty); + const err_field_ptr = self.builder.buildStructGEP(err_union_llvm_ty, operand, err_field_index, ""); + const loaded = self.builder.buildLoad(err_set_ty, err_field_ptr, ""); return self.builder.buildICmp(op, loaded, zero, ""); } @@ -5900,7 +5945,7 @@ pub const FuncGen = struct { // We have a pointer to a zero-bit value and we need to return // a pointer to a zero-bit value. - // TODO once we update to LLVM 14 this bitcast won't be necessary. + // TODO once we update to LLVM 16 this bitcast won't be necessary. const res_ptr_ty = try self.dg.lowerType(result_ty); return self.builder.buildBitCast(operand, res_ptr_ty, ""); } @@ -5908,7 +5953,8 @@ pub const FuncGen = struct { // The payload and the optional are the same value. return operand; } - return self.builder.buildStructGEP(operand, 0, ""); + const optional_llvm_ty = try self.dg.lowerType(optional_ty); + return self.builder.buildStructGEP(optional_llvm_ty, operand, 0, ""); } fn airOptionalPayloadPtrSet(self: *FuncGen, inst: Air.Inst.Index) !?*const llvm.Value { @@ -5925,7 +5971,7 @@ pub const FuncGen = struct { // We have a pointer to a i8. We need to set it to 1 and then return the same pointer. _ = self.builder.buildStore(non_null_bit, operand); - // TODO once we update to LLVM 14 this bitcast won't be necessary. + // TODO once we update to LLVM 16 this bitcast won't be necessary. const res_ptr_ty = try self.dg.lowerType(result_ty); return self.builder.buildBitCast(operand, res_ptr_ty, ""); } @@ -5936,7 +5982,8 @@ pub const FuncGen = struct { } // First set the non-null bit. - const non_null_ptr = self.builder.buildStructGEP(operand, 1, ""); + const optional_llvm_ty = try self.dg.lowerType(optional_ty); + const non_null_ptr = self.builder.buildStructGEP(optional_llvm_ty, operand, 1, ""); // TODO set alignment on this store _ = self.builder.buildStore(non_null_bit, non_null_ptr); @@ -5944,7 +5991,7 @@ pub const FuncGen = struct { if (self.liveness.isUnused(inst)) return null; - return self.builder.buildStructGEP(operand, 0, ""); + return self.builder.buildStructGEP(optional_llvm_ty, operand, 0, ""); } fn airOptionalPayload(self: *FuncGen, inst: Air.Inst.Index) !?*const llvm.Value { @@ -5961,7 +6008,8 @@ pub const FuncGen = struct { return operand; } - return self.optPayloadHandle(operand, optional_ty); + const opt_llvm_ty = try self.dg.lowerType(optional_ty); + return self.optPayloadHandle(opt_llvm_ty, operand, optional_ty); } fn airErrUnionPayload( @@ -5987,14 +6035,15 @@ pub const FuncGen = struct { return self.builder.buildBitCast(operand, res_ptr_ty, ""); } const offset = errUnionPayloadOffset(payload_ty, target); + const err_union_llvm_ty = try self.dg.lowerType(err_union_ty); if (operand_is_ptr or isByRef(payload_ty)) { - return self.builder.buildStructGEP(operand, offset, ""); + return self.builder.buildStructGEP(err_union_llvm_ty, operand, offset, ""); } else if (isByRef(err_union_ty)) { - const payload_ptr = self.builder.buildStructGEP(operand, offset, ""); + const payload_ptr = self.builder.buildStructGEP(err_union_llvm_ty, operand, offset, ""); if (isByRef(payload_ty)) { return payload_ptr; } - const load_inst = self.builder.buildLoad(payload_ptr, ""); + const load_inst = self.builder.buildLoad(payload_ptr.getGEPSourceElementType(), payload_ptr, ""); load_inst.setAlignment(payload_ty.abiAlignment(target)); return load_inst; } @@ -6022,18 +6071,21 @@ pub const FuncGen = struct { } } + const err_set_llvm_ty = try self.dg.lowerType(Type.anyerror); + const payload_ty = err_union_ty.errorUnionPayload(); if (!payload_ty.hasRuntimeBitsIgnoreComptime()) { if (!operand_is_ptr) return operand; - return self.builder.buildLoad(operand, ""); + return self.builder.buildLoad(err_set_llvm_ty, operand, ""); } const target = self.dg.module.getTarget(); const offset = errUnionErrorOffset(payload_ty, target); if (operand_is_ptr or isByRef(err_union_ty)) { - const err_field_ptr = self.builder.buildStructGEP(operand, offset, ""); - return self.builder.buildLoad(err_field_ptr, ""); + const err_union_llvm_ty = try self.dg.lowerType(err_union_ty); + const err_field_ptr = self.builder.buildStructGEP(err_union_llvm_ty, operand, offset, ""); + return self.builder.buildLoad(err_set_llvm_ty, err_field_ptr, ""); } return self.builder.buildExtractValue(operand, offset, ""); @@ -6042,19 +6094,20 @@ pub const FuncGen = struct { fn airErrUnionPayloadPtrSet(self: *FuncGen, inst: Air.Inst.Index) !?*const llvm.Value { const ty_op = self.air.instructions.items(.data)[inst].ty_op; const operand = try self.resolveInst(ty_op.operand); - const error_union_ty = self.air.typeOf(ty_op.operand).childType(); + const err_union_ty = self.air.typeOf(ty_op.operand).childType(); - const payload_ty = error_union_ty.errorUnionPayload(); + const payload_ty = err_union_ty.errorUnionPayload(); const non_error_val = try self.dg.lowerValue(.{ .ty = Type.anyerror, .val = Value.zero }); if (!payload_ty.hasRuntimeBitsIgnoreComptime()) { _ = self.builder.buildStore(non_error_val, operand); return operand; } const target = self.dg.module.getTarget(); + const err_union_llvm_ty = try self.dg.lowerType(err_union_ty); { const error_offset = errUnionErrorOffset(payload_ty, target); // First set the non-error value. - const non_null_ptr = self.builder.buildStructGEP(operand, error_offset, ""); + const non_null_ptr = self.builder.buildStructGEP(err_union_llvm_ty, operand, error_offset, ""); const store_inst = self.builder.buildStore(non_error_val, non_null_ptr); store_inst.setAlignment(Type.anyerror.abiAlignment(target)); } @@ -6063,7 +6116,7 @@ pub const FuncGen = struct { return null; const payload_offset = errUnionPayloadOffset(payload_ty, target); - return self.builder.buildStructGEP(operand, payload_offset, ""); + return self.builder.buildStructGEP(err_union_llvm_ty, operand, payload_offset, ""); } fn airErrReturnTrace(self: *FuncGen, _: Air.Inst.Index) !?*const llvm.Value { @@ -6093,14 +6146,14 @@ pub const FuncGen = struct { const llvm_optional_ty = try self.dg.lowerType(optional_ty); if (isByRef(optional_ty)) { const optional_ptr = self.buildAlloca(llvm_optional_ty); - const payload_ptr = self.builder.buildStructGEP(optional_ptr, 0, ""); + const payload_ptr = self.builder.buildStructGEP(llvm_optional_ty, optional_ptr, 0, ""); var ptr_ty_payload: Type.Payload.ElemType = .{ .base = .{ .tag = .single_mut_pointer }, .data = payload_ty, }; const payload_ptr_ty = Type.initPayload(&ptr_ty_payload.base); self.store(payload_ptr, payload_ptr_ty, operand, .NotAtomic); - const non_null_ptr = self.builder.buildStructGEP(optional_ptr, 1, ""); + const non_null_ptr = self.builder.buildStructGEP(llvm_optional_ty, optional_ptr, 1, ""); _ = self.builder.buildStore(non_null_bit, non_null_ptr); return optional_ptr; } @@ -6126,10 +6179,10 @@ pub const FuncGen = struct { const error_offset = errUnionErrorOffset(payload_ty, target); if (isByRef(inst_ty)) { const result_ptr = self.buildAlloca(err_un_llvm_ty); - const err_ptr = self.builder.buildStructGEP(result_ptr, error_offset, ""); + const err_ptr = self.builder.buildStructGEP(err_un_llvm_ty, result_ptr, error_offset, ""); const store_inst = self.builder.buildStore(ok_err_code, err_ptr); store_inst.setAlignment(Type.anyerror.abiAlignment(target)); - const payload_ptr = self.builder.buildStructGEP(result_ptr, payload_offset, ""); + const payload_ptr = self.builder.buildStructGEP(err_un_llvm_ty, result_ptr, payload_offset, ""); var ptr_ty_payload: Type.Payload.ElemType = .{ .base = .{ .tag = .single_mut_pointer }, .data = payload_ty, @@ -6160,10 +6213,10 @@ pub const FuncGen = struct { const error_offset = errUnionErrorOffset(payload_ty, target); if (isByRef(err_un_ty)) { const result_ptr = self.buildAlloca(err_un_llvm_ty); - const err_ptr = self.builder.buildStructGEP(result_ptr, error_offset, ""); + const err_ptr = self.builder.buildStructGEP(err_un_llvm_ty, result_ptr, error_offset, ""); const store_inst = self.builder.buildStore(operand, err_ptr); store_inst.setAlignment(Type.anyerror.abiAlignment(target)); - const payload_ptr = self.builder.buildStructGEP(result_ptr, payload_offset, ""); + const payload_ptr = self.builder.buildStructGEP(err_un_llvm_ty, result_ptr, payload_offset, ""); var ptr_ty_payload: Type.Payload.ElemType = .{ .base = .{ .tag = .single_mut_pointer }, .data = payload_ty, @@ -6188,7 +6241,7 @@ pub const FuncGen = struct { const llvm_u32 = self.context.intType(32); const llvm_fn = self.getIntrinsic("llvm.wasm.memory.size", &.{llvm_u32}); const args: [1]*const llvm.Value = .{llvm_u32.constInt(index, .False)}; - return self.builder.buildCall(llvm_fn, &args, args.len, .Fast, .Auto, ""); + return self.builder.buildCall(llvm_fn.typeOf(), llvm_fn, &args, args.len, .Fast, .Auto, ""); } fn airWasmMemoryGrow(self: *FuncGen, inst: Air.Inst.Index) !?*const llvm.Value { @@ -6201,7 +6254,7 @@ pub const FuncGen = struct { llvm_u32.constInt(index, .False), operand, }; - return self.builder.buildCall(llvm_fn, &args, args.len, .Fast, .Auto, ""); + return self.builder.buildCall(llvm_fn.typeOf(), llvm_fn, &args, args.len, .Fast, .Auto, ""); } fn airMin(self: *FuncGen, inst: Air.Inst.Index) !?*const llvm.Value { @@ -6504,15 +6557,16 @@ pub const FuncGen = struct { const base_ptr = try self.resolveInst(bin_op.lhs); const offset = try self.resolveInst(bin_op.rhs); const ptr_ty = self.air.typeOf(bin_op.lhs); + const llvm_elem_ty = try self.dg.lowerType(ptr_ty.childType()); if (ptr_ty.ptrSize() == .One) { // It's a pointer to an array, so according to LLVM we need an extra GEP index. const indices: [2]*const llvm.Value = .{ self.context.intType(32).constNull(), offset, }; - return self.builder.buildInBoundsGEP(base_ptr, &indices, indices.len, ""); + return self.builder.buildInBoundsGEP(llvm_elem_ty, base_ptr, &indices, indices.len, ""); } else { const indices: [1]*const llvm.Value = .{offset}; - return self.builder.buildInBoundsGEP(base_ptr, &indices, indices.len, ""); + return self.builder.buildInBoundsGEP(llvm_elem_ty, base_ptr, &indices, indices.len, ""); } } @@ -6525,15 +6579,16 @@ pub const FuncGen = struct { const offset = try self.resolveInst(bin_op.rhs); const negative_offset = self.builder.buildNeg(offset, ""); const ptr_ty = self.air.typeOf(bin_op.lhs); + const llvm_elem_ty = try self.dg.lowerType(ptr_ty.childType()); if (ptr_ty.ptrSize() == .One) { // It's a pointer to an array, so according to LLVM we need an extra GEP index. const indices: [2]*const llvm.Value = .{ self.context.intType(32).constNull(), negative_offset, }; - return self.builder.buildInBoundsGEP(base_ptr, &indices, indices.len, ""); + return self.builder.buildInBoundsGEP(llvm_elem_ty, base_ptr, &indices, indices.len, ""); } else { const indices: [1]*const llvm.Value = .{negative_offset}; - return self.builder.buildInBoundsGEP(base_ptr, &indices, indices.len, ""); + return self.builder.buildInBoundsGEP(llvm_elem_ty, base_ptr, &indices, indices.len, ""); } } @@ -6564,7 +6619,7 @@ pub const FuncGen = struct { const tg = self.dg.module.getTarget(); const llvm_fn = self.getIntrinsic(intrinsic_name, &.{llvm_lhs_ty}); - const result_struct = self.builder.buildCall(llvm_fn, &[_]*const llvm.Value{ lhs, rhs }, 2, .Fast, .Auto, ""); + const result_struct = self.builder.buildCall(llvm_fn.typeOf(), llvm_fn, &[_]*const llvm.Value{ lhs, rhs }, 2, .Fast, .Auto, ""); const result = self.builder.buildExtractValue(result_struct, 0, ""); const overflow_bit = self.builder.buildExtractValue(result_struct, 1, ""); @@ -6579,12 +6634,12 @@ pub const FuncGen = struct { const result_alignment = dest_ty.abiAlignment(target); alloca_inst.setAlignment(result_alignment); { - const field_ptr = self.builder.buildStructGEP(alloca_inst, result_index, ""); + const field_ptr = self.builder.buildStructGEP(llvm_dest_ty, alloca_inst, result_index, ""); const store_inst = self.builder.buildStore(result, field_ptr); store_inst.setAlignment(result_alignment); } { - const field_ptr = self.builder.buildStructGEP(alloca_inst, overflow_index, ""); + const field_ptr = self.builder.buildStructGEP(llvm_dest_ty, alloca_inst, overflow_index, ""); const store_inst = self.builder.buildStore(overflow_bit, field_ptr); store_inst.setAlignment(1); } @@ -6616,7 +6671,7 @@ pub const FuncGen = struct { for (args_vectors) |arg_vector, k| { args[k] = self.builder.buildExtractElement(arg_vector, index_i32, ""); } - const result_elem = self.builder.buildCall(llvm_fn, &args, args_len, .C, .Auto, ""); + const result_elem = self.builder.buildCall(llvm_fn.typeOf(), llvm_fn, &args, args_len, .C, .Auto, ""); result = self.builder.buildInsertElement(result, result_elem, index_i32, ""); } return result; @@ -6743,7 +6798,7 @@ pub const FuncGen = struct { return self.builder.buildICmp(int_pred, result, zero_vector, ""); } - const result = self.builder.buildCall(libc_fn, ¶ms, params.len, .C, .Auto, ""); + const result = self.builder.buildCall(libc_fn.typeOf(), libc_fn, ¶ms, params.len, .C, .Auto, ""); return self.builder.buildICmp(int_pred, result, zero, ""); } @@ -6871,7 +6926,7 @@ pub const FuncGen = struct { break :b libc_fn; }, }; - return self.builder.buildCall(llvm_fn, ¶ms, params_len, .C, .Auto, ""); + return self.builder.buildCall(llvm_fn.typeOf(), llvm_fn, ¶ms, params_len, .C, .Auto, ""); } fn airMulAdd(self: *FuncGen, inst: Air.Inst.Index) !?*const llvm.Value { @@ -6931,12 +6986,12 @@ pub const FuncGen = struct { const result_alignment = dest_ty.abiAlignment(target); alloca_inst.setAlignment(result_alignment); { - const field_ptr = self.builder.buildStructGEP(alloca_inst, result_index, ""); + const field_ptr = self.builder.buildStructGEP(llvm_dest_ty, alloca_inst, result_index, ""); const store_inst = self.builder.buildStore(result, field_ptr); store_inst.setAlignment(result_alignment); } { - const field_ptr = self.builder.buildStructGEP(alloca_inst, overflow_index, ""); + const field_ptr = self.builder.buildStructGEP(llvm_dest_ty, alloca_inst, overflow_index, ""); const store_inst = self.builder.buildStore(overflow_bit, field_ptr); store_inst.setAlignment(1); } @@ -7226,7 +7281,7 @@ pub const FuncGen = struct { const index_usize = llvm_usize.constInt(i, .False); const index_u32 = llvm_u32.constInt(i, .False); const indexes: [2]*const llvm.Value = .{ zero, index_usize }; - const elem_ptr = self.builder.buildInBoundsGEP(array_ptr, &indexes, indexes.len, ""); + const elem_ptr = self.builder.buildInBoundsGEP(llvm_dest_ty, array_ptr, &indexes, indexes.len, ""); const elem = self.builder.buildExtractElement(operand, index_u32, ""); _ = self.builder.buildStore(elem, elem_ptr); } @@ -7243,7 +7298,7 @@ pub const FuncGen = struct { if (bitcast_ok) { const llvm_vector_ptr_ty = llvm_vector_ty.pointerType(0); const casted_ptr = self.builder.buildBitCast(operand, llvm_vector_ptr_ty, ""); - const vector = self.builder.buildLoad(casted_ptr, ""); + const vector = self.builder.buildLoad(llvm_vector_ty, casted_ptr, ""); // The array is aligned to the element's alignment, while the vector might have a completely // different alignment. This means we need to enforce the alignment of this load. vector.setAlignment(elem_ty.abiAlignment(target)); @@ -7251,6 +7306,7 @@ pub const FuncGen = struct { } else { // If the ABI size of the element type is not evenly divisible by size in bits; // a simple bitcast will not work, and we fall back to extractelement. + const elem_llvm_ty = try self.dg.lowerType(elem_ty); const llvm_usize = try self.dg.lowerType(Type.usize); const llvm_u32 = self.context.intType(32); const zero = llvm_usize.constNull(); @@ -7261,8 +7317,8 @@ pub const FuncGen = struct { const index_usize = llvm_usize.constInt(i, .False); const index_u32 = llvm_u32.constInt(i, .False); const indexes: [2]*const llvm.Value = .{ zero, index_usize }; - const elem_ptr = self.builder.buildInBoundsGEP(operand, &indexes, indexes.len, ""); - const elem = self.builder.buildLoad(elem_ptr, ""); + const elem_ptr = self.builder.buildInBoundsGEP(elem_llvm_ty, operand, &indexes, indexes.len, ""); + const elem = self.builder.buildLoad(elem_llvm_ty, elem_ptr, ""); vector = self.builder.buildInsertElement(vector, elem, index_u32, ""); } @@ -7273,7 +7329,7 @@ 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), ""); - const load_inst = self.builder.buildLoad(casted_ptr, ""); + const load_inst = self.builder.buildLoad(llvm_dest_ty, casted_ptr, ""); load_inst.setAlignment(operand_ty.abiAlignment(target)); return load_inst; } @@ -7301,7 +7357,7 @@ pub const FuncGen = struct { const casted_ptr = self.builder.buildBitCast(result_ptr, operand_llvm_ty.pointerType(0), ""); const store_inst = self.builder.buildStore(operand, casted_ptr); store_inst.setAlignment(alignment); - const load_inst = self.builder.buildLoad(result_ptr, ""); + const load_inst = self.builder.buildLoad(llvm_dest_ty, result_ptr, ""); load_inst.setAlignment(alignment); return load_inst; } @@ -7481,7 +7537,7 @@ pub const FuncGen = struct { fn airBreakpoint(self: *FuncGen, inst: Air.Inst.Index) !?*const llvm.Value { _ = inst; const llvm_fn = self.getIntrinsic("llvm.debugtrap", &.{}); - _ = self.builder.buildCall(llvm_fn, undefined, 0, .C, .Auto, ""); + _ = self.builder.buildCall(llvm_fn.typeOf(), llvm_fn, undefined, 0, .C, .Auto, ""); return null; } @@ -7498,7 +7554,7 @@ pub const FuncGen = struct { const llvm_i32 = self.context.intType(32); const llvm_fn = self.getIntrinsic("llvm.returnaddress", &.{}); const params = [_]*const llvm.Value{llvm_i32.constNull()}; - const ptr_val = self.builder.buildCall(llvm_fn, ¶ms, params.len, .Fast, .Auto, ""); + const ptr_val = self.builder.buildCall(llvm_fn.typeOf(), llvm_fn, ¶ms, params.len, .Fast, .Auto, ""); return self.builder.buildPtrToInt(ptr_val, llvm_usize, ""); } @@ -7515,7 +7571,7 @@ pub const FuncGen = struct { }; const params = [_]*const llvm.Value{llvm_i32.constNull()}; - const ptr_val = self.builder.buildCall(llvm_fn, ¶ms, params.len, .Fast, .Auto, ""); + const ptr_val = self.builder.buildCall(llvm_fn.typeOf(), llvm_fn, ¶ms, params.len, .Fast, .Auto, ""); const llvm_usize = try self.dg.lowerType(Type.usize); return self.builder.buildPtrToInt(ptr_val, llvm_usize, ""); } @@ -7740,8 +7796,9 @@ pub const FuncGen = struct { _ = self.builder.buildStore(new_tag, union_ptr); return null; } + const un_llvm_ty = try self.dg.lowerType(un_ty); const tag_index = @boolToInt(layout.tag_align < layout.payload_align); - const tag_field_ptr = self.builder.buildStructGEP(union_ptr, tag_index, ""); + const tag_field_ptr = self.builder.buildStructGEP(un_llvm_ty, union_ptr, tag_index, ""); // TODO alignment on this store _ = self.builder.buildStore(new_tag, tag_field_ptr); return null; @@ -7757,12 +7814,13 @@ pub const FuncGen = struct { if (layout.tag_size == 0) return null; const union_handle = try self.resolveInst(ty_op.operand); if (isByRef(un_ty)) { + const llvm_un_ty = try self.dg.lowerType(un_ty); if (layout.payload_size == 0) { - return self.builder.buildLoad(union_handle, ""); + return self.builder.buildLoad(llvm_un_ty, union_handle, ""); } const tag_index = @boolToInt(layout.tag_align < layout.payload_align); - const tag_field_ptr = self.builder.buildStructGEP(union_handle, tag_index, ""); - return self.builder.buildLoad(tag_field_ptr, ""); + const tag_field_ptr = self.builder.buildStructGEP(llvm_un_ty, union_handle, tag_index, ""); + return self.builder.buildLoad(tag_field_ptr.getGEPSourceElementType(), tag_field_ptr, ""); } else { if (layout.payload_size == 0) { return union_handle; @@ -7805,7 +7863,7 @@ pub const FuncGen = struct { const fn_val = self.getIntrinsic(llvm_fn_name, &.{operand_llvm_ty}); const params = [_]*const llvm.Value{ operand, llvm_i1.constNull() }; - const wrong_size_result = self.builder.buildCall(fn_val, ¶ms, params.len, .C, .Auto, ""); + const wrong_size_result = self.builder.buildCall(fn_val.typeOf(), fn_val, ¶ms, params.len, .C, .Auto, ""); const result_ty = self.air.typeOfIndex(inst); const result_llvm_ty = try self.dg.lowerType(result_ty); @@ -7832,7 +7890,7 @@ pub const FuncGen = struct { const operand_llvm_ty = try self.dg.lowerType(operand_ty); const fn_val = self.getIntrinsic(llvm_fn_name, &.{operand_llvm_ty}); - const wrong_size_result = self.builder.buildCall(fn_val, ¶ms, params.len, .C, .Auto, ""); + const wrong_size_result = self.builder.buildCall(fn_val.typeOf(), fn_val, ¶ms, params.len, .C, .Auto, ""); const result_ty = self.air.typeOfIndex(inst); const result_llvm_ty = try self.dg.lowerType(result_ty); @@ -7889,7 +7947,7 @@ pub const FuncGen = struct { const params = [_]*const llvm.Value{operand}; const fn_val = self.getIntrinsic(llvm_fn_name, &.{operand_llvm_ty}); - const wrong_size_result = self.builder.buildCall(fn_val, ¶ms, params.len, .C, .Auto, ""); + const wrong_size_result = self.builder.buildCall(fn_val.typeOf(), fn_val, ¶ms, params.len, .C, .Auto, ""); const result_ty = self.air.typeOfIndex(inst); const result_llvm_ty = try self.dg.lowerType(result_ty); @@ -7912,7 +7970,7 @@ pub const FuncGen = struct { const llvm_fn = try self.getEnumTagNameFunction(enum_ty); const params = [_]*const llvm.Value{operand}; - return self.builder.buildCall(llvm_fn, ¶ms, params.len, .Fast, .Auto, ""); + return self.builder.buildCall(llvm_fn.typeOf(), llvm_fn, ¶ms, params.len, .Fast, .Auto, ""); } fn getEnumTagNameFunction(self: *FuncGen, enum_ty: Type) !*const llvm.Value { @@ -7973,7 +8031,8 @@ pub const FuncGen = struct { for (fields.keys()) |name, field_index| { const str_init = self.dg.context.constString(name.ptr, @intCast(c_uint, name.len), .False); - const str_global = self.dg.object.llvm_module.addGlobal(str_init.typeOf(), ""); + const str_init_llvm_ty = str_init.typeOf(); + const str_global = self.dg.object.llvm_module.addGlobal(str_init_llvm_ty, ""); str_global.setInitializer(str_init); str_global.setLinkage(.Private); str_global.setGlobalConstant(.True); @@ -7981,7 +8040,7 @@ pub const FuncGen = struct { str_global.setAlignment(1); const slice_fields = [_]*const llvm.Value{ - str_global.constInBoundsGEP(&array_ptr_indices, array_ptr_indices.len), + str_init_llvm_ty.constInBoundsGEP(str_global, &array_ptr_indices, array_ptr_indices.len), usize_llvm_ty.constInt(name.len, .False), }; const slice_init = llvm_ret_ty.constNamedStruct(&slice_fields, slice_fields.len); @@ -8006,7 +8065,7 @@ pub const FuncGen = struct { switch_instr.addCase(this_tag_int_value, return_block); self.builder.positionBuilderAtEnd(return_block); - const loaded = self.builder.buildLoad(slice_global, ""); + const loaded = self.builder.buildLoad(llvm_ret_ty, slice_global, ""); loaded.setAlignment(slice_alignment); _ = self.builder.buildRet(loaded); } @@ -8040,12 +8099,15 @@ pub const FuncGen = struct { const un_op = self.air.instructions.items(.data)[inst].un_op; const operand = try self.resolveInst(un_op); + const slice_ty = self.air.typeOfIndex(inst); + const slice_llvm_ty = try self.dg.lowerType(slice_ty); const error_name_table_ptr = try self.getErrorNameTable(); - const error_name_table = self.builder.buildLoad(error_name_table_ptr, ""); + const ptr_slice_llvm_ty = slice_llvm_ty.pointerType(0); + const error_name_table = self.builder.buildLoad(ptr_slice_llvm_ty, error_name_table_ptr, ""); const indices = [_]*const llvm.Value{operand}; - const error_name_ptr = self.builder.buildInBoundsGEP(error_name_table, &indices, indices.len, ""); - return self.builder.buildLoad(error_name_ptr, ""); + const error_name_ptr = self.builder.buildInBoundsGEP(slice_llvm_ty, error_name_table, &indices, indices.len, ""); + return self.builder.buildLoad(slice_llvm_ty, error_name_ptr, ""); } fn airSplat(self: *FuncGen, inst: Air.Inst.Index) !?*const llvm.Value { @@ -8222,7 +8284,7 @@ pub const FuncGen = struct { const llvm_elem = try self.resolveInst(elem); const llvm_i = llvmFieldIndex(result_ty, i, target, &ptr_ty_buf).?; indices[1] = llvm_u32.constInt(llvm_i, .False); - const field_ptr = self.builder.buildInBoundsGEP(alloca_inst, &indices, indices.len, ""); + const field_ptr = self.builder.buildInBoundsGEP(llvm_result_ty, alloca_inst, &indices, indices.len, ""); var field_ptr_payload: Type.Payload.Pointer = .{ .data = .{ .pointee_type = self.air.typeOf(elem), @@ -8268,7 +8330,7 @@ pub const FuncGen = struct { llvm_usize.constNull(), llvm_usize.constInt(@intCast(c_uint, i), .False), }; - const elem_ptr = self.builder.buildInBoundsGEP(alloca_inst, &indices, indices.len, ""); + const elem_ptr = self.builder.buildInBoundsGEP(llvm_result_ty, alloca_inst, &indices, indices.len, ""); const llvm_elem = try self.resolveInst(elem); self.store(elem_ptr, elem_ptr_ty, llvm_elem, .NotAtomic); } @@ -8277,7 +8339,7 @@ pub const FuncGen = struct { llvm_usize.constNull(), llvm_usize.constInt(@intCast(c_uint, array_info.len), .False), }; - const elem_ptr = self.builder.buildInBoundsGEP(alloca_inst, &indices, indices.len, ""); + const elem_ptr = self.builder.buildInBoundsGEP(llvm_result_ty, alloca_inst, &indices, indices.len, ""); const llvm_elem = try self.dg.lowerValue(.{ .ty = array_info.elem_type, .val = sent_val, @@ -8377,7 +8439,7 @@ pub const FuncGen = struct { index_type.constNull(), }; const len: c_uint = if (field_size == layout.payload_size) 2 else 3; - const field_ptr = self.builder.buildInBoundsGEP(casted_ptr, &indices, len, ""); + const field_ptr = self.builder.buildInBoundsGEP(llvm_union_ty, casted_ptr, &indices, len, ""); self.store(field_ptr, field_ptr_ty, llvm_payload, .NotAtomic); return result_ptr; } @@ -8389,7 +8451,7 @@ pub const FuncGen = struct { index_type.constNull(), }; const len: c_uint = if (field_size == layout.payload_size) 2 else 3; - const field_ptr = self.builder.buildInBoundsGEP(casted_ptr, &indices, len, ""); + const field_ptr = self.builder.buildInBoundsGEP(llvm_union_ty, casted_ptr, &indices, len, ""); self.store(field_ptr, field_ptr_ty, llvm_payload, .NotAtomic); } { @@ -8397,7 +8459,7 @@ pub const FuncGen = struct { index_type.constNull(), index_type.constInt(@boolToInt(layout.tag_align < layout.payload_align), .False), }; - const field_ptr = self.builder.buildInBoundsGEP(casted_ptr, &indices, indices.len, ""); + const field_ptr = self.builder.buildInBoundsGEP(llvm_union_ty, casted_ptr, &indices, indices.len, ""); const tag_llvm_ty = try self.dg.lowerType(union_obj.tag_ty); const llvm_tag = tag_llvm_ty.constInt(extra.field_index, .False); const store_inst = self.builder.buildStore(llvm_tag, field_ptr); @@ -8464,7 +8526,7 @@ pub const FuncGen = struct { llvm_u32.constInt(prefetch.locality, .False), llvm_u32.constInt(@enumToInt(prefetch.cache), .False), }; - _ = self.builder.buildCall(fn_val, ¶ms, params.len, .C, .Auto, ""); + _ = self.builder.buildCall(fn_val.typeOf(), fn_val, ¶ms, params.len, .C, .Auto, ""); return null; } @@ -8544,7 +8606,7 @@ pub const FuncGen = struct { }; var args: [1]*const llvm.Value = .{arg}; - const result = self.builder.buildCall(llvm_fn, &args, args.len, .C, .Auto, ""); + const result = self.builder.buildCall(llvm_fn.typeOf(), llvm_fn, &args, args.len, .C, .Auto, ""); const final_cast_llvm_ty = final_cast orelse return result; return self.builder.buildBitCast(result, final_cast_llvm_ty, ""); } @@ -8571,22 +8633,29 @@ pub const FuncGen = struct { } /// Assumes the optional is not pointer-like and payload has bits. - fn optIsNonNull(self: *FuncGen, opt_handle: *const llvm.Value, is_by_ref: bool) *const llvm.Value { + fn optIsNonNull( + self: *FuncGen, + opt_llvm_ty: *const llvm.Type, + opt_handle: *const llvm.Value, + is_by_ref: bool, + ) *const llvm.Value { + const non_null_llvm_ty = self.context.intType(8); const field = b: { if (is_by_ref) { - const field_ptr = self.builder.buildStructGEP(opt_handle, 1, ""); - break :b self.builder.buildLoad(field_ptr, ""); + const field_ptr = self.builder.buildStructGEP(opt_llvm_ty, opt_handle, 1, ""); + break :b self.builder.buildLoad(non_null_llvm_ty, field_ptr, ""); } break :b self.builder.buildExtractValue(opt_handle, 1, ""); }; comptime assert(optional_layout_version == 3); - return self.builder.buildICmp(.NE, field, self.context.intType(8).constInt(0, .False), ""); + return self.builder.buildICmp(.NE, field, non_null_llvm_ty.constInt(0, .False), ""); } /// Assumes the optional is not pointer-like and payload has bits. fn optPayloadHandle( fg: *FuncGen, + opt_llvm_ty: *const llvm.Type, opt_handle: *const llvm.Value, opt_ty: Type, ) *const llvm.Value { @@ -8595,14 +8664,14 @@ pub const FuncGen = struct { if (isByRef(opt_ty)) { // We have a pointer and we need to return a pointer to the first field. - const payload_ptr = fg.builder.buildStructGEP(opt_handle, 0, ""); + const payload_ptr = fg.builder.buildStructGEP(opt_llvm_ty, opt_handle, 0, ""); if (isByRef(payload_ty)) { return payload_ptr; } const target = fg.dg.module.getTarget(); const payload_alignment = payload_ty.abiAlignment(target); - const load_inst = fg.builder.buildLoad(payload_ptr, ""); + const load_inst = fg.builder.buildLoad(payload_ptr.getGEPSourceElementType(), payload_ptr, ""); load_inst.setAlignment(payload_alignment); return load_inst; } @@ -8627,12 +8696,12 @@ pub const FuncGen = struct { alloca_inst.setAlignment(payload_alignment); { - const field_ptr = self.builder.buildStructGEP(alloca_inst, 0, ""); + const field_ptr = self.builder.buildStructGEP(optional_llvm_ty, alloca_inst, 0, ""); const store_inst = self.builder.buildStore(payload, field_ptr); store_inst.setAlignment(payload_alignment); } { - const field_ptr = self.builder.buildStructGEP(alloca_inst, 1, ""); + const field_ptr = self.builder.buildStructGEP(optional_llvm_ty, alloca_inst, 1, ""); const store_inst = self.builder.buildStore(non_null_field, field_ptr); store_inst.setAlignment(1); } @@ -8678,18 +8747,20 @@ pub const FuncGen = struct { if (byte_offset == 0) { return self.builder.buildBitCast(struct_ptr, result_llvm_ty, ""); } - const llvm_bytes_ptr_ty = self.context.intType(8).pointerType(0); - const ptr_as_bytes = self.builder.buildBitCast(struct_ptr, llvm_bytes_ptr_ty, ""); + const byte_llvm_ty = self.context.intType(8); + const ptr_as_bytes = self.builder.buildBitCast(struct_ptr, byte_llvm_ty.pointerType(0), ""); const llvm_usize = try self.dg.lowerType(Type.usize); const llvm_index = llvm_usize.constInt(byte_offset, .False); const indices: [1]*const llvm.Value = .{llvm_index}; - const new_ptr = self.builder.buildInBoundsGEP(ptr_as_bytes, &indices, indices.len, ""); + const new_ptr = self.builder.buildInBoundsGEP(byte_llvm_ty, ptr_as_bytes, &indices, indices.len, ""); return self.builder.buildBitCast(new_ptr, result_llvm_ty, ""); }, else => { + const struct_llvm_ty = try self.dg.lowerType(struct_ty); + var ty_buf: Type.Payload.Pointer = undefined; if (llvmFieldIndex(struct_ty, field_index, target, &ty_buf)) |llvm_field_index| { - return self.builder.buildStructGEP(struct_ptr, llvm_field_index, ""); + return self.builder.buildStructGEP(struct_llvm_ty, struct_ptr, llvm_field_index, ""); } else { // If we found no index then this means this is a zero sized field at the // end of the struct. Treat our struct pointer as an array of two and get @@ -8698,7 +8769,7 @@ pub const FuncGen = struct { const llvm_usize = try self.dg.lowerType(Type.usize); const llvm_index = llvm_usize.constInt(1, .False); const indices: [1]*const llvm.Value = .{llvm_index}; - return self.builder.buildInBoundsGEP(struct_ptr, &indices, indices.len, ""); + return self.builder.buildInBoundsGEP(struct_llvm_ty, struct_ptr, &indices, indices.len, ""); } }, }, @@ -8716,27 +8787,18 @@ pub const FuncGen = struct { ) !?*const llvm.Value { const union_obj = union_ty.cast(Type.Payload.Union).?.data; const field = &union_obj.fields.values()[field_index]; - const result_llvm_ty = try self.dg.lowerType(self.air.typeOfIndex(inst)); if (!field.ty.hasRuntimeBitsIgnoreComptime()) { return null; } const target = self.dg.module.getTarget(); const layout = union_ty.unionGetLayout(target); const payload_index = @boolToInt(layout.tag_align >= layout.payload_align); - const union_field_ptr = self.builder.buildStructGEP(union_ptr, payload_index, ""); + const union_llvm_ty = try self.dg.lowerType(union_ty); + const union_field_ptr = self.builder.buildStructGEP(union_llvm_ty, union_ptr, payload_index, ""); + const result_llvm_ty = try self.dg.lowerType(self.air.typeOfIndex(inst)); return self.builder.buildBitCast(union_field_ptr, result_llvm_ty, ""); } - fn sliceElemPtr( - self: *FuncGen, - slice: *const llvm.Value, - index: *const llvm.Value, - ) *const llvm.Value { - const base_ptr = self.builder.buildExtractValue(slice, 0, ""); - const indices: [1]*const llvm.Value = .{index}; - return self.builder.buildInBoundsGEP(base_ptr, &indices, indices.len, ""); - } - fn getIntrinsic(self: *FuncGen, name: []const u8, types: []const *const llvm.Type) *const llvm.Value { const id = llvm.lookupIntrinsicID(name.ptr, name.len); assert(id != 0); @@ -8754,8 +8816,8 @@ pub const FuncGen = struct { const ptr_alignment = ptr_ty.ptrAlignment(target); const ptr_volatile = llvm.Bool.fromBool(ptr_ty.isVolatilePtr()); if (info.host_size == 0) { + const elem_llvm_ty = try self.dg.lowerType(info.pointee_type); if (isByRef(info.pointee_type)) { - const elem_llvm_ty = try self.dg.lowerType(info.pointee_type); const result_align = info.pointee_type.abiAlignment(target); const max_align = @maximum(result_align, ptr_alignment); const result_ptr = self.buildAlloca(elem_llvm_ty); @@ -8773,15 +8835,15 @@ pub const FuncGen = struct { ); return result_ptr; } - const llvm_inst = self.builder.buildLoad(ptr, ""); + const llvm_inst = self.builder.buildLoad(elem_llvm_ty, ptr, ""); llvm_inst.setAlignment(ptr_alignment); llvm_inst.setVolatile(ptr_volatile); return llvm_inst; } - const int_ptr_ty = self.context.intType(info.host_size * 8).pointerType(0); - const int_ptr = self.builder.buildBitCast(ptr, int_ptr_ty, ""); - const containing_int = self.builder.buildLoad(int_ptr, ""); + const int_elem_ty = self.context.intType(info.host_size * 8); + const int_ptr = self.builder.buildBitCast(ptr, int_elem_ty.pointerType(0), ""); + const containing_int = self.builder.buildLoad(int_elem_ty, int_ptr, ""); containing_int.setAlignment(ptr_alignment); containing_int.setVolatile(ptr_volatile); @@ -8828,9 +8890,9 @@ pub const FuncGen = struct { const ptr_alignment = ptr_ty.ptrAlignment(target); const ptr_volatile = llvm.Bool.fromBool(info.@"volatile"); if (info.host_size != 0) { - const int_ptr_ty = self.context.intType(info.host_size * 8).pointerType(0); - const int_ptr = self.builder.buildBitCast(ptr, int_ptr_ty, ""); - const containing_int = self.builder.buildLoad(int_ptr, ""); + const int_elem_ty = self.context.intType(info.host_size * 8); + const int_ptr = self.builder.buildBitCast(ptr, int_elem_ty.pointerType(0), ""); + const containing_int = self.builder.buildLoad(int_elem_ty, int_ptr, ""); assert(ordering == .NotAtomic); containing_int.setAlignment(ptr_alignment); containing_int.setVolatile(ptr_volatile); diff --git a/src/codegen/llvm/bindings.zig b/src/codegen/llvm/bindings.zig index 7a3ed9ebd1..9c337cc287 100644 --- a/src/codegen/llvm/bindings.zig +++ b/src/codegen/llvm/bindings.zig @@ -141,14 +141,6 @@ pub const Value = opaque { pub const setAliasee = LLVMAliasSetAliasee; extern fn LLVMAliasSetAliasee(Alias: *const Value, Aliasee: *const Value) void; - pub const constInBoundsGEP = LLVMConstInBoundsGEP2; - extern fn LLVMConstInBoundsGEP2( - Ty: *const Type, - ConstantVal: *const Value, - ConstantIndices: [*]const *const Value, - NumIndices: c_uint, - ) *const Value; - pub const constBitCast = LLVMConstBitCast; extern fn LLVMConstBitCast(ConstantVal: *const Value, ToType: *const Type) *const Value; @@ -249,6 +241,9 @@ pub const Value = opaque { pub const addFunctionAttr = ZigLLVMAddFunctionAttr; extern fn ZigLLVMAddFunctionAttr(Fn: *const Value, attr_name: [*:0]const u8, attr_value: [*:0]const u8) void; + + pub const getGEPSourceElementType = LLVMGetGEPSourceElementType; + extern fn LLVMGetGEPSourceElementType(GEP: *const Value) *const Type; }; pub const Type = opaque { @@ -280,6 +275,9 @@ pub const Type = opaque { pub const getUndef = LLVMGetUndef; extern fn LLVMGetUndef(Ty: *const Type) *const Value; + pub const pointerType = LLVMPointerType; + extern fn LLVMPointerType(ElementType: *const Type, AddressSpace: c_uint) *const Type; + pub const arrayType = LLVMArrayType; extern fn LLVMArrayType(ElementType: *const Type, ElementCount: c_uint) *const Type; @@ -311,6 +309,14 @@ pub const Type = opaque { pub const isSized = LLVMTypeIsSized; extern fn LLVMTypeIsSized(Ty: *const Type) Bool; + + pub const constInBoundsGEP = LLVMConstInBoundsGEP2; + extern fn LLVMConstInBoundsGEP2( + Ty: *const Type, + ConstantVal: *const Value, + ConstantIndices: [*]const *const Value, + NumIndices: c_uint, + ) *const Value; }; pub const Module = opaque { -- cgit v1.2.3 From aa79cc10aa38c2c3641d5a430aa33b8bfa6a3d61 Mon Sep 17 00:00:00 2001 From: Andrew Kelley Date: Mon, 1 Aug 2022 22:40:18 -0700 Subject: fix bugs from previous two commits --- src/codegen/llvm.zig | 36 +++++++-------- src/stage1/codegen.cpp | 120 ++++++++++++++++++++++++++++--------------------- 2 files changed, 87 insertions(+), 69 deletions(-) (limited to 'src/codegen/llvm.zig') diff --git a/src/codegen/llvm.zig b/src/codegen/llvm.zig index 900c98c30d..ece704a04c 100644 --- a/src/codegen/llvm.zig +++ b/src/codegen/llvm.zig @@ -4622,7 +4622,7 @@ pub const FuncGen = struct { const operand = try self.resolveInst(un_op); const llvm_fn = try self.getCmpLtErrorsLenFunction(); const args: [1]*const llvm.Value = .{operand}; - return self.builder.buildCall(llvm_fn.typeOf(), llvm_fn, &args, args.len, .Fast, .Auto, ""); + return self.builder.buildCall(llvm_fn.globalGetValueType(), llvm_fn, &args, args.len, .Fast, .Auto, ""); } fn cmp( @@ -5058,7 +5058,7 @@ pub const FuncGen = struct { const libc_fn = self.getLibcFunction(fn_name, ¶m_types, dest_llvm_ty); const params = [1]*const llvm.Value{extended}; - return self.builder.buildCall(libc_fn.typeOf(), libc_fn, ¶ms, params.len, .C, .Auto, ""); + return self.builder.buildCall(libc_fn.globalGetValueType(), libc_fn, ¶ms, params.len, .C, .Auto, ""); } fn airFloatToInt(self: *FuncGen, inst: Air.Inst.Index, want_fast_math: bool) !?*const llvm.Value { @@ -5113,7 +5113,7 @@ pub const FuncGen = struct { const libc_fn = self.getLibcFunction(fn_name, ¶m_types, libc_ret_ty); const params = [1]*const llvm.Value{operand}; - var result = self.builder.buildCall(libc_fn.typeOf(), libc_fn, ¶ms, params.len, .C, .Auto, ""); + var result = self.builder.buildCall(libc_fn.globalGetValueType(), libc_fn, ¶ms, params.len, .C, .Auto, ""); if (libc_ret_ty != ret_ty) result = self.builder.buildBitCast(result, ret_ty, ""); if (ret_ty != dest_llvm_ty) result = self.builder.buildTrunc(result, dest_llvm_ty, ""); @@ -6241,7 +6241,7 @@ pub const FuncGen = struct { const llvm_u32 = self.context.intType(32); const llvm_fn = self.getIntrinsic("llvm.wasm.memory.size", &.{llvm_u32}); const args: [1]*const llvm.Value = .{llvm_u32.constInt(index, .False)}; - return self.builder.buildCall(llvm_fn.typeOf(), llvm_fn, &args, args.len, .Fast, .Auto, ""); + return self.builder.buildCall(llvm_fn.globalGetValueType(), llvm_fn, &args, args.len, .Fast, .Auto, ""); } fn airWasmMemoryGrow(self: *FuncGen, inst: Air.Inst.Index) !?*const llvm.Value { @@ -6254,7 +6254,7 @@ pub const FuncGen = struct { llvm_u32.constInt(index, .False), operand, }; - return self.builder.buildCall(llvm_fn.typeOf(), llvm_fn, &args, args.len, .Fast, .Auto, ""); + return self.builder.buildCall(llvm_fn.globalGetValueType(), llvm_fn, &args, args.len, .Fast, .Auto, ""); } fn airMin(self: *FuncGen, inst: Air.Inst.Index) !?*const llvm.Value { @@ -6619,7 +6619,7 @@ pub const FuncGen = struct { const tg = self.dg.module.getTarget(); const llvm_fn = self.getIntrinsic(intrinsic_name, &.{llvm_lhs_ty}); - const result_struct = self.builder.buildCall(llvm_fn.typeOf(), llvm_fn, &[_]*const llvm.Value{ lhs, rhs }, 2, .Fast, .Auto, ""); + const result_struct = self.builder.buildCall(llvm_fn.globalGetValueType(), llvm_fn, &[_]*const llvm.Value{ lhs, rhs }, 2, .Fast, .Auto, ""); const result = self.builder.buildExtractValue(result_struct, 0, ""); const overflow_bit = self.builder.buildExtractValue(result_struct, 1, ""); @@ -6671,7 +6671,7 @@ pub const FuncGen = struct { for (args_vectors) |arg_vector, k| { args[k] = self.builder.buildExtractElement(arg_vector, index_i32, ""); } - const result_elem = self.builder.buildCall(llvm_fn.typeOf(), llvm_fn, &args, args_len, .C, .Auto, ""); + const result_elem = self.builder.buildCall(llvm_fn.globalGetValueType(), llvm_fn, &args, args_len, .C, .Auto, ""); result = self.builder.buildInsertElement(result, result_elem, index_i32, ""); } return result; @@ -6798,7 +6798,7 @@ pub const FuncGen = struct { return self.builder.buildICmp(int_pred, result, zero_vector, ""); } - const result = self.builder.buildCall(libc_fn.typeOf(), libc_fn, ¶ms, params.len, .C, .Auto, ""); + const result = self.builder.buildCall(libc_fn.globalGetValueType(), libc_fn, ¶ms, params.len, .C, .Auto, ""); return self.builder.buildICmp(int_pred, result, zero, ""); } @@ -6926,7 +6926,7 @@ pub const FuncGen = struct { break :b libc_fn; }, }; - return self.builder.buildCall(llvm_fn.typeOf(), llvm_fn, ¶ms, params_len, .C, .Auto, ""); + return self.builder.buildCall(llvm_fn.globalGetValueType(), llvm_fn, ¶ms, params_len, .C, .Auto, ""); } fn airMulAdd(self: *FuncGen, inst: Air.Inst.Index) !?*const llvm.Value { @@ -7537,7 +7537,7 @@ pub const FuncGen = struct { fn airBreakpoint(self: *FuncGen, inst: Air.Inst.Index) !?*const llvm.Value { _ = inst; const llvm_fn = self.getIntrinsic("llvm.debugtrap", &.{}); - _ = self.builder.buildCall(llvm_fn.typeOf(), llvm_fn, undefined, 0, .C, .Auto, ""); + _ = self.builder.buildCall(llvm_fn.globalGetValueType(), llvm_fn, undefined, 0, .C, .Auto, ""); return null; } @@ -7554,7 +7554,7 @@ pub const FuncGen = struct { const llvm_i32 = self.context.intType(32); const llvm_fn = self.getIntrinsic("llvm.returnaddress", &.{}); const params = [_]*const llvm.Value{llvm_i32.constNull()}; - const ptr_val = self.builder.buildCall(llvm_fn.typeOf(), llvm_fn, ¶ms, params.len, .Fast, .Auto, ""); + const ptr_val = self.builder.buildCall(llvm_fn.globalGetValueType(), llvm_fn, ¶ms, params.len, .Fast, .Auto, ""); return self.builder.buildPtrToInt(ptr_val, llvm_usize, ""); } @@ -7571,7 +7571,7 @@ pub const FuncGen = struct { }; const params = [_]*const llvm.Value{llvm_i32.constNull()}; - const ptr_val = self.builder.buildCall(llvm_fn.typeOf(), llvm_fn, ¶ms, params.len, .Fast, .Auto, ""); + const ptr_val = self.builder.buildCall(llvm_fn.globalGetValueType(), llvm_fn, ¶ms, params.len, .Fast, .Auto, ""); const llvm_usize = try self.dg.lowerType(Type.usize); return self.builder.buildPtrToInt(ptr_val, llvm_usize, ""); } @@ -7863,7 +7863,7 @@ pub const FuncGen = struct { const fn_val = self.getIntrinsic(llvm_fn_name, &.{operand_llvm_ty}); const params = [_]*const llvm.Value{ operand, llvm_i1.constNull() }; - const wrong_size_result = self.builder.buildCall(fn_val.typeOf(), fn_val, ¶ms, params.len, .C, .Auto, ""); + const wrong_size_result = self.builder.buildCall(fn_val.globalGetValueType(), fn_val, ¶ms, params.len, .C, .Auto, ""); const result_ty = self.air.typeOfIndex(inst); const result_llvm_ty = try self.dg.lowerType(result_ty); @@ -7890,7 +7890,7 @@ pub const FuncGen = struct { const operand_llvm_ty = try self.dg.lowerType(operand_ty); const fn_val = self.getIntrinsic(llvm_fn_name, &.{operand_llvm_ty}); - const wrong_size_result = self.builder.buildCall(fn_val.typeOf(), fn_val, ¶ms, params.len, .C, .Auto, ""); + const wrong_size_result = self.builder.buildCall(fn_val.globalGetValueType(), fn_val, ¶ms, params.len, .C, .Auto, ""); const result_ty = self.air.typeOfIndex(inst); const result_llvm_ty = try self.dg.lowerType(result_ty); @@ -7947,7 +7947,7 @@ pub const FuncGen = struct { const params = [_]*const llvm.Value{operand}; const fn_val = self.getIntrinsic(llvm_fn_name, &.{operand_llvm_ty}); - const wrong_size_result = self.builder.buildCall(fn_val.typeOf(), fn_val, ¶ms, params.len, .C, .Auto, ""); + const wrong_size_result = self.builder.buildCall(fn_val.globalGetValueType(), fn_val, ¶ms, params.len, .C, .Auto, ""); const result_ty = self.air.typeOfIndex(inst); const result_llvm_ty = try self.dg.lowerType(result_ty); @@ -7970,7 +7970,7 @@ pub const FuncGen = struct { const llvm_fn = try self.getEnumTagNameFunction(enum_ty); const params = [_]*const llvm.Value{operand}; - return self.builder.buildCall(llvm_fn.typeOf(), llvm_fn, ¶ms, params.len, .Fast, .Auto, ""); + return self.builder.buildCall(llvm_fn.globalGetValueType(), llvm_fn, ¶ms, params.len, .Fast, .Auto, ""); } fn getEnumTagNameFunction(self: *FuncGen, enum_ty: Type) !*const llvm.Value { @@ -8526,7 +8526,7 @@ pub const FuncGen = struct { llvm_u32.constInt(prefetch.locality, .False), llvm_u32.constInt(@enumToInt(prefetch.cache), .False), }; - _ = self.builder.buildCall(fn_val.typeOf(), fn_val, ¶ms, params.len, .C, .Auto, ""); + _ = self.builder.buildCall(fn_val.globalGetValueType(), fn_val, ¶ms, params.len, .C, .Auto, ""); return null; } @@ -8606,7 +8606,7 @@ pub const FuncGen = struct { }; var args: [1]*const llvm.Value = .{arg}; - const result = self.builder.buildCall(llvm_fn.typeOf(), llvm_fn, &args, args.len, .C, .Auto, ""); + const result = self.builder.buildCall(llvm_fn.globalGetValueType(), llvm_fn, &args, args.len, .C, .Auto, ""); const final_cast_llvm_ty = final_cast orelse return result; return self.builder.buildBitCast(result, final_cast_llvm_ty, ""); } diff --git a/src/stage1/codegen.cpp b/src/stage1/codegen.cpp index 9b3e6607e5..a3d11471df 100644 --- a/src/stage1/codegen.cpp +++ b/src/stage1/codegen.cpp @@ -1092,7 +1092,7 @@ static void gen_panic(CodeGen *g, LLVMValueRef msg_arg, LLVMValueRef stack_trace msg_arg, stack_trace_arg, }; - ZigLLVMBuildCall(g->builder, LLVMTypeOf(fn_val), fn_val, args, 2, llvm_cc, ZigLLVM_CallAttrAuto, ""); + ZigLLVMBuildCall(g->builder, LLVMGlobalGetValueType(fn_val), fn_val, args, 2, llvm_cc, ZigLLVM_CallAttrAuto, ""); if (!stack_trace_is_llvm_alloca) { // The stack trace argument is not in the stack of the caller, so // we'd like to set tail call here, but because slices (the type of msg_arg) are @@ -1369,7 +1369,7 @@ static LLVMValueRef get_return_err_fn(CodeGen *g) { LLVMPositionBuilderAtEnd(g->builder, dest_non_null_block); LLVMValueRef args[] = { err_ret_trace_ptr, return_address }; - ZigLLVMBuildCall(g->builder, LLVMTypeOf(add_error_return_trace_addr_fn_val), + ZigLLVMBuildCall(g->builder, LLVMGlobalGetValueType(add_error_return_trace_addr_fn_val), add_error_return_trace_addr_fn_val, args, 2, get_llvm_cc(g, CallingConventionUnspecified), ZigLLVM_CallAttrAlwaysInline, ""); LLVMBuildRetVoid(g->builder); @@ -1546,14 +1546,14 @@ static void gen_safety_crash_for_err(CodeGen *g, LLVMValueRef err_val, Scope *sc err_ret_trace_val, err_val, }; - call_instruction = ZigLLVMBuildCall(g->builder, LLVMTypeOf(safety_crash_err_fn), + call_instruction = ZigLLVMBuildCall(g->builder, LLVMGlobalGetValueType(safety_crash_err_fn), safety_crash_err_fn, args, 2, get_llvm_cc(g, CallingConventionUnspecified), ZigLLVM_CallAttrAuto, ""); } else { LLVMValueRef args[] = { err_val, }; - call_instruction = ZigLLVMBuildCall(g->builder, LLVMTypeOf(safety_crash_err_fn), + call_instruction = ZigLLVMBuildCall(g->builder, LLVMGlobalGetValueType(safety_crash_err_fn), safety_crash_err_fn, args, 1, get_llvm_cc(g, CallingConventionUnspecified), ZigLLVM_CallAttrAuto, ""); } @@ -1732,7 +1732,7 @@ static LLVMValueRef gen_soft_float_widen_or_shorten(CodeGen *g, ZigType *actual_ func_ref = LLVMAddFunction(g->module, fn_name, fn_type); } - result = LLVMBuildCall2(g->builder, LLVMTypeOf(func_ref), func_ref, &expr_val, 1, ""); + result = LLVMBuildCall2(g->builder, LLVMGlobalGetValueType(func_ref), func_ref, &expr_val, 1, ""); // On non-Arm platforms we need to bitcast __trunc<>fhf2 result back to f16 if (castTruncatedToF16) { @@ -1878,7 +1878,7 @@ static LLVMValueRef gen_overflow_op(CodeGen *g, ZigType *operand_type, AddSubMul val1, val2, }; - LLVMValueRef result_struct = LLVMBuildCall2(g->builder, LLVMTypeOf(fn_val), fn_val, params, 2, ""); + LLVMValueRef result_struct = LLVMBuildCall2(g->builder, LLVMGlobalGetValueType(fn_val), fn_val, params, 2, ""); LLVMValueRef result = LLVMBuildExtractValue(g->builder, result_struct, 0, ""); LLVMValueRef overflow_bit = LLVMBuildExtractValue(g->builder, result_struct, 1, ""); if (operand_type->id == ZigTypeIdVector) { @@ -2663,7 +2663,7 @@ static LLVMValueRef get_merge_err_ret_traces_fn_val(CodeGen *g) { LLVMValueRef this_addr_val = LLVMBuildLoad2(g->builder, LLVMGetGEPSourceElementType(addr_ptr), addr_ptr, ""); LLVMValueRef args[] = {dest_stack_trace_ptr, this_addr_val}; - ZigLLVMBuildCall(g->builder, LLVMTypeOf(add_error_return_trace_addr_fn_val), + ZigLLVMBuildCall(g->builder, LLVMGlobalGetValueType(add_error_return_trace_addr_fn_val), add_error_return_trace_addr_fn_val, args, 2, get_llvm_cc(g, CallingConventionUnspecified), ZigLLVM_CallAttrAlwaysInline, ""); LLVMValueRef prev_frames_left = LLVMBuildLoad2(g->builder, usize_type_ref, frames_left_ptr, ""); LLVMValueRef new_frames_left = LLVMBuildNUWSub(g->builder, prev_frames_left, usize_one, ""); @@ -2703,7 +2703,7 @@ static LLVMValueRef ir_render_save_err_ret_addr(CodeGen *g, Stage1Air *executabl bool is_llvm_alloca; LLVMValueRef my_err_trace_val = get_cur_err_ret_trace_val(g, save_err_ret_addr_instruction->base.scope, &is_llvm_alloca); - ZigLLVMBuildCall(g->builder, LLVMTypeOf(return_err_fn), return_err_fn, &my_err_trace_val, 1, + ZigLLVMBuildCall(g->builder, LLVMGlobalGetValueType(return_err_fn), return_err_fn, &my_err_trace_val, 1, get_llvm_cc(g, CallingConventionUnspecified), ZigLLVM_CallAttrAuto, ""); ZigType *ret_type = g->cur_fn->type_entry->data.fn.fn_type_id.return_type; @@ -2753,7 +2753,7 @@ static LLVMValueRef gen_resume(CodeGen *g, LLVMValueRef fn_val, LLVMValueRef tar LLVMValueRef arg_val = LLVMConstSub(LLVMConstAllOnes(usize_type_ref), LLVMConstInt(usize_type_ref, resume_id, false)); LLVMValueRef args[] = {target_frame_ptr, arg_val}; - return ZigLLVMBuildCall(g->builder, LLVMTypeOf(fn_val), fn_val, args, 2, ZigLLVM_Fast, ZigLLVM_CallAttrAuto, ""); + return ZigLLVMBuildCall(g->builder, LLVMGlobalGetValueType(fn_val), fn_val, args, 2, ZigLLVM_Fast, ZigLLVM_CallAttrAuto, ""); } static LLVMBasicBlockRef gen_suspend_begin(CodeGen *g, const char *name_hint) { @@ -2885,7 +2885,7 @@ static void gen_async_return(CodeGen *g, Stage1AirInstReturn *instruction) { bool is_llvm_alloca; LLVMValueRef my_err_trace_val = get_cur_err_ret_trace_val(g, instruction->base.scope, &is_llvm_alloca); LLVMValueRef args[] = { dest_trace_ptr, my_err_trace_val }; - ZigLLVMBuildCall(g->builder, LLVMTypeOf(get_merge_err_ret_traces_fn_val(g)), + ZigLLVMBuildCall(g->builder, LLVMGlobalGetValueType(get_merge_err_ret_traces_fn_val(g)), get_merge_err_ret_traces_fn_val(g), args, 2, get_llvm_cc(g, CallingConventionUnspecified), ZigLLVM_CallAttrAuto, ""); } @@ -3057,14 +3057,14 @@ static LLVMValueRef gen_soft_float_un_op(CodeGen *g, LLVMValueRef op, ZigType *o LLVMValueRef func_ref = get_soft_float_fn(g, fn_name, 1, scalar_type->llvm_type, scalar_type->llvm_type); if (vector_len == 0) { - return LLVMBuildCall2(g->builder, LLVMTypeOf(func_ref), func_ref, &op, 1, ""); + return LLVMBuildCall2(g->builder, LLVMGlobalGetValueType(func_ref), func_ref, &op, 1, ""); } else { LLVMValueRef result = LLVMGetUndef(operand_type->llvm_type); LLVMTypeRef usize_ref = g->builtin_types.entry_usize->llvm_type; for (uint32_t i = 0; i < vector_len; i++) { LLVMValueRef index_value = LLVMConstInt(usize_ref, i, false); LLVMValueRef param = LLVMBuildExtractElement(g->builder, op, index_value, ""); - LLVMValueRef call_result = LLVMBuildCall2(g->builder, LLVMTypeOf(func_ref), func_ref, ¶m, 1, ""); + LLVMValueRef call_result = LLVMBuildCall2(g->builder, LLVMGlobalGetValueType(func_ref), func_ref, ¶m, 1, ""); result = LLVMBuildInsertElement(g->builder, result, call_result, index_value, ""); } return result; @@ -3081,7 +3081,7 @@ static LLVMValueRef gen_float_un_op(CodeGen *g, LLVMValueRef operand, ZigType *o return gen_soft_float_un_op(g, operand, operand_type, op); } LLVMValueRef float_op_fn = get_float_fn(g, operand_type, ZigLLVMFnIdFloatOp, op); - return LLVMBuildCall2(g->builder, LLVMTypeOf(float_op_fn), float_op_fn, &operand, 1, ""); + return LLVMBuildCall2(g->builder, LLVMGlobalGetValueType(float_op_fn), float_op_fn, &operand, 1, ""); } enum DivKind { @@ -3447,7 +3447,7 @@ static LLVMValueRef gen_soft_int_to_float_op(CodeGen *g, LLVMValueRef value_ref, } LLVMValueRef params[1] = {value_ref}; - return LLVMBuildCall2(g->builder, LLVMTypeOf(func_ref), func_ref, params, param_count, ""); + return LLVMBuildCall2(g->builder, LLVMGlobalGetValueType(func_ref), func_ref, params, param_count, ""); } static LLVMValueRef gen_soft_float_to_int_op(CodeGen *g, LLVMValueRef value_ref, ZigType *operand_type, ZigType *result_type) { @@ -3483,7 +3483,7 @@ static LLVMValueRef gen_soft_float_to_int_op(CodeGen *g, LLVMValueRef value_ref, } LLVMValueRef params[1] = {value_ref}; - LLVMValueRef result = LLVMBuildCall2(g->builder, LLVMTypeOf(func_ref), func_ref, params, param_count, ""); + LLVMValueRef result = LLVMBuildCall2(g->builder, LLVMGlobalGetValueType(func_ref), func_ref, params, param_count, ""); if ((wider_type->data.integral.bit_count == 128) && (g->zig_target->os == OsWindows) && (g->zig_target->arch == ZigLLVM_x86_64)) { result = LLVMBuildBitCast(g->builder, result, wider_type->llvm_type, ""); @@ -3596,7 +3596,7 @@ static LLVMValueRef gen_soft_float_bin_op(CodeGen *g, LLVMValueRef op1_value, LL LLVMValueRef result; if (vector_len == 0) { LLVMValueRef params[2] = {op1_value, op2_value}; - result = LLVMBuildCall2(g->builder, LLVMTypeOf(func_ref), func_ref, params, param_count, ""); + result = LLVMBuildCall2(g->builder, LLVMGlobalGetValueType(func_ref), func_ref, params, param_count, ""); result = add_icmp(g, result, res_icmp); } else { ZigType *alloca_ty = operand_type; @@ -3610,7 +3610,7 @@ static LLVMValueRef gen_soft_float_bin_op(CodeGen *g, LLVMValueRef op1_value, LL LLVMBuildExtractElement(g->builder, op1_value, index_value, ""), LLVMBuildExtractElement(g->builder, op2_value, index_value, ""), }; - LLVMValueRef call_result = LLVMBuildCall2(g->builder, LLVMTypeOf(func_ref), func_ref, params, param_count, ""); + LLVMValueRef call_result = LLVMBuildCall2(g->builder, LLVMGlobalGetValueType(func_ref), func_ref, params, param_count, ""); call_result = add_icmp(g, call_result, res_icmp); result = LLVMBuildInsertElement(g->builder, result, call_result, index_value, ""); } @@ -4585,7 +4585,7 @@ static LLVMValueRef gen_valgrind_client_request(CodeGen *g, LLVMValueRef default LLVMValueRef asm_fn = LLVMGetInlineAsm(function_type, buf_ptr(asm_template), buf_len(asm_template), buf_ptr(asm_constraints), buf_len(asm_constraints), asm_has_side_effects, asm_is_alignstack, LLVMInlineAsmDialectATT, false); - return LLVMBuildCall2(g->builder, LLVMTypeOf(asm_fn), asm_fn, param_values, input_and_output_count, ""); + return LLVMBuildCall2(g->builder, LLVMGlobalGetValueType(asm_fn), asm_fn, param_values, input_and_output_count, ""); } } zig_unreachable(); @@ -4849,7 +4849,7 @@ static void gen_set_stack_pointer(CodeGen *g, LLVMValueRef aligned_end_addr) { aligned_end_addr, }; - LLVMBuildCall2(g->builder, LLVMTypeOf(write_register_fn_val), write_register_fn_val, params, 2, ""); + LLVMBuildCall2(g->builder, LLVMGlobalGetValueType(write_register_fn_val), write_register_fn_val, params, 2, ""); } static void render_async_spills(CodeGen *g) { @@ -4996,10 +4996,6 @@ static LLVMValueRef ir_render_call(CodeGen *g, Stage1Air *executable, Stage1AirI callee_is_async = fn_type->data.fn.fn_type_id.cc == CallingConventionAsync; } - LLVMTypeRef frame_struct_llvm_ty = (instruction->fn_entry != nullptr) ? - get_llvm_type(g, get_fn_frame_type(g, instruction->fn_entry)) : - g->any_frame_header_llvm_ty; - FnTypeId *fn_type_id = &fn_type->data.fn.fn_type_id; ZigType *src_return_type = fn_type_id->return_type; @@ -5018,23 +5014,33 @@ static LLVMValueRef ir_render_call(CodeGen *g, Stage1Air *executable, Stage1AirI ZigType *anyframe_type = nullptr; LLVMValueRef frame_result_loc_uncasted = nullptr; LLVMValueRef frame_result_loc; + LLVMTypeRef frame_struct_llvm_ty; LLVMValueRef awaiter_init_val; LLVMValueRef ret_ptr; if (callee_is_async) { if (instruction->new_stack == nullptr) { if (instruction->modifier == CallModifierAsync) { frame_result_loc = result_loc; + if (result_loc != nullptr) { + ir_assert(instruction->result_loc->value->type->id == ZigTypeIdPointer, &instruction->base); + frame_struct_llvm_ty = get_llvm_type(g, instruction->result_loc->value->type->data.pointer.child_type); + } else { + frame_struct_llvm_ty = nullptr; + } } else { ir_assert(instruction->frame_result_loc != nullptr, &instruction->base); frame_result_loc_uncasted = ir_llvm_value(g, instruction->frame_result_loc); ir_assert(instruction->fn_entry != nullptr, &instruction->base); - frame_result_loc = frame_result_loc_uncasted; + frame_struct_llvm_ty = get_llvm_type(g, instruction->fn_entry->frame_type); + frame_result_loc = LLVMBuildBitCast(g->builder, frame_result_loc_uncasted, + LLVMPointerType(frame_struct_llvm_ty, 0), ""); } } else { if (instruction->new_stack->value->type->id == ZigTypeIdPointer && instruction->new_stack->value->type->data.pointer.child_type->id == ZigTypeIdFnFrame) { frame_result_loc = ir_llvm_value(g, instruction->new_stack); + frame_struct_llvm_ty = get_llvm_type(g, instruction->new_stack->value->type->data.pointer.child_type); } else { LLVMValueRef frame_slice_ptr = ir_llvm_value(g, instruction->new_stack); LLVMTypeRef frame_slice_llvm_ty = @@ -5063,12 +5069,16 @@ static LLVMValueRef ir_render_call(CodeGen *g, Stage1Air *executable, Stage1AirI LLVMGetGEPSourceElementType(frame_ptr_ptr), frame_ptr_ptr, ""); if (instruction->fn_entry == nullptr) { anyframe_type = get_any_frame_type(g, src_return_type); - frame_result_loc = frame_ptr; + frame_result_loc = LLVMBuildBitCast(g->builder, frame_ptr, get_llvm_type(g, anyframe_type), ""); + frame_struct_llvm_ty = g->any_frame_header_llvm_ty; } else { ZigType *frame_type = get_fn_frame_type(g, instruction->fn_entry); if ((err = type_resolve(g, frame_type, ResolveStatusLLVMFull))) codegen_report_errors_and_exit(g); - frame_result_loc = frame_ptr; + ZigType *ptr_frame_type = get_pointer_to_type(g, frame_type, false); + frame_result_loc = LLVMBuildBitCast(g->builder, frame_ptr, + get_llvm_type(g, ptr_frame_type), ""); + frame_struct_llvm_ty = get_llvm_type(g, frame_type); } } } @@ -5156,6 +5166,12 @@ static LLVMValueRef ir_render_call(CodeGen *g, Stage1Air *executable, Stage1AirI zig_panic("TODO @asyncCall of non-async function"); } frame_result_loc = result_loc; + if (result_loc != nullptr) { + ir_assert(instruction->result_loc->value->type->id == ZigTypeIdPointer, &instruction->base); + frame_struct_llvm_ty = get_llvm_type(g, instruction->result_loc->value->type->data.pointer.child_type); + } else { + frame_struct_llvm_ty = nullptr; + } awaiter_init_val = LLVMConstAllOnes(usize_type_ref); LLVMValueRef awaiter_ptr = LLVMBuildStructGEP2(g->builder, frame_struct_llvm_ty, frame_result_loc, frame_awaiter_index, ""); @@ -5352,11 +5368,13 @@ static LLVMValueRef ir_render_call(CodeGen *g, Stage1Air *executable, Stage1AirI } if (frame_result_loc_uncasted != nullptr) { if (instruction->fn_entry != nullptr) { + frame_struct_llvm_ty = get_llvm_type(g, instruction->fn_entry->frame_type); frame_result_loc = LLVMBuildBitCast(g->builder, frame_result_loc_uncasted, - LLVMPointerType(get_llvm_type(g, instruction->fn_entry->frame_type), 0), ""); + LLVMPointerType(frame_struct_llvm_ty, 0), ""); } else { frame_result_loc = LLVMBuildBitCast(g->builder, frame_result_loc_uncasted, get_llvm_type(g, anyframe_type), ""); + frame_struct_llvm_ty = g->any_frame_header_llvm_ty; } } @@ -5369,7 +5387,7 @@ static LLVMValueRef ir_render_call(CodeGen *g, Stage1Air *executable, Stage1AirI } if (instruction->new_stack == nullptr || instruction->is_async_call_builtin) { - result = ZigLLVMBuildCall(g->builder, LLVMTypeOf(fn_val), fn_val, + result = ZigLLVMBuildCall(g->builder, LLVMGlobalGetValueType(fn_val), fn_val, gen_param_values.items, (unsigned)gen_param_values.length, llvm_cc, call_attr, ""); } else if (instruction->modifier == CallModifierAsync) { zig_panic("TODO @asyncCall of non-async function"); @@ -5380,14 +5398,14 @@ static LLVMValueRef ir_render_call(CodeGen *g, Stage1Air *executable, Stage1AirI LLVMValueRef old_stack_ref; if (src_return_type->id != ZigTypeIdUnreachable) { LLVMValueRef stacksave_fn_val = get_stacksave_fn_val(g); - old_stack_ref = LLVMBuildCall2(g->builder, LLVMTypeOf(stacksave_fn_val), stacksave_fn_val, nullptr, 0, ""); + old_stack_ref = LLVMBuildCall2(g->builder, LLVMGlobalGetValueType(stacksave_fn_val), stacksave_fn_val, nullptr, 0, ""); } gen_set_stack_pointer(g, new_stack_addr); - result = ZigLLVMBuildCall(g->builder, LLVMTypeOf(fn_val), fn_val, + result = ZigLLVMBuildCall(g->builder, LLVMGlobalGetValueType(fn_val), fn_val, gen_param_values.items, (unsigned)gen_param_values.length, llvm_cc, call_attr, ""); if (src_return_type->id != ZigTypeIdUnreachable) { LLVMValueRef stackrestore_fn_val = get_stackrestore_fn_val(g); - LLVMBuildCall2(g->builder, LLVMTypeOf(stackrestore_fn_val), stackrestore_fn_val, &old_stack_ref, 1, ""); + LLVMBuildCall2(g->builder, LLVMGlobalGetValueType(stackrestore_fn_val), stackrestore_fn_val, &old_stack_ref, 1, ""); } } @@ -5735,7 +5753,7 @@ static LLVMValueRef ir_render_asm_gen(CodeGen *g, Stage1Air *executable, Stage1A LLVMValueRef asm_fn = LLVMGetInlineAsm(function_type, buf_ptr(&llvm_template), buf_len(&llvm_template), buf_ptr(&constraint_buf), buf_len(&constraint_buf), is_volatile, false, LLVMInlineAsmDialectATT, false); - LLVMValueRef built_call = LLVMBuildCall2(g->builder, LLVMTypeOf(asm_fn), asm_fn, param_values, (unsigned)input_and_output_count, ""); + LLVMValueRef built_call = LLVMBuildCall2(g->builder, LLVMGlobalGetValueType(asm_fn), asm_fn, param_values, (unsigned)input_and_output_count, ""); for (size_t i = 0; i < input_and_output_count; i += 1) { if (param_needs_attr[i]) { @@ -5895,7 +5913,7 @@ static LLVMValueRef ir_render_clz(CodeGen *g, Stage1Air *executable, Stage1AirIn operand, LLVMConstNull(LLVMInt1Type()), }; - LLVMValueRef wrong_size_int = LLVMBuildCall2(g->builder, LLVMTypeOf(fn_val), fn_val, params, 2, ""); + LLVMValueRef wrong_size_int = LLVMBuildCall2(g->builder, LLVMGlobalGetValueType(fn_val), fn_val, params, 2, ""); return gen_widen_or_shorten(g, false, int_type, instruction->base.value->type, wrong_size_int); } @@ -5907,7 +5925,7 @@ static LLVMValueRef ir_render_ctz(CodeGen *g, Stage1Air *executable, Stage1AirIn operand, LLVMConstNull(LLVMInt1Type()), }; - LLVMValueRef wrong_size_int = LLVMBuildCall2(g->builder, LLVMTypeOf(fn_val), fn_val, params, 2, ""); + LLVMValueRef wrong_size_int = LLVMBuildCall2(g->builder, LLVMGlobalGetValueType(fn_val), fn_val, params, 2, ""); return gen_widen_or_shorten(g, false, int_type, instruction->base.value->type, wrong_size_int); } @@ -5964,7 +5982,7 @@ static LLVMValueRef ir_render_pop_count(CodeGen *g, Stage1Air *executable, Stage ZigType *int_type = instruction->op->value->type; LLVMValueRef fn_val = get_int_builtin_fn(g, int_type, BuiltinFnIdPopCount); LLVMValueRef operand = ir_llvm_value(g, instruction->op); - LLVMValueRef wrong_size_int = LLVMBuildCall2(g->builder, LLVMTypeOf(fn_val), fn_val, &operand, 1, ""); + LLVMValueRef wrong_size_int = LLVMBuildCall2(g->builder, LLVMGlobalGetValueType(fn_val), fn_val, &operand, 1, ""); return gen_widen_or_shorten(g, false, int_type, instruction->base.value->type, wrong_size_int); } @@ -6180,7 +6198,7 @@ static LLVMValueRef ir_render_enum_tag_name(CodeGen *g, Stage1Air *executable, LLVMValueRef enum_name_function = get_enum_tag_name_function(g, enum_type); LLVMValueRef enum_tag_value = ir_llvm_value(g, instruction->target); - return ZigLLVMBuildCall(g->builder, LLVMTypeOf(enum_name_function), enum_name_function, + return ZigLLVMBuildCall(g->builder, LLVMGlobalGetValueType(enum_name_function), enum_name_function, &enum_tag_value, 1, get_llvm_cc(g, CallingConventionUnspecified), ZigLLVM_CallAttrAuto, ""); } @@ -6557,7 +6575,7 @@ static LLVMValueRef ir_render_memcpy(CodeGen *g, Stage1Air *executable, Stage1Ai static LLVMValueRef ir_render_wasm_memory_size(CodeGen *g, Stage1Air *executable, Stage1AirInstWasmMemorySize *instruction) { // TODO adjust for wasm64 LLVMValueRef param = ir_llvm_value(g, instruction->index); - LLVMValueRef val = LLVMBuildCall2(g->builder, LLVMTypeOf(gen_wasm_memory_size(g)), gen_wasm_memory_size(g), ¶m, 1, ""); + LLVMValueRef val = LLVMBuildCall2(g->builder, LLVMGlobalGetValueType(gen_wasm_memory_size(g)), gen_wasm_memory_size(g), ¶m, 1, ""); return val; } @@ -6567,7 +6585,7 @@ static LLVMValueRef ir_render_wasm_memory_grow(CodeGen *g, Stage1Air *executable ir_llvm_value(g, instruction->index), ir_llvm_value(g, instruction->delta), }; - LLVMValueRef val = LLVMBuildCall2(g->builder, LLVMTypeOf(gen_wasm_memory_grow(g)), gen_wasm_memory_grow(g), params, 2, ""); + LLVMValueRef val = LLVMBuildCall2(g->builder, LLVMGlobalGetValueType(gen_wasm_memory_grow(g)), gen_wasm_memory_grow(g), params, 2, ""); return val; } @@ -6613,7 +6631,7 @@ static LLVMValueRef ir_render_prefetch(CodeGen *g, Stage1Air *executable, Stage1 LLVMConstInt(LLVMInt32Type(), instruction->locality, false), LLVMConstInt(LLVMInt32Type(), instruction->cache, false), }; - LLVMValueRef val = LLVMBuildCall2(g->builder, LLVMTypeOf(gen_prefetch(g)), gen_prefetch(g), params, 4, ""); + LLVMValueRef val = LLVMBuildCall2(g->builder, LLVMGlobalGetValueType(gen_prefetch(g)), gen_prefetch(g), params, 4, ""); return val; } @@ -6868,7 +6886,7 @@ static LLVMValueRef get_trap_fn_val(CodeGen *g) { static LLVMValueRef ir_render_breakpoint(CodeGen *g, Stage1Air *executable, Stage1AirInstBreakpoint *instruction) { - LLVMBuildCall2(g->builder, LLVMTypeOf(get_trap_fn_val(g)), get_trap_fn_val(g), nullptr, 0, ""); + LLVMBuildCall2(g->builder, LLVMGlobalGetValueType(get_trap_fn_val(g)), get_trap_fn_val(g), nullptr, 0, ""); return nullptr; } @@ -6882,7 +6900,7 @@ static LLVMValueRef ir_render_return_address(CodeGen *g, Stage1Air *executable, } LLVMValueRef zero = LLVMConstNull(g->builtin_types.entry_i32->llvm_type); - LLVMValueRef ptr_val = LLVMBuildCall2(g->builder, LLVMTypeOf(get_return_address_fn_val(g)), get_return_address_fn_val(g), &zero, 1, ""); + LLVMValueRef ptr_val = LLVMBuildCall2(g->builder, LLVMGlobalGetValueType(get_return_address_fn_val(g)), get_return_address_fn_val(g), &zero, 1, ""); return LLVMBuildPtrToInt(g->builder, ptr_val, g->builtin_types.entry_usize->llvm_type, ""); } @@ -6904,7 +6922,7 @@ static LLVMValueRef ir_render_frame_address(CodeGen *g, Stage1Air *executable, Stage1AirInstFrameAddress *instruction) { LLVMValueRef zero = LLVMConstNull(g->builtin_types.entry_i32->llvm_type); - LLVMValueRef ptr_val = LLVMBuildCall2(g->builder, LLVMTypeOf(get_frame_address_fn_val(g)), get_frame_address_fn_val(g), &zero, 1, ""); + LLVMValueRef ptr_val = LLVMBuildCall2(g->builder, LLVMGlobalGetValueType(get_frame_address_fn_val(g)), get_frame_address_fn_val(g), &zero, 1, ""); return LLVMBuildPtrToInt(g->builder, ptr_val, g->builtin_types.entry_usize->llvm_type, ""); } @@ -6967,7 +6985,7 @@ static LLVMValueRef ir_render_overflow_op(CodeGen *g, Stage1Air *executable, Sta op2, }; - LLVMValueRef result_struct = LLVMBuildCall2(g->builder, LLVMTypeOf(fn_val), fn_val, params, 2, ""); + LLVMValueRef result_struct = LLVMBuildCall2(g->builder, LLVMGlobalGetValueType(fn_val), fn_val, params, 2, ""); LLVMValueRef result = LLVMBuildExtractValue(g->builder, result_struct, 0, ""); LLVMValueRef overflow_bit = LLVMBuildExtractValue(g->builder, result_struct, 1, ""); gen_store(g, result, ptr_result, instruction->result_ptr->value->type); @@ -7339,7 +7357,7 @@ static LLVMValueRef ir_render_soft_mul_add(CodeGen *g, Stage1Air *executable, St LLVMValueRef op3 = ir_llvm_value(g, instruction->op3); if (vector_len == 0) { LLVMValueRef params[3] = { op1, op2, op3 }; - return LLVMBuildCall2(g->builder, LLVMTypeOf(func_ref), func_ref, params, 3, ""); + return LLVMBuildCall2(g->builder, LLVMGlobalGetValueType(func_ref), func_ref, params, 3, ""); } LLVMValueRef result = LLVMGetUndef(get_llvm_type(g, instruction->op1->value->type)); @@ -7352,7 +7370,7 @@ static LLVMValueRef ir_render_soft_mul_add(CodeGen *g, Stage1Air *executable, St LLVMBuildExtractElement(g->builder, op2, index_value, ""), LLVMBuildExtractElement(g->builder, op3, index_value, ""), }; - LLVMValueRef call_result = LLVMBuildCall2(g->builder, LLVMTypeOf(func_ref), func_ref, params, 3, ""); + LLVMValueRef call_result = LLVMBuildCall2(g->builder, LLVMGlobalGetValueType(func_ref), func_ref, params, 3, ""); result = LLVMBuildInsertElement(g->builder, result, call_result, index_value, ""); } return result; @@ -7372,7 +7390,7 @@ static LLVMValueRef ir_render_mul_add(CodeGen *g, Stage1Air *executable, Stage1A instruction->base.value->type->id == ZigTypeIdVector); LLVMValueRef fn_val = get_float_fn(g, instruction->base.value->type, ZigLLVMFnIdFMA, BuiltinFnIdMulAdd); LLVMValueRef args[3] = { op1, op2, op3 }; - return LLVMBuildCall2(g->builder, LLVMTypeOf(fn_val), fn_val, args, 3, ""); + return LLVMBuildCall2(g->builder, LLVMGlobalGetValueType(fn_val), fn_val, args, 3, ""); } static LLVMValueRef ir_render_bswap(CodeGen *g, Stage1Air *executable, Stage1AirInstBswap *instruction) { @@ -7383,7 +7401,7 @@ static LLVMValueRef ir_render_bswap(CodeGen *g, Stage1Air *executable, Stage1Air assert(int_type->id == ZigTypeIdInt); if (int_type->data.integral.bit_count % 16 == 0) { LLVMValueRef fn_val = get_int_builtin_fn(g, expr_type, BuiltinFnIdBswap); - return LLVMBuildCall2(g->builder, LLVMTypeOf(fn_val), fn_val, &op, 1, ""); + return LLVMBuildCall2(g->builder, LLVMGlobalGetValueType(fn_val), fn_val, &op, 1, ""); } // Not an even number of bytes, so we zext 1 byte, then bswap, shift right 1 byte, truncate ZigType *extended_type = get_int_type(g, int_type->data.integral.is_signed, @@ -7402,7 +7420,7 @@ static LLVMValueRef ir_render_bswap(CodeGen *g, Stage1Air *executable, Stage1Air LLVMValueRef extended = LLVMBuildZExt(g->builder, op, get_llvm_type(g, extended_type), ""); // 00aabbcc LLVMValueRef fn_val = get_int_builtin_fn(g, extended_type, BuiltinFnIdBswap); - LLVMValueRef swapped = LLVMBuildCall2(g->builder, LLVMTypeOf(fn_val), fn_val, &extended, 1, ""); + LLVMValueRef swapped = LLVMBuildCall2(g->builder, LLVMGlobalGetValueType(fn_val), fn_val, &extended, 1, ""); // ccbbaa00 LLVMValueRef shifted = ZigLLVMBuildLShrExact(g->builder, swapped, shift_amt, ""); // 00ccbbaa @@ -7438,7 +7456,7 @@ static LLVMValueRef ir_render_bit_reverse(CodeGen *g, Stage1Air *executable, Sta ZigType *int_type = instruction->base.value->type; assert(int_type->id == ZigTypeIdInt); LLVMValueRef fn_val = get_int_builtin_fn(g, instruction->base.value->type, BuiltinFnIdBitReverse); - return LLVMBuildCall2(g->builder, LLVMTypeOf(fn_val), fn_val, &op, 1, ""); + return LLVMBuildCall2(g->builder, LLVMGlobalGetValueType(fn_val), fn_val, &op, 1, ""); } static LLVMValueRef ir_render_vector_to_array(CodeGen *g, Stage1Air *executable, @@ -7603,7 +7621,7 @@ static LLVMValueRef gen_await_early_return(CodeGen *g, Stage1AirInst *source_ins bool is_llvm_alloca; LLVMValueRef dest_trace_ptr = get_cur_err_ret_trace_val(g, source_instr->scope, &is_llvm_alloca); LLVMValueRef args[] = { dest_trace_ptr, src_trace_ptr }; - ZigLLVMBuildCall(g->builder, LLVMTypeOf(get_merge_err_ret_traces_fn_val(g)), + ZigLLVMBuildCall(g->builder, LLVMGlobalGetValueType(get_merge_err_ret_traces_fn_val(g)), get_merge_err_ret_traces_fn_val(g), args, 2, get_llvm_cc(g, CallingConventionUnspecified), ZigLLVM_CallAttrAuto, ""); } @@ -9337,7 +9355,7 @@ static void do_code_gen(CodeGen *g) { LLVMValueRef zero = LLVMConstNull(usize->llvm_type); LLVMValueRef indices[] = {zero, zero}; LLVMValueRef err_ret_array_val_elem0_ptr = LLVMBuildInBoundsGEP2(g->builder, - usize_type_ref, err_ret_array_val, indices, 2, ""); + LLVMGetAllocatedType(err_ret_array_val), err_ret_array_val, indices, 2, ""); ZigType *ptr_ptr_usize_type = get_pointer_to_type(g, get_pointer_to_type(g, usize, false), false); gen_store(g, err_ret_array_val_elem0_ptr, ptr_field_ptr, ptr_ptr_usize_type); -- cgit v1.2.3 From 44f833129c81bfa7117743fc7d54c44db09cc240 Mon Sep 17 00:00:00 2001 From: Andrew Kelley Date: Mon, 1 Aug 2022 23:26:36 -0700 Subject: LLVM backends: work around poorly designed C API As part of the Opaque Pointers upgrade documentation, LLVM says that the function LLVMGetGEPSourceElementType() can be used to obtain element type information in lieu of LLVMGetElementType(), however, this function actually returns the struct type, not the field type. The GEP instruction does store the information we need, however, this is not exposed in the C API. It seems like they accidentally exposed the wrong field, because one would never need the struct type since one must already pass it directly to the GEP instruction, so one will always have it handy, whereas one will usually not have the field type handy. --- src/codegen/llvm.zig | 8 ++--- src/codegen/llvm/bindings.zig | 4 +-- src/stage1/codegen.cpp | 83 +++++++++++++++++++++---------------------- src/zig_llvm.cpp | 4 +++ src/zig_llvm.h | 2 ++ 5 files changed, 52 insertions(+), 49 deletions(-) (limited to 'src/codegen/llvm.zig') diff --git a/src/codegen/llvm.zig b/src/codegen/llvm.zig index ece704a04c..a1000a8945 100644 --- a/src/codegen/llvm.zig +++ b/src/codegen/llvm.zig @@ -4901,7 +4901,7 @@ pub const FuncGen = struct { if (isByRef(payload_ty)) { return payload_ptr; } - const load_inst = fg.builder.buildLoad(payload_ptr.getGEPSourceElementType(), payload_ptr, ""); + const load_inst = fg.builder.buildLoad(payload_ptr.getGEPResultElementType(), payload_ptr, ""); load_inst.setAlignment(payload_ty.abiAlignment(target)); return load_inst; } @@ -6043,7 +6043,7 @@ pub const FuncGen = struct { if (isByRef(payload_ty)) { return payload_ptr; } - const load_inst = self.builder.buildLoad(payload_ptr.getGEPSourceElementType(), payload_ptr, ""); + const load_inst = self.builder.buildLoad(payload_ptr.getGEPResultElementType(), payload_ptr, ""); load_inst.setAlignment(payload_ty.abiAlignment(target)); return load_inst; } @@ -7820,7 +7820,7 @@ pub const FuncGen = struct { } const tag_index = @boolToInt(layout.tag_align < layout.payload_align); const tag_field_ptr = self.builder.buildStructGEP(llvm_un_ty, union_handle, tag_index, ""); - return self.builder.buildLoad(tag_field_ptr.getGEPSourceElementType(), tag_field_ptr, ""); + return self.builder.buildLoad(tag_field_ptr.getGEPResultElementType(), tag_field_ptr, ""); } else { if (layout.payload_size == 0) { return union_handle; @@ -8671,7 +8671,7 @@ pub const FuncGen = struct { } const target = fg.dg.module.getTarget(); const payload_alignment = payload_ty.abiAlignment(target); - const load_inst = fg.builder.buildLoad(payload_ptr.getGEPSourceElementType(), payload_ptr, ""); + const load_inst = fg.builder.buildLoad(payload_ptr.getGEPResultElementType(), payload_ptr, ""); load_inst.setAlignment(payload_alignment); return load_inst; } diff --git a/src/codegen/llvm/bindings.zig b/src/codegen/llvm/bindings.zig index 9c337cc287..4090054800 100644 --- a/src/codegen/llvm/bindings.zig +++ b/src/codegen/llvm/bindings.zig @@ -242,8 +242,8 @@ pub const Value = opaque { pub const addFunctionAttr = ZigLLVMAddFunctionAttr; extern fn ZigLLVMAddFunctionAttr(Fn: *const Value, attr_name: [*:0]const u8, attr_value: [*:0]const u8) void; - pub const getGEPSourceElementType = LLVMGetGEPSourceElementType; - extern fn LLVMGetGEPSourceElementType(GEP: *const Value) *const Type; + pub const getGEPResultElementType = ZigLLVMGetGEPResultElementType; + extern fn ZigLLVMGetGEPResultElementType(GEP: *const Value) *const Type; }; pub const Type = opaque { diff --git a/src/stage1/codegen.cpp b/src/stage1/codegen.cpp index 88c7db2ec8..423e9b7085 100644 --- a/src/stage1/codegen.cpp +++ b/src/stage1/codegen.cpp @@ -1276,16 +1276,16 @@ static LLVMValueRef get_add_error_return_trace_addr_fn(CodeGen *g) { ZigType *slice_type = g->stack_trace_type->data.structure.fields[1]->type_entry; size_t ptr_field_index = slice_type->data.structure.fields[slice_ptr_index]->gen_index; LLVMValueRef ptr_field_ptr = LLVMBuildStructGEP2(g->builder, - LLVMGetGEPSourceElementType(addresses_field_ptr), + ZigLLVMGetGEPResultElementType(addresses_field_ptr), addresses_field_ptr, (unsigned)ptr_field_index, ""); size_t len_field_index = slice_type->data.structure.fields[slice_len_index]->gen_index; LLVMValueRef len_field_ptr = LLVMBuildStructGEP2(g->builder, - LLVMGetGEPSourceElementType(addresses_field_ptr), + ZigLLVMGetGEPResultElementType(addresses_field_ptr), addresses_field_ptr, (unsigned)len_field_index, ""); - LLVMValueRef len_value = gen_load_untyped(g, LLVMGetGEPSourceElementType(len_field_ptr), + LLVMValueRef len_value = gen_load_untyped(g, ZigLLVMGetGEPResultElementType(len_field_ptr), len_field_ptr, 0, false, ""); - LLVMValueRef index_val = gen_load_untyped(g, LLVMGetGEPSourceElementType(index_field_ptr), + LLVMValueRef index_val = gen_load_untyped(g, ZigLLVMGetGEPResultElementType(index_field_ptr), index_field_ptr, 0, false, ""); LLVMValueRef len_val_minus_one = LLVMBuildSub(g->builder, len_value, LLVMConstInt(usize_type_ref, 1, false), ""); LLVMValueRef masked_val = LLVMBuildAnd(g->builder, index_val, len_val_minus_one, ""); @@ -1293,7 +1293,7 @@ static LLVMValueRef get_add_error_return_trace_addr_fn(CodeGen *g) { masked_val, }; - LLVMValueRef ptr_value = gen_load_untyped(g, LLVMGetGEPSourceElementType(ptr_field_ptr), + LLVMValueRef ptr_value = gen_load_untyped(g, ZigLLVMGetGEPResultElementType(ptr_field_ptr), ptr_field_ptr, 0, false, ""); LLVMValueRef address_slot = LLVMBuildInBoundsGEP2(g->builder, usize_type_ref, ptr_value, address_indices, 1, ""); @@ -1455,22 +1455,19 @@ static LLVMValueRef get_safety_crash_err_fn(CodeGen *g) { } // Fetch the error name from the global table - LLVMValueRef err_table_indices[] = { - LLVMConstNull(usize_ty->llvm_type), - err_val, - }; + LLVMValueRef err_table_indices[] = { err_val }; LLVMValueRef err_name_val = LLVMBuildInBoundsGEP2(g->builder, get_llvm_type(g, str_type), g->err_name_table, err_table_indices, 2, ""); LLVMValueRef ptr_field_ptr = LLVMBuildStructGEP2(g->builder, - LLVMGetGEPSourceElementType(err_name_val), err_name_val, slice_ptr_index, ""); - LLVMValueRef err_name_ptr = gen_load_untyped(g, LLVMGetGEPSourceElementType(ptr_field_ptr), + ZigLLVMGetGEPResultElementType(err_name_val), err_name_val, slice_ptr_index, ""); + LLVMValueRef err_name_ptr = gen_load_untyped(g, ZigLLVMGetGEPResultElementType(ptr_field_ptr), ptr_field_ptr, 0, false, ""); LLVMValueRef len_field_ptr = LLVMBuildStructGEP2(g->builder, - LLVMGetGEPSourceElementType(err_name_val), err_name_val, slice_len_index, ""); - LLVMValueRef err_name_len = gen_load_untyped(g, LLVMGetGEPSourceElementType(len_field_ptr), + ZigLLVMGetGEPResultElementType(err_name_val), err_name_val, slice_len_index, ""); + LLVMValueRef err_name_len = gen_load_untyped(g, ZigLLVMGetGEPResultElementType(len_field_ptr), len_field_ptr, 0, false, ""); LLVMValueRef msg_prefix_len = LLVMConstInt(usize_ty->llvm_type, strlen(unwrap_err_msg_text), false); @@ -2374,7 +2371,7 @@ static bool iter_function_params_c_abi(CodeGen *g, ZigType *fn_type, FnWalk *fn_ LLVMValueRef adjusted_ptr_to_struct = LLVMBuildStructGEP2(g->builder, abi_type, val, i, ""); LLVMValueRef loaded = LLVMBuildLoad2(g->builder, - LLVMGetGEPSourceElementType(adjusted_ptr_to_struct), + ZigLLVMGetGEPResultElementType(adjusted_ptr_to_struct), adjusted_ptr_to_struct, ""); fn_walk->data.call.gen_param_values->append(loaded); } @@ -2621,18 +2618,18 @@ static LLVMValueRef get_merge_err_ret_traces_fn_val(CodeGen *g) { ZigType *slice_type = g->stack_trace_type->data.structure.fields[1]->type_entry; size_t ptr_field_index = slice_type->data.structure.fields[slice_ptr_index]->gen_index; LLVMValueRef src_ptr_field_ptr = LLVMBuildStructGEP2(g->builder, - LLVMGetGEPSourceElementType(src_addresses_field_ptr), + ZigLLVMGetGEPResultElementType(src_addresses_field_ptr), src_addresses_field_ptr, (unsigned)ptr_field_index, ""); size_t len_field_index = slice_type->data.structure.fields[slice_len_index]->gen_index; LLVMValueRef src_len_field_ptr = LLVMBuildStructGEP2(g->builder, - LLVMGetGEPSourceElementType(src_addresses_field_ptr), + ZigLLVMGetGEPResultElementType(src_addresses_field_ptr), src_addresses_field_ptr, (unsigned)len_field_index, ""); LLVMValueRef src_index_val = LLVMBuildLoad2(g->builder, - LLVMGetGEPSourceElementType(src_index_field_ptr), src_index_field_ptr, ""); + ZigLLVMGetGEPResultElementType(src_index_field_ptr), src_index_field_ptr, ""); LLVMValueRef src_ptr_val = LLVMBuildLoad2(g->builder, - LLVMGetGEPSourceElementType(src_ptr_field_ptr), src_ptr_field_ptr, ""); + ZigLLVMGetGEPResultElementType(src_ptr_field_ptr), src_ptr_field_ptr, ""); LLVMValueRef src_len_val = LLVMBuildLoad2(g->builder, - LLVMGetGEPSourceElementType(src_len_field_ptr), src_len_field_ptr, ""); + ZigLLVMGetGEPResultElementType(src_len_field_ptr), src_len_field_ptr, ""); LLVMValueRef no_wrap_bit = LLVMBuildICmp(g->builder, LLVMIntULT, src_index_val, src_len_val, ""); LLVMBasicBlockRef no_wrap_block = LLVMAppendBasicBlock(fn_val, "NoWrap"); LLVMBasicBlockRef yes_wrap_block = LLVMAppendBasicBlock(fn_val, "YesWrap"); @@ -2658,7 +2655,7 @@ static LLVMValueRef get_merge_err_ret_traces_fn_val(CodeGen *g) { LLVMValueRef ptr_index = LLVMBuildLoad2(g->builder, usize_type_ref, frame_index_ptr, ""); LLVMValueRef addr_ptr = LLVMBuildInBoundsGEP2(g->builder, usize_type_ref, src_ptr_val, &ptr_index, 1, ""); - LLVMValueRef this_addr_val = LLVMBuildLoad2(g->builder, LLVMGetGEPSourceElementType(addr_ptr), + LLVMValueRef this_addr_val = LLVMBuildLoad2(g->builder, ZigLLVMGetGEPResultElementType(addr_ptr), addr_ptr, ""); LLVMValueRef args[] = {dest_stack_trace_ptr, this_addr_val}; ZigLLVMBuildCall(g->builder, LLVMGlobalGetValueType(add_error_return_trace_addr_fn_val), @@ -4793,7 +4790,7 @@ static LLVMValueRef ir_render_elem_ptr(CodeGen *g, Stage1Air *executable, Stage1 assert(len_index != SIZE_MAX); LLVMValueRef len_ptr = LLVMBuildStructGEP2(g->builder, get_llvm_type(g, array_type), array_ptr, (unsigned)len_index, ""); - LLVMValueRef len = gen_load_untyped(g, LLVMGetGEPSourceElementType(len_ptr), len_ptr, + LLVMValueRef len = gen_load_untyped(g, ZigLLVMGetGEPResultElementType(len_ptr), len_ptr, 0, false, ""); LLVMIntPredicate upper_op = (ptr_type->data.pointer.sentinel != nullptr) ? LLVMIntULE : LLVMIntULT; add_bounds_check(g, subscript_value, LLVMIntEQ, nullptr, upper_op, len); @@ -4803,7 +4800,7 @@ static LLVMValueRef ir_render_elem_ptr(CodeGen *g, Stage1Air *executable, Stage1 assert(ptr_index != SIZE_MAX); LLVMValueRef ptr_ptr = LLVMBuildStructGEP2(g->builder, get_llvm_type(g, array_type), array_ptr, (unsigned)ptr_index, ""); - LLVMValueRef ptr = gen_load_untyped(g, LLVMGetGEPSourceElementType(ptr_ptr), ptr_ptr, 0, + LLVMValueRef ptr = gen_load_untyped(g, ZigLLVMGetGEPResultElementType(ptr_ptr), ptr_ptr, 0, false, ""); LLVMTypeRef elem_llvm_ty = get_llvm_type(g, ptr_type->data.pointer.child_type); return LLVMBuildInBoundsGEP2(g->builder, elem_llvm_ty, ptr, &subscript_value, 1, ""); @@ -4820,9 +4817,9 @@ static LLVMValueRef get_new_stack_addr(CodeGen *g, LLVMTypeRef new_stack_llvm_ty LLVMValueRef ptr_field_ptr = LLVMBuildStructGEP2(g->builder, new_stack_llvm_ty, new_stack, (unsigned)slice_ptr_index, ""); LLVMValueRef len_field_ptr = LLVMBuildStructGEP2(g->builder, new_stack_llvm_ty, new_stack, (unsigned)slice_len_index, ""); - LLVMValueRef ptr_value = gen_load_untyped(g, LLVMGetGEPSourceElementType(ptr_field_ptr), + LLVMValueRef ptr_value = gen_load_untyped(g, ZigLLVMGetGEPResultElementType(ptr_field_ptr), ptr_field_ptr, 0, false, ""); - LLVMValueRef len_value = gen_load_untyped(g, LLVMGetGEPSourceElementType(len_field_ptr), + LLVMValueRef len_value = gen_load_untyped(g, ZigLLVMGetGEPResultElementType(len_field_ptr), len_field_ptr, 0, false, ""); LLVMValueRef ptr_addr = LLVMBuildPtrToInt(g->builder, ptr_value, LLVMTypeOf(len_value), ""); @@ -4962,7 +4959,7 @@ static void gen_init_stack_trace(CodeGen *g, LLVMValueRef trace_field_ptr, LLVMV LLVMValueRef addrs_slice_ptr = LLVMBuildStructGEP2(g->builder, stack_trace_llvm_ty, trace_field_ptr, 1, ""); LLVMValueRef addrs_ptr_ptr = LLVMBuildStructGEP2(g->builder, - LLVMGetGEPSourceElementType(addrs_slice_ptr), + ZigLLVMGetGEPResultElementType(addrs_slice_ptr), addrs_slice_ptr, slice_ptr_index, ""); LLVMValueRef indices[] = { LLVMConstNull(usize_type_ref), LLVMConstNull(usize_type_ref) }; LLVMValueRef trace_field_addrs_as_ptr = LLVMBuildInBoundsGEP2(g->builder, @@ -4970,7 +4967,7 @@ static void gen_init_stack_trace(CodeGen *g, LLVMValueRef trace_field_ptr, LLVMV LLVMBuildStore(g->builder, trace_field_addrs_as_ptr, addrs_ptr_ptr); LLVMValueRef addrs_len_ptr = LLVMBuildStructGEP2(g->builder, - LLVMGetGEPSourceElementType(addrs_slice_ptr), + ZigLLVMGetGEPResultElementType(addrs_slice_ptr), addrs_slice_ptr, slice_len_index, ""); LLVMBuildStore(g->builder, LLVMConstInt(usize_type_ref, stack_trace_ptr_count, false), addrs_len_ptr); } @@ -5064,7 +5061,7 @@ static LLVMValueRef ir_render_call(CodeGen *g, Stage1Air *executable, Stage1AirI LLVMValueRef frame_ptr_ptr = LLVMBuildStructGEP2(g->builder, frame_slice_llvm_ty, frame_slice_ptr, slice_ptr_index, ""); LLVMValueRef frame_ptr = LLVMBuildLoad2(g->builder, - LLVMGetGEPSourceElementType(frame_ptr_ptr), frame_ptr_ptr, ""); + ZigLLVMGetGEPResultElementType(frame_ptr_ptr), frame_ptr_ptr, ""); if (instruction->fn_entry == nullptr) { anyframe_type = get_any_frame_type(g, src_return_type); frame_result_loc = LLVMBuildBitCast(g->builder, frame_ptr, get_llvm_type(g, anyframe_type), ""); @@ -5127,7 +5124,7 @@ static LLVMValueRef ir_render_call(CodeGen *g, Stage1Air *executable, Stage1AirI // Store a zero in the awaiter's result ptr to indicate we do not need a copy made. LLVMValueRef awaiter_ret_ptr = LLVMBuildStructGEP2(g->builder, frame_struct_llvm_ty, frame_result_loc, frame_ret_start + 1, ""); - LLVMValueRef zero_ptr = LLVMConstNull(LLVMGetGEPSourceElementType(awaiter_ret_ptr)); + LLVMValueRef zero_ptr = LLVMConstNull(ZigLLVMGetGEPResultElementType(awaiter_ret_ptr)); LLVMBuildStore(g->builder, zero_ptr, awaiter_ret_ptr); } @@ -5145,7 +5142,7 @@ static LLVMValueRef ir_render_call(CodeGen *g, Stage1Air *executable, Stage1AirI LLVMValueRef fn_ptr_ptr = LLVMBuildStructGEP2(g->builder, frame_struct_llvm_ty, frame_result_loc, frame_fn_ptr_index, ""); LLVMValueRef bitcasted_fn_val = LLVMBuildBitCast(g->builder, fn_val, - LLVMGetGEPSourceElementType(fn_ptr_ptr), ""); + ZigLLVMGetGEPResultElementType(fn_ptr_ptr), ""); LLVMBuildStore(g->builder, bitcasted_fn_val, fn_ptr_ptr); LLVMValueRef resume_index_ptr = LLVMBuildStructGEP2(g->builder, frame_struct_llvm_ty, frame_result_loc, frame_resume_index, ""); @@ -5362,7 +5359,7 @@ static LLVMValueRef ir_render_call(CodeGen *g, Stage1Air *executable, Stage1AirI get_llvm_type(g, instruction->new_stack->value->type->data.pointer.child_type), frame_slice_ptr, slice_ptr_index, ""); frame_result_loc_uncasted = LLVMBuildLoad2(g->builder, - LLVMGetGEPSourceElementType(frame_ptr_ptr), frame_ptr_ptr, ""); + ZigLLVMGetGEPResultElementType(frame_ptr_ptr), frame_ptr_ptr, ""); } if (frame_result_loc_uncasted != nullptr) { if (instruction->fn_entry != nullptr) { @@ -5551,7 +5548,7 @@ static LLVMValueRef ir_render_union_field_ptr(CodeGen *g, Stage1Air *executable, LLVMValueRef tag_field_ptr = LLVMBuildStructGEP2(g->builder, get_llvm_type(g, union_type), union_ptr, union_type->data.unionation.gen_tag_index, ""); - LLVMValueRef tag_value = gen_load_untyped(g, LLVMGetGEPSourceElementType(tag_field_ptr), + LLVMValueRef tag_value = gen_load_untyped(g, ZigLLVMGetGEPResultElementType(tag_field_ptr), tag_field_ptr, 0, false, ""); @@ -5787,7 +5784,7 @@ static LLVMValueRef gen_non_null_bit(CodeGen *g, ZigType *maybe_type, LLVMValueR LLVMValueRef maybe_field_ptr = LLVMBuildStructGEP2(g->builder, get_llvm_type(g, maybe_type), maybe_handle, maybe_null_index, ""); - return gen_load_untyped(g, LLVMGetGEPSourceElementType(maybe_field_ptr), maybe_field_ptr, 0, false, ""); + return gen_load_untyped(g, ZigLLVMGetGEPResultElementType(maybe_field_ptr), maybe_field_ptr, 0, false, ""); } static LLVMValueRef ir_render_test_non_null(CodeGen *g, Stage1Air *executable, @@ -6272,7 +6269,7 @@ static LLVMValueRef ir_render_align_cast(CodeGen *g, Stage1Air *executable, Stag LLVMValueRef ptr_val_ptr = LLVMBuildStructGEP2(g->builder, get_llvm_type(g, instruction->target->value->type->data.pointer.child_type), target_val, (unsigned)ptr_index, ""); - ptr_val = gen_load_untyped(g, LLVMGetGEPSourceElementType(ptr_val_ptr), ptr_val_ptr, 0, false, ""); + ptr_val = gen_load_untyped(g, ZigLLVMGetGEPResultElementType(ptr_val_ptr), ptr_val_ptr, 0, false, ""); } else { zig_unreachable(); } @@ -6759,7 +6756,7 @@ static LLVMValueRef ir_render_slice(CodeGen *g, Stage1Air *executable, Stage1Air if (!instruction->end || want_runtime_safety) { LLVMValueRef src_len_ptr = LLVMBuildStructGEP2(g->builder, get_llvm_type(g, array_type), array_ptr, gen_len_index, ""); - prev_end = gen_load_untyped(g, LLVMGetGEPSourceElementType(src_len_ptr), src_len_ptr, 0, false, ""); + prev_end = gen_load_untyped(g, ZigLLVMGetGEPResultElementType(src_len_ptr), src_len_ptr, 0, false, ""); } LLVMValueRef start_val = ir_llvm_value(g, instruction->start); @@ -6804,7 +6801,7 @@ static LLVMValueRef ir_render_slice(CodeGen *g, Stage1Air *executable, Stage1Air LLVMValueRef src_ptr_ptr = LLVMBuildStructGEP2(g->builder, get_llvm_type(g, array_type), array_ptr, gen_ptr_index, ""); - LLVMValueRef src_ptr = gen_load_untyped(g, LLVMGetGEPSourceElementType(src_ptr_ptr), + LLVMValueRef src_ptr = gen_load_untyped(g, ZigLLVMGetGEPResultElementType(src_ptr_ptr), src_ptr_ptr, 0, false, ""); if (sentinel != nullptr) { @@ -7005,7 +7002,7 @@ static LLVMValueRef ir_render_test_err(CodeGen *g, Stage1Air *executable, Stage1 if (type_has_bits(g, payload_type)) { LLVMValueRef err_val_ptr = LLVMBuildStructGEP2(g->builder, get_llvm_type(g, err_union_type), err_union_handle, err_union_err_index, ""); - err_val = gen_load_untyped(g, LLVMGetGEPSourceElementType(err_val_ptr), err_val_ptr, 0, false, ""); + err_val = gen_load_untyped(g, ZigLLVMGetGEPResultElementType(err_val_ptr), err_val_ptr, 0, false, ""); } else { err_val = err_union_handle; } @@ -7077,7 +7074,7 @@ static LLVMValueRef ir_render_unwrap_err_payload(CodeGen *g, Stage1Air *executab if (type_has_bits(g, payload_type)) { LLVMValueRef err_val_ptr = LLVMBuildStructGEP2(g->builder, err_union_llvm_ty, err_union_handle, err_union_err_index, ""); - err_val = gen_load_untyped(g, LLVMGetGEPSourceElementType(err_val_ptr), err_val_ptr, 0, false, ""); + err_val = gen_load_untyped(g, ZigLLVMGetGEPResultElementType(err_val_ptr), err_val_ptr, 0, false, ""); } else { err_val = err_union_handle; } @@ -7602,7 +7599,7 @@ static LLVMValueRef gen_await_early_return(CodeGen *g, Stage1AirInst *source_ins LLVMValueRef their_result_ptr_ptr = LLVMBuildStructGEP2(g->builder, target_frame_struct_llvm_ty, target_frame_ptr, frame_ret_start, ""); their_result_ptr = LLVMBuildLoad2(g->builder, - LLVMGetGEPSourceElementType(their_result_ptr_ptr), their_result_ptr_ptr, ""); + ZigLLVMGetGEPResultElementType(their_result_ptr_ptr), their_result_ptr_ptr, ""); if (result_loc != nullptr) { LLVMTypeRef ptr_u8 = LLVMPointerType(LLVMInt8Type(), 0); LLVMValueRef dest_ptr_casted = LLVMBuildBitCast(g->builder, result_loc, ptr_u8, ""); @@ -7620,7 +7617,7 @@ static LLVMValueRef gen_await_early_return(CodeGen *g, Stage1AirInst *source_ins target_frame_struct_llvm_ty, target_frame_ptr, frame_index_trace_arg(g, result_type), ""); LLVMValueRef src_trace_ptr = LLVMBuildLoad2(g->builder, - LLVMGetGEPSourceElementType(their_trace_ptr_ptr), their_trace_ptr_ptr, ""); + ZigLLVMGetGEPResultElementType(their_trace_ptr_ptr), their_trace_ptr_ptr, ""); bool is_llvm_alloca; LLVMValueRef dest_trace_ptr = get_cur_err_ret_trace_val(g, source_instr->scope, &is_llvm_alloca); LLVMValueRef args[] = { dest_trace_ptr, src_trace_ptr }; @@ -7668,7 +7665,7 @@ static LLVMValueRef ir_render_await(CodeGen *g, Stage1Air *executable, Stage1Air target_frame_ptr, frame_ret_start + 1, ""); if (result_loc == nullptr) { // no copy needed - LLVMBuildStore(g->builder, LLVMConstNull(LLVMGetGEPSourceElementType(awaiter_ret_ptr_ptr)), + LLVMBuildStore(g->builder, LLVMConstNull(ZigLLVMGetGEPResultElementType(awaiter_ret_ptr_ptr)), awaiter_ret_ptr_ptr); } else { LLVMBuildStore(g->builder, result_loc, awaiter_ret_ptr_ptr); @@ -9353,7 +9350,7 @@ static void do_code_gen(CodeGen *g) { ZigType *slice_type = g->stack_trace_type->data.structure.fields[1]->type_entry; size_t ptr_field_index = slice_type->data.structure.fields[slice_ptr_index]->gen_index; LLVMValueRef ptr_field_ptr = LLVMBuildStructGEP2(g->builder, - LLVMGetGEPSourceElementType(addresses_field_ptr), + ZigLLVMGetGEPResultElementType(addresses_field_ptr), addresses_field_ptr, (unsigned)ptr_field_index, ""); LLVMValueRef zero = LLVMConstNull(usize->llvm_type); LLVMValueRef indices[] = {zero, zero}; @@ -9364,7 +9361,7 @@ static void do_code_gen(CodeGen *g) { size_t len_field_index = slice_type->data.structure.fields[slice_len_index]->gen_index; LLVMValueRef len_field_ptr = LLVMBuildStructGEP2(g->builder, - LLVMGetGEPSourceElementType(addresses_field_ptr), + ZigLLVMGetGEPResultElementType(addresses_field_ptr), addresses_field_ptr, (unsigned)len_field_index, ""); gen_store(g, LLVMConstInt(usize->llvm_type, stack_trace_ptr_count, false), len_field_ptr, get_pointer_to_type(g, usize, false)); } @@ -9443,7 +9440,7 @@ static void do_code_gen(CodeGen *g) { get_llvm_type(g, get_fn_frame_type(g, g->cur_fn)), g->cur_frame_ptr, frame_index_trace_arg(g, fn_type_id->return_type), ""); - LLVMValueRef zero_ptr = LLVMConstNull(LLVMGetGEPSourceElementType(trace_ptr_ptr)); + LLVMValueRef zero_ptr = LLVMConstNull(ZigLLVMGetGEPResultElementType(trace_ptr_ptr)); LLVMBuildStore(g->builder, zero_ptr, trace_ptr_ptr); } diff --git a/src/zig_llvm.cpp b/src/zig_llvm.cpp index a1b0f6a30c..4f9cd76c6a 100644 --- a/src/zig_llvm.cpp +++ b/src/zig_llvm.cpp @@ -1195,6 +1195,10 @@ void ZigLLVMSetCallElemTypeAttr(LLVMValueRef Call, size_t arg_index, LLVMTypeRef Attribute::get(call_inst->getContext(), Attribute::ElementType, llvm_type)); } +LLVMTypeRef ZigLLVMGetGEPResultElementType(LLVMValueRef GEP) { + return wrap(unwrap(GEP)->getResultElementType()); +} + void ZigLLVMFunctionSetPrefixData(LLVMValueRef function, LLVMValueRef data) { unwrap(function)->setPrefixData(unwrap(data)); } diff --git a/src/zig_llvm.h b/src/zig_llvm.h index 6bd6191217..7fdddda6a4 100644 --- a/src/zig_llvm.h +++ b/src/zig_llvm.h @@ -322,6 +322,8 @@ ZIG_EXTERN_C void ZigLLVMAddSretAttr(LLVMValueRef fn_ref, LLVMTypeRef type_val); ZIG_EXTERN_C void ZigLLVMAddFunctionElemTypeAttr(LLVMValueRef fn_ref, size_t arg_index, LLVMTypeRef elem_ty); ZIG_EXTERN_C void ZigLLVMAddFunctionAttrCold(LLVMValueRef fn); +ZIG_EXTERN_C LLVMTypeRef ZigLLVMGetGEPResultElementType(LLVMValueRef GEP); + ZIG_EXTERN_C void ZigLLVMParseCommandLineOptions(size_t argc, const char *const *argv); -- cgit v1.2.3 From 99318e7a95220c0bba88eb42b17747ef79da176d Mon Sep 17 00:00:00 2001 From: Andrew Kelley Date: Tue, 2 Aug 2022 00:04:38 -0700 Subject: LLVM backend fixes Fixing assertions hit after upgrading to opaque pointers API. --- src/codegen/llvm.zig | 2 +- src/stage1/codegen.cpp | 45 +++++++++++++++++++++------------------------ 2 files changed, 22 insertions(+), 25 deletions(-) (limited to 'src/codegen/llvm.zig') diff --git a/src/codegen/llvm.zig b/src/codegen/llvm.zig index a1000a8945..e3cb6f9cd8 100644 --- a/src/codegen/llvm.zig +++ b/src/codegen/llvm.zig @@ -5803,7 +5803,7 @@ pub const FuncGen = struct { .False, ); const call = self.builder.buildCall( - asm_fn.typeOf(), + llvm_fn_ty, asm_fn, llvm_param_values.ptr, @intCast(c_uint, param_count), diff --git a/src/stage1/codegen.cpp b/src/stage1/codegen.cpp index 423e9b7085..960800317e 100644 --- a/src/stage1/codegen.cpp +++ b/src/stage1/codegen.cpp @@ -1352,7 +1352,7 @@ static LLVMValueRef get_return_err_fn(CodeGen *g) { LLVMTypeRef usize_type_ref = g->builtin_types.entry_usize->llvm_type; LLVMValueRef zero = LLVMConstNull(get_llvm_type(g, g->builtin_types.entry_i32)); LLVMValueRef return_address_ptr = LLVMBuildCall2(g->builder, - LLVMTypeOf(get_return_address_fn_val(g)), get_return_address_fn_val(g), &zero, 1, ""); + LLVMGlobalGetValueType(get_return_address_fn_val(g)), get_return_address_fn_val(g), &zero, 1, ""); LLVMValueRef return_address = LLVMBuildPtrToInt(g->builder, return_address_ptr, usize_type_ref, ""); LLVMBasicBlockRef return_block = LLVMAppendBasicBlock(fn_val, "Return"); @@ -1455,9 +1455,12 @@ static LLVMValueRef get_safety_crash_err_fn(CodeGen *g) { } // Fetch the error name from the global table - LLVMValueRef err_table_indices[] = { err_val }; + LLVMValueRef err_table_indices[] = { + LLVMConstNull(usize_ty->llvm_type), + err_val, + }; LLVMValueRef err_name_val = LLVMBuildInBoundsGEP2(g->builder, - get_llvm_type(g, str_type), + LLVMGlobalGetValueType(g->err_name_table), g->err_name_table, err_table_indices, 2, ""); LLVMValueRef ptr_field_ptr = LLVMBuildStructGEP2(g->builder, @@ -4088,9 +4091,8 @@ static LLVMValueRef ir_render_ptr_of_array_to_slice(CodeGen *g, Stage1Air *execu LLVMConstInt(g->builtin_types.entry_usize->llvm_type, 0, false), }; LLVMValueRef expr_val = ir_llvm_value(g, instruction->operand); - LLVMTypeRef elem_llvm_ty = get_llvm_type(g, array_type->data.array.child_type); - LLVMValueRef slice_start_ptr = LLVMBuildInBoundsGEP2(g->builder, elem_llvm_ty, expr_val, - indices, 2, ""); + LLVMValueRef slice_start_ptr = LLVMBuildInBoundsGEP2(g->builder, + get_llvm_type(g, array_type), expr_val, indices, 2, ""); gen_store_untyped(g, slice_start_ptr, ptr_field_ptr, 0, false); } else if (ir_want_runtime_safety(g, &instruction->base) && ptr_index != SIZE_MAX) { LLVMValueRef ptr_field_ptr = LLVMBuildStructGEP2(g->builder, get_llvm_type(g, slice_type), result_loc, ptr_index, ""); @@ -4762,7 +4764,7 @@ static LLVMValueRef ir_render_elem_ptr(CodeGen *g, Stage1Air *executable, Stage1 LLVMConstNull(g->builtin_types.entry_usize->llvm_type), subscript_value }; - return LLVMBuildInBoundsGEP2(g->builder, get_llvm_type(g, child_type), array_ptr, + return LLVMBuildInBoundsGEP2(g->builder, get_llvm_type(g, array_type), array_ptr, indices, 2, ""); } else if (array_type->id == ZigTypeIdPointer) { LLVMValueRef array_ptr = get_handle_value(g, array_ptr_ptr, array_type, array_ptr_type); @@ -5440,8 +5442,6 @@ static LLVMValueRef ir_render_struct_field_ptr(CodeGen *g, Stage1Air *executable LLVMValueRef struct_ptr = ir_llvm_value(g, instruction->struct_ptr); // not necessarily a pointer. could be ZigTypeIdStruct ZigType *struct_ptr_type = instruction->struct_ptr->value->type; - ZigType *struct_ty = (struct_ptr_type->id == ZigTypeIdPointer) ? - struct_ptr_type->data.pointer.child_type : struct_ptr_type; TypeStructField *field = instruction->field; if (!type_has_bits(g, field->type_entry)) @@ -5469,7 +5469,7 @@ static LLVMValueRef ir_render_struct_field_ptr(CodeGen *g, Stage1Air *executable ir_assert(field->gen_index != SIZE_MAX, &instruction->base); LLVMValueRef field_ptr_val = LLVMBuildStructGEP2(g->builder, - get_llvm_type(g, struct_ty), struct_ptr, (unsigned)field->gen_index, ""); + get_llvm_type(g, struct_type), struct_ptr, (unsigned)field->gen_index, ""); ZigType *res_type = instruction->base.value->type; ir_assert(res_type->id == ZigTypeIdPointer, &instruction->base); if (res_type->data.pointer.host_int_bytes != 0) { @@ -5753,7 +5753,8 @@ static LLVMValueRef ir_render_asm_gen(CodeGen *g, Stage1Air *executable, Stage1A LLVMValueRef asm_fn = LLVMGetInlineAsm(function_type, buf_ptr(&llvm_template), buf_len(&llvm_template), buf_ptr(&constraint_buf), buf_len(&constraint_buf), is_volatile, false, LLVMInlineAsmDialectATT, false); - LLVMValueRef built_call = LLVMBuildCall2(g->builder, LLVMGlobalGetValueType(asm_fn), asm_fn, param_values, (unsigned)input_and_output_count, ""); + LLVMValueRef built_call = LLVMBuildCall2(g->builder, function_type, + asm_fn, param_values, (unsigned)input_and_output_count, ""); for (size_t i = 0; i < input_and_output_count; i += 1) { if (param_needs_attr[i] != nullptr) { @@ -6073,11 +6074,9 @@ static LLVMValueRef ir_render_err_name(CodeGen *g, Stage1Air *executable, Stage1 LLVMConstNull(g->builtin_types.entry_usize->llvm_type), err_val, }; - ZigType *u8_ptr_type = get_pointer_to_type_extra(g, g->builtin_types.entry_u8, true, false, - PtrLenUnknown, get_abi_alignment(g, g->builtin_types.entry_u8), 0, 0, false); - ZigType *str_type = get_slice_type(g, u8_ptr_type); - LLVMTypeRef elem_llvm_ty = get_llvm_type(g, str_type); - return LLVMBuildInBoundsGEP2(g->builder, elem_llvm_ty, g->err_name_table, indices, 2, ""); + return LLVMBuildInBoundsGEP2(g->builder, + LLVMGlobalGetValueType(g->err_name_table), + g->err_name_table, indices, 2, ""); } static LLVMValueRef get_enum_tag_name_function(CodeGen *g, ZigType *enum_type) { @@ -6697,15 +6696,14 @@ static LLVMValueRef ir_render_slice(CodeGen *g, Stage1Air *executable, Stage1Air codegen_report_errors_and_exit(g); if (value_has_bits) { - LLVMTypeRef elem_llvm_ty = get_llvm_type(g, array_type->data.array.child_type); - + LLVMTypeRef array_llvm_ty = get_llvm_type(g, array_type); if (want_runtime_safety && sentinel != nullptr) { LLVMValueRef indices[] = { LLVMConstNull(g->builtin_types.entry_usize->llvm_type), end_val, }; LLVMValueRef sentinel_elem_ptr = LLVMBuildInBoundsGEP2(g->builder, - elem_llvm_ty, array_ptr, indices, 2, ""); + array_llvm_ty, array_ptr, indices, 2, ""); add_sentinel_check(g, sentinel_elem_ptr, sentinel); } @@ -6713,7 +6711,7 @@ static LLVMValueRef ir_render_slice(CodeGen *g, Stage1Air *executable, Stage1Air LLVMConstNull(g->builtin_types.entry_usize->llvm_type), start_val, }; - slice_start_ptr = LLVMBuildInBoundsGEP2(g->builder, elem_llvm_ty, array_ptr, indices, 2, ""); + slice_start_ptr = LLVMBuildInBoundsGEP2(g->builder, array_llvm_ty, array_ptr, indices, 2, ""); } len_value = LLVMBuildNUWSub(g->builder, end_val, start_val, ""); @@ -6732,15 +6730,14 @@ static LLVMValueRef ir_render_slice(CodeGen *g, Stage1Air *executable, Stage1Air codegen_report_errors_and_exit(g); if (value_has_bits) { - LLVMTypeRef elem_llvm_ty = get_llvm_type(g, array_type->data.pointer.child_type); - + LLVMTypeRef array_llvm_ty = get_llvm_type(g, array_type); if (want_runtime_safety && sentinel != nullptr) { - LLVMValueRef sentinel_elem_ptr = LLVMBuildInBoundsGEP2(g->builder, elem_llvm_ty, + LLVMValueRef sentinel_elem_ptr = LLVMBuildInBoundsGEP2(g->builder, array_llvm_ty, array_ptr, &end_val, 1, ""); add_sentinel_check(g, sentinel_elem_ptr, sentinel); } - slice_start_ptr = LLVMBuildInBoundsGEP2(g->builder, elem_llvm_ty, array_ptr, + slice_start_ptr = LLVMBuildInBoundsGEP2(g->builder, array_llvm_ty, array_ptr, &start_val, 1, ""); } -- cgit v1.2.3 From a3045b8abbba896da34a02266f2be89dd6c90ecc Mon Sep 17 00:00:00 2001 From: Andrew Kelley Date: Wed, 3 Aug 2022 16:42:27 -0700 Subject: LLVM backends: more LLVM 15 fixes uwtable now needs a "sync" or "async" parameter. more opaque pointer fixes --- src/codegen/llvm.zig | 16 +++++++++------- src/stage1/codegen.cpp | 2 +- 2 files changed, 10 insertions(+), 8 deletions(-) (limited to 'src/codegen/llvm.zig') diff --git a/src/codegen/llvm.zig b/src/codegen/llvm.zig index e3cb6f9cd8..2439948639 100644 --- a/src/codegen/llvm.zig +++ b/src/codegen/llvm.zig @@ -2365,7 +2365,7 @@ pub const DeclGen = struct { } dg.addFnAttr(llvm_fn, "nounwind"); if (comp.unwind_tables) { - dg.addFnAttr(llvm_fn, "uwtable"); + dg.addFnAttrString(llvm_fn, "uwtable", "sync"); } if (comp.bin_file.options.skip_linker_dependencies or comp.bin_file.options.no_builtin) @@ -4996,8 +4996,8 @@ pub const FuncGen = struct { const indices: [2]*const llvm.Value = .{ llvm_usize.constNull(), llvm_usize.constNull(), }; - const elem_llvm_ty = try self.dg.lowerType(array_ty.childType()); - const ptr = self.builder.buildInBoundsGEP(elem_llvm_ty, operand, &indices, indices.len, ""); + const array_llvm_ty = try self.dg.lowerType(array_ty); + const ptr = self.builder.buildInBoundsGEP(array_llvm_ty, operand, &indices, indices.len, ""); const partial = self.builder.buildInsertValue(slice_llvm_ty.getUndef(), ptr, 0, ""); return self.builder.buildInsertValue(partial, len, 1, ""); } @@ -5174,13 +5174,14 @@ pub const FuncGen = struct { const array_llvm_val = try self.resolveInst(bin_op.lhs); const rhs = try self.resolveInst(bin_op.rhs); if (isByRef(array_ty)) { - const elem_ty = array_ty.childType(); - const elem_llvm_ty = try self.dg.lowerType(elem_ty); + const array_llvm_ty = try self.dg.lowerType(array_ty); const indices: [2]*const llvm.Value = .{ self.context.intType(32).constNull(), rhs }; - const elem_ptr = self.builder.buildInBoundsGEP(elem_llvm_ty, array_llvm_val, &indices, indices.len, ""); + const elem_ptr = self.builder.buildInBoundsGEP(array_llvm_ty, array_llvm_val, &indices, indices.len, ""); + const elem_ty = array_ty.childType(); if (isByRef(elem_ty)) { return elem_ptr; } else { + const elem_llvm_ty = try self.dg.lowerType(elem_ty); return self.builder.buildLoad(elem_llvm_ty, elem_ptr, ""); } } @@ -7306,6 +7307,7 @@ pub const FuncGen = struct { } else { // If the ABI size of the element type is not evenly divisible by size in bits; // a simple bitcast will not work, and we fall back to extractelement. + const array_llvm_ty = try self.dg.lowerType(operand_ty); const elem_llvm_ty = try self.dg.lowerType(elem_ty); const llvm_usize = try self.dg.lowerType(Type.usize); const llvm_u32 = self.context.intType(32); @@ -7317,7 +7319,7 @@ pub const FuncGen = struct { const index_usize = llvm_usize.constInt(i, .False); const index_u32 = llvm_u32.constInt(i, .False); const indexes: [2]*const llvm.Value = .{ zero, index_usize }; - const elem_ptr = self.builder.buildInBoundsGEP(elem_llvm_ty, operand, &indexes, indexes.len, ""); + const elem_ptr = self.builder.buildInBoundsGEP(array_llvm_ty, operand, &indexes, indexes.len, ""); const elem = self.builder.buildLoad(elem_llvm_ty, elem_ptr, ""); vector = self.builder.buildInsertElement(vector, elem, index_u32, ""); } diff --git a/src/stage1/codegen.cpp b/src/stage1/codegen.cpp index beb557ee99..111aa7a58f 100644 --- a/src/stage1/codegen.cpp +++ b/src/stage1/codegen.cpp @@ -223,7 +223,7 @@ static ZigLLVM_CallingConv get_llvm_cc(CodeGen *g, CallingConvention cc) { static void add_uwtable_attr(CodeGen *g, LLVMValueRef fn_val) { if (g->unwind_tables) { - addLLVMFnAttr(fn_val, "uwtable"); + addLLVMFnAttrStr(fn_val, "uwtable", "sync"); } } -- cgit v1.2.3 From ac5c6b6061c6454a891c22a8258069370b57c05b Mon Sep 17 00:00:00 2001 From: Andrew Kelley Date: Thu, 4 Aug 2022 17:32:46 -0700 Subject: stage2 LLVM backend: opaque pointer fixes --- src/codegen/llvm.zig | 118 ++++++++++++++++++++++++++++++++------------------- src/type.zig | 5 +++ 2 files changed, 80 insertions(+), 43 deletions(-) (limited to 'src/codegen/llvm.zig') diff --git a/src/codegen/llvm.zig b/src/codegen/llvm.zig index 2439948639..a286f8ad01 100644 --- a/src/codegen/llvm.zig +++ b/src/codegen/llvm.zig @@ -2523,16 +2523,7 @@ pub const DeclGen = struct { if (ptr_info.host_size != 0) { return dg.context.intType(ptr_info.host_size * 8).pointerType(llvm_addrspace); } - const elem_ty = ptr_info.pointee_type; - const lower_elem_ty = switch (elem_ty.zigTypeTag()) { - .Opaque, .Fn => true, - .Array => elem_ty.childType().hasRuntimeBitsIgnoreComptime(), - else => elem_ty.hasRuntimeBitsIgnoreComptime(), - }; - const llvm_elem_ty = if (lower_elem_ty) - try dg.lowerType(elem_ty) - else - dg.context.intType(8); + const llvm_elem_ty = try dg.lowerPtrElemTy(ptr_info.pointee_type); return llvm_elem_ty.pointerType(llvm_addrspace); }, .Opaque => switch (t.tag()) { @@ -2917,6 +2908,23 @@ pub const DeclGen = struct { ); } + /// Use this instead of lowerType when you want to handle correctly the case of elem_ty + /// being a zero bit type, but it should still be lowered as an i8 in such case. + /// There are other similar cases handled here as well. + fn lowerPtrElemTy(dg: *DeclGen, elem_ty: Type) Allocator.Error!*const llvm.Type { + const lower_elem_ty = switch (elem_ty.zigTypeTag()) { + .Opaque, .Fn => true, + .Array => elem_ty.childType().hasRuntimeBitsIgnoreComptime(), + else => elem_ty.hasRuntimeBitsIgnoreComptime(), + }; + const llvm_elem_ty = if (lower_elem_ty) + try dg.lowerType(elem_ty) + else + dg.context.intType(8); + + return llvm_elem_ty; + } + fn lowerValue(dg: *DeclGen, tv: TypedValue) Error!*const llvm.Value { if (tv.val.isUndef()) { const llvm_type = try dg.lowerType(tv.ty); @@ -4674,8 +4682,8 @@ pub const FuncGen = struct { _ = self.builder.buildBr(end_block); self.builder.positionBuilderAtEnd(both_pl_block); - const lhs_payload = self.optPayloadHandle(opt_llvm_ty, lhs, scalar_ty); - const rhs_payload = self.optPayloadHandle(opt_llvm_ty, rhs, scalar_ty); + const lhs_payload = try self.optPayloadHandle(opt_llvm_ty, lhs, scalar_ty); + const rhs_payload = try self.optPayloadHandle(opt_llvm_ty, rhs, scalar_ty); const payload_cmp = try self.cmp(lhs_payload, rhs_payload, payload_ty, op); _ = self.builder.buildBr(end_block); const both_pl_block_end = self.builder.getInsertBlock(); @@ -5133,7 +5141,8 @@ pub const FuncGen = struct { const ty_op = self.air.instructions.items(.data)[inst].ty_op; const slice_ptr = try self.resolveInst(ty_op.operand); - const slice_llvm_ty = try self.dg.lowerType(self.air.typeOf(ty_op.operand).childType()); + const slice_ptr_ty = self.air.typeOf(ty_op.operand); + const slice_llvm_ty = try self.dg.lowerPtrElemTy(slice_ptr_ty.childType()); return self.builder.buildStructGEP(slice_llvm_ty, slice_ptr, index, ""); } @@ -5145,7 +5154,7 @@ pub const FuncGen = struct { const slice = try self.resolveInst(bin_op.lhs); const index = try self.resolveInst(bin_op.rhs); - const llvm_elem_ty = try self.dg.lowerType(slice_ty.childType()); + const llvm_elem_ty = try self.dg.lowerPtrElemTy(slice_ty.childType()); const base_ptr = self.builder.buildExtractValue(slice, 0, ""); const indices: [1]*const llvm.Value = .{index}; const ptr = self.builder.buildInBoundsGEP(llvm_elem_ty, base_ptr, &indices, indices.len, ""); @@ -5160,7 +5169,7 @@ pub const FuncGen = struct { const slice = try self.resolveInst(bin_op.lhs); const index = try self.resolveInst(bin_op.rhs); - const llvm_elem_ty = try self.dg.lowerType(slice_ty.childType()); + const llvm_elem_ty = try self.dg.lowerPtrElemTy(slice_ty.childType()); const base_ptr = self.builder.buildExtractValue(slice, 0, ""); const indices: [1]*const llvm.Value = .{index}; return self.builder.buildInBoundsGEP(llvm_elem_ty, base_ptr, &indices, indices.len, ""); @@ -5195,9 +5204,10 @@ pub const FuncGen = struct { const ptr_ty = self.air.typeOf(bin_op.lhs); if (!ptr_ty.isVolatilePtr() and self.liveness.isUnused(inst)) return null; - const llvm_elem_ty = try self.dg.lowerType(ptr_ty.childType()); + const llvm_elem_ty = try self.dg.lowerPtrElemTy(ptr_ty.childType()); const base_ptr = try self.resolveInst(bin_op.lhs); const rhs = try self.resolveInst(bin_op.rhs); + // TODO: when we go fully opaque pointers in LLVM 16 we can remove this branch const ptr = if (ptr_ty.isSinglePointer()) ptr: { // If this is a single-item pointer to an array, we need another index in the GEP. const indices: [2]*const llvm.Value = .{ self.context.intType(32).constNull(), rhs }; @@ -5220,7 +5230,7 @@ pub const FuncGen = struct { const base_ptr = try self.resolveInst(bin_op.lhs); const rhs = try self.resolveInst(bin_op.rhs); - const llvm_elem_ty = try self.dg.lowerType(elem_ty); + const llvm_elem_ty = try self.dg.lowerPtrElemTy(elem_ty); if (ptr_ty.isSinglePointer()) { // If this is a single-item pointer to an array, we need another index in the GEP. const indices: [2]*const llvm.Value = .{ self.context.intType(32).constNull(), rhs }; @@ -5555,7 +5565,9 @@ pub const FuncGen = struct { const max_param_count = inputs.len + outputs.len; const llvm_param_types = try arena.alloc(*const llvm.Type, max_param_count); const llvm_param_values = try arena.alloc(*const llvm.Value, max_param_count); - const llvm_param_attrs = try arena.alloc(bool, max_param_count); + // This stores whether we need to add an elementtype attribute and + // if so, the element type itself. + const llvm_param_attrs = try arena.alloc(?*const llvm.Type, max_param_count); const target = self.dg.module.getTarget(); var llvm_ret_i: usize = 0; @@ -5573,7 +5585,7 @@ pub const FuncGen = struct { // for the string, we still use the next u32 for the null terminator. extra_i += (constraint.len + name.len + (2 + 3)) / 4; - try llvm_constraints.ensureUnusedCapacity(self.gpa, constraint.len + 1); + try llvm_constraints.ensureUnusedCapacity(self.gpa, constraint.len + 3); if (total_i != 0) { llvm_constraints.appendAssumeCapacity(','); } @@ -5582,8 +5594,10 @@ pub const FuncGen = struct { // Pass any non-return outputs indirectly, if the constraint accepts a memory location llvm_ret_indirect[i] = (output != .none) and constraintAllowsMemory(constraint); if (output != .none) { - try llvm_constraints.ensureUnusedCapacity(self.gpa, llvm_constraints.capacity + 1); const output_inst = try self.resolveInst(output); + const output_ty = self.air.typeOf(output); + assert(output_ty.zigTypeTag() == .Pointer); + const elem_llvm_ty = try self.dg.lowerPtrElemTy(output_ty.childType()); if (llvm_ret_indirect[i]) { // Pass the result by reference as an indirect output (e.g. "=*m") @@ -5591,11 +5605,11 @@ pub const FuncGen = struct { llvm_param_values[llvm_param_i] = output_inst; llvm_param_types[llvm_param_i] = output_inst.typeOf(); - llvm_param_attrs[llvm_param_i] = true; + llvm_param_attrs[llvm_param_i] = elem_llvm_ty; llvm_param_i += 1; } else { // Pass the result directly (e.g. "=r") - llvm_ret_types[llvm_ret_i] = output_inst.typeOf().getElementType(); + llvm_ret_types[llvm_ret_i] = elem_llvm_ty; llvm_ret_i += 1; } } else { @@ -5633,7 +5647,9 @@ pub const FuncGen = struct { const arg_llvm_value = try self.resolveInst(input); const arg_ty = self.air.typeOf(input); + var llvm_elem_ty: ?*const llvm.Type = null; if (isByRef(arg_ty)) { + llvm_elem_ty = try self.dg.lowerPtrElemTy(arg_ty); if (constraintAllowsMemory(constraint)) { llvm_param_values[llvm_param_i] = arg_llvm_value; llvm_param_types[llvm_param_i] = arg_llvm_value.typeOf(); @@ -5677,7 +5693,12 @@ pub const FuncGen = struct { // In the case of indirect inputs, LLVM requires the callsite to have // an elementtype() attribute. - llvm_param_attrs[llvm_param_i] = constraint[0] == '*'; + if (constraint[0] == '*') { + llvm_param_attrs[llvm_param_i] = llvm_elem_ty orelse + try self.dg.lowerPtrElemTy(arg_ty.childType()); + } else { + llvm_param_attrs[llvm_param_i] = null; + } llvm_param_i += 1; total_i += 1; @@ -5812,10 +5833,9 @@ pub const FuncGen = struct { .Auto, "", ); - for (llvm_param_attrs[0..param_count]) |need_elem_ty, i| { - if (need_elem_ty) { - const elem_ty = llvm_param_types[i].getElementType(); - llvm.setCallElemTypeAttr(call, i, elem_ty); + for (llvm_param_attrs[0..param_count]) |llvm_elem_ty, i| { + if (llvm_elem_ty) |llvm_ty| { + llvm.setCallElemTypeAttr(call, i, llvm_ty); } } @@ -6558,7 +6578,7 @@ pub const FuncGen = struct { const base_ptr = try self.resolveInst(bin_op.lhs); const offset = try self.resolveInst(bin_op.rhs); const ptr_ty = self.air.typeOf(bin_op.lhs); - const llvm_elem_ty = try self.dg.lowerType(ptr_ty.childType()); + const llvm_elem_ty = try self.dg.lowerPtrElemTy(ptr_ty.childType()); if (ptr_ty.ptrSize() == .One) { // It's a pointer to an array, so according to LLVM we need an extra GEP index. const indices: [2]*const llvm.Value = .{ @@ -6580,7 +6600,7 @@ pub const FuncGen = struct { const offset = try self.resolveInst(bin_op.rhs); const negative_offset = self.builder.buildNeg(offset, ""); const ptr_ty = self.air.typeOf(bin_op.lhs); - const llvm_elem_ty = try self.dg.lowerType(ptr_ty.childType()); + const llvm_elem_ty = try self.dg.lowerPtrElemTy(ptr_ty.childType()); if (ptr_ty.ptrSize() == .One) { // It's a pointer to an array, so according to LLVM we need an extra GEP index. const indices: [2]*const llvm.Value = .{ @@ -7564,7 +7584,7 @@ pub const FuncGen = struct { if (self.liveness.isUnused(inst)) return null; const llvm_i32 = self.context.intType(32); - const llvm_fn_name = "llvm.frameaddress.p0i8"; + const llvm_fn_name = "llvm.frameaddress.p0"; const llvm_fn = self.dg.object.llvm_module.getNamedFunction(llvm_fn_name) orelse blk: { const llvm_p0i8 = self.context.intType(8).pointerType(0); const param_types = [_]*const llvm.Type{llvm_i32}; @@ -7694,20 +7714,31 @@ pub const FuncGen = struct { const atomic_load = self.air.instructions.items(.data)[inst].atomic_load; const ptr = try self.resolveInst(atomic_load.ptr); const ptr_ty = self.air.typeOf(atomic_load.ptr); - if (!ptr_ty.isVolatilePtr() and self.liveness.isUnused(inst)) + const ptr_info = ptr_ty.ptrInfo().data; + if (!ptr_info.@"volatile" and self.liveness.isUnused(inst)) + return null; + const elem_ty = ptr_info.pointee_type; + if (!elem_ty.hasRuntimeBitsIgnoreComptime()) return null; const ordering = toLlvmAtomicOrdering(atomic_load.order); - const operand_ty = ptr_ty.elemType(); - const opt_abi_ty = self.dg.getAtomicAbiType(operand_ty, false); + const opt_abi_llvm_ty = self.dg.getAtomicAbiType(elem_ty, false); + const target = self.dg.module.getTarget(); + const ptr_alignment = ptr_info.alignment(target); + const ptr_volatile = llvm.Bool.fromBool(ptr_info.@"volatile"); + const elem_llvm_ty = try self.dg.lowerType(elem_ty); - if (opt_abi_ty) |abi_ty| { + if (opt_abi_llvm_ty) |abi_llvm_ty| { // operand needs widening and truncating - const casted_ptr = self.builder.buildBitCast(ptr, abi_ty.pointerType(0), ""); - const load_inst = (try self.load(casted_ptr, ptr_ty)).?; + const casted_ptr = self.builder.buildBitCast(ptr, abi_llvm_ty.pointerType(0), ""); + const load_inst = self.builder.buildLoad(abi_llvm_ty, casted_ptr, ""); + load_inst.setAlignment(ptr_alignment); + load_inst.setVolatile(ptr_volatile); load_inst.setOrdering(ordering); - return self.builder.buildTrunc(load_inst, try self.dg.lowerType(operand_ty), ""); + return self.builder.buildTrunc(load_inst, elem_llvm_ty, ""); } - const load_inst = (try self.load(ptr, ptr_ty)).?; + const load_inst = self.builder.buildLoad(elem_llvm_ty, ptr, ""); + load_inst.setAlignment(ptr_alignment); + load_inst.setVolatile(ptr_volatile); load_inst.setOrdering(ordering); return load_inst; } @@ -8508,7 +8539,7 @@ pub const FuncGen = struct { const llvm_ptr_u8 = llvm_u8.pointerType(0); const llvm_u32 = self.context.intType(32); - const llvm_fn_name = "llvm.prefetch.p0i8"; + const llvm_fn_name = "llvm.prefetch.p0"; const fn_val = self.dg.object.llvm_module.getNamedFunction(llvm_fn_name) orelse blk: { // declare void @llvm.prefetch(i8*, i32, i32, i32) const llvm_void = self.context.voidType(); @@ -8660,7 +8691,7 @@ pub const FuncGen = struct { opt_llvm_ty: *const llvm.Type, opt_handle: *const llvm.Value, opt_ty: Type, - ) *const llvm.Value { + ) !*const llvm.Value { var buf: Type.Payload.ElemType = undefined; const payload_ty = opt_ty.optionalChild(&buf); @@ -8673,7 +8704,8 @@ pub const FuncGen = struct { } const target = fg.dg.module.getTarget(); const payload_alignment = payload_ty.abiAlignment(target); - const load_inst = fg.builder.buildLoad(payload_ptr.getGEPResultElementType(), payload_ptr, ""); + const payload_llvm_ty = try fg.dg.lowerType(payload_ty); + const load_inst = fg.builder.buildLoad(payload_llvm_ty, payload_ptr, ""); load_inst.setAlignment(payload_alignment); return load_inst; } @@ -8758,7 +8790,7 @@ pub const FuncGen = struct { return self.builder.buildBitCast(new_ptr, result_llvm_ty, ""); }, else => { - const struct_llvm_ty = try self.dg.lowerType(struct_ty); + const struct_llvm_ty = try self.dg.lowerPtrElemTy(struct_ty); var ty_buf: Type.Payload.Pointer = undefined; if (llvmFieldIndex(struct_ty, field_index, target, &ty_buf)) |llvm_field_index| { @@ -8815,7 +8847,7 @@ pub const FuncGen = struct { if (!info.pointee_type.hasRuntimeBitsIgnoreComptime()) return null; const target = self.dg.module.getTarget(); - const ptr_alignment = ptr_ty.ptrAlignment(target); + const ptr_alignment = info.alignment(target); const ptr_volatile = llvm.Bool.fromBool(ptr_ty.isVolatilePtr()); if (info.host_size == 0) { const elem_llvm_ty = try self.dg.lowerType(info.pointee_type); diff --git a/src/type.zig b/src/type.zig index e078170281..a585c830fb 100644 --- a/src/type.zig +++ b/src/type.zig @@ -6229,6 +6229,11 @@ pub const Type = extern union { mutable: bool = true, // TODO rename this to const, not mutable @"volatile": bool = false, size: std.builtin.Type.Pointer.Size = .One, + + pub fn alignment(data: Data, target: Target) u32 { + if (data.@"align" != 0) return data.@"align"; + return abiAlignment(data.pointee_type, target); + } }; }; -- cgit v1.2.3 From b5dc8b67bc2e5dd920a5cabbe32c999f8ea71257 Mon Sep 17 00:00:00 2001 From: Andrew Kelley Date: Mon, 29 Aug 2022 15:00:31 -0700 Subject: LLVM: update merged master branch code to opaque pointers --- src/codegen/llvm.zig | 24 +++++++++++++----------- 1 file changed, 13 insertions(+), 11 deletions(-) (limited to 'src/codegen/llvm.zig') diff --git a/src/codegen/llvm.zig b/src/codegen/llvm.zig index e6bebe521e..6d910d0551 100644 --- a/src/codegen/llvm.zig +++ b/src/codegen/llvm.zig @@ -964,19 +964,19 @@ pub const Object = struct { else => {}, } } - const ints_llvm_ty = dg.context.structType(field_types.ptr, @intCast(c_uint, field_types.len), .False); - const casted_ptr = builder.buildBitCast(arg_ptr, ints_llvm_ty.pointerType(0), ""); + const floats_llvm_ty = dg.context.structType(field_types.ptr, @intCast(c_uint, field_types.len), .False); + const casted_ptr = builder.buildBitCast(arg_ptr, floats_llvm_ty.pointerType(0), ""); for (llvm_floats) |_, i_usize| { const i = @intCast(c_uint, i_usize); const param = llvm_func.getParam(i); - const field_ptr = builder.buildStructGEP(casted_ptr, i, ""); + const field_ptr = builder.buildStructGEP(floats_llvm_ty, casted_ptr, i, ""); const store_inst = builder.buildStore(param, field_ptr); store_inst.setAlignment(target.cpu.arch.ptrBitWidth() / 8); } const is_by_ref = isByRef(param_ty); const loaded = if (is_by_ref) arg_ptr else l: { - const load_inst = builder.buildLoad(arg_ptr, ""); + const load_inst = builder.buildLoad(param_llvm_ty, arg_ptr, ""); load_inst.setAlignment(param_alignment); break :l load_inst; }; @@ -4529,13 +4529,13 @@ pub const FuncGen = struct { else => {}, } } - const ints_llvm_ty = self.dg.context.structType(field_types.ptr, @intCast(c_uint, field_types.len), .False); - const casted_ptr = self.builder.buildBitCast(arg_ptr, ints_llvm_ty.pointerType(0), ""); + const floats_llvm_ty = self.dg.context.structType(field_types.ptr, @intCast(c_uint, field_types.len), .False); + const casted_ptr = self.builder.buildBitCast(arg_ptr, floats_llvm_ty.pointerType(0), ""); try llvm_args.ensureUnusedCapacity(it.llvm_types_len); for (llvm_floats) |_, i_usize| { const i = @intCast(c_uint, i_usize); - const field_ptr = self.builder.buildStructGEP(casted_ptr, i, ""); - const load_inst = self.builder.buildLoad(field_ptr, ""); + const field_ptr = self.builder.buildStructGEP(floats_llvm_ty, casted_ptr, i, ""); + const load_inst = self.builder.buildLoad(field_types[i], field_ptr, ""); load_inst.setAlignment(target.cpu.arch.ptrBitWidth() / 8); llvm_args.appendAssumeCapacity(load_inst); } @@ -8169,7 +8169,7 @@ pub const FuncGen = struct { const llvm_fn = try self.getIsNamedEnumValueFunction(enum_ty); const params = [_]*const llvm.Value{operand}; - return self.builder.buildCall(llvm_fn, ¶ms, params.len, .Fast, .Auto, ""); + return self.builder.buildCall(llvm_fn.globalGetValueType(), llvm_fn, ¶ms, params.len, .Fast, .Auto, ""); } fn getIsNamedEnumValueFunction(self: *FuncGen, enum_ty: Type) !*const llvm.Value { @@ -9249,8 +9249,9 @@ pub const FuncGen = struct { switch (target.cpu.arch) { .x86_64 => { + const array_llvm_ty = usize_llvm_ty.arrayType(6); const array_ptr = fg.valgrind_client_request_array orelse a: { - const array_ptr = fg.buildAlloca(usize_llvm_ty.arrayType(6)); + const array_ptr = fg.buildAlloca(array_llvm_ty); array_ptr.setAlignment(usize_alignment); fg.valgrind_client_request_array = array_ptr; break :a array_ptr; @@ -9261,7 +9262,7 @@ pub const FuncGen = struct { const indexes = [_]*const llvm.Value{ zero, usize_llvm_ty.constInt(@intCast(c_uint, i), .False), }; - const elem_ptr = fg.builder.buildInBoundsGEP(array_ptr, &indexes, indexes.len, ""); + const elem_ptr = fg.builder.buildInBoundsGEP(array_llvm_ty, array_ptr, &indexes, indexes.len, ""); const store_inst = fg.builder.buildStore(elem, elem_ptr); store_inst.setAlignment(usize_alignment); } @@ -9291,6 +9292,7 @@ pub const FuncGen = struct { ); const call = fg.builder.buildCall( + fn_llvm_ty, asm_fn, &args, args.len, -- cgit v1.2.3 From bf28765a975355c27558eaa86cf00ccb29b663a7 Mon Sep 17 00:00:00 2001 From: Andrew Kelley Date: Mon, 29 Aug 2022 18:19:39 -0700 Subject: LLVM: upgrade byval attr code to LLVM 15 opaque pointers Follow-up from 74673b7f69b27dc39a653f92eb58bba71e289f39. --- src/codegen/llvm.zig | 23 ++++++++++++----------- 1 file changed, 12 insertions(+), 11 deletions(-) (limited to 'src/codegen/llvm.zig') diff --git a/src/codegen/llvm.zig b/src/codegen/llvm.zig index 6d910d0551..e8e895e1fc 100644 --- a/src/codegen/llvm.zig +++ b/src/codegen/llvm.zig @@ -797,6 +797,7 @@ pub const Object = struct { const param_ty = fn_info.param_types[it.zig_index - 1]; const param = llvm_func.getParam(llvm_arg_i); try args.ensureUnusedCapacity(1); + assert(!it.byval_attr); if (isByRef(param_ty)) { const alignment = param_ty.abiAlignment(target); @@ -840,11 +841,16 @@ pub const Object = struct { }, .byref => { const param_ty = fn_info.param_types[it.zig_index - 1]; + const param_llvm_ty = try dg.lowerType(param_ty); const param = llvm_func.getParam(llvm_arg_i); + const alignment = param_ty.abiAlignment(target); dg.addArgAttr(llvm_func, llvm_arg_i, "nonnull"); dg.addArgAttr(llvm_func, llvm_arg_i, "readonly"); - dg.addArgAttrInt(llvm_func, llvm_arg_i, "align", param_ty.abiAlignment(target)); + dg.addArgAttrInt(llvm_func, llvm_arg_i, "align", alignment); + if (it.byval_attr) { + llvm_func.addByValAttr(llvm_arg_i, param_llvm_ty); + } llvm_arg_i += 1; @@ -853,14 +859,13 @@ pub const Object = struct { if (isByRef(param_ty)) { args.appendAssumeCapacity(param); } else { - const alignment = param_ty.abiAlignment(target); - const param_llvm_ty = try dg.lowerType(param_ty); const load_inst = builder.buildLoad(param_llvm_ty, param, ""); load_inst.setAlignment(alignment); args.appendAssumeCapacity(load_inst); } }, .abi_sized_int => { + assert(!it.byval_attr); const param_ty = fn_info.param_types[it.zig_index - 1]; const param = llvm_func.getParam(llvm_arg_i); llvm_arg_i += 1; @@ -890,6 +895,7 @@ pub const Object = struct { } }, .slice => { + assert(!it.byval_attr); const param_ty = fn_info.param_types[it.zig_index - 1]; const ptr_info = param_ty.ptrInfo().data; @@ -919,6 +925,7 @@ pub const Object = struct { try args.append(aggregate); }, .multiple_llvm_ints => { + assert(!it.byval_attr); const llvm_ints = it.llvm_types_buffer[0..it.llvm_types_len]; const param_ty = fn_info.param_types[it.zig_index - 1]; const param_llvm_ty = try dg.lowerType(param_ty); @@ -949,6 +956,7 @@ pub const Object = struct { try args.append(loaded); }, .multiple_llvm_float => { + assert(!it.byval_attr); const llvm_floats = it.llvm_types_buffer[0..it.llvm_types_len]; const param_ty = fn_info.param_types[it.zig_index - 1]; const param_llvm_ty = try dg.lowerType(param_ty); @@ -983,6 +991,7 @@ pub const Object = struct { try args.append(loaded); }, .as_u16 => { + assert(!it.byval_attr); const param = llvm_func.getParam(llvm_arg_i); llvm_arg_i += 1; const casted = builder.buildBitCast(param, dg.context.halfType(), ""); @@ -2406,14 +2415,6 @@ pub const DeclGen = struct { dg.addFnAttr(llvm_fn, "noreturn"); } - var llvm_arg_i = @as(c_uint, @boolToInt(sret)) + @boolToInt(err_return_tracing); - var it = iterateParamTypes(dg, fn_info); - while (it.next()) |_| : (llvm_arg_i += 1) { - if (!it.byval_attr) continue; - const param = llvm_fn.getParam(llvm_arg_i); - llvm_fn.addByValAttr(llvm_arg_i, param.typeOf().getElementType()); - } - return llvm_fn; } -- cgit v1.2.3 From fb81ba87620467de11db6b904741b4aafc7cb756 Mon Sep 17 00:00:00 2001 From: Andrew Kelley Date: Tue, 30 Aug 2022 14:45:03 -0700 Subject: LLVM: fix extern functions missing attributes Extern functions were missing attributes such as "readonly" on non-optional pointers, and "byval" which is required to match C ABI. Follow-up from bf28765a975355c27558eaa86cf00ccb29b663a7. closes #12683 --- src/codegen/llvm.zig | 126 +++++++++++++++++++++++++++++++++++++-------------- test/standalone.zig | 2 +- 2 files changed, 92 insertions(+), 36 deletions(-) (limited to 'src/codegen/llvm.zig') diff --git a/src/codegen/llvm.zig b/src/codegen/llvm.zig index b241c1cbcb..badf0721c7 100644 --- a/src/codegen/llvm.zig +++ b/src/codegen/llvm.zig @@ -910,10 +910,11 @@ pub const Object = struct { while (it.next()) |lowering| switch (lowering) { .no_bits => continue, .byval => { - const param_ty = fn_info.param_types[it.zig_index - 1]; + assert(!it.byval_attr); + const param_index = it.zig_index - 1; + const param_ty = fn_info.param_types[param_index]; const param = llvm_func.getParam(llvm_arg_i); try args.ensureUnusedCapacity(1); - assert(!it.byval_attr); if (isByRef(param_ty)) { const alignment = param_ty.abiAlignment(target); @@ -926,32 +927,7 @@ pub const Object = struct { } else { args.appendAssumeCapacity(param); - if (param_ty.isPtrAtRuntime()) { - const ptr_info = param_ty.ptrInfo().data; - if (math.cast(u5, it.zig_index - 1)) |i| { - if (@truncate(u1, fn_info.noalias_bits >> i) != 0) { - dg.addArgAttr(llvm_func, llvm_arg_i, "noalias"); - } - } - if (!param_ty.isPtrLikeOptional() and !ptr_info.@"allowzero") { - dg.addArgAttr(llvm_func, llvm_arg_i, "nonnull"); - } - if (!ptr_info.mutable) { - dg.addArgAttr(llvm_func, llvm_arg_i, "readonly"); - } - if (ptr_info.@"align" != 0) { - dg.addArgAttrInt(llvm_func, llvm_arg_i, "align", ptr_info.@"align"); - } else { - const elem_align = @maximum( - ptr_info.pointee_type.abiAlignment(target), - 1, - ); - dg.addArgAttrInt(llvm_func, llvm_arg_i, "align", elem_align); - } - } else if (ccAbiPromoteInt(fn_info.cc, target, param_ty)) |s| switch (s) { - .signed => dg.addArgAttr(llvm_func, llvm_arg_i, "signext"), - .unsigned => dg.addArgAttr(llvm_func, llvm_arg_i, "zeroext"), - }; + dg.addByValParamAttrs(llvm_func, param_ty, param_index, fn_info, llvm_arg_i); } llvm_arg_i += 1; }, @@ -961,13 +937,7 @@ pub const Object = struct { const param = llvm_func.getParam(llvm_arg_i); const alignment = param_ty.abiAlignment(target); - dg.addArgAttr(llvm_func, llvm_arg_i, "nonnull"); - dg.addArgAttr(llvm_func, llvm_arg_i, "readonly"); - dg.addArgAttrInt(llvm_func, llvm_arg_i, "align", alignment); - if (it.byval_attr) { - llvm_func.addByValAttr(llvm_arg_i, param_llvm_ty); - } - + dg.addByRefParamAttrs(llvm_func, llvm_arg_i, alignment, it.byval_attr, param_llvm_ty); llvm_arg_i += 1; try args.ensureUnusedCapacity(1); @@ -2531,6 +2501,39 @@ pub const DeclGen = struct { dg.addFnAttr(llvm_fn, "noreturn"); } + // Add parameter attributes. We handle only the case of extern functions (no body) + // because functions with bodies are handled in `updateFunc`. + if (is_extern) { + var it = iterateParamTypes(dg, fn_info); + it.llvm_index += @boolToInt(sret); + it.llvm_index += @boolToInt(err_return_tracing); + while (it.next()) |lowering| switch (lowering) { + .byval => { + const param_index = it.zig_index - 1; + const param_ty = fn_info.param_types[param_index]; + if (!isByRef(param_ty)) { + dg.addByValParamAttrs(llvm_fn, param_ty, param_index, fn_info, it.llvm_index - 1); + } + }, + .byref => { + const param_ty = fn_info.param_types[it.zig_index - 1]; + const param_llvm_ty = try dg.lowerType(param_ty); + const alignment = param_ty.abiAlignment(target); + dg.addByRefParamAttrs(llvm_fn, it.llvm_index - 1, alignment, it.byval_attr, param_llvm_ty); + }, + // No attributes needed for these. + .no_bits, + .abi_sized_int, + .multiple_llvm_ints, + .multiple_llvm_float, + .as_u16, + => continue, + + .slice => unreachable, // extern functions do not support slice types. + + }; + } + return llvm_fn; } @@ -4141,6 +4144,59 @@ pub const DeclGen = struct { return null; } } + + fn addByValParamAttrs( + dg: DeclGen, + llvm_fn: *const llvm.Value, + param_ty: Type, + param_index: u32, + fn_info: Type.Payload.Function.Data, + llvm_arg_i: u32, + ) void { + const target = dg.module.getTarget(); + if (param_ty.isPtrAtRuntime()) { + const ptr_info = param_ty.ptrInfo().data; + if (math.cast(u5, param_index)) |i| { + if (@truncate(u1, fn_info.noalias_bits >> i) != 0) { + dg.addArgAttr(llvm_fn, llvm_arg_i, "noalias"); + } + } + if (!param_ty.isPtrLikeOptional() and !ptr_info.@"allowzero") { + dg.addArgAttr(llvm_fn, llvm_arg_i, "nonnull"); + } + if (!ptr_info.mutable) { + dg.addArgAttr(llvm_fn, llvm_arg_i, "readonly"); + } + if (ptr_info.@"align" != 0) { + dg.addArgAttrInt(llvm_fn, llvm_arg_i, "align", ptr_info.@"align"); + } else { + const elem_align = @maximum( + ptr_info.pointee_type.abiAlignment(target), + 1, + ); + dg.addArgAttrInt(llvm_fn, llvm_arg_i, "align", elem_align); + } + } else if (ccAbiPromoteInt(fn_info.cc, target, param_ty)) |s| switch (s) { + .signed => dg.addArgAttr(llvm_fn, llvm_arg_i, "signext"), + .unsigned => dg.addArgAttr(llvm_fn, llvm_arg_i, "zeroext"), + }; + } + + fn addByRefParamAttrs( + dg: DeclGen, + llvm_fn: *const llvm.Value, + llvm_arg_i: u32, + alignment: u32, + byval_attr: bool, + param_llvm_ty: *const llvm.Type, + ) void { + dg.addArgAttr(llvm_fn, llvm_arg_i, "nonnull"); + dg.addArgAttr(llvm_fn, llvm_arg_i, "readonly"); + dg.addArgAttrInt(llvm_fn, llvm_arg_i, "align", alignment); + if (byval_attr) { + llvm_fn.addByValAttr(llvm_arg_i, param_llvm_ty); + } + } }; pub const FuncGen = struct { diff --git a/test/standalone.zig b/test/standalone.zig index bfd683ec4c..463b87556e 100644 --- a/test/standalone.zig +++ b/test/standalone.zig @@ -44,7 +44,7 @@ pub fn addCases(cases: *tests.StandaloneContext) void { } // C ABI compatibility issue: https://github.com/ziglang/zig/issues/1481 if (builtin.cpu.arch == .x86_64) { - if (builtin.zig_backend == .stage1 or builtin.zig_backend == .stage2_llvm) { // https://github.com/ziglang/zig/issues/12222 + if (builtin.zig_backend == .stage1 or builtin.zig_backend == .stage2_llvm) { cases.addBuildFile("test/c_abi/build.zig", .{}); } } -- cgit v1.2.3