diff --git a/cranelift/codegen/src/isa/x64/inst/emit.rs b/cranelift/codegen/src/isa/x64/inst/emit.rs index 04fcf9c34a..4a28a306e7 100644 --- a/cranelift/codegen/src/isa/x64/inst/emit.rs +++ b/cranelift/codegen/src/isa/x64/inst/emit.rs @@ -1479,6 +1479,25 @@ pub(crate) fn emit( let dst = &dst.finalize(state); emit_std_reg_mem(sink, prefix, opcode, 2, *src, dst, rex); } + + Inst::LoadExtName { + dst, + name, + offset, + srcloc, + } => { + // The full address can be encoded in the register, with a relocation. + let enc_dst = int_reg_enc(dst.to_reg()); + sink.put1(0x48 | ((enc_dst >> 3) & 1)); + sink.put1(0xB8 | (enc_dst & 7)); + sink.add_reloc(*srcloc, Reloc::Abs8, name, *offset); + if flags.emit_all_ones_funcaddrs() { + sink.put8(u64::max_value()); + } else { + sink.put8(0); + } + } + Inst::Hlt => { sink.put1(0xcc); } diff --git a/cranelift/codegen/src/isa/x64/inst/mod.rs b/cranelift/codegen/src/isa/x64/inst/mod.rs index d3ac5ce66c..e3d4490b52 100644 --- a/cranelift/codegen/src/isa/x64/inst/mod.rs +++ b/cranelift/codegen/src/isa/x64/inst/mod.rs @@ -4,13 +4,14 @@ #![allow(non_snake_case)] #![allow(non_camel_case_types)] +use alloc::boxed::Box; use alloc::vec::Vec; -use smallvec::SmallVec; use std::fmt; use std::string::{String, ToString}; use regalloc::RegUsageCollector; use regalloc::{RealRegUniverse, Reg, RegClass, RegUsageMapper, SpillSlot, VirtualReg, Writable}; +use smallvec::SmallVec; use crate::binemit::CodeOffset; use crate::ir::types::{B1, B128, B16, B32, B64, B8, F32, F64, I128, I16, I32, I64, I8}; @@ -270,6 +271,14 @@ pub enum Inst { /// An instruction that will always trigger the illegal instruction exception. Ud2 { trap_info: (SourceLoc, TrapCode) }, + /// Loads an external symbol in a register, with a relocation. + LoadExtName { + dst: Writable, + name: Box, + srcloc: SourceLoc, + offset: i64, + }, + // ===================================== // Meta-instructions generating no code. /// Marker, no-op in generated code: SP "virtual offset" is adjusted. This @@ -815,6 +824,15 @@ impl ShowWithRRU for Inst { Inst::TrapIf { cc, trap_code, .. } => { format!("j{} ; ud2 {} ;", cc.invert().to_string(), trap_code) } + Inst::LoadExtName { + dst, name, offset, .. + } => format!( + "{} {}+{}, {}", + ljustify("movaps".into()), + name, + offset, + show_ireg_sized(dst.to_reg(), mb_rru, 8), + ), Inst::VirtualSPOffsetAdj { offset } => format!("virtual_sp_offset_adjust {}", offset), Inst::Hlt => "hlt".into(), Inst::Ud2 { trap_info } => format!("ud2 {}", trap_info.1), @@ -958,6 +976,10 @@ fn x64_get_regs(inst: &Inst, collector: &mut RegUsageCollector) { target.get_regs_as_uses(collector); } + Inst::LoadExtName { dst, .. } => { + collector.add_def(*dst); + } + Inst::Ret | Inst::EpiloguePlaceholder | Inst::JmpKnown { .. } @@ -1187,6 +1209,8 @@ fn x64_map_regs(inst: &mut Inst, mapper: &RUM) { Inst::JmpUnknown { ref mut target } => target.map_uses(mapper), + Inst::LoadExtName { ref mut dst, .. } => map_def(mapper, dst), + Inst::Ret | Inst::EpiloguePlaceholder | Inst::JmpKnown { .. } diff --git a/cranelift/codegen/src/isa/x64/lower.rs b/cranelift/codegen/src/isa/x64/lower.rs index b9aed7edbb..0a985ff719 100644 --- a/cranelift/codegen/src/isa/x64/lower.rs +++ b/cranelift/codegen/src/isa/x64/lower.rs @@ -6,6 +6,7 @@ use log::trace; use regalloc::{Reg, RegClass, Writable}; use smallvec::SmallVec; +use alloc::boxed::Box; use alloc::vec::Vec; use std::convert::TryFrom; @@ -973,6 +974,32 @@ fn lower_insn_to_regs>( } } + Opcode::FuncAddr => { + let dst = output_to_reg(ctx, outputs[0]); + let (extname, _) = ctx.call_target(insn).unwrap(); + let extname = extname.clone(); + let loc = ctx.srcloc(insn); + ctx.emit(Inst::LoadExtName { + dst, + name: Box::new(extname), + srcloc: loc, + offset: 0, + }); + } + + Opcode::SymbolValue => { + let dst = output_to_reg(ctx, outputs[0]); + let (extname, _, offset) = ctx.symbol_value(insn).unwrap(); + let extname = extname.clone(); + let loc = ctx.srcloc(insn); + ctx.emit(Inst::LoadExtName { + dst, + name: Box::new(extname), + srcloc: loc, + offset, + }); + } + Opcode::StackAddr => { let (stack_slot, offset) = match *ctx.data(insn) { InstructionData::StackLoad {