wasm: Implement @ptrToInt and fix indirect function call

- Previously the table index and function type index were switched.
This commit swaps them.
- This also emits the correct indirect function calls count when importing the function table
This commit is contained in:
Luuk de Gram 2021-12-29 22:28:18 +01:00
parent f644c8b047
commit b9a0401e23
No known key found for this signature in database
GPG Key ID: A8CFE58E4DC7D664
4 changed files with 20 additions and 9 deletions

View File

@ -1200,6 +1200,7 @@ fn genInst(self: *Self, inst: Air.Inst.Index) !WValue {
.optional_payload => self.airOptionalPayload(inst),
.optional_payload_ptr => self.airOptionalPayload(inst),
.optional_payload_ptr_set => self.airOptionalPayloadPtrSet(inst),
.ptrtoint => self.airPtrToInt(inst),
.ret => self.airRet(inst),
.ret_ptr => self.airRetPtr(inst),
.ret_load => self.airRetLoad(inst),
@ -1729,6 +1730,8 @@ fn emitConstant(self: *Self, val: Value, ty: Type) InnerError!void {
} else {
try self.addLabel(.memory_address, decl.link.wasm.sym_index);
}
} else if (val.castTag(.int_u64)) |int_ptr| {
try self.addImm32(@bitCast(i32, @intCast(u32, int_ptr.data)));
} else return self.fail("Wasm TODO: emitConstant for other const pointer tag {s}", .{val.tag()});
},
.Void => {},
@ -2601,3 +2604,9 @@ fn airArrayToSlice(self: *Self, inst: Air.Inst.Index) InnerError!WValue {
return slice_local;
}
fn airPtrToInt(self: *Self, inst: Air.Inst.Index) InnerError!WValue {
if (self.liveness.isUnused(inst)) return WValue{ .none = {} };
const un_op = self.air.instructions.items(.data)[inst].un_op;
return self.resolveInst(un_op);
}

View File

@ -284,10 +284,12 @@ fn emitCall(emit: *Emit, inst: Mir.Inst.Index) !void {
}
fn emitCallIndirect(emit: *Emit, inst: Mir.Inst.Index) !void {
const label = emit.mir.instructions.items(.data)[inst].label;
const type_index = emit.mir.instructions.items(.data)[inst].label;
try emit.code.append(std.wasm.opcode(.call_indirect));
// NOTE: If we remove unused function types in the future for incremental
// linking, we must also emit a relocation for this `type_index`
try leb128.writeULEB128(emit.code.writer(), type_index);
try leb128.writeULEB128(emit.code.writer(), @as(u32, 0)); // TODO: Emit relocation for table index
try leb128.writeULEB128(emit.code.writer(), label);
}
fn emitFunctionIndex(emit: *Emit, inst: Mir.Inst.Index) !void {

View File

@ -646,7 +646,7 @@ pub fn flushModule(self: *Wasm, comp: *Compilation) !void {
.kind = .{
.table = .{
.limits = .{
.min = @intCast(u32, self.imports.count()),
.min = @intCast(u32, self.function_table.count()),
.max = null,
},
.reftype = .funcref,
@ -678,7 +678,7 @@ pub fn flushModule(self: *Wasm, comp: *Compilation) !void {
header_offset,
.import,
@intCast(u32, (try file.getPos()) - header_offset - header_size),
@intCast(u32, self.imports.count() + @boolToInt(import_memory)),
@intCast(u32, self.imports.count() + @boolToInt(import_memory) + @boolToInt(import_table)),
);
}

View File

@ -26,10 +26,15 @@ test {
_ = @import("behavior/defer.zig");
_ = @import("behavior/enum.zig");
_ = @import("behavior/error.zig");
_ = @import("behavior/fn_in_struct_in_comptime.zig");
_ = @import("behavior/hasdecl.zig");
_ = @import("behavior/hasfield.zig");
_ = @import("behavior/import.zig");
_ = @import("behavior/incomplete_struct_param_tld.zig");
_ = @import("behavior/inttoptr.zig");
_ = @import("behavior/ptrcast.zig");
_ = @import("behavior/pub_enum.zig");
_ = @import("behavior/ref_var_in_if_after_if_2nd_switch_prong.zig");
_ = @import("behavior/slice_sentinel_comptime.zig");
_ = @import("behavior/truncate.zig");
_ = @import("behavior/type.zig");
@ -57,19 +62,14 @@ test {
_ = @import("behavior/for.zig");
_ = @import("behavior/generics.zig");
_ = @import("behavior/if.zig");
_ = @import("behavior/incomplete_struct_param_tld.zig");
_ = @import("behavior/int128.zig");
_ = @import("behavior/inttoptr.zig");
_ = @import("behavior/member_func.zig");
_ = @import("behavior/null.zig");
_ = @import("behavior/optional.zig");
_ = @import("behavior/pointers.zig");
_ = @import("behavior/ptrcast.zig");
_ = @import("behavior/ref_var_in_if_after_if_2nd_switch_prong.zig");
_ = @import("behavior/struct.zig");
_ = @import("behavior/this.zig");
_ = @import("behavior/translate_c_macros.zig");
_ = @import("behavior/underscore.zig");
_ = @import("behavior/while.zig");
_ = @import("behavior/void.zig");