summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorRuss Cox <rsc@golang.org>2009-06-30 20:01:41 -0700
committerRuss Cox <rsc@golang.org>2009-06-30 20:01:41 -0700
commitaf736458bb44f892c35adf0533161fda7e452ae3 (patch)
treec7cbc676c8a071162daeb4524e9b14a2345c3b33 /src
parent8d2eb65d5f613f22e78f20e0ac0f2d7fa4528910 (diff)
downloadgolang-af736458bb44f892c35adf0533161fda7e452ae3.tar.gz
in preparation for changing 6g's behavior to
align the output args separately from the input args, change cgo2c to insert the necessary padding when the two arg lists are concatenated in the c translation. for example, there is a runtime func indexstring(s string, i int32) (b byte) right now in 6g those arguments are aligned in one struct with s at offset 0, i at 16, and b at 20. soon the b byte will be in its own struct and structs are 8 aligned, so it will be b at 24. right now cgo2c generates: void indexstring(string s, int32 i, byte b) this CL makes it generate, in --6g mode: void indexstring(string s, int32 i, uint32, byte b) this is valid 6c input, although not valid gcc input. (the code is being generated for 6c only anyway.) also, allow C code to be mixed in among the Go funcs. every instance of the token `func' is expected to start a new go func. R=iant DELTA=145 (118 added, 0 deleted, 27 changed) OCL=30949 CL=30963
Diffstat (limited to 'src')
-rw-r--r--src/pkg/runtime/cgo2c.c170
1 files changed, 144 insertions, 26 deletions
diff --git a/src/pkg/runtime/cgo2c.c b/src/pkg/runtime/cgo2c.c
index 3905f7e6d..e6c7634ff 100644
--- a/src/pkg/runtime/cgo2c.c
+++ b/src/pkg/runtime/cgo2c.c
@@ -37,6 +37,51 @@ struct params {
char *type;
};
+/* index into type_table */
+enum {
+ Bool,
+ Float,
+ Int,
+ Uint,
+ Uintptr,
+ String,
+ Array,
+};
+
+static struct {
+ char *name;
+ int size;
+} type_table[] = {
+ /* variable sized first, for easy replacement */
+ /* order matches enum above */
+ /* default is 32-bit architecture sizes */
+ "bool", 1,
+ "float", 4,
+ "int", 4,
+ "uint", 4,
+ "uintptr", 4,
+ "String", 8,
+ "Array", 12,
+
+ /* fixed size */
+ "float32", 4,
+ "float64", 8,
+ "byte", 1,
+ "int8", 1,
+ "uint8", 1,
+ "int16", 2,
+ "uint16", 2,
+ "int32", 4,
+ "uint32", 4,
+ "int64", 8,
+ "uint64", 8,
+
+ NULL,
+};
+
+/* Fixed structure alignment (non-gcc only) */
+int structround = 4;
+
/* Unexpected EOF. */
static void
bad_eof(void)
@@ -184,6 +229,8 @@ read_token(void)
if (c == EOF)
break;
if (isspace(c) || strchr(delims, c) != NULL) {
+ if (c == '\n')
+ lineno--;
ungetc(c, stdin);
break;
}
@@ -231,7 +278,7 @@ read_preprocessor_lines(void)
} while (isspace(c));
if (c != '#') {
ungetc(c, stdin);
- return;
+ break;
}
putchar(c);
do {
@@ -272,24 +319,52 @@ read_type(void)
return q;
}
+/* Return the size of the given type. */
+static int
+type_size(char *p)
+{
+ int i;
+
+ if(p[strlen(p)-1] == '*')
+ return type_table[Uintptr].size;
+
+ for(i=0; type_table[i].name; i++)
+ if(strcmp(type_table[i].name, p) == 0)
+ return type_table[i].size;
+ fprintf(stderr, "%s:%u: unknown type %s\n", file, lineno, p);
+ exit(1);
+ return 0;
+}
+
/* Read a list of parameters. Each parameter is a name and a type.
The list ends with a ')'. We have already read the '('. */
static struct params *
-read_params(void)
+read_params(int *poffset)
{
char *token;
- struct params *ret, **pp;
+ struct params *ret, **pp, *p;
+ int offset, size, rnd;
ret = NULL;
pp = &ret;
token = read_token_no_eof();
+ offset = 0;
if (strcmp(token, ")") != 0) {
while (1) {
- *pp = xmalloc(sizeof(struct params));
- (*pp)->name = token;
- (*pp)->type = read_type();
- pp = &(*pp)->next;
- *pp = NULL;
+ p = xmalloc(sizeof(struct params));
+ p->name = token;
+ p->type = read_type();
+ p->next = NULL;
+ *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;
token = read_token_no_eof();
if (strcmp(token, ",") != 0)
@@ -302,24 +377,39 @@ read_params(void)
file, lineno);
exit(1);
}
+ if (poffset != NULL)
+ *poffset = offset;
return ret;
}
/* Read a function header. This reads up to and including the initial
'{' character. Returns 1 if it read a header, 0 at EOF. */
static int
-read_func_header(char **name, struct params **params, struct params **rets)
+read_func_header(char **name, struct params **params, int *paramwid, struct params **rets)
{
+ int lastline;
char *token;
- token = read_token();
- if (token == NULL)
- return 0;
- if (strcmp(token, "func") != 0) {
- fprintf(stderr, "%s:%u: expected \"func\"\n",
- file, lineno);
- exit(1);
+ lastline = -1;
+ while (1) {
+ token = read_token();
+ if (token == NULL)
+ return 0;
+ if (strcmp(token, "func") == 0) {
+ if(lastline != -1)
+ printf("\n");
+ break;
+ }
+ if (lastline != lineno) {
+ if (lastline == lineno-1)
+ printf("\n");
+ else
+ printf("\n#line %d \"%s\"\n", lineno, file);
+ lastline = lineno;
+ }
+ printf("%s ", token);
}
+
*name = read_token_no_eof();
token = read_token();
@@ -328,13 +418,13 @@ read_func_header(char **name, struct params **params, struct params **rets)
file, lineno);
exit(1);
}
- *params = read_params();
+ *params = read_params(paramwid);
token = read_token();
if (token == NULL || strcmp(token, "(") != 0)
*rets = NULL;
else {
- *rets = read_params();
+ *rets = read_params(NULL);
token = read_token();
}
if (token == NULL || strcmp(token, "{") != 0) {
@@ -363,13 +453,25 @@ write_params(struct params *params, int *first)
/* Write a 6g function header. */
static void
write_6g_func_header(char *package, char *name, struct params *params,
- struct params *rets)
+ int paramwid, struct params *rets)
{
- int first;
+ int first, n;
printf("void\n%s·%s(", package, name);
first = 1;
write_params(params, &first);
+
+ /* insert padding to align output struct */
+ if(rets != NULL && paramwid%structround != 0) {
+ n = structround - paramwid%structround;
+ if(n & 1)
+ printf(", uint8");
+ if(n & 2)
+ printf(", uint16");
+ if(n & 4)
+ printf(", uint32");
+ }
+
write_params(rets, &first);
printf(")\n{\n");
}
@@ -456,12 +558,13 @@ write_gcc_func_trailer(char *package, char *name, struct params *rets)
/* Write out a function header. */
static void
write_func_header(char *package, char *name,
- struct params *params, struct params *rets)
+ struct params *params, int paramwid,
+ struct params *rets)
{
if (gcc)
write_gcc_func_header(package, name, params, rets);
else
- write_6g_func_header(package, name, params, rets);
+ write_6g_func_header(package, name, params, paramwid, rets);
printf("#line %d \"%s\"\n", lineno, file);
}
@@ -546,11 +649,12 @@ process_file(void)
{
char *package, *name;
struct params *params, *rets;
+ int paramwid;
package = read_package();
read_preprocessor_lines();
- while (read_func_header(&name, &params, &rets)) {
- write_func_header(package, name, params, rets);
+ while (read_func_header(&name, &params, &paramwid, &rets)) {
+ write_func_header(package, name, params, paramwid, rets);
copy_body();
write_func_trailer(package, name, rets);
free(name);
@@ -570,6 +674,8 @@ usage(void)
int
main(int argc, char **argv)
{
+ char *goarch;
+
while(argc > 1 && argv[1][0] == '-') {
if(strcmp(argv[1], "-") == 0)
break;
@@ -582,13 +688,13 @@ main(int argc, char **argv)
argc--;
argv++;
}
-
+
if(argc <= 1 || strcmp(argv[1], "-") == 0) {
file = "<stdin>";
process_file();
return 0;
}
-
+
if(argc > 2)
usage();
@@ -597,6 +703,18 @@ main(int argc, char **argv)
fprintf(stderr, "open %s: %s\n", file, strerror(errno));
exit(1);
}
+
+ if(!gcc) {
+ // 6g etc; update size table
+ goarch = getenv("GOARCH");
+ if(goarch != NULL && strcmp(goarch, "amd64") == 0) {
+ type_table[Uintptr].size = 8;
+ type_table[String].size = 16;
+ type_table[Array].size = 8+4+4;
+ structround = 8;
+ }
+ }
+
process_file();
return 0;
}