aboutsummaryrefslogtreecommitdiff
path: root/gcc
diff options
context:
space:
mode:
authorIan Lance Taylor <ian@gcc.gnu.org>2019-08-31 03:01:15 +0000
committerIan Lance Taylor <ian@gcc.gnu.org>2019-08-31 03:01:15 +0000
commitc70ff9f9be0c7360a37519ec68ac4dd41e8d0a3c (patch)
tree2a189fbed2324d7708bfe231203bd294028057c9 /gcc
parente7c8f75569e792f81a4f4ceee4e1b20f2544e7a4 (diff)
downloadgcc-c70ff9f9be0c7360a37519ec68ac4dd41e8d0a3c.zip
gcc-c70ff9f9be0c7360a37519ec68ac4dd41e8d0a3c.tar.gz
gcc-c70ff9f9be0c7360a37519ec68ac4dd41e8d0a3c.tar.bz2
compiler, runtime: support and use single argument go:linkname
The gc compiler has started permitting go:linkname comments with a single argument to mean that a function should be externally visible outside the package. Implement this in the Go frontend. Change the libgo runtime package to use it, rather than repeating the name just to export a function. Remove a couple of unnecessary go:linkname comments on declarations. Reviewed-on: https://go-review.googlesource.com/c/gofrontend/+/192197 From-SVN: r275239
Diffstat (limited to 'gcc')
-rw-r--r--gcc/go/gofrontend/MERGE2
-rw-r--r--gcc/go/gofrontend/gogo.cc25
-rw-r--r--gcc/go/gofrontend/gogo.h12
-rw-r--r--gcc/go/gofrontend/lex.cc6
-rw-r--r--gcc/go/gofrontend/lex.h2
5 files changed, 38 insertions, 9 deletions
diff --git a/gcc/go/gofrontend/MERGE b/gcc/go/gofrontend/MERGE
index 888e96d..025e66e 100644
--- a/gcc/go/gofrontend/MERGE
+++ b/gcc/go/gofrontend/MERGE
@@ -1,4 +1,4 @@
-80403eb9e95c9642ebabb4d7c43deedaa763211f
+289d94b9e6303ec74649d1f08d418300f2b4d0fd
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/gogo.cc b/gcc/go/gofrontend/gogo.cc
index f8114ece..d39a4fb 100644
--- a/gcc/go/gofrontend/gogo.cc
+++ b/gcc/go/gofrontend/gogo.cc
@@ -2531,9 +2531,22 @@ Gogo::add_linkname(const std::string& go_name, bool is_exported,
if (no == NULL)
go_error_at(loc, "%s is not defined", go_name.c_str());
else if (no->is_function())
- no->func_value()->set_asm_name(ext_name);
+ {
+ if (ext_name.empty())
+ no->func_value()->set_is_exported_by_linkname();
+ else
+ no->func_value()->set_asm_name(ext_name);
+ }
else if (no->is_function_declaration())
- no->func_declaration_value()->set_asm_name(ext_name);
+ {
+ if (ext_name.empty())
+ go_error_at(loc,
+ ("//%<go:linkname%> missing external name "
+ "for declaration of %s"),
+ go_name.c_str());
+ else
+ no->func_declaration_value()->set_asm_name(ext_name);
+ }
else
go_error_at(loc,
("%s is not a function; "
@@ -5465,7 +5478,8 @@ Function::Function(Function_type* type, Named_object* enclosing, Block* block,
calls_recover_(false), is_recover_thunk_(false), has_recover_thunk_(false),
calls_defer_retaddr_(false), is_type_specific_function_(false),
in_unique_section_(false), export_for_inlining_(false),
- is_inline_only_(false), is_referenced_by_inline_(false)
+ is_inline_only_(false), is_referenced_by_inline_(false),
+ is_exported_by_linkname_(false)
{
}
@@ -6220,6 +6234,11 @@ Function::get_or_make_decl(Gogo* gogo, Named_object* no)
if (this->is_referenced_by_inline_)
flags |= Backend::function_is_visible;
+ // A go:linkname directive can be used to force a function to be
+ // visible.
+ if (this->is_exported_by_linkname_)
+ flags |= Backend::function_is_visible;
+
// If a function calls the predeclared recover function, we
// can't inline it, because recover behaves differently in a
// function passed directly to defer. If this is a recover
diff --git a/gcc/go/gofrontend/gogo.h b/gcc/go/gofrontend/gogo.h
index 087e890..e742b6e 100644
--- a/gcc/go/gofrontend/gogo.h
+++ b/gcc/go/gofrontend/gogo.h
@@ -547,7 +547,9 @@ class Gogo
{ this->file_block_names_[name] = location; }
// Add a linkname, from the go:linkname compiler directive. This
- // changes the externally visible name of go_name to be ext_name.
+ // changes the externally visible name of GO_NAME to be EXT_NAME.
+ // If EXT_NAME is the empty string, GO_NAME is unchanged, but the
+ // symbol is made publicly visible.
void
add_linkname(const std::string& go_name, bool is_exported,
const std::string& ext_name, Location location);
@@ -1359,6 +1361,11 @@ class Function
set_asm_name(const std::string& asm_name)
{ this->asm_name_ = asm_name; }
+ // Mark this symbol as exported by a linkname directive.
+ void
+ set_is_exported_by_linkname()
+ { this->is_exported_by_linkname_ = true; }
+
// Return the pragmas for this function.
unsigned int
pragmas() const
@@ -1706,6 +1713,9 @@ class Function
// True if this function is referenced from an inlined body that
// will be put into the export data.
bool is_referenced_by_inline_ : 1;
+ // True if we should make this function visible to other packages
+ // because of a go:linkname directive.
+ bool is_exported_by_linkname_ : 1;
};
// A snapshot of the current binding state.
diff --git a/gcc/go/gofrontend/lex.cc b/gcc/go/gofrontend/lex.cc
index 3276de4..f023613 100644
--- a/gcc/go/gofrontend/lex.cc
+++ b/gcc/go/gofrontend/lex.cc
@@ -1996,7 +1996,7 @@ Lex::skip_cpp_comment()
while (ps < pend && *ps != ' ' && *ps != '\t')
++ps;
- if (ps < pend)
+ if (ps <= pend)
go_name = std::string(pg, ps - pg);
while (ps < pend && (*ps == ' ' || *ps == '\t'))
++ps;
@@ -2015,8 +2015,8 @@ Lex::skip_cpp_comment()
ext_name.clear();
}
}
- if (go_name.empty() || ext_name.empty())
- go_error_at(loc, "usage: %<//go:linkname%> localname linkname");
+ if (go_name.empty())
+ go_error_at(loc, "usage: %<//go:linkname%> localname [linkname]");
else
{
if (this->linknames_ == NULL)
diff --git a/gcc/go/gofrontend/lex.h b/gcc/go/gofrontend/lex.h
index 59b770c..3be3806 100644
--- a/gcc/go/gofrontend/lex.h
+++ b/gcc/go/gofrontend/lex.h
@@ -380,7 +380,7 @@ class Lex
struct Linkname
{
- std::string ext_name; // External name.
+ std::string ext_name; // External name; empty to just export.
bool is_exported; // Whether the internal name is exported.
Location loc; // Location of go:linkname directive.