diff options
Diffstat (limited to 'src/trans')
-rw-r--r-- | src/trans/codegen.cpp | 21 | ||||
-rw-r--r-- | src/trans/enumerate.cpp | 45 | ||||
-rw-r--r-- | src/trans/main_bindings.hpp | 6 | ||||
-rw-r--r-- | src/trans/monomorphise.cpp | 40 | ||||
-rw-r--r-- | src/trans/trans_list.hpp | 7 |
5 files changed, 102 insertions, 17 deletions
diff --git a/src/trans/codegen.cpp b/src/trans/codegen.cpp index 12252465..9e93caba 100644 --- a/src/trans/codegen.cpp +++ b/src/trans/codegen.cpp @@ -168,29 +168,18 @@ void Trans_Codegen(const ::std::string& outfile, const TransOptions& opt, const const auto& pp = ent.second->pp; TRACE_FUNCTION_F(path); DEBUG("FUNCTION CODE " << path); + // `is_extern` is set if there's no HIR (i.e. this function is from an external crate) bool is_extern = ! static_cast<bool>(fcn.m_code); // If this is a provided trait method, it needs to be monomorphised too. bool is_method = ( fcn.m_args.size() > 0 && visit_ty_with(fcn.m_args[0].second, [&](const auto& x){return x == ::HIR::TypeRef("Self",0xFFFF);}) ); if( pp.has_types() || is_method ) { - ::StaticTraitResolve resolve { crate }; - auto ret_type = pp.monomorph(resolve, fcn.m_return); - ::HIR::Function::args_t args; - for(const auto& a : fcn.m_args) - args.push_back(::std::make_pair( ::HIR::Pattern{}, pp.monomorph(resolve, a.second) )); - auto mir = Trans_Monomorphise(resolve, pp, fcn.m_code.m_mir); - ::std::string s = FMT(path); - ::HIR::ItemPath ip(s); - MIR_Validate(resolve, ip, *mir, args, ret_type); - MIR_Cleanup(resolve, ip, *mir, args, ret_type); - MIR_Optimise(resolve, ip, *mir, args, ret_type); - MIR_Validate(resolve, ip, *mir, args, ret_type); + ASSERT_BUG(sp, ent.second->monomorphised.code, "Function that required monomorphisation wasn't monomorphised"); + // TODO: Flag that this should be a weak (or weak-er) symbol? - // - If it's from an external crate, it should be weak - codegen->emit_function_code(path, fcn, ent.second->pp, is_extern, mir); + // - If it's from an external crate, it should be weak, but what about local ones? + codegen->emit_function_code(path, fcn, ent.second->pp, is_extern, ent.second->monomorphised.code); } - // TODO: Detect if the function was a #[inline] function from another crate, and don't emit if that is the case? - // - Emiting is nice, but it should be emitted as a weak symbol else { codegen->emit_function_code(path, fcn, pp, is_extern, fcn.m_code.m_mir); } diff --git a/src/trans/enumerate.cpp b/src/trans/enumerate.cpp index 4c91f5f3..4a6e5767 100644 --- a/src/trans/enumerate.cpp +++ b/src/trans/enumerate.cpp @@ -332,6 +332,51 @@ TransList Trans_Enumerate_Public(::HIR::Crate& crate) return rv; } +void Trans_Enumerate_Cleanup(const ::HIR::Crate& crate, TransList& list) +{ + EnumState state { crate }; + + // TODO: Get a list of "root" functions (e.g. main, public functions, things used by public generics) and re-enumerate based on that. + + // Visit every function used + for(const auto& ent : list.m_functions) + { + if( ent.second->monomorphised.code ) + { + Trans_Enumerate_FillFrom_MIR(state, *ent.second->monomorphised.code, {}); + } + else if( ent.second->ptr->m_code.m_mir ) + { + Trans_Enumerate_FillFrom_MIR(state, *ent.second->ptr->m_code.m_mir, {}); + } + else + { + } + } + + // Remove any item in `list.m_functions` that doesn't appear in `state.rv.m_functions` + for(auto it = list.m_functions.begin(); it != list.m_functions.end();) + { + auto it2 = state.rv.m_functions.find(it->first); + if( it2 == state.rv.m_functions.end() ) + { + DEBUG("Remove " << it->first); + it = list.m_functions.erase(it); + } + else + { + DEBUG("Keep " << it->first); + ++ it; + } + } + + // Sanity check: all items in `state.rv.m_functions` must exist in `list.m_functions` + for(const auto& e : state.rv.m_functions) + { + auto it = list.m_functions.find(e.first); + ASSERT_BUG(Span(), it != list.m_functions.end(), "Enumerate Error - New function appeared after monomorphisation - " << e.first); + } +} /// Common post-processing void Trans_Enumerate_CommonPost_Run(EnumState& state) diff --git a/src/trans/main_bindings.hpp b/src/trans/main_bindings.hpp index d78991d2..46d2cdb1 100644 --- a/src/trans/main_bindings.hpp +++ b/src/trans/main_bindings.hpp @@ -25,8 +25,12 @@ struct TransOptions }; extern TransList Trans_Enumerate_Main(const ::HIR::Crate& crate); -extern TransList Trans_Enumerate_Test(const ::HIR::Crate& crate); // NOTE: This also sets the saveout flags extern TransList Trans_Enumerate_Public(::HIR::Crate& crate); +/// Re-run enumeration on monomorphised functions, removing now-unused items +extern void Trans_Enumerate_Cleanup(const ::HIR::Crate& crate, TransList& list); + +extern void Trans_Monomorphise_List(const ::HIR::Crate& crate, TransList& list); + extern void Trans_Codegen(const ::std::string& outfile, const TransOptions& opt, const ::HIR::Crate& crate, const TransList& list, bool is_executable); diff --git a/src/trans/monomorphise.cpp b/src/trans/monomorphise.cpp index fd05c85b..892cb730 100644 --- a/src/trans/monomorphise.cpp +++ b/src/trans/monomorphise.cpp @@ -6,8 +6,10 @@ * - MIR monomorphisation */ #include "monomorphise.hpp" +#include "hir_typeck/static.hpp" #include <mir/mir.hpp> #include <hir/hir.hpp> +#include <mir/operations.hpp> // Needed for post-monomorph checks and optimisations namespace { ::MIR::LValue monomorph_LValue(const ::StaticTraitResolve& resolve, const Trans_Params& params, const ::MIR::LValue& tpl) @@ -333,3 +335,41 @@ namespace { return ::MIR::FunctionPointer( box$(output).release() ); } + +/// Monomorphise all functions in a TransList +void Trans_Monomorphise_List(const ::HIR::Crate& crate, TransList& list) +{ + ::StaticTraitResolve resolve { crate }; + for(auto& fcn_ent : list.m_functions) + { + const auto& fcn = *fcn_ent.second->ptr; + // Trait methods (which are the only case where `Self` can exist in the argument list at this stage) always need to be monomorphised. + bool is_method = ( fcn.m_args.size() > 0 && visit_ty_with(fcn.m_args[0].second, [&](const auto& x){return x == ::HIR::TypeRef("Self",0xFFFF);}) ); + if(fcn_ent.second->pp.has_types() || is_method) + { + const auto& path = fcn_ent.first; + const auto& pp = fcn_ent.second->pp; + TRACE_FUNCTION_FR(path, path); + + auto mir = Trans_Monomorphise(resolve, fcn_ent.second->pp, fcn.m_code.m_mir); + + // TODO: Should these be moved to their own pass? Potentially not, the extra pass should just be an inlining optimise pass + auto ret_type = pp.monomorph(resolve, fcn.m_return); + ::HIR::Function::args_t args; + for(const auto& a : fcn.m_args) + args.push_back(::std::make_pair( ::HIR::Pattern{}, pp.monomorph(resolve, a.second) )); + + ::std::string s = FMT(path); + ::HIR::ItemPath ip(s); + MIR_Validate(resolve, ip, *mir, args, ret_type); + MIR_Cleanup(resolve, ip, *mir, args, ret_type); + MIR_Optimise(resolve, ip, *mir, args, ret_type); + MIR_Validate(resolve, ip, *mir, args, ret_type); + + fcn_ent.second->monomorphised.ret_ty = ::std::move(ret_type); + fcn_ent.second->monomorphised.arg_tys = ::std::move(args); + fcn_ent.second->monomorphised.code = ::std::move(mir); + } + } +} + diff --git a/src/trans/trans_list.hpp b/src/trans/trans_list.hpp index 2ef876d6..48274f87 100644 --- a/src/trans/trans_list.hpp +++ b/src/trans/trans_list.hpp @@ -41,10 +41,17 @@ struct Trans_Params } }; +struct CachedFunction { + ::HIR::TypeRef ret_ty; + ::HIR::Function::args_t arg_tys; + ::MIR::FunctionPointer code; +}; struct TransList_Function { const ::HIR::Function* ptr; Trans_Params pp; + // If `pp.has_types` is true, the below is valid + CachedFunction monomorphised; }; struct TransList_Static { |