]> Cypherpunks repositories - gostls13.git/commitdiff
cc: mode to generate go-code for types and variables.
authorLuuk van Dijk <lvd@golang.org>
Tue, 25 Jan 2011 18:00:14 +0000 (19:00 +0100)
committerLuuk van Dijk <lvd@golang.org>
Tue, 25 Jan 2011 18:00:14 +0000 (19:00 +0100)
R=rsc
CC=golang-dev
https://golang.org/cl/3987045

src/cmd/cc/Makefile
src/cmd/cc/cc.h
src/cmd/cc/dcl.c
src/cmd/cc/godefs.c [new file with mode: 0644]
src/cmd/cc/lex.c

index bbb56659f87ac56a31a629cba5b725d4811dff32..8327d9516ffe7460198f59383cc6f2d109ca04cd 100644 (file)
@@ -20,6 +20,7 @@ OFILES=\
        mac.$O\
        dcl.$O\
        acid.$O\
+       godefs.$O\
        bits.$O\
        com.$O\
        scon.$O\
index d8b57ab5df633d6aa4e9ef32f9a26b260053ac77..8e8f6af4401d2dc42c5eb52bdcd59401bc432b2e 100644 (file)
@@ -743,6 +743,13 @@ void       fatal(Node*, char*, ...);
 void   acidtype(Type*);
 void   acidvar(Sym*);
 
+/*
+ * godefs.c
+ */
+int    Uconv(Fmt*);
+void   godeftype(Type*);
+void   godefvar(Sym*);
+
 /*
  * bits.c
  */
index 4c7245762d63cd298cb8bd801af914a84a929735..d7604b649de8baa6a2ba67ab830e1e5297ccbf60 100644 (file)
@@ -130,6 +130,7 @@ loop:
                if(debug['d'])
                        dbgdecl(s);
                acidvar(s);
+               godefvar(s);
                s->varlineno = lineno;
                break;
        }
@@ -587,6 +588,7 @@ sualign(Type *t)
                t->width = w;
                t->align = maxal;
                acidtype(t);
+               godeftype(t);
                return;
 
        case TUNION:
@@ -609,6 +611,7 @@ sualign(Type *t)
                t->width = w;
                t->align = maxal;
                acidtype(t);
+               godeftype(t);
                return;
 
        default:
@@ -1536,6 +1539,7 @@ doenum(Sym *s, Node *n)
        if(debug['d'])
                dbgdecl(s);
        acidvar(s);
+       godefvar(s);
 }
 
 void
diff --git a/src/cmd/cc/godefs.c b/src/cmd/cc/godefs.c
new file mode 100644 (file)
index 0000000..2b3e36d
--- /dev/null
@@ -0,0 +1,388 @@
+//   cmd/cc/godefs.cc
+//
+//   derived from pickle.cc which itself was derived from acid.cc.
+//
+//     Copyright © 1994-1999 Lucent Technologies Inc. All rights reserved.
+//     Portions Copyright © 1995-1997 C H Forsyth (forsyth@terzarima.net)
+//     Portions Copyright © 1997-1999 Vita Nuova Limited
+//     Portions Copyright © 2000-2007 Vita Nuova Holdings Limited (www.vitanuova.com)
+//     Portions Copyright © 2004,2006 Bruce Ellis
+//     Portions Copyright © 2005-2007 C H Forsyth (forsyth@terzarima.net)
+//     Revisions Copyright © 2000-2007 Lucent Technologies Inc. and others
+//     Portions Copyright © 2009-2011 The Go Authors. All rights reserved.
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy
+// of this software and associated documentation files (the "Software"), to deal
+// in the Software without restriction, including without limitation the rights
+// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the Software is
+// furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in
+// all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+// THE SOFTWARE.
+
+#include "cc.h"
+
+static int upper;
+
+static char *kwd[] =
+{
+       "_bool",
+       "_break",
+       "_byte",
+       "_case",
+       "_chan",
+       "_complex32",
+       "_complex64",
+       "_const",
+       "_continue",
+       "_default",
+       "_defer",
+       "_else",
+       "_fallthrough",
+       "_false",
+       "_float32",
+       "_float64",
+       "_for",
+       "_func",
+       "_go",
+       "_goto",
+       "_if",
+       "_import",
+       "_int",
+       "_int16",
+       "_int32",
+       "_int64",
+       "_int8",
+       "_interface",
+       "_intptr",
+       "_map",
+       "_package",
+       "_range",
+       "_return",
+       "_select",
+       "_string",
+       "_struct",
+       "_switch",
+       "_true",
+       "_type",
+       "_uint",
+       "_uint16",
+       "_uint32",
+       "_uint64",
+       "_uint8",
+       "_uintptr",
+       "_var",
+};
+
+static char*
+pmap(char *s)
+{
+       int i, bot, top, mid;
+       char *n;
+
+       if (!upper) {
+               bot = -1;
+               top = nelem(kwd);
+               while(top - bot > 1){
+                       mid = (bot + top) / 2;
+                       i = strcmp(kwd[mid]+1, s);
+                       if(i == 0)
+                               return kwd[mid];
+
+                       if(i < 0)
+                               bot = mid;
+                       else
+                               top = mid;
+               }
+       }
+
+       // strip package name
+       n = strrchr(s, '.');
+       if(n != nil)
+               s = n + 1;
+
+       return s;
+}
+
+static Sym*
+findsue(Type *t)
+{
+       int h;
+       Sym *s;
+
+       if(t != T)
+       for(h=0; h<nelem(hash); h++)
+               for(s = hash[h]; s != S; s = s->link)
+                       if(s->suetag && s->suetag->link == t)
+                               return s;
+       return 0;
+}
+
+static void
+printtypename(Type *t)
+{
+       Sym *s;
+       Type *t1;
+       int w;
+       char *n;
+
+       for( ; t != nil; t = t->link) {
+               switch(t->etype) {
+               case TIND:
+                       // Special handling of *void.
+                       if(t->link != nil && t->link->etype==TVOID) {
+                               Bprint(&outbuf, "unsafe.Pointer");
+                               return;
+                       }
+                       // *func == func
+                       if(t->link != nil && t->link->etype==TFUNC)
+                               continue;
+                       Bprint(&outbuf, "*");
+                       continue;
+               case TARRAY:
+                       w = t->width;
+                       if(t->link && t->link->width)
+                               w /= t->link->width;
+                       Bprint(&outbuf, "[%d]", w);
+                       continue;
+               }
+               break;
+       }
+
+       if(t == nil) {
+               Bprint(&outbuf, "bad // should not happen");
+               return;
+       }
+
+       switch(t->etype) {
+       case TINT:
+               Bprint(&outbuf, "int");
+               break;
+       case TUINT:
+               Bprint(&outbuf, "uint");
+               break;
+       case TCHAR:
+               Bprint(&outbuf, "int8");
+               break;
+       case TUCHAR:
+               Bprint(&outbuf, "uint8");
+               break;
+       case TSHORT:
+               Bprint(&outbuf, "int16");
+               break;
+       case TUSHORT:
+               Bprint(&outbuf, "uint16");
+               break;
+       case TLONG:
+               Bprint(&outbuf, "int32");
+               break;
+       case TULONG:
+               Bprint(&outbuf, "uint32");
+               break;
+       case TVLONG:
+               Bprint(&outbuf, "int64");
+               break;
+       case TUVLONG:
+               Bprint(&outbuf, "uint64");
+               break;
+       case TFLOAT:
+               Bprint(&outbuf, "float32");
+               break;
+       case TDOUBLE:
+               Bprint(&outbuf, "float64");
+               break;
+       case TUNION:
+       case TSTRUCT:
+               s = findsue(t->link);
+               n = "bad";
+               if(s != S)
+                       n = pmap(s->name);
+               else if(t->tag)
+                       n = t->tag->name;
+               if(strcmp(n, "String") == 0){
+                       n = "string";
+               } else if(strcmp(n, "Slice") == 0){
+                       n = "[]byte";
+               }
+               Bprint(&outbuf, n);
+               break;
+       case TFUNC:
+               Bprint(&outbuf, "func(", t);
+               for(t1 = t->down; t1 != T; t1 = t1->down) {
+                       if(t1->etype == TVOID)
+                               break;
+                       if(t1 != t->down)
+                               Bprint(&outbuf, ", ");
+                       printtypename(t1);
+               }
+               Bprint(&outbuf, ")");
+               if(t->link && t->link->etype != TVOID) {
+                       Bprint(&outbuf, " ");
+                       printtypename(t->link);
+               }
+               break;
+       case TDOT:
+               Bprint(&outbuf, "...interface{}");
+               break;
+       default:
+               Bprint(&outbuf, " weird<%T>", t);
+       }
+}
+
+static int
+dontrun(void)
+{
+       Io *i;
+       int n;
+
+       if(!debug['q'] && !debug['Q'])
+               return 1;
+       if(debug['q'] + debug['Q'] > 1) {
+               n = 0;
+               for(i=iostack; i; i=i->link)
+                       n++;
+               if(n > 1)
+                       return 1;
+       }
+
+       upper = debug['Q'];
+
+       return 0;
+}
+
+int
+Uconv(Fmt *fp)
+{
+       char str[STRINGSZ+1];
+       char *s;
+       int i;
+
+       str[0] = 0;
+       s = va_arg(fp->args, char*);
+       if(s && *s) {
+               if(upper)
+                       str[0] = toupper(*s);
+               else
+                       str[0] = tolower(*s);
+               for(i = 1; i < STRINGSZ && s[i] != 0; i++)
+                       str[i] = tolower(s[i]);
+               str[i] = 0;
+       }
+       return fmtstrcpy(fp, str);
+}
+
+void
+godeftype(Type *t)
+{
+       Sym *s;
+       Type *l;
+       char *an;
+       int gotone;
+
+       if(dontrun())
+               return;
+
+       switch(t->etype) {
+       case TUNION:
+       case TSTRUCT:
+               s = findsue(t->link);
+               if(s == S) {
+                       Bprint(&outbuf, "/* can't find Sue for %T */\n\n", t);
+                       return;
+               }
+               an = pmap(s->name);
+               gotone = 0; // for unions, take first member of size equal to union
+
+               Bprint(&outbuf, "type %U struct {\n", an);
+               for(l = t->link; l != T; l = l->down) {
+                       Bprint(&outbuf, "\t");
+                       if(t->etype == TUNION) {
+                               if(!gotone && l->width == t->width)
+                                       gotone = 1;
+                               else
+                                       Bprint(&outbuf, "// (union)\t");
+                       }
+                       if(l->sym != nil)  // not anonymous field
+                               Bprint(&outbuf, "%U\t", pmap(l->sym->name));
+                       printtypename(l);
+                       Bprint(&outbuf, "\n");
+               }
+               Bprint(&outbuf, "}\n\n");
+               break;
+       default:
+               Bprint(&outbuf, "/* %T */\n\n", t);
+               break;
+       }
+}
+
+void
+godefvar(Sym *s)
+{
+       Type *t, *t1;
+       char n;
+
+       if(dontrun('q'))
+               return;
+
+       t = s->type;
+       if(t == nil)
+               return;
+
+       switch(t->etype) {
+       case TENUM:
+               if(!typefd[t->etype])
+                       Bprint(&outbuf, "const %U = %lld\n", pmap(s->name), s->vconst);
+               else
+                       Bprint(&outbuf, "const %U = %f\n;", pmap(s->name), s->fconst);
+               break;
+
+       case TFUNC:
+               Bprint(&outbuf, "func %U(", pmap(s->name));
+               n = 'a';
+               for(t1 = t->down; t1 != T; t1 = t1->down) {
+                       if(t1->etype == TVOID)
+                               break;
+                       if(t1 != t->down)
+                               Bprint(&outbuf, ", ");
+                       Bprint(&outbuf, "%c ", n++);
+                       printtypename(t1);
+               }
+               Bprint(&outbuf, ")");
+               if(t->link && t->link->etype != TVOID) {
+                       Bprint(&outbuf, " ");
+                       printtypename(t->link);
+               }
+               Bprint(&outbuf, "\n");
+               break;
+
+       default:
+               switch(s->class) {
+               case CTYPEDEF:
+                       if(!typesu[t->etype]) {
+                               Bprint(&outbuf, "// type %U\t", pmap(s->name));
+                               printtypename(t);
+                               Bprint(&outbuf, "\n");
+                       }
+                       break;
+               case CSTATIC:
+               case CEXTERN:
+               case CGLOBL:
+                       if(strchr(s->name, '$') != nil)  // TODO(lvd)
+                           break;
+                       Bprint(&outbuf, "var %U\t", pmap(s->name));
+                       printtypename(t);
+                       Bprint(&outbuf, "\n");
+                       break;
+               }
+               break;
+       }
+}
index 933f8351eb2644efc1b788cad14430471f55f8bf..dba8ff6340b2005894160e5f6d8a24b808a5ab5c 100644 (file)
@@ -59,15 +59,20 @@ pathchar(void)
  *     -d              print declarations
  *     -D name         define
  *     -F              format specification check
+ *     -G              print pgen stuff
+ *     -g              print cgen trees
  *     -i              print initialization
  *     -I path         include
  *     -l              generate little-endian code
  *     -L              print every NAME symbol
  *     -M              constant multiplication
  *     -m              print add/sub/mul trees
- *     -n              print acid to file (%.c=%.acid) (with -a or -aa)
+ *     -n              print acid or godefs to file (%.c=%.acid) (with -a or -aa)
  *     -o file         output file
  *     -p              use standard cpp ANSI preprocessor (not on windows)
+ *     -p              something with peepholes
+ *     -q              print equivalent Go code for variables and types (lower-case identifiers)
+ *     -Q              print equivalent Go code for variables and types (upper-case identifiers)
  *     -r              print registerization
  *     -s              print structure offsets (with -a or -aa)
  *     -S              print assembly
@@ -121,7 +126,7 @@ main(int argc, char *argv[])
                p = ARGF();
                if(p) {
                        if(ndef%8 == 0)
-                               defs = allocn(defs, ndef*sizeof(char *), 
+                               defs = allocn(defs, ndef*sizeof(char *),
                                        8*sizeof(char *));
                        defs[ndef++] = p;
                        dodefine(p);
@@ -147,7 +152,7 @@ main(int argc, char *argv[])
                 * if we're writing acid to standard output, don't compile
                 * concurrently, to avoid interleaving output.
                 */
-               if((!debug['a'] || debug['n']) &&
+               if(((!debug['a'] && !debug['q'] && !debug['Q']) || debug['n']) &&
                    (p = getenv("NPROC")) != nil)
                        nproc = atol(p);        /* */
                c = 0;
@@ -220,6 +225,8 @@ compile(char *file, char **defs, int ndef)
                        p = utfrune(outfile, 0);
                        if(debug['a'] && debug['n'])
                                strcat(p, ".acid");
+                       else if((debug['q'] || debug['Q']) && debug['n'])
+                               strcat(p, ".go");
                        else {
                                p[0] = '.';
                                p[1] = thechar;
@@ -244,7 +251,7 @@ compile(char *file, char **defs, int ndef)
         * if we're writing acid to standard output, don't keep scratching
         * outbuf.
         */
-       if(debug['a'] && !debug['n']) {
+       if((debug['a'] || debug['q'] || debug['Q']) && !debug['n']) {
                if (first) {
                        outfile = 0;
                        Binit(&outbuf, dup(1, -1), OWRITE);
@@ -323,7 +330,7 @@ compile(char *file, char **defs, int ndef)
                        newfile(file, -1);
        }
        yyparse();
-       if(!debug['a'])
+       if(!debug['a'] && !debug['q'] && !debug['Q'])
                gclean();
        return nerrors;
 }
@@ -1307,6 +1314,7 @@ cinit(void)
        fmtinstall('L', Lconv);
        fmtinstall('Q', Qconv);
        fmtinstall('|', VBconv);
+       fmtinstall('U', Uconv);
 }
 
 int
@@ -1552,7 +1560,7 @@ setinclude(char *p)
                                return;
 
                if(ninclude%8 == 0)
-                       include = allocn(include, ninclude*sizeof(char *), 
+                       include = allocn(include, ninclude*sizeof(char *),
                                8*sizeof(char *));
                include[ninclude++] = p;
        }
@@ -1593,7 +1601,7 @@ ensuresymb(int32 n)
        if(symb == nil) {
                symb = alloc(NSYMB+1);
                nsymb = NSYMB;
-       }       
+       }
 
        if(n > nsymb) {
                symb = allocn(symb, nsymb, n+1-nsymb);