]> Cypherpunks repositories - gostls13.git/commitdiff
first attempt at real FFI support.
authorRuss Cox <rsc@golang.org>
Mon, 24 Aug 2009 23:15:21 +0000 (16:15 -0700)
committerRuss Cox <rsc@golang.org>
Mon, 24 Aug 2009 23:15:21 +0000 (16:15 -0700)
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

src/cmd/6c/swt.c
src/cmd/ar/ar.c
src/cmd/cc/cc.h
src/cmd/cc/dpchk.c
src/cmd/cc/lexbody
src/cmd/cc/macbody
src/cmd/ld/go.c

index b3f31b04d4830097ef31c2c72d86b9260b3a93b8..9b2381ae934718489b05555479a54cc3d3dac069 100644 (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);
index 77176b13ada9840f21c884fa2a28424cf49cdf40..83ab51c2e37fcde9e1bef110436db5d3615e0c8d 100644 (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;
index 2ebea6f5f65c1705bcfbd7f024b6e32150618cbc..9964681f11850880e64d5b1c9f44154de36b17f1 100644 (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
index 9d22e621eda609805e8973eaf1c3bc3c59aafa9e..b1e988b87ae9aeeedcb5b15d1630ef609f9467ba 100644 (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')
+               ;
+}
+
index 33734c7224eafac1c649760c18744ac879556e2c..1c979a0f1a9e600c3cb6c5563f36c57f08bf0d0a 100644 (file)
@@ -46,6 +46,20 @@ pragvararg(void)
                ;
 }
 
+void
+pragffi(void)
+{
+       while(getnsc() != '\n')
+               ;
+}
+
+void
+pragpackage(void)
+{
+       while(getnsc() != '\n')
+               ;
+}
+
 void
 pragfpround(void)
 {
index 64f04129f411e7e2bb467c10b673ff85a3621e17..09ecccf5d2556b7e93b3f9acdbfe17f4d49f7e59 100644 (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);
index 4bad524133f6a1ab9c87d9b6f866a313eb55764f..b4b75b19b0ef37437c5ece0458741fd6667e7eff 100644 (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;
        }