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.global_addr, 'expand_global_addr')
|
||||||
expand.custom_legalize(insts.heap_addr, 'expand_heap_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')
|
x = Var('x')
|
||||||
y = Var('y')
|
y = Var('y')
|
||||||
a = Var('a')
|
a = Var('a')
|
||||||
|
|||||||
@@ -15,7 +15,7 @@
|
|||||||
|
|
||||||
use cursor::{Cursor, FuncCursor};
|
use cursor::{Cursor, FuncCursor};
|
||||||
use flowgraph::ControlFlowGraph;
|
use flowgraph::ControlFlowGraph;
|
||||||
use ir;
|
use ir::{self, InstBuilder};
|
||||||
use isa::TargetIsa;
|
use isa::TargetIsa;
|
||||||
use bitset::BitSet;
|
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()`.
|
// Concretely, this defines private functions `narrow()`, and `expand()`.
|
||||||
include!(concat!(env!("OUT_DIR"), "/legalizer.rs"));
|
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