wasm: Implement more instructions

Implements the following instructions:
 - int_to_float
 - ptr_slice_len_ptr
 - ptr_slice_ptr_ptr
 - unwrap_errunion_payload_ptr
 - unwrap_errunion_err_ptr
This commit is contained in:
Luuk de Gram 2022-03-23 20:42:11 +01:00
parent 685f05b562
commit 60676a0ba5
No known key found for this signature in database
GPG Key ID: A8CFE58E4DC7D664
3 changed files with 69 additions and 13 deletions

View File

@ -1329,6 +1329,7 @@ fn genInst(self: *Self, inst: Air.Inst.Index) !WValue {
.fptrunc => self.airFptrunc(inst),
.fpext => self.airFpext(inst),
.float_to_int => self.airFloatToInt(inst),
.int_to_float => self.airIntToFloat(inst),
.get_union_tag => self.airGetUnionTag(inst),
// TODO
@ -1382,6 +1383,8 @@ fn genInst(self: *Self, inst: Air.Inst.Index) !WValue {
.slice_elem_val => self.airSliceElemVal(inst),
.slice_elem_ptr => self.airSliceElemPtr(inst),
.slice_ptr => self.airSlicePtr(inst),
.ptr_slice_len_ptr => self.airPtrSliceFieldPtr(inst, self.ptrSize()),
.ptr_slice_ptr_ptr => self.airPtrSliceFieldPtr(inst, 0),
.store => self.airStore(inst),
.set_union_tag => self.airSetUnionTag(inst),
@ -1398,8 +1401,10 @@ fn genInst(self: *Self, inst: Air.Inst.Index) !WValue {
.unreach => self.airUnreachable(inst),
.wrap_optional => self.airWrapOptional(inst),
.unwrap_errunion_payload => self.airUnwrapErrUnionPayload(inst),
.unwrap_errunion_err => self.airUnwrapErrUnionError(inst),
.unwrap_errunion_payload => self.airUnwrapErrUnionPayload(inst, false),
.unwrap_errunion_payload_ptr => self.airUnwrapErrUnionPayload(inst, true),
.unwrap_errunion_err => self.airUnwrapErrUnionError(inst, false),
.unwrap_errunion_err_ptr => self.airUnwrapErrUnionError(inst, true),
.wrap_errunion_payload => self.airWrapErrUnionPayload(inst),
.wrap_errunion_err => self.airWrapErrUnionErr(inst),
.errunion_payload_ptr_set => self.airErrUnionPayloadPtrSet(inst),
@ -1429,8 +1434,6 @@ fn genInst(self: *Self, inst: Air.Inst.Index) !WValue {
.bit_reverse,
.is_err_ptr,
.is_non_err_ptr,
.unwrap_errunion_payload_ptr,
.unwrap_errunion_err_ptr,
.sqrt,
.sin,
@ -1446,9 +1449,6 @@ fn genInst(self: *Self, inst: Air.Inst.Index) !WValue {
.round,
.trunc_float,
.ptr_slice_len_ptr,
.ptr_slice_ptr_ptr,
.int_to_float,
.cmpxchg_weak,
.cmpxchg_strong,
.fence,
@ -2560,30 +2560,32 @@ fn airIsErr(self: *Self, inst: Air.Inst.Index, opcode: wasm.Opcode) InnerError!W
return is_err_tmp;
}
fn airUnwrapErrUnionPayload(self: *Self, inst: Air.Inst.Index) InnerError!WValue {
fn airUnwrapErrUnionPayload(self: *Self, inst: Air.Inst.Index, op_is_ptr: bool) InnerError!WValue {
if (self.liveness.isUnused(inst)) return WValue{ .none = {} };
const ty_op = self.air.instructions.items(.data)[inst].ty_op;
const operand = try self.resolveInst(ty_op.operand);
const err_ty = self.air.typeOf(ty_op.operand);
const op_ty = self.air.typeOf(ty_op.operand);
const err_ty = if (op_is_ptr) op_ty.childType() else op_ty;
const payload_ty = err_ty.errorUnionPayload();
if (!payload_ty.hasRuntimeBits()) return WValue{ .none = {} };
const err_align = err_ty.abiAlignment(self.target);
const set_size = err_ty.errorUnionSet().abiSize(self.target);
const offset = mem.alignForwardGeneric(u64, set_size, err_align);
if (isByRef(payload_ty, self.target)) {
if (op_is_ptr or isByRef(payload_ty, self.target)) {
return self.buildPointerOffset(operand, offset, .new);
}
return self.load(operand, payload_ty, @intCast(u32, offset));
}
fn airUnwrapErrUnionError(self: *Self, inst: Air.Inst.Index) InnerError!WValue {
fn airUnwrapErrUnionError(self: *Self, inst: Air.Inst.Index, op_is_ptr: bool) InnerError!WValue {
if (self.liveness.isUnused(inst)) return WValue{ .none = {} };
const ty_op = self.air.instructions.items(.data)[inst].ty_op;
const operand = try self.resolveInst(ty_op.operand);
const err_ty = self.air.typeOf(ty_op.operand);
const op_ty = self.air.typeOf(ty_op.operand);
const err_ty = if (op_is_ptr) op_ty.childType() else op_ty;
const payload_ty = err_ty.errorUnionPayload();
if (!payload_ty.hasRuntimeBits()) {
if (op_is_ptr or !payload_ty.hasRuntimeBits()) {
return operand;
}
@ -3231,6 +3233,28 @@ fn airFloatToInt(self: *Self, inst: Air.Inst.Index) InnerError!WValue {
return result;
}
fn airIntToFloat(self: *Self, inst: Air.Inst.Index) InnerError!WValue {
if (self.liveness.isUnused(inst)) return WValue{ .none = {} };
const ty_op = self.air.instructions.items(.data)[inst].ty_op;
const operand = try self.resolveInst(ty_op.operand);
const dest_ty = self.air.typeOfIndex(inst);
const op_ty = self.air.typeOf(ty_op.operand);
try self.emitWValue(operand);
const op = buildOpcode(.{
.op = .convert,
.valtype1 = typeToValtype(dest_ty, self.target),
.valtype2 = typeToValtype(op_ty, self.target),
.signedness = if (op_ty.isSignedInt()) .signed else .unsigned,
});
try self.addTag(Mir.Inst.Tag.fromOpcode(op));
const result = try self.allocLocal(dest_ty);
try self.addLabel(.local_set, result.local);
return result;
}
fn airSplat(self: *Self, inst: Air.Inst.Index) InnerError!WValue {
if (self.liveness.isUnused(inst)) return WValue{ .none = {} };
@ -3682,3 +3706,11 @@ fn airErrorName(self: *Self, inst: Air.Inst.Index) InnerError!WValue {
try self.addLabel(.local_set, result_ptr.local);
return result_ptr;
}
fn airPtrSliceFieldPtr(self: *Self, inst: Air.Inst.Index, offset: u32) InnerError!WValue {
if (self.liveness.isUnused(inst)) return WValue{ .none = {} };
const ty_op = self.air.instructions.items(.data)[inst].ty_op;
const slice_ptr = try self.resolveInst(ty_op.operand);
return self.buildPointerOffset(slice_ptr, offset, .new);
}

View File

@ -203,6 +203,14 @@ pub fn emitMir(emit: *Emit) InnerError!void {
.i64_trunc_f32_u => try emit.emitTag(tag),
.i64_trunc_f64_s => try emit.emitTag(tag),
.i64_trunc_f64_u => try emit.emitTag(tag),
.f32_convert_i32_s => try emit.emitTag(tag),
.f32_convert_i32_u => try emit.emitTag(tag),
.f32_convert_i64_s => try emit.emitTag(tag),
.f32_convert_i64_u => try emit.emitTag(tag),
.f64_convert_i32_s => try emit.emitTag(tag),
.f64_convert_i32_u => try emit.emitTag(tag),
.f64_convert_i64_s => try emit.emitTag(tag),
.f64_convert_i64_u => try emit.emitTag(tag),
.i32_rem_s => try emit.emitTag(tag),
.i32_rem_u => try emit.emitTag(tag),
.i64_rem_s => try emit.emitTag(tag),

View File

@ -451,8 +451,24 @@ pub const Inst = struct {
/// Uses `tag`
i64_trunc_f64_u = 0xB1,
/// Uses `tag`
f32_convert_i32_s = 0xB2,
/// Uses `tag`
f32_convert_i32_u = 0xB3,
/// Uses `tag`
f32_convert_i64_s = 0xB4,
/// Uses `tag`
f32_convert_i64_u = 0xB5,
/// Uses `tag`
f32_demote_f64 = 0xB6,
/// Uses `tag`
f64_convert_i32_s = 0xB7,
/// Uses `tag`
f64_convert_i32_u = 0xB8,
/// Uses `tag`
f64_convert_i64_s = 0xB9,
/// Uses `tag`
f64_convert_i64_u = 0xBA,
/// Uses `tag`
f64_promote_f32 = 0xBB,
/// Uses `tag`
i32_reinterpret_f32 = 0xBC,