diff options
author | John Hodge <tpg@mutabah.net> | 2016-08-21 19:16:24 +0800 |
---|---|---|
committer | John Hodge <tpg@mutabah.net> | 2016-08-21 19:16:24 +0800 |
commit | 0bfeff2cadc2f20f9fcceff0a109c046fc08606b (patch) | |
tree | 701f709d6dae1e5c6adb802346c6a3c1061e3a62 /src/mir/check.cpp | |
parent | 61bce0a54921616748112accfcb0352d23d2db43 (diff) | |
download | mrust-0bfeff2cadc2f20f9fcceff0a109c046fc08606b.tar.gz |
MIR Check - Check for `Invalid` terminators
- `Invalid` indicates the block wasn't ended during generation
Diffstat (limited to 'src/mir/check.cpp')
-rw-r--r-- | src/mir/check.cpp | 78 |
1 files changed, 72 insertions, 6 deletions
diff --git a/src/mir/check.cpp b/src/mir/check.cpp index 01e9e05e..dc208431 100644 --- a/src/mir/check.cpp +++ b/src/mir/check.cpp @@ -10,9 +10,75 @@ #include <hir/visitor.hpp> #include <hir_typeck/static.hpp> -void MIR_Validate(const StaticTraitResolve& resolve, const ::MIR::Function& fcn) +void MIR_Validate(const StaticTraitResolve& resolve, const ::MIR::Function& fcn, const ::std::vector< ::std::pair< ::HIR::Pattern, ::HIR::TypeRef> >& args) { + Span sp; + // Validation rules: + // - [CFA] All code paths from bb0 must end with either a return or a diverge (or loop) + // - Requires checking the links between basic blocks, with a bitmap to catch loops/multipath + { + bool returns = false; + ::std::vector<bool> visited_bbs( fcn.blocks.size() ); + ::std::vector<unsigned int> to_visit_blocks; + to_visit_blocks.push_back(0); + while( to_visit_blocks.size() > 0 ) + { + auto block = to_visit_blocks.back(); + to_visit_blocks.pop_back(); + assert(block < fcn.blocks.size()); + if( visited_bbs[block] ) { + continue ; + } + visited_bbs[block] = true; + + #define PUSH_BB(idx, desc) do {\ + ASSERT_BUG(sp, idx < fcn.blocks.size(), "Invalid target block on bb" << block << " - " << desc << " bb" << idx);\ + if( visited_bbs[idx] == false ) {\ + to_visit_blocks.push_back(idx); \ + }\ + } while(0) + TU_MATCH(::MIR::Terminator, (fcn.blocks[block].terminator), (e), + (Incomplete, + BUG(sp, "Encounterd `Incomplete` block in control flow - bb" << block); + ), + (Return, + returns = true; + ), + (Diverge, + //can_panic = true; + ), + (Goto, + PUSH_BB(e, "Goto"); + ), + (Panic, + PUSH_BB(e.dst, "Panic"); + ), + (If, + PUSH_BB(e.bb0, "If true"); + PUSH_BB(e.bb1, "If false"); + ), + (Switch, + for(unsigned int i = 0; i < e.targets.size(); i++ ) { + PUSH_BB(e.targets[i], "Switch V" << i); + } + ), + (Call, + PUSH_BB(e.ret_block, "Call ret"); + PUSH_BB(e.panic_block, "Call panic"); + ) + ) + #undef PUSH_BB + } + if( !returns ) { + DEBUG("- Function doesn't return."); + } + } + // - [ValState] No drops or usage of uninitalised values (Uninit, Moved, or Dropped) + // - [ValState] Temporaries are write-once. + // - Requires maintaining state information for all variables/temporaries with support for loops + // - [Flat] Types must be valid (correct type for slot etc.) + // - Simple check of all assignments/calls/... } namespace { @@ -37,7 +103,7 @@ namespace { this->visit_type( *e.inner ); DEBUG("Array size " << ty); if( e.size ) { - MIR_Validate(m_resolve, *e.size.m_mir); + MIR_Validate(m_resolve, *e.size.m_mir, {}); } ) else { @@ -52,19 +118,19 @@ namespace { auto _ = this->m_resolve.set_item_generics(item.m_params); if( item.m_code ) { DEBUG("Function code " << p); - MIR_Validate(m_resolve, *item.m_code.m_mir); + MIR_Validate(m_resolve, *item.m_code.m_mir, item.m_args); } } void visit_static(::HIR::ItemPath p, ::HIR::Static& item) override { if( item.m_value ) { DEBUG("`static` value " << p); - MIR_Validate(m_resolve, *item.m_value.m_mir); + MIR_Validate(m_resolve, *item.m_value.m_mir, {}); } } void visit_constant(::HIR::ItemPath p, ::HIR::Constant& item) override { if( item.m_value ) { DEBUG("`const` value " << p); - MIR_Validate(m_resolve, *item.m_value.m_mir); + MIR_Validate(m_resolve, *item.m_value.m_mir, {}); } } void visit_enum(::HIR::ItemPath p, ::HIR::Enum& item) override { @@ -72,7 +138,7 @@ namespace { for(auto& var : item.m_variants) { TU_IFLET(::HIR::Enum::Variant, var.second, Value, e, - MIR_Validate(m_resolve, *e.m_mir); + MIR_Validate(m_resolve, *e.m_mir, {}); ) } } |