aboutsummaryrefslogtreecommitdiff
path: root/src/link
diff options
context:
space:
mode:
authorLuuk de Gram <luuk@degram.dev>2023-04-13 19:32:22 +0200
committerGitHub <noreply@github.com>2023-04-13 19:32:22 +0200
commit25e3851fe0f7fe254b48c2242ab8d4ef89165fd5 (patch)
treec7991ec10945496de6dcb8f8aae32d12c077ecd6 /src/link
parentfbcf1c0006dc6656deb3f04e2f52d1da4a599952 (diff)
parentabc1e52e0885c8e46d743d5e48ba260b35ae2769 (diff)
downloadzig-25e3851fe0f7fe254b48c2242ab8d4ef89165fd5.tar.gz
zig-25e3851fe0f7fe254b48c2242ab8d4ef89165fd5.zip
Merge pull request #15257 from Luukdegram/wasm-tagname
wasm: Implement `@tagName` instruction
Diffstat (limited to 'src/link')
-rw-r--r--src/link/Wasm.zig56
-rw-r--r--src/link/Wasm/Atom.zig2
2 files changed, 56 insertions, 2 deletions
diff --git a/src/link/Wasm.zig b/src/link/Wasm.zig
index b1fc25bf26..2125a8faaa 100644
--- a/src/link/Wasm.zig
+++ b/src/link/Wasm.zig
@@ -30,6 +30,7 @@ const Symbol = @import("Wasm/Symbol.zig");
const Object = @import("Wasm/Object.zig");
const Archive = @import("Wasm/Archive.zig");
const types = @import("Wasm/types.zig");
+pub const Relocation = types.Relocation;
pub const base_tag: link.File.Tag = .wasm;
@@ -178,6 +179,10 @@ debug_str_atom: ?Atom.Index = null,
debug_pubnames_atom: ?Atom.Index = null,
debug_pubtypes_atom: ?Atom.Index = null,
+/// List of atom indexes of functions that are generated by the backend,
+/// rather than by the linker.
+synthetic_functions: std.ArrayListUnmanaged(Atom.Index) = .{},
+
pub const Segment = struct {
alignment: u32,
size: u32,
@@ -1208,7 +1213,7 @@ fn resolveLazySymbols(wasm: *Wasm) !void {
// Tries to find a global symbol by its name. Returns null when not found,
/// and its location when it is found.
-fn findGlobalSymbol(wasm: *Wasm, name: []const u8) ?SymbolLoc {
+pub fn findGlobalSymbol(wasm: *Wasm, name: []const u8) ?SymbolLoc {
const offset = wasm.string_table.getOffset(name) orelse return null;
return wasm.globals.get(offset);
}
@@ -1287,6 +1292,7 @@ pub fn deinit(wasm: *Wasm) void {
wasm.exports.deinit(gpa);
wasm.string_table.deinit(gpa);
+ wasm.synthetic_functions.deinit(gpa);
if (wasm.dwarf) |*dwarf| {
dwarf.deinit();
@@ -2272,6 +2278,49 @@ fn createSyntheticFunction(
atom.offset = prev_atom.offset + prev_atom.size;
}
+/// Unlike `createSyntheticFunction` this function is to be called by
+/// the codegeneration backend. This will not allocate the created Atom yet,
+/// but will instead be appended to `synthetic_functions` list and will be
+/// parsed at the end of code generation.
+/// Returns the index of the symbol.
+pub fn createFunction(
+ wasm: *Wasm,
+ symbol_name: []const u8,
+ func_ty: std.wasm.Type,
+ function_body: *std.ArrayList(u8),
+ relocations: *std.ArrayList(Relocation),
+) !u32 {
+ const loc = try wasm.createSyntheticSymbol(symbol_name, .function);
+
+ const atom_index = @intCast(Atom.Index, wasm.managed_atoms.items.len);
+ const atom = try wasm.managed_atoms.addOne(wasm.base.allocator);
+ atom.* = .{
+ .size = @intCast(u32, function_body.items.len),
+ .offset = 0,
+ .sym_index = loc.index,
+ .file = null,
+ .alignment = 1,
+ .next = null,
+ .prev = null,
+ .code = function_body.moveToUnmanaged(),
+ .relocs = relocations.moveToUnmanaged(),
+ };
+ const symbol = loc.getSymbol(wasm);
+ symbol.setFlag(.WASM_SYM_VISIBILITY_HIDDEN); // ensure function does not get exported
+
+ const section_index = wasm.code_section_index orelse idx: {
+ const index = @intCast(u32, wasm.segments.items.len);
+ try wasm.appendDummySegment();
+ break :idx index;
+ };
+ try wasm.appendAtomAtIndex(section_index, atom_index);
+ try wasm.symbol_atom.putNoClobber(wasm.base.allocator, loc, atom_index);
+ try wasm.atom_types.put(wasm.base.allocator, atom_index, try wasm.putOrGetFuncType(func_ty));
+ try wasm.synthetic_functions.append(wasm.base.allocator, atom_index);
+
+ return loc.index;
+}
+
fn initializeTLSFunction(wasm: *Wasm) !void {
if (!wasm.base.options.shared_memory) return;
@@ -3306,6 +3355,11 @@ pub fn flushModule(wasm: *Wasm, comp: *Compilation, prog_node: *std.Progress.Nod
}
}
+ // also parse any backend-generated functions
+ for (wasm.synthetic_functions.items) |atom_index| {
+ try wasm.parseAtom(atom_index, .function);
+ }
+
if (wasm.dwarf) |*dwarf| {
try dwarf.flushModule(wasm.base.options.module.?);
}
diff --git a/src/link/Wasm/Atom.zig b/src/link/Wasm/Atom.zig
index 7d2f5a6696..f8092c6db1 100644
--- a/src/link/Wasm/Atom.zig
+++ b/src/link/Wasm/Atom.zig
@@ -43,7 +43,7 @@ pub const Index = u32;
/// Represents a default empty wasm `Atom`
pub const empty: Atom = .{
- .alignment = 0,
+ .alignment = 1,
.file = null,
.next = null,
.offset = 0,