authorgravatar for luuk@degram.devLuuk de Gram <luuk@degram.dev> 2022-03-05 15:19:54+01:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2022-03-06 14:17:36-05:00
log6d84f22fa0d30f688a2fbe69acab2979373a7806
tree03d39cb2386d7c9da060e84de495a9e2de9dfc51
parent716abe338907dbcb0ea115dd014c2e13c3a6637b

stage2: Fix wasm linker for llvm backend

This fixes 2 entrypoints within the self-hosted wasm linker that would be called for the llvm backend, whereas we should simply call into the llvm backend to perform such action. i.e. not allocate a decl index when we have an llvm object, and when flushing a module, we should be calling it on llvm's object, rather than have the wasm linker perform the operation. Also, this fixes the wasm intrinsics for wasm.memory.size and wasm.memory.grow. Lastly, this commit ensures that when an extern function is being resolved, we tell LLVM how to import such function.

3 files changed, 18 insertions(+), 3 deletions(-)

src/codegen/llvm.zig+10-2
...@@ -708,6 +708,14 @@ pub const DeclGen = struct {...@@ -708,6 +708,14 @@ pub const DeclGen = struct {
708 if (!is_extern) {708 if (!is_extern) {
709 llvm_fn.setLinkage(.Internal);709 llvm_fn.setLinkage(.Internal);
710 llvm_fn.setUnnamedAddr(.True);710 llvm_fn.setUnnamedAddr(.True);
711 } else if (dg.module.getTarget().isWasm()) {
712 dg.addFnAttrString(llvm_fn, "wasm-import-name", std.mem.sliceTo(decl.name, 0));
713 if (decl.getExternFn().?.lib_name) |lib_name| {
714 const module_name = std.mem.sliceTo(lib_name, 0);
715 if (!std.mem.eql(u8, module_name, "c")) {
716 dg.addFnAttrString(llvm_fn, "wasm-import-module", module_name);
717 }
718 }
711 }719 }
712720
713 if (sret) {721 if (sret) {
...@@ -3483,7 +3491,7 @@ pub const FuncGen = struct {...@@ -3483,7 +3491,7 @@ pub const FuncGen = struct {
3483 const pl_op = self.air.instructions.items(.data)[inst].pl_op;3491 const pl_op = self.air.instructions.items(.data)[inst].pl_op;
3484 const index = pl_op.payload;3492 const index = pl_op.payload;
3485 const llvm_u32 = self.context.intType(32);3493 const llvm_u32 = self.context.intType(32);
3486 const llvm_fn = self.getIntrinsic("llvm.wasm.memory.size.i32", &.{llvm_u32});3494 const llvm_fn = self.getIntrinsic("llvm.wasm.memory.size", &.{llvm_u32});
3487 const args: [1]*const llvm.Value = .{llvm_u32.constInt(index, .False)};3495 const args: [1]*const llvm.Value = .{llvm_u32.constInt(index, .False)};
3488 return self.builder.buildCall(llvm_fn, &args, args.len, .Fast, .Auto, "");3496 return self.builder.buildCall(llvm_fn, &args, args.len, .Fast, .Auto, "");
3489 }3497 }
...@@ -3493,7 +3501,7 @@ pub const FuncGen = struct {...@@ -3493,7 +3501,7 @@ pub const FuncGen = struct {
3493 const index = pl_op.payload;3501 const index = pl_op.payload;
3494 const operand = try self.resolveInst(pl_op.operand);3502 const operand = try self.resolveInst(pl_op.operand);
3495 const llvm_u32 = self.context.intType(32);3503 const llvm_u32 = self.context.intType(32);
3496 const llvm_fn = self.getIntrinsic("llvm.wasm.memory.grow.i32", &.{ llvm_u32, llvm_u32 });3504 const llvm_fn = self.getIntrinsic("llvm.wasm.memory.grow", &.{llvm_u32});
3497 const args: [2]*const llvm.Value = .{3505 const args: [2]*const llvm.Value = .{
3498 llvm_u32.constInt(index, .False),3506 llvm_u32.constInt(index, .False),
3499 operand,3507 operand,
src/link/Wasm.zig+7-1
...@@ -466,6 +466,7 @@ pub fn deinit(self: *Wasm) void {...@@ -466,6 +466,7 @@ pub fn deinit(self: *Wasm) void {
466}466}
467467
468pub fn allocateDeclIndexes(self: *Wasm, decl: *Module.Decl) !void {468pub fn allocateDeclIndexes(self: *Wasm, decl: *Module.Decl) !void {
469 if (self.llvm_object) |_| return;
469 if (decl.link.wasm.sym_index != 0) return;470 if (decl.link.wasm.sym_index != 0) return;
470471
471 try self.symbols.ensureUnusedCapacity(self.base.allocator, 1);472 try self.symbols.ensureUnusedCapacity(self.base.allocator, 1);
...@@ -1365,10 +1366,15 @@ pub fn flush(self: *Wasm, comp: *Compilation) !void {...@@ -1365,10 +1366,15 @@ pub fn flush(self: *Wasm, comp: *Compilation) !void {
1365}1366}
13661367
1367pub fn flushModule(self: *Wasm, comp: *Compilation) !void {1368pub fn flushModule(self: *Wasm, comp: *Compilation) !void {
1368 _ = comp;
1369 const tracy = trace(@src());1369 const tracy = trace(@src());
1370 defer tracy.end();1370 defer tracy.end();
13711371
1372 if (build_options.have_llvm) {
1373 if (self.llvm_object) |llvm_object| {
1374 return try llvm_object.flushModule(comp);
1375 }
1376 }
1377
1372 // The amount of sections that will be written1378 // The amount of sections that will be written
1373 var section_count: u32 = 0;1379 var section_count: u32 = 0;
1374 // Index of the code section. Used to tell relocation table where the section lives.1380 // Index of the code section. Used to tell relocation table where the section lives.
test/behavior/struct.zig+1
...@@ -429,6 +429,7 @@ test "packed struct 24bits" {...@@ -429,6 +429,7 @@ test "packed struct 24bits" {
429 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO429 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO
430 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO430 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
431 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO431 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO
432 if (builtin.zig_backend == .stage2_llvm and builtin.stage2_arch == .wasm32) return error.SkipZigTest; // TODO
432433
433 comptime {434 comptime {
434 try expect(@sizeOf(Foo24Bits) == 4);435 try expect(@sizeOf(Foo24Bits) == 4);