summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJohn Hodge <tpg@mutabah.net>2016-12-14 22:33:02 +0800
committerJohn Hodge <tpg@mutabah.net>2016-12-14 22:33:02 +0800
commit2a45f78605089afebfaf628aac50fc5fd51dfb25 (patch)
treef3bc7e7c0118c7f9990a50b7859d0ca8e81607a5
parentdb8c101b11d5f7a926144ccdb8d156fa11944d2a (diff)
downloadmrust-2a45f78605089afebfaf628aac50fc5fd51dfb25.tar.gz
Consteval - Re-enabled full first-pass consteval
-rw-r--r--Makefile2
-rw-r--r--src/hir/dump.cpp4
-rw-r--r--src/hir_conv/constant_evaluation.cpp29
-rw-r--r--src/hir_expand/const_eval_full.cpp122
-rw-r--r--src/main.cpp10
-rw-r--r--src/mir/check.cpp107
-rw-r--r--src/mir/cleanup.cpp13
-rw-r--r--src/mir/from_hir.cpp96
-rw-r--r--src/mir/from_hir_match.cpp3
-rw-r--r--src/mir/main_bindings.hpp3
-rw-r--r--src/mir/optimise.cpp12
-rw-r--r--src/mir/visit_crate_mir.cpp100
-rw-r--r--src/mir/visit_crate_mir.hpp47
13 files changed, 310 insertions, 238 deletions
diff --git a/Makefile b/Makefile
index 78a05e1c..46a34f86 100644
--- a/Makefile
+++ b/Makefile
@@ -92,7 +92,7 @@ OBJ += hir_expand/annotate_value_usage.o hir_expand/closures.o hir_expand/ufcs_e
OBJ += hir_expand/reborrow.o hir_expand/erased_types.o hir_expand/vtable.o
OBJ += hir_expand/const_eval_full.o
OBJ += mir/mir.o mir/mir_ptr.o
-OBJ += mir/dump.o mir/helpers.o
+OBJ += mir/dump.o mir/helpers.o mir/visit_crate_mir.o
OBJ += mir/from_hir.o mir/from_hir_match.o mir/mir_builder.o
OBJ += mir/check.o mir/cleanup.o mir/optimise.o
OBJ += hir/serialise.o hir/deserialise.o hir/serialise_lowlevel.o
diff --git a/src/hir/dump.cpp b/src/hir/dump.cpp
index 5801d5c3..6838f40b 100644
--- a/src/hir/dump.cpp
+++ b/src/hir/dump.cpp
@@ -417,11 +417,11 @@ namespace {
void visit(::HIR::ExprNode_BinOp& node) override
{
m_os << "(";
- this->visit_node_ptr(node.m_right);
+ this->visit_node_ptr(node.m_left);
m_os << ")";
m_os << " " << ::HIR::ExprNode_BinOp::opname(node.m_op) << " ";
m_os << "(";
- this->visit_node_ptr(node.m_left);
+ this->visit_node_ptr(node.m_right);
m_os << ")";
}
void visit(::HIR::ExprNode_UniOp& node) override
diff --git a/src/hir_conv/constant_evaluation.cpp b/src/hir_conv/constant_evaluation.cpp
index 4e15f2d5..64695f84 100644
--- a/src/hir_conv/constant_evaluation.cpp
+++ b/src/hir_conv/constant_evaluation.cpp
@@ -453,7 +453,10 @@ namespace {
}
void visit(::HIR::ExprNode_Borrow& node) override {
- badnode(node);
+ //m_rv_type = ::HIR::TypeRef();
+ //m_rv = ::HIR::Literal::make_BorrowOf( ::HIR::SimplePath() );
+ //return ;
+ //badnode(node);
TU_MATCH_DEF( ::HIR::TypeRef::Data, (m_exp_type.m_data), (te),
(
@@ -478,12 +481,13 @@ namespace {
auto name = FMT(m_newval_state.name_prefix << &node);
if( visit_ty_with(m_rv_type, [&](const auto& x){ return x.m_data.is_Infer(); }) ) {
- ERROR(node.span(), E0000, "Could not trivially infer type of referenced static");
+ ERROR(node.span(), E0000, "Could not trivially infer type of referenced static - " << m_rv_type << ", lit = " << val);
}
m_newval_state.newval_output.push_back(::std::make_pair( name, ::HIR::Static {
false,
- m_rv_type.clone(),
+ //m_rv_type.clone(),
+ {},
::HIR::ExprNodeP(),
mv$(val)
} ));
@@ -810,7 +814,9 @@ namespace {
// TODO: Should be a more complex path to support associated paths
ASSERT_BUG(node.span(), node.m_path.m_data.is_Generic(), "Function path not Path::Generic - " << node.m_path);
m_rv = ::HIR::Literal(node.m_path.m_data.as_Generic().m_path);
- m_rv_type = ::HIR::TypeRef(); // TODO: Better type
+ ::HIR::FunctionType fcn;
+ fcn.m_rettype = box$( e->m_return.clone() );
+ m_rv_type = ::HIR::TypeRef( mv$(fcn) ); // TODO: Better type
),
(Constant,
// TODO: Associated constants
@@ -913,6 +919,7 @@ namespace {
}
void visit(::HIR::ExprNode_Tuple& node) override
{
+ TRACE_FUNCTION_FR("_Tuple", m_rv);
::std::vector< ::HIR::TypeRef> exp_tys;
TU_MATCH_DEF(::HIR::TypeRef::Data, (m_exp_type.m_data), (te),
(
@@ -1491,6 +1498,10 @@ namespace {
case ::HIR::CoreType::U8: lit.as_Integer() &= (1ull<<8)-1; break;
case ::HIR::CoreType::U16: lit.as_Integer() &= (1ull<<16)-1; break;
case ::HIR::CoreType::U32: lit.as_Integer() &= (1ull<<32)-1; break;
+
+ case ::HIR::CoreType::I8: lit.as_Integer() &= (1ull<<8)-1; break;
+ case ::HIR::CoreType::I16: lit.as_Integer() &= (1ull<<16)-1; break;
+ case ::HIR::CoreType::I32: lit.as_Integer() &= (1ull<<32)-1; break;
default:
break;
}
@@ -1554,11 +1565,14 @@ namespace {
{
::HIR::Visitor::visit_constant(p, item);
- //visit_type(item.m_type);
if( item.m_value )
{
- if( ! item.m_type.m_data.is_Primitive() )
- return ;
+ //if( item.m_type.m_data.is_Primitive() )
+ // ;
+ //else if( item.m_type.m_data.is_Borrow() && *item.m_type.m_data.as_Borrow().inner == ::HIR::CoreType::Str )
+ // ;
+ //else
+ // 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(), {});
@@ -1566,7 +1580,6 @@ namespace {
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_enum(::HIR::ItemPath p, ::HIR::Enum& item) override {
diff --git a/src/hir_expand/const_eval_full.cpp b/src/hir_expand/const_eval_full.cpp
index ba8be303..3246fc90 100644
--- a/src/hir_expand/const_eval_full.cpp
+++ b/src/hir_expand/const_eval_full.cpp
@@ -333,7 +333,7 @@ namespace {
return args[e.idx];
),
(Static,
- TODO(sp, "LValue::Static");
+ TODO(sp, "LValue::Static - " << e);
),
(Return,
return retval;
@@ -468,38 +468,39 @@ namespace {
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;
-
+ auto cast_to_int = [&inval,&e,&sp](bool is_signed, unsigned bits) {
+ uint64_t mask = (bits >= 64 ? ~0ull : (1ull << bits) - 1);
+ uint64_t outval;
TU_IFLET( ::HIR::Literal, inval, Integer, i,
- val = ::HIR::Literal(i & mask);
+ outval = i & mask;
+ if( bits < 64 && is_signed && (outval >> (bits-1)) )
+ outval |= ~mask;
)
else TU_IFLET( ::HIR::Literal, inval, Float, i,
- val = ::HIR::Literal( static_cast<uint64_t>(i) & mask);
+ outval = static_cast<uint64_t>(i) & mask;
+ if( is_signed && i < 0 )
+ outval |= ~mask;
)
else {
BUG(sp, "Invalid cast of " << inval.tag_str() << " to " << e.type);
}
- break;
+ return ::HIR::Literal(outval);
+ };
+ switch(te)
+ {
+ // Integers mask down
+ case ::HIR::CoreType::I8: val = cast_to_int(true , 8); break;
+ case ::HIR::CoreType::U8: val = cast_to_int(false, 8); break;
+ case ::HIR::CoreType::I16: val = cast_to_int(true , 16); break;
+ case ::HIR::CoreType::U16: val = cast_to_int(false, 16); break;
+ case ::HIR::CoreType::I32: val = cast_to_int(true , 32); break;
+ case ::HIR::CoreType::U32: val = cast_to_int(false, 32); break;
+
+ case ::HIR::CoreType::I64: val = cast_to_int(true , 64); break;
+ case ::HIR::CoreType::U64: val = cast_to_int(false, 64); break;
+ case ::HIR::CoreType::Isize: val = cast_to_int(true , 64); break;
+ case ::HIR::CoreType::Usize: val = cast_to_int(false, 64); break;
+
case ::HIR::CoreType::F32:
case ::HIR::CoreType::F64:
TU_IFLET( ::HIR::Literal, inval, Integer, i,
@@ -724,6 +725,74 @@ namespace {
BUG(sp, "Attempting to evaluate constant expression with no associated code");
}
}
+
+ void check_lit_type(const Span& sp, const ::HIR::TypeRef& type, ::HIR::Literal& lit)
+ {
+ // TODO: Mask down limited size integers
+ TU_MATCHA( (type.m_data), (te),
+ (Infer,
+ ),
+ (Diverge,
+ ),
+ (Generic,
+ ),
+ (Slice,
+ ),
+ (TraitObject,
+ ),
+ (ErasedType,
+ ),
+ (Closure,
+ ),
+
+ (Path,
+ // List
+ ),
+ (Array,
+ // List
+ ),
+ (Tuple,
+ // List
+ ),
+
+ (Borrow,
+ // A whole host of things
+ ),
+ (Pointer,
+ // Integer, or itemaddr?
+ ),
+ (Function,
+ // ItemAddr
+ ),
+
+ (Primitive,
+ switch(te)
+ {
+ case ::HIR::CoreType::Str:
+ BUG(sp, "Direct str literal not valid");
+ case ::HIR::CoreType::F32:
+ case ::HIR::CoreType::F64:
+ ASSERT_BUG(sp, lit.is_Float(), "Bad literal type for " << type << " - " << lit);
+ break;
+ default:
+ ASSERT_BUG(sp, lit.is_Integer(), "Bad literal type for " << type << " - " << lit);
+ switch(te)
+ {
+ case ::HIR::CoreType::U8: lit.as_Integer() &= (1ull<<8)-1; break;
+ case ::HIR::CoreType::U16: lit.as_Integer() &= (1ull<<16)-1; break;
+ case ::HIR::CoreType::U32: lit.as_Integer() &= (1ull<<32)-1; break;
+
+ //case ::HIR::CoreType::I8: lit.as_Integer() &= (1ull<<8)-1; break;
+ //case ::HIR::CoreType::I16: lit.as_Integer() &= (1ull<<16)-1; break;
+ //case ::HIR::CoreType::I32: lit.as_Integer() &= (1ull<<32)-1; break;
+ default:
+ break;
+ }
+ break;
+ }
+ )
+ )
+ }
class Expander:
public ::HIR::Visitor
@@ -775,6 +844,7 @@ namespace {
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, {}, {});
+ 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);
}
diff --git a/src/main.cpp b/src/main.cpp
index 33bed1bb..b8219c48 100644
--- a/src/main.cpp
+++ b/src/main.cpp
@@ -65,6 +65,8 @@ void init_debug_list()
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( "MIR Cleanup" );
+ g_debug_disable_map.insert( "MIR Optimise" );
g_debug_disable_map.insert( "HIR Serialise" );
g_debug_disable_map.insert( "Trans Enumerate" );
@@ -395,13 +397,13 @@ int main(int argc, char *argv[])
HIR_Dump( os, *hir_crate );
});
- // - Expand constants in MIR
- CompilePhaseV("MIR Const Expand", [&]() {
- //MIR_ExpandConstants(*hir_crate);
+ // - Expand constants in HIR and virtualise calls
+ CompilePhaseV("MIR Cleanup", [&]() {
+ MIR_CleanupCrate(*hir_crate);
});
// Optimise the MIR
CompilePhaseV("MIR Optimise", [&]() {
- //MIR_Optimise(*hir_crate);
+ MIR_OptimiseCrate(*hir_crate);
});
CompilePhaseV("Dump MIR", [&]() {
diff --git a/src/mir/check.cpp b/src/mir/check.cpp
index 80fd65a9..4550a662 100644
--- a/src/mir/check.cpp
+++ b/src/mir/check.cpp
@@ -10,6 +10,7 @@
#include <hir/visitor.hpp>
#include <hir_typeck/static.hpp>
#include <mir/helpers.hpp>
+#include <mir/visit_crate_mir.hpp>
void MIR_Validate(const StaticTraitResolve& resolve, const ::HIR::ItemPath& path, const ::MIR::Function& fcn, const ::HIR::Function::args_t& args, const ::HIR::TypeRef& ret_type)
{
@@ -293,110 +294,14 @@ void MIR_Validate(const StaticTraitResolve& resolve, const ::HIR::ItemPath& path
}
}
-namespace {
- // TODO: Create visitor that handles setting up a StaticTraitResolve?
- class OuterVisitor:
- public ::HIR::Visitor
- {
- StaticTraitResolve m_resolve;
- public:
- OuterVisitor(const ::HIR::Crate& crate):
- m_resolve(crate)
- {}
-
- // NOTE: This is left here to ensure that any expressions that aren't handled by higher code cause a failure
- void visit_expr(::HIR::ExprPtr& exp) override {
- BUG(Span(), "visit_expr hit in OuterVisitor");
- }
-
- void visit_type(::HIR::TypeRef& ty) override
- {
- TU_IFLET(::HIR::TypeRef::Data, ty.m_data, Array, e,
- this->visit_type( *e.inner );
- DEBUG("Array size " << ty);
- if( e.size ) {
- MIR_Validate(m_resolve, ::HIR::ItemPath(), *e.size->m_mir, {}, ::HIR::TypeRef(::HIR::CoreType::Usize));
- }
- )
- else {
- ::HIR::Visitor::visit_type(ty);
- }
- }
-
- // ------
- // Code-containing items
- // ------
- void visit_function(::HIR::ItemPath p, ::HIR::Function& item) override {
- auto _ = this->m_resolve.set_item_generics(item.m_params);
- if( item.m_code ) {
- DEBUG("Function code " << p);
- // TODO: Get span without needing hir/expr.hpp
- static Span sp;
-
- // Replace ErasedType instances in `ret_type`
- const auto& ret_type = item.m_return;
- auto ret_type_v = clone_ty_with(sp, ret_type, [&](const auto& tpl, auto& rv) {
- if( tpl.m_data.is_ErasedType() )
- {
- const auto& e = tpl.m_data.as_ErasedType();
- assert(e.m_index < item.m_code.m_erased_types.size());
- rv = item.m_code.m_erased_types[e.m_index].clone();
- return true;
- }
- return false;
- });
- this->m_resolve.expand_associated_types(sp, ret_type_v);
-
- MIR_Validate(m_resolve, p, *item.m_code.m_mir, item.m_args, ret_type_v);
- }
- }
- void visit_static(::HIR::ItemPath p, ::HIR::Static& item) override {
- if( item.m_value ) {
- DEBUG("`static` value " << p);
- MIR_Validate(m_resolve, p, *item.m_value.m_mir, {}, item.m_type);
- }
- }
- void visit_constant(::HIR::ItemPath p, ::HIR::Constant& item) override {
- if( item.m_value ) {
- DEBUG("`const` value " << p);
- MIR_Validate(m_resolve, p, *item.m_value.m_mir, {}, item.m_type);
- }
- }
- void visit_enum(::HIR::ItemPath p, ::HIR::Enum& item) override {
- auto _ = this->m_resolve.set_item_generics(item.m_params);
-
- // TODO: Use a different type depding on repr()
- auto enum_type = ::HIR::TypeRef(::HIR::CoreType::Isize);
-
- for(auto& var : item.m_variants)
- {
- TU_IFLET(::HIR::Enum::Variant, var.second, Value, e,
- // TODO: Get the repr type
- MIR_Validate(m_resolve, p + var.first, *e.expr.m_mir, {}, enum_type);
- )
- }
- }
-
- // Boilerplate
- void visit_trait(::HIR::ItemPath p, ::HIR::Trait& item) override {
- auto _ = this->m_resolve.set_impl_generics(item.m_params);
- ::HIR::Visitor::visit_trait(p, item);
- }
- void visit_type_impl(::HIR::TypeImpl& impl) override {
- auto _ = this->m_resolve.set_impl_generics(impl.m_params);
- ::HIR::Visitor::visit_type_impl(impl);
- }
- void visit_trait_impl(const ::HIR::SimplePath& trait_path, ::HIR::TraitImpl& impl) override {
- auto _ = this->m_resolve.set_impl_generics(impl.m_params);
- ::HIR::Visitor::visit_trait_impl(trait_path, impl);
- }
- };
-}
-
// --------------------------------------------------------------------
void MIR_CheckCrate(/*const*/ ::HIR::Crate& crate)
{
- OuterVisitor ov(crate);
+ ::MIR::OuterVisitor ov(crate, [](const auto& res, const auto& p, auto& expr, const auto& args, const auto& ty)
+ {
+ MIR_Validate(res, p, *expr.m_mir, args, ty);
+ }
+ );
ov.visit_crate( crate );
}
diff --git a/src/mir/cleanup.cpp b/src/mir/cleanup.cpp
index 0050d475..f8f151ce 100644
--- a/src/mir/cleanup.cpp
+++ b/src/mir/cleanup.cpp
@@ -15,6 +15,7 @@
#include <hir_typeck/static.hpp>
#include <mir/helpers.hpp>
#include <mir/operations.hpp>
+#include <mir/visit_crate_mir.hpp>
struct MirMutator
{
@@ -1018,9 +1019,13 @@ void MIR_Cleanup(const StaticTraitResolve& resolve, const ::HIR::ItemPath& path,
mutator.cur_block += 1;
mutator.cur_stmt = 0;
}
-
-
- // TODO: Make this configurable once the optimisations become expensive
- MIR_Optimise(resolve, path, fcn, args, ret_type);
+}
+
+void MIR_CleanupCrate(::HIR::Crate& crate)
+{
+ ::MIR::OuterVisitor ov { crate, [&](const auto& res, const auto& p, auto& expr_ptr, const auto& args, const auto& ty){
+ MIR_Cleanup(res, p, *expr_ptr.m_mir, args, ty);
+ } };
+ ov.visit_crate(crate);
}
diff --git a/src/mir/from_hir.cpp b/src/mir/from_hir.cpp
index 258449ef..72fe1645 100644
--- a/src/mir/from_hir.cpp
+++ b/src/mir/from_hir.cpp
@@ -16,6 +16,7 @@
#include "main_bindings.hpp"
#include "from_hir.hpp"
#include "operations.hpp"
+#include <mir/visit_crate_mir.hpp>
namespace {
@@ -1881,103 +1882,16 @@ namespace {
root_node.visit( ev );
}
- ::HIR::TypeRef ret;
- MIR_Cleanup(resolve, path, fcn, args, ret);
-
return ::MIR::FunctionPointer(new ::MIR::Function(mv$(fcn)));
}
-namespace {
- // TODO: Create visitor that handles setting up a StaticTraitResolve?
- class OuterVisitor:
- public ::HIR::Visitor
- {
- StaticTraitResolve m_resolve;
- public:
- OuterVisitor(const ::HIR::Crate& crate):
- m_resolve(crate)
- {}
-
- // NOTE: This is left here to ensure that any expressions that aren't handled by higher code cause a failure
- void visit_expr(::HIR::ExprPtr& exp) override {
- BUG(Span(), "visit_expr hit in OuterVisitor");
- }
-
- void visit_type(::HIR::TypeRef& ty) override
- {
- TU_IFLET(::HIR::TypeRef::Data, ty.m_data, Array, e,
- this->visit_type( *e.inner );
- DEBUG("Array size " << ty);
- if( e.size ) {
- auto fcn = LowerMIR(m_resolve, ::HIR::ItemPath(), *e.size, {});
- e.size->m_mir = mv$(fcn);
- }
- )
- else {
- ::HIR::Visitor::visit_type(ty);
- }
- }
-
- // ------
- // Code-containing items
- // ------
- void visit_function(::HIR::ItemPath p, ::HIR::Function& item) override {
- auto _ = this->m_resolve.set_item_generics(item.m_params);
- if( item.m_code )
- {
- DEBUG("Function code " << p);
- item.m_code.m_mir = LowerMIR(m_resolve, p, item.m_code, item.m_args);
- }
- else
- {
- DEBUG("Function code " << p << " (none)");
- }
- }
- void visit_static(::HIR::ItemPath p, ::HIR::Static& item) override {
- if( item.m_value )
- {
- DEBUG("`static` value " << p);
- item.m_value.m_mir = LowerMIR(m_resolve, p, item.m_value, {});
- }
- }
- void visit_constant(::HIR::ItemPath p, ::HIR::Constant& item) override {
- if( item.m_value )
- {
- DEBUG("`const` value " << p);
- item.m_value.m_mir = LowerMIR(m_resolve, p, item.m_value, {});
- }
- }
- void visit_enum(::HIR::ItemPath p, ::HIR::Enum& item) override {
- auto _ = this->m_resolve.set_item_generics(item.m_params);
- for(auto& var : item.m_variants)
- {
- TU_IFLET(::HIR::Enum::Variant, var.second, Value, e,
- e.expr.m_mir = LowerMIR(m_resolve, p + var.first, e.expr, {});
- )
- }
- }
-
- // Boilerplate
- void visit_trait(::HIR::ItemPath p, ::HIR::Trait& item) override {
- auto _ = this->m_resolve.set_impl_generics(item.m_params);
- ::HIR::Visitor::visit_trait(p, item);
- }
- void visit_type_impl(::HIR::TypeImpl& impl) override {
- auto _ = this->m_resolve.set_impl_generics(impl.m_params);
- ::HIR::Visitor::visit_type_impl(impl);
- }
- void visit_trait_impl(const ::HIR::SimplePath& trait_path, ::HIR::TraitImpl& impl) override {
- auto _ = this->m_resolve.set_impl_generics(impl.m_params);
- ::HIR::Visitor::visit_trait_impl(trait_path, impl);
- }
- };
-}
-
// --------------------------------------------------------------------
void HIR_GenerateMIR(::HIR::Crate& crate)
{
- OuterVisitor ov(crate);
- ov.visit_crate( crate );
+ ::MIR::OuterVisitor ov { crate, [&](const auto& res, const auto& p, auto& expr_ptr, const auto& args, const auto& ty){
+ expr_ptr.m_mir = LowerMIR(res, p, expr_ptr, args);
+ } };
+ ov.visit_crate(crate);
}
diff --git a/src/mir/from_hir_match.cpp b/src/mir/from_hir_match.cpp
index c26dbc41..68f4f24b 100644
--- a/src/mir/from_hir_match.cpp
+++ b/src/mir/from_hir_match.cpp
@@ -2156,7 +2156,8 @@ namespace
const char* name, const field_path_t& field_path, ::std::function<void(DecisionTreeNode::Branch&)> and_then
)
{
- ASSERT_BUG(sp, ve_start < ve_end, "Range pattern with one value - " << ve_start << "..." << ve_end);
+ ASSERT_BUG(sp, ve_start != ve_end, "Range pattern with one value - " << ve_start);
+ ASSERT_BUG(sp, ve_start < ve_end, "Range pattern with a start after the end - " << ve_start << "..." << ve_end);
TRACE_FUNCTION_F("[" << FMT_CB(os, for(const auto& i:be) os << i.first <<" , ";) << "]");
// - Find the first entry that ends after the new one starts.
diff --git a/src/mir/main_bindings.hpp b/src/mir/main_bindings.hpp
index 89301a54..dc9a61a9 100644
--- a/src/mir/main_bindings.hpp
+++ b/src/mir/main_bindings.hpp
@@ -15,3 +15,6 @@ class Crate;
extern void HIR_GenerateMIR(::HIR::Crate& crate);
extern void MIR_Dump(::std::ostream& sink, const ::HIR::Crate& crate);
extern void MIR_CheckCrate(/*const*/ ::HIR::Crate& crate);
+
+extern void MIR_CleanupCrate(::HIR::Crate& crate);
+extern void MIR_OptimiseCrate(::HIR::Crate& crate);
diff --git a/src/mir/optimise.cpp b/src/mir/optimise.cpp
index d599c07c..3086ec3f 100644
--- a/src/mir/optimise.cpp
+++ b/src/mir/optimise.cpp
@@ -12,6 +12,7 @@
#include <hir_typeck/static.hpp>
#include <mir/helpers.hpp>
#include <mir/operations.hpp>
+#include <mir/visit_crate_mir.hpp>
namespace {
::MIR::BasicBlockId get_new_target(const ::MIR::TypeResolve& state, ::MIR::BasicBlockId bb)
@@ -173,3 +174,14 @@ void MIR_Optimise(const StaticTraitResolve& resolve, const ::HIR::ItemPath& path
}
}
}
+
+void MIR_OptimiseCrate(::HIR::Crate& crate)
+{
+ ::MIR::OuterVisitor ov { crate, [](const auto& res, const auto& p, auto& expr, const auto& args, const auto& ty)
+ {
+ MIR_Optimise(res, p, *expr.m_mir, args, ty);
+ }
+ };
+ ov.visit_crate(crate);
+}
+
diff --git a/src/mir/visit_crate_mir.cpp b/src/mir/visit_crate_mir.cpp
new file mode 100644
index 00000000..4cd1fddc
--- /dev/null
+++ b/src/mir/visit_crate_mir.cpp
@@ -0,0 +1,100 @@
+/*
+ * MRustC - Rust Compiler
+ * - By John Hodge (Mutabah/thePowersGang)
+ *
+ * mir/visit_crate_mir.cpp
+ * - Visitor to visit all MIR blobs in a crate
+ */
+#include "visit_crate_mir.hpp"
+#include <hir/expr.hpp>
+
+// NOTE: This is left here to ensure that any expressions that aren't handled by higher code cause a failure
+void MIR::OuterVisitor::visit_expr(::HIR::ExprPtr& exp)
+{
+ BUG(Span(), "visit_expr hit in OuterVisitor");
+}
+
+void MIR::OuterVisitor::visit_type(::HIR::TypeRef& ty)
+{
+ TU_IFLET(::HIR::TypeRef::Data, ty.m_data, Array, e,
+ this->visit_type( *e.inner );
+ DEBUG("Array size " << ty);
+ if( e.size ) {
+ m_cb(m_resolve, ::HIR::ItemPath(), *e.size, {}, ::HIR::TypeRef(::HIR::CoreType::Usize));
+ }
+ )
+ else {
+ ::HIR::Visitor::visit_type(ty);
+ }
+}
+
+void MIR::OuterVisitor::visit_function(::HIR::ItemPath p, ::HIR::Function& item)
+{
+ auto _ = this->m_resolve.set_item_generics(item.m_params);
+ if( item.m_code )
+ {
+ DEBUG("Function code " << p);
+ // TODO: Get span without needing hir/expr.hpp
+ static Span sp;
+
+ // Replace ErasedType instances in `ret_type`
+ const auto& ret_type = item.m_return;
+ auto ret_type_v = clone_ty_with(sp, ret_type, [&](const auto& tpl, auto& rv) {
+ if( tpl.m_data.is_ErasedType() )
+ {
+ const auto& e = tpl.m_data.as_ErasedType();
+ assert(e.m_index < item.m_code.m_erased_types.size());
+ rv = item.m_code.m_erased_types[e.m_index].clone();
+ return true;
+ }
+ return false;
+ });
+ this->m_resolve.expand_associated_types(sp, ret_type_v);
+
+ m_cb(m_resolve, p, item.m_code, item.m_args, ret_type_v);
+ }
+}
+void MIR::OuterVisitor::visit_static(::HIR::ItemPath p, ::HIR::Static& item)
+{
+ if( item.m_value ) {
+ DEBUG("`static` value " << p);
+ m_cb(m_resolve, p, item.m_value, {}, item.m_type);
+ }
+}
+void MIR::OuterVisitor::visit_constant(::HIR::ItemPath p, ::HIR::Constant& item)
+{
+ if( item.m_value ) {
+ DEBUG("`const` value " << p);
+ m_cb(m_resolve, p, item.m_value, {}, item.m_type);
+ }
+}
+void MIR::OuterVisitor::visit_enum(::HIR::ItemPath p, ::HIR::Enum& item)
+{
+ auto _ = this->m_resolve.set_item_generics(item.m_params);
+
+ // TODO: Use a different type depding on repr()
+ auto enum_type = ::HIR::TypeRef(::HIR::CoreType::Isize);
+
+ for(auto& var : item.m_variants)
+ {
+ TU_IFLET(::HIR::Enum::Variant, var.second, Value, e,
+ m_cb(m_resolve, p + var.first, e.expr, {}, enum_type);
+ )
+ }
+}
+
+void MIR::OuterVisitor::visit_trait(::HIR::ItemPath p, ::HIR::Trait& item)
+{
+ auto _ = this->m_resolve.set_impl_generics(item.m_params);
+ ::HIR::Visitor::visit_trait(p, item);
+}
+void MIR::OuterVisitor::visit_type_impl(::HIR::TypeImpl& impl)
+{
+ auto _ = this->m_resolve.set_impl_generics(impl.m_params);
+ ::HIR::Visitor::visit_type_impl(impl);
+}
+void MIR::OuterVisitor::visit_trait_impl(const ::HIR::SimplePath& trait_path, ::HIR::TraitImpl& impl)
+{
+ auto _ = this->m_resolve.set_impl_generics(impl.m_params);
+ ::HIR::Visitor::visit_trait_impl(trait_path, impl);
+}
diff --git a/src/mir/visit_crate_mir.hpp b/src/mir/visit_crate_mir.hpp
new file mode 100644
index 00000000..e6964545
--- /dev/null
+++ b/src/mir/visit_crate_mir.hpp
@@ -0,0 +1,47 @@
+/*
+ * MRustC - Rust Compiler
+ * - By John Hodge (Mutabah/thePowersGang)
+ *
+ * mir/visit_crate_mir.hpp
+ * - Visitor to visit all expressions in a crate
+ */
+#pragma once
+#include <hir/visitor.hpp>
+#include <hir_typeck/static.hpp>
+
+namespace MIR {
+
+class OuterVisitor:
+ public ::HIR::Visitor
+{
+public:
+ typedef ::std::function<void(const StaticTraitResolve& resolve, const ::HIR::ItemPath& ip, ::HIR::ExprPtr& expr, const ::HIR::Function::args_t& args, const ::HIR::TypeRef& ret_type)> cb_t;
+private:
+ StaticTraitResolve m_resolve;
+ cb_t m_cb;
+public:
+ OuterVisitor(const ::HIR::Crate& crate, cb_t cb):
+ m_resolve(crate),
+ m_cb(cb)
+ {}
+
+ void visit_expr(::HIR::ExprPtr& exp) override;
+
+ void visit_type(::HIR::TypeRef& ty) override;
+
+ // ------
+ // Code-containing items
+ // ------
+ void visit_function(::HIR::ItemPath p, ::HIR::Function& item) override;
+ void visit_static(::HIR::ItemPath p, ::HIR::Static& item) override;
+ void visit_constant(::HIR::ItemPath p, ::HIR::Constant& item) override;
+ void visit_enum(::HIR::ItemPath p, ::HIR::Enum& item) override;
+
+ // Boilerplate
+ void visit_trait(::HIR::ItemPath p, ::HIR::Trait& item) override;
+ void visit_type_impl(::HIR::TypeImpl& impl) override;
+ void visit_trait_impl(const ::HIR::SimplePath& trait_path, ::HIR::TraitImpl& impl) override;
+};
+
+
+} // namespace MIR