aboutsummaryrefslogtreecommitdiff
path: root/src/codegen
diff options
context:
space:
mode:
authorMatthew Lugg <mlugg@mlugg.co.uk>2024-12-25 02:58:27 +0000
committerGitHub <noreply@github.com>2024-12-25 02:58:27 +0000
commit497592c9b45a94fb7b6028bf45b80f183e395a9b (patch)
tree467873c408750cb4223f3ccf31775e42ec9fbd5c /src/codegen
parentaf5e731729592af4a5716edd3b1e03264d66ea46 (diff)
parent3afda4322c34dedc2319701fdfac3505c8d311e9 (diff)
downloadzig-497592c9b45a94fb7b6028bf45b80f183e395a9b.tar.gz
zig-497592c9b45a94fb7b6028bf45b80f183e395a9b.zip
Merge pull request #22303 from mlugg/131-new
compiler: analyze type and value of global declarations separately
Diffstat (limited to 'src/codegen')
-rw-r--r--src/codegen/c.zig61
-rw-r--r--src/codegen/llvm.zig67
-rw-r--r--src/codegen/spirv.zig29
3 files changed, 77 insertions, 80 deletions
diff --git a/src/codegen/c.zig b/src/codegen/c.zig
index c3e3c7fbdc..2368f202da 100644
--- a/src/codegen/c.zig
+++ b/src/codegen/c.zig
@@ -770,11 +770,14 @@ pub const DeclGen = struct {
const ctype_pool = &dg.ctype_pool;
// Chase function values in order to be able to reference the original function.
- const owner_nav = switch (ip.indexToKey(zcu.navValue(nav_index).toIntern())) {
- .variable => |variable| variable.owner_nav,
- .func => |func| func.owner_nav,
- .@"extern" => |@"extern"| @"extern".owner_nav,
- else => nav_index,
+ const owner_nav = switch (ip.getNav(nav_index).status) {
+ .unresolved => unreachable,
+ .type_resolved => nav_index, // this can't be an extern or a function
+ .fully_resolved => |r| switch (ip.indexToKey(r.val)) {
+ .func => |f| f.owner_nav,
+ .@"extern" => |e| e.owner_nav,
+ else => nav_index,
+ },
};
// Render an undefined pointer if we have a pointer to a zero-bit or comptime type.
@@ -2237,7 +2240,7 @@ pub const DeclGen = struct {
Type.fromInterned(nav.typeOf(ip)),
.{ .nav = nav_index },
CQualifiers.init(.{ .@"const" = flags.is_const }),
- nav.status.resolved.alignment,
+ nav.getAlignment(),
.complete,
);
try fwd.writeAll(";\n");
@@ -2246,19 +2249,19 @@ pub const DeclGen = struct {
fn renderNavName(dg: *DeclGen, writer: anytype, nav_index: InternPool.Nav.Index) !void {
const zcu = dg.pt.zcu;
const ip = &zcu.intern_pool;
- switch (ip.indexToKey(zcu.navValue(nav_index).toIntern())) {
- .@"extern" => |@"extern"| try writer.print("{ }", .{
+ const nav = ip.getNav(nav_index);
+ if (nav.getExtern(ip)) |@"extern"| {
+ try writer.print("{ }", .{
fmtIdent(ip.getNav(@"extern".owner_nav).name.toSlice(ip)),
- }),
- 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.
- const fqn_slice = ip.getNav(nav_index).fqn.toSlice(ip);
- try writer.print("{}__{d}", .{
- fmtIdent(fqn_slice[0..@min(fqn_slice.len, 100)]),
- @intFromEnum(nav_index),
- });
- },
+ });
+ } 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.
+ const fqn_slice = ip.getNav(nav_index).fqn.toSlice(ip);
+ try writer.print("{}__{d}", .{
+ fmtIdent(fqn_slice[0..@min(fqn_slice.len, 100)]),
+ @intFromEnum(nav_index),
+ });
}
}
@@ -2826,7 +2829,7 @@ pub fn genLazyFn(o: *Object, lazy_ctype_pool: *const CType.Pool, lazy_fn: LazyFn
const fwd = o.dg.fwdDeclWriter();
try fwd.print("static zig_{s} ", .{@tagName(key)});
- try o.dg.renderFunctionSignature(fwd, fn_val, ip.getNav(fn_nav_index).status.resolved.alignment, .forward, .{
+ try o.dg.renderFunctionSignature(fwd, fn_val, ip.getNav(fn_nav_index).getAlignment(), .forward, .{
.fmt_ctype_pool_string = fn_name,
});
try fwd.writeAll(";\n");
@@ -2867,13 +2870,13 @@ pub fn genFunc(f: *Function) !void {
try o.dg.renderFunctionSignature(
fwd,
nav_val,
- nav.status.resolved.alignment,
+ nav.status.fully_resolved.alignment,
.forward,
.{ .nav = nav_index },
);
try fwd.writeAll(";\n");
- if (nav.status.resolved.@"linksection".toSlice(ip)) |s|
+ if (nav.status.fully_resolved.@"linksection".toSlice(ip)) |s|
try o.writer().print("zig_linksection_fn({s}) ", .{fmtStringLiteral(s, null)});
try o.dg.renderFunctionSignature(
o.writer(),
@@ -2952,7 +2955,7 @@ pub fn genDecl(o: *Object) !void {
const nav_ty = Type.fromInterned(nav.typeOf(ip));
if (!nav_ty.isFnOrHasRuntimeBitsIgnoreComptime(zcu)) return;
- switch (ip.indexToKey(nav.status.resolved.val)) {
+ switch (ip.indexToKey(nav.status.fully_resolved.val)) {
.@"extern" => |@"extern"| {
if (!ip.isFunctionType(nav_ty.toIntern())) return o.dg.renderFwdDecl(o.dg.pass.nav, .{
.is_extern = true,
@@ -2965,8 +2968,8 @@ pub fn genDecl(o: *Object) !void {
try fwd.writeAll("zig_extern ");
try o.dg.renderFunctionSignature(
fwd,
- Value.fromInterned(nav.status.resolved.val),
- nav.status.resolved.alignment,
+ Value.fromInterned(nav.status.fully_resolved.val),
+ nav.status.fully_resolved.alignment,
.forward,
.{ .@"export" = .{
.main_name = nav.name,
@@ -2985,14 +2988,14 @@ pub fn genDecl(o: *Object) !void {
const w = o.writer();
if (variable.is_weak_linkage) try w.writeAll("zig_weak_linkage ");
if (variable.is_threadlocal and !o.dg.mod.single_threaded) try w.writeAll("zig_threadlocal ");
- if (nav.status.resolved.@"linksection".toSlice(&zcu.intern_pool)) |s|
+ if (nav.status.fully_resolved.@"linksection".toSlice(&zcu.intern_pool)) |s|
try w.print("zig_linksection({s}) ", .{fmtStringLiteral(s, null)});
try o.dg.renderTypeAndName(
w,
nav_ty,
.{ .nav = o.dg.pass.nav },
.{},
- nav.status.resolved.alignment,
+ nav.status.fully_resolved.alignment,
.complete,
);
try w.writeAll(" = ");
@@ -3002,10 +3005,10 @@ pub fn genDecl(o: *Object) !void {
},
else => try genDeclValue(
o,
- Value.fromInterned(nav.status.resolved.val),
+ Value.fromInterned(nav.status.fully_resolved.val),
.{ .nav = o.dg.pass.nav },
- nav.status.resolved.alignment,
- nav.status.resolved.@"linksection",
+ nav.status.fully_resolved.alignment,
+ nav.status.fully_resolved.@"linksection",
),
}
}
diff --git a/src/codegen/llvm.zig b/src/codegen/llvm.zig
index b94ea07995..5b36644019 100644
--- a/src/codegen/llvm.zig
+++ b/src/codegen/llvm.zig
@@ -1476,7 +1476,7 @@ pub const Object = struct {
} }, &o.builder);
}
- if (nav.status.resolved.@"linksection".toSlice(ip)) |section|
+ if (nav.status.fully_resolved.@"linksection".toSlice(ip)) |section|
function_index.setSection(try o.builder.string(section), &o.builder);
var deinit_wip = true;
@@ -1684,7 +1684,7 @@ pub const Object = struct {
const file = try o.getDebugFile(file_scope);
const line_number = zcu.navSrcLine(func.owner_nav) + 1;
- const is_internal_linkage = ip.indexToKey(nav.status.resolved.val) != .@"extern";
+ const is_internal_linkage = ip.indexToKey(nav.status.fully_resolved.val) != .@"extern";
const debug_decl_type = try o.lowerDebugType(fn_ty);
const subprogram = try o.builder.debugSubprogram(
@@ -2928,9 +2928,7 @@ pub const Object = struct {
const gpa = o.gpa;
const nav = ip.getNav(nav_index);
const owner_mod = zcu.navFileScope(nav_index).mod;
- const resolved = nav.status.resolved;
- const val = Value.fromInterned(resolved.val);
- const ty = val.typeOf(zcu);
+ const ty: Type = .fromInterned(nav.typeOf(ip));
const gop = try o.nav_map.getOrPut(gpa, nav_index);
if (gop.found_existing) return gop.value_ptr.ptr(&o.builder).kind.function;
@@ -2938,15 +2936,14 @@ pub const Object = struct {
const target = owner_mod.resolved_target.result;
const sret = firstParamSRet(fn_info, zcu, target);
- const is_extern, const lib_name = switch (ip.indexToKey(val.toIntern())) {
- .variable => |variable| .{ false, variable.lib_name },
- .@"extern" => |@"extern"| .{ true, @"extern".lib_name },
- else => .{ false, .none },
- };
+ const is_extern, const lib_name = if (nav.getExtern(ip)) |@"extern"|
+ .{ true, @"extern".lib_name }
+ else
+ .{ false, .none };
const function_index = try o.builder.addFunction(
try o.lowerType(ty),
try o.builder.strtabString((if (is_extern) nav.name else nav.fqn).toSlice(ip)),
- toLlvmAddressSpace(resolved.@"addrspace", target),
+ toLlvmAddressSpace(nav.getAddrspace(), target),
);
gop.value_ptr.* = function_index.ptrConst(&o.builder).global;
@@ -3064,8 +3061,8 @@ pub const Object = struct {
}
}
- if (resolved.alignment != .none)
- function_index.setAlignment(resolved.alignment.toLlvm(), &o.builder);
+ if (nav.getAlignment() != .none)
+ function_index.setAlignment(nav.getAlignment().toLlvm(), &o.builder);
// Function attributes that are independent of analysis results of the function body.
try o.addCommonFnAttributes(
@@ -3250,17 +3247,21 @@ pub const Object = struct {
const zcu = pt.zcu;
const ip = &zcu.intern_pool;
const nav = ip.getNav(nav_index);
- const resolved = nav.status.resolved;
- const is_extern, const is_threadlocal, const is_weak_linkage, const is_dll_import = switch (ip.indexToKey(resolved.val)) {
- .variable => |variable| .{ false, variable.is_threadlocal, variable.is_weak_linkage, false },
- .@"extern" => |@"extern"| .{ true, @"extern".is_threadlocal, @"extern".is_weak_linkage, @"extern".is_dll_import },
- else => .{ false, false, false, false },
+ const is_extern, const is_threadlocal, const is_weak_linkage, const is_dll_import = switch (nav.status) {
+ .unresolved => unreachable,
+ .fully_resolved => |r| switch (ip.indexToKey(r.val)) {
+ .variable => |variable| .{ false, variable.is_threadlocal, variable.is_weak_linkage, false },
+ .@"extern" => |@"extern"| .{ true, @"extern".is_threadlocal, @"extern".is_weak_linkage, @"extern".is_dll_import },
+ else => .{ false, false, false, false },
+ },
+ // This means it's a source declaration which is not `extern`!
+ .type_resolved => |r| .{ false, r.is_threadlocal, false, false },
};
const variable_index = try o.builder.addVariable(
try o.builder.strtabString((if (is_extern) nav.name else nav.fqn).toSlice(ip)),
try o.lowerType(Type.fromInterned(nav.typeOf(ip))),
- toLlvmGlobalAddressSpace(resolved.@"addrspace", zcu.getTarget()),
+ toLlvmGlobalAddressSpace(nav.getAddrspace(), zcu.getTarget()),
);
gop.value_ptr.* = variable_index.ptrConst(&o.builder).global;
@@ -4529,20 +4530,10 @@ pub const Object = struct {
const zcu = pt.zcu;
const ip = &zcu.intern_pool;
- // In the case of something like:
- // fn foo() void {}
- // const bar = foo;
- // ... &bar;
- // `bar` is just an alias and we actually want to lower a reference to `foo`.
- const owner_nav_index = switch (ip.indexToKey(zcu.navValue(nav_index).toIntern())) {
- .func => |func| func.owner_nav,
- .@"extern" => |@"extern"| @"extern".owner_nav,
- else => nav_index,
- };
- const owner_nav = ip.getNav(owner_nav_index);
+ const nav = ip.getNav(nav_index);
- const nav_ty = Type.fromInterned(owner_nav.typeOf(ip));
- const ptr_ty = try pt.navPtrType(owner_nav_index);
+ const nav_ty = Type.fromInterned(nav.typeOf(ip));
+ const ptr_ty = try pt.navPtrType(nav_index);
const is_fn_body = nav_ty.zigTypeTag(zcu) == .@"fn";
if ((!is_fn_body and !nav_ty.hasRuntimeBits(zcu)) or
@@ -4552,13 +4543,13 @@ pub const Object = struct {
}
const llvm_global = if (is_fn_body)
- (try o.resolveLlvmFunction(owner_nav_index)).ptrConst(&o.builder).global
+ (try o.resolveLlvmFunction(nav_index)).ptrConst(&o.builder).global
else
- (try o.resolveGlobalNav(owner_nav_index)).ptrConst(&o.builder).global;
+ (try o.resolveGlobalNav(nav_index)).ptrConst(&o.builder).global;
const llvm_val = try o.builder.convConst(
llvm_global.toConst(),
- try o.builder.ptrType(toLlvmAddressSpace(owner_nav.status.resolved.@"addrspace", zcu.getTarget())),
+ try o.builder.ptrType(toLlvmAddressSpace(nav.getAddrspace(), zcu.getTarget())),
);
return o.builder.convConst(llvm_val, try o.lowerType(ptr_ty));
@@ -4800,10 +4791,10 @@ pub const NavGen = struct {
const ip = &zcu.intern_pool;
const nav_index = ng.nav_index;
const nav = ip.getNav(nav_index);
- const resolved = nav.status.resolved;
+ const resolved = nav.status.fully_resolved;
const is_extern, const lib_name, const is_threadlocal, const is_weak_linkage, const is_dll_import, const is_const, const init_val, const owner_nav = switch (ip.indexToKey(resolved.val)) {
- .variable => |variable| .{ false, variable.lib_name, variable.is_threadlocal, variable.is_weak_linkage, false, false, variable.init, variable.owner_nav },
+ .variable => |variable| .{ false, .none, variable.is_threadlocal, variable.is_weak_linkage, false, false, variable.init, variable.owner_nav },
.@"extern" => |@"extern"| .{ true, @"extern".lib_name, @"extern".is_threadlocal, @"extern".is_weak_linkage, @"extern".is_dll_import, @"extern".is_const, .none, @"extern".owner_nav },
else => .{ false, .none, false, false, false, true, resolved.val, nav_index },
};
@@ -5766,7 +5757,7 @@ pub const FuncGen = struct {
const msg_nav_index = zcu.panic_messages[@intFromEnum(panic_id)].unwrap().?;
const msg_nav = ip.getNav(msg_nav_index);
const msg_len = Type.fromInterned(msg_nav.typeOf(ip)).childType(zcu).arrayLen(zcu);
- const msg_ptr = try o.lowerValue(msg_nav.status.resolved.val);
+ const msg_ptr = try o.lowerValue(msg_nav.status.fully_resolved.val);
const null_opt_addr_global = try fg.resolveNullOptUsize();
const target = zcu.getTarget();
const llvm_usize = try o.lowerType(Type.usize);
diff --git a/src/codegen/spirv.zig b/src/codegen/spirv.zig
index 16b4a6dfbd..91e2c4f7e7 100644
--- a/src/codegen/spirv.zig
+++ b/src/codegen/spirv.zig
@@ -268,7 +268,7 @@ pub const Object = struct {
// TODO: Extern fn?
const kind: SpvModule.Decl.Kind = if (ip.isFunctionType(nav.typeOf(ip)))
.func
- else switch (nav.status.resolved.@"addrspace") {
+ else switch (nav.getAddrspace()) {
.generic => .invocation_global,
else => .global,
};
@@ -1279,17 +1279,20 @@ const NavGen = struct {
const ip = &zcu.intern_pool;
const ty_id = try self.resolveType(ty, .direct);
const nav = ip.getNav(nav_index);
- const nav_val = zcu.navValue(nav_index);
- const nav_ty = nav_val.typeOf(zcu);
-
- switch (ip.indexToKey(nav_val.toIntern())) {
- .func => {
- // TODO: Properly lower function pointers. For now we are going to hack around it and
- // just generate an empty pointer. Function pointers are represented by a pointer to usize.
- return try self.spv.constUndef(ty_id);
+ const nav_ty: Type = .fromInterned(nav.typeOf(ip));
+
+ switch (nav.status) {
+ .unresolved => unreachable,
+ .type_resolved => {}, // this is not a function or extern
+ .fully_resolved => |r| switch (ip.indexToKey(r.val)) {
+ .func => {
+ // TODO: Properly lower function pointers. For now we are going to hack around it and
+ // just generate an empty pointer. Function pointers are represented by a pointer to usize.
+ return try self.spv.constUndef(ty_id);
+ },
+ .@"extern" => if (ip.isFunctionType(nav_ty.toIntern())) @panic("TODO"),
+ else => {},
},
- .@"extern" => assert(!ip.isFunctionType(nav_ty.toIntern())), // TODO
- else => {},
}
if (!nav_ty.isFnOrHasRuntimeBitsIgnoreComptime(zcu)) {
@@ -1305,7 +1308,7 @@ const NavGen = struct {
.global, .invocation_global => spv_decl.result_id,
};
- const storage_class = self.spvStorageClass(nav.status.resolved.@"addrspace");
+ const storage_class = self.spvStorageClass(nav.getAddrspace());
try self.addFunctionDep(spv_decl_index, storage_class);
const decl_ptr_ty_id = try self.ptrType(nav_ty, storage_class);
@@ -3182,7 +3185,7 @@ const NavGen = struct {
};
assert(maybe_init_val == null); // TODO
- const storage_class = self.spvStorageClass(nav.status.resolved.@"addrspace");
+ const storage_class = self.spvStorageClass(nav.getAddrspace());
assert(storage_class != .Generic); // These should be instance globals
const ptr_ty_id = try self.ptrType(ty, storage_class);