diff options
author | John Hodge <tpg@mutabah.net> | 2016-08-09 00:02:02 +0800 |
---|---|---|
committer | John Hodge <tpg@mutabah.net> | 2016-08-09 00:02:02 +0800 |
commit | 677f715a239a5c8254e2a2fa8c08ca43107e6aba (patch) | |
tree | 6110c6fb1c666f28040988990a98a253225ed0c4 /src | |
parent | 1ced52be0e02b55051fcb1d7962545052e09e2ad (diff) | |
download | mrust-677f715a239a5c8254e2a2fa8c08ca43107e6aba.tar.gz |
MIR - Work on lowering, not included yet and incomplete
Diffstat (limited to 'src')
-rw-r--r-- | src/mir/from_hir.cpp | 150 | ||||
-rw-r--r-- | src/mir/mir.hpp | 2 |
2 files changed, 151 insertions, 1 deletions
diff --git a/src/mir/from_hir.cpp b/src/mir/from_hir.cpp index 7bc25385..487942b5 100644 --- a/src/mir/from_hir.cpp +++ b/src/mir/from_hir.cpp @@ -8,6 +8,7 @@ #include "mir.hpp" #include "mir_ptr.hpp" #include <hir/expr.hpp> +#include <algorithm> namespace { class ExprVisitor_Conv: @@ -15,17 +16,166 @@ namespace { { ::MIR::Function& m_output; + unsigned int m_current_block; + unsigned int m_result_tmp_idx; + struct LoopDesc { + ::std::string label; + unsigned int cur; + unsigned int next; + }; + ::std::vector<LoopDesc> m_loop_stack; + struct BlockDesc { + ::std::vector<unsigned int> bindings; + }; + ::std::vector<BlockDesc> m_block_stack; + public: ExprVisitor_Conv(::MIR::Function& output): m_output(output) {} + void push_stmt_assign(::MIR::LValue dst, ::MIR::RValue val) + { + m_output.blocks.at(m_current_block).statements.push_back( ::MIR::Statement::make_Assign({ mv$(dst), mv$(val) }) ); + } + void push_stmt_drop(::MIR::LValue val) + { + m_output.blocks.at(m_current_block).statements.push_back( ::MIR::Statement::make_Drop({ ::MIR::eDropKind::DEEP, mv$(val) }) ); + } + + void end_block(::MIR::Terminator term) + { + if( m_current_block == 0 && (m_output.blocks.size() > 2 || ! m_output.blocks[0].terminator.is_Return()) ) { + BUG(Span(), "Terminating block when none active"); + } + m_output.blocks.at(m_current_block).terminator = mv$(term); + m_current_block = 0; + } + void set_cur_block(unsigned int new_block) + { + if( m_current_block != 0 || m_output.blocks.size() <= 1) { + BUG(Span(), "Updating block when previous is active"); + } + m_current_block = new_block; + } + ::MIR::BasicBlockId new_bb_linked() + { + auto rv = new_bb_unlinked(); + this->end_block( ::MIR::Terminator::make_Goto(rv) ); + this->set_cur_block(rv); + return rv; + } + ::MIR::BasicBlockId new_bb_unlinked() + { + auto rv = m_output.blocks.size(); + m_output.blocks.push_back({}); + return rv; + } + + void destructure_from(const Span& sp, const ::HIR::Pattern& pat, unsigned int temp_idx) + { + // TODO: Destructure + } + + // -- ExprVisitor void visit(::HIR::ExprNode_Block& node) override { + // TODO: Does this actually need to create a new BB? // Creates a BB, all expressions end up as part of it (with all but the final expression having their results dropped) + if( node.m_nodes.size() > 0 ) + { + m_block_stack.push_back( {} ); + for(unsigned int i = 0; i < node.m_nodes.size()-1; i ++) + { + this->visit_node_ptr(node.m_nodes.back()); + this->push_stmt_drop( ::MIR::LValue::make_Temporary({m_result_tmp_idx}) ); + } + + this->visit_node_ptr(node.m_nodes.back()); + auto ret = m_result_tmp_idx; + + auto bd = mv$( m_block_stack.back() ); + m_block_stack.pop_back(); + + // Drop all bindings introduced during this block. + for( auto& var_idx : bd.bindings ) { + this->push_stmt_drop( ::MIR::LValue::make_Variable(var_idx) ); + } + + m_result_tmp_idx = ret; + } + else + { + TODO(node.span(), "Lower empty blocks"); + } + } + void visit(::HIR::ExprNode_Return& node) override + { + this->visit_node_ptr(node.m_value); + + this->push_stmt_assign( ::MIR::LValue::make_Return({}), ::MIR::RValue::make_Use( ::MIR::LValue::make_Temporary({m_result_tmp_idx}) ) ); + this->end_block( ::MIR::Terminator::make_Return({}) ); + + m_result_tmp_idx = 0; + } + void visit(::HIR::ExprNode_Let& node) override + { + if( node.m_value ) + { + this->visit_node_ptr(node.m_value); + + this->destructure_from(node.span(), node.m_pattern, m_result_tmp_idx); + } + m_result_tmp_idx = 0; + } + void visit(::HIR::ExprNode_Loop& node) override + { + auto loop_block = this->new_bb_linked(); + auto loop_next = this->new_bb_unlinked(); + + m_loop_stack.push_back( LoopDesc { node.m_label, loop_block, loop_next } ); + this->visit_node_ptr(node.m_code); + m_loop_stack.pop_back(); + + this->end_block( ::MIR::Terminator::make_Goto(loop_block) ); + this->set_cur_block(loop_next); + + m_result_tmp_idx = 0; + } + void visit(::HIR::ExprNode_LoopControl& node) override + { + if( m_loop_stack.size() == 0 ) { + BUG(node.span(), "Loop control outside of a loop"); + } + + const auto* target_block = &m_loop_stack.back(); + if( node.m_label != "" ) { + auto it = ::std::find_if(m_loop_stack.rbegin(), m_loop_stack.rend(), [&](const auto& x){ return x.label == node.m_label; }); + if( it == m_loop_stack.rend() ) { + BUG(node.span(), "Named loop '" << node.m_label << " doesn't exist"); + } + target_block = &*it; + } + + if( node.m_continue ) { + this->end_block( ::MIR::Terminator::make_Goto(target_block->cur) ); + } + else { + this->end_block( ::MIR::Terminator::make_Goto(target_block->next) ); + } + m_result_tmp_idx = 0; + } + + void visit(::HIR::ExprNode_Match& node) override + { + this->visit_node_ptr(node.m_value); + //auto match_val = m_result_tmp_idx; + + // TODO: How to convert an arbitary match into a MIR construct. + TODO(node.span(), "Convert match into MIR"); } }; } diff --git a/src/mir/mir.hpp b/src/mir/mir.hpp index 04b7d0a0..750a1ec9 100644 --- a/src/mir/mir.hpp +++ b/src/mir/mir.hpp @@ -147,7 +147,7 @@ TAGGED_UNION(Statement, Assign, RValue src; }), (Drop, struct { - eDropKind kind; + eDropKind kind; // NOTE: For the `box` primitive LValue slot; }) ); |