cranelift: Port trap and resumable_trap lowering to ISLE on x64
This commit is contained in:
@@ -1,4 +1,4 @@
|
|||||||
src/clif.isle f176ef3bba99365
|
src/clif.isle f176ef3bba99365
|
||||||
src/prelude.isle 7b911d3b894ae17
|
src/prelude.isle 181213982a49a4b8
|
||||||
src/isa/aarch64/inst.isle 5fa80451697b084f
|
src/isa/aarch64/inst.isle 5fa80451697b084f
|
||||||
src/isa/aarch64/lower.isle 2d2e1e076a0c8a23
|
src/isa/aarch64/lower.isle 2d2e1e076a0c8a23
|
||||||
|
|||||||
@@ -24,6 +24,7 @@ pub trait Context {
|
|||||||
fn u8_and(&mut self, arg0: u8, arg1: u8) -> u8;
|
fn u8_and(&mut self, arg0: u8, arg1: u8) -> u8;
|
||||||
fn value_reg(&mut self, arg0: Reg) -> ValueRegs;
|
fn value_reg(&mut self, arg0: Reg) -> ValueRegs;
|
||||||
fn value_regs(&mut self, arg0: Reg, arg1: Reg) -> ValueRegs;
|
fn value_regs(&mut self, arg0: Reg, arg1: Reg) -> ValueRegs;
|
||||||
|
fn value_regs_invalid(&mut self) -> ValueRegs;
|
||||||
fn temp_writable_reg(&mut self, arg0: Type) -> WritableReg;
|
fn temp_writable_reg(&mut self, arg0: Type) -> WritableReg;
|
||||||
fn invalid_reg(&mut self) -> Reg;
|
fn invalid_reg(&mut self) -> Reg;
|
||||||
fn put_in_reg(&mut self, arg0: Value) -> Reg;
|
fn put_in_reg(&mut self, arg0: Value) -> Reg;
|
||||||
@@ -92,13 +93,19 @@ pub trait Context {
|
|||||||
fn rotr_opposite_amount(&mut self, arg0: Type, arg1: ImmShift) -> ImmShift;
|
fn rotr_opposite_amount(&mut self, arg0: Type, arg1: ImmShift) -> ImmShift;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Internal type ProducesFlags: defined at src/prelude.isle line 277.
|
/// Internal type SideEffectNoResult: defined at src/prelude.isle line 279.
|
||||||
|
#[derive(Clone, Debug)]
|
||||||
|
pub enum SideEffectNoResult {
|
||||||
|
Inst { inst: MInst },
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Internal type ProducesFlags: defined at src/prelude.isle line 292.
|
||||||
#[derive(Clone, Debug)]
|
#[derive(Clone, Debug)]
|
||||||
pub enum ProducesFlags {
|
pub enum ProducesFlags {
|
||||||
ProducesFlags { inst: MInst, result: Reg },
|
ProducesFlags { inst: MInst, result: Reg },
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Internal type ConsumesFlags: defined at src/prelude.isle line 280.
|
/// Internal type ConsumesFlags: defined at src/prelude.isle line 295.
|
||||||
#[derive(Clone, Debug)]
|
#[derive(Clone, Debug)]
|
||||||
pub enum ConsumesFlags {
|
pub enum ConsumesFlags {
|
||||||
ConsumesFlags { inst: MInst, result: Reg },
|
ConsumesFlags { inst: MInst, result: Reg },
|
||||||
@@ -978,7 +985,7 @@ pub enum AtomicRMWOp {
|
|||||||
// Generated as internal constructor for term temp_reg.
|
// Generated as internal constructor for term temp_reg.
|
||||||
pub fn constructor_temp_reg<C: Context>(ctx: &mut C, arg0: Type) -> Option<Reg> {
|
pub fn constructor_temp_reg<C: Context>(ctx: &mut C, arg0: Type) -> Option<Reg> {
|
||||||
let pattern0_0 = arg0;
|
let pattern0_0 = arg0;
|
||||||
// Rule at src/prelude.isle line 66.
|
// Rule at src/prelude.isle line 70.
|
||||||
let expr0_0 = C::temp_writable_reg(ctx, pattern0_0);
|
let expr0_0 = C::temp_writable_reg(ctx, pattern0_0);
|
||||||
let expr1_0 = C::writable_reg_to_reg(ctx, expr0_0);
|
let expr1_0 = C::writable_reg_to_reg(ctx, expr0_0);
|
||||||
return Some(expr1_0);
|
return Some(expr1_0);
|
||||||
@@ -987,13 +994,31 @@ pub fn constructor_temp_reg<C: Context>(ctx: &mut C, arg0: Type) -> Option<Reg>
|
|||||||
// Generated as internal constructor for term lo_reg.
|
// Generated as internal constructor for term lo_reg.
|
||||||
pub fn constructor_lo_reg<C: Context>(ctx: &mut C, arg0: Value) -> Option<Reg> {
|
pub fn constructor_lo_reg<C: Context>(ctx: &mut C, arg0: Value) -> Option<Reg> {
|
||||||
let pattern0_0 = arg0;
|
let pattern0_0 = arg0;
|
||||||
// Rule at src/prelude.isle line 101.
|
// Rule at src/prelude.isle line 105.
|
||||||
let expr0_0 = C::put_in_regs(ctx, pattern0_0);
|
let expr0_0 = C::put_in_regs(ctx, pattern0_0);
|
||||||
let expr1_0: usize = 0;
|
let expr1_0: usize = 0;
|
||||||
let expr2_0 = C::value_regs_get(ctx, expr0_0, expr1_0);
|
let expr2_0 = C::value_regs_get(ctx, expr0_0, expr1_0);
|
||||||
return Some(expr2_0);
|
return Some(expr2_0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Generated as internal constructor for term value_regs_none.
|
||||||
|
pub fn constructor_value_regs_none<C: Context>(
|
||||||
|
ctx: &mut C,
|
||||||
|
arg0: &SideEffectNoResult,
|
||||||
|
) -> Option<ValueRegs> {
|
||||||
|
let pattern0_0 = arg0;
|
||||||
|
if let &SideEffectNoResult::Inst {
|
||||||
|
inst: ref pattern1_0,
|
||||||
|
} = pattern0_0
|
||||||
|
{
|
||||||
|
// Rule at src/prelude.isle line 284.
|
||||||
|
let expr0_0 = C::emit(ctx, &pattern1_0);
|
||||||
|
let expr1_0 = C::value_regs_invalid(ctx);
|
||||||
|
return Some(expr1_0);
|
||||||
|
}
|
||||||
|
return None;
|
||||||
|
}
|
||||||
|
|
||||||
// Generated as internal constructor for term with_flags.
|
// Generated as internal constructor for term with_flags.
|
||||||
pub fn constructor_with_flags<C: Context>(
|
pub fn constructor_with_flags<C: Context>(
|
||||||
ctx: &mut C,
|
ctx: &mut C,
|
||||||
@@ -1012,7 +1037,7 @@ pub fn constructor_with_flags<C: Context>(
|
|||||||
result: pattern3_1,
|
result: pattern3_1,
|
||||||
} = pattern2_0
|
} = pattern2_0
|
||||||
{
|
{
|
||||||
// Rule at src/prelude.isle line 290.
|
// Rule at src/prelude.isle line 305.
|
||||||
let expr0_0 = C::emit(ctx, &pattern1_0);
|
let expr0_0 = C::emit(ctx, &pattern1_0);
|
||||||
let expr1_0 = C::emit(ctx, &pattern3_0);
|
let expr1_0 = C::emit(ctx, &pattern3_0);
|
||||||
let expr2_0 = C::value_regs(ctx, pattern1_1, pattern3_1);
|
let expr2_0 = C::value_regs(ctx, pattern1_1, pattern3_1);
|
||||||
@@ -1040,7 +1065,7 @@ pub fn constructor_with_flags_1<C: Context>(
|
|||||||
result: pattern3_1,
|
result: pattern3_1,
|
||||||
} = pattern2_0
|
} = pattern2_0
|
||||||
{
|
{
|
||||||
// Rule at src/prelude.isle line 298.
|
// Rule at src/prelude.isle line 313.
|
||||||
let expr0_0 = C::emit(ctx, &pattern1_0);
|
let expr0_0 = C::emit(ctx, &pattern1_0);
|
||||||
let expr1_0 = C::emit(ctx, &pattern3_0);
|
let expr1_0 = C::emit(ctx, &pattern3_0);
|
||||||
return Some(pattern3_1);
|
return Some(pattern3_1);
|
||||||
@@ -1074,7 +1099,7 @@ pub fn constructor_with_flags_2<C: Context>(
|
|||||||
result: pattern5_1,
|
result: pattern5_1,
|
||||||
} = pattern4_0
|
} = pattern4_0
|
||||||
{
|
{
|
||||||
// Rule at src/prelude.isle line 308.
|
// Rule at src/prelude.isle line 323.
|
||||||
let expr0_0 = C::emit(ctx, &pattern1_0);
|
let expr0_0 = C::emit(ctx, &pattern1_0);
|
||||||
let expr1_0 = C::emit(ctx, &pattern5_0);
|
let expr1_0 = C::emit(ctx, &pattern5_0);
|
||||||
let expr2_0 = C::emit(ctx, &pattern3_0);
|
let expr2_0 = C::emit(ctx, &pattern3_0);
|
||||||
|
|||||||
@@ -4,6 +4,7 @@
|
|||||||
|
|
||||||
(type MInst extern
|
(type MInst extern
|
||||||
(enum (Nop (len u8))
|
(enum (Nop (len u8))
|
||||||
|
(Ud2 (trap_code TrapCode))
|
||||||
(AluRmiR (size OperandSize)
|
(AluRmiR (size OperandSize)
|
||||||
(op AluRmiROpcode)
|
(op AluRmiROpcode)
|
||||||
(src1 Reg)
|
(src1 Reg)
|
||||||
@@ -1444,3 +1445,8 @@
|
|||||||
(let ((dst WritableReg (temp_writable_reg $I64))
|
(let ((dst WritableReg (temp_writable_reg $I64))
|
||||||
(_ Unit (emit (MInst.LoadEffectiveAddress addr dst))))
|
(_ Unit (emit (MInst.LoadEffectiveAddress addr dst))))
|
||||||
(writable_reg_to_reg dst)))
|
(writable_reg_to_reg dst)))
|
||||||
|
|
||||||
|
;; Helper for creating `ud2` instructions.
|
||||||
|
(decl ud2 (TrapCode) SideEffectNoResult)
|
||||||
|
(rule (ud2 code)
|
||||||
|
(SideEffectNoResult.Inst (MInst.Ud2 code)))
|
||||||
|
|||||||
@@ -1432,3 +1432,13 @@
|
|||||||
|
|
||||||
(rule (lower (has_type $I32X4 (umin x y)))
|
(rule (lower (has_type $I32X4 (umin x y)))
|
||||||
(value_reg (pminud (put_in_reg x) (put_in_reg_mem y))))
|
(value_reg (pminud (put_in_reg x) (put_in_reg_mem y))))
|
||||||
|
|
||||||
|
;;;; Rules for `trap` ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||||
|
|
||||||
|
(rule (lower (trap code))
|
||||||
|
(value_regs_none (ud2 code)))
|
||||||
|
|
||||||
|
;;;; Rules for `resumable_trap` ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||||
|
|
||||||
|
(rule (lower (resumable_trap code))
|
||||||
|
(value_regs_none (ud2 code)))
|
||||||
|
|||||||
@@ -1234,7 +1234,9 @@ fn lower_insn_to_regs<C: LowerCtx<I = Inst>>(
|
|||||||
| Opcode::Ishl
|
| Opcode::Ishl
|
||||||
| Opcode::Rotl
|
| Opcode::Rotl
|
||||||
| Opcode::Rotr
|
| Opcode::Rotr
|
||||||
| Opcode::Ineg => implemented_in_isle(ctx),
|
| Opcode::Ineg
|
||||||
|
| Opcode::Trap
|
||||||
|
| Opcode::ResumableTrap => implemented_in_isle(ctx),
|
||||||
|
|
||||||
Opcode::Clz => {
|
Opcode::Clz => {
|
||||||
let orig_ty = ty.unwrap();
|
let orig_ty = ty.unwrap();
|
||||||
@@ -2369,11 +2371,6 @@ fn lower_insn_to_regs<C: LowerCtx<I = Inst>>(
|
|||||||
ctx.emit(Inst::Hlt);
|
ctx.emit(Inst::Hlt);
|
||||||
}
|
}
|
||||||
|
|
||||||
Opcode::Trap | Opcode::ResumableTrap => {
|
|
||||||
let trap_code = ctx.data(insn).trap_code().unwrap();
|
|
||||||
ctx.emit_safepoint(Inst::Ud2 { trap_code });
|
|
||||||
}
|
|
||||||
|
|
||||||
Opcode::Trapif | Opcode::Trapff => {
|
Opcode::Trapif | Opcode::Trapff => {
|
||||||
let trap_code = ctx.data(insn).trap_code().unwrap();
|
let trap_code = ctx.data(insn).trap_code().unwrap();
|
||||||
|
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
src/clif.isle f176ef3bba99365
|
src/clif.isle f176ef3bba99365
|
||||||
src/prelude.isle 7b911d3b894ae17
|
src/prelude.isle 181213982a49a4b8
|
||||||
src/isa/x64/inst.isle 755420ee1a9c7aeb
|
src/isa/x64/inst.isle 61004acbb1289816
|
||||||
src/isa/x64/lower.isle 38ddbc7b4a8444cf
|
src/isa/x64/lower.isle 82db7f7d47ac7809
|
||||||
|
|||||||
File diff suppressed because it is too large
Load Diff
@@ -48,6 +48,11 @@ macro_rules! isle_prelude_methods {
|
|||||||
ValueRegs::two(r1, r2)
|
ValueRegs::two(r1, r2)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
fn value_regs_invalid(&mut self) -> ValueRegs {
|
||||||
|
ValueRegs::invalid()
|
||||||
|
}
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
fn temp_writable_reg(&mut self, ty: Type) -> WritableReg {
|
fn temp_writable_reg(&mut self, ty: Type) -> WritableReg {
|
||||||
let value_regs = self.lower_ctx.alloc_tmp(ty);
|
let value_regs = self.lower_ctx.alloc_tmp(ty);
|
||||||
|
|||||||
@@ -57,6 +57,10 @@
|
|||||||
(decl value_regs (Reg Reg) ValueRegs)
|
(decl value_regs (Reg Reg) ValueRegs)
|
||||||
(extern constructor value_regs value_regs)
|
(extern constructor value_regs value_regs)
|
||||||
|
|
||||||
|
;; Construct an empty `ValueRegs` containing only invalid register sentinals.
|
||||||
|
(decl value_regs_invalid () ValueRegs)
|
||||||
|
(extern constructor value_regs_invalid value_regs_invalid)
|
||||||
|
|
||||||
;; Get a temporary register for writing.
|
;; Get a temporary register for writing.
|
||||||
(decl temp_writable_reg (Type) WritableReg)
|
(decl temp_writable_reg (Type) WritableReg)
|
||||||
(extern constructor temp_writable_reg temp_writable_reg)
|
(extern constructor temp_writable_reg temp_writable_reg)
|
||||||
@@ -270,6 +274,17 @@
|
|||||||
(extractor (u64_from_iconst x)
|
(extractor (u64_from_iconst x)
|
||||||
(def_inst (iconst (u64_from_imm64 x))))
|
(def_inst (iconst (u64_from_imm64 x))))
|
||||||
|
|
||||||
|
;;;; Helpers for Side-Effectful Instructions Without Results ;;;;;;;;;;;;;;;;;;;
|
||||||
|
|
||||||
|
(type SideEffectNoResult (enum (Inst (inst MInst))))
|
||||||
|
|
||||||
|
;; Create an empty `ValueRegs`, but do emit the given side-effectful
|
||||||
|
;; instruction.
|
||||||
|
(decl value_regs_none (SideEffectNoResult) ValueRegs)
|
||||||
|
(rule (value_regs_none (SideEffectNoResult.Inst inst))
|
||||||
|
(let ((_ Unit (emit inst)))
|
||||||
|
(value_regs_invalid)))
|
||||||
|
|
||||||
;;;; Helpers for Working with Flags ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
;;;; Helpers for Working with Flags ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||||
|
|
||||||
;; Newtype wrapper around `MInst` for instructions that are used for their
|
;; Newtype wrapper around `MInst` for instructions that are used for their
|
||||||
|
|||||||
Reference in New Issue
Block a user