diff options
-rw-r--r-- | src/mir/from_hir.cpp | 44 | ||||
-rw-r--r-- | src/mir/from_hir.hpp | 7 | ||||
-rw-r--r-- | src/mir/mir_builder.cpp | 106 |
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 { |