Use large-model addressing for calls when in non-PIC mode.
The main use for non-PIC code at present is JIT code, and JIT code can live anywhere in memory and reference other symbols defined anywhere in memory, so it needs to use the "large" code model. func_addr and globalsym_addr instructions were already using `movabs` to support arbitrary 64-bit addresses, so this just makes calls be legalized to support arbitrary 64-bit addresses also.
This commit is contained in:
@@ -65,6 +65,9 @@ expand_flags = XFormGroup('expand_flags', """
|
||||
expand.custom_legalize(insts.global_addr, 'expand_global_addr')
|
||||
expand.custom_legalize(insts.heap_addr, 'expand_heap_addr')
|
||||
|
||||
# Custom expansions for calls.
|
||||
expand.custom_legalize(insts.call, 'expand_call')
|
||||
|
||||
# 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')
|
||||
|
||||
@@ -321,7 +321,6 @@ X86_64.enc(base.globalsym_addr.i64, *r.got_gvaddr8.rex(0x8b, w=1),
|
||||
# Call/return
|
||||
#
|
||||
X86_32.enc(base.call, *r.call_id(0xe8))
|
||||
X86_64.enc(base.call, *r.call_id(0xe8), isap=Not(is_pic))
|
||||
X86_64.enc(base.call, *r.call_plt_id(0xe8), isap=is_pic)
|
||||
|
||||
X86_32.enc(base.call_indirect.i32, *r.call_r(0xff, rrr=2))
|
||||
|
||||
60
lib/cretonne/src/legalizer/call.rs
Normal file
60
lib/cretonne/src/legalizer/call.rs
Normal file
@@ -0,0 +1,60 @@
|
||||
//! Legalization of calls.
|
||||
//!
|
||||
//! This module exports the `expand_call` function which transforms a `call`
|
||||
//! instruction into `func_addr` and `call_indirect` instructions.
|
||||
|
||||
use cursor::{Cursor, FuncCursor};
|
||||
use flowgraph::ControlFlowGraph;
|
||||
use ir::{self, InstBuilder};
|
||||
use isa::TargetIsa;
|
||||
|
||||
/// Expand a `call` instruction.
|
||||
pub fn expand_call(
|
||||
inst: ir::Inst,
|
||||
func: &mut ir::Function,
|
||||
_cfg: &mut ControlFlowGraph,
|
||||
isa: &TargetIsa,
|
||||
) {
|
||||
// Unpack the instruction.
|
||||
let (func_ref, old_args) = match func.dfg[inst] {
|
||||
ir::InstructionData::Call {
|
||||
opcode,
|
||||
ref args,
|
||||
func_ref,
|
||||
} => {
|
||||
debug_assert_eq!(opcode, ir::Opcode::Call);
|
||||
(func_ref, args.clone())
|
||||
}
|
||||
_ => panic!("Wanted call: {}", func.dfg.display_inst(inst, None)),
|
||||
};
|
||||
|
||||
let ptr_ty = if isa.flags().is_64bit() {
|
||||
ir::types::I64
|
||||
} else {
|
||||
ir::types::I32
|
||||
};
|
||||
|
||||
let sig = func.dfg.ext_funcs[func_ref].signature;
|
||||
|
||||
let callee = {
|
||||
let mut pos = FuncCursor::new(func).at_inst(inst);
|
||||
pos.use_srcloc(inst);
|
||||
pos.ins().func_addr(ptr_ty, func_ref)
|
||||
};
|
||||
|
||||
let mut new_args = ir::ValueList::default();
|
||||
new_args.push(callee, &mut func.dfg.value_lists);
|
||||
for i in 0..old_args.len(&func.dfg.value_lists) {
|
||||
new_args.push(
|
||||
old_args.as_slice(&func.dfg.value_lists)[i],
|
||||
&mut func.dfg.value_lists,
|
||||
);
|
||||
}
|
||||
|
||||
func.dfg.replace(inst).IndirectCall(
|
||||
ir::Opcode::CallIndirect,
|
||||
ptr_ty,
|
||||
sig,
|
||||
new_args,
|
||||
);
|
||||
}
|
||||
@@ -21,6 +21,7 @@ use isa::TargetIsa;
|
||||
use timing;
|
||||
|
||||
mod boundary;
|
||||
mod call;
|
||||
mod globalvar;
|
||||
mod heap;
|
||||
mod libcall;
|
||||
@@ -28,6 +29,7 @@ mod split;
|
||||
|
||||
use self::globalvar::expand_global_addr;
|
||||
use self::heap::expand_heap_addr;
|
||||
use self::call::expand_call;
|
||||
use self::libcall::expand_as_libcall;
|
||||
|
||||
/// Legalize `func` for `isa`.
|
||||
|
||||
Reference in New Issue
Block a user