aboutsummaryrefslogtreecommitdiff
path: root/gcc/go
diff options
context:
space:
mode:
authorIan Lance Taylor <iant@google.com>2012-02-07 19:26:30 +0000
committerIan Lance Taylor <ian@gcc.gnu.org>2012-02-07 19:26:30 +0000
commitb806269c9bfe8527dae3f634f5696ec95c5c38e4 (patch)
tree7a4a7ef3281dc5d38c6298df6b666d0b18f5eb8f /gcc/go
parent85dcef0d4194393a9de3cec41fc41331b62a909f (diff)
downloadgcc-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/ChangeLog5
-rw-r--r--gcc/go/gccgo.texi18
-rw-r--r--gcc/go/gofrontend/lex.cc35
-rw-r--r--gcc/go/gofrontend/lex.h8
-rw-r--r--gcc/go/gofrontend/parse.cc22
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