diff options
author | John Hodge <tpg@mutabah.net> | 2016-08-10 20:28:30 +0800 |
---|---|---|
committer | John Hodge <tpg@mutabah.net> | 2016-08-10 20:28:30 +0800 |
commit | e21656f68bab1e3021be97c4708c9854f4da76e1 (patch) | |
tree | b826db97469e0db2c100f9e421aa987dbc553c10 /src | |
parent | fd82195a241a49debb19d7a44442c66ab37d29bb (diff) | |
download | mrust-e21656f68bab1e3021be97c4708c9854f4da76e1.tar.gz |
MIR - Match construction draft, cleanup
Diffstat (limited to 'src')
-rw-r--r-- | src/include/tagged_union.hpp | 2 | ||||
-rw-r--r-- | src/main.cpp | 2 | ||||
-rw-r--r-- | src/mir/from_hir.cpp | 548 |
3 files changed, 410 insertions, 142 deletions
diff --git a/src/include/tagged_union.hpp b/src/include/tagged_union.hpp index e392815e..1e319b08 100644 --- a/src/include/tagged_union.hpp +++ b/src/include/tagged_union.hpp @@ -204,7 +204,7 @@ class _name TU_EXP _inherit { \ Tag m_tag; \ union DataUnion { TU_UNION_FIELDS _variants DataUnion() {} ~DataUnion() {} } m_data;/* */ public:\ - _name(): m_tag(TAG_##_def) { m_data._def = TU_DATANAME(_def)(); }/* + _name(): m_tag(TAG_##_def) { new (&m_data._def) TU_DATANAME(_def)(); }/* */ _name(const _name&) = delete;/* */ _name(_name&& x) noexcept: m_tag(x.m_tag) TU_EXP _extra_move { switch(m_tag) { case TAGDEAD: break; TU_MOVE_CASES _variants } x.m_tag = TAGDEAD; }/* */ _name& operator =(_name&& x) { switch(m_tag) { case TAGDEAD: break; TU_DEST_CASES _variants } m_tag = x.m_tag; TU_EXP _extra_assign switch(m_tag) { case TAGDEAD: break; TU_MOVE_CASES _variants }; return *this; }/* diff --git a/src/main.cpp b/src/main.cpp index d13ec346..adea74f5 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -33,6 +33,8 @@ bool debug_enabled() //return g_cur_phase != "Parse" && g_cur_phase != "Expand";
//return g_cur_phase != "Parse" && g_cur_phase != "Expand" && g_cur_phase != "Resolve";
return g_cur_phase != "Parse" && g_cur_phase != "Expand" && g_cur_phase != "Resolve" && g_cur_phase != "Typecheck Expressions";
+ //return false;
+ //return g_cur_phase == "Lower MIR";
}
::std::ostream& debug_output(int indent, const char* function)
{
diff --git a/src/mir/from_hir.cpp b/src/mir/from_hir.cpp index 4b663879..c8d909e3 100644 --- a/src/mir/from_hir.cpp +++ b/src/mir/from_hir.cpp @@ -16,8 +16,7 @@ #include "main_bindings.hpp" namespace { - class ExprVisitor_Conv: - public ::HIR::ExprVisitor + class MirBuilder { ::MIR::Function& m_output; @@ -26,25 +25,13 @@ namespace { ::MIR::RValue m_result; bool m_result_valid; - - 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): + MirBuilder(::MIR::Function& output): m_output(output), m_block_active(false), m_result_valid(false) { - this->set_cur_block( this->new_bb_unlinked() ); + set_cur_block( new_bb_unlinked() ); } ::MIR::LValue new_temporary(const ::HIR::TypeRef& ty) @@ -59,8 +46,8 @@ namespace { return mv$(e); ) else { - auto temp = this->new_temporary(ty); - this->push_stmt_assign( ::MIR::LValue(temp.as_Temporary()), mv$(val) ); + auto temp = new_temporary(ty); + push_stmt_assign( ::MIR::LValue(temp.as_Temporary()), mv$(val) ); return temp; } } @@ -91,6 +78,9 @@ namespace { m_result = mv$(val); m_result_valid = true; } + bool has_result() const { + return m_result_valid; + } void push_stmt_assign(::MIR::LValue dst, ::MIR::RValue val) { @@ -103,6 +93,9 @@ namespace { m_output.blocks.at(m_current_block).statements.push_back( ::MIR::Statement::make_Drop({ ::MIR::eDropKind::DEEP, mv$(val) }) ); } + bool block_active() const { + return m_block_active; + } void end_block(::MIR::Terminator term) { if( !m_block_active ) { @@ -123,8 +116,8 @@ namespace { ::MIR::BasicBlockId new_bb_linked() { auto rv = new_bb_unlinked(); - this->end_block( ::MIR::Terminator::make_Goto(rv) ); - this->set_cur_block(rv); + end_block( ::MIR::Terminator::make_Goto(rv) ); + set_cur_block(rv); return rv; } ::MIR::BasicBlockId new_bb_unlinked() @@ -133,13 +126,37 @@ namespace { m_output.blocks.push_back({}); return rv; } + }; + + class ExprVisitor_Conv: + public ::HIR::ExprVisitor + { + MirBuilder m_builder; + + 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_builder(output) + { + } + void destructure_from(const Span& sp, const ::HIR::Pattern& pat, ::MIR::LValue lval) { if( pat.m_binding.is_valid() ) { ASSERT_BUG(sp, pat.m_data.is_Any(), "Destructure patterns can't bind and match"); - this->push_stmt_assign( ::MIR::LValue::make_Variable(pat.m_binding.m_slot), mv$(lval) ); + m_builder.push_stmt_assign( ::MIR::LValue::make_Variable(pat.m_binding.m_slot), mv$(lval) ); return ; } // TODO: Destructure @@ -159,21 +176,21 @@ namespace { auto& subnode = node.m_nodes[i]; const Span& sp = subnode->span(); this->visit_node_ptr(subnode); - this->push_stmt_drop( this->lvalue_or_temp(subnode->m_res_type, this->get_result(sp)) ); + m_builder.push_stmt_drop( m_builder.lvalue_or_temp(subnode->m_res_type, m_builder.get_result(sp)) ); } this->visit_node_ptr(node.m_nodes.back()); - auto ret = this->get_result(node.m_nodes.back()->span()); + auto ret = m_builder.get_result(node.m_nodes.back()->span()); 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_builder.push_stmt_drop( ::MIR::LValue::make_Variable(var_idx) ); } - this->set_result(node.span(), mv$(ret)); + m_builder.set_result(node.span(), mv$(ret)); } else { @@ -185,8 +202,8 @@ namespace { TRACE_FUNCTION_F("_Return"); this->visit_node_ptr(node.m_value); - this->push_stmt_assign( ::MIR::LValue::make_Return({}), this->get_result(node.span()) ); - this->end_block( ::MIR::Terminator::make_Return({}) ); + m_builder.push_stmt_assign( ::MIR::LValue::make_Return({}), m_builder.get_result(node.span()) ); + m_builder.end_block( ::MIR::Terminator::make_Return({}) ); } void visit(::HIR::ExprNode_Let& node) override { @@ -195,22 +212,22 @@ namespace { { this->visit_node_ptr(node.m_value); - this->destructure_from(node.span(), node.m_pattern, this->lvalue_or_temp(node.m_type, this->get_result(node.span()) )); + this->destructure_from(node.span(), node.m_pattern, m_builder.lvalue_or_temp(node.m_type, m_builder.get_result(node.span()) )); } - this->set_result(node.span(), ::MIR::RValue::make_Tuple({})); + m_builder.set_result(node.span(), ::MIR::RValue::make_Tuple({})); } void visit(::HIR::ExprNode_Loop& node) override { TRACE_FUNCTION_F("_Loop"); - auto loop_block = this->new_bb_linked(); - auto loop_next = this->new_bb_unlinked(); + auto loop_block = m_builder.new_bb_linked(); + auto loop_next = m_builder.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_builder.end_block( ::MIR::Terminator::make_Goto(loop_block) ); + m_builder.set_cur_block(loop_next); } void visit(::HIR::ExprNode_LoopControl& node) override { @@ -229,10 +246,10 @@ namespace { } if( node.m_continue ) { - this->end_block( ::MIR::Terminator::make_Goto(target_block->cur) ); + m_builder.end_block( ::MIR::Terminator::make_Goto(target_block->cur) ); } else { - this->end_block( ::MIR::Terminator::make_Goto(target_block->next) ); + m_builder.end_block( ::MIR::Terminator::make_Goto(target_block->next) ); } } @@ -240,7 +257,7 @@ namespace { { TRACE_FUNCTION_F("_Match"); this->visit_node_ptr(node.m_value); - auto match_val = this->lvalue_or_temp(node.m_value->m_res_type, this->get_result(node.m_value->span())); + auto match_val = m_builder.lvalue_or_temp(node.m_value->m_res_type, m_builder.get_result(node.m_value->span())); if( node.m_arms.size() == 0 ) { // Nothing @@ -467,8 +484,9 @@ namespace { // Map of arm index to ruleset ::std::vector< ::std::pair< unsigned int, PatternRuleset > > arm_rules; - for(const auto& arm : node.m_arms) { - auto idx = m_arm_rules.size(); + for(unsigned int idx = 0; idx < node.m_arms.size(); idx ++) + { + const auto& arm = node.m_arms[idx]; for( const auto& pat : arm.m_patterns ) { auto builder = PatternRulesetBuilder {}; @@ -488,36 +506,284 @@ namespace { // Generate arm code // - End the current block with a jump to the descision code (TODO: Can this be avoided while still being defensive?) - auto descision_block = this->new_bb_unlinked(); - this->end_block( ::MIR::Terminator::Goto(descision_block) ); + auto descision_block = m_builder.new_bb_unlinked(); + m_builder.end_block( ::MIR::Terminator::make_Goto(descision_block) ); // - Create a result and next block - auto result_val = this->new_temporary(node.m_res_type); - auto next_block = this->new_bb_unlinked(); + auto result_val = m_builder.new_temporary(node.m_res_type); + auto next_block = m_builder.new_bb_unlinked(); // - Generate code for arms. ::std::vector< ::MIR::BasicBlockId> arm_blocks; arm_blocks.reserve( arm_rules.size() ); for(unsigned int i = 0; i < arm_rules.size(); i ++) { - const auto& arm = node.m_arms[i]; - arm_blocks.push_back( this->new_bb_unlinked() ); - this->set_cur_block(arm_blocks.back()); + auto& arm = node.m_arms[i]; + // TODO: Register introduced bindings to be dropped on return/diverge + arm_blocks.push_back( m_builder.new_bb_unlinked() ); + m_builder.set_cur_block(arm_blocks.back()); this->visit_node_ptr(arm.m_code); - this->push_stmt_assign( result_val.clone(), this->get_result(arm.m_code->span()) ); - // TODO: Drop unused bindings introduced by this arm. - this->end_block( ::MIR::Terminator::Goto(next_block) ); + if( !m_builder.block_active() && !m_builder.has_result() ) { + // Nothing need be done, as the block diverged. + } + else { + m_builder.push_stmt_assign( result_val.clone(), m_builder.get_result(arm.m_code->span()) ); + m_builder.end_block( ::MIR::Terminator::make_Goto(next_block) ); + } + } + + // ## Create descision tree in-memory based off the ruleset + // > Tree contains an lvalue and a set of possibilities (PatternRule) connected to another tree or to a branch index + struct DecisionTreeNode { + TAGGED_UNION( Branch, Unset, + (Unset, struct{}), + (Subtree, ::std::unique_ptr<DecisionTreeNode>), + (Terminal, unsigned int) + ); + + TAGGED_UNION( Values, Unset, + (Unset, struct {}), + (Variant, ::std::vector< ::std::pair<unsigned int, Branch> >)/*, + (Unsigned, struct { branchset_t<uint64_t[2]> branches; }), + (String, struct { branchset_t< ::std::string> branches; })*/ + ); + + bool is_specialisation; + ::MIR::LValue value; + Values m_branches; + Branch m_default; + + DecisionTreeNode(): + is_specialisation(false) + {} + + void populate_tree_from_rule(const Span& sp, unsigned int arm_index, const PatternRule* first_rule, unsigned int rule_count) + { + populate_tree_from_rule(sp, first_rule, rule_count, [rule_count](auto& branch){ branch = Branch::make_Terminal(rule_count); }); + } + // `and_then` - Closure called after processing the final rule + void populate_tree_from_rule(const Span& sp, const PatternRule* first_rule, unsigned int rule_count, ::std::function<void(Branch&)> and_then) + { + assert( rule_count > 0 ); + const auto& rule = *first_rule; + + TU_MATCHA( (rule), (e), + (Any, { + if( m_default.is_Unset() ) { + if( rule_count == 1 ) { + and_then(m_default); + } + else { + auto be = box$(DecisionTreeNode()); + be->populate_tree_from_rule(sp, first_rule+1, rule_count-1, and_then); + m_default = Branch(mv$(be)); + } + } + else TU_IFLET( Branch, m_default, Subtree, be, + assert( be ); + assert(rule_count > 1); + be->populate_tree_from_rule(sp, first_rule+1, rule_count-1, and_then); + ) + else { + // NOTE: All lists processed as part of the same tree should be the same length + BUG(sp, "Duplicate terminal rule"); + } + }), + (Variant, { + if( m_branches.is_Unset() ) { + m_branches = Values::make_Variant({}); + } + if( !m_branches.is_Variant() ) { + BUG(sp, "Mismatched rules"); + } + auto& be = m_branches.as_Variant(); + auto it = ::std::find_if( be.begin(), be.end(), [&](const auto& x){ return x.first >= e.idx; }); + // Not found? Insert a new branch + if( it == be.end() || it->first != e.idx ) { + it = be.insert(it, ::std::make_pair(e.idx, Branch( box$(DecisionTreeNode()) ))); + auto& subtree = *it->second.as_Subtree(); + + if( e.sub_rules.size() > 0 && rule_count > 1 ) + { + subtree.populate_tree_from_rule(sp, e.sub_rules.data(), e.sub_rules.size(), [&](auto& branch){ + ASSERT_BUG(sp, branch.is_Unset(), "Duplicate terminator"); + branch.as_Subtree()->populate_tree_from_rule(sp, first_rule+1, rule_count-1, and_then); + }); + } + else if( e.sub_rules.size() > 0) + { + subtree.populate_tree_from_rule(sp, e.sub_rules.data(), e.sub_rules.size(), and_then); + } + else if( rule_count > 1 ) + { + subtree.populate_tree_from_rule(sp, first_rule+1, rule_count-1, and_then); + } + else + { + and_then(it->second); + } + } + else { + assert( !it->second.is_Unset() ); + TU_IFLET(Branch, it->second, Subtree, subtree_ptr, + assert(subtree_ptr); + subtree_ptr->populate_tree_from_rule(sp, first_rule+1, rule_count-1, and_then); + ) + else { + BUG(sp, "Duplicate terminal rule - " << it->second.as_Terminal()); + } + } + }), + (Value, + TODO(sp, "Value patterns"); + ) + ) + } + + /* + void populate_tree_vals(const ::HIR::TypeRef& ty, unsigned int ty_ofs, const ::MIR::LValue& val) + { + TU_MATCHA( (ty.m_data), (e), + ( + (Infer, BUG(sp, "Ivar for in match type"); ), + (Diverge, BUG(sp, "Diverge in match type"); ), + (Primitive, + TODO(sp, "Primitive"); + ), + (Tuple, + if( ty_ofs == 0 && e.size() == 0 ) { + } + else { + assert(ty_ofs < e.size()); + populate_tree_from_rule( e[ty_ofs], 0, ::MIR::LValue::make_Field({ box$(val.clone()), FMT(ty_ofs)}), arm_index, first_rule, rule_count ); + } + // Tuple - Recurse on each sub-type (increasing the index) + for(unsigned int i = 0; i < e.size(); i ++) { + idx += this->create_match_tree(sp, view, idx, e[i]); + } + ), + (Path, + // This is either a struct destructure or an enum + TU_MATCHA( (e.binding), (pbe), + (Unbound, + BUG(sp, "Encounterd unbound path - " << e.path); + ), + (Opaque, + // TODO: Why did this push a pattern? There's no chance of fail. + return 1; + ), + (Struct, + TODO(sp, "Match over struct - " << e.path); + ), + (Enum, + auto variant_count = pbe->m_variants.size(); + auto first_any = variant_count; + for( unsigned int i = 0; i < view.rule_count(); i ++ ) { + if( view.get(i, idx).is_Any() ) { + first_any = i; + break; + } + } + auto any_block = (first_any < variant_count ? m_builder.new_bb_unlinked() : 0); + + // Emit a switch over the variant + ::std::vector< ::MIR::BasicBlockId> variants; + variants.reserve( pbe->m_variants.size() ); + for( unsigned int i = 0; i < view.rule_count(); i ++ ) { + const auto& pat = view.get(i, idx); + if( pat.is_Any() ) { + break ; + } + else TU_IFLET( PatternRule, pat, Variant, e ) { + if( variants.size() == e.idx + 1 ) { + // Repeated index, will be unified later? + } + else { + if( variants.size() != e.idx ) { + assert( variants.size() < e.idx ); + if( ! has_any ) { + ERROR(sp, E0000, "Non-exhaustive match, variant " << pbe->m_variants[variants.size()].first << " missing"); + } + variants.resize( e.idx, any_block ); + } + variants.push_back( m_builder.new_bb_unlinked() ); + } + } + else { + BUG(sp, "Encountered unexpected pattern rule in enum, arm " << i); + } + } + if( variants.size() != variant_count ) + { + if( ! has_any ) { + ERROR(sp, E0000, "Non-exhaustive match, variant " << pbe->m_variants[variants.size()].first << " missing"); + } + variants.resize( e.idx, any_block ); + } + + m_builder.end_block( ::MIR::Terminator::make_Switch({ + view.get_lvalue(idx), mv$(variants) + }) ); + + + // Enums consume one rule + return 1; + ) + ) + ), + (Generic, + // TODO: Why did this push a pattern? There's no chance of fail. + return 1; + ), + (TraitObject, + ERROR(sp, E0000, "Attempting to match over a trait object"); + ), + (Array, + // TODO: Slice patterns, sequential comparison/sub-match + TODO(sp, "Match over array"); + ), + (Slice, + BUG(sp, "Hit match over `[T]` - must be `&[T]`"); + ), + (Borrow, + TU_MATCH_DEF( ::HIR::Pattern::Data, (pat.m_data), (pe), + ( throw ""; ), + (Any, + this->append_from( sp, pat, *e.inner ); + ), + (Ref, + this->append_from( sp, *pe.sub, *e.inner ); + ) + ) + ), + (Pointer, + ERROR(sp, E0000, "Attempting to match over a pointer"); + ), + (Function, + ERROR(sp, E0000, "Attempting to match over a functon pointer"); + ), + (Closure, + ERROR(sp, E0000, "Attempting to match over a closure"); + ) + ) + } + */ + }; + + // - Build tree by running each arm's pattern across it + DecisionTreeNode root_node; + for( const auto& arm_rule : arm_rules ) + { + root_node.populate_tree_from_rule( node.m_arms[arm_rule.first].m_code->span(), arm_rule.first, arm_rule.second.m_rules.data(), arm_rule.second.m_rules.size() ); } - - // Generate decision code based on ruleset and type - this->set_cur_block(descision_block); - TODO(node.span(), "Convert match into MIR using ruleset"); + // TODO: Convert the above decision tree into MIR + TODO(node.span(), "Turn decision tree into MIR"); - this->set_cur_block(next_block); - this->set_result( mv$(result_val) ); + m_builder.set_cur_block(next_block); + m_builder.set_result( node.span(), mv$(result_val) ); } } // ExprNode_Match @@ -526,36 +792,36 @@ namespace { TRACE_FUNCTION_F("_If"); this->visit_node_ptr(node.m_cond); - auto decision_val = this->lvalue_or_temp(node.m_cond->m_res_type, this->get_result(node.m_cond->span()) ); + auto decision_val = m_builder.lvalue_or_temp(node.m_cond->m_res_type, m_builder.get_result(node.m_cond->span()) ); - auto true_branch = this->new_bb_unlinked(); - auto false_branch = this->new_bb_unlinked(); - auto next_block = this->new_bb_unlinked(); - this->end_block( ::MIR::Terminator::make_If({ mv$(decision_val), true_branch, false_branch }) ); + auto true_branch = m_builder.new_bb_unlinked(); + auto false_branch = m_builder.new_bb_unlinked(); + auto next_block = m_builder.new_bb_unlinked(); + m_builder.end_block( ::MIR::Terminator::make_If({ mv$(decision_val), true_branch, false_branch }) ); - auto result_val = this->new_temporary(node.m_res_type); + auto result_val = m_builder.new_temporary(node.m_res_type); - this->set_cur_block(true_branch); + m_builder.set_cur_block(true_branch); this->visit_node_ptr(node.m_true); - this->push_stmt_assign( result_val.clone(), this->get_result(node.m_true->span()) ); - this->end_block( ::MIR::Terminator::make_Goto(next_block) ); + m_builder.push_stmt_assign( result_val.clone(), m_builder.get_result(node.m_true->span()) ); + m_builder.end_block( ::MIR::Terminator::make_Goto(next_block) ); - this->set_cur_block(false_branch); + m_builder.set_cur_block(false_branch); if( node.m_false ) { this->visit_node_ptr(node.m_false); - this->push_stmt_assign( result_val.clone(), this->get_result(node.m_false->span()) ); - this->end_block( ::MIR::Terminator::make_Goto(next_block) ); + m_builder.push_stmt_assign( result_val.clone(), m_builder.get_result(node.m_false->span()) ); + m_builder.end_block( ::MIR::Terminator::make_Goto(next_block) ); } else { // Assign `()` to the result - this->push_stmt_assign( result_val.clone(), ::MIR::RValue::make_Tuple({}) ); - this->end_block( ::MIR::Terminator::make_Goto(next_block) ); + m_builder.push_stmt_assign( result_val.clone(), ::MIR::RValue::make_Tuple({}) ); + m_builder.end_block( ::MIR::Terminator::make_Goto(next_block) ); } - this->set_cur_block(next_block); + m_builder.set_cur_block(next_block); - this->set_result( node.span(), mv$(result_val) ); + m_builder.set_result( node.span(), mv$(result_val) ); } void visit(::HIR::ExprNode_Assign& node) override @@ -564,10 +830,10 @@ namespace { const auto& sp = node.span(); this->visit_node_ptr(node.m_value); - auto val = this->get_result(sp); + auto val = m_builder.get_result(sp); this->visit_node_ptr(node.m_slot); - auto dst = this->get_result_lvalue(sp); + auto dst = m_builder.get_result_lvalue(sp); if( node.m_op != ::HIR::ExprNode_Assign::Op::None ) { @@ -576,7 +842,7 @@ namespace { } else { - this->push_stmt_assign(mv$(dst), mv$(val)); + m_builder.push_stmt_assign(mv$(dst), mv$(val)); } } @@ -584,12 +850,12 @@ namespace { { TRACE_FUNCTION_F("_BinOp"); this->visit_node_ptr(node.m_left); - auto left = this->lvalue_or_temp( node.m_left->m_res_type, this->get_result(node.m_left->span()) ); + auto left = m_builder.lvalue_or_temp( node.m_left->m_res_type, m_builder.get_result(node.m_left->span()) ); this->visit_node_ptr(node.m_right); - auto right = this->lvalue_or_temp( node.m_right->m_res_type, this->get_result(node.m_right->span()) ); + auto right = m_builder.lvalue_or_temp( node.m_right->m_res_type, m_builder.get_result(node.m_right->span()) ); - auto res = this->new_temporary(node.m_res_type); + auto res = m_builder.new_temporary(node.m_res_type); ::MIR::eBinOp op; switch(node.m_op) { @@ -599,19 +865,19 @@ namespace { case ::HIR::ExprNode_BinOp::Op::CmpLtE: op = ::MIR::eBinOp::LE; if(0) case ::HIR::ExprNode_BinOp::Op::CmpGt: op = ::MIR::eBinOp::GT; if(0) case ::HIR::ExprNode_BinOp::Op::CmpGtE: op = ::MIR::eBinOp::GE; - this->push_stmt_assign(res.as_Temporary(), ::MIR::RValue::make_BinOp({ mv$(left), op, mv$(right) })); + m_builder.push_stmt_assign(res.as_Temporary(), ::MIR::RValue::make_BinOp({ mv$(left), op, mv$(right) })); break; case ::HIR::ExprNode_BinOp::Op::Xor: op = ::MIR::eBinOp::BIT_XOR; if(0) case ::HIR::ExprNode_BinOp::Op::Or : op = ::MIR::eBinOp::BIT_OR ; if(0) case ::HIR::ExprNode_BinOp::Op::And: op = ::MIR::eBinOp::BIT_AND; - this->push_stmt_assign(res.as_Temporary(), ::MIR::RValue::make_BinOp({ mv$(left), op, mv$(right) })); + m_builder.push_stmt_assign(res.as_Temporary(), ::MIR::RValue::make_BinOp({ mv$(left), op, mv$(right) })); break; case ::HIR::ExprNode_BinOp::Op::Shr: op = ::MIR::eBinOp::BIT_SHR; if(0) case ::HIR::ExprNode_BinOp::Op::Shl: op = ::MIR::eBinOp::BIT_SHL; // TODO: Overflow checks - this->push_stmt_assign(res.as_Temporary(), ::MIR::RValue::make_BinOp({ mv$(left), op, mv$(right) })); + m_builder.push_stmt_assign(res.as_Temporary(), ::MIR::RValue::make_BinOp({ mv$(left), op, mv$(right) })); break; case ::HIR::ExprNode_BinOp::Op::BoolAnd: @@ -627,41 +893,41 @@ namespace { case ::HIR::ExprNode_BinOp::Op::Div: op = ::MIR::eBinOp::DIV; if(0) case ::HIR::ExprNode_BinOp::Op::Mod: op = ::MIR::eBinOp::MOD; // TODO: Overflow checks - this->push_stmt_assign(res.as_Temporary(), ::MIR::RValue::make_BinOp({ mv$(left), op, mv$(right) })); + m_builder.push_stmt_assign(res.as_Temporary(), ::MIR::RValue::make_BinOp({ mv$(left), op, mv$(right) })); break; } - this->set_result( node.span(), mv$(res) ); + m_builder.set_result( node.span(), mv$(res) ); } void visit(::HIR::ExprNode_UniOp& node) override { TRACE_FUNCTION_F("_UniOp"); this->visit_node_ptr(node.m_value); - auto val = this->lvalue_or_temp( node.m_value->m_res_type, this->get_result(node.m_value->span()) ); + auto val = m_builder.lvalue_or_temp( node.m_value->m_res_type, m_builder.get_result(node.m_value->span()) ); - auto res = this->new_temporary(node.m_res_type); + auto res = m_builder.new_temporary(node.m_res_type); switch(node.m_op) { case ::HIR::ExprNode_UniOp::Op::Ref: - this->push_stmt_assign(res.as_Temporary(), ::MIR::RValue::make_Borrow({ 0, ::HIR::BorrowType::Shared, mv$(val) })); + m_builder.push_stmt_assign(res.as_Temporary(), ::MIR::RValue::make_Borrow({ 0, ::HIR::BorrowType::Shared, mv$(val) })); break; case ::HIR::ExprNode_UniOp::Op::RefMut: - this->push_stmt_assign(res.as_Temporary(), ::MIR::RValue::make_Borrow({ 0, ::HIR::BorrowType::Unique, mv$(val) })); + m_builder.push_stmt_assign(res.as_Temporary(), ::MIR::RValue::make_Borrow({ 0, ::HIR::BorrowType::Unique, mv$(val) })); break; case ::HIR::ExprNode_UniOp::Op::Invert: - this->push_stmt_assign(res.as_Temporary(), ::MIR::RValue::make_UniOp({ mv$(val), ::MIR::eUniOp::INV })); + m_builder.push_stmt_assign(res.as_Temporary(), ::MIR::RValue::make_UniOp({ mv$(val), ::MIR::eUniOp::INV })); break; case ::HIR::ExprNode_UniOp::Op::Negate: - this->push_stmt_assign(res.as_Temporary(), ::MIR::RValue::make_UniOp({ mv$(val), ::MIR::eUniOp::NEG })); + m_builder.push_stmt_assign(res.as_Temporary(), ::MIR::RValue::make_UniOp({ mv$(val), ::MIR::eUniOp::NEG })); break; } - this->set_result( node.span(), mv$(res) ); + m_builder.set_result( node.span(), mv$(res) ); } void visit(::HIR::ExprNode_Cast& node) override { TRACE_FUNCTION_F("_Cast"); this->visit_node_ptr(node.m_value); - auto val = this->lvalue_or_temp( node.m_value->m_res_type, this->get_result(node.m_value->span()) ); + auto val = m_builder.lvalue_or_temp( node.m_value->m_res_type, m_builder.get_result(node.m_value->span()) ); #if 0 TU_MATCH_DEF( ::HIR::TypeRef::Data, (node.m_res_type->m_data), (de), @@ -675,9 +941,9 @@ namespace { ) ) #endif - auto res = this->new_temporary(node.m_res_type); - this->push_stmt_assign(res.clone(), ::MIR::RValue::make_Cast({ mv$(val), node.m_res_type.clone() })); - this->set_result( node.span(), mv$(res) ); + auto res = m_builder.new_temporary(node.m_res_type); + m_builder.push_stmt_assign(res.clone(), ::MIR::RValue::make_Cast({ mv$(val), node.m_res_type.clone() })); + m_builder.set_result( node.span(), mv$(res) ); } void visit(::HIR::ExprNode_Unsize& node) override { @@ -689,10 +955,10 @@ namespace { { TRACE_FUNCTION_F("_Index"); this->visit_node_ptr(node.m_index); - auto index = this->lvalue_or_temp( node.m_index->m_res_type, this->get_result(node.m_index->span()) ); + auto index = m_builder.lvalue_or_temp( node.m_index->m_res_type, m_builder.get_result(node.m_index->span()) ); this->visit_node_ptr(node.m_value); - auto value = this->lvalue_or_temp( node.m_value->m_res_type, this->get_result(node.m_value->span()) ); + auto value = m_builder.lvalue_or_temp( node.m_value->m_res_type, m_builder.get_result(node.m_value->span()) ); if( false ) { @@ -709,32 +975,32 @@ namespace { ) ) - auto limit_lval = this->lvalue_or_temp(node.m_index->m_res_type, mv$(limit_val)); + auto limit_lval = m_builder.lvalue_or_temp(node.m_index->m_res_type, mv$(limit_val)); - auto cmp_res = this->new_temporary( ::HIR::CoreType::Bool ); - this->push_stmt_assign(cmp_res.clone(), ::MIR::RValue::make_BinOp({ index.clone(), ::MIR::eBinOp::GE, mv$(limit_lval) })); - auto arm_panic = this->new_bb_unlinked(); - auto arm_continue = this->new_bb_unlinked(); - this->end_block( ::MIR::Terminator::make_If({ mv$(cmp_res), arm_panic, arm_continue }) ); + auto cmp_res = m_builder.new_temporary( ::HIR::CoreType::Bool ); + m_builder.push_stmt_assign(cmp_res.clone(), ::MIR::RValue::make_BinOp({ index.clone(), ::MIR::eBinOp::GE, mv$(limit_lval) })); + auto arm_panic = m_builder.new_bb_unlinked(); + auto arm_continue = m_builder.new_bb_unlinked(); + m_builder.end_block( ::MIR::Terminator::make_If({ mv$(cmp_res), arm_panic, arm_continue }) ); - this->set_cur_block( arm_panic ); + m_builder.set_cur_block( arm_panic ); // TODO: Call an "index fail" method which always panics. - //this->end_block( ::MIR::Terminator::make_Panic({}) ); - this->end_block( ::MIR::Terminator::make_Diverge({}) ); + //m_builder.end_block( ::MIR::Terminator::make_Panic({}) ); + m_builder.end_block( ::MIR::Terminator::make_Diverge({}) ); - this->set_cur_block( arm_continue ); + m_builder.set_cur_block( arm_continue ); } - this->set_result( node.span(), ::MIR::LValue::make_Index({ box$(index), box$(value) }) ); + m_builder.set_result( node.span(), ::MIR::LValue::make_Index({ box$(index), box$(value) }) ); } void visit(::HIR::ExprNode_Deref& node) override { TRACE_FUNCTION_F("_Deref"); this->visit_node_ptr(node.m_value); - auto val = this->lvalue_or_temp( node.m_value->m_res_type, this->get_result(node.m_value->span()) ); + auto val = m_builder.lvalue_or_temp( node.m_value->m_res_type, m_builder.get_result(node.m_value->span()) ); - this->set_result( node.span(), ::MIR::LValue::make_Deref({ box$(val) }) ); + m_builder.set_result( node.span(), ::MIR::LValue::make_Deref({ box$(val) }) ); } void visit(::HIR::ExprNode_TupleVariant& node) override @@ -745,10 +1011,10 @@ namespace { for(auto& arg : node.m_args) { this->visit_node_ptr(arg); - values.push_back( this->lvalue_or_temp( arg->m_res_type, this->get_result(arg->span()) ) ); + values.push_back( m_builder.lvalue_or_temp( arg->m_res_type, m_builder.get_result(arg->span()) ) ); } - this->set_result( node.span(), ::MIR::RValue::make_Struct({ + m_builder.set_result( node.span(), ::MIR::RValue::make_Struct({ node.m_path.clone(), mv$(values) }) ); @@ -762,7 +1028,7 @@ namespace { for(auto& arg : node.m_args) { this->visit_node_ptr(arg); - values.push_back( this->lvalue_or_temp( arg->m_res_type, this->get_result(arg->span()) ) ); + values.push_back( m_builder.lvalue_or_temp( arg->m_res_type, m_builder.get_result(arg->span()) ) ); } // TODO: Obtain function type for this function @@ -776,24 +1042,24 @@ namespace { { fcn_ty_data.m_arg_types.push_back( node.m_cache.m_arg_types[i].clone() ); } - auto fcn_val = this->new_temporary( ::HIR::TypeRef(mv$(fcn_ty_data)) ); - this->push_stmt_assign( fcn_val.clone(), ::MIR::RValue::make_Constant( ::MIR::Constant(node.m_path.clone()) ) ); + auto fcn_val = m_builder.new_temporary( ::HIR::TypeRef(mv$(fcn_ty_data)) ); + m_builder.push_stmt_assign( fcn_val.clone(), ::MIR::RValue::make_Constant( ::MIR::Constant(node.m_path.clone()) ) ); - auto panic_block = this->new_bb_unlinked(); - auto next_block = this->new_bb_unlinked(); - auto res = this->new_temporary( node.m_res_type ); - this->end_block(::MIR::Terminator::make_Call({ + auto panic_block = m_builder.new_bb_unlinked(); + auto next_block = m_builder.new_bb_unlinked(); + auto res = m_builder.new_temporary( node.m_res_type ); + m_builder.end_block(::MIR::Terminator::make_Call({ next_block, panic_block, res.clone(), mv$(fcn_val), mv$(values) })); - this->set_cur_block(panic_block); + m_builder.set_cur_block(panic_block); // TODO: Proper panic handling - this->end_block( ::MIR::Terminator::make_Diverge({}) ); + m_builder.end_block( ::MIR::Terminator::make_Diverge({}) ); - this->set_cur_block( next_block ); - this->set_result( node.span(), mv$(res) ); + m_builder.set_cur_block( next_block ); + m_builder.set_result( node.span(), mv$(res) ); } void visit(::HIR::ExprNode_CallValue& node) override @@ -808,7 +1074,7 @@ namespace { { TRACE_FUNCTION_F("_Field"); this->visit_node_ptr(node.m_value); - auto val = this->get_result_lvalue(node.m_value->span()); + auto val = m_builder.get_result_lvalue(node.m_value->span()); unsigned int idx; if( '0' <= node.m_field[0] && node.m_field[0] <= '9' ) { @@ -819,7 +1085,7 @@ namespace { const auto& fields = str.m_data.as_Named(); idx = ::std::find_if( fields.begin(), fields.end(), [&](const auto& x){ return x.first == node.m_field; } ) - fields.begin(); } - this->set_result( node.span(), ::MIR::LValue::make_Field({ box$(val), idx }) ); + m_builder.set_result( node.span(), ::MIR::LValue::make_Field({ box$(val), idx }) ); } void visit(::HIR::ExprNode_Literal& node) override { @@ -833,38 +1099,38 @@ namespace { case ::HIR::CoreType::U32: case ::HIR::CoreType::U64: case ::HIR::CoreType::Usize: - this->set_result(node.span(), ::MIR::RValue( ::MIR::Constant(e.m_value) )); + m_builder.set_result(node.span(), ::MIR::RValue( ::MIR::Constant(e.m_value) )); break; case ::HIR::CoreType::I8: case ::HIR::CoreType::I16: case ::HIR::CoreType::I32: case ::HIR::CoreType::I64: case ::HIR::CoreType::Isize: - this->set_result(node.span(), ::MIR::RValue( ::MIR::Constant( static_cast<int64_t>(e.m_value) ) )); + m_builder.set_result(node.span(), ::MIR::RValue( ::MIR::Constant( static_cast<int64_t>(e.m_value) ) )); break; default: BUG(node.span(), "Integer literal with unexpected type - " << node.m_res_type); } ), (Float, - this->set_result(node.span(), ::MIR::RValue::make_Constant( ::MIR::Constant(e.m_value) )); + m_builder.set_result(node.span(), ::MIR::RValue::make_Constant( ::MIR::Constant(e.m_value) )); ), (Boolean, - this->set_result(node.span(), ::MIR::RValue::make_Constant( ::MIR::Constant(e) )); + m_builder.set_result(node.span(), ::MIR::RValue::make_Constant( ::MIR::Constant(e) )); ), (String, - this->set_result(node.span(), ::MIR::RValue::make_Constant( ::MIR::Constant(e) )); + m_builder.set_result(node.span(), ::MIR::RValue::make_Constant( ::MIR::Constant(e) )); ), (ByteString, auto v = mv$( *reinterpret_cast< ::std::vector<uint8_t>*>( &e) ); - this->set_result(node.span(), ::MIR::RValue::make_Constant( ::MIR::Constant(mv$(v)) )); + m_builder.set_result(node.span(), ::MIR::RValue::make_Constant( ::MIR::Constant(mv$(v)) )); ) ) } void visit(::HIR::ExprNode_UnitVariant& node) override { TRACE_FUNCTION_F("_UnitVariant"); - this->set_result( node.span(), ::MIR::RValue::make_Struct({ + m_builder.set_result( node.span(), ::MIR::RValue::make_Struct({ node.m_path.clone(), {} }) ); @@ -872,12 +1138,12 @@ namespace { void visit(::HIR::ExprNode_PathValue& node) override { TRACE_FUNCTION_F("_PathValue - " << node.m_path); - this->set_result( node.span(), ::MIR::LValue::make_Static(node.m_path.clone()) ); + m_builder.set_result( node.span(), ::MIR::LValue::make_Static(node.m_path.clone()) ); } void visit(::HIR::ExprNode_Variable& node) override { TRACE_FUNCTION_F("_Variable - " << node.m_name << " #" << node.m_slot); - this->set_result( node.span(), ::MIR::LValue::make_Variable(node.m_slot) ); + m_builder.set_result( node.span(), ::MIR::LValue::make_Variable(node.m_slot) ); } void visit(::HIR::ExprNode_StructLiteral& node) override @@ -887,7 +1153,7 @@ namespace { if( node.m_base_value ) { this->visit_node_ptr(node.m_base_value); - base_val = this->get_result_lvalue(node.m_base_value->span()); + base_val = m_builder.get_result_lvalue(node.m_base_value->span()); } const ::HIR::t_struct_fields* fields_ptr = nullptr; @@ -919,7 +1185,7 @@ namespace { assert( !values_set[idx] ); values_set[idx] = true; this->visit_node_ptr(ent.second); - values.at(idx) = this->lvalue_or_temp( ent.second->m_res_type, this->get_result(ent.second->span()) ); + values.at(idx) = m_builder.lvalue_or_temp( ent.second->m_res_type, m_builder.get_result(ent.second->span()) ); } for(unsigned int i = 0; i < values.size(); i ++) { @@ -932,12 +1198,12 @@ namespace { else { // Drop unused part of the base if( node.m_base_value) { - this->push_stmt_drop( ::MIR::LValue::make_Field({ box$( base_val.clone() ), i }) ); + m_builder.push_stmt_drop( ::MIR::LValue::make_Field({ box$( base_val.clone() ), i }) ); } } } - this->set_result( node.span(), ::MIR::RValue::make_Struct({ + m_builder.set_result( node.span(), ::MIR::RValue::make_Struct({ node.m_path.clone(), mv$(values) }) ); @@ -951,10 +1217,10 @@ namespace { for(auto& arg : node.m_vals) { this->visit_node_ptr(arg); - values.push_back( this->lvalue_or_temp( arg->m_res_type, this->get_result(arg->span()) ) ); + values.push_back( m_builder.lvalue_or_temp( arg->m_res_type, m_builder.get_result(arg->span()) ) ); } - this->set_result( node.span(), ::MIR::RValue::make_Tuple({ + m_builder.set_result( node.span(), ::MIR::RValue::make_Tuple({ mv$(values) }) ); } @@ -967,10 +1233,10 @@ namespace { for(auto& arg : node.m_vals) { this->visit_node_ptr(arg); - values.push_back( this->lvalue_or_temp( arg->m_res_type, this->get_result(arg->span()) ) ); + values.push_back( m_builder.lvalue_or_temp( arg->m_res_type, m_builder.get_result(arg->span()) ) ); } - this->set_result( node.span(), ::MIR::RValue::make_Array({ + m_builder.set_result( node.span(), ::MIR::RValue::make_Array({ mv$(values) }) ); } @@ -979,9 +1245,9 @@ namespace { { TRACE_FUNCTION_F("_ArraySized"); this->visit_node_ptr( node.m_val ); - auto value = this->lvalue_or_temp( node.m_val->m_res_type, this->get_result(node.m_val->span()) ); + auto value = m_builder.lvalue_or_temp( node.m_val->m_res_type, m_builder.get_result(node.m_val->span()) ); - this->set_result( node.span(), ::MIR::RValue::make_SizedArray({ + m_builder.set_result( node.span(), ::MIR::RValue::make_SizedArray({ mv$(value), static_cast<unsigned int>(node.m_size_val) }) ); |