diff options
author | John Hodge <tpg@ucc.asn.au> | 2017-02-25 12:07:12 +0800 |
---|---|---|
committer | John Hodge <tpg@ucc.asn.au> | 2017-02-25 12:07:12 +0800 |
commit | 8068936c1900453fdcbb74c34ed228519ac4e06b (patch) | |
tree | 2e0847a2b7a0378f49153e035bf8f7ca135ab4ce | |
parent | cb04e0ba3611deff03566eb035b2c35b4b8890f9 (diff) | |
download | mrust-8068936c1900453fdcbb74c34ed228519ac4e06b.tar.gz |
MIR Gen - Use MIR::Param (and associated changes)
-rw-r--r-- | src/hir_expand/const_eval_full.cpp | 4 | ||||
-rw-r--r-- | src/hir_typeck/common.hpp | 30 | ||||
-rw-r--r-- | src/hir_typeck/static.cpp | 84 | ||||
-rw-r--r-- | src/hir_typeck/static.hpp | 11 | ||||
-rw-r--r-- | src/mir/from_hir.cpp | 26 | ||||
-rw-r--r-- | src/mir/from_hir.hpp | 2 | ||||
-rw-r--r-- | src/mir/helpers.cpp | 39 | ||||
-rw-r--r-- | src/mir/helpers.hpp | 3 | ||||
-rw-r--r-- | src/mir/mir_builder.cpp | 23 | ||||
-rw-r--r-- | src/mir/optimise.cpp | 33 | ||||
-rw-r--r-- | src/trans/codegen_c.cpp | 35 |
11 files changed, 253 insertions, 37 deletions
diff --git a/src/hir_expand/const_eval_full.cpp b/src/hir_expand/const_eval_full.cpp index a361ce59..3bdec96f 100644 --- a/src/hir_expand/const_eval_full.cpp +++ b/src/hir_expand/const_eval_full.cpp @@ -750,7 +750,7 @@ namespace { // Call by invoking evaluate_constant on the function { TRACE_FUNCTION_F("Call const fn " << fcnp << " args={ " << call_args << " }"); - dst = evaluate_constant(sp, resolve, newval_state, FMT_CB(ss, ss << fcnp;), fcn.m_code, fcn_ms, mv$(call_args)); + dst = evaluate_constant(sp, resolve, newval_state, FMT_CB(ss, ss << fcnp;), fcn.m_code, mv$(fcn_ms), mv$(call_args)); } DEBUG("= " << dst); @@ -763,7 +763,7 @@ namespace { ::HIR::Literal evaluate_constant(const Span& sp, const StaticTraitResolve& resolve, NewvalState newval_state, FmtLambda name, const ::HIR::ExprPtr& expr, MonomorphState ms, ::std::vector< ::HIR::Literal> args) { if( expr.m_mir ) { - return evaluate_constant_mir(sp, resolve, mv$(newval_state), name, *expr.m_mir, ms, mv$(args)); + return evaluate_constant_mir(sp, resolve, mv$(newval_state), name, *expr.m_mir, mv$(ms), mv$(args)); } else { BUG(sp, "Attempting to evaluate constant expression with no associated code"); diff --git a/src/hir_typeck/common.hpp b/src/hir_typeck/common.hpp index 40e7e73c..54d9b038 100644 --- a/src/hir_typeck/common.hpp +++ b/src/hir_typeck/common.hpp @@ -45,6 +45,36 @@ struct MonomorphState const ::HIR::PathParams* pp_impl; const ::HIR::PathParams* pp_method; + ::HIR::PathParams pp_impl_data; + + MonomorphState(): + self_ty(nullptr), + pp_impl(nullptr), + pp_method(nullptr) + { + } + MonomorphState(MonomorphState&& x): + MonomorphState() + { + *this = ::std::move(x); + } + + MonomorphState& operator=(MonomorphState&& x) { + this->self_ty = x.self_ty; + this->pp_impl = (x.pp_impl == &x.pp_impl_data ? &this->pp_impl_data : x.pp_impl); + this->pp_method = x.pp_method; + this->pp_impl_data = ::std::move(x.pp_impl_data); + return *this; + } + MonomorphState clone() const { + MonomorphState rv; + rv.self_ty = this->self_ty; + rv.pp_impl = (this->pp_impl == &this->pp_impl_data ? &rv.pp_impl_data : this->pp_impl); + rv.pp_method = this->pp_method; + rv.pp_impl_data = this->pp_impl_data.clone(); + return rv; + } + t_cb_generic get_cb(const Span& sp) const; ::HIR::TypeRef monomorph(const Span& sp, const ::HIR::TypeRef& ty, bool allow_infer=true) const { diff --git a/src/hir_typeck/static.cpp b/src/hir_typeck/static.cpp index d719ba22..5fec2477 100644 --- a/src/hir_typeck/static.cpp +++ b/src/hir_typeck/static.cpp @@ -1410,3 +1410,87 @@ const ::HIR::TypeRef* StaticTraitResolve::is_type_phantom_data(const ::HIR::Type // TODO: Properly assert? return &pe.m_params.m_types.at(0); } + +StaticTraitResolve::ValuePtr StaticTraitResolve::get_value(const Span& sp, const ::HIR::Path& p, MonomorphState& out_params, bool signature_only/*=false*/) const +{ + out_params = MonomorphState {}; + TU_MATCHA( (p.m_data), (pe), + (Generic, + out_params.pp_method = &pe.m_params; + const ::HIR::Module& mod = m_crate.get_mod_by_path(sp, pe.m_path, true); + const auto& v = mod.m_value_items.at(pe.m_path.m_components.back()); + TU_MATCHA( (v->ent), (ve), + (Import, BUG(sp, "Module Import");), + (Constant, + return &ve; + ), + (Static, + return &ve; + ), + (Function, + return &ve; + ), + (StructConstant, + TODO(sp, "StructConstant - " << p); + ), + (StructConstructor, + TODO(sp, "StructConstructor - " << p); + ) + ) + throw ""; + ), + (UfcsKnown, + out_params.self_ty = &*pe.type; + out_params.pp_impl = &pe.trait.m_params; + out_params.pp_method = &pe.params; + const ::HIR::Trait& tr = m_crate.get_trait_by_path(sp, pe.trait.m_path); + if( signature_only ) + { + const ::HIR::TraitValueItem& v = tr.m_values.at(pe.item); + TU_MATCHA( (v), (ve), + (Constant, return &ve; ), + (Static, return &ve; ), + (Function, return &ve; ) + ) + } + else + { + TODO(sp, "Search for trait impl"); + } + throw ""; + ), + (UfcsInherent, + out_params.self_ty = &*pe.type; + out_params.pp_impl = &out_params.pp_impl_data; + out_params.pp_method = &pe.params; + ValuePtr rv; + m_crate.find_type_impls(*pe.type, [](const auto&x)->const auto& { return x; }, [&](const auto& impl) { + DEBUG("Found impl" << impl.m_params.fmt_args() << " " << impl.m_type); + // TODO: Populate pp_impl + { + auto fit = impl.m_methods.find(pe.item); + if( fit != impl.m_methods.end() ) + { + DEBUG("- Contains method, good"); + rv = ValuePtr { &fit->second.data }; + return true; + } + } + { + auto it = impl.m_constants.find(pe.item); + if( it != impl.m_constants.end() ) + { + rv = ValuePtr { &it->second.data }; + return true; + } + } + return false; + }); + return rv; + ), + (UfcsUnknown, + BUG(sp, "UfcsUnknown - " << p); + ) + ) + throw ""; +} diff --git a/src/hir_typeck/static.hpp b/src/hir_typeck/static.hpp index 46dcd1a1..cde9797c 100644 --- a/src/hir_typeck/static.hpp +++ b/src/hir_typeck/static.hpp @@ -180,5 +180,16 @@ public: const ::HIR::TypeRef* is_type_owned_box(const ::HIR::TypeRef& ty) const; const ::HIR::TypeRef* is_type_phantom_data(const ::HIR::TypeRef& ty) const; + + + TAGGED_UNION(ValuePtr, NotFound, + (NotFound, struct{}), + (Constant, const ::HIR::Constant*), + (Static, const ::HIR::Static*), + (Function, const ::HIR::Function*) + ); + + /// `signature_only` - Returns a pointer to an item with the correct signature, not the actual implementation (faster) + ValuePtr get_value(const Span& sp, const ::HIR::Path& p, MonomorphState& out_params, bool signature_only=false) const; }; diff --git a/src/mir/from_hir.cpp b/src/mir/from_hir.cpp index 17c44e93..722e3aa1 100644 --- a/src/mir/from_hir.cpp +++ b/src/mir/from_hir.cpp @@ -1493,7 +1493,7 @@ namespace { for(auto& arg : node.m_args) { this->visit_node_ptr(arg); - values.push_back( m_builder.get_result_in_lvalue(arg->span(), arg->m_res_type) ); + values.push_back( m_builder.get_result_in_param(arg->span(), arg->m_res_type) ); } unsigned int variant_index = ~0u; @@ -1527,7 +1527,7 @@ namespace { if( args.size() == 1 ) { - values.push_back( m_builder.get_result_in_lvalue(arg->span(), arg->m_res_type, /*allow_missing_value=*/true) ); + values.push_back( m_builder.get_result_in_param(arg->span(), arg->m_res_type, /*allow_missing_value=*/true) ); } else { @@ -1940,10 +1940,18 @@ namespace { values_set[idx] = true; this->visit_node_ptr(valnode); - // NOTE: Have to allocate a new temporary because ordering matters - auto tmp = m_builder.new_temporary(valnode->m_res_type); - m_builder.push_stmt_assign( valnode->span(), tmp.clone(), m_builder.get_result(valnode->span()) ); - values.at(idx) = mv$(tmp); + auto res = m_builder.get_result(valnode->span()); + if( auto* e = res.opt_Constant() ) + { + values.at(idx) = mv$(*e); + } + else + { + // NOTE: Have to allocate a new temporary because ordering matters + auto tmp = m_builder.new_temporary(valnode->m_res_type); + m_builder.push_stmt_assign( valnode->span(), tmp.clone(), mv$(res) ); + values.at(idx) = mv$(tmp); + } } for(unsigned int i = 0; i < values.size(); i ++) { @@ -1991,7 +1999,7 @@ namespace { for(auto& arg : node.m_vals) { this->visit_node_ptr(arg); - values.push_back( m_builder.lvalue_or_temp( arg->span(), arg->m_res_type, m_builder.get_result(arg->span()) ) ); + values.push_back( m_builder.get_result_in_param(arg->span(), arg->m_res_type) ); } m_builder.set_result( node.span(), ::MIR::RValue::make_Tuple({ @@ -2007,7 +2015,7 @@ namespace { for(auto& arg : node.m_vals) { this->visit_node_ptr(arg); - values.push_back( m_builder.lvalue_or_temp( arg->span(), arg->m_res_type, m_builder.get_result(arg->span()) ) ); + values.push_back( m_builder.get_result_in_param(arg->span(), arg->m_res_type) ); } m_builder.set_result( node.span(), ::MIR::RValue::make_Array({ @@ -2019,7 +2027,7 @@ namespace { { TRACE_FUNCTION_F("_ArraySized"); this->visit_node_ptr( node.m_val ); - auto value = m_builder.lvalue_or_temp( node.span(), node.m_val->m_res_type, m_builder.get_result(node.m_val->span()) ); + auto value = m_builder.get_result_in_param(node.span(), node.m_val->m_res_type); m_builder.set_result( node.span(), ::MIR::RValue::make_SizedArray({ mv$(value), diff --git a/src/mir/from_hir.hpp b/src/mir/from_hir.hpp index c687d275..c8d34151 100644 --- a/src/mir/from_hir.hpp +++ b/src/mir/from_hir.hpp @@ -166,6 +166,8 @@ public: ::MIR::LValue get_result_unwrap_lvalue(const Span& sp); /// Obtains the result, copying into a temporary if required ::MIR::LValue get_result_in_lvalue(const Span& sp, const ::HIR::TypeRef& ty, bool allow_missing_value=false); + /// Obtains a result in a param (or a lvalue) + ::MIR::Param get_result_in_param(const Span& sp, const ::HIR::TypeRef& ty, bool allow_missing_value=false); // - Statements // Push an assignment. NOTE: This also marks the rvalue as moved diff --git a/src/mir/helpers.cpp b/src/mir/helpers.cpp index 9750b978..9c2107ab 100644 --- a/src/mir/helpers.cpp +++ b/src/mir/helpers.cpp @@ -225,6 +225,45 @@ const ::HIR::TypeRef& ::MIR::TypeResolve::get_lvalue_type(::HIR::TypeRef& tmp, c ) throw ""; } + +::HIR::TypeRef MIR::TypeResolve::get_const_type(const ::MIR::Constant& c) const +{ + TU_MATCHA( (c), (e), + (Int, + return e.t; + ), + (Uint, + return e.t; + ), + (Float, + return e.t; + ), + (Bool, + return ::HIR::CoreType::Bool; + ), + (Bytes, + return ::HIR::TypeRef::new_borrow( ::HIR::BorrowType::Shared, ::HIR::TypeRef::new_array( ::HIR::CoreType::U8, e.size() ) ); + ), + (StaticString, + return ::HIR::TypeRef::new_borrow( ::HIR::BorrowType::Shared, ::HIR::CoreType::Str ); + ), + (Const, + MonomorphState p; + auto v = m_resolve.get_value(this->sp, e.p, p, /*signature_only=*/true); + if( const auto* ve = v.opt_Constant() ) { + const auto& ty = (*ve)->m_type; + MIR_TODO(*this, "Monomorphise type " << ty); + } + else { + MIR_BUG(*this, ""); + } + ), + (ItemAddr, + MIR_TODO(*this, "Get type for constant `" << c << "`"); + ) + ) + throw ""; +} const ::HIR::TypeRef* ::MIR::TypeResolve::is_type_owned_box(const ::HIR::TypeRef& ty) const { return m_resolve.is_type_owned_box(ty); diff --git a/src/mir/helpers.hpp b/src/mir/helpers.hpp index ece20605..e8f52651 100644 --- a/src/mir/helpers.hpp +++ b/src/mir/helpers.hpp @@ -21,6 +21,7 @@ namespace MIR { class Function; class LValue; +class Constant; class BasicBlock; typedef unsigned int BasicBlockId; @@ -96,6 +97,8 @@ public: const ::HIR::TypeRef& get_static_type(::HIR::TypeRef& tmp, const ::HIR::Path& path) const; const ::HIR::TypeRef& get_lvalue_type(::HIR::TypeRef& tmp, const ::MIR::LValue& val) const; + ::HIR::TypeRef get_const_type(const ::MIR::Constant& c) const; + const ::HIR::TypeRef* is_type_owned_box(const ::HIR::TypeRef& ty) const; friend ::std::ostream& operator<<(::std::ostream& os, const TypeResolve& x) { diff --git a/src/mir/mir_builder.cpp b/src/mir/mir_builder.cpp index 13d17d91..aa42cbc1 100644 --- a/src/mir/mir_builder.cpp +++ b/src/mir/mir_builder.cpp @@ -170,6 +170,29 @@ void MirBuilder::define_variable(unsigned int idx) return temp; } } +::MIR::Param MirBuilder::get_result_in_param(const Span& sp, const ::HIR::TypeRef& ty, bool allow_missing_value) +{ + if( allow_missing_value && !block_active() ) + { + return new_temporary(ty); + } + + auto rv = get_result(sp); + if( auto* e = rv.opt_Constant() ) + { + return mv$(*e); + } + else if( auto* e = rv.opt_Use() ) + { + return mv$(*e); + } + else + { + auto temp = new_temporary(ty); + push_stmt_assign( sp, ::MIR::LValue(temp.clone()), mv$(rv) ); + return temp; + } +} void MirBuilder::set_result(const Span& sp, ::MIR::RValue val) { if(m_result_valid) { diff --git a/src/mir/optimise.cpp b/src/mir/optimise.cpp index b29ce728..cb96cba0 100644 --- a/src/mir/optimise.cpp +++ b/src/mir/optimise.cpp @@ -625,13 +625,15 @@ bool MIR_Optimise_Inlining(::MIR::TypeResolve& state, ::MIR::Function& fcn) unsigned int var_base = ~0u; unsigned int df_base = ~0u; + size_t tmp_end = 0; + mutable ::std::vector< ::MIR::Constant > const_assignments; + Cloner(const Span& sp, const ::StaticTraitResolve& resolve, ::MIR::Terminator::Data_Call& te): sp(sp), resolve(resolve), te(te) {} - // TODO: Expand associated types ::HIR::TypeRef monomorph(const ::HIR::TypeRef& ty) const { auto rv = monomorphise_type_with(sp, ty, params.get_cb(sp)); resolve.expand_associated_types(sp, rv); @@ -814,9 +816,13 @@ bool MIR_Optimise_Inlining(::MIR::TypeResolve& state, ::MIR::Function& fcn) return ::MIR::LValue::make_Temporary({se.idx + this->tmp_base}); ), (Argument, - // TODO: If this argument is a literal, need to allocate a - // tmep for it - return this->te.args.at(se.idx).as_LValue().clone(); + const auto& arg = this->te.args.at(se.idx); + if( const auto* e = arg.opt_Constant() ) { + auto tmp = ::MIR::LValue::make_Temporary({ static_cast<unsigned>(this->tmp_end + this->const_assignments.size()) }); + this->const_assignments.push_back( e->clone() ); + return tmp; + } + return arg.as_LValue().clone(); ), (Return, return this->te.ret_val.clone(); @@ -863,7 +869,11 @@ bool MIR_Optimise_Inlining(::MIR::TypeResolve& state, ::MIR::Function& fcn) ::MIR::Param clone_param(const ::MIR::Param& src) const { TU_MATCHA( (src), (se), - (LValue, return clone_lval(se);), + (LValue, + if( se.is_Argument() ) + return this->te.args.at(se.as_Argument().idx).clone(); + return clone_lval(se); + ), (Constant, return clone_constant(se); ) ) throw ""; @@ -872,6 +882,9 @@ bool MIR_Optimise_Inlining(::MIR::TypeResolve& state, ::MIR::Function& fcn) { TU_MATCHA( (src), (se), (Use, + if( se.is_Argument() ) + if( const auto* e = this->te.args.at(se.as_Argument().idx).opt_Constant() ) + return e->clone(); return ::MIR::RValue( this->clone_lval(se) ); ), (Constant, @@ -952,6 +965,7 @@ bool MIR_Optimise_Inlining(::MIR::TypeResolve& state, ::MIR::Function& fcn) cloner.tmp_base = fcn.temporaries.size(); for(const auto& ty : called_mir->temporaries) fcn.temporaries.push_back( cloner.monomorph(ty) ); + cloner.tmp_end = fcn.temporaries.size(); cloner.df_base = fcn.drop_flags.size(); fcn.drop_flags.insert( fcn.drop_flags.end(), called_mir->drop_flags.begin(), called_mir->drop_flags.end() ); cloner.bb_base = fcn.blocks.size(); @@ -963,6 +977,15 @@ bool MIR_Optimise_Inlining(::MIR::TypeResolve& state, ::MIR::Function& fcn) { new_blocks.push_back( cloner.clone_bb(bb) ); } + // > Append new temporaries + for(auto& val : cloner.const_assignments) + { + auto ty = state.get_const_type(val); + auto lv = ::MIR::LValue::make_Temporary({ static_cast<unsigned>(fcn.temporaries.size()) }); + fcn.temporaries.push_back( mv$(ty) ); + new_blocks[0].statements.insert( new_blocks[0].statements.begin(), ::MIR::Statement::make_Assign({ mv$(lv), mv$(val) }) ); + } + cloner.const_assignments.clear(); // Apply fcn.blocks.reserve( fcn.blocks.size() + new_blocks.size() ); diff --git a/src/trans/codegen_c.cpp b/src/trans/codegen_c.cpp index b74589c2..5e365ceb 100644 --- a/src/trans/codegen_c.cpp +++ b/src/trans/codegen_c.cpp @@ -2467,25 +2467,17 @@ namespace { const ::HIR::Literal& get_literal_for_const(const ::HIR::Path& path, ::HIR::TypeRef& ty) { - TU_MATCHA( (path.m_data), (pe), - (Generic, - if( pe.m_params.m_types.size() > 0 ) - MIR_TODO(*m_mir_res, "get_literal_for_const - Paths with generics " << path); - const auto& c = m_crate.get_constant_by_path(Span(), pe.m_path); - ty = c.m_type.clone(); - return c.m_value_res; - ), - (UfcsUnknown, - MIR_BUG(*m_mir_res, "get_literal_for_const - UfcsUnknown " << path); - ), - (UfcsKnown, - MIR_TODO(*m_mir_res, "get_literal_for_const - UfcsKnown " << path); - ), - (UfcsInherent, - MIR_TODO(*m_mir_res, "get_literal_for_const - UfcsInherent " << path); - ) - ) - throw ""; + MonomorphState params; + auto v = m_resolve.get_value(m_mir_res->sp, path, params); + if( const auto* e = v.opt_Constant() ) + { + ty = params.monomorph(m_mir_res->sp, (*e)->m_type); + return (*e)->m_value_res; + } + else + { + MIR_BUG(*m_mir_res, "get_literal_for_const - Not a constant - " << path); + } } void assign_from_literal(::std::function<void()> emit_dst, const ::HIR::TypeRef& ty, const ::HIR::Literal& lit) @@ -2861,11 +2853,12 @@ namespace { ), (Const, // TODO: This should have been eliminated? + // NOTE: GCC hack - statement expressions ::HIR::TypeRef ty; const auto& lit = get_literal_for_const(c.p, ty); - m_of << "({"; emit_ctype(ty, FMT_CB(ss, ss<<"v";)); m_of << ";"; + m_of << "({"; emit_ctype(ty, FMT_CB(ss, ss<<"v";)); m_of << "; "; assign_from_literal([&](){ m_of << "v"; }, ty, lit); - m_of << "v})"; + m_of << "; v;})"; ), (ItemAddr, TU_MATCHA( (c.m_data), (pe), |