mirror of
https://github.com/ziglang/zig.git
synced 2025-12-06 14:23:09 +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) {
|
if (decl.link.wasm.sym_index == 0) {
|
||||||
try writer.writeIntLittle(u32, 0);
|
try writer.writeIntLittle(u32, 0);
|
||||||
} else {
|
} else {
|
||||||
try writer.writeIntLittle(u32, try self.bin_file.getDeclVAddr(
|
try writer.writeIntLittle(u32, @intCast(u32, try self.bin_file.getDeclVAddr(
|
||||||
self.decl, // parent decl that owns the atom of the symbol
|
decl,
|
||||||
self.symbol_index, // source symbol index
|
.{
|
||||||
decl, // target decl that contains the target symbol
|
.parent_atom_index = self.symbol_index,
|
||||||
@intCast(u32, self.code.items.len), // offset
|
.offset = self.code.items.len,
|
||||||
@intCast(u32, offset), // addend
|
.addend = @intCast(u32, offset),
|
||||||
));
|
},
|
||||||
|
)));
|
||||||
}
|
}
|
||||||
return Result{ .appended = {} };
|
return Result{ .appended = {} };
|
||||||
}
|
}
|
||||||
@ -1809,8 +1810,12 @@ fn airCall(self: *Self, inst: Air.Inst.Index) InnerError!WValue {
|
|||||||
|
|
||||||
if (func_val.castTag(.function)) |func| {
|
if (func_val.castTag(.function)) |func| {
|
||||||
break :blk func.data.owner_decl;
|
break :blk func.data.owner_decl;
|
||||||
} else if (func_val.castTag(.extern_fn)) |ext_fn| {
|
} else if (func_val.castTag(.extern_fn)) |extern_fn| {
|
||||||
break :blk ext_fn.data.owner_decl;
|
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| {
|
} else if (func_val.castTag(.decl_ref)) |decl_ref| {
|
||||||
break :blk decl_ref.data;
|
break :blk decl_ref.data;
|
||||||
}
|
}
|
||||||
|
|||||||
@ -702,7 +702,7 @@ pub const File = struct {
|
|||||||
.macho => return @fieldParentPtr(MachO, "base", base).getDeclVAddr(decl, reloc_info),
|
.macho => return @fieldParentPtr(MachO, "base", base).getDeclVAddr(decl, reloc_info),
|
||||||
.plan9 => return @fieldParentPtr(Plan9, "base", base).getDeclVAddr(decl, reloc_info),
|
.plan9 => return @fieldParentPtr(Plan9, "base", base).getDeclVAddr(decl, reloc_info),
|
||||||
.c => unreachable,
|
.c => unreachable,
|
||||||
.wasm => unreachable,
|
.wasm => return @fieldParentPtr(Wasm, "base", base).getDeclVAddr(decl, reloc_info),
|
||||||
.spirv => unreachable,
|
.spirv => unreachable,
|
||||||
.nvptx => unreachable,
|
.nvptx => unreachable,
|
||||||
}
|
}
|
||||||
|
|||||||
@ -14,6 +14,7 @@ const Atom = @import("Wasm/Atom.zig");
|
|||||||
const Module = @import("../Module.zig");
|
const Module = @import("../Module.zig");
|
||||||
const Compilation = @import("../Compilation.zig");
|
const Compilation = @import("../Compilation.zig");
|
||||||
const CodeGen = @import("../arch/wasm/CodeGen.zig");
|
const CodeGen = @import("../arch/wasm/CodeGen.zig");
|
||||||
|
const codegen = @import("../codegen.zig");
|
||||||
const link = @import("../link.zig");
|
const link = @import("../link.zig");
|
||||||
const lldMain = @import("../main.zig").lldMain;
|
const lldMain = @import("../main.zig").lldMain;
|
||||||
const trace = @import("../tracy.zig").trace;
|
const trace = @import("../tracy.zig").trace;
|
||||||
@ -488,10 +489,8 @@ pub fn allocateDeclIndexes(self: *Wasm, decl: *Module.Decl) !void {
|
|||||||
self.symbols.appendAssumeCapacity(symbol);
|
self.symbols.appendAssumeCapacity(symbol);
|
||||||
}
|
}
|
||||||
|
|
||||||
try self.resolved_symbols.putNoClobber(self.base.allocator, .{
|
try self.resolved_symbols.putNoClobber(self.base.allocator, atom.symbolLoc(), {});
|
||||||
.index = atom.sym_index,
|
try self.symbol_atom.putNoClobber(self.base.allocator, atom.symbolLoc(), atom);
|
||||||
.file = null,
|
|
||||||
}, {});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn updateFunc(self: *Wasm, module: *Module, func: *Module.Fn, air: Air, liveness: Liveness) !void {
|
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();
|
decl.link.wasm.clear();
|
||||||
|
|
||||||
var codegen: CodeGen = .{
|
var codegen_: CodeGen = .{
|
||||||
.gpa = self.base.allocator,
|
.gpa = self.base.allocator,
|
||||||
.air = air,
|
.air = air,
|
||||||
.liveness = liveness,
|
.liveness = liveness,
|
||||||
@ -519,18 +518,18 @@ pub fn updateFunc(self: *Wasm, module: *Module, func: *Module.Fn, air: Air, live
|
|||||||
.bin_file = self,
|
.bin_file = self,
|
||||||
.module = module,
|
.module = module,
|
||||||
};
|
};
|
||||||
defer codegen.deinit();
|
defer codegen_.deinit();
|
||||||
|
|
||||||
// generate the 'code' section for the function declaration
|
// generate the 'code' section for the function declaration
|
||||||
codegen.genFunc() catch |err| switch (err) {
|
codegen_.genFunc() catch |err| switch (err) {
|
||||||
error.CodegenFail => {
|
error.CodegenFail => {
|
||||||
decl.analysis = .codegen_failure;
|
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;
|
return;
|
||||||
},
|
},
|
||||||
else => |e| return e,
|
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
|
// 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();
|
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);
|
var code_writer = std.ArrayList(u8).init(self.base.allocator);
|
||||||
defer code_writer.deinit();
|
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 res = try codegen.generateSymbol(
|
||||||
const result = decl_gen.genDecl() catch |err| switch (err) {
|
&self.base,
|
||||||
error.CodegenFail => {
|
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;
|
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;
|
return;
|
||||||
},
|
},
|
||||||
else => |e| return e,
|
|
||||||
};
|
|
||||||
|
|
||||||
const code = switch (result) {
|
|
||||||
.externally_managed => |data| data,
|
|
||||||
.appended => code_writer.items,
|
|
||||||
};
|
};
|
||||||
|
|
||||||
return self.finishUpdateDecl(decl, code);
|
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);
|
atom.sym_index = @intCast(u32, self.symbols.items.len);
|
||||||
self.symbols.appendAssumeCapacity(symbol);
|
self.symbols.appendAssumeCapacity(symbol);
|
||||||
}
|
}
|
||||||
try self.resolved_symbols.putNoClobber(self.base.allocator, .{
|
try self.resolved_symbols.putNoClobber(self.base.allocator, atom.symbolLoc(), {});
|
||||||
.file = null,
|
try self.symbol_atom.putNoClobber(self.base.allocator, atom.symbolLoc(), atom);
|
||||||
.index = atom.sym_index,
|
|
||||||
}, {});
|
|
||||||
|
|
||||||
var value_bytes = std.ArrayList(u8).init(self.base.allocator);
|
var value_bytes = std.ArrayList(u8).init(self.base.allocator);
|
||||||
defer value_bytes.deinit();
|
defer value_bytes.deinit();
|
||||||
@ -665,35 +668,31 @@ pub fn lowerUnnamedConst(self: *Wasm, decl: *Module.Decl, tv: TypedValue) !u32 {
|
|||||||
/// Returns the given pointer address
|
/// Returns the given pointer address
|
||||||
pub fn getDeclVAddr(
|
pub fn getDeclVAddr(
|
||||||
self: *Wasm,
|
self: *Wasm,
|
||||||
decl: *Module.Decl,
|
decl: *const Module.Decl,
|
||||||
symbol_index: u32,
|
reloc_info: link.File.RelocInfo,
|
||||||
target_decl: *Module.Decl,
|
) !u64 {
|
||||||
offset: u32,
|
const target_symbol_index = decl.link.wasm.sym_index;
|
||||||
addend: u32,
|
|
||||||
) !u32 {
|
|
||||||
const target_symbol_index = target_decl.link.wasm.sym_index;
|
|
||||||
assert(target_symbol_index != 0);
|
assert(target_symbol_index != 0);
|
||||||
assert(symbol_index != 0);
|
assert(reloc_info.parent_atom_index != 0);
|
||||||
|
const atom = self.symbol_atom.get(.{ .file = null, .index = reloc_info.parent_atom_index }).?;
|
||||||
const atom = decl.link.wasm.symbolAtom(symbol_index);
|
|
||||||
const is_wasm32 = self.base.options.target.cpu.arch == .wasm32;
|
const is_wasm32 = self.base.options.target.cpu.arch == .wasm32;
|
||||||
if (target_decl.ty.zigTypeTag() == .Fn) {
|
if (decl.ty.zigTypeTag() == .Fn) {
|
||||||
assert(addend == 0); // addend not allowed for function relocations
|
assert(reloc_info.addend == 0); // addend not allowed for function relocations
|
||||||
// We found a function pointer, so add it to our table,
|
// We found a function pointer, so add it to our table,
|
||||||
// as function pointers are not allowed to be stored inside the data section.
|
// 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.
|
// They are instead stored in a function table which are called by index.
|
||||||
try self.addTableFunction(target_symbol_index);
|
try self.addTableFunction(target_symbol_index);
|
||||||
try atom.relocs.append(self.base.allocator, .{
|
try atom.relocs.append(self.base.allocator, .{
|
||||||
.index = target_symbol_index,
|
.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,
|
.relocation_type = if (is_wasm32) .R_WASM_TABLE_INDEX_I32 else .R_WASM_TABLE_INDEX_I64,
|
||||||
});
|
});
|
||||||
} else {
|
} else {
|
||||||
try atom.relocs.append(self.base.allocator, .{
|
try atom.relocs.append(self.base.allocator, .{
|
||||||
.index = target_symbol_index,
|
.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,
|
.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,
|
// 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
|
local_symbol.tag = .dead; // also for any local symbol
|
||||||
self.symbols_free_list.append(self.base.allocator, local_atom.sym_index) catch {};
|
self.symbols_free_list.append(self.base.allocator, local_atom.sym_index) catch {};
|
||||||
assert(self.resolved_symbols.swapRemove(local_atom.symbolLoc()));
|
assert(self.resolved_symbols.swapRemove(local_atom.symbolLoc()));
|
||||||
|
assert(self.symbol_atom.remove(local_atom.symbolLoc()));
|
||||||
}
|
}
|
||||||
|
|
||||||
if (decl.isExtern()) {
|
if (decl.isExtern()) {
|
||||||
assert(self.imports.remove(atom.symbolLoc()));
|
assert(self.imports.remove(atom.symbolLoc()));
|
||||||
}
|
}
|
||||||
assert(self.resolved_symbols.swapRemove(atom.symbolLoc()));
|
assert(self.resolved_symbols.swapRemove(atom.symbolLoc()));
|
||||||
|
assert(self.symbol_atom.remove(atom.symbolLoc()));
|
||||||
atom.deinit(self.base.allocator);
|
atom.deinit(self.base.allocator);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -988,7 +989,6 @@ fn allocateAtoms(self: *Wasm) !void {
|
|||||||
atom.size,
|
atom.size,
|
||||||
});
|
});
|
||||||
offset += atom.size;
|
offset += atom.size;
|
||||||
try self.symbol_atom.putNoClobber(self.base.allocator, symbol_loc, atom);
|
|
||||||
atom = atom.next orelse break;
|
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 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];
|
const segment: *Wasm.Segment = &wasm_bin.segments.items[final_index];
|
||||||
segment.alignment = std.math.max(segment.alignment, atom.alignment);
|
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_c) return error.SkipZigTest;
|
||||||
if (builtin.zig_backend == .stage2_arm) 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_x86_64) return error.SkipZigTest;
|
||||||
|
if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest;
|
||||||
_ = nrfx_uart_rx(&g_uart0);
|
_ = 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_c) return error.SkipZigTest; // TODO
|
||||||
if (builtin.zig_backend == .stage2_arm) 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_x86_64) return error.SkipZigTest; // TODO
|
||||||
|
if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO
|
||||||
|
|
||||||
try foobar(FUNCTION_CONSTANT);
|
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 == .stage1) return error.SkipZigTest;
|
||||||
if (builtin.zig_backend == .stage2_arm) 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_x86_64) return error.SkipZigTest;
|
||||||
|
if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest;
|
||||||
|
|
||||||
try expect(@ptrToInt(x) == 0x1000);
|
try expect(@ptrToInt(x) == 0x1000);
|
||||||
try expect(x.len == 0x500);
|
try expect(x.len == 0x500);
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user