Add an index_type field to Table.

This parallels the `index_type` field in `Heap`.
This commit is contained in:
Dan Gohman
2018-08-28 13:57:34 -07:00
parent 0d24641f21
commit 8e2d01a675
9 changed files with 192 additions and 5 deletions

View File

@@ -1,7 +1,7 @@
//! Tables.
use ir::immediates::Imm64;
use ir::GlobalValue;
use ir::{GlobalValue, Type};
use std::fmt;
/// Information about a table declaration.
@@ -19,14 +19,18 @@ pub struct TableData {
/// The size of a table element, in bytes.
pub element_size: Imm64,
/// The index type for the table.
pub index_type: Type,
}
impl fmt::Display for TableData {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
f.write_str("dynamic")?;
write!(
f,
"{}, min {}, bound {}, element_size {}",
self.base_gv, self.min_size, self.bound_gv, self.element_size
" {}, min {}, bound {}, element_size {}, index_type {}",
self.base_gv, self.min_size, self.bound_gv, self.element_size, self.index_type
)
}
}

View File

@@ -49,7 +49,7 @@ fn dynamic_addr(
pos.use_srcloc(inst);
// Start with the bounds check. Trap if `index + 1 > bound`.
let bound = pos.ins().global_value(addr_ty, bound_gv);
let bound = pos.ins().global_value(index_ty, bound_gv);
// `index > bound - 1` is the same as `index >= bound`.
let oob = pos

View File

@@ -433,6 +433,48 @@ impl<'a> Verifier<'a> {
Ok(())
}
fn verify_tables(&self, errors: &mut VerifierErrors) -> VerifierStepResult<()> {
if let Some(isa) = self.isa {
for (table, table_data) in &self.func.tables {
let base = table_data.base_gv;
if !self.func.global_values.is_valid(base) {
return nonfatal!(errors, table, "invalid base global value {}", base);
}
let pointer_type = isa.pointer_type();
let base_type = self.func.global_values[base].global_type(isa);
if base_type != pointer_type {
report!(
errors,
table,
"table base has type {}, which is not the pointer type {}",
base_type,
pointer_type
);
}
let bound_gv = table_data.bound_gv;
if !self.func.global_values.is_valid(bound_gv) {
return nonfatal!(errors, table, "invalid bound global value {}", bound_gv);
}
let index_type = table_data.index_type;
let bound_type = self.func.global_values[bound_gv].global_type(isa);
if index_type != bound_type {
report!(
errors,
table,
"table index type {} differs from the type of its bound, {}",
index_type,
bound_type
);
}
}
}
Ok(())
}
fn ebb_integrity(
&self,
ebb: Ebb,
@@ -1385,6 +1427,19 @@ impl<'a> Verifier<'a> {
);
}
}
ir::InstructionData::TableAddr { table, arg, .. } => {
let index_type = self.func.dfg.value_type(arg);
let table_index_type = self.func.tables[table].index_type;
if index_type != table_index_type {
return nonfatal!(
errors,
inst,
"index type {} differs from table index type {}",
index_type,
table_index_type
);
}
}
ir::InstructionData::UnaryGlobalValue { global_value, .. } => {
if let Some(isa) = self.isa {
let inst_type = self.func.dfg.value_type(self.func.dfg.first_result(inst));
@@ -1611,6 +1666,7 @@ impl<'a> Verifier<'a> {
pub fn run(&self, errors: &mut VerifierErrors) -> VerifierStepResult<()> {
self.verify_global_values(errors)?;
self.verify_heaps(errors)?;
self.verify_tables(errors)?;
self.typecheck_entry_block_params(errors)?;
for ebb in self.func.layout.ebbs() {

View File

@@ -46,6 +46,11 @@ pub trait FuncWriter {
self.write_entity_definition(w, func, heap.into(), heap_data)?;
}
for (table, table_data) in &func.tables {
any = true;
self.write_entity_definition(w, func, table.into(), table_data)?;
}
// Write out all signatures before functions since function declarations can refer to
// signatures.
for (sig, sig_data) in &func.dfg.signatures {