diff options
Diffstat (limited to 'gcc/go')
-rw-r--r-- | gcc/go/gofrontend/MERGE | 2 | ||||
-rw-r--r-- | gcc/go/gofrontend/gogo.cc | 25 | ||||
-rw-r--r-- | gcc/go/gofrontend/gogo.h | 12 | ||||
-rw-r--r-- | gcc/go/gofrontend/lex.cc | 6 | ||||
-rw-r--r-- | gcc/go/gofrontend/lex.h | 2 |
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. |