summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJohn Hodge <tpg@mutabah.net>2016-08-21 17:35:44 +0800
committerJohn Hodge <tpg@mutabah.net>2016-08-21 17:35:44 +0800
commitd28ef52c6424d04662bf4070d263b2bd10e132a0 (patch)
tree3b8118e8a900736ddeed91874a31a930b2bb2d13
parent18be0631d249ed11a1ee433cfb39583dcc342687 (diff)
downloadmrust-d28ef52c6424d04662bf4070d263b2bd10e132a0.tar.gz
MIR Gen - Include Copy checking
-rw-r--r--src/mir/from_hir.cpp44
-rw-r--r--src/mir/from_hir.hpp7
-rw-r--r--src/mir/mir_builder.cpp106
3 files changed, 138 insertions, 19 deletions
diff --git a/src/mir/from_hir.cpp b/src/mir/from_hir.cpp
index 01eda781..3a85ebbd 100644
--- a/src/mir/from_hir.cpp
+++ b/src/mir/from_hir.cpp
@@ -22,9 +22,7 @@ namespace {
class ExprVisitor_Conv:
public MirConverter
{
- public:
- MirBuilder m_builder;
- private:
+ MirBuilder& m_builder;
const ::std::vector< ::HIR::TypeRef>& m_variable_types;
@@ -37,8 +35,8 @@ namespace {
::std::vector<LoopDesc> m_loop_stack;
public:
- ExprVisitor_Conv(::MIR::Function& output, const ::std::vector< ::HIR::TypeRef>& var_types):
- m_builder(output),
+ ExprVisitor_Conv(MirBuilder& builder, const ::std::vector< ::HIR::TypeRef>& var_types):
+ m_builder(builder),
m_variable_types(var_types)
{
}
@@ -1303,7 +1301,7 @@ namespace {
}
-::MIR::FunctionPointer LowerMIR(const ::HIR::ExprPtr& ptr, const ::std::vector< ::std::pair< ::HIR::Pattern, ::HIR::TypeRef> >& args)
+::MIR::FunctionPointer LowerMIR(const StaticTraitResolve& resolve, const ::HIR::ExprPtr& ptr, const ::std::vector< ::std::pair< ::HIR::Pattern, ::HIR::TypeRef> >& args)
{
TRACE_FUNCTION;
@@ -1312,9 +1310,10 @@ namespace {
for(const auto& t : ptr.m_bindings)
fcn.named_variables.push_back( t.clone() );
- // TODO: Construct builder here and lend to ExprVisitor_Conv
+ // Scope ensures that builder cleanup happens before `fcn` is moved
{
- ExprVisitor_Conv ev { fcn, ptr.m_bindings };
+ MirBuilder builder { resolve, fcn };
+ ExprVisitor_Conv ev { builder, ptr.m_bindings };
// 1. Apply destructuring to arguments
unsigned int i = 0;
@@ -1333,11 +1332,14 @@ namespace {
}
namespace {
+ // TODO: Create visitor that handles setting up a StaticTraitResolve?
class OuterVisitor:
public ::HIR::Visitor
{
+ StaticTraitResolve m_resolve;
public:
- OuterVisitor(const ::HIR::Crate& crate)
+ OuterVisitor(const ::HIR::Crate& crate):
+ m_resolve(crate)
{}
// NOTE: This is left here to ensure that any expressions that aren't handled by higher code cause a failure
@@ -1351,7 +1353,7 @@ namespace {
this->visit_type( *e.inner );
DEBUG("Array size " << ty);
if( e.size ) {
- auto fcn = LowerMIR(e.size, {});
+ auto fcn = LowerMIR(m_resolve, e.size, {});
e.size.m_mir = mv$(fcn);
}
)
@@ -1364,10 +1366,11 @@ namespace {
// Code-containing items
// ------
void visit_function(::HIR::ItemPath p, ::HIR::Function& item) override {
+ auto _ = this->m_resolve.set_item_generics(item.m_params);
if( item.m_code )
{
DEBUG("Function code " << p);
- item.m_code.m_mir = LowerMIR(item.m_code, item.m_args);
+ item.m_code.m_mir = LowerMIR(m_resolve, item.m_code, item.m_args);
}
else
{
@@ -1378,17 +1381,18 @@ namespace {
if( item.m_value )
{
DEBUG("`static` value " << p);
- item.m_value.m_mir = LowerMIR(item.m_value, {});
+ item.m_value.m_mir = LowerMIR(m_resolve, item.m_value, {});
}
}
void visit_constant(::HIR::ItemPath p, ::HIR::Constant& item) override {
if( item.m_value )
{
DEBUG("`const` value " << p);
- item.m_value.m_mir = LowerMIR(item.m_value, {});
+ item.m_value.m_mir = LowerMIR(m_resolve, item.m_value, {});
}
}
void visit_enum(::HIR::ItemPath p, ::HIR::Enum& item) override {
+ //auto _ = this->m_resolve.set_item_generics(item.m_params);
//auto enum_type = ::HIR::TypeRef(::HIR::CoreType::Isize);
for(auto& var : item.m_variants)
{
@@ -1400,6 +1404,20 @@ namespace {
)
}
}
+
+ // Boilerplate
+ void visit_trait(::HIR::ItemPath p, ::HIR::Trait& item) override {
+ auto _ = this->m_resolve.set_impl_generics(item.m_params);
+ ::HIR::Visitor::visit_trait(p, item);
+ }
+ void visit_type_impl(::HIR::TypeImpl& impl) override {
+ auto _ = this->m_resolve.set_impl_generics(impl.m_params);
+ ::HIR::Visitor::visit_type_impl(impl);
+ }
+ void visit_trait_impl(const ::HIR::SimplePath& trait_path, ::HIR::TraitImpl& impl) override {
+ auto _ = this->m_resolve.set_impl_generics(impl.m_params);
+ ::HIR::Visitor::visit_trait_impl(trait_path, impl);
+ }
};
}
diff --git a/src/mir/from_hir.hpp b/src/mir/from_hir.hpp
index f899bc29..47bdfb5d 100644
--- a/src/mir/from_hir.hpp
+++ b/src/mir/from_hir.hpp
@@ -9,6 +9,7 @@
#include "mir.hpp"
#include <hir/type.hpp>
#include <hir/expr.hpp> // for ExprNode_Match
+#include <hir_typeck/static.hpp> // StaticTraitResolve for Copy
class MirBuilder;
@@ -74,6 +75,7 @@ class MirBuilder
{
friend class ScopeHandle;
+ const StaticTraitResolve& m_resolve;
::MIR::Function& m_output;
unsigned int m_current_block;
@@ -95,7 +97,7 @@ class MirBuilder
::std::vector<unsigned int> m_scope_stack;
ScopeHandle m_fcn_scope;
public:
- MirBuilder(::MIR::Function& output);
+ MirBuilder(const StaticTraitResolve& resolve, ::MIR::Function& output);
~MirBuilder();
// - Values
@@ -152,6 +154,9 @@ private:
void complete_scope(ScopeDef& sd);
// Helper - Marks a variable/... as moved (and checks if the move is valid)
void moved_lvalue(const ::MIR::LValue& lv);
+
+ void with_val_type(const ::MIR::LValue& val, ::std::function<void(const ::HIR::TypeRef&)> cb);
+ bool lvalue_is_copy(const ::MIR::LValue& lv);
};
class MirConverter:
diff --git a/src/mir/mir_builder.cpp b/src/mir/mir_builder.cpp
index f3b9c263..893dcffa 100644
--- a/src/mir/mir_builder.cpp
+++ b/src/mir/mir_builder.cpp
@@ -11,7 +11,8 @@
// --------------------------------------------------------------------
// MirBuilder
// --------------------------------------------------------------------
-MirBuilder::MirBuilder(::MIR::Function& output):
+MirBuilder::MirBuilder(const StaticTraitResolve& resolve, ::MIR::Function& output):
+ m_resolve(resolve),
m_output(output),
m_block_active(false),
m_result_valid(false),
@@ -208,10 +209,10 @@ void MirBuilder::push_stmt_assign(::MIR::LValue dst, ::MIR::RValue val)
break;
case VarState::Moved:
case VarState::MaybeMoved:
- // ERROR?
+ // ERROR? Temporaries shouldn't be resassigned after becoming valid
break;
case VarState::Init:
- // ERROR.
+ // ERROR. Temporaries are single-assignment
break;
}
set_temp_state(e.idx, VarState::Init);
@@ -227,11 +228,11 @@ void MirBuilder::push_stmt_assign(::MIR::LValue dst, ::MIR::RValue val)
case VarState::Moved:
break;
case VarState::Dropped:
- // TODO: Is this an error?
+ // TODO: Is this an error? The variable has descoped.
break;
case VarState::Init:
// 1. Must be mut
- // 2. Drop
+ // 2. Drop (if not Copy)
push_stmt_drop( dst.clone() );
break;
case VarState::MaybeMoved:
@@ -247,6 +248,12 @@ void MirBuilder::push_stmt_drop(::MIR::LValue val)
{
ASSERT_BUG(Span(), m_block_active, "Pushing statement with no active block");
ASSERT_BUG(Span(), val.tag() != ::MIR::LValue::TAGDEAD, "");
+
+ if( lvalue_is_copy(val) ) {
+ // Don't emit a drop for Copy values
+ return ;
+ }
+
m_output.blocks.at(m_current_block).statements.push_back( ::MIR::Statement::make_Drop({ ::MIR::eDropKind::DEEP, mv$(val) }) );
}
@@ -448,6 +455,95 @@ void MirBuilder::complete_scope(ScopeDef& sd)
)
}
+void MirBuilder::with_val_type(const ::MIR::LValue& val, ::std::function<void(const ::HIR::TypeRef&)> cb)
+{
+ Span sp;
+ TU_MATCH(::MIR::LValue, (val), (e),
+ (Variable,
+ cb( m_output.named_variables.at(e) );
+ ),
+ (Temporary,
+ cb( m_output.temporaries.at(e.idx) );
+ ),
+ (Argument,
+ TODO(sp, "Argument");
+ ),
+ (Static,
+ TODO(sp, "Static");
+ ),
+ (Return,
+ TODO(sp, "Return");
+ ),
+ (Field,
+ with_val_type(*e.val, [&](const auto& ty){
+ TU_MATCH_DEF( ::HIR::TypeRef::Data, (ty.m_data), (te),
+ (
+ BUG(sp, "");
+ ),
+ (Path,
+ TODO(sp, "Field - Path");
+ ),
+ (Tuple,
+ assert( e.field_index < te.size() );
+ cb( te[e.field_index] );
+ )
+ )
+ });
+ ),
+ (Deref,
+ with_val_type(*e.val, [&](const auto& ty){
+ TU_MATCH_DEF( ::HIR::TypeRef::Data, (ty.m_data), (te),
+ (
+ BUG(sp, "");
+ ),
+ (Pointer,
+ cb(*te.inner);
+ ),
+ (Borrow,
+ cb(*te.inner);
+ )
+ )
+ });
+ ),
+ (Index,
+ with_val_type(*e.val, [&](const auto& ty){
+ TU_MATCH_DEF( ::HIR::TypeRef::Data, (ty.m_data), (te),
+ (
+ BUG(sp, "");
+ ),
+ (Slice,
+ cb(*te.inner);
+ ),
+ (Array,
+ cb(*te.inner);
+ )
+ )
+ });
+ ),
+ (Downcast,
+ with_val_type(*e.val, [&](const auto& ty){
+ TU_MATCH_DEF( ::HIR::TypeRef::Data, (ty.m_data), (te),
+ (
+ BUG(sp, "");
+ ),
+ (Path,
+ TODO(sp, "Downcast - Path");
+ )
+ )
+ });
+ )
+ )
+}
+
+bool MirBuilder::lvalue_is_copy(const ::MIR::LValue& val)
+{
+ int rv = 0;
+ with_val_type(val, [&](const auto& ty){
+ rv = (m_resolve.type_is_copy(ty) ? 2 : 1);
+ });
+ assert(rv != 0);
+ return rv == 2;
+}
VarState MirBuilder::get_variable_state(unsigned int idx) const
{