summaryrefslogtreecommitdiff
path: root/src/mir
diff options
context:
space:
mode:
Diffstat (limited to 'src/mir')
-rw-r--r--src/mir/check.cpp2
-rw-r--r--src/mir/cleanup.cpp2
-rw-r--r--src/mir/dump.cpp6
-rw-r--r--src/mir/from_hir.cpp35
-rw-r--r--src/mir/main_bindings.hpp6
-rw-r--r--src/mir/mir_builder.cpp1
-rw-r--r--src/mir/optimise.cpp147
7 files changed, 146 insertions, 53 deletions
diff --git a/src/mir/check.cpp b/src/mir/check.cpp
index cfcc52d4..b2d86590 100644
--- a/src/mir/check.cpp
+++ b/src/mir/check.cpp
@@ -285,6 +285,8 @@ void MIR_Validate_ValState(::MIR::TypeResolve& state, const ::MIR::Function& fcn
};
::std::vector<ToVisit> to_visit_blocks;
+ // TODO: Check that all used locals are also set (anywhere at all)
+
auto add_to_visit = [&](unsigned int idx, ::std::vector<unsigned int> src_path, auto vs) {
for(const auto& b : to_visit_blocks)
if( b.bb == idx && b.state == vs)
diff --git a/src/mir/cleanup.cpp b/src/mir/cleanup.cpp
index 78939f78..37d256df 100644
--- a/src/mir/cleanup.cpp
+++ b/src/mir/cleanup.cpp
@@ -1219,7 +1219,7 @@ void MIR_Cleanup(const StaticTraitResolve& resolve, const ::HIR::ItemPath& path,
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);
+ MIR_Cleanup(res, p, expr_ptr.get_mir_or_error_mut(Span()), args, ty);
} };
ov.visit_crate(crate);
}
diff --git a/src/mir/dump.cpp b/src/mir/dump.cpp
index c390f5b6..90b81d5d 100644
--- a/src/mir/dump.cpp
+++ b/src/mir/dump.cpp
@@ -515,7 +515,7 @@ namespace {
{
m_os << indent() << "{\n";
inc_indent();
- dump_mir(m_os, m_indent_level, *item.m_code.m_mir);
+ dump_mir(m_os, m_indent_level, item.m_code.get_mir_or_error(Span()));
dec_indent();
m_os << indent() << "}\n";
}
@@ -538,7 +538,7 @@ namespace {
inc_indent();
m_os << " = {\n";
inc_indent();
- dump_mir(m_os, m_indent_level, *item.m_value.m_mir);
+ dump_mir(m_os, m_indent_level, item.m_value.get_mir_or_error(Span()));
dec_indent();
m_os << indent() << "} /* = " << item.m_value_res << "*/;\n";
dec_indent();
@@ -562,7 +562,7 @@ namespace {
inc_indent();
m_os << " = {\n";
inc_indent();
- dump_mir(m_os, m_indent_level, *item.m_value.m_mir);
+ dump_mir(m_os, m_indent_level, item.m_value.get_mir_or_error(Span()));
dec_indent();
m_os << indent() << "} /* = " << item.m_value_res << "*/;\n";
dec_indent();
diff --git a/src/mir/from_hir.cpp b/src/mir/from_hir.cpp
index 84d60082..6a96ab64 100644
--- a/src/mir/from_hir.cpp
+++ b/src/mir/from_hir.cpp
@@ -17,7 +17,7 @@
#include "from_hir.hpp"
#include "operations.hpp"
#include <mir/visit_crate_mir.hpp>
-
+#include <hir/expr_state.hpp>
namespace {
@@ -1037,9 +1037,8 @@ namespace {
// Short-circuiting boolean operations
if( node.m_op == ::HIR::ExprNode_BinOp::Op::BoolAnd || node.m_op == ::HIR::ExprNode_BinOp::Op::BoolOr )
{
- // TODO: Generate a SplitScope to handle the early breaks.
- auto split_scope = m_builder.new_scope_split(node.span());
+ DEBUG("- ShortCircuit Left");
this->visit_node_ptr(node.m_left);
auto left = m_builder.get_result_in_lvalue(node.m_left->span(), ty_l);
@@ -1048,12 +1047,16 @@ namespace {
auto bb_false = m_builder.new_bb_unlinked();
m_builder.end_block( ::MIR::Terminator::make_If({ mv$(left), bb_true, bb_false }) );
+ // Generate a SplitScope to handle the conditional nature of the next code
+ auto split_scope = m_builder.new_scope_split(node.span());
+
if( node.m_op == ::HIR::ExprNode_BinOp::Op::BoolOr )
{
+ DEBUG("- ShortCircuit ||");
// If left is true, assign result true and return
m_builder.set_cur_block( bb_true );
m_builder.push_stmt_assign(node.span(), res.clone(), ::MIR::RValue( ::MIR::Constant::make_Bool({true}) ));
- m_builder.end_split_arm(node.m_left->span(), split_scope, true);
+ m_builder.end_split_arm(node.m_left->span(), split_scope, /*reachable=*/true);
m_builder.end_block( ::MIR::Terminator::make_Goto(bb_next) );
// If left is false, assign result to right
@@ -1061,22 +1064,24 @@ namespace {
}
else
{
+ DEBUG("- ShortCircuit &&");
// If left is false, assign result false and return
m_builder.set_cur_block( bb_false );
m_builder.push_stmt_assign(node.span(), res.clone(), ::MIR::RValue( ::MIR::Constant::make_Bool({false}) ));
- m_builder.end_split_arm(node.m_left->span(), split_scope, true);
+ m_builder.end_split_arm(node.m_left->span(), split_scope, /*reachable=*/true);
m_builder.end_block( ::MIR::Terminator::make_Goto(bb_next) );
// If left is true, assign result to right
m_builder.set_cur_block( bb_true );
}
+ DEBUG("- ShortCircuit Right");
auto tmp_scope = m_builder.new_scope_temp(node.m_right->span());
this->visit_node_ptr(node.m_right);
m_builder.push_stmt_assign(node.span(), res.clone(), m_builder.get_result(node.m_right->span()));
m_builder.terminate_scope(node.m_right->span(), mv$(tmp_scope));
- m_builder.end_split_arm(node.m_left->span(), split_scope, true);
+ m_builder.end_split_arm(node.m_right->span(), split_scope, /*reachable=*/true);
m_builder.end_block( ::MIR::Terminator::make_Goto(bb_next) );
m_builder.set_cur_block( bb_next );
@@ -1605,7 +1610,7 @@ namespace {
// Extract the "Place" type
m_builder.end_block(::MIR::Terminator::make_Call({
place__ok, place__panic,
- place.clone(), ::HIR::Path(place_type.clone(), ::HIR::GenericPath(path_Placer, trait_params_data.clone()), "make_place", {}),
+ place.clone(), ::HIR::Path(node.m_place->m_res_type.clone(), ::HIR::GenericPath(path_Placer, trait_params_data.clone()), "make_place", {}),
::make_vec1( mv$(val) )
}));
break; }
@@ -2417,10 +2422,24 @@ namespace {
// --------------------------------------------------------------------
+void HIR_GenerateMIR_Expr(const ::HIR::Crate& crate, const ::HIR::ItemPath& path, ::HIR::ExprPtr& expr_ptr, const ::HIR::Function::args_t& args, const ::HIR::TypeRef& res_ty)
+{
+ if( !expr_ptr.m_mir )
+ {
+ StaticTraitResolve resolve { crate };
+ if(expr_ptr.m_state->m_impl_generics) resolve.set_impl_generics(*expr_ptr.m_state->m_impl_generics);
+ if(expr_ptr.m_state->m_item_generics) resolve.set_item_generics(*expr_ptr.m_state->m_item_generics);
+ expr_ptr.set_mir( LowerMIR(resolve, path, expr_ptr, res_ty, args) );
+ }
+}
+
void HIR_GenerateMIR(::HIR::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, ty, args);
+ if( !expr_ptr.get_mir_opt() )
+ {
+ expr_ptr.set_mir( LowerMIR(res, p, expr_ptr, ty, args) );
+ }
} };
ov.visit_crate(crate);
}
diff --git a/src/mir/main_bindings.hpp b/src/mir/main_bindings.hpp
index cb4f3232..69d5fd90 100644
--- a/src/mir/main_bindings.hpp
+++ b/src/mir/main_bindings.hpp
@@ -7,10 +7,8 @@
*/
#pragma once
#include <iostream>
+#include <hir/hir.hpp>
-namespace HIR {
-class Crate;
-}
class TransList;
extern void HIR_GenerateMIR(::HIR::Crate& crate);
@@ -21,3 +19,5 @@ extern void MIR_CheckCrate_Full(/*const*/ ::HIR::Crate& crate);
extern void MIR_CleanupCrate(::HIR::Crate& crate);
extern void MIR_OptimiseCrate(::HIR::Crate& crate, bool minimal_optimisations);
extern void MIR_OptimiseCrate_Inlining(const ::HIR::Crate& crate, TransList& list);
+
+extern void HIR_GenerateMIR_Expr(const ::HIR::Crate& crate, const ::HIR::ItemPath& path, ::HIR::ExprPtr& expr_ptr, const ::HIR::Function::args_t& args, const ::HIR::TypeRef& res_ty);
diff --git a/src/mir/mir_builder.cpp b/src/mir/mir_builder.cpp
index f2b3a246..3e14ce66 100644
--- a/src/mir/mir_builder.cpp
+++ b/src/mir/mir_builder.cpp
@@ -2193,6 +2193,7 @@ void MirBuilder::moved_lvalue(const Span& sp, const ::MIR::LValue& lv)
{
if( !lvalue_is_copy(sp, lv) ) {
auto& vs = get_val_state_mut(sp, lv);
+ // TODO: If the current state is Optional, set the drop flag to 0
vs = VarState::make_Invalid(InvalidType::Moved);
}
}
diff --git a/src/mir/optimise.cpp b/src/mir/optimise.cpp
index 06a8e3dd..80bca08d 100644
--- a/src/mir/optimise.cpp
+++ b/src/mir/optimise.cpp
@@ -27,7 +27,7 @@
#define CHECK_AFTER_ALL 1
#define DUMP_AFTER_PASS 1
-#define DUMP_AFTER_DONE 0
+#define DUMP_AFTER_DONE 1
#define CHECK_AFTER_DONE 2 // 1 = Check before GC, 2 = check before and after GC
// ----
@@ -106,12 +106,14 @@ bool MIR_OptimiseInline(const StaticTraitResolve& resolve, const ::HIR::ItemPath
// - Constant propagation (inlining may have lead to some more constant information
MIR_Optimise_ConstPropagte(state, fcn);
// - Unify non-overlapping locals
+#if 0
if(MIR_Optimise_UnifyTemporaries(state, fcn))
{
#if CHECK_AFTER_ALL
MIR_Validate(resolve, path, fcn, args, ret_type);
#endif
}
+#endif
// - Remove no-op statements
MIR_Optimise_NoopRemoval(state, fcn);
@@ -238,6 +240,7 @@ void MIR_Optimise(const StaticTraitResolve& resolve, const ::HIR::ItemPath& path
// Run UnifyTemporaries last, then unify blocks, then run some
// optimisations that might be affected
+#if 0
if(MIR_Optimise_UnifyTemporaries(state, fcn))
{
#if CHECK_AFTER_ALL
@@ -247,6 +250,7 @@ void MIR_Optimise(const StaticTraitResolve& resolve, const ::HIR::ItemPath& path
//MIR_Optimise_ConstPropagte(state, fcn);
MIR_Optimise_NoopRemoval(state, fcn);
}
+#endif
#if DUMP_AFTER_DONE
@@ -536,10 +540,10 @@ namespace {
if( it->second->monomorphised.code ) {
return &*it->second->monomorphised.code;
}
- else if( hir_fcn.m_code.m_mir ) {
+ else if( const auto* mir = hir_fcn.m_code.get_mir_opt() ) {
MIR_ASSERT(state, hir_fcn.m_params.m_types.empty(), "Enumeration failure - Function had params, but wasn't monomorphised - " << path);
// TODO: Check for trait methods too?
- return &*hir_fcn.m_code.m_mir;
+ return mir;
}
else {
MIR_ASSERT(state, !hir_fcn.m_code, "LowerMIR failure - No MIR but HIR is present?! - " << path);
@@ -551,10 +555,10 @@ namespace {
TU_MATCHA( (path.m_data), (pe),
(Generic,
const auto& fcn = state.m_crate.get_function_by_path(state.sp, pe.m_path);
- if( fcn.m_code.m_mir )
+ if( const auto* mir = fcn.m_code.get_mir_opt() )
{
params.fcn_params = &pe.m_params;
- return &*fcn.m_code.m_mir;
+ return mir;
}
),
(UfcsKnown,
@@ -626,14 +630,14 @@ namespace {
{
params.impl_params.m_types = mv$(best_impl_params);
DEBUG("Found impl" << impl.m_params.fmt_args() << " " << impl.m_type);
- if( fit->second.data.m_code.m_mir )
- return &*fit->second.data.m_code.m_mir;
+ if( const auto* mir = fit->second.data.m_code.get_mir_opt() )
+ return mir;
}
else
{
params.impl_params = pe.trait.m_params.clone();
- if( ve.m_code.m_mir )
- return &*ve.m_code.m_mir;
+ if( const auto* mir = ve.m_code.get_mir_opt() )
+ return mir;
}
return nullptr;
),
@@ -653,12 +657,12 @@ namespace {
MIR_ASSERT(state, best_impl, "Couldn't find an impl for " << path);
auto fit = best_impl->m_methods.find(pe.item);
MIR_ASSERT(state, fit != best_impl->m_methods.end(), "Couldn't find method in best inherent impl");
- if( fit->second.data.m_code.m_mir )
+ if( const auto* mir = fit->second.data.m_code.get_mir_opt() )
{
params.self_ty = &*pe.type;
params.fcn_params = &pe.params;
params.impl_params = pe.impl_params.clone();
- return &*fit->second.data.m_code.m_mir;
+ return mir;
}
return nullptr;
),
@@ -3243,36 +3247,97 @@ bool MIR_Optimise_DeadDropFlags(::MIR::TypeResolve& state, ::MIR::Function& fcn)
{
bool removed_statement = false;
TRACE_FUNCTION_FR("", removed_statement);
- ::std::vector<bool> read_drop_flags( fcn.drop_flags.size() );
- visit_blocks(state, fcn, [&read_drop_flags](auto , const ::MIR::BasicBlock& block) {
- for(const auto& stmt : block.statements)
- {
- if( const auto* e = stmt.opt_SetDropFlag() )
+ ::std::vector<bool> used_drop_flags( fcn.drop_flags.size() );
+ {
+ ::std::vector<bool> read_drop_flags( fcn.drop_flags.size() );
+ visit_blocks(state, fcn, [&read_drop_flags,&used_drop_flags](auto , const ::MIR::BasicBlock& block) {
+ for(const auto& stmt : block.statements)
{
- if(e->other != ~0u) {
- read_drop_flags[e->other] = true;
+ if( const auto* e = stmt.opt_SetDropFlag() )
+ {
+ if(e->other != ~0u) {
+ read_drop_flags[e->other] = true;
+ used_drop_flags[e->other] = true;
+ }
+ used_drop_flags[e->idx] = true;
+ }
+ else if( const auto* e = stmt.opt_Drop() )
+ {
+ if(e->flag_idx != ~0u) {
+ read_drop_flags[e->flag_idx] = true;
+ used_drop_flags[e->flag_idx] = true;
+ }
}
}
- else if( const auto* e = stmt.opt_Drop() )
+ });
+ DEBUG("Un-read drop flags:" << FMT_CB(ss,
+ for(size_t i = 0; i < read_drop_flags.size(); i ++)
+ if( ! read_drop_flags[i] && used_drop_flags[i] )
+ ss << " " << i;
+ ));
+ visit_blocks_mut(state, fcn, [&read_drop_flags,&removed_statement](auto _id, auto& block) {
+ for(auto it = block.statements.begin(); it != block.statements.end(); )
{
- if(e->flag_idx != ~0u) {
- read_drop_flags[e->flag_idx] = true;
+ if(it->is_SetDropFlag() && ! read_drop_flags[it->as_SetDropFlag().idx] ) {
+ removed_statement = true;
+ it = block.statements.erase(it);
+ }
+ else {
+ ++ it;
}
}
- }
- });
- visit_blocks_mut(state, fcn, [&read_drop_flags,&removed_statement](auto _id, auto& block) {
- for(auto it = block.statements.begin(); it != block.statements.end(); )
- {
- if(it->is_SetDropFlag() && ! read_drop_flags[it->as_SetDropFlag().idx] ) {
- removed_statement = true;
- it = block.statements.erase(it);
+ });
+ }
+
+ // Find any drop flags that are never assigned with a value other than their default, then remove those dead assignments.
+ {
+ ::std::vector<bool> edited_drop_flags( fcn.drop_flags.size() );
+ visit_blocks(state, fcn, [&edited_drop_flags,&fcn](auto , const ::MIR::BasicBlock& block) {
+ for(const auto& stmt : block.statements)
+ {
+ if( const auto* e = stmt.opt_SetDropFlag() )
+ {
+ if(e->other != ~0u) {
+ // If the drop flag is set based on another, assume it's changed
+ edited_drop_flags[e->idx] = true;
+ }
+ else if( e->new_val != fcn.drop_flags[e->idx] ) {
+ // If the new value is not the default, it's changed
+ edited_drop_flags[e->idx] = true;
+ }
+ else {
+ // Set to the default, doesn't change the 'edited' state
+ }
+ }
}
- else {
- ++ it;
+ });
+ DEBUG("Un-edited drop flags:" << FMT_CB(ss,
+ for(size_t i = 0; i < edited_drop_flags.size(); i ++)
+ if( ! edited_drop_flags[i] && used_drop_flags[i] )
+ ss << " " << i;
+ ));
+ visit_blocks_mut(state, fcn, [&edited_drop_flags,&removed_statement,&fcn](auto _id, auto& block) {
+ for(auto it = block.statements.begin(); it != block.statements.end(); )
+ {
+ // If this is a SetDropFlag and the target flag isn't edited, remove
+ if(const auto* e = it->opt_SetDropFlag())
+ {
+ if( ! edited_drop_flags[e->idx] ) {
+ assert( e->new_val == fcn.drop_flags[e->idx] );
+ removed_statement = true;
+ it = block.statements.erase(it);
+ }
+ else {
+ ++ it;
+ }
+ }
+ else {
+ ++ it;
+ }
}
- }
- });
+ });
+ }
+
return removed_statement;
}
@@ -3414,7 +3479,11 @@ bool MIR_Optimise_GarbageCollect(::MIR::TypeResolve& state, ::MIR::Function& fcn
visited[bb] = true;
auto assigned_lval = [&](const ::MIR::LValue& lv) {
- if(const auto* le = lv.opt_Local() )
+ const auto* lvp = &lv;
+ // TODO: Consume through indexing/field accesses
+ while(lvp->is_Field())
+ lvp = &*lvp->as_Field().val;
+ if(const auto* le = lvp->opt_Local() )
used_locals[*le] = true;
};
@@ -3732,11 +3801,12 @@ void MIR_OptimiseCrate(::HIR::Crate& crate, bool do_minimal_optimisation)
if( ! dynamic_cast<::HIR::ExprNode_Block*>(expr.get()) ) {
return ;
}
+ auto& mir = expr.get_mir_or_error_mut(Span());
if( do_minimal_optimisation ) {
- MIR_OptimiseMin(res, p, *expr.m_mir, args, ty);
+ MIR_OptimiseMin(res, p, mir, args, ty);
}
else {
- MIR_Optimise(res, p, *expr.m_mir, args, ty);
+ MIR_Optimise(res, p, mir, args, ty);
}
}
};
@@ -3769,9 +3839,10 @@ void MIR_OptimiseCrate_Inlining(const ::HIR::Crate& crate, TransList& list)
{
did_inline_on_pass |= MIR_OptimiseInline(resolve, ip, *mono_fcn.code, mono_fcn.arg_tys, mono_fcn.ret_ty, list);
}
- else if( hir_fcn.m_code.m_mir)
+ else if( hir_fcn.m_code )
{
- did_inline_on_pass |= MIR_OptimiseInline(resolve, ip, *hir_fcn.m_code.m_mir, hir_fcn.m_args, hir_fcn.m_return, list);
+ auto& mir = hir_fcn.m_code.get_mir_or_error_mut(Span());
+ did_inline_on_pass |= MIR_OptimiseInline(resolve, ip, mir, hir_fcn.m_args, hir_fcn.m_return, list);
}
else
{