summaryrefslogtreecommitdiff
path: root/src/cmd/gc
diff options
context:
space:
mode:
Diffstat (limited to 'src/cmd/gc')
-rw-r--r--src/cmd/gc/bits.c34
-rw-r--r--src/cmd/gc/export.c41
-rw-r--r--src/cmd/gc/go.h19
-rw-r--r--src/cmd/gc/lex.c200
-rw-r--r--src/cmd/gc/obj.c12
-rw-r--r--src/cmd/gc/pgen.c4
-rw-r--r--src/cmd/gc/plive.c19
-rw-r--r--src/cmd/gc/reflect.c14
-rw-r--r--src/cmd/gc/subr.c46
-rw-r--r--src/cmd/gc/walk.c8
10 files changed, 324 insertions, 73 deletions
diff --git a/src/cmd/gc/bits.c b/src/cmd/gc/bits.c
index 2e79f6f1d..fe9a168dc 100644
--- a/src/cmd/gc/bits.c
+++ b/src/cmd/gc/bits.c
@@ -95,11 +95,11 @@ int
bnum(Bits a)
{
int i;
- int32 b;
+ uint64 b;
for(i=0; i<BITS; i++)
if(b = a.b[i])
- return 32*i + bitno(b);
+ return 64*i + bitno(b);
fatal("bad in bnum");
return 0;
}
@@ -110,27 +110,35 @@ blsh(uint n)
Bits c;
c = zbits;
- c.b[n/32] = 1L << (n%32);
+ c.b[n/64] = 1LL << (n%64);
return c;
}
-/*
int
-bset(Bits a, uint n)
+btest(Bits *a, uint n)
{
- if(a.b[n/32] & (1L << (n%32)))
- return 1;
- return 0;
+ return (a->b[n/64] & (1LL << (n%64))) != 0;
+}
+
+void
+biset(Bits *a, uint n)
+{
+ a->b[n/64] |= 1LL << (n%64);
+}
+
+void
+biclr(Bits *a, uint n)
+{
+ a->b[n/64] &= ~(1LL << (n%64));
}
-*/
int
-bitno(int32 b)
+bitno(uint64 b)
{
int i;
- for(i=0; i<32; i++)
- if(b & (1L<<i))
+ for(i=0; i<64; i++)
+ if(b & (1LL<<i))
return i;
fatal("bad in bitno");
return 0;
@@ -157,7 +165,7 @@ Qconv(Fmt *fp)
if(var[i].offset != 0)
fmtprint(fp, "%+lld", (vlong)var[i].offset);
}
- bits.b[i/32] &= ~(1L << (i%32));
+ biclr(&bits, i);
}
return 0;
}
diff --git a/src/cmd/gc/export.c b/src/cmd/gc/export.c
index da5984ceb..aeee55236 100644
--- a/src/cmd/gc/export.c
+++ b/src/cmd/gc/export.c
@@ -7,6 +7,8 @@
#include "go.h"
#include "y.tab.h"
+static NodeList *asmlist;
+
static void dumpexporttype(Type *t);
// Mark n's symbol as exported
@@ -68,6 +70,11 @@ autoexport(Node *n, int ctxt)
// -A is for cmd/gc/mkbuiltin script, so export everything
if(debug['A'] || exportname(n->sym->name) || initname(n->sym->name))
exportsym(n);
+ if(asmhdr && n->sym->pkg == localpkg && !(n->sym->flags & SymAsm)) {
+ n->sym->flags |= SymAsm;
+ asmlist = list(asmlist, n);
+ }
+
}
static void
@@ -519,3 +526,37 @@ importtype(Type *pt, Type *t)
if(debug['E'])
print("import type %T %lT\n", pt, t);
}
+
+void
+dumpasmhdr(void)
+{
+ Biobuf *b;
+ NodeList *l;
+ Node *n;
+ Type *t;
+
+ b = Bopen(asmhdr, OWRITE);
+ if(b == nil)
+ fatal("open %s: %r", asmhdr);
+ Bprint(b, "// generated by %cg -asmhdr from package %s\n\n", thechar, localpkg->name);
+ for(l=asmlist; l; l=l->next) {
+ n = l->n;
+ if(isblanksym(n->sym))
+ continue;
+ switch(n->op) {
+ case OLITERAL:
+ Bprint(b, "#define const_%s %#V\n", n->sym->name, &n->val);
+ break;
+ case OTYPE:
+ t = n->type;
+ if(t->etype != TSTRUCT || t->map != T || t->funarg)
+ break;
+ for(t=t->type; t != T; t=t->down)
+ if(!isblanksym(t->sym))
+ Bprint(b, "#define %s_%s %d\n", n->sym->name, t->sym->name, (int)t->width);
+ break;
+ }
+ }
+
+ Bterm(b);
+}
diff --git a/src/cmd/gc/go.h b/src/cmd/gc/go.h
index 965a0550d..6e326961d 100644
--- a/src/cmd/gc/go.h
+++ b/src/cmd/gc/go.h
@@ -382,6 +382,7 @@ enum
SymExported = 1<<2, // already written out by export
SymUniq = 1<<3,
SymSiggen = 1<<4,
+ SymAsm = 1<<5,
};
struct Sym
@@ -393,6 +394,7 @@ struct Sym
int32 npkg; // number of imported packages with this name
uint32 uniqgen;
Pkg* importdef; // where imported definition was found
+ char* linkname; // link name
// saved and restored by dcopy
Pkg* pkg;
@@ -704,13 +706,13 @@ enum
Ecomplit = 1<<11, // type in composite literal
};
-#define BITS 5
-#define NVAR (BITS*sizeof(uint32)*8)
+#define BITS 3
+#define NVAR (BITS*sizeof(uint64)*8)
typedef struct Bits Bits;
struct Bits
{
- uint32 b[BITS];
+ uint64 b[BITS];
};
EXTERN Bits zbits;
@@ -860,6 +862,8 @@ EXTERN int32 lexlineno;
EXTERN int32 lineno;
EXTERN int32 prevlineno;
+EXTERN Fmt pragcgobuf;
+
EXTERN char* infile;
EXTERN char* outfile;
EXTERN Biobuf* bout;
@@ -890,6 +894,7 @@ EXTERN Pkg* typelinkpkg; // fake package for runtime type info (data)
EXTERN Pkg* weaktypepkg; // weak references to runtime type info
EXTERN Pkg* unsafepkg; // package unsafe
EXTERN Pkg* trackpkg; // fake package for field tracking
+EXTERN Pkg* rawpkg; // fake package for raw symbol names
EXTERN Pkg* phash[128];
EXTERN int tptr; // either TPTR32 or TPTR64
extern char* runtimeimport;
@@ -897,6 +902,7 @@ extern char* unsafeimport;
EXTERN char* myimportpath;
EXTERN Idir* idirs;
EXTERN char* localimport;
+EXTERN char* asmhdr;
EXTERN Type* types[NTYPE];
EXTERN Type* idealstring;
@@ -1027,12 +1033,14 @@ int Qconv(Fmt *fp);
Bits band(Bits a, Bits b);
int bany(Bits *a);
int beq(Bits a, Bits b);
-int bitno(int32 b);
+int bitno(uint64 b);
Bits blsh(uint n);
Bits bnot(Bits a);
int bnum(Bits a);
Bits bor(Bits a, Bits b);
-int bset(Bits a, uint n);
+int btest(Bits *a, uint n);
+void biset(Bits *a, uint n);
+void biclr(Bits *a, uint n);
/*
* bv.c
@@ -1145,6 +1153,7 @@ void escapes(NodeList*);
*/
void autoexport(Node *n, int ctxt);
void dumpexport(void);
+void dumpasmhdr(void);
int exportname(char *s);
void exportsym(Node *n);
void importconst(Sym *s, Type *t, Node *n);
diff --git a/src/cmd/gc/lex.c b/src/cmd/gc/lex.c
index 523ba37aa..2bd7adfb6 100644
--- a/src/cmd/gc/lex.c
+++ b/src/cmd/gc/lex.c
@@ -17,6 +17,8 @@ extern int yychar;
int yyprev;
int yylast;
+static int imported_unsafe;
+
static void lexinit(void);
static void lexinit1(void);
static void lexfini(void);
@@ -271,6 +273,9 @@ main(int argc, char *argv[])
flag_largemodel = 1;
setexp();
+
+ fmtstrinit(&pragcgobuf);
+ quotefmtinstall();
outfile = nil;
flagcount("+", "compiling runtime", &compiling_runtime);
@@ -289,6 +294,7 @@ main(int argc, char *argv[])
flagcount("S", "print assembly listing", &debug['S']);
flagfn0("V", "print compiler version", doversion);
flagcount("W", "debug parse tree after type checking", &debug['W']);
+ flagstr("asmhdr", "file: write assembly header to named file", &asmhdr);
flagcount("complete", "compiling complete package (no C or assembly)", &pure_go);
flagstr("d", "list: print debug information about items in list", &debugstr);
flagcount("e", "no limit on number of errors reported", &debug['e']);
@@ -403,6 +409,8 @@ main(int argc, char *argv[])
block = 1;
iota = -1000000;
+
+ imported_unsafe = 0;
yyparse();
if(nsyntaxerrors != 0)
@@ -509,6 +517,9 @@ main(int argc, char *argv[])
errorexit();
dumpobj();
+
+ if(asmhdr)
+ dumpasmhdr();
if(nerrors+nsavederrors)
errorexit();
@@ -724,6 +735,7 @@ importfile(Val *f, int line)
}
importpkg = mkpkg(f->u.sval);
cannedimports("unsafe.6", unsafeimport);
+ imported_unsafe = 1;
return;
}
@@ -1501,6 +1513,20 @@ caseout:
return LLITERAL;
}
+static void pragcgo(char*);
+
+static int
+more(char **pp)
+{
+ char *p;
+
+ p = *pp;
+ while(yy_isspace(*p))
+ p++;
+ *pp = p;
+ return *p != '\0';
+}
+
/*
* read and interpret syntax that looks like
* //line parse.y:15
@@ -1583,9 +1609,39 @@ go:
*cp++ = c;
}
*cp = 0;
+
+ if(strncmp(lexbuf, "go:cgo_", 7) == 0)
+ pragcgo(lexbuf);
+
ep = strchr(lexbuf, ' ');
if(ep != nil)
*ep = 0;
+
+ if(strcmp(lexbuf, "go:linkname") == 0) {
+ if(!imported_unsafe)
+ yyerror("//go:linkname only allowed in Go files that import \"unsafe\"");
+ if(ep == nil) {
+ yyerror("usage: //go:linkname localname linkname");
+ goto out;
+ }
+ cp = ep+1;
+ while(yy_isspace(*cp))
+ cp++;
+ ep = strchr(cp, ' ');
+ if(ep == nil) {
+ yyerror("usage: //go:linkname localname linkname");
+ goto out;
+ }
+ *ep++ = 0;
+ while(yy_isspace(*ep))
+ ep++;
+ if(*ep == 0) {
+ yyerror("usage: //go:linkname localname linkname");
+ goto out;
+ }
+ lookup(cp)->linkname = strdup(ep);
+ goto out;
+ }
if(strcmp(lexbuf, "go:nointerface") == 0 && fieldtrack_enabled) {
nointerface = 1;
@@ -1604,6 +1660,150 @@ out:
return c;
}
+static char*
+getimpsym(char **pp)
+{
+ char *p, *start;
+
+ more(pp); // skip spaces
+
+ p = *pp;
+ if(*p == '\0' || *p == '"')
+ return nil;
+
+ start = p;
+ while(*p != '\0' && !yy_isspace(*p) && *p != '"')
+ p++;
+ if(*p != '\0')
+ *p++ = '\0';
+
+ *pp = p;
+ return start;
+}
+
+static char*
+getquoted(char **pp)
+{
+ char *p, *start;
+
+ more(pp); // skip spaces
+
+ p = *pp;
+ if(*p != '"')
+ return nil;
+ p++;
+
+ start = p;
+ while(*p != '"') {
+ if(*p == '\0')
+ return nil;
+ p++;
+ }
+ *p++ = '\0';
+ *pp = p;
+ return start;
+}
+
+// Copied nearly verbatim from the C compiler's #pragma parser.
+// TODO: Rewrite more cleanly once the compiler is written in Go.
+static void
+pragcgo(char *text)
+{
+ char *local, *remote, *p, *q, *verb;
+
+ for(q=text; *q != '\0' && *q != ' '; q++)
+ ;
+ if(*q == ' ')
+ *q++ = '\0';
+
+ verb = text+3; // skip "go:"
+
+ if(strcmp(verb, "cgo_dynamic_linker") == 0 || strcmp(verb, "dynlinker") == 0) {
+ p = getquoted(&q);
+ if(p == nil)
+ goto err1;
+ fmtprint(&pragcgobuf, "cgo_dynamic_linker %q\n", p);
+ goto out;
+
+ err1:
+ yyerror("usage: //go:cgo_dynamic_linker \"path\"");
+ goto out;
+ }
+
+ if(strcmp(verb, "dynexport") == 0)
+ verb = "cgo_export_dynamic";
+ if(strcmp(verb, "cgo_export_static") == 0 || strcmp(verb, "cgo_export_dynamic") == 0) {
+ local = getimpsym(&q);
+ if(local == nil)
+ goto err2;
+ if(!more(&q)) {
+ fmtprint(&pragcgobuf, "%s %q\n", verb, local);
+ goto out;
+ }
+ remote = getimpsym(&q);
+ if(remote == nil)
+ goto err2;
+ fmtprint(&pragcgobuf, "%s %q %q\n", verb, local, remote);
+ goto out;
+
+ err2:
+ yyerror("usage: //go:%s local [remote]", verb);
+ goto out;
+ }
+
+ if(strcmp(verb, "cgo_import_dynamic") == 0 || strcmp(verb, "dynimport") == 0) {
+ local = getimpsym(&q);
+ if(local == nil)
+ goto err3;
+ if(!more(&q)) {
+ fmtprint(&pragcgobuf, "cgo_import_dynamic %q\n", local);
+ goto out;
+ }
+ remote = getimpsym(&q);
+ if(remote == nil)
+ goto err3;
+ if(!more(&q)) {
+ fmtprint(&pragcgobuf, "cgo_import_dynamic %q %q\n", local, remote);
+ goto out;
+ }
+ p = getquoted(&q);
+ if(p == nil)
+ goto err3;
+ fmtprint(&pragcgobuf, "cgo_import_dynamic %q %q %q\n", local, remote, p);
+ goto out;
+
+ err3:
+ yyerror("usage: //go:cgo_import_dynamic local [remote [\"library\"]]");
+ goto out;
+ }
+
+ if(strcmp(verb, "cgo_import_static") == 0) {
+ local = getimpsym(&q);
+ if(local == nil || more(&q))
+ goto err4;
+ fmtprint(&pragcgobuf, "cgo_import_static %q\n", local);
+ goto out;
+
+ err4:
+ yyerror("usage: //go:cgo_import_static local");
+ goto out;
+ }
+
+ if(strcmp(verb, "cgo_ldflag") == 0) {
+ p = getquoted(&q);
+ if(p == nil)
+ goto err5;
+ fmtprint(&pragcgobuf, "cgo_ldflag %q\n", p);
+ goto out;
+
+ err5:
+ yyerror("usage: //go:cgo_ldflag \"arg\"");
+ goto out;
+ }
+
+out:;
+}
+
int32
yylex(void)
{
diff --git a/src/cmd/gc/obj.c b/src/cmd/gc/obj.c
index b752a13ce..7e4e97854 100644
--- a/src/cmd/gc/obj.c
+++ b/src/cmd/gc/obj.c
@@ -67,6 +67,16 @@ dumpobj(void)
startobj = Boffset(bout);
Bprint(bout, "go object %s %s %s %s\n", getgoos(), getgoarch(), getgoversion(), expstring());
}
+
+ if(pragcgobuf.to > pragcgobuf.start) {
+ if(writearchive) {
+ // write empty export section; must be before cgo section
+ Bprint(bout, "\n$$\n\n$$\n\n");
+ }
+ Bprint(bout, "\n$$ // cgo\n");
+ Bprint(bout, "%s\n$$\n\n", fmtstrflush(&pragcgobuf));
+ }
+
Bprint(bout, "\n!\n");
@@ -153,6 +163,8 @@ linksym(Sym *s)
return s->lsym;
if(isblanksym(s))
s->lsym = linklookup(ctxt, "_", 0);
+ else if(s->linkname != nil)
+ s->lsym = linklookup(ctxt, s->linkname, 0);
else {
p = smprint("%s.%s", s->pkg->prefix, s->name);
s->lsym = linklookup(ctxt, p, 0);
diff --git a/src/cmd/gc/pgen.c b/src/cmd/gc/pgen.c
index 39028e3f8..259cec85a 100644
--- a/src/cmd/gc/pgen.c
+++ b/src/cmd/gc/pgen.c
@@ -471,7 +471,7 @@ allocauto(Prog* ptxt)
stksize = rnd(stksize, n->type->align);
if(haspointers(n->type))
stkptrsize = stksize;
- if(thechar == '5')
+ if(thechar == '5' || thechar == '9')
stksize = rnd(stksize, widthptr);
if(stksize >= (1ULL<<31)) {
setlineno(curfn);
@@ -528,7 +528,7 @@ cgen_checknil(Node *n)
dump("checknil", n);
fatal("bad checknil");
}
- if((thechar == '5' && n->op != OREGISTER) || !n->addable || n->op == OLITERAL) {
+ if(((thechar == '5' || thechar == '9') && n->op != OREGISTER) || !n->addable || n->op == OLITERAL) {
regalloc(&reg, types[tptr], n);
cgen(n, &reg);
gins(ACHECKNIL, &reg, N);
diff --git a/src/cmd/gc/plive.c b/src/cmd/gc/plive.c
index 0feb2c710..3bfa69b1f 100644
--- a/src/cmd/gc/plive.c
+++ b/src/cmd/gc/plive.c
@@ -1092,7 +1092,7 @@ twobitwalktype1(Type *t, vlong *xoffset, Bvec *bv)
case TCOMPLEX64:
case TCOMPLEX128:
for(i = 0; i < t->width; i++) {
- bvset(bv, ((*xoffset + i) / widthptr) * BitsPerPointer); // 1 = live scalar
+ bvset(bv, ((*xoffset + i) / widthptr) * BitsPerPointer); // 1 = live scalar (BitsScalar)
}
*xoffset += t->width;
break;
@@ -1105,7 +1105,7 @@ twobitwalktype1(Type *t, vlong *xoffset, Bvec *bv)
case TMAP:
if((*xoffset & (widthptr-1)) != 0)
fatal("twobitwalktype1: invalid alignment, %T", t);
- bvset(bv, (*xoffset / widthptr) * BitsPerPointer + 1); // 2 = live ptr
+ bvset(bv, (*xoffset / widthptr) * BitsPerPointer + 1); // 2 = live ptr (BitsPointer)
*xoffset += t->width;
break;
@@ -1113,7 +1113,7 @@ twobitwalktype1(Type *t, vlong *xoffset, Bvec *bv)
// struct { byte *str; intgo len; }
if((*xoffset & (widthptr-1)) != 0)
fatal("twobitwalktype1: invalid alignment, %T", t);
- bvset(bv, (*xoffset / widthptr) * BitsPerPointer + 1); // 2 = live ptr in first slot
+ bvset(bv, (*xoffset / widthptr) * BitsPerPointer + 1); // 2 = live ptr in first slot (BitsPointer)
*xoffset += t->width;
break;
@@ -1123,15 +1123,8 @@ twobitwalktype1(Type *t, vlong *xoffset, Bvec *bv)
// struct { Type *type; union { void *ptr, uintptr val } data; }
if((*xoffset & (widthptr-1)) != 0)
fatal("twobitwalktype1: invalid alignment, %T", t);
- bvset(bv, ((*xoffset / widthptr) * BitsPerPointer) + 0);
- bvset(bv, ((*xoffset / widthptr) * BitsPerPointer) + 1); // 3 = multiword
- // next word contains 2 = Iface, 3 = Eface
- if(isnilinter(t)) {
- bvset(bv, ((*xoffset / widthptr) * BitsPerPointer) + 2);
- bvset(bv, ((*xoffset / widthptr) * BitsPerPointer) + 3);
- } else {
- bvset(bv, ((*xoffset / widthptr) * BitsPerPointer) + 3);
- }
+ bvset(bv, (*xoffset / widthptr) * BitsPerPointer + 1); // 2 = live ptr in first slot (BitsPointer)
+ bvset(bv, (*xoffset / widthptr) * BitsPerPointer + 3); // 2 = live ptr in second slot (BitsPointer)
*xoffset += t->width;
break;
@@ -1144,7 +1137,7 @@ twobitwalktype1(Type *t, vlong *xoffset, Bvec *bv)
// struct { byte *array; uintgo len; uintgo cap; }
if((*xoffset & (widthptr-1)) != 0)
fatal("twobitwalktype1: invalid TARRAY alignment, %T", t);
- bvset(bv, (*xoffset / widthptr) * BitsPerPointer + 1); // 2 = live ptr in first slot
+ bvset(bv, (*xoffset / widthptr) * BitsPerPointer + 1); // 2 = live ptr in first slot (BitsPointer)
*xoffset += t->width;
} else
for(i = 0; i < t->bound; i++)
diff --git a/src/cmd/gc/reflect.c b/src/cmd/gc/reflect.c
index b2ff2fbc5..4155953be 100644
--- a/src/cmd/gc/reflect.c
+++ b/src/cmd/gc/reflect.c
@@ -1318,7 +1318,7 @@ gengcmask(Type *t, uint8 gcmask[16])
{
Bvec *vec;
vlong xoffset, nptr, i, j;
- int half, mw;
+ int half;
uint8 bits, *pos;
memset(gcmask, 0, 16);
@@ -1335,7 +1335,6 @@ gengcmask(Type *t, uint8 gcmask[16])
pos = (uint8*)gcmask;
nptr = (t->width+widthptr-1)/widthptr;
half = 0;
- mw = 0;
// If number of words is odd, repeat the mask.
// This makes simpler handling of arrays in runtime.
for(j=0; j<=(nptr%2); j++) {
@@ -1344,9 +1343,8 @@ gengcmask(Type *t, uint8 gcmask[16])
// Some fake types (e.g. Hmap) has missing fileds.
// twobitwalktype1 generates BitsDead for that holes,
// replace BitsDead with BitsScalar.
- if(!mw && bits == BitsDead)
+ if(bits == BitsDead)
bits = BitsScalar;
- mw = !mw && bits == BitsMultiWord;
bits <<= 2;
if(half)
bits <<= 4;
@@ -1525,11 +1523,9 @@ gengcprog1(ProgGen *g, Type *t, vlong *xoffset)
*xoffset += t->width;
break;
case TINTER:
- proggendata(g, BitsMultiWord);
- if(isnilinter(t))
- proggendata(g, BitsEface);
- else
- proggendata(g, BitsIface);
+ // Assuming IfacePointerOnly=1.
+ proggendata(g, BitsPointer);
+ proggendata(g, BitsPointer);
*xoffset += t->width;
break;
case TARRAY:
diff --git a/src/cmd/gc/subr.c b/src/cmd/gc/subr.c
index c3bc5af3b..5e369b695 100644
--- a/src/cmd/gc/subr.c
+++ b/src/cmd/gc/subr.c
@@ -3802,39 +3802,25 @@ checknil(Node *x, NodeList **init)
/*
* Can this type be stored directly in an interface word?
+ * Yes, if the representation is a single pointer.
*/
int
isdirectiface(Type *t)
{
- // Setting IfacePointerOnly = 1 changes the
- // interface representation so that the data word
- // in an interface value must always be a pointer.
- // Setting it to 0 uses the original representation,
- // where the data word can hold a pointer or any
- // non-pointer value no bigger than a pointer.
- enum {
- IfacePointerOnly = 1,
- };
-
- if(IfacePointerOnly) {
- switch(t->etype) {
- case TPTR32:
- case TPTR64:
- case TCHAN:
- case TMAP:
- case TFUNC:
- case TUNSAFEPTR:
- return 1;
- case TARRAY:
- // Array of 1 direct iface type can be direct.
- return t->bound == 1 && isdirectiface(t->type);
- case TSTRUCT:
- // Struct with 1 field of direct iface type can be direct.
- return t->type != T && t->type->down == T && isdirectiface(t->type->type);
- }
- return 0;
+ switch(t->etype) {
+ case TPTR32:
+ case TPTR64:
+ case TCHAN:
+ case TMAP:
+ case TFUNC:
+ case TUNSAFEPTR:
+ return 1;
+ case TARRAY:
+ // Array of 1 direct iface type can be direct.
+ return t->bound == 1 && isdirectiface(t->type);
+ case TSTRUCT:
+ // Struct with 1 field of direct iface type can be direct.
+ return t->type != T && t->type->down == T && isdirectiface(t->type->type);
}
-
- dowidth(t);
- return t->width <= widthptr;
+ return 0;
}
diff --git a/src/cmd/gc/walk.c b/src/cmd/gc/walk.c
index ff9b36208..77f9c80f9 100644
--- a/src/cmd/gc/walk.c
+++ b/src/cmd/gc/walk.c
@@ -1766,7 +1766,6 @@ walkprint(Node *nn, NodeList **init)
int notfirst, et, op;
NodeList *calls;
- on = nil;
op = nn->op;
all = nn->list;
calls = nil;
@@ -3301,6 +3300,9 @@ walkrotate(Node **np)
int w, sl, sr, s;
Node *l, *r;
Node *n;
+
+ if(thechar == '9')
+ return;
n = *np;
@@ -3426,6 +3428,10 @@ walkdiv(Node **np, NodeList **init)
Type *twide;
Magic m;
+ // TODO(minux)
+ if(thechar == '9')
+ return;
+
n = *np;
if(n->right->op != OLITERAL)
return;