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:
Dan Gohman
2018-06-07 14:57:52 -07:00
parent 683880bd02
commit 13f22065a2
8 changed files with 82 additions and 76 deletions

View File

@@ -28,7 +28,7 @@ use simple_gvn::do_simple_gvn;
use std::vec::Vec; use std::vec::Vec;
use timing; use timing;
use unreachable_code::eliminate_unreachable_code; use unreachable_code::eliminate_unreachable_code;
use verifier; use verifier::{verify_context, verify_locations, VerifierResult};
/// Persistent data structures and compilation pipeline. /// Persistent data structures and compilation pipeline.
pub struct Context { pub struct Context {
@@ -174,8 +174,8 @@ impl Context {
/// Run the verifier on the function. /// Run the verifier on the function.
/// ///
/// Also check that the dominator tree and control flow graph are consistent with 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 { pub fn verify<'a, FOI: Into<FlagsOrIsa<'a>>>(&self, fisa: FOI) -> VerifierResult<()> {
verifier::verify_context(&self.func, &self.cfg, &self.domtree, fisa) verify_context(&self.func, &self.cfg, &self.domtree, fisa)
} }
/// Run the verifier only if the `enable_verifier` setting is true. /// Run the verifier only if the `enable_verifier` setting is true.
@@ -189,8 +189,8 @@ impl Context {
} }
/// Run the locations verifier on the function. /// Run the locations verifier on the function.
pub fn verify_locations(&self, isa: &TargetIsa) -> verifier::Result { pub fn verify_locations(&self, isa: &TargetIsa) -> VerifierResult<()> {
verifier::verify_locations(isa, &self.func, None) verify_locations(isa, &self.func, None)
} }
/// Run the locations verifier only if the `enable_verifier` setting is true. /// Run the locations verifier only if the `enable_verifier` setting is true.

View File

@@ -5,13 +5,13 @@ use isa::TargetIsa;
use result::CtonError; use result::CtonError;
use std::fmt::Write; use std::fmt::Write;
use std::string::{String, ToString}; use std::string::{String, ToString};
use verifier; use verifier::VerifierError;
/// Pretty-print a verifier error. /// Pretty-print a verifier error.
pub fn pretty_verifier_error( pub fn pretty_verifier_error(
func: &ir::Function, func: &ir::Function,
isa: Option<&TargetIsa>, isa: Option<&TargetIsa>,
err: &verifier::Error, err: &VerifierError,
) -> String { ) -> String {
let mut msg = err.to_string(); let mut msg = err.to_string();
match err.location { match err.location {

View File

@@ -1,6 +1,6 @@
//! Result and error types representing the outcome of compiling a function. //! Result and error types representing the outcome of compiling a function.
use verifier; use verifier::VerifierError;
/// A compilation error. /// 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 /// This always represents a bug, either in the code that generated IR for Cretonne, or a bug
/// in Cretonne itself. /// in Cretonne itself.
#[fail(display = "Verifier error: {}", _0)] #[fail(display = "Verifier error: {}", _0)]
Verifier(#[cause] verifier::Error), Verifier(#[cause] VerifierError),
/// An implementation limit was exceeded. /// An implementation limit was exceeded.
/// ///
@@ -34,8 +34,8 @@ pub enum CtonError {
/// A Cretonne compilation result. /// A Cretonne compilation result.
pub type CtonResult = Result<(), CtonError>; pub type CtonResult = Result<(), CtonError>;
impl From<verifier::Error> for CtonError { impl From<VerifierError> for CtonError {
fn from(e: verifier::Error) -> Self { fn from(e: VerifierError) -> Self {
CtonError::Verifier(e) CtonError::Verifier(e)
} }
} }

View File

@@ -7,7 +7,7 @@ use ir::{ExpandedProgramPoint, Function};
use regalloc::liveness::Liveness; use regalloc::liveness::Liveness;
use regalloc::virtregs::VirtRegs; use regalloc::virtregs::VirtRegs;
use timing; use timing;
use verifier::Result; use verifier::VerifierResult;
/// Verify conventional SSA form for `func`. /// Verify conventional SSA form for `func`.
/// ///
@@ -29,7 +29,7 @@ pub fn verify_cssa(
domtree: &DominatorTree, domtree: &DominatorTree,
liveness: &Liveness, liveness: &Liveness,
virtregs: &VirtRegs, virtregs: &VirtRegs,
) -> Result { ) -> VerifierResult<()> {
let _tt = timing::verify_cssa(); let _tt = timing::verify_cssa();
let mut preorder = DominatorTreePreorder::new(); let mut preorder = DominatorTreePreorder::new();
@@ -58,7 +58,7 @@ struct CssaVerifier<'a> {
} }
impl<'a> CssaVerifier<'a> { impl<'a> CssaVerifier<'a> {
fn check_virtregs(&self) -> Result { fn check_virtregs(&self) -> VerifierResult<()> {
for vreg in self.virtregs.all_virtregs() { for vreg in self.virtregs.all_virtregs() {
let values = self.virtregs.values(vreg); let values = self.virtregs.values(vreg);
@@ -135,7 +135,7 @@ impl<'a> CssaVerifier<'a> {
Ok(()) Ok(())
} }
fn check_cssa(&self) -> Result { fn check_cssa(&self) -> VerifierResult<()> {
for ebb in self.func.layout.ebbs() { for ebb in self.func.layout.ebbs() {
let ebb_params = self.func.dfg.ebb_params(ebb); let ebb_params = self.func.dfg.ebb_params(ebb);
for (_, pred) in self.cfg.pred_iter(ebb) { for (_, pred) in self.cfg.pred_iter(ebb) {

View File

@@ -6,9 +6,8 @@ use ir;
use ir::instructions::BranchInfo; use ir::instructions::BranchInfo;
use isa; use isa;
use packed_option::PackedOption; use packed_option::PackedOption;
use std::result;
use timing; use timing;
use verifier::{Error, Result}; use verifier::VerifierResult;
/// Verify that CPU flags are used correctly. /// Verify that CPU flags are used correctly.
/// ///
@@ -26,7 +25,7 @@ pub fn verify_flags(
func: &ir::Function, func: &ir::Function,
cfg: &ControlFlowGraph, cfg: &ControlFlowGraph,
isa: Option<&isa::TargetIsa>, isa: Option<&isa::TargetIsa>,
) -> Result { ) -> VerifierResult<()> {
let _tt = timing::verify_flags(); let _tt = timing::verify_flags();
let mut verifier = FlagsVerifier { let mut verifier = FlagsVerifier {
func, func,
@@ -47,7 +46,7 @@ struct FlagsVerifier<'a> {
} }
impl<'a> 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 // 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. // that one of their successor blocks needs a live-in flags value.
let mut worklist = SparseSet::new(); 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. /// 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. // The single currently live flags value.
let mut live_val = None; let mut live_val = None;
@@ -139,7 +138,7 @@ impl<'a> FlagsVerifier<'a> {
} }
// Merge live flags values, or return an error on conflicting values. // 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 let Some(va) = *a {
if b != va { if b != va {
return err!(inst, "conflicting live CPU flags: {} and {}", va, b); return err!(inst, "conflicting live CPU flags: {} and {}", va, b);

View File

@@ -8,7 +8,7 @@ use regalloc::liveness::Liveness;
use regalloc::liverange::LiveRange; use regalloc::liverange::LiveRange;
use std::cmp::Ordering; use std::cmp::Ordering;
use timing; use timing;
use verifier::Result; use verifier::VerifierResult;
/// Verify liveness information for `func`. /// Verify liveness information for `func`.
/// ///
@@ -27,7 +27,7 @@ pub fn verify_liveness(
func: &Function, func: &Function,
cfg: &ControlFlowGraph, cfg: &ControlFlowGraph,
liveness: &Liveness, liveness: &Liveness,
) -> Result { ) -> VerifierResult<()> {
let _tt = timing::verify_liveness(); let _tt = timing::verify_liveness();
let verifier = LivenessVerifier { let verifier = LivenessVerifier {
isa, isa,
@@ -49,7 +49,7 @@ struct LivenessVerifier<'a> {
impl<'a> LivenessVerifier<'a> { impl<'a> LivenessVerifier<'a> {
/// Check all EBB arguments. /// Check all EBB arguments.
fn check_ebbs(&self) -> Result { fn check_ebbs(&self) -> VerifierResult<()> {
for ebb in self.func.layout.ebbs() { for ebb in self.func.layout.ebbs() {
for &val in self.func.dfg.ebb_params(ebb) { for &val in self.func.dfg.ebb_params(ebb) {
let lr = match self.liveness.get(val) { let lr = match self.liveness.get(val) {
@@ -63,7 +63,7 @@ impl<'a> LivenessVerifier<'a> {
} }
/// Check all instructions. /// Check all instructions.
fn check_insts(&self) -> Result { fn check_insts(&self) -> VerifierResult<()> {
for ebb in self.func.layout.ebbs() { for ebb in self.func.layout.ebbs() {
for inst in self.func.layout.ebb_insts(ebb) { for inst in self.func.layout.ebb_insts(ebb) {
let encoding = self.func.encodings[inst]; let encoding = self.func.encodings[inst];
@@ -141,7 +141,7 @@ impl<'a> LivenessVerifier<'a> {
} }
/// Check the integrity of the live range `lr`. /// 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 l = &self.func.layout;
let loc: AnyEntity = match def.into() { let loc: AnyEntity = match def.into() {

View File

@@ -5,7 +5,7 @@ use isa;
use regalloc::liveness::Liveness; use regalloc::liveness::Liveness;
use regalloc::RegDiversions; use regalloc::RegDiversions;
use timing; use timing;
use verifier::Result; use verifier::VerifierResult;
/// Verify value locations for `func`. /// Verify value locations for `func`.
/// ///
@@ -22,7 +22,7 @@ pub fn verify_locations(
isa: &isa::TargetIsa, isa: &isa::TargetIsa,
func: &ir::Function, func: &ir::Function,
liveness: Option<&Liveness>, liveness: Option<&Liveness>,
) -> Result { ) -> VerifierResult<()> {
let _tt = timing::verify_locations(); let _tt = timing::verify_locations();
let verifier = LocationVerifier { let verifier = LocationVerifier {
isa, isa,
@@ -45,7 +45,7 @@ struct LocationVerifier<'a> {
impl<'a> LocationVerifier<'a> { impl<'a> LocationVerifier<'a> {
/// Check that the assigned value locations match the operand constraints of their uses. /// 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 dfg = &self.func.dfg;
let mut divert = RegDiversions::new(); let mut divert = RegDiversions::new();
@@ -88,7 +88,7 @@ impl<'a> LocationVerifier<'a> {
inst: ir::Inst, inst: ir::Inst,
enc: isa::Encoding, enc: isa::Encoding,
divert: &RegDiversions, divert: &RegDiversions,
) -> Result { ) -> VerifierResult<()> {
let constraints = self.encinfo let constraints = self.encinfo
.operand_constraints(enc) .operand_constraints(enc)
.expect("check_enc_constraints requires a legal encoding"); .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 /// Check that the result values produced by a ghost instruction are not assigned a value
/// location. /// 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); let results = self.func.dfg.inst_results(inst);
for &res in results { for &res in results {
@@ -126,7 +126,12 @@ impl<'a> LocationVerifier<'a> {
} }
/// Check the ABI argument and result locations for a call. /// 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 sig = &self.func.dfg.signatures[sig];
let varargs = self.func.dfg.inst_variable_args(inst); let varargs = self.func.dfg.inst_variable_args(inst);
let results = self.func.dfg.inst_results(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. /// 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 sig = &self.func.signature;
let varargs = self.func.dfg.inst_variable_args(inst); let varargs = self.func.dfg.inst_variable_args(inst);
@@ -180,7 +185,7 @@ impl<'a> LocationVerifier<'a> {
abi: &ir::AbiParam, abi: &ir::AbiParam,
loc: ir::ValueLoc, loc: ir::ValueLoc,
want_kind: ir::StackSlotKind, want_kind: ir::StackSlotKind,
) -> Result { ) -> VerifierResult<()> {
match abi.location { match abi.location {
ir::ArgumentLoc::Unassigned => {} ir::ArgumentLoc::Unassigned => {}
ir::ArgumentLoc::Reg(reg) => { ir::ArgumentLoc::Reg(reg) => {
@@ -233,7 +238,7 @@ impl<'a> LocationVerifier<'a> {
} }
/// Update diversions to reflect the current instruction and check their consistency. /// 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] { let (arg, src) = match self.func.dfg[inst] {
ir::InstructionData::RegMove { arg, src, .. } ir::InstructionData::RegMove { arg, src, .. }
| ir::InstructionData::RegSpill { arg, src, .. } => (arg, ir::ValueLoc::Reg(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 /// We have active diversions before a branch. Make sure none of the diverted values are live
/// on the outgoing CFG edges. /// 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::*; use ir::instructions::BranchInfo::*;
// We can only check CFG edges if we have a liveness analysis. // We can only check CFG edges if we have a liveness analysis.

View File

@@ -71,7 +71,6 @@ use settings::{Flags, FlagsOrIsa};
use std::cmp::Ordering; use std::cmp::Ordering;
use std::collections::BTreeSet; use std::collections::BTreeSet;
use std::fmt::{self, Display, Formatter, Write}; use std::fmt::{self, Display, Formatter, Write};
use std::result;
use std::string::String; use std::string::String;
use std::vec::Vec; use std::vec::Vec;
use timing; use timing;
@@ -80,17 +79,17 @@ pub use self::cssa::verify_cssa;
pub use self::liveness::verify_liveness; pub use self::liveness::verify_liveness;
pub use self::locations::verify_locations; 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 { macro_rules! err {
( $loc:expr, $msg:expr ) => { ( $loc:expr, $msg:expr ) => {
Err(::verifier::Error { Err(::verifier::VerifierError {
location: $loc.into(), location: $loc.into(),
message: String::from($msg), message: String::from($msg),
}) })
}; };
( $loc:expr, $fmt:expr, $( $arg:expr ),+ ) => { ( $loc:expr, $fmt:expr, $( $arg:expr ),+ ) => {
Err(::verifier::Error { Err(::verifier::VerifierError {
location: $loc.into(), location: $loc.into(),
message: format!( $fmt, $( $arg ),+ ), message: format!( $fmt, $( $arg ),+ ),
}) })
@@ -104,24 +103,27 @@ mod locations;
/// A verifier error. /// A verifier error.
#[derive(Fail, Debug, PartialEq, Eq)] #[derive(Fail, Debug, PartialEq, Eq)]
pub struct Error { pub struct VerifierError {
/// The entity causing the verifier error. /// The entity causing the verifier error.
pub location: AnyEntity, pub location: AnyEntity,
/// Error message. /// Error message.
pub message: String, pub message: String,
} }
impl Display for Error { impl Display for VerifierError {
fn fmt(&self, f: &mut Formatter) -> fmt::Result { fn fmt(&self, f: &mut Formatter) -> fmt::Result {
write!(f, "{}: {}", self.location, self.message) write!(f, "{}: {}", self.location, self.message)
} }
} }
/// Verifier result. /// Verifier result.
pub type Result = result::Result<(), Error>; pub type VerifierResult<T> = Result<T, VerifierError>;
/// Verify `func`. /// 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(); let _tt = timing::verifier();
Verifier::new(func, fisa.into()).run() Verifier::new(func, fisa.into()).run()
} }
@@ -133,7 +135,7 @@ pub fn verify_context<'a, FOI: Into<FlagsOrIsa<'a>>>(
cfg: &ControlFlowGraph, cfg: &ControlFlowGraph,
domtree: &DominatorTree, domtree: &DominatorTree,
fisa: FOI, fisa: FOI,
) -> Result { ) -> VerifierResult<()> {
let _tt = timing::verifier(); let _tt = timing::verifier();
let verifier = Verifier::new(func, fisa.into()); let verifier = Verifier::new(func, fisa.into());
if cfg.is_valid() { if cfg.is_valid() {
@@ -167,7 +169,7 @@ impl<'a> Verifier<'a> {
} }
// Check for cycles in the global variable declarations. // 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(); let mut seen = SparseSet::new();
for gv in self.func.global_vars.keys() { for gv in self.func.global_vars.keys() {
@@ -187,7 +189,7 @@ impl<'a> Verifier<'a> {
Ok(()) 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_terminator = self.func.dfg[inst].opcode().is_terminator();
let is_last_inst = self.func.layout.last_inst(ebb) == Some(inst); let is_last_inst = self.func.layout.last_inst(ebb) == Some(inst);
@@ -226,7 +228,7 @@ impl<'a> Verifier<'a> {
Ok(()) Ok(())
} }
fn instruction_integrity(&self, inst: Inst) -> Result { fn instruction_integrity(&self, inst: Inst) -> VerifierResult<()> {
let inst_data = &self.func.dfg[inst]; let inst_data = &self.func.dfg[inst];
let dfg = &self.func.dfg; let dfg = &self.func.dfg;
@@ -255,7 +257,7 @@ impl<'a> Verifier<'a> {
self.verify_entity_references(inst) 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::*; use ir::instructions::InstructionData::*;
for &arg in self.func.dfg.inst_args(inst) { for &arg in self.func.dfg.inst_args(inst) {
@@ -375,7 +377,7 @@ impl<'a> Verifier<'a> {
Ok(()) 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) { if !self.func.dfg.ebb_is_valid(e) || !self.func.layout.is_ebb_inserted(e) {
return err!(inst, "invalid ebb reference {}", e); return err!(inst, "invalid ebb reference {}", e);
} }
@@ -387,7 +389,7 @@ impl<'a> Verifier<'a> {
Ok(()) 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) { if !self.func.dfg.signatures.is_valid(s) {
err!(inst, "invalid signature reference {}", s) err!(inst, "invalid signature reference {}", s)
} else { } 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) { if !self.func.dfg.ext_funcs.is_valid(f) {
err!(inst, "invalid function reference {}", f) err!(inst, "invalid function reference {}", f)
} else { } 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) { if !self.func.stack_slots.is_valid(ss) {
err!(inst, "invalid stack slot {}", ss) err!(inst, "invalid stack slot {}", ss)
} else { } 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) { if !self.func.global_vars.is_valid(gv) {
err!(inst, "invalid global variable {}", gv) err!(inst, "invalid global variable {}", gv)
} else { } 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) { if !self.func.heaps.is_valid(heap) {
err!(inst, "invalid heap {}", heap) err!(inst, "invalid heap {}", heap)
} else { } 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) { if !l.is_valid(&self.func.dfg.value_lists) {
err!(inst, "invalid value list reference {:?}", l) err!(inst, "invalid value list reference {:?}", l)
} else { } 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) { if !self.func.jump_tables.is_valid(j) {
err!(inst, "invalid jump table reference {}", j) err!(inst, "invalid jump table reference {}", j)
} else { } 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; let dfg = &self.func.dfg;
if !dfg.value_is_valid(v) { if !dfg.value_is_valid(v) {
err!(loc_inst, "invalid value reference {}", 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)?; self.verify_value(loc_inst, v)?;
let dfg = &self.func.dfg; let dfg = &self.func.dfg;
@@ -523,7 +525,7 @@ impl<'a> Verifier<'a> {
Ok(()) 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)?; self.verify_value(loc_inst, v)?;
match self.func.dfg.value_def(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 // 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 // dominator for each EBB. Therefore the current domtree is valid if it matches the freshly
// computed one. // computed one.
@@ -602,7 +604,7 @@ impl<'a> Verifier<'a> {
Ok(()) Ok(())
} }
fn typecheck_entry_block_params(&self) -> Result { fn typecheck_entry_block_params(&self) -> VerifierResult<()> {
if let Some(ebb) = self.func.layout.entry_block() { if let Some(ebb) = self.func.layout.entry_block() {
let expected_types = &self.func.signature.params; let expected_types = &self.func.signature.params;
let ebb_param_count = self.func.dfg.num_ebb_params(ebb); let ebb_param_count = self.func.dfg.num_ebb_params(ebb);
@@ -632,7 +634,7 @@ impl<'a> Verifier<'a> {
Ok(()) Ok(())
} }
fn typecheck(&self, inst: Inst) -> Result { fn typecheck(&self, inst: Inst) -> VerifierResult<()> {
let inst_data = &self.func.dfg[inst]; let inst_data = &self.func.dfg[inst];
let constraints = inst_data.opcode().constraints(); let constraints = inst_data.opcode().constraints();
@@ -660,7 +662,7 @@ impl<'a> Verifier<'a> {
Ok(()) 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; let mut i = 0;
for &result in self.func.dfg.inst_results(inst) { for &result in self.func.dfg.inst_results(inst) {
let result_type = self.func.dfg.value_type(result); let result_type = self.func.dfg.value_type(result);
@@ -689,7 +691,7 @@ impl<'a> Verifier<'a> {
Ok(()) 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(); let constraints = self.func.dfg[inst].opcode().constraints();
for (i, &arg) in self.func.dfg.inst_fixed_args(inst).iter().enumerate() { for (i, &arg) in self.func.dfg.inst_fixed_args(inst).iter().enumerate() {
@@ -724,7 +726,7 @@ impl<'a> Verifier<'a> {
Ok(()) Ok(())
} }
fn typecheck_variable_args(&self, inst: Inst) -> Result { fn typecheck_variable_args(&self, inst: Inst) -> VerifierResult<()> {
match self.func.dfg.analyze_branch(inst) { match self.func.dfg.analyze_branch(inst) {
BranchInfo::SingleDest(ebb, _) => { BranchInfo::SingleDest(ebb, _) => {
let iter = self.func let iter = self.func
@@ -777,7 +779,7 @@ impl<'a> Verifier<'a> {
&self, &self,
inst: Inst, inst: Inst,
iter: I, iter: I,
) -> Result { ) -> VerifierResult<()> {
let variable_args = self.func.dfg.inst_variable_args(inst); let variable_args = self.func.dfg.inst_variable_args(inst);
let mut i = 0; 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 /// When a signature has been legalized, all values passed as outgoing arguments on the stack
/// must be assigned to a matching `OutgoingArg` stack slot. /// 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]; let sig = &self.func.dfg.signatures[sig_ref];
// Before legalization, there's nothing to check. // Before legalization, there's nothing to check.
@@ -878,7 +880,7 @@ impl<'a> Verifier<'a> {
Ok(()) Ok(())
} }
fn typecheck_return(&self, inst: Inst) -> Result { fn typecheck_return(&self, inst: Inst) -> VerifierResult<()> {
if self.func.dfg[inst].opcode().is_return() { if self.func.dfg[inst].opcode().is_return() {
let args = self.func.dfg.inst_variable_args(inst); let args = self.func.dfg.inst_variable_args(inst);
let expected_types = &self.func.signature.returns; 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 // Check special-purpose type constraints that can't be expressed in the normal opcode
// constraints. // 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] { if let ir::InstructionData::Unary { opcode, arg } = self.func.dfg[inst] {
let arg_type = self.func.dfg.value_type(arg); let arg_type = self.func.dfg.value_type(arg);
match opcode { match opcode {
@@ -950,7 +952,7 @@ impl<'a> Verifier<'a> {
Ok(()) Ok(())
} }
fn cfg_integrity(&self, cfg: &ControlFlowGraph) -> Result { fn cfg_integrity(&self, cfg: &ControlFlowGraph) -> VerifierResult<()> {
let mut expected_succs = BTreeSet::<Ebb>::new(); let mut expected_succs = BTreeSet::<Ebb>::new();
let mut got_succs = BTreeSet::<Ebb>::new(); let mut got_succs = BTreeSet::<Ebb>::new();
let mut expected_preds = BTreeSet::<Inst>::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 /// 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. /// 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. // 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 // 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 /// Verify the `return_at_end` property which requires that there are no internal return
/// instructions. /// instructions.
fn verify_return_at_end(&self) -> Result { fn verify_return_at_end(&self) -> VerifierResult<()> {
for ebb in self.func.layout.ebbs() { for ebb in self.func.layout.ebbs() {
let inst = self.func.layout.last_inst(ebb).unwrap(); let inst = self.func.layout.last_inst(ebb).unwrap();
if self.func.dfg[inst].opcode().is_return() && Some(ebb) != self.func.layout.last_ebb() if self.func.dfg[inst].opcode().is_return() && Some(ebb) != self.func.layout.last_ebb()
@@ -1121,7 +1123,7 @@ impl<'a> Verifier<'a> {
Ok(()) Ok(())
} }
pub fn run(&self) -> Result { pub fn run(&self) -> VerifierResult<()> {
self.verify_global_vars()?; self.verify_global_vars()?;
self.typecheck_entry_block_params()?; self.typecheck_entry_block_params()?;
for ebb in self.func.layout.ebbs() { for ebb in self.func.layout.ebbs() {
@@ -1145,7 +1147,7 @@ impl<'a> Verifier<'a> {
#[cfg(test)] #[cfg(test)]
mod tests { mod tests {
use super::{Error, Verifier}; use super::{Verifier, VerifierError};
use entity::EntityList; use entity::EntityList;
use ir::instructions::{InstructionData, Opcode}; use ir::instructions::{InstructionData, Opcode};
use ir::Function; use ir::Function;
@@ -1155,7 +1157,7 @@ mod tests {
($e:expr, $msg:expr) => { ($e:expr, $msg:expr) => {
match $e { match $e {
Ok(_) => panic!("Expected an error"), Ok(_) => panic!("Expected an error"),
Err(Error { message, .. }) => { Err(VerifierError { message, .. }) => {
if !message.contains($msg) { if !message.contains($msg) {
#[cfg(feature = "std")] #[cfg(feature = "std")]
panic!(format!( panic!(format!(