summaryrefslogtreecommitdiff
path: root/src/mir
diff options
context:
space:
mode:
authorJohn Hodge (bugs) <tpg@mutabah.net>2017-06-04 21:23:24 +0800
committerJohn Hodge (bugs) <tpg@mutabah.net>2017-06-04 21:23:24 +0800
commit83dbb728f62306d2e43b2688dd0f2d320fd5b038 (patch)
treea064267bdf8d0455ed725140abfcbed3e04b2d4a /src/mir
parent0b9fd0014c8f32ecf299dae2ad1811dfb484af46 (diff)
parentf19c75571c48588fb3816e8eb5b96f03474fbdf5 (diff)
downloadmrust-83dbb728f62306d2e43b2688dd0f2d320fd5b038.tar.gz
Merge branch 'master' of https://github.com/thepowersgang/mrustc
Diffstat (limited to 'src/mir')
-rw-r--r--src/mir/from_hir.cpp29
-rw-r--r--src/mir/helpers.cpp70
-rw-r--r--src/mir/mir_builder.cpp92
-rw-r--r--src/mir/optimise.cpp187
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 ++)