diff options
author | John Hodge (bugs) <tpg@mutabah.net> | 2017-06-04 21:23:24 +0800 |
---|---|---|
committer | John Hodge (bugs) <tpg@mutabah.net> | 2017-06-04 21:23:24 +0800 |
commit | 83dbb728f62306d2e43b2688dd0f2d320fd5b038 (patch) | |
tree | a064267bdf8d0455ed725140abfcbed3e04b2d4a /src/mir | |
parent | 0b9fd0014c8f32ecf299dae2ad1811dfb484af46 (diff) | |
parent | f19c75571c48588fb3816e8eb5b96f03474fbdf5 (diff) | |
download | mrust-83dbb728f62306d2e43b2688dd0f2d320fd5b038.tar.gz |
Merge branch 'master' of https://github.com/thepowersgang/mrustc
Diffstat (limited to 'src/mir')
-rw-r--r-- | src/mir/from_hir.cpp | 29 | ||||
-rw-r--r-- | src/mir/helpers.cpp | 70 | ||||
-rw-r--r-- | src/mir/mir_builder.cpp | 92 | ||||
-rw-r--r-- | src/mir/optimise.cpp | 187 |
4 files changed, 237 insertions, 141 deletions
diff --git a/src/mir/from_hir.cpp b/src/mir/from_hir.cpp index ceda0a87..d9796aed 100644 --- a/src/mir/from_hir.cpp +++ b/src/mir/from_hir.cpp @@ -1723,6 +1723,16 @@ namespace { })); } + // rustc has drop_in_place as a lang item, mrustc uses an intrinsic + if( gpath.m_path == m_builder.crate().get_lang_item_path_opt("drop_in_place") ) + { + m_builder.end_block(::MIR::Terminator::make_Call({ + next_block, panic_block, + res.clone(), ::MIR::CallTarget::make_Intrinsic({ "drop_in_place", gpath.m_params.clone() }), + mv$(values) + })); + } + if( fcn.m_return.m_data.is_Diverge() ) { unconditional_diverge = true; @@ -1814,19 +1824,22 @@ namespace { ::std::stringstream(node.m_field) >> idx; m_builder.set_result( node.span(), ::MIR::LValue::make_Field({ box$(val), idx }) ); } - else if( val_ty.m_data.as_Path().binding.is_Struct() ) { - const auto& str = *node.m_value->m_res_type.m_data.as_Path().binding.as_Struct(); + else if( const auto* bep = val_ty.m_data.as_Path().binding.opt_Struct() ) { + const auto& str = **bep; const auto& fields = str.m_data.as_Named(); idx = ::std::find_if( fields.begin(), fields.end(), [&](const auto& x){ return x.first == node.m_field; } ) - fields.begin(); m_builder.set_result( node.span(), ::MIR::LValue::make_Field({ box$(val), idx }) ); } - else { - const auto& unm = *node.m_value->m_res_type.m_data.as_Path().binding.as_Union(); + else if( const auto* bep = val_ty.m_data.as_Path().binding.opt_Union() ) { + const auto& unm = **bep; const auto& fields = unm.m_variants; idx = ::std::find_if( fields.begin(), fields.end(), [&](const auto& x){ return x.first == node.m_field; } ) - fields.begin(); m_builder.set_result( node.span(), ::MIR::LValue::make_Downcast({ box$(val), idx }) ); } + else { + BUG(node.span(), "Field access on non-union/struct - " << val_ty); + } } void visit(::HIR::ExprNode_Literal& node) override { @@ -2075,6 +2088,14 @@ namespace { BUG(node.span(), "_StructLiteral Union"); ), (Struct, + if(e->m_data.is_Unit()) { + m_builder.set_result( node.span(), ::MIR::RValue::make_Struct({ + node.m_path.clone(), + variant_index, + {} + }) ); + return ; + } fields_ptr = &e->m_data.as_Named(); ) ) diff --git a/src/mir/helpers.cpp b/src/mir/helpers.cpp index 9242ccb7..c38e73e9 100644 --- a/src/mir/helpers.cpp +++ b/src/mir/helpers.cpp @@ -106,31 +106,53 @@ const ::HIR::TypeRef& ::MIR::TypeResolve::get_lvalue_type(::HIR::TypeRef& tmp, c return te[e.field_index]; ), (Path, - MIR_ASSERT(*this, te.binding.is_Struct(), "Field on non-Struct - " << ty); - const auto& str = *te.binding.as_Struct(); - auto monomorph = [&](const auto& ty)->const auto& { - if( monomorphise_type_needed(ty) ) { - tmp = monomorphise_type(sp, str.m_params, te.path.m_data.as_Generic().m_params, ty); - m_resolve.expand_associated_types(sp, tmp); - return tmp; - } - else { - return ty; - } - }; - TU_MATCHA( (str.m_data), (se), - (Unit, - MIR_BUG(*this, "Field on unit-like struct - " << ty); - ), - (Tuple, - MIR_ASSERT(*this, e.field_index < se.size(), "Field index out of range in tuple-struct " << te.path); - return monomorph(se[e.field_index].ent); - ), - (Named, - MIR_ASSERT(*this, e.field_index < se.size(), "Field index out of range in struct " << te.path); - return monomorph(se[e.field_index].second.ent); + if( const auto* tep = te.binding.opt_Struct() ) + { + const auto& str = **tep; + auto monomorph = [&](const auto& ty)->const auto& { + if( monomorphise_type_needed(ty) ) { + tmp = monomorphise_type(sp, str.m_params, te.path.m_data.as_Generic().m_params, ty); + m_resolve.expand_associated_types(sp, tmp); + return tmp; + } + else { + return ty; + } + }; + TU_MATCHA( (str.m_data), (se), + (Unit, + MIR_BUG(*this, "Field on unit-like struct - " << ty); + ), + (Tuple, + MIR_ASSERT(*this, e.field_index < se.size(), "Field index out of range in tuple-struct " << te.path); + return monomorph(se[e.field_index].ent); + ), + (Named, + MIR_ASSERT(*this, e.field_index < se.size(), "Field index out of range in struct " << te.path); + return monomorph(se[e.field_index].second.ent); + ) ) - ) + } + else if( const auto* tep = te.binding.opt_Union() ) + { + const auto& unm = **tep; + auto maybe_monomorph = [&](const ::HIR::TypeRef& t)->const ::HIR::TypeRef& { + if( monomorphise_type_needed(t) ) { + tmp = monomorphise_type(sp, unm.m_params, te.path.m_data.as_Generic().m_params, t); + m_resolve.expand_associated_types(sp, tmp); + return tmp; + } + else { + return t; + } + }; + MIR_ASSERT(*this, e.field_index < unm.m_variants.size(), "Field index out of range for union"); + return maybe_monomorph(unm.m_variants.at(e.field_index).second.ent); + } + else + { + MIR_BUG(*this, "Field access on invalid type - " << ty); + } ) ) ), diff --git a/src/mir/mir_builder.cpp b/src/mir/mir_builder.cpp index 8cb8c088..478146e8 100644 --- a/src/mir/mir_builder.cpp +++ b/src/mir/mir_builder.cpp @@ -814,6 +814,7 @@ void MirBuilder::terminate_scope(const Span& sp, ScopeHandle scope, bool emit_cl drop_scope_values(scope_def); // Emit ScopeEnd for all controlled values + #if 0 ::MIR::Statement::Data_ScopeEnd se; if(const auto* e = scope_def.data.opt_Variables() ) { se.vars = e->vars; @@ -827,6 +828,7 @@ void MirBuilder::terminate_scope(const Span& sp, ScopeHandle scope, bool emit_cl if( !se.vars.empty() || !se.tmps.empty() ) { this->push_stmt(sp, ::MIR::Statement( mv$(se) )); } + #endif } // 3. Pop scope (last because `drop_scope_values` uses the stack) @@ -1638,39 +1640,59 @@ void MirBuilder::with_val_type(const Span& sp, const ::MIR::LValue& val, ::std:: cb( *te.inner ); ), (Path, - ASSERT_BUG(sp, te.binding.is_Struct(), "Field on non-Struct - " << ty); - const auto& str = *te.binding.as_Struct(); - TU_MATCHA( (str.m_data), (se), - (Unit, - BUG(sp, "Field on unit-like struct - " << ty); - ), - (Tuple, - ASSERT_BUG(sp, e.field_index < se.size(), - "Field index out of range in tuple-struct " << ty << " - " << e.field_index << " > " << se.size()); - const auto& fld = se[e.field_index]; - if( monomorphise_type_needed(fld.ent) ) { - auto sty = monomorphise_type(sp, str.m_params, te.path.m_data.as_Generic().m_params, fld.ent); - m_resolve.expand_associated_types(sp, sty); - cb(sty); - } - else { - cb(fld.ent); - } - ), - (Named, - ASSERT_BUG(sp, e.field_index < se.size(), - "Field index out of range in struct " << ty << " - " << e.field_index << " > " << se.size()); - const auto& fld = se[e.field_index].second; - if( monomorphise_type_needed(fld.ent) ) { - auto sty = monomorphise_type(sp, str.m_params, te.path.m_data.as_Generic().m_params, fld.ent); - m_resolve.expand_associated_types(sp, sty); - cb(sty); - } - else { - cb(fld.ent); - } + ::HIR::TypeRef tmp; + if( const auto* tep = te.binding.opt_Struct() ) + { + const auto& str = **tep; + auto maybe_monomorph = [&](const ::HIR::TypeRef& t)->const ::HIR::TypeRef& { + if( monomorphise_type_needed(t) ) { + tmp = monomorphise_type(sp, str.m_params, te.path.m_data.as_Generic().m_params, t); + m_resolve.expand_associated_types(sp, tmp); + return tmp; + } + else { + return t; + } + }; + TU_MATCHA( (str.m_data), (se), + (Unit, + BUG(sp, "Field on unit-like struct - " << ty); + ), + (Tuple, + ASSERT_BUG(sp, e.field_index < se.size(), + "Field index out of range in tuple-struct " << ty << " - " << e.field_index << " > " << se.size()); + const auto& fld = se[e.field_index]; + cb( maybe_monomorph(fld.ent) ); + ), + (Named, + ASSERT_BUG(sp, e.field_index < se.size(), + "Field index out of range in struct " << ty << " - " << e.field_index << " > " << se.size()); + const auto& fld = se[e.field_index].second; + cb( maybe_monomorph(fld.ent) ); + ) ) - ) + } + else if( const auto* tep = te.binding.opt_Union() ) + { + BUG(sp, "Field access on a union isn't valid, use Downcast instead - " << ty); + const auto& unm = **tep; + auto maybe_monomorph = [&](const ::HIR::TypeRef& t)->const ::HIR::TypeRef& { + if( monomorphise_type_needed(t) ) { + tmp = monomorphise_type(sp, unm.m_params, te.path.m_data.as_Generic().m_params, t); + m_resolve.expand_associated_types(sp, tmp); + return tmp; + } + else { + return t; + } + }; + ASSERT_BUG(sp, e.field_index < unm.m_variants.size(), "Field index out of range for union"); + cb( maybe_monomorph(unm.m_variants.at(e.field_index).second.ent) ); + } + else + { + BUG(sp, "Field acess on unexpected type - " << ty); + } ), (Tuple, ASSERT_BUG(sp, e.field_index < te.size(), "Field index out of range in tuple " << e.field_index << " >= " << te.size()); @@ -2196,8 +2218,10 @@ void MirBuilder::drop_value_from_state(const Span& sp, const VarState& vs, ::MIR ), (Partial, bool is_enum = false; + bool is_union = false; with_val_type(sp, lv, [&](const auto& ty){ is_enum = ty.m_data.is_Path() && ty.m_data.as_Path().binding.is_Enum(); + is_union = ty.m_data.is_Path() && ty.m_data.as_Path().binding.is_Union(); }); if(is_enum) { @@ -2207,6 +2231,10 @@ void MirBuilder::drop_value_from_state(const Span& sp, const VarState& vs, ::MIR // drop_value_from_state(sp, vse.inner_states[i], ::MIR::LValue::make_Downcast({ box$(lv.clone()), static_cast<unsigned int>(i) })); //} } + else if( is_union ) + { + // NOTE: Unions don't drop inner items. + } else { for(size_t i = 0; i < vse.inner_states.size(); i ++) diff --git a/src/mir/optimise.cpp b/src/mir/optimise.cpp index 3b5fa036..8e350c45 100644 --- a/src/mir/optimise.cpp +++ b/src/mir/optimise.cpp @@ -390,6 +390,58 @@ namespace { ) return nullptr; } + + + void visit_blocks_mut(::MIR::TypeResolve& state, ::MIR::Function& fcn, ::std::function<void(::MIR::BasicBlockId, ::MIR::BasicBlock&)> cb) + { + ::std::vector<bool> visited( fcn.blocks.size() ); + ::std::vector< ::MIR::BasicBlockId> to_visit; + to_visit.push_back( 0 ); + while( to_visit.size() > 0 ) + { + auto bb = to_visit.back(); to_visit.pop_back(); + if( visited[bb] ) continue; + visited[bb] = true; + auto& block = fcn.blocks[bb]; + + cb(bb, block); + + TU_MATCHA( (block.terminator), (e), + (Incomplete, + ), + (Return, + ), + (Diverge, + ), + (Goto, + if( !visited[e] ) + to_visit.push_back(e); + ), + (Panic, + ), + (If, + if( !visited[e.bb0] ) + to_visit.push_back(e.bb0); + if( !visited[e.bb1] ) + to_visit.push_back(e.bb1); + ), + (Switch, + for(auto& target : e.targets) + if( !visited[target] ) + to_visit.push_back(target); + ), + (Call, + if( !visited[e.ret_block] ) + to_visit.push_back(e.ret_block); + if( !visited[e.panic_block] ) + to_visit.push_back(e.panic_block); + ) + ) + } + } + void visit_blocks(::MIR::TypeResolve& state, const ::MIR::Function& fcn, ::std::function<void(::MIR::BasicBlockId, const ::MIR::BasicBlock&)> cb) { + visit_blocks_mut(state, const_cast<::MIR::Function&>(fcn), [cb](auto id, auto& blk){ cb(id, blk); }); + } } bool MIR_Optimise_BlockSimplify(::MIR::TypeResolve& state, ::MIR::Function& fcn); @@ -398,6 +450,7 @@ bool MIR_Optimise_PropagateSingleAssignments(::MIR::TypeResolve& state, ::MIR::F bool MIR_Optimise_UnifyTemporaries(::MIR::TypeResolve& state, ::MIR::Function& fcn); bool MIR_Optimise_UnifyBlocks(::MIR::TypeResolve& state, ::MIR::Function& fcn); bool MIR_Optimise_ConstPropagte(::MIR::TypeResolve& state, ::MIR::Function& fcn); +bool MIR_Optimise_DeadDropFlags(::MIR::TypeResolve& state, ::MIR::Function& fcn); bool MIR_Optimise_GarbageCollect_Partial(::MIR::TypeResolve& state, ::MIR::Function& fcn); bool MIR_Optimise_GarbageCollect(::MIR::TypeResolve& state, ::MIR::Function& fcn); @@ -445,6 +498,9 @@ void MIR_Optimise(const StaticTraitResolve& resolve, const ::HIR::ItemPath& path // >> Combine Duplicate Blocks change_happened |= MIR_Optimise_UnifyBlocks(state, fcn); + // >> Remove assignments of unsed drop flags + change_happened |= MIR_Optimise_DeadDropFlags(state, fcn); + if( change_happened ) { #if DUMP_AFTER_PASS @@ -2231,6 +2287,45 @@ bool MIR_Optimise_PropagateSingleAssignments(::MIR::TypeResolve& state, ::MIR::F return replacement_happend; } +// ---------------------------------------- +// Clear all drop flags that are never read +// ---------------------------------------- +bool MIR_Optimise_DeadDropFlags(::MIR::TypeResolve& state, ::MIR::Function& fcn) +{ + ::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() ) + { + if(e->other != ~0u) { + read_drop_flags[e->other] = true; + } + } + else if( const auto* e = stmt.opt_Drop() ) + { + if(e->flag_idx != ~0u) { + read_drop_flags[e->flag_idx] = true; + } + } + } + }); + bool removed_statement = false; + 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); + } + else { + ++ it; + } + } + }); + return removed_statement; +} + // -------------------------------------------------------------------- // Clear all unused blocks @@ -2238,47 +2333,10 @@ bool MIR_Optimise_PropagateSingleAssignments(::MIR::TypeResolve& state, ::MIR::F bool MIR_Optimise_GarbageCollect_Partial(::MIR::TypeResolve& state, ::MIR::Function& fcn) { ::std::vector<bool> visited( fcn.blocks.size() ); - ::std::vector< ::MIR::BasicBlockId> to_visit; - to_visit.push_back( 0 ); - while( to_visit.size() > 0 ) - { - auto bb = to_visit.back(); to_visit.pop_back(); - if( visited[bb] ) continue; - visited[bb] = true; - const auto& block = fcn.blocks[bb]; - - TU_MATCHA( (block.terminator), (e), - (Incomplete, - ), - (Return, - ), - (Diverge, - ), - (Goto, - if( !visited[e] ) - to_visit.push_back(e); - ), - (Panic, - ), - (If, - if( !visited[e.bb0] ) - to_visit.push_back(e.bb0); - if( !visited[e.bb1] ) - to_visit.push_back(e.bb1); - ), - (Switch, - for(auto& target : e.targets) - if( !visited[target] ) - to_visit.push_back(target); - ), - (Call, - if( !visited[e.ret_block] ) - to_visit.push_back(e.ret_block); - if( !visited[e.panic_block] ) - to_visit.push_back(e.panic_block); - ) - ) - } + visit_blocks(state, fcn, [&visited](auto bb, const auto& _blokc) { + assert( !visited[bb] ); + visited[bb] = true; + }); bool rv = false; for(unsigned int i = 0; i < visited.size(); i ++) { @@ -2301,13 +2359,9 @@ bool MIR_Optimise_GarbageCollect(::MIR::TypeResolve& state, ::MIR::Function& fcn ::std::vector<bool> used_vars( fcn.named_variables.size() ); ::std::vector<bool> used_dfs( fcn.drop_flags.size() ); ::std::vector<bool> visited( fcn.blocks.size() ); - ::std::vector< ::MIR::BasicBlockId> to_visit; - to_visit.push_back( 0 ); - while( to_visit.size() > 0 ) - { - auto bb = to_visit.back(); to_visit.pop_back(); + + visit_blocks(state, fcn, [&](auto bb, const auto& block) { visited[bb] = true; - const auto& block = fcn.blocks[bb]; auto assigned_lval = [&](const ::MIR::LValue& lv) { if(const auto* le = lv.opt_Temporary() ) @@ -2339,40 +2393,11 @@ bool MIR_Optimise_GarbageCollect(::MIR::TypeResolve& state, ::MIR::Function& fcn } } - TU_MATCHA( (block.terminator), (e), - (Incomplete, - ), - (Return, - ), - (Diverge, - ), - (Goto, - if( !visited[e] ) - to_visit.push_back(e); - ), - (Panic, - ), - (If, - if( !visited[e.bb0] ) - to_visit.push_back(e.bb0); - if( !visited[e.bb1] ) - to_visit.push_back(e.bb1); - ), - (Switch, - for(auto& target : e.targets) - if( !visited[target] ) - to_visit.push_back(target); - ), - (Call, - if( !visited[e.ret_block] ) - to_visit.push_back(e.ret_block); - if( !visited[e.panic_block] ) - to_visit.push_back(e.panic_block); - - assigned_lval(e.ret_val); - ) - ) - } + if( const auto* te = block.terminator.opt_Call() ) + { + assigned_lval(te->ret_val); + } + }); ::std::vector<unsigned int> block_rewrite_table; for(unsigned int i = 0, j = 0; i < fcn.blocks.size(); i ++) |