mirror of
https://github.com/ziglang/zig.git
synced 2026-02-12 20:37:54 +00:00
wasm: Implement @maximum & @minimum
This implements the `max` and `min` AIR instructions by checking whether LHS is great/lesser than RHS. If that's the case, we assign LHS to the result, otherwise assign RHS to it instead.
This commit is contained in:
parent
3ee44ce949
commit
219fa192c6
@ -1307,6 +1307,8 @@ fn genInst(self: *Self, inst: Air.Inst.Index) !WValue {
|
||||
.shl_exact => self.airBinOp(inst, .shl),
|
||||
.shr, .shr_exact => self.airBinOp(inst, .shr),
|
||||
.xor => self.airBinOp(inst, .xor),
|
||||
.max => self.airMaxMin(inst, .max),
|
||||
.min => self.airMaxMin(inst, .min),
|
||||
|
||||
.add_with_overflow => self.airBinOpOverflow(inst, .add),
|
||||
.sub_with_overflow => self.airBinOpOverflow(inst, .sub),
|
||||
@ -1431,8 +1433,6 @@ fn genInst(self: *Self, inst: Air.Inst.Index) !WValue {
|
||||
.div_floor,
|
||||
.div_exact,
|
||||
.mod,
|
||||
.max,
|
||||
.min,
|
||||
.assembly,
|
||||
.shl_sat,
|
||||
.ret_addr,
|
||||
@ -3873,3 +3873,42 @@ fn airBinOpOverflow(self: *Self, inst: Air.Inst.Index, op: Op) InnerError!WValue
|
||||
|
||||
return result_ptr;
|
||||
}
|
||||
|
||||
fn airMaxMin(self: *Self, inst: Air.Inst.Index, op: enum { max, min }) InnerError!WValue {
|
||||
if (self.liveness.isUnused(inst)) return WValue{ .none = {} };
|
||||
const bin_op = self.air.instructions.items(.data)[inst].bin_op;
|
||||
const ty = self.air.typeOfIndex(inst);
|
||||
if (ty.zigTypeTag() == .Vector) {
|
||||
return self.fail("TODO: `@maximum` and `@minimum` for vectors", .{});
|
||||
}
|
||||
|
||||
if (ty.abiSize(self.target) > 8) {
|
||||
return self.fail("TODO: `@maximum` and `@minimum` for types larger than 8 bytes", .{});
|
||||
}
|
||||
|
||||
const lhs = try self.resolveInst(bin_op.lhs);
|
||||
const rhs = try self.resolveInst(bin_op.rhs);
|
||||
|
||||
const result = try self.allocLocal(ty);
|
||||
|
||||
try self.startBlock(.block, wasm.block_empty);
|
||||
try self.startBlock(.block, wasm.block_empty);
|
||||
|
||||
// check if LHS is greater/lesser than RHS
|
||||
const cmp_result = try self.cmp(lhs, rhs, ty, if (op == .max) .gt else .lt);
|
||||
try self.addLabel(.local_get, cmp_result.local);
|
||||
try self.addLabel(.br_if, 0); // break to outer loop if LHS is greater/lesser than RHS
|
||||
|
||||
// set RHS as max/min
|
||||
try self.emitWValue(rhs);
|
||||
try self.addLabel(.local_set, result.local);
|
||||
try self.addLabel(.br, 1); // break out of all blocks
|
||||
try self.endBlock();
|
||||
|
||||
// set LHS as max/min
|
||||
try self.emitWValue(lhs);
|
||||
try self.addLabel(.local_set, result.local);
|
||||
try self.endBlock();
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user