diff --git a/cranelift/codegen/src/isa/x64/inst/emit.rs b/cranelift/codegen/src/isa/x64/inst/emit.rs index 23043602ad..7565d785fc 100644 --- a/cranelift/codegen/src/isa/x64/inst/emit.rs +++ b/cranelift/codegen/src/isa/x64/inst/emit.rs @@ -1021,6 +1021,18 @@ pub(crate) fn emit( sink.put4(nt_disp); } + Inst::OneWayJmpCond { cc, dst } => { + let cond_start = sink.cur_offset(); + let cond_disp_off = cond_start + 2; + if let Some(l) = dst.as_label() { + sink.use_label_at_offset(cond_disp_off, l, LabelUse::JmpRel32); + } + let dst_disp = dst.as_offset32_or_zero() as u32; + sink.put1(0x0F); + sink.put1(0x80 + cc.get_enc()); + sink.put4(dst_disp); + } + Inst::JmpUnknown { target } => { match target { RegMem::Reg { reg } => { diff --git a/cranelift/codegen/src/isa/x64/inst/mod.rs b/cranelift/codegen/src/isa/x64/inst/mod.rs index 77c3a73cc3..ac95450669 100644 --- a/cranelift/codegen/src/isa/x64/inst/mod.rs +++ b/cranelift/codegen/src/isa/x64/inst/mod.rs @@ -200,6 +200,10 @@ pub enum Inst { not_taken: BranchTarget, }, + /// A one-way conditional branch, invisible to the CFG processing; used *only* as part of + /// straight-line sequences in code to be emitted. + OneWayJmpCond { cc: CC, dst: BranchTarget }, + /// Indirect jump: jmpq (reg mem). JmpUnknown { target: RegMem }, @@ -634,7 +638,11 @@ impl ShowWithRRU for Inst { taken.show_rru(mb_rru), not_taken.show_rru(mb_rru) ), - // + Inst::OneWayJmpCond { cc, dst } => format!( + "{} {}", + ljustify2("j".to_string(), cc.to_string()), + dst.show_rru(mb_rru), + ), Inst::JmpUnknown { target } => format!( "{} *{}", ljustify("jmp".to_string()), @@ -757,6 +765,7 @@ fn x64_get_regs(inst: &Inst, collector: &mut RegUsageCollector) { | Inst::EpiloguePlaceholder | Inst::JmpKnown { .. } | Inst::JmpCond { .. } + | Inst::OneWayJmpCond { .. } | Inst::Nop { .. } | Inst::JmpUnknown { .. } | Inst::VirtualSPOffsetAdj { .. } @@ -970,6 +979,7 @@ fn x64_map_regs(inst: &mut Inst, mapper: &RUM) { | Inst::EpiloguePlaceholder | Inst::JmpKnown { .. } | Inst::JmpCond { .. } + | Inst::OneWayJmpCond { .. } | Inst::Nop { .. } | Inst::JmpUnknown { .. } | Inst::VirtualSPOffsetAdj { .. }