summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJohn Hodge <tpg@mutabah.net>2016-08-24 09:35:35 +0800
committerJohn Hodge <tpg@mutabah.net>2016-08-24 09:35:35 +0800
commit781e7852dafeef9e807648db3d3ce9b853490661 (patch)
tree77f810973eb02693cddc852d06813f29bf18d46d
parent262563ff10b0c2f34649e5177ee8673cc874ae85 (diff)
downloadmrust-781e7852dafeef9e807648db3d3ce9b853490661.tar.gz
HIR Expand - Add a reborrow pass (inserts &mut* on by-value &mut
-rw-r--r--Makefile1
-rw-r--r--src/hir_expand/main_bindings.hpp1
-rw-r--r--src/hir_expand/reborrow.cpp184
-rw-r--r--src/include/span.hpp2
-rw-r--r--src/main.cpp3
-rw-r--r--src/span.cpp6
6 files changed, 197 insertions, 0 deletions
diff --git a/Makefile b/Makefile
index 9d4383d2..3d219bea 100644
--- a/Makefile
+++ b/Makefile
@@ -62,6 +62,7 @@ OBJ += hir_typeck/expr_visit.o
OBJ += hir_typeck/expr_cs.o
OBJ += hir_typeck/expr_check.o
OBJ += hir_expand/annotate_value_usage.o hir_expand/closures.o hir_expand/ufcs_everything.o
+ OBJ += hir_expand/reborrow.o
OBJ += mir/mir.o mir/mir_ptr.o
OBJ += mir/dump.o
OBJ += mir/from_hir.o mir/from_hir_match.o mir/mir_builder.o
diff --git a/src/hir_expand/main_bindings.hpp b/src/hir_expand/main_bindings.hpp
index 085673fe..5de002be 100644
--- a/src/hir_expand/main_bindings.hpp
+++ b/src/hir_expand/main_bindings.hpp
@@ -9,3 +9,4 @@ namespace HIR {
extern void HIR_Expand_AnnotateUsage(::HIR::Crate& crate);
extern void HIR_Expand_Closures(::HIR::Crate& crate);
extern void HIR_Expand_UfcsEverything(::HIR::Crate& crate);
+extern void HIR_Expand_Reborrows(::HIR::Crate& crate);
diff --git a/src/hir_expand/reborrow.cpp b/src/hir_expand/reborrow.cpp
new file mode 100644
index 00000000..449cb52a
--- /dev/null
+++ b/src/hir_expand/reborrow.cpp
@@ -0,0 +1,184 @@
+/*
+ * MRustC - Rust Compiler
+ * - By John Hodge (Mutabah/thePowersGang)
+ *
+ * hir_expand/reborrow.cpp
+ * - Insert reborrows when a &mut would be moved
+ */
+#include <hir/visitor.hpp>
+#include <hir/expr.hpp>
+#include <hir_typeck/static.hpp>
+#include <algorithm>
+#include "main_bindings.hpp"
+
+namespace {
+ inline HIR::ExprNodeP mk_exprnodep(HIR::ExprNode* en, ::HIR::TypeRef ty){ en->m_res_type = mv$(ty); return HIR::ExprNodeP(en); }
+}
+#define NEWNODE(TY, CLASS, ...) mk_exprnodep(new HIR::ExprNode_##CLASS(__VA_ARGS__), TY)
+
+namespace {
+
+ class ExprVisitor_Mutate:
+ public ::HIR::ExprVisitorDef
+ {
+ const ::HIR::Crate& m_crate;
+ ::HIR::ExprNodeP m_replacement;
+
+ public:
+ ExprVisitor_Mutate(const ::HIR::Crate& crate):
+ m_crate(crate)
+ {
+ }
+ void visit_node_ptr(::HIR::ExprPtr& root) {
+ const auto& node_ref = *root;
+ const char* node_ty = typeid(node_ref).name();
+ TRACE_FUNCTION_FR(&*root << " " << node_ty << " : " << root->m_res_type, node_ty);
+ root->visit(*this);
+ if( m_replacement ) {
+ auto usage = root->m_usage;
+ const auto* ptr = m_replacement.get();
+ DEBUG("=> REPLACE " << ptr << " " << typeid(*ptr).name());
+ root.reset( m_replacement.release() );
+ root->m_usage = usage;
+ }
+ }
+
+ void visit_node_ptr(::HIR::ExprNodeP& node) override {
+ const auto& node_ref = *node;
+ const char* node_ty = typeid(node_ref).name();
+ TRACE_FUNCTION_FR(&*node << " " << node_ty << " : " << node->m_res_type, node_ty);
+ assert( node );
+ node->visit(*this);
+ if( m_replacement ) {
+ auto usage = node->m_usage;
+ const auto* ptr = m_replacement.get();
+ DEBUG("=> REPLACE " << ptr << " " << typeid(*ptr).name());
+ node = mv$(m_replacement);
+ node->m_usage = usage;
+ }
+ }
+
+ ::HIR::ExprNodeP do_reborrow(::HIR::ExprNodeP node_ptr)
+ {
+ TU_IFLET( ::HIR::TypeRef::Data, node_ptr->m_res_type.m_data, Borrow, e,
+ if( e.type == ::HIR::BorrowType::Unique )
+ {
+ if( dynamic_cast< ::HIR::ExprNode_Index*>(node_ptr.get())
+ || dynamic_cast< ::HIR::ExprNode_Variable*>(node_ptr.get())
+ || dynamic_cast< ::HIR::ExprNode_Field*>(node_ptr.get())
+ || dynamic_cast< ::HIR::ExprNode_Deref*>(node_ptr.get())
+ )
+ {
+ DEBUG("Insert reborrow - " << node_ptr->span() << " - type=" << node_ptr->m_res_type);
+ auto sp = node_ptr->span();
+ auto ty_mut = node_ptr->m_res_type.clone();
+ auto ty = e.inner->clone();
+ node_ptr = NEWNODE(mv$(ty_mut), Borrow, sp, ::HIR::BorrowType::Unique,
+ NEWNODE(mv$(ty), Deref, sp, mv$(node_ptr))
+ );
+ }
+ }
+ )
+ return node_ptr;
+ }
+
+ void visit(::HIR::ExprNode_Assign& node) override {
+ node.m_value = do_reborrow(mv$(node.m_value));
+ }
+ void visit(::HIR::ExprNode_CallPath& node) override {
+ for(auto& arg : node.m_args)
+ {
+ arg = do_reborrow(mv$(arg));
+ }
+ }
+ void visit(::HIR::ExprNode_CallValue& node) override {
+ for(auto& arg : node.m_args)
+ {
+ arg = do_reborrow(mv$(arg));
+ }
+ }
+ void visit(::HIR::ExprNode_CallMethod& node) override {
+ for(auto& arg : node.m_args)
+ {
+ arg = do_reborrow(mv$(arg));
+ }
+ }
+ };
+ class OuterVisitor:
+ public ::HIR::Visitor
+ {
+ const ::HIR::Crate& m_crate;
+ public:
+ OuterVisitor(const ::HIR::Crate& crate):
+ m_crate(crate)
+ {
+ }
+
+ // NOTE: This is left here to ensure that any expressions that aren't handled by higher code cause a failure
+ void visit_expr(::HIR::ExprPtr& exp) override {
+ BUG(Span(), "visit_expr hit in OuterVisitor");
+ }
+
+ void visit_type(::HIR::TypeRef& ty) override
+ {
+ TU_IFLET(::HIR::TypeRef::Data, ty.m_data, Array, e,
+ this->visit_type( *e.inner );
+ DEBUG("Array size " << ty);
+ if( e.size ) {
+ ExprVisitor_Mutate ev(m_crate);
+ ev.visit_node_ptr( e.size );
+ }
+ )
+ else {
+ ::HIR::Visitor::visit_type(ty);
+ }
+ }
+ // ------
+ // Code-containing items
+ // ------
+ void visit_function(::HIR::ItemPath p, ::HIR::Function& item) override {
+ //auto _ = this->m_ms.set_item_generics(item.m_params);
+ if( item.m_code )
+ {
+ DEBUG("Function code " << p);
+ ExprVisitor_Mutate ev(m_crate);
+ ev.visit_node_ptr( item.m_code );
+ }
+ else
+ {
+ DEBUG("Function code " << p << " (none)");
+ }
+ }
+ void visit_static(::HIR::ItemPath p, ::HIR::Static& item) override {
+ if( item.m_value )
+ {
+ ExprVisitor_Mutate ev(m_crate);
+ ev.visit_node_ptr(item.m_value);
+ }
+ }
+ void visit_constant(::HIR::ItemPath p, ::HIR::Constant& item) override {
+ if( item.m_value )
+ {
+ ExprVisitor_Mutate ev(m_crate);
+ ev.visit_node_ptr(item.m_value);
+ }
+ }
+ void visit_enum(::HIR::ItemPath p, ::HIR::Enum& item) override {
+ for(auto& var : item.m_variants)
+ {
+ TU_IFLET(::HIR::Enum::Variant, var.second, Value, e,
+ DEBUG("Enum value " << p << " - " << var.first);
+
+ ExprVisitor_Mutate ev(m_crate);
+ ev.visit_node_ptr(e);
+ )
+ }
+ }
+ };
+} // namespace
+
+void HIR_Expand_Reborrows(::HIR::Crate& crate)
+{
+ OuterVisitor ov(crate);
+ ov.visit_crate( crate );
+}
diff --git a/src/include/span.hpp b/src/include/span.hpp
index 35d59f42..81ccd179 100644
--- a/src/include/span.hpp
+++ b/src/include/span.hpp
@@ -51,6 +51,8 @@ struct Span
void error(ErrorType tag, ::std::function<void(::std::ostream&)> msg) const;
void warning(WarningType tag, ::std::function<void(::std::ostream&)> msg) const;
void note(::std::function<void(::std::ostream&)> msg) const;
+
+ friend ::std::ostream& operator<<(::std::ostream& os, const Span& sp);
};
template<typename T>
diff --git a/src/main.cpp b/src/main.cpp
index 14fa1c2e..67083720 100644
--- a/src/main.cpp
+++ b/src/main.cpp
@@ -228,6 +228,9 @@ int main(int argc, char *argv[])
CompilePhaseV("Expand HIR Calls", [&]() {
HIR_Expand_UfcsEverything(*hir_crate);
});
+ CompilePhaseV("Expand HIR Reborrows", [&]() {
+ HIR_Expand_Reborrows(*hir_crate);
+ });
// - Ensure that typeck worked (including Fn trait call insertion etc)
CompilePhaseV("Typecheck Expressions (validate)", [&]() {
Typecheck_Expressions_Validate(*hir_crate);
diff --git a/src/span.cpp b/src/span.cpp
index e74fb0d4..29d7201b 100644
--- a/src/span.cpp
+++ b/src/span.cpp
@@ -62,3 +62,9 @@ void Span::note(::std::function<void(::std::ostream&)> msg) const {
::std::cerr << ::std::endl;
//abort();
}
+
+::std::ostream& operator<<(::std::ostream& os, const Span& sp)
+{
+ os << sp.filename << ":" << sp.start_line;
+ return os;
+}