diff options
author | John Hodge <tpg@ucc.asn.au> | 2017-05-07 15:55:51 +0800 |
---|---|---|
committer | John Hodge <tpg@ucc.asn.au> | 2017-05-07 15:55:51 +0800 |
commit | 592c816af31a534dde7274d2bd38661585a71ac7 (patch) | |
tree | 7eb175fb179d65ea7f413a87c871a81f3e8b6b72 | |
parent | ec1dc3542bd5122db57f4459f63a6040f5e3ab20 (diff) | |
download | mrust-592c816af31a534dde7274d2bd38661585a71ac7.tar.gz |
HIR - Replace m_yeilds_final_value with a node
-rw-r--r-- | src/hir/dump.cpp | 30 | ||||
-rw-r--r-- | src/hir/expr.cpp | 2 | ||||
-rw-r--r-- | src/hir/expr.hpp | 9 | ||||
-rw-r--r-- | src/hir/from_ast_expr.cpp | 8 | ||||
-rw-r--r-- | src/hir_conv/constant_evaluation.cpp | 4 | ||||
-rw-r--r-- | src/hir_expand/annotate_value_usage.cpp | 2 | ||||
-rw-r--r-- | src/hir_expand/reborrow.cpp | 4 | ||||
-rw-r--r-- | src/hir_typeck/expr_check.cpp | 5 | ||||
-rw-r--r-- | src/hir_typeck/expr_cs.cpp | 110 | ||||
-rw-r--r-- | src/mir/dump.cpp | 26 | ||||
-rw-r--r-- | src/mir/from_hir.cpp | 119 |
11 files changed, 172 insertions, 147 deletions
diff --git a/src/hir/dump.cpp b/src/hir/dump.cpp index 614e95eb..8bcffa4e 100644 --- a/src/hir/dump.cpp +++ b/src/hir/dump.cpp @@ -302,28 +302,28 @@ namespace { void visit(::HIR::ExprNode_Block& node) override { if( node.m_nodes.size() == 0 ) { - m_os << "{ }"; + m_os << "{"; + if( node.m_value_node ) + { + m_os << " "; + this->visit_node_ptr(node.m_value_node); + } + m_os << " }"; } - //else if( node.m_nodes.size() == 1) { - // m_os << "{ "; - // this->visit_node_ptr(node.m_nodes.front()); - // m_os << " }"; - //} else { m_os << "{\n"; inc_indent(); for(auto& sn : node.m_nodes) { + m_os << "\n"; m_os << indent(); this->visit_node_ptr(sn); - if( &sn != &node.m_nodes.back() ) { - m_os << ";\n"; - } - else if( !node.m_yields_final ) { - m_os << ";\n"; - } - else { - m_os << "\n"; - } + m_os << ";\n"; + } + if( node.m_value_node ) + { + m_os << indent(); + this->visit_node_ptr(node.m_value_node); + m_os << "\n"; } dec_indent(); m_os << indent() << "}"; diff --git a/src/hir/expr.cpp b/src/hir/expr.cpp index e19e7df6..53f85c42 100644 --- a/src/hir/expr.cpp +++ b/src/hir/expr.cpp @@ -23,6 +23,8 @@ DEF_VISIT(ExprNode_Block, node, for(auto& subnode : node.m_nodes) { visit_node_ptr(subnode); } + if( node.m_value_node ) + visit_node_ptr(node.m_value_node); ) DEF_VISIT(ExprNode_Asm, node, for(auto& v : node.m_outputs) diff --git a/src/hir/expr.hpp b/src/hir/expr.hpp index 81e89b28..3c37a930 100644 --- a/src/hir/expr.hpp +++ b/src/hir/expr.hpp @@ -68,21 +68,20 @@ struct ExprNode_Block: { bool m_is_unsafe; ::std::vector< ExprNodeP > m_nodes; - bool m_yields_final; + ExprNodeP m_value_node; // can be null ::HIR::SimplePath m_local_mod; t_trait_list m_traits; ExprNode_Block(Span sp): ExprNode(mv$(sp)), - m_is_unsafe(false), - m_yields_final(false) + m_is_unsafe(false) {} - ExprNode_Block(Span sp, bool is_unsafe, ::std::vector<ExprNodeP> nodes): + ExprNode_Block(Span sp, bool is_unsafe, ::std::vector<ExprNodeP> nodes, ExprNodeP value_node): ExprNode( mv$(sp) ), m_is_unsafe(is_unsafe), m_nodes( mv$(nodes) ), - m_yields_final(false) + m_value_node( mv$(value_node) ) {} NODE_METHODS(); diff --git a/src/hir/from_ast_expr.cpp b/src/hir/from_ast_expr.cpp index d1d24f28..cd2b27fa 100644 --- a/src/hir/from_ast_expr.cpp +++ b/src/hir/from_ast_expr.cpp @@ -33,7 +33,11 @@ struct LowerHIR_ExprNode_Visitor: ASSERT_BUG(v.get_pos(), n, "NULL node encountered in block"); rv->m_nodes.push_back( LowerHIR_ExprNode_Inner( *n ) ); } - rv->m_yields_final = v.m_yields_final_value; + if( v.m_yields_final_value && ! rv->m_nodes.empty() ) + { + rv->m_value_node = mv$(rv->m_nodes.back()); + rv->m_nodes.pop_back(); + } if( v.m_local_mod ) { @@ -328,7 +332,7 @@ struct LowerHIR_ExprNode_Visitor: m_rv.reset( new ::HIR::ExprNode_Loop( v.span(), v.m_label, - ::HIR::ExprNodeP(new ::HIR::ExprNode_Block( v.span(), false, mv$(code))) + ::HIR::ExprNodeP(new ::HIR::ExprNode_Block( v.span(), false, mv$(code), {} )) ) ); break; } case ::AST::ExprNode_Loop::WHILELET: { diff --git a/src/hir_conv/constant_evaluation.cpp b/src/hir_conv/constant_evaluation.cpp index a70840ed..6949e2d6 100644 --- a/src/hir_conv/constant_evaluation.cpp +++ b/src/hir_conv/constant_evaluation.cpp @@ -276,6 +276,10 @@ namespace { { e->visit(*this); } + if( node.m_value_node ) + node.m_value_node->visit(*this); + else + ; } void visit(::HIR::ExprNode_Asm& node) override { badnode(node); diff --git a/src/hir_expand/annotate_value_usage.cpp b/src/hir_expand/annotate_value_usage.cpp index f21c68ab..dbcd6b13 100644 --- a/src/hir_expand/annotate_value_usage.cpp +++ b/src/hir_expand/annotate_value_usage.cpp @@ -84,6 +84,8 @@ namespace { for( auto& subnode : node.m_nodes ) { this->visit_node_ptr(subnode); } + if( node.m_value_node ) + this->visit_node_ptr(node.m_value_node); } void visit(::HIR::ExprNode_Asm& node) override diff --git a/src/hir_expand/reborrow.cpp b/src/hir_expand/reborrow.cpp index 688dcf97..b6f6aeb4 100644 --- a/src/hir_expand/reborrow.cpp +++ b/src/hir_expand/reborrow.cpp @@ -73,8 +73,8 @@ namespace { // Recurse into blocks - Neater this way else if( auto p = dynamic_cast< ::HIR::ExprNode_Block*>(node_ptr.get()) ) { - auto& last_node = p->m_nodes.back(); - last_node = do_reborrow(mv$(last_node)); + ASSERT_BUG( node_ptr->span(), p->m_value_node, "reborrow into block that doesn't yield" ); + p->m_value_node = do_reborrow(mv$(p->m_value_node)); } else { diff --git a/src/hir_typeck/expr_check.cpp b/src/hir_typeck/expr_check.cpp index 4f7bb5f4..614d52f4 100644 --- a/src/hir_typeck/expr_check.cpp +++ b/src/hir_typeck/expr_check.cpp @@ -59,9 +59,10 @@ namespace { { n->visit(*this); } - if( node.m_nodes.size() > 0 && node.m_yields_final ) + if( node.m_value_node ) { - check_types_equal(node.span(), node.m_res_type, node.m_nodes.back()->m_res_type); + node.m_value_node->visit(*this); + check_types_equal(node.span(), node.m_res_type, node.m_value_node->m_res_type); } } void visit(::HIR::ExprNode_Asm& node) override diff --git a/src/hir_typeck/expr_cs.cpp b/src/hir_typeck/expr_cs.cpp index acf991dd..12819251 100644 --- a/src/hir_typeck/expr_cs.cpp +++ b/src/hir_typeck/expr_cs.cpp @@ -543,13 +543,12 @@ namespace { return ty.m_data.is_Diverge();// || (ty.m_data.is_Infer() && ty.m_data.as_Infer().ty_class == ::HIR::InferClass::Diverge); }; + bool diverges = false; + this->push_traits( node.m_traits ); if( node.m_nodes.size() > 0 ) { - bool diverges = false; - this->push_traits( node.m_traits ); - this->push_inner_coerce(false); - for( unsigned int i = 0; i < node.m_nodes.size()-1; i ++ ) + for( unsigned int i = 0; i < node.m_nodes.size(); i ++ ) { auto& snp = node.m_nodes[i]; this->context.add_ivars( snp->m_res_type ); @@ -561,62 +560,56 @@ namespace { } } this->pop_inner_coerce(); + } - if( node.m_yields_final ) - { - auto& snp = node.m_nodes.back(); - DEBUG("Block yields final value"); - this->context.add_ivars( snp->m_res_type ); - this->context.equate_types(snp->span(), node.m_res_type, snp->m_res_type); - snp->visit(*this); - } - else + if( node.m_value_node ) + { + auto& snp = node.m_value_node; + DEBUG("Block yields final value"); + this->context.add_ivars( snp->m_res_type ); + this->context.equate_types(snp->span(), node.m_res_type, snp->m_res_type); + snp->visit(*this); + } + else if( node.m_nodes.size() > 0 ) + { + // NOTE: If the final statement in the block diverges, mark this as diverging + const auto& snp = node.m_nodes.back(); + bool defer = false; + if( !diverges ) { - auto& snp = node.m_nodes.back(); - this->context.add_ivars( snp->m_res_type ); - // - Not yielded - so don't equate the return - snp->visit(*this); - - // NOTE: If the final statement in the block diverges, mark this as diverging - bool defer = false; - if( !diverges ) - { - TU_IFLET(::HIR::TypeRef::Data, this->context.get_type(snp->m_res_type).m_data, Infer, e, - switch(e.ty_class) - { - case ::HIR::InferClass::Integer: - case ::HIR::InferClass::Float: - diverges = false; - break; - default: - defer = true; - break; - } - ) - else if( is_diverge(snp->m_res_type) ) { - diverges = true; - } - else { + TU_IFLET(::HIR::TypeRef::Data, this->context.get_type(snp->m_res_type).m_data, Infer, e, + switch(e.ty_class) + { + case ::HIR::InferClass::Integer: + case ::HIR::InferClass::Float: diverges = false; + break; + default: + defer = true; + break; } - } - - // If a statement in this block diverges - if( defer ) { - DEBUG("Block final node returns _, derfer diverge check"); - this->context.add_revisit(node); - } - else if( diverges ) { - DEBUG("Block diverges, yield !"); - this->context.equate_types(node.span(), node.m_res_type, ::HIR::TypeRef::new_diverge()); + ) + else if( is_diverge(snp->m_res_type) ) { + diverges = true; } else { - DEBUG("Block doesn't diverge but doesn't yield a value, yield ()"); - this->context.equate_types(node.span(), node.m_res_type, ::HIR::TypeRef::new_unit()); + diverges = false; } } - this->pop_traits( node.m_traits ); + // If a statement in this block diverges + if( defer ) { + DEBUG("Block final node returns _, derfer diverge check"); + this->context.add_revisit(node); + } + else if( diverges ) { + DEBUG("Block diverges, yield !"); + this->context.equate_types(node.span(), node.m_res_type, ::HIR::TypeRef::new_diverge()); + } + else { + DEBUG("Block doesn't diverge but doesn't yield a value, yield ()"); + this->context.equate_types(node.span(), node.m_res_type, ::HIR::TypeRef::new_unit()); + } } else { @@ -624,6 +617,7 @@ namespace { DEBUG("Block is empty, yield ()"); this->context.equate_types(node.span(), node.m_res_type, ::HIR::TypeRef::new_unit()); } + this->pop_traits( node.m_traits ); } void visit(::HIR::ExprNode_Asm& node) override { @@ -1953,6 +1947,7 @@ namespace { return ty.m_data.is_Diverge();// || (ty.m_data.is_Infer() && ty.m_data.as_Infer().ty_class == ::HIR::InferClass::Diverge); }; + assert( !node.m_nodes.empty() ); const auto& last_ty = this->context.get_type( node.m_nodes.back()->m_res_type ); DEBUG("_Block: last_ty = " << last_ty); @@ -4133,11 +4128,12 @@ namespace { while( auto* p = dynamic_cast< ::HIR::ExprNode_Block*>(&**node_ptr_ptr) ) { DEBUG("- Moving into block"); - ASSERT_BUG( p->span(), context.m_ivars.types_equal(p->m_res_type, p->m_nodes.back()->m_res_type), - "Block and result mismatch - " << context.m_ivars.fmt_type(p->m_res_type) << " != " << context.m_ivars.fmt_type(p->m_nodes.back()->m_res_type)); + assert( p->m_value_node ); + ASSERT_BUG( p->span(), context.m_ivars.types_equal(p->m_res_type, p->m_value_node->m_res_type), + "Block and result mismatch - " << context.m_ivars.fmt_type(p->m_res_type) << " != " << context.m_ivars.fmt_type(p->m_value_node->m_res_type)); // - Override the the result type to the desired result p->m_res_type = ::HIR::TypeRef::new_borrow(borrow_type, des_borrow_inner.clone()); - node_ptr_ptr = &p->m_nodes.back(); + node_ptr_ptr = &p->m_value_node; } #endif auto& node_ptr = *node_ptr_ptr; @@ -4721,13 +4717,13 @@ namespace { while( auto* p = dynamic_cast< ::HIR::ExprNode_Block*>(&**npp) ) { DEBUG("- Propagate to the last node of a _Block"); - ASSERT_BUG( p->span(), context.m_ivars.types_equal(p->m_res_type, p->m_nodes.back()->m_res_type), - "Block and result mismatch - " << context.m_ivars.fmt_type(p->m_res_type) << " != " << context.m_ivars.fmt_type(p->m_nodes.back()->m_res_type)); + ASSERT_BUG( p->span(), context.m_ivars.types_equal(p->m_res_type, p->m_value_node->m_res_type), + "Block and result mismatch - " << context.m_ivars.fmt_type(p->m_res_type) << " != " << context.m_ivars.fmt_type(p->m_value_node->m_res_type)); ASSERT_BUG( p->span(), context.m_ivars.types_equal(p->m_res_type, ty_src), "Block and result mismatch - " << context.m_ivars.fmt_type(p->m_res_type) << " != " << context.m_ivars.fmt_type(ty_src) ); p->m_res_type = new_type.clone(); - npp = &p->m_nodes.back(); + npp = &p->m_value_node; } ::HIR::ExprNodeP& node_ptr = *npp; #endif diff --git a/src/mir/dump.cpp b/src/mir/dump.cpp index 0187e8b2..b4177295 100644 --- a/src/mir/dump.cpp +++ b/src/mir/dump.cpp @@ -515,6 +515,30 @@ namespace { m_os << indent() << " ;\n"; } } + void visit_constant(::HIR::ItemPath p, ::HIR::Constant& item) override + { + m_os << indent(); + m_os << "const "; + if( m_short_item_name ) + m_os << p.get_name(); + else + m_os << p; + m_os << ": " << item.m_type; + if( item.m_value ) + { + inc_indent(); + m_os << " = {\n"; + inc_indent(); + dump_mir(m_os, m_indent_level, *item.m_value.m_mir); + dec_indent(); + m_os << indent() << "} /* = " << item.m_value_res << "*/;\n"; + dec_indent(); + } + else + { + m_os << ";\n"; + } + } void visit_static(::HIR::ItemPath p, ::HIR::Static& item) override { m_os << indent(); @@ -527,7 +551,7 @@ namespace { if( item.m_value ) { inc_indent(); - m_os << "= {\n"; + m_os << " = {\n"; inc_indent(); dump_mir(m_os, m_indent_level, *item.m_value.m_mir); dec_indent(); diff --git a/src/mir/from_hir.cpp b/src/mir/from_hir.cpp index 98aa74d8..d0b2dbbc 100644 --- a/src/mir/from_hir.cpp +++ b/src/mir/from_hir.cpp @@ -405,86 +405,79 @@ namespace { { TRACE_FUNCTION_F("_Block"); // NOTE: This doesn't create a BB, as BBs are not needed for scoping - if( node.m_nodes.size() > 0 ) - { - bool diverged = false; + bool diverged = false; - auto res_val = (node.m_yields_final ? m_builder.new_temporary(node.m_res_type) : ::MIR::LValue()); - auto scope = m_builder.new_scope_var(node.span()); - auto tmp_scope = m_builder.new_scope_temp(node.span()); - auto _block_tmp_scope = save_and_edit(m_block_tmp_scope, &tmp_scope); + auto res_val = (node.m_value_node ? m_builder.new_temporary(node.m_res_type) : ::MIR::LValue()); + auto scope = m_builder.new_scope_var(node.span()); + auto tmp_scope = m_builder.new_scope_temp(node.span()); + auto _block_tmp_scope = save_and_edit(m_block_tmp_scope, &tmp_scope); - for(unsigned int i = 0; i < node.m_nodes.size() - (node.m_yields_final ? 1 : 0); i ++) - { - auto _ = save_and_edit(m_borrow_raise_target, nullptr); - auto& subnode = node.m_nodes[i]; - const Span& sp = subnode->span(); + for(unsigned int i = 0; i < node.m_nodes.size(); i ++) + { + auto _ = save_and_edit(m_borrow_raise_target, nullptr); + auto& subnode = node.m_nodes[i]; + const Span& sp = subnode->span(); - auto stmt_scope = m_builder.new_scope_temp(sp); - this->visit_node_ptr(subnode); + auto stmt_scope = m_builder.new_scope_temp(sp); + this->visit_node_ptr(subnode); - if( m_builder.block_active() || m_builder.has_result() ) { - // TODO: Emit a drop - m_builder.get_result(sp); - m_builder.terminate_scope(sp, mv$(stmt_scope)); - } - else { - m_builder.terminate_scope(sp, mv$(stmt_scope), false); + if( m_builder.block_active() || m_builder.has_result() ) { + // TODO: Emit a drop + m_builder.get_result(sp); + m_builder.terminate_scope(sp, mv$(stmt_scope)); + } + else { + m_builder.terminate_scope(sp, mv$(stmt_scope), false); - m_builder.set_cur_block( m_builder.new_bb_unlinked() ); - diverged = true; - } + m_builder.set_cur_block( m_builder.new_bb_unlinked() ); + diverged = true; } + } - // For the last node, specially handle. - if( node.m_yields_final ) - { - auto& subnode = node.m_nodes.back(); - const Span& sp = subnode->span(); + // For the last node, specially handle. + if( node.m_value_node ) + { + auto& subnode = node.m_value_node; + const Span& sp = subnode->span(); - auto stmt_scope = m_builder.new_scope_temp(sp); - this->visit_node_ptr(subnode); - if( m_builder.has_result() || m_builder.block_active() ) - { - ASSERT_BUG(sp, m_builder.block_active(), "Result yielded, but no active block"); - ASSERT_BUG(sp, m_builder.has_result(), "Active block but no result yeilded"); - // PROBLEM: This can drop the result before we want to use it. + auto stmt_scope = m_builder.new_scope_temp(sp); + this->visit_node_ptr(subnode); + if( m_builder.has_result() || m_builder.block_active() ) + { + ASSERT_BUG(sp, m_builder.block_active(), "Result yielded, but no active block"); + ASSERT_BUG(sp, m_builder.has_result(), "Active block but no result yeilded"); + // PROBLEM: This can drop the result before we want to use it. - m_builder.push_stmt_assign(sp, res_val.clone(), m_builder.get_result(sp)); + m_builder.push_stmt_assign(sp, res_val.clone(), m_builder.get_result(sp)); - m_builder.terminate_scope(sp, mv$(stmt_scope)); - m_builder.terminate_scope(node.span(), mv$(tmp_scope) ); - m_builder.terminate_scope(node.span(), mv$(scope) ); - m_builder.set_result( node.span(), mv$(res_val) ); - } - else - { - m_builder.terminate_scope( sp, mv$(stmt_scope), false ); - m_builder.terminate_scope( node.span(), mv$(tmp_scope), false ); - m_builder.terminate_scope( node.span(), mv$(scope), false ); - // Block diverged in final node. - } + m_builder.terminate_scope(sp, mv$(stmt_scope)); + m_builder.terminate_scope(node.span(), mv$(tmp_scope) ); + m_builder.terminate_scope(node.span(), mv$(scope) ); + m_builder.set_result( node.span(), mv$(res_val) ); } else { - if( diverged ) - { - m_builder.terminate_scope( node.span(), mv$(tmp_scope), false ); - m_builder.terminate_scope( node.span(), mv$(scope), false ); - m_builder.end_block( ::MIR::Terminator::make_Diverge({}) ); - // Don't set a result if there's no block. - } - else - { - m_builder.terminate_scope( node.span(), mv$(tmp_scope) ); - m_builder.terminate_scope( node.span(), mv$(scope) ); - m_builder.set_result(node.span(), ::MIR::RValue::make_Tuple({})); - } + m_builder.terminate_scope( sp, mv$(stmt_scope), false ); + m_builder.terminate_scope( node.span(), mv$(tmp_scope), false ); + m_builder.terminate_scope( node.span(), mv$(scope), false ); + // Block diverged in final node. } } else { - m_builder.set_result(node.span(), ::MIR::RValue::make_Tuple({})); + if( diverged ) + { + m_builder.terminate_scope( node.span(), mv$(tmp_scope), false ); + m_builder.terminate_scope( node.span(), mv$(scope), false ); + m_builder.end_block( ::MIR::Terminator::make_Diverge({}) ); + // Don't set a result if there's no block. + } + else + { + m_builder.terminate_scope( node.span(), mv$(tmp_scope) ); + m_builder.terminate_scope( node.span(), mv$(scope) ); + m_builder.set_result(node.span(), ::MIR::RValue::make_Tuple({})); + } } } void visit(::HIR::ExprNode_Asm& node) override |