summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorJohn Hodge <tpg@mutabah.net>2016-08-09 00:02:02 +0800
committerJohn Hodge <tpg@mutabah.net>2016-08-09 00:02:02 +0800
commit677f715a239a5c8254e2a2fa8c08ca43107e6aba (patch)
tree6110c6fb1c666f28040988990a98a253225ed0c4 /src
parent1ced52be0e02b55051fcb1d7962545052e09e2ad (diff)
downloadmrust-677f715a239a5c8254e2a2fa8c08ca43107e6aba.tar.gz
MIR - Work on lowering, not included yet and incomplete
Diffstat (limited to 'src')
-rw-r--r--src/mir/from_hir.cpp150
-rw-r--r--src/mir/mir.hpp2
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;
})
);