aboutsummaryrefslogtreecommitdiff
path: root/gcc/go
diff options
context:
space:
mode:
authorMartin Liska <mliska@suse.cz>2021-08-05 19:50:30 +0200
committerMartin Liska <mliska@suse.cz>2021-08-05 19:50:30 +0200
commitf182597d273fe81ffae6dfece17fecadd01842f7 (patch)
treede04d1a91a0c59ca773707b395393d0ce12516e7 /gcc/go
parentfc45f824a020dff1ec2ea68cef1d23345fb7d447 (diff)
parent4739344d36e6d24764cbedde44a3fff6edc70f6c (diff)
downloadgcc-f182597d273fe81ffae6dfece17fecadd01842f7.zip
gcc-f182597d273fe81ffae6dfece17fecadd01842f7.tar.gz
gcc-f182597d273fe81ffae6dfece17fecadd01842f7.tar.bz2
Merge branch 'master' into devel/sphinx
Diffstat (limited to 'gcc/go')
-rw-r--r--gcc/go/gofrontend/MERGE2
-rw-r--r--gcc/go/gofrontend/escape.cc117
-rw-r--r--gcc/go/gofrontend/expressions.cc49
-rw-r--r--gcc/go/gofrontend/expressions.h75
-rw-r--r--gcc/go/gofrontend/runtime.def8
-rw-r--r--gcc/go/gofrontend/statements.cc59
-rw-r--r--gcc/go/gofrontend/types.cc4
7 files changed, 227 insertions, 87 deletions
diff --git a/gcc/go/gofrontend/MERGE b/gcc/go/gofrontend/MERGE
index 95b9340..394530c 100644
--- a/gcc/go/gofrontend/MERGE
+++ b/gcc/go/gofrontend/MERGE
@@ -1,4 +1,4 @@
-0a4d612e6b211780b294717503fc739bbd1f509c
+b47bcf942daa9a0c252db9b57b8f138adbfcdaa2
The first line of this file holds the git revision number of the last
merge done from the gofrontend repository.
diff --git a/gcc/go/gofrontend/escape.cc b/gcc/go/gofrontend/escape.cc
index cf68874..c8978ac 100644
--- a/gcc/go/gofrontend/escape.cc
+++ b/gcc/go/gofrontend/escape.cc
@@ -1608,8 +1608,33 @@ Escape_analysis_assign::expression(Expression** pexpr)
}
break;
- default:
+ case Builtin_call_expression::BUILTIN_CLOSE:
+ case Builtin_call_expression::BUILTIN_DELETE:
+ case Builtin_call_expression::BUILTIN_PRINT:
+ case Builtin_call_expression::BUILTIN_PRINTLN:
+ case Builtin_call_expression::BUILTIN_LEN:
+ case Builtin_call_expression::BUILTIN_CAP:
+ case Builtin_call_expression::BUILTIN_COMPLEX:
+ case Builtin_call_expression::BUILTIN_REAL:
+ case Builtin_call_expression::BUILTIN_IMAG:
+ case Builtin_call_expression::BUILTIN_RECOVER:
+ case Builtin_call_expression::BUILTIN_ALIGNOF:
+ case Builtin_call_expression::BUILTIN_OFFSETOF:
+ case Builtin_call_expression::BUILTIN_SIZEOF:
+ // these do not escape.
+ break;
+
+ case Builtin_call_expression::BUILTIN_ADD:
+ case Builtin_call_expression::BUILTIN_SLICE:
+ // handled in ::assign.
break;
+
+ case Builtin_call_expression::BUILTIN_MAKE:
+ case Builtin_call_expression::BUILTIN_NEW:
+ // should have been lowered to runtime calls at this point.
+ // fallthrough
+ default:
+ go_unreachable();
}
break;
}
@@ -2325,19 +2350,82 @@ Escape_analysis_assign::assign(Node* dst, Node* src)
}
break;
+ case Expression::EXPRESSION_SLICE_INFO:
+ {
+ Slice_info_expression* sie = e->slice_info_expression();
+ if (sie->info() == Expression::SLICE_INFO_VALUE_POINTER)
+ {
+ Node* slice = Node::make_node(sie->slice());
+ this->assign(dst, slice);
+ }
+ }
+ break;
+
case Expression::EXPRESSION_CALL:
{
Call_expression* call = e->call_expression();
if (call->is_builtin())
{
Builtin_call_expression* bce = call->builtin_call_expression();
- if (bce->code() == Builtin_call_expression::BUILTIN_APPEND)
+ switch (bce->code())
{
- // Append returns the first argument.
- // The subsequent arguments are already leaked because
- // they are operands to append.
- Node* appendee = Node::make_node(call->args()->front());
- this->assign(dst, appendee);
+ case Builtin_call_expression::BUILTIN_APPEND:
+ {
+ // Append returns the first argument.
+ // The subsequent arguments are already leaked because
+ // they are operands to append.
+ Node* appendee = Node::make_node(call->args()->front());
+ this->assign(dst, appendee);
+ }
+ break;
+
+ case Builtin_call_expression::BUILTIN_ADD:
+ {
+ // unsafe.Add(p, off).
+ // Flow p to result.
+ Node* arg = Node::make_node(call->args()->front());
+ this->assign(dst, arg);
+ }
+ break;
+
+ case Builtin_call_expression::BUILTIN_SLICE:
+ {
+ // unsafe.Slice(p, len).
+ // The resulting slice has the same backing store as p. Flow p to result.
+ Node* arg = Node::make_node(call->args()->front());
+ this->assign(dst, arg);
+ }
+ break;
+
+ case Builtin_call_expression::BUILTIN_LEN:
+ case Builtin_call_expression::BUILTIN_CAP:
+ case Builtin_call_expression::BUILTIN_COMPLEX:
+ case Builtin_call_expression::BUILTIN_REAL:
+ case Builtin_call_expression::BUILTIN_IMAG:
+ case Builtin_call_expression::BUILTIN_RECOVER:
+ case Builtin_call_expression::BUILTIN_ALIGNOF:
+ case Builtin_call_expression::BUILTIN_OFFSETOF:
+ case Builtin_call_expression::BUILTIN_SIZEOF:
+ // these do not escape.
+ break;
+
+ case Builtin_call_expression::BUILTIN_COPY:
+ // handled in ::expression.
+ break;
+
+ case Builtin_call_expression::BUILTIN_CLOSE:
+ case Builtin_call_expression::BUILTIN_DELETE:
+ case Builtin_call_expression::BUILTIN_PRINT:
+ case Builtin_call_expression::BUILTIN_PRINTLN:
+ case Builtin_call_expression::BUILTIN_PANIC:
+ // these do not have result.
+ // fallthrough
+ case Builtin_call_expression::BUILTIN_MAKE:
+ case Builtin_call_expression::BUILTIN_NEW:
+ // should have been lowered to runtime calls at this point.
+ // fallthrough
+ default:
+ go_unreachable();
}
break;
}
@@ -2592,6 +2680,21 @@ Escape_analysis_assign::assign(Node* dst, Node* src)
}
break;
+ case Expression::EXPRESSION_CONDITIONAL:
+ {
+ Conditional_expression* ce = e->conditional_expression();
+ this->assign(dst, Node::make_node(ce->then_expr()));
+ this->assign(dst, Node::make_node(ce->else_expr()));
+ }
+ break;
+
+ case Expression::EXPRESSION_COMPOUND:
+ {
+ Compound_expression* ce = e->compound_expression();
+ this->assign(dst, Node::make_node(ce->expr()));
+ }
+ break;
+
default:
// TODO(cmang): Add debug info here; this should not be reachable.
// For now, just to be conservative, we'll just say dst flows to src.
diff --git a/gcc/go/gofrontend/expressions.cc b/gcc/go/gofrontend/expressions.cc
index 15c9eab..3e433d6 100644
--- a/gcc/go/gofrontend/expressions.cc
+++ b/gcc/go/gofrontend/expressions.cc
@@ -3962,7 +3962,10 @@ Type_conversion_expression::do_lower(Gogo*, Named_object*,
if (type->points_to() != NULL
&& type->points_to()->array_type() != NULL
&& !type->points_to()->is_slice_type()
- && val->type()->is_slice_type())
+ && val->type()->is_slice_type()
+ && Type::are_identical(type->points_to()->array_type()->element_type(),
+ val->type()->array_type()->element_type(),
+ 0, NULL))
{
Temporary_statement* val_temp = NULL;
if (!val->is_multi_eval_safe())
@@ -18006,49 +18009,7 @@ Expression::make_type_info(Type* type, Type_info type_info)
return new Type_info_expression(type, type_info);
}
-// An expression that evaluates to some characteristic of a slice.
-// This is used when indexing, bound-checking, or nil checking a slice.
-
-class Slice_info_expression : public Expression
-{
- public:
- Slice_info_expression(Expression* slice, Slice_info slice_info,
- Location location)
- : Expression(EXPRESSION_SLICE_INFO, location),
- slice_(slice), slice_info_(slice_info)
- { }
-
- protected:
- Type*
- do_type();
-
- void
- do_determine_type(const Type_context*)
- { }
-
- Expression*
- do_copy()
- {
- return new Slice_info_expression(this->slice_->copy(), this->slice_info_,
- this->location());
- }
-
- Bexpression*
- do_get_backend(Translate_context* context);
-
- void
- do_dump_expression(Ast_dump_context*) const;
-
- void
- do_issue_nil_check()
- { this->slice_->issue_nil_check(); }
-
- private:
- // The slice for which we are getting information.
- Expression* slice_;
- // What information we want.
- Slice_info slice_info_;
-};
+// Slice_info_expression.
// Return the type of the slice info.
diff --git a/gcc/go/gofrontend/expressions.h b/gcc/go/gofrontend/expressions.h
index 492849b..79a8785 100644
--- a/gcc/go/gofrontend/expressions.h
+++ b/gcc/go/gofrontend/expressions.h
@@ -62,6 +62,7 @@ class Type_guard_expression;
class Heap_expression;
class Receive_expression;
class Slice_value_expression;
+class Slice_info_expression;
class Conditional_expression;
class Compound_expression;
class Numeric_constant;
@@ -900,6 +901,14 @@ class Expression
compound_expression()
{ return this->convert<Compound_expression, EXPRESSION_COMPOUND>(); }
+ // If this is a slice info expression, return the
+ // Slice_info_expression structure. Otherwise, return NULL.
+ Slice_info_expression*
+ slice_info_expression()
+ {
+ return this->convert<Slice_info_expression, EXPRESSION_SLICE_INFO>();
+ }
+
// Return true if this is a composite literal.
bool
is_composite_literal() const;
@@ -4262,6 +4271,60 @@ class Slice_value_expression : public Expression
Expression* cap_;
};
+// An expression that evaluates to some characteristic of a slice.
+// This is used when indexing, bound-checking, or nil checking a slice.
+
+class Slice_info_expression : public Expression
+{
+ public:
+ Slice_info_expression(Expression* slice, Slice_info slice_info,
+ Location location)
+ : Expression(EXPRESSION_SLICE_INFO, location),
+ slice_(slice), slice_info_(slice_info)
+ { }
+
+ // The slice operand of this slice info expression.
+ Expression*
+ slice() const
+ { return this->slice_; }
+
+ // The info this expression is about.
+ Slice_info
+ info() const
+ { return this->slice_info_; }
+
+ protected:
+ Type*
+ do_type();
+
+ void
+ do_determine_type(const Type_context*)
+ { }
+
+ Expression*
+ do_copy()
+ {
+ return new Slice_info_expression(this->slice_->copy(), this->slice_info_,
+ this->location());
+ }
+
+ Bexpression*
+ do_get_backend(Translate_context* context);
+
+ void
+ do_dump_expression(Ast_dump_context*) const;
+
+ void
+ do_issue_nil_check()
+ { this->slice_->issue_nil_check(); }
+
+ private:
+ // The slice for which we are getting information.
+ Expression* slice_;
+ // What information we want.
+ Slice_info slice_info_;
+};
+
// Conditional expressions.
class Conditional_expression : public Expression
@@ -4277,6 +4340,14 @@ class Conditional_expression : public Expression
condition() const
{ return this->cond_; }
+ Expression*
+ then_expr() const
+ { return this->then_; }
+
+ Expression*
+ else_expr() const
+ { return this->else_; }
+
protected:
int
do_traverse(Traverse*);
@@ -4322,6 +4393,10 @@ class Compound_expression : public Expression
init() const
{ return this->init_; }
+ Expression*
+ expr() const
+ { return this->expr_; }
+
protected:
int
do_traverse(Traverse*);
diff --git a/gcc/go/gofrontend/runtime.def b/gcc/go/gofrontend/runtime.def
index fad8ceb..87a2708 100644
--- a/gcc/go/gofrontend/runtime.def
+++ b/gcc/go/gofrontend/runtime.def
@@ -204,12 +204,8 @@ DEF_GO_RUNTIME(SELECTNBSEND, "runtime.selectnbsend", P2(CHAN, POINTER), R1(BOOL)
// Non-blocking receive a value from a channel, used for two-case select
// statement with a default case.
-DEF_GO_RUNTIME(SELECTNBRECV, "runtime.selectnbrecv", P2(POINTER, CHAN), R1(BOOL))
-
-// Non-blocking tuple receive from a channel, used for two-case select
-// statement with a default case.
-DEF_GO_RUNTIME(SELECTNBRECV2, "runtime.selectnbrecv2", P3(POINTER, POINTER, CHAN),
- R1(BOOL))
+DEF_GO_RUNTIME(SELECTNBRECV, "runtime.selectnbrecv", P2(POINTER, CHAN),
+ R2(BOOL, BOOL))
// Block execution. Used for zero-case select.
DEF_GO_RUNTIME(BLOCK, "runtime.block", P0(), R0())
diff --git a/gcc/go/gofrontend/statements.cc b/gcc/go/gofrontend/statements.cc
index 9643d1b..95fa3c4 100644
--- a/gcc/go/gofrontend/statements.cc
+++ b/gcc/go/gofrontend/statements.cc
@@ -6051,7 +6051,7 @@ Select_statement::lower_two_case(Block* b)
Expression* chanref = Expression::make_temporary_reference(chantmp, loc);
Block* bchan;
- Expression* call;
+ Expression* cond;
if (chancase.is_send())
{
// if selectnbsend(chan, &val) { body } else { default body }
@@ -6065,7 +6065,7 @@ Select_statement::lower_two_case(Block* b)
Expression* ref = Expression::make_temporary_reference(ts, loc);
Expression* addr = Expression::make_unary(OPERATOR_AND, ref, loc);
- call = Runtime::make_call(Runtime::SELECTNBSEND, loc, 2, chanref, addr);
+ cond = Runtime::make_call(Runtime::SELECTNBSEND, loc, 2, chanref, addr);
bchan = chancase.statements();
}
else
@@ -6075,34 +6075,31 @@ Select_statement::lower_two_case(Block* b)
Expression* ref = Expression::make_temporary_reference(ts, loc);
Expression* addr = Expression::make_unary(OPERATOR_AND, ref, loc);
- Expression* okref = NULL;
- if (chancase.closed() == NULL && chancase.closedvar() == NULL)
- {
- // Simple receive.
- // if selectnbrecv(&lhs, chan) { body } else { default body }
- call = Runtime::make_call(Runtime::SELECTNBRECV, loc, 2, addr, chanref);
- }
- else
- {
- // Tuple receive.
- // if selectnbrecv2(&lhs, &ok, chan) { body } else { default body }
-
- Type* booltype = Type::make_boolean_type();
- Temporary_statement* okts = Statement::make_temporary(booltype, NULL,
- loc);
- b->add_statement(okts);
-
- okref = Expression::make_temporary_reference(okts, loc);
- Expression* okaddr = Expression::make_unary(OPERATOR_AND, okref, loc);
- call = Runtime::make_call(Runtime::SELECTNBRECV2, loc, 3, addr, okaddr,
- chanref);
- }
+
+ // selected, ok = selectnbrecv(&lhs, chan)
+ Call_expression* call = Runtime::make_call(Runtime::SELECTNBRECV, loc, 2,
+ addr, chanref);
+
+ Temporary_statement* selected_temp =
+ Statement::make_temporary(Type::make_boolean_type(),
+ Expression::make_call_result(call, 0),
+ loc);
+ b->add_statement(selected_temp);
+
+ Temporary_statement* ok_temp =
+ Statement::make_temporary(Type::make_boolean_type(),
+ Expression::make_call_result(call, 1),
+ loc);
+ b->add_statement(ok_temp);
+
+ cond = Expression::make_temporary_reference(selected_temp, loc);
Location cloc = chancase.location();
bchan = new Block(b, loc);
if (chancase.val() != NULL && !chancase.val()->is_sink_expression())
{
- Statement* as = Statement::make_assignment(chancase.val(), ref->copy(),
+ Statement* as = Statement::make_assignment(chancase.val(),
+ ref->copy(),
cloc);
bchan->add_statement(as);
}
@@ -6114,12 +6111,18 @@ Select_statement::lower_two_case(Block* b)
if (chancase.closed() != NULL && !chancase.closed()->is_sink_expression())
{
+ Expression* okref = Expression::make_temporary_reference(ok_temp,
+ cloc);
Statement* as = Statement::make_assignment(chancase.closed(),
- okref->copy(), cloc);
+ okref, cloc);
bchan->add_statement(as);
}
else if (chancase.closedvar() != NULL)
- chancase.closedvar()->var_value()->set_init(okref->copy());
+ {
+ Expression* okref = Expression::make_temporary_reference(ok_temp,
+ cloc);
+ chancase.closedvar()->var_value()->set_init(okref);
+ }
Statement* bs = Statement::make_block_statement(chancase.statements(),
cloc);
@@ -6127,7 +6130,7 @@ Select_statement::lower_two_case(Block* b)
}
Statement* ifs =
- Statement::make_if_statement(call, bchan, defcase.statements(), loc);
+ Statement::make_if_statement(cond, bchan, defcase.statements(), loc);
b->add_statement(ifs);
Statement* label =
diff --git a/gcc/go/gofrontend/types.cc b/gcc/go/gofrontend/types.cc
index 7c7b2eb..0c44186 100644
--- a/gcc/go/gofrontend/types.cc
+++ b/gcc/go/gofrontend/types.cc
@@ -846,7 +846,9 @@ Type::are_convertible(const Type* lhs, const Type* rhs, std::string* reason)
if (rhs->is_slice_type()
&& lhs->points_to() != NULL
&& lhs->points_to()->array_type() != NULL
- && !lhs->points_to()->is_slice_type())
+ && !lhs->points_to()->is_slice_type()
+ && Type::are_identical(lhs->points_to()->array_type()->element_type(),
+ rhs->array_type()->element_type(), 0, reason))
return true;
// An unsafe.Pointer type may be converted to any pointer type or to