summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/hir/hir.hpp3
-rw-r--r--src/hir_conv/constant_evaluation.cpp51
-rw-r--r--src/trans/codegen_c.cpp17
-rw-r--r--src/trans/enumerate.cpp39
-rw-r--r--src/trans/monomorphise.cpp30
-rw-r--r--src/trans/trans_list.cpp15
-rw-r--r--src/trans/trans_list.hpp1
7 files changed, 116 insertions, 40 deletions
diff --git a/src/hir/hir.hpp b/src/hir/hir.hpp
index f0844580..6c8385c4 100644
--- a/src/hir/hir.hpp
+++ b/src/hir/hir.hpp
@@ -173,6 +173,9 @@ public:
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 6838e186..6067b32f 100644
--- a/src/hir_conv/constant_evaluation.cpp
+++ b/src/hir_conv/constant_evaluation.cpp
@@ -16,12 +16,15 @@
#include <trans/target.hpp>
#include <hir/expr_state.hpp>
+#include "constant_evaluation.hpp"
#include <trans/monomorphise.hpp> // 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 <anon>
+
+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 373a36a8..08b4f2de 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 da11386c..00b938ff 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 0a0b43b5..cf101443 100644
--- a/src/trans/monomorphise.cpp
+++ b/src/trans/monomorphise.cpp
@@ -10,6 +10,7 @@
#include <mir/mir.hpp>
#include <hir/hir.hpp>
#include <mir/operations.hpp> // Needed for post-monomorph checks and optimisations
+#include <hir_conv/constant_evaluation.hpp>
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 04e1e9a1..54ae8011 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 b58a241d..df550925 100644
--- a/src/trans/trans_list.hpp
+++ b/src/trans/trans_list.hpp
@@ -95,6 +95,7 @@ public:
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;
}