aboutsummaryrefslogtreecommitdiff
path: root/gcc/go/gofrontend/parse.cc
diff options
context:
space:
mode:
authorIan Lance Taylor <ian@gcc.gnu.org>2017-06-23 16:03:49 +0000
committerIan Lance Taylor <ian@gcc.gnu.org>2017-06-23 16:03:49 +0000
commit5f0b897b2ee47bf3845d924dd5bc3beb949bc78b (patch)
tree3f8b464d9ac9de6affa319ea9639ee19ef983302 /gcc/go/gofrontend/parse.cc
parentef2361cbd8462374b28e9e8becf8710a9b30d125 (diff)
downloadgcc-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.cc52
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();