Skip to content

Commit

Permalink
Trans Monomorph - Associated constants left as Defer
Browse files Browse the repository at this point in the history
  • Loading branch information
thepowersgang committed Apr 28, 2019
1 parent 2aaec20 commit 406fe84
Show file tree
Hide file tree
Showing 7 changed files with 116 additions and 40 deletions.
3 changes: 3 additions & 0 deletions src/hir/hir.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -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
{
Expand Down
51 changes: 25 additions & 26 deletions src/hir_conv/constant_evaluation.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand All @@ -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 ++;
Expand All @@ -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)
{
Expand Down Expand Up @@ -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)
{
Expand Down Expand Up @@ -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());
Expand Down Expand Up @@ -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)
{
Expand Down Expand Up @@ -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();
Expand Down Expand Up @@ -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");
Expand All @@ -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);
Expand All @@ -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);
Expand All @@ -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();
Expand Down Expand Up @@ -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");
Expand Down
17 changes: 15 additions & 2 deletions src/trans/codegen_c.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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
{
Expand Down
39 changes: 29 additions & 10 deletions src/trans/enumerate.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -903,13 +903,18 @@ 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),
(LValue,
H::visit_lvalue(tv, pp, fcn, e);
),
(Constant,
H::visit_const(tv, pp, fcn, e);
)
)
}
Expand Down Expand Up @@ -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);
Expand Down Expand Up @@ -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;
Expand Down Expand Up @@ -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);
}
}
}
}
Expand Down Expand Up @@ -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);
Expand Down
30 changes: 28 additions & 2 deletions src/trans/monomorphise.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand Down Expand Up @@ -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);
Expand All @@ -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) ));
}
}

15 changes: 15 additions & 0 deletions src/trans/trans_list.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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
{
Expand Down
1 change: 1 addition & 0 deletions src/trans/trans_list.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -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;
}
Expand Down

0 comments on commit 406fe84

Please sign in to comment.