diff options
author | Martin Liska <mliska@suse.cz> | 2021-08-05 19:50:30 +0200 |
---|---|---|
committer | Martin Liska <mliska@suse.cz> | 2021-08-05 19:50:30 +0200 |
commit | f182597d273fe81ffae6dfece17fecadd01842f7 (patch) | |
tree | de04d1a91a0c59ca773707b395393d0ce12516e7 /gcc/go | |
parent | fc45f824a020dff1ec2ea68cef1d23345fb7d447 (diff) | |
parent | 4739344d36e6d24764cbedde44a3fff6edc70f6c (diff) | |
download | gcc-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/MERGE | 2 | ||||
-rw-r--r-- | gcc/go/gofrontend/escape.cc | 117 | ||||
-rw-r--r-- | gcc/go/gofrontend/expressions.cc | 49 | ||||
-rw-r--r-- | gcc/go/gofrontend/expressions.h | 75 | ||||
-rw-r--r-- | gcc/go/gofrontend/runtime.def | 8 | ||||
-rw-r--r-- | gcc/go/gofrontend/statements.cc | 59 | ||||
-rw-r--r-- | gcc/go/gofrontend/types.cc | 4 |
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 |