aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorLuuk de Gram <luuk@degram.dev>2022-02-23 22:45:51 +0100
committerLuuk de Gram <luuk@degram.dev>2022-02-25 09:33:15 +0100
commitf4adb53bcfff18c24758bf4ea2968efd17911e02 (patch)
treee8af179bb1a842b1e7dbf6fa63614583bb359667 /src
parent27eb42c15e4e9ab547eaf02cca8810cc0e10e6bf (diff)
downloadzig-f4adb53bcfff18c24758bf4ea2968efd17911e02.tar.gz
zig-f4adb53bcfff18c24758bf4ea2968efd17911e02.zip
wasm: Refactor lowerUnnamedConst
Rather than ping ponging between codegen and the linker to generate the symbols/atoms for a local constant and its relocations. We now create all neccesary objects within the linker. This simplifies the code as we can now simply call `lowerUnnamedConst` from anywhere in codegen, allowing us to further improve lowering constants into .rodata so we do not have to sacrifice lowering certain types such as decl_ref's where its type is a slice.
Diffstat (limited to 'src')
-rw-r--r--src/arch/wasm/CodeGen.zig34
-rw-r--r--src/link/Wasm.zig63
-rw-r--r--src/link/Wasm/Atom.zig3
3 files changed, 55 insertions, 45 deletions
diff --git a/src/arch/wasm/CodeGen.zig b/src/arch/wasm/CodeGen.zig
index 888e78f8c2..01b297d9e8 100644
--- a/src/arch/wasm/CodeGen.zig
+++ b/src/arch/wasm/CodeGen.zig
@@ -645,31 +645,8 @@ fn resolveInst(self: *Self, ref: Air.Inst.Ref) InnerError!WValue {
// In the other cases, we will simply lower the constant to a value that fits
// into a single local (such as a pointer, integer, bool, etc).
const result = if (isByRef(ty, self.target)) blk: {
- var value_bytes = std.ArrayList(u8).init(self.gpa);
- defer value_bytes.deinit();
-
- var decl_gen: DeclGen = .{
- .bin_file = self.bin_file,
- .decl = self.decl,
- .err_msg = undefined,
- .gpa = self.gpa,
- .module = self.module,
- .code = &value_bytes,
- .symbol_index = try self.bin_file.createLocalSymbol(self.decl, ty),
- };
- const result = decl_gen.genTypedValue(ty, val) catch |err| {
- // When a codegen error occured, take ownership of the error message
- if (err == error.CodegenFail) {
- self.err_msg = decl_gen.err_msg;
- }
- return err;
- };
- const code = switch (result) {
- .appended => value_bytes.items,
- .externally_managed => |data| data,
- };
- try self.bin_file.updateLocalSymbolCode(self.decl, decl_gen.symbol_index, code);
- break :blk WValue{ .memory = decl_gen.symbol_index };
+ const sym_index = try self.bin_file.lowerUnnamedConst(self.decl, .{ .ty = ty, .val = val });
+ break :blk WValue{ .memory = sym_index };
} else try self.lowerConstant(val, ty);
gop.value_ptr.* = result;
@@ -986,7 +963,7 @@ pub const DeclGen = struct {
}
/// Generates the wasm bytecode for the declaration belonging to `Context`
- fn genTypedValue(self: *DeclGen, ty: Type, val: Value) InnerError!Result {
+ pub fn genTypedValue(self: *DeclGen, ty: Type, val: Value) InnerError!Result {
log.debug("genTypedValue: ty = {}, val = {}", .{ ty, val });
const writer = self.code.writer();
@@ -1324,10 +1301,9 @@ pub const DeclGen = struct {
try writer.writeIntLittle(u32, 0);
} else {
try writer.writeIntLittle(u32, try self.bin_file.getDeclVAddr(
- self.decl, // The decl containing the source symbol index
- decl.ty, // type we generate the address of
+ self.decl, // parent decl that owns the atom of the symbol
self.symbol_index, // source symbol index
- decl.link.wasm.sym_index, // target symbol index
+ decl, // target decl that contains the target symbol
@intCast(u32, self.code.items.len), // offset
@intCast(u32, offset), // addend
));
diff --git a/src/link/Wasm.zig b/src/link/Wasm.zig
index 63de591297..a9cf045072 100644
--- a/src/link/Wasm.zig
+++ b/src/link/Wasm.zig
@@ -21,6 +21,7 @@ const build_options = @import("build_options");
const wasi_libc = @import("../wasi_libc.zig");
const Cache = @import("../Cache.zig");
const Type = @import("../type.zig").Type;
+const TypedValue = @import("../TypedValue.zig");
const LlvmObject = @import("../codegen/llvm.zig").Object;
const Air = @import("../Air.zig");
const Liveness = @import("../Liveness.zig");
@@ -497,10 +498,13 @@ fn finishUpdateDecl(self: *Wasm, decl: *Module.Decl, code: []const u8) !void {
try atom.code.appendSlice(self.base.allocator, code);
}
-/// Creates a new local symbol for a given type (and its bytes it's represented by)
-/// and then append it as a 'contained' atom onto the Decl.
-pub fn createLocalSymbol(self: *Wasm, decl: *Module.Decl, ty: Type) !u32 {
- assert(ty.zigTypeTag() != .Fn); // cannot create local symbols for functions
+/// Lowers a constant typed value to a local symbol and atom.
+/// Returns the symbol index of the local
+/// The given `decl` is the parent decl whom owns the constant.
+pub fn lowerUnnamedConst(self: *Wasm, decl: *Module.Decl, tv: TypedValue) !u32 {
+ assert(tv.ty.zigTypeTag() != .Fn); // cannot create local symbols for functions
+
+ // Create and initialize a new local symbol and atom
const local_index = decl.link.wasm.locals.items.len;
const name = try std.fmt.allocPrintZ(self.base.allocator, "__unnamed_{s}_{d}", .{ decl.name, local_index });
var symbol: Symbol = .{
@@ -510,10 +514,10 @@ pub fn createLocalSymbol(self: *Wasm, decl: *Module.Decl, ty: Type) !u32 {
.index = undefined,
};
symbol.setFlag(.WASM_SYM_BINDING_LOCAL);
- symbol.setFlag(.WASM_SYM_VISIBILITY_HIDDEN);
- var atom = Atom.empty;
- atom.alignment = ty.abiAlignment(self.base.options.target);
+ const atom = try decl.link.wasm.locals.addOne(self.base.allocator);
+ atom.* = Atom.empty;
+ atom.alignment = tv.ty.abiAlignment(self.base.options.target);
try self.symbols.ensureUnusedCapacity(self.base.allocator, 1);
if (self.symbols_free_list.popOrNull()) |index| {
@@ -528,14 +532,36 @@ pub fn createLocalSymbol(self: *Wasm, decl: *Module.Decl, ty: Type) !u32 {
.index = atom.sym_index,
}, {});
- try decl.link.wasm.locals.append(self.base.allocator, atom);
- return atom.sym_index;
-}
+ var value_bytes = std.ArrayList(u8).init(self.base.allocator);
+ defer value_bytes.deinit();
+
+ const module = self.base.options.module.?;
+ var decl_gen: CodeGen.DeclGen = .{
+ .bin_file = self,
+ .decl = decl,
+ .err_msg = undefined,
+ .gpa = self.base.allocator,
+ .module = module,
+ .code = &value_bytes,
+ .symbol_index = atom.sym_index,
+ };
+
+ const result = decl_gen.genTypedValue(tv.ty, tv.val) catch |err| switch (err) {
+ error.CodegenFail => {
+ decl.analysis = .codegen_failure;
+ try module.failed_decls.put(module.gpa, decl, decl_gen.err_msg);
+ return error.AnalysisFail;
+ },
+ else => |e| return e,
+ };
+ const code = switch (result) {
+ .appended => value_bytes.items,
+ .externally_managed => |data| data,
+ };
-pub fn updateLocalSymbolCode(self: *Wasm, decl: *Module.Decl, symbol_index: u32, code: []const u8) !void {
- const atom = decl.link.wasm.symbolAtom(symbol_index);
atom.size = @intCast(u32, code.len);
try atom.code.appendSlice(self.base.allocator, code);
+ return atom.sym_index;
}
/// For a given decl, find the given symbol index's atom, and create a relocation for the type.
@@ -543,16 +569,18 @@ pub fn updateLocalSymbolCode(self: *Wasm, decl: *Module.Decl, symbol_index: u32,
pub fn getDeclVAddr(
self: *Wasm,
decl: *Module.Decl,
- ty: Type,
symbol_index: u32,
- target_symbol_index: u32,
+ target_decl: *Module.Decl,
offset: u32,
addend: u32,
) !u32 {
+ const target_symbol_index = target_decl.link.wasm.sym_index;
assert(target_symbol_index != 0);
+ assert(symbol_index != 0);
+
const atom = decl.link.wasm.symbolAtom(symbol_index);
const is_wasm32 = self.base.options.target.cpu.arch == .wasm32;
- if (ty.zigTypeTag() == .Fn) {
+ if (target_decl.ty.zigTypeTag() == .Fn) {
assert(addend == 0); // addend not allowed for function relocations
// We found a function pointer, so add it to our table,
// as function pointers are not allowed to be stored inside the data section.
@@ -1192,6 +1220,11 @@ fn resetState(self: *Wasm) void {
const atom = &decl.*.link.wasm;
atom.next = null;
atom.prev = null;
+
+ for (atom.locals.items) |*local_atom| {
+ local_atom.next = null;
+ local_atom.prev = null;
+ }
}
self.functions.clearRetainingCapacity();
self.exports.clearRetainingCapacity();
diff --git a/src/link/Wasm/Atom.zig b/src/link/Wasm/Atom.zig
index 683a18ba1f..d7cf43b2da 100644
--- a/src/link/Wasm/Atom.zig
+++ b/src/link/Wasm/Atom.zig
@@ -170,9 +170,10 @@ fn relocationValue(self: Atom, relocation: types.Relocation, wasm_bin: *const Wa
.R_WASM_MEMORY_ADDR_SLEB,
.R_WASM_MEMORY_ADDR_SLEB64,
=> {
- if (symbol.isUndefined() and (symbol.tag == .data or symbol.isWeak())) {
+ if (symbol.isUndefined() and symbol.isWeak()) {
return 0;
}
+ std.debug.assert(symbol.tag == .data);
const merge_segment = wasm_bin.base.options.output_mode != .Obj;
const segment_name = wasm_bin.segment_info.items[symbol.index].outputName(merge_segment);
const atom_index = wasm_bin.data_segments.get(segment_name).?;