aboutsummaryrefslogtreecommitdiff
path: root/src/arch/wasm/CodeGen.zig
diff options
context:
space:
mode:
authorLuuk de Gram <luuk@degram.dev>2022-01-16 20:34:56 +0100
committerLuuk de Gram <luuk@degram.dev>2022-01-19 20:01:23 +0100
commit9615d7aee7fa0478ad01e4054b620213b73278e1 (patch)
treefaeb532e10fc9d3b7d24d2066af6bb8bdc3bcd14 /src/arch/wasm/CodeGen.zig
parent38253a680d8a53723667eca2c1f9a56b183dea8c (diff)
downloadzig-9615d7aee7fa0478ad01e4054b620213b73278e1.tar.gz
zig-9615d7aee7fa0478ad01e4054b620213b73278e1.zip
wasm: Refactor storing values.
Due to the new structure of lowerConstant, we can now simplify the logic in a lot of situations. - We no longer have to check the `WValue`'s tag to determine how to load/store a value. - We can now provide simple memcopy's for aggregate types. - Constants are now memoized, meaning we do no longer lower constants on each callsite.
Diffstat (limited to 'src/arch/wasm/CodeGen.zig')
-rw-r--r--src/arch/wasm/CodeGen.zig476
1 files changed, 196 insertions, 280 deletions
diff --git a/src/arch/wasm/CodeGen.zig b/src/arch/wasm/CodeGen.zig
index 1b9edc60c1..372510e62c 100644
--- a/src/arch/wasm/CodeGen.zig
+++ b/src/arch/wasm/CodeGen.zig
@@ -27,8 +27,6 @@ const WValue = union(enum) {
none: void,
/// Index of the local variable
local: u32,
- /// Represents the index of a local that contains a pointer to its stack position
- stack: u32,
/// An immediate 32bit value
imm32: u32,
/// An immediate 64bit value
@@ -38,21 +36,13 @@ const WValue = union(enum) {
/// A constant 64bit float value
float64: f64,
/// A value that represents a pointer to the data section
- memory: u64,
+ /// Note: The value contains the symbol index, rather than the actual address
+ /// as we use this to perform the relocation.
+ memory: u32,
/// Represents a function pointer
/// In wasm function pointers are indexes into a function table,
/// rather than an address in the data section.
function_index: u32,
- /// Used for types that contains of multiple areas within
- /// a memory region in the stack.
- /// The local represents the position in the stack,
- /// whereas the offset represents the offset from that position.
- local_with_offset: struct {
- /// Index of the local variable
- local: u32,
- /// The offset from the local's stack position
- offset: u32,
- },
};
/// Wasm ops, but without input/output/signedness information
@@ -514,7 +504,7 @@ pub const Result = union(enum) {
};
/// Hashmap to store generated `WValue` for each `Air.Inst.Ref`
-pub const ValueTable = std.AutoHashMapUnmanaged(Air.Inst.Index, WValue);
+pub const ValueTable = std.AutoHashMapUnmanaged(Air.Inst.Ref, WValue);
const Self = @This();
@@ -601,7 +591,7 @@ fn fail(self: *Self, comptime fmt: []const u8, args: anytype) InnerError {
/// Resolves the `WValue` for the given instruction `inst`
/// When the given instruction has a `Value`, it returns a constant instead
-fn resolveInst(self: Self, ref: Air.Inst.Ref) WValue {
+fn resolveInst(self: *Self, ref: Air.Inst.Ref) InnerError!WValue {
const gop = try self.values.getOrPut(self.gpa, ref);
if (gop.found_existing) return gop.value_ptr.*;
@@ -609,7 +599,10 @@ fn resolveInst(self: Self, ref: Air.Inst.Ref) WValue {
// means we must generate it from a constant.
const val = self.air.value(ref).?;
const ty = self.air.typeOf(ref);
- return self.lowerConstant(val, ty);
+ if (!ty.hasCodeGenBits() and !ty.isInt()) return WValue{ .none = {} };
+ const result = try self.lowerConstant(val, ty);
+ gop.value_ptr.* = result;
+ return result;
}
/// Appends a MIR instruction and returns its index within the list of instructions
@@ -729,10 +722,9 @@ fn genBlockType(self: *Self, ty: Type) InnerError!u8 {
}
/// Writes the bytecode depending on the given `WValue` in `val`
-fn emitWValue(self: *Self, val: WValue) InnerError!void {
- switch (val) {
+fn emitWValue(self: *Self, value: WValue) InnerError!void {
+ switch (value) {
.none => {}, // no-op
- .local_with_offset => |with_off| try self.addLabel(.local_get, with_off.local),
.local => |idx| try self.addLabel(.local_get, idx),
.imm32 => |val| try self.addImm32(@bitCast(i32, val)),
.imm64 => |val| try self.addImm64(val),
@@ -1195,7 +1187,6 @@ fn toWasmIntBits(bits: u16) ?u16 {
/// Performs a copy of bytes for a given type. Copying all bytes
/// from rhs to lhs.
-/// Asserts `lhs` and `rhs` have their active tag set to `local`
///
/// TODO: Perform feature detection and when bulk_memory is available,
/// use wasm's mem.copy instruction.
@@ -1204,9 +1195,9 @@ fn memCopy(self: *Self, ty: Type, lhs: WValue, rhs: WValue) !void {
var offset: u32 = 0;
while (offset < abi_size) : (offset += 1) {
// get lhs' address to store the result
- try self.addLabel(.local_get, lhs.local);
+ try self.emitWValue(lhs);
// load byte from rhs' adress
- try self.addLabel(.local_get, rhs.local);
+ try self.emitWValue(rhs);
try self.addMemArg(.i32_load8_u, .{ .offset = offset, .alignment = 1 });
// store the result in lhs (we already have its address on the stack)
try self.addMemArg(.i32_store8, .{ .offset = offset, .alignment = 1 });
@@ -1456,13 +1447,13 @@ fn genInst(self: *Self, inst: Air.Inst.Index) !WValue {
fn genBody(self: *Self, body: []const Air.Inst.Index) InnerError!void {
for (body) |inst| {
const result = try self.genInst(inst);
- try self.values.putNoClobber(self.gpa, inst, result);
+ try self.values.putNoClobber(self.gpa, Air.indexToRef(inst), result);
}
}
fn airRet(self: *Self, inst: Air.Inst.Index) InnerError!WValue {
const un_op = self.air.instructions.items(.data)[inst].un_op;
- const operand = self.resolveInst(un_op);
+ const operand = try self.resolveInst(un_op);
// result must be stored in the stack and we return a pointer
// to the stack instead
if (self.return_value != .none) {
@@ -1492,7 +1483,7 @@ fn airRetPtr(self: *Self, inst: Air.Inst.Index) InnerError!WValue {
fn airRetLoad(self: *Self, inst: Air.Inst.Index) InnerError!WValue {
const un_op = self.air.instructions.items(.data)[inst].un_op;
- const operand = self.resolveInst(un_op);
+ const operand = try self.resolveInst(un_op);
const ret_ty = self.air.typeOf(un_op).childType();
if (!ret_ty.hasCodeGenBits()) return WValue.none;
@@ -1539,24 +1530,11 @@ fn airCall(self: *Self, inst: Air.Inst.Index) InnerError!WValue {
for (args) |arg| {
const arg_ref = @intToEnum(Air.Inst.Ref, arg);
- const arg_val = self.resolveInst(arg_ref);
+ const arg_val = try self.resolveInst(arg_ref);
const arg_ty = self.air.typeOf(arg_ref);
if (!arg_ty.hasCodeGenBits()) continue;
-
- // If we need to pass by reference, but the argument is a constant,
- // we must first lower it before passing it.
- if (self.isByRef(arg_ty) and arg_val == .constant) {
- const arg_local = try self.allocStack(arg_ty);
- try self.store(arg_local, arg_val, arg_ty, 0);
- try self.emitWValue(arg_local);
- } else if (arg_val == .none) {
- // TODO: Remove this branch when zero-sized pointers do not generate
- // an argument.
- try self.addImm32(0);
- } else {
- try self.emitWValue(arg_val);
- }
+ try self.emitWValue(arg_val);
}
if (target) |direct| {
@@ -1565,7 +1543,7 @@ fn airCall(self: *Self, inst: Air.Inst.Index) InnerError!WValue {
// in this case we call a function pointer
// so load its value onto the stack
std.debug.assert(ty.zigTypeTag() == .Pointer);
- const operand = self.resolveInst(pl_op.operand);
+ const operand = try self.resolveInst(pl_op.operand);
try self.emitWValue(operand);
var fn_type = try self.genFunctype(fn_ty);
@@ -1609,142 +1587,44 @@ fn airAlloc(self: *Self, inst: Air.Inst.Index) InnerError!WValue {
fn airStore(self: *Self, inst: Air.Inst.Index) InnerError!WValue {
const bin_op = self.air.instructions.items(.data)[inst].bin_op;
- const lhs = self.resolveInst(bin_op.lhs);
- const rhs = self.resolveInst(bin_op.rhs);
+ const lhs = try self.resolveInst(bin_op.lhs);
+ const rhs = try self.resolveInst(bin_op.rhs);
const ty = self.air.typeOf(bin_op.lhs).childType();
- const offset: u32 = switch (lhs) {
- .local_with_offset => |with_off| with_off.offset,
- else => 0,
- };
-
- try self.store(lhs, rhs, ty, offset);
+ try self.store(lhs, rhs, ty, 0);
return .none;
}
fn store(self: *Self, lhs: WValue, rhs: WValue, ty: Type, offset: u32) InnerError!void {
switch (ty.zigTypeTag()) {
- .ErrorUnion, .Optional => {
- var buf: Type.Payload.ElemType = undefined;
- const payload_ty = if (ty.zigTypeTag() == .ErrorUnion) ty.errorUnionPayload() else ty.optionalChild(&buf);
- const tag_ty = if (ty.zigTypeTag() == .ErrorUnion) ty.errorUnionSet() else Type.initTag(.u8);
- const payload_offset = if (ty.zigTypeTag() == .ErrorUnion)
- @intCast(u32, tag_ty.abiSize(self.target))
- else if (ty.isPtrLikeOptional())
- @as(u32, 0)
- else
- @intCast(u32, ty.abiSize(self.target) - payload_ty.abiSize(self.target));
-
- switch (rhs) {
- .constant => {
- if (rhs.constant.val.castTag(.decl_ref)) |_| {
- // retrieve values from memory instead
- const mem_local = try self.allocLocal(Type.usize);
- try self.emitWValue(rhs);
- try self.addLabel(.local_set, mem_local.local);
- try self.store(lhs, mem_local, ty, 0);
- return;
- } else if (ty.isPtrLikeOptional()) {
- // set the address of rhs to lhs
- try self.store(lhs, rhs, Type.usize, 0);
- return;
- }
- // constant will contain both tag and payload,
- // so save those in 2 temporary locals before storing them
- // in memory
- try self.emitWValue(rhs);
- const tag_local = try self.allocLocal(tag_ty);
-
- if (payload_ty.hasCodeGenBits()) {
- const payload_local = try self.allocLocal(payload_ty);
- try self.addLabel(.local_set, payload_local.local);
- if (self.isByRef(payload_ty)) {
- const ptr = try self.buildPointerOffset(lhs, payload_offset, .new);
- try self.store(ptr, payload_local, payload_ty, 0);
- } else {
- try self.store(lhs, payload_local, payload_ty, payload_offset);
- }
- }
- try self.addLabel(.local_set, tag_local.local);
+ .ErrorUnion => {
+ const err_ty = ty.errorUnionSet();
+ const pl_ty = ty.errorUnionPayload();
+ if (!pl_ty.hasCodeGenBits()) {
+ const err_val = try self.load(rhs, err_ty, 0);
+ return self.store(lhs, err_val, err_ty, 0);
+ }
- try self.store(lhs, tag_local, tag_ty, 0);
- return;
- },
- .local => {
- // When the optional is pointer-like, we simply store the pointer
- // instead.
- if (ty.isPtrLikeOptional()) {
- try self.store(lhs, rhs, Type.usize, 0);
- return;
- }
- // Load values from `rhs` stack position and store in `lhs` instead
- const tag_local = try self.load(rhs, tag_ty, 0);
- if (payload_ty.hasCodeGenBits()) {
- if (self.isByRef(payload_ty)) {
- const payload_ptr = try self.buildPointerOffset(rhs, payload_offset, .new);
- const lhs_payload_ptr = try self.buildPointerOffset(lhs, payload_offset, .new);
- try self.store(lhs_payload_ptr, payload_ptr, payload_ty, 0);
- } else {
- const payload_local = try self.load(rhs, payload_ty, payload_offset);
- try self.store(lhs, payload_local, payload_ty, payload_offset);
- }
- }
- return try self.store(lhs, tag_local, tag_ty, 0);
- },
- .local_with_offset => |with_offset| {
- // check if we're storing the payload, or the error
- if (with_offset.offset == 0) {
- try self.store(lhs, .{ .local = with_offset.local }, tag_ty, 0);
- return;
- }
- const tag_local = try self.allocLocal(tag_ty);
- try self.addImm32(0);
- try self.addLabel(.local_set, tag_local.local);
- try self.store(lhs, tag_local, tag_ty, 0);
-
- return try self.store(
- lhs,
- .{ .local = with_offset.local },
- payload_ty,
- with_offset.offset,
- );
- },
- else => unreachable,
+ return try self.memCopy(ty, lhs, rhs);
+ },
+ .Optional => {
+ if (ty.isPtrLikeOptional()) {
+ return self.store(lhs, rhs, Type.usize, 0);
+ }
+ var buf: Type.Payload.ElemType = undefined;
+ const pl_ty = ty.optionalChild(&buf);
+ if (!pl_ty.hasCodeGenBits()) {
+ // const null_val = try self.load(rhs, Type.initTag(.u8), 0);
+ return self.store(lhs, rhs, Type.initTag(.u8), 0);
}
+
+ return self.memCopy(ty, lhs, rhs);
},
.Struct, .Array => {
return try self.memCopy(ty, lhs, rhs);
},
.Pointer => {
- if (ty.isSlice() and rhs == .constant) {
- try self.emitWValue(rhs);
-
- const val = rhs.constant.val;
- const len_local = try self.allocLocal(Type.usize);
- const ptr_local = try self.allocLocal(Type.usize);
- const len_offset = self.ptrSize();
- if (val.castTag(.decl_ref)) |decl| {
- const decl_ty: Type = decl.data.ty;
- if (decl_ty.isSlice()) {
- // for decl references we also need to retrieve the length and the original decl's pointer
- try self.addMemArg(.i32_load, .{ .offset = 0, .alignment = self.ptrSize() });
- try self.addLabel(.memory_address, decl.data.link.wasm.sym_index);
- try self.addMemArg(.i32_load, .{ .offset = len_offset, .alignment = self.ptrSize() });
- } else if (decl_ty.zigTypeTag() == .Array) {
- const len = decl_ty.arrayLen();
- switch (self.ptrSize()) {
- 4 => try self.addImm32(@bitCast(i32, @intCast(u32, len))),
- 8 => try self.addImm64(len),
- else => unreachable,
- }
- } else return self.fail("Wasm todo: Implement storing slices for decl_ref with type: {}", .{decl_ty});
- }
- try self.addLabel(.local_set, len_local.local);
- try self.addLabel(.local_set, ptr_local.local);
- try self.store(lhs, ptr_local, Type.usize, 0);
- try self.store(lhs, len_local, Type.usize, len_offset);
- return;
- } else if (ty.isSlice()) {
+ if (ty.isSlice()) {
// store pointer first
const ptr_local = try self.load(rhs, Type.usize, 0);
try self.store(lhs, ptr_local, Type.usize, 0);
@@ -1790,7 +1670,7 @@ fn store(self: *Self, lhs: WValue, rhs: WValue, ty: Type, offset: u32) InnerErro
fn airLoad(self: *Self, inst: Air.Inst.Index) InnerError!WValue {
const ty_op = self.air.instructions.items(.data)[inst].ty_op;
- const operand = self.resolveInst(ty_op.operand);
+ const operand = try self.resolveInst(ty_op.operand);
const ty = self.air.getRefType(ty_op.ty);
if (!ty.hasCodeGenBits()) return WValue{ .none = {} };
@@ -1801,10 +1681,7 @@ fn airLoad(self: *Self, inst: Air.Inst.Index) InnerError!WValue {
return new_local;
}
- return switch (operand) {
- .local_with_offset => |with_offset| try self.load(operand, ty, with_offset.offset),
- else => try self.load(operand, ty, 0),
- };
+ return self.load(operand, ty, 0);
}
fn load(self: *Self, operand: WValue, ty: Type, offset: u32) InnerError!WValue {
@@ -1862,8 +1739,8 @@ fn airBinOp(self: *Self, inst: Air.Inst.Index, op: Op) InnerError!WValue {
if (self.liveness.isUnused(inst)) return WValue{ .none = {} };
const bin_op = self.air.instructions.items(.data)[inst].bin_op;
- const lhs = self.resolveInst(bin_op.lhs);
- const rhs = self.resolveInst(bin_op.rhs);
+ const lhs = try self.resolveInst(bin_op.lhs);
+ const rhs = try self.resolveInst(bin_op.rhs);
const operand_ty = self.air.typeOfIndex(inst);
if (self.isByRef(operand_ty)) {
@@ -1889,8 +1766,8 @@ fn airBinOp(self: *Self, inst: Air.Inst.Index, op: Op) InnerError!WValue {
fn airWrapBinOp(self: *Self, inst: Air.Inst.Index, op: Op) InnerError!WValue {
const bin_op = self.air.instructions.items(.data)[inst].bin_op;
- const lhs = self.resolveInst(bin_op.lhs);
- const rhs = self.resolveInst(bin_op.rhs);
+ const lhs = try self.resolveInst(bin_op.lhs);
+ const rhs = try self.resolveInst(bin_op.rhs);
try self.emitWValue(lhs);
try self.emitWValue(rhs);
@@ -1960,8 +1837,7 @@ fn lowerConstant(self: *Self, val: Value, ty: Type) InnerError!WValue {
var space: Value.BigIntSpace = undefined;
const bigint = val.toBigInt(&space);
if (bigint.limbs.len == 1 and bigint.limbs[0] == 0) {
- try self.addLabel(.local_get, result.local);
- return;
+ return result;
}
if (@sizeOf(usize) != @sizeOf(u64)) {
return self.fail("Wasm todo: Implement big integers for 32bit compiler", .{});
@@ -1979,9 +1855,9 @@ fn lowerConstant(self: *Self, val: Value, ty: Type) InnerError!WValue {
.Float => switch (ty.floatBits(self.target)) {
0...32 => return WValue{ .float32 = val.toFloat(f32) },
33...64 => return WValue{ .float64 = val.toFloat(f64) },
- else => |bits| return self.fail("Wasm TODO: emitConstant for floats with {d} bits", .{bits}),
+ else => |bits| return self.fail("Wasm TODO: lowerConstant for floats with {d} bits", .{bits}),
},
- .Pointer => switch (val) {
+ .Pointer => switch (val.tag()) {
.slice => {
const result = try self.allocStack(ty);
var buf: Type.SlicePtrFieldTypeBuffer = undefined;
@@ -1998,6 +1874,7 @@ fn lowerConstant(self: *Self, val: Value, ty: Type) InnerError!WValue {
try self.addImm64(len);
try self.addMemArg(.i64_store, .{ .offset = self.ptrSize(), .alignment = self.ptrSize() });
},
+ else => unreachable,
}
return result;
},
@@ -2005,14 +1882,24 @@ fn lowerConstant(self: *Self, val: Value, ty: Type) InnerError!WValue {
const decl = val.castTag(.decl_ref).?.data;
decl.markAlive();
const target_sym_index = decl.link.wasm.sym_index;
- if (decl.ty.zigTypeTag() == .Fn) {
+ if (ty.isSlice()) {
+ var slice_len: Value.Payload.U64 = .{
+ .base = .{ .tag = .int_u64 },
+ .data = val.sliceLen(),
+ };
+ var slice_val: Value.Payload.Slice = .{
+ .base = .{ .tag = .slice },
+ .data = .{ .ptr = val.slicePtr(), .len = Value.initPayload(&slice_len.base) },
+ };
+ return self.lowerConstant(Value.initPayload(&slice_val.base), ty);
+ } else if (decl.ty.zigTypeTag() == .Fn) {
try self.bin_file.addTableFunction(target_sym_index);
return WValue{ .function_index = target_sym_index };
} else return WValue{ .memory = target_sym_index };
},
.int_u64, .one => return WValue{ .imm32 = @intCast(u32, val.toUnsignedInt()) },
.zero, .null_value => return WValue{ .imm32 = 0 },
- else => return self.fail("Wasm TODO: emitConstant for other const pointer tag {s}", .{val.tag()}),
+ else => return self.fail("Wasm TODO: lowerConstant for other const pointer tag {s}", .{val.tag()}),
},
.Enum => {
if (val.castTag(.enum_field_index)) |field_index| {
@@ -2035,9 +1922,12 @@ fn lowerConstant(self: *Self, val: Value, ty: Type) InnerError!WValue {
return self.lowerConstant(val, int_tag_ty);
}
},
- .ErrorSet => {
- const error_index = self.global_error_set.get(val.getError().?).?;
- return WValue{ .imm32 = error_index };
+ .ErrorSet => switch (val.tag()) {
+ .@"error" => {
+ const error_index = self.global_error_set.get(val.getError().?).?;
+ return WValue{ .imm32 = error_index };
+ },
+ else => return WValue{ .imm32 = 0 },
},
.ErrorUnion => {
const error_type = ty.errorUnionSet();
@@ -2051,25 +1941,25 @@ fn lowerConstant(self: *Self, val: Value, ty: Type) InnerError!WValue {
const result = try self.allocStack(ty);
try self.store(result, error_value, error_type, 0);
- const payload = try lowerConstant(
+ const payload = try self.lowerConstant(
if (val.castTag(.eu_payload)) |pl| pl.data else Value.initTag(.undef),
payload_type,
);
- const pl_ptr = if (self.isByRef(payload_type)) try self.buildPointerOffset(
- result,
- error_type.abiSize(self.target),
- .new,
- ) else result;
- try self.store(pl_ptr, payload, payload_type, 0);
+ const pl_ptr = if (self.isByRef(payload_type))
+ try self.buildPointerOffset(result, error_type.abiSize(self.target), .new)
+ else
+ result;
+ try self.store(pl_ptr, payload, payload_type, @intCast(u32, error_type.abiSize(self.target)));
return result;
},
.Optional => if (ty.isPtrLikeOptional()) {
- return self.lowerConstant(val, payload_type);
+ var buf: Type.Payload.ElemType = undefined;
+ return self.lowerConstant(val, ty.optionalChild(&buf));
} else {
var buf: Type.Payload.ElemType = undefined;
const payload_type = ty.optionalChild(&buf);
const is_pl = val.tag() == .opt_payload;
- const null_value = WValue{ .imm32 = if (is_pl) @as(u32, 0) else 1 };
+ const null_value = WValue{ .imm32 = if (is_pl) @as(u32, 1) else 0 };
if (!payload_type.hasCodeGenBits()) {
return null_value;
}
@@ -2081,11 +1971,11 @@ fn lowerConstant(self: *Self, val: Value, ty: Type) InnerError!WValue {
payload_type,
);
+ const offset = @intCast(u32, ty.abiSize(self.target) - payload_type.abiSize(self.target));
const pl_ptr = if (self.isByRef(payload_type)) blk: {
- const offset = ty.abiSize(self.target) - payload_type.abiSize();
break :blk try self.buildPointerOffset(result, offset, .new);
} else result;
- try self.store(pl_ptr, payload, payload_type, 0);
+ try self.store(pl_ptr, payload, payload_type, offset);
return result;
},
.Struct => {
@@ -2096,7 +1986,6 @@ fn lowerConstant(self: *Self, val: Value, ty: Type) InnerError!WValue {
const fields = ty.structFields();
const offset = try self.copyLocal(result, ty);
for (fields.values()) |field, index| {
- const tmp = try self.allocLocal(field.ty);
const field_value = try self.lowerConstant(struct_data.data[index], field.ty);
try self.store(offset, field_value, field.ty, 0);
@@ -2118,12 +2007,10 @@ fn lowerConstant(self: *Self, val: Value, ty: Type) InnerError!WValue {
} else if (val.castTag(.array)) |array| {
const elem_ty = ty.childType();
const elem_size = elem_ty.abiSize(self.target);
- const tmp = try self.allocLocal(elem_ty);
const offset = try self.copyLocal(result, ty);
for (array.data) |value, index| {
- try self.lowerConstant(value, elem_ty);
- try self.addLabel(.local_set, tmp.local);
- try self.store(offset, tmp, elem_ty, 0);
+ const elem_val = try self.lowerConstant(value, elem_ty);
+ try self.store(offset, elem_val, elem_ty, 0);
if (index != (array.data.len - 1)) {
_ = try self.buildPointerOffset(offset, elem_size, .modify);
@@ -2136,18 +2023,16 @@ fn lowerConstant(self: *Self, val: Value, ty: Type) InnerError!WValue {
const sentinel = ty.sentinel();
const len = ty.arrayLen();
const len_with_sent = len + @boolToInt(sentinel != null);
- const tmp = try self.allocLocal(elem_ty);
const offset = try self.copyLocal(result, ty);
var index: u32 = 0;
while (index < len_with_sent) : (index += 1) {
- if (sentinel != null and index == len) {
- try self.lowerConstant(sentinel.?, elem_ty);
- } else {
+ const elem_val = if (sentinel != null and index == len)
+ try self.lowerConstant(sentinel.?, elem_ty)
+ else
try self.lowerConstant(value, elem_ty);
- }
- try self.addLabel(.local_set, tmp.local);
- try self.store(offset, tmp, elem_ty, 0);
+
+ try self.store(offset, elem_val, elem_ty, 0);
if (index != (len_with_sent - 1)) {
_ = try self.buildPointerOffset(offset, elem_size, .modify);
@@ -2156,19 +2041,18 @@ fn lowerConstant(self: *Self, val: Value, ty: Type) InnerError!WValue {
} else if (val.tag() == .empty_array_sentinel) {
const elem_ty = ty.childType();
const sent_val = ty.sentinel().?;
- const tmp = try self.allocLocal(elem_ty);
- try self.lowerConstant(sent_val, elem_ty);
- try self.addLabel(.local_set, tmp.local);
- try self.store(result, tmp, elem_ty, 0);
+ const sentinel = try self.lowerConstant(sent_val, elem_ty);
+ try self.store(result, sentinel, elem_ty, 0);
} else unreachable;
return result;
},
- else => |zig_type| return self.fail("Wasm TODO: emitConstant for zigTypeTag {s}", .{zig_type}),
+ else => |zig_type| return self.fail("Wasm TODO: LowerConstant for zigTypeTag {s}", .{zig_type}),
}
}
fn emitUndefined(self: *Self, ty: Type) InnerError!WValue {
switch (ty.zigTypeTag()) {
+ .Bool, .ErrorSet => return WValue{ .imm32 = 0xaaaaaaaa },
.Int => switch (ty.intInfo(self.target).bits) {
0...32 => return WValue{ .imm32 = 0xaaaaaaaa },
33...64 => return WValue{ .imm64 = 0xaaaaaaaaaaaaaaaa },
@@ -2185,7 +2069,7 @@ fn emitUndefined(self: *Self, ty: Type) InnerError!WValue {
var offset: u32 = 0;
while (offset < abi_size) : (offset += 1) {
try self.emitWValue(result);
- try self.addImm32(0xaaaaaaaa);
+ try self.addImm32(@bitCast(i32, @as(u32, 0xaaaaaaaa)));
switch (self.arch()) {
.wasm32 => try self.addMemArg(.i32_store8, .{ .offset = offset, .alignment = 1 }),
.wasm64 => try self.addMemArg(.i64_store8, .{ .offset = offset, .alignment = 1 }),
@@ -2199,7 +2083,50 @@ fn emitUndefined(self: *Self, ty: Type) InnerError!WValue {
.wasm64 => return WValue{ .imm64 = 0xaaaaaaaaaaaaaaaa },
else => unreachable,
},
- else => return self.fail("Wasm TODO: emitUndefined for type: {}\n", .{ty}),
+ .Optional => {
+ var buf: Type.Payload.ElemType = undefined;
+ const pl_ty = ty.optionalChild(&buf);
+ if (ty.isPtrLikeOptional()) {
+ return self.emitUndefined(pl_ty);
+ }
+ if (!pl_ty.hasCodeGenBits()) {
+ return self.emitUndefined(Type.initTag(.u8));
+ }
+ const result = try self.allocStack(ty);
+ const abi_size = ty.abiSize(self.target);
+ var offset: u32 = 0;
+ while (offset < abi_size) : (offset += 1) {
+ try self.emitWValue(result);
+ try self.addImm32(@bitCast(i32, @as(u32, 0xaaaaaaaa)));
+ switch (self.arch()) {
+ .wasm32 => try self.addMemArg(.i32_store8, .{ .offset = offset, .alignment = 1 }),
+ .wasm64 => try self.addMemArg(.i64_store8, .{ .offset = offset, .alignment = 1 }),
+ else => unreachable,
+ }
+ }
+ return result;
+ },
+ .ErrorUnion => {
+ // const error_set = ty.errorUnionSet();
+ const pl_ty = ty.errorUnionPayload();
+ if (!pl_ty.hasCodeGenBits()) {
+ return WValue{ .imm32 = 0xaaaaaaaa };
+ }
+ const result = try self.allocStack(ty);
+ const abi_size = ty.abiSize(self.target);
+ var offset: u32 = 0;
+ while (offset < abi_size) : (offset += 1) {
+ try self.emitWValue(result);
+ try self.addImm32(@bitCast(i32, @as(u32, 0xaaaaaaaa)));
+ switch (self.arch()) {
+ .wasm32 => try self.addMemArg(.i32_store8, .{ .offset = offset, .alignment = 1 }),
+ .wasm64 => try self.addMemArg(.i64_store8, .{ .offset = offset, .alignment = 1 }),
+ else => unreachable,
+ }
+ }
+ return result;
+ },
+ else => return self.fail("Wasm TODO: emitUndefined for type: {}\n", .{ty.zigTypeTag()}),
}
}
@@ -2298,7 +2225,7 @@ fn airLoop(self: *Self, inst: Air.Inst.Index) InnerError!WValue {
fn airCondBr(self: *Self, inst: Air.Inst.Index) InnerError!WValue {
const pl_op = self.air.instructions.items(.data)[inst].pl_op;
- const condition = self.resolveInst(pl_op.operand);
+ const condition = try self.resolveInst(pl_op.operand);
const extra = self.air.extraData(Air.CondBr, pl_op.payload);
const then_body = self.air.extra[extra.end..][0..extra.data.then_body_len];
const else_body = self.air.extra[extra.end + then_body.len ..][0..extra.data.else_body_len];
@@ -2325,8 +2252,8 @@ fn airCondBr(self: *Self, inst: Air.Inst.Index) InnerError!WValue {
fn airCmp(self: *Self, inst: Air.Inst.Index, op: std.math.CompareOperator) InnerError!WValue {
const bin_op = self.air.instructions.items(.data)[inst].bin_op;
- const lhs = self.resolveInst(bin_op.lhs);
- const rhs = self.resolveInst(bin_op.rhs);
+ const lhs = try self.resolveInst(bin_op.lhs);
+ const rhs = try self.resolveInst(bin_op.rhs);
const operand_ty = self.air.typeOf(bin_op.lhs);
if (operand_ty.zigTypeTag() == .Optional and !operand_ty.isPtrLikeOptional()) {
@@ -2377,7 +2304,7 @@ fn airBr(self: *Self, inst: Air.Inst.Index) InnerError!WValue {
// if operand has codegen bits we should break with a value
if (self.air.typeOf(br.operand).hasCodeGenBits()) {
- try self.emitWValue(self.resolveInst(br.operand));
+ try self.emitWValue(try self.resolveInst(br.operand));
if (block.value != .none) {
try self.addLabel(.local_set, block.value.local);
@@ -2395,7 +2322,7 @@ fn airBr(self: *Self, inst: Air.Inst.Index) InnerError!WValue {
fn airNot(self: *Self, inst: Air.Inst.Index) InnerError!WValue {
const ty_op = self.air.instructions.items(.data)[inst].ty_op;
- const operand = self.resolveInst(ty_op.operand);
+ const operand = try self.resolveInst(ty_op.operand);
try self.emitWValue(operand);
// wasm does not have booleans nor the `not` instruction, therefore compare with 0
@@ -2425,20 +2352,21 @@ fn airUnreachable(self: *Self, inst: Air.Inst.Index) InnerError!WValue {
fn airBitcast(self: *Self, inst: Air.Inst.Index) InnerError!WValue {
const ty_op = self.air.instructions.items(.data)[inst].ty_op;
- const operand = self.resolveInst(ty_op.operand);
- if (operand == .constant) {
- const result = try self.allocLocal(self.air.typeOfIndex(inst));
- try self.emitWValue(operand);
- try self.addLabel(.local_set, result.local);
- return result;
- }
+ const operand = try self.resolveInst(ty_op.operand);
+ // if (operand == .constant) {
+ // std.debug.print("Let's take a look at this!!!!!!\n--------------------\n", .{});
+ // const result = try self.allocLocal(self.air.typeOfIndex(inst));
+ // try self.emitWValue(operand);
+ // try self.addLabel(.local_set, result.local);
+ // return result;
+ // }
return operand;
}
fn airStructFieldPtr(self: *Self, inst: Air.Inst.Index) InnerError!WValue {
const ty_pl = self.air.instructions.items(.data)[inst].ty_pl;
const extra = self.air.extraData(Air.StructField, ty_pl.payload);
- const struct_ptr = self.resolveInst(extra.data.struct_operand);
+ const struct_ptr = try self.resolveInst(extra.data.struct_operand);
const struct_ty = self.air.typeOf(extra.data.struct_operand).childType();
const offset = std.math.cast(u32, struct_ty.structFieldOffset(extra.data.field_index, self.target)) catch {
return self.fail("Field type '{}' too big to fit into stack frame", .{
@@ -2450,7 +2378,7 @@ fn airStructFieldPtr(self: *Self, inst: Air.Inst.Index) InnerError!WValue {
fn airStructFieldPtrIndex(self: *Self, inst: Air.Inst.Index, index: u32) InnerError!WValue {
const ty_op = self.air.instructions.items(.data)[inst].ty_op;
- const struct_ptr = self.resolveInst(ty_op.operand);
+ const struct_ptr = try self.resolveInst(ty_op.operand);
const struct_ty = self.air.typeOf(ty_op.operand).childType();
const field_ty = struct_ty.structFieldType(index);
const offset = std.math.cast(u32, struct_ty.structFieldOffset(index, self.target)) catch {
@@ -2462,47 +2390,35 @@ fn airStructFieldPtrIndex(self: *Self, inst: Air.Inst.Index, index: u32) InnerEr
}
fn structFieldPtr(self: *Self, struct_ptr: WValue, offset: u32) InnerError!WValue {
- var final_offset = offset;
- const local = switch (struct_ptr) {
- .local => |local| local,
- .local_with_offset => |with_offset| blk: {
- final_offset += with_offset.offset;
- break :blk with_offset.local;
- },
- else => unreachable,
- };
- return self.buildPointerOffset(.{ .local = local }, final_offset, .new);
+ return self.buildPointerOffset(struct_ptr, offset, .new);
}
fn airStructFieldVal(self: *Self, inst: Air.Inst.Index) InnerError!WValue {
- if (self.liveness.isUnused(inst)) return WValue.none;
+ if (self.liveness.isUnused(inst)) return WValue{ .none = {} };
const ty_pl = self.air.instructions.items(.data)[inst].ty_pl;
const struct_field = self.air.extraData(Air.StructField, ty_pl.payload).data;
const struct_ty = self.air.typeOf(struct_field.struct_operand);
- const operand = self.resolveInst(struct_field.struct_operand);
+ const operand = try self.resolveInst(struct_field.struct_operand);
const field_index = struct_field.field_index;
const field_ty = struct_ty.structFieldType(field_index);
- if (!field_ty.hasCodeGenBits()) return WValue.none;
+ if (!field_ty.hasCodeGenBits()) return WValue{ .none = {} };
const offset = std.math.cast(u32, struct_ty.structFieldOffset(field_index, self.target)) catch {
return self.fail("Field type '{}' too big to fit into stack frame", .{field_ty});
};
if (self.isByRef(field_ty)) {
- return WValue{ .local_with_offset = .{ .local = operand.local, .offset = offset } };
+ return self.buildPointerOffset(operand, offset, .new);
}
- switch (operand) {
- .local_with_offset => |with_offset| return try self.load(operand, field_ty, offset + with_offset.offset),
- else => return try self.load(operand, field_ty, offset),
- }
+ return self.load(operand, field_ty, offset);
}
fn airSwitchBr(self: *Self, inst: Air.Inst.Index) InnerError!WValue {
// result type is always 'noreturn'
const blocktype = wasm.block_empty;
const pl_op = self.air.instructions.items(.data)[inst].pl_op;
- const target = self.resolveInst(pl_op.operand);
+ const target = try self.resolveInst(pl_op.operand);
const target_ty = self.air.typeOf(pl_op.operand);
const switch_br = self.air.extraData(Air.SwitchBr, pl_op.payload);
var extra_index: usize = switch_br.end;
@@ -2650,7 +2566,7 @@ fn airSwitchBr(self: *Self, inst: Air.Inst.Index) InnerError!WValue {
fn airIsErr(self: *Self, inst: Air.Inst.Index, opcode: wasm.Opcode) InnerError!WValue {
const un_op = self.air.instructions.items(.data)[inst].un_op;
- const operand = self.resolveInst(un_op);
+ const operand = try self.resolveInst(un_op);
const err_ty = self.air.typeOf(un_op);
const pl_ty = err_ty.errorUnionPayload();
@@ -2675,7 +2591,7 @@ fn airIsErr(self: *Self, inst: Air.Inst.Index, opcode: wasm.Opcode) InnerError!W
fn airUnwrapErrUnionPayload(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 = self.resolveInst(ty_op.operand);
+ const operand = try self.resolveInst(ty_op.operand);
const err_ty = self.air.typeOf(ty_op.operand);
const payload_ty = err_ty.errorUnionPayload();
if (!payload_ty.hasCodeGenBits()) return WValue{ .none = {} };
@@ -2690,7 +2606,7 @@ fn airUnwrapErrUnionError(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 = self.resolveInst(ty_op.operand);
+ const operand = try self.resolveInst(ty_op.operand);
const err_ty = self.air.typeOf(ty_op.operand);
const payload_ty = err_ty.errorUnionPayload();
if (!payload_ty.hasCodeGenBits()) {
@@ -2703,7 +2619,7 @@ fn airUnwrapErrUnionError(self: *Self, inst: Air.Inst.Index) InnerError!WValue {
fn airWrapErrUnionPayload(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 = self.resolveInst(ty_op.operand);
+ const operand = try self.resolveInst(ty_op.operand);
const op_ty = self.air.typeOf(ty_op.operand);
if (!op_ty.hasCodeGenBits()) return operand;
@@ -2725,7 +2641,7 @@ fn airWrapErrUnionPayload(self: *Self, inst: Air.Inst.Index) InnerError!WValue {
fn airWrapErrUnionErr(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 = self.resolveInst(ty_op.operand);
+ const operand = try self.resolveInst(ty_op.operand);
const err_ty = self.air.getRefType(ty_op.ty);
const err_union = try self.allocStack(err_ty);
@@ -2739,7 +2655,7 @@ fn airIntcast(self: *Self, inst: Air.Inst.Index) InnerError!WValue {
const ty_op = self.air.instructions.items(.data)[inst].ty_op;
const ty = self.air.getRefType(ty_op.ty);
- const operand = self.resolveInst(ty_op.operand);
+ const operand = try self.resolveInst(ty_op.operand);
const ref_ty = self.air.typeOf(ty_op.operand);
const ref_info = ref_ty.intInfo(self.target);
const wanted_info = ty.intInfo(self.target);
@@ -2770,7 +2686,7 @@ fn airIntcast(self: *Self, inst: Air.Inst.Index) InnerError!WValue {
fn airIsNull(self: *Self, inst: Air.Inst.Index, opcode: wasm.Opcode, op_kind: enum { value, ptr }) InnerError!WValue {
const un_op = self.air.instructions.items(.data)[inst].un_op;
- const operand = self.resolveInst(un_op);
+ const operand = try self.resolveInst(un_op);
const op_ty = self.air.typeOf(un_op);
const optional_ty = if (op_kind == .ptr) op_ty.childType() else op_ty;
@@ -2801,7 +2717,7 @@ fn isNull(self: *Self, operand: WValue, optional_ty: Type, opcode: wasm.Opcode)
fn airOptionalPayload(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 = self.resolveInst(ty_op.operand);
+ const operand = try self.resolveInst(ty_op.operand);
const opt_ty = self.air.typeOf(ty_op.operand);
const payload_ty = self.air.typeOfIndex(inst);
if (!payload_ty.hasCodeGenBits()) return WValue{ .none = {} };
@@ -2820,7 +2736,7 @@ fn airOptionalPayloadPtr(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 = self.resolveInst(ty_op.operand);
+ const operand = try self.resolveInst(ty_op.operand);
const opt_ty = self.air.typeOf(ty_op.operand).childType();
var buf: Type.Payload.ElemType = undefined;
@@ -2835,7 +2751,7 @@ fn airOptionalPayloadPtr(self: *Self, inst: Air.Inst.Index) InnerError!WValue {
fn airOptionalPayloadPtrSet(self: *Self, inst: Air.Inst.Index) InnerError!WValue {
const ty_op = self.air.instructions.items(.data)[inst].ty_op;
- const operand = self.resolveInst(ty_op.operand);
+ const operand = try self.resolveInst(ty_op.operand);
const opt_ty = self.air.typeOf(ty_op.operand).childType();
var buf: Type.Payload.ElemType = undefined;
const payload_ty = opt_ty.optionalChild(&buf);
@@ -2871,7 +2787,7 @@ fn airWrapOptional(self: *Self, inst: Air.Inst.Index) InnerError!WValue {
return non_null_bit;
}
- const operand = self.resolveInst(ty_op.operand);
+ const operand = try self.resolveInst(ty_op.operand);
const op_ty = self.air.typeOfIndex(inst);
if (op_ty.isPtrLikeOptional()) {
return operand;
@@ -2897,8 +2813,8 @@ fn airSlice(self: *Self, inst: Air.Inst.Index) InnerError!WValue {
const ty_pl = self.air.instructions.items(.data)[inst].ty_pl;
const bin_op = self.air.extraData(Air.Bin, ty_pl.payload).data;
- const lhs = self.resolveInst(bin_op.lhs);
- const rhs = self.resolveInst(bin_op.rhs);
+ const lhs = try self.resolveInst(bin_op.lhs);
+ const rhs = try self.resolveInst(bin_op.rhs);
const slice_ty = self.air.typeOfIndex(inst);
const slice = try self.allocStack(slice_ty);
@@ -2912,7 +2828,7 @@ fn airSliceLen(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 = self.resolveInst(ty_op.operand);
+ const operand = try self.resolveInst(ty_op.operand);
return try self.load(operand, Type.usize, self.ptrSize());
}
@@ -2922,8 +2838,8 @@ fn airSliceElemVal(self: *Self, inst: Air.Inst.Index) InnerError!WValue {
const bin_op = self.air.instructions.items(.data)[inst].bin_op;
const slice_ty = self.air.typeOf(bin_op.lhs);
- const slice = self.resolveInst(bin_op.lhs);
- const index = self.resolveInst(bin_op.rhs);
+ const slice = try self.resolveInst(bin_op.lhs);
+ const index = try self.resolveInst(bin_op.rhs);
const elem_ty = slice_ty.childType();
const elem_size = elem_ty.abiSize(self.target);
@@ -2954,8 +2870,8 @@ fn airSliceElemPtr(self: *Self, inst: Air.Inst.Index) InnerError!WValue {
const elem_ty = self.air.getRefType(ty_pl.ty).childType();
const elem_size = elem_ty.abiSize(self.target);
- const slice = self.resolveInst(bin_op.lhs);
- const index = self.resolveInst(bin_op.rhs);
+ const slice = try self.resolveInst(bin_op.lhs);
+ const index = try self.resolveInst(bin_op.rhs);
const slice_ptr = try self.load(slice, slice_ty, 0);
try self.addLabel(.local_get, slice_ptr.local);
@@ -2974,14 +2890,14 @@ fn airSliceElemPtr(self: *Self, inst: Air.Inst.Index) InnerError!WValue {
fn airSlicePtr(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 = self.resolveInst(ty_op.operand);
+ const operand = try self.resolveInst(ty_op.operand);
return try self.load(operand, Type.usize, 0);
}
fn airTrunc(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 = self.resolveInst(ty_op.operand);
+ const operand = try self.resolveInst(ty_op.operand);
const op_ty = self.air.typeOf(ty_op.operand);
const int_info = self.air.getRefType(ty_op.ty).intInfo(self.target);
const wanted_bits = int_info.bits;
@@ -3040,12 +2956,12 @@ fn airTrunc(self: *Self, inst: Air.Inst.Index) InnerError!WValue {
fn airBoolToInt(self: *Self, inst: Air.Inst.Index) InnerError!WValue {
const un_op = self.air.instructions.items(.data)[inst].un_op;
- return self.resolveInst(un_op);
+ return try self.resolveInst(un_op);
}
fn airArrayToSlice(self: *Self, inst: Air.Inst.Index) InnerError!WValue {
const ty_op = self.air.instructions.items(.data)[inst].ty_op;
- const operand = self.resolveInst(ty_op.operand);
+ const operand = try self.resolveInst(ty_op.operand);
const array_ty = self.air.typeOf(ty_op.operand).childType();
const ty = Type.@"usize";
const ptr_width = @intCast(u32, ty.abiSize(self.target));
@@ -3072,7 +2988,7 @@ fn airArrayToSlice(self: *Self, inst: Air.Inst.Index) InnerError!WValue {
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);
+ return try self.resolveInst(un_op);
}
fn airPtrElemVal(self: *Self, inst: Air.Inst.Index) InnerError!WValue {
@@ -3080,8 +2996,8 @@ fn airPtrElemVal(self: *Self, inst: Air.Inst.Index) InnerError!WValue {
const bin_op = self.air.instructions.items(.data)[inst].bin_op;
const ptr_ty = self.air.typeOf(bin_op.lhs);
- const pointer = self.resolveInst(bin_op.lhs);
- const index = self.resolveInst(bin_op.rhs);
+ const pointer = try self.resolveInst(bin_op.lhs);
+ const index = try self.resolveInst(bin_op.rhs);
const elem_ty = ptr_ty.childType();
const elem_size = elem_ty.abiSize(self.target);
@@ -3115,8 +3031,8 @@ fn airPtrElemPtr(self: *Self, inst: Air.Inst.Index) InnerError!WValue {
const elem_ty = self.air.getRefType(ty_pl.ty).childType();
const elem_size = elem_ty.abiSize(self.target);
- const ptr = self.resolveInst(bin_op.lhs);
- const index = self.resolveInst(bin_op.rhs);
+ const ptr = try self.resolveInst(bin_op.lhs);
+ const index = try self.resolveInst(bin_op.rhs);
// load pointer onto the stack
if (ptr_ty.isSlice()) {
@@ -3140,8 +3056,8 @@ fn airPtrElemPtr(self: *Self, inst: Air.Inst.Index) InnerError!WValue {
fn airPtrBinOp(self: *Self, inst: Air.Inst.Index, op: Op) InnerError!WValue {
if (self.liveness.isUnused(inst)) return WValue{ .none = {} };
const bin_op = self.air.instructions.items(.data)[inst].bin_op;
- const ptr = self.resolveInst(bin_op.lhs);
- const offset = self.resolveInst(bin_op.rhs);
+ const ptr = try self.resolveInst(bin_op.lhs);
+ const offset = try self.resolveInst(bin_op.rhs);
const ptr_ty = self.air.typeOf(bin_op.lhs);
const pointee_ty = switch (ptr_ty.ptrSize()) {
.One => ptr_ty.childType().childType(), // ptr to array, so get array element type
@@ -3167,9 +3083,9 @@ fn airMemset(self: *Self, inst: Air.Inst.Index) InnerError!WValue {
const pl_op = self.air.instructions.items(.data)[inst].pl_op;
const bin_op = self.air.extraData(Air.Bin, pl_op.payload).data;
- const ptr = self.resolveInst(pl_op.operand);
- const value = self.resolveInst(bin_op.lhs);
- const len = self.resolveInst(bin_op.rhs);
+ const ptr = try self.resolveInst(pl_op.operand);
+ const value = try self.resolveInst(bin_op.lhs);
+ const len = try self.resolveInst(bin_op.rhs);
try self.memSet(ptr, len, value);
return WValue.none;
@@ -3236,8 +3152,8 @@ fn airArrayElemVal(self: *Self, inst: Air.Inst.Index) InnerError!WValue {
const bin_op = self.air.instructions.items(.data)[inst].bin_op;
const array_ty = self.air.typeOf(bin_op.lhs);
- const array = self.resolveInst(bin_op.lhs);
- const index = self.resolveInst(bin_op.rhs);
+ const array = try self.resolveInst(bin_op.lhs);
+ const index = try self.resolveInst(bin_op.rhs);
const elem_ty = array_ty.childType();
const elem_size = elem_ty.abiSize(self.target);
@@ -3261,7 +3177,7 @@ fn airFloatToInt(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 = self.resolveInst(ty_op.operand);
+ const operand = try self.resolveInst(ty_op.operand);
const dest_ty = self.air.typeOfIndex(inst);
const op_ty = self.air.typeOf(ty_op.operand);
@@ -3283,7 +3199,7 @@ fn airSplat(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 = self.resolveInst(ty_op.operand);
+ const operand = try self.resolveInst(ty_op.operand);
_ = ty_op;
_ = operand;