diff --git a/cranelift/docs/langref.rst b/cranelift/docs/langref.rst index b4a9f1dcb2..17a146ba07 100644 --- a/cranelift/docs/langref.rst +++ b/cranelift/docs/langref.rst @@ -380,6 +380,7 @@ is zero. .. autoinst:: trap .. autoinst:: trapz .. autoinst:: trapnz +.. autoinst:: trapif Function calls diff --git a/cranelift/filetests/parser/tiny.cton b/cranelift/filetests/parser/tiny.cton index 5e8c8e85c3..748c8f9a13 100644 --- a/cranelift/filetests/parser/tiny.cton +++ b/cranelift/filetests/parser/tiny.cton @@ -210,3 +210,18 @@ ebb0: ; nextln: copy_special %20 -> %10 ; nextln: return ; nextln: } + +function %cond_traps(i32) { +ebb0(v0: i32): + trapz v0, stk_ovf + v1 = ifcmp_imm v0, 5 + trapif ugt v1, oob + return +} +; sameln: function %cond_traps(i32) +; nextln: ebb0($v0: i32): +; nextln: trapz $v0, stk_ovf +; nextln: $v1 = ifcmp_imm v0, 5 +; nextln: trapif ugt $v1, oob +; nextln: return +; nextln: } diff --git a/lib/cretonne/meta/base/formats.py b/lib/cretonne/meta/base/formats.py index 394e1f4dc4..1be94a7b09 100644 --- a/lib/cretonne/meta/base/formats.py +++ b/lib/cretonne/meta/base/formats.py @@ -74,6 +74,7 @@ RegFill = InstructionFormat( Trap = InstructionFormat(trapcode) CondTrap = InstructionFormat(VALUE, trapcode) +IntCondTrap = InstructionFormat(intcc, VALUE, trapcode) # Finally extract the names of global variables in this module. InstructionFormat.extract_names(globals()) diff --git a/lib/cretonne/meta/base/instructions.py b/lib/cretonne/meta/base/instructions.py index fad863d976..875a0e7537 100644 --- a/lib/cretonne/meta/base/instructions.py +++ b/lib/cretonne/meta/base/instructions.py @@ -167,6 +167,15 @@ trapnz = Instruction( """, ins=(c, code), can_trap=True) +Cond = Operand('Cond', intcc) +f = Operand('f', iflags) + +trapif = Instruction( + 'trapif', r""" + Trap when condition is true in integer CPU flags. + """, + ins=(Cond, f, code), can_trap=True) + rvals = Operand('rvals', VARIABLE_ARGS, doc='return values') x_return = Instruction( diff --git a/lib/cretonne/src/ir/instructions.rs b/lib/cretonne/src/ir/instructions.rs index 9e28616377..449da29b93 100644 --- a/lib/cretonne/src/ir/instructions.rs +++ b/lib/cretonne/src/ir/instructions.rs @@ -264,6 +264,12 @@ pub enum InstructionData { arg: Value, code: ir::TrapCode, }, + IntCondTrap { + opcode: Opcode, + cond: IntCC, + arg: Value, + code: ir::TrapCode, + }, } /// A variable list of `Value` operands used for function call arguments and passing arguments to diff --git a/lib/cretonne/src/verifier/mod.rs b/lib/cretonne/src/verifier/mod.rs index 1b27c41766..fa5c751430 100644 --- a/lib/cretonne/src/verifier/mod.rs +++ b/lib/cretonne/src/verifier/mod.rs @@ -365,6 +365,7 @@ impl<'a> Verifier<'a> { CopySpecial { .. } | Trap { .. } | CondTrap { .. } | + IntCondTrap { .. } | NullAry { .. } => {} } diff --git a/lib/cretonne/src/write.rs b/lib/cretonne/src/write.rs index 2312e5644f..ea9e3a3e4a 100644 --- a/lib/cretonne/src/write.rs +++ b/lib/cretonne/src/write.rs @@ -428,6 +428,7 @@ pub fn write_operands( } Trap { code, .. } => write!(w, " {}", code), CondTrap { arg, code, .. } => write!(w, " {}, {}", arg, code), + IntCondTrap { cond, arg, code, .. } => write!(w, " {} {}, {}", cond, arg, code), } } diff --git a/lib/reader/src/parser.rs b/lib/reader/src/parser.rs index 95923d013d..c4c7b6e852 100644 --- a/lib/reader/src/parser.rs +++ b/lib/reader/src/parser.rs @@ -2348,6 +2348,21 @@ impl<'a> Parser<'a> { let code = self.match_enum("expected trap code")?; InstructionData::CondTrap { opcode, arg, code } } + InstructionFormat::IntCondTrap => { + let cond = self.match_enum("expected intcc condition code")?; + let arg = self.match_value("expected SSA value operand")?; + self.match_token( + Token::Comma, + "expected ',' between operands", + )?; + let code = self.match_enum("expected trap code")?; + InstructionData::IntCondTrap { + opcode, + cond, + arg, + code, + } + } }; Ok(idata) }