diff options
| -rw-r--r-- | src/codegen/llvm.zig | 1823 |
1 files changed, 971 insertions, 852 deletions
diff --git a/src/codegen/llvm.zig b/src/codegen/llvm.zig index 78f8d28797..75b8a19e7d 100644 --- a/src/codegen/llvm.zig +++ b/src/codegen/llvm.zig @@ -568,20 +568,20 @@ pub const Object = struct { return slice.ptr; } - fn genErrorNameTable(self: *Object) !void { - // If self.error_name_table is null, there was no instruction that actually referenced the error table. - const error_name_table_ptr_global = self.error_name_table orelse return; + fn genErrorNameTable(o: *Object) !void { + // If o.error_name_table is null, there was no instruction that actually referenced the error table. + const error_name_table_ptr_global = o.error_name_table orelse return; - const mod = self.module; + const mod = o.module; const target = mod.getTarget(); - const llvm_ptr_ty = self.context.pointerType(0); // TODO: Address space - const llvm_usize_ty = self.context.intType(target.ptrBitWidth()); + const llvm_ptr_ty = o.context.pointerType(0); // TODO: Address space + const llvm_usize_ty = o.context.intType(target.ptrBitWidth()); const type_fields = [_]*llvm.Type{ llvm_ptr_ty, llvm_usize_ty, }; - const llvm_slice_ty = self.context.structType(&type_fields, type_fields.len, .False); + const llvm_slice_ty = o.context.structType(&type_fields, type_fields.len, .False); const slice_ty = Type.slice_const_u8_sentinel_0; const slice_alignment = slice_ty.abiAlignment(mod); @@ -592,8 +592,8 @@ pub const Object = struct { llvm_errors[0] = llvm_slice_ty.getUndef(); for (llvm_errors[1..], error_name_list[1..]) |*llvm_error, name_nts| { const name = mod.intern_pool.stringToSlice(name_nts); - const str_init = self.context.constString(name.ptr, @intCast(c_uint, name.len), .False); - const str_global = self.llvm_module.addGlobal(str_init.typeOf(), ""); + const str_init = o.context.constString(name.ptr, @intCast(c_uint, name.len), .False); + const str_global = o.llvm_module.addGlobal(str_init.typeOf(), ""); str_global.setInitializer(str_init); str_global.setLinkage(.Private); str_global.setGlobalConstant(.True); @@ -609,7 +609,7 @@ pub const Object = struct { const error_name_table_init = llvm_slice_ty.constArray(llvm_errors.ptr, @intCast(c_uint, error_name_list.len)); - const error_name_table_global = self.llvm_module.addGlobal(error_name_table_init.typeOf(), ""); + const error_name_table_global = o.llvm_module.addGlobal(error_name_table_init.typeOf(), ""); error_name_table_global.setInitializer(error_name_table_init); error_name_table_global.setLinkage(.Private); error_name_table_global.setGlobalConstant(.True); @@ -873,35 +873,32 @@ pub const Object = struct { const target = mod.getTarget(); var dg: DeclGen = .{ - .context = o.context, .object = o, - .module = mod, .decl_index = decl_index, .decl = decl, .err_msg = null, - .gpa = mod.gpa, }; - const llvm_func = try dg.resolveLlvmFunction(decl_index); + const llvm_func = try o.resolveLlvmFunction(decl_index); if (mod.align_stack_fns.get(func_index)) |align_info| { - dg.addFnAttrInt(llvm_func, "alignstack", align_info.alignment.toByteUnitsOptional().?); - dg.addFnAttr(llvm_func, "noinline"); + o.addFnAttrInt(llvm_func, "alignstack", align_info.alignment.toByteUnitsOptional().?); + o.addFnAttr(llvm_func, "noinline"); } else { - DeclGen.removeFnAttr(llvm_func, "alignstack"); - if (!func.is_noinline) DeclGen.removeFnAttr(llvm_func, "noinline"); + Object.removeFnAttr(llvm_func, "alignstack"); + if (!func.is_noinline) Object.removeFnAttr(llvm_func, "noinline"); } if (func.is_cold) { - dg.addFnAttr(llvm_func, "cold"); + o.addFnAttr(llvm_func, "cold"); } else { - DeclGen.removeFnAttr(llvm_func, "cold"); + Object.removeFnAttr(llvm_func, "cold"); } if (func.is_noinline) { - dg.addFnAttr(llvm_func, "noinline"); + o.addFnAttr(llvm_func, "noinline"); } else { - DeclGen.removeFnAttr(llvm_func, "noinline"); + Object.removeFnAttr(llvm_func, "noinline"); } // TODO: disable this if safety is off for the function scope @@ -909,15 +906,15 @@ pub const Object = struct { if (ssp_buf_size != 0) { var buf: [12]u8 = undefined; const arg = std.fmt.bufPrintZ(&buf, "{d}", .{ssp_buf_size}) catch unreachable; - dg.addFnAttr(llvm_func, "sspstrong"); - dg.addFnAttrString(llvm_func, "stack-protector-buffer-size", arg); + o.addFnAttr(llvm_func, "sspstrong"); + o.addFnAttrString(llvm_func, "stack-protector-buffer-size", arg); } // TODO: disable this if safety is off for the function scope if (mod.comp.bin_file.options.stack_check) { - dg.addFnAttrString(llvm_func, "probe-stack", "__zig_probe_stack"); + o.addFnAttrString(llvm_func, "probe-stack", "__zig_probe_stack"); } else if (target.os.tag == .uefi) { - dg.addFnAttrString(llvm_func, "no-stack-arg-probe", ""); + o.addFnAttrString(llvm_func, "no-stack-arg-probe", ""); } if (mod.intern_pool.stringToSliceUnwrap(decl.@"linksection")) |section| @@ -929,20 +926,20 @@ pub const Object = struct { bb.deleteBasicBlock(); } - const builder = dg.context.createBuilder(); + const builder = o.context.createBuilder(); - const entry_block = dg.context.appendBasicBlock(llvm_func, "Entry"); + const entry_block = o.context.appendBasicBlock(llvm_func, "Entry"); builder.positionBuilderAtEnd(entry_block); // This gets the LLVM values from the function and stores them in `dg.args`. const fn_info = mod.typeToFunc(decl.ty).?; const sret = firstParamSRet(fn_info, mod); const ret_ptr = if (sret) llvm_func.getParam(0) else null; - const gpa = dg.gpa; + const gpa = o.gpa; if (ccAbiPromoteInt(fn_info.cc, mod, fn_info.return_type.toType())) |s| switch (s) { - .signed => dg.addAttr(llvm_func, 0, "signext"), - .unsigned => dg.addAttr(llvm_func, 0, "zeroext"), + .signed => o.addAttr(llvm_func, 0, "signext"), + .unsigned => o.addAttr(llvm_func, 0, "zeroext"), }; const err_return_tracing = fn_info.return_type.toType().isError(mod) and @@ -961,7 +958,7 @@ pub const Object = struct { { var llvm_arg_i = @as(c_uint, @intFromBool(ret_ptr != null)) + @intFromBool(err_return_tracing); - var it = iterateParamTypes(&dg, fn_info); + var it = iterateParamTypes(o, fn_info); while (it.next()) |lowering| switch (lowering) { .no_bits => continue, .byval => { @@ -974,24 +971,24 @@ pub const Object = struct { if (isByRef(param_ty, mod)) { const alignment = param_ty.abiAlignment(mod); const param_llvm_ty = param.typeOf(); - const arg_ptr = buildAllocaInner(dg.context, builder, llvm_func, false, param_llvm_ty, alignment, target); + const arg_ptr = buildAllocaInner(o.context, builder, llvm_func, false, param_llvm_ty, alignment, target); const store_inst = builder.buildStore(param, arg_ptr); store_inst.setAlignment(alignment); args.appendAssumeCapacity(arg_ptr); } else { args.appendAssumeCapacity(param); - dg.addByValParamAttrs(llvm_func, param_ty, param_index, fn_info, llvm_arg_i); + o.addByValParamAttrs(llvm_func, param_ty, param_index, fn_info, llvm_arg_i); } llvm_arg_i += 1; }, .byref => { const param_ty = fn_info.param_types[it.zig_index - 1].toType(); - const param_llvm_ty = try dg.lowerType(param_ty); + const param_llvm_ty = try o.lowerType(param_ty); const param = llvm_func.getParam(llvm_arg_i); const alignment = param_ty.abiAlignment(mod); - dg.addByRefParamAttrs(llvm_func, llvm_arg_i, alignment, it.byval_attr, param_llvm_ty); + o.addByRefParamAttrs(llvm_func, llvm_arg_i, alignment, it.byval_attr, param_llvm_ty); llvm_arg_i += 1; try args.ensureUnusedCapacity(1); @@ -1006,11 +1003,11 @@ pub const Object = struct { }, .byref_mut => { const param_ty = fn_info.param_types[it.zig_index - 1].toType(); - const param_llvm_ty = try dg.lowerType(param_ty); + const param_llvm_ty = try o.lowerType(param_ty); const param = llvm_func.getParam(llvm_arg_i); const alignment = param_ty.abiAlignment(mod); - dg.addArgAttr(llvm_func, llvm_arg_i, "noundef"); + o.addArgAttr(llvm_func, llvm_arg_i, "noundef"); llvm_arg_i += 1; try args.ensureUnusedCapacity(1); @@ -1029,14 +1026,14 @@ pub const Object = struct { const param = llvm_func.getParam(llvm_arg_i); llvm_arg_i += 1; - const param_llvm_ty = try dg.lowerType(param_ty); + const param_llvm_ty = try o.lowerType(param_ty); const abi_size = @intCast(c_uint, param_ty.abiSize(mod)); - const int_llvm_ty = dg.context.intType(abi_size * 8); + const int_llvm_ty = o.context.intType(abi_size * 8); const alignment = @max( param_ty.abiAlignment(mod), - dg.object.target_data.abiAlignmentOfType(int_llvm_ty), + o.target_data.abiAlignmentOfType(int_llvm_ty), ); - const arg_ptr = buildAllocaInner(dg.context, builder, llvm_func, false, param_llvm_ty, alignment, target); + const arg_ptr = buildAllocaInner(o.context, builder, llvm_func, false, param_llvm_ty, alignment, target); const store_inst = builder.buildStore(param, arg_ptr); store_inst.setAlignment(alignment); @@ -1057,24 +1054,24 @@ pub const Object = struct { 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"); + o.addArgAttr(llvm_func, llvm_arg_i, "noalias"); } } if (param_ty.zigTypeTag(mod) != .Optional) { - dg.addArgAttr(llvm_func, llvm_arg_i, "nonnull"); + o.addArgAttr(llvm_func, llvm_arg_i, "nonnull"); } if (ptr_info.flags.is_const) { - dg.addArgAttr(llvm_func, llvm_arg_i, "readonly"); + o.addArgAttr(llvm_func, llvm_arg_i, "readonly"); } const elem_align = ptr_info.flags.alignment.toByteUnitsOptional() orelse @max(ptr_info.child.toType().abiAlignment(mod), 1); - dg.addArgAttrInt(llvm_func, llvm_arg_i, "align", elem_align); + o.addArgAttrInt(llvm_func, llvm_arg_i, "align", elem_align); const ptr_param = llvm_func.getParam(llvm_arg_i); llvm_arg_i += 1; const len_param = llvm_func.getParam(llvm_arg_i); llvm_arg_i += 1; - const slice_llvm_ty = try dg.lowerType(param_ty); + const slice_llvm_ty = try o.lowerType(param_ty); const partial = builder.buildInsertValue(slice_llvm_ty.getUndef(), ptr_param, 0, ""); const aggregate = builder.buildInsertValue(partial, len_param, 1, ""); try args.append(aggregate); @@ -1083,10 +1080,10 @@ pub const Object = struct { assert(!it.byval_attr); const field_types = it.llvm_types_buffer[0..it.llvm_types_len]; const param_ty = fn_info.param_types[it.zig_index - 1].toType(); - const param_llvm_ty = try dg.lowerType(param_ty); + const param_llvm_ty = try o.lowerType(param_ty); const param_alignment = param_ty.abiAlignment(mod); - const arg_ptr = buildAllocaInner(dg.context, builder, llvm_func, false, param_llvm_ty, param_alignment, target); - const llvm_ty = dg.context.structType(field_types.ptr, @intCast(c_uint, field_types.len), .False); + const arg_ptr = buildAllocaInner(o.context, builder, llvm_func, false, param_llvm_ty, param_alignment, target); + const llvm_ty = o.context.structType(field_types.ptr, @intCast(c_uint, field_types.len), .False); for (field_types, 0..) |_, field_i_usize| { const field_i = @intCast(c_uint, field_i_usize); const param = llvm_func.getParam(llvm_arg_i); @@ -1108,18 +1105,18 @@ pub const Object = struct { assert(!it.byval_attr); const param = llvm_func.getParam(llvm_arg_i); llvm_arg_i += 1; - const casted = builder.buildBitCast(param, dg.context.halfType(), ""); + const casted = builder.buildBitCast(param, o.context.halfType(), ""); try args.ensureUnusedCapacity(1); args.appendAssumeCapacity(casted); }, .float_array => { const param_ty = fn_info.param_types[it.zig_index - 1].toType(); - const param_llvm_ty = try dg.lowerType(param_ty); + const param_llvm_ty = try o.lowerType(param_ty); const param = llvm_func.getParam(llvm_arg_i); llvm_arg_i += 1; const alignment = param_ty.abiAlignment(mod); - const arg_ptr = buildAllocaInner(dg.context, builder, llvm_func, false, param_llvm_ty, alignment, target); + const arg_ptr = buildAllocaInner(o.context, builder, llvm_func, false, param_llvm_ty, alignment, target); _ = builder.buildStore(param, arg_ptr); if (isByRef(param_ty, mod)) { @@ -1132,12 +1129,12 @@ pub const Object = struct { }, .i32_array, .i64_array => { const param_ty = fn_info.param_types[it.zig_index - 1].toType(); - const param_llvm_ty = try dg.lowerType(param_ty); + const param_llvm_ty = try o.lowerType(param_ty); const param = llvm_func.getParam(llvm_arg_i); llvm_arg_i += 1; const alignment = param_ty.abiAlignment(mod); - const arg_ptr = buildAllocaInner(dg.context, builder, llvm_func, false, param_llvm_ty, alignment, target); + const arg_ptr = buildAllocaInner(o.context, builder, llvm_func, false, param_llvm_ty, alignment, target); _ = builder.buildStore(param, arg_ptr); if (isByRef(param_ty, mod)) { @@ -1154,8 +1151,8 @@ pub const Object = struct { var di_file: ?*llvm.DIFile = null; var di_scope: ?*llvm.DIScope = null; - if (dg.object.di_builder) |dib| { - di_file = try dg.object.getDIFile(gpa, mod.namespacePtr(decl.src_namespace).file_scope); + if (o.di_builder) |dib| { + di_file = try o.getDIFile(gpa, mod.namespacePtr(decl.src_namespace).file_scope); const line_number = decl.src_line + 1; const is_internal_linkage = decl.val.getExternFunc(mod) == null and @@ -1179,7 +1176,7 @@ pub const Object = struct { mod.comp.bin_file.options.optimize_mode != .Debug, null, // decl_subprogram ); - try dg.object.di_map.put(gpa, decl, subprogram.toNode()); + try o.di_map.put(gpa, decl, subprogram.toNode()); llvm_func.fnSetSubprogram(subprogram); @@ -1190,7 +1187,7 @@ pub const Object = struct { .gpa = gpa, .air = air, .liveness = liveness, - .context = dg.context, + .context = o.context, .dg = &dg, .builder = builder, .ret_ptr = ret_ptr, @@ -1225,13 +1222,10 @@ pub const Object = struct { pub fn updateDecl(self: *Object, module: *Module, decl_index: Module.Decl.Index) !void { const decl = module.declPtr(decl_index); var dg: DeclGen = .{ - .context = self.context, .object = self, - .module = module, .decl = decl, .decl_index = decl_index, .err_msg = null, - .gpa = module.gpa, }; dg.genDecl() catch |err| switch (err) { error.CodegenFail => { @@ -2421,117 +2415,16 @@ pub const Object = struct { try ty.print(buffer.writer(), o.module); return buffer.toOwnedSliceSentinel(0); } -}; - -pub const DeclGen = struct { - context: *llvm.Context, - object: *Object, - module: *Module, - decl: *Module.Decl, - decl_index: Module.Decl.Index, - gpa: Allocator, - err_msg: ?*Module.ErrorMsg, - - fn todo(self: *DeclGen, comptime format: []const u8, args: anytype) Error { - @setCold(true); - assert(self.err_msg == null); - const mod = self.module; - const src_loc = LazySrcLoc.nodeOffset(0).toSrcLoc(self.decl, mod); - self.err_msg = try Module.ErrorMsg.create(self.gpa, src_loc, "TODO (LLVM): " ++ format, args); - return error.CodegenFail; - } - - fn llvmModule(self: *DeclGen) *llvm.Module { - return self.object.llvm_module; - } - - fn genDecl(dg: *DeclGen) !void { - const mod = dg.module; - const decl = dg.decl; - const decl_index = dg.decl_index; - assert(decl.has_tv); - - if (decl.val.getExternFunc(mod)) |extern_func| { - _ = try dg.resolveLlvmFunction(extern_func.decl); - } else { - const target = mod.getTarget(); - var global = try dg.resolveGlobalDecl(decl_index); - global.setAlignment(decl.getAlignment(mod)); - if (mod.intern_pool.stringToSliceUnwrap(decl.@"linksection")) |s| global.setSection(s); - assert(decl.has_tv); - const init_val = if (decl.val.getVariable(mod)) |variable| init_val: { - break :init_val variable.init; - } else init_val: { - global.setGlobalConstant(.True); - break :init_val decl.val.toIntern(); - }; - if (init_val != .none) { - const llvm_init = try dg.lowerValue(.{ .ty = decl.ty, .val = init_val.toValue() }); - if (global.globalGetValueType() == llvm_init.typeOf()) { - global.setInitializer(llvm_init); - } else { - // LLVM does not allow us to change the type of globals. So we must - // create a new global with the correct type, copy all its attributes, - // and then update all references to point to the new global, - // delete the original, and rename the new one to the old one's name. - // This is necessary because LLVM does not support const bitcasting - // a struct with padding bytes, which is needed to lower a const union value - // to LLVM, when a field other than the most-aligned is active. Instead, - // we must lower to an unnamed struct, and pointer cast at usage sites - // of the global. Such an unnamed struct is the cause of the global type - // mismatch, because we don't have the LLVM type until the *value* is created, - // whereas the global needs to be created based on the type alone, because - // lowering the value may reference the global as a pointer. - const llvm_global_addrspace = toLlvmGlobalAddressSpace(decl.@"addrspace", target); - const new_global = dg.object.llvm_module.addGlobalInAddressSpace( - llvm_init.typeOf(), - "", - llvm_global_addrspace, - ); - new_global.setLinkage(global.getLinkage()); - new_global.setUnnamedAddr(global.getUnnamedAddress()); - new_global.setAlignment(global.getAlignment()); - if (mod.intern_pool.stringToSliceUnwrap(decl.@"linksection")) |s| - new_global.setSection(s); - new_global.setInitializer(llvm_init); - // TODO: How should this work then the address space of a global changed? - global.replaceAllUsesWith(new_global); - dg.object.decl_map.putAssumeCapacity(decl_index, new_global); - new_global.takeName(global); - global.deleteGlobal(); - global = new_global; - } - } - - if (dg.object.di_builder) |dib| { - const di_file = try dg.object.getDIFile(dg.gpa, mod.namespacePtr(decl.src_namespace).file_scope); - - const line_number = decl.src_line + 1; - const is_internal_linkage = !dg.module.decl_exports.contains(decl_index); - const di_global = dib.createGlobalVariableExpression( - di_file.toScope(), - mod.intern_pool.stringToSlice(decl.name), - global.getValueName(), - di_file, - line_number, - try dg.object.lowerDebugType(decl.ty, .full), - is_internal_linkage, - ); - - try dg.object.di_map.put(dg.gpa, dg.decl, di_global.getVariable().toNode()); - if (!is_internal_linkage or decl.isExtern(mod)) global.attachMetaData(di_global); - } - } - } /// If the llvm function does not exist, create it. /// Note that this can be called before the function's semantic analysis has /// completed, so if any attributes rely on that, they must be done in updateFunc, not here. - fn resolveLlvmFunction(dg: *DeclGen, decl_index: Module.Decl.Index) !*llvm.Value { - const mod = dg.module; + fn resolveLlvmFunction(o: *Object, decl_index: Module.Decl.Index) !*llvm.Value { + const mod = o.module; + const gpa = o.gpa; const decl = mod.declPtr(decl_index); const zig_fn_type = decl.ty; - const gop = try dg.object.decl_map.getOrPut(dg.gpa, decl_index); + const gop = try o.decl_map.getOrPut(gpa, decl_index); if (gop.found_existing) return gop.value_ptr.*; assert(decl.has_tv); @@ -2539,12 +2432,12 @@ pub const DeclGen = struct { const target = mod.getTarget(); const sret = firstParamSRet(fn_info, mod); - const fn_type = try dg.lowerType(zig_fn_type); + const fn_type = try o.lowerType(zig_fn_type); const fqn = try decl.getFullyQualifiedName(mod); const llvm_addrspace = toLlvmAddressSpace(decl.@"addrspace", target); - const llvm_fn = dg.llvmModule().addFunctionInAddressSpace(mod.intern_pool.stringToSlice(fqn), fn_type, llvm_addrspace); + const llvm_fn = o.llvm_module.addFunctionInAddressSpace(mod.intern_pool.stringToSlice(fqn), fn_type, llvm_addrspace); gop.value_ptr.* = llvm_fn; const is_extern = decl.isExtern(mod); @@ -2553,20 +2446,20 @@ pub const DeclGen = struct { llvm_fn.setUnnamedAddr(.True); } else { if (target.isWasm()) { - dg.addFnAttrString(llvm_fn, "wasm-import-name", mod.intern_pool.stringToSlice(decl.name)); + o.addFnAttrString(llvm_fn, "wasm-import-name", mod.intern_pool.stringToSlice(decl.name)); if (mod.intern_pool.stringToSliceUnwrap(decl.getOwnedExternFunc(mod).?.lib_name)) |lib_name| { if (!std.mem.eql(u8, lib_name, "c")) { - dg.addFnAttrString(llvm_fn, "wasm-import-module", lib_name); + o.addFnAttrString(llvm_fn, "wasm-import-module", lib_name); } } } } if (sret) { - dg.addArgAttr(llvm_fn, 0, "nonnull"); // Sret pointers must not be address 0 - dg.addArgAttr(llvm_fn, 0, "noalias"); + o.addArgAttr(llvm_fn, 0, "nonnull"); // Sret pointers must not be address 0 + o.addArgAttr(llvm_fn, 0, "noalias"); - const raw_llvm_ret_ty = try dg.lowerType(fn_info.return_type.toType()); + const raw_llvm_ret_ty = try o.lowerType(fn_info.return_type.toType()); llvm_fn.addSretAttr(raw_llvm_ret_ty); } @@ -2574,7 +2467,7 @@ pub const DeclGen = struct { mod.comp.bin_file.options.error_return_tracing; if (err_return_tracing) { - dg.addArgAttr(llvm_fn, @intFromBool(sret), "nonnull"); + o.addArgAttr(llvm_fn, @intFromBool(sret), "nonnull"); } switch (fn_info.cc) { @@ -2582,7 +2475,7 @@ pub const DeclGen = struct { llvm_fn.setFunctionCallConv(.Fast); }, .Naked => { - dg.addFnAttr(llvm_fn, "naked"); + o.addFnAttr(llvm_fn, "naked"); }, .Async => { llvm_fn.setFunctionCallConv(.Fast); @@ -2598,16 +2491,16 @@ pub const DeclGen = struct { } // Function attributes that are independent of analysis results of the function body. - dg.addCommonFnAttributes(llvm_fn); + o.addCommonFnAttributes(llvm_fn); if (fn_info.return_type == .noreturn_type) { - dg.addFnAttr(llvm_fn, "noreturn"); + o.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); + var it = iterateParamTypes(o, fn_info); it.llvm_index += @intFromBool(sret); it.llvm_index += @intFromBool(err_return_tracing); while (it.next()) |lowering| switch (lowering) { @@ -2615,17 +2508,17 @@ pub const DeclGen = struct { const param_index = it.zig_index - 1; const param_ty = fn_info.param_types[param_index].toType(); if (!isByRef(param_ty, mod)) { - dg.addByValParamAttrs(llvm_fn, param_ty, param_index, fn_info, it.llvm_index - 1); + o.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.toType()); + const param_llvm_ty = try o.lowerType(param_ty.toType()); const alignment = param_ty.toType().abiAlignment(mod); - dg.addByRefParamAttrs(llvm_fn, it.llvm_index - 1, alignment, it.byval_attr, param_llvm_ty); + o.addByRefParamAttrs(llvm_fn, it.llvm_index - 1, alignment, it.byval_attr, param_llvm_ty); }, .byref_mut => { - dg.addArgAttr(llvm_fn, it.llvm_index - 1, "noundef"); + o.addArgAttr(llvm_fn, it.llvm_index - 1, "noundef"); }, // No attributes needed for these. .no_bits, @@ -2645,20 +2538,20 @@ pub const DeclGen = struct { return llvm_fn; } - fn addCommonFnAttributes(dg: *DeclGen, llvm_fn: *llvm.Value) void { - const comp = dg.module.comp; + fn addCommonFnAttributes(o: *Object, llvm_fn: *llvm.Value) void { + const comp = o.module.comp; if (!comp.bin_file.options.red_zone) { - dg.addFnAttr(llvm_fn, "noredzone"); + o.addFnAttr(llvm_fn, "noredzone"); } if (comp.bin_file.options.omit_frame_pointer) { - dg.addFnAttrString(llvm_fn, "frame-pointer", "none"); + o.addFnAttrString(llvm_fn, "frame-pointer", "none"); } else { - dg.addFnAttrString(llvm_fn, "frame-pointer", "all"); + o.addFnAttrString(llvm_fn, "frame-pointer", "all"); } - dg.addFnAttr(llvm_fn, "nounwind"); + o.addFnAttr(llvm_fn, "nounwind"); if (comp.unwind_tables) { - dg.addFnAttrInt(llvm_fn, "uwtable", 2); + o.addFnAttrInt(llvm_fn, "uwtable", 2); } if (comp.bin_file.options.skip_linker_dependencies or comp.bin_file.options.no_builtin) @@ -2668,14 +2561,14 @@ pub const DeclGen = struct { // and llvm detects that the body is equivalent to memcpy, it may replace the // body of memcpy with a call to memcpy, which would then cause a stack // overflow instead of performing memcpy. - dg.addFnAttr(llvm_fn, "nobuiltin"); + o.addFnAttr(llvm_fn, "nobuiltin"); } if (comp.bin_file.options.optimize_mode == .ReleaseSmall) { - dg.addFnAttr(llvm_fn, "minsize"); - dg.addFnAttr(llvm_fn, "optsize"); + o.addFnAttr(llvm_fn, "minsize"); + o.addFnAttr(llvm_fn, "optsize"); } if (comp.bin_file.options.tsan) { - dg.addFnAttr(llvm_fn, "sanitize_thread"); + o.addFnAttr(llvm_fn, "sanitize_thread"); } if (comp.getTarget().cpu.model.llvm_name) |s| { llvm_fn.addFunctionAttr("target-cpu", s); @@ -2688,21 +2581,21 @@ pub const DeclGen = struct { } } - fn resolveGlobalDecl(dg: *DeclGen, decl_index: Module.Decl.Index) Error!*llvm.Value { - const gop = try dg.object.decl_map.getOrPut(dg.gpa, decl_index); + fn resolveGlobalDecl(o: *Object, decl_index: Module.Decl.Index) Error!*llvm.Value { + const gop = try o.decl_map.getOrPut(o.gpa, decl_index); if (gop.found_existing) return gop.value_ptr.*; - errdefer assert(dg.object.decl_map.remove(decl_index)); + errdefer assert(o.decl_map.remove(decl_index)); - const mod = dg.module; + const mod = o.module; const decl = mod.declPtr(decl_index); const fqn = try decl.getFullyQualifiedName(mod); const target = mod.getTarget(); - const llvm_type = try dg.lowerType(decl.ty); + const llvm_type = try o.lowerType(decl.ty); const llvm_actual_addrspace = toLlvmGlobalAddressSpace(decl.@"addrspace", target); - const llvm_global = dg.object.llvm_module.addGlobalInAddressSpace( + const llvm_global = o.llvm_module.addGlobalInAddressSpace( llvm_type, mod.intern_pool.stringToSlice(fqn), llvm_actual_addrspace, @@ -2731,128 +2624,128 @@ pub const DeclGen = struct { return llvm_global; } - fn isUnnamedType(dg: *DeclGen, ty: Type, val: *llvm.Value) bool { + fn isUnnamedType(o: *Object, ty: Type, val: *llvm.Value) bool { // Once `lowerType` succeeds, successive calls to it with the same Zig type // are guaranteed to succeed. So if a call to `lowerType` fails here it means // it is the first time lowering the type, which means the value can't possible // have that type. - const llvm_ty = dg.lowerType(ty) catch return true; + const llvm_ty = o.lowerType(ty) catch return true; return val.typeOf() != llvm_ty; } - fn lowerType(dg: *DeclGen, t: Type) Allocator.Error!*llvm.Type { - const llvm_ty = try lowerTypeInner(dg, t); - const mod = dg.module; + fn lowerType(o: *Object, t: Type) Allocator.Error!*llvm.Type { + const llvm_ty = try lowerTypeInner(o, t); + const mod = o.module; if (std.debug.runtime_safety and false) check: { if (t.zigTypeTag(mod) == .Opaque) break :check; if (!t.hasRuntimeBits(mod)) break :check; if (!llvm_ty.isSized().toBool()) break :check; const zig_size = t.abiSize(mod); - const llvm_size = dg.object.target_data.abiSizeOfType(llvm_ty); + const llvm_size = o.target_data.abiSizeOfType(llvm_ty); if (llvm_size != zig_size) { log.err("when lowering {}, Zig ABI size = {d} but LLVM ABI size = {d}", .{ - t.fmt(dg.module), zig_size, llvm_size, + t.fmt(o.module), zig_size, llvm_size, }); } } return llvm_ty; } - fn lowerTypeInner(dg: *DeclGen, t: Type) Allocator.Error!*llvm.Type { - const gpa = dg.gpa; - const mod = dg.module; + fn lowerTypeInner(o: *Object, t: Type) Allocator.Error!*llvm.Type { + const gpa = o.gpa; + const mod = o.module; const target = mod.getTarget(); switch (t.zigTypeTag(mod)) { - .Void, .NoReturn => return dg.context.voidType(), + .Void, .NoReturn => return o.context.voidType(), .Int => { const info = t.intInfo(mod); assert(info.bits != 0); - return dg.context.intType(info.bits); + return o.context.intType(info.bits); }, .Enum => { const int_ty = t.intTagType(mod); const bit_count = int_ty.intInfo(mod).bits; assert(bit_count != 0); - return dg.context.intType(bit_count); + return o.context.intType(bit_count); }, .Float => switch (t.floatBits(target)) { - 16 => return if (backendSupportsF16(target)) dg.context.halfType() else dg.context.intType(16), - 32 => return dg.context.floatType(), - 64 => return dg.context.doubleType(), - 80 => return if (backendSupportsF80(target)) dg.context.x86FP80Type() else dg.context.intType(80), - 128 => return dg.context.fp128Type(), + 16 => return if (backendSupportsF16(target)) o.context.halfType() else o.context.intType(16), + 32 => return o.context.floatType(), + 64 => return o.context.doubleType(), + 80 => return if (backendSupportsF80(target)) o.context.x86FP80Type() else o.context.intType(80), + 128 => return o.context.fp128Type(), else => unreachable, }, - .Bool => return dg.context.intType(1), + .Bool => return o.context.intType(1), .Pointer => { if (t.isSlice(mod)) { const ptr_type = t.slicePtrFieldType(mod); const fields: [2]*llvm.Type = .{ - try dg.lowerType(ptr_type), - try dg.lowerType(Type.usize), + try o.lowerType(ptr_type), + try o.lowerType(Type.usize), }; - return dg.context.structType(&fields, fields.len, .False); + return o.context.structType(&fields, fields.len, .False); } const ptr_info = t.ptrInfo(mod); const llvm_addrspace = toLlvmAddressSpace(ptr_info.flags.address_space, target); - return dg.context.pointerType(llvm_addrspace); + return o.context.pointerType(llvm_addrspace); }, .Opaque => { - if (t.toIntern() == .anyopaque_type) return dg.context.intType(8); + if (t.toIntern() == .anyopaque_type) return o.context.intType(8); - const gop = try dg.object.type_map.getOrPut(gpa, t.toIntern()); + const gop = try o.type_map.getOrPut(gpa, t.toIntern()); if (gop.found_existing) return gop.value_ptr.*; const opaque_type = mod.intern_pool.indexToKey(t.toIntern()).opaque_type; const name = mod.intern_pool.stringToSlice(try mod.opaqueFullyQualifiedName(opaque_type)); - const llvm_struct_ty = dg.context.structCreateNamed(name); + const llvm_struct_ty = o.context.structCreateNamed(name); gop.value_ptr.* = llvm_struct_ty; // must be done before any recursive calls return llvm_struct_ty; }, .Array => { const elem_ty = t.childType(mod); if (std.debug.runtime_safety) assert((try elem_ty.onePossibleValue(mod)) == null); - const elem_llvm_ty = try dg.lowerType(elem_ty); + const elem_llvm_ty = try o.lowerType(elem_ty); const total_len = t.arrayLen(mod) + @intFromBool(t.sentinel(mod) != null); return elem_llvm_ty.arrayType(@intCast(c_uint, total_len)); }, .Vector => { - const elem_type = try dg.lowerType(t.childType(mod)); + const elem_type = try o.lowerType(t.childType(mod)); return elem_type.vectorType(t.vectorLen(mod)); }, .Optional => { const child_ty = t.optionalChild(mod); if (!child_ty.hasRuntimeBitsIgnoreComptime(mod)) { - return dg.context.intType(8); + return o.context.intType(8); } - const payload_llvm_ty = try dg.lowerType(child_ty); + const payload_llvm_ty = try o.lowerType(child_ty); if (t.optionalReprIsPayload(mod)) { return payload_llvm_ty; } comptime assert(optional_layout_version == 3); var fields_buf: [3]*llvm.Type = .{ - payload_llvm_ty, dg.context.intType(8), undefined, + payload_llvm_ty, o.context.intType(8), undefined, }; const offset = child_ty.abiSize(mod) + 1; const abi_size = t.abiSize(mod); const padding = @intCast(c_uint, abi_size - offset); if (padding == 0) { - return dg.context.structType(&fields_buf, 2, .False); + return o.context.structType(&fields_buf, 2, .False); } - fields_buf[2] = dg.context.intType(8).arrayType(padding); - return dg.context.structType(&fields_buf, 3, .False); + fields_buf[2] = o.context.intType(8).arrayType(padding); + return o.context.structType(&fields_buf, 3, .False); }, .ErrorUnion => { const payload_ty = t.errorUnionPayload(mod); if (!payload_ty.hasRuntimeBitsIgnoreComptime(mod)) { - return try dg.lowerType(Type.anyerror); + return try o.lowerType(Type.anyerror); } - const llvm_error_type = try dg.lowerType(Type.anyerror); - const llvm_payload_type = try dg.lowerType(payload_ty); + const llvm_error_type = try o.lowerType(Type.anyerror); + const llvm_payload_type = try o.lowerType(payload_ty); const payload_align = payload_ty.abiAlignment(mod); const error_align = Type.anyerror.abiAlignment(mod); @@ -2870,10 +2763,10 @@ pub const DeclGen = struct { const abi_size = std.mem.alignForward(u64, payload_end, error_align); const padding = @intCast(c_uint, abi_size - payload_end); if (padding == 0) { - return dg.context.structType(&fields_buf, 2, .False); + return o.context.structType(&fields_buf, 2, .False); } - fields_buf[2] = dg.context.intType(8).arrayType(padding); - return dg.context.structType(&fields_buf, 3, .False); + fields_buf[2] = o.context.intType(8).arrayType(padding); + return o.context.structType(&fields_buf, 3, .False); } else { fields_buf[0] = llvm_payload_type; fields_buf[1] = llvm_error_type; @@ -2883,20 +2776,20 @@ pub const DeclGen = struct { const abi_size = std.mem.alignForward(u64, error_end, payload_align); const padding = @intCast(c_uint, abi_size - error_end); if (padding == 0) { - return dg.context.structType(&fields_buf, 2, .False); + return o.context.structType(&fields_buf, 2, .False); } - fields_buf[2] = dg.context.intType(8).arrayType(padding); - return dg.context.structType(&fields_buf, 3, .False); + fields_buf[2] = o.context.intType(8).arrayType(padding); + return o.context.structType(&fields_buf, 3, .False); } }, - .ErrorSet => return dg.context.intType(16), + .ErrorSet => return o.context.intType(16), .Struct => { - const gop = try dg.object.type_map.getOrPut(gpa, t.toIntern()); + const gop = try o.type_map.getOrPut(gpa, t.toIntern()); if (gop.found_existing) return gop.value_ptr.*; const struct_type = switch (mod.intern_pool.indexToKey(t.toIntern())) { .anon_struct_type => |tuple| { - const llvm_struct_ty = dg.context.structCreateNamed(""); + const llvm_struct_ty = o.context.structCreateNamed(""); gop.value_ptr.* = llvm_struct_ty; // must be done before any recursive calls var llvm_field_types: std.ArrayListUnmanaged(*llvm.Type) = .{}; @@ -2918,10 +2811,10 @@ pub const DeclGen = struct { const padding_len = offset - prev_offset; if (padding_len > 0) { - const llvm_array_ty = dg.context.intType(8).arrayType(@intCast(c_uint, padding_len)); + const llvm_array_ty = o.context.intType(8).arrayType(@intCast(c_uint, padding_len)); try llvm_field_types.append(gpa, llvm_array_ty); } - const field_llvm_ty = try dg.lowerType(field_ty.toType()); + const field_llvm_ty = try o.lowerType(field_ty.toType()); try llvm_field_types.append(gpa, field_llvm_ty); offset += field_ty.toType().abiSize(mod); @@ -2931,7 +2824,7 @@ pub const DeclGen = struct { offset = std.mem.alignForward(u64, offset, big_align); const padding_len = offset - prev_offset; if (padding_len > 0) { - const llvm_array_ty = dg.context.intType(8).arrayType(@intCast(c_uint, padding_len)); + const llvm_array_ty = o.context.intType(8).arrayType(@intCast(c_uint, padding_len)); try llvm_field_types.append(gpa, llvm_array_ty); } } @@ -2952,14 +2845,14 @@ pub const DeclGen = struct { if (struct_obj.layout == .Packed) { assert(struct_obj.haveLayout()); - const int_llvm_ty = try dg.lowerType(struct_obj.backing_int_ty); + const int_llvm_ty = try o.lowerType(struct_obj.backing_int_ty); gop.value_ptr.* = int_llvm_ty; return int_llvm_ty; } const name = mod.intern_pool.stringToSlice(try struct_obj.getFullyQualifiedName(mod)); - const llvm_struct_ty = dg.context.structCreateNamed(name); + const llvm_struct_ty = o.context.structCreateNamed(name); gop.value_ptr.* = llvm_struct_ty; // must be done before any recursive calls assert(struct_obj.haveFieldTypes()); @@ -2987,10 +2880,10 @@ pub const DeclGen = struct { const padding_len = offset - prev_offset; if (padding_len > 0) { - const llvm_array_ty = dg.context.intType(8).arrayType(@intCast(c_uint, padding_len)); + const llvm_array_ty = o.context.intType(8).arrayType(@intCast(c_uint, padding_len)); try llvm_field_types.append(gpa, llvm_array_ty); } - const field_llvm_ty = try dg.lowerType(field.ty); + const field_llvm_ty = try o.lowerType(field.ty); try llvm_field_types.append(gpa, field_llvm_ty); offset += field.ty.abiSize(mod); @@ -3000,7 +2893,7 @@ pub const DeclGen = struct { offset = std.mem.alignForward(u64, offset, big_align); const padding_len = offset - prev_offset; if (padding_len > 0) { - const llvm_array_ty = dg.context.intType(8).arrayType(@intCast(c_uint, padding_len)); + const llvm_array_ty = o.context.intType(8).arrayType(@intCast(c_uint, padding_len)); try llvm_field_types.append(gpa, llvm_array_ty); } } @@ -3014,7 +2907,7 @@ pub const DeclGen = struct { return llvm_struct_ty; }, .Union => { - const gop = try dg.object.type_map.getOrPut(gpa, t.toIntern()); + const gop = try o.type_map.getOrPut(gpa, t.toIntern()); if (gop.found_existing) return gop.value_ptr.*; const layout = t.unionGetLayout(mod); @@ -3022,24 +2915,24 @@ pub const DeclGen = struct { if (union_obj.layout == .Packed) { const bitsize = @intCast(c_uint, t.bitSize(mod)); - const int_llvm_ty = dg.context.intType(bitsize); + const int_llvm_ty = o.context.intType(bitsize); gop.value_ptr.* = int_llvm_ty; return int_llvm_ty; } if (layout.payload_size == 0) { - const enum_tag_llvm_ty = try dg.lowerType(union_obj.tag_ty); + const enum_tag_llvm_ty = try o.lowerType(union_obj.tag_ty); gop.value_ptr.* = enum_tag_llvm_ty; return enum_tag_llvm_ty; } const name = mod.intern_pool.stringToSlice(try union_obj.getFullyQualifiedName(mod)); - const llvm_union_ty = dg.context.structCreateNamed(name); + const llvm_union_ty = o.context.structCreateNamed(name); gop.value_ptr.* = llvm_union_ty; // must be done before any recursive calls const aligned_field = union_obj.fields.values()[layout.most_aligned_field]; - const llvm_aligned_field_ty = try dg.lowerType(aligned_field.ty); + const llvm_aligned_field_ty = try o.lowerType(aligned_field.ty); const llvm_payload_ty = t: { if (layout.most_aligned_field_size == layout.payload_size) { @@ -3051,9 +2944,9 @@ pub const DeclGen = struct { @intCast(c_uint, layout.payload_size - layout.most_aligned_field_size); const fields: [2]*llvm.Type = .{ llvm_aligned_field_ty, - dg.context.intType(8).arrayType(padding_len), + o.context.intType(8).arrayType(padding_len), }; - break :t dg.context.structType(&fields, fields.len, .True); + break :t o.context.structType(&fields, fields.len, .True); }; if (layout.tag_size == 0) { @@ -3061,7 +2954,7 @@ pub const DeclGen = struct { llvm_union_ty.structSetBody(&llvm_fields, llvm_fields.len, .False); return llvm_union_ty; } - const enum_tag_llvm_ty = try dg.lowerType(union_obj.tag_ty); + const enum_tag_llvm_ty = try o.lowerType(union_obj.tag_ty); // Put the tag before or after the payload depending on which one's // alignment is greater. @@ -3076,14 +2969,14 @@ pub const DeclGen = struct { // Insert padding to make the LLVM struct ABI size match the Zig union ABI size. if (layout.padding != 0) { - llvm_fields[2] = dg.context.intType(8).arrayType(layout.padding); + llvm_fields[2] = o.context.intType(8).arrayType(layout.padding); llvm_fields_len = 3; } llvm_union_ty.structSetBody(&llvm_fields, llvm_fields_len, .False); return llvm_union_ty; }, - .Fn => return lowerTypeFn(dg, t), + .Fn => return lowerTypeFn(o, t), .ComptimeInt => unreachable, .ComptimeFloat => unreachable, .Type => unreachable, @@ -3096,39 +2989,39 @@ pub const DeclGen = struct { } } - fn lowerTypeFn(dg: *DeclGen, fn_ty: Type) Allocator.Error!*llvm.Type { - const mod = dg.module; + fn lowerTypeFn(o: *Object, fn_ty: Type) Allocator.Error!*llvm.Type { + const mod = o.module; const fn_info = mod.typeToFunc(fn_ty).?; - const llvm_ret_ty = try lowerFnRetTy(dg, fn_info); + const llvm_ret_ty = try lowerFnRetTy(o, fn_info); - var llvm_params = std.ArrayList(*llvm.Type).init(dg.gpa); + var llvm_params = std.ArrayList(*llvm.Type).init(o.gpa); defer llvm_params.deinit(); if (firstParamSRet(fn_info, mod)) { - try llvm_params.append(dg.context.pointerType(0)); + try llvm_params.append(o.context.pointerType(0)); } if (fn_info.return_type.toType().isError(mod) and mod.comp.bin_file.options.error_return_tracing) { - const ptr_ty = try mod.singleMutPtrType(try dg.object.getStackTraceType()); - try llvm_params.append(try dg.lowerType(ptr_ty)); + const ptr_ty = try mod.singleMutPtrType(try o.getStackTraceType()); + try llvm_params.append(try o.lowerType(ptr_ty)); } - var it = iterateParamTypes(dg, fn_info); + var it = iterateParamTypes(o, fn_info); while (it.next()) |lowering| switch (lowering) { .no_bits => continue, .byval => { const param_ty = fn_info.param_types[it.zig_index - 1].toType(); - try llvm_params.append(try dg.lowerType(param_ty)); + try llvm_params.append(try o.lowerType(param_ty)); }, .byref, .byref_mut => { - try llvm_params.append(dg.context.pointerType(0)); + try llvm_params.append(o.context.pointerType(0)); }, .abi_sized_int => { const param_ty = fn_info.param_types[it.zig_index - 1].toType(); const abi_size = @intCast(c_uint, param_ty.abiSize(mod)); - try llvm_params.append(dg.context.intType(abi_size * 8)); + try llvm_params.append(o.context.intType(abi_size * 8)); }, .slice => { const param_ty = fn_info.param_types[it.zig_index - 1].toType(); @@ -3136,8 +3029,8 @@ pub const DeclGen = struct { param_ty.optionalChild(mod).slicePtrFieldType(mod) else param_ty.slicePtrFieldType(mod); - const ptr_llvm_ty = try dg.lowerType(ptr_ty); - const len_llvm_ty = try dg.lowerType(Type.usize); + const ptr_llvm_ty = try o.lowerType(ptr_ty); + const len_llvm_ty = try o.lowerType(Type.usize); try llvm_params.ensureUnusedCapacity(2); llvm_params.appendAssumeCapacity(ptr_llvm_ty); @@ -3147,18 +3040,18 @@ pub const DeclGen = struct { try llvm_params.appendSlice(it.llvm_types_buffer[0..it.llvm_types_len]); }, .as_u16 => { - try llvm_params.append(dg.context.intType(16)); + try llvm_params.append(o.context.intType(16)); }, .float_array => |count| { const param_ty = fn_info.param_types[it.zig_index - 1].toType(); - const float_ty = try dg.lowerType(aarch64_c_abi.getFloatArrayType(param_ty, mod).?); + const float_ty = try o.lowerType(aarch64_c_abi.getFloatArrayType(param_ty, mod).?); const field_count = @intCast(c_uint, count); const arr_ty = float_ty.arrayType(field_count); try llvm_params.append(arr_ty); }, .i32_array, .i64_array => |arr_len| { const elem_size: u8 = if (lowering == .i32_array) 32 else 64; - const arr_ty = dg.context.intType(elem_size).arrayType(arr_len); + const arr_ty = o.context.intType(elem_size).arrayType(arr_len); try llvm_params.append(arr_ty); }, }; @@ -3174,8 +3067,8 @@ 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!*llvm.Type { - const mod = dg.module; + fn lowerPtrElemTy(o: *Object, elem_ty: Type) Allocator.Error!*llvm.Type { + const mod = o.module; const lower_elem_ty = switch (elem_ty.zigTypeTag(mod)) { .Opaque => true, .Fn => !mod.typeToFunc(elem_ty).?.is_generic, @@ -3183,15 +3076,16 @@ pub const DeclGen = struct { else => elem_ty.hasRuntimeBitsIgnoreComptime(mod), }; const llvm_elem_ty = if (lower_elem_ty) - try dg.lowerType(elem_ty) + try o.lowerType(elem_ty) else - dg.context.intType(8); + o.context.intType(8); return llvm_elem_ty; } - fn lowerValue(dg: *DeclGen, arg_tv: TypedValue) Error!*llvm.Value { - const mod = dg.module; + fn lowerValue(o: *Object, arg_tv: TypedValue) Error!*llvm.Value { + const mod = o.module; + const gpa = o.gpa; const target = mod.getTarget(); var tv = arg_tv; switch (mod.intern_pool.indexToKey(tv.val.toIntern())) { @@ -3199,7 +3093,7 @@ pub const DeclGen = struct { else => {}, } if (tv.val.isUndefDeep(mod)) { - const llvm_type = try dg.lowerType(tv.ty); + const llvm_type = try o.lowerType(tv.ty); return llvm_type.getUndef(); } @@ -3233,7 +3127,7 @@ pub const DeclGen = struct { .generic_poison, => unreachable, // non-runtime values .false, .true => { - const llvm_type = try dg.lowerType(tv.ty); + const llvm_type = try o.lowerType(tv.ty); return if (tv.val.toBool()) llvm_type.constAllOnes() else llvm_type.constNull(); }, }, @@ -3247,17 +3141,17 @@ pub const DeclGen = struct { .func => |func| mod.funcPtr(func.index).owner_decl, else => unreachable, }; - const fn_decl = dg.module.declPtr(fn_decl_index); - try dg.module.markDeclAlive(fn_decl); - return dg.resolveLlvmFunction(fn_decl_index); + const fn_decl = o.module.declPtr(fn_decl_index); + try o.module.markDeclAlive(fn_decl); + return o.resolveLlvmFunction(fn_decl_index); }, .int => { var bigint_space: Value.BigIntSpace = undefined; const bigint = tv.val.toBigInt(&bigint_space, mod); - return lowerBigInt(dg, tv.ty, bigint); + return lowerBigInt(o, tv.ty, bigint); }, .err => |err| { - const llvm_ty = try dg.lowerType(Type.anyerror); + const llvm_ty = try o.lowerType(Type.anyerror); const int = try mod.getErrorValue(err.name); return llvm_ty.constInt(int, .False); }, @@ -3278,13 +3172,13 @@ pub const DeclGen = struct { const payload_type = tv.ty.errorUnionPayload(mod); if (!payload_type.hasRuntimeBitsIgnoreComptime(mod)) { // We use the error type directly as the type. - return dg.lowerValue(err_tv); + return o.lowerValue(err_tv); } const payload_align = payload_type.abiAlignment(mod); const error_align = err_tv.ty.abiAlignment(mod); - const llvm_error_value = try dg.lowerValue(err_tv); - const llvm_payload_value = try dg.lowerValue(.{ + const llvm_error_value = try o.lowerValue(err_tv); + const llvm_payload_value = try o.lowerValue(.{ .ty = payload_type, .val = switch (error_union.val) { .err_name => try mod.intern(.{ .undef = payload_type.toIntern() }), @@ -3293,7 +3187,7 @@ pub const DeclGen = struct { }); var fields_buf: [3]*llvm.Value = undefined; - const llvm_ty = try dg.lowerType(tv.ty); + const llvm_ty = try o.lowerType(tv.ty); const llvm_field_count = llvm_ty.countStructElementTypes(); if (llvm_field_count > 2) { assert(llvm_field_count == 3); @@ -3303,11 +3197,11 @@ pub const DeclGen = struct { if (error_align > payload_align) { fields_buf[0] = llvm_error_value; fields_buf[1] = llvm_payload_value; - return dg.context.constStruct(&fields_buf, llvm_field_count, .False); + return o.context.constStruct(&fields_buf, llvm_field_count, .False); } else { fields_buf[0] = llvm_payload_value; fields_buf[1] = llvm_error_value; - return dg.context.constStruct(&fields_buf, llvm_field_count, .False); + return o.context.constStruct(&fields_buf, llvm_field_count, .False); } }, .enum_tag => { @@ -3317,7 +3211,7 @@ pub const DeclGen = struct { const bigint = int_val.toBigInt(&bigint_space, mod); const int_info = tv.ty.intInfo(mod); - const llvm_type = dg.context.intType(int_info.bits); + const llvm_type = o.context.intType(int_info.bits); const unsigned_val = v: { if (bigint.limbs.len == 1) { @@ -3337,30 +3231,30 @@ pub const DeclGen = struct { return unsigned_val; }, .float => { - const llvm_ty = try dg.lowerType(tv.ty); + const llvm_ty = try o.lowerType(tv.ty); switch (tv.ty.floatBits(target)) { 16 => { const repr = @bitCast(u16, tv.val.toFloat(f16, mod)); - const llvm_i16 = dg.context.intType(16); + const llvm_i16 = o.context.intType(16); const int = llvm_i16.constInt(repr, .False); return int.constBitCast(llvm_ty); }, 32 => { const repr = @bitCast(u32, tv.val.toFloat(f32, mod)); - const llvm_i32 = dg.context.intType(32); + const llvm_i32 = o.context.intType(32); const int = llvm_i32.constInt(repr, .False); return int.constBitCast(llvm_ty); }, 64 => { const repr = @bitCast(u64, tv.val.toFloat(f64, mod)); - const llvm_i64 = dg.context.intType(64); + const llvm_i64 = o.context.intType(64); const int = llvm_i64.constInt(repr, .False); return int.constBitCast(llvm_ty); }, 80 => { const float = tv.val.toFloat(f80, mod); const repr = std.math.break_f80(float); - const llvm_i80 = dg.context.intType(80); + const llvm_i80 = o.context.intType(80); var x = llvm_i80.constInt(repr.exp, .False); x = x.constShl(llvm_i80.constInt(64, .False)); x = x.constOr(llvm_i80.constInt(repr.fraction, .False)); @@ -3377,7 +3271,7 @@ pub const DeclGen = struct { if (native_endian == .Big) { std.mem.swap(u64, &buf[0], &buf[1]); } - const int = dg.context.intType(128).constIntOfArbitraryPrecision(buf.len, &buf); + const int = o.context.intType(128).constIntOfArbitraryPrecision(buf.len, &buf); return int.constBitCast(llvm_ty); }, else => unreachable, @@ -3389,14 +3283,14 @@ pub const DeclGen = struct { else => .{ .ty = tv.ty.slicePtrFieldType(mod), .val = tv.val.slicePtr(mod) }, }; const llvm_ptr_val = switch (ptr.addr) { - .decl => |decl| try dg.lowerDeclRefValue(ptr_tv, decl), - .mut_decl => |mut_decl| try dg.lowerDeclRefValue(ptr_tv, mut_decl.decl), - .int => |int| try dg.lowerIntAsPtr(int.toValue()), + .decl => |decl| try o.lowerDeclRefValue(ptr_tv, decl), + .mut_decl => |mut_decl| try o.lowerDeclRefValue(ptr_tv, mut_decl.decl), + .int => |int| try o.lowerIntAsPtr(int.toValue()), .eu_payload, .opt_payload, .elem, .field, - => try dg.lowerParentPtr(ptr_tv.val, ptr_tv.ty.ptrInfo(mod).packed_offset.bit_offset % 8 == 0), + => try o.lowerParentPtr(ptr_tv.val, ptr_tv.ty.ptrInfo(mod).packed_offset.bit_offset % 8 == 0), .comptime_field => unreachable, }; switch (ptr.len) { @@ -3404,9 +3298,9 @@ pub const DeclGen = struct { else => { const fields: [2]*llvm.Value = .{ llvm_ptr_val, - try dg.lowerValue(.{ .ty = Type.usize, .val = ptr.len.toValue() }), + try o.lowerValue(.{ .ty = Type.usize, .val = ptr.len.toValue() }), }; - return dg.context.constStruct(&fields, fields.len, .False); + return o.context.constStruct(&fields, fields.len, .False); }, } }, @@ -3414,7 +3308,7 @@ pub const DeclGen = struct { comptime assert(optional_layout_version == 3); const payload_ty = tv.ty.optionalChild(mod); - const llvm_i8 = dg.context.intType(8); + const llvm_i8 = o.context.intType(8); const non_null_bit = switch (opt.val) { .none => llvm_i8.constNull(), else => llvm_i8.constInt(1, .False), @@ -3422,16 +3316,16 @@ pub const DeclGen = struct { if (!payload_ty.hasRuntimeBitsIgnoreComptime(mod)) { return non_null_bit; } - const llvm_ty = try dg.lowerType(tv.ty); + const llvm_ty = try o.lowerType(tv.ty); if (tv.ty.optionalReprIsPayload(mod)) return switch (opt.val) { .none => llvm_ty.constNull(), - else => |payload| dg.lowerValue(.{ .ty = payload_ty, .val = payload.toValue() }), + else => |payload| o.lowerValue(.{ .ty = payload_ty, .val = payload.toValue() }), }; assert(payload_ty.zigTypeTag(mod) != .Fn); const llvm_field_count = llvm_ty.countStructElementTypes(); var fields_buf: [3]*llvm.Value = undefined; - fields_buf[0] = try dg.lowerValue(.{ + fields_buf[0] = try o.lowerValue(.{ .ty = payload_ty, .val = switch (opt.val) { .none => try mod.intern(.{ .undef = payload_ty.toIntern() }), @@ -3443,33 +3337,32 @@ pub const DeclGen = struct { assert(llvm_field_count == 3); fields_buf[2] = llvm_ty.structGetTypeAtIndex(2).getUndef(); } - return dg.context.constStruct(&fields_buf, llvm_field_count, .False); + return o.context.constStruct(&fields_buf, llvm_field_count, .False); }, .aggregate => |aggregate| switch (mod.intern_pool.indexToKey(tv.ty.toIntern())) { .array_type => switch (aggregate.storage) { - .bytes => |bytes| return dg.context.constString( + .bytes => |bytes| return o.context.constString( bytes.ptr, @intCast(c_uint, tv.ty.arrayLenIncludingSentinel(mod)), .True, // Don't null terminate. Bytes has the sentinel, if any. ), .elems => |elem_vals| { const elem_ty = tv.ty.childType(mod); - const gpa = dg.gpa; const llvm_elems = try gpa.alloc(*llvm.Value, elem_vals.len); defer gpa.free(llvm_elems); var need_unnamed = false; for (elem_vals, 0..) |elem_val, i| { - llvm_elems[i] = try dg.lowerValue(.{ .ty = elem_ty, .val = elem_val.toValue() }); - need_unnamed = need_unnamed or dg.isUnnamedType(elem_ty, llvm_elems[i]); + llvm_elems[i] = try o.lowerValue(.{ .ty = elem_ty, .val = elem_val.toValue() }); + need_unnamed = need_unnamed or o.isUnnamedType(elem_ty, llvm_elems[i]); } if (need_unnamed) { - return dg.context.constStruct( + return o.context.constStruct( llvm_elems.ptr, @intCast(c_uint, llvm_elems.len), .True, ); } else { - const llvm_elem_ty = try dg.lowerType(elem_ty); + const llvm_elem_ty = try o.lowerType(elem_ty); return llvm_elem_ty.constArray( llvm_elems.ptr, @intCast(c_uint, llvm_elems.len), @@ -3481,31 +3374,30 @@ pub const DeclGen = struct { const sentinel = tv.ty.sentinel(mod); const len = @intCast(usize, tv.ty.arrayLen(mod)); const len_including_sent = len + @intFromBool(sentinel != null); - const gpa = dg.gpa; const llvm_elems = try gpa.alloc(*llvm.Value, len_including_sent); defer gpa.free(llvm_elems); var need_unnamed = false; if (len != 0) { for (llvm_elems[0..len]) |*elem| { - elem.* = try dg.lowerValue(.{ .ty = elem_ty, .val = val.toValue() }); + elem.* = try o.lowerValue(.{ .ty = elem_ty, .val = val.toValue() }); } - need_unnamed = need_unnamed or dg.isUnnamedType(elem_ty, llvm_elems[0]); + need_unnamed = need_unnamed or o.isUnnamedType(elem_ty, llvm_elems[0]); } if (sentinel) |sent| { - llvm_elems[len] = try dg.lowerValue(.{ .ty = elem_ty, .val = sent }); - need_unnamed = need_unnamed or dg.isUnnamedType(elem_ty, llvm_elems[len]); + llvm_elems[len] = try o.lowerValue(.{ .ty = elem_ty, .val = sent }); + need_unnamed = need_unnamed or o.isUnnamedType(elem_ty, llvm_elems[len]); } if (need_unnamed) { - return dg.context.constStruct( + return o.context.constStruct( llvm_elems.ptr, @intCast(c_uint, llvm_elems.len), .True, ); } else { - const llvm_elem_ty = try dg.lowerType(elem_ty); + const llvm_elem_ty = try o.lowerType(elem_ty); return llvm_elem_ty.constArray( llvm_elems.ptr, @intCast(c_uint, llvm_elems.len), @@ -3515,17 +3407,17 @@ pub const DeclGen = struct { }, .vector_type => |vector_type| { const elem_ty = vector_type.child.toType(); - const llvm_elems = try dg.gpa.alloc(*llvm.Value, vector_type.len); - defer dg.gpa.free(llvm_elems); - const llvm_i8 = dg.context.intType(8); + const llvm_elems = try gpa.alloc(*llvm.Value, vector_type.len); + defer gpa.free(llvm_elems); + const llvm_i8 = o.context.intType(8); for (llvm_elems, 0..) |*llvm_elem, i| { llvm_elem.* = switch (aggregate.storage) { .bytes => |bytes| llvm_i8.constInt(bytes[i], .False), - .elems => |elems| try dg.lowerValue(.{ + .elems => |elems| try o.lowerValue(.{ .ty = elem_ty, .val = elems[i].toValue(), }), - .repeated_elem => |elem| try dg.lowerValue(.{ + .repeated_elem => |elem| try o.lowerValue(.{ .ty = elem_ty, .val = elem.toValue(), }), @@ -3537,8 +3429,6 @@ pub const DeclGen = struct { ); }, .anon_struct_type => |tuple| { - const gpa = dg.gpa; - var llvm_fields: std.ArrayListUnmanaged(*llvm.Value) = .{}; defer llvm_fields.deinit(gpa); @@ -3560,18 +3450,18 @@ pub const DeclGen = struct { const padding_len = offset - prev_offset; if (padding_len > 0) { - const llvm_array_ty = dg.context.intType(8).arrayType(@intCast(c_uint, padding_len)); + const llvm_array_ty = o.context.intType(8).arrayType(@intCast(c_uint, padding_len)); // TODO make this and all other padding elsewhere in debug // builds be 0xaa not undef. llvm_fields.appendAssumeCapacity(llvm_array_ty.getUndef()); } - const field_llvm_val = try dg.lowerValue(.{ + const field_llvm_val = try o.lowerValue(.{ .ty = field_ty.toType(), .val = try tv.val.fieldValue(mod, i), }); - need_unnamed = need_unnamed or dg.isUnnamedType(field_ty.toType(), field_llvm_val); + need_unnamed = need_unnamed or o.isUnnamedType(field_ty.toType(), field_llvm_val); llvm_fields.appendAssumeCapacity(field_llvm_val); @@ -3582,19 +3472,19 @@ pub const DeclGen = struct { offset = std.mem.alignForward(u64, offset, big_align); const padding_len = offset - prev_offset; if (padding_len > 0) { - const llvm_array_ty = dg.context.intType(8).arrayType(@intCast(c_uint, padding_len)); + const llvm_array_ty = o.context.intType(8).arrayType(@intCast(c_uint, padding_len)); llvm_fields.appendAssumeCapacity(llvm_array_ty.getUndef()); } } if (need_unnamed) { - return dg.context.constStruct( + return o.context.constStruct( llvm_fields.items.ptr, @intCast(c_uint, llvm_fields.items.len), .False, ); } else { - const llvm_struct_ty = try dg.lowerType(tv.ty); + const llvm_struct_ty = try o.lowerType(tv.ty); return llvm_struct_ty.constNamedStruct( llvm_fields.items.ptr, @intCast(c_uint, llvm_fields.items.len), @@ -3603,13 +3493,12 @@ pub const DeclGen = struct { }, .struct_type => |struct_type| { const struct_obj = mod.structPtrUnwrap(struct_type.index).?; - const llvm_struct_ty = try dg.lowerType(tv.ty); - const gpa = dg.gpa; + const llvm_struct_ty = try o.lowerType(tv.ty); if (struct_obj.layout == .Packed) { assert(struct_obj.haveLayout()); const big_bits = struct_obj.backing_int_ty.bitSize(mod); - const int_llvm_ty = dg.context.intType(@intCast(c_uint, big_bits)); + const int_llvm_ty = o.context.intType(@intCast(c_uint, big_bits)); const fields = struct_obj.fields.values(); comptime assert(Type.packed_struct_layout_version == 2); var running_int: *llvm.Value = int_llvm_ty.constNull(); @@ -3617,12 +3506,12 @@ pub const DeclGen = struct { for (fields, 0..) |field, i| { if (!field.ty.hasRuntimeBitsIgnoreComptime(mod)) continue; - const non_int_val = try dg.lowerValue(.{ + const non_int_val = try o.lowerValue(.{ .ty = field.ty, .val = try tv.val.fieldValue(mod, i), }); const ty_bit_size = @intCast(u16, field.ty.bitSize(mod)); - const small_int_ty = dg.context.intType(ty_bit_size); + const small_int_ty = o.context.intType(ty_bit_size); const small_int_val = if (field.ty.isPtrAtRuntime(mod)) non_int_val.constPtrToInt(small_int_ty) else @@ -3658,18 +3547,18 @@ pub const DeclGen = struct { const padding_len = offset - prev_offset; if (padding_len > 0) { - const llvm_array_ty = dg.context.intType(8).arrayType(@intCast(c_uint, padding_len)); + const llvm_array_ty = o.context.intType(8).arrayType(@intCast(c_uint, padding_len)); // TODO make this and all other padding elsewhere in debug // builds be 0xaa not undef. llvm_fields.appendAssumeCapacity(llvm_array_ty.getUndef()); } - const field_llvm_val = try dg.lowerValue(.{ + const field_llvm_val = try o.lowerValue(.{ .ty = field.ty, .val = try tv.val.fieldValue(mod, field_and_index.index), }); - need_unnamed = need_unnamed or dg.isUnnamedType(field.ty, field_llvm_val); + need_unnamed = need_unnamed or o.isUnnamedType(field.ty, field_llvm_val); llvm_fields.appendAssumeCapacity(field_llvm_val); @@ -3680,13 +3569,13 @@ pub const DeclGen = struct { offset = std.mem.alignForward(u64, offset, big_align); const padding_len = offset - prev_offset; if (padding_len > 0) { - const llvm_array_ty = dg.context.intType(8).arrayType(@intCast(c_uint, padding_len)); + const llvm_array_ty = o.context.intType(8).arrayType(@intCast(c_uint, padding_len)); llvm_fields.appendAssumeCapacity(llvm_array_ty.getUndef()); } } if (need_unnamed) { - return dg.context.constStruct( + return o.context.constStruct( llvm_fields.items.ptr, @intCast(c_uint, llvm_fields.items.len), .False, @@ -3701,7 +3590,7 @@ pub const DeclGen = struct { else => unreachable, }, .un => { - const llvm_union_ty = try dg.lowerType(tv.ty); + const llvm_union_ty = try o.lowerType(tv.ty); const tag_and_val: Value.Payload.Union.Data = switch (tv.val.toIntern()) { .none => tv.val.castTag(.@"union").?.data, else => switch (mod.intern_pool.indexToKey(tv.val.toIntern())) { @@ -3713,22 +3602,22 @@ pub const DeclGen = struct { const layout = tv.ty.unionGetLayout(mod); if (layout.payload_size == 0) { - return lowerValue(dg, .{ + return lowerValue(o, .{ .ty = tv.ty.unionTagTypeSafety(mod).?, .val = tag_and_val.tag, }); } const union_obj = mod.typeToUnion(tv.ty).?; - const field_index = tv.ty.unionTagFieldIndex(tag_and_val.tag, dg.module).?; + const field_index = tv.ty.unionTagFieldIndex(tag_and_val.tag, o.module).?; assert(union_obj.haveFieldTypes()); const field_ty = union_obj.fields.values()[field_index].ty; if (union_obj.layout == .Packed) { if (!field_ty.hasRuntimeBits(mod)) return llvm_union_ty.constNull(); - const non_int_val = try lowerValue(dg, .{ .ty = field_ty, .val = tag_and_val.val }); + const non_int_val = try lowerValue(o, .{ .ty = field_ty, .val = tag_and_val.val }); const ty_bit_size = @intCast(u16, field_ty.bitSize(mod)); - const small_int_ty = dg.context.intType(ty_bit_size); + const small_int_ty = o.context.intType(ty_bit_size); const small_int_val = if (field_ty.isPtrAtRuntime(mod)) non_int_val.constPtrToInt(small_int_ty) else @@ -3744,30 +3633,30 @@ pub const DeclGen = struct { const payload = p: { if (!field_ty.hasRuntimeBitsIgnoreComptime(mod)) { const padding_len = @intCast(c_uint, layout.payload_size); - break :p dg.context.intType(8).arrayType(padding_len).getUndef(); + break :p o.context.intType(8).arrayType(padding_len).getUndef(); } - const field = try lowerValue(dg, .{ .ty = field_ty, .val = tag_and_val.val }); - need_unnamed = need_unnamed or dg.isUnnamedType(field_ty, field); + const field = try lowerValue(o, .{ .ty = field_ty, .val = tag_and_val.val }); + need_unnamed = need_unnamed or o.isUnnamedType(field_ty, field); const field_size = field_ty.abiSize(mod); if (field_size == layout.payload_size) { break :p field; } const padding_len = @intCast(c_uint, layout.payload_size - field_size); const fields: [2]*llvm.Value = .{ - field, dg.context.intType(8).arrayType(padding_len).getUndef(), + field, o.context.intType(8).arrayType(padding_len).getUndef(), }; - break :p dg.context.constStruct(&fields, fields.len, .True); + break :p o.context.constStruct(&fields, fields.len, .True); }; if (layout.tag_size == 0) { const fields: [1]*llvm.Value = .{payload}; if (need_unnamed) { - return dg.context.constStruct(&fields, fields.len, .False); + return o.context.constStruct(&fields, fields.len, .False); } else { return llvm_union_ty.constNamedStruct(&fields, fields.len); } } - const llvm_tag_value = try lowerValue(dg, .{ + const llvm_tag_value = try lowerValue(o, .{ .ty = tv.ty.unionTagTypeSafety(mod).?, .val = tag_and_val.tag, }); @@ -3779,11 +3668,11 @@ pub const DeclGen = struct { fields = .{ payload, llvm_tag_value, undefined }; } if (layout.padding != 0) { - fields[2] = dg.context.intType(8).arrayType(layout.padding).getUndef(); + fields[2] = o.context.intType(8).arrayType(layout.padding).getUndef(); fields_len = 3; } if (need_unnamed) { - return dg.context.constStruct(&fields, fields_len, .False); + return o.context.constStruct(&fields, fields_len, .False); } else { return llvm_union_ty.constNamedStruct(&fields, fields_len); } @@ -3792,24 +3681,24 @@ pub const DeclGen = struct { } } - fn lowerIntAsPtr(dg: *DeclGen, val: Value) Error!*llvm.Value { - switch (dg.module.intern_pool.indexToKey(val.toIntern())) { - .undef => return dg.context.pointerType(0).getUndef(), + fn lowerIntAsPtr(o: *Object, val: Value) Error!*llvm.Value { + switch (o.module.intern_pool.indexToKey(val.toIntern())) { + .undef => return o.context.pointerType(0).getUndef(), .int => { var bigint_space: Value.BigIntSpace = undefined; - const bigint = val.toBigInt(&bigint_space, dg.module); - const llvm_int = lowerBigInt(dg, Type.usize, bigint); - return llvm_int.constIntToPtr(dg.context.pointerType(0)); + const bigint = val.toBigInt(&bigint_space, o.module); + const llvm_int = lowerBigInt(o, Type.usize, bigint); + return llvm_int.constIntToPtr(o.context.pointerType(0)); }, else => unreachable, } } - fn lowerBigInt(dg: *DeclGen, ty: Type, bigint: std.math.big.int.Const) *llvm.Value { - const mod = dg.module; + fn lowerBigInt(o: *Object, ty: Type, bigint: std.math.big.int.Const) *llvm.Value { + const mod = o.module; const int_info = ty.intInfo(mod); assert(int_info.bits != 0); - const llvm_type = dg.context.intType(int_info.bits); + const llvm_type = o.context.intType(int_info.bits); const unsigned_val = v: { if (bigint.limbs.len == 1) { @@ -3835,26 +3724,26 @@ pub const DeclGen = struct { }; fn lowerParentPtrDecl( - dg: *DeclGen, + o: *Object, ptr_val: Value, decl_index: Module.Decl.Index, ) Error!*llvm.Value { - const mod = dg.module; + const mod = o.module; const decl = mod.declPtr(decl_index); try mod.markDeclAlive(decl); const ptr_ty = try mod.singleMutPtrType(decl.ty); - return try dg.lowerDeclRefValue(.{ .ty = ptr_ty, .val = ptr_val }, decl_index); + return try o.lowerDeclRefValue(.{ .ty = ptr_ty, .val = ptr_val }, decl_index); } - fn lowerParentPtr(dg: *DeclGen, ptr_val: Value, byte_aligned: bool) Error!*llvm.Value { - const mod = dg.module; + fn lowerParentPtr(o: *Object, ptr_val: Value, byte_aligned: bool) Error!*llvm.Value { + const mod = o.module; const target = mod.getTarget(); return switch (mod.intern_pool.indexToKey(ptr_val.toIntern()).ptr.addr) { - .decl => |decl| dg.lowerParentPtrDecl(ptr_val, decl), - .mut_decl => |mut_decl| dg.lowerParentPtrDecl(ptr_val, mut_decl.decl), - .int => |int| dg.lowerIntAsPtr(int.toValue()), + .decl => |decl| o.lowerParentPtrDecl(ptr_val, decl), + .mut_decl => |mut_decl| o.lowerParentPtrDecl(ptr_val, mut_decl.decl), + .int => |int| o.lowerIntAsPtr(int.toValue()), .eu_payload => |eu_ptr| { - const parent_llvm_ptr = try dg.lowerParentPtr(eu_ptr.toValue(), true); + const parent_llvm_ptr = try o.lowerParentPtr(eu_ptr.toValue(), true); const eu_ty = mod.intern_pool.typeOf(eu_ptr).toType().childType(mod); const payload_ty = eu_ty.errorUnionPayload(mod); @@ -3865,16 +3754,16 @@ pub const DeclGen = struct { } const payload_offset: u8 = if (payload_ty.abiAlignment(mod) > Type.anyerror.abiSize(mod)) 2 else 1; - const llvm_u32 = dg.context.intType(32); + const llvm_u32 = o.context.intType(32); const indices: [2]*llvm.Value = .{ llvm_u32.constInt(0, .False), llvm_u32.constInt(payload_offset, .False), }; - const eu_llvm_ty = try dg.lowerType(eu_ty); + const eu_llvm_ty = try o.lowerType(eu_ty); return eu_llvm_ty.constInBoundsGEP(parent_llvm_ptr, &indices, indices.len); }, .opt_payload => |opt_ptr| { - const parent_llvm_ptr = try dg.lowerParentPtr(opt_ptr.toValue(), true); + const parent_llvm_ptr = try o.lowerParentPtr(opt_ptr.toValue(), true); const opt_ty = mod.intern_pool.typeOf(opt_ptr).toType().childType(mod); const payload_ty = opt_ty.optionalChild(mod); @@ -3886,32 +3775,32 @@ pub const DeclGen = struct { return parent_llvm_ptr; } - const llvm_u32 = dg.context.intType(32); + const llvm_u32 = o.context.intType(32); const indices: [2]*llvm.Value = .{ llvm_u32.constInt(0, .False), llvm_u32.constInt(0, .False), }; - const opt_llvm_ty = try dg.lowerType(opt_ty); + const opt_llvm_ty = try o.lowerType(opt_ty); return opt_llvm_ty.constInBoundsGEP(parent_llvm_ptr, &indices, indices.len); }, .comptime_field => unreachable, .elem => |elem_ptr| { - const parent_llvm_ptr = try dg.lowerParentPtr(elem_ptr.base.toValue(), true); + const parent_llvm_ptr = try o.lowerParentPtr(elem_ptr.base.toValue(), true); - const llvm_usize = try dg.lowerType(Type.usize); + const llvm_usize = try o.lowerType(Type.usize); const indices: [1]*llvm.Value = .{ llvm_usize.constInt(elem_ptr.index, .False), }; const elem_ty = mod.intern_pool.typeOf(elem_ptr.base).toType().elemType2(mod); - const elem_llvm_ty = try dg.lowerType(elem_ty); + const elem_llvm_ty = try o.lowerType(elem_ty); return elem_llvm_ty.constInBoundsGEP(parent_llvm_ptr, &indices, indices.len); }, .field => |field_ptr| { - const parent_llvm_ptr = try dg.lowerParentPtr(field_ptr.base.toValue(), byte_aligned); + const parent_llvm_ptr = try o.lowerParentPtr(field_ptr.base.toValue(), byte_aligned); const parent_ty = mod.intern_pool.typeOf(field_ptr.base).toType().childType(mod); const field_index = @intCast(u32, field_ptr.index); - const llvm_u32 = dg.context.intType(32); + const llvm_u32 = o.context.intType(32); switch (parent_ty.zigTypeTag(mod)) { .Union => { if (parent_ty.containerLayout(mod) == .Packed) { @@ -3932,13 +3821,13 @@ pub const DeclGen = struct { llvm_u32.constInt(0, .False), llvm_u32.constInt(llvm_pl_index, .False), }; - const parent_llvm_ty = try dg.lowerType(parent_ty); + const parent_llvm_ty = try o.lowerType(parent_ty); return parent_llvm_ty.constInBoundsGEP(parent_llvm_ptr, &indices, indices.len); }, .Struct => { if (parent_ty.containerLayout(mod) == .Packed) { if (!byte_aligned) return parent_llvm_ptr; - const llvm_usize = dg.context.intType(target.ptrBitWidth()); + const llvm_usize = o.context.intType(target.ptrBitWidth()); const base_addr = parent_llvm_ptr.constPtrToInt(llvm_usize); // count bits of fields before this one const prev_bits = b: { @@ -3951,11 +3840,11 @@ pub const DeclGen = struct { }; const byte_offset = llvm_usize.constInt(prev_bits / 8, .False); const field_addr = base_addr.constAdd(byte_offset); - const final_llvm_ty = dg.context.pointerType(0); + const final_llvm_ty = o.context.pointerType(0); return field_addr.constIntToPtr(final_llvm_ty); } - const parent_llvm_ty = try dg.lowerType(parent_ty); + const parent_llvm_ty = try o.lowerType(parent_ty); if (llvmField(parent_ty, field_index, mod)) |llvm_field| { const indices: [2]*llvm.Value = .{ llvm_u32.constInt(0, .False), @@ -3974,7 +3863,7 @@ pub const DeclGen = struct { llvm_u32.constInt(0, .False), llvm_u32.constInt(field_index, .False), }; - const parent_llvm_ty = try dg.lowerType(parent_ty); + const parent_llvm_ty = try o.lowerType(parent_ty); return parent_llvm_ty.constInBoundsGEP(parent_llvm_ptr, &indices, indices.len); }, else => unreachable, @@ -3984,11 +3873,11 @@ pub const DeclGen = struct { } fn lowerDeclRefValue( - self: *DeclGen, + o: *Object, tv: TypedValue, decl_index: Module.Decl.Index, ) Error!*llvm.Value { - const mod = self.module; + const mod = o.module; // In the case of something like: // fn foo() void {} @@ -3998,11 +3887,11 @@ pub const DeclGen = struct { const decl = mod.declPtr(decl_index); if (decl.val.getFunction(mod)) |func| { if (func.owner_decl != decl_index) { - return self.lowerDeclRefValue(tv, func.owner_decl); + return o.lowerDeclRefValue(tv, func.owner_decl); } } else if (decl.val.getExternFunc(mod)) |func| { if (func.decl != decl_index) { - return self.lowerDeclRefValue(tv, func.decl); + return o.lowerDeclRefValue(tv, func.decl); } } @@ -4010,25 +3899,25 @@ pub const DeclGen = struct { if ((!is_fn_body and !decl.ty.hasRuntimeBits(mod)) or (is_fn_body and mod.typeToFunc(decl.ty).?.is_generic)) { - return self.lowerPtrToVoid(tv.ty); + return o.lowerPtrToVoid(tv.ty); } try mod.markDeclAlive(decl); const llvm_decl_val = if (is_fn_body) - try self.resolveLlvmFunction(decl_index) + try o.resolveLlvmFunction(decl_index) else - try self.resolveGlobalDecl(decl_index); + try o.resolveGlobalDecl(decl_index); const target = mod.getTarget(); const llvm_wanted_addrspace = toLlvmAddressSpace(decl.@"addrspace", target); const llvm_actual_addrspace = toLlvmGlobalAddressSpace(decl.@"addrspace", target); const llvm_val = if (llvm_wanted_addrspace != llvm_actual_addrspace) blk: { - const llvm_decl_wanted_ptr_ty = self.context.pointerType(llvm_wanted_addrspace); + const llvm_decl_wanted_ptr_ty = o.context.pointerType(llvm_wanted_addrspace); break :blk llvm_decl_val.constAddrSpaceCast(llvm_decl_wanted_ptr_ty); } else llvm_decl_val; - const llvm_type = try self.lowerType(tv.ty); + const llvm_type = try o.lowerType(tv.ty); if (tv.ty.zigTypeTag(mod) == .Int) { return llvm_val.constPtrToInt(llvm_type); } else { @@ -4036,15 +3925,15 @@ pub const DeclGen = struct { } } - fn lowerPtrToVoid(dg: *DeclGen, ptr_ty: Type) !*llvm.Value { - const mod = dg.module; + fn lowerPtrToVoid(o: *Object, ptr_ty: Type) !*llvm.Value { + const mod = o.module; // Even though we are pointing at something which has zero bits (e.g. `void`), // Pointers are defined to have bits. So we must return something here. // The value cannot be undefined, because we use the `nonnull` annotation // for non-optional pointers. We also need to respect the alignment, even though // the address will never be dereferenced. - const llvm_usize = try dg.lowerType(Type.usize); - const llvm_ptr_ty = try dg.lowerType(ptr_ty); + const llvm_usize = try o.lowerType(Type.usize); + const llvm_ptr_ty = try o.lowerType(ptr_ty); if (ptr_ty.ptrInfo(mod).flags.alignment.toByteUnitsOptional()) |alignment| { return llvm_usize.constInt(alignment, .False).constIntToPtr(llvm_ptr_ty); } @@ -4053,7 +3942,7 @@ pub const DeclGen = struct { // have an "undef_but_not_null" attribute. As an example, if this `alloc` AIR // instruction is followed by a `wrap_optional`, it will return this value // verbatim, and the result should test as non-null. - const target = dg.module.getTarget(); + const target = mod.getTarget(); const int = switch (target.ptrBitWidth()) { 16 => llvm_usize.constInt(0xaaaa, .False), 32 => llvm_usize.constInt(0xaaaaaaaa, .False), @@ -4063,16 +3952,16 @@ pub const DeclGen = struct { return int.constIntToPtr(llvm_ptr_ty); } - fn addAttr(dg: DeclGen, val: *llvm.Value, index: llvm.AttributeIndex, name: []const u8) void { - return dg.addAttrInt(val, index, name, 0); + fn addAttr(o: *Object, val: *llvm.Value, index: llvm.AttributeIndex, name: []const u8) void { + return o.addAttrInt(val, index, name, 0); } - fn addArgAttr(dg: DeclGen, fn_val: *llvm.Value, param_index: u32, attr_name: []const u8) void { - return dg.addAttr(fn_val, param_index + 1, attr_name); + fn addArgAttr(o: *Object, fn_val: *llvm.Value, param_index: u32, attr_name: []const u8) void { + return o.addAttr(fn_val, param_index + 1, attr_name); } - fn addArgAttrInt(dg: DeclGen, fn_val: *llvm.Value, param_index: u32, attr_name: []const u8, int: u64) void { - return dg.addAttrInt(fn_val, param_index + 1, attr_name, int); + fn addArgAttrInt(o: *Object, fn_val: *llvm.Value, param_index: u32, attr_name: []const u8, int: u64) void { + return o.addAttrInt(fn_val, param_index + 1, attr_name, int); } fn removeAttr(val: *llvm.Value, index: llvm.AttributeIndex, name: []const u8) void { @@ -4082,7 +3971,7 @@ pub const DeclGen = struct { } fn addAttrInt( - dg: DeclGen, + o: *Object, val: *llvm.Value, index: llvm.AttributeIndex, name: []const u8, @@ -4090,18 +3979,18 @@ pub const DeclGen = struct { ) void { const kind_id = llvm.getEnumAttributeKindForName(name.ptr, name.len); assert(kind_id != 0); - const llvm_attr = dg.context.createEnumAttribute(kind_id, int); + const llvm_attr = o.context.createEnumAttribute(kind_id, int); val.addAttributeAtIndex(index, llvm_attr); } fn addAttrString( - dg: *DeclGen, + o: *Object, val: *llvm.Value, index: llvm.AttributeIndex, name: []const u8, value: []const u8, ) void { - const llvm_attr = dg.context.createStringAttribute( + const llvm_attr = o.context.createStringAttribute( name.ptr, @intCast(c_uint, name.len), value.ptr, @@ -4110,94 +3999,193 @@ pub const DeclGen = struct { val.addAttributeAtIndex(index, llvm_attr); } - fn addFnAttr(dg: DeclGen, val: *llvm.Value, name: []const u8) void { - dg.addAttr(val, std.math.maxInt(llvm.AttributeIndex), name); + fn addFnAttr(o: *Object, val: *llvm.Value, name: []const u8) void { + o.addAttr(val, std.math.maxInt(llvm.AttributeIndex), name); } - fn addFnAttrString(dg: *DeclGen, val: *llvm.Value, name: []const u8, value: []const u8) void { - dg.addAttrString(val, std.math.maxInt(llvm.AttributeIndex), name, value); + fn addFnAttrString(o: *Object, val: *llvm.Value, name: []const u8, value: []const u8) void { + o.addAttrString(val, std.math.maxInt(llvm.AttributeIndex), name, value); } fn removeFnAttr(fn_val: *llvm.Value, name: []const u8) void { removeAttr(fn_val, std.math.maxInt(llvm.AttributeIndex), name); } - fn addFnAttrInt(dg: DeclGen, fn_val: *llvm.Value, name: []const u8, int: u64) void { - return dg.addAttrInt(fn_val, std.math.maxInt(llvm.AttributeIndex), name, int); + fn addFnAttrInt(o: *Object, fn_val: *llvm.Value, name: []const u8, int: u64) void { + return o.addAttrInt(fn_val, std.math.maxInt(llvm.AttributeIndex), name, int); } /// If the operand type of an atomic operation is not byte sized we need to /// widen it before using it and then truncate the result. /// RMW exchange of floating-point values is bitcasted to same-sized integer /// types to work around a LLVM deficiency when targeting ARM/AArch64. - fn getAtomicAbiType(dg: *DeclGen, ty: Type, is_rmw_xchg: bool) ?*llvm.Type { - const mod = dg.module; + fn getAtomicAbiType(o: *Object, ty: Type, is_rmw_xchg: bool) ?*llvm.Type { + const mod = o.module; const int_ty = switch (ty.zigTypeTag(mod)) { .Int => ty, .Enum => ty.intTagType(mod), .Float => { if (!is_rmw_xchg) return null; - return dg.context.intType(@intCast(c_uint, ty.abiSize(mod) * 8)); + return o.context.intType(@intCast(c_uint, ty.abiSize(mod) * 8)); }, - .Bool => return dg.context.intType(8), + .Bool => return o.context.intType(8), else => return null, }; const bit_count = int_ty.intInfo(mod).bits; if (!std.math.isPowerOfTwo(bit_count) or (bit_count % 8) != 0) { - return dg.context.intType(@intCast(c_uint, int_ty.abiSize(mod) * 8)); + return o.context.intType(@intCast(c_uint, int_ty.abiSize(mod) * 8)); } else { return null; } } fn addByValParamAttrs( - dg: DeclGen, + o: *Object, llvm_fn: *llvm.Value, param_ty: Type, param_index: u32, fn_info: InternPool.Key.FuncType, llvm_arg_i: u32, ) void { - const mod = dg.module; + const mod = o.module; if (param_ty.isPtrAtRuntime(mod)) { const ptr_info = param_ty.ptrInfo(mod); if (math.cast(u5, param_index)) |i| { if (@truncate(u1, fn_info.noalias_bits >> i) != 0) { - dg.addArgAttr(llvm_fn, llvm_arg_i, "noalias"); + o.addArgAttr(llvm_fn, llvm_arg_i, "noalias"); } } if (!param_ty.isPtrLikeOptional(mod) and !ptr_info.flags.is_allowzero) { - dg.addArgAttr(llvm_fn, llvm_arg_i, "nonnull"); + o.addArgAttr(llvm_fn, llvm_arg_i, "nonnull"); } if (ptr_info.flags.is_const) { - dg.addArgAttr(llvm_fn, llvm_arg_i, "readonly"); + o.addArgAttr(llvm_fn, llvm_arg_i, "readonly"); } const elem_align = ptr_info.flags.alignment.toByteUnitsOptional() orelse @max(ptr_info.child.toType().abiAlignment(mod), 1); - dg.addArgAttrInt(llvm_fn, llvm_arg_i, "align", elem_align); + o.addArgAttrInt(llvm_fn, llvm_arg_i, "align", elem_align); } else if (ccAbiPromoteInt(fn_info.cc, mod, param_ty)) |s| switch (s) { - .signed => dg.addArgAttr(llvm_fn, llvm_arg_i, "signext"), - .unsigned => dg.addArgAttr(llvm_fn, llvm_arg_i, "zeroext"), + .signed => o.addArgAttr(llvm_fn, llvm_arg_i, "signext"), + .unsigned => o.addArgAttr(llvm_fn, llvm_arg_i, "zeroext"), }; } fn addByRefParamAttrs( - dg: DeclGen, + o: *Object, llvm_fn: *llvm.Value, llvm_arg_i: u32, alignment: u32, byval_attr: bool, param_llvm_ty: *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); + o.addArgAttr(llvm_fn, llvm_arg_i, "nonnull"); + o.addArgAttr(llvm_fn, llvm_arg_i, "readonly"); + o.addArgAttrInt(llvm_fn, llvm_arg_i, "align", alignment); if (byval_attr) { llvm_fn.addByValAttr(llvm_arg_i, param_llvm_ty); } } }; +pub const DeclGen = struct { + object: *Object, + decl: *Module.Decl, + decl_index: Module.Decl.Index, + err_msg: ?*Module.ErrorMsg, + + fn todo(dg: *DeclGen, comptime format: []const u8, args: anytype) Error { + @setCold(true); + assert(dg.err_msg == null); + const o = dg.object; + const gpa = o.gpa; + const mod = o.module; + const src_loc = LazySrcLoc.nodeOffset(0).toSrcLoc(dg.decl, mod); + dg.err_msg = try Module.ErrorMsg.create(gpa, src_loc, "TODO (LLVM): " ++ format, args); + return error.CodegenFail; + } + + fn genDecl(dg: *DeclGen) !void { + const o = dg.object; + const mod = o.module; + const decl = dg.decl; + const decl_index = dg.decl_index; + assert(decl.has_tv); + + if (decl.val.getExternFunc(mod)) |extern_func| { + _ = try o.resolveLlvmFunction(extern_func.decl); + } else { + const target = mod.getTarget(); + var global = try o.resolveGlobalDecl(decl_index); + global.setAlignment(decl.getAlignment(mod)); + if (mod.intern_pool.stringToSliceUnwrap(decl.@"linksection")) |s| global.setSection(s); + assert(decl.has_tv); + const init_val = if (decl.val.getVariable(mod)) |variable| init_val: { + break :init_val variable.init; + } else init_val: { + global.setGlobalConstant(.True); + break :init_val decl.val.toIntern(); + }; + if (init_val != .none) { + const llvm_init = try o.lowerValue(.{ .ty = decl.ty, .val = init_val.toValue() }); + if (global.globalGetValueType() == llvm_init.typeOf()) { + global.setInitializer(llvm_init); + } else { + // LLVM does not allow us to change the type of globals. So we must + // create a new global with the correct type, copy all its attributes, + // and then update all references to point to the new global, + // delete the original, and rename the new one to the old one's name. + // This is necessary because LLVM does not support const bitcasting + // a struct with padding bytes, which is needed to lower a const union value + // to LLVM, when a field other than the most-aligned is active. Instead, + // we must lower to an unnamed struct, and pointer cast at usage sites + // of the global. Such an unnamed struct is the cause of the global type + // mismatch, because we don't have the LLVM type until the *value* is created, + // whereas the global needs to be created based on the type alone, because + // lowering the value may reference the global as a pointer. + // Related: https://github.com/ziglang/zig/issues/13265 + const llvm_global_addrspace = toLlvmGlobalAddressSpace(decl.@"addrspace", target); + const new_global = o.llvm_module.addGlobalInAddressSpace( + llvm_init.typeOf(), + "", + llvm_global_addrspace, + ); + new_global.setLinkage(global.getLinkage()); + new_global.setUnnamedAddr(global.getUnnamedAddress()); + new_global.setAlignment(global.getAlignment()); + if (mod.intern_pool.stringToSliceUnwrap(decl.@"linksection")) |s| + new_global.setSection(s); + new_global.setInitializer(llvm_init); + // TODO: How should this work then the address space of a global changed? + global.replaceAllUsesWith(new_global); + o.decl_map.putAssumeCapacity(decl_index, new_global); + new_global.takeName(global); + global.deleteGlobal(); + global = new_global; + } + } + + if (o.di_builder) |dib| { + const di_file = try o.getDIFile(o.gpa, mod.namespacePtr(decl.src_namespace).file_scope); + + const line_number = decl.src_line + 1; + const is_internal_linkage = !o.module.decl_exports.contains(decl_index); + const di_global = dib.createGlobalVariableExpression( + di_file.toScope(), + mod.intern_pool.stringToSlice(decl.name), + global.getValueName(), + di_file, + line_number, + try o.lowerDebugType(decl.ty, .full), + is_internal_linkage, + ); + + try o.di_map.put(o.gpa, dg.decl, di_global.getVariable().toNode()); + if (!is_internal_linkage or decl.isExtern(mod)) global.attachMetaData(di_global); + } + } + } +}; + pub const FuncGen = struct { gpa: Allocator, dg: *DeclGen, @@ -4268,15 +4256,13 @@ pub const FuncGen = struct { return self.dg.todo(format, args); } - fn llvmModule(self: *FuncGen) *llvm.Module { - return self.dg.object.llvm_module; - } - fn resolveInst(self: *FuncGen, inst: Air.Inst.Ref) !*llvm.Value { - const gop = try self.func_inst_table.getOrPut(self.dg.gpa, inst); + const gpa = self.gpa; + const gop = try self.func_inst_table.getOrPut(gpa, inst); if (gop.found_existing) return gop.value_ptr.*; - const mod = self.dg.module; + const o = self.dg.object; + const mod = o.module; const llvm_val = try self.resolveValue(.{ .ty = self.typeOf(inst), .val = (try self.air.value(inst, mod)).?, @@ -4286,8 +4272,9 @@ pub const FuncGen = struct { } fn resolveValue(self: *FuncGen, tv: TypedValue) !*llvm.Value { - const mod = self.dg.module; - const llvm_val = try self.dg.lowerValue(tv); + const o = self.dg.object; + const mod = o.module; + const llvm_val = try o.lowerValue(tv); if (!isByRef(tv.ty, mod)) return llvm_val; // We have an LLVM value but we need to create a global constant and @@ -4295,7 +4282,7 @@ pub const FuncGen = struct { const target = mod.getTarget(); const llvm_wanted_addrspace = toLlvmAddressSpace(.generic, target); const llvm_actual_addrspace = toLlvmGlobalAddressSpace(.generic, target); - const global = self.dg.object.llvm_module.addGlobalInAddressSpace(llvm_val.typeOf(), "", llvm_actual_addrspace); + const global = o.llvm_module.addGlobalInAddressSpace(llvm_val.typeOf(), "", llvm_actual_addrspace); global.setInitializer(llvm_val); global.setLinkage(.Private); global.setGlobalConstant(.True); @@ -4309,7 +4296,8 @@ pub const FuncGen = struct { } fn genBody(self: *FuncGen, body: []const Air.Inst.Index) Error!void { - const mod = self.dg.module; + const o = self.dg.object; + const mod = o.module; const ip = &mod.intern_pool; const air_tags = self.air.instructions.items(.tag); for (body, 0..) |inst, i| { @@ -4563,7 +4551,8 @@ pub const FuncGen = struct { const pl_op = self.air.instructions.items(.data)[inst].pl_op; const extra = self.air.extraData(Air.Call, pl_op.payload); const args = @ptrCast([]const Air.Inst.Ref, self.air.extra[extra.end..][0..extra.data.args_len]); - const mod = self.dg.module; + const o = self.dg.object; + const mod = o.module; const callee_ty = self.typeOf(pl_op.operand); const zig_fn_ty = switch (callee_ty.zigTypeTag(mod)) { .Fn => callee_ty, @@ -4580,26 +4569,26 @@ pub const FuncGen = struct { defer llvm_args.deinit(); const ret_ptr = if (!sret) null else blk: { - const llvm_ret_ty = try self.dg.lowerType(return_type); + const llvm_ret_ty = try o.lowerType(return_type); const ret_ptr = self.buildAlloca(llvm_ret_ty, return_type.abiAlignment(mod)); try llvm_args.append(ret_ptr); break :blk ret_ptr; }; const err_return_tracing = return_type.isError(mod) and - self.dg.module.comp.bin_file.options.error_return_tracing; + o.module.comp.bin_file.options.error_return_tracing; if (err_return_tracing) { try llvm_args.append(self.err_ret_trace.?); } - var it = iterateParamTypes(self.dg, fn_info); + var it = iterateParamTypes(o, fn_info); while (it.nextCall(self, args)) |lowering| switch (lowering) { .no_bits => continue, .byval => { 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.dg.lowerType(param_ty); + const llvm_param_ty = try o.lowerType(param_ty); if (isByRef(param_ty, mod)) { const alignment = param_ty.abiAlignment(mod); const load_inst = self.builder.buildLoad(llvm_param_ty, llvm_arg, ""); @@ -4630,7 +4619,7 @@ pub const FuncGen = struct { const llvm_arg = try self.resolveInst(arg); const alignment = param_ty.abiAlignment(mod); - const param_llvm_ty = try self.dg.lowerType(param_ty); + const param_llvm_ty = try o.lowerType(param_ty); const arg_ptr = self.buildAlloca(param_llvm_ty, alignment); if (isByRef(param_ty, mod)) { const load_inst = self.builder.buildLoad(param_llvm_ty, llvm_arg, ""); @@ -4662,7 +4651,7 @@ pub const FuncGen = struct { // a local, store as one type, and then load as another type. const alignment = @max( param_ty.abiAlignment(mod), - self.dg.object.target_data.abiAlignmentOfType(int_llvm_ty), + o.target_data.abiAlignmentOfType(int_llvm_ty), ); const int_ptr = self.buildAlloca(int_llvm_ty, alignment); const store_inst = self.builder.buildStore(llvm_arg, int_ptr); @@ -4721,7 +4710,7 @@ pub const FuncGen = struct { llvm_arg = store_inst; } - const float_ty = try self.dg.lowerType(aarch64_c_abi.getFloatArrayType(arg_ty, mod).?); + const float_ty = try o.lowerType(aarch64_c_abi.getFloatArrayType(arg_ty, mod).?); const array_llvm_ty = float_ty.arrayType(count); const alignment = arg_ty.abiAlignment(mod); @@ -4750,7 +4739,7 @@ pub const FuncGen = struct { }; const call = self.builder.buildCall( - try self.dg.lowerType(zig_fn_ty), + try o.lowerType(zig_fn_ty), llvm_fn, llvm_args.items.ptr, @intCast(c_uint, llvm_args.items.len), @@ -4761,7 +4750,7 @@ pub const FuncGen = struct { if (callee_ty.zigTypeTag(mod) == .Pointer) { // Add argument attributes for function pointer calls. - it = iterateParamTypes(self.dg, fn_info); + it = iterateParamTypes(o, fn_info); it.llvm_index += @intFromBool(sret); it.llvm_index += @intFromBool(err_return_tracing); while (it.next()) |lowering| switch (lowering) { @@ -4769,18 +4758,18 @@ pub const FuncGen = struct { const param_index = it.zig_index - 1; const param_ty = fn_info.param_types[param_index].toType(); if (!isByRef(param_ty, mod)) { - self.dg.addByValParamAttrs(call, param_ty, param_index, fn_info, it.llvm_index - 1); + o.addByValParamAttrs(call, param_ty, param_index, fn_info, it.llvm_index - 1); } }, .byref => { const param_index = it.zig_index - 1; const param_ty = fn_info.param_types[param_index].toType(); - const param_llvm_ty = try self.dg.lowerType(param_ty); + const param_llvm_ty = try o.lowerType(param_ty); const alignment = param_ty.abiAlignment(mod); - self.dg.addByRefParamAttrs(call, it.llvm_index - 1, alignment, it.byval_attr, param_llvm_ty); + o.addByRefParamAttrs(call, it.llvm_index - 1, alignment, it.byval_attr, param_llvm_ty); }, .byref_mut => { - self.dg.addArgAttr(call, it.llvm_index - 1, "noundef"); + o.addArgAttr(call, it.llvm_index - 1, "noundef"); }, // No attributes needed for these. .no_bits, @@ -4800,18 +4789,18 @@ pub const FuncGen = struct { if (math.cast(u5, it.zig_index - 1)) |i| { if (@truncate(u1, fn_info.noalias_bits >> i) != 0) { - self.dg.addArgAttr(call, llvm_arg_i, "noalias"); + o.addArgAttr(call, llvm_arg_i, "noalias"); } } if (param_ty.zigTypeTag(mod) != .Optional) { - self.dg.addArgAttr(call, llvm_arg_i, "nonnull"); + o.addArgAttr(call, llvm_arg_i, "nonnull"); } if (ptr_info.flags.is_const) { - self.dg.addArgAttr(call, llvm_arg_i, "readonly"); + o.addArgAttr(call, llvm_arg_i, "readonly"); } const elem_align = ptr_info.flags.alignment.toByteUnitsOptional() orelse @max(ptr_info.child.toType().abiAlignment(mod), 1); - self.dg.addArgAttrInt(call, llvm_arg_i, "align", elem_align); + o.addArgAttrInt(call, llvm_arg_i, "align", elem_align); }, }; } @@ -4824,7 +4813,7 @@ pub const FuncGen = struct { return null; } - const llvm_ret_ty = try self.dg.lowerType(return_type); + const llvm_ret_ty = try o.lowerType(return_type); if (ret_ptr) |rp| { call.setCallSret(llvm_ret_ty); @@ -4838,13 +4827,13 @@ pub const FuncGen = struct { } } - const abi_ret_ty = try lowerFnRetTy(self.dg, fn_info); + const abi_ret_ty = try lowerFnRetTy(o, fn_info); if (abi_ret_ty != llvm_ret_ty) { // In this case the function return type is honoring the calling convention by having // a different LLVM type than the usual one. We solve this here at the callsite // by using our canonical type, then loading it if necessary. - const alignment = self.dg.object.target_data.abiAlignmentOfType(abi_ret_ty); + const alignment = o.target_data.abiAlignmentOfType(abi_ret_ty); const rp = self.buildAlloca(llvm_ret_ty, alignment); const store_inst = self.builder.buildStore(call, rp); store_inst.setAlignment(alignment); @@ -4871,7 +4860,8 @@ pub const FuncGen = struct { } fn airRet(self: *FuncGen, inst: Air.Inst.Index) !?*llvm.Value { - const mod = self.dg.module; + const o = self.dg.object; + const mod = o.module; const un_op = self.air.instructions.items(.data)[inst].un_op; const ret_ty = self.typeOf(un_op); if (self.ret_ptr) |ret_ptr| { @@ -4887,7 +4877,7 @@ pub const FuncGen = struct { // Functions with an empty error set are emitted with an error code // return type and return zero so they can be function pointers coerced // to functions that return anyerror. - const err_int = try self.dg.lowerType(Type.anyerror); + const err_int = try o.lowerType(Type.anyerror); _ = self.builder.buildRet(err_int.constInt(0, .False)); } else { _ = self.builder.buildRetVoid(); @@ -4895,7 +4885,7 @@ pub const FuncGen = struct { return null; } - const abi_ret_ty = try lowerFnRetTy(self.dg, fn_info); + const abi_ret_ty = try lowerFnRetTy(o, fn_info); const operand = try self.resolveInst(un_op); const alignment = ret_ty.abiAlignment(mod); @@ -4924,7 +4914,8 @@ pub const FuncGen = struct { } fn airRetLoad(self: *FuncGen, inst: Air.Inst.Index) !?*llvm.Value { - const mod = self.dg.module; + const o = self.dg.object; + const mod = o.module; const un_op = self.air.instructions.items(.data)[inst].un_op; const ptr_ty = self.typeOf(un_op); const ret_ty = ptr_ty.childType(mod); @@ -4934,7 +4925,7 @@ pub const FuncGen = struct { // Functions with an empty error set are emitted with an error code // return type and return zero so they can be function pointers coerced // to functions that return anyerror. - const err_int = try self.dg.lowerType(Type.anyerror); + const err_int = try o.lowerType(Type.anyerror); _ = self.builder.buildRet(err_int.constInt(0, .False)); } else { _ = self.builder.buildRetVoid(); @@ -4946,7 +4937,7 @@ pub const FuncGen = struct { return null; } const ptr = try self.resolveInst(un_op); - const abi_ret_ty = try lowerFnRetTy(self.dg, fn_info); + const abi_ret_ty = try lowerFnRetTy(o, fn_info); const loaded = self.builder.buildLoad(abi_ret_ty, ptr, ""); loaded.setAlignment(ret_ty.abiAlignment(mod)); _ = self.builder.buildRet(loaded); @@ -4954,32 +4945,34 @@ pub const FuncGen = struct { } fn airCVaArg(self: *FuncGen, inst: Air.Inst.Index) !?*llvm.Value { + const o = self.dg.object; const ty_op = self.air.instructions.items(.data)[inst].ty_op; const list = try self.resolveInst(ty_op.operand); const arg_ty = self.air.getRefType(ty_op.ty); - const llvm_arg_ty = try self.dg.lowerType(arg_ty); + const llvm_arg_ty = try o.lowerType(arg_ty); return self.builder.buildVAArg(list, llvm_arg_ty, ""); } fn airCVaCopy(self: *FuncGen, inst: Air.Inst.Index) !?*llvm.Value { + const o = self.dg.object; const ty_op = self.air.instructions.items(.data)[inst].ty_op; const src_list = try self.resolveInst(ty_op.operand); const va_list_ty = self.air.getRefType(ty_op.ty); - const llvm_va_list_ty = try self.dg.lowerType(va_list_ty); - const mod = self.dg.module; + const llvm_va_list_ty = try o.lowerType(va_list_ty); + const mod = o.module; const result_alignment = va_list_ty.abiAlignment(mod); const dest_list = self.buildAlloca(llvm_va_list_ty, result_alignment); const llvm_fn_name = "llvm.va_copy"; - const llvm_fn = self.dg.object.llvm_module.getNamedFunction(llvm_fn_name) orelse blk: { + const llvm_fn = o.llvm_module.getNamedFunction(llvm_fn_name) orelse blk: { const param_types = [_]*llvm.Type{ self.context.pointerType(0), self.context.pointerType(0), }; const fn_type = llvm.functionType(self.context.voidType(), ¶m_types, param_types.len, .False); - break :blk self.dg.object.llvm_module.addFunction(llvm_fn_name, fn_type); + break :blk o.llvm_module.addFunction(llvm_fn_name, fn_type); }; const args: [2]*llvm.Value = .{ dest_list, src_list }; @@ -4995,14 +4988,15 @@ pub const FuncGen = struct { } fn airCVaEnd(self: *FuncGen, inst: Air.Inst.Index) !?*llvm.Value { + const o = self.dg.object; const un_op = self.air.instructions.items(.data)[inst].un_op; const list = try self.resolveInst(un_op); const llvm_fn_name = "llvm.va_end"; - const llvm_fn = self.dg.object.llvm_module.getNamedFunction(llvm_fn_name) orelse blk: { + const llvm_fn = o.llvm_module.getNamedFunction(llvm_fn_name) orelse blk: { const param_types = [_]*llvm.Type{self.context.pointerType(0)}; const fn_type = llvm.functionType(self.context.voidType(), ¶m_types, param_types.len, .False); - break :blk self.dg.object.llvm_module.addFunction(llvm_fn_name, fn_type); + break :blk o.llvm_module.addFunction(llvm_fn_name, fn_type); }; const args: [1]*llvm.Value = .{list}; _ = self.builder.buildCall(llvm_fn.globalGetValueType(), llvm_fn, &args, args.len, .Fast, .Auto, ""); @@ -5010,18 +5004,19 @@ pub const FuncGen = struct { } fn airCVaStart(self: *FuncGen, inst: Air.Inst.Index) !?*llvm.Value { - const mod = self.dg.module; + const o = self.dg.object; + const mod = o.module; const va_list_ty = self.typeOfIndex(inst); - const llvm_va_list_ty = try self.dg.lowerType(va_list_ty); + const llvm_va_list_ty = try o.lowerType(va_list_ty); const result_alignment = va_list_ty.abiAlignment(mod); const list = self.buildAlloca(llvm_va_list_ty, result_alignment); const llvm_fn_name = "llvm.va_start"; - const llvm_fn = self.dg.object.llvm_module.getNamedFunction(llvm_fn_name) orelse blk: { + const llvm_fn = o.llvm_module.getNamedFunction(llvm_fn_name) orelse blk: { const param_types = [_]*llvm.Type{self.context.pointerType(0)}; const fn_type = llvm.functionType(self.context.voidType(), ¶m_types, param_types.len, .False); - break :blk self.dg.object.llvm_module.addFunction(llvm_fn_name, fn_type); + break :blk o.llvm_module.addFunction(llvm_fn_name, fn_type); }; const args: [1]*llvm.Value = .{list}; _ = self.builder.buildCall(llvm_fn.globalGetValueType(), llvm_fn, &args, args.len, .Fast, .Auto, ""); @@ -5075,7 +5070,8 @@ pub const FuncGen = struct { operand_ty: Type, op: math.CompareOperator, ) Allocator.Error!*llvm.Value { - const mod = self.dg.module; + const o = self.dg.object; + const mod = o.module; const scalar_ty = operand_ty.scalarType(mod); const int_ty = switch (scalar_ty.zigTypeTag(mod)) { .Enum => scalar_ty.intTagType(mod), @@ -5090,7 +5086,7 @@ 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, mod); - const opt_llvm_ty = try self.dg.lowerType(scalar_ty); + const opt_llvm_ty = try o.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); @@ -5169,7 +5165,8 @@ pub const FuncGen = struct { } fn airBlock(self: *FuncGen, inst: Air.Inst.Index) !?*llvm.Value { - const mod = self.dg.module; + const o = self.dg.object; + const mod = o.module; const ty_pl = self.air.instructions.items(.data)[inst].ty_pl; const extra = self.air.extraData(Air.Block, ty_pl.payload); const body = self.air.extra[extra.end..][0..extra.data.body_len]; @@ -5199,7 +5196,7 @@ pub const FuncGen = struct { const is_body = inst_ty.zigTypeTag(mod) == .Fn; if (!is_body and !inst_ty.hasRuntimeBitsIgnoreComptime(mod)) return null; - const raw_llvm_ty = try self.dg.lowerType(inst_ty); + const raw_llvm_ty = try o.lowerType(inst_ty); const llvm_ty = ty: { // If the zig tag type is a function, this represents an actual function body; not @@ -5222,12 +5219,13 @@ pub const FuncGen = struct { } fn airBr(self: *FuncGen, inst: Air.Inst.Index) !?*llvm.Value { + const o = self.dg.object; const branch = self.air.instructions.items(.data)[inst].br; const block = self.blocks.get(branch.block_inst).?; // Add the values to the lists only if the break provides a value. const operand_ty = self.typeOf(branch.operand); - const mod = self.dg.module; + const mod = o.module; if (operand_ty.hasRuntimeBitsIgnoreComptime(mod) or operand_ty.zigTypeTag(mod) == .Fn) { const val = try self.resolveInst(branch.operand); @@ -5264,7 +5262,8 @@ pub const FuncGen = struct { } fn airTry(self: *FuncGen, body_tail: []const Air.Inst.Index) !?*llvm.Value { - const mod = self.dg.module; + const o = self.dg.object; + const mod = o.module; const inst = body_tail[0]; const pl_op = self.air.instructions.items(.data)[inst].pl_op; const err_union = try self.resolveInst(pl_op.operand); @@ -5278,7 +5277,8 @@ pub const FuncGen = struct { } fn airTryPtr(self: *FuncGen, inst: Air.Inst.Index) !?*llvm.Value { - const mod = self.dg.module; + const o = self.dg.object; + const mod = o.module; const ty_pl = self.air.instructions.items(.data)[inst].ty_pl; const extra = self.air.extraData(Air.TryPtr, ty_pl.payload); const err_union_ptr = try self.resolveInst(extra.data.ptr); @@ -5297,14 +5297,15 @@ pub const FuncGen = struct { can_elide_load: bool, is_unused: bool, ) !?*llvm.Value { - const mod = fg.dg.module; + const o = fg.dg.object; + const mod = o.module; const payload_ty = err_union_ty.errorUnionPayload(mod); const payload_has_bits = payload_ty.hasRuntimeBitsIgnoreComptime(mod); - const err_union_llvm_ty = try fg.dg.lowerType(err_union_ty); + const err_union_llvm_ty = try o.lowerType(err_union_ty); if (!err_union_ty.errorUnionSet(mod).errorSetIsEmpty(mod)) { const is_err = err: { - const err_set_ty = try fg.dg.lowerType(Type.anyerror); + const err_set_ty = try o.lowerType(Type.anyerror); const zero = err_set_ty.constNull(); if (!payload_has_bits) { // TODO add alignment to this load @@ -5359,7 +5360,8 @@ pub const FuncGen = struct { } fn airSwitchBr(self: *FuncGen, inst: Air.Inst.Index) !?*llvm.Value { - const mod = self.dg.module; + const o = self.dg.object; + const mod = o.module; const pl_op = self.air.instructions.items(.data)[inst].pl_op; const cond = try self.resolveInst(pl_op.operand); const switch_br = self.air.extraData(Air.SwitchBr, pl_op.payload); @@ -5409,7 +5411,8 @@ pub const FuncGen = struct { } fn airLoop(self: *FuncGen, inst: Air.Inst.Index) !?*llvm.Value { - const mod = self.dg.module; + const o = self.dg.object; + const mod = o.module; const ty_pl = self.air.instructions.items(.data)[inst].ty_pl; const loop = self.air.extraData(Air.Block, ty_pl.payload); const body = self.air.extra[loop.end..][0..loop.data.body_len]; @@ -5432,13 +5435,14 @@ pub const FuncGen = struct { } fn airArrayToSlice(self: *FuncGen, inst: Air.Inst.Index) !?*llvm.Value { - const mod = self.dg.module; + const o = self.dg.object; + const mod = o.module; const ty_op = self.air.instructions.items(.data)[inst].ty_op; const operand_ty = self.typeOf(ty_op.operand); const array_ty = operand_ty.childType(mod); - const llvm_usize = try self.dg.lowerType(Type.usize); + const llvm_usize = try o.lowerType(Type.usize); const len = llvm_usize.constInt(array_ty.arrayLen(mod), .False); - const slice_llvm_ty = try self.dg.lowerType(self.typeOfIndex(inst)); + const slice_llvm_ty = try o.lowerType(self.typeOfIndex(inst)); const operand = try self.resolveInst(ty_op.operand); if (!array_ty.hasRuntimeBitsIgnoreComptime(mod)) { const partial = self.builder.buildInsertValue(slice_llvm_ty.getUndef(), operand, 0, ""); @@ -5447,14 +5451,15 @@ pub const FuncGen = struct { const indices: [2]*llvm.Value = .{ llvm_usize.constNull(), llvm_usize.constNull(), }; - const array_llvm_ty = try self.dg.lowerType(array_ty); + const array_llvm_ty = try o.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, ""); } fn airFloatFromInt(self: *FuncGen, inst: Air.Inst.Index) !?*llvm.Value { - const mod = self.dg.module; + const o = self.dg.object; + const mod = o.module; const ty_op = self.air.instructions.items(.data)[inst].ty_op; const operand = try self.resolveInst(ty_op.operand); @@ -5463,7 +5468,7 @@ pub const FuncGen = struct { const dest_ty = self.typeOfIndex(inst); const dest_scalar_ty = dest_ty.scalarType(mod); - const dest_llvm_ty = try self.dg.lowerType(dest_ty); + const dest_llvm_ty = try o.lowerType(dest_ty); const target = mod.getTarget(); if (intrinsicsAllowed(dest_scalar_ty, target)) { @@ -5513,7 +5518,8 @@ pub const FuncGen = struct { fn airIntFromFloat(self: *FuncGen, inst: Air.Inst.Index, want_fast_math: bool) !?*llvm.Value { self.builder.setFastMath(want_fast_math); - const mod = self.dg.module; + const o = self.dg.object; + const mod = o.module; const target = mod.getTarget(); const ty_op = self.air.instructions.items(.data)[inst].ty_op; @@ -5523,7 +5529,7 @@ pub const FuncGen = struct { const dest_ty = self.typeOfIndex(inst); const dest_scalar_ty = dest_ty.scalarType(mod); - const dest_llvm_ty = try self.dg.lowerType(dest_ty); + const dest_llvm_ty = try o.lowerType(dest_ty); if (intrinsicsAllowed(operand_scalar_ty, target)) { // TODO set fast math flag @@ -5555,7 +5561,7 @@ pub const FuncGen = struct { compiler_rt_dest_abbrev, }) catch unreachable; - const operand_llvm_ty = try self.dg.lowerType(operand_ty); + const operand_llvm_ty = try o.lowerType(operand_ty); const param_types = [1]*llvm.Type{operand_llvm_ty}; const libc_fn = self.getLibcFunction(fn_name, ¶m_types, libc_ret_ty); const params = [1]*llvm.Value{operand}; @@ -5568,7 +5574,8 @@ pub const FuncGen = struct { } fn sliceOrArrayPtr(fg: *FuncGen, ptr: *llvm.Value, ty: Type) *llvm.Value { - const mod = fg.dg.module; + const o = fg.dg.object; + const mod = o.module; if (ty.isSlice(mod)) { return fg.builder.buildExtractValue(ptr, 0, ""); } else { @@ -5577,7 +5584,8 @@ pub const FuncGen = struct { } fn sliceOrArrayLenInBytes(fg: *FuncGen, ptr: *llvm.Value, ty: Type) *llvm.Value { - const mod = fg.dg.module; + const o = fg.dg.object; + const mod = o.module; const target = mod.getTarget(); const llvm_usize_ty = fg.context.intType(target.ptrBitWidth()); switch (ty.ptrSize(mod)) { @@ -5606,24 +5614,26 @@ pub const FuncGen = struct { } fn airPtrSliceFieldPtr(self: *FuncGen, inst: Air.Inst.Index, index: c_uint) !?*llvm.Value { - const mod = self.dg.module; + const o = self.dg.object; + const mod = o.module; const ty_op = self.air.instructions.items(.data)[inst].ty_op; const slice_ptr = try self.resolveInst(ty_op.operand); const slice_ptr_ty = self.typeOf(ty_op.operand); - const slice_llvm_ty = try self.dg.lowerPtrElemTy(slice_ptr_ty.childType(mod)); + const slice_llvm_ty = try o.lowerPtrElemTy(slice_ptr_ty.childType(mod)); return self.builder.buildStructGEP(slice_llvm_ty, slice_ptr, index, ""); } fn airSliceElemVal(self: *FuncGen, body_tail: []const Air.Inst.Index) !?*llvm.Value { - const mod = self.dg.module; + const o = self.dg.object; + const mod = o.module; const inst = body_tail[0]; const bin_op = self.air.instructions.items(.data)[inst].bin_op; const slice_ty = self.typeOf(bin_op.lhs); const slice = try self.resolveInst(bin_op.lhs); const index = try self.resolveInst(bin_op.rhs); const elem_ty = slice_ty.childType(mod); - const llvm_elem_ty = try self.dg.lowerPtrElemTy(elem_ty); + const llvm_elem_ty = try o.lowerPtrElemTy(elem_ty); const base_ptr = self.builder.buildExtractValue(slice, 0, ""); const indices: [1]*llvm.Value = .{index}; const ptr = self.builder.buildInBoundsGEP(llvm_elem_ty, base_ptr, &indices, indices.len, ""); @@ -5638,28 +5648,30 @@ pub const FuncGen = struct { } fn airSliceElemPtr(self: *FuncGen, inst: Air.Inst.Index) !?*llvm.Value { - const mod = self.dg.module; + const o = self.dg.object; + const mod = o.module; 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.typeOf(bin_op.lhs); const slice = try self.resolveInst(bin_op.lhs); const index = try self.resolveInst(bin_op.rhs); - const llvm_elem_ty = try self.dg.lowerPtrElemTy(slice_ty.childType(mod)); + const llvm_elem_ty = try o.lowerPtrElemTy(slice_ty.childType(mod)); const base_ptr = self.builder.buildExtractValue(slice, 0, ""); const indices: [1]*llvm.Value = .{index}; return self.builder.buildInBoundsGEP(llvm_elem_ty, base_ptr, &indices, indices.len, ""); } fn airArrayElemVal(self: *FuncGen, body_tail: []const Air.Inst.Index) !?*llvm.Value { - const mod = self.dg.module; + const o = self.dg.object; + const mod = o.module; const inst = body_tail[0]; const bin_op = self.air.instructions.items(.data)[inst].bin_op; const array_ty = self.typeOf(bin_op.lhs); const array_llvm_val = try self.resolveInst(bin_op.lhs); const rhs = try self.resolveInst(bin_op.rhs); - const array_llvm_ty = try self.dg.lowerType(array_ty); + const array_llvm_ty = try o.lowerType(array_ty); const elem_ty = array_ty.childType(mod); if (isByRef(array_ty, mod)) { const indices: [2]*llvm.Value = .{ self.context.intType(32).constNull(), rhs }; @@ -5671,7 +5683,7 @@ pub const FuncGen = struct { return self.loadByRef(elem_ptr, elem_ty, elem_ty.abiAlignment(mod), false); } else { const lhs_index = Air.refToIndex(bin_op.lhs).?; - const elem_llvm_ty = try self.dg.lowerType(elem_ty); + const elem_llvm_ty = try o.lowerType(elem_ty); if (self.air.instructions.items(.tag)[lhs_index] == .load) { const load_data = self.air.instructions.items(.data)[lhs_index]; const load_ptr = load_data.ty_op.operand; @@ -5695,12 +5707,13 @@ pub const FuncGen = struct { } fn airPtrElemVal(self: *FuncGen, body_tail: []const Air.Inst.Index) !?*llvm.Value { - const mod = self.dg.module; + const o = self.dg.object; + const mod = o.module; const inst = body_tail[0]; const bin_op = self.air.instructions.items(.data)[inst].bin_op; const ptr_ty = self.typeOf(bin_op.lhs); const elem_ty = ptr_ty.childType(mod); - const llvm_elem_ty = try self.dg.lowerPtrElemTy(elem_ty); + const llvm_elem_ty = try o.lowerPtrElemTy(elem_ty); 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 @@ -5723,12 +5736,13 @@ pub const FuncGen = struct { } fn airPtrElemPtr(self: *FuncGen, inst: Air.Inst.Index) !?*llvm.Value { - const mod = self.dg.module; + const o = self.dg.object; + const mod = o.module; const ty_pl = self.air.instructions.items(.data)[inst].ty_pl; const bin_op = self.air.extraData(Air.Bin, ty_pl.payload).data; const ptr_ty = self.typeOf(bin_op.lhs); const elem_ty = ptr_ty.childType(mod); - if (!elem_ty.hasRuntimeBitsIgnoreComptime(mod)) return self.dg.lowerPtrToVoid(ptr_ty); + if (!elem_ty.hasRuntimeBitsIgnoreComptime(mod)) return o.lowerPtrToVoid(ptr_ty); const base_ptr = try self.resolveInst(bin_op.lhs); const rhs = try self.resolveInst(bin_op.rhs); @@ -5736,7 +5750,7 @@ pub const FuncGen = struct { const elem_ptr = self.air.getRefType(ty_pl.ty); if (elem_ptr.ptrInfo(mod).flags.vector_index != .none) return base_ptr; - const llvm_elem_ty = try self.dg.lowerPtrElemTy(elem_ty); + const llvm_elem_ty = try o.lowerPtrElemTy(elem_ty); if (ptr_ty.isSinglePointer(mod)) { // If this is a single-item pointer to an array, we need another index in the GEP. const indices: [2]*llvm.Value = .{ self.context.intType(32).constNull(), rhs }; @@ -5767,7 +5781,8 @@ pub const FuncGen = struct { } fn airStructFieldVal(self: *FuncGen, body_tail: []const Air.Inst.Index) !?*llvm.Value { - const mod = self.dg.module; + const o = self.dg.object; + const mod = o.module; const inst = body_tail[0]; const ty_pl = self.air.instructions.items(.data)[inst].ty_pl; const struct_field = self.air.extraData(Air.StructField, ty_pl.payload).data; @@ -5789,7 +5804,7 @@ pub const FuncGen = struct { const containing_int = struct_llvm_val; const shift_amt = containing_int.typeOf().constInt(bit_offset, .False); const shifted_value = self.builder.buildLShr(containing_int, shift_amt, ""); - const elem_llvm_ty = try self.dg.lowerType(field_ty); + const elem_llvm_ty = try o.lowerType(field_ty); if (field_ty.zigTypeTag(mod) == .Float or field_ty.zigTypeTag(mod) == .Vector) { const elem_bits = @intCast(c_uint, field_ty.bitSize(mod)); const same_size_int = self.context.intType(elem_bits); @@ -5811,7 +5826,7 @@ pub const FuncGen = struct { .Union => { assert(struct_ty.containerLayout(mod) == .Packed); const containing_int = struct_llvm_val; - const elem_llvm_ty = try self.dg.lowerType(field_ty); + const elem_llvm_ty = try o.lowerType(field_ty); if (field_ty.zigTypeTag(mod) == .Float or field_ty.zigTypeTag(mod) == .Vector) { const elem_bits = @intCast(c_uint, field_ty.bitSize(mod)); const same_size_int = self.context.intType(elem_bits); @@ -5833,7 +5848,7 @@ pub const FuncGen = struct { .Struct => { assert(struct_ty.containerLayout(mod) != .Packed); const llvm_field = llvmField(struct_ty, field_index, mod).?; - const struct_llvm_ty = try self.dg.lowerType(struct_ty); + const struct_llvm_ty = try o.lowerType(struct_ty); const field_ptr = self.builder.buildStructGEP(struct_llvm_ty, struct_llvm_val, llvm_field.index, ""); const field_ptr_ty = try mod.ptrType(.{ .child = llvm_field.ty.toIntern(), @@ -5852,11 +5867,11 @@ pub const FuncGen = struct { } }, .Union => { - const union_llvm_ty = try self.dg.lowerType(struct_ty); + const union_llvm_ty = try o.lowerType(struct_ty); const layout = struct_ty.unionGetLayout(mod); const payload_index = @intFromBool(layout.tag_align >= layout.payload_align); const field_ptr = self.builder.buildStructGEP(union_llvm_ty, struct_llvm_val, payload_index, ""); - const llvm_field_ty = try self.dg.lowerType(field_ty); + const llvm_field_ty = try o.lowerType(field_ty); if (isByRef(field_ty, mod)) { if (canElideLoad(self, body_tail)) return field_ptr; @@ -5871,17 +5886,18 @@ pub const FuncGen = struct { } fn airFieldParentPtr(self: *FuncGen, inst: Air.Inst.Index) !?*llvm.Value { - const mod = self.dg.module; + const o = self.dg.object; + const mod = o.module; const ty_pl = self.air.instructions.items(.data)[inst].ty_pl; const extra = self.air.extraData(Air.FieldParentPtr, ty_pl.payload).data; const field_ptr = try self.resolveInst(extra.field_ptr); - const target = self.dg.module.getTarget(); + const target = o.module.getTarget(); const parent_ty = self.air.getRefType(ty_pl.ty).childType(mod); const field_offset = parent_ty.structFieldOffset(extra.field_index, mod); - const res_ty = try self.dg.lowerType(self.air.getRefType(ty_pl.ty)); + const res_ty = try o.lowerType(self.air.getRefType(ty_pl.ty)); if (field_offset == 0) { return field_ptr; } @@ -5919,14 +5935,15 @@ pub const FuncGen = struct { } fn airDbgInlineBegin(self: *FuncGen, inst: Air.Inst.Index) !?*llvm.Value { - const dib = self.dg.object.di_builder orelse return null; + const o = self.dg.object; + const dib = o.di_builder orelse return null; const ty_fn = self.air.instructions.items(.data)[inst].ty_fn; - const mod = self.dg.module; + const mod = o.module; const func = mod.funcPtr(ty_fn.func); const decl_index = func.owner_decl; const decl = mod.declPtr(decl_index); - const di_file = try self.dg.object.getDIFile(self.gpa, mod.namespacePtr(decl.src_namespace).file_scope); + const di_file = try o.getDIFile(self.gpa, mod.namespacePtr(decl.src_namespace).file_scope); self.di_file = di_file; const line_number = decl.src_line + 1; const cur_debug_location = self.builder.getCurrentDebugLocation2(); @@ -5955,7 +5972,7 @@ pub const FuncGen = struct { .section_is_generic = false, .addrspace_is_generic = false, }); - const fn_di_ty = try self.dg.object.lowerDebugType(fn_ty, .full); + const fn_di_ty = try o.lowerDebugType(fn_ty, .full); const subprogram = dib.createFunction( di_file.toScope(), mod.intern_pool.stringToSlice(decl.name), @@ -5978,13 +5995,14 @@ pub const FuncGen = struct { } fn airDbgInlineEnd(self: *FuncGen, inst: Air.Inst.Index) !?*llvm.Value { - if (self.dg.object.di_builder == null) return null; + const o = self.dg.object; + if (o.di_builder == null) return null; const ty_fn = self.air.instructions.items(.data)[inst].ty_fn; - const mod = self.dg.module; + const mod = o.module; const func = mod.funcPtr(ty_fn.func); const decl = mod.declPtr(func.owner_decl); - const di_file = try self.dg.object.getDIFile(self.gpa, mod.namespacePtr(decl.src_namespace).file_scope); + const di_file = try o.getDIFile(self.gpa, mod.namespacePtr(decl.src_namespace).file_scope); self.di_file = di_file; const old = self.dbg_inlined.pop(); self.di_scope = old.scope; @@ -5993,7 +6011,8 @@ pub const FuncGen = struct { } fn airDbgBlockBegin(self: *FuncGen) !?*llvm.Value { - const dib = self.dg.object.di_builder orelse return null; + const o = self.dg.object; + const dib = o.di_builder orelse return null; const old_scope = self.di_scope.?; try self.dbg_block_stack.append(self.gpa, old_scope); const lexical_block = dib.createLexicalBlock(old_scope, self.di_file.?, self.prev_dbg_line, self.prev_dbg_column); @@ -6002,14 +6021,16 @@ pub const FuncGen = struct { } fn airDbgBlockEnd(self: *FuncGen) !?*llvm.Value { - if (self.dg.object.di_builder == null) return null; + const o = self.dg.object; + if (o.di_builder == null) return null; self.di_scope = self.dbg_block_stack.pop(); return null; } fn airDbgVarPtr(self: *FuncGen, inst: Air.Inst.Index) !?*llvm.Value { - const mod = self.dg.module; - const dib = self.dg.object.di_builder orelse return null; + const o = self.dg.object; + const mod = o.module; + const dib = o.di_builder orelse return null; const pl_op = self.air.instructions.items(.data)[inst].pl_op; const operand = try self.resolveInst(pl_op.operand); const name = self.air.nullTerminatedString(pl_op.payload); @@ -6020,7 +6041,7 @@ pub const FuncGen = struct { name.ptr, self.di_file.?, self.prev_dbg_line, - try self.dg.object.lowerDebugType(ptr_ty.childType(mod), .full), + try o.lowerDebugType(ptr_ty.childType(mod), .full), true, // always preserve 0, // flags ); @@ -6035,13 +6056,14 @@ pub const FuncGen = struct { } fn airDbgVarVal(self: *FuncGen, inst: Air.Inst.Index) !?*llvm.Value { - const dib = self.dg.object.di_builder orelse return null; + const o = self.dg.object; + const dib = o.di_builder orelse return null; const pl_op = self.air.instructions.items(.data)[inst].pl_op; const operand = try self.resolveInst(pl_op.operand); const operand_ty = self.typeOf(pl_op.operand); const name = self.air.nullTerminatedString(pl_op.payload); - if (needDbgVarWorkaround(self.dg)) { + if (needDbgVarWorkaround(o)) { return null; } @@ -6050,7 +6072,7 @@ pub const FuncGen = struct { name.ptr, self.di_file.?, self.prev_dbg_line, - try self.dg.object.lowerDebugType(operand_ty, .full), + try o.lowerDebugType(operand_ty, .full), true, // always preserve 0, // flags ); @@ -6060,10 +6082,10 @@ pub const FuncGen = struct { null; const debug_loc = llvm.getDebugLoc(self.prev_dbg_line, self.prev_dbg_column, self.di_scope.?, inlined_at); const insert_block = self.builder.getInsertBlock(); - const mod = self.dg.module; + const mod = o.module; if (isByRef(operand_ty, mod)) { _ = dib.insertDeclareAtEnd(operand, di_local_var, debug_loc, insert_block); - } else if (self.dg.module.comp.bin_file.options.optimize_mode == .Debug) { + } else if (o.module.comp.bin_file.options.optimize_mode == .Debug) { const alignment = operand_ty.abiAlignment(mod); const alloca = self.buildAlloca(operand.typeOf(), alignment); const store_inst = self.builder.buildStore(operand, alloca); @@ -6082,6 +6104,7 @@ pub const FuncGen = struct { // We don't have such an assembler implemented yet though. For now, // this implementation feeds the inline assembly code directly to LLVM. + const o = self.dg.object; const ty_pl = self.air.instructions.items(.data)[inst].ty_pl; const extra = self.air.extraData(Air.Asm, ty_pl.payload); const is_volatile = @truncate(u1, extra.data.flags >> 31) != 0; @@ -6112,7 +6135,7 @@ pub const FuncGen = struct { // This stores whether we need to add an elementtype attribute and // if so, the element type itself. const llvm_param_attrs = try arena.alloc(?*llvm.Type, max_param_count); - const mod = self.dg.module; + const mod = o.module; const target = mod.getTarget(); var llvm_ret_i: usize = 0; @@ -6142,7 +6165,7 @@ pub const FuncGen = struct { const output_inst = try self.resolveInst(output); const output_ty = self.typeOf(output); assert(output_ty.zigTypeTag(mod) == .Pointer); - const elem_llvm_ty = try self.dg.lowerPtrElemTy(output_ty.childType(mod)); + const elem_llvm_ty = try o.lowerPtrElemTy(output_ty.childType(mod)); if (llvm_ret_indirect[i]) { // Pass the result by reference as an indirect output (e.g. "=*m") @@ -6159,7 +6182,7 @@ pub const FuncGen = struct { } } else { const ret_ty = self.typeOfIndex(inst); - llvm_ret_types[llvm_ret_i] = try self.dg.lowerType(ret_ty); + llvm_ret_types[llvm_ret_i] = try o.lowerType(ret_ty); llvm_ret_i += 1; } @@ -6196,13 +6219,13 @@ pub const FuncGen = struct { const arg_ty = self.typeOf(input); var llvm_elem_ty: ?*llvm.Type = null; if (isByRef(arg_ty, mod)) { - llvm_elem_ty = try self.dg.lowerPtrElemTy(arg_ty); + llvm_elem_ty = try o.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(); } else { const alignment = arg_ty.abiAlignment(mod); - const arg_llvm_ty = try self.dg.lowerType(arg_ty); + const arg_llvm_ty = try o.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; @@ -6243,7 +6266,7 @@ pub const FuncGen = struct { // an elementtype(<ty>) attribute. if (constraint[0] == '*') { llvm_param_attrs[llvm_param_i] = llvm_elem_ty orelse - try self.dg.lowerPtrElemTy(arg_ty.childType(mod)); + try o.lowerPtrElemTy(arg_ty.childType(mod)); } else { llvm_param_attrs[llvm_param_i] = null; } @@ -6434,12 +6457,13 @@ pub const FuncGen = struct { operand_is_ptr: bool, pred: llvm.IntPredicate, ) !?*llvm.Value { - const mod = self.dg.module; + const o = self.dg.object; + const mod = o.module; const un_op = self.air.instructions.items(.data)[inst].un_op; const operand = try self.resolveInst(un_op); const operand_ty = self.typeOf(un_op); const optional_ty = if (operand_is_ptr) operand_ty.childType(mod) else operand_ty; - const optional_llvm_ty = try self.dg.lowerType(optional_ty); + const optional_llvm_ty = try o.lowerType(optional_ty); const payload_ty = optional_ty.optionalChild(mod); if (optional_ty.optionalReprIsPayload(mod)) { const loaded = if (operand_is_ptr) @@ -6448,7 +6472,7 @@ pub const FuncGen = struct { operand; if (payload_ty.isSlice(mod)) { const slice_ptr = self.builder.buildExtractValue(loaded, 0, ""); - const ptr_ty = try self.dg.lowerType(payload_ty.slicePtrFieldType(mod)); + const ptr_ty = try o.lowerType(payload_ty.slicePtrFieldType(mod)); return self.builder.buildICmp(pred, slice_ptr, ptr_ty.constNull(), ""); } return self.builder.buildICmp(pred, loaded, optional_llvm_ty.constNull(), ""); @@ -6480,13 +6504,14 @@ pub const FuncGen = struct { op: llvm.IntPredicate, operand_is_ptr: bool, ) !?*llvm.Value { - const mod = self.dg.module; + const o = self.dg.object; + const mod = o.module; const un_op = self.air.instructions.items(.data)[inst].un_op; const operand = try self.resolveInst(un_op); const operand_ty = self.typeOf(un_op); const err_union_ty = if (operand_is_ptr) operand_ty.childType(mod) else operand_ty; const payload_ty = err_union_ty.errorUnionPayload(mod); - const err_set_ty = try self.dg.lowerType(Type.anyerror); + const err_set_ty = try o.lowerType(Type.anyerror); const zero = err_set_ty.constNull(); if (err_union_ty.errorUnionSet(mod).errorSetIsEmpty(mod)) { @@ -6500,7 +6525,7 @@ pub const FuncGen = struct { if (!payload_ty.hasRuntimeBitsIgnoreComptime(mod)) { const loaded = if (operand_is_ptr) - self.builder.buildLoad(try self.dg.lowerType(err_union_ty), operand, "") + self.builder.buildLoad(try o.lowerType(err_union_ty), operand, "") else operand; return self.builder.buildICmp(op, loaded, zero, ""); @@ -6509,7 +6534,7 @@ pub const FuncGen = struct { const err_field_index = errUnionErrorOffset(payload_ty, mod); if (operand_is_ptr or isByRef(err_union_ty, mod)) { - const err_union_llvm_ty = try self.dg.lowerType(err_union_ty); + const err_union_llvm_ty = try o.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, ""); @@ -6520,7 +6545,8 @@ pub const FuncGen = struct { } fn airOptionalPayloadPtr(self: *FuncGen, inst: Air.Inst.Index) !?*llvm.Value { - const mod = self.dg.module; + const o = self.dg.object; + const mod = o.module; const ty_op = self.air.instructions.items(.data)[inst].ty_op; const operand = try self.resolveInst(ty_op.operand); const optional_ty = self.typeOf(ty_op.operand).childType(mod); @@ -6534,14 +6560,15 @@ pub const FuncGen = struct { // The payload and the optional are the same value. return operand; } - const optional_llvm_ty = try self.dg.lowerType(optional_ty); + const optional_llvm_ty = try o.lowerType(optional_ty); return self.builder.buildStructGEP(optional_llvm_ty, operand, 0, ""); } fn airOptionalPayloadPtrSet(self: *FuncGen, inst: Air.Inst.Index) !?*llvm.Value { comptime assert(optional_layout_version == 3); - const mod = self.dg.module; + const o = self.dg.object; + const mod = o.module; const ty_op = self.air.instructions.items(.data)[inst].ty_op; const operand = try self.resolveInst(ty_op.operand); const optional_ty = self.typeOf(ty_op.operand).childType(mod); @@ -6559,7 +6586,7 @@ pub const FuncGen = struct { } // First set the non-null bit. - const optional_llvm_ty = try self.dg.lowerType(optional_ty); + const optional_llvm_ty = try o.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); @@ -6572,7 +6599,8 @@ pub const FuncGen = struct { } fn airOptionalPayload(self: *FuncGen, body_tail: []const Air.Inst.Index) !?*llvm.Value { - const mod = self.dg.module; + const o = self.dg.object; + const mod = o.module; const inst = body_tail[0]; const ty_op = self.air.instructions.items(.data)[inst].ty_op; const operand = try self.resolveInst(ty_op.operand); @@ -6585,7 +6613,7 @@ pub const FuncGen = struct { return operand; } - const opt_llvm_ty = try self.dg.lowerType(optional_ty); + const opt_llvm_ty = try o.lowerType(optional_ty); const can_elide_load = if (isByRef(payload_ty, mod)) self.canElideLoad(body_tail) else false; return self.optPayloadHandle(opt_llvm_ty, operand, optional_ty, can_elide_load); } @@ -6595,7 +6623,8 @@ pub const FuncGen = struct { body_tail: []const Air.Inst.Index, operand_is_ptr: bool, ) !?*llvm.Value { - const mod = self.dg.module; + const o = self.dg.object; + const mod = o.module; const inst = body_tail[0]; const ty_op = self.air.instructions.items(.data)[inst].ty_op; const operand = try self.resolveInst(ty_op.operand); @@ -6608,7 +6637,7 @@ pub const FuncGen = struct { return if (operand_is_ptr) operand else null; } const offset = errUnionPayloadOffset(payload_ty, mod); - const err_union_llvm_ty = try self.dg.lowerType(err_union_ty); + const err_union_llvm_ty = try o.lowerType(err_union_ty); if (operand_is_ptr) { return self.builder.buildStructGEP(err_union_llvm_ty, operand, offset, ""); } else if (isByRef(err_union_ty, mod)) { @@ -6631,13 +6660,14 @@ pub const FuncGen = struct { inst: Air.Inst.Index, operand_is_ptr: bool, ) !?*llvm.Value { - const mod = self.dg.module; + const o = self.dg.object; + const mod = o.module; const ty_op = self.air.instructions.items(.data)[inst].ty_op; const operand = try self.resolveInst(ty_op.operand); const operand_ty = self.typeOf(ty_op.operand); const err_union_ty = if (operand_is_ptr) operand_ty.childType(mod) else operand_ty; if (err_union_ty.errorUnionSet(mod).errorSetIsEmpty(mod)) { - const err_llvm_ty = try self.dg.lowerType(Type.anyerror); + const err_llvm_ty = try o.lowerType(Type.anyerror); if (operand_is_ptr) { return operand; } else { @@ -6645,7 +6675,7 @@ pub const FuncGen = struct { } } - const err_set_llvm_ty = try self.dg.lowerType(Type.anyerror); + const err_set_llvm_ty = try o.lowerType(Type.anyerror); const payload_ty = err_union_ty.errorUnionPayload(mod); if (!payload_ty.hasRuntimeBitsIgnoreComptime(mod)) { @@ -6656,7 +6686,7 @@ pub const FuncGen = struct { const offset = errUnionErrorOffset(payload_ty, mod); if (operand_is_ptr or isByRef(err_union_ty, mod)) { - const err_union_llvm_ty = try self.dg.lowerType(err_union_ty); + const err_union_llvm_ty = try o.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, ""); } @@ -6665,18 +6695,19 @@ pub const FuncGen = struct { } fn airErrUnionPayloadPtrSet(self: *FuncGen, inst: Air.Inst.Index) !?*llvm.Value { - const mod = self.dg.module; + const o = self.dg.object; + const mod = o.module; const ty_op = self.air.instructions.items(.data)[inst].ty_op; const operand = try self.resolveInst(ty_op.operand); const err_union_ty = self.typeOf(ty_op.operand).childType(mod); const payload_ty = err_union_ty.errorUnionPayload(mod); - const non_error_val = try self.dg.lowerValue(.{ .ty = Type.anyerror, .val = try mod.intValue(Type.err_int, 0) }); + const non_error_val = try o.lowerValue(.{ .ty = Type.anyerror, .val = try mod.intValue(Type.err_int, 0) }); if (!payload_ty.hasRuntimeBitsIgnoreComptime(mod)) { _ = self.builder.buildStore(non_error_val, operand); return operand; } - const err_union_llvm_ty = try self.dg.lowerType(err_union_ty); + const err_union_llvm_ty = try o.lowerType(err_union_ty); { const error_offset = errUnionErrorOffset(payload_ty, mod); // First set the non-error value. @@ -6704,14 +6735,15 @@ pub const FuncGen = struct { } fn airSaveErrReturnTraceIndex(self: *FuncGen, inst: Air.Inst.Index) !?*llvm.Value { + const o = self.dg.object; const ty_pl = self.air.instructions.items(.data)[inst].ty_pl; //const struct_ty = try self.resolveInst(ty_pl.ty); const struct_ty = self.air.getRefType(ty_pl.ty); const field_index = ty_pl.payload; - const mod = self.dg.module; + const mod = o.module; const llvm_field = llvmField(struct_ty, field_index, mod).?; - const struct_llvm_ty = try self.dg.lowerType(struct_ty); + const struct_llvm_ty = try o.lowerType(struct_ty); const field_ptr = self.builder.buildStructGEP(struct_llvm_ty, self.err_ret_trace.?, llvm_field.index, ""); const field_ptr_ty = try mod.ptrType(.{ .child = llvm_field.ty.toIntern(), @@ -6723,7 +6755,8 @@ pub const FuncGen = struct { } fn airWrapOptional(self: *FuncGen, inst: Air.Inst.Index) !?*llvm.Value { - const mod = self.dg.module; + const o = self.dg.object; + const mod = o.module; const ty_op = self.air.instructions.items(.data)[inst].ty_op; const payload_ty = self.typeOf(ty_op.operand); const non_null_bit = self.context.intType(8).constInt(1, .False); @@ -6734,7 +6767,7 @@ pub const FuncGen = struct { if (optional_ty.optionalReprIsPayload(mod)) { return operand; } - const llvm_optional_ty = try self.dg.lowerType(optional_ty); + const llvm_optional_ty = try o.lowerType(optional_ty); if (isByRef(optional_ty, mod)) { const optional_ptr = self.buildAlloca(llvm_optional_ty, optional_ty.abiAlignment(mod)); const payload_ptr = self.builder.buildStructGEP(llvm_optional_ty, optional_ptr, 0, ""); @@ -6749,7 +6782,8 @@ pub const FuncGen = struct { } fn airWrapErrUnionPayload(self: *FuncGen, inst: Air.Inst.Index) !?*llvm.Value { - const mod = self.dg.module; + const o = self.dg.object; + const mod = o.module; const ty_op = self.air.instructions.items(.data)[inst].ty_op; const err_un_ty = self.typeOfIndex(inst); const operand = try self.resolveInst(ty_op.operand); @@ -6757,8 +6791,8 @@ pub const FuncGen = struct { if (!payload_ty.hasRuntimeBitsIgnoreComptime(mod)) { return operand; } - const ok_err_code = (try self.dg.lowerType(Type.anyerror)).constNull(); - const err_un_llvm_ty = try self.dg.lowerType(err_un_ty); + const ok_err_code = (try o.lowerType(Type.anyerror)).constNull(); + const err_un_llvm_ty = try o.lowerType(err_un_ty); const payload_offset = errUnionPayloadOffset(payload_ty, mod); const error_offset = errUnionErrorOffset(payload_ty, mod); @@ -6778,7 +6812,8 @@ pub const FuncGen = struct { } fn airWrapErrUnionErr(self: *FuncGen, inst: Air.Inst.Index) !?*llvm.Value { - const mod = self.dg.module; + const o = self.dg.object; + const mod = o.module; const ty_op = self.air.instructions.items(.data)[inst].ty_op; const err_un_ty = self.typeOfIndex(inst); const payload_ty = err_un_ty.errorUnionPayload(mod); @@ -6786,7 +6821,7 @@ pub const FuncGen = struct { if (!payload_ty.hasRuntimeBitsIgnoreComptime(mod)) { return operand; } - const err_un_llvm_ty = try self.dg.lowerType(err_un_ty); + const err_un_llvm_ty = try o.lowerType(err_un_ty); const payload_offset = errUnionPayloadOffset(payload_ty, mod); const error_offset = errUnionErrorOffset(payload_ty, mod); @@ -6831,7 +6866,8 @@ pub const FuncGen = struct { } fn airVectorStoreElem(self: *FuncGen, inst: Air.Inst.Index) !?*llvm.Value { - const mod = self.dg.module; + const o = self.dg.object; + const mod = o.module; const data = self.air.instructions.items(.data)[inst].vector_store_elem; const extra = self.air.extraData(Air.Bin, data.payload).data; @@ -6841,7 +6877,7 @@ pub const FuncGen = struct { const operand = try self.resolveInst(extra.rhs); const loaded_vector = blk: { - const elem_llvm_ty = try self.dg.lowerType(vector_ptr_ty.childType(mod)); + const elem_llvm_ty = try o.lowerType(vector_ptr_ty.childType(mod)); const load_inst = self.builder.buildLoad(elem_llvm_ty, vector_ptr, ""); load_inst.setAlignment(vector_ptr_ty.ptrAlignment(mod)); load_inst.setVolatile(llvm.Bool.fromBool(vector_ptr_ty.isVolatilePtr(mod))); @@ -6853,7 +6889,8 @@ pub const FuncGen = struct { } fn airMin(self: *FuncGen, inst: Air.Inst.Index) !?*llvm.Value { - const mod = self.dg.module; + const o = self.dg.object; + const mod = o.module; const bin_op = self.air.instructions.items(.data)[inst].bin_op; const lhs = try self.resolveInst(bin_op.lhs); const rhs = try self.resolveInst(bin_op.rhs); @@ -6865,7 +6902,8 @@ pub const FuncGen = struct { } fn airMax(self: *FuncGen, inst: Air.Inst.Index) !?*llvm.Value { - const mod = self.dg.module; + const o = self.dg.object; + const mod = o.module; const bin_op = self.air.instructions.items(.data)[inst].bin_op; const lhs = try self.resolveInst(bin_op.lhs); const rhs = try self.resolveInst(bin_op.rhs); @@ -6877,12 +6915,13 @@ pub const FuncGen = struct { } fn airSlice(self: *FuncGen, inst: Air.Inst.Index) !?*llvm.Value { + const o = self.dg.object; const ty_pl = self.air.instructions.items(.data)[inst].ty_pl; const bin_op = self.air.extraData(Air.Bin, ty_pl.payload).data; const ptr = try self.resolveInst(bin_op.lhs); const len = try self.resolveInst(bin_op.rhs); const inst_ty = self.typeOfIndex(inst); - const llvm_slice_ty = try self.dg.lowerType(inst_ty); + const llvm_slice_ty = try o.lowerType(inst_ty); // In case of slicing a global, the result type looks something like `{ i8*, i64 }` // but `ptr` is pointing to the global directly. @@ -6893,7 +6932,8 @@ pub const FuncGen = struct { fn airAdd(self: *FuncGen, inst: Air.Inst.Index, want_fast_math: bool) !?*llvm.Value { self.builder.setFastMath(want_fast_math); - const mod = self.dg.module; + const o = self.dg.object; + const mod = o.module; const bin_op = self.air.instructions.items(.data)[inst].bin_op; const lhs = try self.resolveInst(bin_op.lhs); const rhs = try self.resolveInst(bin_op.rhs); @@ -6916,7 +6956,8 @@ pub const FuncGen = struct { } fn airAddSat(self: *FuncGen, inst: Air.Inst.Index) !?*llvm.Value { - const mod = self.dg.module; + const o = self.dg.object; + const mod = o.module; const bin_op = self.air.instructions.items(.data)[inst].bin_op; const lhs = try self.resolveInst(bin_op.lhs); const rhs = try self.resolveInst(bin_op.rhs); @@ -6932,7 +6973,8 @@ pub const FuncGen = struct { fn airSub(self: *FuncGen, inst: Air.Inst.Index, want_fast_math: bool) !?*llvm.Value { self.builder.setFastMath(want_fast_math); - const mod = self.dg.module; + const o = self.dg.object; + const mod = o.module; const bin_op = self.air.instructions.items(.data)[inst].bin_op; const lhs = try self.resolveInst(bin_op.lhs); const rhs = try self.resolveInst(bin_op.rhs); @@ -6955,7 +6997,8 @@ pub const FuncGen = struct { } fn airSubSat(self: *FuncGen, inst: Air.Inst.Index) !?*llvm.Value { - const mod = self.dg.module; + const o = self.dg.object; + const mod = o.module; const bin_op = self.air.instructions.items(.data)[inst].bin_op; const lhs = try self.resolveInst(bin_op.lhs); const rhs = try self.resolveInst(bin_op.rhs); @@ -6970,7 +7013,8 @@ pub const FuncGen = struct { fn airMul(self: *FuncGen, inst: Air.Inst.Index, want_fast_math: bool) !?*llvm.Value { self.builder.setFastMath(want_fast_math); - const mod = self.dg.module; + const o = self.dg.object; + const mod = o.module; const bin_op = self.air.instructions.items(.data)[inst].bin_op; const lhs = try self.resolveInst(bin_op.lhs); const rhs = try self.resolveInst(bin_op.rhs); @@ -6993,7 +7037,8 @@ pub const FuncGen = struct { } fn airMulSat(self: *FuncGen, inst: Air.Inst.Index) !?*llvm.Value { - const mod = self.dg.module; + const o = self.dg.object; + const mod = o.module; const bin_op = self.air.instructions.items(.data)[inst].bin_op; const lhs = try self.resolveInst(bin_op.lhs); const rhs = try self.resolveInst(bin_op.rhs); @@ -7019,7 +7064,8 @@ pub const FuncGen = struct { fn airDivTrunc(self: *FuncGen, inst: Air.Inst.Index, want_fast_math: bool) !?*llvm.Value { self.builder.setFastMath(want_fast_math); - const mod = self.dg.module; + const o = self.dg.object; + const mod = o.module; const bin_op = self.air.instructions.items(.data)[inst].bin_op; const lhs = try self.resolveInst(bin_op.lhs); const rhs = try self.resolveInst(bin_op.rhs); @@ -7037,7 +7083,8 @@ pub const FuncGen = struct { fn airDivFloor(self: *FuncGen, inst: Air.Inst.Index, want_fast_math: bool) !?*llvm.Value { self.builder.setFastMath(want_fast_math); - const mod = self.dg.module; + const o = self.dg.object; + const mod = o.module; const bin_op = self.air.instructions.items(.data)[inst].bin_op; const lhs = try self.resolveInst(bin_op.lhs); const rhs = try self.resolveInst(bin_op.rhs); @@ -7049,11 +7096,11 @@ pub const FuncGen = struct { return self.buildFloatOp(.floor, inst_ty, 1, .{result}); } if (scalar_ty.isSignedInt(mod)) { - const inst_llvm_ty = try self.dg.lowerType(inst_ty); + const inst_llvm_ty = try o.lowerType(inst_ty); const scalar_bit_size_minus_one = scalar_ty.bitSize(mod) - 1; const bit_size_minus_one = if (inst_ty.zigTypeTag(mod) == .Vector) const_vector: { const vec_len = inst_ty.vectorLen(mod); - const scalar_llvm_ty = try self.dg.lowerType(scalar_ty); + const scalar_llvm_ty = try o.lowerType(scalar_ty); const shifts = try self.gpa.alloc(*llvm.Value, vec_len); defer self.gpa.free(shifts); @@ -7077,7 +7124,8 @@ pub const FuncGen = struct { fn airDivExact(self: *FuncGen, inst: Air.Inst.Index, want_fast_math: bool) !?*llvm.Value { self.builder.setFastMath(want_fast_math); - const mod = self.dg.module; + const o = self.dg.object; + const mod = o.module; const bin_op = self.air.instructions.items(.data)[inst].bin_op; const lhs = try self.resolveInst(bin_op.lhs); const rhs = try self.resolveInst(bin_op.rhs); @@ -7092,7 +7140,8 @@ pub const FuncGen = struct { fn airRem(self: *FuncGen, inst: Air.Inst.Index, want_fast_math: bool) !?*llvm.Value { self.builder.setFastMath(want_fast_math); - const mod = self.dg.module; + const o = self.dg.object; + const mod = o.module; const bin_op = self.air.instructions.items(.data)[inst].bin_op; const lhs = try self.resolveInst(bin_op.lhs); const rhs = try self.resolveInst(bin_op.rhs); @@ -7107,12 +7156,13 @@ pub const FuncGen = struct { fn airMod(self: *FuncGen, inst: Air.Inst.Index, want_fast_math: bool) !?*llvm.Value { self.builder.setFastMath(want_fast_math); - const mod = self.dg.module; + const o = self.dg.object; + const mod = o.module; const bin_op = self.air.instructions.items(.data)[inst].bin_op; 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.dg.lowerType(inst_ty); + const inst_llvm_ty = try o.lowerType(inst_ty); const scalar_ty = inst_ty.scalarType(mod); if (scalar_ty.isRuntimeFloat()) { @@ -7127,7 +7177,7 @@ pub const FuncGen = struct { const scalar_bit_size_minus_one = scalar_ty.bitSize(mod) - 1; const bit_size_minus_one = if (inst_ty.zigTypeTag(mod) == .Vector) const_vector: { const vec_len = inst_ty.vectorLen(mod); - const scalar_llvm_ty = try self.dg.lowerType(scalar_ty); + const scalar_llvm_ty = try o.lowerType(scalar_ty); const shifts = try self.gpa.alloc(*llvm.Value, vec_len); defer self.gpa.free(shifts); @@ -7149,13 +7199,14 @@ pub const FuncGen = struct { } fn airPtrAdd(self: *FuncGen, inst: Air.Inst.Index) !?*llvm.Value { - const mod = self.dg.module; + const o = self.dg.object; + const mod = o.module; const ty_pl = self.air.instructions.items(.data)[inst].ty_pl; const bin_op = self.air.extraData(Air.Bin, ty_pl.payload).data; const ptr = try self.resolveInst(bin_op.lhs); const offset = try self.resolveInst(bin_op.rhs); const ptr_ty = self.typeOf(bin_op.lhs); - const llvm_elem_ty = try self.dg.lowerPtrElemTy(ptr_ty.childType(mod)); + const llvm_elem_ty = try o.lowerPtrElemTy(ptr_ty.childType(mod)); switch (ptr_ty.ptrSize(mod)) { .One => { // It's a pointer to an array, so according to LLVM we need an extra GEP index. @@ -7175,14 +7226,15 @@ pub const FuncGen = struct { } fn airPtrSub(self: *FuncGen, inst: Air.Inst.Index) !?*llvm.Value { - const mod = self.dg.module; + const o = self.dg.object; + const mod = o.module; const ty_pl = self.air.instructions.items(.data)[inst].ty_pl; const bin_op = self.air.extraData(Air.Bin, ty_pl.payload).data; const ptr = try self.resolveInst(bin_op.lhs); const offset = try self.resolveInst(bin_op.rhs); const negative_offset = self.builder.buildNeg(offset, ""); const ptr_ty = self.typeOf(bin_op.lhs); - const llvm_elem_ty = try self.dg.lowerPtrElemTy(ptr_ty.childType(mod)); + const llvm_elem_ty = try o.lowerPtrElemTy(ptr_ty.childType(mod)); switch (ptr_ty.ptrSize(mod)) { .One => { // It's a pointer to an array, so according to LLVM we need an extra GEP index. @@ -7209,7 +7261,8 @@ pub const FuncGen = struct { signed_intrinsic: []const u8, unsigned_intrinsic: []const u8, ) !?*llvm.Value { - const mod = self.dg.module; + const o = self.dg.object; + const mod = o.module; const ty_pl = self.air.instructions.items(.data)[inst].ty_pl; const extra = self.air.extraData(Air.Bin, ty_pl.payload).data; @@ -7222,8 +7275,8 @@ pub const FuncGen = struct { const intrinsic_name = if (scalar_ty.isSignedInt(mod)) signed_intrinsic else unsigned_intrinsic; - const llvm_lhs_ty = try self.dg.lowerType(lhs_ty); - const llvm_dest_ty = try self.dg.lowerType(dest_ty); + const llvm_lhs_ty = try o.lowerType(lhs_ty); + const llvm_dest_ty = try o.lowerType(dest_ty); const llvm_fn = self.getIntrinsic(intrinsic_name, &.{llvm_lhs_ty}); const result_struct = self.builder.buildCall(llvm_fn.globalGetValueType(), llvm_fn, &[_]*llvm.Value{ lhs, rhs }, 2, .Fast, .Auto, ""); @@ -7287,13 +7340,14 @@ pub const FuncGen = struct { param_types: []const *llvm.Type, return_type: *llvm.Type, ) *llvm.Value { - return self.dg.object.llvm_module.getNamedFunction(fn_name.ptr) orelse b: { - const alias = self.dg.object.llvm_module.getNamedGlobalAlias(fn_name.ptr, fn_name.len); + const o = self.dg.object; + return o.llvm_module.getNamedFunction(fn_name.ptr) orelse b: { + const alias = o.llvm_module.getNamedGlobalAlias(fn_name.ptr, fn_name.len); break :b if (alias) |a| a.getAliasee() else null; } orelse b: { const params_len = @intCast(c_uint, param_types.len); const fn_type = llvm.functionType(return_type, param_types.ptr, params_len, .False); - const f = self.dg.object.llvm_module.addFunction(fn_name, fn_type); + const f = o.llvm_module.addFunction(fn_name, fn_type); break :b f; }; } @@ -7306,10 +7360,11 @@ pub const FuncGen = struct { ty: Type, params: [2]*llvm.Value, ) !*llvm.Value { - const mod = self.dg.module; - const target = self.dg.module.getTarget(); + const o = self.dg.object; + const mod = o.module; + const target = o.module.getTarget(); const scalar_ty = ty.scalarType(mod); - const scalar_llvm_ty = try self.dg.lowerType(scalar_ty); + const scalar_llvm_ty = try o.lowerType(scalar_ty); if (intrinsicsAllowed(scalar_ty, target)) { const llvm_predicate: llvm.RealPredicate = switch (pred) { @@ -7408,11 +7463,12 @@ pub const FuncGen = struct { comptime params_len: usize, params: [params_len]*llvm.Value, ) !*llvm.Value { - const mod = self.dg.module; + const o = self.dg.object; + const mod = o.module; const target = mod.getTarget(); const scalar_ty = ty.scalarType(mod); - const llvm_ty = try self.dg.lowerType(ty); - const scalar_llvm_ty = try self.dg.lowerType(scalar_ty); + const llvm_ty = try o.lowerType(ty); + const scalar_llvm_ty = try o.lowerType(scalar_ty); const intrinsics_allowed = op != .tan and intrinsicsAllowed(scalar_ty, target); var fn_name_buf: [64]u8 = undefined; @@ -7508,7 +7564,8 @@ pub const FuncGen = struct { } fn airShlWithOverflow(self: *FuncGen, inst: Air.Inst.Index) !?*llvm.Value { - const mod = self.dg.module; + const o = self.dg.object; + const mod = o.module; const ty_pl = self.air.instructions.items(.data)[inst].ty_pl; const extra = self.air.extraData(Air.Bin, ty_pl.payload).data; @@ -7521,10 +7578,10 @@ pub const FuncGen = struct { const rhs_scalar_ty = rhs_ty.scalarType(mod); const dest_ty = self.typeOfIndex(inst); - const llvm_dest_ty = try self.dg.lowerType(dest_ty); + const llvm_dest_ty = try o.lowerType(dest_ty); const casted_rhs = if (rhs_scalar_ty.bitSize(mod) < lhs_scalar_ty.bitSize(mod)) - self.builder.buildZExt(rhs, try self.dg.lowerType(lhs_ty), "") + self.builder.buildZExt(rhs, try o.lowerType(lhs_ty), "") else rhs; @@ -7582,7 +7639,8 @@ pub const FuncGen = struct { } fn airShlExact(self: *FuncGen, inst: Air.Inst.Index) !?*llvm.Value { - const mod = self.dg.module; + const o = self.dg.object; + const mod = o.module; const bin_op = self.air.instructions.items(.data)[inst].bin_op; const lhs = try self.resolveInst(bin_op.lhs); @@ -7594,7 +7652,7 @@ pub const FuncGen = struct { const rhs_scalar_ty = rhs_ty.scalarType(mod); const casted_rhs = if (rhs_scalar_ty.bitSize(mod) < lhs_scalar_ty.bitSize(mod)) - self.builder.buildZExt(rhs, try self.dg.lowerType(lhs_ty), "") + self.builder.buildZExt(rhs, try o.lowerType(lhs_ty), "") else rhs; if (lhs_scalar_ty.isSignedInt(mod)) return self.builder.buildNSWShl(lhs, casted_rhs, ""); @@ -7602,7 +7660,8 @@ pub const FuncGen = struct { } fn airShl(self: *FuncGen, inst: Air.Inst.Index) !?*llvm.Value { - const mod = self.dg.module; + const o = self.dg.object; + const mod = o.module; const bin_op = self.air.instructions.items(.data)[inst].bin_op; const lhs = try self.resolveInst(bin_op.lhs); @@ -7614,14 +7673,15 @@ pub const FuncGen = struct { const rhs_scalar_ty = rhs_type.scalarType(mod); const casted_rhs = if (rhs_scalar_ty.bitSize(mod) < lhs_scalar_ty.bitSize(mod)) - self.builder.buildZExt(rhs, try self.dg.lowerType(lhs_type), "") + self.builder.buildZExt(rhs, try o.lowerType(lhs_type), "") else rhs; return self.builder.buildShl(lhs, casted_rhs, ""); } fn airShlSat(self: *FuncGen, inst: Air.Inst.Index) !?*llvm.Value { - const mod = self.dg.module; + const o = self.dg.object; + const mod = o.module; const bin_op = self.air.instructions.items(.data)[inst].bin_op; const lhs = try self.resolveInst(bin_op.lhs); @@ -7648,7 +7708,7 @@ pub const FuncGen = struct { // poison value." // However Zig semantics says that saturating shift left can never produce // undefined; instead it saturates. - const lhs_scalar_llvm_ty = try self.dg.lowerType(lhs_scalar_ty); + const lhs_scalar_llvm_ty = try o.lowerType(lhs_scalar_ty); const bits = lhs_scalar_llvm_ty.constInt(lhs_bits, .False); const lhs_max = lhs_scalar_llvm_ty.constAllOnes(); if (rhs_ty.zigTypeTag(mod) == .Vector) { @@ -7664,7 +7724,8 @@ pub const FuncGen = struct { } fn airShr(self: *FuncGen, inst: Air.Inst.Index, is_exact: bool) !?*llvm.Value { - const mod = self.dg.module; + const o = self.dg.object; + const mod = o.module; const bin_op = self.air.instructions.items(.data)[inst].bin_op; const lhs = try self.resolveInst(bin_op.lhs); @@ -7676,7 +7737,7 @@ pub const FuncGen = struct { const rhs_scalar_ty = rhs_ty.scalarType(mod); const casted_rhs = if (rhs_scalar_ty.bitSize(mod) < lhs_scalar_ty.bitSize(mod)) - self.builder.buildZExt(rhs, try self.dg.lowerType(lhs_ty), "") + self.builder.buildZExt(rhs, try o.lowerType(lhs_ty), "") else rhs; const is_signed_int = lhs_scalar_ty.isSignedInt(mod); @@ -7697,11 +7758,12 @@ pub const FuncGen = struct { } fn airIntCast(self: *FuncGen, inst: Air.Inst.Index) !?*llvm.Value { - const mod = self.dg.module; + const o = self.dg.object; + const mod = o.module; const ty_op = self.air.instructions.items(.data)[inst].ty_op; const dest_ty = self.typeOfIndex(inst); const dest_info = dest_ty.intInfo(mod); - const dest_llvm_ty = try self.dg.lowerType(dest_ty); + const dest_llvm_ty = try o.lowerType(dest_ty); const operand = try self.resolveInst(ty_op.operand); const operand_ty = self.typeOf(ty_op.operand); const operand_info = operand_ty.intInfo(mod); @@ -7719,14 +7781,16 @@ pub const FuncGen = struct { } fn airTrunc(self: *FuncGen, inst: Air.Inst.Index) !?*llvm.Value { + const o = self.dg.object; const ty_op = self.air.instructions.items(.data)[inst].ty_op; const operand = try self.resolveInst(ty_op.operand); - const dest_llvm_ty = try self.dg.lowerType(self.typeOfIndex(inst)); + const dest_llvm_ty = try o.lowerType(self.typeOfIndex(inst)); return self.builder.buildTrunc(operand, dest_llvm_ty, ""); } fn airFptrunc(self: *FuncGen, inst: Air.Inst.Index) !?*llvm.Value { - const mod = self.dg.module; + const o = self.dg.object; + const mod = o.module; const ty_op = self.air.instructions.items(.data)[inst].ty_op; const operand = try self.resolveInst(ty_op.operand); const operand_ty = self.typeOf(ty_op.operand); @@ -7736,11 +7800,11 @@ pub const FuncGen = struct { const src_bits = operand_ty.floatBits(target); if (intrinsicsAllowed(dest_ty, target) and intrinsicsAllowed(operand_ty, target)) { - const dest_llvm_ty = try self.dg.lowerType(dest_ty); + const dest_llvm_ty = try o.lowerType(dest_ty); return self.builder.buildFPTrunc(operand, dest_llvm_ty, ""); } else { - const operand_llvm_ty = try self.dg.lowerType(operand_ty); - const dest_llvm_ty = try self.dg.lowerType(dest_ty); + const operand_llvm_ty = try o.lowerType(operand_ty); + const dest_llvm_ty = try o.lowerType(dest_ty); var fn_name_buf: [64]u8 = undefined; const fn_name = std.fmt.bufPrintZ(&fn_name_buf, "__trunc{s}f{s}f2", .{ @@ -7756,7 +7820,8 @@ pub const FuncGen = struct { } fn airFpext(self: *FuncGen, inst: Air.Inst.Index) !?*llvm.Value { - const mod = self.dg.module; + const o = self.dg.object; + const mod = o.module; const ty_op = self.air.instructions.items(.data)[inst].ty_op; const operand = try self.resolveInst(ty_op.operand); const operand_ty = self.typeOf(ty_op.operand); @@ -7766,11 +7831,11 @@ pub const FuncGen = struct { const src_bits = operand_ty.floatBits(target); if (intrinsicsAllowed(dest_ty, target) and intrinsicsAllowed(operand_ty, target)) { - const dest_llvm_ty = try self.dg.lowerType(dest_ty); + const dest_llvm_ty = try o.lowerType(dest_ty); return self.builder.buildFPExt(operand, dest_llvm_ty, ""); } else { - const operand_llvm_ty = try self.dg.lowerType(operand_ty); - const dest_llvm_ty = try self.dg.lowerType(dest_ty); + const operand_llvm_ty = try o.lowerType(operand_ty); + const dest_llvm_ty = try o.lowerType(dest_ty); var fn_name_buf: [64]u8 = undefined; const fn_name = std.fmt.bufPrintZ(&fn_name_buf, "__extend{s}f{s}f2", .{ @@ -7786,11 +7851,12 @@ pub const FuncGen = struct { } fn airIntFromPtr(self: *FuncGen, inst: Air.Inst.Index) !?*llvm.Value { + const o = self.dg.object; const un_op = self.air.instructions.items(.data)[inst].un_op; const operand = try self.resolveInst(un_op); const ptr_ty = self.typeOf(un_op); const operand_ptr = self.sliceOrArrayPtr(operand, ptr_ty); - const dest_llvm_ty = try self.dg.lowerType(self.typeOfIndex(inst)); + const dest_llvm_ty = try o.lowerType(self.typeOfIndex(inst)); return self.builder.buildPtrToInt(operand_ptr, dest_llvm_ty, ""); } @@ -7803,10 +7869,11 @@ pub const FuncGen = struct { } fn bitCast(self: *FuncGen, operand: *llvm.Value, operand_ty: Type, inst_ty: Type) !*llvm.Value { - const mod = self.dg.module; + const o = self.dg.object; + const mod = o.module; const operand_is_ref = isByRef(operand_ty, mod); const result_is_ref = isByRef(inst_ty, mod); - const llvm_dest_ty = try self.dg.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 :) @@ -7836,7 +7903,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 llvm_usize = try self.dg.lowerType(Type.usize); + const llvm_usize = try o.lowerType(Type.usize); const llvm_u32 = self.context.intType(32); const zero = llvm_usize.constNull(); const vector_len = operand_ty.arrayLen(mod); @@ -7853,7 +7920,7 @@ pub const FuncGen = struct { return array_ptr; } else if (operand_ty.zigTypeTag(mod) == .Array and inst_ty.zigTypeTag(mod) == .Vector) { const elem_ty = operand_ty.childType(mod); - const llvm_vector_ty = try self.dg.lowerType(inst_ty); + const llvm_vector_ty = try o.lowerType(inst_ty); if (!operand_is_ref) { return self.dg.todo("implement bitcast non-ref array to vector", .{}); } @@ -7868,9 +7935,9 @@ 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 array_llvm_ty = try o.lowerType(operand_ty); + const elem_llvm_ty = try o.lowerType(elem_ty); + const llvm_usize = try o.lowerType(Type.usize); const llvm_u32 = self.context.intType(32); const zero = llvm_usize.constNull(); const vector_len = operand_ty.arrayLen(mod); @@ -7926,13 +7993,14 @@ pub const FuncGen = struct { } fn airArg(self: *FuncGen, inst: Air.Inst.Index) !?*llvm.Value { - const mod = self.dg.module; + const o = self.dg.object; + const mod = o.module; const arg_val = self.args[self.arg_index]; self.arg_index += 1; const inst_ty = self.typeOfIndex(inst); - if (self.dg.object.di_builder) |dib| { - if (needDbgVarWorkaround(self.dg)) { + if (o.di_builder) |dib| { + if (needDbgVarWorkaround(o)) { return arg_val; } @@ -7945,7 +8013,7 @@ pub const FuncGen = struct { func.getParamName(mod, src_index).ptr, // TODO test 0 bit args self.di_file.?, lbrace_line, - try self.dg.object.lowerDebugType(inst_ty, .full), + try o.lowerDebugType(inst_ty, .full), true, // always preserve 0, // flags self.arg_index, // includes +1 because 0 is return type @@ -7955,7 +8023,7 @@ pub const FuncGen = struct { const insert_block = self.builder.getInsertBlock(); if (isByRef(inst_ty, mod)) { _ = dib.insertDeclareAtEnd(arg_val, di_local_var, debug_loc, insert_block); - } else if (self.dg.module.comp.bin_file.options.optimize_mode == .Debug) { + } else if (o.module.comp.bin_file.options.optimize_mode == .Debug) { const alignment = inst_ty.abiAlignment(mod); const alloca = self.buildAlloca(arg_val.typeOf(), alignment); const store_inst = self.builder.buildStore(arg_val, alloca); @@ -7970,34 +8038,41 @@ pub const FuncGen = struct { } fn airAlloc(self: *FuncGen, inst: Air.Inst.Index) !?*llvm.Value { - const mod = self.dg.module; + const o = self.dg.object; + const mod = o.module; const ptr_ty = self.typeOfIndex(inst); const pointee_type = ptr_ty.childType(mod); - if (!pointee_type.isFnOrHasRuntimeBitsIgnoreComptime(mod)) return self.dg.lowerPtrToVoid(ptr_ty); + if (!pointee_type.isFnOrHasRuntimeBitsIgnoreComptime(mod)) + return o.lowerPtrToVoid(ptr_ty); - const pointee_llvm_ty = try self.dg.lowerType(pointee_type); + const pointee_llvm_ty = try o.lowerType(pointee_type); const alignment = ptr_ty.ptrAlignment(mod); return self.buildAlloca(pointee_llvm_ty, alignment); } fn airRetPtr(self: *FuncGen, inst: Air.Inst.Index) !?*llvm.Value { - const mod = self.dg.module; + const o = self.dg.object; + const mod = o.module; const ptr_ty = self.typeOfIndex(inst); const ret_ty = ptr_ty.childType(mod); - if (!ret_ty.isFnOrHasRuntimeBitsIgnoreComptime(mod)) return self.dg.lowerPtrToVoid(ptr_ty); + if (!ret_ty.isFnOrHasRuntimeBitsIgnoreComptime(mod)) return o.lowerPtrToVoid(ptr_ty); if (self.ret_ptr) |ret_ptr| return ret_ptr; - const ret_llvm_ty = try self.dg.lowerType(ret_ty); + const ret_llvm_ty = try o.lowerType(ret_ty); return self.buildAlloca(ret_llvm_ty, ptr_ty.ptrAlignment(mod)); } /// Use this instead of builder.buildAlloca, because this function makes sure to /// put the alloca instruction at the top of the function! fn buildAlloca(self: *FuncGen, llvm_ty: *llvm.Type, alignment: ?c_uint) *llvm.Value { - return buildAllocaInner(self.context, self.builder, self.llvm_func, self.di_scope != null, llvm_ty, alignment, self.dg.module.getTarget()); + const o = self.dg.object; + const mod = o.module; + const target = mod.getTarget(); + return buildAllocaInner(self.context, self.builder, self.llvm_func, self.di_scope != null, llvm_ty, alignment, target); } fn airStore(self: *FuncGen, inst: Air.Inst.Index, safety: bool) !?*llvm.Value { - const mod = self.dg.module; + const o = self.dg.object; + const mod = o.module; const bin_op = self.air.instructions.items(.data)[inst].bin_op; const dest_ptr = try self.resolveInst(bin_op.lhs); const ptr_ty = self.typeOf(bin_op.lhs); @@ -8014,7 +8089,7 @@ pub const FuncGen = struct { else u8_llvm_ty.getUndef(); const operand_size = operand_ty.abiSize(mod); - const usize_llvm_ty = try self.dg.lowerType(Type.usize); + const usize_llvm_ty = try o.lowerType(Type.usize); const len = usize_llvm_ty.constInt(operand_size, .False); const dest_ptr_align = ptr_ty.ptrAlignment(mod); _ = self.builder.buildMemSet(dest_ptr, fill_byte, len, dest_ptr_align, ptr_ty.isVolatilePtr(mod)); @@ -8036,7 +8111,8 @@ pub const FuncGen = struct { /// /// The first instruction of `body_tail` is the one whose copy we want to elide. fn canElideLoad(fg: *FuncGen, body_tail: []const Air.Inst.Index) bool { - const mod = fg.dg.module; + const o = fg.dg.object; + const mod = o.module; const ip = &mod.intern_pool; for (body_tail[1..]) |body_inst| { switch (fg.liveness.categorizeOperand(fg.air, body_inst, body_tail[0], ip)) { @@ -8051,7 +8127,8 @@ pub const FuncGen = struct { } fn airLoad(fg: *FuncGen, body_tail: []const Air.Inst.Index) !?*llvm.Value { - const mod = fg.dg.module; + const o = fg.dg.object; + const mod = o.module; const inst = body_tail[0]; const ty_op = fg.air.instructions.items(.data)[inst].ty_op; const ptr_ty = fg.typeOf(ty_op.operand); @@ -8083,8 +8160,9 @@ pub const FuncGen = struct { fn airRetAddr(self: *FuncGen, inst: Air.Inst.Index) !?*llvm.Value { _ = inst; - const mod = self.dg.module; - const llvm_usize = try self.dg.lowerType(Type.usize); + const o = self.dg.object; + const mod = o.module; + const llvm_usize = try o.lowerType(Type.usize); const target = mod.getTarget(); if (!target_util.supportsReturnAddress(target)) { // https://github.com/ziglang/zig/issues/11946 @@ -8100,18 +8178,19 @@ pub const FuncGen = struct { fn airFrameAddress(self: *FuncGen, inst: Air.Inst.Index) !?*llvm.Value { _ = inst; + const o = self.dg.object; const llvm_i32 = self.context.intType(32); const llvm_fn_name = "llvm.frameaddress.p0"; - const llvm_fn = self.dg.object.llvm_module.getNamedFunction(llvm_fn_name) orelse blk: { + const llvm_fn = o.llvm_module.getNamedFunction(llvm_fn_name) orelse blk: { const llvm_p0i8 = self.context.pointerType(0); const param_types = [_]*llvm.Type{llvm_i32}; const fn_type = llvm.functionType(llvm_p0i8, ¶m_types, param_types.len, .False); - break :blk self.dg.object.llvm_module.addFunction(llvm_fn_name, fn_type); + break :blk o.llvm_module.addFunction(llvm_fn_name, fn_type); }; const params = [_]*llvm.Value{llvm_i32.constNull()}; 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); + const llvm_usize = try o.lowerType(Type.usize); return self.builder.buildPtrToInt(ptr_val, llvm_usize, ""); } @@ -8124,14 +8203,15 @@ pub const FuncGen = struct { } fn airCmpxchg(self: *FuncGen, inst: Air.Inst.Index, is_weak: bool) !?*llvm.Value { - const mod = self.dg.module; + const o = self.dg.object; + const mod = o.module; const ty_pl = self.air.instructions.items(.data)[inst].ty_pl; const extra = self.air.extraData(Air.Cmpxchg, ty_pl.payload).data; const ptr = try self.resolveInst(extra.ptr); var expected_value = try self.resolveInst(extra.expected_value); var new_value = try self.resolveInst(extra.new_value); const operand_ty = self.typeOf(extra.ptr).childType(mod); - const opt_abi_ty = self.dg.getAtomicAbiType(operand_ty, false); + const opt_abi_ty = o.getAtomicAbiType(operand_ty, false); if (opt_abi_ty) |abi_ty| { // operand needs widening and truncating if (operand_ty.isSignedInt(mod)) { @@ -8156,7 +8236,7 @@ pub const FuncGen = struct { var payload = self.builder.buildExtractValue(result, 0, ""); if (opt_abi_ty != null) { - payload = self.builder.buildTrunc(payload, try self.dg.lowerType(operand_ty), ""); + payload = self.builder.buildTrunc(payload, try o.lowerType(operand_ty), ""); } const success_bit = self.builder.buildExtractValue(result, 1, ""); @@ -8171,7 +8251,8 @@ pub const FuncGen = struct { } fn airAtomicRmw(self: *FuncGen, inst: Air.Inst.Index) !?*llvm.Value { - const mod = self.dg.module; + const o = self.dg.object; + const mod = o.module; const pl_op = self.air.instructions.items(.data)[inst].pl_op; const extra = self.air.extraData(Air.AtomicRmw, pl_op.payload).data; const ptr = try self.resolveInst(pl_op.operand); @@ -8183,7 +8264,7 @@ pub const FuncGen = struct { const op = toLlvmAtomicRmwBinOp(extra.op(), is_signed_int, is_float); const ordering = toLlvmAtomicOrdering(extra.ordering()); const single_threaded = llvm.Bool.fromBool(self.single_threaded); - const opt_abi_ty = self.dg.getAtomicAbiType(operand_ty, op == .Xchg); + const opt_abi_ty = o.getAtomicAbiType(operand_ty, op == .Xchg); if (opt_abi_ty) |abi_ty| { // operand needs widening and truncating or bitcasting. const casted_operand = if (is_float) @@ -8200,7 +8281,7 @@ pub const FuncGen = struct { ordering, single_threaded, ); - const operand_llvm_ty = try self.dg.lowerType(operand_ty); + const operand_llvm_ty = try o.lowerType(operand_ty); if (is_float) { return self.builder.buildBitCast(uncasted_result, operand_llvm_ty, ""); } else { @@ -8213,7 +8294,7 @@ pub const FuncGen = struct { } // It's a pointer but we need to treat it as an int. - const usize_llvm_ty = try self.dg.lowerType(Type.usize); + const usize_llvm_ty = try o.lowerType(Type.usize); const casted_operand = self.builder.buildPtrToInt(operand, usize_llvm_ty, ""); const uncasted_result = self.builder.buildAtomicRmw( op, @@ -8222,12 +8303,13 @@ pub const FuncGen = struct { ordering, single_threaded, ); - const operand_llvm_ty = try self.dg.lowerType(operand_ty); + const operand_llvm_ty = try o.lowerType(operand_ty); return self.builder.buildIntToPtr(uncasted_result, operand_llvm_ty, ""); } fn airAtomicLoad(self: *FuncGen, inst: Air.Inst.Index) !?*llvm.Value { - const mod = self.dg.module; + const o = self.dg.object; + const mod = o.module; const atomic_load = self.air.instructions.items(.data)[inst].atomic_load; const ptr = try self.resolveInst(atomic_load.ptr); const ptr_ty = self.typeOf(atomic_load.ptr); @@ -8236,11 +8318,11 @@ pub const FuncGen = struct { if (!elem_ty.hasRuntimeBitsIgnoreComptime(mod)) return null; const ordering = toLlvmAtomicOrdering(atomic_load.order); - const opt_abi_llvm_ty = self.dg.getAtomicAbiType(elem_ty, false); + const opt_abi_llvm_ty = o.getAtomicAbiType(elem_ty, false); const ptr_alignment = @intCast(u32, ptr_info.flags.alignment.toByteUnitsOptional() orelse ptr_info.child.toType().abiAlignment(mod)); const ptr_volatile = llvm.Bool.fromBool(ptr_info.flags.is_volatile); - const elem_llvm_ty = try self.dg.lowerType(elem_ty); + const elem_llvm_ty = try o.lowerType(elem_ty); if (opt_abi_llvm_ty) |abi_llvm_ty| { // operand needs widening and truncating @@ -8262,14 +8344,15 @@ pub const FuncGen = struct { inst: Air.Inst.Index, ordering: llvm.AtomicOrdering, ) !?*llvm.Value { - const mod = self.dg.module; + const o = self.dg.object; + const mod = o.module; const bin_op = self.air.instructions.items(.data)[inst].bin_op; const ptr_ty = self.typeOf(bin_op.lhs); const operand_ty = ptr_ty.childType(mod); if (!operand_ty.isFnOrHasRuntimeBitsIgnoreComptime(mod)) return null; const ptr = try self.resolveInst(bin_op.lhs); var element = try self.resolveInst(bin_op.rhs); - const opt_abi_ty = self.dg.getAtomicAbiType(operand_ty, false); + const opt_abi_ty = o.getAtomicAbiType(operand_ty, false); if (opt_abi_ty) |abi_ty| { // operand needs widening @@ -8284,7 +8367,8 @@ pub const FuncGen = struct { } fn airMemset(self: *FuncGen, inst: Air.Inst.Index, safety: bool) !?*llvm.Value { - const mod = self.dg.module; + const o = self.dg.object; + const mod = o.module; const bin_op = self.air.instructions.items(.data)[inst].bin_op; const dest_slice = try self.resolveInst(bin_op.lhs); const ptr_ty = self.typeOf(bin_op.lhs); @@ -8366,7 +8450,7 @@ pub const FuncGen = struct { .One => llvm_usize_ty.constInt(ptr_ty.childType(mod).arrayLen(mod), .False), .Many, .C => unreachable, }; - const elem_llvm_ty = try self.dg.lowerType(elem_ty); + const elem_llvm_ty = try o.lowerType(elem_ty); const len_gep = [_]*llvm.Value{len}; const end_ptr = self.builder.buildInBoundsGEP(elem_llvm_ty, dest_ptr, &len_gep, len_gep.len, ""); _ = self.builder.buildBr(loop_block); @@ -8407,6 +8491,8 @@ pub const FuncGen = struct { } fn airMemcpy(self: *FuncGen, inst: Air.Inst.Index) !?*llvm.Value { + const o = self.dg.object; + const mod = o.module; const bin_op = self.air.instructions.items(.data)[inst].bin_op; const dest_slice = try self.resolveInst(bin_op.lhs); const dest_ptr_ty = self.typeOf(bin_op.lhs); @@ -8415,7 +8501,6 @@ pub const FuncGen = struct { const src_ptr = self.sliceOrArrayPtr(src_slice, src_ptr_ty); const len = self.sliceOrArrayLenInBytes(dest_slice, dest_ptr_ty); const dest_ptr = self.sliceOrArrayPtr(dest_slice, dest_ptr_ty); - const mod = self.dg.module; const is_volatile = src_ptr_ty.isVolatilePtr(mod) or dest_ptr_ty.isVolatilePtr(mod); _ = self.builder.buildMemCpy( dest_ptr, @@ -8429,7 +8514,8 @@ pub const FuncGen = struct { } fn airSetUnionTag(self: *FuncGen, inst: Air.Inst.Index) !?*llvm.Value { - const mod = self.dg.module; + const o = self.dg.object; + const mod = o.module; const bin_op = self.air.instructions.items(.data)[inst].bin_op; const un_ty = self.typeOf(bin_op.lhs).childType(mod); const layout = un_ty.unionGetLayout(mod); @@ -8441,7 +8527,7 @@ pub const FuncGen = struct { _ = self.builder.buildStore(new_tag, union_ptr); return null; } - const un_llvm_ty = try self.dg.lowerType(un_ty); + const un_llvm_ty = try o.lowerType(un_ty); const tag_index = @intFromBool(layout.tag_align < layout.payload_align); const tag_field_ptr = self.builder.buildStructGEP(un_llvm_ty, union_ptr, tag_index, ""); // TODO alignment on this store @@ -8450,14 +8536,15 @@ pub const FuncGen = struct { } fn airGetUnionTag(self: *FuncGen, inst: Air.Inst.Index) !?*llvm.Value { - const mod = self.dg.module; + const o = self.dg.object; + const mod = o.module; const ty_op = self.air.instructions.items(.data)[inst].ty_op; const un_ty = self.typeOf(ty_op.operand); const layout = un_ty.unionGetLayout(mod); if (layout.tag_size == 0) return null; const union_handle = try self.resolveInst(ty_op.operand); if (isByRef(un_ty, mod)) { - const llvm_un_ty = try self.dg.lowerType(un_ty); + const llvm_un_ty = try o.lowerType(un_ty); if (layout.payload_size == 0) { return self.builder.buildLoad(llvm_un_ty, union_handle, ""); } @@ -8492,19 +8579,20 @@ pub const FuncGen = struct { } fn airClzCtz(self: *FuncGen, inst: Air.Inst.Index, llvm_fn_name: []const u8) !?*llvm.Value { - const mod = self.dg.module; + const o = self.dg.object; + const mod = o.module; const ty_op = self.air.instructions.items(.data)[inst].ty_op; const operand_ty = self.typeOf(ty_op.operand); const operand = try self.resolveInst(ty_op.operand); const llvm_i1 = self.context.intType(1); - const operand_llvm_ty = try self.dg.lowerType(operand_ty); + const operand_llvm_ty = try o.lowerType(operand_ty); const fn_val = self.getIntrinsic(llvm_fn_name, &.{operand_llvm_ty}); const params = [_]*llvm.Value{ operand, llvm_i1.constNull() }; const wrong_size_result = self.builder.buildCall(fn_val.globalGetValueType(), fn_val, ¶ms, params.len, .C, .Auto, ""); const result_ty = self.typeOfIndex(inst); - const result_llvm_ty = try self.dg.lowerType(result_ty); + const result_llvm_ty = try o.lowerType(result_ty); const bits = operand_ty.intInfo(mod).bits; const result_bits = result_ty.intInfo(mod).bits; @@ -8518,18 +8606,19 @@ pub const FuncGen = struct { } fn airBitOp(self: *FuncGen, inst: Air.Inst.Index, llvm_fn_name: []const u8) !?*llvm.Value { - const mod = self.dg.module; + const o = self.dg.object; + const mod = o.module; const ty_op = self.air.instructions.items(.data)[inst].ty_op; const operand_ty = self.typeOf(ty_op.operand); const operand = try self.resolveInst(ty_op.operand); const params = [_]*llvm.Value{operand}; - const operand_llvm_ty = try self.dg.lowerType(operand_ty); + const operand_llvm_ty = try o.lowerType(operand_ty); const fn_val = self.getIntrinsic(llvm_fn_name, &.{operand_llvm_ty}); const wrong_size_result = self.builder.buildCall(fn_val.globalGetValueType(), fn_val, ¶ms, params.len, .C, .Auto, ""); const result_ty = self.typeOfIndex(inst); - const result_llvm_ty = try self.dg.lowerType(result_ty); + const result_llvm_ty = try o.lowerType(result_ty); const bits = operand_ty.intInfo(mod).bits; const result_bits = result_ty.intInfo(mod).bits; @@ -8543,14 +8632,15 @@ pub const FuncGen = struct { } fn airByteSwap(self: *FuncGen, inst: Air.Inst.Index, llvm_fn_name: []const u8) !?*llvm.Value { - const mod = self.dg.module; + const o = self.dg.object; + const mod = o.module; const ty_op = self.air.instructions.items(.data)[inst].ty_op; const operand_ty = self.typeOf(ty_op.operand); var bits = operand_ty.intInfo(mod).bits; assert(bits % 8 == 0); var operand = try self.resolveInst(ty_op.operand); - var operand_llvm_ty = try self.dg.lowerType(operand_ty); + var operand_llvm_ty = try o.lowerType(operand_ty); if (bits % 16 == 8) { // If not an even byte-multiple, we need zero-extend + shift-left 1 byte @@ -8584,7 +8674,7 @@ pub const FuncGen = struct { const wrong_size_result = self.builder.buildCall(fn_val.globalGetValueType(), fn_val, ¶ms, params.len, .C, .Auto, ""); const result_ty = self.typeOfIndex(inst); - const result_llvm_ty = try self.dg.lowerType(result_ty); + const result_llvm_ty = try o.lowerType(result_ty); const result_bits = result_ty.intInfo(mod).bits; if (bits > result_bits) { return self.builder.buildTrunc(wrong_size_result, result_llvm_ty, ""); @@ -8596,7 +8686,8 @@ pub const FuncGen = struct { } fn airErrorSetHasValue(self: *FuncGen, inst: Air.Inst.Index) !?*llvm.Value { - const mod = self.dg.module; + const o = self.dg.object; + const mod = o.module; const ty_op = self.air.instructions.items(.data)[inst].ty_op; const operand = try self.resolveInst(ty_op.operand); const error_set_ty = self.air.getRefType(ty_op.ty); @@ -8609,7 +8700,7 @@ pub const FuncGen = struct { for (names) |name| { const err_int = @intCast(Module.ErrorInt, mod.global_error_set.getIndex(name).?); - const this_tag_int_value = try self.dg.lowerValue(.{ + const this_tag_int_value = try o.lowerValue(.{ .ty = Type.err_int, .val = try mod.intValue(Type.err_int, err_int), }); @@ -8646,13 +8737,14 @@ pub const FuncGen = struct { } fn getIsNamedEnumValueFunction(self: *FuncGen, enum_ty: Type) !*llvm.Value { - const mod = self.dg.module; + const o = self.dg.object; + const mod = o.module; const enum_type = mod.intern_pool.indexToKey(enum_ty.toIntern()).enum_type; // TODO: detect when the type changes and re-emit this function. - const gop = try self.dg.object.named_enum_map.getOrPut(self.dg.gpa, enum_type.decl); + const gop = try o.named_enum_map.getOrPut(o.gpa, enum_type.decl); if (gop.found_existing) return gop.value_ptr.*; - errdefer assert(self.dg.object.named_enum_map.remove(enum_type.decl)); + errdefer assert(o.named_enum_map.remove(enum_type.decl)); var arena_allocator = std.heap.ArenaAllocator.init(self.gpa); defer arena_allocator.deinit(); @@ -8661,14 +8753,14 @@ pub const FuncGen = struct { const fqn = try mod.declPtr(enum_type.decl).getFullyQualifiedName(mod); const llvm_fn_name = try std.fmt.allocPrintZ(arena, "__zig_is_named_enum_value_{}", .{fqn.fmt(&mod.intern_pool)}); - const param_types = [_]*llvm.Type{try self.dg.lowerType(enum_type.tag_ty.toType())}; + const param_types = [_]*llvm.Type{try o.lowerType(enum_type.tag_ty.toType())}; - const llvm_ret_ty = try self.dg.lowerType(Type.bool); + const llvm_ret_ty = try o.lowerType(Type.bool); const fn_type = llvm.functionType(llvm_ret_ty, ¶m_types, param_types.len, .False); - const fn_val = self.dg.object.llvm_module.addFunction(llvm_fn_name, fn_type); + const fn_val = o.llvm_module.addFunction(llvm_fn_name, fn_type); fn_val.setLinkage(.Internal); fn_val.setFunctionCallConv(.Fast); - self.dg.addCommonFnAttributes(fn_val); + o.addCommonFnAttributes(fn_val); gop.value_ptr.* = fn_val; const prev_block = self.builder.getInsertBlock(); @@ -8692,7 +8784,7 @@ pub const FuncGen = struct { for (enum_type.names, 0..) |_, field_index_usize| { const field_index = @intCast(u32, field_index_usize); const this_tag_int_value = int: { - break :int try self.dg.lowerValue(.{ + break :int try o.lowerValue(.{ .ty = enum_ty, .val = try mod.enumValueFieldIndex(enum_ty, field_index), }); @@ -8718,13 +8810,14 @@ pub const FuncGen = struct { } fn getEnumTagNameFunction(self: *FuncGen, enum_ty: Type) !*llvm.Value { - const mod = self.dg.module; + const o = self.dg.object; + const mod = o.module; const enum_type = mod.intern_pool.indexToKey(enum_ty.toIntern()).enum_type; // TODO: detect when the type changes and re-emit this function. - const gop = try self.dg.object.decl_map.getOrPut(self.dg.gpa, enum_type.decl); + const gop = try o.decl_map.getOrPut(o.gpa, enum_type.decl); if (gop.found_existing) return gop.value_ptr.*; - errdefer assert(self.dg.object.decl_map.remove(enum_type.decl)); + errdefer assert(o.decl_map.remove(enum_type.decl)); var arena_allocator = std.heap.ArenaAllocator.init(self.gpa); defer arena_allocator.deinit(); @@ -8734,17 +8827,17 @@ pub const FuncGen = struct { const llvm_fn_name = try std.fmt.allocPrintZ(arena, "__zig_tag_name_{}", .{fqn.fmt(&mod.intern_pool)}); const slice_ty = Type.slice_const_u8_sentinel_0; - const llvm_ret_ty = try self.dg.lowerType(slice_ty); - const usize_llvm_ty = try self.dg.lowerType(Type.usize); + const llvm_ret_ty = try o.lowerType(slice_ty); + const usize_llvm_ty = try o.lowerType(Type.usize); const slice_alignment = slice_ty.abiAlignment(mod); - const param_types = [_]*llvm.Type{try self.dg.lowerType(enum_type.tag_ty.toType())}; + const param_types = [_]*llvm.Type{try o.lowerType(enum_type.tag_ty.toType())}; const fn_type = llvm.functionType(llvm_ret_ty, ¶m_types, param_types.len, .False); - const fn_val = self.dg.object.llvm_module.addFunction(llvm_fn_name, fn_type); + const fn_val = o.llvm_module.addFunction(llvm_fn_name, fn_type); fn_val.setLinkage(.Internal); fn_val.setFunctionCallConv(.Fast); - self.dg.addCommonFnAttributes(fn_val); + o.addCommonFnAttributes(fn_val); gop.value_ptr.* = fn_val; const prev_block = self.builder.getInsertBlock(); @@ -8773,7 +8866,7 @@ pub const FuncGen = struct { const name = mod.intern_pool.stringToSlice(name_ip); const str_init = self.context.constString(name.ptr, @intCast(c_uint, name.len), .False); const str_init_llvm_ty = str_init.typeOf(); - const str_global = self.dg.object.llvm_module.addGlobal(str_init_llvm_ty, ""); + const str_global = o.llvm_module.addGlobal(str_init_llvm_ty, ""); str_global.setInitializer(str_init); str_global.setLinkage(.Private); str_global.setGlobalConstant(.True); @@ -8785,7 +8878,7 @@ pub const FuncGen = struct { usize_llvm_ty.constInt(name.len, .False), }; const slice_init = llvm_ret_ty.constNamedStruct(&slice_fields, slice_fields.len); - const slice_global = self.dg.object.llvm_module.addGlobal(slice_init.typeOf(), ""); + const slice_global = o.llvm_module.addGlobal(slice_init.typeOf(), ""); slice_global.setInitializer(slice_init); slice_global.setLinkage(.Private); slice_global.setGlobalConstant(.True); @@ -8793,7 +8886,7 @@ pub const FuncGen = struct { slice_global.setAlignment(slice_alignment); const return_block = self.context.appendBasicBlock(fn_val, "Name"); - const this_tag_int_value = try self.dg.lowerValue(.{ + const this_tag_int_value = try o.lowerValue(.{ .ty = enum_ty, .val = try mod.enumValueFieldIndex(enum_ty, field_index), }); @@ -8811,29 +8904,32 @@ pub const FuncGen = struct { } fn getCmpLtErrorsLenFunction(self: *FuncGen) !*llvm.Value { - if (self.dg.object.llvm_module.getNamedFunction(lt_errors_fn_name)) |llvm_fn| { + const o = self.dg.object; + + if (o.llvm_module.getNamedFunction(lt_errors_fn_name)) |llvm_fn| { return llvm_fn; } // Function signature: fn (anyerror) bool - const ret_llvm_ty = try self.dg.lowerType(Type.bool); - const anyerror_llvm_ty = try self.dg.lowerType(Type.anyerror); + const ret_llvm_ty = try o.lowerType(Type.bool); + const anyerror_llvm_ty = try o.lowerType(Type.anyerror); const param_types = [_]*llvm.Type{anyerror_llvm_ty}; const fn_type = llvm.functionType(ret_llvm_ty, ¶m_types, param_types.len, .False); - const llvm_fn = self.dg.object.llvm_module.addFunction(lt_errors_fn_name, fn_type); + const llvm_fn = o.llvm_module.addFunction(lt_errors_fn_name, fn_type); llvm_fn.setLinkage(.Internal); llvm_fn.setFunctionCallConv(.Fast); - self.dg.addCommonFnAttributes(llvm_fn); + o.addCommonFnAttributes(llvm_fn); return llvm_fn; } fn airErrorName(self: *FuncGen, inst: Air.Inst.Index) !?*llvm.Value { + const o = self.dg.object; const un_op = self.air.instructions.items(.data)[inst].un_op; const operand = try self.resolveInst(un_op); const slice_ty = self.typeOfIndex(inst); - const slice_llvm_ty = try self.dg.lowerType(slice_ty); + const slice_llvm_ty = try o.lowerType(slice_ty); const error_name_table_ptr = try self.getErrorNameTable(); const ptr_slice_llvm_ty = self.context.pointerType(0); @@ -8844,7 +8940,8 @@ pub const FuncGen = struct { } fn airSplat(self: *FuncGen, inst: Air.Inst.Index) !?*llvm.Value { - const mod = self.dg.module; + const o = self.dg.object; + const mod = o.module; const ty_op = self.air.instructions.items(.data)[inst].ty_op; const scalar = try self.resolveInst(ty_op.operand); const vector_ty = self.typeOfIndex(inst); @@ -8863,7 +8960,8 @@ pub const FuncGen = struct { } fn airShuffle(self: *FuncGen, inst: Air.Inst.Index) !?*llvm.Value { - const mod = self.dg.module; + const o = self.dg.object; + const mod = o.module; const ty_pl = self.air.instructions.items(.data)[inst].ty_pl; const extra = self.air.extraData(Air.Shuffle, ty_pl.payload).data; const a = try self.resolveInst(extra.a); @@ -8916,7 +9014,8 @@ pub const FuncGen = struct { vector_len: usize, accum_init: *llvm.Value, ) !*llvm.Value { - const llvm_usize_ty = try self.dg.lowerType(Type.usize); + const o = self.dg.object; + const llvm_usize_ty = try o.lowerType(Type.usize); const llvm_vector_len = llvm_usize_ty.constInt(vector_len, .False); const llvm_result_ty = accum_init.typeOf(); @@ -8963,7 +9062,8 @@ pub const FuncGen = struct { fn airReduce(self: *FuncGen, inst: Air.Inst.Index, want_fast_math: bool) !?*llvm.Value { self.builder.setFastMath(want_fast_math); - const mod = self.dg.module; + const o = self.dg.object; + const mod = o.module; const target = mod.getTarget(); const reduce = self.air.instructions.items(.data)[inst].reduce; @@ -8992,7 +9092,7 @@ pub const FuncGen = struct { .Add => switch (scalar_ty.zigTypeTag(mod)) { .Int => return self.builder.buildAddReduce(operand), .Float => if (intrinsicsAllowed(scalar_ty, target)) { - const scalar_llvm_ty = try self.dg.lowerType(scalar_ty); + const scalar_llvm_ty = try o.lowerType(scalar_ty); const neutral_value = scalar_llvm_ty.constReal(-0.0); return self.builder.buildFPAddReduce(neutral_value, operand); }, @@ -9001,7 +9101,7 @@ pub const FuncGen = struct { .Mul => switch (scalar_ty.zigTypeTag(mod)) { .Int => return self.builder.buildMulReduce(operand), .Float => if (intrinsicsAllowed(scalar_ty, target)) { - const scalar_llvm_ty = try self.dg.lowerType(scalar_ty); + const scalar_llvm_ty = try o.lowerType(scalar_ty); const neutral_value = scalar_llvm_ty.constReal(1.0); return self.builder.buildFPMulReduce(neutral_value, operand); }, @@ -9029,10 +9129,10 @@ pub const FuncGen = struct { else => unreachable, }; - const param_llvm_ty = try self.dg.lowerType(scalar_ty); + const param_llvm_ty = try o.lowerType(scalar_ty); const param_types = [2]*llvm.Type{ param_llvm_ty, param_llvm_ty }; const libc_fn = self.getLibcFunction(fn_name, ¶m_types, param_llvm_ty); - const init_value = try self.dg.lowerValue(.{ + const init_value = try o.lowerValue(.{ .ty = scalar_ty, .val = try mod.floatValue(scalar_ty, switch (reduce.operation) { .Min => std.math.nan(f32), @@ -9046,12 +9146,13 @@ pub const FuncGen = struct { } fn airAggregateInit(self: *FuncGen, inst: Air.Inst.Index) !?*llvm.Value { - const mod = self.dg.module; + const o = self.dg.object; + const mod = o.module; const ty_pl = self.air.instructions.items(.data)[inst].ty_pl; const result_ty = self.typeOfIndex(inst); const len = @intCast(usize, result_ty.arrayLen(mod)); const elements = @ptrCast([]const Air.Inst.Ref, self.air.extra[ty_pl.payload..][0..len]); - const llvm_result_ty = try self.dg.lowerType(result_ty); + const llvm_result_ty = try o.lowerType(result_ty); switch (result_ty.zigTypeTag(mod)) { .Vector => { @@ -9139,7 +9240,7 @@ pub const FuncGen = struct { .Array => { assert(isByRef(result_ty, mod)); - const llvm_usize = try self.dg.lowerType(Type.usize); + const llvm_usize = try o.lowerType(Type.usize); const alloca_inst = self.buildAlloca(llvm_result_ty, result_ty.abiAlignment(mod)); const array_info = result_ty.arrayInfo(mod); @@ -9177,11 +9278,12 @@ pub const FuncGen = struct { } fn airUnionInit(self: *FuncGen, inst: Air.Inst.Index) !?*llvm.Value { - const mod = self.dg.module; + const o = self.dg.object; + const mod = o.module; const ty_pl = self.air.instructions.items(.data)[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.dg.lowerType(union_ty); + const union_llvm_ty = try o.lowerType(union_ty); const layout = union_ty.unionGetLayout(mod); const union_obj = mod.typeToUnion(union_ty).?; @@ -9223,7 +9325,7 @@ pub const FuncGen = struct { const llvm_payload = try self.resolveInst(extra.init); assert(union_obj.haveFieldTypes()); const field = union_obj.fields.values()[extra.field_index]; - const field_llvm_ty = try self.dg.lowerType(field.ty); + const field_llvm_ty = try o.lowerType(field.ty); const field_size = field.ty.abiSize(mod); const field_align = field.normalAlignment(mod); @@ -9246,7 +9348,7 @@ pub const FuncGen = struct { const fields: [1]*llvm.Type = .{payload}; break :t self.context.structType(&fields, fields.len, .False); } - const tag_llvm_ty = try self.dg.lowerType(union_obj.tag_ty); + const tag_llvm_ty = try o.lowerType(union_obj.tag_ty); var fields: [3]*llvm.Type = undefined; var fields_len: c_uint = 2; if (layout.tag_align >= layout.payload_align) { @@ -9299,7 +9401,7 @@ pub const FuncGen = struct { index_type.constInt(@intFromBool(layout.tag_align < layout.payload_align), .False), }; const field_ptr = self.builder.buildInBoundsGEP(llvm_union_ty, result_ptr, &indices, indices.len, ""); - const tag_llvm_ty = try self.dg.lowerType(union_obj.tag_ty); + const tag_llvm_ty = try o.lowerType(union_obj.tag_ty); const llvm_tag = tag_llvm_ty.constInt(tag_int, .False); const store_inst = self.builder.buildStore(llvm_tag, field_ptr); store_inst.setAlignment(union_obj.tag_ty.abiAlignment(mod)); @@ -9309,6 +9411,7 @@ pub const FuncGen = struct { } fn airPrefetch(self: *FuncGen, inst: Air.Inst.Index) !?*llvm.Value { + const o = self.dg.object; const prefetch = self.air.instructions.items(.data)[inst].prefetch; comptime assert(@intFromEnum(std.builtin.PrefetchOptions.Rw.read) == 0); @@ -9326,7 +9429,7 @@ pub const FuncGen = struct { // by the target. // To work around this, don't emit llvm.prefetch in this case. // See https://bugs.llvm.org/show_bug.cgi?id=21037 - const mod = self.dg.module; + const mod = o.module; const target = mod.getTarget(); switch (prefetch.cache) { .instruction => switch (target.cpu.arch) { @@ -9352,14 +9455,14 @@ pub const FuncGen = struct { const llvm_u32 = self.context.intType(32); const llvm_fn_name = "llvm.prefetch.p0"; - const fn_val = self.dg.object.llvm_module.getNamedFunction(llvm_fn_name) orelse blk: { + const fn_val = o.llvm_module.getNamedFunction(llvm_fn_name) orelse blk: { // declare void @llvm.prefetch(i8*, i32, i32, i32) const llvm_void = self.context.voidType(); const param_types = [_]*llvm.Type{ llvm_ptr_u8, llvm_u32, llvm_u32, llvm_u32, }; const fn_type = llvm.functionType(llvm_void, ¶m_types, param_types.len, .False); - break :blk self.dg.object.llvm_module.addFunction(llvm_fn_name, fn_type); + break :blk o.llvm_module.addFunction(llvm_fn_name, fn_type); }; const ptr = try self.resolveInst(prefetch.ptr); @@ -9375,11 +9478,12 @@ pub const FuncGen = struct { } fn airAddrSpaceCast(self: *FuncGen, inst: Air.Inst.Index) !?*llvm.Value { + const o = self.dg.object; const ty_op = self.air.instructions.items(.data)[inst].ty_op; const inst_ty = self.typeOfIndex(inst); const operand = try self.resolveInst(ty_op.operand); - const llvm_dest_ty = try self.dg.lowerType(inst_ty); + const llvm_dest_ty = try o.lowerType(inst_ty); return self.builder.buildAddrSpaceCast(operand, llvm_dest_ty, ""); } @@ -9399,7 +9503,8 @@ pub const FuncGen = struct { } fn airWorkItemId(self: *FuncGen, inst: Air.Inst.Index) !?*llvm.Value { - const target = self.dg.module.getTarget(); + const o = self.dg.object; + const target = o.module.getTarget(); assert(target.cpu.arch == .amdgcn); // TODO is to port this function to other GPU architectures const pl_op = self.air.instructions.items(.data)[inst].pl_op; @@ -9408,7 +9513,8 @@ pub const FuncGen = struct { } fn airWorkGroupSize(self: *FuncGen, inst: Air.Inst.Index) !?*llvm.Value { - const target = self.dg.module.getTarget(); + const o = self.dg.object; + const target = o.module.getTarget(); assert(target.cpu.arch == .amdgcn); // TODO is to port this function to other GPU architectures const pl_op = self.air.instructions.items(.data)[inst].pl_op; @@ -9437,7 +9543,8 @@ pub const FuncGen = struct { } fn airWorkGroupId(self: *FuncGen, inst: Air.Inst.Index) !?*llvm.Value { - const target = self.dg.module.getTarget(); + const o = self.dg.object; + const target = o.module.getTarget(); assert(target.cpu.arch == .amdgcn); // TODO is to port this function to other GPU architectures const pl_op = self.air.instructions.items(.data)[inst].pl_op; @@ -9446,23 +9553,24 @@ pub const FuncGen = struct { } fn getErrorNameTable(self: *FuncGen) !*llvm.Value { - if (self.dg.object.error_name_table) |table| { + const o = self.dg.object; + if (o.error_name_table) |table| { return table; } - const mod = self.dg.module; + const mod = o.module; const slice_ty = Type.slice_const_u8_sentinel_0; const slice_alignment = slice_ty.abiAlignment(mod); const llvm_slice_ptr_ty = self.context.pointerType(0); // TODO: Address space - const error_name_table_global = self.dg.object.llvm_module.addGlobal(llvm_slice_ptr_ty, "__zig_err_name_table"); + const error_name_table_global = o.llvm_module.addGlobal(llvm_slice_ptr_ty, "__zig_err_name_table"); error_name_table_global.setInitializer(llvm_slice_ptr_ty.getUndef()); error_name_table_global.setLinkage(.Private); error_name_table_global.setGlobalConstant(.True); error_name_table_global.setUnnamedAddr(.True); error_name_table_global.setAlignment(slice_alignment); - self.dg.object.error_name_table = error_name_table_global; + o.error_name_table = error_name_table_global; return error_name_table_global; } @@ -9494,7 +9602,8 @@ pub const FuncGen = struct { opt_ty: Type, can_elide_load: bool, ) !*llvm.Value { - const mod = fg.dg.module; + const o = fg.dg.object; + const mod = o.module; const payload_ty = opt_ty.optionalChild(mod); if (isByRef(opt_ty, mod)) { @@ -9508,7 +9617,7 @@ pub const FuncGen = struct { return fg.loadByRef(payload_ptr, payload_ty, payload_alignment, false); } - const payload_llvm_ty = try fg.dg.lowerType(payload_ty); + const payload_llvm_ty = try o.lowerType(payload_ty); const load_inst = fg.builder.buildLoad(payload_llvm_ty, payload_ptr, ""); load_inst.setAlignment(payload_alignment); return load_inst; @@ -9524,9 +9633,10 @@ pub const FuncGen = struct { payload: *llvm.Value, non_null_bit: *llvm.Value, ) !?*llvm.Value { - const optional_llvm_ty = try self.dg.lowerType(optional_ty); + const o = self.dg.object; + const optional_llvm_ty = try o.lowerType(optional_ty); const non_null_field = self.builder.buildZExt(non_null_bit, self.context.intType(8), ""); - const mod = self.dg.module; + const mod = o.module; if (isByRef(optional_ty, mod)) { const payload_alignment = optional_ty.abiAlignment(mod); @@ -9557,7 +9667,8 @@ pub const FuncGen = struct { struct_ptr_ty: Type, field_index: u32, ) !?*llvm.Value { - const mod = self.dg.module; + const o = self.dg.object; + const mod = o.module; const struct_ty = struct_ptr_ty.childType(mod); switch (struct_ty.zigTypeTag(mod)) { .Struct => switch (struct_ty.containerLayout(mod)) { @@ -9578,13 +9689,13 @@ pub const FuncGen = struct { const byte_offset = struct_ty.packedStructFieldByteOffset(field_index, mod); if (byte_offset == 0) return struct_ptr; const byte_llvm_ty = self.context.intType(8); - const llvm_usize = try self.dg.lowerType(Type.usize); + const llvm_usize = try o.lowerType(Type.usize); const llvm_index = llvm_usize.constInt(byte_offset, .False); const indices: [1]*llvm.Value = .{llvm_index}; return self.builder.buildInBoundsGEP(byte_llvm_ty, struct_ptr, &indices, indices.len, ""); }, else => { - const struct_llvm_ty = try self.dg.lowerPtrElemTy(struct_ty); + const struct_llvm_ty = try o.lowerPtrElemTy(struct_ty); if (llvmField(struct_ty, field_index, mod)) |llvm_field| { return self.builder.buildStructGEP(struct_llvm_ty, struct_ptr, llvm_field.index, ""); @@ -9604,7 +9715,7 @@ pub const FuncGen = struct { const layout = struct_ty.unionGetLayout(mod); if (layout.payload_size == 0 or struct_ty.containerLayout(mod) == .Packed) return struct_ptr; const payload_index = @intFromBool(layout.tag_align >= layout.payload_align); - const union_llvm_ty = try self.dg.lowerType(struct_ty); + const union_llvm_ty = try o.lowerType(struct_ty); const union_field_ptr = self.builder.buildStructGEP(union_llvm_ty, struct_ptr, payload_index, ""); return union_field_ptr; }, @@ -9612,10 +9723,11 @@ pub const FuncGen = struct { } } - fn getIntrinsic(self: *FuncGen, name: []const u8, types: []const *llvm.Type) *llvm.Value { + fn getIntrinsic(fg: *FuncGen, name: []const u8, types: []const *llvm.Type) *llvm.Value { const id = llvm.lookupIntrinsicID(name.ptr, name.len); assert(id != 0); - return self.llvmModule().getIntrinsicDeclaration(id, types.ptr, types.len); + const o = fg.dg.object; + return o.llvm_module.getIntrinsicDeclaration(id, types.ptr, types.len); } /// Load a by-ref type by constructing a new alloca and performing a memcpy. @@ -9626,8 +9738,9 @@ pub const FuncGen = struct { ptr_alignment: u32, is_volatile: bool, ) !*llvm.Value { - const mod = fg.dg.module; - const pointee_llvm_ty = try fg.dg.lowerType(pointee_type); + const o = fg.dg.object; + const mod = o.module; + const pointee_llvm_ty = try o.lowerType(pointee_type); const result_align = @max(ptr_alignment, pointee_type.abiAlignment(mod)); const result_ptr = fg.buildAlloca(pointee_llvm_ty, result_align); const llvm_usize = fg.context.intType(Type.usize.intInfo(mod).bits); @@ -9647,7 +9760,8 @@ pub const FuncGen = struct { /// alloca and copies the value into it, then returns the alloca instruction. /// For isByRef=false types, it creates a load instruction and returns it. fn load(self: *FuncGen, ptr: *llvm.Value, ptr_ty: Type) !?*llvm.Value { - const mod = self.dg.module; + const o = self.dg.object; + const mod = o.module; const info = ptr_ty.ptrInfo(mod); const elem_ty = info.child.toType(); if (!elem_ty.hasRuntimeBitsIgnoreComptime(mod)) return null; @@ -9659,7 +9773,7 @@ pub const FuncGen = struct { assert(info.flags.vector_index != .runtime); if (info.flags.vector_index != .none) { const index_u32 = self.context.intType(32).constInt(@intFromEnum(info.flags.vector_index), .False); - const vec_elem_ty = try self.dg.lowerType(elem_ty); + const vec_elem_ty = try o.lowerType(elem_ty); const vec_ty = vec_elem_ty.vectorType(info.packed_offset.host_size); const loaded_vector = self.builder.buildLoad(vec_ty, ptr, ""); @@ -9673,7 +9787,7 @@ pub const FuncGen = struct { if (isByRef(elem_ty, mod)) { return self.loadByRef(ptr, elem_ty, ptr_alignment, info.flags.is_volatile); } - const elem_llvm_ty = try self.dg.lowerType(elem_ty); + const elem_llvm_ty = try o.lowerType(elem_ty); const llvm_inst = self.builder.buildLoad(elem_llvm_ty, ptr, ""); llvm_inst.setAlignment(ptr_alignment); llvm_inst.setVolatile(ptr_volatile); @@ -9688,7 +9802,7 @@ pub const FuncGen = struct { const elem_bits = @intCast(c_uint, ptr_ty.childType(mod).bitSize(mod)); const shift_amt = containing_int.typeOf().constInt(info.packed_offset.bit_offset, .False); const shifted_value = self.builder.buildLShr(containing_int, shift_amt, ""); - const elem_llvm_ty = try self.dg.lowerType(elem_ty); + const elem_llvm_ty = try o.lowerType(elem_ty); if (isByRef(elem_ty, mod)) { const result_align = elem_ty.abiAlignment(mod); @@ -9723,7 +9837,8 @@ pub const FuncGen = struct { elem: *llvm.Value, ordering: llvm.AtomicOrdering, ) !void { - const mod = self.dg.module; + const o = self.dg.object; + const mod = o.module; const info = ptr_ty.ptrInfo(mod); const elem_ty = info.child.toType(); if (!elem_ty.isFnOrHasRuntimeBitsIgnoreComptime(mod)) { @@ -9735,7 +9850,7 @@ pub const FuncGen = struct { assert(info.flags.vector_index != .runtime); if (info.flags.vector_index != .none) { const index_u32 = self.context.intType(32).constInt(@intFromEnum(info.flags.vector_index), .False); - const vec_elem_ty = try self.dg.lowerType(elem_ty); + const vec_elem_ty = try o.lowerType(elem_ty); const vec_ty = vec_elem_ty.vectorType(info.packed_offset.host_size); const loaded_vector = self.builder.buildLoad(vec_ty, ptr, ""); @@ -9805,7 +9920,8 @@ pub const FuncGen = struct { fn valgrindMarkUndef(fg: *FuncGen, ptr: *llvm.Value, len: *llvm.Value) void { const VG_USERREQ__MAKE_MEM_UNDEFINED = 1296236545; - const target = fg.dg.module.getTarget(); + const o = fg.dg.object; + const target = o.module.getTarget(); const usize_llvm_ty = fg.context.intType(target.ptrBitWidth()); const zero = usize_llvm_ty.constInt(0, .False); const req = usize_llvm_ty.constInt(VG_USERREQ__MAKE_MEM_UNDEFINED, .False); @@ -9823,7 +9939,8 @@ pub const FuncGen = struct { a4: *llvm.Value, a5: *llvm.Value, ) *llvm.Value { - const mod = fg.dg.module; + const o = fg.dg.object; + const mod = o.module; const target = mod.getTarget(); if (!target_util.hasValgrindSupport(target)) return default_value; @@ -9907,12 +10024,14 @@ pub const FuncGen = struct { } fn typeOf(fg: *FuncGen, inst: Air.Inst.Ref) Type { - const mod = fg.dg.module; + const o = fg.dg.object; + const mod = o.module; return fg.air.typeOf(inst, &mod.intern_pool); } fn typeOfIndex(fg: *FuncGen, inst: Air.Inst.Index) Type { - const mod = fg.dg.module; + const o = fg.dg.object; + const mod = o.module; return fg.air.typeOfIndex(inst, &mod.intern_pool); } }; @@ -10370,160 +10489,160 @@ fn firstParamSRetSystemV(ty: Type, mod: *Module) bool { /// In order to support the C calling convention, some return types need to be lowered /// completely differently in the function prototype to honor the C ABI, and then /// be effectively bitcasted to the actual return type. -fn lowerFnRetTy(dg: *DeclGen, fn_info: InternPool.Key.FuncType) !*llvm.Type { - const mod = dg.module; +fn lowerFnRetTy(o: *Object, fn_info: InternPool.Key.FuncType) !*llvm.Type { + const mod = o.module; const return_type = fn_info.return_type.toType(); if (!return_type.hasRuntimeBitsIgnoreComptime(mod)) { // If the return type is an error set or an error union, then we make this // anyerror return type instead, so that it can be coerced into a function // pointer type which has anyerror as the return type. if (return_type.isError(mod)) { - return dg.lowerType(Type.anyerror); + return o.lowerType(Type.anyerror); } else { - return dg.context.voidType(); + return o.context.voidType(); } } const target = mod.getTarget(); switch (fn_info.cc) { .Unspecified, .Inline => { if (isByRef(return_type, mod)) { - return dg.context.voidType(); + return o.context.voidType(); } else { - return dg.lowerType(return_type); + return o.lowerType(return_type); } }, .C => { switch (target.cpu.arch) { - .mips, .mipsel => return dg.lowerType(return_type), + .mips, .mipsel => return o.lowerType(return_type), .x86_64 => switch (target.os.tag) { - .windows => return lowerWin64FnRetTy(dg, fn_info), - else => return lowerSystemVFnRetTy(dg, fn_info), + .windows => return lowerWin64FnRetTy(o, fn_info), + else => return lowerSystemVFnRetTy(o, fn_info), }, .wasm32 => { if (isScalar(mod, return_type)) { - return dg.lowerType(return_type); + return o.lowerType(return_type); } const classes = wasm_c_abi.classifyType(return_type, mod); if (classes[0] == .indirect or classes[0] == .none) { - return dg.context.voidType(); + return o.context.voidType(); } assert(classes[0] == .direct and classes[1] == .none); const scalar_type = wasm_c_abi.scalarType(return_type, mod); const abi_size = scalar_type.abiSize(mod); - return dg.context.intType(@intCast(c_uint, abi_size * 8)); + return o.context.intType(@intCast(c_uint, abi_size * 8)); }, .aarch64, .aarch64_be => { switch (aarch64_c_abi.classifyType(return_type, mod)) { - .memory => return dg.context.voidType(), - .float_array => return dg.lowerType(return_type), - .byval => return dg.lowerType(return_type), + .memory => return o.context.voidType(), + .float_array => return o.lowerType(return_type), + .byval => return o.lowerType(return_type), .integer => { const bit_size = return_type.bitSize(mod); - return dg.context.intType(@intCast(c_uint, bit_size)); + return o.context.intType(@intCast(c_uint, bit_size)); }, - .double_integer => return dg.context.intType(64).arrayType(2), + .double_integer => return o.context.intType(64).arrayType(2), } }, .arm, .armeb => { switch (arm_c_abi.classifyType(return_type, mod, .ret)) { - .memory, .i64_array => return dg.context.voidType(), + .memory, .i64_array => return o.context.voidType(), .i32_array => |len| if (len == 1) { - return dg.context.intType(32); + return o.context.intType(32); } else { - return dg.context.voidType(); + return o.context.voidType(); }, - .byval => return dg.lowerType(return_type), + .byval => return o.lowerType(return_type), } }, .riscv32, .riscv64 => { switch (riscv_c_abi.classifyType(return_type, mod)) { - .memory => return dg.context.voidType(), + .memory => return o.context.voidType(), .integer => { const bit_size = return_type.bitSize(mod); - return dg.context.intType(@intCast(c_uint, bit_size)); + return o.context.intType(@intCast(c_uint, bit_size)); }, .double_integer => { var llvm_types_buffer: [2]*llvm.Type = .{ - dg.context.intType(64), - dg.context.intType(64), + o.context.intType(64), + o.context.intType(64), }; - return dg.context.structType(&llvm_types_buffer, 2, .False); + return o.context.structType(&llvm_types_buffer, 2, .False); }, - .byval => return dg.lowerType(return_type), + .byval => return o.lowerType(return_type), } }, // TODO investigate C ABI for other architectures - else => return dg.lowerType(return_type), + else => return o.lowerType(return_type), } }, - .Win64 => return lowerWin64FnRetTy(dg, fn_info), - .SysV => return lowerSystemVFnRetTy(dg, fn_info), + .Win64 => return lowerWin64FnRetTy(o, fn_info), + .SysV => return lowerSystemVFnRetTy(o, fn_info), .Stdcall => { if (isScalar(mod, return_type)) { - return dg.lowerType(return_type); + return o.lowerType(return_type); } else { - return dg.context.voidType(); + return o.context.voidType(); } }, - else => return dg.lowerType(return_type), + else => return o.lowerType(return_type), } } -fn lowerWin64FnRetTy(dg: *DeclGen, fn_info: InternPool.Key.FuncType) !*llvm.Type { - const mod = dg.module; +fn lowerWin64FnRetTy(o: *Object, fn_info: InternPool.Key.FuncType) !*llvm.Type { + const mod = o.module; const return_type = fn_info.return_type.toType(); switch (x86_64_abi.classifyWindows(return_type, mod)) { .integer => { if (isScalar(mod, return_type)) { - return dg.lowerType(return_type); + return o.lowerType(return_type); } else { const abi_size = return_type.abiSize(mod); - return dg.context.intType(@intCast(c_uint, abi_size * 8)); + return o.context.intType(@intCast(c_uint, abi_size * 8)); } }, - .win_i128 => return dg.context.intType(64).vectorType(2), - .memory => return dg.context.voidType(), - .sse => return dg.lowerType(return_type), + .win_i128 => return o.context.intType(64).vectorType(2), + .memory => return o.context.voidType(), + .sse => return o.lowerType(return_type), else => unreachable, } } -fn lowerSystemVFnRetTy(dg: *DeclGen, fn_info: InternPool.Key.FuncType) !*llvm.Type { - const mod = dg.module; +fn lowerSystemVFnRetTy(o: *Object, fn_info: InternPool.Key.FuncType) !*llvm.Type { + const mod = o.module; const return_type = fn_info.return_type.toType(); if (isScalar(mod, return_type)) { - return dg.lowerType(return_type); + return o.lowerType(return_type); } const classes = x86_64_abi.classifySystemV(return_type, mod, .ret); if (classes[0] == .memory) { - return dg.context.voidType(); + return o.context.voidType(); } var llvm_types_buffer: [8]*llvm.Type = undefined; var llvm_types_index: u32 = 0; for (classes) |class| { switch (class) { .integer => { - llvm_types_buffer[llvm_types_index] = dg.context.intType(64); + llvm_types_buffer[llvm_types_index] = o.context.intType(64); llvm_types_index += 1; }, .sse, .sseup => { - llvm_types_buffer[llvm_types_index] = dg.context.doubleType(); + llvm_types_buffer[llvm_types_index] = o.context.doubleType(); llvm_types_index += 1; }, .float => { - llvm_types_buffer[llvm_types_index] = dg.context.floatType(); + llvm_types_buffer[llvm_types_index] = o.context.floatType(); llvm_types_index += 1; }, .float_combine => { - llvm_types_buffer[llvm_types_index] = dg.context.floatType().vectorType(2); + llvm_types_buffer[llvm_types_index] = o.context.floatType().vectorType(2); llvm_types_index += 1; }, .x87 => { if (llvm_types_index != 0 or classes[2] != .none) { - return dg.context.voidType(); + return o.context.voidType(); } - llvm_types_buffer[llvm_types_index] = dg.context.x86FP80Type(); + llvm_types_buffer[llvm_types_index] = o.context.x86FP80Type(); llvm_types_index += 1; }, .x87up => continue, @@ -10537,13 +10656,13 @@ fn lowerSystemVFnRetTy(dg: *DeclGen, fn_info: InternPool.Key.FuncType) !*llvm.Ty } if (classes[0] == .integer and classes[1] == .none) { const abi_size = return_type.abiSize(mod); - return dg.context.intType(@intCast(c_uint, abi_size * 8)); + return o.context.intType(@intCast(c_uint, abi_size * 8)); } - return dg.context.structType(&llvm_types_buffer, llvm_types_index, .False); + return o.context.structType(&llvm_types_buffer, llvm_types_index, .False); } const ParamTypeIterator = struct { - dg: *DeclGen, + object: *Object, fn_info: InternPool.Key.FuncType, zig_index: u32, llvm_index: u32, @@ -10586,7 +10705,7 @@ const ParamTypeIterator = struct { } fn nextInner(it: *ParamTypeIterator, ty: Type) ?Lowering { - const mod = it.dg.module; + const mod = it.object.module; const target = mod.getTarget(); if (!ty.hasRuntimeBitsIgnoreComptime(mod)) { @@ -10641,7 +10760,7 @@ const ParamTypeIterator = struct { .byval => return .byval, .integer => { it.llvm_types_len = 1; - it.llvm_types_buffer[0] = it.dg.context.intType(64); + it.llvm_types_buffer[0] = it.object.context.intType(64); return .multiple_llvm_types; }, .double_integer => return Lowering{ .i64_array = 2 }, @@ -10703,7 +10822,7 @@ const ParamTypeIterator = struct { } fn nextWin64(it: *ParamTypeIterator, ty: Type) ?Lowering { - const mod = it.dg.module; + const mod = it.object.module; switch (x86_64_abi.classifyWindows(ty, mod)) { .integer => { if (isScalar(mod, ty)) { @@ -10736,7 +10855,7 @@ const ParamTypeIterator = struct { } fn nextSystemV(it: *ParamTypeIterator, ty: Type) ?Lowering { - const mod = it.dg.module; + const mod = it.object.module; const classes = x86_64_abi.classifySystemV(ty, mod, .arg); if (classes[0] == .memory) { it.zig_index += 1; @@ -10754,19 +10873,19 @@ const ParamTypeIterator = struct { for (classes) |class| { switch (class) { .integer => { - llvm_types_buffer[llvm_types_index] = it.dg.context.intType(64); + llvm_types_buffer[llvm_types_index] = it.object.context.intType(64); llvm_types_index += 1; }, .sse, .sseup => { - llvm_types_buffer[llvm_types_index] = it.dg.context.doubleType(); + llvm_types_buffer[llvm_types_index] = it.object.context.doubleType(); llvm_types_index += 1; }, .float => { - llvm_types_buffer[llvm_types_index] = it.dg.context.floatType(); + llvm_types_buffer[llvm_types_index] = it.object.context.floatType(); llvm_types_index += 1; }, .float_combine => { - llvm_types_buffer[llvm_types_index] = it.dg.context.floatType().vectorType(2); + llvm_types_buffer[llvm_types_index] = it.object.context.floatType().vectorType(2); llvm_types_index += 1; }, .x87 => { @@ -10797,9 +10916,9 @@ const ParamTypeIterator = struct { } }; -fn iterateParamTypes(dg: *DeclGen, fn_info: InternPool.Key.FuncType) ParamTypeIterator { +fn iterateParamTypes(object: *Object, fn_info: InternPool.Key.FuncType) ParamTypeIterator { return .{ - .dg = dg, + .object = object, .fn_info = fn_info, .zig_index = 0, .llvm_index = 0, @@ -11055,8 +11174,8 @@ const lt_errors_fn_name = "__zig_lt_errors_len"; /// Without this workaround, LLVM crashes with "unknown codeview register H1" /// https://github.com/llvm/llvm-project/issues/56484 -fn needDbgVarWorkaround(dg: *DeclGen) bool { - const target = dg.module.getTarget(); +fn needDbgVarWorkaround(o: *Object) bool { + const target = o.module.getTarget(); if (target.os.tag == .windows and target.cpu.arch == .aarch64) { return true; } |
