mirror of
https://github.com/ziglang/zig.git
synced 2025-12-06 06:13:07 +00:00
wasm: Call generateSymbol for updateDecl
To unify the wasm backend with the other backends, we will now call `generateSymbol` to lower a Decl into bytes. This means we also have to change some function signatures to comply with the linker interface. Since the general purpose generateSymbol is less featureful than wasm's, some tests are temporarily disabled.
This commit is contained in:
parent
12e636c24e
commit
5a45fe2dba
@ -1318,13 +1318,14 @@ pub const DeclGen = struct {
|
||||
if (decl.link.wasm.sym_index == 0) {
|
||||
try writer.writeIntLittle(u32, 0);
|
||||
} else {
|
||||
try writer.writeIntLittle(u32, try self.bin_file.getDeclVAddr(
|
||||
self.decl, // parent decl that owns the atom of the symbol
|
||||
self.symbol_index, // source symbol index
|
||||
decl, // target decl that contains the target symbol
|
||||
@intCast(u32, self.code.items.len), // offset
|
||||
@intCast(u32, offset), // addend
|
||||
));
|
||||
try writer.writeIntLittle(u32, @intCast(u32, try self.bin_file.getDeclVAddr(
|
||||
decl,
|
||||
.{
|
||||
.parent_atom_index = self.symbol_index,
|
||||
.offset = self.code.items.len,
|
||||
.addend = @intCast(u32, offset),
|
||||
},
|
||||
)));
|
||||
}
|
||||
return Result{ .appended = {} };
|
||||
}
|
||||
@ -1809,8 +1810,12 @@ fn airCall(self: *Self, inst: Air.Inst.Index) InnerError!WValue {
|
||||
|
||||
if (func_val.castTag(.function)) |func| {
|
||||
break :blk func.data.owner_decl;
|
||||
} else if (func_val.castTag(.extern_fn)) |ext_fn| {
|
||||
break :blk ext_fn.data.owner_decl;
|
||||
} else if (func_val.castTag(.extern_fn)) |extern_fn| {
|
||||
const ext_decl = extern_fn.data.owner_decl;
|
||||
var func_type = try genFunctype(self.gpa, ext_decl.ty, self.target);
|
||||
defer func_type.deinit(self.gpa);
|
||||
ext_decl.fn_link.wasm.type_index = try self.bin_file.putOrGetFuncType(func_type);
|
||||
break :blk ext_decl;
|
||||
} else if (func_val.castTag(.decl_ref)) |decl_ref| {
|
||||
break :blk decl_ref.data;
|
||||
}
|
||||
|
||||
@ -702,7 +702,7 @@ pub const File = struct {
|
||||
.macho => return @fieldParentPtr(MachO, "base", base).getDeclVAddr(decl, reloc_info),
|
||||
.plan9 => return @fieldParentPtr(Plan9, "base", base).getDeclVAddr(decl, reloc_info),
|
||||
.c => unreachable,
|
||||
.wasm => unreachable,
|
||||
.wasm => return @fieldParentPtr(Wasm, "base", base).getDeclVAddr(decl, reloc_info),
|
||||
.spirv => unreachable,
|
||||
.nvptx => unreachable,
|
||||
}
|
||||
|
||||
@ -14,6 +14,7 @@ const Atom = @import("Wasm/Atom.zig");
|
||||
const Module = @import("../Module.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 trace = @import("../tracy.zig").trace;
|
||||
@ -488,10 +489,8 @@ pub fn allocateDeclIndexes(self: *Wasm, decl: *Module.Decl) !void {
|
||||
self.symbols.appendAssumeCapacity(symbol);
|
||||
}
|
||||
|
||||
try self.resolved_symbols.putNoClobber(self.base.allocator, .{
|
||||
.index = atom.sym_index,
|
||||
.file = null,
|
||||
}, {});
|
||||
try self.resolved_symbols.putNoClobber(self.base.allocator, atom.symbolLoc(), {});
|
||||
try self.symbol_atom.putNoClobber(self.base.allocator, atom.symbolLoc(), atom);
|
||||
}
|
||||
|
||||
pub fn updateFunc(self: *Wasm, module: *Module, func: *Module.Fn, air: Air, liveness: Liveness) !void {
|
||||
@ -506,7 +505,7 @@ pub fn updateFunc(self: *Wasm, module: *Module, func: *Module.Fn, air: Air, live
|
||||
|
||||
decl.link.wasm.clear();
|
||||
|
||||
var codegen: CodeGen = .{
|
||||
var codegen_: CodeGen = .{
|
||||
.gpa = self.base.allocator,
|
||||
.air = air,
|
||||
.liveness = liveness,
|
||||
@ -519,18 +518,18 @@ pub fn updateFunc(self: *Wasm, module: *Module, func: *Module.Fn, air: Air, live
|
||||
.bin_file = self,
|
||||
.module = module,
|
||||
};
|
||||
defer codegen.deinit();
|
||||
defer codegen_.deinit();
|
||||
|
||||
// generate the 'code' section for the function declaration
|
||||
codegen.genFunc() catch |err| switch (err) {
|
||||
codegen_.genFunc() catch |err| switch (err) {
|
||||
error.CodegenFail => {
|
||||
decl.analysis = .codegen_failure;
|
||||
try module.failed_decls.put(module.gpa, decl, codegen.err_msg);
|
||||
try module.failed_decls.put(module.gpa, decl, codegen_.err_msg);
|
||||
return;
|
||||
},
|
||||
else => |e| return e,
|
||||
};
|
||||
return self.finishUpdateDecl(decl, codegen.code.items);
|
||||
return self.finishUpdateDecl(decl, codegen_.code.items);
|
||||
}
|
||||
|
||||
// Generate code for the Decl, storing it in memory to be later written to
|
||||
@ -547,31 +546,37 @@ pub fn updateDecl(self: *Wasm, module: *Module, decl: *Module.Decl) !void {
|
||||
|
||||
decl.link.wasm.clear();
|
||||
|
||||
if (decl.isExtern()) {
|
||||
return self.addOrUpdateImport(decl);
|
||||
}
|
||||
|
||||
if (decl.val.castTag(.function)) |_| {
|
||||
return;
|
||||
} else if (decl.val.castTag(.extern_fn)) |_| {
|
||||
return;
|
||||
}
|
||||
const val = if (decl.val.castTag(.variable)) |payload| payload.data.init else decl.val;
|
||||
|
||||
var code_writer = std.ArrayList(u8).init(self.base.allocator);
|
||||
defer code_writer.deinit();
|
||||
var decl_gen: CodeGen.DeclGen = .{
|
||||
.gpa = self.base.allocator,
|
||||
.decl = decl,
|
||||
.symbol_index = decl.link.wasm.sym_index,
|
||||
.bin_file = self,
|
||||
.err_msg = undefined,
|
||||
.code = &code_writer,
|
||||
.module = module,
|
||||
};
|
||||
|
||||
// generate the 'code' section for the function declaration
|
||||
const result = decl_gen.genDecl() catch |err| switch (err) {
|
||||
error.CodegenFail => {
|
||||
const res = try codegen.generateSymbol(
|
||||
&self.base,
|
||||
decl.srcLoc(),
|
||||
.{ .ty = decl.ty, .val = val },
|
||||
&code_writer,
|
||||
.none,
|
||||
.{ .parent_atom_index = decl.link.wasm.sym_index },
|
||||
);
|
||||
|
||||
const code = switch (res) {
|
||||
.externally_managed => |x| x,
|
||||
.appended => code_writer.items,
|
||||
.fail => |em| {
|
||||
decl.analysis = .codegen_failure;
|
||||
try module.failed_decls.put(module.gpa, decl, decl_gen.err_msg);
|
||||
try module.failed_decls.put(module.gpa, decl, em);
|
||||
return;
|
||||
},
|
||||
else => |e| return e,
|
||||
};
|
||||
|
||||
const code = switch (result) {
|
||||
.externally_managed => |data| data,
|
||||
.appended => code_writer.items,
|
||||
};
|
||||
|
||||
return self.finishUpdateDecl(decl, code);
|
||||
@ -624,10 +629,8 @@ pub fn lowerUnnamedConst(self: *Wasm, decl: *Module.Decl, tv: TypedValue) !u32 {
|
||||
atom.sym_index = @intCast(u32, self.symbols.items.len);
|
||||
self.symbols.appendAssumeCapacity(symbol);
|
||||
}
|
||||
try self.resolved_symbols.putNoClobber(self.base.allocator, .{
|
||||
.file = null,
|
||||
.index = atom.sym_index,
|
||||
}, {});
|
||||
try self.resolved_symbols.putNoClobber(self.base.allocator, atom.symbolLoc(), {});
|
||||
try self.symbol_atom.putNoClobber(self.base.allocator, atom.symbolLoc(), atom);
|
||||
|
||||
var value_bytes = std.ArrayList(u8).init(self.base.allocator);
|
||||
defer value_bytes.deinit();
|
||||
@ -665,35 +668,31 @@ pub fn lowerUnnamedConst(self: *Wasm, decl: *Module.Decl, tv: TypedValue) !u32 {
|
||||
/// Returns the given pointer address
|
||||
pub fn getDeclVAddr(
|
||||
self: *Wasm,
|
||||
decl: *Module.Decl,
|
||||
symbol_index: u32,
|
||||
target_decl: *Module.Decl,
|
||||
offset: u32,
|
||||
addend: u32,
|
||||
) !u32 {
|
||||
const target_symbol_index = target_decl.link.wasm.sym_index;
|
||||
decl: *const Module.Decl,
|
||||
reloc_info: link.File.RelocInfo,
|
||||
) !u64 {
|
||||
const target_symbol_index = decl.link.wasm.sym_index;
|
||||
assert(target_symbol_index != 0);
|
||||
assert(symbol_index != 0);
|
||||
|
||||
const atom = decl.link.wasm.symbolAtom(symbol_index);
|
||||
assert(reloc_info.parent_atom_index != 0);
|
||||
const atom = self.symbol_atom.get(.{ .file = null, .index = reloc_info.parent_atom_index }).?;
|
||||
const is_wasm32 = self.base.options.target.cpu.arch == .wasm32;
|
||||
if (target_decl.ty.zigTypeTag() == .Fn) {
|
||||
assert(addend == 0); // addend not allowed for function relocations
|
||||
if (decl.ty.zigTypeTag() == .Fn) {
|
||||
assert(reloc_info.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.
|
||||
// They are instead stored in a function table which are called by index.
|
||||
try self.addTableFunction(target_symbol_index);
|
||||
try atom.relocs.append(self.base.allocator, .{
|
||||
.index = target_symbol_index,
|
||||
.offset = offset,
|
||||
.offset = @intCast(u32, reloc_info.offset),
|
||||
.relocation_type = if (is_wasm32) .R_WASM_TABLE_INDEX_I32 else .R_WASM_TABLE_INDEX_I64,
|
||||
});
|
||||
} else {
|
||||
try atom.relocs.append(self.base.allocator, .{
|
||||
.index = target_symbol_index,
|
||||
.offset = offset,
|
||||
.offset = @intCast(u32, reloc_info.offset),
|
||||
.relocation_type = if (is_wasm32) .R_WASM_MEMORY_ADDR_I32 else .R_WASM_MEMORY_ADDR_I64,
|
||||
.addend = addend,
|
||||
.addend = reloc_info.addend,
|
||||
});
|
||||
}
|
||||
// we do not know the final address at this point,
|
||||
@ -823,12 +822,14 @@ pub fn freeDecl(self: *Wasm, decl: *Module.Decl) void {
|
||||
local_symbol.tag = .dead; // also for any local symbol
|
||||
self.symbols_free_list.append(self.base.allocator, local_atom.sym_index) catch {};
|
||||
assert(self.resolved_symbols.swapRemove(local_atom.symbolLoc()));
|
||||
assert(self.symbol_atom.remove(local_atom.symbolLoc()));
|
||||
}
|
||||
|
||||
if (decl.isExtern()) {
|
||||
assert(self.imports.remove(atom.symbolLoc()));
|
||||
}
|
||||
assert(self.resolved_symbols.swapRemove(atom.symbolLoc()));
|
||||
assert(self.symbol_atom.remove(atom.symbolLoc()));
|
||||
atom.deinit(self.base.allocator);
|
||||
}
|
||||
|
||||
@ -988,7 +989,6 @@ fn allocateAtoms(self: *Wasm) !void {
|
||||
atom.size,
|
||||
});
|
||||
offset += atom.size;
|
||||
try self.symbol_atom.putNoClobber(self.base.allocator, symbol_loc, atom);
|
||||
atom = atom.next orelse break;
|
||||
}
|
||||
}
|
||||
|
||||
@ -861,6 +861,7 @@ pub fn parseIntoAtoms(self: *Object, gpa: Allocator, object_index: u16, wasm_bin
|
||||
}
|
||||
|
||||
try atom.code.appendSlice(gpa, relocatable_data.data[0..relocatable_data.size]);
|
||||
try wasm_bin.symbol_atom.putNoClobber(gpa, atom.symbolLoc(), atom);
|
||||
|
||||
const segment: *Wasm.Segment = &wasm_bin.segments.items[final_index];
|
||||
segment.alignment = std.math.max(segment.alignment, atom.alignment);
|
||||
|
||||
@ -18,5 +18,6 @@ test "reference a global threadlocal variable" {
|
||||
if (builtin.zig_backend == .stage2_c) return error.SkipZigTest;
|
||||
if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
|
||||
if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest;
|
||||
if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest;
|
||||
_ = nrfx_uart_rx(&g_uart0);
|
||||
}
|
||||
|
||||
@ -1060,6 +1060,7 @@ test "compile time int to ptr of function" {
|
||||
if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO
|
||||
if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
|
||||
if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO
|
||||
if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO
|
||||
|
||||
try foobar(FUNCTION_CONSTANT);
|
||||
}
|
||||
|
||||
@ -209,6 +209,7 @@ test "compile time slice of pointer to hard coded address" {
|
||||
if (builtin.zig_backend == .stage1) return error.SkipZigTest;
|
||||
if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
|
||||
if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest;
|
||||
if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest;
|
||||
|
||||
try expect(@ptrToInt(x) == 0x1000);
|
||||
try expect(x.len == 0x500);
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user