diff options
author | John Hodge <tpg@ucc.asn.au> | 2017-04-22 13:31:07 +0800 |
---|---|---|
committer | John Hodge <tpg@ucc.asn.au> | 2017-04-22 13:31:07 +0800 |
commit | 83b9e560df97f054dc2ea0660cda3fb55cd274d7 (patch) | |
tree | 057be3e50eee6278f00b260a581d08931aa6e929 | |
parent | 6f5792ac00800b1a28b8c9c81eb80046f37b2f03 (diff) | |
download | mrust-83b9e560df97f054dc2ea0660cda3fb55cd274d7.tar.gz |
MIR - Add ScopeEnd statement to indicate where a value will no longer be used
-rw-r--r-- | src/hir/deserialise.cpp | 5 | ||||
-rw-r--r-- | src/hir/serialise.cpp | 5 | ||||
-rw-r--r-- | src/mir/check.cpp | 4 | ||||
-rw-r--r-- | src/mir/check_full.cpp | 3 | ||||
-rw-r--r-- | src/mir/cleanup.cpp | 2 | ||||
-rw-r--r-- | src/mir/dump.cpp | 8 | ||||
-rw-r--r-- | src/mir/from_hir.hpp | 2 | ||||
-rw-r--r-- | src/mir/helpers.cpp | 2 | ||||
-rw-r--r-- | src/mir/mir.cpp | 8 | ||||
-rw-r--r-- | src/mir/mir.hpp | 5 | ||||
-rw-r--r-- | src/mir/mir_builder.cpp | 39 | ||||
-rw-r--r-- | src/mir/optimise.cpp | 65 | ||||
-rw-r--r-- | src/trans/codegen_c.cpp | 11 | ||||
-rw-r--r-- | src/trans/enumerate.cpp | 4 | ||||
-rw-r--r-- | src/trans/monomorphise.cpp | 3 |
15 files changed, 139 insertions, 27 deletions
diff --git a/src/hir/deserialise.cpp b/src/hir/deserialise.cpp index 4a9b5720..19306a63 100644 --- a/src/hir/deserialise.cpp +++ b/src/hir/deserialise.cpp @@ -1008,6 +1008,11 @@ namespace { m_in.read_bool(), static_cast<unsigned int>(m_in.read_count()) }); + case 4: + return ::MIR::Statement::make_ScopeEnd({ + deserialise_vec<unsigned int>(), + deserialise_vec<unsigned int>() + }); default: ::std::cerr << "Bad tag for a MIR Statement" << ::std::endl; throw ""; diff --git a/src/hir/serialise.cpp b/src/hir/serialise.cpp index 81319c2e..e5264ae2 100644 --- a/src/hir/serialise.cpp +++ b/src/hir/serialise.cpp @@ -495,6 +495,11 @@ namespace { m_out.write_count(e.idx); m_out.write_bool(e.new_val); m_out.write_count(e.other); + ), + (ScopeEnd, + m_out.write_tag(4); + serialise_vec(e.vars); + serialise_vec(e.tmps); ) ) } diff --git a/src/mir/check.cpp b/src/mir/check.cpp index 7c8fbd13..4dbdb45f 100644 --- a/src/mir/check.cpp +++ b/src/mir/check.cpp @@ -457,6 +457,8 @@ void MIR_Validate_ValState(::MIR::TypeResolve& state, const ::MIR::Function& fcn // Mark destination as valid val_state.mark_validity( state, stmt.as_Assign().dst, true ); break; + case ::MIR::Statement::TAG_ScopeEnd: + break; } } @@ -852,6 +854,8 @@ void MIR_Validate(const StaticTraitResolve& resolve, const ::HIR::ItemPath& path case ::MIR::Statement::TAG_Drop: // TODO: Anything need checking here? break; + case ::MIR::Statement::TAG_ScopeEnd: + break; } } diff --git a/src/mir/check_full.cpp b/src/mir/check_full.cpp index 96da8a74..992db468 100644 --- a/src/mir/check_full.cpp +++ b/src/mir/check_full.cpp @@ -712,6 +712,9 @@ void MIR_Validate_FullValState(::MIR::TypeResolve& mir_res, const ::MIR::Functio state.move_lvalue(mir_res, se.slot); } } + ), + (ScopeEnd, + // TODO: Mark all mentioned variables as invalid ) ) } diff --git a/src/mir/cleanup.cpp b/src/mir/cleanup.cpp index 6516dd60..17dca948 100644 --- a/src/mir/cleanup.cpp +++ b/src/mir/cleanup.cpp @@ -932,6 +932,8 @@ void MIR_Cleanup(const StaticTraitResolve& resolve, const ::HIR::ItemPath& path, ), (SetDropFlag, ), + (ScopeEnd, + ), (Asm, for(auto& v : se.inputs) MIR_Cleanup_LValue(state, mutator, v.second); diff --git a/src/mir/dump.cpp b/src/mir/dump.cpp index eb74dc9e..0187e8b2 100644 --- a/src/mir/dump.cpp +++ b/src/mir/dump.cpp @@ -99,6 +99,14 @@ namespace { m_os << " IF df$" << e.flag_idx; } m_os << ");\n"; + ), + (ScopeEnd, + m_os << "// Scope End: "; + for(auto idx : e.vars) + m_os << "var$" << idx << ","; + for(auto idx : e.tmps) + m_os << "tmp$" << idx << ","; + m_os << "\n"; ) ) } diff --git a/src/mir/from_hir.hpp b/src/mir/from_hir.hpp index 5b0b8904..e124770c 100644 --- a/src/mir/from_hir.hpp +++ b/src/mir/from_hir.hpp @@ -199,6 +199,8 @@ public: void push_stmt_set_dropflag_val(const Span& sp, unsigned int index, bool value); void push_stmt_set_dropflag_other(const Span& sp, unsigned int index, unsigned int other); + void push_stmt(const Span& sp, ::MIR::Statement stmt); + // - Block management bool block_active() const { return m_block_active; diff --git a/src/mir/helpers.cpp b/src/mir/helpers.cpp index e0e646fa..21e16116 100644 --- a/src/mir/helpers.cpp +++ b/src/mir/helpers.cpp @@ -402,6 +402,8 @@ namespace { (Drop, // Well, it mutates... rv |= visit_mir_lvalue(e.slot, ValUsage::Write, cb); + ), + (ScopeEnd, ) ) return rv; diff --git a/src/mir/mir.cpp b/src/mir/mir.cpp index 3c16af37..9edc925b 100644 --- a/src/mir/mir.cpp +++ b/src/mir/mir.cpp @@ -483,6 +483,14 @@ namespace MIR { if(e.flag_idx != ~0u) os << "IF df$" << e.flag_idx; os << ")"; + ), + (ScopeEnd, + os << "ScopeEnd("; + for(auto idx : e.vars) + os << "var$" << idx << ","; + for(auto idx : e.tmps) + os << "tmp$" << idx << ","; + os << ")"; ) ) return os; diff --git a/src/mir/mir.hpp b/src/mir/mir.hpp index 93a430ff..dc33d673 100644 --- a/src/mir/mir.hpp +++ b/src/mir/mir.hpp @@ -272,6 +272,10 @@ TAGGED_UNION(Statement, Assign, eDropKind kind; // NOTE: For the `box` primitive LValue slot; unsigned int flag_idx; // Valid if != ~0u + }), + (ScopeEnd, struct { + ::std::vector<unsigned> vars; + ::std::vector<unsigned> tmps; }) ); extern ::std::ostream& operator<<(::std::ostream& os, const Statement& x); @@ -286,6 +290,7 @@ struct BasicBlock class Function { public: + // TODO: Unify Variables, Temporaries, and Arguments ::std::vector< ::HIR::TypeRef> named_variables; ::std::vector< ::HIR::TypeRef> temporaries; ::std::vector<bool> drop_flags; diff --git a/src/mir/mir_builder.cpp b/src/mir/mir_builder.cpp index 686df677..c023b797 100644 --- a/src/mir/mir_builder.cpp +++ b/src/mir/mir_builder.cpp @@ -304,7 +304,7 @@ void MirBuilder::push_stmt_assign(const Span& sp, ::MIR::LValue dst, ::MIR::RVal // Drop target if populated mark_value_assigned(sp, dst); - m_output.blocks.at(m_current_block).statements.push_back( ::MIR::Statement::make_Assign({ mv$(dst), mv$(val) }) ); + this->push_stmt( sp, ::MIR::Statement::make_Assign({ mv$(dst), mv$(val) }) ); } void MirBuilder::push_stmt_drop(const Span& sp, ::MIR::LValue val, unsigned int flag/*=~0u*/) { @@ -316,9 +316,7 @@ void MirBuilder::push_stmt_drop(const Span& sp, ::MIR::LValue val, unsigned int return ; } - auto stmt = ::MIR::Statement::make_Drop({ ::MIR::eDropKind::DEEP, mv$(val), flag }); - DEBUG(stmt); - m_output.blocks.at(m_current_block).statements.push_back( mv$(stmt) ); + this->push_stmt(sp, ::MIR::Statement::make_Drop({ ::MIR::eDropKind::DEEP, mv$(val), flag })); if( flag != ~0u ) { @@ -333,9 +331,7 @@ void MirBuilder::push_stmt_drop_shallow(const Span& sp, ::MIR::LValue val, unsig // TODO: Ensure that the type is a Box? - auto stmt = ::MIR::Statement::make_Drop({ ::MIR::eDropKind::SHALLOW, mv$(val), flag }); - DEBUG(stmt); - m_output.blocks.at(m_current_block).statements.push_back( mv$(stmt) ); + this->push_stmt(sp, ::MIR::Statement::make_Drop({ ::MIR::eDropKind::SHALLOW, mv$(val), flag })); if( flag != ~0u ) { @@ -352,21 +348,19 @@ void MirBuilder::push_stmt_asm(const Span& sp, ::MIR::Statement::Data_Asm data) mark_value_assigned(sp, v.second); // 2. Push - auto stmt = ::MIR::Statement::make_Asm( mv$(data) ); - DEBUG(stmt); - m_output.blocks.at(m_current_block).statements.push_back( mv$(stmt) ); + this->push_stmt(sp, ::MIR::Statement::make_Asm( mv$(data) )); } void MirBuilder::push_stmt_set_dropflag_val(const Span& sp, unsigned int idx, bool value) { - ASSERT_BUG(sp, m_block_active, "Pushing statement with no active block"); - auto stmt = ::MIR::Statement::make_SetDropFlag({ idx, value }); - DEBUG(stmt); - m_output.blocks.at(m_current_block).statements.push_back( mv$(stmt) ); + this->push_stmt(sp, ::MIR::Statement::make_SetDropFlag({ idx, value })); } void MirBuilder::push_stmt_set_dropflag_other(const Span& sp, unsigned int idx, unsigned int other) { + this->push_stmt(sp, ::MIR::Statement::make_SetDropFlag({ idx, false, other })); +} +void MirBuilder::push_stmt(const Span& sp, ::MIR::Statement stmt) +{ ASSERT_BUG(sp, m_block_active, "Pushing statement with no active block"); - auto stmt = ::MIR::Statement::make_SetDropFlag({ idx, false, other }); DEBUG(stmt); m_output.blocks.at(m_current_block).statements.push_back( mv$(stmt) ); } @@ -777,6 +771,21 @@ void MirBuilder::terminate_scope(const Span& sp, ScopeHandle scope, bool emit_cl { // 2. Emit drops for all non-moved variables (share with below) drop_scope_values(scope_def); + + // Emit ScopeEnd for all controlled values + ::MIR::Statement::Data_ScopeEnd se; + if(const auto* e = scope_def.data.opt_Variables() ) { + se.vars = e->vars; + } + else if(const auto* e = scope_def.data.opt_Temporaries()) { + se.tmps = e->temporaries; + } + else { + } + // Only push the ScopeEnd if there were variables to end + if( !se.vars.empty() || !se.tmps.empty() ) { + this->push_stmt(sp, ::MIR::Statement( mv$(se) )); + } } // 3. Pop scope (last because `drop_scope_values` uses the stack) diff --git a/src/mir/optimise.cpp b/src/mir/optimise.cpp index 390bd1d6..063e5fe3 100644 --- a/src/mir/optimise.cpp +++ b/src/mir/optimise.cpp @@ -185,6 +185,8 @@ namespace { (Drop, // Well, it mutates... rv |= visit_mir_lvalue_mut(e.slot, ValUsage::Write, cb); + ), + (ScopeEnd, ) ) return rv; @@ -686,22 +688,21 @@ bool MIR_Optimise_Inlining(::MIR::TypeResolve& state, ::MIR::Function& fcn) return rv; } - ::MIR::BasicBlock clone_bb(const ::MIR::BasicBlock& src) const + ::MIR::BasicBlock clone_bb(const ::MIR::BasicBlock& src, unsigned src_idx, unsigned new_idx) const { ::MIR::BasicBlock rv; rv.statements.reserve( src.statements.size() ); for(const auto& stmt : src.statements) { + DEBUG("BB" << src_idx << "->BB" << new_idx << "/" << rv.statements.size() << ": " << stmt); TU_MATCHA( (stmt), (se), (Assign, - DEBUG(se.dst << " = " << se.src); rv.statements.push_back( ::MIR::Statement::make_Assign({ this->clone_lval(se.dst), this->clone_rval(se.src) }) ); ), (Asm, - DEBUG("asm!"); rv.statements.push_back( ::MIR::Statement::make_Asm({ se.tpl, this->clone_name_lval_vec(se.outputs), @@ -711,7 +712,6 @@ bool MIR_Optimise_Inlining(::MIR::TypeResolve& state, ::MIR::Function& fcn) }) ); ), (SetDropFlag, - DEBUG("df" << se.idx << " = "); rv.statements.push_back( ::MIR::Statement::make_SetDropFlag({ this->df_base + se.idx, se.new_val, @@ -719,17 +719,27 @@ bool MIR_Optimise_Inlining(::MIR::TypeResolve& state, ::MIR::Function& fcn) }) ); ), (Drop, - DEBUG("drop " << se.slot); rv.statements.push_back( ::MIR::Statement::make_Drop({ se.kind, this->clone_lval(se.slot), se.flag_idx == ~0u ? ~0u : this->df_base + se.flag_idx }) ); + ), + (ScopeEnd, + ::MIR::Statement::Data_ScopeEnd new_se; + new_se.vars.reserve(se.vars.size()); + for(auto idx : se.vars) + new_se.vars.push_back(this->var_base + idx); + new_se.tmps.reserve(se.tmps.size()); + for(auto idx : se.tmps) + new_se.tmps.push_back(this->tmp_base + idx); + rv.statements.push_back(::MIR::Statement( mv$(new_se) )); ) ) } - DEBUG(src.terminator); + DEBUG("BB" << src_idx << "->BB" << new_idx << "/" << rv.statements.size() << ": " << src.terminator); rv.terminator = this->clone_term(src.terminator); + DEBUG("-> " << rv.terminator); return rv; } ::MIR::Terminator clone_term(const ::MIR::Terminator& src) const @@ -981,7 +991,7 @@ bool MIR_Optimise_Inlining(::MIR::TypeResolve& state, ::MIR::Function& fcn) new_blocks.reserve( called_mir->blocks.size() ); for(const auto& bb : called_mir->blocks) { - new_blocks.push_back( cloner.clone_bb(bb) ); + new_blocks.push_back( cloner.clone_bb(bb, (&bb - called_mir->blocks.data()), fcn.blocks.size() + new_blocks.size()) ); } // > Append new temporaries for(auto& val : cloner.const_assignments) @@ -1138,6 +1148,12 @@ bool MIR_Optimise_UnifyBlocks(::MIR::TypeResolve& state, ::MIR::Function& fcn) return false; if( ae.slot != be.slot ) return false; + ), + (ScopeEnd, + if( ae.vars != be.vars ) + return false; + if( ae.tmps == be.tmps ) + return false; ) ) } @@ -1230,7 +1246,7 @@ bool MIR_Optimise_UnifyBlocks(::MIR::TypeResolve& state, ::MIR::Function& fcn) if( ! replacements.empty() ) { //MIR_TODO(state, "Unify blocks - " << replacements); - DEBUG("Unify blocks - " << replacements); + DEBUG("Unify blocks (old: new) - " << replacements); auto patch_tgt = [&replacements](::MIR::BasicBlockId& tgt) { auto it = replacements.find(tgt); if( it != replacements.end() ) @@ -1326,8 +1342,8 @@ bool MIR_Optimise_ConstPropagte(::MIR::TypeResolve& state, ::MIR::Function& fcn) changed = true; } } - // NOTE: Quick special-case for bswap<u8> (a no-op) - else if( tef.name == "bswap" && tef.params.m_types.at(0) == ::HIR::CoreType::U8 ) + // NOTE: Quick special-case for bswap<u8/i8> (a no-op) + else if( tef.name == "bswap" && (tef.params.m_types.at(0) == ::HIR::CoreType::U8 || tef.params.m_types.at(0) == ::HIR::CoreType::I8 ) { DEBUG("bswap<u8> is a no-op"); if( auto* e = te.args.at(0).opt_LValue() ) @@ -2311,6 +2327,35 @@ bool MIR_Optimise_GarbageCollect(::MIR::TypeResolve& state, ::MIR::Function& fcn if( se->other != ~0u ) se->other = df_rewrite_table[se->other]; } + else if( auto* se = stmt_it->opt_ScopeEnd() ) + { + for(auto it = se->vars.begin(); it != se->vars.end(); ) + { + if( var_rewrite_table.at(*it) == ~0u ) { + it = se->vars.erase(it); + } + else { + *it = var_rewrite_table.at(*it); + ++ it; + } + } + for(auto it = se->tmps.begin(); it != se->tmps.end(); ) + { + if( temp_rewrite_table.at(*it) == ~0u ) { + it = se->tmps.erase(it); + } + else { + *it = temp_rewrite_table.at(*it); + ++ it; + } + } + + if( se->vars.empty() && se->tmps.empty() ) { + DEBUG("- Delete ScopeEnd (now empty)"); + stmt_it = it->statements.erase(stmt_it); + -- stmt_it; + } + } } state.set_cur_stmt_term(i); // Rewrite and advance diff --git a/src/trans/codegen_c.cpp b/src/trans/codegen_c.cpp index 983bdfd4..c3532073 100644 --- a/src/trans/codegen_c.cpp +++ b/src/trans/codegen_c.cpp @@ -1315,6 +1315,9 @@ namespace { switch( stmt.tag() ) { case ::MIR::Statement::TAGDEAD: throw ""; + case ::MIR::Statement::TAG_ScopeEnd: + m_of << "// " << stmt << "\n"; + break; case ::MIR::Statement::TAG_SetDropFlag: { const auto& e = stmt.as_SetDropFlag(); m_of << "\tdf" << e.idx << " = "; @@ -1330,7 +1333,7 @@ namespace { const auto& ty = mir_res.get_lvalue_type(tmp, e.slot); if( e.flag_idx != ~0u ) - m_of << "if( df" << e.flag_idx << " ) {\n"; + m_of << "\tif( df" << e.flag_idx << " ) {\n"; switch( e.kind ) { @@ -1353,7 +1356,7 @@ namespace { break; } if( e.flag_idx != ~0u ) - m_of << "}\n"; + m_of << "\t}\n"; break; } case ::MIR::Statement::TAG_Asm: { const auto& e = stmt.as_Asm(); @@ -2720,7 +2723,11 @@ namespace { if( ' ' <= v && v < 0x7F && v != '"' && v != '\\' ) m_of << v; else + { m_of << "\\" << ((unsigned int)v & 0xFF); + if( isdigit( *(&v+1) ) ) + m_of << "\"\""; + } } m_of << "\"" << ::std::dec; m_of << ";\n\t"; diff --git a/src/trans/enumerate.cpp b/src/trans/enumerate.cpp index 481b275b..02116d18 100644 --- a/src/trans/enumerate.cpp +++ b/src/trans/enumerate.cpp @@ -875,6 +875,8 @@ void Trans_Enumerate_Types(EnumState& state) for(const auto& v : se.inputs) H::visit_lvalue(tv,pp,fcn, v.second); ), + (ScopeEnd, + ), (Assign, H::visit_lvalue(tv,pp,fcn, se.dst); TU_MATCHA( (se.src), (re), @@ -1461,6 +1463,8 @@ void Trans_Enumerate_FillFrom_MIR(EnumState& state, const ::MIR::Function& code, ), (SetDropFlag, ), + (ScopeEnd, + ), (Drop, DEBUG("- DROP " << se.slot); Trans_Enumerate_FillFrom_MIR_LValue(state, se.slot, pp); diff --git a/src/trans/monomorphise.cpp b/src/trans/monomorphise.cpp index 1688a8f5..1a7d8e79 100644 --- a/src/trans/monomorphise.cpp +++ b/src/trans/monomorphise.cpp @@ -150,6 +150,9 @@ namespace { case ::MIR::Statement::TAG_SetDropFlag: statements.push_back( ::MIR::Statement( stmt.as_SetDropFlag() ) ); break; + case ::MIR::Statement::TAG_ScopeEnd: + statements.push_back( ::MIR::Statement( stmt.as_ScopeEnd() ) ); + break; case ::MIR::Statement::TAG_Drop: { const auto& e = stmt.as_Drop(); DEBUG("- DROP " << e.slot); |