Rename verifier's Result and Error.
This provides consistency with similar types in other parts of Cretonne, and avoids shadowing `Result` from the standard prelude.
This commit is contained in:
@@ -28,7 +28,7 @@ use simple_gvn::do_simple_gvn;
|
||||
use std::vec::Vec;
|
||||
use timing;
|
||||
use unreachable_code::eliminate_unreachable_code;
|
||||
use verifier;
|
||||
use verifier::{verify_context, verify_locations, VerifierResult};
|
||||
|
||||
/// Persistent data structures and compilation pipeline.
|
||||
pub struct Context {
|
||||
@@ -174,8 +174,8 @@ impl Context {
|
||||
/// Run the verifier on the function.
|
||||
///
|
||||
/// Also check that the dominator tree and control flow graph are consistent with the function.
|
||||
pub fn verify<'a, FOI: Into<FlagsOrIsa<'a>>>(&self, fisa: FOI) -> verifier::Result {
|
||||
verifier::verify_context(&self.func, &self.cfg, &self.domtree, fisa)
|
||||
pub fn verify<'a, FOI: Into<FlagsOrIsa<'a>>>(&self, fisa: FOI) -> VerifierResult<()> {
|
||||
verify_context(&self.func, &self.cfg, &self.domtree, fisa)
|
||||
}
|
||||
|
||||
/// Run the verifier only if the `enable_verifier` setting is true.
|
||||
@@ -189,8 +189,8 @@ impl Context {
|
||||
}
|
||||
|
||||
/// Run the locations verifier on the function.
|
||||
pub fn verify_locations(&self, isa: &TargetIsa) -> verifier::Result {
|
||||
verifier::verify_locations(isa, &self.func, None)
|
||||
pub fn verify_locations(&self, isa: &TargetIsa) -> VerifierResult<()> {
|
||||
verify_locations(isa, &self.func, None)
|
||||
}
|
||||
|
||||
/// Run the locations verifier only if the `enable_verifier` setting is true.
|
||||
|
||||
@@ -5,13 +5,13 @@ use isa::TargetIsa;
|
||||
use result::CtonError;
|
||||
use std::fmt::Write;
|
||||
use std::string::{String, ToString};
|
||||
use verifier;
|
||||
use verifier::VerifierError;
|
||||
|
||||
/// Pretty-print a verifier error.
|
||||
pub fn pretty_verifier_error(
|
||||
func: &ir::Function,
|
||||
isa: Option<&TargetIsa>,
|
||||
err: &verifier::Error,
|
||||
err: &VerifierError,
|
||||
) -> String {
|
||||
let mut msg = err.to_string();
|
||||
match err.location {
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
//! Result and error types representing the outcome of compiling a function.
|
||||
|
||||
use verifier;
|
||||
use verifier::VerifierError;
|
||||
|
||||
/// A compilation error.
|
||||
///
|
||||
@@ -12,7 +12,7 @@ pub enum CtonError {
|
||||
/// This always represents a bug, either in the code that generated IR for Cretonne, or a bug
|
||||
/// in Cretonne itself.
|
||||
#[fail(display = "Verifier error: {}", _0)]
|
||||
Verifier(#[cause] verifier::Error),
|
||||
Verifier(#[cause] VerifierError),
|
||||
|
||||
/// An implementation limit was exceeded.
|
||||
///
|
||||
@@ -34,8 +34,8 @@ pub enum CtonError {
|
||||
/// A Cretonne compilation result.
|
||||
pub type CtonResult = Result<(), CtonError>;
|
||||
|
||||
impl From<verifier::Error> for CtonError {
|
||||
fn from(e: verifier::Error) -> Self {
|
||||
impl From<VerifierError> for CtonError {
|
||||
fn from(e: VerifierError) -> Self {
|
||||
CtonError::Verifier(e)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -7,7 +7,7 @@ use ir::{ExpandedProgramPoint, Function};
|
||||
use regalloc::liveness::Liveness;
|
||||
use regalloc::virtregs::VirtRegs;
|
||||
use timing;
|
||||
use verifier::Result;
|
||||
use verifier::VerifierResult;
|
||||
|
||||
/// Verify conventional SSA form for `func`.
|
||||
///
|
||||
@@ -29,7 +29,7 @@ pub fn verify_cssa(
|
||||
domtree: &DominatorTree,
|
||||
liveness: &Liveness,
|
||||
virtregs: &VirtRegs,
|
||||
) -> Result {
|
||||
) -> VerifierResult<()> {
|
||||
let _tt = timing::verify_cssa();
|
||||
|
||||
let mut preorder = DominatorTreePreorder::new();
|
||||
@@ -58,7 +58,7 @@ struct CssaVerifier<'a> {
|
||||
}
|
||||
|
||||
impl<'a> CssaVerifier<'a> {
|
||||
fn check_virtregs(&self) -> Result {
|
||||
fn check_virtregs(&self) -> VerifierResult<()> {
|
||||
for vreg in self.virtregs.all_virtregs() {
|
||||
let values = self.virtregs.values(vreg);
|
||||
|
||||
@@ -135,7 +135,7 @@ impl<'a> CssaVerifier<'a> {
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn check_cssa(&self) -> Result {
|
||||
fn check_cssa(&self) -> VerifierResult<()> {
|
||||
for ebb in self.func.layout.ebbs() {
|
||||
let ebb_params = self.func.dfg.ebb_params(ebb);
|
||||
for (_, pred) in self.cfg.pred_iter(ebb) {
|
||||
|
||||
@@ -6,9 +6,8 @@ use ir;
|
||||
use ir::instructions::BranchInfo;
|
||||
use isa;
|
||||
use packed_option::PackedOption;
|
||||
use std::result;
|
||||
use timing;
|
||||
use verifier::{Error, Result};
|
||||
use verifier::VerifierResult;
|
||||
|
||||
/// Verify that CPU flags are used correctly.
|
||||
///
|
||||
@@ -26,7 +25,7 @@ pub fn verify_flags(
|
||||
func: &ir::Function,
|
||||
cfg: &ControlFlowGraph,
|
||||
isa: Option<&isa::TargetIsa>,
|
||||
) -> Result {
|
||||
) -> VerifierResult<()> {
|
||||
let _tt = timing::verify_flags();
|
||||
let mut verifier = FlagsVerifier {
|
||||
func,
|
||||
@@ -47,7 +46,7 @@ struct FlagsVerifier<'a> {
|
||||
}
|
||||
|
||||
impl<'a> FlagsVerifier<'a> {
|
||||
fn check(&mut self) -> Result {
|
||||
fn check(&mut self) -> VerifierResult<()> {
|
||||
// List of EBBs that need to be processed. EBBs may be re-added to this list when we detect
|
||||
// that one of their successor blocks needs a live-in flags value.
|
||||
let mut worklist = SparseSet::new();
|
||||
@@ -81,7 +80,7 @@ impl<'a> FlagsVerifier<'a> {
|
||||
}
|
||||
|
||||
/// Check flags usage in `ebb` and return the live-in flags value, if any.
|
||||
fn visit_ebb(&self, ebb: ir::Ebb) -> result::Result<Option<ir::Value>, Error> {
|
||||
fn visit_ebb(&self, ebb: ir::Ebb) -> VerifierResult<Option<ir::Value>> {
|
||||
// The single currently live flags value.
|
||||
let mut live_val = None;
|
||||
|
||||
@@ -139,7 +138,7 @@ impl<'a> FlagsVerifier<'a> {
|
||||
}
|
||||
|
||||
// Merge live flags values, or return an error on conflicting values.
|
||||
fn merge(a: &mut Option<ir::Value>, b: ir::Value, inst: ir::Inst) -> Result {
|
||||
fn merge(a: &mut Option<ir::Value>, b: ir::Value, inst: ir::Inst) -> VerifierResult<()> {
|
||||
if let Some(va) = *a {
|
||||
if b != va {
|
||||
return err!(inst, "conflicting live CPU flags: {} and {}", va, b);
|
||||
|
||||
@@ -8,7 +8,7 @@ use regalloc::liveness::Liveness;
|
||||
use regalloc::liverange::LiveRange;
|
||||
use std::cmp::Ordering;
|
||||
use timing;
|
||||
use verifier::Result;
|
||||
use verifier::VerifierResult;
|
||||
|
||||
/// Verify liveness information for `func`.
|
||||
///
|
||||
@@ -27,7 +27,7 @@ pub fn verify_liveness(
|
||||
func: &Function,
|
||||
cfg: &ControlFlowGraph,
|
||||
liveness: &Liveness,
|
||||
) -> Result {
|
||||
) -> VerifierResult<()> {
|
||||
let _tt = timing::verify_liveness();
|
||||
let verifier = LivenessVerifier {
|
||||
isa,
|
||||
@@ -49,7 +49,7 @@ struct LivenessVerifier<'a> {
|
||||
|
||||
impl<'a> LivenessVerifier<'a> {
|
||||
/// Check all EBB arguments.
|
||||
fn check_ebbs(&self) -> Result {
|
||||
fn check_ebbs(&self) -> VerifierResult<()> {
|
||||
for ebb in self.func.layout.ebbs() {
|
||||
for &val in self.func.dfg.ebb_params(ebb) {
|
||||
let lr = match self.liveness.get(val) {
|
||||
@@ -63,7 +63,7 @@ impl<'a> LivenessVerifier<'a> {
|
||||
}
|
||||
|
||||
/// Check all instructions.
|
||||
fn check_insts(&self) -> Result {
|
||||
fn check_insts(&self) -> VerifierResult<()> {
|
||||
for ebb in self.func.layout.ebbs() {
|
||||
for inst in self.func.layout.ebb_insts(ebb) {
|
||||
let encoding = self.func.encodings[inst];
|
||||
@@ -141,7 +141,7 @@ impl<'a> LivenessVerifier<'a> {
|
||||
}
|
||||
|
||||
/// Check the integrity of the live range `lr`.
|
||||
fn check_lr(&self, def: ProgramPoint, val: Value, lr: &LiveRange) -> Result {
|
||||
fn check_lr(&self, def: ProgramPoint, val: Value, lr: &LiveRange) -> VerifierResult<()> {
|
||||
let l = &self.func.layout;
|
||||
|
||||
let loc: AnyEntity = match def.into() {
|
||||
|
||||
@@ -5,7 +5,7 @@ use isa;
|
||||
use regalloc::liveness::Liveness;
|
||||
use regalloc::RegDiversions;
|
||||
use timing;
|
||||
use verifier::Result;
|
||||
use verifier::VerifierResult;
|
||||
|
||||
/// Verify value locations for `func`.
|
||||
///
|
||||
@@ -22,7 +22,7 @@ pub fn verify_locations(
|
||||
isa: &isa::TargetIsa,
|
||||
func: &ir::Function,
|
||||
liveness: Option<&Liveness>,
|
||||
) -> Result {
|
||||
) -> VerifierResult<()> {
|
||||
let _tt = timing::verify_locations();
|
||||
let verifier = LocationVerifier {
|
||||
isa,
|
||||
@@ -45,7 +45,7 @@ struct LocationVerifier<'a> {
|
||||
|
||||
impl<'a> LocationVerifier<'a> {
|
||||
/// Check that the assigned value locations match the operand constraints of their uses.
|
||||
fn check_constraints(&self) -> Result {
|
||||
fn check_constraints(&self) -> VerifierResult<()> {
|
||||
let dfg = &self.func.dfg;
|
||||
let mut divert = RegDiversions::new();
|
||||
|
||||
@@ -88,7 +88,7 @@ impl<'a> LocationVerifier<'a> {
|
||||
inst: ir::Inst,
|
||||
enc: isa::Encoding,
|
||||
divert: &RegDiversions,
|
||||
) -> Result {
|
||||
) -> VerifierResult<()> {
|
||||
let constraints = self.encinfo
|
||||
.operand_constraints(enc)
|
||||
.expect("check_enc_constraints requires a legal encoding");
|
||||
@@ -107,7 +107,7 @@ impl<'a> LocationVerifier<'a> {
|
||||
|
||||
/// Check that the result values produced by a ghost instruction are not assigned a value
|
||||
/// location.
|
||||
fn check_ghost_results(&self, inst: ir::Inst) -> Result {
|
||||
fn check_ghost_results(&self, inst: ir::Inst) -> VerifierResult<()> {
|
||||
let results = self.func.dfg.inst_results(inst);
|
||||
|
||||
for &res in results {
|
||||
@@ -126,7 +126,12 @@ impl<'a> LocationVerifier<'a> {
|
||||
}
|
||||
|
||||
/// Check the ABI argument and result locations for a call.
|
||||
fn check_call_abi(&self, inst: ir::Inst, sig: ir::SigRef, divert: &RegDiversions) -> Result {
|
||||
fn check_call_abi(
|
||||
&self,
|
||||
inst: ir::Inst,
|
||||
sig: ir::SigRef,
|
||||
divert: &RegDiversions,
|
||||
) -> VerifierResult<()> {
|
||||
let sig = &self.func.dfg.signatures[sig];
|
||||
let varargs = self.func.dfg.inst_variable_args(inst);
|
||||
let results = self.func.dfg.inst_results(inst);
|
||||
@@ -155,7 +160,7 @@ impl<'a> LocationVerifier<'a> {
|
||||
}
|
||||
|
||||
/// Check the ABI argument locations for a return.
|
||||
fn check_return_abi(&self, inst: ir::Inst, divert: &RegDiversions) -> Result {
|
||||
fn check_return_abi(&self, inst: ir::Inst, divert: &RegDiversions) -> VerifierResult<()> {
|
||||
let sig = &self.func.signature;
|
||||
let varargs = self.func.dfg.inst_variable_args(inst);
|
||||
|
||||
@@ -180,7 +185,7 @@ impl<'a> LocationVerifier<'a> {
|
||||
abi: &ir::AbiParam,
|
||||
loc: ir::ValueLoc,
|
||||
want_kind: ir::StackSlotKind,
|
||||
) -> Result {
|
||||
) -> VerifierResult<()> {
|
||||
match abi.location {
|
||||
ir::ArgumentLoc::Unassigned => {}
|
||||
ir::ArgumentLoc::Reg(reg) => {
|
||||
@@ -233,7 +238,7 @@ impl<'a> LocationVerifier<'a> {
|
||||
}
|
||||
|
||||
/// Update diversions to reflect the current instruction and check their consistency.
|
||||
fn update_diversions(&self, inst: ir::Inst, divert: &mut RegDiversions) -> Result {
|
||||
fn update_diversions(&self, inst: ir::Inst, divert: &mut RegDiversions) -> VerifierResult<()> {
|
||||
let (arg, src) = match self.func.dfg[inst] {
|
||||
ir::InstructionData::RegMove { arg, src, .. }
|
||||
| ir::InstructionData::RegSpill { arg, src, .. } => (arg, ir::ValueLoc::Reg(src)),
|
||||
@@ -264,7 +269,7 @@ impl<'a> LocationVerifier<'a> {
|
||||
|
||||
/// We have active diversions before a branch. Make sure none of the diverted values are live
|
||||
/// on the outgoing CFG edges.
|
||||
fn check_cfg_edges(&self, inst: ir::Inst, divert: &RegDiversions) -> Result {
|
||||
fn check_cfg_edges(&self, inst: ir::Inst, divert: &RegDiversions) -> VerifierResult<()> {
|
||||
use ir::instructions::BranchInfo::*;
|
||||
|
||||
// We can only check CFG edges if we have a liveness analysis.
|
||||
|
||||
@@ -71,7 +71,6 @@ use settings::{Flags, FlagsOrIsa};
|
||||
use std::cmp::Ordering;
|
||||
use std::collections::BTreeSet;
|
||||
use std::fmt::{self, Display, Formatter, Write};
|
||||
use std::result;
|
||||
use std::string::String;
|
||||
use std::vec::Vec;
|
||||
use timing;
|
||||
@@ -80,17 +79,17 @@ pub use self::cssa::verify_cssa;
|
||||
pub use self::liveness::verify_liveness;
|
||||
pub use self::locations::verify_locations;
|
||||
|
||||
// Create an `Err` variant of `Result<X>` from a location and `format!` arguments.
|
||||
// Create an `Err` variant of `VerifierResult<X>` from a location and `format!` arguments.
|
||||
macro_rules! err {
|
||||
( $loc:expr, $msg:expr ) => {
|
||||
Err(::verifier::Error {
|
||||
Err(::verifier::VerifierError {
|
||||
location: $loc.into(),
|
||||
message: String::from($msg),
|
||||
})
|
||||
};
|
||||
|
||||
( $loc:expr, $fmt:expr, $( $arg:expr ),+ ) => {
|
||||
Err(::verifier::Error {
|
||||
Err(::verifier::VerifierError {
|
||||
location: $loc.into(),
|
||||
message: format!( $fmt, $( $arg ),+ ),
|
||||
})
|
||||
@@ -104,24 +103,27 @@ mod locations;
|
||||
|
||||
/// A verifier error.
|
||||
#[derive(Fail, Debug, PartialEq, Eq)]
|
||||
pub struct Error {
|
||||
pub struct VerifierError {
|
||||
/// The entity causing the verifier error.
|
||||
pub location: AnyEntity,
|
||||
/// Error message.
|
||||
pub message: String,
|
||||
}
|
||||
|
||||
impl Display for Error {
|
||||
impl Display for VerifierError {
|
||||
fn fmt(&self, f: &mut Formatter) -> fmt::Result {
|
||||
write!(f, "{}: {}", self.location, self.message)
|
||||
}
|
||||
}
|
||||
|
||||
/// Verifier result.
|
||||
pub type Result = result::Result<(), Error>;
|
||||
pub type VerifierResult<T> = Result<T, VerifierError>;
|
||||
|
||||
/// Verify `func`.
|
||||
pub fn verify_function<'a, FOI: Into<FlagsOrIsa<'a>>>(func: &Function, fisa: FOI) -> Result {
|
||||
pub fn verify_function<'a, FOI: Into<FlagsOrIsa<'a>>>(
|
||||
func: &Function,
|
||||
fisa: FOI,
|
||||
) -> VerifierResult<()> {
|
||||
let _tt = timing::verifier();
|
||||
Verifier::new(func, fisa.into()).run()
|
||||
}
|
||||
@@ -133,7 +135,7 @@ pub fn verify_context<'a, FOI: Into<FlagsOrIsa<'a>>>(
|
||||
cfg: &ControlFlowGraph,
|
||||
domtree: &DominatorTree,
|
||||
fisa: FOI,
|
||||
) -> Result {
|
||||
) -> VerifierResult<()> {
|
||||
let _tt = timing::verifier();
|
||||
let verifier = Verifier::new(func, fisa.into());
|
||||
if cfg.is_valid() {
|
||||
@@ -167,7 +169,7 @@ impl<'a> Verifier<'a> {
|
||||
}
|
||||
|
||||
// Check for cycles in the global variable declarations.
|
||||
fn verify_global_vars(&self) -> Result {
|
||||
fn verify_global_vars(&self) -> VerifierResult<()> {
|
||||
let mut seen = SparseSet::new();
|
||||
|
||||
for gv in self.func.global_vars.keys() {
|
||||
@@ -187,7 +189,7 @@ impl<'a> Verifier<'a> {
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn ebb_integrity(&self, ebb: Ebb, inst: Inst) -> Result {
|
||||
fn ebb_integrity(&self, ebb: Ebb, inst: Inst) -> VerifierResult<()> {
|
||||
let is_terminator = self.func.dfg[inst].opcode().is_terminator();
|
||||
let is_last_inst = self.func.layout.last_inst(ebb) == Some(inst);
|
||||
|
||||
@@ -226,7 +228,7 @@ impl<'a> Verifier<'a> {
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn instruction_integrity(&self, inst: Inst) -> Result {
|
||||
fn instruction_integrity(&self, inst: Inst) -> VerifierResult<()> {
|
||||
let inst_data = &self.func.dfg[inst];
|
||||
let dfg = &self.func.dfg;
|
||||
|
||||
@@ -255,7 +257,7 @@ impl<'a> Verifier<'a> {
|
||||
self.verify_entity_references(inst)
|
||||
}
|
||||
|
||||
fn verify_entity_references(&self, inst: Inst) -> Result {
|
||||
fn verify_entity_references(&self, inst: Inst) -> VerifierResult<()> {
|
||||
use ir::instructions::InstructionData::*;
|
||||
|
||||
for &arg in self.func.dfg.inst_args(inst) {
|
||||
@@ -375,7 +377,7 @@ impl<'a> Verifier<'a> {
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn verify_ebb(&self, inst: Inst, e: Ebb) -> Result {
|
||||
fn verify_ebb(&self, inst: Inst, e: Ebb) -> VerifierResult<()> {
|
||||
if !self.func.dfg.ebb_is_valid(e) || !self.func.layout.is_ebb_inserted(e) {
|
||||
return err!(inst, "invalid ebb reference {}", e);
|
||||
}
|
||||
@@ -387,7 +389,7 @@ impl<'a> Verifier<'a> {
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn verify_sig_ref(&self, inst: Inst, s: SigRef) -> Result {
|
||||
fn verify_sig_ref(&self, inst: Inst, s: SigRef) -> VerifierResult<()> {
|
||||
if !self.func.dfg.signatures.is_valid(s) {
|
||||
err!(inst, "invalid signature reference {}", s)
|
||||
} else {
|
||||
@@ -395,7 +397,7 @@ impl<'a> Verifier<'a> {
|
||||
}
|
||||
}
|
||||
|
||||
fn verify_func_ref(&self, inst: Inst, f: FuncRef) -> Result {
|
||||
fn verify_func_ref(&self, inst: Inst, f: FuncRef) -> VerifierResult<()> {
|
||||
if !self.func.dfg.ext_funcs.is_valid(f) {
|
||||
err!(inst, "invalid function reference {}", f)
|
||||
} else {
|
||||
@@ -403,7 +405,7 @@ impl<'a> Verifier<'a> {
|
||||
}
|
||||
}
|
||||
|
||||
fn verify_stack_slot(&self, inst: Inst, ss: StackSlot) -> Result {
|
||||
fn verify_stack_slot(&self, inst: Inst, ss: StackSlot) -> VerifierResult<()> {
|
||||
if !self.func.stack_slots.is_valid(ss) {
|
||||
err!(inst, "invalid stack slot {}", ss)
|
||||
} else {
|
||||
@@ -411,7 +413,7 @@ impl<'a> Verifier<'a> {
|
||||
}
|
||||
}
|
||||
|
||||
fn verify_global_var(&self, inst: Inst, gv: GlobalVar) -> Result {
|
||||
fn verify_global_var(&self, inst: Inst, gv: GlobalVar) -> VerifierResult<()> {
|
||||
if !self.func.global_vars.is_valid(gv) {
|
||||
err!(inst, "invalid global variable {}", gv)
|
||||
} else {
|
||||
@@ -419,7 +421,7 @@ impl<'a> Verifier<'a> {
|
||||
}
|
||||
}
|
||||
|
||||
fn verify_heap(&self, inst: Inst, heap: ir::Heap) -> Result {
|
||||
fn verify_heap(&self, inst: Inst, heap: ir::Heap) -> VerifierResult<()> {
|
||||
if !self.func.heaps.is_valid(heap) {
|
||||
err!(inst, "invalid heap {}", heap)
|
||||
} else {
|
||||
@@ -427,7 +429,7 @@ impl<'a> Verifier<'a> {
|
||||
}
|
||||
}
|
||||
|
||||
fn verify_value_list(&self, inst: Inst, l: &ValueList) -> Result {
|
||||
fn verify_value_list(&self, inst: Inst, l: &ValueList) -> VerifierResult<()> {
|
||||
if !l.is_valid(&self.func.dfg.value_lists) {
|
||||
err!(inst, "invalid value list reference {:?}", l)
|
||||
} else {
|
||||
@@ -435,7 +437,7 @@ impl<'a> Verifier<'a> {
|
||||
}
|
||||
}
|
||||
|
||||
fn verify_jump_table(&self, inst: Inst, j: JumpTable) -> Result {
|
||||
fn verify_jump_table(&self, inst: Inst, j: JumpTable) -> VerifierResult<()> {
|
||||
if !self.func.jump_tables.is_valid(j) {
|
||||
err!(inst, "invalid jump table reference {}", j)
|
||||
} else {
|
||||
@@ -443,7 +445,7 @@ impl<'a> Verifier<'a> {
|
||||
}
|
||||
}
|
||||
|
||||
fn verify_value(&self, loc_inst: Inst, v: Value) -> Result {
|
||||
fn verify_value(&self, loc_inst: Inst, v: Value) -> VerifierResult<()> {
|
||||
let dfg = &self.func.dfg;
|
||||
if !dfg.value_is_valid(v) {
|
||||
err!(loc_inst, "invalid value reference {}", v)
|
||||
@@ -452,7 +454,7 @@ impl<'a> Verifier<'a> {
|
||||
}
|
||||
}
|
||||
|
||||
fn verify_inst_arg(&self, loc_inst: Inst, v: Value) -> Result {
|
||||
fn verify_inst_arg(&self, loc_inst: Inst, v: Value) -> VerifierResult<()> {
|
||||
self.verify_value(loc_inst, v)?;
|
||||
|
||||
let dfg = &self.func.dfg;
|
||||
@@ -523,7 +525,7 @@ impl<'a> Verifier<'a> {
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn verify_inst_result(&self, loc_inst: Inst, v: Value) -> Result {
|
||||
fn verify_inst_result(&self, loc_inst: Inst, v: Value) -> VerifierResult<()> {
|
||||
self.verify_value(loc_inst, v)?;
|
||||
|
||||
match self.func.dfg.value_def(v) {
|
||||
@@ -546,7 +548,7 @@ impl<'a> Verifier<'a> {
|
||||
}
|
||||
}
|
||||
|
||||
fn domtree_integrity(&self, domtree: &DominatorTree) -> Result {
|
||||
fn domtree_integrity(&self, domtree: &DominatorTree) -> VerifierResult<()> {
|
||||
// We consider two `DominatorTree`s to be equal if they return the same immediate
|
||||
// dominator for each EBB. Therefore the current domtree is valid if it matches the freshly
|
||||
// computed one.
|
||||
@@ -602,7 +604,7 @@ impl<'a> Verifier<'a> {
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn typecheck_entry_block_params(&self) -> Result {
|
||||
fn typecheck_entry_block_params(&self) -> VerifierResult<()> {
|
||||
if let Some(ebb) = self.func.layout.entry_block() {
|
||||
let expected_types = &self.func.signature.params;
|
||||
let ebb_param_count = self.func.dfg.num_ebb_params(ebb);
|
||||
@@ -632,7 +634,7 @@ impl<'a> Verifier<'a> {
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn typecheck(&self, inst: Inst) -> Result {
|
||||
fn typecheck(&self, inst: Inst) -> VerifierResult<()> {
|
||||
let inst_data = &self.func.dfg[inst];
|
||||
let constraints = inst_data.opcode().constraints();
|
||||
|
||||
@@ -660,7 +662,7 @@ impl<'a> Verifier<'a> {
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn typecheck_results(&self, inst: Inst, ctrl_type: Type) -> Result {
|
||||
fn typecheck_results(&self, inst: Inst, ctrl_type: Type) -> VerifierResult<()> {
|
||||
let mut i = 0;
|
||||
for &result in self.func.dfg.inst_results(inst) {
|
||||
let result_type = self.func.dfg.value_type(result);
|
||||
@@ -689,7 +691,7 @@ impl<'a> Verifier<'a> {
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn typecheck_fixed_args(&self, inst: Inst, ctrl_type: Type) -> Result {
|
||||
fn typecheck_fixed_args(&self, inst: Inst, ctrl_type: Type) -> VerifierResult<()> {
|
||||
let constraints = self.func.dfg[inst].opcode().constraints();
|
||||
|
||||
for (i, &arg) in self.func.dfg.inst_fixed_args(inst).iter().enumerate() {
|
||||
@@ -724,7 +726,7 @@ impl<'a> Verifier<'a> {
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn typecheck_variable_args(&self, inst: Inst) -> Result {
|
||||
fn typecheck_variable_args(&self, inst: Inst) -> VerifierResult<()> {
|
||||
match self.func.dfg.analyze_branch(inst) {
|
||||
BranchInfo::SingleDest(ebb, _) => {
|
||||
let iter = self.func
|
||||
@@ -777,7 +779,7 @@ impl<'a> Verifier<'a> {
|
||||
&self,
|
||||
inst: Inst,
|
||||
iter: I,
|
||||
) -> Result {
|
||||
) -> VerifierResult<()> {
|
||||
let variable_args = self.func.dfg.inst_variable_args(inst);
|
||||
let mut i = 0;
|
||||
|
||||
@@ -816,7 +818,7 @@ impl<'a> Verifier<'a> {
|
||||
///
|
||||
/// When a signature has been legalized, all values passed as outgoing arguments on the stack
|
||||
/// must be assigned to a matching `OutgoingArg` stack slot.
|
||||
fn check_outgoing_args(&self, inst: Inst, sig_ref: SigRef) -> Result {
|
||||
fn check_outgoing_args(&self, inst: Inst, sig_ref: SigRef) -> VerifierResult<()> {
|
||||
let sig = &self.func.dfg.signatures[sig_ref];
|
||||
|
||||
// Before legalization, there's nothing to check.
|
||||
@@ -878,7 +880,7 @@ impl<'a> Verifier<'a> {
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn typecheck_return(&self, inst: Inst) -> Result {
|
||||
fn typecheck_return(&self, inst: Inst) -> VerifierResult<()> {
|
||||
if self.func.dfg[inst].opcode().is_return() {
|
||||
let args = self.func.dfg.inst_variable_args(inst);
|
||||
let expected_types = &self.func.signature.returns;
|
||||
@@ -904,7 +906,7 @@ impl<'a> Verifier<'a> {
|
||||
|
||||
// Check special-purpose type constraints that can't be expressed in the normal opcode
|
||||
// constraints.
|
||||
fn typecheck_special(&self, inst: Inst, ctrl_type: Type) -> Result {
|
||||
fn typecheck_special(&self, inst: Inst, ctrl_type: Type) -> VerifierResult<()> {
|
||||
if let ir::InstructionData::Unary { opcode, arg } = self.func.dfg[inst] {
|
||||
let arg_type = self.func.dfg.value_type(arg);
|
||||
match opcode {
|
||||
@@ -950,7 +952,7 @@ impl<'a> Verifier<'a> {
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn cfg_integrity(&self, cfg: &ControlFlowGraph) -> Result {
|
||||
fn cfg_integrity(&self, cfg: &ControlFlowGraph) -> VerifierResult<()> {
|
||||
let mut expected_succs = BTreeSet::<Ebb>::new();
|
||||
let mut got_succs = BTreeSet::<Ebb>::new();
|
||||
let mut expected_preds = BTreeSet::<Inst>::new();
|
||||
@@ -1001,7 +1003,7 @@ impl<'a> Verifier<'a> {
|
||||
|
||||
/// If the verifier has been set up with an ISA, make sure that the recorded encoding for the
|
||||
/// instruction (if any) matches how the ISA would encode it.
|
||||
fn verify_encoding(&self, inst: Inst) -> Result {
|
||||
fn verify_encoding(&self, inst: Inst) -> VerifierResult<()> {
|
||||
// When the encodings table is empty, we don't require any instructions to be encoded.
|
||||
//
|
||||
// Once some instructions are encoded, we require all side-effecting instructions to have a
|
||||
@@ -1109,7 +1111,7 @@ impl<'a> Verifier<'a> {
|
||||
|
||||
/// Verify the `return_at_end` property which requires that there are no internal return
|
||||
/// instructions.
|
||||
fn verify_return_at_end(&self) -> Result {
|
||||
fn verify_return_at_end(&self) -> VerifierResult<()> {
|
||||
for ebb in self.func.layout.ebbs() {
|
||||
let inst = self.func.layout.last_inst(ebb).unwrap();
|
||||
if self.func.dfg[inst].opcode().is_return() && Some(ebb) != self.func.layout.last_ebb()
|
||||
@@ -1121,7 +1123,7 @@ impl<'a> Verifier<'a> {
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub fn run(&self) -> Result {
|
||||
pub fn run(&self) -> VerifierResult<()> {
|
||||
self.verify_global_vars()?;
|
||||
self.typecheck_entry_block_params()?;
|
||||
for ebb in self.func.layout.ebbs() {
|
||||
@@ -1145,7 +1147,7 @@ impl<'a> Verifier<'a> {
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::{Error, Verifier};
|
||||
use super::{Verifier, VerifierError};
|
||||
use entity::EntityList;
|
||||
use ir::instructions::{InstructionData, Opcode};
|
||||
use ir::Function;
|
||||
@@ -1155,7 +1157,7 @@ mod tests {
|
||||
($e:expr, $msg:expr) => {
|
||||
match $e {
|
||||
Ok(_) => panic!("Expected an error"),
|
||||
Err(Error { message, .. }) => {
|
||||
Err(VerifierError { message, .. }) => {
|
||||
if !message.contains($msg) {
|
||||
#[cfg(feature = "std")]
|
||||
panic!(format!(
|
||||
|
||||
Reference in New Issue
Block a user