1
0
mirror of https://github.com/golang/go synced 2024-11-20 08:04:42 -07:00

first attempt at real FFI support.

in a .6 file, an export line

	//ffi T localfib remotefib remote.so

means the dynamic linker should initialize
localfib, always a pointer, to the address of
remotefib, either text (T) or data (D) after
loading remote.so.

the C compiler will generate an export section
when given the pragmas

	#pragma package fib
	#pragma ffi T localfib remotefib remote.so

needing #pragma package is a bit of a kludge
and hopefully could go away later.

this is just the 6 tool chain support.
other architectures will happen once 6 settles down.

code using this to do FFI is in a later CL.

R=r
DELTA=161  (141 added, 14 deleted, 6 changed)
OCL=33783
CL=33795
This commit is contained in:
Russ Cox 2009-08-24 16:15:21 -07:00
parent 0262f8834d
commit 8c253bcae5
7 changed files with 149 additions and 22 deletions

View File

@ -232,6 +232,19 @@ outcode(void)
Binit(&b, f, OWRITE);
Bprint(&b, "%s\n", thestring);
if(nffi > 0) {
int i;
if(package == nil) {
yyerror("#pragma ffi without #pragma package");
package = "_ffi_";
}
Bprint(&b, "\n$$ // ffi\n", thestring);
Bprint(&b, "package %s\n", package);
for(i=0; i<nffi; i++)
Bprint(&b, "//ffi %c %s %s %s\n", ffi[i].type, ffi[i].local, ffi[i].remote, ffi[i].path);
Bprint(&b, "$$\n\n$$\n\n");
}
Bprint(&b, "!\n");
outhist(&b);

View File

@ -1550,6 +1550,7 @@ parsepkgdata(char **pp, char *ep, char **prefixp, char **namep, char **defp)
// skip white space
p = *pp;
again:
while(p < ep && (*p == ' ' || *p == '\t'))
p++;
if(p == ep)
@ -1569,7 +1570,13 @@ parsepkgdata(char **pp, char *ep, char **prefixp, char **namep, char **defp)
p += 5;
else if(strncmp(p, "const ", 6) == 0)
p += 6;
else{
else if(strncmp(p, "//", 2) == 0) {
p = memchr(p, '\n', ep - p);
if(p == nil)
return 0;
p++;
goto again;
} else {
fprint(2, "ar: confused in pkg data near <<%.20s>>\n", p);
errors++;
return -1;

View File

@ -49,6 +49,7 @@ typedef struct Hist Hist;
typedef struct Term Term;
typedef struct Init Init;
typedef struct Bits Bits;
typedef struct Ffi Ffi;
#define NHUNK 50000L
#define BUFSIZ 8192
@ -436,6 +437,18 @@ struct Funct
Sym* castfr[NTYPE];
};
struct Ffi
{
char type;
char* local;
char* remote;
char* path;
};
EXTERN Ffi *ffi;
EXTERN int nffi;
EXTERN char* package;
EXTERN struct
{
Type* tenum; /* type of entire enum */
@ -740,6 +753,8 @@ void pragpack(void);
void pragfpround(void);
void pragtextflag(void);
void pragincomplete(void);
void pragffi(void);
void pragpackage(void);
/*
* calls to machine depend part

View File

@ -200,13 +200,35 @@ arginit(void)
flagbits['X'] = flagbits['o'];
}
static char*
getquoted(void)
{
int c;
char *t;
Rune r;
c = getnsc();
if(c != '"')
return nil;
t = fmtbuf;
for(;;) {
r = getr();
if(r == ' ' || r == '\n')
return nil;
if(r == '"')
break;
t += runetochar(t, &r);
}
*t = 0;
return strdup(fmtbuf);
}
void
pragvararg(void)
{
Sym *s;
int n, c;
char *t;
Rune r;
Type *ty;
if(!debug['F'])
@ -251,20 +273,9 @@ ckflag:
cktype:
/*#pragma varargck type O int*/
c = getnsc();
if(c != '"')
t = getquoted();
if(t == nil)
goto bad;
t = fmtbuf;
for(;;) {
r = getr();
if(r == ' ' || r == '\n')
goto bad;
if(r == '"')
break;
t += runetochar(t, &r);
}
*t = 0;
t = strdup(fmtbuf);
s = getsym();
if(s == S)
goto bad;
@ -516,3 +527,64 @@ out:
if(debug['f'])
print("%s incomplete\n", s->name);
}
void
pragffi(void)
{
Sym *local, *remote, *type;
char *path;
Ffi *f;
type = getsym();
if(type == nil)
goto err;
local = getsym();
if(local == nil)
goto err;
remote = getsym();
if(remote == nil)
goto err;
path = getquoted();
if(path == nil)
goto err;
if(nffi%32 == 0)
ffi = realloc(ffi, (nffi+32)*sizeof ffi[0]);
f = &ffi[nffi++];
f->type = type->name[0];
f->local = local->name;
f->remote = remote->name;
f->path = path;
goto out;
err:
yyerror("usage: #pragma ffi typechar local remote \"path\"");
out:
while(getnsc() != '\n')
;
}
void
pragpackage(void)
{
Sym *s;
s = getsym();
if(s == nil)
goto err;
package = s->name;
goto out;
err:
yyerror("malformed #pragma package");
out:
while(getnsc() != '\n')
;
}

View File

@ -46,6 +46,20 @@ pragvararg(void)
;
}
void
pragffi(void)
{
while(getnsc() != '\n')
;
}
void
pragpackage(void)
{
while(getnsc() != '\n')
;
}
void
pragfpround(void)
{

View File

@ -283,7 +283,7 @@ macdef(void)
continue;
}
if(ischr){
if(c == '\\'){
if(c == '\\'){
base = allocn(base, len, 1);
base[len++] = c;
c = getc();
@ -400,7 +400,7 @@ macexpand(Sym *s, char *b)
print("#expand %s %s\n", s->name, ob);
return;
}
nargs = (char)(*s->macro & ~VARMAC) - 1;
dots = *s->macro & VARMAC;
@ -737,6 +737,14 @@ macprag(void)
pragincomplete();
return;
}
if(s && strcmp(s->name, "ffi") == 0) {
pragffi();
return;
}
if(s && strcmp(s->name, "package") == 0) {
pragpackage();
return;
}
while(getnsc() != '\n')
;
return;
@ -763,7 +771,7 @@ praglib:
goto bad;
/*
* put pragma-line in as a funny history
* put pragma-line in as a funny history
*/
c = strlen(symb) + 1;
hp = alloc(c);

View File

@ -102,7 +102,7 @@ ldpkg(Biobuf *f, int64 len, char *filename)
while(*p0 == ' ' || *p0 == '\t' || *p0 == '\n')
p0++;
if(strncmp(p0, "package ", 8) != 0) {
fprint(2, "%s: bad package section in %s\n", argv0, filename);
fprint(2, "%s: bad package section in %s - %s\n", argv0, filename, p0);
return;
}
p0 += 8;
@ -199,8 +199,6 @@ again:
return 0;
// prefix: (var|type|func|const)
prefix = p;
prefix = p;
if(p + 6 > ep)
return -1;
@ -251,7 +249,7 @@ again:
goto again;
} else {
err:
fprint(2, "%s: confused in pkg data near <<%.20s>>\n", argv0, prefix);
fprint(2, "%s: confused in pkg data near <<%.40s>>\n", argv0, prefix);
nerrors++;
return -1;
}