summaryrefslogtreecommitdiff
path: root/src/cmd/dist
diff options
context:
space:
mode:
authorRuss Cox <rsc@golang.org>2014-02-20 15:58:47 -0500
committerRuss Cox <rsc@golang.org>2014-02-20 15:58:47 -0500
commit50be4ad5a71a5db95c620805be653d41c7d41ebd (patch)
tree04da6a5c5c0cb818c19ba9d3bd0ff29fab3f02d7 /src/cmd/dist
parent2efcb8f023cf5fa5c79ff62790be9f2eef4e248a (diff)
downloadgo-50be4ad5a71a5db95c620805be653d41c7d41ebd.tar.gz
runtime: use goc2c as much as possible
Package runtime's C functions written to be called from Go started out written in C using carefully constructed argument lists and the FLUSH macro to write a result back to memory. For some functions, the appropriate parameter list ended up being architecture-dependent due to differences in alignment, so we added 'goc2c', which takes a .goc file containing Go func declarations but C bodies, rewrites the Go func declaration to equivalent C declarations for the target architecture, adds the needed FLUSH statements, and writes out an equivalent C file. That C file is compiled as part of package runtime. Native Client's x86-64 support introduces the most complex alignment rules yet, breaking many functions that could until now be portably written in C. Using goc2c for those avoids the breakage. Separately, Keith's work on emitting stack information from the C compiler would require the hand-written functions to add #pragmas specifying how many arguments are result parameters. Using goc2c for those avoids maintaining #pragmas. For both reasons, use goc2c for as many Go-called C functions as possible. This CL is a replay of the bulk of CL 15400047 and CL 15790043, both of which were reviewed as part of the NaCl port and are checked in to the NaCl branch. This CL is part of bringing the NaCl code into the main tree. No new code here, just reformatting and occasional movement into .h files. LGTM=r R=dave, alex.brainman, r CC=golang-codereviews https://codereview.appspot.com/65220044
Diffstat (limited to 'src/cmd/dist')
-rw-r--r--src/cmd/dist/buildruntime.c4
-rw-r--r--src/cmd/dist/goc2c.c97
2 files changed, 70 insertions, 31 deletions
diff --git a/src/cmd/dist/buildruntime.c b/src/cmd/dist/buildruntime.c
index 1babddaad..59b355b07 100644
--- a/src/cmd/dist/buildruntime.c
+++ b/src/cmd/dist/buildruntime.c
@@ -370,10 +370,8 @@ mkzsys(char *dir, char *file)
}
static char *runtimedefs[] = {
+ "defs.c",
"proc.c",
- "iface.c",
- "hashmap.c",
- "chan.c",
"parfor.c",
};
diff --git a/src/cmd/dist/goc2c.c b/src/cmd/dist/goc2c.c
index f0fa04335..36b43f56e 100644
--- a/src/cmd/dist/goc2c.c
+++ b/src/cmd/dist/goc2c.c
@@ -85,11 +85,15 @@ enum {
String,
Slice,
Eface,
+ Complex128,
+ Float32,
+ Float64,
};
static struct {
char *name;
int size;
+ int rnd; // alignment
} type_table[] = {
/*
* variable sized first, for easy replacement.
@@ -105,6 +109,7 @@ static struct {
{"String", 8},
{"Slice", 12},
{"Eface", 8},
+ {"Complex128", 16},
/* fixed size */
{"float32", 4},
@@ -130,7 +135,7 @@ int structround = 4;
static void
bad_eof(void)
{
- fatal("%s:%ud: unexpected EOF\n", file, lineno);
+ fatal("%s:%d: unexpected EOF\n", file, lineno);
}
/* Free a list of parameters. */
@@ -295,9 +300,9 @@ read_package(void)
token = read_token_no_eof();
if (token == nil)
- fatal("%s:%ud: no token\n", file, lineno);
+ fatal("%s:%d: no token\n", file, lineno);
if (!streq(token, "package")) {
- fatal("%s:%ud: expected \"package\", got \"%s\"\n",
+ fatal("%s:%d: expected \"package\", got \"%s\"\n",
file, lineno, token);
}
return read_token_no_eof();
@@ -307,6 +312,9 @@ read_package(void)
static void
read_preprocessor_lines(void)
{
+ int first;
+
+ first = 1;
while (1) {
int c;
@@ -317,6 +325,10 @@ read_preprocessor_lines(void)
xungetc();
break;
}
+ if(first) {
+ first = 0;
+ xputchar('\n');
+ }
xputchar(c);
do {
c = getchar_update_lineno();
@@ -365,17 +377,24 @@ read_type(void)
/* Return the size of the given type. */
static int
-type_size(char *p)
+type_size(char *p, int *rnd)
{
int i;
- if(p[xstrlen(p)-1] == '*')
+ if(p[xstrlen(p)-1] == '*') {
+ *rnd = type_table[Uintptr].rnd;
return type_table[Uintptr].size;
+ }
+
+ if(streq(p, "Iface"))
+ p = "Eface";
for(i=0; type_table[i].name; i++)
- if(streq(type_table[i].name, p))
+ if(streq(type_table[i].name, p)) {
+ *rnd = type_table[i].rnd;
return type_table[i].size;
- fatal("%s:%ud: unknown type %s\n", file, lineno, p);
+ }
+ fatal("%s:%d: unknown type %s\n", file, lineno, p);
return 0;
}
@@ -398,18 +417,22 @@ read_params(int *poffset)
while (1) {
p = xmalloc(sizeof(struct params));
p->name = token;
- p->type = read_type();
p->next = nil;
*pp = p;
pp = &p->next;
- size = type_size(p->type);
- rnd = size;
- if(rnd > structround)
- rnd = structround;
- if(offset%rnd)
- offset += rnd - offset%rnd;
- offset += size;
+ if(streq(token, "...")) {
+ p->type = xstrdup("");
+ } else {
+ p->type = read_type();
+ rnd = 0;
+ size = type_size(p->type, &rnd);
+ if(rnd > structround)
+ rnd = structround;
+ if(offset%rnd)
+ offset += rnd - offset%rnd;
+ offset += size;
+ }
token = read_token_no_eof();
if (!streq(token, ","))
@@ -418,7 +441,7 @@ read_params(int *poffset)
}
}
if (!streq(token, ")")) {
- fatal("%s:%ud: expected '('\n",
+ fatal("%s:%d: expected '('\n",
file, lineno);
}
if (poffset != nil)
@@ -438,6 +461,7 @@ read_func_header(char **name, struct params **params, int *paramwid, struct para
lastline = -1;
while (1) {
+ read_preprocessor_lines();
token = read_token();
if (token == nil)
return 0;
@@ -460,7 +484,7 @@ read_func_header(char **name, struct params **params, int *paramwid, struct para
token = read_token();
if (token == nil || !streq(token, "(")) {
- fatal("%s:%ud: expected \"(\"\n",
+ fatal("%s:%d: expected \"(\"\n",
file, lineno);
}
*params = read_params(paramwid);
@@ -473,7 +497,7 @@ read_func_header(char **name, struct params **params, int *paramwid, struct para
token = read_token();
}
if (token == nil || !streq(token, "{")) {
- fatal("%s:%ud: expected \"{\"\n",
+ fatal("%s:%d: expected \"{\"\n",
file, lineno);
}
return 1;
@@ -501,7 +525,11 @@ write_6g_func_header(char *package, char *name, struct params *params,
{
int first, n;
- bwritef(output, "void\n%s·%s(", package, name);
+ bwritef(output, "void\n");
+ if(!contains(name, "·"))
+ bwritef(output, "%s·", package);
+ bwritef(output, "%s(", name);
+
first = 1;
write_params(params, &first);
@@ -527,7 +555,8 @@ write_6g_func_trailer(struct params *rets)
struct params *p;
for (p = rets; p != nil; p = p->next)
- bwritef(output, "\tFLUSH(&%s);\n", p->name);
+ if(!streq(p->name, "..."))
+ bwritef(output, "\tFLUSH(&%s);\n", p->name);
bwritef(output, "}\n");
}
@@ -726,6 +755,7 @@ process_file(void)
void
goc2c(char *goc, char *c)
{
+ int i;
Buf in, out;
binit(&in);
@@ -739,13 +769,15 @@ goc2c(char *goc, char *c)
if(!gcc) {
if(streq(goarch, "amd64")) {
type_table[Uintptr].size = 8;
- type_table[Eface].size = 8+8;
- type_table[String].size = 16;
if(use64bitint) {
type_table[Int].size = 8;
- type_table[Uint].size = 8;
+ } else {
+ type_table[Int].size = 4;
}
- type_table[Slice].size = 8+2*type_table[Int].size;
+ structround = 8;
+ } else if(streq(goarch, "amd64p32")) {
+ type_table[Uintptr].size = 4;
+ type_table[Int].size = 4;
structround = 8;
} else {
// NOTE: These are set in the initializer,
@@ -753,13 +785,22 @@ goc2c(char *goc, char *c)
// previous invocation of goc2c, so we have
// to restore them.
type_table[Uintptr].size = 4;
- type_table[String].size = 8;
- type_table[Slice].size = 16;
- type_table[Eface].size = 4+4;
type_table[Int].size = 4;
- type_table[Uint].size = 4;
structround = 4;
}
+
+ type_table[Uint].size = type_table[Int].size;
+ type_table[Slice].size = type_table[Uintptr].size+2*type_table[Int].size;
+ type_table[Eface].size = 2*type_table[Uintptr].size;
+ type_table[String].size = 2*type_table[Uintptr].size;
+
+ for(i=0; i<nelem(type_table); i++)
+ type_table[i].rnd = type_table[i].size;
+
+ type_table[String].rnd = type_table[Uintptr].rnd;
+ type_table[Slice].rnd = type_table[Uintptr].rnd;
+ type_table[Eface].rnd = type_table[Uintptr].rnd;
+ type_table[Complex128].rnd = type_table[Float64].rnd;
}
bprintf(&out, "// auto generated by go tool dist\n// goos=%s goarch=%s\n\n", goos, goarch);