diff options
author | Ian Lance Taylor <iant@google.com> | 2012-02-07 19:26:30 +0000 |
---|---|---|
committer | Ian Lance Taylor <ian@gcc.gnu.org> | 2012-02-07 19:26:30 +0000 |
commit | b806269c9bfe8527dae3f634f5696ec95c5c38e4 (patch) | |
tree | 7a4a7ef3281dc5d38c6298df6b666d0b18f5eb8f /gcc/go | |
parent | 85dcef0d4194393a9de3cec41fc41331b62a909f (diff) | |
download | gcc-b806269c9bfe8527dae3f634f5696ec95c5c38e4.zip gcc-b806269c9bfe8527dae3f634f5696ec95c5c38e4.tar.gz gcc-b806269c9bfe8527dae3f634f5696ec95c5c38e4.tar.bz2 |
compiler, libgo: Use //extern comments rather than __asm__.
From-SVN: r183981
Diffstat (limited to 'gcc/go')
-rw-r--r-- | gcc/go/ChangeLog | 5 | ||||
-rw-r--r-- | gcc/go/gccgo.texi | 18 | ||||
-rw-r--r-- | gcc/go/gofrontend/lex.cc | 35 | ||||
-rw-r--r-- | gcc/go/gofrontend/lex.h | 8 | ||||
-rw-r--r-- | gcc/go/gofrontend/parse.cc | 22 |
5 files changed, 76 insertions, 12 deletions
diff --git a/gcc/go/ChangeLog b/gcc/go/ChangeLog index 04ac6ac..40afb84 100644 --- a/gcc/go/ChangeLog +++ b/gcc/go/ChangeLog @@ -1,3 +1,8 @@ +2012-02-07 Ian Lance Taylor <iant@google.com> + + * gccgo.texi (Function Names): Document //extern instead of + __asm__. + 2012-02-01 Jakub Jelinek <jakub@redhat.com> PR target/52079 diff --git a/gcc/go/gccgo.texi b/gcc/go/gccgo.texi index dc8b022..13b56fc 100644 --- a/gcc/go/gccgo.texi +++ b/gcc/go/gccgo.texi @@ -304,14 +304,20 @@ function is still using it. @node Function Names @section Function Names -@cindex @code{__asm__} +@cindex @code{extern} +@cindex external names Go code can call C functions directly using a Go extension implemented -in @command{gccgo}: a function declaration may be followed by -@code{__asm__ ("@var{name}")}. For example, here is how the C function -@code{open} can be declared in Go: +in @command{gccgo}: a function declaration may be preceded by a +comment giving the external name. The comment must be at the +beginning of the line and must start with @code{//extern}. This must +be followed by a space and then the external name of the function. +The function declaration must be on the line immediately after the +comment. For example, here is how the C function @code{open} can be +declared in Go: @smallexample -func c_open(name *byte, mode int, perm int) int __asm__ ("open"); +//extern open +func c_open(name *byte, mode int, perm int) int @end smallexample The C function naturally expects a nul terminated string, which in Go @@ -333,7 +339,7 @@ present the name of a Go function that does not have a receiver is @option{-fgo-prefix} option used when the package is compiled; if the option is not used, the default is simply @code{go}. To call the function from C you must set the name using the @command{gcc} -extension similar to the @command{gccgo} extension. +@code{__asm__} extension. @smallexample extern int go_function(int) __asm__ ("myprefix.mypackage.Function"); diff --git a/gcc/go/gofrontend/lex.cc b/gcc/go/gofrontend/lex.cc index d46334f..53618fc 100644 --- a/gcc/go/gofrontend/lex.cc +++ b/gcc/go/gofrontend/lex.cc @@ -442,7 +442,7 @@ Token::print(FILE* file) const Lex::Lex(const char* input_file_name, FILE* input_file, Linemap* linemap) : input_file_name_(input_file_name), input_file_(input_file), linemap_(linemap), linebuf_(NULL), linebufsize_(120), linesize_(0), - lineoff_(0), lineno_(0), add_semi_at_eol_(false) + lineoff_(0), lineno_(0), add_semi_at_eol_(false), extern_() { this->linebuf_ = new char[this->linebufsize_]; this->linemap_->start_file(input_file_name, 0); @@ -541,6 +541,7 @@ Lex::earlier_location(int chars) const Token Lex::next_token() { + bool saw_cpp_comment = false; while (true) { if (!this->require_line()) @@ -552,6 +553,10 @@ Lex::next_token() return this->make_eof_token(); } + if (!saw_cpp_comment) + this->extern_.clear(); + saw_cpp_comment = false; + const char* p = this->linebuf_ + this->lineoff_; const char* pend = this->linebuf_ + this->linesize_; @@ -588,6 +593,7 @@ Lex::next_token() p = pend; if (p[-1] == '\n' && this->add_semi_at_eol_) --p; + saw_cpp_comment = true; } else if (p[1] == '*') { @@ -1606,6 +1612,10 @@ Lex::skip_c_comment() void Lex::skip_cpp_comment() { + // Ensure that if EXTERN_ is set, it means that we just saw a + // //extern comment. + this->extern_.clear(); + const char* p = this->linebuf_ + this->lineoff_; const char* pend = this->linebuf_ + this->linesize_; @@ -1648,12 +1658,35 @@ Lex::skip_cpp_comment() } } + // As a special gccgo extension, a C++ comment at the start of the + // line of the form + // //extern NAME + // which immediately precedes a function declaration means that the + // external name of the function declaration is NAME. This is + // normally used to permit Go code to call a C function. + if (this->lineoff_ == 2 + && pend - p > 7 + && memcmp(p, "extern ", 7) == 0) + { + p += 7; + while (p < pend && (*p == ' ' || *p == '\t')) + ++p; + const char* plend = pend; + while (plend > p + && (plend[-1] == ' ' || plend[-1] == '\t' || plend[-1] == '\n')) + --plend; + if (plend > p) + this->extern_ = std::string(p, plend - p); + } + while (p < pend) { this->lineoff_ = p - this->linebuf_; unsigned int c; bool issued_error; p = this->advance_one_utf8_char(p, &c, &issued_error); + if (issued_error) + this->extern_.clear(); } } diff --git a/gcc/go/gofrontend/lex.h b/gcc/go/gofrontend/lex.h index b184b1e..8858e73 100644 --- a/gcc/go/gofrontend/lex.h +++ b/gcc/go/gofrontend/lex.h @@ -344,6 +344,11 @@ class Lex Token next_token(); + // Return the contents of any current //extern comment. + const std::string& + extern_name() const + { return this->extern_; } + // Return whether the identifier NAME should be exported. NAME is a // mangled name which includes only ASCII characters. static bool @@ -474,6 +479,9 @@ class Lex size_t lineno_; // Whether to add a semicolon if we see a newline now. bool add_semi_at_eol_; + // The external name to use for a function declaration, from a magic + // //extern comment. + std::string extern_; }; #endif // !defined(GO_LEX_H) diff --git a/gcc/go/gofrontend/parse.cc b/gcc/go/gofrontend/parse.cc index 10abfc0..6eb1981 100644 --- a/gcc/go/gofrontend/parse.cc +++ b/gcc/go/gofrontend/parse.cc @@ -2093,17 +2093,19 @@ Parse::simple_var_decl_or_assignment(const std::string& name, // FunctionDecl = "func" identifier Signature [ Block ] . // MethodDecl = "func" Receiver identifier Signature [ Block ] . -// gcc extension: +// Deprecated gcc extension: // FunctionDecl = "func" identifier Signature // __asm__ "(" string_lit ")" . // This extension means a function whose real name is the identifier -// inside the asm. +// inside the asm. This extension will be removed at some future +// date. It has been replaced with //extern comments. void Parse::function_decl() { go_assert(this->peek_token()->is_keyword(KEYWORD_FUNC)); Location location = this->location(); + std::string extern_name = this->lex_->extern_name(); const Token* token = this->advance_token(); Typed_identifier* rec = NULL; @@ -2173,10 +2175,20 @@ Parse::function_decl() { if (named_object == NULL && !Gogo::is_sink_name(name)) { - if (fntype != NULL) - this->gogo_->declare_function(name, fntype, location); - else + if (fntype == NULL) this->gogo_->add_erroneous_name(name); + else + { + named_object = this->gogo_->declare_function(name, fntype, + location); + if (!extern_name.empty() + && named_object->is_function_declaration()) + { + Function_declaration* fd = + named_object->func_declaration_value(); + fd->set_asm_name(extern_name); + } + } } } else |