Introduce globalsym_addr.
This is an instruction used in legalization of GlobalVarData::Sym global variables.
This commit is contained in:
@@ -12,6 +12,8 @@ function %I32() {
|
||||
fn0 = function %foo()
|
||||
sig0 = ()
|
||||
|
||||
gv0 = globalsym %some_gv
|
||||
|
||||
ss0 = incoming_arg 8, offset 0
|
||||
ss1 = incoming_arg 1024, offset -1024
|
||||
ss2 = incoming_arg 1024, offset -2048
|
||||
@@ -342,9 +344,9 @@ ebb0:
|
||||
; asm: call foo
|
||||
call fn0() ; bin: e8 PCRel4(fn0) 00000000
|
||||
|
||||
; asm: movl $-1, %ecx
|
||||
; asm: movl $0, %ecx
|
||||
[-,%rcx] v400 = func_addr.i32 fn0 ; bin: b9 Abs4(fn0) 00000000
|
||||
; asm: movl $-1, %esi
|
||||
; asm: movl $0, %esi
|
||||
[-,%rsi] v401 = func_addr.i32 fn0 ; bin: be Abs4(fn0) 00000000
|
||||
|
||||
; asm: call *%ecx
|
||||
@@ -352,6 +354,11 @@ ebb0:
|
||||
; asm: call *%esi
|
||||
call_indirect sig0, v401() ; bin: ff d6
|
||||
|
||||
; asm: movl $0, %ecx
|
||||
[-,%rcx] v450 = globalsym_addr.i32 gv0 ; bin: b9 Abs4(gv0) 00000000
|
||||
; asm: movl $0, %esi
|
||||
[-,%rsi] v451 = globalsym_addr.i32 gv0 ; bin: be Abs4(gv0) 00000000
|
||||
|
||||
; Spill / Fill.
|
||||
|
||||
; asm: movl %ecx, 1032(%esp)
|
||||
|
||||
@@ -14,6 +14,8 @@ function %I64() {
|
||||
fn0 = function %foo()
|
||||
sig0 = ()
|
||||
|
||||
gv0 = globalsym %some_gv
|
||||
|
||||
; Use incoming_arg stack slots because they won't be relocated by the frame
|
||||
; layout.
|
||||
ss0 = incoming_arg 8, offset 0
|
||||
@@ -429,11 +431,11 @@ ebb0:
|
||||
; asm: call foo
|
||||
call fn0() ; bin: e8 PCRel4(fn0) 00000000
|
||||
|
||||
; asm: movabsq $-1, %rcx
|
||||
; asm: movabsq $0, %rcx
|
||||
[-,%rcx] v400 = func_addr.i64 fn0 ; bin: 48 b9 Abs8(fn0) 0000000000000000
|
||||
; asm: movabsq $-1, %rsi
|
||||
; asm: movabsq $0, %rsi
|
||||
[-,%rsi] v401 = func_addr.i64 fn0 ; bin: 48 be Abs8(fn0) 0000000000000000
|
||||
; asm: movabsq $-1, %r10
|
||||
; asm: movabsq $0, %r10
|
||||
[-,%r10] v402 = func_addr.i64 fn0 ; bin: 49 ba Abs8(fn0) 0000000000000000
|
||||
|
||||
; asm: call *%rcx
|
||||
@@ -443,6 +445,13 @@ ebb0:
|
||||
; asm: call *%r10
|
||||
call_indirect sig0, v402() ; bin: 41 ff d2
|
||||
|
||||
; asm: movabsq $-1, %rcx
|
||||
[-,%rcx] v450 = globalsym_addr.i64 gv0 ; bin: 48 b9 Abs8(gv0) 0000000000000000
|
||||
; asm: movabsq $-1, %rsi
|
||||
[-,%rsi] v451 = globalsym_addr.i64 gv0 ; bin: 48 be Abs8(gv0) 0000000000000000
|
||||
; asm: movabsq $-1, %r10
|
||||
[-,%r10] v452 = globalsym_addr.i64 gv0 ; bin: 49 ba Abs8(gv0) 0000000000000000
|
||||
|
||||
; Spill / Fill.
|
||||
|
||||
; asm: movq %rcx, 1032(%rsp)
|
||||
|
||||
@@ -29,6 +29,19 @@ ebb1(v1: i64):
|
||||
; check: return $v2
|
||||
}
|
||||
|
||||
function %sym() -> i64 {
|
||||
gv0 = globalsym %something
|
||||
gv1 = globalsym #d0bad180d0b5d182d0bed0bd
|
||||
|
||||
ebb1:
|
||||
v0 = global_addr.i64 gv0
|
||||
; check: $v0 = globalsym_addr.i64 gv0
|
||||
v1 = global_addr.i64 gv1
|
||||
; check: $v1 = globalsym_addr.i64 gv1
|
||||
v2 = bxor v0, v1
|
||||
return v2
|
||||
}
|
||||
|
||||
; SpiderMonkey VM-style static 4+2 GB heap.
|
||||
; This eliminates bounds checks completely for offsets < 2GB.
|
||||
function %staticheap_sm64(i32, i64 vmctx) -> f32 spiderwasm {
|
||||
|
||||
@@ -79,6 +79,10 @@ impl binemit::CodeSink for TextSink {
|
||||
write!(self.text, "{}({}) ", self.rnames[reloc.0 as usize], fref).unwrap();
|
||||
}
|
||||
|
||||
fn reloc_globalsym(&mut self, reloc: binemit::Reloc, global: ir::GlobalVar) {
|
||||
write!(self.text, "{}({}) ", self.rnames[reloc.0 as usize], global).unwrap();
|
||||
}
|
||||
|
||||
fn reloc_jt(&mut self, reloc: binemit::Reloc, jt: ir::JumpTable) {
|
||||
write!(self.text, "{}({}) ", self.rnames[reloc.0 as usize], jt).unwrap();
|
||||
}
|
||||
|
||||
@@ -99,5 +99,6 @@ impl binemit::CodeSink for SizeSink {
|
||||
|
||||
fn reloc_ebb(&mut self, _reloc: binemit::Reloc, _ebb: ir::Ebb) {}
|
||||
fn reloc_func(&mut self, _reloc: binemit::Reloc, _fref: ir::FuncRef) {}
|
||||
fn reloc_globalsym(&mut self, _reloc: binemit::Reloc, _global: ir::GlobalVar) {}
|
||||
fn reloc_jt(&mut self, _reloc: binemit::Reloc, _jt: ir::JumpTable) {}
|
||||
}
|
||||
|
||||
@@ -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.
|
||||
#
|
||||
|
||||
@@ -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
|
||||
#
|
||||
|
||||
@@ -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.
|
||||
#
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user