summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/hir_conv/constant_evaluation.cpp150
-rw-r--r--src/hir_expand/const_eval_full.cpp808
-rw-r--r--src/hir_expand/main_bindings.hpp1
-rw-r--r--src/hir_typeck/common.cpp17
-rw-r--r--src/hir_typeck/common.hpp18
-rw-r--r--src/hir_typeck/expr_visit.cpp1
-rw-r--r--src/main.cpp11
-rw-r--r--src/mir/cleanup.cpp2
-rw-r--r--src/mir/mir.cpp28
-rw-r--r--src/trans/enumerate.cpp29
10 files changed, 1040 insertions, 25 deletions
diff --git a/src/hir_conv/constant_evaluation.cpp b/src/hir_conv/constant_evaluation.cpp
index 38b24f64..4e15f2d5 100644
--- a/src/hir_conv/constant_evaluation.cpp
+++ b/src/hir_conv/constant_evaluation.cpp
@@ -1,7 +1,9 @@
/*
- * Evaluate constants
+ * MRustC - Rust Compiler
+ * - By John Hodge (Mutabah/thePowersGang)
*
- * HACK - Should be replaced with a reentrant typeck/mir pass
+ * hir_conv/constant_evaluation.cpp
+ * - Minimal (integer only) constant evaluation
*/
#include "main_bindings.hpp"
#include <hir/hir.hpp>
@@ -10,6 +12,7 @@
#include <algorithm>
#include <mir/mir.hpp>
#include <hir_typeck/common.hpp> // Monomorph
+#include <mir/helpers.hpp>
namespace {
typedef ::std::vector< ::std::pair< ::std::string, ::HIR::Static> > t_new_values;
@@ -18,13 +21,29 @@ namespace {
t_new_values& newval_output;
const ::HIR::ItemPath& mod_path;
::std::string name_prefix;
+ unsigned int next_item_idx;
NewvalState(t_new_values& newval_output, const ::HIR::ItemPath& mod_path, ::std::string prefix):
newval_output(newval_output),
mod_path(mod_path),
- name_prefix(prefix)
+ name_prefix(prefix),
+ next_item_idx(0)
{
}
+
+ ::HIR::SimplePath new_static(::HIR::TypeRef type, ::HIR::Literal value)
+ {
+ auto name = FMT(name_prefix << next_item_idx);
+ next_item_idx ++;
+ auto rv = (mod_path + name.c_str()).get_simple_path();
+ newval_output.push_back( ::std::make_pair( mv$(name), ::HIR::Static {
+ false,
+ mv$(type),
+ ::HIR::ExprPtr(),
+ mv$(value)
+ } ) );
+ return rv;
+ }
};
::HIR::Literal evaluate_constant(const Span& sp, const ::HIR::Crate& crate, NewvalState newval_state, const ::HIR::ExprPtr& expr, ::HIR::TypeRef exp, ::std::vector< ::HIR::Literal> args={});
@@ -434,6 +453,8 @@ namespace {
}
void visit(::HIR::ExprNode_Borrow& node) override {
+ badnode(node);
+
TU_MATCH_DEF( ::HIR::TypeRef::Data, (m_exp_type.m_data), (te),
(
ERROR(node.span(), E0000, "Invalid expected type for a &-ptr - " << m_exp_type);
@@ -1011,6 +1032,9 @@ namespace {
{
TRACE_FUNCTION;
+ StaticTraitResolve resolve { crate };
+ ::MIR::TypeResolve state { sp, resolve, FMT_CB(), exp, {}, fcn };
+
::HIR::Literal retval;
::std::vector< ::HIR::Literal> locals;
::std::vector< ::HIR::Literal> temps;
@@ -1078,10 +1102,14 @@ namespace {
for(;;)
{
const auto& block = fcn.blocks[cur_block];
+ unsigned int next_stmt_idx = 0;
for(const auto& stmt : block.statements)
{
+ state.set_cur_stmt(cur_block, next_stmt_idx++);
+
if( ! stmt.is_Assign() ) {
- BUG(sp, "Non-assign statement - drop " << stmt.as_Drop().slot);
+ //BUG(sp, "Non-assign statement - drop " << stmt.as_Drop().slot);
+ continue ;
}
::HIR::Literal val;
@@ -1133,7 +1161,20 @@ namespace {
val = ::HIR::Literal::make_List( mv$(vals) );
),
(Borrow,
- TODO(sp, "RValue::Borrow");
+ if( e.type != ::HIR::BorrowType::Shared ) {
+ MIR_BUG(state, "Only shared borrows are allowed in constants");
+ }
+
+ auto inner_val = read_lval(e.val);
+
+ ::HIR::TypeRef inner_ty;
+ const auto& inner_ty_r = state.get_lvalue_type(inner_ty, e.val);
+ if( &inner_ty_r != &inner_ty )
+ inner_ty = inner_ty_r.clone();
+
+ // Create new static containing borrowed data
+ auto item_path = newval_state.new_static( mv$(inner_ty), mv$(inner_val) );
+ val = ::HIR::Literal::make_BorrowOf( mv$(item_path) );
),
(Cast,
auto inval = read_lval(e.val);
@@ -1161,6 +1202,8 @@ namespace {
if(0)
case ::HIR::CoreType::I64:
case ::HIR::CoreType::U64:
+ case ::HIR::CoreType::Usize:
+ case ::HIR::CoreType::Isize:
mask = 0xFFFFFFFFFFFFFFFF;
TU_IFLET( ::HIR::Literal, inval, Integer, i,
@@ -1173,6 +1216,18 @@ namespace {
BUG(sp, "Invalid cast of " << inval.tag_str() << " to " << e.type);
}
break;
+ case ::HIR::CoreType::F32:
+ case ::HIR::CoreType::F64:
+ TU_IFLET( ::HIR::Literal, inval, Integer, i,
+ val = ::HIR::Literal( static_cast<double>(i) );
+ )
+ else TU_IFLET( ::HIR::Literal, inval, Float, i,
+ val = ::HIR::Literal( i );
+ )
+ else {
+ BUG(sp, "Invalid cast of " << inval.tag_str() << " to " << e.type);
+ }
+ break;
default:
TODO(sp, "RValue::Cast to " << e.type << ", val = " << inval);
}
@@ -1182,6 +1237,9 @@ namespace {
TU_IFLET( ::HIR::Literal, inval, Integer, i,
val = ::HIR::Literal(i);
)
+ else TU_IFLET( ::HIR::Literal, inval, BorrowOf, i,
+ val = mv$(inval);
+ )
else {
BUG(sp, "Invalid cast of " << inval.tag_str() << " to " << e.type);
}
@@ -1196,6 +1254,35 @@ namespace {
(
TODO(sp, "RValue::BinOp - " << sa.src << ", val = " << inval_l << " , " << inval_r);
),
+ (Float,
+ switch(e.op)
+ {
+ case ::MIR::eBinOp::ADD: val = ::HIR::Literal( l + r ); break;
+ case ::MIR::eBinOp::SUB: val = ::HIR::Literal( l - r ); break;
+ case ::MIR::eBinOp::MUL: val = ::HIR::Literal( l * r ); break;
+ case ::MIR::eBinOp::DIV: val = ::HIR::Literal( l / r ); break;
+ case ::MIR::eBinOp::MOD:
+ case ::MIR::eBinOp::ADD_OV:
+ case ::MIR::eBinOp::SUB_OV:
+ case ::MIR::eBinOp::MUL_OV:
+ case ::MIR::eBinOp::DIV_OV:
+ TODO(sp, "RValue::BinOp - " << sa.src << ", val = " << inval_l << " , " << inval_r);
+
+ case ::MIR::eBinOp::BIT_OR :
+ case ::MIR::eBinOp::BIT_AND:
+ case ::MIR::eBinOp::BIT_XOR:
+ case ::MIR::eBinOp::BIT_SHL:
+ case ::MIR::eBinOp::BIT_SHR:
+ TODO(sp, "RValue::BinOp - " << sa.src << ", val = " << inval_l << " , " << inval_r);
+ // TODO: GT/LT are incorrect for signed integers
+ case ::MIR::eBinOp::EQ: val = ::HIR::Literal( static_cast<uint64_t>(l == r) ); break;
+ case ::MIR::eBinOp::NE: val = ::HIR::Literal( static_cast<uint64_t>(l != r) ); break;
+ case ::MIR::eBinOp::GT: val = ::HIR::Literal( static_cast<uint64_t>(l > r) ); break;
+ case ::MIR::eBinOp::GE: val = ::HIR::Literal( static_cast<uint64_t>(l >= r) ); break;
+ case ::MIR::eBinOp::LT: val = ::HIR::Literal( static_cast<uint64_t>(l < r) ); break;
+ case ::MIR::eBinOp::LE: val = ::HIR::Literal( static_cast<uint64_t>(l <= r) ); break;
+ }
+ ),
(Integer,
switch(e.op)
{
@@ -1233,7 +1320,18 @@ namespace {
{
case ::MIR::eUniOp::INV:
val = ::HIR::Literal( ~i );
- break;
+ break;
+ case ::MIR::eUniOp::NEG:
+ val = ::HIR::Literal( -i );
+ break;
+ }
+ )
+ else TU_IFLET( ::HIR::Literal, inval, Float, i,
+ switch( e.op )
+ {
+ case ::MIR::eUniOp::INV:
+ BUG(sp, "Invalid invert of Float");
+ break;
case ::MIR::eUniOp::NEG:
val = ::HIR::Literal( -i );
break;
@@ -1250,7 +1348,14 @@ namespace {
TODO(sp, "RValue::DstPtr");
),
(MakeDst,
- TODO(sp, "RValue::MakeDst");
+ auto ptr = read_lval(e.ptr_val);
+ auto meta = read_lval(e.meta_val);
+ if( ! meta.is_Integer() ) {
+ TODO(sp, "RValue::MakeDst - (non-integral meta) " << ptr << " , " << meta);
+ }
+ else {
+ val = mv$(ptr);
+ }
),
(Tuple,
::std::vector< ::HIR::Literal> vals;
@@ -1281,6 +1386,7 @@ namespace {
auto& dst = get_lval(sa.dst);
dst = mv$(val);
}
+ state.set_cur_stmt_term(cur_block);
TU_MATCH_DEF( ::MIR::Terminator, (block.terminator), (e),
(
BUG(sp, "Unexpected terminator - " << block.terminator);
@@ -1319,12 +1425,12 @@ namespace {
::HIR::Literal evaluate_constant(const Span& sp, const ::HIR::Crate& crate, NewvalState newval_state, const ::HIR::ExprPtr& expr, ::HIR::TypeRef exp, ::std::vector< ::HIR::Literal> args)
{
- if( expr ) {
- return evaluate_constant_hir(sp, crate, mv$(newval_state), *expr, mv$(exp), mv$(args));
- }
- else if( expr.m_mir ) {
+ if( expr.m_mir ) {
return evaluate_constant_mir(sp, crate, mv$(newval_state), *expr.m_mir, mv$(exp), mv$(args));
}
+ else if( expr ) {
+ return evaluate_constant_hir(sp, crate, mv$(newval_state), *expr, mv$(exp), mv$(args));
+ }
else {
BUG(sp, "Attempting to evaluate constant expression with no associated code");
}
@@ -1446,26 +1552,21 @@ namespace {
}
void visit_constant(::HIR::ItemPath p, ::HIR::Constant& item) override
{
- visit_type(item.m_type);
+ ::HIR::Visitor::visit_constant(p, item);
+
+ //visit_type(item.m_type);
if( item.m_value )
{
+ if( ! item.m_type.m_data.is_Primitive() )
+ return ;
+
auto nvs = NewvalState { m_new_values, *m_mod_path, FMT(p.get_name() << "$") };
item.m_value_res = evaluate_constant(item.m_value->span(), m_crate, nvs, item.m_value, item.m_type.clone(), {});
check_lit_type(item.m_value->span(), item.m_type, item.m_value_res);
DEBUG("constant: " << item.m_type << " = " << item.m_value_res);
- visit_expr(item.m_value);
- }
- }
- void visit_static(::HIR::ItemPath p, ::HIR::Static& item) override
- {
- visit_type(item.m_type);
- if( item.m_value )
- {
- item.m_value_res = evaluate_constant(item.m_value->span(), m_crate, NewvalState { m_new_values, *m_mod_path, FMT(p.get_name() << "$") }, item.m_value, item.m_type.clone(), {});
- DEBUG("static: " << item.m_type << " = " << item.m_value_res);
- visit_expr(item.m_value);
+ //visit_expr(item.m_value);
}
}
void visit_enum(::HIR::ItemPath p, ::HIR::Enum& item) override {
@@ -1512,7 +1613,8 @@ namespace {
void visit(::HIR::ExprNode_ArraySized& node) override {
assert( node.m_size );
- auto val = evaluate_constant_hir(node.span(), m_exp.m_crate, NewvalState { m_exp.m_new_values, *m_exp.m_mod_path, FMT("array_" << &node << "$") }, *node.m_size, ::HIR::CoreType::Usize, {});
+ NewvalState nvs { m_exp.m_new_values, *m_exp.m_mod_path, FMT("array_" << &node << "$") };
+ auto val = evaluate_constant_hir(node.span(), m_exp.m_crate, mv$(nvs), *node.m_size, ::HIR::CoreType::Usize, {});
if( !val.is_Integer() )
ERROR(node.span(), E0000, "Array size isn't an integer");
node.m_size_val = val.as_Integer();
diff --git a/src/hir_expand/const_eval_full.cpp b/src/hir_expand/const_eval_full.cpp
new file mode 100644
index 00000000..9411e1c7
--- /dev/null
+++ b/src/hir_expand/const_eval_full.cpp
@@ -0,0 +1,808 @@
+/*
+ * MRustC - Rust Compiler
+ * - By John Hodge (Mutabah/thePowersGang)
+ *
+ * hir_expand/const_eval_full.cpp
+ * - More-complete constant evaluation
+ */
+#include "main_bindings.hpp"
+#include <hir/hir.hpp>
+#include <hir/expr.hpp>
+#include <hir/visitor.hpp>
+#include <algorithm>
+#include <mir/mir.hpp>
+#include <hir_typeck/common.hpp> // Monomorph
+#include <mir/helpers.hpp>
+
+namespace {
+ typedef ::std::vector< ::std::pair< ::std::string, ::HIR::Static> > t_new_values;
+
+ struct NewvalState {
+ t_new_values& newval_output;
+ const ::HIR::ItemPath& mod_path;
+ ::std::string name_prefix;
+ unsigned int next_item_idx;
+
+ NewvalState(t_new_values& newval_output, const ::HIR::ItemPath& mod_path, ::std::string prefix):
+ newval_output(newval_output),
+ mod_path(mod_path),
+ name_prefix(prefix),
+ next_item_idx(0)
+ {
+ }
+
+ ::HIR::SimplePath new_static(::HIR::TypeRef type, ::HIR::Literal value)
+ {
+ auto name = FMT(name_prefix << next_item_idx);
+ next_item_idx ++;
+ auto rv = (mod_path + name.c_str()).get_simple_path();
+ newval_output.push_back( ::std::make_pair( mv$(name), ::HIR::Static {
+ false,
+ mv$(type),
+ ::HIR::ExprPtr(),
+ mv$(value)
+ } ) );
+ return rv;
+ }
+ };
+
+ ::HIR::Literal evaluate_constant(const Span& sp, const ::StaticTraitResolve& resolve, NewvalState newval_state, const ::HIR::ExprPtr& expr, MonomorphState ms, ::std::vector< ::HIR::Literal> args);
+
+ ::HIR::Literal clone_literal(const ::HIR::Literal& v)
+ {
+ TU_MATCH(::HIR::Literal, (v), (e),
+ (Invalid,
+ return ::HIR::Literal();
+ ),
+ (List,
+ ::std::vector< ::HIR::Literal> vals;
+ for(const auto& val : e) {
+ vals.push_back( clone_literal(val) );
+ }
+ return ::HIR::Literal( mv$(vals) );
+ ),
+ (Variant,
+ ::std::vector< ::HIR::Literal> vals;
+ for(const auto& val : e.vals) {
+ vals.push_back( clone_literal(val) );
+ }
+ return ::HIR::Literal::make_Variant({ e.idx, mv$(vals) });
+ ),
+ (Integer,
+ return ::HIR::Literal(e);
+ ),
+ (Float,
+ return ::HIR::Literal(e);
+ ),
+ (BorrowOf,
+ return ::HIR::Literal(e.clone());
+ ),
+ (String,
+ return ::HIR::Literal(e);
+ )
+ )
+ throw "";
+ }
+
+ void monomorph_literal_inplace(const Span& sp, ::HIR::Literal& lit, const MonomorphState& ms)
+ {
+ TU_MATCH(::HIR::Literal, (lit), (e),
+ (Invalid,
+ ),
+ (List,
+ for(auto& val : e) {
+ monomorph_literal_inplace(sp, val, ms);
+ }
+ ),
+ (Variant,
+ for(auto& val : e.vals) {
+ monomorph_literal_inplace(sp, val, ms);
+ }
+ ),
+ (Integer,
+ ),
+ (Float,
+ ),
+ (BorrowOf,
+ DEBUG(e);
+ e = ms.monomorph(sp, e);
+ // TODO: expand associated types
+ ),
+ (String,
+ )
+ )
+ }
+
+ TAGGED_UNION(EntPtr, NotFound,
+ (NotFound, struct{}),
+ (Function, const ::HIR::Function*),
+ (Static, const ::HIR::Static*),
+ (Constant, const ::HIR::Constant*),
+ (Struct, const ::HIR::Struct*)
+ );
+ enum class EntNS {
+ Type,
+ Value
+ };
+ EntPtr get_ent_simplepath(const Span& sp, const ::HIR::Crate& crate, const ::HIR::SimplePath& path, EntNS ns)
+ {
+ const ::HIR::Module* mod;
+ if( path.m_crate_name != "" ) {
+ ASSERT_BUG(sp, crate.m_ext_crates.count(path.m_crate_name) > 0, "Crate '" << path.m_crate_name << "' not loaded");
+ mod = &crate.m_ext_crates.at(path.m_crate_name)->m_root_module;
+ }
+ else {
+ mod = &crate.m_root_module;
+ }
+
+ for( unsigned int i = 0; i < path.m_components.size() - 1; i ++ )
+ {
+ const auto& pc = path.m_components[i];
+ auto it = mod->m_mod_items.find( pc );
+ if( it == mod->m_mod_items.end() ) {
+ BUG(sp, "Couldn't find component " << i << " of " << path);
+ }
+ TU_MATCH_DEF( ::HIR::TypeItem, (it->second->ent), (e2),
+ (
+ BUG(sp, "Node " << i << " of path " << path << " wasn't a module");
+ ),
+ (Module,
+ mod = &e2;
+ )
+ )
+ }
+
+ switch( ns )
+ {
+ case EntNS::Value: {
+ auto it = mod->m_value_items.find( path.m_components.back() );
+ if( it == mod->m_value_items.end() ) {
+ return EntPtr {};
+ }
+
+ TU_MATCH( ::HIR::ValueItem, (it->second->ent), (e),
+ (Import,
+ ),
+ (StructConstant,
+ ),
+ (StructConstructor,
+ ),
+ (Function,
+ return EntPtr { &e };
+ ),
+ (Constant,
+ return EntPtr { &e };
+ ),
+ (Static,
+ return EntPtr { &e };
+ )
+ )
+ BUG(sp, "Path " << path << " pointed to a invalid item - " << it->second->ent.tag_str());
+ } break;
+ case EntNS::Type: {
+ auto it = mod->m_mod_items.find( path.m_components.back() );
+ if( it == mod->m_mod_items.end() ) {
+ return EntPtr {};
+ }
+
+ TU_MATCH( ::HIR::TypeItem, (it->second->ent), (e),
+ (Import,
+ ),
+ (Module,
+ ),
+ (Trait,
+ ),
+ (Struct,
+ return &e;
+ ),
+ (Union,
+ ),
+ (Enum,
+ ),
+ (TypeAlias,
+ )
+ )
+ BUG(sp, "Path " << path << " pointed to an invalid item - " << it->second->ent.tag_str());
+ } break;
+ }
+ throw "";
+ }
+ EntPtr get_ent_fullpath(const Span& sp, const ::HIR::Crate& crate, const ::HIR::Path& path, EntNS ns, MonomorphState& out_ms)
+ {
+ TU_MATCH(::HIR::Path::Data, (path.m_data), (e),
+ (Generic,
+ out_ms = MonomorphState {};
+ out_ms.pp_method = &e.m_params;
+ return get_ent_simplepath(sp, crate, e.m_path, ns);
+ ),
+ (UfcsInherent,
+ // Easy (ish)
+ EntPtr rv;
+ crate.find_type_impls(*e.type, [](const auto&x)->const auto& { return x; }, [&](const auto& impl) {
+ switch( ns )
+ {
+ case EntNS::Value:
+ {
+ auto fit = impl.m_methods.find(e.item);
+ if( fit != impl.m_methods.end() )
+ {
+ DEBUG("Found impl" << impl.m_params.fmt_args() << " " << impl.m_type);
+ rv = EntPtr { &fit->second.data };
+ return true;
+ }
+ }
+ {
+ auto it = impl.m_constants.find(e.item);
+ if( it != impl.m_constants.end() )
+ {
+ rv = EntPtr { &it->second.data };
+ return true;
+ }
+ }
+ break;
+ case EntNS::Type:
+ break;
+ }
+ return false;
+ });
+ out_ms = MonomorphState {};
+ out_ms.pp_method = &e.params;
+ out_ms.pp_impl = &e.impl_params;
+ return rv;
+ ),
+ (UfcsKnown,
+ EntPtr rv;
+ crate.find_trait_impls(e.trait.m_path, *e.type, [](const auto&x)->const auto& { return x; }, [&](const auto& impl) {
+ // Hacky selection of impl.
+ // - TODO: Specialisation
+ // - TODO: Inference? (requires full typeck)
+ switch( ns )
+ {
+ case EntNS::Value:
+ {
+ auto fit = impl.m_methods.find(e.item);
+ if( fit != impl.m_methods.end() )
+ {
+ DEBUG("Found impl" << impl.m_params.fmt_args() << " " << impl.m_type);
+ rv = EntPtr { &fit->second.data };
+ return true;
+ }
+ }
+ {
+ auto it = impl.m_constants.find(e.item);
+ if( it != impl.m_constants.end() )
+ {
+ rv = EntPtr { &it->second.data };
+ return true;
+ }
+ }
+ break;
+ case EntNS::Type:
+ break;
+ }
+ return false;
+ });
+ out_ms = MonomorphState {};
+ out_ms.pp_method = &e.params;
+ // TODO: How to get pp_impl here? Needs specialisation magic.
+ return rv;
+ ),
+ (UfcsUnknown,
+ // TODO: Are these valid at this point in compilation?
+ TODO(sp, "get_ent_fullpath(path = " << path << ")");
+ )
+ )
+ throw "";
+ }
+ const ::HIR::Function& get_function(const Span& sp, const ::HIR::Crate& crate, const ::HIR::Path& path, MonomorphState& out_ms)
+ {
+ auto rv = get_ent_fullpath(sp, crate, path, EntNS::Value, out_ms);
+ TU_IFLET( EntPtr, rv, Function, e,
+ return *e;
+ )
+ else {
+ TODO(sp, "Could not find function for " << path << " - " << rv.tag_str());
+ }
+ }
+
+ ::HIR::Literal evaluate_constant_mir(const Span& sp, const StaticTraitResolve& resolve, NewvalState newval_state, const ::MIR::Function& fcn, MonomorphState ms, ::std::vector< ::HIR::Literal> args)
+ {
+ TRACE_FUNCTION;
+
+ ::MIR::TypeResolve state { sp, resolve, FMT_CB(), ::HIR::TypeRef(), {}, fcn };
+
+ ::HIR::Literal retval;
+ ::std::vector< ::HIR::Literal> locals;
+ ::std::vector< ::HIR::Literal> temps;
+ locals.resize( fcn.named_variables.size() );
+ temps.resize( fcn.temporaries.size() );
+
+ auto get_lval = [&](const ::MIR::LValue& lv) -> ::HIR::Literal& {
+ TU_MATCHA( (lv), (e),
+ (Variable,
+ if( e >= locals.size() )
+ BUG(sp, "Local index out of range - " << e << " >= " << locals.size());
+ return locals[e];
+ ),
+ (Temporary,
+ if( e.idx >= temps.size() )
+ BUG(sp, "Temp index out of range - " << e.idx << " >= " << temps.size());
+ return temps[e.idx];
+ ),
+ (Argument,
+ return args[e.idx];
+ ),
+ (Static,
+ TODO(sp, "LValue::Static");
+ ),
+ (Return,
+ return retval;
+ ),
+ (Field,
+ TODO(sp, "LValue::Field");
+ ),
+ (Deref,
+ TODO(sp, "LValue::Deref");
+ ),
+ (Index,
+ TODO(sp, "LValue::Index");
+ ),
+ (Downcast,
+ TODO(sp, "LValue::Downcast");
+ )
+ )
+ throw "";
+ };
+ auto read_lval = [&](const ::MIR::LValue& lv) -> ::HIR::Literal {
+ auto& v = get_lval(lv);
+ TU_MATCH_DEF(::HIR::Literal, (v), (e),
+ (
+ return mv$(v);
+ ),
+ (Invalid,
+ BUG(sp, "Read of lvalue with Literal::Invalid - " << lv);
+ ),
+ (BorrowOf,
+ return ::HIR::Literal(e.clone());
+ ),
+ (Integer,
+ return ::HIR::Literal(e);
+ ),
+ (Float,
+ return ::HIR::Literal(e);
+ )
+ )
+ };
+
+ unsigned int cur_block = 0;
+ for(;;)
+ {
+ const auto& block = fcn.blocks[cur_block];
+ unsigned int next_stmt_idx = 0;
+ for(const auto& stmt : block.statements)
+ {
+ state.set_cur_stmt(cur_block, next_stmt_idx++);
+
+ if( ! stmt.is_Assign() ) {
+ //BUG(sp, "Non-assign statement - drop " << stmt.as_Drop().slot);
+ continue ;
+ }
+ const auto& sa = stmt.as_Assign();
+
+ DEBUG(sa.dst << " = " << sa.src);
+ ::HIR::Literal val;
+ TU_MATCHA( (sa.src), (e),
+ (Use,
+ val = read_lval(e);
+ ),
+ (Constant,
+ TU_MATCH(::MIR::Constant, (e), (e2),
+ (Int,
+ val = ::HIR::Literal(static_cast<uint64_t>(e2));
+ ),
+ (Uint,
+ val = ::HIR::Literal(e2);
+ ),
+ (Float,
+ val = ::HIR::Literal(e2);
+ ),
+ (Bool,
+ val = ::HIR::Literal(static_cast<uint64_t>(e2));
+ ),
+ (Bytes,
+ val = ::HIR::Literal::make_String({e2.begin(), e2.end()});
+ ),
+ (StaticString,
+ val = ::HIR::Literal(e2);
+ ),
+ (Const,
+ MonomorphState const_ms;
+ // TODO: Monomorph the path? (Not needed... yet)
+ auto ent = get_ent_fullpath(sp, resolve.m_crate, e2.p, EntNS::Value, const_ms);
+ ASSERT_BUG(sp, ent.is_Constant(), "MIR Constant::Const("<<e2.p<<") didn't point to a Constant - " << ent.tag_str());
+ val = clone_literal( ent.as_Constant()->m_value_res );
+ if( val.is_Invalid() ) {
+ val = evaluate_constant(sp, resolve, newval_state, ent.as_Constant()->m_value, {}, {});
+ }
+ // Monomorphise the value according to `const_ms`
+ monomorph_literal_inplace(sp, val, const_ms);
+ ),
+ (ItemAddr,
+ val = ::HIR::Literal::make_BorrowOf( ms.monomorph(sp, e2) );
+ )
+ )
+ ),
+ (SizedArray,
+ ::std::vector< ::HIR::Literal> vals;
+ if( e.count > 0 )
+ {
+ vals.reserve( e.count );
+ val = read_lval(e.val);
+ for(unsigned int i = 1; i < e.count; i++)
+ vals.push_back( clone_literal(val) );
+ vals.push_back( mv$(val) );
+ }
+ val = ::HIR::Literal::make_List( mv$(vals) );
+ ),
+ (Borrow,
+ if( e.type != ::HIR::BorrowType::Shared ) {
+ MIR_BUG(state, "Only shared borrows are allowed in constants");
+ }
+
+ auto inner_val = read_lval(e.val);
+
+ ::HIR::TypeRef inner_ty;
+ const auto& inner_ty_r = state.get_lvalue_type(inner_ty, e.val);
+ if( &inner_ty_r != &inner_ty )
+ inner_ty = inner_ty_r.clone();
+
+ // Create new static containing borrowed data
+ auto item_path = newval_state.new_static( mv$(inner_ty), mv$(inner_val) );
+ val = ::HIR::Literal::make_BorrowOf( mv$(item_path) );
+ ),
+ (Cast,
+ auto inval = read_lval(e.val);
+ TU_MATCH_DEF(::HIR::TypeRef::Data, (e.type.m_data), (te),
+ (
+ // NOTE: Can be an unsizing!
+ TODO(sp, "RValue::Cast to " << e.type << ", val = " << inval);
+ ),
+ (Primitive,
+ uint64_t mask;
+ switch(te)
+ {
+ // Integers mask down
+ case ::HIR::CoreType::I8:
+ case ::HIR::CoreType::U8:
+ mask = 0xFF;
+ if(0)
+ case ::HIR::CoreType::I16:
+ case ::HIR::CoreType::U16:
+ mask = 0xFFFF;
+ if(0)
+ case ::HIR::CoreType::I32:
+ case ::HIR::CoreType::U32:
+ mask = 0xFFFFFFFF;
+ if(0)
+ case ::HIR::CoreType::I64:
+ case ::HIR::CoreType::U64:
+ case ::HIR::CoreType::Usize:
+ case ::HIR::CoreType::Isize:
+ mask = 0xFFFFFFFFFFFFFFFF;
+
+ TU_IFLET( ::HIR::Literal, inval, Integer, i,
+ val = ::HIR::Literal(i & mask);
+ )
+ else TU_IFLET( ::HIR::Literal, inval, Float, i,
+ val = ::HIR::Literal( static_cast<uint64_t>(i) & mask);
+ )
+ else {
+ BUG(sp, "Invalid cast of " << inval.tag_str() << " to " << e.type);
+ }
+ break;
+ case ::HIR::CoreType::F32:
+ case ::HIR::CoreType::F64:
+ TU_IFLET( ::HIR::Literal, inval, Integer, i,
+ val = ::HIR::Literal( static_cast<double>(i) );
+ )
+ else TU_IFLET( ::HIR::Literal, inval, Float, i,
+ val = ::HIR::Literal( i );
+ )
+ else {
+ BUG(sp, "Invalid cast of " << inval.tag_str() << " to " << e.type);
+ }
+ break;
+ default:
+ TODO(sp, "RValue::Cast to " << e.type << ", val = " << inval);
+ }
+ ),
+ // Allow casting any integer value to a pointer (TODO: Ensure that the pointer is sized?)
+ (Pointer,
+ TU_IFLET( ::HIR::Literal, inval, Integer, i,
+ val = ::HIR::Literal(i);
+ )
+ else TU_IFLET( ::HIR::Literal, inval, BorrowOf, i,
+ val = mv$(inval);
+ )
+ else {
+ BUG(sp, "Invalid cast of " << inval.tag_str() << " to " << e.type);
+ }
+ )
+ )
+ ),
+ (BinOp,
+ auto inval_l = read_lval(e.val_l);
+ auto inval_r = read_lval(e.val_r);
+ ASSERT_BUG(sp, inval_l.tag() == inval_r.tag(), "Mismatched literal types in binop - " << inval_l << " and " << inval_r);
+ TU_MATCH_DEF( ::HIR::Literal, (inval_l, inval_r), (l, r),
+ (
+ TODO(sp, "RValue::BinOp - " << sa.src << ", val = " << inval_l << " , " << inval_r);
+ ),
+ (Float,
+ switch(e.op)
+ {
+ case ::MIR::eBinOp::ADD: val = ::HIR::Literal( l + r ); break;
+ case ::MIR::eBinOp::SUB: val = ::HIR::Literal( l - r ); break;
+ case ::MIR::eBinOp::MUL: val = ::HIR::Literal( l * r ); break;
+ case ::MIR::eBinOp::DIV: val = ::HIR::Literal( l / r ); break;
+ case ::MIR::eBinOp::MOD:
+ case ::MIR::eBinOp::ADD_OV:
+ case ::MIR::eBinOp::SUB_OV:
+ case ::MIR::eBinOp::MUL_OV:
+ case ::MIR::eBinOp::DIV_OV:
+ TODO(sp, "RValue::BinOp - " << sa.src << ", val = " << inval_l << " , " << inval_r);
+
+ case ::MIR::eBinOp::BIT_OR :
+ case ::MIR::eBinOp::BIT_AND:
+ case ::MIR::eBinOp::BIT_XOR:
+ case ::MIR::eBinOp::BIT_SHL:
+ case ::MIR::eBinOp::BIT_SHR:
+ TODO(sp, "RValue::BinOp - " << sa.src << ", val = " << inval_l << " , " << inval_r);
+ // TODO: GT/LT are incorrect for signed integers
+ case ::MIR::eBinOp::EQ: val = ::HIR::Literal( static_cast<uint64_t>(l == r) ); break;
+ case ::MIR::eBinOp::NE: val = ::HIR::Literal( static_cast<uint64_t>(l != r) ); break;
+ case ::MIR::eBinOp::GT: val = ::HIR::Literal( static_cast<uint64_t>(l > r) ); break;
+ case ::MIR::eBinOp::GE: val = ::HIR::Literal( static_cast<uint64_t>(l >= r) ); break;
+ case ::MIR::eBinOp::LT: val = ::HIR::Literal( static_cast<uint64_t>(l < r) ); break;
+ case ::MIR::eBinOp::LE: val = ::HIR::Literal( static_cast<uint64_t>(l <= r) ); break;
+ }
+ ),
+ (Integer,
+ switch(e.op)
+ {
+ case ::MIR::eBinOp::ADD: val = ::HIR::Literal( l + r ); break;
+ case ::MIR::eBinOp::SUB: val = ::HIR::Literal( l - r ); break;
+ case ::MIR::eBinOp::MUL: val = ::HIR::Literal( l * r ); break;
+ case ::MIR::eBinOp::DIV: val = ::HIR::Literal( l / r ); break;
+ case ::MIR::eBinOp::MOD: val = ::HIR::Literal( l % r ); break;
+ case ::MIR::eBinOp::ADD_OV:
+ case ::MIR::eBinOp::SUB_OV:
+ case ::MIR::eBinOp::MUL_OV:
+ case ::MIR::eBinOp::DIV_OV:
+ TODO(sp, "RValue::BinOp - " << sa.src << ", val = " << inval_l << " , " << inval_r);
+
+ case ::MIR::eBinOp::BIT_OR : val = ::HIR::Literal( l | r ); break;
+ case ::MIR::eBinOp::BIT_AND: val = ::HIR::Literal( l & r ); break;
+ case ::MIR::eBinOp::BIT_XOR: val = ::HIR::Literal( l ^ r ); break;
+ case ::MIR::eBinOp::BIT_SHL: val = ::HIR::Literal( l << r ); break;
+ case ::MIR::eBinOp::BIT_SHR: val = ::HIR::Literal( l >> r ); break;
+ // TODO: GT/LT are incorrect for signed integers
+ case ::MIR::eBinOp::EQ: val = ::HIR::Literal( static_cast<uint64_t>(l == r) ); break;
+ case ::MIR::eBinOp::NE: val = ::HIR::Literal( static_cast<uint64_t>(l != r) ); break;
+ case ::MIR::eBinOp::GT: val = ::HIR::Literal( static_cast<uint64_t>(l > r) ); break;
+ case ::MIR::eBinOp::GE: val = ::HIR::Literal( static_cast<uint64_t>(l >= r) ); break;
+ case ::MIR::eBinOp::LT: val = ::HIR::Literal( static_cast<uint64_t>(l < r) ); break;
+ case ::MIR::eBinOp::LE: val = ::HIR::Literal( static_cast<uint64_t>(l <= r) ); break;
+ }
+ )
+ )
+ ),
+ (UniOp,
+ auto inval = read_lval(e.val);
+ TU_IFLET( ::HIR::Literal, inval, Integer, i,
+ switch( e.op )
+ {
+ case ::MIR::eUniOp::INV:
+ val = ::HIR::Literal( ~i );
+ break;
+ case ::MIR::eUniOp::NEG:
+ val = ::HIR::Literal( -i );
+ break;
+ }
+ )
+ else TU_IFLET( ::HIR::Literal, inval, Float, i,
+ switch( e.op )
+ {
+ case ::MIR::eUniOp::INV:
+ BUG(sp, "Invalid invert of Float");
+ break;
+ case ::MIR::eUniOp::NEG:
+ val = ::HIR::Literal( -i );
+ break;
+ }
+ )
+ else {
+ BUG(sp, "Invalid invert of " << inval.tag_str());
+ }
+ ),
+ (DstMeta,
+ TODO(sp, "RValue::DstMeta");
+ ),
+ (DstPtr,
+ TODO(sp, "RValue::DstPtr");
+ ),
+ (MakeDst,
+ auto ptr = read_lval(e.ptr_val);
+ auto meta = read_lval(e.meta_val);
+ if( ! meta.is_Integer() ) {
+ TODO(sp, "RValue::MakeDst - (non-integral meta) " << ptr << " , " << meta);
+ }
+ else {
+ val = mv$(ptr);
+ }
+ ),
+ (Tuple,
+ ::std::vector< ::HIR::Literal> vals;
+ vals.reserve( e.vals.size() );
+ for(const auto& v : e.vals)
+ vals.push_back( read_lval(v) );
+ val = ::HIR::Literal::make_List( mv$(vals) );
+ ),
+ (Array,
+ ::std::vector< ::HIR::Literal> vals;
+ vals.reserve( e.vals.size() );
+ for(const auto& v : e.vals)
+ vals.push_back( read_lval(v) );
+ val = ::HIR::Literal::make_List( mv$(vals) );
+ ),
+ (Variant,
+ TODO(sp, "MIR _Variant");
+ ),
+ (Struct,
+ ::std::vector< ::HIR::Literal> vals;
+ vals.reserve( e.vals.size() );
+ for(const auto& v : e.vals)
+ vals.push_back( read_lval(v) );
+ val = ::HIR::Literal::make_List( mv$(vals) );
+ )
+ )
+
+ auto& dst = get_lval(sa.dst);
+ DEBUG("= " << val);
+ dst = mv$(val);
+ }
+ state.set_cur_stmt_term(cur_block);
+ DEBUG("> " << block.terminator);
+ TU_MATCH_DEF( ::MIR::Terminator, (block.terminator), (e),
+ (
+ BUG(sp, "Unexpected terminator - " << block.terminator);
+ ),
+ (Goto,
+ cur_block = e;
+ ),
+ (Return,
+ return retval;
+ ),
+ (Call,
+ if( !e.fcn.is_Path() )
+ BUG(sp, "Unexpected terminator - " << block.terminator);
+ const auto& fcnp_raw = e.fcn.as_Path();
+ auto fcnp = ms.monomorph(sp, fcnp_raw);
+
+ auto& dst = get_lval(e.ret_val);
+ MonomorphState fcn_ms;
+ auto& fcn = get_function(sp, resolve.m_crate, fcnp, fcn_ms);
+
+ ::std::vector< ::HIR::Literal> call_args;
+ call_args.reserve( e.args.size() );
+ for(const auto& a : e.args)
+ call_args.push_back( read_lval(a) );
+ // TODO: Set m_const during parse and check here
+
+ // Call by invoking evaluate_constant on the function
+ {
+ TRACE_FUNCTION_F("Call const fn " << fcnp << " args={ " << call_args << " }");
+ dst = evaluate_constant(sp, resolve, newval_state, fcn.m_code, fcn_ms, mv$(call_args));
+ }
+
+ DEBUG("= " << dst);
+ cur_block = e.ret_block;
+ )
+ )
+ }
+ }
+
+ ::HIR::Literal evaluate_constant(const Span& sp, const StaticTraitResolve& resolve, NewvalState newval_state, const ::HIR::ExprPtr& expr, MonomorphState ms, ::std::vector< ::HIR::Literal> args)
+ {
+ if( expr.m_mir ) {
+ return evaluate_constant_mir(sp, resolve, mv$(newval_state), *expr.m_mir, ms, mv$(args));
+ }
+ else {
+ BUG(sp, "Attempting to evaluate constant expression with no associated code");
+ }
+ }
+
+ class Expander:
+ public ::HIR::Visitor
+ {
+ const ::HIR::Crate& m_crate;
+ StaticTraitResolve m_resolve;
+
+ const ::HIR::ItemPath* m_mod_path;
+ t_new_values m_new_values;
+
+ public:
+ Expander(const ::HIR::Crate& crate):
+ m_crate(crate),
+ m_resolve(crate)
+ {}
+
+ void visit_module(::HIR::ItemPath p, ::HIR::Module& mod) override
+ {
+ auto saved_mp = m_mod_path;
+ m_mod_path = &p;
+ auto saved = mv$( m_new_values );
+
+ ::HIR::Visitor::visit_module(p, mod);
+
+ for( auto& item : m_new_values )
+ {
+ mod.m_value_items.insert( ::std::make_pair(
+ mv$(item.first),
+ box$(::HIR::VisEnt<::HIR::ValueItem> { false, ::HIR::ValueItem(mv$(item.second)) })
+ ) );
+ }
+ m_new_values = mv$(saved);
+ m_mod_path = saved_mp;
+ }
+
+ void visit_type(::HIR::TypeRef& ty) override
+ {
+ ::HIR::Visitor::visit_type(ty);
+
+ TU_IFLET(::HIR::TypeRef::Data, ty.m_data, Array, e,
+ assert( e.size_val != ~0u );
+ )
+ }
+ void visit_constant(::HIR::ItemPath p, ::HIR::Constant& item) override
+ {
+ visit_type(item.m_type);
+ if( item.m_value )
+ {
+ auto nvs = NewvalState { m_new_values, *m_mod_path, FMT(p.get_name() << "$") };
+ item.m_value_res = evaluate_constant(item.m_value->span(), m_resolve, nvs, item.m_value, {}, {});
+
+ DEBUG("constant: " << item.m_type << " = " << item.m_value_res);
+ visit_expr(item.m_value);
+ }
+ }
+ void visit_static(::HIR::ItemPath p, ::HIR::Static& item) override
+ {
+ visit_type(item.m_type);
+ if( item.m_value )
+ {
+ auto nvs = NewvalState { m_new_values, *m_mod_path, FMT(p.get_name() << "$") };
+ item.m_value_res = evaluate_constant(item.m_value->span(), m_resolve, mv$(nvs), item.m_value, {}, {});
+ DEBUG("static: " << item.m_type << " = " << item.m_value_res);
+ visit_expr(item.m_value);
+ }
+ }
+ void visit_enum(::HIR::ItemPath p, ::HIR::Enum& item) override {
+ for(auto& var : item.m_variants)
+ {
+ TU_IFLET(::HIR::Enum::Variant, var.second, Value, e,
+ auto nvs = NewvalState { m_new_values, *m_mod_path, FMT(p.get_name() << "$" << var.first << "$") };
+ e.val = evaluate_constant(e.expr->span(), m_resolve, mv$(nvs), e.expr, {}, {});
+ DEBUG("enum variant: " << p << "::" << var.first << " = " << e.val);
+ )
+ }
+ ::HIR::Visitor::visit_enum(p, item);
+ }
+ };
+} // namespace
+
+void ConvertHIR_ConstantEvaluateFull(::HIR::Crate& crate)
+{
+ Expander exp { crate };
+ exp.visit_crate( crate );
+}
diff --git a/src/hir_expand/main_bindings.hpp b/src/hir_expand/main_bindings.hpp
index 4a3ac160..6b9d5bab 100644
--- a/src/hir_expand/main_bindings.hpp
+++ b/src/hir_expand/main_bindings.hpp
@@ -17,3 +17,4 @@ extern void HIR_Expand_Closures(::HIR::Crate& crate);
extern void HIR_Expand_UfcsEverything(::HIR::Crate& crate);
extern void HIR_Expand_Reborrows(::HIR::Crate& crate);
extern void HIR_Expand_ErasedType(::HIR::Crate& crate);
+extern void ConvertHIR_ConstantEvaluateFull(::HIR::Crate& crate);
diff --git a/src/hir_typeck/common.cpp b/src/hir_typeck/common.cpp
index bed6b0f4..0751d5a1 100644
--- a/src/hir_typeck/common.cpp
+++ b/src/hir_typeck/common.cpp
@@ -373,6 +373,23 @@ namespace {
}, false);
}
+t_cb_generic MonomorphState::get_cb(const Span& sp) const
+{
+ return monomorphise_type_get_cb(sp, this->self_ty, this->pp_impl, this->pp_method);
+}
+::std::ostream& operator<<(::std::ostream& os, const MonomorphState& ms)
+{
+ os << "MonomorphState {";
+ if(ms.self_ty)
+ os << " self=" << *ms.self_ty;
+ if(ms.pp_impl)
+ os << " I=" << *ms.pp_impl;
+ if(ms.pp_method)
+ os << " M=" << *ms.pp_method;
+ os << " }";
+ return os;
+}
+
void check_type_class_primitive(const Span& sp, const ::HIR::TypeRef& type, ::HIR::InferClass ic, ::HIR::CoreType ct)
{
switch(ic)
diff --git a/src/hir_typeck/common.hpp b/src/hir_typeck/common.hpp
index 07ad9ff5..d6bf30c1 100644
--- a/src/hir_typeck/common.hpp
+++ b/src/hir_typeck/common.hpp
@@ -38,6 +38,24 @@ typedef ::std::function<bool(const ::HIR::TypeRef&, ::HIR::TypeRef&)> t_cb_clo
/// Clones a type, calling the provided callback on every type (optionally providing a replacement)
extern ::HIR::TypeRef clone_ty_with(const Span& sp, const ::HIR::TypeRef& tpl, t_cb_clone_ty callback);
+// Helper for passing a group of params around
+struct MonomorphState
+{
+ const ::HIR::TypeRef* self_ty;
+ const ::HIR::PathParams* pp_impl;
+ const ::HIR::PathParams* pp_method;
+
+ t_cb_generic get_cb(const Span& sp) const;
+
+ ::HIR::TypeRef monomorph(const Span& sp, const ::HIR::TypeRef& ty, bool allow_infer=true) const {
+ return monomorphise_type_with(sp, ty, this->get_cb(sp), allow_infer);
+ }
+ ::HIR::Path monomorph(const Span& sp, const ::HIR::Path& tpl, bool allow_infer=true) const {
+ return monomorphise_path_with(sp, tpl, this->get_cb(sp), allow_infer);
+ }
+};
+extern ::std::ostream& operator<<(::std::ostream& os, const MonomorphState& ms);
+
static inline t_cb_generic monomorphise_type_get_cb(const Span& sp, const ::HIR::TypeRef* self_ty, const ::HIR::PathParams* params_i, const ::HIR::PathParams* params_m, const ::HIR::PathParams* params_p=nullptr)
{
return [=](const auto& gt)->const auto& {
diff --git a/src/hir_typeck/expr_visit.cpp b/src/hir_typeck/expr_visit.cpp
index 9713e862..83036720 100644
--- a/src/hir_typeck/expr_visit.cpp
+++ b/src/hir_typeck/expr_visit.cpp
@@ -11,6 +11,7 @@ namespace {
Typecheck_Code_CS(ms, args, result_type, expr);
}
+
class OuterVisitor:
public ::HIR::Visitor
{
diff --git a/src/main.cpp b/src/main.cpp
index 9d003537..96d05f29 100644
--- a/src/main.cpp
+++ b/src/main.cpp
@@ -64,6 +64,7 @@ void init_debug_list()
g_debug_disable_map.insert( "Lower MIR" );
g_debug_disable_map.insert( "MIR Validate" );
g_debug_disable_map.insert( "Dump MIR" );
+ g_debug_disable_map.insert( "Constant Evaluate Full" );
g_debug_disable_map.insert( "HIR Serialise" );
g_debug_disable_map.insert( "Trans Enumerate" );
@@ -384,6 +385,16 @@ int main(int argc, char *argv[])
MIR_CheckCrate(*hir_crate);
});
+ // Second shot of constant evaluation (with full type information)
+ CompilePhaseV("Constant Evaluate Full", [&]() {
+ ConvertHIR_ConstantEvaluateFull(*hir_crate);
+ });
+
+ CompilePhaseV("Dump HIR", [&]() {
+ ::std::ofstream os (FMT(params.outfile << "_2_hir.rs"));
+ HIR_Dump( os, *hir_crate );
+ });
+
// Optimise the MIR
// TODO: MIR Optimisation
diff --git a/src/mir/cleanup.cpp b/src/mir/cleanup.cpp
index c5a8c5b9..4268b288 100644
--- a/src/mir/cleanup.cpp
+++ b/src/mir/cleanup.cpp
@@ -74,6 +74,8 @@ const ::HIR::Literal* MIR_Cleanup_GetConstant(const Span& sp, const StaticTraitR
if( pe.m_params.m_types.size() != 0 )
TODO(sp, "Generic constants - " << path);
out_ty = constant.m_type.clone();
+ if( constant.m_value_res.is_Invalid() )
+ return nullptr;
return &constant.m_value_res;
),
(UfcsUnknown,
diff --git a/src/mir/mir.cpp b/src/mir/mir.cpp
index 2dd911ec..d7ae41cc 100644
--- a/src/mir/mir.cpp
+++ b/src/mir/mir.cpp
@@ -104,7 +104,33 @@ namespace MIR {
os << "Cast(" << e.val << " as " << e.type << ")";
),
(BinOp,
- os << "BinOp(" << e.val_l << " " << static_cast<int>(e.op) << " " << e.val_r << ")";
+ os << "BinOp(" << e.val_l << " ";
+ switch(e.op)
+ {
+ case ::MIR::eBinOp::ADD: os << "ADD"; break;
+ case ::MIR::eBinOp::SUB: os << "SUB"; break;
+ case ::MIR::eBinOp::MUL: os << "MUL"; break;
+ case ::MIR::eBinOp::DIV: os << "DIV"; break;
+ case ::MIR::eBinOp::MOD: os << "MOD"; break;
+ case ::MIR::eBinOp::ADD_OV: os << "ADD_OV"; break;
+ case ::MIR::eBinOp::SUB_OV: os << "SUB_OV"; break;
+ case ::MIR::eBinOp::MUL_OV: os << "MUL_OV"; break;
+ case ::MIR::eBinOp::DIV_OV: os << "DIV_OV"; break;
+
+ case ::MIR::eBinOp::BIT_OR : os << "BIT_OR" ; break;
+ case ::MIR::eBinOp::BIT_AND: os << "BIT_AND"; break;
+ case ::MIR::eBinOp::BIT_XOR: os << "BIT_XOR"; break;
+ case ::MIR::eBinOp::BIT_SHL: os << "BIT_SHL"; break;
+ case ::MIR::eBinOp::BIT_SHR: os << "BIT_SHR"; break;
+
+ case ::MIR::eBinOp::EQ: os << "EQ"; break;
+ case ::MIR::eBinOp::NE: os << "NE"; break;
+ case ::MIR::eBinOp::GT: os << "GT"; break;
+ case ::MIR::eBinOp::GE: os << "GE"; break;
+ case ::MIR::eBinOp::LT: os << "LT"; break;
+ case ::MIR::eBinOp::LE: os << "LE"; break;
+ }
+ os << " " << e.val_r << ")";
),
(UniOp,
os << "UniOp(" << e.val << " " << static_cast<int>(e.op) << ")";
diff --git a/src/trans/enumerate.cpp b/src/trans/enumerate.cpp
index 62f6648e..85bb7474 100644
--- a/src/trans/enumerate.cpp
+++ b/src/trans/enumerate.cpp
@@ -499,6 +499,31 @@ void Trans_Enumerate_FillFrom_MIR(TransList& out, const ::HIR::Crate& crate, con
}
}
+void Trans_Enumerate_FillFrom_Literal(TransList& out, const ::HIR::Crate& crate, const ::HIR::Literal& lit, const Trans_Params& pp)
+{
+ TU_MATCHA( (lit), (e),
+ (Invalid,
+ ),
+ (List,
+ for(const auto& v : e)
+ Trans_Enumerate_FillFrom_Literal(out, crate, v, pp);
+ ),
+ (Variant,
+ for(const auto& v : e.vals)
+ Trans_Enumerate_FillFrom_Literal(out, crate, v, pp);
+ ),
+ (Integer,
+ ),
+ (Float,
+ ),
+ (BorrowOf,
+ Trans_Enumerate_FillFrom_Path(out, crate, e, pp);
+ ),
+ (String,
+ )
+ )
+}
+
void Trans_Enumerate_FillFrom(TransList& out, const ::HIR::Crate& crate, const ::HIR::Function& function, TransList_Function& out_fcn, Trans_Params pp)
{
TRACE_FUNCTION_F("Function pp=" << pp.pp_method<<"+"<<pp.pp_impl);
@@ -516,6 +541,10 @@ void Trans_Enumerate_FillFrom(TransList& out, const ::HIR::Crate& crate, const :
{
Trans_Enumerate_FillFrom_MIR(out, crate, *item.m_value.m_mir, pp);
}
+ else if( ! item.m_value_res.is_Invalid() )
+ {
+ Trans_Enumerate_FillFrom_Literal(out, crate, item.m_value_res, pp);
+ }
out_stat.ptr = &item;
out_stat.pp = mv$(pp);
}