zig

fork of https://codeberg.org/ziglang/zig
Log | Files | Refs | README | LICENSE

commit bd8088bb9826b40be281d5cca89eac7ff7b76241 (tree)
parent 5941c9da08ae0d8ba4add37f0baeafdcd160dbd4
Author: Matthew Lugg <mlugg@mlugg.co.uk>
Date:   Mon, 23 Mar 2026 11:26:23 +0000

llvm: random enhancements and cleanups

Diffstat:
Msrc/Air.zig | 17++++++++++++-----
Msrc/Compilation.zig | 2+-
Msrc/codegen/llvm.zig | 207++++++++++++++++++++++++++++++++++++++++++-------------------------------------
Msrc/codegen/llvm/FuncGen.zig | 807+++++++++++++++++++++++++++++++++++--------------------------------------------
4 files changed, 482 insertions(+), 551 deletions(-)

diff --git a/src/Air.zig b/src/Air.zig @@ -870,13 +870,20 @@ pub const Inst = struct { /// Uses the `pl_op` field, payload represents the index of the target memory. wasm_memory_grow, - /// Returns `true` if and only if the operand, an integer with - /// the same size as the error integer type, is less than the - /// total number of errors in the Module. + /// Returns `true` if and only if the operand, an integer with the same + /// size as the error integer type, is less than *or equal to* the total + /// number of errors in the Zcu. The "or equal to" is a consequence of + /// value 0 being reserved for the "non-error" status in error unions. + /// MLUGG TODO: rename this instruction to `cmp_lte_errors_len` + /// + /// This instruction exists (as opposed to just using `cmp_lte` against + /// a constant) because the number of errors in the Zcu is not known + /// until `Compilation.flush`. Before then, semantic analysis could + /// discover new errors at any time. + /// /// Result type is always `bool`. + /// /// Uses the `un_op` field. - /// Note that the number of errors in the Module cannot be considered stable until - /// flush(). cmp_lt_errors_len, /// Returns pointer to current error return trace. diff --git a/src/Compilation.zig b/src/Compilation.zig @@ -2485,7 +2485,7 @@ pub fn create(gpa: Allocator, arena: Allocator, io: Io, diag: *CreateDiagnostic, if (use_llvm) { if (opt_zcu) |zcu| { - zcu.llvm_object = try LlvmObject.create(arena, comp); + zcu.llvm_object = try LlvmObject.create(arena, zcu); } } diff --git a/src/codegen/llvm.zig b/src/codegen/llvm.zig @@ -549,7 +549,7 @@ pub const Object = struct { /// type from the global error set. debug_anyerror_fwd_ref: Builder.Metadata.Optional, - target: *const std.Target, + zcu: *Zcu, /// Ideally we would use `llvm_module.getNamedFunction` to go from *Decl to LLVM function, /// but that has some downsides: /// * we have to compute the fully qualified name every time we want to do the lookup @@ -574,9 +574,12 @@ pub const Object = struct { /// Note that the values are not added until `emit`, when all errors in /// the compilation are known. error_name_table: Builder.Variable.Index, - - /// Memoizes a null `?usize` value. - null_opt_usize: Builder.Constant, + /// Constant variable whose value is the number of errors in the Zcu. + /// + /// Initially `.none`---populated lazily by `getErrorsLen`. + /// + /// If this is not `.none`, the variable's initializer is set in `emit`. + errors_len_variable: Builder.Variable.Index, /// Values for `@llvm.used`. used: std.ArrayList(Builder.Constant), @@ -585,10 +588,11 @@ pub const Object = struct { const TypeMap = std.AutoHashMapUnmanaged(InternPool.Index, Builder.Type); - pub fn create(arena: Allocator, comp: *Compilation) !Ptr { + pub fn create(arena: Allocator, zcu: *Zcu) !Ptr { dev.check(.llvm_backend); + const comp = zcu.comp; const gpa = comp.gpa; - const target = &comp.root_mod.resolved_target.result; + const target = zcu.getTarget(); const llvm_target_triple = try targetTriple(arena, target); var builder = try Builder.init(.{ @@ -616,10 +620,7 @@ pub const Object = struct { // way already, but here we throw all that sweet information // into the garbage can by converting into absolute paths. What // a terrible tragedy. - const compile_unit_dir = blk: { - const zcu = comp.zcu orelse break :blk comp.dirs.cwd; - break :blk try zcu.main_mod.root.toAbsolute(comp.dirs, arena); - }; + const compile_unit_dir = try zcu.main_mod.root.toAbsolute(comp.dirs, arena); const debug_file = try builder.debugFile( try builder.metadataString(comp.root_name), @@ -665,14 +666,14 @@ pub const Object = struct { .debug_file_map = .empty, .debug_types = .empty, .debug_anyerror_fwd_ref = .none, - .target = target, + .zcu = zcu, .nav_map = .empty, .uav_map = .empty, .enum_tag_name_map = .empty, .named_enum_map = .empty, .type_map = .empty, .error_name_table = .none, - .null_opt_usize = .no_init, + .errors_len_variable = .none, .used = .empty, }; return obj; @@ -722,7 +723,7 @@ pub const Object = struct { name_variable_index.setLinkage(.private, &o.builder); name_variable_index.setMutability(.constant, &o.builder); name_variable_index.setUnnamedAddr(.unnamed_addr, &o.builder); - name_variable_index.setAlignment(comptime Builder.Alignment.fromByteUnits(1), &o.builder); + name_variable_index.setAlignment(comptime .fromByteUnits(1), &o.builder); llvm_error.* = try o.builder.structConst(llvm_slice_ty, &.{ name_variable_index.toConst(&o.builder), @@ -730,52 +731,17 @@ pub const Object = struct { }); } - const table_variable_index = try o.builder.addVariable(.empty, llvm_table_ty, .default); - try table_variable_index.setInitializer( + try o.error_name_table.setInitializer( try o.builder.arrayConst(llvm_table_ty, llvm_errors), &o.builder, ); - table_variable_index.setLinkage(.private, &o.builder); - table_variable_index.setMutability(.constant, &o.builder); - table_variable_index.setUnnamedAddr(.unnamed_addr, &o.builder); - table_variable_index.setAlignment( - slice_ty.abiAlignment(zcu).toLlvm(), - &o.builder, - ); - - try o.error_name_table.setInitializer(table_variable_index.toConst(&o.builder), &o.builder); - } - - fn genCmpLtErrorsLenFunction(o: *Object, pt: Zcu.PerThread) !void { - // If there is no such function in the module, it means the source code does not need it. - const name = o.builder.strtabStringIfExists(lt_errors_fn_name) orelse return; - const llvm_fn = o.builder.getGlobal(name) orelse return; - const errors_len = pt.zcu.intern_pool.global_error_set.getNamesFromMainThread().len; - - var wip = try Builder.WipFunction.init(&o.builder, .{ - .function = llvm_fn.ptrConst(&o.builder).kind.function, - .strip = true, - }); - defer wip.deinit(); - wip.cursor = .{ .block = try wip.block(0, "Entry") }; - - // Example source of the following LLVM IR: - // fn __zig_lt_errors_len(index: u16) bool { - // return index <= total_errors_len; - // } - - const lhs = wip.arg(0); - const rhs = try o.builder.intValue(try o.errorIntType(pt), errors_len); - const is_lt = try wip.icmp(.ule, lhs, rhs, ""); - _ = try wip.ret(is_lt); - try wip.finish(); } - fn genModuleLevelAssembly(object: *Object, pt: Zcu.PerThread) Allocator.Error!void { + fn genModuleLevelAssembly(object: *Object) Allocator.Error!void { const b = &object.builder; const gpa = b.gpa; b.module_asm.clearRetainingCapacity(); - for (pt.zcu.global_assembly.values()) |assembly| { + for (object.zcu.global_assembly.values()) |assembly| { try b.module_asm.ensureUnusedCapacity(gpa, assembly.len + 1); b.module_asm.appendSliceAssumeCapacity(assembly); b.module_asm.appendAssumeCapacity('\n'); @@ -808,9 +774,13 @@ pub const Object = struct { const diags = &comp.link_diags; { + if (o.errors_len_variable != .none) { + const errors_len = zcu.intern_pool.global_error_set.getNamesFromMainThread().len; + const init_val = try o.builder.intConst(try o.errorIntType(), errors_len); + try o.errors_len_variable.setInitializer(init_val, &o.builder); + } try o.genErrorNameTable(pt); - try o.genCmpLtErrorsLenFunction(pt); - try o.genModuleLevelAssembly(pt); + try o.genModuleLevelAssembly(); if (o.used.items.len > 0) { const array_llvm_ty = try o.builder.arrayType(o.used.items.len, .ptr); @@ -827,7 +797,7 @@ pub const Object = struct { if (!o.builder.strip) { if (o.debug_anyerror_fwd_ref.unwrap()) |fwd_ref| { - const debug_anyerror_type = try o.lowerDebugAnyerrorType(pt); + const debug_anyerror_type = try o.lowerDebugAnyerrorType(); o.builder.resolveDebugForwardReference(fwd_ref, debug_anyerror_type); } @@ -1454,7 +1424,7 @@ pub const Object = struct { } const file, const subprogram = if (!wip.strip) debug_info: { - const file = try o.getDebugFile(pt, file_scope); + const file = try o.getDebugFile(file_scope); const line_number = zcu.navSrcLine(func.owner_nav) + 1; const is_internal_linkage = ip.indexToKey(nav.resolved.?.value) != .@"extern"; @@ -1658,7 +1628,7 @@ pub const Object = struct { const line_number = zcu.navSrcLine(nav_index) + 1; if (!mod.strip) { - const debug_file = try o.getDebugFile(pt, file_scope); + const debug_file = try o.getDebugFile(file_scope); const debug_global_var = try o.builder.debugGlobalVar( try o.builder.metadataString(nav.name.toSlice(ip)), // Name @@ -1796,7 +1766,7 @@ pub const Object = struct { try global_index.rename(main_exp_name, &o.builder); break :i global_index; } - const llvm_addr_space = toLlvmAddressSpace(.generic, o.target); + const llvm_addr_space = toLlvmAddressSpace(.generic, zcu.getTarget()); const variable_index = try o.builder.addVariable( main_exp_name, try o.lowerType(pt, Type.fromInterned(ip.typeOf(exported_value))), @@ -2002,13 +1972,13 @@ pub const Object = struct { } } - pub fn getDebugFile(o: *Object, pt: Zcu.PerThread, file_index: Zcu.File.Index) Allocator.Error!Builder.Metadata { + pub fn getDebugFile(o: *Object, file_index: Zcu.File.Index) Allocator.Error!Builder.Metadata { const gpa = o.gpa; const gop = try o.debug_file_map.getOrPut(gpa, file_index); errdefer assert(o.debug_file_map.remove(file_index)); if (gop.found_existing) return gop.value_ptr.*; - const path = pt.zcu.fileByIndex(file_index).path; - const abs_path = try path.toAbsolute(pt.zcu.comp.dirs, gpa); + const path = o.zcu.fileByIndex(file_index).path; + const abs_path = try path.toAbsolute(o.zcu.comp.dirs, gpa); defer gpa.free(abs_path); gop.value_ptr.* = try o.builder.debugFile( @@ -2035,8 +2005,8 @@ pub const Object = struct { assert(!o.builder.strip); const gpa = o.gpa; - const target = o.target; const zcu = pt.zcu; + const target = zcu.getTarget(); const ip = &zcu.intern_pool; const name = try o.builder.metadataStringFmt("{f}", .{ty.fmt(pt)}); @@ -2386,7 +2356,7 @@ pub const Object = struct { const struct_type = zcu.typeToStruct(ty).?; - const file = try o.getDebugFile(pt, struct_type.zir_index.resolveFile(ip)); + const file = try o.getDebugFile(struct_type.zir_index.resolveFile(ip)); const scope = if (ty.getParentNamespace(zcu).unwrap()) |parent_namespace| try o.namespaceToDebugScope(pt, parent_namespace) else @@ -2453,7 +2423,7 @@ pub const Object = struct { .@"union" => { const union_type = ip.loadUnionType(ty.toIntern()); - const file = try o.getDebugFile(pt, union_type.zir_index.resolveFile(ip)); + const file = try o.getDebugFile(union_type.zir_index.resolveFile(ip)); const scope = if (ty.getParentNamespace(zcu).unwrap()) |parent_namespace| try o.namespaceToDebugScope(pt, parent_namespace) else @@ -2611,7 +2581,7 @@ pub const Object = struct { ); }, .@"enum" => { - const file = try o.getDebugFile(pt, ty.typeDeclInstAllowGeneratedTag(zcu).?.resolveFile(ip)); + const file = try o.getDebugFile(ty.typeDeclInstAllowGeneratedTag(zcu).?.resolveFile(ip)); const scope = if (ty.getParentNamespace(zcu).unwrap()) |parent_namespace| try o.namespaceToDebugScope(pt, parent_namespace) else @@ -2672,7 +2642,7 @@ pub const Object = struct { return o.builder.debugSignedType(name, 0); } - const file = try o.getDebugFile(pt, ty.typeDeclInstAllowGeneratedTag(zcu).?.resolveFile(ip)); + const file = try o.getDebugFile(ty.typeDeclInstAllowGeneratedTag(zcu).?.resolveFile(ip)); const scope = if (ty.getParentNamespace(zcu).unwrap()) |parent_namespace| try o.namespaceToDebugScope(pt, parent_namespace) else @@ -2697,8 +2667,8 @@ pub const Object = struct { } /// Called in `emit` so that the global error set is fully populated. - fn lowerDebugAnyerrorType(o: *Object, pt: Zcu.PerThread) Allocator.Error!Builder.Metadata { - const zcu = pt.zcu; + fn lowerDebugAnyerrorType(o: *Object) Allocator.Error!Builder.Metadata { + const zcu = o.zcu; const ip = &zcu.intern_pool; const gpa = zcu.comp.gpa; @@ -2732,7 +2702,7 @@ pub const Object = struct { null, // file o.debug_compile_unit.unwrap().?, // scope 0, // line - try o.getDebugType(pt, try pt.intType(.unsigned, error_set_bits)), + try o.builder.debugUnsignedType(null, error_set_bits), Type.anyerror.abiSize(zcu) * 8, Type.anyerror.abiAlignment(zcu).toByteUnits().? * 8, try o.builder.metadataTuple(enumerators), @@ -2744,7 +2714,7 @@ pub const Object = struct { fn namespaceToDebugScope(o: *Object, pt: Zcu.PerThread, namespace_index: InternPool.NamespaceIndex) !Builder.Metadata { const zcu = pt.zcu; const namespace = zcu.namespacePtr(namespace_index); - if (namespace.parent == .none) return try o.getDebugFile(pt, namespace.file_scope); + if (namespace.parent == .none) return try o.getDebugFile(namespace.file_scope); return o.getDebugType(pt, .fromInterned(namespace.owner_type)); } @@ -3086,8 +3056,8 @@ pub const Object = struct { return variable_index; } - pub fn errorIntType(o: *Object, pt: Zcu.PerThread) Allocator.Error!Builder.Type { - return o.builder.intType(pt.zcu.errorSetBits()); + pub fn errorIntType(o: *Object) Allocator.Error!Builder.Type { + return o.builder.intType(o.zcu.errorSetBits()); } pub fn lowerType(o: *Object, pt: Zcu.PerThread, t: Type) Allocator.Error!Builder.Type { @@ -3146,7 +3116,7 @@ pub const Object = struct { .bool_type => .i1, .void_type => .void, .type_type => unreachable, - .anyerror_type => try o.errorIntType(pt), + .anyerror_type => try o.errorIntType(), .comptime_int_type, .comptime_float_type, .noreturn_type, @@ -3168,7 +3138,7 @@ pub const Object = struct { .optional_noreturn_type => unreachable, .anyerror_void_error_union_type, .adhoc_inferred_error_set_type, - => try o.errorIntType(pt), + => try o.errorIntType(), .generic_poison_type, .empty_tuple_type, => unreachable, @@ -3241,7 +3211,7 @@ pub const Object = struct { .error_union_type => |error_union_type| { // Must stay in sync with `codegen.errUnionPayloadOffset`. // See logic in `lowerPtr`. - const error_type = try o.errorIntType(pt); + const error_type = try o.errorIntType(); if (!Type.fromInterned(error_union_type.payload_type).hasRuntimeBits(zcu)) return error_type; const payload_type = try o.lowerType(pt, Type.fromInterned(error_union_type.payload_type)); @@ -3474,7 +3444,7 @@ pub const Object = struct { }, .enum_type => try o.lowerType(pt, t.intTagType(zcu)), .func_type => |func_type| try o.lowerFnType(pt, func_type), - .error_set_type, .inferred_error_set_type => try o.errorIntType(pt), + .error_set_type, .inferred_error_set_type => try o.errorIntType(), // values, not types .undef, .simple_value, @@ -3624,7 +3594,7 @@ pub const Object = struct { }, .err => |err| { const int = try pt.getErrorValue(err.name); - const llvm_int = try o.builder.intConst(try o.errorIntType(pt), int); + const llvm_int = try o.builder.intConst(try o.errorIntType(), int); return llvm_int; }, .error_union => |error_union| { @@ -4288,29 +4258,40 @@ pub const Object = struct { if (byval) try attributes.addParamAttr(llvm_arg_i, .{ .byval = param_llvm_ty }, &o.builder); } - /// MLUGG TODO: this is super dumb - pub fn getCmpLtErrorsLenFunction(o: *Object, pt: Zcu.PerThread) !Builder.Function.Index { - const name = try o.builder.strtabString(lt_errors_fn_name); - if (o.builder.getGlobal(name)) |llvm_fn| return llvm_fn.ptrConst(&o.builder).kind.function; + pub fn getErrorNameTable(o: *Object) Allocator.Error!Builder.Variable.Index { + if (o.error_name_table != .none) return o.error_name_table; - const zcu = pt.zcu; - const target = &zcu.root_mod.resolved_target.result; - const function_index = try o.builder.addFunction( - try o.builder.fnType(.i1, &.{try o.errorIntType(pt)}, .normal), - name, - toLlvmAddressSpace(.generic, target), + const name = try o.builder.strtabString("__zig_error_name_table"); + // TODO: Address space + const variable_index = try o.builder.addVariable(name, .ptr, .default); + variable_index.setLinkage(.private, &o.builder); + variable_index.setMutability(.constant, &o.builder); + variable_index.setUnnamedAddr(.unnamed_addr, &o.builder); + variable_index.setAlignment( + Type.slice_const_u8_sentinel_0.abiAlignment(o.zcu).toLlvm(), + &o.builder, ); - var attributes: Builder.FunctionAttributes.Wip = .{}; - defer attributes.deinit(&o.builder); - try o.addCommonFnAttributes(&attributes, zcu.root_mod, zcu.root_mod.omit_frame_pointer); + o.error_name_table = variable_index; + return variable_index; + } - function_index.setLinkage(if (o.builder.strip) .private else .internal, &o.builder); - function_index.setCallConv(.fastcc, &o.builder); - function_index.setAttributes(try attributes.finish(&o.builder), &o.builder); - return function_index; + pub fn getErrorsLen(o: *Object) Allocator.Error!Builder.Variable.Index { + const builder = &o.builder; + if (o.errors_len_variable == .none) { + const llvm_err_int_ty = try o.errorIntType(); + const name = try builder.strtabString("__zig_errors_len"); + const variable_index = try builder.addVariable(name, llvm_err_int_ty, .default); + variable_index.setLinkage(.private, builder); + variable_index.setMutability(.constant, builder); + variable_index.setUnnamedAddr(.unnamed_addr, builder); + variable_index.setAlignment(Type.errorAbiAlignment(o.zcu).toLlvm(), builder); + o.errors_len_variable = variable_index; + } + return o.errors_len_variable; } + /// MLUGG TODO: this also needs incremental updates dumbass pub fn getEnumTagNameFunction(o: *Object, pt: Zcu.PerThread, enum_ty: Type) !Builder.Function.Index { const zcu = pt.zcu; const ip = &zcu.intern_pool; @@ -4394,7 +4375,25 @@ pub const Object = struct { return o.lazy_abi_aligns.items[@intFromEnum(index)]; } - pub fn updateIsNamedEnumValueFunction( + pub fn getIsNamedEnumValueFunction(o: *Object, pt: Zcu.PerThread, enum_ty: Type) !Builder.Function.Index { + const zcu = pt.zcu; + const ip = &zcu.intern_pool; + + const gop = try o.named_enum_map.getOrPut(o.gpa, enum_ty.toIntern()); + if (gop.found_existing) return gop.value_ptr.*; + errdefer assert(o.named_enum_map.remove(enum_ty.toIntern())); + const function_index = try o.builder.addFunction( + // Dummy function type; `updateIsNamedEnumValue` will replace it with the correct type. + // TODO: change the builder API so we don't need to do this. + try o.builder.fnType(.void, &.{}, .normal), + try o.builder.strtabStringFmt("__zig_is_named_enum_value_{f}", .{enum_ty.containerTypeName(ip).fmt(ip)}), + toLlvmAddressSpace(.generic, zcu.getTarget()), + ); + gop.value_ptr.* = function_index; + try o.updateIsNamedEnumValueFunction(pt, enum_ty, function_index); + return function_index; + } + fn updateIsNamedEnumValueFunction( o: *Object, pt: Zcu.PerThread, enum_ty: Type, @@ -4445,6 +4444,24 @@ pub const Object = struct { try wip.finish(); } + + pub fn getLibcFunction( + o: *Object, + fn_name: Builder.StrtabString, + param_types: []const Builder.Type, + return_type: Builder.Type, + ) Allocator.Error!Builder.Function.Index { + if (o.builder.getGlobal(fn_name)) |global| return switch (global.ptrConst(&o.builder).kind) { + .alias => |alias| alias.getAliasee(&o.builder).ptrConst(&o.builder).kind.function, + .function => |function| function, + .variable, .replaced => unreachable, + }; + return o.builder.addFunction( + try o.builder.fnType(return_type, param_types, .normal), + fn_name, + toLlvmAddressSpace(.generic, o.zcu.getTarget()), + ); + } }; const CallingConventionInfo = struct { @@ -4796,8 +4813,6 @@ const struct_layout_version = 2; // https://github.com/llvm/llvm-project/issues/56585/ is fixed pub const optional_layout_version = 3; -const lt_errors_fn_name = "__zig_lt_errors_len"; - pub fn initializeLLVMTarget(arch: std.Target.Cpu.Arch) void { switch (arch) { .aarch64, .aarch64_be => { diff --git a/src/codegen/llvm/FuncGen.zig b/src/codegen/llvm/FuncGen.zig @@ -1,7 +1,5 @@ const FuncGen = @This(); -pub const Error = Zcu.CodegenFailError; - object: *Object, nav_index: InternPool.Nav.Index, pt: Zcu.PerThread, @@ -63,7 +61,17 @@ disable_intrinsics: bool, /// Have we seen loads or stores involving `allowzero` pointers? allowzero_access: bool, -fn todo(fg: *FuncGen, comptime format: []const u8, args: anytype) Error { +/// In general, codegen should never emit errors; we cannot report useful source locations for them +/// and they don't really play nicely with incremental compilation. The LLVM backend mostly obeys +/// this rule. Where it does not, it calls `todo` to emit an error, and results in this error set +/// being used for the function +/// +/// Please avoid using this error set in new code. Ideally, every fallible function in this file +/// should have the error set `Allocator.Error`. +const TodoError = Zcu.CodegenFailError; + +/// Avoid introducing new calls to this function---see documentation comment on `TodoError`. +fn todo(fg: *FuncGen, comptime format: []const u8, args: anytype) TodoError { @branchHint(.cold); return fg.pt.zcu.codegenFail( fg.nav_index, @@ -167,7 +175,11 @@ fn resolveValue(self: *FuncGen, val: Value) Allocator.Error!Builder.Constant { } } -pub fn genBody(self: *FuncGen, body: []const Air.Inst.Index, coverage_point: Air.CoveragePoint) Error!void { +fn lowerType(fg: *const FuncGen, ty: Type) Allocator.Error!Builder.Type { + return fg.object.lowerType(fg.pt, ty); +} + +pub fn genBody(self: *FuncGen, body: []const Air.Inst.Index, coverage_point: Air.CoveragePoint) TodoError!void { const o = self.object; const zcu = self.pt.zcu; const ip = &zcu.intern_pool; @@ -443,13 +455,16 @@ pub fn genBody(self: *FuncGen, body: []const Air.Inst.Index, coverage_point: Air // Instructions which may be `noreturn`. .block => res: { - const res = try self.airBlock(inst); - if (self.typeOfIndex(inst).isNoReturn(zcu)) return; + const block = self.air.unwrapBlock(inst); + const res = try self.lowerBlock(inst, null, block.body); + if (block.ty.isNoReturn(zcu)) return; break :res res; }, .dbg_inline_block => res: { - const res = try self.airDbgInlineBlock(inst); - if (self.typeOfIndex(inst).isNoReturn(zcu)) return; + const block = self.air.unwrapDbgBlock(inst); + self.arg_inline_index = 0; + const res = try self.lowerBlock(inst, block.func, block.body); + if (block.ty.isNoReturn(zcu)) return; break :res res; }, .call, .call_always_tail, .call_never_tail, .call_never_inline => |tag| res: { @@ -479,7 +494,7 @@ fn genBodyDebugScope( maybe_inline_func: ?InternPool.Index, body: []const Air.Inst.Index, coverage_point: Air.CoveragePoint, -) Error!void { +) TodoError!void { const o = self.object; if (self.wip.strip) return self.genBody(body, coverage_point); @@ -508,7 +523,7 @@ fn genBodyDebugScope( const file_scope = zcu.navFileScopeIndex(func.owner_nav); const mod = zcu.fileByIndex(file_scope).mod.?; - self.file = try o.getDebugFile(pt, file_scope); + self.file = try o.getDebugFile(file_scope); self.base_line = zcu.navSrcLine(func.owner_nav); const line_number = self.base_line + 1; @@ -562,7 +577,7 @@ const CallAttr = enum { AlwaysInline, }; -fn airCall(self: *FuncGen, inst: Air.Inst.Index, modifier: std.builtin.CallModifier) !Builder.Value { +fn airCall(self: *FuncGen, inst: Air.Inst.Index, modifier: std.builtin.CallModifier) Allocator.Error!Builder.Value { const air_call = self.air.unwrapCall(inst); const args = air_call.args; const o = self.object; @@ -598,7 +613,7 @@ fn airCall(self: *FuncGen, inst: Air.Inst.Index, modifier: std.builtin.CallModif } const ret_ptr = if (!sret) null else blk: { - const llvm_ret_ty = try o.lowerType(pt, return_type); + const llvm_ret_ty = try self.lowerType(return_type); try attributes.addParamAttr(0, .{ .sret = llvm_ret_ty }, &o.builder); const alignment = return_type.abiAlignment(zcu).toLlvm(); @@ -620,7 +635,7 @@ fn airCall(self: *FuncGen, inst: Air.Inst.Index, modifier: std.builtin.CallModif const arg = args[it.zig_index - 1]; const param_ty = self.typeOf(arg); const llvm_arg = try self.resolveInst(arg); - const llvm_param_ty = try o.lowerType(pt, param_ty); + const llvm_param_ty = try self.lowerType(param_ty); if (isByRef(param_ty, zcu)) { const alignment = param_ty.abiAlignment(zcu).toLlvm(); const loaded = try self.wip.load(.normal, llvm_param_ty, llvm_arg, alignment, ""); @@ -649,7 +664,7 @@ fn airCall(self: *FuncGen, inst: Air.Inst.Index, modifier: std.builtin.CallModif const llvm_arg = try self.resolveInst(arg); const alignment = param_ty.abiAlignment(zcu).toLlvm(); - const param_llvm_ty = try o.lowerType(pt, param_ty); + const param_llvm_ty = try self.lowerType(param_ty); const arg_ptr = try self.buildAlloca(param_llvm_ty, alignment); if (isByRef(param_ty, zcu)) { const loaded = try self.wip.load(.normal, param_llvm_ty, llvm_arg, alignment, ""); @@ -719,7 +734,7 @@ fn airCall(self: *FuncGen, inst: Air.Inst.Index, modifier: std.builtin.CallModif llvm_arg = ptr; } - const float_ty = try o.lowerType(pt, aarch64_c_abi.getFloatArrayType(arg_ty, zcu).?); + const float_ty = try self.lowerType(aarch64_c_abi.getFloatArrayType(arg_ty, zcu).?); const array_ty = try o.builder.arrayType(count, float_ty); const loaded = try self.wip.load(.normal, array_ty, llvm_arg, alignment, ""); @@ -760,7 +775,7 @@ fn airCall(self: *FuncGen, inst: Air.Inst.Index, modifier: std.builtin.CallModif .byref => { const param_index = it.zig_index - 1; const param_ty = Type.fromInterned(fn_info.param_types.get(ip)[param_index]); - const param_llvm_ty = try o.lowerType(pt, param_ty); + const param_llvm_ty = try self.lowerType(param_ty); const alignment = param_ty.abiAlignment(zcu).toLlvm(); try o.addByRefParamAttrs(&attributes, it.llvm_index - 1, alignment, it.byval_attr, param_llvm_ty); }, @@ -812,7 +827,7 @@ fn airCall(self: *FuncGen, inst: Air.Inst.Index, modifier: std.builtin.CallModif }, toLlvmCallConvTag(fn_info.cc, target).?, try attributes.finish(&o.builder), - try o.lowerType(pt, zig_fn_ty), + try self.lowerType(zig_fn_ty), llvm_fn, llvm_args.items, "", @@ -826,7 +841,7 @@ fn airCall(self: *FuncGen, inst: Air.Inst.Index, modifier: std.builtin.CallModif return .none; } - const llvm_ret_ty = try o.lowerType(pt, return_type); + const llvm_ret_ty = try self.lowerType(return_type); if (ret_ptr) |rp| { if (isByRef(return_type, zcu)) { return rp; @@ -864,7 +879,7 @@ fn airCall(self: *FuncGen, inst: Air.Inst.Index, modifier: std.builtin.CallModif } } -fn buildSimplePanic(fg: *FuncGen, panic_id: Zcu.SimplePanicId) !void { +fn buildSimplePanic(fg: *FuncGen, panic_id: Zcu.SimplePanicId) Allocator.Error!void { const o = fg.object; const pt = fg.pt; const zcu = pt.zcu; @@ -888,7 +903,7 @@ fn buildSimplePanic(fg: *FuncGen, panic_id: Zcu.SimplePanicId) !void { _ = try fg.wip.@"unreachable"(); } -fn airRet(self: *FuncGen, inst: Air.Inst.Index, safety: bool) !void { +fn airRet(self: *FuncGen, inst: Air.Inst.Index, safety: bool) Allocator.Error!void { const o = self.object; const pt = self.pt; const zcu = pt.zcu; @@ -910,7 +925,7 @@ fn airRet(self: *FuncGen, inst: Air.Inst.Index, safety: bool) !void { // https://github.com/ziglang/zig/issues/15337 break :undef; } - const len = try o.builder.intValue(try o.lowerType(pt, Type.usize), ret_ty.abiSize(zcu)); + const len = try o.builder.intValue(try self.lowerType(.usize), ret_ty.abiSize(zcu)); _ = try self.wip.callMemSet( self.ret_ptr, ptr_ty.ptrAlignment(zcu).toLlvm(), @@ -946,7 +961,7 @@ fn airRet(self: *FuncGen, inst: Air.Inst.Index, safety: bool) !void { // 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. - _ = try self.wip.ret(try o.builder.intValue(try o.errorIntType(pt), 0)); + _ = try self.wip.ret(try o.builder.intValue(try o.errorIntType(), 0)); } else { _ = try self.wip.retVoid(); } @@ -961,7 +976,7 @@ fn airRet(self: *FuncGen, inst: Air.Inst.Index, safety: bool) !void { if (val_is_undef and safety) { const llvm_ret_ty = operand.typeOfWip(&self.wip); const rp = try self.buildAlloca(llvm_ret_ty, alignment); - const len = try o.builder.intValue(try o.lowerType(pt, Type.usize), ret_ty.abiSize(zcu)); + const len = try o.builder.intValue(try self.lowerType(Type.usize), ret_ty.abiSize(zcu)); _ = try self.wip.callMemSet( rp, alignment, @@ -997,7 +1012,7 @@ fn airRet(self: *FuncGen, inst: Air.Inst.Index, safety: bool) !void { return; } -fn airRetLoad(self: *FuncGen, inst: Air.Inst.Index) !void { +fn airRetLoad(self: *FuncGen, inst: Air.Inst.Index) Allocator.Error!void { const o = self.object; const pt = self.pt; const zcu = pt.zcu; @@ -1011,7 +1026,7 @@ fn airRetLoad(self: *FuncGen, inst: Air.Inst.Index) !void { // 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. - _ = try self.wip.ret(try o.builder.intValue(try o.errorIntType(pt), 0)); + _ = try self.wip.ret(try o.builder.intValue(try o.errorIntType(), 0)); } else { _ = try self.wip.retVoid(); } @@ -1028,25 +1043,22 @@ fn airRetLoad(self: *FuncGen, inst: Air.Inst.Index) !void { return; } -fn airCVaArg(self: *FuncGen, inst: Air.Inst.Index) !Builder.Value { - const o = self.object; - const pt = self.pt; +fn airCVaArg(self: *FuncGen, inst: Air.Inst.Index) Allocator.Error!Builder.Value { const ty_op = self.air.instructions.items(.data)[@intFromEnum(inst)].ty_op; const list = try self.resolveInst(ty_op.operand); const arg_ty = ty_op.ty.toType(); - const llvm_arg_ty = try o.lowerType(pt, arg_ty); + const llvm_arg_ty = try self.lowerType(arg_ty); return self.wip.vaArg(list, llvm_arg_ty, ""); } -fn airCVaCopy(self: *FuncGen, inst: Air.Inst.Index) !Builder.Value { - const o = self.object; +fn airCVaCopy(self: *FuncGen, inst: Air.Inst.Index) Allocator.Error!Builder.Value { const pt = self.pt; const zcu = pt.zcu; const ty_op = self.air.instructions.items(.data)[@intFromEnum(inst)].ty_op; const src_list = try self.resolveInst(ty_op.operand); const va_list_ty = ty_op.ty.toType(); - const llvm_va_list_ty = try o.lowerType(pt, va_list_ty); + const llvm_va_list_ty = try self.lowerType(va_list_ty); const result_alignment = va_list_ty.abiAlignment(pt.zcu).toLlvm(); const dest_list = try self.buildAlloca(llvm_va_list_ty, result_alignment); @@ -1058,7 +1070,7 @@ fn airCVaCopy(self: *FuncGen, inst: Air.Inst.Index) !Builder.Value { try self.wip.load(.normal, llvm_va_list_ty, dest_list, result_alignment, ""); } -fn airCVaEnd(self: *FuncGen, inst: Air.Inst.Index) !Builder.Value { +fn airCVaEnd(self: *FuncGen, inst: Air.Inst.Index) Allocator.Error!Builder.Value { const un_op = self.air.instructions.items(.data)[@intFromEnum(inst)].un_op; const src_list = try self.resolveInst(un_op); @@ -1066,12 +1078,11 @@ fn airCVaEnd(self: *FuncGen, inst: Air.Inst.Index) !Builder.Value { return .none; } -fn airCVaStart(self: *FuncGen, inst: Air.Inst.Index) !Builder.Value { - const o = self.object; +fn airCVaStart(self: *FuncGen, inst: Air.Inst.Index) Allocator.Error!Builder.Value { const pt = self.pt; const zcu = pt.zcu; const va_list_ty = self.typeOfIndex(inst); - const llvm_va_list_ty = try o.lowerType(pt, va_list_ty); + const llvm_va_list_ty = try self.lowerType(va_list_ty); const result_alignment = va_list_ty.abiAlignment(pt.zcu).toLlvm(); const dest_list = try self.buildAlloca(llvm_va_list_ty, result_alignment); @@ -1088,7 +1099,7 @@ fn airCmp( inst: Air.Inst.Index, op: math.CompareOperator, fast: Builder.FastMathKind, -) !Builder.Value { +) Allocator.Error!Builder.Value { const bin_op = self.air.instructions.items(.data)[@intFromEnum(inst)].bin_op; const lhs = try self.resolveInst(bin_op.lhs); const rhs = try self.resolveInst(bin_op.rhs); @@ -1097,7 +1108,7 @@ fn airCmp( return self.cmp(fast, op, operand_ty, lhs, rhs); } -fn airCmpVector(self: *FuncGen, inst: Air.Inst.Index, fast: Builder.FastMathKind) !Builder.Value { +fn airCmpVector(self: *FuncGen, inst: Air.Inst.Index, fast: Builder.FastMathKind) Allocator.Error!Builder.Value { const ty_pl = self.air.instructions.items(.data)[@intFromEnum(inst)].ty_pl; const extra = self.air.extraData(Air.VectorCmp, ty_pl.payload).data; @@ -1109,21 +1120,20 @@ fn airCmpVector(self: *FuncGen, inst: Air.Inst.Index, fast: Builder.FastMathKind return self.cmp(fast, cmp_op, vec_ty, lhs, rhs); } -fn airCmpLtErrorsLen(self: *FuncGen, inst: Air.Inst.Index) !Builder.Value { +fn airCmpLtErrorsLen(self: *FuncGen, inst: Air.Inst.Index) Allocator.Error!Builder.Value { const o = self.object; - const pt = self.pt; const un_op = self.air.instructions.items(.data)[@intFromEnum(inst)].un_op; const operand = try self.resolveInst(un_op); - const llvm_fn = try o.getCmpLtErrorsLenFunction(pt); - return self.wip.call( + const errors_len_ptr = try o.getErrorsLen(); + const errors_len_val = try self.wip.load( .normal, - .fastcc, - .none, - llvm_fn.typeOf(&o.builder), - llvm_fn.toValue(&o.builder), - &.{operand}, + try o.errorIntType(), + errors_len_ptr.toValue(&o.builder), + Type.errorAbiAlignment(o.zcu).toLlvm(), "", ); + // Despite the name, this instruction is actually lte. MLUGG TODO RENAME + return self.wip.icmp(.ule, operand, errors_len_val, ""); } fn cmp( @@ -1228,18 +1238,12 @@ fn cmp( return self.wip.icmp(cond, lhs, rhs, ""); } -fn airBlock(self: *FuncGen, inst: Air.Inst.Index) !Builder.Value { - const block = self.air.unwrapBlock(inst); - return self.lowerBlock(inst, null, block.body); -} - fn lowerBlock( self: *FuncGen, inst: Air.Inst.Index, maybe_inline_func: ?InternPool.Index, body: []const Air.Inst.Index, -) !Builder.Value { - const o = self.object; +) TodoError!Builder.Value { const pt = self.pt; const zcu = pt.zcu; const inst_ty = self.typeOfIndex(inst); @@ -1267,7 +1271,7 @@ fn lowerBlock( // Create a phi node only if the block returns a value. if (have_block_result) { - const raw_llvm_ty = try o.lowerType(pt, inst_ty); + const raw_llvm_ty = try self.lowerType(inst_ty); const llvm_ty: Builder.Type = ty: { // If the zig tag type is a function, this represents an actual function body; not // a pointer to it. LLVM IR allows the call instruction to use function bodies instead @@ -1289,7 +1293,7 @@ fn lowerBlock( } } -fn airBr(self: *FuncGen, inst: Air.Inst.Index) !void { +fn airBr(self: *FuncGen, inst: Air.Inst.Index) Allocator.Error!void { const zcu = self.pt.zcu; const branch = self.air.instructions.items(.data)[@intFromEnum(inst)].br; const block = self.blocks.get(branch.block_inst).?; @@ -1306,7 +1310,7 @@ fn airBr(self: *FuncGen, inst: Air.Inst.Index) !void { _ = try self.wip.br(block.parent_bb); } -fn airRepeat(self: *FuncGen, inst: Air.Inst.Index) !void { +fn airRepeat(self: *FuncGen, inst: Air.Inst.Index) Allocator.Error!void { const repeat = self.air.instructions.items(.data)[@intFromEnum(inst)].repeat; const loop_bb = self.loops.get(repeat.loop_inst).?; loop_bb.ptr(&self.wip).incoming += 1; @@ -1318,7 +1322,7 @@ fn lowerSwitchDispatch( switch_inst: Air.Inst.Index, cond_ref: Air.Inst.Ref, dispatch_info: SwitchDispatchInfo, -) !void { +) Allocator.Error!void { const o = self.object; const pt = self.pt; const zcu = pt.zcu; @@ -1384,7 +1388,7 @@ fn lowerSwitchDispatch( const table_index = try self.wip.conv( .unsigned, try self.wip.bin(.@"sub nuw", cond, jmp_table.min.toValue(), ""), - try o.lowerType(pt, .usize), + try self.lowerType(.usize), "", ); const target_ptr_ptr = try self.ptraddScaled( @@ -1409,7 +1413,7 @@ fn lowerSwitchDispatch( // The switch prongs will correspond to our scalar cases. Ranges will // be handled by conditional branches in the `else` prong. - const llvm_usize = try o.lowerType(pt, Type.usize); + const llvm_usize = try self.lowerType(Type.usize); const cond_int = if (cond.typeOfWip(&self.wip).isPointer(&o.builder)) try self.wip.cast(.ptrtoint, cond, llvm_usize, "") else @@ -1501,13 +1505,13 @@ fn lowerSwitchDispatch( } } -fn airSwitchDispatch(self: *FuncGen, inst: Air.Inst.Index) !void { +fn airSwitchDispatch(self: *FuncGen, inst: Air.Inst.Index) Allocator.Error!void { const br = self.air.instructions.items(.data)[@intFromEnum(inst)].br; const dispatch_info = self.switch_dispatch_info.get(br.block_inst).?; return self.lowerSwitchDispatch(br.block_inst, br.operand, dispatch_info); } -fn airCondBr(self: *FuncGen, inst: Air.Inst.Index) !void { +fn airCondBr(self: *FuncGen, inst: Air.Inst.Index) TodoError!void { const cond_br = self.air.unwrapCondBr(inst); const cond = try self.resolveInst(cond_br.condition); const then_body = cond_br.then_body; @@ -1567,7 +1571,7 @@ fn airCondBr(self: *FuncGen, inst: Air.Inst.Index) !void { // No need to reset the insert cursor since this instruction is noreturn. } -fn airTry(self: *FuncGen, inst: Air.Inst.Index, err_cold: bool) !Builder.Value { +fn airTry(self: *FuncGen, inst: Air.Inst.Index, err_cold: bool) TodoError!Builder.Value { const unwrapped_try = self.air.unwrapTry(inst); const err_union = try self.resolveInst(unwrapped_try.error_union); const body = unwrapped_try.else_body; @@ -1576,7 +1580,7 @@ fn airTry(self: *FuncGen, inst: Air.Inst.Index, err_cold: bool) !Builder.Value { return lowerTry(self, err_union, body, err_union_ty, false, .none, is_unused, err_cold); } -fn airTryPtr(self: *FuncGen, inst: Air.Inst.Index, err_cold: bool) !Builder.Value { +fn airTryPtr(self: *FuncGen, inst: Air.Inst.Index, err_cold: bool) TodoError!Builder.Value { const zcu = self.pt.zcu; const unwrapped_try = self.air.unwrapTryPtr(inst); const err_union_ptr = try self.resolveInst(unwrapped_try.error_union_ptr); @@ -1599,13 +1603,13 @@ fn lowerTry( operand_ptr_align: InternPool.Alignment, is_unused: bool, err_cold: bool, -) !Builder.Value { +) TodoError!Builder.Value { const o = fg.object; const pt = fg.pt; const zcu = pt.zcu; const payload_ty = err_union_ty.errorUnionPayload(zcu); const payload_has_bits = payload_ty.hasRuntimeBits(zcu); - const error_type = try o.errorIntType(pt); + const error_type = try o.errorIntType(); const err_set_align: InternPool.Alignment, const payload_align: InternPool.Alignment = if (operand_is_ptr) .{ operand_ptr_align.minStrict(Type.anyerror.abiAlignment(zcu)), @@ -1657,11 +1661,11 @@ fn lowerTry( } else if (isByRef(payload_ty, zcu)) { return fg.loadByRef(payload_ptr, payload_ty, payload_align.toLlvm(), .normal); } else { - return fg.wip.load(.normal, try o.lowerType(pt, payload_ty), payload_ptr, payload_align.toLlvm(), ""); + return fg.wip.load(.normal, try fg.lowerType(payload_ty), payload_ptr, payload_align.toLlvm(), ""); } } -fn airSwitchBr(self: *FuncGen, inst: Air.Inst.Index, is_dispatch_loop: bool) !void { +fn airSwitchBr(self: *FuncGen, inst: Air.Inst.Index, is_dispatch_loop: bool) TodoError!void { const o = self.object; const pt = self.pt; const zcu = pt.zcu; @@ -1909,7 +1913,7 @@ fn switchCaseItemRange(self: *FuncGen, switch_br: Air.UnwrappedSwitch) ?[2]Value return .{ min.?, max.? }; } -fn airLoop(self: *FuncGen, inst: Air.Inst.Index) !void { +fn airLoop(self: *FuncGen, inst: Air.Inst.Index) TodoError!void { const block = self.air.unwrapBlock(inst); const body = block.body; const loop_block = try self.wip.block(1, "Loop"); // `airRepeat` will increment incoming each time @@ -1922,21 +1926,21 @@ fn airLoop(self: *FuncGen, inst: Air.Inst.Index) !void { try self.genBodyDebugScope(null, body, .none); } -fn airArrayToSlice(self: *FuncGen, inst: Air.Inst.Index) !Builder.Value { +fn airArrayToSlice(self: *FuncGen, inst: Air.Inst.Index) Allocator.Error!Builder.Value { const o = self.object; const pt = self.pt; const zcu = pt.zcu; const ty_op = self.air.instructions.items(.data)[@intFromEnum(inst)].ty_op; const operand_ty = self.typeOf(ty_op.operand); const array_ty = operand_ty.childType(zcu); - const llvm_usize = try o.lowerType(pt, Type.usize); + const llvm_usize = try self.lowerType(.usize); const len = try o.builder.intValue(llvm_usize, array_ty.arrayLen(zcu)); - const slice_llvm_ty = try o.lowerType(pt, self.typeOfIndex(inst)); + const slice_llvm_ty = try self.lowerType(self.typeOfIndex(inst)); const operand = try self.resolveInst(ty_op.operand); return self.wip.buildAggregate(slice_llvm_ty, &.{ operand, len }, ""); } -fn airFloatFromInt(self: *FuncGen, inst: Air.Inst.Index) !Builder.Value { +fn airFloatFromInt(self: *FuncGen, inst: Air.Inst.Index) TodoError!Builder.Value { const o = self.object; const pt = self.pt; const zcu = pt.zcu; @@ -1949,7 +1953,7 @@ fn airFloatFromInt(self: *FuncGen, inst: Air.Inst.Index) !Builder.Value { const dest_ty = self.typeOfIndex(inst); const dest_scalar_ty = dest_ty.scalarType(zcu); - const dest_llvm_ty = try o.lowerType(pt, dest_ty); + const dest_llvm_ty = try self.lowerType(dest_ty); const target = zcu.getTarget(); if (intrinsicsAllowed(dest_scalar_ty, target)) return self.wip.conv( @@ -1987,7 +1991,7 @@ fn airFloatFromInt(self: *FuncGen, inst: Air.Inst.Index) !Builder.Value { extended = try self.wip.cast(.bitcast, extended, param_type, ""); } - const libc_fn = try self.getLibcFunction(fn_name, &.{param_type}, dest_llvm_ty); + const libc_fn = try o.getLibcFunction(fn_name, &.{param_type}, dest_llvm_ty); return self.wip.call( .normal, .ccc, @@ -2003,7 +2007,7 @@ fn airIntFromFloat( self: *FuncGen, inst: Air.Inst.Index, fast: Builder.FastMathKind, -) !Builder.Value { +) TodoError!Builder.Value { _ = fast; const o = self.object; @@ -2018,7 +2022,7 @@ fn airIntFromFloat( const dest_ty = self.typeOfIndex(inst); const dest_scalar_ty = dest_ty.scalarType(zcu); - const dest_llvm_ty = try o.lowerType(pt, dest_ty); + const dest_llvm_ty = try self.lowerType(dest_ty); if (intrinsicsAllowed(operand_scalar_ty, target)) { // TODO set fast math flag @@ -2052,8 +2056,8 @@ fn airIntFromFloat( compiler_rt_dest_abbrev, }); - const operand_llvm_ty = try o.lowerType(pt, operand_ty); - const libc_fn = try self.getLibcFunction(fn_name, &.{operand_llvm_ty}, libc_ret_ty); + const operand_llvm_ty = try self.lowerType(operand_ty); + const libc_fn = try o.getLibcFunction(fn_name, &.{operand_llvm_ty}, libc_ret_ty); var result = try self.wip.call( .normal, .ccc, @@ -2078,7 +2082,7 @@ fn sliceOrArrayLenInBytes(fg: *FuncGen, ptr: Builder.Value, ty: Type) Allocator. const o = fg.object; const pt = fg.pt; const zcu = pt.zcu; - const llvm_usize = try o.lowerType(pt, Type.usize); + const llvm_usize = try fg.lowerType(.usize); switch (ty.ptrSize(zcu)) { .slice => { const len = try fg.wip.extractValue(ptr, &.{1}, ""); @@ -2098,20 +2102,20 @@ fn sliceOrArrayLenInBytes(fg: *FuncGen, ptr: Builder.Value, ty: Type) Allocator. } } -fn airSliceField(self: *FuncGen, inst: Air.Inst.Index, index: u32) !Builder.Value { +fn airSliceField(self: *FuncGen, inst: Air.Inst.Index, index: u32) Allocator.Error!Builder.Value { const ty_op = self.air.instructions.items(.data)[@intFromEnum(inst)].ty_op; const operand = try self.resolveInst(ty_op.operand); return self.wip.extractValue(operand, &.{index}, ""); } -fn airPtrSliceFieldPtr(self: *FuncGen, inst: Air.Inst.Index, index: u1) !Builder.Value { +fn airPtrSliceFieldPtr(self: *FuncGen, inst: Air.Inst.Index, index: u1) Allocator.Error!Builder.Value { const zcu = self.pt.zcu; const ty_op = self.air.instructions.items(.data)[@intFromEnum(inst)].ty_op; const slice_ptr = try self.resolveInst(ty_op.operand); return self.ptraddConst(slice_ptr, index * Type.usize.abiSize(zcu)); } -fn airSliceElemVal(self: *FuncGen, inst: Air.Inst.Index) !Builder.Value { +fn airSliceElemVal(self: *FuncGen, inst: Air.Inst.Index) Allocator.Error!Builder.Value { const pt = self.pt; const zcu = pt.zcu; const bin_op = self.air.instructions.items(.data)[@intFromEnum(inst)].bin_op; @@ -2133,7 +2137,7 @@ fn airSliceElemVal(self: *FuncGen, inst: Air.Inst.Index) !Builder.Value { } } -fn airSliceElemPtr(self: *FuncGen, inst: Air.Inst.Index) !Builder.Value { +fn airSliceElemPtr(self: *FuncGen, inst: Air.Inst.Index) Allocator.Error!Builder.Value { const pt = self.pt; const zcu = pt.zcu; const ty_pl = self.air.instructions.items(.data)[@intFromEnum(inst)].ty_pl; @@ -2146,7 +2150,7 @@ fn airSliceElemPtr(self: *FuncGen, inst: Air.Inst.Index) !Builder.Value { return self.ptraddScaled(base_ptr, index, slice_ty.childType(zcu).abiSize(zcu)); } -fn airArrayElemVal(self: *FuncGen, inst: Air.Inst.Index) !Builder.Value { +fn airArrayElemVal(self: *FuncGen, inst: Air.Inst.Index) Allocator.Error!Builder.Value { const pt = self.pt; const zcu = pt.zcu; @@ -2169,7 +2173,7 @@ fn airArrayElemVal(self: *FuncGen, inst: Air.Inst.Index) !Builder.Value { return self.wip.extractElement(array_llvm_val, rhs, ""); } -fn airPtrElemVal(self: *FuncGen, inst: Air.Inst.Index) !Builder.Value { +fn airPtrElemVal(self: *FuncGen, inst: Air.Inst.Index) Allocator.Error!Builder.Value { const pt = self.pt; const zcu = pt.zcu; const bin_op = self.air.instructions.items(.data)[@intFromEnum(inst)].bin_op; @@ -2189,7 +2193,7 @@ fn airPtrElemVal(self: *FuncGen, inst: Air.Inst.Index) !Builder.Value { return self.load(ptr, ptr_ty); } -fn airPtrElemPtr(self: *FuncGen, inst: Air.Inst.Index) !Builder.Value { +fn airPtrElemPtr(self: *FuncGen, inst: Air.Inst.Index) Allocator.Error!Builder.Value { const pt = self.pt; const zcu = pt.zcu; const ty_pl = self.air.instructions.items(.data)[@intFromEnum(inst)].ty_pl; @@ -2207,7 +2211,7 @@ fn airPtrElemPtr(self: *FuncGen, inst: Air.Inst.Index) !Builder.Value { return self.ptraddScaled(base_ptr, rhs, elem_ty.abiSize(zcu)); } -fn airStructFieldPtr(self: *FuncGen, inst: Air.Inst.Index) !Builder.Value { +fn airStructFieldPtr(self: *FuncGen, inst: Air.Inst.Index) Allocator.Error!Builder.Value { const ty_pl = self.air.instructions.items(.data)[@intFromEnum(inst)].ty_pl; const struct_field = self.air.extraData(Air.StructField, ty_pl.payload).data; const struct_ptr = try self.resolveInst(struct_field.struct_operand); @@ -2219,14 +2223,14 @@ fn airStructFieldPtrIndex( self: *FuncGen, inst: Air.Inst.Index, field_index: u32, -) !Builder.Value { +) Allocator.Error!Builder.Value { const ty_op = self.air.instructions.items(.data)[@intFromEnum(inst)].ty_op; const struct_ptr = try self.resolveInst(ty_op.operand); const struct_ptr_ty = self.typeOf(ty_op.operand); return self.fieldPtr(struct_ptr, struct_ptr_ty, field_index); } -fn airStructFieldVal(self: *FuncGen, inst: Air.Inst.Index) !Builder.Value { +fn airStructFieldVal(self: *FuncGen, inst: Air.Inst.Index) Allocator.Error!Builder.Value { const o = self.object; const pt = self.pt; const zcu = pt.zcu; @@ -2267,7 +2271,7 @@ fn airStructFieldVal(self: *FuncGen, inst: Air.Inst.Index) !Builder.Value { }, .float => { // bitcast int->float - return self.wip.cast(.bitcast, field_int_val, try o.lowerType(pt, field_ty), ""); + return self.wip.cast(.bitcast, field_int_val, try self.lowerType(field_ty), ""); }, } } @@ -2292,7 +2296,7 @@ fn airStructFieldVal(self: *FuncGen, inst: Air.Inst.Index) !Builder.Value { } } -fn airFieldParentPtr(self: *FuncGen, inst: Air.Inst.Index) !Builder.Value { +fn airFieldParentPtr(self: *FuncGen, inst: Air.Inst.Index) Allocator.Error!Builder.Value { const o = self.object; const pt = self.pt; const zcu = pt.zcu; @@ -2305,8 +2309,8 @@ fn airFieldParentPtr(self: *FuncGen, inst: Air.Inst.Index) !Builder.Value { const field_offset = parent_ty.structFieldOffset(extra.field_index, zcu); if (field_offset == 0) return field_ptr; - const res_ty = try o.lowerType(pt, ty_pl.ty.toType()); - const llvm_usize = try o.lowerType(pt, Type.usize); + const res_ty = try self.lowerType(ty_pl.ty.toType()); + const llvm_usize = try self.lowerType(Type.usize); const field_ptr_int = try self.wip.cast(.ptrtoint, field_ptr, llvm_usize, ""); const base_ptr_int = try self.wip.bin( @@ -2318,19 +2322,19 @@ fn airFieldParentPtr(self: *FuncGen, inst: Air.Inst.Index) !Builder.Value { return self.wip.cast(.inttoptr, base_ptr_int, res_ty, ""); } -fn airNot(self: *FuncGen, inst: Air.Inst.Index) !Builder.Value { +fn airNot(self: *FuncGen, inst: Air.Inst.Index) Allocator.Error!Builder.Value { const ty_op = self.air.instructions.items(.data)[@intFromEnum(inst)].ty_op; const operand = try self.resolveInst(ty_op.operand); return self.wip.not(operand, ""); } -fn airUnreach(self: *FuncGen, inst: Air.Inst.Index) !void { +fn airUnreach(self: *FuncGen, inst: Air.Inst.Index) Allocator.Error!void { _ = inst; _ = try self.wip.@"unreachable"(); } -fn airDbgStmt(self: *FuncGen, inst: Air.Inst.Index) !Builder.Value { +fn airDbgStmt(self: *FuncGen, inst: Air.Inst.Index) Allocator.Error!Builder.Value { const dbg_stmt = self.air.instructions.items(.data)[@intFromEnum(inst)].dbg_stmt; self.prev_dbg_line = @intCast(self.base_line + dbg_stmt.line + 1); self.prev_dbg_column = @intCast(dbg_stmt.column + 1); @@ -2345,19 +2349,13 @@ fn airDbgStmt(self: *FuncGen, inst: Air.Inst.Index) !Builder.Value { return .none; } -fn airDbgEmptyStmt(self: *FuncGen, inst: Air.Inst.Index) !Builder.Value { +fn airDbgEmptyStmt(self: *FuncGen, inst: Air.Inst.Index) Allocator.Error!Builder.Value { _ = self; _ = inst; return .none; } -fn airDbgInlineBlock(self: *FuncGen, inst: Air.Inst.Index) !Builder.Value { - const block = self.air.unwrapDbgBlock(inst); - self.arg_inline_index = 0; - return self.lowerBlock(inst, block.func, block.body); -} - -fn airDbgVarPtr(self: *FuncGen, inst: Air.Inst.Index) !Builder.Value { +fn airDbgVarPtr(self: *FuncGen, inst: Air.Inst.Index) Allocator.Error!Builder.Value { const o = self.object; const pt = self.pt; const zcu = pt.zcu; @@ -2390,7 +2388,7 @@ fn airDbgVarPtr(self: *FuncGen, inst: Air.Inst.Index) !Builder.Value { return .none; } -fn airDbgVarVal(self: *FuncGen, inst: Air.Inst.Index, is_arg: bool) !Builder.Value { +fn airDbgVarVal(self: *FuncGen, inst: Air.Inst.Index, is_arg: bool) Allocator.Error!Builder.Value { const o = self.object; const pt = self.pt; const pl_op = self.air.instructions.items(.data)[@intFromEnum(inst)].pl_op; @@ -2468,7 +2466,7 @@ fn airDbgVarVal(self: *FuncGen, inst: Air.Inst.Index, is_arg: bool) !Builder.Val return .none; } -fn airAssembly(self: *FuncGen, inst: Air.Inst.Index) !Builder.Value { +fn airAssembly(self: *FuncGen, inst: Air.Inst.Index) TodoError!Builder.Value { // Eventually, the Zig compiler needs to be reworked to have inline // assembly go through the same parsing code regardless of backend, and // have LLVM-flavored inline assembly be *output* from that assembler. @@ -2530,7 +2528,7 @@ fn airAssembly(self: *FuncGen, inst: Air.Inst.Index) !Builder.Value { const output_inst = try self.resolveInst(output.operand); const output_ty = self.typeOf(output.operand); assert(output_ty.zigTypeTag(zcu) == .pointer); - const elem_llvm_ty = try o.lowerType(pt, output_ty.childType(zcu)); + const elem_llvm_ty = try self.lowerType(output_ty.childType(zcu)); switch (constraint[0]) { '=' => {}, @@ -2568,7 +2566,7 @@ fn airAssembly(self: *FuncGen, inst: Air.Inst.Index) !Builder.Value { llvm_ret_indirect[output.index] = false; const ret_ty = self.typeOfIndex(inst); - llvm_ret_types[llvm_ret_i] = try o.lowerType(pt, ret_ty); + llvm_ret_types[llvm_ret_i] = try self.lowerType(ret_ty); llvm_ret_i += 1; } @@ -2607,7 +2605,7 @@ fn airAssembly(self: *FuncGen, inst: Air.Inst.Index) !Builder.Value { llvm_param_types[llvm_param_i] = arg_llvm_value.typeOfWip(&self.wip); } else { const alignment = arg_ty.abiAlignment(zcu).toLlvm(); - const arg_llvm_ty = try o.lowerType(pt, arg_ty); + const arg_llvm_ty = try self.lowerType(arg_ty); const load_inst = try self.wip.load(.normal, arg_llvm_ty, arg_llvm_value, alignment, ""); llvm_param_values[llvm_param_i] = load_inst; @@ -2648,7 +2646,7 @@ fn airAssembly(self: *FuncGen, inst: Air.Inst.Index) !Builder.Value { llvm_param_attrs[llvm_param_i] = if (constraint[0] == '*') blk: { if (!is_by_ref) self.maybeMarkAllowZeroAccess(arg_ty.ptrInfo(zcu)); - break :blk try o.lowerType(pt, if (is_by_ref) arg_ty else arg_ty.childType(zcu)); + break :blk try self.lowerType(if (is_by_ref) arg_ty else arg_ty.childType(zcu)); } else .none; llvm_param_i += 1; @@ -2662,7 +2660,7 @@ fn airAssembly(self: *FuncGen, inst: Air.Inst.Index) !Builder.Value { if (constraint[0] != '+') continue; const rw_ty = self.typeOf(output.operand); - const llvm_elem_ty = try o.lowerType(pt, rw_ty.childType(zcu)); + const llvm_elem_ty = try self.lowerType(rw_ty.childType(zcu)); if (llvm_ret_indirect[output.index]) { llvm_param_values[llvm_param_i] = llvm_rw_vals[output.index]; llvm_param_types[llvm_param_i] = llvm_rw_vals[output.index].typeOfWip(&self.wip); @@ -2855,7 +2853,7 @@ fn airIsNonNull( inst: Air.Inst.Index, operand_is_ptr: bool, cond: Builder.IntegerCondition, -) !Builder.Value { +) Allocator.Error!Builder.Value { const o = self.object; const pt = self.pt; const zcu = pt.zcu; @@ -2863,7 +2861,7 @@ fn airIsNonNull( const operand = try self.resolveInst(un_op); const operand_ty = self.typeOf(un_op); const optional_ty = if (operand_is_ptr) operand_ty.childType(zcu) else operand_ty; - const optional_llvm_ty = try o.lowerType(pt, optional_ty); + const optional_llvm_ty = try self.lowerType(optional_ty); const payload_ty = optional_ty.optionalChild(zcu); const access_kind: Builder.MemoryAccessKind = @@ -2905,7 +2903,7 @@ fn airIsErr( inst: Air.Inst.Index, cond: Builder.IntegerCondition, operand_is_ptr: bool, -) !Builder.Value { +) Allocator.Error!Builder.Value { const o = self.object; const pt = self.pt; const zcu = pt.zcu; @@ -2914,7 +2912,7 @@ fn airIsErr( const operand_ty = self.typeOf(un_op); const err_union_ty = if (operand_is_ptr) operand_ty.childType(zcu) else operand_ty; const payload_ty = err_union_ty.errorUnionPayload(zcu); - const error_type = try o.errorIntType(pt); + const error_type = try o.errorIntType(); const zero = try o.builder.intValue(error_type, 0); const access_kind: Builder.MemoryAccessKind = @@ -2933,7 +2931,7 @@ fn airIsErr( if (!payload_ty.hasRuntimeBits(zcu)) { const loaded = if (operand_is_ptr) - try self.wip.load(access_kind, try o.lowerType(pt, err_union_ty), operand, operand_ty.ptrAlignment(zcu).toLlvm(), "") + try self.wip.load(access_kind, try self.lowerType(err_union_ty), operand, operand_ty.ptrAlignment(zcu).toLlvm(), "") else operand; return self.wip.icmp(cond, loaded, zero, ""); @@ -2957,7 +2955,7 @@ fn airOptionalPayloadPtr(self: *FuncGen, inst: Air.Inst.Index) Allocator.Error!B return operand; } -fn airOptionalPayloadPtrSet(self: *FuncGen, inst: Air.Inst.Index) !Builder.Value { +fn airOptionalPayloadPtrSet(self: *FuncGen, inst: Air.Inst.Index) Allocator.Error!Builder.Value { comptime assert(optional_layout_version == 3); const o = self.object; @@ -3002,7 +3000,7 @@ fn airOptionalPayloadPtrSet(self: *FuncGen, inst: Air.Inst.Index) !Builder.Value return operand; // payload is at offset 0 } -fn airOptionalPayload(self: *FuncGen, inst: Air.Inst.Index) !Builder.Value { +fn airOptionalPayload(self: *FuncGen, inst: Air.Inst.Index) Allocator.Error!Builder.Value { const pt = self.pt; const zcu = pt.zcu; const ty_op = self.air.instructions.items(.data)[@intFromEnum(inst)].ty_op; @@ -3019,8 +3017,7 @@ fn airOptionalPayload(self: *FuncGen, inst: Air.Inst.Index) !Builder.Value { return self.optPayloadHandle(operand, optional_ty, false); } -fn airErrUnionPayload(self: *FuncGen, inst: Air.Inst.Index, operand_is_ptr: bool) !Builder.Value { - const o = self.object; +fn airErrUnionPayload(self: *FuncGen, inst: Air.Inst.Index, operand_is_ptr: bool) Allocator.Error!Builder.Value { const pt = self.pt; const zcu = pt.zcu; const ty_op = self.air.instructions.items(.data)[@intFromEnum(inst)].ty_op; @@ -3042,7 +3039,7 @@ fn airErrUnionPayload(self: *FuncGen, inst: Air.Inst.Index, operand_is_ptr: bool if (isByRef(payload_ty, zcu)) { return self.loadByRef(payload_ptr, payload_ty, payload_alignment, .normal); } else { - const payload_llvm_ty = try o.lowerType(pt, payload_ty); + const payload_llvm_ty = try self.lowerType(payload_ty); return self.wip.load(.normal, payload_llvm_ty, payload_ptr, payload_alignment, ""); } } @@ -3051,14 +3048,14 @@ fn airErrUnionErr( self: *FuncGen, inst: Air.Inst.Index, operand_is_ptr: bool, -) !Builder.Value { +) Allocator.Error!Builder.Value { const o = self.object; const pt = self.pt; const zcu = pt.zcu; const ty_op = self.air.instructions.items(.data)[@intFromEnum(inst)].ty_op; const operand = try self.resolveInst(ty_op.operand); const operand_ty = self.typeOf(ty_op.operand); - const error_type = try o.errorIntType(pt); + const error_type = try o.errorIntType(); const err_union_ty = if (operand_is_ptr) operand_ty.childType(zcu) else operand_ty; if (err_union_ty.errorUnionSet(zcu).errorSetIsEmpty(zcu)) { if (operand_is_ptr) { @@ -3094,7 +3091,7 @@ fn airErrUnionErr( return self.wip.load(access_kind, error_type, err_field_ptr, err_align.toLlvm(), ""); } -fn airErrUnionPayloadPtrSet(self: *FuncGen, inst: Air.Inst.Index) !Builder.Value { +fn airErrUnionPayloadPtrSet(self: *FuncGen, inst: Air.Inst.Index) Allocator.Error!Builder.Value { const o = self.object; const pt = self.pt; const zcu = pt.zcu; @@ -3105,7 +3102,7 @@ fn airErrUnionPayloadPtrSet(self: *FuncGen, inst: Air.Inst.Index) !Builder.Value const err_union_ptr_align = err_union_ptr_ty.ptrAlignment(zcu); const payload_ty = err_union_ty.errorUnionPayload(zcu); - const non_error_val = try o.builder.intValue(try o.errorIntType(pt), 0); + const non_error_val = try o.builder.intValue(try o.errorIntType(), 0); const access_kind: Builder.MemoryAccessKind = if (err_union_ptr_ty.isVolatilePtr(zcu)) .@"volatile" else .normal; @@ -3124,18 +3121,18 @@ fn airErrUnionPayloadPtrSet(self: *FuncGen, inst: Air.Inst.Index) !Builder.Value return self.ptraddConst(operand, codegen.errUnionPayloadOffset(payload_ty, zcu)); } -fn airErrReturnTrace(self: *FuncGen, _: Air.Inst.Index) !Builder.Value { +fn airErrReturnTrace(self: *FuncGen, _: Air.Inst.Index) Allocator.Error!Builder.Value { assert(self.err_ret_trace != .none); return self.err_ret_trace; } -fn airSetErrReturnTrace(self: *FuncGen, inst: Air.Inst.Index) !Builder.Value { +fn airSetErrReturnTrace(self: *FuncGen, inst: Air.Inst.Index) Allocator.Error!Builder.Value { const un_op = self.air.instructions.items(.data)[@intFromEnum(inst)].un_op; self.err_ret_trace = try self.resolveInst(un_op); return .none; } -fn airSaveErrReturnTraceIndex(self: *FuncGen, inst: Air.Inst.Index) !Builder.Value { +fn airSaveErrReturnTraceIndex(self: *FuncGen, inst: Air.Inst.Index) Allocator.Error!Builder.Value { const pt = self.pt; const zcu = pt.zcu; @@ -3184,7 +3181,7 @@ fn isNextRet( return false; } -fn airWrapOptional(self: *FuncGen, body_tail: []const Air.Inst.Index) !Builder.Value { +fn airWrapOptional(self: *FuncGen, body_tail: []const Air.Inst.Index) Allocator.Error!Builder.Value { const o = self.object; const pt = self.pt; const zcu = pt.zcu; @@ -3198,7 +3195,7 @@ fn airWrapOptional(self: *FuncGen, body_tail: []const Air.Inst.Index) !Builder.V const optional_ty = self.typeOfIndex(inst); if (optional_ty.optionalReprIsPayload(zcu)) return operand; assert(isByRef(optional_ty, zcu)); // optionals with runtime bits are by-ref unless `optionalReprIsPayload` - const llvm_optional_ty = try o.lowerType(pt, optional_ty); + const llvm_optional_ty = try self.lowerType(optional_ty); const optional_ptr = if (self.isNextRet(body_tail)) self.ret_ptr else brk: { @@ -3216,7 +3213,7 @@ fn airWrapOptional(self: *FuncGen, body_tail: []const Air.Inst.Index) !Builder.V return optional_ptr; } -fn airWrapErrUnionPayload(self: *FuncGen, body_tail: []const Air.Inst.Index) !Builder.Value { +fn airWrapErrUnionPayload(self: *FuncGen, body_tail: []const Air.Inst.Index) Allocator.Error!Builder.Value { const o = self.object; const pt = self.pt; const zcu = pt.zcu; @@ -3227,8 +3224,8 @@ fn airWrapErrUnionPayload(self: *FuncGen, body_tail: []const Air.Inst.Index) !Bu const payload_ty = self.typeOf(ty_op.operand); assert(payload_ty.hasRuntimeBits(zcu)); assert(isByRef(err_un_ty, zcu)); // error unions with runtime bits are always by-ref - const ok_err_code = try o.builder.intValue(try o.errorIntType(pt), 0); - const err_un_llvm_ty = try o.lowerType(pt, err_un_ty); + const ok_err_code = try o.builder.intValue(try o.errorIntType(), 0); + const err_un_llvm_ty = try self.lowerType(err_un_ty); const result_ptr = if (self.isNextRet(body_tail)) self.ret_ptr @@ -3247,8 +3244,7 @@ fn airWrapErrUnionPayload(self: *FuncGen, body_tail: []const Air.Inst.Index) !Bu return result_ptr; } -fn airWrapErrUnionErr(self: *FuncGen, body_tail: []const Air.Inst.Index) !Builder.Value { - const o = self.object; +fn airWrapErrUnionErr(self: *FuncGen, body_tail: []const Air.Inst.Index) Allocator.Error!Builder.Value { const pt = self.pt; const zcu = pt.zcu; const inst = body_tail[0]; @@ -3258,7 +3254,7 @@ fn airWrapErrUnionErr(self: *FuncGen, body_tail: []const Air.Inst.Index) !Builde const operand = try self.resolveInst(ty_op.operand); if (!payload_ty.hasRuntimeBits(zcu)) return operand; assert(isByRef(err_un_ty, zcu)); // error unions with runtime bits are always by-ref - const err_un_llvm_ty = try o.lowerType(pt, err_un_ty); + const err_un_llvm_ty = try self.lowerType(err_un_ty); const result_ptr = if (self.isNextRet(body_tail)) self.ret_ptr @@ -3279,29 +3275,27 @@ fn airWrapErrUnionErr(self: *FuncGen, body_tail: []const Air.Inst.Index) !Builde return result_ptr; } -fn airWasmMemorySize(self: *FuncGen, inst: Air.Inst.Index) !Builder.Value { +fn airWasmMemorySize(self: *FuncGen, inst: Air.Inst.Index) Allocator.Error!Builder.Value { const o = self.object; - const pt = self.pt; const pl_op = self.air.instructions.items(.data)[@intFromEnum(inst)].pl_op; const index = pl_op.payload; - const llvm_usize = try o.lowerType(pt, Type.usize); + const llvm_usize = try self.lowerType(Type.usize); return self.wip.callIntrinsic(.normal, .none, .@"wasm.memory.size", &.{llvm_usize}, &.{ try o.builder.intValue(.i32, index), }, ""); } -fn airWasmMemoryGrow(self: *FuncGen, inst: Air.Inst.Index) !Builder.Value { +fn airWasmMemoryGrow(self: *FuncGen, inst: Air.Inst.Index) Allocator.Error!Builder.Value { const o = self.object; - const pt = self.pt; const pl_op = self.air.instructions.items(.data)[@intFromEnum(inst)].pl_op; const index = pl_op.payload; - const llvm_isize = try o.lowerType(pt, Type.isize); + const llvm_isize = try self.lowerType(Type.isize); return self.wip.callIntrinsic(.normal, .none, .@"wasm.memory.grow", &.{llvm_isize}, &.{ try o.builder.intValue(.i32, index), try self.resolveInst(pl_op.operand), }, ""); } -fn airRuntimeNavPtr(fg: *FuncGen, inst: Air.Inst.Index) !Builder.Value { +fn airRuntimeNavPtr(fg: *FuncGen, inst: Air.Inst.Index) Allocator.Error!Builder.Value { const o = fg.object; const pt = fg.pt; const ty_nav = fg.air.instructions.items(.data)[@intFromEnum(inst)].ty_nav; @@ -3309,8 +3303,7 @@ fn airRuntimeNavPtr(fg: *FuncGen, inst: Air.Inst.Index) !Builder.Value { return llvm_ptr_const.toValue(); } -fn airMin(self: *FuncGen, inst: Air.Inst.Index) !Builder.Value { - const o = self.object; +fn airMin(self: *FuncGen, inst: Air.Inst.Index) Allocator.Error!Builder.Value { const pt = self.pt; const zcu = pt.zcu; const bin_op = self.air.instructions.items(.data)[@intFromEnum(inst)].bin_op; @@ -3324,14 +3317,13 @@ fn airMin(self: *FuncGen, inst: Air.Inst.Index) !Builder.Value { .normal, .none, if (scalar_ty.isSignedInt(zcu)) .smin else .umin, - &.{try o.lowerType(pt, inst_ty)}, + &.{try self.lowerType(inst_ty)}, &.{ lhs, rhs }, "", ); } -fn airMax(self: *FuncGen, inst: Air.Inst.Index) !Builder.Value { - const o = self.object; +fn airMax(self: *FuncGen, inst: Air.Inst.Index) Allocator.Error!Builder.Value { const pt = self.pt; const zcu = pt.zcu; const bin_op = self.air.instructions.items(.data)[@intFromEnum(inst)].bin_op; @@ -3345,24 +3337,22 @@ fn airMax(self: *FuncGen, inst: Air.Inst.Index) !Builder.Value { .normal, .none, if (scalar_ty.isSignedInt(zcu)) .smax else .umax, - &.{try o.lowerType(pt, inst_ty)}, + &.{try self.lowerType(inst_ty)}, &.{ lhs, rhs }, "", ); } -fn airSlice(self: *FuncGen, inst: Air.Inst.Index) !Builder.Value { - const o = self.object; - const pt = self.pt; +fn airSlice(self: *FuncGen, inst: Air.Inst.Index) Allocator.Error!Builder.Value { const ty_pl = self.air.instructions.items(.data)[@intFromEnum(inst)].ty_pl; const bin_op = self.air.extraData(Air.Bin, ty_pl.payload).data; const ptr = try self.resolveInst(bin_op.lhs); const len = try self.resolveInst(bin_op.rhs); const inst_ty = self.typeOfIndex(inst); - return self.wip.buildAggregate(try o.lowerType(pt, inst_ty), &.{ ptr, len }, ""); + return self.wip.buildAggregate(try self.lowerType(inst_ty), &.{ ptr, len }, ""); } -fn airAdd(self: *FuncGen, inst: Air.Inst.Index, fast: Builder.FastMathKind) !Builder.Value { +fn airAdd(self: *FuncGen, inst: Air.Inst.Index, fast: Builder.FastMathKind) Allocator.Error!Builder.Value { const zcu = self.pt.zcu; const bin_op = self.air.instructions.items(.data)[@intFromEnum(inst)].bin_op; const lhs = try self.resolveInst(bin_op.lhs); @@ -3379,7 +3369,7 @@ fn airSafeArithmetic( inst: Air.Inst.Index, signed_intrinsic: Builder.Intrinsic, unsigned_intrinsic: Builder.Intrinsic, -) !Builder.Value { +) Allocator.Error!Builder.Value { const o = fg.object; const pt = fg.pt; const zcu = pt.zcu; @@ -3391,7 +3381,7 @@ fn airSafeArithmetic( const scalar_ty = inst_ty.scalarType(zcu); const intrinsic = if (scalar_ty.isSignedInt(zcu)) signed_intrinsic else unsigned_intrinsic; - const llvm_inst_ty = try o.lowerType(pt, inst_ty); + const llvm_inst_ty = try fg.lowerType(inst_ty); const results = try fg.wip.callIntrinsic(.normal, .none, intrinsic, &.{llvm_inst_ty}, &.{ lhs, rhs }, ""); @@ -3420,7 +3410,7 @@ fn airSafeArithmetic( return fg.wip.extractValue(results, &.{0}, ""); } -fn airAddWrap(self: *FuncGen, inst: Air.Inst.Index) !Builder.Value { +fn airAddWrap(self: *FuncGen, inst: Air.Inst.Index) Allocator.Error!Builder.Value { const bin_op = self.air.instructions.items(.data)[@intFromEnum(inst)].bin_op; const lhs = try self.resolveInst(bin_op.lhs); const rhs = try self.resolveInst(bin_op.rhs); @@ -3428,8 +3418,7 @@ fn airAddWrap(self: *FuncGen, inst: Air.Inst.Index) !Builder.Value { return self.wip.bin(.add, lhs, rhs, ""); } -fn airAddSat(self: *FuncGen, inst: Air.Inst.Index) !Builder.Value { - const o = self.object; +fn airAddSat(self: *FuncGen, inst: Air.Inst.Index) Allocator.Error!Builder.Value { const pt = self.pt; const zcu = pt.zcu; const bin_op = self.air.instructions.items(.data)[@intFromEnum(inst)].bin_op; @@ -3442,13 +3431,13 @@ fn airAddSat(self: *FuncGen, inst: Air.Inst.Index) !Builder.Value { .normal, .none, if (scalar_ty.isSignedInt(zcu)) .@"sadd.sat" else .@"uadd.sat", - &.{try o.lowerType(pt, inst_ty)}, + &.{try self.lowerType(inst_ty)}, &.{ lhs, rhs }, "", ); } -fn airSub(self: *FuncGen, inst: Air.Inst.Index, fast: Builder.FastMathKind) !Builder.Value { +fn airSub(self: *FuncGen, inst: Air.Inst.Index, fast: Builder.FastMathKind) Allocator.Error!Builder.Value { const zcu = self.pt.zcu; const bin_op = self.air.instructions.items(.data)[@intFromEnum(inst)].bin_op; const lhs = try self.resolveInst(bin_op.lhs); @@ -3460,7 +3449,7 @@ fn airSub(self: *FuncGen, inst: Air.Inst.Index, fast: Builder.FastMathKind) !Bui return self.wip.bin(if (scalar_ty.isSignedInt(zcu)) .@"sub nsw" else .@"sub nuw", lhs, rhs, ""); } -fn airSubWrap(self: *FuncGen, inst: Air.Inst.Index) !Builder.Value { +fn airSubWrap(self: *FuncGen, inst: Air.Inst.Index) Allocator.Error!Builder.Value { const bin_op = self.air.instructions.items(.data)[@intFromEnum(inst)].bin_op; const lhs = try self.resolveInst(bin_op.lhs); const rhs = try self.resolveInst(bin_op.rhs); @@ -3468,8 +3457,7 @@ fn airSubWrap(self: *FuncGen, inst: Air.Inst.Index) !Builder.Value { return self.wip.bin(.sub, lhs, rhs, ""); } -fn airSubSat(self: *FuncGen, inst: Air.Inst.Index) !Builder.Value { - const o = self.object; +fn airSubSat(self: *FuncGen, inst: Air.Inst.Index) Allocator.Error!Builder.Value { const pt = self.pt; const zcu = pt.zcu; const bin_op = self.air.instructions.items(.data)[@intFromEnum(inst)].bin_op; @@ -3482,13 +3470,13 @@ fn airSubSat(self: *FuncGen, inst: Air.Inst.Index) !Builder.Value { .normal, .none, if (scalar_ty.isSignedInt(zcu)) .@"ssub.sat" else .@"usub.sat", - &.{try o.lowerType(pt, inst_ty)}, + &.{try self.lowerType(inst_ty)}, &.{ lhs, rhs }, "", ); } -fn airMul(self: *FuncGen, inst: Air.Inst.Index, fast: Builder.FastMathKind) !Builder.Value { +fn airMul(self: *FuncGen, inst: Air.Inst.Index, fast: Builder.FastMathKind) Allocator.Error!Builder.Value { const zcu = self.pt.zcu; const bin_op = self.air.instructions.items(.data)[@intFromEnum(inst)].bin_op; const lhs = try self.resolveInst(bin_op.lhs); @@ -3500,7 +3488,7 @@ fn airMul(self: *FuncGen, inst: Air.Inst.Index, fast: Builder.FastMathKind) !Bui return self.wip.bin(if (scalar_ty.isSignedInt(zcu)) .@"mul nsw" else .@"mul nuw", lhs, rhs, ""); } -fn airMulWrap(self: *FuncGen, inst: Air.Inst.Index) !Builder.Value { +fn airMulWrap(self: *FuncGen, inst: Air.Inst.Index) Allocator.Error!Builder.Value { const bin_op = self.air.instructions.items(.data)[@intFromEnum(inst)].bin_op; const lhs = try self.resolveInst(bin_op.lhs); const rhs = try self.resolveInst(bin_op.rhs); @@ -3508,8 +3496,7 @@ fn airMulWrap(self: *FuncGen, inst: Air.Inst.Index) !Builder.Value { return self.wip.bin(.mul, lhs, rhs, ""); } -fn airMulSat(self: *FuncGen, inst: Air.Inst.Index) !Builder.Value { - const o = self.object; +fn airMulSat(self: *FuncGen, inst: Air.Inst.Index) Allocator.Error!Builder.Value { const pt = self.pt; const zcu = pt.zcu; const bin_op = self.air.instructions.items(.data)[@intFromEnum(inst)].bin_op; @@ -3522,13 +3509,13 @@ fn airMulSat(self: *FuncGen, inst: Air.Inst.Index) !Builder.Value { .normal, .none, if (scalar_ty.isSignedInt(zcu)) .@"smul.fix.sat" else .@"umul.fix.sat", - &.{try o.lowerType(pt, inst_ty)}, + &.{try self.lowerType(inst_ty)}, &.{ lhs, rhs, .@"0" }, "", ); } -fn airDivFloat(self: *FuncGen, inst: Air.Inst.Index, fast: Builder.FastMathKind) !Builder.Value { +fn airDivFloat(self: *FuncGen, inst: Air.Inst.Index, fast: Builder.FastMathKind) Allocator.Error!Builder.Value { const bin_op = self.air.instructions.items(.data)[@intFromEnum(inst)].bin_op; const lhs = try self.resolveInst(bin_op.lhs); const rhs = try self.resolveInst(bin_op.rhs); @@ -3537,7 +3524,7 @@ fn airDivFloat(self: *FuncGen, inst: Air.Inst.Index, fast: Builder.FastMathKind) return self.buildFloatOp(.div, fast, inst_ty, 2, .{ lhs, rhs }); } -fn airDivTrunc(self: *FuncGen, inst: Air.Inst.Index, fast: Builder.FastMathKind) !Builder.Value { +fn airDivTrunc(self: *FuncGen, inst: Air.Inst.Index, fast: Builder.FastMathKind) Allocator.Error!Builder.Value { const zcu = self.pt.zcu; const bin_op = self.air.instructions.items(.data)[@intFromEnum(inst)].bin_op; const lhs = try self.resolveInst(bin_op.lhs); @@ -3552,7 +3539,7 @@ fn airDivTrunc(self: *FuncGen, inst: Air.Inst.Index, fast: Builder.FastMathKind) return self.wip.bin(if (scalar_ty.isSignedInt(zcu)) .sdiv else .udiv, lhs, rhs, ""); } -fn airDivFloor(self: *FuncGen, inst: Air.Inst.Index, fast: Builder.FastMathKind) !Builder.Value { +fn airDivFloor(self: *FuncGen, inst: Air.Inst.Index, fast: Builder.FastMathKind) Allocator.Error!Builder.Value { const o = self.object; const pt = self.pt; const zcu = pt.zcu; @@ -3567,7 +3554,7 @@ fn airDivFloor(self: *FuncGen, inst: Air.Inst.Index, fast: Builder.FastMathKind) return self.buildFloatOp(.floor, fast, inst_ty, 1, .{result}); } if (scalar_ty.isSignedInt(zcu)) { - const inst_llvm_ty = try o.lowerType(pt, inst_ty); + const inst_llvm_ty = try self.lowerType(inst_ty); const ExpectedContents = [std.math.big.int.calcTwosCompLimbCount(256)]std.math.big.Limb; var stack align(@max( @@ -3603,7 +3590,7 @@ fn airDivFloor(self: *FuncGen, inst: Air.Inst.Index, fast: Builder.FastMathKind) return self.wip.bin(.udiv, lhs, rhs, ""); } -fn airDivExact(self: *FuncGen, inst: Air.Inst.Index, fast: Builder.FastMathKind) !Builder.Value { +fn airDivExact(self: *FuncGen, inst: Air.Inst.Index, fast: Builder.FastMathKind) Allocator.Error!Builder.Value { const zcu = self.pt.zcu; const bin_op = self.air.instructions.items(.data)[@intFromEnum(inst)].bin_op; const lhs = try self.resolveInst(bin_op.lhs); @@ -3620,7 +3607,7 @@ fn airDivExact(self: *FuncGen, inst: Air.Inst.Index, fast: Builder.FastMathKind) ); } -fn airRem(self: *FuncGen, inst: Air.Inst.Index, fast: Builder.FastMathKind) !Builder.Value { +fn airRem(self: *FuncGen, inst: Air.Inst.Index, fast: Builder.FastMathKind) Allocator.Error!Builder.Value { const zcu = self.pt.zcu; const bin_op = self.air.instructions.items(.data)[@intFromEnum(inst)].bin_op; const lhs = try self.resolveInst(bin_op.lhs); @@ -3636,7 +3623,7 @@ fn airRem(self: *FuncGen, inst: Air.Inst.Index, fast: Builder.FastMathKind) !Bui .urem, lhs, rhs, ""); } -fn airMod(self: *FuncGen, inst: Air.Inst.Index, fast: Builder.FastMathKind) !Builder.Value { +fn airMod(self: *FuncGen, inst: Air.Inst.Index, fast: Builder.FastMathKind) Allocator.Error!Builder.Value { const o = self.object; const pt = self.pt; const zcu = pt.zcu; @@ -3644,7 +3631,7 @@ fn airMod(self: *FuncGen, inst: Air.Inst.Index, fast: Builder.FastMathKind) !Bui 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 o.lowerType(pt, inst_ty); + const inst_llvm_ty = try self.lowerType(inst_ty); const scalar_ty = inst_ty.scalarType(zcu); if (scalar_ty.isRuntimeFloat()) { @@ -3690,7 +3677,7 @@ fn airMod(self: *FuncGen, inst: Air.Inst.Index, fast: Builder.FastMathKind) !Bui return self.wip.bin(.urem, lhs, rhs, ""); } -fn airPtrAdd(self: *FuncGen, inst: Air.Inst.Index) !Builder.Value { +fn airPtrAdd(self: *FuncGen, inst: Air.Inst.Index) Allocator.Error!Builder.Value { const zcu = self.pt.zcu; const ty_pl = self.air.instructions.items(.data)[@intFromEnum(inst)].ty_pl; const bin_op = self.air.extraData(Air.Bin, ty_pl.payload).data; @@ -3705,14 +3692,14 @@ fn airPtrAdd(self: *FuncGen, inst: Air.Inst.Index) !Builder.Value { return self.ptraddScaled(ptr, index, elem_ty.abiSize(zcu)); } -fn airPtrSub(self: *FuncGen, inst: Air.Inst.Index) !Builder.Value { +fn airPtrSub(self: *FuncGen, inst: Air.Inst.Index) Allocator.Error!Builder.Value { const o = self.object; const pt = self.pt; const zcu = pt.zcu; const ty_pl = self.air.instructions.items(.data)[@intFromEnum(inst)].ty_pl; const bin_op = self.air.extraData(Air.Bin, ty_pl.payload).data; const ptr_or_slice = try self.resolveInst(bin_op.lhs); - const llvm_usize_ty = try o.lowerType(pt, .usize); + const llvm_usize_ty = try self.lowerType(.usize); const ptr_ty = self.typeOf(bin_op.lhs); const elem_ty = ptr_ty.indexableElem(zcu); const ptr = switch (ptr_ty.ptrSize(zcu)) { @@ -3722,7 +3709,7 @@ fn airPtrSub(self: *FuncGen, inst: Air.Inst.Index) !Builder.Value { const scale_val = try o.builder.intValue(llvm_usize_ty, -@as(i65, elem_ty.abiSize(zcu))); const positive_index = try self.resolveInst(bin_op.rhs); const negative_offset = try self.wip.bin(.@"mul nsw", positive_index, scale_val, ""); - return self.ptradd(ptr, negative_offset); + return self.wip.gep(.inbounds, .i8, ptr, &.{negative_offset}, ""); } fn airOverflow( @@ -3730,8 +3717,7 @@ fn airOverflow( inst: Air.Inst.Index, signed_intrinsic: Builder.Intrinsic, unsigned_intrinsic: Builder.Intrinsic, -) !Builder.Value { - const o = self.object; +) Allocator.Error!Builder.Value { const pt = self.pt; const zcu = pt.zcu; const ty_pl = self.air.instructions.items(.data)[@intFromEnum(inst)].ty_pl; @@ -3746,8 +3732,8 @@ fn airOverflow( assert(isByRef(inst_ty, zcu)); // auto structs are by-ref const intrinsic = if (scalar_ty.isSignedInt(zcu)) signed_intrinsic else unsigned_intrinsic; - const llvm_inst_ty = try o.lowerType(pt, inst_ty); - const llvm_lhs_ty = try o.lowerType(pt, lhs_ty); + const llvm_inst_ty = try self.lowerType(inst_ty); + const llvm_lhs_ty = try self.lowerType(lhs_ty); const results = try self.wip.callIntrinsic(.normal, .none, intrinsic, &.{llvm_lhs_ty}, &.{ lhs, rhs }, ""); @@ -3778,7 +3764,7 @@ fn buildElementwiseCall( args_vectors: []const Builder.Value, result_vector: Builder.Value, vector_len: usize, -) !Builder.Value { +) Allocator.Error!Builder.Value { const o = self.object; assert(args_vectors.len <= 3); @@ -3805,25 +3791,6 @@ fn buildElementwiseCall( return result; } -fn getLibcFunction( - self: *FuncGen, - fn_name: Builder.StrtabString, - param_types: []const Builder.Type, - return_type: Builder.Type, -) Allocator.Error!Builder.Function.Index { - const o = self.object; - if (o.builder.getGlobal(fn_name)) |global| return switch (global.ptrConst(&o.builder).kind) { - .alias => |alias| alias.getAliasee(&o.builder).ptrConst(&o.builder).kind.function, - .function => |function| function, - .variable, .replaced => unreachable, - }; - return o.builder.addFunction( - try o.builder.fnType(return_type, param_types, .normal), - fn_name, - toLlvmAddressSpace(.generic, self.pt.zcu.getTarget()), - ); -} - /// Creates a floating point comparison by lowering to the appropriate /// hardware instruction or softfloat routine for the target fn buildFloatCmp( @@ -3832,13 +3799,13 @@ fn buildFloatCmp( pred: math.CompareOperator, ty: Type, params: [2]Builder.Value, -) !Builder.Value { +) Allocator.Error!Builder.Value { const o = self.object; const pt = self.pt; const zcu = pt.zcu; const target = zcu.getTarget(); const scalar_ty = ty.scalarType(zcu); - const scalar_llvm_ty = try o.lowerType(pt, scalar_ty); + const scalar_llvm_ty = try self.lowerType(scalar_ty); if (intrinsicsAllowed(scalar_ty, target)) { const cond: Builder.FloatCondition = switch (pred) { @@ -3864,7 +3831,7 @@ fn buildFloatCmp( }; const fn_name = try o.builder.strtabStringFmt("__{s}{s}f2", .{ fn_base_name, compiler_rt_float_abbrev }); - const libc_fn = try self.getLibcFunction(fn_name, &.{ scalar_llvm_ty, scalar_llvm_ty }, .i32); + const libc_fn = try o.getLibcFunction(fn_name, &.{ scalar_llvm_ty, scalar_llvm_ty }, .i32); const int_cond: Builder.IntegerCondition = switch (pred) { .eq => .eq, @@ -3939,13 +3906,13 @@ fn buildFloatOp( ty: Type, comptime params_len: usize, params: [params_len]Builder.Value, -) !Builder.Value { +) Allocator.Error!Builder.Value { const o = self.object; const pt = self.pt; const zcu = pt.zcu; const target = zcu.getTarget(); const scalar_ty = ty.scalarType(zcu); - const llvm_ty = try o.lowerType(pt, ty); + const llvm_ty = try self.lowerType(ty); if (op != .tan and intrinsicsAllowed(scalar_ty, target)) switch (op) { // Some operations are dedicated LLVM instructions, not available as intrinsics @@ -4048,7 +4015,7 @@ fn buildFloatOp( }; const scalar_llvm_ty = llvm_ty.scalarType(&o.builder); - const libc_fn = try self.getLibcFunction( + const libc_fn = try o.getLibcFunction( fn_name, ([1]Builder.Type{scalar_llvm_ty} ** 3)[0..params.len], scalar_llvm_ty, @@ -4069,7 +4036,7 @@ fn buildFloatOp( ); } -fn airMulAdd(self: *FuncGen, inst: Air.Inst.Index) !Builder.Value { +fn airMulAdd(self: *FuncGen, inst: Air.Inst.Index) Allocator.Error!Builder.Value { const pl_op = self.air.instructions.items(.data)[@intFromEnum(inst)].pl_op; const extra = self.air.extraData(Air.Bin, pl_op.payload).data; @@ -4081,8 +4048,7 @@ fn airMulAdd(self: *FuncGen, inst: Air.Inst.Index) !Builder.Value { return self.buildFloatOp(.fma, .normal, ty, 3, .{ mulend1, mulend2, addend }); } -fn airShlWithOverflow(self: *FuncGen, inst: Air.Inst.Index) !Builder.Value { - const o = self.object; +fn airShlWithOverflow(self: *FuncGen, inst: Air.Inst.Index) Allocator.Error!Builder.Value { const pt = self.pt; const zcu = pt.zcu; const ty_pl = self.air.instructions.items(.data)[@intFromEnum(inst)].ty_pl; @@ -4092,15 +4058,19 @@ fn airShlWithOverflow(self: *FuncGen, inst: Air.Inst.Index) !Builder.Value { const rhs = try self.resolveInst(extra.rhs); const lhs_ty = self.typeOf(extra.lhs); - if (lhs_ty.isVector(zcu) and !self.typeOf(extra.rhs).isVector(zcu)) - return self.todo("implement vector shifts with scalar rhs", .{}); + if (lhs_ty.isVector(zcu) and !self.typeOf(extra.rhs).isVector(zcu)) { + // `Sema` does not currently emit this pattern---instead it is specific to `Air.Legalize` + // features which we do not use. Therefore this branch is currently impossible. + unreachable; + } + const lhs_scalar_ty = lhs_ty.scalarType(zcu); const dest_ty = self.typeOfIndex(inst); assert(isByRef(dest_ty, zcu)); // auto structs are by-ref - const llvm_dest_ty = try o.lowerType(pt, dest_ty); + const llvm_dest_ty = try self.lowerType(dest_ty); - const casted_rhs = try self.wip.conv(.unsigned, rhs, try o.lowerType(pt, lhs_ty), ""); + const casted_rhs = try self.wip.conv(.unsigned, rhs, try self.lowerType(lhs_ty), ""); const result = try self.wip.bin(.shl, lhs, casted_rhs, ""); const reconstructed = try self.wip.bin(if (lhs_scalar_ty.isSignedInt(zcu)) @@ -4128,29 +4098,28 @@ fn airShlWithOverflow(self: *FuncGen, inst: Air.Inst.Index) !Builder.Value { return alloca_inst; } -fn airAnd(self: *FuncGen, inst: Air.Inst.Index) !Builder.Value { +fn airAnd(self: *FuncGen, inst: Air.Inst.Index) Allocator.Error!Builder.Value { const bin_op = self.air.instructions.items(.data)[@intFromEnum(inst)].bin_op; const lhs = try self.resolveInst(bin_op.lhs); const rhs = try self.resolveInst(bin_op.rhs); return self.wip.bin(.@"and", lhs, rhs, ""); } -fn airOr(self: *FuncGen, inst: Air.Inst.Index) !Builder.Value { +fn airOr(self: *FuncGen, inst: Air.Inst.Index) Allocator.Error!Builder.Value { const bin_op = self.air.instructions.items(.data)[@intFromEnum(inst)].bin_op; const lhs = try self.resolveInst(bin_op.lhs); const rhs = try self.resolveInst(bin_op.rhs); return self.wip.bin(.@"or", lhs, rhs, ""); } -fn airXor(self: *FuncGen, inst: Air.Inst.Index) !Builder.Value { +fn airXor(self: *FuncGen, inst: Air.Inst.Index) Allocator.Error!Builder.Value { const bin_op = self.air.instructions.items(.data)[@intFromEnum(inst)].bin_op; const lhs = try self.resolveInst(bin_op.lhs); const rhs = try self.resolveInst(bin_op.rhs); return self.wip.bin(.xor, lhs, rhs, ""); } -fn airShlExact(self: *FuncGen, inst: Air.Inst.Index) !Builder.Value { - const o = self.object; +fn airShlExact(self: *FuncGen, inst: Air.Inst.Index) Allocator.Error!Builder.Value { const pt = self.pt; const zcu = pt.zcu; const bin_op = self.air.instructions.items(.data)[@intFromEnum(inst)].bin_op; @@ -4159,19 +4128,21 @@ fn airShlExact(self: *FuncGen, inst: Air.Inst.Index) !Builder.Value { const rhs = try self.resolveInst(bin_op.rhs); const lhs_ty = self.typeOf(bin_op.lhs); - if (lhs_ty.isVector(zcu) and !self.typeOf(bin_op.rhs).isVector(zcu)) - return self.todo("implement vector shifts with scalar rhs", .{}); + if (lhs_ty.isVector(zcu) and !self.typeOf(bin_op.rhs).isVector(zcu)) { + // `Sema` does not currently emit this pattern---instead it is specific to `Air.Legalize` + // features which we do not use. Therefore this branch is currently impossible. + unreachable; + } const lhs_scalar_ty = lhs_ty.scalarType(zcu); - const casted_rhs = try self.wip.conv(.unsigned, rhs, try o.lowerType(pt, lhs_ty), ""); + const casted_rhs = try self.wip.conv(.unsigned, rhs, try self.lowerType(lhs_ty), ""); return self.wip.bin(if (lhs_scalar_ty.isSignedInt(zcu)) .@"shl nsw" else .@"shl nuw", lhs, casted_rhs, ""); } -fn airShl(self: *FuncGen, inst: Air.Inst.Index) !Builder.Value { - const o = self.object; +fn airShl(self: *FuncGen, inst: Air.Inst.Index) Allocator.Error!Builder.Value { const pt = self.pt; const zcu = pt.zcu; const bin_op = self.air.instructions.items(.data)[@intFromEnum(inst)].bin_op; @@ -4180,14 +4151,16 @@ fn airShl(self: *FuncGen, inst: Air.Inst.Index) !Builder.Value { const rhs = try self.resolveInst(bin_op.rhs); const lhs_ty = self.typeOf(bin_op.lhs); - if (lhs_ty.isVector(zcu) and !self.typeOf(bin_op.rhs).isVector(zcu)) - return self.todo("implement vector shifts with scalar rhs", .{}); - - const casted_rhs = try self.wip.conv(.unsigned, rhs, try o.lowerType(pt, lhs_ty), ""); + if (lhs_ty.isVector(zcu) and !self.typeOf(bin_op.rhs).isVector(zcu)) { + // `Sema` does not currently emit this pattern---instead it is specific to `Air.Legalize` + // features which we do not use. Therefore this branch is currently impossible. + unreachable; + } + const casted_rhs = try self.wip.conv(.unsigned, rhs, try self.lowerType(lhs_ty), ""); return self.wip.bin(.shl, lhs, casted_rhs, ""); } -fn airShlSat(self: *FuncGen, inst: Air.Inst.Index) !Builder.Value { +fn airShlSat(self: *FuncGen, inst: Air.Inst.Index) Allocator.Error!Builder.Value { const o = self.object; const pt = self.pt; const zcu = pt.zcu; @@ -4198,15 +4171,18 @@ fn airShlSat(self: *FuncGen, inst: Air.Inst.Index) !Builder.Value { const lhs_ty = self.typeOf(bin_op.lhs); const lhs_info = lhs_ty.intInfo(zcu); - const llvm_lhs_ty = try o.lowerType(pt, lhs_ty); + const llvm_lhs_ty = try self.lowerType(lhs_ty); const llvm_lhs_scalar_ty = llvm_lhs_ty.scalarType(&o.builder); const rhs_ty = self.typeOf(bin_op.rhs); - if (lhs_ty.isVector(zcu) and !rhs_ty.isVector(zcu)) - return self.todo("implement vector shifts with scalar rhs", .{}); + if (lhs_ty.isVector(zcu) and !rhs_ty.isVector(zcu)) { + // `Sema` does not currently emit this pattern---instead it is specific to `Air.Legalize` + // features which we do not use. Therefore this branch is currently impossible. + unreachable; + } const rhs_info = rhs_ty.intInfo(zcu); assert(rhs_info.signedness == .unsigned); - const llvm_rhs_ty = try o.lowerType(pt, rhs_ty); + const llvm_rhs_ty = try self.lowerType(rhs_ty); const llvm_rhs_scalar_ty = llvm_rhs_ty.scalarType(&o.builder); const result = try self.wip.callIntrinsic( @@ -4267,8 +4243,7 @@ fn airShlSat(self: *FuncGen, inst: Air.Inst.Index) !Builder.Value { return self.wip.select(.normal, in_range, result, lhs_sat, ""); } -fn airShr(self: *FuncGen, inst: Air.Inst.Index, is_exact: bool) !Builder.Value { - const o = self.object; +fn airShr(self: *FuncGen, inst: Air.Inst.Index, is_exact: bool) Allocator.Error!Builder.Value { const pt = self.pt; const zcu = pt.zcu; const bin_op = self.air.instructions.items(.data)[@intFromEnum(inst)].bin_op; @@ -4277,11 +4252,14 @@ fn airShr(self: *FuncGen, inst: Air.Inst.Index, is_exact: bool) !Builder.Value { const rhs = try self.resolveInst(bin_op.rhs); const lhs_ty = self.typeOf(bin_op.lhs); - if (lhs_ty.isVector(zcu) and !self.typeOf(bin_op.rhs).isVector(zcu)) - return self.todo("implement vector shifts with scalar rhs", .{}); + if (lhs_ty.isVector(zcu) and !self.typeOf(bin_op.rhs).isVector(zcu)) { + // `Sema` does not currently emit this pattern---instead it is specific to `Air.Legalize` + // features which we do not use. Therefore this branch is currently impossible. + unreachable; + } const lhs_scalar_ty = lhs_ty.scalarType(zcu); - const casted_rhs = try self.wip.conv(.unsigned, rhs, try o.lowerType(pt, lhs_ty), ""); + const casted_rhs = try self.wip.conv(.unsigned, rhs, try self.lowerType(lhs_ty), ""); const is_signed_int = lhs_scalar_ty.isSignedInt(zcu); return self.wip.bin(if (is_exact) @@ -4289,7 +4267,7 @@ fn airShr(self: *FuncGen, inst: Air.Inst.Index, is_exact: bool) !Builder.Value { else if (is_signed_int) .ashr else .lshr, lhs, casted_rhs, ""); } -fn airAbs(self: *FuncGen, inst: Air.Inst.Index) !Builder.Value { +fn airAbs(self: *FuncGen, inst: Air.Inst.Index) Allocator.Error!Builder.Value { const o = self.object; const pt = self.pt; const zcu = pt.zcu; @@ -4303,7 +4281,7 @@ fn airAbs(self: *FuncGen, inst: Air.Inst.Index) !Builder.Value { .normal, .none, .abs, - &.{try o.lowerType(pt, operand_ty)}, + &.{try self.lowerType(operand_ty)}, &.{ operand, try o.builder.intValue(.i1, 0) }, "", ), @@ -4312,13 +4290,13 @@ fn airAbs(self: *FuncGen, inst: Air.Inst.Index) !Builder.Value { } } -fn airIntCast(fg: *FuncGen, inst: Air.Inst.Index, safety: bool) !Builder.Value { +fn airIntCast(fg: *FuncGen, inst: Air.Inst.Index, safety: bool) Allocator.Error!Builder.Value { const o = fg.object; const pt = fg.pt; const zcu = pt.zcu; const ty_op = fg.air.instructions.items(.data)[@intFromEnum(inst)].ty_op; const dest_ty = fg.typeOfIndex(inst); - const dest_llvm_ty = try o.lowerType(pt, dest_ty); + const dest_llvm_ty = try fg.lowerType(dest_ty); const operand = try fg.resolveInst(ty_op.operand); const operand_ty = fg.typeOf(ty_op.operand); const operand_info = operand_ty.intInfo(zcu); @@ -4346,8 +4324,8 @@ fn airIntCast(fg: *FuncGen, inst: Air.Inst.Index, safety: bool) !Builder.Value { if (!have_min_check and !have_max_check) break :bounds_check; - const operand_llvm_ty = try o.lowerType(pt, operand_ty); - const operand_scalar_llvm_ty = try o.lowerType(pt, operand_scalar); + const operand_llvm_ty = try fg.lowerType(operand_ty); + const operand_scalar_llvm_ty = try fg.lowerType(operand_scalar); const is_vector = operand_ty.zigTypeTag(zcu) == .vector; assert(is_vector == (dest_ty.zigTypeTag(zcu) == .vector)); @@ -4401,7 +4379,7 @@ fn airIntCast(fg: *FuncGen, inst: Air.Inst.Index, safety: bool) !Builder.Value { }, operand, dest_llvm_ty, ""); if (safety and dest_is_enum and !dest_ty.isNonexhaustiveEnum(zcu)) { - const llvm_fn = try fg.getIsNamedEnumValueFunction(dest_ty); + const llvm_fn = try o.getIsNamedEnumValueFunction(pt, dest_ty); const is_valid_enum_val = try fg.wip.call( .normal, .fastcc, @@ -4422,16 +4400,14 @@ fn airIntCast(fg: *FuncGen, inst: Air.Inst.Index, safety: bool) !Builder.Value { return result; } -fn airTrunc(self: *FuncGen, inst: Air.Inst.Index) !Builder.Value { - const o = self.object; - const pt = self.pt; +fn airTrunc(self: *FuncGen, inst: Air.Inst.Index) Allocator.Error!Builder.Value { const ty_op = self.air.instructions.items(.data)[@intFromEnum(inst)].ty_op; const operand = try self.resolveInst(ty_op.operand); - const dest_llvm_ty = try o.lowerType(pt, self.typeOfIndex(inst)); + const dest_llvm_ty = try self.lowerType(self.typeOfIndex(inst)); return self.wip.cast(.trunc, operand, dest_llvm_ty, ""); } -fn airFptrunc(self: *FuncGen, inst: Air.Inst.Index) !Builder.Value { +fn airFptrunc(self: *FuncGen, inst: Air.Inst.Index) Allocator.Error!Builder.Value { const o = self.object; const pt = self.pt; const zcu = pt.zcu; @@ -4442,10 +4418,10 @@ fn airFptrunc(self: *FuncGen, inst: Air.Inst.Index) !Builder.Value { const target = zcu.getTarget(); if (intrinsicsAllowed(dest_ty, target) and intrinsicsAllowed(operand_ty, target)) { - return self.wip.cast(.fptrunc, operand, try o.lowerType(pt, dest_ty), ""); + return self.wip.cast(.fptrunc, operand, try self.lowerType(dest_ty), ""); } else { - const operand_llvm_ty = try o.lowerType(pt, operand_ty); - const dest_llvm_ty = try o.lowerType(pt, dest_ty); + const operand_llvm_ty = try self.lowerType(operand_ty); + const dest_llvm_ty = try self.lowerType(dest_ty); const dest_bits = dest_ty.floatBits(target); const src_bits = operand_ty.floatBits(target); @@ -4453,7 +4429,7 @@ fn airFptrunc(self: *FuncGen, inst: Air.Inst.Index) !Builder.Value { compilerRtFloatAbbrev(src_bits), compilerRtFloatAbbrev(dest_bits), }); - const libc_fn = try self.getLibcFunction(fn_name, &.{operand_llvm_ty}, dest_llvm_ty); + const libc_fn = try o.getLibcFunction(fn_name, &.{operand_llvm_ty}, dest_llvm_ty); return self.wip.call( .normal, .ccc, @@ -4466,7 +4442,7 @@ fn airFptrunc(self: *FuncGen, inst: Air.Inst.Index) !Builder.Value { } } -fn airFpext(self: *FuncGen, inst: Air.Inst.Index) !Builder.Value { +fn airFpext(self: *FuncGen, inst: Air.Inst.Index) Allocator.Error!Builder.Value { const o = self.object; const pt = self.pt; const zcu = pt.zcu; @@ -4477,10 +4453,10 @@ fn airFpext(self: *FuncGen, inst: Air.Inst.Index) !Builder.Value { const target = zcu.getTarget(); if (intrinsicsAllowed(dest_ty, target) and intrinsicsAllowed(operand_ty, target)) { - return self.wip.cast(.fpext, operand, try o.lowerType(pt, dest_ty), ""); + return self.wip.cast(.fpext, operand, try self.lowerType(dest_ty), ""); } else { - const operand_llvm_ty = try o.lowerType(pt, operand_ty); - const dest_llvm_ty = try o.lowerType(pt, dest_ty); + const operand_llvm_ty = try self.lowerType(operand_ty); + const dest_llvm_ty = try self.lowerType(dest_ty); const dest_bits = dest_ty.scalarType(zcu).floatBits(target); const src_bits = operand_ty.scalarType(zcu).floatBits(target); @@ -4488,7 +4464,7 @@ fn airFpext(self: *FuncGen, inst: Air.Inst.Index) !Builder.Value { compilerRtFloatAbbrev(src_bits), compilerRtFloatAbbrev(dest_bits), }); - const libc_fn = try self.getLibcFunction(fn_name, &.{operand_llvm_ty}, dest_llvm_ty); + const libc_fn = try o.getLibcFunction(fn_name, &.{operand_llvm_ty}, dest_llvm_ty); if (dest_ty.isVector(zcu)) return self.buildElementwiseCall( libc_fn, &.{operand}, @@ -4507,7 +4483,7 @@ fn airFpext(self: *FuncGen, inst: Air.Inst.Index) !Builder.Value { } } -fn airBitCast(self: *FuncGen, inst: Air.Inst.Index) !Builder.Value { +fn airBitCast(self: *FuncGen, inst: Air.Inst.Index) Allocator.Error!Builder.Value { const ty_op = self.air.instructions.items(.data)[@intFromEnum(inst)].ty_op; const operand_ty = self.typeOf(ty_op.operand); const inst_ty = self.typeOfIndex(inst); @@ -4515,13 +4491,13 @@ fn airBitCast(self: *FuncGen, inst: Air.Inst.Index) !Builder.Value { return self.bitCast(operand, operand_ty, inst_ty); } -fn bitCast(self: *FuncGen, operand: Builder.Value, operand_ty: Type, inst_ty: Type) !Builder.Value { +fn bitCast(self: *FuncGen, operand: Builder.Value, operand_ty: Type, inst_ty: Type) Allocator.Error!Builder.Value { const o = self.object; const pt = self.pt; const zcu = pt.zcu; const operand_is_ref = isByRef(operand_ty, zcu); const result_is_ref = isByRef(inst_ty, zcu); - const llvm_dest_ty = try o.lowerType(pt, inst_ty); + const llvm_dest_ty = try self.lowerType(inst_ty); if (operand_is_ref and result_is_ref) { // They are both pointers, so just return the same opaque pointer :) @@ -4544,11 +4520,8 @@ fn bitCast(self: *FuncGen, operand: Builder.Value, operand_ty: Type, inst_ty: Ty } if (operand_ty.zigTypeTag(zcu) == .vector and inst_ty.zigTypeTag(zcu) == .array) { - const elem_ty = inst_ty.childType(zcu); - assert(elem_ty.toIntern() == operand_scalar_ty.toIntern()); - if (!result_is_ref) { - return self.todo("implement bitcast vector to non-ref array", .{}); - } + const elem_ty = operand_scalar_ty; + assert(result_is_ref); // arrays are always by-ref provided they have runtime bits const alignment = inst_ty.abiAlignment(zcu).toLlvm(); const array_ptr = try self.buildAlloca(llvm_dest_ty, alignment); const bitcast_ok = elem_ty.bitSize(zcu) == elem_ty.abiSize(zcu) * 8; @@ -4569,9 +4542,8 @@ fn bitCast(self: *FuncGen, operand: Builder.Value, operand_ty: Type, inst_ty: Ty return array_ptr; } else if (operand_ty.zigTypeTag(zcu) == .array and inst_ty.zigTypeTag(zcu) == .vector) { const elem_ty = operand_ty.childType(zcu); - assert(elem_ty.toIntern() == inst_scalar_ty.toIntern()); - const llvm_vector_ty = try o.lowerType(pt, inst_ty); - if (!operand_is_ref) return self.todo("implement bitcast non-ref array to vector", .{}); + assert(operand_is_ref); // arrays are always by-ref provided they have runtime bits + const llvm_vector_ty = try self.lowerType(inst_ty); const bitcast_ok = elem_ty.bitSize(zcu) == elem_ty.abiSize(zcu) * 8; if (bitcast_ok) { @@ -4582,7 +4554,7 @@ fn bitCast(self: *FuncGen, operand: Builder.Value, operand_ty: Type, inst_ty: Ty } else { // If the ABI size of the element type is not evenly divisible by size in bits; // a simple bitcast will not work, and we fall back to extractelement. - const elem_llvm_ty = try o.lowerType(pt, elem_ty); + const elem_llvm_ty = try self.lowerType(elem_ty); const elem_size = elem_ty.abiSize(zcu); const vector_len = operand_ty.arrayLen(zcu); var vector = try o.builder.poisonValue(llvm_vector_ty); @@ -4624,7 +4596,7 @@ fn bitCast(self: *FuncGen, operand: Builder.Value, operand_ty: Type, inst_ty: Ty return self.wip.cast(.bitcast, operand, llvm_dest_ty, ""); } -fn airArg(self: *FuncGen, inst: Air.Inst.Index) !Builder.Value { +fn airArg(self: *FuncGen, inst: Air.Inst.Index) Allocator.Error!Builder.Value { const o = self.object; const pt = self.pt; const zcu = pt.zcu; @@ -4714,7 +4686,7 @@ fn airArg(self: *FuncGen, inst: Air.Inst.Index) !Builder.Value { return arg_val; } -fn airAlloc(self: *FuncGen, inst: Air.Inst.Index) !Builder.Value { +fn airAlloc(self: *FuncGen, inst: Air.Inst.Index) Allocator.Error!Builder.Value { const o = self.object; const pt = self.pt; const zcu = pt.zcu; @@ -4723,12 +4695,12 @@ fn airAlloc(self: *FuncGen, inst: Air.Inst.Index) !Builder.Value { if (!pointee_type.hasRuntimeBits(zcu)) return (try o.lowerPtrToVoid(pt, ptr_ty)).toValue(); - const pointee_llvm_ty = try o.lowerType(pt, pointee_type); + const pointee_llvm_ty = try self.lowerType(pointee_type); const alignment = ptr_ty.ptrAlignment(zcu).toLlvm(); return self.buildAlloca(pointee_llvm_ty, alignment); } -fn airRetPtr(self: *FuncGen, inst: Air.Inst.Index) !Builder.Value { +fn airRetPtr(self: *FuncGen, inst: Air.Inst.Index) Allocator.Error!Builder.Value { const o = self.object; const pt = self.pt; const zcu = pt.zcu; @@ -4737,7 +4709,7 @@ fn airRetPtr(self: *FuncGen, inst: Air.Inst.Index) !Builder.Value { if (!ret_ty.hasRuntimeBits(zcu)) return (try o.lowerPtrToVoid(pt, ptr_ty)).toValue(); if (self.ret_ptr != .none) return self.ret_ptr; - const ret_llvm_ty = try o.lowerType(pt, ret_ty); + const ret_llvm_ty = try self.lowerType(ret_ty); const alignment = ptr_ty.ptrAlignment(zcu).toLlvm(); return self.buildAlloca(ret_llvm_ty, alignment); } @@ -4753,7 +4725,7 @@ fn buildAlloca( return buildAllocaInner(&self.wip, llvm_ty, alignment, target); } -fn airStore(self: *FuncGen, inst: Air.Inst.Index, safety: bool) !Builder.Value { +fn airStore(self: *FuncGen, inst: Air.Inst.Index, safety: bool) Allocator.Error!Builder.Value { const o = self.object; const pt = self.pt; const zcu = pt.zcu; @@ -4790,7 +4762,7 @@ fn airStore(self: *FuncGen, inst: Air.Inst.Index, safety: bool) !Builder.Value { self.maybeMarkAllowZeroAccess(ptr_info); - const len = try o.builder.intValue(try o.lowerType(pt, Type.usize), operand_ty.abiSize(zcu)); + const len = try o.builder.intValue(try self.lowerType(Type.usize), operand_ty.abiSize(zcu)); _ = try self.wip.callMemSet( dest_ptr, ptr_ty.ptrAlignment(zcu).toLlvm(), @@ -4812,7 +4784,7 @@ fn airStore(self: *FuncGen, inst: Air.Inst.Index, safety: bool) !Builder.Value { return .none; } -fn airLoad(fg: *FuncGen, inst: Air.Inst.Index) !Builder.Value { +fn airLoad(fg: *FuncGen, inst: Air.Inst.Index) Allocator.Error!Builder.Value { const pt = fg.pt; const zcu = pt.zcu; const ty_op = fg.air.instructions.items(.data)[@intFromEnum(inst)].ty_op; @@ -4823,7 +4795,7 @@ fn airLoad(fg: *FuncGen, inst: Air.Inst.Index) !Builder.Value { return fg.load(ptr, ptr_ty); } -fn airTrap(self: *FuncGen, inst: Air.Inst.Index) !void { +fn airTrap(self: *FuncGen, inst: Air.Inst.Index) Allocator.Error!void { _ = inst; const target = self.pt.zcu.getTarget(); if ((target.cpu.arch == .mips or target.cpu.arch == .mipsel) and @@ -4847,17 +4819,16 @@ fn airTrap(self: *FuncGen, inst: Air.Inst.Index) !void { _ = try self.wip.@"unreachable"(); } -fn airBreakpoint(self: *FuncGen, inst: Air.Inst.Index) !Builder.Value { +fn airBreakpoint(self: *FuncGen, inst: Air.Inst.Index) Allocator.Error!Builder.Value { _ = inst; _ = try self.wip.callIntrinsic(.normal, .none, .debugtrap, &.{}, &.{}, ""); return .none; } -fn airRetAddr(self: *FuncGen, inst: Air.Inst.Index) !Builder.Value { +fn airRetAddr(self: *FuncGen, inst: Air.Inst.Index) Allocator.Error!Builder.Value { _ = inst; const o = self.object; - const pt = self.pt; - const llvm_usize = try o.lowerType(pt, Type.usize); + const llvm_usize = try self.lowerType(Type.usize); if (!target_util.supportsReturnAddress(self.pt.zcu.getTarget(), self.ownerModule().optimize_mode)) { // https://github.com/ziglang/zig/issues/11946 return o.builder.intValue(llvm_usize, 0); @@ -4866,19 +4837,17 @@ fn airRetAddr(self: *FuncGen, inst: Air.Inst.Index) !Builder.Value { return self.wip.cast(.ptrtoint, result, llvm_usize, ""); } -fn airFrameAddress(self: *FuncGen, inst: Air.Inst.Index) !Builder.Value { +fn airFrameAddress(self: *FuncGen, inst: Air.Inst.Index) Allocator.Error!Builder.Value { _ = inst; - const o = self.object; - const pt = self.pt; const result = try self.wip.callIntrinsic(.normal, .none, .frameaddress, &.{.ptr}, &.{.@"0"}, ""); - return self.wip.cast(.ptrtoint, result, try o.lowerType(pt, Type.usize), ""); + return self.wip.cast(.ptrtoint, result, try self.lowerType(Type.usize), ""); } fn airCmpxchg( self: *FuncGen, inst: Air.Inst.Index, kind: Builder.Function.Instruction.CmpXchg.Kind, -) !Builder.Value { +) Allocator.Error!Builder.Value { const o = self.object; const pt = self.pt; const zcu = pt.zcu; @@ -4889,7 +4858,7 @@ fn airCmpxchg( var expected_value = try self.resolveInst(extra.expected_value); var new_value = try self.resolveInst(extra.new_value); const operand_ty = ptr_ty.childType(zcu); - const llvm_operand_ty = try o.lowerType(pt, operand_ty); + const llvm_operand_ty = try self.lowerType(operand_ty); const llvm_abi_ty = try self.getAtomicAbiType(operand_ty, false); if (llvm_abi_ty != .none) { // operand needs widening and truncating @@ -4932,7 +4901,7 @@ fn airCmpxchg( const non_null_bit = try self.wip.not(success_bit, ""); const payload_align = operand_ty.abiAlignment(zcu).toLlvm(); - const alloca_inst = try self.buildAlloca(try o.lowerType(pt, optional_ty), payload_align); + const alloca_inst = try self.buildAlloca(try self.lowerType(optional_ty), payload_align); // Payload is always the first field at offset 0, so address is `alloca_inst` _ = try self.wip.store(.normal, payload, alloca_inst, payload_align); @@ -4944,7 +4913,7 @@ fn airCmpxchg( return alloca_inst; } -fn airAtomicRmw(self: *FuncGen, inst: Air.Inst.Index) !Builder.Value { +fn airAtomicRmw(self: *FuncGen, inst: Air.Inst.Index) Allocator.Error!Builder.Value { const o = self.object; const pt = self.pt; const zcu = pt.zcu; @@ -4959,7 +4928,7 @@ fn airAtomicRmw(self: *FuncGen, inst: Air.Inst.Index) !Builder.Value { const op = toLlvmAtomicRmwBinOp(extra.op(), is_signed_int, is_float); const ordering = toLlvmAtomicOrdering(extra.ordering()); const llvm_abi_ty = try self.getAtomicAbiType(operand_ty, op == .xchg); - const llvm_operand_ty = try o.lowerType(pt, operand_ty); + const llvm_operand_ty = try self.lowerType(operand_ty); const access_kind: Builder.MemoryAccessKind = if (ptr_ty.isVolatilePtr(zcu)) .@"volatile" else .normal; @@ -5002,7 +4971,7 @@ fn airAtomicRmw(self: *FuncGen, inst: Air.Inst.Index) !Builder.Value { access_kind, op, ptr, - try self.wip.cast(.ptrtoint, operand, try o.lowerType(pt, Type.usize), ""), + try self.wip.cast(.ptrtoint, operand, try self.lowerType(Type.usize), ""), self.sync_scope, ordering, ptr_alignment, @@ -5010,8 +4979,7 @@ fn airAtomicRmw(self: *FuncGen, inst: Air.Inst.Index) !Builder.Value { ), llvm_operand_ty, ""); } -fn airAtomicLoad(self: *FuncGen, inst: Air.Inst.Index) !Builder.Value { - const o = self.object; +fn airAtomicLoad(self: *FuncGen, inst: Air.Inst.Index) Allocator.Error!Builder.Value { const pt = self.pt; const zcu = pt.zcu; const atomic_load = self.air.instructions.items(.data)[@intFromEnum(inst)].atomic_load; @@ -5028,7 +4996,7 @@ fn airAtomicLoad(self: *FuncGen, inst: Air.Inst.Index) !Builder.Value { Type.fromInterned(info.child).abiAlignment(zcu)).toLlvm(); const access_kind: Builder.MemoryAccessKind = if (info.flags.is_volatile) .@"volatile" else .normal; - const elem_llvm_ty = try o.lowerType(pt, elem_ty); + const elem_llvm_ty = try self.lowerType(elem_ty); self.maybeMarkAllowZeroAccess(info); @@ -5060,7 +5028,7 @@ fn airAtomicStore( self: *FuncGen, inst: Air.Inst.Index, ordering: Builder.AtomicOrdering, -) !Builder.Value { +) Allocator.Error!Builder.Value { const pt = self.pt; const zcu = pt.zcu; const bin_op = self.air.instructions.items(.data)[@intFromEnum(inst)].bin_op; @@ -5087,7 +5055,7 @@ fn airAtomicStore( return .none; } -fn airMemset(self: *FuncGen, inst: Air.Inst.Index, safety: bool) !Builder.Value { +fn airMemset(self: *FuncGen, inst: Air.Inst.Index, safety: bool) Allocator.Error!Builder.Value { const o = self.object; const pt = self.pt; const zcu = pt.zcu; @@ -5186,7 +5154,7 @@ fn airMemset(self: *FuncGen, inst: Air.Inst.Index, safety: bool) !Builder.Value const body_block = try self.wip.block(1, "InlineMemsetBody"); const end_block = try self.wip.block(1, "InlineMemsetEnd"); - const llvm_usize_ty = try o.lowerType(pt, Type.usize); + const llvm_usize_ty = try self.lowerType(Type.usize); const end_ptr = switch (ptr_ty.ptrSize(zcu)) { .slice => try self.ptraddScaled( dest_ptr, @@ -5225,7 +5193,7 @@ fn airMemset(self: *FuncGen, inst: Air.Inst.Index, safety: bool) !Builder.Value return .none; } -fn airMemcpy(self: *FuncGen, inst: Air.Inst.Index) !Builder.Value { +fn airMemcpy(self: *FuncGen, inst: Air.Inst.Index) Allocator.Error!Builder.Value { const pt = self.pt; const zcu = pt.zcu; const bin_op = self.air.instructions.items(.data)[@intFromEnum(inst)].bin_op; @@ -5254,7 +5222,7 @@ fn airMemcpy(self: *FuncGen, inst: Air.Inst.Index) !Builder.Value { return .none; } -fn airMemmove(self: *FuncGen, inst: Air.Inst.Index) !Builder.Value { +fn airMemmove(self: *FuncGen, inst: Air.Inst.Index) Allocator.Error!Builder.Value { const pt = self.pt; const zcu = pt.zcu; const bin_op = self.air.instructions.items(.data)[@intFromEnum(inst)].bin_op; @@ -5279,14 +5247,15 @@ fn airMemmove(self: *FuncGen, inst: Air.Inst.Index) !Builder.Value { return .none; } -fn airSetUnionTag(self: *FuncGen, inst: Air.Inst.Index) !Builder.Value { +fn airSetUnionTag(self: *FuncGen, inst: Air.Inst.Index) Allocator.Error!Builder.Value { const pt = self.pt; const zcu = pt.zcu; const bin_op = self.air.instructions.items(.data)[@intFromEnum(inst)].bin_op; const un_ptr_ty = self.typeOf(bin_op.lhs); const un_ty = un_ptr_ty.childType(zcu); const layout = un_ty.unionGetLayout(zcu); - assert(layout.tag_size != 0); + + if (layout.tag_size == 0) return .none; // TODO: stop Sema emitting this const access_kind: Builder.MemoryAccessKind = if (un_ptr_ty.isVolatilePtr(zcu)) .@"volatile" else .normal; @@ -5309,7 +5278,7 @@ fn airSetUnionTag(self: *FuncGen, inst: Air.Inst.Index) !Builder.Value { return .none; } -fn airGetUnionTag(self: *FuncGen, inst: Air.Inst.Index) !Builder.Value { +fn airGetUnionTag(self: *FuncGen, inst: Air.Inst.Index) Allocator.Error!Builder.Value { const o = self.object; const pt = self.pt; const zcu = pt.zcu; @@ -5319,7 +5288,7 @@ fn airGetUnionTag(self: *FuncGen, inst: Air.Inst.Index) !Builder.Value { assert(layout.tag_size != 0); const union_ptr = try self.resolveInst(ty_op.operand); if (isByRef(un_ty, zcu)) { - const llvm_un_ty = try o.lowerType(pt, un_ty); + const llvm_un_ty = try self.lowerType(un_ty); if (layout.payload_size == 0) return self.wip.load(.normal, llvm_un_ty, union_ptr, .default, ""); const tag_index = @intFromBool(layout.tag_align.compare(.lt, layout.payload_align)); @@ -5333,7 +5302,7 @@ fn airGetUnionTag(self: *FuncGen, inst: Air.Inst.Index) !Builder.Value { } } -fn airUnaryOp(self: *FuncGen, inst: Air.Inst.Index, comptime op: FloatOp) !Builder.Value { +fn airUnaryOp(self: *FuncGen, inst: Air.Inst.Index, comptime op: FloatOp) Allocator.Error!Builder.Value { const un_op = self.air.instructions.items(.data)[@intFromEnum(inst)].un_op; const operand = try self.resolveInst(un_op); const operand_ty = self.typeOf(un_op); @@ -5341,7 +5310,7 @@ fn airUnaryOp(self: *FuncGen, inst: Air.Inst.Index, comptime op: FloatOp) !Build return self.buildFloatOp(op, .normal, operand_ty, 1, .{operand}); } -fn airNeg(self: *FuncGen, inst: Air.Inst.Index, fast: Builder.FastMathKind) !Builder.Value { +fn airNeg(self: *FuncGen, inst: Air.Inst.Index, fast: Builder.FastMathKind) Allocator.Error!Builder.Value { const un_op = self.air.instructions.items(.data)[@intFromEnum(inst)].un_op; const operand = try self.resolveInst(un_op); const operand_ty = self.typeOf(un_op); @@ -5349,9 +5318,7 @@ fn airNeg(self: *FuncGen, inst: Air.Inst.Index, fast: Builder.FastMathKind) !Bui return self.buildFloatOp(.neg, fast, operand_ty, 1, .{operand}); } -fn airClzCtz(self: *FuncGen, inst: Air.Inst.Index, intrinsic: Builder.Intrinsic) !Builder.Value { - const o = self.object; - const pt = self.pt; +fn airClzCtz(self: *FuncGen, inst: Air.Inst.Index, intrinsic: Builder.Intrinsic) Allocator.Error!Builder.Value { const ty_op = self.air.instructions.items(.data)[@intFromEnum(inst)].ty_op; const inst_ty = self.typeOfIndex(inst); const operand_ty = self.typeOf(ty_op.operand); @@ -5361,16 +5328,14 @@ fn airClzCtz(self: *FuncGen, inst: Air.Inst.Index, intrinsic: Builder.Intrinsic) .normal, .none, intrinsic, - &.{try o.lowerType(pt, operand_ty)}, + &.{try self.lowerType(operand_ty)}, &.{ operand, .false }, "", ); - return self.wip.conv(.unsigned, result, try o.lowerType(pt, inst_ty), ""); + return self.wip.conv(.unsigned, result, try self.lowerType(inst_ty), ""); } -fn airBitOp(self: *FuncGen, inst: Air.Inst.Index, intrinsic: Builder.Intrinsic) !Builder.Value { - const o = self.object; - const pt = self.pt; +fn airBitOp(self: *FuncGen, inst: Air.Inst.Index, intrinsic: Builder.Intrinsic) Allocator.Error!Builder.Value { const ty_op = self.air.instructions.items(.data)[@intFromEnum(inst)].ty_op; const inst_ty = self.typeOfIndex(inst); const operand_ty = self.typeOf(ty_op.operand); @@ -5380,14 +5345,14 @@ fn airBitOp(self: *FuncGen, inst: Air.Inst.Index, intrinsic: Builder.Intrinsic) .normal, .none, intrinsic, - &.{try o.lowerType(pt, operand_ty)}, + &.{try self.lowerType(operand_ty)}, &.{operand}, "", ); - return self.wip.conv(.unsigned, result, try o.lowerType(pt, inst_ty), ""); + return self.wip.conv(.unsigned, result, try self.lowerType(inst_ty), ""); } -fn airByteSwap(self: *FuncGen, inst: Air.Inst.Index) !Builder.Value { +fn airByteSwap(self: *FuncGen, inst: Air.Inst.Index) Allocator.Error!Builder.Value { const o = self.object; const pt = self.pt; const zcu = pt.zcu; @@ -5398,7 +5363,7 @@ fn airByteSwap(self: *FuncGen, inst: Air.Inst.Index) !Builder.Value { const inst_ty = self.typeOfIndex(inst); var operand = try self.resolveInst(ty_op.operand); - var llvm_operand_ty = try o.lowerType(pt, operand_ty); + var llvm_operand_ty = try self.lowerType(operand_ty); if (bits % 16 == 8) { // If not an even byte-multiple, we need zero-extend + shift-left 1 byte @@ -5419,10 +5384,10 @@ fn airByteSwap(self: *FuncGen, inst: Air.Inst.Index) !Builder.Value { const result = try self.wip.callIntrinsic(.normal, .none, .bswap, &.{llvm_operand_ty}, &.{operand}, ""); - return self.wip.conv(.unsigned, result, try o.lowerType(pt, inst_ty), ""); + return self.wip.conv(.unsigned, result, try self.lowerType(inst_ty), ""); } -fn airErrorSetHasValue(self: *FuncGen, inst: Air.Inst.Index) !Builder.Value { +fn airErrorSetHasValue(self: *FuncGen, inst: Air.Inst.Index) Allocator.Error!Builder.Value { const o = self.object; const pt = self.pt; const zcu = pt.zcu; @@ -5440,7 +5405,7 @@ fn airErrorSetHasValue(self: *FuncGen, inst: Air.Inst.Index) !Builder.Value { for (0..names.len) |name_index| { const err_int = ip.getErrorValueIfExists(names.get(ip)[name_index]).?; - const this_tag_int_value = try o.builder.intConst(try o.errorIntType(pt), err_int); + const this_tag_int_value = try o.builder.intConst(try o.errorIntType(), err_int); try wip_switch.addCase(this_tag_int_value, valid_block, &self.wip); } self.wip.cursor = .{ .block = valid_block }; @@ -5455,13 +5420,13 @@ fn airErrorSetHasValue(self: *FuncGen, inst: Air.Inst.Index) !Builder.Value { return phi.toValue(); } -fn airIsNamedEnumValue(self: *FuncGen, inst: Air.Inst.Index) !Builder.Value { +fn airIsNamedEnumValue(self: *FuncGen, inst: Air.Inst.Index) Allocator.Error!Builder.Value { const o = self.object; const un_op = self.air.instructions.items(.data)[@intFromEnum(inst)].un_op; const operand = try self.resolveInst(un_op); const enum_ty = self.typeOf(un_op); - const llvm_fn = try self.getIsNamedEnumValueFunction(enum_ty); + const llvm_fn = try o.getIsNamedEnumValueFunction(self.pt, enum_ty); return self.wip.call( .normal, .fastcc, @@ -5473,28 +5438,7 @@ fn airIsNamedEnumValue(self: *FuncGen, inst: Air.Inst.Index) !Builder.Value { ); } -fn getIsNamedEnumValueFunction(self: *FuncGen, enum_ty: Type) !Builder.Function.Index { - const o = self.object; - const pt = self.pt; - const zcu = pt.zcu; - const ip = &zcu.intern_pool; - - const gop = try o.named_enum_map.getOrPut(o.gpa, enum_ty.toIntern()); - if (gop.found_existing) return gop.value_ptr.*; - errdefer assert(o.named_enum_map.remove(enum_ty.toIntern())); - const function_index = try o.builder.addFunction( - // Dummy function type; `updateIsNamedEnumValue` will replace it with the correct type. - // TODO: change the builder API so we don't need to do this. - try o.builder.fnType(.void, &.{}, .normal), - try o.builder.strtabStringFmt("__zig_is_named_enum_value_{f}", .{enum_ty.containerTypeName(ip).fmt(ip)}), - toLlvmAddressSpace(.generic, zcu.getTarget()), - ); - gop.value_ptr.* = function_index; - try o.updateIsNamedEnumValueFunction(pt, enum_ty, function_index); - return function_index; -} - -fn airTagName(self: *FuncGen, inst: Air.Inst.Index) !Builder.Value { +fn airTagName(self: *FuncGen, inst: Air.Inst.Index) Allocator.Error!Builder.Value { const o = self.object; const pt = self.pt; const un_op = self.air.instructions.items(.data)[@intFromEnum(inst)].un_op; @@ -5513,34 +5457,31 @@ fn airTagName(self: *FuncGen, inst: Air.Inst.Index) !Builder.Value { ); } -fn airErrorName(self: *FuncGen, inst: Air.Inst.Index) !Builder.Value { +fn airErrorName(self: *FuncGen, inst: Air.Inst.Index) Allocator.Error!Builder.Value { const o = self.object; const pt = self.pt; const zcu = pt.zcu; const un_op = self.air.instructions.items(.data)[@intFromEnum(inst)].un_op; const operand = try self.resolveInst(un_op); const slice_ty = self.typeOfIndex(inst); - const slice_llvm_ty = try o.lowerType(pt, slice_ty); + const slice_llvm_ty = try self.lowerType(slice_ty); // If operand is small (e.g. `u8`), then signedness becomes a problem -- GEP always treats the index as signed. - const operand_usize = try self.wip.conv(.unsigned, operand, try o.lowerType(pt, .usize), ""); + const operand_usize = try self.wip.conv(.unsigned, operand, try self.lowerType(.usize), ""); - const error_name_table_ptr = try self.getErrorNameTable(); - const error_name_table = try self.wip.load(.normal, .ptr, error_name_table_ptr.toValue(&o.builder), .default, ""); - const error_name_ptr = try self.ptraddScaled(error_name_table, operand_usize, slice_ty.abiSize(zcu)); + const error_name_table_ptr = try o.getErrorNameTable(); + const error_name_ptr = try self.ptraddScaled(error_name_table_ptr.toValue(&o.builder), operand_usize, slice_ty.abiSize(zcu)); return self.wip.load(.normal, slice_llvm_ty, error_name_ptr, .default, ""); } -fn airSplat(self: *FuncGen, inst: Air.Inst.Index) !Builder.Value { - const o = self.object; - const pt = self.pt; +fn airSplat(self: *FuncGen, inst: Air.Inst.Index) Allocator.Error!Builder.Value { const ty_op = self.air.instructions.items(.data)[@intFromEnum(inst)].ty_op; const scalar = try self.resolveInst(ty_op.operand); const vector_ty = self.typeOfIndex(inst); - return self.wip.splatVector(try o.lowerType(pt, vector_ty), scalar, ""); + return self.wip.splatVector(try self.lowerType(vector_ty), scalar, ""); } -fn airSelect(self: *FuncGen, inst: Air.Inst.Index) !Builder.Value { +fn airSelect(self: *FuncGen, inst: Air.Inst.Index) Allocator.Error!Builder.Value { const pl_op = self.air.instructions.items(.data)[@intFromEnum(inst)].pl_op; const extra = self.air.extraData(Air.Bin, pl_op.payload).data; const pred = try self.resolveInst(pl_op.operand); @@ -5550,7 +5491,7 @@ fn airSelect(self: *FuncGen, inst: Air.Inst.Index) !Builder.Value { return self.wip.select(.normal, pred, a, b, ""); } -fn airShuffleOne(fg: *FuncGen, inst: Air.Inst.Index) !Builder.Value { +fn airShuffleOne(fg: *FuncGen, inst: Air.Inst.Index) Allocator.Error!Builder.Value { const o = fg.object; const pt = fg.pt; const zcu = pt.zcu; @@ -5561,9 +5502,9 @@ fn airShuffleOne(fg: *FuncGen, inst: Air.Inst.Index) !Builder.Value { const operand = try fg.resolveInst(unwrapped.operand); const mask = unwrapped.mask; const operand_ty = fg.typeOf(unwrapped.operand); - const llvm_operand_ty = try o.lowerType(pt, operand_ty); - const llvm_result_ty = try o.lowerType(pt, unwrapped.result_ty); - const llvm_elem_ty = try o.lowerType(pt, unwrapped.result_ty.childType(zcu)); + const llvm_operand_ty = try fg.lowerType(operand_ty); + const llvm_result_ty = try fg.lowerType(unwrapped.result_ty); + const llvm_elem_ty = try fg.lowerType(unwrapped.result_ty.childType(zcu)); const llvm_poison_elem = try o.builder.poisonConst(llvm_elem_ty); const llvm_poison_mask_elem = try o.builder.poisonConst(.i32); const llvm_mask_ty = try o.builder.vectorType(.normal, @intCast(mask.len), .i32); @@ -5657,7 +5598,7 @@ fn airShuffleOne(fg: *FuncGen, inst: Air.Inst.Index) !Builder.Value { ); } -fn airShuffleTwo(fg: *FuncGen, inst: Air.Inst.Index) !Builder.Value { +fn airShuffleTwo(fg: *FuncGen, inst: Air.Inst.Index) Allocator.Error!Builder.Value { const o = fg.object; const pt = fg.pt; const zcu = pt.zcu; @@ -5666,7 +5607,7 @@ fn airShuffleTwo(fg: *FuncGen, inst: Air.Inst.Index) !Builder.Value { const unwrapped = fg.air.unwrapShuffleTwo(zcu, inst); const mask = unwrapped.mask; - const llvm_elem_ty = try o.lowerType(pt, unwrapped.result_ty.childType(zcu)); + const llvm_elem_ty = try fg.lowerType(unwrapped.result_ty.childType(zcu)); const llvm_mask_ty = try o.builder.vectorType(.normal, @intCast(mask.len), .i32); const llvm_poison_mask_elem = try o.builder.poisonConst(.i32); @@ -5756,10 +5697,9 @@ fn buildReducedCall( operand_vector: Builder.Value, vector_len: usize, accum_init: Builder.Value, -) !Builder.Value { +) Allocator.Error!Builder.Value { const o = self.object; - const pt = self.pt; - const usize_ty = try o.lowerType(pt, Type.usize); + const usize_ty = try self.lowerType(Type.usize); const llvm_vector_len = try o.builder.intValue(usize_ty, vector_len); const llvm_result_ty = accum_init.typeOfWip(&self.wip); @@ -5811,7 +5751,7 @@ fn buildReducedCall( return self.wip.load(.normal, llvm_result_ty, accum_ptr, .default, ""); } -fn airReduce(self: *FuncGen, inst: Air.Inst.Index, fast: Builder.FastMathKind) !Builder.Value { +fn airReduce(self: *FuncGen, inst: Air.Inst.Index, fast: Builder.FastMathKind) Allocator.Error!Builder.Value { const o = self.object; const pt = self.pt; const zcu = pt.zcu; @@ -5820,9 +5760,9 @@ fn airReduce(self: *FuncGen, inst: Air.Inst.Index, fast: Builder.FastMathKind) ! const reduce = self.air.instructions.items(.data)[@intFromEnum(inst)].reduce; const operand = try self.resolveInst(reduce.operand); const operand_ty = self.typeOf(reduce.operand); - const llvm_operand_ty = try o.lowerType(pt, operand_ty); + const llvm_operand_ty = try self.lowerType(operand_ty); const scalar_ty = self.typeOfIndex(inst); - const llvm_scalar_ty = try o.lowerType(pt, scalar_ty); + const llvm_scalar_ty = try self.lowerType(scalar_ty); switch (reduce.operation) { .And, .Or, .Xor => return self.wip.callIntrinsic(.normal, .none, switch (reduce.operation) { @@ -5890,8 +5830,7 @@ fn airReduce(self: *FuncGen, inst: Air.Inst.Index, fast: Builder.FastMathKind) ! else => unreachable, }; - const libc_fn = - try self.getLibcFunction(fn_name, &.{ llvm_scalar_ty, llvm_scalar_ty }, llvm_scalar_ty); + const libc_fn = try o.getLibcFunction(fn_name, &.{ llvm_scalar_ty, llvm_scalar_ty }, llvm_scalar_ty); const init_val = switch (llvm_scalar_ty) { .i16 => try o.builder.intValue(.i16, @as(i16, @bitCast( @as(f16, switch (reduce.operation) { @@ -5922,7 +5861,7 @@ fn airReduce(self: *FuncGen, inst: Air.Inst.Index, fast: Builder.FastMathKind) ! return self.buildReducedCall(libc_fn, operand, operand_ty.vectorLen(zcu), init_val); } -fn airAggregateInit(self: *FuncGen, inst: Air.Inst.Index) !Builder.Value { +fn airAggregateInit(self: *FuncGen, inst: Air.Inst.Index) Allocator.Error!Builder.Value { const o = self.object; const pt = self.pt; const zcu = pt.zcu; @@ -5931,7 +5870,7 @@ fn airAggregateInit(self: *FuncGen, inst: Air.Inst.Index) !Builder.Value { const result_ty = self.typeOfIndex(inst); const len: usize = @intCast(result_ty.arrayLen(zcu)); const elements: []const Air.Inst.Ref = @ptrCast(self.air.extra.items[ty_pl.payload..][0..len]); - const llvm_result_ty = try o.lowerType(pt, result_ty); + const llvm_result_ty = try self.lowerType(result_ty); switch (result_ty.zigTypeTag(zcu)) { .vector => { @@ -5997,7 +5936,7 @@ fn airAggregateInit(self: *FuncGen, inst: Air.Inst.Index) !Builder.Value { field_ptr_align.toLlvm(), llvm_field_val, field_ty.abiAlignment(zcu).toLlvm(), - try o.builder.intValue(try o.lowerType(pt, .usize), field_ty.abiSize(zcu)), + try o.builder.intValue(try self.lowerType(.usize), field_ty.abiSize(zcu)), .normal, self.disable_intrinsics, ); @@ -6042,7 +5981,7 @@ fn airAggregateInit(self: *FuncGen, inst: Air.Inst.Index) !Builder.Value { } } -fn airUnionInit(self: *FuncGen, inst: Air.Inst.Index) !Builder.Value { +fn airUnionInit(self: *FuncGen, inst: Air.Inst.Index) Allocator.Error!Builder.Value { const o = self.object; const pt = self.pt; const zcu = pt.zcu; @@ -6050,7 +5989,7 @@ fn airUnionInit(self: *FuncGen, inst: Air.Inst.Index) !Builder.Value { const ty_pl = self.air.instructions.items(.data)[@intFromEnum(inst)].ty_pl; const extra = self.air.extraData(Air.UnionInit, ty_pl.payload).data; const union_ty = self.typeOfIndex(inst); - const union_llvm_ty = try o.lowerType(pt, union_ty); + const union_llvm_ty = try self.lowerType(union_ty); const union_obj = zcu.typeToUnion(union_ty).?; assert(union_obj.layout != .@"packed"); @@ -6086,7 +6025,7 @@ fn airUnionInit(self: *FuncGen, inst: Air.Inst.Index) !Builder.Value { return result_ptr; } -fn airPrefetch(self: *FuncGen, inst: Air.Inst.Index) !Builder.Value { +fn airPrefetch(self: *FuncGen, inst: Air.Inst.Index) Allocator.Error!Builder.Value { const o = self.object; const prefetch = self.air.instructions.items(.data)[@intFromEnum(inst)].prefetch; @@ -6135,14 +6074,12 @@ fn airPrefetch(self: *FuncGen, inst: Air.Inst.Index) !Builder.Value { return .none; } -fn airAddrSpaceCast(self: *FuncGen, inst: Air.Inst.Index) !Builder.Value { - const o = self.object; - const pt = self.pt; +fn airAddrSpaceCast(self: *FuncGen, inst: Air.Inst.Index) Allocator.Error!Builder.Value { const ty_op = self.air.instructions.items(.data)[@intFromEnum(inst)].ty_op; const inst_ty = self.typeOfIndex(inst); const operand = try self.resolveInst(ty_op.operand); - return self.wip.cast(.addrspacecast, operand, try o.lowerType(pt, inst_ty), ""); + return self.wip.cast(.addrspacecast, operand, try self.lowerType(inst_ty), ""); } fn workIntrinsic( @@ -6150,7 +6087,7 @@ fn workIntrinsic( dimension: u32, default: u32, comptime basename: []const u8, -) !Builder.Value { +) Allocator.Error!Builder.Value { return self.wip.callIntrinsic(.normal, .none, switch (dimension) { 0 => @field(Builder.Intrinsic, basename ++ ".x"), 1 => @field(Builder.Intrinsic, basename ++ ".y"), @@ -6159,7 +6096,7 @@ fn workIntrinsic( }, &.{}, &.{}, ""); } -fn airWorkItemId(self: *FuncGen, inst: Air.Inst.Index) !Builder.Value { +fn airWorkItemId(self: *FuncGen, inst: Air.Inst.Index) Allocator.Error!Builder.Value { const target = self.pt.zcu.getTarget(); const pl_op = self.air.instructions.items(.data)[@intFromEnum(inst)].pl_op; @@ -6172,7 +6109,7 @@ fn airWorkItemId(self: *FuncGen, inst: Air.Inst.Index) !Builder.Value { }; } -fn airWorkGroupSize(self: *FuncGen, inst: Air.Inst.Index) !Builder.Value { +fn airWorkGroupSize(self: *FuncGen, inst: Air.Inst.Index) Allocator.Error!Builder.Value { const pt = self.pt; const target = pt.zcu.getTarget(); @@ -6200,7 +6137,7 @@ fn airWorkGroupSize(self: *FuncGen, inst: Air.Inst.Index) !Builder.Value { } } -fn airWorkGroupId(self: *FuncGen, inst: Air.Inst.Index) !Builder.Value { +fn airWorkGroupId(self: *FuncGen, inst: Air.Inst.Index) Allocator.Error!Builder.Value { const target = self.pt.zcu.getTarget(); const pl_op = self.air.instructions.items(.data)[@intFromEnum(inst)].pl_op; @@ -6213,28 +6150,6 @@ fn airWorkGroupId(self: *FuncGen, inst: Air.Inst.Index) !Builder.Value { }; } -fn getErrorNameTable(self: *FuncGen) Allocator.Error!Builder.Variable.Index { - const o = self.object; - const pt = self.pt; - - const table = o.error_name_table; - if (table != .none) return table; - - // TODO: Address space - const variable_index = - try o.builder.addVariable(try o.builder.strtabString("__zig_err_name_table"), .ptr, .default); - variable_index.setLinkage(.private, &o.builder); - variable_index.setMutability(.constant, &o.builder); - variable_index.setUnnamedAddr(.unnamed_addr, &o.builder); - variable_index.setAlignment( - Type.slice_const_u8_sentinel_0.abiAlignment(pt.zcu).toLlvm(), - &o.builder, - ); - - o.error_name_table = variable_index; - return variable_index; -} - /// Assumes that `Type.optionalReprIsPayload` is `false` for `opt_ty` and that the payload has bits. fn optCmpNull( self: *FuncGen, @@ -6258,7 +6173,7 @@ fn optPayloadHandle( opt_ptr: Builder.Value, opt_ty: Type, can_elide_load: bool, -) !Builder.Value { +) Allocator.Error!Builder.Value { const pt = fg.pt; const zcu = pt.zcu; assert(isByRef(opt_ty, zcu)); @@ -6281,7 +6196,7 @@ fn fieldPtr( aggregate_ptr: Builder.Value, aggregate_ptr_ty: Type, field_index: u32, -) !Builder.Value { +) Allocator.Error!Builder.Value { const pt = self.pt; const zcu = pt.zcu; const aggregate_ty = aggregate_ptr_ty.childType(zcu); @@ -6305,7 +6220,7 @@ fn loadTruncate( payload_ty: Type, payload_ptr: Builder.Value, payload_alignment: Builder.Alignment, -) !Builder.Value { +) Allocator.Error!Builder.Value { // from https://llvm.org/docs/LangRef.html#load-instruction : // "When loading a value of a type like i20 with a size that is not an integral number of bytes, the result is undefined if the value was not originally written using a store of the same type. " // => so load the byte aligned value and trunc the unwanted bits. @@ -6313,7 +6228,7 @@ fn loadTruncate( const o = fg.object; const pt = fg.pt; const zcu = pt.zcu; - const payload_llvm_ty = try o.lowerType(pt, payload_ty); + const payload_llvm_ty = try fg.lowerType(payload_ty); const abi_size = payload_ty.abiSize(zcu); const load_llvm_ty = if (payload_ty.isAbiInt(zcu)) @@ -6321,7 +6236,7 @@ fn loadTruncate( else payload_llvm_ty; const loaded = try fg.wip.load(access_kind, load_llvm_ty, payload_ptr, payload_alignment, ""); - const shifted = if (payload_llvm_ty != load_llvm_ty and o.target.cpu.arch.endian() == .big) + const shifted = if (payload_llvm_ty != load_llvm_ty and zcu.getTarget().cpu.arch.endian() == .big) try fg.wip.bin(.lshr, loaded, try o.builder.intValue( load_llvm_ty, (payload_ty.abiSize(zcu) - (std.math.divCeil(u64, payload_ty.bitSize(zcu), 8) catch unreachable)) * 8, @@ -6339,10 +6254,10 @@ fn loadByRef( pointee_type: Type, ptr_alignment: Builder.Alignment, access_kind: Builder.MemoryAccessKind, -) !Builder.Value { +) Allocator.Error!Builder.Value { const o = fg.object; const pt = fg.pt; - const pointee_llvm_ty = try o.lowerType(pt, pointee_type); + const pointee_llvm_ty = try fg.lowerType(pointee_type); const result_align = InternPool.Alignment.fromLlvm(ptr_alignment) .max(pointee_type.abiAlignment(pt.zcu)).toLlvm(); const result_ptr = try fg.buildAlloca(pointee_llvm_ty, result_align); @@ -6352,7 +6267,7 @@ fn loadByRef( result_align, ptr, ptr_alignment, - try o.builder.intValue(try o.lowerType(pt, Type.usize), size_bytes), + try o.builder.intValue(try fg.lowerType(.usize), size_bytes), access_kind, fg.disable_intrinsics, ); @@ -6362,7 +6277,7 @@ fn loadByRef( /// This function always performs a copy. For isByRef=true types, it creates a new /// 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: Builder.Value, ptr_ty: Type) !Builder.Value { +fn load(self: *FuncGen, ptr: Builder.Value, ptr_ty: Type) Allocator.Error!Builder.Value { const o = self.object; const pt = self.pt; const zcu = pt.zcu; @@ -6380,7 +6295,7 @@ fn load(self: *FuncGen, ptr: Builder.Value, ptr_ty: Type) !Builder.Value { if (info.flags.vector_index != .none) { const index_u32 = try o.builder.intValue(.i32, info.flags.vector_index); - const vec_elem_ty = try o.lowerType(pt, elem_ty); + const vec_elem_ty = try self.lowerType(elem_ty); const vec_ty = try o.builder.vectorType(.normal, info.packed_offset.host_size, vec_elem_ty); const loaded_vector = try self.wip.load(access_kind, vec_ty, ptr, ptr_alignment, ""); @@ -6401,7 +6316,7 @@ fn load(self: *FuncGen, ptr: Builder.Value, ptr_ty: Type) !Builder.Value { const elem_bits = ptr_ty.childType(zcu).bitSize(zcu); const shift_amt = try o.builder.intValue(containing_int_ty, info.packed_offset.bit_offset); const shifted_value = try self.wip.bin(.lshr, containing_int, shift_amt, ""); - const elem_llvm_ty = try o.lowerType(pt, elem_ty); + const elem_llvm_ty = try self.lowerType(elem_ty); if (isByRef(elem_ty, zcu)) { const result_align = elem_ty.abiAlignment(zcu).toLlvm(); @@ -6434,7 +6349,7 @@ fn store( ptr_ty: Type, elem: Builder.Value, ordering: Builder.AtomicOrdering, -) !void { +) Allocator.Error!void { const o = self.object; const pt = self.pt; const zcu = pt.zcu; @@ -6449,7 +6364,7 @@ fn store( if (info.flags.vector_index != .none) { const index_u32 = try o.builder.intValue(.i32, info.flags.vector_index); - const vec_elem_ty = try o.lowerType(pt, elem_ty); + const vec_elem_ty = try self.lowerType(elem_ty); const vec_ty = try o.builder.vectorType(.normal, info.packed_offset.host_size, vec_elem_ty); const loaded_vector = try self.wip.load(.normal, vec_ty, ptr, ptr_alignment, ""); @@ -6518,7 +6433,7 @@ fn store( ptr_alignment, elem, elem_ty.abiAlignment(zcu).toLlvm(), - try o.builder.intValue(try o.lowerType(pt, Type.usize), elem_ty.abiSize(zcu)), + try o.builder.intValue(try self.lowerType(Type.usize), elem_ty.abiSize(zcu)), access_kind, self.disable_intrinsics, ); @@ -6527,8 +6442,7 @@ fn store( fn valgrindMarkUndef(fg: *FuncGen, ptr: Builder.Value, len: Builder.Value) Allocator.Error!void { const VG_USERREQ__MAKE_MEM_UNDEFINED = 1296236545; const o = fg.object; - const pt = fg.pt; - const usize_ty = try o.lowerType(pt, Type.usize); + const usize_ty = try fg.lowerType(.usize); const zero = try o.builder.intValue(usize_ty, 0); const req = try o.builder.intValue(usize_ty, VG_USERREQ__MAKE_MEM_UNDEFINED); const ptr_as_usize = try fg.wip.cast(.ptrtoint, ptr, usize_ty, ""); @@ -6551,7 +6465,7 @@ fn valgrindClientRequest( const target = zcu.getTarget(); if (!target_util.hasValgrindSupport(target, .stage2_llvm)) return default_value; - const llvm_usize = try o.lowerType(pt, Type.usize); + const llvm_usize = try fg.lowerType(.usize); const usize_alignment = Type.usize.abiAlignment(zcu).toLlvm(); const array_llvm_ty = try o.builder.arrayType(6, llvm_usize); @@ -7360,11 +7274,12 @@ pub fn isByRef(ty: Type, zcu: *const Zcu) bool { => false, .array, - .error_union, .frame, => ty.hasRuntimeBits(zcu), - .optional => ty.hasRuntimeBits(zcu) and !ty.optionalReprIsPayload(zcu), + .error_union => ty.errorUnionPayload(zcu).hasRuntimeBits(zcu), + + .optional => !ty.optionalReprIsPayload(zcu) and ty.optionalChild(zcu).hasRuntimeBits(zcu), .@"struct" => switch (ty.containerLayout(zcu)) { .@"packed" => false, @@ -7402,25 +7317,19 @@ fn getAtomicAbiType(fg: *const FuncGen, ty: Type, is_rmw_xchg: bool) Allocator.E fn ptraddConst(fg: *FuncGen, ptr: Builder.Value, offset: u64) Allocator.Error!Builder.Value { if (offset == 0) return ptr; - const llvm_usize_ty = try fg.object.lowerType(fg.pt, .usize); + const llvm_usize_ty = try fg.lowerType(.usize); const offset_val = try fg.object.builder.intValue(llvm_usize_ty, offset); - return fg.ptradd(ptr, offset_val); + return fg.wip.gep(.inbounds, .i8, ptr, &.{offset_val}, ""); } fn ptraddScaled(fg: *FuncGen, ptr: Builder.Value, index: Builder.Value, scale: u64) Allocator.Error!Builder.Value { - switch (scale) { - 0 => return ptr, - 1 => return fg.ptradd(ptr, index), - else => { - const o = fg.object; - const llvm_usize_ty = try o.lowerType(fg.pt, .usize); - const scale_val = try o.builder.intValue(llvm_usize_ty, scale); - const offset = try fg.wip.bin(.@"mul nuw", index, scale_val, ""); - return fg.ptradd(ptr, offset); - }, - } -} -fn ptradd(fg: *FuncGen, ptr: Builder.Value, offset: Builder.Value) Allocator.Error!Builder.Value { - return fg.wip.gep(.inbounds, .i8, ptr, &.{offset}, ""); + if (scale == 0) return ptr; + // Right now LLVM seems to fare a bit worse with an explicit `mul nuw` instruction than it does + // if we use a bigger type for the GEP, so we'll do that. As I understand it, it has not yet + // been decided whether the planned `ptradd` instruction will accept a scale or not; if it does + // not then presumably upstream will improve their handling of explicit `mul nuw` computing the + // offset. + const llvm_scale_ty = try fg.object.builder.arrayType(scale, .i8); + return fg.wip.gep(.inbounds, llvm_scale_ty, ptr, &.{index}, ""); } fn compilerRtIntBits(bits: u16) ?u16 {