Commit 9b3c8fd3a8
Changed files (2)
src
link
src/link/Wasm/ZigObject.zig
@@ -3,6 +3,7 @@
//! and any relocations that may have been emitted.
//! Think about this as fake in-memory Object file for the Zig module.
+path: []const u8,
/// List of all `Decl` that are currently alive.
/// Each index maps to the corresponding `Atom.Index`.
decls: std.AutoHashMapUnmanaged(InternPool.DeclIndex, Atom.Index) = .{},
@@ -22,7 +23,7 @@ global_syms: std.AutoHashMapUnmanaged(u32, u32) = .{},
/// List of symbol indexes which are free to be used.
symbols_free_list: std.ArrayListUnmanaged(u32) = .{},
/// Extra metadata about the linking section, such as alignment of segments and their name.
-segment_info: std.ArrayListUnmanage(types.Segment) = &.{},
+segment_info: std.ArrayListUnmanaged(types.Segment) = .{},
/// File encapsulated string table, used to deduplicate strings within the generated file.
string_table: StringTable = .{},
/// Map for storing anonymous declarations. Each anonymous decl maps to its Atom's index.
@@ -72,6 +73,30 @@ debug_str_index: ?u32 = null,
/// The index of the segment representing the custom '.debug_pubtypes' section.
debug_abbrev_index: ?u32 = null,
+/// Initializes the `ZigObject` with initial symbols.
+pub fn init(zig_object: *ZigObject, wasm_file: *Wasm) !void {
+ // Initialize an undefined global with the name __stack_pointer. Codegen will use
+ // this to generate relocations when moving the stack pointer. This symbol will be
+ // resolved automatically by the final linking stage.
+ try zig_object.createStackPointer(wasm_file);
+
+ // TODO: Initialize debug information when we reimplement Dwarf support.
+}
+
+fn createStackPointer(zig_object: *ZigObject, wasm_file: *Wasm) !void {
+ const gpa = wasm_file.base.comp.gpa;
+ const sym_index = try zig_object.getGlobalSymbol(gpa, "__stack_pointer", .global);
+ zig_object.symbols.items[sym_index].index = zig_object.imported_globals_count;
+ const is_wasm32 = wasm_file.base.comp.root_mod.resolved_target.result.cpu.arch == .wasm32;
+ try zig_object.imports.putNoClobber(gpa, sym_index, .{
+ .name = zig_object.symbols.items[sym_index].name,
+ .module_name = try zig_object.string_table.insert(gpa, wasm_file.host_name),
+ .kind = .{ .global = .{ .valtype = if (is_wasm32) .i32 else .i64, .mutable = true } },
+ });
+ zig_object.imported_globals_count += 1;
+ zig_object.stack_pointer_sym = sym_index;
+}
+
/// Frees and invalidates all memory of the incrementally compiled Zig module.
/// It is illegal behavior to access the `ZigObject` after calling `deinit`.
pub fn deinit(zig_object: *ZigObject, gpa: std.mem.Allocator) void {
@@ -113,6 +138,7 @@ pub fn deinit(zig_object: *ZigObject, gpa: std.mem.Allocator) void {
if (zig_object.dwarf) |*dwarf| {
dwarf.deinit();
}
+ gpa.free(zig_object.path);
zig_object.* = undefined;
}
@@ -531,32 +557,31 @@ pub fn addOrUpdateImport(
/// such as an exported or imported symbol.
/// If the symbol does not yet exist, creates a new one symbol instead
/// and then returns the index to it.
-pub fn getGlobalSymbol(zig_object: *ZigObject, wasm_file: *Wasm, name: []const u8) !u32 {
- const gpa = wasm_file.base.comp.gpa;
+pub fn getGlobalSymbol(zig_object: *ZigObject, gpa: std.mem.Allocator, name: []const u8, tag: Symbol.Tag) !u32 {
const name_index = try zig_object.string_table.insert(gpa, name);
const gop = try zig_object.global_syms.getOrPut(gpa, name_index);
if (gop.found_existing) {
- return gop.value_ptr.index;
+ return gop.value_ptr.*;
}
var symbol: Symbol = .{
.name = name_index,
.flags = 0,
- .index = undefined, // index to type will be set after merging function symbols
- .tag = .function,
- .virtual_address = undefined,
+ .index = undefined, // index to type will be set after merging symbols
+ .tag = tag,
+ .virtual_address = std.math.maxInt(u32),
};
symbol.setGlobal(true);
symbol.setUndefined(true);
- const sym_index = if (zig_object.symbol.popOrNull()) |index| index else blk: {
+ const sym_index = if (zig_object.symbols_free_list.popOrNull()) |index| index else blk: {
const index: u32 = @intCast(zig_object.symbols.items.len);
try zig_object.symbols.ensureUnusedCapacity(gpa, 1);
zig_object.symbols.items.len += 1;
break :blk index;
};
zig_object.symbols.items[sym_index] = symbol;
- gop.value_ptr.* = .{ .index = sym_index, .file = null };
+ gop.value_ptr.* = sym_index;
return sym_index;
}
src/link/Wasm.zig
@@ -1,37 +1,41 @@
const Wasm = @This();
const std = @import("std");
-const builtin = @import("builtin");
-const mem = std.mem;
-const Allocator = std.mem.Allocator;
+
const assert = std.debug.assert;
+const build_options = @import("build_options");
+const builtin = @import("builtin");
+const codegen = @import("../codegen.zig");
const fs = std.fs;
const leb = std.leb;
-const log = std.log.scoped(.link);
-
-pub const Atom = @import("Wasm/Atom.zig");
-const Dwarf = @import("Dwarf.zig");
-const Module = @import("../Module.zig");
-const InternPool = @import("../InternPool.zig");
-const Compilation = @import("../Compilation.zig");
-const CodeGen = @import("../arch/wasm/CodeGen.zig");
-const codegen = @import("../codegen.zig");
const link = @import("../link.zig");
const lldMain = @import("../main.zig").lldMain;
+const log = std.log.scoped(.link);
+const mem = std.mem;
const trace = @import("../tracy.zig").trace;
-const build_options = @import("build_options");
+const types = @import("Wasm/types.zig");
const wasi_libc = @import("../wasi_libc.zig");
-const Cache = std.Build.Cache;
-const Type = @import("../type.zig").Type;
-const Value = @import("../Value.zig");
-const TypedValue = @import("../TypedValue.zig");
-const LlvmObject = @import("../codegen/llvm.zig").Object;
+
const Air = @import("../Air.zig");
+const Allocator = std.mem.Allocator;
+const Archive = @import("Wasm/Archive.zig");
+const Cache = std.Build.Cache;
+const CodeGen = @import("../arch/wasm/CodeGen.zig");
+const Compilation = @import("../Compilation.zig");
+const Dwarf = @import("Dwarf.zig");
+const File = @import("Wasm/file.zig").File;
+const InternPool = @import("../InternPool.zig");
const Liveness = @import("../Liveness.zig");
-const Symbol = @import("Wasm/Symbol.zig");
+const LlvmObject = @import("../codegen/llvm.zig").Object;
+const Module = @import("../Module.zig");
const Object = @import("Wasm/Object.zig");
-const Archive = @import("Wasm/Archive.zig");
-const types = @import("Wasm/types.zig");
+const Symbol = @import("Wasm/Symbol.zig");
+const Type = @import("../type.zig").Type;
+const TypedValue = @import("../TypedValue.zig");
+const Value = @import("../value.zig").Value;
+const ZigObject = @import("Wasm/ZigObject.zig");
+
+pub const Atom = @import("Wasm/Atom.zig");
pub const Relocation = types.Relocation;
pub const base_tag: link.File.Tag = .wasm;
@@ -57,6 +61,11 @@ export_table: bool,
name: []const u8,
/// If this is not null, an object file is created by LLVM and linked with LLD afterwards.
llvm_object: ?*LlvmObject = null,
+/// The file index of a `ZigObject`. This will only contain a valid index when a zcu exists,
+/// and the chosen backend is the Wasm backend.
+zig_object_index: File.Index = .null,
+/// List of relocatable files to be linked into the final binary.
+files: std.MultiArrayList(File.Entry) = .{},
/// When importing objects from the host environment, a name must be supplied.
/// LLVM uses "env" by default when none is given. This would be a good default for Zig
/// to support existing code.
@@ -556,9 +565,27 @@ pub fn createEmpty(
}
}
+ if (comp.module) |zcu| {
+ if (!use_llvm) {
+ const index: File.Index = @enumFromInt(wasm.files.len);
+ var zig_object: ZigObject = .{
+ .path = try std.fmt.allocPrint(gpa, "{s}.o", .{std.fs.path.stem(zcu.main_mod.root_src_path)}),
+ .stack_pointer_sym = undefined,
+ };
+ try zig_object.init(wasm);
+ try wasm.files.append(gpa, .{ .zig_object = zig_object });
+ wasm.zig_object_index = index;
+ }
+ }
+
return wasm;
}
+fn zigObjectPtr(wasm: *Wasm) ?*ZigObject {
+ if (wasm.zig_object_index == .null) return null;
+ return &wasm.files.items(.data)[@intFromEnum(wasm.zig_object_index)].zig_object;
+}
+
/// For a given name, creates a new global synthetic symbol.
/// Leaves index undefined and the default flags (0).
fn createSyntheticSymbol(wasm: *Wasm, name: []const u8, tag: Symbol.Tag) !SymbolLoc {