Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add iadd_overflow_trap #5123

Merged
merged 12 commits into from
Oct 27, 2022
7 changes: 7 additions & 0 deletions cranelift/codegen/meta/src/shared/formats.rs
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ pub(crate) struct Formats {
pub(crate) int_compare: Rc<InstructionFormat>,
pub(crate) int_compare_imm: Rc<InstructionFormat>,
pub(crate) int_cond_trap: Rc<InstructionFormat>,
pub(crate) int_add_trap: Rc<InstructionFormat>,
pub(crate) jump: Rc<InstructionFormat>,
pub(crate) load: Rc<InstructionFormat>,
pub(crate) load_no_offset: Rc<InstructionFormat>,
Expand Down Expand Up @@ -223,6 +224,12 @@ impl Formats {
.imm(&imm.trapcode)
.build(),

int_add_trap: Builder::new("IntAddTrap")
.value()
.value()
.imm(&imm.trapcode)
.build(),

float_cond_trap: Builder::new("FloatCondTrap")
.imm(&imm.floatcc)
.value()
Expand Down
31 changes: 31 additions & 0 deletions cranelift/codegen/meta/src/shared/instructions.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2174,6 +2174,37 @@ pub(crate) fn define(
.operands_out(vec![a, c_if_out]),
);

{
let code = &Operand::new("code", &imm.trapcode);

let i32_64 = &TypeVar::new(
"i32_64",
"A 32 or 64-bit scalar integer type",
TypeSetBuilder::new().ints(32..64).build(),
);

let a = &Operand::new("a", i32_64);
let x = &Operand::new("x", i32_64);
let y = &Operand::new("y", i32_64);
ig.push(
Inst::new(
"iadd_overflow_trap",
r#"
Add 32 or 64-bit integers, and trap if overflow occurs.

This is the same as `iadd_cout` but traps instead of returning a carry flag.
elliottt marked this conversation as resolved.
Show resolved Hide resolved

Polymorphic over all scalar integer types, but does not support vector
types.
"#,
&formats.int_add_trap,
)
.operands_in(vec![x, y, code])
.operands_out(vec![a])
.can_trap(true),
);
}

ig.push(
Inst::new(
"isub_bin",
Expand Down
2 changes: 2 additions & 0 deletions cranelift/codegen/src/isa/aarch64/lower_inst.rs
Original file line number Diff line number Diff line change
Expand Up @@ -259,6 +259,8 @@ pub(crate) fn lower_insn_to_regs(

Opcode::IaddIfcout => implemented_in_isle(ctx),

Opcode::IaddOverflowTrap => implemented_in_isle(ctx),

Opcode::IaddImm
| Opcode::ImulImm
| Opcode::UdivImm
Expand Down
1 change: 1 addition & 0 deletions cranelift/codegen/src/isa/s390x/lower.rs
Original file line number Diff line number Diff line change
Expand Up @@ -241,6 +241,7 @@ impl LowerBackend for S390xBackend {
| Opcode::IaddCout
| Opcode::IaddCarry
| Opcode::IaddIfcarry
| Opcode::IaddOverflowTrap
| Opcode::IsubBin
| Opcode::IsubIfbin
| Opcode::IsubBout
Expand Down
35 changes: 35 additions & 0 deletions cranelift/codegen/src/isa/x64/lower.isle
Original file line number Diff line number Diff line change
Expand Up @@ -1352,6 +1352,41 @@
(rule (lower (trap code))
(side_effect (x64_ud2 code)))

;;;; Rules for `iadd_overflow_trap` ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

(rule (lower (has_type (fits_in_64 ty) (iadd_overflow_trap a b tc)))
(with_flags
(x64_add_with_flags_paired ty a b)
(trap_if (CC.B) tc)))

;; Add a register and constant.

(rule 1 (lower (has_type (fits_in_64 ty)
(iadd_overflow_trap a (simm32_from_value b) tc)))
(with_flags
(x64_add_with_flags_paired ty a b)
(trap_if (CC.B) tc)))

(rule 2 (lower (has_type (fits_in_64 ty)
(iadd_overflow_trap (simm32_from_value a) b tc)))
(with_flags
(x64_add_with_flags_paired ty b a)
(trap_if (CC.B) tc)))

;; Add a register and memory.

(rule 3 (lower (has_type (fits_in_64 ty)
(iadd_overflow_trap a (sinkable_load b) tc)))
(with_flags
(x64_add_with_flags_paired ty a (sink_load_to_gpr_mem_imm b))
(trap_if (CC.B) tc)))

(rule 4 (lower (has_type (fits_in_64 ty)
(iadd_overflow_trap (sinkable_load a) b tc)))
(with_flags
(x64_add_with_flags_paired ty b (sink_load_to_gpr_mem_imm a))
(trap_if (CC.B) tc)))

;;;; Rules for `trapif` ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

;; The flags must not have been clobbered by any other instruction between the
Expand Down
1 change: 1 addition & 0 deletions cranelift/codegen/src/isa/x64/lower.rs
Original file line number Diff line number Diff line change
Expand Up @@ -521,6 +521,7 @@ fn lower_insn_to_regs(
| Opcode::IaddCout
| Opcode::IaddCarry
| Opcode::IaddIfcarry
| Opcode::IaddOverflowTrap
| Opcode::IsubBin
| Opcode::IsubIfbin
| Opcode::IsubBout
Expand Down
8 changes: 8 additions & 0 deletions cranelift/codegen/src/prelude_lower.isle
Original file line number Diff line number Diff line change
Expand Up @@ -425,6 +425,14 @@
(_y Unit (emit consumer_inst)))
(value_regs producer_result consumer_result)))

;; A flag-producer that also produces a result, paired with a consumer that has
;; no results.
(rule (with_flags (ProducesFlags.ProducesFlagsReturnsResultWithConsumer producer_inst producer_result)
(ConsumesFlags.ConsumesFlagsSideEffect consumer_inst))
(let ((_ Unit (emit producer_inst))
(_ Unit (emit consumer_inst)))
(value_reg producer_result)))

(rule (with_flags (ProducesFlags.ProducesFlagsSideEffect producer_inst)
(ConsumesFlags.ConsumesFlagsReturnsReg consumer_inst consumer_result))
(let ((_x Unit (emit producer_inst))
Expand Down
1 change: 1 addition & 0 deletions cranelift/codegen/src/verifier/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -759,6 +759,7 @@ impl<'a> Verifier<'a> {
| Ternary { .. }
| TernaryImm8 { .. }
| Shuffle { .. }
| IntAddTrap { .. }
| IntCompare { .. }
| IntCompareImm { .. }
| FloatCompare { .. }
Expand Down
1 change: 1 addition & 0 deletions cranelift/codegen/src/write.rs
Original file line number Diff line number Diff line change
Expand Up @@ -418,6 +418,7 @@ pub fn write_operands(w: &mut dyn Write, dfg: &DataFlowGraph, inst: Inst) -> fmt
}
IntCompare { cond, args, .. } => write!(w, " {} {}, {}", cond, args[0], args[1]),
IntCompareImm { cond, arg, imm, .. } => write!(w, " {} {}, {}", cond, arg, imm),
IntAddTrap { args, code, .. } => write!(w, " {}, {}, {}", args[0], args[1], code),
FloatCompare { cond, args, .. } => write!(w, " {} {}, {}", cond, args[0], args[1]),
Jump {
destination,
Expand Down
9 changes: 9 additions & 0 deletions cranelift/interpreter/src/step.rs
Original file line number Diff line number Diff line change
Expand Up @@ -754,6 +754,15 @@ where
assign_multiple(&[sum, Value::bool(carry, false, types::I8)?])
}
Opcode::IaddIfcarry => unimplemented!("IaddIfcarry"),
Opcode::IaddOverflowTrap => {
let sum = Value::add(arg(0)?, arg(1)?)?;
let carry = Value::lt(&sum, &arg(0)?)? && Value::lt(&sum, &arg(1)?)?;
if carry {
ControlFlow::Trap(CraneliftTrap::User(trap_code()))
} else {
assign(sum)
}
}
Opcode::IsubBin => choose(
Value::into_bool(arg(2)?)?,
Value::sub(arg(0)?, Value::add(arg(1)?, Value::int(1, ctrl_ty)?)?)?,
Expand Down
12 changes: 12 additions & 0 deletions cranelift/reader/src/parser.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3091,6 +3091,18 @@ impl<'a> Parser<'a> {
args: [arg, addr],
}
}
InstructionFormat::IntAddTrap => {
let a = self.match_value("expected SSA value operand")?;
self.match_token(Token::Comma, "expected ',' between operands")?;
let b = self.match_value("expected SSA value operand")?;
self.match_token(Token::Comma, "expected ',' between operands")?;
let code = self.match_enum("expected trap code")?;
InstructionData::IntAddTrap {
opcode,
args: [a, b],
code,
}
}
};
Ok(idata)
}
Expand Down