Add custom legalization for conditional traps.
The expansion of these instructions requires the CFG to be modified, something the Python XForms can't yet do.
This commit is contained in:
30
cranelift/filetests/isa/intel/legalize-custom.cton
Normal file
30
cranelift/filetests/isa/intel/legalize-custom.cton
Normal file
@@ -0,0 +1,30 @@
|
||||
; Test the custom legalizations.
|
||||
test legalizer
|
||||
isa intel
|
||||
set is_64bit
|
||||
isa intel
|
||||
|
||||
; regex: V=v\d+
|
||||
; regex: EBB=ebb\d+
|
||||
|
||||
function %cond_trap(i32) {
|
||||
ebb0(v1: i32):
|
||||
trapz v1
|
||||
return
|
||||
; check: $ebb0($v1: i32):
|
||||
; nextln: brnz $v1, $(new=$EBB)
|
||||
; nextln: trap
|
||||
; check: $new:
|
||||
; nextln: return
|
||||
}
|
||||
|
||||
function %cond_trap2(i32) {
|
||||
ebb0(v1: i32):
|
||||
trapnz v1
|
||||
return
|
||||
; check: $ebb0($v1: i32):
|
||||
; nextln: brz $v1, $(new=$EBB)
|
||||
; nextln: trap
|
||||
; check: $new:
|
||||
; nextln: return
|
||||
}
|
||||
@@ -48,6 +48,11 @@ expand = XFormGroup('expand', """
|
||||
expand.custom_legalize(insts.global_addr, 'expand_global_addr')
|
||||
expand.custom_legalize(insts.heap_addr, 'expand_heap_addr')
|
||||
|
||||
# Custom expansions that need to change the CFG.
|
||||
# TODO: Add sufficient XForm syntax that we don't need to hand-code these.
|
||||
expand.custom_legalize(insts.trapz, 'expand_cond_trap')
|
||||
expand.custom_legalize(insts.trapnz, 'expand_cond_trap')
|
||||
|
||||
x = Var('x')
|
||||
y = Var('y')
|
||||
a = Var('a')
|
||||
|
||||
@@ -15,7 +15,7 @@
|
||||
|
||||
use cursor::{Cursor, FuncCursor};
|
||||
use flowgraph::ControlFlowGraph;
|
||||
use ir;
|
||||
use ir::{self, InstBuilder};
|
||||
use isa::TargetIsa;
|
||||
use bitset::BitSet;
|
||||
|
||||
@@ -96,3 +96,49 @@ pub fn legalize_function(func: &mut ir::Function, cfg: &mut ControlFlowGraph, is
|
||||
//
|
||||
// Concretely, this defines private functions `narrow()`, and `expand()`.
|
||||
include!(concat!(env!("OUT_DIR"), "/legalizer.rs"));
|
||||
|
||||
/// Custom expansion for conditional trap instructions.
|
||||
/// TODO: Add CFG support to the Python patterns so we won't have to do this.
|
||||
fn expand_cond_trap(inst: ir::Inst, func: &mut ir::Function, cfg: &mut ControlFlowGraph) {
|
||||
// Parse the instruction.
|
||||
let trapz;
|
||||
let arg = match func.dfg[inst] {
|
||||
ir::InstructionData::Unary { opcode, arg } => {
|
||||
// We want to branch *over* an unconditional trap.
|
||||
trapz = match opcode {
|
||||
ir::Opcode::Trapz => true,
|
||||
ir::Opcode::Trapnz => false,
|
||||
_ => panic!("Expected cond trap: {}", func.dfg.display_inst(inst, None)),
|
||||
};
|
||||
arg
|
||||
}
|
||||
_ => panic!("Expected cond trap: {}", func.dfg.display_inst(inst, None)),
|
||||
};
|
||||
|
||||
// Split the EBB after `inst`:
|
||||
//
|
||||
// trapnz arg
|
||||
//
|
||||
// Becomes:
|
||||
//
|
||||
// brz arg, new_ebb
|
||||
// trap
|
||||
// new_ebb:
|
||||
//
|
||||
let old_ebb = func.layout.pp_ebb(inst);
|
||||
let new_ebb = func.dfg.make_ebb();
|
||||
if trapz {
|
||||
func.dfg.replace(inst).brnz(arg, new_ebb, &[]);
|
||||
} else {
|
||||
func.dfg.replace(inst).brz(arg, new_ebb, &[]);
|
||||
}
|
||||
|
||||
let mut pos = FuncCursor::new(func).at_inst(inst);
|
||||
pos.next_inst();
|
||||
pos.ins().trap();
|
||||
pos.insert_ebb(new_ebb);
|
||||
|
||||
// Finally update the CFG.
|
||||
cfg.recompute_ebb(pos.func, old_ebb);
|
||||
cfg.recompute_ebb(pos.func, new_ebb);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user