summaryrefslogtreecommitdiff
path: root/src/trans
diff options
context:
space:
mode:
Diffstat (limited to 'src/trans')
-rw-r--r--src/trans/codegen.cpp21
-rw-r--r--src/trans/enumerate.cpp45
-rw-r--r--src/trans/main_bindings.hpp6
-rw-r--r--src/trans/monomorphise.cpp40
-rw-r--r--src/trans/trans_list.hpp7
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
{