Fix legalization of heap_addrs with 32-bit indices. (#480)
This makes several changes: - It adds an index_type to heap declarations, allowing heaps to specify the type for indexing. This also anticipates 64-bit heap support. - It adds a memory_type to deref global values, allowing deref globals to have types other than pointers. This is used to allow the bound variable in dynamic heaps to have type i32, to match the index type in heaps with i32 index type. - And, it fixes heap legalization to do the bounds check in the heap's index type.
This commit is contained in:
@@ -13,7 +13,7 @@ pub fn expand_global_value(
|
||||
inst: ir::Inst,
|
||||
func: &mut ir::Function,
|
||||
_cfg: &mut ControlFlowGraph,
|
||||
_isa: &TargetIsa,
|
||||
isa: &TargetIsa,
|
||||
) {
|
||||
// Unpack the instruction.
|
||||
let gv = match func.dfg[inst] {
|
||||
@@ -29,8 +29,12 @@ pub fn expand_global_value(
|
||||
|
||||
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),
|
||||
ir::GlobalValueData::Deref {
|
||||
base,
|
||||
offset,
|
||||
memory_type,
|
||||
} => deref_addr(inst, func, base, offset.into(), memory_type, isa),
|
||||
ir::GlobalValueData::Sym { .. } => globalsym(inst, func, gv, isa),
|
||||
}
|
||||
}
|
||||
|
||||
@@ -46,11 +50,18 @@ fn vmctx_addr(inst: ir::Inst, func: &mut ir::Function, offset: i64) {
|
||||
}
|
||||
|
||||
/// Expand a `global_value` instruction for a deref global.
|
||||
fn deref_addr(inst: ir::Inst, func: &mut ir::Function, base: ir::GlobalValue, offset: i64) {
|
||||
fn deref_addr(
|
||||
inst: ir::Inst,
|
||||
func: &mut ir::Function,
|
||||
base: ir::GlobalValue,
|
||||
offset: i64,
|
||||
memory_type: ir::Type,
|
||||
isa: &TargetIsa,
|
||||
) {
|
||||
// We need to load a pointer from the `base` global value, 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 ptr_ty = isa.pointer_type();
|
||||
let mut pos = FuncCursor::new(func).at_inst(inst);
|
||||
pos.use_srcloc(inst);
|
||||
|
||||
@@ -59,12 +70,12 @@ fn deref_addr(inst: ir::Inst, func: &mut ir::Function, base: ir::GlobalValue, of
|
||||
// Deref globals are required to be accessible and aligned.
|
||||
mflags.set_notrap();
|
||||
mflags.set_aligned();
|
||||
let base_ptr = pos.ins().load(ptr_ty, mflags, base_addr, 0);
|
||||
pos.func.dfg.replace(inst).iadd_imm(base_ptr, offset);
|
||||
let loaded = pos.ins().load(memory_type, mflags, base_addr, 0);
|
||||
pos.func.dfg.replace(inst).iadd_imm(loaded, offset);
|
||||
}
|
||||
|
||||
/// 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));
|
||||
fn globalsym(inst: ir::Inst, func: &mut ir::Function, gv: ir::GlobalValue, isa: &TargetIsa) {
|
||||
let ptr_ty = isa.pointer_type();
|
||||
func.dfg.replace(inst).globalsym_addr(ptr_ty, gv);
|
||||
}
|
||||
|
||||
@@ -57,7 +57,7 @@ fn dynamic_addr(
|
||||
pos.use_srcloc(inst);
|
||||
|
||||
// Start with the bounds check. Trap if `offset + access_size > bound`.
|
||||
let bound = pos.ins().global_value(addr_ty, bound_gv);
|
||||
let bound = pos.ins().global_value(offset_ty, bound_gv);
|
||||
let oob;
|
||||
if access_size == 1 {
|
||||
// `offset > bound - 1` is the same as `offset >= bound`.
|
||||
|
||||
Reference in New Issue
Block a user