diff --git a/src/codegen/llvm.zig b/src/codegen/llvm.zig index b34f630fc2..1ce296f452 100644 --- a/src/codegen/llvm.zig +++ b/src/codegen/llvm.zig @@ -562,7 +562,7 @@ pub const Object = struct { /// Same deal as `decl_map` but for anonymous declarations, which are always global constants. uav_map: std.AutoHashMapUnmanaged(InternPool.Index, Builder.Global.Index), /// Maps enum types to their corresponding LLVM functions for implementing the `tag_name` instruction. - enum_tag_name_map: std.AutoHashMapUnmanaged(InternPool.Index, Builder.Global.Index), + enum_tag_name_map: std.AutoHashMapUnmanaged(InternPool.Index, Builder.Function.Index), /// Serves the same purpose as `enum_tag_name_map` but for the `is_named_enum_value` instruction. named_enum_map: std.AutoHashMapUnmanaged(InternPool.Index, Builder.Function.Index), /// Maps Zig types to LLVM types. The table memory is backed by the GPA of @@ -1138,7 +1138,7 @@ pub const Object = struct { func_index: InternPool.Index, air: *const Air, liveness: *const ?Air.Liveness, - ) !void { + ) Zcu.CodegenFailError!void { const zcu = o.zcu; const comp = zcu.comp; const ip = &zcu.intern_pool; @@ -1514,10 +1514,7 @@ pub const Object = struct { defer fg.deinit(); deinit_wip = false; - fg.genBody(air.getMainBody(), .poi) catch |err| switch (err) { - error.CodegenFail => return, // MLUGG TODO - else => |e| return e, - }; + try fg.genBody(air.getMainBody(), .poi); // If we saw any loads or stores involving `allowzero` pointers, we need to mark the whole // function as considering null pointers valid so that LLVM's optimizers don't remove these @@ -1894,6 +1891,9 @@ pub const Object = struct { if (o.named_enum_map.get(ty)) |function_index| { try o.updateIsNamedEnumValueFunction(.fromInterned(ty), function_index); } + if (o.enum_tag_name_map.get(ty)) |function_index| { + try o.updateEnumTagNameFunction(.fromInterned(ty), function_index); + } } /// Should only be called by the `link.ConstPool` implementation. @@ -4271,25 +4271,39 @@ pub const Object = struct { return o.errors_len_variable; } - /// MLUGG TODO: this also needs incremental updates dumbass - pub fn getEnumTagNameFunction(o: *Object, enum_ty: Type) !Builder.Function.Index { + pub fn getEnumTagNameFunction(o: *Object, enum_ty: Type) Allocator.Error!Builder.Function.Index { const zcu = o.zcu; const ip = &zcu.intern_pool; - const enum_type = ip.loadEnumType(enum_ty.toIntern()); const gop = try o.enum_tag_name_map.getOrPut(o.gpa, enum_ty.toIntern()); - if (gop.found_existing) return gop.value_ptr.ptrConst(&o.builder).kind.function; + if (gop.found_existing) return gop.value_ptr.*; errdefer assert(o.enum_tag_name_map.remove(enum_ty.toIntern())); - - const usize_ty = try o.lowerType(.usize); - const ret_ty = try o.lowerType(.slice_const_u8_sentinel_0); - const llvm_int_ty = try o.lowerType(.fromInterned(enum_type.int_tag_type)); - const target = &zcu.root_mod.resolved_target.result; const function_index = try o.builder.addFunction( - try o.builder.fnType(ret_ty, &.{llvm_int_ty}, .normal), - try o.builder.strtabStringFmt("__zig_tag_name_{f}", .{enum_type.name.fmt(ip)}), - toLlvmAddressSpace(.generic, target), + // Dummy function type; `updateEnumTagNameFunction` will replace it with the correct type. + // TODO: change the builder API so we don't need to do this. + try o.builder.fnType(.void, &.{}, .normal), + try o.builder.strtabStringFmt("__zig_tag_name_{f}", .{enum_ty.containerTypeName(ip).fmt(ip)}), + toLlvmAddressSpace(.generic, zcu.getTarget()), ); + gop.value_ptr.* = function_index; + try o.updateEnumTagNameFunction(enum_ty, function_index); + return function_index; + } + fn updateEnumTagNameFunction( + o: *Object, + enum_ty: Type, + function_index: Builder.Function.Index, + ) Allocator.Error!void { + const zcu = o.zcu; + const ip = &zcu.intern_pool; + const loaded_enum = ip.loadEnumType(enum_ty.toIntern()); + + const llvm_usize_ty = try o.lowerType(.usize); + const llvm_ret_ty = try o.lowerType(.slice_const_u8_sentinel_0); + const llvm_int_ty = try o.lowerType(.fromInterned(loaded_enum.int_tag_type)); + + function_index.ptrConst(&o.builder).global.ptr(&o.builder).type = + try o.builder.fnType(llvm_ret_ty, &.{llvm_int_ty}, .normal); var attributes: Builder.FunctionAttributes.Wip = .{}; defer attributes.deinit(&o.builder); @@ -4298,7 +4312,6 @@ pub const Object = struct { function_index.setLinkage(if (o.builder.strip) .private else .internal, &o.builder); function_index.setCallConv(.fastcc, &o.builder); function_index.setAttributes(try attributes.finish(&o.builder), &o.builder); - gop.value_ptr.* = function_index.ptrConst(&o.builder).global; var wip = try Builder.WipFunction.init(&o.builder, .{ .function = function_index, @@ -4312,13 +4325,13 @@ pub const Object = struct { var wip_switch = try wip.@"switch"( tag_int_value, bad_value_block, - @intCast(enum_type.field_names.len), + @intCast(loaded_enum.field_names.len), .none, ); defer wip_switch.finish(&wip); - for (0..enum_type.field_names.len) |field_index| { - const name = try o.builder.stringNull(enum_type.field_names.get(ip)[field_index].toSlice(ip)); + for (0..loaded_enum.field_names.len) |field_index| { + const name = try o.builder.stringNull(loaded_enum.field_names.get(ip)[field_index].toSlice(ip)); const name_init = try o.builder.stringConst(name); const name_variable_index = try o.builder.addVariable(.empty, name_init.typeOf(&o.builder), .default); @@ -4328,13 +4341,13 @@ pub const Object = struct { name_variable_index.setUnnamedAddr(.unnamed_addr, &o.builder); name_variable_index.setAlignment(comptime Builder.Alignment.fromByteUnits(1), &o.builder); - const name_val = try o.builder.structValue(ret_ty, &.{ + const name_val = try o.builder.structValue(llvm_ret_ty, &.{ name_variable_index.toConst(&o.builder), - try o.builder.intConst(usize_ty, name.slice(&o.builder).?.len - 1), + try o.builder.intConst(llvm_usize_ty, name.slice(&o.builder).?.len - 1), }); const return_block = try wip.block(1, "Name"); - const llvm_tag_val = switch (enum_type.field_values.getOrNone(ip, field_index)) { + const llvm_tag_val = switch (loaded_enum.field_values.getOrNone(ip, field_index)) { .none => try o.builder.intConst(llvm_int_ty, field_index), // auto-numbered else => |tag_val_ip| try o.lowerValue(tag_val_ip), }; @@ -4348,7 +4361,6 @@ pub const Object = struct { _ = try wip.@"unreachable"(); try wip.finish(); - return function_index; } pub fn lazyAbiAlignment(o: *Object, pt: Zcu.PerThread, ty: Type) Allocator.Error!Builder.Alignment.Lazy { @@ -4356,7 +4368,7 @@ pub const Object = struct { return o.lazy_abi_aligns.items[@intFromEnum(index)]; } - pub fn getIsNamedEnumValueFunction(o: *Object, enum_ty: Type) !Builder.Function.Index { + pub fn getIsNamedEnumValueFunction(o: *Object, enum_ty: Type) Allocator.Error!Builder.Function.Index { const zcu = o.zcu; const ip = &zcu.intern_pool; @@ -4380,22 +4392,22 @@ pub const Object = struct { function_index: Builder.Function.Index, ) Allocator.Error!void { const zcu = o.zcu; - const builder = &o.builder; - const loaded_enum = zcu.intern_pool.loadEnumType(enum_ty.toIntern()); + const ip = &zcu.intern_pool; + const loaded_enum = ip.loadEnumType(enum_ty.toIntern()); const llvm_int_ty = try o.lowerType(.fromInterned(loaded_enum.int_tag_type)); - function_index.ptrConst(builder).global.ptr(builder).type = - try builder.fnType(.i1, &.{llvm_int_ty}, .normal); + function_index.ptrConst(&o.builder).global.ptr(&o.builder).type = + try o.builder.fnType(.i1, &.{llvm_int_ty}, .normal); var attributes: Builder.FunctionAttributes.Wip = .{}; - defer attributes.deinit(builder); + defer attributes.deinit(&o.builder); try o.addCommonFnAttributes(&attributes, zcu.root_mod, zcu.root_mod.omit_frame_pointer); - function_index.setLinkage(if (o.builder.strip) .private else .internal, builder); - function_index.setCallConv(.fastcc, builder); - function_index.setAttributes(try attributes.finish(builder), builder); + function_index.setLinkage(if (o.builder.strip) .private else .internal, &o.builder); + function_index.setCallConv(.fastcc, &o.builder); + function_index.setAttributes(try attributes.finish(&o.builder), &o.builder); - var wip: Builder.WipFunction = try .init(builder, .{ + var wip: Builder.WipFunction = try .init(&o.builder, .{ .function = function_index, .strip = true, }); @@ -4409,7 +4421,7 @@ pub const Object = struct { defer wip_switch.finish(&wip); if (loaded_enum.field_values.len > 0) { - for (loaded_enum.field_values.get(&zcu.intern_pool)) |tag_val_ip| { + for (loaded_enum.field_values.get(ip)) |tag_val_ip| { const llvm_tag_val = try o.lowerValue(tag_val_ip); try wip_switch.addCase(llvm_tag_val, named_block, &wip); } diff --git a/src/codegen/llvm/FuncGen.zig b/src/codegen/llvm/FuncGen.zig index 2b4bef2bc7..6f90cfd3c5 100644 --- a/src/codegen/llvm/FuncGen.zig +++ b/src/codegen/llvm/FuncGen.zig @@ -175,11 +175,6 @@ fn resolveValue(self: *FuncGen, val: Value) Allocator.Error!Builder.Constant { } } -/// MLUGG TODO okay yeah prolly delete this again -fn lowerType(fg: *const FuncGen, ty: Type) Allocator.Error!Builder.Type { - return fg.object.lowerType(ty); -} - pub fn genBody(self: *FuncGen, body: []const Air.Inst.Index, coverage_point: Air.CoveragePoint) TodoError!void { const o = self.object; const zcu = self.object.zcu; @@ -608,7 +603,7 @@ fn airCall(self: *FuncGen, inst: Air.Inst.Index, modifier: std.builtin.CallModif } const ret_ptr = if (!sret) null else blk: { - const llvm_ret_ty = try self.lowerType(return_type); + const llvm_ret_ty = try o.lowerType(return_type); try attributes.addParamAttr(0, .{ .sret = llvm_ret_ty }, &o.builder); const alignment = return_type.abiAlignment(zcu).toLlvm(); @@ -630,7 +625,7 @@ fn airCall(self: *FuncGen, inst: Air.Inst.Index, modifier: std.builtin.CallModif const arg = args[it.zig_index - 1]; const param_ty = self.typeOf(arg); const llvm_arg = try self.resolveInst(arg); - const llvm_param_ty = try self.lowerType(param_ty); + const llvm_param_ty = try o.lowerType(param_ty); if (isByRef(param_ty, zcu)) { const alignment = param_ty.abiAlignment(zcu).toLlvm(); const loaded = try self.wip.load(.normal, llvm_param_ty, llvm_arg, alignment, ""); @@ -659,7 +654,7 @@ fn airCall(self: *FuncGen, inst: Air.Inst.Index, modifier: std.builtin.CallModif const llvm_arg = try self.resolveInst(arg); const alignment = param_ty.abiAlignment(zcu).toLlvm(); - const param_llvm_ty = try self.lowerType(param_ty); + const param_llvm_ty = try o.lowerType(param_ty); const arg_ptr = try self.buildAlloca(param_llvm_ty, alignment); if (isByRef(param_ty, zcu)) { const loaded = try self.wip.load(.normal, param_llvm_ty, llvm_arg, alignment, ""); @@ -729,7 +724,7 @@ fn airCall(self: *FuncGen, inst: Air.Inst.Index, modifier: std.builtin.CallModif llvm_arg = ptr; } - const float_ty = try self.lowerType(aarch64_c_abi.getFloatArrayType(arg_ty, zcu).?); + const float_ty = try o.lowerType(aarch64_c_abi.getFloatArrayType(arg_ty, zcu).?); const array_ty = try o.builder.arrayType(count, float_ty); const loaded = try self.wip.load(.normal, array_ty, llvm_arg, alignment, ""); @@ -770,7 +765,7 @@ fn airCall(self: *FuncGen, inst: Air.Inst.Index, modifier: std.builtin.CallModif .byref => { const param_index = it.zig_index - 1; const param_ty = Type.fromInterned(fn_info.param_types.get(ip)[param_index]); - const param_llvm_ty = try self.lowerType(param_ty); + const param_llvm_ty = try o.lowerType(param_ty); const alignment = param_ty.abiAlignment(zcu).toLlvm(); try o.addByRefParamAttrs(&attributes, it.llvm_index - 1, alignment, it.byval_attr, param_llvm_ty); }, @@ -822,7 +817,7 @@ fn airCall(self: *FuncGen, inst: Air.Inst.Index, modifier: std.builtin.CallModif }, toLlvmCallConvTag(fn_info.cc, target).?, try attributes.finish(&o.builder), - try self.lowerType(zig_fn_ty), + try o.lowerType(zig_fn_ty), llvm_fn, llvm_args.items, "", @@ -836,7 +831,7 @@ fn airCall(self: *FuncGen, inst: Air.Inst.Index, modifier: std.builtin.CallModif return .none; } - const llvm_ret_ty = try self.lowerType(return_type); + const llvm_ret_ty = try o.lowerType(return_type); if (ret_ptr) |rp| { if (isByRef(return_type, zcu)) { return rp; @@ -908,7 +903,7 @@ fn airRet(self: *FuncGen, inst: Air.Inst.Index, safety: bool) Allocator.Error!vo const operand = try self.resolveInst(un_op); const val_is_undef = if (un_op.toInterned()) |i| Value.fromInterned(i).isUndef(zcu) else false; if (val_is_undef and safety) { - const len = try o.builder.intValue(try self.lowerType(.usize), ret_ty.abiSize(zcu)); + const len = try o.builder.intValue(try o.lowerType(.usize), ret_ty.abiSize(zcu)); _ = try self.wip.callMemSet( self.ret_ptr, ret_ty.abiAlignment(zcu).toLlvm(), @@ -964,7 +959,7 @@ fn airRet(self: *FuncGen, inst: Air.Inst.Index, safety: bool) Allocator.Error!vo if (val_is_undef and safety) { const llvm_ret_ty = operand.typeOfWip(&self.wip); const rp = try self.buildAlloca(llvm_ret_ty, alignment); - const len = try o.builder.intValue(try self.lowerType(.usize), ret_ty.abiSize(zcu)); + const len = try o.builder.intValue(try o.lowerType(.usize), ret_ty.abiSize(zcu)); _ = try self.wip.callMemSet( rp, alignment, @@ -1034,17 +1029,18 @@ fn airCVaArg(self: *FuncGen, inst: Air.Inst.Index) Allocator.Error!Builder.Value const ty_op = self.air.instructions.items(.data)[@intFromEnum(inst)].ty_op; const list = try self.resolveInst(ty_op.operand); const arg_ty = ty_op.ty.toType(); - const llvm_arg_ty = try self.lowerType(arg_ty); + const llvm_arg_ty = try self.object.lowerType(arg_ty); return self.wip.vaArg(list, llvm_arg_ty, ""); } fn airCVaCopy(self: *FuncGen, inst: Air.Inst.Index) Allocator.Error!Builder.Value { - const zcu = self.object.zcu; + const o = self.object; + const zcu = o.zcu; const ty_op = self.air.instructions.items(.data)[@intFromEnum(inst)].ty_op; const src_list = try self.resolveInst(ty_op.operand); const va_list_ty = ty_op.ty.toType(); - const llvm_va_list_ty = try self.lowerType(va_list_ty); + const llvm_va_list_ty = try o.lowerType(va_list_ty); const result_alignment = va_list_ty.abiAlignment(zcu).toLlvm(); const dest_list = try self.buildAlloca(llvm_va_list_ty, result_alignment); @@ -1065,9 +1061,10 @@ fn airCVaEnd(self: *FuncGen, inst: Air.Inst.Index) Allocator.Error!Builder.Value } fn airCVaStart(self: *FuncGen, inst: Air.Inst.Index) Allocator.Error!Builder.Value { - const zcu = self.object.zcu; + const o = self.object; + const zcu = o.zcu; const va_list_ty = self.typeOfIndex(inst); - const llvm_va_list_ty = try self.lowerType(va_list_ty); + const llvm_va_list_ty = try o.lowerType(va_list_ty); const result_alignment = va_list_ty.abiAlignment(zcu).toLlvm(); const dest_list = try self.buildAlloca(llvm_va_list_ty, result_alignment); @@ -1227,7 +1224,8 @@ fn lowerBlock( maybe_inline_func: ?InternPool.Index, body: []const Air.Inst.Index, ) TodoError!Builder.Value { - const zcu = self.object.zcu; + const o = self.object; + const zcu = o.zcu; const inst_ty = self.typeOfIndex(inst); if (inst_ty.isNoReturn(zcu)) { @@ -1253,7 +1251,7 @@ fn lowerBlock( // Create a phi node only if the block returns a value. if (have_block_result) { - const raw_llvm_ty = try self.lowerType(inst_ty); + const raw_llvm_ty = try o.lowerType(inst_ty); const llvm_ty: Builder.Type = ty: { // If the zig tag type is a function, this represents an actual function body; not // a pointer to it. LLVM IR allows the call instruction to use function bodies instead @@ -1370,7 +1368,7 @@ fn lowerSwitchDispatch( const table_index = try self.wip.conv( .unsigned, try self.wip.bin(.@"sub nuw", cond, jmp_table.min.toValue(), ""), - try self.lowerType(.usize), + try o.lowerType(.usize), "", ); const target_ptr_ptr = try self.ptraddScaled( @@ -1395,7 +1393,7 @@ fn lowerSwitchDispatch( // The switch prongs will correspond to our scalar cases. Ranges will // be handled by conditional branches in the `else` prong. - const llvm_usize = try self.lowerType(.usize); + const llvm_usize = try o.lowerType(.usize); const cond_int = if (cond.typeOfWip(&self.wip).isPointer(&o.builder)) try self.wip.cast(.ptrtoint, cond, llvm_usize, "") else @@ -1642,7 +1640,7 @@ fn lowerTry( } else if (isByRef(payload_ty, zcu)) { return fg.loadByRef(payload_ptr, payload_ty, payload_align.toLlvm(), .normal); } else { - return fg.wip.load(.normal, try fg.lowerType(payload_ty), payload_ptr, payload_align.toLlvm(), ""); + return fg.wip.load(.normal, try o.lowerType(payload_ty), payload_ptr, payload_align.toLlvm(), ""); } } @@ -1912,9 +1910,9 @@ fn airArrayToSlice(self: *FuncGen, inst: Air.Inst.Index) Allocator.Error!Builder const ty_op = self.air.instructions.items(.data)[@intFromEnum(inst)].ty_op; const operand_ty = self.typeOf(ty_op.operand); const array_ty = operand_ty.childType(zcu); - const llvm_usize = try self.lowerType(.usize); + const llvm_usize = try o.lowerType(.usize); const len = try o.builder.intValue(llvm_usize, array_ty.arrayLen(zcu)); - const slice_llvm_ty = try self.lowerType(self.typeOfIndex(inst)); + const slice_llvm_ty = try o.lowerType(self.typeOfIndex(inst)); const operand = try self.resolveInst(ty_op.operand); return self.wip.buildAggregate(slice_llvm_ty, &.{ operand, len }, ""); } @@ -1931,7 +1929,7 @@ fn airFloatFromInt(self: *FuncGen, inst: Air.Inst.Index) TodoError!Builder.Value const dest_ty = self.typeOfIndex(inst); const dest_scalar_ty = dest_ty.scalarType(zcu); - const dest_llvm_ty = try self.lowerType(dest_ty); + const dest_llvm_ty = try o.lowerType(dest_ty); const target = zcu.getTarget(); if (intrinsicsAllowed(dest_scalar_ty, target)) return self.wip.conv( @@ -1999,7 +1997,7 @@ fn airIntFromFloat( const dest_ty = self.typeOfIndex(inst); const dest_scalar_ty = dest_ty.scalarType(zcu); - const dest_llvm_ty = try self.lowerType(dest_ty); + const dest_llvm_ty = try o.lowerType(dest_ty); if (intrinsicsAllowed(operand_scalar_ty, target)) { // TODO set fast math flag @@ -2033,7 +2031,7 @@ fn airIntFromFloat( compiler_rt_dest_abbrev, }); - const operand_llvm_ty = try self.lowerType(operand_ty); + const operand_llvm_ty = try o.lowerType(operand_ty); const libc_fn = try o.getLibcFunction(fn_name, &.{operand_llvm_ty}, libc_ret_ty); var result = try self.wip.call( .normal, @@ -2058,7 +2056,7 @@ fn sliceOrArrayPtr(fg: *FuncGen, ptr: Builder.Value, ty: Type) Allocator.Error!B fn sliceOrArrayLenInBytes(fg: *FuncGen, ptr: Builder.Value, ty: Type) Allocator.Error!Builder.Value { const o = fg.object; const zcu = o.zcu; - const llvm_usize = try fg.lowerType(.usize); + const llvm_usize = try o.lowerType(.usize); switch (ty.ptrSize(zcu)) { .slice => { const len = try fg.wip.extractValue(ptr, &.{1}, ""); @@ -2240,7 +2238,7 @@ fn airStructFieldVal(self: *FuncGen, inst: Air.Inst.Index) Allocator.Error!Build }, .float => { // bitcast int->float - return self.wip.cast(.bitcast, field_int_val, try self.lowerType(field_ty), ""); + return self.wip.cast(.bitcast, field_int_val, try o.lowerType(field_ty), ""); }, } } @@ -2277,8 +2275,8 @@ fn airFieldParentPtr(self: *FuncGen, inst: Air.Inst.Index) Allocator.Error!Build const field_offset = parent_ty.structFieldOffset(extra.field_index, zcu); if (field_offset == 0) return field_ptr; - const res_ty = try self.lowerType(ty_pl.ty.toType()); - const llvm_usize = try self.lowerType(.usize); + const res_ty = try o.lowerType(ty_pl.ty.toType()); + const llvm_usize = try o.lowerType(.usize); const field_ptr_int = try self.wip.cast(.ptrtoint, field_ptr, llvm_usize, ""); const base_ptr_int = try self.wip.bin( @@ -2495,7 +2493,7 @@ fn airAssembly(self: *FuncGen, inst: Air.Inst.Index) TodoError!Builder.Value { const output_inst = try self.resolveInst(output.operand); const output_ty = self.typeOf(output.operand); assert(output_ty.zigTypeTag(zcu) == .pointer); - const elem_llvm_ty = try self.lowerType(output_ty.childType(zcu)); + const elem_llvm_ty = try o.lowerType(output_ty.childType(zcu)); switch (constraint[0]) { '=' => {}, @@ -2533,7 +2531,7 @@ fn airAssembly(self: *FuncGen, inst: Air.Inst.Index) TodoError!Builder.Value { llvm_ret_indirect[output.index] = false; const ret_ty = self.typeOfIndex(inst); - llvm_ret_types[llvm_ret_i] = try self.lowerType(ret_ty); + llvm_ret_types[llvm_ret_i] = try o.lowerType(ret_ty); llvm_ret_i += 1; } @@ -2572,7 +2570,7 @@ fn airAssembly(self: *FuncGen, inst: Air.Inst.Index) TodoError!Builder.Value { llvm_param_types[llvm_param_i] = arg_llvm_value.typeOfWip(&self.wip); } else { const alignment = arg_ty.abiAlignment(zcu).toLlvm(); - const arg_llvm_ty = try self.lowerType(arg_ty); + const arg_llvm_ty = try o.lowerType(arg_ty); const load_inst = try self.wip.load(.normal, arg_llvm_ty, arg_llvm_value, alignment, ""); llvm_param_values[llvm_param_i] = load_inst; @@ -2613,7 +2611,7 @@ fn airAssembly(self: *FuncGen, inst: Air.Inst.Index) TodoError!Builder.Value { llvm_param_attrs[llvm_param_i] = if (constraint[0] == '*') blk: { if (!is_by_ref) self.maybeMarkAllowZeroAccess(arg_ty.ptrInfo(zcu)); - break :blk try self.lowerType(if (is_by_ref) arg_ty else arg_ty.childType(zcu)); + break :blk try o.lowerType(if (is_by_ref) arg_ty else arg_ty.childType(zcu)); } else .none; llvm_param_i += 1; @@ -2627,7 +2625,7 @@ fn airAssembly(self: *FuncGen, inst: Air.Inst.Index) TodoError!Builder.Value { if (constraint[0] != '+') continue; const rw_ty = self.typeOf(output.operand); - const llvm_elem_ty = try self.lowerType(rw_ty.childType(zcu)); + const llvm_elem_ty = try o.lowerType(rw_ty.childType(zcu)); if (llvm_ret_indirect[output.index]) { llvm_param_values[llvm_param_i] = llvm_rw_vals[output.index]; llvm_param_types[llvm_param_i] = llvm_rw_vals[output.index].typeOfWip(&self.wip); @@ -2827,7 +2825,7 @@ fn airIsNonNull( const operand = try self.resolveInst(un_op); const operand_ty = self.typeOf(un_op); const optional_ty = if (operand_is_ptr) operand_ty.childType(zcu) else operand_ty; - const optional_llvm_ty = try self.lowerType(optional_ty); + const optional_llvm_ty = try o.lowerType(optional_ty); const payload_ty = optional_ty.optionalChild(zcu); const access_kind: Builder.MemoryAccessKind = @@ -2896,7 +2894,7 @@ fn airIsErr( if (!payload_ty.hasRuntimeBits(zcu)) { const loaded = if (operand_is_ptr) - try self.wip.load(access_kind, try self.lowerType(err_union_ty), operand, operand_ty.ptrAlignment(zcu).toLlvm(), "") + try self.wip.load(access_kind, try o.lowerType(err_union_ty), operand, operand_ty.ptrAlignment(zcu).toLlvm(), "") else operand; return self.wip.icmp(cond, loaded, zero, ""); @@ -2981,7 +2979,8 @@ fn airOptionalPayload(self: *FuncGen, inst: Air.Inst.Index) Allocator.Error!Buil } fn airErrUnionPayload(self: *FuncGen, inst: Air.Inst.Index, operand_is_ptr: bool) Allocator.Error!Builder.Value { - const zcu = self.object.zcu; + const o = self.object; + const zcu = o.zcu; const ty_op = self.air.instructions.items(.data)[@intFromEnum(inst)].ty_op; const operand = try self.resolveInst(ty_op.operand); const operand_ty = self.typeOf(ty_op.operand); @@ -3001,7 +3000,7 @@ fn airErrUnionPayload(self: *FuncGen, inst: Air.Inst.Index, operand_is_ptr: bool if (isByRef(payload_ty, zcu)) { return self.loadByRef(payload_ptr, payload_ty, payload_alignment, .normal); } else { - const payload_llvm_ty = try self.lowerType(payload_ty); + const payload_llvm_ty = try o.lowerType(payload_ty); return self.wip.load(.normal, payload_llvm_ty, payload_ptr, payload_alignment, ""); } } @@ -3148,7 +3147,7 @@ fn airWrapOptional(self: *FuncGen, body_tail: []const Air.Inst.Index) Allocator. const optional_ty = self.typeOfIndex(inst); if (optional_ty.optionalReprIsPayload(zcu)) return operand; assert(isByRef(optional_ty, zcu)); // optionals with runtime bits are by-ref unless `optionalReprIsPayload` - const llvm_optional_ty = try self.lowerType(optional_ty); + const llvm_optional_ty = try o.lowerType(optional_ty); const optional_ptr = if (self.isNextRet(body_tail)) self.ret_ptr else brk: { @@ -3181,7 +3180,7 @@ fn airWrapErrUnionPayload(self: *FuncGen, body_tail: []const Air.Inst.Index) All assert(payload_ty.hasRuntimeBits(zcu)); assert(isByRef(err_un_ty, zcu)); // error unions with runtime bits are always by-ref const ok_err_code = try o.builder.intValue(try o.errorIntType(), 0); - const err_un_llvm_ty = try self.lowerType(err_un_ty); + const err_un_llvm_ty = try o.lowerType(err_un_ty); const result_ptr = if (self.isNextRet(body_tail)) self.ret_ptr @@ -3205,7 +3204,8 @@ fn airWrapErrUnionPayload(self: *FuncGen, body_tail: []const Air.Inst.Index) All } fn airWrapErrUnionErr(self: *FuncGen, body_tail: []const Air.Inst.Index) Allocator.Error!Builder.Value { - const zcu = self.object.zcu; + const o = self.object; + const zcu = o.zcu; const inst = body_tail[0]; const ty_op = self.air.instructions.items(.data)[@intFromEnum(inst)].ty_op; const err_un_ty = self.typeOfIndex(inst); @@ -3213,7 +3213,7 @@ fn airWrapErrUnionErr(self: *FuncGen, body_tail: []const Air.Inst.Index) Allocat const operand = try self.resolveInst(ty_op.operand); if (!payload_ty.hasRuntimeBits(zcu)) return operand; assert(isByRef(err_un_ty, zcu)); // error unions with runtime bits are always by-ref - const err_un_llvm_ty = try self.lowerType(err_un_ty); + const err_un_llvm_ty = try o.lowerType(err_un_ty); const result_ptr = if (self.isNextRet(body_tail)) self.ret_ptr @@ -3236,7 +3236,7 @@ fn airWasmMemorySize(self: *FuncGen, inst: Air.Inst.Index) Allocator.Error!Build const o = self.object; const pl_op = self.air.instructions.items(.data)[@intFromEnum(inst)].pl_op; const index = pl_op.payload; - const llvm_usize = try self.lowerType(.usize); + const llvm_usize = try o.lowerType(.usize); return self.wip.callIntrinsic(.normal, .none, .@"wasm.memory.size", &.{llvm_usize}, &.{ try o.builder.intValue(.i32, index), }, ""); @@ -3246,7 +3246,7 @@ fn airWasmMemoryGrow(self: *FuncGen, inst: Air.Inst.Index) Allocator.Error!Build const o = self.object; const pl_op = self.air.instructions.items(.data)[@intFromEnum(inst)].pl_op; const index = pl_op.payload; - const llvm_isize = try self.lowerType(.isize); + const llvm_isize = try o.lowerType(.isize); return self.wip.callIntrinsic(.normal, .none, .@"wasm.memory.grow", &.{llvm_isize}, &.{ try o.builder.intValue(.i32, index), try self.resolveInst(pl_op.operand), }, ""); @@ -3260,7 +3260,8 @@ fn airRuntimeNavPtr(fg: *FuncGen, inst: Air.Inst.Index) Allocator.Error!Builder. } fn airMin(self: *FuncGen, inst: Air.Inst.Index) Allocator.Error!Builder.Value { - const zcu = self.object.zcu; + const o = self.object; + const zcu = o.zcu; const bin_op = self.air.instructions.items(.data)[@intFromEnum(inst)].bin_op; const lhs = try self.resolveInst(bin_op.lhs); const rhs = try self.resolveInst(bin_op.rhs); @@ -3272,14 +3273,15 @@ fn airMin(self: *FuncGen, inst: Air.Inst.Index) Allocator.Error!Builder.Value { .normal, .none, if (scalar_ty.isSignedInt(zcu)) .smin else .umin, - &.{try self.lowerType(inst_ty)}, + &.{try o.lowerType(inst_ty)}, &.{ lhs, rhs }, "", ); } fn airMax(self: *FuncGen, inst: Air.Inst.Index) Allocator.Error!Builder.Value { - const zcu = self.object.zcu; + const o = self.object; + const zcu = o.zcu; const bin_op = self.air.instructions.items(.data)[@intFromEnum(inst)].bin_op; const lhs = try self.resolveInst(bin_op.lhs); const rhs = try self.resolveInst(bin_op.rhs); @@ -3291,7 +3293,7 @@ fn airMax(self: *FuncGen, inst: Air.Inst.Index) Allocator.Error!Builder.Value { .normal, .none, if (scalar_ty.isSignedInt(zcu)) .smax else .umax, - &.{try self.lowerType(inst_ty)}, + &.{try o.lowerType(inst_ty)}, &.{ lhs, rhs }, "", ); @@ -3303,7 +3305,7 @@ fn airSlice(self: *FuncGen, inst: Air.Inst.Index) Allocator.Error!Builder.Value const ptr = try self.resolveInst(bin_op.lhs); const len = try self.resolveInst(bin_op.rhs); const inst_ty = self.typeOfIndex(inst); - return self.wip.buildAggregate(try self.lowerType(inst_ty), &.{ ptr, len }, ""); + return self.wip.buildAggregate(try self.object.lowerType(inst_ty), &.{ ptr, len }, ""); } fn airAdd(self: *FuncGen, inst: Air.Inst.Index, fast: Builder.FastMathKind) Allocator.Error!Builder.Value { @@ -3334,7 +3336,7 @@ fn airSafeArithmetic( const scalar_ty = inst_ty.scalarType(zcu); const intrinsic = if (scalar_ty.isSignedInt(zcu)) signed_intrinsic else unsigned_intrinsic; - const llvm_inst_ty = try fg.lowerType(inst_ty); + const llvm_inst_ty = try o.lowerType(inst_ty); const results = try fg.wip.callIntrinsic(.normal, .none, intrinsic, &.{llvm_inst_ty}, &.{ lhs, rhs }, ""); @@ -3372,7 +3374,8 @@ fn airAddWrap(self: *FuncGen, inst: Air.Inst.Index) Allocator.Error!Builder.Valu } fn airAddSat(self: *FuncGen, inst: Air.Inst.Index) Allocator.Error!Builder.Value { - const zcu = self.object.zcu; + const o = self.object; + const zcu = o.zcu; const bin_op = self.air.instructions.items(.data)[@intFromEnum(inst)].bin_op; const lhs = try self.resolveInst(bin_op.lhs); const rhs = try self.resolveInst(bin_op.rhs); @@ -3383,7 +3386,7 @@ fn airAddSat(self: *FuncGen, inst: Air.Inst.Index) Allocator.Error!Builder.Value .normal, .none, if (scalar_ty.isSignedInt(zcu)) .@"sadd.sat" else .@"uadd.sat", - &.{try self.lowerType(inst_ty)}, + &.{try o.lowerType(inst_ty)}, &.{ lhs, rhs }, "", ); @@ -3410,7 +3413,8 @@ fn airSubWrap(self: *FuncGen, inst: Air.Inst.Index) Allocator.Error!Builder.Valu } fn airSubSat(self: *FuncGen, inst: Air.Inst.Index) Allocator.Error!Builder.Value { - const zcu = self.object.zcu; + const o = self.object; + const zcu = o.zcu; const bin_op = self.air.instructions.items(.data)[@intFromEnum(inst)].bin_op; const lhs = try self.resolveInst(bin_op.lhs); const rhs = try self.resolveInst(bin_op.rhs); @@ -3421,7 +3425,7 @@ fn airSubSat(self: *FuncGen, inst: Air.Inst.Index) Allocator.Error!Builder.Value .normal, .none, if (scalar_ty.isSignedInt(zcu)) .@"ssub.sat" else .@"usub.sat", - &.{try self.lowerType(inst_ty)}, + &.{try o.lowerType(inst_ty)}, &.{ lhs, rhs }, "", ); @@ -3448,7 +3452,8 @@ fn airMulWrap(self: *FuncGen, inst: Air.Inst.Index) Allocator.Error!Builder.Valu } fn airMulSat(self: *FuncGen, inst: Air.Inst.Index) Allocator.Error!Builder.Value { - const zcu = self.object.zcu; + const o = self.object; + const zcu = o.zcu; const bin_op = self.air.instructions.items(.data)[@intFromEnum(inst)].bin_op; const lhs = try self.resolveInst(bin_op.lhs); const rhs = try self.resolveInst(bin_op.rhs); @@ -3459,7 +3464,7 @@ fn airMulSat(self: *FuncGen, inst: Air.Inst.Index) Allocator.Error!Builder.Value .normal, .none, if (scalar_ty.isSignedInt(zcu)) .@"smul.fix.sat" else .@"umul.fix.sat", - &.{try self.lowerType(inst_ty)}, + &.{try o.lowerType(inst_ty)}, &.{ lhs, rhs, .@"0" }, "", ); @@ -3503,7 +3508,7 @@ fn airDivFloor(self: *FuncGen, inst: Air.Inst.Index, fast: Builder.FastMathKind) return self.buildFloatOp(.floor, fast, inst_ty, 1, .{result}); } if (scalar_ty.isSignedInt(zcu)) { - const inst_llvm_ty = try self.lowerType(inst_ty); + const inst_llvm_ty = try o.lowerType(inst_ty); const ExpectedContents = [std.math.big.int.calcTwosCompLimbCount(256)]std.math.big.Limb; var stack align(@max( @@ -3579,7 +3584,7 @@ fn airMod(self: *FuncGen, inst: Air.Inst.Index, fast: Builder.FastMathKind) Allo const lhs = try self.resolveInst(bin_op.lhs); const rhs = try self.resolveInst(bin_op.rhs); const inst_ty = self.typeOfIndex(inst); - const inst_llvm_ty = try self.lowerType(inst_ty); + const inst_llvm_ty = try o.lowerType(inst_ty); const scalar_ty = inst_ty.scalarType(zcu); if (scalar_ty.isRuntimeFloat()) { @@ -3646,7 +3651,7 @@ fn airPtrSub(self: *FuncGen, inst: Air.Inst.Index) Allocator.Error!Builder.Value const ty_pl = self.air.instructions.items(.data)[@intFromEnum(inst)].ty_pl; const bin_op = self.air.extraData(Air.Bin, ty_pl.payload).data; const ptr_or_slice = try self.resolveInst(bin_op.lhs); - const llvm_usize_ty = try self.lowerType(.usize); + const llvm_usize_ty = try o.lowerType(.usize); const ptr_ty = self.typeOf(bin_op.lhs); const elem_ty = ptr_ty.indexableElem(zcu); const ptr = switch (ptr_ty.ptrSize(zcu)) { @@ -3665,7 +3670,8 @@ fn airOverflow( signed_intrinsic: Builder.Intrinsic, unsigned_intrinsic: Builder.Intrinsic, ) Allocator.Error!Builder.Value { - const zcu = self.object.zcu; + const o = self.object; + const zcu = o.zcu; const ty_pl = self.air.instructions.items(.data)[@intFromEnum(inst)].ty_pl; const extra = self.air.extraData(Air.Bin, ty_pl.payload).data; @@ -3678,8 +3684,8 @@ fn airOverflow( assert(isByRef(inst_ty, zcu)); // auto structs are by-ref const intrinsic = if (scalar_ty.isSignedInt(zcu)) signed_intrinsic else unsigned_intrinsic; - const llvm_inst_ty = try self.lowerType(inst_ty); - const llvm_lhs_ty = try self.lowerType(lhs_ty); + const llvm_inst_ty = try o.lowerType(inst_ty); + const llvm_lhs_ty = try o.lowerType(lhs_ty); const results = try self.wip.callIntrinsic(.normal, .none, intrinsic, &.{llvm_lhs_ty}, &.{ lhs, rhs }, ""); @@ -3750,7 +3756,7 @@ fn buildFloatCmp( const zcu = o.zcu; const target = zcu.getTarget(); const scalar_ty = ty.scalarType(zcu); - const scalar_llvm_ty = try self.lowerType(scalar_ty); + const scalar_llvm_ty = try o.lowerType(scalar_ty); if (intrinsicsAllowed(scalar_ty, target)) { const cond: Builder.FloatCondition = switch (pred) { @@ -3856,7 +3862,7 @@ fn buildFloatOp( const zcu = o.zcu; const target = zcu.getTarget(); const scalar_ty = ty.scalarType(zcu); - const llvm_ty = try self.lowerType(ty); + const llvm_ty = try o.lowerType(ty); if (op != .tan and intrinsicsAllowed(scalar_ty, target)) switch (op) { // Some operations are dedicated LLVM instructions, not available as intrinsics @@ -3993,7 +3999,8 @@ fn airMulAdd(self: *FuncGen, inst: Air.Inst.Index) Allocator.Error!Builder.Value } fn airShlWithOverflow(self: *FuncGen, inst: Air.Inst.Index) Allocator.Error!Builder.Value { - const zcu = self.object.zcu; + const o = self.object; + const zcu = o.zcu; const ty_pl = self.air.instructions.items(.data)[@intFromEnum(inst)].ty_pl; const extra = self.air.extraData(Air.Bin, ty_pl.payload).data; @@ -4011,9 +4018,9 @@ fn airShlWithOverflow(self: *FuncGen, inst: Air.Inst.Index) Allocator.Error!Buil const dest_ty = self.typeOfIndex(inst); assert(isByRef(dest_ty, zcu)); // auto structs are by-ref - const llvm_dest_ty = try self.lowerType(dest_ty); + const llvm_dest_ty = try o.lowerType(dest_ty); - const casted_rhs = try self.wip.conv(.unsigned, rhs, try self.lowerType(lhs_ty), ""); + const casted_rhs = try self.wip.conv(.unsigned, rhs, try o.lowerType(lhs_ty), ""); const result = try self.wip.bin(.shl, lhs, casted_rhs, ""); const reconstructed = try self.wip.bin(if (lhs_scalar_ty.isSignedInt(zcu)) @@ -4063,7 +4070,8 @@ fn airXor(self: *FuncGen, inst: Air.Inst.Index) Allocator.Error!Builder.Value { } fn airShlExact(self: *FuncGen, inst: Air.Inst.Index) Allocator.Error!Builder.Value { - const zcu = self.object.zcu; + const o = self.object; + const zcu = o.zcu; const bin_op = self.air.instructions.items(.data)[@intFromEnum(inst)].bin_op; const lhs = try self.resolveInst(bin_op.lhs); @@ -4077,7 +4085,7 @@ fn airShlExact(self: *FuncGen, inst: Air.Inst.Index) Allocator.Error!Builder.Val } const lhs_scalar_ty = lhs_ty.scalarType(zcu); - const casted_rhs = try self.wip.conv(.unsigned, rhs, try self.lowerType(lhs_ty), ""); + const casted_rhs = try self.wip.conv(.unsigned, rhs, try o.lowerType(lhs_ty), ""); return self.wip.bin(if (lhs_scalar_ty.isSignedInt(zcu)) .@"shl nsw" else @@ -4085,7 +4093,8 @@ fn airShlExact(self: *FuncGen, inst: Air.Inst.Index) Allocator.Error!Builder.Val } fn airShl(self: *FuncGen, inst: Air.Inst.Index) Allocator.Error!Builder.Value { - const zcu = self.object.zcu; + const o = self.object; + const zcu = o.zcu; const bin_op = self.air.instructions.items(.data)[@intFromEnum(inst)].bin_op; const lhs = try self.resolveInst(bin_op.lhs); @@ -4097,7 +4106,7 @@ fn airShl(self: *FuncGen, inst: Air.Inst.Index) Allocator.Error!Builder.Value { // features which we do not use. Therefore this branch is currently impossible. unreachable; } - const casted_rhs = try self.wip.conv(.unsigned, rhs, try self.lowerType(lhs_ty), ""); + const casted_rhs = try self.wip.conv(.unsigned, rhs, try o.lowerType(lhs_ty), ""); return self.wip.bin(.shl, lhs, casted_rhs, ""); } @@ -4111,7 +4120,7 @@ fn airShlSat(self: *FuncGen, inst: Air.Inst.Index) Allocator.Error!Builder.Value const lhs_ty = self.typeOf(bin_op.lhs); const lhs_info = lhs_ty.intInfo(zcu); - const llvm_lhs_ty = try self.lowerType(lhs_ty); + const llvm_lhs_ty = try o.lowerType(lhs_ty); const llvm_lhs_scalar_ty = llvm_lhs_ty.scalarType(&o.builder); const rhs_ty = self.typeOf(bin_op.rhs); @@ -4122,7 +4131,7 @@ fn airShlSat(self: *FuncGen, inst: Air.Inst.Index) Allocator.Error!Builder.Value } const rhs_info = rhs_ty.intInfo(zcu); assert(rhs_info.signedness == .unsigned); - const llvm_rhs_ty = try self.lowerType(rhs_ty); + const llvm_rhs_ty = try o.lowerType(rhs_ty); const llvm_rhs_scalar_ty = llvm_rhs_ty.scalarType(&o.builder); const result = try self.wip.callIntrinsic( @@ -4184,7 +4193,8 @@ fn airShlSat(self: *FuncGen, inst: Air.Inst.Index) Allocator.Error!Builder.Value } fn airShr(self: *FuncGen, inst: Air.Inst.Index, is_exact: bool) Allocator.Error!Builder.Value { - const zcu = self.object.zcu; + const o = self.object; + const zcu = o.zcu; const bin_op = self.air.instructions.items(.data)[@intFromEnum(inst)].bin_op; const lhs = try self.resolveInst(bin_op.lhs); @@ -4198,7 +4208,7 @@ fn airShr(self: *FuncGen, inst: Air.Inst.Index, is_exact: bool) Allocator.Error! } const lhs_scalar_ty = lhs_ty.scalarType(zcu); - const casted_rhs = try self.wip.conv(.unsigned, rhs, try self.lowerType(lhs_ty), ""); + const casted_rhs = try self.wip.conv(.unsigned, rhs, try o.lowerType(lhs_ty), ""); const is_signed_int = lhs_scalar_ty.isSignedInt(zcu); return self.wip.bin(if (is_exact) @@ -4219,7 +4229,7 @@ fn airAbs(self: *FuncGen, inst: Air.Inst.Index) Allocator.Error!Builder.Value { .normal, .none, .abs, - &.{try self.lowerType(operand_ty)}, + &.{try o.lowerType(operand_ty)}, &.{ operand, try o.builder.intValue(.i1, 0) }, "", ), @@ -4233,7 +4243,7 @@ fn airIntCast(fg: *FuncGen, inst: Air.Inst.Index, safety: bool) Allocator.Error! const zcu = o.zcu; const ty_op = fg.air.instructions.items(.data)[@intFromEnum(inst)].ty_op; const dest_ty = fg.typeOfIndex(inst); - const dest_llvm_ty = try fg.lowerType(dest_ty); + const dest_llvm_ty = try o.lowerType(dest_ty); const operand = try fg.resolveInst(ty_op.operand); const operand_ty = fg.typeOf(ty_op.operand); const operand_info = operand_ty.intInfo(zcu); @@ -4261,8 +4271,8 @@ fn airIntCast(fg: *FuncGen, inst: Air.Inst.Index, safety: bool) Allocator.Error! if (!have_min_check and !have_max_check) break :bounds_check; - const operand_llvm_ty = try fg.lowerType(operand_ty); - const operand_scalar_llvm_ty = try fg.lowerType(operand_scalar); + const operand_llvm_ty = try o.lowerType(operand_ty); + const operand_scalar_llvm_ty = try o.lowerType(operand_scalar); const is_vector = operand_ty.zigTypeTag(zcu) == .vector; assert(is_vector == (dest_ty.zigTypeTag(zcu) == .vector)); @@ -4340,7 +4350,7 @@ fn airIntCast(fg: *FuncGen, inst: Air.Inst.Index, safety: bool) Allocator.Error! fn airTrunc(self: *FuncGen, inst: Air.Inst.Index) Allocator.Error!Builder.Value { const ty_op = self.air.instructions.items(.data)[@intFromEnum(inst)].ty_op; const operand = try self.resolveInst(ty_op.operand); - const dest_llvm_ty = try self.lowerType(self.typeOfIndex(inst)); + const dest_llvm_ty = try self.object.lowerType(self.typeOfIndex(inst)); return self.wip.cast(.trunc, operand, dest_llvm_ty, ""); } @@ -4354,10 +4364,10 @@ fn airFptrunc(self: *FuncGen, inst: Air.Inst.Index) Allocator.Error!Builder.Valu const target = zcu.getTarget(); if (intrinsicsAllowed(dest_ty, target) and intrinsicsAllowed(operand_ty, target)) { - return self.wip.cast(.fptrunc, operand, try self.lowerType(dest_ty), ""); + return self.wip.cast(.fptrunc, operand, try o.lowerType(dest_ty), ""); } else { - const operand_llvm_ty = try self.lowerType(operand_ty); - const dest_llvm_ty = try self.lowerType(dest_ty); + const operand_llvm_ty = try o.lowerType(operand_ty); + const dest_llvm_ty = try o.lowerType(dest_ty); const dest_bits = dest_ty.floatBits(target); const src_bits = operand_ty.floatBits(target); @@ -4388,10 +4398,10 @@ fn airFpext(self: *FuncGen, inst: Air.Inst.Index) Allocator.Error!Builder.Value const target = zcu.getTarget(); if (intrinsicsAllowed(dest_ty, target) and intrinsicsAllowed(operand_ty, target)) { - return self.wip.cast(.fpext, operand, try self.lowerType(dest_ty), ""); + return self.wip.cast(.fpext, operand, try o.lowerType(dest_ty), ""); } else { - const operand_llvm_ty = try self.lowerType(operand_ty); - const dest_llvm_ty = try self.lowerType(dest_ty); + const operand_llvm_ty = try o.lowerType(operand_ty); + const dest_llvm_ty = try o.lowerType(dest_ty); const dest_bits = dest_ty.scalarType(zcu).floatBits(target); const src_bits = operand_ty.scalarType(zcu).floatBits(target); @@ -4431,7 +4441,7 @@ fn bitCast(self: *FuncGen, operand: Builder.Value, operand_ty: Type, inst_ty: Ty const zcu = o.zcu; const operand_is_ref = isByRef(operand_ty, zcu); const result_is_ref = isByRef(inst_ty, zcu); - const llvm_dest_ty = try self.lowerType(inst_ty); + const llvm_dest_ty = try o.lowerType(inst_ty); if (operand_is_ref and result_is_ref) { // They are both pointers, so just return the same opaque pointer :) @@ -4477,7 +4487,7 @@ fn bitCast(self: *FuncGen, operand: Builder.Value, operand_ty: Type, inst_ty: Ty } else if (operand_ty.zigTypeTag(zcu) == .array and inst_ty.zigTypeTag(zcu) == .vector) { const elem_ty = operand_ty.childType(zcu); assert(operand_is_ref); // arrays are always by-ref provided they have runtime bits - const llvm_vector_ty = try self.lowerType(inst_ty); + const llvm_vector_ty = try o.lowerType(inst_ty); const bitcast_ok = elem_ty.bitSize(zcu) == elem_ty.abiSize(zcu) * 8; if (bitcast_ok) { @@ -4488,7 +4498,7 @@ fn bitCast(self: *FuncGen, operand: Builder.Value, operand_ty: Type, inst_ty: Ty } 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.lowerType(elem_ty); + const elem_llvm_ty = try o.lowerType(elem_ty); const elem_size = elem_ty.abiSize(zcu); const vector_len = operand_ty.arrayLen(zcu); var vector = try o.builder.poisonValue(llvm_vector_ty); @@ -4629,7 +4639,7 @@ fn airAlloc(self: *FuncGen, inst: Air.Inst.Index) Allocator.Error!Builder.Value const ptr_info = ptr_ty.ptrInfo(zcu); return (try o.lowerPtrToVoid(ptr_info.flags.alignment, ptr_info.flags.address_space)).toValue(); } - const pointee_llvm_ty = try self.lowerType(pointee_type); + const pointee_llvm_ty = try o.lowerType(pointee_type); const alignment = ptr_ty.ptrAlignment(zcu).toLlvm(); return self.buildAlloca(pointee_llvm_ty, alignment); } @@ -4644,7 +4654,7 @@ fn airRetPtr(self: *FuncGen, inst: Air.Inst.Index) Allocator.Error!Builder.Value return (try o.lowerPtrToVoid(ptr_info.flags.alignment, ptr_info.flags.address_space)).toValue(); } if (self.ret_ptr != .none) return self.ret_ptr; - const ret_llvm_ty = try self.lowerType(ret_ty); + const ret_llvm_ty = try o.lowerType(ret_ty); const alignment = ptr_ty.ptrAlignment(zcu).toLlvm(); return self.buildAlloca(ret_llvm_ty, alignment); } @@ -4696,7 +4706,7 @@ fn airStore(self: *FuncGen, inst: Air.Inst.Index, safety: bool) Allocator.Error! self.maybeMarkAllowZeroAccess(ptr_info); - const len = try o.builder.intValue(try self.lowerType(.usize), operand_ty.abiSize(zcu)); + const len = try o.builder.intValue(try o.lowerType(.usize), operand_ty.abiSize(zcu)); _ = try self.wip.callMemSet( dest_ptr, ptr_ty.ptrAlignment(zcu).toLlvm(), @@ -4735,7 +4745,7 @@ fn airLoad(fg: *FuncGen, inst: Air.Inst.Index) Allocator.Error!Builder.Value { if (ptr_info.flags.vector_index != .none) { const index_u32 = try o.builder.intValue(.i32, ptr_info.flags.vector_index); - const vec_elem_ty = try fg.lowerType(elem_ty); + const vec_elem_ty = try o.lowerType(elem_ty); const vec_ty = try o.builder.vectorType(.normal, ptr_info.packed_offset.host_size, vec_elem_ty); const loaded_vector = try fg.wip.load(access_kind, vec_ty, ptr, llvm_ptr_align, ""); @@ -4753,7 +4763,7 @@ fn airLoad(fg: *FuncGen, inst: Air.Inst.Index) Allocator.Error!Builder.Value { const elem_bits = ptr_ty.childType(zcu).bitSize(zcu); const shift_amt = try o.builder.intValue(containing_int_ty, ptr_info.packed_offset.bit_offset); const shifted_value = try fg.wip.bin(.lshr, containing_int, shift_amt, ""); - const elem_llvm_ty = try fg.lowerType(elem_ty); + const elem_llvm_ty = try o.lowerType(elem_ty); if (isByRef(elem_ty, zcu)) { const result_align = elem_ty.abiAlignment(zcu).toLlvm(); @@ -4813,7 +4823,7 @@ fn airBreakpoint(self: *FuncGen, inst: Air.Inst.Index) Allocator.Error!Builder.V fn airRetAddr(self: *FuncGen, inst: Air.Inst.Index) Allocator.Error!Builder.Value { _ = inst; const o = self.object; - const llvm_usize = try self.lowerType(.usize); + const llvm_usize = try o.lowerType(.usize); if (!target_util.supportsReturnAddress(self.object.zcu.getTarget(), self.ownerModule().optimize_mode)) { // https://github.com/ziglang/zig/issues/11946 return o.builder.intValue(llvm_usize, 0); @@ -4825,7 +4835,7 @@ fn airRetAddr(self: *FuncGen, inst: Air.Inst.Index) Allocator.Error!Builder.Valu fn airFrameAddress(self: *FuncGen, inst: Air.Inst.Index) Allocator.Error!Builder.Value { _ = inst; const result = try self.wip.callIntrinsic(.normal, .none, .frameaddress, &.{.ptr}, &.{.@"0"}, ""); - return self.wip.cast(.ptrtoint, result, try self.lowerType(.usize), ""); + return self.wip.cast(.ptrtoint, result, try self.object.lowerType(.usize), ""); } fn airCmpxchg( @@ -4842,7 +4852,7 @@ fn airCmpxchg( var expected_value = try self.resolveInst(extra.expected_value); var new_value = try self.resolveInst(extra.new_value); const operand_ty = ptr_ty.childType(zcu); - const llvm_operand_ty = try self.lowerType(operand_ty); + const llvm_operand_ty = try o.lowerType(operand_ty); const llvm_abi_ty = try self.getAtomicAbiType(operand_ty, false); if (llvm_abi_ty != .none) { // operand needs widening and truncating @@ -4885,7 +4895,7 @@ fn airCmpxchg( const non_null_bit = try self.wip.not(success_bit, ""); const payload_align = operand_ty.abiAlignment(zcu).toLlvm(); - const alloca_inst = try self.buildAlloca(try self.lowerType(optional_ty), payload_align); + const alloca_inst = try self.buildAlloca(try o.lowerType(optional_ty), payload_align); // Payload is always the first field at offset 0, so address is `alloca_inst` _ = try self.wip.store(.normal, payload, alloca_inst, payload_align); @@ -4911,7 +4921,7 @@ fn airAtomicRmw(self: *FuncGen, inst: Air.Inst.Index) Allocator.Error!Builder.Va const op = toLlvmAtomicRmwBinOp(extra.op(), is_signed_int, is_float); const ordering = toLlvmAtomicOrdering(extra.ordering()); const llvm_abi_ty = try self.getAtomicAbiType(operand_ty, op == .xchg); - const llvm_operand_ty = try self.lowerType(operand_ty); + const llvm_operand_ty = try o.lowerType(operand_ty); const access_kind: Builder.MemoryAccessKind = if (ptr_ty.isVolatilePtr(zcu)) .@"volatile" else .normal; @@ -4954,7 +4964,7 @@ fn airAtomicRmw(self: *FuncGen, inst: Air.Inst.Index) Allocator.Error!Builder.Va access_kind, op, ptr, - try self.wip.cast(.ptrtoint, operand, try self.lowerType(.usize), ""), + try self.wip.cast(.ptrtoint, operand, try o.lowerType(.usize), ""), self.sync_scope, ordering, ptr_alignment, @@ -4963,7 +4973,8 @@ fn airAtomicRmw(self: *FuncGen, inst: Air.Inst.Index) Allocator.Error!Builder.Va } fn airAtomicLoad(self: *FuncGen, inst: Air.Inst.Index) Allocator.Error!Builder.Value { - const zcu = self.object.zcu; + const o = self.object; + const zcu = o.zcu; const atomic_load = self.air.instructions.items(.data)[@intFromEnum(inst)].atomic_load; const ptr = try self.resolveInst(atomic_load.ptr); const ptr_ty = self.typeOf(atomic_load.ptr); @@ -4978,7 +4989,7 @@ fn airAtomicLoad(self: *FuncGen, inst: Air.Inst.Index) Allocator.Error!Builder.V Type.fromInterned(info.child).abiAlignment(zcu)).toLlvm(); const access_kind: Builder.MemoryAccessKind = if (info.flags.is_volatile) .@"volatile" else .normal; - const elem_llvm_ty = try self.lowerType(elem_ty); + const elem_llvm_ty = try o.lowerType(elem_ty); self.maybeMarkAllowZeroAccess(info); @@ -5135,7 +5146,7 @@ fn airMemset(self: *FuncGen, inst: Air.Inst.Index, safety: bool) Allocator.Error const body_block = try self.wip.block(1, "InlineMemsetBody"); const end_block = try self.wip.block(1, "InlineMemsetEnd"); - const llvm_usize_ty = try self.lowerType(.usize); + const llvm_usize_ty = try o.lowerType(.usize); const end_ptr = switch (ptr_ty.ptrSize(zcu)) { .slice => try self.ptraddScaled( dest_ptr, @@ -5265,7 +5276,7 @@ fn airGetUnionTag(self: *FuncGen, inst: Air.Inst.Index) Allocator.Error!Builder. assert(layout.tag_size != 0); const union_ptr = try self.resolveInst(ty_op.operand); if (isByRef(un_ty, zcu)) { - const llvm_un_ty = try self.lowerType(un_ty); + const llvm_un_ty = try o.lowerType(un_ty); if (layout.payload_size == 0) return self.wip.load(.normal, llvm_un_ty, union_ptr, .default, ""); const tag_index = @intFromBool(layout.tag_align.compare(.lt, layout.payload_align)); @@ -5296,6 +5307,7 @@ fn airNeg(self: *FuncGen, inst: Air.Inst.Index, fast: Builder.FastMathKind) Allo } fn airClzCtz(self: *FuncGen, inst: Air.Inst.Index, intrinsic: Builder.Intrinsic) Allocator.Error!Builder.Value { + const o = self.object; const ty_op = self.air.instructions.items(.data)[@intFromEnum(inst)].ty_op; const inst_ty = self.typeOfIndex(inst); const operand_ty = self.typeOf(ty_op.operand); @@ -5305,14 +5317,15 @@ fn airClzCtz(self: *FuncGen, inst: Air.Inst.Index, intrinsic: Builder.Intrinsic) .normal, .none, intrinsic, - &.{try self.lowerType(operand_ty)}, + &.{try o.lowerType(operand_ty)}, &.{ operand, .false }, "", ); - return self.wip.conv(.unsigned, result, try self.lowerType(inst_ty), ""); + return self.wip.conv(.unsigned, result, try o.lowerType(inst_ty), ""); } fn airBitOp(self: *FuncGen, inst: Air.Inst.Index, intrinsic: Builder.Intrinsic) Allocator.Error!Builder.Value { + const o = self.object; const ty_op = self.air.instructions.items(.data)[@intFromEnum(inst)].ty_op; const inst_ty = self.typeOfIndex(inst); const operand_ty = self.typeOf(ty_op.operand); @@ -5322,11 +5335,11 @@ fn airBitOp(self: *FuncGen, inst: Air.Inst.Index, intrinsic: Builder.Intrinsic) .normal, .none, intrinsic, - &.{try self.lowerType(operand_ty)}, + &.{try o.lowerType(operand_ty)}, &.{operand}, "", ); - return self.wip.conv(.unsigned, result, try self.lowerType(inst_ty), ""); + return self.wip.conv(.unsigned, result, try o.lowerType(inst_ty), ""); } fn airByteSwap(self: *FuncGen, inst: Air.Inst.Index) Allocator.Error!Builder.Value { @@ -5339,7 +5352,7 @@ fn airByteSwap(self: *FuncGen, inst: Air.Inst.Index) Allocator.Error!Builder.Val const inst_ty = self.typeOfIndex(inst); var operand = try self.resolveInst(ty_op.operand); - var llvm_operand_ty = try self.lowerType(operand_ty); + var llvm_operand_ty = try o.lowerType(operand_ty); if (bits % 16 == 8) { // If not an even byte-multiple, we need zero-extend + shift-left 1 byte @@ -5360,7 +5373,7 @@ fn airByteSwap(self: *FuncGen, inst: Air.Inst.Index) Allocator.Error!Builder.Val const result = try self.wip.callIntrinsic(.normal, .none, .bswap, &.{llvm_operand_ty}, &.{operand}, ""); - return self.wip.conv(.unsigned, result, try self.lowerType(inst_ty), ""); + return self.wip.conv(.unsigned, result, try o.lowerType(inst_ty), ""); } fn airErrorSetHasValue(self: *FuncGen, inst: Air.Inst.Index) Allocator.Error!Builder.Value { @@ -5437,10 +5450,10 @@ fn airErrorName(self: *FuncGen, inst: Air.Inst.Index) Allocator.Error!Builder.Va const un_op = self.air.instructions.items(.data)[@intFromEnum(inst)].un_op; const operand = try self.resolveInst(un_op); const slice_ty = self.typeOfIndex(inst); - const slice_llvm_ty = try self.lowerType(slice_ty); + const slice_llvm_ty = try o.lowerType(slice_ty); // If operand is small (e.g. `u8`), then signedness becomes a problem -- GEP always treats the index as signed. - const operand_usize = try self.wip.conv(.unsigned, operand, try self.lowerType(.usize), ""); + const operand_usize = try self.wip.conv(.unsigned, operand, try o.lowerType(.usize), ""); const error_name_table_ptr = try o.getErrorNameTable(); const error_name_ptr = try self.ptraddScaled(error_name_table_ptr.toValue(&o.builder), operand_usize, slice_ty.abiSize(zcu)); @@ -5451,7 +5464,7 @@ fn airSplat(self: *FuncGen, inst: Air.Inst.Index) Allocator.Error!Builder.Value const ty_op = self.air.instructions.items(.data)[@intFromEnum(inst)].ty_op; const scalar = try self.resolveInst(ty_op.operand); const vector_ty = self.typeOfIndex(inst); - return self.wip.splatVector(try self.lowerType(vector_ty), scalar, ""); + return self.wip.splatVector(try self.object.lowerType(vector_ty), scalar, ""); } fn airSelect(self: *FuncGen, inst: Air.Inst.Index) Allocator.Error!Builder.Value { @@ -5474,9 +5487,9 @@ fn airShuffleOne(fg: *FuncGen, inst: Air.Inst.Index) Allocator.Error!Builder.Val const operand = try fg.resolveInst(unwrapped.operand); const mask = unwrapped.mask; const operand_ty = fg.typeOf(unwrapped.operand); - const llvm_operand_ty = try fg.lowerType(operand_ty); - const llvm_result_ty = try fg.lowerType(unwrapped.result_ty); - const llvm_elem_ty = try fg.lowerType(unwrapped.result_ty.childType(zcu)); + const llvm_operand_ty = try o.lowerType(operand_ty); + const llvm_result_ty = try o.lowerType(unwrapped.result_ty); + const llvm_elem_ty = try o.lowerType(unwrapped.result_ty.childType(zcu)); const llvm_poison_elem = try o.builder.poisonConst(llvm_elem_ty); const llvm_poison_mask_elem = try o.builder.poisonConst(.i32); const llvm_mask_ty = try o.builder.vectorType(.normal, @intCast(mask.len), .i32); @@ -5578,7 +5591,7 @@ fn airShuffleTwo(fg: *FuncGen, inst: Air.Inst.Index) Allocator.Error!Builder.Val const unwrapped = fg.air.unwrapShuffleTwo(zcu, inst); const mask = unwrapped.mask; - const llvm_elem_ty = try fg.lowerType(unwrapped.result_ty.childType(zcu)); + const llvm_elem_ty = try o.lowerType(unwrapped.result_ty.childType(zcu)); const llvm_mask_ty = try o.builder.vectorType(.normal, @intCast(mask.len), .i32); const llvm_poison_mask_elem = try o.builder.poisonConst(.i32); @@ -5670,7 +5683,7 @@ fn buildReducedCall( accum_init: Builder.Value, ) Allocator.Error!Builder.Value { const o = self.object; - const usize_ty = try self.lowerType(.usize); + const usize_ty = try o.lowerType(.usize); const llvm_vector_len = try o.builder.intValue(usize_ty, vector_len); const llvm_result_ty = accum_init.typeOfWip(&self.wip); @@ -5730,9 +5743,9 @@ fn airReduce(self: *FuncGen, inst: Air.Inst.Index, fast: Builder.FastMathKind) A const reduce = self.air.instructions.items(.data)[@intFromEnum(inst)].reduce; const operand = try self.resolveInst(reduce.operand); const operand_ty = self.typeOf(reduce.operand); - const llvm_operand_ty = try self.lowerType(operand_ty); + const llvm_operand_ty = try o.lowerType(operand_ty); const scalar_ty = self.typeOfIndex(inst); - const llvm_scalar_ty = try self.lowerType(scalar_ty); + const llvm_scalar_ty = try o.lowerType(scalar_ty); switch (reduce.operation) { .And, .Or, .Xor => return self.wip.callIntrinsic(.normal, .none, switch (reduce.operation) { @@ -5839,7 +5852,7 @@ fn airAggregateInit(self: *FuncGen, inst: Air.Inst.Index) Allocator.Error!Builde const result_ty = self.typeOfIndex(inst); const len: usize = @intCast(result_ty.arrayLen(zcu)); const elements: []const Air.Inst.Ref = @ptrCast(self.air.extra.items[ty_pl.payload..][0..len]); - const llvm_result_ty = try self.lowerType(result_ty); + const llvm_result_ty = try o.lowerType(result_ty); switch (result_ty.zigTypeTag(zcu)) { .vector => { @@ -5905,7 +5918,7 @@ fn airAggregateInit(self: *FuncGen, inst: Air.Inst.Index) Allocator.Error!Builde field_ptr_align.toLlvm(), llvm_field_val, field_ty.abiAlignment(zcu).toLlvm(), - try o.builder.intValue(try self.lowerType(.usize), field_ty.abiSize(zcu)), + try o.builder.intValue(try o.lowerType(.usize), field_ty.abiSize(zcu)), .normal, self.disable_intrinsics, ); @@ -5956,7 +5969,7 @@ fn airUnionInit(self: *FuncGen, inst: Air.Inst.Index) Allocator.Error!Builder.Va const ty_pl = self.air.instructions.items(.data)[@intFromEnum(inst)].ty_pl; const extra = self.air.extraData(Air.UnionInit, ty_pl.payload).data; const union_ty = self.typeOfIndex(inst); - const union_llvm_ty = try self.lowerType(union_ty); + const union_llvm_ty = try o.lowerType(union_ty); const union_obj = zcu.typeToUnion(union_ty).?; assert(union_obj.layout != .@"packed"); @@ -6046,8 +6059,7 @@ fn airAddrSpaceCast(self: *FuncGen, inst: Air.Inst.Index) Allocator.Error!Builde const ty_op = self.air.instructions.items(.data)[@intFromEnum(inst)].ty_op; const inst_ty = self.typeOfIndex(inst); const operand = try self.resolveInst(ty_op.operand); - - return self.wip.cast(.addrspacecast, operand, try self.lowerType(inst_ty), ""); + return self.wip.cast(.addrspacecast, operand, try self.object.lowerType(inst_ty), ""); } fn workIntrinsic( @@ -6192,7 +6204,7 @@ fn loadTruncate( const o = fg.object; const zcu = o.zcu; - const payload_llvm_ty = try fg.lowerType(payload_ty); + const payload_llvm_ty = try o.lowerType(payload_ty); const abi_size = payload_ty.abiSize(zcu); const load_llvm_ty = if (payload_ty.isAbiInt(zcu)) @@ -6220,7 +6232,7 @@ fn loadByRef( access_kind: Builder.MemoryAccessKind, ) Allocator.Error!Builder.Value { const o = fg.object; - const pointee_llvm_ty = try fg.lowerType(pointee_type); + const pointee_llvm_ty = try o.lowerType(pointee_type); const result_align = InternPool.Alignment.fromLlvm(ptr_alignment) .max(pointee_type.abiAlignment(o.zcu)).toLlvm(); const result_ptr = try fg.buildAlloca(pointee_llvm_ty, result_align); @@ -6230,7 +6242,7 @@ fn loadByRef( result_align, ptr, ptr_alignment, - try o.builder.intValue(try fg.lowerType(.usize), size_bytes), + try o.builder.intValue(try o.lowerType(.usize), size_bytes), access_kind, fg.disable_intrinsics, ); @@ -6274,7 +6286,7 @@ fn storeFull( if (info.flags.vector_index != .none) { const index_u32 = try o.builder.intValue(.i32, info.flags.vector_index); - const vec_elem_ty = try self.lowerType(elem_ty); + const vec_elem_ty = try o.lowerType(elem_ty); const vec_ty = try o.builder.vectorType(.normal, info.packed_offset.host_size, vec_elem_ty); const loaded_vector = try self.wip.load(.normal, vec_ty, ptr, ptr_alignment, ""); @@ -6343,7 +6355,7 @@ fn storeFull( ptr_alignment, elem, elem_ty.abiAlignment(zcu).toLlvm(), - try o.builder.intValue(try self.lowerType(.usize), elem_ty.abiSize(zcu)), + try o.builder.intValue(try o.lowerType(.usize), elem_ty.abiSize(zcu)), access_kind, self.disable_intrinsics, ); @@ -6370,7 +6382,7 @@ fn store( elem, elem_ty.abiAlignment(zcu).toLlvm(), try o.builder.intValue( - try fg.lowerType(.usize), + try o.lowerType(.usize), elem_ty.abiSize(zcu), ), .normal, @@ -6391,7 +6403,7 @@ fn store( fn valgrindMarkUndef(fg: *FuncGen, ptr: Builder.Value, len: Builder.Value) Allocator.Error!void { const VG_USERREQ__MAKE_MEM_UNDEFINED = 1296236545; const o = fg.object; - const usize_ty = try fg.lowerType(.usize); + const usize_ty = try o.lowerType(.usize); const zero = try o.builder.intValue(usize_ty, 0); const req = try o.builder.intValue(usize_ty, VG_USERREQ__MAKE_MEM_UNDEFINED); const ptr_as_usize = try fg.wip.cast(.ptrtoint, ptr, usize_ty, ""); @@ -6413,7 +6425,7 @@ fn valgrindClientRequest( const target = zcu.getTarget(); if (!target_util.hasValgrindSupport(target, .stage2_llvm)) return default_value; - const llvm_usize = try fg.lowerType(.usize); + const llvm_usize = try o.lowerType(.usize); const usize_alignment = Type.usize.abiAlignment(zcu).toLlvm(); const array_llvm_ty = try o.builder.arrayType(6, llvm_usize); @@ -7261,8 +7273,9 @@ fn getAtomicAbiType(fg: *const FuncGen, ty: Type, is_rmw_xchg: bool) Allocator.E fn ptraddConst(fg: *FuncGen, ptr: Builder.Value, offset: u64) Allocator.Error!Builder.Value { if (offset == 0) return ptr; - const llvm_usize_ty = try fg.lowerType(.usize); - const offset_val = try fg.object.builder.intValue(llvm_usize_ty, offset); + const o = fg.object; + const llvm_usize_ty = try o.lowerType(.usize); + const offset_val = try o.builder.intValue(llvm_usize_ty, offset); return fg.wip.gep(.inbounds, .i8, ptr, &.{offset_val}, ""); } fn ptraddScaled(fg: *FuncGen, ptr: Builder.Value, index: Builder.Value, scale: u64) Allocator.Error!Builder.Value {