Change GlobalVar to GlobalValue
This commit is contained in:
committed by
Dan Gohman
parent
49cc693d64
commit
5c320a0d30
@@ -110,7 +110,7 @@ Program structure
|
||||
|
||||
In LLVM IR, the largest representable unit is the *module* which corresponds
|
||||
more or less to a C translation unit. It is a collection of functions and
|
||||
global variables that may contain references to external symbols too.
|
||||
global valueiables that may contain references to external symbols too.
|
||||
|
||||
In Cretonne IR, the largest representable unit is the *function*. This is so
|
||||
that functions can easily be compiled in parallel without worrying about
|
||||
|
||||
@@ -554,7 +554,7 @@ stack overflow checks in the prologue.
|
||||
the stack pointer has reached or exceeded the limit, generate a trap with a
|
||||
``stk_ovf`` code.
|
||||
|
||||
The global variable must be accessible and naturally aligned for a
|
||||
The global valueiable must be accessible and naturally aligned for a
|
||||
pointer-sized value.
|
||||
|
||||
Setting `stack_limit` is an alternative way to detect stack overflow, when using
|
||||
@@ -563,12 +563,12 @@ stack overflow checks in the prologue.
|
||||
Global variables
|
||||
----------------
|
||||
|
||||
A *global variable* is an :term:`accessible` object in memory whose address is
|
||||
A *global valueiable* is an :term:`accessible` object in memory whose address is
|
||||
not known at compile time. The address is computed at runtime by
|
||||
:inst:`global_addr`, possibly using information provided by the linker via
|
||||
relocations. There are multiple kinds of global variables using different
|
||||
:inst:`global_value`, possibly using information provided by the linker via
|
||||
relocations. There are multiple kinds of global valueiables using different
|
||||
methods for determining their address. Cretonne does not track the type or even
|
||||
the size of global variables, they are just pointers to non-stack memory.
|
||||
the size of global valueiables, they are just pointers to non-stack memory.
|
||||
|
||||
When Cretonne is generating code for a virtual machine environment, globals can
|
||||
be used to access data structures in the VM's runtime. This requires functions
|
||||
@@ -578,26 +578,26 @@ Cretonne functions.
|
||||
|
||||
.. inst:: GV = vmctx+Offset
|
||||
|
||||
Declare a global variable in the VM context struct.
|
||||
Declare a global valueiable in the VM context struct.
|
||||
|
||||
This declares a global variable whose address is a constant offset from the
|
||||
This declares a global valueiable whose address is a constant offset from the
|
||||
VM context pointer which is passed as a hidden argument to all functions
|
||||
JIT-compiled for the VM.
|
||||
|
||||
Typically, the VM context is a C struct, and the declared global variable
|
||||
Typically, the VM context is a C struct, and the declared global valueiable
|
||||
is a member of the struct.
|
||||
|
||||
:arg Offset: Byte offset from the VM context pointer to the global
|
||||
variable.
|
||||
:result GV: Global variable.
|
||||
|
||||
The address of a global variable can also be derived by treating another global
|
||||
The address of a global valueiable can also be derived by treating another global
|
||||
variable as a struct pointer. This makes it possible to chase pointers into VM
|
||||
runtime data structures.
|
||||
|
||||
.. inst:: GV = deref(BaseGV)+Offset
|
||||
|
||||
Declare a global variable in a struct pointed to by BaseGV.
|
||||
Declare a global valueiable in a struct pointed to by BaseGV.
|
||||
|
||||
The address of GV can be computed by first loading a pointer from BaseGV
|
||||
and adding Offset to it.
|
||||
@@ -605,7 +605,7 @@ runtime data structures.
|
||||
It is assumed the BaseGV resides in readable memory with the appropriate
|
||||
alignment for storing a pointer.
|
||||
|
||||
Chains of ``deref`` global variables are possible, but cycles are not
|
||||
Chains of ``deref`` global valueiables are possible, but cycles are not
|
||||
allowed. They will be caught by the IR verifier.
|
||||
|
||||
:arg BaseGV: Global variable containing the base pointer.
|
||||
@@ -615,7 +615,7 @@ runtime data structures.
|
||||
|
||||
.. inst:: GV = [colocated] globalsym name
|
||||
|
||||
Declare a global variable at a symbolic address.
|
||||
Declare a global valueiable at a symbolic address.
|
||||
|
||||
The address of GV is symbolic and will be assigned a relocation, so that
|
||||
it can be resolved by a later linking phase.
|
||||
@@ -627,7 +627,7 @@ runtime data structures.
|
||||
:arg name: External name.
|
||||
:result GV: Global variable.
|
||||
|
||||
.. autoinst:: global_addr
|
||||
.. autoinst:: global_value
|
||||
.. autoinst:: globalsym_addr
|
||||
|
||||
|
||||
@@ -701,7 +701,7 @@ trap when accessed.
|
||||
address space reserved for the heap, not including the guard pages.
|
||||
:arg GuardBytes: Size of the guard pages in bytes.
|
||||
|
||||
When the base is a global variable, it must be :term:`accessible` and naturally
|
||||
When the base is a global valueiable, it must be :term:`accessible` and naturally
|
||||
aligned for a pointer value.
|
||||
|
||||
The ``reserved_reg`` option is not yet implemented.
|
||||
@@ -711,7 +711,7 @@ Dynamic heaps
|
||||
|
||||
A *dynamic heap* can be relocated to a different base address when it is
|
||||
resized, and its bound can move dynamically. The guard pages move when the heap
|
||||
is resized. The bound of a dynamic heap is stored in a global variable.
|
||||
is resized. The bound of a dynamic heap is stored in a global valueiable.
|
||||
|
||||
.. inst:: H = dynamic Base, min MinBytes, bound BoundGV, guard GuardBytes
|
||||
|
||||
@@ -724,7 +724,7 @@ is resized. The bound of a dynamic heap is stored in a global variable.
|
||||
:arg BoundGV: Global variable containing the current heap bound in bytes.
|
||||
:arg GuardBytes: Size of the guard pages in bytes.
|
||||
|
||||
When the base is a global variable, it must be :term:`accessible` and naturally
|
||||
When the base is a global valueiable, it must be :term:`accessible` and naturally
|
||||
aligned for a pointer value.
|
||||
|
||||
The ``reserved_reg`` option is not yet implemented.
|
||||
|
||||
@@ -15,7 +15,7 @@ The meta language descriptions are Python modules under the
|
||||
steps:
|
||||
|
||||
1. The Python modules are imported. This has the effect of building static data
|
||||
structures in global variables in the modules. These static data structures
|
||||
structures in global valueiables in the modules. These static data structures
|
||||
in the :mod:`base` and :mod:`isa` packages use the classes in the
|
||||
:mod:`cdsl` package to describe instruction sets and other properties.
|
||||
|
||||
@@ -81,7 +81,7 @@ open :class:`InstructionGroup`.
|
||||
:members:
|
||||
|
||||
The basic Cretonne instruction set described in :doc:`langref` is defined by the
|
||||
Python module :mod:`base.instructions`. This module has a global variable
|
||||
Python module :mod:`base.instructions`. This module has a global valueiable
|
||||
:data:`base.instructions.GROUP` which is an :class:`InstructionGroup` instance
|
||||
containing all the base instructions.
|
||||
|
||||
|
||||
@@ -9,7 +9,7 @@ function %vmctx(i64 vmctx) -> i64 {
|
||||
gv1 = vmctx-16
|
||||
|
||||
ebb1(v1: i64):
|
||||
v2 = global_addr.i64 gv1
|
||||
v2 = global_value.i64 gv1
|
||||
; check: v2 = iadd_imm v1, -16
|
||||
return v2
|
||||
; check: return v2
|
||||
@@ -20,7 +20,7 @@ function %deref(i64 vmctx) -> i64 {
|
||||
gv2 = deref(gv1)+32
|
||||
|
||||
ebb1(v1: i64):
|
||||
v2 = global_addr.i64 gv2
|
||||
v2 = global_value.i64 gv2
|
||||
; check: $(a1=$V) = iadd_imm v1, -16
|
||||
; check: $(p1=$V) = load.i64 notrap aligned $a1
|
||||
; check: v2 = iadd_imm $p1, 32
|
||||
@@ -33,9 +33,9 @@ function %sym() -> i64 {
|
||||
gv1 = globalsym u123:456
|
||||
|
||||
ebb1:
|
||||
v0 = global_addr.i64 gv0
|
||||
v0 = global_value.i64 gv0
|
||||
; check: v0 = globalsym_addr.i64 gv0
|
||||
v1 = global_addr.i64 gv1
|
||||
v1 = global_value.i64 gv1
|
||||
; check: v1 = globalsym_addr.i64 gv1
|
||||
v2 = bxor v0, v1
|
||||
return v2
|
||||
|
||||
@@ -10,8 +10,8 @@ function %vmglobal() -> i32 {
|
||||
gv5 = vmctx -256
|
||||
; check: gv5 = vmctx-256
|
||||
ebb0:
|
||||
v1 = global_addr.i32 gv3
|
||||
; check: v1 = global_addr.i32 gv3
|
||||
v1 = global_value.i32 gv3
|
||||
; check: v1 = global_value.i32 gv3
|
||||
return v1
|
||||
}
|
||||
|
||||
@@ -20,19 +20,19 @@ function %deref() -> i32 {
|
||||
gv4 = deref(gv3)-32
|
||||
; check: gv4 = deref(gv3)-32
|
||||
ebb0:
|
||||
v1 = global_addr.i32 gv4
|
||||
; check: v1 = global_addr.i32 gv4
|
||||
v1 = global_value.i32 gv4
|
||||
; check: v1 = global_value.i32 gv4
|
||||
return v1
|
||||
}
|
||||
|
||||
; Refer to a global variable before it's been declared.
|
||||
; Refer to a global valueiable before it's been declared.
|
||||
function %backref() -> i32 {
|
||||
gv1 = deref(gv2)-32
|
||||
; check: gv1 = deref(gv2)-32
|
||||
gv2 = vmctx+16
|
||||
; check: gv2 = vmctx+16
|
||||
ebb0:
|
||||
v1 = global_addr.i32 gv1
|
||||
v1 = global_value.i32 gv1
|
||||
return v1
|
||||
}
|
||||
|
||||
@@ -42,10 +42,10 @@ function %sym() -> i32 {
|
||||
gv1 = globalsym u8:9
|
||||
; check: gv1 = globalsym u8:9
|
||||
ebb0:
|
||||
v0 = global_addr.i32 gv0
|
||||
; check: v0 = global_addr.i32 gv0
|
||||
v1 = global_addr.i32 gv1
|
||||
; check: v1 = global_addr.i32 gv1
|
||||
v0 = global_value.i32 gv0
|
||||
; check: v0 = global_value.i32 gv0
|
||||
v1 = global_value.i32 gv1
|
||||
; check: v1 = global_value.i32 gv1
|
||||
v2 = bxor v0, v1
|
||||
return v2
|
||||
}
|
||||
|
||||
@@ -16,8 +16,8 @@ ebb = EntityRefKind(
|
||||
#: A reference to a stack slot declared in the function preamble.
|
||||
stack_slot = EntityRefKind('stack_slot', 'A stack slot.')
|
||||
|
||||
#: A reference to a global variable.
|
||||
global_var = EntityRefKind('global_var', 'A global variable.')
|
||||
#: A reference to a global valueiable.
|
||||
global_value = EntityRefKind('global_value', 'A global value.')
|
||||
|
||||
#: A reference to a function sugnature declared in the function preamble.
|
||||
#: This is used to provide the call signature in a call_indirect instruction.
|
||||
|
||||
@@ -18,7 +18,7 @@ UnaryImm = InstructionFormat(imm64)
|
||||
UnaryIeee32 = InstructionFormat(ieee32)
|
||||
UnaryIeee64 = InstructionFormat(ieee64)
|
||||
UnaryBool = InstructionFormat(boolean)
|
||||
UnaryGlobalVar = InstructionFormat(entities.global_var)
|
||||
UnaryGlobalValue = InstructionFormat(entities.global_value)
|
||||
|
||||
Binary = InstructionFormat(VALUE, VALUE)
|
||||
BinaryImm = InstructionFormat(VALUE, imm64)
|
||||
@@ -79,5 +79,5 @@ CondTrap = InstructionFormat(VALUE, trapcode)
|
||||
IntCondTrap = InstructionFormat(intcc, VALUE, trapcode)
|
||||
FloatCondTrap = InstructionFormat(floatcc, VALUE, trapcode)
|
||||
|
||||
# Finally extract the names of global variables in this module.
|
||||
# Finally extract the names of global valueiables in this module.
|
||||
InstructionFormat.extract_names(globals())
|
||||
|
||||
@@ -491,19 +491,19 @@ stack_addr = Instruction(
|
||||
# Global variables.
|
||||
#
|
||||
|
||||
GV = Operand('GV', entities.global_var)
|
||||
GV = Operand('GV', entities.global_value)
|
||||
|
||||
global_addr = Instruction(
|
||||
'global_addr', r"""
|
||||
Compute the address of global variable GV.
|
||||
global_value = Instruction(
|
||||
'global_value', r"""
|
||||
Compute the value of global GV.
|
||||
""",
|
||||
ins=GV, outs=addr)
|
||||
|
||||
# A specialized form of global_addr instructions that only handles
|
||||
# A specialized form of global_value instructions that only handles
|
||||
# symbolic names.
|
||||
globalsym_addr = Instruction(
|
||||
'globalsym_addr', r"""
|
||||
Compute the address of global variable GV, which is a symbolic name.
|
||||
Compute the address of global GV, which is a symbolic name.
|
||||
""",
|
||||
ins=GV, outs=addr)
|
||||
|
||||
|
||||
@@ -62,7 +62,7 @@ expand_flags = XFormGroup('expand_flags', """
|
||||
|
||||
|
||||
# Custom expansions for memory objects.
|
||||
expand.custom_legalize(insts.global_addr, 'expand_global_addr')
|
||||
expand.custom_legalize(insts.global_value, 'expand_global_value')
|
||||
expand.custom_legalize(insts.heap_addr, 'expand_heap_addr')
|
||||
|
||||
# Custom expansions for calls.
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
Cretonne predicates that consider `Function` fields.
|
||||
"""
|
||||
from cdsl.predicates import FieldPredicate
|
||||
from .formats import UnaryGlobalVar, InstructionFormat
|
||||
from .formats import UnaryGlobalValue, InstructionFormat
|
||||
|
||||
try:
|
||||
from typing import TYPE_CHECKING
|
||||
@@ -32,7 +32,7 @@ class IsColocatedData(FieldPredicate):
|
||||
def __init__(self):
|
||||
# type: () -> None
|
||||
super(IsColocatedData, self).__init__(
|
||||
UnaryGlobalVar.global_var, 'is_colocated_data', ('func',))
|
||||
UnaryGlobalValue.global_value, 'is_colocated_data', ('func',))
|
||||
|
||||
|
||||
class LengthEquals(FieldPredicate):
|
||||
|
||||
@@ -53,7 +53,7 @@ call_conv = EnumSetting(
|
||||
|
||||
# Note that Cretonne doesn't currently need an is_pie flag, because PIE is just
|
||||
# PIC where symbols can't be pre-empted, which can be expressed with the
|
||||
# `colocated` flag on external functions and global variables.
|
||||
# `colocated` flag on external functions and global valueiables.
|
||||
is_pic = BoolSetting("Enable Position-Independent Code generation")
|
||||
|
||||
colocated_libcalls = BoolSetting(
|
||||
|
||||
@@ -208,7 +208,7 @@ class InstructionFormat(object):
|
||||
"""
|
||||
Given a dict mapping name -> object as returned by `globals()`, find
|
||||
all the InstructionFormat objects and set their name from the dict key.
|
||||
This is used to name a bunch of global variables in a module.
|
||||
This is used to name a bunch of global valueiables in a module.
|
||||
"""
|
||||
for name, obj in globs.items():
|
||||
if isinstance(obj, InstructionFormat):
|
||||
|
||||
@@ -365,7 +365,7 @@ class RegClass(object):
|
||||
"""
|
||||
Given a dict mapping name -> object as returned by `globals()`, find
|
||||
all the RegClass objects and set their name from the dict key.
|
||||
This is used to name a bunch of global variables in a module.
|
||||
This is used to name a bunch of global valueiables in a module.
|
||||
"""
|
||||
for name, obj in globs.items():
|
||||
if isinstance(obj, RegClass):
|
||||
|
||||
@@ -14,7 +14,7 @@ from base.formats import IntCompare, IntCompareImm, FloatCompare
|
||||
from base.formats import IntCond, FloatCond
|
||||
from base.formats import IntSelect, IntCondTrap, FloatCondTrap
|
||||
from base.formats import Jump, Branch, BranchInt, BranchFloat
|
||||
from base.formats import Ternary, FuncAddr, UnaryGlobalVar
|
||||
from base.formats import Ternary, FuncAddr, UnaryGlobalValue
|
||||
from base.formats import RegMove, RegSpill, RegFill, CopySpecial
|
||||
from base.formats import LoadComplex, StoreComplex
|
||||
from .registers import GPR, ABCD, FPR, GPR_DEREF_SAFE, GPR_ZERO_DEREF_SAFE
|
||||
@@ -703,50 +703,50 @@ got_fnaddr8 = TailRecipe(
|
||||
|
||||
# XX+rd id with Abs4 globalsym relocation.
|
||||
gvaddr4 = TailRecipe(
|
||||
'gvaddr4', UnaryGlobalVar, size=4, ins=(), outs=GPR,
|
||||
'gvaddr4', UnaryGlobalValue, size=4, ins=(), outs=GPR,
|
||||
emit='''
|
||||
PUT_OP(bits | (out_reg0 & 7), rex1(out_reg0), sink);
|
||||
sink.reloc_external(Reloc::Abs4,
|
||||
&func.global_vars[global_var].symbol_name(),
|
||||
&func.global_values[global_value].symbol_name(),
|
||||
0);
|
||||
sink.put4(0);
|
||||
''')
|
||||
|
||||
# XX+rd iq with Abs8 globalsym relocation.
|
||||
gvaddr8 = TailRecipe(
|
||||
'gvaddr8', UnaryGlobalVar, size=8, ins=(), outs=GPR,
|
||||
'gvaddr8', UnaryGlobalValue, size=8, ins=(), outs=GPR,
|
||||
emit='''
|
||||
PUT_OP(bits | (out_reg0 & 7), rex1(out_reg0), sink);
|
||||
sink.reloc_external(Reloc::Abs8,
|
||||
&func.global_vars[global_var].symbol_name(),
|
||||
&func.global_values[global_value].symbol_name(),
|
||||
0);
|
||||
sink.put8(0);
|
||||
''')
|
||||
|
||||
# XX+rd iq with PCRel4 globalsym relocation.
|
||||
pcrel_gvaddr8 = TailRecipe(
|
||||
'pcrel_gvaddr8', UnaryGlobalVar, size=5, ins=(), outs=GPR,
|
||||
'pcrel_gvaddr8', UnaryGlobalValue, size=5, ins=(), outs=GPR,
|
||||
emit='''
|
||||
PUT_OP(bits, rex2(0, out_reg0), sink);
|
||||
modrm_rm(5, out_reg0, sink);
|
||||
// The addend adjusts for the difference between the end of the
|
||||
// instruction and the beginning of the immediate field.
|
||||
sink.reloc_external(Reloc::X86PCRel4,
|
||||
&func.global_vars[global_var].symbol_name(),
|
||||
&func.global_values[global_value].symbol_name(),
|
||||
-4);
|
||||
sink.put4(0);
|
||||
''')
|
||||
|
||||
# XX+rd iq with Abs8 globalsym relocation.
|
||||
got_gvaddr8 = TailRecipe(
|
||||
'got_gvaddr8', UnaryGlobalVar, size=5, ins=(), outs=GPR,
|
||||
'got_gvaddr8', UnaryGlobalValue, size=5, ins=(), outs=GPR,
|
||||
emit='''
|
||||
PUT_OP(bits, rex2(0, out_reg0), sink);
|
||||
modrm_rm(5, out_reg0, sink);
|
||||
// The addend adjusts for the difference between the end of the
|
||||
// instruction and the beginning of the immediate field.
|
||||
sink.reloc_external(Reloc::X86GOTPCRel4,
|
||||
&func.global_vars[global_var].symbol_name(),
|
||||
&func.global_values[global_value].symbol_name(),
|
||||
-4);
|
||||
sink.put4(0);
|
||||
''')
|
||||
|
||||
@@ -82,18 +82,18 @@ impl StackSlot {
|
||||
}
|
||||
}
|
||||
|
||||
/// An opaque reference to a global variable.
|
||||
/// An opaque reference to a global valueiable.
|
||||
#[derive(Copy, Clone, PartialEq, Eq, Hash)]
|
||||
pub struct GlobalVar(u32);
|
||||
entity_impl!(GlobalVar, "gv");
|
||||
pub struct GlobalValue(u32);
|
||||
entity_impl!(GlobalValue, "gv");
|
||||
|
||||
impl GlobalVar {
|
||||
/// Create a new global variable reference from its number.
|
||||
impl GlobalValue {
|
||||
/// Create a new global valueiable reference from its number.
|
||||
///
|
||||
/// This method is for use by the parser.
|
||||
pub fn with_number(n: u32) -> Option<Self> {
|
||||
if n < u32::MAX {
|
||||
Some(GlobalVar(n))
|
||||
Some(GlobalValue(n))
|
||||
} else {
|
||||
None
|
||||
}
|
||||
@@ -186,7 +186,7 @@ pub enum AnyEntity {
|
||||
/// A stack slot.
|
||||
StackSlot(StackSlot),
|
||||
/// A Global variable.
|
||||
GlobalVar(GlobalVar),
|
||||
GlobalValue(GlobalValue),
|
||||
/// A jump table.
|
||||
JumpTable(JumpTable),
|
||||
/// An external function.
|
||||
@@ -205,7 +205,7 @@ impl fmt::Display for AnyEntity {
|
||||
AnyEntity::Inst(r) => r.fmt(f),
|
||||
AnyEntity::Value(r) => r.fmt(f),
|
||||
AnyEntity::StackSlot(r) => r.fmt(f),
|
||||
AnyEntity::GlobalVar(r) => r.fmt(f),
|
||||
AnyEntity::GlobalValue(r) => r.fmt(f),
|
||||
AnyEntity::JumpTable(r) => r.fmt(f),
|
||||
AnyEntity::FuncRef(r) => r.fmt(f),
|
||||
AnyEntity::SigRef(r) => r.fmt(f),
|
||||
@@ -244,9 +244,9 @@ impl From<StackSlot> for AnyEntity {
|
||||
}
|
||||
}
|
||||
|
||||
impl From<GlobalVar> for AnyEntity {
|
||||
fn from(r: GlobalVar) -> Self {
|
||||
AnyEntity::GlobalVar(r)
|
||||
impl From<GlobalValue> for AnyEntity {
|
||||
fn from(r: GlobalValue) -> Self {
|
||||
AnyEntity::GlobalValue(r)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -284,7 +284,7 @@ pub enum ArgumentPurpose {
|
||||
/// A VM context pointer.
|
||||
///
|
||||
/// This is a pointer to a context struct containing details about the current sandbox. It is
|
||||
/// used as a base pointer for `vmctx` global variables.
|
||||
/// used as a base pointer for `vmctx` global valueiables.
|
||||
VMContext,
|
||||
|
||||
/// A signature identifier.
|
||||
|
||||
@@ -7,7 +7,7 @@ use binemit::CodeOffset;
|
||||
use entity::{EntityMap, PrimaryMap};
|
||||
use ir;
|
||||
use ir::{DataFlowGraph, ExternalName, Layout, Signature};
|
||||
use ir::{Ebb, ExtFuncData, FuncRef, GlobalVar, GlobalVarData, Heap, HeapData, JumpTable,
|
||||
use ir::{Ebb, ExtFuncData, FuncRef, GlobalValue, GlobalValueData, Heap, HeapData, JumpTable,
|
||||
JumpTableData, SigRef, StackSlot, StackSlotData};
|
||||
use ir::{EbbOffsets, InstEncodings, JumpTables, SourceLocs, StackSlots, ValueLocations};
|
||||
use isa::{EncInfo, Encoding, Legalize, TargetIsa};
|
||||
@@ -32,10 +32,10 @@ pub struct Function {
|
||||
|
||||
/// If not `None`, represents the address that the stack pointer should
|
||||
/// be checked against.
|
||||
pub stack_limit: Option<ir::GlobalVar>,
|
||||
pub stack_limit: Option<ir::GlobalValue>,
|
||||
|
||||
/// Global variables referenced.
|
||||
pub global_vars: PrimaryMap<ir::GlobalVar, ir::GlobalVarData>,
|
||||
pub global_values: PrimaryMap<ir::GlobalValue, ir::GlobalValueData>,
|
||||
|
||||
/// Heaps referenced.
|
||||
pub heaps: PrimaryMap<ir::Heap, ir::HeapData>,
|
||||
@@ -78,7 +78,7 @@ impl Function {
|
||||
signature: sig,
|
||||
stack_slots: StackSlots::new(),
|
||||
stack_limit: None,
|
||||
global_vars: PrimaryMap::new(),
|
||||
global_values: PrimaryMap::new(),
|
||||
heaps: PrimaryMap::new(),
|
||||
jump_tables: PrimaryMap::new(),
|
||||
dfg: DataFlowGraph::new(),
|
||||
@@ -94,7 +94,7 @@ impl Function {
|
||||
pub fn clear(&mut self) {
|
||||
self.signature.clear(CallConv::Fast);
|
||||
self.stack_slots.clear();
|
||||
self.global_vars.clear();
|
||||
self.global_values.clear();
|
||||
self.heaps.clear();
|
||||
self.jump_tables.clear();
|
||||
self.dfg.clear();
|
||||
@@ -129,7 +129,7 @@ impl Function {
|
||||
/// Sets the stack limit for the function.
|
||||
///
|
||||
/// Returns previous one if any.
|
||||
pub fn set_stack_limit(&mut self, stack_limit: Option<GlobalVar>) -> Option<GlobalVar> {
|
||||
pub fn set_stack_limit(&mut self, stack_limit: Option<GlobalValue>) -> Option<GlobalValue> {
|
||||
let prev = self.stack_limit.take();
|
||||
self.stack_limit = stack_limit;
|
||||
prev
|
||||
@@ -145,9 +145,9 @@ impl Function {
|
||||
self.dfg.ext_funcs.push(data)
|
||||
}
|
||||
|
||||
/// Declares a global variable accessible to the function.
|
||||
pub fn create_global_var(&mut self, data: GlobalVarData) -> GlobalVar {
|
||||
self.global_vars.push(data)
|
||||
/// Declares a global valueiable accessible to the function.
|
||||
pub fn create_global_value(&mut self, data: GlobalValueData) -> GlobalValue {
|
||||
self.global_values.push(data)
|
||||
}
|
||||
|
||||
/// Declares a heap accessible to the function.
|
||||
|
||||
70
lib/codegen/src/ir/globalvalue.rs
Normal file
70
lib/codegen/src/ir/globalvalue.rs
Normal file
@@ -0,0 +1,70 @@
|
||||
//! Global variables.
|
||||
|
||||
use ir::immediates::Offset32;
|
||||
use ir::{ExternalName, GlobalValue};
|
||||
use std::fmt;
|
||||
|
||||
/// Information about a global valueiable declaration.
|
||||
#[derive(Clone)]
|
||||
pub enum GlobalValueData {
|
||||
/// Variable is part of the VM context struct, it's address is a constant offset from the VM
|
||||
/// context pointer.
|
||||
VMContext {
|
||||
/// Offset from the `vmctx` pointer to this global.
|
||||
offset: Offset32,
|
||||
},
|
||||
|
||||
/// Variable is part of a struct pointed to by another global valueiable.
|
||||
///
|
||||
/// The `base` global valueiable is assumed to contain a pointer to a struct. This global
|
||||
/// variable lives at an offset into the struct. The memory must be accessible, and
|
||||
/// naturally aligned to hold a pointer value.
|
||||
Deref {
|
||||
/// The base pointer global valueiable.
|
||||
base: GlobalValue,
|
||||
|
||||
/// Byte offset to be added to the pointer loaded from `base`.
|
||||
offset: Offset32,
|
||||
},
|
||||
|
||||
/// Variable is at an address identified by a symbolic name. Cretonne itself
|
||||
/// does not interpret this name; it's used by embedders to link with other
|
||||
/// data structures.
|
||||
Sym {
|
||||
/// The symbolic name.
|
||||
name: ExternalName,
|
||||
|
||||
/// Will this variable be defined nearby, such that it will always be a certain distance
|
||||
/// away, after linking? If so, references to it can avoid going through a GOT. Note that
|
||||
/// symbols meant to be preemptible cannot be colocated.
|
||||
colocated: bool,
|
||||
},
|
||||
}
|
||||
|
||||
impl GlobalValueData {
|
||||
/// Assume that `self` is an `GlobalValueData::Sym` and return its name.
|
||||
pub fn symbol_name(&self) -> &ExternalName {
|
||||
match *self {
|
||||
GlobalValueData::Sym { ref name, .. } => name,
|
||||
_ => panic!("only symbols have names"),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl fmt::Display for GlobalValueData {
|
||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||
match *self {
|
||||
GlobalValueData::VMContext { offset } => write!(f, "vmctx{}", offset),
|
||||
GlobalValueData::Deref { base, offset } => write!(f, "deref({}){}", base, offset),
|
||||
GlobalValueData::Sym {
|
||||
ref name,
|
||||
colocated,
|
||||
} => {
|
||||
if colocated {
|
||||
write!(f, "colocated ")?;
|
||||
}
|
||||
write!(f, "globalsym {}", name)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,12 +1,12 @@
|
||||
//! Global variables.
|
||||
|
||||
use ir::immediates::Offset32;
|
||||
use ir::{ExternalName, GlobalVar};
|
||||
use ir::{ExternalName, GlobalValue};
|
||||
use std::fmt;
|
||||
|
||||
/// Information about a global variable declaration.
|
||||
/// Information about a global valueiable declaration.
|
||||
#[derive(Clone)]
|
||||
pub enum GlobalVarData {
|
||||
pub enum GlobalValueData {
|
||||
/// Variable is part of the VM context struct, it's address is a constant offset from the VM
|
||||
/// context pointer.
|
||||
VMContext {
|
||||
@@ -14,14 +14,14 @@ pub enum GlobalVarData {
|
||||
offset: Offset32,
|
||||
},
|
||||
|
||||
/// Variable is part of a struct pointed to by another global variable.
|
||||
/// Variable is part of a struct pointed to by another global valueiable.
|
||||
///
|
||||
/// The `base` global variable is assumed to contain a pointer to a struct. This global
|
||||
/// The `base` global valueiable is assumed to contain a pointer to a struct. This global
|
||||
/// variable lives at an offset into the struct. The memory must be accessible, and
|
||||
/// naturally aligned to hold a pointer value.
|
||||
Deref {
|
||||
/// The base pointer global variable.
|
||||
base: GlobalVar,
|
||||
/// The base pointer global valueiable.
|
||||
base: GlobalValue,
|
||||
|
||||
/// Byte offset to be added to the pointer loaded from `base`.
|
||||
offset: Offset32,
|
||||
@@ -41,22 +41,22 @@ pub enum GlobalVarData {
|
||||
},
|
||||
}
|
||||
|
||||
impl GlobalVarData {
|
||||
/// Assume that `self` is an `GlobalVarData::Sym` and return its name.
|
||||
impl GlobalValueData {
|
||||
/// Assume that `self` is an `GlobalValueData::Sym` and return its name.
|
||||
pub fn symbol_name(&self) -> &ExternalName {
|
||||
match *self {
|
||||
GlobalVarData::Sym { ref name, .. } => name,
|
||||
GlobalValueData::Sym { ref name, .. } => name,
|
||||
_ => panic!("only symbols have names"),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl fmt::Display for GlobalVarData {
|
||||
impl fmt::Display for GlobalValueData {
|
||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||
match *self {
|
||||
GlobalVarData::VMContext { offset } => write!(f, "vmctx{}", offset),
|
||||
GlobalVarData::Deref { base, offset } => write!(f, "deref({}){}", base, offset),
|
||||
GlobalVarData::Sym {
|
||||
GlobalValueData::VMContext { offset } => write!(f, "vmctx{}", offset),
|
||||
GlobalValueData::Deref { base, offset } => write!(f, "deref({}){}", base, offset),
|
||||
GlobalValueData::Sym {
|
||||
ref name,
|
||||
colocated,
|
||||
} => {
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
//! Heaps.
|
||||
|
||||
use ir::immediates::Imm64;
|
||||
use ir::GlobalVar;
|
||||
use ir::GlobalValue;
|
||||
use std::fmt;
|
||||
|
||||
/// Information about a heap declaration.
|
||||
@@ -29,9 +29,9 @@ pub enum HeapBase {
|
||||
/// This feature is not yet implemented.
|
||||
ReservedReg,
|
||||
|
||||
/// The heap base is in a global variable. The variable must be accessible and naturally
|
||||
/// The heap base is in a global valueiable. The variable must be accessible and naturally
|
||||
/// aligned for a pointer.
|
||||
GlobalVar(GlobalVar),
|
||||
GlobalValue(GlobalValue),
|
||||
}
|
||||
|
||||
/// Style of heap including style-specific information.
|
||||
@@ -41,7 +41,7 @@ pub enum HeapStyle {
|
||||
Dynamic {
|
||||
/// Global variable holding the current bound of the heap in bytes. It is
|
||||
/// required to be accessible and naturally aligned for a pointer-sized integer.
|
||||
bound_gv: GlobalVar,
|
||||
bound_gv: GlobalValue,
|
||||
},
|
||||
|
||||
/// A static heap has a fixed base address and a number of not-yet-allocated pages before the
|
||||
@@ -61,7 +61,7 @@ impl fmt::Display for HeapData {
|
||||
|
||||
match self.base {
|
||||
HeapBase::ReservedReg => write!(f, " reserved_reg")?,
|
||||
HeapBase::GlobalVar(gv) => write!(f, " {}", gv)?,
|
||||
HeapBase::GlobalValue(gv) => write!(f, " {}", gv)?,
|
||||
}
|
||||
|
||||
write!(f, ", min {}", self.min_size)?;
|
||||
|
||||
@@ -7,7 +7,7 @@ pub mod entities;
|
||||
mod extfunc;
|
||||
mod extname;
|
||||
pub mod function;
|
||||
mod globalvar;
|
||||
mod globalvalue;
|
||||
mod heap;
|
||||
pub mod immediates;
|
||||
pub mod instructions;
|
||||
@@ -24,11 +24,11 @@ mod valueloc;
|
||||
|
||||
pub use ir::builder::{InsertBuilder, InstBuilder, InstBuilderBase, InstInserterBase};
|
||||
pub use ir::dfg::{DataFlowGraph, ValueDef};
|
||||
pub use ir::entities::{Ebb, FuncRef, GlobalVar, Heap, Inst, JumpTable, SigRef, StackSlot, Value};
|
||||
pub use ir::entities::{Ebb, FuncRef, GlobalValue, Heap, Inst, JumpTable, SigRef, StackSlot, Value};
|
||||
pub use ir::extfunc::{AbiParam, ArgumentExtension, ArgumentPurpose, ExtFuncData, Signature};
|
||||
pub use ir::extname::ExternalName;
|
||||
pub use ir::function::Function;
|
||||
pub use ir::globalvar::GlobalVarData;
|
||||
pub use ir::globalvalue::GlobalValueData;
|
||||
pub use ir::heap::{HeapBase, HeapData, HeapStyle};
|
||||
pub use ir::instructions::{InstructionData, Opcode, ValueList, ValueListPool, VariableArgs};
|
||||
pub use ir::jumptable::JumpTableData;
|
||||
|
||||
@@ -1,15 +1,15 @@
|
||||
//! Legalization of global variables.
|
||||
//! Legalization of global valueiables.
|
||||
//!
|
||||
//! This module exports the `expand_global_addr` function which transforms a `global_addr`
|
||||
//! instruction into code that depends on the kind of global variable referenced.
|
||||
//! This module exports the `expand_global_value` function which transforms a `global_value`
|
||||
//! instruction into code that depends on the kind of global valueiable referenced.
|
||||
|
||||
use cursor::{Cursor, FuncCursor};
|
||||
use flowgraph::ControlFlowGraph;
|
||||
use ir::{self, InstBuilder};
|
||||
use isa::TargetIsa;
|
||||
|
||||
/// Expand a `global_addr` instruction according to the definition of the global variable.
|
||||
pub fn expand_global_addr(
|
||||
/// Expand a `global_value` instruction according to the definition of the global valueiable.
|
||||
pub fn expand_global_value(
|
||||
inst: ir::Inst,
|
||||
func: &mut ir::Function,
|
||||
_cfg: &mut ControlFlowGraph,
|
||||
@@ -17,40 +17,43 @@ pub fn expand_global_addr(
|
||||
) {
|
||||
// Unpack the instruction.
|
||||
let gv = match func.dfg[inst] {
|
||||
ir::InstructionData::UnaryGlobalVar { opcode, global_var } => {
|
||||
debug_assert_eq!(opcode, ir::Opcode::GlobalAddr);
|
||||
global_var
|
||||
ir::InstructionData::UnaryGlobalValue {
|
||||
opcode,
|
||||
global_value,
|
||||
} => {
|
||||
debug_assert_eq!(opcode, ir::Opcode::GlobalValue);
|
||||
global_value
|
||||
}
|
||||
_ => panic!("Wanted global_addr: {}", func.dfg.display_inst(inst, None)),
|
||||
_ => panic!("Wanted global_value: {}", func.dfg.display_inst(inst, None)),
|
||||
};
|
||||
|
||||
match func.global_vars[gv] {
|
||||
ir::GlobalVarData::VMContext { offset } => vmctx_addr(inst, func, offset.into()),
|
||||
ir::GlobalVarData::Deref { base, offset } => deref_addr(inst, func, base, offset.into()),
|
||||
ir::GlobalVarData::Sym { .. } => globalsym(inst, func, gv),
|
||||
match func.global_values[gv] {
|
||||
ir::GlobalValueData::VMContext { offset } => vmctx_addr(inst, func, offset.into()),
|
||||
ir::GlobalValueData::Deref { base, offset } => deref_addr(inst, func, base, offset.into()),
|
||||
ir::GlobalValueData::Sym { .. } => globalsym(inst, func, gv),
|
||||
}
|
||||
}
|
||||
|
||||
/// Expand a `global_addr` instruction for a vmctx global.
|
||||
/// Expand a `global_value` instruction for a vmctx global.
|
||||
fn vmctx_addr(inst: ir::Inst, func: &mut ir::Function, offset: i64) {
|
||||
// Get the value representing the `vmctx` argument.
|
||||
let vmctx = func.special_param(ir::ArgumentPurpose::VMContext)
|
||||
.expect("Missing vmctx parameter");
|
||||
|
||||
// Simply replace the `global_addr` instruction with an `iadd_imm`, reusing the result value.
|
||||
// Simply replace the `global_value` instruction with an `iadd_imm`, reusing the result value.
|
||||
func.dfg.replace(inst).iadd_imm(vmctx, offset);
|
||||
}
|
||||
|
||||
/// Expand a `global_addr` instruction for a deref global.
|
||||
fn deref_addr(inst: ir::Inst, func: &mut ir::Function, base: ir::GlobalVar, offset: i64) {
|
||||
// We need to load a pointer from the `base` global variable, so insert a new `global_addr`
|
||||
/// Expand a `global_value` instruction for a deref global.
|
||||
fn deref_addr(inst: ir::Inst, func: &mut ir::Function, base: ir::GlobalValue, offset: i64) {
|
||||
// We need to load a pointer from the `base` global valueiable, so insert a new `global_value`
|
||||
// instruction. This depends on the iterative legalization loop. Note that the IR verifier
|
||||
// detects any cycles in the `deref` globals.
|
||||
let ptr_ty = func.dfg.value_type(func.dfg.first_result(inst));
|
||||
let mut pos = FuncCursor::new(func).at_inst(inst);
|
||||
pos.use_srcloc(inst);
|
||||
|
||||
let base_addr = pos.ins().global_addr(ptr_ty, base);
|
||||
let base_addr = pos.ins().global_value(ptr_ty, base);
|
||||
let mut mflags = ir::MemFlags::new();
|
||||
// Deref globals are required to be accessible and aligned.
|
||||
mflags.set_notrap();
|
||||
@@ -59,8 +62,8 @@ fn deref_addr(inst: ir::Inst, func: &mut ir::Function, base: ir::GlobalVar, offs
|
||||
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) {
|
||||
/// Expand a `global_value` instruction for a symbolic name global.
|
||||
fn globalsym(inst: ir::Inst, func: &mut ir::Function, gv: ir::GlobalValue) {
|
||||
let ptr_ty = func.dfg.value_type(func.dfg.first_result(inst));
|
||||
func.dfg.replace(inst).globalsym_addr(ptr_ty, gv);
|
||||
}
|
||||
@@ -46,7 +46,7 @@ fn dynamic_addr(
|
||||
heap: ir::Heap,
|
||||
offset: ir::Value,
|
||||
size: u32,
|
||||
bound_gv: ir::GlobalVar,
|
||||
bound_gv: ir::GlobalValue,
|
||||
func: &mut ir::Function,
|
||||
) {
|
||||
let size = i64::from(size);
|
||||
@@ -57,7 +57,7 @@ fn dynamic_addr(
|
||||
pos.use_srcloc(inst);
|
||||
|
||||
// Start with the bounds check. Trap if `offset + size > bound`.
|
||||
let bound_addr = pos.ins().global_addr(addr_ty, bound_gv);
|
||||
let bound_addr = pos.ins().global_value(addr_ty, bound_gv);
|
||||
let mut mflags = MemFlags::new();
|
||||
// The bound variable is requied to be accessible and aligned.
|
||||
mflags.set_notrap();
|
||||
@@ -162,8 +162,8 @@ fn offset_addr(
|
||||
// Add the heap base address base
|
||||
match pos.func.heaps[heap].base {
|
||||
ir::HeapBase::ReservedReg => unimplemented!(),
|
||||
ir::HeapBase::GlobalVar(base_gv) => {
|
||||
let base_addr = pos.ins().global_addr(addr_ty, base_gv);
|
||||
ir::HeapBase::GlobalValue(base_gv) => {
|
||||
let base_addr = pos.ins().global_value(addr_ty, base_gv);
|
||||
let mut mflags = MemFlags::new();
|
||||
// The base address variable is requied to be accessible and aligned.
|
||||
mflags.set_notrap();
|
||||
|
||||
@@ -22,13 +22,13 @@ use timing;
|
||||
|
||||
mod boundary;
|
||||
mod call;
|
||||
mod globalvar;
|
||||
mod globalvalue;
|
||||
mod heap;
|
||||
mod libcall;
|
||||
mod split;
|
||||
|
||||
use self::call::expand_call;
|
||||
use self::globalvar::expand_global_addr;
|
||||
use self::globalvalue::expand_global_value;
|
||||
use self::heap::expand_heap_addr;
|
||||
use self::libcall::expand_as_libcall;
|
||||
|
||||
|
||||
@@ -53,9 +53,9 @@ pub fn is_colocated_func(func_ref: ir::FuncRef, func: &ir::Function) -> bool {
|
||||
}
|
||||
|
||||
#[allow(dead_code)]
|
||||
pub fn is_colocated_data(global_var: ir::GlobalVar, func: &ir::Function) -> bool {
|
||||
match func.global_vars[global_var] {
|
||||
ir::GlobalVarData::Sym { colocated, .. } => colocated,
|
||||
pub fn is_colocated_data(global_value: ir::GlobalValue, func: &ir::Function) -> bool {
|
||||
match func.global_values[global_value] {
|
||||
ir::GlobalValueData::Sym { colocated, .. } => colocated,
|
||||
_ => panic!("is_colocated_data only makes sense for data with symbolic addresses"),
|
||||
}
|
||||
}
|
||||
|
||||
@@ -777,7 +777,7 @@ impl Solver {
|
||||
if is_global {
|
||||
let mut new_var = Variable::new_live(value, rc, reg, true);
|
||||
new_var.is_global = true;
|
||||
dbg!("add_tied_input: new tied-global var: {}", new_var);
|
||||
dbg!("add_tied_input: new tied-global value: {}", new_var);
|
||||
self.vars.push(new_var);
|
||||
self.regs_in.free(rc, reg);
|
||||
} else {
|
||||
@@ -920,7 +920,7 @@ impl Solver {
|
||||
Some(reg) => reg,
|
||||
None => {
|
||||
// If `v` must avoid global interference, there is not point in requesting
|
||||
// live registers be diverted. We need to make it a non-global variable.
|
||||
// live registers be diverted. We need to make it a non-global valueiable.
|
||||
if v.is_global && gregs.iter(rc).next().is_none() {
|
||||
return Err(SolverError::Global(v.value));
|
||||
} else {
|
||||
|
||||
@@ -63,7 +63,7 @@ use flowgraph::ControlFlowGraph;
|
||||
use ir;
|
||||
use ir::entities::AnyEntity;
|
||||
use ir::instructions::{BranchInfo, CallInfo, InstructionFormat, ResolvedConstraint};
|
||||
use ir::{types, ArgumentLoc, Ebb, FuncRef, Function, GlobalVar, Inst, JumpTable, Opcode, SigRef,
|
||||
use ir::{types, ArgumentLoc, Ebb, FuncRef, Function, GlobalValue, Inst, JumpTable, Opcode, SigRef,
|
||||
StackSlot, StackSlotKind, Type, Value, ValueDef, ValueList, ValueLoc};
|
||||
use isa::TargetIsa;
|
||||
use iterators::IteratorExtras;
|
||||
@@ -168,16 +168,16 @@ impl<'a> Verifier<'a> {
|
||||
}
|
||||
}
|
||||
|
||||
// Check for cycles in the global variable declarations.
|
||||
fn verify_global_vars(&self) -> VerifierResult<()> {
|
||||
// Check for cycles in the global valueiable declarations.
|
||||
fn verify_global_values(&self) -> VerifierResult<()> {
|
||||
let mut seen = SparseSet::new();
|
||||
|
||||
for gv in self.func.global_vars.keys() {
|
||||
for gv in self.func.global_values.keys() {
|
||||
seen.clear();
|
||||
seen.insert(gv);
|
||||
|
||||
let mut cur = gv;
|
||||
while let ir::GlobalVarData::Deref { base, .. } = self.func.global_vars[cur] {
|
||||
while let ir::GlobalValueData::Deref { base, .. } = self.func.global_values[cur] {
|
||||
if seen.insert(base).is_some() {
|
||||
return err!(gv, "deref cycle: {}", DisplayList(seen.as_slice()));
|
||||
}
|
||||
@@ -327,8 +327,8 @@ impl<'a> Verifier<'a> {
|
||||
StackLoad { stack_slot, .. } | StackStore { stack_slot, .. } => {
|
||||
self.verify_stack_slot(inst, stack_slot)?;
|
||||
}
|
||||
UnaryGlobalVar { global_var, .. } => {
|
||||
self.verify_global_var(inst, global_var)?;
|
||||
UnaryGlobalValue { global_value, .. } => {
|
||||
self.verify_global_value(inst, global_value)?;
|
||||
}
|
||||
HeapAddr { heap, .. } => {
|
||||
self.verify_heap(inst, heap)?;
|
||||
@@ -413,9 +413,9 @@ impl<'a> Verifier<'a> {
|
||||
}
|
||||
}
|
||||
|
||||
fn verify_global_var(&self, inst: Inst, gv: GlobalVar) -> VerifierResult<()> {
|
||||
if !self.func.global_vars.is_valid(gv) {
|
||||
err!(inst, "invalid global variable {}", gv)
|
||||
fn verify_global_value(&self, inst: Inst, gv: GlobalValue) -> VerifierResult<()> {
|
||||
if !self.func.global_values.is_valid(gv) {
|
||||
err!(inst, "invalid global valueiable {}", gv)
|
||||
} else {
|
||||
Ok(())
|
||||
}
|
||||
@@ -1124,7 +1124,7 @@ impl<'a> Verifier<'a> {
|
||||
}
|
||||
|
||||
pub fn run(&self) -> VerifierResult<()> {
|
||||
self.verify_global_vars()?;
|
||||
self.verify_global_values()?;
|
||||
self.typecheck_entry_block_params()?;
|
||||
for ebb in self.func.layout.ebbs() {
|
||||
for inst in self.func.layout.ebb_insts(ebb) {
|
||||
|
||||
@@ -49,7 +49,7 @@ fn write_preamble(
|
||||
writeln!(w, " {} = {}", ss, slot)?;
|
||||
}
|
||||
|
||||
for (gv, gv_data) in &func.global_vars {
|
||||
for (gv, gv_data) in &func.global_values {
|
||||
any = true;
|
||||
writeln!(w, " {} = {}", gv, gv_data)?;
|
||||
}
|
||||
@@ -285,7 +285,7 @@ pub fn write_operands(
|
||||
UnaryIeee32 { imm, .. } => write!(w, " {}", imm),
|
||||
UnaryIeee64 { imm, .. } => write!(w, " {}", imm),
|
||||
UnaryBool { imm, .. } => write!(w, " {}", imm),
|
||||
UnaryGlobalVar { global_var, .. } => write!(w, " {}", global_var),
|
||||
UnaryGlobalValue { global_value, .. } => write!(w, " {}", global_value),
|
||||
Binary { args, .. } => write!(w, " {}, {}", args[0], args[1]),
|
||||
BinaryImm { arg, imm, .. } => write!(w, " {}, {}", arg, imm),
|
||||
Ternary { args, .. } => write!(w, " {}, {}, {}", args[0], args[1], args[2]),
|
||||
|
||||
@@ -266,7 +266,7 @@ impl Backend for FaerieBackend {
|
||||
&mut self,
|
||||
_data: &mut FaerieCompiledData,
|
||||
_offset: usize,
|
||||
_what: ir::GlobalVar,
|
||||
_what: ir::GlobalValue,
|
||||
_usize: binemit::Addend,
|
||||
) {
|
||||
unimplemented!()
|
||||
|
||||
@@ -3,10 +3,10 @@ use cretonne_codegen::cursor::{Cursor, FuncCursor};
|
||||
use cretonne_codegen::entity::{EntityMap, EntityRef, EntitySet};
|
||||
use cretonne_codegen::ir;
|
||||
use cretonne_codegen::ir::function::DisplayFunction;
|
||||
use cretonne_codegen::ir::{DataFlowGraph, Ebb, ExtFuncData, FuncRef, Function, GlobalVar,
|
||||
GlobalVarData, Heap, HeapData, Inst, InstBuilderBase, InstructionData,
|
||||
JumpTable, JumpTableData, SigRef, Signature, StackSlot, StackSlotData,
|
||||
Type, Value};
|
||||
use cretonne_codegen::ir::{DataFlowGraph, Ebb, ExtFuncData, FuncRef, Function, GlobalValue,
|
||||
GlobalValueData, Heap, HeapData, Inst, InstBuilderBase,
|
||||
InstructionData, JumpTable, JumpTableData, SigRef, Signature,
|
||||
StackSlot, StackSlotData, Type, Value};
|
||||
use cretonne_codegen::isa::TargetIsa;
|
||||
use cretonne_codegen::packed_option::PackedOption;
|
||||
use ssa::{Block, SSABuilder, SideEffects};
|
||||
@@ -377,9 +377,9 @@ where
|
||||
self.func.import_function(data)
|
||||
}
|
||||
|
||||
/// Declares a global variable accessible to the function.
|
||||
pub fn create_global_var(&mut self, data: GlobalVarData) -> GlobalVar {
|
||||
self.func.create_global_var(data)
|
||||
/// Declares a global valueiable accessible to the function.
|
||||
pub fn create_global_value(&mut self, data: GlobalValueData) -> GlobalValue {
|
||||
self.func.create_global_value(data)
|
||||
}
|
||||
|
||||
/// Declares a heap accessible to the function.
|
||||
|
||||
@@ -84,7 +84,7 @@ where
|
||||
&mut self,
|
||||
data: &mut Self::CompiledData,
|
||||
offset: usize,
|
||||
what: ir::GlobalVar,
|
||||
what: ir::GlobalValue,
|
||||
addend: binemit::Addend,
|
||||
);
|
||||
|
||||
|
||||
@@ -52,11 +52,11 @@ pub struct DataDescription {
|
||||
/// External function declarations.
|
||||
pub function_decls: PrimaryMap<ir::FuncRef, ir::ExternalName>,
|
||||
/// External data object declarations.
|
||||
pub data_decls: PrimaryMap<ir::GlobalVar, ir::ExternalName>,
|
||||
pub data_decls: PrimaryMap<ir::GlobalValue, ir::ExternalName>,
|
||||
/// Function addresses to write at specified offsets.
|
||||
pub function_relocs: Vec<(CodeOffset, ir::FuncRef)>,
|
||||
/// Data addresses to write at specified offsets.
|
||||
pub data_relocs: Vec<(CodeOffset, ir::GlobalVar, Addend)>,
|
||||
pub data_relocs: Vec<(CodeOffset, ir::GlobalValue, Addend)>,
|
||||
}
|
||||
|
||||
/// This is to data objects what cretonne_codegen::Context is to functions.
|
||||
@@ -114,14 +114,14 @@ impl DataContext {
|
||||
self.description.function_decls.push(name)
|
||||
}
|
||||
|
||||
/// Declares a global variable import.
|
||||
/// Declares a global valueiable import.
|
||||
///
|
||||
/// TODO: Rename to import_data?
|
||||
///
|
||||
/// Users of the `Module` API generally should call
|
||||
/// `Module::declare_data_in_data` instead, as it takes care of generating
|
||||
/// the appropriate `ExternalName`.
|
||||
pub fn import_global_var(&mut self, name: ir::ExternalName) -> ir::GlobalVar {
|
||||
pub fn import_global_value(&mut self, name: ir::ExternalName) -> ir::GlobalValue {
|
||||
self.description.data_decls.push(name)
|
||||
}
|
||||
|
||||
@@ -131,7 +131,7 @@ impl DataContext {
|
||||
}
|
||||
|
||||
/// Write the address of `data` into the data at offset `offset`.
|
||||
pub fn write_data_addr(&mut self, offset: CodeOffset, data: ir::GlobalVar, addend: Addend) {
|
||||
pub fn write_data_addr(&mut self, offset: CodeOffset, data: ir::GlobalValue, addend: Addend) {
|
||||
self.description.data_relocs.push((offset, data, addend))
|
||||
}
|
||||
|
||||
@@ -168,8 +168,8 @@ mod tests {
|
||||
let _func_a = data_ctx.import_function(ir::ExternalName::user(0, 0));
|
||||
let func_b = data_ctx.import_function(ir::ExternalName::user(0, 1));
|
||||
let func_c = data_ctx.import_function(ir::ExternalName::user(1, 0));
|
||||
let _data_a = data_ctx.import_global_var(ir::ExternalName::user(2, 2));
|
||||
let data_b = data_ctx.import_global_var(ir::ExternalName::user(2, 3));
|
||||
let _data_a = data_ctx.import_global_value(ir::ExternalName::user(2, 2));
|
||||
let data_b = data_ctx.import_global_value(ir::ExternalName::user(2, 3));
|
||||
|
||||
data_ctx.write_function_addr(8, func_b);
|
||||
data_ctx.write_function_addr(16, func_c);
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
|
||||
// TODO: Should `ir::Function` really have a `name`?
|
||||
|
||||
// TODO: Factor out `ir::Function`'s `ext_funcs` and `global_vars` into a struct
|
||||
// TODO: Factor out `ir::Function`'s `ext_funcs` and `global_values` into a struct
|
||||
// shared with `DataContext`?
|
||||
|
||||
use cretonne_codegen::entity::{EntityRef, PrimaryMap};
|
||||
@@ -440,10 +440,10 @@ where
|
||||
/// Use this when you're building the IR of a function to reference a data object.
|
||||
///
|
||||
/// TODO: Same as above.
|
||||
pub fn declare_data_in_func(&self, data: DataId, func: &mut ir::Function) -> ir::GlobalVar {
|
||||
pub fn declare_data_in_func(&self, data: DataId, func: &mut ir::Function) -> ir::GlobalValue {
|
||||
let decl = &self.contents.data_objects[data].decl;
|
||||
let colocated = decl.linkage.is_final();
|
||||
func.create_global_var(ir::GlobalVarData::Sym {
|
||||
func.create_global_value(ir::GlobalValueData::Sym {
|
||||
name: ir::ExternalName::user(1, data.index() as u32),
|
||||
colocated,
|
||||
})
|
||||
@@ -455,8 +455,8 @@ where
|
||||
}
|
||||
|
||||
/// TODO: Same as above.
|
||||
pub fn declare_data_in_data(&self, data: DataId, ctx: &mut DataContext) -> ir::GlobalVar {
|
||||
ctx.import_global_var(ir::ExternalName::user(1, data.index() as u32))
|
||||
pub fn declare_data_in_data(&self, data: DataId, ctx: &mut DataContext) -> ir::GlobalValue {
|
||||
ctx.import_global_value(ir::ExternalName::user(1, data.index() as u32))
|
||||
}
|
||||
|
||||
/// Define a function, producing the function body from the given `Context`.
|
||||
@@ -536,7 +536,7 @@ where
|
||||
&mut self,
|
||||
data: DataId,
|
||||
offset: usize,
|
||||
what: ir::GlobalVar,
|
||||
what: ir::GlobalValue,
|
||||
addend: binemit::Addend,
|
||||
) {
|
||||
let info = &mut self.contents.data_objects[data];
|
||||
|
||||
@@ -34,7 +34,7 @@ pub enum Token<'a> {
|
||||
Value(Value), // v12, v7
|
||||
Ebb(Ebb), // ebb3
|
||||
StackSlot(u32), // ss3
|
||||
GlobalVar(u32), // gv3
|
||||
GlobalValue(u32), // gv3
|
||||
Heap(u32), // heap2
|
||||
JumpTable(u32), // jt2
|
||||
FuncRef(u32), // fn2
|
||||
@@ -338,7 +338,7 @@ impl<'a> Lexer<'a> {
|
||||
"v" => Value::with_number(number).map(Token::Value),
|
||||
"ebb" => Ebb::with_number(number).map(Token::Ebb),
|
||||
"ss" => Some(Token::StackSlot(number)),
|
||||
"gv" => Some(Token::GlobalVar(number)),
|
||||
"gv" => Some(Token::GlobalValue(number)),
|
||||
"heap" => Some(Token::Heap(number)),
|
||||
"jt" => Some(Token::JumpTable(number)),
|
||||
"fn" => Some(Token::FuncRef(number)),
|
||||
|
||||
@@ -7,7 +7,7 @@ use cretonne_codegen::ir::immediates::{Ieee32, Ieee64, Imm64, Offset32, Uimm32};
|
||||
use cretonne_codegen::ir::instructions::{InstructionData, InstructionFormat, VariableArgs};
|
||||
use cretonne_codegen::ir::types::VOID;
|
||||
use cretonne_codegen::ir::{AbiParam, ArgumentExtension, ArgumentLoc, Ebb, ExtFuncData,
|
||||
ExternalName, FuncRef, Function, GlobalVar, GlobalVarData, Heap,
|
||||
ExternalName, FuncRef, Function, GlobalValue, GlobalValueData, Heap,
|
||||
HeapBase, HeapData, HeapStyle, JumpTable, JumpTableData, MemFlags,
|
||||
Opcode, SigRef, Signature, StackSlot, StackSlotData, StackSlotKind,
|
||||
Type, Value, ValueLoc};
|
||||
@@ -139,22 +139,27 @@ impl<'a> Context<'a> {
|
||||
}
|
||||
}
|
||||
|
||||
// Allocate a global variable slot.
|
||||
fn add_gv(&mut self, gv: GlobalVar, data: GlobalVarData, loc: &Location) -> ParseResult<()> {
|
||||
while self.function.global_vars.next_key().index() <= gv.index() {
|
||||
self.function.create_global_var(GlobalVarData::Sym {
|
||||
// Allocate a global valueiable slot.
|
||||
fn add_gv(
|
||||
&mut self,
|
||||
gv: GlobalValue,
|
||||
data: GlobalValueData,
|
||||
loc: &Location,
|
||||
) -> ParseResult<()> {
|
||||
while self.function.global_values.next_key().index() <= gv.index() {
|
||||
self.function.create_global_value(GlobalValueData::Sym {
|
||||
name: ExternalName::testcase(""),
|
||||
colocated: false,
|
||||
});
|
||||
}
|
||||
self.function.global_vars[gv] = data;
|
||||
self.function.global_values[gv] = data;
|
||||
self.map.def_gv(gv, loc)
|
||||
}
|
||||
|
||||
// Resolve a reference to a global variable.
|
||||
fn check_gv(&self, gv: GlobalVar, loc: &Location) -> ParseResult<()> {
|
||||
// Resolve a reference to a global valueiable.
|
||||
fn check_gv(&self, gv: GlobalValue, loc: &Location) -> ParseResult<()> {
|
||||
if !self.map.contains_gv(gv) {
|
||||
err!(loc, "undefined global variable {}", gv)
|
||||
err!(loc, "undefined global valueiable {}", gv)
|
||||
} else {
|
||||
Ok(())
|
||||
}
|
||||
@@ -245,7 +250,7 @@ impl<'a> Context<'a> {
|
||||
}
|
||||
|
||||
// Assign the global for the stack limit.
|
||||
fn set_stack_limit(&mut self, gv: GlobalVar, loc: &Location) -> ParseResult<()> {
|
||||
fn set_stack_limit(&mut self, gv: GlobalValue, loc: &Location) -> ParseResult<()> {
|
||||
if let Some(_) = self.function.set_stack_limit(Some(gv)) {
|
||||
err!(loc, "multiple stack_limit declarations")
|
||||
} else {
|
||||
@@ -396,11 +401,11 @@ impl<'a> Parser<'a> {
|
||||
err!(self.loc, err_msg)
|
||||
}
|
||||
|
||||
// Match and consume a global variable reference.
|
||||
fn match_gv(&mut self, err_msg: &str) -> ParseResult<GlobalVar> {
|
||||
if let Some(Token::GlobalVar(gv)) = self.token() {
|
||||
// Match and consume a global valueiable reference.
|
||||
fn match_gv(&mut self, err_msg: &str) -> ParseResult<GlobalValue> {
|
||||
if let Some(Token::GlobalValue(gv)) = self.token() {
|
||||
self.consume();
|
||||
if let Some(gv) = GlobalVar::with_number(gv) {
|
||||
if let Some(gv) = GlobalValue::with_number(gv) {
|
||||
return Ok(gv);
|
||||
}
|
||||
}
|
||||
@@ -1000,9 +1005,9 @@ impl<'a> Parser<'a> {
|
||||
self.parse_stack_slot_decl()
|
||||
.and_then(|(ss, dat)| ctx.add_ss(ss, dat, &loc))
|
||||
}
|
||||
Some(Token::GlobalVar(..)) => {
|
||||
Some(Token::GlobalValue(..)) => {
|
||||
self.start_gathering_comments();
|
||||
self.parse_global_var_decl()
|
||||
self.parse_global_value_decl()
|
||||
.and_then(|(gv, dat)| ctx.add_gv(gv, dat, &self.loc))
|
||||
}
|
||||
Some(Token::Heap(..)) => {
|
||||
@@ -1072,36 +1077,45 @@ impl<'a> Parser<'a> {
|
||||
Ok((ss, data))
|
||||
}
|
||||
|
||||
// Parse a global variable decl.
|
||||
// Parse a global valueiable decl.
|
||||
//
|
||||
// global-var-decl ::= * GlobalVar(gv) "=" global-var-desc
|
||||
// global-var-decl ::= * GlobalValue(gv) "=" global-var-desc
|
||||
// global-var-desc ::= "vmctx" offset32
|
||||
// | "deref" "(" GlobalVar(base) ")" offset32
|
||||
// | "deref" "(" GlobalValue(base) ")" offset32
|
||||
// | globalsym ["colocated"] name
|
||||
//
|
||||
fn parse_global_var_decl(&mut self) -> ParseResult<(GlobalVar, GlobalVarData)> {
|
||||
let gv = self.match_gv("expected global variable number: gv«n»")?;
|
||||
fn parse_global_value_decl(&mut self) -> ParseResult<(GlobalValue, GlobalValueData)> {
|
||||
let gv = self.match_gv("expected global valueiable number: gv«n»")?;
|
||||
|
||||
self.match_token(Token::Equal, "expected '=' in global variable declaration")?;
|
||||
self.match_token(
|
||||
Token::Equal,
|
||||
"expected '=' in global valueiable declaration",
|
||||
)?;
|
||||
|
||||
let data = match self.match_any_identifier("expected global variable kind")? {
|
||||
let data = match self.match_any_identifier("expected global valueiable kind")? {
|
||||
"vmctx" => {
|
||||
let offset = self.optional_offset32()?;
|
||||
GlobalVarData::VMContext { offset }
|
||||
GlobalValueData::VMContext { offset }
|
||||
}
|
||||
"deref" => {
|
||||
self.match_token(Token::LPar, "expected '(' in 'deref' global variable decl")?;
|
||||
let base = self.match_gv("expected global variable: gv«n»")?;
|
||||
self.match_token(Token::RPar, "expected ')' in 'deref' global variable decl")?;
|
||||
self.match_token(
|
||||
Token::LPar,
|
||||
"expected '(' in 'deref' global valueiable decl",
|
||||
)?;
|
||||
let base = self.match_gv("expected global valueiable: gv«n»")?;
|
||||
self.match_token(
|
||||
Token::RPar,
|
||||
"expected ')' in 'deref' global valueiable decl",
|
||||
)?;
|
||||
let offset = self.optional_offset32()?;
|
||||
GlobalVarData::Deref { base, offset }
|
||||
GlobalValueData::Deref { base, offset }
|
||||
}
|
||||
"globalsym" => {
|
||||
let colocated = self.optional(Token::Identifier("colocated"));
|
||||
let name = self.parse_external_name()?;
|
||||
GlobalVarData::Sym { name, colocated }
|
||||
GlobalValueData::Sym { name, colocated }
|
||||
}
|
||||
other => return err!(self.loc, "Unknown global variable kind '{}'", other),
|
||||
other => return err!(self.loc, "Unknown global valueiable kind '{}'", other),
|
||||
};
|
||||
|
||||
// Collect any trailing comments.
|
||||
@@ -1117,7 +1131,7 @@ impl<'a> Parser<'a> {
|
||||
// heap-desc ::= heap-style heap-base { "," heap-attr }
|
||||
// heap-style ::= "static" | "dynamic"
|
||||
// heap-base ::= "reserved_reg"
|
||||
// | GlobalVar(base)
|
||||
// | GlobalValue(base)
|
||||
// heap-attr ::= "min" Imm64(bytes)
|
||||
// | "max" Imm64(bytes)
|
||||
// | "guard" Imm64(bytes)
|
||||
@@ -1130,15 +1144,15 @@ impl<'a> Parser<'a> {
|
||||
|
||||
// heap-desc ::= heap-style * heap-base { "," heap-attr }
|
||||
// heap-base ::= * "reserved_reg"
|
||||
// | * GlobalVar(base)
|
||||
// | * GlobalValue(base)
|
||||
let base = match self.token() {
|
||||
Some(Token::Identifier("reserved_reg")) => HeapBase::ReservedReg,
|
||||
Some(Token::GlobalVar(base_num)) => {
|
||||
let base_gv = match GlobalVar::with_number(base_num) {
|
||||
Some(Token::GlobalValue(base_num)) => {
|
||||
let base_gv = match GlobalValue::with_number(base_num) {
|
||||
Some(gv) => gv,
|
||||
None => return err!(self.loc, "invalid global variable number for heap base"),
|
||||
None => return err!(self.loc, "invalid global valueiable number for heap base"),
|
||||
};
|
||||
HeapBase::GlobalVar(base_gv)
|
||||
HeapBase::GlobalValue(base_gv)
|
||||
}
|
||||
_ => return err!(self.loc, "expected heap base"),
|
||||
};
|
||||
@@ -1309,11 +1323,11 @@ impl<'a> Parser<'a> {
|
||||
}
|
||||
}
|
||||
|
||||
/// stack-limit-decl ::= "stack_limit" "=" GlobalVar(gv)
|
||||
fn parse_stack_limit_decl(&mut self) -> ParseResult<GlobalVar> {
|
||||
/// stack-limit-decl ::= "stack_limit" "=" GlobalValue(gv)
|
||||
fn parse_stack_limit_decl(&mut self) -> ParseResult<GlobalValue> {
|
||||
self.consume();
|
||||
self.match_token(Token::Equal, "expected '=' in stack limit declaration")?;
|
||||
let gv = self.match_gv("expected global variable")?;
|
||||
let gv = self.match_gv("expected global valueiable")?;
|
||||
|
||||
Ok(gv)
|
||||
}
|
||||
@@ -1889,12 +1903,12 @@ impl<'a> Parser<'a> {
|
||||
opcode,
|
||||
imm: self.match_bool("expected immediate boolean operand")?,
|
||||
},
|
||||
InstructionFormat::UnaryGlobalVar => {
|
||||
let gv = self.match_gv("expected global variable")?;
|
||||
InstructionFormat::UnaryGlobalValue => {
|
||||
let gv = self.match_gv("expected global valueiable")?;
|
||||
ctx.check_gv(gv, &self.loc)?;
|
||||
InstructionData::UnaryGlobalVar {
|
||||
InstructionData::UnaryGlobalValue {
|
||||
opcode,
|
||||
global_var: gv,
|
||||
global_value: gv,
|
||||
}
|
||||
}
|
||||
InstructionFormat::Binary => {
|
||||
|
||||
@@ -7,7 +7,7 @@
|
||||
//! to parser clients.
|
||||
|
||||
use cretonne_codegen::ir::entities::AnyEntity;
|
||||
use cretonne_codegen::ir::{Ebb, FuncRef, GlobalVar, Heap, JumpTable, SigRef, StackSlot, Value};
|
||||
use cretonne_codegen::ir::{Ebb, FuncRef, GlobalValue, Heap, JumpTable, SigRef, StackSlot, Value};
|
||||
use error::{Location, ParseResult};
|
||||
use lexer::split_entity_name;
|
||||
use std::collections::HashMap;
|
||||
@@ -36,8 +36,8 @@ impl SourceMap {
|
||||
self.locations.contains_key(&ss.into())
|
||||
}
|
||||
|
||||
/// Look up a global variable entity.
|
||||
pub fn contains_gv(&self, gv: GlobalVar) -> bool {
|
||||
/// Look up a global valueiable entity.
|
||||
pub fn contains_gv(&self, gv: GlobalValue) -> bool {
|
||||
self.locations.contains_key(&gv.into())
|
||||
}
|
||||
|
||||
@@ -86,7 +86,7 @@ impl SourceMap {
|
||||
Some(ss.into())
|
||||
}
|
||||
}),
|
||||
"gv" => GlobalVar::with_number(num).and_then(|gv| {
|
||||
"gv" => GlobalValue::with_number(num).and_then(|gv| {
|
||||
if !self.contains_gv(gv) {
|
||||
None
|
||||
} else {
|
||||
@@ -154,8 +154,8 @@ impl SourceMap {
|
||||
self.def_entity(entity.into(), loc)
|
||||
}
|
||||
|
||||
/// Define the global variable `entity`.
|
||||
pub fn def_gv(&mut self, entity: GlobalVar, loc: &Location) -> ParseResult<()> {
|
||||
/// Define the global valueiable `entity`.
|
||||
pub fn def_gv(&mut self, entity: GlobalValue, loc: &Location) -> ParseResult<()> {
|
||||
self.def_entity(entity.into(), loc)
|
||||
}
|
||||
|
||||
|
||||
@@ -217,7 +217,7 @@ impl<'simple_jit_backend> Backend for SimpleJITBackend {
|
||||
&mut self,
|
||||
_data: &mut Self::CompiledData,
|
||||
_offset: usize,
|
||||
_what: ir::GlobalVar,
|
||||
_what: ir::GlobalValue,
|
||||
_usize: Addend,
|
||||
) {
|
||||
unimplemented!();
|
||||
|
||||
@@ -24,7 +24,7 @@ pub mod prelude {
|
||||
pub use codegen::ir::condcodes::{FloatCC, IntCC};
|
||||
pub use codegen::ir::immediates::{Ieee32, Ieee64, Imm64};
|
||||
pub use codegen::ir::types;
|
||||
pub use codegen::ir::{AbiParam, Ebb, ExtFuncData, GlobalVarData, InstBuilder, JumpTableData,
|
||||
pub use codegen::ir::{AbiParam, Ebb, ExtFuncData, GlobalValueData, InstBuilder, JumpTableData,
|
||||
MemFlags, Signature, StackSlotData, StackSlotKind, TrapCode, Type, Value};
|
||||
pub use codegen::isa;
|
||||
pub use codegen::settings::{self, CallConv, Configurable};
|
||||
|
||||
@@ -74,7 +74,7 @@ pub fn translate_operator<FE: FuncEnvironment + ?Sized>(
|
||||
let val = match state.get_global(builder.func, global_index, environ) {
|
||||
GlobalValue::Const(val) => val,
|
||||
GlobalValue::Memory { gv, ty } => {
|
||||
let addr = builder.ins().global_addr(environ.native_pointer(), gv);
|
||||
let addr = builder.ins().global_value(environ.native_pointer(), gv);
|
||||
let mut flags = ir::MemFlags::new();
|
||||
flags.set_notrap();
|
||||
flags.set_aligned();
|
||||
@@ -87,7 +87,7 @@ pub fn translate_operator<FE: FuncEnvironment + ?Sized>(
|
||||
match state.get_global(builder.func, global_index, environ) {
|
||||
GlobalValue::Const(_) => panic!("global #{} is a constant", global_index),
|
||||
GlobalValue::Memory { gv, .. } => {
|
||||
let addr = builder.ins().global_addr(environ.native_pointer(), gv);
|
||||
let addr = builder.ins().global_value(environ.native_pointer(), gv);
|
||||
let mut flags = ir::MemFlags::new();
|
||||
flags.set_notrap();
|
||||
flags.set_aligned();
|
||||
|
||||
@@ -159,7 +159,7 @@ impl<'dummy_environment> FuncEnvironment for DummyFuncEnvironment<'dummy_environ
|
||||
fn make_global(&mut self, func: &mut ir::Function, index: GlobalIndex) -> GlobalValue {
|
||||
// Just create a dummy `vmctx` global.
|
||||
let offset = ((index * 8) as i32 + 8).into();
|
||||
let gv = func.create_global_var(ir::GlobalVarData::VMContext { offset });
|
||||
let gv = func.create_global_value(ir::GlobalValueData::VMContext { offset });
|
||||
GlobalValue::Memory {
|
||||
gv,
|
||||
ty: self.mod_info.globals[index].entity.ty,
|
||||
@@ -168,10 +168,10 @@ impl<'dummy_environment> FuncEnvironment for DummyFuncEnvironment<'dummy_environ
|
||||
|
||||
fn make_heap(&mut self, func: &mut ir::Function, _index: MemoryIndex) -> ir::Heap {
|
||||
// Create a static heap whose base address is stored at `vmctx+0`.
|
||||
let gv = func.create_global_var(ir::GlobalVarData::VMContext { offset: 0.into() });
|
||||
let gv = func.create_global_value(ir::GlobalValueData::VMContext { offset: 0.into() });
|
||||
|
||||
func.create_heap(ir::HeapData {
|
||||
base: ir::HeapBase::GlobalVar(gv),
|
||||
base: ir::HeapBase::GlobalValue(gv),
|
||||
min_size: 0.into(),
|
||||
guard_size: 0x8000_0000.into(),
|
||||
style: ir::HeapStyle::Static {
|
||||
|
||||
@@ -9,17 +9,17 @@ use translation_utils::{FunctionIndex, Global, GlobalIndex, Memory, MemoryIndex,
|
||||
Table, TableIndex};
|
||||
use wasmparser::BinaryReaderError;
|
||||
|
||||
/// The value of a WebAssembly global variable.
|
||||
/// The value of a WebAssembly global valueiable.
|
||||
#[derive(Clone, Copy)]
|
||||
pub enum GlobalValue {
|
||||
/// This is a constant global with a value known at compile time.
|
||||
Const(ir::Value),
|
||||
|
||||
/// This is a variable in memory that should be referenced as a `GlobalVar`.
|
||||
/// This is a variable in memory that should be referenced as a `GlobalValue`.
|
||||
Memory {
|
||||
/// Which global variable should be referenced.
|
||||
gv: ir::GlobalVar,
|
||||
/// The global variable's type.
|
||||
/// Which global valueiable should be referenced.
|
||||
gv: ir::GlobalValue,
|
||||
/// The global valueiable's type.
|
||||
ty: ir::Type,
|
||||
},
|
||||
}
|
||||
@@ -88,12 +88,12 @@ pub trait FuncEnvironment {
|
||||
ir::Type::int(u16::from(self.triple().pointer_width().unwrap().bits())).unwrap()
|
||||
}
|
||||
|
||||
/// Set up the necessary preamble definitions in `func` to access the global variable
|
||||
/// Set up the necessary preamble definitions in `func` to access the global valueiable
|
||||
/// identified by `index`.
|
||||
///
|
||||
/// The index space covers both imported globals and globals defined by the module.
|
||||
///
|
||||
/// Return the global variable reference that should be used to access the global and the
|
||||
/// Return the global valueiable reference that should be used to access the global and the
|
||||
/// WebAssembly type of the global.
|
||||
fn make_global(&mut self, func: &mut ir::Function, index: GlobalIndex) -> GlobalValue;
|
||||
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
//! The code of theses helper function is straightforward since it is only about reading metadata
|
||||
//! about linear memories, tables, globals, etc. and storing them for later use.
|
||||
//!
|
||||
//! The special case of the initialize expressions for table elements offsets or global variables
|
||||
//! The special case of the initialize expressions for table elements offsets or global valueiables
|
||||
//! is handled, according to the semantics of WebAssembly, to only specific expressions that are
|
||||
//! interpreted on the fly.
|
||||
use cretonne_codegen::ir::{self, AbiParam, Signature};
|
||||
|
||||
@@ -134,7 +134,7 @@ pub struct TranslationState {
|
||||
pub control_stack: Vec<ControlStackFrame>,
|
||||
pub reachable: bool,
|
||||
|
||||
// Map of global variables that have already been created by `FuncEnvironment::make_global`.
|
||||
// Map of global valueiables that have already been created by `FuncEnvironment::make_global`.
|
||||
globals: HashMap<GlobalIndex, GlobalValue>,
|
||||
|
||||
// Map of heaps that have been created by `FuncEnvironment::make_heap`.
|
||||
@@ -272,7 +272,7 @@ impl TranslationState {
|
||||
|
||||
/// Methods for handling entity references.
|
||||
impl TranslationState {
|
||||
/// Get the `GlobalVar` reference that should be used to access the global variable `index`.
|
||||
/// Get the `GlobalValue` reference that should be used to access the global valueiable `index`.
|
||||
/// Create the reference if necessary.
|
||||
/// Also return the WebAssembly type of the global.
|
||||
pub fn get_global<FE: FuncEnvironment + ?Sized>(
|
||||
|
||||
@@ -7,7 +7,7 @@ use wasmparser;
|
||||
pub type FunctionIndex = usize;
|
||||
/// Index of a table (imported or defined) inside the WebAssembly module.
|
||||
pub type TableIndex = usize;
|
||||
/// Index of a global variable (imported or defined) inside the WebAssembly module.
|
||||
/// Index of a global valueiable (imported or defined) inside the WebAssembly module.
|
||||
pub type GlobalIndex = usize;
|
||||
/// Index of a linear memory (imported or defined) inside the WebAssembly module.
|
||||
pub type MemoryIndex = usize;
|
||||
|
||||
Reference in New Issue
Block a user