1
0
mirror of https://github.com/golang/go synced 2024-11-18 12:34:42 -07:00

undo CL 11683043 / bb75d03e6ccb

Broke arm build.
R=dave

««« original CL description
cc: generate argument pointer maps for C functions.

R=golang-dev, rsc
CC=golang-dev
https://golang.org/cl/11683043
»»»

R=golang-dev
CC=golang-dev
https://golang.org/cl/11788043
This commit is contained in:
Keith Randall 2013-07-24 15:04:10 -07:00
parent 6e37bc1eec
commit b3defa2e8e

View File

@ -31,8 +31,6 @@
#include "gc.h" #include "gc.h"
#include "../../pkg/runtime/funcdata.h" #include "../../pkg/runtime/funcdata.h"
static int32 pointermap(Sym *gcsym, int32 offset);
int int
hasdotdotdot(void) hasdotdotdot(void)
{ {
@ -103,22 +101,7 @@ codgen(Node *n, Node *nn)
p = gtext(n1->sym, stkoff); p = gtext(n1->sym, stkoff);
sp = p; sp = p;
/*
* generate funcdata symbol for this function.
* data is filled in at the end of codgen().
*/
snprint(namebuf, sizeof namebuf, "gc·%d", ngcsym++);
gcsym = slookup(namebuf);
gcsym->class = CSTATIC;
memset(&nod, 0, sizeof nod);
nod.op = ONAME;
nod.sym = gcsym;
nod.class = CSTATIC;
gins(AFUNCDATA, nodconst(FUNCDATA_GC), &nod);
/* /*
* isolate first argument * isolate first argument
*/ */
@ -156,6 +139,17 @@ codgen(Node *n, Node *nn)
maxargsafe = xround(maxargsafe, 8); maxargsafe = xround(maxargsafe, 8);
sp->to.offset += maxargsafe; sp->to.offset += maxargsafe;
snprint(namebuf, sizeof namebuf, "gc·%d", ngcsym++);
gcsym = slookup(namebuf);
gcsym->class = CSTATIC;
memset(&nod, 0, sizeof nod);
nod.op = ONAME;
nod.sym = gcsym;
nod.class = CSTATIC;
gins(AFUNCDATA, nodconst(FUNCDATA_GC), &nod);
// TODO(rsc): "stkoff" is not right. It does not account for // TODO(rsc): "stkoff" is not right. It does not account for
// the possibility of data stored in .safe variables. // the possibility of data stored in .safe variables.
// Unfortunately those move up and down just like // Unfortunately those move up and down just like
@ -168,7 +162,8 @@ codgen(Node *n, Node *nn)
off = 0; off = 0;
gextern(gcsym, nodconst(stkoff), off, 4); // locals gextern(gcsym, nodconst(stkoff), off, 4); // locals
off += 4; off += 4;
off = pointermap(gcsym, off); // nptrs and ptrs[...] gextern(gcsym, nodconst(0), off, 4); // nptrs
off += 4;
gcsym->type = typ(0, T); gcsym->type = typ(0, T);
gcsym->type->width = off; gcsym->type->width = off;
} }
@ -638,105 +633,3 @@ bcomplex(Node *n, Node *c)
boolgen(n, 1, Z); boolgen(n, 1, Z);
return 0; return 0;
} }
// Makes a bitmap marking the the pointers in t. t starts at the given byte
// offset in the argument list. The returned bitmap should be for pointer
// indexes (relative to offset 0) between baseidx and baseidx+32.
static int32
pointermap_type(Type *t, int32 offset, int32 baseidx)
{
Type *t1;
int32 idx;
int32 m;
switch(t->etype) {
case TCHAR:
case TUCHAR:
case TSHORT:
case TUSHORT:
case TINT:
case TUINT:
case TLONG:
case TULONG:
case TVLONG:
case TUVLONG:
case TFLOAT:
case TDOUBLE:
// non-pointer types
return 0;
case TIND:
case TARRAY: // unlike Go, C passes arrays by reference
// pointer types
if((offset + t->offset) % ewidth[TIND] != 0)
yyerror("unaligned pointer");
idx = (offset + t->offset) / ewidth[TIND];
if(idx >= baseidx && idx < baseidx + 32)
return 1 << (idx - baseidx);
return 0;
case TSTRUCT:
// build map recursively
m = 0;
for(t1=t->link; t1; t1=t1->down)
m |= pointermap_type(t1, offset, baseidx);
return m;
case TUNION:
// We require that all elements of the union have the same pointer map.
m = pointermap_type(t->link, offset, baseidx);
for(t1=t->link->down; t1; t1=t1->down) {
if(pointermap_type(t1, offset, baseidx) != m)
yyerror("invalid union in argument list - pointer maps differ");
}
return m;
default:
yyerror("can't handle arg type %s\n", tnames[t->etype]);
return 0;
}
}
// Compute a bit vector to describe the pointer containing locations
// in the argument list. Adds the data to gcsym and returns the offset
// of end of the bit vector.
static int32
pointermap(Sym *gcsym, int32 off)
{
int32 nptrs;
int32 i;
int32 s; // offset in argument list (in bytes)
int32 m; // current ptrs[i/32]
Type *t;
if(hasdotdotdot()) {
// give up for C vararg functions.
// TODO: maybe make a map just for the args we do know?
gextern(gcsym, nodconst(0), off, 4); // nptrs=0
return off + 4;
}
nptrs = (argsize() + ewidth[TIND] - 1) / ewidth[TIND];
gextern(gcsym, nodconst(nptrs), off, 4);
off += 4;
for(i = 0; i < nptrs; i += 32) {
// generate mask for ptrs at offsets i ... i+31
m = 0;
s = align(0, thisfn->link, Aarg0, nil);
if(s > 0 && i == 0) {
// C Calling convention returns structs by copying
// them to a location pointed to by a hidden first
// argument. This first argument is a pointer.
if(s != ewidth[TIND])
yyerror("passbyptr arg not the right size");
m = 1;
}
for(t=thisfn->down; t!=T; t=t->down) {
if(t->etype == TVOID)
continue;
s = align(s, t, Aarg1, nil);
m |= pointermap_type(t, s, i);
s = align(s, t, Aarg2, nil);
}
gextern(gcsym, nodconst(m), off, 4);
off += 4;
}
return off;
// TODO: needs a test for nptrs>32
}