summaryrefslogtreecommitdiff
path: root/src/mir/check.cpp
diff options
context:
space:
mode:
authorJohn Hodge <tpg@mutabah.net>2016-08-21 19:16:24 +0800
committerJohn Hodge <tpg@mutabah.net>2016-08-21 19:16:24 +0800
commit0bfeff2cadc2f20f9fcceff0a109c046fc08606b (patch)
tree701f709d6dae1e5c6adb802346c6a3c1061e3a62 /src/mir/check.cpp
parent61bce0a54921616748112accfcb0352d23d2db43 (diff)
downloadmrust-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.cpp78
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, {});
)
}
}