From 16d0509139a1c2c10758410003bf4240442d1b5b Mon Sep 17 00:00:00 2001 From: Jacob Young Date: Thu, 28 Mar 2024 20:14:16 -0400 Subject: [PATCH] cbe: fix bugs revealed by an upcoming commit Closes #18023 --- lib/zig.h | 9 +- src/Compilation.zig | 3 +- src/codegen/c.zig | 2459 +++++++++++++++++++++------------------- src/codegen/c/type.zig | 298 ++--- src/link/C.zig | 114 +- 5 files changed, 1497 insertions(+), 1386 deletions(-) diff --git a/lib/zig.h b/lib/zig.h index 7a1c69575a24..f2ae283bafb2 100644 --- a/lib/zig.h +++ b/lib/zig.h @@ -165,11 +165,14 @@ typedef char bool; #endif #if zig_has_attribute(section) -#define zig_linksection(name, def, ...) def __attribute__((section(name))) +#define zig_linksection(name) __attribute__((section(name))) +#define zig_linksection_fn zig_linksection #elif _MSC_VER -#define zig_linksection(name, def, ...) __pragma(section(name, __VA_ARGS__)) __declspec(allocate(name)) def +#define zig_linksection(name) __pragma(section(name, read, write)) __declspec(allocate(name)) +#define zig_linksection_fn(name) __pragma(section(name, read, execute)) __declspec(code_seg(name)) #else -#define zig_linksection(name, def, ...) zig_linksection_unavailable +#define zig_linksection(name) zig_linksection_unavailable +#define zig_linksection_fn zig_linksection #endif #if zig_has_builtin(unreachable) || defined(zig_gnuc) diff --git a/src/Compilation.zig b/src/Compilation.zig index 5a6e02d400d4..442c1075e076 100644 --- a/src/Compilation.zig +++ b/src/Compilation.zig @@ -3451,7 +3451,8 @@ fn processOneJob(comp: *Compilation, job: Job, prog_node: *std.Progress.Node) !v var dg: c_codegen.DeclGen = .{ .gpa = gpa, - .module = module, + .zcu = module, + .mod = module.namespacePtr(decl.src_namespace).file_scope.mod, .error_msg = null, .pass = .{ .decl = decl_index }, .is_naked_fn = false, diff --git a/src/codegen/c.zig b/src/codegen/c.zig index 7ae5c87ee540..246f4e1e0feb 100644 --- a/src/codegen/c.zig +++ b/src/codegen/c.zig @@ -5,12 +5,13 @@ const mem = std.mem; const log = std.log.scoped(.c); const link = @import("../link.zig"); -const Module = @import("../Module.zig"); +const Zcu = @import("../Module.zig"); +const Module = @import("../Package/Module.zig"); const Compilation = @import("../Compilation.zig"); const Value = @import("../Value.zig"); const Type = @import("../type.zig").Type; const C = link.File.C; -const Decl = Module.Decl; +const Decl = Zcu.Decl; const trace = @import("../tracy.zig").trace; const LazySrcLoc = std.zig.LazySrcLoc; const Air = @import("../Air.zig"); @@ -30,7 +31,7 @@ pub const CValue = union(enum) { /// Address of a local. local_ref: LocalIndex, /// A constant instruction, to be rendered inline. - constant: InternPool.Index, + constant: Value, /// Index into the parameters arg: usize, /// The array field of a parameter @@ -72,13 +73,15 @@ pub const LazyFnValue = struct { }; pub const LazyFnMap = std.AutoArrayHashMapUnmanaged(LazyFnKey, LazyFnValue); -const LoopDepth = u16; const Local = struct { cty_idx: CType.Index, - alignas: CType.AlignAs, + flags: packed struct(u32) { + alignas: CType.AlignAs, + _: u20 = undefined, + }, pub fn getType(local: Local) LocalType { - return .{ .cty_idx = local.cty_idx, .alignas = local.alignas }; + return .{ .cty_idx = local.cty_idx, .alignas = local.flags.alignas }; } }; @@ -300,11 +303,11 @@ pub const Function = struct { const gop = try f.value_map.getOrPut(ref); if (gop.found_existing) return gop.value_ptr.*; - const mod = f.object.dg.module; - const val = (try f.air.value(ref, mod)).?; + const zcu = f.object.dg.zcu; + const val = (try f.air.value(ref, zcu)).?; const ty = f.typeOf(ref); - const result: CValue = if (lowersToArray(ty, mod)) result: { + const result: CValue = if (lowersToArray(ty, zcu)) result: { const writer = f.object.codeHeaderWriter(); const alignment: Alignment = .none; const decl_c_value = try f.allocLocalValue(ty, alignment); @@ -313,17 +316,17 @@ pub const Function = struct { try writer.writeAll("static "); try f.object.dg.renderTypeAndName(writer, ty, decl_c_value, Const, alignment, .complete); try writer.writeAll(" = "); - try f.object.dg.renderValue(writer, ty, val, .StaticInitializer); + try f.object.dg.renderValue(writer, val, .StaticInitializer); try writer.writeAll(";\n "); break :result decl_c_value; - } else .{ .constant = val.toIntern() }; + } else .{ .constant = val }; gop.value_ptr.* = result; return result; } fn wantSafety(f: *Function) bool { - return switch (f.object.dg.module.optimizeMode()) { + return switch (f.object.dg.zcu.optimizeMode()) { .Debug, .ReleaseSafe => true, .ReleaseFast, .ReleaseSmall => false, }; @@ -333,11 +336,13 @@ pub const Function = struct { /// those which go into `allocs`. This function does not add the resulting local into `allocs`; /// that responsibility lies with the caller. fn allocLocalValue(f: *Function, ty: Type, alignment: Alignment) !CValue { - const mod = f.object.dg.module; + const zcu = f.object.dg.zcu; const gpa = f.object.dg.gpa; try f.locals.append(gpa, .{ .cty_idx = try f.typeToIndex(ty, .complete), - .alignas = CType.AlignAs.init(alignment, ty.abiAlignment(mod)), + .flags = .{ + .alignas = CType.AlignAs.init(alignment, ty.abiAlignment(zcu)), + }, }); return .{ .new_local = @intCast(f.locals.items.len - 1) }; } @@ -355,79 +360,100 @@ pub const Function = struct { /// Only allocates the local; does not print anything. Will attempt to re-use locals, so should /// not be used for persistent locals (i.e. those in `allocs`). fn allocAlignedLocal(f: *Function, ty: Type, _: CQualifiers, alignment: Alignment) !CValue { - const mod = f.object.dg.module; + const zcu = f.object.dg.zcu; if (f.free_locals_map.getPtr(.{ .cty_idx = try f.typeToIndex(ty, .complete), - .alignas = CType.AlignAs.init(alignment, ty.abiAlignment(mod)), + .alignas = CType.AlignAs.init(alignment, ty.abiAlignment(zcu)), })) |locals_list| { if (locals_list.popOrNull()) |local_entry| { return .{ .new_local = local_entry.key }; } } - return try f.allocLocalValue(ty, alignment); + return f.allocLocalValue(ty, alignment); } fn writeCValue(f: *Function, w: anytype, c_value: CValue, location: ValueRenderLocation) !void { switch (c_value) { - .constant => |val| try f.object.dg.renderValue( - w, - Type.fromInterned(f.object.dg.module.intern_pool.typeOf(val)), - Value.fromInterned(val), - location, - ), - .undef => |ty| try f.object.dg.renderValue(w, ty, Value.undef, location), + .none => unreachable, + .new_local, .local => |i| try w.print("t{d}", .{i}), + .local_ref => |i| { + const local = &f.locals.items[i]; + if (local.flags.alignas.abiOrder().compare(.lt)) { + const zcu = f.object.dg.zcu; + const pointee_ty = try zcu.intType(.unsigned, @min( + local.flags.alignas.@"align".toByteUnitsOptional().?, + f.object.dg.mod.resolved_target.result.maxIntAlignment(), + ) * 8); + const ptr_ty = try zcu.singleMutPtrType(pointee_ty); + + try w.writeByte('('); + try f.renderType(w, ptr_ty); + try w.writeByte(')'); + } + try w.print("&t{d}", .{i}); + }, + .constant => |val| try f.object.dg.renderValue(w, val, location), + .arg => |i| try w.print("a{d}", .{i}), + .arg_array => |i| try f.writeCValueMember(w, .{ .arg = i }, .{ .identifier = "array" }), + .undef => |ty| try f.object.dg.renderUndefValue(w, ty, location), else => try f.object.dg.writeCValue(w, c_value), } } fn writeCValueDeref(f: *Function, w: anytype, c_value: CValue) !void { switch (c_value) { - .constant => |val| { + .none => unreachable, + .new_local, .local, .constant => { try w.writeAll("(*"); - try f.object.dg.renderValue( - w, - Type.fromInterned(f.object.dg.module.intern_pool.typeOf(val)), - Value.fromInterned(val), - .Other, - ); + try f.writeCValue(w, c_value, .Other); + try w.writeByte(')'); + }, + .local_ref => |i| try w.print("t{d}", .{i}), + .arg => |i| try w.print("(*a{d})", .{i}), + .arg_array => |i| { + try w.writeAll("(*"); + try f.writeCValueMember(w, .{ .arg = i }, .{ .identifier = "array" }); try w.writeByte(')'); }, else => try f.object.dg.writeCValueDeref(w, c_value), } } - fn writeCValueMember(f: *Function, w: anytype, c_value: CValue, member: CValue) !void { + fn writeCValueMember( + f: *Function, + writer: anytype, + c_value: CValue, + member: CValue, + ) error{ OutOfMemory, AnalysisFail }!void { switch (c_value) { - .constant => |val| { - try f.object.dg.renderValue( - w, - Type.fromInterned(f.object.dg.module.intern_pool.typeOf(val)), - Value.fromInterned(val), - .Other, - ); - try w.writeByte('.'); - try f.writeCValue(w, member, .Other); + .new_local, .local, .local_ref, .constant, .arg, .arg_array => { + try f.writeCValue(writer, c_value, .Other); + try writer.writeByte('.'); + try f.writeCValue(writer, member, .Other); }, - else => try f.object.dg.writeCValueMember(w, c_value, member), + else => return f.object.dg.writeCValueMember(writer, c_value, member), } } - fn writeCValueDerefMember(f: *Function, w: anytype, c_value: CValue, member: CValue) !void { + fn writeCValueDerefMember(f: *Function, writer: anytype, c_value: CValue, member: CValue) !void { switch (c_value) { - .constant => |val| { - try w.writeByte('('); - try f.object.dg.renderValue( - w, - Type.fromInterned(f.object.dg.module.intern_pool.typeOf(val)), - Value.fromInterned(val), - .Other, - ); - try w.writeAll(")->"); - try f.writeCValue(w, member, .Other); + .new_local, .local, .arg, .arg_array => { + try f.writeCValue(writer, c_value, .Other); + try writer.writeAll("->"); + }, + .constant => { + try writer.writeByte('('); + try f.writeCValue(writer, c_value, .Other); + try writer.writeAll(")->"); + }, + .local_ref => { + try f.writeCValueDeref(writer, c_value); + try writer.writeByte('.'); }, - else => try f.object.dg.writeCValueDerefMember(w, c_value, member), + else => return f.object.dg.writeCValueDerefMember(writer, c_value, member), } + try f.writeCValue(writer, member, .Other); } fn fail(f: *Function, comptime format: []const u8, args: anytype) error{ AnalysisFail, OutOfMemory } { @@ -462,8 +488,8 @@ pub const Function = struct { return f.object.dg.renderIntCast(w, dest_ty, .{ .c_value = .{ .f = f, .value = src, .v = v } }, src_ty, location); } - fn fmtIntLiteral(f: *Function, ty: Type, val: Value) !std.fmt.Formatter(formatIntLiteral) { - return f.object.dg.fmtIntLiteral(ty, val, .Other); + fn fmtIntLiteral(f: *Function, val: Value) !std.fmt.Formatter(formatIntLiteral) { + return f.object.dg.fmtIntLiteral(val, .Other); } fn getLazyFnName(f: *Function, key: LazyFnKey, data: LazyFnValue.Data) ![]const u8 { @@ -475,7 +501,7 @@ pub const Function = struct { var promoted = f.object.dg.ctypes.promote(gpa); defer f.object.dg.ctypes.demote(promoted); const arena = promoted.arena.allocator(); - const mod = f.object.dg.module; + const zcu = f.object.dg.zcu; gop.value_ptr.* = .{ .fn_name = switch (key) { @@ -484,7 +510,7 @@ pub const Function = struct { .never_inline, => |owner_decl| try std.fmt.allocPrint(arena, "zig_{s}_{}__{d}", .{ @tagName(key), - fmtIdent(mod.intern_pool.stringToSlice(mod.declPtr(owner_decl).name)), + fmtIdent(zcu.intern_pool.stringToSlice(zcu.declPtr(owner_decl).name)), @intFromEnum(owner_decl), }), }, @@ -510,17 +536,17 @@ pub const Function = struct { } fn typeOf(f: *Function, inst: Air.Inst.Ref) Type { - const mod = f.object.dg.module; - return f.air.typeOf(inst, &mod.intern_pool); + const zcu = f.object.dg.zcu; + return f.air.typeOf(inst, &zcu.intern_pool); } fn typeOfIndex(f: *Function, inst: Air.Inst.Index) Type { - const mod = f.object.dg.module; - return f.air.typeOfIndex(inst, &mod.intern_pool); + const zcu = f.object.dg.zcu; + return f.air.typeOfIndex(inst, &zcu.intern_pool); } }; -/// This data is available when outputting .c code for a `Module`. +/// This data is available when outputting .c code for a `Zcu`. /// It is not available when generating .h file. pub const Object = struct { dg: DeclGen, @@ -542,12 +568,13 @@ pub const Object = struct { /// This data is available both when outputting .c code and when outputting an .h file. pub const DeclGen = struct { gpa: mem.Allocator, - module: *Module, + zcu: *Zcu, + mod: *Module, pass: Pass, is_naked_fn: bool, /// This is a borrowed reference from `link.C`. fwd_decl: std.ArrayList(u8), - error_msg: ?*Module.ErrorMsg, + error_msg: ?*Zcu.ErrorMsg, ctypes: CType.Store, /// Keeps track of anonymous decls that need to be rendered before this /// (named) Decl in the output C code. @@ -566,75 +593,70 @@ pub const DeclGen = struct { fn fail(dg: *DeclGen, comptime format: []const u8, args: anytype) error{ AnalysisFail, OutOfMemory } { @setCold(true); - const mod = dg.module; + const zcu = dg.zcu; const decl_index = dg.pass.decl; - const decl = mod.declPtr(decl_index); - const src_loc = decl.srcLoc(mod); - dg.error_msg = try Module.ErrorMsg.create(dg.gpa, src_loc, format, args); + const decl = zcu.declPtr(decl_index); + const src_loc = decl.srcLoc(zcu); + dg.error_msg = try Zcu.ErrorMsg.create(dg.gpa, src_loc, format, args); return error.AnalysisFail; } fn renderAnonDeclValue( dg: *DeclGen, writer: anytype, - ty: Type, ptr_val: Value, anon_decl: InternPool.Key.Ptr.Addr.AnonDecl, location: ValueRenderLocation, ) error{ OutOfMemory, AnalysisFail }!void { - const mod = dg.module; - const ip = &mod.intern_pool; - const decl_val = anon_decl.val; - const decl_ty = Type.fromInterned(ip.typeOf(decl_val)); + const zcu = dg.zcu; + const ip = &zcu.intern_pool; + const decl_val = Value.fromInterned(anon_decl.val); + const decl_ty = decl_val.typeOf(zcu); // Render an undefined pointer if we have a pointer to a zero-bit or comptime type. - if (ty.isPtrAtRuntime(mod) and !decl_ty.isFnOrHasRuntimeBits(mod)) { - return dg.writeCValue(writer, .{ .undef = ty }); + const ptr_ty = ptr_val.typeOf(zcu); + if (ptr_ty.isPtrAtRuntime(zcu) and !decl_ty.isFnOrHasRuntimeBits(zcu)) { + return dg.writeCValue(writer, .{ .undef = ptr_ty }); } // Chase function values in order to be able to reference the original function. - if (Value.fromInterned(decl_val).getFunction(mod)) |func| { - _ = func; - _ = ptr_val; - _ = location; - @panic("TODO"); - } - if (Value.fromInterned(decl_val).getExternFunc(mod)) |extern_func| { - _ = extern_func; - _ = ptr_val; - _ = location; - @panic("TODO"); - } + if (decl_val.getFunction(zcu)) |func| + return dg.renderDeclValue(writer, ptr_val, func.owner_decl, location); + if (decl_val.getExternFunc(zcu)) |extern_func| + return dg.renderDeclValue(writer, ptr_val, extern_func.decl, location); - assert(Value.fromInterned(decl_val).getVariable(mod) == null); + assert(decl_val.getVariable(zcu) == null); // We shouldn't cast C function pointers as this is UB (when you call // them). The analysis until now should ensure that the C function // pointers are compatible. If they are not, then there is a bug // somewhere and we should let the C compiler tell us about it. - const need_typecast = if (ty.castPtrToFn(mod)) |_| false else !ty.childType(mod).eql(decl_ty, mod); - if (need_typecast) { + const child_cty = (try dg.typeToCType(ptr_ty, .complete)).cast(CType.Payload.Child).?.data; + const decl_cty = try dg.typeToIndex(decl_ty, .complete); + const need_cast = child_cty != decl_cty and + (dg.indexToCType(child_cty).tag() != .function or dg.indexToCType(decl_cty).tag() != .function); + if (need_cast) { try writer.writeAll("(("); - try dg.renderType(writer, ty); + try dg.renderType(writer, ptr_ty); try writer.writeByte(')'); } try writer.writeByte('&'); try renderAnonDeclName(writer, decl_val); - if (need_typecast) try writer.writeByte(')'); + if (need_cast) try writer.writeByte(')'); // Indicate that the anon decl should be rendered to the output so that // our reference above is not undefined. const ptr_type = ip.indexToKey(anon_decl.orig_ty).ptr_type; - const gop = try dg.anon_decl_deps.getOrPut(dg.gpa, decl_val); + const gop = try dg.anon_decl_deps.getOrPut(dg.gpa, anon_decl.val); if (!gop.found_existing) gop.value_ptr.* = .{}; // Only insert an alignment entry if the alignment is greater than ABI // alignment. If there is already an entry, keep the greater alignment. const explicit_alignment = ptr_type.flags.alignment; if (explicit_alignment != .none) { - const abi_alignment = Type.fromInterned(ptr_type.child).abiAlignment(mod); + const abi_alignment = Type.fromInterned(ptr_type.child).abiAlignment(zcu); if (explicit_alignment.compareStrict(.gt, abi_alignment)) { - const aligned_gop = try dg.aligned_anon_decls.getOrPut(dg.gpa, decl_val); + const aligned_gop = try dg.aligned_anon_decls.getOrPut(dg.gpa, anon_decl.val); aligned_gop.value_ptr.* = if (aligned_gop.found_existing) aligned_gop.value_ptr.maxStrict(explicit_alignment) else @@ -646,41 +668,45 @@ pub const DeclGen = struct { fn renderDeclValue( dg: *DeclGen, writer: anytype, - ty: Type, val: Value, decl_index: InternPool.DeclIndex, location: ValueRenderLocation, ) error{ OutOfMemory, AnalysisFail }!void { - const mod = dg.module; - const decl = mod.declPtr(decl_index); + const zcu = dg.zcu; + const decl = zcu.declPtr(decl_index); assert(decl.has_tv); // Render an undefined pointer if we have a pointer to a zero-bit or comptime type. - if (ty.isPtrAtRuntime(mod) and !decl.typeOf(mod).isFnOrHasRuntimeBits(mod)) { + const ty = val.typeOf(zcu); + const decl_ty = decl.typeOf(zcu); + if (ty.isPtrAtRuntime(zcu) and !decl_ty.isFnOrHasRuntimeBits(zcu)) { return dg.writeCValue(writer, .{ .undef = ty }); } // Chase function values in order to be able to reference the original function. - if (decl.val.getFunction(mod)) |func| if (func.owner_decl != decl_index) - return dg.renderDeclValue(writer, ty, val, func.owner_decl, location); - if (decl.val.getExternFunc(mod)) |extern_func| if (extern_func.decl != decl_index) - return dg.renderDeclValue(writer, ty, val, extern_func.decl, location); + if (decl.val.getFunction(zcu)) |func| if (func.owner_decl != decl_index) + return dg.renderDeclValue(writer, val, func.owner_decl, location); + if (decl.val.getExternFunc(zcu)) |extern_func| if (extern_func.decl != decl_index) + return dg.renderDeclValue(writer, val, extern_func.decl, location); - if (decl.val.getVariable(mod)) |variable| try dg.renderFwdDecl(decl_index, variable, .tentative); + if (decl.val.getVariable(zcu)) |variable| try dg.renderFwdDecl(decl_index, variable, .tentative); // We shouldn't cast C function pointers as this is UB (when you call // them). The analysis until now should ensure that the C function // pointers are compatible. If they are not, then there is a bug // somewhere and we should let the C compiler tell us about it. - const need_typecast = if (ty.castPtrToFn(mod)) |_| false else !ty.childType(mod).eql(decl.typeOf(mod), mod); - if (need_typecast) { + const child_cty = (try dg.typeToCType(ty, .complete)).cast(CType.Payload.Child).?.data; + const decl_cty = try dg.typeToIndex(decl_ty, .complete); + const need_cast = child_cty != decl_cty and + (dg.indexToCType(child_cty).tag() != .function or dg.indexToCType(decl_cty).tag() != .function); + if (need_cast) { try writer.writeAll("(("); try dg.renderType(writer, ty); try writer.writeByte(')'); } try writer.writeByte('&'); try dg.renderDeclName(writer, decl_index, 0); - if (need_typecast) try writer.writeByte(')'); + if (need_cast) try writer.writeByte(')'); } /// Renders a "parent" pointer by recursing to the root decl/variable @@ -691,31 +717,32 @@ pub const DeclGen = struct { ptr_val: InternPool.Index, location: ValueRenderLocation, ) error{ OutOfMemory, AnalysisFail }!void { - const mod = dg.module; - const ptr_ty = Type.fromInterned(mod.intern_pool.typeOf(ptr_val)); + const zcu = dg.zcu; + const ip = &zcu.intern_pool; + const ptr_ty = Type.fromInterned(ip.typeOf(ptr_val)); const ptr_cty = try dg.typeToIndex(ptr_ty, .complete); - const ptr = mod.intern_pool.indexToKey(ptr_val).ptr; + const ptr_child_cty = dg.indexToCType(ptr_cty).cast(CType.Payload.Child).?.data; + const ptr = ip.indexToKey(ptr_val).ptr; switch (ptr.addr) { - .decl => |d| try dg.renderDeclValue(writer, ptr_ty, Value.fromInterned(ptr_val), d, location), - .anon_decl => |anon_decl| try dg.renderAnonDeclValue(writer, ptr_ty, Value.fromInterned(ptr_val), anon_decl, location), + .decl => |d| try dg.renderDeclValue(writer, Value.fromInterned(ptr_val), d, location), + .anon_decl => |anon_decl| try dg.renderAnonDeclValue(writer, Value.fromInterned(ptr_val), anon_decl, location), .int => |int| { try writer.writeByte('('); try dg.renderCType(writer, ptr_cty); - try writer.print("){x}", .{try dg.fmtIntLiteral(Type.usize, Value.fromInterned(int), .Other)}); + try writer.print("){x}", .{try dg.fmtIntLiteral(Value.fromInterned(int), .Other)}); }, .eu_payload, .opt_payload => |base| { - const ptr_base_ty = Type.fromInterned(mod.intern_pool.typeOf(base)); - const base_ty = ptr_base_ty.childType(mod); + const ptr_base_ty = Type.fromInterned(ip.typeOf(base)); + const base_ty = ptr_base_ty.childType(zcu); // Ensure complete type definition is visible before accessing fields. _ = try dg.typeToIndex(base_ty, .complete); const payload_ty = switch (ptr.addr) { - .eu_payload => base_ty.errorUnionPayload(mod), - .opt_payload => base_ty.optionalChild(mod), + .eu_payload => base_ty.errorUnionPayload(zcu), + .opt_payload => base_ty.optionalChild(zcu), else => unreachable, }; - const ptr_payload_ty = try mod.adjustPtrTypeChild(ptr_base_ty, payload_ty); - const ptr_payload_cty = try dg.typeToIndex(ptr_payload_ty, .complete); - if (ptr_cty != ptr_payload_cty) { + const payload_cty = try dg.typeToIndex(payload_ty, .forward); + if (ptr_child_cty != payload_cty) { try writer.writeByte('('); try dg.renderCType(writer, ptr_cty); try writer.writeByte(')'); @@ -725,70 +752,90 @@ pub const DeclGen = struct { try writer.writeAll(")->payload"); }, .elem => |elem| { - const ptr_base_ty = Type.fromInterned(mod.intern_pool.typeOf(elem.base)); - const elem_ty = ptr_base_ty.elemType2(mod); - const ptr_elem_ty = try mod.adjustPtrTypeChild(ptr_base_ty, elem_ty); - const ptr_elem_cty = try dg.typeToIndex(ptr_elem_ty, .complete); - if (ptr_cty != ptr_elem_cty) { + const ptr_base_ty = Type.fromInterned(ip.typeOf(elem.base)); + const elem_ty = ptr_base_ty.elemType2(zcu); + const elem_cty = try dg.typeToIndex(elem_ty, .forward); + if (ptr_child_cty != elem_cty) { try writer.writeByte('('); try dg.renderCType(writer, ptr_cty); try writer.writeByte(')'); } try writer.writeAll("&("); - if (mod.intern_pool.indexToKey(ptr_base_ty.toIntern()).ptr_type.flags.size == .One) + if (ip.indexToKey(ptr_base_ty.toIntern()).ptr_type.flags.size == .One) try writer.writeByte('*'); try dg.renderParentPtr(writer, elem.base, location); try writer.print(")[{d}]", .{elem.index}); }, .field => |field| { - const ptr_base_ty = Type.fromInterned(mod.intern_pool.typeOf(field.base)); - const base_ty = ptr_base_ty.childType(mod); + const ptr_base_ty = Type.fromInterned(ip.typeOf(field.base)); + const base_ty = ptr_base_ty.childType(zcu); // Ensure complete type definition is visible before accessing fields. _ = try dg.typeToIndex(base_ty, .complete); - const field_ty = switch (mod.intern_pool.indexToKey(base_ty.toIntern())) { - .anon_struct_type, .struct_type, .union_type => base_ty.structFieldType(@as(usize, @intCast(field.index)), mod), - .ptr_type => |ptr_type| switch (ptr_type.flags.size) { - .One, .Many, .C => unreachable, - .Slice => switch (field.index) { - Value.slice_ptr_index => base_ty.slicePtrFieldType(mod), - Value.slice_len_index => Type.usize, - else => unreachable, - }, + switch (fieldLocation(ptr_base_ty, ptr_ty, @as(u32, @intCast(field.index)), zcu)) { + .begin => { + const ptr_base_cty = try dg.typeToIndex(ptr_base_ty, .complete); + if (ptr_cty != ptr_base_cty) { + try writer.writeByte('('); + try dg.renderCType(writer, ptr_cty); + try writer.writeByte(')'); + } + try dg.renderParentPtr(writer, field.base, location); }, - else => unreachable, - }; - const ptr_field_ty = try mod.adjustPtrTypeChild(ptr_base_ty, field_ty); - const ptr_field_cty = try dg.typeToIndex(ptr_field_ty, .complete); - if (ptr_cty != ptr_field_cty) { - try writer.writeByte('('); - try dg.renderCType(writer, ptr_cty); - try writer.writeByte(')'); - } - switch (fieldLocation(ptr_base_ty, ptr_ty, @as(u32, @intCast(field.index)), mod)) { - .begin => try dg.renderParentPtr(writer, field.base, location), .field => |name| { + const field_ty = switch (ip.indexToKey(base_ty.toIntern())) { + .anon_struct_type, + .struct_type, + .union_type, + => base_ty.structFieldType(@as(usize, @intCast(field.index)), zcu), + .ptr_type => |ptr_type| switch (ptr_type.flags.size) { + .One, .Many, .C => unreachable, + .Slice => switch (field.index) { + Value.slice_ptr_index => base_ty.slicePtrFieldType(zcu), + Value.slice_len_index => Type.usize, + else => unreachable, + }, + }, + else => unreachable, + }; + const field_cty = try dg.typeToIndex(field_ty, .forward); + if (ptr_child_cty != field_cty) { + try writer.writeByte('('); + try dg.renderCType(writer, ptr_cty); + try writer.writeByte(')'); + } try writer.writeAll("&("); try dg.renderParentPtr(writer, field.base, location); try writer.writeAll(")->"); try dg.writeCValue(writer, name); }, .byte_offset => |byte_offset| { - const u8_ptr_ty = try mod.adjustPtrTypeChild(ptr_ty, Type.u8); - const byte_offset_val = try mod.intValue(Type.usize, byte_offset); + const u8_ptr_ty = try zcu.adjustPtrTypeChild(ptr_ty, Type.u8); + const u8_ptr_cty = try dg.typeToIndex(u8_ptr_ty, .complete); + if (ptr_cty != u8_ptr_cty) { + try writer.writeByte('('); + try dg.renderCType(writer, ptr_cty); + try writer.writeByte(')'); + } try writer.writeAll("(("); - try dg.renderType(writer, u8_ptr_ty); + try dg.renderCType(writer, u8_ptr_cty); try writer.writeByte(')'); try dg.renderParentPtr(writer, field.base, location); try writer.print(" + {})", .{ - try dg.fmtIntLiteral(Type.usize, byte_offset_val, .Other), + try dg.fmtIntLiteral(try zcu.intValue(Type.usize, byte_offset), .Other), }); }, .end => { + const ptr_base_cty = try dg.typeToIndex(ptr_base_ty, .complete); + if (ptr_cty != ptr_base_cty) { + try writer.writeByte('('); + try dg.renderCType(writer, ptr_cty); + try writer.writeByte(')'); + } try writer.writeAll("(("); try dg.renderParentPtr(writer, field.base, location); try writer.print(") + {})", .{ - try dg.fmtIntLiteral(Type.usize, try mod.intValue(Type.usize, 1), .Other), + try dg.fmtIntLiteral(try zcu.intValue(Type.usize, 1), .Other), }); }, } @@ -800,215 +847,21 @@ pub const DeclGen = struct { fn renderValue( dg: *DeclGen, writer: anytype, - ty: Type, val: Value, location: ValueRenderLocation, ) error{ OutOfMemory, AnalysisFail }!void { - const mod = dg.module; - const ip = &mod.intern_pool; + const zcu = dg.zcu; + const ip = &zcu.intern_pool; + const target = &dg.mod.resolved_target.result; - const target = mod.getTarget(); const initializer_type: ValueRenderLocation = switch (location) { .StaticInitializer => .StaticInitializer, else => .Initializer, }; - const safety_on = switch (mod.optimizeMode()) { - .Debug, .ReleaseSafe => true, - .ReleaseFast, .ReleaseSmall => false, - }; - - if (val.isUndefDeep(mod)) { - switch (ty.zigTypeTag(mod)) { - .Bool => { - if (safety_on) { - return writer.writeAll("0xaa"); - } else { - return writer.writeAll("false"); - } - }, - .Int, .Enum, .ErrorSet => return writer.print("{x}", .{try dg.fmtIntLiteral(ty, val, location)}), - .Float => { - const bits = ty.floatBits(target); - // All unsigned ints matching float types are pre-allocated. - const repr_ty = mod.intType(.unsigned, bits) catch unreachable; - - try writer.writeAll("zig_make_"); - try dg.renderTypeForBuiltinFnName(writer, ty); - try writer.writeByte('('); - switch (bits) { - 16 => try writer.print("{x}", .{@as(f16, @bitCast(undefPattern(i16)))}), - 32 => try writer.print("{x}", .{@as(f32, @bitCast(undefPattern(i32)))}), - 64 => try writer.print("{x}", .{@as(f64, @bitCast(undefPattern(i64)))}), - 80 => try writer.print("{x}", .{@as(f80, @bitCast(undefPattern(i80)))}), - 128 => try writer.print("{x}", .{@as(f128, @bitCast(undefPattern(i128)))}), - else => unreachable, - } - try writer.writeAll(", "); - try dg.renderValue(writer, repr_ty, Value.undef, .FunctionArgument); - return writer.writeByte(')'); - }, - .Pointer => if (ty.isSlice(mod)) { - if (!location.isInitializer()) { - try writer.writeByte('('); - try dg.renderType(writer, ty); - try writer.writeByte(')'); - } - - try writer.writeAll("{("); - const ptr_ty = ty.slicePtrFieldType(mod); - try dg.renderType(writer, ptr_ty); - return writer.print("){x}, {0x}}}", .{try dg.fmtIntLiteral(Type.usize, val, .Other)}); - } else { - try writer.writeAll("(("); - try dg.renderType(writer, ty); - return writer.print("){x})", .{try dg.fmtIntLiteral(Type.usize, val, .Other)}); - }, - .Optional => { - const payload_ty = ty.optionalChild(mod); - - if (!payload_ty.hasRuntimeBitsIgnoreComptime(mod)) { - return dg.renderValue(writer, Type.bool, val, location); - } - - if (ty.optionalReprIsPayload(mod)) { - return dg.renderValue(writer, payload_ty, val, location); - } - - if (!location.isInitializer()) { - try writer.writeByte('('); - try dg.renderType(writer, ty); - try writer.writeByte(')'); - } - - try writer.writeAll("{ .payload = "); - try dg.renderValue(writer, payload_ty, val, initializer_type); - try writer.writeAll(", .is_null = "); - try dg.renderValue(writer, Type.bool, val, initializer_type); - return writer.writeAll(" }"); - }, - .Struct => switch (ty.containerLayout(mod)) { - .auto, .@"extern" => { - if (!location.isInitializer()) { - try writer.writeByte('('); - try dg.renderType(writer, ty); - try writer.writeByte(')'); - } - - try writer.writeByte('{'); - var empty = true; - for (0..ty.structFieldCount(mod)) |field_index| { - if (ty.structFieldIsComptime(field_index, mod)) continue; - const field_ty = ty.structFieldType(field_index, mod); - if (!field_ty.hasRuntimeBits(mod)) continue; - - if (!empty) try writer.writeByte(','); - try dg.renderValue(writer, field_ty, val, initializer_type); - - empty = false; - } - - return writer.writeByte('}'); - }, - .@"packed" => return writer.print("{x}", .{try dg.fmtIntLiteral(ty, Value.undef, .Other)}), - }, - .Union => { - if (!location.isInitializer()) { - try writer.writeByte('('); - try dg.renderType(writer, ty); - try writer.writeByte(')'); - } - - try writer.writeByte('{'); - if (ty.unionTagTypeSafety(mod)) |tag_ty| { - const layout = ty.unionGetLayout(mod); - if (layout.tag_size != 0) { - try writer.writeAll(" .tag = "); - try dg.renderValue(writer, tag_ty, val, initializer_type); - } - if (ty.unionHasAllZeroBitFieldTypes(mod)) return try writer.writeByte('}'); - if (layout.tag_size != 0) try writer.writeByte(','); - try writer.writeAll(" .payload = {"); - } - const union_obj = mod.typeToUnion(ty).?; - for (0..union_obj.field_types.len) |field_index| { - const field_ty = Type.fromInterned(union_obj.field_types.get(ip)[field_index]); - if (!field_ty.hasRuntimeBits(mod)) continue; - try dg.renderValue(writer, field_ty, val, initializer_type); - break; - } - if (ty.unionTagTypeSafety(mod)) |_| try writer.writeByte('}'); - return writer.writeByte('}'); - }, - .ErrorUnion => { - const payload_ty = ty.errorUnionPayload(mod); - const error_ty = ty.errorUnionSet(mod); - - if (!payload_ty.hasRuntimeBitsIgnoreComptime(mod)) { - return dg.renderValue(writer, error_ty, val, location); - } - - if (!location.isInitializer()) { - try writer.writeByte('('); - try dg.renderType(writer, ty); - try writer.writeByte(')'); - } - - try writer.writeAll("{ .payload = "); - try dg.renderValue(writer, payload_ty, val, initializer_type); - try writer.writeAll(", .error = "); - try dg.renderValue(writer, error_ty, val, initializer_type); - return writer.writeAll(" }"); - }, - .Array, .Vector => { - const ai = ty.arrayInfo(mod); - if (ai.elem_type.eql(Type.u8, mod)) { - const c_len = ty.arrayLenIncludingSentinel(mod); - var literal = stringLiteral(writer, c_len); - try literal.start(); - var index: u64 = 0; - while (index < c_len) : (index += 1) - try literal.writeChar(0xaa); - return literal.end(); - } else { - if (!location.isInitializer()) { - try writer.writeByte('('); - try dg.renderType(writer, ty); - try writer.writeByte(')'); - } - - try writer.writeByte('{'); - const c_len = ty.arrayLenIncludingSentinel(mod); - var index: u64 = 0; - while (index < c_len) : (index += 1) { - if (index > 0) try writer.writeAll(", "); - try dg.renderValue(writer, ty.childType(mod), val, initializer_type); - } - return writer.writeByte('}'); - } - }, - .ComptimeInt, - .ComptimeFloat, - .Type, - .EnumLiteral, - .Void, - .NoReturn, - .Undefined, - .Null, - .Opaque, - => unreachable, - - .Fn, - .Frame, - .AnyFrame, - => |tag| return dg.fail("TODO: C backend: implement value of type {s}", .{ - @tagName(tag), - }), - } - unreachable; - } - - switch (ip.indexToKey(val.ip_index)) { + const ty = val.typeOf(zcu); + if (val.isUndefDeep(zcu)) return dg.renderUndefValue(writer, ty, location); + switch (ip.indexToKey(val.toIntern())) { // types, not values .int_type, .ptr_type, @@ -1050,26 +903,28 @@ pub const DeclGen = struct { .empty_enum_value, => unreachable, // non-runtime values .int => |int| switch (int.storage) { - .u64, .i64, .big_int => try writer.print("{}", .{try dg.fmtIntLiteral(ty, val, location)}), + .u64, .i64, .big_int => try writer.print("{}", .{try dg.fmtIntLiteral(val, location)}), .lazy_align, .lazy_size => { try writer.writeAll("(("); try dg.renderType(writer, ty); - return writer.print("){x})", .{try dg.fmtIntLiteral(Type.usize, val, .Other)}); + try writer.print("){x})", .{try dg.fmtIntLiteral( + try zcu.intValue(Type.usize, val.toUnsignedInt(zcu)), + .Other, + )}); }, }, .err => |err| try writer.print("zig_error_{}", .{ fmtIdent(ip.stringToSlice(err.name)), }), .error_union => |error_union| { - const payload_ty = ty.errorUnionPayload(mod); - const error_ty = ty.errorUnionSet(mod); - const err_int_ty = try mod.errorIntType(); - if (!payload_ty.hasRuntimeBitsIgnoreComptime(mod)) { + const payload_ty = ty.errorUnionPayload(zcu); + const error_ty = ty.errorUnionSet(zcu); + const err_int_ty = try zcu.errorIntType(); + if (!payload_ty.hasRuntimeBitsIgnoreComptime(zcu)) { switch (error_union.val) { .err_name => |err_name| return dg.renderValue( writer, - error_ty, - Value.fromInterned((try mod.intern(.{ .err = .{ + Value.fromInterned((try zcu.intern(.{ .err = .{ .ty = error_ty.toIntern(), .name = err_name, } }))), @@ -1077,8 +932,7 @@ pub const DeclGen = struct { ), .payload => return dg.renderValue( writer, - err_int_ty, - try mod.intValue(err_int_ty, 0), + try zcu.intValue(err_int_ty, 0), location, ), } @@ -1093,9 +947,8 @@ pub const DeclGen = struct { try writer.writeAll("{ .payload = "); try dg.renderValue( writer, - payload_ty, Value.fromInterned(switch (error_union.val) { - .err_name => try mod.intern(.{ .undef = payload_ty.ip_index }), + .err_name => (try zcu.undefValue(payload_ty)).toIntern(), .payload => |payload| payload, }), initializer_type, @@ -1104,8 +957,7 @@ pub const DeclGen = struct { switch (error_union.val) { .err_name => |err_name| try dg.renderValue( writer, - error_ty, - Value.fromInterned((try mod.intern(.{ .err = .{ + Value.fromInterned((try zcu.intern(.{ .err = .{ .ty = error_ty.toIntern(), .name = err_name, } }))), @@ -1113,24 +965,23 @@ pub const DeclGen = struct { ), .payload => try dg.renderValue( writer, - err_int_ty, - try mod.intValue(err_int_ty, 0), + try zcu.intValue(err_int_ty, 0), location, ), } try writer.writeAll(" }"); }, - .enum_tag => { - const enum_tag = ip.indexToKey(val.ip_index).enum_tag; - const int_tag_ty = ip.typeOf(enum_tag.int); - try dg.renderValue(writer, Type.fromInterned(int_tag_ty), Value.fromInterned(enum_tag.int), location); - }, + .enum_tag => |enum_tag| try dg.renderValue( + writer, + Value.fromInterned(enum_tag.int), + location, + ), .float => { - const bits = ty.floatBits(target); - const f128_val = val.toFloat(f128, mod); + const bits = ty.floatBits(target.*); + const f128_val = val.toFloat(f128, zcu); // All unsigned ints matching float types are pre-allocated. - const repr_ty = mod.intType(.unsigned, bits) catch unreachable; + const repr_ty = zcu.intType(.unsigned, bits) catch unreachable; assert(bits <= 128); var repr_val_limbs: [BigInt.calcTwosCompLimbCount(128)]BigIntLimb = undefined; @@ -1141,26 +992,24 @@ pub const DeclGen = struct { }; switch (bits) { - 16 => repr_val_big.set(@as(u16, @bitCast(val.toFloat(f16, mod)))), - 32 => repr_val_big.set(@as(u32, @bitCast(val.toFloat(f32, mod)))), - 64 => repr_val_big.set(@as(u64, @bitCast(val.toFloat(f64, mod)))), - 80 => repr_val_big.set(@as(u80, @bitCast(val.toFloat(f80, mod)))), + 16 => repr_val_big.set(@as(u16, @bitCast(val.toFloat(f16, zcu)))), + 32 => repr_val_big.set(@as(u32, @bitCast(val.toFloat(f32, zcu)))), + 64 => repr_val_big.set(@as(u64, @bitCast(val.toFloat(f64, zcu)))), + 80 => repr_val_big.set(@as(u80, @bitCast(val.toFloat(f80, zcu)))), 128 => repr_val_big.set(@as(u128, @bitCast(f128_val))), else => unreachable, } - const repr_val = try mod.intValue_big(repr_ty, repr_val_big.toConst()); - var empty = true; if (std.math.isFinite(f128_val)) { try writer.writeAll("zig_make_"); try dg.renderTypeForBuiltinFnName(writer, ty); try writer.writeByte('('); switch (bits) { - 16 => try writer.print("{x}", .{val.toFloat(f16, mod)}), - 32 => try writer.print("{x}", .{val.toFloat(f32, mod)}), - 64 => try writer.print("{x}", .{val.toFloat(f64, mod)}), - 80 => try writer.print("{x}", .{val.toFloat(f80, mod)}), + 16 => try writer.print("{x}", .{val.toFloat(f16, zcu)}), + 32 => try writer.print("{x}", .{val.toFloat(f32, zcu)}), + 64 => try writer.print("{x}", .{val.toFloat(f64, zcu)}), + 80 => try writer.print("{x}", .{val.toFloat(f80, zcu)}), 128 => try writer.print("{x}", .{f128_val}), else => unreachable, } @@ -1200,17 +1049,20 @@ pub const DeclGen = struct { if (std.math.isNan(f128_val)) switch (bits) { // We only actually need to pass the significand, but it will get // properly masked anyway, so just pass the whole value. - 16 => try writer.print("\"0x{x}\"", .{@as(u16, @bitCast(val.toFloat(f16, mod)))}), - 32 => try writer.print("\"0x{x}\"", .{@as(u32, @bitCast(val.toFloat(f32, mod)))}), - 64 => try writer.print("\"0x{x}\"", .{@as(u64, @bitCast(val.toFloat(f64, mod)))}), - 80 => try writer.print("\"0x{x}\"", .{@as(u80, @bitCast(val.toFloat(f80, mod)))}), + 16 => try writer.print("\"0x{x}\"", .{@as(u16, @bitCast(val.toFloat(f16, zcu)))}), + 32 => try writer.print("\"0x{x}\"", .{@as(u32, @bitCast(val.toFloat(f32, zcu)))}), + 64 => try writer.print("\"0x{x}\"", .{@as(u64, @bitCast(val.toFloat(f64, zcu)))}), + 80 => try writer.print("\"0x{x}\"", .{@as(u80, @bitCast(val.toFloat(f80, zcu)))}), 128 => try writer.print("\"0x{x}\"", .{@as(u128, @bitCast(f128_val))}), else => unreachable, }; try writer.writeAll(", "); empty = false; } - try writer.print("{x}", .{try dg.fmtIntLiteral(repr_ty, repr_val, location)}); + try writer.print("{x}", .{try dg.fmtIntLiteral( + try zcu.intValue_big(repr_ty, repr_val_big.toConst()), + location, + )}); if (!empty) try writer.writeByte(')'); }, .slice => |slice| { @@ -1220,42 +1072,39 @@ pub const DeclGen = struct { try writer.writeByte(')'); } try writer.writeByte('{'); - try dg.renderValue(writer, ty.slicePtrFieldType(mod), Value.fromInterned(slice.ptr), initializer_type); + try dg.renderValue(writer, Value.fromInterned(slice.ptr), initializer_type); try writer.writeAll(", "); - try dg.renderValue(writer, Type.usize, Value.fromInterned(slice.len), initializer_type); + try dg.renderValue(writer, Value.fromInterned(slice.len), initializer_type); try writer.writeByte('}'); }, .ptr => |ptr| switch (ptr.addr) { - .decl => |d| try dg.renderDeclValue(writer, ty, val, d, location), - .anon_decl => |decl_val| try dg.renderAnonDeclValue(writer, ty, val, decl_val, location), + .decl => |d| try dg.renderDeclValue(writer, val, d, location), + .anon_decl => |decl_val| try dg.renderAnonDeclValue(writer, val, decl_val, location), .int => |int| { try writer.writeAll("(("); try dg.renderType(writer, ty); - try writer.print("){x})", .{ - try dg.fmtIntLiteral(Type.usize, Value.fromInterned(int), location), - }); + try writer.print("){x})", .{try dg.fmtIntLiteral(Value.fromInterned(int), location)}); }, .eu_payload, .opt_payload, .elem, .field, - => try dg.renderParentPtr(writer, val.ip_index, location), + => try dg.renderParentPtr(writer, val.toIntern(), location), .comptime_field, .comptime_alloc => unreachable, }, .opt => |opt| { - const payload_ty = ty.optionalChild(mod); + const payload_ty = ty.optionalChild(zcu); const is_null_val = Value.makeBool(opt.val == .none); - if (!payload_ty.hasRuntimeBitsIgnoreComptime(mod)) - return dg.renderValue(writer, Type.bool, is_null_val, location); + if (!payload_ty.hasRuntimeBitsIgnoreComptime(zcu)) + return dg.renderValue(writer, is_null_val, location); - if (ty.optionalReprIsPayload(mod)) return dg.renderValue( + if (ty.optionalReprIsPayload(zcu)) return dg.renderValue( writer, - payload_ty, switch (opt.val) { - .none => switch (payload_ty.zigTypeTag(mod)) { - .ErrorSet => try mod.intValue(try mod.errorIntType(), 0), - .Pointer => try mod.getCoerced(val, payload_ty), + .none => switch (payload_ty.zigTypeTag(zcu)) { + .ErrorSet => try zcu.intValue(try zcu.errorIntType(), 0), + .Pointer => try zcu.getCoerced(val, payload_ty), else => unreachable, }, else => |payload| Value.fromInterned(payload), @@ -1270,15 +1119,19 @@ pub const DeclGen = struct { } try writer.writeAll("{ .payload = "); - try dg.renderValue(writer, payload_ty, Value.fromInterned(switch (opt.val) { - .none => try mod.intern(.{ .undef = payload_ty.ip_index }), - else => |payload| payload, - }), initializer_type); + switch (opt.val) { + .none => try dg.renderUndefValue(writer, payload_ty, initializer_type), + else => |payload| try dg.renderValue( + writer, + Value.fromInterned(payload), + initializer_type, + ), + } try writer.writeAll(", .is_null = "); - try dg.renderValue(writer, Type.bool, is_null_val, initializer_type); + try dg.renderValue(writer, is_null_val, initializer_type); try writer.writeAll(" }"); }, - .aggregate => switch (ip.indexToKey(ty.ip_index)) { + .aggregate => switch (ip.indexToKey(ty.toIntern())) { .array_type, .vector_type => { if (location == .FunctionArgument) { try writer.writeByte('('); @@ -1287,21 +1140,21 @@ pub const DeclGen = struct { } // Fall back to generic implementation. - const ai = ty.arrayInfo(mod); - if (ai.elem_type.eql(Type.u8, mod)) { - var literal = stringLiteral(writer, ty.arrayLenIncludingSentinel(mod)); + const ai = ty.arrayInfo(zcu); + if (ai.elem_type.eql(Type.u8, zcu)) { + var literal = stringLiteral(writer, ty.arrayLenIncludingSentinel(zcu)); try literal.start(); var index: usize = 0; while (index < ai.len) : (index += 1) { - const elem_val = try val.elemValue(mod, index); - const elem_val_u8: u8 = if (elem_val.isUndef(mod)) + const elem_val = try val.elemValue(zcu, index); + const elem_val_u8: u8 = if (elem_val.isUndef(zcu)) undefPattern(u8) else - @intCast(elem_val.toUnsignedInt(mod)); + @intCast(elem_val.toUnsignedInt(zcu)); try literal.writeChar(elem_val_u8); } if (ai.sentinel) |s| { - const s_u8: u8 = @intCast(s.toUnsignedInt(mod)); + const s_u8: u8 = @intCast(s.toUnsignedInt(zcu)); if (s_u8 != 0) try literal.writeChar(s_u8); } try literal.end(); @@ -1310,12 +1163,12 @@ pub const DeclGen = struct { var index: usize = 0; while (index < ai.len) : (index += 1) { if (index != 0) try writer.writeByte(','); - const elem_val = try val.elemValue(mod, index); - try dg.renderValue(writer, ai.elem_type, elem_val, initializer_type); + const elem_val = try val.elemValue(zcu, index); + try dg.renderValue(writer, elem_val, initializer_type); } if (ai.sentinel) |s| { if (index != 0) try writer.writeByte(','); - try dg.renderValue(writer, ai.elem_type, s, initializer_type); + try dg.renderValue(writer, s, initializer_type); } try writer.writeByte('}'); } @@ -1333,19 +1186,21 @@ pub const DeclGen = struct { const comptime_val = tuple.values.get(ip)[field_index]; if (comptime_val != .none) continue; const field_ty = Type.fromInterned(tuple.types.get(ip)[field_index]); - if (!field_ty.hasRuntimeBitsIgnoreComptime(mod)) continue; + if (!field_ty.hasRuntimeBitsIgnoreComptime(zcu)) continue; if (!empty) try writer.writeByte(','); - const field_val = Value.fromInterned(switch (ip.indexToKey(val.ip_index).aggregate.storage) { - .bytes => |bytes| try ip.get(mod.gpa, .{ .int = .{ - .ty = field_ty.toIntern(), - .storage = .{ .u64 = bytes[field_index] }, - } }), - .elems => |elems| elems[field_index], - .repeated_elem => |elem| elem, - }); - try dg.renderValue(writer, field_ty, field_val, initializer_type); + const field_val = Value.fromInterned( + switch (ip.indexToKey(val.toIntern()).aggregate.storage) { + .bytes => |bytes| try ip.get(zcu.gpa, .{ .int = .{ + .ty = field_ty.toIntern(), + .storage = .{ .u64 = bytes[field_index] }, + } }), + .elems => |elems| elems[field_index], + .repeated_elem => |elem| elem, + }, + ); + try dg.renderValue(writer, field_val, initializer_type); empty = false; } @@ -1366,43 +1221,43 @@ pub const DeclGen = struct { for (0..struct_type.field_types.len) |field_index| { const field_ty = Type.fromInterned(struct_type.field_types.get(ip)[field_index]); if (struct_type.fieldIsComptime(ip, field_index)) continue; - if (!field_ty.hasRuntimeBitsIgnoreComptime(mod)) continue; + if (!field_ty.hasRuntimeBitsIgnoreComptime(zcu)) continue; if (!empty) try writer.writeByte(','); - const field_val = switch (ip.indexToKey(val.ip_index).aggregate.storage) { - .bytes => |bytes| try ip.get(mod.gpa, .{ .int = .{ + const field_val = switch (ip.indexToKey(val.toIntern()).aggregate.storage) { + .bytes => |bytes| try ip.get(zcu.gpa, .{ .int = .{ .ty = field_ty.toIntern(), .storage = .{ .u64 = bytes[field_index] }, } }), .elems => |elems| elems[field_index], .repeated_elem => |elem| elem, }; - try dg.renderValue(writer, field_ty, Value.fromInterned(field_val), initializer_type); + try dg.renderValue(writer, Value.fromInterned(field_val), initializer_type); empty = false; } try writer.writeByte('}'); }, .@"packed" => { - const int_info = ty.intInfo(mod); + const int_info = ty.intInfo(zcu); const bits = Type.smallestUnsignedBits(int_info.bits - 1); - const bit_offset_ty = try mod.intType(.unsigned, bits); + const bit_offset_ty = try zcu.intType(.unsigned, bits); var bit_offset: u64 = 0; var eff_num_fields: usize = 0; for (0..struct_type.field_types.len) |field_index| { const field_ty = Type.fromInterned(struct_type.field_types.get(ip)[field_index]); - if (!field_ty.hasRuntimeBitsIgnoreComptime(mod)) continue; + if (!field_ty.hasRuntimeBitsIgnoreComptime(zcu)) continue; eff_num_fields += 1; } if (eff_num_fields == 0) { try writer.writeByte('('); - try dg.renderValue(writer, ty, Value.undef, initializer_type); + try dg.renderUndefValue(writer, ty, initializer_type); try writer.writeByte(')'); - } else if (ty.bitSize(mod) > 64) { + } else if (ty.bitSize(zcu) > 64) { // zig_or_u128(zig_or_u128(zig_shl_u128(a, a_off), zig_shl_u128(b, b_off)), zig_shl_u128(c, c_off)) var num_or = eff_num_fields - 1; while (num_or > 0) : (num_or -= 1) { @@ -1415,10 +1270,10 @@ pub const DeclGen = struct { var needs_closing_paren = false; for (0..struct_type.field_types.len) |field_index| { const field_ty = Type.fromInterned(struct_type.field_types.get(ip)[field_index]); - if (!field_ty.hasRuntimeBitsIgnoreComptime(mod)) continue; + if (!field_ty.hasRuntimeBitsIgnoreComptime(zcu)) continue; - const field_val = switch (ip.indexToKey(val.ip_index).aggregate.storage) { - .bytes => |bytes| try ip.get(mod.gpa, .{ .int = .{ + const field_val = switch (ip.indexToKey(val.toIntern()).aggregate.storage) { + .bytes => |bytes| try ip.get(zcu.gpa, .{ .int = .{ .ty = field_ty.toIntern(), .storage = .{ .u64 = bytes[field_index] }, } }), @@ -1432,8 +1287,7 @@ pub const DeclGen = struct { try writer.writeByte('('); try dg.renderIntCast(writer, ty, cast_context, field_ty, .FunctionArgument); try writer.writeAll(", "); - const bit_offset_val = try mod.intValue(bit_offset_ty, bit_offset); - try dg.renderValue(writer, bit_offset_ty, bit_offset_val, .FunctionArgument); + try dg.renderValue(writer, try zcu.intValue(bit_offset_ty, bit_offset), .FunctionArgument); try writer.writeByte(')'); } else { try dg.renderIntCast(writer, ty, cast_context, field_ty, .FunctionArgument); @@ -1442,7 +1296,7 @@ pub const DeclGen = struct { if (needs_closing_paren) try writer.writeByte(')'); if (eff_index != eff_num_fields - 1) try writer.writeAll(", "); - bit_offset += field_ty.bitSize(mod); + bit_offset += field_ty.bitSize(zcu); needs_closing_paren = true; eff_index += 1; } @@ -1452,15 +1306,15 @@ pub const DeclGen = struct { var empty = true; for (0..struct_type.field_types.len) |field_index| { const field_ty = Type.fromInterned(struct_type.field_types.get(ip)[field_index]); - if (!field_ty.hasRuntimeBitsIgnoreComptime(mod)) continue; + if (!field_ty.hasRuntimeBitsIgnoreComptime(zcu)) continue; if (!empty) try writer.writeAll(" | "); try writer.writeByte('('); try dg.renderType(writer, ty); try writer.writeByte(')'); - const field_val = switch (ip.indexToKey(val.ip_index).aggregate.storage) { - .bytes => |bytes| try ip.get(mod.gpa, .{ .int = .{ + const field_val = switch (ip.indexToKey(val.toIntern()).aggregate.storage) { + .bytes => |bytes| try ip.get(zcu.gpa, .{ .int = .{ .ty = field_ty.toIntern(), .storage = .{ .u64 = bytes[field_index] }, } }), @@ -1469,15 +1323,14 @@ pub const DeclGen = struct { }; if (bit_offset != 0) { - try dg.renderValue(writer, field_ty, Value.fromInterned(field_val), .Other); + try dg.renderValue(writer, Value.fromInterned(field_val), .Other); try writer.writeAll(" << "); - const bit_offset_val = try mod.intValue(bit_offset_ty, bit_offset); - try dg.renderValue(writer, bit_offset_ty, bit_offset_val, .FunctionArgument); + try dg.renderValue(writer, try zcu.intValue(bit_offset_ty, bit_offset), .FunctionArgument); } else { - try dg.renderValue(writer, field_ty, Value.fromInterned(field_val), .Other); + try dg.renderValue(writer, Value.fromInterned(field_val), .Other); } - bit_offset += field_ty.bitSize(mod); + bit_offset += field_ty.bitSize(zcu); empty = false; } try writer.writeByte(')'); @@ -1488,9 +1341,9 @@ pub const DeclGen = struct { else => unreachable, }, .un => |un| { - const union_obj = mod.typeToUnion(ty).?; + const union_obj = zcu.typeToUnion(ty).?; if (un.tag == .none) { - const backing_ty = try ty.unionBackingType(mod); + const backing_ty = try ty.unionBackingType(zcu); switch (union_obj.getLayout(ip)) { .@"packed" => { if (!location.isInitializer()) { @@ -1498,20 +1351,20 @@ pub const DeclGen = struct { try dg.renderType(writer, backing_ty); try writer.writeByte(')'); } - try dg.renderValue(writer, backing_ty, Value.fromInterned(un.val), initializer_type); + try dg.renderValue(writer, Value.fromInterned(un.val), initializer_type); }, .@"extern" => { if (location == .StaticInitializer) { return dg.fail("TODO: C backend: implement extern union backing type rendering in static initializers", .{}); } - const ptr_ty = try mod.singleConstPtrType(ty); + const ptr_ty = try zcu.singleConstPtrType(ty); try writer.writeAll("*(("); try dg.renderType(writer, ptr_ty); try writer.writeAll(")("); try dg.renderType(writer, backing_ty); try writer.writeAll("){"); - try dg.renderValue(writer, backing_ty, Value.fromInterned(un.val), initializer_type); + try dg.renderValue(writer, Value.fromInterned(un.val), initializer_type); try writer.writeAll("})"); }, else => unreachable, @@ -1523,21 +1376,21 @@ pub const DeclGen = struct { try writer.writeByte(')'); } - const field_index = mod.unionTagFieldIndex(union_obj, Value.fromInterned(un.tag)).?; + const field_index = zcu.unionTagFieldIndex(union_obj, Value.fromInterned(un.tag)).?; const field_ty = Type.fromInterned(union_obj.field_types.get(ip)[field_index]); const field_name = union_obj.loadTagType(ip).names.get(ip)[field_index]; if (union_obj.getLayout(ip) == .@"packed") { - if (field_ty.hasRuntimeBits(mod)) { - if (field_ty.isPtrAtRuntime(mod)) { + if (field_ty.hasRuntimeBits(zcu)) { + if (field_ty.isPtrAtRuntime(zcu)) { try writer.writeByte('('); try dg.renderType(writer, ty); try writer.writeByte(')'); - } else if (field_ty.zigTypeTag(mod) == .Float) { + } else if (field_ty.zigTypeTag(zcu) == .Float) { try writer.writeByte('('); try dg.renderType(writer, ty); try writer.writeByte(')'); } - try dg.renderValue(writer, field_ty, Value.fromInterned(un.val), initializer_type); + try dg.renderValue(writer, Value.fromInterned(un.val), initializer_type); } else { try writer.writeAll("0"); } @@ -1545,30 +1398,236 @@ pub const DeclGen = struct { } try writer.writeByte('{'); - if (ty.unionTagTypeSafety(mod)) |tag_ty| { - const layout = mod.getUnionLayout(union_obj); + if (ty.unionTagTypeSafety(zcu)) |_| { + const layout = zcu.getUnionLayout(union_obj); if (layout.tag_size != 0) { try writer.writeAll(" .tag = "); - try dg.renderValue(writer, tag_ty, Value.fromInterned(un.tag), initializer_type); + try dg.renderValue(writer, Value.fromInterned(un.tag), initializer_type); } - if (ty.unionHasAllZeroBitFieldTypes(mod)) return try writer.writeByte('}'); + if (ty.unionHasAllZeroBitFieldTypes(zcu)) return try writer.writeByte('}'); if (layout.tag_size != 0) try writer.writeByte(','); try writer.writeAll(" .payload = {"); } - if (field_ty.hasRuntimeBits(mod)) { + if (field_ty.hasRuntimeBits(zcu)) { try writer.print(" .{ } = ", .{fmtIdent(ip.stringToSlice(field_name))}); - try dg.renderValue(writer, field_ty, Value.fromInterned(un.val), initializer_type); + try dg.renderValue(writer, Value.fromInterned(un.val), initializer_type); try writer.writeByte(' '); } else for (0..union_obj.field_types.len) |this_field_index| { const this_field_ty = Type.fromInterned(union_obj.field_types.get(ip)[this_field_index]); - if (!this_field_ty.hasRuntimeBits(mod)) continue; - try dg.renderValue(writer, this_field_ty, Value.undef, initializer_type); + if (!this_field_ty.hasRuntimeBits(zcu)) continue; + try dg.renderUndefValue(writer, this_field_ty, initializer_type); break; } - if (ty.unionTagTypeSafety(mod)) |_| try writer.writeByte('}'); + if (ty.unionTagTypeSafety(zcu)) |_| try writer.writeByte('}'); + try writer.writeByte('}'); + } + }, + } + } + + fn renderUndefValue( + dg: *DeclGen, + writer: anytype, + ty: Type, + location: ValueRenderLocation, + ) error{ OutOfMemory, AnalysisFail }!void { + const zcu = dg.zcu; + const ip = &zcu.intern_pool; + const target = &dg.mod.resolved_target.result; + + const initializer_type: ValueRenderLocation = switch (location) { + .StaticInitializer => .StaticInitializer, + else => .Initializer, + }; + + const safety_on = switch (zcu.optimizeMode()) { + .Debug, .ReleaseSafe => true, + .ReleaseFast, .ReleaseSmall => false, + }; + + switch (ty.zigTypeTag(zcu)) { + .Bool => try writer.writeAll(if (safety_on) "0xaa" else "false"), + .Int, .Enum, .ErrorSet => try writer.print("{x}", .{ + try dg.fmtIntLiteral(try zcu.undefValue(ty), location), + }), + .Float => { + const bits = ty.floatBits(target.*); + // All unsigned ints matching float types are pre-allocated. + const repr_ty = zcu.intType(.unsigned, bits) catch unreachable; + + try writer.writeAll("zig_make_"); + try dg.renderTypeForBuiltinFnName(writer, ty); + try writer.writeByte('('); + switch (bits) { + 16 => try writer.print("{x}", .{@as(f16, @bitCast(undefPattern(i16)))}), + 32 => try writer.print("{x}", .{@as(f32, @bitCast(undefPattern(i32)))}), + 64 => try writer.print("{x}", .{@as(f64, @bitCast(undefPattern(i64)))}), + 80 => try writer.print("{x}", .{@as(f80, @bitCast(undefPattern(i80)))}), + 128 => try writer.print("{x}", .{@as(f128, @bitCast(undefPattern(i128)))}), + else => unreachable, + } + try writer.writeAll(", "); + try dg.renderUndefValue(writer, repr_ty, .FunctionArgument); + try writer.writeByte(')'); + }, + .Pointer => if (ty.isSlice(zcu)) { + if (!location.isInitializer()) { + try writer.writeByte('('); + try dg.renderType(writer, ty); + try writer.writeByte(')'); + } + + try writer.writeAll("{("); + const ptr_ty = ty.slicePtrFieldType(zcu); + try dg.renderType(writer, ptr_ty); + try writer.print("){x}, {0x}}}", .{try dg.fmtIntLiteral(try zcu.undefValue(Type.usize), .Other)}); + } else { + try writer.writeAll("(("); + try dg.renderType(writer, ty); + try writer.print("){x})", .{try dg.fmtIntLiteral(try zcu.undefValue(Type.usize), .Other)}); + }, + .Optional => { + const payload_ty = ty.optionalChild(zcu); + + if (!payload_ty.hasRuntimeBitsIgnoreComptime(zcu)) { + return dg.renderUndefValue(writer, Type.bool, location); + } + + if (ty.optionalReprIsPayload(zcu)) { + return dg.renderUndefValue(writer, payload_ty, location); + } + + if (!location.isInitializer()) { + try writer.writeByte('('); + try dg.renderType(writer, ty); + try writer.writeByte(')'); + } + + try writer.writeAll("{ .payload = "); + try dg.renderUndefValue(writer, payload_ty, initializer_type); + try writer.writeAll(", .is_null = "); + try dg.renderUndefValue(writer, Type.bool, initializer_type); + try writer.writeAll(" }"); + }, + .Struct => switch (ty.containerLayout(zcu)) { + .auto, .@"extern" => { + if (!location.isInitializer()) { + try writer.writeByte('('); + try dg.renderType(writer, ty); + try writer.writeByte(')'); + } + + try writer.writeByte('{'); + var empty = true; + for (0..ty.structFieldCount(zcu)) |field_index| { + if (ty.structFieldIsComptime(field_index, zcu)) continue; + const field_ty = ty.structFieldType(field_index, zcu); + if (!field_ty.hasRuntimeBits(zcu)) continue; + + if (!empty) try writer.writeByte(','); + try dg.renderUndefValue(writer, field_ty, initializer_type); + + empty = false; + } + try writer.writeByte('}'); + }, + .@"packed" => try writer.print("{x}", .{ + try dg.fmtIntLiteral(try zcu.undefValue(ty), .Other), + }), + }, + .Union => { + if (!location.isInitializer()) { + try writer.writeByte('('); + try dg.renderType(writer, ty); + try writer.writeByte(')'); } + + try writer.writeByte('{'); + if (ty.unionTagTypeSafety(zcu)) |tag_ty| { + const layout = ty.unionGetLayout(zcu); + if (layout.tag_size != 0) { + try writer.writeAll(" .tag = "); + try dg.renderUndefValue(writer, tag_ty, initializer_type); + } + if (ty.unionHasAllZeroBitFieldTypes(zcu)) return try writer.writeByte('}'); + if (layout.tag_size != 0) try writer.writeByte(','); + try writer.writeAll(" .payload = {"); + } + const union_obj = zcu.typeToUnion(ty).?; + for (0..union_obj.field_types.len) |field_index| { + const field_ty = Type.fromInterned(union_obj.field_types.get(ip)[field_index]); + if (!field_ty.hasRuntimeBits(zcu)) continue; + try dg.renderUndefValue(writer, field_ty, initializer_type); + break; + } + if (ty.unionTagTypeSafety(zcu)) |_| try writer.writeByte('}'); + try writer.writeByte('}'); }, + .ErrorUnion => { + const payload_ty = ty.errorUnionPayload(zcu); + const error_ty = ty.errorUnionSet(zcu); + + if (!payload_ty.hasRuntimeBitsIgnoreComptime(zcu)) { + return dg.renderUndefValue(writer, error_ty, location); + } + + if (!location.isInitializer()) { + try writer.writeByte('('); + try dg.renderType(writer, ty); + try writer.writeByte(')'); + } + + try writer.writeAll("{ .payload = "); + try dg.renderUndefValue(writer, payload_ty, initializer_type); + try writer.writeAll(", .error = "); + try dg.renderUndefValue(writer, error_ty, initializer_type); + try writer.writeAll(" }"); + }, + .Array, .Vector => { + const ai = ty.arrayInfo(zcu); + if (ai.elem_type.eql(Type.u8, zcu)) { + const c_len = ty.arrayLenIncludingSentinel(zcu); + var literal = stringLiteral(writer, c_len); + try literal.start(); + var index: u64 = 0; + while (index < c_len) : (index += 1) + try literal.writeChar(0xaa); + try literal.end(); + } else { + if (!location.isInitializer()) { + try writer.writeByte('('); + try dg.renderType(writer, ty); + try writer.writeByte(')'); + } + + try writer.writeByte('{'); + const c_len = ty.arrayLenIncludingSentinel(zcu); + var index: u64 = 0; + while (index < c_len) : (index += 1) { + if (index > 0) try writer.writeAll(", "); + try dg.renderUndefValue(writer, ty.childType(zcu), initializer_type); + } + try writer.writeByte('}'); + } + }, + .ComptimeInt, + .ComptimeFloat, + .Type, + .EnumLiteral, + .Void, + .NoReturn, + .Undefined, + .Null, + .Opaque, + => unreachable, + + .Fn, + .Frame, + .AnyFrame, + => |tag| return dg.fail("TODO: C backend: implement value of type {s}", .{ + @tagName(tag), + }), } } @@ -1583,14 +1642,14 @@ pub const DeclGen = struct { }, ) !void { const store = &dg.ctypes.set; - const mod = dg.module; - const ip = &mod.intern_pool; + const zcu = dg.zcu; + const ip = &zcu.intern_pool; - const fn_decl = mod.declPtr(fn_decl_index); - const fn_ty = fn_decl.typeOf(mod); + const fn_decl = zcu.declPtr(fn_decl_index); + const fn_ty = fn_decl.typeOf(zcu); const fn_cty_idx = try dg.typeToIndex(fn_ty, kind); - const fn_info = mod.typeToFunc(fn_ty).?; + const fn_info = zcu.typeToFunc(fn_ty).?; if (fn_info.cc == .Naked) { switch (kind) { .forward => try w.writeAll("zig_naked_decl "), @@ -1598,11 +1657,11 @@ pub const DeclGen = struct { else => unreachable, } } - if (fn_decl.val.getFunction(mod)) |func| if (func.analysis(ip).is_cold) + if (fn_decl.val.getFunction(zcu)) |func| if (func.analysis(ip).is_cold) try w.writeAll("zig_cold "); if (fn_info.return_type == .noreturn_type) try w.writeAll("zig_noreturn "); - var trailing = try renderTypePrefix(dg.pass, store.*, mod, w, fn_cty_idx, .suffix, .{}); + var trailing = try renderTypePrefix(dg.pass, store.*, zcu, w, fn_cty_idx, .suffix, .{}); if (toCallingConvention(fn_info.cc)) |call_conv| { try w.print("{}zig_callconv({s})", .{ trailing, call_conv }); @@ -1629,7 +1688,7 @@ pub const DeclGen = struct { try renderTypeSuffix( dg.pass, store.*, - mod, + zcu, w, fn_cty_idx, .suffix, @@ -1647,11 +1706,11 @@ pub const DeclGen = struct { } switch (name) { .export_index => |export_index| mangled: { - const maybe_exports = mod.decl_exports.get(fn_decl_index); + const maybe_exports = zcu.decl_exports.get(fn_decl_index); const external_name = ip.stringToSlice( if (maybe_exports) |exports| exports.items[export_index].opts.name - else if (fn_decl.isExtern(mod)) + else if (fn_decl.isExtern(zcu)) fn_decl.name else break :mangled, @@ -1694,15 +1753,15 @@ pub const DeclGen = struct { } fn typeToIndex(dg: *DeclGen, ty: Type, kind: CType.Kind) !CType.Index { - return dg.ctypes.typeToIndex(dg.gpa, ty, dg.module, kind); + return dg.ctypes.typeToIndex(dg.gpa, ty, dg.zcu, dg.mod, kind); } fn typeToCType(dg: *DeclGen, ty: Type, kind: CType.Kind) !CType { - return dg.ctypes.typeToCType(dg.gpa, ty, dg.module, kind); + return dg.ctypes.typeToCType(dg.gpa, ty, dg.zcu, dg.mod, kind); } fn byteSize(dg: *DeclGen, cty: CType) u64 { - return cty.byteSize(dg.ctypes.set, dg.module.getTarget()); + return cty.byteSize(dg.ctypes.set, dg.mod); } /// Renders a type as a single identifier, generating intermediate typedefs @@ -1722,9 +1781,9 @@ pub const DeclGen = struct { fn renderCType(dg: *DeclGen, w: anytype, idx: CType.Index) error{ OutOfMemory, AnalysisFail }!void { const store = &dg.ctypes.set; - const mod = dg.module; - _ = try renderTypePrefix(dg.pass, store.*, mod, w, idx, .suffix, .{}); - try renderTypeSuffix(dg.pass, store.*, mod, w, idx, .suffix, .{}); + const zcu = dg.zcu; + _ = try renderTypePrefix(dg.pass, store.*, zcu, w, idx, .suffix, .{}); + try renderTypeSuffix(dg.pass, store.*, zcu, w, idx, .suffix, .{}); } const IntCastContext = union(enum) { @@ -1737,15 +1796,13 @@ pub const DeclGen = struct { value: Value, }, - pub fn writeValue(self: *const IntCastContext, dg: *DeclGen, w: anytype, value_ty: Type, location: ValueRenderLocation) !void { + pub fn writeValue(self: *const IntCastContext, dg: *DeclGen, w: anytype, location: ValueRenderLocation) !void { switch (self.*) { .c_value => |v| { try v.f.writeCValue(w, v.value, location); try v.v.elem(v.f, w); }, - .value => |v| { - try dg.renderValue(w, value_ty, v.value, location); - }, + .value => |v| try dg.renderValue(w, v.value, location), } } }; @@ -1764,18 +1821,18 @@ pub const DeclGen = struct { /// | > 64 bit integer | < 64 bit integer | zig_make_(0, src) /// | > 64 bit integer | > 64 bit integer | zig_make_(zig_hi_(src), zig_lo_(src)) fn renderIntCast(dg: *DeclGen, w: anytype, dest_ty: Type, context: IntCastContext, src_ty: Type, location: ValueRenderLocation) !void { - const mod = dg.module; - const dest_bits = dest_ty.bitSize(mod); - const dest_int_info = dest_ty.intInfo(mod); + const zcu = dg.zcu; + const dest_bits = dest_ty.bitSize(zcu); + const dest_int_info = dest_ty.intInfo(zcu); - const src_is_ptr = src_ty.isPtrAtRuntime(mod); + const src_is_ptr = src_ty.isPtrAtRuntime(zcu); const src_eff_ty: Type = if (src_is_ptr) switch (dest_int_info.signedness) { .unsigned => Type.usize, .signed => Type.isize, } else src_ty; - const src_bits = src_eff_ty.bitSize(mod); - const src_int_info = if (src_eff_ty.isAbiInt(mod)) src_eff_ty.intInfo(mod) else null; + const src_bits = src_eff_ty.bitSize(zcu); + const src_int_info = if (src_eff_ty.isAbiInt(zcu)) src_eff_ty.intInfo(zcu) else null; if (dest_bits <= 64 and src_bits <= 64) { const needs_cast = src_int_info == null or (toCIntBits(dest_int_info.bits) != toCIntBits(src_int_info.?.bits) or @@ -1791,7 +1848,7 @@ pub const DeclGen = struct { try dg.renderType(w, src_eff_ty); try w.writeByte(')'); } - try context.writeValue(dg, w, src_ty, location); + try context.writeValue(dg, w, location); } else if (dest_bits <= 64 and src_bits > 64) { assert(!src_is_ptr); if (dest_bits < 64) { @@ -1802,7 +1859,7 @@ pub const DeclGen = struct { try w.writeAll("zig_lo_"); try dg.renderTypeForBuiltinFnName(w, src_eff_ty); try w.writeByte('('); - try context.writeValue(dg, w, src_ty, .FunctionArgument); + try context.writeValue(dg, w, .FunctionArgument); try w.writeByte(')'); } else if (dest_bits > 64 and src_bits <= 64) { try w.writeAll("zig_make_"); @@ -1813,7 +1870,7 @@ pub const DeclGen = struct { try dg.renderType(w, src_eff_ty); try w.writeByte(')'); } - try context.writeValue(dg, w, src_ty, .FunctionArgument); + try context.writeValue(dg, w, .FunctionArgument); try w.writeByte(')'); } else { assert(!src_is_ptr); @@ -1822,11 +1879,11 @@ pub const DeclGen = struct { try w.writeAll("(zig_hi_"); try dg.renderTypeForBuiltinFnName(w, src_eff_ty); try w.writeByte('('); - try context.writeValue(dg, w, src_ty, .FunctionArgument); + try context.writeValue(dg, w, .FunctionArgument); try w.writeAll("), zig_lo_"); try dg.renderTypeForBuiltinFnName(w, src_eff_ty); try w.writeByte('('); - try context.writeValue(dg, w, src_ty, .FunctionArgument); + try context.writeValue(dg, w, .FunctionArgument); try w.writeAll("))"); } } @@ -1848,8 +1905,8 @@ pub const DeclGen = struct { alignment: Alignment, kind: CType.Kind, ) error{ OutOfMemory, AnalysisFail }!void { - const mod = dg.module; - const alignas = CType.AlignAs.init(alignment, ty.abiAlignment(mod)); + const zcu = dg.zcu; + const alignas = CType.AlignAs.init(alignment, ty.abiAlignment(zcu)); try dg.renderCTypeAndName(w, try dg.typeToIndex(ty, kind), name, qualifiers, alignas); } @@ -1862,7 +1919,7 @@ pub const DeclGen = struct { alignas: CType.AlignAs, ) error{ OutOfMemory, AnalysisFail }!void { const store = &dg.ctypes.set; - const mod = dg.module; + const zcu = dg.zcu; switch (alignas.abiOrder()) { .lt => try w.print("zig_under_align({}) ", .{alignas.toByteUnits()}), @@ -1870,39 +1927,46 @@ pub const DeclGen = struct { .gt => try w.print("zig_align({}) ", .{alignas.toByteUnits()}), } - const trailing = try renderTypePrefix(dg.pass, store.*, mod, w, cty_idx, .suffix, qualifiers); + const trailing = try renderTypePrefix(dg.pass, store.*, zcu, w, cty_idx, .suffix, qualifiers); try w.print("{}", .{trailing}); - try dg.writeCValue(w, name); - try renderTypeSuffix(dg.pass, store.*, mod, w, cty_idx, .suffix, .{}); + try dg.writeName(w, name); + try renderTypeSuffix(dg.pass, store.*, zcu, w, cty_idx, .suffix, .{}); } fn declIsGlobal(dg: *DeclGen, val: Value) bool { - const mod = dg.module; - return switch (mod.intern_pool.indexToKey(val.ip_index)) { - .variable => |variable| mod.decl_exports.contains(variable.decl), + const zcu = dg.zcu; + return switch (zcu.intern_pool.indexToKey(val.toIntern())) { + .variable => |variable| zcu.decl_exports.contains(variable.decl), .extern_func => true, - .func => |func| mod.decl_exports.contains(func.owner_decl), + .func => |func| zcu.decl_exports.contains(func.owner_decl), else => unreachable, }; } + fn writeName(dg: *DeclGen, w: anytype, c_value: CValue) !void { + switch (c_value) { + .new_local, .local => |i| try w.print("t{d}", .{i}), + .constant => |val| try renderAnonDeclName(w, val), + .decl => |decl| try dg.renderDeclName(w, decl, 0), + .identifier => |ident| try w.print("{ }", .{fmtIdent(ident)}), + else => unreachable, + } + } + fn writeCValue(dg: *DeclGen, w: anytype, c_value: CValue) !void { switch (c_value) { - .none => unreachable, - .local, .new_local => |i| return w.print("t{d}", .{i}), - .local_ref => |i| return w.print("&t{d}", .{i}), - .constant => |val| return renderAnonDeclName(w, val), - .arg => |i| return w.print("a{d}", .{i}), - .arg_array => |i| return dg.writeCValueMember(w, .{ .arg = i }, .{ .identifier = "array" }), - .field => |i| return w.print("f{d}", .{i}), - .decl => |decl| return dg.renderDeclName(w, decl, 0), + .none, .new_local, .local, .local_ref => unreachable, + .constant => |val| try renderAnonDeclName(w, val), + .arg, .arg_array => unreachable, + .field => |i| try w.print("f{d}", .{i}), + .decl => |decl| try dg.renderDeclName(w, decl, 0), .decl_ref => |decl| { try w.writeByte('&'); - return dg.renderDeclName(w, decl, 0); + try dg.renderDeclName(w, decl, 0); }, - .undef => |ty| return dg.renderValue(w, ty, Value.undef, .Other), - .identifier => |ident| return w.print("{ }", .{fmtIdent(ident)}), - .payload_identifier => |ident| return w.print("{ }.{ }", .{ + .undef => |ty| try dg.renderUndefValue(w, ty, .Other), + .identifier => |ident| try w.print("{ }", .{fmtIdent(ident)}), + .payload_identifier => |ident| try w.print("{ }.{ }", .{ fmtIdent("payload"), fmtIdent(ident), }), @@ -1911,26 +1975,17 @@ pub const DeclGen = struct { fn writeCValueDeref(dg: *DeclGen, w: anytype, c_value: CValue) !void { switch (c_value) { - .none => unreachable, - .local, .new_local => |i| return w.print("(*t{d})", .{i}), - .local_ref => |i| return w.print("t{d}", .{i}), - .constant => unreachable, - .arg => |i| return w.print("(*a{d})", .{i}), - .arg_array => |i| { - try w.writeAll("(*"); - try dg.writeCValueMember(w, .{ .arg = i }, .{ .identifier = "array" }); - return w.writeByte(')'); - }, - .field => |i| return w.print("f{d}", .{i}), + .none, .new_local, .local, .local_ref, .constant, .arg, .arg_array => unreachable, + .field => |i| try w.print("f{d}", .{i}), .decl => |decl| { try w.writeAll("(*"); try dg.renderDeclName(w, decl, 0); - return w.writeByte(')'); + try w.writeByte(')'); }, - .decl_ref => |decl| return dg.renderDeclName(w, decl, 0), + .decl_ref => |decl| try dg.renderDeclName(w, decl, 0), .undef => unreachable, - .identifier => |ident| return w.print("(*{ })", .{fmtIdent(ident)}), - .payload_identifier => |ident| return w.print("(*{ }.{ })", .{ + .identifier => |ident| try w.print("(*{ })", .{fmtIdent(ident)}), + .payload_identifier => |ident| try w.print("(*{ }.{ })", .{ fmtIdent("payload"), fmtIdent(ident), }), @@ -1950,12 +2005,12 @@ pub const DeclGen = struct { fn writeCValueDerefMember(dg: *DeclGen, writer: anytype, c_value: CValue, member: CValue) !void { switch (c_value) { - .none, .constant, .field, .undef => unreachable, - .new_local, .local, .arg, .arg_array, .decl, .identifier, .payload_identifier => { + .none, .new_local, .local, .local_ref, .constant, .field, .undef, .arg, .arg_array => unreachable, + .decl, .identifier, .payload_identifier => { try dg.writeCValue(writer, c_value); try writer.writeAll("->"); }, - .local_ref, .decl_ref => { + .decl_ref => { try dg.writeCValueDeref(writer, c_value); try writer.writeByte('.'); }, @@ -1969,11 +2024,12 @@ pub const DeclGen = struct { variable: InternPool.Key.Variable, fwd_kind: enum { tentative, final }, ) !void { - const decl = dg.module.declPtr(decl_index); + const zcu = dg.zcu; + const decl = zcu.declPtr(decl_index); const fwd = dg.fwdDeclWriter(); const is_global = variable.is_extern or dg.declIsGlobal(decl.val); try fwd.writeAll(if (is_global) "zig_extern " else "static "); - const maybe_exports = dg.module.decl_exports.get(decl_index); + const maybe_exports = zcu.decl_exports.get(decl_index); const export_weak_linkage = if (maybe_exports) |exports| exports.items[0].opts.linkage == .weak else @@ -1982,14 +2038,14 @@ pub const DeclGen = struct { if (variable.is_threadlocal) try fwd.writeAll("zig_threadlocal "); try dg.renderTypeAndName( fwd, - decl.typeOf(dg.module), + decl.typeOf(zcu), .{ .decl = decl_index }, CQualifiers.init(.{ .@"const" = variable.is_const }), decl.alignment, .complete, ); mangled: { - const external_name = dg.module.intern_pool.stringToSlice(if (maybe_exports) |exports| + const external_name = zcu.intern_pool.stringToSlice(if (maybe_exports) |exports| exports.items[0].opts.name else if (variable.is_extern) decl.name @@ -2007,23 +2063,23 @@ pub const DeclGen = struct { } fn renderDeclName(dg: *DeclGen, writer: anytype, decl_index: InternPool.DeclIndex, export_index: u32) !void { - const mod = dg.module; - const decl = mod.declPtr(decl_index); + const zcu = dg.zcu; + const decl = zcu.declPtr(decl_index); - if (mod.decl_exports.get(decl_index)) |exports| { + if (zcu.decl_exports.get(decl_index)) |exports| { try writer.print("{ }", .{ - fmtIdent(mod.intern_pool.stringToSlice(exports.items[export_index].opts.name)), + fmtIdent(zcu.intern_pool.stringToSlice(exports.items[export_index].opts.name)), }); - } else if (decl.getExternDecl(mod).unwrap()) |extern_decl_index| { + } else if (decl.getExternDecl(zcu).unwrap()) |extern_decl_index| { try writer.print("{ }", .{ - fmtIdent(mod.intern_pool.stringToSlice(mod.declPtr(extern_decl_index).name)), + fmtIdent(zcu.intern_pool.stringToSlice(zcu.declPtr(extern_decl_index).name)), }); } else { // MSVC has a limit of 4095 character token length limit, and fmtIdent can (worst case), // expand to 3x the length of its input, but let's cut it off at a much shorter limit. var name: [100]u8 = undefined; var name_stream = std.io.fixedBufferStream(&name); - decl.renderFullyQualifiedName(mod, name_stream.writer()) catch |err| switch (err) { + decl.renderFullyQualifiedName(zcu, name_stream.writer()) catch |err| switch (err) { error.NoSpaceLeft => {}, }; try writer.print("{}__{d}", .{ @@ -2033,8 +2089,8 @@ pub const DeclGen = struct { } } - fn renderAnonDeclName(writer: anytype, anon_decl_val: InternPool.Index) !void { - return writer.print("__anon_{d}", .{@intFromEnum(anon_decl_val)}); + fn renderAnonDeclName(writer: anytype, anon_decl_val: Value) !void { + try writer.print("__anon_{d}", .{@intFromEnum(anon_decl_val.toIntern())}); } fn renderTypeForBuiltinFnName(dg: *DeclGen, writer: anytype, ty: Type) !void { @@ -2047,7 +2103,7 @@ pub const DeclGen = struct { if (cty.isBool()) signAbbrev(.unsigned) else if (cty.isInteger()) - signAbbrev(cty.signedness(dg.module.getTarget())) + signAbbrev(cty.signedness(dg.mod)) else if (cty.isFloat()) @as(u8, 'f') else if (cty.isPointer()) @@ -2056,7 +2112,7 @@ pub const DeclGen = struct { return dg.fail("TODO: CBE: implement renderTypeForBuiltinFnName for type {}", .{ cty.tag(), }), - if (cty.isFloat()) cty.floatActiveBits(dg.module.getTarget()) else dg.byteSize(cty) * 8, + if (cty.isFloat()) cty.floatActiveBits(dg.mod) else dg.byteSize(cty) * 8, }), .array => try writer.writeAll("big"), } @@ -2065,43 +2121,39 @@ pub const DeclGen = struct { fn renderBuiltinInfo(dg: *DeclGen, writer: anytype, ty: Type, info: BuiltinInfo) !void { const cty = try dg.typeToCType(ty, .complete); const is_big = cty.tag() == .array; - switch (info) { .none => if (!is_big) return, .bits => {}, } - const mod = dg.module; - const int_info = if (ty.isAbiInt(mod)) ty.intInfo(mod) else std.builtin.Type.Int{ + const zcu = dg.zcu; + const int_info = if (ty.isAbiInt(zcu)) ty.intInfo(zcu) else std.builtin.Type.Int{ .signedness = .unsigned, - .bits = @as(u16, @intCast(ty.bitSize(mod))), + .bits = @as(u16, @intCast(ty.bitSize(zcu))), }; if (is_big) try writer.print(", {}", .{int_info.signedness == .signed}); - - const bits_ty = if (is_big) Type.u16 else Type.u8; try writer.print(", {}", .{try dg.fmtIntLiteral( - bits_ty, - try mod.intValue(bits_ty, int_info.bits), + try zcu.intValue(if (is_big) Type.u16 else Type.u8, int_info.bits), .FunctionArgument, )}); } fn fmtIntLiteral( dg: *DeclGen, - ty: Type, val: Value, loc: ValueRenderLocation, ) !std.fmt.Formatter(formatIntLiteral) { - const mod = dg.module; + const zcu = dg.zcu; const kind: CType.Kind = switch (loc) { .FunctionArgument => .parameter, .Initializer, .Other => .complete, .StaticInitializer => .global, }; + const ty = val.typeOf(zcu); return std.fmt.Formatter(formatIntLiteral){ .data = .{ .dg = dg, - .int_info = ty.intInfo(mod), + .int_info = ty.intInfo(zcu), .kind = kind, .cty = try dg.typeToCType(ty, kind), .val = val, @@ -2133,7 +2185,7 @@ const RenderCTypeTrailing = enum { } }; fn renderTypeName( - mod: *Module, + zcu: *Zcu, w: anytype, idx: CType.Index, cty: CType, @@ -2157,7 +2209,7 @@ fn renderTypeName( try w.print("{s} {s}{}__{d}", .{ @tagName(tag)["fwd_".len..], attributes, - fmtIdent(mod.intern_pool.stringToSlice(mod.declPtr(owner_decl).name)), + fmtIdent(zcu.intern_pool.stringToSlice(zcu.declPtr(owner_decl).name)), @intFromEnum(owner_decl), }); }, @@ -2166,7 +2218,7 @@ fn renderTypeName( fn renderTypePrefix( pass: DeclGen.Pass, store: CType.Store.Set, - mod: *Module, + zcu: *Zcu, w: anytype, idx: CType.Index, parent_fix: CTypeFix, @@ -2224,7 +2276,7 @@ fn renderTypePrefix( const child_trailing = try renderTypePrefix( pass, store, - mod, + zcu, w, child_idx, .prefix, @@ -2247,7 +2299,7 @@ fn renderTypePrefix( => { const child_idx = cty.cast(CType.Payload.Sequence).?.data.elem_type; const child_trailing = - try renderTypePrefix(pass, store, mod, w, child_idx, .suffix, qualifiers); + try renderTypePrefix(pass, store, zcu, w, child_idx, .suffix, qualifiers); switch (parent_fix) { .prefix => { try w.print("{}(", .{child_trailing}); @@ -2262,12 +2314,12 @@ fn renderTypePrefix( => switch (pass) { .decl => |decl_index| try w.print("decl__{d}_{d}", .{ @intFromEnum(decl_index), idx }), .anon => |anon_decl| try w.print("anon__{d}_{d}", .{ @intFromEnum(anon_decl), idx }), - .flush => try renderTypeName(mod, w, idx, cty, ""), + .flush => try renderTypeName(zcu, w, idx, cty, ""), }, .fwd_struct, .fwd_union, - => try renderTypeName(mod, w, idx, cty, ""), + => try renderTypeName(zcu, w, idx, cty, ""), .unnamed_struct, .unnamed_union, @@ -2278,7 +2330,7 @@ fn renderTypePrefix( @tagName(tag)["unnamed_".len..], if (cty.isPacked()) "zig_packed(" else "", }); - try renderAggregateFields(mod, w, store, cty, 1); + try renderAggregateFields(zcu, w, store, cty, 1); if (cty.isPacked()) try w.writeByte(')'); }, @@ -2291,7 +2343,7 @@ fn renderTypePrefix( => return renderTypePrefix( pass, store, - mod, + zcu, w, cty.cast(CType.Payload.Aggregate).?.data.fwd_decl, parent_fix, @@ -2304,7 +2356,7 @@ fn renderTypePrefix( const child_trailing = try renderTypePrefix( pass, store, - mod, + zcu, w, cty.cast(CType.Payload.Function).?.data.return_type, .suffix, @@ -2331,7 +2383,7 @@ fn renderTypePrefix( fn renderTypeSuffix( pass: DeclGen.Pass, store: CType.Store.Set, - mod: *Module, + zcu: *Zcu, w: anytype, idx: CType.Index, parent_fix: CTypeFix, @@ -2385,7 +2437,7 @@ fn renderTypeSuffix( => try renderTypeSuffix( pass, store, - mod, + zcu, w, cty.cast(CType.Payload.Child).?.data, .prefix, @@ -2404,7 +2456,7 @@ fn renderTypeSuffix( try renderTypeSuffix( pass, store, - mod, + zcu, w, cty.cast(CType.Payload.Sequence).?.data.elem_type, .suffix, @@ -2444,9 +2496,9 @@ fn renderTypeSuffix( if (need_comma) try w.writeAll(", "); need_comma = true; const trailing = - try renderTypePrefix(pass, store, mod, w, param_type, .suffix, qualifiers); + try renderTypePrefix(pass, store, zcu, w, param_type, .suffix, qualifiers); if (qualifiers.contains(.@"const")) try w.print("{}a{d}", .{ trailing, param_i }); - try renderTypeSuffix(pass, store, mod, w, param_type, .suffix, .{}); + try renderTypeSuffix(pass, store, zcu, w, param_type, .suffix, .{}); } switch (tag) { .function => {}, @@ -2460,12 +2512,12 @@ fn renderTypeSuffix( if (!need_comma) try w.writeAll("void"); try w.writeByte(')'); - try renderTypeSuffix(pass, store, mod, w, data.return_type, .suffix, .{}); + try renderTypeSuffix(pass, store, zcu, w, data.return_type, .suffix, .{}); }, } } fn renderAggregateFields( - mod: *Module, + zcu: *Zcu, writer: anytype, store: CType.Store.Set, cty: CType, @@ -2480,9 +2532,9 @@ fn renderAggregateFields( .eq => {}, .gt => try writer.print("zig_align({}) ", .{field.alignas.toByteUnits()}), } - const trailing = try renderTypePrefix(.flush, store, mod, writer, field.type, .suffix, .{}); + const trailing = try renderTypePrefix(.flush, store, zcu, writer, field.type, .suffix, .{}); try writer.print("{}{ }", .{ trailing, fmtIdent(mem.span(field.name)) }); - try renderTypeSuffix(.flush, store, mod, writer, field.type, .suffix, .{}); + try renderTypeSuffix(.flush, store, zcu, writer, field.type, .suffix, .{}); try writer.writeAll(";\n"); } try writer.writeByteNTimes(' ', indent); @@ -2490,7 +2542,7 @@ fn renderAggregateFields( } pub fn genTypeDecl( - mod: *Module, + zcu: *Zcu, writer: anytype, global_store: CType.Store.Set, global_idx: CType.Index, @@ -2503,9 +2555,9 @@ pub fn genTypeDecl( switch (global_cty.tag()) { .fwd_anon_struct => if (pass != .flush) { try writer.writeAll("typedef "); - _ = try renderTypePrefix(.flush, global_store, mod, writer, global_idx, .suffix, .{}); + _ = try renderTypePrefix(.flush, global_store, zcu, writer, global_idx, .suffix, .{}); try writer.writeByte(' '); - _ = try renderTypePrefix(pass, decl_store, mod, writer, decl_idx, .suffix, .{}); + _ = try renderTypePrefix(pass, decl_store, zcu, writer, decl_idx, .suffix, .{}); try writer.writeAll(";\n"); }, @@ -2526,14 +2578,14 @@ pub fn genTypeDecl( _ = try renderTypePrefix( .flush, global_store, - mod, + zcu, writer, global_idx, .suffix, .{}, ); try writer.writeAll("; /* "); - try mod.declPtr(owner_decl).renderFullyQualifiedName(mod, writer); + try zcu.declPtr(owner_decl).renderFullyQualifiedName(zcu, writer); try writer.writeAll(" */\n"); }, @@ -2546,14 +2598,14 @@ pub fn genTypeDecl( => { const fwd_idx = global_cty.cast(CType.Payload.Aggregate).?.data.fwd_decl; try renderTypeName( - mod, + zcu, writer, fwd_idx, global_store.indexToCType(fwd_idx), if (global_cty.isPacked()) "zig_packed(" else "", ); try writer.writeByte(' '); - try renderAggregateFields(mod, writer, global_store, global_cty, 0); + try renderAggregateFields(zcu, writer, global_store, global_cty, 0); if (global_cty.isPacked()) try writer.writeByte(')'); try writer.writeAll(";\n"); }, @@ -2566,30 +2618,30 @@ pub fn genTypeDecl( } } -pub fn genGlobalAsm(mod: *Module, writer: anytype) !void { - for (mod.global_assembly.values()) |asm_source| { +pub fn genGlobalAsm(zcu: *Zcu, writer: anytype) !void { + for (zcu.global_assembly.values()) |asm_source| { try writer.print("__asm({s});\n", .{fmtStringLiteral(asm_source, null)}); } } pub fn genErrDecls(o: *Object) !void { - const mod = o.dg.module; - const ip = &mod.intern_pool; + const zcu = o.dg.zcu; + const ip = &zcu.intern_pool; const writer = o.writer(); var max_name_len: usize = 0; // do not generate an invalid empty enum when the global error set is empty - if (mod.global_error_set.keys().len > 1) { + if (zcu.global_error_set.keys().len > 1) { try writer.writeAll("enum {\n"); o.indent_writer.pushIndent(); - for (mod.global_error_set.keys()[1..], 1..) |name_nts, value| { + for (zcu.global_error_set.keys()[1..], 1..) |name_nts, value| { const name = ip.stringToSlice(name_nts); max_name_len = @max(name.len, max_name_len); - const err_val = try mod.intern(.{ .err = .{ + const err_val = try zcu.intern(.{ .err = .{ .ty = .anyerror_type, .name = name_nts, } }); - try o.dg.renderValue(writer, Type.anyerror, Value.fromInterned(err_val), .Other); + try o.dg.renderValue(writer, Value.fromInterned(err_val), .Other); try writer.print(" = {d}u,\n", .{value}); } o.indent_writer.popIndent(); @@ -2601,44 +2653,56 @@ pub fn genErrDecls(o: *Object) !void { defer o.dg.gpa.free(name_buf); @memcpy(name_buf[0..name_prefix.len], name_prefix); - for (mod.global_error_set.keys()) |name_ip| { + for (zcu.global_error_set.keys()) |name_ip| { const name = ip.stringToSlice(name_ip); @memcpy(name_buf[name_prefix.len..][0..name.len], name); const identifier = name_buf[0 .. name_prefix.len + name.len]; - const name_ty = try mod.arrayType(.{ + const name_ty = try zcu.arrayType(.{ .len = name.len, .child = .u8_type, .sentinel = .zero_u8, }); - const name_val = try mod.intern(.{ .aggregate = .{ + const name_val = try zcu.intern(.{ .aggregate = .{ .ty = name_ty.toIntern(), .storage = .{ .bytes = name }, } }); try writer.writeAll("static "); - try o.dg.renderTypeAndName(writer, name_ty, .{ .identifier = identifier }, Const, .none, .complete); + try o.dg.renderTypeAndName( + writer, + name_ty, + .{ .identifier = identifier }, + Const, + .none, + .complete, + ); try writer.writeAll(" = "); - try o.dg.renderValue(writer, name_ty, Value.fromInterned(name_val), .StaticInitializer); + try o.dg.renderValue(writer, Value.fromInterned(name_val), .StaticInitializer); try writer.writeAll(";\n"); } - const name_array_ty = try mod.arrayType(.{ - .len = mod.global_error_set.count(), + const name_array_ty = try zcu.arrayType(.{ + .len = zcu.global_error_set.count(), .child = .slice_const_u8_sentinel_0_type, }); try writer.writeAll("static "); - try o.dg.renderTypeAndName(writer, name_array_ty, .{ .identifier = array_identifier }, Const, .none, .complete); + try o.dg.renderTypeAndName( + writer, + name_array_ty, + .{ .identifier = array_identifier }, + Const, + .none, + .complete, + ); try writer.writeAll(" = {"); - for (mod.global_error_set.keys(), 0..) |name_nts, value| { + for (zcu.global_error_set.keys(), 0..) |name_nts, value| { const name = ip.stringToSlice(name_nts); if (value != 0) try writer.writeByte(','); - - const len_val = try mod.intValue(Type.usize, name.len); - try writer.print("{{" ++ name_prefix ++ "{}, {}}}", .{ - fmtIdent(name), try o.dg.fmtIntLiteral(Type.usize, len_val, .StaticInitializer), + fmtIdent(name), + try o.dg.fmtIntLiteral(try zcu.intValue(Type.usize, name.len), .StaticInitializer), }); } try writer.writeAll("};\n"); @@ -2648,16 +2712,16 @@ fn genExports(o: *Object) !void { const tracy = trace(@src()); defer tracy.end(); - const mod = o.dg.module; - const ip = &mod.intern_pool; + const zcu = o.dg.zcu; + const ip = &zcu.intern_pool; const decl_index = switch (o.dg.pass) { .decl => |decl| decl, .anon, .flush => return, }; - const decl = mod.declPtr(decl_index); + const decl = zcu.declPtr(decl_index); const fwd = o.dg.fwdDeclWriter(); - const exports = mod.decl_exports.get(decl_index) orelse return; + const exports = zcu.decl_exports.get(decl_index) orelse return; if (exports.items.len < 2) return; const is_variable_const = switch (ip.indexToKey(decl.val.toIntern())) { @@ -2685,7 +2749,7 @@ fn genExports(o: *Object) !void { const export_name = ip.stringToSlice(@"export".opts.name); try o.dg.renderTypeAndName( fwd, - decl.typeOf(mod), + decl.typeOf(zcu), .{ .identifier = export_name }, CQualifiers.init(.{ .@"const" = is_variable_const }), decl.alignment, @@ -2708,8 +2772,8 @@ fn genExports(o: *Object) !void { } pub fn genLazyFn(o: *Object, lazy_fn: LazyFnMap.Entry) !void { - const mod = o.dg.module; - const ip = &mod.intern_pool; + const zcu = o.dg.zcu; + const ip = &zcu.intern_pool; const w = o.writer(); const key = lazy_fn.key_ptr.*; const val = lazy_fn.value_ptr; @@ -2727,47 +2791,45 @@ pub fn genLazyFn(o: *Object, lazy_fn: LazyFnMap.Entry) !void { try w.writeByte('('); try o.dg.renderTypeAndName(w, enum_ty, .{ .identifier = "tag" }, Const, .none, .complete); try w.writeAll(") {\n switch (tag) {\n"); - const tag_names = enum_ty.enumFields(mod); + const tag_names = enum_ty.enumFields(zcu); for (0..tag_names.len) |tag_index| { const tag_name = ip.stringToSlice(tag_names.get(ip)[tag_index]); - const tag_val = try mod.enumValueFieldIndex(enum_ty, @intCast(tag_index)); + const tag_val = try zcu.enumValueFieldIndex(enum_ty, @intCast(tag_index)); - const int_val = try tag_val.intFromEnum(enum_ty, mod); - - const name_ty = try mod.arrayType(.{ + const name_ty = try zcu.arrayType(.{ .len = tag_name.len, .child = .u8_type, .sentinel = .zero_u8, }); - const name_val = try mod.intern(.{ .aggregate = .{ + const name_val = try zcu.intern(.{ .aggregate = .{ .ty = name_ty.toIntern(), .storage = .{ .bytes = tag_name }, } }); - const len_val = try mod.intValue(Type.usize, tag_name.len); try w.print(" case {}: {{\n static ", .{ - try o.dg.fmtIntLiteral(enum_ty, int_val, .Other), + try o.dg.fmtIntLiteral(try tag_val.intFromEnum(enum_ty, zcu), .Other), }); try o.dg.renderTypeAndName(w, name_ty, .{ .identifier = "name" }, Const, .none, .complete); try w.writeAll(" = "); - try o.dg.renderValue(w, name_ty, Value.fromInterned(name_val), .Initializer); + try o.dg.renderValue(w, Value.fromInterned(name_val), .Initializer); try w.writeAll(";\n return ("); try o.dg.renderType(w, name_slice_ty); try w.print("){{{}, {}}};\n", .{ - fmtIdent("name"), try o.dg.fmtIntLiteral(Type.usize, len_val, .Other), + fmtIdent("name"), + try o.dg.fmtIntLiteral(try zcu.intValue(Type.usize, tag_name.len), .Other), }); try w.writeAll(" }\n"); } try w.writeAll(" }\n while ("); - try o.dg.renderValue(w, Type.bool, Value.true, .Other); + try o.dg.renderValue(w, Value.true, .Other); try w.writeAll(") "); _ = try airBreakpoint(w); try w.writeAll("}\n"); }, .never_tail, .never_inline => |fn_decl_index| { - const fn_decl = mod.declPtr(fn_decl_index); - const fn_cty = try o.dg.typeToCType(fn_decl.typeOf(mod), .complete); + const fn_decl = zcu.declPtr(fn_decl_index); + const fn_cty = try o.dg.typeToCType(fn_decl.typeOf(zcu), .complete); const fn_info = fn_cty.cast(CType.Payload.Function).?.data; const fwd_decl_writer = o.dg.fwdDeclWriter(); @@ -2799,10 +2861,10 @@ pub fn genFunc(f: *Function) !void { defer tracy.end(); const o = &f.object; - const mod = o.dg.module; + const zcu = o.dg.zcu; const gpa = o.dg.gpa; const decl_index = o.dg.pass.decl; - const decl = mod.declPtr(decl_index); + const decl = zcu.declPtr(decl_index); o.code_header = std.ArrayList(u8).init(gpa); defer o.code_header.deinit(); @@ -2811,7 +2873,7 @@ pub fn genFunc(f: *Function) !void { const fwd_decl_writer = o.dg.fwdDeclWriter(); try fwd_decl_writer.writeAll(if (is_global) "zig_extern " else "static "); - if (mod.decl_exports.get(decl_index)) |exports| + if (zcu.decl_exports.get(decl_index)) |exports| if (exports.items[0].opts.linkage == .weak) try fwd_decl_writer.writeAll("zig_weak_linkage_fn "); try o.dg.renderFunctionSignature(fwd_decl_writer, decl_index, .forward, .{ .export_index = 0 }); try fwd_decl_writer.writeAll(";\n"); @@ -2819,6 +2881,8 @@ pub fn genFunc(f: *Function) !void { try o.indent_writer.insertNewline(); if (!is_global) try o.writer().writeAll("static "); + if (zcu.intern_pool.stringToSliceUnwrap(decl.@"linksection")) |s| + try o.writer().print("zig_linksection_fn({s}) ", .{fmtStringLiteral(s, null)}); try o.dg.renderFunctionSignature(o.writer(), decl_index, .complete, .{ .export_index = 0 }); try o.writer().writeByte(' '); @@ -2867,7 +2931,7 @@ pub fn genFunc(f: *Function) !void { for (free_locals.values()) |list| { for (list.keys()) |local_index| { const local = f.locals.items[local_index]; - try o.dg.renderCTypeAndName(w, local.cty_idx, .{ .local = local_index }, .{}, local.alignas); + try o.dg.renderCTypeAndName(w, local.cty_idx, .{ .local = local_index }, .{}, local.flags.alignas); try w.writeAll(";\n "); } } @@ -2884,43 +2948,41 @@ pub fn genDecl(o: *Object) !void { const tracy = trace(@src()); defer tracy.end(); - const mod = o.dg.module; + const zcu = o.dg.zcu; const decl_index = o.dg.pass.decl; - const decl = mod.declPtr(decl_index); - const decl_val = decl.val; - const decl_ty = decl_val.typeOf(mod); + const decl = zcu.declPtr(decl_index); + const decl_ty = decl.typeOf(zcu); - if (!decl_ty.isFnOrHasRuntimeBitsIgnoreComptime(mod)) return; - if (decl_val.getExternFunc(mod)) |_| { + if (!decl_ty.isFnOrHasRuntimeBitsIgnoreComptime(zcu)) return; + if (decl.val.getExternFunc(zcu)) |_| { const fwd_decl_writer = o.dg.fwdDeclWriter(); try fwd_decl_writer.writeAll("zig_extern "); try o.dg.renderFunctionSignature(fwd_decl_writer, decl_index, .forward, .{ .export_index = 0 }); try fwd_decl_writer.writeAll(";\n"); try genExports(o); - } else if (decl_val.getVariable(mod)) |variable| { + } else if (decl.val.getVariable(zcu)) |variable| { try o.dg.renderFwdDecl(decl_index, variable, .final); try genExports(o); if (variable.is_extern) return; - const is_global = variable.is_extern or o.dg.declIsGlobal(decl_val); + const is_global = variable.is_extern or o.dg.declIsGlobal(decl.val); const w = o.writer(); if (!is_global) try w.writeAll("static "); if (variable.is_weak_linkage) try w.writeAll("zig_weak_linkage "); if (variable.is_threadlocal) try w.writeAll("zig_threadlocal "); - if (mod.intern_pool.stringToSliceUnwrap(decl.@"linksection")) |s| - try w.print("zig_linksection(\"{s}\", ", .{s}); + if (zcu.intern_pool.stringToSliceUnwrap(decl.@"linksection")) |s| + try w.print("zig_linksection({s}) ", .{fmtStringLiteral(s, null)}); const decl_c_value = .{ .decl = decl_index }; try o.dg.renderTypeAndName(w, decl_ty, decl_c_value, .{}, decl.alignment, .complete); - if (decl.@"linksection" != .none) try w.writeAll(", read, write)"); try w.writeAll(" = "); - try o.dg.renderValue(w, decl_ty, Value.fromInterned(variable.init), .StaticInitializer); + try o.dg.renderValue(w, Value.fromInterned(variable.init), .StaticInitializer); try w.writeByte(';'); try o.indent_writer.insertNewline(); } else { - const is_global = o.dg.module.decl_exports.contains(decl_index); + const is_global = o.dg.zcu.decl_exports.contains(decl_index); const decl_c_value = .{ .decl = decl_index }; - try genDeclValue(o, decl_val, is_global, decl_c_value, decl.alignment, decl.@"linksection"); + try genDeclValue(o, decl.val, is_global, decl_c_value, decl.alignment, decl.@"linksection"); } } @@ -2930,19 +2992,19 @@ pub fn genDeclValue( is_global: bool, decl_c_value: CValue, alignment: Alignment, - link_section: InternPool.OptionalNullTerminatedString, + @"linksection": InternPool.OptionalNullTerminatedString, ) !void { - const mod = o.dg.module; + const zcu = o.dg.zcu; const fwd_decl_writer = o.dg.fwdDeclWriter(); - const ty = val.typeOf(mod); + const ty = val.typeOf(zcu); try fwd_decl_writer.writeAll(if (is_global) "zig_extern " else "static "); try o.dg.renderTypeAndName(fwd_decl_writer, ty, decl_c_value, Const, alignment, .complete); switch (o.dg.pass) { .decl => |decl_index| { - if (mod.decl_exports.get(decl_index)) |exports| { - const export_name = mod.intern_pool.stringToSlice(exports.items[0].opts.name); + if (zcu.decl_exports.get(decl_index)) |exports| { + const export_name = zcu.intern_pool.stringToSlice(exports.items[0].opts.name); if (isMangledIdent(export_name, true)) { try fwd_decl_writer.print(" zig_mangled_final({ }, {s})", .{ fmtIdent(export_name), fmtStringLiteral(export_name, null), @@ -2958,13 +3020,11 @@ pub fn genDeclValue( const w = o.writer(); if (!is_global) try w.writeAll("static "); - - if (mod.intern_pool.stringToSliceUnwrap(link_section)) |s| - try w.print("zig_linksection(\"{s}\", ", .{s}); + if (zcu.intern_pool.stringToSliceUnwrap(@"linksection")) |s| + try w.print("zig_linksection({s}) ", .{fmtStringLiteral(s, null)}); try o.dg.renderTypeAndName(w, ty, decl_c_value, Const, alignment, .complete); - if (link_section != .none) try w.writeAll(", read)"); try w.writeAll(" = "); - try o.dg.renderValue(w, ty, val, .StaticInitializer); + try o.dg.renderValue(w, val, .StaticInitializer); try w.writeAll(";\n"); } @@ -2972,12 +3032,12 @@ pub fn genHeader(dg: *DeclGen) error{ AnalysisFail, OutOfMemory }!void { const tracy = trace(@src()); defer tracy.end(); - const mod = dg.module; + const zcu = dg.zcu; const decl_index = dg.pass.decl; - const decl = mod.declPtr(decl_index); + const decl = zcu.declPtr(decl_index); const writer = dg.fwdDeclWriter(); - switch (decl.val.typeOf(mod).zigTypeTag(mod)) { + switch (decl.typeOf(zcu).zigTypeTag(zcu)) { .Fn => if (dg.declIsGlobal(decl.val)) { try writer.writeAll("zig_extern "); try dg.renderFunctionSignature(writer, dg.pass.decl, .complete, .{ .export_index = 0 }); @@ -3060,8 +3120,8 @@ fn genBodyResolveState(f: *Function, inst: Air.Inst.Index, leading_deaths: []con } fn genBodyInner(f: *Function, body: []const Air.Inst.Index) error{ AnalysisFail, OutOfMemory }!void { - const mod = f.object.dg.module; - const ip = &mod.intern_pool; + const zcu = f.object.dg.zcu; + const ip = &zcu.intern_pool; const air_tags = f.air.instructions.items(.tag); for (body) |inst| { @@ -3096,10 +3156,10 @@ fn genBodyInner(f: *Function, body: []const Air.Inst.Index) error{ AnalysisFail, .div_trunc, .div_exact => try airBinOp(f, inst, "/", "div_trunc", .none), .rem => blk: { const bin_op = f.air.instructions.items(.data)[@intFromEnum(inst)].bin_op; - const lhs_scalar_ty = f.typeOf(bin_op.lhs).scalarType(mod); + const lhs_scalar_ty = f.typeOf(bin_op.lhs).scalarType(zcu); // For binary operations @TypeOf(lhs)==@TypeOf(rhs), // so we only check one. - break :blk if (lhs_scalar_ty.isInt(mod)) + break :blk if (lhs_scalar_ty.isInt(zcu)) try airBinOp(f, inst, "%", "rem", .none) else try airBinFloatOp(f, inst, "fmod"); @@ -3359,10 +3419,10 @@ fn airSliceField(f: *Function, inst: Air.Inst.Index, is_ptr: bool, field_name: [ } fn airPtrElemVal(f: *Function, inst: Air.Inst.Index) !CValue { - const mod = f.object.dg.module; + const zcu = f.object.dg.zcu; const inst_ty = f.typeOfIndex(inst); const bin_op = f.air.instructions.items(.data)[@intFromEnum(inst)].bin_op; - if (!inst_ty.hasRuntimeBitsIgnoreComptime(mod)) { + if (!inst_ty.hasRuntimeBitsIgnoreComptime(zcu)) { try reap(f, inst, &.{ bin_op.lhs, bin_op.rhs }); return .none; } @@ -3385,14 +3445,17 @@ fn airPtrElemVal(f: *Function, inst: Air.Inst.Index) !CValue { } fn airPtrElemPtr(f: *Function, inst: Air.Inst.Index) !CValue { - const mod = f.object.dg.module; + const zcu = f.object.dg.zcu; const ty_pl = f.air.instructions.items(.data)[@intFromEnum(inst)].ty_pl; const bin_op = f.air.extraData(Air.Bin, ty_pl.payload).data; const inst_ty = f.typeOfIndex(inst); const ptr_ty = f.typeOf(bin_op.lhs); - const elem_ty = ptr_ty.childType(mod); - const elem_has_bits = elem_ty.hasRuntimeBitsIgnoreComptime(mod); + const ptr_align = ptr_ty.ptrAlignment(zcu); + const elem_ty = ptr_ty.elemType2(zcu); + const elem_align = elem_ty.abiAlignment(zcu); + const is_under_aligned = ptr_align.compareStrict(.lt, elem_align); + const elem_has_bits = elem_ty.hasRuntimeBitsIgnoreComptime(zcu); const ptr = try f.resolveInst(bin_op.lhs); const index = try f.resolveInst(bin_op.rhs); @@ -3407,13 +3470,22 @@ fn airPtrElemPtr(f: *Function, inst: Air.Inst.Index) !CValue { try f.renderType(writer, inst_ty); try writer.writeByte(')'); if (elem_has_bits) try writer.writeByte('&'); - if (elem_has_bits and ptr_ty.ptrSize(mod) == .One) { + if (elem_has_bits and ptr_ty.ptrSize(zcu) == .One and !is_under_aligned) { // It's a pointer to an array, so we need to de-reference. try f.writeCValueDeref(writer, ptr); } else try f.writeCValue(writer, ptr, .Other); if (elem_has_bits) { try writer.writeByte('['); try f.writeCValue(writer, index, .Other); + if (is_under_aligned) { + const factor = @divExact(elem_align.toByteUnitsOptional().?, @min( + ptr_align.toByteUnitsOptional().?, + f.object.dg.mod.resolved_target.result.maxIntAlignment(), + )); + try writer.print(" * {}", .{ + try f.fmtIntLiteral(try zcu.intValue(Type.usize, factor)), + }); + } try writer.writeByte(']'); } try a.end(f, writer); @@ -3421,10 +3493,10 @@ fn airPtrElemPtr(f: *Function, inst: Air.Inst.Index) !CValue { } fn airSliceElemVal(f: *Function, inst: Air.Inst.Index) !CValue { - const mod = f.object.dg.module; + const zcu = f.object.dg.zcu; const inst_ty = f.typeOfIndex(inst); const bin_op = f.air.instructions.items(.data)[@intFromEnum(inst)].bin_op; - if (!inst_ty.hasRuntimeBitsIgnoreComptime(mod)) { + if (!inst_ty.hasRuntimeBitsIgnoreComptime(zcu)) { try reap(f, inst, &.{ bin_op.lhs, bin_op.rhs }); return .none; } @@ -3447,14 +3519,14 @@ fn airSliceElemVal(f: *Function, inst: Air.Inst.Index) !CValue { } fn airSliceElemPtr(f: *Function, inst: Air.Inst.Index) !CValue { - const mod = f.object.dg.module; + const zcu = f.object.dg.zcu; const ty_pl = f.air.instructions.items(.data)[@intFromEnum(inst)].ty_pl; const bin_op = f.air.extraData(Air.Bin, ty_pl.payload).data; const inst_ty = f.typeOfIndex(inst); const slice_ty = f.typeOf(bin_op.lhs); - const elem_ty = slice_ty.elemType2(mod); - const elem_has_bits = elem_ty.hasRuntimeBitsIgnoreComptime(mod); + const elem_ty = slice_ty.elemType2(zcu); + const elem_has_bits = elem_ty.hasRuntimeBitsIgnoreComptime(zcu); const slice = try f.resolveInst(bin_op.lhs); const index = try f.resolveInst(bin_op.rhs); @@ -3477,10 +3549,10 @@ fn airSliceElemPtr(f: *Function, inst: Air.Inst.Index) !CValue { } fn airArrayElemVal(f: *Function, inst: Air.Inst.Index) !CValue { - const mod = f.object.dg.module; + const zcu = f.object.dg.zcu; const bin_op = f.air.instructions.items(.data)[@intFromEnum(inst)].bin_op; const inst_ty = f.typeOfIndex(inst); - if (!inst_ty.hasRuntimeBitsIgnoreComptime(mod)) { + if (!inst_ty.hasRuntimeBitsIgnoreComptime(zcu)) { try reap(f, inst, &.{ bin_op.lhs, bin_op.rhs }); return .none; } @@ -3503,33 +3575,33 @@ fn airArrayElemVal(f: *Function, inst: Air.Inst.Index) !CValue { } fn airAlloc(f: *Function, inst: Air.Inst.Index) !CValue { - const mod = f.object.dg.module; + const zcu = f.object.dg.zcu; const inst_ty = f.typeOfIndex(inst); - const elem_type = inst_ty.childType(mod); - if (!elem_type.isFnOrHasRuntimeBitsIgnoreComptime(mod)) return .{ .undef = inst_ty }; + const elem_type = inst_ty.childType(zcu); + if (!elem_type.isFnOrHasRuntimeBitsIgnoreComptime(zcu)) return .{ .undef = inst_ty }; const local = try f.allocLocalValue( elem_type, - inst_ty.ptrAlignment(mod), + inst_ty.ptrAlignment(zcu), ); log.debug("%{d}: allocated unfreeable t{d}", .{ inst, local.new_local }); - const gpa = f.object.dg.module.gpa; + const gpa = f.object.dg.zcu.gpa; try f.allocs.put(gpa, local.new_local, true); return .{ .local_ref = local.new_local }; } fn airRetPtr(f: *Function, inst: Air.Inst.Index) !CValue { - const mod = f.object.dg.module; + const zcu = f.object.dg.zcu; const inst_ty = f.typeOfIndex(inst); - const elem_ty = inst_ty.childType(mod); - if (!elem_ty.isFnOrHasRuntimeBitsIgnoreComptime(mod)) return .{ .undef = inst_ty }; + const elem_ty = inst_ty.childType(zcu); + if (!elem_ty.isFnOrHasRuntimeBitsIgnoreComptime(zcu)) return .{ .undef = inst_ty }; const local = try f.allocLocalValue( elem_ty, - inst_ty.ptrAlignment(mod), + inst_ty.ptrAlignment(zcu), ); log.debug("%{d}: allocated unfreeable t{d}", .{ inst, local.new_local }); - const gpa = f.object.dg.module.gpa; + const gpa = f.object.dg.zcu.gpa; try f.allocs.put(gpa, local.new_local, true); return .{ .local_ref = local.new_local }; } @@ -3559,15 +3631,15 @@ fn airArg(f: *Function, inst: Air.Inst.Index) !CValue { } fn airLoad(f: *Function, inst: Air.Inst.Index) !CValue { - const mod = f.object.dg.module; + const zcu = f.object.dg.zcu; const ty_op = f.air.instructions.items(.data)[@intFromEnum(inst)].ty_op; const ptr_ty = f.typeOf(ty_op.operand); - const ptr_scalar_ty = ptr_ty.scalarType(mod); - const ptr_info = ptr_scalar_ty.ptrInfo(mod); + const ptr_scalar_ty = ptr_ty.scalarType(zcu); + const ptr_info = ptr_scalar_ty.ptrInfo(zcu); const src_ty = Type.fromInterned(ptr_info.child); - if (!src_ty.hasRuntimeBitsIgnoreComptime(mod)) { + if (!src_ty.hasRuntimeBitsIgnoreComptime(zcu)) { try reap(f, inst, &.{ty_op.operand}); return .none; } @@ -3577,10 +3649,10 @@ fn airLoad(f: *Function, inst: Air.Inst.Index) !CValue { try reap(f, inst, &.{ty_op.operand}); const is_aligned = if (ptr_info.flags.alignment != .none) - ptr_info.flags.alignment.compare(.gte, src_ty.abiAlignment(mod)) + ptr_info.flags.alignment.compare(.gte, src_ty.abiAlignment(zcu)) else true; - const is_array = lowersToArray(src_ty, mod); + const is_array = lowersToArray(src_ty, zcu); const need_memcpy = !is_aligned or is_array; const writer = f.object.writer(); @@ -3600,12 +3672,12 @@ fn airLoad(f: *Function, inst: Air.Inst.Index) !CValue { try writer.writeAll("))"); } else if (ptr_info.packed_offset.host_size > 0 and ptr_info.flags.vector_index == .none) { const host_bits: u16 = ptr_info.packed_offset.host_size * 8; - const host_ty = try mod.intType(.unsigned, host_bits); + const host_ty = try zcu.intType(.unsigned, host_bits); - const bit_offset_ty = try mod.intType(.unsigned, Type.smallestUnsignedBits(host_bits - 1)); - const bit_offset_val = try mod.intValue(bit_offset_ty, ptr_info.packed_offset.bit_offset); + const bit_offset_ty = try zcu.intType(.unsigned, Type.smallestUnsignedBits(host_bits - 1)); + const bit_offset_val = try zcu.intValue(bit_offset_ty, ptr_info.packed_offset.bit_offset); - const field_ty = try mod.intType(.unsigned, @as(u16, @intCast(src_ty.bitSize(mod)))); + const field_ty = try zcu.intType(.unsigned, @as(u16, @intCast(src_ty.bitSize(zcu)))); try f.writeCValue(writer, local, .Other); try v.elem(f, writer); @@ -3616,9 +3688,9 @@ fn airLoad(f: *Function, inst: Air.Inst.Index) !CValue { try writer.writeAll("(("); try f.renderType(writer, field_ty); try writer.writeByte(')'); - const cant_cast = host_ty.isInt(mod) and host_ty.bitSize(mod) > 64; + const cant_cast = host_ty.isInt(zcu) and host_ty.bitSize(zcu) > 64; if (cant_cast) { - if (field_ty.bitSize(mod) > 64) return f.fail("TODO: C backend: implement casting between types > 64 bits", .{}); + if (field_ty.bitSize(zcu) > 64) return f.fail("TODO: C backend: implement casting between types > 64 bits", .{}); try writer.writeAll("zig_lo_"); try f.object.dg.renderTypeForBuiltinFnName(writer, host_ty); try writer.writeByte('('); @@ -3628,7 +3700,7 @@ fn airLoad(f: *Function, inst: Air.Inst.Index) !CValue { try writer.writeByte('('); try f.writeCValueDeref(writer, operand); try v.elem(f, writer); - try writer.print(", {})", .{try f.fmtIntLiteral(bit_offset_ty, bit_offset_val)}); + try writer.print(", {})", .{try f.fmtIntLiteral(bit_offset_val)}); if (cant_cast) try writer.writeByte(')'); try f.object.dg.renderBuiltinInfo(writer, field_ty, .bits); try writer.writeByte(')'); @@ -3646,22 +3718,22 @@ fn airLoad(f: *Function, inst: Air.Inst.Index) !CValue { } fn airRet(f: *Function, inst: Air.Inst.Index, is_ptr: bool) !CValue { - const mod = f.object.dg.module; + const zcu = f.object.dg.zcu; const un_op = f.air.instructions.items(.data)[@intFromEnum(inst)].un_op; const writer = f.object.writer(); const op_inst = un_op.toIndex(); const op_ty = f.typeOf(un_op); - const ret_ty = if (is_ptr) op_ty.childType(mod) else op_ty; - const lowered_ret_ty = try lowerFnRetTy(ret_ty, mod); + const ret_ty = if (is_ptr) op_ty.childType(zcu) else op_ty; + const lowered_ret_ty = try lowerFnRetTy(ret_ty, zcu); if (op_inst != null and f.air.instructions.items(.tag)[@intFromEnum(op_inst.?)] == .call_always_tail) { try reap(f, inst, &.{un_op}); _ = try airCall(f, op_inst.?, .always_tail); - } else if (lowered_ret_ty.hasRuntimeBitsIgnoreComptime(mod)) { + } else if (lowered_ret_ty.hasRuntimeBitsIgnoreComptime(zcu)) { const operand = try f.resolveInst(un_op); try reap(f, inst, &.{un_op}); var deref = is_ptr; - const is_array = lowersToArray(ret_ty, mod); + const is_array = lowersToArray(ret_ty, zcu); const ret_val = if (is_array) ret_val: { const array_local = try f.allocLocal(inst, lowered_ret_ty); try writer.writeAll("memcpy("); @@ -3696,16 +3768,16 @@ fn airRet(f: *Function, inst: Air.Inst.Index, is_ptr: bool) !CValue { } fn airIntCast(f: *Function, inst: Air.Inst.Index) !CValue { - const mod = f.object.dg.module; + const zcu = f.object.dg.zcu; const ty_op = f.air.instructions.items(.data)[@intFromEnum(inst)].ty_op; const operand = try f.resolveInst(ty_op.operand); try reap(f, inst, &.{ty_op.operand}); const inst_ty = f.typeOfIndex(inst); - const inst_scalar_ty = inst_ty.scalarType(mod); + const inst_scalar_ty = inst_ty.scalarType(zcu); const operand_ty = f.typeOf(ty_op.operand); - const scalar_ty = operand_ty.scalarType(mod); + const scalar_ty = operand_ty.scalarType(zcu); const writer = f.object.writer(); const local = try f.allocLocal(inst, inst_ty); @@ -3722,20 +3794,20 @@ fn airIntCast(f: *Function, inst: Air.Inst.Index) !CValue { } fn airTrunc(f: *Function, inst: Air.Inst.Index) !CValue { - const mod = f.object.dg.module; + const zcu = f.object.dg.zcu; const ty_op = f.air.instructions.items(.data)[@intFromEnum(inst)].ty_op; const operand = try f.resolveInst(ty_op.operand); try reap(f, inst, &.{ty_op.operand}); const inst_ty = f.typeOfIndex(inst); - const inst_scalar_ty = inst_ty.scalarType(mod); - const dest_int_info = inst_scalar_ty.intInfo(mod); + const inst_scalar_ty = inst_ty.scalarType(zcu); + const dest_int_info = inst_scalar_ty.intInfo(zcu); const dest_bits = dest_int_info.bits; const dest_c_bits = toCIntBits(dest_int_info.bits) orelse return f.fail("TODO: C backend: implement integer types larger than 128 bits", .{}); const operand_ty = f.typeOf(ty_op.operand); - const scalar_ty = operand_ty.scalarType(mod); - const scalar_int_info = scalar_ty.intInfo(mod); + const scalar_ty = operand_ty.scalarType(zcu); + const scalar_int_info = scalar_ty.intInfo(zcu); const writer = f.object.writer(); const local = try f.allocLocal(inst, inst_ty); @@ -3763,18 +3835,19 @@ fn airTrunc(f: *Function, inst: Air.Inst.Index) !CValue { try v.elem(f, writer); } else switch (dest_int_info.signedness) { .unsigned => { - const mask_val = try inst_scalar_ty.maxIntScalar(mod, scalar_ty); try writer.writeAll("zig_and_"); try f.object.dg.renderTypeForBuiltinFnName(writer, scalar_ty); try writer.writeByte('('); try f.writeCValue(writer, operand, .FunctionArgument); try v.elem(f, writer); - try writer.print(", {x})", .{try f.fmtIntLiteral(scalar_ty, mask_val)}); + try writer.print(", {x})", .{ + try f.fmtIntLiteral(try inst_scalar_ty.maxIntScalar(zcu, scalar_ty)), + }); }, .signed => { const c_bits = toCIntBits(scalar_int_info.bits) orelse return f.fail("TODO: C backend: implement integer types larger than 128 bits", .{}); - const shift_val = try mod.intValue(Type.u8, c_bits - dest_bits); + const shift_val = try zcu.intValue(Type.u8, c_bits - dest_bits); try writer.writeAll("zig_shr_"); try f.object.dg.renderTypeForBuiltinFnName(writer, scalar_ty); @@ -3792,9 +3865,9 @@ fn airTrunc(f: *Function, inst: Air.Inst.Index) !CValue { try f.writeCValue(writer, operand, .FunctionArgument); try v.elem(f, writer); if (c_bits == 128) try writer.writeByte(')'); - try writer.print(", {})", .{try f.fmtIntLiteral(Type.u8, shift_val)}); + try writer.print(", {})", .{try f.fmtIntLiteral(shift_val)}); if (c_bits == 128) try writer.writeByte(')'); - try writer.print(", {})", .{try f.fmtIntLiteral(Type.u8, shift_val)}); + try writer.print(", {})", .{try f.fmtIntLiteral(shift_val)}); }, } @@ -3821,18 +3894,18 @@ fn airIntFromBool(f: *Function, inst: Air.Inst.Index) !CValue { } fn airStore(f: *Function, inst: Air.Inst.Index, safety: bool) !CValue { - const mod = f.object.dg.module; + const zcu = f.object.dg.zcu; // *a = b; const bin_op = f.air.instructions.items(.data)[@intFromEnum(inst)].bin_op; const ptr_ty = f.typeOf(bin_op.lhs); - const ptr_scalar_ty = ptr_ty.scalarType(mod); - const ptr_info = ptr_scalar_ty.ptrInfo(mod); + const ptr_scalar_ty = ptr_ty.scalarType(zcu); + const ptr_info = ptr_scalar_ty.ptrInfo(zcu); const ptr_val = try f.resolveInst(bin_op.lhs); const src_ty = f.typeOf(bin_op.rhs); - const val_is_undef = if (try f.air.value(bin_op.rhs, mod)) |v| v.isUndefDeep(mod) else false; + const val_is_undef = if (try f.air.value(bin_op.rhs, zcu)) |v| v.isUndefDeep(zcu) else false; if (val_is_undef) { try reap(f, inst, &.{ bin_op.lhs, bin_op.rhs }); @@ -3848,10 +3921,10 @@ fn airStore(f: *Function, inst: Air.Inst.Index, safety: bool) !CValue { } const is_aligned = if (ptr_info.flags.alignment != .none) - ptr_info.flags.alignment.compare(.gte, src_ty.abiAlignment(mod)) + ptr_info.flags.alignment.compare(.gte, src_ty.abiAlignment(zcu)) else true; - const is_array = lowersToArray(Type.fromInterned(ptr_info.child), mod); + const is_array = lowersToArray(Type.fromInterned(ptr_info.child), zcu); const need_memcpy = !is_aligned or is_array; const src_val = try f.resolveInst(bin_op.rhs); @@ -3863,7 +3936,7 @@ fn airStore(f: *Function, inst: Air.Inst.Index, safety: bool) !CValue { if (need_memcpy) { // For this memcpy to safely work we need the rhs to have the same // underlying type as the lhs (i.e. they must both be arrays of the same underlying type). - assert(src_ty.eql(Type.fromInterned(ptr_info.child), f.object.dg.module)); + assert(src_ty.eql(Type.fromInterned(ptr_info.child), f.object.dg.zcu)); // If the source is a constant, writeCValue will emit a brace initialization // so work around this by initializing into new local. @@ -3893,12 +3966,12 @@ fn airStore(f: *Function, inst: Air.Inst.Index, safety: bool) !CValue { } } else if (ptr_info.packed_offset.host_size > 0 and ptr_info.flags.vector_index == .none) { const host_bits = ptr_info.packed_offset.host_size * 8; - const host_ty = try mod.intType(.unsigned, host_bits); + const host_ty = try zcu.intType(.unsigned, host_bits); - const bit_offset_ty = try mod.intType(.unsigned, Type.smallestUnsignedBits(host_bits - 1)); - const bit_offset_val = try mod.intValue(bit_offset_ty, ptr_info.packed_offset.bit_offset); + const bit_offset_ty = try zcu.intType(.unsigned, Type.smallestUnsignedBits(host_bits - 1)); + const bit_offset_val = try zcu.intValue(bit_offset_ty, ptr_info.packed_offset.bit_offset); - const src_bits = src_ty.bitSize(mod); + const src_bits = src_ty.bitSize(zcu); const ExpectedContents = [BigInt.Managed.default_capacity]BigIntLimb; var stack align(@alignOf(ExpectedContents)) = @@ -3911,7 +3984,7 @@ fn airStore(f: *Function, inst: Air.Inst.Index, safety: bool) !CValue { try mask.shiftLeft(&mask, ptr_info.packed_offset.bit_offset); try mask.bitNotWrap(&mask, .unsigned, host_bits); - const mask_val = try mod.intValue_big(host_ty, mask.toConst()); + const mask_val = try zcu.intValue_big(host_ty, mask.toConst()); try f.writeCValueDeref(writer, ptr_val); try v.elem(f, writer); @@ -3922,12 +3995,12 @@ fn airStore(f: *Function, inst: Air.Inst.Index, safety: bool) !CValue { try writer.writeByte('('); try f.writeCValueDeref(writer, ptr_val); try v.elem(f, writer); - try writer.print(", {x}), zig_shl_", .{try f.fmtIntLiteral(host_ty, mask_val)}); + try writer.print(", {x}), zig_shl_", .{try f.fmtIntLiteral(mask_val)}); try f.object.dg.renderTypeForBuiltinFnName(writer, host_ty); try writer.writeByte('('); - const cant_cast = host_ty.isInt(mod) and host_ty.bitSize(mod) > 64; + const cant_cast = host_ty.isInt(zcu) and host_ty.bitSize(zcu) > 64; if (cant_cast) { - if (src_ty.bitSize(mod) > 64) return f.fail("TODO: C backend: implement casting between types > 64 bits", .{}); + if (src_ty.bitSize(zcu) > 64) return f.fail("TODO: C backend: implement casting between types > 64 bits", .{}); try writer.writeAll("zig_make_"); try f.object.dg.renderTypeForBuiltinFnName(writer, host_ty); try writer.writeAll("(0, "); @@ -3937,7 +4010,7 @@ fn airStore(f: *Function, inst: Air.Inst.Index, safety: bool) !CValue { try writer.writeByte(')'); } - if (src_ty.isPtrAtRuntime(mod)) { + if (src_ty.isPtrAtRuntime(zcu)) { try writer.writeByte('('); try f.renderType(writer, Type.usize); try writer.writeByte(')'); @@ -3945,7 +4018,7 @@ fn airStore(f: *Function, inst: Air.Inst.Index, safety: bool) !CValue { try f.writeCValue(writer, src_val, .Other); try v.elem(f, writer); if (cant_cast) try writer.writeByte(')'); - try writer.print(", {}))", .{try f.fmtIntLiteral(bit_offset_ty, bit_offset_val)}); + try writer.print(", {}))", .{try f.fmtIntLiteral(bit_offset_val)}); } else { try f.writeCValueDeref(writer, ptr_val); try v.elem(f, writer); @@ -3960,7 +4033,7 @@ fn airStore(f: *Function, inst: Air.Inst.Index, safety: bool) !CValue { } fn airOverflow(f: *Function, inst: Air.Inst.Index, operation: []const u8, info: BuiltinInfo) !CValue { - const mod = f.object.dg.module; + const zcu = f.object.dg.zcu; const ty_pl = f.air.instructions.items(.data)[@intFromEnum(inst)].ty_pl; const bin_op = f.air.extraData(Air.Bin, ty_pl.payload).data; @@ -3970,7 +4043,7 @@ fn airOverflow(f: *Function, inst: Air.Inst.Index, operation: []const u8, info: const inst_ty = f.typeOfIndex(inst); const operand_ty = f.typeOf(bin_op.lhs); - const scalar_ty = operand_ty.scalarType(mod); + const scalar_ty = operand_ty.scalarType(zcu); const w = f.object.writer(); const local = try f.allocLocal(inst, inst_ty); @@ -3998,11 +4071,11 @@ fn airOverflow(f: *Function, inst: Air.Inst.Index, operation: []const u8, info: } fn airNot(f: *Function, inst: Air.Inst.Index) !CValue { - const mod = f.object.dg.module; + const zcu = f.object.dg.zcu; const ty_op = f.air.instructions.items(.data)[@intFromEnum(inst)].ty_op; const operand_ty = f.typeOf(ty_op.operand); - const scalar_ty = operand_ty.scalarType(mod); - if (scalar_ty.ip_index != .bool_type) return try airUnBuiltinCall(f, inst, "not", .bits); + const scalar_ty = operand_ty.scalarType(zcu); + if (scalar_ty.toIntern() != .bool_type) return try airUnBuiltinCall(f, inst, "not", .bits); const op = try f.resolveInst(ty_op.operand); try reap(f, inst, &.{ty_op.operand}); @@ -4031,11 +4104,11 @@ fn airBinOp( operation: []const u8, info: BuiltinInfo, ) !CValue { - const mod = f.object.dg.module; + const zcu = f.object.dg.zcu; const bin_op = f.air.instructions.items(.data)[@intFromEnum(inst)].bin_op; const operand_ty = f.typeOf(bin_op.lhs); - const scalar_ty = operand_ty.scalarType(mod); - if ((scalar_ty.isInt(mod) and scalar_ty.bitSize(mod) > 64) or scalar_ty.isRuntimeFloat()) + const scalar_ty = operand_ty.scalarType(zcu); + if ((scalar_ty.isInt(zcu) and scalar_ty.bitSize(zcu) > 64) or scalar_ty.isRuntimeFloat()) return try airBinBuiltinCall(f, inst, operation, info); const lhs = try f.resolveInst(bin_op.lhs); @@ -4069,12 +4142,12 @@ fn airCmpOp( data: anytype, operator: std.math.CompareOperator, ) !CValue { - const mod = f.object.dg.module; + const zcu = f.object.dg.zcu; const lhs_ty = f.typeOf(data.lhs); - const scalar_ty = lhs_ty.scalarType(mod); + const scalar_ty = lhs_ty.scalarType(zcu); - const scalar_bits = scalar_ty.bitSize(mod); - if (scalar_ty.isInt(mod) and scalar_bits > 64) + const scalar_bits = scalar_ty.bitSize(zcu); + if (scalar_ty.isInt(zcu) and scalar_bits > 64) return airCmpBuiltinCall( f, inst, @@ -4092,7 +4165,7 @@ fn airCmpOp( try reap(f, inst, &.{ data.lhs, data.rhs }); const rhs_ty = f.typeOf(data.rhs); - const need_cast = lhs_ty.isSinglePointer(mod) or rhs_ty.isSinglePointer(mod); + const need_cast = lhs_ty.isSinglePointer(zcu) or rhs_ty.isSinglePointer(zcu); const writer = f.object.writer(); const local = try f.allocLocal(inst, inst_ty); const v = try Vectorize.start(f, inst, writer, lhs_ty); @@ -4117,12 +4190,12 @@ fn airEquality( inst: Air.Inst.Index, operator: std.math.CompareOperator, ) !CValue { - const mod = f.object.dg.module; + const zcu = f.object.dg.zcu; const bin_op = f.air.instructions.items(.data)[@intFromEnum(inst)].bin_op; const operand_ty = f.typeOf(bin_op.lhs); - const operand_bits = operand_ty.bitSize(mod); - if (operand_ty.isInt(mod) and operand_bits > 64) + const operand_bits = operand_ty.bitSize(zcu); + if (operand_ty.isInt(zcu) and operand_bits > 64) return airCmpBuiltinCall( f, inst, @@ -4145,7 +4218,7 @@ fn airEquality( try f.writeCValue(writer, local, .Other); try a.assign(f, writer); - if (operand_ty.zigTypeTag(mod) == .Optional and !operand_ty.optionalReprIsPayload(mod)) { + if (operand_ty.zigTypeTag(zcu) == .Optional and !operand_ty.optionalReprIsPayload(zcu)) { try f.writeCValueMember(writer, lhs, .{ .identifier = "is_null" }); try writer.writeAll(" || "); try f.writeCValueMember(writer, rhs, .{ .identifier = "is_null" }); @@ -4184,7 +4257,7 @@ fn airCmpLtErrorsLen(f: *Function, inst: Air.Inst.Index) !CValue { } fn airPtrAddSub(f: *Function, inst: Air.Inst.Index, operator: u8) !CValue { - const mod = f.object.dg.module; + const zcu = f.object.dg.zcu; const ty_pl = f.air.instructions.items(.data)[@intFromEnum(inst)].ty_pl; const bin_op = f.air.extraData(Air.Bin, ty_pl.payload).data; @@ -4193,8 +4266,8 @@ fn airPtrAddSub(f: *Function, inst: Air.Inst.Index, operator: u8) !CValue { try reap(f, inst, &.{ bin_op.lhs, bin_op.rhs }); const inst_ty = f.typeOfIndex(inst); - const inst_scalar_ty = inst_ty.scalarType(mod); - const elem_ty = inst_scalar_ty.elemType2(mod); + const inst_scalar_ty = inst_ty.scalarType(zcu); + const elem_ty = inst_scalar_ty.elemType2(zcu); const local = try f.allocLocal(inst, inst_ty); const writer = f.object.writer(); @@ -4203,7 +4276,7 @@ fn airPtrAddSub(f: *Function, inst: Air.Inst.Index, operator: u8) !CValue { try v.elem(f, writer); try writer.writeAll(" = "); - if (elem_ty.hasRuntimeBitsIgnoreComptime(mod)) { + if (elem_ty.hasRuntimeBitsIgnoreComptime(zcu)) { // We must convert to and from integer types to prevent UB if the operation // results in a NULL pointer, or if LHS is NULL. The operation is only UB // if the result is NULL and then dereferenced. @@ -4232,13 +4305,13 @@ fn airPtrAddSub(f: *Function, inst: Air.Inst.Index, operator: u8) !CValue { } fn airMinMax(f: *Function, inst: Air.Inst.Index, operator: u8, operation: []const u8) !CValue { - const mod = f.object.dg.module; + const zcu = f.object.dg.zcu; const bin_op = f.air.instructions.items(.data)[@intFromEnum(inst)].bin_op; const inst_ty = f.typeOfIndex(inst); - const inst_scalar_ty = inst_ty.scalarType(mod); + const inst_scalar_ty = inst_ty.scalarType(zcu); - if (inst_scalar_ty.isInt(mod) and inst_scalar_ty.bitSize(mod) > 64) + if (inst_scalar_ty.isInt(zcu) and inst_scalar_ty.bitSize(zcu) > 64) return try airBinBuiltinCall(f, inst, operation[1..], .none); if (inst_scalar_ty.isRuntimeFloat()) return try airBinFloatOp(f, inst, operation); @@ -4274,7 +4347,7 @@ fn airMinMax(f: *Function, inst: Air.Inst.Index, operator: u8, operation: []cons } fn airSlice(f: *Function, inst: Air.Inst.Index) !CValue { - const mod = f.object.dg.module; + const zcu = f.object.dg.zcu; const ty_pl = f.air.instructions.items(.data)[@intFromEnum(inst)].ty_pl; const bin_op = f.air.extraData(Air.Bin, ty_pl.payload).data; @@ -4283,7 +4356,7 @@ fn airSlice(f: *Function, inst: Air.Inst.Index) !CValue { try reap(f, inst, &.{ bin_op.lhs, bin_op.rhs }); const inst_ty = f.typeOfIndex(inst); - const ptr_ty = inst_ty.slicePtrFieldType(mod); + const ptr_ty = inst_ty.slicePtrFieldType(zcu); const writer = f.object.writer(); const local = try f.allocLocal(inst, inst_ty); @@ -4291,9 +4364,6 @@ fn airSlice(f: *Function, inst: Air.Inst.Index) !CValue { const a = try Assignment.start(f, writer, ptr_ty); try f.writeCValueMember(writer, local, .{ .identifier = "ptr" }); try a.assign(f, writer); - try writer.writeByte('('); - try f.renderType(writer, ptr_ty); - try writer.writeByte(')'); try f.writeCValue(writer, ptr, .Other); try a.end(f, writer); } @@ -4301,7 +4371,7 @@ fn airSlice(f: *Function, inst: Air.Inst.Index) !CValue { const a = try Assignment.start(f, writer, Type.usize); try f.writeCValueMember(writer, local, .{ .identifier = "len" }); try a.assign(f, writer); - try f.writeCValue(writer, len, .Other); + try f.writeCValue(writer, len, .Initializer); try a.end(f, writer); } return local; @@ -4312,7 +4382,7 @@ fn airCall( inst: Air.Inst.Index, modifier: std.builtin.CallModifier, ) !CValue { - const mod = f.object.dg.module; + const zcu = f.object.dg.zcu; // Not even allowed to call panic in a naked function. if (f.object.dg.is_naked_fn) return .none; @@ -4334,7 +4404,7 @@ fn airCall( } resolved_arg.* = try f.resolveInst(arg); if (arg_cty != try f.typeToIndex(arg_ty, .complete)) { - const lowered_arg_ty = try lowerFnRetTy(arg_ty, mod); + const lowered_arg_ty = try lowerFnRetTy(arg_ty, zcu); const array_local = try f.allocLocal(inst, lowered_arg_ty); try writer.writeAll("memcpy("); @@ -4357,20 +4427,19 @@ fn airCall( } const callee_ty = f.typeOf(pl_op.operand); - const fn_ty = switch (callee_ty.zigTypeTag(mod)) { + const fn_info = zcu.typeToFunc(switch (callee_ty.zigTypeTag(zcu)) { .Fn => callee_ty, - .Pointer => callee_ty.childType(mod), + .Pointer => callee_ty.childType(zcu), else => unreachable, - }; - - const ret_ty = fn_ty.fnReturnType(mod); - const lowered_ret_ty = try lowerFnRetTy(ret_ty, mod); + }).?; + const ret_ty = Type.fromInterned(fn_info.return_type); + const lowered_ret_ty = try lowerFnRetTy(ret_ty, zcu); const result_local = result: { if (modifier == .always_tail) { try writer.writeAll("zig_always_tail return "); break :result .none; - } else if (!lowered_ret_ty.hasRuntimeBitsIgnoreComptime(mod)) { + } else if (!lowered_ret_ty.hasRuntimeBitsIgnoreComptime(zcu)) { break :result .none; } else if (f.liveness.isUnused(inst)) { try writer.writeByte('('); @@ -4388,8 +4457,8 @@ fn airCall( callee: { known: { const fn_decl = fn_decl: { - const callee_val = (try f.air.value(pl_op.operand, mod)) orelse break :known; - break :fn_decl switch (mod.intern_pool.indexToKey(callee_val.ip_index)) { + const callee_val = (try f.air.value(pl_op.operand, zcu)) orelse break :known; + break :fn_decl switch (zcu.intern_pool.indexToKey(callee_val.toIntern())) { .extern_func => |extern_func| extern_func.decl, .func => |func| func.owner_decl, .ptr => |ptr| switch (ptr.addr) { @@ -4420,18 +4489,21 @@ fn airCall( } try writer.writeByte('('); - var args_written: usize = 0; + var need_comma = false; for (resolved_args) |resolved_arg| { if (resolved_arg == .none) continue; - if (args_written != 0) try writer.writeAll(", "); + if (need_comma) try writer.writeAll(", "); + need_comma = true; try f.writeCValue(writer, resolved_arg, .FunctionArgument); - if (resolved_arg == .new_local) try freeLocal(f, inst, resolved_arg.new_local, null); - args_written += 1; + switch (resolved_arg) { + .new_local => |local| try freeLocal(f, inst, local, null), + else => {}, + } } try writer.writeAll(");\n"); const result = result: { - if (result_local == .none or !lowersToArray(ret_ty, mod)) + if (result_local == .none or !lowersToArray(ret_ty, zcu)) break :result result_local; const array_local = try f.allocLocal(inst, ret_ty); @@ -4465,22 +4537,22 @@ fn airDbgStmt(f: *Function, inst: Air.Inst.Index) !CValue { } fn airDbgInlineBlock(f: *Function, inst: Air.Inst.Index) !CValue { - const mod = f.object.dg.module; + const zcu = f.object.dg.zcu; const ty_pl = f.air.instructions.items(.data)[@intFromEnum(inst)].ty_pl; const extra = f.air.extraData(Air.DbgInlineBlock, ty_pl.payload); - const owner_decl = mod.funcOwnerDeclPtr(extra.data.func); + const owner_decl = zcu.funcOwnerDeclPtr(extra.data.func); const writer = f.object.writer(); try writer.writeAll("/* "); - try owner_decl.renderFullyQualifiedName(mod, writer); + try owner_decl.renderFullyQualifiedName(zcu, writer); try writer.writeAll(" */ "); return lowerBlock(f, inst, @ptrCast(f.air.extra[extra.end..][0..extra.data.body_len])); } fn airDbgVar(f: *Function, inst: Air.Inst.Index) !CValue { - const mod = f.object.dg.module; + const zcu = f.object.dg.zcu; const pl_op = f.air.instructions.items(.data)[@intFromEnum(inst)].pl_op; const name = f.air.nullTerminatedString(pl_op.payload); - const operand_is_undef = if (try f.air.value(pl_op.operand, mod)) |v| v.isUndefDeep(mod) else false; + const operand_is_undef = if (try f.air.value(pl_op.operand, zcu)) |v| v.isUndefDeep(zcu) else false; if (!operand_is_undef) _ = try f.resolveInst(pl_op.operand); try reap(f, inst, &.{pl_op.operand}); @@ -4496,7 +4568,7 @@ fn airBlock(f: *Function, inst: Air.Inst.Index) !CValue { } fn lowerBlock(f: *Function, inst: Air.Inst.Index, body: []const Air.Inst.Index) !CValue { - const mod = f.object.dg.module; + const zcu = f.object.dg.zcu; const liveness_block = f.liveness.getBlock(inst); const block_id: usize = f.next_block_index; @@ -4504,7 +4576,7 @@ fn lowerBlock(f: *Function, inst: Air.Inst.Index, body: []const Air.Inst.Index) const writer = f.object.writer(); const inst_ty = f.typeOfIndex(inst); - const result = if (inst_ty.hasRuntimeBitsIgnoreComptime(mod) and !f.liveness.isUnused(inst)) + const result = if (inst_ty.hasRuntimeBitsIgnoreComptime(zcu) and !f.liveness.isUnused(inst)) try f.allocLocal(inst, inst_ty) else .none; @@ -4526,7 +4598,7 @@ fn lowerBlock(f: *Function, inst: Air.Inst.Index, body: []const Air.Inst.Index) try f.object.indent_writer.insertNewline(); // noreturn blocks have no `br` instructions reaching them, so we don't want a label - if (!f.typeOfIndex(inst).isNoReturn(mod)) { + if (!f.typeOfIndex(inst).isNoReturn(zcu)) { // label must be followed by an expression, include an empty one. try writer.print("zig_block_{d}:;\n", .{block_id}); } @@ -4543,11 +4615,11 @@ fn airTry(f: *Function, inst: Air.Inst.Index) !CValue { } fn airTryPtr(f: *Function, inst: Air.Inst.Index) !CValue { - const mod = f.object.dg.module; + const zcu = f.object.dg.zcu; const ty_pl = f.air.instructions.items(.data)[@intFromEnum(inst)].ty_pl; const extra = f.air.extraData(Air.TryPtr, ty_pl.payload); const body: []const Air.Inst.Index = @ptrCast(f.air.extra[extra.end..][0..extra.data.body_len]); - const err_union_ty = f.typeOf(extra.data.ptr).childType(mod); + const err_union_ty = f.typeOf(extra.data.ptr).childType(zcu); return lowerTry(f, inst, extra.data.ptr, body, err_union_ty, true); } @@ -4559,15 +4631,15 @@ fn lowerTry( err_union_ty: Type, is_ptr: bool, ) !CValue { - const mod = f.object.dg.module; + const zcu = f.object.dg.zcu; const err_union = try f.resolveInst(operand); const inst_ty = f.typeOfIndex(inst); const liveness_condbr = f.liveness.getCondBr(inst); const writer = f.object.writer(); - const payload_ty = err_union_ty.errorUnionPayload(mod); - const payload_has_bits = payload_ty.hasRuntimeBitsIgnoreComptime(mod); + const payload_ty = err_union_ty.errorUnionPayload(zcu); + const payload_has_bits = payload_ty.hasRuntimeBitsIgnoreComptime(zcu); - if (!err_union_ty.errorUnionSet(mod).errorSetIsEmpty(mod)) { + if (!err_union_ty.errorUnionSet(zcu).errorSetIsEmpty(zcu)) { try writer.writeAll("if ("); if (!payload_has_bits) { if (is_ptr) @@ -4661,7 +4733,7 @@ const LocalResult = struct { need_free: bool, fn move(lr: LocalResult, f: *Function, inst: Air.Inst.Index, dest_ty: Type) !CValue { - const mod = f.object.dg.module; + const zcu = f.object.dg.zcu; if (lr.need_free) { // Move the freshly allocated local to be owned by this instruction, @@ -4673,7 +4745,7 @@ const LocalResult = struct { try lr.free(f); const writer = f.object.writer(); try f.writeCValue(writer, local, .Other); - if (dest_ty.isAbiInt(mod)) { + if (dest_ty.isAbiInt(zcu)) { try writer.writeAll(" = "); } else { try writer.writeAll(" = ("); @@ -4693,13 +4765,13 @@ const LocalResult = struct { }; fn bitcast(f: *Function, dest_ty: Type, operand: CValue, operand_ty: Type) !LocalResult { - const mod = f.object.dg.module; - const target = mod.getTarget(); + const zcu = f.object.dg.zcu; + const target = &f.object.dg.mod.resolved_target.result; const writer = f.object.writer(); - if (operand_ty.isAbiInt(mod) and dest_ty.isAbiInt(mod)) { - const src_info = dest_ty.intInfo(mod); - const dest_info = operand_ty.intInfo(mod); + if (operand_ty.isAbiInt(zcu) and dest_ty.isAbiInt(zcu)) { + const src_info = dest_ty.intInfo(zcu); + const dest_info = operand_ty.intInfo(zcu); if (src_info.signedness == dest_info.signedness and src_info.bits == dest_info.bits) { @@ -4710,7 +4782,7 @@ fn bitcast(f: *Function, dest_ty: Type, operand: CValue, operand_ty: Type) !Loca } } - if (dest_ty.isPtrAtRuntime(mod) and operand_ty.isPtrAtRuntime(mod)) { + if (dest_ty.isPtrAtRuntime(zcu) and operand_ty.isPtrAtRuntime(zcu)) { const local = try f.allocLocal(null, dest_ty); try f.writeCValue(writer, local, .Other); try writer.writeAll(" = ("); @@ -4727,7 +4799,7 @@ fn bitcast(f: *Function, dest_ty: Type, operand: CValue, operand_ty: Type) !Loca const operand_lval = if (operand == .constant) blk: { const operand_local = try f.allocLocal(null, operand_ty); try f.writeCValue(writer, operand_local, .Other); - if (operand_ty.isAbiInt(mod)) { + if (operand_ty.isAbiInt(zcu)) { try writer.writeAll(" = "); } else { try writer.writeAll(" = ("); @@ -4747,14 +4819,14 @@ fn bitcast(f: *Function, dest_ty: Type, operand: CValue, operand_ty: Type) !Loca try writer.writeAll(", sizeof("); try f.renderType( writer, - if (dest_ty.abiSize(mod) <= operand_ty.abiSize(mod)) dest_ty else operand_ty, + if (dest_ty.abiSize(zcu) <= operand_ty.abiSize(zcu)) dest_ty else operand_ty, ); try writer.writeAll("));\n"); // Ensure padding bits have the expected value. - if (dest_ty.isAbiInt(mod)) { + if (dest_ty.isAbiInt(zcu)) { const dest_cty = try f.typeToCType(dest_ty, .complete); - const dest_info = dest_ty.intInfo(mod); + const dest_info = dest_ty.intInfo(zcu); var bits: u16 = dest_info.bits; var wrap_cty: ?CType = null; var need_bitcasts = false; @@ -4779,7 +4851,7 @@ fn bitcast(f: *Function, dest_ty: Type, operand: CValue, operand_ty: Type) !Loca try writer.writeByte('('); } try writer.writeAll("zig_wrap_"); - const info_ty = try mod.intType(dest_info.signedness, bits); + const info_ty = try zcu.intType(dest_info.signedness, bits); if (wrap_cty) |cty| try f.object.dg.renderCTypeForBuiltinFnName(writer, cty) else @@ -4912,7 +4984,7 @@ fn airCondBr(f: *Function, inst: Air.Inst.Index) !CValue { } fn airSwitchBr(f: *Function, inst: Air.Inst.Index) !CValue { - const mod = f.object.dg.module; + const zcu = f.object.dg.zcu; const pl_op = f.air.instructions.items(.data)[@intFromEnum(inst)].pl_op; const condition = try f.resolveInst(pl_op.operand); try reap(f, inst, &.{pl_op.operand}); @@ -4921,11 +4993,11 @@ fn airSwitchBr(f: *Function, inst: Air.Inst.Index) !CValue { const writer = f.object.writer(); try writer.writeAll("switch ("); - if (condition_ty.zigTypeTag(mod) == .Bool) { + if (condition_ty.zigTypeTag(zcu) == .Bool) { try writer.writeByte('('); try f.renderType(writer, Type.u1); try writer.writeByte(')'); - } else if (condition_ty.isPtrAtRuntime(mod)) { + } else if (condition_ty.isPtrAtRuntime(zcu)) { try writer.writeByte('('); try f.renderType(writer, Type.usize); try writer.writeByte(')'); @@ -4952,12 +5024,12 @@ fn airSwitchBr(f: *Function, inst: Air.Inst.Index) !CValue { for (items) |item| { try f.object.indent_writer.insertNewline(); try writer.writeAll("case "); - if (condition_ty.isPtrAtRuntime(mod)) { + if (condition_ty.isPtrAtRuntime(zcu)) { try writer.writeByte('('); try f.renderType(writer, Type.usize); try writer.writeByte(')'); } - try f.object.dg.renderValue(writer, condition_ty, (try f.air.value(item, mod)).?, .Other); + try f.object.dg.renderValue(writer, (try f.air.value(item, zcu)).?, .Other); try writer.writeByte(':'); } try writer.writeByte(' '); @@ -4994,13 +5066,13 @@ fn airSwitchBr(f: *Function, inst: Air.Inst.Index) !CValue { } fn asmInputNeedsLocal(f: *Function, constraint: []const u8, value: CValue) bool { - const target = f.object.dg.module.getTarget(); + const target = &f.object.dg.mod.resolved_target.result; return switch (constraint[0]) { '{' => true, 'i', 'r' => false, 'I' => !target.cpu.arch.isArmOrThumb(), else => switch (value) { - .constant => |val| switch (f.object.dg.module.intern_pool.indexToKey(val)) { + .constant => |val| switch (f.object.dg.zcu.intern_pool.indexToKey(val.toIntern())) { .ptr => |ptr| switch (ptr.addr) { .decl => false, else => true, @@ -5013,7 +5085,7 @@ fn asmInputNeedsLocal(f: *Function, constraint: []const u8, value: CValue) bool } fn airAsm(f: *Function, inst: Air.Inst.Index) !CValue { - const mod = f.object.dg.module; + const zcu = f.object.dg.zcu; const ty_pl = f.air.instructions.items(.data)[@intFromEnum(inst)].ty_pl; const extra = f.air.extraData(Air.Asm, ty_pl.payload); const is_volatile = @as(u1, @truncate(extra.data.flags >> 31)) != 0; @@ -5028,7 +5100,7 @@ fn airAsm(f: *Function, inst: Air.Inst.Index) !CValue { const result = result: { const writer = f.object.writer(); const inst_ty = f.typeOfIndex(inst); - const local = if (inst_ty.hasRuntimeBitsIgnoreComptime(mod)) local: { + const local = if (inst_ty.hasRuntimeBitsIgnoreComptime(zcu)) local: { const local = try f.allocLocal(inst, inst_ty); if (f.wantSafety()) { try f.writeCValue(writer, local, .Other); @@ -5057,7 +5129,7 @@ fn airAsm(f: *Function, inst: Air.Inst.Index) !CValue { const is_reg = constraint[1] == '{'; if (is_reg) { - const output_ty = if (output == .none) inst_ty else f.typeOf(output).childType(mod); + const output_ty = if (output == .none) inst_ty else f.typeOf(output).childType(zcu); try writer.writeAll("register "); const alignment: Alignment = .none; const local_value = try f.allocLocalValue(output_ty, alignment); @@ -5275,7 +5347,7 @@ fn airIsNull( operator: []const u8, is_ptr: bool, ) !CValue { - const mod = f.object.dg.module; + const zcu = f.object.dg.zcu; const un_op = f.air.instructions.items(.data)[@intFromEnum(inst)].un_op; const writer = f.object.writer(); @@ -5292,22 +5364,22 @@ fn airIsNull( } const operand_ty = f.typeOf(un_op); - const optional_ty = if (is_ptr) operand_ty.childType(mod) else operand_ty; - const payload_ty = optional_ty.optionalChild(mod); - const err_int_ty = try mod.errorIntType(); + const optional_ty = if (is_ptr) operand_ty.childType(zcu) else operand_ty; + const payload_ty = optional_ty.optionalChild(zcu); + const err_int_ty = try zcu.errorIntType(); - const rhs = if (!payload_ty.hasRuntimeBitsIgnoreComptime(mod)) + const rhs = if (!payload_ty.hasRuntimeBitsIgnoreComptime(zcu)) Value.true - else if (optional_ty.isPtrLikeOptional(mod)) + else if (optional_ty.isPtrLikeOptional(zcu)) // operand is a regular pointer, test `operand !=/== NULL` - try mod.getCoerced(Value.null, optional_ty) - else if (payload_ty.zigTypeTag(mod) == .ErrorSet) - try mod.intValue(err_int_ty, 0) - else if (payload_ty.isSlice(mod) and optional_ty.optionalReprIsPayload(mod)) rhs: { + try zcu.getCoerced(Value.null, optional_ty) + else if (payload_ty.zigTypeTag(zcu) == .ErrorSet) + try zcu.intValue(err_int_ty, 0) + else if (payload_ty.isSlice(zcu) and optional_ty.optionalReprIsPayload(zcu)) rhs: { try writer.writeAll(".ptr"); - const slice_ptr_ty = payload_ty.slicePtrFieldType(mod); - const opt_slice_ptr_ty = try mod.optionalType(slice_ptr_ty.toIntern()); - break :rhs try mod.nullValue(opt_slice_ptr_ty); + const slice_ptr_ty = payload_ty.slicePtrFieldType(zcu); + const opt_slice_ptr_ty = try zcu.optionalType(slice_ptr_ty.toIntern()); + break :rhs try zcu.nullValue(opt_slice_ptr_ty); } else rhs: { try writer.writeAll(".is_null"); break :rhs Value.true; @@ -5315,22 +5387,22 @@ fn airIsNull( try writer.writeByte(' '); try writer.writeAll(operator); try writer.writeByte(' '); - try f.object.dg.renderValue(writer, rhs.typeOf(mod), rhs, .Other); + try f.object.dg.renderValue(writer, rhs, .Other); try writer.writeAll(";\n"); return local; } fn airOptionalPayload(f: *Function, inst: Air.Inst.Index) !CValue { - const mod = f.object.dg.module; + const zcu = f.object.dg.zcu; const ty_op = f.air.instructions.items(.data)[@intFromEnum(inst)].ty_op; const operand = try f.resolveInst(ty_op.operand); try reap(f, inst, &.{ty_op.operand}); const opt_ty = f.typeOf(ty_op.operand); - const payload_ty = opt_ty.optionalChild(mod); + const payload_ty = opt_ty.optionalChild(zcu); - if (!payload_ty.hasRuntimeBitsIgnoreComptime(mod)) { + if (!payload_ty.hasRuntimeBitsIgnoreComptime(zcu)) { return .none; } @@ -5338,7 +5410,7 @@ fn airOptionalPayload(f: *Function, inst: Air.Inst.Index) !CValue { const writer = f.object.writer(); const local = try f.allocLocal(inst, inst_ty); - if (opt_ty.optionalReprIsPayload(mod)) { + if (opt_ty.optionalReprIsPayload(zcu)) { try f.writeCValue(writer, local, .Other); try writer.writeAll(" = "); try f.writeCValue(writer, operand, .Other); @@ -5355,24 +5427,24 @@ fn airOptionalPayload(f: *Function, inst: Air.Inst.Index) !CValue { } fn airOptionalPayloadPtr(f: *Function, inst: Air.Inst.Index) !CValue { - const mod = f.object.dg.module; + const zcu = f.object.dg.zcu; const ty_op = f.air.instructions.items(.data)[@intFromEnum(inst)].ty_op; const writer = f.object.writer(); const operand = try f.resolveInst(ty_op.operand); try reap(f, inst, &.{ty_op.operand}); const ptr_ty = f.typeOf(ty_op.operand); - const opt_ty = ptr_ty.childType(mod); + const opt_ty = ptr_ty.childType(zcu); const inst_ty = f.typeOfIndex(inst); - if (!inst_ty.childType(mod).hasRuntimeBitsIgnoreComptime(mod)) { + if (!inst_ty.childType(zcu).hasRuntimeBitsIgnoreComptime(zcu)) { return .{ .undef = inst_ty }; } const local = try f.allocLocal(inst, inst_ty); try f.writeCValue(writer, local, .Other); - if (opt_ty.optionalReprIsPayload(mod)) { + if (opt_ty.optionalReprIsPayload(zcu)) { // the operand is just a regular pointer, no need to do anything special. // *?*T -> **T and ?*T -> *T are **T -> **T and *T -> *T in C try writer.writeAll(" = "); @@ -5386,18 +5458,18 @@ fn airOptionalPayloadPtr(f: *Function, inst: Air.Inst.Index) !CValue { } fn airOptionalPayloadPtrSet(f: *Function, inst: Air.Inst.Index) !CValue { - const mod = f.object.dg.module; + const zcu = f.object.dg.zcu; const ty_op = f.air.instructions.items(.data)[@intFromEnum(inst)].ty_op; const writer = f.object.writer(); const operand = try f.resolveInst(ty_op.operand); try reap(f, inst, &.{ty_op.operand}); const operand_ty = f.typeOf(ty_op.operand); - const opt_ty = operand_ty.childType(mod); + const opt_ty = operand_ty.childType(zcu); const inst_ty = f.typeOfIndex(inst); - if (opt_ty.optionalReprIsPayload(mod)) { + if (opt_ty.optionalReprIsPayload(zcu)) { if (f.liveness.isUnused(inst)) { return .none; } @@ -5412,7 +5484,7 @@ fn airOptionalPayloadPtrSet(f: *Function, inst: Air.Inst.Index) !CValue { } else { try f.writeCValueDeref(writer, operand); try writer.writeAll(".is_null = "); - try f.object.dg.renderValue(writer, Type.bool, Value.false, .Initializer); + try f.object.dg.renderValue(writer, Value.false, .Initializer); try writer.writeAll(";\n"); if (f.liveness.isUnused(inst)) { @@ -5432,50 +5504,50 @@ fn fieldLocation( container_ptr_ty: Type, field_ptr_ty: Type, field_index: u32, - mod: *Module, + zcu: *Zcu, ) union(enum) { begin: void, field: CValue, byte_offset: u32, end: void, } { - const ip = &mod.intern_pool; - const container_ty = container_ptr_ty.childType(mod); - return switch (container_ty.zigTypeTag(mod)) { + const ip = &zcu.intern_pool; + const container_ty = container_ptr_ty.childType(zcu); + return switch (container_ty.zigTypeTag(zcu)) { .Struct => blk: { - if (mod.typeToPackedStruct(container_ty)) |struct_type| { - if (field_ptr_ty.ptrInfo(mod).packed_offset.host_size == 0) - break :blk .{ .byte_offset = @divExact(mod.structPackedFieldBitOffset(struct_type, field_index) + container_ptr_ty.ptrInfo(mod).packed_offset.bit_offset, 8) } + if (zcu.typeToPackedStruct(container_ty)) |struct_type| { + if (field_ptr_ty.ptrInfo(zcu).packed_offset.host_size == 0) + break :blk .{ .byte_offset = @divExact(zcu.structPackedFieldBitOffset(struct_type, field_index) + container_ptr_ty.ptrInfo(zcu).packed_offset.bit_offset, 8) } else break :blk .begin; } - for (field_index..container_ty.structFieldCount(mod)) |next_field_index_usize| { + for (field_index..container_ty.structFieldCount(zcu)) |next_field_index_usize| { const next_field_index: u32 = @intCast(next_field_index_usize); - if (container_ty.structFieldIsComptime(next_field_index, mod)) continue; - const field_ty = container_ty.structFieldType(next_field_index, mod); - if (!field_ty.hasRuntimeBitsIgnoreComptime(mod)) continue; + if (container_ty.structFieldIsComptime(next_field_index, zcu)) continue; + const field_ty = container_ty.structFieldType(next_field_index, zcu); + if (!field_ty.hasRuntimeBitsIgnoreComptime(zcu)) continue; - break :blk .{ .field = if (container_ty.isSimpleTuple(mod)) + break :blk .{ .field = if (container_ty.isSimpleTuple(zcu)) .{ .field = next_field_index } else - .{ .identifier = ip.stringToSlice(container_ty.legacyStructFieldName(next_field_index, mod)) } }; + .{ .identifier = ip.stringToSlice(container_ty.legacyStructFieldName(next_field_index, zcu)) } }; } - break :blk if (container_ty.hasRuntimeBitsIgnoreComptime(mod)) .end else .begin; + break :blk if (container_ty.hasRuntimeBitsIgnoreComptime(zcu)) .end else .begin; }, .Union => { - const union_obj = mod.typeToUnion(container_ty).?; + const union_obj = zcu.typeToUnion(container_ty).?; return switch (union_obj.getLayout(ip)) { .auto, .@"extern" => { const field_ty = Type.fromInterned(union_obj.field_types.get(ip)[field_index]); - if (!field_ty.hasRuntimeBitsIgnoreComptime(mod)) - return if (container_ty.unionTagTypeSafety(mod) != null and - !container_ty.unionHasAllZeroBitFieldTypes(mod)) + if (!field_ty.hasRuntimeBitsIgnoreComptime(zcu)) + return if (container_ty.unionTagTypeSafety(zcu) != null and + !container_ty.unionHasAllZeroBitFieldTypes(zcu)) .{ .field = .{ .identifier = "payload" } } else .begin; const field_name = union_obj.loadTagType(ip).names.get(ip)[field_index]; - return .{ .field = if (container_ty.unionTagTypeSafety(mod)) |_| + return .{ .field = if (container_ty.unionTagTypeSafety(zcu)) |_| .{ .payload_identifier = ip.stringToSlice(field_name) } else .{ .identifier = ip.stringToSlice(field_name) } }; @@ -5483,7 +5555,7 @@ fn fieldLocation( .@"packed" => .begin, }; }, - .Pointer => switch (container_ty.ptrSize(mod)) { + .Pointer => switch (container_ty.ptrSize(zcu)) { .Slice => switch (field_index) { 0 => .{ .field = .{ .identifier = "ptr" } }, 1 => .{ .field = .{ .identifier = "len" } }, @@ -5515,12 +5587,12 @@ fn airStructFieldPtrIndex(f: *Function, inst: Air.Inst.Index, index: u8) !CValue } fn airFieldParentPtr(f: *Function, inst: Air.Inst.Index) !CValue { - const mod = f.object.dg.module; + const zcu = f.object.dg.zcu; const ty_pl = f.air.instructions.items(.data)[@intFromEnum(inst)].ty_pl; const extra = f.air.extraData(Air.FieldParentPtr, ty_pl.payload).data; const container_ptr_ty = f.typeOfIndex(inst); - const container_ty = container_ptr_ty.childType(mod); + const container_ty = container_ptr_ty.childType(zcu); const field_ptr_ty = f.typeOf(extra.field_ptr); const field_ptr_val = try f.resolveInst(extra.field_ptr); @@ -5533,10 +5605,10 @@ fn airFieldParentPtr(f: *Function, inst: Air.Inst.Index) !CValue { try f.renderType(writer, container_ptr_ty); try writer.writeByte(')'); - switch (fieldLocation(container_ptr_ty, field_ptr_ty, extra.field_index, mod)) { + switch (fieldLocation(container_ptr_ty, field_ptr_ty, extra.field_index, zcu)) { .begin => try f.writeCValue(writer, field_ptr_val, .Initializer), .field => |field| { - const u8_ptr_ty = try mod.adjustPtrTypeChild(field_ptr_ty, Type.u8); + const u8_ptr_ty = try zcu.adjustPtrTypeChild(field_ptr_ty, Type.u8); try writer.writeAll("(("); try f.renderType(writer, u8_ptr_ty); @@ -5549,19 +5621,19 @@ fn airFieldParentPtr(f: *Function, inst: Air.Inst.Index) !CValue { try writer.writeAll("))"); }, .byte_offset => |byte_offset| { - const u8_ptr_ty = try mod.adjustPtrTypeChild(field_ptr_ty, Type.u8); - - const byte_offset_val = try mod.intValue(Type.usize, byte_offset); + const u8_ptr_ty = try zcu.adjustPtrTypeChild(field_ptr_ty, Type.u8); try writer.writeAll("(("); try f.renderType(writer, u8_ptr_ty); try writer.writeByte(')'); try f.writeCValue(writer, field_ptr_val, .Other); - try writer.print(" - {})", .{try f.fmtIntLiteral(Type.usize, byte_offset_val)}); + try writer.print(" - {})", .{ + try f.fmtIntLiteral(try zcu.intValue(Type.usize, byte_offset)), + }); }, .end => { try f.writeCValue(writer, field_ptr_val, .Other); - try writer.print(" - {}", .{try f.fmtIntLiteral(Type.usize, try mod.intValue(Type.usize, 1))}); + try writer.print(" - {}", .{try f.fmtIntLiteral(try zcu.intValue(Type.usize, 1))}); }, } @@ -5576,8 +5648,8 @@ fn fieldPtr( container_ptr_val: CValue, field_index: u32, ) !CValue { - const mod = f.object.dg.module; - const container_ty = container_ptr_ty.childType(mod); + const zcu = f.object.dg.zcu; + const container_ty = container_ptr_ty.childType(zcu); const field_ptr_ty = f.typeOfIndex(inst); // Ensure complete type definition is visible before accessing fields. @@ -5590,27 +5662,27 @@ fn fieldPtr( try f.renderType(writer, field_ptr_ty); try writer.writeByte(')'); - switch (fieldLocation(container_ptr_ty, field_ptr_ty, field_index, mod)) { + switch (fieldLocation(container_ptr_ty, field_ptr_ty, field_index, zcu)) { .begin => try f.writeCValue(writer, container_ptr_val, .Initializer), .field => |field| { try writer.writeByte('&'); try f.writeCValueDerefMember(writer, container_ptr_val, field); }, .byte_offset => |byte_offset| { - const u8_ptr_ty = try mod.adjustPtrTypeChild(field_ptr_ty, Type.u8); - - const byte_offset_val = try mod.intValue(Type.usize, byte_offset); + const u8_ptr_ty = try zcu.adjustPtrTypeChild(field_ptr_ty, Type.u8); try writer.writeAll("(("); try f.renderType(writer, u8_ptr_ty); try writer.writeByte(')'); try f.writeCValue(writer, container_ptr_val, .Other); - try writer.print(" + {})", .{try f.fmtIntLiteral(Type.usize, byte_offset_val)}); + try writer.print(" + {})", .{ + try f.fmtIntLiteral(try zcu.intValue(Type.usize, byte_offset)), + }); }, .end => { try writer.writeByte('('); try f.writeCValue(writer, container_ptr_val, .Other); - try writer.print(" + {})", .{try f.fmtIntLiteral(Type.usize, try mod.intValue(Type.usize, 1))}); + try writer.print(" + {})", .{try f.fmtIntLiteral(try zcu.intValue(Type.usize, 1))}); }, } @@ -5619,13 +5691,13 @@ fn fieldPtr( } fn airStructFieldVal(f: *Function, inst: Air.Inst.Index) !CValue { - const mod = f.object.dg.module; - const ip = &mod.intern_pool; + const zcu = f.object.dg.zcu; + const ip = &zcu.intern_pool; const ty_pl = f.air.instructions.items(.data)[@intFromEnum(inst)].ty_pl; const extra = f.air.extraData(Air.StructField, ty_pl.payload).data; const inst_ty = f.typeOfIndex(inst); - if (!inst_ty.hasRuntimeBitsIgnoreComptime(mod)) { + if (!inst_ty.hasRuntimeBitsIgnoreComptime(zcu)) { try reap(f, inst, &.{extra.struct_operand}); return .none; } @@ -5638,26 +5710,25 @@ fn airStructFieldVal(f: *Function, inst: Air.Inst.Index) !CValue { // Ensure complete type definition is visible before accessing fields. _ = try f.typeToIndex(struct_ty, .complete); - const field_name: CValue = switch (mod.intern_pool.indexToKey(struct_ty.ip_index)) { - .struct_type => switch (struct_ty.containerLayout(mod)) { - .auto, .@"extern" => if (struct_ty.isSimpleTuple(mod)) + const field_name: CValue = switch (zcu.intern_pool.indexToKey(struct_ty.toIntern())) { + .struct_type => switch (struct_ty.containerLayout(zcu)) { + .auto, .@"extern" => if (struct_ty.isSimpleTuple(zcu)) .{ .field = extra.field_index } else - .{ .identifier = ip.stringToSlice(struct_ty.legacyStructFieldName(extra.field_index, mod)) }, + .{ .identifier = ip.stringToSlice(struct_ty.legacyStructFieldName(extra.field_index, zcu)) }, .@"packed" => { - const struct_type = mod.typeToStruct(struct_ty).?; - const int_info = struct_ty.intInfo(mod); + const struct_type = zcu.typeToStruct(struct_ty).?; + const int_info = struct_ty.intInfo(zcu); - const bit_offset_ty = try mod.intType(.unsigned, Type.smallestUnsignedBits(int_info.bits - 1)); + const bit_offset_ty = try zcu.intType(.unsigned, Type.smallestUnsignedBits(int_info.bits - 1)); - const bit_offset = mod.structPackedFieldBitOffset(struct_type, extra.field_index); - const bit_offset_val = try mod.intValue(bit_offset_ty, bit_offset); + const bit_offset = zcu.structPackedFieldBitOffset(struct_type, extra.field_index); - const field_int_signedness = if (inst_ty.isAbiInt(mod)) - inst_ty.intInfo(mod).signedness + const field_int_signedness = if (inst_ty.isAbiInt(zcu)) + inst_ty.intInfo(zcu).signedness else .unsigned; - const field_int_ty = try mod.intType(field_int_signedness, @as(u16, @intCast(inst_ty.bitSize(mod)))); + const field_int_ty = try zcu.intType(field_int_signedness, @as(u16, @intCast(inst_ty.bitSize(zcu)))); const temp_local = try f.allocLocal(inst, field_int_ty); try f.writeCValue(writer, temp_local, .Other); @@ -5668,7 +5739,7 @@ fn airStructFieldVal(f: *Function, inst: Air.Inst.Index) !CValue { try writer.writeByte(')'); const cant_cast = int_info.bits > 64; if (cant_cast) { - if (field_int_ty.bitSize(mod) > 64) return f.fail("TODO: C backend: implement casting between types > 64 bits", .{}); + if (field_int_ty.bitSize(zcu) > 64) return f.fail("TODO: C backend: implement casting between types > 64 bits", .{}); try writer.writeAll("zig_lo_"); try f.object.dg.renderTypeForBuiltinFnName(writer, struct_ty); try writer.writeByte('('); @@ -5681,13 +5752,13 @@ fn airStructFieldVal(f: *Function, inst: Air.Inst.Index) !CValue { try f.writeCValue(writer, struct_byval, .Other); if (bit_offset > 0) { try writer.writeAll(", "); - try f.object.dg.renderValue(writer, bit_offset_ty, bit_offset_val, .FunctionArgument); + try f.object.dg.renderValue(writer, try zcu.intValue(bit_offset_ty, bit_offset), .FunctionArgument); try writer.writeByte(')'); } if (cant_cast) try writer.writeByte(')'); try f.object.dg.renderBuiltinInfo(writer, field_int_ty, .bits); try writer.writeAll(");\n"); - if (inst_ty.eql(field_int_ty, f.object.dg.module)) return temp_local; + if (inst_ty.eql(field_int_ty, f.object.dg.zcu)) return temp_local; const local = try f.allocLocal(inst, inst_ty); try writer.writeAll("memcpy("); @@ -5705,7 +5776,7 @@ fn airStructFieldVal(f: *Function, inst: Air.Inst.Index) !CValue { .anon_struct_type => |anon_struct_type| if (anon_struct_type.names.len == 0) .{ .field = extra.field_index } else - .{ .identifier = ip.stringToSlice(struct_ty.legacyStructFieldName(extra.field_index, mod)) }, + .{ .identifier = ip.stringToSlice(struct_ty.legacyStructFieldName(extra.field_index, zcu)) }, .union_type => field_name: { const union_obj = ip.loadUnionType(struct_ty.toIntern()); @@ -5757,7 +5828,7 @@ fn airStructFieldVal(f: *Function, inst: Air.Inst.Index) !CValue { /// *(E!T) -> E /// Note that the result is never a pointer. fn airUnwrapErrUnionErr(f: *Function, inst: Air.Inst.Index) !CValue { - const mod = f.object.dg.module; + const zcu = f.object.dg.zcu; const ty_op = f.air.instructions.items(.data)[@intFromEnum(inst)].ty_op; const inst_ty = f.typeOfIndex(inst); @@ -5765,13 +5836,13 @@ fn airUnwrapErrUnionErr(f: *Function, inst: Air.Inst.Index) !CValue { const operand_ty = f.typeOf(ty_op.operand); try reap(f, inst, &.{ty_op.operand}); - const operand_is_ptr = operand_ty.zigTypeTag(mod) == .Pointer; - const error_union_ty = if (operand_is_ptr) operand_ty.childType(mod) else operand_ty; - const error_ty = error_union_ty.errorUnionSet(mod); - const payload_ty = error_union_ty.errorUnionPayload(mod); + const operand_is_ptr = operand_ty.zigTypeTag(zcu) == .Pointer; + const error_union_ty = if (operand_is_ptr) operand_ty.childType(zcu) else operand_ty; + const error_ty = error_union_ty.errorUnionSet(zcu); + const payload_ty = error_union_ty.errorUnionPayload(zcu); const local = try f.allocLocal(inst, inst_ty); - if (!payload_ty.hasRuntimeBits(mod) and operand == .local and operand.local == local.new_local) { + if (!payload_ty.hasRuntimeBits(zcu) and operand == .local and operand.local == local.new_local) { // The store will be 'x = x'; elide it. return local; } @@ -5780,35 +5851,32 @@ fn airUnwrapErrUnionErr(f: *Function, inst: Air.Inst.Index) !CValue { try f.writeCValue(writer, local, .Other); try writer.writeAll(" = "); - if (!payload_ty.hasRuntimeBits(mod)) { - try f.writeCValue(writer, operand, .Other); - } else { - if (!error_ty.errorSetIsEmpty(mod)) - if (operand_is_ptr) - try f.writeCValueDerefMember(writer, operand, .{ .identifier = "error" }) - else - try f.writeCValueMember(writer, operand, .{ .identifier = "error" }) - else { - const err_int_ty = try mod.errorIntType(); - try f.object.dg.renderValue(writer, err_int_ty, try mod.intValue(err_int_ty, 0), .Initializer); - } - } + if (!payload_ty.hasRuntimeBits(zcu)) + try f.writeCValue(writer, operand, .Other) + else if (error_ty.errorSetIsEmpty(zcu)) + try writer.print("{}", .{ + try f.fmtIntLiteral(try zcu.intValue(try zcu.errorIntType(), 0)), + }) + else if (operand_is_ptr) + try f.writeCValueDerefMember(writer, operand, .{ .identifier = "error" }) + else + try f.writeCValueMember(writer, operand, .{ .identifier = "error" }); try writer.writeAll(";\n"); return local; } fn airUnwrapErrUnionPay(f: *Function, inst: Air.Inst.Index, is_ptr: bool) !CValue { - const mod = f.object.dg.module; + const zcu = f.object.dg.zcu; const ty_op = f.air.instructions.items(.data)[@intFromEnum(inst)].ty_op; const inst_ty = f.typeOfIndex(inst); const operand = try f.resolveInst(ty_op.operand); try reap(f, inst, &.{ty_op.operand}); const operand_ty = f.typeOf(ty_op.operand); - const error_union_ty = if (is_ptr) operand_ty.childType(mod) else operand_ty; + const error_union_ty = if (is_ptr) operand_ty.childType(zcu) else operand_ty; const writer = f.object.writer(); - if (!error_union_ty.errorUnionPayload(mod).hasRuntimeBits(mod)) { + if (!error_union_ty.errorUnionPayload(zcu).hasRuntimeBits(zcu)) { if (!is_ptr) return .none; const local = try f.allocLocal(inst, inst_ty); @@ -5834,11 +5902,11 @@ fn airUnwrapErrUnionPay(f: *Function, inst: Air.Inst.Index, is_ptr: bool) !CValu } fn airWrapOptional(f: *Function, inst: Air.Inst.Index) !CValue { - const mod = f.object.dg.module; + const zcu = f.object.dg.zcu; const ty_op = f.air.instructions.items(.data)[@intFromEnum(inst)].ty_op; const inst_ty = f.typeOfIndex(inst); - const repr_is_payload = inst_ty.optionalReprIsPayload(mod); + const repr_is_payload = inst_ty.optionalReprIsPayload(zcu); const payload_ty = f.typeOf(ty_op.operand); const payload = try f.resolveInst(ty_op.operand); try reap(f, inst, &.{ty_op.operand}); @@ -5859,20 +5927,20 @@ fn airWrapOptional(f: *Function, inst: Air.Inst.Index) !CValue { const a = try Assignment.start(f, writer, Type.bool); try f.writeCValueMember(writer, local, .{ .identifier = "is_null" }); try a.assign(f, writer); - try f.object.dg.renderValue(writer, Type.bool, Value.false, .Other); + try f.object.dg.renderValue(writer, Value.false, .Other); try a.end(f, writer); } return local; } fn airWrapErrUnionErr(f: *Function, inst: Air.Inst.Index) !CValue { - const mod = f.object.dg.module; + const zcu = f.object.dg.zcu; const ty_op = f.air.instructions.items(.data)[@intFromEnum(inst)].ty_op; const inst_ty = f.typeOfIndex(inst); - const payload_ty = inst_ty.errorUnionPayload(mod); - const repr_is_err = !payload_ty.hasRuntimeBitsIgnoreComptime(mod); - const err_ty = inst_ty.errorUnionSet(mod); + const payload_ty = inst_ty.errorUnionPayload(zcu); + const repr_is_err = !payload_ty.hasRuntimeBitsIgnoreComptime(zcu); + const err_ty = inst_ty.errorUnionSet(zcu); const err = try f.resolveInst(ty_op.operand); try reap(f, inst, &.{ty_op.operand}); @@ -5888,7 +5956,7 @@ fn airWrapErrUnionErr(f: *Function, inst: Air.Inst.Index) !CValue { const a = try Assignment.start(f, writer, payload_ty); try f.writeCValueMember(writer, local, .{ .identifier = "payload" }); try a.assign(f, writer); - try f.object.dg.renderValue(writer, payload_ty, Value.undef, .Other); + try f.object.dg.renderUndefValue(writer, payload_ty, .Other); try a.end(f, writer); } { @@ -5905,29 +5973,25 @@ fn airWrapErrUnionErr(f: *Function, inst: Air.Inst.Index) !CValue { } fn airErrUnionPayloadPtrSet(f: *Function, inst: Air.Inst.Index) !CValue { - const mod = f.object.dg.module; + const zcu = f.object.dg.zcu; const writer = f.object.writer(); const ty_op = f.air.instructions.items(.data)[@intFromEnum(inst)].ty_op; const operand = try f.resolveInst(ty_op.operand); - const error_union_ty = f.typeOf(ty_op.operand).childType(mod); + const error_union_ty = f.typeOf(ty_op.operand).childType(zcu); - const payload_ty = error_union_ty.errorUnionPayload(mod); - const err_int_ty = try mod.errorIntType(); + const payload_ty = error_union_ty.errorUnionPayload(zcu); + const err_int_ty = try zcu.errorIntType(); + const no_err = try zcu.intValue(err_int_ty, 0); // First, set the non-error value. - if (!payload_ty.hasRuntimeBitsIgnoreComptime(mod)) { + if (!payload_ty.hasRuntimeBitsIgnoreComptime(zcu)) { try f.writeCValueDeref(writer, operand); - try writer.writeAll(" = "); - try f.object.dg.renderValue(writer, err_int_ty, try mod.intValue(err_int_ty, 0), .Other); - try writer.writeAll(";\n "); - + try writer.print(" = {};\n", .{try f.fmtIntLiteral(no_err)}); return operand; } try reap(f, inst, &.{ty_op.operand}); try f.writeCValueDeref(writer, operand); - try writer.writeAll(".error = "); - try f.object.dg.renderValue(writer, err_int_ty, try mod.intValue(err_int_ty, 0), .Other); - try writer.writeAll(";\n"); + try writer.print(".error = {};\n", .{try f.fmtIntLiteral(no_err)}); // Then return the payload pointer (only if it is used) if (f.liveness.isUnused(inst)) return .none; @@ -5956,14 +6020,14 @@ fn airSaveErrReturnTraceIndex(f: *Function, inst: Air.Inst.Index) !CValue { } fn airWrapErrUnionPay(f: *Function, inst: Air.Inst.Index) !CValue { - const mod = f.object.dg.module; + const zcu = f.object.dg.zcu; const ty_op = f.air.instructions.items(.data)[@intFromEnum(inst)].ty_op; const inst_ty = f.typeOfIndex(inst); - const payload_ty = inst_ty.errorUnionPayload(mod); + const payload_ty = inst_ty.errorUnionPayload(zcu); const payload = try f.resolveInst(ty_op.operand); - const repr_is_err = !payload_ty.hasRuntimeBitsIgnoreComptime(mod); - const err_ty = inst_ty.errorUnionSet(mod); + const repr_is_err = !payload_ty.hasRuntimeBitsIgnoreComptime(zcu); + const err_ty = inst_ty.errorUnionSet(zcu); try reap(f, inst, &.{ty_op.operand}); const writer = f.object.writer(); @@ -5982,15 +6046,14 @@ fn airWrapErrUnionPay(f: *Function, inst: Air.Inst.Index) !CValue { else try f.writeCValueMember(writer, local, .{ .identifier = "error" }); try a.assign(f, writer); - const err_int_ty = try mod.errorIntType(); - try f.object.dg.renderValue(writer, err_int_ty, try mod.intValue(err_int_ty, 0), .Other); + try f.object.dg.renderValue(writer, try zcu.intValue(try zcu.errorIntType(), 0), .Other); try a.end(f, writer); } return local; } fn airIsErr(f: *Function, inst: Air.Inst.Index, is_ptr: bool, operator: []const u8) !CValue { - const mod = f.object.dg.module; + const zcu = f.object.dg.zcu; const un_op = f.air.instructions.items(.data)[@intFromEnum(inst)].un_op; const writer = f.object.writer(); @@ -5998,16 +6061,16 @@ fn airIsErr(f: *Function, inst: Air.Inst.Index, is_ptr: bool, operator: []const try reap(f, inst, &.{un_op}); const operand_ty = f.typeOf(un_op); const local = try f.allocLocal(inst, Type.bool); - const err_union_ty = if (is_ptr) operand_ty.childType(mod) else operand_ty; - const payload_ty = err_union_ty.errorUnionPayload(mod); - const error_ty = err_union_ty.errorUnionSet(mod); + const err_union_ty = if (is_ptr) operand_ty.childType(zcu) else operand_ty; + const payload_ty = err_union_ty.errorUnionPayload(zcu); + const error_ty = err_union_ty.errorUnionSet(zcu); + const a = try Assignment.start(f, writer, Type.bool); try f.writeCValue(writer, local, .Other); - try writer.writeAll(" = "); - - const err_int_ty = try mod.errorIntType(); - if (!error_ty.errorSetIsEmpty(mod)) - if (payload_ty.hasRuntimeBits(mod)) + try a.assign(f, writer); + const err_int_ty = try zcu.errorIntType(); + if (!error_ty.errorSetIsEmpty(zcu)) + if (payload_ty.hasRuntimeBits(zcu)) if (is_ptr) try f.writeCValueDerefMember(writer, operand, .{ .identifier = "error" }) else @@ -6015,63 +6078,84 @@ fn airIsErr(f: *Function, inst: Air.Inst.Index, is_ptr: bool, operator: []const else try f.writeCValue(writer, operand, .Other) else - try f.object.dg.renderValue(writer, err_int_ty, try mod.intValue(err_int_ty, 0), .Other); + try f.object.dg.renderValue(writer, try zcu.intValue(err_int_ty, 0), .Other); try writer.writeByte(' '); try writer.writeAll(operator); try writer.writeByte(' '); - try f.object.dg.renderValue(writer, err_int_ty, try mod.intValue(err_int_ty, 0), .Other); - try writer.writeAll(";\n"); + try f.object.dg.renderValue(writer, try zcu.intValue(err_int_ty, 0), .Other); + try a.end(f, writer); return local; } fn airArrayToSlice(f: *Function, inst: Air.Inst.Index) !CValue { - const mod = f.object.dg.module; + const zcu = f.object.dg.zcu; const ty_op = f.air.instructions.items(.data)[@intFromEnum(inst)].ty_op; const operand = try f.resolveInst(ty_op.operand); try reap(f, inst, &.{ty_op.operand}); const inst_ty = f.typeOfIndex(inst); + const ptr_ty = inst_ty.slicePtrFieldType(zcu); const writer = f.object.writer(); const local = try f.allocLocal(inst, inst_ty); - const array_ty = f.typeOf(ty_op.operand).childType(mod); - - try f.writeCValueMember(writer, local, .{ .identifier = "ptr" }); - try writer.writeAll(" = "); - // Unfortunately, C does not support any equivalent to - // &(*(void *)p)[0], although LLVM does via GetElementPtr - if (operand == .undef) { - try f.writeCValue(writer, .{ .undef = inst_ty.slicePtrFieldType(mod) }, .Initializer); - } else if (array_ty.hasRuntimeBitsIgnoreComptime(mod)) { - try writer.writeAll("&("); - try f.writeCValueDeref(writer, operand); - try writer.print(")[{}]", .{try f.fmtIntLiteral(Type.usize, try mod.intValue(Type.usize, 0))}); - } else try f.writeCValue(writer, operand, .Initializer); - try writer.writeAll("; "); + const operand_ty = f.typeOf(ty_op.operand); + const array_ty = operand_ty.childType(zcu); - const len_val = try mod.intValue(Type.usize, array_ty.arrayLen(mod)); - try f.writeCValueMember(writer, local, .{ .identifier = "len" }); - try writer.print(" = {};\n", .{try f.fmtIntLiteral(Type.usize, len_val)}); + { + const a = try Assignment.start(f, writer, ptr_ty); + try f.writeCValueMember(writer, local, .{ .identifier = "ptr" }); + try a.assign(f, writer); + if (operand == .undef) { + try f.writeCValue(writer, .{ .undef = inst_ty.slicePtrFieldType(zcu) }, .Initializer); + } else { + const ptr_cty = try f.typeToIndex(ptr_ty, .complete); + const ptr_child_cty = f.indexToCType(ptr_cty).cast(CType.Payload.Child).?.data; + const elem_ty = array_ty.childType(zcu); + const elem_cty = try f.typeToIndex(elem_ty, .complete); + if (ptr_child_cty != elem_cty) { + try writer.writeByte('('); + try f.renderCType(writer, ptr_cty); + try writer.writeByte(')'); + } + const operand_cty = try f.typeToCType(operand_ty, .complete); + const operand_child_cty = operand_cty.cast(CType.Payload.Child).?.data; + if (f.indexToCType(operand_child_cty).tag() == .array) { + try writer.writeByte('&'); + try f.writeCValueDeref(writer, operand); + try writer.print("[{}]", .{try f.fmtIntLiteral(try zcu.intValue(Type.usize, 0))}); + } else try f.writeCValue(writer, operand, .Initializer); + } + try a.end(f, writer); + } + { + const a = try Assignment.start(f, writer, Type.usize); + try f.writeCValueMember(writer, local, .{ .identifier = "len" }); + try a.assign(f, writer); + try writer.print("{}", .{ + try f.fmtIntLiteral(try zcu.intValue(Type.usize, array_ty.arrayLen(zcu))), + }); + try a.end(f, writer); + } return local; } fn airFloatCast(f: *Function, inst: Air.Inst.Index) !CValue { - const mod = f.object.dg.module; + const zcu = f.object.dg.zcu; const ty_op = f.air.instructions.items(.data)[@intFromEnum(inst)].ty_op; const inst_ty = f.typeOfIndex(inst); - const inst_scalar_ty = inst_ty.scalarType(mod); + const inst_scalar_ty = inst_ty.scalarType(zcu); const operand = try f.resolveInst(ty_op.operand); try reap(f, inst, &.{ty_op.operand}); const operand_ty = f.typeOf(ty_op.operand); - const scalar_ty = operand_ty.scalarType(mod); - const target = f.object.dg.module.getTarget(); + const scalar_ty = operand_ty.scalarType(zcu); + const target = &f.object.dg.mod.resolved_target.result; const operation = if (inst_scalar_ty.isRuntimeFloat() and scalar_ty.isRuntimeFloat()) - if (inst_scalar_ty.floatBits(target) < scalar_ty.floatBits(target)) "trunc" else "extend" - else if (inst_scalar_ty.isInt(mod) and scalar_ty.isRuntimeFloat()) - if (inst_scalar_ty.isSignedInt(mod)) "fix" else "fixuns" - else if (inst_scalar_ty.isRuntimeFloat() and scalar_ty.isInt(mod)) - if (scalar_ty.isSignedInt(mod)) "float" else "floatun" + if (inst_scalar_ty.floatBits(target.*) < scalar_ty.floatBits(target.*)) "trunc" else "extend" + else if (inst_scalar_ty.isInt(zcu) and scalar_ty.isRuntimeFloat()) + if (inst_scalar_ty.isSignedInt(zcu)) "fix" else "fixuns" + else if (inst_scalar_ty.isRuntimeFloat() and scalar_ty.isInt(zcu)) + if (scalar_ty.isSignedInt(zcu)) "float" else "floatun" else unreachable; @@ -6082,20 +6166,20 @@ fn airFloatCast(f: *Function, inst: Air.Inst.Index) !CValue { try f.writeCValue(writer, local, .Other); try v.elem(f, writer); try a.assign(f, writer); - if (inst_scalar_ty.isInt(mod) and scalar_ty.isRuntimeFloat()) { + if (inst_scalar_ty.isInt(zcu) and scalar_ty.isRuntimeFloat()) { try writer.writeAll("zig_wrap_"); try f.object.dg.renderTypeForBuiltinFnName(writer, inst_scalar_ty); try writer.writeByte('('); } try writer.writeAll("zig_"); try writer.writeAll(operation); - try writer.writeAll(compilerRtAbbrev(scalar_ty, mod)); - try writer.writeAll(compilerRtAbbrev(inst_scalar_ty, mod)); + try writer.writeAll(compilerRtAbbrev(scalar_ty, zcu, target.*)); + try writer.writeAll(compilerRtAbbrev(inst_scalar_ty, zcu, target.*)); try writer.writeByte('('); try f.writeCValue(writer, operand, .FunctionArgument); try v.elem(f, writer); try writer.writeByte(')'); - if (inst_scalar_ty.isInt(mod) and scalar_ty.isRuntimeFloat()) { + if (inst_scalar_ty.isInt(zcu) and scalar_ty.isRuntimeFloat()) { try f.object.dg.renderBuiltinInfo(writer, inst_scalar_ty, .bits); try writer.writeByte(')'); } @@ -6106,7 +6190,7 @@ fn airFloatCast(f: *Function, inst: Air.Inst.Index) !CValue { } fn airIntFromPtr(f: *Function, inst: Air.Inst.Index) !CValue { - const mod = f.object.dg.module; + const zcu = f.object.dg.zcu; const un_op = f.air.instructions.items(.data)[@intFromEnum(inst)].un_op; const operand = try f.resolveInst(un_op); @@ -6120,7 +6204,7 @@ fn airIntFromPtr(f: *Function, inst: Air.Inst.Index) !CValue { try writer.writeAll(" = ("); try f.renderType(writer, inst_ty); try writer.writeByte(')'); - if (operand_ty.isSlice(mod)) { + if (operand_ty.isSlice(zcu)) { try f.writeCValueMember(writer, operand, .{ .identifier = "ptr" }); } else { try f.writeCValue(writer, operand, .Other); @@ -6135,15 +6219,15 @@ fn airUnBuiltinCall( operation: []const u8, info: BuiltinInfo, ) !CValue { - const mod = f.object.dg.module; + const zcu = f.object.dg.zcu; const ty_op = f.air.instructions.items(.data)[@intFromEnum(inst)].ty_op; const operand = try f.resolveInst(ty_op.operand); try reap(f, inst, &.{ty_op.operand}); const inst_ty = f.typeOfIndex(inst); - const inst_scalar_ty = inst_ty.scalarType(mod); + const inst_scalar_ty = inst_ty.scalarType(zcu); const operand_ty = f.typeOf(ty_op.operand); - const scalar_ty = operand_ty.scalarType(mod); + const scalar_ty = operand_ty.scalarType(zcu); const inst_scalar_cty = try f.typeToCType(inst_scalar_ty, .complete); const ref_ret = inst_scalar_cty.tag() == .array; @@ -6179,7 +6263,7 @@ fn airBinBuiltinCall( operation: []const u8, info: BuiltinInfo, ) !CValue { - const mod = f.object.dg.module; + const zcu = f.object.dg.zcu; const bin_op = f.air.instructions.items(.data)[@intFromEnum(inst)].bin_op; const operand_ty = f.typeOf(bin_op.lhs); @@ -6191,8 +6275,8 @@ fn airBinBuiltinCall( if (!is_big) try reap(f, inst, &.{ bin_op.lhs, bin_op.rhs }); const inst_ty = f.typeOfIndex(inst); - const inst_scalar_ty = inst_ty.scalarType(mod); - const scalar_ty = operand_ty.scalarType(mod); + const inst_scalar_ty = inst_ty.scalarType(zcu); + const scalar_ty = operand_ty.scalarType(zcu); const inst_scalar_cty = try f.typeToCType(inst_scalar_ty, .complete); const ref_ret = inst_scalar_cty.tag() == .array; @@ -6234,15 +6318,15 @@ fn airCmpBuiltinCall( operation: enum { cmp, operator }, info: BuiltinInfo, ) !CValue { - const mod = f.object.dg.module; + const zcu = f.object.dg.zcu; const lhs = try f.resolveInst(data.lhs); const rhs = try f.resolveInst(data.rhs); try reap(f, inst, &.{ data.lhs, data.rhs }); const inst_ty = f.typeOfIndex(inst); - const inst_scalar_ty = inst_ty.scalarType(mod); + const inst_scalar_ty = inst_ty.scalarType(zcu); const operand_ty = f.typeOf(data.lhs); - const scalar_ty = operand_ty.scalarType(mod); + const scalar_ty = operand_ty.scalarType(zcu); const inst_scalar_cty = try f.typeToCType(inst_scalar_ty, .complete); const ref_ret = inst_scalar_cty.tag() == .array; @@ -6275,7 +6359,7 @@ fn airCmpBuiltinCall( try writer.writeByte(')'); if (!ref_ret) try writer.print("{s}{}", .{ compareOperatorC(operator), - try f.fmtIntLiteral(Type.i32, try mod.intValue(Type.i32, 0)), + try f.fmtIntLiteral(try zcu.intValue(Type.i32, 0)), }); try writer.writeAll(";\n"); try v.end(f, inst, writer); @@ -6284,7 +6368,7 @@ fn airCmpBuiltinCall( } fn airCmpxchg(f: *Function, inst: Air.Inst.Index, flavor: [*:0]const u8) !CValue { - const mod = f.object.dg.module; + const zcu = f.object.dg.zcu; const ty_pl = f.air.instructions.items(.data)[@intFromEnum(inst)].ty_pl; const extra = f.air.extraData(Air.Cmpxchg, ty_pl.payload).data; const inst_ty = f.typeOfIndex(inst); @@ -6292,19 +6376,19 @@ fn airCmpxchg(f: *Function, inst: Air.Inst.Index, flavor: [*:0]const u8) !CValue const expected_value = try f.resolveInst(extra.expected_value); const new_value = try f.resolveInst(extra.new_value); const ptr_ty = f.typeOf(extra.ptr); - const ty = ptr_ty.childType(mod); + const ty = ptr_ty.childType(zcu); const writer = f.object.writer(); const new_value_mat = try Materialize.start(f, inst, writer, ty, new_value); try reap(f, inst, &.{ extra.ptr, extra.expected_value, extra.new_value }); const repr_ty = if (ty.isRuntimeFloat()) - mod.intType(.unsigned, @as(u16, @intCast(ty.abiSize(mod) * 8))) catch unreachable + zcu.intType(.unsigned, @as(u16, @intCast(ty.abiSize(zcu) * 8))) catch unreachable else ty; const local = try f.allocLocal(inst, inst_ty); - if (inst_ty.isPtrLikeOptional(mod)) { + if (inst_ty.isPtrLikeOptional(zcu)) { { const a = try Assignment.start(f, writer, ty); try f.writeCValue(writer, local, .Other); @@ -6317,7 +6401,7 @@ fn airCmpxchg(f: *Function, inst: Air.Inst.Index, flavor: [*:0]const u8) !CValue try writer.print("zig_cmpxchg_{s}((zig_atomic(", .{flavor}); try f.renderType(writer, ty); try writer.writeByte(')'); - if (ptr_ty.isVolatilePtr(mod)) try writer.writeAll(" volatile"); + if (ptr_ty.isVolatilePtr(zcu)) try writer.writeAll(" volatile"); try writer.writeAll(" *)"); try f.writeCValue(writer, ptr, .Other); try writer.writeAll(", "); @@ -6331,7 +6415,7 @@ fn airCmpxchg(f: *Function, inst: Air.Inst.Index, flavor: [*:0]const u8) !CValue try writer.writeAll(", "); try f.object.dg.renderTypeForBuiltinFnName(writer, ty); try writer.writeAll(", "); - try f.object.dg.renderType(writer, repr_ty); + try f.renderType(writer, repr_ty); try writer.writeByte(')'); try writer.writeAll(") {\n"); f.object.indent_writer.pushIndent(); @@ -6359,7 +6443,7 @@ fn airCmpxchg(f: *Function, inst: Air.Inst.Index, flavor: [*:0]const u8) !CValue try writer.print("zig_cmpxchg_{s}((zig_atomic(", .{flavor}); try f.renderType(writer, ty); try writer.writeByte(')'); - if (ptr_ty.isVolatilePtr(mod)) try writer.writeAll(" volatile"); + if (ptr_ty.isVolatilePtr(zcu)) try writer.writeAll(" volatile"); try writer.writeAll(" *)"); try f.writeCValue(writer, ptr, .Other); try writer.writeAll(", "); @@ -6373,7 +6457,7 @@ fn airCmpxchg(f: *Function, inst: Air.Inst.Index, flavor: [*:0]const u8) !CValue try writer.writeAll(", "); try f.object.dg.renderTypeForBuiltinFnName(writer, ty); try writer.writeAll(", "); - try f.object.dg.renderType(writer, repr_ty); + try f.renderType(writer, repr_ty); try writer.writeByte(')'); try a.end(f, writer); } @@ -6389,12 +6473,12 @@ fn airCmpxchg(f: *Function, inst: Air.Inst.Index, flavor: [*:0]const u8) !CValue } fn airAtomicRmw(f: *Function, inst: Air.Inst.Index) !CValue { - const mod = f.object.dg.module; + const zcu = f.object.dg.zcu; const pl_op = f.air.instructions.items(.data)[@intFromEnum(inst)].pl_op; const extra = f.air.extraData(Air.AtomicRmw, pl_op.payload).data; const inst_ty = f.typeOfIndex(inst); const ptr_ty = f.typeOf(pl_op.operand); - const ty = ptr_ty.childType(mod); + const ty = ptr_ty.childType(zcu); const ptr = try f.resolveInst(pl_op.operand); const operand = try f.resolveInst(extra.operand); @@ -6402,10 +6486,10 @@ fn airAtomicRmw(f: *Function, inst: Air.Inst.Index) !CValue { const operand_mat = try Materialize.start(f, inst, writer, ty, operand); try reap(f, inst, &.{ pl_op.operand, extra.operand }); - const repr_bits = @as(u16, @intCast(ty.abiSize(mod) * 8)); + const repr_bits = @as(u16, @intCast(ty.abiSize(zcu) * 8)); const is_float = ty.isRuntimeFloat(); const is_128 = repr_bits == 128; - const repr_ty = if (is_float) mod.intType(.unsigned, repr_bits) catch unreachable else ty; + const repr_ty = if (is_float) zcu.intType(.unsigned, repr_bits) catch unreachable else ty; const local = try f.allocLocal(inst, inst_ty); try writer.print("zig_atomicrmw_{s}", .{toAtomicRmwSuffix(extra.op())}); @@ -6421,7 +6505,7 @@ fn airAtomicRmw(f: *Function, inst: Air.Inst.Index) !CValue { if (use_atomic) try writer.writeAll("zig_atomic("); try f.renderType(writer, ty); if (use_atomic) try writer.writeByte(')'); - if (ptr_ty.isVolatilePtr(mod)) try writer.writeAll(" volatile"); + if (ptr_ty.isVolatilePtr(zcu)) try writer.writeAll(" volatile"); try writer.writeAll(" *)"); try f.writeCValue(writer, ptr, .Other); try writer.writeAll(", "); @@ -6431,7 +6515,7 @@ fn airAtomicRmw(f: *Function, inst: Air.Inst.Index) !CValue { try writer.writeAll(", "); try f.object.dg.renderTypeForBuiltinFnName(writer, ty); try writer.writeAll(", "); - try f.object.dg.renderType(writer, repr_ty); + try f.renderType(writer, repr_ty); try writer.writeAll(");\n"); try operand_mat.end(f, inst); @@ -6444,15 +6528,15 @@ fn airAtomicRmw(f: *Function, inst: Air.Inst.Index) !CValue { } fn airAtomicLoad(f: *Function, inst: Air.Inst.Index) !CValue { - const mod = f.object.dg.module; + const zcu = f.object.dg.zcu; const atomic_load = f.air.instructions.items(.data)[@intFromEnum(inst)].atomic_load; const ptr = try f.resolveInst(atomic_load.ptr); try reap(f, inst, &.{atomic_load.ptr}); const ptr_ty = f.typeOf(atomic_load.ptr); - const ty = ptr_ty.childType(mod); + const ty = ptr_ty.childType(zcu); const repr_ty = if (ty.isRuntimeFloat()) - mod.intType(.unsigned, @as(u16, @intCast(ty.abiSize(mod) * 8))) catch unreachable + zcu.intType(.unsigned, @as(u16, @intCast(ty.abiSize(zcu) * 8))) catch unreachable else ty; @@ -6465,7 +6549,7 @@ fn airAtomicLoad(f: *Function, inst: Air.Inst.Index) !CValue { try writer.writeAll(", (zig_atomic("); try f.renderType(writer, ty); try writer.writeByte(')'); - if (ptr_ty.isVolatilePtr(mod)) try writer.writeAll(" volatile"); + if (ptr_ty.isVolatilePtr(zcu)) try writer.writeAll(" volatile"); try writer.writeAll(" *)"); try f.writeCValue(writer, ptr, .Other); try writer.writeAll(", "); @@ -6473,17 +6557,17 @@ fn airAtomicLoad(f: *Function, inst: Air.Inst.Index) !CValue { try writer.writeAll(", "); try f.object.dg.renderTypeForBuiltinFnName(writer, ty); try writer.writeAll(", "); - try f.object.dg.renderType(writer, repr_ty); + try f.renderType(writer, repr_ty); try writer.writeAll(");\n"); return local; } fn airAtomicStore(f: *Function, inst: Air.Inst.Index, order: [*:0]const u8) !CValue { - const mod = f.object.dg.module; + const zcu = f.object.dg.zcu; const bin_op = f.air.instructions.items(.data)[@intFromEnum(inst)].bin_op; const ptr_ty = f.typeOf(bin_op.lhs); - const ty = ptr_ty.childType(mod); + const ty = ptr_ty.childType(zcu); const ptr = try f.resolveInst(bin_op.lhs); const element = try f.resolveInst(bin_op.rhs); @@ -6492,14 +6576,14 @@ fn airAtomicStore(f: *Function, inst: Air.Inst.Index, order: [*:0]const u8) !CVa try reap(f, inst, &.{ bin_op.lhs, bin_op.rhs }); const repr_ty = if (ty.isRuntimeFloat()) - mod.intType(.unsigned, @as(u16, @intCast(ty.abiSize(mod) * 8))) catch unreachable + zcu.intType(.unsigned, @as(u16, @intCast(ty.abiSize(zcu) * 8))) catch unreachable else ty; try writer.writeAll("zig_atomic_store((zig_atomic("); try f.renderType(writer, ty); try writer.writeByte(')'); - if (ptr_ty.isVolatilePtr(mod)) try writer.writeAll(" volatile"); + if (ptr_ty.isVolatilePtr(zcu)) try writer.writeAll(" volatile"); try writer.writeAll(" *)"); try f.writeCValue(writer, ptr, .Other); try writer.writeAll(", "); @@ -6507,7 +6591,7 @@ fn airAtomicStore(f: *Function, inst: Air.Inst.Index, order: [*:0]const u8) !CVa try writer.print(", {s}, ", .{order}); try f.object.dg.renderTypeForBuiltinFnName(writer, ty); try writer.writeAll(", "); - try f.object.dg.renderType(writer, repr_ty); + try f.renderType(writer, repr_ty); try writer.writeAll(");\n"); try element_mat.end(f, inst); @@ -6515,8 +6599,8 @@ fn airAtomicStore(f: *Function, inst: Air.Inst.Index, order: [*:0]const u8) !CVa } fn writeSliceOrPtr(f: *Function, writer: anytype, ptr: CValue, ptr_ty: Type) !void { - const mod = f.object.dg.module; - if (ptr_ty.isSlice(mod)) { + const zcu = f.object.dg.zcu; + if (ptr_ty.isSlice(zcu)) { try f.writeCValueMember(writer, ptr, .{ .identifier = "ptr" }); } else { try f.writeCValue(writer, ptr, .FunctionArgument); @@ -6524,14 +6608,14 @@ fn writeSliceOrPtr(f: *Function, writer: anytype, ptr: CValue, ptr_ty: Type) !vo } fn airMemset(f: *Function, inst: Air.Inst.Index, safety: bool) !CValue { - const mod = f.object.dg.module; + const zcu = f.object.dg.zcu; const bin_op = f.air.instructions.items(.data)[@intFromEnum(inst)].bin_op; const dest_ty = f.typeOf(bin_op.lhs); const dest_slice = try f.resolveInst(bin_op.lhs); const value = try f.resolveInst(bin_op.rhs); const elem_ty = f.typeOf(bin_op.rhs); - const elem_abi_size = elem_ty.abiSize(mod); - const val_is_undef = if (try f.air.value(bin_op.rhs, mod)) |val| val.isUndefDeep(mod) else false; + const elem_abi_size = elem_ty.abiSize(zcu); + const val_is_undef = if (try f.air.value(bin_op.rhs, zcu)) |val| val.isUndefDeep(zcu) else false; const writer = f.object.writer(); if (val_is_undef) { @@ -6541,7 +6625,7 @@ fn airMemset(f: *Function, inst: Air.Inst.Index, safety: bool) !CValue { } try writer.writeAll("memset("); - switch (dest_ty.ptrSize(mod)) { + switch (dest_ty.ptrSize(zcu)) { .Slice => { try f.writeCValueMember(writer, dest_slice, .{ .identifier = "ptr" }); try writer.writeAll(", 0xaa, "); @@ -6553,8 +6637,8 @@ fn airMemset(f: *Function, inst: Air.Inst.Index, safety: bool) !CValue { } }, .One => { - const array_ty = dest_ty.childType(mod); - const len = array_ty.arrayLen(mod) * elem_abi_size; + const array_ty = dest_ty.childType(zcu); + const len = array_ty.arrayLen(zcu) * elem_abi_size; try f.writeCValue(writer, dest_slice, .FunctionArgument); try writer.print(", 0xaa, {d});\n", .{len}); @@ -6565,12 +6649,12 @@ fn airMemset(f: *Function, inst: Air.Inst.Index, safety: bool) !CValue { return .none; } - if (elem_abi_size > 1 or dest_ty.isVolatilePtr(mod)) { + if (elem_abi_size > 1 or dest_ty.isVolatilePtr(zcu)) { // For the assignment in this loop, the array pointer needs to get // casted to a regular pointer, otherwise an error like this occurs: // error: array type 'uint32_t[20]' (aka 'unsigned int[20]') is not assignable - const elem_ptr_ty = try mod.ptrType(.{ - .child = elem_ty.ip_index, + const elem_ptr_ty = try zcu.ptrType(.{ + .child = elem_ty.toIntern(), .flags = .{ .size = .C, }, @@ -6581,17 +6665,17 @@ fn airMemset(f: *Function, inst: Air.Inst.Index, safety: bool) !CValue { try writer.writeAll("for ("); try f.writeCValue(writer, index, .Other); try writer.writeAll(" = "); - try f.object.dg.renderValue(writer, Type.usize, try mod.intValue(Type.usize, 0), .Initializer); + try f.object.dg.renderValue(writer, try zcu.intValue(Type.usize, 0), .Initializer); try writer.writeAll("; "); try f.writeCValue(writer, index, .Other); try writer.writeAll(" != "); - switch (dest_ty.ptrSize(mod)) { + switch (dest_ty.ptrSize(zcu)) { .Slice => { try f.writeCValueMember(writer, dest_slice, .{ .identifier = "len" }); }, .One => { - const array_ty = dest_ty.childType(mod); - try writer.print("{d}", .{array_ty.arrayLen(mod)}); + const array_ty = dest_ty.childType(zcu); + try writer.print("{d}", .{array_ty.arrayLen(zcu)}); }, .Many, .C => unreachable, } @@ -6620,7 +6704,7 @@ fn airMemset(f: *Function, inst: Air.Inst.Index, safety: bool) !CValue { const bitcasted = try bitcast(f, Type.u8, value, elem_ty); try writer.writeAll("memset("); - switch (dest_ty.ptrSize(mod)) { + switch (dest_ty.ptrSize(zcu)) { .Slice => { try f.writeCValueMember(writer, dest_slice, .{ .identifier = "ptr" }); try writer.writeAll(", "); @@ -6630,8 +6714,8 @@ fn airMemset(f: *Function, inst: Air.Inst.Index, safety: bool) !CValue { try writer.writeAll(");\n"); }, .One => { - const array_ty = dest_ty.childType(mod); - const len = array_ty.arrayLen(mod) * elem_abi_size; + const array_ty = dest_ty.childType(zcu); + const len = array_ty.arrayLen(zcu) * elem_abi_size; try f.writeCValue(writer, dest_slice, .FunctionArgument); try writer.writeAll(", "); @@ -6646,7 +6730,7 @@ fn airMemset(f: *Function, inst: Air.Inst.Index, safety: bool) !CValue { } fn airMemcpy(f: *Function, inst: Air.Inst.Index) !CValue { - const mod = f.object.dg.module; + const zcu = f.object.dg.zcu; const bin_op = f.air.instructions.items(.data)[@intFromEnum(inst)].bin_op; const dest_ptr = try f.resolveInst(bin_op.lhs); const src_ptr = try f.resolveInst(bin_op.rhs); @@ -6659,10 +6743,10 @@ fn airMemcpy(f: *Function, inst: Air.Inst.Index) !CValue { try writer.writeAll(", "); try writeSliceOrPtr(f, writer, src_ptr, src_ty); try writer.writeAll(", "); - switch (dest_ty.ptrSize(mod)) { + switch (dest_ty.ptrSize(zcu)) { .Slice => { - const elem_ty = dest_ty.childType(mod); - const elem_abi_size = elem_ty.abiSize(mod); + const elem_ty = dest_ty.childType(zcu); + const elem_abi_size = elem_ty.abiSize(zcu); try f.writeCValueMember(writer, dest_ptr, .{ .identifier = "len" }); if (elem_abi_size > 1) { try writer.print(" * {d});\n", .{elem_abi_size}); @@ -6671,10 +6755,10 @@ fn airMemcpy(f: *Function, inst: Air.Inst.Index) !CValue { } }, .One => { - const array_ty = dest_ty.childType(mod); - const elem_ty = array_ty.childType(mod); - const elem_abi_size = elem_ty.abiSize(mod); - const len = array_ty.arrayLen(mod) * elem_abi_size; + const array_ty = dest_ty.childType(zcu); + const elem_ty = array_ty.childType(zcu); + const elem_abi_size = elem_ty.abiSize(zcu); + const len = array_ty.arrayLen(zcu) * elem_abi_size; try writer.print("{d});\n", .{len}); }, .Many, .C => unreachable, @@ -6685,16 +6769,16 @@ fn airMemcpy(f: *Function, inst: Air.Inst.Index) !CValue { } fn airSetUnionTag(f: *Function, inst: Air.Inst.Index) !CValue { - const mod = f.object.dg.module; + const zcu = f.object.dg.zcu; const bin_op = f.air.instructions.items(.data)[@intFromEnum(inst)].bin_op; const union_ptr = try f.resolveInst(bin_op.lhs); const new_tag = try f.resolveInst(bin_op.rhs); try reap(f, inst, &.{ bin_op.lhs, bin_op.rhs }); - const union_ty = f.typeOf(bin_op.lhs).childType(mod); - const layout = union_ty.unionGetLayout(mod); + const union_ty = f.typeOf(bin_op.lhs).childType(zcu); + const layout = union_ty.unionGetLayout(zcu); if (layout.tag_size == 0) return .none; - const tag_ty = union_ty.unionTagTypeSafety(mod).?; + const tag_ty = union_ty.unionTagTypeSafety(zcu).?; const writer = f.object.writer(); const a = try Assignment.start(f, writer, tag_ty); @@ -6706,14 +6790,14 @@ fn airSetUnionTag(f: *Function, inst: Air.Inst.Index) !CValue { } fn airGetUnionTag(f: *Function, inst: Air.Inst.Index) !CValue { - const mod = f.object.dg.module; + const zcu = f.object.dg.zcu; const ty_op = f.air.instructions.items(.data)[@intFromEnum(inst)].ty_op; const operand = try f.resolveInst(ty_op.operand); try reap(f, inst, &.{ty_op.operand}); const union_ty = f.typeOf(ty_op.operand); - const layout = union_ty.unionGetLayout(mod); + const layout = union_ty.unionGetLayout(zcu); if (layout.tag_size == 0) return .none; const inst_ty = f.typeOfIndex(inst); @@ -6728,7 +6812,7 @@ fn airGetUnionTag(f: *Function, inst: Air.Inst.Index) !CValue { } fn airTagName(f: *Function, inst: Air.Inst.Index) !CValue { - const mod = f.object.dg.module; + const zcu = f.object.dg.zcu; const un_op = f.air.instructions.items(.data)[@intFromEnum(inst)].un_op; const inst_ty = f.typeOfIndex(inst); @@ -6740,7 +6824,7 @@ fn airTagName(f: *Function, inst: Air.Inst.Index) !CValue { const local = try f.allocLocal(inst, inst_ty); try f.writeCValue(writer, local, .Other); try writer.print(" = {s}(", .{ - try f.getLazyFnName(.{ .tag_name = enum_ty.getOwnerDecl(mod) }, .{ .tag_name = enum_ty }), + try f.getLazyFnName(.{ .tag_name = enum_ty.getOwnerDecl(zcu) }, .{ .tag_name = enum_ty }), }); try f.writeCValue(writer, operand, .Other); try writer.writeAll(");\n"); @@ -6765,14 +6849,14 @@ fn airErrorName(f: *Function, inst: Air.Inst.Index) !CValue { } fn airSplat(f: *Function, inst: Air.Inst.Index) !CValue { - const mod = f.object.dg.module; + const zcu = f.object.dg.zcu; const ty_op = f.air.instructions.items(.data)[@intFromEnum(inst)].ty_op; const operand = try f.resolveInst(ty_op.operand); try reap(f, inst, &.{ty_op.operand}); const inst_ty = f.typeOfIndex(inst); - const inst_scalar_ty = inst_ty.scalarType(mod); + const inst_scalar_ty = inst_ty.scalarType(zcu); const writer = f.object.writer(); const local = try f.allocLocal(inst, inst_ty); @@ -6820,7 +6904,7 @@ fn airSelect(f: *Function, inst: Air.Inst.Index) !CValue { } fn airShuffle(f: *Function, inst: Air.Inst.Index) !CValue { - const mod = f.object.dg.module; + const zcu = f.object.dg.zcu; const ty_pl = f.air.instructions.items(.data)[@intFromEnum(inst)].ty_pl; const extra = f.air.extraData(Air.Shuffle, ty_pl.payload).data; @@ -6836,15 +6920,15 @@ fn airShuffle(f: *Function, inst: Air.Inst.Index) !CValue { for (0..extra.mask_len) |index| { try f.writeCValue(writer, local, .Other); try writer.writeByte('['); - try f.object.dg.renderValue(writer, Type.usize, try mod.intValue(Type.usize, index), .Other); + try f.object.dg.renderValue(writer, try zcu.intValue(Type.usize, index), .Other); try writer.writeAll("] = "); - const mask_elem = (try mask.elemValue(mod, index)).toSignedInt(mod); - const src_val = try mod.intValue(Type.usize, @as(u64, @intCast(mask_elem ^ mask_elem >> 63))); + const mask_elem = (try mask.elemValue(zcu, index)).toSignedInt(zcu); + const src_val = try zcu.intValue(Type.usize, @as(u64, @intCast(mask_elem ^ mask_elem >> 63))); try f.writeCValue(writer, if (mask_elem >= 0) lhs else rhs, .Other); try writer.writeByte('['); - try f.object.dg.renderValue(writer, Type.usize, src_val, .Other); + try f.object.dg.renderValue(writer, src_val, .Other); try writer.writeAll("];\n"); } @@ -6852,7 +6936,7 @@ fn airShuffle(f: *Function, inst: Air.Inst.Index) !CValue { } fn airReduce(f: *Function, inst: Air.Inst.Index) !CValue { - const mod = f.object.dg.module; + const zcu = f.object.dg.zcu; const reduce = f.air.instructions.items(.data)[@intFromEnum(inst)].reduce; const scalar_ty = f.typeOfIndex(inst); @@ -6861,7 +6945,7 @@ fn airReduce(f: *Function, inst: Air.Inst.Index) !CValue { const operand_ty = f.typeOf(reduce.operand); const writer = f.object.writer(); - const use_operator = scalar_ty.bitSize(mod) <= 64; + const use_operator = scalar_ty.bitSize(zcu) <= 64; const op: union(enum) { const Func = struct { operation: []const u8, info: BuiltinInfo = .none }; float_op: Func, @@ -6872,28 +6956,28 @@ fn airReduce(f: *Function, inst: Air.Inst.Index) !CValue { .And => if (use_operator) .{ .infix = " &= " } else .{ .builtin = .{ .operation = "and" } }, .Or => if (use_operator) .{ .infix = " |= " } else .{ .builtin = .{ .operation = "or" } }, .Xor => if (use_operator) .{ .infix = " ^= " } else .{ .builtin = .{ .operation = "xor" } }, - .Min => switch (scalar_ty.zigTypeTag(mod)) { + .Min => switch (scalar_ty.zigTypeTag(zcu)) { .Int => if (use_operator) .{ .ternary = " < " } else .{ .builtin = .{ .operation = "min" }, }, .Float => .{ .float_op = .{ .operation = "fmin" } }, else => unreachable, }, - .Max => switch (scalar_ty.zigTypeTag(mod)) { + .Max => switch (scalar_ty.zigTypeTag(zcu)) { .Int => if (use_operator) .{ .ternary = " > " } else .{ .builtin = .{ .operation = "max" }, }, .Float => .{ .float_op = .{ .operation = "fmax" } }, else => unreachable, }, - .Add => switch (scalar_ty.zigTypeTag(mod)) { + .Add => switch (scalar_ty.zigTypeTag(zcu)) { .Int => if (use_operator) .{ .infix = " += " } else .{ .builtin = .{ .operation = "addw", .info = .bits }, }, .Float => .{ .builtin = .{ .operation = "add" } }, else => unreachable, }, - .Mul => switch (scalar_ty.zigTypeTag(mod)) { + .Mul => switch (scalar_ty.zigTypeTag(zcu)) { .Int => if (use_operator) .{ .infix = " *= " } else .{ .builtin = .{ .operation = "mulw", .info = .bits }, }, @@ -6908,7 +6992,7 @@ fn airReduce(f: *Function, inst: Air.Inst.Index) !CValue { // Equivalent to: // reduce: { // var accum: T = init; - // for (vec) : (elem) { + // for (vec) |elem| { // accum = func(accum, elem); // } // break :reduce accum; @@ -6918,40 +7002,40 @@ fn airReduce(f: *Function, inst: Air.Inst.Index) !CValue { try f.writeCValue(writer, accum, .Other); try writer.writeAll(" = "); - try f.object.dg.renderValue(writer, scalar_ty, switch (reduce.operation) { - .Or, .Xor => switch (scalar_ty.zigTypeTag(mod)) { + try f.object.dg.renderValue(writer, switch (reduce.operation) { + .Or, .Xor => switch (scalar_ty.zigTypeTag(zcu)) { .Bool => Value.false, - .Int => try mod.intValue(scalar_ty, 0), + .Int => try zcu.intValue(scalar_ty, 0), else => unreachable, }, - .And => switch (scalar_ty.zigTypeTag(mod)) { + .And => switch (scalar_ty.zigTypeTag(zcu)) { .Bool => Value.true, - .Int => switch (scalar_ty.intInfo(mod).signedness) { - .unsigned => try scalar_ty.maxIntScalar(mod, scalar_ty), - .signed => try mod.intValue(scalar_ty, -1), + .Int => switch (scalar_ty.intInfo(zcu).signedness) { + .unsigned => try scalar_ty.maxIntScalar(zcu, scalar_ty), + .signed => try zcu.intValue(scalar_ty, -1), }, else => unreachable, }, - .Add => switch (scalar_ty.zigTypeTag(mod)) { - .Int => try mod.intValue(scalar_ty, 0), - .Float => try mod.floatValue(scalar_ty, 0.0), + .Add => switch (scalar_ty.zigTypeTag(zcu)) { + .Int => try zcu.intValue(scalar_ty, 0), + .Float => try zcu.floatValue(scalar_ty, 0.0), else => unreachable, }, - .Mul => switch (scalar_ty.zigTypeTag(mod)) { - .Int => try mod.intValue(scalar_ty, 1), - .Float => try mod.floatValue(scalar_ty, 1.0), + .Mul => switch (scalar_ty.zigTypeTag(zcu)) { + .Int => try zcu.intValue(scalar_ty, 1), + .Float => try zcu.floatValue(scalar_ty, 1.0), else => unreachable, }, - .Min => switch (scalar_ty.zigTypeTag(mod)) { + .Min => switch (scalar_ty.zigTypeTag(zcu)) { .Bool => Value.true, - .Int => try scalar_ty.maxIntScalar(mod, scalar_ty), - .Float => try mod.floatValue(scalar_ty, std.math.nan(f128)), + .Int => try scalar_ty.maxIntScalar(zcu, scalar_ty), + .Float => try zcu.floatValue(scalar_ty, std.math.nan(f128)), else => unreachable, }, - .Max => switch (scalar_ty.zigTypeTag(mod)) { + .Max => switch (scalar_ty.zigTypeTag(zcu)) { .Bool => Value.false, - .Int => try scalar_ty.minIntScalar(mod, scalar_ty), - .Float => try mod.floatValue(scalar_ty, std.math.nan(f128)), + .Int => try scalar_ty.minIntScalar(zcu, scalar_ty), + .Float => try zcu.floatValue(scalar_ty, std.math.nan(f128)), else => unreachable, }, }, .Initializer); @@ -7007,11 +7091,11 @@ fn airReduce(f: *Function, inst: Air.Inst.Index) !CValue { } fn airAggregateInit(f: *Function, inst: Air.Inst.Index) !CValue { - const mod = f.object.dg.module; - const ip = &mod.intern_pool; + const zcu = f.object.dg.zcu; + const ip = &zcu.intern_pool; const ty_pl = f.air.instructions.items(.data)[@intFromEnum(inst)].ty_pl; const inst_ty = f.typeOfIndex(inst); - const len = @as(usize, @intCast(inst_ty.arrayLen(mod))); + const len = @as(usize, @intCast(inst_ty.arrayLen(zcu))); const elements = @as([]const Air.Inst.Ref, @ptrCast(f.air.extra[ty_pl.payload..][0..len])); const gpa = f.object.dg.gpa; const resolved_elements = try gpa.alloc(CValue, elements.len); @@ -7028,10 +7112,9 @@ fn airAggregateInit(f: *Function, inst: Air.Inst.Index) !CValue { const writer = f.object.writer(); const local = try f.allocLocal(inst, inst_ty); - switch (inst_ty.zigTypeTag(mod)) { + switch (inst_ty.zigTypeTag(zcu)) { .Array, .Vector => { - const elem_ty = inst_ty.childType(mod); - const a = try Assignment.init(f, elem_ty); + const a = try Assignment.init(f, inst_ty.childType(zcu)); for (resolved_elements, 0..) |element, i| { try a.restart(f, writer); try f.writeCValue(writer, local, .Other); @@ -7040,26 +7123,26 @@ fn airAggregateInit(f: *Function, inst: Air.Inst.Index) !CValue { try f.writeCValue(writer, element, .Other); try a.end(f, writer); } - if (inst_ty.sentinel(mod)) |sentinel| { + if (inst_ty.sentinel(zcu)) |sentinel| { try a.restart(f, writer); try f.writeCValue(writer, local, .Other); try writer.print("[{d}]", .{resolved_elements.len}); try a.assign(f, writer); - try f.object.dg.renderValue(writer, elem_ty, sentinel, .Other); + try f.object.dg.renderValue(writer, sentinel, .Other); try a.end(f, writer); } }, - .Struct => switch (inst_ty.containerLayout(mod)) { + .Struct => switch (inst_ty.containerLayout(zcu)) { .auto, .@"extern" => for (resolved_elements, 0..) |element, field_index| { - if (inst_ty.structFieldIsComptime(field_index, mod)) continue; - const field_ty = inst_ty.structFieldType(field_index, mod); - if (!field_ty.hasRuntimeBitsIgnoreComptime(mod)) continue; + if (inst_ty.structFieldIsComptime(field_index, zcu)) continue; + const field_ty = inst_ty.structFieldType(field_index, zcu); + if (!field_ty.hasRuntimeBitsIgnoreComptime(zcu)) continue; const a = try Assignment.start(f, writer, field_ty); - try f.writeCValueMember(writer, local, if (inst_ty.isSimpleTuple(mod)) + try f.writeCValueMember(writer, local, if (inst_ty.isSimpleTuple(zcu)) .{ .field = field_index } else - .{ .identifier = ip.stringToSlice(inst_ty.legacyStructFieldName(@intCast(field_index), mod)) }); + .{ .identifier = ip.stringToSlice(inst_ty.legacyStructFieldName(@intCast(field_index), zcu)) }); try a.assign(f, writer); try f.writeCValue(writer, element, .Other); try a.end(f, writer); @@ -7067,17 +7150,17 @@ fn airAggregateInit(f: *Function, inst: Air.Inst.Index) !CValue { .@"packed" => { try f.writeCValue(writer, local, .Other); try writer.writeAll(" = "); - const int_info = inst_ty.intInfo(mod); + const int_info = inst_ty.intInfo(zcu); - const bit_offset_ty = try mod.intType(.unsigned, Type.smallestUnsignedBits(int_info.bits - 1)); + const bit_offset_ty = try zcu.intType(.unsigned, Type.smallestUnsignedBits(int_info.bits - 1)); var bit_offset: u64 = 0; var empty = true; for (0..elements.len) |field_index| { - if (inst_ty.structFieldIsComptime(field_index, mod)) continue; - const field_ty = inst_ty.structFieldType(field_index, mod); - if (!field_ty.hasRuntimeBitsIgnoreComptime(mod)) continue; + if (inst_ty.structFieldIsComptime(field_index, zcu)) continue; + const field_ty = inst_ty.structFieldType(field_index, zcu); + if (!field_ty.hasRuntimeBitsIgnoreComptime(zcu)) continue; if (!empty) { try writer.writeAll("zig_or_"); @@ -7088,9 +7171,9 @@ fn airAggregateInit(f: *Function, inst: Air.Inst.Index) !CValue { } empty = true; for (resolved_elements, 0..) |element, field_index| { - if (inst_ty.structFieldIsComptime(field_index, mod)) continue; - const field_ty = inst_ty.structFieldType(field_index, mod); - if (!field_ty.hasRuntimeBitsIgnoreComptime(mod)) continue; + if (inst_ty.structFieldIsComptime(field_index, zcu)) continue; + const field_ty = inst_ty.structFieldType(field_index, zcu); + if (!field_ty.hasRuntimeBitsIgnoreComptime(zcu)) continue; if (!empty) try writer.writeAll(", "); // TODO: Skip this entire shift if val is 0? @@ -7098,13 +7181,13 @@ fn airAggregateInit(f: *Function, inst: Air.Inst.Index) !CValue { try f.object.dg.renderTypeForBuiltinFnName(writer, inst_ty); try writer.writeByte('('); - if (inst_ty.isAbiInt(mod) and (field_ty.isAbiInt(mod) or field_ty.isPtrAtRuntime(mod))) { + if (inst_ty.isAbiInt(zcu) and (field_ty.isAbiInt(zcu) or field_ty.isPtrAtRuntime(zcu))) { try f.renderIntCast(writer, inst_ty, element, .{}, field_ty, .FunctionArgument); } else { try writer.writeByte('('); try f.renderType(writer, inst_ty); try writer.writeByte(')'); - if (field_ty.isPtrAtRuntime(mod)) { + if (field_ty.isPtrAtRuntime(zcu)) { try writer.writeByte('('); try f.renderType(writer, switch (int_info.signedness) { .unsigned => Type.usize, @@ -7115,14 +7198,14 @@ fn airAggregateInit(f: *Function, inst: Air.Inst.Index) !CValue { try f.writeCValue(writer, element, .Other); } - try writer.writeAll(", "); - const bit_offset_val = try mod.intValue(bit_offset_ty, bit_offset); - try f.object.dg.renderValue(writer, bit_offset_ty, bit_offset_val, .FunctionArgument); + try writer.print(", {}", .{ + try f.fmtIntLiteral(try zcu.intValue(bit_offset_ty, bit_offset)), + }); try f.object.dg.renderBuiltinInfo(writer, inst_ty, .bits); try writer.writeByte(')'); if (!empty) try writer.writeByte(')'); - bit_offset += field_ty.bitSize(mod); + bit_offset += field_ty.bitSize(zcu); empty = false; } @@ -7136,13 +7219,13 @@ fn airAggregateInit(f: *Function, inst: Air.Inst.Index) !CValue { } fn airUnionInit(f: *Function, inst: Air.Inst.Index) !CValue { - const mod = f.object.dg.module; - const ip = &mod.intern_pool; + const zcu = f.object.dg.zcu; + const ip = &zcu.intern_pool; const ty_pl = f.air.instructions.items(.data)[@intFromEnum(inst)].ty_pl; const extra = f.air.extraData(Air.UnionInit, ty_pl.payload).data; const union_ty = f.typeOfIndex(inst); - const union_obj = mod.typeToUnion(union_ty).?; + const union_obj = zcu.typeToUnion(union_ty).?; const field_name = union_obj.loadTagType(ip).names.get(ip)[extra.field_index]; const payload_ty = f.typeOf(extra.init); const payload = try f.resolveInst(extra.init); @@ -7158,19 +7241,16 @@ fn airUnionInit(f: *Function, inst: Air.Inst.Index) !CValue { return local; } - const field: CValue = if (union_ty.unionTagTypeSafety(mod)) |tag_ty| field: { - const layout = union_ty.unionGetLayout(mod); + const field: CValue = if (union_ty.unionTagTypeSafety(zcu)) |tag_ty| field: { + const layout = union_ty.unionGetLayout(zcu); if (layout.tag_size != 0) { - const field_index = tag_ty.enumFieldIndex(field_name, mod).?; - - const tag_val = try mod.enumValueFieldIndex(tag_ty, field_index); - - const int_val = try tag_val.intFromEnum(tag_ty, mod); + const field_index = tag_ty.enumFieldIndex(field_name, zcu).?; + const tag_val = try zcu.enumValueFieldIndex(tag_ty, field_index); const a = try Assignment.start(f, writer, tag_ty); try f.writeCValueMember(writer, local, .{ .identifier = "tag" }); try a.assign(f, writer); - try writer.print("{}", .{try f.fmtIntLiteral(tag_ty, int_val)}); + try writer.print("{}", .{try f.fmtIntLiteral(try tag_val.intFromEnum(tag_ty, zcu))}); try a.end(f, writer); } break :field .{ .payload_identifier = ip.stringToSlice(field_name) }; @@ -7185,7 +7265,7 @@ fn airUnionInit(f: *Function, inst: Air.Inst.Index) !CValue { } fn airPrefetch(f: *Function, inst: Air.Inst.Index) !CValue { - const mod = f.object.dg.module; + const zcu = f.object.dg.zcu; const prefetch = f.air.instructions.items(.data)[@intFromEnum(inst)].prefetch; const ptr_ty = f.typeOf(prefetch.ptr); @@ -7196,7 +7276,7 @@ fn airPrefetch(f: *Function, inst: Air.Inst.Index) !CValue { switch (prefetch.cache) { .data => { try writer.writeAll("zig_prefetch("); - if (ptr_ty.isSlice(mod)) + if (ptr_ty.isSlice(zcu)) try f.writeCValueMember(writer, ptr, .{ .identifier = "ptr" }) else try f.writeCValue(writer, ptr, .FunctionArgument); @@ -7242,14 +7322,14 @@ fn airWasmMemoryGrow(f: *Function, inst: Air.Inst.Index) !CValue { } fn airFloatNeg(f: *Function, inst: Air.Inst.Index) !CValue { - const mod = f.object.dg.module; + const zcu = f.object.dg.zcu; const un_op = f.air.instructions.items(.data)[@intFromEnum(inst)].un_op; const operand = try f.resolveInst(un_op); try reap(f, inst, &.{un_op}); const operand_ty = f.typeOf(un_op); - const scalar_ty = operand_ty.scalarType(mod); + const scalar_ty = operand_ty.scalarType(zcu); const writer = f.object.writer(); const local = try f.allocLocal(inst, operand_ty); @@ -7268,15 +7348,15 @@ fn airFloatNeg(f: *Function, inst: Air.Inst.Index) !CValue { } fn airAbs(f: *Function, inst: Air.Inst.Index) !CValue { - const mod = f.object.dg.module; + const zcu = f.object.dg.zcu; const ty_op = f.air.instructions.items(.data)[@intFromEnum(inst)].ty_op; const operand = try f.resolveInst(ty_op.operand); const ty = f.typeOf(ty_op.operand); - const scalar_ty = ty.scalarType(mod); + const scalar_ty = ty.scalarType(zcu); - switch (scalar_ty.zigTypeTag(mod)) { - .Int => if (ty.zigTypeTag(mod) == .Vector) { - return f.fail("TODO implement airAbs for '{}'", .{ty.fmt(mod)}); + switch (scalar_ty.zigTypeTag(zcu)) { + .Int => if (ty.zigTypeTag(zcu) == .Vector) { + return f.fail("TODO implement airAbs for '{}'", .{ty.fmt(zcu)}); } else { return airUnBuiltinCall(f, inst, "abs", .none); }, @@ -7286,8 +7366,8 @@ fn airAbs(f: *Function, inst: Air.Inst.Index) !CValue { } fn unFloatOp(f: *Function, inst: Air.Inst.Index, operand: CValue, ty: Type, operation: []const u8) !CValue { - const mod = f.object.dg.module; - const scalar_ty = ty.scalarType(mod); + const zcu = f.object.dg.zcu; + const scalar_ty = ty.scalarType(zcu); const writer = f.object.writer(); const local = try f.allocLocal(inst, ty); @@ -7316,7 +7396,7 @@ fn airUnFloatOp(f: *Function, inst: Air.Inst.Index, operation: []const u8) !CVal } fn airBinFloatOp(f: *Function, inst: Air.Inst.Index, operation: []const u8) !CValue { - const mod = f.object.dg.module; + const zcu = f.object.dg.zcu; const bin_op = f.air.instructions.items(.data)[@intFromEnum(inst)].bin_op; const lhs = try f.resolveInst(bin_op.lhs); @@ -7324,7 +7404,7 @@ fn airBinFloatOp(f: *Function, inst: Air.Inst.Index, operation: []const u8) !CVa try reap(f, inst, &.{ bin_op.lhs, bin_op.rhs }); const inst_ty = f.typeOfIndex(inst); - const inst_scalar_ty = inst_ty.scalarType(mod); + const inst_scalar_ty = inst_ty.scalarType(zcu); const writer = f.object.writer(); const local = try f.allocLocal(inst, inst_ty); @@ -7346,7 +7426,7 @@ fn airBinFloatOp(f: *Function, inst: Air.Inst.Index, operation: []const u8) !CVa } fn airMulAdd(f: *Function, inst: Air.Inst.Index) !CValue { - const mod = f.object.dg.module; + const zcu = f.object.dg.zcu; const pl_op = f.air.instructions.items(.data)[@intFromEnum(inst)].pl_op; const bin_op = f.air.extraData(Air.Bin, pl_op.payload).data; @@ -7356,7 +7436,7 @@ fn airMulAdd(f: *Function, inst: Air.Inst.Index) !CValue { try reap(f, inst, &.{ bin_op.lhs, bin_op.rhs, pl_op.operand }); const inst_ty = f.typeOfIndex(inst); - const inst_scalar_ty = inst_ty.scalarType(mod); + const inst_scalar_ty = inst_ty.scalarType(zcu); const writer = f.object.writer(); const local = try f.allocLocal(inst, inst_ty); @@ -7381,11 +7461,11 @@ fn airMulAdd(f: *Function, inst: Air.Inst.Index) !CValue { } fn airCVaStart(f: *Function, inst: Air.Inst.Index) !CValue { - const mod = f.object.dg.module; + const zcu = f.object.dg.zcu; const inst_ty = f.typeOfIndex(inst); const decl_index = f.object.dg.pass.decl; - const decl = mod.declPtr(decl_index); - const fn_cty = try f.typeToCType(decl.typeOf(mod), .complete); + const decl = zcu.declPtr(decl_index); + const fn_cty = try f.typeToCType(decl.typeOf(zcu), .complete); const param_len = fn_cty.castTag(.varargs_function).?.data.param_types.len; const writer = f.object.writer(); @@ -7589,9 +7669,8 @@ fn signAbbrev(signedness: std.builtin.Signedness) u8 { }; } -fn compilerRtAbbrev(ty: Type, mod: *Module) []const u8 { - const target = mod.getTarget(); - return if (ty.isInt(mod)) switch (ty.intInfo(mod).bits) { +fn compilerRtAbbrev(ty: Type, zcu: *Zcu, target: std.Target) []const u8 { + return if (ty.isInt(zcu)) switch (ty.intInfo(zcu).bits) { 1...32 => "si", 33...64 => "di", 65...128 => "ti", @@ -7753,8 +7832,8 @@ fn formatIntLiteral( options: std.fmt.FormatOptions, writer: anytype, ) @TypeOf(writer).Error!void { - const mod = data.dg.module; - const target = mod.getTarget(); + const zcu = data.dg.zcu; + const target = &data.dg.mod.resolved_target.result; const ExpectedContents = struct { const base = 10; @@ -7774,7 +7853,7 @@ fn formatIntLiteral( defer allocator.free(undef_limbs); var int_buf: Value.BigIntSpace = undefined; - const int = if (data.val.isUndefDeep(mod)) blk: { + const int = if (data.val.isUndefDeep(zcu)) blk: { undef_limbs = try allocator.alloc(BigIntLimb, BigInt.calcTwosCompLimbCount(data.int_info.bits)); @memset(undef_limbs, undefPattern(BigIntLimb)); @@ -7785,10 +7864,10 @@ fn formatIntLiteral( }; undef_int.truncate(undef_int.toConst(), data.int_info.signedness, data.int_info.bits); break :blk undef_int.toConst(); - } else data.val.toBigInt(&int_buf, mod); + } else data.val.toBigInt(&int_buf, zcu); assert(int.fitsInTwosComp(data.int_info.signedness, data.int_info.bits)); - const c_bits: usize = @intCast(data.cty.byteSize(data.dg.ctypes.set, target) * 8); + const c_bits: usize = @intCast(data.cty.byteSize(data.dg.ctypes.set, data.dg.mod) * 8); var one_limbs: [BigInt.calcLimbLen(1)]BigIntLimb = undefined; const one = BigInt.Mutable.init(&one_limbs, 1).toConst(); @@ -7919,7 +7998,7 @@ fn formatIntLiteral( .int_info = c_limb_int_info, .kind = data.kind, .cty = c_limb_cty, - .val = try mod.intValue_big(Type.comptime_int, c_limb_mut.toConst()), + .val = try zcu.intValue_big(Type.comptime_int, c_limb_mut.toConst()), }, fmt, options, writer); } } @@ -8016,21 +8095,17 @@ const Vectorize = struct { index: CValue = .none, pub fn start(f: *Function, inst: Air.Inst.Index, writer: anytype, ty: Type) !Vectorize { - const mod = f.object.dg.module; - return if (ty.zigTypeTag(mod) == .Vector) index: { - const len_val = try mod.intValue(Type.usize, ty.vectorLen(mod)); - + const zcu = f.object.dg.zcu; + return if (ty.zigTypeTag(zcu) == .Vector) index: { const local = try f.allocLocal(inst, Type.usize); try writer.writeAll("for ("); try f.writeCValue(writer, local, .Other); - try writer.print(" = {d}; ", .{try f.fmtIntLiteral(Type.usize, try mod.intValue(Type.usize, 0))}); + try writer.print(" = {d}; ", .{try f.fmtIntLiteral(try zcu.intValue(Type.usize, 0))}); try f.writeCValue(writer, local, .Other); - try writer.print(" < {d}; ", .{ - try f.fmtIntLiteral(Type.usize, len_val), - }); + try writer.print(" < {d}; ", .{try f.fmtIntLiteral(try zcu.intValue(Type.usize, ty.vectorLen(zcu)))}); try f.writeCValue(writer, local, .Other); - try writer.print(" += {d}) {{\n", .{try f.fmtIntLiteral(Type.usize, try mod.intValue(Type.usize, 1))}); + try writer.print(" += {d}) {{\n", .{try f.fmtIntLiteral(try zcu.intValue(Type.usize, 1))}); f.object.indent_writer.pushIndent(); break :index .{ .index = local }; @@ -8054,16 +8129,16 @@ const Vectorize = struct { } }; -fn lowerFnRetTy(ret_ty: Type, mod: *Module) !Type { - if (ret_ty.ip_index == .noreturn_type) return Type.noreturn; +fn lowerFnRetTy(ret_ty: Type, zcu: *Zcu) !Type { + if (ret_ty.toIntern() == .noreturn_type) return Type.noreturn; - if (lowersToArray(ret_ty, mod)) { - const gpa = mod.gpa; - const ip = &mod.intern_pool; + if (lowersToArray(ret_ty, zcu)) { + const gpa = zcu.gpa; + const ip = &zcu.intern_pool; const names = [1]InternPool.NullTerminatedString{ try ip.getOrPutString(gpa, "array"), }; - const types = [1]InternPool.Index{ret_ty.ip_index}; + const types = [1]InternPool.Index{ret_ty.toIntern()}; const values = [1]InternPool.Index{.none}; const interned = try ip.getAnonStructType(gpa, .{ .names = &names, @@ -8073,13 +8148,13 @@ fn lowerFnRetTy(ret_ty: Type, mod: *Module) !Type { return Type.fromInterned(interned); } - return if (ret_ty.hasRuntimeBitsIgnoreComptime(mod)) ret_ty else Type.void; + return if (ret_ty.hasRuntimeBitsIgnoreComptime(zcu)) ret_ty else Type.void; } -fn lowersToArray(ty: Type, mod: *Module) bool { - return switch (ty.zigTypeTag(mod)) { +fn lowersToArray(ty: Type, zcu: *Zcu) bool { + return switch (ty.zigTypeTag(zcu)) { .Array, .Vector => return true, - else => return ty.isAbiInt(mod) and toCIntBits(@as(u32, @intCast(ty.bitSize(mod)))) == null, + else => return ty.isAbiInt(zcu) and toCIntBits(@as(u32, @intCast(ty.bitSize(zcu)))) == null, }; } @@ -8098,7 +8173,7 @@ fn die(f: *Function, inst: Air.Inst.Index, ref: Air.Inst.Ref) !void { const ref_inst = ref.toIndex() orelse return; const c_value = (f.value_map.fetchRemove(ref) orelse return).value; const local_index = switch (c_value) { - .local, .new_local => |l| l, + .new_local, .local => |l| l, else => return, }; try freeLocal(f, inst, local_index, ref_inst); diff --git a/src/codegen/c/type.zig b/src/codegen/c/type.zig index 66f92c930d99..a75f5e8f1564 100644 --- a/src/codegen/c/type.zig +++ b/src/codegen/c/type.zig @@ -3,10 +3,10 @@ const mem = std.mem; const Allocator = mem.Allocator; const assert = std.debug.assert; const autoHash = std.hash.autoHash; -const Target = std.Target; const Alignment = @import("../../InternPool.zig").Alignment; -const Module = @import("../../Module.zig"); +const Zcu = @import("../../Module.zig"); +const Module = @import("../../Package/Module.zig"); const InternPool = @import("../../InternPool.zig"); const Type = @import("../../type.zig").Type; @@ -280,7 +280,7 @@ pub const CType = extern union { }; }; - pub const AlignAs = struct { + pub const AlignAs = packed struct { @"align": Alignment, abi: Alignment, @@ -298,19 +298,19 @@ pub const CType = extern union { Alignment.fromNonzeroByteUnits(abi_alignment), ); } - pub fn abiAlign(ty: Type, mod: *Module) AlignAs { - const abi_align = ty.abiAlignment(mod); + pub fn abiAlign(ty: Type, zcu: *Zcu) AlignAs { + const abi_align = ty.abiAlignment(zcu); return init(abi_align, abi_align); } - pub fn fieldAlign(struct_ty: Type, field_i: usize, mod: *Module) AlignAs { + pub fn fieldAlign(struct_ty: Type, field_i: usize, zcu: *Zcu) AlignAs { return init( - struct_ty.structFieldAlign(field_i, mod), - struct_ty.structFieldType(field_i, mod).abiAlignment(mod), + struct_ty.structFieldAlign(field_i, zcu), + struct_ty.structFieldType(field_i, zcu).abiAlignment(zcu), ); } - pub fn unionPayloadAlign(union_ty: Type, mod: *Module) AlignAs { - const union_obj = mod.typeToUnion(union_ty).?; - const union_payload_align = mod.unionAbiAlignment(union_obj); + pub fn unionPayloadAlign(union_ty: Type, zcu: *Zcu) AlignAs { + const union_obj = zcu.typeToUnion(union_ty).?; + const union_payload_align = zcu.unionAbiAlignment(union_obj); return init(union_payload_align, union_payload_align); } @@ -356,8 +356,8 @@ pub const CType = extern union { return self.map.entries.items(.hash)[index - Tag.no_payload_count]; } - pub fn typeToIndex(self: Set, ty: Type, mod: *Module, kind: Kind) ?Index { - const lookup = Convert.Lookup{ .imm = .{ .set = &self, .mod = mod } }; + pub fn typeToIndex(self: Set, ty: Type, zcu: *Zcu, mod: *Module, kind: Kind) ?Index { + const lookup = Convert.Lookup{ .imm = .{ .set = &self, .zcu = zcu, .mod = mod } }; var convert: Convert = undefined; convert.initType(ty, kind, lookup) catch unreachable; @@ -398,10 +398,11 @@ pub const CType = extern union { pub fn typeToIndex( self: *Promoted, ty: Type, + zcu: *Zcu, mod: *Module, kind: Kind, ) Allocator.Error!Index { - const lookup = Convert.Lookup{ .mut = .{ .promoted = self, .mod = mod } }; + const lookup = Convert.Lookup{ .mut = .{ .promoted = self, .zcu = zcu, .mod = mod } }; var convert: Convert = undefined; try convert.initType(ty, kind, lookup); @@ -417,7 +418,7 @@ pub const CType = extern union { ); if (!gop.found_existing) { errdefer _ = self.set.map.pop(); - gop.key_ptr.* = try createFromConvert(self, ty, lookup.getModule(), kind, convert); + gop.key_ptr.* = try createFromConvert(self, ty, zcu, mod, kind, convert); } if (std.debug.runtime_safety) { const adapter = TypeAdapter64{ @@ -457,15 +458,15 @@ pub const CType = extern union { return promoted.cTypeToIndex(cty); } - pub fn typeToCType(self: *Store, gpa: Allocator, ty: Type, mod: *Module, kind: Kind) !CType { - const idx = try self.typeToIndex(gpa, ty, mod, kind); + pub fn typeToCType(self: *Store, gpa: Allocator, ty: Type, zcu: *Zcu, mod: *Module, kind: Kind) !CType { + const idx = try self.typeToIndex(gpa, ty, zcu, mod, kind); return self.indexToCType(idx); } - pub fn typeToIndex(self: *Store, gpa: Allocator, ty: Type, mod: *Module, kind: Kind) !Index { + pub fn typeToIndex(self: *Store, gpa: Allocator, ty: Type, zcu: *Zcu, mod: *Module, kind: Kind) !Index { var promoted = self.promote(gpa); defer self.demote(promoted); - return promoted.typeToIndex(ty, mod, kind); + return promoted.typeToIndex(ty, zcu, mod, kind); } pub fn clearRetainingCapacity(self: *Store, gpa: Allocator) void { @@ -549,9 +550,9 @@ pub const CType = extern union { }; } - pub fn signedness(self: CType, target: std.Target) std.builtin.Signedness { + pub fn signedness(self: CType, mod: *Module) std.builtin.Signedness { return switch (self.tag()) { - .char => target.charSignedness(), + .char => mod.resolved_target.result.charSignedness(), .@"signed char", .short, .int, @@ -854,7 +855,8 @@ pub const CType = extern union { } } - pub fn floatActiveBits(self: CType, target: Target) u16 { + pub fn floatActiveBits(self: CType, mod: *Module) u16 { + const target = &mod.resolved_target.result; return switch (self.tag()) { .float => target.c_type_bit_size(.float), .double => target.c_type_bit_size(.double), @@ -868,7 +870,8 @@ pub const CType = extern union { }; } - pub fn byteSize(self: CType, store: Store.Set, target: Target) u64 { + pub fn byteSize(self: CType, store: Store.Set, mod: *Module) u64 { + const target = &mod.resolved_target.result; return switch (self.tag()) { .void => 0, .char, .@"signed char", ._Bool, .@"unsigned char", .bool, .uint8_t, .int8_t => 1, @@ -906,7 +909,7 @@ pub const CType = extern union { .vector, => { const data = self.cast(Payload.Sequence).?.data; - return data.len * store.indexToCType(data.elem_type).byteSize(store, target); + return data.len * store.indexToCType(data.elem_type).byteSize(store, mod); }, .fwd_anon_struct, @@ -1248,13 +1251,18 @@ pub const CType = extern union { } pub const Lookup = union(enum) { - fail: *Module, + fail: struct { + zcu: *Zcu, + mod: *Module, + }, imm: struct { set: *const Store.Set, + zcu: *Zcu, mod: *Module, }, mut: struct { promoted: *Store.Promoted, + zcu: *Zcu, mod: *Module, }, @@ -1265,15 +1273,15 @@ pub const CType = extern union { }; } - pub fn getTarget(self: @This()) Target { - return self.getModule().getTarget(); + pub fn getZcu(self: @This()) *Zcu { + return switch (self) { + inline else => |pl| pl.zcu, + }; } pub fn getModule(self: @This()) *Module { return switch (self) { - .fail => |mod| mod, - .imm => |imm| imm.mod, - .mut => |mut| mut.mod, + inline else => |pl| pl.mod, }; } @@ -1288,8 +1296,8 @@ pub const CType = extern union { pub fn typeToIndex(self: @This(), ty: Type, kind: Kind) !?Index { return switch (self) { .fail => null, - .imm => |imm| imm.set.typeToIndex(ty, imm.mod, kind), - .mut => |mut| try mut.promoted.typeToIndex(ty, mut.mod, kind), + .imm => |imm| imm.set.typeToIndex(ty, imm.zcu, imm.mod, kind), + .mut => |mut| try mut.promoted.typeToIndex(ty, mut.zcu, mut.mod, kind), }; } @@ -1300,7 +1308,7 @@ pub const CType = extern union { pub fn freeze(self: @This()) @This() { return switch (self) { .fail, .imm => self, - .mut => |mut| .{ .imm = .{ .set = &mut.promoted.set, .mod = mut.mod } }, + .mut => |mut| .{ .imm = .{ .set = &mut.promoted.set, .zcu = mut.zcu, .mod = mut.mod } }, }; } }; @@ -1354,7 +1362,7 @@ pub const CType = extern union { self.storage.anon.fields[0] = .{ .name = "array", .type = array_idx, - .alignas = AlignAs.abiAlign(ty, lookup.getModule()), + .alignas = AlignAs.abiAlign(ty, lookup.getZcu()), }; self.initAnon(kind, fwd_idx, 1); } else self.init(switch (kind) { @@ -1366,13 +1374,13 @@ pub const CType = extern union { } pub fn initType(self: *@This(), ty: Type, kind: Kind, lookup: Lookup) !void { - const mod = lookup.getModule(); - const ip = &mod.intern_pool; + const zcu = lookup.getZcu(); + const ip = &zcu.intern_pool; self.* = undefined; - if (!ty.isFnOrHasRuntimeBitsIgnoreComptime(mod)) + if (!ty.isFnOrHasRuntimeBitsIgnoreComptime(zcu)) self.init(.void) - else if (ty.isAbiInt(mod)) switch (ty.ip_index) { + else if (ty.isAbiInt(zcu)) switch (ty.ip_index) { .usize_type => self.init(.uintptr_t), .isize_type => self.init(.intptr_t), .c_char_type => self.init(.char), @@ -1384,13 +1392,13 @@ pub const CType = extern union { .c_ulong_type => self.init(.@"unsigned long"), .c_longlong_type => self.init(.@"long long"), .c_ulonglong_type => self.init(.@"unsigned long long"), - else => switch (tagFromIntInfo(ty.intInfo(mod))) { + else => switch (tagFromIntInfo(ty.intInfo(zcu))) { .void => unreachable, else => |t| self.init(t), .array => switch (kind) { .forward, .complete, .global => { - const abi_size = ty.abiSize(mod); - const abi_align = ty.abiAlignment(mod).toByteUnits(0); + const abi_size = ty.abiSize(zcu); + const abi_align = ty.abiAlignment(zcu).toByteUnits(0); self.storage = .{ .seq = .{ .base = .{ .tag = .array }, .data = .{ .len = @divExact(abi_size, abi_align), .elem_type = tagFromIntInfo(.{ @@ -1406,7 +1414,7 @@ pub const CType = extern union { .payload => unreachable, }, }, - } else switch (ty.zigTypeTag(mod)) { + } else switch (ty.zigTypeTag(zcu)) { .Frame => unreachable, .AnyFrame => unreachable, @@ -1436,7 +1444,7 @@ pub const CType = extern union { }), .Pointer => { - const info = ty.ptrInfo(mod); + const info = ty.ptrInfo(zcu); switch (info.flags.size) { .Slice => { if (switch (kind) { @@ -1444,18 +1452,18 @@ pub const CType = extern union { .complete, .parameter, .global => try lookup.typeToIndex(ty, .forward), .payload => unreachable, }) |fwd_idx| { - const ptr_ty = ty.slicePtrFieldType(mod); + const ptr_ty = ty.slicePtrFieldType(zcu); if (try lookup.typeToIndex(ptr_ty, kind)) |ptr_idx| { self.storage = .{ .anon = undefined }; self.storage.anon.fields[0] = .{ .name = "ptr", .type = ptr_idx, - .alignas = AlignAs.abiAlign(ptr_ty, mod), + .alignas = AlignAs.abiAlign(ptr_ty, zcu), }; self.storage.anon.fields[1] = .{ .name = "len", .type = Tag.uintptr_t.toIndex(), - .alignas = AlignAs.abiAlign(Type.usize, mod), + .alignas = AlignAs.abiAlign(Type.usize, zcu), }; self.initAnon(kind, fwd_idx, 2); } else self.init(switch (kind) { @@ -1478,11 +1486,16 @@ pub const CType = extern union { }, }; - const pointee_ty = if (info.packed_offset.host_size > 0 and - info.flags.vector_index == .none) - try mod.intType(.unsigned, info.packed_offset.host_size * 8) + const pointee_ty = if (info.packed_offset.host_size > 0 and info.flags.vector_index == .none) + try zcu.intType(.unsigned, info.packed_offset.host_size * 8) + else if (info.flags.alignment == .none or + info.flags.alignment.compareStrict(.gte, Type.fromInterned(info.child).abiAlignment(zcu))) + Type.fromInterned(info.child) else - Type.fromInterned(info.child); + try zcu.intType(.unsigned, @min( + info.flags.alignment.toByteUnitsOptional().?, + lookup.getModule().resolved_target.result.maxIntAlignment(), + ) * 8); if (try lookup.typeToIndex(pointee_ty, .forward)) |child_idx| { self.storage = .{ .child = .{ @@ -1495,24 +1508,24 @@ pub const CType = extern union { } }, - .Struct, .Union => |zig_ty_tag| if (ty.containerLayout(mod) == .@"packed") { - if (mod.typeToPackedStruct(ty)) |packed_struct| { + .Struct, .Union => |zig_ty_tag| if (ty.containerLayout(zcu) == .@"packed") { + if (zcu.typeToPackedStruct(ty)) |packed_struct| { try self.initType(Type.fromInterned(packed_struct.backingIntType(ip).*), kind, lookup); } else { - const bits: u16 = @intCast(ty.bitSize(mod)); - const int_ty = try mod.intType(.unsigned, bits); + const bits: u16 = @intCast(ty.bitSize(zcu)); + const int_ty = try zcu.intType(.unsigned, bits); try self.initType(int_ty, kind, lookup); } - } else if (ty.isTupleOrAnonStruct(mod)) { + } else if (ty.isTupleOrAnonStruct(zcu)) { if (lookup.isMutable()) { for (0..switch (zig_ty_tag) { - .Struct => ty.structFieldCount(mod), - .Union => mod.typeToUnion(ty).?.field_types.len, + .Struct => ty.structFieldCount(zcu), + .Union => zcu.typeToUnion(ty).?.field_types.len, else => unreachable, }) |field_i| { - const field_ty = ty.structFieldType(field_i, mod); - if ((zig_ty_tag == .Struct and ty.structFieldIsComptime(field_i, mod)) or - !field_ty.hasRuntimeBitsIgnoreComptime(mod)) continue; + const field_ty = ty.structFieldType(field_i, zcu); + if ((zig_ty_tag == .Struct and ty.structFieldIsComptime(field_i, zcu)) or + !field_ty.hasRuntimeBitsIgnoreComptime(zcu)) continue; _ = try lookup.typeToIndex(field_ty, switch (kind) { .forward, .forward_parameter => .forward, .complete, .parameter => .complete, @@ -1540,14 +1553,14 @@ pub const CType = extern union { .payload => unreachable, }); } else { - const tag_ty = ty.unionTagTypeSafety(mod); + const tag_ty = ty.unionTagTypeSafety(zcu); const is_tagged_union_wrapper = kind != .payload and tag_ty != null; const is_struct = zig_ty_tag == .Struct or is_tagged_union_wrapper; switch (kind) { .forward, .forward_parameter => { self.storage = .{ .fwd = .{ .base = .{ .tag = if (is_struct) .fwd_struct else .fwd_union }, - .data = ty.getOwnerDecl(mod), + .data = ty.getOwnerDecl(zcu), } }; self.value = .{ .cty = initPayload(&self.storage.fwd) }; }, @@ -1562,7 +1575,7 @@ pub const CType = extern union { self.storage.anon.fields[field_count] = .{ .name = "payload", .type = payload_idx.?, - .alignas = AlignAs.unionPayloadAlign(ty, mod), + .alignas = AlignAs.unionPayloadAlign(ty, zcu), }; field_count += 1; } @@ -1570,7 +1583,7 @@ pub const CType = extern union { self.storage.anon.fields[field_count] = .{ .name = "tag", .type = tag_idx.?, - .alignas = AlignAs.abiAlign(tag_ty.?, mod), + .alignas = AlignAs.abiAlign(tag_ty.?, zcu), }; field_count += 1; } @@ -1583,19 +1596,19 @@ pub const CType = extern union { } }; self.value = .{ .cty = initPayload(&self.storage.anon.pl.complete) }; } else self.init(.@"struct"); - } else if (kind == .payload and ty.unionHasAllZeroBitFieldTypes(mod)) { + } else if (kind == .payload and ty.unionHasAllZeroBitFieldTypes(zcu)) { self.init(.void); } else { var is_packed = false; for (0..switch (zig_ty_tag) { - .Struct => ty.structFieldCount(mod), - .Union => mod.typeToUnion(ty).?.field_types.len, + .Struct => ty.structFieldCount(zcu), + .Union => zcu.typeToUnion(ty).?.field_types.len, else => unreachable, }) |field_i| { - const field_ty = ty.structFieldType(field_i, mod); - if (!field_ty.hasRuntimeBitsIgnoreComptime(mod)) continue; + const field_ty = ty.structFieldType(field_i, zcu); + if (!field_ty.hasRuntimeBitsIgnoreComptime(zcu)) continue; - const field_align = AlignAs.fieldAlign(ty, field_i, mod); + const field_align = AlignAs.fieldAlign(ty, field_i, zcu); if (field_align.abiOrder().compare(.lt)) { is_packed = true; if (!lookup.isMutable()) break; @@ -1634,9 +1647,9 @@ pub const CType = extern union { .Vector => .vector, else => unreachable, }; - if (try lookup.typeToIndex(ty.childType(mod), kind)) |child_idx| { + if (try lookup.typeToIndex(ty.childType(zcu), kind)) |child_idx| { self.storage = .{ .seq = .{ .base = .{ .tag = t }, .data = .{ - .len = ty.arrayLenIncludingSentinel(mod), + .len = ty.arrayLenIncludingSentinel(zcu), .elem_type = child_idx, } } }; self.value = .{ .cty = initPayload(&self.storage.seq) }; @@ -1648,9 +1661,9 @@ pub const CType = extern union { }, .Optional => { - const payload_ty = ty.optionalChild(mod); - if (payload_ty.hasRuntimeBitsIgnoreComptime(mod)) { - if (ty.optionalReprIsPayload(mod)) { + const payload_ty = ty.optionalChild(zcu); + if (payload_ty.hasRuntimeBitsIgnoreComptime(zcu)) { + if (ty.optionalReprIsPayload(zcu)) { try self.initType(payload_ty, kind, lookup); } else if (switch (kind) { .forward, .forward_parameter => @as(Index, undefined), @@ -1667,12 +1680,12 @@ pub const CType = extern union { self.storage.anon.fields[0] = .{ .name = "payload", .type = payload_idx, - .alignas = AlignAs.abiAlign(payload_ty, mod), + .alignas = AlignAs.abiAlign(payload_ty, zcu), }; self.storage.anon.fields[1] = .{ .name = "is_null", .type = Tag.bool.toIndex(), - .alignas = AlignAs.abiAlign(Type.bool, mod), + .alignas = AlignAs.abiAlign(Type.bool, zcu), }; self.initAnon(kind, fwd_idx, 2); } else self.init(switch (kind) { @@ -1690,14 +1703,14 @@ pub const CType = extern union { .complete, .parameter, .global => try lookup.typeToIndex(ty, .forward), .payload => unreachable, }) |fwd_idx| { - const payload_ty = ty.errorUnionPayload(mod); + const payload_ty = ty.errorUnionPayload(zcu); if (try lookup.typeToIndex(payload_ty, switch (kind) { .forward, .forward_parameter => .forward, .complete, .parameter => .complete, .global => .global, .payload => unreachable, })) |payload_idx| { - const error_ty = ty.errorUnionSet(mod); + const error_ty = ty.errorUnionSet(zcu); if (payload_idx == Tag.void.toIndex()) { try self.initType(error_ty, kind, lookup); } else if (try lookup.typeToIndex(error_ty, kind)) |error_idx| { @@ -1705,12 +1718,12 @@ pub const CType = extern union { self.storage.anon.fields[0] = .{ .name = "payload", .type = payload_idx, - .alignas = AlignAs.abiAlign(payload_ty, mod), + .alignas = AlignAs.abiAlign(payload_ty, zcu), }; self.storage.anon.fields[1] = .{ .name = "error", .type = error_idx, - .alignas = AlignAs.abiAlign(error_ty, mod), + .alignas = AlignAs.abiAlign(error_ty, zcu), }; self.initAnon(kind, fwd_idx, 2); } else self.init(switch (kind) { @@ -1729,7 +1742,7 @@ pub const CType = extern union { .Opaque => self.init(.void), .Fn => { - const info = mod.typeToFunc(ty).?; + const info = zcu.typeToFunc(ty).?; if (!info.is_generic) { if (lookup.isMutable()) { const param_kind: Kind = switch (kind) { @@ -1739,7 +1752,7 @@ pub const CType = extern union { }; _ = try lookup.typeToIndex(Type.fromInterned(info.return_type), param_kind); for (info.param_types.get(ip)) |param_type| { - if (!Type.fromInterned(param_type).hasRuntimeBitsIgnoreComptime(mod)) continue; + if (!Type.fromInterned(param_type).hasRuntimeBitsIgnoreComptime(zcu)) continue; _ = try lookup.typeToIndex(Type.fromInterned(param_type), param_kind); } } @@ -1906,20 +1919,21 @@ pub const CType = extern union { } } - fn createFromType(store: *Store.Promoted, ty: Type, mod: *Module, kind: Kind) !CType { + fn createFromType(store: *Store.Promoted, ty: Type, zcu: *Zcu, mod: *Module, kind: Kind) !CType { var convert: Convert = undefined; - try convert.initType(ty, kind, .{ .imm = .{ .set = &store.set, .mod = mod } }); - return createFromConvert(store, ty, mod, kind, &convert); + try convert.initType(ty, kind, .{ .imm = .{ .set = &store.set, .zcu = zcu } }); + return createFromConvert(store, ty, zcu, mod, kind, &convert); } fn createFromConvert( store: *Store.Promoted, ty: Type, + zcu: *Zcu, mod: *Module, kind: Kind, convert: Convert, ) !CType { - const ip = &mod.intern_pool; + const ip = &zcu.intern_pool; const arena = store.arena.allocator(); switch (convert.value) { .cty => |c| return c.copy(arena), @@ -1937,18 +1951,18 @@ pub const CType = extern union { .packed_struct, .packed_union, => { - const zig_ty_tag = ty.zigTypeTag(mod); + const zig_ty_tag = ty.zigTypeTag(zcu); const fields_len = switch (zig_ty_tag) { - .Struct => ty.structFieldCount(mod), - .Union => mod.typeToUnion(ty).?.field_types.len, + .Struct => ty.structFieldCount(zcu), + .Union => zcu.typeToUnion(ty).?.field_types.len, else => unreachable, }; var c_fields_len: usize = 0; for (0..fields_len) |field_i| { - const field_ty = ty.structFieldType(field_i, mod); - if ((zig_ty_tag == .Struct and ty.structFieldIsComptime(field_i, mod)) or - !field_ty.hasRuntimeBitsIgnoreComptime(mod)) continue; + const field_ty = ty.structFieldType(field_i, zcu); + if ((zig_ty_tag == .Struct and ty.structFieldIsComptime(field_i, zcu)) or + !field_ty.hasRuntimeBitsIgnoreComptime(zcu)) continue; c_fields_len += 1; } @@ -1956,26 +1970,26 @@ pub const CType = extern union { var c_field_i: usize = 0; for (0..fields_len) |field_i_usize| { const field_i: u32 = @intCast(field_i_usize); - const field_ty = ty.structFieldType(field_i, mod); - if ((zig_ty_tag == .Struct and ty.structFieldIsComptime(field_i, mod)) or - !field_ty.hasRuntimeBitsIgnoreComptime(mod)) continue; + const field_ty = ty.structFieldType(field_i, zcu); + if ((zig_ty_tag == .Struct and ty.structFieldIsComptime(field_i, zcu)) or + !field_ty.hasRuntimeBitsIgnoreComptime(zcu)) continue; defer c_field_i += 1; fields_pl[c_field_i] = .{ - .name = try if (ty.isSimpleTuple(mod)) + .name = try if (ty.isSimpleTuple(zcu)) std.fmt.allocPrintZ(arena, "f{}", .{field_i}) else arena.dupeZ(u8, ip.stringToSlice(switch (zig_ty_tag) { - .Struct => ty.legacyStructFieldName(field_i, mod), + .Struct => ty.legacyStructFieldName(field_i, zcu), .Union => ip.loadUnionType(ty.toIntern()).loadTagType(ip).names.get(ip)[field_i], else => unreachable, })), - .type = store.set.typeToIndex(field_ty, mod, switch (kind) { + .type = store.set.typeToIndex(field_ty, zcu, mod, switch (kind) { .forward, .forward_parameter => .forward, .complete, .parameter, .payload => .complete, .global => .global, }).?, - .alignas = AlignAs.fieldAlign(ty, field_i, mod), + .alignas = AlignAs.fieldAlign(ty, field_i, zcu), }; } @@ -1996,8 +2010,8 @@ pub const CType = extern union { const unnamed_pl = try arena.create(Payload.Unnamed); unnamed_pl.* = .{ .base = .{ .tag = t }, .data = .{ .fields = fields_pl, - .owner_decl = ty.getOwnerDecl(mod), - .id = if (ty.unionTagTypeSafety(mod)) |_| 0 else unreachable, + .owner_decl = ty.getOwnerDecl(zcu), + .id = if (ty.unionTagTypeSafety(zcu)) |_| 0 else unreachable, } }; return initPayload(unnamed_pl); }, @@ -2012,7 +2026,7 @@ pub const CType = extern union { const struct_pl = try arena.create(Payload.Aggregate); struct_pl.* = .{ .base = .{ .tag = t }, .data = .{ .fields = fields_pl, - .fwd_decl = store.set.typeToIndex(ty, mod, .forward).?, + .fwd_decl = store.set.typeToIndex(ty, zcu, mod, .forward).?, } }; return initPayload(struct_pl); }, @@ -2024,7 +2038,7 @@ pub const CType = extern union { .function, .varargs_function, => { - const info = mod.typeToFunc(ty).?; + const info = zcu.typeToFunc(ty).?; assert(!info.is_generic); const param_kind: Kind = switch (kind) { .forward, .forward_parameter => .forward_parameter, @@ -2034,21 +2048,21 @@ pub const CType = extern union { var c_params_len: usize = 0; for (info.param_types.get(ip)) |param_type| { - if (!Type.fromInterned(param_type).hasRuntimeBitsIgnoreComptime(mod)) continue; + if (!Type.fromInterned(param_type).hasRuntimeBitsIgnoreComptime(zcu)) continue; c_params_len += 1; } const params_pl = try arena.alloc(Index, c_params_len); var c_param_i: usize = 0; for (info.param_types.get(ip)) |param_type| { - if (!Type.fromInterned(param_type).hasRuntimeBitsIgnoreComptime(mod)) continue; - params_pl[c_param_i] = store.set.typeToIndex(Type.fromInterned(param_type), mod, param_kind).?; + if (!Type.fromInterned(param_type).hasRuntimeBitsIgnoreComptime(zcu)) continue; + params_pl[c_param_i] = store.set.typeToIndex(Type.fromInterned(param_type), zcu, mod, param_kind).?; c_param_i += 1; } const fn_pl = try arena.create(Payload.Function); fn_pl.* = .{ .base = .{ .tag = t }, .data = .{ - .return_type = store.set.typeToIndex(Type.fromInterned(info.return_type), mod, param_kind).?, + .return_type = store.set.typeToIndex(Type.fromInterned(info.return_type), zcu, mod, param_kind).?, .param_types = params_pl, } }; return initPayload(fn_pl); @@ -2075,8 +2089,8 @@ pub const CType = extern union { } pub fn eql(self: @This(), ty: Type, cty: CType) bool { - const mod = self.lookup.getModule(); - const ip = &mod.intern_pool; + const zcu = self.lookup.getZcu(); + const ip = &zcu.intern_pool; switch (self.convert.value) { .cty => |c| return c.eql(cty), .tag => |t| { @@ -2086,24 +2100,24 @@ pub const CType = extern union { .fwd_anon_struct, .fwd_anon_union, => { - if (!ty.isTupleOrAnonStruct(mod)) return false; + if (!ty.isTupleOrAnonStruct(zcu)) return false; var name_buf: [ std.fmt.count("f{}", .{std.math.maxInt(usize)}) ]u8 = undefined; const c_fields = cty.cast(Payload.Fields).?.data; - const zig_ty_tag = ty.zigTypeTag(mod); + const zig_ty_tag = ty.zigTypeTag(zcu); var c_field_i: usize = 0; for (0..switch (zig_ty_tag) { - .Struct => ty.structFieldCount(mod), - .Union => mod.typeToUnion(ty).?.field_types.len, + .Struct => ty.structFieldCount(zcu), + .Union => zcu.typeToUnion(ty).?.field_types.len, else => unreachable, }) |field_i_usize| { const field_i: u32 = @intCast(field_i_usize); - const field_ty = ty.structFieldType(field_i, mod); - if ((zig_ty_tag == .Struct and ty.structFieldIsComptime(field_i, mod)) or - !field_ty.hasRuntimeBitsIgnoreComptime(mod)) continue; + const field_ty = ty.structFieldType(field_i, zcu); + if ((zig_ty_tag == .Struct and ty.structFieldIsComptime(field_i, zcu)) or + !field_ty.hasRuntimeBitsIgnoreComptime(zcu)) continue; defer c_field_i += 1; const c_field = &c_fields[c_field_i]; @@ -2115,16 +2129,16 @@ pub const CType = extern union { .payload => unreachable, }) or !mem.eql( u8, - if (ty.isSimpleTuple(mod)) + if (ty.isSimpleTuple(zcu)) std.fmt.bufPrintZ(&name_buf, "f{}", .{field_i}) catch unreachable else ip.stringToSlice(switch (zig_ty_tag) { - .Struct => ty.legacyStructFieldName(field_i, mod), + .Struct => ty.legacyStructFieldName(field_i, zcu), .Union => ip.loadUnionType(ty.toIntern()).loadTagType(ip).names.get(ip)[field_i], else => unreachable, }), mem.span(c_field.name), - ) or AlignAs.fieldAlign(ty, field_i, mod).@"align" != + ) or AlignAs.fieldAlign(ty, field_i, zcu).@"align" != c_field.alignas.@"align") return false; } return true; @@ -2136,9 +2150,9 @@ pub const CType = extern union { .packed_unnamed_union, => switch (self.kind) { .forward, .forward_parameter, .complete, .parameter, .global => unreachable, - .payload => if (ty.unionTagTypeSafety(mod)) |_| { + .payload => if (ty.unionTagTypeSafety(zcu)) |_| { const data = cty.cast(Payload.Unnamed).?.data; - return ty.getOwnerDecl(mod) == data.owner_decl and data.id == 0; + return ty.getOwnerDecl(zcu) == data.owner_decl and data.id == 0; } else unreachable, }, @@ -2157,9 +2171,9 @@ pub const CType = extern union { .function, .varargs_function, => { - if (ty.zigTypeTag(mod) != .Fn) return false; + if (ty.zigTypeTag(zcu) != .Fn) return false; - const info = mod.typeToFunc(ty).?; + const info = zcu.typeToFunc(ty).?; assert(!info.is_generic); const data = cty.cast(Payload.Function).?.data; const param_kind: Kind = switch (self.kind) { @@ -2173,7 +2187,7 @@ pub const CType = extern union { var c_param_i: usize = 0; for (info.param_types.get(ip)) |param_type| { - if (!Type.fromInterned(param_type).hasRuntimeBitsIgnoreComptime(mod)) continue; + if (!Type.fromInterned(param_type).hasRuntimeBitsIgnoreComptime(zcu)) continue; if (c_param_i >= data.param_types.len) return false; const param_cty = data.param_types[c_param_i]; @@ -2213,8 +2227,8 @@ pub const CType = extern union { .tag => |t| { autoHash(hasher, t); - const mod = self.lookup.getModule(); - const ip = &mod.intern_pool; + const zcu = self.lookup.getZcu(); + const ip = &zcu.intern_pool; switch (t) { .fwd_anon_struct, .fwd_anon_union, @@ -2223,16 +2237,16 @@ pub const CType = extern union { std.fmt.count("f{}", .{std.math.maxInt(usize)}) ]u8 = undefined; - const zig_ty_tag = ty.zigTypeTag(mod); - for (0..switch (ty.zigTypeTag(mod)) { - .Struct => ty.structFieldCount(mod), - .Union => mod.typeToUnion(ty).?.field_types.len, + const zig_ty_tag = ty.zigTypeTag(zcu); + for (0..switch (ty.zigTypeTag(zcu)) { + .Struct => ty.structFieldCount(zcu), + .Union => zcu.typeToUnion(ty).?.field_types.len, else => unreachable, }) |field_i_usize| { const field_i: u32 = @intCast(field_i_usize); - const field_ty = ty.structFieldType(field_i, mod); - if ((zig_ty_tag == .Struct and ty.structFieldIsComptime(field_i, mod)) or - !field_ty.hasRuntimeBitsIgnoreComptime(mod)) continue; + const field_ty = ty.structFieldType(field_i, zcu); + if ((zig_ty_tag == .Struct and ty.structFieldIsComptime(field_i, zcu)) or + !field_ty.hasRuntimeBitsIgnoreComptime(zcu)) continue; self.updateHasherRecurse(hasher, field_ty, switch (self.kind) { .forward, .forward_parameter => .forward, @@ -2240,15 +2254,15 @@ pub const CType = extern union { .global => .global, .payload => unreachable, }); - hasher.update(if (ty.isSimpleTuple(mod)) + hasher.update(if (ty.isSimpleTuple(zcu)) std.fmt.bufPrint(&name_buf, "f{}", .{field_i}) catch unreachable else - mod.intern_pool.stringToSlice(switch (zig_ty_tag) { - .Struct => ty.legacyStructFieldName(field_i, mod), + zcu.intern_pool.stringToSlice(switch (zig_ty_tag) { + .Struct => ty.legacyStructFieldName(field_i, zcu), .Union => ip.loadUnionType(ty.toIntern()).loadTagType(ip).names.get(ip)[field_i], else => unreachable, })); - autoHash(hasher, AlignAs.fieldAlign(ty, field_i, mod).@"align"); + autoHash(hasher, AlignAs.fieldAlign(ty, field_i, zcu).@"align"); } }, @@ -2258,8 +2272,8 @@ pub const CType = extern union { .packed_unnamed_union, => switch (self.kind) { .forward, .forward_parameter, .complete, .parameter, .global => unreachable, - .payload => if (ty.unionTagTypeSafety(mod)) |_| { - autoHash(hasher, ty.getOwnerDecl(mod)); + .payload => if (ty.unionTagTypeSafety(zcu)) |_| { + autoHash(hasher, ty.getOwnerDecl(zcu)); autoHash(hasher, @as(u32, 0)); } else unreachable, }, @@ -2275,7 +2289,7 @@ pub const CType = extern union { .function, .varargs_function, => { - const info = mod.typeToFunc(ty).?; + const info = zcu.typeToFunc(ty).?; assert(!info.is_generic); const param_kind: Kind = switch (self.kind) { .forward, .forward_parameter => .forward_parameter, @@ -2285,7 +2299,7 @@ pub const CType = extern union { self.updateHasherRecurse(hasher, Type.fromInterned(info.return_type), param_kind); for (info.param_types.get(ip)) |param_type| { - if (!Type.fromInterned(param_type).hasRuntimeBitsIgnoreComptime(mod)) continue; + if (!Type.fromInterned(param_type).hasRuntimeBitsIgnoreComptime(zcu)) continue; self.updateHasherRecurse(hasher, Type.fromInterned(param_type), param_kind); } }, diff --git a/src/link/C.zig b/src/link/C.zig index 73049b40cd13..d717903ff317 100644 --- a/src/link/C.zig +++ b/src/link/C.zig @@ -6,7 +6,8 @@ const fs = std.fs; const C = @This(); const build_options = @import("build_options"); -const Module = @import("../Module.zig"); +const Zcu = @import("../Module.zig"); +const Module = @import("../Package/Module.zig"); const InternPool = @import("../InternPool.zig"); const Alignment = InternPool.Alignment; const Compilation = @import("../Compilation.zig"); @@ -177,16 +178,16 @@ pub fn freeDecl(self: *C, decl_index: InternPool.DeclIndex) void { pub fn updateFunc( self: *C, - module: *Module, + zcu: *Zcu, func_index: InternPool.Index, air: Air, liveness: Liveness, ) !void { const gpa = self.base.comp.gpa; - const func = module.funcInfo(func_index); + const func = zcu.funcInfo(func_index); const decl_index = func.owner_decl; - const decl = module.declPtr(decl_index); + const decl = zcu.declPtr(decl_index); const gop = try self.decl_table.getOrPut(gpa, decl_index); if (!gop.found_existing) gop.value_ptr.* = .{}; const ctypes = &gop.value_ptr.ctypes; @@ -206,10 +207,11 @@ pub fn updateFunc( .object = .{ .dg = .{ .gpa = gpa, - .module = module, + .zcu = zcu, + .mod = zcu.namespacePtr(decl.src_namespace).file_scope.mod, .error_msg = null, .pass = .{ .decl = decl_index }, - .is_naked_fn = decl.typeOf(module).fnCallingConvention(module) == .Naked, + .is_naked_fn = decl.typeOf(zcu).fnCallingConvention(zcu) == .Naked, .fwd_decl = fwd_decl.toManaged(gpa), .ctypes = ctypes.*, .anon_decl_deps = self.anon_decls, @@ -232,7 +234,7 @@ pub fn updateFunc( codegen.genFunc(&function) catch |err| switch (err) { error.AnalysisFail => { - try module.failed_decls.put(gpa, decl_index, function.object.dg.error_msg.?); + try zcu.failed_decls.put(gpa, decl_index, function.object.dg.error_msg.?); return; }, else => |e| return e, @@ -249,7 +251,7 @@ pub fn updateFunc( gop.value_ptr.fwd_decl = try self.addString(function.object.dg.fwd_decl.items); } -fn updateAnonDecl(self: *C, module: *Module, i: usize) !void { +fn updateAnonDecl(self: *C, zcu: *Zcu, i: usize) !void { const gpa = self.base.comp.gpa; const anon_decl = self.anon_decls.keys()[i]; @@ -261,7 +263,8 @@ fn updateAnonDecl(self: *C, module: *Module, i: usize) !void { var object: codegen.Object = .{ .dg = .{ .gpa = gpa, - .module = module, + .zcu = zcu, + .mod = zcu.root_mod, .error_msg = null, .pass = .{ .anon = anon_decl }, .is_naked_fn = false, @@ -283,12 +286,12 @@ fn updateAnonDecl(self: *C, module: *Module, i: usize) !void { code.* = object.code.moveToUnmanaged(); } - const c_value: codegen.CValue = .{ .constant = anon_decl }; + const c_value: codegen.CValue = .{ .constant = Value.fromInterned(anon_decl) }; const alignment: Alignment = self.aligned_anon_decls.get(anon_decl) orelse .none; - codegen.genDeclValue(&object, Value.fromInterned(anon_decl), false, c_value, alignment, .none) catch |err| switch (err) { + codegen.genDeclValue(&object, c_value.constant, false, c_value, alignment, .none) catch |err| switch (err) { error.AnalysisFail => { @panic("TODO: C backend AnalysisFail on anonymous decl"); - //try module.failed_decls.put(gpa, decl_index, object.dg.error_msg.?); + //try zcu.failed_decls.put(gpa, decl_index, object.dg.error_msg.?); //return; }, else => |e| return e, @@ -304,12 +307,13 @@ fn updateAnonDecl(self: *C, module: *Module, i: usize) !void { }; } -pub fn updateDecl(self: *C, module: *Module, decl_index: InternPool.DeclIndex) !void { +pub fn updateDecl(self: *C, zcu: *Zcu, decl_index: InternPool.DeclIndex) !void { const tracy = trace(@src()); defer tracy.end(); const gpa = self.base.comp.gpa; + const decl = zcu.declPtr(decl_index); const gop = try self.decl_table.getOrPut(gpa, decl_index); if (!gop.found_existing) { gop.value_ptr.* = .{}; @@ -324,7 +328,8 @@ pub fn updateDecl(self: *C, module: *Module, decl_index: InternPool.DeclIndex) ! var object: codegen.Object = .{ .dg = .{ .gpa = gpa, - .module = module, + .zcu = zcu, + .mod = zcu.namespacePtr(decl.src_namespace).file_scope.mod, .error_msg = null, .pass = .{ .decl = decl_index }, .is_naked_fn = false, @@ -347,7 +352,7 @@ pub fn updateDecl(self: *C, module: *Module, decl_index: InternPool.DeclIndex) ! codegen.genDecl(&object) catch |err| switch (err) { error.AnalysisFail => { - try module.failed_decls.put(gpa, decl_index, object.dg.error_msg.?); + try zcu.failed_decls.put(gpa, decl_index, object.dg.error_msg.?); return; }, else => |e| return e, @@ -362,11 +367,11 @@ pub fn updateDecl(self: *C, module: *Module, decl_index: InternPool.DeclIndex) ! gop.value_ptr.fwd_decl = try self.addString(object.dg.fwd_decl.items); } -pub fn updateDeclLineNumber(self: *C, module: *Module, decl_index: InternPool.DeclIndex) !void { +pub fn updateDeclLineNumber(self: *C, zcu: *Zcu, decl_index: InternPool.DeclIndex) !void { // The C backend does not have the ability to fix line numbers without re-generating // the entire Decl. _ = self; - _ = module; + _ = zcu; _ = decl_index; } @@ -399,12 +404,12 @@ pub fn flushModule(self: *C, arena: Allocator, prog_node: *std.Progress.Node) !v const comp = self.base.comp; const gpa = comp.gpa; - const module = self.base.comp.module.?; + const zcu = self.base.comp.module.?; { var i: usize = 0; while (i < self.anon_decls.count()) : (i += 1) { - try updateAnonDecl(self, module, i); + try updateAnonDecl(self, zcu, i); } } @@ -414,7 +419,7 @@ pub fn flushModule(self: *C, arena: Allocator, prog_node: *std.Progress.Node) !v var f: Flush = .{}; defer f.deinit(gpa); - const abi_defines = try self.abiDefines(module.getTarget()); + const abi_defines = try self.abiDefines(zcu.getTarget()); defer abi_defines.deinit(); // Covers defines, zig.h, ctypes, asm, lazy fwd. @@ -429,7 +434,7 @@ pub fn flushModule(self: *C, arena: Allocator, prog_node: *std.Progress.Node) !v { var asm_buf = f.asm_buf.toManaged(gpa); defer f.asm_buf = asm_buf.moveToUnmanaged(); - try codegen.genGlobalAsm(module, asm_buf.writer()); + try codegen.genGlobalAsm(zcu, asm_buf.writer()); f.appendBufAssumeCapacity(asm_buf.items); } @@ -438,7 +443,7 @@ pub fn flushModule(self: *C, arena: Allocator, prog_node: *std.Progress.Node) !v self.lazy_fwd_decl_buf.clearRetainingCapacity(); self.lazy_code_buf.clearRetainingCapacity(); - try self.flushErrDecls(&f.lazy_ctypes); + try self.flushErrDecls(zcu, &f.lazy_ctypes); // Unlike other backends, the .c code we are emitting has order-dependent decls. // `CType`s, forward decls, and non-functions first. @@ -446,19 +451,20 @@ pub fn flushModule(self: *C, arena: Allocator, prog_node: *std.Progress.Node) !v { var export_names: std.AutoHashMapUnmanaged(InternPool.NullTerminatedString, void) = .{}; defer export_names.deinit(gpa); - try export_names.ensureTotalCapacity(gpa, @intCast(module.decl_exports.entries.len)); - for (module.decl_exports.values()) |exports| for (exports.items) |@"export"| + try export_names.ensureTotalCapacity(gpa, @intCast(zcu.decl_exports.entries.len)); + for (zcu.decl_exports.values()) |exports| for (exports.items) |@"export"| try export_names.put(gpa, @"export".opts.name, {}); for (self.anon_decls.values()) |*decl_block| { - try self.flushDeclBlock(&f, decl_block, export_names, .none); + try self.flushDeclBlock(zcu, zcu.root_mod, &f, decl_block, export_names, .none); } for (self.decl_table.keys(), self.decl_table.values()) |decl_index, *decl_block| { - assert(module.declPtr(decl_index).has_tv); - const decl = module.declPtr(decl_index); - const extern_symbol_name = if (decl.isExtern(module)) decl.name.toOptional() else .none; - try self.flushDeclBlock(&f, decl_block, export_names, extern_symbol_name); + const decl = zcu.declPtr(decl_index); + assert(decl.has_tv); + const extern_symbol_name = if (decl.isExtern(zcu)) decl.name.toOptional() else .none; + const mod = zcu.namespacePtr(decl.src_namespace).file_scope.mod; + try self.flushDeclBlock(zcu, mod, &f, decl_block, export_names, extern_symbol_name); } } @@ -466,14 +472,14 @@ pub fn flushModule(self: *C, arena: Allocator, prog_node: *std.Progress.Node) !v // We need to flush lazy ctypes after flushing all decls but before flushing any decl ctypes. // This ensures that every lazy CType.Index exactly matches the global CType.Index. assert(f.ctypes.count() == 0); - try self.flushCTypes(&f, .flush, f.lazy_ctypes); + try self.flushCTypes(zcu, &f, .flush, f.lazy_ctypes); for (self.anon_decls.keys(), self.anon_decls.values()) |anon_decl, decl_block| { - try self.flushCTypes(&f, .{ .anon = anon_decl }, decl_block.ctypes); + try self.flushCTypes(zcu, &f, .{ .anon = anon_decl }, decl_block.ctypes); } for (self.decl_table.keys(), self.decl_table.values()) |decl_index, decl_block| { - try self.flushCTypes(&f, .{ .decl = decl_index }, decl_block.ctypes); + try self.flushCTypes(zcu, &f, .{ .decl = decl_index }, decl_block.ctypes); } } @@ -543,12 +549,12 @@ const FlushDeclError = error{ fn flushCTypes( self: *C, + zcu: *Zcu, f: *Flush, pass: codegen.DeclGen.Pass, decl_ctypes: codegen.CType.Store, ) FlushDeclError!void { const gpa = self.base.comp.gpa; - const mod = self.base.comp.module.?; const decl_ctypes_len = decl_ctypes.count(); f.ctypes_map.clearRetainingCapacity(); @@ -615,7 +621,7 @@ fn flushCTypes( assert(decl_cty.hash(decl_ctypes.set) == global_cty.hash(global_ctypes.set)); } try codegen.genTypeDecl( - mod, + zcu, writer, global_ctypes.set, global_idx, @@ -627,7 +633,7 @@ fn flushCTypes( } } -fn flushErrDecls(self: *C, ctypes: *codegen.CType.Store) FlushDeclError!void { +fn flushErrDecls(self: *C, zcu: *Zcu, ctypes: *codegen.CType.Store) FlushDeclError!void { const gpa = self.base.comp.gpa; const fwd_decl = &self.lazy_fwd_decl_buf; @@ -636,7 +642,8 @@ fn flushErrDecls(self: *C, ctypes: *codegen.CType.Store) FlushDeclError!void { var object = codegen.Object{ .dg = .{ .gpa = gpa, - .module = self.base.comp.module.?, + .zcu = zcu, + .mod = zcu.root_mod, .error_msg = null, .pass = .flush, .is_naked_fn = false, @@ -667,6 +674,8 @@ fn flushErrDecls(self: *C, ctypes: *codegen.CType.Store) FlushDeclError!void { fn flushLazyFn( self: *C, + zcu: *Zcu, + mod: *Module, ctypes: *codegen.CType.Store, lazy_fn: codegen.LazyFnMap.Entry, ) FlushDeclError!void { @@ -678,7 +687,8 @@ fn flushLazyFn( var object = codegen.Object{ .dg = .{ .gpa = gpa, - .module = self.base.comp.module.?, + .zcu = zcu, + .mod = mod, .error_msg = null, .pass = .flush, .is_naked_fn = false, @@ -709,7 +719,13 @@ fn flushLazyFn( ctypes.* = object.dg.ctypes.move(); } -fn flushLazyFns(self: *C, f: *Flush, lazy_fns: codegen.LazyFnMap) FlushDeclError!void { +fn flushLazyFns( + self: *C, + zcu: *Zcu, + mod: *Module, + f: *Flush, + lazy_fns: codegen.LazyFnMap, +) FlushDeclError!void { const gpa = self.base.comp.gpa; try f.lazy_fns.ensureUnusedCapacity(gpa, @intCast(lazy_fns.count())); @@ -718,19 +734,21 @@ fn flushLazyFns(self: *C, f: *Flush, lazy_fns: codegen.LazyFnMap) FlushDeclError const gop = f.lazy_fns.getOrPutAssumeCapacity(entry.key_ptr.*); if (gop.found_existing) continue; gop.value_ptr.* = {}; - try self.flushLazyFn(&f.lazy_ctypes, entry); + try self.flushLazyFn(zcu, mod, &f.lazy_ctypes, entry); } } fn flushDeclBlock( self: *C, + zcu: *Zcu, + mod: *Module, f: *Flush, decl_block: *DeclBlock, export_names: std.AutoHashMapUnmanaged(InternPool.NullTerminatedString, void), extern_symbol_name: InternPool.OptionalNullTerminatedString, ) FlushDeclError!void { const gpa = self.base.comp.gpa; - try self.flushLazyFns(f, decl_block.lazy_fns); + try self.flushLazyFns(zcu, mod, f, decl_block.lazy_fns); try f.all_buffers.ensureUnusedCapacity(gpa, 1); fwd_decl: { if (extern_symbol_name.unwrap()) |name| { @@ -740,15 +758,15 @@ fn flushDeclBlock( } } -pub fn flushEmitH(module: *Module) !void { +pub fn flushEmitH(zcu: *Zcu) !void { const tracy = trace(@src()); defer tracy.end(); - const emit_h = module.emit_h orelse return; + const emit_h = zcu.emit_h orelse return; // We collect a list of buffers to write, and write them all at once with pwritev 😎 const num_buffers = emit_h.decl_table.count() + 1; - var all_buffers = try std.ArrayList(std.posix.iovec_const).initCapacity(module.gpa, num_buffers); + var all_buffers = try std.ArrayList(std.posix.iovec_const).initCapacity(zcu.gpa, num_buffers); defer all_buffers.deinit(); var file_size: u64 = zig_h.len; @@ -771,7 +789,7 @@ pub fn flushEmitH(module: *Module) !void { } } - const directory = emit_h.loc.directory orelse module.comp.local_cache_directory; + const directory = emit_h.loc.directory orelse zcu.comp.local_cache_directory; const file = try directory.handle.createFile(emit_h.loc.basename, .{ // We set the end position explicitly below; by not truncating the file, we possibly // make it easier on the file system by doing 1 reallocation instead of two. @@ -785,12 +803,12 @@ pub fn flushEmitH(module: *Module) !void { pub fn updateExports( self: *C, - module: *Module, - exported: Module.Exported, - exports: []const *Module.Export, + zcu: *Zcu, + exported: Zcu.Exported, + exports: []const *Zcu.Export, ) !void { _ = exports; _ = exported; - _ = module; + _ = zcu; _ = self; }