aboutsummaryrefslogtreecommitdiff
path: root/src/codegen
diff options
context:
space:
mode:
authorAndrew Kelley <andrew@ziglang.org>2022-04-19 21:51:08 -0700
committerAndrew Kelley <andrew@ziglang.org>2022-04-20 17:37:35 -0700
commitf7596ae9423e9de8276629803147e1a243f2177b (patch)
treeb97f2a8e8fdb84a118f587bcbfd76918710587dd /src/codegen
parent4f527e5d36f66a83ff6a263a03f16e2c4d049f1e (diff)
downloadzig-f7596ae9423e9de8276629803147e1a243f2177b.tar.gz
zig-f7596ae9423e9de8276629803147e1a243f2177b.zip
stage2: use indexes for Decl objects
Rather than allocating Decl objects with an Allocator, we instead allocate them with a SegmentedList. This provides four advantages: * Stable memory so that one thread can access a Decl object while another thread allocates additional Decl objects from this list. * It allows us to use u32 indexes to reference Decl objects rather than pointers, saving memory in Type, Value, and dependency sets. * Using integers to reference Decl objects rather than pointers makes serialization trivial. * It provides a unique integer to be used for anonymous symbol names, avoiding multi-threaded contention on an atomic counter.
Diffstat (limited to 'src/codegen')
-rw-r--r--src/codegen/c.zig87
-rw-r--r--src/codegen/llvm.zig247
-rw-r--r--src/codegen/spirv.zig16
3 files changed, 187 insertions, 163 deletions
diff --git a/src/codegen/c.zig b/src/codegen/c.zig
index 54f8285291..a0b1bc30b9 100644
--- a/src/codegen/c.zig
+++ b/src/codegen/c.zig
@@ -32,8 +32,8 @@ pub const CValue = union(enum) {
/// Index into the parameters
arg: usize,
/// By-value
- decl: *Decl,
- decl_ref: *Decl,
+ decl: Decl.Index,
+ decl_ref: Decl.Index,
/// An undefined (void *) pointer (cannot be dereferenced)
undefined_ptr: void,
/// Render the slice as an identifier (using fmtIdent)
@@ -58,7 +58,7 @@ pub const TypedefMap = std.ArrayHashMap(
const FormatTypeAsCIdentContext = struct {
ty: Type,
- target: std.Target,
+ mod: *Module,
};
/// TODO make this not cut off at 128 bytes
@@ -71,14 +71,14 @@ fn formatTypeAsCIdentifier(
_ = fmt;
_ = options;
var buffer = [1]u8{0} ** 128;
- var buf = std.fmt.bufPrint(&buffer, "{}", .{data.ty.fmt(data.target)}) catch &buffer;
+ var buf = std.fmt.bufPrint(&buffer, "{}", .{data.ty.fmt(data.mod)}) catch &buffer;
return formatIdent(buf, "", .{}, writer);
}
-pub fn typeToCIdentifier(ty: Type, target: std.Target) std.fmt.Formatter(formatTypeAsCIdentifier) {
+pub fn typeToCIdentifier(ty: Type, mod: *Module) std.fmt.Formatter(formatTypeAsCIdentifier) {
return .{ .data = .{
.ty = ty,
- .target = target,
+ .mod = mod,
} };
}
@@ -349,6 +349,7 @@ pub const DeclGen = struct {
gpa: std.mem.Allocator,
module: *Module,
decl: *Decl,
+ decl_index: Decl.Index,
fwd_decl: std.ArrayList(u8),
error_msg: ?*Module.ErrorMsg,
/// The key of this map is Type which has references to typedefs_arena.
@@ -376,10 +377,8 @@ pub const DeclGen = struct {
writer: anytype,
ty: Type,
val: Value,
- decl: *Decl,
+ decl_index: Decl.Index,
) error{ OutOfMemory, AnalysisFail }!void {
- const target = dg.module.getTarget();
-
if (ty.isSlice()) {
try writer.writeByte('(');
try dg.renderTypecast(writer, ty);
@@ -387,11 +386,12 @@ pub const DeclGen = struct {
var buf: Type.SlicePtrFieldTypeBuffer = undefined;
try dg.renderValue(writer, ty.slicePtrFieldType(&buf), val.slicePtr());
try writer.writeAll(", ");
- try writer.print("{d}", .{val.sliceLen(target)});
+ try writer.print("{d}", .{val.sliceLen(dg.module)});
try writer.writeAll("}");
return;
}
+ const decl = dg.module.declPtr(decl_index);
assert(decl.has_tv);
// 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
@@ -399,21 +399,21 @@ pub const DeclGen = struct {
// somewhere and we should let the C compiler tell us about it.
if (ty.castPtrToFn() == null) {
// Determine if we must pointer cast.
- if (ty.eql(decl.ty, target)) {
+ if (ty.eql(decl.ty, dg.module)) {
try writer.writeByte('&');
- try dg.renderDeclName(writer, decl);
+ try dg.renderDeclName(writer, decl_index);
return;
}
try writer.writeAll("((");
try dg.renderTypecast(writer, ty);
try writer.writeAll(")&");
- try dg.renderDeclName(writer, decl);
+ try dg.renderDeclName(writer, decl_index);
try writer.writeByte(')');
return;
}
- try dg.renderDeclName(writer, decl);
+ try dg.renderDeclName(writer, decl_index);
}
fn renderInt128(
@@ -471,13 +471,13 @@ pub const DeclGen = struct {
try writer.writeByte(')');
switch (ptr_val.tag()) {
.decl_ref_mut, .decl_ref, .variable => {
- const decl = switch (ptr_val.tag()) {
+ const decl_index = switch (ptr_val.tag()) {
.decl_ref => ptr_val.castTag(.decl_ref).?.data,
- .decl_ref_mut => ptr_val.castTag(.decl_ref_mut).?.data.decl,
+ .decl_ref_mut => ptr_val.castTag(.decl_ref_mut).?.data.decl_index,
.variable => ptr_val.castTag(.variable).?.data.owner_decl,
else => unreachable,
};
- try dg.renderDeclValue(writer, ptr_ty, ptr_val, decl);
+ try dg.renderDeclValue(writer, ptr_ty, ptr_val, decl_index);
},
.field_ptr => {
const field_ptr = ptr_val.castTag(.field_ptr).?.data;
@@ -685,7 +685,7 @@ pub const DeclGen = struct {
var index: usize = 0;
while (index < ai.len) : (index += 1) {
if (index != 0) try writer.writeAll(",");
- const elem_val = try val.elemValue(arena_allocator, index);
+ const elem_val = try val.elemValue(dg.module, arena_allocator, index);
try dg.renderValue(writer, ai.elem_type, elem_val);
}
if (ai.sentinel) |s| {
@@ -837,7 +837,7 @@ pub const DeclGen = struct {
try writer.writeAll(".payload = {");
}
- const index = union_ty.tag_ty.enumTagFieldIndex(union_obj.tag, target).?;
+ const index = union_ty.tag_ty.enumTagFieldIndex(union_obj.tag, dg.module).?;
const field_ty = ty.unionFields().values()[index].ty;
const field_name = ty.unionFields().keys()[index];
if (field_ty.hasRuntimeBits()) {
@@ -889,7 +889,7 @@ pub const DeclGen = struct {
try w.writeAll("void");
}
try w.writeAll(" ");
- try dg.renderDeclName(w, dg.decl);
+ try dg.renderDeclName(w, dg.decl_index);
try w.writeAll("(");
const param_len = dg.decl.ty.fnParamLen();
@@ -927,8 +927,7 @@ pub const DeclGen = struct {
try bw.writeAll(" (*");
const name_start = buffer.items.len;
- const target = dg.module.getTarget();
- try bw.print("zig_F_{s})(", .{typeToCIdentifier(t, target)});
+ try bw.print("zig_F_{s})(", .{typeToCIdentifier(t, dg.module)});
const name_end = buffer.items.len - 2;
const param_len = fn_info.param_types.len;
@@ -982,11 +981,10 @@ pub const DeclGen = struct {
try bw.writeAll("; size_t len; } ");
const name_index = buffer.items.len;
- const target = dg.module.getTarget();
if (t.isConstPtr()) {
- try bw.print("zig_L_{s}", .{typeToCIdentifier(child_type, target)});
+ try bw.print("zig_L_{s}", .{typeToCIdentifier(child_type, dg.module)});
} else {
- try bw.print("zig_M_{s}", .{typeToCIdentifier(child_type, target)});
+ try bw.print("zig_M_{s}", .{typeToCIdentifier(child_type, dg.module)});
}
if (ptr_sentinel) |s| {
try bw.writeAll("_s_");
@@ -1009,7 +1007,7 @@ pub const DeclGen = struct {
fn renderStructTypedef(dg: *DeclGen, t: Type) error{ OutOfMemory, AnalysisFail }![]const u8 {
const struct_obj = t.castTag(.@"struct").?.data; // Handle 0 bit types elsewhere.
- const fqn = try struct_obj.getFullyQualifiedName(dg.typedefs.allocator);
+ const fqn = try struct_obj.getFullyQualifiedName(dg.module);
defer dg.typedefs.allocator.free(fqn);
var buffer = std.ArrayList(u8).init(dg.typedefs.allocator);
@@ -1072,8 +1070,7 @@ pub const DeclGen = struct {
try buffer.appendSlice("} ");
const name_start = buffer.items.len;
- const target = dg.module.getTarget();
- try writer.print("zig_T_{};\n", .{typeToCIdentifier(t, target)});
+ try writer.print("zig_T_{};\n", .{typeToCIdentifier(t, dg.module)});
const rendered = buffer.toOwnedSlice();
errdefer dg.typedefs.allocator.free(rendered);
@@ -1090,7 +1087,7 @@ pub const DeclGen = struct {
fn renderUnionTypedef(dg: *DeclGen, t: Type) error{ OutOfMemory, AnalysisFail }![]const u8 {
const union_ty = t.cast(Type.Payload.Union).?.data;
- const fqn = try union_ty.getFullyQualifiedName(dg.typedefs.allocator);
+ const fqn = try union_ty.getFullyQualifiedName(dg.module);
defer dg.typedefs.allocator.free(fqn);
const target = dg.module.getTarget();
@@ -1157,7 +1154,6 @@ pub const DeclGen = struct {
try dg.renderTypeAndName(bw, child_type, payload_name, .Mut, 0);
try bw.writeAll("; uint16_t error; } ");
const name_index = buffer.items.len;
- const target = dg.module.getTarget();
if (err_set_type.castTag(.error_set_inferred)) |inf_err_set_payload| {
const func = inf_err_set_payload.data.func;
try bw.writeAll("zig_E_");
@@ -1165,7 +1161,7 @@ pub const DeclGen = struct {
try bw.writeAll(";\n");
} else {
try bw.print("zig_E_{s}_{s};\n", .{
- typeToCIdentifier(err_set_type, target), typeToCIdentifier(child_type, target),
+ typeToCIdentifier(err_set_type, dg.module), typeToCIdentifier(child_type, dg.module),
});
}
@@ -1195,8 +1191,7 @@ pub const DeclGen = struct {
try dg.renderType(bw, elem_type);
const name_start = buffer.items.len + 1;
- const target = dg.module.getTarget();
- try bw.print(" zig_A_{s}_{d}", .{ typeToCIdentifier(elem_type, target), c_len });
+ try bw.print(" zig_A_{s}_{d}", .{ typeToCIdentifier(elem_type, dg.module), c_len });
const name_end = buffer.items.len;
try bw.print("[{d}];\n", .{c_len});
@@ -1224,8 +1219,7 @@ pub const DeclGen = struct {
try dg.renderTypeAndName(bw, child_type, payload_name, .Mut, 0);
try bw.writeAll("; bool is_null; } ");
const name_index = buffer.items.len;
- const target = dg.module.getTarget();
- try bw.print("zig_Q_{s};\n", .{typeToCIdentifier(child_type, target)});
+ try bw.print("zig_Q_{s};\n", .{typeToCIdentifier(child_type, dg.module)});
const rendered = buffer.toOwnedSlice();
errdefer dg.typedefs.allocator.free(rendered);
@@ -1535,16 +1529,17 @@ pub const DeclGen = struct {
}
}
- fn renderDeclName(dg: DeclGen, writer: anytype, decl: *Decl) !void {
- decl.markAlive();
+ fn renderDeclName(dg: DeclGen, writer: anytype, decl_index: Decl.Index) !void {
+ const decl = dg.module.declPtr(decl_index);
+ dg.module.markDeclAlive(decl);
- if (dg.module.decl_exports.get(decl)) |exports| {
+ if (dg.module.decl_exports.get(decl_index)) |exports| {
return writer.writeAll(exports[0].options.name);
} else if (decl.val.tag() == .extern_fn) {
return writer.writeAll(mem.sliceTo(decl.name, 0));
} else {
const gpa = dg.module.gpa;
- const name = try decl.getFullyQualifiedName(gpa);
+ const name = try decl.getFullyQualifiedName(dg.module);
defer gpa.free(name);
return writer.print("{ }", .{fmtIdent(name)});
}
@@ -1616,7 +1611,11 @@ pub fn genDecl(o: *Object) !void {
try fwd_decl_writer.writeAll("zig_threadlocal ");
}
- const decl_c_value: CValue = if (is_global) .{ .bytes = mem.span(o.dg.decl.name) } else .{ .decl = o.dg.decl };
+ const decl_c_value: CValue = if (is_global) .{
+ .bytes = mem.span(o.dg.decl.name),
+ } else .{
+ .decl = o.dg.decl_index,
+ };
try o.dg.renderTypeAndName(fwd_decl_writer, o.dg.decl.ty, decl_c_value, .Mut, o.dg.decl.@"align");
try fwd_decl_writer.writeAll(";\n");
@@ -1641,7 +1640,7 @@ pub fn genDecl(o: *Object) !void {
// TODO ask the Decl if it is const
// https://github.com/ziglang/zig/issues/7582
- const decl_c_value: CValue = .{ .decl = o.dg.decl };
+ const decl_c_value: CValue = .{ .decl = o.dg.decl_index };
try o.dg.renderTypeAndName(writer, tv.ty, decl_c_value, .Mut, o.dg.decl.@"align");
try writer.writeAll(" = ");
@@ -2234,13 +2233,12 @@ fn airStore(f: *Function, inst: Air.Inst.Index) !CValue {
if (src_val_is_undefined)
return try airStoreUndefined(f, dest_ptr);
- const target = f.object.dg.module.getTarget();
const writer = f.object.writer();
if (lhs_child_type.zigTypeTag() == .Array) {
// 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).
const rhs_type = f.air.typeOf(bin_op.rhs);
- assert(rhs_type.eql(lhs_child_type, target));
+ assert(rhs_type.eql(lhs_child_type, f.object.dg.module));
// If the source is a constant, writeCValue will emit a brace initialization
// so work around this by initializing into new local.
@@ -2780,7 +2778,8 @@ fn airDbgInline(f: *Function, inst: Air.Inst.Index) !CValue {
const ty_pl = f.air.instructions.items(.data)[inst].ty_pl;
const writer = f.object.writer();
const function = f.air.values[ty_pl.payload].castTag(.function).?.data;
- try writer.print("/* dbg func:{s} */\n", .{function.owner_decl.name});
+ const mod = f.object.dg.module;
+ try writer.print("/* dbg func:{s} */\n", .{mod.declPtr(function.owner_decl).name});
return CValue.none;
}
diff --git a/src/codegen/llvm.zig b/src/codegen/llvm.zig
index cdb9addcff..ba637cb99e 100644
--- a/src/codegen/llvm.zig
+++ b/src/codegen/llvm.zig
@@ -161,6 +161,7 @@ pub fn targetTriple(allocator: Allocator, target: std.Target) ![:0]u8 {
pub const Object = struct {
gpa: Allocator,
+ module: *Module,
llvm_module: *const llvm.Module,
di_builder: ?*llvm.DIBuilder,
/// One of these mappings:
@@ -181,7 +182,7 @@ pub const Object = struct {
/// version of the name and incorrectly get function not found in the llvm module.
/// * it works for functions not all globals.
/// Therefore, this table keeps track of the mapping.
- decl_map: std.AutoHashMapUnmanaged(*const Module.Decl, *const llvm.Value),
+ decl_map: std.AutoHashMapUnmanaged(Module.Decl.Index, *const llvm.Value),
/// Maps Zig types to LLVM types. The table memory itself is backed by the GPA of
/// the compiler, but the Type/Value memory here is backed by `type_map_arena`.
/// TODO we need to remove entries from this map in response to incremental compilation
@@ -340,6 +341,7 @@ pub const Object = struct {
return Object{
.gpa = gpa,
+ .module = options.module.?,
.llvm_module = llvm_module,
.di_map = .{},
.di_builder = opt_di_builder,
@@ -568,18 +570,20 @@ pub const Object = struct {
air: Air,
liveness: Liveness,
) !void {
- const decl = func.owner_decl;
+ const decl_index = func.owner_decl;
+ const decl = module.declPtr(decl_index);
var dg: DeclGen = .{
.context = o.context,
.object = o,
.module = module,
+ .decl_index = decl_index,
.decl = decl,
.err_msg = null,
.gpa = module.gpa,
};
- const llvm_func = try dg.resolveLlvmFunction(decl);
+ const llvm_func = try dg.resolveLlvmFunction(decl_index);
if (module.align_stack_fns.get(func)) |align_info| {
dg.addFnAttrInt(llvm_func, "alignstack", align_info.alignment);
@@ -632,7 +636,7 @@ pub const Object = struct {
const line_number = decl.src_line + 1;
const is_internal_linkage = decl.val.tag() != .extern_fn and
- !dg.module.decl_exports.contains(decl);
+ !dg.module.decl_exports.contains(decl_index);
const noret_bit: c_uint = if (fn_info.return_type.isNoReturn())
llvm.DIFlags.NoReturn
else
@@ -684,48 +688,51 @@ pub const Object = struct {
fg.genBody(air.getMainBody()) catch |err| switch (err) {
error.CodegenFail => {
decl.analysis = .codegen_failure;
- try module.failed_decls.put(module.gpa, decl, dg.err_msg.?);
+ try module.failed_decls.put(module.gpa, decl_index, dg.err_msg.?);
dg.err_msg = null;
return;
},
else => |e| return e,
};
- const decl_exports = module.decl_exports.get(decl) orelse &[0]*Module.Export{};
- try o.updateDeclExports(module, decl, decl_exports);
+ const decl_exports = module.decl_exports.get(decl_index) orelse &[0]*Module.Export{};
+ try o.updateDeclExports(module, decl_index, decl_exports);
}
- pub fn updateDecl(self: *Object, module: *Module, decl: *Module.Decl) !void {
+ pub fn updateDecl(self: *Object, module: *Module, decl_index: Module.Decl.Index) !void {
+ const decl = module.declPtr(decl_index);
var dg: DeclGen = .{
.context = self.context,
.object = self,
.module = module,
.decl = decl,
+ .decl_index = decl_index,
.err_msg = null,
.gpa = module.gpa,
};
dg.genDecl() catch |err| switch (err) {
error.CodegenFail => {
decl.analysis = .codegen_failure;
- try module.failed_decls.put(module.gpa, decl, dg.err_msg.?);
+ try module.failed_decls.put(module.gpa, decl_index, dg.err_msg.?);
dg.err_msg = null;
return;
},
else => |e| return e,
};
- const decl_exports = module.decl_exports.get(decl) orelse &[0]*Module.Export{};
- try self.updateDeclExports(module, decl, decl_exports);
+ const decl_exports = module.decl_exports.get(decl_index) orelse &[0]*Module.Export{};
+ try self.updateDeclExports(module, decl_index, decl_exports);
}
pub fn updateDeclExports(
self: *Object,
- module: *const Module,
- decl: *const Module.Decl,
+ module: *Module,
+ decl_index: Module.Decl.Index,
exports: []const *Module.Export,
) !void {
// If the module does not already have the function, we ignore this function call
// because we call `updateDeclExports` at the end of `updateFunc` and `updateDecl`.
- const llvm_global = self.decl_map.get(decl) orelse return;
+ const llvm_global = self.decl_map.get(decl_index) orelse return;
+ const decl = module.declPtr(decl_index);
if (decl.isExtern()) {
llvm_global.setValueName(decl.name);
llvm_global.setUnnamedAddr(.False);
@@ -798,7 +805,7 @@ pub const Object = struct {
}
}
} else {
- const fqn = try decl.getFullyQualifiedName(module.gpa);
+ const fqn = try decl.getFullyQualifiedName(module);
defer module.gpa.free(fqn);
llvm_global.setValueName2(fqn.ptr, fqn.len);
llvm_global.setLinkage(.Internal);
@@ -814,8 +821,8 @@ pub const Object = struct {
}
}
- pub fn freeDecl(self: *Object, decl: *Module.Decl) void {
- const llvm_value = self.decl_map.get(decl) orelse return;
+ pub fn freeDecl(self: *Object, decl_index: Module.Decl.Index) void {
+ const llvm_value = self.decl_map.get(decl_index) orelse return;
llvm_value.deleteGlobal();
}
@@ -847,7 +854,7 @@ pub const Object = struct {
const gpa = o.gpa;
// Be careful not to reference this `gop` variable after any recursive calls
// to `lowerDebugType`.
- const gop = try o.di_type_map.getOrPutContext(gpa, ty, .{ .target = o.target });
+ const gop = try o.di_type_map.getOrPutContext(gpa, ty, .{ .mod = o.module });
if (gop.found_existing) {
const annotated = gop.value_ptr.*;
const di_type = annotated.toDIType();
@@ -860,7 +867,7 @@ pub const Object = struct {
};
return o.lowerDebugTypeImpl(entry, resolve, di_type);
}
- errdefer assert(o.di_type_map.orderedRemoveContext(ty, .{ .target = o.target }));
+ errdefer assert(o.di_type_map.orderedRemoveContext(ty, .{ .mod = o.module }));
// The Type memory is ephemeral; since we want to store a longer-lived
// reference, we need to copy it here.
gop.key_ptr.* = try ty.copy(o.type_map_arena.allocator());
@@ -891,7 +898,7 @@ pub const Object = struct {
.Int => {
const info = ty.intInfo(target);
assert(info.bits != 0);
- const name = try ty.nameAlloc(gpa, target);
+ const name = try ty.nameAlloc(gpa, o.module);
defer gpa.free(name);
const dwarf_encoding: c_uint = switch (info.signedness) {
.signed => DW.ATE.signed,
@@ -902,13 +909,14 @@ pub const Object = struct {
return di_type;
},
.Enum => {
- const owner_decl = ty.getOwnerDecl();
+ const owner_decl_index = ty.getOwnerDecl();
+ const owner_decl = o.module.declPtr(owner_decl_index);
if (!ty.hasRuntimeBitsIgnoreComptime()) {
- const enum_di_ty = try o.makeEmptyNamespaceDIType(owner_decl);
+ const enum_di_ty = try o.makeEmptyNamespaceDIType(owner_decl_index);
// The recursive call to `lowerDebugType` via `makeEmptyNamespaceDIType`
// means we can't use `gop` anymore.
- try o.di_type_map.putContext(gpa, ty, AnnotatedDITypePtr.initFull(enum_di_ty), .{ .target = o.target });
+ try o.di_type_map.putContext(gpa, ty, AnnotatedDITypePtr.initFull(enum_di_ty), .{ .mod = o.module });
return enum_di_ty;
}
@@ -938,7 +946,7 @@ pub const Object = struct {
const di_file = try o.getDIFile(gpa, owner_decl.src_namespace.file_scope);
const di_scope = try o.namespaceToDebugScope(owner_decl.src_namespace);
- const name = try ty.nameAlloc(gpa, target);
+ const name = try ty.nameAlloc(gpa, o.module);
defer gpa.free(name);
var buffer: Type.Payload.Bits = undefined;
const int_ty = ty.intTagType(&buffer);
@@ -956,12 +964,12 @@ pub const Object = struct {
"",
);
// The recursive call to `lowerDebugType` means we can't use `gop` anymore.
- try o.di_type_map.putContext(gpa, ty, AnnotatedDITypePtr.initFull(enum_di_ty), .{ .target = o.target });
+ try o.di_type_map.putContext(gpa, ty, AnnotatedDITypePtr.initFull(enum_di_ty), .{ .mod = o.module });
return enum_di_ty;
},
.Float => {
const bits = ty.floatBits(target);
- const name = try ty.nameAlloc(gpa, target);
+ const name = try ty.nameAlloc(gpa, o.module);
defer gpa.free(name);
const di_type = dib.createBasicType(name, bits, DW.ATE.float);
gop.value_ptr.* = AnnotatedDITypePtr.initFull(di_type);
@@ -1009,7 +1017,7 @@ pub const Object = struct {
const bland_ptr_ty = Type.initPayload(&payload.base);
const ptr_di_ty = try o.lowerDebugType(bland_ptr_ty, resolve);
// The recursive call to `lowerDebugType` means we can't use `gop` anymore.
- try o.di_type_map.putContext(gpa, ty, AnnotatedDITypePtr.init(ptr_di_ty, resolve), .{ .target = o.target });
+ try o.di_type_map.putContext(gpa, ty, AnnotatedDITypePtr.init(ptr_di_ty, resolve), .{ .mod = o.module });
return ptr_di_ty;
}
@@ -1018,7 +1026,7 @@ pub const Object = struct {
const ptr_ty = ty.slicePtrFieldType(&buf);
const len_ty = Type.usize;
- const name = try ty.nameAlloc(gpa, target);
+ const name = try ty.nameAlloc(gpa, o.module);
defer gpa.free(name);
const di_file: ?*llvm.DIFile = null;
const line = 0;
@@ -1089,12 +1097,12 @@ pub const Object = struct {
);
dib.replaceTemporary(fwd_decl, full_di_ty);
// The recursive call to `lowerDebugType` means we can't use `gop` anymore.
- try o.di_type_map.putContext(gpa, ty, AnnotatedDITypePtr.initFull(full_di_ty), .{ .target = o.target });
+ try o.di_type_map.putContext(gpa, ty, AnnotatedDITypePtr.initFull(full_di_ty), .{ .mod = o.module });
return full_di_ty;
}
const elem_di_ty = try o.lowerDebugType(ptr_info.pointee_type, .fwd);
- const name = try ty.nameAlloc(gpa, target);
+ const name = try ty.nameAlloc(gpa, o.module);
defer gpa.free(name);
const ptr_di_ty = dib.createPointerType(
elem_di_ty,
@@ -1103,7 +1111,7 @@ pub const Object = struct {
name,
);
// The recursive call to `lowerDebugType` means we can't use `gop` anymore.
- try o.di_type_map.putContext(gpa, ty, AnnotatedDITypePtr.initFull(ptr_di_ty), .{ .target = o.target });
+ try o.di_type_map.putContext(gpa, ty, AnnotatedDITypePtr.initFull(ptr_di_ty), .{ .mod = o.module });
return ptr_di_ty;
},
.Opaque => {
@@ -1112,9 +1120,10 @@ pub const Object = struct {
gop.value_ptr.* = AnnotatedDITypePtr.initFull(di_ty);
return di_ty;
}
- const name = try ty.nameAlloc(gpa, target);
+ const name = try ty.nameAlloc(gpa, o.module);
defer gpa.free(name);
- const owner_decl = ty.getOwnerDecl();
+ const owner_decl_index = ty.getOwnerDecl();
+ const owner_decl = o.module.declPtr(owner_decl_index);
const opaque_di_ty = dib.createForwardDeclType(
DW.TAG.structure_type,
name,
@@ -1124,7 +1133,7 @@ pub const Object = struct {
);
// The recursive call to `lowerDebugType` va `namespaceToDebugScope`
// means we can't use `gop` anymore.
- try o.di_type_map.putContext(gpa, ty, AnnotatedDITypePtr.initFull(opaque_di_ty), .{ .target = o.target });
+ try o.di_type_map.putContext(gpa, ty, AnnotatedDITypePtr.initFull(opaque_di_ty), .{ .mod = o.module });
return opaque_di_ty;
},
.Array => {
@@ -1135,7 +1144,7 @@ pub const Object = struct {
@intCast(c_int, ty.arrayLen()),
);
// The recursive call to `lowerDebugType` means we can't use `gop` anymore.
- try o.di_type_map.putContext(gpa, ty, AnnotatedDITypePtr.initFull(array_di_ty), .{ .target = o.target });
+ try o.di_type_map.putContext(gpa, ty, AnnotatedDITypePtr.initFull(array_di_ty), .{ .mod = o.module });
return array_di_ty;
},
.Vector => {
@@ -1146,11 +1155,11 @@ pub const Object = struct {
ty.vectorLen(),
);
// The recursive call to `lowerDebugType` means we can't use `gop` anymore.
- try o.di_type_map.putContext(gpa, ty, AnnotatedDITypePtr.initFull(vector_di_ty), .{ .target = o.target });
+ try o.di_type_map.putContext(gpa, ty, AnnotatedDITypePtr.initFull(vector_di_ty), .{ .mod = o.module });
return vector_di_ty;
},
.Optional => {
- const name = try ty.nameAlloc(gpa, target);
+ const name = try ty.nameAlloc(gpa, o.module);
defer gpa.free(name);
var buf: Type.Payload.ElemType = undefined;
const child_ty = ty.optionalChild(&buf);
@@ -1162,7 +1171,7 @@ pub const Object = struct {
if (ty.isPtrLikeOptional()) {
const ptr_di_ty = try o.lowerDebugType(child_ty, resolve);
// The recursive call to `lowerDebugType` means we can't use `gop` anymore.
- try o.di_type_map.putContext(gpa, ty, AnnotatedDITypePtr.initFull(ptr_di_ty), .{ .target = o.target });
+ try o.di_type_map.putContext(gpa, ty, AnnotatedDITypePtr.initFull(ptr_di_ty), .{ .mod = o.module });
return ptr_di_ty;
}
@@ -1235,7 +1244,7 @@ pub const Object = struct {
);
dib.replaceTemporary(fwd_decl, full_di_ty);
// The recursive call to `lowerDebugType` means we can't use `gop` anymore.
- try o.di_type_map.putContext(gpa, ty, AnnotatedDITypePtr.initFull(full_di_ty), .{ .target = o.target });
+ try o.di_type_map.putContext(gpa, ty, AnnotatedDITypePtr.initFull(full_di_ty), .{ .mod = o.module });
return full_di_ty;
},
.ErrorUnion => {
@@ -1244,10 +1253,10 @@ pub const Object = struct {
if (!payload_ty.hasRuntimeBitsIgnoreComptime()) {
const err_set_di_ty = try o.lowerDebugType(err_set_ty, .full);
// The recursive call to `lowerDebugType` means we can't use `gop` anymore.
- try o.di_type_map.putContext(gpa, ty, AnnotatedDITypePtr.initFull(err_set_di_ty), .{ .target = o.target });
+ try o.di_type_map.putContext(gpa, ty, AnnotatedDITypePtr.initFull(err_set_di_ty), .{ .mod = o.module });
return err_set_di_ty;
}
- const name = try ty.nameAlloc(gpa, target);
+ const name = try ty.nameAlloc(gpa, o.module);
defer gpa.free(name);
const di_file: ?*llvm.DIFile = null;
const line = 0;
@@ -1332,7 +1341,7 @@ pub const Object = struct {
);
dib.replaceTemporary(fwd_decl, full_di_ty);
// The recursive call to `lowerDebugType` means we can't use `gop` anymore.
- try o.di_type_map.putContext(gpa, ty, AnnotatedDITypePtr.initFull(full_di_ty), .{ .target = o.target });
+ try o.di_type_map.putContext(gpa, ty, AnnotatedDITypePtr.initFull(full_di_ty), .{ .mod = o.module });
return full_di_ty;
},
.ErrorSet => {
@@ -1344,7 +1353,7 @@ pub const Object = struct {
},
.Struct => {
const compile_unit_scope = o.di_compile_unit.?.toScope();
- const name = try ty.nameAlloc(gpa, target);
+ const name = try ty.nameAlloc(gpa, o.module);
defer gpa.free(name);
if (ty.castTag(.@"struct")) |payload| {
@@ -1431,7 +1440,7 @@ pub const Object = struct {
);
dib.replaceTemporary(fwd_decl, full_di_ty);
// The recursive call to `lowerDebugType` means we can't use `gop` anymore.
- try o.di_type_map.putContext(gpa, ty, AnnotatedDITypePtr.initFull(full_di_ty), .{ .target = o.target });
+ try o.di_type_map.putContext(gpa, ty, AnnotatedDITypePtr.initFull(full_di_ty), .{ .mod = o.module });
return full_di_ty;
}
@@ -1445,23 +1454,23 @@ pub const Object = struct {
// into. Therefore we can satisfy this by making an empty namespace,
// rather than changing the frontend to unnecessarily resolve the
// struct field types.
- const owner_decl = ty.getOwnerDecl();
- const struct_di_ty = try o.makeEmptyNamespaceDIType(owner_decl);
+ const owner_decl_index = ty.getOwnerDecl();
+ const struct_di_ty = try o.makeEmptyNamespaceDIType(owner_decl_index);
dib.replaceTemporary(fwd_decl, struct_di_ty);
// The recursive call to `lowerDebugType` via `makeEmptyNamespaceDIType`
// means we can't use `gop` anymore.
- try o.di_type_map.putContext(gpa, ty, AnnotatedDITypePtr.initFull(struct_di_ty), .{ .target = o.target });
+ try o.di_type_map.putContext(gpa, ty, AnnotatedDITypePtr.initFull(struct_di_ty), .{ .mod = o.module });
return struct_di_ty;
}
}
if (!ty.hasRuntimeBitsIgnoreComptime()) {
- const owner_decl = ty.getOwnerDecl();
- const struct_di_ty = try o.makeEmptyNamespaceDIType(owner_decl);
+ const owner_decl_index = ty.getOwnerDecl();
+ const struct_di_ty = try o.makeEmptyNamespaceDIType(owner_decl_index);
dib.replaceTemporary(fwd_decl, struct_di_ty);
// The recursive call to `lowerDebugType` via `makeEmptyNamespaceDIType`
// means we can't use `gop` anymore.
- try o.di_type_map.putContext(gpa, ty, AnnotatedDITypePtr.initFull(struct_di_ty), .{ .target = o.target });
+ try o.di_type_map.putContext(gpa, ty, AnnotatedDITypePtr.initFull(struct_di_ty), .{ .mod = o.module });
return struct_di_ty;
}
@@ -1516,14 +1525,14 @@ pub const Object = struct {
);
dib.replaceTemporary(fwd_decl, full_di_ty);
// The recursive call to `lowerDebugType` means we can't use `gop` anymore.
- try o.di_type_map.putContext(gpa, ty, AnnotatedDITypePtr.initFull(full_di_ty), .{ .target = o.target });
+ try o.di_type_map.putContext(gpa, ty, AnnotatedDITypePtr.initFull(full_di_ty), .{ .mod = o.module });
return full_di_ty;
},
.Union => {
const compile_unit_scope = o.di_compile_unit.?.toScope();
- const owner_decl = ty.getOwnerDecl();
+ const owner_decl_index = ty.getOwnerDecl();
- const name = try ty.nameAlloc(gpa, target);
+ const name = try ty.nameAlloc(gpa, o.module);
defer gpa.free(name);
const fwd_decl = opt_fwd_decl orelse blk: {
@@ -1540,11 +1549,11 @@ pub const Object = struct {
};
if (!ty.hasRuntimeBitsIgnoreComptime()) {
- const union_di_ty = try o.makeEmptyNamespaceDIType(owner_decl);
+ const union_di_ty = try o.makeEmptyNamespaceDIType(owner_decl_index);
dib.replaceTemporary(fwd_decl, union_di_ty);
// The recursive call to `lowerDebugType` via `makeEmptyNamespaceDIType`
// means we can't use `gop` anymore.
- try o.di_type_map.putContext(gpa, ty, AnnotatedDITypePtr.initFull(union_di_ty), .{ .target = o.target });
+ try o.di_type_map.putContext(gpa, ty, AnnotatedDITypePtr.initFull(union_di_ty), .{ .mod = o.module });
return union_di_ty;
}
@@ -1572,7 +1581,7 @@ pub const Object = struct {
dib.replaceTemporary(fwd_decl, full_di_ty);
// The recursive call to `lowerDebugType` via `makeEmptyNamespaceDIType`
// means we can't use `gop` anymore.
- try o.di_type_map.putContext(gpa, ty, AnnotatedDITypePtr.initFull(full_di_ty), .{ .target = o.target });
+ try o.di_type_map.putContext(gpa, ty, AnnotatedDITypePtr.initFull(full_di_ty), .{ .mod = o.module });
return full_di_ty;
}
@@ -1626,7 +1635,7 @@ pub const Object = struct {
if (layout.tag_size == 0) {
dib.replaceTemporary(fwd_decl, union_di_ty);
// The recursive call to `lowerDebugType` means we can't use `gop` anymore.
- try o.di_type_map.putContext(gpa, ty, AnnotatedDITypePtr.initFull(union_di_ty), .{ .target = o.target });
+ try o.di_type_map.putContext(gpa, ty, AnnotatedDITypePtr.initFull(union_di_ty), .{ .mod = o.module });
return union_di_ty;
}
@@ -1685,7 +1694,7 @@ pub const Object = struct {
);
dib.replaceTemporary(fwd_decl, full_di_ty);
// The recursive call to `lowerDebugType` means we can't use `gop` anymore.
- try o.di_type_map.putContext(gpa, ty, AnnotatedDITypePtr.initFull(full_di_ty), .{ .target = o.target });
+ try o.di_type_map.putContext(gpa, ty, AnnotatedDITypePtr.initFull(full_di_ty), .{ .mod = o.module });
return full_di_ty;
},
.Fn => {
@@ -1733,7 +1742,7 @@ pub const Object = struct {
0,
);
// The recursive call to `lowerDebugType` means we can't use `gop` anymore.
- try o.di_type_map.putContext(gpa, ty, AnnotatedDITypePtr.initFull(fn_di_ty), .{ .target = o.target });
+ try o.di_type_map.putContext(gpa, ty, AnnotatedDITypePtr.initFull(fn_di_ty), .{ .mod = o.module });
return fn_di_ty;
},
.ComptimeInt => unreachable,
@@ -1762,7 +1771,8 @@ pub const Object = struct {
/// This is to be used instead of void for debug info types, to avoid tripping
/// Assertion `!isa<DIType>(Scope) && "shouldn't make a namespace scope for a type"'
/// when targeting CodeView (Windows).
- fn makeEmptyNamespaceDIType(o: *Object, decl: *const Module.Decl) !*llvm.DIType {
+ fn makeEmptyNamespaceDIType(o: *Object, decl_index: Module.Decl.Index) !*llvm.DIType {
+ const decl = o.module.declPtr(decl_index);
const fields: [0]*llvm.DIType = .{};
return o.di_builder.?.createStructType(
try o.namespaceToDebugScope(decl.src_namespace),
@@ -1787,6 +1797,7 @@ pub const DeclGen = struct {
object: *Object,
module: *Module,
decl: *Module.Decl,
+ decl_index: Module.Decl.Index,
gpa: Allocator,
err_msg: ?*Module.ErrorMsg,
@@ -1804,6 +1815,7 @@ pub const DeclGen = struct {
fn genDecl(dg: *DeclGen) !void {
const decl = dg.decl;
+ const decl_index = dg.decl_index;
assert(decl.has_tv);
log.debug("gen: {s} type: {}, value: {}", .{
@@ -1817,7 +1829,7 @@ pub const DeclGen = struct {
_ = try dg.resolveLlvmFunction(extern_fn.data.owner_decl);
} else {
const target = dg.module.getTarget();
- var global = try dg.resolveGlobalDecl(decl);
+ var global = try dg.resolveGlobalDecl(decl_index);
global.setAlignment(decl.getAlignment(target));
assert(decl.has_tv);
const init_val = if (decl.val.castTag(.variable)) |payload| init_val: {
@@ -1858,7 +1870,7 @@ pub const DeclGen = struct {
// old uses.
const new_global_ptr = new_global.constBitCast(global.typeOf());
global.replaceAllUsesWith(new_global_ptr);
- dg.object.decl_map.putAssumeCapacity(decl, new_global);
+ dg.object.decl_map.putAssumeCapacity(decl_index, new_global);
new_global.takeName(global);
global.deleteGlobal();
global = new_global;
@@ -1869,7 +1881,7 @@ pub const DeclGen = struct {
const di_file = try dg.object.getDIFile(dg.gpa, decl.src_namespace.file_scope);
const line_number = decl.src_line + 1;
- const is_internal_linkage = !dg.module.decl_exports.contains(decl);
+ const is_internal_linkage = !dg.module.decl_exports.contains(decl_index);
const di_global = dib.createGlobalVariable(
di_file.toScope(),
decl.name,
@@ -1888,12 +1900,10 @@ pub const DeclGen = struct {
/// If the llvm function does not exist, create it.
/// Note that this can be called before the function's semantic analysis has
/// completed, so if any attributes rely on that, they must be done in updateFunc, not here.
- fn resolveLlvmFunction(dg: *DeclGen, decl: *Module.Decl) !*const llvm.Value {
- return dg.resolveLlvmFunctionExtra(decl, decl.ty);
- }
-
- fn resolveLlvmFunctionExtra(dg: *DeclGen, decl: *Module.Decl, zig_fn_type: Type) !*const llvm.Value {
- const gop = try dg.object.decl_map.getOrPut(dg.gpa, decl);
+ fn resolveLlvmFunction(dg: *DeclGen, decl_index: Module.Decl.Index) !*const llvm.Value {
+ const decl = dg.module.declPtr(decl_index);
+ const zig_fn_type = decl.ty;
+ const gop = try dg.object.decl_map.getOrPut(dg.gpa, decl_index);
if (gop.found_existing) return gop.value_ptr.*;
assert(decl.has_tv);
@@ -1903,7 +1913,7 @@ pub const DeclGen = struct {
const fn_type = try dg.llvmType(zig_fn_type);
- const fqn = try decl.getFullyQualifiedName(dg.gpa);
+ const fqn = try decl.getFullyQualifiedName(dg.module);
defer dg.gpa.free(fqn);
const llvm_addrspace = dg.llvmAddressSpace(decl.@"addrspace");
@@ -1996,12 +2006,13 @@ pub const DeclGen = struct {
// TODO add target-cpu and target-features fn attributes
}
- fn resolveGlobalDecl(dg: *DeclGen, decl: *Module.Decl) Error!*const llvm.Value {
- const gop = try dg.object.decl_map.getOrPut(dg.gpa, decl);
+ fn resolveGlobalDecl(dg: *DeclGen, decl_index: Module.Decl.Index) Error!*const llvm.Value {
+ const gop = try dg.object.decl_map.getOrPut(dg.gpa, decl_index);
if (gop.found_existing) return gop.value_ptr.*;
- errdefer assert(dg.object.decl_map.remove(decl));
+ errdefer assert(dg.object.decl_map.remove(decl_index));
- const fqn = try decl.getFullyQualifiedName(dg.gpa);
+ const decl = dg.module.declPtr(decl_index);
+ const fqn = try decl.getFullyQualifiedName(dg.module);
defer dg.gpa.free(fqn);
const llvm_type = try dg.llvmType(decl.ty);
@@ -2122,7 +2133,7 @@ pub const DeclGen = struct {
},
.Opaque => switch (t.tag()) {
.@"opaque" => {
- const gop = try dg.object.type_map.getOrPutContext(gpa, t, .{ .target = target });
+ const gop = try dg.object.type_map.getOrPutContext(gpa, t, .{ .mod = dg.module });
if (gop.found_existing) return gop.value_ptr.*;
// The Type memory is ephemeral; since we want to store a longer-lived
@@ -2130,7 +2141,7 @@ pub const DeclGen = struct {
gop.key_ptr.* = try t.copy(dg.object.type_map_arena.allocator());
const opaque_obj = t.castTag(.@"opaque").?.data;
- const name = try opaque_obj.getFullyQualifiedName(gpa);
+ const name = try opaque_obj.getFullyQualifiedName(dg.module);
defer gpa.free(name);
const llvm_struct_ty = dg.context.structCreateNamed(name);
@@ -2191,7 +2202,7 @@ pub const DeclGen = struct {
return dg.context.intType(16);
},
.Struct => {
- const gop = try dg.object.type_map.getOrPutContext(gpa, t, .{ .target = target });
+ const gop = try dg.object.type_map.getOrPutContext(gpa, t, .{ .mod = dg.module });
if (gop.found_existing) return gop.value_ptr.*;
// The Type memory is ephemeral; since we want to store a longer-lived
@@ -2260,7 +2271,7 @@ pub const DeclGen = struct {
return int_llvm_ty;
}
- const name = try struct_obj.getFullyQualifiedName(gpa);
+ const name = try struct_obj.getFullyQualifiedName(dg.module);
defer gpa.free(name);
const llvm_struct_ty = dg.context.structCreateNamed(name);
@@ -2314,7 +2325,7 @@ pub const DeclGen = struct {
return llvm_struct_ty;
},
.Union => {
- const gop = try dg.object.type_map.getOrPutContext(gpa, t, .{ .target = target });
+ const gop = try dg.object.type_map.getOrPutContext(gpa, t, .{ .mod = dg.module });
if (gop.found_existing) return gop.value_ptr.*;
// The Type memory is ephemeral; since we want to store a longer-lived
@@ -2330,7 +2341,7 @@ pub const DeclGen = struct {
return enum_tag_llvm_ty;
}
- const name = try union_obj.getFullyQualifiedName(gpa);
+ const name = try union_obj.getFullyQualifiedName(dg.module);
defer gpa.free(name);
const llvm_union_ty = dg.context.structCreateNamed(name);
@@ -2439,7 +2450,7 @@ pub const DeclGen = struct {
// TODO this duplicates code with Pointer but they should share the handling
// of the tv.val.tag() and then Int should do extra constPtrToInt on top
.Int => switch (tv.val.tag()) {
- .decl_ref_mut => return lowerDeclRefValue(dg, tv, tv.val.castTag(.decl_ref_mut).?.data.decl),
+ .decl_ref_mut => return lowerDeclRefValue(dg, tv, tv.val.castTag(.decl_ref_mut).?.data.decl_index),
.decl_ref => return lowerDeclRefValue(dg, tv, tv.val.castTag(.decl_ref).?.data),
else => {
var bigint_space: Value.BigIntSpace = undefined;
@@ -2524,12 +2535,13 @@ pub const DeclGen = struct {
}
},
.Pointer => switch (tv.val.tag()) {
- .decl_ref_mut => return lowerDeclRefValue(dg, tv, tv.val.castTag(.decl_ref_mut).?.data.decl),
+ .decl_ref_mut => return lowerDeclRefValue(dg, tv, tv.val.castTag(.decl_ref_mut).?.data.decl_index),
.decl_ref => return lowerDeclRefValue(dg, tv, tv.val.castTag(.decl_ref).?.data),
.variable => {
- const decl = tv.val.castTag(.variable).?.data.owner_decl;
- decl.markAlive();
- const val = try dg.resolveGlobalDecl(decl);
+ const decl_index = tv.val.castTag(.variable).?.data.owner_decl;
+ const decl = dg.module.declPtr(decl_index);
+ dg.module.markDeclAlive(decl);
+ const val = try dg.resolveGlobalDecl(decl_index);
const llvm_var_type = try dg.llvmType(tv.ty);
const llvm_addrspace = dg.llvmAddressSpace(decl.@"addrspace");
const llvm_type = llvm_var_type.pointerType(llvm_addrspace);
@@ -2683,13 +2695,14 @@ pub const DeclGen = struct {
return dg.context.constStruct(&fields, fields.len, .False);
},
.Fn => {
- const fn_decl = switch (tv.val.tag()) {
+ const fn_decl_index = switch (tv.val.tag()) {
.extern_fn => tv.val.castTag(.extern_fn).?.data.owner_decl,
.function => tv.val.castTag(.function).?.data.owner_decl,
else => unreachable,
};
- fn_decl.markAlive();
- return dg.resolveLlvmFunction(fn_decl);
+ const fn_decl = dg.module.declPtr(fn_decl_index);
+ dg.module.markDeclAlive(fn_decl);
+ return dg.resolveLlvmFunction(fn_decl_index);
},
.ErrorSet => {
const llvm_ty = try dg.llvmType(tv.ty);
@@ -2911,7 +2924,7 @@ pub const DeclGen = struct {
});
}
const union_obj = tv.ty.cast(Type.Payload.Union).?.data;
- const field_index = union_obj.tag_ty.enumTagFieldIndex(tag_and_val.tag, target).?;
+ const field_index = union_obj.tag_ty.enumTagFieldIndex(tag_and_val.tag, dg.module).?;
assert(union_obj.haveFieldTypes());
const field_ty = union_obj.fields.values()[field_index].ty;
const payload = p: {
@@ -3049,17 +3062,22 @@ pub const DeclGen = struct {
llvm_ptr: *const llvm.Value,
};
- fn lowerParentPtrDecl(dg: *DeclGen, ptr_val: Value, decl: *Module.Decl, ptr_child_ty: Type) Error!*const llvm.Value {
- decl.markAlive();
+ fn lowerParentPtrDecl(
+ dg: *DeclGen,
+ ptr_val: Value,
+ decl_index: Module.Decl.Index,
+ ptr_child_ty: Type,
+ ) Error!*const llvm.Value {
+ const decl = dg.module.declPtr(decl_index);
+ dg.module.markDeclAlive(decl);
var ptr_ty_payload: Type.Payload.ElemType = .{
.base = .{ .tag = .single_mut_pointer },
.data = decl.ty,
};
const ptr_ty = Type.initPayload(&ptr_ty_payload.base);
- const llvm_ptr = try dg.lowerDeclRefValue(.{ .ty = ptr_ty, .val = ptr_val }, decl);
+ const llvm_ptr = try dg.lowerDeclRefValue(.{ .ty = ptr_ty, .val = ptr_val }, decl_index);
- const target = dg.module.getTarget();
- if (ptr_child_ty.eql(decl.ty, target)) {
+ if (ptr_child_ty.eql(decl.ty, dg.module)) {
return llvm_ptr;
} else {
return llvm_ptr.constBitCast((try dg.llvmType(ptr_child_ty)).pointerType(0));
@@ -3071,7 +3089,7 @@ pub const DeclGen = struct {
var bitcast_needed: bool = undefined;
const llvm_ptr = switch (ptr_val.tag()) {
.decl_ref_mut => {
- const decl = ptr_val.castTag(.decl_ref_mut).?.data.decl;
+ const decl = ptr_val.castTag(.decl_ref_mut).?.data.decl_index;
return dg.lowerParentPtrDecl(ptr_val, decl, ptr_child_ty);
},
.decl_ref => {
@@ -3123,7 +3141,7 @@ pub const DeclGen = struct {
},
.Struct => {
const field_ty = parent_ty.structFieldType(field_index);
- bitcast_needed = !field_ty.eql(ptr_child_ty, target);
+ bitcast_needed = !field_ty.eql(ptr_child_ty, dg.module);
var ty_buf: Type.Payload.Pointer = undefined;
const llvm_field_index = llvmFieldIndex(parent_ty, field_index, target, &ty_buf).?;
@@ -3139,7 +3157,7 @@ pub const DeclGen = struct {
.elem_ptr => blk: {
const elem_ptr = ptr_val.castTag(.elem_ptr).?.data;
const parent_llvm_ptr = try dg.lowerParentPtr(elem_ptr.array_ptr, elem_ptr.elem_ty);
- bitcast_needed = !elem_ptr.elem_ty.eql(ptr_child_ty, target);
+ bitcast_needed = !elem_ptr.elem_ty.eql(ptr_child_ty, dg.module);
const llvm_usize = try dg.llvmType(Type.usize);
const indices: [1]*const llvm.Value = .{
@@ -3153,7 +3171,7 @@ pub const DeclGen = struct {
var buf: Type.Payload.ElemType = undefined;
const payload_ty = opt_payload_ptr.container_ty.optionalChild(&buf);
- bitcast_needed = !payload_ty.eql(ptr_child_ty, target);
+ bitcast_needed = !payload_ty.eql(ptr_child_ty, dg.module);
if (!payload_ty.hasRuntimeBitsIgnoreComptime() or payload_ty.isPtrLikeOptional()) {
// In this case, we represent pointer to optional the same as pointer
@@ -3173,7 +3191,7 @@ pub const DeclGen = struct {
const parent_llvm_ptr = try dg.lowerParentPtr(eu_payload_ptr.container_ptr, eu_payload_ptr.container_ty);
const payload_ty = eu_payload_ptr.container_ty.errorUnionPayload();
- bitcast_needed = !payload_ty.eql(ptr_child_ty, target);
+ bitcast_needed = !payload_ty.eql(ptr_child_ty, dg.module);
if (!payload_ty.hasRuntimeBitsIgnoreComptime()) {
// In this case, we represent pointer to error union the same as pointer
@@ -3201,15 +3219,14 @@ pub const DeclGen = struct {
fn lowerDeclRefValue(
self: *DeclGen,
tv: TypedValue,
- decl: *Module.Decl,
+ decl_index: Module.Decl.Index,
) Error!*const llvm.Value {
- const target = self.module.getTarget();
if (tv.ty.isSlice()) {
var buf: Type.SlicePtrFieldTypeBuffer = undefined;
const ptr_ty = tv.ty.slicePtrFieldType(&buf);
var slice_len: Value.Payload.U64 = .{
.base = .{ .tag = .int_u64 },
- .data = tv.val.sliceLen(target),
+ .data = tv.val.sliceLen(self.module),
};
const fields: [2]*const llvm.Value = .{
try self.genTypedValue(.{
@@ -3229,8 +3246,9 @@ pub const DeclGen = struct {
// const bar = foo;
// ... &bar;
// `bar` is just an alias and we actually want to lower a reference to `foo`.
+ const decl = self.module.declPtr(decl_index);
if (decl.val.castTag(.function)) |func| {
- if (func.data.owner_decl != decl) {
+ if (func.data.owner_decl != decl_index) {
return self.lowerDeclRefValue(tv, func.data.owner_decl);
}
}
@@ -3240,12 +3258,12 @@ pub const DeclGen = struct {
return self.lowerPtrToVoid(tv.ty);
}
- decl.markAlive();
+ self.module.markDeclAlive(decl);
const llvm_val = if (is_fn_body)
- try self.resolveLlvmFunction(decl)
+ try self.resolveLlvmFunction(decl_index)
else
- try self.resolveGlobalDecl(decl);
+ try self.resolveGlobalDecl(decl_index);
const llvm_type = try self.llvmType(tv.ty);
if (tv.ty.zigTypeTag() == .Int) {
@@ -4405,7 +4423,8 @@ pub const FuncGen = struct {
const ty_pl = self.air.instructions.items(.data)[inst].ty_pl;
const func = self.air.values[ty_pl.payload].castTag(.function).?.data;
- const decl = func.owner_decl;
+ const decl_index = func.owner_decl;
+ const decl = self.dg.module.declPtr(decl_index);
const di_file = try self.dg.object.getDIFile(self.gpa, decl.src_namespace.file_scope);
self.di_file = di_file;
const line_number = decl.src_line + 1;
@@ -4417,10 +4436,10 @@ pub const FuncGen = struct {
.base_line = self.base_line,
});
- const fqn = try decl.getFullyQualifiedName(self.gpa);
+ const fqn = try decl.getFullyQualifiedName(self.dg.module);
defer self.gpa.free(fqn);
- const is_internal_linkage = !self.dg.module.decl_exports.contains(decl);
+ const is_internal_linkage = !self.dg.module.decl_exports.contains(decl_index);
const subprogram = dib.createFunction(
di_file.toScope(),
decl.name,
@@ -4447,7 +4466,8 @@ pub const FuncGen = struct {
const ty_pl = self.air.instructions.items(.data)[inst].ty_pl;
const func = self.air.values[ty_pl.payload].castTag(.function).?.data;
- const decl = func.owner_decl;
+ const mod = self.dg.module;
+ const decl = mod.declPtr(func.owner_decl);
const di_file = try self.dg.object.getDIFile(self.gpa, decl.src_namespace.file_scope);
self.di_file = di_file;
const old = self.dbg_inlined.pop();
@@ -5887,7 +5907,7 @@ pub const FuncGen = struct {
if (self.dg.object.di_builder) |dib| {
const src_index = self.getSrcArgIndex(self.arg_index - 1);
const func = self.dg.decl.getFunction().?;
- const lbrace_line = func.owner_decl.src_line + func.lbrace_line + 1;
+ const lbrace_line = self.dg.module.declPtr(func.owner_decl).src_line + func.lbrace_line + 1;
const lbrace_col = func.lbrace_column + 1;
const di_local_var = dib.createParameterVariable(
self.di_scope.?,
@@ -6430,8 +6450,9 @@ pub const FuncGen = struct {
const operand = try self.resolveInst(un_op);
const enum_ty = self.air.typeOf(un_op);
+ const mod = self.dg.module;
const llvm_fn_name = try std.fmt.allocPrintZ(arena, "__zig_tag_name_{s}", .{
- try enum_ty.getOwnerDecl().getFullyQualifiedName(arena),
+ try mod.declPtr(enum_ty.getOwnerDecl()).getFullyQualifiedName(mod),
});
const llvm_fn = try self.getEnumTagNameFunction(enum_ty, llvm_fn_name);
@@ -6617,7 +6638,7 @@ pub const FuncGen = struct {
for (values) |*val, i| {
var buf: Value.ElemValueBuffer = undefined;
- const elem = mask.elemValueBuffer(i, &buf);
+ const elem = mask.elemValueBuffer(self.dg.module, i, &buf);
if (elem.isUndef()) {
val.* = llvm_i32.getUndef();
} else {
diff --git a/src/codegen/spirv.zig b/src/codegen/spirv.zig
index 6072c59845..791c2dc187 100644
--- a/src/codegen/spirv.zig
+++ b/src/codegen/spirv.zig
@@ -633,7 +633,13 @@ pub const DeclGen = struct {
return result_id.toRef();
}
- fn airArithOp(self: *DeclGen, inst: Air.Inst.Index, comptime fop: Opcode, comptime sop: Opcode, comptime uop: Opcode) !IdRef {
+ fn airArithOp(
+ self: *DeclGen,
+ inst: Air.Inst.Index,
+ comptime fop: Opcode,
+ comptime sop: Opcode,
+ comptime uop: Opcode,
+ ) !IdRef {
// LHS and RHS are guaranteed to have the same type, and AIR guarantees
// the result to be the same as the LHS and RHS, which matches SPIR-V.
const ty = self.air.typeOfIndex(inst);
@@ -644,10 +650,8 @@ pub const DeclGen = struct {
const result_id = self.spv.allocId();
const result_type_id = try self.resolveTypeId(ty);
- const target = self.getTarget();
-
- assert(self.air.typeOf(bin_op.lhs).eql(ty, target));
- assert(self.air.typeOf(bin_op.rhs).eql(ty, target));
+ assert(self.air.typeOf(bin_op.lhs).eql(ty, self.module));
+ assert(self.air.typeOf(bin_op.rhs).eql(ty, self.module));
// Binary operations are generally applicable to both scalar and vector operations
// in SPIR-V, but int and float versions of operations require different opcodes.
@@ -694,7 +698,7 @@ pub const DeclGen = struct {
const result_id = self.spv.allocId();
const result_type_id = try self.resolveTypeId(Type.initTag(.bool));
const op_ty = self.air.typeOf(bin_op.lhs);
- assert(op_ty.eql(self.air.typeOf(bin_op.rhs), self.getTarget()));
+ assert(op_ty.eql(self.air.typeOf(bin_op.rhs), self.module));
// Comparisons are generally applicable to both scalar and vector operations in SPIR-V,
// but int and float versions of operations require different opcodes.