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:
Dan Gohman
2018-04-09 14:53:00 -07:00
parent 2703b8ce6f
commit eab57c0a40
7 changed files with 72 additions and 3 deletions

View File

@@ -473,8 +473,11 @@ ebb0:
; asm: movzbq %dl, %rsi ; asm: movzbq %dl, %rsi
[-,%rsi] v351 = bint.i64 v301 ; bin: 0f b6 f2 [-,%rsi] v351 = bint.i64 v301 ; bin: 0f b6 f2
; asm: call foo ; TODO: x86-64 can't encode a direct call to an arbitrary 64-bit address in
call fn0() ; bin: e8 PCRel4(%foo-4) 00000000 ; a single instruction. When we add a concept of colocated definitions, this
; test can be re-enabled.
; disabled: asm: call foo
; disabled: call fn0() ; bin: e8 PCRel4(%foo-4) 00000000
; asm: movabsq $0, %rcx ; asm: movabsq $0, %rcx
[-,%rcx] v400 = func_addr.i64 fn0 ; bin: 48 b9 Abs8(%foo) 0000000000000000 [-,%rcx] v400 = func_addr.i64 fn0 ; bin: 48 b9 Abs8(%foo) 0000000000000000

View File

@@ -2,6 +2,7 @@ test legalizer
; Pre-SSE 4.1, we need to use runtime library calls for floating point rounding operations. ; Pre-SSE 4.1, we need to use runtime library calls for floating point rounding operations.
set is_64bit set is_64bit
set is_pic
isa intel isa intel
function %floor(f32) -> f32 { function %floor(f32) -> f32 {

View File

@@ -1,6 +1,7 @@
test compile test compile
set is_64bit set is_64bit
set is_compressed set is_compressed
set is_pic
isa intel haswell isa intel haswell
; An empty function. ; An empty function.

View File

@@ -65,6 +65,9 @@ expand_flags = XFormGroup('expand_flags', """
expand.custom_legalize(insts.global_addr, 'expand_global_addr') expand.custom_legalize(insts.global_addr, 'expand_global_addr')
expand.custom_legalize(insts.heap_addr, 'expand_heap_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. # Custom expansions that need to change the CFG.
# TODO: Add sufficient XForm syntax that we don't need to hand-code these. # TODO: Add sufficient XForm syntax that we don't need to hand-code these.
expand.custom_legalize(insts.trapz, 'expand_cond_trap') expand.custom_legalize(insts.trapz, 'expand_cond_trap')

View File

@@ -321,7 +321,6 @@ X86_64.enc(base.globalsym_addr.i64, *r.got_gvaddr8.rex(0x8b, w=1),
# Call/return # Call/return
# #
X86_32.enc(base.call, *r.call_id(0xe8)) 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_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)) X86_32.enc(base.call_indirect.i32, *r.call_r(0xff, rrr=2))

View 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,
);
}

View File

@@ -21,6 +21,7 @@ use isa::TargetIsa;
use timing; use timing;
mod boundary; mod boundary;
mod call;
mod globalvar; mod globalvar;
mod heap; mod heap;
mod libcall; mod libcall;
@@ -28,6 +29,7 @@ mod split;
use self::globalvar::expand_global_addr; use self::globalvar::expand_global_addr;
use self::heap::expand_heap_addr; use self::heap::expand_heap_addr;
use self::call::expand_call;
use self::libcall::expand_as_libcall; use self::libcall::expand_as_libcall;
/// Legalize `func` for `isa`. /// Legalize `func` for `isa`.