| ... | ... | @@ -1148,6 +1148,7 @@ fn genInst(self: *Self, inst: Air.Inst.Index) !WValue { |
| 1148 | 1148 | .unwrap_errunion_payload => self.airUnwrapErrUnionPayload(inst), |
| 1149 | 1149 | .unwrap_errunion_err => self.airUnwrapErrUnionError(inst), |
| 1150 | 1150 | .wrap_errunion_payload => self.airWrapErrUnionPayload(inst), |
| 1151 | .wrap_errunion_err => self.airWrapErrUnionErr(inst), |
| 1151 | 1152 | |
| 1152 | 1153 | .optional_payload => self.airOptionalPayload(inst), |
| 1153 | 1154 | .optional_payload_ptr => self.airOptionalPayload(inst), |
| ... | ... | @@ -1328,16 +1329,15 @@ fn store(self: *Self, lhs: WValue, rhs: WValue, ty: Type, offset: u32) InnerErro |
| 1328 | 1329 | return; |
| 1329 | 1330 | }, |
| 1330 | 1331 | .local => { |
| 1331 | | // Load values from `rhs` stack position and store in `lhs` instead |
| 1332 | | const tag_local = try self.load(rhs, tag_ty, 0); |
| 1333 | | const payload_local = try self.load(rhs, payload_ty, payload_offset); |
| 1334 | | |
| 1335 | | try self.store(lhs, tag_local, tag_ty, 0); |
| 1336 | | return try self.store(lhs, payload_local, payload_ty, payload_offset); |
| 1332 | if (payload_ty.hasCodeGenBits()) { |
| 1333 | try self.store(lhs, rhs, payload_ty, payload_offset); |
| 1334 | } |
| 1335 | return try self.store(lhs, rhs, tag_ty, 0); |
| 1337 | 1336 | }, |
| 1338 | 1337 | .local_with_offset => |with_offset| { |
| 1339 | 1338 | const tag_local = try self.allocLocal(tag_ty); |
| 1340 | 1339 | try self.addImm32(0); |
| 1340 | try self.addLabel(.local_set, tag_local.local); |
| 1341 | 1341 | try self.store(lhs, tag_local, tag_ty, 0); |
| 1342 | 1342 | |
| 1343 | 1343 | return try self.store( |
| ... | ... | @@ -1415,7 +1415,10 @@ fn load(self: *Self, operand: WValue, ty: Type, offset: u32) InnerError!WValue { |
| 1415 | 1415 | // load local's value from memory by its stack position |
| 1416 | 1416 | try self.emitWValue(operand); |
| 1417 | 1417 | // Build the opcode with the right bitsize |
| 1418 | | const signedness: std.builtin.Signedness = if (ty.isUnsignedInt()) .unsigned else .signed; |
| 1418 | const signedness: std.builtin.Signedness = if (ty.isUnsignedInt() or ty.zigTypeTag() == .ErrorSet) |
| 1419 | .unsigned |
| 1420 | else |
| 1421 | .signed; |
| 1419 | 1422 | // check if we should pass by pointer or value based on ABI size |
| 1420 | 1423 | // TODO: Implement a way to get ABI values from a given type, |
| 1421 | 1424 | // that is portable across the backend, rather than copying logic. |
| ... | ... | @@ -2081,9 +2084,25 @@ fn airUnwrapErrUnionError(self: *Self, inst: Air.Inst.Index) InnerError!WValue { |
| 2081 | 2084 | } |
| 2082 | 2085 | |
| 2083 | 2086 | fn airWrapErrUnionPayload(self: *Self, inst: Air.Inst.Index) InnerError!WValue { |
| 2087 | if (self.liveness.isUnused(inst)) return WValue.none; |
| 2088 | const ty_op = self.air.instructions.items(.data)[inst].ty_op; |
| 2089 | const operand = self.resolveInst(ty_op.operand); |
| 2090 | |
| 2091 | const op_ty = self.air.typeOf(ty_op.operand); |
| 2092 | if (!op_ty.hasCodeGenBits()) return WValue.none; |
| 2093 | const err_ty = self.air.getRefType(ty_op.ty); |
| 2094 | const offset = err_ty.errorUnionSet().abiSize(self.target); |
| 2095 | |
| 2096 | return WValue{ .local_with_offset = .{ |
| 2097 | .local = operand.local, |
| 2098 | .offset = @intCast(u32, offset), |
| 2099 | } }; |
| 2100 | } |
| 2101 | |
| 2102 | fn airWrapErrUnionErr(self: *Self, inst: Air.Inst.Index) InnerError!WValue { |
| 2103 | if (self.liveness.isUnused(inst)) return WValue.none; |
| 2084 | 2104 | const ty_op = self.air.instructions.items(.data)[inst].ty_op; |
| 2085 | | _ = ty_op; |
| 2086 | | return self.fail("TODO: wasm airWrapErrUnionPayload", .{}); |
| 2105 | return self.resolveInst(ty_op.operand); |
| 2087 | 2106 | } |
| 2088 | 2107 | |
| 2089 | 2108 | fn airIntcast(self: *Self, inst: Air.Inst.Index) InnerError!WValue { |