diff --git a/src/hir/hir.hpp b/src/hir/hir.hpp index f0844580a..6c8385c47 100644 --- a/src/hir/hir.hpp +++ b/src/hir/hir.hpp @@ -173,6 +173,9 @@ class Constant TypeRef m_type; ExprPtr m_value; Literal m_value_res; + + // A cache of monomorphised versions when the `const` depends on generics for its value + mutable ::std::map< ::HIR::Path, Literal> m_monomorph_cache; }; class Function { diff --git a/src/hir_conv/constant_evaluation.cpp b/src/hir_conv/constant_evaluation.cpp index 6838e1861..6067b32fb 100644 --- a/src/hir_conv/constant_evaluation.cpp +++ b/src/hir_conv/constant_evaluation.cpp @@ -16,12 +16,15 @@ #include #include +#include "constant_evaluation.hpp" #include // For handling monomorph of MIR in provided associated constants #define CHECK_DEFER(var) do { if( var.is_Defer() ) { m_rv = ::HIR::Literal::make_Defer({}); return ; } } while(0) namespace { - struct NewvalState { + struct NewvalState + : public HIR::Evaluator::Newval + { const ::HIR::Module& mod; const ::HIR::ItemPath& mod_path; ::std::string name_prefix; @@ -35,7 +38,7 @@ namespace { { } - ::HIR::SimplePath new_static(::HIR::TypeRef type, ::HIR::Literal value) + virtual ::HIR::Path new_static(::HIR::TypeRef type, ::HIR::Literal value) override { auto name = FMT(name_prefix << next_item_idx); next_item_idx ++; @@ -51,23 +54,6 @@ namespace { return rv; } }; - struct Evaluator - { - const Span& root_span; - StaticTraitResolve resolve; - NewvalState nvs; - - Evaluator(const Span& sp, const ::HIR::Crate& crate, NewvalState nvs): - root_span(sp), - resolve(crate), - nvs( ::std::move(nvs) ) - { - } - - ::HIR::Literal evaluate_constant(const ::HIR::ItemPath& ip, const ::HIR::ExprPtr& expr, ::HIR::TypeRef exp, MonomorphState ms={}); - - ::HIR::Literal evaluate_constant_mir(const ::HIR::ItemPath& ip, const ::MIR::Function& fcn, MonomorphState ms, ::HIR::TypeRef exp, ::std::vector< ::HIR::Literal> args); - }; ::HIR::Literal clone_literal(const ::HIR::Literal& v) { @@ -276,6 +262,9 @@ namespace { TODO(sp, "Could not find function for " << path << " - " << rv.tag_str()); } } +} // namespace + +namespace HIR { ::HIR::Literal Evaluator::evaluate_constant_mir(const ::HIR::ItemPath& ip, const ::MIR::Function& fcn, MonomorphState ms, ::HIR::TypeRef exp, ::std::vector< ::HIR::Literal> args) { @@ -417,7 +406,8 @@ namespace { auto& item = const_cast<::HIR::Constant&>(c); // Challenge: Adding items to the module might invalidate an iterator. ::HIR::ItemPath mod_ip { item.m_value.m_state->m_mod_path }; - auto eval = Evaluator { item.m_value.span(), resolve.m_crate, NewvalState { item.m_value.m_state->m_module, mod_ip, FMT(&c << "$") } }; + auto nvs = NewvalState { item.m_value.m_state->m_module, mod_ip, FMT(&c << "$") }; + auto eval = ::HIR::Evaluator { item.m_value.span(), resolve.m_crate, nvs }; DEBUG("- Evaluate " << p); DEBUG("- " << ::HIR::ItemPath(p)); item.m_value_res = eval.evaluate_constant(::HIR::ItemPath(p), item.m_value, item.m_type.clone()); @@ -875,6 +865,9 @@ namespace { BUG(this->root_span, "Attempting to evaluate constant expression with no associated code"); } } +} // namespace HIR + +namespace { void check_lit_type(const Span& sp, const ::HIR::TypeRef& type, ::HIR::Literal& lit) { @@ -1028,7 +1021,8 @@ namespace { }); const auto& template_const = vi.second.as_Constant(); if( template_const.m_value_res.is_Defer() ) { - auto eval = Evaluator { sp, m_crate, NewvalState { *m_mod, *m_mod_path, FMT("impl" << &impl << "$" << vi.first << "$") } }; + auto nvs = NewvalState { *m_mod, *m_mod_path, FMT("impl" << &impl << "$" << vi.first << "$") }; + auto eval = ::HIR::Evaluator { sp, m_crate, nvs }; ::HIR::ExprPtr ep; Trans_Params tp(sp); tp.self_type = ms.self_ty->clone(); @@ -1094,7 +1088,8 @@ namespace { const auto& expr_ptr = *e.size; auto ty_name = FMT("ty_" << &ty << "$"); - auto eval = Evaluator { expr_ptr->span(), m_crate, NewvalState { *m_mod, *m_mod_path, ty_name } }; + auto nvs = NewvalState { *m_mod, *m_mod_path, ty_name }; + auto eval = ::HIR::Evaluator { expr_ptr->span(), m_crate, nvs }; auto val = eval.evaluate_constant(::HIR::ItemPath(*m_mod_path, ty_name.c_str()), expr_ptr, ::HIR::CoreType::Usize); if( !val.is_Integer() ) ERROR(expr_ptr->span(), E0000, "Array size isn't an integer"); @@ -1110,7 +1105,8 @@ namespace { // NOTE: Consteval needed here for MIR match generation to work if( item.m_value || item.m_value.m_mir ) { - auto eval = Evaluator { item.m_value.span(), m_crate, NewvalState { *m_mod, *m_mod_path, FMT(p.get_name() << "$") } }; + auto nvs = NewvalState { *m_mod, *m_mod_path, FMT(p.get_name() << "$") }; + auto eval = ::HIR::Evaluator { item.m_value.span(), m_crate, nvs }; item.m_value_res = eval.evaluate_constant(p, item.m_value, item.m_type.clone(), m_monomorph_state.clone()); check_lit_type(item.m_value.span(), item.m_type, item.m_value_res); @@ -1124,7 +1120,8 @@ namespace { if( item.m_value ) { - auto eval = Evaluator { item.m_value->span(), m_crate, NewvalState { *m_mod, *m_mod_path, FMT(p.get_name() << "$") } }; + auto nvs = NewvalState { *m_mod, *m_mod_path, FMT(p.get_name() << "$") }; + auto eval = ::HIR::Evaluator { item.m_value->span(), m_crate, nvs }; item.m_value_res = eval.evaluate_constant(p, item.m_value, item.m_type.clone()); check_lit_type(item.m_value->span(), item.m_type, item.m_value_res); @@ -1142,7 +1139,8 @@ namespace { { if( var.expr ) { - auto eval = Evaluator { var.expr->span(), m_crate, NewvalState { *m_mod, *m_mod_path, FMT(p.get_name() << "$" << var.name << "$") } }; + auto nvs = NewvalState { *m_mod, *m_mod_path, FMT(p.get_name() << "$" << var.name << "$") }; + auto eval = ::HIR::Evaluator { var.expr->span(), m_crate, nvs }; auto val = eval.evaluate_constant(p, var.expr, ty.clone()); DEBUG("enum variant: " << p << "::" << var.name << " = " << val); i = val.as_Integer(); @@ -1178,7 +1176,8 @@ namespace { void visit(::HIR::ExprNode_ArraySized& node) override { assert( node.m_size ); auto name = FMT("array_" << &node << "$"); - auto eval = Evaluator { node.span(), m_exp.m_crate, NewvalState { *m_exp.m_mod, *m_exp.m_mod_path, name } }; + auto nvs = NewvalState { *m_exp.m_mod, *m_exp.m_mod_path, name }; + auto eval = ::HIR::Evaluator { node.span(), m_exp.m_crate, nvs }; auto val = eval.evaluate_constant( ::HIR::ItemPath(*m_exp.m_mod_path, name.c_str()), node.m_size, ::HIR::CoreType::Usize ); if( !val.is_Integer() ) ERROR(node.span(), E0000, "Array size isn't an integer"); diff --git a/src/trans/codegen_c.cpp b/src/trans/codegen_c.cpp index 373a36a83..08b4f2de5 100644 --- a/src/trans/codegen_c.cpp +++ b/src/trans/codegen_c.cpp @@ -5288,8 +5288,21 @@ namespace { 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; + const auto& hir_const = **e; + ty = params.monomorph(m_mir_res->sp, hir_const.m_type); + if( hir_const.m_value_res.is_Defer() ) + { + // Do some form of lookup of a pre-cached evaluated monomorphised constant + // - Maybe on the `Constant` entry there can be a list of pre-monomorphised values + auto it = hir_const.m_monomorph_cache.find(path); + if( it == hir_const.m_monomorph_cache.end() ) + { + MIR_BUG(*m_mir_res, "Constant with Defer literal and no cached monomorphisation - " << path); + // TODO: Can do the consteval here? + } + return it->second; + } + return hir_const.m_value_res; } else { diff --git a/src/trans/enumerate.cpp b/src/trans/enumerate.cpp index da11386c6..00b938ff4 100644 --- a/src/trans/enumerate.cpp +++ b/src/trans/enumerate.cpp @@ -903,6 +903,10 @@ void Trans_Enumerate_Types(EnumState& state) return blank; } + static void visit_const(TypeVisitor& tv, const Trans_Params& pp, const ::HIR::Function& fcn, const ::MIR::Constant& p) + { + } + static void visit_param(TypeVisitor& tv, const Trans_Params& pp, const ::HIR::Function& fcn, const ::MIR::Param& p) { TU_MATCHA( (p), (e), @@ -910,6 +914,7 @@ void Trans_Enumerate_Types(EnumState& state) H::visit_lvalue(tv, pp, fcn, e); ), (Constant, + H::visit_const(tv, pp, fcn, e); ) ) } @@ -937,6 +942,7 @@ void Trans_Enumerate_Types(EnumState& state) H::visit_lvalue(tv,pp,fcn, re); ), (Constant, + H::visit_const(tv,pp,fcn, re); ), (SizedArray, H::visit_param(tv,pp,fcn, re.val); @@ -1182,14 +1188,14 @@ namespace { return true; } } - //{ - // auto it = impl.m_constants.find(e.item); - // if( it != impl.m_constants.end() ) - // { - // rv = EntPtr { &it->second.data }; - // return true; - // } - //} + { + auto it = impl.m_constants.find(pe->item); + if( it != impl.m_constants.end() ) + { + rv = EntPtr { &it->second.data }; + return true; + } + } return false; }); return rv; @@ -1481,7 +1487,19 @@ void Trans_Enumerate_FillFrom_Path(EnumState& state, const ::HIR::Path& path, co } } TU_ARMA(Constant, e) { - Trans_Enumerate_FillFrom_Literal(state, e->m_value_res, sub_pp); + if( e->m_value_res.is_Defer() ) + { + if( auto* slot = state.rv.add_const(mv$(path_mono)) ) + { + Trans_Enumerate_FillFrom_MIR(state, *e->m_value.m_mir, sub_pp); + slot->ptr = e; + slot->pp = ::std::move(sub_pp); + } + } + else + { + Trans_Enumerate_FillFrom_Literal(state, e->m_value_res, sub_pp); + } } } } @@ -1522,7 +1540,8 @@ void Trans_Enumerate_FillFrom_MIR_Constant(EnumState& state, const ::MIR::Consta (Bytes, ), (StaticString, ), // String (Const, - //Trans_Enumerate_FillFrom_Path(state, ce.p, pp); + // - Check if this constant has a value of Defer + Trans_Enumerate_FillFrom_Path(state, ce.p, pp); ), (ItemAddr, Trans_Enumerate_FillFrom_Path(state, ce, pp); diff --git a/src/trans/monomorphise.cpp b/src/trans/monomorphise.cpp index 0a0b43b5b..cf1014432 100644 --- a/src/trans/monomorphise.cpp +++ b/src/trans/monomorphise.cpp @@ -10,6 +10,7 @@ #include #include #include // Needed for post-monomorph checks and optimisations +#include namespace { ::MIR::LValue monomorph_LValue(const ::StaticTraitResolve& resolve, const Trans_Params& params, const ::MIR::LValue& tpl) @@ -361,8 +362,8 @@ void Trans_Monomorphise_List(const ::HIR::Crate& crate, TransList& list) 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); + //::std::string s = FMT(path); + ::HIR::ItemPath ip(path); MIR_Validate(resolve, ip, *mir, args, ret_type); MIR_Cleanup(resolve, ip, *mir, args, ret_type); MIR_Optimise(resolve, ip, *mir, args, ret_type); @@ -373,5 +374,30 @@ void Trans_Monomorphise_List(const ::HIR::Crate& crate, TransList& list) fcn_ent.second->monomorphised.code = ::std::move(mir); } } + + // Also do constants and statics (stored in where?) + for(auto& ent : list.m_constants) + { + const auto& path = ent.first; + const auto& pp = ent.second->pp; + const auto& c = *ent.second->ptr; + TRACE_FUNCTION_FR(path, path); + auto ty = pp.monomorph(resolve, c.m_type); + // 1. Evaluate the constant + struct Nvs: public ::HIR::Evaluator::Newval + { + ::HIR::Path new_static(::HIR::TypeRef type, ::HIR::Literal value) override { + TODO(Span(), "Create new static in monomorph pass - " << value << " : " << type); + } + } nvs; + auto eval = ::HIR::Evaluator { pp.sp, crate, nvs }; + MonomorphState ms; + ms.self_ty = &pp.self_type; + ms.pp_impl = &pp.pp_impl; + ms.pp_method = &pp.pp_method; + auto new_lit = eval.evaluate_constant(path, c.m_value, ::std::move(ty), ::std::move(ms)); + // 2. Store evaluated HIR::Literal in c.m_monomorph_cache + c.m_monomorph_cache.insert(::std::make_pair( path.clone(), ::std::move(new_lit) )); + } } diff --git a/src/trans/trans_list.cpp b/src/trans/trans_list.cpp index 04e1e9a10..54ae80113 100644 --- a/src/trans/trans_list.cpp +++ b/src/trans/trans_list.cpp @@ -38,6 +38,21 @@ TransList_Static* TransList::add_static(::HIR::Path p) return nullptr; } } +TransList_Const* TransList::add_const(::HIR::Path p) +{ + auto rv = m_constants.insert( ::std::make_pair(mv$(p), nullptr) ); + if( rv.second ) + { + DEBUG("Const " << rv.first->first); + assert( !rv.first->second ); + rv.first->second.reset( new TransList_Const {} ); + return &*rv.first->second; + } + else + { + return nullptr; + } +} t_cb_generic Trans_Params::get_cb() const { diff --git a/src/trans/trans_list.hpp b/src/trans/trans_list.hpp index b58a241d7..df5509251 100644 --- a/src/trans/trans_list.hpp +++ b/src/trans/trans_list.hpp @@ -95,6 +95,7 @@ class TransList TransList_Function* add_function(::HIR::Path p); TransList_Static* add_static(::HIR::Path p); + TransList_Const* add_const(::HIR::Path p); bool add_vtable(::HIR::Path p, Trans_Params pp) { return m_vtables.insert( ::std::make_pair( mv$(p), mv$(pp) ) ).second; }