aboutsummaryrefslogtreecommitdiff
path: root/src/link.zig
diff options
context:
space:
mode:
authorAndrew Kelley <andrew@ziglang.org>2023-10-26 20:32:16 -0700
committerAndrew Kelley <andrew@ziglang.org>2023-10-26 20:32:16 -0700
commit4bc88dd11641a664d80b00ad784bafc6da776697 (patch)
tree0dfff49ae93d5826a0c10e3819a1225e4f992693 /src/link.zig
parentba9e38847a097777370b4721780d5dbefda1b12f (diff)
downloadzig-4bc88dd11641a664d80b00ad784bafc6da776697.tar.gz
zig-4bc88dd11641a664d80b00ad784bafc6da776697.zip
link: support exporting constant values without a Decl
The main motivating change here is to prevent the creation of a fake Decl object by the frontend in order to `@export()` a value. Instead, `link.updateDeclExports` is renamed to `link.updateExports` and accepts a tagged union which can be either a Decl.Index or a InternPool.Index.
Diffstat (limited to 'src/link.zig')
-rw-r--r--src/link.zig49
1 files changed, 32 insertions, 17 deletions
diff --git a/src/link.zig b/src/link.zig
index 6e5c809f62..1648d6a63e 100644
--- a/src/link.zig
+++ b/src/link.zig
@@ -587,7 +587,7 @@ pub const File = struct {
}
}
- /// May be called before or after updateDeclExports for any given Decl.
+ /// May be called before or after updateExports for any given Decl.
pub fn updateDecl(base: *File, module: *Module, decl_index: Module.Decl.Index) UpdateDeclError!void {
const decl = module.declPtr(decl_index);
assert(decl.has_tv);
@@ -609,7 +609,7 @@ pub const File = struct {
}
}
- /// May be called before or after updateDeclExports for any given Decl.
+ /// May be called before or after updateExports for any given Decl.
pub fn updateFunc(base: *File, module: *Module, func_index: InternPool.Index, air: Air, liveness: Liveness) UpdateDeclError!void {
if (build_options.only_c) {
assert(base.tag == .c);
@@ -882,33 +882,34 @@ pub const File = struct {
}
}
- pub const UpdateDeclExportsError = error{
+ pub const UpdateExportsError = error{
OutOfMemory,
AnalysisFail,
};
+ /// This is called for every exported thing. `exports` is almost always
+ /// a list of size 1, meaning that `exported` is exported once. However, it is possible
+ /// to export the same thing with multiple different symbol names (aliases).
/// May be called before or after updateDecl for any given Decl.
- pub fn updateDeclExports(
+ pub fn updateExports(
base: *File,
module: *Module,
- decl_index: Module.Decl.Index,
+ exported: Module.Exported,
exports: []const *Module.Export,
- ) UpdateDeclExportsError!void {
- const decl = module.declPtr(decl_index);
- assert(decl.has_tv);
+ ) UpdateExportsError!void {
if (build_options.only_c) {
assert(base.tag == .c);
- return @fieldParentPtr(C, "base", base).updateDeclExports(module, decl_index, exports);
+ return @fieldParentPtr(C, "base", base).updateExports(module, exported, exports);
}
switch (base.tag) {
- .coff => return @fieldParentPtr(Coff, "base", base).updateDeclExports(module, decl_index, exports),
- .elf => return @fieldParentPtr(Elf, "base", base).updateDeclExports(module, decl_index, exports),
- .macho => return @fieldParentPtr(MachO, "base", base).updateDeclExports(module, decl_index, exports),
- .c => return @fieldParentPtr(C, "base", base).updateDeclExports(module, decl_index, exports),
- .wasm => return @fieldParentPtr(Wasm, "base", base).updateDeclExports(module, decl_index, exports),
- .spirv => return @fieldParentPtr(SpirV, "base", base).updateDeclExports(module, decl_index, exports),
- .plan9 => return @fieldParentPtr(Plan9, "base", base).updateDeclExports(module, decl_index, exports),
- .nvptx => return @fieldParentPtr(NvPtx, "base", base).updateDeclExports(module, decl_index, exports),
+ .coff => return @fieldParentPtr(Coff, "base", base).updateExports(module, exported, exports),
+ .elf => return @fieldParentPtr(Elf, "base", base).updateExports(module, exported, exports),
+ .macho => return @fieldParentPtr(MachO, "base", base).updateExports(module, exported, exports),
+ .c => return @fieldParentPtr(C, "base", base).updateExports(module, exported, exports),
+ .wasm => return @fieldParentPtr(Wasm, "base", base).updateExports(module, exported, exports),
+ .spirv => return @fieldParentPtr(SpirV, "base", base).updateExports(module, exported, exports),
+ .plan9 => return @fieldParentPtr(Plan9, "base", base).updateExports(module, exported, exports),
+ .nvptx => return @fieldParentPtr(NvPtx, "base", base).updateExports(module, exported, exports),
}
}
@@ -968,6 +969,20 @@ pub const File = struct {
}
}
+ pub fn deleteDeclExport(base: *File, decl_index: Module.Decl.Index, name: InternPool.NullTerminatedString) !void {
+ if (build_options.only_c) unreachable;
+ switch (base.tag) {
+ .coff => return @fieldParentPtr(Coff, "base", base).deleteDeclExport(decl_index, name),
+ .elf => return @fieldParentPtr(Elf, "base", base).deleteDeclExport(decl_index, name),
+ .macho => return @fieldParentPtr(MachO, "base", base).deleteDeclExport(decl_index, name),
+ .plan9 => {},
+ .c => {},
+ .wasm => return @fieldParentPtr(Wasm, "base", base).deleteDeclExport(decl_index),
+ .spirv => {},
+ .nvptx => {},
+ }
+ }
+
/// This function is called by the frontend before flush(). It communicates that
/// `options.bin_file.emit` directory needs to be renamed from
/// `[zig-cache]/tmp/[random]` to `[zig-cache]/o/[digest]`.