summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/include/tagged_union.hpp2
-rw-r--r--src/main.cpp2
-rw-r--r--src/mir/from_hir.cpp548
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)
}) );