diff --git a/cranelift/codegen/src/isa/aarch64/inst.isle b/cranelift/codegen/src/isa/aarch64/inst.isle index 18398ca736..8345d6eab4 100644 --- a/cranelift/codegen/src/isa/aarch64/inst.isle +++ b/cranelift/codegen/src/isa/aarch64/inst.isle @@ -695,6 +695,7 @@ ;; An instruction guaranteed to always be undefined and to trigger an illegal instruction at ;; runtime. (Udf + (use_allocated_encoding bool) (trap_code TrapCode)) ;; Compute the address (using a PC-relative offset) of a memory location, using the `ADR` @@ -1905,6 +1906,12 @@ (_2 Unit (emit (MInst.VecRRR (VecALUOp.Bsl) dst x y (vector_size ty))))) dst)) +;; Helper for generating a `udf` instruction. + +(decl udf (bool TrapCode) SideEffectNoResult) +(rule (udf use_allocated_encoding trap_code) + (SideEffectNoResult.Inst (MInst.Udf use_allocated_encoding trap_code))) + ;; Immediate value helpers ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; (decl imm (Type u64) Reg) diff --git a/cranelift/codegen/src/isa/aarch64/inst/emit.rs b/cranelift/codegen/src/isa/aarch64/inst/emit.rs index 57def924b1..d5cbc4d649 100644 --- a/cranelift/codegen/src/isa/aarch64/inst/emit.rs +++ b/cranelift/codegen/src/isa/aarch64/inst/emit.rs @@ -626,6 +626,8 @@ pub struct EmitState { stack_map: Option, /// Current source-code location corresponding to instruction to be emitted. cur_srcloc: SourceLoc, + /// Is code generated for the SpiderMonkey WebAssembly convention. + is_baldrdash_target: bool, } impl MachInstEmitState for EmitState { @@ -635,6 +637,7 @@ impl MachInstEmitState for EmitState { nominal_sp_to_fp: abi.frame_size() as i64, stack_map: None, cur_srcloc: SourceLoc::default(), + is_baldrdash_target: abi.call_conv().extends_baldrdash(), } } @@ -2811,7 +2814,10 @@ impl MachInstEmit for Inst { )); sink.use_label_at_offset(off, label, LabelUse::Branch19); // udf - let trap = Inst::Udf { trap_code }; + let trap = Inst::Udf { + use_allocated_encoding: !state.is_baldrdash_target, + trap_code, + }; trap.emit(&[], sink, emit_info, state); // LABEL: sink.bind_label(label); @@ -2827,12 +2833,21 @@ impl MachInstEmit for Inst { &Inst::Brk => { sink.put4(0xd4200000); } - &Inst::Udf { trap_code } => { + &Inst::Udf { + use_allocated_encoding, + trap_code, + } => { + let encoding = if use_allocated_encoding { + 0xc11f + } else { + 0xd4a00000 + }; + sink.add_trap(trap_code); if let Some(s) = state.take_stack_map() { sink.add_stack_map(StackMapExtent::UpcomingBytes(4), s); } - sink.put4(0xd4a00000); + sink.put4(encoding); } &Inst::Adr { rd, off } => { let rd = allocs.next_writable(rd); diff --git a/cranelift/codegen/src/isa/aarch64/inst/emit_tests.rs b/cranelift/codegen/src/isa/aarch64/inst/emit_tests.rs index c475dd261b..230a324a37 100644 --- a/cranelift/codegen/src/isa/aarch64/inst/emit_tests.rs +++ b/cranelift/codegen/src/isa/aarch64/inst/emit_tests.rs @@ -40,6 +40,14 @@ fn test_aarch64_binemit() { insns.push((Inst::Ret { rets: vec![] }, "C0035FD6", "ret")); insns.push((Inst::Nop0, "", "nop-zero-len")); insns.push((Inst::Nop4, "1F2003D5", "nop")); + insns.push(( + Inst::Udf { + use_allocated_encoding: false, + trap_code: TrapCode::Interrupt, + }, + "0000A0D4", + "udf", + )); insns.push(( Inst::AluRRR { alu_op: ALUOp::Add, @@ -5124,7 +5132,7 @@ fn test_aarch64_binemit() { trap_code: TrapCode::Interrupt, kind: CondBrKind::NotZero(xreg(8)), }, - "480000B40000A0D4", + "480000B41FC10000", "cbz x8, 8 ; udf", )); insns.push(( @@ -5132,7 +5140,7 @@ fn test_aarch64_binemit() { trap_code: TrapCode::Interrupt, kind: CondBrKind::Zero(xreg(8)), }, - "480000B50000A0D4", + "480000B51FC10000", "cbnz x8, 8 ; udf", )); insns.push(( @@ -5140,7 +5148,7 @@ fn test_aarch64_binemit() { trap_code: TrapCode::Interrupt, kind: CondBrKind::Cond(Cond::Ne), }, - "400000540000A0D4", + "400000541FC10000", "b.eq 8 ; udf", )); insns.push(( @@ -5148,7 +5156,7 @@ fn test_aarch64_binemit() { trap_code: TrapCode::Interrupt, kind: CondBrKind::Cond(Cond::Eq), }, - "410000540000A0D4", + "410000541FC10000", "b.ne 8 ; udf", )); insns.push(( @@ -5156,7 +5164,7 @@ fn test_aarch64_binemit() { trap_code: TrapCode::Interrupt, kind: CondBrKind::Cond(Cond::Lo), }, - "420000540000A0D4", + "420000541FC10000", "b.hs 8 ; udf", )); insns.push(( @@ -5164,7 +5172,7 @@ fn test_aarch64_binemit() { trap_code: TrapCode::Interrupt, kind: CondBrKind::Cond(Cond::Hs), }, - "430000540000A0D4", + "430000541FC10000", "b.lo 8 ; udf", )); insns.push(( @@ -5172,7 +5180,7 @@ fn test_aarch64_binemit() { trap_code: TrapCode::Interrupt, kind: CondBrKind::Cond(Cond::Pl), }, - "440000540000A0D4", + "440000541FC10000", "b.mi 8 ; udf", )); insns.push(( @@ -5180,7 +5188,7 @@ fn test_aarch64_binemit() { trap_code: TrapCode::Interrupt, kind: CondBrKind::Cond(Cond::Mi), }, - "450000540000A0D4", + "450000541FC10000", "b.pl 8 ; udf", )); insns.push(( @@ -5188,7 +5196,7 @@ fn test_aarch64_binemit() { trap_code: TrapCode::Interrupt, kind: CondBrKind::Cond(Cond::Vc), }, - "460000540000A0D4", + "460000541FC10000", "b.vs 8 ; udf", )); insns.push(( @@ -5196,7 +5204,7 @@ fn test_aarch64_binemit() { trap_code: TrapCode::Interrupt, kind: CondBrKind::Cond(Cond::Vs), }, - "470000540000A0D4", + "470000541FC10000", "b.vc 8 ; udf", )); insns.push(( @@ -5204,7 +5212,7 @@ fn test_aarch64_binemit() { trap_code: TrapCode::Interrupt, kind: CondBrKind::Cond(Cond::Ls), }, - "480000540000A0D4", + "480000541FC10000", "b.hi 8 ; udf", )); insns.push(( @@ -5212,7 +5220,7 @@ fn test_aarch64_binemit() { trap_code: TrapCode::Interrupt, kind: CondBrKind::Cond(Cond::Hi), }, - "490000540000A0D4", + "490000541FC10000", "b.ls 8 ; udf", )); insns.push(( @@ -5220,7 +5228,7 @@ fn test_aarch64_binemit() { trap_code: TrapCode::Interrupt, kind: CondBrKind::Cond(Cond::Lt), }, - "4A0000540000A0D4", + "4A0000541FC10000", "b.ge 8 ; udf", )); insns.push(( @@ -5228,7 +5236,7 @@ fn test_aarch64_binemit() { trap_code: TrapCode::Interrupt, kind: CondBrKind::Cond(Cond::Ge), }, - "4B0000540000A0D4", + "4B0000541FC10000", "b.lt 8 ; udf", )); insns.push(( @@ -5236,7 +5244,7 @@ fn test_aarch64_binemit() { trap_code: TrapCode::Interrupt, kind: CondBrKind::Cond(Cond::Le), }, - "4C0000540000A0D4", + "4C0000541FC10000", "b.gt 8 ; udf", )); insns.push(( @@ -5244,7 +5252,7 @@ fn test_aarch64_binemit() { trap_code: TrapCode::Interrupt, kind: CondBrKind::Cond(Cond::Gt), }, - "4D0000540000A0D4", + "4D0000541FC10000", "b.le 8 ; udf", )); insns.push(( @@ -5252,7 +5260,7 @@ fn test_aarch64_binemit() { trap_code: TrapCode::Interrupt, kind: CondBrKind::Cond(Cond::Nv), }, - "4E0000540000A0D4", + "4E0000541FC10000", "b.al 8 ; udf", )); insns.push(( @@ -5260,7 +5268,7 @@ fn test_aarch64_binemit() { trap_code: TrapCode::Interrupt, kind: CondBrKind::Cond(Cond::Al), }, - "4F0000540000A0D4", + "4F0000541FC10000", "b.nv 8 ; udf", )); diff --git a/cranelift/codegen/src/isa/aarch64/inst/mod.rs b/cranelift/codegen/src/isa/aarch64/inst/mod.rs index e43e9ad7ee..015773e5fd 100644 --- a/cranelift/codegen/src/isa/aarch64/inst/mod.rs +++ b/cranelift/codegen/src/isa/aarch64/inst/mod.rs @@ -2564,7 +2564,16 @@ impl Inst { format!("br {}", rn) } &Inst::Brk => "brk #0".to_string(), - &Inst::Udf { .. } => "udf".to_string(), + &Inst::Udf { + use_allocated_encoding, + .. + } => { + if use_allocated_encoding { + "udf #0xc11f".to_string() + } else { + "udf".to_string() + } + } &Inst::TrapIf { ref kind, .. } => match kind { &CondBrKind::Zero(reg) => { let reg = pretty_print_reg(reg, allocs); diff --git a/cranelift/codegen/src/isa/aarch64/lower.isle b/cranelift/codegen/src/isa/aarch64/lower.isle index de30bff355..e14a33302b 100644 --- a/cranelift/codegen/src/isa/aarch64/lower.isle +++ b/cranelift/codegen/src/isa/aarch64/lower.isle @@ -1244,7 +1244,19 @@ (vec_size VectorSize (vector_size ty))) (value_reg (int_cmp_zero_swap cond rn vec_size)))) -;;;; Rules for `AtomicRMW` ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;;;; Rules for `trap` ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; + +(rule (lower (trap trap_code)) + (let ((use_allocated_encoding bool (is_not_baldrdash_call_conv))) + (side_effect (udf use_allocated_encoding trap_code)))) + +;;;; Rules for `resumable_trap` ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; + +(rule (lower (resumable_trap trap_code)) + (let ((use_allocated_encoding bool (is_not_baldrdash_call_conv))) + (side_effect (udf use_allocated_encoding trap_code)))) + +;;;; Rules for `AtomicRMW` ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; (rule 1 (lower (and (use_lse) (has_type (valid_atomic_transaction ty) diff --git a/cranelift/codegen/src/isa/aarch64/lower_inst.rs b/cranelift/codegen/src/isa/aarch64/lower_inst.rs index f13f09cf40..506fef70b1 100644 --- a/cranelift/codegen/src/isa/aarch64/lower_inst.rs +++ b/cranelift/codegen/src/isa/aarch64/lower_inst.rs @@ -618,10 +618,7 @@ pub(crate) fn lower_insn_to_regs>( ctx.emit(Inst::Brk); } - Opcode::Trap | Opcode::ResumableTrap => { - let trap_code = ctx.data(insn).trap_code().unwrap(); - ctx.emit(Inst::Udf { trap_code }); - } + Opcode::Trap | Opcode::ResumableTrap => implemented_in_isle(ctx), Opcode::Trapif | Opcode::Trapff => { let trap_code = ctx.data(insn).trap_code().unwrap(); diff --git a/cranelift/codegen/src/machinst/buffer.rs b/cranelift/codegen/src/machinst/buffer.rs index 7bd532b8ee..4eced0c754 100644 --- a/cranelift/codegen/src/machinst/buffer.rs +++ b/cranelift/codegen/src/machinst/buffer.rs @@ -1672,6 +1672,7 @@ mod test { buf.bind_label(label(1)); let inst = Inst::Udf { + use_allocated_encoding: true, trap_code: TrapCode::Interrupt, }; inst.emit(&[], &mut buf, &info, &mut state); diff --git a/cranelift/codegen/src/machinst/isle.rs b/cranelift/codegen/src/machinst/isle.rs index 24cee437a8..3ef083a286 100644 --- a/cranelift/codegen/src/machinst/isle.rs +++ b/cranelift/codegen/src/machinst/isle.rs @@ -462,6 +462,11 @@ macro_rules! isle_prelude_methods { } } + #[inline] + fn is_not_baldrdash_call_conv(&mut self) -> Option { + Some(!self.lower_ctx.abi().call_conv().extends_baldrdash()) + } + #[inline] fn func_ref_data(&mut self, func_ref: FuncRef) -> (SigRef, ExternalName, RelocDistance) { let funcdata = &self.lower_ctx.dfg().ext_funcs[func_ref]; diff --git a/cranelift/codegen/src/prelude.isle b/cranelift/codegen/src/prelude.isle index d387a77fac..e0729dc3cb 100644 --- a/cranelift/codegen/src/prelude.isle +++ b/cranelift/codegen/src/prelude.isle @@ -615,6 +615,9 @@ (decl avoid_div_traps () Type) (extern extractor avoid_div_traps avoid_div_traps) +(decl pure is_not_baldrdash_call_conv () bool) +(extern constructor is_not_baldrdash_call_conv is_not_baldrdash_call_conv) + ;;;; Helpers for accessing instruction data ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;; Accessor for `FuncRef`. diff --git a/cranelift/filetests/filetests/isa/aarch64/heap_addr.clif b/cranelift/filetests/filetests/isa/aarch64/heap_addr.clif index d353c80e1b..6fd8d2fab7 100644 --- a/cranelift/filetests/filetests/isa/aarch64/heap_addr.clif +++ b/cranelift/filetests/filetests/isa/aarch64/heap_addr.clif @@ -26,7 +26,7 @@ block0(v0: i64, v1: i32): ; csel x0, x14, x13, hi ; ret ; block2: -; udf +; udf #0xc11f function %static_heap_check(i64 vmctx, i32) -> i64 { gv0 = vmctx @@ -48,5 +48,5 @@ block0(v0: i64, v1: i32): ; csel x0, x11, x10, hi ; ret ; block2: -; udf +; udf #0xc11f diff --git a/cranelift/filetests/filetests/isa/aarch64/traps.clif b/cranelift/filetests/filetests/isa/aarch64/traps.clif index e01b3e77cb..206ee938f2 100644 --- a/cranelift/filetests/filetests/isa/aarch64/traps.clif +++ b/cranelift/filetests/filetests/isa/aarch64/traps.clif @@ -8,7 +8,7 @@ block0: } ; block0: -; udf +; udf #0xc11f function %g(i64) { block0(v0: i64):