summaryrefslogtreecommitdiff
path: root/src/mir/from_hir.hpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/mir/from_hir.hpp')
-rw-r--r--src/mir/from_hir.hpp76
1 files changed, 75 insertions, 1 deletions
diff --git a/src/mir/from_hir.hpp b/src/mir/from_hir.hpp
index c5fd105c..d4690936 100644
--- a/src/mir/from_hir.hpp
+++ b/src/mir/from_hir.hpp
@@ -10,9 +10,38 @@
#include <hir/type.hpp>
#include <hir/expr.hpp> // for ExprNode_Match
+class MirBuilder;
+
+class ScopeHandle
+{
+ friend class MirBuilder;
+
+ const MirBuilder& m_builder;
+ unsigned int idx;
+
+ ScopeHandle(const MirBuilder& builder, unsigned int idx):
+ m_builder(builder),
+ idx(idx)
+ {
+ }
+public:
+ ScopeHandle(const ScopeHandle& x) = delete;
+ ScopeHandle(ScopeHandle&& x):
+ m_builder(x.m_builder),
+ idx(x.idx)
+ {
+ x.idx = ~0;
+ }
+ ScopeHandle& operator=(const ScopeHandle& x) = delete;
+ ScopeHandle& operator=(ScopeHandle&& x) = delete;
+ ~ScopeHandle();
+};
+
/// Helper class to construct MIR
class MirBuilder
{
+ friend class ScopeHandle;
+
::MIR::Function& m_output;
unsigned int m_current_block;
@@ -20,15 +49,41 @@ class MirBuilder
::MIR::RValue m_result;
bool m_result_valid;
+
+ ::std::vector<bool> variables_valid;
+ ::std::vector<bool> temporaries_valid;
+
+ struct ScopeDef
+ {
+ bool complete = false;
+ ::std::vector<unsigned int> variables; // Variables to be dropped at the end of this scope
+ ::std::vector<unsigned int> temporaries; // Temporaries introduced during this scope
+
+ bool is_conditional = false;
+ #if 0
+ ::std::vector<bool> moved_vars; // Bitmap of variables moved in the current branch
+ ::std::vector<bool> all_moved_vars; // Bitmap of variables moved in at least one branch
+ ::std::vector<bool> all_unmoved_vars; // Bitmap of variables NOT moved in at least one branch
+ #endif
+ };
+
+ ::std::vector<ScopeDef> m_scopes;
+ ::std::vector<unsigned int> m_scope_stack;
+ ScopeHandle m_fcn_scope;
public:
MirBuilder(::MIR::Function& output):
m_output(output),
m_block_active(false),
- m_result_valid(false)
+ m_result_valid(false),
+ m_fcn_scope(*this, 0)
{
set_cur_block( new_bb_unlinked() );
+ m_scopes.push_back( ScopeDef {} );
+ m_scope_stack.push_back( 0 );
}
+ ~MirBuilder();
+ // - Values
::MIR::LValue new_temporary(const ::HIR::TypeRef& ty);
::MIR::LValue lvalue_or_temp(const ::HIR::TypeRef& ty, ::MIR::RValue val);
@@ -39,9 +94,13 @@ public:
::MIR::LValue get_result_lvalue(const Span& sp);
void set_result(const Span& sp, ::MIR::RValue val);
+ // - Statements
+ // Push an assignment. NOTE: This also marks the rvalue as moved
void push_stmt_assign(::MIR::LValue dst, ::MIR::RValue val);
+ // Push a drop (likely only used by scope cleanup)
void push_stmt_drop(::MIR::LValue val);
+ // - Block management
bool block_active() const {
return m_block_active;
}
@@ -52,6 +111,21 @@ public:
::MIR::BasicBlockId new_bb_linked();
::MIR::BasicBlockId new_bb_unlinked();
+
+ // --- Scopes ---
+ /// `is_conditional`: If true, this scope is the contents of a conditional branch of the parent scope
+ ScopeHandle new_scope(const Span& sp, bool is_conditional=false);
+ void terminate_scope(const Span& sp, ScopeHandle );
+ void terminate_scope_early(const Span& sp, const ScopeHandle& );
+
+ const ScopeHandle& fcn_scope() const {
+ return m_fcn_scope;
+ }
+
+private:
+ void drop_scope_values(const ScopeDef& sd);
+ // Helper - Marks a variable/... as moved (and checks if the move is valid)
+ void moved_lvalue(const ::MIR::LValue& lv);
};
class MirConverter: