summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJohn Hodge <tpg@ucc.asn.au>2017-05-07 15:55:51 +0800
committerJohn Hodge <tpg@ucc.asn.au>2017-05-07 15:55:51 +0800
commit592c816af31a534dde7274d2bd38661585a71ac7 (patch)
tree7eb175fb179d65ea7f413a87c871a81f3e8b6b72
parentec1dc3542bd5122db57f4459f63a6040f5e3ab20 (diff)
downloadmrust-592c816af31a534dde7274d2bd38661585a71ac7.tar.gz
HIR - Replace m_yeilds_final_value with a node
-rw-r--r--src/hir/dump.cpp30
-rw-r--r--src/hir/expr.cpp2
-rw-r--r--src/hir/expr.hpp9
-rw-r--r--src/hir/from_ast_expr.cpp8
-rw-r--r--src/hir_conv/constant_evaluation.cpp4
-rw-r--r--src/hir_expand/annotate_value_usage.cpp2
-rw-r--r--src/hir_expand/reborrow.cpp4
-rw-r--r--src/hir_typeck/expr_check.cpp5
-rw-r--r--src/hir_typeck/expr_cs.cpp110
-rw-r--r--src/mir/dump.cpp26
-rw-r--r--src/mir/from_hir.cpp119
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