diff options
author | Ian Lance Taylor <ian@gcc.gnu.org> | 2017-06-23 16:03:49 +0000 |
---|---|---|
committer | Ian Lance Taylor <ian@gcc.gnu.org> | 2017-06-23 16:03:49 +0000 |
commit | 5f0b897b2ee47bf3845d924dd5bc3beb949bc78b (patch) | |
tree | 3f8b464d9ac9de6affa319ea9639ee19ef983302 /gcc/go/gofrontend/parse.cc | |
parent | ef2361cbd8462374b28e9e8becf8710a9b30d125 (diff) | |
download | gcc-5f0b897b2ee47bf3845d924dd5bc3beb949bc78b.zip gcc-5f0b897b2ee47bf3845d924dd5bc3beb949bc78b.tar.gz gcc-5f0b897b2ee47bf3845d924dd5bc3beb949bc78b.tar.bz2 |
compiler: add go:notinheap magic comment
Implement go:notinheap as the gc compiler does. A type marked as
go:notinheap may not live in the heap, and does not require a write
barrier. Struct and array types that incorporate notinheap types are
themselves notinheap. Allocating a value of a notinheap type on the
heap is an error.
This is not just an optimization. There is code where a write barrier
may not occur that was getting a write barrier with gccgo but not gc,
because the types in question were notinheap. The case I found was
setting the mcache field in exitsyscallfast.
Reviewed-on: https://go-review.googlesource.com/46490
From-SVN: r249594
Diffstat (limited to 'gcc/go/gofrontend/parse.cc')
-rw-r--r-- | gcc/go/gofrontend/parse.cc | 52 |
1 files changed, 38 insertions, 14 deletions
diff --git a/gcc/go/gofrontend/parse.cc b/gcc/go/gofrontend/parse.cc index 84840fb..28b1772 100644 --- a/gcc/go/gofrontend/parse.cc +++ b/gcc/go/gofrontend/parse.cc @@ -1310,14 +1310,16 @@ Parse::declaration() const Token* token = this->peek_token(); unsigned int pragmas = this->lex_->get_and_clear_pragmas(); - if (pragmas != 0 && !token->is_keyword(KEYWORD_FUNC)) + if (pragmas != 0 + && !token->is_keyword(KEYWORD_FUNC) + && !token->is_keyword(KEYWORD_TYPE)) go_warning_at(token->location(), 0, "ignoring magic comment before non-function"); if (token->is_keyword(KEYWORD_CONST)) this->const_decl(); else if (token->is_keyword(KEYWORD_TYPE)) - this->type_decl(); + this->type_decl(pragmas); else if (token->is_keyword(KEYWORD_VAR)) this->var_decl(); else if (token->is_keyword(KEYWORD_FUNC)) @@ -1342,7 +1344,8 @@ Parse::declaration_may_start_here() // Decl<P> = P | "(" [ List<P> ] ")" . void -Parse::decl(void (Parse::*pfn)(void*), void* varg) +Parse::decl(void (Parse::*pfn)(void*, unsigned int), void* varg, + unsigned int pragmas) { if (this->peek_token()->is_eof()) { @@ -1352,9 +1355,12 @@ Parse::decl(void (Parse::*pfn)(void*), void* varg) } if (!this->peek_token()->is_op(OPERATOR_LPAREN)) - (this->*pfn)(varg); + (this->*pfn)(varg, pragmas); else { + if (pragmas != 0) + go_warning_at(this->location(), 0, + "ignoring magic //go:... comment before group"); if (!this->advance_token()->is_op(OPERATOR_RPAREN)) { this->list(pfn, varg, true); @@ -1378,9 +1384,10 @@ Parse::decl(void (Parse::*pfn)(void*), void* varg) // might follow. This is either a '}' or a ')'. void -Parse::list(void (Parse::*pfn)(void*), void* varg, bool follow_is_paren) +Parse::list(void (Parse::*pfn)(void*, unsigned int), void* varg, + bool follow_is_paren) { - (this->*pfn)(varg); + (this->*pfn)(varg, 0); Operator follow = follow_is_paren ? OPERATOR_RPAREN : OPERATOR_RCURLY; while (this->peek_token()->is_op(OPERATOR_SEMICOLON) || this->peek_token()->is_op(OPERATOR_COMMA)) @@ -1389,7 +1396,7 @@ Parse::list(void (Parse::*pfn)(void*), void* varg, bool follow_is_paren) go_error_at(this->location(), "unexpected comma"); if (this->advance_token()->is_op(follow)) break; - (this->*pfn)(varg); + (this->*pfn)(varg, 0); } } @@ -1508,17 +1515,17 @@ Parse::const_spec(Type** last_type, Expression_list** last_expr_list) // TypeDecl = "type" Decl<TypeSpec> . void -Parse::type_decl() +Parse::type_decl(unsigned int pragmas) { go_assert(this->peek_token()->is_keyword(KEYWORD_TYPE)); this->advance_token(); - this->decl(&Parse::type_spec, NULL); + this->decl(&Parse::type_spec, NULL, pragmas); } // TypeSpec = identifier ["="] Type . void -Parse::type_spec(void*) +Parse::type_spec(void*, unsigned int pragmas) { const Token* token = this->peek_token(); if (!token->is_identifier()) @@ -1592,6 +1599,15 @@ Parse::type_spec(void*) this->gogo_->define_type(named_type, nt); go_assert(named_type->package() == NULL); + + if ((pragmas & GOPRAGMA_NOTINHEAP) != 0) + { + nt->set_not_in_heap(); + pragmas &= ~GOPRAGMA_NOTINHEAP; + } + if (pragmas != 0) + go_warning_at(location, 0, + "ignoring magic //go:... comment before type"); } else { @@ -1608,15 +1624,19 @@ Parse::var_decl() { go_assert(this->peek_token()->is_keyword(KEYWORD_VAR)); this->advance_token(); - this->decl(&Parse::var_spec, NULL); + this->decl(&Parse::var_spec, NULL, 0); } // VarSpec = IdentifierList // ( CompleteType [ "=" ExpressionList ] | "=" ExpressionList ) . void -Parse::var_spec(void*) +Parse::var_spec(void*, unsigned int pragmas) { + if (pragmas != 0) + go_warning_at(this->location(), 0, + "ignoring magic //go:... comment before var"); + // Get the variable names. Typed_identifier_list til; this->identifier_list(&til); @@ -5698,14 +5718,18 @@ Parse::import_decl() { go_assert(this->peek_token()->is_keyword(KEYWORD_IMPORT)); this->advance_token(); - this->decl(&Parse::import_spec, NULL); + this->decl(&Parse::import_spec, NULL, 0); } // ImportSpec = [ "." | PackageName ] PackageFileName . void -Parse::import_spec(void*) +Parse::import_spec(void*, unsigned int pragmas) { + if (pragmas != 0) + go_warning_at(this->location(), 0, + "ignoring magic //go:... comment before import"); + const Token* token = this->peek_token(); Location location = token->location(); |