Change GlobalVar to GlobalValue

This commit is contained in:
Lachlan Sneff
2018-06-14 01:07:27 -04:00
committed by Dan Gohman
parent 49cc693d64
commit 5c320a0d30
44 changed files with 324 additions and 237 deletions

View File

@@ -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)
}
}

View File

@@ -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.

View File

@@ -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.

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

View File

@@ -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,
} => {

View File

@@ -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)?;

View File

@@ -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;

View File

@@ -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);
}

View File

@@ -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();

View File

@@ -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;

View File

@@ -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"),
}
}

View File

@@ -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 {

View File

@@ -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) {

View File

@@ -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]),