diff options
author | John Hodge <tpg@mutabah.net> | 2016-12-14 22:33:02 +0800 |
---|---|---|
committer | John Hodge <tpg@mutabah.net> | 2016-12-14 22:33:02 +0800 |
commit | 2a45f78605089afebfaf628aac50fc5fd51dfb25 (patch) | |
tree | f3bc7e7c0118c7f9990a50b7859d0ca8e81607a5 | |
parent | db8c101b11d5f7a926144ccdb8d156fa11944d2a (diff) | |
download | mrust-2a45f78605089afebfaf628aac50fc5fd51dfb25.tar.gz |
Consteval - Re-enabled full first-pass consteval
-rw-r--r-- | Makefile | 2 | ||||
-rw-r--r-- | src/hir/dump.cpp | 4 | ||||
-rw-r--r-- | src/hir_conv/constant_evaluation.cpp | 29 | ||||
-rw-r--r-- | src/hir_expand/const_eval_full.cpp | 122 | ||||
-rw-r--r-- | src/main.cpp | 10 | ||||
-rw-r--r-- | src/mir/check.cpp | 107 | ||||
-rw-r--r-- | src/mir/cleanup.cpp | 13 | ||||
-rw-r--r-- | src/mir/from_hir.cpp | 96 | ||||
-rw-r--r-- | src/mir/from_hir_match.cpp | 3 | ||||
-rw-r--r-- | src/mir/main_bindings.hpp | 3 | ||||
-rw-r--r-- | src/mir/optimise.cpp | 12 | ||||
-rw-r--r-- | src/mir/visit_crate_mir.cpp | 100 | ||||
-rw-r--r-- | src/mir/visit_crate_mir.hpp | 47 |
13 files changed, 310 insertions, 238 deletions
@@ -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 |