Introduce globalsym_addr.

This is an instruction used in legalization of GlobalVarData::Sym global
variables.
This commit is contained in:
Dan Gohman
2017-10-30 10:02:29 -07:00
parent cb805f704d
commit 9c54c3fff0
11 changed files with 96 additions and 9 deletions

View File

@@ -389,6 +389,14 @@ global_addr = Instruction(
""",
ins=GV, outs=addr)
# A specialized form of global_addr instructions that only handles
# symbolic names.
globalsym_addr = Instruction(
'globalsym_addr', r"""
Compute the address of global variable GV, which is a symbolic name.
""",
ins=GV, outs=addr)
#
# WebAssembly bounds-checked heap accesses.
#

View File

@@ -271,6 +271,13 @@ I32.enc(base.func_addr.i32, *r.allones_fnaddr4(0xb8),
I64.enc(base.func_addr.i64, *r.allones_fnaddr8.rex(0xb8, w=1),
isap=allones_funcaddrs)
#
# Global addresses.
#
I32.enc(base.globalsym_addr.i32, *r.gvaddr4(0xb8))
I64.enc(base.globalsym_addr.i64, *r.gvaddr8.rex(0xb8, w=1))
#
# Call/return
#

View File

@@ -9,7 +9,7 @@ from base.formats import Unary, UnaryImm, Binary, BinaryImm, MultiAry
from base.formats import Trap, Call, IndirectCall, Store, Load
from base.formats import IntCompare, FloatCompare, IntCond, FloatCond
from base.formats import Jump, Branch, BranchInt, BranchFloat
from base.formats import Ternary, FuncAddr
from base.formats import Ternary, FuncAddr, UnaryGlobalVar
from base.formats import RegMove, RegSpill, RegFill
from .registers import GPR, ABCD, FPR, GPR8, FPR8, FLAG, StackGPR32, StackFPR32
from .defs import supported_floatccs
@@ -510,6 +510,24 @@ allones_fnaddr8 = TailRecipe(
sink.put8(!0);
''')
# XX+rd id with Abs4 globalsym relocation.
gvaddr4 = TailRecipe(
'gvaddr4', UnaryGlobalVar, size=4, ins=(), outs=GPR,
emit='''
PUT_OP(bits | (out_reg0 & 7), rex1(out_reg0), sink);
sink.reloc_globalsym(RelocKind::Abs4.into(), global_var);
sink.put4(0);
''')
# XX+rd iq with Abs8 globalsym relocation.
gvaddr8 = TailRecipe(
'gvaddr8', UnaryGlobalVar, size=8, ins=(), outs=GPR,
emit='''
PUT_OP(bits | (out_reg0 & 7), rex1(out_reg0), sink);
sink.reloc_globalsym(RelocKind::Abs8.into(), global_var);
sink.put8(0);
''')
#
# Store recipes.
#

View File

@@ -14,7 +14,7 @@
//! relocations to a `RelocSink` trait object. Relocations are less frequent than the
//! `CodeSink::put*` methods, so the performance impact of the virtual callbacks is less severe.
use ir::{Ebb, FuncRef, JumpTable};
use ir::{Ebb, FuncRef, GlobalVar, JumpTable};
use super::{CodeSink, CodeOffset, Reloc};
use std::ptr::write_unaligned;
@@ -54,6 +54,11 @@ pub trait RelocSink {
/// Add a relocation referencing an external function at the current offset.
fn reloc_func(&mut self, CodeOffset, Reloc, FuncRef);
/// Add a relocation referencing an external global variable symbol at the
/// current offset.
fn reloc_globalsym(&mut self, CodeOffset, Reloc, GlobalVar);
/// Add a relocation referencing a jump table.
/// Add a relocation referencing a jump table.
fn reloc_jt(&mut self, CodeOffset, Reloc, JumpTable);
}
@@ -101,6 +106,11 @@ impl<'a> CodeSink for MemoryCodeSink<'a> {
self.relocs.reloc_func(ofs, rel, func);
}
fn reloc_globalsym(&mut self, rel: Reloc, global: GlobalVar) {
let ofs = self.offset();
self.relocs.reloc_globalsym(ofs, rel, global);
}
fn reloc_jt(&mut self, rel: Reloc, jt: JumpTable) {
let ofs = self.offset();
self.relocs.reloc_jt(ofs, rel, jt);

View File

@@ -9,7 +9,7 @@ mod memorysink;
pub use self::relaxation::relax_branches;
pub use self::memorysink::{MemoryCodeSink, RelocSink};
use ir::{Ebb, FuncRef, JumpTable, Function, Inst};
use ir::{Ebb, FuncRef, GlobalVar, JumpTable, Function, Inst};
use regalloc::RegDiversions;
/// Offset in bytes from the beginning of the function.
@@ -47,6 +47,10 @@ pub trait CodeSink {
/// Add a relocation referencing an external function at the current offset.
fn reloc_func(&mut self, Reloc, FuncRef);
/// Add a relocation referencing an external global variable symbol at the
/// current offset. This is only used for `GlobalVarData::Sym` globals.
fn reloc_globalsym(&mut self, Reloc, GlobalVar);
/// Add a relocation referencing a jump table.
fn reloc_jt(&mut self, Reloc, JumpTable);
}

View File

@@ -21,7 +21,7 @@ pub fn expand_global_addr(inst: ir::Inst, func: &mut ir::Function, _cfg: &mut Co
match func.global_vars[gv] {
ir::GlobalVarData::VmCtx { offset } => vmctx_addr(inst, func, offset.into()),
ir::GlobalVarData::Deref { base, offset } => deref_addr(inst, func, base, offset.into()),
ir::GlobalVarData::Sym { .. } => (),
ir::GlobalVarData::Sym { .. } => globalsym(inst, func, gv),
}
}
@@ -50,3 +50,9 @@ fn deref_addr(inst: ir::Inst, func: &mut ir::Function, base: ir::GlobalVar, offs
let base_ptr = pos.ins().load(ptr_ty, ir::MemFlags::new(), base_addr, 0);
pos.func.dfg.replace(inst).iadd_imm(base_ptr, offset);
}
/// Expand a `global_addr` instruction for a symbolic name global.
fn globalsym(inst: ir::Inst, func: &mut ir::Function, gv: ir::GlobalVar) {
let ptr_ty = func.dfg.value_type(func.dfg.first_result(inst));
func.dfg.replace(inst).globalsym_addr(ptr_ty, gv);
}