]> Cypherpunks repositories - gostls13.git/commitdiff
[dev.cc] cmd/6a, cmd/6g etc: replace C implementations with Go implementations
authorRuss Cox <rsc@golang.org>
Mon, 23 Feb 2015 19:20:01 +0000 (14:20 -0500)
committerRuss Cox <rsc@golang.org>
Mon, 23 Feb 2015 19:56:40 +0000 (19:56 +0000)
Change-Id: I58e00a39cf63df07813d21453f91e68eef6a413c
Reviewed-on: https://go-review.googlesource.com/5635
Reviewed-by: Rob Pike <r@golang.org>
175 files changed:
src/cmd/5a/Makefile [deleted file]
src/cmd/5a/a.h [deleted file]
src/cmd/5a/a.y
src/cmd/5a/doc.go [deleted file]
src/cmd/5a/lex.c [deleted file]
src/cmd/5a/lex.go [moved from src/cmd/new5a/lex.go with 100% similarity]
src/cmd/5a/y.go [moved from src/cmd/new5a/y.go with 100% similarity]
src/cmd/5a/y.tab.c [deleted file]
src/cmd/5a/y.tab.h [deleted file]
src/cmd/5g/Makefile [deleted file]
src/cmd/5g/cgen.c [deleted file]
src/cmd/5g/cgen.go [moved from src/cmd/new5g/cgen.go with 100% similarity]
src/cmd/5g/cgen64.c [deleted file]
src/cmd/5g/cgen64.go [moved from src/cmd/new5g/cgen64.go with 100% similarity]
src/cmd/5g/doc.go [deleted file]
src/cmd/5g/galign.c [deleted file]
src/cmd/5g/galign.go [moved from src/cmd/new5g/galign.go with 100% similarity]
src/cmd/5g/gg.go [moved from src/cmd/new5g/gg.go with 100% similarity]
src/cmd/5g/gg.h [deleted file]
src/cmd/5g/ggen.c [deleted file]
src/cmd/5g/ggen.go [moved from src/cmd/new5g/ggen.go with 100% similarity]
src/cmd/5g/gsubr.c [deleted file]
src/cmd/5g/gsubr.go [moved from src/cmd/new5g/gsubr.go with 100% similarity]
src/cmd/5g/peep.c [deleted file]
src/cmd/5g/peep.go [moved from src/cmd/new5g/peep.go with 100% similarity]
src/cmd/5g/prog.c [deleted file]
src/cmd/5g/prog.go [moved from src/cmd/new5g/prog.go with 100% similarity]
src/cmd/5g/reg.c [deleted file]
src/cmd/5g/reg.go [moved from src/cmd/new5g/reg.go with 100% similarity]
src/cmd/5g/util.go [moved from src/cmd/new5g/util.go with 100% similarity]
src/cmd/6a/Makefile [deleted file]
src/cmd/6a/a.h [deleted file]
src/cmd/6a/a.y
src/cmd/6a/doc.go [deleted file]
src/cmd/6a/lex.c [deleted file]
src/cmd/6a/lex.go [moved from src/cmd/new6a/lex.go with 100% similarity]
src/cmd/6a/y.go [moved from src/cmd/new6a/y.go with 100% similarity]
src/cmd/6a/y.tab.c [deleted file]
src/cmd/6a/y.tab.h [deleted file]
src/cmd/6g/Makefile [deleted file]
src/cmd/6g/cgen.c [deleted file]
src/cmd/6g/cgen.go [moved from src/cmd/new6g/cgen.go with 100% similarity]
src/cmd/6g/doc.go [deleted file]
src/cmd/6g/galign.c [deleted file]
src/cmd/6g/galign.go [moved from src/cmd/new6g/galign.go with 100% similarity]
src/cmd/6g/gg.go [moved from src/cmd/new6g/gg.go with 100% similarity]
src/cmd/6g/gg.h [deleted file]
src/cmd/6g/ggen.c [deleted file]
src/cmd/6g/ggen.go [moved from src/cmd/new6g/ggen.go with 100% similarity]
src/cmd/6g/gsubr.c [deleted file]
src/cmd/6g/gsubr.go [moved from src/cmd/new6g/gsubr.go with 100% similarity]
src/cmd/6g/peep.c [deleted file]
src/cmd/6g/peep.go [moved from src/cmd/new6g/peep.go with 100% similarity]
src/cmd/6g/prog.c [deleted file]
src/cmd/6g/prog.go [moved from src/cmd/new6g/prog.go with 100% similarity]
src/cmd/6g/reg.c [deleted file]
src/cmd/6g/reg.go [moved from src/cmd/new6g/reg.go with 100% similarity]
src/cmd/6g/util.go [moved from src/cmd/new6g/util.go with 100% similarity]
src/cmd/8a/Makefile [deleted file]
src/cmd/8a/a.h [deleted file]
src/cmd/8a/a.y
src/cmd/8a/doc.go [deleted file]
src/cmd/8a/lex.c [deleted file]
src/cmd/8a/lex.go [moved from src/cmd/new8a/lex.go with 100% similarity]
src/cmd/8a/y.go [moved from src/cmd/new8a/y.go with 100% similarity]
src/cmd/8a/y.tab.c [deleted file]
src/cmd/8a/y.tab.h [deleted file]
src/cmd/8g/Makefile [deleted file]
src/cmd/8g/cgen.c [deleted file]
src/cmd/8g/cgen.go [moved from src/cmd/new8g/cgen.go with 100% similarity]
src/cmd/8g/cgen64.c [deleted file]
src/cmd/8g/cgen64.go [moved from src/cmd/new8g/cgen64.go with 100% similarity]
src/cmd/8g/doc.go [deleted file]
src/cmd/8g/galign.c [deleted file]
src/cmd/8g/galign.go [moved from src/cmd/new8g/galign.go with 100% similarity]
src/cmd/8g/gg.go [moved from src/cmd/new8g/gg.go with 100% similarity]
src/cmd/8g/gg.h [deleted file]
src/cmd/8g/ggen.c [deleted file]
src/cmd/8g/ggen.go [moved from src/cmd/new8g/ggen.go with 100% similarity]
src/cmd/8g/gsubr.c [deleted file]
src/cmd/8g/gsubr.go [moved from src/cmd/new8g/gsubr.go with 100% similarity]
src/cmd/8g/peep.c [deleted file]
src/cmd/8g/peep.go [moved from src/cmd/new8g/peep.go with 100% similarity]
src/cmd/8g/prog.c [deleted file]
src/cmd/8g/prog.go [moved from src/cmd/new8g/prog.go with 100% similarity]
src/cmd/8g/reg.c [deleted file]
src/cmd/8g/reg.go [moved from src/cmd/new8g/reg.go with 100% similarity]
src/cmd/8g/util.go [moved from src/cmd/new8g/util.go with 100% similarity]
src/cmd/9a/Makefile [deleted file]
src/cmd/9a/a.h [deleted file]
src/cmd/9a/a.y
src/cmd/9a/doc.go [deleted file]
src/cmd/9a/lex.c [deleted file]
src/cmd/9a/lex.go [moved from src/cmd/new9a/lex.go with 100% similarity]
src/cmd/9a/y.go [moved from src/cmd/new9a/y.go with 100% similarity]
src/cmd/9a/y.tab.c [deleted file]
src/cmd/9a/y.tab.h [deleted file]
src/cmd/9g/cgen.c [deleted file]
src/cmd/9g/cgen.go [moved from src/cmd/new9g/cgen.go with 100% similarity]
src/cmd/9g/doc.go [deleted file]
src/cmd/9g/galign.c [deleted file]
src/cmd/9g/galign.go [moved from src/cmd/new9g/galign.go with 100% similarity]
src/cmd/9g/gg.go [moved from src/cmd/new9g/gg.go with 100% similarity]
src/cmd/9g/gg.h [deleted file]
src/cmd/9g/ggen.c [deleted file]
src/cmd/9g/ggen.go [moved from src/cmd/new9g/ggen.go with 100% similarity]
src/cmd/9g/gsubr.c [deleted file]
src/cmd/9g/gsubr.go [moved from src/cmd/new9g/gsubr.go with 100% similarity]
src/cmd/9g/opt.go [moved from src/cmd/new9g/opt.go with 100% similarity]
src/cmd/9g/opt.h [deleted file]
src/cmd/9g/peep.c [deleted file]
src/cmd/9g/peep.go [moved from src/cmd/new9g/peep.go with 100% similarity]
src/cmd/9g/prog.c [deleted file]
src/cmd/9g/prog.go [moved from src/cmd/new9g/prog.go with 100% similarity]
src/cmd/9g/reg.c [deleted file]
src/cmd/9g/reg.go [moved from src/cmd/new9g/reg.go with 100% similarity]
src/cmd/9g/util.go [moved from src/cmd/new9g/util.go with 100% similarity]
src/cmd/gc/Makefile [deleted file]
src/cmd/gc/align.c [deleted file]
src/cmd/gc/array.c [deleted file]
src/cmd/gc/bisonerrors [deleted file]
src/cmd/gc/bits.c [deleted file]
src/cmd/gc/builtin.c [deleted file]
src/cmd/gc/bv.c [deleted file]
src/cmd/gc/closure.c [deleted file]
src/cmd/gc/const.c [deleted file]
src/cmd/gc/cplx.c [deleted file]
src/cmd/gc/dcl.c [deleted file]
src/cmd/gc/doc.go [deleted file]
src/cmd/gc/esc.c [deleted file]
src/cmd/gc/export.c [deleted file]
src/cmd/gc/fmt.c [deleted file]
src/cmd/gc/gen.c [deleted file]
src/cmd/gc/go.errors [deleted file]
src/cmd/gc/go.h [deleted file]
src/cmd/gc/go.y [deleted file]
src/cmd/gc/gsubr.c [deleted file]
src/cmd/gc/init.c [deleted file]
src/cmd/gc/inl.c [deleted file]
src/cmd/gc/lex.c [deleted file]
src/cmd/gc/md5.c [deleted file]
src/cmd/gc/md5.h [deleted file]
src/cmd/gc/mkbuiltin [deleted file]
src/cmd/gc/mkbuiltin1.c [deleted file]
src/cmd/gc/mkopnames [deleted file]
src/cmd/gc/mparith1.c [deleted file]
src/cmd/gc/mparith2.c [deleted file]
src/cmd/gc/mparith3.c [deleted file]
src/cmd/gc/obj.c [deleted file]
src/cmd/gc/order.c [deleted file]
src/cmd/gc/pgen.c [deleted file]
src/cmd/gc/plive.c [deleted file]
src/cmd/gc/popt.c [deleted file]
src/cmd/gc/popt.h [deleted file]
src/cmd/gc/racewalk.c [deleted file]
src/cmd/gc/range.c [deleted file]
src/cmd/gc/reflect.c [deleted file]
src/cmd/gc/reg.c [deleted file]
src/cmd/gc/runtime.go [deleted file]
src/cmd/gc/select.c [deleted file]
src/cmd/gc/sinit.c [deleted file]
src/cmd/gc/subr.c [deleted file]
src/cmd/gc/swt.c [deleted file]
src/cmd/gc/typecheck.c [deleted file]
src/cmd/gc/unsafe.c [deleted file]
src/cmd/gc/unsafe.go [deleted file]
src/cmd/gc/walk.c [deleted file]
src/cmd/gc/y.tab.c [deleted file]
src/cmd/gc/y.tab.h [deleted file]
src/cmd/gc/yerr.h [deleted file]
src/cmd/new5a/a.y [deleted file]
src/cmd/new6a/a.y [deleted file]
src/cmd/new8a/a.y [deleted file]
src/cmd/new9a/a.y [deleted file]
src/cmd/objwriter/main.go [deleted file]

diff --git a/src/cmd/5a/Makefile b/src/cmd/5a/Makefile
deleted file mode 100644 (file)
index 27290dd..0000000
+++ /dev/null
@@ -1,10 +0,0 @@
-# Copyright 2012 The Go Authors.  All rights reserved.
-# Use of this source code is governed by a BSD-style
-# license that can be found in the LICENSE file.
-
-include ../../Make.dist
-
-install: y.tab.h
-
-y.tab.h: a.y
-       LANG=C LANGUAGE=en_US.UTF8 bison -d -v -y a.y
diff --git a/src/cmd/5a/a.h b/src/cmd/5a/a.h
deleted file mode 100644 (file)
index 8a6764b..0000000
+++ /dev/null
@@ -1,173 +0,0 @@
-// Inferno utils/5a/a.h
-// http://code.google.com/p/inferno-os/source/browse/utils/5a/a.h
-//
-//     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 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 <bio.h>
-#include <link.h>
-#include "../5l/5.out.h"
-
-#ifndef        EXTERN
-#define        EXTERN  extern
-#endif
-
-#undef getc
-#undef ungetc
-#undef BUFSIZ
-
-#define        getc    ccgetc
-#define        ungetc  ccungetc
-
-typedef        struct  Sym     Sym;
-typedef        struct  Io      Io;
-
-#define        MAXALIGN        7
-#define        FPCHIP          1
-#define        NSYMB           8192
-#define        BUFSIZ          8192
-#define        HISTSZ          20
-#ifndef        EOF
-#define        EOF             (-1)
-#endif
-#define        IGN             (-2)
-#define        GETC()          ((--fi.c < 0)? filbuf(): *fi.p++ & 0xff)
-#define        NHASH           503
-#define        STRINGSZ        200
-#define        NMACRO          10
-
-struct Sym
-{
-       Sym*    link;
-       char*   macro;
-       int32   value;
-       ushort  type;
-       char    *name;
-       char*   labelname;
-       char    sym;
-};
-#define        S       ((Sym*)0)
-
-EXTERN struct
-{
-       char*   p;
-       int     c;
-} fi;
-
-struct Io
-{
-       Io*     link;
-       char    b[BUFSIZ];
-       char*   p;
-       short   c;
-       short   f;
-};
-#define        I       ((Io*)0)
-
-enum
-{
-       CLAST,
-       CMACARG,
-       CMACRO,
-       CPREPROC,
-       
-       Always = C_SCOND_NONE,
-};
-
-EXTERN int     debug[256];
-EXTERN Sym*    hash[NHASH];
-EXTERN char**  Dlist;
-EXTERN int     nDlist;
-EXTERN int     newflag;
-EXTERN char*   hunk;
-EXTERN char**  include;
-EXTERN Io*     iofree;
-EXTERN Io*     ionext;
-EXTERN Io*     iostack;
-EXTERN int32   lineno;
-EXTERN int     nerrors;
-EXTERN int32   nhunk;
-EXTERN int     ninclude;
-EXTERN int32   nsymb;
-EXTERN Addr    nullgen;
-EXTERN char*   outfile;
-EXTERN int     pass;
-EXTERN int32   pc;
-EXTERN int     peekc;
-EXTERN int32   stmtline;
-EXTERN int     sym;
-EXTERN char*   symb;
-EXTERN int     thechar;
-EXTERN char*   thestring;
-EXTERN int32   thunk;
-EXTERN Biobuf  obuf;
-EXTERN Link*   ctxt;
-EXTERN Biobuf  bstdout;
-EXTERN Prog*   lastpc;
-
-void*  alloc(int32);
-void*  allocn(void*, int32, int32);
-void   ensuresymb(int32);
-void   errorexit(void);
-void   pushio(void);
-void   newio(void);
-void   newfile(char*, int);
-Sym*   slookup(char*);
-Sym*   lookup(void);
-Sym*   labellookup(Sym*);
-void   settext(LSym*);
-void   syminit(Sym*);
-int32  yylex(void);
-int    getc(void);
-int    getnsc(void);
-void   unget(int);
-int    escchar(int);
-void   cinit(void);
-void   pinit(char*);
-void   cclean(void);
-int    isreg(Addr*);
-void   outcode(int, int, Addr*, int, Addr*);
-int    filbuf(void);
-Sym*   getsym(void);
-void   domacro(void);
-void   macund(void);
-void   macdef(void);
-void   macexpand(Sym*, char*);
-void   macinc(void);
-void   maclin(void);
-void   macprag(void);
-void   macif(int);
-void   macend(void);
-void   dodefine(char*);
-void   prfile(int32);
-void   linehist(char*, int);
-void   gethunk(void);
-void   yyerror(char*, ...);
-int    yyparse(void);
-void   setinclude(char*);
-int    assemble(char*);
-void   listinit(void);
index 10e9f6feea3aa20e0220ea1df34ae3cf91744be5..39fab8fa26e7e2938c068b7fdd66f79ffe46f515 100644 (file)
 // THE SOFTWARE.
 
 %{
-#include <u.h>
-#include <stdio.h>     /* if we don't, bison will, and a.h re-#defines getc */
-#include <libc.h>
-#include "a.h"
-#include "../../runtime/funcdata.h"
+package main
+
+import (
+       "cmd/internal/asm"
+       "cmd/internal/obj"
+       . "cmd/internal/obj/arm"
+)
 %}
-%union
-{
-       Sym     *sym;
-       int32   lval;
-       double  dval;
-       char    sval[8];
-       Addr    addr;
+
+%union {
+       sym *asm.Sym
+       lval int32
+       dval float64
+       sval string
+       addr obj.Addr
 }
+
 %left  '|'
 %left  '^'
 %left  '&'
 %left  '*' '/' '%'
 %token <lval>  LTYPE1 LTYPE2 LTYPE3 LTYPE4 LTYPE5
 %token <lval>  LTYPE6 LTYPE7 LTYPE8 LTYPE9 LTYPEA
-%token <lval>  LTYPEB LGLOBL LTYPEC LTYPED LTYPEE
+%token <lval>  LTYPEB LTYPEC LTYPED LTYPEE
 %token <lval>  LTYPEG LTYPEH LTYPEI LTYPEJ LTYPEK
 %token <lval>  LTYPEL LTYPEM LTYPEN LTYPEBX LTYPEPLD
 %token <lval>  LCONST LSP LSB LFP LPC
 %token <lval>  LTYPEX LTYPEPC LTYPEF LR LREG LF LFREG LC LCREG LPSR LFCR
-%token <lval>  LCOND LS LAT
+%token <lval>  LCOND LS LAT LGLOBL
 %token <dval>  LFCONST
 %token <sval>  LSCONST
 %token <sym>   LNAME LLAB LVAR
 prog:
 |      prog
        {
-               stmtline = lineno;
+               stmtline = asm.Lineno;
        }
        line
 
 line:
        LNAME ':'
        {
-               $1 = labellookup($1);
-               if($1->type == LLAB && $1->value != pc)
-                       yyerror("redeclaration of %s", $1->labelname);
-               $1->type = LLAB;
-               $1->value = pc;
+               $1 = asm.LabelLookup($1);
+               if $1.Type == LLAB && $1.Value != int64(asm.PC) {
+                       yyerror("redeclaration of %s", $1.Labelname)
+               }
+               $1.Type = LLAB;
+               $1.Value = int64(asm.PC)
        }
        line
 |      LNAME '=' expr ';'
        {
-               $1->type = LVAR;
-               $1->value = $3;
+               $1.Type = LVAR;
+               $1.Value = int64($3);
        }
 |      LVAR '=' expr ';'
        {
-               if($1->value != $3)
-                       yyerror("redeclaration of %s", $1->name);
-               $1->value = $3;
+               if $1.Value != int64($3) {
+                       yyerror("redeclaration of %s", $1.Name)
+               }
+               $1.Value = int64($3);
        }
 |      ';'
 |      inst ';'
@@ -171,20 +176,20 @@ inst:
  */
 |      LTYPE8 cond ioreg ',' '[' reglist ']'
        {
-               Addr g;
+               var g obj.Addr
 
                g = nullgen;
-               g.type = TYPE_CONST;
-               g.offset = $6;
+               g.Type = obj.TYPE_CONST;
+               g.Offset = int64($6);
                outcode($1, $2, &$3, 0, &g);
        }
 |      LTYPE8 cond '[' reglist ']' ',' ioreg
        {
-               Addr g;
+               var g obj.Addr
 
                g = nullgen;
-               g.type = TYPE_CONST;
-               g.offset = $4;
+               g.Type = obj.TYPE_CONST;
+               g.Offset = int64($4);
                outcode($1, $2, &g, 0, &$7);
        }
 /*
@@ -192,15 +197,15 @@ inst:
  */
 |      LTYPE9 cond reg ',' ireg ',' reg
        {
-               outcode($1, $2, &$5, $3.reg, &$7);
+               outcode($1, $2, &$5, int32($3.Reg), &$7);
        }
 |      LTYPE9 cond reg ',' ireg comma
        {
-               outcode($1, $2, &$5, $3.reg, &$3);
+               outcode($1, $2, &$5, int32($3.Reg), &$3);
        }
 |      LTYPE9 cond comma ireg ',' reg
        {
-               outcode($1, $2, &$4, $6.reg, &$6);
+               outcode($1, $2, &$4, int32($6.Reg), &$6);
        }
 /*
  * RET
@@ -214,16 +219,16 @@ inst:
  */
 |      LTYPEB name ',' '$' textsize
        {
-               settext($2.sym);
+               asm.Settext($2.Sym);
                outcode($1, Always, &$2, 0, &$5);
        }
 |      LTYPEB name ',' con ',' '$' textsize
        {
-               settext($2.sym);
+               asm.Settext($2.Sym);
                outcode($1, Always, &$2, 0, &$7);
-               if(pass > 1) {
-                       lastpc->from3.type = TYPE_CONST;
-                       lastpc->from3.offset = $4;
+               if asm.Pass > 1 {
+                       lastpc.From3.Type = obj.TYPE_CONST;
+                       lastpc.From3.Offset = int64($4)
                }
        }
 /*
@@ -231,27 +236,28 @@ inst:
  */
 |      LGLOBL name ',' imm
        {
-               settext($2.sym);
-               outcode($1, Always, &$2, 0, &$4);
+               asm.Settext($2.Sym)
+               outcode($1, Always, &$2, 0, &$4)
        }
 |      LGLOBL name ',' con ',' imm
        {
-               settext($2.sym);
-               outcode($1, Always, &$2, 0, &$6);
-               if(pass > 1) {
-                       lastpc->from3.type = TYPE_CONST;
-                       lastpc->from3.offset = $4;
+               asm.Settext($2.Sym)
+               outcode($1, Always, &$2, 0, &$6)
+               if asm.Pass > 1 {
+                       lastpc.From3.Type = obj.TYPE_CONST
+                       lastpc.From3.Offset = int64($4)
                }
        }
+
 /*
  * DATA
  */
 |      LTYPEC name '/' con ',' ximm
        {
-               outcode($1, Always, &$2, 0, &$6);
-               if(pass > 1) {
-                       lastpc->from3.type = TYPE_CONST;
-                       lastpc->from3.offset = $4;
+               outcode($1, Always, &$2, 0, &$6)
+               if asm.Pass > 1 {
+                       lastpc.From3.Type = obj.TYPE_CONST
+                       lastpc.From3.Offset = int64($4)
                }
        }
 /*
@@ -285,18 +291,18 @@ inst:
        }
 |      LTYPEL cond freg ',' freg comma
        {
-               outcode($1, $2, &$3, $5.reg, &nullgen);
+               outcode($1, $2, &$3, int32($5.Reg), &nullgen);
        }
 /*
  * MCR MRC
  */
 |      LTYPEJ cond con ',' expr ',' spreg ',' creg ',' creg oexpr
        {
-               Addr g;
+               var g obj.Addr
 
                g = nullgen;
-               g.type = TYPE_CONST;
-               g.offset =
+               g.Type = obj.TYPE_CONST;
+               g.Offset = int64(
                        (0xe << 24) |           /* opcode */
                        ($1 << 20) |            /* MCR/MRC */
                        (($2^C_SCOND_XOR) << 28) |              /* scond */
@@ -306,7 +312,7 @@ inst:
                        (($9 & 15) << 16) |     /* Crn */
                        (($11 & 15) << 0) |     /* Crm */
                        (($12 & 7) << 5) |      /* coprocessor information */
-                       (1<<4);                 /* must be set */
+                       (1<<4));                        /* must be set */
                outcode(AMRC, Always, &nullgen, 0, &g);
        }
 /*
@@ -314,17 +320,17 @@ inst:
  */
 |      LTYPEM cond reg ',' reg ',' regreg
        {
-               outcode($1, $2, &$3, $5.reg, &$7);
+               outcode($1, $2, &$3, int32($5.Reg), &$7);
        }
 /*
- * MULA r1,r2,r3,r4: (r1*r2+r3) & 0xffffffff -> r4
+ * MULA r1,r2,r3,r4: (r1*r2+r3) & 0xffffffff . r4
  * MULAW{T,B} r1,r2,r3,r4
  */
 |      LTYPEN cond reg ',' reg ',' reg ',' spreg
        {
-               $7.type = TYPE_REGREG2;
-               $7.offset = $9;
-               outcode($1, $2, &$3, $5.reg, &$7);
+               $7.Type = obj.TYPE_REGREG2;
+               $7.Offset = int64($9);
+               outcode($1, $2, &$3, int32($5.Reg), &$7);
        }
 /*
  * PLD
@@ -338,8 +344,9 @@ inst:
  */
 |      LTYPEPC gen ',' gen
        {
-               if($2.type != TYPE_CONST || $4.type != TYPE_CONST)
-                       yyerror("arguments to PCDATA must be integer constants");
+               if $2.Type != obj.TYPE_CONST || $4.Type != obj.TYPE_CONST {
+                       yyerror("arguments to PCDATA must be integer constants")
+               }
                outcode($1, Always, &$2, 0, &$4);
        }
 /*
@@ -347,10 +354,12 @@ inst:
  */
 |      LTYPEF gen ',' gen
        {
-               if($2.type != TYPE_CONST)
-                       yyerror("index for FUNCDATA must be integer constant");
-               if($4.type != NAME_EXTERN && $4.type != NAME_STATIC && $4.type != TYPE_MEM)
-                       yyerror("value for FUNCDATA must be symbol reference");
+               if $2.Type != obj.TYPE_CONST {
+                       yyerror("index for FUNCDATA must be integer constant")
+               }
+               if $4.Type != obj.NAME_EXTERN && $4.Type != obj.NAME_STATIC && $4.Type != obj.TYPE_MEM {
+                       yyerror("value for FUNCDATA must be symbol reference")
+               }
                outcode($1, Always, &$2, 0, &$4);
        }
 /*
@@ -361,13 +370,43 @@ inst:
                outcode($1, Always, &nullgen, 0, &nullgen);
        }
 
+textsize:
+       LCONST
+       {
+               $$ = nullgen;
+               $$.Type = obj.TYPE_TEXTSIZE;
+               $$.Offset = int64($1)
+               $$.U.Argsize = obj.ArgsSizeUnknown;
+       }
+|      '-' LCONST
+       {
+               $$ = nullgen;
+               $$.Type = obj.TYPE_TEXTSIZE;
+               $$.Offset = -int64($2)
+               $$.U.Argsize = obj.ArgsSizeUnknown;
+       }
+|      LCONST '-' LCONST
+       {
+               $$ = nullgen;
+               $$.Type = obj.TYPE_TEXTSIZE;
+               $$.Offset = int64($1)
+               $$.U.Argsize = int32($3);
+       }
+|      '-' LCONST '-' LCONST
+       {
+               $$ = nullgen;
+               $$.Type = obj.TYPE_TEXTSIZE;
+               $$.Offset = -int64($2)
+               $$.U.Argsize = int32($4);
+       }
+
 cond:
        {
                $$ = Always;
        }
 |      cond LCOND
        {
-               $$ = ($1 & ~C_SCOND) | $2;
+               $$ = ($1 & C_SCOND) | $2;
        }
 |      cond LS
        {
@@ -381,65 +420,36 @@ rel:
        con '(' LPC ')'
        {
                $$ = nullgen;
-               $$.type = TYPE_BRANCH;
-               $$.offset = $1 + pc;
+               $$.Type = obj.TYPE_BRANCH;
+               $$.Offset = int64($1) + int64(asm.PC);
        }
 |      LNAME offset
        {
-               $1 = labellookup($1);
+               $1 = asm.LabelLookup($1);
                $$ = nullgen;
-               if(pass == 2 && $1->type != LLAB)
-                       yyerror("undefined label: %s", $1->labelname);
-               $$.type = TYPE_BRANCH;
-               $$.offset = $1->value + $2;
-       }
-
-textsize:
-       LCONST
-       {
-               $$ = nullgen;
-               $$.type = TYPE_TEXTSIZE;
-               $$.offset = $1;
-               $$.u.argsize = ArgsSizeUnknown;
-       }
-|      '-' LCONST
-       {
-               $$ = nullgen;
-               $$.type = TYPE_TEXTSIZE;
-               $$.offset = -$2;
-               $$.u.argsize = ArgsSizeUnknown;
-       }
-|      LCONST '-' LCONST
-       {
-               $$ = nullgen;
-               $$.type = TYPE_TEXTSIZE;
-               $$.offset = $1;
-               $$.u.argsize = $3;
-       }
-|      '-' LCONST '-' LCONST
-       {
-               $$ = nullgen;
-               $$.type = TYPE_TEXTSIZE;
-               $$.offset = -$2;
-               $$.u.argsize = $4;
+               if asm.Pass == 2 && $1.Type != LLAB {
+                       yyerror("undefined label: %s", $1.Labelname)
+               }
+               $$.Type = obj.TYPE_BRANCH;
+               $$.Offset = $1.Value + int64($2);
        }
 
 ximm:  '$' con
        {
                $$ = nullgen;
-               $$.type = TYPE_CONST;
-               $$.offset = $2;
+               $$.Type = obj.TYPE_CONST;
+               $$.Offset = int64($2);
        }
 |      '$' oreg
        {
                $$ = $2;
-               $$.type = TYPE_ADDR;
+               $$.Type = obj.TYPE_ADDR;
        }
 |      '$' LSCONST
        {
                $$ = nullgen;
-               $$.type = TYPE_SCONST;
-               memcpy($$.u.sval, $2, sizeof($$.u.sval));
+               $$.Type = obj.TYPE_SCONST;
+               $$.U.Sval = $2
        }
 |      fcon
 
@@ -447,45 +457,34 @@ fcon:
        '$' LFCONST
        {
                $$ = nullgen;
-               $$.type = TYPE_FCONST;
-               $$.u.dval = $2;
+               $$.Type = obj.TYPE_FCONST;
+               $$.U.Dval = $2;
        }
 |      '$' '-' LFCONST
        {
                $$ = nullgen;
-               $$.type = TYPE_FCONST;
-               $$.u.dval = -$3;
+               $$.Type = obj.TYPE_FCONST;
+               $$.U.Dval = -$3;
        }
 
 reglist:
        spreg
        {
-               if($1 < REG_R0 || $1 > REG_R15)
-                       yyerror("invalid register in reglist");
-
-               $$ = 1 << ($1&15);
+               $$ = 1 << uint($1&15);
        }
 |      spreg '-' spreg
        {
-               int i;
-
-               if($1 < REG_R0 || $1 > REG_R15)
-                       yyerror("invalid register in reglist");
-               if($3 < REG_R0 || $3 > REG_R15)
-                       yyerror("invalid register in reglist");
-
                $$=0;
-               for(i=$1; i<=$3; i++)
-                       $$ |= 1<<(i&15);
-               for(i=$3; i<=$1; i++)
-                       $$ |= 1<<(i&15);
+               for i:=$1; i<=$3; i++ {
+                       $$ |= 1<<uint(i&15)
+               }
+               for i:=$3; i<=$1; i++ {
+                       $$ |= 1<<uint(i&15)
+               }
        }
 |      spreg comma reglist
        {
-               if($1 < REG_R0 || $1 > REG_R15)
-                       yyerror("invalid register in reglist");
-
-               $$ = (1<<($1&15)) | $3;
+               $$ = (1<<uint($1&15)) | $3;
        }
 
 gen:
@@ -495,25 +494,25 @@ gen:
 |      shift '(' spreg ')'
        {
                $$ = $1;
-               $$.reg = $3;
+               $$.Reg = int16($3);
        }
 |      LPSR
        {
                $$ = nullgen;
-               $$.type = TYPE_REG;
-               $$.reg = $1;
+               $$.Type = obj.TYPE_REG
+               $$.Reg = int16($1);
        }
 |      LFCR
        {
                $$ = nullgen;
-               $$.type = TYPE_REG;
-               $$.reg = $1;
+               $$.Type = obj.TYPE_REG
+               $$.Reg = int16($1);
        }
 |      con
        {
                $$ = nullgen;
-               $$.type = TYPE_MEM;
-               $$.offset = $1;
+               $$.Type = obj.TYPE_MEM;
+               $$.Offset = int64($1);
        }
 |      oreg
 |      freg
@@ -523,7 +522,7 @@ nireg:
 |      name
        {
                $$ = $1;
-               if($1.name != NAME_EXTERN && $1.name != NAME_STATIC) {
+               if($1.Name != obj.NAME_EXTERN && $1.Name != obj.NAME_STATIC) {
                }
        }
 
@@ -531,9 +530,9 @@ ireg:
        '(' spreg ')'
        {
                $$ = nullgen;
-               $$.type = TYPE_MEM;
-               $$.reg = $2;
-               $$.offset = 0;
+               $$.Type = obj.TYPE_MEM;
+               $$.Reg = int16($2);
+               $$.Offset = 0;
        }
 
 ioreg:
@@ -541,9 +540,9 @@ ioreg:
 |      con '(' sreg ')'
        {
                $$ = nullgen;
-               $$.type = TYPE_MEM;
-               $$.reg = $3;
-               $$.offset = $1;
+               $$.Type = obj.TYPE_MEM;
+               $$.Reg = int16($3);
+               $$.Offset = int64($1);
        }
 
 oreg:
@@ -551,8 +550,8 @@ oreg:
 |      name '(' sreg ')'
        {
                $$ = $1;
-               $$.type = TYPE_MEM;
-               $$.reg = $3;
+               $$.Type = obj.TYPE_MEM;
+               $$.Reg = int16($3);
        }
 |      ioreg
 
@@ -564,64 +563,66 @@ imsr:
 imm:   '$' con
        {
                $$ = nullgen;
-               $$.type = TYPE_CONST;
-               $$.offset = $2;
+               $$.Type = obj.TYPE_CONST;
+               $$.Offset = int64($2);
        }
 
 reg:
        spreg
        {
                $$ = nullgen;
-               $$.type = TYPE_REG;
-               $$.reg = $1;
+               $$.Type = obj.TYPE_REG;
+               $$.Reg = int16($1);
        }
 
 regreg:
        '(' spreg ',' spreg ')'
        {
                $$ = nullgen;
-               $$.type = TYPE_REGREG;
-               $$.reg = $2;
-               $$.offset = $4;
+               $$.Type = obj.TYPE_REGREG;
+               $$.Reg = int16($2);
+               $$.Offset = int64($4);
        }
 
 shift:
        spreg '<' '<' rcon
        {
                $$ = nullgen;
-               $$.type = TYPE_SHIFT;
-               $$.offset = $1&15 | $4 | (0 << 5);
+               $$.Type = obj.TYPE_SHIFT;
+               $$.Offset = int64($1&15) | int64($4) | (0 << 5);
        }
 |      spreg '>' '>' rcon
        {
                $$ = nullgen;
-               $$.type = TYPE_SHIFT;
-               $$.offset = $1&15 | $4 | (1 << 5);
+               $$.Type = obj.TYPE_SHIFT;
+               $$.Offset = int64($1&15) | int64($4) | (1 << 5);
        }
 |      spreg '-' '>' rcon
        {
                $$ = nullgen;
-               $$.type = TYPE_SHIFT;
-               $$.offset = $1&15 | $4 | (2 << 5);
+               $$.Type = obj.TYPE_SHIFT;
+               $$.Offset = int64($1&15) | int64($4) | (2 << 5);
        }
 |      spreg LAT '>' rcon
        {
                $$ = nullgen;
-               $$.type = TYPE_SHIFT;
-               $$.offset = $1&15 | $4 | (3 << 5);
+               $$.Type = obj.TYPE_SHIFT;
+               $$.Offset = int64($1&15) | int64($4) | (3 << 5);
        }
 
 rcon:
        spreg
        {
-               if($$ < REG_R0 || $$ > REG_R15)
-                       print("register value out of range in shift\n");
+               if $$ < REG_R0 || $$ > REG_R15 {
+                       print("register value out of range\n")
+               }
                $$ = (($1&15) << 8) | (1 << 4);
        }
 |      con
        {
-               if($$ < 0 || $$ >= 32)
-                       print("shift value out of range\n");
+               if $$ < 0 || $$ >= 32 {
+                       print("shift value out of range\n")
+               }
                $$ = ($1&31) << 7;
        }
 
@@ -633,8 +634,9 @@ sreg:
        }
 |      LR '(' expr ')'
        {
-               if($3 < 0 || $3 >= NREG)
-                       print("register value out of range in R(...)\n");
+               if $3 < 0 || $3 >= NREG {
+                       print("register value out of range\n")
+               }
                $$ = REG_R0 + $3;
        }
 
@@ -649,8 +651,9 @@ creg:
        LCREG
 |      LC '(' expr ')'
        {
-               if($3 < 0 || $3 >= NREG)
-                       print("register value out of range in C(...)\n");
+               if $3 < 0 || $3 >= NREG {
+                       print("register value out of range\n")
+               }
                $$ = $3; // TODO(rsc): REG_C0+$3
        }
 
@@ -662,40 +665,40 @@ freg:
        LFREG
        {
                $$ = nullgen;
-               $$.type = TYPE_REG;
-               $$.reg = $1;
+               $$.Type = obj.TYPE_REG;
+               $$.Reg = int16($1);
        }
 |      LF '(' con ')'
        {
                $$ = nullgen;
-               $$.type = TYPE_REG;
-               $$.reg = REG_F0 + $3;
+               $$.Type = obj.TYPE_REG;
+               $$.Reg = int16(REG_F0 + $3);
        }
 
 name:
        con '(' pointer ')'
        {
                $$ = nullgen;
-               $$.type = TYPE_MEM;
-               $$.name = $3;
-               $$.sym = nil;
-               $$.offset = $1;
+               $$.Type = obj.TYPE_MEM;
+               $$.Name = int8($3);
+               $$.Sym = nil;
+               $$.Offset = int64($1);
        }
 |      LNAME offset '(' pointer ')'
        {
                $$ = nullgen;
-               $$.type = TYPE_MEM;
-               $$.name = $4;
-               $$.sym = linklookup(ctxt, $1->name, 0);
-               $$.offset = $2;
+               $$.Type = obj.TYPE_MEM;
+               $$.Name = int8($4);
+               $$.Sym = obj.Linklookup(asm.Ctxt, $1.Name, 0);
+               $$.Offset = int64($2);
        }
 |      LNAME '<' '>' offset '(' LSB ')'
        {
                $$ = nullgen;
-               $$.type = TYPE_MEM;
-               $$.name = NAME_STATIC;
-               $$.sym = linklookup(ctxt, $1->name, 1);
-               $$.offset = $4;
+               $$.Type = obj.TYPE_MEM;
+               $$.Name = obj.NAME_STATIC;
+               $$.Sym = obj.Linklookup(asm.Ctxt, $1.Name, 1);
+               $$.Offset = int64($4);
        }
 
 offset:
@@ -720,7 +723,7 @@ con:
        LCONST
 |      LVAR
        {
-               $$ = $1->value;
+               $$ = int32($1.Value);
        }
 |      '-' con
        {
@@ -732,7 +735,7 @@ con:
        }
 |      '~' con
        {
-               $$ = ~$2;
+               $$ = ^$2;
        }
 |      '(' expr ')'
        {
@@ -772,11 +775,11 @@ expr:
        }
 |      expr '<' '<' expr
        {
-               $$ = $1 << $4;
+               $$ = $1 << uint($4);
        }
 |      expr '>' '>' expr
        {
-               $$ = $1 >> $4;
+               $$ = $1 >> uint($4);
        }
 |      expr '&' expr
        {
diff --git a/src/cmd/5a/doc.go b/src/cmd/5a/doc.go
deleted file mode 100644 (file)
index 3e9e78f..0000000
+++ /dev/null
@@ -1,20 +0,0 @@
-// Copyright 2009 The Go Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style
-// license that can be found in the LICENSE file.
-
-// +build ignore
-
-/*
-
-5a is a version of the Plan 9 assembler.  The original is documented at
-
-       http://plan9.bell-labs.com/magic/man2html/1/8a
-
-Go-specific considerations are documented at
-
-       http://golang.org/doc/asm
-
-Its target architecture is the ARM, referred to by these tools as arm.
-
-*/
-package main
diff --git a/src/cmd/5a/lex.c b/src/cmd/5a/lex.c
deleted file mode 100644 (file)
index 6f56922..0000000
+++ /dev/null
@@ -1,538 +0,0 @@
-// Inferno utils/5a/lex.c
-// http://code.google.com/p/inferno-os/source/browse/utils/5a/lex.c
-//
-//     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 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.
-
-#define        EXTERN
-#include <u.h>
-#include <libc.h>
-#include "a.h"
-#include "y.tab.h"
-
-enum
-{
-       Plan9   = 1<<0,
-       Unix    = 1<<1,
-       Windows = 1<<2,
-};
-
-int
-systemtype(int sys)
-{
-#ifdef _WIN32
-       return sys&Windows;
-#else
-       return sys&Plan9;
-#endif
-}
-
-int
-Lconv(Fmt *fp)
-{
-       return linklinefmt(ctxt, fp);
-}
-
-void
-dodef(char *p)
-{
-       if(nDlist%8 == 0)
-               Dlist = allocn(Dlist, nDlist*sizeof(char *),
-                       8*sizeof(char *));
-       Dlist[nDlist++] = p;
-}
-
-void
-usage(void)
-{
-       print("usage: %ca [options] file.c...\n", thechar);
-       flagprint(1);
-       errorexit();
-}
-
-void
-main(int argc, char *argv[])
-{
-       char *p;
-
-       thechar = '5';
-       thestring = "arm";
-
-       ctxt = linknew(&linkarm);
-       ctxt->diag = yyerror;
-       ctxt->bso = &bstdout;
-       ctxt->enforce_data_order = 1;
-       Binit(&bstdout, 1, OWRITE);
-       listinit5();
-       fmtinstall('L', Lconv);
-
-       // Allow GOARCH=thestring or GOARCH=thestringsuffix,
-       // but not other values.        
-       p = getgoarch();
-       if(strncmp(p, thestring, strlen(thestring)) != 0)
-               sysfatal("cannot use %cc with GOARCH=%s", thechar, p);
-
-       ensuresymb(NSYMB);
-       memset(debug, 0, sizeof(debug));
-       cinit();
-       outfile = 0;
-       setinclude(".");
-       
-       flagfn1("D", "name[=value]: add #define", dodef);
-       flagfn1("I", "dir: add dir to include path", setinclude);
-       flagcount("S", "print assembly and machine code", &debug['S']);
-       flagcount("m", "debug preprocessor macros", &debug['m']);
-       flagstr("o", "file: set output file", &outfile);
-       flagstr("trimpath", "prefix: remove prefix from recorded source file paths", &ctxt->trimpath);
-
-       flagparse(&argc, &argv, usage);
-       ctxt->debugasm = debug['S'];
-
-       if(argc < 1)
-               usage();
-       if(argc > 1){
-               print("can't assemble multiple files\n");
-               errorexit();
-       }
-
-       if(assemble(argv[0]))
-               errorexit();
-       Bflush(&bstdout);
-       if(nerrors > 0)
-               errorexit();
-       exits(0);
-}
-
-int
-assemble(char *file)
-{
-       char *ofile, *p;
-       int i, of;
-
-       ofile = alloc(strlen(file)+3); // +3 for .x\0 (x=thechar)
-       strcpy(ofile, file);
-       p = utfrrune(ofile, '/');
-       if(p) {
-               include[0] = ofile;
-               *p++ = 0;
-       } else
-               p = ofile;
-       if(outfile == 0) {
-               outfile = p;
-               if(outfile){
-                       p = utfrrune(outfile, '.');
-                       if(p)
-                               if(p[1] == 's' && p[2] == 0)
-                                       p[0] = 0;
-                       p = utfrune(outfile, 0);
-                       p[0] = '.';
-                       p[1] = thechar;
-                       p[2] = 0;
-               } else
-                       outfile = "/dev/null";
-       }
-
-       of = create(outfile, OWRITE, 0664);
-       if(of < 0) {
-               yyerror("%ca: cannot create %s", thechar, outfile);
-               errorexit();
-       }
-       Binit(&obuf, of, OWRITE);
-       Bprint(&obuf, "go object %s %s %s\n", getgoos(), getgoarch(), getgoversion());
-       Bprint(&obuf, "!\n");
-
-       for(pass = 1; pass <= 2; pass++) {
-               pinit(file);
-               for(i=0; i<nDlist; i++)
-                       dodefine(Dlist[i]);
-               yyparse();
-               cclean();
-               if(nerrors)
-                       return nerrors;
-       }
-
-       writeobj(ctxt, &obuf);
-       Bflush(&obuf);
-       return 0;
-}
-
-struct
-{
-       char    *name;
-       ushort  type;
-       ushort  value;
-} itab[] =
-{
-       "SP",           LSP,    NAME_AUTO,
-       "SB",           LSB,    NAME_EXTERN,
-       "FP",           LFP,    NAME_PARAM,
-       "PC",           LPC,    TYPE_BRANCH,
-
-       "R",            LR,     REG_F0,
-
-       "R0",           LREG,   REG_R0,
-       "R1",           LREG,   REG_R1,
-       "R2",           LREG,   REG_R2,
-       "R3",           LREG,   REG_R3,
-       "R4",           LREG,   REG_R4,
-       "R5",           LREG,   REG_R5,
-       "R6",           LREG,   REG_R6,
-       "R7",           LREG,   REG_R7,
-       "R8",           LREG,   REG_R8,
-       "R9",           LREG,   REG_R9,
-       "g",            LREG,   REG_R10, // avoid unintentionally clobber g using R10
-       "R11",          LREG,   REG_R11,
-       "R12",          LREG,   REG_R12,
-       "R13",          LREG,   REG_R13,
-       "R14",          LREG,   REG_R14,
-       "R15",          LREG,   REG_R15,
-
-       "F",            LF,     REG_F0,
-
-       "F0",           LFREG,  REG_F0,
-       "F1",           LFREG,  REG_F1,
-       "F2",           LFREG,  REG_F2,
-       "F3",           LFREG,  REG_F3,
-       "F4",           LFREG,  REG_F4,
-       "F5",           LFREG,  REG_F5,
-       "F6",           LFREG,  REG_F6,
-       "F7",           LFREG,  REG_F7,
-       "F8",           LFREG,  REG_F8,
-       "F9",           LFREG,  REG_F9,
-       "F10",          LFREG,  REG_F10,
-       "F11",          LFREG,  REG_F11,
-       "F12",          LFREG,  REG_F12,
-       "F13",          LFREG,  REG_F13,
-       "F14",          LFREG,  REG_F14,
-       "F15",          LFREG,  REG_F15,
-
-       "C",            LC,     0,
-
-       "C0",           LCREG,  0,
-       "C1",           LCREG,  1,
-       "C2",           LCREG,  2,
-       "C3",           LCREG,  3,
-       "C4",           LCREG,  4,
-       "C5",           LCREG,  5,
-       "C6",           LCREG,  6,
-       "C7",           LCREG,  7,
-       "C8",           LCREG,  8,
-       "C9",           LCREG,  9,
-       "C10",          LCREG,  10,
-       "C11",          LCREG,  11,
-       "C12",          LCREG,  12,
-       "C13",          LCREG,  13,
-       "C14",          LCREG,  14,
-       "C15",          LCREG,  15,
-
-       "CPSR",         LPSR,   REG_CPSR,
-       "SPSR",         LPSR,   REG_SPSR,
-
-       "FPSR",         LFCR,   REG_FPSR,
-       "FPCR",         LFCR,   REG_FPCR,
-
-       ".EQ",          LCOND,  C_SCOND_EQ,
-       ".NE",          LCOND,  C_SCOND_NE,
-       ".CS",          LCOND,  C_SCOND_HS,
-       ".HS",          LCOND,  C_SCOND_HS,
-       ".CC",          LCOND,  C_SCOND_LO,
-       ".LO",          LCOND,  C_SCOND_LO,
-       ".MI",          LCOND,  C_SCOND_MI,
-       ".PL",          LCOND,  C_SCOND_PL,
-       ".VS",          LCOND,  C_SCOND_VS,
-       ".VC",          LCOND,  C_SCOND_VC,
-       ".HI",          LCOND,  C_SCOND_HI,
-       ".LS",          LCOND,  C_SCOND_LS,
-       ".GE",          LCOND,  C_SCOND_GE,
-       ".LT",          LCOND,  C_SCOND_LT,
-       ".GT",          LCOND,  C_SCOND_GT,
-       ".LE",          LCOND,  C_SCOND_LE,
-       ".AL",          LCOND,  C_SCOND_NONE,
-
-       ".U",           LS,     C_UBIT,
-       ".S",           LS,     C_SBIT,
-       ".W",           LS,     C_WBIT,
-       ".P",           LS,     C_PBIT,
-       ".PW",          LS,     C_WBIT|C_PBIT,
-       ".WP",          LS,     C_WBIT|C_PBIT,
-
-       ".F",           LS,     C_FBIT,
-
-       ".IBW",         LS,     C_WBIT|C_PBIT|C_UBIT,
-       ".IAW",         LS,     C_WBIT|C_UBIT,
-       ".DBW",         LS,     C_WBIT|C_PBIT,
-       ".DAW",         LS,     C_WBIT,
-       ".IB",          LS,     C_PBIT|C_UBIT,
-       ".IA",          LS,     C_UBIT,
-       ".DB",          LS,     C_PBIT,
-       ".DA",          LS,     0,
-
-       "@",            LAT,    0,
-
-       "AND",          LTYPE1, AAND,
-       "EOR",          LTYPE1, AEOR,
-       "SUB",          LTYPE1, ASUB,
-       "RSB",          LTYPE1, ARSB,
-       "ADD",          LTYPE1, AADD,
-       "ADC",          LTYPE1, AADC,
-       "SBC",          LTYPE1, ASBC,
-       "RSC",          LTYPE1, ARSC,
-       "ORR",          LTYPE1, AORR,
-       "BIC",          LTYPE1, ABIC,
-
-       "SLL",          LTYPE1, ASLL,
-       "SRL",          LTYPE1, ASRL,
-       "SRA",          LTYPE1, ASRA,
-
-       "MUL",          LTYPE1, AMUL,
-       "MULA",         LTYPEN, AMULA,
-       "DIV",          LTYPE1, ADIV,
-       "MOD",          LTYPE1, AMOD,
-
-       "MULL",         LTYPEM, AMULL,
-       "MULAL",        LTYPEM, AMULAL,
-       "MULLU",        LTYPEM, AMULLU,
-       "MULALU",       LTYPEM, AMULALU,
-
-       "MVN",          LTYPE2, AMVN,   /* op2 ignored */
-
-       "MOVB",         LTYPE3, AMOVB,
-       "MOVBU",        LTYPE3, AMOVBU,
-       "MOVH",         LTYPE3, AMOVH,
-       "MOVHU",        LTYPE3, AMOVHU,
-       "MOVW",         LTYPE3, AMOVW,
-
-       "MOVD",         LTYPE3, AMOVD,
-       "MOVDF",                LTYPE3, AMOVDF,
-       "MOVDW",        LTYPE3, AMOVDW,
-       "MOVF",         LTYPE3, AMOVF,
-       "MOVFD",                LTYPE3, AMOVFD,
-       "MOVFW",                LTYPE3, AMOVFW,
-       "MOVWD",        LTYPE3, AMOVWD,
-       "MOVWF",                LTYPE3, AMOVWF,
-
-       "LDREX",                LTYPE3, ALDREX,
-       "LDREXD",               LTYPE3, ALDREXD,
-       "STREX",                LTYPE9, ASTREX,
-       "STREXD",               LTYPE9, ASTREXD,
-
-/*
-       "NEGF",         LTYPEI, ANEGF,
-       "NEGD",         LTYPEI, ANEGD,
-       "SQTF",         LTYPEI, ASQTF,
-       "SQTD",         LTYPEI, ASQTD,
-       "RNDF",         LTYPEI, ARNDF,
-       "RNDD",         LTYPEI, ARNDD,
-       "URDF",         LTYPEI, AURDF,
-       "URDD",         LTYPEI, AURDD,
-       "NRMF",         LTYPEI, ANRMF,
-       "NRMD",         LTYPEI, ANRMD,
-*/
-
-       "ABSF",         LTYPEI, AABSF,
-       "ABSD",         LTYPEI, AABSD,
-       "SQRTF",        LTYPEI, ASQRTF,
-       "SQRTD",        LTYPEI, ASQRTD,
-       "CMPF",         LTYPEL, ACMPF,
-       "CMPD",         LTYPEL, ACMPD,
-       "ADDF",         LTYPEK, AADDF,
-       "ADDD",         LTYPEK, AADDD,
-       "SUBF",         LTYPEK, ASUBF,
-       "SUBD",         LTYPEK, ASUBD,
-       "MULF",         LTYPEK, AMULF,
-       "MULD",         LTYPEK, AMULD,
-       "DIVF",         LTYPEK, ADIVF,
-       "DIVD",         LTYPEK, ADIVD,
-
-       "B",            LTYPE4, AB,
-       "BL",           LTYPE4, ABL,
-       "BX",           LTYPEBX,        ABX,
-
-       "BEQ",          LTYPE5, ABEQ,
-       "BNE",          LTYPE5, ABNE,
-       "BCS",          LTYPE5, ABCS,
-       "BHS",          LTYPE5, ABHS,
-       "BCC",          LTYPE5, ABCC,
-       "BLO",          LTYPE5, ABLO,
-       "BMI",          LTYPE5, ABMI,
-       "BPL",          LTYPE5, ABPL,
-       "BVS",          LTYPE5, ABVS,
-       "BVC",          LTYPE5, ABVC,
-       "BHI",          LTYPE5, ABHI,
-       "BLS",          LTYPE5, ABLS,
-       "BGE",          LTYPE5, ABGE,
-       "BLT",          LTYPE5, ABLT,
-       "BGT",          LTYPE5, ABGT,
-       "BLE",          LTYPE5, ABLE,
-       "BCASE",        LTYPE5, ABCASE,
-
-       "SWI",          LTYPE6, ASWI,
-
-       "CMP",          LTYPE7, ACMP,
-       "TST",          LTYPE7, ATST,
-       "TEQ",          LTYPE7, ATEQ,
-       "CMN",          LTYPE7, ACMN,
-
-       "MOVM",         LTYPE8, AMOVM,
-
-       "SWPBU",        LTYPE9, ASWPBU,
-       "SWPW",         LTYPE9, ASWPW,
-
-       "RET",          LTYPEA, ARET,
-       "RFE",          LTYPEA, ARFE,
-
-       "TEXT",         LTYPEB, ATEXT,
-       "GLOBL",        LGLOBL, AGLOBL,
-       "DATA",         LTYPEC, ADATA,
-       "CASE",         LTYPED, ACASE,
-       "END",          LTYPEE, AEND,
-       "WORD",         LTYPEH, AWORD,
-       "NOP",          LTYPEI, ANOP,
-
-       "MCR",          LTYPEJ, 0,
-       "MRC",          LTYPEJ, 1,
-
-       "PLD",          LTYPEPLD, APLD,
-       "UNDEF",        LTYPEE, AUNDEF,
-       "CLZ",          LTYPE2, ACLZ,
-
-       "MULWT",        LTYPE1, AMULWT,
-       "MULWB",        LTYPE1, AMULWB,
-       "MULAWT",       LTYPEN, AMULAWT,
-       "MULAWB",       LTYPEN, AMULAWB,
-
-       "USEFIELD",     LTYPEN, AUSEFIELD,
-       "PCDATA",       LTYPEPC,        APCDATA,
-       "FUNCDATA",     LTYPEF, AFUNCDATA,
-
-       0
-};
-
-void
-cinit(void)
-{
-       Sym *s;
-       int i;
-
-       nullgen.type = TYPE_NONE;
-       nullgen.name = NAME_NONE;
-
-       nerrors = 0;
-       iostack = I;
-       iofree = I;
-       peekc = IGN;
-       nhunk = 0;
-       for(i=0; i<NHASH; i++)
-               hash[i] = S;
-       for(i=0; itab[i].name; i++) {
-               s = slookup(itab[i].name);
-               s->type = itab[i].type;
-               s->value = itab[i].value;
-       }
-}
-
-void
-syminit(Sym *s)
-{
-
-       s->type = LNAME;
-       s->value = 0;
-}
-
-int
-isreg(Addr *g)
-{
-
-       USED(g);
-       return 1;
-}
-
-void
-cclean(void)
-{
-       outcode(AEND, Always, &nullgen, 0, &nullgen);
-}
-
-static int bcode[] =
-{
-       ABEQ,
-       ABNE,
-       ABCS,
-       ABCC,
-       ABMI,
-       ABPL,
-       ABVS,
-       ABVC,
-       ABHI,
-       ABLS,
-       ABGE,
-       ABLT,
-       ABGT,
-       ABLE,
-       AB,
-       ANOP,
-};
-
-void
-outcode(int a, int scond, Addr *g1, int reg, Addr *g2)
-{
-       Prog *p;
-       Plist *pl;
-
-       /* hack to make B.NE etc. work: turn it into the corresponding conditional */
-       if(a == AB){
-               a = bcode[(scond^C_SCOND_XOR)&0xf];
-               scond = (scond & ~0xf) | C_SCOND_NONE;
-       }
-
-       if(pass == 1)
-               goto out;
-       
-       p = malloc(sizeof *p);
-       memset(p, 0, sizeof *p);
-       p->as = a;
-       p->lineno = stmtline;
-       p->scond = scond;
-       p->from = *g1;
-       p->reg = reg;
-       p->to = *g2;
-       p->pc = pc;
-
-       if(lastpc == nil) {
-               pl = linknewplist(ctxt);
-               pl->firstpc = p;
-       } else
-               lastpc->link = p;
-       lastpc = p;     
-
-out:
-       if(a != AGLOBL && a != ADATA)
-               pc++;
-}
-
-#include "../cc/lexbody"
-#include "../cc/macbody"
similarity index 100%
rename from src/cmd/new5a/lex.go
rename to src/cmd/5a/lex.go
similarity index 100%
rename from src/cmd/new5a/y.go
rename to src/cmd/5a/y.go
diff --git a/src/cmd/5a/y.tab.c b/src/cmd/5a/y.tab.c
deleted file mode 100644 (file)
index 416af9a..0000000
+++ /dev/null
@@ -1,2855 +0,0 @@
-/* A Bison parser, made by GNU Bison 2.3.  */
-
-/* Skeleton implementation for Bison's Yacc-like parsers in C
-
-   Copyright (C) 1984, 1989, 1990, 2000, 2001, 2002, 2003, 2004, 2005, 2006
-   Free Software Foundation, Inc.
-
-   This program is free software; you can redistribute it and/or modify
-   it under the terms of the GNU General Public License as published by
-   the Free Software Foundation; either version 2, or (at your option)
-   any later version.
-
-   This program is distributed in the hope that it will be useful,
-   but WITHOUT ANY WARRANTY; without even the implied warranty of
-   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-   GNU General Public License for more details.
-
-   You should have received a copy of the GNU General Public License
-   along with this program; if not, write to the Free Software
-   Foundation, Inc., 51 Franklin Street, Fifth Floor,
-   Boston, MA 02110-1301, USA.  */
-
-/* As a special exception, you may create a larger work that contains
-   part or all of the Bison parser skeleton and distribute that work
-   under terms of your choice, so long as that work isn't itself a
-   parser generator using the skeleton or a modified version thereof
-   as a parser skeleton.  Alternatively, if you modify or redistribute
-   the parser skeleton itself, you may (at your option) remove this
-   special exception, which will cause the skeleton and the resulting
-   Bison output files to be licensed under the GNU General Public
-   License without this special exception.
-
-   This special exception was added by the Free Software Foundation in
-   version 2.2 of Bison.  */
-
-/* C LALR(1) parser skeleton written by Richard Stallman, by
-   simplifying the original so-called "semantic" parser.  */
-
-/* All symbols defined below should begin with yy or YY, to avoid
-   infringing on user name space.  This should be done even for local
-   variables, as they might otherwise be expanded by user macros.
-   There are some unavoidable exceptions within include files to
-   define necessary library symbols; they are noted "INFRINGES ON
-   USER NAME SPACE" below.  */
-
-/* Identify Bison output.  */
-#define YYBISON 1
-
-/* Bison version.  */
-#define YYBISON_VERSION "2.3"
-
-/* Skeleton name.  */
-#define YYSKELETON_NAME "yacc.c"
-
-/* Pure parsers.  */
-#define YYPURE 0
-
-/* Using locations.  */
-#define YYLSP_NEEDED 0
-
-
-
-/* Tokens.  */
-#ifndef YYTOKENTYPE
-# define YYTOKENTYPE
-   /* Put the tokens into the symbol table, so that GDB and other debuggers
-      know about them.  */
-   enum yytokentype {
-     LTYPE1 = 258,
-     LTYPE2 = 259,
-     LTYPE3 = 260,
-     LTYPE4 = 261,
-     LTYPE5 = 262,
-     LTYPE6 = 263,
-     LTYPE7 = 264,
-     LTYPE8 = 265,
-     LTYPE9 = 266,
-     LTYPEA = 267,
-     LTYPEB = 268,
-     LGLOBL = 269,
-     LTYPEC = 270,
-     LTYPED = 271,
-     LTYPEE = 272,
-     LTYPEG = 273,
-     LTYPEH = 274,
-     LTYPEI = 275,
-     LTYPEJ = 276,
-     LTYPEK = 277,
-     LTYPEL = 278,
-     LTYPEM = 279,
-     LTYPEN = 280,
-     LTYPEBX = 281,
-     LTYPEPLD = 282,
-     LCONST = 283,
-     LSP = 284,
-     LSB = 285,
-     LFP = 286,
-     LPC = 287,
-     LTYPEX = 288,
-     LTYPEPC = 289,
-     LTYPEF = 290,
-     LR = 291,
-     LREG = 292,
-     LF = 293,
-     LFREG = 294,
-     LC = 295,
-     LCREG = 296,
-     LPSR = 297,
-     LFCR = 298,
-     LCOND = 299,
-     LS = 300,
-     LAT = 301,
-     LFCONST = 302,
-     LSCONST = 303,
-     LNAME = 304,
-     LLAB = 305,
-     LVAR = 306
-   };
-#endif
-/* Tokens.  */
-#define LTYPE1 258
-#define LTYPE2 259
-#define LTYPE3 260
-#define LTYPE4 261
-#define LTYPE5 262
-#define LTYPE6 263
-#define LTYPE7 264
-#define LTYPE8 265
-#define LTYPE9 266
-#define LTYPEA 267
-#define LTYPEB 268
-#define LGLOBL 269
-#define LTYPEC 270
-#define LTYPED 271
-#define LTYPEE 272
-#define LTYPEG 273
-#define LTYPEH 274
-#define LTYPEI 275
-#define LTYPEJ 276
-#define LTYPEK 277
-#define LTYPEL 278
-#define LTYPEM 279
-#define LTYPEN 280
-#define LTYPEBX 281
-#define LTYPEPLD 282
-#define LCONST 283
-#define LSP 284
-#define LSB 285
-#define LFP 286
-#define LPC 287
-#define LTYPEX 288
-#define LTYPEPC 289
-#define LTYPEF 290
-#define LR 291
-#define LREG 292
-#define LF 293
-#define LFREG 294
-#define LC 295
-#define LCREG 296
-#define LPSR 297
-#define LFCR 298
-#define LCOND 299
-#define LS 300
-#define LAT 301
-#define LFCONST 302
-#define LSCONST 303
-#define LNAME 304
-#define LLAB 305
-#define LVAR 306
-
-
-
-
-/* Copy the first part of user declarations.  */
-#line 31 "a.y"
-
-#include <u.h>
-#include <stdio.h>     /* if we don't, bison will, and a.h re-#defines getc */
-#include <libc.h>
-#include "a.h"
-#include "../../runtime/funcdata.h"
-
-
-/* Enabling traces.  */
-#ifndef YYDEBUG
-# define YYDEBUG 0
-#endif
-
-/* Enabling verbose error messages.  */
-#ifdef YYERROR_VERBOSE
-# undef YYERROR_VERBOSE
-# define YYERROR_VERBOSE 1
-#else
-# define YYERROR_VERBOSE 0
-#endif
-
-/* Enabling the token table.  */
-#ifndef YYTOKEN_TABLE
-# define YYTOKEN_TABLE 0
-#endif
-
-#if ! defined YYSTYPE && ! defined YYSTYPE_IS_DECLARED
-typedef union YYSTYPE
-#line 39 "a.y"
-{
-       Sym     *sym;
-       int32   lval;
-       double  dval;
-       char    sval[8];
-       Addr    addr;
-}
-/* Line 193 of yacc.c.  */
-#line 214 "y.tab.c"
-       YYSTYPE;
-# define yystype YYSTYPE /* obsolescent; will be withdrawn */
-# define YYSTYPE_IS_DECLARED 1
-# define YYSTYPE_IS_TRIVIAL 1
-#endif
-
-
-
-/* Copy the second part of user declarations.  */
-
-
-/* Line 216 of yacc.c.  */
-#line 227 "y.tab.c"
-
-#ifdef short
-# undef short
-#endif
-
-#ifdef YYTYPE_UINT8
-typedef YYTYPE_UINT8 yytype_uint8;
-#else
-typedef unsigned char yytype_uint8;
-#endif
-
-#ifdef YYTYPE_INT8
-typedef YYTYPE_INT8 yytype_int8;
-#elif (defined __STDC__ || defined __C99__FUNC__ \
-     || defined __cplusplus || defined _MSC_VER)
-typedef signed char yytype_int8;
-#else
-typedef short int yytype_int8;
-#endif
-
-#ifdef YYTYPE_UINT16
-typedef YYTYPE_UINT16 yytype_uint16;
-#else
-typedef unsigned short int yytype_uint16;
-#endif
-
-#ifdef YYTYPE_INT16
-typedef YYTYPE_INT16 yytype_int16;
-#else
-typedef short int yytype_int16;
-#endif
-
-#ifndef YYSIZE_T
-# ifdef __SIZE_TYPE__
-#  define YYSIZE_T __SIZE_TYPE__
-# elif defined size_t
-#  define YYSIZE_T size_t
-# elif ! defined YYSIZE_T && (defined __STDC__ || defined __C99__FUNC__ \
-     || defined __cplusplus || defined _MSC_VER)
-#  include <stddef.h> /* INFRINGES ON USER NAME SPACE */
-#  define YYSIZE_T size_t
-# else
-#  define YYSIZE_T unsigned int
-# endif
-#endif
-
-#define YYSIZE_MAXIMUM ((YYSIZE_T) -1)
-
-#ifndef YY_
-# if defined YYENABLE_NLS && YYENABLE_NLS
-#  if ENABLE_NLS
-#   include <libintl.h> /* INFRINGES ON USER NAME SPACE */
-#   define YY_(msgid) dgettext ("bison-runtime", msgid)
-#  endif
-# endif
-# ifndef YY_
-#  define YY_(msgid) msgid
-# endif
-#endif
-
-/* Suppress unused-variable warnings by "using" E.  */
-#if ! defined lint || defined __GNUC__
-# define YYUSE(e) ((void) (e))
-#else
-# define YYUSE(e) /* empty */
-#endif
-
-/* Identity function, used to suppress warnings about constant conditions.  */
-#ifndef lint
-# define YYID(n) (n)
-#else
-#if (defined __STDC__ || defined __C99__FUNC__ \
-     || defined __cplusplus || defined _MSC_VER)
-static int
-YYID (int i)
-#else
-static int
-YYID (i)
-    int i;
-#endif
-{
-  return i;
-}
-#endif
-
-#if ! defined yyoverflow || YYERROR_VERBOSE
-
-/* The parser invokes alloca or malloc; define the necessary symbols.  */
-
-# ifdef YYSTACK_USE_ALLOCA
-#  if YYSTACK_USE_ALLOCA
-#   ifdef __GNUC__
-#    define YYSTACK_ALLOC __builtin_alloca
-#   elif defined __BUILTIN_VA_ARG_INCR
-#    include <alloca.h> /* INFRINGES ON USER NAME SPACE */
-#   elif defined _AIX
-#    define YYSTACK_ALLOC __alloca
-#   elif defined _MSC_VER
-#    include <malloc.h> /* INFRINGES ON USER NAME SPACE */
-#    define alloca _alloca
-#   else
-#    define YYSTACK_ALLOC alloca
-#    if ! defined _ALLOCA_H && ! defined _STDLIB_H && (defined __STDC__ || defined __C99__FUNC__ \
-     || defined __cplusplus || defined _MSC_VER)
-#     include <stdlib.h> /* INFRINGES ON USER NAME SPACE */
-#     ifndef _STDLIB_H
-#      define _STDLIB_H 1
-#     endif
-#    endif
-#   endif
-#  endif
-# endif
-
-# ifdef YYSTACK_ALLOC
-   /* Pacify GCC's `empty if-body' warning.  */
-#  define YYSTACK_FREE(Ptr) do { /* empty */; } while (YYID (0))
-#  ifndef YYSTACK_ALLOC_MAXIMUM
-    /* The OS might guarantee only one guard page at the bottom of the stack,
-       and a page size can be as small as 4096 bytes.  So we cannot safely
-       invoke alloca (N) if N exceeds 4096.  Use a slightly smaller number
-       to allow for a few compiler-allocated temporary stack slots.  */
-#   define YYSTACK_ALLOC_MAXIMUM 4032 /* reasonable circa 2006 */
-#  endif
-# else
-#  define YYSTACK_ALLOC YYMALLOC
-#  define YYSTACK_FREE YYFREE
-#  ifndef YYSTACK_ALLOC_MAXIMUM
-#   define YYSTACK_ALLOC_MAXIMUM YYSIZE_MAXIMUM
-#  endif
-#  if (defined __cplusplus && ! defined _STDLIB_H \
-       && ! ((defined YYMALLOC || defined malloc) \
-            && (defined YYFREE || defined free)))
-#   include <stdlib.h> /* INFRINGES ON USER NAME SPACE */
-#   ifndef _STDLIB_H
-#    define _STDLIB_H 1
-#   endif
-#  endif
-#  ifndef YYMALLOC
-#   define YYMALLOC malloc
-#   if ! defined malloc && ! defined _STDLIB_H && (defined __STDC__ || defined __C99__FUNC__ \
-     || defined __cplusplus || defined _MSC_VER)
-void *malloc (YYSIZE_T); /* INFRINGES ON USER NAME SPACE */
-#   endif
-#  endif
-#  ifndef YYFREE
-#   define YYFREE free
-#   if ! defined free && ! defined _STDLIB_H && (defined __STDC__ || defined __C99__FUNC__ \
-     || defined __cplusplus || defined _MSC_VER)
-void free (void *); /* INFRINGES ON USER NAME SPACE */
-#   endif
-#  endif
-# endif
-#endif /* ! defined yyoverflow || YYERROR_VERBOSE */
-
-
-#if (! defined yyoverflow \
-     && (! defined __cplusplus \
-        || (defined YYSTYPE_IS_TRIVIAL && YYSTYPE_IS_TRIVIAL)))
-
-/* A type that is properly aligned for any stack member.  */
-union yyalloc
-{
-  yytype_int16 yyss;
-  YYSTYPE yyvs;
-  };
-
-/* The size of the maximum gap between one aligned stack and the next.  */
-# define YYSTACK_GAP_MAXIMUM (sizeof (union yyalloc) - 1)
-
-/* The size of an array large to enough to hold all stacks, each with
-   N elements.  */
-# define YYSTACK_BYTES(N) \
-     ((N) * (sizeof (yytype_int16) + sizeof (YYSTYPE)) \
-      + YYSTACK_GAP_MAXIMUM)
-
-/* Copy COUNT objects from FROM to TO.  The source and destination do
-   not overlap.  */
-# ifndef YYCOPY
-#  if defined __GNUC__ && 1 < __GNUC__
-#   define YYCOPY(To, From, Count) \
-      __builtin_memcpy (To, From, (Count) * sizeof (*(From)))
-#  else
-#   define YYCOPY(To, From, Count)             \
-      do                                       \
-       {                                       \
-         YYSIZE_T yyi;                         \
-         for (yyi = 0; yyi < (Count); yyi++)   \
-           (To)[yyi] = (From)[yyi];            \
-       }                                       \
-      while (YYID (0))
-#  endif
-# endif
-
-/* Relocate STACK from its old location to the new one.  The
-   local variables YYSIZE and YYSTACKSIZE give the old and new number of
-   elements in the stack, and YYPTR gives the new location of the
-   stack.  Advance YYPTR to a properly aligned location for the next
-   stack.  */
-# define YYSTACK_RELOCATE(Stack)                                       \
-    do                                                                 \
-      {                                                                        \
-       YYSIZE_T yynewbytes;                                            \
-       YYCOPY (&yyptr->Stack, Stack, yysize);                          \
-       Stack = &yyptr->Stack;                                          \
-       yynewbytes = yystacksize * sizeof (*Stack) + YYSTACK_GAP_MAXIMUM; \
-       yyptr += yynewbytes / sizeof (*yyptr);                          \
-      }                                                                        \
-    while (YYID (0))
-
-#endif
-
-/* YYFINAL -- State number of the termination state.  */
-#define YYFINAL  2
-/* YYLAST -- Last index in YYTABLE.  */
-#define YYLAST   655
-
-/* YYNTOKENS -- Number of terminals.  */
-#define YYNTOKENS  72
-/* YYNNTS -- Number of nonterminals.  */
-#define YYNNTS  35
-/* YYNRULES -- Number of rules.  */
-#define YYNRULES  134
-/* YYNRULES -- Number of states.  */
-#define YYNSTATES  344
-
-/* YYTRANSLATE(YYLEX) -- Bison symbol number corresponding to YYLEX.  */
-#define YYUNDEFTOK  2
-#define YYMAXUTOK   306
-
-#define YYTRANSLATE(YYX)                                               \
-  ((unsigned int) (YYX) <= YYMAXUTOK ? yytranslate[YYX] : YYUNDEFTOK)
-
-/* YYTRANSLATE[YYLEX] -- Bison symbol number corresponding to YYLEX.  */
-static const yytype_uint8 yytranslate[] =
-{
-       0,     2,     2,     2,     2,     2,     2,     2,     2,     2,
-       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
-       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
-       2,     2,     2,     2,     2,     2,    68,    12,     5,     2,
-      69,    70,    10,     8,    65,     9,     2,    11,     2,     2,
-       2,     2,     2,     2,     2,     2,     2,     2,    62,    64,
-       6,    63,     7,     2,     2,     2,     2,     2,     2,     2,
-       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
-       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
-       2,    66,     2,    67,     4,     2,     2,     2,     2,     2,
-       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
-       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
-       2,     2,     2,     2,     3,     2,    71,     2,     2,     2,
-       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
-       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
-       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
-       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
-       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
-       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
-       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
-       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
-       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
-       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
-       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
-       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
-       2,     2,     2,     2,     2,     2,     1,     2,    13,    14,
-      15,    16,    17,    18,    19,    20,    21,    22,    23,    24,
-      25,    26,    27,    28,    29,    30,    31,    32,    33,    34,
-      35,    36,    37,    38,    39,    40,    41,    42,    43,    44,
-      45,    46,    47,    48,    49,    50,    51,    52,    53,    54,
-      55,    56,    57,    58,    59,    60,    61
-};
-
-#if YYDEBUG
-/* YYPRHS[YYN] -- Index of the first RHS symbol of rule number YYN in
-   YYRHS.  */
-static const yytype_uint16 yyprhs[] =
-{
-       0,     0,     3,     4,     5,     9,    10,    15,    20,    25,
-      27,    30,    33,    41,    48,    54,    60,    66,    71,    76,
-      80,    84,    89,    96,   104,   112,   120,   127,   134,   138,
-     144,   152,   157,   164,   171,   176,   180,   186,   192,   200,
-     207,   220,   228,   238,   241,   246,   251,   254,   255,   258,
-     261,   262,   265,   270,   273,   275,   278,   282,   287,   290,
-     293,   296,   298,   301,   305,   307,   311,   315,   317,   319,
-     321,   326,   328,   330,   332,   334,   336,   338,   340,   344,
-     346,   351,   353,   358,   360,   362,   364,   366,   369,   371,
-     377,   382,   387,   392,   397,   399,   401,   403,   405,   410,
-     412,   414,   416,   421,   423,   425,   427,   432,   437,   443,
-     451,   452,   455,   458,   460,   462,   464,   466,   468,   471,
-     474,   477,   481,   482,   485,   487,   491,   495,   499,   503,
-     507,   512,   517,   521,   525
-};
-
-/* YYRHS -- A `-1'-separated list of the rules' RHS.  */
-static const yytype_int8 yyrhs[] =
-{
-      73,     0,    -1,    -1,    -1,    73,    74,    75,    -1,    -1,
-      59,    62,    76,    75,    -1,    59,    63,   106,    64,    -1,
-      61,    63,   106,    64,    -1,    64,    -1,    77,    64,    -1,
-       1,    64,    -1,    13,    78,    90,    65,    97,    65,    92,
-      -1,    13,    78,    90,    65,    97,    65,    -1,    13,    78,
-      90,    65,    92,    -1,    14,    78,    90,    65,    92,    -1,
-      15,    78,    85,    65,    85,    -1,    16,    78,    79,    80,
-      -1,    16,    78,    79,    86,    -1,    36,    79,    87,    -1,
-      17,    79,    80,    -1,    18,    78,    79,    85,    -1,    19,
-      78,    90,    65,    97,    79,    -1,    20,    78,    88,    65,
-      66,    84,    67,    -1,    20,    78,    66,    84,    67,    65,
-      88,    -1,    21,    78,    92,    65,    87,    65,    92,    -1,
-      21,    78,    92,    65,    87,    79,    -1,    21,    78,    79,
-      87,    65,    92,    -1,    22,    78,    79,    -1,    23,   101,
-      65,    68,    81,    -1,    23,   101,    65,   104,    65,    68,
-      81,    -1,    24,   101,    65,    91,    -1,    24,   101,    65,
-     104,    65,    91,    -1,    25,   101,    11,   104,    65,    82,
-      -1,    26,    78,    92,    79,    -1,    29,    79,    82,    -1,
-      30,    78,   100,    65,   100,    -1,    32,    78,    99,    65,
-     100,    -1,    32,    78,    99,    65,    49,    65,   100,    -1,
-      33,    78,   100,    65,   100,    79,    -1,    31,    78,   104,
-      65,   106,    65,    97,    65,    98,    65,    98,   105,    -1,
-      34,    78,    92,    65,    92,    65,    93,    -1,    35,    78,
-      92,    65,    92,    65,    92,    65,    97,    -1,    37,    89,
-      -1,    44,    85,    65,    85,    -1,    45,    85,    65,    85,
-      -1,    27,    79,    -1,    -1,    78,    54,    -1,    78,    55,
-      -1,    -1,    65,    79,    -1,   104,    69,    42,    70,    -1,
-      59,   102,    -1,    38,    -1,     9,    38,    -1,    38,     9,
-      38,    -1,     9,    38,     9,    38,    -1,    68,   104,    -1,
-      68,    89,    -1,    68,    58,    -1,    83,    -1,    68,    57,
-      -1,    68,     9,    57,    -1,    97,    -1,    97,     9,    97,
-      -1,    97,    79,    84,    -1,    92,    -1,    82,    -1,    94,
-      -1,    94,    69,    97,    70,    -1,    52,    -1,    53,    -1,
-     104,    -1,    89,    -1,   100,    -1,    87,    -1,   101,    -1,
-      69,    97,    70,    -1,    87,    -1,   104,    69,    96,    70,
-      -1,   101,    -1,   101,    69,    96,    70,    -1,    88,    -1,
-      92,    -1,    91,    -1,    94,    -1,    68,   104,    -1,    97,
-      -1,    69,    97,    65,    97,    70,    -1,    97,     6,     6,
-      95,    -1,    97,     7,     7,    95,    -1,    97,     9,     7,
-      95,    -1,    97,    56,     7,    95,    -1,    97,    -1,   104,
-      -1,    47,    -1,    42,    -1,    46,    69,   106,    70,    -1,
-      96,    -1,    39,    -1,    51,    -1,    50,    69,   106,    70,
-      -1,   100,    -1,    83,    -1,    49,    -1,    48,    69,   104,
-      70,    -1,   104,    69,   103,    70,    -1,    59,   102,    69,
-     103,    70,    -1,    59,     6,     7,   102,    69,    40,    70,
-      -1,    -1,     8,   104,    -1,     9,   104,    -1,    40,    -1,
-      39,    -1,    41,    -1,    38,    -1,    61,    -1,     9,   104,
-      -1,     8,   104,    -1,    71,   104,    -1,    69,   106,    70,
-      -1,    -1,    65,   106,    -1,   104,    -1,   106,     8,   106,
-      -1,   106,     9,   106,    -1,   106,    10,   106,    -1,   106,
-      11,   106,    -1,   106,    12,   106,    -1,   106,     6,     6,
-     106,    -1,   106,     7,     7,   106,    -1,   106,     5,   106,
-      -1,   106,     4,   106,    -1,   106,     3,   106,    -1
-};
-
-/* YYRLINE[YYN] -- source line where rule number YYN was defined.  */
-static const yytype_uint16 yyrline[] =
-{
-       0,    68,    68,    70,    69,    77,    76,    85,    90,    96,
-      97,    98,   104,   108,   112,   119,   126,   133,   137,   144,
-     151,   158,   165,   172,   181,   193,   197,   201,   208,   215,
-     220,   232,   237,   249,   260,   267,   274,   278,   282,   286,
-     293,   315,   323,   332,   339,   348,   359,   365,   368,   372,
-     377,   378,   381,   387,   398,   405,   412,   419,   427,   433,
-     438,   444,   447,   453,   461,   468,   483,   492,   493,   494,
-     495,   500,   506,   512,   518,   519,   522,   523,   531,   540,
-     541,   550,   551,   557,   560,   561,   562,   564,   572,   580,
-     589,   595,   601,   607,   615,   621,   629,   630,   634,   642,
-     643,   649,   650,   658,   659,   662,   668,   676,   684,   692,
-     702,   705,   709,   715,   716,   717,   720,   721,   725,   729,
-     733,   737,   743,   746,   752,   753,   757,   761,   765,   769,
-     773,   777,   781,   785,   789
-};
-#endif
-
-#if YYDEBUG || YYERROR_VERBOSE || YYTOKEN_TABLE
-/* YYTNAME[SYMBOL-NUM] -- String name of the symbol SYMBOL-NUM.
-   First, the terminals, then, starting at YYNTOKENS, nonterminals.  */
-static const char *const yytname[] =
-{
-  "$end", "error", "$undefined", "'|'", "'^'", "'&'", "'<'", "'>'", "'+'",
-  "'-'", "'*'", "'/'", "'%'", "LTYPE1", "LTYPE2", "LTYPE3", "LTYPE4",
-  "LTYPE5", "LTYPE6", "LTYPE7", "LTYPE8", "LTYPE9", "LTYPEA", "LTYPEB",
-  "LGLOBL", "LTYPEC", "LTYPED", "LTYPEE", "LTYPEG", "LTYPEH", "LTYPEI",
-  "LTYPEJ", "LTYPEK", "LTYPEL", "LTYPEM", "LTYPEN", "LTYPEBX", "LTYPEPLD",
-  "LCONST", "LSP", "LSB", "LFP", "LPC", "LTYPEX", "LTYPEPC", "LTYPEF",
-  "LR", "LREG", "LF", "LFREG", "LC", "LCREG", "LPSR", "LFCR", "LCOND",
-  "LS", "LAT", "LFCONST", "LSCONST", "LNAME", "LLAB", "LVAR", "':'", "'='",
-  "';'", "','", "'['", "']'", "'$'", "'('", "')'", "'~'", "$accept",
-  "prog", "@1", "line", "@2", "inst", "cond", "comma", "rel", "textsize",
-  "ximm", "fcon", "reglist", "gen", "nireg", "ireg", "ioreg", "oreg",
-  "imsr", "imm", "reg", "regreg", "shift", "rcon", "sreg", "spreg", "creg",
-  "frcon", "freg", "name", "offset", "pointer", "con", "oexpr", "expr", 0
-};
-#endif
-
-# ifdef YYPRINT
-/* YYTOKNUM[YYLEX-NUM] -- Internal token number corresponding to
-   token YYLEX-NUM.  */
-static const yytype_uint16 yytoknum[] =
-{
-       0,   256,   257,   124,    94,    38,    60,    62,    43,    45,
-      42,    47,    37,   258,   259,   260,   261,   262,   263,   264,
-     265,   266,   267,   268,   269,   270,   271,   272,   273,   274,
-     275,   276,   277,   278,   279,   280,   281,   282,   283,   284,
-     285,   286,   287,   288,   289,   290,   291,   292,   293,   294,
-     295,   296,   297,   298,   299,   300,   301,   302,   303,   304,
-     305,   306,    58,    61,    59,    44,    91,    93,    36,    40,
-      41,   126
-};
-# endif
-
-/* YYR1[YYN] -- Symbol number of symbol that rule YYN derives.  */
-static const yytype_uint8 yyr1[] =
-{
-       0,    72,    73,    74,    73,    76,    75,    75,    75,    75,
-      75,    75,    77,    77,    77,    77,    77,    77,    77,    77,
-      77,    77,    77,    77,    77,    77,    77,    77,    77,    77,
-      77,    77,    77,    77,    77,    77,    77,    77,    77,    77,
-      77,    77,    77,    77,    77,    77,    77,    78,    78,    78,
-      79,    79,    80,    80,    81,    81,    81,    81,    82,    82,
-      82,    82,    83,    83,    84,    84,    84,    85,    85,    85,
-      85,    85,    85,    85,    85,    85,    86,    86,    87,    88,
-      88,    89,    89,    89,    90,    90,    90,    91,    92,    93,
-      94,    94,    94,    94,    95,    95,    96,    96,    96,    97,
-      97,    98,    98,    99,    99,   100,   100,   101,   101,   101,
-     102,   102,   102,   103,   103,   103,   104,   104,   104,   104,
-     104,   104,   105,   105,   106,   106,   106,   106,   106,   106,
-     106,   106,   106,   106,   106
-};
-
-/* YYR2[YYN] -- Number of symbols composing right hand side of rule YYN.  */
-static const yytype_uint8 yyr2[] =
-{
-       0,     2,     0,     0,     3,     0,     4,     4,     4,     1,
-       2,     2,     7,     6,     5,     5,     5,     4,     4,     3,
-       3,     4,     6,     7,     7,     7,     6,     6,     3,     5,
-       7,     4,     6,     6,     4,     3,     5,     5,     7,     6,
-      12,     7,     9,     2,     4,     4,     2,     0,     2,     2,
-       0,     2,     4,     2,     1,     2,     3,     4,     2,     2,
-       2,     1,     2,     3,     1,     3,     3,     1,     1,     1,
-       4,     1,     1,     1,     1,     1,     1,     1,     3,     1,
-       4,     1,     4,     1,     1,     1,     1,     2,     1,     5,
-       4,     4,     4,     4,     1,     1,     1,     1,     4,     1,
-       1,     1,     4,     1,     1,     1,     4,     4,     5,     7,
-       0,     2,     2,     1,     1,     1,     1,     1,     2,     2,
-       2,     3,     0,     2,     1,     3,     3,     3,     3,     3,
-       4,     4,     3,     3,     3
-};
-
-/* YYDEFACT[STATE-NAME] -- Default rule to reduce with in state
-   STATE-NUM when YYTABLE doesn't specify something else to do.  Zero
-   means the default is an error.  */
-static const yytype_uint8 yydefact[] =
-{
-       2,     3,     1,     0,     0,    47,    47,    47,    47,    50,
-      47,    47,    47,    47,    47,     0,     0,     0,    47,    50,
-      50,    47,    47,    47,    47,    47,    47,    50,     0,     0,
-       0,     0,     0,     9,     4,     0,    11,     0,     0,     0,
-      50,    50,     0,    50,     0,     0,    50,    50,     0,     0,
-     116,   110,   117,     0,     0,     0,     0,     0,     0,     0,
-      46,     0,     0,     0,     0,     0,     0,     0,     0,     0,
-      79,    83,    43,    81,     0,   100,    97,     0,    96,     0,
-     105,    71,    72,     0,    68,    61,     0,    74,    67,    69,
-      99,    88,    75,    73,     0,     5,     0,     0,    10,    48,
-      49,     0,     0,    85,    84,    86,     0,     0,     0,    51,
-     110,    20,     0,     0,     0,     0,     0,     0,     0,     0,
-      88,    28,   119,   118,     0,     0,     0,     0,   124,     0,
-     120,     0,     0,     0,     0,    50,    35,     0,     0,     0,
-     104,     0,   103,     0,     0,     0,     0,    19,     0,     0,
-       0,     0,     0,     0,    62,    60,    59,    58,     0,     0,
-       0,     0,     0,     0,     0,     0,     0,     0,    87,     0,
-       0,     0,   110,    17,    18,    76,    77,     0,    53,     0,
-      21,     0,     0,    50,     0,     0,     0,     0,   110,   111,
-     112,     0,     0,     0,     0,     0,     0,     0,     0,     0,
-       0,     0,   121,     0,     0,   114,   113,   115,     0,    31,
-       0,     0,    34,     0,     0,     0,     0,     0,     0,     0,
-      78,     0,     0,     0,     0,    63,    44,     0,     0,     0,
-       0,     0,    45,     6,     7,     8,    14,    88,    15,    16,
-      53,     0,     0,    50,     0,     0,     0,     0,     0,    50,
-       0,     0,   134,   133,   132,     0,     0,   125,   126,   127,
-     128,   129,     0,    54,    29,     0,   107,     0,     0,    36,
-       0,   105,    37,    50,     0,     0,    82,    80,    98,   106,
-      70,    90,    94,    95,    91,    92,    93,    13,    52,    22,
-       0,    65,    66,     0,    27,    50,    26,     0,   108,   130,
-     131,    55,     0,     0,    32,    33,     0,     0,    39,     0,
-       0,    12,    24,    23,    25,     0,     0,    56,    30,     0,
-      38,     0,    41,     0,   109,    57,     0,     0,     0,     0,
-     101,     0,     0,    42,     0,     0,     0,     0,   122,    89,
-     102,     0,    40,   123
-};
-
-/* YYDEFGOTO[NTERM-NUM].  */
-static const yytype_int16 yydefgoto[] =
-{
-      -1,     1,     3,    34,   165,    35,    37,   109,   111,   264,
-      84,    85,   182,    86,   174,    70,    71,    87,   102,   103,
-      88,   322,    89,   281,    90,   120,   331,   141,    92,    73,
-     127,   208,   128,   342,   129
-};
-
-/* YYPACT[STATE-NUM] -- Index in YYTABLE of the portion describing
-   STATE-NUM.  */
-#define YYPACT_NINF -130
-static const yytype_int16 yypact[] =
-{
-    -130,    12,  -130,   305,   -35,  -130,  -130,  -130,  -130,   -33,
-    -130,  -130,  -130,  -130,  -130,   427,   427,   427,  -130,   -33,
-     -33,  -130,  -130,  -130,  -130,  -130,  -130,   -33,   445,   370,
-     370,    10,   -24,  -130,  -130,   -30,  -130,   140,   140,   335,
-     -13,   -33,   449,   -13,   140,    70,   484,   -13,   359,   359,
-    -130,   114,  -130,   359,   359,    27,   -11,    62,    76,   167,
-    -130,     7,   171,   424,    64,   171,   167,   167,    65,   405,
-    -130,  -130,  -130,    68,    74,  -130,  -130,    78,  -130,    86,
-    -130,  -130,  -130,   402,  -130,  -130,    96,  -130,  -130,   107,
-    -130,    21,  -130,    74,   118,  -130,   359,   359,  -130,  -130,
-    -130,   359,   131,  -130,  -130,  -130,   150,   158,   473,  -130,
-      98,  -130,   155,   370,   187,    43,   192,   199,    65,   205,
-    -130,  -130,  -130,  -130,   262,   359,   359,   203,  -130,    90,
-    -130,   106,   164,   233,   359,   -33,  -130,   211,   223,    -3,
-    -130,   226,  -130,   231,   235,   240,    43,  -130,   220,   122,
-     608,   359,   359,   491,  -130,  -130,  -130,    74,   370,    43,
-     287,   291,   300,   301,   370,   305,   560,   582,  -130,    43,
-      43,   370,   114,  -130,  -130,  -130,  -130,   264,  -130,   267,
-    -130,    43,   279,    -4,   281,   122,   283,    65,    98,  -130,
-    -130,   164,   359,   359,   359,   345,   356,   359,   359,   359,
-     359,   359,  -130,    15,   306,  -130,  -130,  -130,   282,  -130,
-     307,   310,  -130,    32,   359,   308,   132,    32,    43,    43,
-    -130,   315,   316,   225,   321,  -130,  -130,   322,   405,   405,
-     405,   405,  -130,  -130,  -130,  -130,  -130,   311,  -130,  -130,
-     203,   204,   323,   -33,   333,    43,    43,    43,    43,   334,
-     331,   337,   631,   611,   547,   359,   359,   228,   228,  -130,
-    -130,  -130,   332,   371,  -130,   353,  -130,   357,     7,  -130,
-     350,   336,  -130,   -33,   340,   361,  -130,  -130,  -130,  -130,
-    -130,  -130,  -130,  -130,  -130,  -130,  -130,    43,  -130,  -130,
-     513,  -130,  -130,   360,  -130,   146,  -130,   384,  -130,   303,
-     303,   425,   399,    15,  -130,  -130,    43,    32,  -130,   373,
-      43,  -130,  -130,  -130,  -130,   375,   408,  -130,  -130,   383,
-    -130,    43,  -130,   385,  -130,  -130,   120,   390,    43,   380,
-    -130,   391,    43,  -130,   359,   120,   394,   275,   403,  -130,
-    -130,   359,  -130,   622
-};
-
-/* YYPGOTO[NTERM-NUM].  */
-static const yytype_int16 yypgoto[] =
-{
-    -130,  -130,  -130,   302,  -130,  -130,   589,    24,   362,   166,
-     -58,   411,   -57,    -8,  -130,   -61,   -43,    -7,    22,  -129,
-     -21,  -130,    72,    34,   -94,   -29,   137,  -130,   -51,     3,
-     -84,   286,    20,  -130,    61
-};
-
-/* YYTABLE[YYPACT[STATE-NUM]].  What to do in state STATE-NUM.  If
-   positive, shift that token.  If negative, reduce the rule which
-   number is the opposite.  If zero, do what YYDEFACT says.
-   If YYTABLE_NINF, syntax error.  */
-#define YYTABLE_NINF -65
-static const yytype_int16 yytable[] =
-{
-      91,    91,   116,   136,   209,   245,   215,   147,    91,    91,
-      91,   137,     2,   142,   143,    91,   104,   104,    55,    57,
-      58,    72,    94,   104,   262,   119,   178,   160,   161,    36,
-     162,   107,    41,    42,    98,    56,    56,    56,   135,    97,
-     148,    99,   100,    60,    61,   144,   145,   175,    74,    93,
-      93,    68,    41,   263,   154,   221,   222,   186,   132,    93,
-     106,    41,   112,   -64,   108,   117,   114,   113,   122,   123,
-     118,   121,    95,    96,   130,    83,   156,   163,    48,    49,
-      79,    80,    75,   138,    91,    76,   183,   134,   240,    77,
-      78,   222,   131,   192,   193,   194,   195,   196,   197,   198,
-     199,   200,   201,   157,   250,   180,   125,   126,    50,   105,
-     105,   176,    79,    80,    48,    49,   105,   148,    99,   100,
-     124,   168,   125,   126,    99,   100,   249,   133,   177,    91,
-     227,    52,   139,    93,   146,    91,   115,   149,   304,    69,
-     237,    54,    91,   150,    50,   189,   190,   151,   236,   238,
-     226,   204,   243,   210,   211,   152,   232,   166,   167,   212,
-     202,   158,   269,   239,    76,   272,   273,    52,    77,    78,
-     329,   330,   224,   123,   203,    53,   159,    54,    93,    75,
-      79,   271,    76,   164,    93,    75,    77,    78,    76,   292,
-     293,    93,    77,    78,    99,   100,   169,   274,   275,   282,
-     282,   282,   282,   205,   206,   207,    75,   246,   101,    76,
-     305,    41,   223,    77,    78,   170,   291,   183,   183,    79,
-      80,    99,   100,   171,   179,    99,   100,   294,   192,   193,
-     194,   195,   196,   197,   198,   199,   200,   201,   199,   200,
-     201,    48,    49,   205,   206,   207,   242,   312,   283,   283,
-     283,   283,   181,   252,   253,   254,   320,   184,   257,   258,
-     259,   260,   261,   284,   285,   286,   311,   289,   185,   188,
-     187,    50,   191,   296,   314,   270,   213,   319,   192,   193,
-     194,   195,   196,   197,   198,   199,   200,   201,   214,   323,
-     220,   216,   327,   228,    52,   278,   217,   308,   229,   333,
-     218,   101,    53,   336,    54,   219,     4,   230,   231,   242,
-     117,   197,   198,   199,   200,   201,   299,   300,     5,     6,
-       7,     8,     9,    10,    11,    12,    13,    14,    15,    16,
-      17,    18,    19,   241,    20,    21,    22,    23,    24,    25,
-      26,    27,    28,    48,    49,   340,   244,   247,   248,    29,
-      30,   255,   266,   192,   193,   194,   195,   196,   197,   198,
-     199,   200,   201,   256,    31,   225,    32,    48,    49,    33,
-     301,   265,   267,    50,    75,   268,   287,    76,    48,    49,
-     302,    77,    78,    79,    80,   276,   277,    81,    82,    99,
-     100,   279,   280,   288,    51,   337,    52,    50,   290,   295,
-     297,   307,   343,    83,    69,   309,    54,   298,    50,    75,
-      48,   153,    76,    48,    49,   306,    77,    78,    79,    80,
-      52,   303,    81,    82,   315,   101,   310,   313,    53,    51,
-      54,    52,    48,    49,   316,    48,    49,   317,    83,    69,
-      50,    54,   321,    50,    75,   324,   325,    76,   326,   334,
-     328,    77,    78,    48,    49,   332,   335,    48,    49,   154,
-     155,    51,    50,    52,   339,    50,    52,   233,   341,   318,
-     173,    69,   338,    54,    53,   140,    54,   251,    99,   100,
-       0,    48,    49,    50,     0,    52,    51,    50,    52,     0,
-       0,     0,     0,    53,     0,    54,    53,     0,    54,    48,
-      49,     0,     0,     0,    51,     0,    52,     0,   110,     0,
-      52,    50,     0,     0,    69,     0,    54,     0,    53,     0,
-      54,    48,    49,    75,     0,     0,    76,     0,     0,    50,
-      77,    78,   172,     0,    52,     0,     0,     0,    99,   100,
-       0,     0,    69,     0,    54,     0,     0,     0,   225,    41,
-       0,    50,    52,   195,   196,   197,   198,   199,   200,   201,
-      53,     0,    54,   192,   193,   194,   195,   196,   197,   198,
-     199,   200,   201,     0,    52,     0,     0,     0,     0,     0,
-       0,     0,    69,     0,    54,   192,   193,   194,   195,   196,
-     197,   198,   199,   200,   201,    38,    39,    40,     0,    43,
-      44,    45,    46,    47,     0,     0,     0,    59,     0,     0,
-      62,    63,    64,    65,    66,    67,   194,   195,   196,   197,
-     198,   199,   200,   201,   234,   192,   193,   194,   195,   196,
-     197,   198,   199,   200,   201,   193,   194,   195,   196,   197,
-     198,   199,   200,   201,     0,     0,   235,   205,   206,   207,
-      76,     0,     0,     0,    77,    78
-};
-
-static const yytype_int16 yycheck[] =
-{
-      29,    30,    45,    61,   133,     9,     9,    68,    37,    38,
-      39,    62,     0,    64,    65,    44,    37,    38,    15,    16,
-      17,    28,    30,    44,     9,    46,   110,     6,     7,    64,
-       9,    39,    65,     9,    64,    15,    16,    17,    59,    63,
-      69,    54,    55,    19,    20,    66,    67,   108,    28,    29,
-      30,    27,    65,    38,    57,   149,   150,   118,    69,    39,
-      38,    65,    42,    67,    40,    45,    44,    43,    48,    49,
-      46,    47,    62,    63,    54,    68,    83,    56,     8,     9,
-      48,    49,    39,    63,   113,    42,   115,    11,   172,    46,
-      47,   185,    65,     3,     4,     5,     6,     7,     8,     9,
-      10,    11,    12,    83,   188,   113,     8,     9,    38,    37,
-      38,   108,    48,    49,     8,     9,    44,   146,    54,    55,
-       6,   101,     8,     9,    54,    55,   187,    65,   108,   158,
-     159,    61,    68,   113,    69,   164,    66,    69,   267,    69,
-     169,    71,   171,    69,    38,   125,   126,    69,   169,   170,
-     158,   131,   181,   133,   134,    69,   164,    96,    97,   135,
-      70,    65,   213,   171,    42,   216,   217,    61,    46,    47,
-      50,    51,   152,   153,    68,    69,    69,    71,   158,    39,
-      48,    49,    42,    65,   164,    39,    46,    47,    42,   246,
-     247,   171,    46,    47,    54,    55,    65,   218,   219,   228,
-     229,   230,   231,    39,    40,    41,    39,   183,    68,    42,
-     268,    65,   151,    46,    47,    65,   245,   246,   247,    48,
-      49,    54,    55,    65,    69,    54,    55,   248,     3,     4,
-       5,     6,     7,     8,     9,    10,    11,    12,    10,    11,
-      12,     8,     9,    39,    40,    41,    42,   290,   228,   229,
-     230,   231,    65,   192,   193,   194,   307,    65,   197,   198,
-     199,   200,   201,   229,   230,   231,   287,   243,    69,     7,
-      65,    38,    69,   249,   295,   214,    65,   306,     3,     4,
-       5,     6,     7,     8,     9,    10,    11,    12,    65,   310,
-      70,    65,   321,     6,    61,    70,    65,   273,     7,   328,
-      65,    68,    69,   332,    71,    65,     1,     7,     7,    42,
-     290,     8,     9,    10,    11,    12,   255,   256,    13,    14,
-      15,    16,    17,    18,    19,    20,    21,    22,    23,    24,
-      25,    26,    27,    69,    29,    30,    31,    32,    33,    34,
-      35,    36,    37,     8,     9,    70,    67,    66,    65,    44,
-      45,     6,    70,     3,     4,     5,     6,     7,     8,     9,
-      10,    11,    12,     7,    59,    57,    61,     8,     9,    64,
-      38,    65,    65,    38,    39,    65,    65,    42,     8,     9,
-       9,    46,    47,    48,    49,    70,    70,    52,    53,    54,
-      55,    70,    70,    70,    59,   334,    61,    38,    65,    65,
-      69,    65,   341,    68,    69,    65,    71,    70,    38,    39,
-       8,     9,    42,     8,     9,    65,    46,    47,    48,    49,
-      61,    68,    52,    53,    40,    68,    65,    67,    69,    59,
-      71,    61,     8,     9,     9,     8,     9,    38,    68,    69,
-      38,    71,    69,    38,    39,    70,    38,    42,    65,    69,
-      65,    46,    47,     8,     9,    65,    65,     8,     9,    57,
-      58,    59,    38,    61,    70,    38,    61,   165,    65,   303,
-     108,    69,   335,    71,    69,    64,    71,   191,    54,    55,
-      -1,     8,     9,    38,    -1,    61,    59,    38,    61,    -1,
-      -1,    -1,    -1,    69,    -1,    71,    69,    -1,    71,     8,
-       9,    -1,    -1,    -1,    59,    -1,    61,    -1,    59,    -1,
-      61,    38,    -1,    -1,    69,    -1,    71,    -1,    69,    -1,
-      71,     8,     9,    39,    -1,    -1,    42,    -1,    -1,    38,
-      46,    47,    59,    -1,    61,    -1,    -1,    -1,    54,    55,
-      -1,    -1,    69,    -1,    71,    -1,    -1,    -1,    57,    65,
-      -1,    38,    61,     6,     7,     8,     9,    10,    11,    12,
-      69,    -1,    71,     3,     4,     5,     6,     7,     8,     9,
-      10,    11,    12,    -1,    61,    -1,    -1,    -1,    -1,    -1,
-      -1,    -1,    69,    -1,    71,     3,     4,     5,     6,     7,
-       8,     9,    10,    11,    12,     6,     7,     8,    -1,    10,
-      11,    12,    13,    14,    -1,    -1,    -1,    18,    -1,    -1,
-      21,    22,    23,    24,    25,    26,     5,     6,     7,     8,
-       9,    10,    11,    12,    64,     3,     4,     5,     6,     7,
-       8,     9,    10,    11,    12,     4,     5,     6,     7,     8,
-       9,    10,    11,    12,    -1,    -1,    64,    39,    40,    41,
-      42,    -1,    -1,    -1,    46,    47
-};
-
-/* YYSTOS[STATE-NUM] -- The (internal number of the) accessing
-   symbol of state STATE-NUM.  */
-static const yytype_uint8 yystos[] =
-{
-       0,    73,     0,    74,     1,    13,    14,    15,    16,    17,
-      18,    19,    20,    21,    22,    23,    24,    25,    26,    27,
-      29,    30,    31,    32,    33,    34,    35,    36,    37,    44,
-      45,    59,    61,    64,    75,    77,    64,    78,    78,    78,
-      78,    65,    79,    78,    78,    78,    78,    78,     8,     9,
-      38,    59,    61,    69,    71,   101,   104,   101,   101,    78,
-      79,    79,    78,    78,    78,    78,    78,    78,    79,    69,
-      87,    88,    89,   101,   104,    39,    42,    46,    47,    48,
-      49,    52,    53,    68,    82,    83,    85,    89,    92,    94,
-      96,    97,   100,   104,    85,    62,    63,    63,    64,    54,
-      55,    68,    90,    91,    92,    94,    90,    85,    79,    79,
-      59,    80,   104,    79,    90,    66,    88,   104,    79,    92,
-      97,    79,   104,   104,     6,     8,     9,   102,   104,   106,
-     104,    65,    69,    65,    11,    92,    82,   100,   104,    68,
-      83,    99,   100,   100,    92,    92,    69,    87,    97,    69,
-      69,    69,    69,     9,    57,    58,    89,   104,    65,    69,
-       6,     7,     9,    56,    65,    76,   106,   106,   104,    65,
-      65,    65,    59,    80,    86,    87,   101,   104,   102,    69,
-      85,    65,    84,    97,    65,    69,    87,    65,     7,   104,
-     104,    69,     3,     4,     5,     6,     7,     8,     9,    10,
-      11,    12,    70,    68,   104,    39,    40,    41,   103,    91,
-     104,   104,    79,    65,    65,     9,    65,    65,    65,    65,
-      70,    96,    96,   106,   104,    57,    85,    97,     6,     7,
-       7,     7,    85,    75,    64,    64,    92,    97,    92,    85,
-     102,    69,    42,    97,    67,     9,    79,    66,    65,    87,
-     102,   103,   106,   106,   106,     6,     7,   106,   106,   106,
-     106,   106,     9,    38,    81,    65,    70,    65,    65,   100,
-     106,    49,   100,   100,    92,    92,    70,    70,    70,    70,
-      70,    95,    97,   104,    95,    95,    95,    65,    70,    79,
-      65,    97,    84,    84,    92,    65,    79,    69,    70,   106,
-     106,    38,     9,    68,    91,    82,    65,    65,    79,    65,
-      65,    92,    88,    67,    92,    40,     9,    38,    81,    97,
-     100,    69,    93,    92,    70,    38,    65,    97,    65,    50,
-      51,    98,    65,    97,    69,    65,    97,   106,    98,    70,
-      70,    65,   105,   106
-};
-
-#define yyerrok                (yyerrstatus = 0)
-#define yyclearin      (yychar = YYEMPTY)
-#define YYEMPTY                (-2)
-#define YYEOF          0
-
-#define YYACCEPT       goto yyacceptlab
-#define YYABORT                goto yyabortlab
-#define YYERROR                goto yyerrorlab
-
-
-/* Like YYERROR except do call yyerror.  This remains here temporarily
-   to ease the transition to the new meaning of YYERROR, for GCC.
-   Once GCC version 2 has supplanted version 1, this can go.  */
-
-#define YYFAIL         goto yyerrlab
-
-#define YYRECOVERING()  (!!yyerrstatus)
-
-#define YYBACKUP(Token, Value)                                 \
-do                                                             \
-  if (yychar == YYEMPTY && yylen == 1)                         \
-    {                                                          \
-      yychar = (Token);                                                \
-      yylval = (Value);                                                \
-      yytoken = YYTRANSLATE (yychar);                          \
-      YYPOPSTACK (1);                                          \
-      goto yybackup;                                           \
-    }                                                          \
-  else                                                         \
-    {                                                          \
-      yyerror (YY_("syntax error: cannot back up")); \
-      YYERROR;                                                 \
-    }                                                          \
-while (YYID (0))
-
-
-#define YYTERROR       1
-#define YYERRCODE      256
-
-
-/* YYLLOC_DEFAULT -- Set CURRENT to span from RHS[1] to RHS[N].
-   If N is 0, then set CURRENT to the empty location which ends
-   the previous symbol: RHS[0] (always defined).  */
-
-#define YYRHSLOC(Rhs, K) ((Rhs)[K])
-#ifndef YYLLOC_DEFAULT
-# define YYLLOC_DEFAULT(Current, Rhs, N)                               \
-    do                                                                 \
-      if (YYID (N))                                                    \
-       {                                                               \
-         (Current).first_line   = YYRHSLOC (Rhs, 1).first_line;        \
-         (Current).first_column = YYRHSLOC (Rhs, 1).first_column;      \
-         (Current).last_line    = YYRHSLOC (Rhs, N).last_line;         \
-         (Current).last_column  = YYRHSLOC (Rhs, N).last_column;       \
-       }                                                               \
-      else                                                             \
-       {                                                               \
-         (Current).first_line   = (Current).last_line   =              \
-           YYRHSLOC (Rhs, 0).last_line;                                \
-         (Current).first_column = (Current).last_column =              \
-           YYRHSLOC (Rhs, 0).last_column;                              \
-       }                                                               \
-    while (YYID (0))
-#endif
-
-
-/* YY_LOCATION_PRINT -- Print the location on the stream.
-   This macro was not mandated originally: define only if we know
-   we won't break user code: when these are the locations we know.  */
-
-#ifndef YY_LOCATION_PRINT
-# if defined YYLTYPE_IS_TRIVIAL && YYLTYPE_IS_TRIVIAL
-#  define YY_LOCATION_PRINT(File, Loc)                 \
-     fprintf (File, "%d.%d-%d.%d",                     \
-             (Loc).first_line, (Loc).first_column,     \
-             (Loc).last_line,  (Loc).last_column)
-# else
-#  define YY_LOCATION_PRINT(File, Loc) ((void) 0)
-# endif
-#endif
-
-
-/* YYLEX -- calling `yylex' with the right arguments.  */
-
-#ifdef YYLEX_PARAM
-# define YYLEX yylex (YYLEX_PARAM)
-#else
-# define YYLEX yylex ()
-#endif
-
-/* Enable debugging if requested.  */
-#if YYDEBUG
-
-# ifndef YYFPRINTF
-#  include <stdio.h> /* INFRINGES ON USER NAME SPACE */
-#  define YYFPRINTF fprintf
-# endif
-
-# define YYDPRINTF(Args)                       \
-do {                                           \
-  if (yydebug)                                 \
-    YYFPRINTF Args;                            \
-} while (YYID (0))
-
-# define YY_SYMBOL_PRINT(Title, Type, Value, Location)                   \
-do {                                                                     \
-  if (yydebug)                                                           \
-    {                                                                    \
-      YYFPRINTF (stderr, "%s ", Title);                                          \
-      yy_symbol_print (stderr,                                           \
-                 Type, Value); \
-      YYFPRINTF (stderr, "\n");                                                  \
-    }                                                                    \
-} while (YYID (0))
-
-
-/*--------------------------------.
-| Print this symbol on YYOUTPUT.  |
-`--------------------------------*/
-
-/*ARGSUSED*/
-#if (defined __STDC__ || defined __C99__FUNC__ \
-     || defined __cplusplus || defined _MSC_VER)
-static void
-yy_symbol_value_print (FILE *yyoutput, int yytype, YYSTYPE const * const yyvaluep)
-#else
-static void
-yy_symbol_value_print (yyoutput, yytype, yyvaluep)
-    FILE *yyoutput;
-    int yytype;
-    YYSTYPE const * const yyvaluep;
-#endif
-{
-  if (!yyvaluep)
-    return;
-# ifdef YYPRINT
-  if (yytype < YYNTOKENS)
-    YYPRINT (yyoutput, yytoknum[yytype], *yyvaluep);
-# else
-  YYUSE (yyoutput);
-# endif
-  switch (yytype)
-    {
-      default:
-       break;
-    }
-}
-
-
-/*--------------------------------.
-| Print this symbol on YYOUTPUT.  |
-`--------------------------------*/
-
-#if (defined __STDC__ || defined __C99__FUNC__ \
-     || defined __cplusplus || defined _MSC_VER)
-static void
-yy_symbol_print (FILE *yyoutput, int yytype, YYSTYPE const * const yyvaluep)
-#else
-static void
-yy_symbol_print (yyoutput, yytype, yyvaluep)
-    FILE *yyoutput;
-    int yytype;
-    YYSTYPE const * const yyvaluep;
-#endif
-{
-  if (yytype < YYNTOKENS)
-    YYFPRINTF (yyoutput, "token %s (", yytname[yytype]);
-  else
-    YYFPRINTF (yyoutput, "nterm %s (", yytname[yytype]);
-
-  yy_symbol_value_print (yyoutput, yytype, yyvaluep);
-  YYFPRINTF (yyoutput, ")");
-}
-
-/*------------------------------------------------------------------.
-| yy_stack_print -- Print the state stack from its BOTTOM up to its |
-| TOP (included).                                                   |
-`------------------------------------------------------------------*/
-
-#if (defined __STDC__ || defined __C99__FUNC__ \
-     || defined __cplusplus || defined _MSC_VER)
-static void
-yy_stack_print (yytype_int16 *bottom, yytype_int16 *top)
-#else
-static void
-yy_stack_print (bottom, top)
-    yytype_int16 *bottom;
-    yytype_int16 *top;
-#endif
-{
-  YYFPRINTF (stderr, "Stack now");
-  for (; bottom <= top; ++bottom)
-    YYFPRINTF (stderr, " %d", *bottom);
-  YYFPRINTF (stderr, "\n");
-}
-
-# define YY_STACK_PRINT(Bottom, Top)                           \
-do {                                                           \
-  if (yydebug)                                                 \
-    yy_stack_print ((Bottom), (Top));                          \
-} while (YYID (0))
-
-
-/*------------------------------------------------.
-| Report that the YYRULE is going to be reduced.  |
-`------------------------------------------------*/
-
-#if (defined __STDC__ || defined __C99__FUNC__ \
-     || defined __cplusplus || defined _MSC_VER)
-static void
-yy_reduce_print (YYSTYPE *yyvsp, int yyrule)
-#else
-static void
-yy_reduce_print (yyvsp, yyrule)
-    YYSTYPE *yyvsp;
-    int yyrule;
-#endif
-{
-  int yynrhs = yyr2[yyrule];
-  int yyi;
-  unsigned long int yylno = yyrline[yyrule];
-  YYFPRINTF (stderr, "Reducing stack by rule %d (line %lu):\n",
-            yyrule - 1, yylno);
-  /* The symbols being reduced.  */
-  for (yyi = 0; yyi < yynrhs; yyi++)
-    {
-      fprintf (stderr, "   $%d = ", yyi + 1);
-      yy_symbol_print (stderr, yyrhs[yyprhs[yyrule] + yyi],
-                      &(yyvsp[(yyi + 1) - (yynrhs)])
-                                      );
-      fprintf (stderr, "\n");
-    }
-}
-
-# define YY_REDUCE_PRINT(Rule)         \
-do {                                   \
-  if (yydebug)                         \
-    yy_reduce_print (yyvsp, Rule); \
-} while (YYID (0))
-
-/* Nonzero means print parse trace.  It is left uninitialized so that
-   multiple parsers can coexist.  */
-int yydebug;
-#else /* !YYDEBUG */
-# define YYDPRINTF(Args)
-# define YY_SYMBOL_PRINT(Title, Type, Value, Location)
-# define YY_STACK_PRINT(Bottom, Top)
-# define YY_REDUCE_PRINT(Rule)
-#endif /* !YYDEBUG */
-
-
-/* YYINITDEPTH -- initial size of the parser's stacks.  */
-#ifndef        YYINITDEPTH
-# define YYINITDEPTH 200
-#endif
-
-/* YYMAXDEPTH -- maximum size the stacks can grow to (effective only
-   if the built-in stack extension method is used).
-
-   Do not make this value too large; the results are undefined if
-   YYSTACK_ALLOC_MAXIMUM < YYSTACK_BYTES (YYMAXDEPTH)
-   evaluated with infinite-precision integer arithmetic.  */
-
-#ifndef YYMAXDEPTH
-# define YYMAXDEPTH 10000
-#endif
-
-\f
-
-#if YYERROR_VERBOSE
-
-# ifndef yystrlen
-#  if defined __GLIBC__ && defined _STRING_H
-#   define yystrlen strlen
-#  else
-/* Return the length of YYSTR.  */
-#if (defined __STDC__ || defined __C99__FUNC__ \
-     || defined __cplusplus || defined _MSC_VER)
-static YYSIZE_T
-yystrlen (const char *yystr)
-#else
-static YYSIZE_T
-yystrlen (yystr)
-    const char *yystr;
-#endif
-{
-  YYSIZE_T yylen;
-  for (yylen = 0; yystr[yylen]; yylen++)
-    continue;
-  return yylen;
-}
-#  endif
-# endif
-
-# ifndef yystpcpy
-#  if defined __GLIBC__ && defined _STRING_H && defined _GNU_SOURCE
-#   define yystpcpy stpcpy
-#  else
-/* Copy YYSRC to YYDEST, returning the address of the terminating '\0' in
-   YYDEST.  */
-#if (defined __STDC__ || defined __C99__FUNC__ \
-     || defined __cplusplus || defined _MSC_VER)
-static char *
-yystpcpy (char *yydest, const char *yysrc)
-#else
-static char *
-yystpcpy (yydest, yysrc)
-    char *yydest;
-    const char *yysrc;
-#endif
-{
-  char *yyd = yydest;
-  const char *yys = yysrc;
-
-  while ((*yyd++ = *yys++) != '\0')
-    continue;
-
-  return yyd - 1;
-}
-#  endif
-# endif
-
-# ifndef yytnamerr
-/* Copy to YYRES the contents of YYSTR after stripping away unnecessary
-   quotes and backslashes, so that it's suitable for yyerror.  The
-   heuristic is that double-quoting is unnecessary unless the string
-   contains an apostrophe, a comma, or backslash (other than
-   backslash-backslash).  YYSTR is taken from yytname.  If YYRES is
-   null, do not copy; instead, return the length of what the result
-   would have been.  */
-static YYSIZE_T
-yytnamerr (char *yyres, const char *yystr)
-{
-  if (*yystr == '"')
-    {
-      YYSIZE_T yyn = 0;
-      char const *yyp = yystr;
-
-      for (;;)
-       switch (*++yyp)
-         {
-         case '\'':
-         case ',':
-           goto do_not_strip_quotes;
-
-         case '\\':
-           if (*++yyp != '\\')
-             goto do_not_strip_quotes;
-           /* Fall through.  */
-         default:
-           if (yyres)
-             yyres[yyn] = *yyp;
-           yyn++;
-           break;
-
-         case '"':
-           if (yyres)
-             yyres[yyn] = '\0';
-           return yyn;
-         }
-    do_not_strip_quotes: ;
-    }
-
-  if (! yyres)
-    return yystrlen (yystr);
-
-  return yystpcpy (yyres, yystr) - yyres;
-}
-# endif
-
-/* Copy into YYRESULT an error message about the unexpected token
-   YYCHAR while in state YYSTATE.  Return the number of bytes copied,
-   including the terminating null byte.  If YYRESULT is null, do not
-   copy anything; just return the number of bytes that would be
-   copied.  As a special case, return 0 if an ordinary "syntax error"
-   message will do.  Return YYSIZE_MAXIMUM if overflow occurs during
-   size calculation.  */
-static YYSIZE_T
-yysyntax_error (char *yyresult, int yystate, int yychar)
-{
-  int yyn = yypact[yystate];
-
-  if (! (YYPACT_NINF < yyn && yyn <= YYLAST))
-    return 0;
-  else
-    {
-      int yytype = YYTRANSLATE (yychar);
-      YYSIZE_T yysize0 = yytnamerr (0, yytname[yytype]);
-      YYSIZE_T yysize = yysize0;
-      YYSIZE_T yysize1;
-      int yysize_overflow = 0;
-      enum { YYERROR_VERBOSE_ARGS_MAXIMUM = 5 };
-      char const *yyarg[YYERROR_VERBOSE_ARGS_MAXIMUM];
-      int yyx;
-
-# if 0
-      /* This is so xgettext sees the translatable formats that are
-        constructed on the fly.  */
-      YY_("syntax error, unexpected %s");
-      YY_("syntax error, unexpected %s, expecting %s");
-      YY_("syntax error, unexpected %s, expecting %s or %s");
-      YY_("syntax error, unexpected %s, expecting %s or %s or %s");
-      YY_("syntax error, unexpected %s, expecting %s or %s or %s or %s");
-# endif
-      char *yyfmt;
-      char const *yyf;
-      static char const yyunexpected[] = "syntax error, unexpected %s";
-      static char const yyexpecting[] = ", expecting %s";
-      static char const yyor[] = " or %s";
-      char yyformat[sizeof yyunexpected
-                   + sizeof yyexpecting - 1
-                   + ((YYERROR_VERBOSE_ARGS_MAXIMUM - 2)
-                      * (sizeof yyor - 1))];
-      char const *yyprefix = yyexpecting;
-
-      /* Start YYX at -YYN if negative to avoid negative indexes in
-        YYCHECK.  */
-      int yyxbegin = yyn < 0 ? -yyn : 0;
-
-      /* Stay within bounds of both yycheck and yytname.  */
-      int yychecklim = YYLAST - yyn + 1;
-      int yyxend = yychecklim < YYNTOKENS ? yychecklim : YYNTOKENS;
-      int yycount = 1;
-
-      yyarg[0] = yytname[yytype];
-      yyfmt = yystpcpy (yyformat, yyunexpected);
-
-      for (yyx = yyxbegin; yyx < yyxend; ++yyx)
-       if (yycheck[yyx + yyn] == yyx && yyx != YYTERROR)
-         {
-           if (yycount == YYERROR_VERBOSE_ARGS_MAXIMUM)
-             {
-               yycount = 1;
-               yysize = yysize0;
-               yyformat[sizeof yyunexpected - 1] = '\0';
-               break;
-             }
-           yyarg[yycount++] = yytname[yyx];
-           yysize1 = yysize + yytnamerr (0, yytname[yyx]);
-           yysize_overflow |= (yysize1 < yysize);
-           yysize = yysize1;
-           yyfmt = yystpcpy (yyfmt, yyprefix);
-           yyprefix = yyor;
-         }
-
-      yyf = YY_(yyformat);
-      yysize1 = yysize + yystrlen (yyf);
-      yysize_overflow |= (yysize1 < yysize);
-      yysize = yysize1;
-
-      if (yysize_overflow)
-       return YYSIZE_MAXIMUM;
-
-      if (yyresult)
-       {
-         /* Avoid sprintf, as that infringes on the user's name space.
-            Don't have undefined behavior even if the translation
-            produced a string with the wrong number of "%s"s.  */
-         char *yyp = yyresult;
-         int yyi = 0;
-         while ((*yyp = *yyf) != '\0')
-           {
-             if (*yyp == '%' && yyf[1] == 's' && yyi < yycount)
-               {
-                 yyp += yytnamerr (yyp, yyarg[yyi++]);
-                 yyf += 2;
-               }
-             else
-               {
-                 yyp++;
-                 yyf++;
-               }
-           }
-       }
-      return yysize;
-    }
-}
-#endif /* YYERROR_VERBOSE */
-\f
-
-/*-----------------------------------------------.
-| Release the memory associated to this symbol.  |
-`-----------------------------------------------*/
-
-/*ARGSUSED*/
-#if (defined __STDC__ || defined __C99__FUNC__ \
-     || defined __cplusplus || defined _MSC_VER)
-static void
-yydestruct (const char *yymsg, int yytype, YYSTYPE *yyvaluep)
-#else
-static void
-yydestruct (yymsg, yytype, yyvaluep)
-    const char *yymsg;
-    int yytype;
-    YYSTYPE *yyvaluep;
-#endif
-{
-  YYUSE (yyvaluep);
-
-  if (!yymsg)
-    yymsg = "Deleting";
-  YY_SYMBOL_PRINT (yymsg, yytype, yyvaluep, yylocationp);
-
-  switch (yytype)
-    {
-
-      default:
-       break;
-    }
-}
-\f
-
-/* Prevent warnings from -Wmissing-prototypes.  */
-
-#ifdef YYPARSE_PARAM
-#if defined __STDC__ || defined __cplusplus
-int yyparse (void *YYPARSE_PARAM);
-#else
-int yyparse ();
-#endif
-#else /* ! YYPARSE_PARAM */
-#if defined __STDC__ || defined __cplusplus
-int yyparse (void);
-#else
-int yyparse ();
-#endif
-#endif /* ! YYPARSE_PARAM */
-
-
-
-/* The look-ahead symbol.  */
-int yychar;
-
-/* The semantic value of the look-ahead symbol.  */
-YYSTYPE yylval;
-
-/* Number of syntax errors so far.  */
-int yynerrs;
-
-
-
-/*----------.
-| yyparse.  |
-`----------*/
-
-#ifdef YYPARSE_PARAM
-#if (defined __STDC__ || defined __C99__FUNC__ \
-     || defined __cplusplus || defined _MSC_VER)
-int
-yyparse (void *YYPARSE_PARAM)
-#else
-int
-yyparse (YYPARSE_PARAM)
-    void *YYPARSE_PARAM;
-#endif
-#else /* ! YYPARSE_PARAM */
-#if (defined __STDC__ || defined __C99__FUNC__ \
-     || defined __cplusplus || defined _MSC_VER)
-int
-yyparse (void)
-#else
-int
-yyparse ()
-
-#endif
-#endif
-{
-  
-  int yystate;
-  int yyn;
-  int yyresult;
-  /* Number of tokens to shift before error messages enabled.  */
-  int yyerrstatus;
-  /* Look-ahead token as an internal (translated) token number.  */
-  int yytoken = 0;
-#if YYERROR_VERBOSE
-  /* Buffer for error messages, and its allocated size.  */
-  char yymsgbuf[128];
-  char *yymsg = yymsgbuf;
-  YYSIZE_T yymsg_alloc = sizeof yymsgbuf;
-#endif
-
-  /* Three stacks and their tools:
-     `yyss': related to states,
-     `yyvs': related to semantic values,
-     `yyls': related to locations.
-
-     Refer to the stacks thru separate pointers, to allow yyoverflow
-     to reallocate them elsewhere.  */
-
-  /* The state stack.  */
-  yytype_int16 yyssa[YYINITDEPTH];
-  yytype_int16 *yyss = yyssa;
-  yytype_int16 *yyssp;
-
-  /* The semantic value stack.  */
-  YYSTYPE yyvsa[YYINITDEPTH];
-  YYSTYPE *yyvs = yyvsa;
-  YYSTYPE *yyvsp;
-
-
-
-#define YYPOPSTACK(N)   (yyvsp -= (N), yyssp -= (N))
-
-  YYSIZE_T yystacksize = YYINITDEPTH;
-
-  /* The variables used to return semantic value and location from the
-     action routines.  */
-  YYSTYPE yyval;
-
-
-  /* The number of symbols on the RHS of the reduced rule.
-     Keep to zero when no symbol should be popped.  */
-  int yylen = 0;
-
-  YYDPRINTF ((stderr, "Starting parse\n"));
-
-  yystate = 0;
-  yyerrstatus = 0;
-  yynerrs = 0;
-  yychar = YYEMPTY;            /* Cause a token to be read.  */
-
-  /* Initialize stack pointers.
-     Waste one element of value and location stack
-     so that they stay on the same level as the state stack.
-     The wasted elements are never initialized.  */
-
-  yyssp = yyss;
-  yyvsp = yyvs;
-
-  goto yysetstate;
-
-/*------------------------------------------------------------.
-| yynewstate -- Push a new state, which is found in yystate.  |
-`------------------------------------------------------------*/
- yynewstate:
-  /* In all cases, when you get here, the value and location stacks
-     have just been pushed.  So pushing a state here evens the stacks.  */
-  yyssp++;
-
- yysetstate:
-  *yyssp = yystate;
-
-  if (yyss + yystacksize - 1 <= yyssp)
-    {
-      /* Get the current used size of the three stacks, in elements.  */
-      YYSIZE_T yysize = yyssp - yyss + 1;
-
-#ifdef yyoverflow
-      {
-       /* Give user a chance to reallocate the stack.  Use copies of
-          these so that the &'s don't force the real ones into
-          memory.  */
-       YYSTYPE *yyvs1 = yyvs;
-       yytype_int16 *yyss1 = yyss;
-
-
-       /* Each stack pointer address is followed by the size of the
-          data in use in that stack, in bytes.  This used to be a
-          conditional around just the two extra args, but that might
-          be undefined if yyoverflow is a macro.  */
-       yyoverflow (YY_("memory exhausted"),
-                   &yyss1, yysize * sizeof (*yyssp),
-                   &yyvs1, yysize * sizeof (*yyvsp),
-
-                   &yystacksize);
-
-       yyss = yyss1;
-       yyvs = yyvs1;
-      }
-#else /* no yyoverflow */
-# ifndef YYSTACK_RELOCATE
-      goto yyexhaustedlab;
-# else
-      /* Extend the stack our own way.  */
-      if (YYMAXDEPTH <= yystacksize)
-       goto yyexhaustedlab;
-      yystacksize *= 2;
-      if (YYMAXDEPTH < yystacksize)
-       yystacksize = YYMAXDEPTH;
-
-      {
-       yytype_int16 *yyss1 = yyss;
-       union yyalloc *yyptr =
-         (union yyalloc *) YYSTACK_ALLOC (YYSTACK_BYTES (yystacksize));
-       if (! yyptr)
-         goto yyexhaustedlab;
-       YYSTACK_RELOCATE (yyss);
-       YYSTACK_RELOCATE (yyvs);
-
-#  undef YYSTACK_RELOCATE
-       if (yyss1 != yyssa)
-         YYSTACK_FREE (yyss1);
-      }
-# endif
-#endif /* no yyoverflow */
-
-      yyssp = yyss + yysize - 1;
-      yyvsp = yyvs + yysize - 1;
-
-
-      YYDPRINTF ((stderr, "Stack size increased to %lu\n",
-                 (unsigned long int) yystacksize));
-
-      if (yyss + yystacksize - 1 <= yyssp)
-       YYABORT;
-    }
-
-  YYDPRINTF ((stderr, "Entering state %d\n", yystate));
-
-  goto yybackup;
-
-/*-----------.
-| yybackup.  |
-`-----------*/
-yybackup:
-
-  /* Do appropriate processing given the current state.  Read a
-     look-ahead token if we need one and don't already have one.  */
-
-  /* First try to decide what to do without reference to look-ahead token.  */
-  yyn = yypact[yystate];
-  if (yyn == YYPACT_NINF)
-    goto yydefault;
-
-  /* Not known => get a look-ahead token if don't already have one.  */
-
-  /* YYCHAR is either YYEMPTY or YYEOF or a valid look-ahead symbol.  */
-  if (yychar == YYEMPTY)
-    {
-      YYDPRINTF ((stderr, "Reading a token: "));
-      yychar = YYLEX;
-    }
-
-  if (yychar <= YYEOF)
-    {
-      yychar = yytoken = YYEOF;
-      YYDPRINTF ((stderr, "Now at end of input.\n"));
-    }
-  else
-    {
-      yytoken = YYTRANSLATE (yychar);
-      YY_SYMBOL_PRINT ("Next token is", yytoken, &yylval, &yylloc);
-    }
-
-  /* If the proper action on seeing token YYTOKEN is to reduce or to
-     detect an error, take that action.  */
-  yyn += yytoken;
-  if (yyn < 0 || YYLAST < yyn || yycheck[yyn] != yytoken)
-    goto yydefault;
-  yyn = yytable[yyn];
-  if (yyn <= 0)
-    {
-      if (yyn == 0 || yyn == YYTABLE_NINF)
-       goto yyerrlab;
-      yyn = -yyn;
-      goto yyreduce;
-    }
-
-  if (yyn == YYFINAL)
-    YYACCEPT;
-
-  /* Count tokens shifted since error; after three, turn off error
-     status.  */
-  if (yyerrstatus)
-    yyerrstatus--;
-
-  /* Shift the look-ahead token.  */
-  YY_SYMBOL_PRINT ("Shifting", yytoken, &yylval, &yylloc);
-
-  /* Discard the shifted token unless it is eof.  */
-  if (yychar != YYEOF)
-    yychar = YYEMPTY;
-
-  yystate = yyn;
-  *++yyvsp = yylval;
-
-  goto yynewstate;
-
-
-/*-----------------------------------------------------------.
-| yydefault -- do the default action for the current state.  |
-`-----------------------------------------------------------*/
-yydefault:
-  yyn = yydefact[yystate];
-  if (yyn == 0)
-    goto yyerrlab;
-  goto yyreduce;
-
-
-/*-----------------------------.
-| yyreduce -- Do a reduction.  |
-`-----------------------------*/
-yyreduce:
-  /* yyn is the number of a rule to reduce with.  */
-  yylen = yyr2[yyn];
-
-  /* If YYLEN is nonzero, implement the default value of the action:
-     `$$ = $1'.
-
-     Otherwise, the following line sets YYVAL to garbage.
-     This behavior is undocumented and Bison
-     users should not rely upon it.  Assigning to YYVAL
-     unconditionally makes the parser a bit smaller, and it avoids a
-     GCC warning that YYVAL may be used uninitialized.  */
-  yyval = yyvsp[1-yylen];
-
-
-  YY_REDUCE_PRINT (yyn);
-  switch (yyn)
-    {
-        case 3:
-#line 70 "a.y"
-    {
-               stmtline = lineno;
-       }
-    break;
-
-  case 5:
-#line 77 "a.y"
-    {
-               (yyvsp[(1) - (2)].sym) = labellookup((yyvsp[(1) - (2)].sym));
-               if((yyvsp[(1) - (2)].sym)->type == LLAB && (yyvsp[(1) - (2)].sym)->value != pc)
-                       yyerror("redeclaration of %s", (yyvsp[(1) - (2)].sym)->labelname);
-               (yyvsp[(1) - (2)].sym)->type = LLAB;
-               (yyvsp[(1) - (2)].sym)->value = pc;
-       }
-    break;
-
-  case 7:
-#line 86 "a.y"
-    {
-               (yyvsp[(1) - (4)].sym)->type = LVAR;
-               (yyvsp[(1) - (4)].sym)->value = (yyvsp[(3) - (4)].lval);
-       }
-    break;
-
-  case 8:
-#line 91 "a.y"
-    {
-               if((yyvsp[(1) - (4)].sym)->value != (yyvsp[(3) - (4)].lval))
-                       yyerror("redeclaration of %s", (yyvsp[(1) - (4)].sym)->name);
-               (yyvsp[(1) - (4)].sym)->value = (yyvsp[(3) - (4)].lval);
-       }
-    break;
-
-  case 12:
-#line 105 "a.y"
-    {
-               outcode((yyvsp[(1) - (7)].lval), (yyvsp[(2) - (7)].lval), &(yyvsp[(3) - (7)].addr), (yyvsp[(5) - (7)].lval), &(yyvsp[(7) - (7)].addr));
-       }
-    break;
-
-  case 13:
-#line 109 "a.y"
-    {
-               outcode((yyvsp[(1) - (6)].lval), (yyvsp[(2) - (6)].lval), &(yyvsp[(3) - (6)].addr), (yyvsp[(5) - (6)].lval), &nullgen);
-       }
-    break;
-
-  case 14:
-#line 113 "a.y"
-    {
-               outcode((yyvsp[(1) - (5)].lval), (yyvsp[(2) - (5)].lval), &(yyvsp[(3) - (5)].addr), 0, &(yyvsp[(5) - (5)].addr));
-       }
-    break;
-
-  case 15:
-#line 120 "a.y"
-    {
-               outcode((yyvsp[(1) - (5)].lval), (yyvsp[(2) - (5)].lval), &(yyvsp[(3) - (5)].addr), 0, &(yyvsp[(5) - (5)].addr));
-       }
-    break;
-
-  case 16:
-#line 127 "a.y"
-    {
-               outcode((yyvsp[(1) - (5)].lval), (yyvsp[(2) - (5)].lval), &(yyvsp[(3) - (5)].addr), 0, &(yyvsp[(5) - (5)].addr));
-       }
-    break;
-
-  case 17:
-#line 134 "a.y"
-    {
-               outcode((yyvsp[(1) - (4)].lval), (yyvsp[(2) - (4)].lval), &nullgen, 0, &(yyvsp[(4) - (4)].addr));
-       }
-    break;
-
-  case 18:
-#line 138 "a.y"
-    {
-               outcode((yyvsp[(1) - (4)].lval), (yyvsp[(2) - (4)].lval), &nullgen, 0, &(yyvsp[(4) - (4)].addr));
-       }
-    break;
-
-  case 19:
-#line 145 "a.y"
-    {
-               outcode((yyvsp[(1) - (3)].lval), Always, &nullgen, 0, &(yyvsp[(3) - (3)].addr));
-       }
-    break;
-
-  case 20:
-#line 152 "a.y"
-    {
-               outcode((yyvsp[(1) - (3)].lval), Always, &nullgen, 0, &(yyvsp[(3) - (3)].addr));
-       }
-    break;
-
-  case 21:
-#line 159 "a.y"
-    {
-               outcode((yyvsp[(1) - (4)].lval), (yyvsp[(2) - (4)].lval), &nullgen, 0, &(yyvsp[(4) - (4)].addr));
-       }
-    break;
-
-  case 22:
-#line 166 "a.y"
-    {
-               outcode((yyvsp[(1) - (6)].lval), (yyvsp[(2) - (6)].lval), &(yyvsp[(3) - (6)].addr), (yyvsp[(5) - (6)].lval), &nullgen);
-       }
-    break;
-
-  case 23:
-#line 173 "a.y"
-    {
-               Addr g;
-
-               g = nullgen;
-               g.type = TYPE_CONST;
-               g.offset = (yyvsp[(6) - (7)].lval);
-               outcode((yyvsp[(1) - (7)].lval), (yyvsp[(2) - (7)].lval), &(yyvsp[(3) - (7)].addr), 0, &g);
-       }
-    break;
-
-  case 24:
-#line 182 "a.y"
-    {
-               Addr g;
-
-               g = nullgen;
-               g.type = TYPE_CONST;
-               g.offset = (yyvsp[(4) - (7)].lval);
-               outcode((yyvsp[(1) - (7)].lval), (yyvsp[(2) - (7)].lval), &g, 0, &(yyvsp[(7) - (7)].addr));
-       }
-    break;
-
-  case 25:
-#line 194 "a.y"
-    {
-               outcode((yyvsp[(1) - (7)].lval), (yyvsp[(2) - (7)].lval), &(yyvsp[(5) - (7)].addr), (yyvsp[(3) - (7)].addr).reg, &(yyvsp[(7) - (7)].addr));
-       }
-    break;
-
-  case 26:
-#line 198 "a.y"
-    {
-               outcode((yyvsp[(1) - (6)].lval), (yyvsp[(2) - (6)].lval), &(yyvsp[(5) - (6)].addr), (yyvsp[(3) - (6)].addr).reg, &(yyvsp[(3) - (6)].addr));
-       }
-    break;
-
-  case 27:
-#line 202 "a.y"
-    {
-               outcode((yyvsp[(1) - (6)].lval), (yyvsp[(2) - (6)].lval), &(yyvsp[(4) - (6)].addr), (yyvsp[(6) - (6)].addr).reg, &(yyvsp[(6) - (6)].addr));
-       }
-    break;
-
-  case 28:
-#line 209 "a.y"
-    {
-               outcode((yyvsp[(1) - (3)].lval), (yyvsp[(2) - (3)].lval), &nullgen, 0, &nullgen);
-       }
-    break;
-
-  case 29:
-#line 216 "a.y"
-    {
-               settext((yyvsp[(2) - (5)].addr).sym);
-               outcode((yyvsp[(1) - (5)].lval), Always, &(yyvsp[(2) - (5)].addr), 0, &(yyvsp[(5) - (5)].addr));
-       }
-    break;
-
-  case 30:
-#line 221 "a.y"
-    {
-               settext((yyvsp[(2) - (7)].addr).sym);
-               outcode((yyvsp[(1) - (7)].lval), Always, &(yyvsp[(2) - (7)].addr), 0, &(yyvsp[(7) - (7)].addr));
-               if(pass > 1) {
-                       lastpc->from3.type = TYPE_CONST;
-                       lastpc->from3.offset = (yyvsp[(4) - (7)].lval);
-               }
-       }
-    break;
-
-  case 31:
-#line 233 "a.y"
-    {
-               settext((yyvsp[(2) - (4)].addr).sym);
-               outcode((yyvsp[(1) - (4)].lval), Always, &(yyvsp[(2) - (4)].addr), 0, &(yyvsp[(4) - (4)].addr));
-       }
-    break;
-
-  case 32:
-#line 238 "a.y"
-    {
-               settext((yyvsp[(2) - (6)].addr).sym);
-               outcode((yyvsp[(1) - (6)].lval), Always, &(yyvsp[(2) - (6)].addr), 0, &(yyvsp[(6) - (6)].addr));
-               if(pass > 1) {
-                       lastpc->from3.type = TYPE_CONST;
-                       lastpc->from3.offset = (yyvsp[(4) - (6)].lval);
-               }
-       }
-    break;
-
-  case 33:
-#line 250 "a.y"
-    {
-               outcode((yyvsp[(1) - (6)].lval), Always, &(yyvsp[(2) - (6)].addr), 0, &(yyvsp[(6) - (6)].addr));
-               if(pass > 1) {
-                       lastpc->from3.type = TYPE_CONST;
-                       lastpc->from3.offset = (yyvsp[(4) - (6)].lval);
-               }
-       }
-    break;
-
-  case 34:
-#line 261 "a.y"
-    {
-               outcode((yyvsp[(1) - (4)].lval), (yyvsp[(2) - (4)].lval), &(yyvsp[(3) - (4)].addr), 0, &nullgen);
-       }
-    break;
-
-  case 35:
-#line 268 "a.y"
-    {
-               outcode((yyvsp[(1) - (3)].lval), Always, &nullgen, 0, &(yyvsp[(3) - (3)].addr));
-       }
-    break;
-
-  case 36:
-#line 275 "a.y"
-    {
-               outcode((yyvsp[(1) - (5)].lval), (yyvsp[(2) - (5)].lval), &(yyvsp[(3) - (5)].addr), 0, &(yyvsp[(5) - (5)].addr));
-       }
-    break;
-
-  case 37:
-#line 279 "a.y"
-    {
-               outcode((yyvsp[(1) - (5)].lval), (yyvsp[(2) - (5)].lval), &(yyvsp[(3) - (5)].addr), 0, &(yyvsp[(5) - (5)].addr));
-       }
-    break;
-
-  case 38:
-#line 283 "a.y"
-    {
-               outcode((yyvsp[(1) - (7)].lval), (yyvsp[(2) - (7)].lval), &(yyvsp[(3) - (7)].addr), (yyvsp[(5) - (7)].lval), &(yyvsp[(7) - (7)].addr));
-       }
-    break;
-
-  case 39:
-#line 287 "a.y"
-    {
-               outcode((yyvsp[(1) - (6)].lval), (yyvsp[(2) - (6)].lval), &(yyvsp[(3) - (6)].addr), (yyvsp[(5) - (6)].addr).reg, &nullgen);
-       }
-    break;
-
-  case 40:
-#line 294 "a.y"
-    {
-               Addr g;
-
-               g = nullgen;
-               g.type = TYPE_CONST;
-               g.offset =
-                       (0xe << 24) |           /* opcode */
-                       ((yyvsp[(1) - (12)].lval) << 20) |              /* MCR/MRC */
-                       (((yyvsp[(2) - (12)].lval)^C_SCOND_XOR) << 28) |                /* scond */
-                       (((yyvsp[(3) - (12)].lval) & 15) << 8) |        /* coprocessor number */
-                       (((yyvsp[(5) - (12)].lval) & 7) << 21) |        /* coprocessor operation */
-                       (((yyvsp[(7) - (12)].lval) & 15) << 12) |       /* arm register */
-                       (((yyvsp[(9) - (12)].lval) & 15) << 16) |       /* Crn */
-                       (((yyvsp[(11) - (12)].lval) & 15) << 0) |       /* Crm */
-                       (((yyvsp[(12) - (12)].lval) & 7) << 5) |        /* coprocessor information */
-                       (1<<4);                 /* must be set */
-               outcode(AMRC, Always, &nullgen, 0, &g);
-       }
-    break;
-
-  case 41:
-#line 316 "a.y"
-    {
-               outcode((yyvsp[(1) - (7)].lval), (yyvsp[(2) - (7)].lval), &(yyvsp[(3) - (7)].addr), (yyvsp[(5) - (7)].addr).reg, &(yyvsp[(7) - (7)].addr));
-       }
-    break;
-
-  case 42:
-#line 324 "a.y"
-    {
-               (yyvsp[(7) - (9)].addr).type = TYPE_REGREG2;
-               (yyvsp[(7) - (9)].addr).offset = (yyvsp[(9) - (9)].lval);
-               outcode((yyvsp[(1) - (9)].lval), (yyvsp[(2) - (9)].lval), &(yyvsp[(3) - (9)].addr), (yyvsp[(5) - (9)].addr).reg, &(yyvsp[(7) - (9)].addr));
-       }
-    break;
-
-  case 43:
-#line 333 "a.y"
-    {
-               outcode((yyvsp[(1) - (2)].lval), Always, &(yyvsp[(2) - (2)].addr), 0, &nullgen);
-       }
-    break;
-
-  case 44:
-#line 340 "a.y"
-    {
-               if((yyvsp[(2) - (4)].addr).type != TYPE_CONST || (yyvsp[(4) - (4)].addr).type != TYPE_CONST)
-                       yyerror("arguments to PCDATA must be integer constants");
-               outcode((yyvsp[(1) - (4)].lval), Always, &(yyvsp[(2) - (4)].addr), 0, &(yyvsp[(4) - (4)].addr));
-       }
-    break;
-
-  case 45:
-#line 349 "a.y"
-    {
-               if((yyvsp[(2) - (4)].addr).type != TYPE_CONST)
-                       yyerror("index for FUNCDATA must be integer constant");
-               if((yyvsp[(4) - (4)].addr).type != NAME_EXTERN && (yyvsp[(4) - (4)].addr).type != NAME_STATIC && (yyvsp[(4) - (4)].addr).type != TYPE_MEM)
-                       yyerror("value for FUNCDATA must be symbol reference");
-               outcode((yyvsp[(1) - (4)].lval), Always, &(yyvsp[(2) - (4)].addr), 0, &(yyvsp[(4) - (4)].addr));
-       }
-    break;
-
-  case 46:
-#line 360 "a.y"
-    {
-               outcode((yyvsp[(1) - (2)].lval), Always, &nullgen, 0, &nullgen);
-       }
-    break;
-
-  case 47:
-#line 365 "a.y"
-    {
-               (yyval.lval) = Always;
-       }
-    break;
-
-  case 48:
-#line 369 "a.y"
-    {
-               (yyval.lval) = ((yyvsp[(1) - (2)].lval) & ~C_SCOND) | (yyvsp[(2) - (2)].lval);
-       }
-    break;
-
-  case 49:
-#line 373 "a.y"
-    {
-               (yyval.lval) = (yyvsp[(1) - (2)].lval) | (yyvsp[(2) - (2)].lval);
-       }
-    break;
-
-  case 52:
-#line 382 "a.y"
-    {
-               (yyval.addr) = nullgen;
-               (yyval.addr).type = TYPE_BRANCH;
-               (yyval.addr).offset = (yyvsp[(1) - (4)].lval) + pc;
-       }
-    break;
-
-  case 53:
-#line 388 "a.y"
-    {
-               (yyvsp[(1) - (2)].sym) = labellookup((yyvsp[(1) - (2)].sym));
-               (yyval.addr) = nullgen;
-               if(pass == 2 && (yyvsp[(1) - (2)].sym)->type != LLAB)
-                       yyerror("undefined label: %s", (yyvsp[(1) - (2)].sym)->labelname);
-               (yyval.addr).type = TYPE_BRANCH;
-               (yyval.addr).offset = (yyvsp[(1) - (2)].sym)->value + (yyvsp[(2) - (2)].lval);
-       }
-    break;
-
-  case 54:
-#line 399 "a.y"
-    {
-               (yyval.addr) = nullgen;
-               (yyval.addr).type = TYPE_TEXTSIZE;
-               (yyval.addr).offset = (yyvsp[(1) - (1)].lval);
-               (yyval.addr).u.argsize = ArgsSizeUnknown;
-       }
-    break;
-
-  case 55:
-#line 406 "a.y"
-    {
-               (yyval.addr) = nullgen;
-               (yyval.addr).type = TYPE_TEXTSIZE;
-               (yyval.addr).offset = -(yyvsp[(2) - (2)].lval);
-               (yyval.addr).u.argsize = ArgsSizeUnknown;
-       }
-    break;
-
-  case 56:
-#line 413 "a.y"
-    {
-               (yyval.addr) = nullgen;
-               (yyval.addr).type = TYPE_TEXTSIZE;
-               (yyval.addr).offset = (yyvsp[(1) - (3)].lval);
-               (yyval.addr).u.argsize = (yyvsp[(3) - (3)].lval);
-       }
-    break;
-
-  case 57:
-#line 420 "a.y"
-    {
-               (yyval.addr) = nullgen;
-               (yyval.addr).type = TYPE_TEXTSIZE;
-               (yyval.addr).offset = -(yyvsp[(2) - (4)].lval);
-               (yyval.addr).u.argsize = (yyvsp[(4) - (4)].lval);
-       }
-    break;
-
-  case 58:
-#line 428 "a.y"
-    {
-               (yyval.addr) = nullgen;
-               (yyval.addr).type = TYPE_CONST;
-               (yyval.addr).offset = (yyvsp[(2) - (2)].lval);
-       }
-    break;
-
-  case 59:
-#line 434 "a.y"
-    {
-               (yyval.addr) = (yyvsp[(2) - (2)].addr);
-               (yyval.addr).type = TYPE_ADDR;
-       }
-    break;
-
-  case 60:
-#line 439 "a.y"
-    {
-               (yyval.addr) = nullgen;
-               (yyval.addr).type = TYPE_SCONST;
-               memcpy((yyval.addr).u.sval, (yyvsp[(2) - (2)].sval), sizeof((yyval.addr).u.sval));
-       }
-    break;
-
-  case 62:
-#line 448 "a.y"
-    {
-               (yyval.addr) = nullgen;
-               (yyval.addr).type = TYPE_FCONST;
-               (yyval.addr).u.dval = (yyvsp[(2) - (2)].dval);
-       }
-    break;
-
-  case 63:
-#line 454 "a.y"
-    {
-               (yyval.addr) = nullgen;
-               (yyval.addr).type = TYPE_FCONST;
-               (yyval.addr).u.dval = -(yyvsp[(3) - (3)].dval);
-       }
-    break;
-
-  case 64:
-#line 462 "a.y"
-    {
-               if((yyvsp[(1) - (1)].lval) < REG_R0 || (yyvsp[(1) - (1)].lval) > REG_R15)
-                       yyerror("invalid register in reglist");
-
-               (yyval.lval) = 1 << ((yyvsp[(1) - (1)].lval)&15);
-       }
-    break;
-
-  case 65:
-#line 469 "a.y"
-    {
-               int i;
-
-               if((yyvsp[(1) - (3)].lval) < REG_R0 || (yyvsp[(1) - (3)].lval) > REG_R15)
-                       yyerror("invalid register in reglist");
-               if((yyvsp[(3) - (3)].lval) < REG_R0 || (yyvsp[(3) - (3)].lval) > REG_R15)
-                       yyerror("invalid register in reglist");
-
-               (yyval.lval)=0;
-               for(i=(yyvsp[(1) - (3)].lval); i<=(yyvsp[(3) - (3)].lval); i++)
-                       (yyval.lval) |= 1<<(i&15);
-               for(i=(yyvsp[(3) - (3)].lval); i<=(yyvsp[(1) - (3)].lval); i++)
-                       (yyval.lval) |= 1<<(i&15);
-       }
-    break;
-
-  case 66:
-#line 484 "a.y"
-    {
-               if((yyvsp[(1) - (3)].lval) < REG_R0 || (yyvsp[(1) - (3)].lval) > REG_R15)
-                       yyerror("invalid register in reglist");
-
-               (yyval.lval) = (1<<((yyvsp[(1) - (3)].lval)&15)) | (yyvsp[(3) - (3)].lval);
-       }
-    break;
-
-  case 70:
-#line 496 "a.y"
-    {
-               (yyval.addr) = (yyvsp[(1) - (4)].addr);
-               (yyval.addr).reg = (yyvsp[(3) - (4)].lval);
-       }
-    break;
-
-  case 71:
-#line 501 "a.y"
-    {
-               (yyval.addr) = nullgen;
-               (yyval.addr).type = TYPE_REG;
-               (yyval.addr).reg = (yyvsp[(1) - (1)].lval);
-       }
-    break;
-
-  case 72:
-#line 507 "a.y"
-    {
-               (yyval.addr) = nullgen;
-               (yyval.addr).type = TYPE_REG;
-               (yyval.addr).reg = (yyvsp[(1) - (1)].lval);
-       }
-    break;
-
-  case 73:
-#line 513 "a.y"
-    {
-               (yyval.addr) = nullgen;
-               (yyval.addr).type = TYPE_MEM;
-               (yyval.addr).offset = (yyvsp[(1) - (1)].lval);
-       }
-    break;
-
-  case 77:
-#line 524 "a.y"
-    {
-               (yyval.addr) = (yyvsp[(1) - (1)].addr);
-               if((yyvsp[(1) - (1)].addr).name != NAME_EXTERN && (yyvsp[(1) - (1)].addr).name != NAME_STATIC) {
-               }
-       }
-    break;
-
-  case 78:
-#line 532 "a.y"
-    {
-               (yyval.addr) = nullgen;
-               (yyval.addr).type = TYPE_MEM;
-               (yyval.addr).reg = (yyvsp[(2) - (3)].lval);
-               (yyval.addr).offset = 0;
-       }
-    break;
-
-  case 80:
-#line 542 "a.y"
-    {
-               (yyval.addr) = nullgen;
-               (yyval.addr).type = TYPE_MEM;
-               (yyval.addr).reg = (yyvsp[(3) - (4)].lval);
-               (yyval.addr).offset = (yyvsp[(1) - (4)].lval);
-       }
-    break;
-
-  case 82:
-#line 552 "a.y"
-    {
-               (yyval.addr) = (yyvsp[(1) - (4)].addr);
-               (yyval.addr).type = TYPE_MEM;
-               (yyval.addr).reg = (yyvsp[(3) - (4)].lval);
-       }
-    break;
-
-  case 87:
-#line 565 "a.y"
-    {
-               (yyval.addr) = nullgen;
-               (yyval.addr).type = TYPE_CONST;
-               (yyval.addr).offset = (yyvsp[(2) - (2)].lval);
-       }
-    break;
-
-  case 88:
-#line 573 "a.y"
-    {
-               (yyval.addr) = nullgen;
-               (yyval.addr).type = TYPE_REG;
-               (yyval.addr).reg = (yyvsp[(1) - (1)].lval);
-       }
-    break;
-
-  case 89:
-#line 581 "a.y"
-    {
-               (yyval.addr) = nullgen;
-               (yyval.addr).type = TYPE_REGREG;
-               (yyval.addr).reg = (yyvsp[(2) - (5)].lval);
-               (yyval.addr).offset = (yyvsp[(4) - (5)].lval);
-       }
-    break;
-
-  case 90:
-#line 590 "a.y"
-    {
-               (yyval.addr) = nullgen;
-               (yyval.addr).type = TYPE_SHIFT;
-               (yyval.addr).offset = (yyvsp[(1) - (4)].lval)&15 | (yyvsp[(4) - (4)].lval) | (0 << 5);
-       }
-    break;
-
-  case 91:
-#line 596 "a.y"
-    {
-               (yyval.addr) = nullgen;
-               (yyval.addr).type = TYPE_SHIFT;
-               (yyval.addr).offset = (yyvsp[(1) - (4)].lval)&15 | (yyvsp[(4) - (4)].lval) | (1 << 5);
-       }
-    break;
-
-  case 92:
-#line 602 "a.y"
-    {
-               (yyval.addr) = nullgen;
-               (yyval.addr).type = TYPE_SHIFT;
-               (yyval.addr).offset = (yyvsp[(1) - (4)].lval)&15 | (yyvsp[(4) - (4)].lval) | (2 << 5);
-       }
-    break;
-
-  case 93:
-#line 608 "a.y"
-    {
-               (yyval.addr) = nullgen;
-               (yyval.addr).type = TYPE_SHIFT;
-               (yyval.addr).offset = (yyvsp[(1) - (4)].lval)&15 | (yyvsp[(4) - (4)].lval) | (3 << 5);
-       }
-    break;
-
-  case 94:
-#line 616 "a.y"
-    {
-               if((yyval.lval) < REG_R0 || (yyval.lval) > REG_R15)
-                       print("register value out of range in shift\n");
-               (yyval.lval) = (((yyvsp[(1) - (1)].lval)&15) << 8) | (1 << 4);
-       }
-    break;
-
-  case 95:
-#line 622 "a.y"
-    {
-               if((yyval.lval) < 0 || (yyval.lval) >= 32)
-                       print("shift value out of range\n");
-               (yyval.lval) = ((yyvsp[(1) - (1)].lval)&31) << 7;
-       }
-    break;
-
-  case 97:
-#line 631 "a.y"
-    {
-               (yyval.lval) = REGPC;
-       }
-    break;
-
-  case 98:
-#line 635 "a.y"
-    {
-               if((yyvsp[(3) - (4)].lval) < 0 || (yyvsp[(3) - (4)].lval) >= NREG)
-                       print("register value out of range in R(...)\n");
-               (yyval.lval) = REG_R0 + (yyvsp[(3) - (4)].lval);
-       }
-    break;
-
-  case 100:
-#line 644 "a.y"
-    {
-               (yyval.lval) = REGSP;
-       }
-    break;
-
-  case 102:
-#line 651 "a.y"
-    {
-               if((yyvsp[(3) - (4)].lval) < 0 || (yyvsp[(3) - (4)].lval) >= NREG)
-                       print("register value out of range in C(...)\n");
-               (yyval.lval) = (yyvsp[(3) - (4)].lval); // TODO(rsc): REG_C0+$3
-       }
-    break;
-
-  case 105:
-#line 663 "a.y"
-    {
-               (yyval.addr) = nullgen;
-               (yyval.addr).type = TYPE_REG;
-               (yyval.addr).reg = (yyvsp[(1) - (1)].lval);
-       }
-    break;
-
-  case 106:
-#line 669 "a.y"
-    {
-               (yyval.addr) = nullgen;
-               (yyval.addr).type = TYPE_REG;
-               (yyval.addr).reg = REG_F0 + (yyvsp[(3) - (4)].lval);
-       }
-    break;
-
-  case 107:
-#line 677 "a.y"
-    {
-               (yyval.addr) = nullgen;
-               (yyval.addr).type = TYPE_MEM;
-               (yyval.addr).name = (yyvsp[(3) - (4)].lval);
-               (yyval.addr).sym = nil;
-               (yyval.addr).offset = (yyvsp[(1) - (4)].lval);
-       }
-    break;
-
-  case 108:
-#line 685 "a.y"
-    {
-               (yyval.addr) = nullgen;
-               (yyval.addr).type = TYPE_MEM;
-               (yyval.addr).name = (yyvsp[(4) - (5)].lval);
-               (yyval.addr).sym = linklookup(ctxt, (yyvsp[(1) - (5)].sym)->name, 0);
-               (yyval.addr).offset = (yyvsp[(2) - (5)].lval);
-       }
-    break;
-
-  case 109:
-#line 693 "a.y"
-    {
-               (yyval.addr) = nullgen;
-               (yyval.addr).type = TYPE_MEM;
-               (yyval.addr).name = NAME_STATIC;
-               (yyval.addr).sym = linklookup(ctxt, (yyvsp[(1) - (7)].sym)->name, 1);
-               (yyval.addr).offset = (yyvsp[(4) - (7)].lval);
-       }
-    break;
-
-  case 110:
-#line 702 "a.y"
-    {
-               (yyval.lval) = 0;
-       }
-    break;
-
-  case 111:
-#line 706 "a.y"
-    {
-               (yyval.lval) = (yyvsp[(2) - (2)].lval);
-       }
-    break;
-
-  case 112:
-#line 710 "a.y"
-    {
-               (yyval.lval) = -(yyvsp[(2) - (2)].lval);
-       }
-    break;
-
-  case 117:
-#line 722 "a.y"
-    {
-               (yyval.lval) = (yyvsp[(1) - (1)].sym)->value;
-       }
-    break;
-
-  case 118:
-#line 726 "a.y"
-    {
-               (yyval.lval) = -(yyvsp[(2) - (2)].lval);
-       }
-    break;
-
-  case 119:
-#line 730 "a.y"
-    {
-               (yyval.lval) = (yyvsp[(2) - (2)].lval);
-       }
-    break;
-
-  case 120:
-#line 734 "a.y"
-    {
-               (yyval.lval) = ~(yyvsp[(2) - (2)].lval);
-       }
-    break;
-
-  case 121:
-#line 738 "a.y"
-    {
-               (yyval.lval) = (yyvsp[(2) - (3)].lval);
-       }
-    break;
-
-  case 122:
-#line 743 "a.y"
-    {
-               (yyval.lval) = 0;
-       }
-    break;
-
-  case 123:
-#line 747 "a.y"
-    {
-               (yyval.lval) = (yyvsp[(2) - (2)].lval);
-       }
-    break;
-
-  case 125:
-#line 754 "a.y"
-    {
-               (yyval.lval) = (yyvsp[(1) - (3)].lval) + (yyvsp[(3) - (3)].lval);
-       }
-    break;
-
-  case 126:
-#line 758 "a.y"
-    {
-               (yyval.lval) = (yyvsp[(1) - (3)].lval) - (yyvsp[(3) - (3)].lval);
-       }
-    break;
-
-  case 127:
-#line 762 "a.y"
-    {
-               (yyval.lval) = (yyvsp[(1) - (3)].lval) * (yyvsp[(3) - (3)].lval);
-       }
-    break;
-
-  case 128:
-#line 766 "a.y"
-    {
-               (yyval.lval) = (yyvsp[(1) - (3)].lval) / (yyvsp[(3) - (3)].lval);
-       }
-    break;
-
-  case 129:
-#line 770 "a.y"
-    {
-               (yyval.lval) = (yyvsp[(1) - (3)].lval) % (yyvsp[(3) - (3)].lval);
-       }
-    break;
-
-  case 130:
-#line 774 "a.y"
-    {
-               (yyval.lval) = (yyvsp[(1) - (4)].lval) << (yyvsp[(4) - (4)].lval);
-       }
-    break;
-
-  case 131:
-#line 778 "a.y"
-    {
-               (yyval.lval) = (yyvsp[(1) - (4)].lval) >> (yyvsp[(4) - (4)].lval);
-       }
-    break;
-
-  case 132:
-#line 782 "a.y"
-    {
-               (yyval.lval) = (yyvsp[(1) - (3)].lval) & (yyvsp[(3) - (3)].lval);
-       }
-    break;
-
-  case 133:
-#line 786 "a.y"
-    {
-               (yyval.lval) = (yyvsp[(1) - (3)].lval) ^ (yyvsp[(3) - (3)].lval);
-       }
-    break;
-
-  case 134:
-#line 790 "a.y"
-    {
-               (yyval.lval) = (yyvsp[(1) - (3)].lval) | (yyvsp[(3) - (3)].lval);
-       }
-    break;
-
-
-/* Line 1267 of yacc.c.  */
-#line 2642 "y.tab.c"
-      default: break;
-    }
-  YY_SYMBOL_PRINT ("-> $$ =", yyr1[yyn], &yyval, &yyloc);
-
-  YYPOPSTACK (yylen);
-  yylen = 0;
-  YY_STACK_PRINT (yyss, yyssp);
-
-  *++yyvsp = yyval;
-
-
-  /* Now `shift' the result of the reduction.  Determine what state
-     that goes to, based on the state we popped back to and the rule
-     number reduced by.  */
-
-  yyn = yyr1[yyn];
-
-  yystate = yypgoto[yyn - YYNTOKENS] + *yyssp;
-  if (0 <= yystate && yystate <= YYLAST && yycheck[yystate] == *yyssp)
-    yystate = yytable[yystate];
-  else
-    yystate = yydefgoto[yyn - YYNTOKENS];
-
-  goto yynewstate;
-
-
-/*------------------------------------.
-| yyerrlab -- here on detecting error |
-`------------------------------------*/
-yyerrlab:
-  /* If not already recovering from an error, report this error.  */
-  if (!yyerrstatus)
-    {
-      ++yynerrs;
-#if ! YYERROR_VERBOSE
-      yyerror (YY_("syntax error"));
-#else
-      {
-       YYSIZE_T yysize = yysyntax_error (0, yystate, yychar);
-       if (yymsg_alloc < yysize && yymsg_alloc < YYSTACK_ALLOC_MAXIMUM)
-         {
-           YYSIZE_T yyalloc = 2 * yysize;
-           if (! (yysize <= yyalloc && yyalloc <= YYSTACK_ALLOC_MAXIMUM))
-             yyalloc = YYSTACK_ALLOC_MAXIMUM;
-           if (yymsg != yymsgbuf)
-             YYSTACK_FREE (yymsg);
-           yymsg = (char *) YYSTACK_ALLOC (yyalloc);
-           if (yymsg)
-             yymsg_alloc = yyalloc;
-           else
-             {
-               yymsg = yymsgbuf;
-               yymsg_alloc = sizeof yymsgbuf;
-             }
-         }
-
-       if (0 < yysize && yysize <= yymsg_alloc)
-         {
-           (void) yysyntax_error (yymsg, yystate, yychar);
-           yyerror (yymsg);
-         }
-       else
-         {
-           yyerror (YY_("syntax error"));
-           if (yysize != 0)
-             goto yyexhaustedlab;
-         }
-      }
-#endif
-    }
-
-
-
-  if (yyerrstatus == 3)
-    {
-      /* If just tried and failed to reuse look-ahead token after an
-        error, discard it.  */
-
-      if (yychar <= YYEOF)
-       {
-         /* Return failure if at end of input.  */
-         if (yychar == YYEOF)
-           YYABORT;
-       }
-      else
-       {
-         yydestruct ("Error: discarding",
-                     yytoken, &yylval);
-         yychar = YYEMPTY;
-       }
-    }
-
-  /* Else will try to reuse look-ahead token after shifting the error
-     token.  */
-  goto yyerrlab1;
-
-
-/*---------------------------------------------------.
-| yyerrorlab -- error raised explicitly by YYERROR.  |
-`---------------------------------------------------*/
-yyerrorlab:
-
-  /* Pacify compilers like GCC when the user code never invokes
-     YYERROR and the label yyerrorlab therefore never appears in user
-     code.  */
-  if (/*CONSTCOND*/ 0)
-     goto yyerrorlab;
-
-  /* Do not reclaim the symbols of the rule which action triggered
-     this YYERROR.  */
-  YYPOPSTACK (yylen);
-  yylen = 0;
-  YY_STACK_PRINT (yyss, yyssp);
-  yystate = *yyssp;
-  goto yyerrlab1;
-
-
-/*-------------------------------------------------------------.
-| yyerrlab1 -- common code for both syntax error and YYERROR.  |
-`-------------------------------------------------------------*/
-yyerrlab1:
-  yyerrstatus = 3;     /* Each real token shifted decrements this.  */
-
-  for (;;)
-    {
-      yyn = yypact[yystate];
-      if (yyn != YYPACT_NINF)
-       {
-         yyn += YYTERROR;
-         if (0 <= yyn && yyn <= YYLAST && yycheck[yyn] == YYTERROR)
-           {
-             yyn = yytable[yyn];
-             if (0 < yyn)
-               break;
-           }
-       }
-
-      /* Pop the current state because it cannot handle the error token.  */
-      if (yyssp == yyss)
-       YYABORT;
-
-
-      yydestruct ("Error: popping",
-                 yystos[yystate], yyvsp);
-      YYPOPSTACK (1);
-      yystate = *yyssp;
-      YY_STACK_PRINT (yyss, yyssp);
-    }
-
-  if (yyn == YYFINAL)
-    YYACCEPT;
-
-  *++yyvsp = yylval;
-
-
-  /* Shift the error token.  */
-  YY_SYMBOL_PRINT ("Shifting", yystos[yyn], yyvsp, yylsp);
-
-  yystate = yyn;
-  goto yynewstate;
-
-
-/*-------------------------------------.
-| yyacceptlab -- YYACCEPT comes here.  |
-`-------------------------------------*/
-yyacceptlab:
-  yyresult = 0;
-  goto yyreturn;
-
-/*-----------------------------------.
-| yyabortlab -- YYABORT comes here.  |
-`-----------------------------------*/
-yyabortlab:
-  yyresult = 1;
-  goto yyreturn;
-
-#ifndef yyoverflow
-/*-------------------------------------------------.
-| yyexhaustedlab -- memory exhaustion comes here.  |
-`-------------------------------------------------*/
-yyexhaustedlab:
-  yyerror (YY_("memory exhausted"));
-  yyresult = 2;
-  /* Fall through.  */
-#endif
-
-yyreturn:
-  if (yychar != YYEOF && yychar != YYEMPTY)
-     yydestruct ("Cleanup: discarding lookahead",
-                yytoken, &yylval);
-  /* Do not reclaim the symbols of the rule which action triggered
-     this YYABORT or YYACCEPT.  */
-  YYPOPSTACK (yylen);
-  YY_STACK_PRINT (yyss, yyssp);
-  while (yyssp != yyss)
-    {
-      yydestruct ("Cleanup: popping",
-                 yystos[*yyssp], yyvsp);
-      YYPOPSTACK (1);
-    }
-#ifndef yyoverflow
-  if (yyss != yyssa)
-    YYSTACK_FREE (yyss);
-#endif
-#if YYERROR_VERBOSE
-  if (yymsg != yymsgbuf)
-    YYSTACK_FREE (yymsg);
-#endif
-  /* Make sure YYID is used.  */
-  return YYID (yyresult);
-}
-
-
-
diff --git a/src/cmd/5a/y.tab.h b/src/cmd/5a/y.tab.h
deleted file mode 100644 (file)
index fbbdbef..0000000
+++ /dev/null
@@ -1,166 +0,0 @@
-/* A Bison parser, made by GNU Bison 2.3.  */
-
-/* Skeleton interface for Bison's Yacc-like parsers in C
-
-   Copyright (C) 1984, 1989, 1990, 2000, 2001, 2002, 2003, 2004, 2005, 2006
-   Free Software Foundation, Inc.
-
-   This program is free software; you can redistribute it and/or modify
-   it under the terms of the GNU General Public License as published by
-   the Free Software Foundation; either version 2, or (at your option)
-   any later version.
-
-   This program is distributed in the hope that it will be useful,
-   but WITHOUT ANY WARRANTY; without even the implied warranty of
-   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-   GNU General Public License for more details.
-
-   You should have received a copy of the GNU General Public License
-   along with this program; if not, write to the Free Software
-   Foundation, Inc., 51 Franklin Street, Fifth Floor,
-   Boston, MA 02110-1301, USA.  */
-
-/* As a special exception, you may create a larger work that contains
-   part or all of the Bison parser skeleton and distribute that work
-   under terms of your choice, so long as that work isn't itself a
-   parser generator using the skeleton or a modified version thereof
-   as a parser skeleton.  Alternatively, if you modify or redistribute
-   the parser skeleton itself, you may (at your option) remove this
-   special exception, which will cause the skeleton and the resulting
-   Bison output files to be licensed under the GNU General Public
-   License without this special exception.
-
-   This special exception was added by the Free Software Foundation in
-   version 2.2 of Bison.  */
-
-/* Tokens.  */
-#ifndef YYTOKENTYPE
-# define YYTOKENTYPE
-   /* Put the tokens into the symbol table, so that GDB and other debuggers
-      know about them.  */
-   enum yytokentype {
-     LTYPE1 = 258,
-     LTYPE2 = 259,
-     LTYPE3 = 260,
-     LTYPE4 = 261,
-     LTYPE5 = 262,
-     LTYPE6 = 263,
-     LTYPE7 = 264,
-     LTYPE8 = 265,
-     LTYPE9 = 266,
-     LTYPEA = 267,
-     LTYPEB = 268,
-     LGLOBL = 269,
-     LTYPEC = 270,
-     LTYPED = 271,
-     LTYPEE = 272,
-     LTYPEG = 273,
-     LTYPEH = 274,
-     LTYPEI = 275,
-     LTYPEJ = 276,
-     LTYPEK = 277,
-     LTYPEL = 278,
-     LTYPEM = 279,
-     LTYPEN = 280,
-     LTYPEBX = 281,
-     LTYPEPLD = 282,
-     LCONST = 283,
-     LSP = 284,
-     LSB = 285,
-     LFP = 286,
-     LPC = 287,
-     LTYPEX = 288,
-     LTYPEPC = 289,
-     LTYPEF = 290,
-     LR = 291,
-     LREG = 292,
-     LF = 293,
-     LFREG = 294,
-     LC = 295,
-     LCREG = 296,
-     LPSR = 297,
-     LFCR = 298,
-     LCOND = 299,
-     LS = 300,
-     LAT = 301,
-     LFCONST = 302,
-     LSCONST = 303,
-     LNAME = 304,
-     LLAB = 305,
-     LVAR = 306
-   };
-#endif
-/* Tokens.  */
-#define LTYPE1 258
-#define LTYPE2 259
-#define LTYPE3 260
-#define LTYPE4 261
-#define LTYPE5 262
-#define LTYPE6 263
-#define LTYPE7 264
-#define LTYPE8 265
-#define LTYPE9 266
-#define LTYPEA 267
-#define LTYPEB 268
-#define LGLOBL 269
-#define LTYPEC 270
-#define LTYPED 271
-#define LTYPEE 272
-#define LTYPEG 273
-#define LTYPEH 274
-#define LTYPEI 275
-#define LTYPEJ 276
-#define LTYPEK 277
-#define LTYPEL 278
-#define LTYPEM 279
-#define LTYPEN 280
-#define LTYPEBX 281
-#define LTYPEPLD 282
-#define LCONST 283
-#define LSP 284
-#define LSB 285
-#define LFP 286
-#define LPC 287
-#define LTYPEX 288
-#define LTYPEPC 289
-#define LTYPEF 290
-#define LR 291
-#define LREG 292
-#define LF 293
-#define LFREG 294
-#define LC 295
-#define LCREG 296
-#define LPSR 297
-#define LFCR 298
-#define LCOND 299
-#define LS 300
-#define LAT 301
-#define LFCONST 302
-#define LSCONST 303
-#define LNAME 304
-#define LLAB 305
-#define LVAR 306
-
-
-
-
-#if ! defined YYSTYPE && ! defined YYSTYPE_IS_DECLARED
-typedef union YYSTYPE
-#line 39 "a.y"
-{
-       Sym     *sym;
-       int32   lval;
-       double  dval;
-       char    sval[8];
-       Addr    addr;
-}
-/* Line 1529 of yacc.c.  */
-#line 159 "y.tab.h"
-       YYSTYPE;
-# define yystype YYSTYPE /* obsolescent; will be withdrawn */
-# define YYSTYPE_IS_DECLARED 1
-# define YYSTYPE_IS_TRIVIAL 1
-#endif
-
-extern YYSTYPE yylval;
-
diff --git a/src/cmd/5g/Makefile b/src/cmd/5g/Makefile
deleted file mode 100644 (file)
index 3f528d7..0000000
+++ /dev/null
@@ -1,5 +0,0 @@
-# Copyright 2012 The Go Authors. All rights reserved.
-# Use of this source code is governed by a BSD-style
-# license that can be found in the LICENSE file.
-
-include ../../Make.dist
diff --git a/src/cmd/5g/cgen.c b/src/cmd/5g/cgen.c
deleted file mode 100644 (file)
index 354e0cb..0000000
+++ /dev/null
@@ -1,1840 +0,0 @@
-// Copyright 2009 The Go Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style
-// license that can be found in the LICENSE file.
-
-#include <u.h>
-#include <libc.h>
-#include "gg.h"
-
-/*
- * generate:
- *     res = n;
- * simplifies and calls gmove.
- */
-void
-cgen(Node *n, Node *res)
-{
-       Node *nl, *nr, *r;
-       Node n1, n2, f0, f1;
-       int a, w, rg;
-       Prog *p1, *p2, *p3;
-       Addr addr;
-
-       if(debug['g']) {
-               dump("\ncgen-n", n);
-               dump("cgen-res", res);
-       }
-       if(n == N || n->type == T)
-               goto ret;
-
-       if(res == N || res->type == T)
-               fatal("cgen: res nil");
-
-       switch(n->op) {
-       case OSLICE:
-       case OSLICEARR:
-       case OSLICESTR:
-       case OSLICE3:
-       case OSLICE3ARR:
-               if (res->op != ONAME || !res->addable) {
-                       tempname(&n1, n->type);
-                       cgen_slice(n, &n1);
-                       cgen(&n1, res);
-               } else
-                       cgen_slice(n, res);
-               return;
-       case OEFACE:
-               if (res->op != ONAME || !res->addable) {
-                       tempname(&n1, n->type);
-                       cgen_eface(n, &n1);
-                       cgen(&n1, res);
-               } else
-                       cgen_eface(n, res);
-               return;
-       }
-
-       while(n->op == OCONVNOP)
-               n = n->left;
-
-       if(n->ullman >= UINF) {
-               if(n->op == OINDREG)
-                       fatal("cgen: this is going to misscompile");
-               if(res->ullman >= UINF) {
-                       tempname(&n1, n->type);
-                       cgen(n, &n1);
-                       cgen(&n1, res);
-                       goto ret;
-               }
-       }
-
-       if(isfat(n->type)) {
-               if(n->type->width < 0)
-                       fatal("forgot to compute width for %T", n->type);
-               sgen(n, res, n->type->width);
-               goto ret;
-       }
-
-
-       // update addressability for string, slice
-       // can't do in walk because n->left->addable
-       // changes if n->left is an escaping local variable.
-       switch(n->op) {
-       case OSPTR:
-       case OLEN:
-               if(isslice(n->left->type) || istype(n->left->type, TSTRING))
-                       n->addable = n->left->addable;
-               break;
-       case OCAP:
-               if(isslice(n->left->type))
-                       n->addable = n->left->addable;
-               break;
-       case OITAB:
-               n->addable = n->left->addable;
-               break;
-       }
-
-       // if both are addressable, move
-       if(n->addable && res->addable) {
-               if(is64(n->type) || is64(res->type) ||
-                  n->op == OREGISTER || res->op == OREGISTER ||
-                  iscomplex[n->type->etype] || iscomplex[res->type->etype]) {
-                       gmove(n, res);
-               } else {
-                       regalloc(&n1, n->type, N);
-                       gmove(n, &n1);
-                       cgen(&n1, res);
-                       regfree(&n1);
-               }
-               goto ret;
-       }
-
-       // if both are not addressable, use a temporary.
-       if(!n->addable && !res->addable) {
-               // could use regalloc here sometimes,
-               // but have to check for ullman >= UINF.
-               tempname(&n1, n->type);
-               cgen(n, &n1);
-               cgen(&n1, res);
-               return;
-       }
-
-       // if result is not addressable directly but n is,
-       // compute its address and then store via the address.
-       if(!res->addable) {
-               igen(res, &n1, N);
-               cgen(n, &n1);
-               regfree(&n1);
-               return;
-       }
-
-       if(complexop(n, res)) {
-               complexgen(n, res);
-               return;
-       }
-
-       // if n is sudoaddable generate addr and move
-       if (!is64(n->type) && !is64(res->type) && !iscomplex[n->type->etype] && !iscomplex[res->type->etype]) {
-               a = optoas(OAS, n->type);
-               if(sudoaddable(a, n, &addr, &w)) {
-                       if (res->op != OREGISTER) {
-                               regalloc(&n2, res->type, N);
-                               p1 = gins(a, N, &n2);
-                               p1->from = addr;
-                               if(debug['g'])
-                                       print("%P [ignore previous line]\n", p1);
-                               gmove(&n2, res);
-                               regfree(&n2);
-                       } else {
-                               p1 = gins(a, N, res);
-                               p1->from = addr;
-                               if(debug['g'])
-                                       print("%P [ignore previous line]\n", p1);
-                       }
-                       sudoclean();
-                       goto ret;
-               }
-       }
-
-       // otherwise, the result is addressable but n is not.
-       // let's do some computation.
-
-       nl = n->left;
-       nr = n->right;
-
-       if(nl != N && nl->ullman >= UINF)
-       if(nr != N && nr->ullman >= UINF) {
-               tempname(&n1, nl->type);
-               cgen(nl, &n1);
-               n2 = *n;
-               n2.left = &n1;
-               cgen(&n2, res);
-               goto ret;
-       }
-
-       // 64-bit ops are hard on 32-bit machine.
-       if(is64(n->type) || is64(res->type) || n->left != N && is64(n->left->type)) {
-               switch(n->op) {
-               // math goes to cgen64.
-               case OMINUS:
-               case OCOM:
-               case OADD:
-               case OSUB:
-               case OMUL:
-               case OLROT:
-               case OLSH:
-               case ORSH:
-               case OAND:
-               case OOR:
-               case OXOR:
-                       cgen64(n, res);
-                       return;
-               }
-       }
-
-       if(nl != N && isfloat[n->type->etype] && isfloat[nl->type->etype])
-               goto flt;
-       switch(n->op) {
-       default:
-               dump("cgen", n);
-               fatal("cgen: unknown op %+hN", n);
-               break;
-
-       case OREAL:
-       case OIMAG:
-       case OCOMPLEX:
-               fatal("unexpected complex");
-               break;
-
-       // these call bgen to get a bool value
-       case OOROR:
-       case OANDAND:
-       case OEQ:
-       case ONE:
-       case OLT:
-       case OLE:
-       case OGE:
-       case OGT:
-       case ONOT:
-               p1 = gbranch(AB, T, 0);
-               p2 = pc;
-               gmove(nodbool(1), res);
-               p3 = gbranch(AB, T, 0);
-               patch(p1, pc);
-               bgen(n, 1, 0, p2);
-               gmove(nodbool(0), res);
-               patch(p3, pc);
-               goto ret;
-
-       case OPLUS:
-               cgen(nl, res);
-               goto ret;
-
-       // unary
-       case OCOM:
-               a = optoas(OXOR, nl->type);
-               regalloc(&n1, nl->type, N);
-               cgen(nl, &n1);
-               nodconst(&n2, nl->type, -1);
-               gins(a, &n2, &n1);
-               goto norm;
-
-       case OMINUS:
-               regalloc(&n1, nl->type, N);
-               cgen(nl, &n1);
-               nodconst(&n2, nl->type, 0);
-               gins(optoas(OMINUS, nl->type), &n2, &n1);
-               goto norm;
-
-       // symmetric binary
-       case OAND:
-       case OOR:
-       case OXOR:
-       case OADD:
-       case OMUL:
-               a = optoas(n->op, nl->type);
-               goto sbop;
-
-       // asymmetric binary
-       case OSUB:
-               a = optoas(n->op, nl->type);
-               goto abop;
-
-       case OHMUL:
-               cgen_hmul(nl, nr, res);
-               break;
-
-       case OLROT:
-       case OLSH:
-       case ORSH:
-               cgen_shift(n->op, n->bounded, nl, nr, res);
-               break;
-
-       case OCONV:
-               if(eqtype(n->type, nl->type) || noconv(n->type, nl->type)) {
-                       cgen(nl, res);
-                       break;
-               }
-               if(nl->addable && !is64(nl->type)) {
-                       regalloc(&n1, nl->type, res);
-                       gmove(nl, &n1);
-               } else {
-                       if(n->type->width > widthptr || is64(nl->type) || isfloat[nl->type->etype])
-                               tempname(&n1, nl->type);
-                       else
-                               regalloc(&n1, nl->type, res);
-                       cgen(nl, &n1);
-               }
-               if(n->type->width > widthptr || is64(n->type) || isfloat[n->type->etype])
-                       tempname(&n2, n->type);
-               else
-                       regalloc(&n2, n->type, N);
-               gmove(&n1, &n2);
-               gmove(&n2, res);
-               if(n1.op == OREGISTER)
-                       regfree(&n1);
-               if(n2.op == OREGISTER)
-                       regfree(&n2);
-               break;
-
-       case ODOT:
-       case ODOTPTR:
-       case OINDEX:
-       case OIND:
-       case ONAME:     // PHEAP or PPARAMREF var
-               igen(n, &n1, res);
-               gmove(&n1, res);
-               regfree(&n1);
-               break;
-
-       case OITAB:
-               // interface table is first word of interface value
-               igen(nl, &n1, res);
-               n1.type = n->type;
-               gmove(&n1, res);
-               regfree(&n1);
-               break;
-
-       case OSPTR:
-               // pointer is the first word of string or slice.
-               if(isconst(nl, CTSTR)) {
-                       regalloc(&n1, types[tptr], res);
-                       p1 = gins(AMOVW, N, &n1);
-                       datastring(nl->val.u.sval->s, nl->val.u.sval->len, &p1->from);
-                       gmove(&n1, res);
-                       regfree(&n1);
-                       break;
-               }
-               igen(nl, &n1, res);
-               n1.type = n->type;
-               gmove(&n1, res);
-               regfree(&n1);
-               break;
-
-       case OLEN:
-               if(istype(nl->type, TMAP) || istype(nl->type, TCHAN)) {
-                       // map has len in the first 32-bit word.
-                       // a zero pointer means zero length
-                       regalloc(&n1, types[tptr], res);
-                       cgen(nl, &n1);
-
-                       nodconst(&n2, types[tptr], 0);
-                       gcmp(optoas(OCMP, types[tptr]), &n1, &n2);
-                       p1 = gbranch(optoas(OEQ, types[tptr]), T, -1);
-
-                       n2 = n1;
-                       n2.op = OINDREG;
-                       n2.type = types[TINT32];
-                       gmove(&n2, &n1);
-
-                       patch(p1, pc);
-
-                       gmove(&n1, res);
-                       regfree(&n1);
-                       break;
-               }
-               if(istype(nl->type, TSTRING) || isslice(nl->type)) {
-                       // both slice and string have len one pointer into the struct.
-                       igen(nl, &n1, res);
-                       n1.type = types[TUINT32];
-                       n1.xoffset += Array_nel;
-                       gmove(&n1, res);
-                       regfree(&n1);
-                       break;
-               }
-               fatal("cgen: OLEN: unknown type %lT", nl->type);
-               break;
-
-       case OCAP:
-               if(istype(nl->type, TCHAN)) {
-                       // chan has cap in the second 32-bit word.
-                       // a zero pointer means zero length
-                       regalloc(&n1, types[tptr], res);
-                       cgen(nl, &n1);
-
-                       nodconst(&n2, types[tptr], 0);
-                       gcmp(optoas(OCMP, types[tptr]), &n1, &n2);
-                       p1 = gbranch(optoas(OEQ, types[tptr]), T, -1);
-
-                       n2 = n1;
-                       n2.op = OINDREG;
-                       n2.xoffset = 4;
-                       n2.type = types[TINT32];
-                       gmove(&n2, &n1);
-
-                       patch(p1, pc);
-
-                       gmove(&n1, res);
-                       regfree(&n1);
-                       break;
-               }
-               if(isslice(nl->type)) {
-                       igen(nl, &n1, res);
-                       n1.type = types[TUINT32];
-                       n1.xoffset += Array_cap;
-                       gmove(&n1, res);
-                       regfree(&n1);
-                       break;
-               }
-               fatal("cgen: OCAP: unknown type %lT", nl->type);
-               break;
-
-       case OADDR:
-               agen(nl, res);
-               break;
-
-       case OCALLMETH:
-       case OCALLFUNC:
-               // Release res so that it is available for cgen_call.
-               // Pick it up again after the call.
-               rg = -1;
-               if(n->ullman >= UINF) {
-                       if(res != N && (res->op == OREGISTER || res->op == OINDREG)) {
-                               rg = res->val.u.reg;
-                               reg[rg]--;
-                       }
-               }
-               if(n->op == OCALLMETH)
-                       cgen_callmeth(n, 0);
-               else
-                       cgen_call(n, 0);
-               if(rg >= 0)
-                       reg[rg]++;
-               cgen_callret(n, res);
-               break;
-
-       case OCALLINTER:
-               cgen_callinter(n, res, 0);
-               cgen_callret(n, res);
-               break;
-
-       case OMOD:
-       case ODIV:
-               a = optoas(n->op, nl->type);
-               goto abop;
-       }
-       goto ret;
-
-sbop:  // symmetric binary
-       if(nl->ullman < nr->ullman) {
-               r = nl;
-               nl = nr;
-               nr = r;
-       }
-
-abop:  // asymmetric binary
-       // TODO(kaib): use fewer registers here.
-       if(nl->ullman >= nr->ullman) {
-               regalloc(&n1, nl->type, res);
-               cgen(nl, &n1);
-               switch(n->op) {
-               case OADD:
-               case OSUB:
-               case OAND:
-               case OOR:
-               case OXOR:
-                       if(smallintconst(nr)) {
-                               n2 = *nr;
-                               break;
-                       }
-               default:
-                       regalloc(&n2, nr->type, N);
-                       cgen(nr, &n2);
-               }
-       } else {
-               switch(n->op) {
-               case OADD:
-               case OSUB:
-               case OAND:
-               case OOR:
-               case OXOR:
-                       if(smallintconst(nr)) {
-                               n2 = *nr;
-                               break;
-                       }
-               default:
-                       regalloc(&n2, nr->type, res);
-                       cgen(nr, &n2);
-               }
-               regalloc(&n1, nl->type, N);
-               cgen(nl, &n1);
-       }
-       gins(a, &n2, &n1);
-norm:
-       // Normalize result for types smaller than word.
-       if(n->type->width < widthptr) {
-               switch(n->op) {
-               case OADD:
-               case OSUB:
-               case OMUL:
-               case OCOM:
-               case OMINUS:
-                       gins(optoas(OAS, n->type), &n1, &n1);
-                       break;
-               }
-       }
-       gmove(&n1, res);
-       regfree(&n1);
-       if(n2.op != OLITERAL)
-               regfree(&n2);
-       goto ret;
-
-flt:   // floating-point.
-       regalloc(&f0, nl->type, res);
-       if(nr != N)
-               goto flt2;
-
-       if(n->op == OMINUS) {
-               nr = nodintconst(-1);
-               convlit(&nr, n->type);
-               n->op = OMUL;
-               goto flt2;
-       }
-
-       // unary
-       cgen(nl, &f0);
-       if(n->op != OCONV && n->op != OPLUS)
-               gins(optoas(n->op, n->type), &f0, &f0);
-       gmove(&f0, res);
-       regfree(&f0);
-       goto ret;
-
-flt2:  // binary
-       if(nl->ullman >= nr->ullman) {
-               cgen(nl, &f0);
-               regalloc(&f1, n->type, N);
-               gmove(&f0, &f1);
-               cgen(nr, &f0);
-               gins(optoas(n->op, n->type), &f0, &f1);
-       } else {
-               cgen(nr, &f0);
-               regalloc(&f1, n->type, N);
-               cgen(nl, &f1);
-               gins(optoas(n->op, n->type), &f0, &f1);
-       }
-       gmove(&f1, res);
-       regfree(&f0);
-       regfree(&f1);
-       goto ret;
-
-ret:
-       ;
-}
-
-/*
- * generate array index into res.
- * n might be any size; res is 32-bit.
- * returns Prog* to patch to panic call.
- */
-Prog*
-cgenindex(Node *n, Node *res, int bounded)
-{
-       Node tmp, lo, hi, zero, n1, n2;
-
-       if(!is64(n->type)) {
-               cgen(n, res);
-               return nil;
-       }
-
-       tempname(&tmp, types[TINT64]);
-       cgen(n, &tmp);
-       split64(&tmp, &lo, &hi);
-       gmove(&lo, res);
-       if(bounded) {
-               splitclean();
-               return nil;
-       }
-       regalloc(&n1, types[TINT32], N);
-       regalloc(&n2, types[TINT32], N);
-       nodconst(&zero, types[TINT32], 0);
-       gmove(&hi, &n1);
-       gmove(&zero, &n2);
-       gcmp(ACMP, &n1, &n2);
-       regfree(&n2);
-       regfree(&n1);
-       splitclean();
-       return gbranch(ABNE, T, -1);
-}
-
-/*
- * generate:
- *     res = &n;
- * The generated code checks that the result is not nil.
- */
-void
-agen(Node *n, Node *res)
-{
-       Node *nl;
-       Node n1, n2, n3;
-       int r;
-
-       if(debug['g']) {
-               dump("\nagen-res", res);
-               dump("agen-r", n);
-       }
-       if(n == N || n->type == T || res == N || res->type == T)
-               fatal("agen");
-
-       while(n->op == OCONVNOP)
-               n = n->left;
-
-       if(isconst(n, CTNIL) && n->type->width > widthptr) {
-               // Use of a nil interface or nil slice.
-               // Create a temporary we can take the address of and read.
-               // The generated code is just going to panic, so it need not
-               // be terribly efficient. See issue 3670.
-               tempname(&n1, n->type);
-               gvardef(&n1);
-               clearfat(&n1);
-               regalloc(&n2, types[tptr], res);
-               gins(AMOVW, &n1, &n2);
-               gmove(&n2, res);
-               regfree(&n2);
-               goto ret;
-       }
-               
-
-       if(n->addable) {
-               memset(&n1, 0, sizeof n1);
-               n1.op = OADDR;
-               n1.left = n;
-               regalloc(&n2, types[tptr], res);
-               gins(AMOVW, &n1, &n2);
-               gmove(&n2, res);
-               regfree(&n2);
-               goto ret;
-       }
-
-       nl = n->left;
-
-       switch(n->op) {
-       default:
-               fatal("agen: unknown op %+hN", n);
-               break;
-
-       case OCALLMETH:
-       case OCALLFUNC:
-               // Release res so that it is available for cgen_call.
-               // Pick it up again after the call.
-               r = -1;
-               if(n->ullman >= UINF) {
-                       if(res->op == OREGISTER || res->op == OINDREG) {
-                               r = res->val.u.reg;
-                               reg[r]--;
-                       }
-               }
-               if(n->op == OCALLMETH)
-                       cgen_callmeth(n, 0);
-               else
-                       cgen_call(n, 0);
-               if(r >= 0)
-                       reg[r]++;
-               cgen_aret(n, res);
-               break;
-
-       case OCALLINTER:
-               cgen_callinter(n, res, 0);
-               cgen_aret(n, res);
-               break;
-
-       case OSLICE:
-       case OSLICEARR:
-       case OSLICESTR:
-       case OSLICE3:
-       case OSLICE3ARR:
-               tempname(&n1, n->type);
-               cgen_slice(n, &n1);
-               agen(&n1, res);
-               break;
-
-       case OEFACE:
-               tempname(&n1, n->type);
-               cgen_eface(n, &n1);
-               agen(&n1, res);
-               break;
-
-       case OINDEX:
-               agenr(n, &n1, res);
-               gmove(&n1, res);
-               regfree(&n1);
-               break;
-
-       case ONAME:
-               // should only get here with names in this func.
-               if(n->funcdepth > 0 && n->funcdepth != funcdepth) {
-                       dump("bad agen", n);
-                       fatal("agen: bad ONAME funcdepth %d != %d",
-                               n->funcdepth, funcdepth);
-               }
-
-               // should only get here for heap vars or paramref
-               if(!(n->class & PHEAP) && n->class != PPARAMREF) {
-                       dump("bad agen", n);
-                       fatal("agen: bad ONAME class %#x", n->class);
-               }
-               cgen(n->heapaddr, res);
-               if(n->xoffset != 0) {
-                       nodconst(&n1, types[TINT32], n->xoffset);
-                       regalloc(&n2, n1.type, N);
-                       regalloc(&n3, types[TINT32], N);
-                       gmove(&n1, &n2);
-                       gmove(res, &n3);
-                       gins(optoas(OADD, types[tptr]), &n2, &n3);
-                       gmove(&n3, res);
-                       regfree(&n2);
-                       regfree(&n3);
-               }
-               break;
-
-       case OIND:
-               cgen(nl, res);
-               cgen_checknil(res);
-               break;
-
-       case ODOT:
-               agen(nl, res);
-               if(n->xoffset != 0) {
-                       nodconst(&n1, types[TINT32], n->xoffset);
-                       regalloc(&n2, n1.type, N);
-                       regalloc(&n3, types[TINT32], N);
-                       gmove(&n1, &n2);
-                       gmove(res, &n3);
-                       gins(optoas(OADD, types[tptr]), &n2, &n3);
-                       gmove(&n3, res);
-                       regfree(&n2);
-                       regfree(&n3);
-               }
-               break;
-
-       case ODOTPTR:
-               cgen(nl, res);
-               cgen_checknil(res);
-               if(n->xoffset != 0) {
-                       nodconst(&n1, types[TINT32], n->xoffset);
-                       regalloc(&n2, n1.type, N);
-                       regalloc(&n3, types[tptr], N);
-                       gmove(&n1, &n2);
-                       gmove(res, &n3);
-                       gins(optoas(OADD, types[tptr]), &n2, &n3);
-                       gmove(&n3, res);
-                       regfree(&n2);
-                       regfree(&n3);
-               }
-               break;
-       }
-
-ret:
-       ;
-}
-
-/*
- * generate:
- *     newreg = &n;
- *     res = newreg
- *
- * on exit, a has been changed to be *newreg.
- * caller must regfree(a).
- * The generated code checks that the result is not *nil.
- */
-void
-igen(Node *n, Node *a, Node *res)
-{
-       Node n1;
-       int r;
-
-       if(debug['g']) {
-               dump("\nigen-n", n);
-       }
-       switch(n->op) {
-       case ONAME:
-               if((n->class&PHEAP) || n->class == PPARAMREF)
-                       break;
-               *a = *n;
-               return;
-
-       case OINDREG:
-               // Increase the refcount of the register so that igen's caller
-               // has to call regfree.
-               if(n->val.u.reg != REGSP)
-                       reg[n->val.u.reg]++;
-               *a = *n;
-               return;
-
-       case ODOT:
-               igen(n->left, a, res);
-               a->xoffset += n->xoffset;
-               a->type = n->type;
-               return;
-
-       case ODOTPTR:
-               if(n->left->addable
-                       || n->left->op == OCALLFUNC
-                       || n->left->op == OCALLMETH
-                       || n->left->op == OCALLINTER) {
-                       // igen-able nodes.
-                       igen(n->left, &n1, res);
-                       regalloc(a, types[tptr], &n1);
-                       gmove(&n1, a);
-                       regfree(&n1);
-               } else {
-                       regalloc(a, types[tptr], res);
-                       cgen(n->left, a);
-               }
-               cgen_checknil(a);
-               a->op = OINDREG;
-               a->xoffset = n->xoffset;
-               a->type = n->type;
-               return;
-
-       case OCALLMETH:
-       case OCALLFUNC:
-       case OCALLINTER:
-               // Release res so that it is available for cgen_call.
-               // Pick it up again after the call.
-               r = -1;
-               if(n->ullman >= UINF) {
-                       if(res != N && (res->op == OREGISTER || res->op == OINDREG)) {
-                               r = res->val.u.reg;
-                               reg[r]--;
-                       }
-               }
-               switch(n->op) {
-               case OCALLMETH:
-                       cgen_callmeth(n, 0);
-                       break;
-               case OCALLFUNC:
-                       cgen_call(n, 0);
-                       break;
-               case OCALLINTER:
-                       cgen_callinter(n, N, 0);
-                       break;
-               }
-               if(r >= 0)
-                       reg[r]++;
-               regalloc(a, types[tptr], res);
-               cgen_aret(n, a);
-               a->op = OINDREG;
-               a->type = n->type;
-               return;
-       }
-
-       agenr(n, a, res);
-       a->op = OINDREG;
-       a->type = n->type;
-}
-
-/*
- * allocate a register in res and generate
- *  newreg = &n
- * The caller must call regfree(a).
- */
-void
-cgenr(Node *n, Node *a, Node *res)
-{
-       Node n1;
-
-       if(debug['g'])
-               dump("cgenr-n", n);
-
-       if(isfat(n->type))
-               fatal("cgenr on fat node");
-
-       if(n->addable) {
-               regalloc(a, types[tptr], res);
-               gmove(n, a);
-               return;
-       }
-
-       switch(n->op) {
-       case ONAME:
-       case ODOT:
-       case ODOTPTR:
-       case OINDEX:
-       case OCALLFUNC:
-       case OCALLMETH:
-       case OCALLINTER:
-               igen(n, &n1, res);
-               regalloc(a, types[tptr], &n1);
-               gmove(&n1, a);
-               regfree(&n1);
-               break;
-       default:
-               regalloc(a, n->type, res);
-               cgen(n, a);
-               break;
-       }
-}
-
-/*
- * generate:
- *     newreg = &n;
- *
- * caller must regfree(a).
- * The generated code checks that the result is not nil.
- */
-void
-agenr(Node *n, Node *a, Node *res)
-{
-       Node *nl, *nr;
-       Node n1, n2, n3, n4, tmp;
-       Prog *p1, *p2;
-       uint32 w;
-       uint64 v;
-       int bounded;
-
-       if(debug['g'])
-               dump("agenr-n", n);
-
-       nl = n->left;
-       nr = n->right;
-
-       switch(n->op) {
-       case ODOT:
-       case ODOTPTR:
-       case OCALLFUNC:
-       case OCALLMETH:
-       case OCALLINTER:
-               igen(n, &n1, res);
-               regalloc(a, types[tptr], &n1);
-               agen(&n1, a);
-               regfree(&n1);
-               break;
-
-       case OIND:
-               cgenr(n->left, a, res);
-               cgen_checknil(a);
-               break;
-
-       case OINDEX:
-               p2 = nil;  // to be patched to panicindex.
-               w = n->type->width;
-               bounded = debug['B'] || n->bounded;
-               if(nr->addable) {
-                       if(!isconst(nr, CTINT))
-                               tempname(&tmp, types[TINT32]);
-                       if(!isconst(nl, CTSTR))
-                               agenr(nl, &n3, res);
-                       if(!isconst(nr, CTINT)) {
-                               p2 = cgenindex(nr, &tmp, bounded);
-                               regalloc(&n1, tmp.type, N);
-                               gmove(&tmp, &n1);
-                       }
-               } else
-               if(nl->addable) {
-                       if(!isconst(nr, CTINT)) {
-                               tempname(&tmp, types[TINT32]);
-                               p2 = cgenindex(nr, &tmp, bounded);
-                               regalloc(&n1, tmp.type, N);
-                               gmove(&tmp, &n1);
-                       }
-                       if(!isconst(nl, CTSTR)) {
-                               agenr(nl, &n3, res);
-                       }
-               } else {
-                       tempname(&tmp, types[TINT32]);
-                       p2 = cgenindex(nr, &tmp, bounded);
-                       nr = &tmp;
-                       if(!isconst(nl, CTSTR))
-                               agenr(nl, &n3, res);
-                       regalloc(&n1, tmp.type, N);
-                       gins(optoas(OAS, tmp.type), &tmp, &n1);
-               }
-
-               // &a is in &n3 (allocated in res)
-               // i is in &n1 (if not constant)
-               // w is width
-
-               // constant index
-               if(isconst(nr, CTINT)) {
-                       if(isconst(nl, CTSTR))
-                               fatal("constant string constant index");
-                       v = mpgetfix(nr->val.u.xval);
-                       if(isslice(nl->type) || nl->type->etype == TSTRING) {
-                               if(!debug['B'] && !n->bounded) {
-                                       n1 = n3;
-                                       n1.op = OINDREG;
-                                       n1.type = types[tptr];
-                                       n1.xoffset = Array_nel;
-                                       regalloc(&n4, n1.type, N);
-                                       gmove(&n1, &n4);
-                                       nodconst(&n2, types[TUINT32], v);
-                                       gcmp(optoas(OCMP, types[TUINT32]), &n4, &n2);
-                                       regfree(&n4);
-                                       p1 = gbranch(optoas(OGT, types[TUINT32]), T, +1);
-                                       ginscall(panicindex, 0);
-                                       patch(p1, pc);
-                               }
-
-                               n1 = n3;
-                               n1.op = OINDREG;
-                               n1.type = types[tptr];
-                               n1.xoffset = Array_array;
-                               gmove(&n1, &n3);
-                       }
-
-                       nodconst(&n2, types[tptr], v*w);
-                       gins(optoas(OADD, types[tptr]), &n2, &n3);
-                       *a = n3;
-                       break;
-               }
-
-               regalloc(&n2, types[TINT32], &n1);                      // i
-               gmove(&n1, &n2);
-               regfree(&n1);
-
-               if(!debug['B'] && !n->bounded) {
-                       // check bounds
-                       if(isconst(nl, CTSTR)) {
-                               nodconst(&n4, types[TUINT32], nl->val.u.sval->len);
-                       } else if(isslice(nl->type) || nl->type->etype == TSTRING) {
-                               n1 = n3;
-                               n1.op = OINDREG;
-                               n1.type = types[tptr];
-                               n1.xoffset = Array_nel;
-                               regalloc(&n4, types[TUINT32], N);
-                               gmove(&n1, &n4);
-                       } else {
-                               nodconst(&n4, types[TUINT32], nl->type->bound);
-                       }
-                       gcmp(optoas(OCMP, types[TUINT32]), &n2, &n4);
-                       if(n4.op == OREGISTER)
-                               regfree(&n4);
-                       p1 = gbranch(optoas(OLT, types[TUINT32]), T, +1);
-                       if(p2)
-                               patch(p2, pc);
-                       ginscall(panicindex, 0);
-                       patch(p1, pc);
-               }
-               
-               if(isconst(nl, CTSTR)) {
-                       regalloc(&n3, types[tptr], res);
-                       p1 = gins(AMOVW, N, &n3);
-                       datastring(nl->val.u.sval->s, nl->val.u.sval->len, &p1->from);
-                       p1->from.type = TYPE_ADDR;
-               } else
-               if(isslice(nl->type) || nl->type->etype == TSTRING) {
-                       n1 = n3;
-                       n1.op = OINDREG;
-                       n1.type = types[tptr];
-                       n1.xoffset = Array_array;
-                       gmove(&n1, &n3);
-               }
-
-               if(w == 0) {
-                       // nothing to do
-               } else if(w == 1 || w == 2 || w == 4 || w == 8) {
-                       memset(&n4, 0, sizeof n4);
-                       n4.op = OADDR;
-                       n4.left = &n2;
-                       cgen(&n4, &n3);
-                       if (w == 1)
-                               gins(AADD, &n2, &n3);
-                       else if(w == 2)
-                               gshift(AADD, &n2, SHIFT_LL, 1, &n3);
-                       else if(w == 4)
-                               gshift(AADD, &n2, SHIFT_LL, 2, &n3);
-                       else if(w == 8)
-                               gshift(AADD, &n2, SHIFT_LL, 3, &n3);
-               } else {
-                       regalloc(&n4, types[TUINT32], N);
-                       nodconst(&n1, types[TUINT32], w);
-                       gmove(&n1, &n4);
-                       gins(optoas(OMUL, types[TUINT32]), &n4, &n2);
-                       gins(optoas(OADD, types[tptr]), &n2, &n3);
-                       regfree(&n4);
-               }
-
-               *a = n3;
-               regfree(&n2);
-               break;
-
-       default:
-               regalloc(a, types[tptr], res);
-               agen(n, a);
-               break;
-       }
-}
-
-void
-gencmp0(Node *n, Type *t, int o, int likely, Prog *to)
-{
-       Node n1, n2, n3;
-       int a;
-
-       regalloc(&n1, t, N);
-       cgen(n, &n1);
-       a = optoas(OCMP, t);
-       if(a != ACMP) {
-               nodconst(&n2, t, 0);
-               regalloc(&n3, t, N);
-               gmove(&n2, &n3);
-               gcmp(a, &n1, &n3);
-               regfree(&n3);
-       } else
-               gins(ATST, &n1, N);
-       a = optoas(o, t);
-       patch(gbranch(a, t, likely), to);
-       regfree(&n1);
-}
-
-/*
- * generate:
- *     if(n == true) goto to;
- */
-void
-bgen(Node *n, int true, int likely, Prog *to)
-{
-       int et, a;
-       Node *nl, *nr, *r;
-       Node n1, n2, n3, tmp;
-       NodeList *ll;
-       Prog *p1, *p2;
-
-       if(debug['g']) {
-               dump("\nbgen", n);
-       }
-
-       if(n == N)
-               n = nodbool(1);
-
-       if(n->ninit != nil)
-               genlist(n->ninit);
-
-       if(n->type == T) {
-               convlit(&n, types[TBOOL]);
-               if(n->type == T)
-                       goto ret;
-       }
-
-       et = n->type->etype;
-       if(et != TBOOL) {
-               yyerror("cgen: bad type %T for %O", n->type, n->op);
-               patch(gins(AEND, N, N), to);
-               goto ret;
-       }
-       nr = N;
-
-       switch(n->op) {
-       default:
-               a = ONE;
-               if(!true)
-                       a = OEQ;
-               gencmp0(n, n->type, a, likely, to);
-               goto ret;
-
-       case OLITERAL:
-               // need to ask if it is bool?
-               if(!true == !n->val.u.bval)
-                       patch(gbranch(AB, T, 0), to);
-               goto ret;
-
-       case OANDAND:
-       case OOROR:
-               if((n->op == OANDAND) == true) {
-                       p1 = gbranch(AJMP, T, 0);
-                       p2 = gbranch(AJMP, T, 0);
-                       patch(p1, pc);
-                       bgen(n->left, !true, -likely, p2);
-                       bgen(n->right, !true, -likely, p2);
-                       p1 = gbranch(AJMP, T, 0);
-                       patch(p1, to);
-                       patch(p2, pc);
-               } else {
-                       bgen(n->left, true, likely, to);
-                       bgen(n->right, true, likely, to);
-               }
-               goto ret;
-
-       case OEQ:
-       case ONE:
-       case OLT:
-       case OGT:
-       case OLE:
-       case OGE:
-               nr = n->right;
-               if(nr == N || nr->type == T)
-                       goto ret;
-
-       case ONOT:      // unary
-               nl = n->left;
-               if(nl == N || nl->type == T)
-                       goto ret;
-       }
-
-       switch(n->op) {
-
-       case ONOT:
-               bgen(nl, !true, likely, to);
-               goto ret;
-
-       case OEQ:
-       case ONE:
-       case OLT:
-       case OGT:
-       case OLE:
-       case OGE:
-               a = n->op;
-               if(!true) {
-                       if(isfloat[nl->type->etype]) {
-                               // brcom is not valid on floats when NaN is involved.
-                               p1 = gbranch(AB, T, 0);
-                               p2 = gbranch(AB, T, 0);
-                               patch(p1, pc);
-                               ll = n->ninit;
-                               n->ninit = nil;
-                               bgen(n, 1, -likely, p2);
-                               n->ninit = ll;
-                               patch(gbranch(AB, T, 0), to);
-                               patch(p2, pc);
-                               goto ret;
-                       }                               
-                       a = brcom(a);
-                       true = !true;
-               }
-
-               // make simplest on right
-               if(nl->op == OLITERAL || (nl->ullman < UINF && nl->ullman < nr->ullman)) {
-                       a = brrev(a);
-                       r = nl;
-                       nl = nr;
-                       nr = r;
-               }
-
-               if(isslice(nl->type)) {
-                       // only valid to cmp darray to literal nil
-                       if((a != OEQ && a != ONE) || nr->op != OLITERAL) {
-                               yyerror("illegal array comparison");
-                               break;
-                       }
-
-                       igen(nl, &n1, N);
-                       n1.xoffset += Array_array;
-                       n1.type = types[tptr];
-                       gencmp0(&n1, types[tptr], a, likely, to);
-                       regfree(&n1);
-                       break;
-               }
-
-               if(isinter(nl->type)) {
-                       // front end shold only leave cmp to literal nil
-                       if((a != OEQ && a != ONE) || nr->op != OLITERAL) {
-                               yyerror("illegal interface comparison");
-                               break;
-                       }
-
-                       igen(nl, &n1, N);
-                       n1.type = types[tptr];
-                       n1.xoffset += 0;
-                       gencmp0(&n1, types[tptr], a, likely, to);
-                       regfree(&n1);
-                       break;
-               }
-
-               if(iscomplex[nl->type->etype]) {
-                       complexbool(a, nl, nr, true, likely, to);
-                       break;
-               }
-
-               if(is64(nr->type)) {
-                       if(!nl->addable) {
-                               tempname(&n1, nl->type);
-                               cgen(nl, &n1);
-                               nl = &n1;
-                       }
-                       if(!nr->addable) {
-                               tempname(&n2, nr->type);
-                               cgen(nr, &n2);
-                               nr = &n2;
-                       }
-                       cmp64(nl, nr, a, likely, to);
-                       break;
-               }
-
-               if(nr->op == OLITERAL) {
-                       if(isconst(nr, CTINT) &&  mpgetfix(nr->val.u.xval) == 0) {
-                               gencmp0(nl, nl->type, a, likely, to);
-                               break;
-                       }
-                       if(nr->val.ctype == CTNIL) {
-                               gencmp0(nl, nl->type, a, likely, to);
-                               break;
-                       }
-               }
-
-               a = optoas(a, nr->type);
-
-               if(nr->ullman >= UINF) {
-                       regalloc(&n1, nl->type, N);
-                       cgen(nl, &n1);
-
-                       tempname(&tmp, nl->type);
-                       gmove(&n1, &tmp);
-                       regfree(&n1);
-
-                       regalloc(&n2, nr->type, N);
-                       cgen(nr, &n2);
-
-                       regalloc(&n1, nl->type, N);
-                       cgen(&tmp, &n1);
-
-                       gcmp(optoas(OCMP, nr->type), &n1, &n2);
-                       patch(gbranch(a, nr->type, likely), to);
-
-                       regfree(&n1);
-                       regfree(&n2);
-                       break;
-               }
-
-               tempname(&n3, nl->type);
-               cgen(nl, &n3);
-
-               tempname(&tmp, nr->type);
-               cgen(nr, &tmp);
-
-               regalloc(&n1, nl->type, N);
-               gmove(&n3, &n1);
-
-               regalloc(&n2, nr->type, N);
-               gmove(&tmp, &n2);
-
-               gcmp(optoas(OCMP, nr->type), &n1, &n2);
-               if(isfloat[nl->type->etype]) {
-                       if(n->op == ONE) {
-                               p1 = gbranch(ABVS, nr->type, likely);
-                               patch(gbranch(a, nr->type, likely), to);
-                               patch(p1, to);
-                       } else {
-                               p1 = gbranch(ABVS, nr->type, -likely);
-                               patch(gbranch(a, nr->type, likely), to);
-                               patch(p1, pc);
-                       }
-               } else {
-                       patch(gbranch(a, nr->type, likely), to);
-               }
-               regfree(&n1);
-               regfree(&n2);
-               break;
-       }
-       goto ret;
-
-ret:
-       ;
-}
-
-/*
- * n is on stack, either local variable
- * or return value from function call.
- * return n's offset from SP.
- */
-int32
-stkof(Node *n)
-{
-       Type *t;
-       Iter flist;
-       int32 off;
-
-       switch(n->op) {
-       case OINDREG:
-               return n->xoffset;
-
-       case ODOT:
-               t = n->left->type;
-               if(isptr[t->etype])
-                       break;
-               off = stkof(n->left);
-               if(off == -1000 || off == 1000)
-                       return off;
-               return off + n->xoffset;
-
-       case OINDEX:
-               t = n->left->type;
-               if(!isfixedarray(t))
-                       break;
-               off = stkof(n->left);
-               if(off == -1000 || off == 1000)
-                       return off;
-               if(isconst(n->right, CTINT))
-                       return off + t->type->width * mpgetfix(n->right->val.u.xval);
-               return 1000;
-               
-       case OCALLMETH:
-       case OCALLINTER:
-       case OCALLFUNC:
-               t = n->left->type;
-               if(isptr[t->etype])
-                       t = t->type;
-
-               t = structfirst(&flist, getoutarg(t));
-               if(t != T)
-                       return t->width + 4;    // correct for LR
-               break;
-       }
-
-       // botch - probably failing to recognize address
-       // arithmetic on the above. eg INDEX and DOT
-       return -1000;
-}
-
-/*
- * block copy:
- *     memmove(&res, &n, w);
- * NB: character copy assumed little endian architecture
- */
-void
-sgen(Node *n, Node *res, int64 w)
-{
-       Node dst, src, tmp, nend, r0, r1, r2, *f;
-       int32 c, odst, osrc;
-       int dir, align, op;
-       Prog *p, *ploop;
-       NodeList *l;
-
-       if(debug['g']) {
-               print("\nsgen w=%lld\n", w);
-               dump("r", n);
-               dump("res", res);
-       }
-
-       if(n->ullman >= UINF && res->ullman >= UINF)
-               fatal("sgen UINF");
-
-       if(w < 0 || (int32)w != w)
-               fatal("sgen copy %lld", w);
-
-       if(n->type == T)
-               fatal("sgen: missing type");
-
-       if(w == 0) {
-               // evaluate side effects only.
-               regalloc(&dst, types[tptr], N);
-               agen(res, &dst);
-               agen(n, &dst);
-               regfree(&dst);
-               return;
-       }
-
-       // If copying .args, that's all the results, so record definition sites
-       // for them for the liveness analysis.
-       if(res->op == ONAME && strcmp(res->sym->name, ".args") == 0)
-               for(l = curfn->dcl; l != nil; l = l->next)
-                       if(l->n->class == PPARAMOUT)
-                               gvardef(l->n);
-
-       // Avoid taking the address for simple enough types.
-       if(componentgen(n, res))
-               return;
-       
-       // determine alignment.
-       // want to avoid unaligned access, so have to use
-       // smaller operations for less aligned types.
-       // for example moving [4]byte must use 4 MOVB not 1 MOVW.
-       align = n->type->align;
-       switch(align) {
-       default:
-               fatal("sgen: invalid alignment %d for %T", align, n->type);
-       case 1:
-               op = AMOVB;
-               break;
-       case 2:
-               op = AMOVH;
-               break;
-       case 4:
-               op = AMOVW;
-               break;
-       }
-       if(w%align)
-               fatal("sgen: unaligned size %lld (align=%d) for %T", w, align, n->type);
-       c = w / align;
-
-       // offset on the stack
-       osrc = stkof(n);
-       odst = stkof(res);
-       if(osrc != -1000 && odst != -1000 && (osrc == 1000 || odst == 1000)) {
-               // osrc and odst both on stack, and at least one is in
-               // an unknown position.  Could generate code to test
-               // for forward/backward copy, but instead just copy
-               // to a temporary location first.
-               tempname(&tmp, n->type);
-               sgen(n, &tmp, w);
-               sgen(&tmp, res, w);
-               return;
-       }
-       if(osrc%align != 0 || odst%align != 0)
-               fatal("sgen: unaligned offset src %d or dst %d (align %d)", osrc, odst, align);
-
-       // if we are copying forward on the stack and
-       // the src and dst overlap, then reverse direction
-       dir = align;
-       if(osrc < odst && odst < osrc+w)
-               dir = -dir;
-
-       if(op == AMOVW && !nacl && dir > 0 && c >= 4 && c <= 128) {
-               r0.op = OREGISTER;
-               r0.val.u.reg = REGALLOC_R0;
-               r1.op = OREGISTER;
-               r1.val.u.reg = REGALLOC_R0 + 1;
-               r2.op = OREGISTER;
-               r2.val.u.reg = REGALLOC_R0 + 2;
-
-               regalloc(&src, types[tptr], &r1);
-               regalloc(&dst, types[tptr], &r2);
-               if(n->ullman >= res->ullman) {
-                       // eval n first
-                       agen(n, &src);
-                       if(res->op == ONAME)
-                               gvardef(res);
-                       agen(res, &dst);
-               } else {
-                       // eval res first
-                       if(res->op == ONAME)
-                               gvardef(res);
-                       agen(res, &dst);
-                       agen(n, &src);
-               }
-               regalloc(&tmp, types[tptr], &r0);
-               f = sysfunc("duffcopy");
-               p = gins(ADUFFCOPY, N, f);
-               afunclit(&p->to, f);
-               // 8 and 128 = magic constants: see ../../runtime/asm_arm.s
-               p->to.offset = 8*(128-c);
-
-               regfree(&tmp);
-               regfree(&src);
-               regfree(&dst);
-               return;
-       }
-       
-       if(n->ullman >= res->ullman) {
-               agenr(n, &dst, res);    // temporarily use dst
-               regalloc(&src, types[tptr], N);
-               gins(AMOVW, &dst, &src);
-               if(res->op == ONAME)
-                       gvardef(res);
-               agen(res, &dst);
-       } else {
-               if(res->op == ONAME)
-                       gvardef(res);
-               agenr(res, &dst, res);
-               agenr(n, &src, N);
-       }
-
-       regalloc(&tmp, types[TUINT32], N);
-
-       // set up end marker
-       memset(&nend, 0, sizeof nend);
-       if(c >= 4) {
-               regalloc(&nend, types[TUINT32], N);
-
-               p = gins(AMOVW, &src, &nend);
-               p->from.type = TYPE_ADDR;
-               if(dir < 0)
-                       p->from.offset = dir;
-               else
-                       p->from.offset = w;
-       }
-
-       // move src and dest to the end of block if necessary
-       if(dir < 0) {
-               p = gins(AMOVW, &src, &src);
-               p->from.type = TYPE_ADDR;
-               p->from.offset = w + dir;
-
-               p = gins(AMOVW, &dst, &dst);
-               p->from.type = TYPE_ADDR;
-               p->from.offset = w + dir;
-       }
-       
-       // move
-       if(c >= 4) {
-               p = gins(op, &src, &tmp);
-               p->from.type = TYPE_MEM;
-               p->from.offset = dir;
-               p->scond |= C_PBIT;
-               ploop = p;
-
-               p = gins(op, &tmp, &dst);
-               p->to.type = TYPE_MEM;
-               p->to.offset = dir;
-               p->scond |= C_PBIT;
-
-               p = gins(ACMP, &src, N);
-               raddr(&nend, p);
-
-               patch(gbranch(ABNE, T, 0), ploop);
-               regfree(&nend);
-       } else {
-               while(c-- > 0) {
-                       p = gins(op, &src, &tmp);
-                       p->from.type = TYPE_MEM;
-                       p->from.offset = dir;
-                       p->scond |= C_PBIT;
-       
-                       p = gins(op, &tmp, &dst);
-                       p->to.type = TYPE_MEM;
-                       p->to.offset = dir;
-                       p->scond |= C_PBIT;
-               }
-       }
-
-       regfree(&dst);
-       regfree(&src);
-       regfree(&tmp);
-}
-
-static int
-cadable(Node *n)
-{
-       if(!n->addable) {
-               // dont know how it happens,
-               // but it does
-               return 0;
-       }
-
-       switch(n->op) {
-       case ONAME:
-               return 1;
-       }
-       return 0;
-}
-
-/*
- * copy a composite value by moving its individual components.
- * Slices, strings and interfaces are supported.
- * Small structs or arrays with elements of basic type are
- * also supported.
- * nr is N when assigning a zero value.
- * return 1 if can do, 0 if cant.
- */
-int
-componentgen(Node *nr, Node *nl)
-{
-       Node nodl, nodr, tmp;
-       Type *t;
-       int freel, freer;
-       vlong fldcount;
-       vlong loffset, roffset;
-
-       freel = 0;
-       freer = 0;
-
-       switch(nl->type->etype) {
-       default:
-               goto no;
-
-       case TARRAY:
-               t = nl->type;
-
-               // Slices are ok.
-               if(isslice(t))
-                       break;
-               // Small arrays are ok.
-               if(t->bound > 0 && t->bound <= 3 && !isfat(t->type))
-                       break;
-
-               goto no;
-
-       case TSTRUCT:
-               // Small structs with non-fat types are ok.
-               // Zero-sized structs are treated separately elsewhere.
-               fldcount = 0;
-               for(t=nl->type->type; t; t=t->down) {
-                       if(isfat(t->type))
-                               goto no;
-                       if(t->etype != TFIELD)
-                               fatal("componentgen: not a TFIELD: %lT", t);
-                       fldcount++;
-               }
-               if(fldcount == 0 || fldcount > 4)
-                       goto no;
-
-               break;
-
-       case TSTRING:
-       case TINTER:
-               break;
-       }
-
-       nodl = *nl;
-       if(!cadable(nl)) {
-               if(nr != N && !cadable(nr))
-                       goto no;
-               igen(nl, &nodl, N);
-               freel = 1;
-       }
-
-       if(nr != N) {
-               nodr = *nr;
-               if(!cadable(nr)) {
-                       igen(nr, &nodr, N);
-                       freer = 1;
-               }
-       } else {
-               // When zeroing, prepare a register containing zero.
-               nodconst(&tmp, nl->type, 0);
-               regalloc(&nodr, types[TUINT], N);
-               gmove(&tmp, &nodr);
-               freer = 1;
-       }
-
-       // nl and nr are 'cadable' which basically means they are names (variables) now.
-       // If they are the same variable, don't generate any code, because the
-       // VARDEF we generate will mark the old value as dead incorrectly.
-       // (And also the assignments are useless.)
-       if(nr != N && nl->op == ONAME && nr->op == ONAME && nl == nr)
-               goto yes;
-
-       switch(nl->type->etype) {
-       case TARRAY:
-               // componentgen for arrays.
-               if(nl->op == ONAME)
-                       gvardef(nl);
-               t = nl->type;
-               if(!isslice(t)) {
-                       nodl.type = t->type;
-                       nodr.type = nodl.type;
-                       for(fldcount=0; fldcount < t->bound; fldcount++) {
-                               if(nr == N)
-                                       clearslim(&nodl);
-                               else
-                                       gmove(&nodr, &nodl);
-                               nodl.xoffset += t->type->width;
-                               nodr.xoffset += t->type->width;
-                       }
-                       goto yes;
-               }
-
-               // componentgen for slices.
-               nodl.xoffset += Array_array;
-               nodl.type = ptrto(nl->type->type);
-
-               if(nr != N) {
-                       nodr.xoffset += Array_array;
-                       nodr.type = nodl.type;
-               }
-               gmove(&nodr, &nodl);
-
-               nodl.xoffset += Array_nel-Array_array;
-               nodl.type = types[simtype[TUINT]];
-
-               if(nr != N) {
-                       nodr.xoffset += Array_nel-Array_array;
-                       nodr.type = nodl.type;
-               }
-               gmove(&nodr, &nodl);
-
-               nodl.xoffset += Array_cap-Array_nel;
-               nodl.type = types[simtype[TUINT]];
-
-               if(nr != N) {
-                       nodr.xoffset += Array_cap-Array_nel;
-                       nodr.type = nodl.type;
-               }
-               gmove(&nodr, &nodl);
-
-               goto yes;
-
-       case TSTRING:
-               if(nl->op == ONAME)
-                       gvardef(nl);
-               nodl.xoffset += Array_array;
-               nodl.type = ptrto(types[TUINT8]);
-
-               if(nr != N) {
-                       nodr.xoffset += Array_array;
-                       nodr.type = nodl.type;
-               }
-               gmove(&nodr, &nodl);
-
-               nodl.xoffset += Array_nel-Array_array;
-               nodl.type = types[simtype[TUINT]];
-
-               if(nr != N) {
-                       nodr.xoffset += Array_nel-Array_array;
-                       nodr.type = nodl.type;
-               }
-               gmove(&nodr, &nodl);
-
-               goto yes;
-
-       case TINTER:
-               if(nl->op == ONAME)
-                       gvardef(nl);
-               nodl.xoffset += Array_array;
-               nodl.type = ptrto(types[TUINT8]);
-
-               if(nr != N) {
-                       nodr.xoffset += Array_array;
-                       nodr.type = nodl.type;
-               }
-               gmove(&nodr, &nodl);
-
-               nodl.xoffset += Array_nel-Array_array;
-               nodl.type = ptrto(types[TUINT8]);
-
-               if(nr != N) {
-                       nodr.xoffset += Array_nel-Array_array;
-                       nodr.type = nodl.type;
-               }
-               gmove(&nodr, &nodl);
-
-               goto yes;
-
-       case TSTRUCT:
-               if(nl->op == ONAME)
-                       gvardef(nl);
-               loffset = nodl.xoffset;
-               roffset = nodr.xoffset;
-               // funarg structs may not begin at offset zero.
-               if(nl->type->etype == TSTRUCT && nl->type->funarg && nl->type->type)
-                       loffset -= nl->type->type->width;
-               if(nr != N && nr->type->etype == TSTRUCT && nr->type->funarg && nr->type->type)
-                       roffset -= nr->type->type->width;
-
-               for(t=nl->type->type; t; t=t->down) {
-                       nodl.xoffset = loffset + t->width;
-                       nodl.type = t->type;
-
-                       if(nr == N)
-                               clearslim(&nodl);
-                       else {
-                               nodr.xoffset = roffset + t->width;
-                               nodr.type = nodl.type;
-                               gmove(&nodr, &nodl);
-                       }
-               }
-               goto yes;
-       }
-
-no:
-       if(freer)
-               regfree(&nodr);
-       if(freel)
-               regfree(&nodl);
-       return 0;
-
-yes:
-       if(freer)
-               regfree(&nodr);
-       if(freel)
-               regfree(&nodl);
-       return 1;
-}
similarity index 100%
rename from src/cmd/new5g/cgen.go
rename to src/cmd/5g/cgen.go
diff --git a/src/cmd/5g/cgen64.c b/src/cmd/5g/cgen64.c
deleted file mode 100644 (file)
index 9abab4c..0000000
+++ /dev/null
@@ -1,760 +0,0 @@
-// Copyright 2009 The Go Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style
-// license that can be found in the LICENSE file.
-
-#include <u.h>
-#include <libc.h>
-#include "gg.h"
-
-/*
- * attempt to generate 64-bit
- *     res = n
- * return 1 on success, 0 if op not handled.
- */
-void
-cgen64(Node *n, Node *res)
-{
-       Node t1, t2, *l, *r;
-       Node lo1, lo2, hi1, hi2;
-       Node al, ah, bl, bh, cl, ch, s, n1, creg;
-       Prog *p1, *p2, *p3, *p4, *p5, *p6;
-
-       uint64 v;
-
-       if(res->op != OINDREG && res->op != ONAME) {
-               dump("n", n);
-               dump("res", res);
-               fatal("cgen64 %O of %O", n->op, res->op);
-       }
-
-       l = n->left;
-       if(!l->addable) {
-               tempname(&t1, l->type);
-               cgen(l, &t1);
-               l = &t1;
-       }
-
-       split64(l, &lo1, &hi1);
-       switch(n->op) {
-       default:
-               fatal("cgen64 %O", n->op);
-
-       case OMINUS:
-               split64(res, &lo2, &hi2);
-
-               regalloc(&t1, lo1.type, N);
-               regalloc(&al, lo1.type, N);
-               regalloc(&ah, hi1.type, N);
-
-               gins(AMOVW, &lo1, &al);
-               gins(AMOVW, &hi1, &ah);
-
-               gmove(ncon(0), &t1);
-               p1 = gins(ASUB, &al, &t1);
-               p1->scond |= C_SBIT;
-               gins(AMOVW, &t1, &lo2);
-
-               gmove(ncon(0), &t1);
-               gins(ASBC, &ah, &t1);
-               gins(AMOVW, &t1, &hi2);
-
-               regfree(&t1);
-               regfree(&al);
-               regfree(&ah);
-               splitclean();
-               splitclean();
-               return;
-
-       case OCOM:
-               regalloc(&t1, lo1.type, N);
-               gmove(ncon(-1), &t1);
-
-               split64(res, &lo2, &hi2);
-               regalloc(&n1, lo1.type, N);
-
-               gins(AMOVW, &lo1, &n1);
-               gins(AEOR, &t1, &n1);
-               gins(AMOVW, &n1, &lo2);
-
-               gins(AMOVW, &hi1, &n1);
-               gins(AEOR, &t1, &n1);
-               gins(AMOVW, &n1, &hi2);
-
-               regfree(&t1);
-               regfree(&n1);
-               splitclean();
-               splitclean();
-               return;
-
-       case OADD:
-       case OSUB:
-       case OMUL:
-       case OLSH:
-       case ORSH:
-       case OAND:
-       case OOR:
-       case OXOR:
-       case OLROT:
-               // binary operators.
-               // common setup below.
-               break;
-       }
-
-       // setup for binary operators
-       r = n->right;
-       if(r != N && !r->addable) {
-               tempname(&t2, r->type);
-               cgen(r, &t2);
-               r = &t2;
-       }
-       if(is64(r->type))
-               split64(r, &lo2, &hi2);
-
-       regalloc(&al, lo1.type, N);
-       regalloc(&ah, hi1.type, N);
-
-       // Do op.  Leave result in ah:al.
-       switch(n->op) {
-       default:
-               fatal("cgen64: not implemented: %N\n", n);
-
-       case OADD:
-               // TODO: Constants
-               regalloc(&bl, types[TPTR32], N);
-               regalloc(&bh, types[TPTR32], N);
-               gins(AMOVW, &hi1, &ah);
-               gins(AMOVW, &lo1, &al);
-               gins(AMOVW, &hi2, &bh);
-               gins(AMOVW, &lo2, &bl);
-               p1 = gins(AADD, &bl, &al);
-               p1->scond |= C_SBIT;
-               gins(AADC, &bh, &ah);
-               regfree(&bl);
-               regfree(&bh);
-               break;
-
-       case OSUB:
-               // TODO: Constants.
-               regalloc(&bl, types[TPTR32], N);
-               regalloc(&bh, types[TPTR32], N);
-               gins(AMOVW, &lo1, &al);
-               gins(AMOVW, &hi1, &ah);
-               gins(AMOVW, &lo2, &bl);
-               gins(AMOVW, &hi2, &bh);
-               p1 = gins(ASUB, &bl, &al);
-               p1->scond |= C_SBIT;
-               gins(ASBC, &bh, &ah);
-               regfree(&bl);
-               regfree(&bh);
-               break;
-
-       case OMUL:
-               // TODO(kaib): this can be done with 4 regs and does not need 6
-               regalloc(&bl, types[TPTR32], N);
-               regalloc(&bh, types[TPTR32], N);
-               regalloc(&cl, types[TPTR32], N);
-               regalloc(&ch, types[TPTR32], N);
-
-               // load args into bh:bl and bh:bl.
-               gins(AMOVW, &hi1, &bh);
-               gins(AMOVW, &lo1, &bl);
-               gins(AMOVW, &hi2, &ch);
-               gins(AMOVW, &lo2, &cl);
-
-               // bl * cl -> ah al
-               p1 = gins(AMULLU, N, N);
-               p1->from.type = TYPE_REG;
-               p1->from.reg = bl.val.u.reg;
-               p1->reg = cl.val.u.reg;
-               p1->to.type = TYPE_REGREG;
-               p1->to.reg = ah.val.u.reg;
-               p1->to.offset = al.val.u.reg;
-//print("%P\n", p1);
-
-               // bl * ch + ah -> ah
-               p1 = gins(AMULA, N, N);
-               p1->from.type = TYPE_REG;
-               p1->from.reg = bl.val.u.reg;
-               p1->reg = ch.val.u.reg;
-               p1->to.type = TYPE_REGREG2;
-               p1->to.reg = ah.val.u.reg;
-               p1->to.offset = ah.val.u.reg;
-//print("%P\n", p1);
-
-               // bh * cl + ah -> ah
-               p1 = gins(AMULA, N, N);
-               p1->from.type = TYPE_REG;
-               p1->from.reg = bh.val.u.reg;
-               p1->reg = cl.val.u.reg;
-               p1->to.type = TYPE_REGREG2;
-               p1->to.reg = ah.val.u.reg;
-               p1->to.offset = ah.val.u.reg;
-//print("%P\n", p1);
-
-               regfree(&bh);
-               regfree(&bl);
-               regfree(&ch);
-               regfree(&cl);
-
-               break;
-
-       case OLROT:
-               // We only rotate by a constant c in [0,64).
-               // if c >= 32:
-               //      lo, hi = hi, lo
-               //      c -= 32
-               // if c == 0:
-               //      no-op
-               // else:
-               //      t = hi
-               //      shld hi:lo, c
-               //      shld lo:t, c
-               v = mpgetfix(r->val.u.xval);
-               regalloc(&bl, lo1.type, N);
-               regalloc(&bh, hi1.type, N);
-               if(v >= 32) {
-                       // reverse during load to do the first 32 bits of rotate
-                       v -= 32;
-                       gins(AMOVW, &hi1, &bl);
-                       gins(AMOVW, &lo1, &bh);
-               } else {
-                       gins(AMOVW, &hi1, &bh);
-                       gins(AMOVW, &lo1, &bl);
-               }
-               if(v == 0) {
-                       gins(AMOVW, &bh, &ah);
-                       gins(AMOVW, &bl, &al);
-               } else {
-                       // rotate by 1 <= v <= 31
-                       //      MOVW    bl<<v, al
-                       //      MOVW    bh<<v, ah
-                       //      OR              bl>>(32-v), ah
-                       //      OR              bh>>(32-v), al
-                       gshift(AMOVW, &bl, SHIFT_LL, v, &al);
-                       gshift(AMOVW, &bh, SHIFT_LL, v, &ah);
-                       gshift(AORR, &bl, SHIFT_LR, 32-v, &ah);
-                       gshift(AORR, &bh, SHIFT_LR, 32-v, &al);
-               }
-               regfree(&bl);
-               regfree(&bh);
-               break;
-
-       case OLSH:
-               regalloc(&bl, lo1.type, N);
-               regalloc(&bh, hi1.type, N);
-               gins(AMOVW, &hi1, &bh);
-               gins(AMOVW, &lo1, &bl);
-
-               if(r->op == OLITERAL) {
-                       v = mpgetfix(r->val.u.xval);
-                       if(v >= 64) {
-                               // TODO(kaib): replace with gins(AMOVW, nodintconst(0), &al)
-                               // here and below (verify it optimizes to EOR)
-                               gins(AEOR, &al, &al);
-                               gins(AEOR, &ah, &ah);
-                       } else
-                       if(v > 32) {
-                               gins(AEOR, &al, &al);
-                               //      MOVW    bl<<(v-32), ah
-                               gshift(AMOVW, &bl, SHIFT_LL, (v-32), &ah);
-                       } else
-                       if(v == 32) {
-                               gins(AEOR, &al, &al);
-                               gins(AMOVW, &bl, &ah);
-                       } else
-                       if(v > 0) {
-                               //      MOVW    bl<<v, al
-                               gshift(AMOVW, &bl, SHIFT_LL, v, &al);
-
-                               //      MOVW    bh<<v, ah
-                               gshift(AMOVW, &bh, SHIFT_LL, v, &ah);
-
-                               //      OR              bl>>(32-v), ah
-                               gshift(AORR, &bl, SHIFT_LR, 32-v, &ah);
-                       } else {
-                               gins(AMOVW, &bl, &al);
-                               gins(AMOVW, &bh, &ah);
-                       }
-                       goto olsh_break;
-               }
-
-               regalloc(&s, types[TUINT32], N);
-               regalloc(&creg, types[TUINT32], N);
-               if (is64(r->type)) {
-                       // shift is >= 1<<32
-                       split64(r, &cl, &ch);
-                       gmove(&ch, &s);
-                       gins(ATST, &s, N);
-                       p6 = gbranch(ABNE, T, 0);
-                       gmove(&cl, &s);
-                       splitclean();
-               } else {
-                       gmove(r, &s);
-                       p6 = P;
-               }
-               gins(ATST, &s, N);
-
-               // shift == 0
-               p1 = gins(AMOVW, &bl, &al);
-               p1->scond = C_SCOND_EQ;
-               p1 = gins(AMOVW, &bh, &ah);
-               p1->scond = C_SCOND_EQ;
-               p2 = gbranch(ABEQ, T, 0);
-
-               // shift is < 32
-               nodconst(&n1, types[TUINT32], 32);
-               gmove(&n1, &creg);
-               gcmp(ACMP, &s, &creg);
-
-               //      MOVW.LO         bl<<s, al
-               p1 = gregshift(AMOVW, &bl, SHIFT_LL, &s, &al);
-               p1->scond = C_SCOND_LO;
-
-               //      MOVW.LO         bh<<s, ah
-               p1 = gregshift(AMOVW, &bh, SHIFT_LL, &s, &ah);
-               p1->scond = C_SCOND_LO;
-
-               //      SUB.LO          s, creg
-               p1 = gins(ASUB, &s, &creg);
-               p1->scond = C_SCOND_LO;
-
-               //      OR.LO           bl>>creg, ah
-               p1 = gregshift(AORR, &bl, SHIFT_LR, &creg, &ah);
-               p1->scond = C_SCOND_LO;
-
-               //      BLO     end
-               p3 = gbranch(ABLO, T, 0);
-
-               // shift == 32
-               p1 = gins(AEOR, &al, &al);
-               p1->scond = C_SCOND_EQ;
-               p1 = gins(AMOVW, &bl, &ah);
-               p1->scond = C_SCOND_EQ;
-               p4 = gbranch(ABEQ, T, 0);
-
-               // shift is < 64
-               nodconst(&n1, types[TUINT32], 64);
-               gmove(&n1, &creg);
-               gcmp(ACMP, &s, &creg);
-
-               //      EOR.LO  al, al
-               p1 = gins(AEOR, &al, &al);
-               p1->scond = C_SCOND_LO;
-
-               //      MOVW.LO         creg>>1, creg
-               p1 = gshift(AMOVW, &creg, SHIFT_LR, 1, &creg);
-               p1->scond = C_SCOND_LO;
-
-               //      SUB.LO          creg, s
-               p1 = gins(ASUB, &creg, &s);
-               p1->scond = C_SCOND_LO;
-
-               //      MOVW    bl<<s, ah
-               p1 = gregshift(AMOVW, &bl, SHIFT_LL, &s, &ah);
-               p1->scond = C_SCOND_LO;
-
-               p5 = gbranch(ABLO, T, 0);
-
-               // shift >= 64
-               if (p6 != P) patch(p6, pc);
-               gins(AEOR, &al, &al);
-               gins(AEOR, &ah, &ah);
-
-               patch(p2, pc);
-               patch(p3, pc);
-               patch(p4, pc);
-               patch(p5, pc);
-               regfree(&s);
-               regfree(&creg);
-
-olsh_break:
-               regfree(&bl);
-               regfree(&bh);
-               break;
-
-
-       case ORSH:
-               regalloc(&bl, lo1.type, N);
-               regalloc(&bh, hi1.type, N);
-               gins(AMOVW, &hi1, &bh);
-               gins(AMOVW, &lo1, &bl);
-
-               if(r->op == OLITERAL) {
-                       v = mpgetfix(r->val.u.xval);
-                       if(v >= 64) {
-                               if(bh.type->etype == TINT32) {
-                                       //      MOVW    bh->31, al
-                                       gshift(AMOVW, &bh, SHIFT_AR, 31, &al);
-
-                                       //      MOVW    bh->31, ah
-                                       gshift(AMOVW, &bh, SHIFT_AR, 31, &ah);
-                               } else {
-                                       gins(AEOR, &al, &al);
-                                       gins(AEOR, &ah, &ah);
-                               }
-                       } else
-                       if(v > 32) {
-                               if(bh.type->etype == TINT32) {
-                                       //      MOVW    bh->(v-32), al
-                                       gshift(AMOVW, &bh, SHIFT_AR, v-32, &al);
-
-                                       //      MOVW    bh->31, ah
-                                       gshift(AMOVW, &bh, SHIFT_AR, 31, &ah);
-                               } else {
-                                       //      MOVW    bh>>(v-32), al
-                                       gshift(AMOVW, &bh, SHIFT_LR, v-32, &al);
-                                       gins(AEOR, &ah, &ah);
-                               }
-                       } else
-                       if(v == 32) {
-                               gins(AMOVW, &bh, &al);
-                               if(bh.type->etype == TINT32) {
-                                       //      MOVW    bh->31, ah
-                                       gshift(AMOVW, &bh, SHIFT_AR, 31, &ah);
-                               } else {
-                                       gins(AEOR, &ah, &ah);
-                               }
-                       } else
-                       if( v > 0) {
-                               //      MOVW    bl>>v, al
-                               gshift(AMOVW, &bl, SHIFT_LR, v, &al);
-       
-                               //      OR              bh<<(32-v), al
-                               gshift(AORR, &bh, SHIFT_LL, 32-v, &al);
-
-                               if(bh.type->etype == TINT32) {
-                                       //      MOVW    bh->v, ah
-                                       gshift(AMOVW, &bh, SHIFT_AR, v, &ah);
-                               } else {
-                                       //      MOVW    bh>>v, ah
-                                       gshift(AMOVW, &bh, SHIFT_LR, v, &ah);
-                               }
-                       } else {
-                               gins(AMOVW, &bl, &al);
-                               gins(AMOVW, &bh, &ah);
-                       }
-                       goto orsh_break;
-               }
-
-               regalloc(&s, types[TUINT32], N);
-               regalloc(&creg, types[TUINT32], N);
-               if(is64(r->type)) {
-                       // shift is >= 1<<32
-                       split64(r, &cl, &ch);
-                       gmove(&ch, &s);
-                       gins(ATST, &s, N);
-                       if(bh.type->etype == TINT32)
-                               p1 = gshift(AMOVW, &bh, SHIFT_AR, 31, &ah);
-                       else
-                               p1 = gins(AEOR, &ah, &ah);
-                       p1->scond = C_SCOND_NE;
-                       p6 = gbranch(ABNE, T, 0);
-                       gmove(&cl, &s);
-                       splitclean();
-               } else {
-                       gmove(r, &s);
-                       p6 = P;
-               }
-               gins(ATST, &s, N);
-
-               // shift == 0
-               p1 = gins(AMOVW, &bl, &al);
-               p1->scond = C_SCOND_EQ;
-               p1 = gins(AMOVW, &bh, &ah);
-               p1->scond = C_SCOND_EQ;
-               p2 = gbranch(ABEQ, T, 0);
-
-               // check if shift is < 32
-               nodconst(&n1, types[TUINT32], 32);
-               gmove(&n1, &creg);
-               gcmp(ACMP, &s, &creg);
-
-               //      MOVW.LO         bl>>s, al
-               p1 = gregshift(AMOVW, &bl, SHIFT_LR, &s, &al);
-               p1->scond = C_SCOND_LO;
-
-               //      SUB.LO          s,creg
-               p1 = gins(ASUB, &s, &creg);
-               p1->scond = C_SCOND_LO;
-
-               //      OR.LO           bh<<(32-s), al
-               p1 = gregshift(AORR, &bh, SHIFT_LL, &creg, &al);
-               p1->scond = C_SCOND_LO;
-
-               if(bh.type->etype == TINT32) {
-                       //      MOVW    bh->s, ah
-                       p1 = gregshift(AMOVW, &bh, SHIFT_AR, &s, &ah);
-               } else {
-                       //      MOVW    bh>>s, ah
-                       p1 = gregshift(AMOVW, &bh, SHIFT_LR, &s, &ah);
-               }
-               p1->scond = C_SCOND_LO;
-
-               //      BLO     end
-               p3 = gbranch(ABLO, T, 0);
-
-               // shift == 32
-               p1 = gins(AMOVW, &bh, &al);
-               p1->scond = C_SCOND_EQ;
-               if(bh.type->etype == TINT32)
-                       gshift(AMOVW, &bh, SHIFT_AR, 31, &ah);
-               else
-                       gins(AEOR, &ah, &ah);
-               p4 = gbranch(ABEQ, T, 0);
-
-               // check if shift is < 64
-               nodconst(&n1, types[TUINT32], 64);
-               gmove(&n1, &creg);
-               gcmp(ACMP, &s, &creg);
-
-               //      MOVW.LO         creg>>1, creg
-               p1 = gshift(AMOVW, &creg, SHIFT_LR, 1, &creg);
-               p1->scond = C_SCOND_LO;
-
-               //      SUB.LO          creg, s
-               p1 = gins(ASUB, &creg, &s);
-               p1->scond = C_SCOND_LO;
-
-               if(bh.type->etype == TINT32) {
-                       //      MOVW    bh->(s-32), al
-                       p1 = gregshift(AMOVW, &bh, SHIFT_AR, &s, &al);
-                       p1->scond = C_SCOND_LO;
-               } else {
-                       //      MOVW    bh>>(v-32), al
-                       p1 = gregshift(AMOVW, &bh, SHIFT_LR, &s, &al);
-                       p1->scond = C_SCOND_LO;
-               }
-
-               //      BLO     end
-               p5 = gbranch(ABLO, T, 0);
-
-               // s >= 64
-               if(p6 != P)
-                       patch(p6, pc);
-               if(bh.type->etype == TINT32) {
-                       //      MOVW    bh->31, al
-                       gshift(AMOVW, &bh, SHIFT_AR, 31, &al);
-               } else {
-                       gins(AEOR, &al, &al);
-               }
-
-               patch(p2, pc);
-               patch(p3, pc);
-               patch(p4, pc);
-               patch(p5, pc);
-               regfree(&s);
-               regfree(&creg);
-
-
-orsh_break:
-               regfree(&bl);
-               regfree(&bh);
-               break;
-
-       case OXOR:
-       case OAND:
-       case OOR:
-               // TODO(kaib): literal optimizations
-               // make constant the right side (it usually is anyway).
-//             if(lo1.op == OLITERAL) {
-//                     nswap(&lo1, &lo2);
-//                     nswap(&hi1, &hi2);
-//             }
-//             if(lo2.op == OLITERAL) {
-//                     // special cases for constants.
-//                     lv = mpgetfix(lo2.val.u.xval);
-//                     hv = mpgetfix(hi2.val.u.xval);
-//                     splitclean();   // right side
-//                     split64(res, &lo2, &hi2);
-//                     switch(n->op) {
-//                     case OXOR:
-//                             gmove(&lo1, &lo2);
-//                             gmove(&hi1, &hi2);
-//                             switch(lv) {
-//                             case 0:
-//                                     break;
-//                             case 0xffffffffu:
-//                                     gins(ANOTL, N, &lo2);
-//                                     break;
-//                             default:
-//                                     gins(AXORL, ncon(lv), &lo2);
-//                                     break;
-//                             }
-//                             switch(hv) {
-//                             case 0:
-//                                     break;
-//                             case 0xffffffffu:
-//                                     gins(ANOTL, N, &hi2);
-//                                     break;
-//                             default:
-//                                     gins(AXORL, ncon(hv), &hi2);
-//                                     break;
-//                             }
-//                             break;
-
-//                     case OAND:
-//                             switch(lv) {
-//                             case 0:
-//                                     gins(AMOVL, ncon(0), &lo2);
-//                                     break;
-//                             default:
-//                                     gmove(&lo1, &lo2);
-//                                     if(lv != 0xffffffffu)
-//                                             gins(AANDL, ncon(lv), &lo2);
-//                                     break;
-//                             }
-//                             switch(hv) {
-//                             case 0:
-//                                     gins(AMOVL, ncon(0), &hi2);
-//                                     break;
-//                             default:
-//                                     gmove(&hi1, &hi2);
-//                                     if(hv != 0xffffffffu)
-//                                             gins(AANDL, ncon(hv), &hi2);
-//                                     break;
-//                             }
-//                             break;
-
-//                     case OOR:
-//                             switch(lv) {
-//                             case 0:
-//                                     gmove(&lo1, &lo2);
-//                                     break;
-//                             case 0xffffffffu:
-//                                     gins(AMOVL, ncon(0xffffffffu), &lo2);
-//                                     break;
-//                             default:
-//                                     gmove(&lo1, &lo2);
-//                                     gins(AORL, ncon(lv), &lo2);
-//                                     break;
-//                             }
-//                             switch(hv) {
-//                             case 0:
-//                                     gmove(&hi1, &hi2);
-//                                     break;
-//                             case 0xffffffffu:
-//                                     gins(AMOVL, ncon(0xffffffffu), &hi2);
-//                                     break;
-//                             default:
-//                                     gmove(&hi1, &hi2);
-//                                     gins(AORL, ncon(hv), &hi2);
-//                                     break;
-//                             }
-//                             break;
-//                     }
-//                     splitclean();
-//                     splitclean();
-//                     goto out;
-//             }
-               regalloc(&n1, lo1.type, N);
-               gins(AMOVW, &lo1, &al);
-               gins(AMOVW, &hi1, &ah);
-               gins(AMOVW, &lo2, &n1);
-               gins(optoas(n->op, lo1.type), &n1, &al);
-               gins(AMOVW, &hi2, &n1);
-               gins(optoas(n->op, lo1.type), &n1, &ah);
-               regfree(&n1);
-               break;
-       }
-       if(is64(r->type))
-               splitclean();
-       splitclean();
-
-       split64(res, &lo1, &hi1);
-       gins(AMOVW, &al, &lo1);
-       gins(AMOVW, &ah, &hi1);
-       splitclean();
-
-//out:
-       regfree(&al);
-       regfree(&ah);
-}
-
-/*
- * generate comparison of nl, nr, both 64-bit.
- * nl is memory; nr is constant or memory.
- */
-void
-cmp64(Node *nl, Node *nr, int op, int likely, Prog *to)
-{
-       Node lo1, hi1, lo2, hi2, r1, r2;
-       Prog *br;
-       Type *t;
-
-       split64(nl, &lo1, &hi1);
-       split64(nr, &lo2, &hi2);
-
-       // compare most significant word;
-       // if they differ, we're done.
-       t = hi1.type;
-       regalloc(&r1, types[TINT32], N);
-       regalloc(&r2, types[TINT32], N);
-       gins(AMOVW, &hi1, &r1);
-       gins(AMOVW, &hi2, &r2);
-       gcmp(ACMP, &r1, &r2);
-       regfree(&r1);
-       regfree(&r2);
-
-       br = P;
-       switch(op) {
-       default:
-               fatal("cmp64 %O %T", op, t);
-       case OEQ:
-               // cmp hi
-               // bne L
-               // cmp lo
-               // beq to
-               // L:
-               br = gbranch(ABNE, T, -likely);
-               break;
-       case ONE:
-               // cmp hi
-               // bne to
-               // cmp lo
-               // bne to
-               patch(gbranch(ABNE, T, likely), to);
-               break;
-       case OGE:
-       case OGT:
-               // cmp hi
-               // bgt to
-               // blt L
-               // cmp lo
-               // bge to (or bgt to)
-               // L:
-               patch(gbranch(optoas(OGT, t), T, likely), to);
-               br = gbranch(optoas(OLT, t), T, -likely);
-               break;
-       case OLE:
-       case OLT:
-               // cmp hi
-               // blt to
-               // bgt L
-               // cmp lo
-               // ble to (or jlt to)
-               // L:
-               patch(gbranch(optoas(OLT, t), T, likely), to);
-               br = gbranch(optoas(OGT, t), T, -likely);
-               break;
-       }
-
-       // compare least significant word
-       t = lo1.type;
-       regalloc(&r1, types[TINT32], N);
-       regalloc(&r2, types[TINT32], N);
-       gins(AMOVW, &lo1, &r1);
-       gins(AMOVW, &lo2, &r2);
-       gcmp(ACMP, &r1, &r2);
-       regfree(&r1);
-       regfree(&r2);
-
-       // jump again
-       patch(gbranch(optoas(op, t), T, likely), to);
-
-       // point first branch down here if appropriate
-       if(br != P)
-               patch(br, pc);
-
-       splitclean();
-       splitclean();
-}
similarity index 100%
rename from src/cmd/new5g/cgen64.go
rename to src/cmd/5g/cgen64.go
diff --git a/src/cmd/5g/doc.go b/src/cmd/5g/doc.go
deleted file mode 100644 (file)
index aebdcab..0000000
+++ /dev/null
@@ -1,15 +0,0 @@
-// Copyright 2009 The Go Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style
-// license that can be found in the LICENSE file.
-
-// +build ignore
-
-/*
-
-5g is the version of the gc compiler for the ARM.
-The $GOARCH for these tools is arm.
-
-It reads .go files and outputs .5 files. The flags are documented in ../gc/doc.go.
-
-*/
-package main
diff --git a/src/cmd/5g/galign.c b/src/cmd/5g/galign.c
deleted file mode 100644 (file)
index c4d74f0..0000000
+++ /dev/null
@@ -1,87 +0,0 @@
-// Copyright 2009 The Go Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style
-// license that can be found in the LICENSE file.
-
-#include <u.h>
-#include <libc.h>
-#include "gg.h"
-
-int    thechar = '5';
-char*  thestring       = "arm";
-LinkArch*      thelinkarch = &linkarm;
-
-void
-linkarchinit(void)
-{
-}
-
-vlong MAXWIDTH = (1LL<<32) - 1;
-
-/*
- * go declares several platform-specific type aliases:
- * int, uint, float, and uintptr
- */
-Typedef        typedefs[] =
-{
-       {"int",         TINT,           TINT32},
-       {"uint",                TUINT,          TUINT32},
-       {"uintptr",     TUINTPTR,       TUINT32},
-       {0}
-};
-
-void
-betypeinit(void)
-{
-       widthptr = 4;
-       widthint = 4;
-       widthreg = 4;
-
-       listinit5();
-}
-
-void
-main(int argc, char **argv)
-{
-       thearch.thechar = thechar;
-       thearch.thestring = thestring;
-       thearch.thelinkarch = thelinkarch;
-       thearch.typedefs = typedefs;
-       thearch.REGSP = REGSP;
-       thearch.REGCTXT = REGCTXT;
-       thearch.MAXWIDTH = MAXWIDTH;
-       thearch.anyregalloc = anyregalloc;
-       thearch.betypeinit = betypeinit;
-       thearch.bgen = bgen;
-       thearch.cgen = cgen;
-       thearch.cgen_call = cgen_call;
-       thearch.cgen_callinter = cgen_callinter;
-       thearch.cgen_ret = cgen_ret;
-       thearch.clearfat = clearfat;
-       thearch.defframe = defframe;
-       thearch.excise = excise;
-       thearch.expandchecks = expandchecks;
-       thearch.gclean = gclean;
-       thearch.ginit = ginit;
-       thearch.gins = gins;
-       thearch.ginscall = ginscall;
-       thearch.igen = igen;
-       thearch.linkarchinit = linkarchinit;
-       thearch.peep = peep;
-       thearch.proginfo = proginfo;
-       thearch.regalloc = regalloc;
-       thearch.regfree = regfree;
-       thearch.regtyp = regtyp;
-       thearch.sameaddr = sameaddr;
-       thearch.smallindir = smallindir;
-       thearch.stackaddr = stackaddr;
-       thearch.excludedregs = excludedregs;
-       thearch.RtoB = RtoB;
-       thearch.FtoB = RtoB;
-       thearch.BtoR = BtoR;
-       thearch.BtoF = BtoF;
-       thearch.optoas = optoas;
-       thearch.doregbits = doregbits;
-       thearch.regnames = regnames;
-       
-       gcmain(argc, argv);
-}
similarity index 100%
rename from src/cmd/new5g/galign.go
rename to src/cmd/5g/galign.go
similarity index 100%
rename from src/cmd/new5g/gg.go
rename to src/cmd/5g/gg.go
diff --git a/src/cmd/5g/gg.h b/src/cmd/5g/gg.h
deleted file mode 100644 (file)
index b12c7e2..0000000
+++ /dev/null
@@ -1,177 +0,0 @@
-// Copyright 2009 The Go Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style
-// license that can be found in the LICENSE file.
-
-#ifndef        EXTERN
-#define        EXTERN  extern
-#endif
-
-#include "../gc/go.h"
-#include "../5l/5.out.h"
-
-enum
-{
-       REGALLOC_R0 = REG_R0,
-       REGALLOC_RMAX = REGEXT,
-       REGALLOC_F0 = REG_F0,
-       REGALLOC_FMAX = FREGEXT,
-};
-
-EXTERN uchar   reg[REGALLOC_FMAX+1];
-extern long    unmappedzero;
-
-/*
- * gen.c
- */
-void   compile(Node*);
-void   gen(Node*);
-Node*  lookdot(Node*, Node*, int);
-void   cgen_as(Node*, Node*);
-void   cgen_callmeth(Node*, int);
-void   cgen_callinter(Node*, Node*, int);
-void   cgen_proc(Node*, int);
-void   cgen_callret(Node*, Node*);
-void   cgen_dcl(Node*);
-int    needconvert(Type*, Type*);
-void   genconv(Type*, Type*);
-void   allocparams(void);
-void   checklabels(void);
-void   ginscall(Node*, int);
-
-/*
- * cgen
- */
-void   agen(Node*, Node*);
-Prog* cgenindex(Node *, Node *, int);
-void   igen(Node*, Node*, Node*);
-void agenr(Node *n, Node *a, Node *res);
-vlong  fieldoffset(Type*, Node*);
-void   sgen(Node*, Node*, int64);
-void   gmove(Node*, Node*);
-Prog*  gins(int, Node*, Node*);
-int    samaddr(Node*, Node*);
-void   raddr(Node *n, Prog *p);
-Prog*  gcmp(int, Node*, Node*);
-Prog*  gshift(int as, Node *lhs, int32 stype, int32 sval, Node *rhs);
-Prog * gregshift(int as, Node *lhs, int32 stype, Node *reg, Node *rhs);
-void   naddr(Node*, Addr*, int);
-void   cgen_aret(Node*, Node*);
-void   cgen_hmul(Node*, Node*, Node*);
-void   cgen_shift(int, int, Node*, Node*, Node*);
-int    componentgen(Node*, Node*);
-
-/*
- * cgen64.c
- */
-void   cmp64(Node*, Node*, int, int, Prog*);
-void   cgen64(Node*, Node*);
-
-/*
- * gsubr.c
- */
-void   clearp(Prog*);
-Prog*  gbranch(int, Type*, int);
-Prog*  prog(int);
-void   gconv(int, int);
-int    conv2pt(Type*);
-vlong  convvtox(vlong, int);
-void   fnparam(Type*, int, int);
-Prog*  gop(int, Node*, Node*, Node*);
-int    optoas(int, Type*);
-void   ginit(void);
-void   gclean(void);
-void   regalloc(Node*, Type*, Node*);
-void   regfree(Node*);
-Node*  nodarg(Type*, int);
-void   nodreg(Node*, Type*, int);
-void   nodindreg(Node*, Type*, int);
-void   buildtxt(void);
-Plist* newplist(void);
-int    isfat(Type*);
-int    dotaddable(Node*, Node*);
-void   sudoclean(void);
-int    sudoaddable(int, Node*, Addr*, int*);
-void   afunclit(Addr*, Node*);
-void   datagostring(Strlit*, Addr*);
-void   split64(Node*, Node*, Node*);
-void   splitclean(void);
-Node*  ncon(uint32 i);
-void   gtrack(Sym*);
-
-/*
- * obj.c
- */
-void   datastring(char*, int, Addr*);
-
-/*
- * list.c
- */
-void   listinit(void);
-
-void   zaddr(Biobuf*, Addr*, int, int);
-
-void afunclit(Addr*, Node*);
-int anyregalloc(void);
-void betypeinit(void);
-void bgen(Node*, int, int, Prog*);
-void cgen(Node*, Node*);
-void cgen_call(Node*, int);
-void cgen_callinter(Node*, Node*, int);
-void cgen_ret(Node*);
-void clearfat(Node*);
-void clearp(Prog*);
-void defframe(Prog*);
-int dgostringptr(Sym*, int, char*);
-int dgostrlitptr(Sym*, int, Strlit*);
-int dsname(Sym*, int, char*, int);
-int dsymptr(Sym*, int, Sym*, int);
-void dumpdata(void);
-void dumpit(char*, Flow*, int);
-void excise(Flow*);
-void expandchecks(Prog*);
-void fixautoused(Prog*);
-void gclean(void);
-void   gdata(Node*, Node*, int);
-void   gdatacomplex(Node*, Mpcplx*);
-void   gdatastring(Node*, Strlit*);
-void   ggloblnod(Node *nam);
-void   ggloblsym(Sym *s, int32 width, int8 flags);
-void ginit(void);
-Prog*  gins(int, Node*, Node*);
-void   ginscall(Node*, int);
-Prog*  gjmp(Prog*);
-void gtrack(Sym*);
-void   gused(Node*);
-void   igen(Node*, Node*, Node*);
-int isfat(Type*);
-void linkarchinit(void);
-void markautoused(Prog*);
-void naddr(Node*, Addr*, int);
-Plist* newplist(void);
-Node* nodarg(Type*, int);
-void patch(Prog*, Prog*);
-void proginfo(ProgInfo*, Prog*);
-void regalloc(Node*, Type*, Node*);
-void regfree(Node*);
-void regopt(Prog*);
-int regtyp(Addr*);
-int sameaddr(Addr*, Addr*);
-int smallindir(Addr*, Addr*);
-int stackaddr(Addr*);
-Prog* unpatch(Prog*);
-
-/*
- * reg.c
- */
-uint64 excludedregs(void);
-uint64 RtoB(int);
-uint64 FtoB(int);
-int BtoR(uint64);
-int BtoF(uint64);
-uint64 doregbits(int);
-char** regnames(int*);
-
-/*
- * peep.c
- */
-void peep(Prog*);
diff --git a/src/cmd/5g/ggen.c b/src/cmd/5g/ggen.c
deleted file mode 100644 (file)
index 62b9bea..0000000
+++ /dev/null
@@ -1,751 +0,0 @@
-// Copyright 2009 The Go Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style
-// license that can be found in the LICENSE file.
-
-#undef EXTERN
-#define        EXTERN
-#include <u.h>
-#include <libc.h>
-#include "gg.h"
-#include "../gc/popt.h"
-
-static Prog* appendpp(Prog*, int, int, int, int32, int, int, int32);
-static Prog *zerorange(Prog *p, vlong frame, vlong lo, vlong hi, uint32 *r0);
-
-void
-defframe(Prog *ptxt)
-{
-       uint32 frame, r0;
-       Prog *p;
-       vlong hi, lo;
-       NodeList *l;
-       Node *n;
-
-       // fill in argument size, stack size
-       ptxt->to.type = TYPE_TEXTSIZE;
-       ptxt->to.u.argsize = rnd(curfn->type->argwid, widthptr);
-       frame = rnd(stksize+maxarg, widthreg);
-       ptxt->to.offset = frame;
-       
-       // insert code to contain ambiguously live variables
-       // so that garbage collector only sees initialized values
-       // when it looks for pointers.
-       p = ptxt;
-       lo = hi = 0;
-       r0 = 0;
-       for(l=curfn->dcl; l != nil; l = l->next) {
-               n = l->n;
-               if(!n->needzero)
-                       continue;
-               if(n->class != PAUTO)
-                       fatal("needzero class %d", n->class);
-               if(n->type->width % widthptr != 0 || n->xoffset % widthptr != 0 || n->type->width == 0)
-                       fatal("var %lN has size %d offset %d", n, (int)n->type->width, (int)n->xoffset);
-               if(lo != hi && n->xoffset + n->type->width >= lo - 2*widthptr) {
-                       // merge with range we already have
-                       lo = rnd(n->xoffset, widthptr);
-                       continue;
-               }
-               // zero old range
-               p = zerorange(p, frame, lo, hi, &r0);
-
-               // set new range
-               hi = n->xoffset + n->type->width;
-               lo = n->xoffset;
-       }
-       // zero final range
-       zerorange(p, frame, lo, hi, &r0);
-}
-
-static Prog*
-zerorange(Prog *p, vlong frame, vlong lo, vlong hi, uint32 *r0)
-{
-       vlong cnt, i;
-       Prog *p1;
-       Node *f;
-
-       cnt = hi - lo;
-       if(cnt == 0)
-               return p;
-       if(*r0 == 0) {
-               p = appendpp(p, AMOVW, TYPE_CONST, 0, 0, TYPE_REG, REG_R0, 0);
-               *r0 = 1;
-       }
-       if(cnt < 4*widthptr) {
-               for(i = 0; i < cnt; i += widthptr) 
-                       p = appendpp(p, AMOVW, TYPE_REG, REG_R0, 0, TYPE_MEM, REGSP, 4+frame+lo+i);
-       } else if(!nacl && (cnt <= 128*widthptr)) {
-               p = appendpp(p, AADD, TYPE_CONST, 0, 4+frame+lo, TYPE_REG, REG_R1, 0);
-               p->reg = REGSP;
-               p = appendpp(p, ADUFFZERO, TYPE_NONE, 0, 0, TYPE_MEM, 0, 0);
-               f = sysfunc("duffzero");
-               naddr(f, &p->to, 1);
-               afunclit(&p->to, f);
-               p->to.offset = 4*(128-cnt/widthptr);
-       } else {
-               p = appendpp(p, AADD, TYPE_CONST, 0, 4+frame+lo, TYPE_REG, REG_R1, 0);
-               p->reg = REGSP;
-               p = appendpp(p, AADD, TYPE_CONST, 0, cnt, TYPE_REG, REG_R2, 0);
-               p->reg = REG_R1;
-               p1 = p = appendpp(p, AMOVW, TYPE_REG, REG_R0, 0, TYPE_MEM, REG_R1, 4);
-               p->scond |= C_PBIT;
-               p = appendpp(p, ACMP, TYPE_REG, REG_R1, 0, TYPE_NONE, 0, 0);
-               p->reg = REG_R2;
-               p = appendpp(p, ABNE, TYPE_NONE, 0, 0, TYPE_BRANCH, 0, 0);
-               patch(p, p1);
-       }
-       return p;
-}
-
-static Prog*   
-appendpp(Prog *p, int as, int ftype, int freg, int32 foffset, int ttype, int treg, int32 toffset)      
-{      
-       Prog *q;        
-               
-       q = mal(sizeof(*q));    
-       clearp(q);      
-       q->as = as;     
-       q->lineno = p->lineno;  
-       q->from.type = ftype;   
-       q->from.reg = freg;     
-       q->from.offset = foffset;       
-       q->to.type = ttype;     
-       q->to.reg = treg;       
-       q->to.offset = toffset; 
-       q->link = p->link;      
-       p->link = q;    
-       return q;       
-}
-
-/*
- * generate:
- *     call f
- *     proc=-1 normal call but no return
- *     proc=0  normal call
- *     proc=1  goroutine run in new proc
- *     proc=2  defer call save away stack
-  *    proc=3  normal call to C pointer (not Go func value)
- */
-void
-ginscall(Node *f, int proc)
-{
-       Prog *p;
-       Node r, r1, con;
-       int32 extra;
-
-       if(f->type != T) {
-               extra = 0;
-               if(proc == 1 || proc == 2)
-                       extra = 2 * widthptr;
-               setmaxarg(f->type, extra);
-       }
-
-       switch(proc) {
-       default:
-               fatal("ginscall: bad proc %d", proc);
-               break;
-
-       case 0: // normal call
-       case -1:        // normal call but no return
-               if(f->op == ONAME && f->class == PFUNC) {
-                       if(f == deferreturn) {
-                               // Deferred calls will appear to be returning to
-                               // the BL deferreturn(SB) that we are about to emit.
-                               // However, the stack trace code will show the line
-                               // of the instruction before that return PC. 
-                               // To avoid that instruction being an unrelated instruction,
-                               // insert a NOP so that we will have the right line number.
-                               // ARM NOP 0x00000000 is really AND.EQ R0, R0, R0.
-                               // Use the latter form because the NOP pseudo-instruction
-                               // would be removed by the linker.
-                               nodreg(&r, types[TINT], REG_R0);
-                               p = gins(AAND, &r, &r);
-                               p->scond = C_SCOND_EQ;
-                       }
-                       p = gins(ABL, N, f);
-                       afunclit(&p->to, f);
-                       if(proc == -1 || noreturn(p))
-                               gins(AUNDEF, N, N);
-                       break;
-               }
-               nodreg(&r, types[tptr], REG_R7);
-               nodreg(&r1, types[tptr], REG_R1);
-               gmove(f, &r);
-               r.op = OINDREG;
-               gmove(&r, &r1);
-               r.op = OREGISTER;
-               r1.op = OINDREG;
-               gins(ABL, &r, &r1);
-               break;
-
-       case 3: // normal call of c function pointer
-               gins(ABL, N, f);
-               break;
-
-       case 1: // call in new proc (go)
-       case 2: // deferred call (defer)
-               regalloc(&r, types[tptr], N);
-               nodconst(&con, types[TINT32], argsize(f->type));
-               gins(AMOVW, &con, &r);
-               p = gins(AMOVW, &r, N);
-               p->to.type = TYPE_MEM;
-               p->to.reg = REGSP;
-               p->to.offset = 4;
-
-               gins(AMOVW, f, &r);
-               p = gins(AMOVW, &r, N);
-               p->to.type = TYPE_MEM;
-               p->to.reg = REGSP;
-               p->to.offset = 8;
-
-               regfree(&r);
-
-               if(proc == 1)
-                       ginscall(newproc, 0);
-               else
-                       ginscall(deferproc, 0);
-
-               if(proc == 2) {
-                       nodconst(&con, types[TINT32], 0);
-                       p = gins(ACMP, &con, N);
-                       p->reg = REG_R0;
-                       p = gbranch(ABEQ, T, +1);
-                       cgen_ret(N);
-                       patch(p, pc);
-               }
-               break;
-       }
-}
-
-/*
- * n is call to interface method.
- * generate res = n.
- */
-void
-cgen_callinter(Node *n, Node *res, int proc)
-{
-       int r;
-       Node *i, *f;
-       Node tmpi, nodo, nodr, nodsp;
-       Prog *p;
-
-       i = n->left;
-       if(i->op != ODOTINTER)
-               fatal("cgen_callinter: not ODOTINTER %O", i->op);
-
-       f = i->right;           // field
-       if(f->op != ONAME)
-               fatal("cgen_callinter: not ONAME %O", f->op);
-
-       i = i->left;            // interface
-
-       // Release res register during genlist and cgen,
-       // which might have their own function calls.
-       r = -1;
-       if(res != N && (res->op == OREGISTER || res->op == OINDREG)) {
-               r = res->val.u.reg;
-               reg[r]--;
-       }
-
-       if(!i->addable) {
-               tempname(&tmpi, i->type);
-               cgen(i, &tmpi);
-               i = &tmpi;
-       }
-
-       genlist(n->list);                       // args
-       if(r >= 0)
-               reg[r]++;
-
-       regalloc(&nodr, types[tptr], res);
-       regalloc(&nodo, types[tptr], &nodr);
-       nodo.op = OINDREG;
-
-       agen(i, &nodr);         // REG = &inter
-
-       nodindreg(&nodsp, types[tptr], REGSP);
-       nodsp.xoffset = widthptr;
-       if(proc != 0)
-               nodsp.xoffset += 2 * widthptr; // leave room for size & fn
-       nodo.xoffset += widthptr;
-       cgen(&nodo, &nodsp);    // {4 or 12}(SP) = 4(REG) -- i.data
-
-       nodo.xoffset -= widthptr;
-       cgen(&nodo, &nodr);     // REG = 0(REG) -- i.tab
-       cgen_checknil(&nodr); // in case offset is huge
-
-       nodo.xoffset = n->left->xoffset + 3*widthptr + 8;
-       
-       if(proc == 0) {
-               // plain call: use direct c function pointer - more efficient
-               cgen(&nodo, &nodr);     // REG = 20+offset(REG) -- i.tab->fun[f]
-               nodr.op = OINDREG;
-               proc = 3;
-       } else {
-               // go/defer. generate go func value.
-               p = gins(AMOVW, &nodo, &nodr);
-               p->from.type = TYPE_ADDR;       // REG = &(20+offset(REG)) -- i.tab->fun[f]
-       }
-
-       nodr.type = n->left->type;
-       ginscall(&nodr, proc);
-
-       regfree(&nodr);
-       regfree(&nodo);
-}
-
-/*
- * generate function call;
- *     proc=0  normal call
- *     proc=1  goroutine run in new proc
- *     proc=2  defer call save away stack
- */
-void
-cgen_call(Node *n, int proc)
-{
-       Type *t;
-       Node nod, afun;
-
-       if(n == N)
-               return;
-
-       if(n->left->ullman >= UINF) {
-               // if name involves a fn call
-               // precompute the address of the fn
-               tempname(&afun, types[tptr]);
-               cgen(n->left, &afun);
-       }
-
-       genlist(n->list);               // assign the args
-       t = n->left->type;
-
-       // call tempname pointer
-       if(n->left->ullman >= UINF) {
-               regalloc(&nod, types[tptr], N);
-               cgen_as(&nod, &afun);
-               nod.type = t;
-               ginscall(&nod, proc);
-               regfree(&nod);
-               goto ret;
-       }
-
-       // call pointer
-       if(n->left->op != ONAME || n->left->class != PFUNC) {
-               regalloc(&nod, types[tptr], N);
-               cgen_as(&nod, n->left);
-               nod.type = t;
-               ginscall(&nod, proc);
-               regfree(&nod);
-               goto ret;
-       }
-
-       // call direct
-       n->left->method = 1;
-       ginscall(n->left, proc);
-
-
-ret:
-       ;
-}
-
-/*
- * call to n has already been generated.
- * generate:
- *     res = return value from call.
- */
-void
-cgen_callret(Node *n, Node *res)
-{
-       Node nod;
-       Type *fp, *t;
-       Iter flist;
-
-       t = n->left->type;
-       if(t->etype == TPTR32 || t->etype == TPTR64)
-               t = t->type;
-
-       fp = structfirst(&flist, getoutarg(t));
-       if(fp == T)
-               fatal("cgen_callret: nil");
-
-       memset(&nod, 0, sizeof(nod));
-       nod.op = OINDREG;
-       nod.val.u.reg = REGSP;
-       nod.addable = 1;
-
-       nod.xoffset = fp->width + 4; // +4: saved lr at 0(SP)
-       nod.type = fp->type;
-       cgen_as(res, &nod);
-}
-
-/*
- * call to n has already been generated.
- * generate:
- *     res = &return value from call.
- */
-void
-cgen_aret(Node *n, Node *res)
-{
-       Node nod1, nod2;
-       Type *fp, *t;
-       Iter flist;
-
-       t = n->left->type;
-       if(isptr[t->etype])
-               t = t->type;
-
-       fp = structfirst(&flist, getoutarg(t));
-       if(fp == T)
-               fatal("cgen_aret: nil");
-
-       memset(&nod1, 0, sizeof(nod1));
-       nod1.op = OINDREG;
-       nod1.val.u.reg = REGSP;
-       nod1.addable = 1;
-
-       nod1.xoffset = fp->width + 4; // +4: saved lr at 0(SP)
-       nod1.type = fp->type;
-
-       if(res->op != OREGISTER) {
-               regalloc(&nod2, types[tptr], res);
-               agen(&nod1, &nod2);
-               gins(AMOVW, &nod2, res);
-               regfree(&nod2);
-       } else
-               agen(&nod1, res);
-}
-
-/*
- * generate return.
- * n->left is assignments to return values.
- */
-void
-cgen_ret(Node *n)
-{
-       Prog *p;
-
-       if(n != N)
-               genlist(n->list);               // copy out args
-       if(hasdefer)
-               ginscall(deferreturn, 0);
-       genlist(curfn->exit);
-       p = gins(ARET, N, N);
-       if(n != N && n->op == ORETJMP) {
-               p->to.name = NAME_EXTERN;
-               p->to.type = TYPE_ADDR;
-               p->to.sym = linksym(n->left->sym);
-       }
-}
-
-/*
- * generate high multiply
- *  res = (nl * nr) >> wordsize
- */
-void
-cgen_hmul(Node *nl, Node *nr, Node *res)
-{
-       int w;
-       Node n1, n2, *tmp;
-       Type *t;
-       Prog *p;
-
-       if(nl->ullman < nr->ullman) {
-               tmp = nl;
-               nl = nr;
-               nr = tmp;
-       }
-       t = nl->type;
-       w = t->width * 8;
-       regalloc(&n1, t, res);
-       cgen(nl, &n1);
-       regalloc(&n2, t, N);
-       cgen(nr, &n2);
-       switch(simtype[t->etype]) {
-       case TINT8:
-       case TINT16:
-               gins(optoas(OMUL, t), &n2, &n1);
-               gshift(AMOVW, &n1, SHIFT_AR, w, &n1);
-               break;
-       case TUINT8:
-       case TUINT16:
-               gins(optoas(OMUL, t), &n2, &n1);
-               gshift(AMOVW, &n1, SHIFT_LR, w, &n1);
-               break;
-       case TINT32:
-       case TUINT32:
-               // perform a long multiplication.
-               if(issigned[t->etype])
-                       p = gins(AMULL, &n2, N);
-               else
-                       p = gins(AMULLU, &n2, N);
-               // n2 * n1 -> (n1 n2)
-               p->reg = n1.val.u.reg;
-               p->to.type = TYPE_REGREG;
-               p->to.reg = n1.val.u.reg;
-               p->to.offset = n2.val.u.reg;
-               break;
-       default:
-               fatal("cgen_hmul %T", t);
-               break;
-       }
-       cgen(&n1, res);
-       regfree(&n1);
-       regfree(&n2);
-}
-
-/*
- * generate shift according to op, one of:
- *     res = nl << nr
- *     res = nl >> nr
- */
-void
-cgen_shift(int op, int bounded, Node *nl, Node *nr, Node *res)
-{
-       Node n1, n2, n3, nt, t, lo, hi;
-       int w, v;
-       Prog *p1, *p2, *p3;
-       Type *tr;
-       uvlong sc;
-
-       USED(bounded);
-       if(nl->type->width > 4)
-               fatal("cgen_shift %T", nl->type);
-
-       w = nl->type->width * 8;
-
-       if(op == OLROT) {
-               v = mpgetfix(nr->val.u.xval);
-               regalloc(&n1, nl->type, res);
-               if(w == 32) {
-                       cgen(nl, &n1);
-                       gshift(AMOVW, &n1, SHIFT_RR, w-v, &n1);
-               } else {
-                       regalloc(&n2, nl->type, N);
-                       cgen(nl, &n2);
-                       gshift(AMOVW, &n2, SHIFT_LL, v, &n1);
-                       gshift(AORR, &n2, SHIFT_LR, w-v, &n1);
-                       regfree(&n2);
-                       // Ensure sign/zero-extended result.
-                       gins(optoas(OAS, nl->type), &n1, &n1);
-               }
-               gmove(&n1, res);
-               regfree(&n1);
-               return;
-       }
-
-       if(nr->op == OLITERAL) {
-               regalloc(&n1, nl->type, res);
-               cgen(nl, &n1);
-               sc = mpgetfix(nr->val.u.xval);
-               if(sc == 0) {
-                       // nothing to do
-               } else if(sc >= nl->type->width*8) {
-                       if(op == ORSH && issigned[nl->type->etype])
-                               gshift(AMOVW, &n1, SHIFT_AR, w, &n1);
-                       else
-                               gins(AEOR, &n1, &n1);
-               } else {
-                       if(op == ORSH && issigned[nl->type->etype])
-                               gshift(AMOVW, &n1, SHIFT_AR, sc, &n1);
-                       else if(op == ORSH)
-                               gshift(AMOVW, &n1, SHIFT_LR, sc, &n1);
-                       else // OLSH
-                               gshift(AMOVW, &n1, SHIFT_LL, sc, &n1);
-               }
-               if(w < 32 && op == OLSH)
-                       gins(optoas(OAS, nl->type), &n1, &n1);
-               gmove(&n1, res);
-               regfree(&n1);
-               return;
-       }
-
-       tr = nr->type;
-       if(tr->width > 4) {
-               tempname(&nt, nr->type);
-               if(nl->ullman >= nr->ullman) {
-                       regalloc(&n2, nl->type, res);
-                       cgen(nl, &n2);
-                       cgen(nr, &nt);
-                       n1 = nt;
-               } else {
-                       cgen(nr, &nt);
-                       regalloc(&n2, nl->type, res);
-                       cgen(nl, &n2);
-               }
-               split64(&nt, &lo, &hi);
-               regalloc(&n1, types[TUINT32], N);
-               regalloc(&n3, types[TUINT32], N);
-               gmove(&lo, &n1);
-               gmove(&hi, &n3);
-               splitclean();
-               gins(ATST, &n3, N);
-               nodconst(&t, types[TUINT32], w);
-               p1 = gins(AMOVW, &t, &n1);
-               p1->scond = C_SCOND_NE;
-               tr = types[TUINT32];
-               regfree(&n3);
-       } else {
-               if(nl->ullman >= nr->ullman) {
-                       regalloc(&n2, nl->type, res);
-                       cgen(nl, &n2);
-                       regalloc(&n1, nr->type, N);
-                       cgen(nr, &n1);
-               } else {
-                       regalloc(&n1, nr->type, N);
-                       cgen(nr, &n1);
-                       regalloc(&n2, nl->type, res);
-                       cgen(nl, &n2);
-               }
-       }
-
-       // test for shift being 0
-       gins(ATST, &n1, N);
-       p3 = gbranch(ABEQ, T, -1);
-
-       // test and fix up large shifts
-       // TODO: if(!bounded), don't emit some of this.
-       regalloc(&n3, tr, N);
-       nodconst(&t, types[TUINT32], w);
-       gmove(&t, &n3);
-       gcmp(ACMP, &n1, &n3);
-       if(op == ORSH) {
-               if(issigned[nl->type->etype]) {
-                       p1 = gshift(AMOVW, &n2, SHIFT_AR, w-1, &n2);
-                       p2 = gregshift(AMOVW, &n2, SHIFT_AR, &n1, &n2);
-               } else {
-                       p1 = gins(AEOR, &n2, &n2);
-                       p2 = gregshift(AMOVW, &n2, SHIFT_LR, &n1, &n2);
-               }
-               p1->scond = C_SCOND_HS;
-               p2->scond = C_SCOND_LO;
-       } else {
-               p1 = gins(AEOR, &n2, &n2);
-               p2 = gregshift(AMOVW, &n2, SHIFT_LL, &n1, &n2);
-               p1->scond = C_SCOND_HS;
-               p2->scond = C_SCOND_LO;
-       }
-       regfree(&n3);
-
-       patch(p3, pc);
-       // Left-shift of smaller word must be sign/zero-extended.
-       if(w < 32 && op == OLSH)
-               gins(optoas(OAS, nl->type), &n2, &n2);
-       gmove(&n2, res);
-
-       regfree(&n1);
-       regfree(&n2);
-}
-
-void
-clearfat(Node *nl)
-{
-       uint32 w, c, q;
-       Node dst, nc, nz, end, r0, r1, *f;
-       Prog *p, *pl;
-
-       /* clear a fat object */
-       if(debug['g'])
-               dump("\nclearfat", nl);
-
-       w = nl->type->width;
-       // Avoid taking the address for simple enough types.
-       if(componentgen(N, nl))
-               return;
-
-       c = w % 4;      // bytes
-       q = w / 4;      // quads
-
-       r0.op = OREGISTER;
-       r0.val.u.reg = REGALLOC_R0;
-       r1.op = OREGISTER;
-       r1.val.u.reg = REGALLOC_R0 + 1;
-       regalloc(&dst, types[tptr], &r1);
-       agen(nl, &dst);
-       nodconst(&nc, types[TUINT32], 0);
-       regalloc(&nz, types[TUINT32], &r0);
-       cgen(&nc, &nz);
-
-       if(q > 128) {
-               regalloc(&end, types[tptr], N);
-               p = gins(AMOVW, &dst, &end);
-               p->from.type = TYPE_ADDR;
-               p->from.offset = q*4;
-
-               p = gins(AMOVW, &nz, &dst);
-               p->to.type = TYPE_MEM;
-               p->to.offset = 4;
-               p->scond |= C_PBIT;
-               pl = p;
-
-               p = gins(ACMP, &dst, N);
-               raddr(&end, p);
-               patch(gbranch(ABNE, T, 0), pl);
-
-               regfree(&end);
-       } else if(q >= 4 && !nacl) {
-               f = sysfunc("duffzero");
-               p = gins(ADUFFZERO, N, f);
-               afunclit(&p->to, f);
-               // 4 and 128 = magic constants: see ../../runtime/asm_arm.s
-               p->to.offset = 4*(128-q);
-       } else
-       while(q > 0) {
-               p = gins(AMOVW, &nz, &dst);
-               p->to.type = TYPE_MEM;
-               p->to.offset = 4;
-               p->scond |= C_PBIT;
-//print("1. %P\n", p);
-               q--;
-       }
-
-       while(c > 0) {
-               p = gins(AMOVB, &nz, &dst);
-               p->to.type = TYPE_MEM;
-               p->to.offset = 1;
-               p->scond |= C_PBIT;
-//print("2. %P\n", p);
-               c--;
-       }
-       regfree(&dst);
-       regfree(&nz);
-}
-
-// Called after regopt and peep have run.
-// Expand CHECKNIL pseudo-op into actual nil pointer check.
-void
-expandchecks(Prog *firstp)
-{
-       int reg;
-       Prog *p, *p1;
-
-       for(p = firstp; p != P; p = p->link) {
-               if(p->as != ACHECKNIL)
-                       continue;
-               if(debug_checknil && p->lineno > 1) // p->lineno==1 in generated wrappers
-                       warnl(p->lineno, "generated nil check");
-               if(p->from.type != TYPE_REG)
-                       fatal("invalid nil check %P", p);
-               reg = p->from.reg;
-               // check is
-               //      CMP arg, $0
-               //      MOV.EQ arg, 0(arg)
-               p1 = mal(sizeof *p1);
-               clearp(p1);
-               p1->link = p->link;
-               p->link = p1;
-               p1->lineno = p->lineno;
-               p1->pc = 9999;
-               p1->as = AMOVW;
-               p1->from.type = TYPE_REG;
-               p1->from.reg = reg;
-               p1->to.type = TYPE_MEM;
-               p1->to.reg = reg;
-               p1->to.offset = 0;
-               p1->scond = C_SCOND_EQ;
-               p->as = ACMP;
-               p->from.type = TYPE_CONST;
-               p->from.reg = 0;
-               p->from.offset = 0;
-               p->reg = reg;
-       }
-}
similarity index 100%
rename from src/cmd/new5g/ggen.go
rename to src/cmd/5g/ggen.go
diff --git a/src/cmd/5g/gsubr.c b/src/cmd/5g/gsubr.c
deleted file mode 100644 (file)
index bdb7027..0000000
+++ /dev/null
@@ -1,1527 +0,0 @@
-// Derived from Inferno utils/5c/txt.c
-// http://code.google.com/p/inferno-os/source/browse/utils/5c/txt.c
-//
-//     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 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 <u.h>
-#include <libc.h>
-#include "gg.h"
-#include "../../runtime/funcdata.h"
-
-// TODO(rsc): Can make this bigger if we move
-// the text segment up higher in 5l for all GOOS.
-// At the same time, can raise StackBig in ../../runtime/stack.h.
-long unmappedzero = 4096;
-
-static int     resvd[] =
-{
-       9,     // reserved for m
-       10,    // reserved for g
-       REGSP, // reserved for SP
-};
-
-void
-ginit(void)
-{
-       int i;
-
-       for(i=0; i<nelem(reg); i++)
-               reg[i] = 0;
-       for(i=0; i<nelem(resvd); i++)
-               reg[resvd[i]]++;
-}
-
-void
-gclean(void)
-{
-       int i;
-
-       for(i=0; i<nelem(resvd); i++)
-               reg[resvd[i]]--;
-
-       for(i=0; i<nelem(reg); i++)
-               if(reg[i])
-                       yyerror("reg %R left allocated\n", i);
-}
-
-int
-anyregalloc(void)
-{
-       int i, j;
-
-       for(i=0; i<nelem(reg); i++) {
-               if(reg[i] == 0)
-                       goto ok;
-               for(j=0; j<nelem(resvd); j++)
-                       if(resvd[j] == i)
-                               goto ok;
-               return 1;
-       ok:;
-       }
-       return 0;
-}
-
-uintptr regpc[REGALLOC_FMAX+1];
-
-/*
- * allocate register of type t, leave in n.
- * if o != N, o is desired fixed register.
- * caller must regfree(n).
- */
-void
-regalloc(Node *n, Type *t, Node *o)
-{
-       int i, et, fixfree, floatfree;
-
-       if(0 && debug['r']) {
-               fixfree = 0;
-               for(i=REGALLOC_R0; i<=REGALLOC_RMAX; i++)
-                       if(reg[i] == 0)
-                               fixfree++;
-               floatfree = 0;
-               for(i=REGALLOC_F0; i<=REGALLOC_FMAX; i++)
-                       if(reg[i] == 0)
-                               floatfree++;
-               print("regalloc fix %d float %d\n", fixfree, floatfree);
-       }
-
-       if(t == T)
-               fatal("regalloc: t nil");
-       et = simtype[t->etype];
-       if(is64(t))
-               fatal("regalloc: 64 bit type %T");
-
-       switch(et) {
-       case TINT8:
-       case TUINT8:
-       case TINT16:
-       case TUINT16:
-       case TINT32:
-       case TUINT32:
-       case TPTR32:
-       case TBOOL:
-               if(o != N && o->op == OREGISTER) {
-                       i = o->val.u.reg;
-                       if(i >= REGALLOC_R0 && i <= REGALLOC_RMAX)
-                               goto out;
-               }
-               for(i=REGALLOC_R0; i<=REGALLOC_RMAX; i++)
-                       if(reg[i] == 0) {
-                               regpc[i] = (uintptr)getcallerpc(&n);
-                               goto out;
-                       }
-               print("registers allocated at\n");
-               for(i=REGALLOC_R0; i<=REGALLOC_RMAX; i++)
-                       print("%d %p\n", i, regpc[i]);
-               fatal("out of fixed registers");
-               goto err;
-
-       case TFLOAT32:
-       case TFLOAT64:
-               if(o != N && o->op == OREGISTER) {
-                       i = o->val.u.reg;
-                       if(i >= REGALLOC_F0 && i <= REGALLOC_FMAX)
-                               goto out;
-               }
-               for(i=REGALLOC_F0; i<=REGALLOC_FMAX; i++)
-                       if(reg[i] == 0)
-                               goto out;
-               fatal("out of floating point registers");
-               goto err;
-
-       case TCOMPLEX64:
-       case TCOMPLEX128:
-               tempname(n, t);
-               return;
-       }
-       yyerror("regalloc: unknown type %T", t);
-
-err:
-       nodreg(n, t, REG_R0);
-       return;
-
-out:
-       reg[i]++;
-       nodreg(n, t, i);
-}
-
-void
-regfree(Node *n)
-{
-       int i, fixfree, floatfree;
-
-       if(0 && debug['r']) {
-               fixfree = 0;
-               for(i=REGALLOC_R0; i<=REGALLOC_RMAX; i++)
-                       if(reg[i] == 0)
-                               fixfree++;
-               floatfree = 0;
-               for(i=REGALLOC_F0; i<=REGALLOC_FMAX; i++)
-                       if(reg[i] == 0)
-                               floatfree++;
-               print("regalloc fix %d float %d\n", fixfree, floatfree);
-       }
-
-       if(n->op == ONAME)
-               return;
-       if(n->op != OREGISTER && n->op != OINDREG)
-               fatal("regfree: not a register");
-       i = n->val.u.reg;
-       if(i == REGSP)
-               return;
-       if(i < 0 || i >= nelem(reg) || i >= nelem(regpc))
-               fatal("regfree: reg out of range");
-       if(reg[i] <= 0)
-               fatal("regfree: reg %R not allocated", i);
-       reg[i]--;
-       if(reg[i] == 0)
-               regpc[i] = 0;
-}
-
-/*
- * return constant i node.
- * overwritten by next call, but useful in calls to gins.
- */
-Node*
-ncon(uint32 i)
-{
-       static Node n;
-
-       if(n.type == T)
-               nodconst(&n, types[TUINT32], 0);
-       mpmovecfix(n.val.u.xval, i);
-       return &n;
-}
-
-Node sclean[10];
-int nsclean;
-
-/*
- * n is a 64-bit value.  fill in lo and hi to refer to its 32-bit halves.
- */
-void
-split64(Node *n, Node *lo, Node *hi)
-{
-       Node n1;
-       int64 i;
-
-       if(!is64(n->type))
-               fatal("split64 %T", n->type);
-
-       if(nsclean >= nelem(sclean))
-               fatal("split64 clean");
-       sclean[nsclean].op = OEMPTY;
-       nsclean++;
-       switch(n->op) {
-       default:
-               switch(n->op) {
-               default:
-                       if(!dotaddable(n, &n1)) {
-                               igen(n, &n1, N);
-                               sclean[nsclean-1] = n1;
-                       }
-                       n = &n1;
-                       break;
-               case ONAME:
-                       if(n->class == PPARAMREF) {
-                               cgen(n->heapaddr, &n1);
-                               sclean[nsclean-1] = n1;
-                               n = &n1;
-                       }
-                       break;
-               case OINDREG:
-                       // nothing
-                       break;
-               }
-               *lo = *n;
-               *hi = *n;
-               lo->type = types[TUINT32];
-               if(n->type->etype == TINT64)
-                       hi->type = types[TINT32];
-               else
-                       hi->type = types[TUINT32];
-               hi->xoffset += 4;
-               break;
-
-       case OLITERAL:
-               convconst(&n1, n->type, &n->val);
-               i = mpgetfix(n1.val.u.xval);
-               nodconst(lo, types[TUINT32], (uint32)i);
-               i >>= 32;
-               if(n->type->etype == TINT64)
-                       nodconst(hi, types[TINT32], (int32)i);
-               else
-                       nodconst(hi, types[TUINT32], (uint32)i);
-               break;
-       }
-}
-
-void
-splitclean(void)
-{
-       if(nsclean <= 0)
-               fatal("splitclean");
-       nsclean--;
-       if(sclean[nsclean].op != OEMPTY)
-               regfree(&sclean[nsclean]);
-}
-
-#define        CASE(a,b)       (((a)<<16)|((b)<<0))
-/*c2go int CASE(int, int); */
-
-void
-gmove(Node *f, Node *t)
-{
-       int a, ft, tt, fa, ta;
-       Type *cvt;
-       Node r1, r2, flo, fhi, tlo, thi, con;
-       Prog *p1;
-
-       if(debug['M'])
-               print("gmove %N -> %N\n", f, t);
-
-       ft = simsimtype(f->type);
-       tt = simsimtype(t->type);
-       cvt = t->type;
-
-       if(iscomplex[ft] || iscomplex[tt]) {
-               complexmove(f, t);
-               return;
-       }
-
-       // cannot have two memory operands;
-       // except 64-bit, which always copies via registers anyway.
-       if(!is64(f->type) && !is64(t->type) && ismem(f) && ismem(t))
-               goto hard;
-
-       // convert constant to desired type
-       if(f->op == OLITERAL) {
-               switch(tt) {
-               default:
-                       convconst(&con, t->type, &f->val);
-                       break;
-
-               case TINT16:
-               case TINT8:
-                       convconst(&con, types[TINT32], &f->val);
-                       regalloc(&r1, con.type, t);
-                       gins(AMOVW, &con, &r1);
-                       gmove(&r1, t);
-                       regfree(&r1);
-                       return;
-
-               case TUINT16:
-               case TUINT8:
-                       convconst(&con, types[TUINT32], &f->val);
-                       regalloc(&r1, con.type, t);
-                       gins(AMOVW, &con, &r1);
-                       gmove(&r1, t);
-                       regfree(&r1);
-                       return;
-               }
-
-               f = &con;
-               ft = simsimtype(con.type);
-
-               // constants can't move directly to memory
-               if(ismem(t) && !is64(t->type)) goto hard;
-       }
-
-       // value -> value copy, only one memory operand.
-       // figure out the instruction to use.
-       // break out of switch for one-instruction gins.
-       // goto rdst for "destination must be register".
-       // goto hard for "convert to cvt type first".
-       // otherwise handle and return.
-
-       switch(CASE(ft, tt)) {
-       default:
-               goto fatal;
-
-       /*
-        * integer copy and truncate
-        */
-       case CASE(TINT8, TINT8):        // same size
-               if(!ismem(f)) {
-                       a = AMOVB;
-                       break;
-               }
-       case CASE(TUINT8, TINT8):
-       case CASE(TINT16, TINT8):       // truncate
-       case CASE(TUINT16, TINT8):
-       case CASE(TINT32, TINT8):
-       case CASE(TUINT32, TINT8):
-               a = AMOVBS;
-               break;
-
-       case CASE(TUINT8, TUINT8):
-               if(!ismem(f)) {
-                       a = AMOVB;
-                       break;
-               }
-       case CASE(TINT8, TUINT8):
-       case CASE(TINT16, TUINT8):
-       case CASE(TUINT16, TUINT8):
-       case CASE(TINT32, TUINT8):
-       case CASE(TUINT32, TUINT8):
-               a = AMOVBU;
-               break;
-
-       case CASE(TINT64, TINT8):       // truncate low word
-       case CASE(TUINT64, TINT8):
-               a = AMOVBS;
-               goto trunc64;
-
-       case CASE(TINT64, TUINT8):
-       case CASE(TUINT64, TUINT8):
-               a = AMOVBU;
-               goto trunc64;
-
-       case CASE(TINT16, TINT16):      // same size
-               if(!ismem(f)) {
-                       a = AMOVH;
-                       break;
-               }
-       case CASE(TUINT16, TINT16):
-       case CASE(TINT32, TINT16):      // truncate
-       case CASE(TUINT32, TINT16):
-               a = AMOVHS;
-               break;
-
-       case CASE(TUINT16, TUINT16):
-               if(!ismem(f)) {
-                       a = AMOVH;
-                       break;
-               }
-       case CASE(TINT16, TUINT16):
-       case CASE(TINT32, TUINT16):
-       case CASE(TUINT32, TUINT16):
-               a = AMOVHU;
-               break;
-
-       case CASE(TINT64, TINT16):      // truncate low word
-       case CASE(TUINT64, TINT16):
-               a = AMOVHS;
-               goto trunc64;
-
-       case CASE(TINT64, TUINT16):
-       case CASE(TUINT64, TUINT16):
-               a = AMOVHU;
-               goto trunc64;
-
-       case CASE(TINT32, TINT32):      // same size
-       case CASE(TINT32, TUINT32):
-       case CASE(TUINT32, TINT32):
-       case CASE(TUINT32, TUINT32):
-               a = AMOVW;
-               break;
-
-       case CASE(TINT64, TINT32):      // truncate
-       case CASE(TUINT64, TINT32):
-       case CASE(TINT64, TUINT32):
-       case CASE(TUINT64, TUINT32):
-               split64(f, &flo, &fhi);
-               regalloc(&r1, t->type, N);
-               gins(AMOVW, &flo, &r1);
-               gins(AMOVW, &r1, t);
-               regfree(&r1);
-               splitclean();
-               return;
-
-       case CASE(TINT64, TINT64):      // same size
-       case CASE(TINT64, TUINT64):
-       case CASE(TUINT64, TINT64):
-       case CASE(TUINT64, TUINT64):
-               split64(f, &flo, &fhi);
-               split64(t, &tlo, &thi);
-               regalloc(&r1, flo.type, N);
-               regalloc(&r2, fhi.type, N);
-               gins(AMOVW, &flo, &r1);
-               gins(AMOVW, &fhi, &r2);
-               gins(AMOVW, &r1, &tlo);
-               gins(AMOVW, &r2, &thi);
-               regfree(&r1);
-               regfree(&r2);
-               splitclean();
-               splitclean();
-               return;
-
-       /*
-        * integer up-conversions
-        */
-       case CASE(TINT8, TINT16):       // sign extend int8
-       case CASE(TINT8, TUINT16):
-       case CASE(TINT8, TINT32):
-       case CASE(TINT8, TUINT32):
-               a = AMOVBS;
-               goto rdst;
-       case CASE(TINT8, TINT64):       // convert via int32
-       case CASE(TINT8, TUINT64):
-               cvt = types[TINT32];
-               goto hard;
-
-       case CASE(TUINT8, TINT16):      // zero extend uint8
-       case CASE(TUINT8, TUINT16):
-       case CASE(TUINT8, TINT32):
-       case CASE(TUINT8, TUINT32):
-               a = AMOVBU;
-               goto rdst;
-       case CASE(TUINT8, TINT64):      // convert via uint32
-       case CASE(TUINT8, TUINT64):
-               cvt = types[TUINT32];
-               goto hard;
-
-       case CASE(TINT16, TINT32):      // sign extend int16
-       case CASE(TINT16, TUINT32):
-               a = AMOVHS;
-               goto rdst;
-       case CASE(TINT16, TINT64):      // convert via int32
-       case CASE(TINT16, TUINT64):
-               cvt = types[TINT32];
-               goto hard;
-
-       case CASE(TUINT16, TINT32):     // zero extend uint16
-       case CASE(TUINT16, TUINT32):
-               a = AMOVHU;
-               goto rdst;
-       case CASE(TUINT16, TINT64):     // convert via uint32
-       case CASE(TUINT16, TUINT64):
-               cvt = types[TUINT32];
-               goto hard;
-
-       case CASE(TINT32, TINT64):      // sign extend int32
-       case CASE(TINT32, TUINT64):
-               split64(t, &tlo, &thi);
-               regalloc(&r1, tlo.type, N);
-               regalloc(&r2, thi.type, N);
-               gmove(f, &r1);
-               p1 = gins(AMOVW, &r1, &r2);
-               p1->from.type = TYPE_SHIFT;
-               p1->from.offset = 2 << 5 | 31 << 7 | (r1.val.u.reg&15); // r1->31
-               p1->from.reg = 0;
-//print("gmove: %P\n", p1);
-               gins(AMOVW, &r1, &tlo);
-               gins(AMOVW, &r2, &thi);
-               regfree(&r1);
-               regfree(&r2);
-               splitclean();
-               return;
-
-       case CASE(TUINT32, TINT64):     // zero extend uint32
-       case CASE(TUINT32, TUINT64):
-               split64(t, &tlo, &thi);
-               gmove(f, &tlo);
-               regalloc(&r1, thi.type, N);
-               gins(AMOVW, ncon(0), &r1);
-               gins(AMOVW, &r1, &thi);
-               regfree(&r1);
-               splitclean();
-               return;
-
-       /*
-       * float to integer
-       */
-       case CASE(TFLOAT32, TINT8):
-       case CASE(TFLOAT32, TUINT8):
-       case CASE(TFLOAT32, TINT16):
-       case CASE(TFLOAT32, TUINT16):
-       case CASE(TFLOAT32, TINT32):
-       case CASE(TFLOAT32, TUINT32):
-//     case CASE(TFLOAT32, TUINT64):
-
-       case CASE(TFLOAT64, TINT8):
-       case CASE(TFLOAT64, TUINT8):
-       case CASE(TFLOAT64, TINT16):
-       case CASE(TFLOAT64, TUINT16):
-       case CASE(TFLOAT64, TINT32):
-       case CASE(TFLOAT64, TUINT32):
-//     case CASE(TFLOAT64, TUINT64):
-               fa = AMOVF;
-               a = AMOVFW;
-               if(ft == TFLOAT64) {
-                       fa = AMOVD;
-                       a = AMOVDW;
-               }
-               ta = AMOVW;
-               switch(tt) {
-               case TINT8:
-                       ta = AMOVBS;
-                       break;
-               case TUINT8:
-                       ta = AMOVBU;
-                       break;
-               case TINT16:
-                       ta = AMOVHS;
-                       break;
-               case TUINT16:
-                       ta = AMOVHU;
-                       break;
-               }
-
-               regalloc(&r1, types[ft], f);
-               regalloc(&r2, types[tt], t);
-               gins(fa, f, &r1);       // load to fpu
-               p1 = gins(a, &r1, &r1); // convert to w
-               switch(tt) {
-               case TUINT8:
-               case TUINT16:
-               case TUINT32:
-                       p1->scond |= C_UBIT;
-               }
-               gins(AMOVW, &r1, &r2);  // copy to cpu
-               gins(ta, &r2, t);       // store
-               regfree(&r1);
-               regfree(&r2);
-               return;
-
-       /*
-        * integer to float
-        */
-       case CASE(TINT8, TFLOAT32):
-       case CASE(TUINT8, TFLOAT32):
-       case CASE(TINT16, TFLOAT32):
-       case CASE(TUINT16, TFLOAT32):
-       case CASE(TINT32, TFLOAT32):
-       case CASE(TUINT32, TFLOAT32):
-       case CASE(TINT8, TFLOAT64):
-       case CASE(TUINT8, TFLOAT64):
-       case CASE(TINT16, TFLOAT64):
-       case CASE(TUINT16, TFLOAT64):
-       case CASE(TINT32, TFLOAT64):
-       case CASE(TUINT32, TFLOAT64):
-               fa = AMOVW;
-               switch(ft) {
-               case TINT8:
-                       fa = AMOVBS;
-                       break;
-               case TUINT8:
-                       fa = AMOVBU;
-                       break;
-               case TINT16:
-                       fa = AMOVHS;
-                       break;
-               case TUINT16:
-                       fa = AMOVHU;
-                       break;
-               }
-               a = AMOVWF;
-               ta = AMOVF;
-               if(tt == TFLOAT64) {
-                       a = AMOVWD;
-                       ta = AMOVD;
-               }
-               regalloc(&r1, types[ft], f);
-               regalloc(&r2, types[tt], t);
-               gins(fa, f, &r1);       // load to cpu
-               gins(AMOVW, &r1, &r2);  // copy to fpu
-               p1 = gins(a, &r2, &r2); // convert
-               switch(ft) {
-               case TUINT8:
-               case TUINT16:
-               case TUINT32:
-                       p1->scond |= C_UBIT;
-               }
-               gins(ta, &r2, t);       // store
-               regfree(&r1);
-               regfree(&r2);
-               return;
-
-       case CASE(TUINT64, TFLOAT32):
-       case CASE(TUINT64, TFLOAT64):
-               fatal("gmove UINT64, TFLOAT not implemented");
-               return;
-
-
-       /*
-        * float to float
-        */
-       case CASE(TFLOAT32, TFLOAT32):
-               a = AMOVF;
-               break;
-
-       case CASE(TFLOAT64, TFLOAT64):
-               a = AMOVD;
-               break;
-
-       case CASE(TFLOAT32, TFLOAT64):
-               regalloc(&r1, types[TFLOAT64], t);
-               gins(AMOVF, f, &r1);
-               gins(AMOVFD, &r1, &r1);
-               gins(AMOVD, &r1, t);
-               regfree(&r1);
-               return;
-
-       case CASE(TFLOAT64, TFLOAT32):
-               regalloc(&r1, types[TFLOAT64], t);
-               gins(AMOVD, f, &r1);
-               gins(AMOVDF, &r1, &r1);
-               gins(AMOVF, &r1, t);
-               regfree(&r1);
-               return;
-       }
-
-       gins(a, f, t);
-       return;
-
-rdst:
-       // TODO(kaib): we almost always require a register dest anyway, this can probably be
-       // removed.
-       // requires register destination
-       regalloc(&r1, t->type, t);
-       gins(a, f, &r1);
-       gmove(&r1, t);
-       regfree(&r1);
-       return;
-
-hard:
-       // requires register intermediate
-       regalloc(&r1, cvt, t);
-       gmove(f, &r1);
-       gmove(&r1, t);
-       regfree(&r1);
-       return;
-
-trunc64:
-       // truncate 64 bit integer
-       split64(f, &flo, &fhi);
-       regalloc(&r1, t->type, N);
-       gins(a, &flo, &r1);
-       gins(a, &r1, t);
-       regfree(&r1);
-       splitclean();
-       return;
-
-fatal:
-       // should not happen
-       fatal("gmove %N -> %N", f, t);
-}
-
-int
-samaddr(Node *f, Node *t)
-{
-
-       if(f->op != t->op)
-               return 0;
-
-       switch(f->op) {
-       case OREGISTER:
-               if(f->val.u.reg != t->val.u.reg)
-                       break;
-               return 1;
-       }
-       return 0;
-}
-
-/*
- * generate one instruction:
- *     as f, t
- */
-Prog*
-gins(int as, Node *f, Node *t)
-{
-//     Node nod;
-//     int32 v;
-       Prog *p;
-       Addr af, at;
-
-       if(f != N && f->op == OINDEX) {
-               fatal("gins OINDEX not implemented");
-//             regalloc(&nod, &regnode, Z);
-//             v = constnode.vconst;
-//             cgen(f->right, &nod);
-//             constnode.vconst = v;
-//             idx.reg = nod.reg;
-//             regfree(&nod);
-       }
-       if(t != N && t->op == OINDEX) {
-               fatal("gins OINDEX not implemented");
-//             regalloc(&nod, &regnode, Z);
-//             v = constnode.vconst;
-//             cgen(t->right, &nod);
-//             constnode.vconst = v;
-//             idx.reg = nod.reg;
-//             regfree(&nod);
-       }
-
-       memset(&af, 0, sizeof af);
-       memset(&at, 0, sizeof at);
-       if(f != N)
-               naddr(f, &af, 1);
-       if(t != N)
-               naddr(t, &at, 1);
-       p = prog(as);
-       if(f != N)
-               p->from = af;
-       if(t != N)
-               p->to = at;
-       if(debug['g'])
-               print("%P\n", p);
-       return p;
-}
-
-/*
- * insert n into reg slot of p
- */
-void
-raddr(Node *n, Prog *p)
-{
-       Addr a;
-
-       naddr(n, &a, 1);
-       if(a.type != TYPE_REG) {
-               if(n)
-                       fatal("bad in raddr: %O", n->op);
-               else
-                       fatal("bad in raddr: <null>");
-               p->reg = 0;
-       } else
-               p->reg = a.reg;
-}
-
-/* generate a comparison
-TODO(kaib): one of the args can actually be a small constant. relax the constraint and fix call sites.
- */
-Prog*
-gcmp(int as, Node *lhs, Node *rhs)
-{
-       Prog *p;
-
-       if(lhs->op != OREGISTER)
-               fatal("bad operands to gcmp: %O %O", lhs->op, rhs->op);
-
-       p = gins(as, rhs, N);
-       raddr(lhs, p);
-       return p;
-}
-
-/* generate a constant shift
- * arm encodes a shift by 32 as 0, thus asking for 0 shift is illegal.
-*/
-Prog*
-gshift(int as, Node *lhs, int32 stype, int32 sval, Node *rhs)
-{
-       Prog *p;
-
-       if(sval <= 0 || sval > 32)
-               fatal("bad shift value: %d", sval);
-
-       sval = sval&0x1f;
-
-       p = gins(as, N, rhs);
-       p->from.type = TYPE_SHIFT;
-       p->from.offset = stype | sval<<7 | (lhs->val.u.reg&15);
-       return p;
-}
-
-/* generate a register shift
-*/
-Prog *
-gregshift(int as, Node *lhs, int32 stype, Node *reg, Node *rhs)
-{
-       Prog *p;
-       p = gins(as, N, rhs);
-       p->from.type = TYPE_SHIFT;
-       p->from.offset = stype | (reg->val.u.reg&15) << 8 | 1<<4 | (lhs->val.u.reg&15);
-       return p;
-}
-
-/*
- * return Axxx for Oxxx on type t.
- */
-int
-optoas(int op, Type *t)
-{
-       int a;
-
-       if(t == T)
-               fatal("optoas: t is nil");
-
-       a = AXXX;
-       switch(CASE(op, simtype[t->etype])) {
-       default:
-               fatal("optoas: no entry %O-%T etype %T simtype %T", op, t, types[t->etype], types[simtype[t->etype]]);
-               break;
-
-/*     case CASE(OADDR, TPTR32):
-               a = ALEAL;
-               break;
-
-       case CASE(OADDR, TPTR64):
-               a = ALEAQ;
-               break;
-*/
-       // TODO(kaib): make sure the conditional branches work on all edge cases
-       case CASE(OEQ, TBOOL):
-       case CASE(OEQ, TINT8):
-       case CASE(OEQ, TUINT8):
-       case CASE(OEQ, TINT16):
-       case CASE(OEQ, TUINT16):
-       case CASE(OEQ, TINT32):
-       case CASE(OEQ, TUINT32):
-       case CASE(OEQ, TINT64):
-       case CASE(OEQ, TUINT64):
-       case CASE(OEQ, TPTR32):
-       case CASE(OEQ, TPTR64):
-       case CASE(OEQ, TFLOAT32):
-       case CASE(OEQ, TFLOAT64):
-               a = ABEQ;
-               break;
-
-       case CASE(ONE, TBOOL):
-       case CASE(ONE, TINT8):
-       case CASE(ONE, TUINT8):
-       case CASE(ONE, TINT16):
-       case CASE(ONE, TUINT16):
-       case CASE(ONE, TINT32):
-       case CASE(ONE, TUINT32):
-       case CASE(ONE, TINT64):
-       case CASE(ONE, TUINT64):
-       case CASE(ONE, TPTR32):
-       case CASE(ONE, TPTR64):
-       case CASE(ONE, TFLOAT32):
-       case CASE(ONE, TFLOAT64):
-               a = ABNE;
-               break;
-
-       case CASE(OLT, TINT8):
-       case CASE(OLT, TINT16):
-       case CASE(OLT, TINT32):
-       case CASE(OLT, TINT64):
-       case CASE(OLT, TFLOAT32):
-       case CASE(OLT, TFLOAT64):
-               a = ABLT;
-               break;
-
-       case CASE(OLT, TUINT8):
-       case CASE(OLT, TUINT16):
-       case CASE(OLT, TUINT32):
-       case CASE(OLT, TUINT64):
-               a = ABLO;
-               break;
-
-       case CASE(OLE, TINT8):
-       case CASE(OLE, TINT16):
-       case CASE(OLE, TINT32):
-       case CASE(OLE, TINT64):
-       case CASE(OLE, TFLOAT32):
-       case CASE(OLE, TFLOAT64):
-               a = ABLE;
-               break;
-
-       case CASE(OLE, TUINT8):
-       case CASE(OLE, TUINT16):
-       case CASE(OLE, TUINT32):
-       case CASE(OLE, TUINT64):
-               a = ABLS;
-               break;
-
-       case CASE(OGT, TINT8):
-       case CASE(OGT, TINT16):
-       case CASE(OGT, TINT32):
-       case CASE(OGT, TINT64):
-       case CASE(OGT, TFLOAT32):
-       case CASE(OGT, TFLOAT64):
-               a = ABGT;
-               break;
-
-       case CASE(OGT, TUINT8):
-       case CASE(OGT, TUINT16):
-       case CASE(OGT, TUINT32):
-       case CASE(OGT, TUINT64):
-               a = ABHI;
-               break;
-
-       case CASE(OGE, TINT8):
-       case CASE(OGE, TINT16):
-       case CASE(OGE, TINT32):
-       case CASE(OGE, TINT64):
-       case CASE(OGE, TFLOAT32):
-       case CASE(OGE, TFLOAT64):
-               a = ABGE;
-               break;
-
-       case CASE(OGE, TUINT8):
-       case CASE(OGE, TUINT16):
-       case CASE(OGE, TUINT32):
-       case CASE(OGE, TUINT64):
-               a = ABHS;
-               break;
-
-       case CASE(OCMP, TBOOL):
-       case CASE(OCMP, TINT8):
-       case CASE(OCMP, TUINT8):
-       case CASE(OCMP, TINT16):
-       case CASE(OCMP, TUINT16):
-       case CASE(OCMP, TINT32):
-       case CASE(OCMP, TUINT32):
-       case CASE(OCMP, TPTR32):
-               a = ACMP;
-               break;
-
-       case CASE(OCMP, TFLOAT32):
-               a = ACMPF;
-               break;
-
-       case CASE(OCMP, TFLOAT64):
-               a = ACMPD;
-               break;
-
-       case CASE(OAS, TBOOL):
-               a = AMOVB;
-               break;
-
-       case CASE(OAS, TINT8):
-               a = AMOVBS;
-               break;
-
-       case CASE(OAS, TUINT8):
-               a = AMOVBU;
-               break;
-
-       case CASE(OAS, TINT16):
-               a = AMOVHS;
-               break;
-
-       case CASE(OAS, TUINT16):
-               a = AMOVHU;
-               break;
-
-       case CASE(OAS, TINT32):
-       case CASE(OAS, TUINT32):
-       case CASE(OAS, TPTR32):
-               a = AMOVW;
-               break;
-
-       case CASE(OAS, TFLOAT32):
-               a = AMOVF;
-               break;
-
-       case CASE(OAS, TFLOAT64):
-               a = AMOVD;
-               break;
-
-       case CASE(OADD, TINT8):
-       case CASE(OADD, TUINT8):
-       case CASE(OADD, TINT16):
-       case CASE(OADD, TUINT16):
-       case CASE(OADD, TINT32):
-       case CASE(OADD, TUINT32):
-       case CASE(OADD, TPTR32):
-               a = AADD;
-               break;
-
-       case CASE(OADD, TFLOAT32):
-               a = AADDF;
-               break;
-
-       case CASE(OADD, TFLOAT64):
-               a = AADDD;
-               break;
-
-       case CASE(OSUB, TINT8):
-       case CASE(OSUB, TUINT8):
-       case CASE(OSUB, TINT16):
-       case CASE(OSUB, TUINT16):
-       case CASE(OSUB, TINT32):
-       case CASE(OSUB, TUINT32):
-       case CASE(OSUB, TPTR32):
-               a = ASUB;
-               break;
-
-       case CASE(OSUB, TFLOAT32):
-               a = ASUBF;
-               break;
-
-       case CASE(OSUB, TFLOAT64):
-               a = ASUBD;
-               break;
-
-       case CASE(OMINUS, TINT8):
-       case CASE(OMINUS, TUINT8):
-       case CASE(OMINUS, TINT16):
-       case CASE(OMINUS, TUINT16):
-       case CASE(OMINUS, TINT32):
-       case CASE(OMINUS, TUINT32):
-       case CASE(OMINUS, TPTR32):
-               a = ARSB;
-               break;
-
-       case CASE(OAND, TINT8):
-       case CASE(OAND, TUINT8):
-       case CASE(OAND, TINT16):
-       case CASE(OAND, TUINT16):
-       case CASE(OAND, TINT32):
-       case CASE(OAND, TUINT32):
-       case CASE(OAND, TPTR32):
-               a = AAND;
-               break;
-
-       case CASE(OOR, TINT8):
-       case CASE(OOR, TUINT8):
-       case CASE(OOR, TINT16):
-       case CASE(OOR, TUINT16):
-       case CASE(OOR, TINT32):
-       case CASE(OOR, TUINT32):
-       case CASE(OOR, TPTR32):
-               a = AORR;
-               break;
-
-       case CASE(OXOR, TINT8):
-       case CASE(OXOR, TUINT8):
-       case CASE(OXOR, TINT16):
-       case CASE(OXOR, TUINT16):
-       case CASE(OXOR, TINT32):
-       case CASE(OXOR, TUINT32):
-       case CASE(OXOR, TPTR32):
-               a = AEOR;
-               break;
-
-       case CASE(OLSH, TINT8):
-       case CASE(OLSH, TUINT8):
-       case CASE(OLSH, TINT16):
-       case CASE(OLSH, TUINT16):
-       case CASE(OLSH, TINT32):
-       case CASE(OLSH, TUINT32):
-       case CASE(OLSH, TPTR32):
-               a = ASLL;
-               break;
-
-       case CASE(ORSH, TUINT8):
-       case CASE(ORSH, TUINT16):
-       case CASE(ORSH, TUINT32):
-       case CASE(ORSH, TPTR32):
-               a = ASRL;
-               break;
-
-       case CASE(ORSH, TINT8):
-       case CASE(ORSH, TINT16):
-       case CASE(ORSH, TINT32):
-               a = ASRA;
-               break;
-
-       case CASE(OMUL, TUINT8):
-       case CASE(OMUL, TUINT16):
-       case CASE(OMUL, TUINT32):
-       case CASE(OMUL, TPTR32):
-               a = AMULU;
-               break;
-
-       case CASE(OMUL, TINT8):
-       case CASE(OMUL, TINT16):
-       case CASE(OMUL, TINT32):
-               a = AMUL;
-               break;
-
-       case CASE(OMUL, TFLOAT32):
-               a = AMULF;
-               break;
-
-       case CASE(OMUL, TFLOAT64):
-               a = AMULD;
-               break;
-
-       case CASE(ODIV, TUINT8):
-       case CASE(ODIV, TUINT16):
-       case CASE(ODIV, TUINT32):
-       case CASE(ODIV, TPTR32):
-               a = ADIVU;
-               break;
-
-       case CASE(ODIV, TINT8):
-       case CASE(ODIV, TINT16):
-       case CASE(ODIV, TINT32):
-               a = ADIV;
-               break;
-
-       case CASE(OMOD, TUINT8):
-       case CASE(OMOD, TUINT16):
-       case CASE(OMOD, TUINT32):
-       case CASE(OMOD, TPTR32):
-               a = AMODU;
-               break;
-
-       case CASE(OMOD, TINT8):
-       case CASE(OMOD, TINT16):
-       case CASE(OMOD, TINT32):
-               a = AMOD;
-               break;
-
-//     case CASE(OEXTEND, TINT16):
-//             a = ACWD;
-//             break;
-
-//     case CASE(OEXTEND, TINT32):
-//             a = ACDQ;
-//             break;
-
-//     case CASE(OEXTEND, TINT64):
-//             a = ACQO;
-//             break;
-
-       case CASE(ODIV, TFLOAT32):
-               a = ADIVF;
-               break;
-
-       case CASE(ODIV, TFLOAT64):
-               a = ADIVD;
-               break;
-
-       }
-       return a;
-}
-
-enum
-{
-       ODynam  = 1<<0,
-       OPtrto  = 1<<1,
-};
-
-static Node    clean[20];
-static int     cleani = 0;
-
-void
-sudoclean(void)
-{
-       if(clean[cleani-1].op != OEMPTY)
-               regfree(&clean[cleani-1]);
-       if(clean[cleani-2].op != OEMPTY)
-               regfree(&clean[cleani-2]);
-       cleani -= 2;
-}
-
-int
-dotaddable(Node *n, Node *n1)
-{
-       int o;
-       int64 oary[10];
-       Node *nn;
-
-       if(n->op != ODOT)
-               return 0;
-
-       o = dotoffset(n, oary, &nn);
-       if(nn != N && nn->addable && o == 1 && oary[0] >= 0) {
-               *n1 = *nn;
-               n1->type = n->type;
-               n1->xoffset += oary[0];
-               return 1;
-       }
-       return 0;
-}
-
-/*
- * generate code to compute address of n,
- * a reference to a (perhaps nested) field inside
- * an array or struct.
- * return 0 on failure, 1 on success.
- * on success, leaves usable address in a.
- *
- * caller is responsible for calling sudoclean
- * after successful sudoaddable,
- * to release the register used for a.
- */
-int
-sudoaddable(int as, Node *n, Addr *a, int *w)
-{
-       int o, i;
-       int64 oary[10];
-       int64 v;
-       Node n1, n2, n3, n4, *nn, *l, *r;
-       Node *reg, *reg1;
-       Prog *p1, *p2;
-       Type *t;
-
-       if(n->type == T)
-               return 0;
-
-       memset(a, 0, sizeof *a);
-
-       switch(n->op) {
-       case OLITERAL:
-               if(!isconst(n, CTINT))
-                       break;
-               v = mpgetfix(n->val.u.xval);
-               if(v >= 32000 || v <= -32000)
-                       break;
-               goto lit;
-
-       case ODOT:
-       case ODOTPTR:
-               cleani += 2;
-               reg = &clean[cleani-1];
-               reg1 = &clean[cleani-2];
-               reg->op = OEMPTY;
-               reg1->op = OEMPTY;
-               goto odot;
-
-       case OINDEX:
-               return 0;
-               // disabled: OINDEX case is now covered by agenr
-               // for a more suitable register allocation pattern.
-               if(n->left->type->etype == TSTRING)
-                       return 0;
-               cleani += 2;
-               reg = &clean[cleani-1];
-               reg1 = &clean[cleani-2];
-               reg->op = OEMPTY;
-               reg1->op = OEMPTY;
-               goto oindex;
-       }
-       return 0;
-
-lit:
-       switch(as) {
-       default:
-               return 0;
-       case AADD: case ASUB: case AAND: case AORR: case AEOR:
-       case AMOVB: case AMOVBS: case AMOVBU:
-       case AMOVH: case AMOVHS: case AMOVHU:
-       case AMOVW:
-               break;
-       }
-
-       cleani += 2;
-       reg = &clean[cleani-1];
-       reg1 = &clean[cleani-2];
-       reg->op = OEMPTY;
-       reg1->op = OEMPTY;
-       naddr(n, a, 1);
-       goto yes;
-
-odot:
-       o = dotoffset(n, oary, &nn);
-       if(nn == N)
-               goto no;
-
-       if(nn->addable && o == 1 && oary[0] >= 0) {
-               // directly addressable set of DOTs
-               n1 = *nn;
-               n1.type = n->type;
-               n1.xoffset += oary[0];
-               naddr(&n1, a, 1);
-               goto yes;
-       }
-
-       regalloc(reg, types[tptr], N);
-       n1 = *reg;
-       n1.op = OINDREG;
-       if(oary[0] >= 0) {
-               agen(nn, reg);
-               n1.xoffset = oary[0];
-       } else {
-               cgen(nn, reg);
-               cgen_checknil(reg);
-               n1.xoffset = -(oary[0]+1);
-       }
-
-       for(i=1; i<o; i++) {
-               if(oary[i] >= 0)
-                       fatal("can't happen");
-               gins(AMOVW, &n1, reg);
-               cgen_checknil(reg);
-               n1.xoffset = -(oary[i]+1);
-       }
-
-       a->type = TYPE_NONE;
-       a->name = NAME_NONE;
-       n1.type = n->type;
-       naddr(&n1, a, 1);
-       goto yes;
-
-oindex:
-       l = n->left;
-       r = n->right;
-       if(l->ullman >= UINF && r->ullman >= UINF)
-               goto no;
-
-       // set o to type of array
-       o = 0;
-       if(isptr[l->type->etype]) {
-               o += OPtrto;
-               if(l->type->type->etype != TARRAY)
-                       fatal("not ptr ary");
-               if(l->type->type->bound < 0)
-                       o += ODynam;
-       } else {
-               if(l->type->etype != TARRAY)
-                       fatal("not ary");
-               if(l->type->bound < 0)
-                       o += ODynam;
-       }
-
-       *w = n->type->width;
-       if(isconst(r, CTINT))
-               goto oindex_const;
-
-       switch(*w) {
-       default:
-               goto no;
-       case 1:
-       case 2:
-       case 4:
-       case 8:
-               break;
-       }
-
-       // load the array (reg)
-       if(l->ullman > r->ullman) {
-               regalloc(reg, types[tptr], N);
-               if(o & OPtrto) {
-                       cgen(l, reg);
-                       cgen_checknil(reg);
-               } else
-                       agen(l, reg);
-       }
-
-       // load the index (reg1)
-       t = types[TUINT32];
-       if(issigned[r->type->etype])
-               t = types[TINT32];
-       regalloc(reg1, t, N);
-       regalloc(&n3, types[TINT32], reg1);
-       p2 = cgenindex(r, &n3, debug['B'] || n->bounded);
-       gmove(&n3, reg1);
-       regfree(&n3);
-
-       // load the array (reg)
-       if(l->ullman <= r->ullman) {
-               regalloc(reg, types[tptr], N);
-               if(o & OPtrto) {
-                       cgen(l, reg);
-                       cgen_checknil(reg);
-               } else
-                       agen(l, reg);
-       }
-
-       // check bounds
-       if(!debug['B']) {
-               if(o & ODynam) {
-                       n2 = *reg;
-                       n2.op = OINDREG;
-                       n2.type = types[tptr];
-                       n2.xoffset = Array_nel;
-               } else {
-                       if(o & OPtrto)
-                               nodconst(&n2, types[TUINT32], l->type->type->bound);
-                       else
-                               nodconst(&n2, types[TUINT32], l->type->bound);
-               }
-               regalloc(&n3, n2.type, N);
-               cgen(&n2, &n3);
-               gcmp(optoas(OCMP, types[TUINT32]), reg1, &n3);
-               regfree(&n3);
-               p1 = gbranch(optoas(OLT, types[TUINT32]), T, +1);
-               if(p2)
-                       patch(p2, pc);
-               ginscall(panicindex, 0);
-               patch(p1, pc);
-       }
-
-       if(o & ODynam) {
-               n2 = *reg;
-               n2.op = OINDREG;
-               n2.type = types[tptr];
-               n2.xoffset = Array_array;
-               gmove(&n2, reg);
-       }
-
-       switch(*w) {
-       case 1:
-               gins(AADD, reg1, reg);
-               break;
-       case 2:
-               gshift(AADD, reg1, SHIFT_LL, 1, reg);
-               break;
-       case 4:
-               gshift(AADD, reg1, SHIFT_LL, 2, reg);
-               break;
-       case 8:
-               gshift(AADD, reg1, SHIFT_LL, 3, reg);
-               break;
-       }
-
-       naddr(reg1, a, 1);
-       a->type = TYPE_MEM;
-       a->reg = reg->val.u.reg;
-       a->offset = 0;
-       goto yes;
-
-oindex_const:
-       // index is constant
-       // can check statically and
-       // can multiply by width statically
-
-       regalloc(reg, types[tptr], N);
-       if(o & OPtrto) {
-               cgen(l, reg);
-               cgen_checknil(reg);
-       } else
-               agen(l, reg);
-
-       v = mpgetfix(r->val.u.xval);
-       if(o & ODynam) {
-               if(!debug['B'] && !n->bounded) {
-                       n1 = *reg;
-                       n1.op = OINDREG;
-                       n1.type = types[tptr];
-                       n1.xoffset = Array_nel;
-                       nodconst(&n2, types[TUINT32], v);
-                       regalloc(&n3, types[TUINT32], N);
-                       cgen(&n2, &n3);
-                       regalloc(&n4, n1.type, N);
-                       cgen(&n1, &n4);
-                       gcmp(optoas(OCMP, types[TUINT32]), &n4, &n3);
-                       regfree(&n4);
-                       regfree(&n3);
-                       p1 = gbranch(optoas(OGT, types[TUINT32]), T, +1);
-                       ginscall(panicindex, 0);
-                       patch(p1, pc);
-               }
-
-               n1 = *reg;
-               n1.op = OINDREG;
-               n1.type = types[tptr];
-               n1.xoffset = Array_array;
-               gmove(&n1, reg);
-       }
-
-       n2 = *reg;
-       n2.op = OINDREG;
-       n2.xoffset = v * (*w);
-       a->type = TYPE_NONE;
-       a->name = NAME_NONE;
-       naddr(&n2, a, 1);
-       goto yes;
-
-yes:
-       return 1;
-
-no:
-       sudoclean();
-       return 0;
-}
similarity index 100%
rename from src/cmd/new5g/gsubr.go
rename to src/cmd/5g/gsubr.go
diff --git a/src/cmd/5g/peep.c b/src/cmd/5g/peep.c
deleted file mode 100644 (file)
index 7fe3e10..0000000
+++ /dev/null
@@ -1,1619 +0,0 @@
-// Inferno utils/5c/peep.c
-// http://code.google.com/p/inferno-os/source/browse/utils/5c/peep.c
-//
-//     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 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 <u.h>
-#include <libc.h>
-#include "gg.h"
-#include "../gc/popt.h"
-
-static int     xtramodes(Graph*, Flow*, Adr*);
-static int     shortprop(Flow *r);
-static int     subprop(Flow*);
-static int     copyprop(Graph*, Flow*);
-static int     copy1(Adr*, Adr*, Flow*, int);
-static int     copyas(Adr*, Adr*);
-static int     copyau(Adr*, Adr*);
-static int     copysub(Adr*, Adr*, Adr*, int);
-static int     copysub1(Prog*, Adr*, Adr*, int);
-static Flow*   findpre(Flow *r, Adr *v);
-static int     copyau1(Prog *p, Adr *v);
-static int     isdconst(Addr *a);
-static int     isfloatreg(Addr*);
-static int     copyu(Prog *p, Adr *v, Adr *s);
-
-static uint32  gactive;
-
-// UNUSED
-int    shiftprop(Flow *r);
-void   constprop(Adr *c1, Adr *v1, Flow *r);
-void   predicate(Graph*);
-
-
-void
-peep(Prog *firstp)
-{
-       Flow *r;
-       Graph *g;
-       Prog *p;
-       int t;
-
-       g = flowstart(firstp, 0);
-       if(g == nil)
-               return;
-       gactive = 0;
-
-loop1:
-       if(debug['P'] && debug['v'])
-               dumpit("loop1", g->start, 0);
-
-       t = 0;
-       for(r=g->start; r!=nil; r=r->link) {
-               p = r->prog;
-               switch(p->as) {
-               case ASLL:
-               case ASRL:
-               case ASRA:
-                       /*
-                        * elide shift into TYPE_SHIFT operand of subsequent instruction
-                        */
-//                     if(shiftprop(r)) {
-//                             excise(r);
-//                             t++;
-//                             break;
-//                     }
-                       break;
-
-               case AMOVB:
-               case AMOVH:
-               case AMOVW:
-               case AMOVF:
-               case AMOVD:
-                       if(regtyp(&p->from))
-                       if(p->from.type == p->to.type && isfloatreg(&p->from) == isfloatreg(&p->to))
-                       if(p->scond == C_SCOND_NONE) {
-                               if(copyprop(g, r)) {
-                                       excise(r);
-                                       t++;
-                                       break;
-                               }
-                               if(subprop(r) && copyprop(g, r)) {
-                                       excise(r);
-                                       t++;
-                                       break;
-                               }
-                       }
-                       break;
-
-               case AMOVHS:
-               case AMOVHU:
-               case AMOVBS:
-               case AMOVBU:
-                       if(p->from.type == TYPE_REG) {
-                               if(shortprop(r))
-                                       t++;
-                       }
-                       break;
-
-                       /*
-                       if(p->scond == C_SCOND_NONE)
-                       if(regtyp(&p->to))
-                       if(isdconst(&p->from)) {
-                               constprop(&p->from, &p->to, r->s1);
-                       }
-                       break;
-                       */
-               }
-       }
-       if(t)
-               goto loop1;
-
-       for(r=g->start; r!=nil; r=r->link) {
-               p = r->prog;
-               switch(p->as) {
-               case AEOR:
-                       /*
-                        * EOR -1,x,y => MVN x,y
-                        */
-                       if(isdconst(&p->from) && p->from.offset == -1) {
-                               p->as = AMVN;
-                               p->from.type = TYPE_REG;
-                               if(p->reg != 0)
-                                       p->from.reg = p->reg;
-                               else
-                                       p->from.reg = p->to.reg;
-                               p->reg = 0;
-                       }
-                       break;
-               }
-       }
-
-       for(r=g->start; r!=nil; r=r->link) {
-               p = r->prog;
-               switch(p->as) {
-               case AMOVW:
-               case AMOVB:
-               case AMOVBS:
-               case AMOVBU:
-                       if(p->from.type == TYPE_MEM && p->from.offset == 0)
-                               xtramodes(g, r, &p->from);
-                       else
-                       if(p->to.type == TYPE_MEM && p->to.offset == 0)
-                               xtramodes(g, r, &p->to);
-                       else
-                               continue;
-                       break;
-//             case ACMP:
-//                     /*
-//                      * elide CMP $0,x if calculation of x can set condition codes
-//                      */
-//                     if(isdconst(&p->from) || p->from.offset != 0)
-//                             continue;
-//                     r2 = r->s1;
-//                     if(r2 == nil)
-//                             continue;
-//                     t = r2->prog->as;
-//                     switch(t) {
-//                     default:
-//                             continue;
-//                     case ABEQ:
-//                     case ABNE:
-//                     case ABMI:
-//                     case ABPL:
-//                             break;
-//                     case ABGE:
-//                             t = ABPL;
-//                             break;
-//                     case ABLT:
-//                             t = ABMI;
-//                             break;
-//                     case ABHI:
-//                             t = ABNE;
-//                             break;
-//                     case ABLS:
-//                             t = ABEQ;
-//                             break;
-//                     }
-//                     r1 = r;
-//                     do
-//                             r1 = uniqp(r1);
-//                     while (r1 != nil && r1->prog->as == ANOP);
-//                     if(r1 == nil)
-//                             continue;
-//                     p1 = r1->prog;
-//                     if(p1->to.type != TYPE_REG)
-//                             continue;
-//                     if(p1->to.reg != p->reg)
-//                     if(!(p1->as == AMOVW && p1->from.type == TYPE_REG && p1->from.reg == p->reg))
-//                             continue;
-//
-//                     switch(p1->as) {
-//                     default:
-//                             continue;
-//                     case AMOVW:
-//                             if(p1->from.type != TYPE_REG)
-//                                     continue;
-//                     case AAND:
-//                     case AEOR:
-//                     case AORR:
-//                     case ABIC:
-//                     case AMVN:
-//                     case ASUB:
-//                     case ARSB:
-//                     case AADD:
-//                     case AADC:
-//                     case ASBC:
-//                     case ARSC:
-//                             break;
-//                     }
-//                     p1->scond |= C_SBIT;
-//                     r2->prog->as = t;
-//                     excise(r);
-//                     continue;
-               }
-       }
-
-//     predicate(g);
-
-       flowend(g);
-}
-
-int
-regtyp(Adr *a)
-{
-       return a->type == TYPE_REG && (REG_R0 <= a->reg && a->reg <= REG_R15 || REG_F0 <= a->reg && a->reg <= REG_F15);
-}
-
-/*
- * the idea is to substitute
- * one register for another
- * from one MOV to another
- *     MOV     a, R0
- *     ADD     b, R0   / no use of R1
- *     MOV     R0, R1
- * would be converted to
- *     MOV     a, R1
- *     ADD     b, R1
- *     MOV     R1, R0
- * hopefully, then the former or latter MOV
- * will be eliminated by copy propagation.
- */
-static int
-subprop(Flow *r0)
-{
-       Prog *p;
-       Adr *v1, *v2;
-       Flow *r;
-       int t;
-       ProgInfo info;
-
-       p = r0->prog;
-       v1 = &p->from;
-       if(!regtyp(v1))
-               return 0;
-       v2 = &p->to;
-       if(!regtyp(v2))
-               return 0;
-       for(r=uniqp(r0); r!=nil; r=uniqp(r)) {
-               if(uniqs(r) == nil)
-                       break;
-               p = r->prog;
-               if(p->as == AVARDEF || p->as == AVARKILL)
-                       continue;
-               proginfo(&info, p);
-               if(info.flags & Call)
-                       return 0;
-
-               if((info.flags & CanRegRead) && p->to.type == TYPE_REG) {
-                       info.flags |= RegRead;
-                       info.flags &= ~(CanRegRead | RightRead);
-                       p->reg = p->to.reg;
-               }
-
-               switch(p->as) {
-               case AMULLU:
-               case AMULA:
-               case AMVN:
-                       return 0;
-               }
-               
-               if((info.flags & (RightRead|RightWrite)) == RightWrite) {
-                       if(p->to.type == v1->type)
-                       if(p->to.reg == v1->reg)
-                       if(p->scond == C_SCOND_NONE)
-                               goto gotit;
-               }
-
-               if(copyau(&p->from, v2) ||
-                  copyau1(p, v2) ||
-                  copyau(&p->to, v2))
-                       break;
-               if(copysub(&p->from, v1, v2, 0) ||
-                  copysub1(p, v1, v2, 0) ||
-                  copysub(&p->to, v1, v2, 0))
-                       break;
-       }
-       return 0;
-
-gotit:
-       copysub(&p->to, v1, v2, 1);
-       if(debug['P']) {
-               print("gotit: %D->%D\n%P", v1, v2, r->prog);
-               if(p->from.type == v2->type)
-                       print(" excise");
-               print("\n");
-       }
-       for(r=uniqs(r); r!=r0; r=uniqs(r)) {
-               p = r->prog;
-               copysub(&p->from, v1, v2, 1);
-               copysub1(p, v1, v2, 1);
-               copysub(&p->to, v1, v2, 1);
-               if(debug['P'])
-                       print("%P\n", r->prog);
-       }
-       t = v1->reg;
-       v1->reg = v2->reg;
-       v2->reg = t;
-       if(debug['P'])
-               print("%P last\n", r->prog);
-       return 1;
-}
-
-/*
- * The idea is to remove redundant copies.
- *     v1->v2  F=0
- *     (use v2 s/v2/v1/)*
- *     set v1  F=1
- *     use v2  return fail
- *     -----------------
- *     v1->v2  F=0
- *     (use v2 s/v2/v1/)*
- *     set v1  F=1
- *     set v2  return success
- */
-static int
-copyprop(Graph *g, Flow *r0)
-{
-       Prog *p;
-       Adr *v1, *v2;
-
-       USED(g);
-       p = r0->prog;
-       v1 = &p->from;
-       v2 = &p->to;
-       if(copyas(v1, v2))
-               return 1;
-       gactive++;
-       return copy1(v1, v2, r0->s1, 0);
-}
-
-static int
-copy1(Adr *v1, Adr *v2, Flow *r, int f)
-{
-       int t;
-       Prog *p;
-
-       if(r->active == gactive) {
-               if(debug['P'])
-                       print("act set; return 1\n");
-               return 1;
-       }
-       r->active = gactive;
-       if(debug['P'])
-               print("copy %D->%D f=%d\n", v1, v2, f);
-       for(; r != nil; r = r->s1) {
-               p = r->prog;
-               if(debug['P'])
-                       print("%P", p);
-               if(!f && uniqp(r) == nil) {
-                       f = 1;
-                       if(debug['P'])
-                               print("; merge; f=%d", f);
-               }
-               t = copyu(p, v2, nil);
-               switch(t) {
-               case 2: /* rar, can't split */
-                       if(debug['P'])
-                               print("; %Drar; return 0\n", v2);
-                       return 0;
-
-               case 3: /* set */
-                       if(debug['P'])
-                               print("; %Dset; return 1\n", v2);
-                       return 1;
-
-               case 1: /* used, substitute */
-               case 4: /* use and set */
-                       if(f) {
-                               if(!debug['P'])
-                                       return 0;
-                               if(t == 4)
-                                       print("; %Dused+set and f=%d; return 0\n", v2, f);
-                               else
-                                       print("; %Dused and f=%d; return 0\n", v2, f);
-                               return 0;
-                       }
-                       if(copyu(p, v2, v1)) {
-                               if(debug['P'])
-                                       print("; sub fail; return 0\n");
-                               return 0;
-                       }
-                       if(debug['P'])
-                               print("; sub%D/%D", v2, v1);
-                       if(t == 4) {
-                               if(debug['P'])
-                                       print("; %Dused+set; return 1\n", v2);
-                               return 1;
-                       }
-                       break;
-               }
-               if(!f) {
-                       t = copyu(p, v1, nil);
-                       if(!f && (t == 2 || t == 3 || t == 4)) {
-                               f = 1;
-                               if(debug['P'])
-                                       print("; %Dset and !f; f=%d", v1, f);
-                       }
-               }
-               if(debug['P'])
-                       print("\n");
-               if(r->s2)
-                       if(!copy1(v1, v2, r->s2, f))
-                               return 0;
-       }
-       return 1;
-}
-
-// UNUSED
-/*
- * The idea is to remove redundant constants.
- *     $c1->v1
- *     ($c1->v2 s/$c1/v1)*
- *     set v1  return
- * The v1->v2 should be eliminated by copy propagation.
- */
-void
-constprop(Adr *c1, Adr *v1, Flow *r)
-{
-       Prog *p;
-
-       if(debug['P'])
-               print("constprop %D->%D\n", c1, v1);
-       for(; r != nil; r = r->s1) {
-               p = r->prog;
-               if(debug['P'])
-                       print("%P", p);
-               if(uniqp(r) == nil) {
-                       if(debug['P'])
-                               print("; merge; return\n");
-                       return;
-               }
-               if(p->as == AMOVW && copyas(&p->from, c1)) {
-                               if(debug['P'])
-                                       print("; sub%D/%D", &p->from, v1);
-                               p->from = *v1;
-               } else if(copyu(p, v1, nil) > 1) {
-                       if(debug['P'])
-                               print("; %Dset; return\n", v1);
-                       return;
-               }
-               if(debug['P'])
-                       print("\n");
-               if(r->s2)
-                       constprop(c1, v1, r->s2);
-       }
-}
-
-/*
- * shortprop eliminates redundant zero/sign extensions.
- *
- *   MOVBS x, R
- *   <no use R>
- *   MOVBS R, R'
- *
- * changed to
- *
- *   MOVBS x, R
- *   ...
- *   MOVB  R, R' (compiled to mov)
- *
- * MOVBS above can be a MOVBS, MOVBU, MOVHS or MOVHU.
- */
-static int
-shortprop(Flow *r)
-{
-       Prog *p, *p1;
-       Flow *r1;
-
-       p = r->prog;
-       r1 = findpre(r, &p->from);
-       if(r1 == nil)
-               return 0;
-
-       p1 = r1->prog;
-       if(p1->as == p->as) {
-               // Two consecutive extensions.
-               goto gotit;
-       }
-
-       if(p1->as == AMOVW && isdconst(&p1->from)
-          && p1->from.offset >= 0 && p1->from.offset < 128) {
-               // Loaded an immediate.
-               goto gotit;
-       }
-
-       return 0;
-
-gotit:
-       if(debug['P'])
-               print("shortprop\n%P\n%P", p1, p);
-       switch(p->as) {
-       case AMOVBS:
-       case AMOVBU:
-               p->as = AMOVB;
-               break;
-       case AMOVHS:
-       case AMOVHU:
-               p->as = AMOVH;
-               break;
-       }
-       if(debug['P'])
-               print(" => %A\n", p->as);
-       return 1;
-}
-
-// UNUSED
-/*
- * ASLL x,y,w
- * .. (not use w, not set x y w)
- * AXXX w,a,b (a != w)
- * .. (not use w)
- * (set w)
- * ----------- changed to
- * ..
- * AXXX (x<<y),a,b
- * ..
- */
-
-int
-shiftprop(Flow *r)
-{
-       Flow *r1;
-       Prog *p, *p1, *p2;
-       int n, o;
-       Adr a;
-
-       p = r->prog;
-       if(p->to.type != TYPE_REG) {
-               if(debug['P'])
-                       print("\tBOTCH: result not reg; FAILURE\n");
-               return 0;
-       }
-       n = p->to.reg;
-       a = zprog.from;
-       if(p->reg != 0 && p->reg != p->to.reg) {
-               a.type = TYPE_REG;
-               a.reg = p->reg;
-       }
-       if(debug['P'])
-               print("shiftprop\n%P", p);
-       r1 = r;
-       for(;;) {
-               /* find first use of shift result; abort if shift operands or result are changed */
-               r1 = uniqs(r1);
-               if(r1 == nil) {
-                       if(debug['P'])
-                               print("\tbranch; FAILURE\n");
-                       return 0;
-               }
-               if(uniqp(r1) == nil) {
-                       if(debug['P'])
-                               print("\tmerge; FAILURE\n");
-                       return 0;
-               }
-               p1 = r1->prog;
-               if(debug['P'])
-                       print("\n%P", p1);
-               switch(copyu(p1, &p->to, nil)) {
-               case 0: /* not used or set */
-                       if((p->from.type == TYPE_REG && copyu(p1, &p->from, nil) > 1) ||
-                          (a.type == TYPE_REG && copyu(p1, &a, nil) > 1)) {
-                               if(debug['P'])
-                                       print("\targs modified; FAILURE\n");
-                               return 0;
-                       }
-                       continue;
-               case 3: /* set, not used */ {
-                       if(debug['P'])
-                               print("\tBOTCH: noref; FAILURE\n");
-                       return 0;
-               }
-               }
-               break;
-       }
-       /* check whether substitution can be done */
-       switch(p1->as) {
-       default:
-               if(debug['P'])
-                       print("\tnon-dpi; FAILURE\n");
-               return 0;
-
-       case AAND:
-       case AEOR:
-       case AADD:
-       case AADC:
-       case AORR:
-       case ASUB:
-       case ASBC:
-       case ARSB:
-       case ARSC:
-               if(p1->reg == n || (p1->reg == 0 && p1->to.type == TYPE_REG && p1->to.reg == n)) {
-                       if(p1->from.type != TYPE_REG) {
-                               if(debug['P'])
-                                       print("\tcan't swap; FAILURE\n");
-                               return 0;
-                       }
-                       p1->reg = p1->from.reg;
-                       p1->from.reg = n;
-                       switch(p1->as) {
-                       case ASUB:
-                               p1->as = ARSB;
-                               break;
-                       case ARSB:
-                               p1->as = ASUB;
-                               break;
-                       case ASBC:
-                               p1->as = ARSC;
-                               break;
-                       case ARSC:
-                               p1->as = ASBC;
-                               break;
-                       }
-                       if(debug['P'])
-                               print("\t=>%P", p1);
-               }
-       case ABIC:
-       case ATST:
-       case ACMP:
-       case ACMN:
-               if(p1->reg == n) {
-                       if(debug['P'])
-                               print("\tcan't swap; FAILURE\n");
-                       return 0;
-               }
-               if(p1->reg == 0 && p1->to.reg == n) {
-                       if(debug['P'])
-                               print("\tshift result used twice; FAILURE\n");
-                       return 0;
-               }
-//     case AMVN:
-               if(p1->from.type == TYPE_SHIFT) {
-                       if(debug['P'])
-                               print("\tshift result used in shift; FAILURE\n");
-                       return 0;
-               }
-               if(p1->from.type != TYPE_REG || p1->from.reg != n) {
-                       if(debug['P'])
-                               print("\tBOTCH: where is it used?; FAILURE\n");
-                       return 0;
-               }
-               break;
-       }
-       /* check whether shift result is used subsequently */
-       p2 = p1;
-       if(p1->to.reg != n)
-       for (;;) {
-               r1 = uniqs(r1);
-               if(r1 == nil) {
-                       if(debug['P'])
-                               print("\tinconclusive; FAILURE\n");
-                       return 0;
-               }
-               p1 = r1->prog;
-               if(debug['P'])
-                       print("\n%P", p1);
-               switch(copyu(p1, &p->to, nil)) {
-               case 0: /* not used or set */
-                       continue;
-               case 3: /* set, not used */
-                       break;
-               default:/* used */
-                       if(debug['P'])
-                               print("\treused; FAILURE\n");
-                       return 0;
-               }
-               break;
-       }
-
-       /* make the substitution */
-       p2->from.reg = 0;
-       o = p->reg;
-       if(o == 0)
-               o = p->to.reg;
-       o &= 15;
-
-       switch(p->from.type){
-       case TYPE_CONST:
-               o |= (p->from.offset&0x1f)<<7;
-               break;
-       case TYPE_REG:
-               o |= (1<<4) | ((p->from.reg&15)<<8);
-               break;
-       }
-       switch(p->as){
-       case ASLL:
-               o |= 0<<5;
-               break;
-       case ASRL:
-               o |= 1<<5;
-               break;
-       case ASRA:
-               o |= 2<<5;
-               break;
-       }
-       p2->from = zprog.from;
-       p2->from.type = TYPE_SHIFT;
-       p2->from.offset = o;
-       if(debug['P'])
-               print("\t=>%P\tSUCCEED\n", p2);
-       return 1;
-}
-
-/*
- * findpre returns the last instruction mentioning v
- * before r. It must be a set, and there must be
- * a unique path from that instruction to r.
- */
-static Flow*
-findpre(Flow *r, Adr *v)
-{
-       Flow *r1;
-
-       for(r1=uniqp(r); r1!=nil; r=r1,r1=uniqp(r)) {
-               if(uniqs(r1) != r)
-                       return nil;
-               switch(copyu(r1->prog, v, nil)) {
-               case 1: /* used */
-               case 2: /* read-alter-rewrite */
-                       return nil;
-               case 3: /* set */
-               case 4: /* set and used */
-                       return r1;
-               }
-       }
-       return nil;
-}
-
-/*
- * findinc finds ADD instructions with a constant
- * argument which falls within the immed_12 range.
- */
-static Flow*
-findinc(Flow *r, Flow *r2, Adr *v)
-{
-       Flow *r1;
-       Prog *p;
-
-
-       for(r1=uniqs(r); r1!=nil && r1!=r2; r=r1,r1=uniqs(r)) {
-               if(uniqp(r1) != r)
-                       return nil;
-               switch(copyu(r1->prog, v, nil)) {
-               case 0: /* not touched */
-                       continue;
-               case 4: /* set and used */
-                       p = r1->prog;
-                       if(p->as == AADD)
-                       if(isdconst(&p->from))
-                       if(p->from.offset > -4096 && p->from.offset < 4096)
-                               return r1;
-               default:
-                       return nil;
-               }
-       }
-       return nil;
-}
-
-static int
-nochange(Flow *r, Flow *r2, Prog *p)
-{
-       Adr a[3];
-       int i, n;
-
-       if(r == r2)
-               return 1;
-       n = 0;
-       if(p->reg != 0 && p->reg != p->to.reg) {
-               a[n].type = TYPE_REG;
-               a[n++].reg = p->reg;
-       }
-       switch(p->from.type) {
-       case TYPE_SHIFT:
-               a[n].type = TYPE_REG;
-               a[n++].reg = REG_R0 + (p->from.offset&0xf);
-       case TYPE_REG:
-               a[n].type = TYPE_REG;
-               a[n++].reg = p->from.reg;
-       }
-       if(n == 0)
-               return 1;
-       for(; r!=nil && r!=r2; r=uniqs(r)) {
-               p = r->prog;
-               for(i=0; i<n; i++)
-                       if(copyu(p, &a[i], nil) > 1)
-                               return 0;
-       }
-       return 1;
-}
-
-static int
-findu1(Flow *r, Adr *v)
-{
-       for(; r != nil; r = r->s1) {
-               if(r->active)
-                       return 0;
-               r->active = 1;
-               switch(copyu(r->prog, v, nil)) {
-               case 1: /* used */
-               case 2: /* read-alter-rewrite */
-               case 4: /* set and used */
-                       return 1;
-               case 3: /* set */
-                       return 0;
-               }
-               if(r->s2)
-                       if (findu1(r->s2, v))
-                               return 1;
-       }
-       return 0;
-}
-
-static int
-finduse(Graph *g, Flow *r, Adr *v)
-{
-       Flow *r1;
-
-       for(r1=g->start; r1!=nil; r1=r1->link)
-               r1->active = 0;
-       return findu1(r, v);
-}
-
-/*
- * xtramodes enables the ARM post increment and
- * shift offset addressing modes to transform
- *   MOVW   0(R3),R1
- *   ADD    $4,R3,R3
- * into
- *   MOVW.P 4(R3),R1
- * and 
- *   ADD    R0,R1
- *   MOVBU  0(R1),R0
- * into 
- *   MOVBU  R0<<0(R1),R0
- */
-static int
-xtramodes(Graph *g, Flow *r, Adr *a)
-{
-       Flow *r1, *r2, *r3;
-       Prog *p, *p1;
-       Adr v;
-
-       p = r->prog;
-       v = *a;
-       v.type = TYPE_REG;
-       r1 = findpre(r, &v);
-       if(r1 != nil) {
-               p1 = r1->prog;
-               if(p1->to.type == TYPE_REG && p1->to.reg == v.reg)
-               switch(p1->as) {
-               case AADD:
-                       if(p1->scond & C_SBIT)
-                               // avoid altering ADD.S/ADC sequences.
-                               break;
-                       if(p1->from.type == TYPE_REG ||
-                          (p1->from.type == TYPE_SHIFT && (p1->from.offset&(1<<4)) == 0 &&
-                           ((p->as != AMOVB && p->as != AMOVBS) || (a == &p->from && (p1->from.offset&~0xf) == 0))) ||
-                          ((p1->from.type == TYPE_ADDR || p1->from.type == TYPE_CONST) &&
-                           p1->from.offset > -4096 && p1->from.offset < 4096))
-                       if(nochange(uniqs(r1), r, p1)) {
-                               if(a != &p->from || v.reg != p->to.reg)
-                               if (finduse(g, r->s1, &v)) {
-                                       if(p1->reg == 0 || p1->reg == v.reg)
-                                               /* pre-indexing */
-                                               p->scond |= C_WBIT;
-                                       else return 0;
-                               }
-                               switch (p1->from.type) {
-                               case TYPE_REG:
-                                       /* register offset */
-                                       if(nacl)
-                                               return 0;
-                                       *a = zprog.from;
-                                       a->type = TYPE_SHIFT;
-                                       a->offset = p1->from.reg&15;
-                                       break;
-                               case TYPE_SHIFT:
-                                       /* scaled register offset */
-                                       if(nacl)
-                                               return 0;
-                                       *a = zprog.from;
-                                       a->type = TYPE_SHIFT;
-                               case TYPE_CONST:
-                               case TYPE_ADDR:
-                                       /* immediate offset */
-                                       a->offset = p1->from.offset;
-                                       break;
-                               }
-                               if(p1->reg != 0)
-                                       a->reg = p1->reg;
-                               excise(r1);
-                               return 1;
-                       }
-                       break;
-               case AMOVW:
-                       if(p1->from.type == TYPE_REG)
-                       if((r2 = findinc(r1, r, &p1->from)) != nil) {
-                       for(r3=uniqs(r2); r3->prog->as==ANOP; r3=uniqs(r3))
-                               ;
-                       if(r3 == r) {
-                               /* post-indexing */
-                               p1 = r2->prog;
-                               a->reg = p1->to.reg;
-                               a->offset = p1->from.offset;
-                               p->scond |= C_PBIT;
-                               if(!finduse(g, r, &r1->prog->to))
-                                       excise(r1);
-                               excise(r2);
-                               return 1;
-                       }
-                       }
-                       break;
-               }
-       }
-       if(a != &p->from || a->reg != p->to.reg)
-       if((r1 = findinc(r, nil, &v)) != nil) {
-               /* post-indexing */
-               p1 = r1->prog;
-               a->offset = p1->from.offset;
-               p->scond |= C_PBIT;
-               excise(r1);
-               return 1;
-       }
-       return 0;
-}
-
-/*
- * return
- * 1 if v only used (and substitute),
- * 2 if read-alter-rewrite
- * 3 if set
- * 4 if set and used
- * 0 otherwise (not touched)
- */
-static int
-copyu(Prog *p, Adr *v, Adr *s)
-{
-       switch(p->as) {
-
-       default:
-               print("copyu: can't find %A\n", p->as);
-               return 2;
-
-       case AMOVM:
-               if(v->type != TYPE_REG)
-                       return 0;
-               if(p->from.type == TYPE_CONST) {        /* read reglist, read/rar */
-                       if(s != nil) {
-                               if(p->from.offset&(1<<v->reg))
-                                       return 1;
-                               if(copysub(&p->to, v, s, 1))
-                                       return 1;
-                               return 0;
-                       }
-                       if(copyau(&p->to, v)) {
-                               if(p->scond&C_WBIT)
-                                       return 2;
-                               return 1;
-                       }
-                       if(p->from.offset&(1<<v->reg))
-                               return 1;
-               } else {                        /* read/rar, write reglist */
-                       if(s != nil) {
-                               if(p->to.offset&(1<<v->reg))
-                                       return 1;
-                               if(copysub(&p->from, v, s, 1))
-                                       return 1;
-                               return 0;
-                       }
-                       if(copyau(&p->from, v)) {
-                               if(p->scond&C_WBIT)
-                                       return 2;
-                               if(p->to.offset&(1<<v->reg))
-                                       return 4;
-                               return 1;
-                       }
-                       if(p->to.offset&(1<<v->reg))
-                               return 3;
-               }
-               return 0;
-
-       case ANOP:      /* read,, write */
-       case AMOVW:
-       case AMOVF:
-       case AMOVD:
-       case AMOVH:
-       case AMOVHS:
-       case AMOVHU:
-       case AMOVB:
-       case AMOVBS:
-       case AMOVBU:
-       case AMOVFW:
-       case AMOVWF:
-       case AMOVDW:
-       case AMOVWD:
-       case AMOVFD:
-       case AMOVDF:
-               if(p->scond&(C_WBIT|C_PBIT))
-               if(v->type == TYPE_REG) {
-                       if(p->from.type == TYPE_MEM || p->from.type == TYPE_SHIFT) {
-                               if(p->from.reg == v->reg)
-                                       return 2;
-                       } else {
-                               if(p->to.reg == v->reg)
-                                       return 2;
-                       }
-               }
-               if(s != nil) {
-                       if(copysub(&p->from, v, s, 1))
-                               return 1;
-                       if(!copyas(&p->to, v))
-                               if(copysub(&p->to, v, s, 1))
-                                       return 1;
-                       return 0;
-               }
-               if(copyas(&p->to, v)) {
-                       if(p->scond != C_SCOND_NONE)
-                               return 2;
-                       if(copyau(&p->from, v))
-                               return 4;
-                       return 3;
-               }
-               if(copyau(&p->from, v))
-                       return 1;
-               if(copyau(&p->to, v))
-                       return 1;
-               return 0;
-
-       case AMULLU:    /* read, read, write, write */
-       case AMULL:
-       case AMULA:
-       case AMVN:
-               return 2;
-
-       case AADD:      /* read, read, write */
-       case AADC:
-       case ASUB:
-       case ASBC:
-       case ARSB:
-       case ASLL:
-       case ASRL:
-       case ASRA:
-       case AORR:
-       case AAND:
-       case AEOR:
-       case AMUL:
-       case AMULU:
-       case ADIV:
-       case ADIVU:
-       case AMOD:
-       case AMODU:
-       case AADDF:
-       case AADDD:
-       case ASUBF:
-       case ASUBD:
-       case AMULF:
-       case AMULD:
-       case ADIVF:
-       case ADIVD:
-
-       case ACHECKNIL: /* read */
-       case ACMPF:     /* read, read, */
-       case ACMPD:
-       case ACMP:
-       case ACMN:
-       case ACASE:
-       case ATST:      /* read,, */
-               if(s != nil) {
-                       if(copysub(&p->from, v, s, 1))
-                               return 1;
-                       if(copysub1(p, v, s, 1))
-                               return 1;
-                       if(!copyas(&p->to, v))
-                               if(copysub(&p->to, v, s, 1))
-                                       return 1;
-                       return 0;
-               }
-               if(copyas(&p->to, v)) {
-                       if(p->scond != C_SCOND_NONE)
-                               return 2;
-                       if(p->reg == 0)
-                               p->reg = p->to.reg;
-                       if(copyau(&p->from, v))
-                               return 4;
-                       if(copyau1(p, v))
-                               return 4;
-                       return 3;
-               }
-               if(copyau(&p->from, v))
-                       return 1;
-               if(copyau1(p, v))
-                       return 1;
-               if(copyau(&p->to, v))
-                       return 1;
-               return 0;
-
-       case ABEQ:      /* read, read */
-       case ABNE:
-       case ABCS:
-       case ABHS:
-       case ABCC:
-       case ABLO:
-       case ABMI:
-       case ABPL:
-       case ABVS:
-       case ABVC:
-       case ABHI:
-       case ABLS:
-       case ABGE:
-       case ABLT:
-       case ABGT:
-       case ABLE:
-               if(s != nil) {
-                       if(copysub(&p->from, v, s, 1))
-                               return 1;
-                       return copysub1(p, v, s, 1);
-               }
-               if(copyau(&p->from, v))
-                       return 1;
-               if(copyau1(p, v))
-                       return 1;
-               return 0;
-
-       case AB:        /* funny */
-               if(s != nil) {
-                       if(copysub(&p->to, v, s, 1))
-                               return 1;
-                       return 0;
-               }
-               if(copyau(&p->to, v))
-                       return 1;
-               return 0;
-
-       case ARET:      /* funny */
-               if(s != nil)
-                       return 1;
-               return 3;
-
-       case ABL:       /* funny */
-               if(v->type == TYPE_REG) {
-                       // TODO(rsc): REG_R0 and REG_F0 used to be
-                       // (when register numbers started at 0) exregoffset and exfregoffset,
-                       // which are unset entirely. 
-                       // It's strange that this handles R0 and F0 differently from the other
-                       // registers. Possible failure to optimize?
-                       if(REG_R0 < v->reg && v->reg <= REGEXT)
-                               return 2;
-                       if(v->reg == REGARG)
-                               return 2;
-                       if(REG_F0 < v->reg && v->reg <= FREGEXT)
-                               return 2;
-               }
-               if(p->from.type == TYPE_REG && v->type == TYPE_REG && p->from.reg == v->reg)
-                       return 2;
-
-               if(s != nil) {
-                       if(copysub(&p->to, v, s, 1))
-                               return 1;
-                       return 0;
-               }
-               if(copyau(&p->to, v))
-                       return 4;
-               return 3;
-       case ADUFFZERO:
-               // R0 is zero, used by DUFFZERO, cannot be substituted.
-               // R1 is ptr to memory, used and set, cannot be substituted.
-               if(v->type == TYPE_REG) {
-                       if(v->reg == REGALLOC_R0)
-                               return 1;
-                       if(v->reg == REGALLOC_R0+1)
-                               return 2;
-               }
-               return 0;
-       case ADUFFCOPY:
-               // R0 is scratch, set by DUFFCOPY, cannot be substituted.
-               // R1, R2 areptr to src, dst, used and set, cannot be substituted.
-               if(v->type == TYPE_REG) {
-                       if(v->reg == REGALLOC_R0)
-                               return 3;
-                       if(v->reg == REGALLOC_R0+1 || v->reg == REGALLOC_R0+2)
-                               return 2;
-               }
-               return 0;
-                       
-       case ATEXT:     /* funny */
-               if(v->type == TYPE_REG)
-                       if(v->reg == REGARG)
-                               return 3;
-               return 0;
-
-       case APCDATA:
-       case AFUNCDATA:
-       case AVARDEF:
-       case AVARKILL:
-               return 0;
-       }
-}
-
-/*
- * direct reference,
- * could be set/use depending on
- * semantics
- */
-static int
-copyas(Adr *a, Adr *v)
-{
-
-       if(regtyp(v)) {
-               if(a->type == v->type)
-               if(a->reg == v->reg)
-                       return 1;
-       } else
-       if(v->type == TYPE_CONST) {             /* for constprop */
-               if(a->type == v->type)
-               if(a->name == v->name)
-               if(a->sym == v->sym)
-               if(a->reg == v->reg)
-               if(a->offset == v->offset)
-                       return 1;
-       }
-       return 0;
-}
-
-int
-sameaddr(Adr *a, Adr *v)
-{
-       if(a->type != v->type)
-               return 0;
-       if(regtyp(v) && a->reg == v->reg)
-               return 1;
-       // TODO(rsc): Change v->type to v->name and enable.
-       //if(v->type == NAME_AUTO || v->type == NAME_PARAM) {
-       //      if(v->offset == a->offset)
-       //              return 1;
-       //}
-       return 0;
-}
-
-/*
- * either direct or indirect
- */
-static int
-copyau(Adr *a, Adr *v)
-{
-
-       if(copyas(a, v))
-               return 1;
-       if(v->type == TYPE_REG) {
-               if(a->type == TYPE_ADDR && a->reg != 0) {
-                       if(a->reg == v->reg)
-                               return 1;
-               } else
-               if(a->type == TYPE_MEM) {
-                       if(a->reg == v->reg)
-                               return 1;
-               } else
-               if(a->type == TYPE_REGREG || a->type == TYPE_REGREG2) {
-                       if(a->reg == v->reg)
-                               return 1;
-                       if(a->offset == v->reg)
-                               return 1;
-               } else
-               if(a->type == TYPE_SHIFT) {
-                       if((a->offset&0xf) == v->reg - REG_R0)
-                               return 1;
-                       if((a->offset&(1<<4)) && ((a->offset>>8)&0xf) == v->reg - REG_R0)
-                               return 1;
-               }
-       }
-       return 0;
-}
-
-/*
- * compare v to the center
- * register in p (p->reg)
- */
-static int
-copyau1(Prog *p, Adr *v)
-{
-       if(v->type == TYPE_REG && v->reg == 0)
-               return 0;
-       return p->reg == v->reg;
-}
-
-/*
- * substitute s for v in a
- * return failure to substitute
- */
-static int
-copysub(Adr *a, Adr *v, Adr *s, int f)
-{
-
-       if(f)
-       if(copyau(a, v)) {
-               if(a->type == TYPE_SHIFT) {
-                       if((a->offset&0xf) == v->reg - REG_R0)
-                               a->offset = (a->offset&~0xf)|(s->reg&0xf);
-                       if((a->offset&(1<<4)) && ((a->offset>>8)&0xf) == v->reg - REG_R0)
-                               a->offset = (a->offset&~(0xf<<8))|((s->reg&0xf)<<8);
-               } else
-               if(a->type == TYPE_REGREG || a->type == TYPE_REGREG2) {
-                       if(a->offset == v->reg)
-                               a->offset = s->reg;
-                       if(a->reg == v->reg)
-                               a->reg = s->reg;
-               } else
-                       a->reg = s->reg;
-       }
-       return 0;
-}
-
-static int
-copysub1(Prog *p1, Adr *v, Adr *s, int f)
-{
-
-       if(f)
-       if(copyau1(p1, v))
-               p1->reg = s->reg;
-       return 0;
-}
-
-struct {
-       int opcode;
-       int notopcode;
-       int scond;
-       int notscond;
-} predinfo[]  = {
-       { ABEQ, ABNE,   0x0,    0x1, },
-       { ABNE, ABEQ,   0x1,    0x0, },
-       { ABCS, ABCC,   0x2,    0x3, },
-       { ABHS, ABLO,   0x2,    0x3, },
-       { ABCC, ABCS,   0x3,    0x2, },
-       { ABLO, ABHS,   0x3,    0x2, },
-       { ABMI, ABPL,   0x4,    0x5, },
-       { ABPL, ABMI,   0x5,    0x4, },
-       { ABVS, ABVC,   0x6,    0x7, },
-       { ABVC, ABVS,   0x7,    0x6, },
-       { ABHI, ABLS,   0x8,    0x9, },
-       { ABLS, ABHI,   0x9,    0x8, },
-       { ABGE, ABLT,   0xA,    0xB, },
-       { ABLT, ABGE,   0xB,    0xA, },
-       { ABGT, ABLE,   0xC,    0xD, },
-       { ABLE, ABGT,   0xD,    0xC, },
-};
-
-typedef struct {
-       Flow *start;
-       Flow *last;
-       Flow *end;
-       int len;
-} Joininfo;
-
-enum {
-       Join,
-       Split,
-       End,
-       Branch,
-       Setcond,
-       Toolong
-};
-
-enum {
-       Falsecond,
-       Truecond,
-       Delbranch,
-       Keepbranch
-};
-
-static int
-isbranch(Prog *p)
-{
-       return (ABEQ <= p->as) && (p->as <= ABLE);
-}
-
-static int
-predicable(Prog *p)
-{
-       switch(p->as) {
-       case ANOP:
-       case AXXX:
-       case ADATA:
-       case AGLOBL:
-       case ATEXT:
-       case AWORD:
-       case ABCASE:
-       case ACASE:
-               return 0;
-       }
-       if(isbranch(p))
-               return 0;
-       return 1;
-}
-
-/*
- * Depends on an analysis of the encodings performed by 5l.
- * These seem to be all of the opcodes that lead to the "S" bit
- * being set in the instruction encodings.
- *
- * C_SBIT may also have been set explicitly in p->scond.
- */
-static int
-modifiescpsr(Prog *p)
-{
-       switch(p->as) {
-       case AMULLU:
-       case AMULA:
-       case AMULU:
-       case ADIVU:
-
-       case ATEQ:
-       case ACMN:
-       case ATST:
-       case ACMP:
-       case AMUL:
-       case ADIV:
-       case AMOD:
-       case AMODU:
-       case ABL:
-               return 1;
-       }
-       if(p->scond & C_SBIT)
-               return 1;
-       return 0;
-}
-
-/*
- * Find the maximal chain of instructions starting with r which could
- * be executed conditionally
- */
-static int
-joinsplit(Flow *r, Joininfo *j)
-{
-       j->start = r;
-       j->last = r;
-       j->len = 0;
-       do {
-               if (r->p2 && (r->p1 || r->p2->p2link)) {
-                       j->end = r;
-                       return Join;
-               }
-               if (r->s1 && r->s2) {
-                       j->end = r;
-                       return Split;
-               }
-               j->last = r;
-               if (r->prog->as != ANOP)
-                       j->len++;
-               if (!r->s1 && !r->s2) {
-                       j->end = r->link;
-                       return End;
-               }
-               if (r->s2) {
-                       j->end = r->s2;
-                       return Branch;
-               }
-               if (modifiescpsr(r->prog)) {
-                       j->end = r->s1;
-                       return Setcond;
-               }
-               r = r->s1;
-       } while (j->len < 4);
-       j->end = r;
-       return Toolong;
-}
-
-static Flow*
-successor(Flow *r)
-{
-       if(r->s1)
-               return r->s1;
-       else
-               return r->s2;
-}
-
-static void
-applypred(Flow *rstart, Joininfo *j, int cond, int branch)
-{
-       int pred;
-       Flow *r;
-
-       if(j->len == 0)
-               return;
-       if(cond == Truecond)
-               pred = predinfo[rstart->prog->as - ABEQ].scond;
-       else
-               pred = predinfo[rstart->prog->as - ABEQ].notscond;
-
-       for(r = j->start;; r = successor(r)) {
-               if(r->prog->as == AB) {
-                       if(r != j->last || branch == Delbranch)
-                               excise(r);
-                       else {
-                               if(cond == Truecond)
-                                       r->prog->as = predinfo[rstart->prog->as - ABEQ].opcode;
-                               else
-                                       r->prog->as = predinfo[rstart->prog->as - ABEQ].notopcode;
-                       }
-               }
-               else
-               if(predicable(r->prog))
-                       r->prog->scond = (r->prog->scond&~C_SCOND)|pred;
-               if(r->s1 != r->link) {
-                       r->s1 = r->link;
-                       r->link->p1 = r;
-               }
-               if(r == j->last)
-                       break;
-       }
-}
-
-void
-predicate(Graph *g)
-{
-       Flow *r;
-       int t1, t2;
-       Joininfo j1, j2;
-
-       for(r=g->start; r!=nil; r=r->link) {
-               if (isbranch(r->prog)) {
-                       t1 = joinsplit(r->s1, &j1);
-                       t2 = joinsplit(r->s2, &j2);
-                       if(j1.last->link != j2.start)
-                               continue;
-                       if(j1.end == j2.end)
-                       if((t1 == Branch && (t2 == Join || t2 == Setcond)) ||
-                          (t2 == Join && (t1 == Join || t1 == Setcond))) {
-                               applypred(r, &j1, Falsecond, Delbranch);
-                               applypred(r, &j2, Truecond, Delbranch);
-                               excise(r);
-                               continue;
-                       }
-                       if(t1 == End || t1 == Branch) {
-                               applypred(r, &j1, Falsecond, Keepbranch);
-                               excise(r);
-                               continue;
-                       }
-               }
-       }
-}
-
-static int
-isdconst(Addr *a)
-{
-       return a->type == TYPE_CONST;
-}
-
-static int
-isfloatreg(Addr *a)
-{
-       return REG_F0 <= a->reg && a->reg <= REG_F15;
-}
-
-int
-stackaddr(Addr *a)
-{
-       return regtyp(a) && a->reg == REGSP;
-}
-
-int
-smallindir(Addr *a, Addr *reg)
-{
-       return reg->type == TYPE_REG && a->type == TYPE_MEM &&
-               a->reg == reg->reg &&
-               0 <= a->offset && a->offset < 4096;
-}
-
-void
-excise(Flow *r)
-{
-       Prog *p;
-
-       p = r->prog;
-       nopout(p);
-}
similarity index 100%
rename from src/cmd/new5g/peep.go
rename to src/cmd/5g/peep.go
diff --git a/src/cmd/5g/prog.c b/src/cmd/5g/prog.c
deleted file mode 100644 (file)
index 9d5adef..0000000
+++ /dev/null
@@ -1,160 +0,0 @@
-// Copyright 2013 The Go Authors.  All rights reserved.
-// Use of this source code is governed by a BSD-style
-// license that can be found in the LICENSE file.
-
-#include <u.h>
-#include <libc.h>
-#include "gg.h"
-#include "../gc/popt.h"
-
-enum
-{
-       RightRdwr = RightRead | RightWrite,
-};
-
-// This table gives the basic information about instruction
-// generated by the compiler and processed in the optimizer.
-// See opt.h for bit definitions.
-//
-// Instructions not generated need not be listed.
-// As an exception to that rule, we typically write down all the
-// size variants of an operation even if we just use a subset.
-//
-// The table is formatted for 8-space tabs.
-static ProgInfo progtable[ALAST] = {
-       [ATYPE]=        {Pseudo | Skip},
-       [ATEXT]=        {Pseudo},
-       [AFUNCDATA]=    {Pseudo},
-       [APCDATA]=      {Pseudo},
-       [AUNDEF]=       {Break},
-       [AUSEFIELD]=    {OK},
-       [ACHECKNIL]=    {LeftRead},
-       [AVARDEF]=      {Pseudo | RightWrite},
-       [AVARKILL]=     {Pseudo | RightWrite},
-
-       // NOP is an internal no-op that also stands
-       // for USED and SET annotations, not the Intel opcode.
-       [ANOP]=         {LeftRead | RightWrite},
-       
-       // Integer.
-       [AADC]=         {SizeL | LeftRead | RegRead | RightWrite},
-       [AADD]=         {SizeL | LeftRead | RegRead | RightWrite},
-       [AAND]=         {SizeL | LeftRead | RegRead | RightWrite},
-       [ABIC]=         {SizeL | LeftRead | RegRead | RightWrite},
-       [ACMN]=         {SizeL | LeftRead | RightRead},
-       [ACMP]=         {SizeL | LeftRead | RightRead},
-       [ADIVU]=        {SizeL | LeftRead | RegRead | RightWrite},
-       [ADIV]=         {SizeL | LeftRead | RegRead | RightWrite},
-       [AEOR]=         {SizeL | LeftRead | RegRead | RightWrite},
-       [AMODU]=        {SizeL | LeftRead | RegRead | RightWrite},
-       [AMOD]=         {SizeL | LeftRead | RegRead | RightWrite},
-       [AMULALU]=      {SizeL | LeftRead | RegRead | RightRdwr},
-       [AMULAL]=       {SizeL | LeftRead | RegRead | RightRdwr},
-       [AMULA]=        {SizeL | LeftRead | RegRead | RightRdwr},
-       [AMULU]=        {SizeL | LeftRead | RegRead | RightWrite},
-       [AMUL]=         {SizeL | LeftRead | RegRead | RightWrite},
-       [AMULL]=        {SizeL | LeftRead | RegRead | RightWrite},
-       [AMULLU]=       {SizeL | LeftRead | RegRead | RightWrite},
-       [AMVN]=         {SizeL | LeftRead | RightWrite},
-       [AORR]=         {SizeL | LeftRead | RegRead | RightWrite},
-       [ARSB]=         {SizeL | LeftRead | RegRead | RightWrite},
-       [ARSC]=         {SizeL | LeftRead | RegRead | RightWrite},
-       [ASBC]=         {SizeL | LeftRead | RegRead | RightWrite},
-       [ASLL]=         {SizeL | LeftRead | RegRead | RightWrite},
-       [ASRA]=         {SizeL | LeftRead | RegRead | RightWrite},
-       [ASRL]=         {SizeL | LeftRead | RegRead | RightWrite},
-       [ASUB]=         {SizeL | LeftRead | RegRead | RightWrite},
-       [ATEQ]=         {SizeL | LeftRead | RightRead},
-       [ATST]=         {SizeL | LeftRead | RightRead},
-
-       // Floating point.
-       [AADDD]=        {SizeD | LeftRead | RightRdwr},
-       [AADDF]=        {SizeF | LeftRead | RightRdwr},
-       [ACMPD]=        {SizeD | LeftRead | RightRead},
-       [ACMPF]=        {SizeF | LeftRead | RightRead},
-       [ADIVD]=        {SizeD | LeftRead | RightRdwr},
-       [ADIVF]=        {SizeF | LeftRead | RightRdwr},
-       [AMULD]=        {SizeD | LeftRead | RightRdwr},
-       [AMULF]=        {SizeF | LeftRead | RightRdwr},
-       [ASUBD]=        {SizeD | LeftRead | RightRdwr},
-       [ASUBF]=        {SizeF | LeftRead | RightRdwr},
-
-       // Conversions.
-       [AMOVWD]=               {SizeD | LeftRead | RightWrite | Conv},
-       [AMOVWF]=               {SizeF | LeftRead | RightWrite | Conv},
-       [AMOVDF]=               {SizeF | LeftRead | RightWrite | Conv},
-       [AMOVDW]=               {SizeL | LeftRead | RightWrite | Conv},
-       [AMOVFD]=               {SizeD | LeftRead | RightWrite | Conv},
-       [AMOVFW]=               {SizeL | LeftRead | RightWrite | Conv},
-
-       // Moves.
-       [AMOVB]=                {SizeB | LeftRead | RightWrite | Move},
-       [AMOVD]=                {SizeD | LeftRead | RightWrite | Move},
-       [AMOVF]=                {SizeF | LeftRead | RightWrite | Move},
-       [AMOVH]=                {SizeW | LeftRead | RightWrite | Move},
-       [AMOVW]=                {SizeL | LeftRead | RightWrite | Move},
-       // In addtion, duffzero reads R0,R1 and writes R1.  This fact is
-       // encoded in peep.c
-       [ADUFFZERO]=            {Call},
-       // In addtion, duffcopy reads R1,R2 and writes R0,R1,R2.  This fact is
-       // encoded in peep.c
-       [ADUFFCOPY]=            {Call},
-
-       // These should be split into the two different conversions instead
-       // of overloading the one.
-       [AMOVBS]=               {SizeB | LeftRead | RightWrite | Conv},
-       [AMOVBU]=               {SizeB | LeftRead | RightWrite | Conv},
-       [AMOVHS]=               {SizeW | LeftRead | RightWrite | Conv},
-       [AMOVHU]=               {SizeW | LeftRead | RightWrite | Conv},
-       
-       // Jumps.
-       [AB]=           {Jump | Break},
-       [ABL]=          {Call},
-       [ABEQ]=         {Cjmp},
-       [ABNE]=         {Cjmp},
-       [ABCS]=         {Cjmp},
-       [ABHS]=         {Cjmp},
-       [ABCC]=         {Cjmp},
-       [ABLO]=         {Cjmp},
-       [ABMI]=         {Cjmp},
-       [ABPL]=         {Cjmp},
-       [ABVS]=         {Cjmp},
-       [ABVC]=         {Cjmp},
-       [ABHI]=         {Cjmp},
-       [ABLS]=         {Cjmp},
-       [ABGE]=         {Cjmp},
-       [ABLT]=         {Cjmp},
-       [ABGT]=         {Cjmp},
-       [ABLE]=         {Cjmp},
-       [ARET]=         {Break},
-};
-
-void
-proginfo(ProgInfo *info, Prog *p)
-{
-       *info = progtable[p->as];
-       if(info->flags == 0)
-               fatal("unknown instruction %P", p);
-
-       if(p->from.type == TYPE_ADDR && p->from.sym != nil && (info->flags & LeftRead)) {
-               info->flags &= ~LeftRead;
-               info->flags |= LeftAddr;
-       }
-
-       if((info->flags & RegRead) && p->reg == 0) {
-               info->flags &= ~RegRead;
-               info->flags |= CanRegRead | RightRead;
-       }
-       
-       if(((p->scond & C_SCOND) != C_SCOND_NONE) && (info->flags & RightWrite))
-               info->flags |= RightRead;
-       
-       switch(p->as) {
-       case ADIV:
-       case ADIVU:
-       case AMOD:
-       case AMODU:
-               info->regset |= RtoB(REG_R12);
-               break;
-       }
-}
similarity index 100%
rename from src/cmd/new5g/prog.go
rename to src/cmd/5g/prog.go
diff --git a/src/cmd/5g/reg.c b/src/cmd/5g/reg.c
deleted file mode 100644 (file)
index 1216e01..0000000
+++ /dev/null
@@ -1,146 +0,0 @@
-// Inferno utils/5c/reg.c
-// http://code.google.com/p/inferno-os/source/browse/utils/5c/reg.c
-//
-//     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 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 <u.h>
-#include <libc.h>
-#include "gg.h"
-#include "../gc/popt.h"
-
-enum {
-       NREGVAR = 32,
-};
-
-static char* regname[] = {
-       ".R0",
-       ".R1",
-       ".R2",
-       ".R3",
-       ".R4",
-       ".R5",
-       ".R6",
-       ".R7",
-       ".R8",
-       ".R9",
-       ".R10",
-       ".R11",
-       ".R12",
-       ".R13",
-       ".R14",
-       ".R15",
-       ".F0",
-       ".F1",
-       ".F2",
-       ".F3",
-       ".F4",
-       ".F5",
-       ".F6",
-       ".F7",
-       ".F8",
-       ".F9",
-       ".F10",
-       ".F11",
-       ".F12",
-       ".F13",
-       ".F14",
-       ".F15",
-};
-
-char**
-regnames(int *n)
-{
-       *n = NREGVAR;
-       return regname;
-}
-
-uint64
-excludedregs(void)
-{
-       return RtoB(REGSP)|RtoB(REGLINK)|RtoB(REGPC);
-}
-
-uint64
-doregbits(int r)
-{
-       USED(r);
-       return 0;
-}
-
-/*
- *     bit     reg
- *     0       R0
- *     1       R1
- *     ...     ...
- *     10      R10
- *     12  R12
- *
- *     bit     reg
- *     18      F2
- *     19      F3
- *     ...     ...
- *     31      F15
- */
-uint64
-RtoB(int r)
-{
-       if(REG_R0 <= r && r <= REG_R15) {
-               if(r >= REGTMP-2 && r != REG_R12)       // excluded R9 and R10 for m and g, but not R12
-                       return 0;
-               return 1ULL << (r - REG_R0);
-       }
-       
-       if(REG_F0 <= r && r <= REG_F15) {
-               if(r < REG_F2 || r > REG_F0+NFREG-1)
-                       return 0;
-               return 1ULL << ((r - REG_F0) + 16);
-       }
-       
-       return 0;
-}
-
-int
-BtoR(uint64 b)
-{
-       // TODO Allow R0 and R1, but be careful with a 0 return
-       // TODO Allow R9. Only R10 is reserved now (just g, not m).
-       b &= 0x11fcL;   // excluded R9 and R10 for m and g, but not R12
-       if(b == 0)
-               return 0;
-       return bitno(b) + REG_R0;
-}
-
-int
-BtoF(uint64 b)
-{
-       b &= 0xfffc0000L;
-       if(b == 0)
-               return 0;
-       return bitno(b) - 16 + REG_F0;
-}
similarity index 100%
rename from src/cmd/new5g/reg.go
rename to src/cmd/5g/reg.go
similarity index 100%
rename from src/cmd/new5g/util.go
rename to src/cmd/5g/util.go
diff --git a/src/cmd/6a/Makefile b/src/cmd/6a/Makefile
deleted file mode 100644 (file)
index 27290dd..0000000
+++ /dev/null
@@ -1,10 +0,0 @@
-# Copyright 2012 The Go Authors.  All rights reserved.
-# Use of this source code is governed by a BSD-style
-# license that can be found in the LICENSE file.
-
-include ../../Make.dist
-
-install: y.tab.h
-
-y.tab.h: a.y
-       LANG=C LANGUAGE=en_US.UTF8 bison -d -v -y a.y
diff --git a/src/cmd/6a/a.h b/src/cmd/6a/a.h
deleted file mode 100644 (file)
index 95c4bab..0000000
+++ /dev/null
@@ -1,188 +0,0 @@
-// Inferno utils/6a/a.h
-// http://code.google.com/p/inferno-os/source/browse/utils/6a/a.h
-//
-//     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 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 <bio.h>
-#include <link.h>
-#include "../6l/6.out.h"
-
-#ifndef        EXTERN
-#define        EXTERN  extern
-#endif
-
-#undef getc
-#undef ungetc
-#undef BUFSIZ
-
-#define        getc    ccgetc
-#define        ungetc  ccungetc
-
-typedef        struct  Sym     Sym;
-typedef        struct  Ref     Ref;
-typedef        struct  Io      Io;
-typedef        struct  Addr2   Addr2;
-
-#define        MAXALIGN        7
-#define        FPCHIP          1
-#define        NSYMB           500
-#define        BUFSIZ          8192
-#define        HISTSZ          20
-#ifndef        EOF
-#define        EOF             (-1)
-#endif
-#define        IGN             (-2)
-#define        GETC()          ((--fi.c < 0)? filbuf(): *fi.p++ & 0xff)
-#define        NHASH           503
-#define        STRINGSZ        200
-#define        NMACRO          10
-
-struct Sym
-{
-       Sym*    link;
-       Ref*    ref;
-       char*   macro;
-       vlong   value;
-       ushort  type;
-       char    *name;
-       char*   labelname;
-       char    sym;
-};
-#define        S       ((Sym*)0)
-
-struct Ref
-{
-       int     class;
-};
-
-EXTERN struct
-{
-       char*   p;
-       int     c;
-} fi;
-
-struct Io
-{
-       Io*     link;
-       char    b[BUFSIZ];
-       char*   p;
-       short   c;
-       short   f;
-};
-#define        I       ((Io*)0)
-
-struct Addr2
-{
-       Addr    from;
-       Addr    to;
-};
-
-enum
-{
-       CLAST,
-       CMACARG,
-       CMACRO,
-       CPREPROC,
-};
-
-EXTERN int     debug[256];
-EXTERN Sym*    hash[NHASH];
-EXTERN char**  Dlist;
-EXTERN int     nDlist;
-EXTERN int     newflag;
-EXTERN char*   hunk;
-EXTERN char**  include;
-EXTERN Io*     iofree;
-EXTERN Io*     ionext;
-EXTERN Io*     iostack;
-EXTERN int32   lineno;
-EXTERN int     nerrors;
-EXTERN int32   nhunk;
-EXTERN int     ninclude;
-EXTERN int32   nsymb;
-EXTERN Addr    nullgen;
-EXTERN char*   outfile;
-EXTERN int     pass;
-EXTERN int32   pc;
-EXTERN int     peekc;
-EXTERN int32   stmtline;
-EXTERN int     sym;
-EXTERN char*   symb;
-EXTERN int     thechar;
-EXTERN char*   thestring;
-EXTERN int32   thunk;
-EXTERN Biobuf  obuf;
-EXTERN Link*   ctxt;
-EXTERN Biobuf  bstdout;
-EXTERN Prog*   lastpc;
-
-void*  alloc(int32);
-void*  allocn(void*, int32, int32);
-void   ensuresymb(int32);
-void   errorexit(void);
-void   pushio(void);
-void   newio(void);
-void   newfile(char*, int);
-Sym*   slookup(char*);
-Sym*   lookup(void);
-Sym*   labellookup(Sym*);
-void   settext(LSym*);
-void   syminit(Sym*);
-int32  yylex(void);
-int    getc(void);
-int    getnsc(void);
-void   unget(int);
-int    escchar(int);
-void   cinit(void);
-void   checkscale(int);
-void   pinit(char*);
-void   cclean(void);
-int    isreg(Addr*);
-void   outcode(int, Addr2*);
-void   outhist(void);
-void   zaddr(Addr*, int);
-void   zname(char*, int, int);
-int    filbuf(void);
-Sym*   getsym(void);
-void   domacro(void);
-void   macund(void);
-void   macdef(void);
-void   macexpand(Sym*, char*);
-void   macinc(void);
-void   macprag(void);
-void   maclin(void);
-void   macif(int);
-void   macend(void);
-void   dodefine(char*);
-void   prfile(int32);
-void   linehist(char*, int);
-void   gethunk(void);
-void   yyerror(char*, ...);
-int    yyparse(void);
-void   setinclude(char*);
-int    assemble(char*);
index df3ca40b2c0d27677614540b2461c3ad92befb9d..bd59a1faba4e115a3b4f8a9ff311fe13b1c61302 100644 (file)
 // THE SOFTWARE.
 
 %{
-#include <u.h>
-#include <stdio.h>     /* if we don't, bison will, and a.h re-#defines getc */
-#include <libc.h>
-#include "a.h"
-#include "../../runtime/funcdata.h"
+package main
+
+import (
+       "cmd/internal/asm"
+       "cmd/internal/obj"
+       "cmd/internal/obj/x86"
+)
 %}
-%union {
-       Sym     *sym;
-       vlong   lval;
-       double  dval;
-       char    sval[8];
-       Addr    addr;
-       Addr2   addr2;
+
+%union {
+       sym *asm.Sym
+       lval int64
+       dval float64
+       sval string
+       addr obj.Addr
+       addr2 Addr2
 }
+
 %left  '|'
 %left  '^'
 %left  '&'
@@ -58,7 +62,7 @@
 %token <sval>  LSCONST LSP
 %token <sym>   LNAME LLAB LVAR
 %type  <lval>  con expr pointer offset
-%type  <addr>  mem imm reg nam rel rem rim rom omem nmem textsize
+%type  <addr>  mem imm textsize reg nam rel rem rim rom omem nmem
 %type  <addr2> nonnon nonrel nonrem rimnon rimrem remrim
 %type  <addr2> spec3 spec4 spec5 spec6 spec7 spec8 spec9
 %type  <addr2> spec10 spec12 spec13
 prog:
 |      prog 
        {
-               stmtline = lineno;
+               stmtline = asm.Lineno;
        }
        line
 
 line:
        LNAME ':'
        {
-               $1 = labellookup($1);
-               if($1->type == LLAB && $1->value != pc)
-                       yyerror("redeclaration of %s (%s)", $1->labelname, $1->name);
-               $1->type = LLAB;
-               $1->value = pc;
+               $1 = asm.LabelLookup($1);
+               if $1.Type == LLAB && $1.Value != int64(asm.PC) {
+                       yyerror("redeclaration of %s (%s)", $1.Labelname, $1.Name);
+               }
+               $1.Type = LLAB;
+               $1.Value = int64(asm.PC)
        }
        line
 |      ';'
@@ -87,34 +92,35 @@ line:
 inst:
        LNAME '=' expr
        {
-               $1->type = LVAR;
-               $1->value = $3;
+               $1.Type = LVAR;
+               $1.Value = $3;
        }
 |      LVAR '=' expr
        {
-               if($1->value != $3)
-                       yyerror("redeclaration of %s", $1->name);
-               $1->value = $3;
-       }
-|      LTYPE0 nonnon   { outcode($1, &$2); }
-|      LTYPE1 nonrem   { outcode($1, &$2); }
-|      LTYPE2 rimnon   { outcode($1, &$2); }
-|      LTYPE3 rimrem   { outcode($1, &$2); }
-|      LTYPE4 remrim   { outcode($1, &$2); }
-|      LTYPER nonrel   { outcode($1, &$2); }
+               if $1.Value != $3 {
+                       yyerror("redeclaration of %s", $1.Name);
+               }
+               $1.Value = $3;
+       }
+|      LTYPE0 nonnon   { outcode(int($1), &$2); }
+|      LTYPE1 nonrem   { outcode(int($1), &$2); }
+|      LTYPE2 rimnon   { outcode(int($1), &$2); }
+|      LTYPE3 rimrem   { outcode(int($1), &$2); }
+|      LTYPE4 remrim   { outcode(int($1), &$2); }
+|      LTYPER nonrel   { outcode(int($1), &$2); }
 |      spec1
 |      spec2
-|      LTYPEC spec3    { outcode($1, &$2); }
-|      LTYPEN spec4    { outcode($1, &$2); }
-|      LTYPES spec5    { outcode($1, &$2); }
-|      LTYPEM spec6    { outcode($1, &$2); }
-|      LTYPEI spec7    { outcode($1, &$2); }
-|      LTYPEXC spec8   { outcode($1, &$2); }
-|      LTYPEX spec9    { outcode($1, &$2); }
-|      LTYPERT spec10  { outcode($1, &$2); }
+|      LTYPEC spec3    { outcode(int($1), &$2); }
+|      LTYPEN spec4    { outcode(int($1), &$2); }
+|      LTYPES spec5    { outcode(int($1), &$2); }
+|      LTYPEM spec6    { outcode(int($1), &$2); }
+|      LTYPEI spec7    { outcode(int($1), &$2); }
+|      LTYPEXC spec8   { outcode(int($1), &$2); }
+|      LTYPEX spec9    { outcode(int($1), &$2); }
+|      LTYPERT spec10  { outcode(int($1), &$2); }
 |      spec11
-|      LTYPEPC spec12  { outcode($1, &$2); }
-|      LTYPEF spec13   { outcode($1, &$2); }
+|      LTYPEPC spec12  { outcode(int($1), &$2); }
+|      LTYPEF spec13   { outcode(int($1), &$2); }
 
 nonnon:
        {
@@ -185,57 +191,45 @@ nonrel:
 spec1: /* DATA */
        LTYPED nam '/' con ',' imm
        {
-               Addr2 a;
-               a.from = $2;
-               a.to = $6;
-               outcode(ADATA, &a);
-               if(pass > 1) {
-                       lastpc->from3.type = TYPE_CONST;
-                       lastpc->from3.offset = $4;
+               var a Addr2
+               a.from = $2
+               a.to = $6
+               outcode(obj.ADATA, &a)
+               if asm.Pass > 1 {
+                       lastpc.From3.Type = obj.TYPE_CONST
+                       lastpc.From3.Offset = $4
                }
        }
 
 spec2: /* TEXT */
        LTYPET mem ',' '$' textsize
        {
-               Addr2 a;
-               settext($2.sym);
-               a.from = $2;
-               a.to = $5;
-               outcode(ATEXT, &a);
+               asm.Settext($2.Sym);
+               outcode(obj.ATEXT, &Addr2{$2, $5})
        }
 |      LTYPET mem ',' con ',' '$' textsize
        {
-               Addr2 a;
-               settext($2.sym);
-               a.from = $2;
-               a.to = $7;
-               outcode(ATEXT, &a);
-               if(pass > 1) {
-                       lastpc->from3.type = TYPE_CONST;
-                       lastpc->from3.offset = $4;
+               asm.Settext($2.Sym);
+               outcode(obj.ATEXT, &Addr2{$2, $7})
+               if asm.Pass > 1 {
+                       lastpc.From3.Type = obj.TYPE_CONST
+                       lastpc.From3.Offset = $4
                }
        }
 
 spec11:        /* GLOBL */
        LTYPEG mem ',' imm
        {
-               Addr2 a;
-               settext($2.sym);
-               a.from = $2;
-               a.to = $4;
-               outcode(AGLOBL, &a);
+               asm.Settext($2.Sym)
+               outcode(obj.AGLOBL, &Addr2{$2, $4})
        }
 |      LTYPEG mem ',' con ',' imm
        {
-               Addr2 a;
-               settext($2.sym);
-               a.from = $2;
-               a.to = $6;
-               outcode(AGLOBL, &a);
-               if(pass > 1) {
-                       lastpc->from3.type = TYPE_CONST;
-                       lastpc->from3.offset = $4;
+               asm.Settext($2.Sym)
+               outcode(obj.AGLOBL, &Addr2{$2, $6})
+               if asm.Pass > 1 {
+                       lastpc.From3.Type = obj.TYPE_CONST
+                       lastpc.From3.Offset = $4
                }
        }
 
@@ -265,9 +259,10 @@ spec5:     /* SHL/SHR */
        {
                $$.from = $1;
                $$.to = $3;
-               if($$.from.index != TYPE_NONE)
+               if $$.from.Index != obj.TYPE_NONE {
                        yyerror("dp shift with lhs index");
-               $$.from.index = $5;
+               }
+               $$.from.Index = int16($5);
        }
 
 spec6: /* MOVW/MOVL */
@@ -280,9 +275,10 @@ spec6:     /* MOVW/MOVL */
        {
                $$.from = $1;
                $$.to = $3;
-               if($$.to.index != TYPE_NONE)
+               if $$.to.Index != obj.TYPE_NONE {
                        yyerror("dp move with lhs index");
-               $$.to.index = $5;
+               }
+               $$.to.Index = int16($5);
        }
 
 spec7:
@@ -307,7 +303,7 @@ spec8:      /* CMPPS/CMPPD */
        {
                $$.from = $1;
                $$.to = $3;
-               $$.to.offset = $5;
+               $$.to.Offset = $5;
        }
 
 spec9: /* shufl */
@@ -315,9 +311,10 @@ spec9:     /* shufl */
        {
                $$.from = $3;
                $$.to = $5;
-               if($1.type != TYPE_CONST)
+               if $1.Type != obj.TYPE_CONST {
                        yyerror("illegal constant");
-               $$.to.offset = $1.offset;
+               }
+               $$.to.Offset = $1.Offset;
        }
 
 spec10:        /* RET/RETF */
@@ -331,11 +328,12 @@ spec10:   /* RET/RETF */
                $$.to = nullgen;
        }
 
-spec12:        /* PCDATA */
+spec12:        /* asm.PCDATA */
        rim ',' rim
        {
-               if($1.type != TYPE_CONST || $3.type != TYPE_CONST)
-                       yyerror("arguments to PCDATA must be integer constants");
+               if $1.Type != obj.TYPE_CONST || $3.Type != obj.TYPE_CONST {
+                       yyerror("arguments to asm.PCDATA must be integer constants");
+               }
                $$.from = $1;
                $$.to = $3;
        }
@@ -343,10 +341,12 @@ spec12:   /* PCDATA */
 spec13:        /* FUNCDATA */
        rim ',' rim
        {
-               if($1.type != TYPE_CONST)
+               if $1.Type != obj.TYPE_CONST {
                        yyerror("index for FUNCDATA must be integer constant");
-               if($3.type != TYPE_MEM || ($3.name != NAME_EXTERN && $3.name != NAME_STATIC))
+               }
+               if $3.Type != obj.TYPE_MEM || ($3.Name != obj.NAME_EXTERN && $3.Name != obj.NAME_STATIC) {
                        yyerror("value for FUNCDATA must be symbol reference");
+               }
                $$.from = $1;
                $$.to = $3;
        }
@@ -377,109 +377,110 @@ rel:
        con '(' LPC ')'
        {
                $$ = nullgen;
-               $$.type = TYPE_BRANCH;
-               $$.offset = $1 + pc;
+               $$.Type = obj.TYPE_BRANCH;
+               $$.Offset = $1 + int64(asm.PC);
        }
 |      LNAME offset
        {
-               $1 = labellookup($1);
+               $1 = asm.LabelLookup($1);
                $$ = nullgen;
-               if(pass == 2 && $1->type != LLAB)
-                       yyerror("undefined label: %s", $1->labelname);
-               $$.type = TYPE_BRANCH;
-               $$.offset = $1->value + $2;
+               if asm.Pass == 2 && $1.Type != LLAB {
+                       yyerror("undefined label: %s", $1.Labelname);
+               }
+               $$.Type = obj.TYPE_BRANCH;
+               $$.Offset = $1.Value + $2;
        }
 
 reg:
        LBREG
        {
                $$ = nullgen;
-               $$.type = TYPE_REG;
-               $$.reg = $1;
+               $$.Type = obj.TYPE_REG
+               $$.Reg = int16($1);
        }
 |      LFREG
        {
                $$ = nullgen;
-               $$.type = TYPE_REG;
-               $$.reg = $1;
+               $$.Type = obj.TYPE_REG
+               $$.Reg = int16($1);
        }
 |      LLREG
        {
                $$ = nullgen;
-               $$.type = TYPE_REG;
-               $$.reg = $1;
+               $$.Type = obj.TYPE_REG
+               $$.Reg = int16($1);
        }
 |      LMREG
        {
                $$ = nullgen;
-               $$.type = TYPE_REG;
-               $$.reg = $1;
+               $$.Type = obj.TYPE_REG
+               $$.Reg = int16($1);
        }
 |      LSP
        {
                $$ = nullgen;
-               $$.type = TYPE_REG;
-               $$.reg = REG_SP;
+               $$.Type = obj.TYPE_REG
+               $$.Reg = x86.REG_SP;
        }
 |      LSREG
        {
                $$ = nullgen;
-               $$.type = TYPE_REG;
-               $$.reg = $1;
+               $$.Type = obj.TYPE_REG
+               $$.Reg = int16($1);
        }
 |      LXREG
        {
                $$ = nullgen;
-               $$.type = TYPE_REG;
-               $$.reg = $1;
+               $$.Type = obj.TYPE_REG
+               $$.Reg = int16($1);
        }
 
 imm:
        '$' con
        {
                $$ = nullgen;
-               $$.type = TYPE_CONST;
-               $$.offset = $2;
+               $$.Type = obj.TYPE_CONST;
+               $$.Offset = $2;
        }
 |      '$' nam
        {
                $$ = $2;
-               $$.type = TYPE_ADDR;
+               $$.Type = obj.TYPE_ADDR;
                /*
-               if($2.type == D_AUTO || $2.type == D_PARAM)
+               if($2.Type == x86.D_AUTO || $2.Type == x86.D_PARAM)
                        yyerror("constant cannot be automatic: %s",
-                               $2.sym->name);
+                               $2.sym.Name);
                 */
        }
 |      '$' LSCONST
        {
                $$ = nullgen;
-               $$.type = TYPE_SCONST;
-               memcpy($$.u.sval, $2, sizeof($$.u.sval));
+               $$.Type = obj.TYPE_SCONST;
+               $$.U.Sval = ($2+"\x00\x00\x00\x00\x00\x00\x00\x00")[:8]
        }
 |      '$' LFCONST
        {
                $$ = nullgen;
-               $$.type = TYPE_FCONST;
-               $$.u.dval = $2;
+               $$.Type = obj.TYPE_FCONST;
+               $$.U.Dval = $2;
        }
 |      '$' '(' LFCONST ')'
        {
                $$ = nullgen;
-               $$.type = TYPE_FCONST;
-               $$.u.dval = $3;
+               $$.Type = obj.TYPE_FCONST;
+               $$.U.Dval = $3;
        }
 |      '$' '(' '-' LFCONST ')'
        {
                $$ = nullgen;
-               $$.type = TYPE_FCONST;
-               $$.u.dval = -$4;
+               $$.Type = obj.TYPE_FCONST;
+               $$.U.Dval = -$4;
        }
 |      '$' '-' LFCONST
        {
                $$ = nullgen;
-               $$.type = TYPE_FCONST;
-               $$.u.dval = -$3;
+               $$.Type = obj.TYPE_FCONST;
+               $$.U.Dval = -$3;
        }
 
 mem:
@@ -490,87 +491,87 @@ omem:
        con
        {
                $$ = nullgen;
-               $$.type = TYPE_MEM;
-               $$.offset = $1;
+               $$.Type = obj.TYPE_MEM
+               $$.Offset = $1;
        }
 |      con '(' LLREG ')'
        {
                $$ = nullgen;
-               $$.type = TYPE_MEM;
-               $$.reg = $3;
-               $$.offset = $1;
+               $$.Type = obj.TYPE_MEM
+               $$.Reg = int16($3)
+               $$.Offset = $1;
        }
 |      con '(' LSP ')'
        {
                $$ = nullgen;
-               $$.type = TYPE_MEM;
-               $$.reg = REG_SP;
-               $$.offset = $1;
+               $$.Type = obj.TYPE_MEM
+               $$.Reg = x86.REG_SP
+               $$.Offset = $1;
        }
 |      con '(' LSREG ')'
        {
                $$ = nullgen;
-               $$.type = TYPE_MEM;
-               $$.reg = $3;
-               $$.offset = $1;
+               $$.Type = obj.TYPE_MEM
+               $$.Reg = int16($3)
+               $$.Offset = $1;
        }
 |      con '(' LLREG '*' con ')'
        {
                $$ = nullgen;
-               $$.type = TYPE_MEM;
-               $$.offset = $1;
-               $$.index = $3;
-               $$.scale = $5;
-               checkscale($$.scale);
+               $$.Type = obj.TYPE_MEM
+               $$.Offset = $1;
+               $$.Index = int16($3);
+               $$.Scale = int8($5);
+               checkscale($$.Scale);
        }
 |      con '(' LLREG ')' '(' LLREG '*' con ')'
        {
                $$ = nullgen;
-               $$.type = TYPE_MEM;
-               $$.reg = $3;
-               $$.offset = $1;
-               $$.index = $6;
-               $$.scale = $8;
-               checkscale($$.scale);
+               $$.Type = obj.TYPE_MEM
+               $$.Reg = int16($3)
+               $$.Offset = $1;
+               $$.Index = int16($6);
+               $$.Scale = int8($8);
+               checkscale($$.Scale);
        }
 |      con '(' LLREG ')' '(' LSREG '*' con ')'
        {
                $$ = nullgen;
-               $$.type = TYPE_MEM;
-               $$.reg = $3;
-               $$.offset = $1;
-               $$.index = $6;
-               $$.scale = $8;
-               checkscale($$.scale);
+               $$.Type = obj.TYPE_MEM
+               $$.Reg = int16($3)
+               $$.Offset = $1;
+               $$.Index = int16($6);
+               $$.Scale = int8($8);
+               checkscale($$.Scale);
        }
 |      '(' LLREG ')'
        {
                $$ = nullgen;
-               $$.type = TYPE_MEM;
-               $$.reg = $2;
+               $$.Type = obj.TYPE_MEM
+               $$.Reg = int16($2)
        }
 |      '(' LSP ')'
        {
                $$ = nullgen;
-               $$.type = TYPE_MEM;
-               $$.reg = REG_SP;
+               $$.Type = obj.TYPE_MEM
+               $$.Reg = x86.REG_SP
        }
 |      '(' LLREG '*' con ')'
        {
                $$ = nullgen;
-               $$.type = TYPE_MEM;
-               $$.index = $2;
-               $$.scale = $4;
-               checkscale($$.scale);
+               $$.Type = obj.TYPE_MEM
+               $$.Index = int16($2);
+               $$.Scale = int8($4);
+               checkscale($$.Scale);
        }
 |      '(' LLREG ')' '(' LLREG '*' con ')'
        {
                $$ = nullgen;
-               $$.type = TYPE_MEM;
-               $$.reg = $2;
-               $$.index = $5;
-               $$.scale = $7;
-               checkscale($$.scale);
+               $$.Type = obj.TYPE_MEM
+               $$.Reg = int16($2)
+               $$.Index = int16($5);
+               $$.Scale = int8($7);
+               checkscale($$.Scale);
        }
 
 nmem:
@@ -581,27 +582,27 @@ nmem:
 |      nam '(' LLREG '*' con ')'
        {
                $$ = $1;
-               $$.index = $3;
-               $$.scale = $5;
-               checkscale($$.scale);
+               $$.Index = int16($3);
+               $$.Scale = int8($5);
+               checkscale($$.Scale);
        }
 
 nam:
        LNAME offset '(' pointer ')'
        {
                $$ = nullgen;
-               $$.type = TYPE_MEM;
-               $$.name = $4;
-               $$.sym = linklookup(ctxt, $1->name, 0);
-               $$.offset = $2;
+               $$.Type = obj.TYPE_MEM
+               $$.Name = int8($4)
+               $$.Sym = obj.Linklookup(asm.Ctxt, $1.Name, 0);
+               $$.Offset = $2;
        }
 |      LNAME '<' '>' offset '(' LSB ')'
        {
                $$ = nullgen;
-               $$.type = TYPE_MEM;
-               $$.name = NAME_STATIC;
-               $$.sym = linklookup(ctxt, $1->name, 1);
-               $$.offset = $4;
+               $$.Type = obj.TYPE_MEM
+               $$.Name = obj.NAME_STATIC
+               $$.Sym = obj.Linklookup(asm.Ctxt, $1.Name, 1);
+               $$.Offset = $4;
        }
 
 offset:
@@ -621,7 +622,7 @@ pointer:
        LSB
 |      LSP
        {
-               $$ = NAME_AUTO;
+               $$ = obj.NAME_AUTO;
        }
 |      LFP
 
@@ -629,7 +630,7 @@ con:
        LCONST
 |      LVAR
        {
-               $$ = $1->value;
+               $$ = $1.Value;
        }
 |      '-' con
        {
@@ -641,7 +642,7 @@ con:
        }
 |      '~' con
        {
-               $$ = ~$2;
+               $$ = ^$2;
        }
 |      '(' expr ')'
        {
@@ -652,30 +653,30 @@ textsize:
        LCONST
        {
                $$ = nullgen;
-               $$.type = TYPE_TEXTSIZE;
-               $$.offset = $1;
-               $$.u.argsize = ArgsSizeUnknown;
+               $$.Type = obj.TYPE_TEXTSIZE;
+               $$.Offset = $1;
+               $$.U.Argsize = obj.ArgsSizeUnknown;
        }
 |      '-' LCONST
        {
                $$ = nullgen;
-               $$.type = TYPE_TEXTSIZE;
-               $$.offset = -$2;
-               $$.u.argsize = ArgsSizeUnknown;
+               $$.Type = obj.TYPE_TEXTSIZE;
+               $$.Offset = -$2;
+               $$.U.Argsize = obj.ArgsSizeUnknown;
        }
 |      LCONST '-' LCONST
        {
                $$ = nullgen;
-               $$.type = TYPE_TEXTSIZE;
-               $$.offset = $1;
-               $$.u.argsize = $3;
+               $$.Type = obj.TYPE_TEXTSIZE;
+               $$.Offset = $1;
+               $$.U.Argsize = int32($3);
        }
 |      '-' LCONST '-' LCONST
        {
                $$ = nullgen;
-               $$.type = TYPE_TEXTSIZE;
-               $$.offset = -$2;
-               $$.u.argsize = $4;
+               $$.Type = obj.TYPE_TEXTSIZE;
+               $$.Offset = -$2;
+               $$.U.Argsize = int32($4);
        }
 
 expr:
@@ -702,11 +703,11 @@ expr:
        }
 |      expr '<' '<' expr
        {
-               $$ = $1 << $4;
+               $$ = $1 << uint($4);
        }
 |      expr '>' '>' expr
        {
-               $$ = $1 >> $4;
+               $$ = $1 >> uint($4);
        }
 |      expr '&' expr
        {
diff --git a/src/cmd/6a/doc.go b/src/cmd/6a/doc.go
deleted file mode 100644 (file)
index 9f14cc0..0000000
+++ /dev/null
@@ -1,20 +0,0 @@
-// Copyright 2009 The Go Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style
-// license that can be found in the LICENSE file.
-
-// +build ignore
-
-/*
-
-6a is a version of the Plan 9 assembler.  The original is documented at
-
-       http://plan9.bell-labs.com/magic/man2html/1/8a
-
-Go-specific considerations are documented at
-
-       http://golang.org/doc/asm
-
-Its target architecture is the x86-64, referred to by these tools as amd64.
-
-*/
-package main
diff --git a/src/cmd/6a/lex.c b/src/cmd/6a/lex.c
deleted file mode 100644 (file)
index c600796..0000000
+++ /dev/null
@@ -1,1137 +0,0 @@
-// Inferno utils/6a/lex.c
-// http://code.google.com/p/inferno-os/source/browse/utils/6a/lex.c
-//
-//     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 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.
-
-#define        EXTERN
-#include <u.h>
-#include <libc.h>
-#include "a.h"
-#include "y.tab.h"
-
-enum
-{
-       Plan9   = 1<<0,
-       Unix    = 1<<1,
-       Windows = 1<<2,
-};
-
-int
-systemtype(int sys)
-{
-#ifdef _WIN32
-       return sys&Windows;
-#else
-       return sys&Plan9;
-#endif
-}
-
-int
-pathchar(void)
-{
-       return '/';
-}
-
-int
-Lconv(Fmt *fp)
-{
-       return linklinefmt(ctxt, fp);
-}
-
-void
-dodef(char *p)
-{
-       if(nDlist%8 == 0)
-               Dlist = allocn(Dlist, nDlist*sizeof(char *),
-                       8*sizeof(char *));
-       Dlist[nDlist++] = p;
-}
-
-LinkArch*       thelinkarch = &linkamd64;
-
-void
-usage(void)
-{
-       print("usage: %ca [options] file.c...\n", thechar);
-       flagprint(1);
-       errorexit();
-}
-
-void
-main(int argc, char *argv[])
-{
-       char *p;
-
-       thechar = '6';
-       thestring = "amd64";
-
-       // Allow GOARCH=thestring or GOARCH=thestringsuffix,
-       // but not other values.        
-       p = getgoarch();
-       if(strncmp(p, thestring, strlen(thestring)) != 0)
-               sysfatal("cannot use %cc with GOARCH=%s", thechar, p);
-       if(strcmp(p, "amd64p32") == 0)
-               thelinkarch = &linkamd64p32;
-
-       ctxt = linknew(thelinkarch);
-       ctxt->diag = yyerror;
-       ctxt->bso = &bstdout;
-       ctxt->enforce_data_order = 1;
-       Binit(&bstdout, 1, OWRITE);
-       listinit6();
-       fmtinstall('L', Lconv);
-
-       ensuresymb(NSYMB);
-       memset(debug, 0, sizeof(debug));
-       cinit();
-       outfile = 0;
-       setinclude(".");
-       
-       flagfn1("D", "name[=value]: add #define", dodef);
-       flagfn1("I", "dir: add dir to include path", setinclude);
-       flagcount("S", "print assembly and machine code", &debug['S']);
-       flagcount("m", "debug preprocessor macros", &debug['m']);
-       flagstr("o", "file: set output file", &outfile);
-       flagstr("trimpath", "prefix: remove prefix from recorded source file paths", &ctxt->trimpath);
-
-       flagparse(&argc, &argv, usage);
-       ctxt->debugasm = debug['S'];
-
-       if(argc < 1)
-               usage();
-       if(argc > 1){
-               print("can't assemble multiple files\n");
-               errorexit();
-       }
-
-       if(assemble(argv[0]))
-               errorexit();
-       Bflush(&bstdout);
-       if(nerrors > 0)
-               errorexit();
-       exits(0);
-}
-
-int
-assemble(char *file)
-{
-       char *ofile, *p;
-       int i, of;
-
-       ofile = alloc(strlen(file)+3); // +3 for .x\0 (x=thechar)
-       strcpy(ofile, file);
-       p = utfrrune(ofile, pathchar());
-       if(p) {
-               include[0] = ofile;
-               *p++ = 0;
-       } else
-               p = ofile;
-       if(outfile == 0) {
-               outfile = p;
-               if(outfile){
-                       p = utfrrune(outfile, '.');
-                       if(p)
-                               if(p[1] == 's' && p[2] == 0)
-                                       p[0] = 0;
-                       p = utfrune(outfile, 0);
-                       p[0] = '.';
-                       p[1] = thechar;
-                       p[2] = 0;
-               } else
-                       outfile = "/dev/null";
-       }
-
-       of = create(outfile, OWRITE, 0664);
-       if(of < 0) {
-               yyerror("%ca: cannot create %s", thechar, outfile);
-               errorexit();
-       }
-       Binit(&obuf, of, OWRITE);
-       Bprint(&obuf, "go object %s %s %s\n", getgoos(), getgoarch(), getgoversion());
-       Bprint(&obuf, "!\n");
-
-       for(pass = 1; pass <= 2; pass++) {
-               pinit(file);
-               for(i=0; i<nDlist; i++)
-                       dodefine(Dlist[i]);
-               yyparse();
-               cclean();
-               if(nerrors)
-                       return nerrors;
-       }
-
-       writeobj(ctxt, &obuf);
-       Bflush(&obuf);
-       return 0;
-}
-
-struct
-{
-       char    *name;
-       /*
-        * type is the lexical type to return.  It dictates what kind of
-        * operands 6a allows to follow it (in a.y) as the possible operand
-        * types are handled by a grammar.  How do you know which LTYPE?
-        * Either read a.y or think of an instruction that has the same
-        * possible operands and look up what it takes.
-        */
-       ushort  type;
-       ushort  value;
-} itab[] =
-{
-       "SP",           LSP,    NAME_AUTO,
-       "SB",           LSB,    NAME_EXTERN,
-       "FP",           LFP,    NAME_PARAM,
-
-       "PC",           LPC,    TYPE_BRANCH,
-
-       "AL",           LBREG,  REG_AL,
-       "CL",           LBREG,  REG_CL,
-       "DL",           LBREG,  REG_DL,
-       "BL",           LBREG,  REG_BL,
-/*     "SPB",          LBREG,  REG_SPB,        */
-       "SIB",          LBREG,  REG_SIB,
-       "DIB",          LBREG,  REG_DIB,
-       "BPB",          LBREG,  REG_BPB,
-       "R8B",          LBREG,  REG_R8B,
-       "R9B",          LBREG,  REG_R9B,
-       "R10B",         LBREG,  REG_R10B,
-       "R11B",         LBREG,  REG_R11B,
-       "R12B",         LBREG,  REG_R12B,
-       "R13B",         LBREG,  REG_R13B,
-       "R14B",         LBREG,  REG_R14B,
-       "R15B",         LBREG,  REG_R15B,
-
-       "AH",           LBREG,  REG_AH,
-       "CH",           LBREG,  REG_CH,
-       "DH",           LBREG,  REG_DH,
-       "BH",           LBREG,  REG_BH,
-
-       "AX",           LLREG,  REG_AX,
-       "CX",           LLREG,  REG_CX,
-       "DX",           LLREG,  REG_DX,
-       "BX",           LLREG,  REG_BX,
-/*     "SP",           LLREG,  REG_SP, */
-       "BP",           LLREG,  REG_BP,
-       "SI",           LLREG,  REG_SI,
-       "DI",           LLREG,  REG_DI,
-       "R8",           LLREG,  REG_R8,
-       "R9",           LLREG,  REG_R9,
-       "R10",          LLREG,  REG_R10,
-       "R11",          LLREG,  REG_R11,
-       "R12",          LLREG,  REG_R12,
-       "R13",          LLREG,  REG_R13,
-       "R14",          LLREG,  REG_R14,
-       "R15",          LLREG,  REG_R15,
-
-       "RARG",         LLREG,  REGARG,
-
-       "F0",           LFREG,  REG_F0+0,
-       "F1",           LFREG,  REG_F0+1,
-       "F2",           LFREG,  REG_F0+2,
-       "F3",           LFREG,  REG_F0+3,
-       "F4",           LFREG,  REG_F0+4,
-       "F5",           LFREG,  REG_F0+5,
-       "F6",           LFREG,  REG_F0+6,
-       "F7",           LFREG,  REG_F0+7,
-
-       "M0",           LMREG,  REG_M0+0,
-       "M1",           LMREG,  REG_M0+1,
-       "M2",           LMREG,  REG_M0+2,
-       "M3",           LMREG,  REG_M0+3,
-       "M4",           LMREG,  REG_M0+4,
-       "M5",           LMREG,  REG_M0+5,
-       "M6",           LMREG,  REG_M0+6,
-       "M7",           LMREG,  REG_M0+7,
-
-       "X0",           LXREG,  REG_X0+0,
-       "X1",           LXREG,  REG_X0+1,
-       "X2",           LXREG,  REG_X0+2,
-       "X3",           LXREG,  REG_X0+3,
-       "X4",           LXREG,  REG_X0+4,
-       "X5",           LXREG,  REG_X0+5,
-       "X6",           LXREG,  REG_X0+6,
-       "X7",           LXREG,  REG_X0+7,
-       "X8",           LXREG,  REG_X0+8,
-       "X9",           LXREG,  REG_X0+9,
-       "X10",          LXREG,  REG_X0+10,
-       "X11",          LXREG,  REG_X0+11,
-       "X12",          LXREG,  REG_X0+12,
-       "X13",          LXREG,  REG_X0+13,
-       "X14",          LXREG,  REG_X0+14,
-       "X15",          LXREG,  REG_X0+15,
-
-       "CS",           LSREG,  REG_CS,
-       "SS",           LSREG,  REG_SS,
-       "DS",           LSREG,  REG_DS,
-       "ES",           LSREG,  REG_ES,
-       "FS",           LSREG,  REG_FS,
-       "GS",           LSREG,  REG_GS,
-
-       "GDTR",         LBREG,  REG_GDTR,
-       "IDTR",         LBREG,  REG_IDTR,
-       "LDTR",         LBREG,  REG_LDTR,
-       "MSW",          LBREG,  REG_MSW,
-       "TASK",         LBREG,  REG_TASK,
-
-       "CR0",          LBREG,  REG_CR+0,
-       "CR1",          LBREG,  REG_CR+1,
-       "CR2",          LBREG,  REG_CR+2,
-       "CR3",          LBREG,  REG_CR+3,
-       "CR4",          LBREG,  REG_CR+4,
-       "CR5",          LBREG,  REG_CR+5,
-       "CR6",          LBREG,  REG_CR+6,
-       "CR7",          LBREG,  REG_CR+7,
-       "CR8",          LBREG,  REG_CR+8,
-       "CR9",          LBREG,  REG_CR+9,
-       "CR10",         LBREG,  REG_CR+10,
-       "CR11",         LBREG,  REG_CR+11,
-       "CR12",         LBREG,  REG_CR+12,
-       "CR13",         LBREG,  REG_CR+13,
-       "CR14",         LBREG,  REG_CR+14,
-       "CR15",         LBREG,  REG_CR+15,
-
-       "DR0",          LBREG,  REG_DR+0,
-       "DR1",          LBREG,  REG_DR+1,
-       "DR2",          LBREG,  REG_DR+2,
-       "DR3",          LBREG,  REG_DR+3,
-       "DR4",          LBREG,  REG_DR+4,
-       "DR5",          LBREG,  REG_DR+5,
-       "DR6",          LBREG,  REG_DR+6,
-       "DR7",          LBREG,  REG_DR+7,
-
-       "TR0",          LBREG,  REG_TR+0,
-       "TR1",          LBREG,  REG_TR+1,
-       "TR2",          LBREG,  REG_TR+2,
-       "TR3",          LBREG,  REG_TR+3,
-       "TR4",          LBREG,  REG_TR+4,
-       "TR5",          LBREG,  REG_TR+5,
-       "TR6",          LBREG,  REG_TR+6,
-       "TR7",          LBREG,  REG_TR+7,
-       "TLS",          LSREG,  REG_TLS,
-
-       "AAA",          LTYPE0, AAAA,
-       "AAD",          LTYPE0, AAAD,
-       "AAM",          LTYPE0, AAAM,
-       "AAS",          LTYPE0, AAAS,
-       "ADCB",         LTYPE3, AADCB,
-       "ADCL",         LTYPE3, AADCL,
-       "ADCQ",         LTYPE3, AADCQ,
-       "ADCW",         LTYPE3, AADCW,
-       "ADDB",         LTYPE3, AADDB,
-       "ADDL",         LTYPE3, AADDL,
-       "ADDQ",         LTYPE3, AADDQ,
-       "ADDW",         LTYPE3, AADDW,
-       "ADJSP",        LTYPE2, AADJSP,
-       "ANDB",         LTYPE3, AANDB,
-       "ANDL",         LTYPE3, AANDL,
-       "ANDQ",         LTYPE3, AANDQ,
-       "ANDW",         LTYPE3, AANDW,
-       "ARPL",         LTYPE3, AARPL,
-       "BOUNDL",       LTYPE3, ABOUNDL,
-       "BOUNDW",       LTYPE3, ABOUNDW,
-       "BSFL",         LTYPE3, ABSFL,
-       "BSFQ",         LTYPE3, ABSFQ,
-       "BSFW",         LTYPE3, ABSFW,
-       "BSRL",         LTYPE3, ABSRL,
-       "BSRQ",         LTYPE3, ABSRQ,
-       "BSRW",         LTYPE3, ABSRW,
-       "BSWAPL",       LTYPE1, ABSWAPL,
-       "BSWAPQ",       LTYPE1, ABSWAPQ,
-       "BTCL",         LTYPE3, ABTCL,
-       "BTCQ",         LTYPE3, ABTCQ,
-       "BTCW",         LTYPE3, ABTCW,
-       "BTL",          LTYPE3, ABTL,
-       "BTQ",          LTYPE3, ABTQ,
-       "BTRL",         LTYPE3, ABTRL,
-       "BTRQ",         LTYPE3, ABTRQ,
-       "BTRW",         LTYPE3, ABTRW,
-       "BTSL",         LTYPE3, ABTSL,
-       "BTSQ",         LTYPE3, ABTSQ,
-       "BTSW",         LTYPE3, ABTSW,
-       "BTW",          LTYPE3, ABTW,
-       "BYTE",         LTYPE2, ABYTE,
-       "CALL",         LTYPEC, ACALL,
-       "CLC",          LTYPE0, ACLC,
-       "CLD",          LTYPE0, ACLD,
-       "CLI",          LTYPE0, ACLI,
-       "CLTS",         LTYPE0, ACLTS,
-       "CMC",          LTYPE0, ACMC,
-       "CMPB",         LTYPE4, ACMPB,
-       "CMPL",         LTYPE4, ACMPL,
-       "CMPQ",         LTYPE4, ACMPQ,
-       "CMPW",         LTYPE4, ACMPW,
-       "CMPSB",        LTYPE0, ACMPSB,
-       "CMPSL",        LTYPE0, ACMPSL,
-       "CMPSQ",        LTYPE0, ACMPSQ,
-       "CMPSW",        LTYPE0, ACMPSW,
-       "CMPXCHG8B",    LTYPE1, ACMPXCHG8B,
-       "CMPXCHGB",     LTYPE3, ACMPXCHGB,      /* LTYPE3? */
-       "CMPXCHGL",     LTYPE3, ACMPXCHGL,
-       "CMPXCHGQ",     LTYPE3, ACMPXCHGQ,
-       "CMPXCHGW",     LTYPE3, ACMPXCHGW,
-       "CPUID",        LTYPE0, ACPUID,
-       "DAA",          LTYPE0, ADAA,
-       "DAS",          LTYPE0, ADAS,
-       "DATA",         LTYPED, ADATA,
-       "DECB",         LTYPE1, ADECB,
-       "DECL",         LTYPE1, ADECL,
-       "DECQ",         LTYPE1, ADECQ,
-       "DECW",         LTYPE1, ADECW,
-       "DIVB",         LTYPE2, ADIVB,
-       "DIVL",         LTYPE2, ADIVL,
-       "DIVQ",         LTYPE2, ADIVQ,
-       "DIVW",         LTYPE2, ADIVW,
-       "EMMS",         LTYPE0, AEMMS,
-       "END",          LTYPE0, AEND,
-       "ENTER",        LTYPE2, AENTER,
-       "GLOBL",        LTYPEG, AGLOBL,
-       "HLT",          LTYPE0, AHLT,
-       "IDIVB",        LTYPE2, AIDIVB,
-       "IDIVL",        LTYPE2, AIDIVL,
-       "IDIVQ",        LTYPE2, AIDIVQ,
-       "IDIVW",        LTYPE2, AIDIVW,
-       "IMULB",        LTYPEI, AIMULB,
-       "IMULL",        LTYPEI, AIMULL,
-       "IMULQ",        LTYPEI, AIMULQ,
-       "IMUL3Q",       LTYPEX, AIMUL3Q,
-       "IMULW",        LTYPEI, AIMULW,
-       "INB",          LTYPE0, AINB,
-       "INL",          LTYPE0, AINL,
-       "INW",          LTYPE0, AINW,
-       "INCB",         LTYPE1, AINCB,
-       "INCL",         LTYPE1, AINCL,
-       "INCQ",         LTYPE1, AINCQ,
-       "INCW",         LTYPE1, AINCW,
-       "INSB",         LTYPE0, AINSB,
-       "INSL",         LTYPE0, AINSL,
-       "INSW",         LTYPE0, AINSW,
-       "INT",          LTYPE2, AINT,
-       "INTO",         LTYPE0, AINTO,
-       "INVD",         LTYPE0, AINVD,
-       "INVLPG",       LTYPE2, AINVLPG,
-       "IRETL",        LTYPE0, AIRETL,
-       "IRETQ",        LTYPE0, AIRETQ,
-       "IRETW",        LTYPE0, AIRETW,
-
-       "JOS",          LTYPER, AJOS,   /* overflow set (OF = 1) */
-       "JO",           LTYPER, AJOS,   /* alternate */
-       "JOC",          LTYPER, AJOC,   /* overflow clear (OF = 0) */
-       "JNO",          LTYPER, AJOC,   /* alternate */
-       "JCS",          LTYPER, AJCS,   /* carry set (CF = 1) */
-       "JB",           LTYPER, AJCS,   /* alternate */
-       "JC",           LTYPER, AJCS,   /* alternate */
-       "JNAE",         LTYPER, AJCS,   /* alternate */
-       "JLO",          LTYPER, AJCS,   /* alternate */
-       "JCC",          LTYPER, AJCC,   /* carry clear (CF = 0) */
-       "JAE",          LTYPER, AJCC,   /* alternate */
-       "JNB",          LTYPER, AJCC,   /* alternate */
-       "JNC",          LTYPER, AJCC,   /* alternate */
-       "JHS",          LTYPER, AJCC,   /* alternate */
-       "JEQ",          LTYPER, AJEQ,   /* equal (ZF = 1) */
-       "JE",           LTYPER, AJEQ,   /* alternate */
-       "JZ",           LTYPER, AJEQ,   /* alternate */
-       "JNE",          LTYPER, AJNE,   /* not equal (ZF = 0) */
-       "JNZ",          LTYPER, AJNE,   /* alternate */
-       "JLS",          LTYPER, AJLS,   /* lower or same (unsigned) (CF = 1 || ZF = 1) */
-       "JBE",          LTYPER, AJLS,   /* alternate */
-       "JNA",          LTYPER, AJLS,   /* alternate */
-       "JHI",          LTYPER, AJHI,   /* higher (unsigned) (CF = 0 && ZF = 0) */
-       "JA",           LTYPER, AJHI,   /* alternate */
-       "JNBE",         LTYPER, AJHI,   /* alternate */
-       "JMI",          LTYPER, AJMI,   /* negative (minus) (SF = 1) */
-       "JS",           LTYPER, AJMI,   /* alternate */
-       "JPL",          LTYPER, AJPL,   /* non-negative (plus) (SF = 0) */
-       "JNS",          LTYPER, AJPL,   /* alternate */
-       "JPS",          LTYPER, AJPS,   /* parity set (PF = 1) */
-       "JP",           LTYPER, AJPS,   /* alternate */
-       "JPE",          LTYPER, AJPS,   /* alternate */
-       "JPC",          LTYPER, AJPC,   /* parity clear (PF = 0) */
-       "JNP",          LTYPER, AJPC,   /* alternate */
-       "JPO",          LTYPER, AJPC,   /* alternate */
-       "JLT",          LTYPER, AJLT,   /* less than (signed) (SF != OF) */
-       "JL",           LTYPER, AJLT,   /* alternate */
-       "JNGE",         LTYPER, AJLT,   /* alternate */
-       "JGE",          LTYPER, AJGE,   /* greater than or equal (signed) (SF = OF) */
-       "JNL",          LTYPER, AJGE,   /* alternate */
-       "JLE",          LTYPER, AJLE,   /* less than or equal (signed) (ZF = 1 || SF != OF) */
-       "JNG",          LTYPER, AJLE,   /* alternate */
-       "JGT",          LTYPER, AJGT,   /* greater than (signed) (ZF = 0 && SF = OF) */
-       "JG",           LTYPER, AJGT,   /* alternate */
-       "JNLE",         LTYPER, AJGT,   /* alternate */
-       "JCXZL",        LTYPER, AJCXZL,
-       "JCXZQ",        LTYPER, AJCXZQ,
-       "JMP",          LTYPEC, AJMP,
-       "LAHF",         LTYPE0, ALAHF,
-       "LARL",         LTYPE3, ALARL,
-       "LARW",         LTYPE3, ALARW,
-       "LEAL",         LTYPE3, ALEAL,
-       "LEAQ",         LTYPE3, ALEAQ,
-       "LEAW",         LTYPE3, ALEAW,
-       "LEAVEL",       LTYPE0, ALEAVEL,
-       "LEAVEQ",       LTYPE0, ALEAVEQ,
-       "LEAVEW",       LTYPE0, ALEAVEW,
-       "LFENCE",       LTYPE0, ALFENCE,
-       "LOCK",         LTYPE0, ALOCK,
-       "LODSB",        LTYPE0, ALODSB,
-       "LODSL",        LTYPE0, ALODSL,
-       "LODSQ",        LTYPE0, ALODSQ,
-       "LODSW",        LTYPE0, ALODSW,
-       "LONG",         LTYPE2, ALONG,
-       "LOOP",         LTYPER, ALOOP,
-       "LOOPEQ",       LTYPER, ALOOPEQ,
-       "LOOPNE",       LTYPER, ALOOPNE,
-       "LSLL",         LTYPE3, ALSLL,
-       "LSLW",         LTYPE3, ALSLW,
-       "MFENCE",       LTYPE0, AMFENCE,
-       "MODE",         LTYPE2, AMODE,
-       "MOVB",         LTYPE3, AMOVB,
-       "MOVL",         LTYPEM, AMOVL,
-       "MOVQ",         LTYPEM, AMOVQ,
-       "MOVW",         LTYPEM, AMOVW,
-       "MOVBLSX",      LTYPE3, AMOVBLSX,
-       "MOVBLZX",      LTYPE3, AMOVBLZX,
-       "MOVBQSX",      LTYPE3, AMOVBQSX,
-       "MOVBQZX",      LTYPE3, AMOVBQZX,
-       "MOVBWSX",      LTYPE3, AMOVBWSX,
-       "MOVBWZX",      LTYPE3, AMOVBWZX,
-       "MOVLQSX",      LTYPE3, AMOVLQSX,
-       "MOVLQZX",      LTYPE3, AMOVLQZX,
-       "MOVNTIL",      LTYPE3, AMOVNTIL,
-       "MOVNTIQ",      LTYPE3, AMOVNTIQ,
-       "MOVQL",        LTYPE3, AMOVQL,
-       "MOVWLSX",      LTYPE3, AMOVWLSX,
-       "MOVWLZX",      LTYPE3, AMOVWLZX,
-       "MOVWQSX",      LTYPE3, AMOVWQSX,
-       "MOVWQZX",      LTYPE3, AMOVWQZX,
-       "MOVSB",        LTYPE0, AMOVSB,
-       "MOVSL",        LTYPE0, AMOVSL,
-       "MOVSQ",        LTYPE0, AMOVSQ,
-       "MOVSW",        LTYPE0, AMOVSW,
-       "MULB",         LTYPE2, AMULB,
-       "MULL",         LTYPE2, AMULL,
-       "MULQ",         LTYPE2, AMULQ,
-       "MULW",         LTYPE2, AMULW,
-       "NEGB",         LTYPE1, ANEGB,
-       "NEGL",         LTYPE1, ANEGL,
-       "NEGQ",         LTYPE1, ANEGQ,
-       "NEGW",         LTYPE1, ANEGW,
-       "NOP",          LTYPEN, ANOP,
-       "NOTB",         LTYPE1, ANOTB,
-       "NOTL",         LTYPE1, ANOTL,
-       "NOTQ",         LTYPE1, ANOTQ,
-       "NOTW",         LTYPE1, ANOTW,
-       "ORB",          LTYPE3, AORB,
-       "ORL",          LTYPE3, AORL,
-       "ORQ",          LTYPE3, AORQ,
-       "ORW",          LTYPE3, AORW,
-       "OUTB",         LTYPE0, AOUTB,
-       "OUTL",         LTYPE0, AOUTL,
-       "OUTW",         LTYPE0, AOUTW,
-       "OUTSB",        LTYPE0, AOUTSB,
-       "OUTSL",        LTYPE0, AOUTSL,
-       "OUTSW",        LTYPE0, AOUTSW,
-       "PAUSE",        LTYPEN, APAUSE,
-       "POPAL",        LTYPE0, APOPAL,
-       "POPAW",        LTYPE0, APOPAW,
-       "POPFL",        LTYPE0, APOPFL,
-       "POPFQ",        LTYPE0, APOPFQ,
-       "POPFW",        LTYPE0, APOPFW,
-       "POPL",         LTYPE1, APOPL,
-       "POPQ",         LTYPE1, APOPQ,
-       "POPW",         LTYPE1, APOPW,
-       "PUSHAL",       LTYPE0, APUSHAL,
-       "PUSHAW",       LTYPE0, APUSHAW,
-       "PUSHFL",       LTYPE0, APUSHFL,
-       "PUSHFQ",       LTYPE0, APUSHFQ,
-       "PUSHFW",       LTYPE0, APUSHFW,
-       "PUSHL",        LTYPE2, APUSHL,
-       "PUSHQ",        LTYPE2, APUSHQ,
-       "PUSHW",        LTYPE2, APUSHW,
-       "RCLB",         LTYPE3, ARCLB,
-       "RCLL",         LTYPE3, ARCLL,
-       "RCLQ",         LTYPE3, ARCLQ,
-       "RCLW",         LTYPE3, ARCLW,
-       "RCRB",         LTYPE3, ARCRB,
-       "RCRL",         LTYPE3, ARCRL,
-       "RCRQ",         LTYPE3, ARCRQ,
-       "RCRW",         LTYPE3, ARCRW,
-       "RDMSR",        LTYPE0, ARDMSR,
-       "RDPMC",        LTYPE0, ARDPMC,
-       "RDTSC",        LTYPE0, ARDTSC,
-       "REP",          LTYPE0, AREP,
-       "REPN",         LTYPE0, AREPN,
-       "RET",          LTYPE0, ARET,
-       "RETFL",        LTYPERT,ARETFL,
-       "RETFW",        LTYPERT,ARETFW,
-       "RETFQ",        LTYPERT,ARETFQ,
-       "ROLB",         LTYPE3, AROLB,
-       "ROLL",         LTYPE3, AROLL,
-       "ROLQ",         LTYPE3, AROLQ,
-       "ROLW",         LTYPE3, AROLW,
-       "RORB",         LTYPE3, ARORB,
-       "RORL",         LTYPE3, ARORL,
-       "RORQ",         LTYPE3, ARORQ,
-       "RORW",         LTYPE3, ARORW,
-       "RSM",          LTYPE0, ARSM,
-       "SAHF",         LTYPE0, ASAHF,
-       "SALB",         LTYPE3, ASALB,
-       "SALL",         LTYPE3, ASALL,
-       "SALQ",         LTYPE3, ASALQ,
-       "SALW",         LTYPE3, ASALW,
-       "SARB",         LTYPE3, ASARB,
-       "SARL",         LTYPE3, ASARL,
-       "SARQ",         LTYPE3, ASARQ,
-       "SARW",         LTYPE3, ASARW,
-       "SBBB",         LTYPE3, ASBBB,
-       "SBBL",         LTYPE3, ASBBL,
-       "SBBQ",         LTYPE3, ASBBQ,
-       "SBBW",         LTYPE3, ASBBW,
-       "SCASB",        LTYPE0, ASCASB,
-       "SCASL",        LTYPE0, ASCASL,
-       "SCASQ",        LTYPE0, ASCASQ,
-       "SCASW",        LTYPE0, ASCASW,
-       "SETCC",        LTYPE1, ASETCC, /* see JCC etc above for condition codes */
-       "SETCS",        LTYPE1, ASETCS,
-       "SETEQ",        LTYPE1, ASETEQ,
-       "SETGE",        LTYPE1, ASETGE,
-       "SETGT",        LTYPE1, ASETGT,
-       "SETHI",        LTYPE1, ASETHI,
-       "SETLE",        LTYPE1, ASETLE,
-       "SETLS",        LTYPE1, ASETLS,
-       "SETLT",        LTYPE1, ASETLT,
-       "SETMI",        LTYPE1, ASETMI,
-       "SETNE",        LTYPE1, ASETNE,
-       "SETOC",        LTYPE1, ASETOC,
-       "SETOS",        LTYPE1, ASETOS,
-       "SETPC",        LTYPE1, ASETPC,
-       "SETPL",        LTYPE1, ASETPL,
-       "SETPS",        LTYPE1, ASETPS,
-       "SFENCE",       LTYPE0, ASFENCE,
-       "CDQ",          LTYPE0, ACDQ,
-       "CWD",          LTYPE0, ACWD,
-       "CQO",          LTYPE0, ACQO,
-       "SHLB",         LTYPE3, ASHLB,
-       "SHLL",         LTYPES, ASHLL,
-       "SHLQ",         LTYPES, ASHLQ,
-       "SHLW",         LTYPES, ASHLW,
-       "SHRB",         LTYPE3, ASHRB,
-       "SHRL",         LTYPES, ASHRL,
-       "SHRQ",         LTYPES, ASHRQ,
-       "SHRW",         LTYPES, ASHRW,
-       "STC",          LTYPE0, ASTC,
-       "STD",          LTYPE0, ASTD,
-       "STI",          LTYPE0, ASTI,
-       "STOSB",        LTYPE0, ASTOSB,
-       "STOSL",        LTYPE0, ASTOSL,
-       "STOSQ",        LTYPE0, ASTOSQ,
-       "STOSW",        LTYPE0, ASTOSW,
-       "SUBB",         LTYPE3, ASUBB,
-       "SUBL",         LTYPE3, ASUBL,
-       "SUBQ",         LTYPE3, ASUBQ,
-       "SUBW",         LTYPE3, ASUBW,
-       "SYSCALL",      LTYPE0, ASYSCALL,
-       "SYSRET",       LTYPE0, ASYSRET,
-       "SWAPGS",       LTYPE0, ASWAPGS,
-       "TESTB",        LTYPE3, ATESTB,
-       "TESTL",        LTYPE3, ATESTL,
-       "TESTQ",        LTYPE3, ATESTQ,
-       "TESTW",        LTYPE3, ATESTW,
-       "TEXT",         LTYPET, ATEXT,
-       "VERR",         LTYPE2, AVERR,
-       "VERW",         LTYPE2, AVERW,
-       "QUAD",         LTYPE2, AQUAD,
-       "WAIT",         LTYPE0, AWAIT,
-       "WBINVD",       LTYPE0, AWBINVD,
-       "WRMSR",        LTYPE0, AWRMSR,
-       "WORD",         LTYPE2, AWORD,
-       "XADDB",        LTYPE3, AXADDB,
-       "XADDL",        LTYPE3, AXADDL,
-       "XADDQ",        LTYPE3, AXADDQ,
-       "XADDW",        LTYPE3, AXADDW,
-       "XCHGB",        LTYPE3, AXCHGB,
-       "XCHGL",        LTYPE3, AXCHGL,
-       "XCHGQ",        LTYPE3, AXCHGQ,
-       "XCHGW",        LTYPE3, AXCHGW,
-       "XLAT",         LTYPE2, AXLAT,
-       "XORB",         LTYPE3, AXORB,
-       "XORL",         LTYPE3, AXORL,
-       "XORQ",         LTYPE3, AXORQ,
-       "XORW",         LTYPE3, AXORW,
-
-       "CMOVLCC",      LTYPE3, ACMOVLCC,
-       "CMOVLCS",      LTYPE3, ACMOVLCS,
-       "CMOVLEQ",      LTYPE3, ACMOVLEQ,
-       "CMOVLGE",      LTYPE3, ACMOVLGE,
-       "CMOVLGT",      LTYPE3, ACMOVLGT,
-       "CMOVLHI",      LTYPE3, ACMOVLHI,
-       "CMOVLLE",      LTYPE3, ACMOVLLE,
-       "CMOVLLS",      LTYPE3, ACMOVLLS,
-       "CMOVLLT",      LTYPE3, ACMOVLLT,
-       "CMOVLMI",      LTYPE3, ACMOVLMI,
-       "CMOVLNE",      LTYPE3, ACMOVLNE,
-       "CMOVLOC",      LTYPE3, ACMOVLOC,
-       "CMOVLOS",      LTYPE3, ACMOVLOS,
-       "CMOVLPC",      LTYPE3, ACMOVLPC,
-       "CMOVLPL",      LTYPE3, ACMOVLPL,
-       "CMOVLPS",      LTYPE3, ACMOVLPS,
-       "CMOVQCC",      LTYPE3, ACMOVQCC,
-       "CMOVQCS",      LTYPE3, ACMOVQCS,
-       "CMOVQEQ",      LTYPE3, ACMOVQEQ,
-       "CMOVQGE",      LTYPE3, ACMOVQGE,
-       "CMOVQGT",      LTYPE3, ACMOVQGT,
-       "CMOVQHI",      LTYPE3, ACMOVQHI,
-       "CMOVQLE",      LTYPE3, ACMOVQLE,
-       "CMOVQLS",      LTYPE3, ACMOVQLS,
-       "CMOVQLT",      LTYPE3, ACMOVQLT,
-       "CMOVQMI",      LTYPE3, ACMOVQMI,
-       "CMOVQNE",      LTYPE3, ACMOVQNE,
-       "CMOVQOC",      LTYPE3, ACMOVQOC,
-       "CMOVQOS",      LTYPE3, ACMOVQOS,
-       "CMOVQPC",      LTYPE3, ACMOVQPC,
-       "CMOVQPL",      LTYPE3, ACMOVQPL,
-       "CMOVQPS",      LTYPE3, ACMOVQPS,
-       "CMOVWCC",      LTYPE3, ACMOVWCC,
-       "CMOVWCS",      LTYPE3, ACMOVWCS,
-       "CMOVWEQ",      LTYPE3, ACMOVWEQ,
-       "CMOVWGE",      LTYPE3, ACMOVWGE,
-       "CMOVWGT",      LTYPE3, ACMOVWGT,
-       "CMOVWHI",      LTYPE3, ACMOVWHI,
-       "CMOVWLE",      LTYPE3, ACMOVWLE,
-       "CMOVWLS",      LTYPE3, ACMOVWLS,
-       "CMOVWLT",      LTYPE3, ACMOVWLT,
-       "CMOVWMI",      LTYPE3, ACMOVWMI,
-       "CMOVWNE",      LTYPE3, ACMOVWNE,
-       "CMOVWOC",      LTYPE3, ACMOVWOC,
-       "CMOVWOS",      LTYPE3, ACMOVWOS,
-       "CMOVWPC",      LTYPE3, ACMOVWPC,
-       "CMOVWPL",      LTYPE3, ACMOVWPL,
-       "CMOVWPS",      LTYPE3, ACMOVWPS,
-
-       "FMOVB",        LTYPE3, AFMOVB,
-       "FMOVBP",       LTYPE3, AFMOVBP,
-       "FMOVD",        LTYPE3, AFMOVD,
-       "FMOVDP",       LTYPE3, AFMOVDP,
-       "FMOVF",        LTYPE3, AFMOVF,
-       "FMOVFP",       LTYPE3, AFMOVFP,
-       "FMOVL",        LTYPE3, AFMOVL,
-       "FMOVLP",       LTYPE3, AFMOVLP,
-       "FMOVV",        LTYPE3, AFMOVV,
-       "FMOVVP",       LTYPE3, AFMOVVP,
-       "FMOVW",        LTYPE3, AFMOVW,
-       "FMOVWP",       LTYPE3, AFMOVWP,
-       "FMOVX",        LTYPE3, AFMOVX,
-       "FMOVXP",       LTYPE3, AFMOVXP,
-       "FCOMB",        LTYPE3, AFCOMB,
-       "FCOMBP",       LTYPE3, AFCOMBP,
-       "FCOMD",        LTYPE3, AFCOMD,
-       "FCOMDP",       LTYPE3, AFCOMDP,
-       "FCOMDPP",      LTYPE3, AFCOMDPP,
-       "FCOMF",        LTYPE3, AFCOMF,
-       "FCOMFP",       LTYPE3, AFCOMFP,
-       "FCOML",        LTYPE3, AFCOML,
-       "FCOMLP",       LTYPE3, AFCOMLP,
-       "FCOMW",        LTYPE3, AFCOMW,
-       "FCOMWP",       LTYPE3, AFCOMWP,
-       "FUCOM",        LTYPE3, AFUCOM,
-       "FUCOMP",       LTYPE3, AFUCOMP,
-       "FUCOMPP",      LTYPE3, AFUCOMPP,
-       "FADDW",        LTYPE3, AFADDW,
-       "FADDL",        LTYPE3, AFADDL,
-       "FADDF",        LTYPE3, AFADDF,
-       "FADDD",        LTYPE3, AFADDD,
-       "FADDDP",       LTYPE3, AFADDDP,
-       "FSUBDP",       LTYPE3, AFSUBDP,
-       "FSUBW",        LTYPE3, AFSUBW,
-       "FSUBL",        LTYPE3, AFSUBL,
-       "FSUBF",        LTYPE3, AFSUBF,
-       "FSUBD",        LTYPE3, AFSUBD,
-       "FSUBRDP",      LTYPE3, AFSUBRDP,
-       "FSUBRW",       LTYPE3, AFSUBRW,
-       "FSUBRL",       LTYPE3, AFSUBRL,
-       "FSUBRF",       LTYPE3, AFSUBRF,
-       "FSUBRD",       LTYPE3, AFSUBRD,
-       "FMULDP",       LTYPE3, AFMULDP,
-       "FMULW",        LTYPE3, AFMULW,
-       "FMULL",        LTYPE3, AFMULL,
-       "FMULF",        LTYPE3, AFMULF,
-       "FMULD",        LTYPE3, AFMULD,
-       "FDIVDP",       LTYPE3, AFDIVDP,
-       "FDIVW",        LTYPE3, AFDIVW,
-       "FDIVL",        LTYPE3, AFDIVL,
-       "FDIVF",        LTYPE3, AFDIVF,
-       "FDIVD",        LTYPE3, AFDIVD,
-       "FDIVRDP",      LTYPE3, AFDIVRDP,
-       "FDIVRW",       LTYPE3, AFDIVRW,
-       "FDIVRL",       LTYPE3, AFDIVRL,
-       "FDIVRF",       LTYPE3, AFDIVRF,
-       "FDIVRD",       LTYPE3, AFDIVRD,
-       "FXCHD",        LTYPE3, AFXCHD,
-       "FFREE",        LTYPE1, AFFREE,
-       "FLDCW",        LTYPE2, AFLDCW,
-       "FLDENV",       LTYPE1, AFLDENV,
-       "FRSTOR",       LTYPE2, AFRSTOR,
-       "FSAVE",        LTYPE1, AFSAVE,
-       "FSTCW",        LTYPE1, AFSTCW,
-       "FSTENV",       LTYPE1, AFSTENV,
-       "FSTSW",        LTYPE1, AFSTSW,
-       "F2XM1",        LTYPE0, AF2XM1,
-       "FABS",         LTYPE0, AFABS,
-       "FCHS",         LTYPE0, AFCHS,
-       "FCLEX",        LTYPE0, AFCLEX,
-       "FCOS",         LTYPE0, AFCOS,
-       "FDECSTP",      LTYPE0, AFDECSTP,
-       "FINCSTP",      LTYPE0, AFINCSTP,
-       "FINIT",        LTYPE0, AFINIT,
-       "FLD1",         LTYPE0, AFLD1,
-       "FLDL2E",       LTYPE0, AFLDL2E,
-       "FLDL2T",       LTYPE0, AFLDL2T,
-       "FLDLG2",       LTYPE0, AFLDLG2,
-       "FLDLN2",       LTYPE0, AFLDLN2,
-       "FLDPI",        LTYPE0, AFLDPI,
-       "FLDZ",         LTYPE0, AFLDZ,
-       "FNOP",         LTYPE0, AFNOP,
-       "FPATAN",       LTYPE0, AFPATAN,
-       "FPREM",        LTYPE0, AFPREM,
-       "FPREM1",       LTYPE0, AFPREM1,
-       "FPTAN",        LTYPE0, AFPTAN,
-       "FRNDINT",      LTYPE0, AFRNDINT,
-       "FSCALE",       LTYPE0, AFSCALE,
-       "FSIN",         LTYPE0, AFSIN,
-       "FSINCOS",      LTYPE0, AFSINCOS,
-       "FSQRT",        LTYPE0, AFSQRT,
-       "FTST",         LTYPE0, AFTST,
-       "FXAM",         LTYPE0, AFXAM,
-       "FXTRACT",      LTYPE0, AFXTRACT,
-       "FYL2X",        LTYPE0, AFYL2X,
-       "FYL2XP1",      LTYPE0, AFYL2XP1,
-
-       "ADDPD",        LTYPE3, AADDPD,
-       "ADDPS",        LTYPE3, AADDPS,
-       "ADDSD",        LTYPE3, AADDSD,
-       "ADDSS",        LTYPE3, AADDSS,
-       "ANDNPD",       LTYPE3, AANDNPD,
-       "ANDNPS",       LTYPE3, AANDNPS,
-       "ANDPD",        LTYPE3, AANDPD,
-       "ANDPS",        LTYPE3, AANDPS,
-       "CMPPD",        LTYPEXC,ACMPPD,
-       "CMPPS",        LTYPEXC,ACMPPS,
-       "CMPSD",        LTYPEXC,ACMPSD,
-       "CMPSS",        LTYPEXC,ACMPSS,
-       "COMISD",       LTYPE3, ACOMISD,
-       "COMISS",       LTYPE3, ACOMISS,
-       "CVTPL2PD",     LTYPE3, ACVTPL2PD,
-       "CVTPL2PS",     LTYPE3, ACVTPL2PS,
-       "CVTPD2PL",     LTYPE3, ACVTPD2PL,
-       "CVTPD2PS",     LTYPE3, ACVTPD2PS,
-       "CVTPS2PL",     LTYPE3, ACVTPS2PL,
-       "PF2IW",        LTYPE3, APF2IW,
-       "PF2IL",        LTYPE3, APF2IL,
-       "PF2ID",        LTYPE3, APF2IL, /* syn */
-       "PI2FL",        LTYPE3, API2FL,
-       "PI2FD",        LTYPE3, API2FL, /* syn */
-       "PI2FW",        LTYPE3, API2FW,
-       "CVTPS2PD",     LTYPE3, ACVTPS2PD,
-       "CVTSD2SL",     LTYPE3, ACVTSD2SL,
-       "CVTSD2SQ",     LTYPE3, ACVTSD2SQ,
-       "CVTSD2SS",     LTYPE3, ACVTSD2SS,
-       "CVTSL2SD",     LTYPE3, ACVTSL2SD,
-       "CVTSQ2SD",     LTYPE3, ACVTSQ2SD,
-       "CVTSL2SS",     LTYPE3, ACVTSL2SS,
-       "CVTSQ2SS",     LTYPE3, ACVTSQ2SS,
-       "CVTSS2SD",     LTYPE3, ACVTSS2SD,
-       "CVTSS2SL",     LTYPE3, ACVTSS2SL,
-       "CVTSS2SQ",     LTYPE3, ACVTSS2SQ,
-       "CVTTPD2PL",    LTYPE3, ACVTTPD2PL,
-       "CVTTPS2PL",    LTYPE3, ACVTTPS2PL,
-       "CVTTSD2SL",    LTYPE3, ACVTTSD2SL,
-       "CVTTSD2SQ",    LTYPE3, ACVTTSD2SQ,
-       "CVTTSS2SL",    LTYPE3, ACVTTSS2SL,
-       "CVTTSS2SQ",    LTYPE3, ACVTTSS2SQ,
-       "DIVPD",        LTYPE3, ADIVPD,
-       "DIVPS",        LTYPE3, ADIVPS,
-       "DIVSD",        LTYPE3, ADIVSD,
-       "DIVSS",        LTYPE3, ADIVSS,
-       "FXRSTOR",      LTYPE2, AFXRSTOR,
-       "FXRSTOR64",    LTYPE2, AFXRSTOR64,
-       "FXSAVE",       LTYPE1, AFXSAVE,
-       "FXSAVE64",     LTYPE1, AFXSAVE64,
-       "LDMXCSR",      LTYPE2, ALDMXCSR,
-       "MASKMOVOU",    LTYPE3, AMASKMOVOU,
-       "MASKMOVDQU",   LTYPE3, AMASKMOVOU,     /* syn */
-       "MASKMOVQ",     LTYPE3, AMASKMOVQ,
-       "MAXPD",        LTYPE3, AMAXPD,
-       "MAXPS",        LTYPE3, AMAXPS,
-       "MAXSD",        LTYPE3, AMAXSD,
-       "MAXSS",        LTYPE3, AMAXSS,
-       "MINPD",        LTYPE3, AMINPD,
-       "MINPS",        LTYPE3, AMINPS,
-       "MINSD",        LTYPE3, AMINSD,
-       "MINSS",        LTYPE3, AMINSS,
-       "MOVAPD",       LTYPE3, AMOVAPD,
-       "MOVAPS",       LTYPE3, AMOVAPS,
-       "MOVD",         LTYPE3, AMOVQ,  /* syn */
-       "MOVDQ2Q",      LTYPE3, AMOVQ,  /* syn */
-       "MOVO",         LTYPE3, AMOVO,
-       "MOVOA",        LTYPE3, AMOVO,  /* syn */
-       "MOVOU",        LTYPE3, AMOVOU,
-       "MOVHLPS",      LTYPE3, AMOVHLPS,
-       "MOVHPD",       LTYPE3, AMOVHPD,
-       "MOVHPS",       LTYPE3, AMOVHPS,
-       "MOVLHPS",      LTYPE3, AMOVLHPS,
-       "MOVLPD",       LTYPE3, AMOVLPD,
-       "MOVLPS",       LTYPE3, AMOVLPS,
-       "MOVMSKPD",     LTYPE3, AMOVMSKPD,
-       "MOVMSKPS",     LTYPE3, AMOVMSKPS,
-       "MOVNTO",       LTYPE3, AMOVNTO,
-       "MOVNTDQ",      LTYPE3, AMOVNTO,        /* syn */
-       "MOVNTPD",      LTYPE3, AMOVNTPD,
-       "MOVNTPS",      LTYPE3, AMOVNTPS,
-       "MOVNTQ",       LTYPE3, AMOVNTQ,
-       "MOVQOZX",      LTYPE3, AMOVQOZX,
-       "MOVSD",        LTYPE3, AMOVSD,
-       "MOVSS",        LTYPE3, AMOVSS,
-       "MOVUPD",       LTYPE3, AMOVUPD,
-       "MOVUPS",       LTYPE3, AMOVUPS,
-       "MULPD",        LTYPE3, AMULPD,
-       "MULPS",        LTYPE3, AMULPS,
-       "MULSD",        LTYPE3, AMULSD,
-       "MULSS",        LTYPE3, AMULSS,
-       "ORPD",         LTYPE3, AORPD,
-       "ORPS",         LTYPE3, AORPS,
-       "PACKSSLW",     LTYPE3, APACKSSLW,
-       "PACKSSWB",     LTYPE3, APACKSSWB,
-       "PACKUSWB",     LTYPE3, APACKUSWB,
-       "PADDB",        LTYPE3, APADDB,
-       "PADDL",        LTYPE3, APADDL,
-       "PADDQ",        LTYPE3, APADDQ,
-       "PADDSB",       LTYPE3, APADDSB,
-       "PADDSW",       LTYPE3, APADDSW,
-       "PADDUSB",      LTYPE3, APADDUSB,
-       "PADDUSW",      LTYPE3, APADDUSW,
-       "PADDW",        LTYPE3, APADDW,
-       "PAND",         LTYPE3, APAND,
-       "PANDB",        LTYPE3, APANDB,
-       "PANDL",        LTYPE3, APANDL,
-       "PANDSB",       LTYPE3, APANDSB,
-       "PANDSW",       LTYPE3, APANDSW,
-       "PANDUSB",      LTYPE3, APANDUSB,
-       "PANDUSW",      LTYPE3, APANDUSW,
-       "PANDW",        LTYPE3, APANDW,
-       "PANDN",        LTYPE3, APANDN,
-       "PAVGB",        LTYPE3, APAVGB,
-       "PAVGW",        LTYPE3, APAVGW,
-       "PCMPEQB",      LTYPE3, APCMPEQB,
-       "PCMPEQL",      LTYPE3, APCMPEQL,
-       "PCMPEQW",      LTYPE3, APCMPEQW,
-       "PCMPGTB",      LTYPE3, APCMPGTB,
-       "PCMPGTL",      LTYPE3, APCMPGTL,       
-       "PCMPGTW",      LTYPE3, APCMPGTW,
-       "PEXTRW",       LTYPEX, APEXTRW,
-       "PINSRW",       LTYPEX, APINSRW,
-       "PINSRD",       LTYPEX, APINSRD,
-       "PINSRQ",       LTYPEX, APINSRQ,
-       "PMADDWL",      LTYPE3, APMADDWL,
-       "PMAXSW",       LTYPE3, APMAXSW,
-       "PMAXUB",       LTYPE3, APMAXUB,
-       "PMINSW",       LTYPE3, APMINSW,
-       "PMINUB",       LTYPE3, APMINUB,
-       "PMOVMSKB",     LTYPE3, APMOVMSKB,
-       "PMULHRW",      LTYPE3, APMULHRW,
-       "PMULHUW",      LTYPE3, APMULHUW,
-       "PMULHW",       LTYPE3, APMULHW,
-       "PMULLW",       LTYPE3, APMULLW,
-       "PMULULQ",      LTYPE3, APMULULQ,
-       "POR",          LTYPE3, APOR,
-       "PSADBW",       LTYPE3, APSADBW,
-       "PSHUFHW",      LTYPEX, APSHUFHW,
-       "PSHUFL",       LTYPEX, APSHUFL,
-       "PSHUFLW",      LTYPEX, APSHUFLW,
-       "PSHUFW",       LTYPEX, APSHUFW,
-       "PSHUFB",       LTYPEM, APSHUFB,
-       "PSLLO",        LTYPE3, APSLLO,
-       "PSLLDQ",       LTYPE3, APSLLO, /* syn */
-       "PSLLL",        LTYPE3, APSLLL,
-       "PSLLQ",        LTYPE3, APSLLQ,
-       "PSLLW",        LTYPE3, APSLLW,
-       "PSRAL",        LTYPE3, APSRAL,
-       "PSRAW",        LTYPE3, APSRAW,
-       "PSRLO",        LTYPE3, APSRLO,
-       "PSRLDQ",       LTYPE3, APSRLO, /* syn */
-       "PSRLL",        LTYPE3, APSRLL,
-       "PSRLQ",        LTYPE3, APSRLQ,
-       "PSRLW",        LTYPE3, APSRLW,
-       "PSUBB",        LTYPE3, APSUBB,
-       "PSUBL",        LTYPE3, APSUBL,
-       "PSUBQ",        LTYPE3, APSUBQ,
-       "PSUBSB",       LTYPE3, APSUBSB,
-       "PSUBSW",       LTYPE3, APSUBSW,
-       "PSUBUSB",      LTYPE3, APSUBUSB,
-       "PSUBUSW",      LTYPE3, APSUBUSW,
-       "PSUBW",        LTYPE3, APSUBW,
-       "PUNPCKHBW",    LTYPE3, APUNPCKHBW,
-       "PUNPCKHLQ",    LTYPE3, APUNPCKHLQ,
-       "PUNPCKHQDQ",   LTYPE3, APUNPCKHQDQ,
-       "PUNPCKHWL",    LTYPE3, APUNPCKHWL,
-       "PUNPCKLBW",    LTYPE3, APUNPCKLBW,
-       "PUNPCKLLQ",    LTYPE3, APUNPCKLLQ,
-       "PUNPCKLQDQ",   LTYPE3, APUNPCKLQDQ,
-       "PUNPCKLWL",    LTYPE3, APUNPCKLWL,
-       "PXOR",         LTYPE3, APXOR,
-       "RCPPS",        LTYPE3, ARCPPS,
-       "RCPSS",        LTYPE3, ARCPSS,
-       "RSQRTPS",      LTYPE3, ARSQRTPS,
-       "RSQRTSS",      LTYPE3, ARSQRTSS,
-       "SHUFPD",       LTYPEX, ASHUFPD,
-       "SHUFPS",       LTYPEX, ASHUFPS,
-       "SQRTPD",       LTYPE3, ASQRTPD,
-       "SQRTPS",       LTYPE3, ASQRTPS,
-       "SQRTSD",       LTYPE3, ASQRTSD,
-       "SQRTSS",       LTYPE3, ASQRTSS,
-       "STMXCSR",      LTYPE1, ASTMXCSR,
-       "SUBPD",        LTYPE3, ASUBPD,
-       "SUBPS",        LTYPE3, ASUBPS,
-       "SUBSD",        LTYPE3, ASUBSD,
-       "SUBSS",        LTYPE3, ASUBSS,
-       "UCOMISD",      LTYPE3, AUCOMISD,
-       "UCOMISS",      LTYPE3, AUCOMISS,
-       "UNPCKHPD",     LTYPE3, AUNPCKHPD,
-       "UNPCKHPS",     LTYPE3, AUNPCKHPS,
-       "UNPCKLPD",     LTYPE3, AUNPCKLPD,
-       "UNPCKLPS",     LTYPE3, AUNPCKLPS,
-       "XORPD",        LTYPE3, AXORPD,
-       "XORPS",        LTYPE3, AXORPS,
-       "CRC32B",       LTYPE4, ACRC32B,
-       "CRC32Q",       LTYPE4, ACRC32Q,
-       "PREFETCHT0",           LTYPE2, APREFETCHT0,
-       "PREFETCHT1",           LTYPE2, APREFETCHT1,
-       "PREFETCHT2",           LTYPE2, APREFETCHT2,
-       "PREFETCHNTA",          LTYPE2, APREFETCHNTA,
-       "UNDEF",        LTYPE0, AUNDEF,
-       "AESENC",       LTYPE3, AAESENC,
-       "AESENCLAST",   LTYPE3, AAESENCLAST,
-       "AESDEC",       LTYPE3, AAESDEC,
-       "AESDECLAST",   LTYPE3, AAESDECLAST,
-       "AESIMC",       LTYPE3, AAESIMC,
-       "AESKEYGENASSIST", LTYPEX, AAESKEYGENASSIST,
-       "PSHUFD",       LTYPEX, APSHUFD,
-       "USEFIELD",     LTYPEN, AUSEFIELD,
-       "PCLMULQDQ",    LTYPEX, APCLMULQDQ,
-       "PCDATA",       LTYPEPC,        APCDATA,
-       "FUNCDATA",     LTYPEF, AFUNCDATA,
-       0
-};
-
-void
-cinit(void)
-{
-       Sym *s;
-       int i;
-
-       nullgen.type = TYPE_NONE;
-       nullgen.index = TYPE_NONE;
-
-       nerrors = 0;
-       iostack = I;
-       iofree = I;
-       peekc = IGN;
-       nhunk = 0;
-       for(i=0; i<NHASH; i++)
-               hash[i] = S;
-       for(i=0; itab[i].name; i++) {
-               s = slookup(itab[i].name);
-               if(s->type != LNAME)
-                       yyerror("double initialization %s", itab[i].name);
-               s->type = itab[i].type;
-               s->value = itab[i].value;
-       }
-}
-
-void
-checkscale(int scale)
-{
-
-       switch(scale) {
-       case 1:
-       case 2:
-       case 4:
-       case 8:
-               return;
-       }
-       yyerror("scale must be 1248: %d", scale);
-}
-
-void
-syminit(Sym *s)
-{
-
-       s->type = LNAME;
-       s->value = 0;
-}
-
-void
-cclean(void)
-{
-       Addr2 g2;
-
-       g2.from = nullgen;
-       g2.to = nullgen;
-       outcode(AEND, &g2);
-}
-
-void
-outcode(int a, Addr2 *g2)
-{
-       Prog *p;
-       Plist *pl;
-       
-       if(pass == 1)
-               goto out;
-
-       p = malloc(sizeof *p);
-       memset(p, 0, sizeof *p);
-       p->as = a;
-       p->lineno = stmtline;
-       p->from = g2->from;
-       p->to = g2->to;
-       p->pc = pc;
-
-       if(lastpc == nil) {
-               pl = linknewplist(ctxt);
-               pl->firstpc = p;
-       } else
-               lastpc->link = p;
-       lastpc = p;     
-
-out:
-       if(a != AGLOBL && a != ADATA)
-               pc++;
-}
-
-#include "../cc/lexbody"
-#include "../cc/macbody"
similarity index 100%
rename from src/cmd/new6a/lex.go
rename to src/cmd/6a/lex.go
similarity index 100%
rename from src/cmd/new6a/y.go
rename to src/cmd/6a/y.go
diff --git a/src/cmd/6a/y.tab.c b/src/cmd/6a/y.tab.c
deleted file mode 100644 (file)
index a3ee581..0000000
+++ /dev/null
@@ -1,2800 +0,0 @@
-/* A Bison parser, made by GNU Bison 2.3.  */
-
-/* Skeleton implementation for Bison's Yacc-like parsers in C
-
-   Copyright (C) 1984, 1989, 1990, 2000, 2001, 2002, 2003, 2004, 2005, 2006
-   Free Software Foundation, Inc.
-
-   This program is free software; you can redistribute it and/or modify
-   it under the terms of the GNU General Public License as published by
-   the Free Software Foundation; either version 2, or (at your option)
-   any later version.
-
-   This program is distributed in the hope that it will be useful,
-   but WITHOUT ANY WARRANTY; without even the implied warranty of
-   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-   GNU General Public License for more details.
-
-   You should have received a copy of the GNU General Public License
-   along with this program; if not, write to the Free Software
-   Foundation, Inc., 51 Franklin Street, Fifth Floor,
-   Boston, MA 02110-1301, USA.  */
-
-/* As a special exception, you may create a larger work that contains
-   part or all of the Bison parser skeleton and distribute that work
-   under terms of your choice, so long as that work isn't itself a
-   parser generator using the skeleton or a modified version thereof
-   as a parser skeleton.  Alternatively, if you modify or redistribute
-   the parser skeleton itself, you may (at your option) remove this
-   special exception, which will cause the skeleton and the resulting
-   Bison output files to be licensed under the GNU General Public
-   License without this special exception.
-
-   This special exception was added by the Free Software Foundation in
-   version 2.2 of Bison.  */
-
-/* C LALR(1) parser skeleton written by Richard Stallman, by
-   simplifying the original so-called "semantic" parser.  */
-
-/* All symbols defined below should begin with yy or YY, to avoid
-   infringing on user name space.  This should be done even for local
-   variables, as they might otherwise be expanded by user macros.
-   There are some unavoidable exceptions within include files to
-   define necessary library symbols; they are noted "INFRINGES ON
-   USER NAME SPACE" below.  */
-
-/* Identify Bison output.  */
-#define YYBISON 1
-
-/* Bison version.  */
-#define YYBISON_VERSION "2.3"
-
-/* Skeleton name.  */
-#define YYSKELETON_NAME "yacc.c"
-
-/* Pure parsers.  */
-#define YYPURE 0
-
-/* Using locations.  */
-#define YYLSP_NEEDED 0
-
-
-
-/* Tokens.  */
-#ifndef YYTOKENTYPE
-# define YYTOKENTYPE
-   /* Put the tokens into the symbol table, so that GDB and other debuggers
-      know about them.  */
-   enum yytokentype {
-     LTYPE0 = 258,
-     LTYPE1 = 259,
-     LTYPE2 = 260,
-     LTYPE3 = 261,
-     LTYPE4 = 262,
-     LTYPEC = 263,
-     LTYPED = 264,
-     LTYPEN = 265,
-     LTYPER = 266,
-     LTYPET = 267,
-     LTYPEG = 268,
-     LTYPEPC = 269,
-     LTYPES = 270,
-     LTYPEM = 271,
-     LTYPEI = 272,
-     LTYPEXC = 273,
-     LTYPEX = 274,
-     LTYPERT = 275,
-     LTYPEF = 276,
-     LCONST = 277,
-     LFP = 278,
-     LPC = 279,
-     LSB = 280,
-     LBREG = 281,
-     LLREG = 282,
-     LSREG = 283,
-     LFREG = 284,
-     LMREG = 285,
-     LXREG = 286,
-     LFCONST = 287,
-     LSCONST = 288,
-     LSP = 289,
-     LNAME = 290,
-     LLAB = 291,
-     LVAR = 292
-   };
-#endif
-/* Tokens.  */
-#define LTYPE0 258
-#define LTYPE1 259
-#define LTYPE2 260
-#define LTYPE3 261
-#define LTYPE4 262
-#define LTYPEC 263
-#define LTYPED 264
-#define LTYPEN 265
-#define LTYPER 266
-#define LTYPET 267
-#define LTYPEG 268
-#define LTYPEPC 269
-#define LTYPES 270
-#define LTYPEM 271
-#define LTYPEI 272
-#define LTYPEXC 273
-#define LTYPEX 274
-#define LTYPERT 275
-#define LTYPEF 276
-#define LCONST 277
-#define LFP 278
-#define LPC 279
-#define LSB 280
-#define LBREG 281
-#define LLREG 282
-#define LSREG 283
-#define LFREG 284
-#define LMREG 285
-#define LXREG 286
-#define LFCONST 287
-#define LSCONST 288
-#define LSP 289
-#define LNAME 290
-#define LLAB 291
-#define LVAR 292
-
-
-
-
-/* Copy the first part of user declarations.  */
-#line 31 "a.y"
-
-#include <u.h>
-#include <stdio.h>     /* if we don't, bison will, and a.h re-#defines getc */
-#include <libc.h>
-#include "a.h"
-#include "../../runtime/funcdata.h"
-
-
-/* Enabling traces.  */
-#ifndef YYDEBUG
-# define YYDEBUG 0
-#endif
-
-/* Enabling verbose error messages.  */
-#ifdef YYERROR_VERBOSE
-# undef YYERROR_VERBOSE
-# define YYERROR_VERBOSE 1
-#else
-# define YYERROR_VERBOSE 0
-#endif
-
-/* Enabling the token table.  */
-#ifndef YYTOKEN_TABLE
-# define YYTOKEN_TABLE 0
-#endif
-
-#if ! defined YYSTYPE && ! defined YYSTYPE_IS_DECLARED
-typedef union YYSTYPE
-#line 38 "a.y"
-{
-       Sym     *sym;
-       vlong   lval;
-       double  dval;
-       char    sval[8];
-       Addr    addr;
-       Addr2   addr2;
-}
-/* Line 193 of yacc.c.  */
-#line 187 "y.tab.c"
-       YYSTYPE;
-# define yystype YYSTYPE /* obsolescent; will be withdrawn */
-# define YYSTYPE_IS_DECLARED 1
-# define YYSTYPE_IS_TRIVIAL 1
-#endif
-
-
-
-/* Copy the second part of user declarations.  */
-
-
-/* Line 216 of yacc.c.  */
-#line 200 "y.tab.c"
-
-#ifdef short
-# undef short
-#endif
-
-#ifdef YYTYPE_UINT8
-typedef YYTYPE_UINT8 yytype_uint8;
-#else
-typedef unsigned char yytype_uint8;
-#endif
-
-#ifdef YYTYPE_INT8
-typedef YYTYPE_INT8 yytype_int8;
-#elif (defined __STDC__ || defined __C99__FUNC__ \
-     || defined __cplusplus || defined _MSC_VER)
-typedef signed char yytype_int8;
-#else
-typedef short int yytype_int8;
-#endif
-
-#ifdef YYTYPE_UINT16
-typedef YYTYPE_UINT16 yytype_uint16;
-#else
-typedef unsigned short int yytype_uint16;
-#endif
-
-#ifdef YYTYPE_INT16
-typedef YYTYPE_INT16 yytype_int16;
-#else
-typedef short int yytype_int16;
-#endif
-
-#ifndef YYSIZE_T
-# ifdef __SIZE_TYPE__
-#  define YYSIZE_T __SIZE_TYPE__
-# elif defined size_t
-#  define YYSIZE_T size_t
-# elif ! defined YYSIZE_T && (defined __STDC__ || defined __C99__FUNC__ \
-     || defined __cplusplus || defined _MSC_VER)
-#  include <stddef.h> /* INFRINGES ON USER NAME SPACE */
-#  define YYSIZE_T size_t
-# else
-#  define YYSIZE_T unsigned int
-# endif
-#endif
-
-#define YYSIZE_MAXIMUM ((YYSIZE_T) -1)
-
-#ifndef YY_
-# if defined YYENABLE_NLS && YYENABLE_NLS
-#  if ENABLE_NLS
-#   include <libintl.h> /* INFRINGES ON USER NAME SPACE */
-#   define YY_(msgid) dgettext ("bison-runtime", msgid)
-#  endif
-# endif
-# ifndef YY_
-#  define YY_(msgid) msgid
-# endif
-#endif
-
-/* Suppress unused-variable warnings by "using" E.  */
-#if ! defined lint || defined __GNUC__
-# define YYUSE(e) ((void) (e))
-#else
-# define YYUSE(e) /* empty */
-#endif
-
-/* Identity function, used to suppress warnings about constant conditions.  */
-#ifndef lint
-# define YYID(n) (n)
-#else
-#if (defined __STDC__ || defined __C99__FUNC__ \
-     || defined __cplusplus || defined _MSC_VER)
-static int
-YYID (int i)
-#else
-static int
-YYID (i)
-    int i;
-#endif
-{
-  return i;
-}
-#endif
-
-#if ! defined yyoverflow || YYERROR_VERBOSE
-
-/* The parser invokes alloca or malloc; define the necessary symbols.  */
-
-# ifdef YYSTACK_USE_ALLOCA
-#  if YYSTACK_USE_ALLOCA
-#   ifdef __GNUC__
-#    define YYSTACK_ALLOC __builtin_alloca
-#   elif defined __BUILTIN_VA_ARG_INCR
-#    include <alloca.h> /* INFRINGES ON USER NAME SPACE */
-#   elif defined _AIX
-#    define YYSTACK_ALLOC __alloca
-#   elif defined _MSC_VER
-#    include <malloc.h> /* INFRINGES ON USER NAME SPACE */
-#    define alloca _alloca
-#   else
-#    define YYSTACK_ALLOC alloca
-#    if ! defined _ALLOCA_H && ! defined _STDLIB_H && (defined __STDC__ || defined __C99__FUNC__ \
-     || defined __cplusplus || defined _MSC_VER)
-#     include <stdlib.h> /* INFRINGES ON USER NAME SPACE */
-#     ifndef _STDLIB_H
-#      define _STDLIB_H 1
-#     endif
-#    endif
-#   endif
-#  endif
-# endif
-
-# ifdef YYSTACK_ALLOC
-   /* Pacify GCC's `empty if-body' warning.  */
-#  define YYSTACK_FREE(Ptr) do { /* empty */; } while (YYID (0))
-#  ifndef YYSTACK_ALLOC_MAXIMUM
-    /* The OS might guarantee only one guard page at the bottom of the stack,
-       and a page size can be as small as 4096 bytes.  So we cannot safely
-       invoke alloca (N) if N exceeds 4096.  Use a slightly smaller number
-       to allow for a few compiler-allocated temporary stack slots.  */
-#   define YYSTACK_ALLOC_MAXIMUM 4032 /* reasonable circa 2006 */
-#  endif
-# else
-#  define YYSTACK_ALLOC YYMALLOC
-#  define YYSTACK_FREE YYFREE
-#  ifndef YYSTACK_ALLOC_MAXIMUM
-#   define YYSTACK_ALLOC_MAXIMUM YYSIZE_MAXIMUM
-#  endif
-#  if (defined __cplusplus && ! defined _STDLIB_H \
-       && ! ((defined YYMALLOC || defined malloc) \
-            && (defined YYFREE || defined free)))
-#   include <stdlib.h> /* INFRINGES ON USER NAME SPACE */
-#   ifndef _STDLIB_H
-#    define _STDLIB_H 1
-#   endif
-#  endif
-#  ifndef YYMALLOC
-#   define YYMALLOC malloc
-#   if ! defined malloc && ! defined _STDLIB_H && (defined __STDC__ || defined __C99__FUNC__ \
-     || defined __cplusplus || defined _MSC_VER)
-void *malloc (YYSIZE_T); /* INFRINGES ON USER NAME SPACE */
-#   endif
-#  endif
-#  ifndef YYFREE
-#   define YYFREE free
-#   if ! defined free && ! defined _STDLIB_H && (defined __STDC__ || defined __C99__FUNC__ \
-     || defined __cplusplus || defined _MSC_VER)
-void free (void *); /* INFRINGES ON USER NAME SPACE */
-#   endif
-#  endif
-# endif
-#endif /* ! defined yyoverflow || YYERROR_VERBOSE */
-
-
-#if (! defined yyoverflow \
-     && (! defined __cplusplus \
-        || (defined YYSTYPE_IS_TRIVIAL && YYSTYPE_IS_TRIVIAL)))
-
-/* A type that is properly aligned for any stack member.  */
-union yyalloc
-{
-  yytype_int16 yyss;
-  YYSTYPE yyvs;
-  };
-
-/* The size of the maximum gap between one aligned stack and the next.  */
-# define YYSTACK_GAP_MAXIMUM (sizeof (union yyalloc) - 1)
-
-/* The size of an array large to enough to hold all stacks, each with
-   N elements.  */
-# define YYSTACK_BYTES(N) \
-     ((N) * (sizeof (yytype_int16) + sizeof (YYSTYPE)) \
-      + YYSTACK_GAP_MAXIMUM)
-
-/* Copy COUNT objects from FROM to TO.  The source and destination do
-   not overlap.  */
-# ifndef YYCOPY
-#  if defined __GNUC__ && 1 < __GNUC__
-#   define YYCOPY(To, From, Count) \
-      __builtin_memcpy (To, From, (Count) * sizeof (*(From)))
-#  else
-#   define YYCOPY(To, From, Count)             \
-      do                                       \
-       {                                       \
-         YYSIZE_T yyi;                         \
-         for (yyi = 0; yyi < (Count); yyi++)   \
-           (To)[yyi] = (From)[yyi];            \
-       }                                       \
-      while (YYID (0))
-#  endif
-# endif
-
-/* Relocate STACK from its old location to the new one.  The
-   local variables YYSIZE and YYSTACKSIZE give the old and new number of
-   elements in the stack, and YYPTR gives the new location of the
-   stack.  Advance YYPTR to a properly aligned location for the next
-   stack.  */
-# define YYSTACK_RELOCATE(Stack)                                       \
-    do                                                                 \
-      {                                                                        \
-       YYSIZE_T yynewbytes;                                            \
-       YYCOPY (&yyptr->Stack, Stack, yysize);                          \
-       Stack = &yyptr->Stack;                                          \
-       yynewbytes = yystacksize * sizeof (*Stack) + YYSTACK_GAP_MAXIMUM; \
-       yyptr += yynewbytes / sizeof (*yyptr);                          \
-      }                                                                        \
-    while (YYID (0))
-
-#endif
-
-/* YYFINAL -- State number of the termination state.  */
-#define YYFINAL  2
-/* YYLAST -- Last index in YYTABLE.  */
-#define YYLAST   524
-
-/* YYNTOKENS -- Number of terminals.  */
-#define YYNTOKENS  56
-/* YYNNTS -- Number of nonterminals.  */
-#define YYNNTS  40
-/* YYNRULES -- Number of rules.  */
-#define YYNRULES  133
-/* YYNRULES -- Number of states.  */
-#define YYNSTATES  271
-
-/* YYTRANSLATE(YYLEX) -- Bison symbol number corresponding to YYLEX.  */
-#define YYUNDEFTOK  2
-#define YYMAXUTOK   292
-
-#define YYTRANSLATE(YYX)                                               \
-  ((unsigned int) (YYX) <= YYMAXUTOK ? yytranslate[YYX] : YYUNDEFTOK)
-
-/* YYTRANSLATE[YYLEX] -- Bison symbol number corresponding to YYLEX.  */
-static const yytype_uint8 yytranslate[] =
-{
-       0,     2,     2,     2,     2,     2,     2,     2,     2,     2,
-       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
-       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
-       2,     2,     2,     2,     2,     2,    52,    12,     5,     2,
-      53,    54,    10,     8,    51,     9,     2,    11,     2,     2,
-       2,     2,     2,     2,     2,     2,     2,     2,    48,    49,
-       6,    50,     7,     2,     2,     2,     2,     2,     2,     2,
-       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
-       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
-       2,     2,     2,     2,     4,     2,     2,     2,     2,     2,
-       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
-       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
-       2,     2,     2,     2,     3,     2,    55,     2,     2,     2,
-       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
-       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
-       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
-       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
-       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
-       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
-       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
-       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
-       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
-       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
-       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
-       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
-       2,     2,     2,     2,     2,     2,     1,     2,    13,    14,
-      15,    16,    17,    18,    19,    20,    21,    22,    23,    24,
-      25,    26,    27,    28,    29,    30,    31,    32,    33,    34,
-      35,    36,    37,    38,    39,    40,    41,    42,    43,    44,
-      45,    46,    47
-};
-
-#if YYDEBUG
-/* YYPRHS[YYN] -- Index of the first RHS symbol of rule number YYN in
-   YYRHS.  */
-static const yytype_uint16 yyprhs[] =
-{
-       0,     0,     3,     4,     5,     9,    10,    15,    17,    20,
-      23,    27,    31,    34,    37,    40,    43,    46,    49,    51,
-      53,    56,    59,    62,    65,    68,    71,    74,    77,    79,
-      82,    85,    86,    88,    92,    96,    99,   101,   104,   106,
-     109,   111,   115,   122,   128,   136,   141,   148,   151,   153,
-     155,   157,   161,   167,   171,   177,   180,   182,   186,   192,
-     198,   199,   201,   205,   209,   211,   213,   215,   217,   220,
-     223,   225,   227,   229,   231,   236,   239,   241,   243,   245,
-     247,   249,   251,   253,   256,   259,   262,   265,   270,   276,
-     280,   282,   284,   286,   291,   296,   301,   308,   318,   328,
-     332,   336,   342,   351,   353,   360,   366,   374,   375,   378,
-     381,   383,   385,   387,   389,   391,   394,   397,   400,   404,
-     406,   409,   413,   418,   420,   424,   428,   432,   436,   440,
-     445,   450,   454,   458
-};
-
-/* YYRHS -- A `-1'-separated list of the rules' RHS.  */
-static const yytype_int8 yyrhs[] =
-{
-      57,     0,    -1,    -1,    -1,    57,    58,    59,    -1,    -1,
-      45,    48,    60,    59,    -1,    49,    -1,    61,    49,    -1,
-       1,    49,    -1,    45,    50,    95,    -1,    47,    50,    95,
-      -1,    13,    62,    -1,    14,    66,    -1,    15,    65,    -1,
-      16,    63,    -1,    17,    64,    -1,    21,    67,    -1,    68,
-      -1,    69,    -1,    18,    71,    -1,    20,    72,    -1,    25,
-      73,    -1,    26,    74,    -1,    27,    75,    -1,    28,    76,
-      -1,    29,    77,    -1,    30,    78,    -1,    70,    -1,    24,
-      79,    -1,    31,    80,    -1,    -1,    51,    -1,    83,    51,
-      81,    -1,    81,    51,    83,    -1,    83,    51,    -1,    83,
-      -1,    51,    81,    -1,    81,    -1,    51,    84,    -1,    84,
-      -1,    86,    51,    84,    -1,    19,    90,    11,    93,    51,
-      86,    -1,    22,    87,    51,    52,    94,    -1,    22,    87,
-      51,    93,    51,    52,    94,    -1,    23,    87,    51,    86,
-      -1,    23,    87,    51,    93,    51,    86,    -1,    51,    82,
-      -1,    82,    -1,    62,    -1,    66,    -1,    83,    51,    81,
-      -1,    83,    51,    81,    48,    37,    -1,    83,    51,    81,
-      -1,    83,    51,    81,    48,    38,    -1,    83,    51,    -1,
-      83,    -1,    83,    51,    81,    -1,    85,    51,    81,    51,
-      93,    -1,    86,    51,    81,    51,    85,    -1,    -1,    86,
-      -1,    83,    51,    83,    -1,    83,    51,    83,    -1,    85,
-      -1,    87,    -1,    84,    -1,    89,    -1,    10,    85,    -1,
-      10,    88,    -1,    85,    -1,    88,    -1,    81,    -1,    86,
-      -1,    93,    53,    34,    54,    -1,    45,    91,    -1,    36,
-      -1,    39,    -1,    37,    -1,    40,    -1,    44,    -1,    38,
-      -1,    41,    -1,    52,    93,    -1,    52,    90,    -1,    52,
-      43,    -1,    52,    42,    -1,    52,    53,    42,    54,    -1,
-      52,    53,     9,    42,    54,    -1,    52,     9,    42,    -1,
-      88,    -1,    89,    -1,    93,    -1,    93,    53,    37,    54,
-      -1,    93,    53,    44,    54,    -1,    93,    53,    38,    54,
-      -1,    93,    53,    37,    10,    93,    54,    -1,    93,    53,
-      37,    54,    53,    37,    10,    93,    54,    -1,    93,    53,
-      37,    54,    53,    38,    10,    93,    54,    -1,    53,    37,
-      54,    -1,    53,    44,    54,    -1,    53,    37,    10,    93,
-      54,    -1,    53,    37,    54,    53,    37,    10,    93,    54,
-      -1,    90,    -1,    90,    53,    37,    10,    93,    54,    -1,
-      45,    91,    53,    92,    54,    -1,    45,     6,     7,    91,
-      53,    35,    54,    -1,    -1,     8,    93,    -1,     9,    93,
-      -1,    35,    -1,    44,    -1,    33,    -1,    32,    -1,    47,
-      -1,     9,    93,    -1,     8,    93,    -1,    55,    93,    -1,
-      53,    95,    54,    -1,    32,    -1,     9,    32,    -1,    32,
-       9,    32,    -1,     9,    32,     9,    32,    -1,    93,    -1,
-      95,     8,    95,    -1,    95,     9,    95,    -1,    95,    10,
-      95,    -1,    95,    11,    95,    -1,    95,    12,    95,    -1,
-      95,     6,     6,    95,    -1,    95,     7,     7,    95,    -1,
-      95,     5,    95,    -1,    95,     4,    95,    -1,    95,     3,
-      95,    -1
-};
-
-/* YYRLINE[YYN] -- source line where rule number YYN was defined.  */
-static const yytype_uint16 yyrline[] =
-{
-       0,    66,    66,    68,    67,    75,    74,    83,    84,    85,
-      88,    93,    99,   100,   101,   102,   103,   104,   105,   106,
-     107,   108,   109,   110,   111,   112,   113,   114,   115,   116,
-     117,   120,   124,   131,   138,   145,   150,   157,   162,   169,
-     174,   179,   186,   199,   207,   221,   229,   243,   248,   255,
-     256,   259,   264,   274,   279,   289,   294,   299,   306,   314,
-     324,   328,   335,   344,   355,   356,   359,   360,   361,   365,
-     369,   370,   373,   374,   377,   383,   394,   400,   406,   412,
-     418,   424,   430,   438,   444,   454,   460,   466,   472,   478,
-     486,   487,   490,   496,   503,   510,   517,   526,   536,   546,
-     552,   558,   566,   577,   581,   590,   598,   608,   611,   615,
-     621,   622,   626,   629,   630,   634,   638,   642,   646,   652,
-     659,   666,   673,   682,   683,   687,   691,   695,   699,   703,
-     707,   711,   715,   719
-};
-#endif
-
-#if YYDEBUG || YYERROR_VERBOSE || YYTOKEN_TABLE
-/* YYTNAME[SYMBOL-NUM] -- String name of the symbol SYMBOL-NUM.
-   First, the terminals, then, starting at YYNTOKENS, nonterminals.  */
-static const char *const yytname[] =
-{
-  "$end", "error", "$undefined", "'|'", "'^'", "'&'", "'<'", "'>'", "'+'",
-  "'-'", "'*'", "'/'", "'%'", "LTYPE0", "LTYPE1", "LTYPE2", "LTYPE3",
-  "LTYPE4", "LTYPEC", "LTYPED", "LTYPEN", "LTYPER", "LTYPET", "LTYPEG",
-  "LTYPEPC", "LTYPES", "LTYPEM", "LTYPEI", "LTYPEXC", "LTYPEX", "LTYPERT",
-  "LTYPEF", "LCONST", "LFP", "LPC", "LSB", "LBREG", "LLREG", "LSREG",
-  "LFREG", "LMREG", "LXREG", "LFCONST", "LSCONST", "LSP", "LNAME", "LLAB",
-  "LVAR", "':'", "';'", "'='", "','", "'$'", "'('", "')'", "'~'",
-  "$accept", "prog", "@1", "line", "@2", "inst", "nonnon", "rimrem",
-  "remrim", "rimnon", "nonrem", "nonrel", "spec1", "spec2", "spec11",
-  "spec3", "spec4", "spec5", "spec6", "spec7", "spec8", "spec9", "spec10",
-  "spec12", "spec13", "rem", "rom", "rim", "rel", "reg", "imm", "mem",
-  "omem", "nmem", "nam", "offset", "pointer", "con", "textsize", "expr", 0
-};
-#endif
-
-# ifdef YYPRINT
-/* YYTOKNUM[YYLEX-NUM] -- Internal token number corresponding to
-   token YYLEX-NUM.  */
-static const yytype_uint16 yytoknum[] =
-{
-       0,   256,   257,   124,    94,    38,    60,    62,    43,    45,
-      42,    47,    37,   258,   259,   260,   261,   262,   263,   264,
-     265,   266,   267,   268,   269,   270,   271,   272,   273,   274,
-     275,   276,   277,   278,   279,   280,   281,   282,   283,   284,
-     285,   286,   287,   288,   289,   290,   291,   292,    58,    59,
-      61,    44,    36,    40,    41,   126
-};
-# endif
-
-/* YYR1[YYN] -- Symbol number of symbol that rule YYN derives.  */
-static const yytype_uint8 yyr1[] =
-{
-       0,    56,    57,    58,    57,    60,    59,    59,    59,    59,
-      61,    61,    61,    61,    61,    61,    61,    61,    61,    61,
-      61,    61,    61,    61,    61,    61,    61,    61,    61,    61,
-      61,    62,    62,    63,    64,    65,    65,    66,    66,    67,
-      67,    67,    68,    69,    69,    70,    70,    71,    71,    72,
-      72,    73,    73,    74,    74,    75,    75,    75,    76,    77,
-      78,    78,    79,    80,    81,    81,    82,    82,    82,    82,
-      82,    82,    83,    83,    84,    84,    85,    85,    85,    85,
-      85,    85,    85,    86,    86,    86,    86,    86,    86,    86,
-      87,    87,    88,    88,    88,    88,    88,    88,    88,    88,
-      88,    88,    88,    89,    89,    90,    90,    91,    91,    91,
-      92,    92,    92,    93,    93,    93,    93,    93,    93,    94,
-      94,    94,    94,    95,    95,    95,    95,    95,    95,    95,
-      95,    95,    95,    95
-};
-
-/* YYR2[YYN] -- Number of symbols composing right hand side of rule YYN.  */
-static const yytype_uint8 yyr2[] =
-{
-       0,     2,     0,     0,     3,     0,     4,     1,     2,     2,
-       3,     3,     2,     2,     2,     2,     2,     2,     1,     1,
-       2,     2,     2,     2,     2,     2,     2,     2,     1,     2,
-       2,     0,     1,     3,     3,     2,     1,     2,     1,     2,
-       1,     3,     6,     5,     7,     4,     6,     2,     1,     1,
-       1,     3,     5,     3,     5,     2,     1,     3,     5,     5,
-       0,     1,     3,     3,     1,     1,     1,     1,     2,     2,
-       1,     1,     1,     1,     4,     2,     1,     1,     1,     1,
-       1,     1,     1,     2,     2,     2,     2,     4,     5,     3,
-       1,     1,     1,     4,     4,     4,     6,     9,     9,     3,
-       3,     5,     8,     1,     6,     5,     7,     0,     2,     2,
-       1,     1,     1,     1,     1,     2,     2,     2,     3,     1,
-       2,     3,     4,     1,     3,     3,     3,     3,     3,     4,
-       4,     3,     3,     3
-};
-
-/* YYDEFACT[STATE-NAME] -- Default rule to reduce with in state
-   STATE-NUM when YYTABLE doesn't specify something else to do.  Zero
-   means the default is an error.  */
-static const yytype_uint8 yydefact[] =
-{
-       2,     3,     1,     0,     0,    31,     0,     0,     0,     0,
-       0,     0,    31,     0,     0,     0,     0,     0,     0,     0,
-       0,     0,    60,     0,     0,     0,     7,     4,     0,    18,
-      19,    28,     9,    32,    12,     0,     0,   113,    76,    78,
-      81,    77,    79,    82,    80,   107,   114,     0,     0,     0,
-      13,    38,    64,    65,    90,    91,   103,    92,     0,    14,
-      72,    36,    73,    15,     0,    16,     0,     0,   107,     0,
-      20,    48,    66,    70,    71,    67,    92,     0,    32,    49,
-      50,    21,   107,     0,     0,    17,    40,     0,     0,     0,
-       0,    29,     0,    22,     0,    23,     0,    24,    56,    25,
-       0,    26,     0,    27,    61,    30,     0,     5,     0,     0,
-       8,   116,   115,     0,     0,     0,     0,    37,     0,     0,
-     123,     0,   117,     0,     0,     0,    86,    85,     0,    84,
-      83,    35,     0,     0,    68,    69,    75,    47,     0,     0,
-      75,    39,     0,     0,     0,     0,     0,     0,     0,    55,
-       0,     0,     0,     0,    10,    11,   107,   108,   109,     0,
-       0,    99,   100,     0,     0,     0,     0,     0,     0,     0,
-       0,     0,     0,   118,     0,     0,     0,     0,    89,     0,
-       0,    33,    34,     0,     0,    41,     0,     0,    45,     0,
-      62,    51,    53,    57,     0,     0,    63,     6,     0,   112,
-     110,   111,     0,     0,     0,   133,   132,   131,     0,     0,
-     124,   125,   126,   127,   128,     0,     0,    93,    95,    94,
-       0,    87,    74,     0,     0,   119,    43,     0,     0,     0,
-       0,     0,     0,     0,   105,   101,     0,   129,   130,     0,
-       0,     0,    88,    42,   120,     0,     0,    46,    52,    54,
-      58,    59,     0,     0,   104,    96,     0,     0,     0,   121,
-      44,   106,     0,     0,     0,   122,   102,     0,     0,    97,
-      98
-};
-
-/* YYDEFGOTO[NTERM-NUM].  */
-static const yytype_int16 yydefgoto[] =
-{
-      -1,     1,     3,    27,   153,    28,    34,    63,    65,    59,
-      50,    85,    29,    30,    31,    70,    81,    93,    95,    97,
-      99,   101,   103,    91,   105,    60,    71,    61,    72,    52,
-      62,    53,    54,    55,    56,   116,   202,    57,   226,   121
-};
-
-/* YYPACT[STATE-NUM] -- Index in YYTABLE of the portion describing
-   STATE-NUM.  */
-#define YYPACT_NINF -87
-static const yytype_int16 yypact[] =
-{
-     -87,    24,   -87,   211,    20,    -5,   236,   256,   256,   330,
-     156,    25,   290,    55,   364,   364,   256,   256,   256,   256,
-     145,    29,    29,   256,    17,    46,   -87,   -87,    26,   -87,
-     -87,   -87,   -87,   -87,   -87,   451,   451,   -87,   -87,   -87,
-     -87,   -87,   -87,   -87,   -87,    27,   -87,   330,   270,   451,
-     -87,   -87,   -87,   -87,   -87,   -87,    39,    44,    48,   -87,
-     -87,    65,   -87,   -87,    66,   -87,    68,   350,    27,   310,
-     -87,   -87,   -87,   -87,   -87,   -87,    71,   110,   330,   -87,
-     -87,   -87,    23,   384,   451,   -87,   -87,    75,    72,    77,
-      82,   -87,    85,   -87,    87,   -87,    88,   -87,    89,   -87,
-      90,   -87,    91,   -87,   -87,   -87,    92,   -87,   451,   451,
-     -87,   -87,   -87,   120,   451,   451,    98,   -87,     7,   113,
-     -87,   168,   -87,   115,     5,   391,   -87,   -87,   398,   -87,
-     -87,   -87,   330,   256,   -87,   -87,    98,   -87,     3,   451,
-     -87,   -87,   384,   122,   416,   426,   256,   330,   330,   330,
-     330,   330,   256,   211,   504,   504,    23,   -87,   -87,    76,
-     451,   117,   -87,   451,   451,   451,   162,   180,   451,   451,
-     451,   451,   451,   -87,   181,     8,   136,   148,   -87,   433,
-     150,   -87,   -87,   154,   159,   -87,    12,   163,   -87,   165,
-     -87,   169,   170,   -87,   204,   206,   -87,   -87,   160,   -87,
-     -87,   -87,   205,   207,   182,   485,   512,   240,   451,   451,
-     102,   102,   -87,   -87,   -87,   451,   451,   209,   -87,   -87,
-     212,   -87,   -87,    29,   231,   258,   -87,   217,    29,   233,
-     244,   451,   145,   249,   -87,   -87,   261,    42,    42,   232,
-     250,   -22,   -87,   -87,   276,   273,    12,   -87,   -87,   -87,
-     -87,   -87,   252,   451,   -87,   -87,   280,   300,   281,   -87,
-     -87,   -87,   262,   451,   451,   -87,   -87,   267,   278,   -87,
-     -87
-};
-
-/* YYPGOTO[NTERM-NUM].  */
-static const yytype_int16 yypgoto[] =
-{
-     -87,   -87,   -87,   171,   -87,   -87,   303,   -87,   -87,   -87,
-     321,   -87,   -87,   -87,   -87,   -87,   -87,   -87,   -87,   -87,
-     -87,   -87,   -87,   -87,   -87,    -2,   243,    11,   -11,    -9,
-      -8,    74,    -1,     2,    -3,   -62,   -87,   -10,    94,   -86
-};
-
-/* YYTABLE[YYPACT[STATE-NUM]].  What to do in state STATE-NUM.  If
-   positive, shift that token.  If negative, reduce the rule which
-   number is the opposite.  If zero, do what YYDEFACT says.
-   If YYTABLE_NINF, syntax error.  */
-#define YYTABLE_NINF -1
-static const yytype_uint16 yytable[] =
-{
-      76,    73,    86,    88,    51,    87,   136,    66,    77,    74,
-      51,   100,    75,   102,   104,   256,   257,   160,   216,    64,
-     140,   224,   154,   155,     2,   111,   112,    92,    94,    96,
-      98,   114,   115,   113,   106,   114,   115,   183,   120,   122,
-     175,   176,   175,   176,   225,   117,    33,   177,   130,   177,
-     168,   169,   170,   171,   172,   129,    35,   125,   134,    76,
-      73,   161,   217,    35,    36,   107,   135,   108,    74,    32,
-      45,    75,   141,    88,   120,   110,   117,   205,   206,   207,
-      37,    58,   210,   211,   212,   213,   214,    37,    89,    90,
-     126,   127,   123,    45,   198,    46,   109,   124,   120,   120,
-      82,   128,    46,    49,   157,   158,    83,    58,    84,   199,
-      49,   200,   170,   171,   172,   112,   131,   132,   120,   133,
-     201,   139,   237,   238,   138,   143,   142,   156,   144,   184,
-     181,   185,    88,   145,   187,   189,   146,   188,   147,   148,
-     149,   150,   151,   152,   182,   191,   192,   193,   194,   195,
-     203,   159,   174,   120,   120,   120,   183,   190,   120,   120,
-     120,   120,   120,   196,    35,    36,    67,   162,   208,   112,
-     204,   163,   164,   165,   166,   167,   168,   169,   170,   171,
-     172,    38,    39,    40,    41,    42,    43,   209,    37,    44,
-     218,   215,    38,    39,    40,    41,    42,    43,   120,   120,
-      44,    68,   219,    46,   221,   239,   240,    69,   222,    48,
-     223,    49,     4,   233,   227,   243,   228,   229,   230,   236,
-     247,   250,   173,   251,     5,     6,     7,     8,     9,    10,
-      11,    12,    13,    14,    15,    16,    17,    18,    19,    20,
-      21,    22,    23,   262,    35,    36,   166,   167,   168,   169,
-     170,   171,   172,   267,   268,   231,    24,   232,    25,   234,
-      26,   235,   241,   244,    35,    36,   242,   245,    37,   246,
-     248,   253,    38,    39,    40,    41,    42,    43,    35,    36,
-      44,    45,   249,    46,   252,   258,   254,    47,    37,    48,
-     263,    49,    38,    39,    40,    41,    42,    43,    35,    36,
-      44,    45,    37,    46,   255,   259,   261,   118,    58,    48,
-     264,    49,   137,   265,   119,    79,   266,    46,    35,    36,
-      67,   269,    37,    84,   197,    49,    38,    39,    40,    41,
-      42,    43,   270,    80,    44,    45,     0,    46,    35,    36,
-     260,    78,    37,    48,     0,    49,    38,    39,    40,    41,
-      42,    43,     0,     0,    44,    68,     0,    46,    35,    36,
-       0,     0,    37,    48,     0,    49,    38,    39,    40,    41,
-      42,    43,    35,    36,    44,    45,     0,    46,     0,     0,
-       0,     0,    37,    48,     0,    49,    38,    39,    40,    41,
-      42,    43,    35,    36,    44,     0,    37,    46,     0,    35,
-      36,     0,     0,    48,     0,    49,    35,   179,     0,    45,
-       0,    46,     0,     0,     0,     0,    37,    48,     0,    49,
-       0,     0,     0,    37,    35,    36,     0,     0,     0,    82,
-      37,    46,     0,   178,    35,    36,     0,    84,    46,    49,
-     180,    35,    36,     0,    84,    46,    49,     0,    37,     0,
-       0,    84,     0,    49,     0,     0,     0,     0,    37,    35,
-      36,     0,     0,    46,     0,    37,     0,     0,   186,    84,
-       0,    49,     0,    46,     0,   220,     0,     0,    58,    84,
-      46,    49,     0,    37,     0,     0,    84,     0,    49,   164,
-     165,   166,   167,   168,   169,   170,   171,   172,    46,     0,
-       0,     0,     0,     0,    84,     0,    49,   163,   164,   165,
-     166,   167,   168,   169,   170,   171,   172,   165,   166,   167,
-     168,   169,   170,   171,   172
-};
-
-static const yytype_int16 yycheck[] =
-{
-      10,    10,    13,    13,     6,    13,    68,     9,    11,    10,
-      12,    20,    10,    21,    22,    37,    38,    10,    10,     8,
-      82,     9,   108,   109,     0,    35,    36,    16,    17,    18,
-      19,     8,     9,     6,    23,     8,     9,    34,    48,    49,
-      37,    38,    37,    38,    32,    47,    51,    44,    58,    44,
-       8,     9,    10,    11,    12,    58,     8,     9,    67,    69,
-      69,    54,    54,     8,     9,    48,    67,    50,    69,    49,
-      45,    69,    83,    83,    84,    49,    78,   163,   164,   165,
-      32,    52,   168,   169,   170,   171,   172,    32,    14,    15,
-      42,    43,    53,    45,   156,    47,    50,    53,   108,   109,
-      45,    53,    47,    55,   114,   115,    51,    52,    53,    33,
-      55,    35,    10,    11,    12,   125,    51,    51,   128,    51,
-      44,    11,   208,   209,    53,    53,    51,     7,    51,   139,
-     132,   142,   142,    51,   144,   145,    51,   145,    51,    51,
-      51,    51,    51,    51,   133,   147,   148,   149,   150,   151,
-     160,    53,    37,   163,   164,   165,    34,   146,   168,   169,
-     170,   171,   172,   152,     8,     9,    10,    54,     6,   179,
-      53,     3,     4,     5,     6,     7,     8,     9,    10,    11,
-      12,    36,    37,    38,    39,    40,    41,     7,    32,    44,
-      54,    10,    36,    37,    38,    39,    40,    41,   208,   209,
-      44,    45,    54,    47,    54,   215,   216,    51,    54,    53,
-      51,    55,     1,    53,    51,   223,    51,    48,    48,    37,
-     228,   231,    54,   232,    13,    14,    15,    16,    17,    18,
-      19,    20,    21,    22,    23,    24,    25,    26,    27,    28,
-      29,    30,    31,   253,     8,     9,     6,     7,     8,     9,
-      10,    11,    12,   263,   264,    51,    45,    51,    47,    54,
-      49,    54,    53,    32,     8,     9,    54,     9,    32,    52,
-      37,    10,    36,    37,    38,    39,    40,    41,     8,     9,
-      44,    45,    38,    47,    35,     9,    54,    51,    32,    53,
-      10,    55,    36,    37,    38,    39,    40,    41,     8,     9,
-      44,    45,    32,    47,    54,    32,    54,    37,    52,    53,
-      10,    55,    69,    32,    44,    12,    54,    47,     8,     9,
-      10,    54,    32,    53,   153,    55,    36,    37,    38,    39,
-      40,    41,    54,    12,    44,    45,    -1,    47,     8,     9,
-     246,    51,    32,    53,    -1,    55,    36,    37,    38,    39,
-      40,    41,    -1,    -1,    44,    45,    -1,    47,     8,     9,
-      -1,    -1,    32,    53,    -1,    55,    36,    37,    38,    39,
-      40,    41,     8,     9,    44,    45,    -1,    47,    -1,    -1,
-      -1,    -1,    32,    53,    -1,    55,    36,    37,    38,    39,
-      40,    41,     8,     9,    44,    -1,    32,    47,    -1,     8,
-       9,    -1,    -1,    53,    -1,    55,     8,     9,    -1,    45,
-      -1,    47,    -1,    -1,    -1,    -1,    32,    53,    -1,    55,
-      -1,    -1,    -1,    32,     8,     9,    -1,    -1,    -1,    45,
-      32,    47,    -1,    42,     8,     9,    -1,    53,    47,    55,
-      42,     8,     9,    -1,    53,    47,    55,    -1,    32,    -1,
-      -1,    53,    -1,    55,    -1,    -1,    -1,    -1,    32,     8,
-       9,    -1,    -1,    47,    -1,    32,    -1,    -1,    52,    53,
-      -1,    55,    -1,    47,    -1,    42,    -1,    -1,    52,    53,
-      47,    55,    -1,    32,    -1,    -1,    53,    -1,    55,     4,
-       5,     6,     7,     8,     9,    10,    11,    12,    47,    -1,
-      -1,    -1,    -1,    -1,    53,    -1,    55,     3,     4,     5,
-       6,     7,     8,     9,    10,    11,    12,     5,     6,     7,
-       8,     9,    10,    11,    12
-};
-
-/* YYSTOS[STATE-NUM] -- The (internal number of the) accessing
-   symbol of state STATE-NUM.  */
-static const yytype_uint8 yystos[] =
-{
-       0,    57,     0,    58,     1,    13,    14,    15,    16,    17,
-      18,    19,    20,    21,    22,    23,    24,    25,    26,    27,
-      28,    29,    30,    31,    45,    47,    49,    59,    61,    68,
-      69,    70,    49,    51,    62,     8,     9,    32,    36,    37,
-      38,    39,    40,    41,    44,    45,    47,    51,    53,    55,
-      66,    81,    85,    87,    88,    89,    90,    93,    52,    65,
-      81,    83,    86,    63,    83,    64,    81,    10,    45,    51,
-      71,    82,    84,    85,    88,    89,    93,    90,    51,    62,
-      66,    72,    45,    51,    53,    67,    84,    86,    93,    87,
-      87,    79,    83,    73,    83,    74,    83,    75,    83,    76,
-      85,    77,    86,    78,    86,    80,    83,    48,    50,    50,
-      49,    93,    93,     6,     8,     9,    91,    81,    37,    44,
-      93,    95,    93,    53,    53,     9,    42,    43,    53,    90,
-      93,    51,    51,    51,    85,    88,    91,    82,    53,    11,
-      91,    84,    51,    53,    51,    51,    51,    51,    51,    51,
-      51,    51,    51,    60,    95,    95,     7,    93,    93,    53,
-      10,    54,    54,     3,     4,     5,     6,     7,     8,     9,
-      10,    11,    12,    54,    37,    37,    38,    44,    42,     9,
-      42,    81,    83,    34,    93,    84,    52,    93,    86,    93,
-      83,    81,    81,    81,    81,    81,    83,    59,    91,    33,
-      35,    44,    92,    93,    53,    95,    95,    95,     6,     7,
-      95,    95,    95,    95,    95,    10,    10,    54,    54,    54,
-      42,    54,    54,    51,     9,    32,    94,    51,    51,    48,
-      48,    51,    51,    53,    54,    54,    37,    95,    95,    93,
-      93,    53,    54,    86,    32,     9,    52,    86,    37,    38,
-      93,    85,    35,    10,    54,    54,    37,    38,     9,    32,
-      94,    54,    93,    10,    10,    32,    54,    93,    93,    54,
-      54
-};
-
-#define yyerrok                (yyerrstatus = 0)
-#define yyclearin      (yychar = YYEMPTY)
-#define YYEMPTY                (-2)
-#define YYEOF          0
-
-#define YYACCEPT       goto yyacceptlab
-#define YYABORT                goto yyabortlab
-#define YYERROR                goto yyerrorlab
-
-
-/* Like YYERROR except do call yyerror.  This remains here temporarily
-   to ease the transition to the new meaning of YYERROR, for GCC.
-   Once GCC version 2 has supplanted version 1, this can go.  */
-
-#define YYFAIL         goto yyerrlab
-
-#define YYRECOVERING()  (!!yyerrstatus)
-
-#define YYBACKUP(Token, Value)                                 \
-do                                                             \
-  if (yychar == YYEMPTY && yylen == 1)                         \
-    {                                                          \
-      yychar = (Token);                                                \
-      yylval = (Value);                                                \
-      yytoken = YYTRANSLATE (yychar);                          \
-      YYPOPSTACK (1);                                          \
-      goto yybackup;                                           \
-    }                                                          \
-  else                                                         \
-    {                                                          \
-      yyerror (YY_("syntax error: cannot back up")); \
-      YYERROR;                                                 \
-    }                                                          \
-while (YYID (0))
-
-
-#define YYTERROR       1
-#define YYERRCODE      256
-
-
-/* YYLLOC_DEFAULT -- Set CURRENT to span from RHS[1] to RHS[N].
-   If N is 0, then set CURRENT to the empty location which ends
-   the previous symbol: RHS[0] (always defined).  */
-
-#define YYRHSLOC(Rhs, K) ((Rhs)[K])
-#ifndef YYLLOC_DEFAULT
-# define YYLLOC_DEFAULT(Current, Rhs, N)                               \
-    do                                                                 \
-      if (YYID (N))                                                    \
-       {                                                               \
-         (Current).first_line   = YYRHSLOC (Rhs, 1).first_line;        \
-         (Current).first_column = YYRHSLOC (Rhs, 1).first_column;      \
-         (Current).last_line    = YYRHSLOC (Rhs, N).last_line;         \
-         (Current).last_column  = YYRHSLOC (Rhs, N).last_column;       \
-       }                                                               \
-      else                                                             \
-       {                                                               \
-         (Current).first_line   = (Current).last_line   =              \
-           YYRHSLOC (Rhs, 0).last_line;                                \
-         (Current).first_column = (Current).last_column =              \
-           YYRHSLOC (Rhs, 0).last_column;                              \
-       }                                                               \
-    while (YYID (0))
-#endif
-
-
-/* YY_LOCATION_PRINT -- Print the location on the stream.
-   This macro was not mandated originally: define only if we know
-   we won't break user code: when these are the locations we know.  */
-
-#ifndef YY_LOCATION_PRINT
-# if defined YYLTYPE_IS_TRIVIAL && YYLTYPE_IS_TRIVIAL
-#  define YY_LOCATION_PRINT(File, Loc)                 \
-     fprintf (File, "%d.%d-%d.%d",                     \
-             (Loc).first_line, (Loc).first_column,     \
-             (Loc).last_line,  (Loc).last_column)
-# else
-#  define YY_LOCATION_PRINT(File, Loc) ((void) 0)
-# endif
-#endif
-
-
-/* YYLEX -- calling `yylex' with the right arguments.  */
-
-#ifdef YYLEX_PARAM
-# define YYLEX yylex (YYLEX_PARAM)
-#else
-# define YYLEX yylex ()
-#endif
-
-/* Enable debugging if requested.  */
-#if YYDEBUG
-
-# ifndef YYFPRINTF
-#  include <stdio.h> /* INFRINGES ON USER NAME SPACE */
-#  define YYFPRINTF fprintf
-# endif
-
-# define YYDPRINTF(Args)                       \
-do {                                           \
-  if (yydebug)                                 \
-    YYFPRINTF Args;                            \
-} while (YYID (0))
-
-# define YY_SYMBOL_PRINT(Title, Type, Value, Location)                   \
-do {                                                                     \
-  if (yydebug)                                                           \
-    {                                                                    \
-      YYFPRINTF (stderr, "%s ", Title);                                          \
-      yy_symbol_print (stderr,                                           \
-                 Type, Value); \
-      YYFPRINTF (stderr, "\n");                                                  \
-    }                                                                    \
-} while (YYID (0))
-
-
-/*--------------------------------.
-| Print this symbol on YYOUTPUT.  |
-`--------------------------------*/
-
-/*ARGSUSED*/
-#if (defined __STDC__ || defined __C99__FUNC__ \
-     || defined __cplusplus || defined _MSC_VER)
-static void
-yy_symbol_value_print (FILE *yyoutput, int yytype, YYSTYPE const * const yyvaluep)
-#else
-static void
-yy_symbol_value_print (yyoutput, yytype, yyvaluep)
-    FILE *yyoutput;
-    int yytype;
-    YYSTYPE const * const yyvaluep;
-#endif
-{
-  if (!yyvaluep)
-    return;
-# ifdef YYPRINT
-  if (yytype < YYNTOKENS)
-    YYPRINT (yyoutput, yytoknum[yytype], *yyvaluep);
-# else
-  YYUSE (yyoutput);
-# endif
-  switch (yytype)
-    {
-      default:
-       break;
-    }
-}
-
-
-/*--------------------------------.
-| Print this symbol on YYOUTPUT.  |
-`--------------------------------*/
-
-#if (defined __STDC__ || defined __C99__FUNC__ \
-     || defined __cplusplus || defined _MSC_VER)
-static void
-yy_symbol_print (FILE *yyoutput, int yytype, YYSTYPE const * const yyvaluep)
-#else
-static void
-yy_symbol_print (yyoutput, yytype, yyvaluep)
-    FILE *yyoutput;
-    int yytype;
-    YYSTYPE const * const yyvaluep;
-#endif
-{
-  if (yytype < YYNTOKENS)
-    YYFPRINTF (yyoutput, "token %s (", yytname[yytype]);
-  else
-    YYFPRINTF (yyoutput, "nterm %s (", yytname[yytype]);
-
-  yy_symbol_value_print (yyoutput, yytype, yyvaluep);
-  YYFPRINTF (yyoutput, ")");
-}
-
-/*------------------------------------------------------------------.
-| yy_stack_print -- Print the state stack from its BOTTOM up to its |
-| TOP (included).                                                   |
-`------------------------------------------------------------------*/
-
-#if (defined __STDC__ || defined __C99__FUNC__ \
-     || defined __cplusplus || defined _MSC_VER)
-static void
-yy_stack_print (yytype_int16 *bottom, yytype_int16 *top)
-#else
-static void
-yy_stack_print (bottom, top)
-    yytype_int16 *bottom;
-    yytype_int16 *top;
-#endif
-{
-  YYFPRINTF (stderr, "Stack now");
-  for (; bottom <= top; ++bottom)
-    YYFPRINTF (stderr, " %d", *bottom);
-  YYFPRINTF (stderr, "\n");
-}
-
-# define YY_STACK_PRINT(Bottom, Top)                           \
-do {                                                           \
-  if (yydebug)                                                 \
-    yy_stack_print ((Bottom), (Top));                          \
-} while (YYID (0))
-
-
-/*------------------------------------------------.
-| Report that the YYRULE is going to be reduced.  |
-`------------------------------------------------*/
-
-#if (defined __STDC__ || defined __C99__FUNC__ \
-     || defined __cplusplus || defined _MSC_VER)
-static void
-yy_reduce_print (YYSTYPE *yyvsp, int yyrule)
-#else
-static void
-yy_reduce_print (yyvsp, yyrule)
-    YYSTYPE *yyvsp;
-    int yyrule;
-#endif
-{
-  int yynrhs = yyr2[yyrule];
-  int yyi;
-  unsigned long int yylno = yyrline[yyrule];
-  YYFPRINTF (stderr, "Reducing stack by rule %d (line %lu):\n",
-            yyrule - 1, yylno);
-  /* The symbols being reduced.  */
-  for (yyi = 0; yyi < yynrhs; yyi++)
-    {
-      fprintf (stderr, "   $%d = ", yyi + 1);
-      yy_symbol_print (stderr, yyrhs[yyprhs[yyrule] + yyi],
-                      &(yyvsp[(yyi + 1) - (yynrhs)])
-                                      );
-      fprintf (stderr, "\n");
-    }
-}
-
-# define YY_REDUCE_PRINT(Rule)         \
-do {                                   \
-  if (yydebug)                         \
-    yy_reduce_print (yyvsp, Rule); \
-} while (YYID (0))
-
-/* Nonzero means print parse trace.  It is left uninitialized so that
-   multiple parsers can coexist.  */
-int yydebug;
-#else /* !YYDEBUG */
-# define YYDPRINTF(Args)
-# define YY_SYMBOL_PRINT(Title, Type, Value, Location)
-# define YY_STACK_PRINT(Bottom, Top)
-# define YY_REDUCE_PRINT(Rule)
-#endif /* !YYDEBUG */
-
-
-/* YYINITDEPTH -- initial size of the parser's stacks.  */
-#ifndef        YYINITDEPTH
-# define YYINITDEPTH 200
-#endif
-
-/* YYMAXDEPTH -- maximum size the stacks can grow to (effective only
-   if the built-in stack extension method is used).
-
-   Do not make this value too large; the results are undefined if
-   YYSTACK_ALLOC_MAXIMUM < YYSTACK_BYTES (YYMAXDEPTH)
-   evaluated with infinite-precision integer arithmetic.  */
-
-#ifndef YYMAXDEPTH
-# define YYMAXDEPTH 10000
-#endif
-
-\f
-
-#if YYERROR_VERBOSE
-
-# ifndef yystrlen
-#  if defined __GLIBC__ && defined _STRING_H
-#   define yystrlen strlen
-#  else
-/* Return the length of YYSTR.  */
-#if (defined __STDC__ || defined __C99__FUNC__ \
-     || defined __cplusplus || defined _MSC_VER)
-static YYSIZE_T
-yystrlen (const char *yystr)
-#else
-static YYSIZE_T
-yystrlen (yystr)
-    const char *yystr;
-#endif
-{
-  YYSIZE_T yylen;
-  for (yylen = 0; yystr[yylen]; yylen++)
-    continue;
-  return yylen;
-}
-#  endif
-# endif
-
-# ifndef yystpcpy
-#  if defined __GLIBC__ && defined _STRING_H && defined _GNU_SOURCE
-#   define yystpcpy stpcpy
-#  else
-/* Copy YYSRC to YYDEST, returning the address of the terminating '\0' in
-   YYDEST.  */
-#if (defined __STDC__ || defined __C99__FUNC__ \
-     || defined __cplusplus || defined _MSC_VER)
-static char *
-yystpcpy (char *yydest, const char *yysrc)
-#else
-static char *
-yystpcpy (yydest, yysrc)
-    char *yydest;
-    const char *yysrc;
-#endif
-{
-  char *yyd = yydest;
-  const char *yys = yysrc;
-
-  while ((*yyd++ = *yys++) != '\0')
-    continue;
-
-  return yyd - 1;
-}
-#  endif
-# endif
-
-# ifndef yytnamerr
-/* Copy to YYRES the contents of YYSTR after stripping away unnecessary
-   quotes and backslashes, so that it's suitable for yyerror.  The
-   heuristic is that double-quoting is unnecessary unless the string
-   contains an apostrophe, a comma, or backslash (other than
-   backslash-backslash).  YYSTR is taken from yytname.  If YYRES is
-   null, do not copy; instead, return the length of what the result
-   would have been.  */
-static YYSIZE_T
-yytnamerr (char *yyres, const char *yystr)
-{
-  if (*yystr == '"')
-    {
-      YYSIZE_T yyn = 0;
-      char const *yyp = yystr;
-
-      for (;;)
-       switch (*++yyp)
-         {
-         case '\'':
-         case ',':
-           goto do_not_strip_quotes;
-
-         case '\\':
-           if (*++yyp != '\\')
-             goto do_not_strip_quotes;
-           /* Fall through.  */
-         default:
-           if (yyres)
-             yyres[yyn] = *yyp;
-           yyn++;
-           break;
-
-         case '"':
-           if (yyres)
-             yyres[yyn] = '\0';
-           return yyn;
-         }
-    do_not_strip_quotes: ;
-    }
-
-  if (! yyres)
-    return yystrlen (yystr);
-
-  return yystpcpy (yyres, yystr) - yyres;
-}
-# endif
-
-/* Copy into YYRESULT an error message about the unexpected token
-   YYCHAR while in state YYSTATE.  Return the number of bytes copied,
-   including the terminating null byte.  If YYRESULT is null, do not
-   copy anything; just return the number of bytes that would be
-   copied.  As a special case, return 0 if an ordinary "syntax error"
-   message will do.  Return YYSIZE_MAXIMUM if overflow occurs during
-   size calculation.  */
-static YYSIZE_T
-yysyntax_error (char *yyresult, int yystate, int yychar)
-{
-  int yyn = yypact[yystate];
-
-  if (! (YYPACT_NINF < yyn && yyn <= YYLAST))
-    return 0;
-  else
-    {
-      int yytype = YYTRANSLATE (yychar);
-      YYSIZE_T yysize0 = yytnamerr (0, yytname[yytype]);
-      YYSIZE_T yysize = yysize0;
-      YYSIZE_T yysize1;
-      int yysize_overflow = 0;
-      enum { YYERROR_VERBOSE_ARGS_MAXIMUM = 5 };
-      char const *yyarg[YYERROR_VERBOSE_ARGS_MAXIMUM];
-      int yyx;
-
-# if 0
-      /* This is so xgettext sees the translatable formats that are
-        constructed on the fly.  */
-      YY_("syntax error, unexpected %s");
-      YY_("syntax error, unexpected %s, expecting %s");
-      YY_("syntax error, unexpected %s, expecting %s or %s");
-      YY_("syntax error, unexpected %s, expecting %s or %s or %s");
-      YY_("syntax error, unexpected %s, expecting %s or %s or %s or %s");
-# endif
-      char *yyfmt;
-      char const *yyf;
-      static char const yyunexpected[] = "syntax error, unexpected %s";
-      static char const yyexpecting[] = ", expecting %s";
-      static char const yyor[] = " or %s";
-      char yyformat[sizeof yyunexpected
-                   + sizeof yyexpecting - 1
-                   + ((YYERROR_VERBOSE_ARGS_MAXIMUM - 2)
-                      * (sizeof yyor - 1))];
-      char const *yyprefix = yyexpecting;
-
-      /* Start YYX at -YYN if negative to avoid negative indexes in
-        YYCHECK.  */
-      int yyxbegin = yyn < 0 ? -yyn : 0;
-
-      /* Stay within bounds of both yycheck and yytname.  */
-      int yychecklim = YYLAST - yyn + 1;
-      int yyxend = yychecklim < YYNTOKENS ? yychecklim : YYNTOKENS;
-      int yycount = 1;
-
-      yyarg[0] = yytname[yytype];
-      yyfmt = yystpcpy (yyformat, yyunexpected);
-
-      for (yyx = yyxbegin; yyx < yyxend; ++yyx)
-       if (yycheck[yyx + yyn] == yyx && yyx != YYTERROR)
-         {
-           if (yycount == YYERROR_VERBOSE_ARGS_MAXIMUM)
-             {
-               yycount = 1;
-               yysize = yysize0;
-               yyformat[sizeof yyunexpected - 1] = '\0';
-               break;
-             }
-           yyarg[yycount++] = yytname[yyx];
-           yysize1 = yysize + yytnamerr (0, yytname[yyx]);
-           yysize_overflow |= (yysize1 < yysize);
-           yysize = yysize1;
-           yyfmt = yystpcpy (yyfmt, yyprefix);
-           yyprefix = yyor;
-         }
-
-      yyf = YY_(yyformat);
-      yysize1 = yysize + yystrlen (yyf);
-      yysize_overflow |= (yysize1 < yysize);
-      yysize = yysize1;
-
-      if (yysize_overflow)
-       return YYSIZE_MAXIMUM;
-
-      if (yyresult)
-       {
-         /* Avoid sprintf, as that infringes on the user's name space.
-            Don't have undefined behavior even if the translation
-            produced a string with the wrong number of "%s"s.  */
-         char *yyp = yyresult;
-         int yyi = 0;
-         while ((*yyp = *yyf) != '\0')
-           {
-             if (*yyp == '%' && yyf[1] == 's' && yyi < yycount)
-               {
-                 yyp += yytnamerr (yyp, yyarg[yyi++]);
-                 yyf += 2;
-               }
-             else
-               {
-                 yyp++;
-                 yyf++;
-               }
-           }
-       }
-      return yysize;
-    }
-}
-#endif /* YYERROR_VERBOSE */
-\f
-
-/*-----------------------------------------------.
-| Release the memory associated to this symbol.  |
-`-----------------------------------------------*/
-
-/*ARGSUSED*/
-#if (defined __STDC__ || defined __C99__FUNC__ \
-     || defined __cplusplus || defined _MSC_VER)
-static void
-yydestruct (const char *yymsg, int yytype, YYSTYPE *yyvaluep)
-#else
-static void
-yydestruct (yymsg, yytype, yyvaluep)
-    const char *yymsg;
-    int yytype;
-    YYSTYPE *yyvaluep;
-#endif
-{
-  YYUSE (yyvaluep);
-
-  if (!yymsg)
-    yymsg = "Deleting";
-  YY_SYMBOL_PRINT (yymsg, yytype, yyvaluep, yylocationp);
-
-  switch (yytype)
-    {
-
-      default:
-       break;
-    }
-}
-\f
-
-/* Prevent warnings from -Wmissing-prototypes.  */
-
-#ifdef YYPARSE_PARAM
-#if defined __STDC__ || defined __cplusplus
-int yyparse (void *YYPARSE_PARAM);
-#else
-int yyparse ();
-#endif
-#else /* ! YYPARSE_PARAM */
-#if defined __STDC__ || defined __cplusplus
-int yyparse (void);
-#else
-int yyparse ();
-#endif
-#endif /* ! YYPARSE_PARAM */
-
-
-
-/* The look-ahead symbol.  */
-int yychar;
-
-/* The semantic value of the look-ahead symbol.  */
-YYSTYPE yylval;
-
-/* Number of syntax errors so far.  */
-int yynerrs;
-
-
-
-/*----------.
-| yyparse.  |
-`----------*/
-
-#ifdef YYPARSE_PARAM
-#if (defined __STDC__ || defined __C99__FUNC__ \
-     || defined __cplusplus || defined _MSC_VER)
-int
-yyparse (void *YYPARSE_PARAM)
-#else
-int
-yyparse (YYPARSE_PARAM)
-    void *YYPARSE_PARAM;
-#endif
-#else /* ! YYPARSE_PARAM */
-#if (defined __STDC__ || defined __C99__FUNC__ \
-     || defined __cplusplus || defined _MSC_VER)
-int
-yyparse (void)
-#else
-int
-yyparse ()
-
-#endif
-#endif
-{
-  
-  int yystate;
-  int yyn;
-  int yyresult;
-  /* Number of tokens to shift before error messages enabled.  */
-  int yyerrstatus;
-  /* Look-ahead token as an internal (translated) token number.  */
-  int yytoken = 0;
-#if YYERROR_VERBOSE
-  /* Buffer for error messages, and its allocated size.  */
-  char yymsgbuf[128];
-  char *yymsg = yymsgbuf;
-  YYSIZE_T yymsg_alloc = sizeof yymsgbuf;
-#endif
-
-  /* Three stacks and their tools:
-     `yyss': related to states,
-     `yyvs': related to semantic values,
-     `yyls': related to locations.
-
-     Refer to the stacks thru separate pointers, to allow yyoverflow
-     to reallocate them elsewhere.  */
-
-  /* The state stack.  */
-  yytype_int16 yyssa[YYINITDEPTH];
-  yytype_int16 *yyss = yyssa;
-  yytype_int16 *yyssp;
-
-  /* The semantic value stack.  */
-  YYSTYPE yyvsa[YYINITDEPTH];
-  YYSTYPE *yyvs = yyvsa;
-  YYSTYPE *yyvsp;
-
-
-
-#define YYPOPSTACK(N)   (yyvsp -= (N), yyssp -= (N))
-
-  YYSIZE_T yystacksize = YYINITDEPTH;
-
-  /* The variables used to return semantic value and location from the
-     action routines.  */
-  YYSTYPE yyval;
-
-
-  /* The number of symbols on the RHS of the reduced rule.
-     Keep to zero when no symbol should be popped.  */
-  int yylen = 0;
-
-  YYDPRINTF ((stderr, "Starting parse\n"));
-
-  yystate = 0;
-  yyerrstatus = 0;
-  yynerrs = 0;
-  yychar = YYEMPTY;            /* Cause a token to be read.  */
-
-  /* Initialize stack pointers.
-     Waste one element of value and location stack
-     so that they stay on the same level as the state stack.
-     The wasted elements are never initialized.  */
-
-  yyssp = yyss;
-  yyvsp = yyvs;
-
-  goto yysetstate;
-
-/*------------------------------------------------------------.
-| yynewstate -- Push a new state, which is found in yystate.  |
-`------------------------------------------------------------*/
- yynewstate:
-  /* In all cases, when you get here, the value and location stacks
-     have just been pushed.  So pushing a state here evens the stacks.  */
-  yyssp++;
-
- yysetstate:
-  *yyssp = yystate;
-
-  if (yyss + yystacksize - 1 <= yyssp)
-    {
-      /* Get the current used size of the three stacks, in elements.  */
-      YYSIZE_T yysize = yyssp - yyss + 1;
-
-#ifdef yyoverflow
-      {
-       /* Give user a chance to reallocate the stack.  Use copies of
-          these so that the &'s don't force the real ones into
-          memory.  */
-       YYSTYPE *yyvs1 = yyvs;
-       yytype_int16 *yyss1 = yyss;
-
-
-       /* Each stack pointer address is followed by the size of the
-          data in use in that stack, in bytes.  This used to be a
-          conditional around just the two extra args, but that might
-          be undefined if yyoverflow is a macro.  */
-       yyoverflow (YY_("memory exhausted"),
-                   &yyss1, yysize * sizeof (*yyssp),
-                   &yyvs1, yysize * sizeof (*yyvsp),
-
-                   &yystacksize);
-
-       yyss = yyss1;
-       yyvs = yyvs1;
-      }
-#else /* no yyoverflow */
-# ifndef YYSTACK_RELOCATE
-      goto yyexhaustedlab;
-# else
-      /* Extend the stack our own way.  */
-      if (YYMAXDEPTH <= yystacksize)
-       goto yyexhaustedlab;
-      yystacksize *= 2;
-      if (YYMAXDEPTH < yystacksize)
-       yystacksize = YYMAXDEPTH;
-
-      {
-       yytype_int16 *yyss1 = yyss;
-       union yyalloc *yyptr =
-         (union yyalloc *) YYSTACK_ALLOC (YYSTACK_BYTES (yystacksize));
-       if (! yyptr)
-         goto yyexhaustedlab;
-       YYSTACK_RELOCATE (yyss);
-       YYSTACK_RELOCATE (yyvs);
-
-#  undef YYSTACK_RELOCATE
-       if (yyss1 != yyssa)
-         YYSTACK_FREE (yyss1);
-      }
-# endif
-#endif /* no yyoverflow */
-
-      yyssp = yyss + yysize - 1;
-      yyvsp = yyvs + yysize - 1;
-
-
-      YYDPRINTF ((stderr, "Stack size increased to %lu\n",
-                 (unsigned long int) yystacksize));
-
-      if (yyss + yystacksize - 1 <= yyssp)
-       YYABORT;
-    }
-
-  YYDPRINTF ((stderr, "Entering state %d\n", yystate));
-
-  goto yybackup;
-
-/*-----------.
-| yybackup.  |
-`-----------*/
-yybackup:
-
-  /* Do appropriate processing given the current state.  Read a
-     look-ahead token if we need one and don't already have one.  */
-
-  /* First try to decide what to do without reference to look-ahead token.  */
-  yyn = yypact[yystate];
-  if (yyn == YYPACT_NINF)
-    goto yydefault;
-
-  /* Not known => get a look-ahead token if don't already have one.  */
-
-  /* YYCHAR is either YYEMPTY or YYEOF or a valid look-ahead symbol.  */
-  if (yychar == YYEMPTY)
-    {
-      YYDPRINTF ((stderr, "Reading a token: "));
-      yychar = YYLEX;
-    }
-
-  if (yychar <= YYEOF)
-    {
-      yychar = yytoken = YYEOF;
-      YYDPRINTF ((stderr, "Now at end of input.\n"));
-    }
-  else
-    {
-      yytoken = YYTRANSLATE (yychar);
-      YY_SYMBOL_PRINT ("Next token is", yytoken, &yylval, &yylloc);
-    }
-
-  /* If the proper action on seeing token YYTOKEN is to reduce or to
-     detect an error, take that action.  */
-  yyn += yytoken;
-  if (yyn < 0 || YYLAST < yyn || yycheck[yyn] != yytoken)
-    goto yydefault;
-  yyn = yytable[yyn];
-  if (yyn <= 0)
-    {
-      if (yyn == 0 || yyn == YYTABLE_NINF)
-       goto yyerrlab;
-      yyn = -yyn;
-      goto yyreduce;
-    }
-
-  if (yyn == YYFINAL)
-    YYACCEPT;
-
-  /* Count tokens shifted since error; after three, turn off error
-     status.  */
-  if (yyerrstatus)
-    yyerrstatus--;
-
-  /* Shift the look-ahead token.  */
-  YY_SYMBOL_PRINT ("Shifting", yytoken, &yylval, &yylloc);
-
-  /* Discard the shifted token unless it is eof.  */
-  if (yychar != YYEOF)
-    yychar = YYEMPTY;
-
-  yystate = yyn;
-  *++yyvsp = yylval;
-
-  goto yynewstate;
-
-
-/*-----------------------------------------------------------.
-| yydefault -- do the default action for the current state.  |
-`-----------------------------------------------------------*/
-yydefault:
-  yyn = yydefact[yystate];
-  if (yyn == 0)
-    goto yyerrlab;
-  goto yyreduce;
-
-
-/*-----------------------------.
-| yyreduce -- Do a reduction.  |
-`-----------------------------*/
-yyreduce:
-  /* yyn is the number of a rule to reduce with.  */
-  yylen = yyr2[yyn];
-
-  /* If YYLEN is nonzero, implement the default value of the action:
-     `$$ = $1'.
-
-     Otherwise, the following line sets YYVAL to garbage.
-     This behavior is undocumented and Bison
-     users should not rely upon it.  Assigning to YYVAL
-     unconditionally makes the parser a bit smaller, and it avoids a
-     GCC warning that YYVAL may be used uninitialized.  */
-  yyval = yyvsp[1-yylen];
-
-
-  YY_REDUCE_PRINT (yyn);
-  switch (yyn)
-    {
-        case 3:
-#line 68 "a.y"
-    {
-               stmtline = lineno;
-       }
-    break;
-
-  case 5:
-#line 75 "a.y"
-    {
-               (yyvsp[(1) - (2)].sym) = labellookup((yyvsp[(1) - (2)].sym));
-               if((yyvsp[(1) - (2)].sym)->type == LLAB && (yyvsp[(1) - (2)].sym)->value != pc)
-                       yyerror("redeclaration of %s (%s)", (yyvsp[(1) - (2)].sym)->labelname, (yyvsp[(1) - (2)].sym)->name);
-               (yyvsp[(1) - (2)].sym)->type = LLAB;
-               (yyvsp[(1) - (2)].sym)->value = pc;
-       }
-    break;
-
-  case 10:
-#line 89 "a.y"
-    {
-               (yyvsp[(1) - (3)].sym)->type = LVAR;
-               (yyvsp[(1) - (3)].sym)->value = (yyvsp[(3) - (3)].lval);
-       }
-    break;
-
-  case 11:
-#line 94 "a.y"
-    {
-               if((yyvsp[(1) - (3)].sym)->value != (yyvsp[(3) - (3)].lval))
-                       yyerror("redeclaration of %s", (yyvsp[(1) - (3)].sym)->name);
-               (yyvsp[(1) - (3)].sym)->value = (yyvsp[(3) - (3)].lval);
-       }
-    break;
-
-  case 12:
-#line 99 "a.y"
-    { outcode((yyvsp[(1) - (2)].lval), &(yyvsp[(2) - (2)].addr2)); }
-    break;
-
-  case 13:
-#line 100 "a.y"
-    { outcode((yyvsp[(1) - (2)].lval), &(yyvsp[(2) - (2)].addr2)); }
-    break;
-
-  case 14:
-#line 101 "a.y"
-    { outcode((yyvsp[(1) - (2)].lval), &(yyvsp[(2) - (2)].addr2)); }
-    break;
-
-  case 15:
-#line 102 "a.y"
-    { outcode((yyvsp[(1) - (2)].lval), &(yyvsp[(2) - (2)].addr2)); }
-    break;
-
-  case 16:
-#line 103 "a.y"
-    { outcode((yyvsp[(1) - (2)].lval), &(yyvsp[(2) - (2)].addr2)); }
-    break;
-
-  case 17:
-#line 104 "a.y"
-    { outcode((yyvsp[(1) - (2)].lval), &(yyvsp[(2) - (2)].addr2)); }
-    break;
-
-  case 20:
-#line 107 "a.y"
-    { outcode((yyvsp[(1) - (2)].lval), &(yyvsp[(2) - (2)].addr2)); }
-    break;
-
-  case 21:
-#line 108 "a.y"
-    { outcode((yyvsp[(1) - (2)].lval), &(yyvsp[(2) - (2)].addr2)); }
-    break;
-
-  case 22:
-#line 109 "a.y"
-    { outcode((yyvsp[(1) - (2)].lval), &(yyvsp[(2) - (2)].addr2)); }
-    break;
-
-  case 23:
-#line 110 "a.y"
-    { outcode((yyvsp[(1) - (2)].lval), &(yyvsp[(2) - (2)].addr2)); }
-    break;
-
-  case 24:
-#line 111 "a.y"
-    { outcode((yyvsp[(1) - (2)].lval), &(yyvsp[(2) - (2)].addr2)); }
-    break;
-
-  case 25:
-#line 112 "a.y"
-    { outcode((yyvsp[(1) - (2)].lval), &(yyvsp[(2) - (2)].addr2)); }
-    break;
-
-  case 26:
-#line 113 "a.y"
-    { outcode((yyvsp[(1) - (2)].lval), &(yyvsp[(2) - (2)].addr2)); }
-    break;
-
-  case 27:
-#line 114 "a.y"
-    { outcode((yyvsp[(1) - (2)].lval), &(yyvsp[(2) - (2)].addr2)); }
-    break;
-
-  case 29:
-#line 116 "a.y"
-    { outcode((yyvsp[(1) - (2)].lval), &(yyvsp[(2) - (2)].addr2)); }
-    break;
-
-  case 30:
-#line 117 "a.y"
-    { outcode((yyvsp[(1) - (2)].lval), &(yyvsp[(2) - (2)].addr2)); }
-    break;
-
-  case 31:
-#line 120 "a.y"
-    {
-               (yyval.addr2).from = nullgen;
-               (yyval.addr2).to = nullgen;
-       }
-    break;
-
-  case 32:
-#line 125 "a.y"
-    {
-               (yyval.addr2).from = nullgen;
-               (yyval.addr2).to = nullgen;
-       }
-    break;
-
-  case 33:
-#line 132 "a.y"
-    {
-               (yyval.addr2).from = (yyvsp[(1) - (3)].addr);
-               (yyval.addr2).to = (yyvsp[(3) - (3)].addr);
-       }
-    break;
-
-  case 34:
-#line 139 "a.y"
-    {
-               (yyval.addr2).from = (yyvsp[(1) - (3)].addr);
-               (yyval.addr2).to = (yyvsp[(3) - (3)].addr);
-       }
-    break;
-
-  case 35:
-#line 146 "a.y"
-    {
-               (yyval.addr2).from = (yyvsp[(1) - (2)].addr);
-               (yyval.addr2).to = nullgen;
-       }
-    break;
-
-  case 36:
-#line 151 "a.y"
-    {
-               (yyval.addr2).from = (yyvsp[(1) - (1)].addr);
-               (yyval.addr2).to = nullgen;
-       }
-    break;
-
-  case 37:
-#line 158 "a.y"
-    {
-               (yyval.addr2).from = nullgen;
-               (yyval.addr2).to = (yyvsp[(2) - (2)].addr);
-       }
-    break;
-
-  case 38:
-#line 163 "a.y"
-    {
-               (yyval.addr2).from = nullgen;
-               (yyval.addr2).to = (yyvsp[(1) - (1)].addr);
-       }
-    break;
-
-  case 39:
-#line 170 "a.y"
-    {
-               (yyval.addr2).from = nullgen;
-               (yyval.addr2).to = (yyvsp[(2) - (2)].addr);
-       }
-    break;
-
-  case 40:
-#line 175 "a.y"
-    {
-               (yyval.addr2).from = nullgen;
-               (yyval.addr2).to = (yyvsp[(1) - (1)].addr);
-       }
-    break;
-
-  case 41:
-#line 180 "a.y"
-    {
-               (yyval.addr2).from = (yyvsp[(1) - (3)].addr);
-               (yyval.addr2).to = (yyvsp[(3) - (3)].addr);
-       }
-    break;
-
-  case 42:
-#line 187 "a.y"
-    {
-               Addr2 a;
-               a.from = (yyvsp[(2) - (6)].addr);
-               a.to = (yyvsp[(6) - (6)].addr);
-               outcode(ADATA, &a);
-               if(pass > 1) {
-                       lastpc->from3.type = TYPE_CONST;
-                       lastpc->from3.offset = (yyvsp[(4) - (6)].lval);
-               }
-       }
-    break;
-
-  case 43:
-#line 200 "a.y"
-    {
-               Addr2 a;
-               settext((yyvsp[(2) - (5)].addr).sym);
-               a.from = (yyvsp[(2) - (5)].addr);
-               a.to = (yyvsp[(5) - (5)].addr);
-               outcode(ATEXT, &a);
-       }
-    break;
-
-  case 44:
-#line 208 "a.y"
-    {
-               Addr2 a;
-               settext((yyvsp[(2) - (7)].addr).sym);
-               a.from = (yyvsp[(2) - (7)].addr);
-               a.to = (yyvsp[(7) - (7)].addr);
-               outcode(ATEXT, &a);
-               if(pass > 1) {
-                       lastpc->from3.type = TYPE_CONST;
-                       lastpc->from3.offset = (yyvsp[(4) - (7)].lval);
-               }
-       }
-    break;
-
-  case 45:
-#line 222 "a.y"
-    {
-               Addr2 a;
-               settext((yyvsp[(2) - (4)].addr).sym);
-               a.from = (yyvsp[(2) - (4)].addr);
-               a.to = (yyvsp[(4) - (4)].addr);
-               outcode(AGLOBL, &a);
-       }
-    break;
-
-  case 46:
-#line 230 "a.y"
-    {
-               Addr2 a;
-               settext((yyvsp[(2) - (6)].addr).sym);
-               a.from = (yyvsp[(2) - (6)].addr);
-               a.to = (yyvsp[(6) - (6)].addr);
-               outcode(AGLOBL, &a);
-               if(pass > 1) {
-                       lastpc->from3.type = TYPE_CONST;
-                       lastpc->from3.offset = (yyvsp[(4) - (6)].lval);
-               }
-       }
-    break;
-
-  case 47:
-#line 244 "a.y"
-    {
-               (yyval.addr2).from = nullgen;
-               (yyval.addr2).to = (yyvsp[(2) - (2)].addr);
-       }
-    break;
-
-  case 48:
-#line 249 "a.y"
-    {
-               (yyval.addr2).from = nullgen;
-               (yyval.addr2).to = (yyvsp[(1) - (1)].addr);
-       }
-    break;
-
-  case 51:
-#line 260 "a.y"
-    {
-               (yyval.addr2).from = (yyvsp[(1) - (3)].addr);
-               (yyval.addr2).to = (yyvsp[(3) - (3)].addr);
-       }
-    break;
-
-  case 52:
-#line 265 "a.y"
-    {
-               (yyval.addr2).from = (yyvsp[(1) - (5)].addr);
-               (yyval.addr2).to = (yyvsp[(3) - (5)].addr);
-               if((yyval.addr2).from.index != TYPE_NONE)
-                       yyerror("dp shift with lhs index");
-               (yyval.addr2).from.index = (yyvsp[(5) - (5)].lval);
-       }
-    break;
-
-  case 53:
-#line 275 "a.y"
-    {
-               (yyval.addr2).from = (yyvsp[(1) - (3)].addr);
-               (yyval.addr2).to = (yyvsp[(3) - (3)].addr);
-       }
-    break;
-
-  case 54:
-#line 280 "a.y"
-    {
-               (yyval.addr2).from = (yyvsp[(1) - (5)].addr);
-               (yyval.addr2).to = (yyvsp[(3) - (5)].addr);
-               if((yyval.addr2).to.index != TYPE_NONE)
-                       yyerror("dp move with lhs index");
-               (yyval.addr2).to.index = (yyvsp[(5) - (5)].lval);
-       }
-    break;
-
-  case 55:
-#line 290 "a.y"
-    {
-               (yyval.addr2).from = (yyvsp[(1) - (2)].addr);
-               (yyval.addr2).to = nullgen;
-       }
-    break;
-
-  case 56:
-#line 295 "a.y"
-    {
-               (yyval.addr2).from = (yyvsp[(1) - (1)].addr);
-               (yyval.addr2).to = nullgen;
-       }
-    break;
-
-  case 57:
-#line 300 "a.y"
-    {
-               (yyval.addr2).from = (yyvsp[(1) - (3)].addr);
-               (yyval.addr2).to = (yyvsp[(3) - (3)].addr);
-       }
-    break;
-
-  case 58:
-#line 307 "a.y"
-    {
-               (yyval.addr2).from = (yyvsp[(1) - (5)].addr);
-               (yyval.addr2).to = (yyvsp[(3) - (5)].addr);
-               (yyval.addr2).to.offset = (yyvsp[(5) - (5)].lval);
-       }
-    break;
-
-  case 59:
-#line 315 "a.y"
-    {
-               (yyval.addr2).from = (yyvsp[(3) - (5)].addr);
-               (yyval.addr2).to = (yyvsp[(5) - (5)].addr);
-               if((yyvsp[(1) - (5)].addr).type != TYPE_CONST)
-                       yyerror("illegal constant");
-               (yyval.addr2).to.offset = (yyvsp[(1) - (5)].addr).offset;
-       }
-    break;
-
-  case 60:
-#line 324 "a.y"
-    {
-               (yyval.addr2).from = nullgen;
-               (yyval.addr2).to = nullgen;
-       }
-    break;
-
-  case 61:
-#line 329 "a.y"
-    {
-               (yyval.addr2).from = (yyvsp[(1) - (1)].addr);
-               (yyval.addr2).to = nullgen;
-       }
-    break;
-
-  case 62:
-#line 336 "a.y"
-    {
-               if((yyvsp[(1) - (3)].addr).type != TYPE_CONST || (yyvsp[(3) - (3)].addr).type != TYPE_CONST)
-                       yyerror("arguments to PCDATA must be integer constants");
-               (yyval.addr2).from = (yyvsp[(1) - (3)].addr);
-               (yyval.addr2).to = (yyvsp[(3) - (3)].addr);
-       }
-    break;
-
-  case 63:
-#line 345 "a.y"
-    {
-               if((yyvsp[(1) - (3)].addr).type != TYPE_CONST)
-                       yyerror("index for FUNCDATA must be integer constant");
-               if((yyvsp[(3) - (3)].addr).type != TYPE_MEM || ((yyvsp[(3) - (3)].addr).name != NAME_EXTERN && (yyvsp[(3) - (3)].addr).name != NAME_STATIC))
-                       yyerror("value for FUNCDATA must be symbol reference");
-               (yyval.addr2).from = (yyvsp[(1) - (3)].addr);
-               (yyval.addr2).to = (yyvsp[(3) - (3)].addr);
-       }
-    break;
-
-  case 68:
-#line 362 "a.y"
-    {
-               (yyval.addr) = (yyvsp[(2) - (2)].addr);
-       }
-    break;
-
-  case 69:
-#line 366 "a.y"
-    {
-               (yyval.addr) = (yyvsp[(2) - (2)].addr);
-       }
-    break;
-
-  case 74:
-#line 378 "a.y"
-    {
-               (yyval.addr) = nullgen;
-               (yyval.addr).type = TYPE_BRANCH;
-               (yyval.addr).offset = (yyvsp[(1) - (4)].lval) + pc;
-       }
-    break;
-
-  case 75:
-#line 384 "a.y"
-    {
-               (yyvsp[(1) - (2)].sym) = labellookup((yyvsp[(1) - (2)].sym));
-               (yyval.addr) = nullgen;
-               if(pass == 2 && (yyvsp[(1) - (2)].sym)->type != LLAB)
-                       yyerror("undefined label: %s", (yyvsp[(1) - (2)].sym)->labelname);
-               (yyval.addr).type = TYPE_BRANCH;
-               (yyval.addr).offset = (yyvsp[(1) - (2)].sym)->value + (yyvsp[(2) - (2)].lval);
-       }
-    break;
-
-  case 76:
-#line 395 "a.y"
-    {
-               (yyval.addr) = nullgen;
-               (yyval.addr).type = TYPE_REG;
-               (yyval.addr).reg = (yyvsp[(1) - (1)].lval);
-       }
-    break;
-
-  case 77:
-#line 401 "a.y"
-    {
-               (yyval.addr) = nullgen;
-               (yyval.addr).type = TYPE_REG;
-               (yyval.addr).reg = (yyvsp[(1) - (1)].lval);
-       }
-    break;
-
-  case 78:
-#line 407 "a.y"
-    {
-               (yyval.addr) = nullgen;
-               (yyval.addr).type = TYPE_REG;
-               (yyval.addr).reg = (yyvsp[(1) - (1)].lval);
-       }
-    break;
-
-  case 79:
-#line 413 "a.y"
-    {
-               (yyval.addr) = nullgen;
-               (yyval.addr).type = TYPE_REG;
-               (yyval.addr).reg = (yyvsp[(1) - (1)].lval);
-       }
-    break;
-
-  case 80:
-#line 419 "a.y"
-    {
-               (yyval.addr) = nullgen;
-               (yyval.addr).type = TYPE_REG;
-               (yyval.addr).reg = REG_SP;
-       }
-    break;
-
-  case 81:
-#line 425 "a.y"
-    {
-               (yyval.addr) = nullgen;
-               (yyval.addr).type = TYPE_REG;
-               (yyval.addr).reg = (yyvsp[(1) - (1)].lval);
-       }
-    break;
-
-  case 82:
-#line 431 "a.y"
-    {
-               (yyval.addr) = nullgen;
-               (yyval.addr).type = TYPE_REG;
-               (yyval.addr).reg = (yyvsp[(1) - (1)].lval);
-       }
-    break;
-
-  case 83:
-#line 439 "a.y"
-    {
-               (yyval.addr) = nullgen;
-               (yyval.addr).type = TYPE_CONST;
-               (yyval.addr).offset = (yyvsp[(2) - (2)].lval);
-       }
-    break;
-
-  case 84:
-#line 445 "a.y"
-    {
-               (yyval.addr) = (yyvsp[(2) - (2)].addr);
-               (yyval.addr).type = TYPE_ADDR;
-               /*
-               if($2.type == D_AUTO || $2.type == D_PARAM)
-                       yyerror("constant cannot be automatic: %s",
-                               $2.sym->name);
-                */
-       }
-    break;
-
-  case 85:
-#line 455 "a.y"
-    {
-               (yyval.addr) = nullgen;
-               (yyval.addr).type = TYPE_SCONST;
-               memcpy((yyval.addr).u.sval, (yyvsp[(2) - (2)].sval), sizeof((yyval.addr).u.sval));
-       }
-    break;
-
-  case 86:
-#line 461 "a.y"
-    {
-               (yyval.addr) = nullgen;
-               (yyval.addr).type = TYPE_FCONST;
-               (yyval.addr).u.dval = (yyvsp[(2) - (2)].dval);
-       }
-    break;
-
-  case 87:
-#line 467 "a.y"
-    {
-               (yyval.addr) = nullgen;
-               (yyval.addr).type = TYPE_FCONST;
-               (yyval.addr).u.dval = (yyvsp[(3) - (4)].dval);
-       }
-    break;
-
-  case 88:
-#line 473 "a.y"
-    {
-               (yyval.addr) = nullgen;
-               (yyval.addr).type = TYPE_FCONST;
-               (yyval.addr).u.dval = -(yyvsp[(4) - (5)].dval);
-       }
-    break;
-
-  case 89:
-#line 479 "a.y"
-    {
-               (yyval.addr) = nullgen;
-               (yyval.addr).type = TYPE_FCONST;
-               (yyval.addr).u.dval = -(yyvsp[(3) - (3)].dval);
-       }
-    break;
-
-  case 92:
-#line 491 "a.y"
-    {
-               (yyval.addr) = nullgen;
-               (yyval.addr).type = TYPE_MEM;
-               (yyval.addr).offset = (yyvsp[(1) - (1)].lval);
-       }
-    break;
-
-  case 93:
-#line 497 "a.y"
-    {
-               (yyval.addr) = nullgen;
-               (yyval.addr).type = TYPE_MEM;
-               (yyval.addr).reg = (yyvsp[(3) - (4)].lval);
-               (yyval.addr).offset = (yyvsp[(1) - (4)].lval);
-       }
-    break;
-
-  case 94:
-#line 504 "a.y"
-    {
-               (yyval.addr) = nullgen;
-               (yyval.addr).type = TYPE_MEM;
-               (yyval.addr).reg = REG_SP;
-               (yyval.addr).offset = (yyvsp[(1) - (4)].lval);
-       }
-    break;
-
-  case 95:
-#line 511 "a.y"
-    {
-               (yyval.addr) = nullgen;
-               (yyval.addr).type = TYPE_MEM;
-               (yyval.addr).reg = (yyvsp[(3) - (4)].lval);
-               (yyval.addr).offset = (yyvsp[(1) - (4)].lval);
-       }
-    break;
-
-  case 96:
-#line 518 "a.y"
-    {
-               (yyval.addr) = nullgen;
-               (yyval.addr).type = TYPE_MEM;
-               (yyval.addr).offset = (yyvsp[(1) - (6)].lval);
-               (yyval.addr).index = (yyvsp[(3) - (6)].lval);
-               (yyval.addr).scale = (yyvsp[(5) - (6)].lval);
-               checkscale((yyval.addr).scale);
-       }
-    break;
-
-  case 97:
-#line 527 "a.y"
-    {
-               (yyval.addr) = nullgen;
-               (yyval.addr).type = TYPE_MEM;
-               (yyval.addr).reg = (yyvsp[(3) - (9)].lval);
-               (yyval.addr).offset = (yyvsp[(1) - (9)].lval);
-               (yyval.addr).index = (yyvsp[(6) - (9)].lval);
-               (yyval.addr).scale = (yyvsp[(8) - (9)].lval);
-               checkscale((yyval.addr).scale);
-       }
-    break;
-
-  case 98:
-#line 537 "a.y"
-    {
-               (yyval.addr) = nullgen;
-               (yyval.addr).type = TYPE_MEM;
-               (yyval.addr).reg = (yyvsp[(3) - (9)].lval);
-               (yyval.addr).offset = (yyvsp[(1) - (9)].lval);
-               (yyval.addr).index = (yyvsp[(6) - (9)].lval);
-               (yyval.addr).scale = (yyvsp[(8) - (9)].lval);
-               checkscale((yyval.addr).scale);
-       }
-    break;
-
-  case 99:
-#line 547 "a.y"
-    {
-               (yyval.addr) = nullgen;
-               (yyval.addr).type = TYPE_MEM;
-               (yyval.addr).reg = (yyvsp[(2) - (3)].lval);
-       }
-    break;
-
-  case 100:
-#line 553 "a.y"
-    {
-               (yyval.addr) = nullgen;
-               (yyval.addr).type = TYPE_MEM;
-               (yyval.addr).reg = REG_SP;
-       }
-    break;
-
-  case 101:
-#line 559 "a.y"
-    {
-               (yyval.addr) = nullgen;
-               (yyval.addr).type = TYPE_MEM;
-               (yyval.addr).index = (yyvsp[(2) - (5)].lval);
-               (yyval.addr).scale = (yyvsp[(4) - (5)].lval);
-               checkscale((yyval.addr).scale);
-       }
-    break;
-
-  case 102:
-#line 567 "a.y"
-    {
-               (yyval.addr) = nullgen;
-               (yyval.addr).type = TYPE_MEM;
-               (yyval.addr).reg = (yyvsp[(2) - (8)].lval);
-               (yyval.addr).index = (yyvsp[(5) - (8)].lval);
-               (yyval.addr).scale = (yyvsp[(7) - (8)].lval);
-               checkscale((yyval.addr).scale);
-       }
-    break;
-
-  case 103:
-#line 578 "a.y"
-    {
-               (yyval.addr) = (yyvsp[(1) - (1)].addr);
-       }
-    break;
-
-  case 104:
-#line 582 "a.y"
-    {
-               (yyval.addr) = (yyvsp[(1) - (6)].addr);
-               (yyval.addr).index = (yyvsp[(3) - (6)].lval);
-               (yyval.addr).scale = (yyvsp[(5) - (6)].lval);
-               checkscale((yyval.addr).scale);
-       }
-    break;
-
-  case 105:
-#line 591 "a.y"
-    {
-               (yyval.addr) = nullgen;
-               (yyval.addr).type = TYPE_MEM;
-               (yyval.addr).name = (yyvsp[(4) - (5)].lval);
-               (yyval.addr).sym = linklookup(ctxt, (yyvsp[(1) - (5)].sym)->name, 0);
-               (yyval.addr).offset = (yyvsp[(2) - (5)].lval);
-       }
-    break;
-
-  case 106:
-#line 599 "a.y"
-    {
-               (yyval.addr) = nullgen;
-               (yyval.addr).type = TYPE_MEM;
-               (yyval.addr).name = NAME_STATIC;
-               (yyval.addr).sym = linklookup(ctxt, (yyvsp[(1) - (7)].sym)->name, 1);
-               (yyval.addr).offset = (yyvsp[(4) - (7)].lval);
-       }
-    break;
-
-  case 107:
-#line 608 "a.y"
-    {
-               (yyval.lval) = 0;
-       }
-    break;
-
-  case 108:
-#line 612 "a.y"
-    {
-               (yyval.lval) = (yyvsp[(2) - (2)].lval);
-       }
-    break;
-
-  case 109:
-#line 616 "a.y"
-    {
-               (yyval.lval) = -(yyvsp[(2) - (2)].lval);
-       }
-    break;
-
-  case 111:
-#line 623 "a.y"
-    {
-               (yyval.lval) = NAME_AUTO;
-       }
-    break;
-
-  case 114:
-#line 631 "a.y"
-    {
-               (yyval.lval) = (yyvsp[(1) - (1)].sym)->value;
-       }
-    break;
-
-  case 115:
-#line 635 "a.y"
-    {
-               (yyval.lval) = -(yyvsp[(2) - (2)].lval);
-       }
-    break;
-
-  case 116:
-#line 639 "a.y"
-    {
-               (yyval.lval) = (yyvsp[(2) - (2)].lval);
-       }
-    break;
-
-  case 117:
-#line 643 "a.y"
-    {
-               (yyval.lval) = ~(yyvsp[(2) - (2)].lval);
-       }
-    break;
-
-  case 118:
-#line 647 "a.y"
-    {
-               (yyval.lval) = (yyvsp[(2) - (3)].lval);
-       }
-    break;
-
-  case 119:
-#line 653 "a.y"
-    {
-               (yyval.addr) = nullgen;
-               (yyval.addr).type = TYPE_TEXTSIZE;
-               (yyval.addr).offset = (yyvsp[(1) - (1)].lval);
-               (yyval.addr).u.argsize = ArgsSizeUnknown;
-       }
-    break;
-
-  case 120:
-#line 660 "a.y"
-    {
-               (yyval.addr) = nullgen;
-               (yyval.addr).type = TYPE_TEXTSIZE;
-               (yyval.addr).offset = -(yyvsp[(2) - (2)].lval);
-               (yyval.addr).u.argsize = ArgsSizeUnknown;
-       }
-    break;
-
-  case 121:
-#line 667 "a.y"
-    {
-               (yyval.addr) = nullgen;
-               (yyval.addr).type = TYPE_TEXTSIZE;
-               (yyval.addr).offset = (yyvsp[(1) - (3)].lval);
-               (yyval.addr).u.argsize = (yyvsp[(3) - (3)].lval);
-       }
-    break;
-
-  case 122:
-#line 674 "a.y"
-    {
-               (yyval.addr) = nullgen;
-               (yyval.addr).type = TYPE_TEXTSIZE;
-               (yyval.addr).offset = -(yyvsp[(2) - (4)].lval);
-               (yyval.addr).u.argsize = (yyvsp[(4) - (4)].lval);
-       }
-    break;
-
-  case 124:
-#line 684 "a.y"
-    {
-               (yyval.lval) = (yyvsp[(1) - (3)].lval) + (yyvsp[(3) - (3)].lval);
-       }
-    break;
-
-  case 125:
-#line 688 "a.y"
-    {
-               (yyval.lval) = (yyvsp[(1) - (3)].lval) - (yyvsp[(3) - (3)].lval);
-       }
-    break;
-
-  case 126:
-#line 692 "a.y"
-    {
-               (yyval.lval) = (yyvsp[(1) - (3)].lval) * (yyvsp[(3) - (3)].lval);
-       }
-    break;
-
-  case 127:
-#line 696 "a.y"
-    {
-               (yyval.lval) = (yyvsp[(1) - (3)].lval) / (yyvsp[(3) - (3)].lval);
-       }
-    break;
-
-  case 128:
-#line 700 "a.y"
-    {
-               (yyval.lval) = (yyvsp[(1) - (3)].lval) % (yyvsp[(3) - (3)].lval);
-       }
-    break;
-
-  case 129:
-#line 704 "a.y"
-    {
-               (yyval.lval) = (yyvsp[(1) - (4)].lval) << (yyvsp[(4) - (4)].lval);
-       }
-    break;
-
-  case 130:
-#line 708 "a.y"
-    {
-               (yyval.lval) = (yyvsp[(1) - (4)].lval) >> (yyvsp[(4) - (4)].lval);
-       }
-    break;
-
-  case 131:
-#line 712 "a.y"
-    {
-               (yyval.lval) = (yyvsp[(1) - (3)].lval) & (yyvsp[(3) - (3)].lval);
-       }
-    break;
-
-  case 132:
-#line 716 "a.y"
-    {
-               (yyval.lval) = (yyvsp[(1) - (3)].lval) ^ (yyvsp[(3) - (3)].lval);
-       }
-    break;
-
-  case 133:
-#line 720 "a.y"
-    {
-               (yyval.lval) = (yyvsp[(1) - (3)].lval) | (yyvsp[(3) - (3)].lval);
-       }
-    break;
-
-
-/* Line 1267 of yacc.c.  */
-#line 2587 "y.tab.c"
-      default: break;
-    }
-  YY_SYMBOL_PRINT ("-> $$ =", yyr1[yyn], &yyval, &yyloc);
-
-  YYPOPSTACK (yylen);
-  yylen = 0;
-  YY_STACK_PRINT (yyss, yyssp);
-
-  *++yyvsp = yyval;
-
-
-  /* Now `shift' the result of the reduction.  Determine what state
-     that goes to, based on the state we popped back to and the rule
-     number reduced by.  */
-
-  yyn = yyr1[yyn];
-
-  yystate = yypgoto[yyn - YYNTOKENS] + *yyssp;
-  if (0 <= yystate && yystate <= YYLAST && yycheck[yystate] == *yyssp)
-    yystate = yytable[yystate];
-  else
-    yystate = yydefgoto[yyn - YYNTOKENS];
-
-  goto yynewstate;
-
-
-/*------------------------------------.
-| yyerrlab -- here on detecting error |
-`------------------------------------*/
-yyerrlab:
-  /* If not already recovering from an error, report this error.  */
-  if (!yyerrstatus)
-    {
-      ++yynerrs;
-#if ! YYERROR_VERBOSE
-      yyerror (YY_("syntax error"));
-#else
-      {
-       YYSIZE_T yysize = yysyntax_error (0, yystate, yychar);
-       if (yymsg_alloc < yysize && yymsg_alloc < YYSTACK_ALLOC_MAXIMUM)
-         {
-           YYSIZE_T yyalloc = 2 * yysize;
-           if (! (yysize <= yyalloc && yyalloc <= YYSTACK_ALLOC_MAXIMUM))
-             yyalloc = YYSTACK_ALLOC_MAXIMUM;
-           if (yymsg != yymsgbuf)
-             YYSTACK_FREE (yymsg);
-           yymsg = (char *) YYSTACK_ALLOC (yyalloc);
-           if (yymsg)
-             yymsg_alloc = yyalloc;
-           else
-             {
-               yymsg = yymsgbuf;
-               yymsg_alloc = sizeof yymsgbuf;
-             }
-         }
-
-       if (0 < yysize && yysize <= yymsg_alloc)
-         {
-           (void) yysyntax_error (yymsg, yystate, yychar);
-           yyerror (yymsg);
-         }
-       else
-         {
-           yyerror (YY_("syntax error"));
-           if (yysize != 0)
-             goto yyexhaustedlab;
-         }
-      }
-#endif
-    }
-
-
-
-  if (yyerrstatus == 3)
-    {
-      /* If just tried and failed to reuse look-ahead token after an
-        error, discard it.  */
-
-      if (yychar <= YYEOF)
-       {
-         /* Return failure if at end of input.  */
-         if (yychar == YYEOF)
-           YYABORT;
-       }
-      else
-       {
-         yydestruct ("Error: discarding",
-                     yytoken, &yylval);
-         yychar = YYEMPTY;
-       }
-    }
-
-  /* Else will try to reuse look-ahead token after shifting the error
-     token.  */
-  goto yyerrlab1;
-
-
-/*---------------------------------------------------.
-| yyerrorlab -- error raised explicitly by YYERROR.  |
-`---------------------------------------------------*/
-yyerrorlab:
-
-  /* Pacify compilers like GCC when the user code never invokes
-     YYERROR and the label yyerrorlab therefore never appears in user
-     code.  */
-  if (/*CONSTCOND*/ 0)
-     goto yyerrorlab;
-
-  /* Do not reclaim the symbols of the rule which action triggered
-     this YYERROR.  */
-  YYPOPSTACK (yylen);
-  yylen = 0;
-  YY_STACK_PRINT (yyss, yyssp);
-  yystate = *yyssp;
-  goto yyerrlab1;
-
-
-/*-------------------------------------------------------------.
-| yyerrlab1 -- common code for both syntax error and YYERROR.  |
-`-------------------------------------------------------------*/
-yyerrlab1:
-  yyerrstatus = 3;     /* Each real token shifted decrements this.  */
-
-  for (;;)
-    {
-      yyn = yypact[yystate];
-      if (yyn != YYPACT_NINF)
-       {
-         yyn += YYTERROR;
-         if (0 <= yyn && yyn <= YYLAST && yycheck[yyn] == YYTERROR)
-           {
-             yyn = yytable[yyn];
-             if (0 < yyn)
-               break;
-           }
-       }
-
-      /* Pop the current state because it cannot handle the error token.  */
-      if (yyssp == yyss)
-       YYABORT;
-
-
-      yydestruct ("Error: popping",
-                 yystos[yystate], yyvsp);
-      YYPOPSTACK (1);
-      yystate = *yyssp;
-      YY_STACK_PRINT (yyss, yyssp);
-    }
-
-  if (yyn == YYFINAL)
-    YYACCEPT;
-
-  *++yyvsp = yylval;
-
-
-  /* Shift the error token.  */
-  YY_SYMBOL_PRINT ("Shifting", yystos[yyn], yyvsp, yylsp);
-
-  yystate = yyn;
-  goto yynewstate;
-
-
-/*-------------------------------------.
-| yyacceptlab -- YYACCEPT comes here.  |
-`-------------------------------------*/
-yyacceptlab:
-  yyresult = 0;
-  goto yyreturn;
-
-/*-----------------------------------.
-| yyabortlab -- YYABORT comes here.  |
-`-----------------------------------*/
-yyabortlab:
-  yyresult = 1;
-  goto yyreturn;
-
-#ifndef yyoverflow
-/*-------------------------------------------------.
-| yyexhaustedlab -- memory exhaustion comes here.  |
-`-------------------------------------------------*/
-yyexhaustedlab:
-  yyerror (YY_("memory exhausted"));
-  yyresult = 2;
-  /* Fall through.  */
-#endif
-
-yyreturn:
-  if (yychar != YYEOF && yychar != YYEMPTY)
-     yydestruct ("Cleanup: discarding lookahead",
-                yytoken, &yylval);
-  /* Do not reclaim the symbols of the rule which action triggered
-     this YYABORT or YYACCEPT.  */
-  YYPOPSTACK (yylen);
-  YY_STACK_PRINT (yyss, yyssp);
-  while (yyssp != yyss)
-    {
-      yydestruct ("Cleanup: popping",
-                 yystos[*yyssp], yyvsp);
-      YYPOPSTACK (1);
-    }
-#ifndef yyoverflow
-  if (yyss != yyssa)
-    YYSTACK_FREE (yyss);
-#endif
-#if YYERROR_VERBOSE
-  if (yymsg != yymsgbuf)
-    YYSTACK_FREE (yymsg);
-#endif
-  /* Make sure YYID is used.  */
-  return YYID (yyresult);
-}
-
-
-
diff --git a/src/cmd/6a/y.tab.h b/src/cmd/6a/y.tab.h
deleted file mode 100644 (file)
index e0eb5e1..0000000
+++ /dev/null
@@ -1,139 +0,0 @@
-/* A Bison parser, made by GNU Bison 2.3.  */
-
-/* Skeleton interface for Bison's Yacc-like parsers in C
-
-   Copyright (C) 1984, 1989, 1990, 2000, 2001, 2002, 2003, 2004, 2005, 2006
-   Free Software Foundation, Inc.
-
-   This program is free software; you can redistribute it and/or modify
-   it under the terms of the GNU General Public License as published by
-   the Free Software Foundation; either version 2, or (at your option)
-   any later version.
-
-   This program is distributed in the hope that it will be useful,
-   but WITHOUT ANY WARRANTY; without even the implied warranty of
-   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-   GNU General Public License for more details.
-
-   You should have received a copy of the GNU General Public License
-   along with this program; if not, write to the Free Software
-   Foundation, Inc., 51 Franklin Street, Fifth Floor,
-   Boston, MA 02110-1301, USA.  */
-
-/* As a special exception, you may create a larger work that contains
-   part or all of the Bison parser skeleton and distribute that work
-   under terms of your choice, so long as that work isn't itself a
-   parser generator using the skeleton or a modified version thereof
-   as a parser skeleton.  Alternatively, if you modify or redistribute
-   the parser skeleton itself, you may (at your option) remove this
-   special exception, which will cause the skeleton and the resulting
-   Bison output files to be licensed under the GNU General Public
-   License without this special exception.
-
-   This special exception was added by the Free Software Foundation in
-   version 2.2 of Bison.  */
-
-/* Tokens.  */
-#ifndef YYTOKENTYPE
-# define YYTOKENTYPE
-   /* Put the tokens into the symbol table, so that GDB and other debuggers
-      know about them.  */
-   enum yytokentype {
-     LTYPE0 = 258,
-     LTYPE1 = 259,
-     LTYPE2 = 260,
-     LTYPE3 = 261,
-     LTYPE4 = 262,
-     LTYPEC = 263,
-     LTYPED = 264,
-     LTYPEN = 265,
-     LTYPER = 266,
-     LTYPET = 267,
-     LTYPEG = 268,
-     LTYPEPC = 269,
-     LTYPES = 270,
-     LTYPEM = 271,
-     LTYPEI = 272,
-     LTYPEXC = 273,
-     LTYPEX = 274,
-     LTYPERT = 275,
-     LTYPEF = 276,
-     LCONST = 277,
-     LFP = 278,
-     LPC = 279,
-     LSB = 280,
-     LBREG = 281,
-     LLREG = 282,
-     LSREG = 283,
-     LFREG = 284,
-     LMREG = 285,
-     LXREG = 286,
-     LFCONST = 287,
-     LSCONST = 288,
-     LSP = 289,
-     LNAME = 290,
-     LLAB = 291,
-     LVAR = 292
-   };
-#endif
-/* Tokens.  */
-#define LTYPE0 258
-#define LTYPE1 259
-#define LTYPE2 260
-#define LTYPE3 261
-#define LTYPE4 262
-#define LTYPEC 263
-#define LTYPED 264
-#define LTYPEN 265
-#define LTYPER 266
-#define LTYPET 267
-#define LTYPEG 268
-#define LTYPEPC 269
-#define LTYPES 270
-#define LTYPEM 271
-#define LTYPEI 272
-#define LTYPEXC 273
-#define LTYPEX 274
-#define LTYPERT 275
-#define LTYPEF 276
-#define LCONST 277
-#define LFP 278
-#define LPC 279
-#define LSB 280
-#define LBREG 281
-#define LLREG 282
-#define LSREG 283
-#define LFREG 284
-#define LMREG 285
-#define LXREG 286
-#define LFCONST 287
-#define LSCONST 288
-#define LSP 289
-#define LNAME 290
-#define LLAB 291
-#define LVAR 292
-
-
-
-
-#if ! defined YYSTYPE && ! defined YYSTYPE_IS_DECLARED
-typedef union YYSTYPE
-#line 38 "a.y"
-{
-       Sym     *sym;
-       vlong   lval;
-       double  dval;
-       char    sval[8];
-       Addr    addr;
-       Addr2   addr2;
-}
-/* Line 1529 of yacc.c.  */
-#line 132 "y.tab.h"
-       YYSTYPE;
-# define yystype YYSTYPE /* obsolescent; will be withdrawn */
-# define YYSTYPE_IS_DECLARED 1
-# define YYSTYPE_IS_TRIVIAL 1
-#endif
-
-extern YYSTYPE yylval;
-
diff --git a/src/cmd/6g/Makefile b/src/cmd/6g/Makefile
deleted file mode 100644 (file)
index 3f528d7..0000000
+++ /dev/null
@@ -1,5 +0,0 @@
-# Copyright 2012 The Go Authors. All rights reserved.
-# Use of this source code is governed by a BSD-style
-# license that can be found in the LICENSE file.
-
-include ../../Make.dist
diff --git a/src/cmd/6g/cgen.c b/src/cmd/6g/cgen.c
deleted file mode 100644 (file)
index 77ab2d2..0000000
+++ /dev/null
@@ -1,1745 +0,0 @@
-// Copyright 2009 The Go Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style
-// license that can be found in the LICENSE file.
-
-#include <u.h>
-#include <libc.h>
-#include "gg.h"
-
-/*
- * generate:
- *     res = n;
- * simplifies and calls gmove.
- */
-void
-cgen(Node *n, Node *res)
-{
-       Node *nl, *nr, *r;
-       Node n1, n2;
-       int a, f;
-       Prog *p1, *p2, *p3;
-       Addr addr;
-
-       if(debug['g']) {
-               dump("\ncgen-n", n);
-               dump("cgen-res", res);
-       }
-       if(n == N || n->type == T)
-               goto ret;
-
-       if(res == N || res->type == T)
-               fatal("cgen: res nil");
-
-       while(n->op == OCONVNOP)
-               n = n->left;
-
-       switch(n->op) {
-       case OSLICE:
-       case OSLICEARR:
-       case OSLICESTR:
-       case OSLICE3:
-       case OSLICE3ARR:
-               if (res->op != ONAME || !res->addable) {
-                       tempname(&n1, n->type);
-                       cgen_slice(n, &n1);
-                       cgen(&n1, res);
-               } else
-                       cgen_slice(n, res);
-               goto ret;
-       case OEFACE:
-               if (res->op != ONAME || !res->addable) {
-                       tempname(&n1, n->type);
-                       cgen_eface(n, &n1);
-                       cgen(&n1, res);
-               } else
-                       cgen_eface(n, res);
-               goto ret;
-       }
-
-       if(n->ullman >= UINF) {
-               if(n->op == OINDREG)
-                       fatal("cgen: this is going to misscompile");
-               if(res->ullman >= UINF) {
-                       tempname(&n1, n->type);
-                       cgen(n, &n1);
-                       cgen(&n1, res);
-                       goto ret;
-               }
-       }
-
-       if(isfat(n->type)) {
-               if(n->type->width < 0)
-                       fatal("forgot to compute width for %T", n->type);
-               sgen(n, res, n->type->width);
-               goto ret;
-       }
-
-       if(!res->addable) {
-               if(n->ullman > res->ullman) {
-                       regalloc(&n1, n->type, res);
-                       cgen(n, &n1);
-                       if(n1.ullman > res->ullman) {
-                               dump("n1", &n1);
-                               dump("res", res);
-                               fatal("loop in cgen");
-                       }
-                       cgen(&n1, res);
-                       regfree(&n1);
-                       goto ret;
-               }
-
-               if(res->ullman >= UINF)
-                       goto gen;
-
-               if(complexop(n, res)) {
-                       complexgen(n, res);
-                       goto ret;
-               }
-
-               f = 1;  // gen thru register
-               switch(n->op) {
-               case OLITERAL:
-                       if(smallintconst(n))
-                               f = 0;
-                       break;
-               case OREGISTER:
-                       f = 0;
-                       break;
-               }
-
-               if(!iscomplex[n->type->etype]) {
-                       a = optoas(OAS, res->type);
-                       if(sudoaddable(a, res, &addr)) {
-                               if(f) {
-                                       regalloc(&n2, res->type, N);
-                                       cgen(n, &n2);
-                                       p1 = gins(a, &n2, N);
-                                       regfree(&n2);
-                               } else
-                                       p1 = gins(a, n, N);
-                               p1->to = addr;
-                               if(debug['g'])
-                                       print("%P [ignore previous line]\n", p1);
-                               sudoclean();
-                               goto ret;
-                       }
-               }
-
-       gen:
-               igen(res, &n1, N);
-               cgen(n, &n1);
-               regfree(&n1);
-               goto ret;
-       }
-
-       // update addressability for string, slice
-       // can't do in walk because n->left->addable
-       // changes if n->left is an escaping local variable.
-       switch(n->op) {
-       case OSPTR:
-       case OLEN:
-               if(isslice(n->left->type) || istype(n->left->type, TSTRING))
-                       n->addable = n->left->addable;
-               break;
-       case OCAP:
-               if(isslice(n->left->type))
-                       n->addable = n->left->addable;
-               break;
-       case OITAB:
-               n->addable = n->left->addable;
-               break;
-       }
-
-       if(complexop(n, res)) {
-               complexgen(n, res);
-               goto ret;
-       }
-
-       if(n->addable) {
-               gmove(n, res);
-               goto ret;
-       }
-
-       nl = n->left;
-       nr = n->right;
-
-       if(nl != N && nl->ullman >= UINF)
-       if(nr != N && nr->ullman >= UINF) {
-               tempname(&n1, nl->type);
-               cgen(nl, &n1);
-               n2 = *n;
-               n2.left = &n1;
-               cgen(&n2, res);
-               goto ret;
-       }
-
-       if(!iscomplex[n->type->etype]) {
-               a = optoas(OAS, n->type);
-               if(sudoaddable(a, n, &addr)) {
-                       if(res->op == OREGISTER) {
-                               p1 = gins(a, N, res);
-                               p1->from = addr;
-                       } else {
-                               regalloc(&n2, n->type, N);
-                               p1 = gins(a, N, &n2);
-                               p1->from = addr;
-                               gins(a, &n2, res);
-                               regfree(&n2);
-                       }
-                       sudoclean();
-                       goto ret;
-               }
-       }
-
-       switch(n->op) {
-       default:
-               dump("cgen", n);
-               fatal("cgen: unknown op %+hN", n);
-               break;
-
-       // these call bgen to get a bool value
-       case OOROR:
-       case OANDAND:
-       case OEQ:
-       case ONE:
-       case OLT:
-       case OLE:
-       case OGE:
-       case OGT:
-       case ONOT:
-               p1 = gbranch(AJMP, T, 0);
-               p2 = pc;
-               gmove(nodbool(1), res);
-               p3 = gbranch(AJMP, T, 0);
-               patch(p1, pc);
-               bgen(n, 1, 0, p2);
-               gmove(nodbool(0), res);
-               patch(p3, pc);
-               goto ret;
-
-       case OPLUS:
-               cgen(nl, res);
-               goto ret;
-
-       // unary
-       case OCOM:
-               a = optoas(OXOR, nl->type);
-               regalloc(&n1, nl->type, N);
-               cgen(nl, &n1);
-               nodconst(&n2, nl->type, -1);
-               gins(a, &n2, &n1);
-               gmove(&n1, res);
-               regfree(&n1);
-               goto ret;
-
-       case OMINUS:
-               if(isfloat[nl->type->etype]) {
-                       nr = nodintconst(-1);
-                       convlit(&nr, n->type);
-                       a = optoas(OMUL, nl->type);
-                       goto sbop;
-               }
-               a = optoas(n->op, nl->type);
-               goto uop;
-
-       // symmetric binary
-       case OAND:
-       case OOR:
-       case OXOR:
-       case OADD:
-       case OMUL:
-               a = optoas(n->op, nl->type);
-               if(a == AIMULB) {
-                       cgen_bmul(n->op, nl, nr, res);
-                       break;
-               }
-               goto sbop;
-
-       // asymmetric binary
-       case OSUB:
-               a = optoas(n->op, nl->type);
-               goto abop;
-
-       case OHMUL:
-               cgen_hmul(nl, nr, res);
-               break;
-
-       case OCONV:
-               if(n->type->width > nl->type->width) {
-                       // If loading from memory, do conversion during load,
-                       // so as to avoid use of 8-bit register in, say, int(*byteptr).
-                       switch(nl->op) {
-                       case ODOT:
-                       case ODOTPTR:
-                       case OINDEX:
-                       case OIND:
-                       case ONAME:
-                               igen(nl, &n1, res);
-                               regalloc(&n2, n->type, res);
-                               gmove(&n1, &n2);
-                               gmove(&n2, res);
-                               regfree(&n2);
-                               regfree(&n1);
-                               goto ret;
-                       }
-               }
-
-               regalloc(&n1, nl->type, res);
-               regalloc(&n2, n->type, &n1);
-               cgen(nl, &n1);
-
-               // if we do the conversion n1 -> n2 here
-               // reusing the register, then gmove won't
-               // have to allocate its own register.
-               gmove(&n1, &n2);
-               gmove(&n2, res);
-               regfree(&n2);
-               regfree(&n1);
-               break;
-
-       case ODOT:
-       case ODOTPTR:
-       case OINDEX:
-       case OIND:
-       case ONAME:     // PHEAP or PPARAMREF var
-               igen(n, &n1, res);
-               gmove(&n1, res);
-               regfree(&n1);
-               break;
-       
-       case OITAB:
-               // interface table is first word of interface value
-               igen(nl, &n1, res);
-               n1.type = n->type;
-               gmove(&n1, res);
-               regfree(&n1);
-               break;
-
-       case OSPTR:
-               // pointer is the first word of string or slice.
-               if(isconst(nl, CTSTR)) {
-                       regalloc(&n1, types[tptr], res);
-                       p1 = gins(ALEAQ, N, &n1);
-                       datastring(nl->val.u.sval->s, nl->val.u.sval->len, &p1->from);
-                       gmove(&n1, res);
-                       regfree(&n1);
-                       break;
-               }
-               igen(nl, &n1, res);
-               n1.type = n->type;
-               gmove(&n1, res);
-               regfree(&n1);
-               break;
-
-       case OLEN:
-               if(istype(nl->type, TMAP) || istype(nl->type, TCHAN)) {
-                       // map and chan have len in the first int-sized word.
-                       // a zero pointer means zero length
-                       regalloc(&n1, types[tptr], res);
-                       cgen(nl, &n1);
-
-                       nodconst(&n2, types[tptr], 0);
-                       gins(optoas(OCMP, types[tptr]), &n1, &n2);
-                       p1 = gbranch(optoas(OEQ, types[tptr]), T, 0);
-
-                       n2 = n1;
-                       n2.op = OINDREG;
-                       n2.type = types[simtype[TINT]];
-                       gmove(&n2, &n1);
-
-                       patch(p1, pc);
-
-                       gmove(&n1, res);
-                       regfree(&n1);
-                       break;
-               }
-               if(istype(nl->type, TSTRING) || isslice(nl->type)) {
-                       // both slice and string have len one pointer into the struct.
-                       // a zero pointer means zero length
-                       igen(nl, &n1, res);
-                       n1.type = types[simtype[TUINT]];
-                       n1.xoffset += Array_nel;
-                       gmove(&n1, res);
-                       regfree(&n1);
-                       break;
-               }
-               fatal("cgen: OLEN: unknown type %lT", nl->type);
-               break;
-
-       case OCAP:
-               if(istype(nl->type, TCHAN)) {
-                       // chan has cap in the second int-sized word.
-                       // a zero pointer means zero length
-                       regalloc(&n1, types[tptr], res);
-                       cgen(nl, &n1);
-
-                       nodconst(&n2, types[tptr], 0);
-                       gins(optoas(OCMP, types[tptr]), &n1, &n2);
-                       p1 = gbranch(optoas(OEQ, types[tptr]), T, 0);
-
-                       n2 = n1;
-                       n2.op = OINDREG;
-                       n2.xoffset = widthint;
-                       n2.type = types[simtype[TINT]];
-                       gmove(&n2, &n1);
-
-                       patch(p1, pc);
-
-                       gmove(&n1, res);
-                       regfree(&n1);
-                       break;
-               }
-               if(isslice(nl->type)) {
-                       igen(nl, &n1, res);
-                       n1.type = types[simtype[TUINT]];
-                       n1.xoffset += Array_cap;
-                       gmove(&n1, res);
-                       regfree(&n1);
-                       break;
-               }
-               fatal("cgen: OCAP: unknown type %lT", nl->type);
-               break;
-
-       case OADDR:
-               if(n->bounded) // let race detector avoid nil checks
-                       disable_checknil++;
-               agen(nl, res);
-               if(n->bounded)
-                       disable_checknil--;
-               break;
-
-       case OCALLMETH:
-               cgen_callmeth(n, 0);
-               cgen_callret(n, res);
-               break;
-
-       case OCALLINTER:
-               cgen_callinter(n, res, 0);
-               cgen_callret(n, res);
-               break;
-
-       case OCALLFUNC:
-               cgen_call(n, 0);
-               cgen_callret(n, res);
-               break;
-
-       case OMOD:
-       case ODIV:
-               if(isfloat[n->type->etype]) {
-                       a = optoas(n->op, nl->type);
-                       goto abop;
-               }
-
-               if(nl->ullman >= nr->ullman) {
-                       regalloc(&n1, nl->type, res);
-                       cgen(nl, &n1);
-                       cgen_div(n->op, &n1, nr, res);
-                       regfree(&n1);
-               } else {
-                       if(!smallintconst(nr)) {
-                               regalloc(&n2, nr->type, res);
-                               cgen(nr, &n2);
-                       } else {
-                               n2 = *nr;
-                       }
-                       cgen_div(n->op, nl, &n2, res);
-                       if(n2.op != OLITERAL)
-                               regfree(&n2);
-               }
-               break;
-
-       case OLSH:
-       case ORSH:
-       case OLROT:
-               cgen_shift(n->op, n->bounded, nl, nr, res);
-               break;
-       }
-       goto ret;
-
-sbop:  // symmetric binary
-       /*
-        * put simplest on right - we'll generate into left
-        * and then adjust it using the computation of right.
-        * constants and variables have the same ullman
-        * count, so look for constants specially.
-        *
-        * an integer constant we can use as an immediate
-        * is simpler than a variable - we can use the immediate
-        * in the adjustment instruction directly - so it goes
-        * on the right.
-        *
-        * other constants, like big integers or floating point
-        * constants, require a mov into a register, so those
-        * might as well go on the left, so we can reuse that
-        * register for the computation.
-        */
-       if(nl->ullman < nr->ullman ||
-          (nl->ullman == nr->ullman &&
-           (smallintconst(nl) || (nr->op == OLITERAL && !smallintconst(nr))))) {
-               r = nl;
-               nl = nr;
-               nr = r;
-       }
-
-abop:  // asymmetric binary
-       if(nl->ullman >= nr->ullman) {
-               regalloc(&n1, nl->type, res);
-               cgen(nl, &n1);
-       /*
-        * This generates smaller code - it avoids a MOV - but it's
-        * easily 10% slower due to not being able to
-        * optimize/manipulate the move.
-        * To see, run: go test -bench . crypto/md5
-        * with and without.
-        *
-               if(sudoaddable(a, nr, &addr)) {
-                       p1 = gins(a, N, &n1);
-                       p1->from = addr;
-                       gmove(&n1, res);
-                       sudoclean();
-                       regfree(&n1);
-                       goto ret;
-               }
-        *
-        */
-
-               if(smallintconst(nr))
-                       n2 = *nr;
-               else {
-                       regalloc(&n2, nr->type, N);
-                       cgen(nr, &n2);
-               }
-       } else {
-               if(smallintconst(nr))
-                       n2 = *nr;
-               else {
-                       regalloc(&n2, nr->type, res);
-                       cgen(nr, &n2);
-               }
-               regalloc(&n1, nl->type, N);
-               cgen(nl, &n1);
-       }
-       gins(a, &n2, &n1);
-       gmove(&n1, res);
-       regfree(&n1);
-       if(n2.op != OLITERAL)
-               regfree(&n2);
-       goto ret;
-
-uop:   // unary
-       regalloc(&n1, nl->type, res);
-       cgen(nl, &n1);
-       gins(a, N, &n1);
-       gmove(&n1, res);
-       regfree(&n1);
-       goto ret;
-
-ret:
-       ;
-}
-
-/*
- * allocate a register (reusing res if possible) and generate
- *  a = n
- * The caller must call regfree(a).
- */
-void
-cgenr(Node *n, Node *a, Node *res)
-{
-       Node n1;
-
-       if(debug['g'])
-               dump("cgenr-n", n);
-
-       if(isfat(n->type))
-               fatal("cgenr on fat node");
-
-       if(n->addable) {
-               regalloc(a, n->type, res);
-               gmove(n, a);
-               return;
-       }
-
-       switch(n->op) {
-       case ONAME:
-       case ODOT:
-       case ODOTPTR:
-       case OINDEX:
-       case OCALLFUNC:
-       case OCALLMETH:
-       case OCALLINTER:
-               igen(n, &n1, res);
-               regalloc(a, types[tptr], &n1);
-               gmove(&n1, a);
-               regfree(&n1);
-               break;
-       default:
-               regalloc(a, n->type, res);
-               cgen(n, a);
-               break;
-       }
-}
-
-/*
- * allocate a register (reusing res if possible) and generate
- * a = &n
- * The caller must call regfree(a).
- * The generated code checks that the result is not nil.
- */
-void
-agenr(Node *n, Node *a, Node *res)
-{
-       Node *nl, *nr;
-       Node n1, n2, n3, n5, tmp, tmp2, nlen;
-       Prog *p1;
-       Type *t;
-       uint64 w;
-       uint64 v;
-       int freelen;
-
-       if(debug['g']) {
-               dump("\nagenr-n", n);
-       }
-
-       nl = n->left;
-       nr = n->right;
-
-       switch(n->op) {
-       case ODOT:
-       case ODOTPTR:
-       case OCALLFUNC:
-       case OCALLMETH:
-       case OCALLINTER:
-               igen(n, &n1, res);
-               regalloc(a, types[tptr], &n1);
-               agen(&n1, a);
-               regfree(&n1);
-               break;
-
-       case OIND:
-               cgenr(n->left, a, res);
-               cgen_checknil(a);
-               break;
-
-       case OINDEX:
-               freelen = 0;
-               w = n->type->width;
-               // Generate the non-addressable child first.
-               if(nr->addable)
-                       goto irad;
-               if(nl->addable) {
-                       cgenr(nr, &n1, N);
-                       if(!isconst(nl, CTSTR)) {
-                               if(isfixedarray(nl->type)) {
-                                       agenr(nl, &n3, res);
-                               } else {
-                                       igen(nl, &nlen, res);
-                                       freelen = 1;
-                                       nlen.type = types[tptr];
-                                       nlen.xoffset += Array_array;
-                                       regalloc(&n3, types[tptr], res);
-                                       gmove(&nlen, &n3);
-                                       nlen.type = types[simtype[TUINT]];
-                                       nlen.xoffset += Array_nel-Array_array;
-                               }
-                       }
-                       goto index;
-               }
-               tempname(&tmp, nr->type);
-               cgen(nr, &tmp);
-               nr = &tmp;
-       irad:
-               if(!isconst(nl, CTSTR)) {
-                       if(isfixedarray(nl->type)) {
-                               agenr(nl, &n3, res);
-                       } else {
-                               if(!nl->addable) {
-                                       // igen will need an addressable node.
-                                       tempname(&tmp2, nl->type);
-                                       cgen(nl, &tmp2);
-                                       nl = &tmp2;
-                               }
-                               igen(nl, &nlen, res);
-                               freelen = 1;
-                               nlen.type = types[tptr];
-                               nlen.xoffset += Array_array;
-                               regalloc(&n3, types[tptr], res);
-                               gmove(&nlen, &n3);
-                               nlen.type = types[simtype[TUINT]];
-                               nlen.xoffset += Array_nel-Array_array;
-                       }
-               }
-               if(!isconst(nr, CTINT)) {
-                       cgenr(nr, &n1, N);
-               }
-               goto index;
-
-       index:
-               // &a is in &n3 (allocated in res)
-               // i is in &n1 (if not constant)
-               // len(a) is in nlen (if needed)
-               // w is width
-
-               // constant index
-               if(isconst(nr, CTINT)) {
-                       if(isconst(nl, CTSTR))
-                               fatal("constant string constant index");        // front end should handle
-                       v = mpgetfix(nr->val.u.xval);
-                       if(isslice(nl->type) || nl->type->etype == TSTRING) {
-                               if(!debug['B'] && !n->bounded) {
-                                       nodconst(&n2, types[simtype[TUINT]], v);
-                                       if(smallintconst(nr)) {
-                                               gins(optoas(OCMP, types[simtype[TUINT]]), &nlen, &n2);
-                                       } else {
-                                               regalloc(&tmp, types[simtype[TUINT]], N);
-                                               gmove(&n2, &tmp);
-                                               gins(optoas(OCMP, types[simtype[TUINT]]), &nlen, &tmp);
-                                               regfree(&tmp);
-                                       }
-                                       p1 = gbranch(optoas(OGT, types[simtype[TUINT]]), T, +1);
-                                       ginscall(panicindex, -1);
-                                       patch(p1, pc);
-                               }
-                               regfree(&nlen);
-                       }
-
-                       if (v*w != 0)
-                               ginscon(optoas(OADD, types[tptr]), v*w, &n3);
-                       *a = n3;
-                       break;
-               }
-
-               // type of the index
-               t = types[TUINT64];
-               if(issigned[n1.type->etype])
-                       t = types[TINT64];
-
-               regalloc(&n2, t, &n1);                  // i
-               gmove(&n1, &n2);
-               regfree(&n1);
-
-               if(!debug['B'] && !n->bounded) {
-                       // check bounds
-                       t = types[simtype[TUINT]];
-                       if(is64(nr->type))
-                               t = types[TUINT64];
-                       if(isconst(nl, CTSTR)) {
-                               nodconst(&nlen, t, nl->val.u.sval->len);
-                       } else if(isslice(nl->type) || nl->type->etype == TSTRING) {
-                               if(is64(nr->type)) {
-                                       regalloc(&n5, t, N);
-                                       gmove(&nlen, &n5);
-                                       regfree(&nlen);
-                                       nlen = n5;
-                               }
-                       } else {
-                               nodconst(&nlen, t, nl->type->bound);
-                               if(!smallintconst(&nlen)) {
-                                       regalloc(&n5, t, N);
-                                       gmove(&nlen, &n5);
-                                       nlen = n5;
-                                       freelen = 1;
-                               }
-                       }
-                       gins(optoas(OCMP, t), &n2, &nlen);
-                       p1 = gbranch(optoas(OLT, t), T, +1);
-                       ginscall(panicindex, -1);
-                       patch(p1, pc);
-               }
-
-               if(isconst(nl, CTSTR)) {
-                       regalloc(&n3, types[tptr], res);
-                       p1 = gins(ALEAQ, N, &n3);
-                       datastring(nl->val.u.sval->s, nl->val.u.sval->len, &p1->from);
-                       gins(AADDQ, &n2, &n3);
-                       goto indexdone;
-               }
-
-               if(w == 0) {
-                       // nothing to do
-               } else if(w == 1 || w == 2 || w == 4 || w == 8) {
-                       p1 = gins(ALEAQ, &n2, &n3);
-                       p1->from.type = TYPE_MEM;
-                       p1->from.scale = w;
-                       p1->from.index = p1->from.reg;
-                       p1->from.reg = p1->to.reg;
-               } else {
-                       ginscon(optoas(OMUL, t), w, &n2);
-                       gins(optoas(OADD, types[tptr]), &n2, &n3);
-               }
-
-       indexdone:
-               *a = n3;
-               regfree(&n2);
-               if(freelen)
-                       regfree(&nlen);
-               break;
-
-       default:
-               regalloc(a, types[tptr], res);
-               agen(n, a);
-               break;
-       }
-}
-
-/*
- * generate:
- *     res = &n;
- * The generated code checks that the result is not nil.
- */
-void
-agen(Node *n, Node *res)
-{
-       Node *nl;
-       Node n1, n2;
-
-       if(debug['g']) {
-               dump("\nagen-res", res);
-               dump("agen-r", n);
-       }
-       if(n == N || n->type == T)
-               return;
-
-       while(n->op == OCONVNOP)
-               n = n->left;
-
-       if(isconst(n, CTNIL) && n->type->width > widthptr) {
-               // Use of a nil interface or nil slice.
-               // Create a temporary we can take the address of and read.
-               // The generated code is just going to panic, so it need not
-               // be terribly efficient. See issue 3670.
-               tempname(&n1, n->type);
-               gvardef(&n1);
-               clearfat(&n1);
-               regalloc(&n2, types[tptr], res);
-               gins(ALEAQ, &n1, &n2);
-               gmove(&n2, res);
-               regfree(&n2);
-               goto ret;
-       }
-               
-       if(n->addable) {
-               regalloc(&n1, types[tptr], res);
-               gins(ALEAQ, n, &n1);
-               gmove(&n1, res);
-               regfree(&n1);
-               goto ret;
-       }
-
-       nl = n->left;
-
-       switch(n->op) {
-       default:
-               fatal("agen: unknown op %+hN", n);
-               break;
-
-       case OCALLMETH:
-               cgen_callmeth(n, 0);
-               cgen_aret(n, res);
-               break;
-
-       case OCALLINTER:
-               cgen_callinter(n, res, 0);
-               cgen_aret(n, res);
-               break;
-
-       case OCALLFUNC:
-               cgen_call(n, 0);
-               cgen_aret(n, res);
-               break;
-
-       case OSLICE:
-       case OSLICEARR:
-       case OSLICESTR:
-       case OSLICE3:
-       case OSLICE3ARR:
-               tempname(&n1, n->type);
-               cgen_slice(n, &n1);
-               agen(&n1, res);
-               break;
-
-       case OEFACE:
-               tempname(&n1, n->type);
-               cgen_eface(n, &n1);
-               agen(&n1, res);
-               break;
-
-       case OINDEX:
-               agenr(n, &n1, res);
-               gmove(&n1, res);
-               regfree(&n1);
-               break;
-
-       case ONAME:
-               // should only get here with names in this func.
-               if(n->funcdepth > 0 && n->funcdepth != funcdepth) {
-                       dump("bad agen", n);
-                       fatal("agen: bad ONAME funcdepth %d != %d",
-                               n->funcdepth, funcdepth);
-               }
-
-               // should only get here for heap vars or paramref
-               if(!(n->class & PHEAP) && n->class != PPARAMREF) {
-                       dump("bad agen", n);
-                       fatal("agen: bad ONAME class %#x", n->class);
-               }
-               cgen(n->heapaddr, res);
-               if(n->xoffset != 0)
-                       ginscon(optoas(OADD, types[tptr]), n->xoffset, res);
-               break;
-
-       case OIND:
-               cgen(nl, res);
-               cgen_checknil(res);
-               break;
-
-       case ODOT:
-               agen(nl, res);
-               if(n->xoffset != 0)
-                       ginscon(optoas(OADD, types[tptr]), n->xoffset, res);
-               break;
-
-       case ODOTPTR:
-               cgen(nl, res);
-               cgen_checknil(res);
-               if(n->xoffset != 0)
-                       ginscon(optoas(OADD, types[tptr]), n->xoffset, res);
-               break;
-       }
-
-ret:
-       ;
-}
-
-/*
- * generate:
- *     newreg = &n;
- *     res = newreg
- *
- * on exit, a has been changed to be *newreg.
- * caller must regfree(a).
- * The generated code checks that the result is not *nil.
- */
-void
-igen(Node *n, Node *a, Node *res)
-{
-       Type *fp;
-       Iter flist;
-       Node n1;
-
-       if(debug['g']) {
-               dump("\nigen-n", n);
-       }
-       switch(n->op) {
-       case ONAME:
-               if((n->class&PHEAP) || n->class == PPARAMREF)
-                       break;
-               *a = *n;
-               return;
-
-       case OINDREG:
-               // Increase the refcount of the register so that igen's caller
-               // has to call regfree.
-               if(n->val.u.reg != REG_SP)
-                       reg[n->val.u.reg]++;
-               *a = *n;
-               return;
-
-       case ODOT:
-               igen(n->left, a, res);
-               a->xoffset += n->xoffset;
-               a->type = n->type;
-               fixlargeoffset(a);
-               return;
-
-       case ODOTPTR:
-               cgenr(n->left, a, res);
-               cgen_checknil(a);
-               a->op = OINDREG;
-               a->xoffset += n->xoffset;
-               a->type = n->type;
-               fixlargeoffset(a);
-               return;
-
-       case OCALLFUNC:
-       case OCALLMETH:
-       case OCALLINTER:
-               switch(n->op) {
-               case OCALLFUNC:
-                       cgen_call(n, 0);
-                       break;
-               case OCALLMETH:
-                       cgen_callmeth(n, 0);
-                       break;
-               case OCALLINTER:
-                       cgen_callinter(n, N, 0);
-                       break;
-               }
-               fp = structfirst(&flist, getoutarg(n->left->type));
-               memset(a, 0, sizeof *a);
-               a->op = OINDREG;
-               a->val.u.reg = REG_SP;
-               a->addable = 1;
-               a->xoffset = fp->width;
-               a->type = n->type;
-               return;
-
-       case OINDEX:
-               // Index of fixed-size array by constant can
-               // put the offset in the addressing.
-               // Could do the same for slice except that we need
-               // to use the real index for the bounds checking.
-               if(isfixedarray(n->left->type) ||
-                  (isptr[n->left->type->etype] && isfixedarray(n->left->left->type)))
-               if(isconst(n->right, CTINT)) {
-                       // Compute &a.
-                       if(!isptr[n->left->type->etype])
-                               igen(n->left, a, res);
-                       else {
-                               igen(n->left, &n1, res);
-                               cgen_checknil(&n1);
-                               regalloc(a, types[tptr], res);
-                               gmove(&n1, a);
-                               regfree(&n1);
-                               a->op = OINDREG;
-                       }
-
-                       // Compute &a[i] as &a + i*width.
-                       a->type = n->type;
-                       a->xoffset += mpgetfix(n->right->val.u.xval)*n->type->width;
-                       fixlargeoffset(a);
-                       return;
-               }
-               break;
-       }
-
-       agenr(n, a, res);
-       a->op = OINDREG;
-       a->type = n->type;
-}
-
-/*
- * generate:
- *     if(n == true) goto to;
- */
-void
-bgen(Node *n, int true, int likely, Prog *to)
-{
-       int et, a;
-       Node *nl, *nr, *l, *r;
-       Node n1, n2, tmp;
-       NodeList *ll;
-       Prog *p1, *p2;
-
-       if(debug['g']) {
-               dump("\nbgen", n);
-       }
-
-       if(n == N)
-               n = nodbool(1);
-
-       if(n->ninit != nil)
-               genlist(n->ninit);
-
-       if(n->type == T) {
-               convlit(&n, types[TBOOL]);
-               if(n->type == T)
-                       goto ret;
-       }
-
-       et = n->type->etype;
-       if(et != TBOOL) {
-               yyerror("cgen: bad type %T for %O", n->type, n->op);
-               patch(gins(AEND, N, N), to);
-               goto ret;
-       }
-       nr = N;
-
-       while(n->op == OCONVNOP) {
-               n = n->left;
-               if(n->ninit != nil)
-                       genlist(n->ninit);
-       }
-
-       switch(n->op) {
-       default:
-               goto def;
-
-       case OLITERAL:
-               // need to ask if it is bool?
-               if(!true == !n->val.u.bval)
-                       patch(gbranch(AJMP, T, likely), to);
-               goto ret;
-
-       case ONAME:
-               if(n->addable == 0)
-                       goto def;
-               nodconst(&n1, n->type, 0);
-               gins(optoas(OCMP, n->type), n, &n1);
-               a = AJNE;
-               if(!true)
-                       a = AJEQ;
-               patch(gbranch(a, n->type, likely), to);
-               goto ret;
-
-       case OANDAND:
-       case OOROR:
-               if((n->op == OANDAND) == true) {
-                       p1 = gbranch(AJMP, T, 0);
-                       p2 = gbranch(AJMP, T, 0);
-                       patch(p1, pc);
-                       bgen(n->left, !true, -likely, p2);
-                       bgen(n->right, !true, -likely, p2);
-                       p1 = gbranch(AJMP, T, 0);
-                       patch(p1, to);
-                       patch(p2, pc);
-               } else {
-                       bgen(n->left, true, likely, to);
-                       bgen(n->right, true, likely, to);
-               }
-               goto ret;
-
-       case OEQ:
-       case ONE:
-       case OLT:
-       case OGT:
-       case OLE:
-       case OGE:
-               nr = n->right;
-               if(nr == N || nr->type == T)
-                       goto ret;
-
-       case ONOT:      // unary
-               nl = n->left;
-               if(nl == N || nl->type == T)
-                       goto ret;
-               break;
-       }
-
-       switch(n->op) {
-
-       case ONOT:
-               bgen(nl, !true, likely, to);
-               goto ret;
-
-       case OEQ:
-       case ONE:
-       case OLT:
-       case OGT:
-       case OLE:
-       case OGE:
-               a = n->op;
-               if(!true) {
-                       if(isfloat[nr->type->etype]) {
-                               // brcom is not valid on floats when NaN is involved.
-                               p1 = gbranch(AJMP, T, 0);
-                               p2 = gbranch(AJMP, T, 0);
-                               patch(p1, pc);
-                               ll = n->ninit;   // avoid re-genning ninit
-                               n->ninit = nil;
-                               bgen(n, 1, -likely, p2);
-                               n->ninit = ll;
-                               patch(gbranch(AJMP, T, 0), to);
-                               patch(p2, pc);
-                               goto ret;
-                       }                               
-                       a = brcom(a);
-                       true = !true;
-               }
-
-               // make simplest on right
-               if(nl->op == OLITERAL || (nl->ullman < nr->ullman && nl->ullman < UINF)) {
-                       a = brrev(a);
-                       r = nl;
-                       nl = nr;
-                       nr = r;
-               }
-
-               if(isslice(nl->type)) {
-                       // front end should only leave cmp to literal nil
-                       if((a != OEQ && a != ONE) || nr->op != OLITERAL) {
-                               yyerror("illegal slice comparison");
-                               break;
-                       }
-                       a = optoas(a, types[tptr]);
-                       igen(nl, &n1, N);
-                       n1.xoffset += Array_array;
-                       n1.type = types[tptr];
-                       nodconst(&tmp, types[tptr], 0);
-                       gins(optoas(OCMP, types[tptr]), &n1, &tmp);
-                       patch(gbranch(a, types[tptr], likely), to);
-                       regfree(&n1);
-                       break;
-               }
-
-               if(isinter(nl->type)) {
-                       // front end should only leave cmp to literal nil
-                       if((a != OEQ && a != ONE) || nr->op != OLITERAL) {
-                               yyerror("illegal interface comparison");
-                               break;
-                       }
-                       a = optoas(a, types[tptr]);
-                       igen(nl, &n1, N);
-                       n1.type = types[tptr];
-                       nodconst(&tmp, types[tptr], 0);
-                       gins(optoas(OCMP, types[tptr]), &n1, &tmp);
-                       patch(gbranch(a, types[tptr], likely), to);
-                       regfree(&n1);
-                       break;
-               }
-               if(iscomplex[nl->type->etype]) {
-                       complexbool(a, nl, nr, true, likely, to);
-                       break;
-               }
-
-               if(nr->ullman >= UINF) {
-                       regalloc(&n1, nl->type, N);
-                       cgen(nl, &n1);
-
-                       tempname(&tmp, nl->type);
-                       gmove(&n1, &tmp);
-                       regfree(&n1);
-
-                       regalloc(&n2, nr->type, N);
-                       cgen(nr, &n2);
-
-                       regalloc(&n1, nl->type, N);
-                       cgen(&tmp, &n1);
-
-                       goto cmp;
-               }
-
-               regalloc(&n1, nl->type, N);
-               cgen(nl, &n1);
-
-               if(smallintconst(nr)) {
-                       gins(optoas(OCMP, nr->type), &n1, nr);
-                       patch(gbranch(optoas(a, nr->type), nr->type, likely), to);
-                       regfree(&n1);
-                       break;
-               }
-
-               regalloc(&n2, nr->type, N);
-               cgen(nr, &n2);
-       cmp:
-               // only < and <= work right with NaN; reverse if needed
-               l = &n1;
-               r = &n2;
-               if(isfloat[nl->type->etype] && (a == OGT || a == OGE)) {
-                       l = &n2;
-                       r = &n1;
-                       a = brrev(a);
-               }
-
-               gins(optoas(OCMP, nr->type), l, r);
-
-               if(isfloat[nr->type->etype] && (n->op == OEQ || n->op == ONE)) {
-                       if(n->op == OEQ) {
-                               // neither NE nor P
-                               p1 = gbranch(AJNE, T, -likely);
-                               p2 = gbranch(AJPS, T, -likely);
-                               patch(gbranch(AJMP, T, 0), to);
-                               patch(p1, pc);
-                               patch(p2, pc);
-                       } else {
-                               // either NE or P
-                               patch(gbranch(AJNE, T, likely), to);
-                               patch(gbranch(AJPS, T, likely), to);
-                       }
-               } else
-                       patch(gbranch(optoas(a, nr->type), nr->type, likely), to);
-               regfree(&n1);
-               regfree(&n2);
-               break;
-       }
-       goto ret;
-
-def:
-       regalloc(&n1, n->type, N);
-       cgen(n, &n1);
-       nodconst(&n2, n->type, 0);
-       gins(optoas(OCMP, n->type), &n1, &n2);
-       a = AJNE;
-       if(!true)
-               a = AJEQ;
-       patch(gbranch(a, n->type, likely), to);
-       regfree(&n1);
-       goto ret;
-
-ret:
-       ;
-}
-
-/*
- * n is on stack, either local variable
- * or return value from function call.
- * return n's offset from SP.
- */
-int64
-stkof(Node *n)
-{
-       Type *t;
-       Iter flist;
-       int64 off;
-
-       switch(n->op) {
-       case OINDREG:
-               return n->xoffset;
-
-       case ODOT:
-               t = n->left->type;
-               if(isptr[t->etype])
-                       break;
-               off = stkof(n->left);
-               if(off == -1000 || off == 1000)
-                       return off;
-               return off + n->xoffset;
-
-       case OINDEX:
-               t = n->left->type;
-               if(!isfixedarray(t))
-                       break;
-               off = stkof(n->left);
-               if(off == -1000 || off == 1000)
-                       return off;
-               if(isconst(n->right, CTINT))
-                       return off + t->type->width * mpgetfix(n->right->val.u.xval);
-               return 1000;
-               
-       case OCALLMETH:
-       case OCALLINTER:
-       case OCALLFUNC:
-               t = n->left->type;
-               if(isptr[t->etype])
-                       t = t->type;
-
-               t = structfirst(&flist, getoutarg(t));
-               if(t != T)
-                       return t->width;
-               break;
-       }
-
-       // botch - probably failing to recognize address
-       // arithmetic on the above. eg INDEX and DOT
-       return -1000;
-}
-
-/*
- * block copy:
- *     memmove(&ns, &n, w);
- */
-void
-sgen(Node *n, Node *ns, int64 w)
-{
-       Node nodl, nodr, nodsi, noddi, cx, oldcx, tmp;
-       vlong c, q, odst, osrc;
-       NodeList *l;
-       Prog *p;
-
-       if(debug['g']) {
-               print("\nsgen w=%lld\n", w);
-               dump("r", n);
-               dump("res", ns);
-       }
-
-       if(n->ullman >= UINF && ns->ullman >= UINF)
-               fatal("sgen UINF");
-
-       if(w < 0)
-               fatal("sgen copy %lld", w);
-       
-       // If copying .args, that's all the results, so record definition sites
-       // for them for the liveness analysis.
-       if(ns->op == ONAME && strcmp(ns->sym->name, ".args") == 0)
-               for(l = curfn->dcl; l != nil; l = l->next)
-                       if(l->n->class == PPARAMOUT)
-                               gvardef(l->n);
-
-       // Avoid taking the address for simple enough types.
-       if(componentgen(n, ns))
-               return;
-       
-       if(w == 0) {
-               // evaluate side effects only
-               regalloc(&nodr, types[tptr], N);
-               agen(ns, &nodr);
-               agen(n, &nodr);
-               regfree(&nodr);
-               return;
-       }
-
-       // offset on the stack
-       osrc = stkof(n);
-       odst = stkof(ns);
-
-       if(osrc != -1000 && odst != -1000 && (osrc == 1000 || odst == 1000)) {
-               // osrc and odst both on stack, and at least one is in
-               // an unknown position.  Could generate code to test
-               // for forward/backward copy, but instead just copy
-               // to a temporary location first.
-               tempname(&tmp, n->type);
-               sgen(n, &tmp, w);
-               sgen(&tmp, ns, w);
-               return;
-       }
-
-       nodreg(&noddi, types[tptr], REG_DI);
-       nodreg(&nodsi, types[tptr], REG_SI);
-
-       if(n->ullman >= ns->ullman) {
-               agenr(n, &nodr, &nodsi);
-               if(ns->op == ONAME)
-                       gvardef(ns);
-               agenr(ns, &nodl, &noddi);
-       } else {
-               if(ns->op == ONAME)
-                       gvardef(ns);
-               agenr(ns, &nodl, &noddi);
-               agenr(n, &nodr, &nodsi);
-       }
-       
-       if(nodl.val.u.reg != REG_DI)
-               gmove(&nodl, &noddi);
-       if(nodr.val.u.reg != REG_SI)
-               gmove(&nodr, &nodsi);
-       regfree(&nodl);
-       regfree(&nodr);
-
-       c = w % 8;      // bytes
-       q = w / 8;      // quads
-
-       savex(REG_CX, &cx, &oldcx, N, types[TINT64]);
-
-       // if we are copying forward on the stack and
-       // the src and dst overlap, then reverse direction
-       if(osrc < odst && odst < osrc+w) {
-               // reverse direction
-               gins(ASTD, N, N);               // set direction flag
-               if(c > 0) {
-                       gconreg(addptr, w-1, REG_SI);
-                       gconreg(addptr, w-1, REG_DI);
-
-                       gconreg(movptr, c, REG_CX);
-                       gins(AREP, N, N);       // repeat
-                       gins(AMOVSB, N, N);     // MOVB *(SI)-,*(DI)-
-               }
-
-               if(q > 0) {
-                       if(c > 0) {
-                               gconreg(addptr, -7, REG_SI);
-                               gconreg(addptr, -7, REG_DI);
-                       } else {
-                               gconreg(addptr, w-8, REG_SI);
-                               gconreg(addptr, w-8, REG_DI);
-                       }
-                       gconreg(movptr, q, REG_CX);
-                       gins(AREP, N, N);       // repeat
-                       gins(AMOVSQ, N, N);     // MOVQ *(SI)-,*(DI)-
-               }
-               // we leave with the flag clear
-               gins(ACLD, N, N);
-       } else {
-               // normal direction
-               if(q > 128 || (nacl && q >= 4)) {
-                       gconreg(movptr, q, REG_CX);
-                       gins(AREP, N, N);       // repeat
-                       gins(AMOVSQ, N, N);     // MOVQ *(SI)+,*(DI)+
-               } else if (q >= 4) {
-                       p = gins(ADUFFCOPY, N, N);
-                       p->to.type = TYPE_ADDR;
-                       p->to.sym = linksym(pkglookup("duffcopy", runtimepkg));
-                       // 14 and 128 = magic constants: see ../../runtime/asm_amd64.s
-                       p->to.offset = 14*(128-q);
-               } else if(!nacl && c == 0) {
-                       // We don't need the MOVSQ side-effect of updating SI and DI,
-                       // and issuing a sequence of MOVQs directly is faster.
-                       nodsi.op = OINDREG;
-                       noddi.op = OINDREG;
-                       while(q > 0) {
-                               gmove(&nodsi, &cx); // MOVQ x+(SI),CX
-                               gmove(&cx, &noddi); // MOVQ CX,x+(DI)
-                               nodsi.xoffset += 8;
-                               noddi.xoffset += 8;
-                               q--;
-                       }
-               } else
-               while(q > 0) {
-                       gins(AMOVSQ, N, N);     // MOVQ *(SI)+,*(DI)+
-                       q--;
-               }
-               // copy the remaining c bytes
-               if(w < 4 || c <= 1 || (odst < osrc && osrc < odst+w)) {
-                       while(c > 0) {
-                               gins(AMOVSB, N, N);     // MOVB *(SI)+,*(DI)+
-                               c--;
-                       }
-               } else if(w < 8 || c <= 4) {
-                       nodsi.op = OINDREG;
-                       noddi.op = OINDREG;
-                       cx.type = types[TINT32];
-                       nodsi.type = types[TINT32];
-                       noddi.type = types[TINT32];
-                       if(c > 4) {
-                               nodsi.xoffset = 0;
-                               noddi.xoffset = 0;
-                               gmove(&nodsi, &cx);
-                               gmove(&cx, &noddi);
-                       }
-                       nodsi.xoffset = c-4;
-                       noddi.xoffset = c-4;
-                       gmove(&nodsi, &cx);
-                       gmove(&cx, &noddi);
-               } else {
-                       nodsi.op = OINDREG;
-                       noddi.op = OINDREG;
-                       cx.type = types[TINT64];
-                       nodsi.type = types[TINT64];
-                       noddi.type = types[TINT64];
-                       nodsi.xoffset = c-8;
-                       noddi.xoffset = c-8;
-                       gmove(&nodsi, &cx);
-                       gmove(&cx, &noddi);
-               }
-       }
-
-       restx(&cx, &oldcx);
-}
-
-static int
-cadable(Node *n)
-{
-       if(!n->addable) {
-               // dont know how it happens,
-               // but it does
-               return 0;
-       }
-
-       switch(n->op) {
-       case ONAME:
-               return 1;
-       }
-       return 0;
-}
-
-/*
- * copy a composite value by moving its individual components.
- * Slices, strings and interfaces are supported.
- * Small structs or arrays with elements of basic type are
- * also supported.
- * nr is N when assigning a zero value.
- * return 1 if can do, 0 if can't.
- */
-int
-componentgen(Node *nr, Node *nl)
-{
-       Node nodl, nodr, tmp;
-       Type *t;
-       int freel, freer;
-       vlong fldcount;
-       vlong loffset, roffset;
-
-       freel = 0;
-       freer = 0;
-
-       switch(nl->type->etype) {
-       default:
-               goto no;
-
-       case TARRAY:
-               t = nl->type;
-
-               // Slices are ok.
-               if(isslice(t))
-                       break;
-               // Small arrays are ok.
-               if(t->bound > 0 && t->bound <= 3 && !isfat(t->type))
-                       break;
-
-               goto no;
-
-       case TSTRUCT:
-               // Small structs with non-fat types are ok.
-               // Zero-sized structs are treated separately elsewhere.
-               fldcount = 0;
-               for(t=nl->type->type; t; t=t->down) {
-                       if(isfat(t->type))
-                               goto no;
-                       if(t->etype != TFIELD)
-                               fatal("componentgen: not a TFIELD: %lT", t);
-                       fldcount++;
-               }
-               if(fldcount == 0 || fldcount > 4)
-                       goto no;
-
-               break;
-
-       case TSTRING:
-       case TINTER:
-               break;
-       }
-
-       nodl = *nl;
-       if(!cadable(nl)) {
-               if(nr != N && !cadable(nr))
-                       goto no;
-               igen(nl, &nodl, N);
-               freel = 1;
-       }
-
-       if(nr != N) {
-               nodr = *nr;
-               if(!cadable(nr)) {
-                       igen(nr, &nodr, N);
-                       freer = 1;
-               }
-       } else {
-               // When zeroing, prepare a register containing zero.
-               nodconst(&tmp, nl->type, 0);
-               regalloc(&nodr, types[TUINT], N);
-               gmove(&tmp, &nodr);
-               freer = 1;
-       }
-       
-       // nl and nr are 'cadable' which basically means they are names (variables) now.
-       // If they are the same variable, don't generate any code, because the
-       // VARDEF we generate will mark the old value as dead incorrectly.
-       // (And also the assignments are useless.)
-       if(nr != N && nl->op == ONAME && nr->op == ONAME && nl == nr)
-               goto yes;
-
-       switch(nl->type->etype) {
-       case TARRAY:
-               // componentgen for arrays.
-               if(nl->op == ONAME)
-                       gvardef(nl);
-               t = nl->type;
-               if(!isslice(t)) {
-                       nodl.type = t->type;
-                       nodr.type = nodl.type;
-                       for(fldcount=0; fldcount < t->bound; fldcount++) {
-                               if(nr == N)
-                                       clearslim(&nodl);
-                               else
-                                       gmove(&nodr, &nodl);
-                               nodl.xoffset += t->type->width;
-                               nodr.xoffset += t->type->width;
-                       }
-                       goto yes;
-               }
-
-               // componentgen for slices.
-               nodl.xoffset += Array_array;
-               nodl.type = ptrto(nl->type->type);
-
-               if(nr != N) {
-                       nodr.xoffset += Array_array;
-                       nodr.type = nodl.type;
-               }
-               gmove(&nodr, &nodl);
-
-               nodl.xoffset += Array_nel-Array_array;
-               nodl.type = types[simtype[TUINT]];
-
-               if(nr != N) {
-                       nodr.xoffset += Array_nel-Array_array;
-                       nodr.type = nodl.type;
-               }
-               gmove(&nodr, &nodl);
-
-               nodl.xoffset += Array_cap-Array_nel;
-               nodl.type = types[simtype[TUINT]];
-
-               if(nr != N) {
-                       nodr.xoffset += Array_cap-Array_nel;
-                       nodr.type = nodl.type;
-               }
-               gmove(&nodr, &nodl);
-
-               goto yes;
-
-       case TSTRING:
-               if(nl->op == ONAME)
-                       gvardef(nl);
-               nodl.xoffset += Array_array;
-               nodl.type = ptrto(types[TUINT8]);
-
-               if(nr != N) {
-                       nodr.xoffset += Array_array;
-                       nodr.type = nodl.type;
-               }
-               gmove(&nodr, &nodl);
-
-               nodl.xoffset += Array_nel-Array_array;
-               nodl.type = types[simtype[TUINT]];
-
-               if(nr != N) {
-                       nodr.xoffset += Array_nel-Array_array;
-                       nodr.type = nodl.type;
-               }
-               gmove(&nodr, &nodl);
-
-               goto yes;
-
-       case TINTER:
-               if(nl->op == ONAME)
-                       gvardef(nl);
-               nodl.xoffset += Array_array;
-               nodl.type = ptrto(types[TUINT8]);
-
-               if(nr != N) {
-                       nodr.xoffset += Array_array;
-                       nodr.type = nodl.type;
-               }
-               gmove(&nodr, &nodl);
-
-               nodl.xoffset += Array_nel-Array_array;
-               nodl.type = ptrto(types[TUINT8]);
-
-               if(nr != N) {
-                       nodr.xoffset += Array_nel-Array_array;
-                       nodr.type = nodl.type;
-               }
-               gmove(&nodr, &nodl);
-
-               goto yes;
-
-       case TSTRUCT:
-               if(nl->op == ONAME)
-                       gvardef(nl);
-               loffset = nodl.xoffset;
-               roffset = nodr.xoffset;
-               // funarg structs may not begin at offset zero.
-               if(nl->type->etype == TSTRUCT && nl->type->funarg && nl->type->type)
-                       loffset -= nl->type->type->width;
-               if(nr != N && nr->type->etype == TSTRUCT && nr->type->funarg && nr->type->type)
-                       roffset -= nr->type->type->width;
-
-               for(t=nl->type->type; t; t=t->down) {
-                       nodl.xoffset = loffset + t->width;
-                       nodl.type = t->type;
-
-                       if(nr == N)
-                               clearslim(&nodl);
-                       else {
-                               nodr.xoffset = roffset + t->width;
-                               nodr.type = nodl.type;
-                               gmove(&nodr, &nodl);
-                       }
-               }
-               goto yes;
-       }
-
-no:
-       if(freer)
-               regfree(&nodr);
-       if(freel)
-               regfree(&nodl);
-       return 0;
-
-yes:
-       if(freer)
-               regfree(&nodr);
-       if(freel)
-               regfree(&nodl);
-       return 1;
-}
similarity index 100%
rename from src/cmd/new6g/cgen.go
rename to src/cmd/6g/cgen.go
diff --git a/src/cmd/6g/doc.go b/src/cmd/6g/doc.go
deleted file mode 100644 (file)
index 07b2818..0000000
+++ /dev/null
@@ -1,15 +0,0 @@
-// Copyright 2009 The Go Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style
-// license that can be found in the LICENSE file.
-
-// +build ignore
-
-/*
-
-6g is the version of the gc compiler for the x86-64.
-The $GOARCH for these tools is amd64.
-
-It reads .go files and outputs .6 files. The flags are documented in ../gc/doc.go.
-
-*/
-package main
diff --git a/src/cmd/6g/galign.c b/src/cmd/6g/galign.c
deleted file mode 100644 (file)
index fa9998b..0000000
+++ /dev/null
@@ -1,110 +0,0 @@
-// Copyright 2009 The Go Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style
-// license that can be found in the LICENSE file.
-
-#include <u.h>
-#include <libc.h>
-#include "gg.h"
-
-int    thechar = '6';
-char*  thestring       = "amd64";
-LinkArch*      thelinkarch = &linkamd64;
-
-void
-linkarchinit(void)
-{
-       if(strcmp(getgoarch(), "amd64p32") == 0) {
-               thelinkarch = &linkamd64p32;
-               thearch.thelinkarch = thelinkarch;
-               thestring = "amd64p32";
-               thearch.thestring = "amd64p32";
-       }
-}
-
-vlong MAXWIDTH = 1LL<<50;
-
-int    addptr = AADDQ;
-int    movptr = AMOVQ;
-int    leaptr = ALEAQ;
-int    cmpptr = ACMPQ;
-
-/*
- * go declares several platform-specific type aliases:
- * int, uint, float, and uintptr
- */
-Typedef        typedefs[] =
-{
-       {"int",         TINT,           TINT64},
-       {"uint",                TUINT,          TUINT64},
-       {"uintptr",     TUINTPTR,       TUINT64},
-       {0}
-};
-
-void
-betypeinit(void)
-{
-       widthptr = 8;
-       widthint = 8;
-       widthreg = 8;
-       if(strcmp(getgoarch(), "amd64p32") == 0) {
-               widthptr = 4;
-               widthint = 4;
-               addptr = AADDL;
-               movptr = AMOVL;
-               leaptr = ALEAL;
-               cmpptr = ACMPL;
-               typedefs[0].sameas = TINT32;
-               typedefs[1].sameas = TUINT32;
-               typedefs[2].sameas = TUINT32;
-               
-       }
-
-       listinit6();
-}
-
-void
-main(int argc, char **argv)
-{
-       thearch.thechar = thechar;
-       thearch.thestring = thestring;
-       thearch.thelinkarch = thelinkarch;
-       thearch.typedefs = typedefs;
-       thearch.REGSP = REGSP;
-       thearch.REGCTXT = REGCTXT;
-       thearch.MAXWIDTH = MAXWIDTH;
-       thearch.anyregalloc = anyregalloc;
-       thearch.betypeinit = betypeinit;
-       thearch.bgen = bgen;
-       thearch.cgen = cgen;
-       thearch.cgen_call = cgen_call;
-       thearch.cgen_callinter = cgen_callinter;
-       thearch.cgen_ret = cgen_ret;
-       thearch.clearfat = clearfat;
-       thearch.defframe = defframe;
-       thearch.excise = excise;
-       thearch.expandchecks = expandchecks;
-       thearch.gclean = gclean;
-       thearch.ginit = ginit;
-       thearch.gins = gins;
-       thearch.ginscall = ginscall;
-       thearch.igen = igen;
-       thearch.linkarchinit = linkarchinit;
-       thearch.peep = peep;
-       thearch.proginfo = proginfo;
-       thearch.regalloc = regalloc;
-       thearch.regfree = regfree;
-       thearch.regtyp = regtyp;
-       thearch.sameaddr = sameaddr;
-       thearch.smallindir = smallindir;
-       thearch.stackaddr = stackaddr;
-       thearch.excludedregs = excludedregs;
-       thearch.RtoB = RtoB;
-       thearch.FtoB = FtoB;
-       thearch.BtoR = BtoR;
-       thearch.BtoF = BtoF;
-       thearch.optoas = optoas;
-       thearch.doregbits = doregbits;
-       thearch.regnames = regnames;
-       
-       gcmain(argc, argv);
-}
similarity index 100%
rename from src/cmd/new6g/galign.go
rename to src/cmd/6g/galign.go
similarity index 100%
rename from src/cmd/new6g/gg.go
rename to src/cmd/6g/gg.go
diff --git a/src/cmd/6g/gg.h b/src/cmd/6g/gg.h
deleted file mode 100644 (file)
index a6dfad9..0000000
+++ /dev/null
@@ -1,176 +0,0 @@
-// Copyright 2009 The Go Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style
-// license that can be found in the LICENSE file.
-
-#ifndef        EXTERN
-#define        EXTERN  extern
-#endif
-
-#include "../gc/go.h"
-#include "../6l/6.out.h"
-
-EXTERN uchar   reg[MAXREG];
-EXTERN Node*   panicdiv;
-extern vlong   unmappedzero;
-extern int     addptr;
-extern int     cmpptr;
-extern int     movptr;
-extern int     leaptr;
-
-/*
- * ggen.c
- */
-void   compile(Node*);
-void   gen(Node*);
-Node*  lookdot(Node*, Node*, int);
-void   cgen_as(Node*, Node*);
-void   cgen_callmeth(Node*, int);
-void   cgen_callinter(Node*, Node*, int);
-void   cgen_proc(Node*, int);
-void   cgen_callret(Node*, Node*);
-void   cgen_div(int, Node*, Node*, Node*);
-void   cgen_bmul(int, Node*, Node*, Node*);
-void   cgen_hmul(Node*, Node*, Node*);
-void   cgen_shift(int, int, Node*, Node*, Node*);
-void   cgen_dcl(Node*);
-int    needconvert(Type*, Type*);
-void   genconv(Type*, Type*);
-void   allocparams(void);
-void   checklabels(void);
-void   ginscall(Node*, int);
-int    gen_as_init(Node*);
-
-/*
- * cgen.c
- */
-void   agen(Node*, Node*);
-void   agenr(Node*, Node*, Node*);
-void   cgenr(Node*, Node*, Node*);
-void   igen(Node*, Node*, Node*);
-vlong  fieldoffset(Type*, Node*);
-void   sgen(Node*, Node*, int64);
-void   gmove(Node*, Node*);
-Prog*  gins(int, Node*, Node*);
-int    samaddr(Node*, Node*);
-void   naddr(Node*, Addr*, int);
-void   cgen_aret(Node*, Node*);
-void   restx(Node*, Node*);
-void   savex(int, Node*, Node*, Node*, Type*);
-int    componentgen(Node*, Node*);
-
-/*
- * gsubr.c
- */
-void   clearp(Prog*);
-Prog*  gbranch(int, Type*, int);
-Prog*  prog(int);
-void   gconv(int, int);
-int    conv2pt(Type*);
-vlong  convvtox(vlong, int);
-void   fnparam(Type*, int, int);
-Prog*  gop(int, Node*, Node*, Node*);
-int    optoas(int, Type*);
-void   ginit(void);
-void   gclean(void);
-void   regalloc(Node*, Type*, Node*);
-void   regfree(Node*);
-Node*  nodarg(Type*, int);
-void   nodreg(Node*, Type*, int);
-void   nodindreg(Node*, Type*, int);
-void   gconreg(int, vlong, int);
-void   ginscon(int, vlong, Node*);
-void   buildtxt(void);
-Plist* newplist(void);
-int    isfat(Type*);
-void   sudoclean(void);
-int    sudoaddable(int, Node*, Addr*);
-void   afunclit(Addr*, Node*);
-void   nodfconst(Node*, Type*, Mpflt*);
-void   gtrack(Sym*);
-void   fixlargeoffset(Node *n);
-
-/*
- * cplx.c
- */
-int    complexop(Node*, Node*);
-void   complexmove(Node*, Node*);
-void   complexgen(Node*, Node*);
-
-/*
- * gobj.c
- */
-void   datastring(char*, int, Addr*);
-void   datagostring(Strlit*, Addr*);
-
-/*
- * list.c
- */
-void   listinit(void);
-
-void   zaddr(Biobuf*, Addr*, int, int);
-
-void afunclit(Addr*, Node*);
-int anyregalloc(void);
-void betypeinit(void);
-void bgen(Node*, int, int, Prog*);
-void cgen(Node*, Node*);
-void cgen_call(Node*, int);
-void cgen_callinter(Node*, Node*, int);
-void cgen_ret(Node*);
-void clearfat(Node*);
-void clearp(Prog*);
-void defframe(Prog*);
-int dgostringptr(Sym*, int, char*);
-int dgostrlitptr(Sym*, int, Strlit*);
-int dsname(Sym*, int, char*, int);
-int dsymptr(Sym*, int, Sym*, int);
-void dumpdata(void);
-void dumpit(char*, Flow*, int);
-void excise(Flow*);
-void expandchecks(Prog*);
-void fixautoused(Prog*);
-void gclean(void);
-void   gdata(Node*, Node*, int);
-void   gdatacomplex(Node*, Mpcplx*);
-void   gdatastring(Node*, Strlit*);
-void   ggloblnod(Node *nam);
-void   ggloblsym(Sym *s, int32 width, int8 flags);
-void ginit(void);
-Prog*  gins(int, Node*, Node*);
-void   ginscall(Node*, int);
-Prog*  gjmp(Prog*);
-void gtrack(Sym*);
-void   gused(Node*);
-void   igen(Node*, Node*, Node*);
-int isfat(Type*);
-void linkarchinit(void);
-void markautoused(Prog*);
-void naddr(Node*, Addr*, int);
-Plist* newplist(void);
-Node* nodarg(Type*, int);
-void patch(Prog*, Prog*);
-void proginfo(ProgInfo*, Prog*);
-void regalloc(Node*, Type*, Node*);
-void regfree(Node*);
-void regopt(Prog*);
-int regtyp(Addr*);
-int sameaddr(Addr*, Addr*);
-int smallindir(Addr*, Addr*);
-int stackaddr(Addr*);
-Prog* unpatch(Prog*);
-
-/*
- * reg.c
- */
-uint64 excludedregs(void);
-uint64 RtoB(int);
-uint64 FtoB(int);
-int BtoR(uint64);
-int BtoF(uint64);
-uint64 doregbits(int);
-char** regnames(int*);
-
-/*
- * peep.c
- */
-void peep(Prog*);
diff --git a/src/cmd/6g/ggen.c b/src/cmd/6g/ggen.c
deleted file mode 100644 (file)
index 7210458..0000000
+++ /dev/null
@@ -1,1046 +0,0 @@
-// Copyright 2009 The Go Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style
-// license that can be found in the LICENSE file.
-
-#undef EXTERN
-#define        EXTERN
-#include <u.h>
-#include <libc.h>
-#include "gg.h"
-#include "../gc/popt.h"
-
-static Prog *appendpp(Prog*, int, int, int, vlong, int, int, vlong);
-static Prog *zerorange(Prog *p, vlong frame, vlong lo, vlong hi, uint32 *ax);
-
-void
-defframe(Prog *ptxt)
-{
-       uint32 frame, ax;
-       Prog *p;
-       vlong hi, lo;
-       NodeList *l;
-       Node *n;
-
-       // fill in argument size, stack size
-       ptxt->to.type = TYPE_TEXTSIZE;
-       ptxt->to.u.argsize = rnd(curfn->type->argwid, widthptr);
-       frame = rnd(stksize+maxarg, widthreg);
-       ptxt->to.offset = frame;
-       
-       // insert code to zero ambiguously live variables
-       // so that the garbage collector only sees initialized values
-       // when it looks for pointers.
-       p = ptxt;
-       lo = hi = 0;
-       ax = 0;
-       // iterate through declarations - they are sorted in decreasing xoffset order.
-       for(l=curfn->dcl; l != nil; l = l->next) {
-               n = l->n;
-               if(!n->needzero)
-                       continue;
-               if(n->class != PAUTO)
-                       fatal("needzero class %d", n->class);
-               if(n->type->width % widthptr != 0 || n->xoffset % widthptr != 0 || n->type->width == 0)
-                       fatal("var %lN has size %d offset %d", n, (int)n->type->width, (int)n->xoffset);
-
-               if(lo != hi && n->xoffset + n->type->width >= lo - 2*widthreg) {
-                       // merge with range we already have
-                       lo = n->xoffset;
-                       continue;
-               }
-               // zero old range
-               p = zerorange(p, frame, lo, hi, &ax);
-
-               // set new range
-               hi = n->xoffset + n->type->width;
-               lo = n->xoffset;
-       }
-       // zero final range
-       zerorange(p, frame, lo, hi, &ax);
-}
-
-static Prog*
-zerorange(Prog *p, vlong frame, vlong lo, vlong hi, uint32 *ax)
-{
-       vlong cnt, i;
-
-       cnt = hi - lo;
-       if(cnt == 0)
-               return p;
-       if(*ax == 0) {
-               p = appendpp(p, AMOVQ, TYPE_CONST, 0, 0, TYPE_REG, REG_AX, 0);
-               *ax = 1;
-       }
-       if(cnt % widthreg != 0) {
-               // should only happen with nacl
-               if(cnt % widthptr != 0)
-                       fatal("zerorange count not a multiple of widthptr %d", cnt);
-               p = appendpp(p, AMOVL, TYPE_REG, REG_AX, 0, TYPE_MEM, REG_SP, frame+lo);
-               lo += widthptr;
-               cnt -= widthptr;
-       }
-       if(cnt <= 4*widthreg) {
-               for(i = 0; i < cnt; i += widthreg) {
-                       p = appendpp(p, AMOVQ, TYPE_REG, REG_AX, 0, TYPE_MEM, REG_SP, frame+lo+i);
-               }
-       } else if(!nacl && (cnt <= 128*widthreg)) {
-               p = appendpp(p, leaptr, TYPE_MEM, REG_SP, frame+lo, TYPE_REG, REG_DI, 0);
-               p = appendpp(p, ADUFFZERO, TYPE_NONE, 0, 0, TYPE_ADDR, 0, 2*(128-cnt/widthreg));
-               p->to.sym = linksym(pkglookup("duffzero", runtimepkg));
-       } else {
-               p = appendpp(p, AMOVQ, TYPE_CONST, 0, cnt/widthreg, TYPE_REG, REG_CX, 0);
-               p = appendpp(p, leaptr, TYPE_MEM, REG_SP, frame+lo, TYPE_REG, REG_DI, 0);
-               p = appendpp(p, AREP, TYPE_NONE, 0, 0, TYPE_NONE, 0, 0);
-               p = appendpp(p, ASTOSQ, TYPE_NONE, 0, 0, TYPE_NONE, 0, 0);
-       }
-       return p;
-}
-
-static Prog*   
-appendpp(Prog *p, int as, int ftype, int freg, vlong foffset, int ttype, int treg, vlong toffset)      
-{
-       Prog *q;
-       q = mal(sizeof(*q));    
-       clearp(q);      
-       q->as = as;     
-       q->lineno = p->lineno;  
-       q->from.type = ftype;
-       q->from.reg = freg;
-       q->from.offset = foffset;       
-       q->to.type = ttype;     
-       q->to.reg = treg;
-       q->to.offset = toffset; 
-       q->link = p->link;      
-       p->link = q;    
-       return q;       
-}
-
-/*
- * generate:
- *     call f
- *     proc=-1 normal call but no return
- *     proc=0  normal call
- *     proc=1  goroutine run in new proc
- *     proc=2  defer call save away stack
-  *    proc=3  normal call to C pointer (not Go func value)
- */
-void
-ginscall(Node *f, int proc)
-{
-       Prog *p;
-       Node reg, stk;
-       Node r1;
-       int32 extra;
-
-       if(f->type != T) {
-               extra = 0;
-               if(proc == 1 || proc == 2)
-                       extra = 2 * widthptr;
-               setmaxarg(f->type, extra);
-       }
-
-       switch(proc) {
-       default:
-               fatal("ginscall: bad proc %d", proc);
-               break;
-
-       case 0: // normal call
-       case -1:        // normal call but no return
-               if(f->op == ONAME && f->class == PFUNC) {
-                       if(f == deferreturn) {
-                               // Deferred calls will appear to be returning to
-                               // the CALL deferreturn(SB) that we are about to emit.
-                               // However, the stack trace code will show the line
-                               // of the instruction byte before the return PC. 
-                               // To avoid that being an unrelated instruction,
-                               // insert an x86 NOP that we will have the right line number.
-                               // x86 NOP 0x90 is really XCHG AX, AX; use that description
-                               // because the NOP pseudo-instruction would be removed by
-                               // the linker.
-                               nodreg(&reg, types[TINT], REG_AX);
-                               gins(AXCHGL, &reg, &reg);
-                       }
-                       p = gins(ACALL, N, f);
-                       afunclit(&p->to, f);
-                       if(proc == -1 || noreturn(p))
-                               gins(AUNDEF, N, N);
-                       break;
-               }
-               nodreg(&reg, types[tptr], REG_DX);
-               nodreg(&r1, types[tptr], REG_BX);
-               gmove(f, &reg);
-               reg.op = OINDREG;
-               gmove(&reg, &r1);
-               reg.op = OREGISTER;
-               gins(ACALL, &reg, &r1);
-               break;
-       
-       case 3: // normal call of c function pointer
-               gins(ACALL, N, f);
-               break;
-
-       case 1: // call in new proc (go)
-       case 2: // deferred call (defer)
-               memset(&stk, 0, sizeof(stk));
-               stk.op = OINDREG;
-               stk.val.u.reg = REG_SP;
-               stk.xoffset = 0;
-
-               if(widthptr == 8) {
-                       // size of arguments at 0(SP)
-                       ginscon(AMOVQ, argsize(f->type), &stk);
-
-                       // FuncVal* at 8(SP)
-                       stk.xoffset = widthptr;
-                       nodreg(&reg, types[TINT64], REG_AX);
-                       gmove(f, &reg);
-                       gins(AMOVQ, &reg, &stk);
-               } else {
-                       // size of arguments at 0(SP)
-                       ginscon(AMOVL, argsize(f->type), &stk);
-
-                       // FuncVal* at 4(SP)
-                       stk.xoffset = widthptr;
-                       nodreg(&reg, types[TINT32], REG_AX);
-                       gmove(f, &reg);
-                       gins(AMOVL, &reg, &stk);
-               }
-
-               if(proc == 1)
-                       ginscall(newproc, 0);
-               else {
-                       if(!hasdefer)
-                               fatal("hasdefer=0 but has defer");
-                       ginscall(deferproc, 0);
-               }
-               if(proc == 2) {
-                       nodreg(&reg, types[TINT32], REG_AX);
-                       gins(ATESTL, &reg, &reg);
-                       p = gbranch(AJEQ, T, +1);
-                       cgen_ret(N);
-                       patch(p, pc);
-               }
-               break;
-       }
-}
-
-/*
- * n is call to interface method.
- * generate res = n.
- */
-void
-cgen_callinter(Node *n, Node *res, int proc)
-{
-       Node *i, *f;
-       Node tmpi, nodi, nodo, nodr, nodsp;
-
-       i = n->left;
-       if(i->op != ODOTINTER)
-               fatal("cgen_callinter: not ODOTINTER %O", i->op);
-
-       f = i->right;           // field
-       if(f->op != ONAME)
-               fatal("cgen_callinter: not ONAME %O", f->op);
-
-       i = i->left;            // interface
-
-       if(!i->addable) {
-               tempname(&tmpi, i->type);
-               cgen(i, &tmpi);
-               i = &tmpi;
-       }
-
-       genlist(n->list);               // assign the args
-
-       // i is now addable, prepare an indirected
-       // register to hold its address.
-       igen(i, &nodi, res);            // REG = &inter
-
-       nodindreg(&nodsp, types[tptr], REG_SP);
-       nodsp.xoffset = 0;
-       if(proc != 0)
-               nodsp.xoffset += 2 * widthptr; // leave room for size & fn
-       nodi.type = types[tptr];
-       nodi.xoffset += widthptr;
-       cgen(&nodi, &nodsp);    // {0, 8(nacl), or 16}(SP) = 8(REG) -- i.data
-
-       regalloc(&nodo, types[tptr], res);
-       nodi.type = types[tptr];
-       nodi.xoffset -= widthptr;
-       cgen(&nodi, &nodo);     // REG = 0(REG) -- i.tab
-       regfree(&nodi);
-
-       regalloc(&nodr, types[tptr], &nodo);
-       if(n->left->xoffset == BADWIDTH)
-               fatal("cgen_callinter: badwidth");
-       cgen_checknil(&nodo); // in case offset is huge
-       nodo.op = OINDREG;
-       nodo.xoffset = n->left->xoffset + 3*widthptr + 8;
-       if(proc == 0) {
-               // plain call: use direct c function pointer - more efficient
-               cgen(&nodo, &nodr);     // REG = 32+offset(REG) -- i.tab->fun[f]
-               proc = 3;
-       } else {
-               // go/defer. generate go func value.
-               gins(ALEAQ, &nodo, &nodr);      // REG = &(32+offset(REG)) -- i.tab->fun[f]
-       }
-
-       nodr.type = n->left->type;
-       ginscall(&nodr, proc);
-
-       regfree(&nodr);
-       regfree(&nodo);
-}
-
-/*
- * generate function call;
- *     proc=0  normal call
- *     proc=1  goroutine run in new proc
- *     proc=2  defer call save away stack
- */
-void
-cgen_call(Node *n, int proc)
-{
-       Type *t;
-       Node nod, afun;
-
-       if(n == N)
-               return;
-
-       if(n->left->ullman >= UINF) {
-               // if name involves a fn call
-               // precompute the address of the fn
-               tempname(&afun, types[tptr]);
-               cgen(n->left, &afun);
-       }
-
-       genlist(n->list);               // assign the args
-       t = n->left->type;
-
-       // call tempname pointer
-       if(n->left->ullman >= UINF) {
-               regalloc(&nod, types[tptr], N);
-               cgen_as(&nod, &afun);
-               nod.type = t;
-               ginscall(&nod, proc);
-               regfree(&nod);
-               return;
-       }
-
-       // call pointer
-       if(n->left->op != ONAME || n->left->class != PFUNC) {
-               regalloc(&nod, types[tptr], N);
-               cgen_as(&nod, n->left);
-               nod.type = t;
-               ginscall(&nod, proc);
-               regfree(&nod);
-               return;
-       }
-
-       // call direct
-       n->left->method = 1;
-       ginscall(n->left, proc);
-}
-
-/*
- * call to n has already been generated.
- * generate:
- *     res = return value from call.
- */
-void
-cgen_callret(Node *n, Node *res)
-{
-       Node nod;
-       Type *fp, *t;
-       Iter flist;
-
-       t = n->left->type;
-       if(t->etype == TPTR32 || t->etype == TPTR64)
-               t = t->type;
-
-       fp = structfirst(&flist, getoutarg(t));
-       if(fp == T)
-               fatal("cgen_callret: nil");
-
-       memset(&nod, 0, sizeof(nod));
-       nod.op = OINDREG;
-       nod.val.u.reg = REG_SP;
-       nod.addable = 1;
-
-       nod.xoffset = fp->width;
-       nod.type = fp->type;
-       cgen_as(res, &nod);
-}
-
-/*
- * call to n has already been generated.
- * generate:
- *     res = &return value from call.
- */
-void
-cgen_aret(Node *n, Node *res)
-{
-       Node nod1, nod2;
-       Type *fp, *t;
-       Iter flist;
-
-       t = n->left->type;
-       if(isptr[t->etype])
-               t = t->type;
-
-       fp = structfirst(&flist, getoutarg(t));
-       if(fp == T)
-               fatal("cgen_aret: nil");
-
-       memset(&nod1, 0, sizeof(nod1));
-       nod1.op = OINDREG;
-       nod1.val.u.reg = REG_SP;
-       nod1.addable = 1;
-
-       nod1.xoffset = fp->width;
-       nod1.type = fp->type;
-
-       if(res->op != OREGISTER) {
-               regalloc(&nod2, types[tptr], res);
-               gins(leaptr, &nod1, &nod2);
-               gins(movptr, &nod2, res);
-               regfree(&nod2);
-       } else
-               gins(leaptr, &nod1, res);
-}
-
-/*
- * generate return.
- * n->left is assignments to return values.
- */
-void
-cgen_ret(Node *n)
-{
-       Prog *p;
-
-       if(n != N)
-               genlist(n->list);               // copy out args
-       if(hasdefer)
-               ginscall(deferreturn, 0);
-       genlist(curfn->exit);
-       p = gins(ARET, N, N);
-       if(n != N && n->op == ORETJMP) {
-               p->to.type = TYPE_MEM;
-               p->to.name = NAME_EXTERN;
-               p->to.sym = linksym(n->left->sym);
-       }
-}
-
-/*
- * generate division.
- * generates one of:
- *     res = nl / nr
- *     res = nl % nr
- * according to op.
- */
-void
-dodiv(int op, Node *nl, Node *nr, Node *res)
-{
-       int a, check;
-       Node n3, n4;
-       Type *t, *t0;
-       Node ax, dx, ax1, n31, oldax, olddx;
-       Prog *p1, *p2;
-
-       // Have to be careful about handling
-       // most negative int divided by -1 correctly.
-       // The hardware will trap.
-       // Also the byte divide instruction needs AH,
-       // which we otherwise don't have to deal with.
-       // Easiest way to avoid for int8, int16: use int32.
-       // For int32 and int64, use explicit test.
-       // Could use int64 hw for int32.
-       t = nl->type;
-       t0 = t;
-       check = 0;
-       if(issigned[t->etype]) {
-               check = 1;
-               if(isconst(nl, CTINT) && mpgetfix(nl->val.u.xval) != -(1ULL<<(t->width*8-1)))
-                       check = 0;
-               else if(isconst(nr, CTINT) && mpgetfix(nr->val.u.xval) != -1)
-                       check = 0;
-       }
-       if(t->width < 4) {
-               if(issigned[t->etype])
-                       t = types[TINT32];
-               else
-                       t = types[TUINT32];
-               check = 0;
-       }
-       a = optoas(op, t);
-
-       regalloc(&n3, t0, N);
-       if(nl->ullman >= nr->ullman) {
-               savex(REG_AX, &ax, &oldax, res, t0);
-               cgen(nl, &ax);
-               regalloc(&ax, t0, &ax); // mark ax live during cgen
-               cgen(nr, &n3);
-               regfree(&ax);
-       } else {
-               cgen(nr, &n3);
-               savex(REG_AX, &ax, &oldax, res, t0);
-               cgen(nl, &ax);
-       }
-       if(t != t0) {
-               // Convert
-               ax1 = ax;
-               n31 = n3;
-               ax.type = t;
-               n3.type = t;
-               gmove(&ax1, &ax);
-               gmove(&n31, &n3);
-       }
-
-       p2 = P;
-       if(nacl) {
-               // Native Client does not relay the divide-by-zero trap
-               // to the executing program, so we must insert a check
-               // for ourselves.
-               nodconst(&n4, t, 0);
-               gins(optoas(OCMP, t), &n3, &n4);
-               p1 = gbranch(optoas(ONE, t), T, +1);
-               if(panicdiv == N)
-                       panicdiv = sysfunc("panicdivide");
-               ginscall(panicdiv, -1);
-               patch(p1, pc);
-       }
-       if(check) {
-               nodconst(&n4, t, -1);
-               gins(optoas(OCMP, t), &n3, &n4);
-               p1 = gbranch(optoas(ONE, t), T, +1);
-               if(op == ODIV) {
-                       // a / (-1) is -a.
-                       gins(optoas(OMINUS, t), N, &ax);
-                       gmove(&ax, res);
-               } else {
-                       // a % (-1) is 0.
-                       nodconst(&n4, t, 0);
-                       gmove(&n4, res);
-               }
-               p2 = gbranch(AJMP, T, 0);
-               patch(p1, pc);
-       }
-       savex(REG_DX, &dx, &olddx, res, t);
-       if(!issigned[t->etype]) {
-               nodconst(&n4, t, 0);
-               gmove(&n4, &dx);
-       } else
-               gins(optoas(OEXTEND, t), N, N);
-       gins(a, &n3, N);
-       regfree(&n3);
-       if(op == ODIV)
-               gmove(&ax, res);
-       else
-               gmove(&dx, res);
-       restx(&dx, &olddx);
-       if(check)
-               patch(p2, pc);
-       restx(&ax, &oldax);
-}
-
-/*
- * register dr is one of the special ones (AX, CX, DI, SI, etc.).
- * we need to use it.  if it is already allocated as a temporary
- * (r > 1; can only happen if a routine like sgen passed a
- * special as cgen's res and then cgen used regalloc to reuse
- * it as its own temporary), then move it for now to another
- * register.  caller must call restx to move it back.
- * the move is not necessary if dr == res, because res is
- * known to be dead.
- */
-void
-savex(int dr, Node *x, Node *oldx, Node *res, Type *t)
-{
-       int r;
-
-       r = reg[dr];
-
-       // save current ax and dx if they are live
-       // and not the destination
-       memset(oldx, 0, sizeof *oldx);
-       nodreg(x, t, dr);
-       if(r > 1 && !samereg(x, res)) {
-               regalloc(oldx, types[TINT64], N);
-               x->type = types[TINT64];
-               gmove(x, oldx);
-               x->type = t;
-               oldx->ostk = r; // squirrel away old r value
-               reg[dr] = 1;
-       }
-}
-
-void
-restx(Node *x, Node *oldx)
-{
-       if(oldx->op != 0) {
-               x->type = types[TINT64];
-               reg[x->val.u.reg] = oldx->ostk;
-               gmove(oldx, x);
-               regfree(oldx);
-       }
-}
-
-/*
- * generate division according to op, one of:
- *     res = nl / nr
- *     res = nl % nr
- */
-void
-cgen_div(int op, Node *nl, Node *nr, Node *res)
-{
-       Node n1, n2, n3;
-       int w, a;
-       Magic m;
-
-       if(nr->op != OLITERAL)
-               goto longdiv;
-       w = nl->type->width*8;
-
-       // Front end handled 32-bit division. We only need to handle 64-bit.
-       // try to do division by multiply by (2^w)/d
-       // see hacker's delight chapter 10
-       switch(simtype[nl->type->etype]) {
-       default:
-               goto longdiv;
-
-       case TUINT64:
-               m.w = w;
-               m.ud = mpgetfix(nr->val.u.xval);
-               umagic(&m);
-               if(m.bad)
-                       break;
-               if(op == OMOD)
-                       goto longmod;
-
-               cgenr(nl, &n1, N);
-               nodconst(&n2, nl->type, m.um);
-               regalloc(&n3, nl->type, res);
-               cgen_hmul(&n1, &n2, &n3);
-
-               if(m.ua) {
-                       // need to add numerator accounting for overflow
-                       gins(optoas(OADD, nl->type), &n1, &n3);
-                       nodconst(&n2, nl->type, 1);
-                       gins(optoas(ORROTC, nl->type), &n2, &n3);
-                       nodconst(&n2, nl->type, m.s-1);
-                       gins(optoas(ORSH, nl->type), &n2, &n3);
-               } else {
-                       nodconst(&n2, nl->type, m.s);
-                       gins(optoas(ORSH, nl->type), &n2, &n3); // shift dx
-               }
-
-               gmove(&n3, res);
-               regfree(&n1);
-               regfree(&n3);
-               return;
-
-       case TINT64:
-               m.w = w;
-               m.sd = mpgetfix(nr->val.u.xval);
-               smagic(&m);
-               if(m.bad)
-                       break;
-               if(op == OMOD)
-                       goto longmod;
-
-               cgenr(nl, &n1, res);
-               nodconst(&n2, nl->type, m.sm);
-               regalloc(&n3, nl->type, N);
-               cgen_hmul(&n1, &n2, &n3);
-
-               if(m.sm < 0) {
-                       // need to add numerator
-                       gins(optoas(OADD, nl->type), &n1, &n3);
-               }
-
-               nodconst(&n2, nl->type, m.s);
-               gins(optoas(ORSH, nl->type), &n2, &n3); // shift n3
-
-               nodconst(&n2, nl->type, w-1);
-               gins(optoas(ORSH, nl->type), &n2, &n1); // -1 iff num is neg
-               gins(optoas(OSUB, nl->type), &n1, &n3); // added
-
-               if(m.sd < 0) {
-                       // this could probably be removed
-                       // by factoring it into the multiplier
-                       gins(optoas(OMINUS, nl->type), N, &n3);
-               }
-
-               gmove(&n3, res);
-               regfree(&n1);
-               regfree(&n3);
-               return;
-       }
-       goto longdiv;
-
-longdiv:
-       // division and mod using (slow) hardware instruction
-       dodiv(op, nl, nr, res);
-       return;
-
-longmod:
-       // mod using formula A%B = A-(A/B*B) but
-       // we know that there is a fast algorithm for A/B
-       regalloc(&n1, nl->type, res);
-       cgen(nl, &n1);
-       regalloc(&n2, nl->type, N);
-       cgen_div(ODIV, &n1, nr, &n2);
-       a = optoas(OMUL, nl->type);
-       if(w == 8) {
-               // use 2-operand 16-bit multiply
-               // because there is no 2-operand 8-bit multiply
-               a = AIMULW;
-       }
-       if(!smallintconst(nr)) {
-               regalloc(&n3, nl->type, N);
-               cgen(nr, &n3);
-               gins(a, &n3, &n2);
-               regfree(&n3);
-       } else
-               gins(a, nr, &n2);
-       gins(optoas(OSUB, nl->type), &n2, &n1);
-       gmove(&n1, res);
-       regfree(&n1);
-       regfree(&n2);
-}
-
-/*
- * generate high multiply:
- *   res = (nl*nr) >> width
- */
-void
-cgen_hmul(Node *nl, Node *nr, Node *res)
-{
-       Type *t;
-       int a;
-       Node n1, n2, ax, dx, *tmp;
-
-       t = nl->type;
-       a = optoas(OHMUL, t);
-       if(nl->ullman < nr->ullman) {
-               tmp = nl;
-               nl = nr;
-               nr = tmp;
-       }
-       cgenr(nl, &n1, res);
-       cgenr(nr, &n2, N);
-       nodreg(&ax, t, REG_AX);
-       gmove(&n1, &ax);
-       gins(a, &n2, N);
-       regfree(&n2);
-       regfree(&n1);
-
-       if(t->width == 1) {
-               // byte multiply behaves differently.
-               nodreg(&ax, t, REG_AH);
-               nodreg(&dx, t, REG_DX);
-               gmove(&ax, &dx);
-       }
-       nodreg(&dx, t, REG_DX);
-       gmove(&dx, res);
-}
-
-/*
- * generate shift according to op, one of:
- *     res = nl << nr
- *     res = nl >> nr
- */
-void
-cgen_shift(int op, int bounded, Node *nl, Node *nr, Node *res)
-{
-       Node n1, n2, n3, n4, n5, cx, oldcx;
-       int a, rcx;
-       Prog *p1;
-       uvlong sc;
-       Type *tcount;
-
-       a = optoas(op, nl->type);
-
-       if(nr->op == OLITERAL) {
-               regalloc(&n1, nl->type, res);
-               cgen(nl, &n1);
-               sc = mpgetfix(nr->val.u.xval);
-               if(sc >= nl->type->width*8) {
-                       // large shift gets 2 shifts by width-1
-                       nodconst(&n3, types[TUINT32], nl->type->width*8-1);
-                       gins(a, &n3, &n1);
-                       gins(a, &n3, &n1);
-               } else
-                       gins(a, nr, &n1);
-               gmove(&n1, res);
-               regfree(&n1);
-               goto ret;
-       }
-
-       if(nl->ullman >= UINF) {
-               tempname(&n4, nl->type);
-               cgen(nl, &n4);
-               nl = &n4;
-       }
-       if(nr->ullman >= UINF) {
-               tempname(&n5, nr->type);
-               cgen(nr, &n5);
-               nr = &n5;
-       }
-
-       rcx = reg[REG_CX];
-       nodreg(&n1, types[TUINT32], REG_CX);
-       
-       // Allow either uint32 or uint64 as shift type,
-       // to avoid unnecessary conversion from uint32 to uint64
-       // just to do the comparison.
-       tcount = types[simtype[nr->type->etype]];
-       if(tcount->etype < TUINT32)
-               tcount = types[TUINT32];
-
-       regalloc(&n1, nr->type, &n1);           // to hold the shift type in CX
-       regalloc(&n3, tcount, &n1);     // to clear high bits of CX
-
-       nodreg(&cx, types[TUINT64], REG_CX);
-       memset(&oldcx, 0, sizeof oldcx);
-       if(rcx > 0 && !samereg(&cx, res)) {
-               regalloc(&oldcx, types[TUINT64], N);
-               gmove(&cx, &oldcx);
-       }
-       cx.type = tcount;
-
-       if(samereg(&cx, res))
-               regalloc(&n2, nl->type, N);
-       else
-               regalloc(&n2, nl->type, res);
-       if(nl->ullman >= nr->ullman) {
-               cgen(nl, &n2);
-               cgen(nr, &n1);
-               gmove(&n1, &n3);
-       } else {
-               cgen(nr, &n1);
-               gmove(&n1, &n3);
-               cgen(nl, &n2);
-       }
-       regfree(&n3);
-
-       // test and fix up large shifts
-       if(!bounded) {
-               nodconst(&n3, tcount, nl->type->width*8);
-               gins(optoas(OCMP, tcount), &n1, &n3);
-               p1 = gbranch(optoas(OLT, tcount), T, +1);
-               if(op == ORSH && issigned[nl->type->etype]) {
-                       nodconst(&n3, types[TUINT32], nl->type->width*8-1);
-                       gins(a, &n3, &n2);
-               } else {
-                       nodconst(&n3, nl->type, 0);
-                       gmove(&n3, &n2);
-               }
-               patch(p1, pc);
-       }
-
-       gins(a, &n1, &n2);
-
-       if(oldcx.op != 0) {
-               cx.type = types[TUINT64];
-               gmove(&oldcx, &cx);
-               regfree(&oldcx);
-       }
-
-       gmove(&n2, res);
-
-       regfree(&n1);
-       regfree(&n2);
-
-ret:
-       ;
-}
-
-/*
- * generate byte multiply:
- *     res = nl * nr
- * there is no 2-operand byte multiply instruction so
- * we do a full-width multiplication and truncate afterwards.
- */
-void
-cgen_bmul(int op, Node *nl, Node *nr, Node *res)
-{
-       Node n1, n2, n1b, n2b, *tmp;
-       Type *t;
-       int a;
-
-       // largest ullman on left.
-       if(nl->ullman < nr->ullman) {
-               tmp = nl;
-               nl = nr;
-               nr = tmp;
-       }
-
-       // generate operands in "8-bit" registers.
-       regalloc(&n1b, nl->type, res);
-       cgen(nl, &n1b);
-       regalloc(&n2b, nr->type, N);
-       cgen(nr, &n2b);
-
-       // perform full-width multiplication.
-       t = types[TUINT64];
-       if(issigned[nl->type->etype])
-               t = types[TINT64];
-       nodreg(&n1, t, n1b.val.u.reg);
-       nodreg(&n2, t, n2b.val.u.reg);
-       a = optoas(op, t);
-       gins(a, &n2, &n1);
-
-       // truncate.
-       gmove(&n1, res);
-       regfree(&n1b);
-       regfree(&n2b);
-}
-
-void
-clearfat(Node *nl)
-{
-       int64 w, c, q;
-       Node n1, oldn1, ax, oldax, di, z;
-       Prog *p;
-
-       /* clear a fat object */
-       if(debug['g'])
-               dump("\nclearfat", nl);
-
-       w = nl->type->width;
-       // Avoid taking the address for simple enough types.
-       if(componentgen(N, nl))
-               return;
-
-       c = w % 8;      // bytes
-       q = w / 8;      // quads
-
-       if(q < 4) {
-               // Write sequence of MOV 0, off(base) instead of using STOSQ.
-               // The hope is that although the code will be slightly longer,
-               // the MOVs will have no dependencies and pipeline better
-               // than the unrolled STOSQ loop.
-               // NOTE: Must use agen, not igen, so that optimizer sees address
-               // being taken. We are not writing on field boundaries.
-               agenr(nl, &n1, N);
-               n1.op = OINDREG;
-               nodconst(&z, types[TUINT64], 0);
-               while(q-- > 0) {
-                       n1.type = z.type;
-                       gins(AMOVQ, &z, &n1);
-                       n1.xoffset += 8;
-               }
-               if(c >= 4) {
-                       nodconst(&z, types[TUINT32], 0);
-                       n1.type = z.type;
-                       gins(AMOVL, &z, &n1);
-                       n1.xoffset += 4;
-                       c -= 4;
-               }
-               nodconst(&z, types[TUINT8], 0);
-               while(c-- > 0) {
-                       n1.type = z.type;
-                       gins(AMOVB, &z, &n1);
-                       n1.xoffset++;
-               }
-               regfree(&n1);
-               return;
-       }
-
-       savex(REG_DI, &n1, &oldn1, N, types[tptr]);
-       agen(nl, &n1);
-
-       savex(REG_AX, &ax, &oldax, N, types[tptr]);
-       gconreg(AMOVL, 0, REG_AX);
-
-       if(q > 128 || nacl) {
-               gconreg(movptr, q, REG_CX);
-               gins(AREP, N, N);       // repeat
-               gins(ASTOSQ, N, N);     // STOQ AL,*(DI)+
-       } else {
-               p = gins(ADUFFZERO, N, N);
-               p->to.type = TYPE_ADDR;
-               p->to.sym = linksym(pkglookup("duffzero", runtimepkg));
-               // 2 and 128 = magic constants: see ../../runtime/asm_amd64.s
-               p->to.offset = 2*(128-q);
-       }
-
-       z = ax;
-       di = n1;
-       if(w >= 8 && c >= 4) {
-               di.op = OINDREG;
-               di.type = z.type = types[TINT64];
-               p = gins(AMOVQ, &z, &di);
-               p->to.scale = 1;
-               p->to.offset = c-8;
-       } else if(c >= 4) {
-               di.op = OINDREG;
-               di.type = z.type = types[TINT32];
-               p = gins(AMOVL, &z, &di);
-               if(c > 4) {
-                       p = gins(AMOVL, &z, &di);
-                       p->to.scale = 1;
-                       p->to.offset = c-4;
-               }
-       } else
-       while(c > 0) {
-               gins(ASTOSB, N, N);     // STOB AL,*(DI)+
-               c--;
-       }
-
-       restx(&n1, &oldn1);
-       restx(&ax, &oldax);
-}
-
-// Called after regopt and peep have run.
-// Expand CHECKNIL pseudo-op into actual nil pointer check.
-void
-expandchecks(Prog *firstp)
-{
-       Prog *p, *p1, *p2;
-
-       for(p = firstp; p != P; p = p->link) {
-               if(p->as != ACHECKNIL)
-                       continue;
-               if(debug_checknil && p->lineno > 1) // p->lineno==1 in generated wrappers
-                       warnl(p->lineno, "generated nil check");
-               // check is
-               //      CMP arg, $0
-               //      JNE 2(PC) (likely)
-               //      MOV AX, 0
-               p1 = mal(sizeof *p1);
-               p2 = mal(sizeof *p2);
-               clearp(p1);
-               clearp(p2);
-               p1->link = p2;
-               p2->link = p->link;
-               p->link = p1;
-               p1->lineno = p->lineno;
-               p2->lineno = p->lineno;
-               p1->pc = 9999;
-               p2->pc = 9999;
-               p->as = cmpptr;
-               p->to.type = TYPE_CONST;
-               p->to.offset = 0;
-               p1->as = AJNE;
-               p1->from.type = TYPE_CONST;
-               p1->from.offset = 1; // likely
-               p1->to.type = TYPE_BRANCH;
-               p1->to.u.branch = p2->link;
-               // crash by write to memory address 0.
-               // if possible, since we know arg is 0, use 0(arg),
-               // which will be shorter to encode than plain 0.
-               p2->as = AMOVL;
-               p2->from.type = TYPE_REG;
-               p2->from.reg = REG_AX;
-               if(regtyp(&p->from)) {
-                       p2->to.type = TYPE_MEM;
-                       p2->to.reg = p->from.reg;
-               } else {
-                       p2->to.type = TYPE_MEM;
-                       p2->to.reg = REG_NONE;
-               }
-               p2->to.offset = 0;
-       }
-}
similarity index 100%
rename from src/cmd/new6g/ggen.go
rename to src/cmd/6g/ggen.go
diff --git a/src/cmd/6g/gsubr.c b/src/cmd/6g/gsubr.c
deleted file mode 100644 (file)
index 55d3425..0000000
+++ /dev/null
@@ -1,1737 +0,0 @@
-// Derived from Inferno utils/6c/txt.c
-// http://code.google.com/p/inferno-os/source/browse/utils/6c/txt.c
-//
-//     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 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 <u.h>
-#include <libc.h>
-#include "gg.h"
-#include "../../runtime/funcdata.h"
-
-// TODO(rsc): Can make this bigger if we move
-// the text segment up higher in 6l for all GOOS.
-// At the same time, can raise StackBig in ../../runtime/stack.h.
-vlong unmappedzero = 4096;
-static int     resvd[] =
-{
-       REG_DI, // for movstring
-       REG_SI, // for movstring
-
-       REG_AX, // for divide
-       REG_CX, // for shift
-       REG_DX, // for divide
-       REG_SP, // for stack
-};
-
-void
-ginit(void)
-{
-       int i;
-
-       for(i=0; i<nelem(reg); i++)
-               reg[i] = 1;
-       for(i=REG_AX; i<=REG_R15; i++)
-               reg[i] = 0;
-       for(i=REG_X0; i<=REG_X15; i++)
-               reg[i] = 0;
-
-       for(i=0; i<nelem(resvd); i++)
-               reg[resvd[i]]++;
-       
-       if(nacl) {
-               reg[REG_BP]++;
-               reg[REG_R15]++;
-       } else if(framepointer_enabled) {
-               // BP is part of the calling convention of framepointer_enabled.
-               reg[REG_BP]++;
-       }
-}
-
-void
-gclean(void)
-{
-       int i;
-
-       for(i=0; i<nelem(resvd); i++)
-               reg[resvd[i]]--;
-       if(nacl) {
-               reg[REG_BP]--;
-               reg[REG_R15]--;
-       } else if(framepointer_enabled) {
-               reg[REG_BP]--;
-       }
-
-
-       for(i=REG_AX; i<=REG_R15; i++)
-               if(reg[i])
-                       yyerror("reg %R left allocated\n", i);
-       for(i=REG_X0; i<=REG_X15; i++)
-               if(reg[i])
-                       yyerror("reg %R left allocated\n", i);
-}
-
-int
-anyregalloc(void)
-{
-       int i, j;
-
-       for(i=REG_AX; i<=REG_R15; i++) {
-               if(reg[i] == 0)
-                       goto ok;
-               for(j=0; j<nelem(resvd); j++)
-                       if(resvd[j] == i)
-                               goto ok;
-               return 1;
-       ok:;
-       }
-       return 0;
-}
-
-static uintptr regpc[REG_R15+1 - REG_AX];
-
-/*
- * allocate register of type t, leave in n.
- * if o != N, o is desired fixed register.
- * caller must regfree(n).
- */
-void
-regalloc(Node *n, Type *t, Node *o)
-{
-       int i, et;
-
-       if(t == T)
-               fatal("regalloc: t nil");
-       et = simtype[t->etype];
-
-       switch(et) {
-       case TINT8:
-       case TUINT8:
-       case TINT16:
-       case TUINT16:
-       case TINT32:
-       case TUINT32:
-       case TINT64:
-       case TUINT64:
-       case TPTR32:
-       case TPTR64:
-       case TBOOL:
-               if(o != N && o->op == OREGISTER) {
-                       i = o->val.u.reg;
-                       if(i >= REG_AX && i <= REG_R15)
-                               goto out;
-               }
-               for(i=REG_AX; i<=REG_R15; i++)
-                       if(reg[i] == 0) {
-                               regpc[i-REG_AX] = (uintptr)getcallerpc(&n);
-                               goto out;
-                       }
-
-               flusherrors();
-               for(i=0; i+REG_AX<=REG_R15; i++)
-                       print("%d %p\n", i, regpc[i]);
-               fatal("out of fixed registers");
-
-       case TFLOAT32:
-       case TFLOAT64:
-               if(o != N && o->op == OREGISTER) {
-                       i = o->val.u.reg;
-                       if(i >= REG_X0 && i <= REG_X15)
-                               goto out;
-               }
-               for(i=REG_X0; i<=REG_X15; i++)
-                       if(reg[i] == 0)
-                               goto out;
-               fatal("out of floating registers");
-
-       case TCOMPLEX64:
-       case TCOMPLEX128:
-               tempname(n, t);
-               return;
-       }
-       fatal("regalloc: unknown type %T", t);
-       return;
-
-out:
-       reg[i]++;
-       nodreg(n, t, i);
-}
-
-void
-regfree(Node *n)
-{
-       int i;
-
-       if(n->op == ONAME)
-               return;
-       if(n->op != OREGISTER && n->op != OINDREG)
-               fatal("regfree: not a register");
-       i = n->val.u.reg;
-       if(i == REG_SP)
-               return;
-       if(i < 0 || i >= nelem(reg))
-               fatal("regfree: reg out of range");
-       if(reg[i] <= 0)
-               fatal("regfree: reg not allocated");
-       reg[i]--;
-       if(reg[i] == 0 && REG_AX <= i && i <= REG_R15)
-               regpc[i - REG_AX] = 0;
-}
-
-/*
- * generate
- *     as $c, reg
- */
-void
-gconreg(int as, vlong c, int reg)
-{
-       Node nr;
-
-       switch(as) {
-       case AADDL:
-       case AMOVL:
-       case ALEAL:
-               nodreg(&nr, types[TINT32], reg);
-               break;
-       default:
-               nodreg(&nr, types[TINT64], reg);
-       }
-
-       ginscon(as, c, &nr);
-}
-
-/*
- * generate
- *     as $c, n
- */
-void
-ginscon(int as, vlong c, Node *n2)
-{
-       Node n1, ntmp;
-
-       switch(as) {
-       case AADDL:
-       case AMOVL:
-       case ALEAL:
-               nodconst(&n1, types[TINT32], c);
-               break;
-       default:
-               nodconst(&n1, types[TINT64], c);
-       }
-
-       if(as != AMOVQ && (c < -(1LL<<31) || c >= 1LL<<31)) {
-               // cannot have 64-bit immediate in ADD, etc.
-               // instead, MOV into register first.
-               regalloc(&ntmp, types[TINT64], N);
-               gins(AMOVQ, &n1, &ntmp);
-               gins(as, &ntmp, n2);
-               regfree(&ntmp);
-               return;
-       }
-       gins(as, &n1, n2);
-}
-
-#define        CASE(a,b)       (((a)<<16)|((b)<<0))
-/*c2go int CASE(int, int); */
-
-/*
- * set up nodes representing 2^63
- */
-Node bigi;
-Node bigf;
-
-void
-bignodes(void)
-{
-       static int did;
-
-       if(did)
-               return;
-       did = 1;
-
-       nodconst(&bigi, types[TUINT64], 1);
-       mpshiftfix(bigi.val.u.xval, 63);
-
-       bigf = bigi;
-       bigf.type = types[TFLOAT64];
-       bigf.val.ctype = CTFLT;
-       bigf.val.u.fval = mal(sizeof *bigf.val.u.fval);
-       mpmovefixflt(bigf.val.u.fval, bigi.val.u.xval);
-}
-
-/*
- * generate move:
- *     t = f
- * hard part is conversions.
- */
-void
-gmove(Node *f, Node *t)
-{
-       int a, ft, tt;
-       Type *cvt;
-       Node r1, r2, r3, r4, zero, one, con;
-       Prog *p1, *p2;
-
-       if(debug['M'])
-               print("gmove %lN -> %lN\n", f, t);
-
-       ft = simsimtype(f->type);
-       tt = simsimtype(t->type);
-       cvt = t->type;
-
-       if(iscomplex[ft] || iscomplex[tt]) {
-               complexmove(f, t);
-               return;
-       }
-
-       // cannot have two memory operands
-       if(ismem(f) && ismem(t))
-               goto hard;
-
-       // convert constant to desired type
-       if(f->op == OLITERAL) {
-               convconst(&con, t->type, &f->val);
-               f = &con;
-               ft = tt;        // so big switch will choose a simple mov
-
-               // some constants can't move directly to memory.
-               if(ismem(t)) {
-                       // float constants come from memory.
-                       if(isfloat[tt])
-                               goto hard;
-
-                       // 64-bit immediates are really 32-bit sign-extended
-                       // unless moving into a register.
-                       if(isint[tt]) {
-                               if(mpcmpfixfix(con.val.u.xval, minintval[TINT32]) < 0)
-                                       goto hard;
-                               if(mpcmpfixfix(con.val.u.xval, maxintval[TINT32]) > 0)
-                                       goto hard;
-                       }
-               }
-       }
-
-       // value -> value copy, only one memory operand.
-       // figure out the instruction to use.
-       // break out of switch for one-instruction gins.
-       // goto rdst for "destination must be register".
-       // goto hard for "convert to cvt type first".
-       // otherwise handle and return.
-
-       switch(CASE(ft, tt)) {
-       default:
-               fatal("gmove %lT -> %lT", f->type, t->type);
-
-       /*
-        * integer copy and truncate
-        */
-       case CASE(TINT8, TINT8):        // same size
-       case CASE(TINT8, TUINT8):
-       case CASE(TUINT8, TINT8):
-       case CASE(TUINT8, TUINT8):
-       case CASE(TINT16, TINT8):       // truncate
-       case CASE(TUINT16, TINT8):
-       case CASE(TINT32, TINT8):
-       case CASE(TUINT32, TINT8):
-       case CASE(TINT64, TINT8):
-       case CASE(TUINT64, TINT8):
-       case CASE(TINT16, TUINT8):
-       case CASE(TUINT16, TUINT8):
-       case CASE(TINT32, TUINT8):
-       case CASE(TUINT32, TUINT8):
-       case CASE(TINT64, TUINT8):
-       case CASE(TUINT64, TUINT8):
-               a = AMOVB;
-               break;
-
-       case CASE(TINT16, TINT16):      // same size
-       case CASE(TINT16, TUINT16):
-       case CASE(TUINT16, TINT16):
-       case CASE(TUINT16, TUINT16):
-       case CASE(TINT32, TINT16):      // truncate
-       case CASE(TUINT32, TINT16):
-       case CASE(TINT64, TINT16):
-       case CASE(TUINT64, TINT16):
-       case CASE(TINT32, TUINT16):
-       case CASE(TUINT32, TUINT16):
-       case CASE(TINT64, TUINT16):
-       case CASE(TUINT64, TUINT16):
-               a = AMOVW;
-               break;
-
-       case CASE(TINT32, TINT32):      // same size
-       case CASE(TINT32, TUINT32):
-       case CASE(TUINT32, TINT32):
-       case CASE(TUINT32, TUINT32):
-               a = AMOVL;
-               break;
-
-       case CASE(TINT64, TINT32):      // truncate
-       case CASE(TUINT64, TINT32):
-       case CASE(TINT64, TUINT32):
-       case CASE(TUINT64, TUINT32):
-               a = AMOVQL;
-               break;
-
-       case CASE(TINT64, TINT64):      // same size
-       case CASE(TINT64, TUINT64):
-       case CASE(TUINT64, TINT64):
-       case CASE(TUINT64, TUINT64):
-               a = AMOVQ;
-               break;
-
-       /*
-        * integer up-conversions
-        */
-       case CASE(TINT8, TINT16):       // sign extend int8
-       case CASE(TINT8, TUINT16):
-               a = AMOVBWSX;
-               goto rdst;
-       case CASE(TINT8, TINT32):
-       case CASE(TINT8, TUINT32):
-               a = AMOVBLSX;
-               goto rdst;
-       case CASE(TINT8, TINT64):
-       case CASE(TINT8, TUINT64):
-               a = AMOVBQSX;
-               goto rdst;
-
-       case CASE(TUINT8, TINT16):      // zero extend uint8
-       case CASE(TUINT8, TUINT16):
-               a = AMOVBWZX;
-               goto rdst;
-       case CASE(TUINT8, TINT32):
-       case CASE(TUINT8, TUINT32):
-               a = AMOVBLZX;
-               goto rdst;
-       case CASE(TUINT8, TINT64):
-       case CASE(TUINT8, TUINT64):
-               a = AMOVBQZX;
-               goto rdst;
-
-       case CASE(TINT16, TINT32):      // sign extend int16
-       case CASE(TINT16, TUINT32):
-               a = AMOVWLSX;
-               goto rdst;
-       case CASE(TINT16, TINT64):
-       case CASE(TINT16, TUINT64):
-               a = AMOVWQSX;
-               goto rdst;
-
-       case CASE(TUINT16, TINT32):     // zero extend uint16
-       case CASE(TUINT16, TUINT32):
-               a = AMOVWLZX;
-               goto rdst;
-       case CASE(TUINT16, TINT64):
-       case CASE(TUINT16, TUINT64):
-               a = AMOVWQZX;
-               goto rdst;
-
-       case CASE(TINT32, TINT64):      // sign extend int32
-       case CASE(TINT32, TUINT64):
-               a = AMOVLQSX;
-               goto rdst;
-
-       case CASE(TUINT32, TINT64):     // zero extend uint32
-       case CASE(TUINT32, TUINT64):
-               // AMOVL into a register zeros the top of the register,
-               // so this is not always necessary, but if we rely on AMOVL
-               // the optimizer is almost certain to screw with us.
-               a = AMOVLQZX;
-               goto rdst;
-
-       /*
-       * float to integer
-       */
-       case CASE(TFLOAT32, TINT32):
-               a = ACVTTSS2SL;
-               goto rdst;
-
-       case CASE(TFLOAT64, TINT32):
-               a = ACVTTSD2SL;
-               goto rdst;
-
-       case CASE(TFLOAT32, TINT64):
-               a = ACVTTSS2SQ;
-               goto rdst;
-
-       case CASE(TFLOAT64, TINT64):
-               a = ACVTTSD2SQ;
-               goto rdst;
-
-       case CASE(TFLOAT32, TINT16):
-       case CASE(TFLOAT32, TINT8):
-       case CASE(TFLOAT32, TUINT16):
-       case CASE(TFLOAT32, TUINT8):
-       case CASE(TFLOAT64, TINT16):
-       case CASE(TFLOAT64, TINT8):
-       case CASE(TFLOAT64, TUINT16):
-       case CASE(TFLOAT64, TUINT8):
-               // convert via int32.
-               cvt = types[TINT32];
-               goto hard;
-
-       case CASE(TFLOAT32, TUINT32):
-       case CASE(TFLOAT64, TUINT32):
-               // convert via int64.
-               cvt = types[TINT64];
-               goto hard;
-
-       case CASE(TFLOAT32, TUINT64):
-       case CASE(TFLOAT64, TUINT64):
-               // algorithm is:
-               //      if small enough, use native float64 -> int64 conversion.
-               //      otherwise, subtract 2^63, convert, and add it back.
-               a = ACVTTSS2SQ;
-               if(ft == TFLOAT64)
-                       a = ACVTTSD2SQ;
-               bignodes();
-               regalloc(&r1, types[ft], N);
-               regalloc(&r2, types[tt], t);
-               regalloc(&r3, types[ft], N);
-               regalloc(&r4, types[tt], N);
-               gins(optoas(OAS, f->type), f, &r1);
-               gins(optoas(OCMP, f->type), &bigf, &r1);
-               p1 = gbranch(optoas(OLE, f->type), T, +1);
-               gins(a, &r1, &r2);
-               p2 = gbranch(AJMP, T, 0);
-               patch(p1, pc);
-               gins(optoas(OAS, f->type), &bigf, &r3);
-               gins(optoas(OSUB, f->type), &r3, &r1);
-               gins(a, &r1, &r2);
-               gins(AMOVQ, &bigi, &r4);
-               gins(AXORQ, &r4, &r2);
-               patch(p2, pc);
-               gmove(&r2, t);
-               regfree(&r4);
-               regfree(&r3);
-               regfree(&r2);
-               regfree(&r1);
-               return;
-
-       /*
-        * integer to float
-        */
-       case CASE(TINT32, TFLOAT32):
-               a = ACVTSL2SS;
-               goto rdst;
-
-
-       case CASE(TINT32, TFLOAT64):
-               a = ACVTSL2SD;
-               goto rdst;
-
-       case CASE(TINT64, TFLOAT32):
-               a = ACVTSQ2SS;
-               goto rdst;
-
-       case CASE(TINT64, TFLOAT64):
-               a = ACVTSQ2SD;
-               goto rdst;
-
-       case CASE(TINT16, TFLOAT32):
-       case CASE(TINT16, TFLOAT64):
-       case CASE(TINT8, TFLOAT32):
-       case CASE(TINT8, TFLOAT64):
-       case CASE(TUINT16, TFLOAT32):
-       case CASE(TUINT16, TFLOAT64):
-       case CASE(TUINT8, TFLOAT32):
-       case CASE(TUINT8, TFLOAT64):
-               // convert via int32
-               cvt = types[TINT32];
-               goto hard;
-
-       case CASE(TUINT32, TFLOAT32):
-       case CASE(TUINT32, TFLOAT64):
-               // convert via int64.
-               cvt = types[TINT64];
-               goto hard;
-
-       case CASE(TUINT64, TFLOAT32):
-       case CASE(TUINT64, TFLOAT64):
-               // algorithm is:
-               //      if small enough, use native int64 -> uint64 conversion.
-               //      otherwise, halve (rounding to odd?), convert, and double.
-               a = ACVTSQ2SS;
-               if(tt == TFLOAT64)
-                       a = ACVTSQ2SD;
-               nodconst(&zero, types[TUINT64], 0);
-               nodconst(&one, types[TUINT64], 1);
-               regalloc(&r1, f->type, f);
-               regalloc(&r2, t->type, t);
-               regalloc(&r3, f->type, N);
-               regalloc(&r4, f->type, N);
-               gmove(f, &r1);
-               gins(ACMPQ, &r1, &zero);
-               p1 = gbranch(AJLT, T, +1);
-               gins(a, &r1, &r2);
-               p2 = gbranch(AJMP, T, 0);
-               patch(p1, pc);
-               gmove(&r1, &r3);
-               gins(ASHRQ, &one, &r3);
-               gmove(&r1, &r4);
-               gins(AANDL, &one, &r4);
-               gins(AORQ, &r4, &r3);
-               gins(a, &r3, &r2);
-               gins(optoas(OADD, t->type), &r2, &r2);
-               patch(p2, pc);
-               gmove(&r2, t);
-               regfree(&r4);
-               regfree(&r3);
-               regfree(&r2);
-               regfree(&r1);
-               return;
-
-       /*
-        * float to float
-        */
-       case CASE(TFLOAT32, TFLOAT32):
-               a = AMOVSS;
-               break;
-
-       case CASE(TFLOAT64, TFLOAT64):
-               a = AMOVSD;
-               break;
-
-       case CASE(TFLOAT32, TFLOAT64):
-               a = ACVTSS2SD;
-               goto rdst;
-
-       case CASE(TFLOAT64, TFLOAT32):
-               a = ACVTSD2SS;
-               goto rdst;
-       }
-
-       gins(a, f, t);
-       return;
-
-rdst:
-       // requires register destination
-       regalloc(&r1, t->type, t);
-       gins(a, f, &r1);
-       gmove(&r1, t);
-       regfree(&r1);
-       return;
-
-hard:
-       // requires register intermediate
-       regalloc(&r1, cvt, t);
-       gmove(f, &r1);
-       gmove(&r1, t);
-       regfree(&r1);
-       return;
-}
-
-int
-samaddr(Node *f, Node *t)
-{
-
-       if(f->op != t->op)
-               return 0;
-
-       switch(f->op) {
-       case OREGISTER:
-               if(f->val.u.reg != t->val.u.reg)
-                       break;
-               return 1;
-       }
-       return 0;
-}
-
-/*
- * generate one instruction:
- *     as f, t
- */
-Prog*
-gins(int as, Node *f, Node *t)
-{
-//     Node nod;
-       int32 w;
-       Prog *p;
-       Addr af, at;
-
-//     if(f != N && f->op == OINDEX) {
-//             regalloc(&nod, &regnode, Z);
-//             v = constnode.vconst;
-//             cgen(f->right, &nod);
-//             constnode.vconst = v;
-//             idx.reg = nod.reg;
-//             regfree(&nod);
-//     }
-//     if(t != N && t->op == OINDEX) {
-//             regalloc(&nod, &regnode, Z);
-//             v = constnode.vconst;
-//             cgen(t->right, &nod);
-//             constnode.vconst = v;
-//             idx.reg = nod.reg;
-//             regfree(&nod);
-//     }
-
-       switch(as) {
-       case AMOVB:
-       case AMOVW:
-       case AMOVL:
-       case AMOVQ:
-       case AMOVSS:
-       case AMOVSD:
-               if(f != N && t != N && samaddr(f, t))
-                       return nil;
-               break;
-       
-       case ALEAQ:
-               if(f != N && isconst(f, CTNIL)) {
-                       fatal("gins LEAQ nil %T", f->type);
-               }
-               break;
-       }
-
-       memset(&af, 0, sizeof af);
-       memset(&at, 0, sizeof at);
-       if(f != N)
-               naddr(f, &af, 1);
-       if(t != N)
-               naddr(t, &at, 1);
-       p = prog(as);
-       if(f != N)
-               p->from = af;
-       if(t != N)
-               p->to = at;
-       if(debug['g'])
-               print("%P\n", p);
-
-       w = 0;
-       switch(as) {
-       case AMOVB:
-               w = 1;
-               break;
-       case AMOVW:
-               w = 2;
-               break;
-       case AMOVL:
-               w = 4;
-               break;
-       case AMOVQ:
-               w = 8;
-               break;
-       }
-       if(w != 0 && ((f != N && af.width < w) || (t != N && at.width > w))) {
-               dump("f", f);
-               dump("t", t);
-               fatal("bad width: %P (%d, %d)\n", p, af.width, at.width);
-       }
-       if(p->to.type == TYPE_ADDR && w > 0)
-               fatal("bad use of addr: %P", p);
-
-       return p;
-}
-
-void
-fixlargeoffset(Node *n)
-{
-       Node a;
-
-       if(n == N)
-               return;
-       if(n->op != OINDREG)
-               return;
-       if(n->val.u.reg == REG_SP) // stack offset cannot be large
-               return;
-       if(n->xoffset != (int32)n->xoffset) {
-               // offset too large, add to register instead.
-               a = *n;
-               a.op = OREGISTER;
-               a.type = types[tptr];
-               a.xoffset = 0;
-               cgen_checknil(&a);
-               ginscon(optoas(OADD, types[tptr]), n->xoffset, &a);
-               n->xoffset = 0;
-       }
-}
-
-/*
- * return Axxx for Oxxx on type t.
- */
-int
-optoas(int op, Type *t)
-{
-       int a;
-
-       if(t == T)
-               fatal("optoas: t is nil");
-
-       a = AXXX;
-       switch(CASE(op, simtype[t->etype])) {
-       default:
-               fatal("optoas: no entry %O-%T", op, t);
-               break;
-
-       case CASE(OADDR, TPTR32):
-               a = ALEAL;
-               break;
-
-       case CASE(OADDR, TPTR64):
-               a = ALEAQ;
-               break;
-
-       case CASE(OEQ, TBOOL):
-       case CASE(OEQ, TINT8):
-       case CASE(OEQ, TUINT8):
-       case CASE(OEQ, TINT16):
-       case CASE(OEQ, TUINT16):
-       case CASE(OEQ, TINT32):
-       case CASE(OEQ, TUINT32):
-       case CASE(OEQ, TINT64):
-       case CASE(OEQ, TUINT64):
-       case CASE(OEQ, TPTR32):
-       case CASE(OEQ, TPTR64):
-       case CASE(OEQ, TFLOAT32):
-       case CASE(OEQ, TFLOAT64):
-               a = AJEQ;
-               break;
-
-       case CASE(ONE, TBOOL):
-       case CASE(ONE, TINT8):
-       case CASE(ONE, TUINT8):
-       case CASE(ONE, TINT16):
-       case CASE(ONE, TUINT16):
-       case CASE(ONE, TINT32):
-       case CASE(ONE, TUINT32):
-       case CASE(ONE, TINT64):
-       case CASE(ONE, TUINT64):
-       case CASE(ONE, TPTR32):
-       case CASE(ONE, TPTR64):
-       case CASE(ONE, TFLOAT32):
-       case CASE(ONE, TFLOAT64):
-               a = AJNE;
-               break;
-
-       case CASE(OLT, TINT8):
-       case CASE(OLT, TINT16):
-       case CASE(OLT, TINT32):
-       case CASE(OLT, TINT64):
-               a = AJLT;
-               break;
-
-       case CASE(OLT, TUINT8):
-       case CASE(OLT, TUINT16):
-       case CASE(OLT, TUINT32):
-       case CASE(OLT, TUINT64):
-               a = AJCS;
-               break;
-
-       case CASE(OLE, TINT8):
-       case CASE(OLE, TINT16):
-       case CASE(OLE, TINT32):
-       case CASE(OLE, TINT64):
-               a = AJLE;
-               break;
-
-       case CASE(OLE, TUINT8):
-       case CASE(OLE, TUINT16):
-       case CASE(OLE, TUINT32):
-       case CASE(OLE, TUINT64):
-               a = AJLS;
-               break;
-
-       case CASE(OGT, TINT8):
-       case CASE(OGT, TINT16):
-       case CASE(OGT, TINT32):
-       case CASE(OGT, TINT64):
-               a = AJGT;
-               break;
-
-       case CASE(OGT, TUINT8):
-       case CASE(OGT, TUINT16):
-       case CASE(OGT, TUINT32):
-       case CASE(OGT, TUINT64):
-       case CASE(OLT, TFLOAT32):
-       case CASE(OLT, TFLOAT64):
-               a = AJHI;
-               break;
-
-       case CASE(OGE, TINT8):
-       case CASE(OGE, TINT16):
-       case CASE(OGE, TINT32):
-       case CASE(OGE, TINT64):
-               a = AJGE;
-               break;
-
-       case CASE(OGE, TUINT8):
-       case CASE(OGE, TUINT16):
-       case CASE(OGE, TUINT32):
-       case CASE(OGE, TUINT64):
-       case CASE(OLE, TFLOAT32):
-       case CASE(OLE, TFLOAT64):
-               a = AJCC;
-               break;
-
-       case CASE(OCMP, TBOOL):
-       case CASE(OCMP, TINT8):
-       case CASE(OCMP, TUINT8):
-               a = ACMPB;
-               break;
-
-       case CASE(OCMP, TINT16):
-       case CASE(OCMP, TUINT16):
-               a = ACMPW;
-               break;
-
-       case CASE(OCMP, TINT32):
-       case CASE(OCMP, TUINT32):
-       case CASE(OCMP, TPTR32):
-               a = ACMPL;
-               break;
-
-       case CASE(OCMP, TINT64):
-       case CASE(OCMP, TUINT64):
-       case CASE(OCMP, TPTR64):
-               a = ACMPQ;
-               break;
-
-       case CASE(OCMP, TFLOAT32):
-               a = AUCOMISS;
-               break;
-
-       case CASE(OCMP, TFLOAT64):
-               a = AUCOMISD;
-               break;
-
-       case CASE(OAS, TBOOL):
-       case CASE(OAS, TINT8):
-       case CASE(OAS, TUINT8):
-               a = AMOVB;
-               break;
-
-       case CASE(OAS, TINT16):
-       case CASE(OAS, TUINT16):
-               a = AMOVW;
-               break;
-
-       case CASE(OAS, TINT32):
-       case CASE(OAS, TUINT32):
-       case CASE(OAS, TPTR32):
-               a = AMOVL;
-               break;
-
-       case CASE(OAS, TINT64):
-       case CASE(OAS, TUINT64):
-       case CASE(OAS, TPTR64):
-               a = AMOVQ;
-               break;
-
-       case CASE(OAS, TFLOAT32):
-               a = AMOVSS;
-               break;
-
-       case CASE(OAS, TFLOAT64):
-               a = AMOVSD;
-               break;
-
-       case CASE(OADD, TINT8):
-       case CASE(OADD, TUINT8):
-               a = AADDB;
-               break;
-
-       case CASE(OADD, TINT16):
-       case CASE(OADD, TUINT16):
-               a = AADDW;
-               break;
-
-       case CASE(OADD, TINT32):
-       case CASE(OADD, TUINT32):
-       case CASE(OADD, TPTR32):
-               a = AADDL;
-               break;
-
-       case CASE(OADD, TINT64):
-       case CASE(OADD, TUINT64):
-       case CASE(OADD, TPTR64):
-               a = AADDQ;
-               break;
-
-       case CASE(OADD, TFLOAT32):
-               a = AADDSS;
-               break;
-
-       case CASE(OADD, TFLOAT64):
-               a = AADDSD;
-               break;
-
-       case CASE(OSUB, TINT8):
-       case CASE(OSUB, TUINT8):
-               a = ASUBB;
-               break;
-
-       case CASE(OSUB, TINT16):
-       case CASE(OSUB, TUINT16):
-               a = ASUBW;
-               break;
-
-       case CASE(OSUB, TINT32):
-       case CASE(OSUB, TUINT32):
-       case CASE(OSUB, TPTR32):
-               a = ASUBL;
-               break;
-
-       case CASE(OSUB, TINT64):
-       case CASE(OSUB, TUINT64):
-       case CASE(OSUB, TPTR64):
-               a = ASUBQ;
-               break;
-
-       case CASE(OSUB, TFLOAT32):
-               a = ASUBSS;
-               break;
-
-       case CASE(OSUB, TFLOAT64):
-               a = ASUBSD;
-               break;
-
-       case CASE(OINC, TINT8):
-       case CASE(OINC, TUINT8):
-               a = AINCB;
-               break;
-
-       case CASE(OINC, TINT16):
-       case CASE(OINC, TUINT16):
-               a = AINCW;
-               break;
-
-       case CASE(OINC, TINT32):
-       case CASE(OINC, TUINT32):
-       case CASE(OINC, TPTR32):
-               a = AINCL;
-               break;
-
-       case CASE(OINC, TINT64):
-       case CASE(OINC, TUINT64):
-       case CASE(OINC, TPTR64):
-               a = AINCQ;
-               break;
-
-       case CASE(ODEC, TINT8):
-       case CASE(ODEC, TUINT8):
-               a = ADECB;
-               break;
-
-       case CASE(ODEC, TINT16):
-       case CASE(ODEC, TUINT16):
-               a = ADECW;
-               break;
-
-       case CASE(ODEC, TINT32):
-       case CASE(ODEC, TUINT32):
-       case CASE(ODEC, TPTR32):
-               a = ADECL;
-               break;
-
-       case CASE(ODEC, TINT64):
-       case CASE(ODEC, TUINT64):
-       case CASE(ODEC, TPTR64):
-               a = ADECQ;
-               break;
-
-       case CASE(OMINUS, TINT8):
-       case CASE(OMINUS, TUINT8):
-               a = ANEGB;
-               break;
-
-       case CASE(OMINUS, TINT16):
-       case CASE(OMINUS, TUINT16):
-               a = ANEGW;
-               break;
-
-       case CASE(OMINUS, TINT32):
-       case CASE(OMINUS, TUINT32):
-       case CASE(OMINUS, TPTR32):
-               a = ANEGL;
-               break;
-
-       case CASE(OMINUS, TINT64):
-       case CASE(OMINUS, TUINT64):
-       case CASE(OMINUS, TPTR64):
-               a = ANEGQ;
-               break;
-
-       case CASE(OAND, TINT8):
-       case CASE(OAND, TUINT8):
-               a = AANDB;
-               break;
-
-       case CASE(OAND, TINT16):
-       case CASE(OAND, TUINT16):
-               a = AANDW;
-               break;
-
-       case CASE(OAND, TINT32):
-       case CASE(OAND, TUINT32):
-       case CASE(OAND, TPTR32):
-               a = AANDL;
-               break;
-
-       case CASE(OAND, TINT64):
-       case CASE(OAND, TUINT64):
-       case CASE(OAND, TPTR64):
-               a = AANDQ;
-               break;
-
-       case CASE(OOR, TINT8):
-       case CASE(OOR, TUINT8):
-               a = AORB;
-               break;
-
-       case CASE(OOR, TINT16):
-       case CASE(OOR, TUINT16):
-               a = AORW;
-               break;
-
-       case CASE(OOR, TINT32):
-       case CASE(OOR, TUINT32):
-       case CASE(OOR, TPTR32):
-               a = AORL;
-               break;
-
-       case CASE(OOR, TINT64):
-       case CASE(OOR, TUINT64):
-       case CASE(OOR, TPTR64):
-               a = AORQ;
-               break;
-
-       case CASE(OXOR, TINT8):
-       case CASE(OXOR, TUINT8):
-               a = AXORB;
-               break;
-
-       case CASE(OXOR, TINT16):
-       case CASE(OXOR, TUINT16):
-               a = AXORW;
-               break;
-
-       case CASE(OXOR, TINT32):
-       case CASE(OXOR, TUINT32):
-       case CASE(OXOR, TPTR32):
-               a = AXORL;
-               break;
-
-       case CASE(OXOR, TINT64):
-       case CASE(OXOR, TUINT64):
-       case CASE(OXOR, TPTR64):
-               a = AXORQ;
-               break;
-
-       case CASE(OLROT, TINT8):
-       case CASE(OLROT, TUINT8):
-               a = AROLB;
-               break;
-
-       case CASE(OLROT, TINT16):
-       case CASE(OLROT, TUINT16):
-               a = AROLW;
-               break;
-
-       case CASE(OLROT, TINT32):
-       case CASE(OLROT, TUINT32):
-       case CASE(OLROT, TPTR32):
-               a = AROLL;
-               break;
-
-       case CASE(OLROT, TINT64):
-       case CASE(OLROT, TUINT64):
-       case CASE(OLROT, TPTR64):
-               a = AROLQ;
-               break;
-
-       case CASE(OLSH, TINT8):
-       case CASE(OLSH, TUINT8):
-               a = ASHLB;
-               break;
-
-       case CASE(OLSH, TINT16):
-       case CASE(OLSH, TUINT16):
-               a = ASHLW;
-               break;
-
-       case CASE(OLSH, TINT32):
-       case CASE(OLSH, TUINT32):
-       case CASE(OLSH, TPTR32):
-               a = ASHLL;
-               break;
-
-       case CASE(OLSH, TINT64):
-       case CASE(OLSH, TUINT64):
-       case CASE(OLSH, TPTR64):
-               a = ASHLQ;
-               break;
-
-       case CASE(ORSH, TUINT8):
-               a = ASHRB;
-               break;
-
-       case CASE(ORSH, TUINT16):
-               a = ASHRW;
-               break;
-
-       case CASE(ORSH, TUINT32):
-       case CASE(ORSH, TPTR32):
-               a = ASHRL;
-               break;
-
-       case CASE(ORSH, TUINT64):
-       case CASE(ORSH, TPTR64):
-               a = ASHRQ;
-               break;
-
-       case CASE(ORSH, TINT8):
-               a = ASARB;
-               break;
-
-       case CASE(ORSH, TINT16):
-               a = ASARW;
-               break;
-
-       case CASE(ORSH, TINT32):
-               a = ASARL;
-               break;
-
-       case CASE(ORSH, TINT64):
-               a = ASARQ;
-               break;
-
-       case CASE(ORROTC, TINT8):
-       case CASE(ORROTC, TUINT8):
-               a = ARCRB;
-               break;
-
-       case CASE(ORROTC, TINT16):
-       case CASE(ORROTC, TUINT16):
-               a = ARCRW;
-               break;
-
-       case CASE(ORROTC, TINT32):
-       case CASE(ORROTC, TUINT32):
-               a = ARCRL;
-               break;
-
-       case CASE(ORROTC, TINT64):
-       case CASE(ORROTC, TUINT64):
-               a = ARCRQ;
-               break;
-
-       case CASE(OHMUL, TINT8):
-       case CASE(OMUL, TINT8):
-       case CASE(OMUL, TUINT8):
-               a = AIMULB;
-               break;
-
-       case CASE(OHMUL, TINT16):
-       case CASE(OMUL, TINT16):
-       case CASE(OMUL, TUINT16):
-               a = AIMULW;
-               break;
-
-       case CASE(OHMUL, TINT32):
-       case CASE(OMUL, TINT32):
-       case CASE(OMUL, TUINT32):
-       case CASE(OMUL, TPTR32):
-               a = AIMULL;
-               break;
-
-       case CASE(OHMUL, TINT64):
-       case CASE(OMUL, TINT64):
-       case CASE(OMUL, TUINT64):
-       case CASE(OMUL, TPTR64):
-               a = AIMULQ;
-               break;
-
-       case CASE(OHMUL, TUINT8):
-               a = AMULB;
-               break;
-
-       case CASE(OHMUL, TUINT16):
-               a = AMULW;
-               break;
-
-       case CASE(OHMUL, TUINT32):
-       case CASE(OHMUL, TPTR32):
-               a = AMULL;
-               break;
-
-       case CASE(OHMUL, TUINT64):
-       case CASE(OHMUL, TPTR64):
-               a = AMULQ;
-               break;
-
-       case CASE(OMUL, TFLOAT32):
-               a = AMULSS;
-               break;
-
-       case CASE(OMUL, TFLOAT64):
-               a = AMULSD;
-               break;
-
-       case CASE(ODIV, TINT8):
-       case CASE(OMOD, TINT8):
-               a = AIDIVB;
-               break;
-
-       case CASE(ODIV, TUINT8):
-       case CASE(OMOD, TUINT8):
-               a = ADIVB;
-               break;
-
-       case CASE(ODIV, TINT16):
-       case CASE(OMOD, TINT16):
-               a = AIDIVW;
-               break;
-
-       case CASE(ODIV, TUINT16):
-       case CASE(OMOD, TUINT16):
-               a = ADIVW;
-               break;
-
-       case CASE(ODIV, TINT32):
-       case CASE(OMOD, TINT32):
-               a = AIDIVL;
-               break;
-
-       case CASE(ODIV, TUINT32):
-       case CASE(ODIV, TPTR32):
-       case CASE(OMOD, TUINT32):
-       case CASE(OMOD, TPTR32):
-               a = ADIVL;
-               break;
-
-       case CASE(ODIV, TINT64):
-       case CASE(OMOD, TINT64):
-               a = AIDIVQ;
-               break;
-
-       case CASE(ODIV, TUINT64):
-       case CASE(ODIV, TPTR64):
-       case CASE(OMOD, TUINT64):
-       case CASE(OMOD, TPTR64):
-               a = ADIVQ;
-               break;
-
-       case CASE(OEXTEND, TINT16):
-               a = ACWD;
-               break;
-
-       case CASE(OEXTEND, TINT32):
-               a = ACDQ;
-               break;
-
-       case CASE(OEXTEND, TINT64):
-               a = ACQO;
-               break;
-
-       case CASE(ODIV, TFLOAT32):
-               a = ADIVSS;
-               break;
-
-       case CASE(ODIV, TFLOAT64):
-               a = ADIVSD;
-               break;
-
-       }
-       return a;
-}
-
-enum
-{
-       ODynam          = 1<<0,
-       OAddable        = 1<<1,
-};
-
-static Node    clean[20];
-static int     cleani = 0;
-
-int
-xgen(Node *n, Node *a, int o)
-{
-       regalloc(a, types[tptr], N);
-
-       if(o & ODynam)
-       if(n->addable)
-       if(n->op != OINDREG)
-       if(n->op != OREGISTER)
-               return 1;
-
-       agen(n, a);
-       return 0;
-}
-
-void
-sudoclean(void)
-{
-       if(clean[cleani-1].op != OEMPTY)
-               regfree(&clean[cleani-1]);
-       if(clean[cleani-2].op != OEMPTY)
-               regfree(&clean[cleani-2]);
-       cleani -= 2;
-}
-
-/*
- * generate code to compute address of n,
- * a reference to a (perhaps nested) field inside
- * an array or struct.
- * return 0 on failure, 1 on success.
- * on success, leaves usable address in a.
- *
- * caller is responsible for calling sudoclean
- * after successful sudoaddable,
- * to release the register used for a.
- */
-int
-sudoaddable(int as, Node *n, Addr *a)
-{
-       int o, i;
-       int64 oary[10];
-       int64 v, w;
-       Node n1, n2, n3, n4, *nn, *l, *r;
-       Node *reg, *reg1;
-       Prog *p1;
-       Type *t;
-
-       if(n->type == T)
-               return 0;
-
-       memset(a, 0, sizeof *a);
-
-       switch(n->op) {
-       case OLITERAL:
-               if(!isconst(n, CTINT))
-                       break;
-               v = mpgetfix(n->val.u.xval);
-               if(v >= 32000 || v <= -32000)
-                       break;
-               goto lit;
-
-       case ODOT:
-       case ODOTPTR:
-               cleani += 2;
-               reg = &clean[cleani-1];
-               reg1 = &clean[cleani-2];
-               reg->op = OEMPTY;
-               reg1->op = OEMPTY;
-               goto odot;
-
-       case OINDEX:
-               return 0;
-               // disabled: OINDEX case is now covered by agenr
-               // for a more suitable register allocation pattern.
-               if(n->left->type->etype == TSTRING)
-                       return 0;
-               goto oindex;
-       }
-       return 0;
-
-lit:
-       switch(as) {
-       default:
-               return 0;
-       case AADDB: case AADDW: case AADDL: case AADDQ:
-       case ASUBB: case ASUBW: case ASUBL: case ASUBQ:
-       case AANDB: case AANDW: case AANDL: case AANDQ:
-       case AORB:  case AORW:  case AORL:  case AORQ:
-       case AXORB: case AXORW: case AXORL: case AXORQ:
-       case AINCB: case AINCW: case AINCL: case AINCQ:
-       case ADECB: case ADECW: case ADECL: case ADECQ:
-       case AMOVB: case AMOVW: case AMOVL: case AMOVQ:
-               break;
-       }
-
-       cleani += 2;
-       reg = &clean[cleani-1];
-       reg1 = &clean[cleani-2];
-       reg->op = OEMPTY;
-       reg1->op = OEMPTY;
-       naddr(n, a, 1);
-       goto yes;
-
-odot:
-       o = dotoffset(n, oary, &nn);
-       if(nn == N)
-               goto no;
-
-       if(nn->addable && o == 1 && oary[0] >= 0) {
-               // directly addressable set of DOTs
-               n1 = *nn;
-               n1.type = n->type;
-               n1.xoffset += oary[0];
-               naddr(&n1, a, 1);
-               goto yes;
-       }
-
-       regalloc(reg, types[tptr], N);
-       n1 = *reg;
-       n1.op = OINDREG;
-       if(oary[0] >= 0) {
-               agen(nn, reg);
-               n1.xoffset = oary[0];
-       } else {
-               cgen(nn, reg);
-               cgen_checknil(reg);
-               n1.xoffset = -(oary[0]+1);
-       }
-
-       for(i=1; i<o; i++) {
-               if(oary[i] >= 0)
-                       fatal("can't happen");
-               gins(movptr, &n1, reg);
-               cgen_checknil(reg);
-               n1.xoffset = -(oary[i]+1);
-       }
-
-       a->type = TYPE_NONE;
-       a->index = TYPE_NONE;
-       fixlargeoffset(&n1);
-       naddr(&n1, a, 1);
-       goto yes;
-
-oindex:
-       l = n->left;
-       r = n->right;
-       if(l->ullman >= UINF && r->ullman >= UINF)
-               return 0;
-
-       // set o to type of array
-       o = 0;
-       if(isptr[l->type->etype])
-               fatal("ptr ary");
-       if(l->type->etype != TARRAY)
-               fatal("not ary");
-       if(l->type->bound < 0)
-               o |= ODynam;
-
-       w = n->type->width;
-       if(isconst(r, CTINT))
-               goto oindex_const;
-
-       switch(w) {
-       default:
-               return 0;
-       case 1:
-       case 2:
-       case 4:
-       case 8:
-               break;
-       }
-
-       cleani += 2;
-       reg = &clean[cleani-1];
-       reg1 = &clean[cleani-2];
-       reg->op = OEMPTY;
-       reg1->op = OEMPTY;
-
-       // load the array (reg)
-       if(l->ullman > r->ullman) {
-               if(xgen(l, reg, o))
-                       o |= OAddable;
-       }
-
-       // load the index (reg1)
-       t = types[TUINT64];
-       if(issigned[r->type->etype])
-               t = types[TINT64];
-       regalloc(reg1, t, N);
-       regalloc(&n3, r->type, reg1);
-       cgen(r, &n3);
-       gmove(&n3, reg1);
-       regfree(&n3);
-
-       // load the array (reg)
-       if(l->ullman <= r->ullman) {
-               if(xgen(l, reg, o))
-                       o |= OAddable;
-       }
-
-       // check bounds
-       if(!debug['B'] && !n->bounded) {
-               // check bounds
-               n4.op = OXXX;
-               t = types[simtype[TUINT]];
-               if(o & ODynam) {
-                       if(o & OAddable) {
-                               n2 = *l;
-                               n2.xoffset += Array_nel;
-                               n2.type = types[simtype[TUINT]];
-                       } else {
-                               n2 = *reg;
-                               n2.xoffset = Array_nel;
-                               n2.op = OINDREG;
-                               n2.type = types[simtype[TUINT]];
-                       }
-               } else {
-                       if(is64(r->type))
-                               t = types[TUINT64];
-                       nodconst(&n2, types[TUINT64], l->type->bound);
-               }
-               gins(optoas(OCMP, t), reg1, &n2);
-               p1 = gbranch(optoas(OLT, t), T, +1);
-               if(n4.op != OXXX)
-                       regfree(&n4);
-               ginscall(panicindex, -1);
-               patch(p1, pc);
-       }
-
-       if(o & ODynam) {
-               if(o & OAddable) {
-                       n2 = *l;
-                       n2.xoffset += Array_array;
-                       n2.type = types[tptr];
-                       gmove(&n2, reg);
-               } else {
-                       n2 = *reg;
-                       n2.op = OINDREG;
-                       n2.xoffset = Array_array;
-                       n2.type = types[tptr];
-                       gmove(&n2, reg);
-               }
-       }
-
-       if(o & OAddable) {
-               naddr(reg1, a, 1);
-               a->offset = 0;
-               a->scale = w;
-               a->index = a->reg;
-               a->type = TYPE_MEM;
-               a->reg = reg->val.u.reg;
-       } else {
-               naddr(reg1, a, 1);
-               a->offset = 0;
-               a->scale = w;
-               a->index = a->reg;
-               a->type = TYPE_MEM;
-               a->reg = reg->val.u.reg;
-       }
-
-       goto yes;
-
-oindex_const:
-       // index is constant
-       // can check statically and
-       // can multiply by width statically
-
-       v = mpgetfix(r->val.u.xval);
-
-       if(sudoaddable(as, l, a))
-               goto oindex_const_sudo;
-
-       cleani += 2;
-       reg = &clean[cleani-1];
-       reg1 = &clean[cleani-2];
-       reg->op = OEMPTY;
-       reg1->op = OEMPTY;
-
-       if(o & ODynam) {
-               regalloc(reg, types[tptr], N);
-               agen(l, reg);
-       
-               if(!debug['B'] && !n->bounded) {
-                       n1 = *reg;
-                       n1.op = OINDREG;
-                       n1.type = types[tptr];
-                       n1.xoffset = Array_nel;
-                       nodconst(&n2, types[TUINT64], v);
-                       gins(optoas(OCMP, types[simtype[TUINT]]), &n1, &n2);
-                       p1 = gbranch(optoas(OGT, types[simtype[TUINT]]), T, +1);
-                       ginscall(panicindex, -1);
-                       patch(p1, pc);
-               }
-
-               n1 = *reg;
-               n1.op = OINDREG;
-               n1.type = types[tptr];
-               n1.xoffset = Array_array;
-               gmove(&n1, reg);
-
-               n2 = *reg;
-               n2.op = OINDREG;
-               n2.xoffset = v*w;
-               fixlargeoffset(&n2);
-               a->type = TYPE_NONE;
-               a->index = TYPE_NONE;
-               naddr(&n2, a, 1);
-               goto yes;
-       }
-       
-       igen(l, &n1, N);
-       if(n1.op == OINDREG) {
-               *reg = n1;
-               reg->op = OREGISTER;
-       }
-       n1.xoffset += v*w;
-       fixlargeoffset(&n1);
-       a->type = TYPE_NONE;
-       a->index= TYPE_NONE;
-       naddr(&n1, a, 1);
-       goto yes;
-
-oindex_const_sudo:
-       if((o & ODynam) == 0) {
-               // array indexed by a constant
-               a->offset += v*w;
-               goto yes;
-       }
-
-       // slice indexed by a constant
-       if(!debug['B'] && !n->bounded) {
-               a->offset += Array_nel;
-               nodconst(&n2, types[TUINT64], v);
-               p1 = gins(optoas(OCMP, types[simtype[TUINT]]), N, &n2);
-               p1->from = *a;
-               p1 = gbranch(optoas(OGT, types[simtype[TUINT]]), T, +1);
-               ginscall(panicindex, -1);
-               patch(p1, pc);
-               a->offset -= Array_nel;
-       }
-
-       a->offset += Array_array;
-       reg = &clean[cleani-1];
-       if(reg->op == OEMPTY)
-               regalloc(reg, types[tptr], N);
-
-       p1 = gins(movptr, N, reg);
-       p1->from = *a;
-
-       n2 = *reg;
-       n2.op = OINDREG;
-       n2.xoffset = v*w;
-       fixlargeoffset(&n2);
-       a->type = TYPE_NONE;
-       a->index = TYPE_NONE;
-       naddr(&n2, a, 1);
-       goto yes;
-
-yes:
-       return 1;
-
-no:
-       sudoclean();
-       return 0;
-}
similarity index 100%
rename from src/cmd/new6g/gsubr.go
rename to src/cmd/6g/gsubr.go
diff --git a/src/cmd/6g/peep.c b/src/cmd/6g/peep.c
deleted file mode 100644 (file)
index 261cb6e..0000000
+++ /dev/null
@@ -1,988 +0,0 @@
-// Derived from Inferno utils/6c/peep.c
-// http://code.google.com/p/inferno-os/source/browse/utils/6c/peep.c
-//
-//     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 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 <u.h>
-#include <libc.h>
-#include "gg.h"
-#include "../gc/popt.h"
-
-static void    conprop(Flow *r);
-static void    elimshortmov(Graph *g);
-static int     prevl(Flow *r, int reg);
-static void    pushback(Flow *r);
-static int     regconsttyp(Adr*);
-static int     subprop(Flow*);
-static int     copyprop(Graph*, Flow*);
-static int     copy1(Adr*, Adr*, Flow*, int);
-static int     copyas(Adr*, Adr*);
-static int     copyau(Adr*, Adr*);
-static int     copysub(Adr*, Adr*, Adr*, int);
-static int     copyu(Prog*, Adr*, Adr*);
-
-static uint32  gactive;
-
-enum
-{
-       exregoffset = REG_R15,
-};
-
-// do we need the carry bit
-static int
-needc(Prog *p)
-{
-       ProgInfo info;
-
-       while(p != P) {
-               proginfo(&info, p);
-               if(info.flags & UseCarry)
-                       return 1;
-               if(info.flags & (SetCarry|KillCarry))
-                       return 0;
-               p = p->link;
-       }
-       return 0;
-}
-
-static Flow*
-rnops(Flow *r)
-{
-       Prog *p;
-       Flow *r1;
-
-       if(r != nil)
-       for(;;) {
-               p = r->prog;
-               if(p->as != ANOP || p->from.type != TYPE_NONE || p->to.type != TYPE_NONE)
-                       break;
-               r1 = uniqs(r);
-               if(r1 == nil)
-                       break;
-               r = r1;
-       }
-       return r;
-}
-
-void
-peep(Prog *firstp)
-{
-       Flow *r, *r1;
-       Graph *g;
-       Prog *p, *p1;
-       int t;
-
-       g = flowstart(firstp, 0);
-       if(g == nil)
-               return;
-       gactive = 0;
-
-       // byte, word arithmetic elimination.
-       elimshortmov(g);
-
-       // constant propagation
-       // find MOV $con,R followed by
-       // another MOV $con,R without
-       // setting R in the interim
-       for(r=g->start; r!=nil; r=r->link) {
-               p = r->prog;
-               switch(p->as) {
-               case ALEAL:
-               case ALEAQ:
-                       if(regtyp(&p->to))
-                       if(p->from.sym != nil)
-                       if(p->from.index == REG_NONE)
-                               conprop(r);
-                       break;
-
-               case AMOVB:
-               case AMOVW:
-               case AMOVL:
-               case AMOVQ:
-               case AMOVSS:
-               case AMOVSD:
-                       if(regtyp(&p->to))
-                       if(p->from.type == TYPE_CONST || p->from.type == TYPE_FCONST)
-                               conprop(r);
-                       break;
-               }
-       }
-
-loop1:
-       if(debug['P'] && debug['v'])
-               dumpit("loop1", g->start, 0);
-
-       t = 0;
-       for(r=g->start; r!=nil; r=r->link) {
-               p = r->prog;
-               switch(p->as) {
-               case AMOVL:
-               case AMOVQ:
-               case AMOVSS:
-               case AMOVSD:
-                       if(regtyp(&p->to))
-                       if(regtyp(&p->from)) {
-                               if(copyprop(g, r)) {
-                                       excise(r);
-                                       t++;
-                               } else
-                               if(subprop(r) && copyprop(g, r)) {
-                                       excise(r);
-                                       t++;
-                               }
-                       }
-                       break;
-
-               case AMOVBLZX:
-               case AMOVWLZX:
-               case AMOVBLSX:
-               case AMOVWLSX:
-                       if(regtyp(&p->to)) {
-                               r1 = rnops(uniqs(r));
-                               if(r1 != nil) {
-                                       p1 = r1->prog;
-                                       if(p->as == p1->as && p->to.type == p1->from.type && p->to.reg == p1->from.reg){
-                                               p1->as = AMOVL;
-                                               t++;
-                                       }
-                               }
-                       }
-                       break;
-
-               case AMOVBQSX:
-               case AMOVBQZX:
-               case AMOVWQSX:
-               case AMOVWQZX:
-               case AMOVLQSX:
-               case AMOVLQZX:
-               case AMOVQL:
-                       if(regtyp(&p->to)) {
-                               r1 = rnops(uniqs(r));
-                               if(r1 != nil) {
-                                       p1 = r1->prog;
-                                       if(p->as == p1->as && p->to.type == p1->from.type && p->to.reg == p1->from.reg){
-                                               p1->as = AMOVQ;
-                                               t++;
-                                       }
-                               }
-                       }
-                       break;
-
-               case AADDL:
-               case AADDQ:
-               case AADDW:
-                       if(p->from.type != TYPE_CONST || needc(p->link))
-                               break;
-                       if(p->from.offset == -1){
-                               if(p->as == AADDQ)
-                                       p->as = ADECQ;
-                               else
-                               if(p->as == AADDL)
-                                       p->as = ADECL;
-                               else
-                                       p->as = ADECW;
-                               p->from = zprog.from;
-                               break;
-                       }
-                       if(p->from.offset == 1){
-                               if(p->as == AADDQ)
-                                       p->as = AINCQ;
-                               else if(p->as == AADDL)
-                                       p->as = AINCL;
-                               else
-                                       p->as = AINCW;
-                               p->from = zprog.from;
-                               break;
-                       }
-                       break;
-
-               case ASUBL:
-               case ASUBQ:
-               case ASUBW:
-                       if(p->from.type != TYPE_CONST || needc(p->link))
-                               break;
-                       if(p->from.offset == -1) {
-                               if(p->as == ASUBQ)
-                                       p->as = AINCQ;
-                               else
-                               if(p->as == ASUBL)
-                                       p->as = AINCL;
-                               else
-                                       p->as = AINCW;
-                               p->from = zprog.from;
-                               break;
-                       }
-                       if(p->from.offset == 1){
-                               if(p->as == ASUBQ)
-                                       p->as = ADECQ;
-                               else
-                               if(p->as == ASUBL)
-                                       p->as = ADECL;
-                               else
-                                       p->as = ADECW;
-                               p->from = zprog.from;
-                               break;
-                       }
-                       break;
-               }
-       }
-       if(t)
-               goto loop1;
-
-       // MOVLQZX removal.
-       // The MOVLQZX exists to avoid being confused for a
-       // MOVL that is just copying 32-bit data around during
-       // copyprop.  Now that copyprop is done, remov MOVLQZX R1, R2
-       // if it is dominated by an earlier ADDL/MOVL/etc into R1 that
-       // will have already cleared the high bits.
-       //
-       // MOVSD removal.
-       // We never use packed registers, so a MOVSD between registers
-       // can be replaced by MOVAPD, which moves the pair of float64s
-       // instead of just the lower one.  We only use the lower one, but
-       // the processor can do better if we do moves using both.
-       for(r=g->start; r!=nil; r=r->link) {
-               p = r->prog;
-               if(p->as == AMOVLQZX)
-               if(regtyp(&p->from))
-               if(p->from.type == p->to.type && p->from.reg == p->to.reg)
-               if(prevl(r, p->from.reg))
-                       excise(r);
-               
-               if(p->as == AMOVSD)
-               if(regtyp(&p->from))
-               if(regtyp(&p->to))
-                       p->as = AMOVAPD;
-       }
-
-       // load pipelining
-       // push any load from memory as early as possible
-       // to give it time to complete before use.
-       for(r=g->start; r!=nil; r=r->link) {
-               p = r->prog;
-               switch(p->as) {
-               case AMOVB:
-               case AMOVW:
-               case AMOVL:
-               case AMOVQ:
-               case AMOVLQZX:
-                       if(regtyp(&p->to) && !regconsttyp(&p->from))
-                               pushback(r);
-               }
-       }
-       
-       flowend(g);
-}
-
-static void
-pushback(Flow *r0)
-{
-       Flow *r, *b;
-       Prog *p0, *p, t;
-       
-       b = nil;
-       p0 = r0->prog;
-       for(r=uniqp(r0); r!=nil && uniqs(r)!=nil; r=uniqp(r)) {
-               p = r->prog;
-               if(p->as != ANOP) {
-                       if(!regconsttyp(&p->from) || !regtyp(&p->to))
-                               break;
-                       if(copyu(p, &p0->to, nil) || copyu(p0, &p->to, nil))
-                               break;
-               }
-               if(p->as == ACALL)
-                       break;
-               b = r;
-       }
-       
-       if(b == nil) {
-               if(debug['v']) {
-                       print("no pushback: %P\n", r0->prog);
-                       if(r)
-                               print("\t%P [%d]\n", r->prog, uniqs(r)!=nil);
-               }
-               return;
-       }
-
-       if(debug['v']) {
-               print("pushback\n");
-               for(r=b;; r=r->link) {
-                       print("\t%P\n", r->prog);
-                       if(r == r0)
-                               break;
-               }
-       }
-
-       t = *r0->prog;
-       for(r=uniqp(r0);; r=uniqp(r)) {
-               p0 = r->link->prog;
-               p = r->prog;
-               p0->as = p->as;
-               p0->lineno = p->lineno;
-               p0->from = p->from;
-               p0->to = p->to;
-
-               if(r == b)
-                       break;
-       }
-       p0 = r->prog;
-       p0->as = t.as;
-       p0->lineno = t.lineno;
-       p0->from = t.from;
-       p0->to = t.to;
-
-       if(debug['v']) {
-               print("\tafter\n");
-               for(r=b;; r=r->link) {
-                       print("\t%P\n", r->prog);
-                       if(r == r0)
-                               break;
-               }
-       }
-}
-
-void
-excise(Flow *r)
-{
-       Prog *p;
-
-       p = r->prog;
-       if(debug['P'] && debug['v'])
-               print("%P ===delete===\n", p);
-
-       nopout(p);
-
-       ostats.ndelmov++;
-}
-
-int
-regtyp(Adr *a)
-{
-       return a->type == TYPE_REG && (REG_AX <= a->reg && a->reg <= REG_R15 || REG_X0 <= a->reg && a->reg <= REG_X15);
-}
-
-// movb elimination.
-// movb is simulated by the linker
-// when a register other than ax, bx, cx, dx
-// is used, so rewrite to other instructions
-// when possible.  a movb into a register
-// can smash the entire 32-bit register without
-// causing any trouble.
-//
-// TODO: Using the Q forms here instead of the L forms
-// seems unnecessary, and it makes the instructions longer.
-static void
-elimshortmov(Graph *g)
-{
-       Prog *p;
-       Flow *r;
-
-       for(r=g->start; r!=nil; r=r->link) {
-               p = r->prog;
-               if(regtyp(&p->to)) {
-                       switch(p->as) {
-                       case AINCB:
-                       case AINCW:
-                               p->as = AINCQ;
-                               break;
-                       case ADECB:
-                       case ADECW:
-                               p->as = ADECQ;
-                               break;
-                       case ANEGB:
-                       case ANEGW:
-                               p->as = ANEGQ;
-                               break;
-                       case ANOTB:
-                       case ANOTW:
-                               p->as = ANOTQ;
-                               break;
-                       }
-                       if(regtyp(&p->from) || p->from.type == TYPE_CONST) {
-                               // move or artihmetic into partial register.
-                               // from another register or constant can be movl.
-                               // we don't switch to 64-bit arithmetic if it can
-                               // change how the carry bit is set (and the carry bit is needed).
-                               switch(p->as) {
-                               case AMOVB:
-                               case AMOVW:
-                                       p->as = AMOVQ;
-                                       break;
-                               case AADDB:
-                               case AADDW:
-                                       if(!needc(p->link))
-                                               p->as = AADDQ;
-                                       break;
-                               case ASUBB:
-                               case ASUBW:
-                                       if(!needc(p->link))
-                                               p->as = ASUBQ;
-                                       break;
-                               case AMULB:
-                               case AMULW:
-                                       p->as = AMULQ;
-                                       break;
-                               case AIMULB:
-                               case AIMULW:
-                                       p->as = AIMULQ;
-                                       break;
-                               case AANDB:
-                               case AANDW:
-                                       p->as = AANDQ;
-                                       break;
-                               case AORB:
-                               case AORW:
-                                       p->as = AORQ;
-                                       break;
-                               case AXORB:
-                               case AXORW:
-                                       p->as = AXORQ;
-                                       break;
-                               case ASHLB:
-                               case ASHLW:
-                                       p->as = ASHLQ;
-                                       break;
-                               }
-                       } else if(p->from.type != TYPE_REG) {
-                               // explicit zero extension, but don't
-                               // do that if source is a byte register
-                               // (only AH can occur and it's forbidden).
-                               switch(p->as) {
-                               case AMOVB:
-                                       p->as = AMOVBQZX;
-                                       break;
-                               case AMOVW:
-                                       p->as = AMOVWQZX;
-                                       break;
-                               }
-                       }
-               }
-       }
-}
-
-// is 'a' a register or constant?
-static int
-regconsttyp(Adr *a)
-{
-       if(regtyp(a))
-               return 1;
-       switch(a->type) {
-       case TYPE_CONST:
-       case TYPE_FCONST:
-       case TYPE_SCONST:
-       case TYPE_ADDR: // TODO(rsc): Not all TYPE_ADDRs are constants.
-               return 1;
-       }
-       return 0;
-}
-
-// is reg guaranteed to be truncated by a previous L instruction?
-static int
-prevl(Flow *r0, int reg)
-{
-       Prog *p;
-       Flow *r;
-       ProgInfo info;
-
-       for(r=uniqp(r0); r!=nil; r=uniqp(r)) {
-               p = r->prog;
-               if(p->to.type == TYPE_REG && p->to.reg == reg) {
-                       proginfo(&info, p);
-                       if(info.flags & RightWrite) {
-                               if(info.flags & SizeL)
-                                       return 1;
-                               return 0;
-                       }
-               }
-       }
-       return 0;
-}
-
-/*
- * the idea is to substitute
- * one register for another
- * from one MOV to another
- *     MOV     a, R0
- *     ADD     b, R0   / no use of R1
- *     MOV     R0, R1
- * would be converted to
- *     MOV     a, R1
- *     ADD     b, R1
- *     MOV     R1, R0
- * hopefully, then the former or latter MOV
- * will be eliminated by copy propagation.
- */
-static int
-subprop(Flow *r0)
-{
-       Prog *p;
-       ProgInfo info;
-       Adr *v1, *v2;
-       Flow *r;
-       int t;
-
-       if(debug['P'] && debug['v'])
-               print("subprop %P\n", r0->prog);
-       p = r0->prog;
-       v1 = &p->from;
-       if(!regtyp(v1)) {
-               if(debug['P'] && debug['v'])
-                       print("\tnot regtype %D; return 0\n", v1);
-               return 0;
-       }
-       v2 = &p->to;
-       if(!regtyp(v2)) {
-               if(debug['P'] && debug['v'])
-                       print("\tnot regtype %D; return 0\n", v2);
-               return 0;
-       }
-       for(r=uniqp(r0); r!=nil; r=uniqp(r)) {
-               if(debug['P'] && debug['v'])
-                       print("\t? %P\n", r->prog);
-               if(uniqs(r) == nil) {
-                       if(debug['P'] && debug['v'])
-                               print("\tno unique successor\n");
-                       break;
-               }
-               p = r->prog;
-               if(p->as == AVARDEF || p->as == AVARKILL)
-                       continue;
-               proginfo(&info, p);
-               if(info.flags & Call) {
-                       if(debug['P'] && debug['v'])
-                               print("\tfound %P; return 0\n", p);
-                       return 0;
-               }
-
-               if(info.reguse | info.regset) {
-                       if(debug['P'] && debug['v'])
-                               print("\tfound %P; return 0\n", p);
-                       return 0;
-               }
-
-               if((info.flags & Move) && (info.flags & (SizeL|SizeQ|SizeF|SizeD)) && p->to.type == v1->type && p->to.reg == v1->reg)
-                       goto gotit;
-
-               if(copyau(&p->from, v2) ||
-                  copyau(&p->to, v2)) {
-                       if(debug['P'] && debug['v'])
-                               print("\tcopyau %D failed\n", v2);
-                       break;
-               }
-               if(copysub(&p->from, v1, v2, 0) ||
-                  copysub(&p->to, v1, v2, 0)) {
-                       if(debug['P'] && debug['v'])
-                               print("\tcopysub failed\n");
-                       break;
-               }
-       }
-       if(debug['P'] && debug['v'])
-               print("\tran off end; return 0\n");
-       return 0;
-
-gotit:
-       copysub(&p->to, v1, v2, 1);
-       if(debug['P']) {
-               print("gotit: %D->%D\n%P", v1, v2, r->prog);
-               if(p->from.type == v2->type && p->from.reg == v2->reg)
-                       print(" excise");
-               print("\n");
-       }
-       for(r=uniqs(r); r!=r0; r=uniqs(r)) {
-               p = r->prog;
-               copysub(&p->from, v1, v2, 1);
-               copysub(&p->to, v1, v2, 1);
-               if(debug['P'])
-                       print("%P\n", r->prog);
-       }
-       t = v1->reg;
-       v1->reg = v2->reg;
-       v2->reg = t;
-       if(debug['P'])
-               print("%P last\n", r->prog);
-       return 1;
-}
-
-/*
- * The idea is to remove redundant copies.
- *     v1->v2  F=0
- *     (use v2 s/v2/v1/)*
- *     set v1  F=1
- *     use v2  return fail
- *     -----------------
- *     v1->v2  F=0
- *     (use v2 s/v2/v1/)*
- *     set v1  F=1
- *     set v2  return success
- */
-static int
-copyprop(Graph *g, Flow *r0)
-{
-       Prog *p;
-       Adr *v1, *v2;
-
-       USED(g);
-       if(debug['P'] && debug['v'])
-               print("copyprop %P\n", r0->prog);
-       p = r0->prog;
-       v1 = &p->from;
-       v2 = &p->to;
-       if(copyas(v1, v2))
-               return 1;
-       gactive++;
-       return copy1(v1, v2, r0->s1, 0);
-}
-
-static int
-copy1(Adr *v1, Adr *v2, Flow *r, int f)
-{
-       int t;
-       Prog *p;
-
-       if(r->active == gactive) {
-               if(debug['P'])
-                       print("act set; return 1\n");
-               return 1;
-       }
-       r->active = gactive;
-       if(debug['P'])
-               print("copy %D->%D f=%d\n", v1, v2, f);
-       for(; r != nil; r = r->s1) {
-               p = r->prog;
-               if(debug['P'])
-                       print("%P", p);
-               if(!f && uniqp(r) == nil) {
-                       f = 1;
-                       if(debug['P'])
-                               print("; merge; f=%d", f);
-               }
-               t = copyu(p, v2, nil);
-               switch(t) {
-               case 2: /* rar, can't split */
-                       if(debug['P'])
-                               print("; %D rar; return 0\n", v2);
-                       return 0;
-
-               case 3: /* set */
-                       if(debug['P'])
-                               print("; %D set; return 1\n", v2);
-                       return 1;
-
-               case 1: /* used, substitute */
-               case 4: /* use and set */
-                       if(f) {
-                               if(!debug['P'])
-                                       return 0;
-                               if(t == 4)
-                                       print("; %D used+set and f=%d; return 0\n", v2, f);
-                               else
-                                       print("; %D used and f=%d; return 0\n", v2, f);
-                               return 0;
-                       }
-                       if(copyu(p, v2, v1)) {
-                               if(debug['P'])
-                                       print("; sub fail; return 0\n");
-                               return 0;
-                       }
-                       if(debug['P'])
-                               print("; sub %D/%D", v2, v1);
-                       if(t == 4) {
-                               if(debug['P'])
-                                       print("; %D used+set; return 1\n", v2);
-                               return 1;
-                       }
-                       break;
-               }
-               if(!f) {
-                       t = copyu(p, v1, nil);
-                       if(!f && (t == 2 || t == 3 || t == 4)) {
-                               f = 1;
-                               if(debug['P'])
-                                       print("; %D set and !f; f=%d", v1, f);
-                       }
-               }
-               if(debug['P'])
-                       print("\n");
-               if(r->s2)
-                       if(!copy1(v1, v2, r->s2, f))
-                               return 0;
-       }
-       return 1;
-}
-
-/*
- * return
- * 1 if v only used (and substitute),
- * 2 if read-alter-rewrite
- * 3 if set
- * 4 if set and used
- * 0 otherwise (not touched)
- */
-static int
-copyu(Prog *p, Adr *v, Adr *s)
-{
-       ProgInfo info;
-
-       switch(p->as) {
-       case AJMP:
-               if(s != nil) {
-                       if(copysub(&p->to, v, s, 1))
-                               return 1;
-                       return 0;
-               }
-               if(copyau(&p->to, v))
-                       return 1;
-               return 0;
-
-       case ARET:
-               if(s != nil)
-                       return 1;
-               return 3;
-
-       case ACALL:
-               if(REGEXT && v->type == TYPE_REG && v->reg <= REGEXT && v->reg > exregoffset)
-                       return 2;
-               if(REGARG >= 0 && v->type == TYPE_REG && v->reg == REGARG)
-                       return 2;
-               if(v->type == p->from.type && v->reg == p->from.reg)
-                       return 2;
-
-               if(s != nil) {
-                       if(copysub(&p->to, v, s, 1))
-                               return 1;
-                       return 0;
-               }
-               if(copyau(&p->to, v))
-                       return 4;
-               return 3;
-
-       case ATEXT:
-               if(REGARG >= 0 && v->type == TYPE_REG && v->reg == REGARG)
-                       return 3;
-               return 0;
-       }
-
-       if(p->as == AVARDEF || p->as == AVARKILL)
-               return 0;
-       proginfo(&info, p);
-
-       if((info.reguse|info.regset) & RtoB(v->reg))
-               return 2;
-               
-       if(info.flags & LeftAddr)
-               if(copyas(&p->from, v))
-                       return 2;
-
-       if((info.flags & (RightRead|RightWrite)) == (RightRead|RightWrite))
-               if(copyas(&p->to, v))
-                       return 2;
-       
-       if(info.flags & RightWrite) {
-               if(copyas(&p->to, v)) {
-                       if(s != nil)
-                               return copysub(&p->from, v, s, 1);
-                       if(copyau(&p->from, v))
-                               return 4;
-                       return 3;
-               }
-       }
-       
-       if(info.flags & (LeftAddr|LeftRead|LeftWrite|RightAddr|RightRead|RightWrite)) {
-               if(s != nil) {
-                       if(copysub(&p->from, v, s, 1))
-                               return 1;
-                       return copysub(&p->to, v, s, 1);
-               }
-               if(copyau(&p->from, v))
-                       return 1;
-               if(copyau(&p->to, v))
-                       return 1;
-       }
-
-       return 0;
-}
-
-/*
- * direct reference,
- * could be set/use depending on
- * semantics
- */
-static int
-copyas(Adr *a, Adr *v)
-{
-       if(REG_AL <= a->reg && a->reg <= REG_R15B)
-               fatal("use of byte register");
-       if(REG_AL <= v->reg && v->reg <= REG_R15B)
-               fatal("use of byte register");
-
-       if(a->type != v->type || a->name != v->name || a->reg != v->reg)
-               return 0;
-       if(regtyp(v))
-               return 1;
-       if(v->type == TYPE_MEM && (v->name == NAME_AUTO || v->name == NAME_PARAM))
-               if(v->offset == a->offset)
-                       return 1;
-       return 0;
-}
-
-int
-sameaddr(Addr *a, Addr *v)
-{
-       if(a->type != v->type || a->name != v->name || a->reg != v->reg)
-               return 0;
-       if(regtyp(v))
-               return 1;
-       if(v->type == TYPE_MEM && (v->name == NAME_AUTO || v->name == NAME_PARAM))
-               if(v->offset == a->offset)
-                       return 1;
-       return 0;
-}
-
-/*
- * either direct or indirect
- */
-static int
-copyau(Adr *a, Adr *v)
-{
-
-       if(copyas(a, v)) {
-               if(debug['P'] && debug['v'])
-                       print("\tcopyau: copyas returned 1\n");
-               return 1;
-       }
-       if(regtyp(v)) {
-               if(a->type == TYPE_MEM && a->reg == v->reg) {
-                       if(debug['P'] && debug['v'])
-                               print("\tcopyau: found indir use - return 1\n");
-                       return 1;
-               }
-               if(a->index == v->reg) {
-                       if(debug['P'] && debug['v'])
-                               print("\tcopyau: found index use - return 1\n");
-                       return 1;
-               }
-       }
-       return 0;
-}
-
-/*
- * substitute s for v in a
- * return failure to substitute
- */
-static int
-copysub(Adr *a, Adr *v, Adr *s, int f)
-{
-       int reg;
-
-       if(copyas(a, v)) {
-               reg = s->reg;
-               if(reg >= REG_AX && reg <= REG_R15 || reg >= REG_X0 && reg <= REG_X0+15) {
-                       if(f)
-                               a->reg = reg;
-               }
-               return 0;
-       }
-       if(regtyp(v)) {
-               reg = v->reg;
-               if(a->type == TYPE_MEM && a->reg == reg) {
-                       if((s->reg == REG_BP || s->reg == REG_R13) && a->index != REG_NONE)
-                               return 1;       /* can't use BP-base with index */
-                       if(f)
-                               a->reg = s->reg;
-//                     return 0;
-               }
-               if(a->index == reg) {
-                       if(f)
-                               a->index = s->reg;
-                       return 0;
-               }
-               return 0;
-       }
-       return 0;
-}
-
-static void
-conprop(Flow *r0)
-{
-       Flow *r;
-       Prog *p, *p0;
-       int t;
-       Adr *v0;
-
-       p0 = r0->prog;
-       v0 = &p0->to;
-       r = r0;
-
-loop:
-       r = uniqs(r);
-       if(r == nil || r == r0)
-               return;
-       if(uniqp(r) == nil)
-               return;
-
-       p = r->prog;
-       t = copyu(p, v0, nil);
-       switch(t) {
-       case 0: // miss
-       case 1: // use
-               goto loop;
-
-       case 2: // rar
-       case 4: // use and set
-               break;
-
-       case 3: // set
-               if(p->as == p0->as)
-               if(p->from.type == p0->from.type)
-               if(p->from.reg == p0->from.reg)
-               if(p->from.node == p0->from.node)
-               if(p->from.offset == p0->from.offset)
-               if(p->from.scale == p0->from.scale)
-               if(p->from.type == TYPE_FCONST && p->from.u.dval == p0->from.u.dval)
-               if(p->from.index == p0->from.index) {
-                       excise(r);
-                       goto loop;
-               }
-               break;
-       }
-}
-
-int
-smallindir(Addr *a, Addr *reg)
-{
-       return regtyp(reg) &&
-               a->type == TYPE_MEM && a->reg == reg->reg &&
-               a->index == REG_NONE &&
-               0 <= a->offset && a->offset < 4096;
-}
-
-int
-stackaddr(Addr *a)
-{
-       return a->type == TYPE_REG && a->reg == REG_SP;
-}
similarity index 100%
rename from src/cmd/new6g/peep.go
rename to src/cmd/6g/peep.go
diff --git a/src/cmd/6g/prog.c b/src/cmd/6g/prog.c
deleted file mode 100644 (file)
index 79b7911..0000000
+++ /dev/null
@@ -1,318 +0,0 @@
-// Copyright 2013 The Go Authors.  All rights reserved.
-// Use of this source code is governed by a BSD-style
-// license that can be found in the LICENSE file.
-
-#include <u.h>
-#include <libc.h>
-#include "gg.h"
-#include "../gc/popt.h"
-
-// Matches real RtoB but can be used in global initializer.
-#define RtoB(r) (1<<((r)-REG_AX))
-
-enum {
-       AX = RtoB(REG_AX),
-       BX = RtoB(REG_BX),
-       CX = RtoB(REG_CX),
-       DX = RtoB(REG_DX),
-       DI = RtoB(REG_DI),
-       SI = RtoB(REG_SI),
-       
-       LeftRdwr = LeftRead | LeftWrite,
-       RightRdwr = RightRead | RightWrite,
-};
-
-#undef RtoB
-
-// This table gives the basic information about instruction
-// generated by the compiler and processed in the optimizer.
-// See opt.h for bit definitions.
-//
-// Instructions not generated need not be listed.
-// As an exception to that rule, we typically write down all the
-// size variants of an operation even if we just use a subset.
-//
-// The table is formatted for 8-space tabs.
-static ProgInfo progtable[ALAST] = {
-       [ATYPE]=        {Pseudo | Skip},
-       [ATEXT]=        {Pseudo},
-       [AFUNCDATA]=    {Pseudo},
-       [APCDATA]=      {Pseudo},
-       [AUNDEF]=       {Break},
-       [AUSEFIELD]=    {OK},
-       [ACHECKNIL]=    {LeftRead},
-       [AVARDEF]=      {Pseudo | RightWrite},
-       [AVARKILL]=     {Pseudo | RightWrite},
-
-       // NOP is an internal no-op that also stands
-       // for USED and SET annotations, not the Intel opcode.
-       [ANOP]=         {LeftRead | RightWrite},
-
-       [AADCL]=        {SizeL | LeftRead | RightRdwr | SetCarry | UseCarry},
-       [AADCQ]=        {SizeQ | LeftRead | RightRdwr | SetCarry | UseCarry},
-       [AADCW]=        {SizeW | LeftRead | RightRdwr | SetCarry | UseCarry},
-
-       [AADDB]=        {SizeB | LeftRead | RightRdwr | SetCarry},
-       [AADDL]=        {SizeL | LeftRead | RightRdwr | SetCarry},
-       [AADDW]=        {SizeW | LeftRead | RightRdwr | SetCarry},
-       [AADDQ]=        {SizeQ | LeftRead | RightRdwr | SetCarry},
-       
-       [AADDSD]=       {SizeD | LeftRead | RightRdwr},
-       [AADDSS]=       {SizeF | LeftRead | RightRdwr},
-
-       [AANDB]=        {SizeB | LeftRead | RightRdwr | SetCarry},
-       [AANDL]=        {SizeL | LeftRead | RightRdwr | SetCarry},
-       [AANDQ]=        {SizeQ | LeftRead | RightRdwr | SetCarry},
-       [AANDW]=        {SizeW | LeftRead | RightRdwr | SetCarry},
-
-       [ACALL]=        {RightAddr | Call | KillCarry},
-
-       [ACDQ]=         {OK, AX, AX | DX},
-       [ACQO]=         {OK, AX, AX | DX},
-       [ACWD]=         {OK, AX, AX | DX},
-
-       [ACLD]=         {OK},
-       [ASTD]=         {OK},
-
-       [ACMPB]=        {SizeB | LeftRead | RightRead | SetCarry},
-       [ACMPL]=        {SizeL | LeftRead | RightRead | SetCarry},
-       [ACMPQ]=        {SizeQ | LeftRead | RightRead | SetCarry},
-       [ACMPW]=        {SizeW | LeftRead | RightRead | SetCarry},
-
-       [ACOMISD]=      {SizeD | LeftRead | RightRead | SetCarry},
-       [ACOMISS]=      {SizeF | LeftRead | RightRead | SetCarry},
-
-       [ACVTSD2SL]=    {SizeL | LeftRead | RightWrite | Conv},
-       [ACVTSD2SQ]=    {SizeQ | LeftRead | RightWrite | Conv},
-       [ACVTSD2SS]=    {SizeF | LeftRead | RightWrite | Conv},
-       [ACVTSL2SD]=    {SizeD | LeftRead | RightWrite | Conv},
-       [ACVTSL2SS]=    {SizeF | LeftRead | RightWrite | Conv},
-       [ACVTSQ2SD]=    {SizeD | LeftRead | RightWrite | Conv},
-       [ACVTSQ2SS]=    {SizeF | LeftRead | RightWrite | Conv},
-       [ACVTSS2SD]=    {SizeD | LeftRead | RightWrite | Conv},
-       [ACVTSS2SL]=    {SizeL | LeftRead | RightWrite | Conv},
-       [ACVTSS2SQ]=    {SizeQ | LeftRead | RightWrite | Conv},
-       [ACVTTSD2SL]=   {SizeL | LeftRead | RightWrite | Conv},
-       [ACVTTSD2SQ]=   {SizeQ | LeftRead | RightWrite | Conv},
-       [ACVTTSS2SL]=   {SizeL | LeftRead | RightWrite | Conv},
-       [ACVTTSS2SQ]=   {SizeQ | LeftRead | RightWrite | Conv},
-
-       [ADECB]=        {SizeB | RightRdwr},
-       [ADECL]=        {SizeL | RightRdwr},
-       [ADECQ]=        {SizeQ | RightRdwr},
-       [ADECW]=        {SizeW | RightRdwr},
-
-       [ADIVB]=        {SizeB | LeftRead | SetCarry, AX, AX},
-       [ADIVL]=        {SizeL | LeftRead | SetCarry, AX|DX, AX|DX},
-       [ADIVQ]=        {SizeQ | LeftRead | SetCarry, AX|DX, AX|DX},
-       [ADIVW]=        {SizeW | LeftRead | SetCarry, AX|DX, AX|DX},
-
-       [ADIVSD]=       {SizeD | LeftRead | RightRdwr},
-       [ADIVSS]=       {SizeF | LeftRead | RightRdwr},
-
-       [AIDIVB]=       {SizeB | LeftRead | SetCarry, AX, AX},
-       [AIDIVL]=       {SizeL | LeftRead | SetCarry, AX|DX, AX|DX},
-       [AIDIVQ]=       {SizeQ | LeftRead | SetCarry, AX|DX, AX|DX},
-       [AIDIVW]=       {SizeW | LeftRead | SetCarry, AX|DX, AX|DX},
-
-       [AIMULB]=       {SizeB | LeftRead | SetCarry, AX, AX},
-       [AIMULL]=       {SizeL | LeftRead | ImulAXDX | SetCarry},
-       [AIMULQ]=       {SizeQ | LeftRead | ImulAXDX | SetCarry},
-       [AIMULW]=       {SizeW | LeftRead | ImulAXDX | SetCarry},
-
-       [AINCB]=        {SizeB | RightRdwr},
-       [AINCL]=        {SizeL | RightRdwr},
-       [AINCQ]=        {SizeQ | RightRdwr},
-       [AINCW]=        {SizeW | RightRdwr},
-
-       [AJCC]=         {Cjmp | UseCarry},
-       [AJCS]=         {Cjmp | UseCarry},
-       [AJEQ]=         {Cjmp | UseCarry},
-       [AJGE]=         {Cjmp | UseCarry},
-       [AJGT]=         {Cjmp | UseCarry},
-       [AJHI]=         {Cjmp | UseCarry},
-       [AJLE]=         {Cjmp | UseCarry},
-       [AJLS]=         {Cjmp | UseCarry},
-       [AJLT]=         {Cjmp | UseCarry},
-       [AJMI]=         {Cjmp | UseCarry},
-       [AJNE]=         {Cjmp | UseCarry},
-       [AJOC]=         {Cjmp | UseCarry},
-       [AJOS]=         {Cjmp | UseCarry},
-       [AJPC]=         {Cjmp | UseCarry},
-       [AJPL]=         {Cjmp | UseCarry},
-       [AJPS]=         {Cjmp | UseCarry},
-
-       [AJMP]=         {Jump | Break | KillCarry},
-
-       [ALEAL]=        {LeftAddr | RightWrite},
-       [ALEAQ]=        {LeftAddr | RightWrite},
-
-       [AMOVBLSX]=     {SizeL | LeftRead | RightWrite | Conv},
-       [AMOVBLZX]=     {SizeL | LeftRead | RightWrite | Conv},
-       [AMOVBQSX]=     {SizeQ | LeftRead | RightWrite | Conv},
-       [AMOVBQZX]=     {SizeQ | LeftRead | RightWrite | Conv},
-       [AMOVBWSX]=     {SizeW | LeftRead | RightWrite | Conv},
-       [AMOVBWZX]=     {SizeW | LeftRead | RightWrite | Conv},
-       [AMOVLQSX]=     {SizeQ | LeftRead | RightWrite | Conv},
-       [AMOVLQZX]=     {SizeQ | LeftRead | RightWrite | Conv},
-       [AMOVWLSX]=     {SizeL | LeftRead | RightWrite | Conv},
-       [AMOVWLZX]=     {SizeL | LeftRead | RightWrite | Conv},
-       [AMOVWQSX]=     {SizeQ | LeftRead | RightWrite | Conv},
-       [AMOVWQZX]=     {SizeQ | LeftRead | RightWrite | Conv},
-       [AMOVQL]=       {SizeL | LeftRead | RightWrite | Conv},
-
-       [AMOVB]=        {SizeB | LeftRead | RightWrite | Move},
-       [AMOVL]=        {SizeL | LeftRead | RightWrite | Move},
-       [AMOVQ]=        {SizeQ | LeftRead | RightWrite | Move},
-       [AMOVW]=        {SizeW | LeftRead | RightWrite | Move},
-
-       [AMOVSB]=       {OK, DI|SI, DI|SI},
-       [AMOVSL]=       {OK, DI|SI, DI|SI},
-       [AMOVSQ]=       {OK, DI|SI, DI|SI},
-       [AMOVSW]=       {OK, DI|SI, DI|SI},
-       [ADUFFCOPY]=    {OK, DI|SI, DI|SI|CX},
-
-       [AMOVSD]=       {SizeD | LeftRead | RightWrite | Move},
-       [AMOVSS]=       {SizeF | LeftRead | RightWrite | Move},
-
-       // We use MOVAPD as a faster synonym for MOVSD.
-       [AMOVAPD]=      {SizeD | LeftRead | RightWrite | Move},
-
-       [AMULB]=        {SizeB | LeftRead | SetCarry, AX, AX},
-       [AMULL]=        {SizeL | LeftRead | SetCarry, AX, AX|DX},
-       [AMULQ]=        {SizeQ | LeftRead | SetCarry, AX, AX|DX},
-       [AMULW]=        {SizeW | LeftRead | SetCarry, AX, AX|DX},
-       
-       [AMULSD]=       {SizeD | LeftRead | RightRdwr},
-       [AMULSS]=       {SizeF | LeftRead | RightRdwr},
-
-       [ANEGB]=        {SizeB | RightRdwr | SetCarry},
-       [ANEGL]=        {SizeL | RightRdwr | SetCarry},
-       [ANEGQ]=        {SizeQ | RightRdwr | SetCarry},
-       [ANEGW]=        {SizeW | RightRdwr | SetCarry},
-
-       [ANOTB]=        {SizeB | RightRdwr},
-       [ANOTL]=        {SizeL | RightRdwr},
-       [ANOTQ]=        {SizeQ | RightRdwr},
-       [ANOTW]=        {SizeW | RightRdwr},
-
-       [AORB]=         {SizeB | LeftRead | RightRdwr | SetCarry},
-       [AORL]=         {SizeL | LeftRead | RightRdwr | SetCarry},
-       [AORQ]=         {SizeQ | LeftRead | RightRdwr | SetCarry},
-       [AORW]=         {SizeW | LeftRead | RightRdwr | SetCarry},
-
-       [APOPQ]=        {SizeQ | RightWrite},
-       [APUSHQ]=       {SizeQ | LeftRead},
-
-       [ARCLB]=        {SizeB | LeftRead | RightRdwr | ShiftCX | SetCarry | UseCarry},
-       [ARCLL]=        {SizeL | LeftRead | RightRdwr | ShiftCX | SetCarry | UseCarry},
-       [ARCLQ]=        {SizeQ | LeftRead | RightRdwr | ShiftCX | SetCarry | UseCarry},
-       [ARCLW]=        {SizeW | LeftRead | RightRdwr | ShiftCX | SetCarry | UseCarry},
-
-       [ARCRB]=        {SizeB | LeftRead | RightRdwr | ShiftCX | SetCarry | UseCarry},
-       [ARCRL]=        {SizeL | LeftRead | RightRdwr | ShiftCX | SetCarry | UseCarry},
-       [ARCRQ]=        {SizeQ | LeftRead | RightRdwr | ShiftCX | SetCarry | UseCarry},
-       [ARCRW]=        {SizeW | LeftRead | RightRdwr | ShiftCX | SetCarry | UseCarry},
-
-       [AREP]=         {OK, CX, CX},
-       [AREPN]=        {OK, CX, CX},
-
-       [ARET]=         {Break | KillCarry},
-
-       [AROLB]=        {SizeB | LeftRead | RightRdwr | ShiftCX | SetCarry},
-       [AROLL]=        {SizeL | LeftRead | RightRdwr | ShiftCX | SetCarry},
-       [AROLQ]=        {SizeQ | LeftRead | RightRdwr | ShiftCX | SetCarry},
-       [AROLW]=        {SizeW | LeftRead | RightRdwr | ShiftCX | SetCarry},
-
-       [ARORB]=        {SizeB | LeftRead | RightRdwr | ShiftCX | SetCarry},
-       [ARORL]=        {SizeL | LeftRead | RightRdwr | ShiftCX | SetCarry},
-       [ARORQ]=        {SizeQ | LeftRead | RightRdwr | ShiftCX | SetCarry},
-       [ARORW]=        {SizeW | LeftRead | RightRdwr | ShiftCX | SetCarry},
-
-       [ASALB]=        {SizeB | LeftRead | RightRdwr | ShiftCX | SetCarry},
-       [ASALL]=        {SizeL | LeftRead | RightRdwr | ShiftCX | SetCarry},
-       [ASALQ]=        {SizeQ | LeftRead | RightRdwr | ShiftCX | SetCarry},
-       [ASALW]=        {SizeW | LeftRead | RightRdwr | ShiftCX | SetCarry},
-
-       [ASARB]=        {SizeB | LeftRead | RightRdwr | ShiftCX | SetCarry},
-       [ASARL]=        {SizeL | LeftRead | RightRdwr | ShiftCX | SetCarry},
-       [ASARQ]=        {SizeQ | LeftRead | RightRdwr | ShiftCX | SetCarry},
-       [ASARW]=        {SizeW | LeftRead | RightRdwr | ShiftCX | SetCarry},
-
-       [ASBBB]=        {SizeB | LeftRead | RightRdwr | SetCarry | UseCarry},
-       [ASBBL]=        {SizeL | LeftRead | RightRdwr | SetCarry | UseCarry},
-       [ASBBQ]=        {SizeQ | LeftRead | RightRdwr | SetCarry | UseCarry},
-       [ASBBW]=        {SizeW | LeftRead | RightRdwr | SetCarry | UseCarry},
-
-       [ASHLB]=        {SizeB | LeftRead | RightRdwr | ShiftCX | SetCarry},
-       [ASHLL]=        {SizeL | LeftRead | RightRdwr | ShiftCX | SetCarry},
-       [ASHLQ]=        {SizeQ | LeftRead | RightRdwr | ShiftCX | SetCarry},
-       [ASHLW]=        {SizeW | LeftRead | RightRdwr | ShiftCX | SetCarry},
-
-       [ASHRB]=        {SizeB | LeftRead | RightRdwr | ShiftCX | SetCarry},
-       [ASHRL]=        {SizeL | LeftRead | RightRdwr | ShiftCX | SetCarry},
-       [ASHRQ]=        {SizeQ | LeftRead | RightRdwr | ShiftCX | SetCarry},
-       [ASHRW]=        {SizeW | LeftRead | RightRdwr | ShiftCX | SetCarry},
-
-       [ASTOSB]=       {OK, AX|DI, DI},
-       [ASTOSL]=       {OK, AX|DI, DI},
-       [ASTOSQ]=       {OK, AX|DI, DI},
-       [ASTOSW]=       {OK, AX|DI, DI},
-       [ADUFFZERO]=    {OK, AX|DI, DI},
-
-       [ASUBB]=        {SizeB | LeftRead | RightRdwr | SetCarry},
-       [ASUBL]=        {SizeL | LeftRead | RightRdwr | SetCarry},
-       [ASUBQ]=        {SizeQ | LeftRead | RightRdwr | SetCarry},
-       [ASUBW]=        {SizeW | LeftRead | RightRdwr | SetCarry},
-
-       [ASUBSD]=       {SizeD | LeftRead | RightRdwr},
-       [ASUBSS]=       {SizeF | LeftRead | RightRdwr},
-
-       [ATESTB]=       {SizeB | LeftRead | RightRead | SetCarry},
-       [ATESTL]=       {SizeL | LeftRead | RightRead | SetCarry},
-       [ATESTQ]=       {SizeQ | LeftRead | RightRead | SetCarry},
-       [ATESTW]=       {SizeW | LeftRead | RightRead | SetCarry},
-
-       [AUCOMISD]=     {SizeD | LeftRead | RightRead},
-       [AUCOMISS]=     {SizeF | LeftRead | RightRead},
-
-       [AXCHGB]=       {SizeB | LeftRdwr | RightRdwr},
-       [AXCHGL]=       {SizeL | LeftRdwr | RightRdwr},
-       [AXCHGQ]=       {SizeQ | LeftRdwr | RightRdwr},
-       [AXCHGW]=       {SizeW | LeftRdwr | RightRdwr},
-
-       [AXORB]=        {SizeB | LeftRead | RightRdwr | SetCarry},
-       [AXORL]=        {SizeL | LeftRead | RightRdwr | SetCarry},
-       [AXORQ]=        {SizeQ | LeftRead | RightRdwr | SetCarry},
-       [AXORW]=        {SizeW | LeftRead | RightRdwr | SetCarry},
-};
-
-void
-proginfo(ProgInfo *info, Prog *p)
-{
-       *info = progtable[p->as];
-       if(info->flags == 0)
-               fatal("unknown instruction %P", p);
-
-       if((info->flags & ShiftCX) && p->from.type != TYPE_CONST)
-               info->reguse |= CX;
-
-       if(info->flags & ImulAXDX) {
-               if(p->to.type == TYPE_NONE) {
-                       info->reguse |= AX;
-                       info->regset |= AX | DX;
-               } else {
-                       info->flags |= RightRdwr;
-               }
-       }
-
-       // Addressing makes some registers used.
-       if(p->from.type == TYPE_MEM && p->from.name == NAME_NONE)
-               info->regindex |= RtoB(p->from.reg);
-       if(p->from.index != REG_NONE)
-               info->regindex |= RtoB(p->from.index);
-       if(p->to.type == TYPE_MEM && p->to.name == NAME_NONE)
-               info->regindex |= RtoB(p->to.reg);
-       if(p->to.index != REG_NONE)
-               info->regindex |= RtoB(p->to.index);
-}
similarity index 100%
rename from src/cmd/new6g/prog.go
rename to src/cmd/6g/prog.go
diff --git a/src/cmd/6g/reg.c b/src/cmd/6g/reg.c
deleted file mode 100644 (file)
index e01f265..0000000
+++ /dev/null
@@ -1,153 +0,0 @@
-// Derived from Inferno utils/6c/reg.c
-// http://code.google.com/p/inferno-os/source/browse/utils/6c/reg.c
-//
-//     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 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 <u.h>
-#include <libc.h>
-#include "gg.h"
-#include "../gc/popt.h"
-
-enum {
-       NREGVAR = 32,
-};
-
-static char* regname[] = {
-       ".AX",
-       ".CX",
-       ".DX",
-       ".BX",
-       ".SP",
-       ".BP",
-       ".SI",
-       ".DI",
-       ".R8",
-       ".R9",
-       ".R10",
-       ".R11",
-       ".R12",
-       ".R13",
-       ".R14",
-       ".R15",
-       ".X0",
-       ".X1",
-       ".X2",
-       ".X3",
-       ".X4",
-       ".X5",
-       ".X6",
-       ".X7",
-       ".X8",
-       ".X9",
-       ".X10",
-       ".X11",
-       ".X12",
-       ".X13",
-       ".X14",
-       ".X15",
-};
-
-char**
-regnames(int *n)
-{
-       *n = NREGVAR;
-       return regname;
-}
-
-uint64
-excludedregs(void)
-{
-       return RtoB(REG_SP);
-}
-
-uint64
-doregbits(int r)
-{
-       uint64 b;
-
-       b = 0;
-       if(r >= REG_AX && r <= REG_R15)
-               b |= RtoB(r);
-       else
-       if(r >= REG_AL && r <= REG_R15B)
-               b |= RtoB(r-REG_AL+REG_AX);
-       else
-       if(r >= REG_AH && r <= REG_BH)
-               b |= RtoB(r-REG_AH+REG_AX);
-       else
-       if(r >= REG_X0 && r <= REG_X0+15)
-               b |= FtoB(r);
-       return b;
-}
-
-uint64
-RtoB(int r)
-{
-
-       if(r < REG_AX || r > REG_R15)
-               return 0;
-       return 1ULL << (r-REG_AX);
-}
-
-int
-BtoR(uint64 b)
-{
-       b &= 0xffffULL;
-       if(nacl)
-               b &= ~((1<<(REG_BP-REG_AX)) | (1<<(REG_R15-REG_AX)));
-       else if(framepointer_enabled)
-               // BP is part of the calling convention if framepointer_enabled.
-               b &= ~(1<<(REG_BP-REG_AX));
-       if(b == 0)
-               return 0;
-       return bitno(b) + REG_AX;
-}
-
-/*
- *     bit     reg
- *     16      X0
- *     ...
- *     31      X15
- */
-uint64
-FtoB(int f)
-{
-       if(f < REG_X0 || f > REG_X15)
-               return 0;
-       return 1ULL << (f - REG_X0 + 16);
-}
-
-int
-BtoF(uint64 b)
-{
-
-       b &= 0xFFFF0000L;
-       if(b == 0)
-               return 0;
-       return bitno(b) - 16 + REG_X0;
-}
similarity index 100%
rename from src/cmd/new6g/reg.go
rename to src/cmd/6g/reg.go
similarity index 100%
rename from src/cmd/new6g/util.go
rename to src/cmd/6g/util.go
diff --git a/src/cmd/8a/Makefile b/src/cmd/8a/Makefile
deleted file mode 100644 (file)
index 27290dd..0000000
+++ /dev/null
@@ -1,10 +0,0 @@
-# Copyright 2012 The Go Authors.  All rights reserved.
-# Use of this source code is governed by a BSD-style
-# license that can be found in the LICENSE file.
-
-include ../../Make.dist
-
-install: y.tab.h
-
-y.tab.h: a.y
-       LANG=C LANGUAGE=en_US.UTF8 bison -d -v -y a.y
diff --git a/src/cmd/8a/a.h b/src/cmd/8a/a.h
deleted file mode 100644 (file)
index 24654b0..0000000
+++ /dev/null
@@ -1,186 +0,0 @@
-// Inferno utils/8a/a.h
-// http://code.google.com/p/inferno-os/source/browse/utils/8a/a.h
-//
-//     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 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 <bio.h>
-#include <link.h>
-#include "../8l/8.out.h"
-
-#ifndef        EXTERN
-#define        EXTERN  extern
-#endif
-
-#undef getc
-#undef ungetc
-#undef BUFSIZ
-
-#define        getc    ccgetc
-#define        ungetc  ccungetc
-
-typedef        struct  Sym     Sym;
-typedef        struct  Ref     Ref;
-typedef        struct  Io      Io;
-typedef        struct  Addr2   Addr2;
-
-#define        MAXALIGN        7
-#define        FPCHIP          1
-#define        NSYMB           500
-#define        BUFSIZ          8192
-#define        HISTSZ          20
-#ifndef        EOF
-#define        EOF             (-1)
-#endif
-#define        IGN             (-2)
-#define        GETC()          ((--fi.c < 0)? filbuf(): *fi.p++ & 0xff)
-#define        NHASH           503
-#define        STRINGSZ        200
-#define        NMACRO          10
-
-struct Sym
-{
-       Sym*    link;
-       Ref*    ref;
-       char*   macro;
-       int32   value;
-       ushort  type;
-       char    *name;
-       char*   labelname;
-       char    sym;
-};
-#define        S       ((Sym*)0)
-
-struct Ref
-{
-       int     class;
-};
-
-EXTERN struct
-{
-       char*   p;
-       int     c;
-} fi;
-
-struct Io
-{
-       Io*     link;
-       char    b[BUFSIZ];
-       char*   p;
-       short   c;
-       short   f;
-};
-#define        I       ((Io*)0)
-
-struct Addr2
-{
-       Addr    from;
-       Addr    to;
-};
-
-enum
-{
-       CLAST,
-       CMACARG,
-       CMACRO,
-       CPREPROC,
-};
-
-EXTERN int     debug[256];
-EXTERN Sym*    hash[NHASH];
-EXTERN char**  Dlist;
-EXTERN int     nDlist;
-EXTERN int     newflag;
-EXTERN char*   hunk;
-EXTERN char**  include;
-EXTERN Io*     iofree;
-EXTERN Io*     ionext;
-EXTERN Io*     iostack;
-EXTERN int32   lineno;
-EXTERN int     nerrors;
-EXTERN int32   nhunk;
-EXTERN int     ninclude;
-EXTERN int32   nsymb;
-EXTERN Addr    nullgen;
-EXTERN char*   outfile;
-EXTERN int     pass;
-EXTERN int32   pc;
-EXTERN int     peekc;
-EXTERN int32   stmtline;
-EXTERN int     sym;
-EXTERN char*   symb;
-EXTERN int     thechar;
-EXTERN char*   thestring;
-EXTERN int32   thunk;
-EXTERN Biobuf  obuf;
-EXTERN Link*   ctxt;
-EXTERN Biobuf  bstdout;
-EXTERN Prog*   lastpc;
-
-void*  alloc(int32);
-void*  allocn(void*, int32, int32);
-void   ensuresymb(int32);
-void   errorexit(void);
-void   pushio(void);
-void   newio(void);
-void   newfile(char*, int);
-Sym*   slookup(char*);
-Sym*   lookup(void);
-Sym*   labellookup(Sym*);
-void   settext(LSym*);
-void   syminit(Sym*);
-int32  yylex(void);
-int    getc(void);
-int    getnsc(void);
-void   unget(int);
-int    escchar(int);
-void   cinit(void);
-void   checkscale(int);
-void   pinit(char*);
-void   cclean(void);
-int    isreg(Addr*);
-void   outcode(int, Addr2*);
-void   outhist(void);
-int    filbuf(void);
-Sym*   getsym(void);
-void   domacro(void);
-void   macund(void);
-void   macdef(void);
-void   macexpand(Sym*, char*);
-void   macinc(void);
-void   macprag(void);
-void   maclin(void);
-void   macif(int);
-void   macend(void);
-void   dodefine(char*);
-void   prfile(int32);
-void   linehist(char*, int);
-void   gethunk(void);
-void   yyerror(char*, ...);
-int    yyparse(void);
-void   setinclude(char*);
-int    assemble(char*);
index 1a3ab72ff21ba793d65032e7a3d3b38878f86f16..906ad331df3d91b6175074414f583045546b1165 100644 (file)
 // THE SOFTWARE.
 
 %{
-#include <u.h>
-#include <stdio.h>     /* if we don't, bison will, and a.h re-#defines getc */
-#include <libc.h>
-#include "a.h"
-#include "../../runtime/funcdata.h"
+package main
+
+import (
+       "cmd/internal/asm"
+       "cmd/internal/obj"
+       . "cmd/internal/obj/i386"
+)
 %}
-%union {
-       Sym     *sym;
-       int32   lval;
-       double  dval;
-       char    sval[8];
-       Addr    addr;
-       Addr2   addr2;
+
+%union {
+       sym *asm.Sym
+       lval int64
+       con2 struct {
+               v1 int32
+               v2 int32
+       }
+       dval float64
+       sval string
+       addr obj.Addr
+       addr2 Addr2
 }
+
 %left  '|'
 %left  '^'
 %left  '&'
 prog:
 |      prog
        {
-               stmtline = lineno;
+               stmtline = asm.Lineno;
        }
        line
 
 line:
        LNAME ':'
        {
-               $1 = labellookup($1);
-               if($1->type == LLAB && $1->value != pc)
-                       yyerror("redeclaration of %s", $1->labelname);
-               $1->type = LLAB;
-               $1->value = pc;
+               $1 = asm.LabelLookup($1);
+               if $1.Type == LLAB && $1.Value != int64(asm.PC) {
+                       yyerror("redeclaration of %s", $1.Labelname)
+               }
+               $1.Type = LLAB;
+               $1.Value = int64(asm.PC)
        }
        line
 |      ';'
@@ -85,33 +94,34 @@ line:
 inst:
        LNAME '=' expr
        {
-               $1->type = LVAR;
-               $1->value = $3;
+               $1.Type = LVAR;
+               $1.Value = $3;
        }
 |      LVAR '=' expr
        {
-               if($1->value != $3)
-                       yyerror("redeclaration of %s", $1->name);
-               $1->value = $3;
-       }
-|      LTYPE0 nonnon   { outcode($1, &$2); }
-|      LTYPE1 nonrem   { outcode($1, &$2); }
-|      LTYPE2 rimnon   { outcode($1, &$2); }
-|      LTYPE3 rimrem   { outcode($1, &$2); }
-|      LTYPE4 remrim   { outcode($1, &$2); }
-|      LTYPER nonrel   { outcode($1, &$2); }
+               if $1.Value != int64($3) {
+                       yyerror("redeclaration of %s", $1.Name);
+               }
+               $1.Value = $3;
+       }
+|      LTYPE0 nonnon   { outcode(int($1), &$2); }
+|      LTYPE1 nonrem   { outcode(int($1), &$2); }
+|      LTYPE2 rimnon   { outcode(int($1), &$2); }
+|      LTYPE3 rimrem   { outcode(int($1), &$2); }
+|      LTYPE4 remrim   { outcode(int($1), &$2); }
+|      LTYPER nonrel   { outcode(int($1), &$2); }
 |      spec1
 |      spec2
-|      LTYPEC spec3    { outcode($1, &$2); }
-|      LTYPEN spec4    { outcode($1, &$2); }
-|      LTYPES spec5    { outcode($1, &$2); }
-|      LTYPEM spec6    { outcode($1, &$2); }
-|      LTYPEI spec7    { outcode($1, &$2); }
+|      LTYPEC spec3    { outcode(int($1), &$2); }
+|      LTYPEN spec4    { outcode(int($1), &$2); }
+|      LTYPES spec5    { outcode(int($1), &$2); }
+|      LTYPEM spec6    { outcode(int($1), &$2); }
+|      LTYPEI spec7    { outcode(int($1), &$2); }
 |      spec8
-|      LTYPEXC spec9   { outcode($1, &$2); }
-|      LTYPEX spec10   { outcode($1, &$2); }
-|      LTYPEPC spec11  { outcode($1, &$2); }
-|      LTYPEF spec12   { outcode($1, &$2); }
+|      LTYPEXC spec9   { outcode(int($1), &$2); }
+|      LTYPEX spec10   { outcode(int($1), &$2); }
+|      LTYPEPC spec11  { outcode(int($1), &$2); }
+|      LTYPEF spec12   { outcode(int($1), &$2); }
 
 nonnon:
        {
@@ -182,60 +192,46 @@ nonrel:
 spec1: /* DATA */
        LTYPED nam '/' con ',' imm
        {
-               Addr2 a;
-               a.from = $2;
-               a.to = $6;
-               outcode(ADATA, &a);
-               if(pass > 1) {
-                       lastpc->from3.type = TYPE_CONST;
-                       lastpc->from3.offset = $4;
+               outcode(obj.ADATA, &Addr2{$2, $6})
+               if asm.Pass > 1 {
+                       lastpc.From3.Type = obj.TYPE_CONST
+                       lastpc.From3.Offset = $4
                }
        }
 
 spec2: /* TEXT */
        LTYPET mem ',' '$' textsize
        {
-               Addr2 a;
-               settext($2.sym);
-               a.from = $2;
-               a.to = $5;
-               outcode(ATEXT, &a);
+               asm.Settext($2.Sym);
+               outcode(obj.ATEXT, &Addr2{$2, $5})
        }
 |      LTYPET mem ',' con ',' '$' textsize
        {
-               Addr2 a;
-               settext($2.sym);
-               a.from = $2;
-               a.to = $7;
-               outcode(ATEXT, &a);
-               if(pass > 1) {
-                       lastpc->from3.type = TYPE_CONST;
-                       lastpc->from3.offset = $4;
+               asm.Settext($2.Sym);
+               outcode(obj.ATEXT, &Addr2{$2, $7})
+               if asm.Pass > 1 {
+                       lastpc.From3.Type = obj.TYPE_CONST
+                       lastpc.From3.Offset = $4
                }
        }
 
 spec8: /* GLOBL */
        LTYPEG mem ',' imm
        {
-               Addr2 a;
-               settext($2.sym);
-               a.from = $2;
-               a.to = $4;
-               outcode(AGLOBL, &a);
+               asm.Settext($2.Sym);
+               outcode(obj.AGLOBL, &Addr2{$2, $4})
        }
 |      LTYPEG mem ',' con ',' imm
        {
-               Addr2 a;
-               settext($2.sym);
-               a.from = $2;
-               a.to = $6;
-               outcode(AGLOBL, &a);
-               if(pass > 1) {
-                       lastpc->from3.type = TYPE_CONST;
-                       lastpc->from3.offset = $4;
+               asm.Settext($2.Sym);
+               outcode(obj.AGLOBL, &Addr2{$2, $6})
+               if asm.Pass > 1 {
+                       lastpc.From3.Type = obj.TYPE_CONST
+                       lastpc.From3.Offset = $4
                }
        }
 
+
 spec3: /* JMP/CALL */
        ',' rom
        {
@@ -251,7 +247,7 @@ spec3:      /* JMP/CALL */
        {
                $$.from = nullgen;
                $$.to = $2;
-               $$.to.type = TYPE_INDIR;
+               $$.to.Type = obj.TYPE_INDIR
        }
 
 spec4: /* NOP */
@@ -268,9 +264,10 @@ spec5:     /* SHL/SHR */
        {
                $$.from = $1;
                $$.to = $3;
-               if($$.from.index != TYPE_NONE)
+               if $$.from.Index != obj.TYPE_NONE {
                        yyerror("dp shift with lhs index");
-               $$.from.index = $5;
+               }
+               $$.from.Index = int16($5);
        }
 
 spec6: /* MOVW/MOVL */
@@ -283,9 +280,10 @@ spec6:     /* MOVW/MOVL */
        {
                $$.from = $1;
                $$.to = $3;
-               if($$.to.index != TYPE_NONE)
+               if $$.to.Index != obj.TYPE_NONE {
                        yyerror("dp move with lhs index");
-               $$.to.index = $5;
+               }
+               $$.to.Index = int16($5);
        }
 
 spec7:
@@ -310,7 +308,7 @@ spec9:      /* CMPPS/CMPPD */
        {
                $$.from = $1;
                $$.to = $3;
-               $$.to.offset = $5;
+               $$.to.Offset = $5;
        }
 
 spec10:        /* PINSRD */
@@ -318,16 +316,18 @@ spec10:   /* PINSRD */
        {
                $$.from = $3;
                $$.to = $5;
-               if($1.type != TYPE_CONST)
-                       yyerror("illegal constant");
-               $$.to.offset = $1.offset;
+               if $1.Type != obj.TYPE_CONST {
+                       yyerror("illegal constant")
+               }
+               $$.to.Offset = $1.Offset;
        }
 
 spec11:        /* PCDATA */
        rim ',' rim
        {
-               if($1.type != TYPE_CONST || $3.type != TYPE_CONST)
+               if $1.Type != obj.TYPE_CONST || $3.Type != obj.TYPE_CONST {
                        yyerror("arguments to PCDATA must be integer constants");
+               }
                $$.from = $1;
                $$.to = $3;
        }
@@ -335,10 +335,12 @@ spec11:   /* PCDATA */
 spec12:        /* FUNCDATA */
        rim ',' rim
        {
-               if($1.type != TYPE_CONST)
+               if $1.Type != obj.TYPE_CONST {
                        yyerror("index for FUNCDATA must be integer constant");
-               if($3.type != TYPE_MEM || ($3.name != NAME_EXTERN && $3.name != NAME_STATIC))
+               }
+               if $3.Type != obj.TYPE_MEM || ($3.Name != obj.NAME_EXTERN && $3.Name != obj.NAME_STATIC) {
                        yyerror("value for FUNCDATA must be symbol reference");
+               }
                $$.from = $1;
                $$.to = $3;
        }
@@ -370,135 +372,137 @@ rel:
        con '(' LPC ')'
        {
                $$ = nullgen;
-               $$.type = TYPE_BRANCH;
-               $$.offset = $1 + pc;
+               $$.Type = obj.TYPE_BRANCH;
+               $$.Offset = $1 + int64(asm.PC);
        }
 |      LNAME offset
        {
-               $1 = labellookup($1);
+               $1 = asm.LabelLookup($1);
                $$ = nullgen;
-               if(pass == 2 && $1->type != LLAB)
-                       yyerror("undefined label: %s", $1->labelname);
-               $$.type = TYPE_BRANCH;
-               $$.offset = $1->value + $2;
+               if asm.Pass == 2 && $1.Type != LLAB {
+                       yyerror("undefined label: %s", $1.Labelname);
+               }
+               $$.Type = obj.TYPE_BRANCH;
+               $$.Offset = $1.Value + $2;
        }
 
 reg:
        LBREG
        {
                $$ = nullgen;
-               $$.type = TYPE_REG;
-               $$.reg = $1;
+               $$.Type = obj.TYPE_REG
+               $$.Reg = int16($1);
        }
 |      LFREG
        {
                $$ = nullgen;
-               $$.type = TYPE_REG;
-               $$.reg = $1;
+               $$.Type = obj.TYPE_REG
+               $$.Reg = int16($1);
        }
 |      LLREG
        {
                $$ = nullgen;
-               $$.type = TYPE_REG;
-               $$.reg = $1;
+               $$.Type = obj.TYPE_REG
+               $$.Reg = int16($1);
        }
 |      LXREG
        {
                $$ = nullgen;
-               $$.type = TYPE_REG;
-               $$.reg = $1;
+               $$.Type = obj.TYPE_REG
+               $$.Reg = int16($1);
        }
 |      LSP
        {
                $$ = nullgen;
-               $$.type = TYPE_REG;
-               $$.reg = REG_SP;
+               $$.Type = obj.TYPE_REG
+               $$.Reg = REG_SP;
        }
 |      LSREG
        {
                $$ = nullgen;
-               $$.type = TYPE_REG;
-               $$.reg = $1;
+               $$.Type = obj.TYPE_REG
+               $$.Reg = int16($1);
        }
 
 imm:
        '$' con
        {
                $$ = nullgen;
-               $$.type = TYPE_CONST;
-               $$.offset = $2;
+               $$.Type = obj.TYPE_CONST;
+               $$.Offset = $2;
        }
 |      '$' nam
        {
                $$ = $2;
-               $$.type = TYPE_ADDR;
+               $$.Type = obj.TYPE_ADDR
                /*
-               if($2.name == NAME_AUTO || $2.name == NAME_PARAM)
+               if($2.Type == D_AUTO || $2.Type == D_PARAM)
                        yyerror("constant cannot be automatic: %s",
-                               $2.sym->name);
+                               $2.Sym.name);
                 */
        }
 |      '$' LSCONST
        {
                $$ = nullgen;
-               $$.type = TYPE_SCONST;
-               memcpy($$.u.sval, $2, sizeof($$.u.sval));
+               $$.Type = obj.TYPE_SCONST;
+               $$.U.Sval = $2
        }
 |      '$' LFCONST
        {
                $$ = nullgen;
-               $$.type = TYPE_FCONST;
-               $$.u.dval = $2;
+               $$.Type = obj.TYPE_FCONST;
+               $$.U.Dval = $2;
        }
 |      '$' '(' LFCONST ')'
        {
                $$ = nullgen;
-               $$.type = TYPE_FCONST;
-               $$.u.dval = $3;
+               $$.Type = obj.TYPE_FCONST;
+               $$.U.Dval = $3;
        }
 |      '$' '(' '-' LFCONST ')'
        {
                $$ = nullgen;
-               $$.type = TYPE_FCONST;
-               $$.u.dval = -$4;
+               $$.Type = obj.TYPE_FCONST;
+               $$.U.Dval = -$4;
        }
 |      '$' '-' LFCONST
        {
                $$ = nullgen;
-               $$.type = TYPE_FCONST;
-               $$.u.dval = -$3;
+               $$.Type = obj.TYPE_FCONST;
+               $$.U.Dval = -$3;
        }
 
 textsize:
        LCONST
        {
                $$ = nullgen;
-               $$.type = TYPE_TEXTSIZE;
-               $$.offset = $1;
-               $$.u.argsize = ArgsSizeUnknown;
+               $$.Type = obj.TYPE_TEXTSIZE;
+               $$.Offset = $1;
+               $$.U.Argsize = obj.ArgsSizeUnknown;
        }
 |      '-' LCONST
        {
                $$ = nullgen;
-               $$.type = TYPE_TEXTSIZE;
-               $$.offset = -$2;
-               $$.u.argsize = ArgsSizeUnknown;
+               $$.Type = obj.TYPE_TEXTSIZE;
+               $$.Offset = -$2;
+               $$.U.Argsize = obj.ArgsSizeUnknown;
        }
 |      LCONST '-' LCONST
        {
                $$ = nullgen;
-               $$.type = TYPE_TEXTSIZE;
-               $$.offset = $1;
-               $$.u.argsize = $3;
+               $$.Type = obj.TYPE_TEXTSIZE;
+               $$.Offset = $1;
+               $$.U.Argsize = int32($3);
        }
 |      '-' LCONST '-' LCONST
        {
                $$ = nullgen;
-               $$.type = TYPE_TEXTSIZE;
-               $$.offset = -$2;
-               $$.u.argsize = $4;
+               $$.Type = obj.TYPE_TEXTSIZE;
+               $$.Offset = -$2;
+               $$.U.Argsize = int32($4);
        }
 
+
 mem:
        omem
 |      nmem
@@ -507,90 +511,87 @@ omem:
        con
        {
                $$ = nullgen;
-               $$.type = TYPE_MEM;
-               $$.reg = REG_NONE;
-               $$.offset = $1;
+               $$.Type = obj.TYPE_MEM
+               $$.Offset = $1;
        }
 |      con '(' LLREG ')'
        {
                $$ = nullgen;
-               $$.type = TYPE_MEM;
-               $$.reg = $3;
-               $$.offset = $1;
+               $$.Type = obj.TYPE_MEM
+               $$.Reg = int16($3)
+               $$.Offset = $1;
        }
 |      con '(' LSP ')'
        {
                $$ = nullgen;
-               $$.type = TYPE_MEM;
-               $$.reg = REG_SP;
-               $$.offset = $1;
+               $$.Type = obj.TYPE_MEM
+               $$.Reg = REG_SP
+               $$.Offset = $1;
        }
 |      con '(' LLREG '*' con ')'
        {
                $$ = nullgen;
-               $$.type = TYPE_MEM;
-               $$.reg = REG_NONE;
-               $$.offset = $1;
-               $$.index = $3;
-               $$.scale = $5;
-               checkscale($$.scale);
+               $$.Type = obj.TYPE_MEM
+               $$.Offset = $1;
+               $$.Index = int16($3);
+               $$.Scale = int8($5);
+               checkscale($$.Scale);
        }
 |      con '(' LLREG ')' '(' LLREG '*' con ')'
        {
                $$ = nullgen;
-               $$.type = TYPE_MEM;
-               $$.reg = $3;
-               $$.offset = $1;
-               $$.index = $6;
-               $$.scale = $8;
-               checkscale($$.scale);
+               $$.Type = obj.TYPE_MEM
+               $$.Reg = int16($3)
+               $$.Offset = $1;
+               $$.Index = int16($6);
+               $$.Scale = int8($8);
+               checkscale($$.Scale);
        }
 |      con '(' LLREG ')' '(' LSREG '*' con ')'
        {
                $$ = nullgen;
-               $$.type = TYPE_MEM;
-               $$.reg = $3;
-               $$.offset = $1;
-               $$.index = $6;
-               $$.scale = $8;
-               checkscale($$.scale);
+               $$.Type = obj.TYPE_MEM
+               $$.Reg = int16($3)
+               $$.Offset = $1;
+               $$.Index = int16($6);
+               $$.Scale = int8($8);
+               checkscale($$.Scale);
        }
 |      '(' LLREG ')'
        {
                $$ = nullgen;
-               $$.type = TYPE_MEM;
-               $$.reg = $2;
+               $$.Type = obj.TYPE_MEM
+               $$.Reg = int16($2);
        }
 |      '(' LSP ')'
        {
                $$ = nullgen;
-               $$.type = TYPE_MEM;
-               $$.reg = REG_SP;
+               $$.Type = obj.TYPE_MEM
+               $$.Reg = REG_SP
        }
 |      con '(' LSREG ')'
        {
                $$ = nullgen;
-               $$.type = TYPE_MEM;
-               $$.reg = $3;
-               $$.offset = $1;
+               $$.Type = obj.TYPE_MEM
+               $$.Reg = int16($3)
+               $$.Offset = $1;
        }
 |      '(' LLREG '*' con ')'
        {
                $$ = nullgen;
-               $$.type = TYPE_MEM;
-               $$.reg = REG_NONE;
-               $$.index = $2;
-               $$.scale = $4;
-               checkscale($$.scale);
+               $$.Type = obj.TYPE_MEM
+               $$.Index = int16($2);
+               $$.Scale = int8($4);
+               checkscale($$.Scale);
        }
 |      '(' LLREG ')' '(' LLREG '*' con ')'
        {
                $$ = nullgen;
-               $$.type = TYPE_MEM;
-               $$.reg = $2;
-               $$.index = $5;
-               $$.scale = $7;
-               checkscale($$.scale);
+               $$.Type = obj.TYPE_MEM
+               $$.Reg = int16($2)
+               $$.Index = int16($5);
+               $$.Scale = int8($7);
+               checkscale($$.Scale);
        }
 
 nmem:
@@ -601,27 +602,27 @@ nmem:
 |      nam '(' LLREG '*' con ')'
        {
                $$ = $1;
-               $$.index = $3;
-               $$.scale = $5;
-               checkscale($$.scale);
+               $$.Index = int16($3);
+               $$.Scale = int8($5);
+               checkscale($$.Scale);
        }
 
 nam:
        LNAME offset '(' pointer ')'
        {
                $$ = nullgen;
-               $$.type = TYPE_MEM;
-               $$.name = $4;
-               $$.sym = linklookup(ctxt, $1->name, 0);
-               $$.offset = $2;
+               $$.Type = obj.TYPE_MEM
+               $$.Name = int8($4);
+               $$.Sym = obj.Linklookup(asm.Ctxt, $1.Name, 0);
+               $$.Offset = $2;
        }
 |      LNAME '<' '>' offset '(' LSB ')'
        {
                $$ = nullgen;
-               $$.type = TYPE_MEM;
-               $$.name = NAME_STATIC;
-               $$.sym = linklookup(ctxt, $1->name, 1);
-               $$.offset = $4;
+               $$.Type = obj.TYPE_MEM
+               $$.Name = obj.NAME_STATIC
+               $$.Sym = obj.Linklookup(asm.Ctxt, $1.Name, 1);
+               $$.Offset = $4;
        }
 
 offset:
@@ -641,7 +642,7 @@ pointer:
        LSB
 |      LSP
        {
-               $$ = NAME_AUTO;
+               $$ = obj.NAME_AUTO;
        }
 |      LFP
 
@@ -649,7 +650,7 @@ con:
        LCONST
 |      LVAR
        {
-               $$ = $1->value;
+               $$ = $1.Value;
        }
 |      '-' con
        {
@@ -661,7 +662,7 @@ con:
        }
 |      '~' con
        {
-               $$ = ~$2;
+               $$ = ^$2;
        }
 |      '(' expr ')'
        {
@@ -692,11 +693,11 @@ expr:
        }
 |      expr '<' '<' expr
        {
-               $$ = $1 << $4;
+               $$ = $1 << uint($4);
        }
 |      expr '>' '>' expr
        {
-               $$ = $1 >> $4;
+               $$ = $1 >> uint($4);
        }
 |      expr '&' expr
        {
diff --git a/src/cmd/8a/doc.go b/src/cmd/8a/doc.go
deleted file mode 100644 (file)
index 84c7254..0000000
+++ /dev/null
@@ -1,21 +0,0 @@
-// Copyright 2009 The Go Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style
-// license that can be found in the LICENSE file.
-
-// +build ignore
-
-/*
-
-8a is a version of the Plan 9 assembler.  The original is documented at
-
-       http://plan9.bell-labs.com/magic/man2html/1/8a
-
-Go-specific considerations are documented at
-
-       http://golang.org/doc/asm
-
-I
-Its target architecture is the x86, referred to by these tools for historical reasons as 386.
-
-*/
-package main
diff --git a/src/cmd/8a/lex.c b/src/cmd/8a/lex.c
deleted file mode 100644 (file)
index 846f6c6..0000000
+++ /dev/null
@@ -1,914 +0,0 @@
-// Inferno utils/8a/lex.c
-// http://code.google.com/p/inferno-os/source/browse/utils/8a/lex.c
-//
-//     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 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.
-
-#define        EXTERN
-#include <u.h>
-#include <libc.h>
-#include "a.h"
-#include "y.tab.h"
-
-enum
-{
-       Plan9   = 1<<0,
-       Unix    = 1<<1,
-       Windows = 1<<2,
-};
-
-int
-systemtype(int sys)
-{
-#ifdef _WIN32
-       return sys&Windows;
-#else
-       return sys&Plan9;
-#endif
-}
-
-int
-pathchar(void)
-{
-       return '/';
-}
-
-int
-Lconv(Fmt *fp)
-{
-       return linklinefmt(ctxt, fp);
-}
-
-void
-dodef(char *p)
-{
-       if(nDlist%8 == 0)
-               Dlist = allocn(Dlist, nDlist*sizeof(char *),
-                       8*sizeof(char *));
-       Dlist[nDlist++] = p;
-}
-
-void
-usage(void)
-{
-       print("usage: %ca [options] file.c...\n", thechar);
-       flagprint(1);
-       errorexit();
-}
-void
-main(int argc, char *argv[])
-{
-       char *p;
-
-       thechar = '8';
-       thestring = "386";
-
-       ctxt = linknew(&link386);
-       ctxt->diag = yyerror;
-       ctxt->bso = &bstdout;
-       ctxt->enforce_data_order = 1;
-       Binit(&bstdout, 1, OWRITE);
-       listinit8();
-       fmtinstall('L', Lconv);
-
-       // Allow GOARCH=thestring or GOARCH=thestringsuffix,
-       // but not other values.        
-       p = getgoarch();
-       if(strncmp(p, thestring, strlen(thestring)) != 0)
-               sysfatal("cannot use %cc with GOARCH=%s", thechar, p);
-
-       ensuresymb(NSYMB);
-       memset(debug, 0, sizeof(debug));
-       cinit();
-       outfile = 0;
-       setinclude(".");
-       
-       flagfn1("D", "name[=value]: add #define", dodef);
-       flagfn1("I", "dir: add dir to include path", setinclude);
-       flagcount("S", "print assembly and machine code", &debug['S']);
-       flagcount("m", "debug preprocessor macros", &debug['m']);
-       flagstr("o", "file: set output file", &outfile);
-       flagstr("trimpath", "prefix: remove prefix from recorded source file paths", &ctxt->trimpath);
-
-       flagparse(&argc, &argv, usage);
-       ctxt->debugasm = debug['S'];
-
-       if(argc < 1)
-               usage();
-       if(argc > 1){
-               print("can't assemble multiple files\n");
-               errorexit();
-       }
-
-       if(assemble(argv[0]))
-               errorexit();
-       Bflush(&bstdout);
-       if(nerrors > 0)
-               errorexit();
-       exits(0);
-}
-
-int
-assemble(char *file)
-{
-       char *ofile, *p;
-       int i, of;
-
-       ofile = alloc(strlen(file)+3); // +3 for .x\0 (x=thechar)
-       strcpy(ofile, file);
-       p = utfrrune(ofile, pathchar());
-       if(p) {
-               include[0] = ofile;
-               *p++ = 0;
-       } else
-               p = ofile;
-       if(outfile == 0) {
-               outfile = p;
-               if(outfile){
-                       p = utfrrune(outfile, '.');
-                       if(p)
-                               if(p[1] == 's' && p[2] == 0)
-                                       p[0] = 0;
-                       p = utfrune(outfile, 0);
-                       p[0] = '.';
-                       p[1] = thechar;
-                       p[2] = 0;
-               } else
-                       outfile = "/dev/null";
-       }
-
-       of = create(outfile, OWRITE, 0664);
-       if(of < 0) {
-               yyerror("%ca: cannot create %s", thechar, outfile);
-               errorexit();
-       }
-       Binit(&obuf, of, OWRITE);
-       Bprint(&obuf, "go object %s %s %s\n", getgoos(), getgoarch(), getgoversion());
-       Bprint(&obuf, "!\n");
-
-       for(pass = 1; pass <= 2; pass++) {
-               pinit(file);
-               for(i=0; i<nDlist; i++)
-                       dodefine(Dlist[i]);
-               yyparse();
-               cclean();
-               if(nerrors)
-                       return nerrors;
-       }
-
-       writeobj(ctxt, &obuf);
-       Bflush(&obuf);
-       return 0;
-}
-
-struct
-{
-       char    *name;
-       ushort  type;
-       ushort  value;
-} itab[] =
-{
-       "SP",           LSP,    NAME_AUTO,
-       "SB",           LSB,    NAME_EXTERN,
-       "FP",           LFP,    NAME_PARAM,
-
-       "PC",           LPC,    TYPE_BRANCH,
-
-       "AL",           LBREG,  REG_AL,
-       "CL",           LBREG,  REG_CL,
-       "DL",           LBREG,  REG_DL,
-       "BL",           LBREG,  REG_BL,
-       "AH",           LBREG,  REG_AH,
-       "CH",           LBREG,  REG_CH,
-       "DH",           LBREG,  REG_DH,
-       "BH",           LBREG,  REG_BH,
-
-       "AX",           LLREG,  REG_AX,
-       "CX",           LLREG,  REG_CX,
-       "DX",           LLREG,  REG_DX,
-       "BX",           LLREG,  REG_BX,
-/*     "SP",           LLREG,  REG_SP, */
-       "BP",           LLREG,  REG_BP,
-       "SI",           LLREG,  REG_SI,
-       "DI",           LLREG,  REG_DI,
-
-       "F0",           LFREG,  REG_F0+0,
-       "F1",           LFREG,  REG_F0+1,
-       "F2",           LFREG,  REG_F0+2,
-       "F3",           LFREG,  REG_F0+3,
-       "F4",           LFREG,  REG_F0+4,
-       "F5",           LFREG,  REG_F0+5,
-       "F6",           LFREG,  REG_F0+6,
-       "F7",           LFREG,  REG_F0+7,
-
-       "X0",           LXREG,  REG_X0+0,
-       "X1",           LXREG,  REG_X0+1,
-       "X2",           LXREG,  REG_X0+2,
-       "X3",           LXREG,  REG_X0+3,
-       "X4",           LXREG,  REG_X0+4,
-       "X5",           LXREG,  REG_X0+5,
-       "X6",           LXREG,  REG_X0+6,
-       "X7",           LXREG,  REG_X0+7,
-
-       "CS",           LSREG,  REG_CS,
-       "SS",           LSREG,  REG_SS,
-       "DS",           LSREG,  REG_DS,
-       "ES",           LSREG,  REG_ES,
-       "FS",           LSREG,  REG_FS,
-       "GS",           LSREG,  REG_GS,
-       "TLS",          LSREG,  REG_TLS,
-
-       "GDTR",         LBREG,  REG_GDTR,
-       "IDTR",         LBREG,  REG_IDTR,
-       "LDTR",         LBREG,  REG_LDTR,
-       "MSW",          LBREG,  REG_MSW,
-       "TASK",         LBREG,  REG_TASK,
-
-       "CR0",          LBREG,  REG_CR+0,
-       "CR1",          LBREG,  REG_CR+1,
-       "CR2",          LBREG,  REG_CR+2,
-       "CR3",          LBREG,  REG_CR+3,
-       "CR4",          LBREG,  REG_CR+4,
-       "CR5",          LBREG,  REG_CR+5,
-       "CR6",          LBREG,  REG_CR+6,
-       "CR7",          LBREG,  REG_CR+7,
-
-       "DR0",          LBREG,  REG_DR+0,
-       "DR1",          LBREG,  REG_DR+1,
-       "DR2",          LBREG,  REG_DR+2,
-       "DR3",          LBREG,  REG_DR+3,
-       "DR4",          LBREG,  REG_DR+4,
-       "DR5",          LBREG,  REG_DR+5,
-       "DR6",          LBREG,  REG_DR+6,
-       "DR7",          LBREG,  REG_DR+7,
-
-       "TR0",          LBREG,  REG_TR+0,
-       "TR1",          LBREG,  REG_TR+1,
-       "TR2",          LBREG,  REG_TR+2,
-       "TR3",          LBREG,  REG_TR+3,
-       "TR4",          LBREG,  REG_TR+4,
-       "TR5",          LBREG,  REG_TR+5,
-       "TR6",          LBREG,  REG_TR+6,
-       "TR7",          LBREG,  REG_TR+7,
-
-       "AAA",          LTYPE0, AAAA,
-       "AAD",          LTYPE0, AAAD,
-       "AAM",          LTYPE0, AAAM,
-       "AAS",          LTYPE0, AAAS,
-       "ADCB",         LTYPE3, AADCB,
-       "ADCL",         LTYPE3, AADCL,
-       "ADCW",         LTYPE3, AADCW,
-       "ADDB",         LTYPE3, AADDB,
-       "ADDL",         LTYPE3, AADDL,
-       "ADDW",         LTYPE3, AADDW,
-       "ADJSP",        LTYPE2, AADJSP,
-       "ANDB",         LTYPE3, AANDB,
-       "ANDL",         LTYPE3, AANDL,
-       "ANDW",         LTYPE3, AANDW,
-       "ARPL",         LTYPE3, AARPL,
-       "BOUNDL",       LTYPE3, ABOUNDL,
-       "BOUNDW",       LTYPE3, ABOUNDW,
-       "BSFL",         LTYPE3, ABSFL,
-       "BSFW",         LTYPE3, ABSFW,
-       "BSRL",         LTYPE3, ABSRL,
-       "BSRW",         LTYPE3, ABSRW,
-       "BSWAPL",       LTYPE1, ABSWAPL,
-       "BTCL",         LTYPE3, ABTCL,
-       "BTCW",         LTYPE3, ABTCW,
-       "BTL",          LTYPE3, ABTL,
-       "BTRL",         LTYPE3, ABTRL,
-       "BTRW",         LTYPE3, ABTRW,
-       "BTSL",         LTYPE3, ABTSL,
-       "BTSW",         LTYPE3, ABTSW,
-       "BTW",          LTYPE3, ABTW,
-       "BYTE",         LTYPE2, ABYTE,
-       "CALL",         LTYPEC, ACALL,
-       "CLC",          LTYPE0, ACLC,
-       "CLD",          LTYPE0, ACLD,
-       "CLI",          LTYPE0, ACLI,
-       "CLTS",         LTYPE0, ACLTS,
-       "CMC",          LTYPE0, ACMC,
-       "CMPB",         LTYPE4, ACMPB,
-       "CMPL",         LTYPE4, ACMPL,
-       "CMPW",         LTYPE4, ACMPW,
-       "CMPSB",        LTYPE0, ACMPSB,
-       "CMPSL",        LTYPE0, ACMPSL,
-       "CMPSW",        LTYPE0, ACMPSW,
-       "CMPXCHG8B",    LTYPE1, ACMPXCHG8B,
-       "CMPXCHGB",     LTYPE3, ACMPXCHGB,
-       "CMPXCHGL",     LTYPE3, ACMPXCHGL,
-       "CMPXCHGW",     LTYPE3, ACMPXCHGW,
-       "CPUID",        LTYPE0, ACPUID,
-       "DAA",          LTYPE0, ADAA,
-       "DAS",          LTYPE0, ADAS,
-       "DATA",         LTYPED, ADATA,
-       "DECB",         LTYPE1, ADECB,
-       "DECL",         LTYPE1, ADECL,
-       "DECW",         LTYPE1, ADECW,
-       "DIVB",         LTYPE2, ADIVB,
-       "DIVL",         LTYPE2, ADIVL,
-       "DIVW",         LTYPE2, ADIVW,
-       "END",          LTYPE0, AEND,
-       "ENTER",        LTYPE2, AENTER,
-       "GLOBL",        LTYPEG, AGLOBL,
-       "HLT",          LTYPE0, AHLT,
-       "IDIVB",        LTYPE2, AIDIVB,
-       "IDIVL",        LTYPE2, AIDIVL,
-       "IDIVW",        LTYPE2, AIDIVW,
-       "IMULB",        LTYPE2, AIMULB,
-       "IMULL",        LTYPEI, AIMULL,
-       "IMULW",        LTYPEI, AIMULW,
-       "INB",          LTYPE0, AINB,
-       "INL",          LTYPE0, AINL,
-       "INW",          LTYPE0, AINW,
-       "INCB",         LTYPE1, AINCB,
-       "INCL",         LTYPE1, AINCL,
-       "INCW",         LTYPE1, AINCW,
-       "INSB",         LTYPE0, AINSB,
-       "INSL",         LTYPE0, AINSL,
-       "INSW",         LTYPE0, AINSW,
-       "INT",          LTYPE2, AINT,
-       "INTO",         LTYPE0, AINTO,
-       "IRETL",        LTYPE0, AIRETL,
-       "IRETW",        LTYPE0, AIRETW,
-
-       "JOS",          LTYPER, AJOS,   /* overflow set (OF = 1) */
-       "JO",           LTYPER, AJOS,   /* alternate */
-       "JOC",          LTYPER, AJOC,   /* overflow clear (OF = 0) */
-       "JNO",          LTYPER, AJOC,   /* alternate */
-       "JCS",          LTYPER, AJCS,   /* carry set (CF = 1) */
-       "JB",           LTYPER, AJCS,   /* alternate */
-       "JC",           LTYPER, AJCS,   /* alternate */
-       "JNAE",         LTYPER, AJCS,   /* alternate */
-       "JLO",          LTYPER, AJCS,   /* alternate */
-       "JCC",          LTYPER, AJCC,   /* carry clear (CF = 0) */
-       "JAE",          LTYPER, AJCC,   /* alternate */
-       "JNB",          LTYPER, AJCC,   /* alternate */
-       "JNC",          LTYPER, AJCC,   /* alternate */
-       "JHS",          LTYPER, AJCC,   /* alternate */
-       "JEQ",          LTYPER, AJEQ,   /* equal (ZF = 1) */
-       "JE",           LTYPER, AJEQ,   /* alternate */
-       "JZ",           LTYPER, AJEQ,   /* alternate */
-       "JNE",          LTYPER, AJNE,   /* not equal (ZF = 0) */
-       "JNZ",          LTYPER, AJNE,   /* alternate */
-       "JLS",          LTYPER, AJLS,   /* lower or same (unsigned) (CF = 1 || ZF = 1) */
-       "JBE",          LTYPER, AJLS,   /* alternate */
-       "JNA",          LTYPER, AJLS,   /* alternate */
-       "JHI",          LTYPER, AJHI,   /* higher (unsigned) (CF = 0 && ZF = 0) */
-       "JA",           LTYPER, AJHI,   /* alternate */
-       "JNBE",         LTYPER, AJHI,   /* alternate */
-       "JMI",          LTYPER, AJMI,   /* negative (minus) (SF = 1) */
-       "JS",           LTYPER, AJMI,   /* alternate */
-       "JPL",          LTYPER, AJPL,   /* non-negative (plus) (SF = 0) */
-       "JNS",          LTYPER, AJPL,   /* alternate */
-       "JPS",          LTYPER, AJPS,   /* parity set (PF = 1) */
-       "JP",           LTYPER, AJPS,   /* alternate */
-       "JPE",          LTYPER, AJPS,   /* alternate */
-       "JPC",          LTYPER, AJPC,   /* parity clear (PF = 0) */
-       "JNP",          LTYPER, AJPC,   /* alternate */
-       "JPO",          LTYPER, AJPC,   /* alternate */
-       "JLT",          LTYPER, AJLT,   /* less than (signed) (SF != OF) */
-       "JL",           LTYPER, AJLT,   /* alternate */
-       "JNGE",         LTYPER, AJLT,   /* alternate */
-       "JGE",          LTYPER, AJGE,   /* greater than or equal (signed) (SF = OF) */
-       "JNL",          LTYPER, AJGE,   /* alternate */
-       "JLE",          LTYPER, AJLE,   /* less than or equal (signed) (ZF = 1 || SF != OF) */
-       "JNG",          LTYPER, AJLE,   /* alternate */
-       "JGT",          LTYPER, AJGT,   /* greater than (signed) (ZF = 0 && SF = OF) */
-       "JG",           LTYPER, AJGT,   /* alternate */
-       "JNLE",         LTYPER, AJGT,   /* alternate */
-
-       "JCXZL",        LTYPER, AJCXZL,
-       "JCXZW",        LTYPER, AJCXZW,
-       "JMP",          LTYPEC, AJMP,
-       "LAHF",         LTYPE0, ALAHF,
-       "LARL",         LTYPE3, ALARL,
-       "LARW",         LTYPE3, ALARW,
-       "LEAL",         LTYPE3, ALEAL,
-       "LEAW",         LTYPE3, ALEAW,
-       "LEAVEL",       LTYPE0, ALEAVEL,
-       "LEAVEW",       LTYPE0, ALEAVEW,
-       "LOCK",         LTYPE0, ALOCK,
-       "LODSB",        LTYPE0, ALODSB,
-       "LODSL",        LTYPE0, ALODSL,
-       "LODSW",        LTYPE0, ALODSW,
-       "LONG",         LTYPE2, ALONG,
-       "LOOP",         LTYPER, ALOOP,
-       "LOOPEQ",       LTYPER, ALOOPEQ,
-       "LOOPNE",       LTYPER, ALOOPNE,
-       "LSLL",         LTYPE3, ALSLL,
-       "LSLW",         LTYPE3, ALSLW,
-       "MOVB",         LTYPE3, AMOVB,
-       "MOVL",         LTYPEM, AMOVL,
-       "MOVW",         LTYPEM, AMOVW,
-       "MOVQ",         LTYPEM, AMOVQ,
-       "MOVBLSX",      LTYPE3, AMOVBLSX,
-       "MOVBLZX",      LTYPE3, AMOVBLZX,
-       "MOVBWSX",      LTYPE3, AMOVBWSX,
-       "MOVBWZX",      LTYPE3, AMOVBWZX,
-       "MOVWLSX",      LTYPE3, AMOVWLSX,
-       "MOVWLZX",      LTYPE3, AMOVWLZX,
-       "MOVSB",        LTYPE0, AMOVSB,
-       "MOVSL",        LTYPE0, AMOVSL,
-       "MOVSW",        LTYPE0, AMOVSW,
-       "MULB",         LTYPE2, AMULB,
-       "MULL",         LTYPE2, AMULL,
-       "MULW",         LTYPE2, AMULW,
-       "NEGB",         LTYPE1, ANEGB,
-       "NEGL",         LTYPE1, ANEGL,
-       "NEGW",         LTYPE1, ANEGW,
-       "NOP",          LTYPEN, ANOP,
-       "NOTB",         LTYPE1, ANOTB,
-       "NOTL",         LTYPE1, ANOTL,
-       "NOTW",         LTYPE1, ANOTW,
-       "ORB",          LTYPE3, AORB,
-       "ORL",          LTYPE3, AORL,
-       "ORW",          LTYPE3, AORW,
-       "OUTB",         LTYPE0, AOUTB,
-       "OUTL",         LTYPE0, AOUTL,
-       "OUTW",         LTYPE0, AOUTW,
-       "OUTSB",        LTYPE0, AOUTSB,
-       "OUTSL",        LTYPE0, AOUTSL,
-       "OUTSW",        LTYPE0, AOUTSW,
-       "PAUSE",        LTYPEN, APAUSE,
-       "PINSRD",       LTYPEX, APINSRD,
-       "POPAL",        LTYPE0, APOPAL,
-       "POPAW",        LTYPE0, APOPAW,
-       "POPFL",        LTYPE0, APOPFL,
-       "POPFW",        LTYPE0, APOPFW,
-       "POPL",         LTYPE1, APOPL,
-       "POPW",         LTYPE1, APOPW,
-       "PUSHAL",       LTYPE0, APUSHAL,
-       "PUSHAW",       LTYPE0, APUSHAW,
-       "PUSHFL",       LTYPE0, APUSHFL,
-       "PUSHFW",       LTYPE0, APUSHFW,
-       "PUSHL",        LTYPE2, APUSHL,
-       "PUSHW",        LTYPE2, APUSHW,
-       "RCLB",         LTYPE3, ARCLB,
-       "RCLL",         LTYPE3, ARCLL,
-       "RCLW",         LTYPE3, ARCLW,
-       "RCRB",         LTYPE3, ARCRB,
-       "RCRL",         LTYPE3, ARCRL,
-       "RCRW",         LTYPE3, ARCRW,
-       "RDTSC",        LTYPE0, ARDTSC,
-       "REP",          LTYPE0, AREP,
-       "REPN",         LTYPE0, AREPN,
-       "RET",          LTYPE0, ARET,
-       "ROLB",         LTYPE3, AROLB,
-       "ROLL",         LTYPE3, AROLL,
-       "ROLW",         LTYPE3, AROLW,
-       "RORB",         LTYPE3, ARORB,
-       "RORL",         LTYPE3, ARORL,
-       "RORW",         LTYPE3, ARORW,
-       "SAHF",         LTYPE0, ASAHF,
-       "SALB",         LTYPE3, ASALB,
-       "SALL",         LTYPE3, ASALL,
-       "SALW",         LTYPE3, ASALW,
-       "SARB",         LTYPE3, ASARB,
-       "SARL",         LTYPE3, ASARL,
-       "SARW",         LTYPE3, ASARW,
-       "SBBB",         LTYPE3, ASBBB,
-       "SBBL",         LTYPE3, ASBBL,
-       "SBBW",         LTYPE3, ASBBW,
-       "SCASB",        LTYPE0, ASCASB,
-       "SCASL",        LTYPE0, ASCASL,
-       "SCASW",        LTYPE0, ASCASW,
-       "SETCC",        LTYPE1, ASETCC, /* see JCC etc above for condition codes */
-       "SETCS",        LTYPE1, ASETCS,
-       "SETEQ",        LTYPE1, ASETEQ,
-       "SETGE",        LTYPE1, ASETGE,
-       "SETGT",        LTYPE1, ASETGT,
-       "SETHI",        LTYPE1, ASETHI,
-       "SETLE",        LTYPE1, ASETLE,
-       "SETLS",        LTYPE1, ASETLS,
-       "SETLT",        LTYPE1, ASETLT,
-       "SETMI",        LTYPE1, ASETMI,
-       "SETNE",        LTYPE1, ASETNE,
-       "SETOC",        LTYPE1, ASETOC,
-       "SETOS",        LTYPE1, ASETOS,
-       "SETPC",        LTYPE1, ASETPC,
-       "SETPL",        LTYPE1, ASETPL,
-       "SETPS",        LTYPE1, ASETPS,
-       "CDQ",          LTYPE0, ACDQ,
-       "CWD",          LTYPE0, ACWD,
-       "SHLB",         LTYPE3, ASHLB,
-       "SHLL",         LTYPES, ASHLL,
-       "SHLW",         LTYPES, ASHLW,
-       "SHRB",         LTYPE3, ASHRB,
-       "SHRL",         LTYPES, ASHRL,
-       "SHRW",         LTYPES, ASHRW,
-       "STC",          LTYPE0, ASTC,
-       "STD",          LTYPE0, ASTD,
-       "STI",          LTYPE0, ASTI,
-       "STOSB",        LTYPE0, ASTOSB,
-       "STOSL",        LTYPE0, ASTOSL,
-       "STOSW",        LTYPE0, ASTOSW,
-       "SUBB",         LTYPE3, ASUBB,
-       "SUBL",         LTYPE3, ASUBL,
-       "SUBW",         LTYPE3, ASUBW,
-       "SYSCALL",      LTYPE0, ASYSCALL,
-       "TESTB",        LTYPE3, ATESTB,
-       "TESTL",        LTYPE3, ATESTL,
-       "TESTW",        LTYPE3, ATESTW,
-       "TEXT",         LTYPET, ATEXT,
-       "VERR",         LTYPE2, AVERR,
-       "VERW",         LTYPE2, AVERW,
-       "WAIT",         LTYPE0, AWAIT,
-       "WORD",         LTYPE2, AWORD,
-       "XADDB",        LTYPE3, AXADDB,
-       "XADDL",        LTYPE3, AXADDL,
-       "XADDW",        LTYPE3, AXADDW,
-       "XCHGB",        LTYPE3, AXCHGB,
-       "XCHGL",        LTYPE3, AXCHGL,
-       "XCHGW",        LTYPE3, AXCHGW,
-       "XLAT",         LTYPE2, AXLAT,
-       "XORB",         LTYPE3, AXORB,
-       "XORL",         LTYPE3, AXORL,
-       "XORW",         LTYPE3, AXORW,
-
-       "CMOVLCC",      LTYPE3, ACMOVLCC,
-       "CMOVLCS",      LTYPE3, ACMOVLCS,
-       "CMOVLEQ",      LTYPE3, ACMOVLEQ,
-       "CMOVLGE",      LTYPE3, ACMOVLGE,
-       "CMOVLGT",      LTYPE3, ACMOVLGT,
-       "CMOVLHI",      LTYPE3, ACMOVLHI,
-       "CMOVLLE",      LTYPE3, ACMOVLLE,
-       "CMOVLLS",      LTYPE3, ACMOVLLS,
-       "CMOVLLT",      LTYPE3, ACMOVLLT,
-       "CMOVLMI",      LTYPE3, ACMOVLMI,
-       "CMOVLNE",      LTYPE3, ACMOVLNE,
-       "CMOVLOC",      LTYPE3, ACMOVLOC,
-       "CMOVLOS",      LTYPE3, ACMOVLOS,
-       "CMOVLPC",      LTYPE3, ACMOVLPC,
-       "CMOVLPL",      LTYPE3, ACMOVLPL,
-       "CMOVLPS",      LTYPE3, ACMOVLPS,
-       "CMOVWCC",      LTYPE3, ACMOVWCC,
-       "CMOVWCS",      LTYPE3, ACMOVWCS,
-       "CMOVWEQ",      LTYPE3, ACMOVWEQ,
-       "CMOVWGE",      LTYPE3, ACMOVWGE,
-       "CMOVWGT",      LTYPE3, ACMOVWGT,
-       "CMOVWHI",      LTYPE3, ACMOVWHI,
-       "CMOVWLE",      LTYPE3, ACMOVWLE,
-       "CMOVWLS",      LTYPE3, ACMOVWLS,
-       "CMOVWLT",      LTYPE3, ACMOVWLT,
-       "CMOVWMI",      LTYPE3, ACMOVWMI,
-       "CMOVWNE",      LTYPE3, ACMOVWNE,
-       "CMOVWOC",      LTYPE3, ACMOVWOC,
-       "CMOVWOS",      LTYPE3, ACMOVWOS,
-       "CMOVWPC",      LTYPE3, ACMOVWPC,
-       "CMOVWPL",      LTYPE3, ACMOVWPL,
-       "CMOVWPS",      LTYPE3, ACMOVWPS,
-
-       "FMOVB",        LTYPE3, AFMOVB,
-       "FMOVBP",       LTYPE3, AFMOVBP,
-       "FMOVD",        LTYPE3, AFMOVD,
-       "FMOVDP",       LTYPE3, AFMOVDP,
-       "FMOVF",        LTYPE3, AFMOVF,
-       "FMOVFP",       LTYPE3, AFMOVFP,
-       "FMOVL",        LTYPE3, AFMOVL,
-       "FMOVLP",       LTYPE3, AFMOVLP,
-       "FMOVV",        LTYPE3, AFMOVV,
-       "FMOVVP",       LTYPE3, AFMOVVP,
-       "FMOVW",        LTYPE3, AFMOVW,
-       "FMOVWP",       LTYPE3, AFMOVWP,
-       "FMOVX",        LTYPE3, AFMOVX,
-       "FMOVXP",       LTYPE3, AFMOVXP,
-       "FCMOVCC",      LTYPE3, AFCMOVCC,
-       "FCMOVCS",      LTYPE3, AFCMOVCS,
-       "FCMOVEQ",      LTYPE3, AFCMOVEQ,
-       "FCMOVHI",      LTYPE3, AFCMOVHI,
-       "FCMOVLS",      LTYPE3, AFCMOVLS,
-       "FCMOVNE",      LTYPE3, AFCMOVNE,
-       "FCMOVNU",      LTYPE3, AFCMOVNU,
-       "FCMOVUN",      LTYPE3, AFCMOVUN,
-       "FCOMB",        LTYPE3, AFCOMB,
-       "FCOMBP",       LTYPE3, AFCOMBP,
-       "FCOMD",        LTYPE3, AFCOMD,
-       "FCOMDP",       LTYPE3, AFCOMDP,
-       "FCOMDPP",      LTYPE3, AFCOMDPP,
-       "FCOMF",        LTYPE3, AFCOMF,
-       "FCOMFP",       LTYPE3, AFCOMFP,
-       "FCOMI",        LTYPE3, AFCOMI,
-       "FCOMIP",       LTYPE3, AFCOMIP,
-       "FCOML",        LTYPE3, AFCOML,
-       "FCOMLP",       LTYPE3, AFCOMLP,
-       "FCOMW",        LTYPE3, AFCOMW,
-       "FCOMWP",       LTYPE3, AFCOMWP,
-       "FUCOM",        LTYPE3, AFUCOM,
-       "FUCOMI",       LTYPE3, AFUCOMI,
-       "FUCOMIP",      LTYPE3, AFUCOMIP,
-       "FUCOMP",       LTYPE3, AFUCOMP,
-       "FUCOMPP",      LTYPE3, AFUCOMPP,
-       "FADDW",        LTYPE3, AFADDW,
-       "FADDL",        LTYPE3, AFADDL,
-       "FADDF",        LTYPE3, AFADDF,
-       "FADDD",        LTYPE3, AFADDD,
-       "FADDDP",       LTYPE3, AFADDDP,
-       "FSUBDP",       LTYPE3, AFSUBDP,
-       "FSUBW",        LTYPE3, AFSUBW,
-       "FSUBL",        LTYPE3, AFSUBL,
-       "FSUBF",        LTYPE3, AFSUBF,
-       "FSUBD",        LTYPE3, AFSUBD,
-       "FSUBRDP",      LTYPE3, AFSUBRDP,
-       "FSUBRW",       LTYPE3, AFSUBRW,
-       "FSUBRL",       LTYPE3, AFSUBRL,
-       "FSUBRF",       LTYPE3, AFSUBRF,
-       "FSUBRD",       LTYPE3, AFSUBRD,
-       "FMULDP",       LTYPE3, AFMULDP,
-       "FMULW",        LTYPE3, AFMULW,
-       "FMULL",        LTYPE3, AFMULL,
-       "FMULF",        LTYPE3, AFMULF,
-       "FMULD",        LTYPE3, AFMULD,
-       "FDIVDP",       LTYPE3, AFDIVDP,
-       "FDIVW",        LTYPE3, AFDIVW,
-       "FDIVL",        LTYPE3, AFDIVL,
-       "FDIVF",        LTYPE3, AFDIVF,
-       "FDIVD",        LTYPE3, AFDIVD,
-       "FDIVRDP",      LTYPE3, AFDIVRDP,
-       "FDIVRW",       LTYPE3, AFDIVRW,
-       "FDIVRL",       LTYPE3, AFDIVRL,
-       "FDIVRF",       LTYPE3, AFDIVRF,
-       "FDIVRD",       LTYPE3, AFDIVRD,
-       "FXCHD",        LTYPE3, AFXCHD,
-       "FFREE",        LTYPE1, AFFREE,
-       "FLDCW",        LTYPE2, AFLDCW,
-       "FLDENV",       LTYPE1, AFLDENV,
-       "FRSTOR",       LTYPE2, AFRSTOR,
-       "FSAVE",        LTYPE1, AFSAVE,
-       "FSTCW",        LTYPE1, AFSTCW,
-       "FSTENV",       LTYPE1, AFSTENV,
-       "FSTSW",        LTYPE1, AFSTSW,
-       "F2XM1",        LTYPE0, AF2XM1,
-       "FABS",         LTYPE0, AFABS,
-       "FCHS",         LTYPE0, AFCHS,
-       "FCLEX",        LTYPE0, AFCLEX,
-       "FCOS",         LTYPE0, AFCOS,
-       "FDECSTP",      LTYPE0, AFDECSTP,
-       "FINCSTP",      LTYPE0, AFINCSTP,
-       "FINIT",        LTYPE0, AFINIT,
-       "FLD1",         LTYPE0, AFLD1,
-       "FLDL2E",       LTYPE0, AFLDL2E,
-       "FLDL2T",       LTYPE0, AFLDL2T,
-       "FLDLG2",       LTYPE0, AFLDLG2,
-       "FLDLN2",       LTYPE0, AFLDLN2,
-       "FLDPI",        LTYPE0, AFLDPI,
-       "FLDZ",         LTYPE0, AFLDZ,
-       "FNOP",         LTYPE0, AFNOP,
-       "FPATAN",       LTYPE0, AFPATAN,
-       "FPREM",        LTYPE0, AFPREM,
-       "FPREM1",       LTYPE0, AFPREM1,
-       "FPTAN",        LTYPE0, AFPTAN,
-       "FRNDINT",      LTYPE0, AFRNDINT,
-       "FSCALE",       LTYPE0, AFSCALE,
-       "FSIN",         LTYPE0, AFSIN,
-       "FSINCOS",      LTYPE0, AFSINCOS,
-       "FSQRT",        LTYPE0, AFSQRT,
-       "FTST",         LTYPE0, AFTST,
-       "FXAM",         LTYPE0, AFXAM,
-       "FXTRACT",      LTYPE0, AFXTRACT,
-       "FYL2X",        LTYPE0, AFYL2X,
-       "FYL2XP1",      LTYPE0, AFYL2XP1,
-       "LFENCE",       LTYPE0, ALFENCE,
-       "MFENCE",       LTYPE0, AMFENCE,
-       "SFENCE",       LTYPE0, ASFENCE,
-       "EMMS",         LTYPE0, AEMMS,
-       "PREFETCHT0",           LTYPE2, APREFETCHT0,
-       "PREFETCHT1",           LTYPE2, APREFETCHT1,
-       "PREFETCHT2",           LTYPE2, APREFETCHT2,
-       "PREFETCHNTA",          LTYPE2, APREFETCHNTA,
-       "UNDEF",        LTYPE0, AUNDEF,
-
-       "ADDPD",        LTYPE3, AADDPD,
-       "ADDPS",        LTYPE3, AADDPS,
-       "ADDSD",        LTYPE3, AADDSD,
-       "ADDSS",        LTYPE3, AADDSS,
-       "AESENC",       LTYPE3, AAESENC,
-       "ANDNPD",       LTYPE3, AANDNPD,
-       "ANDNPS",       LTYPE3, AANDNPS,
-       "ANDPD",        LTYPE3, AANDPD,
-       "ANDPS",        LTYPE3, AANDPS,
-       "CMPPD",        LTYPEXC,ACMPPD,
-       "CMPPS",        LTYPEXC,ACMPPS,
-       "CMPSD",        LTYPEXC,ACMPSD,
-       "CMPSS",        LTYPEXC,ACMPSS,
-       "COMISD",       LTYPE3, ACOMISD,
-       "COMISS",       LTYPE3, ACOMISS,
-       "CVTPL2PD",     LTYPE3, ACVTPL2PD,
-       "CVTPL2PS",     LTYPE3, ACVTPL2PS,
-       "CVTPD2PL",     LTYPE3, ACVTPD2PL,
-       "CVTPD2PS",     LTYPE3, ACVTPD2PS,
-       "CVTPS2PL",     LTYPE3, ACVTPS2PL,
-       "CVTPS2PD",     LTYPE3, ACVTPS2PD,
-       "CVTSD2SL",     LTYPE3, ACVTSD2SL,
-       "CVTSD2SS",     LTYPE3, ACVTSD2SS,
-       "CVTSL2SD",     LTYPE3, ACVTSL2SD,
-       "CVTSL2SS",     LTYPE3, ACVTSL2SS,
-       "CVTSS2SD",     LTYPE3, ACVTSS2SD,
-       "CVTSS2SL",     LTYPE3, ACVTSS2SL,
-       "CVTTPD2PL",    LTYPE3, ACVTTPD2PL,
-       "CVTTPS2PL",    LTYPE3, ACVTTPS2PL,
-       "CVTTSD2SL",    LTYPE3, ACVTTSD2SL,
-       "CVTTSS2SL",    LTYPE3, ACVTTSS2SL,
-       "DIVPD",        LTYPE3, ADIVPD,
-       "DIVPS",        LTYPE3, ADIVPS,
-       "DIVSD",        LTYPE3, ADIVSD,
-       "DIVSS",        LTYPE3, ADIVSS,
-       "MASKMOVOU",    LTYPE3, AMASKMOVOU,
-       "MASKMOVDQU",   LTYPE3, AMASKMOVOU,     /* syn */
-       "MAXPD",        LTYPE3, AMAXPD,
-       "MAXPS",        LTYPE3, AMAXPS,
-       "MAXSD",        LTYPE3, AMAXSD,
-       "MAXSS",        LTYPE3, AMAXSS,
-       "MINPD",        LTYPE3, AMINPD,
-       "MINPS",        LTYPE3, AMINPS,
-       "MINSD",        LTYPE3, AMINSD,
-       "MINSS",        LTYPE3, AMINSS,
-       "MOVAPD",       LTYPE3, AMOVAPD,
-       "MOVAPS",       LTYPE3, AMOVAPS,
-       "MOVO",         LTYPE3, AMOVO,
-       "MOVOA",        LTYPE3, AMOVO,  /* syn */
-       "MOVOU",        LTYPE3, AMOVOU,
-       "MOVHLPS",      LTYPE3, AMOVHLPS,
-       "MOVHPD",       LTYPE3, AMOVHPD,
-       "MOVHPS",       LTYPE3, AMOVHPS,
-       "MOVLHPS",      LTYPE3, AMOVLHPS,
-       "MOVLPD",       LTYPE3, AMOVLPD,
-       "MOVLPS",       LTYPE3, AMOVLPS,
-       "MOVMSKPD",     LTYPE3, AMOVMSKPD,
-       "MOVMSKPS",     LTYPE3, AMOVMSKPS,
-       "MOVNTO",       LTYPE3, AMOVNTO,
-       "MOVNTDQ",      LTYPE3, AMOVNTO,        /* syn */
-       "MOVNTPD",      LTYPE3, AMOVNTPD,
-       "MOVNTPS",      LTYPE3, AMOVNTPS,
-       "MOVSD",        LTYPE3, AMOVSD,
-       "MOVSS",        LTYPE3, AMOVSS,
-       "MOVUPD",       LTYPE3, AMOVUPD,
-       "MOVUPS",       LTYPE3, AMOVUPS,
-       "MULPD",        LTYPE3, AMULPD,
-       "MULPS",        LTYPE3, AMULPS,
-       "MULSD",        LTYPE3, AMULSD,
-       "MULSS",        LTYPE3, AMULSS,
-       "ORPD",         LTYPE3, AORPD,
-       "ORPS",         LTYPE3, AORPS,
-       "PADDQ",        LTYPE3, APADDQ,
-       "PAND",         LTYPE3, APAND,
-       "PCMPEQB",      LTYPE3, APCMPEQB,
-       "PMAXSW",       LTYPE3, APMAXSW,
-       "PMAXUB",       LTYPE3, APMAXUB,
-       "PMINSW",       LTYPE3, APMINSW,
-       "PMINUB",       LTYPE3, APMINUB,
-       "PMOVMSKB",     LTYPE3, APMOVMSKB,
-       "PSADBW",       LTYPE3, APSADBW,
-       "PSHUFB",       LTYPE3, APSHUFB,
-       "PSHUFHW",      LTYPEX, APSHUFHW,
-       "PSHUFL",       LTYPEX, APSHUFL,
-       "PSHUFLW",      LTYPEX, APSHUFLW,
-       "PSUBB",        LTYPE3, APSUBB,
-       "PSUBL",        LTYPE3, APSUBL,
-       "PSUBQ",        LTYPE3, APSUBQ,
-       "PSUBSB",       LTYPE3, APSUBSB,
-       "PSUBSW",       LTYPE3, APSUBSW,
-       "PSUBUSB",      LTYPE3, APSUBUSB,
-       "PSUBUSW",      LTYPE3, APSUBUSW,
-       "PSUBW",        LTYPE3, APSUBW,
-       "PUNPCKHQDQ",   LTYPE3, APUNPCKHQDQ,
-       "PUNPCKLQDQ",   LTYPE3, APUNPCKLQDQ,
-       "PXOR",         LTYPE3, APXOR,
-       "RCPPS",        LTYPE3, ARCPPS,
-       "RCPSS",        LTYPE3, ARCPSS,
-       "RSQRTPS",      LTYPE3, ARSQRTPS,
-       "RSQRTSS",      LTYPE3, ARSQRTSS,
-       "SQRTPD",       LTYPE3, ASQRTPD,
-       "SQRTPS",       LTYPE3, ASQRTPS,
-       "SQRTSD",       LTYPE3, ASQRTSD,
-       "SQRTSS",       LTYPE3, ASQRTSS,
-       "SUBPD",        LTYPE3, ASUBPD,
-       "SUBPS",        LTYPE3, ASUBPS,
-       "SUBSD",        LTYPE3, ASUBSD,
-       "SUBSS",        LTYPE3, ASUBSS,
-       "UCOMISD",      LTYPE3, AUCOMISD,
-       "UCOMISS",      LTYPE3, AUCOMISS,
-       "UNPCKHPD",     LTYPE3, AUNPCKHPD,
-       "UNPCKHPS",     LTYPE3, AUNPCKHPS,
-       "UNPCKLPD",     LTYPE3, AUNPCKLPD,
-       "UNPCKLPS",     LTYPE3, AUNPCKLPS,
-       "XORPD",        LTYPE3, AXORPD,
-       "XORPS",        LTYPE3, AXORPS,
-       "USEFIELD",     LTYPEN, AUSEFIELD,
-       "PCDATA",       LTYPEPC,        APCDATA,
-       "FUNCDATA",     LTYPEF, AFUNCDATA,
-       0
-};
-
-void
-cinit(void)
-{
-       Sym *s;
-       int i;
-
-       nullgen.type = TYPE_NONE;
-       nullgen.index = TYPE_NONE;
-
-       nerrors = 0;
-       iostack = I;
-       iofree = I;
-       peekc = IGN;
-       nhunk = 0;
-       for(i=0; i<NHASH; i++)
-               hash[i] = S;
-       for(i=0; itab[i].name; i++) {
-               s = slookup(itab[i].name);
-               if(s->type != LNAME)
-                       yyerror("double initialization %s", itab[i].name);
-               s->type = itab[i].type;
-               s->value = itab[i].value;
-       }
-}
-
-void
-checkscale(int scale)
-{
-
-       switch(scale) {
-       case 1:
-       case 2:
-       case 4:
-       case 8:
-               return;
-       }
-       yyerror("scale must be 1248: %d", scale);
-}
-
-void
-syminit(Sym *s)
-{
-
-       s->type = LNAME;
-       s->value = 0;
-}
-
-void
-cclean(void)
-{
-       Addr2 g2;
-
-       g2.from = nullgen;
-       g2.to = nullgen;
-       outcode(AEND, &g2);
-}
-
-void
-outcode(int a, Addr2 *g2)
-{
-       Prog *p;
-       Plist *pl;
-       
-       if(pass == 1)
-               goto out;
-
-       p = malloc(sizeof *p);
-       memset(p, 0, sizeof *p);
-       p->as = a;
-       p->lineno = stmtline;
-       p->from = g2->from;
-       p->to = g2->to;
-       p->pc = pc;
-
-       if(lastpc == nil) {
-               pl = linknewplist(ctxt);
-               pl->firstpc = p;
-       } else
-               lastpc->link = p;
-       lastpc = p;     
-
-out:
-       if(a != AGLOBL && a != ADATA)
-               pc++;
-}
-
-#include "../cc/lexbody"
-#include "../cc/macbody"
similarity index 100%
rename from src/cmd/new8a/lex.go
rename to src/cmd/8a/lex.go
similarity index 100%
rename from src/cmd/new8a/y.go
rename to src/cmd/8a/y.go
diff --git a/src/cmd/8a/y.tab.c b/src/cmd/8a/y.tab.c
deleted file mode 100644 (file)
index d80f0ee..0000000
+++ /dev/null
@@ -1,2778 +0,0 @@
-/* A Bison parser, made by GNU Bison 2.3.  */
-
-/* Skeleton implementation for Bison's Yacc-like parsers in C
-
-   Copyright (C) 1984, 1989, 1990, 2000, 2001, 2002, 2003, 2004, 2005, 2006
-   Free Software Foundation, Inc.
-
-   This program is free software; you can redistribute it and/or modify
-   it under the terms of the GNU General Public License as published by
-   the Free Software Foundation; either version 2, or (at your option)
-   any later version.
-
-   This program is distributed in the hope that it will be useful,
-   but WITHOUT ANY WARRANTY; without even the implied warranty of
-   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-   GNU General Public License for more details.
-
-   You should have received a copy of the GNU General Public License
-   along with this program; if not, write to the Free Software
-   Foundation, Inc., 51 Franklin Street, Fifth Floor,
-   Boston, MA 02110-1301, USA.  */
-
-/* As a special exception, you may create a larger work that contains
-   part or all of the Bison parser skeleton and distribute that work
-   under terms of your choice, so long as that work isn't itself a
-   parser generator using the skeleton or a modified version thereof
-   as a parser skeleton.  Alternatively, if you modify or redistribute
-   the parser skeleton itself, you may (at your option) remove this
-   special exception, which will cause the skeleton and the resulting
-   Bison output files to be licensed under the GNU General Public
-   License without this special exception.
-
-   This special exception was added by the Free Software Foundation in
-   version 2.2 of Bison.  */
-
-/* C LALR(1) parser skeleton written by Richard Stallman, by
-   simplifying the original so-called "semantic" parser.  */
-
-/* All symbols defined below should begin with yy or YY, to avoid
-   infringing on user name space.  This should be done even for local
-   variables, as they might otherwise be expanded by user macros.
-   There are some unavoidable exceptions within include files to
-   define necessary library symbols; they are noted "INFRINGES ON
-   USER NAME SPACE" below.  */
-
-/* Identify Bison output.  */
-#define YYBISON 1
-
-/* Bison version.  */
-#define YYBISON_VERSION "2.3"
-
-/* Skeleton name.  */
-#define YYSKELETON_NAME "yacc.c"
-
-/* Pure parsers.  */
-#define YYPURE 0
-
-/* Using locations.  */
-#define YYLSP_NEEDED 0
-
-
-
-/* Tokens.  */
-#ifndef YYTOKENTYPE
-# define YYTOKENTYPE
-   /* Put the tokens into the symbol table, so that GDB and other debuggers
-      know about them.  */
-   enum yytokentype {
-     LTYPE0 = 258,
-     LTYPE1 = 259,
-     LTYPE2 = 260,
-     LTYPE3 = 261,
-     LTYPE4 = 262,
-     LTYPEC = 263,
-     LTYPED = 264,
-     LTYPEN = 265,
-     LTYPER = 266,
-     LTYPET = 267,
-     LTYPES = 268,
-     LTYPEM = 269,
-     LTYPEI = 270,
-     LTYPEG = 271,
-     LTYPEXC = 272,
-     LTYPEX = 273,
-     LTYPEPC = 274,
-     LTYPEF = 275,
-     LCONST = 276,
-     LFP = 277,
-     LPC = 278,
-     LSB = 279,
-     LBREG = 280,
-     LLREG = 281,
-     LSREG = 282,
-     LFREG = 283,
-     LXREG = 284,
-     LFCONST = 285,
-     LSCONST = 286,
-     LSP = 287,
-     LNAME = 288,
-     LLAB = 289,
-     LVAR = 290
-   };
-#endif
-/* Tokens.  */
-#define LTYPE0 258
-#define LTYPE1 259
-#define LTYPE2 260
-#define LTYPE3 261
-#define LTYPE4 262
-#define LTYPEC 263
-#define LTYPED 264
-#define LTYPEN 265
-#define LTYPER 266
-#define LTYPET 267
-#define LTYPES 268
-#define LTYPEM 269
-#define LTYPEI 270
-#define LTYPEG 271
-#define LTYPEXC 272
-#define LTYPEX 273
-#define LTYPEPC 274
-#define LTYPEF 275
-#define LCONST 276
-#define LFP 277
-#define LPC 278
-#define LSB 279
-#define LBREG 280
-#define LLREG 281
-#define LSREG 282
-#define LFREG 283
-#define LXREG 284
-#define LFCONST 285
-#define LSCONST 286
-#define LSP 287
-#define LNAME 288
-#define LLAB 289
-#define LVAR 290
-
-
-
-
-/* Copy the first part of user declarations.  */
-#line 31 "a.y"
-
-#include <u.h>
-#include <stdio.h>     /* if we don't, bison will, and a.h re-#defines getc */
-#include <libc.h>
-#include "a.h"
-#include "../../runtime/funcdata.h"
-
-
-/* Enabling traces.  */
-#ifndef YYDEBUG
-# define YYDEBUG 0
-#endif
-
-/* Enabling verbose error messages.  */
-#ifdef YYERROR_VERBOSE
-# undef YYERROR_VERBOSE
-# define YYERROR_VERBOSE 1
-#else
-# define YYERROR_VERBOSE 0
-#endif
-
-/* Enabling the token table.  */
-#ifndef YYTOKEN_TABLE
-# define YYTOKEN_TABLE 0
-#endif
-
-#if ! defined YYSTYPE && ! defined YYSTYPE_IS_DECLARED
-typedef union YYSTYPE
-#line 38 "a.y"
-{
-       Sym     *sym;
-       int32   lval;
-       double  dval;
-       char    sval[8];
-       Addr    addr;
-       Addr2   addr2;
-}
-/* Line 193 of yacc.c.  */
-#line 183 "y.tab.c"
-       YYSTYPE;
-# define yystype YYSTYPE /* obsolescent; will be withdrawn */
-# define YYSTYPE_IS_DECLARED 1
-# define YYSTYPE_IS_TRIVIAL 1
-#endif
-
-
-
-/* Copy the second part of user declarations.  */
-
-
-/* Line 216 of yacc.c.  */
-#line 196 "y.tab.c"
-
-#ifdef short
-# undef short
-#endif
-
-#ifdef YYTYPE_UINT8
-typedef YYTYPE_UINT8 yytype_uint8;
-#else
-typedef unsigned char yytype_uint8;
-#endif
-
-#ifdef YYTYPE_INT8
-typedef YYTYPE_INT8 yytype_int8;
-#elif (defined __STDC__ || defined __C99__FUNC__ \
-     || defined __cplusplus || defined _MSC_VER)
-typedef signed char yytype_int8;
-#else
-typedef short int yytype_int8;
-#endif
-
-#ifdef YYTYPE_UINT16
-typedef YYTYPE_UINT16 yytype_uint16;
-#else
-typedef unsigned short int yytype_uint16;
-#endif
-
-#ifdef YYTYPE_INT16
-typedef YYTYPE_INT16 yytype_int16;
-#else
-typedef short int yytype_int16;
-#endif
-
-#ifndef YYSIZE_T
-# ifdef __SIZE_TYPE__
-#  define YYSIZE_T __SIZE_TYPE__
-# elif defined size_t
-#  define YYSIZE_T size_t
-# elif ! defined YYSIZE_T && (defined __STDC__ || defined __C99__FUNC__ \
-     || defined __cplusplus || defined _MSC_VER)
-#  include <stddef.h> /* INFRINGES ON USER NAME SPACE */
-#  define YYSIZE_T size_t
-# else
-#  define YYSIZE_T unsigned int
-# endif
-#endif
-
-#define YYSIZE_MAXIMUM ((YYSIZE_T) -1)
-
-#ifndef YY_
-# if defined YYENABLE_NLS && YYENABLE_NLS
-#  if ENABLE_NLS
-#   include <libintl.h> /* INFRINGES ON USER NAME SPACE */
-#   define YY_(msgid) dgettext ("bison-runtime", msgid)
-#  endif
-# endif
-# ifndef YY_
-#  define YY_(msgid) msgid
-# endif
-#endif
-
-/* Suppress unused-variable warnings by "using" E.  */
-#if ! defined lint || defined __GNUC__
-# define YYUSE(e) ((void) (e))
-#else
-# define YYUSE(e) /* empty */
-#endif
-
-/* Identity function, used to suppress warnings about constant conditions.  */
-#ifndef lint
-# define YYID(n) (n)
-#else
-#if (defined __STDC__ || defined __C99__FUNC__ \
-     || defined __cplusplus || defined _MSC_VER)
-static int
-YYID (int i)
-#else
-static int
-YYID (i)
-    int i;
-#endif
-{
-  return i;
-}
-#endif
-
-#if ! defined yyoverflow || YYERROR_VERBOSE
-
-/* The parser invokes alloca or malloc; define the necessary symbols.  */
-
-# ifdef YYSTACK_USE_ALLOCA
-#  if YYSTACK_USE_ALLOCA
-#   ifdef __GNUC__
-#    define YYSTACK_ALLOC __builtin_alloca
-#   elif defined __BUILTIN_VA_ARG_INCR
-#    include <alloca.h> /* INFRINGES ON USER NAME SPACE */
-#   elif defined _AIX
-#    define YYSTACK_ALLOC __alloca
-#   elif defined _MSC_VER
-#    include <malloc.h> /* INFRINGES ON USER NAME SPACE */
-#    define alloca _alloca
-#   else
-#    define YYSTACK_ALLOC alloca
-#    if ! defined _ALLOCA_H && ! defined _STDLIB_H && (defined __STDC__ || defined __C99__FUNC__ \
-     || defined __cplusplus || defined _MSC_VER)
-#     include <stdlib.h> /* INFRINGES ON USER NAME SPACE */
-#     ifndef _STDLIB_H
-#      define _STDLIB_H 1
-#     endif
-#    endif
-#   endif
-#  endif
-# endif
-
-# ifdef YYSTACK_ALLOC
-   /* Pacify GCC's `empty if-body' warning.  */
-#  define YYSTACK_FREE(Ptr) do { /* empty */; } while (YYID (0))
-#  ifndef YYSTACK_ALLOC_MAXIMUM
-    /* The OS might guarantee only one guard page at the bottom of the stack,
-       and a page size can be as small as 4096 bytes.  So we cannot safely
-       invoke alloca (N) if N exceeds 4096.  Use a slightly smaller number
-       to allow for a few compiler-allocated temporary stack slots.  */
-#   define YYSTACK_ALLOC_MAXIMUM 4032 /* reasonable circa 2006 */
-#  endif
-# else
-#  define YYSTACK_ALLOC YYMALLOC
-#  define YYSTACK_FREE YYFREE
-#  ifndef YYSTACK_ALLOC_MAXIMUM
-#   define YYSTACK_ALLOC_MAXIMUM YYSIZE_MAXIMUM
-#  endif
-#  if (defined __cplusplus && ! defined _STDLIB_H \
-       && ! ((defined YYMALLOC || defined malloc) \
-            && (defined YYFREE || defined free)))
-#   include <stdlib.h> /* INFRINGES ON USER NAME SPACE */
-#   ifndef _STDLIB_H
-#    define _STDLIB_H 1
-#   endif
-#  endif
-#  ifndef YYMALLOC
-#   define YYMALLOC malloc
-#   if ! defined malloc && ! defined _STDLIB_H && (defined __STDC__ || defined __C99__FUNC__ \
-     || defined __cplusplus || defined _MSC_VER)
-void *malloc (YYSIZE_T); /* INFRINGES ON USER NAME SPACE */
-#   endif
-#  endif
-#  ifndef YYFREE
-#   define YYFREE free
-#   if ! defined free && ! defined _STDLIB_H && (defined __STDC__ || defined __C99__FUNC__ \
-     || defined __cplusplus || defined _MSC_VER)
-void free (void *); /* INFRINGES ON USER NAME SPACE */
-#   endif
-#  endif
-# endif
-#endif /* ! defined yyoverflow || YYERROR_VERBOSE */
-
-
-#if (! defined yyoverflow \
-     && (! defined __cplusplus \
-        || (defined YYSTYPE_IS_TRIVIAL && YYSTYPE_IS_TRIVIAL)))
-
-/* A type that is properly aligned for any stack member.  */
-union yyalloc
-{
-  yytype_int16 yyss;
-  YYSTYPE yyvs;
-  };
-
-/* The size of the maximum gap between one aligned stack and the next.  */
-# define YYSTACK_GAP_MAXIMUM (sizeof (union yyalloc) - 1)
-
-/* The size of an array large to enough to hold all stacks, each with
-   N elements.  */
-# define YYSTACK_BYTES(N) \
-     ((N) * (sizeof (yytype_int16) + sizeof (YYSTYPE)) \
-      + YYSTACK_GAP_MAXIMUM)
-
-/* Copy COUNT objects from FROM to TO.  The source and destination do
-   not overlap.  */
-# ifndef YYCOPY
-#  if defined __GNUC__ && 1 < __GNUC__
-#   define YYCOPY(To, From, Count) \
-      __builtin_memcpy (To, From, (Count) * sizeof (*(From)))
-#  else
-#   define YYCOPY(To, From, Count)             \
-      do                                       \
-       {                                       \
-         YYSIZE_T yyi;                         \
-         for (yyi = 0; yyi < (Count); yyi++)   \
-           (To)[yyi] = (From)[yyi];            \
-       }                                       \
-      while (YYID (0))
-#  endif
-# endif
-
-/* Relocate STACK from its old location to the new one.  The
-   local variables YYSIZE and YYSTACKSIZE give the old and new number of
-   elements in the stack, and YYPTR gives the new location of the
-   stack.  Advance YYPTR to a properly aligned location for the next
-   stack.  */
-# define YYSTACK_RELOCATE(Stack)                                       \
-    do                                                                 \
-      {                                                                        \
-       YYSIZE_T yynewbytes;                                            \
-       YYCOPY (&yyptr->Stack, Stack, yysize);                          \
-       Stack = &yyptr->Stack;                                          \
-       yynewbytes = yystacksize * sizeof (*Stack) + YYSTACK_GAP_MAXIMUM; \
-       yyptr += yynewbytes / sizeof (*yyptr);                          \
-      }                                                                        \
-    while (YYID (0))
-
-#endif
-
-/* YYFINAL -- State number of the termination state.  */
-#define YYFINAL  2
-/* YYLAST -- Last index in YYTABLE.  */
-#define YYLAST   544
-
-/* YYNTOKENS -- Number of terminals.  */
-#define YYNTOKENS  54
-/* YYNNTS -- Number of nonterminals.  */
-#define YYNNTS  39
-/* YYNRULES -- Number of rules.  */
-#define YYNRULES  131
-/* YYNRULES -- Number of states.  */
-#define YYNSTATES  270
-
-/* YYTRANSLATE(YYLEX) -- Bison symbol number corresponding to YYLEX.  */
-#define YYUNDEFTOK  2
-#define YYMAXUTOK   290
-
-#define YYTRANSLATE(YYX)                                               \
-  ((unsigned int) (YYX) <= YYMAXUTOK ? yytranslate[YYX] : YYUNDEFTOK)
-
-/* YYTRANSLATE[YYLEX] -- Bison symbol number corresponding to YYLEX.  */
-static const yytype_uint8 yytranslate[] =
-{
-       0,     2,     2,     2,     2,     2,     2,     2,     2,     2,
-       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
-       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
-       2,     2,     2,     2,     2,     2,    50,    12,     5,     2,
-      51,    52,    10,     8,    49,     9,     2,    11,     2,     2,
-       2,     2,     2,     2,     2,     2,     2,     2,    46,    47,
-       6,    48,     7,     2,     2,     2,     2,     2,     2,     2,
-       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
-       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
-       2,     2,     2,     2,     4,     2,     2,     2,     2,     2,
-       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
-       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
-       2,     2,     2,     2,     3,     2,    53,     2,     2,     2,
-       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
-       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
-       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
-       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
-       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
-       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
-       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
-       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
-       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
-       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
-       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
-       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
-       2,     2,     2,     2,     2,     2,     1,     2,    13,    14,
-      15,    16,    17,    18,    19,    20,    21,    22,    23,    24,
-      25,    26,    27,    28,    29,    30,    31,    32,    33,    34,
-      35,    36,    37,    38,    39,    40,    41,    42,    43,    44,
-      45
-};
-
-#if YYDEBUG
-/* YYPRHS[YYN] -- Index of the first RHS symbol of rule number YYN in
-   YYRHS.  */
-static const yytype_uint16 yyprhs[] =
-{
-       0,     0,     3,     4,     5,     9,    10,    15,    17,    20,
-      23,    27,    31,    34,    37,    40,    43,    46,    49,    51,
-      53,    56,    59,    62,    65,    68,    70,    73,    76,    79,
-      82,    83,    85,    89,    93,    96,    98,   101,   103,   106,
-     108,   112,   119,   125,   133,   138,   145,   148,   150,   153,
-     155,   157,   161,   167,   171,   177,   180,   182,   186,   192,
-     198,   202,   206,   208,   210,   212,   214,   217,   220,   222,
-     224,   226,   228,   230,   235,   238,   240,   242,   244,   246,
-     248,   250,   253,   256,   259,   262,   267,   273,   277,   279,
-     282,   286,   291,   293,   295,   297,   302,   307,   314,   324,
-     334,   338,   342,   347,   353,   362,   364,   371,   377,   385,
-     386,   389,   392,   394,   396,   398,   400,   402,   405,   408,
-     411,   415,   417,   421,   425,   429,   433,   437,   442,   447,
-     451,   455
-};
-
-/* YYRHS -- A `-1'-separated list of the rules' RHS.  */
-static const yytype_int8 yyrhs[] =
-{
-      55,     0,    -1,    -1,    -1,    55,    56,    57,    -1,    -1,
-      43,    46,    58,    57,    -1,    47,    -1,    59,    47,    -1,
-       1,    47,    -1,    43,    48,    92,    -1,    45,    48,    92,
-      -1,    13,    60,    -1,    14,    64,    -1,    15,    63,    -1,
-      16,    61,    -1,    17,    62,    -1,    21,    65,    -1,    66,
-      -1,    67,    -1,    18,    69,    -1,    20,    70,    -1,    23,
-      71,    -1,    24,    72,    -1,    25,    73,    -1,    68,    -1,
-      27,    74,    -1,    28,    75,    -1,    29,    76,    -1,    30,
-      77,    -1,    -1,    49,    -1,    80,    49,    78,    -1,    78,
-      49,    80,    -1,    80,    49,    -1,    80,    -1,    49,    78,
-      -1,    78,    -1,    49,    81,    -1,    81,    -1,    83,    49,
-      81,    -1,    19,    88,    11,    91,    49,    83,    -1,    22,
-      85,    49,    50,    84,    -1,    22,    85,    49,    91,    49,
-      50,    84,    -1,    26,    85,    49,    83,    -1,    26,    85,
-      49,    91,    49,    83,    -1,    49,    79,    -1,    79,    -1,
-      10,    88,    -1,    60,    -1,    64,    -1,    80,    49,    78,
-      -1,    80,    49,    78,    46,    36,    -1,    80,    49,    78,
-      -1,    80,    49,    78,    46,    37,    -1,    80,    49,    -1,
-      80,    -1,    80,    49,    78,    -1,    82,    49,    78,    49,
-      91,    -1,    83,    49,    78,    49,    82,    -1,    80,    49,
-      80,    -1,    80,    49,    80,    -1,    82,    -1,    85,    -1,
-      81,    -1,    87,    -1,    10,    82,    -1,    10,    86,    -1,
-      82,    -1,    86,    -1,    83,    -1,    78,    -1,    83,    -1,
-      91,    51,    33,    52,    -1,    43,    89,    -1,    35,    -1,
-      38,    -1,    36,    -1,    39,    -1,    42,    -1,    37,    -1,
-      50,    91,    -1,    50,    88,    -1,    50,    41,    -1,    50,
-      40,    -1,    50,    51,    40,    52,    -1,    50,    51,     9,
-      40,    52,    -1,    50,     9,    40,    -1,    31,    -1,     9,
-      31,    -1,    31,     9,    31,    -1,     9,    31,     9,    31,
-      -1,    86,    -1,    87,    -1,    91,    -1,    91,    51,    36,
-      52,    -1,    91,    51,    42,    52,    -1,    91,    51,    36,
-      10,    91,    52,    -1,    91,    51,    36,    52,    51,    36,
-      10,    91,    52,    -1,    91,    51,    36,    52,    51,    37,
-      10,    91,    52,    -1,    51,    36,    52,    -1,    51,    42,
-      52,    -1,    91,    51,    37,    52,    -1,    51,    36,    10,
-      91,    52,    -1,    51,    36,    52,    51,    36,    10,    91,
-      52,    -1,    88,    -1,    88,    51,    36,    10,    91,    52,
-      -1,    43,    89,    51,    90,    52,    -1,    43,     6,     7,
-      89,    51,    34,    52,    -1,    -1,     8,    91,    -1,     9,
-      91,    -1,    34,    -1,    42,    -1,    32,    -1,    31,    -1,
-      45,    -1,     9,    91,    -1,     8,    91,    -1,    53,    91,
-      -1,    51,    92,    52,    -1,    91,    -1,    92,     8,    92,
-      -1,    92,     9,    92,    -1,    92,    10,    92,    -1,    92,
-      11,    92,    -1,    92,    12,    92,    -1,    92,     6,     6,
-      92,    -1,    92,     7,     7,    92,    -1,    92,     5,    92,
-      -1,    92,     4,    92,    -1,    92,     3,    92,    -1
-};
-
-/* YYRLINE[YYN] -- source line where rule number YYN was defined.  */
-static const yytype_uint16 yyrline[] =
-{
-       0,    64,    64,    66,    65,    73,    72,    81,    82,    83,
-      86,    91,    97,    98,    99,   100,   101,   102,   103,   104,
-     105,   106,   107,   108,   109,   110,   111,   112,   113,   114,
-     117,   121,   128,   135,   142,   147,   154,   159,   166,   171,
-     176,   183,   196,   204,   218,   226,   240,   245,   250,   258,
-     259,   262,   267,   277,   282,   292,   297,   302,   309,   317,
-     327,   336,   347,   348,   351,   352,   353,   357,   361,   362,
-     363,   366,   367,   370,   376,   387,   393,   399,   405,   411,
-     417,   425,   431,   441,   447,   453,   459,   465,   473,   480,
-     487,   494,   503,   504,   507,   514,   521,   528,   538,   548,
-     558,   564,   570,   577,   586,   597,   601,   610,   618,   628,
-     631,   635,   641,   642,   646,   649,   650,   654,   658,   662,
-     666,   672,   673,   677,   681,   685,   689,   693,   697,   701,
-     705,   709
-};
-#endif
-
-#if YYDEBUG || YYERROR_VERBOSE || YYTOKEN_TABLE
-/* YYTNAME[SYMBOL-NUM] -- String name of the symbol SYMBOL-NUM.
-   First, the terminals, then, starting at YYNTOKENS, nonterminals.  */
-static const char *const yytname[] =
-{
-  "$end", "error", "$undefined", "'|'", "'^'", "'&'", "'<'", "'>'", "'+'",
-  "'-'", "'*'", "'/'", "'%'", "LTYPE0", "LTYPE1", "LTYPE2", "LTYPE3",
-  "LTYPE4", "LTYPEC", "LTYPED", "LTYPEN", "LTYPER", "LTYPET", "LTYPES",
-  "LTYPEM", "LTYPEI", "LTYPEG", "LTYPEXC", "LTYPEX", "LTYPEPC", "LTYPEF",
-  "LCONST", "LFP", "LPC", "LSB", "LBREG", "LLREG", "LSREG", "LFREG",
-  "LXREG", "LFCONST", "LSCONST", "LSP", "LNAME", "LLAB", "LVAR", "':'",
-  "';'", "'='", "','", "'$'", "'('", "')'", "'~'", "$accept", "prog", "@1",
-  "line", "@2", "inst", "nonnon", "rimrem", "remrim", "rimnon", "nonrem",
-  "nonrel", "spec1", "spec2", "spec8", "spec3", "spec4", "spec5", "spec6",
-  "spec7", "spec9", "spec10", "spec11", "spec12", "rem", "rom", "rim",
-  "rel", "reg", "imm", "textsize", "mem", "omem", "nmem", "nam", "offset",
-  "pointer", "con", "expr", 0
-};
-#endif
-
-# ifdef YYPRINT
-/* YYTOKNUM[YYLEX-NUM] -- Internal token number corresponding to
-   token YYLEX-NUM.  */
-static const yytype_uint16 yytoknum[] =
-{
-       0,   256,   257,   124,    94,    38,    60,    62,    43,    45,
-      42,    47,    37,   258,   259,   260,   261,   262,   263,   264,
-     265,   266,   267,   268,   269,   270,   271,   272,   273,   274,
-     275,   276,   277,   278,   279,   280,   281,   282,   283,   284,
-     285,   286,   287,   288,   289,   290,    58,    59,    61,    44,
-      36,    40,    41,   126
-};
-# endif
-
-/* YYR1[YYN] -- Symbol number of symbol that rule YYN derives.  */
-static const yytype_uint8 yyr1[] =
-{
-       0,    54,    55,    56,    55,    58,    57,    57,    57,    57,
-      59,    59,    59,    59,    59,    59,    59,    59,    59,    59,
-      59,    59,    59,    59,    59,    59,    59,    59,    59,    59,
-      60,    60,    61,    62,    63,    63,    64,    64,    65,    65,
-      65,    66,    67,    67,    68,    68,    69,    69,    69,    70,
-      70,    71,    71,    72,    72,    73,    73,    73,    74,    75,
-      76,    77,    78,    78,    79,    79,    79,    79,    79,    79,
-      79,    80,    80,    81,    81,    82,    82,    82,    82,    82,
-      82,    83,    83,    83,    83,    83,    83,    83,    84,    84,
-      84,    84,    85,    85,    86,    86,    86,    86,    86,    86,
-      86,    86,    86,    86,    86,    87,    87,    88,    88,    89,
-      89,    89,    90,    90,    90,    91,    91,    91,    91,    91,
-      91,    92,    92,    92,    92,    92,    92,    92,    92,    92,
-      92,    92
-};
-
-/* YYR2[YYN] -- Number of symbols composing right hand side of rule YYN.  */
-static const yytype_uint8 yyr2[] =
-{
-       0,     2,     0,     0,     3,     0,     4,     1,     2,     2,
-       3,     3,     2,     2,     2,     2,     2,     2,     1,     1,
-       2,     2,     2,     2,     2,     1,     2,     2,     2,     2,
-       0,     1,     3,     3,     2,     1,     2,     1,     2,     1,
-       3,     6,     5,     7,     4,     6,     2,     1,     2,     1,
-       1,     3,     5,     3,     5,     2,     1,     3,     5,     5,
-       3,     3,     1,     1,     1,     1,     2,     2,     1,     1,
-       1,     1,     1,     4,     2,     1,     1,     1,     1,     1,
-       1,     2,     2,     2,     2,     4,     5,     3,     1,     2,
-       3,     4,     1,     1,     1,     4,     4,     6,     9,     9,
-       3,     3,     4,     5,     8,     1,     6,     5,     7,     0,
-       2,     2,     1,     1,     1,     1,     1,     2,     2,     2,
-       3,     1,     3,     3,     3,     3,     3,     4,     4,     3,
-       3,     3
-};
-
-/* YYDEFACT[STATE-NAME] -- Default rule to reduce with in state
-   STATE-NUM when YYTABLE doesn't specify something else to do.  Zero
-   means the default is an error.  */
-static const yytype_uint8 yydefact[] =
-{
-       2,     3,     1,     0,     0,    30,     0,     0,     0,     0,
-       0,     0,    30,     0,     0,     0,     0,     0,     0,     0,
-       0,     0,     0,     0,     0,     7,     4,     0,    18,    19,
-      25,     9,    31,    12,     0,     0,   115,    75,    77,    80,
-      76,    78,    79,   109,   116,     0,     0,     0,    13,    37,
-      62,    63,    92,    93,   105,    94,     0,    14,    71,    35,
-      72,    15,     0,    16,     0,     0,   109,     0,    20,    47,
-      64,    68,    70,    69,    65,    94,     0,    31,    49,    50,
-      21,   109,     0,     0,    17,    39,     0,     0,     0,    22,
-       0,    23,     0,    24,    56,     0,    26,     0,    27,     0,
-      28,     0,    29,     0,     5,     0,     0,     8,   118,   117,
-       0,     0,     0,     0,    36,     0,     0,   121,     0,   119,
-       0,     0,     0,    84,    83,     0,    82,    81,    34,     0,
-       0,    66,    67,    48,    74,     0,    46,     0,     0,    74,
-      38,     0,     0,     0,     0,     0,    55,     0,     0,     0,
-       0,     0,     0,    10,    11,   109,   110,   111,     0,     0,
-     100,   101,     0,     0,     0,     0,     0,     0,     0,     0,
-       0,     0,   120,     0,     0,     0,     0,    87,     0,     0,
-      32,    33,     0,     0,    40,     0,     0,    51,    53,    57,
-      44,     0,     0,     0,    60,    61,     6,     0,   114,   112,
-     113,     0,     0,     0,   131,   130,   129,     0,     0,   122,
-     123,   124,   125,   126,     0,     0,    95,   102,    96,     0,
-      85,    73,     0,     0,    88,    42,     0,     0,     0,     0,
-       0,     0,     0,   107,   103,     0,   127,   128,     0,     0,
-       0,    86,    41,    89,     0,     0,    52,    54,    45,    58,
-      59,     0,     0,   106,    97,     0,     0,     0,    90,    43,
-     108,     0,     0,     0,    91,   104,     0,     0,    98,    99
-};
-
-/* YYDEFGOTO[NTERM-NUM].  */
-static const yytype_int16 yydefgoto[] =
-{
-      -1,     1,     3,    26,   152,    27,    33,    61,    63,    57,
-      48,    84,    28,    29,    30,    68,    80,    89,    91,    93,
-      96,    98,   100,   102,    58,    69,    59,    70,    50,    60,
-     225,    51,    52,    53,    54,   113,   201,    55,   118
-};
-
-/* YYPACT[STATE-NUM] -- Index in YYTABLE of the portion describing
-   STATE-NUM.  */
-#define YYPACT_NINF -87
-static const yytype_int16 yypact[] =
-{
-     -87,    35,   -87,   242,     2,    -4,   164,   313,   313,   361,
-     265,     8,   337,    60,   410,   313,   313,   313,   410,   241,
-     -11,   313,   313,   -31,    17,   -87,   -87,    23,   -87,   -87,
-     -87,   -87,   -87,   -87,   474,   474,   -87,   -87,   -87,   -87,
-     -87,   -87,   -87,    20,   -87,   361,   401,   474,   -87,   -87,
-     -87,   -87,   -87,   -87,    16,    28,   185,   -87,   -87,    22,
-     -87,   -87,    25,   -87,    31,   361,    20,   289,   -87,   -87,
-     -87,   -87,   -87,   -87,   -87,    48,    29,   361,   -87,   -87,
-     -87,    13,   417,   474,   -87,   -87,    51,    53,    57,   -87,
-      58,   -87,    59,   -87,    70,    71,   -87,    75,   -87,    80,
-     -87,    86,   -87,   102,   -87,   474,   474,   -87,   -87,   -87,
-      37,   474,   474,    76,   -87,     1,   103,   -87,   175,   -87,
-     126,    50,    85,   -87,   -87,   426,   -87,   -87,   -87,   361,
-     313,   -87,   -87,   -87,    76,   385,   -87,    81,   474,   -87,
-     -87,   417,   130,   436,   361,   361,   361,   464,   361,   361,
-     313,   313,   242,   525,   525,    13,   -87,   -87,    18,   474,
-     113,   -87,   474,   474,   474,   165,   167,   474,   474,   474,
-     474,   474,   -87,   186,     3,   123,   156,   -87,   467,   158,
-     -87,   -87,   159,   163,   -87,     7,   169,   173,   177,   -87,
-     -87,   182,   183,   184,   -87,   -87,   -87,   178,   -87,   -87,
-     -87,   172,   187,   198,   136,   239,   532,   474,   474,    78,
-      78,   -87,   -87,   -87,   474,   474,   189,   -87,   -87,   202,
-     -87,   -87,   -11,   204,   228,   -87,   191,   245,   247,   -11,
-     474,   241,   248,   -87,   -87,   276,   180,   180,   236,   238,
-      -5,   -87,   -87,   282,   261,     7,   -87,   -87,   -87,   -87,
-     -87,   243,   474,   -87,   -87,   283,   284,   274,   -87,   -87,
-     -87,   254,   474,   474,   -87,   -87,   257,   259,   -87,   -87
-};
-
-/* YYPGOTO[NTERM-NUM].  */
-static const yytype_int16 yypgoto[] =
-{
-     -87,   -87,   -87,   160,   -87,   -87,   301,   -87,   -87,   -87,
-     305,   -87,   -87,   -87,   -87,   -87,   -87,   -87,   -87,   -87,
-     -87,   -87,   -87,   -87,    21,   252,    26,    -7,    -9,    -8,
-      84,     0,    -3,    -6,    -2,   -58,   -87,   -10,   -86
-};
-
-/* YYTABLE[YYPACT[STATE-NUM]].  What to do in state STATE-NUM.  If
-   positive, shift that token.  If negative, reduce the rule which
-   number is the opposite.  If zero, do what YYDEFACT says.
-   If YYTABLE_NINF, syntax error.  */
-#define YYTABLE_NINF -1
-static const yytype_uint16 yytable[] =
-{
-      75,    71,    72,    87,    74,    86,    85,    73,   134,    76,
-      97,   159,    99,   215,    88,   104,   223,   105,    95,   153,
-     154,   111,   112,   139,   108,   109,   110,    49,   111,   112,
-      64,   255,   256,    49,    62,     2,   117,   119,   224,    56,
-     138,    90,    92,    94,   155,    32,   127,   101,   103,    31,
-     198,    43,   199,   160,   126,   216,   131,    75,    71,    72,
-     200,    74,   132,   133,    73,   106,   114,   120,    34,    35,
-     107,   128,    87,   117,   129,   140,   204,   205,   206,   121,
-     130,   209,   210,   211,   212,   213,   174,   175,   169,   170,
-     171,    36,   176,    34,    35,   117,   117,   197,   114,   137,
-     141,   156,   157,    81,   142,    44,   143,   144,   145,    82,
-      56,    83,   109,    47,   182,   117,    36,   174,   175,   146,
-     147,   236,   237,   176,   148,   177,   131,   158,   183,   149,
-      44,    87,   132,   186,   184,   150,    83,   191,    47,   190,
-     163,   164,   165,   166,   167,   168,   169,   170,   171,   202,
-     180,   151,   117,   117,   117,   161,   181,   117,   117,   117,
-     117,   117,   173,   182,   203,   187,   188,   189,   109,   192,
-     193,   207,    34,    35,   208,   217,   194,   195,   162,   163,
-     164,   165,   166,   167,   168,   169,   170,   171,   167,   168,
-     169,   170,   171,    34,   122,    36,   214,   117,   117,    37,
-      38,    39,    40,    41,   238,   239,    42,    43,   218,    44,
-     220,   221,   222,    45,   242,    46,    36,    47,   226,   227,
-     249,   248,   250,   228,   233,   123,   124,   172,    43,   232,
-      44,   229,   230,   231,   235,   243,   125,   244,    47,   234,
-     240,   245,   261,     4,   164,   165,   166,   167,   168,   169,
-     170,   171,   266,   267,   241,     5,     6,     7,     8,     9,
-      10,    11,    12,    13,    14,    15,    16,    17,    18,    19,
-      20,    21,    22,    34,    35,    65,    37,    38,    39,    40,
-      41,   246,   251,    42,   247,    23,   252,    24,   253,    25,
-     254,   257,   258,   262,   263,   260,    36,    34,    35,   135,
-      37,    38,    39,    40,    41,   264,   265,    42,    66,   268,
-      44,   269,   196,    78,    67,    56,    46,    79,    47,   136,
-      36,    34,    35,     0,    37,    38,    39,    40,    41,   259,
-       0,    42,    66,     0,    44,     0,     0,     0,     0,    56,
-      46,     0,    47,     0,    36,    34,    35,     0,    37,    38,
-      39,    40,    41,     0,     0,    42,    43,     0,    44,     0,
-       0,     0,     0,    56,    46,     0,    47,     0,    36,    34,
-      35,     0,    37,    38,    39,    40,    41,     0,     0,    42,
-      43,     0,    44,     0,     0,     0,    77,     0,    46,     0,
-      47,     0,    36,    34,    35,     0,    37,    38,    39,    40,
-      41,     0,     0,    42,    43,     0,    44,     0,     0,    34,
-      35,     0,    46,     0,    47,     0,    36,     0,    34,    35,
-      37,    38,    39,    40,    41,    34,    35,    42,     0,     0,
-      44,     0,    36,     0,    34,   178,    46,   115,    47,     0,
-       0,    36,     0,   116,    34,    35,    44,     0,    36,     0,
-       0,     0,    83,    43,    47,    44,     0,    36,     0,     0,
-      81,    46,    44,    47,     0,     0,   179,    36,    83,     0,
-      47,    44,    34,    35,     0,    34,    35,    83,     0,    47,
-       0,    44,    34,    35,     0,     0,   185,    83,     0,    47,
-       0,     0,     0,     0,     0,    36,     0,     0,    36,     0,
-       0,     0,     0,     0,     0,    36,     0,   219,     0,    44,
-       0,     0,    44,     0,    56,    83,     0,    47,    83,    44,
-      47,     0,     0,     0,     0,    83,     0,    47,   162,   163,
-     164,   165,   166,   167,   168,   169,   170,   171,   165,   166,
-     167,   168,   169,   170,   171
-};
-
-static const yytype_int16 yycheck[] =
-{
-      10,    10,    10,    13,    10,    13,    13,    10,    66,    11,
-      19,    10,    20,    10,    14,    46,     9,    48,    18,   105,
-     106,     8,     9,    81,    34,    35,     6,     6,     8,     9,
-       9,    36,    37,    12,     8,     0,    46,    47,    31,    50,
-      11,    15,    16,    17,     7,    49,    56,    21,    22,    47,
-      32,    43,    34,    52,    56,    52,    65,    67,    67,    67,
-      42,    67,    65,    65,    67,    48,    45,    51,     8,     9,
-      47,    49,    82,    83,    49,    82,   162,   163,   164,    51,
-      49,   167,   168,   169,   170,   171,    36,    37,    10,    11,
-      12,    31,    42,     8,     9,   105,   106,   155,    77,    51,
-      49,   111,   112,    43,    51,    45,    49,    49,    49,    49,
-      50,    51,   122,    53,    33,   125,    31,    36,    37,    49,
-      49,   207,   208,    42,    49,    40,   135,    51,   138,    49,
-      45,   141,   135,   143,   141,    49,    51,   147,    53,   147,
-       4,     5,     6,     7,     8,     9,    10,    11,    12,   159,
-     129,    49,   162,   163,   164,    52,   130,   167,   168,   169,
-     170,   171,    36,    33,    51,   144,   145,   146,   178,   148,
-     149,     6,     8,     9,     7,    52,   150,   151,     3,     4,
-       5,     6,     7,     8,     9,    10,    11,    12,     8,     9,
-      10,    11,    12,     8,     9,    31,    10,   207,   208,    35,
-      36,    37,    38,    39,   214,   215,    42,    43,    52,    45,
-      52,    52,    49,    49,   222,    51,    31,    53,    49,    46,
-     230,   229,   231,    46,    52,    40,    41,    52,    43,    51,
-      45,    49,    49,    49,    36,    31,    51,     9,    53,    52,
-      51,    50,   252,     1,     5,     6,     7,     8,     9,    10,
-      11,    12,   262,   263,    52,    13,    14,    15,    16,    17,
-      18,    19,    20,    21,    22,    23,    24,    25,    26,    27,
-      28,    29,    30,     8,     9,    10,    35,    36,    37,    38,
-      39,    36,    34,    42,    37,    43,    10,    45,    52,    47,
-      52,     9,    31,    10,    10,    52,    31,     8,     9,    10,
-      35,    36,    37,    38,    39,    31,    52,    42,    43,    52,
-      45,    52,   152,    12,    49,    50,    51,    12,    53,    67,
-      31,     8,     9,    -1,    35,    36,    37,    38,    39,   245,
-      -1,    42,    43,    -1,    45,    -1,    -1,    -1,    -1,    50,
-      51,    -1,    53,    -1,    31,     8,     9,    -1,    35,    36,
-      37,    38,    39,    -1,    -1,    42,    43,    -1,    45,    -1,
-      -1,    -1,    -1,    50,    51,    -1,    53,    -1,    31,     8,
-       9,    -1,    35,    36,    37,    38,    39,    -1,    -1,    42,
-      43,    -1,    45,    -1,    -1,    -1,    49,    -1,    51,    -1,
-      53,    -1,    31,     8,     9,    -1,    35,    36,    37,    38,
-      39,    -1,    -1,    42,    43,    -1,    45,    -1,    -1,     8,
-       9,    -1,    51,    -1,    53,    -1,    31,    -1,     8,     9,
-      35,    36,    37,    38,    39,     8,     9,    42,    -1,    -1,
-      45,    -1,    31,    -1,     8,     9,    51,    36,    53,    -1,
-      -1,    31,    -1,    42,     8,     9,    45,    -1,    31,    -1,
-      -1,    -1,    51,    43,    53,    45,    -1,    31,    -1,    -1,
-      43,    51,    45,    53,    -1,    -1,    40,    31,    51,    -1,
-      53,    45,     8,     9,    -1,     8,     9,    51,    -1,    53,
-      -1,    45,     8,     9,    -1,    -1,    50,    51,    -1,    53,
-      -1,    -1,    -1,    -1,    -1,    31,    -1,    -1,    31,    -1,
-      -1,    -1,    -1,    -1,    -1,    31,    -1,    40,    -1,    45,
-      -1,    -1,    45,    -1,    50,    51,    -1,    53,    51,    45,
-      53,    -1,    -1,    -1,    -1,    51,    -1,    53,     3,     4,
-       5,     6,     7,     8,     9,    10,    11,    12,     6,     7,
-       8,     9,    10,    11,    12
-};
-
-/* YYSTOS[STATE-NUM] -- The (internal number of the) accessing
-   symbol of state STATE-NUM.  */
-static const yytype_uint8 yystos[] =
-{
-       0,    55,     0,    56,     1,    13,    14,    15,    16,    17,
-      18,    19,    20,    21,    22,    23,    24,    25,    26,    27,
-      28,    29,    30,    43,    45,    47,    57,    59,    66,    67,
-      68,    47,    49,    60,     8,     9,    31,    35,    36,    37,
-      38,    39,    42,    43,    45,    49,    51,    53,    64,    78,
-      82,    85,    86,    87,    88,    91,    50,    63,    78,    80,
-      83,    61,    80,    62,    78,    10,    43,    49,    69,    79,
-      81,    82,    83,    86,    87,    91,    88,    49,    60,    64,
-      70,    43,    49,    51,    65,    81,    83,    91,    85,    71,
-      80,    72,    80,    73,    80,    85,    74,    82,    75,    83,
-      76,    80,    77,    80,    46,    48,    48,    47,    91,    91,
-       6,     8,     9,    89,    78,    36,    42,    91,    92,    91,
-      51,    51,     9,    40,    41,    51,    88,    91,    49,    49,
-      49,    82,    86,    88,    89,    10,    79,    51,    11,    89,
-      81,    49,    51,    49,    49,    49,    49,    49,    49,    49,
-      49,    49,    58,    92,    92,     7,    91,    91,    51,    10,
-      52,    52,     3,     4,     5,     6,     7,     8,     9,    10,
-      11,    12,    52,    36,    36,    37,    42,    40,     9,    40,
-      78,    80,    33,    91,    81,    50,    91,    78,    78,    78,
-      83,    91,    78,    78,    80,    80,    57,    89,    32,    34,
-      42,    90,    91,    51,    92,    92,    92,     6,     7,    92,
-      92,    92,    92,    92,    10,    10,    52,    52,    52,    40,
-      52,    52,    49,     9,    31,    84,    49,    46,    46,    49,
-      49,    49,    51,    52,    52,    36,    92,    92,    91,    91,
-      51,    52,    83,    31,     9,    50,    36,    37,    83,    91,
-      82,    34,    10,    52,    52,    36,    37,     9,    31,    84,
-      52,    91,    10,    10,    31,    52,    91,    91,    52,    52
-};
-
-#define yyerrok                (yyerrstatus = 0)
-#define yyclearin      (yychar = YYEMPTY)
-#define YYEMPTY                (-2)
-#define YYEOF          0
-
-#define YYACCEPT       goto yyacceptlab
-#define YYABORT                goto yyabortlab
-#define YYERROR                goto yyerrorlab
-
-
-/* Like YYERROR except do call yyerror.  This remains here temporarily
-   to ease the transition to the new meaning of YYERROR, for GCC.
-   Once GCC version 2 has supplanted version 1, this can go.  */
-
-#define YYFAIL         goto yyerrlab
-
-#define YYRECOVERING()  (!!yyerrstatus)
-
-#define YYBACKUP(Token, Value)                                 \
-do                                                             \
-  if (yychar == YYEMPTY && yylen == 1)                         \
-    {                                                          \
-      yychar = (Token);                                                \
-      yylval = (Value);                                                \
-      yytoken = YYTRANSLATE (yychar);                          \
-      YYPOPSTACK (1);                                          \
-      goto yybackup;                                           \
-    }                                                          \
-  else                                                         \
-    {                                                          \
-      yyerror (YY_("syntax error: cannot back up")); \
-      YYERROR;                                                 \
-    }                                                          \
-while (YYID (0))
-
-
-#define YYTERROR       1
-#define YYERRCODE      256
-
-
-/* YYLLOC_DEFAULT -- Set CURRENT to span from RHS[1] to RHS[N].
-   If N is 0, then set CURRENT to the empty location which ends
-   the previous symbol: RHS[0] (always defined).  */
-
-#define YYRHSLOC(Rhs, K) ((Rhs)[K])
-#ifndef YYLLOC_DEFAULT
-# define YYLLOC_DEFAULT(Current, Rhs, N)                               \
-    do                                                                 \
-      if (YYID (N))                                                    \
-       {                                                               \
-         (Current).first_line   = YYRHSLOC (Rhs, 1).first_line;        \
-         (Current).first_column = YYRHSLOC (Rhs, 1).first_column;      \
-         (Current).last_line    = YYRHSLOC (Rhs, N).last_line;         \
-         (Current).last_column  = YYRHSLOC (Rhs, N).last_column;       \
-       }                                                               \
-      else                                                             \
-       {                                                               \
-         (Current).first_line   = (Current).last_line   =              \
-           YYRHSLOC (Rhs, 0).last_line;                                \
-         (Current).first_column = (Current).last_column =              \
-           YYRHSLOC (Rhs, 0).last_column;                              \
-       }                                                               \
-    while (YYID (0))
-#endif
-
-
-/* YY_LOCATION_PRINT -- Print the location on the stream.
-   This macro was not mandated originally: define only if we know
-   we won't break user code: when these are the locations we know.  */
-
-#ifndef YY_LOCATION_PRINT
-# if defined YYLTYPE_IS_TRIVIAL && YYLTYPE_IS_TRIVIAL
-#  define YY_LOCATION_PRINT(File, Loc)                 \
-     fprintf (File, "%d.%d-%d.%d",                     \
-             (Loc).first_line, (Loc).first_column,     \
-             (Loc).last_line,  (Loc).last_column)
-# else
-#  define YY_LOCATION_PRINT(File, Loc) ((void) 0)
-# endif
-#endif
-
-
-/* YYLEX -- calling `yylex' with the right arguments.  */
-
-#ifdef YYLEX_PARAM
-# define YYLEX yylex (YYLEX_PARAM)
-#else
-# define YYLEX yylex ()
-#endif
-
-/* Enable debugging if requested.  */
-#if YYDEBUG
-
-# ifndef YYFPRINTF
-#  include <stdio.h> /* INFRINGES ON USER NAME SPACE */
-#  define YYFPRINTF fprintf
-# endif
-
-# define YYDPRINTF(Args)                       \
-do {                                           \
-  if (yydebug)                                 \
-    YYFPRINTF Args;                            \
-} while (YYID (0))
-
-# define YY_SYMBOL_PRINT(Title, Type, Value, Location)                   \
-do {                                                                     \
-  if (yydebug)                                                           \
-    {                                                                    \
-      YYFPRINTF (stderr, "%s ", Title);                                          \
-      yy_symbol_print (stderr,                                           \
-                 Type, Value); \
-      YYFPRINTF (stderr, "\n");                                                  \
-    }                                                                    \
-} while (YYID (0))
-
-
-/*--------------------------------.
-| Print this symbol on YYOUTPUT.  |
-`--------------------------------*/
-
-/*ARGSUSED*/
-#if (defined __STDC__ || defined __C99__FUNC__ \
-     || defined __cplusplus || defined _MSC_VER)
-static void
-yy_symbol_value_print (FILE *yyoutput, int yytype, YYSTYPE const * const yyvaluep)
-#else
-static void
-yy_symbol_value_print (yyoutput, yytype, yyvaluep)
-    FILE *yyoutput;
-    int yytype;
-    YYSTYPE const * const yyvaluep;
-#endif
-{
-  if (!yyvaluep)
-    return;
-# ifdef YYPRINT
-  if (yytype < YYNTOKENS)
-    YYPRINT (yyoutput, yytoknum[yytype], *yyvaluep);
-# else
-  YYUSE (yyoutput);
-# endif
-  switch (yytype)
-    {
-      default:
-       break;
-    }
-}
-
-
-/*--------------------------------.
-| Print this symbol on YYOUTPUT.  |
-`--------------------------------*/
-
-#if (defined __STDC__ || defined __C99__FUNC__ \
-     || defined __cplusplus || defined _MSC_VER)
-static void
-yy_symbol_print (FILE *yyoutput, int yytype, YYSTYPE const * const yyvaluep)
-#else
-static void
-yy_symbol_print (yyoutput, yytype, yyvaluep)
-    FILE *yyoutput;
-    int yytype;
-    YYSTYPE const * const yyvaluep;
-#endif
-{
-  if (yytype < YYNTOKENS)
-    YYFPRINTF (yyoutput, "token %s (", yytname[yytype]);
-  else
-    YYFPRINTF (yyoutput, "nterm %s (", yytname[yytype]);
-
-  yy_symbol_value_print (yyoutput, yytype, yyvaluep);
-  YYFPRINTF (yyoutput, ")");
-}
-
-/*------------------------------------------------------------------.
-| yy_stack_print -- Print the state stack from its BOTTOM up to its |
-| TOP (included).                                                   |
-`------------------------------------------------------------------*/
-
-#if (defined __STDC__ || defined __C99__FUNC__ \
-     || defined __cplusplus || defined _MSC_VER)
-static void
-yy_stack_print (yytype_int16 *bottom, yytype_int16 *top)
-#else
-static void
-yy_stack_print (bottom, top)
-    yytype_int16 *bottom;
-    yytype_int16 *top;
-#endif
-{
-  YYFPRINTF (stderr, "Stack now");
-  for (; bottom <= top; ++bottom)
-    YYFPRINTF (stderr, " %d", *bottom);
-  YYFPRINTF (stderr, "\n");
-}
-
-# define YY_STACK_PRINT(Bottom, Top)                           \
-do {                                                           \
-  if (yydebug)                                                 \
-    yy_stack_print ((Bottom), (Top));                          \
-} while (YYID (0))
-
-
-/*------------------------------------------------.
-| Report that the YYRULE is going to be reduced.  |
-`------------------------------------------------*/
-
-#if (defined __STDC__ || defined __C99__FUNC__ \
-     || defined __cplusplus || defined _MSC_VER)
-static void
-yy_reduce_print (YYSTYPE *yyvsp, int yyrule)
-#else
-static void
-yy_reduce_print (yyvsp, yyrule)
-    YYSTYPE *yyvsp;
-    int yyrule;
-#endif
-{
-  int yynrhs = yyr2[yyrule];
-  int yyi;
-  unsigned long int yylno = yyrline[yyrule];
-  YYFPRINTF (stderr, "Reducing stack by rule %d (line %lu):\n",
-            yyrule - 1, yylno);
-  /* The symbols being reduced.  */
-  for (yyi = 0; yyi < yynrhs; yyi++)
-    {
-      fprintf (stderr, "   $%d = ", yyi + 1);
-      yy_symbol_print (stderr, yyrhs[yyprhs[yyrule] + yyi],
-                      &(yyvsp[(yyi + 1) - (yynrhs)])
-                                      );
-      fprintf (stderr, "\n");
-    }
-}
-
-# define YY_REDUCE_PRINT(Rule)         \
-do {                                   \
-  if (yydebug)                         \
-    yy_reduce_print (yyvsp, Rule); \
-} while (YYID (0))
-
-/* Nonzero means print parse trace.  It is left uninitialized so that
-   multiple parsers can coexist.  */
-int yydebug;
-#else /* !YYDEBUG */
-# define YYDPRINTF(Args)
-# define YY_SYMBOL_PRINT(Title, Type, Value, Location)
-# define YY_STACK_PRINT(Bottom, Top)
-# define YY_REDUCE_PRINT(Rule)
-#endif /* !YYDEBUG */
-
-
-/* YYINITDEPTH -- initial size of the parser's stacks.  */
-#ifndef        YYINITDEPTH
-# define YYINITDEPTH 200
-#endif
-
-/* YYMAXDEPTH -- maximum size the stacks can grow to (effective only
-   if the built-in stack extension method is used).
-
-   Do not make this value too large; the results are undefined if
-   YYSTACK_ALLOC_MAXIMUM < YYSTACK_BYTES (YYMAXDEPTH)
-   evaluated with infinite-precision integer arithmetic.  */
-
-#ifndef YYMAXDEPTH
-# define YYMAXDEPTH 10000
-#endif
-
-\f
-
-#if YYERROR_VERBOSE
-
-# ifndef yystrlen
-#  if defined __GLIBC__ && defined _STRING_H
-#   define yystrlen strlen
-#  else
-/* Return the length of YYSTR.  */
-#if (defined __STDC__ || defined __C99__FUNC__ \
-     || defined __cplusplus || defined _MSC_VER)
-static YYSIZE_T
-yystrlen (const char *yystr)
-#else
-static YYSIZE_T
-yystrlen (yystr)
-    const char *yystr;
-#endif
-{
-  YYSIZE_T yylen;
-  for (yylen = 0; yystr[yylen]; yylen++)
-    continue;
-  return yylen;
-}
-#  endif
-# endif
-
-# ifndef yystpcpy
-#  if defined __GLIBC__ && defined _STRING_H && defined _GNU_SOURCE
-#   define yystpcpy stpcpy
-#  else
-/* Copy YYSRC to YYDEST, returning the address of the terminating '\0' in
-   YYDEST.  */
-#if (defined __STDC__ || defined __C99__FUNC__ \
-     || defined __cplusplus || defined _MSC_VER)
-static char *
-yystpcpy (char *yydest, const char *yysrc)
-#else
-static char *
-yystpcpy (yydest, yysrc)
-    char *yydest;
-    const char *yysrc;
-#endif
-{
-  char *yyd = yydest;
-  const char *yys = yysrc;
-
-  while ((*yyd++ = *yys++) != '\0')
-    continue;
-
-  return yyd - 1;
-}
-#  endif
-# endif
-
-# ifndef yytnamerr
-/* Copy to YYRES the contents of YYSTR after stripping away unnecessary
-   quotes and backslashes, so that it's suitable for yyerror.  The
-   heuristic is that double-quoting is unnecessary unless the string
-   contains an apostrophe, a comma, or backslash (other than
-   backslash-backslash).  YYSTR is taken from yytname.  If YYRES is
-   null, do not copy; instead, return the length of what the result
-   would have been.  */
-static YYSIZE_T
-yytnamerr (char *yyres, const char *yystr)
-{
-  if (*yystr == '"')
-    {
-      YYSIZE_T yyn = 0;
-      char const *yyp = yystr;
-
-      for (;;)
-       switch (*++yyp)
-         {
-         case '\'':
-         case ',':
-           goto do_not_strip_quotes;
-
-         case '\\':
-           if (*++yyp != '\\')
-             goto do_not_strip_quotes;
-           /* Fall through.  */
-         default:
-           if (yyres)
-             yyres[yyn] = *yyp;
-           yyn++;
-           break;
-
-         case '"':
-           if (yyres)
-             yyres[yyn] = '\0';
-           return yyn;
-         }
-    do_not_strip_quotes: ;
-    }
-
-  if (! yyres)
-    return yystrlen (yystr);
-
-  return yystpcpy (yyres, yystr) - yyres;
-}
-# endif
-
-/* Copy into YYRESULT an error message about the unexpected token
-   YYCHAR while in state YYSTATE.  Return the number of bytes copied,
-   including the terminating null byte.  If YYRESULT is null, do not
-   copy anything; just return the number of bytes that would be
-   copied.  As a special case, return 0 if an ordinary "syntax error"
-   message will do.  Return YYSIZE_MAXIMUM if overflow occurs during
-   size calculation.  */
-static YYSIZE_T
-yysyntax_error (char *yyresult, int yystate, int yychar)
-{
-  int yyn = yypact[yystate];
-
-  if (! (YYPACT_NINF < yyn && yyn <= YYLAST))
-    return 0;
-  else
-    {
-      int yytype = YYTRANSLATE (yychar);
-      YYSIZE_T yysize0 = yytnamerr (0, yytname[yytype]);
-      YYSIZE_T yysize = yysize0;
-      YYSIZE_T yysize1;
-      int yysize_overflow = 0;
-      enum { YYERROR_VERBOSE_ARGS_MAXIMUM = 5 };
-      char const *yyarg[YYERROR_VERBOSE_ARGS_MAXIMUM];
-      int yyx;
-
-# if 0
-      /* This is so xgettext sees the translatable formats that are
-        constructed on the fly.  */
-      YY_("syntax error, unexpected %s");
-      YY_("syntax error, unexpected %s, expecting %s");
-      YY_("syntax error, unexpected %s, expecting %s or %s");
-      YY_("syntax error, unexpected %s, expecting %s or %s or %s");
-      YY_("syntax error, unexpected %s, expecting %s or %s or %s or %s");
-# endif
-      char *yyfmt;
-      char const *yyf;
-      static char const yyunexpected[] = "syntax error, unexpected %s";
-      static char const yyexpecting[] = ", expecting %s";
-      static char const yyor[] = " or %s";
-      char yyformat[sizeof yyunexpected
-                   + sizeof yyexpecting - 1
-                   + ((YYERROR_VERBOSE_ARGS_MAXIMUM - 2)
-                      * (sizeof yyor - 1))];
-      char const *yyprefix = yyexpecting;
-
-      /* Start YYX at -YYN if negative to avoid negative indexes in
-        YYCHECK.  */
-      int yyxbegin = yyn < 0 ? -yyn : 0;
-
-      /* Stay within bounds of both yycheck and yytname.  */
-      int yychecklim = YYLAST - yyn + 1;
-      int yyxend = yychecklim < YYNTOKENS ? yychecklim : YYNTOKENS;
-      int yycount = 1;
-
-      yyarg[0] = yytname[yytype];
-      yyfmt = yystpcpy (yyformat, yyunexpected);
-
-      for (yyx = yyxbegin; yyx < yyxend; ++yyx)
-       if (yycheck[yyx + yyn] == yyx && yyx != YYTERROR)
-         {
-           if (yycount == YYERROR_VERBOSE_ARGS_MAXIMUM)
-             {
-               yycount = 1;
-               yysize = yysize0;
-               yyformat[sizeof yyunexpected - 1] = '\0';
-               break;
-             }
-           yyarg[yycount++] = yytname[yyx];
-           yysize1 = yysize + yytnamerr (0, yytname[yyx]);
-           yysize_overflow |= (yysize1 < yysize);
-           yysize = yysize1;
-           yyfmt = yystpcpy (yyfmt, yyprefix);
-           yyprefix = yyor;
-         }
-
-      yyf = YY_(yyformat);
-      yysize1 = yysize + yystrlen (yyf);
-      yysize_overflow |= (yysize1 < yysize);
-      yysize = yysize1;
-
-      if (yysize_overflow)
-       return YYSIZE_MAXIMUM;
-
-      if (yyresult)
-       {
-         /* Avoid sprintf, as that infringes on the user's name space.
-            Don't have undefined behavior even if the translation
-            produced a string with the wrong number of "%s"s.  */
-         char *yyp = yyresult;
-         int yyi = 0;
-         while ((*yyp = *yyf) != '\0')
-           {
-             if (*yyp == '%' && yyf[1] == 's' && yyi < yycount)
-               {
-                 yyp += yytnamerr (yyp, yyarg[yyi++]);
-                 yyf += 2;
-               }
-             else
-               {
-                 yyp++;
-                 yyf++;
-               }
-           }
-       }
-      return yysize;
-    }
-}
-#endif /* YYERROR_VERBOSE */
-\f
-
-/*-----------------------------------------------.
-| Release the memory associated to this symbol.  |
-`-----------------------------------------------*/
-
-/*ARGSUSED*/
-#if (defined __STDC__ || defined __C99__FUNC__ \
-     || defined __cplusplus || defined _MSC_VER)
-static void
-yydestruct (const char *yymsg, int yytype, YYSTYPE *yyvaluep)
-#else
-static void
-yydestruct (yymsg, yytype, yyvaluep)
-    const char *yymsg;
-    int yytype;
-    YYSTYPE *yyvaluep;
-#endif
-{
-  YYUSE (yyvaluep);
-
-  if (!yymsg)
-    yymsg = "Deleting";
-  YY_SYMBOL_PRINT (yymsg, yytype, yyvaluep, yylocationp);
-
-  switch (yytype)
-    {
-
-      default:
-       break;
-    }
-}
-\f
-
-/* Prevent warnings from -Wmissing-prototypes.  */
-
-#ifdef YYPARSE_PARAM
-#if defined __STDC__ || defined __cplusplus
-int yyparse (void *YYPARSE_PARAM);
-#else
-int yyparse ();
-#endif
-#else /* ! YYPARSE_PARAM */
-#if defined __STDC__ || defined __cplusplus
-int yyparse (void);
-#else
-int yyparse ();
-#endif
-#endif /* ! YYPARSE_PARAM */
-
-
-
-/* The look-ahead symbol.  */
-int yychar;
-
-/* The semantic value of the look-ahead symbol.  */
-YYSTYPE yylval;
-
-/* Number of syntax errors so far.  */
-int yynerrs;
-
-
-
-/*----------.
-| yyparse.  |
-`----------*/
-
-#ifdef YYPARSE_PARAM
-#if (defined __STDC__ || defined __C99__FUNC__ \
-     || defined __cplusplus || defined _MSC_VER)
-int
-yyparse (void *YYPARSE_PARAM)
-#else
-int
-yyparse (YYPARSE_PARAM)
-    void *YYPARSE_PARAM;
-#endif
-#else /* ! YYPARSE_PARAM */
-#if (defined __STDC__ || defined __C99__FUNC__ \
-     || defined __cplusplus || defined _MSC_VER)
-int
-yyparse (void)
-#else
-int
-yyparse ()
-
-#endif
-#endif
-{
-  
-  int yystate;
-  int yyn;
-  int yyresult;
-  /* Number of tokens to shift before error messages enabled.  */
-  int yyerrstatus;
-  /* Look-ahead token as an internal (translated) token number.  */
-  int yytoken = 0;
-#if YYERROR_VERBOSE
-  /* Buffer for error messages, and its allocated size.  */
-  char yymsgbuf[128];
-  char *yymsg = yymsgbuf;
-  YYSIZE_T yymsg_alloc = sizeof yymsgbuf;
-#endif
-
-  /* Three stacks and their tools:
-     `yyss': related to states,
-     `yyvs': related to semantic values,
-     `yyls': related to locations.
-
-     Refer to the stacks thru separate pointers, to allow yyoverflow
-     to reallocate them elsewhere.  */
-
-  /* The state stack.  */
-  yytype_int16 yyssa[YYINITDEPTH];
-  yytype_int16 *yyss = yyssa;
-  yytype_int16 *yyssp;
-
-  /* The semantic value stack.  */
-  YYSTYPE yyvsa[YYINITDEPTH];
-  YYSTYPE *yyvs = yyvsa;
-  YYSTYPE *yyvsp;
-
-
-
-#define YYPOPSTACK(N)   (yyvsp -= (N), yyssp -= (N))
-
-  YYSIZE_T yystacksize = YYINITDEPTH;
-
-  /* The variables used to return semantic value and location from the
-     action routines.  */
-  YYSTYPE yyval;
-
-
-  /* The number of symbols on the RHS of the reduced rule.
-     Keep to zero when no symbol should be popped.  */
-  int yylen = 0;
-
-  YYDPRINTF ((stderr, "Starting parse\n"));
-
-  yystate = 0;
-  yyerrstatus = 0;
-  yynerrs = 0;
-  yychar = YYEMPTY;            /* Cause a token to be read.  */
-
-  /* Initialize stack pointers.
-     Waste one element of value and location stack
-     so that they stay on the same level as the state stack.
-     The wasted elements are never initialized.  */
-
-  yyssp = yyss;
-  yyvsp = yyvs;
-
-  goto yysetstate;
-
-/*------------------------------------------------------------.
-| yynewstate -- Push a new state, which is found in yystate.  |
-`------------------------------------------------------------*/
- yynewstate:
-  /* In all cases, when you get here, the value and location stacks
-     have just been pushed.  So pushing a state here evens the stacks.  */
-  yyssp++;
-
- yysetstate:
-  *yyssp = yystate;
-
-  if (yyss + yystacksize - 1 <= yyssp)
-    {
-      /* Get the current used size of the three stacks, in elements.  */
-      YYSIZE_T yysize = yyssp - yyss + 1;
-
-#ifdef yyoverflow
-      {
-       /* Give user a chance to reallocate the stack.  Use copies of
-          these so that the &'s don't force the real ones into
-          memory.  */
-       YYSTYPE *yyvs1 = yyvs;
-       yytype_int16 *yyss1 = yyss;
-
-
-       /* Each stack pointer address is followed by the size of the
-          data in use in that stack, in bytes.  This used to be a
-          conditional around just the two extra args, but that might
-          be undefined if yyoverflow is a macro.  */
-       yyoverflow (YY_("memory exhausted"),
-                   &yyss1, yysize * sizeof (*yyssp),
-                   &yyvs1, yysize * sizeof (*yyvsp),
-
-                   &yystacksize);
-
-       yyss = yyss1;
-       yyvs = yyvs1;
-      }
-#else /* no yyoverflow */
-# ifndef YYSTACK_RELOCATE
-      goto yyexhaustedlab;
-# else
-      /* Extend the stack our own way.  */
-      if (YYMAXDEPTH <= yystacksize)
-       goto yyexhaustedlab;
-      yystacksize *= 2;
-      if (YYMAXDEPTH < yystacksize)
-       yystacksize = YYMAXDEPTH;
-
-      {
-       yytype_int16 *yyss1 = yyss;
-       union yyalloc *yyptr =
-         (union yyalloc *) YYSTACK_ALLOC (YYSTACK_BYTES (yystacksize));
-       if (! yyptr)
-         goto yyexhaustedlab;
-       YYSTACK_RELOCATE (yyss);
-       YYSTACK_RELOCATE (yyvs);
-
-#  undef YYSTACK_RELOCATE
-       if (yyss1 != yyssa)
-         YYSTACK_FREE (yyss1);
-      }
-# endif
-#endif /* no yyoverflow */
-
-      yyssp = yyss + yysize - 1;
-      yyvsp = yyvs + yysize - 1;
-
-
-      YYDPRINTF ((stderr, "Stack size increased to %lu\n",
-                 (unsigned long int) yystacksize));
-
-      if (yyss + yystacksize - 1 <= yyssp)
-       YYABORT;
-    }
-
-  YYDPRINTF ((stderr, "Entering state %d\n", yystate));
-
-  goto yybackup;
-
-/*-----------.
-| yybackup.  |
-`-----------*/
-yybackup:
-
-  /* Do appropriate processing given the current state.  Read a
-     look-ahead token if we need one and don't already have one.  */
-
-  /* First try to decide what to do without reference to look-ahead token.  */
-  yyn = yypact[yystate];
-  if (yyn == YYPACT_NINF)
-    goto yydefault;
-
-  /* Not known => get a look-ahead token if don't already have one.  */
-
-  /* YYCHAR is either YYEMPTY or YYEOF or a valid look-ahead symbol.  */
-  if (yychar == YYEMPTY)
-    {
-      YYDPRINTF ((stderr, "Reading a token: "));
-      yychar = YYLEX;
-    }
-
-  if (yychar <= YYEOF)
-    {
-      yychar = yytoken = YYEOF;
-      YYDPRINTF ((stderr, "Now at end of input.\n"));
-    }
-  else
-    {
-      yytoken = YYTRANSLATE (yychar);
-      YY_SYMBOL_PRINT ("Next token is", yytoken, &yylval, &yylloc);
-    }
-
-  /* If the proper action on seeing token YYTOKEN is to reduce or to
-     detect an error, take that action.  */
-  yyn += yytoken;
-  if (yyn < 0 || YYLAST < yyn || yycheck[yyn] != yytoken)
-    goto yydefault;
-  yyn = yytable[yyn];
-  if (yyn <= 0)
-    {
-      if (yyn == 0 || yyn == YYTABLE_NINF)
-       goto yyerrlab;
-      yyn = -yyn;
-      goto yyreduce;
-    }
-
-  if (yyn == YYFINAL)
-    YYACCEPT;
-
-  /* Count tokens shifted since error; after three, turn off error
-     status.  */
-  if (yyerrstatus)
-    yyerrstatus--;
-
-  /* Shift the look-ahead token.  */
-  YY_SYMBOL_PRINT ("Shifting", yytoken, &yylval, &yylloc);
-
-  /* Discard the shifted token unless it is eof.  */
-  if (yychar != YYEOF)
-    yychar = YYEMPTY;
-
-  yystate = yyn;
-  *++yyvsp = yylval;
-
-  goto yynewstate;
-
-
-/*-----------------------------------------------------------.
-| yydefault -- do the default action for the current state.  |
-`-----------------------------------------------------------*/
-yydefault:
-  yyn = yydefact[yystate];
-  if (yyn == 0)
-    goto yyerrlab;
-  goto yyreduce;
-
-
-/*-----------------------------.
-| yyreduce -- Do a reduction.  |
-`-----------------------------*/
-yyreduce:
-  /* yyn is the number of a rule to reduce with.  */
-  yylen = yyr2[yyn];
-
-  /* If YYLEN is nonzero, implement the default value of the action:
-     `$$ = $1'.
-
-     Otherwise, the following line sets YYVAL to garbage.
-     This behavior is undocumented and Bison
-     users should not rely upon it.  Assigning to YYVAL
-     unconditionally makes the parser a bit smaller, and it avoids a
-     GCC warning that YYVAL may be used uninitialized.  */
-  yyval = yyvsp[1-yylen];
-
-
-  YY_REDUCE_PRINT (yyn);
-  switch (yyn)
-    {
-        case 3:
-#line 66 "a.y"
-    {
-               stmtline = lineno;
-       }
-    break;
-
-  case 5:
-#line 73 "a.y"
-    {
-               (yyvsp[(1) - (2)].sym) = labellookup((yyvsp[(1) - (2)].sym));
-               if((yyvsp[(1) - (2)].sym)->type == LLAB && (yyvsp[(1) - (2)].sym)->value != pc)
-                       yyerror("redeclaration of %s", (yyvsp[(1) - (2)].sym)->labelname);
-               (yyvsp[(1) - (2)].sym)->type = LLAB;
-               (yyvsp[(1) - (2)].sym)->value = pc;
-       }
-    break;
-
-  case 10:
-#line 87 "a.y"
-    {
-               (yyvsp[(1) - (3)].sym)->type = LVAR;
-               (yyvsp[(1) - (3)].sym)->value = (yyvsp[(3) - (3)].lval);
-       }
-    break;
-
-  case 11:
-#line 92 "a.y"
-    {
-               if((yyvsp[(1) - (3)].sym)->value != (yyvsp[(3) - (3)].lval))
-                       yyerror("redeclaration of %s", (yyvsp[(1) - (3)].sym)->name);
-               (yyvsp[(1) - (3)].sym)->value = (yyvsp[(3) - (3)].lval);
-       }
-    break;
-
-  case 12:
-#line 97 "a.y"
-    { outcode((yyvsp[(1) - (2)].lval), &(yyvsp[(2) - (2)].addr2)); }
-    break;
-
-  case 13:
-#line 98 "a.y"
-    { outcode((yyvsp[(1) - (2)].lval), &(yyvsp[(2) - (2)].addr2)); }
-    break;
-
-  case 14:
-#line 99 "a.y"
-    { outcode((yyvsp[(1) - (2)].lval), &(yyvsp[(2) - (2)].addr2)); }
-    break;
-
-  case 15:
-#line 100 "a.y"
-    { outcode((yyvsp[(1) - (2)].lval), &(yyvsp[(2) - (2)].addr2)); }
-    break;
-
-  case 16:
-#line 101 "a.y"
-    { outcode((yyvsp[(1) - (2)].lval), &(yyvsp[(2) - (2)].addr2)); }
-    break;
-
-  case 17:
-#line 102 "a.y"
-    { outcode((yyvsp[(1) - (2)].lval), &(yyvsp[(2) - (2)].addr2)); }
-    break;
-
-  case 20:
-#line 105 "a.y"
-    { outcode((yyvsp[(1) - (2)].lval), &(yyvsp[(2) - (2)].addr2)); }
-    break;
-
-  case 21:
-#line 106 "a.y"
-    { outcode((yyvsp[(1) - (2)].lval), &(yyvsp[(2) - (2)].addr2)); }
-    break;
-
-  case 22:
-#line 107 "a.y"
-    { outcode((yyvsp[(1) - (2)].lval), &(yyvsp[(2) - (2)].addr2)); }
-    break;
-
-  case 23:
-#line 108 "a.y"
-    { outcode((yyvsp[(1) - (2)].lval), &(yyvsp[(2) - (2)].addr2)); }
-    break;
-
-  case 24:
-#line 109 "a.y"
-    { outcode((yyvsp[(1) - (2)].lval), &(yyvsp[(2) - (2)].addr2)); }
-    break;
-
-  case 26:
-#line 111 "a.y"
-    { outcode((yyvsp[(1) - (2)].lval), &(yyvsp[(2) - (2)].addr2)); }
-    break;
-
-  case 27:
-#line 112 "a.y"
-    { outcode((yyvsp[(1) - (2)].lval), &(yyvsp[(2) - (2)].addr2)); }
-    break;
-
-  case 28:
-#line 113 "a.y"
-    { outcode((yyvsp[(1) - (2)].lval), &(yyvsp[(2) - (2)].addr2)); }
-    break;
-
-  case 29:
-#line 114 "a.y"
-    { outcode((yyvsp[(1) - (2)].lval), &(yyvsp[(2) - (2)].addr2)); }
-    break;
-
-  case 30:
-#line 117 "a.y"
-    {
-               (yyval.addr2).from = nullgen;
-               (yyval.addr2).to = nullgen;
-       }
-    break;
-
-  case 31:
-#line 122 "a.y"
-    {
-               (yyval.addr2).from = nullgen;
-               (yyval.addr2).to = nullgen;
-       }
-    break;
-
-  case 32:
-#line 129 "a.y"
-    {
-               (yyval.addr2).from = (yyvsp[(1) - (3)].addr);
-               (yyval.addr2).to = (yyvsp[(3) - (3)].addr);
-       }
-    break;
-
-  case 33:
-#line 136 "a.y"
-    {
-               (yyval.addr2).from = (yyvsp[(1) - (3)].addr);
-               (yyval.addr2).to = (yyvsp[(3) - (3)].addr);
-       }
-    break;
-
-  case 34:
-#line 143 "a.y"
-    {
-               (yyval.addr2).from = (yyvsp[(1) - (2)].addr);
-               (yyval.addr2).to = nullgen;
-       }
-    break;
-
-  case 35:
-#line 148 "a.y"
-    {
-               (yyval.addr2).from = (yyvsp[(1) - (1)].addr);
-               (yyval.addr2).to = nullgen;
-       }
-    break;
-
-  case 36:
-#line 155 "a.y"
-    {
-               (yyval.addr2).from = nullgen;
-               (yyval.addr2).to = (yyvsp[(2) - (2)].addr);
-       }
-    break;
-
-  case 37:
-#line 160 "a.y"
-    {
-               (yyval.addr2).from = nullgen;
-               (yyval.addr2).to = (yyvsp[(1) - (1)].addr);
-       }
-    break;
-
-  case 38:
-#line 167 "a.y"
-    {
-               (yyval.addr2).from = nullgen;
-               (yyval.addr2).to = (yyvsp[(2) - (2)].addr);
-       }
-    break;
-
-  case 39:
-#line 172 "a.y"
-    {
-               (yyval.addr2).from = nullgen;
-               (yyval.addr2).to = (yyvsp[(1) - (1)].addr);
-       }
-    break;
-
-  case 40:
-#line 177 "a.y"
-    {
-               (yyval.addr2).from = (yyvsp[(1) - (3)].addr);
-               (yyval.addr2).to = (yyvsp[(3) - (3)].addr);
-       }
-    break;
-
-  case 41:
-#line 184 "a.y"
-    {
-               Addr2 a;
-               a.from = (yyvsp[(2) - (6)].addr);
-               a.to = (yyvsp[(6) - (6)].addr);
-               outcode(ADATA, &a);
-               if(pass > 1) {
-                       lastpc->from3.type = TYPE_CONST;
-                       lastpc->from3.offset = (yyvsp[(4) - (6)].lval);
-               }
-       }
-    break;
-
-  case 42:
-#line 197 "a.y"
-    {
-               Addr2 a;
-               settext((yyvsp[(2) - (5)].addr).sym);
-               a.from = (yyvsp[(2) - (5)].addr);
-               a.to = (yyvsp[(5) - (5)].addr);
-               outcode(ATEXT, &a);
-       }
-    break;
-
-  case 43:
-#line 205 "a.y"
-    {
-               Addr2 a;
-               settext((yyvsp[(2) - (7)].addr).sym);
-               a.from = (yyvsp[(2) - (7)].addr);
-               a.to = (yyvsp[(7) - (7)].addr);
-               outcode(ATEXT, &a);
-               if(pass > 1) {
-                       lastpc->from3.type = TYPE_CONST;
-                       lastpc->from3.offset = (yyvsp[(4) - (7)].lval);
-               }
-       }
-    break;
-
-  case 44:
-#line 219 "a.y"
-    {
-               Addr2 a;
-               settext((yyvsp[(2) - (4)].addr).sym);
-               a.from = (yyvsp[(2) - (4)].addr);
-               a.to = (yyvsp[(4) - (4)].addr);
-               outcode(AGLOBL, &a);
-       }
-    break;
-
-  case 45:
-#line 227 "a.y"
-    {
-               Addr2 a;
-               settext((yyvsp[(2) - (6)].addr).sym);
-               a.from = (yyvsp[(2) - (6)].addr);
-               a.to = (yyvsp[(6) - (6)].addr);
-               outcode(AGLOBL, &a);
-               if(pass > 1) {
-                       lastpc->from3.type = TYPE_CONST;
-                       lastpc->from3.offset = (yyvsp[(4) - (6)].lval);
-               }
-       }
-    break;
-
-  case 46:
-#line 241 "a.y"
-    {
-               (yyval.addr2).from = nullgen;
-               (yyval.addr2).to = (yyvsp[(2) - (2)].addr);
-       }
-    break;
-
-  case 47:
-#line 246 "a.y"
-    {
-               (yyval.addr2).from = nullgen;
-               (yyval.addr2).to = (yyvsp[(1) - (1)].addr);
-       }
-    break;
-
-  case 48:
-#line 251 "a.y"
-    {
-               (yyval.addr2).from = nullgen;
-               (yyval.addr2).to = (yyvsp[(2) - (2)].addr);
-               (yyval.addr2).to.type = TYPE_INDIR;
-       }
-    break;
-
-  case 51:
-#line 263 "a.y"
-    {
-               (yyval.addr2).from = (yyvsp[(1) - (3)].addr);
-               (yyval.addr2).to = (yyvsp[(3) - (3)].addr);
-       }
-    break;
-
-  case 52:
-#line 268 "a.y"
-    {
-               (yyval.addr2).from = (yyvsp[(1) - (5)].addr);
-               (yyval.addr2).to = (yyvsp[(3) - (5)].addr);
-               if((yyval.addr2).from.index != TYPE_NONE)
-                       yyerror("dp shift with lhs index");
-               (yyval.addr2).from.index = (yyvsp[(5) - (5)].lval);
-       }
-    break;
-
-  case 53:
-#line 278 "a.y"
-    {
-               (yyval.addr2).from = (yyvsp[(1) - (3)].addr);
-               (yyval.addr2).to = (yyvsp[(3) - (3)].addr);
-       }
-    break;
-
-  case 54:
-#line 283 "a.y"
-    {
-               (yyval.addr2).from = (yyvsp[(1) - (5)].addr);
-               (yyval.addr2).to = (yyvsp[(3) - (5)].addr);
-               if((yyval.addr2).to.index != TYPE_NONE)
-                       yyerror("dp move with lhs index");
-               (yyval.addr2).to.index = (yyvsp[(5) - (5)].lval);
-       }
-    break;
-
-  case 55:
-#line 293 "a.y"
-    {
-               (yyval.addr2).from = (yyvsp[(1) - (2)].addr);
-               (yyval.addr2).to = nullgen;
-       }
-    break;
-
-  case 56:
-#line 298 "a.y"
-    {
-               (yyval.addr2).from = (yyvsp[(1) - (1)].addr);
-               (yyval.addr2).to = nullgen;
-       }
-    break;
-
-  case 57:
-#line 303 "a.y"
-    {
-               (yyval.addr2).from = (yyvsp[(1) - (3)].addr);
-               (yyval.addr2).to = (yyvsp[(3) - (3)].addr);
-       }
-    break;
-
-  case 58:
-#line 310 "a.y"
-    {
-               (yyval.addr2).from = (yyvsp[(1) - (5)].addr);
-               (yyval.addr2).to = (yyvsp[(3) - (5)].addr);
-               (yyval.addr2).to.offset = (yyvsp[(5) - (5)].lval);
-       }
-    break;
-
-  case 59:
-#line 318 "a.y"
-    {
-               (yyval.addr2).from = (yyvsp[(3) - (5)].addr);
-               (yyval.addr2).to = (yyvsp[(5) - (5)].addr);
-               if((yyvsp[(1) - (5)].addr).type != TYPE_CONST)
-                       yyerror("illegal constant");
-               (yyval.addr2).to.offset = (yyvsp[(1) - (5)].addr).offset;
-       }
-    break;
-
-  case 60:
-#line 328 "a.y"
-    {
-               if((yyvsp[(1) - (3)].addr).type != TYPE_CONST || (yyvsp[(3) - (3)].addr).type != TYPE_CONST)
-                       yyerror("arguments to PCDATA must be integer constants");
-               (yyval.addr2).from = (yyvsp[(1) - (3)].addr);
-               (yyval.addr2).to = (yyvsp[(3) - (3)].addr);
-       }
-    break;
-
-  case 61:
-#line 337 "a.y"
-    {
-               if((yyvsp[(1) - (3)].addr).type != TYPE_CONST)
-                       yyerror("index for FUNCDATA must be integer constant");
-               if((yyvsp[(3) - (3)].addr).type != TYPE_MEM || ((yyvsp[(3) - (3)].addr).name != NAME_EXTERN && (yyvsp[(3) - (3)].addr).name != NAME_STATIC))
-                       yyerror("value for FUNCDATA must be symbol reference");
-               (yyval.addr2).from = (yyvsp[(1) - (3)].addr);
-               (yyval.addr2).to = (yyvsp[(3) - (3)].addr);
-       }
-    break;
-
-  case 66:
-#line 354 "a.y"
-    {
-               (yyval.addr) = (yyvsp[(2) - (2)].addr);
-       }
-    break;
-
-  case 67:
-#line 358 "a.y"
-    {
-               (yyval.addr) = (yyvsp[(2) - (2)].addr);
-       }
-    break;
-
-  case 73:
-#line 371 "a.y"
-    {
-               (yyval.addr) = nullgen;
-               (yyval.addr).type = TYPE_BRANCH;
-               (yyval.addr).offset = (yyvsp[(1) - (4)].lval) + pc;
-       }
-    break;
-
-  case 74:
-#line 377 "a.y"
-    {
-               (yyvsp[(1) - (2)].sym) = labellookup((yyvsp[(1) - (2)].sym));
-               (yyval.addr) = nullgen;
-               if(pass == 2 && (yyvsp[(1) - (2)].sym)->type != LLAB)
-                       yyerror("undefined label: %s", (yyvsp[(1) - (2)].sym)->labelname);
-               (yyval.addr).type = TYPE_BRANCH;
-               (yyval.addr).offset = (yyvsp[(1) - (2)].sym)->value + (yyvsp[(2) - (2)].lval);
-       }
-    break;
-
-  case 75:
-#line 388 "a.y"
-    {
-               (yyval.addr) = nullgen;
-               (yyval.addr).type = TYPE_REG;
-               (yyval.addr).reg = (yyvsp[(1) - (1)].lval);
-       }
-    break;
-
-  case 76:
-#line 394 "a.y"
-    {
-               (yyval.addr) = nullgen;
-               (yyval.addr).type = TYPE_REG;
-               (yyval.addr).reg = (yyvsp[(1) - (1)].lval);
-       }
-    break;
-
-  case 77:
-#line 400 "a.y"
-    {
-               (yyval.addr) = nullgen;
-               (yyval.addr).type = TYPE_REG;
-               (yyval.addr).reg = (yyvsp[(1) - (1)].lval);
-       }
-    break;
-
-  case 78:
-#line 406 "a.y"
-    {
-               (yyval.addr) = nullgen;
-               (yyval.addr).type = TYPE_REG;
-               (yyval.addr).reg = (yyvsp[(1) - (1)].lval);
-       }
-    break;
-
-  case 79:
-#line 412 "a.y"
-    {
-               (yyval.addr) = nullgen;
-               (yyval.addr).type = TYPE_REG;
-               (yyval.addr).reg = REG_SP;
-       }
-    break;
-
-  case 80:
-#line 418 "a.y"
-    {
-               (yyval.addr) = nullgen;
-               (yyval.addr).type = TYPE_REG;
-               (yyval.addr).reg = (yyvsp[(1) - (1)].lval);
-       }
-    break;
-
-  case 81:
-#line 426 "a.y"
-    {
-               (yyval.addr) = nullgen;
-               (yyval.addr).type = TYPE_CONST;
-               (yyval.addr).offset = (yyvsp[(2) - (2)].lval);
-       }
-    break;
-
-  case 82:
-#line 432 "a.y"
-    {
-               (yyval.addr) = (yyvsp[(2) - (2)].addr);
-               (yyval.addr).type = TYPE_ADDR;
-               /*
-               if($2.name == NAME_AUTO || $2.name == NAME_PARAM)
-                       yyerror("constant cannot be automatic: %s",
-                               $2.sym->name);
-                */
-       }
-    break;
-
-  case 83:
-#line 442 "a.y"
-    {
-               (yyval.addr) = nullgen;
-               (yyval.addr).type = TYPE_SCONST;
-               memcpy((yyval.addr).u.sval, (yyvsp[(2) - (2)].sval), sizeof((yyval.addr).u.sval));
-       }
-    break;
-
-  case 84:
-#line 448 "a.y"
-    {
-               (yyval.addr) = nullgen;
-               (yyval.addr).type = TYPE_FCONST;
-               (yyval.addr).u.dval = (yyvsp[(2) - (2)].dval);
-       }
-    break;
-
-  case 85:
-#line 454 "a.y"
-    {
-               (yyval.addr) = nullgen;
-               (yyval.addr).type = TYPE_FCONST;
-               (yyval.addr).u.dval = (yyvsp[(3) - (4)].dval);
-       }
-    break;
-
-  case 86:
-#line 460 "a.y"
-    {
-               (yyval.addr) = nullgen;
-               (yyval.addr).type = TYPE_FCONST;
-               (yyval.addr).u.dval = -(yyvsp[(4) - (5)].dval);
-       }
-    break;
-
-  case 87:
-#line 466 "a.y"
-    {
-               (yyval.addr) = nullgen;
-               (yyval.addr).type = TYPE_FCONST;
-               (yyval.addr).u.dval = -(yyvsp[(3) - (3)].dval);
-       }
-    break;
-
-  case 88:
-#line 474 "a.y"
-    {
-               (yyval.addr) = nullgen;
-               (yyval.addr).type = TYPE_TEXTSIZE;
-               (yyval.addr).offset = (yyvsp[(1) - (1)].lval);
-               (yyval.addr).u.argsize = ArgsSizeUnknown;
-       }
-    break;
-
-  case 89:
-#line 481 "a.y"
-    {
-               (yyval.addr) = nullgen;
-               (yyval.addr).type = TYPE_TEXTSIZE;
-               (yyval.addr).offset = -(yyvsp[(2) - (2)].lval);
-               (yyval.addr).u.argsize = ArgsSizeUnknown;
-       }
-    break;
-
-  case 90:
-#line 488 "a.y"
-    {
-               (yyval.addr) = nullgen;
-               (yyval.addr).type = TYPE_TEXTSIZE;
-               (yyval.addr).offset = (yyvsp[(1) - (3)].lval);
-               (yyval.addr).u.argsize = (yyvsp[(3) - (3)].lval);
-       }
-    break;
-
-  case 91:
-#line 495 "a.y"
-    {
-               (yyval.addr) = nullgen;
-               (yyval.addr).type = TYPE_TEXTSIZE;
-               (yyval.addr).offset = -(yyvsp[(2) - (4)].lval);
-               (yyval.addr).u.argsize = (yyvsp[(4) - (4)].lval);
-       }
-    break;
-
-  case 94:
-#line 508 "a.y"
-    {
-               (yyval.addr) = nullgen;
-               (yyval.addr).type = TYPE_MEM;
-               (yyval.addr).reg = REG_NONE;
-               (yyval.addr).offset = (yyvsp[(1) - (1)].lval);
-       }
-    break;
-
-  case 95:
-#line 515 "a.y"
-    {
-               (yyval.addr) = nullgen;
-               (yyval.addr).type = TYPE_MEM;
-               (yyval.addr).reg = (yyvsp[(3) - (4)].lval);
-               (yyval.addr).offset = (yyvsp[(1) - (4)].lval);
-       }
-    break;
-
-  case 96:
-#line 522 "a.y"
-    {
-               (yyval.addr) = nullgen;
-               (yyval.addr).type = TYPE_MEM;
-               (yyval.addr).reg = REG_SP;
-               (yyval.addr).offset = (yyvsp[(1) - (4)].lval);
-       }
-    break;
-
-  case 97:
-#line 529 "a.y"
-    {
-               (yyval.addr) = nullgen;
-               (yyval.addr).type = TYPE_MEM;
-               (yyval.addr).reg = REG_NONE;
-               (yyval.addr).offset = (yyvsp[(1) - (6)].lval);
-               (yyval.addr).index = (yyvsp[(3) - (6)].lval);
-               (yyval.addr).scale = (yyvsp[(5) - (6)].lval);
-               checkscale((yyval.addr).scale);
-       }
-    break;
-
-  case 98:
-#line 539 "a.y"
-    {
-               (yyval.addr) = nullgen;
-               (yyval.addr).type = TYPE_MEM;
-               (yyval.addr).reg = (yyvsp[(3) - (9)].lval);
-               (yyval.addr).offset = (yyvsp[(1) - (9)].lval);
-               (yyval.addr).index = (yyvsp[(6) - (9)].lval);
-               (yyval.addr).scale = (yyvsp[(8) - (9)].lval);
-               checkscale((yyval.addr).scale);
-       }
-    break;
-
-  case 99:
-#line 549 "a.y"
-    {
-               (yyval.addr) = nullgen;
-               (yyval.addr).type = TYPE_MEM;
-               (yyval.addr).reg = (yyvsp[(3) - (9)].lval);
-               (yyval.addr).offset = (yyvsp[(1) - (9)].lval);
-               (yyval.addr).index = (yyvsp[(6) - (9)].lval);
-               (yyval.addr).scale = (yyvsp[(8) - (9)].lval);
-               checkscale((yyval.addr).scale);
-       }
-    break;
-
-  case 100:
-#line 559 "a.y"
-    {
-               (yyval.addr) = nullgen;
-               (yyval.addr).type = TYPE_MEM;
-               (yyval.addr).reg = (yyvsp[(2) - (3)].lval);
-       }
-    break;
-
-  case 101:
-#line 565 "a.y"
-    {
-               (yyval.addr) = nullgen;
-               (yyval.addr).type = TYPE_MEM;
-               (yyval.addr).reg = REG_SP;
-       }
-    break;
-
-  case 102:
-#line 571 "a.y"
-    {
-               (yyval.addr) = nullgen;
-               (yyval.addr).type = TYPE_MEM;
-               (yyval.addr).reg = (yyvsp[(3) - (4)].lval);
-               (yyval.addr).offset = (yyvsp[(1) - (4)].lval);
-       }
-    break;
-
-  case 103:
-#line 578 "a.y"
-    {
-               (yyval.addr) = nullgen;
-               (yyval.addr).type = TYPE_MEM;
-               (yyval.addr).reg = REG_NONE;
-               (yyval.addr).index = (yyvsp[(2) - (5)].lval);
-               (yyval.addr).scale = (yyvsp[(4) - (5)].lval);
-               checkscale((yyval.addr).scale);
-       }
-    break;
-
-  case 104:
-#line 587 "a.y"
-    {
-               (yyval.addr) = nullgen;
-               (yyval.addr).type = TYPE_MEM;
-               (yyval.addr).reg = (yyvsp[(2) - (8)].lval);
-               (yyval.addr).index = (yyvsp[(5) - (8)].lval);
-               (yyval.addr).scale = (yyvsp[(7) - (8)].lval);
-               checkscale((yyval.addr).scale);
-       }
-    break;
-
-  case 105:
-#line 598 "a.y"
-    {
-               (yyval.addr) = (yyvsp[(1) - (1)].addr);
-       }
-    break;
-
-  case 106:
-#line 602 "a.y"
-    {
-               (yyval.addr) = (yyvsp[(1) - (6)].addr);
-               (yyval.addr).index = (yyvsp[(3) - (6)].lval);
-               (yyval.addr).scale = (yyvsp[(5) - (6)].lval);
-               checkscale((yyval.addr).scale);
-       }
-    break;
-
-  case 107:
-#line 611 "a.y"
-    {
-               (yyval.addr) = nullgen;
-               (yyval.addr).type = TYPE_MEM;
-               (yyval.addr).name = (yyvsp[(4) - (5)].lval);
-               (yyval.addr).sym = linklookup(ctxt, (yyvsp[(1) - (5)].sym)->name, 0);
-               (yyval.addr).offset = (yyvsp[(2) - (5)].lval);
-       }
-    break;
-
-  case 108:
-#line 619 "a.y"
-    {
-               (yyval.addr) = nullgen;
-               (yyval.addr).type = TYPE_MEM;
-               (yyval.addr).name = NAME_STATIC;
-               (yyval.addr).sym = linklookup(ctxt, (yyvsp[(1) - (7)].sym)->name, 1);
-               (yyval.addr).offset = (yyvsp[(4) - (7)].lval);
-       }
-    break;
-
-  case 109:
-#line 628 "a.y"
-    {
-               (yyval.lval) = 0;
-       }
-    break;
-
-  case 110:
-#line 632 "a.y"
-    {
-               (yyval.lval) = (yyvsp[(2) - (2)].lval);
-       }
-    break;
-
-  case 111:
-#line 636 "a.y"
-    {
-               (yyval.lval) = -(yyvsp[(2) - (2)].lval);
-       }
-    break;
-
-  case 113:
-#line 643 "a.y"
-    {
-               (yyval.lval) = NAME_AUTO;
-       }
-    break;
-
-  case 116:
-#line 651 "a.y"
-    {
-               (yyval.lval) = (yyvsp[(1) - (1)].sym)->value;
-       }
-    break;
-
-  case 117:
-#line 655 "a.y"
-    {
-               (yyval.lval) = -(yyvsp[(2) - (2)].lval);
-       }
-    break;
-
-  case 118:
-#line 659 "a.y"
-    {
-               (yyval.lval) = (yyvsp[(2) - (2)].lval);
-       }
-    break;
-
-  case 119:
-#line 663 "a.y"
-    {
-               (yyval.lval) = ~(yyvsp[(2) - (2)].lval);
-       }
-    break;
-
-  case 120:
-#line 667 "a.y"
-    {
-               (yyval.lval) = (yyvsp[(2) - (3)].lval);
-       }
-    break;
-
-  case 122:
-#line 674 "a.y"
-    {
-               (yyval.lval) = (yyvsp[(1) - (3)].lval) + (yyvsp[(3) - (3)].lval);
-       }
-    break;
-
-  case 123:
-#line 678 "a.y"
-    {
-               (yyval.lval) = (yyvsp[(1) - (3)].lval) - (yyvsp[(3) - (3)].lval);
-       }
-    break;
-
-  case 124:
-#line 682 "a.y"
-    {
-               (yyval.lval) = (yyvsp[(1) - (3)].lval) * (yyvsp[(3) - (3)].lval);
-       }
-    break;
-
-  case 125:
-#line 686 "a.y"
-    {
-               (yyval.lval) = (yyvsp[(1) - (3)].lval) / (yyvsp[(3) - (3)].lval);
-       }
-    break;
-
-  case 126:
-#line 690 "a.y"
-    {
-               (yyval.lval) = (yyvsp[(1) - (3)].lval) % (yyvsp[(3) - (3)].lval);
-       }
-    break;
-
-  case 127:
-#line 694 "a.y"
-    {
-               (yyval.lval) = (yyvsp[(1) - (4)].lval) << (yyvsp[(4) - (4)].lval);
-       }
-    break;
-
-  case 128:
-#line 698 "a.y"
-    {
-               (yyval.lval) = (yyvsp[(1) - (4)].lval) >> (yyvsp[(4) - (4)].lval);
-       }
-    break;
-
-  case 129:
-#line 702 "a.y"
-    {
-               (yyval.lval) = (yyvsp[(1) - (3)].lval) & (yyvsp[(3) - (3)].lval);
-       }
-    break;
-
-  case 130:
-#line 706 "a.y"
-    {
-               (yyval.lval) = (yyvsp[(1) - (3)].lval) ^ (yyvsp[(3) - (3)].lval);
-       }
-    break;
-
-  case 131:
-#line 710 "a.y"
-    {
-               (yyval.lval) = (yyvsp[(1) - (3)].lval) | (yyvsp[(3) - (3)].lval);
-       }
-    break;
-
-
-/* Line 1267 of yacc.c.  */
-#line 2565 "y.tab.c"
-      default: break;
-    }
-  YY_SYMBOL_PRINT ("-> $$ =", yyr1[yyn], &yyval, &yyloc);
-
-  YYPOPSTACK (yylen);
-  yylen = 0;
-  YY_STACK_PRINT (yyss, yyssp);
-
-  *++yyvsp = yyval;
-
-
-  /* Now `shift' the result of the reduction.  Determine what state
-     that goes to, based on the state we popped back to and the rule
-     number reduced by.  */
-
-  yyn = yyr1[yyn];
-
-  yystate = yypgoto[yyn - YYNTOKENS] + *yyssp;
-  if (0 <= yystate && yystate <= YYLAST && yycheck[yystate] == *yyssp)
-    yystate = yytable[yystate];
-  else
-    yystate = yydefgoto[yyn - YYNTOKENS];
-
-  goto yynewstate;
-
-
-/*------------------------------------.
-| yyerrlab -- here on detecting error |
-`------------------------------------*/
-yyerrlab:
-  /* If not already recovering from an error, report this error.  */
-  if (!yyerrstatus)
-    {
-      ++yynerrs;
-#if ! YYERROR_VERBOSE
-      yyerror (YY_("syntax error"));
-#else
-      {
-       YYSIZE_T yysize = yysyntax_error (0, yystate, yychar);
-       if (yymsg_alloc < yysize && yymsg_alloc < YYSTACK_ALLOC_MAXIMUM)
-         {
-           YYSIZE_T yyalloc = 2 * yysize;
-           if (! (yysize <= yyalloc && yyalloc <= YYSTACK_ALLOC_MAXIMUM))
-             yyalloc = YYSTACK_ALLOC_MAXIMUM;
-           if (yymsg != yymsgbuf)
-             YYSTACK_FREE (yymsg);
-           yymsg = (char *) YYSTACK_ALLOC (yyalloc);
-           if (yymsg)
-             yymsg_alloc = yyalloc;
-           else
-             {
-               yymsg = yymsgbuf;
-               yymsg_alloc = sizeof yymsgbuf;
-             }
-         }
-
-       if (0 < yysize && yysize <= yymsg_alloc)
-         {
-           (void) yysyntax_error (yymsg, yystate, yychar);
-           yyerror (yymsg);
-         }
-       else
-         {
-           yyerror (YY_("syntax error"));
-           if (yysize != 0)
-             goto yyexhaustedlab;
-         }
-      }
-#endif
-    }
-
-
-
-  if (yyerrstatus == 3)
-    {
-      /* If just tried and failed to reuse look-ahead token after an
-        error, discard it.  */
-
-      if (yychar <= YYEOF)
-       {
-         /* Return failure if at end of input.  */
-         if (yychar == YYEOF)
-           YYABORT;
-       }
-      else
-       {
-         yydestruct ("Error: discarding",
-                     yytoken, &yylval);
-         yychar = YYEMPTY;
-       }
-    }
-
-  /* Else will try to reuse look-ahead token after shifting the error
-     token.  */
-  goto yyerrlab1;
-
-
-/*---------------------------------------------------.
-| yyerrorlab -- error raised explicitly by YYERROR.  |
-`---------------------------------------------------*/
-yyerrorlab:
-
-  /* Pacify compilers like GCC when the user code never invokes
-     YYERROR and the label yyerrorlab therefore never appears in user
-     code.  */
-  if (/*CONSTCOND*/ 0)
-     goto yyerrorlab;
-
-  /* Do not reclaim the symbols of the rule which action triggered
-     this YYERROR.  */
-  YYPOPSTACK (yylen);
-  yylen = 0;
-  YY_STACK_PRINT (yyss, yyssp);
-  yystate = *yyssp;
-  goto yyerrlab1;
-
-
-/*-------------------------------------------------------------.
-| yyerrlab1 -- common code for both syntax error and YYERROR.  |
-`-------------------------------------------------------------*/
-yyerrlab1:
-  yyerrstatus = 3;     /* Each real token shifted decrements this.  */
-
-  for (;;)
-    {
-      yyn = yypact[yystate];
-      if (yyn != YYPACT_NINF)
-       {
-         yyn += YYTERROR;
-         if (0 <= yyn && yyn <= YYLAST && yycheck[yyn] == YYTERROR)
-           {
-             yyn = yytable[yyn];
-             if (0 < yyn)
-               break;
-           }
-       }
-
-      /* Pop the current state because it cannot handle the error token.  */
-      if (yyssp == yyss)
-       YYABORT;
-
-
-      yydestruct ("Error: popping",
-                 yystos[yystate], yyvsp);
-      YYPOPSTACK (1);
-      yystate = *yyssp;
-      YY_STACK_PRINT (yyss, yyssp);
-    }
-
-  if (yyn == YYFINAL)
-    YYACCEPT;
-
-  *++yyvsp = yylval;
-
-
-  /* Shift the error token.  */
-  YY_SYMBOL_PRINT ("Shifting", yystos[yyn], yyvsp, yylsp);
-
-  yystate = yyn;
-  goto yynewstate;
-
-
-/*-------------------------------------.
-| yyacceptlab -- YYACCEPT comes here.  |
-`-------------------------------------*/
-yyacceptlab:
-  yyresult = 0;
-  goto yyreturn;
-
-/*-----------------------------------.
-| yyabortlab -- YYABORT comes here.  |
-`-----------------------------------*/
-yyabortlab:
-  yyresult = 1;
-  goto yyreturn;
-
-#ifndef yyoverflow
-/*-------------------------------------------------.
-| yyexhaustedlab -- memory exhaustion comes here.  |
-`-------------------------------------------------*/
-yyexhaustedlab:
-  yyerror (YY_("memory exhausted"));
-  yyresult = 2;
-  /* Fall through.  */
-#endif
-
-yyreturn:
-  if (yychar != YYEOF && yychar != YYEMPTY)
-     yydestruct ("Cleanup: discarding lookahead",
-                yytoken, &yylval);
-  /* Do not reclaim the symbols of the rule which action triggered
-     this YYABORT or YYACCEPT.  */
-  YYPOPSTACK (yylen);
-  YY_STACK_PRINT (yyss, yyssp);
-  while (yyssp != yyss)
-    {
-      yydestruct ("Cleanup: popping",
-                 yystos[*yyssp], yyvsp);
-      YYPOPSTACK (1);
-    }
-#ifndef yyoverflow
-  if (yyss != yyssa)
-    YYSTACK_FREE (yyss);
-#endif
-#if YYERROR_VERBOSE
-  if (yymsg != yymsgbuf)
-    YYSTACK_FREE (yymsg);
-#endif
-  /* Make sure YYID is used.  */
-  return YYID (yyresult);
-}
-
-
-
diff --git a/src/cmd/8a/y.tab.h b/src/cmd/8a/y.tab.h
deleted file mode 100644 (file)
index 3ab1bfa..0000000
+++ /dev/null
@@ -1,135 +0,0 @@
-/* A Bison parser, made by GNU Bison 2.3.  */
-
-/* Skeleton interface for Bison's Yacc-like parsers in C
-
-   Copyright (C) 1984, 1989, 1990, 2000, 2001, 2002, 2003, 2004, 2005, 2006
-   Free Software Foundation, Inc.
-
-   This program is free software; you can redistribute it and/or modify
-   it under the terms of the GNU General Public License as published by
-   the Free Software Foundation; either version 2, or (at your option)
-   any later version.
-
-   This program is distributed in the hope that it will be useful,
-   but WITHOUT ANY WARRANTY; without even the implied warranty of
-   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-   GNU General Public License for more details.
-
-   You should have received a copy of the GNU General Public License
-   along with this program; if not, write to the Free Software
-   Foundation, Inc., 51 Franklin Street, Fifth Floor,
-   Boston, MA 02110-1301, USA.  */
-
-/* As a special exception, you may create a larger work that contains
-   part or all of the Bison parser skeleton and distribute that work
-   under terms of your choice, so long as that work isn't itself a
-   parser generator using the skeleton or a modified version thereof
-   as a parser skeleton.  Alternatively, if you modify or redistribute
-   the parser skeleton itself, you may (at your option) remove this
-   special exception, which will cause the skeleton and the resulting
-   Bison output files to be licensed under the GNU General Public
-   License without this special exception.
-
-   This special exception was added by the Free Software Foundation in
-   version 2.2 of Bison.  */
-
-/* Tokens.  */
-#ifndef YYTOKENTYPE
-# define YYTOKENTYPE
-   /* Put the tokens into the symbol table, so that GDB and other debuggers
-      know about them.  */
-   enum yytokentype {
-     LTYPE0 = 258,
-     LTYPE1 = 259,
-     LTYPE2 = 260,
-     LTYPE3 = 261,
-     LTYPE4 = 262,
-     LTYPEC = 263,
-     LTYPED = 264,
-     LTYPEN = 265,
-     LTYPER = 266,
-     LTYPET = 267,
-     LTYPES = 268,
-     LTYPEM = 269,
-     LTYPEI = 270,
-     LTYPEG = 271,
-     LTYPEXC = 272,
-     LTYPEX = 273,
-     LTYPEPC = 274,
-     LTYPEF = 275,
-     LCONST = 276,
-     LFP = 277,
-     LPC = 278,
-     LSB = 279,
-     LBREG = 280,
-     LLREG = 281,
-     LSREG = 282,
-     LFREG = 283,
-     LXREG = 284,
-     LFCONST = 285,
-     LSCONST = 286,
-     LSP = 287,
-     LNAME = 288,
-     LLAB = 289,
-     LVAR = 290
-   };
-#endif
-/* Tokens.  */
-#define LTYPE0 258
-#define LTYPE1 259
-#define LTYPE2 260
-#define LTYPE3 261
-#define LTYPE4 262
-#define LTYPEC 263
-#define LTYPED 264
-#define LTYPEN 265
-#define LTYPER 266
-#define LTYPET 267
-#define LTYPES 268
-#define LTYPEM 269
-#define LTYPEI 270
-#define LTYPEG 271
-#define LTYPEXC 272
-#define LTYPEX 273
-#define LTYPEPC 274
-#define LTYPEF 275
-#define LCONST 276
-#define LFP 277
-#define LPC 278
-#define LSB 279
-#define LBREG 280
-#define LLREG 281
-#define LSREG 282
-#define LFREG 283
-#define LXREG 284
-#define LFCONST 285
-#define LSCONST 286
-#define LSP 287
-#define LNAME 288
-#define LLAB 289
-#define LVAR 290
-
-
-
-
-#if ! defined YYSTYPE && ! defined YYSTYPE_IS_DECLARED
-typedef union YYSTYPE
-#line 38 "a.y"
-{
-       Sym     *sym;
-       int32   lval;
-       double  dval;
-       char    sval[8];
-       Addr    addr;
-       Addr2   addr2;
-}
-/* Line 1529 of yacc.c.  */
-#line 128 "y.tab.h"
-       YYSTYPE;
-# define yystype YYSTYPE /* obsolescent; will be withdrawn */
-# define YYSTYPE_IS_DECLARED 1
-# define YYSTYPE_IS_TRIVIAL 1
-#endif
-
-extern YYSTYPE yylval;
-
diff --git a/src/cmd/8g/Makefile b/src/cmd/8g/Makefile
deleted file mode 100644 (file)
index 3f528d7..0000000
+++ /dev/null
@@ -1,5 +0,0 @@
-# Copyright 2012 The Go Authors. All rights reserved.
-# Use of this source code is governed by a BSD-style
-# license that can be found in the LICENSE file.
-
-include ../../Make.dist
diff --git a/src/cmd/8g/cgen.c b/src/cmd/8g/cgen.c
deleted file mode 100644 (file)
index f06927c..0000000
+++ /dev/null
@@ -1,1590 +0,0 @@
-// Copyright 2009 The Go Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style
-// license that can be found in the LICENSE file.
-
-// TODO(rsc):
-//     assume CLD?
-
-#include <u.h>
-#include <libc.h>
-#include "gg.h"
-
-void
-mgen(Node *n, Node *n1, Node *rg)
-{
-       Node n2;
-
-       n1->op = OEMPTY;
-
-       if(n->addable) {
-               *n1 = *n;
-               if(n1->op == OREGISTER || n1->op == OINDREG)
-                       reg[n->val.u.reg]++;
-               return;
-       }
-       tempname(n1, n->type);
-       cgen(n, n1);
-       if(n->type->width <= widthptr || isfloat[n->type->etype]) {
-               n2 = *n1;
-               regalloc(n1, n->type, rg);
-               gmove(&n2, n1);
-       }
-}
-
-void
-mfree(Node *n)
-{
-       if(n->op == OREGISTER)
-               regfree(n);
-}
-
-/*
- * generate:
- *     res = n;
- * simplifies and calls gmove.
- *
- * TODO:
- *     sudoaddable
- */
-void
-cgen(Node *n, Node *res)
-{
-       Node *nl, *nr, *r, n1, n2, nt;
-       Prog *p1, *p2, *p3;
-       int a;
-
-       if(debug['g']) {
-               dump("\ncgen-n", n);
-               dump("cgen-res", res);
-       }
-
-       if(n == N || n->type == T)
-               fatal("cgen: n nil");
-       if(res == N || res->type == T)
-               fatal("cgen: res nil");
-
-       switch(n->op) {
-       case OSLICE:
-       case OSLICEARR:
-       case OSLICESTR:
-       case OSLICE3:
-       case OSLICE3ARR:
-               if (res->op != ONAME || !res->addable) {
-                       tempname(&n1, n->type);
-                       cgen_slice(n, &n1);
-                       cgen(&n1, res);
-               } else
-                       cgen_slice(n, res);
-               return;
-       case OEFACE:
-               if (res->op != ONAME || !res->addable) {
-                       tempname(&n1, n->type);
-                       cgen_eface(n, &n1);
-                       cgen(&n1, res);
-               } else
-                       cgen_eface(n, res);
-               return;
-       }
-
-       while(n->op == OCONVNOP)
-               n = n->left;
-
-       // function calls on both sides?  introduce temporary
-       if(n->ullman >= UINF && res->ullman >= UINF) {
-               tempname(&n1, n->type);
-               cgen(n, &n1);
-               cgen(&n1, res);
-               return;
-       }
-
-       // structs etc get handled specially
-       if(isfat(n->type)) {
-               if(n->type->width < 0)
-                       fatal("forgot to compute width for %T", n->type);
-               sgen(n, res, n->type->width);
-               return;
-       }
-
-       // update addressability for string, slice
-       // can't do in walk because n->left->addable
-       // changes if n->left is an escaping local variable.
-       switch(n->op) {
-       case OSPTR:
-       case OLEN:
-               if(isslice(n->left->type) || istype(n->left->type, TSTRING))
-                       n->addable = n->left->addable;
-               break;
-       case OCAP:
-               if(isslice(n->left->type))
-                       n->addable = n->left->addable;
-               break;
-       case OITAB:
-               n->addable = n->left->addable;
-               break;
-       }
-
-       // if both are addressable, move
-       if(n->addable && res->addable) {
-               gmove(n, res);
-               return;
-       }
-
-       // if both are not addressable, use a temporary.
-       if(!n->addable && !res->addable) {
-               // could use regalloc here sometimes,
-               // but have to check for ullman >= UINF.
-               tempname(&n1, n->type);
-               cgen(n, &n1);
-               cgen(&n1, res);
-               return;
-       }
-
-       // if result is not addressable directly but n is,
-       // compute its address and then store via the address.
-       if(!res->addable) {
-               igen(res, &n1, N);
-               cgen(n, &n1);
-               regfree(&n1);
-               return;
-       }
-
-       // complex types
-       if(complexop(n, res)) {
-               complexgen(n, res);
-               return;
-       }
-
-       // otherwise, the result is addressable but n is not.
-       // let's do some computation.
-
-       // use ullman to pick operand to eval first.
-       nl = n->left;
-       nr = n->right;
-       if(nl != N && nl->ullman >= UINF)
-       if(nr != N && nr->ullman >= UINF) {
-               // both are hard
-               tempname(&n1, nl->type);
-               cgen(nl, &n1);
-               n2 = *n;
-               n2.left = &n1;
-               cgen(&n2, res);
-               return;
-       }
-
-       // 64-bit ops are hard on 32-bit machine.
-       if(is64(n->type) || is64(res->type) || n->left != N && is64(n->left->type)) {
-               switch(n->op) {
-               // math goes to cgen64.
-               case OMINUS:
-               case OCOM:
-               case OADD:
-               case OSUB:
-               case OMUL:
-               case OLROT:
-               case OLSH:
-               case ORSH:
-               case OAND:
-               case OOR:
-               case OXOR:
-                       cgen64(n, res);
-                       return;
-               }
-       }
-
-       if(nl != N && isfloat[n->type->etype] && isfloat[nl->type->etype]) {
-               cgen_float(n, res);
-               return;
-       }
-
-       switch(n->op) {
-       default:
-               dump("cgen", n);
-               fatal("cgen %O", n->op);
-               break;
-
-       case OREAL:
-       case OIMAG:
-       case OCOMPLEX:
-               fatal("unexpected complex");
-               return;
-
-       // these call bgen to get a bool value
-       case OOROR:
-       case OANDAND:
-       case OEQ:
-       case ONE:
-       case OLT:
-       case OLE:
-       case OGE:
-       case OGT:
-       case ONOT:
-               p1 = gbranch(AJMP, T, 0);
-               p2 = pc;
-               gmove(nodbool(1), res);
-               p3 = gbranch(AJMP, T, 0);
-               patch(p1, pc);
-               bgen(n, 1, 0, p2);
-               gmove(nodbool(0), res);
-               patch(p3, pc);
-               return;
-
-       case OPLUS:
-               cgen(nl, res);
-               return;
-
-       case OMINUS:
-       case OCOM:
-               a = optoas(n->op, nl->type);
-               goto uop;
-
-       // symmetric binary
-       case OAND:
-       case OOR:
-       case OXOR:
-       case OADD:
-       case OMUL:
-               a = optoas(n->op, nl->type);
-               if(a == AIMULB) {
-                       cgen_bmul(n->op, nl, nr, res);
-                       break;
-               }
-               goto sbop;
-
-       // asymmetric binary
-       case OSUB:
-               a = optoas(n->op, nl->type);
-               goto abop;
-
-       case OHMUL:
-               cgen_hmul(nl, nr, res);
-               break;
-
-       case OCONV:
-               if(eqtype(n->type, nl->type) || noconv(n->type, nl->type)) {
-                       cgen(nl, res);
-                       break;
-               }
-
-               tempname(&n2, n->type);
-               mgen(nl, &n1, res);
-               gmove(&n1, &n2);
-               gmove(&n2, res);
-               mfree(&n1);
-               break;
-
-       case ODOT:
-       case ODOTPTR:
-       case OINDEX:
-       case OIND:
-       case ONAME:     // PHEAP or PPARAMREF var
-               igen(n, &n1, res);
-               gmove(&n1, res);
-               regfree(&n1);
-               break;
-
-       case OITAB:
-               igen(nl, &n1, res);
-               n1.type = ptrto(types[TUINTPTR]);
-               gmove(&n1, res);
-               regfree(&n1);
-               break;
-
-       case OSPTR:
-               // pointer is the first word of string or slice.
-               if(isconst(nl, CTSTR)) {
-                       regalloc(&n1, types[tptr], res);
-                       p1 = gins(ALEAL, N, &n1);
-                       datastring(nl->val.u.sval->s, nl->val.u.sval->len, &p1->from);
-                       gmove(&n1, res);
-                       regfree(&n1);
-                       break;
-               }
-               igen(nl, &n1, res);
-               n1.type = n->type;
-               gmove(&n1, res);
-               regfree(&n1);
-               break;
-
-       case OLEN:
-               if(istype(nl->type, TMAP) || istype(nl->type, TCHAN)) {
-                       // map has len in the first 32-bit word.
-                       // a zero pointer means zero length
-                       tempname(&n1, types[tptr]);
-                       cgen(nl, &n1);
-                       regalloc(&n2, types[tptr], N);
-                       gmove(&n1, &n2);
-                       n1 = n2;
-
-                       nodconst(&n2, types[tptr], 0);
-                       gins(optoas(OCMP, types[tptr]), &n1, &n2);
-                       p1 = gbranch(optoas(OEQ, types[tptr]), T, -1);
-
-                       n2 = n1;
-                       n2.op = OINDREG;
-                       n2.type = types[TINT32];
-                       gmove(&n2, &n1);
-
-                       patch(p1, pc);
-
-                       gmove(&n1, res);
-                       regfree(&n1);
-                       break;
-               }
-               if(istype(nl->type, TSTRING) || isslice(nl->type)) {
-                       // both slice and string have len one pointer into the struct.
-                       igen(nl, &n1, res);
-                       n1.type = types[TUINT32];
-                       n1.xoffset += Array_nel;
-                       gmove(&n1, res);
-                       regfree(&n1);
-                       break;
-               }
-               fatal("cgen: OLEN: unknown type %lT", nl->type);
-               break;
-
-       case OCAP:
-               if(istype(nl->type, TCHAN)) {
-                       // chan has cap in the second 32-bit word.
-                       // a zero pointer means zero length
-                       tempname(&n1, types[tptr]);
-                       cgen(nl, &n1);
-                       regalloc(&n2, types[tptr], N);
-                       gmove(&n1, &n2);
-                       n1 = n2;
-
-                       nodconst(&n2, types[tptr], 0);
-                       gins(optoas(OCMP, types[tptr]), &n1, &n2);
-                       p1 = gbranch(optoas(OEQ, types[tptr]), T, -1);
-
-                       n2 = n1;
-                       n2.op = OINDREG;
-                       n2.xoffset = 4;
-                       n2.type = types[TINT32];
-                       gmove(&n2, &n1);
-
-                       patch(p1, pc);
-
-                       gmove(&n1, res);
-                       regfree(&n1);
-                       break;
-               }
-               if(isslice(nl->type)) {
-                       igen(nl, &n1, res);
-                       n1.type = types[TUINT32];
-                       n1.xoffset += Array_cap;
-                       gmove(&n1, res);
-                       regfree(&n1);
-                       break;
-               }
-               fatal("cgen: OCAP: unknown type %lT", nl->type);
-               break;
-
-       case OADDR:
-               agen(nl, res);
-               break;
-
-       case OCALLMETH:
-               cgen_callmeth(n, 0);
-               cgen_callret(n, res);
-               break;
-
-       case OCALLINTER:
-               cgen_callinter(n, res, 0);
-               cgen_callret(n, res);
-               break;
-
-       case OCALLFUNC:
-               cgen_call(n, 0);
-               cgen_callret(n, res);
-               break;
-
-       case OMOD:
-       case ODIV:
-               cgen_div(n->op, nl, nr, res);
-               break;
-
-       case OLSH:
-       case ORSH:
-       case OLROT:
-               cgen_shift(n->op, n->bounded, nl, nr, res);
-               break;
-       }
-       return;
-
-sbop:  // symmetric binary
-       if(nl->ullman < nr->ullman || nl->op == OLITERAL) {
-               r = nl;
-               nl = nr;
-               nr = r;
-       }
-
-abop:  // asymmetric binary
-       if(smallintconst(nr)) {
-               mgen(nl, &n1, res);
-               regalloc(&n2, nl->type, &n1);
-               gmove(&n1, &n2);
-               gins(a, nr, &n2);
-               gmove(&n2, res);
-               regfree(&n2);
-               mfree(&n1);
-       } else if(nl->ullman >= nr->ullman) {
-               tempname(&nt, nl->type);
-               cgen(nl, &nt);
-               mgen(nr, &n2, N);
-               regalloc(&n1, nl->type, res);
-               gmove(&nt, &n1);
-               gins(a, &n2, &n1);
-               gmove(&n1, res);
-               regfree(&n1);
-               mfree(&n2);
-       } else {
-               regalloc(&n2, nr->type, res);
-               cgen(nr, &n2);
-               regalloc(&n1, nl->type, N);
-               cgen(nl, &n1);
-               gins(a, &n2, &n1);
-               regfree(&n2);
-               gmove(&n1, res);
-               regfree(&n1);
-       }
-       return;
-
-uop:   // unary
-       tempname(&n1, nl->type);
-       cgen(nl, &n1);
-       gins(a, N, &n1);
-       gmove(&n1, res);
-       return;
-}
-
-/*
- * generate an addressable node in res, containing the value of n.
- * n is an array index, and might be any size; res width is <= 32-bit.
- * returns Prog* to patch to panic call.
- */
-static Prog*
-igenindex(Node *n, Node *res, int bounded)
-{
-       Node tmp, lo, hi, zero;
-
-       if(!is64(n->type)) {
-               if(n->addable) {
-                       // nothing to do.
-                       *res = *n;
-               } else {
-                       tempname(res, types[TUINT32]);
-                       cgen(n, res);
-               }
-               return nil;
-       }
-
-       tempname(&tmp, types[TINT64]);
-       cgen(n, &tmp);
-       split64(&tmp, &lo, &hi);
-       tempname(res, types[TUINT32]);
-       gmove(&lo, res);
-       if(bounded) {
-               splitclean();
-               return nil;
-       }
-       nodconst(&zero, types[TINT32], 0);
-       gins(ACMPL, &hi, &zero);
-       splitclean();
-       return gbranch(AJNE, T, +1);
-}
-               
-/*
- * address gen
- *     res = &n;
- * The generated code checks that the result is not nil.
- */
-void
-agen(Node *n, Node *res)
-{
-       Node *nl, *nr;
-       Node n1, n2, n3, tmp, nlen;
-       Type *t;
-       uint32 w;
-       uint64 v;
-       Prog *p1, *p2;
-       int bounded;
-
-       if(debug['g']) {
-               dump("\nagen-res", res);
-               dump("agen-r", n);
-       }
-       if(n == N || n->type == T || res == N || res->type == T)
-               fatal("agen");
-
-       while(n->op == OCONVNOP)
-               n = n->left;
-
-       if(isconst(n, CTNIL) && n->type->width > widthptr) {
-               // Use of a nil interface or nil slice.
-               // Create a temporary we can take the address of and read.
-               // The generated code is just going to panic, so it need not
-               // be terribly efficient. See issue 3670.
-               tempname(&n1, n->type);
-               gvardef(&n1);
-               clearfat(&n1);
-               regalloc(&n2, types[tptr], res);
-               gins(ALEAL, &n1, &n2);
-               gmove(&n2, res);
-               regfree(&n2);
-               return;
-       }
-               
-       // addressable var is easy
-       if(n->addable) {
-               if(n->op == OREGISTER)
-                       fatal("agen OREGISTER");
-               regalloc(&n1, types[tptr], res);
-               gins(ALEAL, n, &n1);
-               gmove(&n1, res);
-               regfree(&n1);
-               return;
-       }
-
-       // let's compute
-       nl = n->left;
-       nr = n->right;
-
-       switch(n->op) {
-       default:
-               fatal("agen %O", n->op);
-
-       case OCALLMETH:
-               cgen_callmeth(n, 0);
-               cgen_aret(n, res);
-               break;
-
-       case OCALLINTER:
-               cgen_callinter(n, res, 0);
-               cgen_aret(n, res);
-               break;
-
-       case OCALLFUNC:
-               cgen_call(n, 0);
-               cgen_aret(n, res);
-               break;
-
-       case OSLICE:
-       case OSLICEARR:
-       case OSLICESTR:
-       case OSLICE3:
-       case OSLICE3ARR:
-               tempname(&n1, n->type);
-               cgen_slice(n, &n1);
-               agen(&n1, res);
-               break;
-
-       case OEFACE:
-               tempname(&n1, n->type);
-               cgen_eface(n, &n1);
-               agen(&n1, res);
-               break;
-
-       case OINDEX:
-               p2 = nil;  // to be patched to panicindex.
-               w = n->type->width;
-               bounded = debug['B'] || n->bounded;
-               if(nr->addable) {
-                       // Generate &nl first, and move nr into register.
-                       if(!isconst(nl, CTSTR))
-                               igen(nl, &n3, res);
-                       if(!isconst(nr, CTINT)) {
-                               p2 = igenindex(nr, &tmp, bounded);
-                               regalloc(&n1, tmp.type, N);
-                               gmove(&tmp, &n1);
-                       }
-               } else if(nl->addable) {
-                       // Generate nr first, and move &nl into register.
-                       if(!isconst(nr, CTINT)) {
-                               p2 = igenindex(nr, &tmp, bounded);
-                               regalloc(&n1, tmp.type, N);
-                               gmove(&tmp, &n1);
-                       }
-                       if(!isconst(nl, CTSTR))
-                               igen(nl, &n3, res);
-               } else {
-                       p2 = igenindex(nr, &tmp, bounded);
-                       nr = &tmp;
-                       if(!isconst(nl, CTSTR))
-                               igen(nl, &n3, res);
-                       regalloc(&n1, tmp.type, N);
-                       gins(optoas(OAS, tmp.type), &tmp, &n1);
-               }
-
-               // For fixed array we really want the pointer in n3.
-               if(isfixedarray(nl->type)) {
-                       regalloc(&n2, types[tptr], &n3);
-                       agen(&n3, &n2);
-                       regfree(&n3);
-                       n3 = n2;
-               }
-
-               // &a[0] is in n3 (allocated in res)
-               // i is in n1 (if not constant)
-               // len(a) is in nlen (if needed)
-               // w is width
-
-               // constant index
-               if(isconst(nr, CTINT)) {
-                       if(isconst(nl, CTSTR))
-                               fatal("constant string constant index");  // front end should handle
-                       v = mpgetfix(nr->val.u.xval);
-                       if(isslice(nl->type) || nl->type->etype == TSTRING) {
-                               if(!debug['B'] && !n->bounded) {
-                                       nlen = n3;
-                                       nlen.type = types[TUINT32];
-                                       nlen.xoffset += Array_nel;
-                                       nodconst(&n2, types[TUINT32], v);
-                                       gins(optoas(OCMP, types[TUINT32]), &nlen, &n2);
-                                       p1 = gbranch(optoas(OGT, types[TUINT32]), T, +1);
-                                       ginscall(panicindex, -1);
-                                       patch(p1, pc);
-                               }
-                       }
-
-                       // Load base pointer in n2 = n3.
-                       regalloc(&n2, types[tptr], &n3);
-                       n3.type = types[tptr];
-                       n3.xoffset += Array_array;
-                       gmove(&n3, &n2);
-                       regfree(&n3);
-                       if (v*w != 0) {
-                               nodconst(&n1, types[tptr], v*w);
-                               gins(optoas(OADD, types[tptr]), &n1, &n2);
-                       }
-                       gmove(&n2, res);
-                       regfree(&n2);
-                       break;
-               }
-
-               // i is in register n1, extend to 32 bits.
-               t = types[TUINT32];
-               if(issigned[n1.type->etype])
-                       t = types[TINT32];
-
-               regalloc(&n2, t, &n1);                  // i
-               gmove(&n1, &n2);
-               regfree(&n1);
-
-               if(!debug['B'] && !n->bounded) {
-                       // check bounds
-                       t = types[TUINT32];
-                       if(isconst(nl, CTSTR)) {
-                               nodconst(&nlen, t, nl->val.u.sval->len);
-                       } else if(isslice(nl->type) || nl->type->etype == TSTRING) {
-                               nlen = n3;
-                               nlen.type = t;
-                               nlen.xoffset += Array_nel;
-                       } else {
-                               nodconst(&nlen, t, nl->type->bound);
-                       }
-                       gins(optoas(OCMP, t), &n2, &nlen);
-                       p1 = gbranch(optoas(OLT, t), T, +1);
-                       if(p2)
-                               patch(p2, pc);
-                       ginscall(panicindex, -1);
-                       patch(p1, pc);
-               }
-
-               if(isconst(nl, CTSTR)) {
-                       regalloc(&n3, types[tptr], res);
-                       p1 = gins(ALEAL, N, &n3);
-                       datastring(nl->val.u.sval->s, nl->val.u.sval->len, &p1->from);
-                       p1->from.scale = 1;
-                       p1->from.index = n2.val.u.reg;
-                       goto indexdone;
-               }
-
-               // Load base pointer in n3.
-               regalloc(&tmp, types[tptr], &n3);
-               if(isslice(nl->type) || nl->type->etype == TSTRING) {
-                       n3.type = types[tptr];
-                       n3.xoffset += Array_array;
-                       gmove(&n3, &tmp);
-               }
-               regfree(&n3);
-               n3 = tmp;
-
-               if(w == 0) {
-                       // nothing to do
-               } else if(w == 1 || w == 2 || w == 4 || w == 8) {
-                       // LEAL (n3)(n2*w), n3
-                       p1 = gins(ALEAL, &n2, &n3);
-                       p1->from.scale = w;
-                       p1->from.type = TYPE_MEM;
-                       p1->from.index = p1->from.reg;
-                       p1->from.reg = p1->to.reg;
-               } else {
-                       nodconst(&tmp, types[TUINT32], w);
-                       gins(optoas(OMUL, types[TUINT32]), &tmp, &n2);
-                       gins(optoas(OADD, types[tptr]), &n2, &n3);
-               }
-
-       indexdone:
-               gmove(&n3, res);
-               regfree(&n2);
-               regfree(&n3);
-               break;
-
-       case ONAME:
-               // should only get here with names in this func.
-               if(n->funcdepth > 0 && n->funcdepth != funcdepth) {
-                       dump("bad agen", n);
-                       fatal("agen: bad ONAME funcdepth %d != %d",
-                               n->funcdepth, funcdepth);
-               }
-
-               // should only get here for heap vars or paramref
-               if(!(n->class & PHEAP) && n->class != PPARAMREF) {
-                       dump("bad agen", n);
-                       fatal("agen: bad ONAME class %#x", n->class);
-               }
-               cgen(n->heapaddr, res);
-               if(n->xoffset != 0) {
-                       nodconst(&n1, types[tptr], n->xoffset);
-                       gins(optoas(OADD, types[tptr]), &n1, res);
-               }
-               break;
-
-       case OIND:
-               cgen(nl, res);
-               cgen_checknil(res);
-               break;
-
-       case ODOT:
-               agen(nl, res);
-               if(n->xoffset != 0) {
-                       nodconst(&n1, types[tptr], n->xoffset);
-                       gins(optoas(OADD, types[tptr]), &n1, res);
-               }
-               break;
-
-       case ODOTPTR:
-               t = nl->type;
-               if(!isptr[t->etype])
-                       fatal("agen: not ptr %N", n);
-               cgen(nl, res);
-               cgen_checknil(res);
-               if(n->xoffset != 0) {
-                       nodconst(&n1, types[tptr], n->xoffset);
-                       gins(optoas(OADD, types[tptr]), &n1, res);
-               }
-               break;
-       }
-}
-
-/*
- * generate:
- *     newreg = &n;
- *     res = newreg
- *
- * on exit, a has been changed to be *newreg.
- * caller must regfree(a).
- * The generated code checks that the result is not *nil.
- */
-void
-igen(Node *n, Node *a, Node *res)
-{
-       Type *fp;
-       Iter flist;
-       Node n1;
-
-       if(debug['g']) {
-               dump("\nigen-n", n);
-       }
-       switch(n->op) {
-       case ONAME:
-               if((n->class&PHEAP) || n->class == PPARAMREF)
-                       break;
-               *a = *n;
-               return;
-
-       case OINDREG:
-               // Increase the refcount of the register so that igen's caller
-               // has to call regfree.
-               if(n->val.u.reg != REG_SP)
-                       reg[n->val.u.reg]++;
-               *a = *n;
-               return;
-
-       case ODOT:
-               igen(n->left, a, res);
-               a->xoffset += n->xoffset;
-               a->type = n->type;
-               return;
-
-       case ODOTPTR:
-               switch(n->left->op) {
-               case ODOT:
-               case ODOTPTR:
-               case OCALLFUNC:
-               case OCALLMETH:
-               case OCALLINTER:
-                       // igen-able nodes.
-                       igen(n->left, &n1, res);
-                       regalloc(a, types[tptr], &n1);
-                       gmove(&n1, a);
-                       regfree(&n1);
-                       break;
-               default:
-                       regalloc(a, types[tptr], res);
-                       cgen(n->left, a);
-               }
-               cgen_checknil(a);
-               a->op = OINDREG;
-               a->xoffset += n->xoffset;
-               a->type = n->type;
-               return;
-
-       case OCALLFUNC:
-       case OCALLMETH:
-       case OCALLINTER:
-               switch(n->op) {
-               case OCALLFUNC:
-                       cgen_call(n, 0);
-                       break;
-               case OCALLMETH:
-                       cgen_callmeth(n, 0);
-                       break;
-               case OCALLINTER:
-                       cgen_callinter(n, N, 0);
-                       break;
-               }
-               fp = structfirst(&flist, getoutarg(n->left->type));
-               memset(a, 0, sizeof *a);
-               a->op = OINDREG;
-               a->val.u.reg = REG_SP;
-               a->addable = 1;
-               a->xoffset = fp->width;
-               a->type = n->type;
-               return;
-
-       case OINDEX:
-               // Index of fixed-size array by constant can
-               // put the offset in the addressing.
-               // Could do the same for slice except that we need
-               // to use the real index for the bounds checking.
-               if(isfixedarray(n->left->type) ||
-                  (isptr[n->left->type->etype] && isfixedarray(n->left->left->type)))
-               if(isconst(n->right, CTINT)) {
-                       // Compute &a.
-                       if(!isptr[n->left->type->etype])
-                               igen(n->left, a, res);
-                       else {
-                               igen(n->left, &n1, res);
-                               cgen_checknil(&n1);
-                               regalloc(a, types[tptr], res);
-                               gmove(&n1, a);
-                               regfree(&n1);
-                               a->op = OINDREG;
-                       }
-
-                       // Compute &a[i] as &a + i*width.
-                       a->type = n->type;
-                       a->xoffset += mpgetfix(n->right->val.u.xval)*n->type->width;
-                       return;
-               }
-               break;
-       }
-
-       // release register for now, to avoid
-       // confusing tempname.
-       if(res != N && res->op == OREGISTER)
-               reg[res->val.u.reg]--;
-       tempname(&n1, types[tptr]);
-       agen(n, &n1);
-       if(res != N && res->op == OREGISTER)
-               reg[res->val.u.reg]++;
-       regalloc(a, types[tptr], res);
-       gmove(&n1, a);
-       a->op = OINDREG;
-       a->type = n->type;
-}
-
-/*
- * branch gen
- *     if(n == true) goto to;
- */
-void
-bgen(Node *n, int true, int likely, Prog *to)
-{
-       int et, a;
-       Node *nl, *nr, *r;
-       Node n1, n2, tmp;
-       Prog *p1, *p2;
-
-       if(debug['g']) {
-               dump("\nbgen", n);
-       }
-
-       if(n == N)
-               n = nodbool(1);
-
-       if(n->ninit != nil)
-               genlist(n->ninit);
-
-       if(n->type == T) {
-               convlit(&n, types[TBOOL]);
-               if(n->type == T)
-                       return;
-       }
-
-       et = n->type->etype;
-       if(et != TBOOL) {
-               yyerror("cgen: bad type %T for %O", n->type, n->op);
-               patch(gins(AEND, N, N), to);
-               return;
-       }
-
-       while(n->op == OCONVNOP) {
-               n = n->left;
-               if(n->ninit != nil)
-                       genlist(n->ninit);
-       }
-
-       nl = n->left;
-       nr = N;
-
-       if(nl != N && isfloat[nl->type->etype]) {
-               bgen_float(n, true, likely, to);
-               return;
-       }
-
-       switch(n->op) {
-       default:
-               goto def;
-
-       case OLITERAL:
-               // need to ask if it is bool?
-               if(!true == !n->val.u.bval)
-                       patch(gbranch(AJMP, T, 0), to);
-               return;
-
-       case ONAME:
-               if(!n->addable)
-                       goto def;
-               nodconst(&n1, n->type, 0);
-               gins(optoas(OCMP, n->type), n, &n1);
-               a = AJNE;
-               if(!true)
-                       a = AJEQ;
-               patch(gbranch(a, n->type, likely), to);
-               return;
-
-       case OANDAND:
-       case OOROR:
-               if((n->op == OANDAND) == true) {
-                       p1 = gbranch(AJMP, T, 0);
-                       p2 = gbranch(AJMP, T, 0);
-                       patch(p1, pc);
-                       bgen(n->left, !true, -likely, p2);
-                       bgen(n->right, !true, -likely, p2);
-                       p1 = gbranch(AJMP, T, 0);
-                       patch(p1, to);
-                       patch(p2, pc);
-               } else {
-                       bgen(n->left, true, likely, to);
-                       bgen(n->right, true, likely, to);
-               }
-               return;
-
-       case OEQ:
-       case ONE:
-       case OLT:
-       case OGT:
-       case OLE:
-       case OGE:
-               nr = n->right;
-               if(nr == N || nr->type == T)
-                       return;
-
-       case ONOT:      // unary
-               nl = n->left;
-               if(nl == N || nl->type == T)
-                       return;
-       }
-
-       switch(n->op) {
-       case ONOT:
-               bgen(nl, !true, likely, to);
-               break;
-
-       case OEQ:
-       case ONE:
-       case OLT:
-       case OGT:
-       case OLE:
-       case OGE:
-               a = n->op;
-               if(!true) {
-                       a = brcom(a);
-                       true = !true;
-               }
-
-               // make simplest on right
-               if(nl->op == OLITERAL || (nl->ullman < nr->ullman && nl->ullman < UINF)) {
-                       a = brrev(a);
-                       r = nl;
-                       nl = nr;
-                       nr = r;
-               }
-
-               if(isslice(nl->type)) {
-                       // front end should only leave cmp to literal nil
-                       if((a != OEQ && a != ONE) || nr->op != OLITERAL) {
-                               yyerror("illegal slice comparison");
-                               break;
-                       }
-                       a = optoas(a, types[tptr]);
-                       igen(nl, &n1, N);
-                       n1.xoffset += Array_array;
-                       n1.type = types[tptr];
-                       nodconst(&tmp, types[tptr], 0);
-                       gins(optoas(OCMP, types[tptr]), &n1, &tmp);
-                       patch(gbranch(a, types[tptr], likely), to);
-                       regfree(&n1);
-                       break;
-               }
-
-               if(isinter(nl->type)) {
-                       // front end should only leave cmp to literal nil
-                       if((a != OEQ && a != ONE) || nr->op != OLITERAL) {
-                               yyerror("illegal interface comparison");
-                               break;
-                       }
-                       a = optoas(a, types[tptr]);
-                       igen(nl, &n1, N);
-                       n1.type = types[tptr];
-                       nodconst(&tmp, types[tptr], 0);
-                       gins(optoas(OCMP, types[tptr]), &n1, &tmp);
-                       patch(gbranch(a, types[tptr], likely), to);
-                       regfree(&n1);
-                       break;
-               }
-
-               if(iscomplex[nl->type->etype]) {
-                       complexbool(a, nl, nr, true, likely, to);
-                       break;
-               }
-
-               if(is64(nr->type)) {
-                       if(!nl->addable || isconst(nl, CTINT)) {
-                               tempname(&n1, nl->type);
-                               cgen(nl, &n1);
-                               nl = &n1;
-                       }
-                       if(!nr->addable) {
-                               tempname(&n2, nr->type);
-                               cgen(nr, &n2);
-                               nr = &n2;
-                       }
-                       cmp64(nl, nr, a, likely, to);
-                       break;
-               }
-
-               if(nr->ullman >= UINF) {
-                       if(!nl->addable) {
-                               tempname(&n1, nl->type);
-                               cgen(nl, &n1);
-                               nl = &n1;
-                       }
-                       if(!nr->addable) {
-                               tempname(&tmp, nr->type);
-                               cgen(nr, &tmp);
-                               nr = &tmp;
-                       }
-                       regalloc(&n2, nr->type, N);
-                       cgen(nr, &n2);
-                       nr = &n2;
-                       goto cmp;
-               }
-
-               if(!nl->addable) {
-                       tempname(&n1, nl->type);
-                       cgen(nl, &n1);
-                       nl = &n1;
-               }
-
-               if(smallintconst(nr)) {
-                       gins(optoas(OCMP, nr->type), nl, nr);
-                       patch(gbranch(optoas(a, nr->type), nr->type, likely), to);
-                       break;
-               }
-
-               if(!nr->addable) {
-                       tempname(&tmp, nr->type);
-                       cgen(nr, &tmp);
-                       nr = &tmp;
-               }
-               regalloc(&n2, nr->type, N);
-               gmove(nr, &n2);
-               nr = &n2;
-
-cmp:
-               gins(optoas(OCMP, nr->type), nl, nr);
-               patch(gbranch(optoas(a, nr->type), nr->type, likely), to);
-
-               if(nl->op == OREGISTER)
-                       regfree(nl);
-               regfree(nr);
-               break;
-       }
-       return;
-
-def:
-       regalloc(&n1, n->type, N);
-       cgen(n, &n1);
-       nodconst(&n2, n->type, 0);
-       gins(optoas(OCMP, n->type), &n1, &n2);
-       a = AJNE;
-       if(!true)
-               a = AJEQ;
-       patch(gbranch(a, n->type, likely), to);
-       regfree(&n1);
-       return;
-}
-
-/*
- * n is on stack, either local variable
- * or return value from function call.
- * return n's offset from SP.
- */
-int32
-stkof(Node *n)
-{
-       Type *t;
-       Iter flist;
-       int32 off;
-
-       switch(n->op) {
-       case OINDREG:
-               return n->xoffset;
-
-       case ODOT:
-               t = n->left->type;
-               if(isptr[t->etype])
-                       break;
-               off = stkof(n->left);
-               if(off == -1000 || off == 1000)
-                       return off;
-               return off + n->xoffset;
-
-       case OINDEX:
-               t = n->left->type;
-               if(!isfixedarray(t))
-                       break;
-               off = stkof(n->left);
-               if(off == -1000 || off == 1000)
-                       return off;
-               if(isconst(n->right, CTINT))
-                       return off + t->type->width * mpgetfix(n->right->val.u.xval);
-               return 1000;
-               
-       case OCALLMETH:
-       case OCALLINTER:
-       case OCALLFUNC:
-               t = n->left->type;
-               if(isptr[t->etype])
-                       t = t->type;
-
-               t = structfirst(&flist, getoutarg(t));
-               if(t != T)
-                       return t->width;
-               break;
-       }
-
-       // botch - probably failing to recognize address
-       // arithmetic on the above. eg INDEX and DOT
-       return -1000;
-}
-
-/*
- * struct gen
- *     memmove(&res, &n, w);
- */
-void
-sgen(Node *n, Node *res, int64 w)
-{
-       Node dst, src, tdst, tsrc, cx;
-       int32 c, q, odst, osrc;
-       NodeList *l;
-       Prog *p;
-
-       if(debug['g']) {
-               print("\nsgen w=%lld\n", w);
-               dump("r", n);
-               dump("res", res);
-       }
-       if(n->ullman >= UINF && res->ullman >= UINF)
-               fatal("sgen UINF");
-
-       if(w < 0 || (int32)w != w)
-               fatal("sgen copy %lld", w);
-
-       if(w == 0) {
-               // evaluate side effects only.
-               tempname(&tdst, types[tptr]);
-               agen(res, &tdst);
-               agen(n, &tdst);
-               return;
-       }
-
-       // If copying .args, that's all the results, so record definition sites
-       // for them for the liveness analysis.
-       if(res->op == ONAME && strcmp(res->sym->name, ".args") == 0)
-               for(l = curfn->dcl; l != nil; l = l->next)
-                       if(l->n->class == PPARAMOUT)
-                               gvardef(l->n);
-
-       // Avoid taking the address for simple enough types.
-       if(componentgen(n, res))
-               return;
-
-       // offset on the stack
-       osrc = stkof(n);
-       odst = stkof(res);
-       
-       if(osrc != -1000 && odst != -1000 && (osrc == 1000 || odst == 1000)) {
-               // osrc and odst both on stack, and at least one is in
-               // an unknown position.  Could generate code to test
-               // for forward/backward copy, but instead just copy
-               // to a temporary location first.
-               tempname(&tsrc, n->type);
-               sgen(n, &tsrc, w);
-               sgen(&tsrc, res, w);
-               return;
-       }
-
-       nodreg(&dst, types[tptr], REG_DI);
-       nodreg(&src, types[tptr], REG_SI);
-
-       tempname(&tsrc, types[tptr]);
-       tempname(&tdst, types[tptr]);
-       if(!n->addable)
-               agen(n, &tsrc);
-       if(!res->addable)
-               agen(res, &tdst);
-       if(n->addable)
-               agen(n, &src);
-       else
-               gmove(&tsrc, &src);
-
-       if(res->op == ONAME)
-               gvardef(res);
-
-       if(res->addable)
-               agen(res, &dst);
-       else
-               gmove(&tdst, &dst);
-
-       c = w % 4;      // bytes
-       q = w / 4;      // doublewords
-
-       // if we are copying forward on the stack and
-       // the src and dst overlap, then reverse direction
-       if(osrc < odst && odst < osrc+w) {
-               // reverse direction
-               gins(ASTD, N, N);               // set direction flag
-               if(c > 0) {
-                       gconreg(AADDL, w-1, REG_SI);
-                       gconreg(AADDL, w-1, REG_DI);
-
-                       gconreg(AMOVL, c, REG_CX);
-                       gins(AREP, N, N);       // repeat
-                       gins(AMOVSB, N, N);     // MOVB *(SI)-,*(DI)-
-               }
-
-               if(q > 0) {
-                       if(c > 0) {
-                               gconreg(AADDL, -3, REG_SI);
-                               gconreg(AADDL, -3, REG_DI);
-                       } else {
-                               gconreg(AADDL, w-4, REG_SI);
-                               gconreg(AADDL, w-4, REG_DI);
-                       }
-                       gconreg(AMOVL, q, REG_CX);
-                       gins(AREP, N, N);       // repeat
-                       gins(AMOVSL, N, N);     // MOVL *(SI)-,*(DI)-
-               }
-               // we leave with the flag clear
-               gins(ACLD, N, N);
-       } else {
-               gins(ACLD, N, N);       // paranoia.  TODO(rsc): remove?
-               // normal direction
-               if(q > 128 || (q >= 4 && nacl)) {
-                       gconreg(AMOVL, q, REG_CX);
-                       gins(AREP, N, N);       // repeat
-                       gins(AMOVSL, N, N);     // MOVL *(SI)+,*(DI)+
-               } else if(q >= 4) {
-                       p = gins(ADUFFCOPY, N, N);
-                       p->to.type = TYPE_ADDR;
-                       p->to.sym = linksym(pkglookup("duffcopy", runtimepkg));
-                       // 10 and 128 = magic constants: see ../../runtime/asm_386.s
-                       p->to.offset = 10*(128-q);
-               } else if(!nacl && c == 0) {
-                       nodreg(&cx, types[TINT32], REG_CX);
-                       // We don't need the MOVSL side-effect of updating SI and DI,
-                       // and issuing a sequence of MOVLs directly is faster.
-                       src.op = OINDREG;
-                       dst.op = OINDREG;
-                       while(q > 0) {
-                               gmove(&src, &cx); // MOVL x+(SI),CX
-                               gmove(&cx, &dst); // MOVL CX,x+(DI)
-                               src.xoffset += 4;
-                               dst.xoffset += 4;
-                               q--;
-                       }
-               } else
-               while(q > 0) {
-                       gins(AMOVSL, N, N);     // MOVL *(SI)+,*(DI)+
-                       q--;
-               }
-               while(c > 0) {
-                       gins(AMOVSB, N, N);     // MOVB *(SI)+,*(DI)+
-                       c--;
-               }
-       }
-}
-
-static int
-cadable(Node *n)
-{
-       if(!n->addable) {
-               // dont know how it happens,
-               // but it does
-               return 0;
-       }
-
-       switch(n->op) {
-       case ONAME:
-               return 1;
-       }
-       return 0;
-}
-
-/*
- * copy a composite value by moving its individual components.
- * Slices, strings and interfaces are supported.
- * Small structs or arrays with elements of basic type are
- * also supported.
- * nr is N when assigning a zero value.
- * return 1 if can do, 0 if can't.
- */
-int
-componentgen(Node *nr, Node *nl)
-{
-       Node nodl, nodr, tmp;
-       Type *t;
-       int freel, freer;
-       vlong fldcount;
-       vlong loffset, roffset;
-
-       freel = 0;
-       freer = 0;
-
-       switch(nl->type->etype) {
-       default:
-               goto no;
-
-       case TARRAY:
-               t = nl->type;
-
-               // Slices are ok.
-               if(isslice(t))
-                       break;
-               // Small arrays are ok.
-               if(t->bound > 0 && t->bound <= 3 && !isfat(t->type))
-                       break;
-
-               goto no;
-
-       case TSTRUCT:
-               // Small structs with non-fat types are ok.
-               // Zero-sized structs are treated separately elsewhere.
-               fldcount = 0;
-               for(t=nl->type->type; t; t=t->down) {
-                       if(isfat(t->type))
-                               goto no;
-                       if(t->etype != TFIELD)
-                               fatal("componentgen: not a TFIELD: %lT", t);
-                       fldcount++;
-               }
-               if(fldcount == 0 || fldcount > 4)
-                       goto no;
-
-               break;
-
-       case TSTRING:
-       case TINTER:
-               break;
-       }
-
-       nodl = *nl;
-       if(!cadable(nl)) {
-               if(nr != N && !cadable(nr))
-                       goto no;
-               igen(nl, &nodl, N);
-               freel = 1;
-       }
-
-       if(nr != N) {
-               nodr = *nr;
-               if(!cadable(nr)) {
-                       igen(nr, &nodr, N);
-                       freer = 1;
-               }
-       } else {
-               // When zeroing, prepare a register containing zero.
-               nodconst(&tmp, nl->type, 0);
-               regalloc(&nodr, types[TUINT], N);
-               gmove(&tmp, &nodr);
-               freer = 1;
-       }
-       
-       // nl and nr are 'cadable' which basically means they are names (variables) now.
-       // If they are the same variable, don't generate any code, because the
-       // VARDEF we generate will mark the old value as dead incorrectly.
-       // (And also the assignments are useless.)
-       if(nr != N && nl->op == ONAME && nr->op == ONAME && nl == nr)
-               goto yes;
-
-       switch(nl->type->etype) {
-       case TARRAY:
-               // componentgen for arrays.
-               if(nl->op == ONAME)
-                       gvardef(nl);
-               t = nl->type;
-               if(!isslice(t)) {
-                       nodl.type = t->type;
-                       nodr.type = nodl.type;
-                       for(fldcount=0; fldcount < t->bound; fldcount++) {
-                               if(nr == N)
-                                       clearslim(&nodl);
-                               else
-                                       gmove(&nodr, &nodl);
-                               nodl.xoffset += t->type->width;
-                               nodr.xoffset += t->type->width;
-                       }
-                       goto yes;
-               }
-
-               // componentgen for slices.
-               nodl.xoffset += Array_array;
-               nodl.type = ptrto(nl->type->type);
-
-               if(nr != N) {
-                       nodr.xoffset += Array_array;
-                       nodr.type = nodl.type;
-               }
-               gmove(&nodr, &nodl);
-
-               nodl.xoffset += Array_nel-Array_array;
-               nodl.type = types[simtype[TUINT]];
-
-               if(nr != N) {
-                       nodr.xoffset += Array_nel-Array_array;
-                       nodr.type = nodl.type;
-               }
-               gmove(&nodr, &nodl);
-
-               nodl.xoffset += Array_cap-Array_nel;
-               nodl.type = types[simtype[TUINT]];
-
-               if(nr != N) {
-                       nodr.xoffset += Array_cap-Array_nel;
-                       nodr.type = nodl.type;
-               }
-               gmove(&nodr, &nodl);
-
-               goto yes;
-
-       case TSTRING:
-               if(nl->op == ONAME)
-                       gvardef(nl);
-               nodl.xoffset += Array_array;
-               nodl.type = ptrto(types[TUINT8]);
-
-               if(nr != N) {
-                       nodr.xoffset += Array_array;
-                       nodr.type = nodl.type;
-               }
-               gmove(&nodr, &nodl);
-
-               nodl.xoffset += Array_nel-Array_array;
-               nodl.type = types[simtype[TUINT]];
-
-               if(nr != N) {
-                       nodr.xoffset += Array_nel-Array_array;
-                       nodr.type = nodl.type;
-               }
-               gmove(&nodr, &nodl);
-
-               goto yes;
-
-       case TINTER:
-               if(nl->op == ONAME)
-                       gvardef(nl);
-               nodl.xoffset += Array_array;
-               nodl.type = ptrto(types[TUINT8]);
-
-               if(nr != N) {
-                       nodr.xoffset += Array_array;
-                       nodr.type = nodl.type;
-               }
-               gmove(&nodr, &nodl);
-
-               nodl.xoffset += Array_nel-Array_array;
-               nodl.type = ptrto(types[TUINT8]);
-
-               if(nr != N) {
-                       nodr.xoffset += Array_nel-Array_array;
-                       nodr.type = nodl.type;
-               }
-               gmove(&nodr, &nodl);
-
-               goto yes;
-
-       case TSTRUCT:
-               if(nl->op == ONAME)
-                       gvardef(nl);
-               loffset = nodl.xoffset;
-               roffset = nodr.xoffset;
-               // funarg structs may not begin at offset zero.
-               if(nl->type->etype == TSTRUCT && nl->type->funarg && nl->type->type)
-                       loffset -= nl->type->type->width;
-               if(nr != N && nr->type->etype == TSTRUCT && nr->type->funarg && nr->type->type)
-                       roffset -= nr->type->type->width;
-
-               for(t=nl->type->type; t; t=t->down) {
-                       nodl.xoffset = loffset + t->width;
-                       nodl.type = t->type;
-
-                       if(nr == N)
-                               clearslim(&nodl);
-                       else {
-                               nodr.xoffset = roffset + t->width;
-                               nodr.type = nodl.type;
-                               gmove(&nodr, &nodl);
-                       }
-               }
-               goto yes;
-       }
-
-no:
-       if(freer)
-               regfree(&nodr);
-       if(freel)
-               regfree(&nodl);
-       return 0;
-
-yes:
-       if(freer)
-               regfree(&nodr);
-       if(freel)
-               regfree(&nodl);
-       return 1;
-}
similarity index 100%
rename from src/cmd/new8g/cgen.go
rename to src/cmd/8g/cgen.go
diff --git a/src/cmd/8g/cgen64.c b/src/cmd/8g/cgen64.c
deleted file mode 100644 (file)
index d9e812f..0000000
+++ /dev/null
@@ -1,549 +0,0 @@
-// Copyright 2009 The Go Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style
-// license that can be found in the LICENSE file.
-
-#include <u.h>
-#include <libc.h>
-#include "gg.h"
-
-/*
- * attempt to generate 64-bit
- *     res = n
- * return 1 on success, 0 if op not handled.
- */
-void
-cgen64(Node *n, Node *res)
-{
-       Node t1, t2, ax, dx, cx, ex, fx, *l, *r;
-       Node lo1, lo2, hi1, hi2;
-       Prog *p1, *p2;
-       uint64 v;
-       uint32 lv, hv;
-
-       if(res->op != OINDREG && res->op != ONAME) {
-               dump("n", n);
-               dump("res", res);
-               fatal("cgen64 %O of %O", n->op, res->op);
-       }
-       switch(n->op) {
-       default:
-               fatal("cgen64 %O", n->op);
-
-       case OMINUS:
-               cgen(n->left, res);
-               split64(res, &lo1, &hi1);
-               gins(ANEGL, N, &lo1);
-               gins(AADCL, ncon(0), &hi1);
-               gins(ANEGL, N, &hi1);
-               splitclean();
-               return;
-
-       case OCOM:
-               cgen(n->left, res);
-               split64(res, &lo1, &hi1);
-               gins(ANOTL, N, &lo1);
-               gins(ANOTL, N, &hi1);
-               splitclean();
-               return;
-
-       case OADD:
-       case OSUB:
-       case OMUL:
-       case OLROT:
-       case OLSH:
-       case ORSH:
-       case OAND:
-       case OOR:
-       case OXOR:
-               // binary operators.
-               // common setup below.
-               break;
-       }
-
-       l = n->left;
-       r = n->right;
-       if(!l->addable) {
-               tempname(&t1, l->type);
-               cgen(l, &t1);
-               l = &t1;
-       }
-       if(r != N && !r->addable) {
-               tempname(&t2, r->type);
-               cgen(r, &t2);
-               r = &t2;
-       }
-
-       nodreg(&ax, types[TINT32], REG_AX);
-       nodreg(&cx, types[TINT32], REG_CX);
-       nodreg(&dx, types[TINT32], REG_DX);
-
-       // Setup for binary operation.
-       split64(l, &lo1, &hi1);
-       if(is64(r->type))
-               split64(r, &lo2, &hi2);
-
-       // Do op.  Leave result in DX:AX.
-       switch(n->op) {
-       case OADD:
-               // TODO: Constants
-               gins(AMOVL, &lo1, &ax);
-               gins(AMOVL, &hi1, &dx);
-               gins(AADDL, &lo2, &ax);
-               gins(AADCL, &hi2, &dx);
-               break;
-
-       case OSUB:
-               // TODO: Constants.
-               gins(AMOVL, &lo1, &ax);
-               gins(AMOVL, &hi1, &dx);
-               gins(ASUBL, &lo2, &ax);
-               gins(ASBBL, &hi2, &dx);
-               break;
-
-       case OMUL:
-               // let's call the next two EX and FX.
-               regalloc(&ex, types[TPTR32], N);
-               regalloc(&fx, types[TPTR32], N);
-
-               // load args into DX:AX and EX:CX.
-               gins(AMOVL, &lo1, &ax);
-               gins(AMOVL, &hi1, &dx);
-               gins(AMOVL, &lo2, &cx);
-               gins(AMOVL, &hi2, &ex);
-
-               // if DX and EX are zero, use 32 x 32 -> 64 unsigned multiply.
-               gins(AMOVL, &dx, &fx);
-               gins(AORL, &ex, &fx);
-               p1 = gbranch(AJNE, T, 0);
-               gins(AMULL, &cx, N);    // implicit &ax
-               p2 = gbranch(AJMP, T, 0);
-               patch(p1, pc);
-
-               // full 64x64 -> 64, from 32x32 -> 64.
-               gins(AIMULL, &cx, &dx);
-               gins(AMOVL, &ax, &fx);
-               gins(AIMULL, &ex, &fx);
-               gins(AADDL, &dx, &fx);
-               gins(AMOVL, &cx, &dx);
-               gins(AMULL, &dx, N);    // implicit &ax
-               gins(AADDL, &fx, &dx);
-               patch(p2, pc);
-
-               regfree(&ex);
-               regfree(&fx);
-               break;
-       
-       case OLROT:
-               // We only rotate by a constant c in [0,64).
-               // if c >= 32:
-               //      lo, hi = hi, lo
-               //      c -= 32
-               // if c == 0:
-               //      no-op
-               // else:
-               //      t = hi
-               //      shld hi:lo, c
-               //      shld lo:t, c
-               v = mpgetfix(r->val.u.xval);
-               if(v >= 32) {
-                       // reverse during load to do the first 32 bits of rotate
-                       v -= 32;
-                       gins(AMOVL, &lo1, &dx);
-                       gins(AMOVL, &hi1, &ax);
-               } else {
-                       gins(AMOVL, &lo1, &ax);
-                       gins(AMOVL, &hi1, &dx);
-               }
-               if(v == 0) {
-                       // done
-               } else {
-                       gins(AMOVL, &dx, &cx);
-                       p1 = gins(ASHLL, ncon(v), &dx);
-                       p1->from.index = REG_AX;        // double-width shift
-                       p1->from.scale = 0;
-                       p1 = gins(ASHLL, ncon(v), &ax);
-                       p1->from.index = REG_CX;        // double-width shift
-                       p1->from.scale = 0;
-               }
-               break;
-
-       case OLSH:
-               if(r->op == OLITERAL) {
-                       v = mpgetfix(r->val.u.xval);
-                       if(v >= 64) {
-                               if(is64(r->type))
-                                       splitclean();
-                               splitclean();
-                               split64(res, &lo2, &hi2);
-                               gins(AMOVL, ncon(0), &lo2);
-                               gins(AMOVL, ncon(0), &hi2);
-                               splitclean();
-                               goto out;
-                       }
-                       if(v >= 32) {
-                               if(is64(r->type))
-                                       splitclean();
-                               split64(res, &lo2, &hi2);
-                               gmove(&lo1, &hi2);
-                               if(v > 32) {
-                                       gins(ASHLL, ncon(v - 32), &hi2);
-                               }
-                               gins(AMOVL, ncon(0), &lo2);
-                               splitclean();
-                               splitclean();
-                               goto out;
-                       }
-
-                       // general shift
-                       gins(AMOVL, &lo1, &ax);
-                       gins(AMOVL, &hi1, &dx);
-                       p1 = gins(ASHLL, ncon(v), &dx);
-                       p1->from.index = REG_AX;        // double-width shift
-                       p1->from.scale = 0;
-                       gins(ASHLL, ncon(v), &ax);
-                       break;
-               }
-
-               // load value into DX:AX.
-               gins(AMOVL, &lo1, &ax);
-               gins(AMOVL, &hi1, &dx);
-
-               // load shift value into register.
-               // if high bits are set, zero value.
-               p1 = P;
-               if(is64(r->type)) {
-                       gins(ACMPL, &hi2, ncon(0));
-                       p1 = gbranch(AJNE, T, +1);
-                       gins(AMOVL, &lo2, &cx);
-               } else {
-                       cx.type = types[TUINT32];
-                       gmove(r, &cx);
-               }
-
-               // if shift count is >=64, zero value
-               gins(ACMPL, &cx, ncon(64));
-               p2 = gbranch(optoas(OLT, types[TUINT32]), T, +1);
-               if(p1 != P)
-                       patch(p1, pc);
-               gins(AXORL, &dx, &dx);
-               gins(AXORL, &ax, &ax);
-               patch(p2, pc);
-
-               // if shift count is >= 32, zero low.
-               gins(ACMPL, &cx, ncon(32));
-               p1 = gbranch(optoas(OLT, types[TUINT32]), T, +1);
-               gins(AMOVL, &ax, &dx);
-               gins(ASHLL, &cx, &dx);  // SHLL only uses bottom 5 bits of count
-               gins(AXORL, &ax, &ax);
-               p2 = gbranch(AJMP, T, 0);
-               patch(p1, pc);
-
-               // general shift
-               p1 = gins(ASHLL, &cx, &dx);
-               p1->from.index = REG_AX;        // double-width shift
-               p1->from.scale = 0;
-               gins(ASHLL, &cx, &ax);
-               patch(p2, pc);
-               break;
-
-       case ORSH:
-               if(r->op == OLITERAL) {
-                       v = mpgetfix(r->val.u.xval);
-                       if(v >= 64) {
-                               if(is64(r->type))
-                                       splitclean();
-                               splitclean();
-                               split64(res, &lo2, &hi2);
-                               if(hi1.type->etype == TINT32) {
-                                       gmove(&hi1, &lo2);
-                                       gins(ASARL, ncon(31), &lo2);
-                                       gmove(&hi1, &hi2);
-                                       gins(ASARL, ncon(31), &hi2);
-                               } else {
-                                       gins(AMOVL, ncon(0), &lo2);
-                                       gins(AMOVL, ncon(0), &hi2);
-                               }
-                               splitclean();
-                               goto out;
-                       }
-                       if(v >= 32) {
-                               if(is64(r->type))
-                                       splitclean();
-                               split64(res, &lo2, &hi2);
-                               gmove(&hi1, &lo2);
-                               if(v > 32)
-                                       gins(optoas(ORSH, hi1.type), ncon(v-32), &lo2);
-                               if(hi1.type->etype == TINT32) {
-                                       gmove(&hi1, &hi2);
-                                       gins(ASARL, ncon(31), &hi2);
-                               } else
-                                       gins(AMOVL, ncon(0), &hi2);
-                               splitclean();
-                               splitclean();
-                               goto out;
-                       }
-
-                       // general shift
-                       gins(AMOVL, &lo1, &ax);
-                       gins(AMOVL, &hi1, &dx);
-                       p1 = gins(ASHRL, ncon(v), &ax);
-                       p1->from.index = REG_DX;        // double-width shift
-                       p1->from.scale = 0;
-                       gins(optoas(ORSH, hi1.type), ncon(v), &dx);
-                       break;
-               }
-
-               // load value into DX:AX.
-               gins(AMOVL, &lo1, &ax);
-               gins(AMOVL, &hi1, &dx);
-
-               // load shift value into register.
-               // if high bits are set, zero value.
-               p1 = P;
-               if(is64(r->type)) {
-                       gins(ACMPL, &hi2, ncon(0));
-                       p1 = gbranch(AJNE, T, +1);
-                       gins(AMOVL, &lo2, &cx);
-               } else {
-                       cx.type = types[TUINT32];
-                       gmove(r, &cx);
-               }
-
-               // if shift count is >=64, zero or sign-extend value
-               gins(ACMPL, &cx, ncon(64));
-               p2 = gbranch(optoas(OLT, types[TUINT32]), T, +1);
-               if(p1 != P)
-                       patch(p1, pc);
-               if(hi1.type->etype == TINT32) {
-                       gins(ASARL, ncon(31), &dx);
-                       gins(AMOVL, &dx, &ax);
-               } else {
-                       gins(AXORL, &dx, &dx);
-                       gins(AXORL, &ax, &ax);
-               }
-               patch(p2, pc);
-
-               // if shift count is >= 32, sign-extend hi.
-               gins(ACMPL, &cx, ncon(32));
-               p1 = gbranch(optoas(OLT, types[TUINT32]), T, +1);
-               gins(AMOVL, &dx, &ax);
-               if(hi1.type->etype == TINT32) {
-                       gins(ASARL, &cx, &ax);  // SARL only uses bottom 5 bits of count
-                       gins(ASARL, ncon(31), &dx);
-               } else {
-                       gins(ASHRL, &cx, &ax);
-                       gins(AXORL, &dx, &dx);
-               }
-               p2 = gbranch(AJMP, T, 0);
-               patch(p1, pc);
-
-               // general shift
-               p1 = gins(ASHRL, &cx, &ax);
-               p1->from.index = REG_DX;        // double-width shift
-               p1->from.scale = 0;
-               gins(optoas(ORSH, hi1.type), &cx, &dx);
-               patch(p2, pc);
-               break;
-
-       case OXOR:
-       case OAND:
-       case OOR:
-               // make constant the right side (it usually is anyway).
-               if(lo1.op == OLITERAL) {
-                       nswap(&lo1, &lo2);
-                       nswap(&hi1, &hi2);
-               }
-               if(lo2.op == OLITERAL) {
-                       // special cases for constants.
-                       lv = mpgetfix(lo2.val.u.xval);
-                       hv = mpgetfix(hi2.val.u.xval);
-                       splitclean();   // right side
-                       split64(res, &lo2, &hi2);
-                       switch(n->op) {
-                       case OXOR:
-                               gmove(&lo1, &lo2);
-                               gmove(&hi1, &hi2);
-                               switch(lv) {
-                               case 0:
-                                       break;
-                               case 0xffffffffu:
-                                       gins(ANOTL, N, &lo2);
-                                       break;
-                               default:
-                                       gins(AXORL, ncon(lv), &lo2);
-                                       break;
-                               }
-                               switch(hv) {
-                               case 0:
-                                       break;
-                               case 0xffffffffu:
-                                       gins(ANOTL, N, &hi2);
-                                       break;
-                               default:
-                                       gins(AXORL, ncon(hv), &hi2);
-                                       break;
-                               }
-                               break;
-
-                       case OAND:
-                               switch(lv) {
-                               case 0:
-                                       gins(AMOVL, ncon(0), &lo2);
-                                       break;
-                               default:
-                                       gmove(&lo1, &lo2);
-                                       if(lv != 0xffffffffu)
-                                               gins(AANDL, ncon(lv), &lo2);
-                                       break;
-                               }
-                               switch(hv) {
-                               case 0:
-                                       gins(AMOVL, ncon(0), &hi2);
-                                       break;
-                               default:
-                                       gmove(&hi1, &hi2);
-                                       if(hv != 0xffffffffu)
-                                               gins(AANDL, ncon(hv), &hi2);
-                                       break;
-                               }
-                               break;
-
-                       case OOR:
-                               switch(lv) {
-                               case 0:
-                                       gmove(&lo1, &lo2);
-                                       break;
-                               case 0xffffffffu:
-                                       gins(AMOVL, ncon(0xffffffffu), &lo2);
-                                       break;
-                               default:
-                                       gmove(&lo1, &lo2);
-                                       gins(AORL, ncon(lv), &lo2);
-                                       break;
-                               }
-                               switch(hv) {
-                               case 0:
-                                       gmove(&hi1, &hi2);
-                                       break;
-                               case 0xffffffffu:
-                                       gins(AMOVL, ncon(0xffffffffu), &hi2);
-                                       break;
-                               default:
-                                       gmove(&hi1, &hi2);
-                                       gins(AORL, ncon(hv), &hi2);
-                                       break;
-                               }
-                               break;
-                       }
-                       splitclean();
-                       splitclean();
-                       goto out;
-               }
-               gins(AMOVL, &lo1, &ax);
-               gins(AMOVL, &hi1, &dx);
-               gins(optoas(n->op, lo1.type), &lo2, &ax);
-               gins(optoas(n->op, lo1.type), &hi2, &dx);
-               break;
-       }
-       if(is64(r->type))
-               splitclean();
-       splitclean();
-
-       split64(res, &lo1, &hi1);
-       gins(AMOVL, &ax, &lo1);
-       gins(AMOVL, &dx, &hi1);
-       splitclean();
-
-out:;
-}
-
-/*
- * generate comparison of nl, nr, both 64-bit.
- * nl is memory; nr is constant or memory.
- */
-void
-cmp64(Node *nl, Node *nr, int op, int likely, Prog *to)
-{
-       Node lo1, hi1, lo2, hi2, rr;
-       Prog *br;
-       Type *t;
-
-       split64(nl, &lo1, &hi1);
-       split64(nr, &lo2, &hi2);
-
-       // compare most significant word;
-       // if they differ, we're done.
-       t = hi1.type;
-       if(nl->op == OLITERAL || nr->op == OLITERAL)
-               gins(ACMPL, &hi1, &hi2);
-       else {
-               regalloc(&rr, types[TINT32], N);
-               gins(AMOVL, &hi1, &rr);
-               gins(ACMPL, &rr, &hi2);
-               regfree(&rr);
-       }
-       br = P;
-       switch(op) {
-       default:
-               fatal("cmp64 %O %T", op, t);
-       case OEQ:
-               // cmp hi
-               // jne L
-               // cmp lo
-               // jeq to
-               // L:
-               br = gbranch(AJNE, T, -likely);
-               break;
-       case ONE:
-               // cmp hi
-               // jne to
-               // cmp lo
-               // jne to
-               patch(gbranch(AJNE, T, likely), to);
-               break;
-       case OGE:
-       case OGT:
-               // cmp hi
-               // jgt to
-               // jlt L
-               // cmp lo
-               // jge to (or jgt to)
-               // L:
-               patch(gbranch(optoas(OGT, t), T, likely), to);
-               br = gbranch(optoas(OLT, t), T, -likely);
-               break;
-       case OLE:
-       case OLT:
-               // cmp hi
-               // jlt to
-               // jgt L
-               // cmp lo
-               // jle to (or jlt to)
-               // L:
-               patch(gbranch(optoas(OLT, t), T, likely), to);
-               br = gbranch(optoas(OGT, t), T, -likely);
-               break;
-       }
-
-       // compare least significant word
-       t = lo1.type;
-       if(nl->op == OLITERAL || nr->op == OLITERAL)
-               gins(ACMPL, &lo1, &lo2);
-       else {
-               regalloc(&rr, types[TINT32], N);
-               gins(AMOVL, &lo1, &rr);
-               gins(ACMPL, &rr, &lo2);
-               regfree(&rr);
-       }
-
-       // jump again
-       patch(gbranch(optoas(op, t), T, likely), to);
-
-       // point first branch down here if appropriate
-       if(br != P)
-               patch(br, pc);
-
-       splitclean();
-       splitclean();
-}
-
similarity index 100%
rename from src/cmd/new8g/cgen64.go
rename to src/cmd/8g/cgen64.go
diff --git a/src/cmd/8g/doc.go b/src/cmd/8g/doc.go
deleted file mode 100644 (file)
index 9e46dca..0000000
+++ /dev/null
@@ -1,15 +0,0 @@
-// Copyright 2009 The Go Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style
-// license that can be found in the LICENSE file.
-
-// +build ignore
-
-/*
-
-8g is the version of the gc compiler for the x86.
-The $GOARCH for these tools is 386.
-
-It reads .go files and outputs .8 files. The flags are documented in ../gc/doc.go.
-
-*/
-package main
diff --git a/src/cmd/8g/galign.c b/src/cmd/8g/galign.c
deleted file mode 100644 (file)
index 33951ad..0000000
+++ /dev/null
@@ -1,87 +0,0 @@
-// Copyright 2009 The Go Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style
-// license that can be found in the LICENSE file.
-
-#include <u.h>
-#include <libc.h>
-#include "gg.h"
-
-int    thechar = '8';
-char*  thestring       = "386";
-LinkArch*      thelinkarch = &link386;
-
-void
-linkarchinit(void)
-{
-}
-
-vlong MAXWIDTH = (1LL<<32) - 1;
-
-/*
- * go declares several platform-specific type aliases:
- * int, uint, float, and uintptr
- */
-Typedef        typedefs[] =
-{
-       {"int",         TINT,           TINT32},
-       {"uint",                TUINT,          TUINT32},
-       {"uintptr",     TUINTPTR,       TUINT32},
-       {0}
-};
-
-void
-betypeinit(void)
-{
-       widthptr = 4;
-       widthint = 4;
-       widthreg = 4;
-
-       listinit8();
-}
-
-void
-main(int argc, char **argv)
-{
-       thearch.thechar = thechar;
-       thearch.thestring = thestring;
-       thearch.thelinkarch = thelinkarch;
-       thearch.typedefs = typedefs;
-       thearch.REGSP = REGSP;
-       thearch.REGCTXT = REGCTXT;
-       thearch.MAXWIDTH = MAXWIDTH;
-       thearch.anyregalloc = anyregalloc;
-       thearch.betypeinit = betypeinit;
-       thearch.bgen = bgen;
-       thearch.cgen = cgen;
-       thearch.cgen_call = cgen_call;
-       thearch.cgen_callinter = cgen_callinter;
-       thearch.cgen_ret = cgen_ret;
-       thearch.clearfat = clearfat;
-       thearch.defframe = defframe;
-       thearch.excise = excise;
-       thearch.expandchecks = expandchecks;
-       thearch.gclean = gclean;
-       thearch.ginit = ginit;
-       thearch.gins = gins;
-       thearch.ginscall = ginscall;
-       thearch.igen = igen;
-       thearch.linkarchinit = linkarchinit;
-       thearch.peep = peep;
-       thearch.proginfo = proginfo;
-       thearch.regalloc = regalloc;
-       thearch.regfree = regfree;
-       thearch.regtyp = regtyp;
-       thearch.sameaddr = sameaddr;
-       thearch.smallindir = smallindir;
-       thearch.stackaddr = stackaddr;
-       thearch.excludedregs = excludedregs;
-       thearch.RtoB = RtoB;
-       thearch.FtoB = FtoB;
-       thearch.BtoR = BtoR;
-       thearch.BtoF = BtoF;
-       thearch.optoas = optoas;
-       thearch.doregbits = doregbits;
-       thearch.regnames = regnames;
-       
-       gcmain(argc, argv);
-}
similarity index 100%
rename from src/cmd/new8g/galign.go
rename to src/cmd/8g/galign.go
similarity index 100%
rename from src/cmd/new8g/gg.go
rename to src/cmd/8g/gg.go
diff --git a/src/cmd/8g/gg.h b/src/cmd/8g/gg.h
deleted file mode 100644 (file)
index 872d946..0000000
+++ /dev/null
@@ -1,189 +0,0 @@
-// Copyright 2009 The Go Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style
-// license that can be found in the LICENSE file.
-
-#ifndef        EXTERN
-#define        EXTERN  extern
-#endif
-
-#include "../gc/go.h"
-#include "../8l/8.out.h"
-
-// foptoas flags
-enum
-{
-       Frev = 1<<0,
-       Fpop = 1<<1,
-       Fpop2 = 1<<2,
-};
-
-EXTERN uchar   reg[MAXREG];
-EXTERN Node*   panicdiv;
-extern uint32  unmappedzero;
-
-
-/*
- * ggen.c
- */
-void   compile(Node*);
-void   gen(Node*);
-Node*  lookdot(Node*, Node*, int);
-void   cgen_as(Node*, Node*);
-void   cgen_callmeth(Node*, int);
-void   cgen_callinter(Node*, Node*, int);
-void   cgen_proc(Node*, int);
-void   cgen_callret(Node*, Node*);
-void   cgen_div(int, Node*, Node*, Node*);
-void   cgen_bmul(int, Node*, Node*, Node*);
-void   cgen_hmul(Node*, Node*, Node*);
-void   cgen_shift(int, int, Node*, Node*, Node*);
-void   cgen_float(Node*, Node*);
-void   bgen_float(Node *n, int true, int likely, Prog *to);
-void   cgen_dcl(Node*);
-int    needconvert(Type*, Type*);
-void   genconv(Type*, Type*);
-void   allocparams(void);
-void   checklabels(void);
-void   ginscall(Node*, int);
-
-/*
- * cgen.c
- */
-void   agen(Node*, Node*);
-void   igen(Node*, Node*, Node*);
-vlong  fieldoffset(Type*, Node*);
-void   sgen(Node*, Node*, int64);
-void   gmove(Node*, Node*);
-Prog*  gins(int, Node*, Node*);
-int    samaddr(Node*, Node*);
-void   naddr(Node*, Addr*, int);
-void   cgen_aret(Node*, Node*);
-Node*  ncon(uint32);
-void   mgen(Node*, Node*, Node*);
-void   mfree(Node*);
-int    componentgen(Node*, Node*);
-
-/*
- * cgen64.c
- */
-void   cmp64(Node*, Node*, int, int, Prog*);
-void   cgen64(Node*, Node*);
-
-/*
- * gsubr.c
- */
-void   clearp(Prog*);
-Prog*  gbranch(int, Type*, int);
-Prog*  prog(int);
-void   gconv(int, int);
-int    conv2pt(Type*);
-vlong  convvtox(vlong, int);
-void   fnparam(Type*, int, int);
-Prog*  gop(int, Node*, Node*, Node*);
-int    optoas(int, Type*);
-int    foptoas(int, Type*, int);
-void   ginit(void);
-void   gclean(void);
-void   regalloc(Node*, Type*, Node*);
-void   regfree(Node*);
-Node*  nodarg(Type*, int);
-void   nodreg(Node*, Type*, int);
-void   nodindreg(Node*, Type*, int);
-void   nodconst(Node*, Type*, int64);
-void   gconreg(int, vlong, int);
-void   buildtxt(void);
-Plist* newplist(void);
-int    isfat(Type*);
-void   sudoclean(void);
-int    sudoaddable(int, Node*, Addr*);
-int    dotaddable(Node*, Node*);
-void   afunclit(Addr*, Node*);
-void   split64(Node*, Node*, Node*);
-void   splitclean(void);
-void   nswap(Node*, Node*);
-void   gtrack(Sym*);
-/*
- * cplx.c
- */
-int    complexop(Node*, Node*);
-void   complexmove(Node*, Node*);
-void   complexgen(Node*, Node*);
-
-/*
- * gobj.c
- */
-void   datastring(char*, int, Addr*);
-void   datagostring(Strlit*, Addr*);
-
-/*
- * list.c
- */
-void   listinit(void);
-
-void   zaddr(Biobuf*, Addr*, int, int);
-
-void afunclit(Addr*, Node*);
-int anyregalloc(void);
-void betypeinit(void);
-void bgen(Node*, int, int, Prog*);
-void cgen(Node*, Node*);
-void cgen_call(Node*, int);
-void cgen_callinter(Node*, Node*, int);
-void cgen_ret(Node*);
-void clearfat(Node*);
-void clearp(Prog*);
-void defframe(Prog*);
-int dgostringptr(Sym*, int, char*);
-int dgostrlitptr(Sym*, int, Strlit*);
-int dsname(Sym*, int, char*, int);
-int dsymptr(Sym*, int, Sym*, int);
-void dumpdata(void);
-void dumpit(char*, Flow*, int);
-void excise(Flow*);
-void expandchecks(Prog*);
-void fixautoused(Prog*);
-void gclean(void);
-void   gdata(Node*, Node*, int);
-void   gdatacomplex(Node*, Mpcplx*);
-void   gdatastring(Node*, Strlit*);
-void   ggloblnod(Node *nam);
-void   ggloblsym(Sym *s, int32 width, int8 flags);
-void ginit(void);
-Prog*  gins(int, Node*, Node*);
-void   ginscall(Node*, int);
-Prog*  gjmp(Prog*);
-void gtrack(Sym*);
-void   gused(Node*);
-void   igen(Node*, Node*, Node*);
-int isfat(Type*);
-void linkarchinit(void);
-void markautoused(Prog*);
-void naddr(Node*, Addr*, int);
-Plist* newplist(void);
-Node* nodarg(Type*, int);
-void patch(Prog*, Prog*);
-void proginfo(ProgInfo*, Prog*);
-void regalloc(Node*, Type*, Node*);
-void regfree(Node*);
-void regopt(Prog*);
-int regtyp(Addr*);
-int sameaddr(Addr*, Addr*);
-int smallindir(Addr*, Addr*);
-int stackaddr(Addr*);
-Prog* unpatch(Prog*);
-
-/*
- * reg.c
- */
-uint64 excludedregs(void);
-uint64 RtoB(int);
-uint64 FtoB(int);
-int BtoR(uint64);
-int BtoF(uint64);
-uint64 doregbits(int);
-char** regnames(int*);
-
-/*
- * peep.c
- */
-void peep(Prog*);
diff --git a/src/cmd/8g/ggen.c b/src/cmd/8g/ggen.c
deleted file mode 100644 (file)
index 8188348..0000000
+++ /dev/null
@@ -1,1165 +0,0 @@
-// Copyright 2009 The Go Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style
-// license that can be found in the LICENSE file.
-
-#undef EXTERN
-#define        EXTERN
-#include <u.h>
-#include <libc.h>
-#include "gg.h"
-#include "../gc/popt.h"
-
-static Prog *appendpp(Prog*, int, int, int, vlong, int, int, vlong);
-static Prog *zerorange(Prog *p, vlong frame, vlong lo, vlong hi, uint32 *ax);
-
-void
-defframe(Prog *ptxt)
-{
-       uint32 frame, ax;
-       Prog *p;
-       vlong lo, hi;
-       NodeList *l;
-       Node *n;
-
-       // fill in argument size, stack size
-       ptxt->to.type = TYPE_TEXTSIZE;
-       ptxt->to.u.argsize = rnd(curfn->type->argwid, widthptr);
-       frame = rnd(stksize+maxarg, widthreg);
-       ptxt->to.offset = frame;
-       
-       // insert code to zero ambiguously live variables
-       // so that the garbage collector only sees initialized values
-       // when it looks for pointers.
-       p = ptxt;
-       hi = 0;
-       lo = hi;
-       ax = 0;
-       for(l=curfn->dcl; l != nil; l = l->next) {
-               n = l->n;
-               if(!n->needzero)
-                       continue;
-               if(n->class != PAUTO)
-                       fatal("needzero class %d", n->class);
-               if(n->type->width % widthptr != 0 || n->xoffset % widthptr != 0 || n->type->width == 0)
-                       fatal("var %lN has size %d offset %d", n, (int)n->type->width, (int)n->xoffset);
-               if(lo != hi && n->xoffset + n->type->width == lo - 2*widthptr) {
-                       // merge with range we already have
-                       lo = n->xoffset;
-                       continue;
-               }
-               // zero old range
-               p = zerorange(p, frame, lo, hi, &ax);
-
-               // set new range
-               hi = n->xoffset + n->type->width;
-               lo = n->xoffset;
-       }
-       // zero final range
-       zerorange(p, frame, lo, hi, &ax);
-}
-
-static Prog*
-zerorange(Prog *p, vlong frame, vlong lo, vlong hi, uint32 *ax)
-{
-       vlong cnt, i;
-
-       cnt = hi - lo;
-       if(cnt == 0)
-               return p;
-       if(*ax == 0) {
-               p = appendpp(p, AMOVL, TYPE_CONST, 0, 0, TYPE_REG, REG_AX, 0);
-               *ax = 1;
-       }
-       if(cnt <= 4*widthreg) {
-               for(i = 0; i < cnt; i += widthreg) {
-                       p = appendpp(p, AMOVL, TYPE_REG, REG_AX, 0, TYPE_MEM, REG_SP, frame+lo+i);
-               }
-       } else if(!nacl && cnt <= 128*widthreg) {
-               p = appendpp(p, ALEAL, TYPE_MEM, REG_SP, frame+lo, TYPE_REG, REG_DI, 0);
-               p = appendpp(p, ADUFFZERO, TYPE_NONE, 0, 0, TYPE_ADDR, 0, 1*(128-cnt/widthreg));
-               p->to.sym = linksym(pkglookup("duffzero", runtimepkg));
-       } else {
-               p = appendpp(p, AMOVL, TYPE_CONST, 0, cnt/widthreg, TYPE_REG, REG_CX, 0);
-               p = appendpp(p, ALEAL, TYPE_MEM, REG_SP, frame+lo, TYPE_REG, REG_DI, 0);
-               p = appendpp(p, AREP, TYPE_NONE, 0, 0, TYPE_NONE, 0, 0);
-               p = appendpp(p, ASTOSL, TYPE_NONE, 0, 0, TYPE_NONE, 0, 0);
-       }
-       return p;
-}
-
-static Prog*   
-appendpp(Prog *p, int as, int ftype, int freg, vlong foffset, int ttype, int treg, vlong toffset)      
-{
-       Prog *q;
-       q = mal(sizeof(*q));    
-       clearp(q);      
-       q->as = as;     
-       q->lineno = p->lineno;  
-       q->from.type = ftype;   
-       q->from.reg = freg;
-       q->from.offset = foffset;       
-       q->to.type = ttype;     
-       q->to.reg = treg;
-       q->to.offset = toffset; 
-       q->link = p->link;      
-       p->link = q;    
-       return q;       
-}
-
-void
-clearfat(Node *nl)
-{
-       uint32 w, c, q;
-       Node n1, z;
-       Prog *p;
-
-       /* clear a fat object */
-       if(debug['g'])
-               dump("\nclearfat", nl);
-
-       w = nl->type->width;
-       // Avoid taking the address for simple enough types.
-       if(componentgen(N, nl))
-               return;
-
-       c = w % 4;      // bytes
-       q = w / 4;      // quads
-
-       if(q < 4) {
-               // Write sequence of MOV 0, off(base) instead of using STOSL.
-               // The hope is that although the code will be slightly longer,
-               // the MOVs will have no dependencies and pipeline better
-               // than the unrolled STOSL loop.
-               // NOTE: Must use agen, not igen, so that optimizer sees address
-               // being taken. We are not writing on field boundaries.
-               regalloc(&n1, types[tptr], N);
-               agen(nl, &n1);
-               n1.op = OINDREG;
-               nodconst(&z, types[TUINT64], 0);
-               while(q-- > 0) {
-                       n1.type = z.type;
-                       gins(AMOVL, &z, &n1);
-                       n1.xoffset += 4;
-               }
-               nodconst(&z, types[TUINT8], 0);
-               while(c-- > 0) {
-                       n1.type = z.type;
-                       gins(AMOVB, &z, &n1);
-                       n1.xoffset++;
-               }
-               regfree(&n1);
-               return;
-       }
-
-       nodreg(&n1, types[tptr], REG_DI);
-       agen(nl, &n1);
-       gconreg(AMOVL, 0, REG_AX);
-
-       if(q > 128 || (q >= 4 && nacl)) {
-               gconreg(AMOVL, q, REG_CX);
-               gins(AREP, N, N);       // repeat
-               gins(ASTOSL, N, N);     // STOL AL,*(DI)+
-       } else if(q >= 4) {
-               p = gins(ADUFFZERO, N, N);
-               p->to.type = TYPE_ADDR;
-               p->to.sym = linksym(pkglookup("duffzero", runtimepkg));
-               // 1 and 128 = magic constants: see ../../runtime/asm_386.s
-               p->to.offset = 1*(128-q);
-       } else
-       while(q > 0) {
-               gins(ASTOSL, N, N);     // STOL AL,*(DI)+
-               q--;
-       }
-
-       while(c > 0) {
-               gins(ASTOSB, N, N);     // STOB AL,*(DI)+
-               c--;
-       }
-}
-
-/*
- * generate:
- *     call f
- *     proc=-1 normal call but no return
- *     proc=0  normal call
- *     proc=1  goroutine run in new proc
- *     proc=2  defer call save away stack
-  *    proc=3  normal call to C pointer (not Go func value)
- */
-void
-ginscall(Node *f, int proc)
-{
-       Prog *p;
-       Node reg, r1, con, stk;
-       int32 extra;
-
-       if(f->type != T) {
-               extra = 0;
-               if(proc == 1 || proc == 2)
-                       extra = 2 * widthptr;
-               setmaxarg(f->type, extra);
-       }
-
-       switch(proc) {
-       default:
-               fatal("ginscall: bad proc %d", proc);
-               break;
-
-       case 0: // normal call
-       case -1:        // normal call but no return
-               if(f->op == ONAME && f->class == PFUNC) {
-                       if(f == deferreturn) {
-                               // Deferred calls will appear to be returning to
-                               // the CALL deferreturn(SB) that we are about to emit.
-                               // However, the stack trace code will show the line
-                               // of the instruction byte before the return PC. 
-                               // To avoid that being an unrelated instruction,
-                               // insert an x86 NOP that we will have the right line number.
-                               // x86 NOP 0x90 is really XCHG AX, AX; use that description
-                               // because the NOP pseudo-instruction will be removed by
-                               // the linker.
-                               nodreg(&reg, types[TINT], REG_AX);
-                               gins(AXCHGL, &reg, &reg);
-                       }
-                       p = gins(ACALL, N, f);
-                       afunclit(&p->to, f);
-                       if(proc == -1 || noreturn(p))
-                               gins(AUNDEF, N, N);
-                       break;
-               }
-               nodreg(&reg, types[tptr], REG_DX);
-               nodreg(&r1, types[tptr], REG_BX);
-               gmove(f, &reg);
-               reg.op = OINDREG;
-               gmove(&reg, &r1);
-               reg.op = OREGISTER;
-               gins(ACALL, &reg, &r1);
-               break;
-       
-       case 3: // normal call of c function pointer
-               gins(ACALL, N, f);
-               break;
-
-       case 1: // call in new proc (go)
-       case 2: // deferred call (defer)
-               memset(&stk, 0, sizeof(stk));
-               stk.op = OINDREG;
-               stk.val.u.reg = REG_SP;
-               stk.xoffset = 0;
-
-               // size of arguments at 0(SP)
-               nodconst(&con, types[TINT32], argsize(f->type));
-               gins(AMOVL, &con, &stk);
-
-               // FuncVal* at 4(SP)
-               stk.xoffset = widthptr;
-               gins(AMOVL, f, &stk);
-
-               if(proc == 1)
-                       ginscall(newproc, 0);
-               else
-                       ginscall(deferproc, 0);
-               if(proc == 2) {
-                       nodreg(&reg, types[TINT32], REG_AX);
-                       gins(ATESTL, &reg, &reg);
-                       p = gbranch(AJEQ, T, +1);
-                       cgen_ret(N);
-                       patch(p, pc);
-               }
-               break;
-       }
-}
-
-/*
- * n is call to interface method.
- * generate res = n.
- */
-void
-cgen_callinter(Node *n, Node *res, int proc)
-{
-       Node *i, *f;
-       Node tmpi, nodi, nodo, nodr, nodsp;
-
-       i = n->left;
-       if(i->op != ODOTINTER)
-               fatal("cgen_callinter: not ODOTINTER %O", i->op);
-
-       f = i->right;           // field
-       if(f->op != ONAME)
-               fatal("cgen_callinter: not ONAME %O", f->op);
-
-       i = i->left;            // interface
-
-       if(!i->addable) {
-               tempname(&tmpi, i->type);
-               cgen(i, &tmpi);
-               i = &tmpi;
-       }
-
-       genlist(n->list);               // assign the args
-
-       // i is now addable, prepare an indirected
-       // register to hold its address.
-       igen(i, &nodi, res);            // REG = &inter
-
-       nodindreg(&nodsp, types[tptr], REG_SP);
-       nodsp.xoffset = 0;
-       if(proc != 0)
-               nodsp.xoffset += 2 * widthptr; // leave room for size & fn
-       nodi.type = types[tptr];
-       nodi.xoffset += widthptr;
-       cgen(&nodi, &nodsp);    // {0 or 8}(SP) = 4(REG) -- i.data
-
-       regalloc(&nodo, types[tptr], res);
-       nodi.type = types[tptr];
-       nodi.xoffset -= widthptr;
-       cgen(&nodi, &nodo);     // REG = 0(REG) -- i.tab
-       regfree(&nodi);
-
-       regalloc(&nodr, types[tptr], &nodo);
-       if(n->left->xoffset == BADWIDTH)
-               fatal("cgen_callinter: badwidth");
-       cgen_checknil(&nodo);
-       nodo.op = OINDREG;
-       nodo.xoffset = n->left->xoffset + 3*widthptr + 8;
-       
-       if(proc == 0) {
-               // plain call: use direct c function pointer - more efficient
-               cgen(&nodo, &nodr);     // REG = 20+offset(REG) -- i.tab->fun[f]
-               proc = 3;
-       } else {
-               // go/defer. generate go func value.
-               gins(ALEAL, &nodo, &nodr);      // REG = &(20+offset(REG)) -- i.tab->fun[f]
-       }
-
-       nodr.type = n->left->type;
-       ginscall(&nodr, proc);
-
-       regfree(&nodr);
-       regfree(&nodo);
-}
-
-/*
- * generate function call;
- *     proc=0  normal call
- *     proc=1  goroutine run in new proc
- *     proc=2  defer call save away stack
- */
-void
-cgen_call(Node *n, int proc)
-{
-       Type *t;
-       Node nod, afun;
-
-       if(n == N)
-               return;
-
-       if(n->left->ullman >= UINF) {
-               // if name involves a fn call
-               // precompute the address of the fn
-               tempname(&afun, types[tptr]);
-               cgen(n->left, &afun);
-       }
-
-       genlist(n->list);               // assign the args
-       t = n->left->type;
-
-       // call tempname pointer
-       if(n->left->ullman >= UINF) {
-               regalloc(&nod, types[tptr], N);
-               cgen_as(&nod, &afun);
-               nod.type = t;
-               ginscall(&nod, proc);
-               regfree(&nod);
-               return;
-       }
-
-       // call pointer
-       if(n->left->op != ONAME || n->left->class != PFUNC) {
-               regalloc(&nod, types[tptr], N);
-               cgen_as(&nod, n->left);
-               nod.type = t;
-               ginscall(&nod, proc);
-               regfree(&nod);
-               return;
-       }
-
-       // call direct
-       n->left->method = 1;
-       ginscall(n->left, proc);
-}
-
-/*
- * call to n has already been generated.
- * generate:
- *     res = return value from call.
- */
-void
-cgen_callret(Node *n, Node *res)
-{
-       Node nod;
-       Type *fp, *t;
-       Iter flist;
-
-       t = n->left->type;
-       if(t->etype == TPTR32 || t->etype == TPTR64)
-               t = t->type;
-
-       fp = structfirst(&flist, getoutarg(t));
-       if(fp == T)
-               fatal("cgen_callret: nil");
-
-       memset(&nod, 0, sizeof(nod));
-       nod.op = OINDREG;
-       nod.val.u.reg = REG_SP;
-       nod.addable = 1;
-
-       nod.xoffset = fp->width;
-       nod.type = fp->type;
-       cgen_as(res, &nod);
-}
-
-/*
- * call to n has already been generated.
- * generate:
- *     res = &return value from call.
- */
-void
-cgen_aret(Node *n, Node *res)
-{
-       Node nod1, nod2;
-       Type *fp, *t;
-       Iter flist;
-
-       t = n->left->type;
-       if(isptr[t->etype])
-               t = t->type;
-
-       fp = structfirst(&flist, getoutarg(t));
-       if(fp == T)
-               fatal("cgen_aret: nil");
-
-       memset(&nod1, 0, sizeof(nod1));
-       nod1.op = OINDREG;
-       nod1.val.u.reg = REG_SP;
-       nod1.addable = 1;
-
-       nod1.xoffset = fp->width;
-       nod1.type = fp->type;
-
-       if(res->op != OREGISTER) {
-               regalloc(&nod2, types[tptr], res);
-               gins(ALEAL, &nod1, &nod2);
-               gins(AMOVL, &nod2, res);
-               regfree(&nod2);
-       } else
-               gins(ALEAL, &nod1, res);
-}
-
-/*
- * generate return.
- * n->left is assignments to return values.
- */
-void
-cgen_ret(Node *n)
-{
-       Prog *p;
-
-       if(n != N)
-               genlist(n->list);               // copy out args
-       if(hasdefer)
-               ginscall(deferreturn, 0);
-       genlist(curfn->exit);
-       p = gins(ARET, N, N);
-       if(n != N && n->op == ORETJMP) {
-               p->to.type = TYPE_MEM;
-               p->to.name = NAME_EXTERN;
-               p->to.sym = linksym(n->left->sym);
-       }
-}
-
-/*
- * generate division.
- * caller must set:
- *     ax = allocated AX register
- *     dx = allocated DX register
- * generates one of:
- *     res = nl / nr
- *     res = nl % nr
- * according to op.
- */
-void
-dodiv(int op, Node *nl, Node *nr, Node *res, Node *ax, Node *dx)
-{
-       int check;
-       Node n1, t1, t2, t3, t4, n4, nz;
-       Type *t, *t0;
-       Prog *p1, *p2;
-
-       // Have to be careful about handling
-       // most negative int divided by -1 correctly.
-       // The hardware will trap.
-       // Also the byte divide instruction needs AH,
-       // which we otherwise don't have to deal with.
-       // Easiest way to avoid for int8, int16: use int32.
-       // For int32 and int64, use explicit test.
-       // Could use int64 hw for int32.
-       t = nl->type;
-       t0 = t;
-       check = 0;
-       if(issigned[t->etype]) {
-               check = 1;
-               if(isconst(nl, CTINT) && mpgetfix(nl->val.u.xval) != -1LL<<(t->width*8-1))
-                       check = 0;
-               else if(isconst(nr, CTINT) && mpgetfix(nr->val.u.xval) != -1)
-                       check = 0;
-       }
-       if(t->width < 4) {
-               if(issigned[t->etype])
-                       t = types[TINT32];
-               else
-                       t = types[TUINT32];
-               check = 0;
-       }
-
-       tempname(&t1, t);
-       tempname(&t2, t);
-       if(t0 != t) {
-               tempname(&t3, t0);
-               tempname(&t4, t0);
-               cgen(nl, &t3);
-               cgen(nr, &t4);
-               // Convert.
-               gmove(&t3, &t1);
-               gmove(&t4, &t2);
-       } else {
-               cgen(nl, &t1);
-               cgen(nr, &t2);
-       }
-
-       if(!samereg(ax, res) && !samereg(dx, res))
-               regalloc(&n1, t, res);
-       else
-               regalloc(&n1, t, N);
-       gmove(&t2, &n1);
-       gmove(&t1, ax);
-       p2 = P;
-       if(nacl) {
-               // Native Client does not relay the divide-by-zero trap
-               // to the executing program, so we must insert a check
-               // for ourselves.
-               nodconst(&n4, t, 0);
-               gins(optoas(OCMP, t), &n1, &n4);
-               p1 = gbranch(optoas(ONE, t), T, +1);
-               if(panicdiv == N)
-                       panicdiv = sysfunc("panicdivide");
-               ginscall(panicdiv, -1);
-               patch(p1, pc);
-       }
-       if(check) {
-               nodconst(&n4, t, -1);
-               gins(optoas(OCMP, t), &n1, &n4);
-               p1 = gbranch(optoas(ONE, t), T, +1);
-               if(op == ODIV) {
-                       // a / (-1) is -a.
-                       gins(optoas(OMINUS, t), N, ax);
-                       gmove(ax, res);
-               } else {
-                       // a % (-1) is 0.
-                       nodconst(&n4, t, 0);
-                       gmove(&n4, res);
-               }
-               p2 = gbranch(AJMP, T, 0);
-               patch(p1, pc);
-       }
-       if(!issigned[t->etype]) {
-               nodconst(&nz, t, 0);
-               gmove(&nz, dx);
-       } else
-               gins(optoas(OEXTEND, t), N, N);
-       gins(optoas(op, t), &n1, N);
-       regfree(&n1);
-
-       if(op == ODIV)
-               gmove(ax, res);
-       else
-               gmove(dx, res);
-       if(check)
-               patch(p2, pc);
-}
-
-static void
-savex(int dr, Node *x, Node *oldx, Node *res, Type *t)
-{
-       int r;
-
-       r = reg[dr];
-       nodreg(x, types[TINT32], dr);
-
-       // save current ax and dx if they are live
-       // and not the destination
-       memset(oldx, 0, sizeof *oldx);
-       if(r > 0 && !samereg(x, res)) {
-               tempname(oldx, types[TINT32]);
-               gmove(x, oldx);
-       }
-
-       regalloc(x, t, x);
-}
-
-static void
-restx(Node *x, Node *oldx)
-{
-       regfree(x);
-
-       if(oldx->op != 0) {
-               x->type = types[TINT32];
-               gmove(oldx, x);
-       }
-}
-
-/*
- * generate division according to op, one of:
- *     res = nl / nr
- *     res = nl % nr
- */
-void
-cgen_div(int op, Node *nl, Node *nr, Node *res)
-{
-       Node ax, dx, oldax, olddx;
-       Type *t;
-
-       if(is64(nl->type))
-               fatal("cgen_div %T", nl->type);
-
-       if(issigned[nl->type->etype])
-               t = types[TINT32];
-       else
-               t = types[TUINT32];
-       savex(REG_AX, &ax, &oldax, res, t);
-       savex(REG_DX, &dx, &olddx, res, t);
-       dodiv(op, nl, nr, res, &ax, &dx);
-       restx(&dx, &olddx);
-       restx(&ax, &oldax);
-}
-
-/*
- * generate shift according to op, one of:
- *     res = nl << nr
- *     res = nl >> nr
- */
-void
-cgen_shift(int op, int bounded, Node *nl, Node *nr, Node *res)
-{
-       Node n1, n2, nt, cx, oldcx, hi, lo;
-       int a, w;
-       Prog *p1, *p2;
-       uvlong sc;
-
-       if(nl->type->width > 4)
-               fatal("cgen_shift %T", nl->type);
-
-       w = nl->type->width * 8;
-
-       a = optoas(op, nl->type);
-
-       if(nr->op == OLITERAL) {
-               tempname(&n2, nl->type);
-               cgen(nl, &n2);
-               regalloc(&n1, nl->type, res);
-               gmove(&n2, &n1);
-               sc = mpgetfix(nr->val.u.xval);
-               if(sc >= nl->type->width*8) {
-                       // large shift gets 2 shifts by width-1
-                       gins(a, ncon(w-1), &n1);
-                       gins(a, ncon(w-1), &n1);
-               } else
-                       gins(a, nr, &n1);
-               gmove(&n1, res);
-               regfree(&n1);
-               return;
-       }
-
-       memset(&oldcx, 0, sizeof oldcx);
-       nodreg(&cx, types[TUINT32], REG_CX);
-       if(reg[REG_CX] > 1 && !samereg(&cx, res)) {
-               tempname(&oldcx, types[TUINT32]);
-               gmove(&cx, &oldcx);
-       }
-
-       if(nr->type->width > 4) {
-               tempname(&nt, nr->type);
-               n1 = nt;
-       } else {
-               nodreg(&n1, types[TUINT32], REG_CX);
-               regalloc(&n1, nr->type, &n1);           // to hold the shift type in CX
-       }
-
-       if(samereg(&cx, res))
-               regalloc(&n2, nl->type, N);
-       else
-               regalloc(&n2, nl->type, res);
-       if(nl->ullman >= nr->ullman) {
-               cgen(nl, &n2);
-               cgen(nr, &n1);
-       } else {
-               cgen(nr, &n1);
-               cgen(nl, &n2);
-       }
-
-       // test and fix up large shifts
-       if(bounded) {
-               if(nr->type->width > 4) {
-                       // delayed reg alloc
-                       nodreg(&n1, types[TUINT32], REG_CX);
-                       regalloc(&n1, types[TUINT32], &n1);             // to hold the shift type in CX
-                       split64(&nt, &lo, &hi);
-                       gmove(&lo, &n1);
-                       splitclean();
-               }
-       } else {
-               if(nr->type->width > 4) {
-                       // delayed reg alloc
-                       nodreg(&n1, types[TUINT32], REG_CX);
-                       regalloc(&n1, types[TUINT32], &n1);             // to hold the shift type in CX
-                       split64(&nt, &lo, &hi);
-                       gmove(&lo, &n1);
-                       gins(optoas(OCMP, types[TUINT32]), &hi, ncon(0));
-                       p2 = gbranch(optoas(ONE, types[TUINT32]), T, +1);
-                       gins(optoas(OCMP, types[TUINT32]), &n1, ncon(w));
-                       p1 = gbranch(optoas(OLT, types[TUINT32]), T, +1);
-                       splitclean();
-                       patch(p2, pc);
-               } else {
-                       gins(optoas(OCMP, nr->type), &n1, ncon(w));
-                       p1 = gbranch(optoas(OLT, types[TUINT32]), T, +1);
-               }
-               if(op == ORSH && issigned[nl->type->etype]) {
-                       gins(a, ncon(w-1), &n2);
-               } else {
-                       gmove(ncon(0), &n2);
-               }
-               patch(p1, pc);
-       }
-       gins(a, &n1, &n2);
-
-       if(oldcx.op != 0)
-               gmove(&oldcx, &cx);
-
-       gmove(&n2, res);
-
-       regfree(&n1);
-       regfree(&n2);
-}
-
-/*
- * generate byte multiply:
- *     res = nl * nr
- * there is no 2-operand byte multiply instruction so
- * we do a full-width multiplication and truncate afterwards.
- */
-void
-cgen_bmul(int op, Node *nl, Node *nr, Node *res)
-{
-       Node n1, n2, nt, *tmp;
-       Type *t;
-       int a;
-
-       // copy from byte to full registers
-       t = types[TUINT32];
-       if(issigned[nl->type->etype])
-               t = types[TINT32];
-
-       // largest ullman on left.
-       if(nl->ullman < nr->ullman) {
-               tmp = nl;
-               nl = nr;
-               nr = tmp;
-       }
-
-       tempname(&nt, nl->type);
-       cgen(nl, &nt);
-       regalloc(&n1, t, res);
-       cgen(nr, &n1);
-       regalloc(&n2, t, N);
-       gmove(&nt, &n2);
-       a = optoas(op, t);
-       gins(a, &n2, &n1);
-       regfree(&n2);
-       gmove(&n1, res);
-       regfree(&n1);
-}
-
-/*
- * generate high multiply:
- *   res = (nl*nr) >> width
- */
-void
-cgen_hmul(Node *nl, Node *nr, Node *res)
-{
-       Type *t;
-       int a;
-       Node n1, n2, ax, dx;
-
-       t = nl->type;
-       a = optoas(OHMUL, t);
-       // gen nl in n1.
-       tempname(&n1, t);
-       cgen(nl, &n1);
-       // gen nr in n2.
-       regalloc(&n2, t, res);
-       cgen(nr, &n2);
-
-       // multiply.
-       nodreg(&ax, t, REG_AX);
-       gmove(&n2, &ax);
-       gins(a, &n1, N);
-       regfree(&n2);
-
-       if(t->width == 1) {
-               // byte multiply behaves differently.
-               nodreg(&ax, t, REG_AH);
-               nodreg(&dx, t, REG_DX);
-               gmove(&ax, &dx);
-       }
-       nodreg(&dx, t, REG_DX);
-       gmove(&dx, res);
-}
-
-static void cgen_float387(Node *n, Node *res);
-static void cgen_floatsse(Node *n, Node *res);
-
-/*
- * generate floating-point operation.
- */
-void
-cgen_float(Node *n, Node *res)
-{
-       Node *nl;
-       Node n1, n2;
-       Prog *p1, *p2, *p3;
-
-       nl = n->left;
-       switch(n->op) {
-       case OEQ:
-       case ONE:
-       case OLT:
-       case OLE:
-       case OGE:
-               p1 = gbranch(AJMP, T, 0);
-               p2 = pc;
-               gmove(nodbool(1), res);
-               p3 = gbranch(AJMP, T, 0);
-               patch(p1, pc);
-               bgen(n, 1, 0, p2);
-               gmove(nodbool(0), res);
-               patch(p3, pc);
-               return;
-
-       case OPLUS:
-               cgen(nl, res);
-               return;
-
-       case OCONV:
-               if(eqtype(n->type, nl->type) || noconv(n->type, nl->type)) {
-                       cgen(nl, res);
-                       return;
-               }
-
-               tempname(&n2, n->type);
-               mgen(nl, &n1, res);
-               gmove(&n1, &n2);
-               gmove(&n2, res);
-               mfree(&n1);
-               return;
-       }
-
-       if(use_sse)
-               cgen_floatsse(n, res);
-       else
-               cgen_float387(n, res);
-}
-
-// floating-point.  387 (not SSE2)
-static void
-cgen_float387(Node *n, Node *res)
-{
-       Node f0, f1;
-       Node *nl, *nr;
-
-       nl = n->left;
-       nr = n->right;
-       nodreg(&f0, nl->type, REG_F0);
-       nodreg(&f1, n->type, REG_F0+1);
-       if(nr != N)
-               goto flt2;
-
-       // unary
-       cgen(nl, &f0);
-       if(n->op != OCONV && n->op != OPLUS)
-               gins(foptoas(n->op, n->type, 0), N, N);
-       gmove(&f0, res);
-       return;
-
-flt2:  // binary
-       if(nl->ullman >= nr->ullman) {
-               cgen(nl, &f0);
-               if(nr->addable)
-                       gins(foptoas(n->op, n->type, 0), nr, &f0);
-               else {
-                       cgen(nr, &f0);
-                       gins(foptoas(n->op, n->type, Fpop), &f0, &f1);
-               }
-       } else {
-               cgen(nr, &f0);
-               if(nl->addable)
-                       gins(foptoas(n->op, n->type, Frev), nl, &f0);
-               else {
-                       cgen(nl, &f0);
-                       gins(foptoas(n->op, n->type, Frev|Fpop), &f0, &f1);
-               }
-       }
-       gmove(&f0, res);
-       return;
-
-}
-
-static void
-cgen_floatsse(Node *n, Node *res)
-{
-       Node *nl, *nr, *r;
-       Node n1, n2, nt;
-       int a;
-
-       nl = n->left;
-       nr = n->right;
-       switch(n->op) {
-       default:
-               dump("cgen_floatsse", n);
-               fatal("cgen_floatsse %O", n->op);
-               return;
-
-       case OMINUS:
-       case OCOM:
-               nr = nodintconst(-1);
-               convlit(&nr, n->type);
-               a = foptoas(OMUL, nl->type, 0);
-               goto sbop;
-
-       // symmetric binary
-       case OADD:
-       case OMUL:
-               a = foptoas(n->op, nl->type, 0);
-               goto sbop;
-
-       // asymmetric binary
-       case OSUB:
-       case OMOD:
-       case ODIV:
-               a = foptoas(n->op, nl->type, 0);
-               goto abop;
-       }
-
-sbop:  // symmetric binary
-       if(nl->ullman < nr->ullman || nl->op == OLITERAL) {
-               r = nl;
-               nl = nr;
-               nr = r;
-       }
-
-abop:  // asymmetric binary
-       if(nl->ullman >= nr->ullman) {
-               tempname(&nt, nl->type);
-               cgen(nl, &nt);
-               mgen(nr, &n2, N);
-               regalloc(&n1, nl->type, res);
-               gmove(&nt, &n1);
-               gins(a, &n2, &n1);
-               gmove(&n1, res);
-               regfree(&n1);
-               mfree(&n2);
-       } else {
-               regalloc(&n2, nr->type, res);
-               cgen(nr, &n2);
-               regalloc(&n1, nl->type, N);
-               cgen(nl, &n1);
-               gins(a, &n2, &n1);
-               regfree(&n2);
-               gmove(&n1, res);
-               regfree(&n1);
-       }
-       return;
-}
-
-void
-bgen_float(Node *n, int true, int likely, Prog *to)
-{
-       int et, a;
-       Node *nl, *nr, *r;
-       Node n1, n2, n3, tmp, t1, t2, ax;
-       Prog *p1, *p2;
-
-       nl = n->left;
-       nr = n->right;
-       a = n->op;
-       if(!true) {
-               // brcom is not valid on floats when NaN is involved.
-               p1 = gbranch(AJMP, T, 0);
-               p2 = gbranch(AJMP, T, 0);
-               patch(p1, pc);
-               // No need to avoid re-genning ninit.
-               bgen_float(n, 1, -likely, p2);
-               patch(gbranch(AJMP, T, 0), to);
-               patch(p2, pc);
-               return;
-       }
-
-       if(use_sse)
-               goto sse;
-       else
-               goto x87;
-
-x87:
-       a = brrev(a);   // because the args are stacked
-       if(a == OGE || a == OGT) {
-               // only < and <= work right with NaN; reverse if needed
-               r = nr;
-               nr = nl;
-               nl = r;
-               a = brrev(a);
-       }
-
-       nodreg(&tmp, nr->type, REG_F0);
-       nodreg(&n2, nr->type, REG_F0 + 1);
-       nodreg(&ax, types[TUINT16], REG_AX);
-       et = simsimtype(nr->type);
-       if(et == TFLOAT64) {
-               if(nl->ullman > nr->ullman) {
-                       cgen(nl, &tmp);
-                       cgen(nr, &tmp);
-                       gins(AFXCHD, &tmp, &n2);
-               } else {
-                       cgen(nr, &tmp);
-                       cgen(nl, &tmp);
-               }
-               gins(AFUCOMIP, &tmp, &n2);
-               gins(AFMOVDP, &tmp, &tmp);      // annoying pop but still better than STSW+SAHF
-       } else {
-               // TODO(rsc): The moves back and forth to memory
-               // here are for truncating the value to 32 bits.
-               // This handles 32-bit comparison but presumably
-               // all the other ops have the same problem.
-               // We need to figure out what the right general
-               // solution is, besides telling people to use float64.
-               tempname(&t1, types[TFLOAT32]);
-               tempname(&t2, types[TFLOAT32]);
-               cgen(nr, &t1);
-               cgen(nl, &t2);
-               gmove(&t2, &tmp);
-               gins(AFCOMFP, &t1, &tmp);
-               gins(AFSTSW, N, &ax);
-               gins(ASAHF, N, N);
-       }
-
-       goto ret;
-
-sse:
-       if(!nl->addable) {
-               tempname(&n1, nl->type);
-               cgen(nl, &n1);
-               nl = &n1;
-       }
-       if(!nr->addable) {
-               tempname(&tmp, nr->type);
-               cgen(nr, &tmp);
-               nr = &tmp;
-       }
-       regalloc(&n2, nr->type, N);
-       gmove(nr, &n2);
-       nr = &n2;
-
-       if(nl->op != OREGISTER) {
-               regalloc(&n3, nl->type, N);
-               gmove(nl, &n3);
-               nl = &n3;
-       }
-
-       if(a == OGE || a == OGT) {
-               // only < and <= work right with NaN; reverse if needed
-               r = nr;
-               nr = nl;
-               nl = r;
-               a = brrev(a);
-       }
-
-       gins(foptoas(OCMP, nr->type, 0), nl, nr);
-       if(nl->op == OREGISTER)
-               regfree(nl);
-       regfree(nr);
-
-ret:
-       if(a == OEQ) {
-               // neither NE nor P
-               p1 = gbranch(AJNE, T, -likely);
-               p2 = gbranch(AJPS, T, -likely);
-               patch(gbranch(AJMP, T, 0), to);
-               patch(p1, pc);
-               patch(p2, pc);
-       } else if(a == ONE) {
-               // either NE or P
-               patch(gbranch(AJNE, T, likely), to);
-               patch(gbranch(AJPS, T, likely), to);
-       } else
-               patch(gbranch(optoas(a, nr->type), T, likely), to);
-
-}
-
-// Called after regopt and peep have run.
-// Expand CHECKNIL pseudo-op into actual nil pointer check.
-void
-expandchecks(Prog *firstp)
-{
-       Prog *p, *p1, *p2;
-
-       for(p = firstp; p != P; p = p->link) {
-               if(p->as != ACHECKNIL)
-                       continue;
-               if(debug_checknil && p->lineno > 1) // p->lineno==1 in generated wrappers
-                       warnl(p->lineno, "generated nil check");
-               // check is
-               //      CMP arg, $0
-               //      JNE 2(PC) (likely)
-               //      MOV AX, 0
-               p1 = mal(sizeof *p1);
-               p2 = mal(sizeof *p2);
-               clearp(p1);
-               clearp(p2);
-               p1->link = p2;
-               p2->link = p->link;
-               p->link = p1;
-               p1->lineno = p->lineno;
-               p2->lineno = p->lineno;
-               p1->pc = 9999;
-               p2->pc = 9999;
-               p->as = ACMPL;
-               p->to.type = TYPE_CONST;
-               p->to.offset = 0;
-               p1->as = AJNE;
-               p1->from.type = TYPE_CONST;
-               p1->from.offset = 1; // likely
-               p1->to.type = TYPE_BRANCH;
-               p1->to.u.branch = p2->link;
-               // crash by write to memory address 0.
-               // if possible, since we know arg is 0, use 0(arg),
-               // which will be shorter to encode than plain 0.
-               p2->as = AMOVL;
-               p2->from.type = TYPE_REG;
-               p2->from.reg = REG_AX;
-               if(regtyp(&p->from)) {
-                       p2->to.type = TYPE_MEM;
-                       p2->to.reg = p->from.reg;
-               } else
-                       p2->to.type = TYPE_MEM;
-               p2->to.offset = 0;
-       }
-}
similarity index 100%
rename from src/cmd/new8g/ggen.go
rename to src/cmd/8g/ggen.go
diff --git a/src/cmd/8g/gsubr.c b/src/cmd/8g/gsubr.c
deleted file mode 100644 (file)
index b82f762..0000000
+++ /dev/null
@@ -1,1874 +0,0 @@
-// Derived from Inferno utils/8c/txt.c
-// http://code.google.com/p/inferno-os/source/browse/utils/8c/txt.c
-//
-//     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 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 <u.h>
-#include <libc.h>
-#include "gg.h"
-#include "../../runtime/funcdata.h"
-
-// TODO(rsc): Can make this bigger if we move
-// the text segment up higher in 8l for all GOOS.
-// At the same time, can raise StackBig in ../../runtime/stack.h.
-uint32 unmappedzero = 4096;
-
-#define        CASE(a,b)       (((a)<<16)|((b)<<0))
-/*c2go int CASE(int, int);*/
-
-/*
- * return Axxx for Oxxx on type t.
- */
-int
-optoas(int op, Type *t)
-{
-       int a;
-
-       if(t == T)
-               fatal("optoas: t is nil");
-
-       a = AXXX;
-       switch(CASE(op, simtype[t->etype])) {
-       default:
-               fatal("optoas: no entry %O-%T", op, t);
-               break;
-
-       case CASE(OADDR, TPTR32):
-               a = ALEAL;
-               break;
-
-       case CASE(OEQ, TBOOL):
-       case CASE(OEQ, TINT8):
-       case CASE(OEQ, TUINT8):
-       case CASE(OEQ, TINT16):
-       case CASE(OEQ, TUINT16):
-       case CASE(OEQ, TINT32):
-       case CASE(OEQ, TUINT32):
-       case CASE(OEQ, TINT64):
-       case CASE(OEQ, TUINT64):
-       case CASE(OEQ, TPTR32):
-       case CASE(OEQ, TPTR64):
-       case CASE(OEQ, TFLOAT32):
-       case CASE(OEQ, TFLOAT64):
-               a = AJEQ;
-               break;
-
-       case CASE(ONE, TBOOL):
-       case CASE(ONE, TINT8):
-       case CASE(ONE, TUINT8):
-       case CASE(ONE, TINT16):
-       case CASE(ONE, TUINT16):
-       case CASE(ONE, TINT32):
-       case CASE(ONE, TUINT32):
-       case CASE(ONE, TINT64):
-       case CASE(ONE, TUINT64):
-       case CASE(ONE, TPTR32):
-       case CASE(ONE, TPTR64):
-       case CASE(ONE, TFLOAT32):
-       case CASE(ONE, TFLOAT64):
-               a = AJNE;
-               break;
-
-       case CASE(OLT, TINT8):
-       case CASE(OLT, TINT16):
-       case CASE(OLT, TINT32):
-       case CASE(OLT, TINT64):
-               a = AJLT;
-               break;
-
-       case CASE(OLT, TUINT8):
-       case CASE(OLT, TUINT16):
-       case CASE(OLT, TUINT32):
-       case CASE(OLT, TUINT64):
-               a = AJCS;
-               break;
-
-       case CASE(OLE, TINT8):
-       case CASE(OLE, TINT16):
-       case CASE(OLE, TINT32):
-       case CASE(OLE, TINT64):
-               a = AJLE;
-               break;
-
-       case CASE(OLE, TUINT8):
-       case CASE(OLE, TUINT16):
-       case CASE(OLE, TUINT32):
-       case CASE(OLE, TUINT64):
-               a = AJLS;
-               break;
-
-       case CASE(OGT, TINT8):
-       case CASE(OGT, TINT16):
-       case CASE(OGT, TINT32):
-       case CASE(OGT, TINT64):
-               a = AJGT;
-               break;
-
-       case CASE(OGT, TUINT8):
-       case CASE(OGT, TUINT16):
-       case CASE(OGT, TUINT32):
-       case CASE(OGT, TUINT64):
-       case CASE(OLT, TFLOAT32):
-       case CASE(OLT, TFLOAT64):
-               a = AJHI;
-               break;
-
-       case CASE(OGE, TINT8):
-       case CASE(OGE, TINT16):
-       case CASE(OGE, TINT32):
-       case CASE(OGE, TINT64):
-               a = AJGE;
-               break;
-
-       case CASE(OGE, TUINT8):
-       case CASE(OGE, TUINT16):
-       case CASE(OGE, TUINT32):
-       case CASE(OGE, TUINT64):
-       case CASE(OLE, TFLOAT32):
-       case CASE(OLE, TFLOAT64):
-               a = AJCC;
-               break;
-
-       case CASE(OCMP, TBOOL):
-       case CASE(OCMP, TINT8):
-       case CASE(OCMP, TUINT8):
-               a = ACMPB;
-               break;
-
-       case CASE(OCMP, TINT16):
-       case CASE(OCMP, TUINT16):
-               a = ACMPW;
-               break;
-
-       case CASE(OCMP, TINT32):
-       case CASE(OCMP, TUINT32):
-       case CASE(OCMP, TPTR32):
-               a = ACMPL;
-               break;
-
-       case CASE(OAS, TBOOL):
-       case CASE(OAS, TINT8):
-       case CASE(OAS, TUINT8):
-               a = AMOVB;
-               break;
-
-       case CASE(OAS, TINT16):
-       case CASE(OAS, TUINT16):
-               a = AMOVW;
-               break;
-
-       case CASE(OAS, TINT32):
-       case CASE(OAS, TUINT32):
-       case CASE(OAS, TPTR32):
-               a = AMOVL;
-               break;
-       
-       case CASE(OAS, TFLOAT32):
-               a = AMOVSS;
-               break;
-       
-       case CASE(OAS, TFLOAT64):
-               a = AMOVSD;
-               break;
-
-       case CASE(OADD, TINT8):
-       case CASE(OADD, TUINT8):
-               a = AADDB;
-               break;
-
-       case CASE(OADD, TINT16):
-       case CASE(OADD, TUINT16):
-               a = AADDW;
-               break;
-
-       case CASE(OADD, TINT32):
-       case CASE(OADD, TUINT32):
-       case CASE(OADD, TPTR32):
-               a = AADDL;
-               break;
-
-       case CASE(OSUB, TINT8):
-       case CASE(OSUB, TUINT8):
-               a = ASUBB;
-               break;
-
-       case CASE(OSUB, TINT16):
-       case CASE(OSUB, TUINT16):
-               a = ASUBW;
-               break;
-
-       case CASE(OSUB, TINT32):
-       case CASE(OSUB, TUINT32):
-       case CASE(OSUB, TPTR32):
-               a = ASUBL;
-               break;
-
-       case CASE(OINC, TINT8):
-       case CASE(OINC, TUINT8):
-               a = AINCB;
-               break;
-
-       case CASE(OINC, TINT16):
-       case CASE(OINC, TUINT16):
-               a = AINCW;
-               break;
-
-       case CASE(OINC, TINT32):
-       case CASE(OINC, TUINT32):
-       case CASE(OINC, TPTR32):
-               a = AINCL;
-               break;
-
-       case CASE(ODEC, TINT8):
-       case CASE(ODEC, TUINT8):
-               a = ADECB;
-               break;
-
-       case CASE(ODEC, TINT16):
-       case CASE(ODEC, TUINT16):
-               a = ADECW;
-               break;
-
-       case CASE(ODEC, TINT32):
-       case CASE(ODEC, TUINT32):
-       case CASE(ODEC, TPTR32):
-               a = ADECL;
-               break;
-
-       case CASE(OCOM, TINT8):
-       case CASE(OCOM, TUINT8):
-               a = ANOTB;
-               break;
-
-       case CASE(OCOM, TINT16):
-       case CASE(OCOM, TUINT16):
-               a = ANOTW;
-               break;
-
-       case CASE(OCOM, TINT32):
-       case CASE(OCOM, TUINT32):
-       case CASE(OCOM, TPTR32):
-               a = ANOTL;
-               break;
-
-       case CASE(OMINUS, TINT8):
-       case CASE(OMINUS, TUINT8):
-               a = ANEGB;
-               break;
-
-       case CASE(OMINUS, TINT16):
-       case CASE(OMINUS, TUINT16):
-               a = ANEGW;
-               break;
-
-       case CASE(OMINUS, TINT32):
-       case CASE(OMINUS, TUINT32):
-       case CASE(OMINUS, TPTR32):
-               a = ANEGL;
-               break;
-
-       case CASE(OAND, TINT8):
-       case CASE(OAND, TUINT8):
-               a = AANDB;
-               break;
-
-       case CASE(OAND, TINT16):
-       case CASE(OAND, TUINT16):
-               a = AANDW;
-               break;
-
-       case CASE(OAND, TINT32):
-       case CASE(OAND, TUINT32):
-       case CASE(OAND, TPTR32):
-               a = AANDL;
-               break;
-
-       case CASE(OOR, TINT8):
-       case CASE(OOR, TUINT8):
-               a = AORB;
-               break;
-
-       case CASE(OOR, TINT16):
-       case CASE(OOR, TUINT16):
-               a = AORW;
-               break;
-
-       case CASE(OOR, TINT32):
-       case CASE(OOR, TUINT32):
-       case CASE(OOR, TPTR32):
-               a = AORL;
-               break;
-
-       case CASE(OXOR, TINT8):
-       case CASE(OXOR, TUINT8):
-               a = AXORB;
-               break;
-
-       case CASE(OXOR, TINT16):
-       case CASE(OXOR, TUINT16):
-               a = AXORW;
-               break;
-
-       case CASE(OXOR, TINT32):
-       case CASE(OXOR, TUINT32):
-       case CASE(OXOR, TPTR32):
-               a = AXORL;
-               break;
-
-       case CASE(OLROT, TINT8):
-       case CASE(OLROT, TUINT8):
-               a = AROLB;
-               break;
-
-       case CASE(OLROT, TINT16):
-       case CASE(OLROT, TUINT16):
-               a = AROLW;
-               break;
-
-       case CASE(OLROT, TINT32):
-       case CASE(OLROT, TUINT32):
-       case CASE(OLROT, TPTR32):
-               a = AROLL;
-               break;
-
-       case CASE(OLSH, TINT8):
-       case CASE(OLSH, TUINT8):
-               a = ASHLB;
-               break;
-
-       case CASE(OLSH, TINT16):
-       case CASE(OLSH, TUINT16):
-               a = ASHLW;
-               break;
-
-       case CASE(OLSH, TINT32):
-       case CASE(OLSH, TUINT32):
-       case CASE(OLSH, TPTR32):
-               a = ASHLL;
-               break;
-
-       case CASE(ORSH, TUINT8):
-               a = ASHRB;
-               break;
-
-       case CASE(ORSH, TUINT16):
-               a = ASHRW;
-               break;
-
-       case CASE(ORSH, TUINT32):
-       case CASE(ORSH, TPTR32):
-               a = ASHRL;
-               break;
-
-       case CASE(ORSH, TINT8):
-               a = ASARB;
-               break;
-
-       case CASE(ORSH, TINT16):
-               a = ASARW;
-               break;
-
-       case CASE(ORSH, TINT32):
-               a = ASARL;
-               break;
-
-       case CASE(OHMUL, TINT8):
-       case CASE(OMUL, TINT8):
-       case CASE(OMUL, TUINT8):
-               a = AIMULB;
-               break;
-
-       case CASE(OHMUL, TINT16):
-       case CASE(OMUL, TINT16):
-       case CASE(OMUL, TUINT16):
-               a = AIMULW;
-               break;
-
-       case CASE(OHMUL, TINT32):
-       case CASE(OMUL, TINT32):
-       case CASE(OMUL, TUINT32):
-       case CASE(OMUL, TPTR32):
-               a = AIMULL;
-               break;
-
-       case CASE(OHMUL, TUINT8):
-               a = AMULB;
-               break;
-
-       case CASE(OHMUL, TUINT16):
-               a = AMULW;
-               break;
-
-       case CASE(OHMUL, TUINT32):
-       case CASE(OHMUL, TPTR32):
-               a = AMULL;
-               break;
-
-       case CASE(ODIV, TINT8):
-       case CASE(OMOD, TINT8):
-               a = AIDIVB;
-               break;
-
-       case CASE(ODIV, TUINT8):
-       case CASE(OMOD, TUINT8):
-               a = ADIVB;
-               break;
-
-       case CASE(ODIV, TINT16):
-       case CASE(OMOD, TINT16):
-               a = AIDIVW;
-               break;
-
-       case CASE(ODIV, TUINT16):
-       case CASE(OMOD, TUINT16):
-               a = ADIVW;
-               break;
-
-       case CASE(ODIV, TINT32):
-       case CASE(OMOD, TINT32):
-               a = AIDIVL;
-               break;
-
-       case CASE(ODIV, TUINT32):
-       case CASE(ODIV, TPTR32):
-       case CASE(OMOD, TUINT32):
-       case CASE(OMOD, TPTR32):
-               a = ADIVL;
-               break;
-
-       case CASE(OEXTEND, TINT16):
-               a = ACWD;
-               break;
-
-       case CASE(OEXTEND, TINT32):
-               a = ACDQ;
-               break;
-       }
-       return a;
-}
-
-#define FCASE(a, b, c)  (((a)<<16)|((b)<<8)|(c))
-/*c2go int FCASE(int, int, int); */
-int
-foptoas(int op, Type *t, int flg)
-{
-       int et, a;
-
-       a = AXXX;
-       et = simtype[t->etype];
-
-       if(use_sse)
-               goto sse;
-
-       // If we need Fpop, it means we're working on
-       // two different floating-point registers, not memory.
-       // There the instruction only has a float64 form.
-       if(flg & Fpop)
-               et = TFLOAT64;
-
-       // clear Frev if unneeded
-       switch(op) {
-       case OADD:
-       case OMUL:
-               flg &= ~Frev;
-               break;
-       }
-
-       switch(FCASE(op, et, flg)) {
-       case FCASE(OADD, TFLOAT32, 0):
-               return AFADDF;
-       case FCASE(OADD, TFLOAT64, 0):
-               return AFADDD;
-       case FCASE(OADD, TFLOAT64, Fpop):
-               return AFADDDP;
-
-       case FCASE(OSUB, TFLOAT32, 0):
-               return AFSUBF;
-       case FCASE(OSUB, TFLOAT32, Frev):
-               return AFSUBRF;
-
-       case FCASE(OSUB, TFLOAT64, 0):
-               return AFSUBD;
-       case FCASE(OSUB, TFLOAT64, Frev):
-               return AFSUBRD;
-       case FCASE(OSUB, TFLOAT64, Fpop):
-               return AFSUBDP;
-       case FCASE(OSUB, TFLOAT64, Fpop|Frev):
-               return AFSUBRDP;
-
-       case FCASE(OMUL, TFLOAT32, 0):
-               return AFMULF;
-       case FCASE(OMUL, TFLOAT64, 0):
-               return AFMULD;
-       case FCASE(OMUL, TFLOAT64, Fpop):
-               return AFMULDP;
-
-       case FCASE(ODIV, TFLOAT32, 0):
-               return AFDIVF;
-       case FCASE(ODIV, TFLOAT32, Frev):
-               return AFDIVRF;
-
-       case FCASE(ODIV, TFLOAT64, 0):
-               return AFDIVD;
-       case FCASE(ODIV, TFLOAT64, Frev):
-               return AFDIVRD;
-       case FCASE(ODIV, TFLOAT64, Fpop):
-               return AFDIVDP;
-       case FCASE(ODIV, TFLOAT64, Fpop|Frev):
-               return AFDIVRDP;
-
-       case FCASE(OCMP, TFLOAT32, 0):
-               return AFCOMF;
-       case FCASE(OCMP, TFLOAT32, Fpop):
-               return AFCOMFP;
-       case FCASE(OCMP, TFLOAT64, 0):
-               return AFCOMD;
-       case FCASE(OCMP, TFLOAT64, Fpop):
-               return AFCOMDP;
-       case FCASE(OCMP, TFLOAT64, Fpop2):
-               return AFCOMDPP;
-       
-       case FCASE(OMINUS, TFLOAT32, 0):
-               return AFCHS;
-       case FCASE(OMINUS, TFLOAT64, 0):
-               return AFCHS;
-       }
-
-       fatal("foptoas %O %T %#x", op, t, flg);
-       return 0;
-
-sse:
-       switch(CASE(op, et)) {
-       default:
-               fatal("foptoas-sse: no entry %O-%T", op, t);
-               break;
-
-       case CASE(OCMP, TFLOAT32):
-               a = AUCOMISS;
-               break;
-
-       case CASE(OCMP, TFLOAT64):
-               a = AUCOMISD;
-               break;
-
-       case CASE(OAS, TFLOAT32):
-               a = AMOVSS;
-               break;
-
-       case CASE(OAS, TFLOAT64):
-               a = AMOVSD;
-               break;
-
-       case CASE(OADD, TFLOAT32):
-               a = AADDSS;
-               break;
-
-       case CASE(OADD, TFLOAT64):
-               a = AADDSD;
-               break;
-
-       case CASE(OSUB, TFLOAT32):
-               a = ASUBSS;
-               break;
-
-       case CASE(OSUB, TFLOAT64):
-               a = ASUBSD;
-               break;
-
-       case CASE(OMUL, TFLOAT32):
-               a = AMULSS;
-               break;
-
-       case CASE(OMUL, TFLOAT64):
-               a = AMULSD;
-               break;
-
-       case CASE(ODIV, TFLOAT32):
-               a = ADIVSS;
-               break;
-
-       case CASE(ODIV, TFLOAT64):
-               a = ADIVSD;
-               break;
-       }
-       return a;
-}
-
-
-static int     resvd[] =
-{
-//     REG_DI, // for movstring
-//     REG_SI, // for movstring
-
-       REG_AX, // for divide
-       REG_CX, // for shift
-       REG_DX, // for divide
-       REG_SP, // for stack
-
-       REG_BL, // because REG_BX can be allocated
-       REG_BH,
-};
-
-void
-ginit(void)
-{
-       int i;
-
-       for(i=0; i<nelem(reg); i++)
-               reg[i] = 1;
-       for(i=REG_AX; i<=REG_DI; i++)
-               reg[i] = 0;
-       for(i=REG_X0; i<=REG_X7; i++)
-               reg[i] = 0;
-       for(i=0; i<nelem(resvd); i++)
-               reg[resvd[i]]++;
-}
-
-uintptr regpc[MAXREG];
-
-void
-gclean(void)
-{
-       int i;
-
-       for(i=0; i<nelem(resvd); i++)
-               reg[resvd[i]]--;
-
-       for(i=REG_AX; i<=REG_DI; i++)
-               if(reg[i])
-                       yyerror("reg %R left allocated at %ux", i, regpc[i]);
-       for(i=REG_X0; i<=REG_X7; i++)
-               if(reg[i])
-                       yyerror("reg %R left allocated\n", i);
-}
-
-int
-anyregalloc(void)
-{
-       int i, j;
-
-       for(i=REG_AX; i<=REG_DI; i++) {
-               if(reg[i] == 0)
-                       goto ok;
-               for(j=0; j<nelem(resvd); j++)
-                       if(resvd[j] == i)
-                               goto ok;
-               return 1;
-       ok:;
-       }
-       for(i=REG_X0; i<=REG_X7; i++)
-               if(reg[i])
-                       return 1;
-       return 0;
-}
-
-/*
- * allocate register of type t, leave in n.
- * if o != N, o is desired fixed register.
- * caller must regfree(n).
- */
-void
-regalloc(Node *n, Type *t, Node *o)
-{
-       int i, et;
-
-       if(t == T)
-               fatal("regalloc: t nil");
-       et = simtype[t->etype];
-
-       switch(et) {
-       case TINT64:
-       case TUINT64:
-               fatal("regalloc64");
-
-       case TINT8:
-       case TUINT8:
-       case TINT16:
-       case TUINT16:
-       case TINT32:
-       case TUINT32:
-       case TPTR32:
-       case TPTR64:
-       case TBOOL:
-               if(o != N && o->op == OREGISTER) {
-                       i = o->val.u.reg;
-                       if(i >= REG_AX && i <= REG_DI)
-                               goto out;
-               }
-               for(i=REG_AX; i<=REG_DI; i++)
-                       if(reg[i] == 0)
-                               goto out;
-
-               print("registers allocated at\n");
-               for(i=REG_AX; i<=REG_DI; i++)
-                       print("\t%R\t%#lux\n", i, regpc[i]);
-               fatal("out of fixed registers");
-               goto err;
-
-       case TFLOAT32:
-       case TFLOAT64:
-               if(!use_sse) {
-                       i = REG_F0;
-                       goto out;
-               }
-               if(o != N && o->op == OREGISTER) {
-                       i = o->val.u.reg;
-                       if(i >= REG_X0 && i <= REG_X7)
-                               goto out;
-               }
-               for(i=REG_X0; i<=REG_X7; i++)
-                       if(reg[i] == 0)
-                               goto out;
-               print("registers allocated at\n");
-               for(i=REG_X0; i<=REG_X7; i++)
-                       print("\t%R\t%#lux\n", i, regpc[i]);
-               fatal("out of floating registers");
-       }
-       yyerror("regalloc: unknown type %T", t);
-
-err:
-       nodreg(n, t, 0);
-       return;
-
-out:
-       if(i == REG_SP)
-               print("alloc SP\n");
-       if(reg[i] == 0) {
-               regpc[i] = (uintptr)getcallerpc(&n);
-               if(i == REG_AX || i == REG_CX || i == REG_DX || i == REG_SP) {
-                       dump("regalloc-o", o);
-                       fatal("regalloc %R", i);
-               }
-       }
-       reg[i]++;
-       nodreg(n, t, i);
-}
-
-void
-regfree(Node *n)
-{
-       int i;
-       
-       if(n->op == ONAME)
-               return;
-       if(n->op != OREGISTER && n->op != OINDREG)
-               fatal("regfree: not a register");
-       i = n->val.u.reg;
-       if(i == REG_SP)
-               return;
-       if(i < 0 || i >= nelem(reg))
-               fatal("regfree: reg out of range");
-       if(reg[i] <= 0)
-               fatal("regfree: reg not allocated");
-       reg[i]--;
-       if(reg[i] == 0 && (i == REG_AX || i == REG_CX || i == REG_DX || i == REG_SP))
-               fatal("regfree %R", i);
-}
-
-/*
- * generate
- *     as $c, reg
- */
-void
-gconreg(int as, vlong c, int reg)
-{
-       Node n1, n2;
-
-       nodconst(&n1, types[TINT64], c);
-       nodreg(&n2, types[TINT64], reg);
-       gins(as, &n1, &n2);
-}
-
-/*
- * swap node contents
- */
-void
-nswap(Node *a, Node *b)
-{
-       Node t;
-
-       t = *a;
-       *a = *b;
-       *b = t;
-}
-
-/*
- * return constant i node.
- * overwritten by next call, but useful in calls to gins.
- */
-Node*
-ncon(uint32 i)
-{
-       static Node n;
-
-       if(n.type == T)
-               nodconst(&n, types[TUINT32], 0);
-       mpmovecfix(n.val.u.xval, i);
-       return &n;
-}
-
-Node sclean[10];
-int nsclean;
-
-/*
- * n is a 64-bit value.  fill in lo and hi to refer to its 32-bit halves.
- */
-void
-split64(Node *n, Node *lo, Node *hi)
-{
-       Node n1;
-       int64 i;
-
-       if(!is64(n->type))
-               fatal("split64 %T", n->type);
-
-       if(nsclean >= nelem(sclean))
-               fatal("split64 clean");
-       sclean[nsclean].op = OEMPTY;
-       nsclean++;
-       switch(n->op) {
-       default:
-               switch(n->op) {
-               default:
-                       if(!dotaddable(n, &n1)) {
-                               igen(n, &n1, N);
-                               sclean[nsclean-1] = n1;
-                       }
-                       n = &n1;
-                       break;
-               case ONAME:
-                       if(n->class == PPARAMREF) {
-                               cgen(n->heapaddr, &n1);
-                               sclean[nsclean-1] = n1;
-                               n = &n1;
-                       }
-                       break;
-               case OINDREG:
-                       // nothing
-                       break;
-               }
-               *lo = *n;
-               *hi = *n;
-               lo->type = types[TUINT32];
-               if(n->type->etype == TINT64)
-                       hi->type = types[TINT32];
-               else
-                       hi->type = types[TUINT32];
-               hi->xoffset += 4;
-               break;
-
-       case OLITERAL:
-               convconst(&n1, n->type, &n->val);
-               i = mpgetfix(n1.val.u.xval);
-               nodconst(lo, types[TUINT32], (uint32)i);
-               i >>= 32;
-               if(n->type->etype == TINT64)
-                       nodconst(hi, types[TINT32], (int32)i);
-               else
-                       nodconst(hi, types[TUINT32], (uint32)i);
-               break;
-       }
-}
-
-void
-splitclean(void)
-{
-       if(nsclean <= 0)
-               fatal("splitclean");
-       nsclean--;
-       if(sclean[nsclean].op != OEMPTY)
-               regfree(&sclean[nsclean]);
-}
-
-/*
- * set up nodes representing fp constants
- */
-Node zerof;
-Node two64f;
-Node two63f;
-
-void
-bignodes(void)
-{
-       static int did;
-
-       if(did)
-               return;
-       did = 1;
-
-       two64f = *ncon(0);
-       two64f.type = types[TFLOAT64];
-       two64f.val.ctype = CTFLT;
-       two64f.val.u.fval = mal(sizeof *two64f.val.u.fval);
-       mpmovecflt(two64f.val.u.fval, 18446744073709551616.);
-
-       two63f = two64f;
-       two63f.val.u.fval = mal(sizeof *two63f.val.u.fval);
-       mpmovecflt(two63f.val.u.fval, 9223372036854775808.);
-
-       zerof = two64f;
-       zerof.val.u.fval = mal(sizeof *zerof.val.u.fval);
-       mpmovecflt(zerof.val.u.fval, 0);
-}
-
-void
-memname(Node *n, Type *t)
-{
-       tempname(n, t);
-       strcpy(namebuf, n->sym->name);
-       namebuf[0] = '.';       // keep optimizer from registerizing
-       n->sym = lookup(namebuf);
-       n->orig->sym = n->sym;
-}
-
-static void floatmove(Node *f, Node *t);
-static void floatmove_387(Node *f, Node *t);
-static void floatmove_sse(Node *f, Node *t);
-
-void
-gmove(Node *f, Node *t)
-{
-       int a, ft, tt;
-       Type *cvt;
-       Node r1, r2, flo, fhi, tlo, thi, con;
-
-       if(debug['M'])
-               print("gmove %N -> %N\n", f, t);
-
-       ft = simsimtype(f->type);
-       tt = simsimtype(t->type);
-       cvt = t->type;
-       
-       if(iscomplex[ft] || iscomplex[tt]) {
-               complexmove(f, t);
-               return;
-       }
-       if(isfloat[ft] || isfloat[tt]) {
-               floatmove(f, t);
-               return;
-       }
-
-       // cannot have two integer memory operands;
-       // except 64-bit, which always copies via registers anyway.
-       if(isint[ft] && isint[tt] && !is64(f->type) && !is64(t->type) && ismem(f) && ismem(t))
-               goto hard;
-
-       // convert constant to desired type
-       if(f->op == OLITERAL) {
-               convconst(&con, t->type, &f->val);
-               f = &con;
-               ft = simsimtype(con.type);
-       }
-
-       // value -> value copy, only one memory operand.
-       // figure out the instruction to use.
-       // break out of switch for one-instruction gins.
-       // goto rdst for "destination must be register".
-       // goto hard for "convert to cvt type first".
-       // otherwise handle and return.
-
-       switch(CASE(ft, tt)) {
-       default:
-               goto fatal;
-
-       /*
-        * integer copy and truncate
-        */
-       case CASE(TINT8, TINT8):        // same size
-       case CASE(TINT8, TUINT8):
-       case CASE(TUINT8, TINT8):
-       case CASE(TUINT8, TUINT8):
-               a = AMOVB;
-               break;
-
-       case CASE(TINT16, TINT8):       // truncate
-       case CASE(TUINT16, TINT8):
-       case CASE(TINT32, TINT8):
-       case CASE(TUINT32, TINT8):
-       case CASE(TINT16, TUINT8):
-       case CASE(TUINT16, TUINT8):
-       case CASE(TINT32, TUINT8):
-       case CASE(TUINT32, TUINT8):
-               a = AMOVB;
-               goto rsrc;
-
-       case CASE(TINT64, TINT8):       // truncate low word
-       case CASE(TUINT64, TINT8):
-       case CASE(TINT64, TUINT8):
-       case CASE(TUINT64, TUINT8):
-               split64(f, &flo, &fhi);
-               nodreg(&r1, t->type, REG_AX);
-               gmove(&flo, &r1);
-               gins(AMOVB, &r1, t);
-               splitclean();
-               return;
-
-       case CASE(TINT16, TINT16):      // same size
-       case CASE(TINT16, TUINT16):
-       case CASE(TUINT16, TINT16):
-       case CASE(TUINT16, TUINT16):
-               a = AMOVW;
-               break;
-
-       case CASE(TINT32, TINT16):      // truncate
-       case CASE(TUINT32, TINT16):
-       case CASE(TINT32, TUINT16):
-       case CASE(TUINT32, TUINT16):
-               a = AMOVW;
-               goto rsrc;
-
-       case CASE(TINT64, TINT16):      // truncate low word
-       case CASE(TUINT64, TINT16):
-       case CASE(TINT64, TUINT16):
-       case CASE(TUINT64, TUINT16):
-               split64(f, &flo, &fhi);
-               nodreg(&r1, t->type, REG_AX);
-               gmove(&flo, &r1);
-               gins(AMOVW, &r1, t);
-               splitclean();
-               return;
-
-       case CASE(TINT32, TINT32):      // same size
-       case CASE(TINT32, TUINT32):
-       case CASE(TUINT32, TINT32):
-       case CASE(TUINT32, TUINT32):
-               a = AMOVL;
-               break;
-
-       case CASE(TINT64, TINT32):      // truncate
-       case CASE(TUINT64, TINT32):
-       case CASE(TINT64, TUINT32):
-       case CASE(TUINT64, TUINT32):
-               split64(f, &flo, &fhi);
-               nodreg(&r1, t->type, REG_AX);
-               gmove(&flo, &r1);
-               gins(AMOVL, &r1, t);
-               splitclean();
-               return;
-
-       case CASE(TINT64, TINT64):      // same size
-       case CASE(TINT64, TUINT64):
-       case CASE(TUINT64, TINT64):
-       case CASE(TUINT64, TUINT64):
-               split64(f, &flo, &fhi);
-               split64(t, &tlo, &thi);
-               if(f->op == OLITERAL) {
-                       gins(AMOVL, &flo, &tlo);
-                       gins(AMOVL, &fhi, &thi);
-               } else {
-                       nodreg(&r1, types[TUINT32], REG_AX);
-                       nodreg(&r2, types[TUINT32], REG_DX);
-                       gins(AMOVL, &flo, &r1);
-                       gins(AMOVL, &fhi, &r2);
-                       gins(AMOVL, &r1, &tlo);
-                       gins(AMOVL, &r2, &thi);
-               }
-               splitclean();
-               splitclean();
-               return;
-
-       /*
-        * integer up-conversions
-        */
-       case CASE(TINT8, TINT16):       // sign extend int8
-       case CASE(TINT8, TUINT16):
-               a = AMOVBWSX;
-               goto rdst;
-       case CASE(TINT8, TINT32):
-       case CASE(TINT8, TUINT32):
-               a = AMOVBLSX;
-               goto rdst;
-       case CASE(TINT8, TINT64):       // convert via int32
-       case CASE(TINT8, TUINT64):
-               cvt = types[TINT32];
-               goto hard;
-
-       case CASE(TUINT8, TINT16):      // zero extend uint8
-       case CASE(TUINT8, TUINT16):
-               a = AMOVBWZX;
-               goto rdst;
-       case CASE(TUINT8, TINT32):
-       case CASE(TUINT8, TUINT32):
-               a = AMOVBLZX;
-               goto rdst;
-       case CASE(TUINT8, TINT64):      // convert via uint32
-       case CASE(TUINT8, TUINT64):
-               cvt = types[TUINT32];
-               goto hard;
-
-       case CASE(TINT16, TINT32):      // sign extend int16
-       case CASE(TINT16, TUINT32):
-               a = AMOVWLSX;
-               goto rdst;
-       case CASE(TINT16, TINT64):      // convert via int32
-       case CASE(TINT16, TUINT64):
-               cvt = types[TINT32];
-               goto hard;
-
-       case CASE(TUINT16, TINT32):     // zero extend uint16
-       case CASE(TUINT16, TUINT32):
-               a = AMOVWLZX;
-               goto rdst;
-       case CASE(TUINT16, TINT64):     // convert via uint32
-       case CASE(TUINT16, TUINT64):
-               cvt = types[TUINT32];
-               goto hard;
-
-       case CASE(TINT32, TINT64):      // sign extend int32
-       case CASE(TINT32, TUINT64):
-               split64(t, &tlo, &thi);
-               nodreg(&flo, tlo.type, REG_AX);
-               nodreg(&fhi, thi.type, REG_DX);
-               gmove(f, &flo);
-               gins(ACDQ, N, N);
-               gins(AMOVL, &flo, &tlo);
-               gins(AMOVL, &fhi, &thi);
-               splitclean();
-               return;
-
-       case CASE(TUINT32, TINT64):     // zero extend uint32
-       case CASE(TUINT32, TUINT64):
-               split64(t, &tlo, &thi);
-               gmove(f, &tlo);
-               gins(AMOVL, ncon(0), &thi);
-               splitclean();
-               return;
-       }
-
-       gins(a, f, t);
-       return;
-
-rsrc:
-       // requires register source
-       regalloc(&r1, f->type, t);
-       gmove(f, &r1);
-       gins(a, &r1, t);
-       regfree(&r1);
-       return;
-
-rdst:
-       // requires register destination
-       regalloc(&r1, t->type, t);
-       gins(a, f, &r1);
-       gmove(&r1, t);
-       regfree(&r1);
-       return;
-
-hard:
-       // requires register intermediate
-       regalloc(&r1, cvt, t);
-       gmove(f, &r1);
-       gmove(&r1, t);
-       regfree(&r1);
-       return;
-
-fatal:
-       // should not happen
-       fatal("gmove %N -> %N", f, t);
-}
-
-static void
-floatmove(Node *f, Node *t)
-{
-       Node r1, r2, t1, t2, tlo, thi, con, f0, f1, ax, dx, cx;
-       Type *cvt;
-       int ft, tt;
-       Prog *p1, *p2, *p3;
-
-       ft = simsimtype(f->type);
-       tt = simsimtype(t->type);
-       cvt = t->type;
-
-       // cannot have two floating point memory operands.
-       if(isfloat[ft] && isfloat[tt] && ismem(f) && ismem(t))
-               goto hard;
-
-       // convert constant to desired type
-       if(f->op == OLITERAL) {
-               convconst(&con, t->type, &f->val);
-               f = &con;
-               ft = simsimtype(con.type);
-
-               // some constants can't move directly to memory.
-               if(ismem(t)) {
-                       // float constants come from memory.
-                       if(isfloat[tt])
-                               goto hard;
-               }
-       }
-
-       // value -> value copy, only one memory operand.
-       // figure out the instruction to use.
-       // break out of switch for one-instruction gins.
-       // goto rdst for "destination must be register".
-       // goto hard for "convert to cvt type first".
-       // otherwise handle and return.
-
-       switch(CASE(ft, tt)) {
-       default:
-               if(use_sse)
-                       floatmove_sse(f, t);
-               else
-                       floatmove_387(f, t);
-               return;
-
-       // float to very long integer.
-       case CASE(TFLOAT32, TINT64):
-       case CASE(TFLOAT64, TINT64):
-               if(f->op == OREGISTER) {
-                       cvt = f->type;
-                       goto hardmem;
-               }
-               nodreg(&r1, types[ft], REG_F0);
-               if(ft == TFLOAT32)
-                       gins(AFMOVF, f, &r1);
-               else
-                       gins(AFMOVD, f, &r1);
-
-               // set round to zero mode during conversion
-               memname(&t1, types[TUINT16]);
-               memname(&t2, types[TUINT16]);
-               gins(AFSTCW, N, &t1);
-               gins(AMOVW, ncon(0xf7f), &t2);
-               gins(AFLDCW, &t2, N);
-               if(tt == TINT16)
-                       gins(AFMOVWP, &r1, t);
-               else if(tt == TINT32)
-                       gins(AFMOVLP, &r1, t);
-               else
-                       gins(AFMOVVP, &r1, t);
-               gins(AFLDCW, &t1, N);
-               return;
-
-       case CASE(TFLOAT32, TUINT64):
-       case CASE(TFLOAT64, TUINT64):
-               if(!ismem(f)) {
-                       cvt = f->type;
-                       goto hardmem;
-               }
-               bignodes();
-               nodreg(&f0, types[ft], REG_F0);
-               nodreg(&f1, types[ft], REG_F0 + 1);
-               nodreg(&ax, types[TUINT16], REG_AX);
-
-               if(ft == TFLOAT32)
-                       gins(AFMOVF, f, &f0);
-               else
-                       gins(AFMOVD, f, &f0);
-
-               // if 0 > v { answer = 0 }
-               gins(AFMOVD, &zerof, &f0);
-               gins(AFUCOMIP, &f0, &f1);
-               p1 = gbranch(optoas(OGT, types[tt]), T, 0);
-               // if 1<<64 <= v { answer = 0 too }
-               gins(AFMOVD, &two64f, &f0);
-               gins(AFUCOMIP, &f0, &f1);
-               p2 = gbranch(optoas(OGT, types[tt]), T, 0);
-               patch(p1, pc);
-               gins(AFMOVVP, &f0, t);  // don't care about t, but will pop the stack
-               split64(t, &tlo, &thi);
-               gins(AMOVL, ncon(0), &tlo);
-               gins(AMOVL, ncon(0), &thi);
-               splitclean();
-               p1 = gbranch(AJMP, T, 0);
-               patch(p2, pc);
-
-               // in range; algorithm is:
-               //      if small enough, use native float64 -> int64 conversion.
-               //      otherwise, subtract 2^63, convert, and add it back.
-
-               // set round to zero mode during conversion
-               memname(&t1, types[TUINT16]);
-               memname(&t2, types[TUINT16]);
-               gins(AFSTCW, N, &t1);
-               gins(AMOVW, ncon(0xf7f), &t2);
-               gins(AFLDCW, &t2, N);
-
-               // actual work
-               gins(AFMOVD, &two63f, &f0);
-               gins(AFUCOMIP, &f0, &f1);
-               p2 = gbranch(optoas(OLE, types[tt]), T, 0);
-               gins(AFMOVVP, &f0, t);
-               p3 = gbranch(AJMP, T, 0);
-               patch(p2, pc);
-               gins(AFMOVD, &two63f, &f0);
-               gins(AFSUBDP, &f0, &f1);
-               gins(AFMOVVP, &f0, t);
-               split64(t, &tlo, &thi);
-               gins(AXORL, ncon(0x80000000), &thi);    // + 2^63
-               patch(p3, pc);
-               splitclean();
-               // restore rounding mode
-               gins(AFLDCW, &t1, N);
-
-               patch(p1, pc);
-               return;
-
-       /*
-        * integer to float
-        */
-       case CASE(TINT64, TFLOAT32):
-       case CASE(TINT64, TFLOAT64):
-               if(t->op == OREGISTER)
-                       goto hardmem;
-               nodreg(&f0, t->type, REG_F0);
-               gins(AFMOVV, f, &f0);
-               if(tt == TFLOAT32)
-                       gins(AFMOVFP, &f0, t);
-               else
-                       gins(AFMOVDP, &f0, t);
-               return;
-
-       case CASE(TUINT64, TFLOAT32):
-       case CASE(TUINT64, TFLOAT64):
-               // algorithm is:
-               //      if small enough, use native int64 -> float64 conversion.
-               //      otherwise, halve (rounding to odd?), convert, and double.
-               nodreg(&ax, types[TUINT32], REG_AX);
-               nodreg(&dx, types[TUINT32], REG_DX);
-               nodreg(&cx, types[TUINT32], REG_CX);
-               tempname(&t1, f->type);
-               split64(&t1, &tlo, &thi);
-               gmove(f, &t1);
-               gins(ACMPL, &thi, ncon(0));
-               p1 = gbranch(AJLT, T, 0);
-               // native
-               nodreg(&r1, types[tt], REG_F0);
-               gins(AFMOVV, &t1, &r1);
-               if(tt == TFLOAT32)
-                       gins(AFMOVFP, &r1, t);
-               else
-                       gins(AFMOVDP, &r1, t);
-               p2 = gbranch(AJMP, T, 0);
-               // simulated
-               patch(p1, pc);
-               gmove(&tlo, &ax);
-               gmove(&thi, &dx);
-               p1 = gins(ASHRL, ncon(1), &ax);
-               p1->from.index = REG_DX;        // double-width shift DX -> AX
-               p1->from.scale = 0;
-               gins(AMOVL, ncon(0), &cx);
-               gins(ASETCC, N, &cx);
-               gins(AORL, &cx, &ax);
-               gins(ASHRL, ncon(1), &dx);
-               gmove(&dx, &thi);
-               gmove(&ax, &tlo);
-               nodreg(&r1, types[tt], REG_F0);
-               nodreg(&r2, types[tt], REG_F0 + 1);
-               gins(AFMOVV, &t1, &r1);
-               gins(AFMOVD, &r1, &r1);
-               gins(AFADDDP, &r1, &r2);
-               if(tt == TFLOAT32)
-                       gins(AFMOVFP, &r1, t);
-               else
-                       gins(AFMOVDP, &r1, t);
-               patch(p2, pc);
-               splitclean();
-               return;
-       }
-
-hard:
-       // requires register intermediate
-       regalloc(&r1, cvt, t);
-       gmove(f, &r1);
-       gmove(&r1, t);
-       regfree(&r1);
-       return;
-
-hardmem:
-       // requires memory intermediate
-       tempname(&r1, cvt);
-       gmove(f, &r1);
-       gmove(&r1, t);
-       return;
-}
-
-static void
-floatmove_387(Node *f, Node *t)
-{
-       Node r1, t1, t2;
-       Type *cvt;
-       Prog *p1, *p2, *p3;
-       int a, ft, tt;
-
-       ft = simsimtype(f->type);
-       tt = simsimtype(t->type);
-       cvt = t->type;
-
-       switch(CASE(ft, tt)) {
-       default:
-               goto fatal;
-
-       /*
-       * float to integer
-       */
-       case CASE(TFLOAT32, TINT16):
-       case CASE(TFLOAT32, TINT32):
-       case CASE(TFLOAT32, TINT64):
-       case CASE(TFLOAT64, TINT16):
-       case CASE(TFLOAT64, TINT32):
-       case CASE(TFLOAT64, TINT64):
-               if(t->op == OREGISTER)
-                       goto hardmem;
-               nodreg(&r1, types[ft], REG_F0);
-               if(f->op != OREGISTER) {
-                       if(ft == TFLOAT32)
-                               gins(AFMOVF, f, &r1);
-                       else
-                               gins(AFMOVD, f, &r1);
-               }
-
-               // set round to zero mode during conversion
-               memname(&t1, types[TUINT16]);
-               memname(&t2, types[TUINT16]);
-               gins(AFSTCW, N, &t1);
-               gins(AMOVW, ncon(0xf7f), &t2);
-               gins(AFLDCW, &t2, N);
-               if(tt == TINT16)
-                       gins(AFMOVWP, &r1, t);
-               else if(tt == TINT32)
-                       gins(AFMOVLP, &r1, t);
-               else
-                       gins(AFMOVVP, &r1, t);
-               gins(AFLDCW, &t1, N);
-               return;
-
-       case CASE(TFLOAT32, TINT8):
-       case CASE(TFLOAT32, TUINT16):
-       case CASE(TFLOAT32, TUINT8):
-       case CASE(TFLOAT64, TINT8):
-       case CASE(TFLOAT64, TUINT16):
-       case CASE(TFLOAT64, TUINT8):
-               // convert via int32.
-               tempname(&t1, types[TINT32]);
-               gmove(f, &t1);
-               switch(tt) {
-               default:
-                       fatal("gmove %N", t);
-               case TINT8:
-                       gins(ACMPL, &t1, ncon(-0x80));
-                       p1 = gbranch(optoas(OLT, types[TINT32]), T, -1);
-                       gins(ACMPL, &t1, ncon(0x7f));
-                       p2 = gbranch(optoas(OGT, types[TINT32]), T, -1);
-                       p3 = gbranch(AJMP, T, 0);
-                       patch(p1, pc);
-                       patch(p2, pc);
-                       gmove(ncon(-0x80), &t1);
-                       patch(p3, pc);
-                       gmove(&t1, t);
-                       break;
-               case TUINT8:
-                       gins(ATESTL, ncon(0xffffff00), &t1);
-                       p1 = gbranch(AJEQ, T, +1);
-                       gins(AMOVL, ncon(0), &t1);
-                       patch(p1, pc);
-                       gmove(&t1, t);
-                       break;
-               case TUINT16:
-                       gins(ATESTL, ncon(0xffff0000), &t1);
-                       p1 = gbranch(AJEQ, T, +1);
-                       gins(AMOVL, ncon(0), &t1);
-                       patch(p1, pc);
-                       gmove(&t1, t);
-                       break;
-               }
-               return;
-
-       case CASE(TFLOAT32, TUINT32):
-       case CASE(TFLOAT64, TUINT32):
-               // convert via int64.
-               cvt = types[TINT64];
-               goto hardmem;
-
-       /*
-        * integer to float
-        */
-       case CASE(TINT16, TFLOAT32):
-       case CASE(TINT16, TFLOAT64):
-       case CASE(TINT32, TFLOAT32):
-       case CASE(TINT32, TFLOAT64):
-       case CASE(TINT64, TFLOAT32):
-       case CASE(TINT64, TFLOAT64):
-               if(t->op != OREGISTER)
-                       goto hard;
-               if(f->op == OREGISTER) {
-                       cvt = f->type;
-                       goto hardmem;
-               }
-               switch(ft) {
-               case TINT16:
-                       a = AFMOVW;
-                       break;
-               case TINT32:
-                       a = AFMOVL;
-                       break;
-               default:
-                       a = AFMOVV;
-                       break;
-               }
-               break;
-
-       case CASE(TINT8, TFLOAT32):
-       case CASE(TINT8, TFLOAT64):
-       case CASE(TUINT16, TFLOAT32):
-       case CASE(TUINT16, TFLOAT64):
-       case CASE(TUINT8, TFLOAT32):
-       case CASE(TUINT8, TFLOAT64):
-               // convert via int32 memory
-               cvt = types[TINT32];
-               goto hardmem;
-
-       case CASE(TUINT32, TFLOAT32):
-       case CASE(TUINT32, TFLOAT64):
-               // convert via int64 memory
-               cvt = types[TINT64];
-               goto hardmem;
-
-       /*
-        * float to float
-        */
-       case CASE(TFLOAT32, TFLOAT32):
-       case CASE(TFLOAT64, TFLOAT64):
-               // The way the code generator uses floating-point
-               // registers, a move from F0 to F0 is intended as a no-op.
-               // On the x86, it's not: it pushes a second copy of F0
-               // on the floating point stack.  So toss it away here.
-               // Also, F0 is the *only* register we ever evaluate
-               // into, so we should only see register/register as F0/F0.
-               if(ismem(f) && ismem(t))
-                       goto hard;
-               if(f->op == OREGISTER && t->op == OREGISTER) {
-                       if(f->val.u.reg != REG_F0 || t->val.u.reg != REG_F0)
-                               goto fatal;
-                       return;
-               }
-               a = AFMOVF;
-               if(ft == TFLOAT64)
-                       a = AFMOVD;
-               if(ismem(t)) {
-                       if(f->op != OREGISTER || f->val.u.reg != REG_F0)
-                               fatal("gmove %N", f);
-                       a = AFMOVFP;
-                       if(ft == TFLOAT64)
-                               a = AFMOVDP;
-               }
-               break;
-
-       case CASE(TFLOAT32, TFLOAT64):
-               if(ismem(f) && ismem(t))
-                       goto hard;
-               if(f->op == OREGISTER && t->op == OREGISTER) {
-                       if(f->val.u.reg != REG_F0 || t->val.u.reg != REG_F0)
-                               goto fatal;
-                       return;
-               }
-               if(f->op == OREGISTER)
-                       gins(AFMOVDP, f, t);
-               else
-                       gins(AFMOVF, f, t);
-               return;
-
-       case CASE(TFLOAT64, TFLOAT32):
-               if(ismem(f) && ismem(t))
-                       goto hard;
-               if(f->op == OREGISTER && t->op == OREGISTER) {
-                       tempname(&r1, types[TFLOAT32]);
-                       gins(AFMOVFP, f, &r1);
-                       gins(AFMOVF, &r1, t);
-                       return;
-               }
-               if(f->op == OREGISTER)
-                       gins(AFMOVFP, f, t);
-               else
-                       gins(AFMOVD, f, t);
-               return;
-       }
-
-       gins(a, f, t);
-       return;
-
-hard:
-       // requires register intermediate
-       regalloc(&r1, cvt, t);
-       gmove(f, &r1);
-       gmove(&r1, t);
-       regfree(&r1);
-       return;
-
-hardmem:
-       // requires memory intermediate
-       tempname(&r1, cvt);
-       gmove(f, &r1);
-       gmove(&r1, t);
-       return;
-
-fatal:
-       // should not happen
-       fatal("gmove %lN -> %lN", f, t);
-       return;
-}
-
-static void
-floatmove_sse(Node *f, Node *t)
-{
-       Node r1;
-       Type *cvt;
-       int a, ft, tt;
-
-       ft = simsimtype(f->type);
-       tt = simsimtype(t->type);
-
-       switch(CASE(ft, tt)) {
-       default:
-               // should not happen
-               fatal("gmove %N -> %N", f, t);
-               return;
-       /*
-       * float to integer
-       */
-       case CASE(TFLOAT32, TINT16):
-       case CASE(TFLOAT32, TINT8):
-       case CASE(TFLOAT32, TUINT16):
-       case CASE(TFLOAT32, TUINT8):
-       case CASE(TFLOAT64, TINT16):
-       case CASE(TFLOAT64, TINT8):
-       case CASE(TFLOAT64, TUINT16):
-       case CASE(TFLOAT64, TUINT8):
-               // convert via int32.
-               cvt = types[TINT32];
-               goto hard;
-
-       case CASE(TFLOAT32, TUINT32):
-       case CASE(TFLOAT64, TUINT32):
-               // convert via int64.
-               cvt = types[TINT64];
-               goto hardmem;
-
-       case CASE(TFLOAT32, TINT32):
-               a = ACVTTSS2SL;
-               goto rdst;
-
-       case CASE(TFLOAT64, TINT32):
-               a = ACVTTSD2SL;
-               goto rdst;
-
-       /*
-        * integer to float
-        */
-       case CASE(TINT8, TFLOAT32):
-       case CASE(TINT8, TFLOAT64):
-       case CASE(TINT16, TFLOAT32):
-       case CASE(TINT16, TFLOAT64):
-       case CASE(TUINT16, TFLOAT32):
-       case CASE(TUINT16, TFLOAT64):
-       case CASE(TUINT8, TFLOAT32):
-       case CASE(TUINT8, TFLOAT64):
-               // convert via int32 memory
-               cvt = types[TINT32];
-               goto hard;
-
-       case CASE(TUINT32, TFLOAT32):
-       case CASE(TUINT32, TFLOAT64):
-               // convert via int64 memory
-               cvt = types[TINT64];
-               goto hardmem;
-
-       case CASE(TINT32, TFLOAT32):
-               a = ACVTSL2SS;
-               goto rdst;
-
-       case CASE(TINT32, TFLOAT64):
-               a = ACVTSL2SD;
-               goto rdst;
-
-       /*
-        * float to float
-        */
-       case CASE(TFLOAT32, TFLOAT32):
-               a = AMOVSS;
-               break;
-
-       case CASE(TFLOAT64, TFLOAT64):
-               a = AMOVSD;
-               break;
-
-       case CASE(TFLOAT32, TFLOAT64):
-               a = ACVTSS2SD;
-               goto rdst;
-
-       case CASE(TFLOAT64, TFLOAT32):
-               a = ACVTSD2SS;
-               goto rdst;
-       }
-
-       gins(a, f, t);
-       return;
-
-hard:
-       // requires register intermediate
-       regalloc(&r1, cvt, t);
-       gmove(f, &r1);
-       gmove(&r1, t);
-       regfree(&r1);
-       return;
-
-hardmem:
-       // requires memory intermediate
-       tempname(&r1, cvt);
-       gmove(f, &r1);
-       gmove(&r1, t);
-       return;
-
-rdst:
-       // requires register destination
-       regalloc(&r1, t->type, t);
-       gins(a, f, &r1);
-       gmove(&r1, t);
-       regfree(&r1);
-       return;
-}
-
-int
-samaddr(Node *f, Node *t)
-{
-
-       if(f->op != t->op)
-               return 0;
-
-       switch(f->op) {
-       case OREGISTER:
-               if(f->val.u.reg != t->val.u.reg)
-                       break;
-               return 1;
-       }
-       return 0;
-}
-/*
- * generate one instruction:
- *     as f, t
- */
-Prog*
-gins(int as, Node *f, Node *t)
-{
-       Prog *p;
-       Addr af, at;
-       int w;
-
-       if(as == AFMOVF && f && f->op == OREGISTER && t && t->op == OREGISTER)
-               fatal("gins MOVF reg, reg");
-       if(as == ACVTSD2SS && f && f->op == OLITERAL)
-               fatal("gins CVTSD2SS const");
-       if(as == AMOVSD && t && t->op == OREGISTER && t->val.u.reg == REG_F0)
-               fatal("gins MOVSD into F0");
-
-       switch(as) {
-       case AMOVB:
-       case AMOVW:
-       case AMOVL:
-               if(f != N && t != N && samaddr(f, t))
-                       return nil;
-               break;
-       
-       case ALEAL:
-               if(f != N && isconst(f, CTNIL))
-                       fatal("gins LEAL nil %T", f->type);
-               break;
-       }
-
-       memset(&af, 0, sizeof af);
-       memset(&at, 0, sizeof at);
-       if(f != N)
-               naddr(f, &af, 1);
-       if(t != N)
-               naddr(t, &at, 1);
-       p = prog(as);
-       if(f != N)
-               p->from = af;
-       if(t != N)
-               p->to = at;
-       if(debug['g'])
-               print("%P\n", p);
-
-       w = 0;
-       switch(as) {
-       case AMOVB:
-               w = 1;
-               break;
-       case AMOVW:
-               w = 2;
-               break;
-       case AMOVL:
-               w = 4;
-               break;
-       }
-
-       if(1 && w != 0 && f != N && (af.width > w || at.width > w)) {
-               dump("bad width from:", f);
-               dump("bad width to:", t);
-               fatal("bad width: %P (%d, %d)\n", p, af.width, at.width);
-       }
-       if(p->to.type == TYPE_ADDR && w > 0)
-               fatal("bad use of addr: %P", p);
-
-       return p;
-}
-
-int
-dotaddable(Node *n, Node *n1)
-{
-       int o;
-       int64 oary[10];
-       Node *nn;
-
-       if(n->op != ODOT)
-               return 0;
-
-       o = dotoffset(n, oary, &nn);
-       if(nn != N && nn->addable && o == 1 && oary[0] >= 0) {
-               *n1 = *nn;
-               n1->type = n->type;
-               n1->xoffset += oary[0];
-               return 1;
-       }
-       return 0;
-}
-
-void
-sudoclean(void)
-{
-}
-
-int
-sudoaddable(int as, Node *n, Addr *a)
-{
-       USED(as);
-       USED(n);
-
-       memset(a, 0, sizeof *a);
-       return 0;
-}
similarity index 100%
rename from src/cmd/new8g/gsubr.go
rename to src/cmd/8g/gsubr.go
diff --git a/src/cmd/8g/peep.c b/src/cmd/8g/peep.c
deleted file mode 100644 (file)
index 712c8fe..0000000
+++ /dev/null
@@ -1,773 +0,0 @@
-// Derived from Inferno utils/6c/peep.c
-// http://code.google.com/p/inferno-os/source/browse/utils/6c/peep.c
-//
-//     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 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 <u.h>
-#include <libc.h>
-#include "gg.h"
-#include "../gc/popt.h"
-
-enum {
-       REGEXT = 0,
-       exregoffset = REG_DI,
-};
-
-static void    conprop(Flow *r);
-static void    elimshortmov(Graph*);
-static int     subprop(Flow*);
-static int     copyprop(Graph*, Flow*);
-static int     copy1(Adr*, Adr*, Flow*, int);
-static int     copyas(Adr*, Adr*);
-static int     copyau(Adr*, Adr*);
-static int     copysub(Adr*, Adr*, Adr*, int);
-static int     copyu(Prog*, Adr*, Adr*);
-
-static uint32  gactive;
-
-// do we need the carry bit
-static int
-needc(Prog *p)
-{
-       ProgInfo info;
-
-       while(p != P) {
-               proginfo(&info, p);
-               if(info.flags & UseCarry)
-                       return 1;
-               if(info.flags & (SetCarry|KillCarry))
-                       return 0;
-               p = p->link;
-       }
-       return 0;
-}
-
-static Flow*
-rnops(Flow *r)
-{
-       Prog *p;
-       Flow *r1;
-
-       if(r != nil)
-       for(;;) {
-               p = r->prog;
-               if(p->as != ANOP || p->from.type != TYPE_NONE || p->to.type != TYPE_NONE)
-                       break;
-               r1 = uniqs(r);
-               if(r1 == nil)
-                       break;
-               r = r1;
-       }
-       return r;
-}
-
-void
-peep(Prog *firstp)
-{
-       Flow *r, *r1;
-       Graph *g;
-       Prog *p, *p1;
-       int t;
-
-       g = flowstart(firstp, 0);
-       if(g == nil)
-               return;
-       gactive = 0;
-
-       // byte, word arithmetic elimination.
-       elimshortmov(g);
-
-       // constant propagation
-       // find MOV $con,R followed by
-       // another MOV $con,R without
-       // setting R in the interim
-       for(r=g->start; r!=nil; r=r->link) {
-               p = r->prog;
-               switch(p->as) {
-               case ALEAL:
-                       if(regtyp(&p->to))
-                       if(p->from.sym != nil)
-                       if(p->from.index == REG_NONE)
-                               conprop(r);
-                       break;
-
-               case AMOVB:
-               case AMOVW:
-               case AMOVL:
-               case AMOVSS:
-               case AMOVSD:
-                       if(regtyp(&p->to))
-                       if(p->from.type == TYPE_CONST || p->from.type == TYPE_FCONST)
-                               conprop(r);
-                       break;
-               }
-       }
-
-loop1:
-       if(debug['P'] && debug['v'])
-               dumpit("loop1", g->start, 0);
-
-       t = 0;
-       for(r=g->start; r!=nil; r=r->link) {
-               p = r->prog;
-               switch(p->as) {
-               case AMOVL:
-               case AMOVSS:
-               case AMOVSD:
-                       if(regtyp(&p->to))
-                       if(regtyp(&p->from)) {
-                               if(copyprop(g, r)) {
-                                       excise(r);
-                                       t++;
-                               } else
-                               if(subprop(r) && copyprop(g, r)) {
-                                       excise(r);
-                                       t++;
-                               }
-                       }
-                       break;
-
-               case AMOVBLZX:
-               case AMOVWLZX:
-               case AMOVBLSX:
-               case AMOVWLSX:
-                       if(regtyp(&p->to)) {
-                               r1 = rnops(uniqs(r));
-                               if(r1 != nil) {
-                                       p1 = r1->prog;
-                                       if(p->as == p1->as && p->to.type == p1->from.type && p->to.reg == p1->from.reg){
-                                               p1->as = AMOVL;
-                                               t++;
-                                       }
-                               }
-                       }
-                       break;
-
-               case AADDL:
-               case AADDW:
-                       if(p->from.type != TYPE_CONST || needc(p->link))
-                               break;
-                       if(p->from.offset == -1){
-                               if(p->as == AADDL)
-                                       p->as = ADECL;
-                               else
-                                       p->as = ADECW;
-                               p->from = zprog.from;
-                               break;
-                       }
-                       if(p->from.offset == 1){
-                               if(p->as == AADDL)
-                                       p->as = AINCL;
-                               else
-                                       p->as = AINCW;
-                               p->from = zprog.from;
-                               break;
-                       }
-                       break;
-
-               case ASUBL:
-               case ASUBW:
-                       if(p->from.type != TYPE_CONST || needc(p->link))
-                               break;
-                       if(p->from.offset == -1) {
-                               if(p->as == ASUBL)
-                                       p->as = AINCL;
-                               else
-                                       p->as = AINCW;
-                               p->from = zprog.from;
-                               break;
-                       }
-                       if(p->from.offset == 1){
-                               if(p->as == ASUBL)
-                                       p->as = ADECL;
-                               else
-                                       p->as = ADECW;
-                               p->from = zprog.from;
-                               break;
-                       }
-                       break;
-               }
-       }
-       if(t)
-               goto loop1;
-
-       // MOVSD removal.
-       // We never use packed registers, so a MOVSD between registers
-       // can be replaced by MOVAPD, which moves the pair of float64s
-       // instead of just the lower one.  We only use the lower one, but
-       // the processor can do better if we do moves using both.
-       for(r=g->start; r!=nil; r=r->link) {
-               p = r->prog;
-               if(p->as == AMOVSD)
-               if(regtyp(&p->from))
-               if(regtyp(&p->to))
-                       p->as = AMOVAPD;
-       }
-       
-       flowend(g);
-}
-
-void
-excise(Flow *r)
-{
-       Prog *p;
-
-       p = r->prog;
-       if(debug['P'] && debug['v'])
-               print("%P ===delete===\n", p);
-
-       nopout(p);
-
-       ostats.ndelmov++;
-}
-
-int
-regtyp(Adr *a)
-{
-       return a->type == TYPE_REG && (REG_AX <= a->reg && a->reg <= REG_DI || REG_X0 <= a->reg && a->reg <= REG_X7);
-}
-
-// movb elimination.
-// movb is simulated by the linker
-// when a register other than ax, bx, cx, dx
-// is used, so rewrite to other instructions
-// when possible.  a movb into a register
-// can smash the entire 64-bit register without
-// causing any trouble.
-static void
-elimshortmov(Graph *g)
-{
-       Prog *p;
-       Flow *r;
-
-       for(r=g->start; r!=nil; r=r->link) {
-               p = r->prog;
-               if(regtyp(&p->to)) {
-                       switch(p->as) {
-                       case AINCB:
-                       case AINCW:
-                               p->as = AINCL;
-                               break;
-                       case ADECB:
-                       case ADECW:
-                               p->as = ADECL;
-                               break;
-                       case ANEGB:
-                       case ANEGW:
-                               p->as = ANEGL;
-                               break;
-                       case ANOTB:
-                       case ANOTW:
-                               p->as = ANOTL;
-                               break;
-                       }
-                       if(regtyp(&p->from) || p->from.type == TYPE_CONST) {
-                               // move or artihmetic into partial register.
-                               // from another register or constant can be movl.
-                               // we don't switch to 32-bit arithmetic if it can
-                               // change how the carry bit is set (and the carry bit is needed).
-                               switch(p->as) {
-                               case AMOVB:
-                               case AMOVW:
-                                       p->as = AMOVL;
-                                       break;
-                               case AADDB:
-                               case AADDW:
-                                       if(!needc(p->link))
-                                               p->as = AADDL;
-                                       break;
-                               case ASUBB:
-                               case ASUBW:
-                                       if(!needc(p->link))
-                                               p->as = ASUBL;
-                                       break;
-                               case AMULB:
-                               case AMULW:
-                                       p->as = AMULL;
-                                       break;
-                               case AIMULB:
-                               case AIMULW:
-                                       p->as = AIMULL;
-                                       break;
-                               case AANDB:
-                               case AANDW:
-                                       p->as = AANDL;
-                                       break;
-                               case AORB:
-                               case AORW:
-                                       p->as = AORL;
-                                       break;
-                               case AXORB:
-                               case AXORW:
-                                       p->as = AXORL;
-                                       break;
-                               case ASHLB:
-                               case ASHLW:
-                                       p->as = ASHLL;
-                                       break;
-                               }
-                       } else {
-                               // explicit zero extension
-                               switch(p->as) {
-                               case AMOVB:
-                                       p->as = AMOVBLZX;
-                                       break;
-                               case AMOVW:
-                                       p->as = AMOVWLZX;
-                                       break;
-                               }
-                       }
-               }
-       }
-}
-
-/*
- * the idea is to substitute
- * one register for another
- * from one MOV to another
- *     MOV     a, R0
- *     ADD     b, R0   / no use of R1
- *     MOV     R0, R1
- * would be converted to
- *     MOV     a, R1
- *     ADD     b, R1
- *     MOV     R1, R0
- * hopefully, then the former or latter MOV
- * will be eliminated by copy propagation.
- */
-static int
-subprop(Flow *r0)
-{
-       Prog *p;
-       Adr *v1, *v2;
-       Flow *r;
-       int t;
-       ProgInfo info;
-
-       p = r0->prog;
-       v1 = &p->from;
-       if(!regtyp(v1))
-               return 0;
-       v2 = &p->to;
-       if(!regtyp(v2))
-               return 0;
-       for(r=uniqp(r0); r!=nil; r=uniqp(r)) {
-               if(debug['P'] && debug['v'])
-                       print("\t? %P\n", r->prog);
-               if(uniqs(r) == nil)
-                       break;
-               p = r->prog;
-               if(p->as == AVARDEF || p->as == AVARKILL)
-                       continue;
-               proginfo(&info, p);
-               if(info.flags & Call)
-                       return 0;
-
-               if(info.reguse | info.regset)
-                       return 0;
-
-               if((info.flags & Move) && (info.flags & (SizeL|SizeQ|SizeF|SizeD)) && p->to.type == v1->type && p->to.reg == v1->reg)
-                       goto gotit;
-
-               if(copyau(&p->from, v2) || copyau(&p->to, v2))
-                       break;
-               if(copysub(&p->from, v1, v2, 0) || copysub(&p->to, v1, v2, 0))
-                       break;
-       }
-       return 0;
-
-gotit:
-       copysub(&p->to, v1, v2, 1);
-       if(debug['P']) {
-               print("gotit: %D->%D\n%P", v1, v2, r->prog);
-               if(p->from.type == v2->type && p->from.reg == v2->reg)
-                       print(" excise");
-               print("\n");
-       }
-       for(r=uniqs(r); r!=r0; r=uniqs(r)) {
-               p = r->prog;
-               copysub(&p->from, v1, v2, 1);
-               copysub(&p->to, v1, v2, 1);
-               if(debug['P'])
-                       print("%P\n", r->prog);
-       }
-       t = v1->reg;
-       v1->reg = v2->reg;
-       v2->reg = t;
-       if(debug['P'])
-               print("%P last\n", r->prog);
-       return 1;
-}
-
-/*
- * The idea is to remove redundant copies.
- *     v1->v2  F=0
- *     (use v2 s/v2/v1/)*
- *     set v1  F=1
- *     use v2  return fail
- *     -----------------
- *     v1->v2  F=0
- *     (use v2 s/v2/v1/)*
- *     set v1  F=1
- *     set v2  return success
- */
-static int
-copyprop(Graph *g, Flow *r0)
-{
-       Prog *p;
-       Adr *v1, *v2;
-
-       USED(g);
-       p = r0->prog;
-       v1 = &p->from;
-       v2 = &p->to;
-       if(copyas(v1, v2))
-               return 1;
-       gactive++;
-       return copy1(v1, v2, r0->s1, 0);
-}
-
-static int
-copy1(Adr *v1, Adr *v2, Flow *r, int f)
-{
-       int t;
-       Prog *p;
-
-       if(r->active == gactive) {
-               if(debug['P'])
-                       print("act set; return 1\n");
-               return 1;
-       }
-       r->active = gactive;
-       if(debug['P'])
-               print("copy %D->%D f=%d\n", v1, v2, f);
-       for(; r != nil; r = r->s1) {
-               p = r->prog;
-               if(debug['P'])
-                       print("%P", p);
-               if(!f && uniqp(r) == nil) {
-                       f = 1;
-                       if(debug['P'])
-                               print("; merge; f=%d", f);
-               }
-               t = copyu(p, v2, nil);
-               switch(t) {
-               case 2: /* rar, can't split */
-                       if(debug['P'])
-                               print("; %D rar; return 0\n", v2);
-                       return 0;
-
-               case 3: /* set */
-                       if(debug['P'])
-                               print("; %D set; return 1\n", v2);
-                       return 1;
-
-               case 1: /* used, substitute */
-               case 4: /* use and set */
-                       if(f) {
-                               if(!debug['P'])
-                                       return 0;
-                               if(t == 4)
-                                       print("; %D used+set and f=%d; return 0\n", v2, f);
-                               else
-                                       print("; %D used and f=%d; return 0\n", v2, f);
-                               return 0;
-                       }
-                       if(copyu(p, v2, v1)) {
-                               if(debug['P'])
-                                       print("; sub fail; return 0\n");
-                               return 0;
-                       }
-                       if(debug['P'])
-                               print("; sub %D/%D", v2, v1);
-                       if(t == 4) {
-                               if(debug['P'])
-                                       print("; %D used+set; return 1\n", v2);
-                               return 1;
-                       }
-                       break;
-               }
-               if(!f) {
-                       t = copyu(p, v1, nil);
-                       if(!f && (t == 2 || t == 3 || t == 4)) {
-                               f = 1;
-                               if(debug['P'])
-                                       print("; %D set and !f; f=%d", v1, f);
-                       }
-               }
-               if(debug['P'])
-                       print("\n");
-               if(r->s2)
-                       if(!copy1(v1, v2, r->s2, f))
-                               return 0;
-       }
-       return 1;
-}
-
-/*
- * return
- * 1 if v only used (and substitute),
- * 2 if read-alter-rewrite
- * 3 if set
- * 4 if set and used
- * 0 otherwise (not touched)
- */
-static int
-copyu(Prog *p, Adr *v, Adr *s)
-{
-       ProgInfo info;
-
-       switch(p->as) {
-       case AJMP:
-               if(s != nil) {
-                       if(copysub(&p->to, v, s, 1))
-                               return 1;
-                       return 0;
-               }
-               if(copyau(&p->to, v))
-                       return 1;
-               return 0;
-
-       case ARET:
-               if(s != nil)
-                       return 1;
-               return 3;
-
-       case ACALL:
-               if(REGEXT && v->type == TYPE_REG && v->reg <= REGEXT && v->reg > exregoffset)
-                       return 2;
-               if(REGARG >= 0 && v->type == TYPE_REG && v->reg == REGARG)
-                       return 2;
-               if(v->type == p->from.type && v->reg == p->from.reg)
-                       return 2;
-
-               if(s != nil) {
-                       if(copysub(&p->to, v, s, 1))
-                               return 1;
-                       return 0;
-               }
-               if(copyau(&p->to, v))
-                       return 4;
-               return 3;
-
-       case ATEXT:
-               if(REGARG >= 0 && v->type == TYPE_REG && v->reg == REGARG)
-                       return 3;
-               return 0;
-       }
-
-       if(p->as == AVARDEF || p->as == AVARKILL)
-               return 0;
-       proginfo(&info, p);
-
-       if((info.reguse|info.regset) & RtoB(v->reg))
-               return 2;
-               
-       if(info.flags & LeftAddr)
-               if(copyas(&p->from, v))
-                       return 2;
-
-       if((info.flags & (RightRead|RightWrite)) == (RightRead|RightWrite))
-               if(copyas(&p->to, v))
-                       return 2;
-       
-       if(info.flags & RightWrite) {
-               if(copyas(&p->to, v)) {
-                       if(s != nil)
-                               return copysub(&p->from, v, s, 1);
-                       if(copyau(&p->from, v))
-                               return 4;
-                       return 3;
-               }
-       }
-       
-       if(info.flags & (LeftAddr|LeftRead|LeftWrite|RightAddr|RightRead|RightWrite)) {
-               if(s != nil) {
-                       if(copysub(&p->from, v, s, 1))
-                               return 1;
-                       return copysub(&p->to, v, s, 1);
-               }
-               if(copyau(&p->from, v))
-                       return 1;
-               if(copyau(&p->to, v))
-                       return 1;
-       }
-
-       return 0;
-}
-
-/*
- * direct reference,
- * could be set/use depending on
- * semantics
- */
-static int
-copyas(Adr *a, Adr *v)
-{
-       if(REG_AL <= a->reg && a->reg <= REG_BL)
-               fatal("use of byte register");
-       if(REG_AL <= v->reg && v->reg <= REG_BL)
-               fatal("use of byte register");
-
-       if(a->type != v->type || a->name != v->name || a->reg != v->reg)
-               return 0;
-       if(regtyp(v))
-               return 1;
-       if(v->type == TYPE_MEM && (v->name == NAME_AUTO || v->name == NAME_PARAM))
-               if(v->offset == a->offset)
-                       return 1;
-       return 0;
-}
-
-int
-sameaddr(Addr *a, Addr *v)
-{
-       if(a->type != v->type || a->name != v->name || a->reg != v->reg)
-               return 0;
-       if(regtyp(v))
-               return 1;
-       if(v->type == TYPE_MEM && (v->name == NAME_AUTO || v->name == NAME_PARAM))
-               if(v->offset == a->offset)
-                       return 1;
-       return 0;
-}
-
-/*
- * either direct or indirect
- */
-static int
-copyau(Adr *a, Adr *v)
-{
-
-       if(copyas(a, v))
-               return 1;
-       if(regtyp(v)) {
-               if(a->type == TYPE_MEM && a->reg == v->reg)
-                       return 1;
-               if(a->index == v->reg)
-                       return 1;
-       }
-       return 0;
-}
-
-/*
- * substitute s for v in a
- * return failure to substitute
- */
-static int
-copysub(Adr *a, Adr *v, Adr *s, int f)
-{
-       int reg;
-
-       if(copyas(a, v)) {
-               reg = s->reg;
-               if(reg >= REG_AX && reg <= REG_DI || reg >= REG_X0 && reg <= REG_X7) {
-                       if(f)
-                               a->reg = reg;
-               }
-               return 0;
-       }
-       if(regtyp(v)) {
-               reg = v->reg;
-               if(a->type == TYPE_MEM && a->reg == reg) {
-                       if((s->reg == REG_BP) && a->index != TYPE_NONE)
-                               return 1;       /* can't use BP-base with index */
-                       if(f)
-                               a->reg = s->reg;
-//                     return 0;
-               }
-               if(a->index == reg) {
-                       if(f)
-                               a->index = s->reg;
-                       return 0;
-               }
-               return 0;
-       }
-       return 0;
-}
-
-static void
-conprop(Flow *r0)
-{
-       Flow *r;
-       Prog *p, *p0;
-       int t;
-       Adr *v0;
-
-       p0 = r0->prog;
-       v0 = &p0->to;
-       r = r0;
-
-loop:
-       r = uniqs(r);
-       if(r == nil || r == r0)
-               return;
-       if(uniqp(r) == nil)
-               return;
-
-       p = r->prog;
-       t = copyu(p, v0, nil);
-       switch(t) {
-       case 0: // miss
-       case 1: // use
-               goto loop;
-
-       case 2: // rar
-       case 4: // use and set
-               break;
-
-       case 3: // set
-               if(p->as == p0->as)
-               if(p->from.type == p0->from.type)
-               if(p->from.reg == p0->from.reg)
-               if(p->from.node == p0->from.node)
-               if(p->from.offset == p0->from.offset)
-               if(p->from.scale == p0->from.scale)
-               if(p->from.type == TYPE_FCONST && p->from.u.dval == p0->from.u.dval)
-               if(p->from.index == p0->from.index) {
-                       excise(r);
-                       goto loop;
-               }
-               break;
-       }
-}
-
-int
-smallindir(Addr *a, Addr *reg)
-{
-       return regtyp(reg) &&
-               a->type == TYPE_MEM && a->reg == reg->reg &&
-               a->index == REG_NONE &&
-               0 <= a->offset && a->offset < 4096;
-}
-
-int
-stackaddr(Addr *a)
-{
-       return a->type == TYPE_REG && a->reg == REG_SP;
-}
similarity index 100%
rename from src/cmd/new8g/peep.go
rename to src/cmd/8g/peep.go
diff --git a/src/cmd/8g/prog.c b/src/cmd/8g/prog.c
deleted file mode 100644 (file)
index e77a026..0000000
+++ /dev/null
@@ -1,349 +0,0 @@
-// Copyright 2013 The Go Authors.  All rights reserved.
-// Use of this source code is governed by a BSD-style
-// license that can be found in the LICENSE file.
-
-#include <u.h>
-#include <libc.h>
-#include "gg.h"
-#include "../gc/popt.h"
-
-// Matches real RtoB but can be used in global initializer.
-#define RtoB(r) (1<<((r)-REG_AX))
-
-enum {
-       AX = RtoB(REG_AX),
-       BX = RtoB(REG_BX),
-       CX = RtoB(REG_CX),
-       DX = RtoB(REG_DX),
-       DI = RtoB(REG_DI),
-       SI = RtoB(REG_SI),
-       
-       LeftRdwr = LeftRead | LeftWrite,
-       RightRdwr = RightRead | RightWrite,
-};
-
-#undef RtoB
-
-// This table gives the basic information about instruction
-// generated by the compiler and processed in the optimizer.
-// See opt.h for bit definitions.
-//
-// Instructions not generated need not be listed.
-// As an exception to that rule, we typically write down all the
-// size variants of an operation even if we just use a subset.
-//
-// The table is formatted for 8-space tabs.
-static ProgInfo progtable[ALAST] = {
-       [ATYPE]=        {Pseudo | Skip},
-       [ATEXT]=        {Pseudo},
-       [AFUNCDATA]=    {Pseudo},
-       [APCDATA]=      {Pseudo},
-       [AUNDEF]=       {Break},
-       [AUSEFIELD]=    {OK},
-       [ACHECKNIL]=    {LeftRead},
-       [AVARDEF]=      {Pseudo | RightWrite},
-       [AVARKILL]=     {Pseudo | RightWrite},
-
-       // NOP is an internal no-op that also stands
-       // for USED and SET annotations, not the Intel opcode.
-       [ANOP]=         {LeftRead | RightWrite},
-
-       [AADCL]=        {SizeL | LeftRead | RightRdwr | SetCarry | UseCarry},
-       [AADCW]=        {SizeW | LeftRead | RightRdwr | SetCarry | UseCarry},
-
-       [AADDB]=        {SizeB | LeftRead | RightRdwr | SetCarry},
-       [AADDL]=        {SizeL | LeftRead | RightRdwr | SetCarry},
-       [AADDW]=        {SizeW | LeftRead | RightRdwr | SetCarry},
-       
-       [AADDSD]=       {SizeD | LeftRead | RightRdwr},
-       [AADDSS]=       {SizeF | LeftRead | RightRdwr},
-
-       [AANDB]=        {SizeB | LeftRead | RightRdwr | SetCarry},
-       [AANDL]=        {SizeL | LeftRead | RightRdwr | SetCarry},
-       [AANDW]=        {SizeW | LeftRead | RightRdwr | SetCarry},
-
-       [ACALL]=        {RightAddr | Call | KillCarry},
-
-       [ACDQ]=         {OK, AX, AX | DX},
-       [ACWD]=         {OK, AX, AX | DX},
-
-       [ACLD]=         {OK},
-       [ASTD]=         {OK},
-
-       [ACMPB]=        {SizeB | LeftRead | RightRead | SetCarry},
-       [ACMPL]=        {SizeL | LeftRead | RightRead | SetCarry},
-       [ACMPW]=        {SizeW | LeftRead | RightRead | SetCarry},
-
-       [ACOMISD]=      {SizeD | LeftRead | RightRead | SetCarry},
-       [ACOMISS]=      {SizeF | LeftRead | RightRead | SetCarry},
-
-       [ACVTSD2SL]=    {SizeL | LeftRead | RightWrite | Conv},
-       [ACVTSD2SS]=    {SizeF | LeftRead | RightWrite | Conv},
-       [ACVTSL2SD]=    {SizeD | LeftRead | RightWrite | Conv},
-       [ACVTSL2SS]=    {SizeF | LeftRead | RightWrite | Conv},
-       [ACVTSS2SD]=    {SizeD | LeftRead | RightWrite | Conv},
-       [ACVTSS2SL]=    {SizeL | LeftRead | RightWrite | Conv},
-       [ACVTTSD2SL]=   {SizeL | LeftRead | RightWrite | Conv},
-       [ACVTTSS2SL]=   {SizeL | LeftRead | RightWrite | Conv},
-
-       [ADECB]=        {SizeB | RightRdwr},
-       [ADECL]=        {SizeL | RightRdwr},
-       [ADECW]=        {SizeW | RightRdwr},
-
-       [ADIVB]=        {SizeB | LeftRead | SetCarry, AX, AX},
-       [ADIVL]=        {SizeL | LeftRead | SetCarry, AX|DX, AX|DX},
-       [ADIVW]=        {SizeW | LeftRead | SetCarry, AX|DX, AX|DX},
-
-       [ADIVSD]=       {SizeD | LeftRead | RightRdwr},
-       [ADIVSS]=       {SizeF | LeftRead | RightRdwr},
-       
-       [AFLDCW]=       {SizeW | LeftAddr},
-       [AFSTCW]=       {SizeW | RightAddr},
-
-       [AFSTSW]=       {SizeW | RightAddr | RightWrite},
-
-       [AFADDD]=       {SizeD | LeftAddr | RightRdwr},
-       [AFADDDP]=      {SizeD | LeftAddr | RightRdwr},
-       [AFADDF]=       {SizeF | LeftAddr | RightRdwr},
-
-       [AFCOMD]=       {SizeD | LeftAddr | RightRead},
-       [AFCOMDP]=      {SizeD | LeftAddr | RightRead},
-       [AFCOMDPP]=     {SizeD | LeftAddr | RightRead},
-       [AFCOMF]=       {SizeF | LeftAddr | RightRead},
-       [AFCOMFP]=      {SizeF | LeftAddr | RightRead},
-       [AFUCOMIP]=     {SizeF | LeftAddr | RightRead},
-
-       [AFCHS]=        {SizeD | RightRdwr}, // also SizeF
-
-       [AFDIVDP]=      {SizeD | LeftAddr | RightRdwr},
-       [AFDIVF]=       {SizeF | LeftAddr | RightRdwr},
-       [AFDIVD]=       {SizeD | LeftAddr | RightRdwr},
-
-       [AFDIVRDP]=     {SizeD | LeftAddr | RightRdwr},
-       [AFDIVRF]=      {SizeF | LeftAddr | RightRdwr},
-       [AFDIVRD]=      {SizeD | LeftAddr | RightRdwr},
-
-       [AFXCHD]=       {SizeD | LeftRdwr | RightRdwr},
-
-       [AFSUBD]=       {SizeD | LeftAddr | RightRdwr},
-       [AFSUBDP]=      {SizeD | LeftAddr | RightRdwr},
-       [AFSUBF]=       {SizeF | LeftAddr | RightRdwr},
-       [AFSUBRD]=      {SizeD | LeftAddr | RightRdwr},
-       [AFSUBRDP]=     {SizeD | LeftAddr | RightRdwr},
-       [AFSUBRF]=      {SizeF | LeftAddr | RightRdwr},
-
-       [AFMOVD]=       {SizeD | LeftAddr | RightWrite},
-       [AFMOVF]=       {SizeF | LeftAddr | RightWrite},
-       [AFMOVL]=       {SizeL | LeftAddr | RightWrite},
-       [AFMOVW]=       {SizeW | LeftAddr | RightWrite},
-       [AFMOVV]=       {SizeQ | LeftAddr | RightWrite},
-
-       // These instructions are marked as RightAddr
-       // so that the register optimizer does not try to replace the
-       // memory references with integer register references.
-       // But they do not use the previous value at the address, so
-       // we also mark them RightWrite.
-       [AFMOVDP]=      {SizeD | LeftRead | RightWrite | RightAddr},
-       [AFMOVFP]=      {SizeF | LeftRead | RightWrite | RightAddr},
-       [AFMOVLP]=      {SizeL | LeftRead | RightWrite | RightAddr},
-       [AFMOVWP]=      {SizeW | LeftRead | RightWrite | RightAddr},
-       [AFMOVVP]=      {SizeQ | LeftRead | RightWrite | RightAddr},
-
-       [AFMULD]=       {SizeD | LeftAddr | RightRdwr},
-       [AFMULDP]=      {SizeD | LeftAddr | RightRdwr},
-       [AFMULF]=       {SizeF | LeftAddr | RightRdwr},
-
-       [AIDIVB]=       {SizeB | LeftRead | SetCarry, AX, AX},
-       [AIDIVL]=       {SizeL | LeftRead | SetCarry, AX|DX, AX|DX},
-       [AIDIVW]=       {SizeW | LeftRead | SetCarry, AX|DX, AX|DX},
-
-       [AIMULB]=       {SizeB | LeftRead | SetCarry, AX, AX},
-       [AIMULL]=       {SizeL | LeftRead | ImulAXDX | SetCarry},
-       [AIMULW]=       {SizeW | LeftRead | ImulAXDX | SetCarry},
-
-       [AINCB]=        {SizeB | RightRdwr},
-       [AINCL]=        {SizeL | RightRdwr},
-       [AINCW]=        {SizeW | RightRdwr},
-
-       [AJCC]=         {Cjmp | UseCarry},
-       [AJCS]=         {Cjmp | UseCarry},
-       [AJEQ]=         {Cjmp | UseCarry},
-       [AJGE]=         {Cjmp | UseCarry},
-       [AJGT]=         {Cjmp | UseCarry},
-       [AJHI]=         {Cjmp | UseCarry},
-       [AJLE]=         {Cjmp | UseCarry},
-       [AJLS]=         {Cjmp | UseCarry},
-       [AJLT]=         {Cjmp | UseCarry},
-       [AJMI]=         {Cjmp | UseCarry},
-       [AJNE]=         {Cjmp | UseCarry},
-       [AJOC]=         {Cjmp | UseCarry},
-       [AJOS]=         {Cjmp | UseCarry},
-       [AJPC]=         {Cjmp | UseCarry},
-       [AJPL]=         {Cjmp | UseCarry},
-       [AJPS]=         {Cjmp | UseCarry},
-
-       [AJMP]=         {Jump | Break | KillCarry},
-
-       [ALEAL]=        {LeftAddr | RightWrite},
-
-       [AMOVBLSX]=     {SizeL | LeftRead | RightWrite | Conv},
-       [AMOVBLZX]=     {SizeL | LeftRead | RightWrite | Conv},
-       [AMOVBWSX]=     {SizeW | LeftRead | RightWrite | Conv},
-       [AMOVBWZX]=     {SizeW | LeftRead | RightWrite | Conv},
-       [AMOVWLSX]=     {SizeL | LeftRead | RightWrite | Conv},
-       [AMOVWLZX]=     {SizeL | LeftRead | RightWrite | Conv},
-
-       [AMOVB]=        {SizeB | LeftRead | RightWrite | Move},
-       [AMOVL]=        {SizeL | LeftRead | RightWrite | Move},
-       [AMOVW]=        {SizeW | LeftRead | RightWrite | Move},
-
-       [AMOVSB]=       {OK, DI|SI, DI|SI},
-       [AMOVSL]=       {OK, DI|SI, DI|SI},
-       [AMOVSW]=       {OK, DI|SI, DI|SI},
-       [ADUFFCOPY]=    {OK, DI|SI, DI|SI|CX},
-
-       [AMOVSD]=       {SizeD | LeftRead | RightWrite | Move},
-       [AMOVSS]=       {SizeF | LeftRead | RightWrite | Move},
-
-       // We use MOVAPD as a faster synonym for MOVSD.
-       [AMOVAPD]=      {SizeD | LeftRead | RightWrite | Move},
-
-       [AMULB]=        {SizeB | LeftRead | SetCarry, AX, AX},
-       [AMULL]=        {SizeL | LeftRead | SetCarry, AX, AX|DX},
-       [AMULW]=        {SizeW | LeftRead | SetCarry, AX, AX|DX},
-       
-       [AMULSD]=       {SizeD | LeftRead | RightRdwr},
-       [AMULSS]=       {SizeF | LeftRead | RightRdwr},
-
-       [ANEGB]=        {SizeB | RightRdwr | SetCarry},
-       [ANEGL]=        {SizeL | RightRdwr | SetCarry},
-       [ANEGW]=        {SizeW | RightRdwr | SetCarry},
-
-       [ANOTB]=        {SizeB | RightRdwr},
-       [ANOTL]=        {SizeL | RightRdwr},
-       [ANOTW]=        {SizeW | RightRdwr},
-
-       [AORB]=         {SizeB | LeftRead | RightRdwr | SetCarry},
-       [AORL]=         {SizeL | LeftRead | RightRdwr | SetCarry},
-       [AORW]=         {SizeW | LeftRead | RightRdwr | SetCarry},
-
-       [APOPL]=        {SizeL | RightWrite},
-       [APUSHL]=       {SizeL | LeftRead},
-
-       [ARCLB]=        {SizeB | LeftRead | RightRdwr | ShiftCX | SetCarry | UseCarry},
-       [ARCLL]=        {SizeL | LeftRead | RightRdwr | ShiftCX | SetCarry | UseCarry},
-       [ARCLW]=        {SizeW | LeftRead | RightRdwr | ShiftCX | SetCarry | UseCarry},
-
-       [ARCRB]=        {SizeB | LeftRead | RightRdwr | ShiftCX | SetCarry | UseCarry},
-       [ARCRL]=        {SizeL | LeftRead | RightRdwr | ShiftCX | SetCarry | UseCarry},
-       [ARCRW]=        {SizeW | LeftRead | RightRdwr | ShiftCX | SetCarry | UseCarry},
-
-       [AREP]=         {OK, CX, CX},
-       [AREPN]=        {OK, CX, CX},
-
-       [ARET]=         {Break | KillCarry},
-
-       [AROLB]=        {SizeB | LeftRead | RightRdwr | ShiftCX | SetCarry},
-       [AROLL]=        {SizeL | LeftRead | RightRdwr | ShiftCX | SetCarry},
-       [AROLW]=        {SizeW | LeftRead | RightRdwr | ShiftCX | SetCarry},
-
-       [ARORB]=        {SizeB | LeftRead | RightRdwr | ShiftCX | SetCarry},
-       [ARORL]=        {SizeL | LeftRead | RightRdwr | ShiftCX | SetCarry},
-       [ARORW]=        {SizeW | LeftRead | RightRdwr | ShiftCX | SetCarry},
-
-       [ASAHF]=        {OK, AX, AX},
-
-       [ASALB]=        {SizeB | LeftRead | RightRdwr | ShiftCX | SetCarry},
-       [ASALL]=        {SizeL | LeftRead | RightRdwr | ShiftCX | SetCarry},
-       [ASALW]=        {SizeW | LeftRead | RightRdwr | ShiftCX | SetCarry},
-
-       [ASARB]=        {SizeB | LeftRead | RightRdwr | ShiftCX | SetCarry},
-       [ASARL]=        {SizeL | LeftRead | RightRdwr | ShiftCX | SetCarry},
-       [ASARW]=        {SizeW | LeftRead | RightRdwr | ShiftCX | SetCarry},
-
-       [ASBBB]=        {SizeB | LeftRead | RightRdwr | SetCarry | UseCarry},
-       [ASBBL]=        {SizeL | LeftRead | RightRdwr | SetCarry | UseCarry},
-       [ASBBW]=        {SizeW | LeftRead | RightRdwr | SetCarry | UseCarry},
-
-       [ASETCC]=       {SizeB | RightRdwr | UseCarry},
-       [ASETCS]=       {SizeB | RightRdwr | UseCarry},
-       [ASETEQ]=       {SizeB | RightRdwr | UseCarry},
-       [ASETGE]=       {SizeB | RightRdwr | UseCarry},
-       [ASETGT]=       {SizeB | RightRdwr | UseCarry},
-       [ASETHI]=       {SizeB | RightRdwr | UseCarry},
-       [ASETLE]=       {SizeB | RightRdwr | UseCarry},
-       [ASETLS]=       {SizeB | RightRdwr | UseCarry},
-       [ASETLT]=       {SizeB | RightRdwr | UseCarry},
-       [ASETMI]=       {SizeB | RightRdwr | UseCarry},
-       [ASETNE]=       {SizeB | RightRdwr | UseCarry},
-       [ASETOC]=       {SizeB | RightRdwr | UseCarry},
-       [ASETOS]=       {SizeB | RightRdwr | UseCarry},
-       [ASETPC]=       {SizeB | RightRdwr | UseCarry},
-       [ASETPL]=       {SizeB | RightRdwr | UseCarry},
-       [ASETPS]=       {SizeB | RightRdwr | UseCarry},
-
-       [ASHLB]=        {SizeB | LeftRead | RightRdwr | ShiftCX | SetCarry},
-       [ASHLL]=        {SizeL | LeftRead | RightRdwr | ShiftCX | SetCarry},
-       [ASHLW]=        {SizeW | LeftRead | RightRdwr | ShiftCX | SetCarry},
-
-       [ASHRB]=        {SizeB | LeftRead | RightRdwr | ShiftCX | SetCarry},
-       [ASHRL]=        {SizeL | LeftRead | RightRdwr | ShiftCX | SetCarry},
-       [ASHRW]=        {SizeW | LeftRead | RightRdwr | ShiftCX | SetCarry},
-
-       [ASTOSB]=       {OK, AX|DI, DI},
-       [ASTOSL]=       {OK, AX|DI, DI},
-       [ASTOSW]=       {OK, AX|DI, DI},
-       [ADUFFZERO]=    {OK, AX|DI, DI},
-
-       [ASUBB]=        {SizeB | LeftRead | RightRdwr | SetCarry},
-       [ASUBL]=        {SizeL | LeftRead | RightRdwr | SetCarry},
-       [ASUBW]=        {SizeW | LeftRead | RightRdwr | SetCarry},
-
-       [ASUBSD]=       {SizeD | LeftRead | RightRdwr},
-       [ASUBSS]=       {SizeF | LeftRead | RightRdwr},
-
-       [ATESTB]=       {SizeB | LeftRead | RightRead | SetCarry},
-       [ATESTL]=       {SizeL | LeftRead | RightRead | SetCarry},
-       [ATESTW]=       {SizeW | LeftRead | RightRead | SetCarry},
-
-       [AUCOMISD]=     {SizeD | LeftRead | RightRead},
-       [AUCOMISS]=     {SizeF | LeftRead | RightRead},
-
-       [AXCHGB]=       {SizeB | LeftRdwr | RightRdwr},
-       [AXCHGL]=       {SizeL | LeftRdwr | RightRdwr},
-       [AXCHGW]=       {SizeW | LeftRdwr | RightRdwr},
-
-       [AXORB]=        {SizeB | LeftRead | RightRdwr | SetCarry},
-       [AXORL]=        {SizeL | LeftRead | RightRdwr | SetCarry},
-       [AXORW]=        {SizeW | LeftRead | RightRdwr | SetCarry},
-};
-
-void
-proginfo(ProgInfo *info, Prog *p)
-{
-       *info = progtable[p->as];
-       if(info->flags == 0)
-               fatal("unknown instruction %P", p);
-
-       if((info->flags & ShiftCX) && p->from.type != TYPE_CONST)
-               info->reguse |= CX;
-
-       if(info->flags & ImulAXDX) {
-               if(p->to.type == TYPE_NONE) {
-                       info->reguse |= AX;
-                       info->regset |= AX | DX;
-               } else {
-                       info->flags |= RightRdwr;
-               }
-       }
-
-       // Addressing makes some registers used.
-       if(p->from.type == TYPE_MEM && p->from.name == NAME_NONE)
-               info->regindex |= RtoB(p->from.reg);
-       if(p->from.index != REG_NONE)
-               info->regindex |= RtoB(p->from.index);
-       if(p->to.type == TYPE_MEM && p->to.name == NAME_NONE)
-               info->regindex |= RtoB(p->to.reg);
-       if(p->to.index != REG_NONE)
-               info->regindex |= RtoB(p->to.index);
-}
similarity index 100%
rename from src/cmd/new8g/prog.go
rename to src/cmd/8g/prog.go
diff --git a/src/cmd/8g/reg.c b/src/cmd/8g/reg.c
deleted file mode 100644 (file)
index 0470bdf..0000000
+++ /dev/null
@@ -1,112 +0,0 @@
-// Derived from Inferno utils/6c/reg.c
-// http://code.google.com/p/inferno-os/source/browse/utils/6c/reg.c
-//
-//     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 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 <u.h>
-#include <libc.h>
-#include "gg.h"
-#include "../gc/popt.h"
-
-enum {
-       NREGVAR = 16,   /* 8 integer + 8 floating */
-};
-
-static char* regname[] = {
-       ".ax", ".cx", ".dx", ".bx", ".sp", ".bp", ".si", ".di",
-       ".x0", ".x1", ".x2", ".x3", ".x4", ".x5", ".x6", ".x7",
-};
-
-char**
-regnames(int *n)
-{
-       *n = NREGVAR;
-       return regname;
-}
-
-uint64
-excludedregs(void)
-{
-       return RtoB(REG_SP);
-}
-
-uint64
-doregbits(int r)
-{
-       uint64 b;
-
-       b = 0;
-       if(r >= REG_AX && r <= REG_DI)
-               b |= RtoB(r);
-       else
-       if(r >= REG_AL && r <= REG_BL)
-               b |= RtoB(r-REG_AL+REG_AX);
-       else
-       if(r >= REG_AH && r <= REG_BH)
-               b |= RtoB(r-REG_AH+REG_AX);
-       else
-       if(r >= REG_X0 && r <= REG_X0+7)
-               b |= FtoB(r);
-       return b;
-}
-
-uint64
-RtoB(int r)
-{
-
-       if(r < REG_AX || r > REG_DI)
-               return 0;
-       return 1ULL << (r-REG_AX);
-}
-
-int
-BtoR(uint64 b)
-{
-
-       b &= 0xffL;
-       if(b == 0)
-               return 0;
-       return bitno(b) + REG_AX;
-}
-
-uint64
-FtoB(int f)
-{
-       if(f < REG_X0 || f > REG_X7)
-               return 0;
-       return 1ULL << (f - REG_X0 + 8);
-}
-
-int
-BtoF(uint64 b)
-{
-       b &= 0xFF00L;
-       if(b == 0)
-               return 0;
-       return bitno(b) - 8 + REG_X0;
-}
similarity index 100%
rename from src/cmd/new8g/reg.go
rename to src/cmd/8g/reg.go
similarity index 100%
rename from src/cmd/new8g/util.go
rename to src/cmd/8g/util.go
diff --git a/src/cmd/9a/Makefile b/src/cmd/9a/Makefile
deleted file mode 100644 (file)
index 27290dd..0000000
+++ /dev/null
@@ -1,10 +0,0 @@
-# Copyright 2012 The Go Authors.  All rights reserved.
-# Use of this source code is governed by a BSD-style
-# license that can be found in the LICENSE file.
-
-include ../../Make.dist
-
-install: y.tab.h
-
-y.tab.h: a.y
-       LANG=C LANGUAGE=en_US.UTF8 bison -d -v -y a.y
diff --git a/src/cmd/9a/a.h b/src/cmd/9a/a.h
deleted file mode 100644 (file)
index d4f2fee..0000000
+++ /dev/null
@@ -1,172 +0,0 @@
-// cmd/9a/a.h from Vita Nuova.
-//
-//     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-2008 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-2008 Lucent Technologies Inc. and others
-//     Portions Copyright Â© 2009 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 <bio.h>
-#include <link.h>
-#include "../9l/9.out.h"
-
-#ifndef        EXTERN
-#define        EXTERN  extern
-#endif
-
-#undef getc
-#undef ungetc
-#undef BUFSIZ
-
-#define        getc    ccgetc
-#define        ungetc  ccungetc
-
-typedef        struct  Sym     Sym;
-typedef        struct  Io      Io;
-
-#define        MAXALIGN        7
-#define        FPCHIP          1
-#define        NSYMB           8192
-#define        BUFSIZ          8192
-#define        HISTSZ          20
-#define        NINCLUDE        10
-#define        NHUNK           10000
-#ifndef EOF
-#define        EOF             (-1)
-#endif
-#define        IGN             (-2)
-#define        GETC()          ((--fi.c < 0)? filbuf(): *fi.p++ & 0xff)
-#define        NHASH           503
-#define        STRINGSZ        200
-#define        NMACRO          10
-
-struct Sym
-{
-       Sym*    link;
-       char*   macro;
-       vlong   value;
-       ushort  type;
-       char    *name;
-       char*   labelname;
-       char    sym;
-};
-#define        S       ((Sym*)0)
-
-EXTERN struct
-{
-       char*   p;
-       int     c;
-} fi;
-
-struct Io
-{
-       Io*     link;
-       char    b[BUFSIZ];
-       char*   p;
-       short   c;
-       short   f;
-};
-#define        I       ((Io*)0)
-
-enum
-{
-       CLAST,
-       CMACARG,
-       CMACRO,
-       CPREPROC,
-};
-
-EXTERN int     debug[256];
-EXTERN Sym*    hash[NHASH];
-EXTERN char**  Dlist;
-EXTERN int     nDlist;
-EXTERN int     newflag;
-EXTERN char*   hunk;
-EXTERN char**  include;
-EXTERN Io*     iofree;
-EXTERN Io*     ionext;
-EXTERN Io*     iostack;
-EXTERN int32   lineno;
-EXTERN int     nerrors;
-EXTERN int32   nhunk;
-EXTERN int     nosched;
-EXTERN int     ninclude;
-EXTERN int32   nsymb;
-EXTERN Addr    nullgen;
-EXTERN char*   outfile;
-EXTERN int     pass;
-EXTERN int32   pc;
-EXTERN int     peekc;
-EXTERN int32   stmtline;
-EXTERN int     sym;
-EXTERN char*   symb;
-EXTERN int     thechar;
-EXTERN char*   thestring;
-EXTERN int32   thunk;
-EXTERN Biobuf  obuf;
-EXTERN Link*   ctxt;
-EXTERN Biobuf  bstdout;
-EXTERN Prog*   lastpc;
-
-void*  alloc(int32);
-void*  allocn(void*, int32, int32);
-void   ensuresymb(int32);
-void   errorexit(void);
-void   pushio(void);
-void   newio(void);
-void   newfile(char*, int);
-Sym*   slookup(char*);
-Sym*   lookup(void);
-Sym*   labellookup(Sym*);
-void   settext(LSym*);
-void   syminit(Sym*);
-int32  yylex(void);
-int    getc(void);
-int    getnsc(void);
-void   unget(int);
-int    escchar(int);
-void   cinit(void);
-void   pinit(char*);
-void   cclean(void);
-void   outcode(int, Addr*, int, Addr*);
-void   outgcode(int, Addr*, int, Addr*, Addr*);
-int    filbuf(void);
-Sym*   getsym(void);
-void   domacro(void);
-void   macund(void);
-void   macdef(void);
-void   macexpand(Sym*, char*);
-void   macinc(void);
-void   macprag(void);
-void   maclin(void);
-void   macif(int);
-void   macend(void);
-void   dodefine(char*);
-void   prfile(int32);
-void   linehist(char*, int);
-void   gethunk(void);
-void   yyerror(char*, ...);
-int    yyparse(void);
-void   setinclude(char*);
-int    assemble(char*);
index ccc3bcc3a6c01ceb3ecf97b7a26bae1195c9055e..db733c59871eee2d68bed5256f3b57d2bd25c659 100644 (file)
 // THE SOFTWARE.
 
 %{
-#include <u.h>
-#include <stdio.h>     /* if we don't, bison will, and a.h re-#defines getc */
-#include <libc.h>
-#include "a.h"
-#include "../../runtime/funcdata.h"
+package main
+
+import (
+       "cmd/internal/asm"
+       "cmd/internal/obj"
+       . "cmd/internal/obj/ppc64"
+)
 %}
+
 %union
 {
-       Sym     *sym;
-       vlong   lval;
-       double  dval;
-       char    sval[8];
-       Addr    addr;
+       sym *asm.Sym
+       lval int64
+       dval float64
+       sval string
+       addr obj.Addr
 }
+
 %left  '|'
 %left  '^'
 %left  '&'
@@ -50,7 +54,7 @@
 %left  '*' '/' '%'
 %token <lval>  LMOVW LMOVB LABS LLOGW LSHW LADDW LCMP LCROP
 %token <lval>  LBRA LFMOV LFCONV LFCMP LFADD LFMA LTRAP LXORW
-%token <lval>  LNOP LEND LRETT LWORD LTEXT LGLOBL LDATA LRETRN
+%token <lval>  LNOP LEND LRETT LWORD LTEXT LDATA LGLOBL LRETRN
 %token <lval>  LCONST LSP LSB LFP LPC LCREG LFLUSH
 %token <lval>  LREG LFREG LR LCR LF LFPSCR
 %token <lval>  LLR LCTR LSPR LSPREG LSEG LMSR
 prog:
 |      prog
        {
-               stmtline = lineno;
+               stmtline = asm.Lineno
        }
        line
 
 line:
        LNAME ':'
        {
-               $1 = labellookup($1);
-               if($1->type == LLAB && $1->value != pc)
-                       yyerror("redeclaration of %s", $1->labelname);
-               $1->type = LLAB;
-               $1->value = pc;
+               $1 = asm.LabelLookup($1);
+               if $1.Type == LLAB && $1.Value != int64(asm.PC) {
+                       yyerror("redeclaration of %s", $1.Labelname)
+               }
+               $1.Type = LLAB;
+               $1.Value = int64(asm.PC);
        }
        line
 |      LNAME '=' expr ';'
        {
-               $1->type = LVAR;
-               $1->value = $3;
+               $1.Type = LVAR;
+               $1.Value = $3;
        }
 |      LVAR '=' expr ';'
        {
-               if($1->value != $3)
-                       yyerror("redeclaration of %s", $1->name);
-               $1->value = $3;
+               if $1.Value != $3 {
+                       yyerror("redeclaration of %s", $1.Name)
+               }
+               $1.Value = $3;
        }
 |      LSCHED ';'
        {
-               nosched = $1;
+               nosched = int($1);
        }
 |      ';'
 |      inst ';'
@@ -105,122 +111,122 @@ inst:
  */
        LMOVW rreg ',' rreg
        {
-               outcode($1, &$2, 0, &$4);
+               outcode(int($1), &$2, 0, &$4);
        }
 |      LMOVW addr ',' rreg
        {
-               outcode($1, &$2, 0, &$4);
+               outcode(int($1), &$2, 0, &$4);
        }
 |      LMOVW regaddr ',' rreg
        {
-               outcode($1, &$2, 0, &$4);
+               outcode(int($1), &$2, 0, &$4);
        }
 |      LMOVB rreg ',' rreg
        {
-               outcode($1, &$2, 0, &$4);
+               outcode(int($1), &$2, 0, &$4);
        }
 |      LMOVB addr ',' rreg
        {
-               outcode($1, &$2, 0, &$4);
+               outcode(int($1), &$2, 0, &$4);
        }
 |      LMOVB regaddr ',' rreg
        {
-               outcode($1, &$2, 0, &$4);
+               outcode(int($1), &$2, 0, &$4);
        }
 /*
  * load floats
  */
 |      LFMOV addr ',' freg
        {
-               outcode($1, &$2, 0, &$4);
+               outcode(int($1), &$2, 0, &$4);
        }
 |      LFMOV regaddr ',' freg
        {
-               outcode($1, &$2, 0, &$4);
+               outcode(int($1), &$2, 0, &$4);
        }
 |      LFMOV fimm ',' freg
        {
-               outcode($1, &$2, 0, &$4);
+               outcode(int($1), &$2, 0, &$4);
        }
 |      LFMOV freg ',' freg
        {
-               outcode($1, &$2, 0, &$4);
+               outcode(int($1), &$2, 0, &$4);
        }
 |      LFMOV freg ',' addr
        {
-               outcode($1, &$2, 0, &$4);
+               outcode(int($1), &$2, 0, &$4);
        }
 |      LFMOV freg ',' regaddr
        {
-               outcode($1, &$2, 0, &$4);
+               outcode(int($1), &$2, 0, &$4);
        }
 /*
  * store ints and bytes
  */
 |      LMOVW rreg ',' addr
        {
-               outcode($1, &$2, 0, &$4);
+               outcode(int($1), &$2, 0, &$4);
        }
 |      LMOVW rreg ',' regaddr
        {
-               outcode($1, &$2, 0, &$4);
+               outcode(int($1), &$2, 0, &$4);
        }
 |      LMOVB rreg ',' addr
        {
-               outcode($1, &$2, 0, &$4);
+               outcode(int($1), &$2, 0, &$4);
        }
 |      LMOVB rreg ',' regaddr
        {
-               outcode($1, &$2, 0, &$4);
+               outcode(int($1), &$2, 0, &$4);
        }
 /*
  * store floats
  */
 |      LMOVW freg ',' addr
        {
-               outcode($1, &$2, 0, &$4);
+               outcode(int($1), &$2, 0, &$4);
        }
 |      LMOVW freg ',' regaddr
        {
-               outcode($1, &$2, 0, &$4);
+               outcode(int($1), &$2, 0, &$4);
        }
 /*
  * floating point status
  */
 |      LMOVW fpscr ',' freg
        {
-               outcode($1, &$2, 0, &$4);
+               outcode(int($1), &$2, 0, &$4);
        }
 |      LMOVW freg ','  fpscr
        {
-               outcode($1, &$2, 0, &$4);
+               outcode(int($1), &$2, 0, &$4);
        }
 |      LMOVW freg ',' imm ',' fpscr
        {
-               outgcode($1, &$2, 0, &$4, &$6);
+               outgcode(int($1), &$2, 0, &$4, &$6);
        }
 |      LMOVW fpscr ',' creg
        {
-               outcode($1, &$2, 0, &$4);
+               outcode(int($1), &$2, 0, &$4);
        }
 |      LMTFSB imm ',' con
        {
-               outcode($1, &$2, $4, &nullgen);
+               outcode(int($1), &$2, int($4), &nullgen);
        }
 /*
  * field moves (mtcrf)
  */
 |      LMOVW rreg ',' imm ',' lcr
        {
-               outgcode($1, &$2, 0, &$4, &$6);
+               outgcode(int($1), &$2, 0, &$4, &$6);
        }
 |      LMOVW rreg ',' creg
        {
-               outcode($1, &$2, 0, &$4);
+               outcode(int($1), &$2, 0, &$4);
        }
 |      LMOVW rreg ',' lcr
        {
-               outcode($1, &$2, 0, &$4);
+               outcode(int($1), &$2, 0, &$4);
        }
 /*
  * integer operations
@@ -230,84 +236,84 @@ inst:
  */
 |      LADDW rreg ',' sreg ',' rreg
        {
-               outcode($1, &$2, $4, &$6);
+               outcode(int($1), &$2, int($4), &$6);
        }
 |      LADDW imm ',' sreg ',' rreg
        {
-               outcode($1, &$2, $4, &$6);
+               outcode(int($1), &$2, int($4), &$6);
        }
 |      LADDW rreg ',' imm ',' rreg
        {
-               outgcode($1, &$2, 0, &$4, &$6);
+               outgcode(int($1), &$2, 0, &$4, &$6);
        }
 |      LADDW rreg ',' rreg
        {
-               outcode($1, &$2, 0, &$4);
+               outcode(int($1), &$2, 0, &$4);
        }
 |      LADDW imm ',' rreg
        {
-               outcode($1, &$2, 0, &$4);
+               outcode(int($1), &$2, 0, &$4);
        }
 |      LLOGW rreg ',' sreg ',' rreg
        {
-               outcode($1, &$2, $4, &$6);
+               outcode(int($1), &$2, int($4), &$6);
        }
 |      LLOGW rreg ',' rreg
        {
-               outcode($1, &$2, 0, &$4);
+               outcode(int($1), &$2, 0, &$4);
        }
 |      LSHW rreg ',' sreg ',' rreg
        {
-               outcode($1, &$2, $4, &$6);
+               outcode(int($1), &$2, int($4), &$6);
        }
 |      LSHW rreg ',' rreg
        {
-               outcode($1, &$2, 0, &$4);
+               outcode(int($1), &$2, 0, &$4);
        }
 |      LSHW imm ',' sreg ',' rreg
        {
-               outcode($1, &$2, $4, &$6);
+               outcode(int($1), &$2, int($4), &$6);
        }
 |      LSHW imm ',' rreg
        {
-               outcode($1, &$2, 0, &$4);
+               outcode(int($1), &$2, 0, &$4);
        }
 |      LABS rreg ',' rreg
        {
-               outcode($1, &$2, 0, &$4);
+               outcode(int($1), &$2, 0, &$4);
        }
 |      LABS rreg
        {
-               outcode($1, &$2, 0, &$2);
+               outcode(int($1), &$2, 0, &$2);
        }
 /*
  * multiply-accumulate
  */
 |      LMA rreg ',' sreg ',' rreg
        {
-               outcode($1, &$2, $4, &$6);
+               outcode(int($1), &$2, int($4), &$6);
        }
 /*
  * move immediate: macro for cau+or, addi, addis, and other combinations
  */
 |      LMOVW imm ',' rreg
        {
-               outcode($1, &$2, 0, &$4);
+               outcode(int($1), &$2, 0, &$4);
        }
 |      LMOVW ximm ',' rreg
        {
-               outcode($1, &$2, 0, &$4);
+               outcode(int($1), &$2, 0, &$4);
        }
 /*
  * condition register operations
  */
 |      LCROP cbit ',' cbit
        {
-               outcode($1, &$2, $4.reg, &$4);
+               outcode(int($1), &$2, int($4.Reg), &$4);
        }
 |      LCROP cbit ',' con ',' cbit
        {
-               outcode($1, &$2, $4, &$6);
+               outcode(int($1), &$2, int($4), &$6);
        }
 /*
  * condition register moves
@@ -315,35 +321,35 @@ inst:
  */
 |      LMOVW creg ',' creg
        {
-               outcode($1, &$2, 0, &$4);
+               outcode(int($1), &$2, 0, &$4);
        }
 |      LMOVW psr ',' creg
        {
-               outcode($1, &$2, 0, &$4);
+               outcode(int($1), &$2, 0, &$4);
        }
 |      LMOVW lcr ',' rreg
        {
-               outcode($1, &$2, 0, &$4);
+               outcode(int($1), &$2, 0, &$4);
        }
 |      LMOVW psr ',' rreg
        {
-               outcode($1, &$2, 0, &$4);
+               outcode(int($1), &$2, 0, &$4);
        }
 |      LMOVW xlreg ',' rreg
        {
-               outcode($1, &$2, 0, &$4);
+               outcode(int($1), &$2, 0, &$4);
        }
 |      LMOVW rreg ',' xlreg
        {
-               outcode($1, &$2, 0, &$4);
+               outcode(int($1), &$2, 0, &$4);
        }
 |      LMOVW creg ',' psr
        {
-               outcode($1, &$2, 0, &$4);
+               outcode(int($1), &$2, 0, &$4);
        }
 |      LMOVW rreg ',' psr
        {
-               outcode($1, &$2, 0, &$4);
+               outcode(int($1), &$2, 0, &$4);
        }
 /*
  * branch, branch conditional
@@ -352,170 +358,170 @@ inst:
  */
 |      LBRA rel
        {
-               outcode($1, &nullgen, 0, &$2);
+               outcode(int($1), &nullgen, 0, &$2);
        }
 |      LBRA addr
        {
-               outcode($1, &nullgen, 0, &$2);
+               outcode(int($1), &nullgen, 0, &$2);
        }
 |      LBRA '(' xlreg ')'
        {
-               outcode($1, &nullgen, 0, &$3);
+               outcode(int($1), &nullgen, 0, &$3);
        }
 |      LBRA ',' rel
        {
-               outcode($1, &nullgen, 0, &$3);
+               outcode(int($1), &nullgen, 0, &$3);
        }
 |      LBRA ',' addr
        {
-               outcode($1, &nullgen, 0, &$3);
+               outcode(int($1), &nullgen, 0, &$3);
        }
 |      LBRA ',' '(' xlreg ')'
        {
-               outcode($1, &nullgen, 0, &$4);
+               outcode(int($1), &nullgen, 0, &$4);
        }
 |      LBRA creg ',' rel
        {
-               outcode($1, &$2, 0, &$4);
+               outcode(int($1), &$2, 0, &$4);
        }
 |      LBRA creg ',' addr
        {
-               outcode($1, &$2, 0, &$4);
+               outcode(int($1), &$2, 0, &$4);
        }
 |      LBRA creg ',' '(' xlreg ')'
        {
-               outcode($1, &$2, 0, &$5);
+               outcode(int($1), &$2, 0, &$5);
        }
 |      LBRA con ',' rel
        {
-               outcode($1, &nullgen, $2, &$4);
+               outcode(int($1), &nullgen, int($2), &$4);
        }
 |      LBRA con ',' addr
        {
-               outcode($1, &nullgen, $2, &$4);
+               outcode(int($1), &nullgen, int($2), &$4);
        }
 |      LBRA con ',' '(' xlreg ')'
        {
-               outcode($1, &nullgen, $2, &$5);
+               outcode(int($1), &nullgen, int($2), &$5);
        }
 |      LBRA con ',' con ',' rel
        {
-               Addr g;
+               var g obj.Addr
                g = nullgen;
-               g.type = TYPE_CONST;
-               g.offset = $2;
-               outcode($1, &g, REG_R0+$4, &$6);
+               g.Type = obj.TYPE_CONST;
+               g.Offset = $2;
+               outcode(int($1), &g, int(REG_R0+$4), &$6);
        }
 |      LBRA con ',' con ',' addr
        {
-               Addr g;
+               var g obj.Addr
                g = nullgen;
-               g.type = TYPE_CONST;
-               g.offset = $2;
-               outcode($1, &g, REG_R0+$4, &$6);
+               g.Type = obj.TYPE_CONST;
+               g.Offset = $2;
+               outcode(int($1), &g, int(REG_R0+$4), &$6);
        }
 |      LBRA con ',' con ',' '(' xlreg ')'
        {
-               Addr g;
+               var g obj.Addr
                g = nullgen;
-               g.type = TYPE_CONST;
-               g.offset = $2;
-               outcode($1, &g, REG_R0+$4, &$7);
+               g.Type = obj.TYPE_CONST;
+               g.Offset = $2;
+               outcode(int($1), &g, int(REG_R0+$4), &$7);
        }
 /*
  * conditional trap
  */
 |      LTRAP rreg ',' sreg
        {
-               outcode($1, &$2, $4, &nullgen);
+               outcode(int($1), &$2, int($4), &nullgen);
        }
 |      LTRAP imm ',' sreg
        {
-               outcode($1, &$2, $4, &nullgen);
+               outcode(int($1), &$2, int($4), &nullgen);
        }
 |      LTRAP rreg comma
        {
-               outcode($1, &$2, 0, &nullgen);
+               outcode(int($1), &$2, 0, &nullgen);
        }
 |      LTRAP comma
        {
-               outcode($1, &nullgen, 0, &nullgen);
+               outcode(int($1), &nullgen, 0, &nullgen);
        }
 /*
  * floating point operate
  */
 |      LFCONV freg ',' freg
        {
-               outcode($1, &$2, 0, &$4);
+               outcode(int($1), &$2, 0, &$4);
        }
 |      LFADD freg ',' freg
        {
-               outcode($1, &$2, 0, &$4);
+               outcode(int($1), &$2, 0, &$4);
        }
 |      LFADD freg ',' freg ',' freg
        {
-               outcode($1, &$2, $4.reg, &$6);
+               outcode(int($1), &$2, int($4.Reg), &$6);
        }
 |      LFMA freg ',' freg ',' freg ',' freg
        {
-               outgcode($1, &$2, $4.reg, &$6, &$8);
+               outgcode(int($1), &$2, int($4.Reg), &$6, &$8);
        }
 |      LFCMP freg ',' freg
        {
-               outcode($1, &$2, 0, &$4);
+               outcode(int($1), &$2, 0, &$4);
        }
 |      LFCMP freg ',' freg ',' creg
        {
-               outcode($1, &$2, $6.reg, &$4);
+               outcode(int($1), &$2, int($6.Reg), &$4);
        }
 /*
  * CMP
  */
 |      LCMP rreg ',' rreg
        {
-               outcode($1, &$2, 0, &$4);
+               outcode(int($1), &$2, 0, &$4);
        }
 |      LCMP rreg ',' imm
        {
-               outcode($1, &$2, 0, &$4);
+               outcode(int($1), &$2, 0, &$4);
        }
 |      LCMP rreg ',' rreg ',' creg
        {
-               outcode($1, &$2, $6.reg, &$4);
+               outcode(int($1), &$2, int($6.Reg), &$4);
        }
 |      LCMP rreg ',' imm ',' creg
        {
-               outcode($1, &$2, $6.reg, &$4);
+               outcode(int($1), &$2, int($6.Reg), &$4);
        }
 /*
  * rotate and mask
  */
 |      LRLWM  imm ',' rreg ',' imm ',' rreg
        {
-               outgcode($1, &$2, $4.reg, &$6, &$8);
+               outgcode(int($1), &$2, int($4.Reg), &$6, &$8);
        }
 |      LRLWM  imm ',' rreg ',' mask ',' rreg
        {
-               outgcode($1, &$2, $4.reg, &$6, &$8);
+               outgcode(int($1), &$2, int($4.Reg), &$6, &$8);
        }
 |      LRLWM  rreg ',' rreg ',' imm ',' rreg
        {
-               outgcode($1, &$2, $4.reg, &$6, &$8);
+               outgcode(int($1), &$2, int($4.Reg), &$6, &$8);
        }
 |      LRLWM  rreg ',' rreg ',' mask ',' rreg
        {
-               outgcode($1, &$2, $4.reg, &$6, &$8);
+               outgcode(int($1), &$2, int($4.Reg), &$6, &$8);
        }
 /*
  * load/store multiple
  */
 |      LMOVMW addr ',' rreg
        {
-               outcode($1, &$2, 0, &$4);
+               outcode(int($1), &$2, 0, &$4);
        }
 |      LMOVMW rreg ',' addr
        {
-               outcode($1, &$2, 0, &$4);
+               outcode(int($1), &$2, 0, &$4);
        }
 /*
  * various indexed load/store
@@ -523,112 +529,115 @@ inst:
  */
 |      LXLD regaddr ',' rreg
        {
-               outcode($1, &$2, 0, &$4);
+               outcode(int($1), &$2, 0, &$4);
        }
 |      LXLD regaddr ',' imm ',' rreg
        {
-               outgcode($1, &$2, 0, &$4, &$6);
+               outgcode(int($1), &$2, 0, &$4, &$6);
        }
 |      LXST rreg ',' regaddr
        {
-               outcode($1, &$2, 0, &$4);
+               outcode(int($1), &$2, 0, &$4);
        }
 |      LXST rreg ',' imm ',' regaddr
        {
-               outgcode($1, &$2, 0, &$4, &$6);
+               outgcode(int($1), &$2, 0, &$4, &$6);
        }
 |      LXMV regaddr ',' rreg
        {
-               outcode($1, &$2, 0, &$4);
+               outcode(int($1), &$2, 0, &$4);
        }
 |      LXMV rreg ',' regaddr
        {
-               outcode($1, &$2, 0, &$4);
+               outcode(int($1), &$2, 0, &$4);
        }
 |      LXOP regaddr
        {
-               outcode($1, &$2, 0, &nullgen);
+               outcode(int($1), &$2, 0, &nullgen);
        }
 /*
  * NOP
  */
 |      LNOP comma
        {
-               outcode($1, &nullgen, 0, &nullgen);
+               outcode(int($1), &nullgen, 0, &nullgen);
        }
 |      LNOP rreg comma
        {
-               outcode($1, &$2, 0, &nullgen);
+               outcode(int($1), &$2, 0, &nullgen);
        }
 |      LNOP freg comma
        {
-               outcode($1, &$2, 0, &nullgen);
+               outcode(int($1), &$2, 0, &nullgen);
        }
 |      LNOP ',' rreg
        {
-               outcode($1, &nullgen, 0, &$3);
+               outcode(int($1), &nullgen, 0, &$3);
        }
 |      LNOP ',' freg
        {
-               outcode($1, &nullgen, 0, &$3);
+               outcode(int($1), &nullgen, 0, &$3);
        }
 |      LNOP imm /* SYSCALL $num: load $num to R0 before syscall and restore R0 to 0 afterwards. */
        {
-               outcode($1, &$2, 0, &nullgen);
+               outcode(int($1), &$2, 0, &nullgen);
        }
 /*
  * word
  */
 |      LWORD imm comma
        {
-               outcode($1, &$2, 0, &nullgen);
+               outcode(int($1), &$2, 0, &nullgen);
        }
 |      LWORD ximm comma
        {
-               outcode($1, &$2, 0, &nullgen);
+               outcode(int($1), &$2, 0, &nullgen);
        }
 /*
  * PCDATA
  */
 |      LPCDAT imm ',' imm
        {
-               if($2.type != TYPE_CONST || $4.type != TYPE_CONST)
-                       yyerror("arguments to PCDATA must be integer constants");
-               outcode($1, &$2, 0, &$4);
+               if $2.Type != obj.TYPE_CONST || $4.Type != obj.TYPE_CONST {
+                       yyerror("arguments to PCDATA must be integer constants")
+               }
+               outcode(int($1), &$2, 0, &$4);
        }
 /*
  * FUNCDATA
  */
 |      LFUNCDAT imm ',' addr
        {
-               if($2.type != TYPE_CONST)
-                       yyerror("index for FUNCDATA must be integer constant");
-               if($4.type != NAME_EXTERN && $4.type != NAME_STATIC && $4.type != TYPE_MEM)
-                       yyerror("value for FUNCDATA must be symbol reference");
-               outcode($1, &$2, 0, &$4);
+               if $2.Type != obj.TYPE_CONST {
+                       yyerror("index for FUNCDATA must be integer constant")
+               }
+               if $4.Type != obj.TYPE_MEM || ($4.Name != obj.NAME_EXTERN && $4.Name != obj.NAME_STATIC) {
+                       yyerror("value for FUNCDATA must be symbol reference")
+               }
+               outcode(int($1), &$2, 0, &$4);
        }
 /*
  * END
  */
 |      LEND comma
        {
-               outcode($1, &nullgen, 0, &nullgen);
+               outcode(int($1), &nullgen, 0, &nullgen);
        }
 /*
  * TEXT
  */
 |      LTEXT name ',' '$' textsize
        {
-               settext($2.sym);
-               outcode($1, &$2, 0, &$5);
+               asm.Settext($2.Sym);
+               outcode(int($1), &$2, 0, &$5);
        }
 |      LTEXT name ',' con ',' '$' textsize
        {
-               settext($2.sym);
-               outcode($1, &$2, 0, &$7);
-               if(pass > 1) {
-                       lastpc->from3.type = TYPE_CONST;
-                       lastpc->from3.offset = $4;
+               asm.Settext($2.Sym);
+               outcode(int($1), &$2, int($4), &$7);
+               if asm.Pass > 1 {
+                       lastpc.From3.Type = obj.TYPE_CONST
+                       lastpc.From3.Offset = $4
                }
        }
 /*
@@ -636,16 +645,16 @@ inst:
  */
 |      LGLOBL name ',' imm
        {
-               settext($2.sym);
-               outcode($1, &$2, 0, &$4);
+               asm.Settext($2.Sym)
+               outcode(int($1), &$2, 0, &$4)
        }
 |      LGLOBL name ',' con ',' imm
        {
-               settext($2.sym);
-               outcode($1, &$2, 0, &$6);
-               if(pass > 1) {
-                       lastpc->from3.type = TYPE_CONST;
-                       lastpc->from3.offset = $4;
+               asm.Settext($2.Sym)
+               outcode(int($1), &$2, 0, &$6)
+               if asm.Pass > 1 {
+                       lastpc.From3.Type = obj.TYPE_CONST
+                       lastpc.From3.Offset = $4
                }
        }
 
@@ -654,26 +663,26 @@ inst:
  */
 |      LDATA name '/' con ',' imm
        {
-               outcode($1, &$2, 0, &$6);
-               if(pass > 1) {
-                       lastpc->from3.type = TYPE_CONST;
-                       lastpc->from3.offset = $4;
+               outcode(int($1), &$2, 0, &$6);
+               if asm.Pass > 1 {
+                       lastpc.From3.Type = obj.TYPE_CONST
+                       lastpc.From3.Offset = $4
                }
        }
 |      LDATA name '/' con ',' ximm
        {
-               outcode($1, &$2, 0, &$6);
-               if(pass > 1) {
-                       lastpc->from3.type = TYPE_CONST;
-                       lastpc->from3.offset = $4;
+               outcode(int($1), &$2, 0, &$6);
+               if asm.Pass > 1 {
+                       lastpc.From3.Type = obj.TYPE_CONST
+                       lastpc.From3.Offset = $4
                }
        }
 |      LDATA name '/' con ',' fimm
        {
-               outcode($1, &$2, 0, &$6);
-               if(pass > 1) {
-                       lastpc->from3.type = TYPE_CONST;
-                       lastpc->from3.offset = $4;
+               outcode(int($1), &$2, 0, &$6);
+               if asm.Pass > 1 {
+                       lastpc.From3.Type = obj.TYPE_CONST
+                       lastpc.From3.Offset = $4
                }
        }
 /*
@@ -681,32 +690,33 @@ inst:
  */
 |      LRETRN  comma
        {
-               outcode($1, &nullgen, 0, &nullgen);
+               outcode(int($1), &nullgen, 0, &nullgen);
        }
 
 rel:
        con '(' LPC ')'
        {
                $$ = nullgen;
-               $$.type = TYPE_BRANCH;
-               $$.offset = $1 + pc;
+               $$.Type = obj.TYPE_BRANCH;
+               $$.Offset = $1 + int64(asm.PC);
        }
 |      LNAME offset
        {
-               $1 = labellookup($1);
+               $1 = asm.LabelLookup($1);
                $$ = nullgen;
-               if(pass == 2 && $1->type != LLAB)
-                       yyerror("undefined label: %s", $1->labelname);
-               $$.type = TYPE_BRANCH;
-               $$.offset = $1->value + $2;
+               if asm.Pass == 2 && $1.Type != LLAB {
+                       yyerror("undefined label: %s", $1.Labelname)
+               }
+               $$.Type = obj.TYPE_BRANCH;
+               $$.Offset = $1.Value + $2;
        }
 
 rreg:
        sreg
        {
                $$ = nullgen;
-               $$.type = TYPE_REG;
-               $$.reg = $1;
+               $$.Type = obj.TYPE_REG;
+               $$.Reg = int16($1);
        }
 
 xlreg:
@@ -717,48 +727,49 @@ lr:
        LLR
        {
                $$ = nullgen;
-               $$.type = TYPE_REG;
-               $$.reg = $1;
+               $$.Type = obj.TYPE_REG;
+               $$.Reg = int16($1);
        }
 
 lcr:
        LCR
        {
                $$ = nullgen;
-               $$.type = TYPE_REG;
-               $$.reg = $1;    /* whole register */
+               $$.Type = obj.TYPE_REG;
+               $$.Reg = int16($1);     /* whole register */
        }
 
 ctr:
        LCTR
        {
                $$ = nullgen;
-               $$.type = TYPE_REG;
-               $$.reg = $1;
+               $$.Type = obj.TYPE_REG;
+               $$.Reg = int16($1);
        }
 
 msr:
        LMSR
        {
                $$ = nullgen;
-               $$.type = TYPE_REG;
-               $$.reg = $1;
+               $$.Type = obj.TYPE_REG;
+               $$.Reg = int16($1)
        }
 
 psr:
        LSPREG
        {
                $$ = nullgen;
-               $$.type = TYPE_REG;
-               $$.reg = $1;
+               $$.Type = obj.TYPE_REG;
+               $$.Reg = int16($1);
        }
 |      LSPR '(' con ')'
        {
-               if($3 < 0 || $3 >= 1024)
-                       yyerror("SPR/DCR out of range");
+               if $3 < 0 || $3 >= 1024 {
+                       yyerror("SPR/DCR out of range")
+               }
                $$ = nullgen;
-               $$.type = TYPE_REG;
-               $$.reg = $1 + $3;
+               $$.Type = obj.TYPE_REG
+               $$.Reg = int16($1 + $3);
        }
 |      msr
 
@@ -766,137 +777,140 @@ fpscr:
        LFPSCR
        {
                $$ = nullgen;
-               $$.type = TYPE_REG;
-               $$.reg = $1;
+               $$.Type = obj.TYPE_REG;
+               $$.Reg = int16($1);
        }
 
 freg:
        LFREG
        {
                $$ = nullgen;
-               $$.type = TYPE_REG;
-               $$.reg = $1;
+               $$.Type = obj.TYPE_REG;
+               $$.Reg = int16($1);
        }
 |      LF '(' con ')'
        {
                $$ = nullgen;
-               $$.type = TYPE_REG;
-               $$.reg = REG_F0 + $3;
+               $$.Type = obj.TYPE_REG;
+               $$.Reg = int16(REG_F0 + $3);
        }
 
 creg:
        LCREG
        {
                $$ = nullgen;
-               $$.type = TYPE_REG;
-               $$.reg = $1;
+               $$.Type = obj.TYPE_REG;
+               $$.Reg = int16($1);
        }
 |      LCR '(' con ')'
        {
                $$ = nullgen;
-               $$.type = TYPE_REG;
-               $$.reg = REG_C0 + $3;
+               $$.Type = obj.TYPE_REG;
+               $$.Reg = int16(REG_C0 + $3);
        }
 
 
 cbit:  con
        {
                $$ = nullgen;
-               $$.type = TYPE_REG;
-               $$.reg = $1;
+               $$.Type = obj.TYPE_REG;
+               $$.Reg = int16($1);
        }
 
 mask:
        con ',' con
        {
-               int mb, me;
-               uint32 v;
+               var mb, me int
+               var v uint32
 
                $$ = nullgen;
-               $$.type = TYPE_CONST;
-               mb = $1;
-               me = $3;
+               $$.Type = obj.TYPE_CONST;
+               mb = int($1);
+               me = int($3);
                if(mb < 0 || mb > 31 || me < 0 || me > 31){
                        yyerror("illegal mask start/end value(s)");
-                       mb = me = 0;
+                       mb = 0
+                       me = 0;
+               }
+               if mb <= me {
+                       v = (^uint32(0)>>uint(mb)) & (^uint32(0)<<uint(31-me))
+               } else {
+                       v = (^uint32(0)>>uint(me+1)) & (^uint32(0)<<uint(31-(mb-1)))
                }
-               if(mb <= me)
-                       v = ((uint32)~0L>>mb) & (~0L<<(31-me));
-               else
-                       v = ~(((uint32)~0L>>(me+1)) & (~0L<<(31-(mb-1))));
-               $$.offset = v;
+               $$.Offset = int64(v);
        }
 
 textsize:
        LCONST
        {
                $$ = nullgen;
-               $$.type = TYPE_TEXTSIZE;
-               $$.offset = $1;
-               $$.u.argsize = ArgsSizeUnknown;
+               $$.Type = obj.TYPE_TEXTSIZE;
+               $$.Offset = int64($1)
+               $$.U.Argsize = obj.ArgsSizeUnknown;
        }
 |      '-' LCONST
        {
                $$ = nullgen;
-               $$.type = TYPE_TEXTSIZE;
-               $$.offset = -$2;
-               $$.u.argsize = ArgsSizeUnknown;
+               $$.Type = obj.TYPE_TEXTSIZE;
+               $$.Offset = -int64($2)
+               $$.U.Argsize = obj.ArgsSizeUnknown;
        }
 |      LCONST '-' LCONST
        {
                $$ = nullgen;
-               $$.type = TYPE_TEXTSIZE;
-               $$.offset = $1;
-               $$.u.argsize = $3;
+               $$.Type = obj.TYPE_TEXTSIZE;
+               $$.Offset = int64($1)
+               $$.U.Argsize = int32($3);
        }
 |      '-' LCONST '-' LCONST
        {
                $$ = nullgen;
-               $$.type = TYPE_TEXTSIZE;
-               $$.offset = -$2;
-               $$.u.argsize = $4;
+               $$.Type = obj.TYPE_TEXTSIZE;
+               $$.Offset = -int64($2)
+               $$.U.Argsize = int32($4);
        }
 
 ximm:
        '$' addr
        {
                $$ = $2;
-               $$.type = TYPE_ADDR;
+               $$.Type = obj.TYPE_ADDR;
        }
 |      '$' LSCONST
        {
                $$ = nullgen;
-               $$.type = TYPE_SCONST;
-               memcpy($$.u.sval, $2, sizeof($$.u.sval));
+               $$.Type = obj.TYPE_SCONST;
+               $$.U.Sval = $2
        }
 
 fimm:
        '$' LFCONST
        {
                $$ = nullgen;
-               $$.type = TYPE_FCONST;
-               $$.u.dval = $2;
+               $$.Type = obj.TYPE_FCONST;
+               $$.U.Dval = $2;
        }
 |      '$' '-' LFCONST
        {
                $$ = nullgen;
-               $$.type = TYPE_FCONST;
-               $$.u.dval = -$3;
+               $$.Type = obj.TYPE_FCONST;
+               $$.U.Dval = -$3;
        }
 
 imm:   '$' con
        {
                $$ = nullgen;
-               $$.type = TYPE_CONST;
-               $$.offset = $2;
+               $$.Type = obj.TYPE_CONST;
+               $$.Offset = $2;
        }
 
 sreg:
        LREG
 |      LR '(' con ')'
        {
-               if($$ < 0 || $$ >= NREG)
-                       print("register value out of range\n");
+               if $$ < 0 || $$ >= NREG {
+                       print("register value out of range\n")
+               }
                $$ = REG_R0 + $3;
        }
 
@@ -904,17 +918,17 @@ regaddr:
        '(' sreg ')'
        {
                $$ = nullgen;
-               $$.type = TYPE_MEM;
-               $$.reg = $2;
-               $$.offset = 0;
+               $$.Type = obj.TYPE_MEM;
+               $$.Reg = int16($2);
+               $$.Offset = 0;
        }
 |      '(' sreg '+' sreg ')'
        {
                $$ = nullgen;
-               $$.type = TYPE_MEM;
-               $$.reg = $2;
-               $$.scale = $4;
-               $$.offset = 0;
+               $$.Type = obj.TYPE_MEM;
+               $$.Reg = int16($2);
+               $$.Scale = int8($4);
+               $$.Offset = 0;
        }
 
 addr:
@@ -922,35 +936,35 @@ addr:
 |      con '(' sreg ')'
        {
                $$ = nullgen;
-               $$.type = TYPE_MEM;
-               $$.reg = $3;
-               $$.offset = $1;
+               $$.Type = obj.TYPE_MEM;
+               $$.Reg = int16($3);
+               $$.Offset = $1;
        }
 
 name:
        con '(' pointer ')'
        {
                $$ = nullgen;
-               $$.type = TYPE_MEM;
-               $$.name = $3;
-               $$.sym = nil;
-               $$.offset = $1;
+               $$.Type = obj.TYPE_MEM;
+               $$.Name = int8($3);
+               $$.Sym = nil;
+               $$.Offset = $1;
        }
 |      LNAME offset '(' pointer ')'
        {
                $$ = nullgen;
-               $$.type = TYPE_MEM;
-               $$.name = $4;
-               $$.sym = linklookup(ctxt, $1->name, 0);
-               $$.offset = $2;
+               $$.Type = obj.TYPE_MEM;
+               $$.Name = int8($4);
+               $$.Sym = obj.Linklookup(asm.Ctxt, $1.Name, 0);
+               $$.Offset = $2;
        }
 |      LNAME '<' '>' offset '(' LSB ')'
        {
                $$ = nullgen;
-               $$.type = TYPE_MEM;
-               $$.name = NAME_STATIC;
-               $$.sym = linklookup(ctxt, $1->name, 1);
-               $$.offset = $4;
+               $$.Type = obj.TYPE_MEM;
+               $$.Name = obj.NAME_STATIC;
+               $$.Sym = obj.Linklookup(asm.Ctxt, $1.Name, 1);
+               $$.Offset = $4;
        }
 
 comma:
@@ -978,7 +992,7 @@ con:
        LCONST
 |      LVAR
        {
-               $$ = $1->value;
+               $$ = $1.Value;
        }
 |      '-' con
        {
@@ -990,7 +1004,7 @@ con:
        }
 |      '~' con
        {
-               $$ = ~$2;
+               $$ = ^$2;
        }
 |      '(' expr ')'
        {
@@ -1021,11 +1035,11 @@ expr:
        }
 |      expr '<' '<' expr
        {
-               $$ = $1 << $4;
+               $$ = $1 << uint($4);
        }
 |      expr '>' '>' expr
        {
-               $$ = $1 >> $4;
+               $$ = $1 >> uint($4);
        }
 |      expr '&' expr
        {
diff --git a/src/cmd/9a/doc.go b/src/cmd/9a/doc.go
deleted file mode 100644 (file)
index f6eed6d..0000000
+++ /dev/null
@@ -1,21 +0,0 @@
-// Copyright 2009 The Go Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style
-// license that can be found in the LICENSE file.
-
-// +build ignore
-
-/*
-
-9a is a version of the Plan 9 assembler.  The original is documented at
-
-       http://plan9.bell-labs.com/magic/man2html/1/8a
-
-Go-specific considerations are documented at
-
-       http://golang.org/doc/asm
-
-Its target architecture is 64-bit PowerPC and Power Architecture processors,
-referred to by these tools as ppc64 (big endian) or ppc64le (little endian).
-
-*/
-package main
diff --git a/src/cmd/9a/lex.c b/src/cmd/9a/lex.c
deleted file mode 100644 (file)
index ad55237..0000000
+++ /dev/null
@@ -1,726 +0,0 @@
-// cmd/9a/lex.c from Vita Nuova.
-//
-//     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-2008 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-2008 Lucent Technologies Inc. and others
-//     Portions Copyright Â© 2009 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.
-
-#define        EXTERN
-#include <u.h>
-#include <libc.h>
-#include "a.h"
-#include "y.tab.h"
-
-enum
-{
-       Plan9   = 1<<0,
-       Unix    = 1<<1,
-       Windows = 1<<2,
-};
-
-int
-systemtype(int sys)
-{
-#ifdef _WIN32
-       return sys&Windows;
-#else
-       return sys&Plan9;
-#endif
-}
-
-int
-pathchar(void)
-{
-       return '/';
-}
-
-int
-Lconv(Fmt *fp)
-{
-       return linklinefmt(ctxt, fp);
-}
-
-void
-dodef(char *p)
-{
-       if(nDlist%8 == 0)
-               Dlist = allocn(Dlist, nDlist*sizeof(char *),
-                       8*sizeof(char *));
-       Dlist[nDlist++] = p;
-}
-
-LinkArch*       thelinkarch = &linkppc64;
-
-void
-usage(void)
-{
-       print("usage: %ca [options] file.c...\n", thechar);
-       flagprint(1);
-       errorexit();
-}
-
-void
-main(int argc, char *argv[])
-{
-       char *p;
-
-       thechar = '9';
-       thestring = "ppc64";
-
-       // Allow GOARCH=thestring or GOARCH=thestringsuffix,
-       // but not other values.        
-       p = getgoarch();
-       if(strncmp(p, thestring, strlen(thestring)) != 0)
-               sysfatal("cannot use %cc with GOARCH=%s", thechar, p);
-       if(strcmp(p, "ppc64le") == 0)
-               thelinkarch = &linkppc64le;
-
-       ctxt = linknew(thelinkarch);
-       ctxt->diag = yyerror;
-       ctxt->bso = &bstdout;
-       ctxt->enforce_data_order = 1;
-       Binit(&bstdout, 1, OWRITE);
-       listinit9();
-       fmtinstall('L', Lconv);
-
-       ensuresymb(NSYMB);
-       memset(debug, 0, sizeof(debug));
-       cinit();
-       outfile = 0;
-       setinclude(".");
-
-       flagfn1("D", "name[=value]: add #define", dodef);
-       flagfn1("I", "dir: add dir to include path", setinclude);
-       flagcount("S", "print assembly and machine code", &debug['S']);
-       flagcount("m", "debug preprocessor macros", &debug['m']);
-       flagstr("o", "file: set output file", &outfile);
-       flagstr("trimpath", "prefix: remove prefix from recorded source file paths", &ctxt->trimpath);
-
-       flagparse(&argc, &argv, usage);
-       ctxt->debugasm = debug['S'];
-
-       if(argc < 1)
-               usage();
-       if(argc > 1){
-               print("can't assemble multiple files\n");
-               errorexit();
-       }
-
-       if(assemble(argv[0]))
-               errorexit();
-       Bflush(&bstdout);
-       if(nerrors > 0)
-               errorexit();
-       exits(0);
-}
-
-int
-assemble(char *file)
-{
-       char *ofile, *p;
-       int i, of;
-
-       ofile = alloc(strlen(file)+3); // +3 for .x\0 (x=thechar)
-       strcpy(ofile, file);
-       p = utfrrune(ofile, pathchar());
-       if(p) {
-               include[0] = ofile;
-               *p++ = 0;
-       } else
-               p = ofile;
-       if(outfile == 0) {
-               outfile = p;
-               if(outfile){
-                       p = utfrrune(outfile, '.');
-                       if(p)
-                               if(p[1] == 's' && p[2] == 0)
-                                       p[0] = 0;
-                       p = utfrune(outfile, 0);
-                       p[0] = '.';
-                       p[1] = thechar;
-                       p[2] = 0;
-               } else
-                       outfile = "/dev/null";
-       }
-
-       of = create(outfile, OWRITE, 0664);
-       if(of < 0) {
-               yyerror("%ca: cannot create %s", thechar, outfile);
-               errorexit();
-       }
-       Binit(&obuf, of, OWRITE);
-       Bprint(&obuf, "go object %s %s %s\n", getgoos(), getgoarch(), getgoversion());
-       Bprint(&obuf, "!\n");
-
-       for(pass = 1; pass <= 2; pass++) {
-               nosched = 0;
-               pinit(file);
-               for(i=0; i<nDlist; i++)
-                       dodefine(Dlist[i]);
-               yyparse();
-               cclean();
-               if(nerrors)
-                       return nerrors;
-       }
-
-       writeobj(ctxt, &obuf);
-       Bflush(&obuf);
-       return 0;
-}
-
-struct
-{
-       char    *name;
-       ushort  type;
-       ushort  value;
-} itab[] =
-{
-       "SP",           LSP,    NAME_AUTO,
-       "SB",           LSB,    NAME_EXTERN,
-       "FP",           LFP,    NAME_PARAM,
-       "PC",           LPC,    TYPE_BRANCH,
-
-       "LR",           LLR,    REG_LR,
-       "CTR",          LCTR,   REG_CTR,
-
-       "XER",          LSPREG, REG_XER,
-       "MSR",          LMSR,   REG_MSR,
-       "FPSCR",        LFPSCR, REG_FPSCR,
-       "SPR",          LSPR,   REG_SPR0,
-       "DCR",          LSPR,   REG_DCR0,
-
-       "CR",           LCR,    REG_CR,
-       "CR0",          LCREG,  REG_C0,
-       "CR1",          LCREG,  REG_C1,
-       "CR2",          LCREG,  REG_C2,
-       "CR3",          LCREG,  REG_C3,
-       "CR4",          LCREG,  REG_C4,
-       "CR5",          LCREG,  REG_C5,
-       "CR6",          LCREG,  REG_C6,
-       "CR7",          LCREG,  REG_C7,
-
-       "R",            LR,     0,
-       "R0",           LREG,   REG_R0,
-       "R1",           LREG,   REG_R1,
-       "R2",           LREG,   REG_R2,
-       "R3",           LREG,   REG_R3,
-       "R4",           LREG,   REG_R4,
-       "R5",           LREG,   REG_R5,
-       "R6",           LREG,   REG_R6,
-       "R7",           LREG,   REG_R7,
-       "R8",           LREG,   REG_R8,
-       "R9",           LREG,   REG_R9,
-       "R10",          LREG,   REG_R10,
-       "R11",          LREG,   REG_R11,
-       "R12",          LREG,   REG_R12,
-       "R13",          LREG,   REG_R13,
-       "R14",          LREG,   REG_R14,
-       "R15",          LREG,   REG_R15,
-       "R16",          LREG,   REG_R16,
-       "R17",          LREG,   REG_R17,
-       "R18",          LREG,   REG_R18,
-       "R19",          LREG,   REG_R19,
-       "R20",          LREG,   REG_R20,
-       "R21",          LREG,   REG_R21,
-       "R22",          LREG,   REG_R22,
-       "R23",          LREG,   REG_R23,
-       "R24",          LREG,   REG_R24,
-       "R25",          LREG,   REG_R25,
-       "R26",          LREG,   REG_R26,
-       "R27",          LREG,   REG_R27,
-       "R28",          LREG,   REG_R28,
-       "R29",          LREG,   REG_R29,
-       "g",            LREG,   REG_R30, // avoid unintentionally clobbering g using R30
-       "R31",          LREG,   REG_R31,
-
-       "F",            LF,     0,
-       "F0",           LFREG,  REG_F0,
-       "F1",           LFREG,  REG_F1,
-       "F2",           LFREG,  REG_F2,
-       "F3",           LFREG,  REG_F3,
-       "F4",           LFREG,  REG_F4,
-       "F5",           LFREG,  REG_F5,
-       "F6",           LFREG,  REG_F6,
-       "F7",           LFREG,  REG_F7,
-       "F8",           LFREG,  REG_F8,
-       "F9",           LFREG,  REG_F9,
-       "F10",          LFREG,  REG_F10,
-       "F11",          LFREG,  REG_F11,
-       "F12",          LFREG,  REG_F12,
-       "F13",          LFREG,  REG_F13,
-       "F14",          LFREG,  REG_F14,
-       "F15",          LFREG,  REG_F15,
-       "F16",          LFREG,  REG_F16,
-       "F17",          LFREG,  REG_F17,
-       "F18",          LFREG,  REG_F18,
-       "F19",          LFREG,  REG_F19,
-       "F20",          LFREG,  REG_F20,
-       "F21",          LFREG,  REG_F21,
-       "F22",          LFREG,  REG_F22,
-       "F23",          LFREG,  REG_F23,
-       "F24",          LFREG,  REG_F24,
-       "F25",          LFREG,  REG_F25,
-       "F26",          LFREG,  REG_F26,
-       "F27",          LFREG,  REG_F27,
-       "F28",          LFREG,  REG_F28,
-       "F29",          LFREG,  REG_F29,
-       "F30",          LFREG,  REG_F30,
-       "F31",          LFREG,  REG_F31,
-
-       "CREQV",        LCROP, ACREQV,
-       "CRXOR",        LCROP, ACRXOR,
-       "CRAND",        LCROP, ACRAND,
-       "CROR",         LCROP, ACROR,
-       "CRANDN",       LCROP, ACRANDN,
-       "CRORN",        LCROP, ACRORN,
-       "CRNAND",       LCROP, ACRNAND,
-       "CRNOR",        LCROP, ACRNOR,
-
-       "ADD",          LADDW, AADD,
-       "ADDV",         LADDW, AADDV,
-       "ADDCC",        LADDW, AADDCC,
-       "ADDVCC",       LADDW, AADDVCC,
-       "ADDC",         LADDW, AADDC,
-       "ADDCV",        LADDW, AADDCV,
-       "ADDCCC",       LADDW, AADDCCC,
-       "ADDCVCC",      LADDW, AADDCVCC,
-       "ADDE",         LLOGW, AADDE,
-       "ADDEV",        LLOGW, AADDEV,
-       "ADDECC",       LLOGW, AADDECC,
-       "ADDEVCC",      LLOGW, AADDEVCC,
-
-       "ADDME",        LABS, AADDME,
-       "ADDMEV",       LABS, AADDMEV,
-       "ADDMECC",      LABS, AADDMECC,
-       "ADDMEVCC",     LABS, AADDMEVCC,
-       "ADDZE",        LABS, AADDZE,
-       "ADDZEV",       LABS, AADDZEV,
-       "ADDZECC",      LABS, AADDZECC,
-       "ADDZEVCC",     LABS, AADDZEVCC,
-
-       "SUB",          LADDW, ASUB,
-       "SUBV",         LADDW, ASUBV,
-       "SUBCC",        LADDW, ASUBCC,
-       "SUBVCC",       LADDW, ASUBVCC,
-       "SUBE",         LLOGW, ASUBE,
-       "SUBECC",       LLOGW, ASUBECC,
-       "SUBEV",        LLOGW, ASUBEV,
-       "SUBEVCC",      LLOGW, ASUBEVCC,
-       "SUBC",         LADDW, ASUBC,
-       "SUBCCC",       LADDW, ASUBCCC,
-       "SUBCV",        LADDW, ASUBCV,
-       "SUBCVCC",      LADDW, ASUBCVCC,
-
-       "SUBME",        LABS, ASUBME,
-       "SUBMEV",       LABS, ASUBMEV,
-       "SUBMECC",      LABS, ASUBMECC,
-       "SUBMEVCC",     LABS, ASUBMEVCC,
-       "SUBZE",        LABS, ASUBZE,
-       "SUBZEV",       LABS, ASUBZEV,
-       "SUBZECC",      LABS, ASUBZECC,
-       "SUBZEVCC",     LABS, ASUBZEVCC,
-
-       "AND",          LADDW, AAND,
-       "ANDCC",        LADDW, AANDCC,  /* includes andil & andiu */
-       "ANDN",         LLOGW, AANDN,
-       "ANDNCC",       LLOGW, AANDNCC,
-       "EQV",          LLOGW, AEQV,
-       "EQVCC",        LLOGW, AEQVCC,
-       "NAND",         LLOGW, ANAND,
-       "NANDCC",       LLOGW, ANANDCC,
-       "NOR",          LLOGW, ANOR,
-       "NORCC",        LLOGW, ANORCC,
-       "OR",           LADDW, AOR,     /* includes oril & oriu */
-       "ORCC",         LADDW, AORCC,
-       "ORN",          LLOGW, AORN,
-       "ORNCC",        LLOGW, AORNCC,
-       "XOR",          LADDW, AXOR,    /* includes xoril & xoriu */
-       "XORCC",        LLOGW, AXORCC,
-
-       "EXTSB",        LABS,   AEXTSB,
-       "EXTSBCC",      LABS,   AEXTSBCC,
-       "EXTSH",        LABS, AEXTSH,
-       "EXTSHCC",      LABS, AEXTSHCC,
-
-       "CNTLZW",       LABS, ACNTLZW,
-       "CNTLZWCC",     LABS, ACNTLZWCC,
-
-       "RLWMI",        LRLWM, ARLWMI,
-       "RLWMICC",      LRLWM, ARLWMICC,
-       "RLWNM",        LRLWM, ARLWNM,
-       "RLWNMCC", LRLWM, ARLWNMCC,
-
-       "SLW",          LSHW, ASLW,
-       "SLWCC",        LSHW, ASLWCC,
-       "SRW",          LSHW, ASRW,
-       "SRWCC",        LSHW, ASRWCC,
-       "SRAW",         LSHW, ASRAW,
-       "SRAWCC",       LSHW, ASRAWCC,
-
-       "BR",           LBRA, ABR,
-       "BC",           LBRA, ABC,
-       "BCL",          LBRA, ABC,
-       "BL",           LBRA, ABL,
-       "BEQ",          LBRA, ABEQ,
-       "BNE",          LBRA, ABNE,
-       "BGT",          LBRA, ABGT,
-       "BGE",          LBRA, ABGE,
-       "BLT",          LBRA, ABLT,
-       "BLE",          LBRA, ABLE,
-       "BVC",          LBRA, ABVC,
-       "BVS",          LBRA, ABVS,
-
-       "CMP",          LCMP, ACMP,
-       "CMPU",         LCMP, ACMPU,
-       "CMPW",         LCMP, ACMPW,
-       "CMPWU",        LCMP, ACMPWU,
-
-       "DIVW",         LLOGW, ADIVW,
-       "DIVWV",        LLOGW, ADIVWV,
-       "DIVWCC",       LLOGW, ADIVWCC,
-       "DIVWVCC",      LLOGW, ADIVWVCC,
-       "DIVWU",        LLOGW, ADIVWU,
-       "DIVWUV",       LLOGW, ADIVWUV,
-       "DIVWUCC",      LLOGW, ADIVWUCC,
-       "DIVWUVCC",     LLOGW, ADIVWUVCC,
-
-       "FABS",         LFCONV, AFABS,
-       "FABSCC",       LFCONV, AFABSCC,
-       "FNEG",         LFCONV, AFNEG,
-       "FNEGCC",       LFCONV, AFNEGCC,
-       "FNABS",        LFCONV, AFNABS,
-       "FNABSCC",      LFCONV, AFNABSCC,
-
-       "FADD",         LFADD,  AFADD,
-       "FADDCC",       LFADD,  AFADDCC,
-       "FSUB",         LFADD,  AFSUB,
-       "FSUBCC",       LFADD,  AFSUBCC,
-       "FMUL",         LFADD,  AFMUL,
-       "FMULCC",       LFADD,  AFMULCC,
-       "FDIV",         LFADD,  AFDIV,
-       "FDIVCC",       LFADD,  AFDIVCC,
-       "FRSP",         LFCONV, AFRSP,
-       "FRSPCC",       LFCONV, AFRSPCC,
-       "FCTIW",        LFCONV, AFCTIW,
-       "FCTIWCC",      LFCONV, AFCTIWCC,
-       "FCTIWZ",       LFCONV, AFCTIWZ,
-       "FCTIWZCC",     LFCONV, AFCTIWZCC,
-
-       "FMADD",        LFMA, AFMADD,
-       "FMADDCC",      LFMA, AFMADDCC,
-       "FMSUB",        LFMA, AFMSUB,
-       "FMSUBCC",      LFMA, AFMSUBCC,
-       "FNMADD",       LFMA, AFNMADD,
-       "FNMADDCC",     LFMA, AFNMADDCC,
-       "FNMSUB",       LFMA, AFNMSUB,
-       "FNMSUBCC",     LFMA, AFNMSUBCC,
-       "FMADDS",       LFMA, AFMADDS,
-       "FMADDSCC",     LFMA, AFMADDSCC,
-       "FMSUBS",       LFMA, AFMSUBS,
-       "FMSUBSCC",     LFMA, AFMSUBSCC,
-       "FNMADDS",      LFMA, AFNMADDS,
-       "FNMADDSCC",    LFMA, AFNMADDSCC,
-       "FNMSUBS",      LFMA, AFNMSUBS,
-       "FNMSUBSCC",    LFMA, AFNMSUBSCC,
-
-       "FCMPU",        LFCMP, AFCMPU,
-       "FCMPO",        LFCMP, AFCMPO,
-       "MTFSB0",       LMTFSB, AMTFSB0,
-       "MTFSB1",       LMTFSB, AMTFSB1,
-
-       "FMOVD",        LFMOV, AFMOVD,
-       "FMOVS",        LFMOV, AFMOVS,
-       "FMOVDCC",      LFCONV, AFMOVDCC,       /* fmr. */
-
-       "GLOBL",        LGLOBL, AGLOBL,
-
-       "MOVB",         LMOVB, AMOVB,
-       "MOVBZ",        LMOVB, AMOVBZ,
-       "MOVBU",        LMOVB, AMOVBU,
-       "MOVBZU", LMOVB, AMOVBZU,
-       "MOVH",         LMOVB, AMOVH,
-       "MOVHZ",        LMOVB, AMOVHZ,
-       "MOVHU",        LMOVB, AMOVHU,
-       "MOVHZU", LMOVB, AMOVHZU,
-       "MOVHBR",       LXMV, AMOVHBR,
-       "MOVWBR",       LXMV, AMOVWBR,
-       "MOVW",         LMOVW, AMOVW,
-       "MOVWU",        LMOVW, AMOVWU,
-       "MOVMW",        LMOVMW, AMOVMW,
-       "MOVFL",        LMOVW,  AMOVFL,
-
-       "MULLW",        LADDW, AMULLW,          /* includes multiply immediate 10-139 */
-       "MULLWV",       LLOGW, AMULLWV,
-       "MULLWCC",      LLOGW, AMULLWCC,
-       "MULLWVCC",     LLOGW, AMULLWVCC,
-
-       "MULHW",        LLOGW, AMULHW,
-       "MULHWCC",      LLOGW, AMULHWCC,
-       "MULHWU",       LLOGW, AMULHWU,
-       "MULHWUCC",     LLOGW, AMULHWUCC,
-
-       "NEG",          LABS, ANEG,
-       "NEGV",         LABS, ANEGV,
-       "NEGCC",        LABS, ANEGCC,
-       "NEGVCC",       LABS, ANEGVCC,
-
-       "NOP",          LNOP, ANOP,     /* ori 0,0,0 */
-       "SYSCALL",      LNOP, ASYSCALL,
-       "UNDEF",        LNOP, AUNDEF,
-
-       "RET",          LRETRN, ARETURN,
-       "RETURN",       LRETRN, ARETURN,
-       "RFI",          LRETRN, ARFI,
-       "RFCI",         LRETRN, ARFCI,
-
-       "DATA",         LDATA, ADATA,
-       "END",          LEND, AEND,
-       "TEXT",         LTEXT, ATEXT,
-
-       /* 64-bit instructions */
-       "CNTLZD",       LABS,   ACNTLZD,
-       "CNTLZDCC",     LABS,   ACNTLZDCC,
-       "DIVD", LLOGW,  ADIVD,
-       "DIVDCC",       LLOGW,  ADIVDCC,
-       "DIVDVCC",      LLOGW,  ADIVDVCC,
-       "DIVDV",        LLOGW,  ADIVDV,
-       "DIVDU",        LLOGW,  ADIVDU,
-       "DIVDUCC",      LLOGW,  ADIVDUCC,
-       "DIVDUVCC",     LLOGW,  ADIVDUVCC,
-       "DIVDUV",       LLOGW,  ADIVDUV,
-       "EXTSW",        LABS, AEXTSW,
-       "EXTSWCC",      LABS, AEXTSWCC,
-       "FCTID",        LFCONV, AFCTID,
-       "FCTIDCC",      LFCONV, AFCTIDCC,
-       "FCTIDZ",       LFCONV, AFCTIDZ,
-       "FCTIDZCC",     LFCONV, AFCTIDZCC,
-       "FCFID",        LFCONV, AFCFID,
-       "FCFIDCC",      LFCONV, AFCFIDCC,
-       "LDAR", LXLD, ALDAR,
-       "MOVD", LMOVW,  AMOVD,
-       "MOVDU",        LMOVW,  AMOVDU,
-       "MOVWZ",        LMOVW,  AMOVWZ,
-       "MOVWZU",       LMOVW,  AMOVWZU,
-       "MULHD",        LLOGW,  AMULHD,
-       "MULHDCC",      LLOGW,  AMULHDCC,
-       "MULHDU",       LLOGW,  AMULHDU,
-       "MULHDUCC",     LLOGW,  AMULHDUCC,
-       "MULLD",        LADDW,  AMULLD, /* includes multiply immediate? */
-       "MULLDCC",      LLOGW,  AMULLDCC,
-       "MULLDVCC",     LLOGW,  AMULLDVCC,
-       "MULLDV",       LLOGW,  AMULLDV,
-       "RFID", LRETRN, ARFID,
-       "HRFID", LRETRN, AHRFID,
-       "RLDMI",        LRLWM,  ARLDMI,
-       "RLDMICC",      LRLWM,  ARLDMICC,
-       "RLDC", LRLWM,  ARLDC,
-       "RLDCCC",       LRLWM,  ARLDCCC,
-       "RLDCR",        LRLWM,  ARLDCR,
-       "RLDCRCC",      LRLWM,  ARLDCRCC,
-       "RLDCL",        LRLWM,  ARLDCL,
-       "RLDCLCC",      LRLWM,  ARLDCLCC,
-       "SLBIA",        LNOP,   ASLBIA,
-       "SLBIE",        LNOP,   ASLBIE,
-       "SLBMFEE",      LABS,   ASLBMFEE,
-       "SLBMFEV",      LABS,   ASLBMFEV,
-       "SLBMTE",       LABS,   ASLBMTE,
-       "SLD",  LSHW,   ASLD,
-       "SLDCC",        LSHW,   ASLDCC,
-       "SRD",  LSHW,   ASRD,
-       "SRAD", LSHW,   ASRAD,
-       "SRADCC",       LSHW,   ASRADCC,
-       "SRDCC",        LSHW,   ASRDCC,
-       "STDCCC",       LXST,   ASTDCCC,
-       "TD",   LADDW,  ATD,
-
-       /* pseudo instructions */
-       "REM",  LLOGW,  AREM,
-       "REMCC",        LLOGW,  AREMCC,
-       "REMV", LLOGW,  AREMV,
-       "REMVCC",       LLOGW,  AREMVCC,
-       "REMU", LLOGW,  AREMU,
-       "REMUCC",       LLOGW,  AREMUCC,
-       "REMUV",        LLOGW,  AREMUV,
-       "REMUVCC",      LLOGW,  AREMUVCC,
-       "REMD", LLOGW,  AREMD,
-       "REMDCC",       LLOGW,  AREMDCC,
-       "REMDV",        LLOGW,  AREMDV,
-       "REMDVCC",      LLOGW,  AREMDVCC,
-       "REMDU",        LLOGW,  AREMDU,
-       "REMDUCC",      LLOGW,  AREMDUCC,
-       "REMDUV",       LLOGW,  AREMDUV,
-       "REMDUVCC",     LLOGW,  AREMDUVCC,
-
-/* special instructions */
-       "DCBF",         LXOP,   ADCBF,
-       "DCBI",         LXOP,   ADCBI,
-       "DCBST",        LXOP,   ADCBST,
-       "DCBT",         LXOP,   ADCBT,
-       "DCBTST",       LXOP,   ADCBTST,
-       "DCBZ",         LXOP,   ADCBZ,
-       "ICBI",         LXOP,   AICBI,
-
-       "ECIWX",        LXLD,   AECIWX,
-       "ECOWX",        LXST,   AECOWX,
-       "LWAR", LXLD, ALWAR,
-       "LWAR", LXLD, ALWAR,
-       "STWCCC", LXST, ASTWCCC,
-       "EIEIO",        LRETRN, AEIEIO,
-       "TLBIE",        LNOP,   ATLBIE,
-       "TLBIEL",       LNOP,   ATLBIEL,
-       "LSW",  LXLD, ALSW,
-       "STSW", LXST, ASTSW,
-       
-       "ISYNC",        LRETRN, AISYNC,
-       "SYNC",         LRETRN, ASYNC,
-       "TLBSYNC",      LRETRN, ATLBSYNC,
-       "PTESYNC",      LRETRN, APTESYNC,
-/*     "TW",           LADDW,  ATW,*/
-
-       "WORD",         LWORD, AWORD,
-       "DWORD",        LWORD, ADWORD,
-       "SCHED",        LSCHED, 0,
-       "NOSCHED",      LSCHED, 0x80,
-
-       "PCDATA",       LPCDAT, APCDATA,
-       "FUNCDATA",     LFUNCDAT,       AFUNCDATA,
-
-       0
-};
-
-void
-cinit(void)
-{
-       Sym *s;
-       int i;
-
-       nullgen.type = TYPE_NONE;
-       nullgen.name = NAME_NONE;
-       nullgen.reg = 0;
-       nullgen.scale = 0; // replaced Gen.xreg with Prog.scale
-
-       nerrors = 0;
-       iostack = I;
-       iofree = I;
-       peekc = IGN;
-       nhunk = 0;
-       for(i=0; i<NHASH; i++)
-               hash[i] = S;
-       for(i=0; itab[i].name; i++) {
-               s = slookup(itab[i].name);
-               s->type = itab[i].type;
-               s->value = itab[i].value;
-       }
-}
-
-void
-syminit(Sym *s)
-{
-
-       s->type = LNAME;
-       s->value = 0;
-}
-
-void
-cclean(void)
-{
-
-       outcode(AEND, &nullgen, 0, &nullgen);
-}
-
-void
-outcode(int a, Addr *g1, int reg, Addr *g2)
-{
-       Prog *p;
-       Plist *pl;
-
-       if(pass == 1)
-               goto out;
-
-       if(g1->scale != 0) {
-               if(reg != 0 || g2->scale != 0)
-                       yyerror("bad addressing modes");
-               reg = g1->scale;
-       } else
-       if(g2->scale != 0) {
-               if(reg != 0)
-                       yyerror("bad addressing modes");
-               reg = g2->scale;
-       }
-
-       p = emallocz(sizeof(Prog));
-       p->as = a;
-       p->lineno = stmtline;
-       if(nosched)
-               p->mark |= NOSCHED;
-       p->from = *g1;
-       p->reg = reg;
-       p->to = *g2;
-       p->pc = pc;
-
-       if(lastpc == nil) {
-               pl = linknewplist(ctxt);
-               pl->firstpc = p;
-       } else
-               lastpc->link = p;
-       lastpc = p;
-out:
-       if(a != AGLOBL && a != ADATA)
-               pc++;
-}
-
-void
-outgcode(int a, Addr *g1, int reg, Addr *g2, Addr *g3)
-{
-       Prog *p;
-       Plist *pl;
-
-       if(pass == 1)
-               goto out;
-
-       p = emallocz(sizeof(Prog));
-       p->as = a;
-       p->lineno = stmtline;
-       if(nosched)
-               p->mark |= NOSCHED;
-       p->from = *g1;
-       p->reg = reg;
-       p->from3 = *g2;
-       p->to = *g3;
-       p->pc = pc;
-
-       if(lastpc == nil) {
-               pl = linknewplist(ctxt);
-               pl->firstpc = p;
-       } else
-               lastpc->link = p;
-       lastpc = p;
-out:
-       if(a != AGLOBL && a != ADATA)
-               pc++;
-}
-
-#include "../cc/lexbody"
-#include "../cc/macbody"
similarity index 100%
rename from src/cmd/new9a/lex.go
rename to src/cmd/9a/lex.go
similarity index 100%
rename from src/cmd/new9a/y.go
rename to src/cmd/9a/y.go
diff --git a/src/cmd/9a/y.tab.c b/src/cmd/9a/y.tab.c
deleted file mode 100644 (file)
index 829f4d5..0000000
+++ /dev/null
@@ -1,3466 +0,0 @@
-/* A Bison parser, made by GNU Bison 2.3.  */
-
-/* Skeleton implementation for Bison's Yacc-like parsers in C
-
-   Copyright (C) 1984, 1989, 1990, 2000, 2001, 2002, 2003, 2004, 2005, 2006
-   Free Software Foundation, Inc.
-
-   This program is free software; you can redistribute it and/or modify
-   it under the terms of the GNU General Public License as published by
-   the Free Software Foundation; either version 2, or (at your option)
-   any later version.
-
-   This program is distributed in the hope that it will be useful,
-   but WITHOUT ANY WARRANTY; without even the implied warranty of
-   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-   GNU General Public License for more details.
-
-   You should have received a copy of the GNU General Public License
-   along with this program; if not, write to the Free Software
-   Foundation, Inc., 51 Franklin Street, Fifth Floor,
-   Boston, MA 02110-1301, USA.  */
-
-/* As a special exception, you may create a larger work that contains
-   part or all of the Bison parser skeleton and distribute that work
-   under terms of your choice, so long as that work isn't itself a
-   parser generator using the skeleton or a modified version thereof
-   as a parser skeleton.  Alternatively, if you modify or redistribute
-   the parser skeleton itself, you may (at your option) remove this
-   special exception, which will cause the skeleton and the resulting
-   Bison output files to be licensed under the GNU General Public
-   License without this special exception.
-
-   This special exception was added by the Free Software Foundation in
-   version 2.2 of Bison.  */
-
-/* C LALR(1) parser skeleton written by Richard Stallman, by
-   simplifying the original so-called "semantic" parser.  */
-
-/* All symbols defined below should begin with yy or YY, to avoid
-   infringing on user name space.  This should be done even for local
-   variables, as they might otherwise be expanded by user macros.
-   There are some unavoidable exceptions within include files to
-   define necessary library symbols; they are noted "INFRINGES ON
-   USER NAME SPACE" below.  */
-
-/* Identify Bison output.  */
-#define YYBISON 1
-
-/* Bison version.  */
-#define YYBISON_VERSION "2.3"
-
-/* Skeleton name.  */
-#define YYSKELETON_NAME "yacc.c"
-
-/* Pure parsers.  */
-#define YYPURE 0
-
-/* Using locations.  */
-#define YYLSP_NEEDED 0
-
-
-
-/* Tokens.  */
-#ifndef YYTOKENTYPE
-# define YYTOKENTYPE
-   /* Put the tokens into the symbol table, so that GDB and other debuggers
-      know about them.  */
-   enum yytokentype {
-     LMOVW = 258,
-     LMOVB = 259,
-     LABS = 260,
-     LLOGW = 261,
-     LSHW = 262,
-     LADDW = 263,
-     LCMP = 264,
-     LCROP = 265,
-     LBRA = 266,
-     LFMOV = 267,
-     LFCONV = 268,
-     LFCMP = 269,
-     LFADD = 270,
-     LFMA = 271,
-     LTRAP = 272,
-     LXORW = 273,
-     LNOP = 274,
-     LEND = 275,
-     LRETT = 276,
-     LWORD = 277,
-     LTEXT = 278,
-     LGLOBL = 279,
-     LDATA = 280,
-     LRETRN = 281,
-     LCONST = 282,
-     LSP = 283,
-     LSB = 284,
-     LFP = 285,
-     LPC = 286,
-     LCREG = 287,
-     LFLUSH = 288,
-     LREG = 289,
-     LFREG = 290,
-     LR = 291,
-     LCR = 292,
-     LF = 293,
-     LFPSCR = 294,
-     LLR = 295,
-     LCTR = 296,
-     LSPR = 297,
-     LSPREG = 298,
-     LSEG = 299,
-     LMSR = 300,
-     LPCDAT = 301,
-     LFUNCDAT = 302,
-     LSCHED = 303,
-     LXLD = 304,
-     LXST = 305,
-     LXOP = 306,
-     LXMV = 307,
-     LRLWM = 308,
-     LMOVMW = 309,
-     LMOVEM = 310,
-     LMOVFL = 311,
-     LMTFSB = 312,
-     LMA = 313,
-     LFCONST = 314,
-     LSCONST = 315,
-     LNAME = 316,
-     LLAB = 317,
-     LVAR = 318
-   };
-#endif
-/* Tokens.  */
-#define LMOVW 258
-#define LMOVB 259
-#define LABS 260
-#define LLOGW 261
-#define LSHW 262
-#define LADDW 263
-#define LCMP 264
-#define LCROP 265
-#define LBRA 266
-#define LFMOV 267
-#define LFCONV 268
-#define LFCMP 269
-#define LFADD 270
-#define LFMA 271
-#define LTRAP 272
-#define LXORW 273
-#define LNOP 274
-#define LEND 275
-#define LRETT 276
-#define LWORD 277
-#define LTEXT 278
-#define LGLOBL 279
-#define LDATA 280
-#define LRETRN 281
-#define LCONST 282
-#define LSP 283
-#define LSB 284
-#define LFP 285
-#define LPC 286
-#define LCREG 287
-#define LFLUSH 288
-#define LREG 289
-#define LFREG 290
-#define LR 291
-#define LCR 292
-#define LF 293
-#define LFPSCR 294
-#define LLR 295
-#define LCTR 296
-#define LSPR 297
-#define LSPREG 298
-#define LSEG 299
-#define LMSR 300
-#define LPCDAT 301
-#define LFUNCDAT 302
-#define LSCHED 303
-#define LXLD 304
-#define LXST 305
-#define LXOP 306
-#define LXMV 307
-#define LRLWM 308
-#define LMOVMW 309
-#define LMOVEM 310
-#define LMOVFL 311
-#define LMTFSB 312
-#define LMA 313
-#define LFCONST 314
-#define LSCONST 315
-#define LNAME 316
-#define LLAB 317
-#define LVAR 318
-
-
-
-
-/* Copy the first part of user declarations.  */
-#line 30 "a.y"
-
-#include <u.h>
-#include <stdio.h>     /* if we don't, bison will, and a.h re-#defines getc */
-#include <libc.h>
-#include "a.h"
-#include "../../runtime/funcdata.h"
-
-
-/* Enabling traces.  */
-#ifndef YYDEBUG
-# define YYDEBUG 0
-#endif
-
-/* Enabling verbose error messages.  */
-#ifdef YYERROR_VERBOSE
-# undef YYERROR_VERBOSE
-# define YYERROR_VERBOSE 1
-#else
-# define YYERROR_VERBOSE 0
-#endif
-
-/* Enabling the token table.  */
-#ifndef YYTOKEN_TABLE
-# define YYTOKEN_TABLE 0
-#endif
-
-#if ! defined YYSTYPE && ! defined YYSTYPE_IS_DECLARED
-typedef union YYSTYPE
-#line 38 "a.y"
-{
-       Sym     *sym;
-       vlong   lval;
-       double  dval;
-       char    sval[8];
-       Addr    addr;
-}
-/* Line 193 of yacc.c.  */
-#line 238 "y.tab.c"
-       YYSTYPE;
-# define yystype YYSTYPE /* obsolescent; will be withdrawn */
-# define YYSTYPE_IS_DECLARED 1
-# define YYSTYPE_IS_TRIVIAL 1
-#endif
-
-
-
-/* Copy the second part of user declarations.  */
-
-
-/* Line 216 of yacc.c.  */
-#line 251 "y.tab.c"
-
-#ifdef short
-# undef short
-#endif
-
-#ifdef YYTYPE_UINT8
-typedef YYTYPE_UINT8 yytype_uint8;
-#else
-typedef unsigned char yytype_uint8;
-#endif
-
-#ifdef YYTYPE_INT8
-typedef YYTYPE_INT8 yytype_int8;
-#elif (defined __STDC__ || defined __C99__FUNC__ \
-     || defined __cplusplus || defined _MSC_VER)
-typedef signed char yytype_int8;
-#else
-typedef short int yytype_int8;
-#endif
-
-#ifdef YYTYPE_UINT16
-typedef YYTYPE_UINT16 yytype_uint16;
-#else
-typedef unsigned short int yytype_uint16;
-#endif
-
-#ifdef YYTYPE_INT16
-typedef YYTYPE_INT16 yytype_int16;
-#else
-typedef short int yytype_int16;
-#endif
-
-#ifndef YYSIZE_T
-# ifdef __SIZE_TYPE__
-#  define YYSIZE_T __SIZE_TYPE__
-# elif defined size_t
-#  define YYSIZE_T size_t
-# elif ! defined YYSIZE_T && (defined __STDC__ || defined __C99__FUNC__ \
-     || defined __cplusplus || defined _MSC_VER)
-#  include <stddef.h> /* INFRINGES ON USER NAME SPACE */
-#  define YYSIZE_T size_t
-# else
-#  define YYSIZE_T unsigned int
-# endif
-#endif
-
-#define YYSIZE_MAXIMUM ((YYSIZE_T) -1)
-
-#ifndef YY_
-# if defined YYENABLE_NLS && YYENABLE_NLS
-#  if ENABLE_NLS
-#   include <libintl.h> /* INFRINGES ON USER NAME SPACE */
-#   define YY_(msgid) dgettext ("bison-runtime", msgid)
-#  endif
-# endif
-# ifndef YY_
-#  define YY_(msgid) msgid
-# endif
-#endif
-
-/* Suppress unused-variable warnings by "using" E.  */
-#if ! defined lint || defined __GNUC__
-# define YYUSE(e) ((void) (e))
-#else
-# define YYUSE(e) /* empty */
-#endif
-
-/* Identity function, used to suppress warnings about constant conditions.  */
-#ifndef lint
-# define YYID(n) (n)
-#else
-#if (defined __STDC__ || defined __C99__FUNC__ \
-     || defined __cplusplus || defined _MSC_VER)
-static int
-YYID (int i)
-#else
-static int
-YYID (i)
-    int i;
-#endif
-{
-  return i;
-}
-#endif
-
-#if ! defined yyoverflow || YYERROR_VERBOSE
-
-/* The parser invokes alloca or malloc; define the necessary symbols.  */
-
-# ifdef YYSTACK_USE_ALLOCA
-#  if YYSTACK_USE_ALLOCA
-#   ifdef __GNUC__
-#    define YYSTACK_ALLOC __builtin_alloca
-#   elif defined __BUILTIN_VA_ARG_INCR
-#    include <alloca.h> /* INFRINGES ON USER NAME SPACE */
-#   elif defined _AIX
-#    define YYSTACK_ALLOC __alloca
-#   elif defined _MSC_VER
-#    include <malloc.h> /* INFRINGES ON USER NAME SPACE */
-#    define alloca _alloca
-#   else
-#    define YYSTACK_ALLOC alloca
-#    if ! defined _ALLOCA_H && ! defined _STDLIB_H && (defined __STDC__ || defined __C99__FUNC__ \
-     || defined __cplusplus || defined _MSC_VER)
-#     include <stdlib.h> /* INFRINGES ON USER NAME SPACE */
-#     ifndef _STDLIB_H
-#      define _STDLIB_H 1
-#     endif
-#    endif
-#   endif
-#  endif
-# endif
-
-# ifdef YYSTACK_ALLOC
-   /* Pacify GCC's `empty if-body' warning.  */
-#  define YYSTACK_FREE(Ptr) do { /* empty */; } while (YYID (0))
-#  ifndef YYSTACK_ALLOC_MAXIMUM
-    /* The OS might guarantee only one guard page at the bottom of the stack,
-       and a page size can be as small as 4096 bytes.  So we cannot safely
-       invoke alloca (N) if N exceeds 4096.  Use a slightly smaller number
-       to allow for a few compiler-allocated temporary stack slots.  */
-#   define YYSTACK_ALLOC_MAXIMUM 4032 /* reasonable circa 2006 */
-#  endif
-# else
-#  define YYSTACK_ALLOC YYMALLOC
-#  define YYSTACK_FREE YYFREE
-#  ifndef YYSTACK_ALLOC_MAXIMUM
-#   define YYSTACK_ALLOC_MAXIMUM YYSIZE_MAXIMUM
-#  endif
-#  if (defined __cplusplus && ! defined _STDLIB_H \
-       && ! ((defined YYMALLOC || defined malloc) \
-            && (defined YYFREE || defined free)))
-#   include <stdlib.h> /* INFRINGES ON USER NAME SPACE */
-#   ifndef _STDLIB_H
-#    define _STDLIB_H 1
-#   endif
-#  endif
-#  ifndef YYMALLOC
-#   define YYMALLOC malloc
-#   if ! defined malloc && ! defined _STDLIB_H && (defined __STDC__ || defined __C99__FUNC__ \
-     || defined __cplusplus || defined _MSC_VER)
-void *malloc (YYSIZE_T); /* INFRINGES ON USER NAME SPACE */
-#   endif
-#  endif
-#  ifndef YYFREE
-#   define YYFREE free
-#   if ! defined free && ! defined _STDLIB_H && (defined __STDC__ || defined __C99__FUNC__ \
-     || defined __cplusplus || defined _MSC_VER)
-void free (void *); /* INFRINGES ON USER NAME SPACE */
-#   endif
-#  endif
-# endif
-#endif /* ! defined yyoverflow || YYERROR_VERBOSE */
-
-
-#if (! defined yyoverflow \
-     && (! defined __cplusplus \
-        || (defined YYSTYPE_IS_TRIVIAL && YYSTYPE_IS_TRIVIAL)))
-
-/* A type that is properly aligned for any stack member.  */
-union yyalloc
-{
-  yytype_int16 yyss;
-  YYSTYPE yyvs;
-  };
-
-/* The size of the maximum gap between one aligned stack and the next.  */
-# define YYSTACK_GAP_MAXIMUM (sizeof (union yyalloc) - 1)
-
-/* The size of an array large to enough to hold all stacks, each with
-   N elements.  */
-# define YYSTACK_BYTES(N) \
-     ((N) * (sizeof (yytype_int16) + sizeof (YYSTYPE)) \
-      + YYSTACK_GAP_MAXIMUM)
-
-/* Copy COUNT objects from FROM to TO.  The source and destination do
-   not overlap.  */
-# ifndef YYCOPY
-#  if defined __GNUC__ && 1 < __GNUC__
-#   define YYCOPY(To, From, Count) \
-      __builtin_memcpy (To, From, (Count) * sizeof (*(From)))
-#  else
-#   define YYCOPY(To, From, Count)             \
-      do                                       \
-       {                                       \
-         YYSIZE_T yyi;                         \
-         for (yyi = 0; yyi < (Count); yyi++)   \
-           (To)[yyi] = (From)[yyi];            \
-       }                                       \
-      while (YYID (0))
-#  endif
-# endif
-
-/* Relocate STACK from its old location to the new one.  The
-   local variables YYSIZE and YYSTACKSIZE give the old and new number of
-   elements in the stack, and YYPTR gives the new location of the
-   stack.  Advance YYPTR to a properly aligned location for the next
-   stack.  */
-# define YYSTACK_RELOCATE(Stack)                                       \
-    do                                                                 \
-      {                                                                        \
-       YYSIZE_T yynewbytes;                                            \
-       YYCOPY (&yyptr->Stack, Stack, yysize);                          \
-       Stack = &yyptr->Stack;                                          \
-       yynewbytes = yystacksize * sizeof (*Stack) + YYSTACK_GAP_MAXIMUM; \
-       yyptr += yynewbytes / sizeof (*yyptr);                          \
-      }                                                                        \
-    while (YYID (0))
-
-#endif
-
-/* YYFINAL -- State number of the termination state.  */
-#define YYFINAL  2
-/* YYLAST -- Last index in YYTABLE.  */
-#define YYLAST   880
-
-/* YYNTOKENS -- Number of terminals.  */
-#define YYNTOKENS  82
-/* YYNNTS -- Number of nonterminals.  */
-#define YYNNTS  32
-/* YYNRULES -- Number of rules.  */
-#define YYNRULES  187
-/* YYNRULES -- Number of states.  */
-#define YYNSTATES  463
-
-/* YYTRANSLATE(YYLEX) -- Bison symbol number corresponding to YYLEX.  */
-#define YYUNDEFTOK  2
-#define YYMAXUTOK   318
-
-#define YYTRANSLATE(YYX)                                               \
-  ((unsigned int) (YYX) <= YYMAXUTOK ? yytranslate[YYX] : YYUNDEFTOK)
-
-/* YYTRANSLATE[YYLEX] -- Bison symbol number corresponding to YYLEX.  */
-static const yytype_uint8 yytranslate[] =
-{
-       0,     2,     2,     2,     2,     2,     2,     2,     2,     2,
-       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
-       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
-       2,     2,     2,     2,     2,     2,    80,    12,     5,     2,
-      78,    79,    10,     8,    77,     9,     2,    11,     2,     2,
-       2,     2,     2,     2,     2,     2,     2,     2,    74,    76,
-       6,    75,     7,     2,     2,     2,     2,     2,     2,     2,
-       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
-       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
-       2,     2,     2,     2,     4,     2,     2,     2,     2,     2,
-       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
-       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
-       2,     2,     2,     2,     3,     2,    81,     2,     2,     2,
-       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
-       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
-       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
-       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
-       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
-       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
-       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
-       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
-       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
-       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
-       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
-       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
-       2,     2,     2,     2,     2,     2,     1,     2,    13,    14,
-      15,    16,    17,    18,    19,    20,    21,    22,    23,    24,
-      25,    26,    27,    28,    29,    30,    31,    32,    33,    34,
-      35,    36,    37,    38,    39,    40,    41,    42,    43,    44,
-      45,    46,    47,    48,    49,    50,    51,    52,    53,    54,
-      55,    56,    57,    58,    59,    60,    61,    62,    63,    64,
-      65,    66,    67,    68,    69,    70,    71,    72,    73
-};
-
-#if YYDEBUG
-/* YYPRHS[YYN] -- Index of the first RHS symbol of rule number YYN in
-   YYRHS.  */
-static const yytype_uint16 yyprhs[] =
-{
-       0,     0,     3,     4,     5,     9,    10,    15,    20,    25,
-      28,    30,    33,    36,    41,    46,    51,    56,    61,    66,
-      71,    76,    81,    86,    91,    96,   101,   106,   111,   116,
-     121,   126,   131,   136,   143,   148,   153,   160,   165,   170,
-     177,   184,   191,   196,   201,   208,   213,   220,   225,   232,
-     237,   242,   245,   252,   257,   262,   267,   274,   279,   284,
-     289,   294,   299,   304,   309,   314,   317,   320,   325,   329,
-     333,   339,   344,   349,   356,   361,   366,   373,   380,   387,
-     396,   401,   406,   410,   413,   418,   423,   430,   439,   444,
-     451,   456,   461,   468,   475,   484,   493,   502,   511,   516,
-     521,   526,   533,   538,   545,   550,   555,   558,   561,   565,
-     569,   573,   577,   580,   584,   588,   593,   598,   601,   607,
-     615,   620,   627,   634,   641,   648,   651,   656,   659,   661,
-     663,   665,   667,   669,   671,   673,   675,   680,   682,   684,
-     686,   691,   693,   698,   700,   704,   706,   709,   713,   718,
-     721,   724,   727,   731,   734,   736,   741,   745,   751,   753,
-     758,   763,   769,   777,   778,   780,   781,   784,   787,   789,
-     791,   793,   795,   797,   800,   803,   806,   810,   812,   816,
-     820,   824,   828,   832,   837,   842,   846,   850
-};
-
-/* YYRHS -- A `-1'-separated list of the rules' RHS.  */
-static const yytype_int8 yyrhs[] =
-{
-      83,     0,    -1,    -1,    -1,    83,    84,    85,    -1,    -1,
-      71,    74,    86,    85,    -1,    71,    75,   113,    76,    -1,
-      73,    75,   113,    76,    -1,    58,    76,    -1,    76,    -1,
-      87,    76,    -1,     1,    76,    -1,    13,    89,    77,    89,
-      -1,    13,   107,    77,    89,    -1,    13,   106,    77,    89,
-      -1,    14,    89,    77,    89,    -1,    14,   107,    77,    89,
-      -1,    14,   106,    77,    89,    -1,    22,   107,    77,    97,
-      -1,    22,   106,    77,    97,    -1,    22,   103,    77,    97,
-      -1,    22,    97,    77,    97,    -1,    22,    97,    77,   107,
-      -1,    22,    97,    77,   106,    -1,    13,    89,    77,   107,
-      -1,    13,    89,    77,   106,    -1,    14,    89,    77,   107,
-      -1,    14,    89,    77,   106,    -1,    13,    97,    77,   107,
-      -1,    13,    97,    77,   106,    -1,    13,    96,    77,    97,
-      -1,    13,    97,    77,    96,    -1,    13,    97,    77,   104,
-      77,    96,    -1,    13,    96,    77,    98,    -1,    67,   104,
-      77,   112,    -1,    13,    89,    77,   104,    77,    92,    -1,
-      13,    89,    77,    98,    -1,    13,    89,    77,    92,    -1,
-      18,    89,    77,   105,    77,    89,    -1,    18,   104,    77,
-     105,    77,    89,    -1,    18,    89,    77,   104,    77,    89,
-      -1,    18,    89,    77,    89,    -1,    18,   104,    77,    89,
-      -1,    16,    89,    77,   105,    77,    89,    -1,    16,    89,
-      77,    89,    -1,    17,    89,    77,   105,    77,    89,    -1,
-      17,    89,    77,    89,    -1,    17,   104,    77,   105,    77,
-      89,    -1,    17,   104,    77,    89,    -1,    15,    89,    77,
-      89,    -1,    15,    89,    -1,    68,    89,    77,   105,    77,
-      89,    -1,    13,   104,    77,    89,    -1,    13,   102,    77,
-      89,    -1,    20,    99,    77,    99,    -1,    20,    99,    77,
-     112,    77,    99,    -1,    13,    98,    77,    98,    -1,    13,
-      95,    77,    98,    -1,    13,    92,    77,    89,    -1,    13,
-      95,    77,    89,    -1,    13,    90,    77,    89,    -1,    13,
-      89,    77,    90,    -1,    13,    98,    77,    95,    -1,    13,
-      89,    77,    95,    -1,    21,    88,    -1,    21,   107,    -1,
-      21,    78,    90,    79,    -1,    21,    77,    88,    -1,    21,
-      77,   107,    -1,    21,    77,    78,    90,    79,    -1,    21,
-      98,    77,    88,    -1,    21,    98,    77,   107,    -1,    21,
-      98,    77,    78,    90,    79,    -1,    21,   112,    77,    88,
-      -1,    21,   112,    77,   107,    -1,    21,   112,    77,    78,
-      90,    79,    -1,    21,   112,    77,   112,    77,    88,    -1,
-      21,   112,    77,   112,    77,   107,    -1,    21,   112,    77,
-     112,    77,    78,    90,    79,    -1,    27,    89,    77,   105,
-      -1,    27,   104,    77,   105,    -1,    27,    89,   109,    -1,
-      27,   109,    -1,    23,    97,    77,    97,    -1,    25,    97,
-      77,    97,    -1,    25,    97,    77,    97,    77,    97,    -1,
-      26,    97,    77,    97,    77,    97,    77,    97,    -1,    24,
-      97,    77,    97,    -1,    24,    97,    77,    97,    77,    98,
-      -1,    19,    89,    77,    89,    -1,    19,    89,    77,   104,
-      -1,    19,    89,    77,    89,    77,    98,    -1,    19,    89,
-      77,   104,    77,    98,    -1,    63,   104,    77,    89,    77,
-     104,    77,    89,    -1,    63,   104,    77,    89,    77,   100,
-      77,    89,    -1,    63,    89,    77,    89,    77,   104,    77,
-      89,    -1,    63,    89,    77,    89,    77,   100,    77,    89,
-      -1,    64,   107,    77,    89,    -1,    64,    89,    77,   107,
-      -1,    59,   106,    77,    89,    -1,    59,   106,    77,   104,
-      77,    89,    -1,    60,    89,    77,   106,    -1,    60,    89,
-      77,   104,    77,   106,    -1,    62,   106,    77,    89,    -1,
-      62,    89,    77,   106,    -1,    61,   106,    -1,    29,   109,
-      -1,    29,    89,   109,    -1,    29,    97,   109,    -1,    29,
-      77,    89,    -1,    29,    77,    97,    -1,    29,   104,    -1,
-      32,   104,   109,    -1,    32,   102,   109,    -1,    56,   104,
-      77,   104,    -1,    57,   104,    77,   107,    -1,    30,   109,
-      -1,    33,   108,    77,    80,   101,    -1,    33,   108,    77,
-     112,    77,    80,   101,    -1,    34,   108,    77,   104,    -1,
-      34,   108,    77,   112,    77,   104,    -1,    35,   108,    11,
-     112,    77,   104,    -1,    35,   108,    11,   112,    77,   102,
-      -1,    35,   108,    11,   112,    77,   103,    -1,    36,   109,
-      -1,   112,    78,    41,    79,    -1,    71,   110,    -1,   105,
-      -1,    91,    -1,    93,    -1,    50,    -1,    47,    -1,    51,
-      -1,    55,    -1,    53,    -1,    52,    78,   112,    79,    -1,
-      94,    -1,    49,    -1,    45,    -1,    48,    78,   112,    79,
-      -1,    42,    -1,    47,    78,   112,    79,    -1,   112,    -1,
-     112,    77,   112,    -1,    37,    -1,     9,    37,    -1,    37,
-       9,    37,    -1,     9,    37,     9,    37,    -1,    80,   107,
-      -1,    80,    70,    -1,    80,    69,    -1,    80,     9,    69,
-      -1,    80,   112,    -1,    44,    -1,    46,    78,   112,    79,
-      -1,    78,   105,    79,    -1,    78,   105,     8,   105,    79,
-      -1,   108,    -1,   112,    78,   105,    79,    -1,   112,    78,
-     111,    79,    -1,    71,   110,    78,   111,    79,    -1,    71,
-       6,     7,   110,    78,    39,    79,    -1,    -1,    77,    -1,
-      -1,     8,   112,    -1,     9,   112,    -1,    39,    -1,    38,
-      -1,    40,    -1,    37,    -1,    73,    -1,     9,   112,    -1,
-       8,   112,    -1,    81,   112,    -1,    78,   113,    79,    -1,
-     112,    -1,   113,     8,   113,    -1,   113,     9,   113,    -1,
-     113,    10,   113,    -1,   113,    11,   113,    -1,   113,    12,
-     113,    -1,   113,     6,     6,   113,    -1,   113,     7,     7,
-     113,    -1,   113,     5,   113,    -1,   113,     4,   113,    -1,
-     113,     3,   113,    -1
-};
-
-/* YYRLINE[YYN] -- source line where rule number YYN was defined.  */
-static const yytype_uint16 yyrline[] =
-{
-       0,    66,    66,    68,    67,    75,    74,    83,    88,    94,
-      98,    99,   100,   106,   110,   114,   118,   122,   126,   133,
-     137,   141,   145,   149,   153,   160,   164,   168,   172,   179,
-     183,   190,   194,   198,   202,   206,   213,   217,   221,   231,
-     235,   239,   243,   247,   251,   255,   259,   263,   267,   271,
-     275,   279,   286,   293,   297,   304,   308,   316,   320,   324,
-     328,   332,   336,   340,   344,   353,   357,   361,   365,   369,
-     373,   377,   381,   385,   389,   393,   397,   401,   409,   417,
-     428,   432,   436,   440,   447,   451,   455,   459,   463,   467,
-     474,   478,   482,   486,   493,   497,   501,   505,   512,   516,
-     524,   528,   532,   536,   540,   544,   548,   555,   559,   563,
-     567,   571,   575,   582,   586,   593,   602,   613,   620,   625,
-     637,   642,   655,   663,   671,   682,   688,   694,   705,   713,
-     714,   717,   725,   733,   741,   749,   755,   763,   766,   774,
-     780,   788,   794,   802,   810,   831,   838,   845,   852,   861,
-     866,   874,   880,   887,   895,   896,   904,   911,   921,   922,
-     931,   939,   947,   956,   957,   960,   963,   967,   973,   974,
-     975,   978,   979,   983,   987,   991,   995,  1001,  1002,  1006,
-    1010,  1014,  1018,  1022,  1026,  1030,  1034,  1038
-};
-#endif
-
-#if YYDEBUG || YYERROR_VERBOSE || YYTOKEN_TABLE
-/* YYTNAME[SYMBOL-NUM] -- String name of the symbol SYMBOL-NUM.
-   First, the terminals, then, starting at YYNTOKENS, nonterminals.  */
-static const char *const yytname[] =
-{
-  "$end", "error", "$undefined", "'|'", "'^'", "'&'", "'<'", "'>'", "'+'",
-  "'-'", "'*'", "'/'", "'%'", "LMOVW", "LMOVB", "LABS", "LLOGW", "LSHW",
-  "LADDW", "LCMP", "LCROP", "LBRA", "LFMOV", "LFCONV", "LFCMP", "LFADD",
-  "LFMA", "LTRAP", "LXORW", "LNOP", "LEND", "LRETT", "LWORD", "LTEXT",
-  "LGLOBL", "LDATA", "LRETRN", "LCONST", "LSP", "LSB", "LFP", "LPC",
-  "LCREG", "LFLUSH", "LREG", "LFREG", "LR", "LCR", "LF", "LFPSCR", "LLR",
-  "LCTR", "LSPR", "LSPREG", "LSEG", "LMSR", "LPCDAT", "LFUNCDAT", "LSCHED",
-  "LXLD", "LXST", "LXOP", "LXMV", "LRLWM", "LMOVMW", "LMOVEM", "LMOVFL",
-  "LMTFSB", "LMA", "LFCONST", "LSCONST", "LNAME", "LLAB", "LVAR", "':'",
-  "'='", "';'", "','", "'('", "')'", "'$'", "'~'", "$accept", "prog", "@1",
-  "line", "@2", "inst", "rel", "rreg", "xlreg", "lr", "lcr", "ctr", "msr",
-  "psr", "fpscr", "freg", "creg", "cbit", "mask", "textsize", "ximm",
-  "fimm", "imm", "sreg", "regaddr", "addr", "name", "comma", "offset",
-  "pointer", "con", "expr", 0
-};
-#endif
-
-# ifdef YYPRINT
-/* YYTOKNUM[YYLEX-NUM] -- Internal token number corresponding to
-   token YYLEX-NUM.  */
-static const yytype_uint16 yytoknum[] =
-{
-       0,   256,   257,   124,    94,    38,    60,    62,    43,    45,
-      42,    47,    37,   258,   259,   260,   261,   262,   263,   264,
-     265,   266,   267,   268,   269,   270,   271,   272,   273,   274,
-     275,   276,   277,   278,   279,   280,   281,   282,   283,   284,
-     285,   286,   287,   288,   289,   290,   291,   292,   293,   294,
-     295,   296,   297,   298,   299,   300,   301,   302,   303,   304,
-     305,   306,   307,   308,   309,   310,   311,   312,   313,   314,
-     315,   316,   317,   318,    58,    61,    59,    44,    40,    41,
-      36,   126
-};
-# endif
-
-/* YYR1[YYN] -- Symbol number of symbol that rule YYN derives.  */
-static const yytype_uint8 yyr1[] =
-{
-       0,    82,    83,    84,    83,    86,    85,    85,    85,    85,
-      85,    85,    85,    87,    87,    87,    87,    87,    87,    87,
-      87,    87,    87,    87,    87,    87,    87,    87,    87,    87,
-      87,    87,    87,    87,    87,    87,    87,    87,    87,    87,
-      87,    87,    87,    87,    87,    87,    87,    87,    87,    87,
-      87,    87,    87,    87,    87,    87,    87,    87,    87,    87,
-      87,    87,    87,    87,    87,    87,    87,    87,    87,    87,
-      87,    87,    87,    87,    87,    87,    87,    87,    87,    87,
-      87,    87,    87,    87,    87,    87,    87,    87,    87,    87,
-      87,    87,    87,    87,    87,    87,    87,    87,    87,    87,
-      87,    87,    87,    87,    87,    87,    87,    87,    87,    87,
-      87,    87,    87,    87,    87,    87,    87,    87,    87,    87,
-      87,    87,    87,    87,    87,    87,    88,    88,    89,    90,
-      90,    91,    92,    93,    94,    95,    95,    95,    96,    97,
-      97,    98,    98,    99,   100,   101,   101,   101,   101,   102,
-     102,   103,   103,   104,   105,   105,   106,   106,   107,   107,
-     108,   108,   108,   109,   109,   110,   110,   110,   111,   111,
-     111,   112,   112,   112,   112,   112,   112,   113,   113,   113,
-     113,   113,   113,   113,   113,   113,   113,   113
-};
-
-/* YYR2[YYN] -- Number of symbols composing right hand side of rule YYN.  */
-static const yytype_uint8 yyr2[] =
-{
-       0,     2,     0,     0,     3,     0,     4,     4,     4,     2,
-       1,     2,     2,     4,     4,     4,     4,     4,     4,     4,
-       4,     4,     4,     4,     4,     4,     4,     4,     4,     4,
-       4,     4,     4,     6,     4,     4,     6,     4,     4,     6,
-       6,     6,     4,     4,     6,     4,     6,     4,     6,     4,
-       4,     2,     6,     4,     4,     4,     6,     4,     4,     4,
-       4,     4,     4,     4,     4,     2,     2,     4,     3,     3,
-       5,     4,     4,     6,     4,     4,     6,     6,     6,     8,
-       4,     4,     3,     2,     4,     4,     6,     8,     4,     6,
-       4,     4,     6,     6,     8,     8,     8,     8,     4,     4,
-       4,     6,     4,     6,     4,     4,     2,     2,     3,     3,
-       3,     3,     2,     3,     3,     4,     4,     2,     5,     7,
-       4,     6,     6,     6,     6,     2,     4,     2,     1,     1,
-       1,     1,     1,     1,     1,     1,     4,     1,     1,     1,
-       4,     1,     4,     1,     3,     1,     2,     3,     4,     2,
-       2,     2,     3,     2,     1,     4,     3,     5,     1,     4,
-       4,     5,     7,     0,     1,     0,     2,     2,     1,     1,
-       1,     1,     1,     2,     2,     2,     3,     1,     3,     3,
-       3,     3,     3,     4,     4,     3,     3,     3
-};
-
-/* YYDEFACT[STATE-NAME] -- Default rule to reduce with in state
-   STATE-NUM when YYTABLE doesn't specify something else to do.  Zero
-   means the default is an error.  */
-static const yytype_uint8 yydefact[] =
-{
-       2,     3,     1,     0,     0,     0,     0,     0,     0,     0,
-       0,     0,     0,     0,     0,     0,     0,     0,     0,   163,
-     163,   163,     0,     0,     0,     0,   163,     0,     0,     0,
-       0,     0,     0,     0,     0,     0,     0,     0,     0,     0,
-      10,     4,     0,    12,     0,     0,   171,   141,   154,   139,
-       0,   132,     0,   138,   131,   133,     0,   135,   134,   165,
-     172,     0,     0,     0,     0,     0,   129,     0,   130,   137,
-       0,     0,     0,     0,     0,     0,   128,     0,     0,   158,
-       0,     0,     0,     0,    51,     0,     0,     0,     0,     0,
-       0,     0,     0,     0,   143,     0,   165,     0,     0,    65,
-       0,    66,     0,     0,     0,     0,     0,     0,     0,     0,
-       0,     0,   164,   163,     0,    83,   164,   163,   163,   112,
-     107,   117,   163,   163,     0,     0,     0,     0,   125,     0,
-       0,     9,     0,     0,     0,   106,     0,     0,     0,     0,
-       0,     0,     0,     0,     5,     0,     0,    11,   174,   173,
-       0,     0,     0,     0,     0,     0,     0,     0,     0,   177,
-       0,   150,   149,   153,   175,     0,     0,     0,     0,     0,
-       0,     0,     0,     0,     0,     0,     0,     0,     0,     0,
-       0,     0,   153,     0,     0,     0,     0,     0,     0,   127,
-       0,    68,    69,     0,     0,     0,     0,     0,     0,   151,
-       0,     0,     0,     0,     0,     0,     0,     0,   164,    82,
-       0,   110,   111,   108,   109,   114,   113,     0,     0,     0,
-       0,     0,     0,     0,     0,     0,     0,     0,     0,     0,
-       0,     0,     0,     0,     0,     0,     0,     0,     0,     0,
-     165,   166,   167,     0,     0,   156,     0,     0,     0,     0,
-       0,     0,     0,     0,     0,     0,   176,    13,    62,    38,
-      64,    37,     0,    26,    25,    61,    59,    60,    58,    31,
-      34,    32,     0,    30,    29,    63,    57,    54,    53,    15,
-      14,   169,   168,   170,     0,     0,    16,    28,    27,    18,
-      17,    50,    45,   128,    47,   128,    49,   128,    42,     0,
-     128,    43,   128,    90,    91,    55,   143,     0,    67,     0,
-      71,    72,     0,    74,    75,     0,     0,   152,    22,    24,
-      23,    21,    20,    19,    84,    88,    85,     0,    80,    81,
-       0,     0,   120,     0,     0,   115,   116,   100,     0,     0,
-     102,   105,   104,     0,     0,    99,    98,    35,     0,     6,
-       7,     8,   155,   142,   140,   136,     0,     0,     0,   187,
-     186,   185,     0,     0,   178,   179,   180,   181,   182,     0,
-       0,   159,   160,     0,     0,     0,     0,     0,     0,     0,
-       0,     0,    70,     0,     0,     0,   126,     0,     0,     0,
-       0,   145,   118,     0,     0,     0,     0,     0,     0,     0,
-       0,     0,   161,   157,   183,   184,   132,    36,    33,    44,
-      46,    48,    41,    39,    40,    92,    93,    56,    73,    76,
-       0,    77,    78,    89,    86,     0,   146,     0,     0,   121,
-       0,   123,   124,   122,   101,   103,     0,     0,     0,     0,
-       0,    52,     0,     0,     0,     0,   147,   119,     0,     0,
-       0,     0,     0,     0,   162,    79,    87,   148,    97,    96,
-     144,    95,    94
-};
-
-/* YYDEFGOTO[NTERM-NUM].  */
-static const yytype_int16 yydefgoto[] =
-{
-      -1,     1,     3,    41,   233,    42,    99,    64,    65,    66,
-      67,    68,    69,    70,    71,    72,    73,    93,   436,   392,
-      74,   105,    75,    76,    77,   162,    79,   115,   157,   285,
-     159,   160
-};
-
-/* YYPACT[STATE-NUM] -- Index in YYTABLE of the portion describing
-   STATE-NUM.  */
-#define YYPACT_NINF -180
-static const yytype_int16 yypact[] =
-{
-    -180,    12,  -180,   484,   -53,   517,   619,    28,    28,   -24,
-     -24,    28,   799,   577,   596,   -29,   -29,   -29,   -29,    19,
-     -11,   -51,   -38,   701,   701,   701,   -51,   -19,   -19,    -8,
-      -7,    28,    -7,   -14,   -24,   643,   -19,    28,   -36,     6,
-    -180,  -180,    26,  -180,   799,   799,  -180,  -180,  -180,  -180,
-       7,    27,    51,  -180,  -180,  -180,    61,  -180,  -180,   188,
-    -180,   662,   674,   799,    79,    93,  -180,    99,  -180,  -180,
-     112,   116,   126,   136,   138,   157,  -180,   168,   176,  -180,
-      80,   179,   182,   184,   186,   194,   799,   196,   198,   200,
-     201,   202,   799,   203,  -180,    27,   188,   714,   676,  -180,
-     206,  -180,    49,     8,   215,   216,   217,   219,   220,   221,
-     223,   224,  -180,   225,   226,  -180,   181,   -51,   -51,  -180,
-    -180,  -180,   -51,   -51,   227,   158,   231,   296,  -180,   232,
-     233,  -180,    28,   234,   236,  -180,   237,   238,   242,   245,
-     246,   248,   249,   250,  -180,   799,   799,  -180,  -180,  -180,
-     799,   799,   799,   799,   321,   799,   799,   251,     3,  -180,
-     377,  -180,  -180,    80,  -180,   565,    28,    28,   172,   162,
-     623,    31,    28,    28,    28,    28,   230,   619,    28,    28,
-      28,    28,  -180,    28,    28,   -24,    28,   -24,   799,   251,
-     676,  -180,  -180,   254,   257,   723,   753,   111,   268,  -180,
-      67,   -29,   -29,   -29,   -29,   -29,   -29,   -29,    28,  -180,
-      28,  -180,  -180,  -180,  -180,  -180,  -180,   733,    96,   760,
-     799,   -19,   701,   -24,    40,    -7,    28,    28,    28,   701,
-      28,   799,    28,   484,   463,   524,   265,   266,   267,   270,
-     135,  -180,  -180,    96,    28,  -180,   799,   799,   799,   341,
-     347,   799,   799,   799,   799,   799,  -180,  -180,  -180,  -180,
-    -180,  -180,   278,  -180,  -180,  -180,  -180,  -180,  -180,  -180,
-    -180,  -180,   279,  -180,  -180,  -180,  -180,  -180,  -180,  -180,
-    -180,  -180,  -180,  -180,   281,   282,  -180,  -180,  -180,  -180,
-    -180,  -180,  -180,   280,  -180,   285,  -180,   286,  -180,   288,
-     289,  -180,   297,   299,   301,  -180,   319,   294,  -180,   676,
-    -180,  -180,   676,  -180,  -180,   171,   318,  -180,  -180,  -180,
-    -180,  -180,  -180,  -180,  -180,   324,   325,   327,  -180,  -180,
-       9,   328,  -180,   329,   330,  -180,  -180,  -180,   331,   335,
-    -180,  -180,  -180,   336,   337,  -180,  -180,  -180,   338,  -180,
-    -180,  -180,  -180,  -180,  -180,  -180,   320,   339,   340,   571,
-     430,    82,   799,   799,   153,   153,  -180,  -180,  -180,   374,
-     373,  -180,  -180,    28,    28,    28,    28,    28,    28,    20,
-      20,   799,  -180,   344,   345,   772,  -180,    20,   -29,   -29,
-     390,   419,  -180,   349,   -19,   350,    28,    -7,   760,   760,
-      28,   392,  -180,  -180,   277,   277,  -180,  -180,  -180,  -180,
-    -180,  -180,  -180,  -180,  -180,  -180,  -180,  -180,  -180,  -180,
-     676,  -180,  -180,  -180,  -180,   355,   436,   411,     9,  -180,
-     322,  -180,  -180,  -180,  -180,  -180,   375,   376,   378,   380,
-     381,  -180,   372,   382,   -29,   417,  -180,  -180,   790,    28,
-      28,   799,    28,    28,  -180,  -180,  -180,  -180,  -180,  -180,
-    -180,  -180,  -180
-};
-
-/* YYPGOTO[NTERM-NUM].  */
-static const yytype_int16 yypgoto[] =
-{
-    -180,  -180,  -180,   229,  -180,  -180,   -73,    -6,   -62,  -180,
-    -158,  -180,  -180,  -150,  -162,    37,    30,  -179,    60,    32,
-     -16,    68,    97,   167,    81,    95,   159,    24,   -86,   239,
-      35,    87
-};
-
-/* YYTABLE[YYPACT[STATE-NUM]].  What to do in state STATE-NUM.  If
-   positive, shift that token.  If negative, reduce the rule which
-   number is the opposite.  If zero, do what YYDEFACT says.
-   If YYTABLE_NINF, syntax error.  */
-#define YYTABLE_NINF -1
-static const yytype_uint16 yytable[] =
-{
-      81,    84,    85,    87,    89,    91,   122,   259,   271,   305,
-     189,   244,     2,   113,   117,   260,    49,   198,   390,    52,
-      48,   275,    50,    43,   191,   134,   112,   136,   138,   140,
-      48,   143,    50,    48,    49,    50,   194,    52,   144,   145,
-      80,    80,    62,   100,   120,   121,   391,    94,   102,    80,
-     128,   104,   108,   109,   110,   111,    86,   118,   125,   125,
-     125,    86,    47,    48,   132,    50,   116,    95,   131,    86,
-      80,   132,    48,    47,    50,    44,    45,   199,    95,   148,
-     149,   146,   245,    56,    57,   150,    58,    82,   249,   250,
-     251,   252,   253,   254,   255,   106,   112,   163,   164,    86,
-      78,    83,   147,   258,    46,   151,    88,    90,   101,   107,
-     211,   133,    49,   135,   137,    52,   114,   119,   132,   123,
-      86,   182,   310,   313,   129,   130,   196,   197,   307,   152,
-     141,   139,   193,   142,   281,   282,   283,   209,    59,   153,
-      60,   213,   214,   155,   156,    61,   215,   216,    63,   281,
-     282,   283,   316,   212,   356,    48,   165,    50,   176,   257,
-     265,   266,   267,   253,   254,   255,   277,   278,   279,   280,
-     166,   286,   289,   290,   291,   292,   167,   294,   296,   298,
-     301,   303,   124,   126,   127,   236,   237,   238,   239,   168,
-     241,   242,   192,   169,   154,   261,   155,   156,   268,   270,
-      80,   276,   417,   170,    47,    80,   269,    49,   408,    95,
-      52,   407,    80,   171,    47,   172,    48,   337,    50,    95,
-     342,   343,   344,   306,   346,    48,    49,    50,   158,    52,
-     193,   315,   234,   235,   173,    80,   218,   318,   321,   322,
-     323,   324,   325,   326,   327,   174,   263,   383,   385,   197,
-     384,   273,   331,   175,   333,   334,   177,    80,   287,   178,
-     264,   179,   262,   180,    80,   274,   347,   272,   281,   282,
-     283,   181,   288,   183,    48,   184,    50,   185,   186,   187,
-     188,   319,   299,   195,   304,   251,   252,   253,   254,   255,
-     311,   314,   200,   201,   202,   320,   203,   204,   205,   158,
-     206,   207,   208,   210,   217,   340,   341,   220,   219,   221,
-     222,   223,   421,   224,   225,   226,   332,   336,   335,   227,
-     338,   339,   228,   229,   345,   230,   231,   232,   240,   243,
-      44,   448,   197,   359,   360,   361,   308,   317,   364,   365,
-     366,   367,   368,   284,   352,   353,   354,   362,   293,   355,
-     295,   297,   300,   302,   363,   369,   370,   373,   443,    46,
-     371,   372,   374,   375,   284,   376,   377,   409,   410,   411,
-     412,   413,   414,   382,   378,   328,   379,   329,   380,   431,
-     246,   247,   248,   249,   250,   251,   252,   253,   254,   255,
-     434,   199,   161,    59,   441,    60,   381,   386,   401,   348,
-      92,   387,   388,    63,   389,   393,   394,   395,   396,   415,
-     416,   358,   397,   398,   399,   400,    94,   423,   402,   403,
-     193,   406,    53,   418,   419,   424,   425,   426,   427,   428,
-     430,   442,   444,   438,   438,   248,   249,   250,   251,   252,
-     253,   254,   255,   458,   459,   445,   461,   462,   446,   404,
-     405,   454,   449,   450,   457,   451,   256,   452,   453,   439,
-     447,   455,   349,   432,     0,   163,   246,   247,   248,   249,
-     250,   251,   252,   253,   254,   255,     0,     0,   435,     0,
-     422,   456,   357,   149,     0,     4,   460,     0,     0,     0,
-       0,   429,   433,     0,     0,   437,   440,     5,     6,     7,
-       8,     9,    10,    11,    12,    13,    14,    15,    16,    17,
-      18,    19,     0,    20,    21,     0,    22,    23,    24,    25,
-      26,     0,     0,     0,     0,    44,    45,   246,   247,   248,
-     249,   250,   251,   252,   253,   254,   255,     0,     0,   350,
-      27,    28,    29,    30,    31,    32,    33,    34,    35,     0,
-       0,    36,    37,     0,    46,    38,     0,    39,     0,    47,
-      40,    48,    49,    50,    51,    52,    53,    54,    55,    56,
-      57,     0,    58,    44,    45,   247,   248,   249,   250,   251,
-     252,   253,   254,   255,     0,    44,    45,     0,    59,     0,
-      60,     0,     0,     0,     0,    61,     0,    62,    63,     0,
-     351,     0,    46,     0,    44,    45,     0,    47,     0,    48,
-       0,    50,    51,     0,    46,    54,    55,    56,    57,    47,
-      58,     0,     0,     0,    95,     0,     0,    44,    45,     0,
-       0,    44,    45,    46,     0,     0,    59,     0,    60,     0,
-       0,    49,     0,    61,    52,    86,    63,     0,    96,     0,
-      60,    44,    45,     0,    97,    98,    46,     0,    63,     0,
-      46,     0,     0,    48,     0,    50,     0,    59,     0,    60,
-      44,    45,    53,     0,    61,     0,   103,    63,     0,     0,
-      46,     0,    44,    45,    44,    45,     0,    48,     0,    50,
-      59,     0,    60,     0,    59,     0,    60,    61,     0,    46,
-      63,    61,     0,    86,    63,     0,    48,     0,    50,    44,
-      45,    46,     0,    46,    59,     0,    60,     0,     0,     0,
-       0,    92,    44,    45,    63,     0,    54,    55,     0,     0,
-       0,    44,    45,     0,     0,    60,     0,     0,    46,     0,
-      92,    44,    45,    63,   161,    59,     0,    60,     0,    60,
-       0,    46,    92,     0,    92,    63,     0,    63,     0,     0,
-      46,    44,    45,     0,     0,     0,     0,     0,    44,    45,
-      46,     0,    59,     0,    60,     0,     0,     0,     0,    92,
-      44,    45,    63,     0,     0,    96,     0,    60,     0,     0,
-      46,     0,   190,     0,    96,    63,    60,    46,    44,    45,
-       0,   309,     0,     0,    63,     0,    60,    44,    45,    46,
-       0,    92,     0,   330,    63,     0,     0,     0,     0,     0,
-       0,     0,     0,     0,    96,     0,    60,    46,     0,     0,
-       0,   312,     0,    60,    63,     0,    46,     0,    92,     0,
-      86,    63,     0,    96,     0,    60,     0,     0,     0,     0,
-     420,     0,     0,    63,     0,     0,     0,     0,     0,   317,
-       0,     0,     0,    60,     0,     0,     0,     0,    92,     0,
-       0,    63,    60,     0,     0,     0,     0,    92,     0,     0,
-      63
-};
-
-static const yytype_int16 yycheck[] =
-{
-       6,     7,     8,     9,    10,    11,    22,   165,   170,   188,
-      96,     8,     0,    19,    20,   165,    45,     9,     9,    48,
-      44,   171,    46,    76,    97,    31,    77,    33,    34,    35,
-      44,    37,    46,    44,    45,    46,    98,    48,    74,    75,
-       5,     6,    80,    13,    20,    21,    37,    12,    13,    14,
-      26,    14,    15,    16,    17,    18,    80,    20,    23,    24,
-      25,    80,    42,    44,    78,    46,    77,    47,    76,    80,
-      35,    78,    44,    42,    46,     8,     9,    69,    47,    44,
-      45,    75,    79,    52,    53,    78,    55,     6,     6,     7,
-       8,     9,    10,    11,    12,    14,    77,    62,    63,    80,
-       5,     6,    76,   165,    37,    78,     9,    10,    13,    14,
-     116,    30,    45,    32,    33,    48,    19,    20,    78,    22,
-      80,    86,   195,   196,    27,    28,    77,    78,   190,    78,
-      35,    34,    97,    36,    38,    39,    40,   113,    71,    78,
-      73,   117,   118,     8,     9,    78,   122,   123,    81,    38,
-      39,    40,    41,   116,   240,    44,    77,    46,    78,   165,
-     166,   167,   168,    10,    11,    12,   172,   173,   174,   175,
-      77,   177,   178,   179,   180,   181,    77,   183,   184,   185,
-     186,   187,    23,    24,    25,   150,   151,   152,   153,    77,
-     155,   156,    97,    77,     6,   165,     8,     9,   168,   169,
-     165,   171,   381,    77,    42,   170,   169,    45,   370,    47,
-      48,   369,   177,    77,    42,    77,    44,   223,    46,    47,
-     226,   227,   228,   188,   230,    44,    45,    46,    61,    48,
-     195,   196,   145,   146,    77,   200,    78,   200,   201,   202,
-     203,   204,   205,   206,   207,    77,   165,   309,    77,    78,
-     312,   170,   217,    77,   219,   220,    77,   222,   177,    77,
-     165,    77,   165,    77,   229,   170,   231,   170,    38,    39,
-      40,    77,   177,    77,    44,    77,    46,    77,    77,    77,
-      77,   200,   185,    77,   187,     8,     9,    10,    11,    12,
-     195,   196,    77,    77,    77,   200,    77,    77,    77,   132,
-      77,    77,    77,    77,    77,   224,   225,    11,    77,    77,
-      77,    77,   385,    77,    77,    77,   219,   222,   221,    77,
-     223,   224,    77,    77,   229,    77,    77,    77,     7,    78,
-       8,     9,    78,   246,   247,   248,    79,    69,   251,   252,
-     253,   254,   255,   176,    79,    79,    79,     6,   181,    79,
-     183,   184,   185,   186,     7,    77,    77,    77,   420,    37,
-      79,    79,    77,    77,   197,    77,    77,   373,   374,   375,
-     376,   377,   378,    79,    77,   208,    77,   210,    77,   395,
-       3,     4,     5,     6,     7,     8,     9,    10,    11,    12,
-     396,    69,    70,    71,   400,    73,    77,    79,    78,   232,
-      78,    77,    77,    81,    77,    77,    77,    77,    77,   379,
-     380,   244,    77,    77,    77,    77,   381,   387,    79,    79,
-     385,    47,    49,    79,    79,   388,   389,    37,     9,    80,
-      80,    39,    77,   398,   399,     5,     6,     7,     8,     9,
-      10,    11,    12,   449,   450,     9,   452,   453,    37,   362,
-     363,    79,    77,    77,    37,    77,    79,    77,    77,   399,
-     428,    79,   233,   395,    -1,   430,     3,     4,     5,     6,
-       7,     8,     9,    10,    11,    12,    -1,    -1,   397,    -1,
-     385,   444,   243,   448,    -1,     1,   451,    -1,    -1,    -1,
-      -1,   394,   395,    -1,    -1,   398,   399,    13,    14,    15,
-      16,    17,    18,    19,    20,    21,    22,    23,    24,    25,
-      26,    27,    -1,    29,    30,    -1,    32,    33,    34,    35,
-      36,    -1,    -1,    -1,    -1,     8,     9,     3,     4,     5,
-       6,     7,     8,     9,    10,    11,    12,    -1,    -1,    76,
-      56,    57,    58,    59,    60,    61,    62,    63,    64,    -1,
-      -1,    67,    68,    -1,    37,    71,    -1,    73,    -1,    42,
-      76,    44,    45,    46,    47,    48,    49,    50,    51,    52,
-      53,    -1,    55,     8,     9,     4,     5,     6,     7,     8,
-       9,    10,    11,    12,    -1,     8,     9,    -1,    71,    -1,
-      73,    -1,    -1,    -1,    -1,    78,    -1,    80,    81,    -1,
-      76,    -1,    37,    -1,     8,     9,    -1,    42,    -1,    44,
-      -1,    46,    47,    -1,    37,    50,    51,    52,    53,    42,
-      55,    -1,    -1,    -1,    47,    -1,    -1,     8,     9,    -1,
-      -1,     8,     9,    37,    -1,    -1,    71,    -1,    73,    -1,
-      -1,    45,    -1,    78,    48,    80,    81,    -1,    71,    -1,
-      73,     8,     9,    -1,    77,    78,    37,    -1,    81,    -1,
-      37,    -1,    -1,    44,    -1,    46,    -1,    71,    -1,    73,
-       8,     9,    49,    -1,    78,    -1,    80,    81,    -1,    -1,
-      37,    -1,     8,     9,     8,     9,    -1,    44,    -1,    46,
-      71,    -1,    73,    -1,    71,    -1,    73,    78,    -1,    37,
-      81,    78,    -1,    80,    81,    -1,    44,    -1,    46,     8,
-       9,    37,    -1,    37,    71,    -1,    73,    -1,    -1,    -1,
-      -1,    78,     8,     9,    81,    -1,    50,    51,    -1,    -1,
-      -1,     8,     9,    -1,    -1,    73,    -1,    -1,    37,    -1,
-      78,     8,     9,    81,    70,    71,    -1,    73,    -1,    73,
-      -1,    37,    78,    -1,    78,    81,    -1,    81,    -1,    -1,
-      37,     8,     9,    -1,    -1,    -1,    -1,    -1,     8,     9,
-      37,    -1,    71,    -1,    73,    -1,    -1,    -1,    -1,    78,
-       8,     9,    81,    -1,    -1,    71,    -1,    73,    -1,    -1,
-      37,    -1,    78,    -1,    71,    81,    73,    37,     8,     9,
-      -1,    78,    -1,    -1,    81,    -1,    73,     8,     9,    37,
-      -1,    78,    -1,    80,    81,    -1,    -1,    -1,    -1,    -1,
-      -1,    -1,    -1,    -1,    71,    -1,    73,    37,    -1,    -1,
-      -1,    78,    -1,    73,    81,    -1,    37,    -1,    78,    -1,
-      80,    81,    -1,    71,    -1,    73,    -1,    -1,    -1,    -1,
-      78,    -1,    -1,    81,    -1,    -1,    -1,    -1,    -1,    69,
-      -1,    -1,    -1,    73,    -1,    -1,    -1,    -1,    78,    -1,
-      -1,    81,    73,    -1,    -1,    -1,    -1,    78,    -1,    -1,
-      81
-};
-
-/* YYSTOS[STATE-NUM] -- The (internal number of the) accessing
-   symbol of state STATE-NUM.  */
-static const yytype_uint8 yystos[] =
-{
-       0,    83,     0,    84,     1,    13,    14,    15,    16,    17,
-      18,    19,    20,    21,    22,    23,    24,    25,    26,    27,
-      29,    30,    32,    33,    34,    35,    36,    56,    57,    58,
-      59,    60,    61,    62,    63,    64,    67,    68,    71,    73,
-      76,    85,    87,    76,     8,     9,    37,    42,    44,    45,
-      46,    47,    48,    49,    50,    51,    52,    53,    55,    71,
-      73,    78,    80,    81,    89,    90,    91,    92,    93,    94,
-      95,    96,    97,    98,   102,   104,   105,   106,   107,   108,
-     112,    89,   106,   107,    89,    89,    80,    89,   104,    89,
-     104,    89,    78,    99,   112,    47,    71,    77,    78,    88,
-      98,   107,   112,    80,    97,   103,   106,   107,    97,    97,
-      97,    97,    77,    89,   104,   109,    77,    89,    97,   104,
-     109,   109,   102,   104,   108,   112,   108,   108,   109,   104,
-     104,    76,    78,   106,    89,   106,    89,   106,    89,   104,
-      89,   107,   104,    89,    74,    75,    75,    76,   112,   112,
-      78,    78,    78,    78,     6,     8,     9,   110,   105,   112,
-     113,    70,   107,   112,   112,    77,    77,    77,    77,    77,
-      77,    77,    77,    77,    77,    77,    78,    77,    77,    77,
-      77,    77,   112,    77,    77,    77,    77,    77,    77,   110,
-      78,    88,   107,   112,    90,    77,    77,    78,     9,    69,
-      77,    77,    77,    77,    77,    77,    77,    77,    77,   109,
-      77,    89,    97,   109,   109,   109,   109,    77,    78,    77,
-      11,    77,    77,    77,    77,    77,    77,    77,    77,    77,
-      77,    77,    77,    86,   113,   113,   112,   112,   112,   112,
-       7,   112,   112,    78,     8,    79,     3,     4,     5,     6,
-       7,     8,     9,    10,    11,    12,    79,    89,    90,    92,
-      95,    98,   104,   106,   107,    89,    89,    89,    98,    97,
-      98,    96,   104,   106,   107,    95,    98,    89,    89,    89,
-      89,    38,    39,    40,   105,   111,    89,   106,   107,    89,
-      89,    89,    89,   105,    89,   105,    89,   105,    89,   104,
-     105,    89,   105,    89,   104,    99,   112,    90,    79,    78,
-      88,   107,    78,    88,   107,   112,    41,    69,    97,   106,
-     107,    97,    97,    97,    97,    97,    97,    97,   105,   105,
-      80,   112,   104,   112,   112,   104,   107,    89,   104,   104,
-     106,   106,    89,    89,    89,   107,    89,   112,   105,    85,
-      76,    76,    79,    79,    79,    79,   110,   111,   105,   113,
-     113,   113,     6,     7,   113,   113,   113,   113,   113,    77,
-      77,    79,    79,    77,    77,    77,    77,    77,    77,    77,
-      77,    77,    79,    90,    90,    77,    79,    77,    77,    77,
-       9,    37,   101,    77,    77,    77,    77,    77,    77,    77,
-      77,    78,    79,    79,   113,   113,    47,    92,    96,    89,
-      89,    89,    89,    89,    89,    98,    98,    99,    79,    79,
-      78,    88,   107,    98,    97,    97,    37,     9,    80,   104,
-      80,   102,   103,   104,    89,   106,   100,   104,   112,   100,
-     104,    89,    39,    90,    77,     9,    37,   101,     9,    77,
-      77,    77,    77,    77,    79,    79,    97,    37,    89,    89,
-     112,    89,    89
-};
-
-#define yyerrok                (yyerrstatus = 0)
-#define yyclearin      (yychar = YYEMPTY)
-#define YYEMPTY                (-2)
-#define YYEOF          0
-
-#define YYACCEPT       goto yyacceptlab
-#define YYABORT                goto yyabortlab
-#define YYERROR                goto yyerrorlab
-
-
-/* Like YYERROR except do call yyerror.  This remains here temporarily
-   to ease the transition to the new meaning of YYERROR, for GCC.
-   Once GCC version 2 has supplanted version 1, this can go.  */
-
-#define YYFAIL         goto yyerrlab
-
-#define YYRECOVERING()  (!!yyerrstatus)
-
-#define YYBACKUP(Token, Value)                                 \
-do                                                             \
-  if (yychar == YYEMPTY && yylen == 1)                         \
-    {                                                          \
-      yychar = (Token);                                                \
-      yylval = (Value);                                                \
-      yytoken = YYTRANSLATE (yychar);                          \
-      YYPOPSTACK (1);                                          \
-      goto yybackup;                                           \
-    }                                                          \
-  else                                                         \
-    {                                                          \
-      yyerror (YY_("syntax error: cannot back up")); \
-      YYERROR;                                                 \
-    }                                                          \
-while (YYID (0))
-
-
-#define YYTERROR       1
-#define YYERRCODE      256
-
-
-/* YYLLOC_DEFAULT -- Set CURRENT to span from RHS[1] to RHS[N].
-   If N is 0, then set CURRENT to the empty location which ends
-   the previous symbol: RHS[0] (always defined).  */
-
-#define YYRHSLOC(Rhs, K) ((Rhs)[K])
-#ifndef YYLLOC_DEFAULT
-# define YYLLOC_DEFAULT(Current, Rhs, N)                               \
-    do                                                                 \
-      if (YYID (N))                                                    \
-       {                                                               \
-         (Current).first_line   = YYRHSLOC (Rhs, 1).first_line;        \
-         (Current).first_column = YYRHSLOC (Rhs, 1).first_column;      \
-         (Current).last_line    = YYRHSLOC (Rhs, N).last_line;         \
-         (Current).last_column  = YYRHSLOC (Rhs, N).last_column;       \
-       }                                                               \
-      else                                                             \
-       {                                                               \
-         (Current).first_line   = (Current).last_line   =              \
-           YYRHSLOC (Rhs, 0).last_line;                                \
-         (Current).first_column = (Current).last_column =              \
-           YYRHSLOC (Rhs, 0).last_column;                              \
-       }                                                               \
-    while (YYID (0))
-#endif
-
-
-/* YY_LOCATION_PRINT -- Print the location on the stream.
-   This macro was not mandated originally: define only if we know
-   we won't break user code: when these are the locations we know.  */
-
-#ifndef YY_LOCATION_PRINT
-# if defined YYLTYPE_IS_TRIVIAL && YYLTYPE_IS_TRIVIAL
-#  define YY_LOCATION_PRINT(File, Loc)                 \
-     fprintf (File, "%d.%d-%d.%d",                     \
-             (Loc).first_line, (Loc).first_column,     \
-             (Loc).last_line,  (Loc).last_column)
-# else
-#  define YY_LOCATION_PRINT(File, Loc) ((void) 0)
-# endif
-#endif
-
-
-/* YYLEX -- calling `yylex' with the right arguments.  */
-
-#ifdef YYLEX_PARAM
-# define YYLEX yylex (YYLEX_PARAM)
-#else
-# define YYLEX yylex ()
-#endif
-
-/* Enable debugging if requested.  */
-#if YYDEBUG
-
-# ifndef YYFPRINTF
-#  include <stdio.h> /* INFRINGES ON USER NAME SPACE */
-#  define YYFPRINTF fprintf
-# endif
-
-# define YYDPRINTF(Args)                       \
-do {                                           \
-  if (yydebug)                                 \
-    YYFPRINTF Args;                            \
-} while (YYID (0))
-
-# define YY_SYMBOL_PRINT(Title, Type, Value, Location)                   \
-do {                                                                     \
-  if (yydebug)                                                           \
-    {                                                                    \
-      YYFPRINTF (stderr, "%s ", Title);                                          \
-      yy_symbol_print (stderr,                                           \
-                 Type, Value); \
-      YYFPRINTF (stderr, "\n");                                                  \
-    }                                                                    \
-} while (YYID (0))
-
-
-/*--------------------------------.
-| Print this symbol on YYOUTPUT.  |
-`--------------------------------*/
-
-/*ARGSUSED*/
-#if (defined __STDC__ || defined __C99__FUNC__ \
-     || defined __cplusplus || defined _MSC_VER)
-static void
-yy_symbol_value_print (FILE *yyoutput, int yytype, YYSTYPE const * const yyvaluep)
-#else
-static void
-yy_symbol_value_print (yyoutput, yytype, yyvaluep)
-    FILE *yyoutput;
-    int yytype;
-    YYSTYPE const * const yyvaluep;
-#endif
-{
-  if (!yyvaluep)
-    return;
-# ifdef YYPRINT
-  if (yytype < YYNTOKENS)
-    YYPRINT (yyoutput, yytoknum[yytype], *yyvaluep);
-# else
-  YYUSE (yyoutput);
-# endif
-  switch (yytype)
-    {
-      default:
-       break;
-    }
-}
-
-
-/*--------------------------------.
-| Print this symbol on YYOUTPUT.  |
-`--------------------------------*/
-
-#if (defined __STDC__ || defined __C99__FUNC__ \
-     || defined __cplusplus || defined _MSC_VER)
-static void
-yy_symbol_print (FILE *yyoutput, int yytype, YYSTYPE const * const yyvaluep)
-#else
-static void
-yy_symbol_print (yyoutput, yytype, yyvaluep)
-    FILE *yyoutput;
-    int yytype;
-    YYSTYPE const * const yyvaluep;
-#endif
-{
-  if (yytype < YYNTOKENS)
-    YYFPRINTF (yyoutput, "token %s (", yytname[yytype]);
-  else
-    YYFPRINTF (yyoutput, "nterm %s (", yytname[yytype]);
-
-  yy_symbol_value_print (yyoutput, yytype, yyvaluep);
-  YYFPRINTF (yyoutput, ")");
-}
-
-/*------------------------------------------------------------------.
-| yy_stack_print -- Print the state stack from its BOTTOM up to its |
-| TOP (included).                                                   |
-`------------------------------------------------------------------*/
-
-#if (defined __STDC__ || defined __C99__FUNC__ \
-     || defined __cplusplus || defined _MSC_VER)
-static void
-yy_stack_print (yytype_int16 *bottom, yytype_int16 *top)
-#else
-static void
-yy_stack_print (bottom, top)
-    yytype_int16 *bottom;
-    yytype_int16 *top;
-#endif
-{
-  YYFPRINTF (stderr, "Stack now");
-  for (; bottom <= top; ++bottom)
-    YYFPRINTF (stderr, " %d", *bottom);
-  YYFPRINTF (stderr, "\n");
-}
-
-# define YY_STACK_PRINT(Bottom, Top)                           \
-do {                                                           \
-  if (yydebug)                                                 \
-    yy_stack_print ((Bottom), (Top));                          \
-} while (YYID (0))
-
-
-/*------------------------------------------------.
-| Report that the YYRULE is going to be reduced.  |
-`------------------------------------------------*/
-
-#if (defined __STDC__ || defined __C99__FUNC__ \
-     || defined __cplusplus || defined _MSC_VER)
-static void
-yy_reduce_print (YYSTYPE *yyvsp, int yyrule)
-#else
-static void
-yy_reduce_print (yyvsp, yyrule)
-    YYSTYPE *yyvsp;
-    int yyrule;
-#endif
-{
-  int yynrhs = yyr2[yyrule];
-  int yyi;
-  unsigned long int yylno = yyrline[yyrule];
-  YYFPRINTF (stderr, "Reducing stack by rule %d (line %lu):\n",
-            yyrule - 1, yylno);
-  /* The symbols being reduced.  */
-  for (yyi = 0; yyi < yynrhs; yyi++)
-    {
-      fprintf (stderr, "   $%d = ", yyi + 1);
-      yy_symbol_print (stderr, yyrhs[yyprhs[yyrule] + yyi],
-                      &(yyvsp[(yyi + 1) - (yynrhs)])
-                                      );
-      fprintf (stderr, "\n");
-    }
-}
-
-# define YY_REDUCE_PRINT(Rule)         \
-do {                                   \
-  if (yydebug)                         \
-    yy_reduce_print (yyvsp, Rule); \
-} while (YYID (0))
-
-/* Nonzero means print parse trace.  It is left uninitialized so that
-   multiple parsers can coexist.  */
-int yydebug;
-#else /* !YYDEBUG */
-# define YYDPRINTF(Args)
-# define YY_SYMBOL_PRINT(Title, Type, Value, Location)
-# define YY_STACK_PRINT(Bottom, Top)
-# define YY_REDUCE_PRINT(Rule)
-#endif /* !YYDEBUG */
-
-
-/* YYINITDEPTH -- initial size of the parser's stacks.  */
-#ifndef        YYINITDEPTH
-# define YYINITDEPTH 200
-#endif
-
-/* YYMAXDEPTH -- maximum size the stacks can grow to (effective only
-   if the built-in stack extension method is used).
-
-   Do not make this value too large; the results are undefined if
-   YYSTACK_ALLOC_MAXIMUM < YYSTACK_BYTES (YYMAXDEPTH)
-   evaluated with infinite-precision integer arithmetic.  */
-
-#ifndef YYMAXDEPTH
-# define YYMAXDEPTH 10000
-#endif
-
-\f
-
-#if YYERROR_VERBOSE
-
-# ifndef yystrlen
-#  if defined __GLIBC__ && defined _STRING_H
-#   define yystrlen strlen
-#  else
-/* Return the length of YYSTR.  */
-#if (defined __STDC__ || defined __C99__FUNC__ \
-     || defined __cplusplus || defined _MSC_VER)
-static YYSIZE_T
-yystrlen (const char *yystr)
-#else
-static YYSIZE_T
-yystrlen (yystr)
-    const char *yystr;
-#endif
-{
-  YYSIZE_T yylen;
-  for (yylen = 0; yystr[yylen]; yylen++)
-    continue;
-  return yylen;
-}
-#  endif
-# endif
-
-# ifndef yystpcpy
-#  if defined __GLIBC__ && defined _STRING_H && defined _GNU_SOURCE
-#   define yystpcpy stpcpy
-#  else
-/* Copy YYSRC to YYDEST, returning the address of the terminating '\0' in
-   YYDEST.  */
-#if (defined __STDC__ || defined __C99__FUNC__ \
-     || defined __cplusplus || defined _MSC_VER)
-static char *
-yystpcpy (char *yydest, const char *yysrc)
-#else
-static char *
-yystpcpy (yydest, yysrc)
-    char *yydest;
-    const char *yysrc;
-#endif
-{
-  char *yyd = yydest;
-  const char *yys = yysrc;
-
-  while ((*yyd++ = *yys++) != '\0')
-    continue;
-
-  return yyd - 1;
-}
-#  endif
-# endif
-
-# ifndef yytnamerr
-/* Copy to YYRES the contents of YYSTR after stripping away unnecessary
-   quotes and backslashes, so that it's suitable for yyerror.  The
-   heuristic is that double-quoting is unnecessary unless the string
-   contains an apostrophe, a comma, or backslash (other than
-   backslash-backslash).  YYSTR is taken from yytname.  If YYRES is
-   null, do not copy; instead, return the length of what the result
-   would have been.  */
-static YYSIZE_T
-yytnamerr (char *yyres, const char *yystr)
-{
-  if (*yystr == '"')
-    {
-      YYSIZE_T yyn = 0;
-      char const *yyp = yystr;
-
-      for (;;)
-       switch (*++yyp)
-         {
-         case '\'':
-         case ',':
-           goto do_not_strip_quotes;
-
-         case '\\':
-           if (*++yyp != '\\')
-             goto do_not_strip_quotes;
-           /* Fall through.  */
-         default:
-           if (yyres)
-             yyres[yyn] = *yyp;
-           yyn++;
-           break;
-
-         case '"':
-           if (yyres)
-             yyres[yyn] = '\0';
-           return yyn;
-         }
-    do_not_strip_quotes: ;
-    }
-
-  if (! yyres)
-    return yystrlen (yystr);
-
-  return yystpcpy (yyres, yystr) - yyres;
-}
-# endif
-
-/* Copy into YYRESULT an error message about the unexpected token
-   YYCHAR while in state YYSTATE.  Return the number of bytes copied,
-   including the terminating null byte.  If YYRESULT is null, do not
-   copy anything; just return the number of bytes that would be
-   copied.  As a special case, return 0 if an ordinary "syntax error"
-   message will do.  Return YYSIZE_MAXIMUM if overflow occurs during
-   size calculation.  */
-static YYSIZE_T
-yysyntax_error (char *yyresult, int yystate, int yychar)
-{
-  int yyn = yypact[yystate];
-
-  if (! (YYPACT_NINF < yyn && yyn <= YYLAST))
-    return 0;
-  else
-    {
-      int yytype = YYTRANSLATE (yychar);
-      YYSIZE_T yysize0 = yytnamerr (0, yytname[yytype]);
-      YYSIZE_T yysize = yysize0;
-      YYSIZE_T yysize1;
-      int yysize_overflow = 0;
-      enum { YYERROR_VERBOSE_ARGS_MAXIMUM = 5 };
-      char const *yyarg[YYERROR_VERBOSE_ARGS_MAXIMUM];
-      int yyx;
-
-# if 0
-      /* This is so xgettext sees the translatable formats that are
-        constructed on the fly.  */
-      YY_("syntax error, unexpected %s");
-      YY_("syntax error, unexpected %s, expecting %s");
-      YY_("syntax error, unexpected %s, expecting %s or %s");
-      YY_("syntax error, unexpected %s, expecting %s or %s or %s");
-      YY_("syntax error, unexpected %s, expecting %s or %s or %s or %s");
-# endif
-      char *yyfmt;
-      char const *yyf;
-      static char const yyunexpected[] = "syntax error, unexpected %s";
-      static char const yyexpecting[] = ", expecting %s";
-      static char const yyor[] = " or %s";
-      char yyformat[sizeof yyunexpected
-                   + sizeof yyexpecting - 1
-                   + ((YYERROR_VERBOSE_ARGS_MAXIMUM - 2)
-                      * (sizeof yyor - 1))];
-      char const *yyprefix = yyexpecting;
-
-      /* Start YYX at -YYN if negative to avoid negative indexes in
-        YYCHECK.  */
-      int yyxbegin = yyn < 0 ? -yyn : 0;
-
-      /* Stay within bounds of both yycheck and yytname.  */
-      int yychecklim = YYLAST - yyn + 1;
-      int yyxend = yychecklim < YYNTOKENS ? yychecklim : YYNTOKENS;
-      int yycount = 1;
-
-      yyarg[0] = yytname[yytype];
-      yyfmt = yystpcpy (yyformat, yyunexpected);
-
-      for (yyx = yyxbegin; yyx < yyxend; ++yyx)
-       if (yycheck[yyx + yyn] == yyx && yyx != YYTERROR)
-         {
-           if (yycount == YYERROR_VERBOSE_ARGS_MAXIMUM)
-             {
-               yycount = 1;
-               yysize = yysize0;
-               yyformat[sizeof yyunexpected - 1] = '\0';
-               break;
-             }
-           yyarg[yycount++] = yytname[yyx];
-           yysize1 = yysize + yytnamerr (0, yytname[yyx]);
-           yysize_overflow |= (yysize1 < yysize);
-           yysize = yysize1;
-           yyfmt = yystpcpy (yyfmt, yyprefix);
-           yyprefix = yyor;
-         }
-
-      yyf = YY_(yyformat);
-      yysize1 = yysize + yystrlen (yyf);
-      yysize_overflow |= (yysize1 < yysize);
-      yysize = yysize1;
-
-      if (yysize_overflow)
-       return YYSIZE_MAXIMUM;
-
-      if (yyresult)
-       {
-         /* Avoid sprintf, as that infringes on the user's name space.
-            Don't have undefined behavior even if the translation
-            produced a string with the wrong number of "%s"s.  */
-         char *yyp = yyresult;
-         int yyi = 0;
-         while ((*yyp = *yyf) != '\0')
-           {
-             if (*yyp == '%' && yyf[1] == 's' && yyi < yycount)
-               {
-                 yyp += yytnamerr (yyp, yyarg[yyi++]);
-                 yyf += 2;
-               }
-             else
-               {
-                 yyp++;
-                 yyf++;
-               }
-           }
-       }
-      return yysize;
-    }
-}
-#endif /* YYERROR_VERBOSE */
-\f
-
-/*-----------------------------------------------.
-| Release the memory associated to this symbol.  |
-`-----------------------------------------------*/
-
-/*ARGSUSED*/
-#if (defined __STDC__ || defined __C99__FUNC__ \
-     || defined __cplusplus || defined _MSC_VER)
-static void
-yydestruct (const char *yymsg, int yytype, YYSTYPE *yyvaluep)
-#else
-static void
-yydestruct (yymsg, yytype, yyvaluep)
-    const char *yymsg;
-    int yytype;
-    YYSTYPE *yyvaluep;
-#endif
-{
-  YYUSE (yyvaluep);
-
-  if (!yymsg)
-    yymsg = "Deleting";
-  YY_SYMBOL_PRINT (yymsg, yytype, yyvaluep, yylocationp);
-
-  switch (yytype)
-    {
-
-      default:
-       break;
-    }
-}
-\f
-
-/* Prevent warnings from -Wmissing-prototypes.  */
-
-#ifdef YYPARSE_PARAM
-#if defined __STDC__ || defined __cplusplus
-int yyparse (void *YYPARSE_PARAM);
-#else
-int yyparse ();
-#endif
-#else /* ! YYPARSE_PARAM */
-#if defined __STDC__ || defined __cplusplus
-int yyparse (void);
-#else
-int yyparse ();
-#endif
-#endif /* ! YYPARSE_PARAM */
-
-
-
-/* The look-ahead symbol.  */
-int yychar;
-
-/* The semantic value of the look-ahead symbol.  */
-YYSTYPE yylval;
-
-/* Number of syntax errors so far.  */
-int yynerrs;
-
-
-
-/*----------.
-| yyparse.  |
-`----------*/
-
-#ifdef YYPARSE_PARAM
-#if (defined __STDC__ || defined __C99__FUNC__ \
-     || defined __cplusplus || defined _MSC_VER)
-int
-yyparse (void *YYPARSE_PARAM)
-#else
-int
-yyparse (YYPARSE_PARAM)
-    void *YYPARSE_PARAM;
-#endif
-#else /* ! YYPARSE_PARAM */
-#if (defined __STDC__ || defined __C99__FUNC__ \
-     || defined __cplusplus || defined _MSC_VER)
-int
-yyparse (void)
-#else
-int
-yyparse ()
-
-#endif
-#endif
-{
-  
-  int yystate;
-  int yyn;
-  int yyresult;
-  /* Number of tokens to shift before error messages enabled.  */
-  int yyerrstatus;
-  /* Look-ahead token as an internal (translated) token number.  */
-  int yytoken = 0;
-#if YYERROR_VERBOSE
-  /* Buffer for error messages, and its allocated size.  */
-  char yymsgbuf[128];
-  char *yymsg = yymsgbuf;
-  YYSIZE_T yymsg_alloc = sizeof yymsgbuf;
-#endif
-
-  /* Three stacks and their tools:
-     `yyss': related to states,
-     `yyvs': related to semantic values,
-     `yyls': related to locations.
-
-     Refer to the stacks thru separate pointers, to allow yyoverflow
-     to reallocate them elsewhere.  */
-
-  /* The state stack.  */
-  yytype_int16 yyssa[YYINITDEPTH];
-  yytype_int16 *yyss = yyssa;
-  yytype_int16 *yyssp;
-
-  /* The semantic value stack.  */
-  YYSTYPE yyvsa[YYINITDEPTH];
-  YYSTYPE *yyvs = yyvsa;
-  YYSTYPE *yyvsp;
-
-
-
-#define YYPOPSTACK(N)   (yyvsp -= (N), yyssp -= (N))
-
-  YYSIZE_T yystacksize = YYINITDEPTH;
-
-  /* The variables used to return semantic value and location from the
-     action routines.  */
-  YYSTYPE yyval;
-
-
-  /* The number of symbols on the RHS of the reduced rule.
-     Keep to zero when no symbol should be popped.  */
-  int yylen = 0;
-
-  YYDPRINTF ((stderr, "Starting parse\n"));
-
-  yystate = 0;
-  yyerrstatus = 0;
-  yynerrs = 0;
-  yychar = YYEMPTY;            /* Cause a token to be read.  */
-
-  /* Initialize stack pointers.
-     Waste one element of value and location stack
-     so that they stay on the same level as the state stack.
-     The wasted elements are never initialized.  */
-
-  yyssp = yyss;
-  yyvsp = yyvs;
-
-  goto yysetstate;
-
-/*------------------------------------------------------------.
-| yynewstate -- Push a new state, which is found in yystate.  |
-`------------------------------------------------------------*/
- yynewstate:
-  /* In all cases, when you get here, the value and location stacks
-     have just been pushed.  So pushing a state here evens the stacks.  */
-  yyssp++;
-
- yysetstate:
-  *yyssp = yystate;
-
-  if (yyss + yystacksize - 1 <= yyssp)
-    {
-      /* Get the current used size of the three stacks, in elements.  */
-      YYSIZE_T yysize = yyssp - yyss + 1;
-
-#ifdef yyoverflow
-      {
-       /* Give user a chance to reallocate the stack.  Use copies of
-          these so that the &'s don't force the real ones into
-          memory.  */
-       YYSTYPE *yyvs1 = yyvs;
-       yytype_int16 *yyss1 = yyss;
-
-
-       /* Each stack pointer address is followed by the size of the
-          data in use in that stack, in bytes.  This used to be a
-          conditional around just the two extra args, but that might
-          be undefined if yyoverflow is a macro.  */
-       yyoverflow (YY_("memory exhausted"),
-                   &yyss1, yysize * sizeof (*yyssp),
-                   &yyvs1, yysize * sizeof (*yyvsp),
-
-                   &yystacksize);
-
-       yyss = yyss1;
-       yyvs = yyvs1;
-      }
-#else /* no yyoverflow */
-# ifndef YYSTACK_RELOCATE
-      goto yyexhaustedlab;
-# else
-      /* Extend the stack our own way.  */
-      if (YYMAXDEPTH <= yystacksize)
-       goto yyexhaustedlab;
-      yystacksize *= 2;
-      if (YYMAXDEPTH < yystacksize)
-       yystacksize = YYMAXDEPTH;
-
-      {
-       yytype_int16 *yyss1 = yyss;
-       union yyalloc *yyptr =
-         (union yyalloc *) YYSTACK_ALLOC (YYSTACK_BYTES (yystacksize));
-       if (! yyptr)
-         goto yyexhaustedlab;
-       YYSTACK_RELOCATE (yyss);
-       YYSTACK_RELOCATE (yyvs);
-
-#  undef YYSTACK_RELOCATE
-       if (yyss1 != yyssa)
-         YYSTACK_FREE (yyss1);
-      }
-# endif
-#endif /* no yyoverflow */
-
-      yyssp = yyss + yysize - 1;
-      yyvsp = yyvs + yysize - 1;
-
-
-      YYDPRINTF ((stderr, "Stack size increased to %lu\n",
-                 (unsigned long int) yystacksize));
-
-      if (yyss + yystacksize - 1 <= yyssp)
-       YYABORT;
-    }
-
-  YYDPRINTF ((stderr, "Entering state %d\n", yystate));
-
-  goto yybackup;
-
-/*-----------.
-| yybackup.  |
-`-----------*/
-yybackup:
-
-  /* Do appropriate processing given the current state.  Read a
-     look-ahead token if we need one and don't already have one.  */
-
-  /* First try to decide what to do without reference to look-ahead token.  */
-  yyn = yypact[yystate];
-  if (yyn == YYPACT_NINF)
-    goto yydefault;
-
-  /* Not known => get a look-ahead token if don't already have one.  */
-
-  /* YYCHAR is either YYEMPTY or YYEOF or a valid look-ahead symbol.  */
-  if (yychar == YYEMPTY)
-    {
-      YYDPRINTF ((stderr, "Reading a token: "));
-      yychar = YYLEX;
-    }
-
-  if (yychar <= YYEOF)
-    {
-      yychar = yytoken = YYEOF;
-      YYDPRINTF ((stderr, "Now at end of input.\n"));
-    }
-  else
-    {
-      yytoken = YYTRANSLATE (yychar);
-      YY_SYMBOL_PRINT ("Next token is", yytoken, &yylval, &yylloc);
-    }
-
-  /* If the proper action on seeing token YYTOKEN is to reduce or to
-     detect an error, take that action.  */
-  yyn += yytoken;
-  if (yyn < 0 || YYLAST < yyn || yycheck[yyn] != yytoken)
-    goto yydefault;
-  yyn = yytable[yyn];
-  if (yyn <= 0)
-    {
-      if (yyn == 0 || yyn == YYTABLE_NINF)
-       goto yyerrlab;
-      yyn = -yyn;
-      goto yyreduce;
-    }
-
-  if (yyn == YYFINAL)
-    YYACCEPT;
-
-  /* Count tokens shifted since error; after three, turn off error
-     status.  */
-  if (yyerrstatus)
-    yyerrstatus--;
-
-  /* Shift the look-ahead token.  */
-  YY_SYMBOL_PRINT ("Shifting", yytoken, &yylval, &yylloc);
-
-  /* Discard the shifted token unless it is eof.  */
-  if (yychar != YYEOF)
-    yychar = YYEMPTY;
-
-  yystate = yyn;
-  *++yyvsp = yylval;
-
-  goto yynewstate;
-
-
-/*-----------------------------------------------------------.
-| yydefault -- do the default action for the current state.  |
-`-----------------------------------------------------------*/
-yydefault:
-  yyn = yydefact[yystate];
-  if (yyn == 0)
-    goto yyerrlab;
-  goto yyreduce;
-
-
-/*-----------------------------.
-| yyreduce -- Do a reduction.  |
-`-----------------------------*/
-yyreduce:
-  /* yyn is the number of a rule to reduce with.  */
-  yylen = yyr2[yyn];
-
-  /* If YYLEN is nonzero, implement the default value of the action:
-     `$$ = $1'.
-
-     Otherwise, the following line sets YYVAL to garbage.
-     This behavior is undocumented and Bison
-     users should not rely upon it.  Assigning to YYVAL
-     unconditionally makes the parser a bit smaller, and it avoids a
-     GCC warning that YYVAL may be used uninitialized.  */
-  yyval = yyvsp[1-yylen];
-
-
-  YY_REDUCE_PRINT (yyn);
-  switch (yyn)
-    {
-        case 3:
-#line 68 "a.y"
-    {
-               stmtline = lineno;
-       }
-    break;
-
-  case 5:
-#line 75 "a.y"
-    {
-               (yyvsp[(1) - (2)].sym) = labellookup((yyvsp[(1) - (2)].sym));
-               if((yyvsp[(1) - (2)].sym)->type == LLAB && (yyvsp[(1) - (2)].sym)->value != pc)
-                       yyerror("redeclaration of %s", (yyvsp[(1) - (2)].sym)->labelname);
-               (yyvsp[(1) - (2)].sym)->type = LLAB;
-               (yyvsp[(1) - (2)].sym)->value = pc;
-       }
-    break;
-
-  case 7:
-#line 84 "a.y"
-    {
-               (yyvsp[(1) - (4)].sym)->type = LVAR;
-               (yyvsp[(1) - (4)].sym)->value = (yyvsp[(3) - (4)].lval);
-       }
-    break;
-
-  case 8:
-#line 89 "a.y"
-    {
-               if((yyvsp[(1) - (4)].sym)->value != (yyvsp[(3) - (4)].lval))
-                       yyerror("redeclaration of %s", (yyvsp[(1) - (4)].sym)->name);
-               (yyvsp[(1) - (4)].sym)->value = (yyvsp[(3) - (4)].lval);
-       }
-    break;
-
-  case 9:
-#line 95 "a.y"
-    {
-               nosched = (yyvsp[(1) - (2)].lval);
-       }
-    break;
-
-  case 13:
-#line 107 "a.y"
-    {
-               outcode((yyvsp[(1) - (4)].lval), &(yyvsp[(2) - (4)].addr), 0, &(yyvsp[(4) - (4)].addr));
-       }
-    break;
-
-  case 14:
-#line 111 "a.y"
-    {
-               outcode((yyvsp[(1) - (4)].lval), &(yyvsp[(2) - (4)].addr), 0, &(yyvsp[(4) - (4)].addr));
-       }
-    break;
-
-  case 15:
-#line 115 "a.y"
-    {
-               outcode((yyvsp[(1) - (4)].lval), &(yyvsp[(2) - (4)].addr), 0, &(yyvsp[(4) - (4)].addr));
-       }
-    break;
-
-  case 16:
-#line 119 "a.y"
-    {
-               outcode((yyvsp[(1) - (4)].lval), &(yyvsp[(2) - (4)].addr), 0, &(yyvsp[(4) - (4)].addr));
-       }
-    break;
-
-  case 17:
-#line 123 "a.y"
-    {
-               outcode((yyvsp[(1) - (4)].lval), &(yyvsp[(2) - (4)].addr), 0, &(yyvsp[(4) - (4)].addr));
-       }
-    break;
-
-  case 18:
-#line 127 "a.y"
-    {
-               outcode((yyvsp[(1) - (4)].lval), &(yyvsp[(2) - (4)].addr), 0, &(yyvsp[(4) - (4)].addr));
-       }
-    break;
-
-  case 19:
-#line 134 "a.y"
-    {
-               outcode((yyvsp[(1) - (4)].lval), &(yyvsp[(2) - (4)].addr), 0, &(yyvsp[(4) - (4)].addr));
-       }
-    break;
-
-  case 20:
-#line 138 "a.y"
-    {
-               outcode((yyvsp[(1) - (4)].lval), &(yyvsp[(2) - (4)].addr), 0, &(yyvsp[(4) - (4)].addr));
-       }
-    break;
-
-  case 21:
-#line 142 "a.y"
-    {
-               outcode((yyvsp[(1) - (4)].lval), &(yyvsp[(2) - (4)].addr), 0, &(yyvsp[(4) - (4)].addr));
-       }
-    break;
-
-  case 22:
-#line 146 "a.y"
-    {
-               outcode((yyvsp[(1) - (4)].lval), &(yyvsp[(2) - (4)].addr), 0, &(yyvsp[(4) - (4)].addr));
-       }
-    break;
-
-  case 23:
-#line 150 "a.y"
-    {
-               outcode((yyvsp[(1) - (4)].lval), &(yyvsp[(2) - (4)].addr), 0, &(yyvsp[(4) - (4)].addr));
-       }
-    break;
-
-  case 24:
-#line 154 "a.y"
-    {
-               outcode((yyvsp[(1) - (4)].lval), &(yyvsp[(2) - (4)].addr), 0, &(yyvsp[(4) - (4)].addr));
-       }
-    break;
-
-  case 25:
-#line 161 "a.y"
-    {
-               outcode((yyvsp[(1) - (4)].lval), &(yyvsp[(2) - (4)].addr), 0, &(yyvsp[(4) - (4)].addr));
-       }
-    break;
-
-  case 26:
-#line 165 "a.y"
-    {
-               outcode((yyvsp[(1) - (4)].lval), &(yyvsp[(2) - (4)].addr), 0, &(yyvsp[(4) - (4)].addr));
-       }
-    break;
-
-  case 27:
-#line 169 "a.y"
-    {
-               outcode((yyvsp[(1) - (4)].lval), &(yyvsp[(2) - (4)].addr), 0, &(yyvsp[(4) - (4)].addr));
-       }
-    break;
-
-  case 28:
-#line 173 "a.y"
-    {
-               outcode((yyvsp[(1) - (4)].lval), &(yyvsp[(2) - (4)].addr), 0, &(yyvsp[(4) - (4)].addr));
-       }
-    break;
-
-  case 29:
-#line 180 "a.y"
-    {
-               outcode((yyvsp[(1) - (4)].lval), &(yyvsp[(2) - (4)].addr), 0, &(yyvsp[(4) - (4)].addr));
-       }
-    break;
-
-  case 30:
-#line 184 "a.y"
-    {
-               outcode((yyvsp[(1) - (4)].lval), &(yyvsp[(2) - (4)].addr), 0, &(yyvsp[(4) - (4)].addr));
-       }
-    break;
-
-  case 31:
-#line 191 "a.y"
-    {
-               outcode((yyvsp[(1) - (4)].lval), &(yyvsp[(2) - (4)].addr), 0, &(yyvsp[(4) - (4)].addr));
-       }
-    break;
-
-  case 32:
-#line 195 "a.y"
-    {
-               outcode((yyvsp[(1) - (4)].lval), &(yyvsp[(2) - (4)].addr), 0, &(yyvsp[(4) - (4)].addr));
-       }
-    break;
-
-  case 33:
-#line 199 "a.y"
-    {
-               outgcode((yyvsp[(1) - (6)].lval), &(yyvsp[(2) - (6)].addr), 0, &(yyvsp[(4) - (6)].addr), &(yyvsp[(6) - (6)].addr));
-       }
-    break;
-
-  case 34:
-#line 203 "a.y"
-    {
-               outcode((yyvsp[(1) - (4)].lval), &(yyvsp[(2) - (4)].addr), 0, &(yyvsp[(4) - (4)].addr));
-       }
-    break;
-
-  case 35:
-#line 207 "a.y"
-    {
-               outcode((yyvsp[(1) - (4)].lval), &(yyvsp[(2) - (4)].addr), (yyvsp[(4) - (4)].lval), &nullgen);
-       }
-    break;
-
-  case 36:
-#line 214 "a.y"
-    {
-               outgcode((yyvsp[(1) - (6)].lval), &(yyvsp[(2) - (6)].addr), 0, &(yyvsp[(4) - (6)].addr), &(yyvsp[(6) - (6)].addr));
-       }
-    break;
-
-  case 37:
-#line 218 "a.y"
-    {
-               outcode((yyvsp[(1) - (4)].lval), &(yyvsp[(2) - (4)].addr), 0, &(yyvsp[(4) - (4)].addr));
-       }
-    break;
-
-  case 38:
-#line 222 "a.y"
-    {
-               outcode((yyvsp[(1) - (4)].lval), &(yyvsp[(2) - (4)].addr), 0, &(yyvsp[(4) - (4)].addr));
-       }
-    break;
-
-  case 39:
-#line 232 "a.y"
-    {
-               outcode((yyvsp[(1) - (6)].lval), &(yyvsp[(2) - (6)].addr), (yyvsp[(4) - (6)].lval), &(yyvsp[(6) - (6)].addr));
-       }
-    break;
-
-  case 40:
-#line 236 "a.y"
-    {
-               outcode((yyvsp[(1) - (6)].lval), &(yyvsp[(2) - (6)].addr), (yyvsp[(4) - (6)].lval), &(yyvsp[(6) - (6)].addr));
-       }
-    break;
-
-  case 41:
-#line 240 "a.y"
-    {
-               outgcode((yyvsp[(1) - (6)].lval), &(yyvsp[(2) - (6)].addr), 0, &(yyvsp[(4) - (6)].addr), &(yyvsp[(6) - (6)].addr));
-       }
-    break;
-
-  case 42:
-#line 244 "a.y"
-    {
-               outcode((yyvsp[(1) - (4)].lval), &(yyvsp[(2) - (4)].addr), 0, &(yyvsp[(4) - (4)].addr));
-       }
-    break;
-
-  case 43:
-#line 248 "a.y"
-    {
-               outcode((yyvsp[(1) - (4)].lval), &(yyvsp[(2) - (4)].addr), 0, &(yyvsp[(4) - (4)].addr));
-       }
-    break;
-
-  case 44:
-#line 252 "a.y"
-    {
-               outcode((yyvsp[(1) - (6)].lval), &(yyvsp[(2) - (6)].addr), (yyvsp[(4) - (6)].lval), &(yyvsp[(6) - (6)].addr));
-       }
-    break;
-
-  case 45:
-#line 256 "a.y"
-    {
-               outcode((yyvsp[(1) - (4)].lval), &(yyvsp[(2) - (4)].addr), 0, &(yyvsp[(4) - (4)].addr));
-       }
-    break;
-
-  case 46:
-#line 260 "a.y"
-    {
-               outcode((yyvsp[(1) - (6)].lval), &(yyvsp[(2) - (6)].addr), (yyvsp[(4) - (6)].lval), &(yyvsp[(6) - (6)].addr));
-       }
-    break;
-
-  case 47:
-#line 264 "a.y"
-    {
-               outcode((yyvsp[(1) - (4)].lval), &(yyvsp[(2) - (4)].addr), 0, &(yyvsp[(4) - (4)].addr));
-       }
-    break;
-
-  case 48:
-#line 268 "a.y"
-    {
-               outcode((yyvsp[(1) - (6)].lval), &(yyvsp[(2) - (6)].addr), (yyvsp[(4) - (6)].lval), &(yyvsp[(6) - (6)].addr));
-       }
-    break;
-
-  case 49:
-#line 272 "a.y"
-    {
-               outcode((yyvsp[(1) - (4)].lval), &(yyvsp[(2) - (4)].addr), 0, &(yyvsp[(4) - (4)].addr));
-       }
-    break;
-
-  case 50:
-#line 276 "a.y"
-    {
-               outcode((yyvsp[(1) - (4)].lval), &(yyvsp[(2) - (4)].addr), 0, &(yyvsp[(4) - (4)].addr));
-       }
-    break;
-
-  case 51:
-#line 280 "a.y"
-    {
-               outcode((yyvsp[(1) - (2)].lval), &(yyvsp[(2) - (2)].addr), 0, &(yyvsp[(2) - (2)].addr));
-       }
-    break;
-
-  case 52:
-#line 287 "a.y"
-    {
-               outcode((yyvsp[(1) - (6)].lval), &(yyvsp[(2) - (6)].addr), (yyvsp[(4) - (6)].lval), &(yyvsp[(6) - (6)].addr));
-       }
-    break;
-
-  case 53:
-#line 294 "a.y"
-    {
-               outcode((yyvsp[(1) - (4)].lval), &(yyvsp[(2) - (4)].addr), 0, &(yyvsp[(4) - (4)].addr));
-       }
-    break;
-
-  case 54:
-#line 298 "a.y"
-    {
-               outcode((yyvsp[(1) - (4)].lval), &(yyvsp[(2) - (4)].addr), 0, &(yyvsp[(4) - (4)].addr));
-       }
-    break;
-
-  case 55:
-#line 305 "a.y"
-    {
-               outcode((yyvsp[(1) - (4)].lval), &(yyvsp[(2) - (4)].addr), (yyvsp[(4) - (4)].addr).reg, &(yyvsp[(4) - (4)].addr));
-       }
-    break;
-
-  case 56:
-#line 309 "a.y"
-    {
-               outcode((yyvsp[(1) - (6)].lval), &(yyvsp[(2) - (6)].addr), (yyvsp[(4) - (6)].lval), &(yyvsp[(6) - (6)].addr));
-       }
-    break;
-
-  case 57:
-#line 317 "a.y"
-    {
-               outcode((yyvsp[(1) - (4)].lval), &(yyvsp[(2) - (4)].addr), 0, &(yyvsp[(4) - (4)].addr));
-       }
-    break;
-
-  case 58:
-#line 321 "a.y"
-    {
-               outcode((yyvsp[(1) - (4)].lval), &(yyvsp[(2) - (4)].addr), 0, &(yyvsp[(4) - (4)].addr));
-       }
-    break;
-
-  case 59:
-#line 325 "a.y"
-    {
-               outcode((yyvsp[(1) - (4)].lval), &(yyvsp[(2) - (4)].addr), 0, &(yyvsp[(4) - (4)].addr));
-       }
-    break;
-
-  case 60:
-#line 329 "a.y"
-    {
-               outcode((yyvsp[(1) - (4)].lval), &(yyvsp[(2) - (4)].addr), 0, &(yyvsp[(4) - (4)].addr));
-       }
-    break;
-
-  case 61:
-#line 333 "a.y"
-    {
-               outcode((yyvsp[(1) - (4)].lval), &(yyvsp[(2) - (4)].addr), 0, &(yyvsp[(4) - (4)].addr));
-       }
-    break;
-
-  case 62:
-#line 337 "a.y"
-    {
-               outcode((yyvsp[(1) - (4)].lval), &(yyvsp[(2) - (4)].addr), 0, &(yyvsp[(4) - (4)].addr));
-       }
-    break;
-
-  case 63:
-#line 341 "a.y"
-    {
-               outcode((yyvsp[(1) - (4)].lval), &(yyvsp[(2) - (4)].addr), 0, &(yyvsp[(4) - (4)].addr));
-       }
-    break;
-
-  case 64:
-#line 345 "a.y"
-    {
-               outcode((yyvsp[(1) - (4)].lval), &(yyvsp[(2) - (4)].addr), 0, &(yyvsp[(4) - (4)].addr));
-       }
-    break;
-
-  case 65:
-#line 354 "a.y"
-    {
-               outcode((yyvsp[(1) - (2)].lval), &nullgen, 0, &(yyvsp[(2) - (2)].addr));
-       }
-    break;
-
-  case 66:
-#line 358 "a.y"
-    {
-               outcode((yyvsp[(1) - (2)].lval), &nullgen, 0, &(yyvsp[(2) - (2)].addr));
-       }
-    break;
-
-  case 67:
-#line 362 "a.y"
-    {
-               outcode((yyvsp[(1) - (4)].lval), &nullgen, 0, &(yyvsp[(3) - (4)].addr));
-       }
-    break;
-
-  case 68:
-#line 366 "a.y"
-    {
-               outcode((yyvsp[(1) - (3)].lval), &nullgen, 0, &(yyvsp[(3) - (3)].addr));
-       }
-    break;
-
-  case 69:
-#line 370 "a.y"
-    {
-               outcode((yyvsp[(1) - (3)].lval), &nullgen, 0, &(yyvsp[(3) - (3)].addr));
-       }
-    break;
-
-  case 70:
-#line 374 "a.y"
-    {
-               outcode((yyvsp[(1) - (5)].lval), &nullgen, 0, &(yyvsp[(4) - (5)].addr));
-       }
-    break;
-
-  case 71:
-#line 378 "a.y"
-    {
-               outcode((yyvsp[(1) - (4)].lval), &(yyvsp[(2) - (4)].addr), 0, &(yyvsp[(4) - (4)].addr));
-       }
-    break;
-
-  case 72:
-#line 382 "a.y"
-    {
-               outcode((yyvsp[(1) - (4)].lval), &(yyvsp[(2) - (4)].addr), 0, &(yyvsp[(4) - (4)].addr));
-       }
-    break;
-
-  case 73:
-#line 386 "a.y"
-    {
-               outcode((yyvsp[(1) - (6)].lval), &(yyvsp[(2) - (6)].addr), 0, &(yyvsp[(5) - (6)].addr));
-       }
-    break;
-
-  case 74:
-#line 390 "a.y"
-    {
-               outcode((yyvsp[(1) - (4)].lval), &nullgen, (yyvsp[(2) - (4)].lval), &(yyvsp[(4) - (4)].addr));
-       }
-    break;
-
-  case 75:
-#line 394 "a.y"
-    {
-               outcode((yyvsp[(1) - (4)].lval), &nullgen, (yyvsp[(2) - (4)].lval), &(yyvsp[(4) - (4)].addr));
-       }
-    break;
-
-  case 76:
-#line 398 "a.y"
-    {
-               outcode((yyvsp[(1) - (6)].lval), &nullgen, (yyvsp[(2) - (6)].lval), &(yyvsp[(5) - (6)].addr));
-       }
-    break;
-
-  case 77:
-#line 402 "a.y"
-    {
-               Addr g;
-               g = nullgen;
-               g.type = TYPE_CONST;
-               g.offset = (yyvsp[(2) - (6)].lval);
-               outcode((yyvsp[(1) - (6)].lval), &g, REG_R0+(yyvsp[(4) - (6)].lval), &(yyvsp[(6) - (6)].addr));
-       }
-    break;
-
-  case 78:
-#line 410 "a.y"
-    {
-               Addr g;
-               g = nullgen;
-               g.type = TYPE_CONST;
-               g.offset = (yyvsp[(2) - (6)].lval);
-               outcode((yyvsp[(1) - (6)].lval), &g, REG_R0+(yyvsp[(4) - (6)].lval), &(yyvsp[(6) - (6)].addr));
-       }
-    break;
-
-  case 79:
-#line 418 "a.y"
-    {
-               Addr g;
-               g = nullgen;
-               g.type = TYPE_CONST;
-               g.offset = (yyvsp[(2) - (8)].lval);
-               outcode((yyvsp[(1) - (8)].lval), &g, REG_R0+(yyvsp[(4) - (8)].lval), &(yyvsp[(7) - (8)].addr));
-       }
-    break;
-
-  case 80:
-#line 429 "a.y"
-    {
-               outcode((yyvsp[(1) - (4)].lval), &(yyvsp[(2) - (4)].addr), (yyvsp[(4) - (4)].lval), &nullgen);
-       }
-    break;
-
-  case 81:
-#line 433 "a.y"
-    {
-               outcode((yyvsp[(1) - (4)].lval), &(yyvsp[(2) - (4)].addr), (yyvsp[(4) - (4)].lval), &nullgen);
-       }
-    break;
-
-  case 82:
-#line 437 "a.y"
-    {
-               outcode((yyvsp[(1) - (3)].lval), &(yyvsp[(2) - (3)].addr), 0, &nullgen);
-       }
-    break;
-
-  case 83:
-#line 441 "a.y"
-    {
-               outcode((yyvsp[(1) - (2)].lval), &nullgen, 0, &nullgen);
-       }
-    break;
-
-  case 84:
-#line 448 "a.y"
-    {
-               outcode((yyvsp[(1) - (4)].lval), &(yyvsp[(2) - (4)].addr), 0, &(yyvsp[(4) - (4)].addr));
-       }
-    break;
-
-  case 85:
-#line 452 "a.y"
-    {
-               outcode((yyvsp[(1) - (4)].lval), &(yyvsp[(2) - (4)].addr), 0, &(yyvsp[(4) - (4)].addr));
-       }
-    break;
-
-  case 86:
-#line 456 "a.y"
-    {
-               outcode((yyvsp[(1) - (6)].lval), &(yyvsp[(2) - (6)].addr), (yyvsp[(4) - (6)].addr).reg, &(yyvsp[(6) - (6)].addr));
-       }
-    break;
-
-  case 87:
-#line 460 "a.y"
-    {
-               outgcode((yyvsp[(1) - (8)].lval), &(yyvsp[(2) - (8)].addr), (yyvsp[(4) - (8)].addr).reg, &(yyvsp[(6) - (8)].addr), &(yyvsp[(8) - (8)].addr));
-       }
-    break;
-
-  case 88:
-#line 464 "a.y"
-    {
-               outcode((yyvsp[(1) - (4)].lval), &(yyvsp[(2) - (4)].addr), 0, &(yyvsp[(4) - (4)].addr));
-       }
-    break;
-
-  case 89:
-#line 468 "a.y"
-    {
-               outcode((yyvsp[(1) - (6)].lval), &(yyvsp[(2) - (6)].addr), (yyvsp[(6) - (6)].addr).reg, &(yyvsp[(4) - (6)].addr));
-       }
-    break;
-
-  case 90:
-#line 475 "a.y"
-    {
-               outcode((yyvsp[(1) - (4)].lval), &(yyvsp[(2) - (4)].addr), 0, &(yyvsp[(4) - (4)].addr));
-       }
-    break;
-
-  case 91:
-#line 479 "a.y"
-    {
-               outcode((yyvsp[(1) - (4)].lval), &(yyvsp[(2) - (4)].addr), 0, &(yyvsp[(4) - (4)].addr));
-       }
-    break;
-
-  case 92:
-#line 483 "a.y"
-    {
-               outcode((yyvsp[(1) - (6)].lval), &(yyvsp[(2) - (6)].addr), (yyvsp[(6) - (6)].addr).reg, &(yyvsp[(4) - (6)].addr));
-       }
-    break;
-
-  case 93:
-#line 487 "a.y"
-    {
-               outcode((yyvsp[(1) - (6)].lval), &(yyvsp[(2) - (6)].addr), (yyvsp[(6) - (6)].addr).reg, &(yyvsp[(4) - (6)].addr));
-       }
-    break;
-
-  case 94:
-#line 494 "a.y"
-    {
-               outgcode((yyvsp[(1) - (8)].lval), &(yyvsp[(2) - (8)].addr), (yyvsp[(4) - (8)].addr).reg, &(yyvsp[(6) - (8)].addr), &(yyvsp[(8) - (8)].addr));
-       }
-    break;
-
-  case 95:
-#line 498 "a.y"
-    {
-               outgcode((yyvsp[(1) - (8)].lval), &(yyvsp[(2) - (8)].addr), (yyvsp[(4) - (8)].addr).reg, &(yyvsp[(6) - (8)].addr), &(yyvsp[(8) - (8)].addr));
-       }
-    break;
-
-  case 96:
-#line 502 "a.y"
-    {
-               outgcode((yyvsp[(1) - (8)].lval), &(yyvsp[(2) - (8)].addr), (yyvsp[(4) - (8)].addr).reg, &(yyvsp[(6) - (8)].addr), &(yyvsp[(8) - (8)].addr));
-       }
-    break;
-
-  case 97:
-#line 506 "a.y"
-    {
-               outgcode((yyvsp[(1) - (8)].lval), &(yyvsp[(2) - (8)].addr), (yyvsp[(4) - (8)].addr).reg, &(yyvsp[(6) - (8)].addr), &(yyvsp[(8) - (8)].addr));
-       }
-    break;
-
-  case 98:
-#line 513 "a.y"
-    {
-               outcode((yyvsp[(1) - (4)].lval), &(yyvsp[(2) - (4)].addr), 0, &(yyvsp[(4) - (4)].addr));
-       }
-    break;
-
-  case 99:
-#line 517 "a.y"
-    {
-               outcode((yyvsp[(1) - (4)].lval), &(yyvsp[(2) - (4)].addr), 0, &(yyvsp[(4) - (4)].addr));
-       }
-    break;
-
-  case 100:
-#line 525 "a.y"
-    {
-               outcode((yyvsp[(1) - (4)].lval), &(yyvsp[(2) - (4)].addr), 0, &(yyvsp[(4) - (4)].addr));
-       }
-    break;
-
-  case 101:
-#line 529 "a.y"
-    {
-               outgcode((yyvsp[(1) - (6)].lval), &(yyvsp[(2) - (6)].addr), 0, &(yyvsp[(4) - (6)].addr), &(yyvsp[(6) - (6)].addr));
-       }
-    break;
-
-  case 102:
-#line 533 "a.y"
-    {
-               outcode((yyvsp[(1) - (4)].lval), &(yyvsp[(2) - (4)].addr), 0, &(yyvsp[(4) - (4)].addr));
-       }
-    break;
-
-  case 103:
-#line 537 "a.y"
-    {
-               outgcode((yyvsp[(1) - (6)].lval), &(yyvsp[(2) - (6)].addr), 0, &(yyvsp[(4) - (6)].addr), &(yyvsp[(6) - (6)].addr));
-       }
-    break;
-
-  case 104:
-#line 541 "a.y"
-    {
-               outcode((yyvsp[(1) - (4)].lval), &(yyvsp[(2) - (4)].addr), 0, &(yyvsp[(4) - (4)].addr));
-       }
-    break;
-
-  case 105:
-#line 545 "a.y"
-    {
-               outcode((yyvsp[(1) - (4)].lval), &(yyvsp[(2) - (4)].addr), 0, &(yyvsp[(4) - (4)].addr));
-       }
-    break;
-
-  case 106:
-#line 549 "a.y"
-    {
-               outcode((yyvsp[(1) - (2)].lval), &(yyvsp[(2) - (2)].addr), 0, &nullgen);
-       }
-    break;
-
-  case 107:
-#line 556 "a.y"
-    {
-               outcode((yyvsp[(1) - (2)].lval), &nullgen, 0, &nullgen);
-       }
-    break;
-
-  case 108:
-#line 560 "a.y"
-    {
-               outcode((yyvsp[(1) - (3)].lval), &(yyvsp[(2) - (3)].addr), 0, &nullgen);
-       }
-    break;
-
-  case 109:
-#line 564 "a.y"
-    {
-               outcode((yyvsp[(1) - (3)].lval), &(yyvsp[(2) - (3)].addr), 0, &nullgen);
-       }
-    break;
-
-  case 110:
-#line 568 "a.y"
-    {
-               outcode((yyvsp[(1) - (3)].lval), &nullgen, 0, &(yyvsp[(3) - (3)].addr));
-       }
-    break;
-
-  case 111:
-#line 572 "a.y"
-    {
-               outcode((yyvsp[(1) - (3)].lval), &nullgen, 0, &(yyvsp[(3) - (3)].addr));
-       }
-    break;
-
-  case 112:
-#line 576 "a.y"
-    {
-               outcode((yyvsp[(1) - (2)].lval), &(yyvsp[(2) - (2)].addr), 0, &nullgen);
-       }
-    break;
-
-  case 113:
-#line 583 "a.y"
-    {
-               outcode((yyvsp[(1) - (3)].lval), &(yyvsp[(2) - (3)].addr), 0, &nullgen);
-       }
-    break;
-
-  case 114:
-#line 587 "a.y"
-    {
-               outcode((yyvsp[(1) - (3)].lval), &(yyvsp[(2) - (3)].addr), 0, &nullgen);
-       }
-    break;
-
-  case 115:
-#line 594 "a.y"
-    {
-               if((yyvsp[(2) - (4)].addr).type != TYPE_CONST || (yyvsp[(4) - (4)].addr).type != TYPE_CONST)
-                       yyerror("arguments to PCDATA must be integer constants");
-               outcode((yyvsp[(1) - (4)].lval), &(yyvsp[(2) - (4)].addr), 0, &(yyvsp[(4) - (4)].addr));
-       }
-    break;
-
-  case 116:
-#line 603 "a.y"
-    {
-               if((yyvsp[(2) - (4)].addr).type != TYPE_CONST)
-                       yyerror("index for FUNCDATA must be integer constant");
-               if((yyvsp[(4) - (4)].addr).type != NAME_EXTERN && (yyvsp[(4) - (4)].addr).type != NAME_STATIC && (yyvsp[(4) - (4)].addr).type != TYPE_MEM)
-                       yyerror("value for FUNCDATA must be symbol reference");
-               outcode((yyvsp[(1) - (4)].lval), &(yyvsp[(2) - (4)].addr), 0, &(yyvsp[(4) - (4)].addr));
-       }
-    break;
-
-  case 117:
-#line 614 "a.y"
-    {
-               outcode((yyvsp[(1) - (2)].lval), &nullgen, 0, &nullgen);
-       }
-    break;
-
-  case 118:
-#line 621 "a.y"
-    {
-               settext((yyvsp[(2) - (5)].addr).sym);
-               outcode((yyvsp[(1) - (5)].lval), &(yyvsp[(2) - (5)].addr), 0, &(yyvsp[(5) - (5)].addr));
-       }
-    break;
-
-  case 119:
-#line 626 "a.y"
-    {
-               settext((yyvsp[(2) - (7)].addr).sym);
-               outcode((yyvsp[(1) - (7)].lval), &(yyvsp[(2) - (7)].addr), 0, &(yyvsp[(7) - (7)].addr));
-               if(pass > 1) {
-                       lastpc->from3.type = TYPE_CONST;
-                       lastpc->from3.offset = (yyvsp[(4) - (7)].lval);
-               }
-       }
-    break;
-
-  case 120:
-#line 638 "a.y"
-    {
-               settext((yyvsp[(2) - (4)].addr).sym);
-               outcode((yyvsp[(1) - (4)].lval), &(yyvsp[(2) - (4)].addr), 0, &(yyvsp[(4) - (4)].addr));
-       }
-    break;
-
-  case 121:
-#line 643 "a.y"
-    {
-               settext((yyvsp[(2) - (6)].addr).sym);
-               outcode((yyvsp[(1) - (6)].lval), &(yyvsp[(2) - (6)].addr), 0, &(yyvsp[(6) - (6)].addr));
-               if(pass > 1) {
-                       lastpc->from3.type = TYPE_CONST;
-                       lastpc->from3.offset = (yyvsp[(4) - (6)].lval);
-               }
-       }
-    break;
-
-  case 122:
-#line 656 "a.y"
-    {
-               outcode((yyvsp[(1) - (6)].lval), &(yyvsp[(2) - (6)].addr), 0, &(yyvsp[(6) - (6)].addr));
-               if(pass > 1) {
-                       lastpc->from3.type = TYPE_CONST;
-                       lastpc->from3.offset = (yyvsp[(4) - (6)].lval);
-               }
-       }
-    break;
-
-  case 123:
-#line 664 "a.y"
-    {
-               outcode((yyvsp[(1) - (6)].lval), &(yyvsp[(2) - (6)].addr), 0, &(yyvsp[(6) - (6)].addr));
-               if(pass > 1) {
-                       lastpc->from3.type = TYPE_CONST;
-                       lastpc->from3.offset = (yyvsp[(4) - (6)].lval);
-               }
-       }
-    break;
-
-  case 124:
-#line 672 "a.y"
-    {
-               outcode((yyvsp[(1) - (6)].lval), &(yyvsp[(2) - (6)].addr), 0, &(yyvsp[(6) - (6)].addr));
-               if(pass > 1) {
-                       lastpc->from3.type = TYPE_CONST;
-                       lastpc->from3.offset = (yyvsp[(4) - (6)].lval);
-               }
-       }
-    break;
-
-  case 125:
-#line 683 "a.y"
-    {
-               outcode((yyvsp[(1) - (2)].lval), &nullgen, 0, &nullgen);
-       }
-    break;
-
-  case 126:
-#line 689 "a.y"
-    {
-               (yyval.addr) = nullgen;
-               (yyval.addr).type = TYPE_BRANCH;
-               (yyval.addr).offset = (yyvsp[(1) - (4)].lval) + pc;
-       }
-    break;
-
-  case 127:
-#line 695 "a.y"
-    {
-               (yyvsp[(1) - (2)].sym) = labellookup((yyvsp[(1) - (2)].sym));
-               (yyval.addr) = nullgen;
-               if(pass == 2 && (yyvsp[(1) - (2)].sym)->type != LLAB)
-                       yyerror("undefined label: %s", (yyvsp[(1) - (2)].sym)->labelname);
-               (yyval.addr).type = TYPE_BRANCH;
-               (yyval.addr).offset = (yyvsp[(1) - (2)].sym)->value + (yyvsp[(2) - (2)].lval);
-       }
-    break;
-
-  case 128:
-#line 706 "a.y"
-    {
-               (yyval.addr) = nullgen;
-               (yyval.addr).type = TYPE_REG;
-               (yyval.addr).reg = (yyvsp[(1) - (1)].lval);
-       }
-    break;
-
-  case 131:
-#line 718 "a.y"
-    {
-               (yyval.addr) = nullgen;
-               (yyval.addr).type = TYPE_REG;
-               (yyval.addr).reg = (yyvsp[(1) - (1)].lval);
-       }
-    break;
-
-  case 132:
-#line 726 "a.y"
-    {
-               (yyval.addr) = nullgen;
-               (yyval.addr).type = TYPE_REG;
-               (yyval.addr).reg = (yyvsp[(1) - (1)].lval);     /* whole register */
-       }
-    break;
-
-  case 133:
-#line 734 "a.y"
-    {
-               (yyval.addr) = nullgen;
-               (yyval.addr).type = TYPE_REG;
-               (yyval.addr).reg = (yyvsp[(1) - (1)].lval);
-       }
-    break;
-
-  case 134:
-#line 742 "a.y"
-    {
-               (yyval.addr) = nullgen;
-               (yyval.addr).type = TYPE_REG;
-               (yyval.addr).reg = (yyvsp[(1) - (1)].lval);
-       }
-    break;
-
-  case 135:
-#line 750 "a.y"
-    {
-               (yyval.addr) = nullgen;
-               (yyval.addr).type = TYPE_REG;
-               (yyval.addr).reg = (yyvsp[(1) - (1)].lval);
-       }
-    break;
-
-  case 136:
-#line 756 "a.y"
-    {
-               if((yyvsp[(3) - (4)].lval) < 0 || (yyvsp[(3) - (4)].lval) >= 1024)
-                       yyerror("SPR/DCR out of range");
-               (yyval.addr) = nullgen;
-               (yyval.addr).type = TYPE_REG;
-               (yyval.addr).reg = (yyvsp[(1) - (4)].lval) + (yyvsp[(3) - (4)].lval);
-       }
-    break;
-
-  case 138:
-#line 767 "a.y"
-    {
-               (yyval.addr) = nullgen;
-               (yyval.addr).type = TYPE_REG;
-               (yyval.addr).reg = (yyvsp[(1) - (1)].lval);
-       }
-    break;
-
-  case 139:
-#line 775 "a.y"
-    {
-               (yyval.addr) = nullgen;
-               (yyval.addr).type = TYPE_REG;
-               (yyval.addr).reg = (yyvsp[(1) - (1)].lval);
-       }
-    break;
-
-  case 140:
-#line 781 "a.y"
-    {
-               (yyval.addr) = nullgen;
-               (yyval.addr).type = TYPE_REG;
-               (yyval.addr).reg = REG_F0 + (yyvsp[(3) - (4)].lval);
-       }
-    break;
-
-  case 141:
-#line 789 "a.y"
-    {
-               (yyval.addr) = nullgen;
-               (yyval.addr).type = TYPE_REG;
-               (yyval.addr).reg = (yyvsp[(1) - (1)].lval);
-       }
-    break;
-
-  case 142:
-#line 795 "a.y"
-    {
-               (yyval.addr) = nullgen;
-               (yyval.addr).type = TYPE_REG;
-               (yyval.addr).reg = REG_C0 + (yyvsp[(3) - (4)].lval);
-       }
-    break;
-
-  case 143:
-#line 803 "a.y"
-    {
-               (yyval.addr) = nullgen;
-               (yyval.addr).type = TYPE_REG;
-               (yyval.addr).reg = (yyvsp[(1) - (1)].lval);
-       }
-    break;
-
-  case 144:
-#line 811 "a.y"
-    {
-               int mb, me;
-               uint32 v;
-
-               (yyval.addr) = nullgen;
-               (yyval.addr).type = TYPE_CONST;
-               mb = (yyvsp[(1) - (3)].lval);
-               me = (yyvsp[(3) - (3)].lval);
-               if(mb < 0 || mb > 31 || me < 0 || me > 31){
-                       yyerror("illegal mask start/end value(s)");
-                       mb = me = 0;
-               }
-               if(mb <= me)
-                       v = ((uint32)~0L>>mb) & (~0L<<(31-me));
-               else
-                       v = ~(((uint32)~0L>>(me+1)) & (~0L<<(31-(mb-1))));
-               (yyval.addr).offset = v;
-       }
-    break;
-
-  case 145:
-#line 832 "a.y"
-    {
-               (yyval.addr) = nullgen;
-               (yyval.addr).type = TYPE_TEXTSIZE;
-               (yyval.addr).offset = (yyvsp[(1) - (1)].lval);
-               (yyval.addr).u.argsize = ArgsSizeUnknown;
-       }
-    break;
-
-  case 146:
-#line 839 "a.y"
-    {
-               (yyval.addr) = nullgen;
-               (yyval.addr).type = TYPE_TEXTSIZE;
-               (yyval.addr).offset = -(yyvsp[(2) - (2)].lval);
-               (yyval.addr).u.argsize = ArgsSizeUnknown;
-       }
-    break;
-
-  case 147:
-#line 846 "a.y"
-    {
-               (yyval.addr) = nullgen;
-               (yyval.addr).type = TYPE_TEXTSIZE;
-               (yyval.addr).offset = (yyvsp[(1) - (3)].lval);
-               (yyval.addr).u.argsize = (yyvsp[(3) - (3)].lval);
-       }
-    break;
-
-  case 148:
-#line 853 "a.y"
-    {
-               (yyval.addr) = nullgen;
-               (yyval.addr).type = TYPE_TEXTSIZE;
-               (yyval.addr).offset = -(yyvsp[(2) - (4)].lval);
-               (yyval.addr).u.argsize = (yyvsp[(4) - (4)].lval);
-       }
-    break;
-
-  case 149:
-#line 862 "a.y"
-    {
-               (yyval.addr) = (yyvsp[(2) - (2)].addr);
-               (yyval.addr).type = TYPE_ADDR;
-       }
-    break;
-
-  case 150:
-#line 867 "a.y"
-    {
-               (yyval.addr) = nullgen;
-               (yyval.addr).type = TYPE_SCONST;
-               memcpy((yyval.addr).u.sval, (yyvsp[(2) - (2)].sval), sizeof((yyval.addr).u.sval));
-       }
-    break;
-
-  case 151:
-#line 875 "a.y"
-    {
-               (yyval.addr) = nullgen;
-               (yyval.addr).type = TYPE_FCONST;
-               (yyval.addr).u.dval = (yyvsp[(2) - (2)].dval);
-       }
-    break;
-
-  case 152:
-#line 881 "a.y"
-    {
-               (yyval.addr) = nullgen;
-               (yyval.addr).type = TYPE_FCONST;
-               (yyval.addr).u.dval = -(yyvsp[(3) - (3)].dval);
-       }
-    break;
-
-  case 153:
-#line 888 "a.y"
-    {
-               (yyval.addr) = nullgen;
-               (yyval.addr).type = TYPE_CONST;
-               (yyval.addr).offset = (yyvsp[(2) - (2)].lval);
-       }
-    break;
-
-  case 155:
-#line 897 "a.y"
-    {
-               if((yyval.lval) < 0 || (yyval.lval) >= NREG)
-                       print("register value out of range\n");
-               (yyval.lval) = REG_R0 + (yyvsp[(3) - (4)].lval);
-       }
-    break;
-
-  case 156:
-#line 905 "a.y"
-    {
-               (yyval.addr) = nullgen;
-               (yyval.addr).type = TYPE_MEM;
-               (yyval.addr).reg = (yyvsp[(2) - (3)].lval);
-               (yyval.addr).offset = 0;
-       }
-    break;
-
-  case 157:
-#line 912 "a.y"
-    {
-               (yyval.addr) = nullgen;
-               (yyval.addr).type = TYPE_MEM;
-               (yyval.addr).reg = (yyvsp[(2) - (5)].lval);
-               (yyval.addr).scale = (yyvsp[(4) - (5)].lval);
-               (yyval.addr).offset = 0;
-       }
-    break;
-
-  case 159:
-#line 923 "a.y"
-    {
-               (yyval.addr) = nullgen;
-               (yyval.addr).type = TYPE_MEM;
-               (yyval.addr).reg = (yyvsp[(3) - (4)].lval);
-               (yyval.addr).offset = (yyvsp[(1) - (4)].lval);
-       }
-    break;
-
-  case 160:
-#line 932 "a.y"
-    {
-               (yyval.addr) = nullgen;
-               (yyval.addr).type = TYPE_MEM;
-               (yyval.addr).name = (yyvsp[(3) - (4)].lval);
-               (yyval.addr).sym = nil;
-               (yyval.addr).offset = (yyvsp[(1) - (4)].lval);
-       }
-    break;
-
-  case 161:
-#line 940 "a.y"
-    {
-               (yyval.addr) = nullgen;
-               (yyval.addr).type = TYPE_MEM;
-               (yyval.addr).name = (yyvsp[(4) - (5)].lval);
-               (yyval.addr).sym = linklookup(ctxt, (yyvsp[(1) - (5)].sym)->name, 0);
-               (yyval.addr).offset = (yyvsp[(2) - (5)].lval);
-       }
-    break;
-
-  case 162:
-#line 948 "a.y"
-    {
-               (yyval.addr) = nullgen;
-               (yyval.addr).type = TYPE_MEM;
-               (yyval.addr).name = NAME_STATIC;
-               (yyval.addr).sym = linklookup(ctxt, (yyvsp[(1) - (7)].sym)->name, 1);
-               (yyval.addr).offset = (yyvsp[(4) - (7)].lval);
-       }
-    break;
-
-  case 165:
-#line 960 "a.y"
-    {
-               (yyval.lval) = 0;
-       }
-    break;
-
-  case 166:
-#line 964 "a.y"
-    {
-               (yyval.lval) = (yyvsp[(2) - (2)].lval);
-       }
-    break;
-
-  case 167:
-#line 968 "a.y"
-    {
-               (yyval.lval) = -(yyvsp[(2) - (2)].lval);
-       }
-    break;
-
-  case 172:
-#line 980 "a.y"
-    {
-               (yyval.lval) = (yyvsp[(1) - (1)].sym)->value;
-       }
-    break;
-
-  case 173:
-#line 984 "a.y"
-    {
-               (yyval.lval) = -(yyvsp[(2) - (2)].lval);
-       }
-    break;
-
-  case 174:
-#line 988 "a.y"
-    {
-               (yyval.lval) = (yyvsp[(2) - (2)].lval);
-       }
-    break;
-
-  case 175:
-#line 992 "a.y"
-    {
-               (yyval.lval) = ~(yyvsp[(2) - (2)].lval);
-       }
-    break;
-
-  case 176:
-#line 996 "a.y"
-    {
-               (yyval.lval) = (yyvsp[(2) - (3)].lval);
-       }
-    break;
-
-  case 178:
-#line 1003 "a.y"
-    {
-               (yyval.lval) = (yyvsp[(1) - (3)].lval) + (yyvsp[(3) - (3)].lval);
-       }
-    break;
-
-  case 179:
-#line 1007 "a.y"
-    {
-               (yyval.lval) = (yyvsp[(1) - (3)].lval) - (yyvsp[(3) - (3)].lval);
-       }
-    break;
-
-  case 180:
-#line 1011 "a.y"
-    {
-               (yyval.lval) = (yyvsp[(1) - (3)].lval) * (yyvsp[(3) - (3)].lval);
-       }
-    break;
-
-  case 181:
-#line 1015 "a.y"
-    {
-               (yyval.lval) = (yyvsp[(1) - (3)].lval) / (yyvsp[(3) - (3)].lval);
-       }
-    break;
-
-  case 182:
-#line 1019 "a.y"
-    {
-               (yyval.lval) = (yyvsp[(1) - (3)].lval) % (yyvsp[(3) - (3)].lval);
-       }
-    break;
-
-  case 183:
-#line 1023 "a.y"
-    {
-               (yyval.lval) = (yyvsp[(1) - (4)].lval) << (yyvsp[(4) - (4)].lval);
-       }
-    break;
-
-  case 184:
-#line 1027 "a.y"
-    {
-               (yyval.lval) = (yyvsp[(1) - (4)].lval) >> (yyvsp[(4) - (4)].lval);
-       }
-    break;
-
-  case 185:
-#line 1031 "a.y"
-    {
-               (yyval.lval) = (yyvsp[(1) - (3)].lval) & (yyvsp[(3) - (3)].lval);
-       }
-    break;
-
-  case 186:
-#line 1035 "a.y"
-    {
-               (yyval.lval) = (yyvsp[(1) - (3)].lval) ^ (yyvsp[(3) - (3)].lval);
-       }
-    break;
-
-  case 187:
-#line 1039 "a.y"
-    {
-               (yyval.lval) = (yyvsp[(1) - (3)].lval) | (yyvsp[(3) - (3)].lval);
-       }
-    break;
-
-
-/* Line 1267 of yacc.c.  */
-#line 3253 "y.tab.c"
-      default: break;
-    }
-  YY_SYMBOL_PRINT ("-> $$ =", yyr1[yyn], &yyval, &yyloc);
-
-  YYPOPSTACK (yylen);
-  yylen = 0;
-  YY_STACK_PRINT (yyss, yyssp);
-
-  *++yyvsp = yyval;
-
-
-  /* Now `shift' the result of the reduction.  Determine what state
-     that goes to, based on the state we popped back to and the rule
-     number reduced by.  */
-
-  yyn = yyr1[yyn];
-
-  yystate = yypgoto[yyn - YYNTOKENS] + *yyssp;
-  if (0 <= yystate && yystate <= YYLAST && yycheck[yystate] == *yyssp)
-    yystate = yytable[yystate];
-  else
-    yystate = yydefgoto[yyn - YYNTOKENS];
-
-  goto yynewstate;
-
-
-/*------------------------------------.
-| yyerrlab -- here on detecting error |
-`------------------------------------*/
-yyerrlab:
-  /* If not already recovering from an error, report this error.  */
-  if (!yyerrstatus)
-    {
-      ++yynerrs;
-#if ! YYERROR_VERBOSE
-      yyerror (YY_("syntax error"));
-#else
-      {
-       YYSIZE_T yysize = yysyntax_error (0, yystate, yychar);
-       if (yymsg_alloc < yysize && yymsg_alloc < YYSTACK_ALLOC_MAXIMUM)
-         {
-           YYSIZE_T yyalloc = 2 * yysize;
-           if (! (yysize <= yyalloc && yyalloc <= YYSTACK_ALLOC_MAXIMUM))
-             yyalloc = YYSTACK_ALLOC_MAXIMUM;
-           if (yymsg != yymsgbuf)
-             YYSTACK_FREE (yymsg);
-           yymsg = (char *) YYSTACK_ALLOC (yyalloc);
-           if (yymsg)
-             yymsg_alloc = yyalloc;
-           else
-             {
-               yymsg = yymsgbuf;
-               yymsg_alloc = sizeof yymsgbuf;
-             }
-         }
-
-       if (0 < yysize && yysize <= yymsg_alloc)
-         {
-           (void) yysyntax_error (yymsg, yystate, yychar);
-           yyerror (yymsg);
-         }
-       else
-         {
-           yyerror (YY_("syntax error"));
-           if (yysize != 0)
-             goto yyexhaustedlab;
-         }
-      }
-#endif
-    }
-
-
-
-  if (yyerrstatus == 3)
-    {
-      /* If just tried and failed to reuse look-ahead token after an
-        error, discard it.  */
-
-      if (yychar <= YYEOF)
-       {
-         /* Return failure if at end of input.  */
-         if (yychar == YYEOF)
-           YYABORT;
-       }
-      else
-       {
-         yydestruct ("Error: discarding",
-                     yytoken, &yylval);
-         yychar = YYEMPTY;
-       }
-    }
-
-  /* Else will try to reuse look-ahead token after shifting the error
-     token.  */
-  goto yyerrlab1;
-
-
-/*---------------------------------------------------.
-| yyerrorlab -- error raised explicitly by YYERROR.  |
-`---------------------------------------------------*/
-yyerrorlab:
-
-  /* Pacify compilers like GCC when the user code never invokes
-     YYERROR and the label yyerrorlab therefore never appears in user
-     code.  */
-  if (/*CONSTCOND*/ 0)
-     goto yyerrorlab;
-
-  /* Do not reclaim the symbols of the rule which action triggered
-     this YYERROR.  */
-  YYPOPSTACK (yylen);
-  yylen = 0;
-  YY_STACK_PRINT (yyss, yyssp);
-  yystate = *yyssp;
-  goto yyerrlab1;
-
-
-/*-------------------------------------------------------------.
-| yyerrlab1 -- common code for both syntax error and YYERROR.  |
-`-------------------------------------------------------------*/
-yyerrlab1:
-  yyerrstatus = 3;     /* Each real token shifted decrements this.  */
-
-  for (;;)
-    {
-      yyn = yypact[yystate];
-      if (yyn != YYPACT_NINF)
-       {
-         yyn += YYTERROR;
-         if (0 <= yyn && yyn <= YYLAST && yycheck[yyn] == YYTERROR)
-           {
-             yyn = yytable[yyn];
-             if (0 < yyn)
-               break;
-           }
-       }
-
-      /* Pop the current state because it cannot handle the error token.  */
-      if (yyssp == yyss)
-       YYABORT;
-
-
-      yydestruct ("Error: popping",
-                 yystos[yystate], yyvsp);
-      YYPOPSTACK (1);
-      yystate = *yyssp;
-      YY_STACK_PRINT (yyss, yyssp);
-    }
-
-  if (yyn == YYFINAL)
-    YYACCEPT;
-
-  *++yyvsp = yylval;
-
-
-  /* Shift the error token.  */
-  YY_SYMBOL_PRINT ("Shifting", yystos[yyn], yyvsp, yylsp);
-
-  yystate = yyn;
-  goto yynewstate;
-
-
-/*-------------------------------------.
-| yyacceptlab -- YYACCEPT comes here.  |
-`-------------------------------------*/
-yyacceptlab:
-  yyresult = 0;
-  goto yyreturn;
-
-/*-----------------------------------.
-| yyabortlab -- YYABORT comes here.  |
-`-----------------------------------*/
-yyabortlab:
-  yyresult = 1;
-  goto yyreturn;
-
-#ifndef yyoverflow
-/*-------------------------------------------------.
-| yyexhaustedlab -- memory exhaustion comes here.  |
-`-------------------------------------------------*/
-yyexhaustedlab:
-  yyerror (YY_("memory exhausted"));
-  yyresult = 2;
-  /* Fall through.  */
-#endif
-
-yyreturn:
-  if (yychar != YYEOF && yychar != YYEMPTY)
-     yydestruct ("Cleanup: discarding lookahead",
-                yytoken, &yylval);
-  /* Do not reclaim the symbols of the rule which action triggered
-     this YYABORT or YYACCEPT.  */
-  YYPOPSTACK (yylen);
-  YY_STACK_PRINT (yyss, yyssp);
-  while (yyssp != yyss)
-    {
-      yydestruct ("Cleanup: popping",
-                 yystos[*yyssp], yyvsp);
-      YYPOPSTACK (1);
-    }
-#ifndef yyoverflow
-  if (yyss != yyssa)
-    YYSTACK_FREE (yyss);
-#endif
-#if YYERROR_VERBOSE
-  if (yymsg != yymsgbuf)
-    YYSTACK_FREE (yymsg);
-#endif
-  /* Make sure YYID is used.  */
-  return YYID (yyresult);
-}
-
-
-
diff --git a/src/cmd/9a/y.tab.h b/src/cmd/9a/y.tab.h
deleted file mode 100644 (file)
index e7b0033..0000000
+++ /dev/null
@@ -1,190 +0,0 @@
-/* A Bison parser, made by GNU Bison 2.3.  */
-
-/* Skeleton interface for Bison's Yacc-like parsers in C
-
-   Copyright (C) 1984, 1989, 1990, 2000, 2001, 2002, 2003, 2004, 2005, 2006
-   Free Software Foundation, Inc.
-
-   This program is free software; you can redistribute it and/or modify
-   it under the terms of the GNU General Public License as published by
-   the Free Software Foundation; either version 2, or (at your option)
-   any later version.
-
-   This program is distributed in the hope that it will be useful,
-   but WITHOUT ANY WARRANTY; without even the implied warranty of
-   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-   GNU General Public License for more details.
-
-   You should have received a copy of the GNU General Public License
-   along with this program; if not, write to the Free Software
-   Foundation, Inc., 51 Franklin Street, Fifth Floor,
-   Boston, MA 02110-1301, USA.  */
-
-/* As a special exception, you may create a larger work that contains
-   part or all of the Bison parser skeleton and distribute that work
-   under terms of your choice, so long as that work isn't itself a
-   parser generator using the skeleton or a modified version thereof
-   as a parser skeleton.  Alternatively, if you modify or redistribute
-   the parser skeleton itself, you may (at your option) remove this
-   special exception, which will cause the skeleton and the resulting
-   Bison output files to be licensed under the GNU General Public
-   License without this special exception.
-
-   This special exception was added by the Free Software Foundation in
-   version 2.2 of Bison.  */
-
-/* Tokens.  */
-#ifndef YYTOKENTYPE
-# define YYTOKENTYPE
-   /* Put the tokens into the symbol table, so that GDB and other debuggers
-      know about them.  */
-   enum yytokentype {
-     LMOVW = 258,
-     LMOVB = 259,
-     LABS = 260,
-     LLOGW = 261,
-     LSHW = 262,
-     LADDW = 263,
-     LCMP = 264,
-     LCROP = 265,
-     LBRA = 266,
-     LFMOV = 267,
-     LFCONV = 268,
-     LFCMP = 269,
-     LFADD = 270,
-     LFMA = 271,
-     LTRAP = 272,
-     LXORW = 273,
-     LNOP = 274,
-     LEND = 275,
-     LRETT = 276,
-     LWORD = 277,
-     LTEXT = 278,
-     LGLOBL = 279,
-     LDATA = 280,
-     LRETRN = 281,
-     LCONST = 282,
-     LSP = 283,
-     LSB = 284,
-     LFP = 285,
-     LPC = 286,
-     LCREG = 287,
-     LFLUSH = 288,
-     LREG = 289,
-     LFREG = 290,
-     LR = 291,
-     LCR = 292,
-     LF = 293,
-     LFPSCR = 294,
-     LLR = 295,
-     LCTR = 296,
-     LSPR = 297,
-     LSPREG = 298,
-     LSEG = 299,
-     LMSR = 300,
-     LPCDAT = 301,
-     LFUNCDAT = 302,
-     LSCHED = 303,
-     LXLD = 304,
-     LXST = 305,
-     LXOP = 306,
-     LXMV = 307,
-     LRLWM = 308,
-     LMOVMW = 309,
-     LMOVEM = 310,
-     LMOVFL = 311,
-     LMTFSB = 312,
-     LMA = 313,
-     LFCONST = 314,
-     LSCONST = 315,
-     LNAME = 316,
-     LLAB = 317,
-     LVAR = 318
-   };
-#endif
-/* Tokens.  */
-#define LMOVW 258
-#define LMOVB 259
-#define LABS 260
-#define LLOGW 261
-#define LSHW 262
-#define LADDW 263
-#define LCMP 264
-#define LCROP 265
-#define LBRA 266
-#define LFMOV 267
-#define LFCONV 268
-#define LFCMP 269
-#define LFADD 270
-#define LFMA 271
-#define LTRAP 272
-#define LXORW 273
-#define LNOP 274
-#define LEND 275
-#define LRETT 276
-#define LWORD 277
-#define LTEXT 278
-#define LGLOBL 279
-#define LDATA 280
-#define LRETRN 281
-#define LCONST 282
-#define LSP 283
-#define LSB 284
-#define LFP 285
-#define LPC 286
-#define LCREG 287
-#define LFLUSH 288
-#define LREG 289
-#define LFREG 290
-#define LR 291
-#define LCR 292
-#define LF 293
-#define LFPSCR 294
-#define LLR 295
-#define LCTR 296
-#define LSPR 297
-#define LSPREG 298
-#define LSEG 299
-#define LMSR 300
-#define LPCDAT 301
-#define LFUNCDAT 302
-#define LSCHED 303
-#define LXLD 304
-#define LXST 305
-#define LXOP 306
-#define LXMV 307
-#define LRLWM 308
-#define LMOVMW 309
-#define LMOVEM 310
-#define LMOVFL 311
-#define LMTFSB 312
-#define LMA 313
-#define LFCONST 314
-#define LSCONST 315
-#define LNAME 316
-#define LLAB 317
-#define LVAR 318
-
-
-
-
-#if ! defined YYSTYPE && ! defined YYSTYPE_IS_DECLARED
-typedef union YYSTYPE
-#line 38 "a.y"
-{
-       Sym     *sym;
-       vlong   lval;
-       double  dval;
-       char    sval[8];
-       Addr    addr;
-}
-/* Line 1529 of yacc.c.  */
-#line 183 "y.tab.h"
-       YYSTYPE;
-# define yystype YYSTYPE /* obsolescent; will be withdrawn */
-# define YYSTYPE_IS_DECLARED 1
-# define YYSTYPE_IS_TRIVIAL 1
-#endif
-
-extern YYSTYPE yylval;
-
diff --git a/src/cmd/9g/cgen.c b/src/cmd/9g/cgen.c
deleted file mode 100644 (file)
index 009ea1e..0000000
+++ /dev/null
@@ -1,1758 +0,0 @@
-// Copyright 2009 The Go Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style
-// license that can be found in the LICENSE file.
-
-#include <u.h>
-#include <libc.h>
-#include "gg.h"
-
-/*
- * generate:
- *     res = n;
- * simplifies and calls gmove.
- */
-void
-cgen(Node *n, Node *res)
-{
-       Node *nl, *nr, *r;
-       Node n1, n2;
-       int a, f;
-       Prog *p1, *p2, *p3;
-       Addr addr;
-
-//print("cgen %N(%d) -> %N(%d)\n", n, n->addable, res, res->addable);
-       if(debug['g']) {
-               dump("\ncgen-n", n);
-               dump("cgen-res", res);
-       }
-       if(n == N || n->type == T)
-               goto ret;
-
-       if(res == N || res->type == T)
-               fatal("cgen: res nil");
-
-       while(n->op == OCONVNOP)
-               n = n->left;
-
-       switch(n->op) {
-       case OSLICE:
-       case OSLICEARR:
-       case OSLICESTR:
-       case OSLICE3:
-       case OSLICE3ARR:
-               if (res->op != ONAME || !res->addable) {
-                       tempname(&n1, n->type);
-                       cgen_slice(n, &n1);
-                       cgen(&n1, res);
-               } else
-                       cgen_slice(n, res);
-               goto ret;
-       case OEFACE:
-               if (res->op != ONAME || !res->addable) {
-                       tempname(&n1, n->type);
-                       cgen_eface(n, &n1);
-                       cgen(&n1, res);
-               } else
-                       cgen_eface(n, res);
-               goto ret;
-       }
-
-       if(n->ullman >= UINF) {
-               if(n->op == OINDREG)
-                       fatal("cgen: this is going to misscompile");
-               if(res->ullman >= UINF) {
-                       tempname(&n1, n->type);
-                       cgen(n, &n1);
-                       cgen(&n1, res);
-                       goto ret;
-               }
-       }
-
-       if(isfat(n->type)) {
-               if(n->type->width < 0)
-                       fatal("forgot to compute width for %T", n->type);
-               sgen(n, res, n->type->width);
-               goto ret;
-       }
-
-       if(!res->addable) {
-               if(n->ullman > res->ullman) {
-                       regalloc(&n1, n->type, res);
-                       cgen(n, &n1);
-                       if(n1.ullman > res->ullman) {
-                               dump("n1", &n1);
-                               dump("res", res);
-                               fatal("loop in cgen");
-                       }
-                       cgen(&n1, res);
-                       regfree(&n1);
-                       goto ret;
-               }
-
-               if(res->ullman >= UINF)
-                       goto gen;
-
-               if(complexop(n, res)) {
-                       complexgen(n, res);
-                       goto ret;
-               }
-
-               f = 1;  // gen thru register
-               switch(n->op) {
-               case OLITERAL:
-                       if(smallintconst(n))
-                               f = 0;
-                       break;
-               case OREGISTER:
-                       f = 0;
-                       break;
-               }
-
-               if(!iscomplex[n->type->etype]) {
-                       a = optoas(OAS, res->type);
-                       if(sudoaddable(a, res, &addr)) {
-                               if(f) {
-                                       regalloc(&n2, res->type, N);
-                                       cgen(n, &n2);
-                                       p1 = gins(a, &n2, N);
-                                       regfree(&n2);
-                               } else
-                                       p1 = gins(a, n, N);
-                               p1->to = addr;
-                               if(debug['g'])
-                                       print("%P [ignore previous line]\n", p1);
-                               sudoclean();
-                               goto ret;
-                       }
-               }
-
-       gen:
-               igen(res, &n1, N);
-               cgen(n, &n1);
-               regfree(&n1);
-               goto ret;
-       }
-
-       // update addressability for string, slice
-       // can't do in walk because n->left->addable
-       // changes if n->left is an escaping local variable.
-       switch(n->op) {
-       case OSPTR:
-       case OLEN:
-               if(isslice(n->left->type) || istype(n->left->type, TSTRING))
-                       n->addable = n->left->addable;
-               break;
-       case OCAP:
-               if(isslice(n->left->type))
-                       n->addable = n->left->addable;
-               break;
-       case OITAB:
-               n->addable = n->left->addable;
-               break;
-       }
-
-       if(complexop(n, res)) {
-               complexgen(n, res);
-               goto ret;
-       }
-
-       // if both are addressable, move
-       if(n->addable) {
-               if(n->op == OREGISTER || res->op == OREGISTER) {
-                       gmove(n, res);
-               } else {
-                       regalloc(&n1, n->type, N);
-                       gmove(n, &n1);
-                       cgen(&n1, res);
-                       regfree(&n1);
-               }
-               goto ret;
-       }
-
-       nl = n->left;
-       nr = n->right;
-
-       if(nl != N && nl->ullman >= UINF)
-       if(nr != N && nr->ullman >= UINF) {
-               tempname(&n1, nl->type);
-               cgen(nl, &n1);
-               n2 = *n;
-               n2.left = &n1;
-               cgen(&n2, res);
-               goto ret;
-       }
-
-       if(!iscomplex[n->type->etype]) {
-               a = optoas(OAS, n->type);
-               if(sudoaddable(a, n, &addr)) {
-                       if(res->op == OREGISTER) {
-                               p1 = gins(a, N, res);
-                               p1->from = addr;
-                       } else {
-                               regalloc(&n2, n->type, N);
-                               p1 = gins(a, N, &n2);
-                               p1->from = addr;
-                               gins(a, &n2, res);
-                               regfree(&n2);
-                       }
-                       sudoclean();
-                       goto ret;
-               }
-       }
-
-       // TODO(minux): we shouldn't reverse FP comparisons, but then we need to synthesize
-       // OGE, OLE, and ONE ourselves.
-       // if(nl != N && isfloat[n->type->etype] && isfloat[nl->type->etype]) goto flt;
-
-       switch(n->op) {
-       default:
-               dump("cgen", n);
-               fatal("cgen: unknown op %+hN", n);
-               break;
-
-       // these call bgen to get a bool value
-       case OOROR:
-       case OANDAND:
-       case OEQ:
-       case ONE:
-       case OLT:
-       case OLE:
-       case OGE:
-       case OGT:
-       case ONOT:
-               p1 = gbranch(ABR, T, 0);
-               p2 = pc;
-               gmove(nodbool(1), res);
-               p3 = gbranch(ABR, T, 0);
-               patch(p1, pc);
-               bgen(n, 1, 0, p2);
-               gmove(nodbool(0), res);
-               patch(p3, pc);
-               goto ret;
-
-       case OPLUS:
-               cgen(nl, res);
-               goto ret;
-
-       // unary
-       case OCOM:
-               a = optoas(OXOR, nl->type);
-               regalloc(&n1, nl->type, N);
-               cgen(nl, &n1);
-               nodconst(&n2, nl->type, -1);
-               gins(a, &n2, &n1);
-               gmove(&n1, res);
-               regfree(&n1);
-               goto ret;
-
-       case OMINUS:
-               if(isfloat[nl->type->etype]) {
-                       nr = nodintconst(-1);
-                       convlit(&nr, n->type);
-                       a = optoas(OMUL, nl->type);
-                       goto sbop;
-               }
-               a = optoas(n->op, nl->type);
-               goto uop;
-
-       // symmetric binary
-       case OAND:
-       case OOR:
-       case OXOR:
-       case OADD:
-       case OMUL:
-               a = optoas(n->op, nl->type);
-               goto sbop;
-
-       // asymmetric binary
-       case OSUB:
-               a = optoas(n->op, nl->type);
-               goto abop;
-
-       case OHMUL:
-               cgen_hmul(nl, nr, res);
-               break;
-
-       case OCONV:
-               if(n->type->width > nl->type->width) {
-                       // If loading from memory, do conversion during load,
-                       // so as to avoid use of 8-bit register in, say, int(*byteptr).
-                       switch(nl->op) {
-                       case ODOT:
-                       case ODOTPTR:
-                       case OINDEX:
-                       case OIND:
-                       case ONAME:
-                               igen(nl, &n1, res);
-                               regalloc(&n2, n->type, res);
-                               gmove(&n1, &n2);
-                               gmove(&n2, res);
-                               regfree(&n2);
-                               regfree(&n1);
-                               goto ret;
-                       }
-               }
-
-               regalloc(&n1, nl->type, res);
-               regalloc(&n2, n->type, &n1);
-               cgen(nl, &n1);
-
-               // if we do the conversion n1 -> n2 here
-               // reusing the register, then gmove won't
-               // have to allocate its own register.
-               gmove(&n1, &n2);
-               gmove(&n2, res);
-               regfree(&n2);
-               regfree(&n1);
-               break;
-
-       case ODOT:
-       case ODOTPTR:
-       case OINDEX:
-       case OIND:
-       case ONAME:     // PHEAP or PPARAMREF var
-               igen(n, &n1, res);
-               gmove(&n1, res);
-               regfree(&n1);
-               break;
-       
-       case OITAB:
-               // interface table is first word of interface value
-               igen(nl, &n1, res);
-               n1.type = n->type;
-               gmove(&n1, res);
-               regfree(&n1);
-               break;
-
-       case OSPTR:
-               // pointer is the first word of string or slice.
-               if(isconst(nl, CTSTR)) {
-                       regalloc(&n1, types[tptr], res);
-                       p1 = gins(AMOVD, N, &n1);
-                       datastring(nl->val.u.sval->s, nl->val.u.sval->len, &p1->from);
-                       gmove(&n1, res);
-                       regfree(&n1);
-                       break;
-               }
-               igen(nl, &n1, res);
-               n1.type = n->type;
-               gmove(&n1, res);
-               regfree(&n1);
-               break;
-
-       case OLEN:
-               if(istype(nl->type, TMAP) || istype(nl->type, TCHAN)) {
-                       // map and chan have len in the first int-sized word.
-                       // a zero pointer means zero length
-                       regalloc(&n1, types[tptr], res);
-                       cgen(nl, &n1);
-
-                       nodconst(&n2, types[tptr], 0);
-                       gins(optoas(OCMP, types[tptr]), &n1, &n2);
-                       p1 = gbranch(optoas(OEQ, types[tptr]), T, 0);
-
-                       n2 = n1;
-                       n2.op = OINDREG;
-                       n2.type = types[simtype[TINT]];
-                       gmove(&n2, &n1);
-
-                       patch(p1, pc);
-
-                       gmove(&n1, res);
-                       regfree(&n1);
-                       break;
-               }
-               if(istype(nl->type, TSTRING) || isslice(nl->type)) {
-                       // both slice and string have len one pointer into the struct.
-                       // a zero pointer means zero length
-                       igen(nl, &n1, res);
-                       n1.type = types[simtype[TUINT]];
-                       n1.xoffset += Array_nel;
-                       gmove(&n1, res);
-                       regfree(&n1);
-                       break;
-               }
-               fatal("cgen: OLEN: unknown type %lT", nl->type);
-               break;
-
-       case OCAP:
-               if(istype(nl->type, TCHAN)) {
-                       // chan has cap in the second int-sized word.
-                       // a zero pointer means zero length
-                       regalloc(&n1, types[tptr], res);
-                       cgen(nl, &n1);
-
-                       nodconst(&n2, types[tptr], 0);
-                       gins(optoas(OCMP, types[tptr]), &n1, &n2);
-                       p1 = gbranch(optoas(OEQ, types[tptr]), T, 0);
-
-                       n2 = n1;
-                       n2.op = OINDREG;
-                       n2.xoffset = widthint;
-                       n2.type = types[simtype[TINT]];
-                       gmove(&n2, &n1);
-
-                       patch(p1, pc);
-
-                       gmove(&n1, res);
-                       regfree(&n1);
-                       break;
-               }
-               if(isslice(nl->type)) {
-                       igen(nl, &n1, res);
-                       n1.type = types[simtype[TUINT]];
-                       n1.xoffset += Array_cap;
-                       gmove(&n1, res);
-                       regfree(&n1);
-                       break;
-               }
-               fatal("cgen: OCAP: unknown type %lT", nl->type);
-               break;
-
-       case OADDR:
-               if(n->bounded) // let race detector avoid nil checks
-                       disable_checknil++;
-               agen(nl, res);
-               if(n->bounded)
-                       disable_checknil--;
-               break;
-
-       case OCALLMETH:
-               cgen_callmeth(n, 0);
-               cgen_callret(n, res);
-               break;
-
-       case OCALLINTER:
-               cgen_callinter(n, res, 0);
-               cgen_callret(n, res);
-               break;
-
-       case OCALLFUNC:
-               cgen_call(n, 0);
-               cgen_callret(n, res);
-               break;
-
-       case OMOD:
-       case ODIV:
-               if(isfloat[n->type->etype]) {
-                       a = optoas(n->op, nl->type);
-                       goto abop;
-               }
-
-               if(nl->ullman >= nr->ullman) {
-                       regalloc(&n1, nl->type, res);
-                       cgen(nl, &n1);
-                       cgen_div(n->op, &n1, nr, res);
-                       regfree(&n1);
-               } else {
-                       if(!smallintconst(nr)) {
-                               regalloc(&n2, nr->type, res);
-                               cgen(nr, &n2);
-                       } else {
-                               n2 = *nr;
-                       }
-                       cgen_div(n->op, nl, &n2, res);
-                       if(n2.op != OLITERAL)
-                               regfree(&n2);
-               }
-               break;
-
-       case OLSH:
-       case ORSH:
-       case OLROT:
-               cgen_shift(n->op, n->bounded, nl, nr, res);
-               break;
-       }
-       goto ret;
-
-sbop:  // symmetric binary
-       /*
-        * put simplest on right - we'll generate into left
-        * and then adjust it using the computation of right.
-        * constants and variables have the same ullman
-        * count, so look for constants specially.
-        *
-        * an integer constant we can use as an immediate
-        * is simpler than a variable - we can use the immediate
-        * in the adjustment instruction directly - so it goes
-        * on the right.
-        *
-        * other constants, like big integers or floating point
-        * constants, require a mov into a register, so those
-        * might as well go on the left, so we can reuse that
-        * register for the computation.
-        */
-       if(nl->ullman < nr->ullman ||
-          (nl->ullman == nr->ullman &&
-           (smallintconst(nl) || (nr->op == OLITERAL && !smallintconst(nr))))) {
-               r = nl;
-               nl = nr;
-               nr = r;
-       }
-
-abop:  // asymmetric binary
-       if(nl->ullman >= nr->ullman) {
-               regalloc(&n1, nl->type, res);
-               cgen(nl, &n1);
-       /*
-        * This generates smaller code - it avoids a MOV - but it's
-        * easily 10% slower due to not being able to
-        * optimize/manipulate the move.
-        * To see, run: go test -bench . crypto/md5
-        * with and without.
-        *
-               if(sudoaddable(a, nr, &addr)) {
-                       p1 = gins(a, N, &n1);
-                       p1->from = addr;
-                       gmove(&n1, res);
-                       sudoclean();
-                       regfree(&n1);
-                       goto ret;
-               }
-        *
-        */
-               // TODO(minux): enable using constants directly in certain instructions.
-               //if(smallintconst(nr))
-               //      n2 = *nr;
-               //else {
-                       regalloc(&n2, nr->type, N);
-                       cgen(nr, &n2);
-               //}
-       } else {
-               //if(smallintconst(nr))
-               //      n2 = *nr;
-               //else {
-                       regalloc(&n2, nr->type, res);
-                       cgen(nr, &n2);
-               //}
-               regalloc(&n1, nl->type, N);
-               cgen(nl, &n1);
-       }
-       gins(a, &n2, &n1);
-       // Normalize result for types smaller than word.
-       if(n->type->width < widthreg) {
-               switch(n->op) {
-               case OADD:
-               case OSUB:
-               case OMUL:
-               case OLSH:
-                       gins(optoas(OAS, n->type), &n1, &n1);
-                       break;
-               }
-       }
-       gmove(&n1, res);
-       regfree(&n1);
-       if(n2.op != OLITERAL)
-               regfree(&n2);
-       goto ret;
-
-uop:   // unary
-       regalloc(&n1, nl->type, res);
-       cgen(nl, &n1);
-       gins(a, N, &n1);
-       gmove(&n1, res);
-       regfree(&n1);
-       goto ret;
-
-ret:
-       ;
-}
-
-/*
- * allocate a register (reusing res if possible) and generate
- *  a = n
- * The caller must call regfree(a).
- */
-void
-cgenr(Node *n, Node *a, Node *res)
-{
-       Node n1;
-
-       if(debug['g'])
-               dump("cgenr-n", n);
-
-       if(isfat(n->type))
-               fatal("cgenr on fat node");
-
-       if(n->addable) {
-               regalloc(a, n->type, res);
-               gmove(n, a);
-               return;
-       }
-
-       switch(n->op) {
-       case ONAME:
-       case ODOT:
-       case ODOTPTR:
-       case OINDEX:
-       case OCALLFUNC:
-       case OCALLMETH:
-       case OCALLINTER:
-               igen(n, &n1, res);
-               regalloc(a, types[tptr], &n1);
-               gmove(&n1, a);
-               regfree(&n1);
-               break;
-       default:
-               regalloc(a, n->type, res);
-               cgen(n, a);
-               break;
-       }
-}
-
-/*
- * allocate a register (reusing res if possible) and generate
- * a = &n
- * The caller must call regfree(a).
- * The generated code checks that the result is not nil.
- */
-void
-agenr(Node *n, Node *a, Node *res)
-{
-       Node *nl, *nr;
-       Node n1, n2, n3, n4, tmp;
-       Prog *p1, *p2;
-       uint32 w;
-       uint64 v;
-
-       if(debug['g'])
-               dump("agenr-n", n);
-
-       nl = n->left;
-       nr = n->right;
-
-       switch(n->op) {
-       case ODOT:
-       case ODOTPTR:
-       case OCALLFUNC:
-       case OCALLMETH:
-       case OCALLINTER:
-               igen(n, &n1, res);
-               regalloc(a, types[tptr], &n1);
-               agen(&n1, a);
-               regfree(&n1);
-               break;
-
-       case OIND:
-               cgenr(n->left, a, res);
-               cgen_checknil(a);
-               break;
-
-       case OINDEX:
-               p2 = nil;  // to be patched to panicindex.
-               w = n->type->width;
-               //bounded = debug['B'] || n->bounded;
-               if(nr->addable) {
-                       if(!isconst(nr, CTINT))
-                               tempname(&tmp, types[TINT64]);
-                       if(!isconst(nl, CTSTR))
-                               agenr(nl, &n3, res);
-                       if(!isconst(nr, CTINT)) {
-                               cgen(nr, &tmp);
-                               regalloc(&n1, tmp.type, N);
-                               gmove(&tmp, &n1);
-                       }
-               } else if(nl->addable) {
-                       if(!isconst(nr, CTINT)) {
-                               tempname(&tmp, types[TINT64]);
-                               cgen(nr, &tmp);
-                               regalloc(&n1, tmp.type, N);
-                               gmove(&tmp, &n1);
-                       }
-                       if(!isconst(nl, CTSTR)) {
-                               agenr(nl, &n3, res);
-                       }
-               } else {
-                       tempname(&tmp, types[TINT64]);
-                       cgen(nr, &tmp);
-                       nr = &tmp;
-                       if(!isconst(nl, CTSTR))
-                               agenr(nl, &n3, res);
-                       regalloc(&n1, tmp.type, N);
-                       gins(optoas(OAS, tmp.type), &tmp, &n1);
-               }
-
-               // &a is in &n3 (allocated in res)
-               // i is in &n1 (if not constant)
-               // w is width
-
-               // constant index
-               if(isconst(nr, CTINT)) {
-                       if(isconst(nl, CTSTR))
-                               fatal("constant string constant index");
-                       v = mpgetfix(nr->val.u.xval);
-                       if(isslice(nl->type) || nl->type->etype == TSTRING) {
-                               if(!debug['B'] && !n->bounded) {
-                                       n1 = n3;
-                                       n1.op = OINDREG;
-                                       n1.type = types[tptr];
-                                       n1.xoffset = Array_nel;
-                                       regalloc(&n4, n1.type, N);
-                                       gmove(&n1, &n4);
-                                       ginscon2(optoas(OCMP, types[TUINT64]), &n4, v);
-                                       regfree(&n4);
-                                       p1 = gbranch(optoas(OGT, types[TUINT64]), T, +1);
-                                       ginscall(panicindex, 0);
-                                       patch(p1, pc);
-                               }
-
-                               n1 = n3;
-                               n1.op = OINDREG;
-                               n1.type = types[tptr];
-                               n1.xoffset = Array_array;
-                               gmove(&n1, &n3);
-                       }
-
-                       if (v*w != 0) {
-                               ginscon(optoas(OADD, types[tptr]), v*w, &n3);
-                       }
-                       *a = n3;
-                       break;
-               }
-
-               regalloc(&n2, types[TINT64], &n1);                      // i
-               gmove(&n1, &n2);
-               regfree(&n1);
-
-               if(!debug['B'] && !n->bounded) {
-                       // check bounds
-                       if(isconst(nl, CTSTR)) {
-                               nodconst(&n4, types[TUINT64], nl->val.u.sval->len);
-                       } else if(isslice(nl->type) || nl->type->etype == TSTRING) {
-                               n1 = n3;
-                               n1.op = OINDREG;
-                               n1.type = types[tptr];
-                               n1.xoffset = Array_nel;
-                               regalloc(&n4, types[TUINT64], N);
-                               gmove(&n1, &n4);
-                       } else {
-                               if(nl->type->bound < (1<<15)-1)
-                                       nodconst(&n4, types[TUINT64], nl->type->bound);
-                               else {
-                                       regalloc(&n4, types[TUINT64], N);
-                                       p1 = gins(AMOVD, N, &n4);
-                                       p1->from.type = TYPE_CONST;
-                                       p1->from.offset = nl->type->bound;
-                               }
-                       }
-                       gins(optoas(OCMP, types[TUINT64]), &n2, &n4);
-                       if(n4.op == OREGISTER)
-                               regfree(&n4);
-                       p1 = gbranch(optoas(OLT, types[TUINT64]), T, +1);
-                       if(p2)
-                               patch(p2, pc);
-                       ginscall(panicindex, 0);
-                       patch(p1, pc);
-               }
-               
-               if(isconst(nl, CTSTR)) {
-                       regalloc(&n3, types[tptr], res);
-                       p1 = gins(AMOVD, N, &n3);
-                       datastring(nl->val.u.sval->s, nl->val.u.sval->len, &p1->from);
-                       p1->from.type = TYPE_ADDR;
-               } else if(isslice(nl->type) || nl->type->etype == TSTRING) {
-                       n1 = n3;
-                       n1.op = OINDREG;
-                       n1.type = types[tptr];
-                       n1.xoffset = Array_array;
-                       gmove(&n1, &n3);
-               }
-
-               if(w == 0) {
-                       // nothing to do
-               } else if(w == 1) {
-                       /* w already scaled */
-                       gins(optoas(OADD, types[tptr]), &n2, &n3);
-               } /* else if(w == 2 || w == 4 || w == 8) {
-                       // TODO(minux): scale using shift
-               } */ else {
-                       regalloc(&n4, types[TUINT64], N);
-                       nodconst(&n1, types[TUINT64], w);
-                       gmove(&n1, &n4);
-                       gins(optoas(OMUL, types[TUINT64]), &n4, &n2);
-                       gins(optoas(OADD, types[tptr]), &n2, &n3);
-                       regfree(&n4);
-               }
-
-               *a = n3;
-               regfree(&n2);
-               break;
-
-       default:
-               regalloc(a, types[tptr], res);
-               agen(n, a);
-               break;
-       }
-}
-
-static void
-ginsadd(int as, vlong off, Node *dst)
-{
-       Node n1;
-
-       regalloc(&n1, types[tptr], dst);
-       gmove(dst, &n1);
-       ginscon(as, off, &n1);
-       gmove(&n1, dst);
-       regfree(&n1);
-}
-
-/*
- * generate:
- *     res = &n;
- * The generated code checks that the result is not nil.
- */
-void
-agen(Node *n, Node *res)
-{
-       Node *nl;
-       Node n1, n2, n3;
-
-       if(debug['g']) {
-               dump("\nagen-res", res);
-               dump("agen-r", n);
-       }
-       if(n == N || n->type == T)
-               return;
-
-       while(n->op == OCONVNOP)
-               n = n->left;
-
-       if(isconst(n, CTNIL) && n->type->width > widthptr) {
-               // Use of a nil interface or nil slice.
-               // Create a temporary we can take the address of and read.
-               // The generated code is just going to panic, so it need not
-               // be terribly efficient. See issue 3670.
-               tempname(&n1, n->type);
-               gvardef(&n1);
-               clearfat(&n1);
-               regalloc(&n2, types[tptr], res);
-               memset(&n3, 0, sizeof n3);
-               n3.op = OADDR;
-               n3.left = &n1;
-               gins(AMOVD, &n3, &n2);
-               gmove(&n2, res);
-               regfree(&n2);
-               goto ret;
-       }
-               
-       if(n->addable) {
-               memset(&n1, 0, sizeof n1);
-               n1.op = OADDR;
-               n1.left = n;
-               regalloc(&n2, types[tptr], res);
-               gins(AMOVD, &n1, &n2);
-               gmove(&n2, res);
-               regfree(&n2);
-               goto ret;
-       }
-
-       nl = n->left;
-
-       switch(n->op) {
-       default:
-               fatal("agen: unknown op %+hN", n);
-               break;
-
-       case OCALLMETH:
-               // TODO(minux): 5g has this: Release res so that it is available for cgen_call.
-               // Pick it up again after the call for OCALLMETH and OCALLFUNC.
-               cgen_callmeth(n, 0);
-               cgen_aret(n, res);
-               break;
-
-       case OCALLINTER:
-               cgen_callinter(n, res, 0);
-               cgen_aret(n, res);
-               break;
-
-       case OCALLFUNC:
-               cgen_call(n, 0);
-               cgen_aret(n, res);
-               break;
-
-       case OSLICE:
-       case OSLICEARR:
-       case OSLICESTR:
-       case OSLICE3:
-       case OSLICE3ARR:
-               tempname(&n1, n->type);
-               cgen_slice(n, &n1);
-               agen(&n1, res);
-               break;
-
-       case OEFACE:
-               tempname(&n1, n->type);
-               cgen_eface(n, &n1);
-               agen(&n1, res);
-               break;
-
-       case OINDEX:
-               agenr(n, &n1, res);
-               gmove(&n1, res);
-               regfree(&n1);
-               break;
-
-       case ONAME:
-               // should only get here with names in this func.
-               if(n->funcdepth > 0 && n->funcdepth != funcdepth) {
-                       dump("bad agen", n);
-                       fatal("agen: bad ONAME funcdepth %d != %d",
-                               n->funcdepth, funcdepth);
-               }
-
-               // should only get here for heap vars or paramref
-               if(!(n->class & PHEAP) && n->class != PPARAMREF) {
-                       dump("bad agen", n);
-                       fatal("agen: bad ONAME class %#x", n->class);
-               }
-               cgen(n->heapaddr, res);
-               if(n->xoffset != 0) {
-                       ginsadd(optoas(OADD, types[tptr]), n->xoffset, res);
-               }
-               break;
-
-       case OIND:
-               cgen(nl, res);
-               cgen_checknil(res);
-               break;
-
-       case ODOT:
-               agen(nl, res);
-               if(n->xoffset != 0) {
-                       ginsadd(optoas(OADD, types[tptr]), n->xoffset, res);
-               }
-               break;
-
-       case ODOTPTR:
-               cgen(nl, res);
-               cgen_checknil(res);
-               if(n->xoffset != 0) {
-                       ginsadd(optoas(OADD, types[tptr]), n->xoffset, res);
-               }
-               break;
-       }
-
-ret:
-       ;
-}
-
-/*
- * generate:
- *     newreg = &n;
- *     res = newreg
- *
- * on exit, a has been changed to be *newreg.
- * caller must regfree(a).
- * The generated code checks that the result is not *nil.
- */
-void
-igen(Node *n, Node *a, Node *res)
-{
-       Type *fp;
-       Iter flist;
-       Node n1;
-
-       if(debug['g']) {
-               dump("\nigen-n", n);
-       }
-       switch(n->op) {
-       case ONAME:
-               if((n->class&PHEAP) || n->class == PPARAMREF)
-                       break;
-               *a = *n;
-               return;
-
-       case OINDREG:
-               // Increase the refcount of the register so that igen's caller
-               // has to call regfree.
-               if(n->val.u.reg != REGSP)
-                       reg[n->val.u.reg]++;
-               *a = *n;
-               return;
-
-       case ODOT:
-               igen(n->left, a, res);
-               a->xoffset += n->xoffset;
-               a->type = n->type;
-               fixlargeoffset(a);
-               return;
-
-       case ODOTPTR:
-               cgenr(n->left, a, res);
-               cgen_checknil(a);
-               a->op = OINDREG;
-               a->xoffset += n->xoffset;
-               a->type = n->type;
-               fixlargeoffset(a);
-               return;
-
-       case OCALLFUNC:
-       case OCALLMETH:
-       case OCALLINTER:
-               switch(n->op) {
-               case OCALLFUNC:
-                       cgen_call(n, 0);
-                       break;
-               case OCALLMETH:
-                       cgen_callmeth(n, 0);
-                       break;
-               case OCALLINTER:
-                       cgen_callinter(n, N, 0);
-                       break;
-               }
-               fp = structfirst(&flist, getoutarg(n->left->type));
-               memset(a, 0, sizeof *a);
-               a->op = OINDREG;
-               a->val.u.reg = REGSP;
-               a->addable = 1;
-               a->xoffset = fp->width + widthptr; // +widthptr: saved lr at 0(SP)
-               a->type = n->type;
-               return;
-
-       case OINDEX:
-               // Index of fixed-size array by constant can
-               // put the offset in the addressing.
-               // Could do the same for slice except that we need
-               // to use the real index for the bounds checking.
-               if(isfixedarray(n->left->type) ||
-                  (isptr[n->left->type->etype] && isfixedarray(n->left->left->type)))
-               if(isconst(n->right, CTINT)) {
-                       // Compute &a.
-                       if(!isptr[n->left->type->etype])
-                               igen(n->left, a, res);
-                       else {
-                               igen(n->left, &n1, res);
-                               cgen_checknil(&n1);
-                               regalloc(a, types[tptr], res);
-                               gmove(&n1, a);
-                               regfree(&n1);
-                               a->op = OINDREG;
-                       }
-
-                       // Compute &a[i] as &a + i*width.
-                       a->type = n->type;
-                       a->xoffset += mpgetfix(n->right->val.u.xval)*n->type->width;
-                       fixlargeoffset(a);
-                       return;
-               }
-               break;
-       }
-
-       agenr(n, a, res);
-       a->op = OINDREG;
-       a->type = n->type;
-}
-
-/*
- * generate:
- *     if(n == true) goto to;
- */
-void
-bgen(Node *n, int true, int likely, Prog *to)
-{
-       int et, a;
-       Node *nl, *nr, *l, *r;
-       Node n1, n2, tmp;
-       NodeList *ll;
-       Prog *p1, *p2;
-
-       if(debug['g']) {
-               dump("\nbgen", n);
-       }
-
-       if(n == N)
-               n = nodbool(1);
-
-       if(n->ninit != nil)
-               genlist(n->ninit);
-
-       if(n->type == T) {
-               convlit(&n, types[TBOOL]);
-               if(n->type == T)
-                       goto ret;
-       }
-
-       et = n->type->etype;
-       if(et != TBOOL) {
-               yyerror("cgen: bad type %T for %O", n->type, n->op);
-               patch(gins(AEND, N, N), to);
-               goto ret;
-       }
-       nr = N;
-
-       while(n->op == OCONVNOP) {
-               n = n->left;
-               if(n->ninit != nil)
-                       genlist(n->ninit);
-       }
-
-       switch(n->op) {
-       default:
-               regalloc(&n1, n->type, N);
-               cgen(n, &n1);
-               nodconst(&n2, n->type, 0);
-               gins(optoas(OCMP, n->type), &n1, &n2);
-               a = ABNE;
-               if(!true)
-                       a = ABEQ;
-               patch(gbranch(a, n->type, likely), to);
-               regfree(&n1);
-               goto ret;
-
-       case OLITERAL:
-               // need to ask if it is bool?
-               if(!true == !n->val.u.bval)
-                       patch(gbranch(ABR, T, likely), to);
-               goto ret;
-
-       case OANDAND:
-       case OOROR:
-               if((n->op == OANDAND) == true) {
-                       p1 = gbranch(AJMP, T, 0);
-                       p2 = gbranch(AJMP, T, 0);
-                       patch(p1, pc);
-                       bgen(n->left, !true, -likely, p2);
-                       bgen(n->right, !true, -likely, p2);
-                       p1 = gbranch(AJMP, T, 0);
-                       patch(p1, to);
-                       patch(p2, pc);
-               } else {
-                       bgen(n->left, true, likely, to);
-                       bgen(n->right, true, likely, to);
-               }
-               goto ret;
-
-       case OEQ:
-       case ONE:
-       case OLT:
-       case OGT:
-       case OLE:
-       case OGE:
-               nr = n->right;
-               if(nr == N || nr->type == T)
-                       goto ret;
-
-       case ONOT:      // unary
-               nl = n->left;
-               if(nl == N || nl->type == T)
-                       goto ret;
-               break;
-       }
-
-       switch(n->op) {
-
-       case ONOT:
-               bgen(nl, !true, likely, to);
-               goto ret;
-
-       case OEQ:
-       case ONE:
-       case OLT:
-       case OGT:
-       case OLE:
-       case OGE:
-               a = n->op;
-               if(!true) {
-                       if(isfloat[nr->type->etype]) {
-                               // brcom is not valid on floats when NaN is involved.
-                               p1 = gbranch(ABR, T, 0);
-                               p2 = gbranch(ABR, T, 0);
-                               patch(p1, pc);
-                               ll = n->ninit;   // avoid re-genning ninit
-                               n->ninit = nil;
-                               bgen(n, 1, -likely, p2);
-                               n->ninit = ll;
-                               patch(gbranch(ABR, T, 0), to);
-                               patch(p2, pc);
-                               goto ret;
-                       }
-                       a = brcom(a);
-                       true = !true;
-               }
-
-               // make simplest on right
-               if(nl->op == OLITERAL || (nl->ullman < nr->ullman && nl->ullman < UINF)) {
-                       a = brrev(a);
-                       r = nl;
-                       nl = nr;
-                       nr = r;
-               }
-
-               if(isslice(nl->type)) {
-                       // front end should only leave cmp to literal nil
-                       if((a != OEQ && a != ONE) || nr->op != OLITERAL) {
-                               yyerror("illegal slice comparison");
-                               break;
-                       }
-                       a = optoas(a, types[tptr]);
-                       igen(nl, &n1, N);
-                       n1.xoffset += Array_array;
-                       n1.type = types[tptr];
-                       nodconst(&tmp, types[tptr], 0);
-                       regalloc(&n2, types[tptr], &n1);
-                       gmove(&n1, &n2);
-                       gins(optoas(OCMP, types[tptr]), &n2, &tmp);
-                       regfree(&n2);
-                       patch(gbranch(a, types[tptr], likely), to);
-                       regfree(&n1);
-                       break;
-               }
-
-               if(isinter(nl->type)) {
-                       // front end should only leave cmp to literal nil
-                       if((a != OEQ && a != ONE) || nr->op != OLITERAL) {
-                               yyerror("illegal interface comparison");
-                               break;
-                       }
-                       a = optoas(a, types[tptr]);
-                       igen(nl, &n1, N);
-                       n1.type = types[tptr];
-                       nodconst(&tmp, types[tptr], 0);
-                       regalloc(&n2, types[tptr], &n1);
-                       gmove(&n1, &n2);
-                       gins(optoas(OCMP, types[tptr]), &n2, &tmp);
-                       regfree(&n2);
-                       patch(gbranch(a, types[tptr], likely), to);
-                       regfree(&n1);
-                       break;
-               }
-               if(iscomplex[nl->type->etype]) {
-                       complexbool(a, nl, nr, true, likely, to);
-                       break;
-               }
-
-               if(nr->ullman >= UINF) {
-                       regalloc(&n1, nl->type, N);
-                       cgen(nl, &n1);
-
-                       tempname(&tmp, nl->type);
-                       gmove(&n1, &tmp);
-                       regfree(&n1);
-
-                       regalloc(&n2, nr->type, N);
-                       cgen(nr, &n2);
-
-                       regalloc(&n1, nl->type, N);
-                       cgen(&tmp, &n1);
-
-                       goto cmp;
-               }
-
-               regalloc(&n1, nl->type, N);
-               cgen(nl, &n1);
-
-               // TODO(minux): cmpi does accept 16-bit signed immediate as p->to.
-               // and cmpli accepts 16-bit unsigned immediate.
-               //if(smallintconst(nr)) {
-               //      gins(optoas(OCMP, nr->type), &n1, nr);
-               //      patch(gbranch(optoas(a, nr->type), nr->type, likely), to);
-               //      regfree(&n1);
-               //      break;
-               //}
-
-               regalloc(&n2, nr->type, N);
-               cgen(nr, &n2);
-       cmp:
-               l = &n1;
-               r = &n2;
-               gins(optoas(OCMP, nr->type), l, r);
-               if(isfloat[nr->type->etype] && (a == OLE || a == OGE)) {
-                       // To get NaN right, must rewrite x <= y into separate x < y or x = y.
-                       switch(a) {
-                       case OLE:
-                               a = OLT;
-                               break;
-                       case OGE:
-                               a = OGT;
-                               break;
-                       }
-                       patch(gbranch(optoas(a, nr->type), nr->type, likely), to);
-                       patch(gbranch(optoas(OEQ, nr->type), nr->type, likely), to);                    
-               } else {
-                       patch(gbranch(optoas(a, nr->type), nr->type, likely), to);
-               }
-               regfree(&n1);
-               regfree(&n2);
-               break;
-       }
-       goto ret;
-
-ret:
-       ;
-}
-
-/*
- * n is on stack, either local variable
- * or return value from function call.
- * return n's offset from SP.
- */
-int64
-stkof(Node *n)
-{
-       Type *t;
-       Iter flist;
-       int64 off;
-
-       switch(n->op) {
-       case OINDREG:
-               return n->xoffset;
-
-       case ODOT:
-               t = n->left->type;
-               if(isptr[t->etype])
-                       break;
-               off = stkof(n->left);
-               if(off == -1000 || off == 1000)
-                       return off;
-               return off + n->xoffset;
-
-       case OINDEX:
-               t = n->left->type;
-               if(!isfixedarray(t))
-                       break;
-               off = stkof(n->left);
-               if(off == -1000 || off == 1000)
-                       return off;
-               if(isconst(n->right, CTINT))
-                       return off + t->type->width * mpgetfix(n->right->val.u.xval);
-               return 1000;
-               
-       case OCALLMETH:
-       case OCALLINTER:
-       case OCALLFUNC:
-               t = n->left->type;
-               if(isptr[t->etype])
-                       t = t->type;
-
-               t = structfirst(&flist, getoutarg(t));
-               if(t != T)
-                       return t->width + widthptr;     // +widthptr: correct for saved LR
-               break;
-       }
-
-       // botch - probably failing to recognize address
-       // arithmetic on the above. eg INDEX and DOT
-       return -1000;
-}
-
-/*
- * block copy:
- *     memmove(&ns, &n, w);
- */
-void
-sgen(Node *n, Node *ns, int64 w)
-{
-       Node dst, src, tmp, nend;
-       int32 c, odst, osrc;
-       int dir, align, op;
-       Prog *p, *ploop;
-       NodeList *l;
-       Node *res = ns;
-
-       if(debug['g']) {
-               print("\nsgen w=%lld\n", w);
-               dump("r", n);
-               dump("res", ns);
-       }
-
-       if(n->ullman >= UINF && ns->ullman >= UINF)
-               fatal("sgen UINF");
-
-       if(w < 0)
-               fatal("sgen copy %lld", w);
-       
-       // If copying .args, that's all the results, so record definition sites
-       // for them for the liveness analysis.
-       if(ns->op == ONAME && strcmp(ns->sym->name, ".args") == 0)
-               for(l = curfn->dcl; l != nil; l = l->next)
-                       if(l->n->class == PPARAMOUT)
-                               gvardef(l->n);
-
-       // Avoid taking the address for simple enough types.
-       //if(componentgen(n, ns))
-       //      return;
-       
-       if(w == 0) {
-               // evaluate side effects only.
-               regalloc(&dst, types[tptr], N);
-               agen(res, &dst);
-               agen(n, &dst);
-               regfree(&dst);
-               return;
-       }
-
-       // determine alignment.
-       // want to avoid unaligned access, so have to use
-       // smaller operations for less aligned types.
-       // for example moving [4]byte must use 4 MOVB not 1 MOVW.
-       align = n->type->align;
-       switch(align) {
-       default:
-               fatal("sgen: invalid alignment %d for %T", align, n->type);
-       case 1:
-               op = AMOVBU;
-               break;
-       case 2:
-               op = AMOVHU;
-               break;
-       case 4:
-               op = AMOVWZU; // there is no lwau, only lwaux
-               break;
-       case 8:
-               op = AMOVDU;
-               break;
-       }
-       if(w%align)
-               fatal("sgen: unaligned size %lld (align=%d) for %T", w, align, n->type);
-       c = w / align;
-
-       // offset on the stack
-       osrc = stkof(n);
-       odst = stkof(res);
-       if(osrc != -1000 && odst != -1000 && (osrc == 1000 || odst == 1000)) {
-               // osrc and odst both on stack, and at least one is in
-               // an unknown position.  Could generate code to test
-               // for forward/backward copy, but instead just copy
-               // to a temporary location first.
-               tempname(&tmp, n->type);
-               sgen(n, &tmp, w);
-               sgen(&tmp, res, w);
-               return;
-       }
-       if(osrc%align != 0 || odst%align != 0)
-               fatal("sgen: unaligned offset src %d or dst %d (align %d)", osrc, odst, align);
-
-       // if we are copying forward on the stack and
-       // the src and dst overlap, then reverse direction
-       dir = align;
-       if(osrc < odst && odst < osrc+w)
-               dir = -dir;
-
-       if(n->ullman >= res->ullman) {
-               agenr(n, &dst, res);    // temporarily use dst
-               regalloc(&src, types[tptr], N);
-               gins(AMOVD, &dst, &src);
-               if(res->op == ONAME)
-                       gvardef(res);
-               agen(res, &dst);
-       } else {
-               if(res->op == ONAME)
-                       gvardef(res);
-               agenr(res, &dst, res);
-               agenr(n, &src, N);
-       }
-
-       regalloc(&tmp, types[tptr], N);
-
-       // set up end marker
-       memset(&nend, 0, sizeof nend);
-
-       // move src and dest to the end of block if necessary
-       if(dir < 0) {
-               if(c >= 4) {
-                       regalloc(&nend, types[tptr], N);
-                       p = gins(AMOVD, &src, &nend);
-               }
-
-               p = gins(AADD, N, &src);
-               p->from.type = TYPE_CONST;
-               p->from.offset = w;
-
-               p = gins(AADD, N, &dst);
-               p->from.type = TYPE_CONST;
-               p->from.offset = w;
-       } else {
-               p = gins(AADD, N, &src);
-               p->from.type = TYPE_CONST;
-               p->from.offset = -dir;
-
-               p = gins(AADD, N, &dst);
-               p->from.type = TYPE_CONST;
-               p->from.offset = -dir;
-
-               if(c >= 4) {
-                       regalloc(&nend, types[tptr], N);
-                       p = gins(AMOVD, &src, &nend);
-                       p->from.type = TYPE_ADDR;
-                       p->from.offset = w;
-               }
-       }
-
-
-       // move
-       // TODO: enable duffcopy for larger copies.
-       if(c >= 4) {
-               p = gins(op, &src, &tmp);
-               p->from.type = TYPE_MEM;
-               p->from.offset = dir;
-               ploop = p;
-
-               p = gins(op, &tmp, &dst);
-               p->to.type = TYPE_MEM;
-               p->to.offset = dir;
-
-               p = gins(ACMP, &src, &nend);
-
-               patch(gbranch(ABNE, T, 0), ploop);
-               regfree(&nend);
-       } else {
-               // TODO(austin): Instead of generating ADD $-8,R8; ADD
-               // $-8,R7; n*(MOVDU 8(R8),R9; MOVDU R9,8(R7);) just
-               // generate the offsets directly and eliminate the
-               // ADDs.  That will produce shorter, more
-               // pipeline-able code.
-               while(c-- > 0) {
-                       p = gins(op, &src, &tmp);
-                       p->from.type = TYPE_MEM;
-                       p->from.offset = dir;
-       
-                       p = gins(op, &tmp, &dst);
-                       p->to.type = TYPE_MEM;
-                       p->to.offset = dir;
-               }
-       }
-
-       regfree(&dst);
-       regfree(&src);
-       regfree(&tmp);
-}
-
-static int
-cadable(Node *n)
-{
-       if(!n->addable) {
-               // dont know how it happens,
-               // but it does
-               return 0;
-       }
-
-       switch(n->op) {
-       case ONAME:
-               return 1;
-       }
-       return 0;
-}
-
-/*
- * copy a composite value by moving its individual components.
- * Slices, strings and interfaces are supported.
- * Small structs or arrays with elements of basic type are
- * also supported.
- * nr is N when assigning a zero value.
- * return 1 if can do, 0 if can't.
- */
-int
-componentgen(Node *nr, Node *nl)
-{
-       Node nodl, nodr, tmp;
-       Type *t;
-       int freel, freer;
-       vlong fldcount;
-       vlong loffset, roffset;
-
-       freel = 0;
-       freer = 0;
-
-       switch(nl->type->etype) {
-       default:
-               goto no;
-
-       case TARRAY:
-               t = nl->type;
-
-               // Slices are ok.
-               if(isslice(t))
-                       break;
-               // Small arrays are ok.
-               if(t->bound > 0 && t->bound <= 3 && !isfat(t->type))
-                       break;
-
-               goto no;
-
-       case TSTRUCT:
-               // Small structs with non-fat types are ok.
-               // Zero-sized structs are treated separately elsewhere.
-               fldcount = 0;
-               for(t=nl->type->type; t; t=t->down) {
-                       if(isfat(t->type))
-                               goto no;
-                       if(t->etype != TFIELD)
-                               fatal("componentgen: not a TFIELD: %lT", t);
-                       fldcount++;
-               }
-               if(fldcount == 0 || fldcount > 4)
-                       goto no;
-
-               break;
-
-       case TSTRING:
-       case TINTER:
-               break;
-       }
-
-       nodl = *nl;
-       if(!cadable(nl)) {
-               if(nr != N && !cadable(nr))
-                       goto no;
-               igen(nl, &nodl, N);
-               freel = 1;
-       }
-
-       if(nr != N) {
-               nodr = *nr;
-               if(!cadable(nr)) {
-                       igen(nr, &nodr, N);
-                       freer = 1;
-               }
-       } else {
-               // When zeroing, prepare a register containing zero.
-               nodconst(&tmp, nl->type, 0);
-               regalloc(&nodr, types[TUINT], N);
-               gmove(&tmp, &nodr);
-               freer = 1;
-       }
-       
-       // nl and nr are 'cadable' which basically means they are names (variables) now.
-       // If they are the same variable, don't generate any code, because the
-       // VARDEF we generate will mark the old value as dead incorrectly.
-       // (And also the assignments are useless.)
-       if(nr != N && nl->op == ONAME && nr->op == ONAME && nl == nr)
-               goto yes;
-
-       switch(nl->type->etype) {
-       case TARRAY:
-               // componentgen for arrays.
-               if(nl->op == ONAME)
-                       gvardef(nl);
-               t = nl->type;
-               if(!isslice(t)) {
-                       nodl.type = t->type;
-                       nodr.type = nodl.type;
-                       for(fldcount=0; fldcount < t->bound; fldcount++) {
-                               if(nr == N)
-                                       clearslim(&nodl);
-                               else
-                                       gmove(&nodr, &nodl);
-                               nodl.xoffset += t->type->width;
-                               nodr.xoffset += t->type->width;
-                       }
-                       goto yes;
-               }
-
-               // componentgen for slices.
-               nodl.xoffset += Array_array;
-               nodl.type = ptrto(nl->type->type);
-
-               if(nr != N) {
-                       nodr.xoffset += Array_array;
-                       nodr.type = nodl.type;
-               }
-               gmove(&nodr, &nodl);
-
-               nodl.xoffset += Array_nel-Array_array;
-               nodl.type = types[simtype[TUINT]];
-
-               if(nr != N) {
-                       nodr.xoffset += Array_nel-Array_array;
-                       nodr.type = nodl.type;
-               }
-               gmove(&nodr, &nodl);
-
-               nodl.xoffset += Array_cap-Array_nel;
-               nodl.type = types[simtype[TUINT]];
-
-               if(nr != N) {
-                       nodr.xoffset += Array_cap-Array_nel;
-                       nodr.type = nodl.type;
-               }
-               gmove(&nodr, &nodl);
-
-               goto yes;
-
-       case TSTRING:
-               if(nl->op == ONAME)
-                       gvardef(nl);
-               nodl.xoffset += Array_array;
-               nodl.type = ptrto(types[TUINT8]);
-
-               if(nr != N) {
-                       nodr.xoffset += Array_array;
-                       nodr.type = nodl.type;
-               }
-               gmove(&nodr, &nodl);
-
-               nodl.xoffset += Array_nel-Array_array;
-               nodl.type = types[simtype[TUINT]];
-
-               if(nr != N) {
-                       nodr.xoffset += Array_nel-Array_array;
-                       nodr.type = nodl.type;
-               }
-               gmove(&nodr, &nodl);
-
-               goto yes;
-
-       case TINTER:
-               if(nl->op == ONAME)
-                       gvardef(nl);
-               nodl.xoffset += Array_array;
-               nodl.type = ptrto(types[TUINT8]);
-
-               if(nr != N) {
-                       nodr.xoffset += Array_array;
-                       nodr.type = nodl.type;
-               }
-               gmove(&nodr, &nodl);
-
-               nodl.xoffset += Array_nel-Array_array;
-               nodl.type = ptrto(types[TUINT8]);
-
-               if(nr != N) {
-                       nodr.xoffset += Array_nel-Array_array;
-                       nodr.type = nodl.type;
-               }
-               gmove(&nodr, &nodl);
-
-               goto yes;
-
-       case TSTRUCT:
-               if(nl->op == ONAME)
-                       gvardef(nl);
-               loffset = nodl.xoffset;
-               roffset = nodr.xoffset;
-               // funarg structs may not begin at offset zero.
-               if(nl->type->etype == TSTRUCT && nl->type->funarg && nl->type->type)
-                       loffset -= nl->type->type->width;
-               if(nr != N && nr->type->etype == TSTRUCT && nr->type->funarg && nr->type->type)
-                       roffset -= nr->type->type->width;
-
-               for(t=nl->type->type; t; t=t->down) {
-                       nodl.xoffset = loffset + t->width;
-                       nodl.type = t->type;
-
-                       if(nr == N)
-                               clearslim(&nodl);
-                       else {
-                               nodr.xoffset = roffset + t->width;
-                               nodr.type = nodl.type;
-                               gmove(&nodr, &nodl);
-                       }
-               }
-               goto yes;
-       }
-
-no:
-       if(freer)
-               regfree(&nodr);
-       if(freel)
-               regfree(&nodl);
-       return 0;
-
-yes:
-       if(freer)
-               regfree(&nodr);
-       if(freel)
-               regfree(&nodl);
-       return 1;
-}
similarity index 100%
rename from src/cmd/new9g/cgen.go
rename to src/cmd/9g/cgen.go
diff --git a/src/cmd/9g/doc.go b/src/cmd/9g/doc.go
deleted file mode 100644 (file)
index 56bb143..0000000
+++ /dev/null
@@ -1,16 +0,0 @@
-// Copyright 2014 The Go Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style
-// license that can be found in the LICENSE file.
-
-// +build ignore
-
-/*
-
-9g is the version of the gc compiler for 64-bit PowerPC or Power Architecture processors.
-The $GOARCH for these tools is ppc64 (big endian) or
-ppc64le (little endian).
-
-It reads .go files and outputs .9 files. The flags are documented in ../gc/doc.go.
-
-*/
-package main
diff --git a/src/cmd/9g/galign.c b/src/cmd/9g/galign.c
deleted file mode 100644 (file)
index 74856e2..0000000
+++ /dev/null
@@ -1,94 +0,0 @@
-// Copyright 2009 The Go Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style
-// license that can be found in the LICENSE file.
-
-#include <u.h>
-#include <libc.h>
-#include "gg.h"
-
-int    thechar = '9';
-char*  thestring = "ppc64";
-LinkArch*      thelinkarch;
-
-void
-linkarchinit(void)
-{
-       thestring = getgoarch();
-       thearch.thestring = thestring;
-       if(strcmp(thestring, "ppc64le") == 0)
-               thelinkarch = &linkppc64le;
-       else
-               thelinkarch = &linkppc64;
-       thearch.thelinkarch = thelinkarch;
-}
-
-vlong MAXWIDTH = 1LL<<50;
-
-/*
- * go declares several platform-specific type aliases:
- * int, uint, float, and uintptr
- */
-Typedef        typedefs[] =
-{
-       {"int",         TINT,           TINT64},
-       {"uint",                TUINT,          TUINT64},
-       {"uintptr",     TUINTPTR,       TUINT64},
-       {0}
-};
-
-void
-betypeinit(void)
-{
-       widthptr = 8;
-       widthint = 8;
-       widthreg = 8;
-
-       listinit9();
-}
-
-void
-main(int argc, char **argv)
-{
-       thearch.thechar = thechar;
-       thearch.thestring = thestring;
-       thearch.thelinkarch = thelinkarch;
-       thearch.typedefs = typedefs;
-       thearch.REGSP = REGSP;
-       thearch.REGCTXT = REGCTXT;
-       thearch.MAXWIDTH = MAXWIDTH;
-       thearch.anyregalloc = anyregalloc;
-       thearch.betypeinit = betypeinit;
-       thearch.bgen = bgen;
-       thearch.cgen = cgen;
-       thearch.cgen_call = cgen_call;
-       thearch.cgen_callinter = cgen_callinter;
-       thearch.cgen_ret = cgen_ret;
-       thearch.clearfat = clearfat;
-       thearch.defframe = defframe;
-       thearch.excise = excise;
-       thearch.expandchecks = expandchecks;
-       thearch.gclean = gclean;
-       thearch.ginit = ginit;
-       thearch.gins = gins;
-       thearch.ginscall = ginscall;
-       thearch.igen = igen;
-       thearch.linkarchinit = linkarchinit;
-       thearch.peep = peep;
-       thearch.proginfo = proginfo;
-       thearch.regalloc = regalloc;
-       thearch.regfree = regfree;
-       thearch.regtyp = regtyp;
-       thearch.sameaddr = sameaddr;
-       thearch.smallindir = smallindir;
-       thearch.stackaddr = stackaddr;
-       thearch.excludedregs = excludedregs;
-       thearch.RtoB = RtoB;
-       thearch.FtoB = RtoB;
-       thearch.BtoR = BtoR;
-       thearch.BtoF = BtoF;
-       thearch.optoas = optoas;
-       thearch.doregbits = doregbits;
-       thearch.regnames = regnames;
-       
-       gcmain(argc, argv);
-}
similarity index 100%
rename from src/cmd/new9g/galign.go
rename to src/cmd/9g/galign.go
similarity index 100%
rename from src/cmd/new9g/gg.go
rename to src/cmd/9g/gg.go
diff --git a/src/cmd/9g/gg.h b/src/cmd/9g/gg.h
deleted file mode 100644 (file)
index 9386759..0000000
+++ /dev/null
@@ -1,169 +0,0 @@
-// Copyright 2014 The Go Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style
-// license that can be found in the LICENSE file.
-
-#ifndef        EXTERN
-#define        EXTERN  extern
-#endif
-
-#include "../gc/go.h"
-#include "../9l/9.out.h"
-
-EXTERN uchar   reg[NREG+NFREG];
-EXTERN Node*   panicdiv;
-extern vlong   unmappedzero;
-
-/*
- * ggen.c
- */
-void   compile(Node*);
-void   gen(Node*);
-Node*  lookdot(Node*, Node*, int);
-void   cgen_as(Node*, Node*);
-void   cgen_callmeth(Node*, int);
-void   cgen_callinter(Node*, Node*, int);
-void   cgen_proc(Node*, int);
-void   cgen_callret(Node*, Node*);
-void   cgen_div(int, Node*, Node*, Node*);
-void   cgen_hmul(Node*, Node*, Node*);
-void   cgen_shift(int, int, Node*, Node*, Node*);
-void   cgen_dcl(Node*);
-int    needconvert(Type*, Type*);
-void   genconv(Type*, Type*);
-void   allocparams(void);
-void   checklabels(void);
-void   ginscall(Node*, int);
-int    gen_as_init(Node*);
-
-/*
- * cgen.c
- */
-void   agen(Node*, Node*);
-void   agenr(Node*, Node*, Node*);
-void   cgenr(Node*, Node*, Node*);
-void   igen(Node*, Node*, Node*);
-vlong  fieldoffset(Type*, Node*);
-void   sgen(Node*, Node*, int64);
-void   gmove(Node*, Node*);
-Prog*  gins(int, Node*, Node*);
-void   naddr(Node*, Addr*, int);
-void   cgen_aret(Node*, Node*);
-int    componentgen(Node*, Node*);
-
-/*
- * gsubr.c
- */
-void   clearp(Prog*);
-Prog*  gbranch(int, Type*, int);
-Prog*  prog(int);
-void   gconv(int, int);
-int    conv2pt(Type*);
-vlong  convvtox(vlong, int);
-void   fnparam(Type*, int, int);
-Prog*  gop(int, Node*, Node*, Node*);
-int    optoas(int, Type*);
-void   ginit(void);
-void   gclean(void);
-void   regalloc(Node*, Type*, Node*);
-void   regfree(Node*);
-Node*  nodarg(Type*, int);
-void   nodreg(Node*, Type*, int);
-void   nodindreg(Node*, Type*, int);
-void   ginscon(int, vlong, Node*);
-void   ginscon2(int, Node*, vlong);
-void   buildtxt(void);
-Plist* newplist(void);
-int    isfat(Type*);
-void   sudoclean(void);
-int    sudoaddable(int, Node*, Addr*);
-void   afunclit(Addr*, Node*);
-void   nodfconst(Node*, Type*, Mpflt*);
-void   gtrack(Sym*);
-void   fixlargeoffset(Node *n);
-
-/*
- * cplx.c
- */
-int    complexop(Node*, Node*);
-void   complexmove(Node*, Node*);
-void   complexgen(Node*, Node*);
-
-/*
- * gobj.c
- */
-void   datastring(char*, int, Addr*);
-void   datagostring(Strlit*, Addr*);
-
-/*
- * list.c
- */
-void   listinit(void);
-
-void   zaddr(Biobuf*, Addr*, int, int);
-
-void afunclit(Addr*, Node*);
-int anyregalloc(void);
-void betypeinit(void);
-void bgen(Node*, int, int, Prog*);
-void cgen(Node*, Node*);
-void cgen_call(Node*, int);
-void cgen_callinter(Node*, Node*, int);
-void cgen_ret(Node*);
-void clearfat(Node*);
-void clearp(Prog*);
-void defframe(Prog*);
-int dgostringptr(Sym*, int, char*);
-int dgostrlitptr(Sym*, int, Strlit*);
-int dsname(Sym*, int, char*, int);
-int dsymptr(Sym*, int, Sym*, int);
-void dumpdata(void);
-void dumpit(char*, Flow*, int);
-void excise(Flow*);
-void expandchecks(Prog*);
-void fixautoused(Prog*);
-void gclean(void);
-void   gdata(Node*, Node*, int);
-void   gdatacomplex(Node*, Mpcplx*);
-void   gdatastring(Node*, Strlit*);
-void   ggloblnod(Node *nam);
-void   ggloblsym(Sym *s, int32 width, int8 flags);
-void ginit(void);
-Prog*  gins(int, Node*, Node*);
-void   ginscall(Node*, int);
-Prog*  gjmp(Prog*);
-void gtrack(Sym*);
-void   gused(Node*);
-void   igen(Node*, Node*, Node*);
-int isfat(Type*);
-void linkarchinit(void);
-void markautoused(Prog*);
-void naddr(Node*, Addr*, int);
-Plist* newplist(void);
-Node* nodarg(Type*, int);
-void patch(Prog*, Prog*);
-void proginfo(ProgInfo*, Prog*);
-void regalloc(Node*, Type*, Node*);
-void regfree(Node*);
-void regopt(Prog*);
-int regtyp(Addr*);
-int sameaddr(Addr*, Addr*);
-int smallindir(Addr*, Addr*);
-int stackaddr(Addr*);
-Prog* unpatch(Prog*);
-
-
-/*
- * reg.c
- */
-uint64 excludedregs(void);
-uint64 RtoB(int);
-uint64 FtoB(int);
-int BtoR(uint64);
-int BtoF(uint64);
-uint64 doregbits(int);
-char** regnames(int*);
-
-/*
- * peep.c
- */
-void peep(Prog*);
diff --git a/src/cmd/9g/ggen.c b/src/cmd/9g/ggen.c
deleted file mode 100644 (file)
index 7b34282..0000000
+++ /dev/null
@@ -1,965 +0,0 @@
-// Copyright 2009 The Go Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style
-// license that can be found in the LICENSE file.
-
-#undef EXTERN
-#define        EXTERN
-#include <u.h>
-#include <libc.h>
-#include "gg.h"
-#include "../gc/popt.h"
-
-static Prog *appendpp(Prog *p, int as, int ftype, int freg, vlong foffset, int ttype, int treg, vlong toffset);
-static Prog *zerorange(Prog *p, vlong frame, vlong lo, vlong hi);
-
-void
-defframe(Prog *ptxt)
-{
-       uint32 frame;
-       Prog *p;
-       vlong hi, lo;
-       NodeList *l;
-       Node *n;
-
-       // fill in argument size, stack size
-       ptxt->to.type = TYPE_TEXTSIZE;
-       ptxt->to.u.argsize = rnd(curfn->type->argwid, widthptr);
-       frame = rnd(stksize+maxarg, widthreg);
-       ptxt->to.offset = frame;
-       
-       // insert code to zero ambiguously live variables
-       // so that the garbage collector only sees initialized values
-       // when it looks for pointers.
-       p = ptxt;
-       lo = hi = 0;
-       // iterate through declarations - they are sorted in decreasing xoffset order.
-       for(l=curfn->dcl; l != nil; l = l->next) {
-               n = l->n;
-               if(!n->needzero)
-                       continue;
-               if(n->class != PAUTO)
-                       fatal("needzero class %d", n->class);
-               if(n->type->width % widthptr != 0 || n->xoffset % widthptr != 0 || n->type->width == 0)
-                       fatal("var %lN has size %d offset %d", n, (int)n->type->width, (int)n->xoffset);
-
-               if(lo != hi && n->xoffset + n->type->width >= lo - 2*widthreg) {
-                       // merge with range we already have
-                       lo = n->xoffset;
-                       continue;
-               }
-               // zero old range
-               p = zerorange(p, frame, lo, hi);
-
-               // set new range
-               hi = n->xoffset + n->type->width;
-               lo = n->xoffset;
-       }
-       // zero final range
-       zerorange(p, frame, lo, hi);
-}
-
-static Prog*
-zerorange(Prog *p, vlong frame, vlong lo, vlong hi)
-{
-       vlong cnt, i;
-       Prog *p1;
-       Node *f;
-
-       cnt = hi - lo;
-       if(cnt == 0)
-               return p;
-       if(cnt < 4*widthptr) {
-               for(i = 0; i < cnt; i += widthptr)
-                       p = appendpp(p, AMOVD, TYPE_REG, REGZERO, 0, TYPE_MEM, REGSP, 8+frame+lo+i);
-       } else if(cnt <= 128*widthptr) {
-               p = appendpp(p, AADD, TYPE_CONST, 0, 8+frame+lo-8, TYPE_REG, REGRT1, 0);
-               p->reg = REGSP;
-               p = appendpp(p, ADUFFZERO, TYPE_NONE, 0, 0, TYPE_MEM, 0, 0);
-               f = sysfunc("duffzero");
-               naddr(f, &p->to, 1);
-               afunclit(&p->to, f);
-               p->to.offset = 4*(128-cnt/widthptr);
-       } else {
-               p = appendpp(p, AMOVD, TYPE_CONST, 0, 8+frame+lo-8, TYPE_REG, REGTMP, 0);
-               p = appendpp(p, AADD, TYPE_REG, REGTMP, 0, TYPE_REG, REGRT1, 0);
-               p->reg = REGSP;
-               p = appendpp(p, AMOVD, TYPE_CONST, 0, cnt, TYPE_REG, REGTMP, 0);
-               p = appendpp(p, AADD, TYPE_REG, REGTMP, 0, TYPE_REG, REGRT2, 0);
-               p->reg = REGRT1;
-               p1 = p = appendpp(p, AMOVDU, TYPE_REG, REGZERO, 0, TYPE_MEM, REGRT1, widthptr);
-               p = appendpp(p, ACMP, TYPE_REG, REGRT1, 0, TYPE_REG, REGRT2, 0);
-               p = appendpp(p, ABNE, TYPE_NONE, 0, 0, TYPE_BRANCH, 0, 0);
-               patch(p, p1);
-       }
-       return p;
-}
-
-static Prog*
-appendpp(Prog *p, int as, int ftype, int freg, vlong foffset, int ttype, int treg, vlong toffset)
-{
-       Prog *q;
-       q = mal(sizeof(*q));
-       clearp(q);
-       q->as = as;
-       q->lineno = p->lineno;
-       q->from.type = ftype;
-       q->from.reg = freg;
-       q->from.offset = foffset;
-       q->to.type = ttype;
-       q->to.reg = treg;
-       q->to.offset = toffset;
-       q->link = p->link;
-       p->link = q;
-       return q;
-}
-
-/*
- * generate: BL reg, f
- * where both reg and f are registers.
- * On power, f must be moved to CTR first.
- */
-static void
-ginsBL(Node *reg, Node *f)
-{
-       Prog *p;
-       p = gins(AMOVD, f, N);
-       p->to.type = TYPE_REG;
-       p->to.reg = REG_CTR;
-       p = gins(ABL, reg, N);
-       p->to.type = TYPE_REG;
-       p->to.reg = REG_CTR;
-}
-
-/*
- * generate:
- *     call f
- *     proc=-1 normal call but no return
- *     proc=0  normal call
- *     proc=1  goroutine run in new proc
- *     proc=2  defer call save away stack
-  *    proc=3  normal call to C pointer (not Go func value)
- */
-void
-ginscall(Node *f, int proc)
-{
-       Prog *p;
-       Node reg, con, reg2;
-       Node r1;
-       int32 extra;
-
-       if(f->type != T) {
-               extra = 0;
-               if(proc == 1 || proc == 2)
-                       extra = 2 * widthptr;
-               setmaxarg(f->type, extra);
-       }
-
-       switch(proc) {
-       default:
-               fatal("ginscall: bad proc %d", proc);
-               break;
-
-       case 0: // normal call
-       case -1:        // normal call but no return
-               if(f->op == ONAME && f->class == PFUNC) {
-                       if(f == deferreturn) {
-                               // Deferred calls will appear to be returning to
-                               // the CALL deferreturn(SB) that we are about to emit.
-                               // However, the stack trace code will show the line
-                               // of the instruction byte before the return PC. 
-                               // To avoid that being an unrelated instruction,
-                               // insert a ppc64 NOP that we will have the right line number.
-                               // The ppc64 NOP is really or r0, r0, r0; use that description
-                               // because the NOP pseudo-instruction would be removed by
-                               // the linker.
-                               nodreg(&reg, types[TINT], REG_R0);
-                               gins(AOR, &reg, &reg);
-                       }
-                       p = gins(ABL, N, f);
-                       afunclit(&p->to, f);
-                       if(proc == -1 || noreturn(p))
-                               gins(AUNDEF, N, N);
-                       break;
-               }
-               nodreg(&reg, types[tptr], REGCTXT);
-               nodreg(&r1, types[tptr], REG_R3);
-               gmove(f, &reg);
-               reg.op = OINDREG;
-               gmove(&reg, &r1);
-               reg.op = OREGISTER;
-               ginsBL(&reg, &r1);
-               break;
-       
-       case 3: // normal call of c function pointer
-               ginsBL(N, f);
-               break;
-
-       case 1: // call in new proc (go)
-       case 2: // deferred call (defer)
-               nodconst(&con, types[TINT64], argsize(f->type));
-               nodreg(&reg, types[TINT64], REG_R3);
-               nodreg(&reg2, types[TINT64], REG_R4);
-               gmove(f, &reg);
-
-               gmove(&con, &reg2);
-               p = gins(AMOVW, &reg2, N);
-               p->to.type = TYPE_MEM;
-               p->to.reg = REGSP;
-               p->to.offset = 8;
-
-               p = gins(AMOVD, &reg, N);
-               p->to.type = TYPE_MEM;
-               p->to.reg = REGSP;
-               p->to.offset = 16;
-
-               if(proc == 1)
-                       ginscall(newproc, 0);
-               else {
-                       if(!hasdefer)
-                               fatal("hasdefer=0 but has defer");
-                       ginscall(deferproc, 0);
-               }
-
-               if(proc == 2) {
-                       nodreg(&reg, types[TINT64], REG_R3);
-                       p = gins(ACMP, &reg, N);
-                       p->to.type = TYPE_REG;
-                       p->to.reg = REG_R0;
-                       p = gbranch(ABEQ, T, +1);
-                       cgen_ret(N);
-                       patch(p, pc);
-               }
-               break;
-       }
-}
-
-/*
- * n is call to interface method.
- * generate res = n.
- */
-void
-cgen_callinter(Node *n, Node *res, int proc)
-{
-       Node *i, *f;
-       Node tmpi, nodi, nodo, nodr, nodsp;
-       Prog *p;
-
-       i = n->left;
-       if(i->op != ODOTINTER)
-               fatal("cgen_callinter: not ODOTINTER %O", i->op);
-
-       f = i->right;           // field
-       if(f->op != ONAME)
-               fatal("cgen_callinter: not ONAME %O", f->op);
-
-       i = i->left;            // interface
-
-       if(!i->addable) {
-               tempname(&tmpi, i->type);
-               cgen(i, &tmpi);
-               i = &tmpi;
-       }
-
-       genlist(n->list);               // assign the args
-
-       // i is now addable, prepare an indirected
-       // register to hold its address.
-       igen(i, &nodi, res);            // REG = &inter
-
-       nodindreg(&nodsp, types[tptr], REGSP);
-       nodsp.xoffset = widthptr;
-       if(proc != 0)
-               nodsp.xoffset += 2 * widthptr; // leave room for size & fn
-       nodi.type = types[tptr];
-       nodi.xoffset += widthptr;
-       cgen(&nodi, &nodsp);    // {8 or 24}(SP) = 8(REG) -- i.data
-
-       regalloc(&nodo, types[tptr], res);
-       nodi.type = types[tptr];
-       nodi.xoffset -= widthptr;
-       cgen(&nodi, &nodo);     // REG = 0(REG) -- i.tab
-       regfree(&nodi);
-
-       regalloc(&nodr, types[tptr], &nodo);
-       if(n->left->xoffset == BADWIDTH)
-               fatal("cgen_callinter: badwidth");
-       cgen_checknil(&nodo); // in case offset is huge
-       nodo.op = OINDREG;
-       nodo.xoffset = n->left->xoffset + 3*widthptr + 8;
-       if(proc == 0) {
-               // plain call: use direct c function pointer - more efficient
-               cgen(&nodo, &nodr);     // REG = 32+offset(REG) -- i.tab->fun[f]
-               proc = 3;
-       } else {
-               // go/defer. generate go func value.
-               p = gins(AMOVD, &nodo, &nodr);  // REG = &(32+offset(REG)) -- i.tab->fun[f]
-               p->from.type = TYPE_ADDR;
-       }
-
-       nodr.type = n->left->type;
-       ginscall(&nodr, proc);
-
-       regfree(&nodr);
-       regfree(&nodo);
-}
-
-/*
- * generate function call;
- *     proc=0  normal call
- *     proc=1  goroutine run in new proc
- *     proc=2  defer call save away stack
- */
-void
-cgen_call(Node *n, int proc)
-{
-       Type *t;
-       Node nod, afun;
-
-       if(n == N)
-               return;
-
-       if(n->left->ullman >= UINF) {
-               // if name involves a fn call
-               // precompute the address of the fn
-               tempname(&afun, types[tptr]);
-               cgen(n->left, &afun);
-       }
-
-       genlist(n->list);               // assign the args
-       t = n->left->type;
-
-       // call tempname pointer
-       if(n->left->ullman >= UINF) {
-               regalloc(&nod, types[tptr], N);
-               cgen_as(&nod, &afun);
-               nod.type = t;
-               ginscall(&nod, proc);
-               regfree(&nod);
-               return;
-       }
-
-       // call pointer
-       if(n->left->op != ONAME || n->left->class != PFUNC) {
-               regalloc(&nod, types[tptr], N);
-               cgen_as(&nod, n->left);
-               nod.type = t;
-               ginscall(&nod, proc);
-               regfree(&nod);
-               return;
-       }
-
-       // call direct
-       n->left->method = 1;
-       ginscall(n->left, proc);
-}
-
-/*
- * call to n has already been generated.
- * generate:
- *     res = return value from call.
- */
-void
-cgen_callret(Node *n, Node *res)
-{
-       Node nod;
-       Type *fp, *t;
-       Iter flist;
-
-       t = n->left->type;
-       if(t->etype == TPTR32 || t->etype == TPTR64)
-               t = t->type;
-
-       fp = structfirst(&flist, getoutarg(t));
-       if(fp == T)
-               fatal("cgen_callret: nil");
-
-       memset(&nod, 0, sizeof(nod));
-       nod.op = OINDREG;
-       nod.val.u.reg = REGSP;
-       nod.addable = 1;
-
-       nod.xoffset = fp->width + widthptr; // +widthptr: saved LR at 0(R1)
-       nod.type = fp->type;
-       cgen_as(res, &nod);
-}
-
-/*
- * call to n has already been generated.
- * generate:
- *     res = &return value from call.
- */
-void
-cgen_aret(Node *n, Node *res)
-{
-       Node nod1, nod2;
-       Type *fp, *t;
-       Iter flist;
-
-       t = n->left->type;
-       if(isptr[t->etype])
-               t = t->type;
-
-       fp = structfirst(&flist, getoutarg(t));
-       if(fp == T)
-               fatal("cgen_aret: nil");
-
-       memset(&nod1, 0, sizeof(nod1));
-       nod1.op = OINDREG;
-       nod1.val.u.reg = REGSP;
-       nod1.addable = 1;
-
-       nod1.xoffset = fp->width + widthptr; // +widthptr: saved lr at 0(SP)
-       nod1.type = fp->type;
-
-       if(res->op != OREGISTER) {
-               regalloc(&nod2, types[tptr], res);
-               agen(&nod1, &nod2);
-               gins(AMOVD, &nod2, res);
-               regfree(&nod2);
-       } else
-               agen(&nod1, res);
-}
-
-/*
- * generate return.
- * n->left is assignments to return values.
- */
-void
-cgen_ret(Node *n)
-{
-       Prog *p;
-
-       if(n != N)
-               genlist(n->list);               // copy out args
-       if(hasdefer)
-               ginscall(deferreturn, 0);
-       genlist(curfn->exit);
-       p = gins(ARET, N, N);
-       if(n != N && n->op == ORETJMP) {
-               p->to.name = NAME_EXTERN;
-               p->to.type = TYPE_ADDR;
-               p->to.sym = linksym(n->left->sym);
-       }
-}
-
-/*
- * generate division.
- * generates one of:
- *     res = nl / nr
- *     res = nl % nr
- * according to op.
- */
-void
-dodiv(int op, Node *nl, Node *nr, Node *res)
-{
-       int a, check;
-       Type *t, *t0;
-       Node tl, tr, tl2, tr2, nm1, nz, tm;
-       Prog *p1, *p2;
-
-       // Have to be careful about handling
-       // most negative int divided by -1 correctly.
-       // The hardware will generate undefined result.
-       // Also need to explicitly trap on division on zero,
-       // the hardware will silently generate undefined result.
-       // DIVW will leave unpredicable result in higher 32-bit,
-       // so always use DIVD/DIVDU.
-       t = nl->type;
-       t0 = t;
-       check = 0;
-       if(issigned[t->etype]) {
-               check = 1;
-               if(isconst(nl, CTINT) && mpgetfix(nl->val.u.xval) != -(1ULL<<(t->width*8-1)))
-                       check = 0;
-               else if(isconst(nr, CTINT) && mpgetfix(nr->val.u.xval) != -1)
-                       check = 0;
-       }
-       if(t->width < 8) {
-               if(issigned[t->etype])
-                       t = types[TINT64];
-               else
-                       t = types[TUINT64];
-               check = 0;
-       }
-
-       a = optoas(ODIV, t);
-
-       regalloc(&tl, t0, N);
-       regalloc(&tr, t0, N);
-       if(nl->ullman >= nr->ullman) {
-               cgen(nl, &tl);
-               cgen(nr, &tr);
-       } else {
-               cgen(nr, &tr);
-               cgen(nl, &tl);
-       }
-       if(t != t0) {
-               // Convert
-               tl2 = tl;
-               tr2 = tr;
-               tl.type = t;
-               tr.type = t;
-               gmove(&tl2, &tl);
-               gmove(&tr2, &tr);
-       }
-
-       // Handle divide-by-zero panic.
-       p1 = gins(optoas(OCMP, t), &tr, N);
-       p1->to.type = TYPE_REG;
-       p1->to.reg = REGZERO;
-       p1 = gbranch(optoas(ONE, t), T, +1);
-       if(panicdiv == N)
-               panicdiv = sysfunc("panicdivide");
-       ginscall(panicdiv, -1);
-       patch(p1, pc);
-
-       if(check) {
-               nodconst(&nm1, t, -1);
-               gins(optoas(OCMP, t), &tr, &nm1);
-               p1 = gbranch(optoas(ONE, t), T, +1);
-               if(op == ODIV) {
-                       // a / (-1) is -a.
-                       gins(optoas(OMINUS, t), N, &tl);
-                       gmove(&tl, res);
-               } else {
-                       // a % (-1) is 0.
-                       nodconst(&nz, t, 0);
-                       gmove(&nz, res);
-               }
-               p2 = gbranch(AJMP, T, 0);
-               patch(p1, pc);
-       }
-       p1 = gins(a, &tr, &tl);
-       if(op == ODIV) {
-               regfree(&tr);
-               gmove(&tl, res);
-       } else {
-               // A%B = A-(A/B*B)
-               regalloc(&tm, t, N);
-               // patch div to use the 3 register form
-               // TODO(minux): add gins3?
-               p1->reg = p1->to.reg;
-               p1->to.reg = tm.val.u.reg;
-               gins(optoas(OMUL, t), &tr, &tm);
-               regfree(&tr);
-               gins(optoas(OSUB, t), &tm, &tl);
-               regfree(&tm);
-               gmove(&tl, res);
-       }
-       regfree(&tl);
-       if(check)
-               patch(p2, pc);
-}
-
-/*
- * generate division according to op, one of:
- *     res = nl / nr
- *     res = nl % nr
- */
-void
-cgen_div(int op, Node *nl, Node *nr, Node *res)
-{
-       Node n1, n2, n3;
-       int w, a;
-       Magic m;
-
-       // TODO(minux): enable division by magic multiply (also need to fix longmod below)
-       //if(nr->op != OLITERAL)
-               goto longdiv;
-       w = nl->type->width*8;
-
-       // Front end handled 32-bit division. We only need to handle 64-bit.
-       // try to do division by multiply by (2^w)/d
-       // see hacker's delight chapter 10
-       switch(simtype[nl->type->etype]) {
-       default:
-               goto longdiv;
-
-       case TUINT64:
-               m.w = w;
-               m.ud = mpgetfix(nr->val.u.xval);
-               umagic(&m);
-               if(m.bad)
-                       break;
-               if(op == OMOD)
-                       goto longmod;
-
-               cgenr(nl, &n1, N);
-               nodconst(&n2, nl->type, m.um);
-               regalloc(&n3, nl->type, res);
-               cgen_hmul(&n1, &n2, &n3);
-
-               if(m.ua) {
-                       // need to add numerator accounting for overflow
-                       gins(optoas(OADD, nl->type), &n1, &n3);
-                       nodconst(&n2, nl->type, 1);
-                       gins(optoas(ORROTC, nl->type), &n2, &n3);
-                       nodconst(&n2, nl->type, m.s-1);
-                       gins(optoas(ORSH, nl->type), &n2, &n3);
-               } else {
-                       nodconst(&n2, nl->type, m.s);
-                       gins(optoas(ORSH, nl->type), &n2, &n3); // shift dx
-               }
-
-               gmove(&n3, res);
-               regfree(&n1);
-               regfree(&n3);
-               return;
-
-       case TINT64:
-               m.w = w;
-               m.sd = mpgetfix(nr->val.u.xval);
-               smagic(&m);
-               if(m.bad)
-                       break;
-               if(op == OMOD)
-                       goto longmod;
-
-               cgenr(nl, &n1, res);
-               nodconst(&n2, nl->type, m.sm);
-               regalloc(&n3, nl->type, N);
-               cgen_hmul(&n1, &n2, &n3);
-
-               if(m.sm < 0) {
-                       // need to add numerator
-                       gins(optoas(OADD, nl->type), &n1, &n3);
-               }
-
-               nodconst(&n2, nl->type, m.s);
-               gins(optoas(ORSH, nl->type), &n2, &n3); // shift n3
-
-               nodconst(&n2, nl->type, w-1);
-               gins(optoas(ORSH, nl->type), &n2, &n1); // -1 iff num is neg
-               gins(optoas(OSUB, nl->type), &n1, &n3); // added
-
-               if(m.sd < 0) {
-                       // this could probably be removed
-                       // by factoring it into the multiplier
-                       gins(optoas(OMINUS, nl->type), N, &n3);
-               }
-
-               gmove(&n3, res);
-               regfree(&n1);
-               regfree(&n3);
-               return;
-       }
-       goto longdiv;
-
-longdiv:
-       // division and mod using (slow) hardware instruction
-       dodiv(op, nl, nr, res);
-       return;
-
-longmod:
-       // mod using formula A%B = A-(A/B*B) but
-       // we know that there is a fast algorithm for A/B
-       regalloc(&n1, nl->type, res);
-       cgen(nl, &n1);
-       regalloc(&n2, nl->type, N);
-       cgen_div(ODIV, &n1, nr, &n2);
-       a = optoas(OMUL, nl->type);
-       if(w == 8) {
-               // use 2-operand 16-bit multiply
-               // because there is no 2-operand 8-bit multiply
-               //a = AIMULW;
-       }
-       if(!smallintconst(nr)) {
-               regalloc(&n3, nl->type, N);
-               cgen(nr, &n3);
-               gins(a, &n3, &n2);
-               regfree(&n3);
-       } else
-               gins(a, nr, &n2);
-       gins(optoas(OSUB, nl->type), &n2, &n1);
-       gmove(&n1, res);
-       regfree(&n1);
-       regfree(&n2);
-}
-
-/*
- * generate high multiply:
- *   res = (nl*nr) >> width
- */
-void
-cgen_hmul(Node *nl, Node *nr, Node *res)
-{
-       int w;
-       Node n1, n2, *tmp;
-       Type *t;
-       Prog *p;
-
-       // largest ullman on left.
-       if(nl->ullman < nr->ullman) {
-               tmp = nl;
-               nl = nr;
-               nr = tmp;
-       }
-       t = nl->type;
-       w = t->width * 8;
-       cgenr(nl, &n1, res);
-       cgenr(nr, &n2, N);
-       switch(simtype[t->etype]) {
-       case TINT8:
-       case TINT16:
-       case TINT32:
-               gins(optoas(OMUL, t), &n2, &n1);
-               p = gins(ASRAD, N, &n1);
-               p->from.type = TYPE_CONST;
-               p->from.offset = w;
-               break;
-       case TUINT8:
-       case TUINT16:
-       case TUINT32:
-               gins(optoas(OMUL, t), &n2, &n1);
-               p = gins(ASRD, N, &n1);
-               p->from.type = TYPE_CONST;
-               p->from.offset = w;
-               break;
-       case TINT64:
-       case TUINT64:
-               if(issigned[t->etype])
-                       p = gins(AMULHD, &n2, &n1);
-               else
-                       p = gins(AMULHDU, &n2, &n1);
-               break;
-       default:
-               fatal("cgen_hmul %T", t);
-               break;
-       }
-       cgen(&n1, res);
-       regfree(&n1);
-       regfree(&n2);
-}
-
-/*
- * generate shift according to op, one of:
- *     res = nl << nr
- *     res = nl >> nr
- */
-void
-cgen_shift(int op, int bounded, Node *nl, Node *nr, Node *res)
-{
-       Node n1, n2, n3, n4, n5;
-       int a;
-       Prog *p1;
-       uvlong sc;
-       Type *tcount;
-
-       a = optoas(op, nl->type);
-
-       if(nr->op == OLITERAL) {
-               regalloc(&n1, nl->type, res);
-               cgen(nl, &n1);
-               sc = mpgetfix(nr->val.u.xval);
-               if(sc >= nl->type->width*8) {
-                       // large shift gets 2 shifts by width-1
-                       nodconst(&n3, types[TUINT32], nl->type->width*8-1);
-                       gins(a, &n3, &n1);
-                       gins(a, &n3, &n1);
-               } else
-                       gins(a, nr, &n1);
-               gmove(&n1, res);
-               regfree(&n1);
-               goto ret;
-       }
-
-       if(nl->ullman >= UINF) {
-               tempname(&n4, nl->type);
-               cgen(nl, &n4);
-               nl = &n4;
-       }
-       if(nr->ullman >= UINF) {
-               tempname(&n5, nr->type);
-               cgen(nr, &n5);
-               nr = &n5;
-       }
-
-       // Allow either uint32 or uint64 as shift type,
-       // to avoid unnecessary conversion from uint32 to uint64
-       // just to do the comparison.
-       tcount = types[simtype[nr->type->etype]];
-       if(tcount->etype < TUINT32)
-               tcount = types[TUINT32];
-
-       regalloc(&n1, nr->type, N);             // to hold the shift type in CX
-       regalloc(&n3, tcount, &n1);     // to clear high bits of CX
-
-       regalloc(&n2, nl->type, res);
-       if(nl->ullman >= nr->ullman) {
-               cgen(nl, &n2);
-               cgen(nr, &n1);
-               gmove(&n1, &n3);
-       } else {
-               cgen(nr, &n1);
-               gmove(&n1, &n3);
-               cgen(nl, &n2);
-       }
-       regfree(&n3);
-
-       // test and fix up large shifts
-       if(!bounded) {
-               nodconst(&n3, tcount, nl->type->width*8);
-               gins(optoas(OCMP, tcount), &n1, &n3);
-               p1 = gbranch(optoas(OLT, tcount), T, +1);
-               if(op == ORSH && issigned[nl->type->etype]) {
-                       nodconst(&n3, types[TUINT32], nl->type->width*8-1);
-                       gins(a, &n3, &n2);
-               } else {
-                       nodconst(&n3, nl->type, 0);
-                       gmove(&n3, &n2);
-               }
-               patch(p1, pc);
-       }
-
-       gins(a, &n1, &n2);
-
-       gmove(&n2, res);
-
-       regfree(&n1);
-       regfree(&n2);
-
-ret:
-       ;
-}
-
-void
-clearfat(Node *nl)
-{
-       uint64 w, c, q, t, boff;
-       Node dst, end, r0, *f;
-       Prog *p, *pl;
-
-       /* clear a fat object */
-       if(debug['g']) {
-               print("clearfat %N (%T, size: %lld)\n", nl, nl->type, nl->type->width);
-       }
-
-       w = nl->type->width;
-       // Avoid taking the address for simple enough types.
-       //if(componentgen(N, nl))
-       //      return;
-
-       c = w % 8;      // bytes
-       q = w / 8;      // dwords
-
-       if(reg[REGRT1] > 0)
-               fatal("R%d in use during clearfat", REGRT1);
-
-       nodreg(&r0, types[TUINT64], REG_R0); // r0 is always zero
-       nodreg(&dst, types[tptr], REGRT1);
-       reg[REGRT1]++;
-       agen(nl, &dst);
-
-       if(q > 128) {
-               p = gins(ASUB, N, &dst);
-               p->from.type = TYPE_CONST;
-               p->from.offset = 8;
-
-               regalloc(&end, types[tptr], N);
-               p = gins(AMOVD, &dst, &end);
-               p->from.type = TYPE_ADDR;
-               p->from.offset = q*8;
-
-               p = gins(AMOVDU, &r0, &dst);
-               p->to.type = TYPE_MEM;
-               p->to.offset = 8;
-               pl = p;
-
-               p = gins(ACMP, &dst, &end);
-               patch(gbranch(ABNE, T, 0), pl);
-
-               regfree(&end);
-               // The loop leaves R3 on the last zeroed dword
-               boff = 8;
-       } else if(q >= 4) {
-               p = gins(ASUB, N, &dst);
-               p->from.type = TYPE_CONST;
-               p->from.offset = 8;
-               f = sysfunc("duffzero");
-               p = gins(ADUFFZERO, N, f);
-               afunclit(&p->to, f);
-               // 4 and 128 = magic constants: see ../../runtime/asm_ppc64x.s
-               p->to.offset = 4*(128-q);
-               // duffzero leaves R3 on the last zeroed dword
-               boff = 8;
-       } else {
-               for(t = 0; t < q; t++) {
-                       p = gins(AMOVD, &r0, &dst);
-                       p->to.type = TYPE_MEM;
-                       p->to.offset = 8*t;
-               }
-               boff = 8*q;
-       }
-
-       for(t = 0; t < c; t++) {
-               p = gins(AMOVB, &r0, &dst);
-               p->to.type = TYPE_MEM;
-               p->to.offset = t+boff;
-       }
-       reg[REGRT1]--;
-}
-
-// Called after regopt and peep have run.
-// Expand CHECKNIL pseudo-op into actual nil pointer check.
-void
-expandchecks(Prog *firstp)
-{
-       Prog *p, *p1, *p2;
-
-       for(p = firstp; p != P; p = p->link) {
-               if(debug_checknil && ctxt->debugvlog)
-                       print("expandchecks: %P\n", p);
-               if(p->as != ACHECKNIL)
-                       continue;
-               if(debug_checknil && p->lineno > 1) // p->lineno==1 in generated wrappers
-                       warnl(p->lineno, "generated nil check");
-               if(p->from.type != TYPE_REG)
-                       fatal("invalid nil check %P\n", p);
-               /*
-               // check is
-               //      TD $4, R0, arg (R0 is always zero)
-               // eqv. to:
-               //      tdeq r0, arg
-               // NOTE: this needs special runtime support to make SIGTRAP recoverable.
-               reg = p->from.reg;
-               p->as = ATD;
-               p->from = p->to = p->from3 = zprog.from;
-               p->from.type = TYPE_CONST;
-               p->from.offset = 4;
-               p->from.reg = 0;
-               p->reg = REG_R0;
-               p->to.type = TYPE_REG;
-               p->to.reg = reg;
-               */
-               // check is
-               //      CMP arg, R0
-               //      BNE 2(PC) [likely]
-               //      MOVD R0, 0(R0)
-               p1 = mal(sizeof *p1);
-               p2 = mal(sizeof *p2);
-               clearp(p1);
-               clearp(p2);
-               p1->link = p2;
-               p2->link = p->link;
-               p->link = p1;
-               p1->lineno = p->lineno;
-               p2->lineno = p->lineno;
-               p1->pc = 9999;
-               p2->pc = 9999;
-               p->as = ACMP;
-               p->to.type = TYPE_REG;
-               p->to.reg = REGZERO;
-               p1->as = ABNE;
-               //p1->from.type = TYPE_CONST;
-               //p1->from.offset = 1; // likely
-               p1->to.type = TYPE_BRANCH;
-               p1->to.u.branch = p2->link;
-               // crash by write to memory address 0.
-               p2->as = AMOVD;
-               p2->from.type = TYPE_REG;
-               p2->from.reg = REG_R0;
-               p2->to.type = TYPE_MEM;
-               p2->to.reg = REG_R0;
-               p2->to.offset = 0;
-       }
-}
similarity index 100%
rename from src/cmd/new9g/ggen.go
rename to src/cmd/9g/ggen.go
diff --git a/src/cmd/9g/gsubr.c b/src/cmd/9g/gsubr.c
deleted file mode 100644 (file)
index 1fb1511..0000000
+++ /dev/null
@@ -1,1158 +0,0 @@
-// Derived from Inferno utils/6c/txt.c
-// http://code.google.com/p/inferno-os/source/browse/utils/6c/txt.c
-//
-//     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 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 <u.h>
-#include <libc.h>
-#include "gg.h"
-#include "../../runtime/funcdata.h"
-
-// TODO(rsc): Can make this bigger if we move
-// the text segment up higher in 6l for all GOOS.
-// At the same time, can raise StackBig in ../../runtime/stack.h.
-vlong unmappedzero = 4096;
-
-static int     resvd[] =
-{
-       REGZERO,
-       REGSP,  // reserved for SP
-       // We need to preserve the C ABI TLS pointer because sigtramp
-       // may happen during C code and needs to access the g.  C
-       // clobbers REGG, so if Go were to clobber REGTLS, sigtramp
-       // won't know which convention to use.  By preserving REGTLS,
-       // we can just retrieve g from TLS when we aren't sure.
-       REGTLS,
-       // TODO(austin): Consolidate REGTLS and REGG?
-       REGG,
-       REGTMP, // REGTMP
-       FREGCVI,
-       FREGZERO,
-       FREGHALF,
-       FREGONE,
-       FREGTWO,
-};
-
-void
-ginit(void)
-{
-       int i;
-
-       for(i=0; i<nelem(reg); i++)
-               reg[i] = 1;
-       for(i=0; i<NREG+NFREG; i++)
-               reg[i] = 0;
-
-       for(i=0; i<nelem(resvd); i++)
-               reg[resvd[i] - REG_R0]++;
-}
-
-static uintptr regpc[nelem(reg)];
-
-void
-gclean(void)
-{
-       int i;
-
-       for(i=0; i<nelem(resvd); i++)
-               reg[resvd[i] - REG_R0]--;
-
-       for(i=0; i<nelem(reg); i++)
-               if(reg[i])
-                       yyerror("reg %R left allocated, %p\n", i+REG_R0, regpc[i]);
-}
-
-int
-anyregalloc(void)
-{
-       int i, j;
-
-       for(i=0; i<nelem(reg); i++) {
-               if(reg[i] == 0)
-                       goto ok;
-               for(j=0; j<nelem(resvd); j++)
-                       if(resvd[j] == i)
-                               goto ok;
-               return 1;
-       ok:;
-       }
-       return 0;
-}
-
-/*
- * allocate register of type t, leave in n.
- * if o != N, o is desired fixed register.
- * caller must regfree(n).
- */
-void
-regalloc(Node *n, Type *t, Node *o)
-{
-       int i, et;
-       int fixfree, fltfree;
-
-       if(t == T)
-               fatal("regalloc: t nil");
-       et = simtype[t->etype];
-
-       if(debug['r']) {
-               fixfree = 0;
-               fltfree = 0;
-               for(i = REG_R0; i < REG_F31; i++)
-                       if(reg[i - REG_R0] == 0) {
-                               if(i < REG_F0)
-                                       fixfree++;
-                               else
-                                       fltfree++;
-                       }
-               print("regalloc fix %d flt %d free\n", fixfree, fltfree);
-       }
-
-       switch(et) {
-       case TINT8:
-       case TUINT8:
-       case TINT16:
-       case TUINT16:
-       case TINT32:
-       case TUINT32:
-       case TINT64:
-       case TUINT64:
-       case TPTR32:
-       case TPTR64:
-       case TBOOL:
-               if(o != N && o->op == OREGISTER) {
-                       i = o->val.u.reg;
-                       if(i >= REGMIN && i <= REGMAX)
-                               goto out;
-               }
-               for(i=REGMIN; i<=REGMAX; i++)
-                       if(reg[i - REG_R0] == 0) {
-                               regpc[i - REG_R0] = (uintptr)getcallerpc(&n);
-                               goto out;
-                       }
-               flusherrors();
-               for(i=REG_R0; i<REG_R0+NREG; i++)
-                       print("R%d %p\n", i, regpc[i - REG_R0]);
-               fatal("out of fixed registers");
-
-       case TFLOAT32:
-       case TFLOAT64:
-               if(o != N && o->op == OREGISTER) {
-                       i = o->val.u.reg;
-                       if(i >= FREGMIN && i <= FREGMAX)
-                               goto out;
-               }
-               for(i=FREGMIN; i<=FREGMAX; i++)
-                       if(reg[i - REG_R0] == 0) {
-                               regpc[i - REG_R0] = (uintptr)getcallerpc(&n);
-                               goto out;
-                       }
-               flusherrors();
-               for(i=REG_F0; i<REG_F0+NREG; i++)
-                       print("F%d %p\n", i, regpc[i - REG_R0]);
-               fatal("out of floating registers");
-
-       case TCOMPLEX64:
-       case TCOMPLEX128:
-               tempname(n, t);
-               return;
-       }
-       fatal("regalloc: unknown type %T", t);
-       return;
-
-out:
-       reg[i - REG_R0]++;
-       nodreg(n, t, i);
-}
-
-void
-regfree(Node *n)
-{
-       int i;
-
-       if(n->op == ONAME)
-               return;
-       if(n->op != OREGISTER && n->op != OINDREG)
-               fatal("regfree: not a register");
-       i = n->val.u.reg - REG_R0;
-       if(i == REGSP - REG_R0)
-               return;
-       if(i < 0 || i >= nelem(reg))
-               fatal("regfree: reg out of range");
-       if(reg[i] <= 0)
-               fatal("regfree: reg not allocated");
-       reg[i]--;
-       if(reg[i] == 0)
-               regpc[i] = 0;
-}
-
-/*
- * generate
- *     as $c, n
- */
-void
-ginscon(int as, vlong c, Node *n2)
-{
-       Node n1, ntmp;
-
-       nodconst(&n1, types[TINT64], c);
-
-       if(as != AMOVD && (c < -BIG || c > BIG)) {
-               // cannot have more than 16-bit of immediate in ADD, etc.
-               // instead, MOV into register first.
-               regalloc(&ntmp, types[TINT64], N);
-               gins(AMOVD, &n1, &ntmp);
-               gins(as, &ntmp, n2);
-               regfree(&ntmp);
-               return;
-       }
-       gins(as, &n1, n2);
-}
-
-/*
- * generate
- *     as n, $c (CMP/CMPU)
- */
-void
-ginscon2(int as, Node *n2, vlong c)
-{
-       Node n1, ntmp;
-
-       nodconst(&n1, types[TINT64], c);
-
-       switch(as) {
-       default:
-               fatal("ginscon2");
-       case ACMP:
-               if(-BIG <= c && c <= BIG) {
-                       gins(as, n2, &n1);
-                       return;
-               }
-               break;
-       case ACMPU:
-               if(0 <= c && c <= 2*BIG) {
-                       gins(as, n2, &n1);
-                       return;
-               }
-               break;
-       }
-       // MOV n1 into register first
-       regalloc(&ntmp, types[TINT64], N);
-       gins(AMOVD, &n1, &ntmp);
-       gins(as, n2, &ntmp);
-       regfree(&ntmp);
-}
-
-#define        CASE(a,b)       (((a)<<16)|((b)<<0))
-/*c2go int CASE(int, int); */
-
-/*
- * set up nodes representing 2^63
- */
-Node bigi;
-Node bigf;
-
-void
-bignodes(void)
-{
-       static int did;
-
-       if(did)
-               return;
-       did = 1;
-
-       nodconst(&bigi, types[TUINT64], 1);
-       mpshiftfix(bigi.val.u.xval, 63);
-
-       bigf = bigi;
-       bigf.type = types[TFLOAT64];
-       bigf.val.ctype = CTFLT;
-       bigf.val.u.fval = mal(sizeof *bigf.val.u.fval);
-       mpmovefixflt(bigf.val.u.fval, bigi.val.u.xval);
-}
-
-/*
- * generate move:
- *     t = f
- * hard part is conversions.
- */
-void
-gmove(Node *f, Node *t)
-{
-       int a, ft, tt;
-       Type *cvt;
-       Node r1, r2, r3, con;
-       Prog *p1, *p2;
-
-       if(debug['M'])
-               print("gmove %lN -> %lN\n", f, t);
-
-       ft = simsimtype(f->type);
-       tt = simsimtype(t->type);
-       cvt = t->type;
-
-       if(iscomplex[ft] || iscomplex[tt]) {
-               complexmove(f, t);
-               return;
-       }
-
-       // cannot have two memory operands
-       if(ismem(f) && ismem(t))
-               goto hard;
-
-       // convert constant to desired type
-       if(f->op == OLITERAL) {
-               switch(tt) {
-               default:
-                       convconst(&con, t->type, &f->val);
-                       break;
-
-               case TINT32:
-               case TINT16:
-               case TINT8:
-                       convconst(&con, types[TINT64], &f->val);
-                       regalloc(&r1, con.type, t);
-                       gins(AMOVD, &con, &r1);
-                       gmove(&r1, t);
-                       regfree(&r1);
-                       return;
-
-               case TUINT32:
-               case TUINT16:
-               case TUINT8:
-                       convconst(&con, types[TUINT64], &f->val);
-                       regalloc(&r1, con.type, t);
-                       gins(AMOVD, &con, &r1);
-                       gmove(&r1, t);
-                       regfree(&r1);
-                       return;
-               }
-
-               f = &con;
-               ft = tt;        // so big switch will choose a simple mov
-
-               // constants can't move directly to memory.
-               if(ismem(t)) {
-                       goto hard;
-                       // float constants come from memory.
-                       //if(isfloat[tt])
-                       //      goto hard;
-
-                       // 64-bit immediates are also from memory.
-                       //if(isint[tt])
-                       //      goto hard;
-                       //// 64-bit immediates are really 32-bit sign-extended
-                       //// unless moving into a register.
-                       //if(isint[tt]) {
-                       //      if(mpcmpfixfix(con.val.u.xval, minintval[TINT32]) < 0)
-                       //              goto hard;
-                       //      if(mpcmpfixfix(con.val.u.xval, maxintval[TINT32]) > 0)
-                       //              goto hard;
-                       //}
-               }
-       }
-
-       // value -> value copy, only one memory operand.
-       // figure out the instruction to use.
-       // break out of switch for one-instruction gins.
-       // goto rdst for "destination must be register".
-       // goto hard for "convert to cvt type first".
-       // otherwise handle and return.
-
-       switch(CASE(ft, tt)) {
-       default:
-               fatal("gmove %lT -> %lT", f->type, t->type);
-
-       /*
-        * integer copy and truncate
-        */
-       case CASE(TINT8, TINT8):        // same size
-       case CASE(TUINT8, TINT8):
-       case CASE(TINT16, TINT8):       // truncate
-       case CASE(TUINT16, TINT8):
-       case CASE(TINT32, TINT8):
-       case CASE(TUINT32, TINT8):
-       case CASE(TINT64, TINT8):
-       case CASE(TUINT64, TINT8):
-               a = AMOVB;
-               break;
-
-       case CASE(TINT8, TUINT8):       // same size
-       case CASE(TUINT8, TUINT8):
-       case CASE(TINT16, TUINT8):      // truncate
-       case CASE(TUINT16, TUINT8):
-       case CASE(TINT32, TUINT8):
-       case CASE(TUINT32, TUINT8):
-       case CASE(TINT64, TUINT8):
-       case CASE(TUINT64, TUINT8):
-               a = AMOVBZ;
-               break;
-
-       case CASE(TINT16, TINT16):      // same size
-       case CASE(TUINT16, TINT16):
-       case CASE(TINT32, TINT16):      // truncate
-       case CASE(TUINT32, TINT16):
-       case CASE(TINT64, TINT16):
-       case CASE(TUINT64, TINT16):
-               a = AMOVH;
-               break;
-
-       case CASE(TINT16, TUINT16):     // same size
-       case CASE(TUINT16, TUINT16):
-       case CASE(TINT32, TUINT16):     // truncate
-       case CASE(TUINT32, TUINT16):
-       case CASE(TINT64, TUINT16):
-       case CASE(TUINT64, TUINT16):
-               a = AMOVHZ;
-               break;
-
-       case CASE(TINT32, TINT32):      // same size
-       case CASE(TUINT32, TINT32):
-       case CASE(TINT64, TINT32):      // truncate
-       case CASE(TUINT64, TINT32):
-               a = AMOVW;
-               break;
-
-       case CASE(TINT32, TUINT32):     // same size
-       case CASE(TUINT32, TUINT32):
-       case CASE(TINT64, TUINT32):
-       case CASE(TUINT64, TUINT32):
-               a = AMOVWZ;
-               break;
-
-       case CASE(TINT64, TINT64):      // same size
-       case CASE(TINT64, TUINT64):
-       case CASE(TUINT64, TINT64):
-       case CASE(TUINT64, TUINT64):
-               a = AMOVD;
-               break;
-
-       /*
-        * integer up-conversions
-        */
-       case CASE(TINT8, TINT16):       // sign extend int8
-       case CASE(TINT8, TUINT16):
-       case CASE(TINT8, TINT32):
-       case CASE(TINT8, TUINT32):
-       case CASE(TINT8, TINT64):
-       case CASE(TINT8, TUINT64):
-               a = AMOVB;
-               goto rdst;
-
-       case CASE(TUINT8, TINT16):      // zero extend uint8
-       case CASE(TUINT8, TUINT16):
-       case CASE(TUINT8, TINT32):
-       case CASE(TUINT8, TUINT32):
-       case CASE(TUINT8, TINT64):
-       case CASE(TUINT8, TUINT64):
-               a = AMOVBZ;
-               goto rdst;
-
-       case CASE(TINT16, TINT32):      // sign extend int16
-       case CASE(TINT16, TUINT32):
-       case CASE(TINT16, TINT64):
-       case CASE(TINT16, TUINT64):
-               a = AMOVH;
-               goto rdst;
-
-       case CASE(TUINT16, TINT32):     // zero extend uint16
-       case CASE(TUINT16, TUINT32):
-       case CASE(TUINT16, TINT64):
-       case CASE(TUINT16, TUINT64):
-               a = AMOVHZ;
-               goto rdst;
-
-       case CASE(TINT32, TINT64):      // sign extend int32
-       case CASE(TINT32, TUINT64):
-               a = AMOVW;
-               goto rdst;
-
-       case CASE(TUINT32, TINT64):     // zero extend uint32
-       case CASE(TUINT32, TUINT64):
-               a = AMOVWZ;
-               goto rdst;
-
-       /*
-       * float to integer
-       */
-       case CASE(TFLOAT32, TINT32):
-       case CASE(TFLOAT64, TINT32):
-       case CASE(TFLOAT32, TINT64):
-       case CASE(TFLOAT64, TINT64):
-       case CASE(TFLOAT32, TINT16):
-       case CASE(TFLOAT32, TINT8):
-       case CASE(TFLOAT32, TUINT16):
-       case CASE(TFLOAT32, TUINT8):
-       case CASE(TFLOAT64, TINT16):
-       case CASE(TFLOAT64, TINT8):
-       case CASE(TFLOAT64, TUINT16):
-       case CASE(TFLOAT64, TUINT8):
-       case CASE(TFLOAT32, TUINT32):
-       case CASE(TFLOAT64, TUINT32):
-       case CASE(TFLOAT32, TUINT64):
-       case CASE(TFLOAT64, TUINT64):
-               //warn("gmove: convert float to int not implemented: %N -> %N\n", f, t);
-               //return;
-               // algorithm is:
-               //      if small enough, use native float64 -> int64 conversion.
-               //      otherwise, subtract 2^63, convert, and add it back.
-               bignodes();
-               regalloc(&r1, types[ft], f);
-               gmove(f, &r1);
-               if(tt == TUINT64) {
-                       regalloc(&r2, types[TFLOAT64], N);
-                       gmove(&bigf, &r2);
-                       gins(AFCMPU, &r1, &r2);
-                       p1 = gbranch(optoas(OLT, types[TFLOAT64]), T, +1);
-                       gins(AFSUB, &r2, &r1);
-                       patch(p1, pc);
-                       regfree(&r2);
-               }
-               regalloc(&r2, types[TFLOAT64], N);
-               regalloc(&r3, types[TINT64], t);
-               gins(AFCTIDZ, &r1, &r2);
-               p1 = gins(AFMOVD, &r2, N);
-               p1->to.type = TYPE_MEM;
-               p1->to.reg = REGSP;
-               p1->to.offset = -8;
-               p1 = gins(AMOVD, N, &r3);
-               p1->from.type = TYPE_MEM;
-               p1->from.reg = REGSP;
-               p1->from.offset = -8;
-               regfree(&r2);
-               regfree(&r1);
-               if(tt == TUINT64) {
-                       p1 = gbranch(optoas(OLT, types[TFLOAT64]), T, +1); // use CR0 here again
-                       nodreg(&r1, types[TINT64], REGTMP);
-                       gins(AMOVD, &bigi, &r1);
-                       gins(AADD, &r1, &r3);
-                       patch(p1, pc);
-               }
-               gmove(&r3, t);
-               regfree(&r3);
-               return;
-
-       /*
-        * integer to float
-        */
-       case CASE(TINT32, TFLOAT32):
-       case CASE(TINT32, TFLOAT64):
-       case CASE(TINT64, TFLOAT32):
-       case CASE(TINT64, TFLOAT64):
-       case CASE(TINT16, TFLOAT32):
-       case CASE(TINT16, TFLOAT64):
-       case CASE(TINT8, TFLOAT32):
-       case CASE(TINT8, TFLOAT64):
-       case CASE(TUINT16, TFLOAT32):
-       case CASE(TUINT16, TFLOAT64):
-       case CASE(TUINT8, TFLOAT32):
-       case CASE(TUINT8, TFLOAT64):
-       case CASE(TUINT32, TFLOAT32):
-       case CASE(TUINT32, TFLOAT64):
-       case CASE(TUINT64, TFLOAT32):
-       case CASE(TUINT64, TFLOAT64):
-               //warn("gmove: convert int to float not implemented: %N -> %N\n", f, t);
-               //return;
-               // algorithm is:
-               //      if small enough, use native int64 -> uint64 conversion.
-               //      otherwise, halve (rounding to odd?), convert, and double.
-               bignodes();
-               regalloc(&r1, types[TINT64], N);
-               gmove(f, &r1);
-               if(ft == TUINT64) {
-                       nodreg(&r2, types[TUINT64], REGTMP);
-                       gmove(&bigi, &r2);
-                       gins(ACMPU, &r1, &r2);
-                       p1 = gbranch(optoas(OLT, types[TUINT64]), T, +1);
-                       p2 = gins(ASRD, N, &r1);
-                       p2->from.type = TYPE_CONST;
-                       p2->from.offset = 1;
-                       patch(p1, pc);
-               }
-               regalloc(&r2, types[TFLOAT64], t);
-               p1 = gins(AMOVD, &r1, N);
-               p1->to.type = TYPE_MEM;
-               p1->to.reg = REGSP;
-               p1->to.offset = -8;
-               p1 = gins(AFMOVD, N, &r2);
-               p1->from.type = TYPE_MEM;
-               p1->from.reg = REGSP;
-               p1->from.offset = -8;
-               gins(AFCFID, &r2, &r2);
-               regfree(&r1);
-               if(ft == TUINT64) {
-                       p1 = gbranch(optoas(OLT, types[TUINT64]), T, +1); // use CR0 here again
-                       nodreg(&r1, types[TFLOAT64], FREGTWO);
-                       gins(AFMUL, &r1, &r2);
-                       patch(p1, pc);
-               }
-               gmove(&r2, t);
-               regfree(&r2);
-               return;
-
-       /*
-        * float to float
-        */
-       case CASE(TFLOAT32, TFLOAT32):
-               a = AFMOVS;
-               break;
-
-       case CASE(TFLOAT64, TFLOAT64):
-               a = AFMOVD;
-               break;
-
-       case CASE(TFLOAT32, TFLOAT64):
-               a = AFMOVS;
-               goto rdst;
-
-       case CASE(TFLOAT64, TFLOAT32):
-               a = AFRSP;
-               goto rdst;
-       }
-
-       gins(a, f, t);
-       return;
-
-rdst:
-       // requires register destination
-       regalloc(&r1, t->type, t);
-       gins(a, f, &r1);
-       gmove(&r1, t);
-       regfree(&r1);
-       return;
-
-hard:
-       // requires register intermediate
-       regalloc(&r1, cvt, t);
-       gmove(f, &r1);
-       gmove(&r1, t);
-       regfree(&r1);
-       return;
-}
-
-/*
- * generate one instruction:
- *     as f, t
- */
-Prog*
-gins(int as, Node *f, Node *t)
-{
-       int32 w;
-       Prog *p;
-       Addr af, at;
-
-       // TODO(austin): Add self-move test like in 6g (but be careful
-       // of truncation moves)
-
-       memset(&af, 0, sizeof af);
-       memset(&at, 0, sizeof at);
-       if(f != N)
-               naddr(f, &af, 1);
-       if(t != N)
-               naddr(t, &at, 1);
-       p = prog(as);
-       if(f != N)
-               p->from = af;
-       if(t != N)
-               p->to = at;
-       if(debug['g'])
-               print("%P\n", p);
-
-       w = 0;
-       switch(as) {
-       case AMOVB:
-       case AMOVBU:
-       case AMOVBZ:
-       case AMOVBZU:
-               w = 1;
-               break;
-       case AMOVH:
-       case AMOVHU:
-       case AMOVHZ:
-       case AMOVHZU:
-               w = 2;
-               break;
-       case AMOVW:
-       case AMOVWU:
-       case AMOVWZ:
-       case AMOVWZU:
-               w = 4;
-               break;
-       case AMOVD:
-       case AMOVDU:
-               if(af.type == TYPE_CONST || af.type == TYPE_ADDR)
-                       break;
-               w = 8;
-               break;
-       }
-       if(w != 0 && ((f != N && af.width < w) || (t != N && at.type != TYPE_REG && at.width > w))) {
-               dump("f", f);
-               dump("t", t);
-               fatal("bad width: %P (%d, %d)\n", p, af.width, at.width);
-       }
-
-       return p;
-}
-
-void
-fixlargeoffset(Node *n)
-{
-       Node a;
-
-       if(n == N)
-               return;
-       if(n->op != OINDREG)
-               return;
-       if(n->val.u.reg == REGSP) // stack offset cannot be large
-               return;
-       if(n->xoffset != (int32)n->xoffset) {
-               // TODO(minux): offset too large, move into R31 and add to R31 instead.
-               // this is used only in test/fixedbugs/issue6036.go.
-               fatal("offset too large: %N", n);
-               a = *n;
-               a.op = OREGISTER;
-               a.type = types[tptr];
-               a.xoffset = 0;
-               cgen_checknil(&a);
-               ginscon(optoas(OADD, types[tptr]), n->xoffset, &a);
-               n->xoffset = 0;
-       }
-}
-
-/*
- * return Axxx for Oxxx on type t.
- */
-int
-optoas(int op, Type *t)
-{
-       int a;
-
-       if(t == T)
-               fatal("optoas: t is nil");
-
-       a = AXXX;
-       switch(CASE(op, simtype[t->etype])) {
-       default:
-               fatal("optoas: no entry for op=%O type=%T", op, t);
-               break;
-
-       case CASE(OEQ, TBOOL):
-       case CASE(OEQ, TINT8):
-       case CASE(OEQ, TUINT8):
-       case CASE(OEQ, TINT16):
-       case CASE(OEQ, TUINT16):
-       case CASE(OEQ, TINT32):
-       case CASE(OEQ, TUINT32):
-       case CASE(OEQ, TINT64):
-       case CASE(OEQ, TUINT64):
-       case CASE(OEQ, TPTR32):
-       case CASE(OEQ, TPTR64):
-       case CASE(OEQ, TFLOAT32):
-       case CASE(OEQ, TFLOAT64):
-               a = ABEQ;
-               break;
-
-       case CASE(ONE, TBOOL):
-       case CASE(ONE, TINT8):
-       case CASE(ONE, TUINT8):
-       case CASE(ONE, TINT16):
-       case CASE(ONE, TUINT16):
-       case CASE(ONE, TINT32):
-       case CASE(ONE, TUINT32):
-       case CASE(ONE, TINT64):
-       case CASE(ONE, TUINT64):
-       case CASE(ONE, TPTR32):
-       case CASE(ONE, TPTR64):
-       case CASE(ONE, TFLOAT32):
-       case CASE(ONE, TFLOAT64):
-               a = ABNE;
-               break;
-
-       case CASE(OLT, TINT8):  // ACMP
-       case CASE(OLT, TINT16):
-       case CASE(OLT, TINT32):
-       case CASE(OLT, TINT64):
-       case CASE(OLT, TUINT8): // ACMPU
-       case CASE(OLT, TUINT16):
-       case CASE(OLT, TUINT32):
-       case CASE(OLT, TUINT64):
-       case CASE(OLT, TFLOAT32): // AFCMPU
-       case CASE(OLT, TFLOAT64):
-               a = ABLT;
-               break;
-
-       case CASE(OLE, TINT8):  // ACMP
-       case CASE(OLE, TINT16):
-       case CASE(OLE, TINT32):
-       case CASE(OLE, TINT64):
-       case CASE(OLE, TUINT8): // ACMPU
-       case CASE(OLE, TUINT16):
-       case CASE(OLE, TUINT32):
-       case CASE(OLE, TUINT64):
-       case CASE(OLE, TFLOAT32): // AFCMPU
-       case CASE(OLE, TFLOAT64):
-               a = ABLE;
-               break;
-
-       case CASE(OGT, TINT8):
-       case CASE(OGT, TINT16):
-       case CASE(OGT, TINT32):
-       case CASE(OGT, TINT64):
-       case CASE(OGT, TUINT8):
-       case CASE(OGT, TUINT16):
-       case CASE(OGT, TUINT32):
-       case CASE(OGT, TUINT64):
-       case CASE(OGT, TFLOAT32):
-       case CASE(OGT, TFLOAT64):
-               a = ABGT;
-               break;
-
-       case CASE(OGE, TINT8):
-       case CASE(OGE, TINT16):
-       case CASE(OGE, TINT32):
-       case CASE(OGE, TINT64):
-       case CASE(OGE, TUINT8):
-       case CASE(OGE, TUINT16):
-       case CASE(OGE, TUINT32):
-       case CASE(OGE, TUINT64):
-       case CASE(OGE, TFLOAT32):
-       case CASE(OGE, TFLOAT64):
-               a = ABGE;
-               break;
-
-       case CASE(OCMP, TBOOL):
-       case CASE(OCMP, TINT8):
-       case CASE(OCMP, TINT16):
-       case CASE(OCMP, TINT32):
-       case CASE(OCMP, TPTR32):
-       case CASE(OCMP, TINT64):
-               a = ACMP;
-               break;
-
-       case CASE(OCMP, TUINT8):
-       case CASE(OCMP, TUINT16):
-       case CASE(OCMP, TUINT32):
-       case CASE(OCMP, TUINT64):
-       case CASE(OCMP, TPTR64):
-               a = ACMPU;
-               break;
-
-       case CASE(OCMP, TFLOAT32):
-       case CASE(OCMP, TFLOAT64):
-               a = AFCMPU;
-               break;
-
-       case CASE(OAS, TBOOL):
-       case CASE(OAS, TINT8):
-               a = AMOVB;
-               break;
-
-       case CASE(OAS, TUINT8):
-               a = AMOVBZ;
-               break;
-
-       case CASE(OAS, TINT16):
-               a = AMOVH;
-               break;
-
-       case CASE(OAS, TUINT16):
-               a = AMOVHZ;
-               break;
-
-       case CASE(OAS, TINT32):
-               a = AMOVW;
-               break;
-
-       case CASE(OAS, TUINT32):
-       case CASE(OAS, TPTR32):
-               a = AMOVWZ;
-               break;
-
-       case CASE(OAS, TINT64):
-       case CASE(OAS, TUINT64):
-       case CASE(OAS, TPTR64):
-               a = AMOVD;
-               break;
-
-       case CASE(OAS, TFLOAT32):
-               a = AFMOVS;
-               break;
-
-       case CASE(OAS, TFLOAT64):
-               a = AFMOVD;
-               break;
-
-       case CASE(OADD, TINT8):
-       case CASE(OADD, TUINT8):
-       case CASE(OADD, TINT16):
-       case CASE(OADD, TUINT16):
-       case CASE(OADD, TINT32):
-       case CASE(OADD, TUINT32):
-       case CASE(OADD, TPTR32):
-       case CASE(OADD, TINT64):
-       case CASE(OADD, TUINT64):
-       case CASE(OADD, TPTR64):
-               a = AADD;
-               break;
-
-       case CASE(OADD, TFLOAT32):
-               a = AFADDS;
-               break;
-
-       case CASE(OADD, TFLOAT64):
-               a = AFADD;
-               break;
-
-       case CASE(OSUB, TINT8):
-       case CASE(OSUB, TUINT8):
-       case CASE(OSUB, TINT16):
-       case CASE(OSUB, TUINT16):
-       case CASE(OSUB, TINT32):
-       case CASE(OSUB, TUINT32):
-       case CASE(OSUB, TPTR32):
-       case CASE(OSUB, TINT64):
-       case CASE(OSUB, TUINT64):
-       case CASE(OSUB, TPTR64):
-               a = ASUB;
-               break;
-
-       case CASE(OSUB, TFLOAT32):
-               a = AFSUBS;
-               break;
-
-       case CASE(OSUB, TFLOAT64):
-               a = AFSUB;
-               break;
-
-       case CASE(OMINUS, TINT8):
-       case CASE(OMINUS, TUINT8):
-       case CASE(OMINUS, TINT16):
-       case CASE(OMINUS, TUINT16):
-       case CASE(OMINUS, TINT32):
-       case CASE(OMINUS, TUINT32):
-       case CASE(OMINUS, TPTR32):
-       case CASE(OMINUS, TINT64):
-       case CASE(OMINUS, TUINT64):
-       case CASE(OMINUS, TPTR64):
-               a = ANEG;
-               break;
-
-       case CASE(OAND, TINT8):
-       case CASE(OAND, TUINT8):
-       case CASE(OAND, TINT16):
-       case CASE(OAND, TUINT16):
-       case CASE(OAND, TINT32):
-       case CASE(OAND, TUINT32):
-       case CASE(OAND, TPTR32):
-       case CASE(OAND, TINT64):
-       case CASE(OAND, TUINT64):
-       case CASE(OAND, TPTR64):
-               a = AAND;
-               break;
-
-       case CASE(OOR, TINT8):
-       case CASE(OOR, TUINT8):
-       case CASE(OOR, TINT16):
-       case CASE(OOR, TUINT16):
-       case CASE(OOR, TINT32):
-       case CASE(OOR, TUINT32):
-       case CASE(OOR, TPTR32):
-       case CASE(OOR, TINT64):
-       case CASE(OOR, TUINT64):
-       case CASE(OOR, TPTR64):
-               a = AOR;
-               break;
-
-       case CASE(OXOR, TINT8):
-       case CASE(OXOR, TUINT8):
-       case CASE(OXOR, TINT16):
-       case CASE(OXOR, TUINT16):
-       case CASE(OXOR, TINT32):
-       case CASE(OXOR, TUINT32):
-       case CASE(OXOR, TPTR32):
-       case CASE(OXOR, TINT64):
-       case CASE(OXOR, TUINT64):
-       case CASE(OXOR, TPTR64):
-               a = AXOR;
-               break;
-
-       // TODO(minux): handle rotates
-       //case CASE(OLROT, TINT8):
-       //case CASE(OLROT, TUINT8):
-       //case CASE(OLROT, TINT16):
-       //case CASE(OLROT, TUINT16):
-       //case CASE(OLROT, TINT32):
-       //case CASE(OLROT, TUINT32):
-       //case CASE(OLROT, TPTR32):
-       //case CASE(OLROT, TINT64):
-       //case CASE(OLROT, TUINT64):
-       //case CASE(OLROT, TPTR64):
-       //      a = 0//???; RLDC?
-       //      break;
-
-       case CASE(OLSH, TINT8):
-       case CASE(OLSH, TUINT8):
-       case CASE(OLSH, TINT16):
-       case CASE(OLSH, TUINT16):
-       case CASE(OLSH, TINT32):
-       case CASE(OLSH, TUINT32):
-       case CASE(OLSH, TPTR32):
-       case CASE(OLSH, TINT64):
-       case CASE(OLSH, TUINT64):
-       case CASE(OLSH, TPTR64):
-               a = ASLD;
-               break;
-
-       case CASE(ORSH, TUINT8):
-       case CASE(ORSH, TUINT16):
-       case CASE(ORSH, TUINT32):
-       case CASE(ORSH, TPTR32):
-       case CASE(ORSH, TUINT64):
-       case CASE(ORSH, TPTR64):
-               a = ASRD;
-               break;
-
-       case CASE(ORSH, TINT8):
-       case CASE(ORSH, TINT16):
-       case CASE(ORSH, TINT32):
-       case CASE(ORSH, TINT64):
-               a = ASRAD;
-               break;
-
-       // TODO(minux): handle rotates
-       //case CASE(ORROTC, TINT8):
-       //case CASE(ORROTC, TUINT8):
-       //case CASE(ORROTC, TINT16):
-       //case CASE(ORROTC, TUINT16):
-       //case CASE(ORROTC, TINT32):
-       //case CASE(ORROTC, TUINT32):
-       //case CASE(ORROTC, TINT64):
-       //case CASE(ORROTC, TUINT64):
-       //      a = 0//??? RLDC??
-       //      break;
-
-       case CASE(OHMUL, TINT64):
-               a = AMULHD;
-               break;
-       case CASE(OHMUL, TUINT64):
-       case CASE(OHMUL, TPTR64):
-               a = AMULHDU;
-               break;
-
-       case CASE(OMUL, TINT8):
-       case CASE(OMUL, TINT16):
-       case CASE(OMUL, TINT32):
-       case CASE(OMUL, TINT64):
-               a = AMULLD;
-               break;
-
-       case CASE(OMUL, TUINT8):
-       case CASE(OMUL, TUINT16):
-       case CASE(OMUL, TUINT32):
-       case CASE(OMUL, TPTR32):
-               // don't use word multiply, the high 32-bit are undefined.
-               // fallthrough
-       case CASE(OMUL, TUINT64):
-       case CASE(OMUL, TPTR64):
-               a = AMULLD; // for 64-bit multiplies, signedness doesn't matter.
-               break;
-
-       case CASE(OMUL, TFLOAT32):
-               a = AFMULS;
-               break;
-
-       case CASE(OMUL, TFLOAT64):
-               a = AFMUL;
-               break;
-
-       case CASE(ODIV, TINT8):
-       case CASE(ODIV, TINT16):
-       case CASE(ODIV, TINT32):
-       case CASE(ODIV, TINT64):
-               a = ADIVD;
-               break;
-
-       case CASE(ODIV, TUINT8):
-       case CASE(ODIV, TUINT16):
-       case CASE(ODIV, TUINT32):
-       case CASE(ODIV, TPTR32):
-       case CASE(ODIV, TUINT64):
-       case CASE(ODIV, TPTR64):
-               a = ADIVDU;
-               break;
-
-       case CASE(ODIV, TFLOAT32):
-               a = AFDIVS;
-               break;
-
-       case CASE(ODIV, TFLOAT64):
-               a = AFDIV;
-               break;
-
-       }
-       return a;
-}
-
-enum
-{
-       ODynam          = 1<<0,
-       OAddable        = 1<<1,
-};
-
-int
-xgen(Node *n, Node *a, int o)
-{
-       // TODO(minux)
-       USED(n); USED(a); USED(o);
-       return -1;
-}
-
-void
-sudoclean(void)
-{
-       return;
-}
-
-/*
- * generate code to compute address of n,
- * a reference to a (perhaps nested) field inside
- * an array or struct.
- * return 0 on failure, 1 on success.
- * on success, leaves usable address in a.
- *
- * caller is responsible for calling sudoclean
- * after successful sudoaddable,
- * to release the register used for a.
- */
-int
-sudoaddable(int as, Node *n, Addr *a)
-{
-       // TODO(minux)
-       USED(as); USED(n);
-       memset(a, 0, sizeof *a);
-       return 0;
-}
similarity index 100%
rename from src/cmd/new9g/gsubr.go
rename to src/cmd/9g/gsubr.go
similarity index 100%
rename from src/cmd/new9g/opt.go
rename to src/cmd/9g/opt.go
diff --git a/src/cmd/9g/opt.h b/src/cmd/9g/opt.h
deleted file mode 100644 (file)
index 79a34fb..0000000
+++ /dev/null
@@ -1,13 +0,0 @@
-// Copyright 2014 The Go Authors.  All rights reserved.
-// Use of this source code is governed by a BSD-style
-// license that can be found in the LICENSE file.
-
-// Many Power ISA arithmetic and logical instructions come in four
-// standard variants.  These bits let us map between variants.
-enum {
-       V_CC = 1<<0,            // xCC (affect CR field 0 flags)
-       V_V  = 1<<1,            // xV (affect SO and OV flags)
-};
-
-int as2variant(int);
-int variant2as(int, int);
diff --git a/src/cmd/9g/peep.c b/src/cmd/9g/peep.c
deleted file mode 100644 (file)
index cf96d5d..0000000
+++ /dev/null
@@ -1,959 +0,0 @@
-// Derived from Inferno utils/6c/peep.c
-// http://code.google.com/p/inferno-os/source/browse/utils/6c/peep.c
-//
-//     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 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 <u.h>
-#include <libc.h>
-#include "gg.h"
-#include "../gc/popt.h"
-#include "opt.h"
-
-static int     regzer(Addr *a);
-static int     subprop(Flow*);
-static int     copyprop(Flow*);
-static int     copy1(Addr*, Addr*, Flow*, int);
-static int     copyas(Addr*, Addr*);
-static int     copyau(Addr*, Addr*);
-static int     copysub(Addr*, Addr*, Addr*, int);
-static int     copysub1(Prog*, Addr*, Addr*, int);
-static int     copyau1(Prog *p, Addr *v);
-static int     copyu(Prog *p, Addr *v, Addr *s);
-
-static uint32  gactive;
-
-void
-peep(Prog *firstp)
-{
-       Graph *g;
-       Flow *r, *r1;
-       Prog *p, *p1;
-       int t;
-
-       g = flowstart(firstp, 0);
-       if(g == nil)
-               return;
-       gactive = 0;
-
-loop1:
-       if(debug['P'] && debug['v'])
-               dumpit("loop1", g->start, 0);
-
-       t = 0;
-       for(r=g->start; r!=nil; r=r->link) {
-               p = r->prog;
-               // TODO(austin) Handle smaller moves.  arm and amd64
-               // distinguish between moves that moves that *must*
-               // sign/zero extend and moves that don't care so they
-               // can eliminate moves that don't care without
-               // breaking moves that do care.  This might let us
-               // simplify or remove the next peep loop, too.
-               if(p->as == AMOVD || p->as == AFMOVD)
-               if(regtyp(&p->to)) {
-                       // Try to eliminate reg->reg moves
-                       if(regtyp(&p->from))
-                       if(p->from.type == p->to.type) {
-                               if(copyprop(r)) {
-                                       excise(r);
-                                       t++;
-                               } else
-                               if(subprop(r) && copyprop(r)) {
-                                       excise(r);
-                                       t++;
-                               }
-                       }
-                       // Convert uses to $0 to uses of R0 and
-                       // propagate R0
-                       if(regzer(&p->from))
-                       if(p->to.type == TYPE_REG) {
-                               p->from.type = TYPE_REG;
-                               p->from.reg = REGZERO;
-                               if(copyprop(r)) {
-                                       excise(r);
-                                       t++;
-                               } else
-                               if(subprop(r) && copyprop(r)) {
-                                       excise(r);
-                                       t++;
-                               }
-                       }
-               }
-       }
-       if(t)
-               goto loop1;
-
-       /*
-        * look for MOVB x,R; MOVB R,R (for small MOVs not handled above)
-        */
-       for(r=g->start; r!=nil; r=r->link) {
-               p = r->prog;
-               switch(p->as) {
-               default:
-                       continue;
-               case AMOVH:
-               case AMOVHZ:
-               case AMOVB:
-               case AMOVBZ:
-               case AMOVW:
-               case AMOVWZ:
-                       if(p->to.type != TYPE_REG)
-                               continue;
-                       break;
-               }
-               r1 = r->link;
-               if(r1 == nil)
-                       continue;
-               p1 = r1->prog;
-               if(p1->as != p->as)
-                       continue;
-               if(p1->from.type != TYPE_REG || p1->from.reg != p->to.reg)
-                       continue;
-               if(p1->to.type != TYPE_REG || p1->to.reg != p->to.reg)
-                       continue;
-               excise(r1);
-       }
-
-       if(debug['D'] > 1)
-               goto ret;       /* allow following code improvement to be suppressed */
-
-       /*
-        * look for OP x,y,R; CMP R, $0 -> OPCC x,y,R
-        * when OP can set condition codes correctly
-        */
-       for(r=g->start; r!=nil; r=r->link) {
-               p = r->prog;
-               switch(p->as) {
-               case ACMP:
-               case ACMPW:             /* always safe? */
-                       if(!regzer(&p->to))
-                               continue;
-                       r1 = r->s1;
-                       if(r1 == nil)
-                               continue;
-                       switch(r1->prog->as) {
-                       default:
-                               continue;
-                       case ABCL:
-                       case ABC:
-                               /* the conditions can be complex and these are currently little used */
-                               continue;
-                       case ABEQ:
-                       case ABGE:
-                       case ABGT:
-                       case ABLE:
-                       case ABLT:
-                       case ABNE:
-                       case ABVC:
-                       case ABVS:
-                               break;
-                       }
-                       r1 = r;
-                       do
-                               r1 = uniqp(r1);
-                       while (r1 != nil && r1->prog->as == ANOP);
-                       if(r1 == nil)
-                               continue;
-                       p1 = r1->prog;
-                       if(p1->to.type != TYPE_REG || p1->to.reg != p->from.reg)
-                               continue;
-                       switch(p1->as) {
-                       case ASUB:
-                       case AADD:
-                       case AXOR:
-                       case AOR:
-                               /* irregular instructions */
-                               if(p1->from.type == TYPE_CONST || p1->from.type == TYPE_ADDR)
-                                       continue;
-                               break;
-                       }
-                       switch(p1->as) {
-                       default:
-                               continue;
-                       case AMOVW:
-                       case AMOVD:
-                               if(p1->from.type != TYPE_REG)
-                                       continue;
-                               continue;
-                       case AANDCC:
-                       case AANDNCC:
-                       case AORCC:
-                       case AORNCC:
-                       case AXORCC:
-                       case ASUBCC:
-                       case ASUBECC:
-                       case ASUBMECC:
-                       case ASUBZECC:
-                       case AADDCC:
-                       case AADDCCC:
-                       case AADDECC:
-                       case AADDMECC:
-                       case AADDZECC:
-                       case ARLWMICC:
-                       case ARLWNMCC:
-                       /* don't deal with floating point instructions for now */
-/*
-                       case AFABS:
-                       case AFADD:
-                       case AFADDS:
-                       case AFCTIW:
-                       case AFCTIWZ:
-                       case AFDIV:
-                       case AFDIVS:
-                       case AFMADD:
-                       case AFMADDS:
-                       case AFMOVD:
-                       case AFMSUB:
-                       case AFMSUBS:
-                       case AFMUL:
-                       case AFMULS:
-                       case AFNABS:
-                       case AFNEG:
-                       case AFNMADD:
-                       case AFNMADDS:
-                       case AFNMSUB:
-                       case AFNMSUBS:
-                       case AFRSP:
-                       case AFSUB:
-                       case AFSUBS:
-                       case ACNTLZW:
-                       case AMTFSB0:
-                       case AMTFSB1:
-*/
-                       case AADD:
-                       case AADDV:
-                       case AADDC:
-                       case AADDCV:
-                       case AADDME:
-                       case AADDMEV:
-                       case AADDE:
-                       case AADDEV:
-                       case AADDZE:
-                       case AADDZEV:
-                       case AAND:
-                       case AANDN:
-                       case ADIVW:
-                       case ADIVWV:
-                       case ADIVWU:
-                       case ADIVWUV:
-                       case ADIVD:
-                       case ADIVDV:
-                       case ADIVDU:
-                       case ADIVDUV:
-                       case AEQV:
-                       case AEXTSB:
-                       case AEXTSH:
-                       case AEXTSW:
-                       case AMULHW:
-                       case AMULHWU:
-                       case AMULLW:
-                       case AMULLWV:
-                       case AMULHD:
-                       case AMULHDU:
-                       case AMULLD:
-                       case AMULLDV:
-                       case ANAND:
-                       case ANEG:
-                       case ANEGV:
-                       case ANOR:
-                       case AOR:
-                       case AORN:
-                       case AREM:
-                       case AREMV:
-                       case AREMU:
-                       case AREMUV:
-                       case AREMD:
-                       case AREMDV:
-                       case AREMDU:
-                       case AREMDUV:
-                       case ARLWMI:
-                       case ARLWNM:
-                       case ASLW:
-                       case ASRAW:
-                       case ASRW:
-                       case ASLD:
-                       case ASRAD:
-                       case ASRD:
-                       case ASUB:
-                       case ASUBV:
-                       case ASUBC:
-                       case ASUBCV:
-                       case ASUBME:
-                       case ASUBMEV:
-                       case ASUBE:
-                       case ASUBEV:
-                       case ASUBZE:
-                       case ASUBZEV:
-                       case AXOR:
-                               t = variant2as(p1->as, as2variant(p1->as) | V_CC);
-                               break;
-                       }
-                       if(debug['D'])
-                               print("cmp %P; %P -> ", p1, p);
-                       p1->as = t;
-                       if(debug['D'])
-                               print("%P\n", p1);
-                       excise(r);
-                       continue;
-               }
-       }
-
-ret:
-       flowend(g);
-}
-
-void
-excise(Flow *r)
-{
-       Prog *p;
-
-       p = r->prog;
-       if(debug['P'] && debug['v'])
-               print("%P ===delete===\n", p);
-       nopout(p);
-       ostats.ndelmov++;
-}
-
-/*
- * regzer returns 1 if a's value is 0 (a is R0 or $0)
- */
-static int
-regzer(Addr *a)
-{
-       if(a->type == TYPE_CONST || a->type == TYPE_ADDR)
-               if(a->sym == nil && a->reg == 0)
-                       if(a->offset == 0)
-                               return 1;
-       if(a->type == TYPE_REG)
-               if(a->reg == REGZERO)
-                       return 1;
-       return 0;
-}
-
-int
-regtyp(Adr *a)
-{
-       // TODO(rsc): Floating point register exclusions?
-       return a->type == TYPE_REG && REG_R0 <= a->reg && a->reg <= REG_F31 && a->reg != REGZERO;
-}
-
-/*
- * the idea is to substitute
- * one register for another
- * from one MOV to another
- *     MOV     a, R1
- *     ADD     b, R1   / no use of R2
- *     MOV     R1, R2
- * would be converted to
- *     MOV     a, R2
- *     ADD     b, R2
- *     MOV     R2, R1
- * hopefully, then the former or latter MOV
- * will be eliminated by copy propagation.
- *
- * r0 (the argument, not the register) is the MOV at the end of the
- * above sequences.  This returns 1 if it modified any instructions.
- */
-static int
-subprop(Flow *r0)
-{
-       Prog *p;
-       Addr *v1, *v2;
-       Flow *r;
-       int t;
-       ProgInfo info;
-
-       p = r0->prog;
-       v1 = &p->from;
-       if(!regtyp(v1))
-               return 0;
-       v2 = &p->to;
-       if(!regtyp(v2))
-               return 0;
-       for(r=uniqp(r0); r!=nil; r=uniqp(r)) {
-               if(uniqs(r) == nil)
-                       break;
-               p = r->prog;
-               if(p->as == AVARDEF || p->as == AVARKILL)
-                       continue;
-               proginfo(&info, p);
-               if(info.flags & Call)
-                       return 0;
-
-               if((info.flags & (RightRead|RightWrite)) == RightWrite) {
-                       if(p->to.type == v1->type)
-                       if(p->to.reg == v1->reg)
-                               goto gotit;
-               }
-
-               if(copyau(&p->from, v2) ||
-                  copyau1(p, v2) ||
-                  copyau(&p->to, v2))
-                       break;
-               if(copysub(&p->from, v1, v2, 0) ||
-                  copysub1(p, v1, v2, 0) ||
-                  copysub(&p->to, v1, v2, 0))
-                       break;
-       }
-       return 0;
-
-gotit:
-       copysub(&p->to, v1, v2, 1);
-       if(debug['P']) {
-               print("gotit: %D->%D\n%P", v1, v2, r->prog);
-               if(p->from.type == v2->type)
-                       print(" excise");
-               print("\n");
-       }
-       for(r=uniqs(r); r!=r0; r=uniqs(r)) {
-               p = r->prog;
-               copysub(&p->from, v1, v2, 1);
-               copysub1(p, v1, v2, 1);
-               copysub(&p->to, v1, v2, 1);
-               if(debug['P'])
-                       print("%P\n", r->prog);
-       }
-       t = v1->reg;
-       v1->reg = v2->reg;
-       v2->reg = t;
-       if(debug['P'])
-               print("%P last\n", r->prog);
-       return 1;
-}
-
-/*
- * The idea is to remove redundant copies.
- *     v1->v2  F=0
- *     (use v2 s/v2/v1/)*
- *     set v1  F=1
- *     use v2  return fail (v1->v2 move must remain)
- *     -----------------
- *     v1->v2  F=0
- *     (use v2 s/v2/v1/)*
- *     set v1  F=1
- *     set v2  return success (caller can remove v1->v2 move)
- */
-static int
-copyprop(Flow *r0)
-{
-       Prog *p;
-       Addr *v1, *v2;
-
-       p = r0->prog;
-       v1 = &p->from;
-       v2 = &p->to;
-       if(copyas(v1, v2)) {
-               if(debug['P'])
-                       print("eliminating self-move\n", r0->prog);
-               return 1;
-       }
-       gactive++;
-       if(debug['P'])
-               print("trying to eliminate %D->%D move from:\n%P\n", v1, v2, r0->prog);
-       return copy1(v1, v2, r0->s1, 0);
-}
-
-// copy1 replaces uses of v2 with v1 starting at r and returns 1 if
-// all uses were rewritten.
-static int
-copy1(Addr *v1, Addr *v2, Flow *r, int f)
-{
-       int t;
-       Prog *p;
-
-       if(r->active == gactive) {
-               if(debug['P'])
-                       print("act set; return 1\n");
-               return 1;
-       }
-       r->active = gactive;
-       if(debug['P'])
-               print("copy1 replace %D with %D f=%d\n", v2, v1, f);
-       for(; r != nil; r = r->s1) {
-               p = r->prog;
-               if(debug['P'])
-                       print("%P", p);
-               if(!f && uniqp(r) == nil) {
-                       // Multiple predecessors; conservatively
-                       // assume v1 was set on other path
-                       f = 1;
-                       if(debug['P'])
-                               print("; merge; f=%d", f);
-               }
-               t = copyu(p, v2, nil);
-               switch(t) {
-               case 2: /* rar, can't split */
-                       if(debug['P'])
-                               print("; %D rar; return 0\n", v2);
-                       return 0;
-
-               case 3: /* set */
-                       if(debug['P'])
-                               print("; %D set; return 1\n", v2);
-                       return 1;
-
-               case 1: /* used, substitute */
-               case 4: /* use and set */
-                       if(f) {
-                               if(!debug['P'])
-                                       return 0;
-                               if(t == 4)
-                                       print("; %D used+set and f=%d; return 0\n", v2, f);
-                               else
-                                       print("; %D used and f=%d; return 0\n", v2, f);
-                               return 0;
-                       }
-                       if(copyu(p, v2, v1)) {
-                               if(debug['P'])
-                                       print("; sub fail; return 0\n");
-                               return 0;
-                       }
-                       if(debug['P'])
-                               print("; sub %D->%D\n => %P", v2, v1, p);
-                       if(t == 4) {
-                               if(debug['P'])
-                                       print("; %D used+set; return 1\n", v2);
-                               return 1;
-                       }
-                       break;
-               }
-               if(!f) {
-                       t = copyu(p, v1, nil);
-                       if(!f && (t == 2 || t == 3 || t == 4)) {
-                               f = 1;
-                               if(debug['P'])
-                                       print("; %D set and !f; f=%d", v1, f);
-                       }
-               }
-               if(debug['P'])
-                       print("\n");
-               if(r->s2)
-                       if(!copy1(v1, v2, r->s2, f))
-                               return 0;
-       }
-       return 1;
-}
-
-// If s==nil, copyu returns the set/use of v in p; otherwise, it
-// modifies p to replace reads of v with reads of s and returns 0 for
-// success or non-zero for failure.
-//
-// If s==nil, copy returns one of the following values:
-//     1 if v only used
-//     2 if v is set and used in one address (read-alter-rewrite;
-//       can't substitute)
-//     3 if v is only set
-//     4 if v is set in one address and used in another (so addresses
-//       can be rewritten independently)
-//     0 otherwise (not touched)
-static int
-copyu(Prog *p, Addr *v, Addr *s)
-{
-       if(p->from3.type != TYPE_NONE)
-               // 9g never generates a from3
-               print("copyu: from3 (%D) not implemented\n", &p->from3);
-
-       switch(p->as) {
-
-       default:
-               print("copyu: can't find %A\n", p->as);
-               return 2;
-
-       case ANOP:      /* read p->from, write p->to */
-       case AMOVH:
-       case AMOVHZ:
-       case AMOVB:
-       case AMOVBZ:
-       case AMOVW:
-       case AMOVWZ:
-       case AMOVD:
-
-       case ANEG:
-       case ANEGCC:
-       case AADDME:
-       case AADDMECC:
-       case AADDZE:
-       case AADDZECC:
-       case ASUBME:
-       case ASUBMECC:
-       case ASUBZE:
-       case ASUBZECC:
-
-       case AFCTIW:
-       case AFCTIWZ:
-       case AFCTID:
-       case AFCTIDZ:
-       case AFCFID:
-       case AFCFIDCC:
-       case AFMOVS:
-       case AFMOVD:
-       case AFRSP:
-       case AFNEG:
-       case AFNEGCC:
-               if(s != nil) {
-                       if(copysub(&p->from, v, s, 1))
-                               return 1;
-                       // Update only indirect uses of v in p->to
-                       if(!copyas(&p->to, v))
-                               if(copysub(&p->to, v, s, 1))
-                                       return 1;
-                       return 0;
-               }
-               if(copyas(&p->to, v)) {
-                       // Fix up implicit from
-                       if(p->from.type == TYPE_NONE)
-                               p->from = p->to;
-                       if(copyau(&p->from, v))
-                               return 4;
-                       return 3;
-               }
-               if(copyau(&p->from, v))
-                       return 1;
-               if(copyau(&p->to, v))
-                       // p->to only indirectly uses v
-                       return 1;
-               return 0;
-
-       case AMOVBU:    /* rar p->from, write p->to or read p->from, rar p->to */
-       case AMOVBZU:
-       case AMOVHU:
-       case AMOVHZU:
-       case AMOVWZU:
-       case AMOVDU:
-               if(p->from.type == TYPE_MEM) {
-                       if(copyas(&p->from, v))
-                               // No s!=nil check; need to fail
-                               // anyway in that case
-                               return 2;
-                       if(s != nil) {
-                               if(copysub(&p->to, v, s, 1))
-                                       return 1;
-                               return 0;
-                       }
-                       if(copyas(&p->to, v))
-                               return 3;
-               } else if (p->to.type == TYPE_MEM) {
-                       if(copyas(&p->to, v))
-                               return 2;
-                       if(s != nil) {
-                               if(copysub(&p->from, v, s, 1))
-                                       return 1;
-                               return 0;
-                       }
-                       if(copyau(&p->from, v))
-                               return 1;
-               } else {
-                       print("copyu: bad %P\n", p);
-               }
-               return 0;
-
-       case ARLWMI:    /* read p->from, read p->reg, rar p->to */
-       case ARLWMICC:
-               if(copyas(&p->to, v))
-                       return 2;
-               /* fall through */
-
-       case AADD:      /* read p->from, read p->reg, write p->to */
-       case AADDC:
-       case AADDE:
-       case ASUB:
-       case ASLW:
-       case ASRW:
-       case ASRAW:
-       case ASLD:
-       case ASRD:
-       case ASRAD:
-       case AOR:
-       case AORCC:
-       case AORN:
-       case AORNCC:
-       case AAND:
-       case AANDCC:
-       case AANDN:
-       case AANDNCC:
-       case ANAND:
-       case ANANDCC:
-       case ANOR:
-       case ANORCC:
-       case AXOR:
-       case AMULHW:
-       case AMULHWU:
-       case AMULLW:
-       case AMULLD:
-       case ADIVW:
-       case ADIVD:
-       case ADIVWU:
-       case ADIVDU:
-       case AREM:
-       case AREMU:
-       case AREMD:
-       case AREMDU:
-       case ARLWNM:
-       case ARLWNMCC:
-
-       case AFADDS:
-       case AFADD:
-       case AFSUBS:
-       case AFSUB:
-       case AFMULS:
-       case AFMUL:
-       case AFDIVS:
-       case AFDIV:
-               if(s != nil) {
-                       if(copysub(&p->from, v, s, 1))
-                               return 1;
-                       if(copysub1(p, v, s, 1))
-                               return 1;
-                       // Update only indirect uses of v in p->to
-                       if(!copyas(&p->to, v))
-                               if(copysub(&p->to, v, s, 1))
-                                       return 1;
-                       return 0;
-               }
-               if(copyas(&p->to, v)) {
-                       if(p->reg == 0)
-                               // Fix up implicit reg (e.g., ADD
-                               // R3,R4 -> ADD R3,R4,R4) so we can
-                               // update reg and to separately.
-                               p->reg = p->to.reg;
-                       if(copyau(&p->from, v))
-                               return 4;
-                       if(copyau1(p, v))
-                               return 4;
-                       return 3;
-               }
-               if(copyau(&p->from, v))
-                       return 1;
-               if(copyau1(p, v))
-                       return 1;
-               if(copyau(&p->to, v))
-                       return 1;
-               return 0;
-
-       case ABEQ:
-       case ABGT:
-       case ABGE:
-       case ABLT:
-       case ABLE:
-       case ABNE:
-       case ABVC:
-       case ABVS:
-               return 0;
-
-       case ACHECKNIL: /* read p->from */
-       case ACMP:      /* read p->from, read p->to */
-       case ACMPU:
-       case ACMPW:
-       case ACMPWU:
-       case AFCMPO:
-       case AFCMPU:
-               if(s != nil) {
-                       if(copysub(&p->from, v, s, 1))
-                               return 1;
-                       return copysub(&p->to, v, s, 1);
-               }
-               if(copyau(&p->from, v))
-                       return 1;
-               if(copyau(&p->to, v))
-                       return 1;
-               return 0;
-
-       case ABR:       /* read p->to */
-               // 9g never generates a branch to a GPR (this isn't
-               // even a normal instruction; liblink turns it in to a
-               // mov and a branch).
-               if(s != nil) {
-                       if(copysub(&p->to, v, s, 1))
-                               return 1;
-                       return 0;
-               }
-               if(copyau(&p->to, v))
-                       return 1;
-               return 0;
-
-       case ARETURN:   /* funny */
-               if(s != nil)
-                       return 0;
-               // All registers die at this point, so claim
-               // everything is set (and not used).
-               return 3;
-
-       case ABL:       /* funny */
-               if(v->type == TYPE_REG) {
-                       // TODO(rsc): REG_R0 and REG_F0 used to be
-                       // (when register numbers started at 0) exregoffset and exfregoffset,
-                       // which are unset entirely. 
-                       // It's strange that this handles R0 and F0 differently from the other
-                       // registers. Possible failure to optimize?
-                       if(REG_R0 < v->reg && v->reg <= REGEXT)
-                               return 2;
-                       if(v->reg == REGARG)
-                               return 2;
-                       if(REG_F0 < v->reg && v->reg <= FREGEXT)
-                               return 2;
-               }
-               if(p->from.type == TYPE_REG && v->type == TYPE_REG && p->from.reg == v->reg)
-                       return 2;
-
-               if(s != nil) {
-                       if(copysub(&p->to, v, s, 1))
-                               return 1;
-                       return 0;
-               }
-               if(copyau(&p->to, v))
-                       return 4;
-               return 3;
-
-       case ADUFFZERO:
-               // R0 is zero, used by DUFFZERO, cannot be substituted.
-               // R3 is ptr to memory, used and set, cannot be substituted.
-               if(v->type == TYPE_REG) {
-                       if(v->reg == 0)
-                               return 1;
-                       if(v->reg == 3)
-                               return 2;
-               }
-               return 0;
-
-       case ADUFFCOPY:
-               // R3, R4 are ptr to src, dst, used and set, cannot be substituted.
-               // R5 is scratch, set by DUFFCOPY, cannot be substituted.
-               if(v->type == TYPE_REG) {
-                       if(v->reg == 3 || v->reg == 4)
-                               return 2;
-                       if(v->reg == 5)
-                               return 3;
-               }
-               return 0;
-
-       case ATEXT:     /* funny */
-               if(v->type == TYPE_REG)
-                       if(v->reg == REGARG)
-                               return 3;
-               return 0;
-
-       case APCDATA:
-       case AFUNCDATA:
-       case AVARDEF:
-       case AVARKILL:
-               return 0;
-       }
-}
-
-// copyas returns 1 if a and v address the same register.
-//
-// If a is the from operand, this means this operation reads the
-// register in v.  If a is the to operand, this means this operation
-// writes the register in v.
-static int
-copyas(Addr *a, Addr *v)
-{
-       if(regtyp(v))
-               if(a->type == v->type)
-               if(a->reg == v->reg)
-                       return 1;
-       return 0;
-}
-
-// copyau returns 1 if a either directly or indirectly addresses the
-// same register as v.
-//
-// If a is the from operand, this means this operation reads the
-// register in v.  If a is the to operand, this means the operation
-// either reads or writes the register in v (if !copyas(a, v), then
-// the operation reads the register in v).
-static int
-copyau(Addr *a, Addr *v)
-{
-       if(copyas(a, v))
-               return 1;
-       if(v->type == TYPE_REG)
-               if(a->type == TYPE_MEM || (a->type == TYPE_ADDR && a->reg != 0))
-                       if(v->reg == a->reg)
-                               return 1;
-       return 0;
-}
-
-// copyau1 returns 1 if p->reg references the same register as v and v
-// is a direct reference.
-static int
-copyau1(Prog *p, Addr *v)
-{
-       if(regtyp(v) && v->reg != 0)
-               if(p->reg == v->reg)
-                       return 1;
-       return 0;
-}
-
-// copysub replaces v with s in a if f!=0 or indicates it if could if f==0.
-// Returns 1 on failure to substitute (it always succeeds on ppc64).
-static int
-copysub(Addr *a, Addr *v, Addr *s, int f)
-{
-       if(f)
-       if(copyau(a, v))
-               a->reg = s->reg;
-       return 0;
-}
-
-// copysub1 replaces v with s in p1->reg if f!=0 or indicates if it could if f==0.
-// Returns 1 on failure to substitute (it always succeeds on ppc64).
-static int
-copysub1(Prog *p1, Addr *v, Addr *s, int f)
-{
-       if(f)
-       if(copyau1(p1, v))
-               p1->reg = s->reg;
-       return 0;
-}
-
-int
-sameaddr(Addr *a, Addr *v)
-{
-       if(a->type != v->type)
-               return 0;
-       if(regtyp(v) && a->reg == v->reg)
-               return 1;
-       if(v->type == NAME_AUTO || v->type == NAME_PARAM)
-               if(v->offset == a->offset)
-                       return 1;
-       return 0;
-}
-
-int
-smallindir(Addr *a, Addr *reg)
-{
-       return reg->type == TYPE_REG && a->type == TYPE_MEM &&
-               a->reg == reg->reg &&
-               0 <= a->offset && a->offset < 4096;
-}
-
-int
-stackaddr(Addr *a)
-{
-       return a->type == TYPE_REG && a->reg == REGSP;
-}
similarity index 100%
rename from src/cmd/new9g/peep.go
rename to src/cmd/9g/peep.go
diff --git a/src/cmd/9g/prog.c b/src/cmd/9g/prog.c
deleted file mode 100644 (file)
index 561249c..0000000
+++ /dev/null
@@ -1,308 +0,0 @@
-// Copyright 2014 The Go Authors.  All rights reserved.
-// Use of this source code is governed by a BSD-style
-// license that can be found in the LICENSE file.
-
-#include <u.h>
-#include <libc.h>
-#include "gg.h"
-#include "../gc/popt.h"
-#include "opt.h"
-
-enum {
-       LeftRdwr = LeftRead | LeftWrite,
-       RightRdwr = RightRead | RightWrite,
-};
-
-// This table gives the basic information about instruction
-// generated by the compiler and processed in the optimizer.
-// See opt.h for bit definitions.
-//
-// Instructions not generated need not be listed.
-// As an exception to that rule, we typically write down all the
-// size variants of an operation even if we just use a subset.
-//
-// The table is formatted for 8-space tabs.
-static ProgInfo progtable[ALAST] = {
-       [ATYPE]=        {Pseudo | Skip},
-       [ATEXT]=        {Pseudo},
-       [AFUNCDATA]=    {Pseudo},
-       [APCDATA]=      {Pseudo},
-       [AUNDEF]=       {Break},
-       [AUSEFIELD]=    {OK},
-       [ACHECKNIL]=    {LeftRead},
-       [AVARDEF]=      {Pseudo | RightWrite},
-       [AVARKILL]=     {Pseudo | RightWrite},
-
-       // NOP is an internal no-op that also stands
-       // for USED and SET annotations, not the Power opcode.
-       [ANOP]=         {LeftRead | RightWrite},
-
-       // Integer
-       [AADD]=         {SizeQ | LeftRead | RegRead | RightWrite},
-       [ASUB]=         {SizeQ | LeftRead | RegRead | RightWrite},
-       [ANEG]=         {SizeQ | LeftRead | RegRead | RightWrite},
-       [AAND]=         {SizeQ | LeftRead | RegRead | RightWrite},
-       [AOR]=          {SizeQ | LeftRead | RegRead | RightWrite},
-       [AXOR]=         {SizeQ | LeftRead | RegRead | RightWrite},
-       [AMULLD]=       {SizeQ | LeftRead | RegRead | RightWrite},
-       [AMULLW]=       {SizeL | LeftRead | RegRead | RightWrite},
-       [AMULHD]=       {SizeL | LeftRead | RegRead | RightWrite},
-       [AMULHDU]=      {SizeL | LeftRead | RegRead | RightWrite},
-       [ADIVD]=        {SizeQ | LeftRead | RegRead | RightWrite},
-       [ADIVDU]=       {SizeQ | LeftRead | RegRead | RightWrite},
-       [ASLD]=         {SizeQ | LeftRead | RegRead | RightWrite},
-       [ASRD]=         {SizeQ | LeftRead | RegRead | RightWrite},
-       [ASRAD]=        {SizeQ | LeftRead | RegRead | RightWrite},
-       [ACMP]=         {SizeQ | LeftRead | RightRead},
-       [ACMPU]=        {SizeQ | LeftRead | RightRead},
-       [ATD]=          {SizeQ | RightRead},
-
-       // Floating point.
-       [AFADD]=        {SizeD | LeftRead | RegRead | RightWrite},
-       [AFADDS]=       {SizeF | LeftRead | RegRead | RightWrite},
-       [AFSUB]=        {SizeD | LeftRead | RegRead | RightWrite},
-       [AFSUBS]=       {SizeF | LeftRead | RegRead | RightWrite},
-       [AFMUL]=        {SizeD | LeftRead | RegRead | RightWrite},
-       [AFMULS]=       {SizeF | LeftRead | RegRead | RightWrite},
-       [AFDIV]=        {SizeD | LeftRead | RegRead | RightWrite},
-       [AFDIVS]=       {SizeF | LeftRead | RegRead | RightWrite},
-       [AFCTIDZ]=      {SizeF | LeftRead | RegRead | RightWrite},
-       [AFCFID]=       {SizeF | LeftRead | RegRead | RightWrite},
-       [AFCMPU]=       {SizeD | LeftRead | RightRead},
-       [AFRSP]=        {SizeD | LeftRead | RightWrite | Conv},
-
-       // Moves
-       [AMOVB]=        {SizeB | LeftRead | RightWrite | Move | Conv},
-       [AMOVBU]=       {SizeB | LeftRead | RightWrite | Move | Conv | PostInc},
-       [AMOVBZ]=       {SizeB | LeftRead | RightWrite | Move | Conv},
-       [AMOVH]=        {SizeW | LeftRead | RightWrite | Move | Conv},
-       [AMOVHU]=       {SizeW | LeftRead | RightWrite | Move | Conv | PostInc},
-       [AMOVHZ]=       {SizeW | LeftRead | RightWrite | Move | Conv},
-       [AMOVW]=        {SizeL | LeftRead | RightWrite | Move | Conv},
-       // there is no AMOVWU.
-       [AMOVWZU]=      {SizeL | LeftRead | RightWrite | Move | Conv | PostInc},
-       [AMOVWZ]=       {SizeL | LeftRead | RightWrite | Move | Conv},
-       [AMOVD]=        {SizeQ | LeftRead | RightWrite | Move},
-       [AMOVDU]=       {SizeQ | LeftRead | RightWrite | Move | PostInc},
-       [AFMOVS]=       {SizeF | LeftRead | RightWrite | Move | Conv},
-       [AFMOVD]=       {SizeD | LeftRead | RightWrite | Move},
-
-       // Jumps
-       [ABR]=          {Jump | Break},
-       [ABL]=          {Call},
-       [ABEQ]=         {Cjmp},
-       [ABNE]=         {Cjmp},
-       [ABGE]=         {Cjmp},
-       [ABLT]=         {Cjmp},
-       [ABGT]=         {Cjmp},
-       [ABLE]=         {Cjmp},
-       [ARETURN]=      {Break},
-
-       [ADUFFZERO]=    {Call},
-       [ADUFFCOPY]=    {Call},
-};
-
-static void
-initproginfo(void)
-{
-       static int initialized;
-       int addvariant[] = {V_CC, V_V, V_CC|V_V};
-       int as, as2, i, variant;
-
-       if(initialized)
-               return;
-       initialized = 1;
-
-       // Perform one-time expansion of instructions in progtable to
-       // their CC, V, and VCC variants
-       for(as=0; as<nelem(progtable); as++) {
-               if(progtable[as].flags == 0)
-                       continue;
-               variant = as2variant(as);
-               for(i=0; i<nelem(addvariant); i++) {
-                       as2 = variant2as(as, variant | addvariant[i]);
-                       if(as2 != 0 && progtable[as2].flags == 0)
-                               progtable[as2] = progtable[as];
-               }
-       }
-}
-
-void
-proginfo(ProgInfo *info, Prog *p)
-{
-       initproginfo();
-
-       *info = progtable[p->as];
-       if(info->flags == 0) {
-               *info = progtable[AADD];
-               fatal("proginfo: unknown instruction %P", p);
-       }
-
-       if((info->flags & RegRead) && p->reg == 0) {
-               info->flags &= ~RegRead;
-               info->flags |= /*CanRegRead |*/ RightRead;
-       }
-
-       if((p->from.type == TYPE_MEM || p->from.type == TYPE_ADDR) && p->from.reg != 0) {
-               info->regindex |= RtoB(p->from.reg);
-               if(info->flags & PostInc) {
-                       info->regset |= RtoB(p->from.reg);
-               }
-       }
-       if((p->to.type == TYPE_MEM || p->to.type == TYPE_ADDR) && p->to.reg != 0) {
-               info->regindex |= RtoB(p->to.reg);
-               if(info->flags & PostInc) {
-                       info->regset |= RtoB(p->to.reg);
-               }
-       }
-
-       if(p->from.type == TYPE_ADDR && p->from.sym != nil && (info->flags & LeftRead)) {
-               info->flags &= ~LeftRead;
-               info->flags |= LeftAddr;
-       }
-
-       if(p->as == ADUFFZERO) {
-               info->reguse |= (1<<0) | RtoB(REG_R3);
-               info->regset |= RtoB(REG_R3);
-       }
-       if(p->as == ADUFFCOPY) {
-               // TODO(austin) Revisit when duffcopy is implemented
-               info->reguse |= RtoB(REG_R3) | RtoB(REG_R4) | RtoB(REG_R5);
-               info->regset |= RtoB(REG_R3) | RtoB(REG_R4);
-       }
-}
-
-// Instruction variants table.  Initially this contains entries only
-// for the "base" form of each instruction.  On the first call to
-// as2variant or variant2as, we'll add the variants to the table.
-static int varianttable[ALAST][4] = {
-       [AADD]=         {AADD,          AADDCC,         AADDV,          AADDVCC},
-       [AADDC]=        {AADDC,         AADDCCC,        AADDCV,         AADDCVCC},
-       [AADDE]=        {AADDE,         AADDECC,        AADDEV,         AADDEVCC},
-       [AADDME]=       {AADDME,        AADDMECC,       AADDMEV,        AADDMEVCC},
-       [AADDZE]=       {AADDZE,        AADDZECC,       AADDZEV,        AADDZEVCC},
-       [AAND]=         {AAND,          AANDCC,         0,              0},
-       [AANDN]=        {AANDN,         AANDNCC,        0,              0},
-       [ACNTLZD]=      {ACNTLZD,       ACNTLZDCC,      0,              0},
-       [ACNTLZW]=      {ACNTLZW,       ACNTLZWCC,      0,              0},
-       [ADIVD]=        {ADIVD,         ADIVDCC,        ADIVDV,         ADIVDVCC},
-       [ADIVDU]=       {ADIVDU,        ADIVDUCC,       ADIVDUV,        ADIVDUVCC},
-       [ADIVW]=        {ADIVW,         ADIVWCC,        ADIVWV,         ADIVWVCC},
-       [ADIVWU]=       {ADIVWU,        ADIVWUCC,       ADIVWUV,        ADIVWUVCC},
-       [AEQV]=         {AEQV,          AEQVCC,         0,              0},
-       [AEXTSB]=       {AEXTSB,        AEXTSBCC,       0,              0},
-       [AEXTSH]=       {AEXTSH,        AEXTSHCC,       0,              0},
-       [AEXTSW]=       {AEXTSW,        AEXTSWCC,       0,              0},
-       [AFABS]=        {AFABS,         AFABSCC,        0,              0},
-       [AFADD]=        {AFADD,         AFADDCC,        0,              0},
-       [AFADDS]=       {AFADDS,        AFADDSCC,       0,              0},
-       [AFCFID]=       {AFCFID,        AFCFIDCC,       0,              0},
-       [AFCTID]=       {AFCTID,        AFCTIDCC,       0,              0},
-       [AFCTIDZ]=      {AFCTIDZ,       AFCTIDZCC,      0,              0},
-       [AFCTIW]=       {AFCTIW,        AFCTIWCC,       0,              0},
-       [AFCTIWZ]=      {AFCTIWZ,       AFCTIWZCC,      0,              0},
-       [AFDIV]=        {AFDIV,         AFDIVCC,        0,              0},
-       [AFDIVS]=       {AFDIVS,        AFDIVSCC,       0,              0},
-       [AFMADD]=       {AFMADD,        AFMADDCC,       0,              0},
-       [AFMADDS]=      {AFMADDS,       AFMADDSCC,      0,              0},
-       [AFMOVD]=       {AFMOVD,        AFMOVDCC,       0,              0},
-       [AFMSUB]=       {AFMSUB,        AFMSUBCC,       0,              0},
-       [AFMSUBS]=      {AFMSUBS,       AFMSUBSCC,      0,              0},
-       [AFMUL]=        {AFMUL,         AFMULCC,        0,              0},
-       [AFMULS]=       {AFMULS,        AFMULSCC,       0,              0},
-       [AFNABS]=       {AFNABS,        AFNABSCC,       0,              0},
-       [AFNEG]=        {AFNEG,         AFNEGCC,        0,              0},
-       [AFNMADD]=      {AFNMADD,       AFNMADDCC,      0,              0},
-       [AFNMADDS]=     {AFNMADDS,      AFNMADDSCC,     0,              0},
-       [AFNMSUB]=      {AFNMSUB,       AFNMSUBCC,      0,              0},
-       [AFNMSUBS]=     {AFNMSUBS,      AFNMSUBSCC,     0,              0},
-       [AFRES]=        {AFRES,         AFRESCC,        0,              0},
-       [AFRSP]=        {AFRSP,         AFRSPCC,        0,              0},
-       [AFRSQRTE]=     {AFRSQRTE,      AFRSQRTECC,     0,              0},
-       [AFSEL]=        {AFSEL,         AFSELCC,        0,              0},
-       [AFSQRT]=       {AFSQRT,        AFSQRTCC,       0,              0},
-       [AFSQRTS]=      {AFSQRTS,       AFSQRTSCC,      0,              0},
-       [AFSUB]=        {AFSUB,         AFSUBCC,        0,              0},
-       [AFSUBS]=       {AFSUBS,        AFSUBSCC,       0,              0},
-       [AMTFSB0]=      {AMTFSB0,       AMTFSB0CC,      0,              0},
-       [AMTFSB1]=      {AMTFSB1,       AMTFSB1CC,      0,              0},
-       [AMULHD]=       {AMULHD,        AMULHDCC,       0,              0},
-       [AMULHDU]=      {AMULHDU,       AMULHDUCC,      0,              0},
-       [AMULHW]=       {AMULHW,        AMULHWCC,       0,              0},
-       [AMULHWU]=      {AMULHWU,       AMULHWUCC,      0,              0},
-       [AMULLD]=       {AMULLD,        AMULLDCC,       AMULLDV,        AMULLDVCC},
-       [AMULLW]=       {AMULLW,        AMULLWCC,       AMULLWV,        AMULLWVCC},
-       [ANAND]=        {ANAND,         ANANDCC,        0,              0},
-       [ANEG]=         {ANEG,          ANEGCC,         ANEGV,          ANEGVCC},
-       [ANOR]=         {ANOR,          ANORCC,         0,              0},
-       [AOR]=          {AOR,           AORCC,          0,              0},
-       [AORN]=         {AORN,          AORNCC,         0,              0},
-       [AREM]=         {AREM,          AREMCC,         AREMV,          AREMVCC},
-       [AREMD]=        {AREMD,         AREMDCC,        AREMDV,         AREMDVCC},
-       [AREMDU]=       {AREMDU,        AREMDUCC,       AREMDUV,        AREMDUVCC},
-       [AREMU]=        {AREMU,         AREMUCC,        AREMUV,         AREMUVCC},
-       [ARLDC]=        {ARLDC,         ARLDCCC,        0,              0},
-       [ARLDCL]=       {ARLDCL,        ARLDCLCC,       0,              0},
-       [ARLDCR]=       {ARLDCR,        ARLDCRCC,       0,              0},
-       [ARLDMI]=       {ARLDMI,        ARLDMICC,       0,              0},
-       [ARLWMI]=       {ARLWMI,        ARLWMICC,       0,              0},
-       [ARLWNM]=       {ARLWNM,        ARLWNMCC,       0,              0},
-       [ASLD]=         {ASLD,          ASLDCC,         0,              0},
-       [ASLW]=         {ASLW,          ASLWCC,         0,              0},
-       [ASRAD]=        {ASRAD,         ASRADCC,        0,              0},
-       [ASRAW]=        {ASRAW,         ASRAWCC,        0,              0},
-       [ASRD]=         {ASRD,          ASRDCC,         0,              0},
-       [ASRW]=         {ASRW,          ASRWCC,         0,              0},
-       [ASUB]=         {ASUB,          ASUBCC,         ASUBV,          ASUBVCC},
-       [ASUBC]=        {ASUBC,         ASUBCCC,        ASUBCV,         ASUBCVCC},
-       [ASUBE]=        {ASUBE,         ASUBECC,        ASUBEV,         ASUBEVCC},
-       [ASUBME]=       {ASUBME,        ASUBMECC,       ASUBMEV,        ASUBMEVCC},
-       [ASUBZE]=       {ASUBZE,        ASUBZECC,       ASUBZEV,        ASUBZEVCC},
-       [AXOR]=         {AXOR,          AXORCC,         0,              0},
-};
-
-static void
-initvariants(void)
-{
-       static int initialized;
-       int i, j;
-
-       if(initialized)
-               return;
-       initialized = 1;
-
-       for(i=0; i<nelem(varianttable); i++) {
-               if(varianttable[i][0] == 0) {
-                       // Instruction has no variants
-                       varianttable[i][0] = i;
-                       continue;
-               }
-               // Copy base form to other variants
-               if(varianttable[i][0] == i) {
-                       for(j=0; j<nelem(varianttable[i]); j++)
-                               memmove(&varianttable[varianttable[i][j]], &varianttable[i], sizeof(varianttable[i]));
-               }
-       }
-}
-
-// as2variant returns the variant (V_*) flags of instruction as.
-int
-as2variant(int as)
-{
-       int i;
-       initvariants();
-       for(i=0; i<nelem(varianttable[as]); i++)
-               if(varianttable[as][i] == as)
-                       return i;
-       fatal("as2variant: instruction %A is not a variant of itself", as);
-       return 0;
-}
-
-// variant2as returns the instruction as with the given variant (V_*) flags.
-// If no such variant exists, this returns 0.
-int
-variant2as(int as, int flags)
-{
-       initvariants();
-       return varianttable[as][flags];
-}
similarity index 100%
rename from src/cmd/new9g/prog.go
rename to src/cmd/9g/prog.go
diff --git a/src/cmd/9g/reg.c b/src/cmd/9g/reg.c
deleted file mode 100644 (file)
index 84e1747..0000000
+++ /dev/null
@@ -1,172 +0,0 @@
-// Derived from Inferno utils/6c/reg.c
-// http://code.google.com/p/inferno-os/source/browse/utils/6c/reg.c
-//
-//     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 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 <u.h>
-#include <libc.h>
-#include "gg.h"
-#include "../gc/popt.h"
-
-enum {
-       NREGVAR = 64,   /* 32 general + 32 floating */
-};
-
-
-static char* regname[] = {
-       ".R0",
-       ".R1",
-       ".R2",
-       ".R3",
-       ".R4",
-       ".R5",
-       ".R6",
-       ".R7",
-       ".R8",
-       ".R9",
-       ".R10",
-       ".R11",
-       ".R12",
-       ".R13",
-       ".R14",
-       ".R15",
-       ".R16",
-       ".R17",
-       ".R18",
-       ".R19",
-       ".R20",
-       ".R21",
-       ".R22",
-       ".R23",
-       ".R24",
-       ".R25",
-       ".R26",
-       ".R27",
-       ".R28",
-       ".R29",
-       ".R30",
-       ".R31",
-       ".F0",
-       ".F1",
-       ".F2",
-       ".F3",
-       ".F4",
-       ".F5",
-       ".F6",
-       ".F7",
-       ".F8",
-       ".F9",
-       ".F10",
-       ".F11",
-       ".F12",
-       ".F13",
-       ".F14",
-       ".F15",
-       ".F16",
-       ".F17",
-       ".F18",
-       ".F19",
-       ".F20",
-       ".F21",
-       ".F22",
-       ".F23",
-       ".F24",
-       ".F25",
-       ".F26",
-       ".F27",
-       ".F28",
-       ".F29",
-       ".F30",
-       ".F31",
-};
-
-char**
-regnames(int *n)
-{
-       *n = NREGVAR;
-       return regname;
-}
-
-uint64
-excludedregs(void)
-{
-       uint64 regbits;
-
-       // Exclude registers with fixed functions
-       regbits = (1<<0)|RtoB(REGSP)|RtoB(REGG)|RtoB(REGTLS);
-       // Also exclude floating point registers with fixed constants
-       regbits |= RtoB(REG_F27)|RtoB(REG_F28)|RtoB(REG_F29)|RtoB(REG_F30)|RtoB(REG_F31);
-       return regbits;
-}
-
-uint64
-doregbits(int r)
-{
-       USED(r);
-       return 0;
-}
-
-/*
- * track register variables including external registers:
- *     bit     reg
- *     0       R0
- *     1       R1
- *     ...     ...
- *     31      R31
- *     32+0    F0
- *     32+1    F1
- *     ...     ...
- *     32+31   F31
- */
-uint64
-RtoB(int r)
-{
-       if(r > REG_R0 && r <= REG_R31)
-               return 1ULL << (r - REG_R0);
-       if(r >= REG_F0 && r <= REG_F31)
-               return 1ULL << (32 + r - REG_F0);
-       return 0;
-}
-
-int
-BtoR(uint64 b)
-{
-       b &= 0xffffffffull;
-       if(b == 0)
-               return 0;
-       return bitno(b) + REG_R0;
-}
-
-int
-BtoF(uint64 b)
-{
-       b >>= 32;
-       if(b == 0)
-               return 0;
-       return bitno(b) + REG_F0;
-}
similarity index 100%
rename from src/cmd/new9g/reg.go
rename to src/cmd/9g/reg.go
similarity index 100%
rename from src/cmd/new9g/util.go
rename to src/cmd/9g/util.go
diff --git a/src/cmd/gc/Makefile b/src/cmd/gc/Makefile
deleted file mode 100644 (file)
index 58e25fa..0000000
+++ /dev/null
@@ -1,17 +0,0 @@
-# Copyright 2012 The Go Authors. All rights reserved.
-# Use of this source code is governed by a BSD-style
-# license that can be found in the LICENSE file.
-
-include ../../Make.dist
-
-install: y.tab.h builtin.c
-
-y.tab.h: go.y go.errors bisonerrors
-       bison -v -y -d go.y
-       # make yystate global, yytname mutable
-       cat y.tab.c | sed '/ int yystate;/d; s/int yychar;/int yychar, yystate;/; s/static const char \*const yytname/const char *yytname/; s/char const \*yymsgp/char *yymsgp/' >y1.tab.c
-       mv y1.tab.c y.tab.c
-       awk -f bisonerrors y.output go.errors >yerr.h
-
-builtin.c: runtime.go unsafe.go
-       ./mkbuiltin
diff --git a/src/cmd/gc/align.c b/src/cmd/gc/align.c
deleted file mode 100644 (file)
index 59ff0ab..0000000
+++ /dev/null
@@ -1,689 +0,0 @@
-// Copyright 2009 The Go Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style
-// license that can be found in the LICENSE file.
-
-#include <u.h>
-#include <libc.h>
-#include "go.h"
-
-/*
- * machine size and rounding
- * alignment is dictated around
- * the size of a pointer, set in betypeinit
- * (see ../6g/galign.c).
- */
-
-static int defercalc;
-
-vlong
-rnd(vlong o, vlong r)
-{
-       if(r < 1 || r > 8 || (r&(r-1)) != 0)
-               fatal("rnd %lld", r);
-       return (o+r-1)&~(r-1);
-}
-
-static void
-offmod(Type *t)
-{
-       Type *f;
-       int32 o;
-
-       o = 0;
-       for(f=t->type; f!=T; f=f->down) {
-               if(f->etype != TFIELD)
-                       fatal("offmod: not TFIELD: %lT", f);
-               f->width = o;
-               o += widthptr;
-               if(o >= thearch.MAXWIDTH) {
-                       yyerror("interface too large");
-                       o = widthptr;
-               }
-       }
-}
-
-static vlong
-widstruct(Type *errtype, Type *t, vlong o, int flag)
-{
-       Type *f;
-       int64 w;
-       int32 maxalign;
-       vlong starto, lastzero;
-       
-       starto = o;
-       maxalign = flag;
-       if(maxalign < 1)
-               maxalign = 1;
-       lastzero = 0;
-       for(f=t->type; f!=T; f=f->down) {
-               if(f->etype != TFIELD)
-                       fatal("widstruct: not TFIELD: %lT", f);
-               if(f->type == T) {
-                       // broken field, just skip it so that other valid fields
-                       // get a width.
-                       continue;
-               }
-               dowidth(f->type);
-               if(f->type->align > maxalign)
-                       maxalign = f->type->align;
-               if(f->type->width < 0)
-                       fatal("invalid width %lld", f->type->width);
-               w = f->type->width;
-               if(f->type->align > 0)
-                       o = rnd(o, f->type->align);
-               f->width = o;   // really offset for TFIELD
-               if(f->nname != N) {
-                       // this same stackparam logic is in addrescapes
-                       // in typecheck.c.  usually addrescapes runs after
-                       // widstruct, in which case we could drop this,
-                       // but function closure functions are the exception.
-                       if(f->nname->stackparam) {
-                               f->nname->stackparam->xoffset = o;
-                               f->nname->xoffset = 0;
-                       } else
-                               f->nname->xoffset = o;
-               }
-               if(w == 0)
-                       lastzero = o;
-               o += w;
-               if(o >= thearch.MAXWIDTH) {
-                       yyerror("type %lT too large", errtype);
-                       o = 8;  // small but nonzero
-               }
-       }
-       // For nonzero-sized structs which end in a zero-sized thing, we add
-       // an extra byte of padding to the type.  This padding ensures that
-       // taking the address of the zero-sized thing can't manufacture a
-       // pointer to the next object in the heap.  See issue 9401.
-       if(flag == 1 && o > starto && o == lastzero)
-               o++;
-
-       // final width is rounded
-       if(flag)
-               o = rnd(o, maxalign);
-       t->align = maxalign;
-
-       // type width only includes back to first field's offset
-       t->width = o - starto;
-       return o;
-}
-
-void
-dowidth(Type *t)
-{
-       int32 et;
-       int64 w;
-       int lno;
-       Type *t1;
-
-       if(widthptr == 0)
-               fatal("dowidth without betypeinit");
-
-       if(t == T)
-               return;
-
-       if(t->width > 0)
-               return;
-
-       if(t->width == -2) {
-               lno = lineno;
-               lineno = t->lineno;
-               if(!t->broke) {
-                       t->broke = 1;
-                       yyerror("invalid recursive type %T", t);
-               }
-               t->width = 0;
-               lineno = lno;
-               return;
-       }
-
-       // break infinite recursion if the broken recursive type
-       // is referenced again
-       if(t->broke && t->width == 0)
-               return;
-
-       // defer checkwidth calls until after we're done
-       defercalc++;
-
-       lno = lineno;
-       lineno = t->lineno;
-       t->width = -2;
-       t->align = 0;
-
-       et = t->etype;
-       switch(et) {
-       case TFUNC:
-       case TCHAN:
-       case TMAP:
-       case TSTRING:
-               break;
-
-       default:
-               /* simtype == 0 during bootstrap */
-               if(simtype[t->etype] != 0)
-                       et = simtype[t->etype];
-               break;
-       }
-
-       w = 0;
-       switch(et) {
-       default:
-               fatal("dowidth: unknown type: %T", t);
-               break;
-
-       /* compiler-specific stuff */
-       case TINT8:
-       case TUINT8:
-       case TBOOL:             // bool is int8
-               w = 1;
-               break;
-       case TINT16:
-       case TUINT16:
-               w = 2;
-               break;
-       case TINT32:
-       case TUINT32:
-       case TFLOAT32:
-               w = 4;
-               break;
-       case TINT64:
-       case TUINT64:
-       case TFLOAT64:
-       case TCOMPLEX64:
-               w = 8;
-               t->align = widthreg;
-               break;
-       case TCOMPLEX128:
-               w = 16;
-               t->align = widthreg;
-               break;
-       case TPTR32:
-               w = 4;
-               checkwidth(t->type);
-               break;
-       case TPTR64:
-               w = 8;
-               checkwidth(t->type);
-               break;
-       case TUNSAFEPTR:
-               w = widthptr;
-               break;
-       case TINTER:            // implemented as 2 pointers
-               w = 2*widthptr;
-               t->align = widthptr;
-               offmod(t);
-               break;
-       case TCHAN:             // implemented as pointer
-               w = widthptr;
-               checkwidth(t->type);
-
-               // make fake type to check later to
-               // trigger channel argument check.
-               t1 = typ(TCHANARGS);
-               t1->type = t;
-               checkwidth(t1);
-               break;
-       case TCHANARGS:
-               t1 = t->type;
-               dowidth(t->type);       // just in case
-               if(t1->type->width >= (1<<16))
-                       yyerror("channel element type too large (>64kB)");
-               t->width = 1;
-               break;
-       case TMAP:              // implemented as pointer
-               w = widthptr;
-               checkwidth(t->type);
-               checkwidth(t->down);
-               break;
-       case TFORW:             // should have been filled in
-               if(!t->broke)
-                       yyerror("invalid recursive type %T", t);
-               w = 1;  // anything will do
-               break;
-       case TANY:
-               // dummy type; should be replaced before use.
-               if(!debug['A'])
-                       fatal("dowidth any");
-               w = 1;  // anything will do
-               break;
-       case TSTRING:
-               if(sizeof_String == 0)
-                       fatal("early dowidth string");
-               w = sizeof_String;
-               t->align = widthptr;
-               break;
-       case TARRAY:
-               if(t->type == T)
-                       break;
-               if(t->bound >= 0) {
-                       uint64 cap;
-
-                       dowidth(t->type);
-                       if(t->type->width != 0) {
-                               cap = (thearch.MAXWIDTH-1) / t->type->width;
-                               if(t->bound > cap)
-                                       yyerror("type %lT larger than address space", t);
-                       }
-                       w = t->bound * t->type->width;
-                       t->align = t->type->align;
-               }
-               else if(t->bound == -1) {
-                       w = sizeof_Array;
-                       checkwidth(t->type);
-                       t->align = widthptr;
-               }
-               else if(t->bound == -100) {
-                       if(!t->broke) {
-                               yyerror("use of [...] array outside of array literal");
-                               t->broke = 1;
-                       }
-               }
-               else
-                       fatal("dowidth %T", t); // probably [...]T
-               break;
-
-       case TSTRUCT:
-               if(t->funarg)
-                       fatal("dowidth fn struct %T", t);
-               w = widstruct(t, t, 0, 1);
-               break;
-
-       case TFUNC:
-               // make fake type to check later to
-               // trigger function argument computation.
-               t1 = typ(TFUNCARGS);
-               t1->type = t;
-               checkwidth(t1);
-
-               // width of func type is pointer
-               w = widthptr;
-               break;
-
-       case TFUNCARGS:
-               // function is 3 cated structures;
-               // compute their widths as side-effect.
-               t1 = t->type;
-               w = widstruct(t->type, *getthis(t1), 0, 0);
-               w = widstruct(t->type, *getinarg(t1), w, widthreg);
-               w = widstruct(t->type, *getoutarg(t1), w, widthreg);
-               t1->argwid = w;
-               if(w%widthreg)
-                       warn("bad type %T %d\n", t1, w);
-               t->align = 1;
-               break;
-       }
-
-       if(widthptr == 4 && w != (int32)w)
-               yyerror("type %T too large", t);
-
-       t->width = w;
-       if(t->align == 0) {
-               if(w > 8 || (w&(w-1)) != 0)
-                       fatal("invalid alignment for %T", t);
-               t->align = w;
-       }
-       lineno = lno;
-
-       if(defercalc == 1)
-               resumecheckwidth();
-       else
-               --defercalc;
-}
-
-/*
- * when a type's width should be known, we call checkwidth
- * to compute it.  during a declaration like
- *
- *     type T *struct { next T }
- *
- * it is necessary to defer the calculation of the struct width
- * until after T has been initialized to be a pointer to that struct.
- * similarly, during import processing structs may be used
- * before their definition.  in those situations, calling
- * defercheckwidth() stops width calculations until
- * resumecheckwidth() is called, at which point all the
- * checkwidths that were deferred are executed.
- * dowidth should only be called when the type's size
- * is needed immediately.  checkwidth makes sure the
- * size is evaluated eventually.
- */
-typedef struct TypeList TypeList;
-struct TypeList {
-       Type *t;
-       TypeList *next;
-};
-
-static TypeList *tlfree;
-static TypeList *tlq;
-
-void
-checkwidth(Type *t)
-{
-       TypeList *l;
-
-       if(t == T)
-               return;
-
-       // function arg structs should not be checked
-       // outside of the enclosing function.
-       if(t->funarg)
-               fatal("checkwidth %T", t);
-
-       if(!defercalc) {
-               dowidth(t);
-               return;
-       }
-       if(t->deferwidth)
-               return;
-       t->deferwidth = 1;
-
-       l = tlfree;
-       if(l != nil)
-               tlfree = l->next;
-       else
-               l = mal(sizeof *l);
-
-       l->t = t;
-       l->next = tlq;
-       tlq = l;
-}
-
-void
-defercheckwidth(void)
-{
-       // we get out of sync on syntax errors, so don't be pedantic.
-       if(defercalc && nerrors == 0)
-               fatal("defercheckwidth");
-       defercalc = 1;
-}
-
-void
-resumecheckwidth(void)
-{
-       TypeList *l;
-
-       if(!defercalc)
-               fatal("resumecheckwidth");
-       for(l = tlq; l != nil; l = tlq) {
-               l->t->deferwidth = 0;
-               tlq = l->next;
-               dowidth(l->t);
-               l->next = tlfree;
-               tlfree = l;
-       }
-       defercalc = 0;
-}
-
-void
-typeinit(void)
-{
-       int i, etype, sameas;
-       Type *t;
-       Sym *s, *s1;
-
-       if(widthptr == 0)
-               fatal("typeinit before betypeinit");
-
-       for(i=0; i<NTYPE; i++)
-               simtype[i] = i;
-
-       types[TPTR32] = typ(TPTR32);
-       dowidth(types[TPTR32]);
-
-       types[TPTR64] = typ(TPTR64);
-       dowidth(types[TPTR64]);
-       
-       t = typ(TUNSAFEPTR);
-       types[TUNSAFEPTR] = t;
-       t->sym = pkglookup("Pointer", unsafepkg);
-       t->sym->def = typenod(t);
-       
-       dowidth(types[TUNSAFEPTR]);
-
-       tptr = TPTR32;
-       if(widthptr == 8)
-               tptr = TPTR64;
-
-       for(i=TINT8; i<=TUINT64; i++)
-               isint[i] = 1;
-       isint[TINT] = 1;
-       isint[TUINT] = 1;
-       isint[TUINTPTR] = 1;
-
-       isfloat[TFLOAT32] = 1;
-       isfloat[TFLOAT64] = 1;
-
-       iscomplex[TCOMPLEX64] = 1;
-       iscomplex[TCOMPLEX128] = 1;
-
-       isptr[TPTR32] = 1;
-       isptr[TPTR64] = 1;
-
-       isforw[TFORW] = 1;
-
-       issigned[TINT] = 1;
-       issigned[TINT8] = 1;
-       issigned[TINT16] = 1;
-       issigned[TINT32] = 1;
-       issigned[TINT64] = 1;
-
-       /*
-        * initialize okfor
-        */
-       for(i=0; i<NTYPE; i++) {
-               if(isint[i] || i == TIDEAL) {
-                       okforeq[i] = 1;
-                       okforcmp[i] = 1;
-                       okforarith[i] = 1;
-                       okforadd[i] = 1;
-                       okforand[i] = 1;
-                       okforconst[i] = 1;
-                       issimple[i] = 1;
-                       minintval[i] = mal(sizeof(*minintval[i]));
-                       maxintval[i] = mal(sizeof(*maxintval[i]));
-               }
-               if(isfloat[i]) {
-                       okforeq[i] = 1;
-                       okforcmp[i] = 1;
-                       okforadd[i] = 1;
-                       okforarith[i] = 1;
-                       okforconst[i] = 1;
-                       issimple[i] = 1;
-                       minfltval[i] = mal(sizeof(*minfltval[i]));
-                       maxfltval[i] = mal(sizeof(*maxfltval[i]));
-               }
-               if(iscomplex[i]) {
-                       okforeq[i] = 1;
-                       okforadd[i] = 1;
-                       okforarith[i] = 1;
-                       okforconst[i] = 1;
-                       issimple[i] = 1;
-               }
-       }
-
-       issimple[TBOOL] = 1;
-
-       okforadd[TSTRING] = 1;
-
-       okforbool[TBOOL] = 1;
-
-       okforcap[TARRAY] = 1;
-       okforcap[TCHAN] = 1;
-
-       okforconst[TBOOL] = 1;
-       okforconst[TSTRING] = 1;
-
-       okforlen[TARRAY] = 1;
-       okforlen[TCHAN] = 1;
-       okforlen[TMAP] = 1;
-       okforlen[TSTRING] = 1;
-
-       okforeq[TPTR32] = 1;
-       okforeq[TPTR64] = 1;
-       okforeq[TUNSAFEPTR] = 1;
-       okforeq[TINTER] = 1;
-       okforeq[TCHAN] = 1;
-       okforeq[TSTRING] = 1;
-       okforeq[TBOOL] = 1;
-       okforeq[TMAP] = 1;      // nil only; refined in typecheck
-       okforeq[TFUNC] = 1;     // nil only; refined in typecheck
-       okforeq[TARRAY] = 1;    // nil slice only; refined in typecheck
-       okforeq[TSTRUCT] = 1;   // it's complicated; refined in typecheck
-
-       okforcmp[TSTRING] = 1;
-
-       for(i=0; i<nelem(okfor); i++)
-               okfor[i] = okfornone;
-
-       // binary
-       okfor[OADD] = okforadd;
-       okfor[OAND] = okforand;
-       okfor[OANDAND] = okforbool;
-       okfor[OANDNOT] = okforand;
-       okfor[ODIV] = okforarith;
-       okfor[OEQ] = okforeq;
-       okfor[OGE] = okforcmp;
-       okfor[OGT] = okforcmp;
-       okfor[OLE] = okforcmp;
-       okfor[OLT] = okforcmp;
-       okfor[OMOD] = okforand;
-       okfor[OMUL] = okforarith;
-       okfor[ONE] = okforeq;
-       okfor[OOR] = okforand;
-       okfor[OOROR] = okforbool;
-       okfor[OSUB] = okforarith;
-       okfor[OXOR] = okforand;
-       okfor[OLSH] = okforand;
-       okfor[ORSH] = okforand;
-
-       // unary
-       okfor[OCOM] = okforand;
-       okfor[OMINUS] = okforarith;
-       okfor[ONOT] = okforbool;
-       okfor[OPLUS] = okforarith;
-
-       // special
-       okfor[OCAP] = okforcap;
-       okfor[OLEN] = okforlen;
-
-       // comparison
-       iscmp[OLT] = 1;
-       iscmp[OGT] = 1;
-       iscmp[OGE] = 1;
-       iscmp[OLE] = 1;
-       iscmp[OEQ] = 1;
-       iscmp[ONE] = 1;
-
-       mpatofix(maxintval[TINT8], "0x7f");
-       mpatofix(minintval[TINT8], "-0x80");
-       mpatofix(maxintval[TINT16], "0x7fff");
-       mpatofix(minintval[TINT16], "-0x8000");
-       mpatofix(maxintval[TINT32], "0x7fffffff");
-       mpatofix(minintval[TINT32], "-0x80000000");
-       mpatofix(maxintval[TINT64], "0x7fffffffffffffff");
-       mpatofix(minintval[TINT64], "-0x8000000000000000");
-
-       mpatofix(maxintval[TUINT8], "0xff");
-       mpatofix(maxintval[TUINT16], "0xffff");
-       mpatofix(maxintval[TUINT32], "0xffffffff");
-       mpatofix(maxintval[TUINT64], "0xffffffffffffffff");
-
-       /* f is valid float if min < f < max.  (min and max are not themselves valid.) */
-       mpatoflt(maxfltval[TFLOAT32], "33554431p103");  /* 2^24-1 p (127-23) + 1/2 ulp*/
-       mpatoflt(minfltval[TFLOAT32], "-33554431p103");
-       mpatoflt(maxfltval[TFLOAT64], "18014398509481983p970"); /* 2^53-1 p (1023-52) + 1/2 ulp */
-       mpatoflt(minfltval[TFLOAT64], "-18014398509481983p970");
-
-       maxfltval[TCOMPLEX64] = maxfltval[TFLOAT32];
-       minfltval[TCOMPLEX64] = minfltval[TFLOAT32];
-       maxfltval[TCOMPLEX128] = maxfltval[TFLOAT64];
-       minfltval[TCOMPLEX128] = minfltval[TFLOAT64];
-
-       /* for walk to use in error messages */
-       types[TFUNC] = functype(N, nil, nil);
-
-       /* types used in front end */
-       // types[TNIL] got set early in lexinit
-       types[TIDEAL] = typ(TIDEAL);
-       types[TINTER] = typ(TINTER);
-
-       /* simple aliases */
-       simtype[TMAP] = tptr;
-       simtype[TCHAN] = tptr;
-       simtype[TFUNC] = tptr;
-       simtype[TUNSAFEPTR] = tptr;
-
-       /* pick up the backend thearch.typedefs */
-       for(i=0; thearch.typedefs[i].name; i++) {
-               s = lookup(thearch.typedefs[i].name);
-               s1 = pkglookup(thearch.typedefs[i].name, builtinpkg);
-
-               etype = thearch.typedefs[i].etype;
-               if(etype < 0 || etype >= nelem(types))
-                       fatal("typeinit: %s bad etype", s->name);
-               sameas = thearch.typedefs[i].sameas;
-               if(sameas < 0 || sameas >= nelem(types))
-                       fatal("typeinit: %s bad sameas", s->name);
-               simtype[etype] = sameas;
-               minfltval[etype] = minfltval[sameas];
-               maxfltval[etype] = maxfltval[sameas];
-               minintval[etype] = minintval[sameas];
-               maxintval[etype] = maxintval[sameas];
-
-               t = types[etype];
-               if(t != T)
-                       fatal("typeinit: %s already defined", s->name);
-
-               t = typ(etype);
-               t->sym = s1;
-
-               dowidth(t);
-               types[etype] = t;
-               s1->def = typenod(t);
-       }
-
-       Array_array = rnd(0, widthptr);
-       Array_nel = rnd(Array_array+widthptr, widthint);
-       Array_cap = rnd(Array_nel+widthint, widthint);
-       sizeof_Array = rnd(Array_cap+widthint, widthptr);
-
-       // string is same as slice wo the cap
-       sizeof_String = rnd(Array_nel+widthint, widthptr);
-
-       dowidth(types[TSTRING]);
-       dowidth(idealstring);
-}
-
-/*
- * compute total size of f's in/out arguments.
- */
-int
-argsize(Type *t)
-{
-       Iter save;
-       Type *fp;
-       int64 w, x;
-
-       w = 0;
-
-       fp = structfirst(&save, getoutarg(t));
-       while(fp != T) {
-               x = fp->width + fp->type->width;
-               if(x > w)
-                       w = x;
-               fp = structnext(&save);
-       }
-
-       fp = funcfirst(&save, t);
-       while(fp != T) {
-               x = fp->width + fp->type->width;
-               if(x > w)
-                       w = x;
-               fp = funcnext(&save);
-       }
-
-       w = (w+widthptr-1) & ~(widthptr-1);
-       if((int)w != w)
-               fatal("argsize too big");
-       return w;
-}
diff --git a/src/cmd/gc/array.c b/src/cmd/gc/array.c
deleted file mode 100644 (file)
index d5d9646..0000000
+++ /dev/null
@@ -1,107 +0,0 @@
-// Copyright 2013 The Go Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style
-// license that can be found in the LICENSE file.
-
-#include <u.h>
-#include <libc.h>
-#include "go.h"
-
-enum {
-       DEFAULTCAPACITY = 16,
-};
-
-Array*
-arraynew(int capacity, int32 size)
-{
-       Array *result;
-
-       if(capacity < 0)
-               fatal("arraynew: capacity %d is not positive", capacity);
-       if(size < 0)
-               fatal("arraynew: size %d is not positive\n", size);
-       result = malloc(sizeof(*result));
-       if(result == nil)
-               fatal("arraynew: malloc failed\n");
-       result->length = 0;
-       result->size = size;
-       result->capacity = capacity == 0 ? DEFAULTCAPACITY : capacity;
-       result->data = malloc(result->capacity * result->size);
-       if(result->data == nil)
-               fatal("arraynew: malloc failed\n");
-       return result;
-}
-
-void
-arrayfree(Array *array)
-{
-       if(array == nil)
-               return;
-       free(array->data);
-       free(array);
-}
-
-int
-arraylength(Array *array)
-{
-       return array->length;
-}
-
-void*
-arrayget(Array *array, int index)
-{
-       if(array == nil)
-               fatal("arrayget: array is nil\n");
-       if(index < 0 || index >= array->length)
-               fatal("arrayget: index %d is out of bounds for length %d\n", index, array->length);
-       return array->data + index * array->size;
-}
-
-void
-arrayset(Array *array, int index, void *element)
-{
-       if(array == nil)
-               fatal("arrayset: array is nil\n");
-       if(element == nil)
-               fatal("arrayset: element is nil\n");
-       if(index < 0 || index >= array->length)
-               fatal("arrayget: index %d is out of bounds for length %d\n", index, array->length);
-       memmove(array->data + index * array->size, element, array->size);
-}
-
-static void
-ensurecapacity(Array *array, int capacity)
-{
-       int32 newcapacity;
-       char *newdata;
-
-       if(array == nil)
-               fatal("ensurecapacity: array is nil\n");
-       if(capacity < 0)
-               fatal("ensurecapacity: capacity %d is not positive", capacity);
-       if(capacity >= array->capacity) {
-               newcapacity = capacity + (capacity >> 1);
-               newdata = realloc(array->data, newcapacity * array->size);
-               if(newdata == nil)
-                       fatal("ensurecapacity: realloc failed\n");
-               array->capacity = newcapacity;
-               array->data = newdata;
-       }
-}
-
-void
-arrayadd(Array *array, void *element)
-{
-       if(array == nil)
-               fatal("arrayset: array is nil\n");
-       if(element == nil)
-               fatal("arrayset: element is nil\n");
-       ensurecapacity(array, array->length + 1);
-       array->length++;
-       arrayset(array, array->length - 1, element);
-}
-
-void
-arraysort(Array *array, int (*cmp)(const void*, const void*))
-{
-       qsort(array->data, array->length, array->size, cmp);
-}
diff --git a/src/cmd/gc/bisonerrors b/src/cmd/gc/bisonerrors
deleted file mode 100755 (executable)
index fa74c67..0000000
+++ /dev/null
@@ -1,156 +0,0 @@
-#!/usr/bin/awk -f
-# Copyright 2010 The Go Authors.  All rights reserved.
-# Use of this source code is governed by a BSD-style
-# license that can be found in the LICENSE file.
-
-# This program implements the core idea from
-#
-#      Clinton L. Jeffery, Generating LR syntax error messages from examples,
-#      ACM TOPLAS 25(5) (September 2003).  http://doi.acm.org/10.1145/937563.937566
-# 
-# It reads Bison's summary of a grammar followed by a file
-# like go.errors, replacing lines beginning with % by the 
-# yystate and yychar that will be active when an error happens
-# while parsing that line.  
-#
-# Unlike the system described in the paper, the lines in go.errors
-# give grammar symbol name lists, not actual program fragments.
-# This is a little less programmer-friendly but doesn't require being
-# able to run the text through lex.c.
-
-BEGIN{
-       bison = 1
-       grammar = 0
-       states = 0
-       open = 0
-}
-
-# In Grammar section of y.output,
-# record lhs and length of rhs for each rule.
-bison && /^Grammar/ { grammar = 1 }
-bison && /^(Terminals|state 0)/ { grammar = 0 }
-grammar && NF>0 {
-       if($2 != "|") {
-               r = $2
-               sub(/:$/, "", r)
-       }
-       rulelhs[$1] = r
-       rulesize[$1] = NF-2
-       if(rulesize[$1] == 1 && $3 == "%empty") {
-               rulesize[$1] = 0
-       }
-       if(rulesize[$1] == 3 && $3 $4 $5 == "/*empty*/") {
-               rulesize[$1] = 0
-       }
-}
-
-# In state dumps, record shift/reduce actions.
-bison && /^[Ss]tate 0/ { grammar = 0; states = 1 }
-
-states && /^[Ss]tate / { state = $2 }
-states { statetext[state] = statetext[state] $0 "\n" }
-
-states && / shift/ {
-       n = nshift[state]++
-       if($0 ~ /and go to/)
-               shift[state,n] = $7 # GNU Bison
-       else
-               shift[state,n] = $3 # Plan 9 Yacc
-       shifttoken[state,n] = $1
-       next
-}
-states && / (go to|goto)/ {
-       n = nshift[state]++
-       if($0 ~ /go to/)
-               shift[state,n] = $5 # GNU Bison
-       else
-               shift[state,n] = $3 # Plan 9 Yacc
-       shifttoken[state,n] = $1
-       next
-}
-states && / reduce/ {
-       n = nreduce[state]++
-       if($0 ~ /reduce using rule/)
-               reduce[state,n] = $5 # GNU Bison
-       else
-               reduce[state,n] = $3 # Plan 9 yacc
-       reducetoken[state,n] = $1
-       next
-}
-
-# Skip over the summary information printed by Plan 9 yacc.
-/nonterminals$/,/^maximum spread/ { next }
-
-# First // comment marks the beginning of the pattern file.
-/^\/\// { bison = 0; grammar = 0; state = 0 }
-bison { next }
-
-# Treat % as first field on line as introducing a pattern (token sequence).
-# Run it through the LR machine and print the induced "yystate, yychar,"
-# at the point where the error happens.
-$1 == "%" {
-       nstack = 0
-       state = 0
-       f = 2
-       tok = ""
-       for(;;) {
-               if(tok == "" && f <= NF) {
-                       tok = $f
-                       f++
-               }
-               found = 0
-               for(j=0; j<nshift[state]; j++) {
-                       if(shifttoken[state,j] == tok) {
-                               # print "SHIFT " tok " " state " -> " shift[state,j]
-                               stack[nstack++] = state
-                               state = shift[state,j]
-                               found = 1
-                               tok = ""
-                               break
-                       }
-               }
-               if(found)
-                       continue
-               for(j=0; j<nreduce[state]; j++) {
-                       t = reducetoken[state,j]
-                       if(t == tok || t == "$default" || t == ".") {
-                               stack[nstack++] = state
-                               rule = reduce[state,j]
-                               nstack -= rulesize[rule]
-                               state = stack[--nstack]
-                               lhs = rulelhs[rule]
-                               if(tok != "")
-                                       --f
-                               tok = rulelhs[rule]
-                               # print "REDUCE " nstack " " state " " tok " rule " rule " size " rulesize[rule]
-                               found = 1
-                               break
-                       }
-               }
-               if(found)
-                       continue
-
-               # No shift or reduce applied - found the error.
-               printf("\t{%s, %s,\n", state, tok);
-               open = 1;
-               break
-       }
-       next
-}
-
-# Print other lines verbatim.
-open && /,$/ {
-       s = $0;
-       sub(",", "},", s)
-       print s
-       open = 0
-       next
-}
-
-open && /"$/ {
-       print $0 "}"
-       open = 0
-       next
-}
-
-{print}
diff --git a/src/cmd/gc/bits.c b/src/cmd/gc/bits.c
deleted file mode 100644 (file)
index 21e25dd..0000000
+++ /dev/null
@@ -1,173 +0,0 @@
-// Inferno utils/cc/bits.c
-// http://code.google.com/p/inferno-os/source/browse/utils/cc/bits.c
-//
-//     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 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 <u.h>
-#include <libc.h>
-#include "go.h"
-
-/*
-Bits
-bor(Bits a, Bits b)
-{
-       Bits c;
-       int i;
-
-       for(i=0; i<BITS; i++)
-               c.b[i] = a.b[i] | b.b[i];
-       return c;
-}
-
-Bits
-band(Bits a, Bits b)
-{
-       Bits c;
-       int i;
-
-       for(i=0; i<BITS; i++)
-               c.b[i] = a.b[i] & b.b[i];
-       return c;
-}
-
-Bits
-bnot(Bits a)
-{
-       Bits c;
-       int i;
-
-       for(i=0; i<BITS; i++)
-               c.b[i] = ~a.b[i];
-       return c;
-}
-*/
-
-int
-bany(Bits *a)
-{
-       int i;
-
-       for(i=0; i<BITS; i++)
-               if(a->b[i])
-                       return 1;
-       return 0;
-}
-
-/*
-int
-beq(Bits a, Bits b)
-{
-       int i;
-
-       for(i=0; i<BITS; i++)
-               if(a.b[i] != b.b[i])
-                       return 0;
-       return 1;
-}
-*/
-
-int
-bnum(Bits a)
-{
-       int i;
-       uint64 b;
-
-       for(i=0; i<BITS; i++){
-               b = a.b[i];
-               if(b)
-                       return 64*i + bitno(b);
-       }
-       fatal("bad in bnum");
-       return 0;
-}
-
-Bits
-blsh(uint n)
-{
-       Bits c;
-
-       c = zbits;
-       c.b[n/64] = 1LL << (n%64);
-       return c;
-}
-
-int
-btest(Bits *a, uint n)
-{
-       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(uint64 b)
-{
-       int i;
-
-       for(i=0; i<64; i++)
-               if(b & (1LL<<i))
-                       return i;
-       fatal("bad in bitno");
-       return 0;
-}
-
-int
-Qconv(Fmt *fp)
-{
-       Bits bits;
-       int i, first;
-
-       first = 1;
-       bits = va_arg(fp->args, Bits);
-       while(bany(&bits)) {
-               i = bnum(bits);
-               if(first)
-                       first = 0;
-               else
-                       fmtprint(fp, " ");
-               if(var[i].node == N || var[i].node->sym == S)
-                       fmtprint(fp, "$%d", i);
-               else {
-                       fmtprint(fp, "%s(%d)", var[i].node->sym->name, i);
-                       if(var[i].offset != 0)
-                               fmtprint(fp, "%+lld", (vlong)var[i].offset);
-               }
-               biclr(&bits, i);
-       }
-       return 0;
-}
diff --git a/src/cmd/gc/builtin.c b/src/cmd/gc/builtin.c
deleted file mode 100644 (file)
index 1178f62..0000000
+++ /dev/null
@@ -1,165 +0,0 @@
-// AUTO-GENERATED by mkbuiltin; DO NOT EDIT
-#include <u.h>
-#include <libc.h>
-#include "go.h"
-char *runtimeimport =
-       "package runtime\n"
-       "import runtime \"runtime\"\n"
-       "func @\"\".newobject (@\"\".typ·2 *byte) (? *any)\n"
-       "func @\"\".panicindex ()\n"
-       "func @\"\".panicslice ()\n"
-       "func @\"\".panicdivide ()\n"
-       "func @\"\".throwreturn ()\n"
-       "func @\"\".throwinit ()\n"
-       "func @\"\".panicwrap (? string, ? string, ? string)\n"
-       "func @\"\".gopanic (? interface {})\n"
-       "func @\"\".gorecover (? *int32) (? interface {})\n"
-       "func @\"\".printbool (? bool)\n"
-       "func @\"\".printfloat (? float64)\n"
-       "func @\"\".printint (? int64)\n"
-       "func @\"\".printhex (? uint64)\n"
-       "func @\"\".printuint (? uint64)\n"
-       "func @\"\".printcomplex (? complex128)\n"
-       "func @\"\".printstring (? string)\n"
-       "func @\"\".printpointer (? any)\n"
-       "func @\"\".printiface (? any)\n"
-       "func @\"\".printeface (? any)\n"
-       "func @\"\".printslice (? any)\n"
-       "func @\"\".printnl ()\n"
-       "func @\"\".printsp ()\n"
-       "func @\"\".printlock ()\n"
-       "func @\"\".printunlock ()\n"
-       "func @\"\".concatstring2 (? *[32]byte, ? string, ? string) (? string)\n"
-       "func @\"\".concatstring3 (? *[32]byte, ? string, ? string, ? string) (? string)\n"
-       "func @\"\".concatstring4 (? *[32]byte, ? string, ? string, ? string, ? string) (? string)\n"
-       "func @\"\".concatstring5 (? *[32]byte, ? string, ? string, ? string, ? string, ? string) (? string)\n"
-       "func @\"\".concatstrings (? *[32]byte, ? []string) (? string)\n"
-       "func @\"\".cmpstring (? string, ? string) (? int)\n"
-       "func @\"\".eqstring (? string, ? string) (? bool)\n"
-       "func @\"\".intstring (? *[4]byte, ? int64) (? string)\n"
-       "func @\"\".slicebytetostring (? *[32]byte, ? []byte) (? string)\n"
-       "func @\"\".slicebytetostringtmp (? []byte) (? string)\n"
-       "func @\"\".slicerunetostring (? *[32]byte, ? []rune) (? string)\n"
-       "func @\"\".stringtoslicebyte (? *[32]byte, ? string) (? []byte)\n"
-       "func @\"\".stringtoslicebytetmp (? string) (? []byte)\n"
-       "func @\"\".stringtoslicerune (? *[32]rune, ? string) (? []rune)\n"
-       "func @\"\".stringiter (? string, ? int) (? int)\n"
-       "func @\"\".stringiter2 (? string, ? int) (@\"\".retk·1 int, @\"\".retv·2 rune)\n"
-       "func @\"\".slicecopy (@\"\".to·2 any, @\"\".fr·3 any, @\"\".wid·4 uintptr) (? int)\n"
-       "func @\"\".slicestringcopy (@\"\".to·2 any, @\"\".fr·3 any) (? int)\n"
-       "func @\"\".typ2Itab (@\"\".typ·2 *byte, @\"\".typ2·3 *byte, @\"\".cache·4 **byte) (@\"\".ret·1 *byte)\n"
-       "func @\"\".convI2E (@\"\".elem·2 any) (@\"\".ret·1 any)\n"
-       "func @\"\".convI2I (@\"\".typ·2 *byte, @\"\".elem·3 any) (@\"\".ret·1 any)\n"
-       "func @\"\".convT2E (@\"\".typ·2 *byte, @\"\".elem·3 *any) (@\"\".ret·1 any)\n"
-       "func @\"\".convT2I (@\"\".typ·2 *byte, @\"\".typ2·3 *byte, @\"\".cache·4 **byte, @\"\".elem·5 *any) (@\"\".ret·1 any)\n"
-       "func @\"\".assertE2E (@\"\".typ·1 *byte, @\"\".iface·2 any, @\"\".ret·3 *any)\n"
-       "func @\"\".assertE2E2 (@\"\".typ·2 *byte, @\"\".iface·3 any, @\"\".ret·4 *any) (? bool)\n"
-       "func @\"\".assertE2I (@\"\".typ·1 *byte, @\"\".iface·2 any, @\"\".ret·3 *any)\n"
-       "func @\"\".assertE2I2 (@\"\".typ·2 *byte, @\"\".iface·3 any, @\"\".ret·4 *any) (? bool)\n"
-       "func @\"\".assertE2T (@\"\".typ·1 *byte, @\"\".iface·2 any, @\"\".ret·3 *any)\n"
-       "func @\"\".assertE2T2 (@\"\".typ·2 *byte, @\"\".iface·3 any, @\"\".ret·4 *any) (? bool)\n"
-       "func @\"\".assertI2E (@\"\".typ·1 *byte, @\"\".iface·2 any, @\"\".ret·3 *any)\n"
-       "func @\"\".assertI2E2 (@\"\".typ·2 *byte, @\"\".iface·3 any, @\"\".ret·4 *any) (? bool)\n"
-       "func @\"\".assertI2I (@\"\".typ·1 *byte, @\"\".iface·2 any, @\"\".ret·3 *any)\n"
-       "func @\"\".assertI2I2 (@\"\".typ·2 *byte, @\"\".iface·3 any, @\"\".ret·4 *any) (? bool)\n"
-       "func @\"\".assertI2T (@\"\".typ·1 *byte, @\"\".iface·2 any, @\"\".ret·3 *any)\n"
-       "func @\"\".assertI2T2 (@\"\".typ·2 *byte, @\"\".iface·3 any, @\"\".ret·4 *any) (? bool)\n"
-       "func @\"\".ifaceeq (@\"\".i1·2 any, @\"\".i2·3 any) (@\"\".ret·1 bool)\n"
-       "func @\"\".efaceeq (@\"\".i1·2 any, @\"\".i2·3 any) (@\"\".ret·1 bool)\n"
-       "func @\"\".ifacethash (@\"\".i1·2 any) (@\"\".ret·1 uint32)\n"
-       "func @\"\".efacethash (@\"\".i1·2 any) (@\"\".ret·1 uint32)\n"
-       "func @\"\".makemap (@\"\".mapType·2 *byte, @\"\".hint·3 int64, @\"\".mapbuf·4 *any, @\"\".bucketbuf·5 *any) (@\"\".hmap·1 map[any]any)\n"
-       "func @\"\".mapaccess1 (@\"\".mapType·2 *byte, @\"\".hmap·3 map[any]any, @\"\".key·4 *any) (@\"\".val·1 *any)\n"
-       "func @\"\".mapaccess1_fast32 (@\"\".mapType·2 *byte, @\"\".hmap·3 map[any]any, @\"\".key·4 any) (@\"\".val·1 *any)\n"
-       "func @\"\".mapaccess1_fast64 (@\"\".mapType·2 *byte, @\"\".hmap·3 map[any]any, @\"\".key·4 any) (@\"\".val·1 *any)\n"
-       "func @\"\".mapaccess1_faststr (@\"\".mapType·2 *byte, @\"\".hmap·3 map[any]any, @\"\".key·4 any) (@\"\".val·1 *any)\n"
-       "func @\"\".mapaccess2 (@\"\".mapType·3 *byte, @\"\".hmap·4 map[any]any, @\"\".key·5 *any) (@\"\".val·1 *any, @\"\".pres·2 bool)\n"
-       "func @\"\".mapaccess2_fast32 (@\"\".mapType·3 *byte, @\"\".hmap·4 map[any]any, @\"\".key·5 any) (@\"\".val·1 *any, @\"\".pres·2 bool)\n"
-       "func @\"\".mapaccess2_fast64 (@\"\".mapType·3 *byte, @\"\".hmap·4 map[any]any, @\"\".key·5 any) (@\"\".val·1 *any, @\"\".pres·2 bool)\n"
-       "func @\"\".mapaccess2_faststr (@\"\".mapType·3 *byte, @\"\".hmap·4 map[any]any, @\"\".key·5 any) (@\"\".val·1 *any, @\"\".pres·2 bool)\n"
-       "func @\"\".mapassign1 (@\"\".mapType·1 *byte, @\"\".hmap·2 map[any]any, @\"\".key·3 *any, @\"\".val·4 *any)\n"
-       "func @\"\".mapiterinit (@\"\".mapType·1 *byte, @\"\".hmap·2 map[any]any, @\"\".hiter·3 *any)\n"
-       "func @\"\".mapdelete (@\"\".mapType·1 *byte, @\"\".hmap·2 map[any]any, @\"\".key·3 *any)\n"
-       "func @\"\".mapiternext (@\"\".hiter·1 *any)\n"
-       "func @\"\".makechan (@\"\".chanType·2 *byte, @\"\".hint·3 int64) (@\"\".hchan·1 chan any)\n"
-       "func @\"\".chanrecv1 (@\"\".chanType·1 *byte, @\"\".hchan·2 <-chan any, @\"\".elem·3 *any)\n"
-       "func @\"\".chanrecv2 (@\"\".chanType·2 *byte, @\"\".hchan·3 <-chan any, @\"\".elem·4 *any) (? bool)\n"
-       "func @\"\".chansend1 (@\"\".chanType·1 *byte, @\"\".hchan·2 chan<- any, @\"\".elem·3 *any)\n"
-       "func @\"\".closechan (@\"\".hchan·1 any)\n"
-       "func @\"\".writebarrierptr (@\"\".dst·1 *any, @\"\".src·2 any)\n"
-       "func @\"\".writebarrierstring (@\"\".dst·1 *any, @\"\".src·2 any)\n"
-       "func @\"\".writebarrierslice (@\"\".dst·1 *any, @\"\".src·2 any)\n"
-       "func @\"\".writebarrieriface (@\"\".dst·1 *any, @\"\".src·2 any)\n"
-       "func @\"\".writebarrierfat01 (@\"\".dst·1 *any, _ *byte, @\"\".src·3 any)\n"
-       "func @\"\".writebarrierfat10 (@\"\".dst·1 *any, _ *byte, @\"\".src·3 any)\n"
-       "func @\"\".writebarrierfat11 (@\"\".dst·1 *any, _ *byte, @\"\".src·3 any)\n"
-       "func @\"\".writebarrierfat001 (@\"\".dst·1 *any, _ *byte, @\"\".src·3 any)\n"
-       "func @\"\".writebarrierfat010 (@\"\".dst·1 *any, _ *byte, @\"\".src·3 any)\n"
-       "func @\"\".writebarrierfat011 (@\"\".dst·1 *any, _ *byte, @\"\".src·3 any)\n"
-       "func @\"\".writebarrierfat100 (@\"\".dst·1 *any, _ *byte, @\"\".src·3 any)\n"
-       "func @\"\".writebarrierfat101 (@\"\".dst·1 *any, _ *byte, @\"\".src·3 any)\n"
-       "func @\"\".writebarrierfat110 (@\"\".dst·1 *any, _ *byte, @\"\".src·3 any)\n"
-       "func @\"\".writebarrierfat111 (@\"\".dst·1 *any, _ *byte, @\"\".src·3 any)\n"
-       "func @\"\".writebarrierfat0001 (@\"\".dst·1 *any, _ *byte, @\"\".src·3 any)\n"
-       "func @\"\".writebarrierfat0010 (@\"\".dst·1 *any, _ *byte, @\"\".src·3 any)\n"
-       "func @\"\".writebarrierfat0011 (@\"\".dst·1 *any, _ *byte, @\"\".src·3 any)\n"
-       "func @\"\".writebarrierfat0100 (@\"\".dst·1 *any, _ *byte, @\"\".src·3 any)\n"
-       "func @\"\".writebarrierfat0101 (@\"\".dst·1 *any, _ *byte, @\"\".src·3 any)\n"
-       "func @\"\".writebarrierfat0110 (@\"\".dst·1 *any, _ *byte, @\"\".src·3 any)\n"
-       "func @\"\".writebarrierfat0111 (@\"\".dst·1 *any, _ *byte, @\"\".src·3 any)\n"
-       "func @\"\".writebarrierfat1000 (@\"\".dst·1 *any, _ *byte, @\"\".src·3 any)\n"
-       "func @\"\".writebarrierfat1001 (@\"\".dst·1 *any, _ *byte, @\"\".src·3 any)\n"
-       "func @\"\".writebarrierfat1010 (@\"\".dst·1 *any, _ *byte, @\"\".src·3 any)\n"
-       "func @\"\".writebarrierfat1011 (@\"\".dst·1 *any, _ *byte, @\"\".src·3 any)\n"
-       "func @\"\".writebarrierfat1100 (@\"\".dst·1 *any, _ *byte, @\"\".src·3 any)\n"
-       "func @\"\".writebarrierfat1101 (@\"\".dst·1 *any, _ *byte, @\"\".src·3 any)\n"
-       "func @\"\".writebarrierfat1110 (@\"\".dst·1 *any, _ *byte, @\"\".src·3 any)\n"
-       "func @\"\".writebarrierfat1111 (@\"\".dst·1 *any, _ *byte, @\"\".src·3 any)\n"
-       "func @\"\".typedmemmove (@\"\".typ·1 *byte, @\"\".dst·2 *any, @\"\".src·3 *any)\n"
-       "func @\"\".typedslicecopy (@\"\".typ·2 *byte, @\"\".dst·3 any, @\"\".src·4 any) (? int)\n"
-       "func @\"\".selectnbsend (@\"\".chanType·2 *byte, @\"\".hchan·3 chan<- any, @\"\".elem·4 *any) (? bool)\n"
-       "func @\"\".selectnbrecv (@\"\".chanType·2 *byte, @\"\".elem·3 *any, @\"\".hchan·4 <-chan any) (? bool)\n"
-       "func @\"\".selectnbrecv2 (@\"\".chanType·2 *byte, @\"\".elem·3 *any, @\"\".received·4 *bool, @\"\".hchan·5 <-chan any) (? bool)\n"
-       "func @\"\".newselect (@\"\".sel·1 *byte, @\"\".selsize·2 int64, @\"\".size·3 int32)\n"
-       "func @\"\".selectsend (@\"\".sel·2 *byte, @\"\".hchan·3 chan<- any, @\"\".elem·4 *any) (@\"\".selected·1 bool)\n"
-       "func @\"\".selectrecv (@\"\".sel·2 *byte, @\"\".hchan·3 <-chan any, @\"\".elem·4 *any) (@\"\".selected·1 bool)\n"
-       "func @\"\".selectrecv2 (@\"\".sel·2 *byte, @\"\".hchan·3 <-chan any, @\"\".elem·4 *any, @\"\".received·5 *bool) (@\"\".selected·1 bool)\n"
-       "func @\"\".selectdefault (@\"\".sel·2 *byte) (@\"\".selected·1 bool)\n"
-       "func @\"\".selectgo (@\"\".sel·1 *byte)\n"
-       "func @\"\".block ()\n"
-       "func @\"\".makeslice (@\"\".typ·2 *byte, @\"\".nel·3 int64, @\"\".cap·4 int64) (@\"\".ary·1 []any)\n"
-       "func @\"\".growslice (@\"\".typ·2 *byte, @\"\".old·3 []any, @\"\".n·4 int64) (@\"\".ary·1 []any)\n"
-       "func @\"\".memmove (@\"\".to·1 *any, @\"\".frm·2 *any, @\"\".length·3 uintptr)\n"
-       "func @\"\".memclr (@\"\".ptr·1 *byte, @\"\".length·2 uintptr)\n"
-       "func @\"\".memequal (@\"\".x·2 *any, @\"\".y·3 *any, @\"\".size·4 uintptr) (? bool)\n"
-       "func @\"\".memequal8 (@\"\".x·2 *any, @\"\".y·3 *any) (? bool)\n"
-       "func @\"\".memequal16 (@\"\".x·2 *any, @\"\".y·3 *any) (? bool)\n"
-       "func @\"\".memequal32 (@\"\".x·2 *any, @\"\".y·3 *any) (? bool)\n"
-       "func @\"\".memequal64 (@\"\".x·2 *any, @\"\".y·3 *any) (? bool)\n"
-       "func @\"\".memequal128 (@\"\".x·2 *any, @\"\".y·3 *any) (? bool)\n"
-       "func @\"\".int64div (? int64, ? int64) (? int64)\n"
-       "func @\"\".uint64div (? uint64, ? uint64) (? uint64)\n"
-       "func @\"\".int64mod (? int64, ? int64) (? int64)\n"
-       "func @\"\".uint64mod (? uint64, ? uint64) (? uint64)\n"
-       "func @\"\".float64toint64 (? float64) (? int64)\n"
-       "func @\"\".float64touint64 (? float64) (? uint64)\n"
-       "func @\"\".int64tofloat64 (? int64) (? float64)\n"
-       "func @\"\".uint64tofloat64 (? uint64) (? float64)\n"
-       "func @\"\".complex128div (@\"\".num·2 complex128, @\"\".den·3 complex128) (@\"\".quo·1 complex128)\n"
-       "func @\"\".racefuncenter (? uintptr)\n"
-       "func @\"\".racefuncexit ()\n"
-       "func @\"\".raceread (? uintptr)\n"
-       "func @\"\".racewrite (? uintptr)\n"
-       "func @\"\".racereadrange (@\"\".addr·1 uintptr, @\"\".size·2 uintptr)\n"
-       "func @\"\".racewriterange (@\"\".addr·1 uintptr, @\"\".size·2 uintptr)\n"
-       "\n"
-       "$$\n";
-char *unsafeimport =
-       "package unsafe\n"
-       "import runtime \"runtime\"\n"
-       "type @\"\".Pointer uintptr\n"
-       "func @\"\".Offsetof (? any) (? uintptr)\n"
-       "func @\"\".Sizeof (? any) (? uintptr)\n"
-       "func @\"\".Alignof (? any) (? uintptr)\n"
-       "\n"
-       "$$\n";
diff --git a/src/cmd/gc/bv.c b/src/cmd/gc/bv.c
deleted file mode 100644 (file)
index 2428006..0000000
+++ /dev/null
@@ -1,213 +0,0 @@
-// Copyright 2013 The Go Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style
-// license that can be found in the LICENSE file.
-
-#include <u.h>
-#include <libc.h>
-#include "go.h"
-
-enum {
-       WORDSIZE = 4,
-       WORDBITS = 32,
-       WORDMASK = WORDBITS - 1,
-       WORDSHIFT = 5,
-};
-
-static uintptr
-bvsize(uintptr n)
-{
-       return ((n + WORDBITS - 1) / WORDBITS) * WORDSIZE;
-}
-
-int32
-bvbits(Bvec *bv)
-{
-       return bv->n;
-}
-
-int32
-bvwords(Bvec *bv)
-{
-       return (bv->n + WORDBITS - 1) / WORDBITS;
-}
-
-Bvec*
-bvalloc(int32 n)
-{
-       Bvec *bv;
-       uintptr nbytes;
-
-       if(n < 0)
-               fatal("bvalloc: initial size is negative\n");
-       nbytes = sizeof(Bvec) + bvsize(n);
-       bv = malloc(nbytes);
-       if(bv == nil)
-               fatal("bvalloc: malloc failed\n");
-       memset(bv, 0, nbytes);
-       bv->n = n;
-       return bv;
-}
-
-/* difference */
-void
-bvandnot(Bvec *dst, Bvec *src1, Bvec *src2)
-{
-       int32 i, w;
-
-       if(dst->n != src1->n || dst->n != src2->n)
-               fatal("bvand: lengths %d, %d, and %d are not equal", dst->n, src1->n, src2->n);
-       for(i = 0, w = 0; i < dst->n; i += WORDBITS, w++)
-               dst->b[w] = src1->b[w] & ~src2->b[w];
-}
-
-int
-bvcmp(Bvec *bv1, Bvec *bv2)
-{
-       uintptr nbytes;
-
-       if(bv1->n != bv2->n)
-               fatal("bvequal: lengths %d and %d are not equal", bv1->n, bv2->n);
-       nbytes = bvsize(bv1->n);
-       return memcmp(bv1->b, bv2->b, nbytes);
-}
-
-void
-bvcopy(Bvec *dst, Bvec *src)
-{
-       memmove(dst->b, src->b, bvsize(dst->n));
-}
-
-Bvec*
-bvconcat(Bvec *src1, Bvec *src2)
-{
-       Bvec *dst;
-       int32 i;
-
-       dst = bvalloc(src1->n + src2->n);
-       for(i = 0; i < src1->n; i++)
-               if(bvget(src1, i))
-                       bvset(dst, i);
-       for(i = 0; i < src2->n; i++)
-               if(bvget(src2, i))
-                       bvset(dst, i + src1->n);
-       return dst;
-}
-
-int
-bvget(Bvec *bv, int32 i)
-{
-       if(i < 0 || i >= bv->n)
-               fatal("bvget: index %d is out of bounds with length %d\n", i, bv->n);
-       return (bv->b[i>>WORDSHIFT] >> (i&WORDMASK)) & 1;
-}
-
-// bvnext returns the smallest index >= i for which bvget(bv, i) == 1.
-// If there is no such index, bvnext returns -1.
-int
-bvnext(Bvec *bv, int32 i)
-{
-       uint32 w;
-
-       if(i >= bv->n)
-               return -1;
-
-       // Jump i ahead to next word with bits.
-       if((bv->b[i>>WORDSHIFT]>>(i&WORDMASK)) == 0) {
-               i &= ~WORDMASK;
-               i += WORDBITS;
-               while(i < bv->n && bv->b[i>>WORDSHIFT] == 0)
-                       i += WORDBITS;
-       }
-       if(i >= bv->n)
-               return -1;
-
-       // Find 1 bit.
-       w = bv->b[i>>WORDSHIFT]>>(i&WORDMASK);
-       while((w&1) == 0) {
-               w>>=1;
-               i++;
-       }
-       return i;
-}
-
-int
-bvisempty(Bvec *bv)
-{
-       int32 i;
-
-       for(i = 0; i < bv->n; i += WORDBITS)
-               if(bv->b[i>>WORDSHIFT] != 0)
-                       return 0;
-       return 1;
-}
-
-void
-bvnot(Bvec *bv)
-{
-       int32 i, w;
-
-       for(i = 0, w = 0; i < bv->n; i += WORDBITS, w++)
-               bv->b[w] = ~bv->b[w];
-}
-
-/* union */
-void
-bvor(Bvec *dst, Bvec *src1, Bvec *src2)
-{
-       int32 i, w;
-
-       if(dst->n != src1->n || dst->n != src2->n)
-               fatal("bvor: lengths %d, %d, and %d are not equal", dst->n, src1->n, src2->n);
-       for(i = 0, w = 0; i < dst->n; i += WORDBITS, w++)
-               dst->b[w] = src1->b[w] | src2->b[w];
-}
-
-/* intersection */
-void
-bvand(Bvec *dst, Bvec *src1, Bvec *src2)
-{
-       int32 i, w;
-
-       if(dst->n != src1->n || dst->n != src2->n)
-               fatal("bvor: lengths %d, %d, and %d are not equal", dst->n, src1->n, src2->n);
-       for(i = 0, w = 0; i < dst->n; i += WORDBITS, w++)
-               dst->b[w] = src1->b[w] & src2->b[w];
-}
-
-void
-bvprint(Bvec *bv)
-{
-       int32 i;
-
-       print("#*");
-       for(i = 0; i < bv->n; i++)
-               print("%d", bvget(bv, i));
-}
-
-void
-bvreset(Bvec *bv, int32 i)
-{
-       uint32 mask;
-
-       if(i < 0 || i >= bv->n)
-               fatal("bvreset: index %d is out of bounds with length %d\n", i, bv->n);
-       mask = ~(1 << (i % WORDBITS));
-       bv->b[i / WORDBITS] &= mask;
-}
-
-void
-bvresetall(Bvec *bv)
-{
-       memset(bv->b, 0x00, bvsize(bv->n));
-}
-
-void
-bvset(Bvec *bv, int32 i)
-{
-       uint32 mask;
-
-       if(i < 0 || i >= bv->n)
-               fatal("bvset: index %d is out of bounds with length %d\n", i, bv->n);
-       mask = 1U << (i % WORDBITS);
-       bv->b[i / WORDBITS] |= mask;
-}
diff --git a/src/cmd/gc/closure.c b/src/cmd/gc/closure.c
deleted file mode 100644 (file)
index 35b6d4b..0000000
+++ /dev/null
@@ -1,659 +0,0 @@
-// Copyright 2009 The Go Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style
-// license that can be found in the LICENSE file.
-
-/*
- * function literals aka closures
- */
-
-#include <u.h>
-#include <libc.h>
-#include "go.h"
-
-void
-closurehdr(Node *ntype)
-{
-       Node *n, *name, *a;
-       NodeList *l;
-
-       n = nod(OCLOSURE, N, N);
-       n->ntype = ntype;
-       n->funcdepth = funcdepth;
-       n->outerfunc = curfn;
-
-       funchdr(n);
-
-       // steal ntype's argument names and
-       // leave a fresh copy in their place.
-       // references to these variables need to
-       // refer to the variables in the external
-       // function declared below; see walkclosure.
-       n->list = ntype->list;
-       n->rlist = ntype->rlist;
-       ntype->list = nil;
-       ntype->rlist = nil;
-       for(l=n->list; l; l=l->next) {
-               name = l->n->left;
-               if(name)
-                       name = newname(name->sym);
-               a = nod(ODCLFIELD, name, l->n->right);
-               a->isddd = l->n->isddd;
-               if(name)
-                       name->isddd = a->isddd;
-               ntype->list = list(ntype->list, a);
-       }
-       for(l=n->rlist; l; l=l->next) {
-               name = l->n->left;
-               if(name)
-                       name = newname(name->sym);
-               ntype->rlist = list(ntype->rlist, nod(ODCLFIELD, name, l->n->right));
-       }
-}
-
-Node*
-closurebody(NodeList *body)
-{
-       Node *func, *v;
-       NodeList *l;
-
-       if(body == nil)
-               body = list1(nod(OEMPTY, N, N));
-
-       func = curfn;
-       func->nbody = body;
-       func->endlineno = lineno;
-       funcbody(func);
-
-       // closure-specific variables are hanging off the
-       // ordinary ones in the symbol table; see oldname.
-       // unhook them.
-       // make the list of pointers for the closure call.
-       for(l=func->cvars; l; l=l->next) {
-               v = l->n;
-               v->closure->closure = v->outer;
-               v->outerexpr = oldname(v->sym);
-       }
-
-       return func;
-}
-
-static Node* makeclosure(Node *func);
-
-void
-typecheckclosure(Node *func, int top)
-{
-       Node *oldfn, *n;
-       NodeList *l;
-       int olddd;
-
-       for(l=func->cvars; l; l=l->next) {
-               n = l->n->closure;
-               if(!n->captured) {
-                       n->captured = 1;
-                       if(n->decldepth == 0)
-                               fatal("typecheckclosure: var %hN does not have decldepth assigned", n);
-                       // Ignore assignments to the variable in straightline code
-                       // preceding the first capturing by a closure.
-                       if(n->decldepth == decldepth)
-                               n->assigned = 0;
-               }
-       }
-
-       for(l=func->dcl; l; l=l->next)
-               if(l->n->op == ONAME && (l->n->class == PPARAM || l->n->class == PPARAMOUT))
-                       l->n->decldepth = 1;
-
-       oldfn = curfn;
-       typecheck(&func->ntype, Etype);
-       func->type = func->ntype->type;
-       func->top = top;
-
-       // Type check the body now, but only if we're inside a function.
-       // At top level (in a variable initialization: curfn==nil) we're not
-       // ready to type check code yet; we'll check it later, because the
-       // underlying closure function we create is added to xtop.
-       if(curfn && func->type != T) {
-               curfn = func;
-               olddd = decldepth;
-               decldepth = 1;
-               typechecklist(func->nbody, Etop);
-               decldepth = olddd;
-               curfn = oldfn;
-       }
-
-       // Create top-level function 
-       xtop = list(xtop, makeclosure(func));
-}
-
-// closurename returns name for OCLOSURE n.
-// It is not as simple as it ought to be, because we typecheck nested closures
-// starting from the innermost one. So when we check the inner closure,
-// we don't yet have name for the outer closure. This function uses recursion
-// to generate names all the way up if necessary.
-static Sym*
-closurename(Node *n)
-{
-       static int closgen;
-       char *outer, *prefix;
-       int gen;
-
-       if(n->sym != S)
-               return n->sym;
-       gen = 0;
-       outer = nil;
-       prefix = nil;
-       if(n->outerfunc == N) {
-               // Global closure.
-               outer = "glob";
-               prefix = "func";
-               gen = ++closgen;
-       } else if(n->outerfunc->op == ODCLFUNC) {
-               // The outermost closure inside of a named function.
-               outer = n->outerfunc->nname->sym->name;
-               prefix = "func";
-               // Yes, functions can be named _.
-               // Can't use function closgen in such case,
-               // because it would lead to name clashes.
-               if(!isblank(n->outerfunc->nname))
-                       gen = ++n->outerfunc->closgen;
-               else
-                       gen = ++closgen;
-       } else if(n->outerfunc->op == OCLOSURE) {
-               // Nested closure, recurse.
-               outer = closurename(n->outerfunc)->name;
-               prefix = "";
-               gen = ++n->outerfunc->closgen;
-       } else
-               fatal("closurename called for %hN", n);
-       snprint(namebuf, sizeof namebuf, "%s.%s%d", outer, prefix, gen);
-       n->sym = lookup(namebuf);
-       return n->sym;
-}
-
-static Node*
-makeclosure(Node *func)
-{
-       Node *xtype, *xfunc;
-
-       /*
-        * wrap body in external function
-        * that begins by reading closure parameters.
-        */
-       xtype = nod(OTFUNC, N, N);
-       xtype->list = func->list;
-       xtype->rlist = func->rlist;
-
-       // create the function
-       xfunc = nod(ODCLFUNC, N, N);
-       xfunc->nname = newname(closurename(func));
-       xfunc->nname->sym->flags |= SymExported; // disable export
-       xfunc->nname->ntype = xtype;
-       xfunc->nname->defn = xfunc;
-       declare(xfunc->nname, PFUNC);
-       xfunc->nname->funcdepth = func->funcdepth;
-       xfunc->funcdepth = func->funcdepth;
-       xfunc->endlineno = func->endlineno;
-
-       xfunc->nbody = func->nbody;
-       xfunc->dcl = concat(func->dcl, xfunc->dcl);
-       if(xfunc->nbody == nil)
-               fatal("empty body - won't generate any code");
-       typecheck(&xfunc, Etop);
-
-       xfunc->closure = func;
-       func->closure = xfunc;
-
-       func->nbody = nil;
-       func->list = nil;
-       func->rlist = nil;
-
-       return xfunc;
-}
-
-// capturevars is called in a separate phase after all typechecking is done.
-// It decides whether each variable captured by a closure should be captured
-// by value or by reference.
-// We use value capturing for values <= 128 bytes that are never reassigned
-// after capturing (effectively constant).
-void
-capturevars(Node *xfunc)
-{
-       Node *func, *v, *outer;
-       NodeList *l;
-       int lno;
-
-       lno = lineno;
-       lineno = xfunc->lineno;
-
-       func = xfunc->closure;
-       func->enter = nil;
-       for(l=func->cvars; l; l=l->next) {
-               v = l->n;
-               if(v->type == T) {
-                       // if v->type is nil, it means v looked like it was
-                       // going to be used in the closure but wasn't.
-                       // this happens because when parsing a, b, c := f()
-                       // the a, b, c gets parsed as references to older
-                       // a, b, c before the parser figures out this is a
-                       // declaration.
-                       v->op = OXXX;
-                       continue;
-               }
-
-               // type check the & of closed variables outside the closure,
-               // so that the outer frame also grabs them and knows they escape.
-               dowidth(v->type);
-               outer = v->outerexpr;
-               v->outerexpr = N;
-               // out parameters will be assigned to implicitly upon return.
-               if(outer->class != PPARAMOUT && !v->closure->addrtaken && !v->closure->assigned && v->type->width <= 128)
-                       v->byval = 1;
-               else {
-                       v->closure->addrtaken = 1;
-                       outer = nod(OADDR, outer, N);
-               }
-               if(debug['m'] > 1) {
-                       Sym *name;
-                       char *how;
-                       name = nil;
-                       if(v->curfn && v->curfn->nname)
-                               name = v->curfn->nname->sym;
-                       how = "ref";
-                       if(v->byval)
-                               how = "value";
-                       warnl(v->lineno, "%S capturing by %s: %S (addr=%d assign=%d width=%d)",
-                               name, how,
-                               v->sym, v->closure->addrtaken, v->closure->assigned, (int32)v->type->width);
-               }
-               typecheck(&outer, Erv);
-               func->enter = list(func->enter, outer);
-       }
-
-       lineno = lno;
-}
-
-// transformclosure is called in a separate phase after escape analysis.
-// It transform closure bodies to properly reference captured variables.
-void
-transformclosure(Node *xfunc)
-{
-       Node *func, *cv, *addr, *v, *f;
-       NodeList *l, *body;
-       Type **param, *fld;
-       vlong offset;
-       int lno, nvar;
-
-       lno = lineno;
-       lineno = xfunc->lineno;
-       func = xfunc->closure;
-
-       if(func->top&Ecall) {
-               // If the closure is directly called, we transform it to a plain function call
-               // with variables passed as args. This avoids allocation of a closure object.
-               // Here we do only a part of the transformation. Walk of OCALLFUNC(OCLOSURE)
-               // will complete the transformation later.
-               // For illustration, the following closure:
-               //      func(a int) {
-               //              println(byval)
-               //              byref++
-               //      }(42)
-               // becomes:
-               //      func(a int, byval int, &byref *int) {
-               //              println(byval)
-               //              (*&byref)++
-               //      }(42, byval, &byref)
-
-               // f is ONAME of the actual function.
-               f = xfunc->nname;
-               // Get pointer to input arguments and rewind to the end.
-               // We are going to append captured variables to input args.
-               param = &getinargx(f->type)->type;
-               for(; *param; param = &(*param)->down) {
-               }
-               for(l=func->cvars; l; l=l->next) {
-                       v = l->n;
-                       if(v->op == OXXX)
-                               continue;
-                       fld = typ(TFIELD);
-                       fld->funarg = 1;
-                       if(v->byval) {
-                               // If v is captured by value, we merely downgrade it to PPARAM.
-                               v->class = PPARAM;
-                               v->ullman = 1;
-                               fld->nname = v;
-                       } else {
-                               // If v of type T is captured by reference,
-                               // we introduce function param &v *T
-                               // and v remains PPARAMREF with &v heapaddr
-                               // (accesses will implicitly deref &v).
-                               snprint(namebuf, sizeof namebuf, "&%s", v->sym->name);
-                               addr = newname(lookup(namebuf));
-                               addr->type = ptrto(v->type);
-                               addr->class = PPARAM;
-                               v->heapaddr = addr;
-                               fld->nname = addr;
-                       }
-                       fld->type = fld->nname->type;
-                       fld->sym = fld->nname->sym;
-                       // Declare the new param and append it to input arguments.
-                       xfunc->dcl = list(xfunc->dcl, fld->nname);
-                       *param = fld;
-                       param = &fld->down;
-               }
-               // Recalculate param offsets.
-               if(f->type->width > 0)
-                       fatal("transformclosure: width is already calculated");
-               dowidth(f->type);
-               xfunc->type = f->type; // update type of ODCLFUNC
-       } else {
-               // The closure is not called, so it is going to stay as closure.
-               nvar = 0;
-               body = nil;
-               offset = widthptr;
-               for(l=func->cvars; l; l=l->next) {
-                       v = l->n;
-                       if(v->op == OXXX)
-                               continue;
-                       nvar++;
-                       // cv refers to the field inside of closure OSTRUCTLIT.
-                       cv = nod(OCLOSUREVAR, N, N);
-                       cv->type = v->type;
-                       if(!v->byval)
-                               cv->type = ptrto(v->type);
-                       offset = rnd(offset, cv->type->align);
-                       cv->xoffset = offset;
-                       offset += cv->type->width;
-
-                       if(v->byval && v->type->width <= 2*widthptr && thearch.thechar == '6') {
-                               //  If it is a small variable captured by value, downgrade it to PAUTO.
-                               // This optimization is currently enabled only for amd64, see:
-                               // https://github.com/golang/go/issues/9865
-                               v->class = PAUTO;
-                               v->ullman = 1;
-                               xfunc->dcl = list(xfunc->dcl, v);
-                               body = list(body, nod(OAS, v, cv));
-                       } else {
-                               // Declare variable holding addresses taken from closure
-                               // and initialize in entry prologue.
-                               snprint(namebuf, sizeof namebuf, "&%s", v->sym->name);
-                               addr = newname(lookup(namebuf));
-                               addr->ntype = nod(OIND, typenod(v->type), N);
-                               addr->class = PAUTO;
-                               addr->used = 1;
-                               addr->curfn = xfunc;
-                               xfunc->dcl = list(xfunc->dcl, addr);
-                               v->heapaddr = addr;
-                               if(v->byval)
-                                       cv = nod(OADDR, cv, N);
-                               body = list(body, nod(OAS, addr, cv));
-                       }
-               }
-               typechecklist(body, Etop);
-               walkstmtlist(body);
-               xfunc->enter = body;
-               xfunc->needctxt = nvar > 0;
-       }
-
-       lineno = lno;
-}
-
-Node*
-walkclosure(Node *func, NodeList **init)
-{
-       Node *clos, *typ, *typ1, *v;
-       NodeList *l;
-
-       // If no closure vars, don't bother wrapping.
-       if(func->cvars == nil)
-               return func->closure->nname;
-
-       // Create closure in the form of a composite literal.
-       // supposing the closure captures an int i and a string s
-       // and has one float64 argument and no results,
-       // the generated code looks like:
-       //
-       //      clos = &struct{.F uintptr; i *int; s *string}{func.1, &i, &s}
-       //
-       // The use of the struct provides type information to the garbage
-       // collector so that it can walk the closure. We could use (in this case)
-       // [3]unsafe.Pointer instead, but that would leave the gc in the dark.
-       // The information appears in the binary in the form of type descriptors;
-       // the struct is unnamed so that closures in multiple packages with the
-       // same struct type can share the descriptor.
-
-       typ = nod(OTSTRUCT, N, N);
-       typ->list = list1(nod(ODCLFIELD, newname(lookup(".F")), typenod(types[TUINTPTR])));
-       for(l=func->cvars; l; l=l->next) {
-               v = l->n;
-               if(v->op == OXXX)
-                       continue;
-               typ1 = typenod(v->type);
-               if(!v->byval)
-                       typ1 = nod(OIND, typ1, N);
-               typ->list = list(typ->list, nod(ODCLFIELD, newname(v->sym), typ1));
-       }
-
-       clos = nod(OCOMPLIT, N, nod(OIND, typ, N));
-       clos->esc = func->esc;
-       clos->right->implicit = 1;
-       clos->list = concat(list1(nod(OCFUNC, func->closure->nname, N)), func->enter);
-
-       // Force type conversion from *struct to the func type.
-       clos = nod(OCONVNOP, clos, N);
-       clos->type = func->type;
-
-       typecheck(&clos, Erv);
-       // typecheck will insert a PTRLIT node under CONVNOP,
-       // tag it with escape analysis result.
-       clos->left->esc = func->esc;
-       // non-escaping temp to use, if any.
-       // orderexpr did not compute the type; fill it in now.
-       if(func->alloc != N) {
-               func->alloc->type = clos->left->left->type;
-               func->alloc->orig->type = func->alloc->type;
-               clos->left->right = func->alloc;
-               func->alloc = N;
-       }
-       walkexpr(&clos, init);
-
-       return clos;
-}
-
-static Node *makepartialcall(Node*, Type*, Node*);
-
-void
-typecheckpartialcall(Node *fn, Node *sym)
-{
-       switch(fn->op) {
-       case ODOTINTER:
-       case ODOTMETH:
-               break;
-       default:
-               fatal("invalid typecheckpartialcall");
-       }
-
-       // Create top-level function.
-       fn->nname = makepartialcall(fn, fn->type, sym);
-       fn->right = sym;
-       fn->op = OCALLPART;
-       fn->type = fn->nname->type;
-}
-
-static Node*
-makepartialcall(Node *fn, Type *t0, Node *meth)
-{
-       Node *ptr, *n, *fld, *call, *xtype, *xfunc, *cv, *savecurfn;
-       Type *rcvrtype, *basetype, *t;
-       NodeList *body, *l, *callargs, *retargs;
-       char *p;
-       Sym *sym;
-       Pkg *spkg;
-       static Pkg* gopkg;
-       int i, ddd;
-
-       rcvrtype = fn->left->type;
-       if(exportname(meth->sym->name))
-               p = smprint("(%-hT).%s-fm", rcvrtype, meth->sym->name);
-       else
-               p = smprint("(%-hT).(%-S)-fm", rcvrtype, meth->sym);
-       basetype = rcvrtype;
-       if(isptr[rcvrtype->etype])
-               basetype = basetype->type;
-       if(basetype->etype != TINTER && basetype->sym == S)
-               fatal("missing base type for %T", rcvrtype);
-
-       spkg = nil;
-       if(basetype->sym != S)
-               spkg = basetype->sym->pkg;
-       if(spkg == nil) {
-               if(gopkg == nil)
-                       gopkg = mkpkg(newstrlit("go"));
-               spkg = gopkg;
-       }
-       sym = pkglookup(p, spkg);
-       free(p);
-       if(sym->flags & SymUniq)
-               return sym->def;
-       sym->flags |= SymUniq;
-       
-       savecurfn = curfn;
-       curfn = N;
-
-       xtype = nod(OTFUNC, N, N);
-       i = 0;
-       l = nil;
-       callargs = nil;
-       ddd = 0;
-       xfunc = nod(ODCLFUNC, N, N);
-       curfn = xfunc;
-       for(t = getinargx(t0)->type; t; t = t->down) {
-               snprint(namebuf, sizeof namebuf, "a%d", i++);
-               n = newname(lookup(namebuf));
-               n->class = PPARAM;
-               xfunc->dcl = list(xfunc->dcl, n);
-               callargs = list(callargs, n);
-               fld = nod(ODCLFIELD, n, typenod(t->type));
-               if(t->isddd) {
-                       fld->isddd = 1;
-                       ddd = 1;
-               }
-               l = list(l, fld);
-       }
-       xtype->list = l;
-       i = 0;
-       l = nil;
-       retargs = nil;
-       for(t = getoutargx(t0)->type; t; t = t->down) {
-               snprint(namebuf, sizeof namebuf, "r%d", i++);
-               n = newname(lookup(namebuf));
-               n->class = PPARAMOUT;
-               xfunc->dcl = list(xfunc->dcl, n);
-               retargs = list(retargs, n);
-               l = list(l, nod(ODCLFIELD, n, typenod(t->type)));
-       }
-       xtype->rlist = l;
-
-       xfunc->dupok = 1;
-       xfunc->nname = newname(sym);
-       xfunc->nname->sym->flags |= SymExported; // disable export
-       xfunc->nname->ntype = xtype;
-       xfunc->nname->defn = xfunc;
-       declare(xfunc->nname, PFUNC);
-
-       // Declare and initialize variable holding receiver.
-       body = nil;
-       xfunc->needctxt = 1;
-       cv = nod(OCLOSUREVAR, N, N);
-       cv->xoffset = widthptr;
-       cv->type = rcvrtype;
-       if(cv->type->align > widthptr)
-               cv->xoffset = cv->type->align;
-       ptr = nod(ONAME, N, N);
-       ptr->sym = lookup("rcvr");
-       ptr->class = PAUTO;
-       ptr->addable = 1;
-       ptr->ullman = 1;
-       ptr->used = 1;
-       ptr->curfn = xfunc;
-       xfunc->dcl = list(xfunc->dcl, ptr);
-       if(isptr[rcvrtype->etype] || isinter(rcvrtype)) {
-               ptr->ntype = typenod(rcvrtype);
-               body = list(body, nod(OAS, ptr, cv));
-       } else {
-               ptr->ntype = typenod(ptrto(rcvrtype));
-               body = list(body, nod(OAS, ptr, nod(OADDR, cv, N)));
-       }
-
-       call = nod(OCALL, nod(OXDOT, ptr, meth), N);
-       call->list = callargs;
-       call->isddd = ddd;
-       if(t0->outtuple == 0) {
-               body = list(body, call);
-       } else {
-               n = nod(OAS2, N, N);
-               n->list = retargs;
-               n->rlist = list1(call);
-               body = list(body, n);
-               n = nod(ORETURN, N, N);
-               body = list(body, n);
-       }
-
-       xfunc->nbody = body;
-
-       typecheck(&xfunc, Etop);
-       sym->def = xfunc;
-       xtop = list(xtop, xfunc);
-       curfn = savecurfn;
-
-       return xfunc;
-}
-
-Node*
-walkpartialcall(Node *n, NodeList **init)
-{
-       Node *clos, *typ;
-
-       // Create closure in the form of a composite literal.
-       // For x.M with receiver (x) type T, the generated code looks like:
-       //
-       //      clos = &struct{F uintptr; R T}{M.T·f, x}
-       //
-       // Like walkclosure above.
-
-       if(isinter(n->left->type)) {
-               // Trigger panic for method on nil interface now.
-               // Otherwise it happens in the wrapper and is confusing.
-               n->left = cheapexpr(n->left, init);
-               checknil(n->left, init);
-       }
-
-       typ = nod(OTSTRUCT, N, N);
-       typ->list = list1(nod(ODCLFIELD, newname(lookup("F")), typenod(types[TUINTPTR])));
-       typ->list = list(typ->list, nod(ODCLFIELD, newname(lookup("R")), typenod(n->left->type)));
-
-       clos = nod(OCOMPLIT, N, nod(OIND, typ, N));
-       clos->esc = n->esc;
-       clos->right->implicit = 1;
-       clos->list = list1(nod(OCFUNC, n->nname->nname, N));
-       clos->list = list(clos->list, n->left);
-
-       // Force type conversion from *struct to the func type.
-       clos = nod(OCONVNOP, clos, N);
-       clos->type = n->type;
-
-       typecheck(&clos, Erv);
-       // typecheck will insert a PTRLIT node under CONVNOP,
-       // tag it with escape analysis result.
-       clos->left->esc = n->esc;
-       // non-escaping temp to use, if any.
-       // orderexpr did not compute the type; fill it in now.
-       if(n->alloc != N) {
-               n->alloc->type = clos->left->left->type;
-               n->alloc->orig->type = n->alloc->type;
-               clos->left->right = n->alloc;
-               n->alloc = N;
-       }
-       walkexpr(&clos, init);
-
-       return clos;
-}
diff --git a/src/cmd/gc/const.c b/src/cmd/gc/const.c
deleted file mode 100644 (file)
index 50accb9..0000000
+++ /dev/null
@@ -1,1678 +0,0 @@
-// Copyright 2009 The Go Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style
-// license that can be found in the LICENSE file.
-
-#include       <u.h>
-#include       <libc.h>
-#include       "go.h"
-#define        TUP(x,y)        (((x)<<16)|(y))
-/*c2go int TUP(int, int); */
-
-static Val     tocplx(Val);
-static Val     toflt(Val);
-static Val     tostr(Val);
-static Val     copyval(Val);
-static void    cmplxmpy(Mpcplx*, Mpcplx*);
-static void    cmplxdiv(Mpcplx*, Mpcplx*);
-
-/*
- * truncate float literal fv to 32-bit or 64-bit precision
- * according to type; return truncated value.
- */
-Mpflt*
-truncfltlit(Mpflt *oldv, Type *t)
-{
-       double d;
-       Mpflt *fv;
-       Val v;
-
-       if(t == T)
-               return oldv;
-
-       memset(&v, 0, sizeof v);
-       v.ctype = CTFLT;
-       v.u.fval = oldv;
-       overflow(v, t);
-
-       fv = mal(sizeof *fv);
-       *fv = *oldv;
-
-       // convert large precision literal floating
-       // into limited precision (float64 or float32)
-       switch(t->etype) {
-       case TFLOAT64:
-               d = mpgetflt(fv);
-               mpmovecflt(fv, d);
-               break;
-
-       case TFLOAT32:
-               d = mpgetflt32(fv);
-               mpmovecflt(fv, d);
-
-               break;
-       }
-       return fv;
-}
-
-/*
- * convert n, if literal, to type t.
- * implicit conversion.
- */
-void
-convlit(Node **np, Type *t)
-{
-       convlit1(np, t, 0);
-}
-
-/*
- * convert n, if literal, to type t.
- * return a new node if necessary
- * (if n is a named constant, can't edit n->type directly).
- */
-void
-convlit1(Node **np, Type *t, int explicit)
-{
-       int ct, et;
-       Node *n, *nn;
-
-       n = *np;
-       if(n == N || t == T || n->type == T || isideal(t) || n->type == t)
-               return;
-       if(!explicit && !isideal(n->type))
-               return;
-
-       if(n->op == OLITERAL) {
-               nn = nod(OXXX, N, N);
-               *nn = *n;
-               n = nn;
-               *np = n;
-       }
-
-       switch(n->op) {
-       default:
-               if(n->type == idealbool) {
-                       if(t->etype == TBOOL)
-                               n->type = t;
-                       else
-                               n->type = types[TBOOL];
-               }
-               if(n->type->etype == TIDEAL) {
-                       convlit(&n->left, t);
-                       convlit(&n->right, t);
-                       n->type = t;
-               }
-               return;
-       case OLITERAL:
-               // target is invalid type for a constant?  leave alone.
-               if(!okforconst[t->etype] && n->type->etype != TNIL) {
-                       defaultlit(&n, T);
-                       *np = n;
-                       return;
-               }
-               break;
-       case OLSH:
-       case ORSH:
-               convlit1(&n->left, t, explicit && isideal(n->left->type));
-               t = n->left->type;
-               if(t != T && t->etype == TIDEAL && n->val.ctype != CTINT)
-                       n->val = toint(n->val);
-               if(t != T && !isint[t->etype]) {
-                       yyerror("invalid operation: %N (shift of type %T)", n, t);
-                       t = T;
-               }
-               n->type = t;
-               return;
-       case OCOMPLEX:
-               if(n->type->etype == TIDEAL) {
-                       switch(t->etype) {
-                       default:
-                               // If trying to convert to non-complex type,
-                               // leave as complex128 and let typechecker complain.
-                               t = types[TCOMPLEX128];
-                               //fallthrough
-                       case TCOMPLEX128:
-                               n->type = t;
-                               convlit(&n->left, types[TFLOAT64]);
-                               convlit(&n->right, types[TFLOAT64]);
-                               break;
-                       case TCOMPLEX64:
-                               n->type = t;
-                               convlit(&n->left, types[TFLOAT32]);
-                               convlit(&n->right, types[TFLOAT32]);
-                               break;
-                       }
-               }
-               return;
-       }
-
-       // avoided repeated calculations, errors
-       if(eqtype(n->type, t))
-               return;
-
-       ct = consttype(n);
-       if(ct < 0)
-               goto bad;
-
-       et = t->etype;
-       if(et == TINTER) {
-               if(ct == CTNIL && n->type == types[TNIL]) {
-                       n->type = t;
-                       return;
-               }
-               defaultlit(np, T);
-               return;
-       }
-
-       switch(ct) {
-       default:
-               goto bad;
-
-       case CTNIL:
-               switch(et) {
-               default:
-                       n->type = T;
-                       goto bad;
-
-               case TSTRING:
-                       // let normal conversion code handle it
-                       return;
-
-               case TARRAY:
-                       if(!isslice(t))
-                               goto bad;
-                       break;
-
-               case TPTR32:
-               case TPTR64:
-               case TINTER:
-               case TMAP:
-               case TCHAN:
-               case TFUNC:
-               case TUNSAFEPTR:
-                       break;
-
-               case TUINTPTR:
-                       // A nil literal may be converted to uintptr
-                       // if it is an unsafe.Pointer
-                       if(n->type->etype == TUNSAFEPTR) {
-                               n->val.u.xval = mal(sizeof(*n->val.u.xval));
-                               mpmovecfix(n->val.u.xval, 0);
-                               n->val.ctype = CTINT;
-                       } else
-                               goto bad;
-               }
-               break;
-
-       case CTSTR:
-       case CTBOOL:
-               if(et != n->type->etype)
-                       goto bad;
-               break;
-
-       case CTINT:
-       case CTRUNE:
-       case CTFLT:
-       case CTCPLX:
-               ct = n->val.ctype;
-               if(isint[et]) {
-                       switch(ct) {
-                       default:
-                               goto bad;
-                       case CTCPLX:
-                       case CTFLT:
-                       case CTRUNE:
-                               n->val = toint(n->val);
-                               // flowthrough
-                       case CTINT:
-                               overflow(n->val, t);
-                               break;
-                       }
-               } else
-               if(isfloat[et]) {
-                       switch(ct) {
-                       default:
-                               goto bad;
-                       case CTCPLX:
-                       case CTINT:
-                       case CTRUNE:
-                               n->val = toflt(n->val);
-                               // flowthrough
-                       case CTFLT:
-                               n->val.u.fval = truncfltlit(n->val.u.fval, t);
-                               break;
-                       }
-               } else
-               if(iscomplex[et]) {
-                       switch(ct) {
-                       default:
-                               goto bad;
-                       case CTFLT:
-                       case CTINT:
-                       case CTRUNE:
-                               n->val = tocplx(n->val);
-                               break;
-                       case CTCPLX:
-                               overflow(n->val, t);
-                               break;
-                       }
-               } else
-               if(et == TSTRING && (ct == CTINT || ct == CTRUNE) && explicit)
-                       n->val = tostr(n->val);
-               else
-                       goto bad;
-               break;
-       }
-       n->type = t;
-       return;
-
-bad:
-       if(!n->diag) {
-               if(!t->broke)
-                       yyerror("cannot convert %N to type %T", n, t);
-               n->diag = 1;
-       }
-       if(isideal(n->type)) {
-               defaultlit(&n, T);
-               *np = n;
-       }
-       return;
-}
-
-static Val
-copyval(Val v)
-{
-       Mpint *i;
-       Mpflt *f;
-       Mpcplx *c;
-
-       switch(v.ctype) {
-       case CTINT:
-       case CTRUNE:
-               i = mal(sizeof(*i));
-               mpmovefixfix(i, v.u.xval);
-               v.u.xval = i;
-               break;
-       case CTFLT:
-               f = mal(sizeof(*f));
-               mpmovefltflt(f, v.u.fval);
-               v.u.fval = f;
-               break;
-       case CTCPLX:
-               c = mal(sizeof(*c));
-               mpmovefltflt(&c->real, &v.u.cval->real);
-               mpmovefltflt(&c->imag, &v.u.cval->imag);
-               v.u.cval = c;
-               break;
-       }
-       return v;
-}
-
-static Val
-tocplx(Val v)
-{
-       Mpcplx *c;
-
-       switch(v.ctype) {
-       case CTINT:
-       case CTRUNE:
-               c = mal(sizeof(*c));
-               mpmovefixflt(&c->real, v.u.xval);
-               mpmovecflt(&c->imag, 0.0);
-               v.ctype = CTCPLX;
-               v.u.cval = c;
-               break;
-       case CTFLT:
-               c = mal(sizeof(*c));
-               mpmovefltflt(&c->real, v.u.fval);
-               mpmovecflt(&c->imag, 0.0);
-               v.ctype = CTCPLX;
-               v.u.cval = c;
-               break;
-       }
-       return v;
-}
-
-static Val
-toflt(Val v)
-{
-       Mpflt *f;
-
-       switch(v.ctype) {
-       case CTINT:
-       case CTRUNE:
-               f = mal(sizeof(*f));
-               mpmovefixflt(f, v.u.xval);
-               v.ctype = CTFLT;
-               v.u.fval = f;
-               break;
-       case CTCPLX:
-               f = mal(sizeof(*f));
-               mpmovefltflt(f, &v.u.cval->real);
-               if(mpcmpfltc(&v.u.cval->imag, 0) != 0)
-                       yyerror("constant %#F%+#Fi truncated to real", &v.u.cval->real, &v.u.cval->imag);
-               v.ctype = CTFLT;
-               v.u.fval = f;
-               break;
-       }
-       return v;
-}
-
-Val
-toint(Val v)
-{
-       Mpint *i;
-
-       switch(v.ctype) {
-       case CTRUNE:
-               v.ctype = CTINT;
-               break;
-       case CTFLT:
-               i = mal(sizeof(*i));
-               if(mpmovefltfix(i, v.u.fval) < 0)
-                       yyerror("constant %#F truncated to integer", v.u.fval);
-               v.ctype = CTINT;
-               v.u.xval = i;
-               break;
-       case CTCPLX:
-               i = mal(sizeof(*i));
-               if(mpmovefltfix(i, &v.u.cval->real) < 0)
-                       yyerror("constant %#F%+#Fi truncated to integer", &v.u.cval->real, &v.u.cval->imag);
-               if(mpcmpfltc(&v.u.cval->imag, 0) != 0)
-                       yyerror("constant %#F%+#Fi truncated to real", &v.u.cval->real, &v.u.cval->imag);
-               v.ctype = CTINT;
-               v.u.xval = i;
-               break;
-       }
-       return v;
-}
-
-int
-doesoverflow(Val v, Type *t)
-{
-       switch(v.ctype) {
-       case CTINT:
-       case CTRUNE:
-               if(!isint[t->etype])
-                       fatal("overflow: %T integer constant", t);
-               if(mpcmpfixfix(v.u.xval, minintval[t->etype]) < 0 ||
-                  mpcmpfixfix(v.u.xval, maxintval[t->etype]) > 0)
-                       return 1;
-               break;
-       case CTFLT:
-               if(!isfloat[t->etype])
-                       fatal("overflow: %T floating-point constant", t);
-               if(mpcmpfltflt(v.u.fval, minfltval[t->etype]) <= 0 ||
-                  mpcmpfltflt(v.u.fval, maxfltval[t->etype]) >= 0)
-                       return 1;
-               break;
-       case CTCPLX:
-               if(!iscomplex[t->etype])
-                       fatal("overflow: %T complex constant", t);
-               if(mpcmpfltflt(&v.u.cval->real, minfltval[t->etype]) <= 0 ||
-                  mpcmpfltflt(&v.u.cval->real, maxfltval[t->etype]) >= 0 ||
-                  mpcmpfltflt(&v.u.cval->imag, minfltval[t->etype]) <= 0 ||
-                  mpcmpfltflt(&v.u.cval->imag, maxfltval[t->etype]) >= 0)
-                       return 1;
-               break;
-       }
-       return 0;
-}
-
-void
-overflow(Val v, Type *t)
-{
-       // v has already been converted
-       // to appropriate form for t.
-       if(t == T || t->etype == TIDEAL)
-               return;
-
-       if(!doesoverflow(v, t))
-               return;
-
-       switch(v.ctype) {
-       case CTINT:
-       case CTRUNE:
-               yyerror("constant %B overflows %T", v.u.xval, t);
-               break;
-       case CTFLT:
-               yyerror("constant %#F overflows %T", v.u.fval, t);
-               break;
-       case CTCPLX:
-               yyerror("constant %#F overflows %T", v.u.fval, t);
-               break;
-       }
-}
-
-static Val
-tostr(Val v)
-{
-       Rune rune;
-       int l;
-       Strlit *s;
-
-       switch(v.ctype) {
-       case CTINT:
-       case CTRUNE:
-               if(mpcmpfixfix(v.u.xval, minintval[TINT]) < 0 ||
-                  mpcmpfixfix(v.u.xval, maxintval[TINT]) > 0)
-                       yyerror("overflow in int -> string");
-               rune = mpgetfix(v.u.xval);
-               l = runelen(rune);
-               s = mal(sizeof(*s)+l);
-               s->len = l;
-               runetochar((char*)s->s, &rune);
-               memset(&v, 0, sizeof v);
-               v.ctype = CTSTR;
-               v.u.sval = s;
-               break;
-
-       case CTFLT:
-               yyerror("no float -> string");
-
-       case CTNIL:
-               memset(&v, 0, sizeof v);
-               v.ctype = CTSTR;
-               v.u.sval = mal(sizeof *s);
-               break;
-       }
-       return v;
-}
-
-int
-consttype(Node *n)
-{
-       if(n == N || n->op != OLITERAL)
-               return -1;
-       return n->val.ctype;
-}
-
-int
-isconst(Node *n, int ct)
-{
-       int t;
-       
-       t = consttype(n);
-       // If the caller is asking for CTINT, allow CTRUNE too.
-       // Makes life easier for back ends.
-       return t == ct || (ct == CTINT && t == CTRUNE);
-}
-
-static Node*
-saveorig(Node *n)
-{
-       Node *n1;
-
-       if(n == n->orig) {
-               // duplicate node for n->orig.
-               n1 = nod(OLITERAL, N, N);
-               n->orig = n1;
-               *n1 = *n;
-       }
-       return n->orig;
-}
-
-/*
- * if n is constant, rewrite as OLITERAL node.
- */
-void
-evconst(Node *n)
-{
-       Node *nl, *nr, *norig;
-       int32 len;
-       Strlit *str;
-       int wl, wr, lno, et;
-       Val v, rv;
-       Mpint b;
-       NodeList *l1, *l2;
-
-       // pick off just the opcodes that can be
-       // constant evaluated.
-       switch(n->op) {
-       default:
-               return;
-       case OADD:
-       case OAND:
-       case OANDAND:
-       case OANDNOT:
-       case OARRAYBYTESTR:
-       case OCOM:
-       case ODIV:
-       case OEQ:
-       case OGE:
-       case OGT:
-       case OLE:
-       case OLSH:
-       case OLT:
-       case OMINUS:
-       case OMOD:
-       case OMUL:
-       case ONE:
-       case ONOT:
-       case OOR:
-       case OOROR:
-       case OPLUS:
-       case ORSH:
-       case OSUB:
-       case OXOR:
-               break;
-       case OCONV:
-               if(n->type == T)
-                       return;
-               if(!okforconst[n->type->etype] && n->type->etype != TNIL)
-                       return;
-               break;
-       
-       case OADDSTR:
-               // merge adjacent constants in the argument list.
-               for(l1=n->list; l1 != nil; l1= l1->next) {
-                       if(isconst(l1->n, CTSTR) && l1->next != nil && isconst(l1->next->n, CTSTR)) {
-                               l2 = l1;
-                               len = 0;
-                               while(l2 != nil && isconst(l2->n, CTSTR)) {
-                                       nr = l2->n;
-                                       len += nr->val.u.sval->len;
-                                       l2 = l2->next;
-                               }
-                               // merge from l1 up to but not including l2
-                               str = mal(sizeof(*str) + len);
-                               str->len = len;
-                               len = 0;
-                               l2 = l1;
-                               while(l2 != nil && isconst(l2->n, CTSTR)) {
-                                       nr = l2->n;
-                                       memmove(str->s+len, nr->val.u.sval->s, nr->val.u.sval->len);
-                                       len += nr->val.u.sval->len;
-                                       l2 = l2->next;
-                               }
-                               nl = nod(OXXX, N, N);
-                               *nl = *l1->n;
-                               nl->orig = nl;
-                               nl->val.ctype = CTSTR;
-                               nl->val.u.sval = str;
-                               l1->n = nl;
-                               l1->next = l2;
-                       }
-               }
-               // fix list end pointer.
-               for(l2=n->list; l2 != nil; l2=l2->next)
-                       n->list->end = l2;
-               // collapse single-constant list to single constant.
-               if(count(n->list) == 1 && isconst(n->list->n, CTSTR)) {
-                       n->op = OLITERAL;
-                       n->val = n->list->n->val;
-               }
-               return;
-       }
-
-       nl = n->left;
-       if(nl == N || nl->type == T)
-               return;
-       if(consttype(nl) < 0)
-               return;
-       wl = nl->type->etype;
-       if(isint[wl] || isfloat[wl] || iscomplex[wl])
-               wl = TIDEAL;
-
-       nr = n->right;
-       if(nr == N)
-               goto unary;
-       if(nr->type == T)
-               return;
-       if(consttype(nr) < 0)
-               return;
-       wr = nr->type->etype;
-       if(isint[wr] || isfloat[wr] || iscomplex[wr])
-               wr = TIDEAL;
-
-       // check for compatible general types (numeric, string, etc)
-       if(wl != wr)
-               goto illegal;
-
-       // check for compatible types.
-       switch(n->op) {
-       default:
-               // ideal const mixes with anything but otherwise must match.
-               if(nl->type->etype != TIDEAL) {
-                       defaultlit(&nr, nl->type);
-                       n->right = nr;
-               }
-               if(nr->type->etype != TIDEAL) {
-                       defaultlit(&nl, nr->type);
-                       n->left = nl;
-               }
-               if(nl->type->etype != nr->type->etype)
-                       goto illegal;
-               break;
-
-       case OLSH:
-       case ORSH:
-               // right must be unsigned.
-               // left can be ideal.
-               defaultlit(&nr, types[TUINT]);
-               n->right = nr;
-               if(nr->type && (issigned[nr->type->etype] || !isint[nr->type->etype]))
-                       goto illegal;
-               if(nl->val.ctype != CTRUNE)
-                       nl->val = toint(nl->val);
-               nr->val = toint(nr->val);
-               break;
-       }
-
-       // copy numeric value to avoid modifying
-       // n->left, in case someone still refers to it (e.g. iota).
-       v = nl->val;
-       if(wl == TIDEAL)
-               v = copyval(v);
-
-       rv = nr->val;
-
-       // convert to common ideal
-       if(v.ctype == CTCPLX || rv.ctype == CTCPLX) {
-               v = tocplx(v);
-               rv = tocplx(rv);
-       }
-       if(v.ctype == CTFLT || rv.ctype == CTFLT) {
-               v = toflt(v);
-               rv = toflt(rv);
-       }
-
-       // Rune and int turns into rune.
-       if(v.ctype == CTRUNE && rv.ctype == CTINT)
-               rv.ctype = CTRUNE;
-       if(v.ctype == CTINT && rv.ctype == CTRUNE) {
-               if(n->op == OLSH || n->op == ORSH)
-                       rv.ctype = CTINT;
-               else
-                       v.ctype = CTRUNE;
-       }
-
-       if(v.ctype != rv.ctype) {
-               // Use of undefined name as constant?
-               if((v.ctype == 0 || rv.ctype == 0) && nerrors > 0)
-                       return;
-               fatal("constant type mismatch %T(%d) %T(%d)", nl->type, v.ctype, nr->type, rv.ctype);
-       }
-
-       // run op
-       switch(TUP(n->op, v.ctype)) {
-       default:
-               goto illegal;
-       case TUP(OADD, CTINT):
-       case TUP(OADD, CTRUNE):
-               mpaddfixfix(v.u.xval, rv.u.xval, 0);
-               break;
-       case TUP(OSUB, CTINT):
-       case TUP(OSUB, CTRUNE):
-               mpsubfixfix(v.u.xval, rv.u.xval);
-               break;
-       case TUP(OMUL, CTINT):
-       case TUP(OMUL, CTRUNE):
-               mpmulfixfix(v.u.xval, rv.u.xval);
-               break;
-       case TUP(ODIV, CTINT):
-       case TUP(ODIV, CTRUNE):
-               if(mpcmpfixc(rv.u.xval, 0) == 0) {
-                       yyerror("division by zero");
-                       mpmovecfix(v.u.xval, 1);
-                       break;
-               }
-               mpdivfixfix(v.u.xval, rv.u.xval);
-               break;
-       case TUP(OMOD, CTINT):
-       case TUP(OMOD, CTRUNE):
-               if(mpcmpfixc(rv.u.xval, 0) == 0) {
-                       yyerror("division by zero");
-                       mpmovecfix(v.u.xval, 1);
-                       break;
-               }
-               mpmodfixfix(v.u.xval, rv.u.xval);
-               break;
-
-       case TUP(OLSH, CTINT):
-       case TUP(OLSH, CTRUNE):
-               mplshfixfix(v.u.xval, rv.u.xval);
-               break;
-       case TUP(ORSH, CTINT):
-       case TUP(ORSH, CTRUNE):
-               mprshfixfix(v.u.xval, rv.u.xval);
-               break;
-       case TUP(OOR, CTINT):
-       case TUP(OOR, CTRUNE):
-               mporfixfix(v.u.xval, rv.u.xval);
-               break;
-       case TUP(OAND, CTINT):
-       case TUP(OAND, CTRUNE):
-               mpandfixfix(v.u.xval, rv.u.xval);
-               break;
-       case TUP(OANDNOT, CTINT):
-       case TUP(OANDNOT, CTRUNE):
-               mpandnotfixfix(v.u.xval, rv.u.xval);
-               break;
-       case TUP(OXOR, CTINT):
-       case TUP(OXOR, CTRUNE):
-               mpxorfixfix(v.u.xval, rv.u.xval);
-               break;
-
-       case TUP(OADD, CTFLT):
-               mpaddfltflt(v.u.fval, rv.u.fval);
-               break;
-       case TUP(OSUB, CTFLT):
-               mpsubfltflt(v.u.fval, rv.u.fval);
-               break;
-       case TUP(OMUL, CTFLT):
-               mpmulfltflt(v.u.fval, rv.u.fval);
-               break;
-       case TUP(ODIV, CTFLT):
-               if(mpcmpfltc(rv.u.fval, 0) == 0) {
-                       yyerror("division by zero");
-                       mpmovecflt(v.u.fval, 1.0);
-                       break;
-               }
-               mpdivfltflt(v.u.fval, rv.u.fval);
-               break;
-       case TUP(OMOD, CTFLT):
-               // The default case above would print 'ideal % ideal',
-               // which is not quite an ideal error.
-               if(!n->diag) {
-                       yyerror("illegal constant expression: floating-point %% operation");
-                       n->diag = 1;
-               }
-               return;
-
-       case TUP(OADD, CTCPLX):
-               mpaddfltflt(&v.u.cval->real, &rv.u.cval->real);
-               mpaddfltflt(&v.u.cval->imag, &rv.u.cval->imag);
-               break;
-       case TUP(OSUB, CTCPLX):
-               mpsubfltflt(&v.u.cval->real, &rv.u.cval->real);
-               mpsubfltflt(&v.u.cval->imag, &rv.u.cval->imag);
-               break;
-       case TUP(OMUL, CTCPLX):
-               cmplxmpy(v.u.cval, rv.u.cval);
-               break;
-       case TUP(ODIV, CTCPLX):
-               if(mpcmpfltc(&rv.u.cval->real, 0) == 0 &&
-                  mpcmpfltc(&rv.u.cval->imag, 0) == 0) {
-                       yyerror("complex division by zero");
-                       mpmovecflt(&rv.u.cval->real, 1.0);
-                       mpmovecflt(&rv.u.cval->imag, 0.0);
-                       break;
-               }
-               cmplxdiv(v.u.cval, rv.u.cval);
-               break;
-
-       case TUP(OEQ, CTNIL):
-               goto settrue;
-       case TUP(ONE, CTNIL):
-               goto setfalse;
-
-       case TUP(OEQ, CTINT):
-       case TUP(OEQ, CTRUNE):
-               if(mpcmpfixfix(v.u.xval, rv.u.xval) == 0)
-                       goto settrue;
-               goto setfalse;
-       case TUP(ONE, CTINT):
-       case TUP(ONE, CTRUNE):
-               if(mpcmpfixfix(v.u.xval, rv.u.xval) != 0)
-                       goto settrue;
-               goto setfalse;
-       case TUP(OLT, CTINT):
-       case TUP(OLT, CTRUNE):
-               if(mpcmpfixfix(v.u.xval, rv.u.xval) < 0)
-                       goto settrue;
-               goto setfalse;
-       case TUP(OLE, CTINT):
-       case TUP(OLE, CTRUNE):
-               if(mpcmpfixfix(v.u.xval, rv.u.xval) <= 0)
-                       goto settrue;
-               goto setfalse;
-       case TUP(OGE, CTINT):
-       case TUP(OGE, CTRUNE):
-               if(mpcmpfixfix(v.u.xval, rv.u.xval) >= 0)
-                       goto settrue;
-               goto setfalse;
-       case TUP(OGT, CTINT):
-       case TUP(OGT, CTRUNE):
-               if(mpcmpfixfix(v.u.xval, rv.u.xval) > 0)
-                       goto settrue;
-               goto setfalse;
-
-       case TUP(OEQ, CTFLT):
-               if(mpcmpfltflt(v.u.fval, rv.u.fval) == 0)
-                       goto settrue;
-               goto setfalse;
-       case TUP(ONE, CTFLT):
-               if(mpcmpfltflt(v.u.fval, rv.u.fval) != 0)
-                       goto settrue;
-               goto setfalse;
-       case TUP(OLT, CTFLT):
-               if(mpcmpfltflt(v.u.fval, rv.u.fval) < 0)
-                       goto settrue;
-               goto setfalse;
-       case TUP(OLE, CTFLT):
-               if(mpcmpfltflt(v.u.fval, rv.u.fval) <= 0)
-                       goto settrue;
-               goto setfalse;
-       case TUP(OGE, CTFLT):
-               if(mpcmpfltflt(v.u.fval, rv.u.fval) >= 0)
-                       goto settrue;
-               goto setfalse;
-       case TUP(OGT, CTFLT):
-               if(mpcmpfltflt(v.u.fval, rv.u.fval) > 0)
-                       goto settrue;
-               goto setfalse;
-
-       case TUP(OEQ, CTCPLX):
-               if(mpcmpfltflt(&v.u.cval->real, &rv.u.cval->real) == 0 &&
-                  mpcmpfltflt(&v.u.cval->imag, &rv.u.cval->imag) == 0)
-                       goto settrue;
-               goto setfalse;
-       case TUP(ONE, CTCPLX):
-               if(mpcmpfltflt(&v.u.cval->real, &rv.u.cval->real) != 0 ||
-                  mpcmpfltflt(&v.u.cval->imag, &rv.u.cval->imag) != 0)
-                       goto settrue;
-               goto setfalse;
-
-       case TUP(OEQ, CTSTR):
-               if(cmpslit(nl, nr) == 0)
-                       goto settrue;
-               goto setfalse;
-       case TUP(ONE, CTSTR):
-               if(cmpslit(nl, nr) != 0)
-                       goto settrue;
-               goto setfalse;
-       case TUP(OLT, CTSTR):
-               if(cmpslit(nl, nr) < 0)
-                       goto settrue;
-               goto setfalse;
-       case TUP(OLE, CTSTR):
-               if(cmpslit(nl, nr) <= 0)
-                       goto settrue;
-               goto setfalse;
-       case TUP(OGE, CTSTR):
-               if(cmpslit(nl, nr) >= 0l)
-                       goto settrue;
-               goto setfalse;
-       case TUP(OGT, CTSTR):
-               if(cmpslit(nl, nr) > 0)
-                       goto settrue;
-               goto setfalse;
-
-       case TUP(OOROR, CTBOOL):
-               if(v.u.bval || rv.u.bval)
-                       goto settrue;
-               goto setfalse;
-       case TUP(OANDAND, CTBOOL):
-               if(v.u.bval && rv.u.bval)
-                       goto settrue;
-               goto setfalse;
-       case TUP(OEQ, CTBOOL):
-               if(v.u.bval == rv.u.bval)
-                       goto settrue;
-               goto setfalse;
-       case TUP(ONE, CTBOOL):
-               if(v.u.bval != rv.u.bval)
-                       goto settrue;
-               goto setfalse;
-       }
-       goto ret;
-
-unary:
-       // copy numeric value to avoid modifying
-       // nl, in case someone still refers to it (e.g. iota).
-       v = nl->val;
-       if(wl == TIDEAL)
-               v = copyval(v);
-
-       switch(TUP(n->op, v.ctype)) {
-       default:
-               if(!n->diag) {
-                       yyerror("illegal constant expression %O %T", n->op, nl->type);
-                       n->diag = 1;
-               }
-               return;
-
-       case TUP(OCONV, CTNIL):
-       case TUP(OARRAYBYTESTR, CTNIL):
-               if(n->type->etype == TSTRING) {
-                       v = tostr(v);
-                       nl->type = n->type;
-                       break;
-               }
-               // fall through
-       case TUP(OCONV, CTINT):
-       case TUP(OCONV, CTRUNE):
-       case TUP(OCONV, CTFLT):
-       case TUP(OCONV, CTSTR):
-               convlit1(&nl, n->type, 1);
-               v = nl->val;
-               break;
-
-       case TUP(OPLUS, CTINT):
-       case TUP(OPLUS, CTRUNE):
-               break;
-       case TUP(OMINUS, CTINT):
-       case TUP(OMINUS, CTRUNE):
-               mpnegfix(v.u.xval);
-               break;
-       case TUP(OCOM, CTINT):
-       case TUP(OCOM, CTRUNE):
-               et = Txxx;
-               if(nl->type != T)
-                       et = nl->type->etype;
-
-               // calculate the mask in b
-               // result will be (a ^ mask)
-               switch(et) {
-               default:
-                       // signed guys change sign
-                       mpmovecfix(&b, -1);
-                       break;
-
-               case TUINT8:
-               case TUINT16:
-               case TUINT32:
-               case TUINT64:
-               case TUINT:
-               case TUINTPTR:
-                       // unsigned guys invert their bits
-                       mpmovefixfix(&b, maxintval[et]);
-                       break;
-               }
-               mpxorfixfix(v.u.xval, &b);
-               break;
-
-       case TUP(OPLUS, CTFLT):
-               break;
-       case TUP(OMINUS, CTFLT):
-               mpnegflt(v.u.fval);
-               break;
-
-       case TUP(OPLUS, CTCPLX):
-               break;
-       case TUP(OMINUS, CTCPLX):
-               mpnegflt(&v.u.cval->real);
-               mpnegflt(&v.u.cval->imag);
-               break;
-
-       case TUP(ONOT, CTBOOL):
-               if(!v.u.bval)
-                       goto settrue;
-               goto setfalse;
-       }
-
-ret:
-       norig = saveorig(n);
-       *n = *nl;
-       // restore value of n->orig.
-       n->orig = norig;
-       n->val = v;
-
-       // check range.
-       lno = setlineno(n);
-       overflow(v, n->type);
-       lineno = lno;
-
-       // truncate precision for non-ideal float.
-       if(v.ctype == CTFLT && n->type->etype != TIDEAL)
-               n->val.u.fval = truncfltlit(v.u.fval, n->type);
-       return;
-
-settrue:
-       norig = saveorig(n);
-       *n = *nodbool(1);
-       n->orig = norig;
-       return;
-
-setfalse:
-       norig = saveorig(n);
-       *n = *nodbool(0);
-       n->orig = norig;
-       return;
-
-illegal:
-       if(!n->diag) {
-               yyerror("illegal constant expression: %T %O %T",
-                       nl->type, n->op, nr->type);
-               n->diag = 1;
-       }
-       return;
-}
-
-Node*
-nodlit(Val v)
-{
-       Node *n;
-
-       n = nod(OLITERAL, N, N);
-       n->val = v;
-       switch(v.ctype) {
-       default:
-               fatal("nodlit ctype %d", v.ctype);
-       case CTSTR:
-               n->type = idealstring;
-               break;
-       case CTBOOL:
-               n->type = idealbool;
-               break;
-       case CTINT:
-       case CTRUNE:
-       case CTFLT:
-       case CTCPLX:
-               n->type = types[TIDEAL];
-               break;
-       case CTNIL:
-               n->type = types[TNIL];
-               break;
-       }
-       return n;
-}
-
-Node*
-nodcplxlit(Val r, Val i)
-{
-       Node *n;
-       Mpcplx *c;
-
-       r = toflt(r);
-       i = toflt(i);
-
-       c = mal(sizeof(*c));
-       n = nod(OLITERAL, N, N);
-       n->type = types[TIDEAL];
-       n->val.u.cval = c;
-       n->val.ctype = CTCPLX;
-
-       if(r.ctype != CTFLT || i.ctype != CTFLT)
-               fatal("nodcplxlit ctype %d/%d", r.ctype, i.ctype);
-
-       mpmovefltflt(&c->real, r.u.fval);
-       mpmovefltflt(&c->imag, i.u.fval);
-       return n;
-}
-
-// idealkind returns a constant kind like consttype
-// but for an arbitrary "ideal" (untyped constant) expression.
-static int
-idealkind(Node *n)
-{
-       int k1, k2;
-
-       if(n == N || !isideal(n->type))
-               return CTxxx;
-
-       switch(n->op) {
-       default:
-               return CTxxx;
-       case OLITERAL:
-               return n->val.ctype;
-       case OADD:
-       case OAND:
-       case OANDNOT:
-       case OCOM:
-       case ODIV:
-       case OMINUS:
-       case OMOD:
-       case OMUL:
-       case OSUB:
-       case OXOR:
-       case OOR:
-       case OPLUS:
-               // numeric kinds.
-               k1 = idealkind(n->left);
-               k2 = idealkind(n->right);
-               if(k1 > k2)
-                       return k1;
-               else
-                       return k2;
-       case OREAL:
-       case OIMAG:
-               return CTFLT;
-       case OCOMPLEX:
-               return CTCPLX;
-       case OADDSTR:
-               return CTSTR;
-       case OANDAND:
-       case OEQ:
-       case OGE:
-       case OGT:
-       case OLE:
-       case OLT:
-       case ONE:
-       case ONOT:
-       case OOROR:
-       case OCMPSTR:
-       case OCMPIFACE:
-               return CTBOOL;
-       case OLSH:
-       case ORSH:
-               // shifts (beware!).
-               return idealkind(n->left);
-       }
-}
-
-void
-defaultlit(Node **np, Type *t)
-{
-       int lno;
-       int ctype;
-       Node *n, *nn;
-       Type *t1;
-
-       n = *np;
-       if(n == N || !isideal(n->type))
-               return;
-
-       if(n->op == OLITERAL) {
-               nn = nod(OXXX, N, N);
-               *nn = *n;
-               n = nn;
-               *np = n;
-       }
-
-       lno = setlineno(n);
-       ctype = idealkind(n);
-       switch(ctype) {
-       default:
-               if(t != T) {
-                       convlit(np, t);
-                       return;
-               }
-               if(n->val.ctype == CTNIL) {
-                       lineno = lno;
-                       if(!n->diag) {
-                               yyerror("use of untyped nil");
-                               n->diag = 1;
-                       }
-                       n->type = T;
-                       break;
-               }
-               if(n->val.ctype == CTSTR) {
-                       t1 = types[TSTRING];
-                       convlit(np, t1);
-                       break;
-               }
-               yyerror("defaultlit: unknown literal: %N", n);
-               break;
-       case CTxxx:
-               fatal("defaultlit: idealkind is CTxxx: %+N", n);
-               break;
-       case CTBOOL:
-               t1 = types[TBOOL];
-               if(t != T && t->etype == TBOOL)
-                       t1 = t;
-               convlit(np, t1);
-               break;
-       case CTINT:
-               t1 = types[TINT];
-               goto num;
-       case CTRUNE:
-               t1 = runetype;
-               goto num;
-       case CTFLT:
-               t1 = types[TFLOAT64];
-               goto num;
-       case CTCPLX:
-               t1 = types[TCOMPLEX128];
-               goto num;
-       }
-       lineno = lno;
-       return;
-
-num:
-       if(t != T) {
-               if(isint[t->etype]) {
-                       t1 = t;
-                       n->val = toint(n->val);
-               }
-               else
-               if(isfloat[t->etype]) {
-                       t1 = t;
-                       n->val = toflt(n->val);
-               }
-               else
-               if(iscomplex[t->etype]) {
-                       t1 = t;
-                       n->val = tocplx(n->val);
-               }
-       }
-       overflow(n->val, t1);
-       convlit(np, t1);
-       lineno = lno;
-       return;
-}
-
-/*
- * defaultlit on both nodes simultaneously;
- * if they're both ideal going in they better
- * get the same type going out.
- * force means must assign concrete (non-ideal) type.
- */
-void
-defaultlit2(Node **lp, Node **rp, int force)
-{
-       Node *l, *r;
-       int lkind, rkind;
-
-       l = *lp;
-       r = *rp;
-       if(l->type == T || r->type == T)
-               return;
-       if(!isideal(l->type)) {
-               convlit(rp, l->type);
-               return;
-       }
-       if(!isideal(r->type)) {
-               convlit(lp, r->type);
-               return;
-       }
-       if(!force)
-               return;
-       if(l->type->etype == TBOOL) {
-               convlit(lp, types[TBOOL]);
-               convlit(rp, types[TBOOL]);
-       }
-       lkind = idealkind(l);
-       rkind = idealkind(r);
-       if(lkind == CTCPLX || rkind == CTCPLX) {
-               convlit(lp, types[TCOMPLEX128]);
-               convlit(rp, types[TCOMPLEX128]);
-               return;
-       }
-       if(lkind == CTFLT || rkind == CTFLT) {
-               convlit(lp, types[TFLOAT64]);
-               convlit(rp, types[TFLOAT64]);
-               return;
-       }
-
-       if(lkind == CTRUNE || rkind == CTRUNE) {
-               convlit(lp, runetype);
-               convlit(rp, runetype);
-               return;
-       }
-
-       convlit(lp, types[TINT]);
-       convlit(rp, types[TINT]);
-}
-
-int
-cmpslit(Node *l, Node *r)
-{
-       int32 l1, l2, i, m;
-       uchar *s1, *s2;
-
-       l1 = l->val.u.sval->len;
-       l2 = r->val.u.sval->len;
-       s1 = (uchar*)l->val.u.sval->s;
-       s2 = (uchar*)r->val.u.sval->s;
-
-       m = l1;
-       if(l2 < m)
-               m = l2;
-
-       for(i=0; i<m; i++) {
-               if(s1[i] == s2[i])
-                       continue;
-               if(s1[i] > s2[i])
-                       return +1;
-               return -1;
-       }
-       if(l1 == l2)
-               return 0;
-       if(l1 > l2)
-               return +1;
-       return -1;
-}
-
-int
-smallintconst(Node *n)
-{
-       if(n->op == OLITERAL && isconst(n, CTINT) && n->type != T)
-       switch(simtype[n->type->etype]) {
-       case TINT8:
-       case TUINT8:
-       case TINT16:
-       case TUINT16:
-       case TINT32:
-       case TUINT32:
-       case TBOOL:
-       case TPTR32:
-               return 1;
-       case TIDEAL:
-       case TINT64:
-       case TUINT64:
-       case TPTR64:
-               if(mpcmpfixfix(n->val.u.xval, minintval[TINT32]) < 0
-               || mpcmpfixfix(n->val.u.xval, maxintval[TINT32]) > 0)
-                       break;
-               return 1;
-       }
-       return 0;
-}
-
-long
-nonnegconst(Node *n)
-{
-       if(n->op == OLITERAL && n->type != T)
-       switch(simtype[n->type->etype]) {
-       case TINT8:
-       case TUINT8:
-       case TINT16:
-       case TUINT16:
-       case TINT32:
-       case TUINT32:
-       case TINT64:
-       case TUINT64:
-       case TIDEAL:
-               // check negative and 2^31
-               if(mpcmpfixfix(n->val.u.xval, minintval[TUINT32]) < 0
-               || mpcmpfixfix(n->val.u.xval, maxintval[TINT32]) > 0)
-                       break;
-               return mpgetfix(n->val.u.xval);
-       }
-       return -1;
-}
-
-/*
- * convert x to type et and back to int64
- * for sign extension and truncation.
- */
-static int64
-iconv(int64 x, int et)
-{
-       switch(et) {
-       case TINT8:
-               x = (int8)x;
-               break;
-       case TUINT8:
-               x = (uint8)x;
-               break;
-       case TINT16:
-               x = (int16)x;
-               break;
-       case TUINT16:
-               x = (uint64)x;
-               break;
-       case TINT32:
-               x = (int32)x;
-               break;
-       case TUINT32:
-               x = (uint32)x;
-               break;
-       case TINT64:
-       case TUINT64:
-               break;
-       }
-       return x;
-}
-
-/*
- * convert constant val to type t; leave in con.
- * for back end.
- */
-void
-convconst(Node *con, Type *t, Val *val)
-{
-       int64 i;
-       int tt;
-
-       tt = simsimtype(t);
-
-       // copy the constant for conversion
-       nodconst(con, types[TINT8], 0);
-       con->type = t;
-       con->val = *val;
-
-       if(isint[tt]) {
-               con->val.ctype = CTINT;
-               con->val.u.xval = mal(sizeof *con->val.u.xval);
-               switch(val->ctype) {
-               default:
-                       fatal("convconst ctype=%d %lT", val->ctype, t);
-               case CTINT:
-               case CTRUNE:
-                       i = mpgetfix(val->u.xval);
-                       break;
-               case CTBOOL:
-                       i = val->u.bval;
-                       break;
-               case CTNIL:
-                       i = 0;
-                       break;
-               }
-               i = iconv(i, tt);
-               mpmovecfix(con->val.u.xval, i);
-               return;
-       }
-
-       if(isfloat[tt]) {
-               con->val = toflt(con->val);
-               if(con->val.ctype != CTFLT)
-                       fatal("convconst ctype=%d %T", con->val.ctype, t);
-               if(tt == TFLOAT32)
-                       con->val.u.fval = truncfltlit(con->val.u.fval, t);
-               return;
-       }
-
-       if(iscomplex[tt]) {
-               con->val = tocplx(con->val);
-               if(tt == TCOMPLEX64) {
-                       con->val.u.cval->real = *truncfltlit(&con->val.u.cval->real, types[TFLOAT32]);
-                       con->val.u.cval->imag = *truncfltlit(&con->val.u.cval->imag, types[TFLOAT32]);
-               }
-               return;
-       }
-
-       fatal("convconst %lT constant", t);
-
-}
-
-// complex multiply v *= rv
-//     (a, b) * (c, d) = (a*c - b*d, b*c + a*d)
-static void
-cmplxmpy(Mpcplx *v, Mpcplx *rv)
-{
-       Mpflt ac, bd, bc, ad;
-
-       mpmovefltflt(&ac, &v->real);
-       mpmulfltflt(&ac, &rv->real);    // ac
-
-       mpmovefltflt(&bd, &v->imag);
-       mpmulfltflt(&bd, &rv->imag);    // bd
-
-       mpmovefltflt(&bc, &v->imag);
-       mpmulfltflt(&bc, &rv->real);    // bc
-
-       mpmovefltflt(&ad, &v->real);
-       mpmulfltflt(&ad, &rv->imag);    // ad
-
-       mpmovefltflt(&v->real, &ac);
-       mpsubfltflt(&v->real, &bd);     // ac-bd
-
-       mpmovefltflt(&v->imag, &bc);
-       mpaddfltflt(&v->imag, &ad);     // bc+ad
-}
-
-// complex divide v /= rv
-//     (a, b) / (c, d) = ((a*c + b*d), (b*c - a*d))/(c*c + d*d)
-static void
-cmplxdiv(Mpcplx *v, Mpcplx *rv)
-{
-       Mpflt ac, bd, bc, ad, cc_plus_dd;
-
-       mpmovefltflt(&cc_plus_dd, &rv->real);
-       mpmulfltflt(&cc_plus_dd, &rv->real);    // cc
-
-       mpmovefltflt(&ac, &rv->imag);
-       mpmulfltflt(&ac, &rv->imag);            // dd
-
-       mpaddfltflt(&cc_plus_dd, &ac);          // cc+dd
-
-       mpmovefltflt(&ac, &v->real);
-       mpmulfltflt(&ac, &rv->real);            // ac
-
-       mpmovefltflt(&bd, &v->imag);
-       mpmulfltflt(&bd, &rv->imag);            // bd
-
-       mpmovefltflt(&bc, &v->imag);
-       mpmulfltflt(&bc, &rv->real);            // bc
-
-       mpmovefltflt(&ad, &v->real);
-       mpmulfltflt(&ad, &rv->imag);            // ad
-
-       mpmovefltflt(&v->real, &ac);
-       mpaddfltflt(&v->real, &bd);             // ac+bd
-       mpdivfltflt(&v->real, &cc_plus_dd);     // (ac+bd)/(cc+dd)
-
-       mpmovefltflt(&v->imag, &bc);
-       mpsubfltflt(&v->imag, &ad);             // bc-ad
-       mpdivfltflt(&v->imag, &cc_plus_dd);     // (bc+ad)/(cc+dd)
-}
-
-static int hascallchan(Node*);
-
-// Is n a Go language constant (as opposed to a compile-time constant)?
-// Expressions derived from nil, like string([]byte(nil)), while they
-// may be known at compile time, are not Go language constants.
-// Only called for expressions known to evaluated to compile-time
-// constants.
-int
-isgoconst(Node *n)
-{
-       Node *l;
-       Type *t;
-
-       if(n->orig != N)
-               n = n->orig;
-
-       switch(n->op) {
-       case OADD:
-       case OADDSTR:
-       case OAND:
-       case OANDAND:
-       case OANDNOT:
-       case OCOM:
-       case ODIV:
-       case OEQ:
-       case OGE:
-       case OGT:
-       case OLE:
-       case OLSH:
-       case OLT:
-       case OMINUS:
-       case OMOD:
-       case OMUL:
-       case ONE:
-       case ONOT:
-       case OOR:
-       case OOROR:
-       case OPLUS:
-       case ORSH:
-       case OSUB:
-       case OXOR:
-       case OIOTA:
-       case OCOMPLEX:
-       case OREAL:
-       case OIMAG:
-               if(isgoconst(n->left) && (n->right == N || isgoconst(n->right)))
-                       return 1;
-               break;
-
-       case OCONV:
-               if(okforconst[n->type->etype] && isgoconst(n->left))
-                       return 1;
-               break;
-
-       case OLEN:
-       case OCAP:
-               l = n->left;
-               if(isgoconst(l))
-                       return 1;
-               // Special case: len/cap is constant when applied to array or
-               // pointer to array when the expression does not contain
-               // function calls or channel receive operations.
-               t = l->type;
-               if(t != T && isptr[t->etype])
-                       t = t->type;
-               if(isfixedarray(t) && !hascallchan(l))
-                       return 1;
-               break;
-
-       case OLITERAL:
-               if(n->val.ctype != CTNIL)
-                       return 1;
-               break;
-
-       case ONAME:
-               l = n->sym->def;
-               if(l && l->op == OLITERAL && n->val.ctype != CTNIL)
-                       return 1;
-               break;
-       
-       case ONONAME:
-               if(n->sym->def != N && n->sym->def->op == OIOTA)
-                       return 1;
-               break;
-       
-       case OCALL:
-               // Only constant calls are unsafe.Alignof, Offsetof, and Sizeof.
-               l = n->left;
-               while(l->op == OPAREN)
-                       l = l->left;
-               if(l->op != ONAME || l->sym->pkg != unsafepkg)
-                       break;
-               if(strcmp(l->sym->name, "Alignof") == 0 ||
-                  strcmp(l->sym->name, "Offsetof") == 0 ||
-                  strcmp(l->sym->name, "Sizeof") == 0)
-                       return 1;
-               break;          
-       }
-
-       //dump("nonconst", n);
-       return 0;
-}
-
-static int
-hascallchan(Node *n)
-{
-       NodeList *l;
-
-       if(n == N)
-               return 0;
-       switch(n->op) {
-       case OAPPEND:
-       case OCALL:
-       case OCALLFUNC:
-       case OCALLINTER:
-       case OCALLMETH:
-       case OCAP:
-       case OCLOSE:
-       case OCOMPLEX:
-       case OCOPY:
-       case ODELETE:
-       case OIMAG:
-       case OLEN:
-       case OMAKE:
-       case ONEW:
-       case OPANIC:
-       case OPRINT:
-       case OPRINTN:
-       case OREAL:
-       case ORECOVER:
-       case ORECV:
-               return 1;
-       }
-       
-       if(hascallchan(n->left) ||
-          hascallchan(n->right))
-               return 1;
-       
-       for(l=n->list; l; l=l->next)
-               if(hascallchan(l->n))
-                       return 1;
-       for(l=n->rlist; l; l=l->next)
-               if(hascallchan(l->n))
-                       return 1;
-
-       return 0;
-}
diff --git a/src/cmd/gc/cplx.c b/src/cmd/gc/cplx.c
deleted file mode 100644 (file)
index 26c21df..0000000
+++ /dev/null
@@ -1,494 +0,0 @@
-// Copyright 2009 The Go Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style
-// license that can be found in the LICENSE file.
-
-#include <u.h>
-#include <libc.h>
-#include "go.h"
-
-static void    subnode(Node *nr, Node *ni, Node *nc);
-static void    minus(Node *nl, Node *res);
-       void    complexminus(Node*, Node*);
-       void    complexadd(int op, Node*, Node*, Node*);
-       void    complexmul(Node*, Node*, Node*);
-
-#define        CASE(a,b)       (((a)<<16)|((b)<<0))
-
-/*c2go
-static int
-CASE(int a, int b)
-{
-       return a<<16 | b;
-}
-*/
-
-static int
-overlap(Node *f, Node *t)
-{
-       // check whether f and t could be overlapping stack references.
-       // not exact, because it's hard to check for the stack register
-       // in portable code.  close enough: worst case we will allocate
-       // an extra temporary and the registerizer will clean it up.
-       return f->op == OINDREG &&
-               t->op == OINDREG &&
-               f->xoffset+f->type->width >= t->xoffset &&
-               t->xoffset+t->type->width >= f->xoffset;
-}
-
-/*
- * generate:
- *     res = n;
- * simplifies and calls gmove.
- */
-void
-complexmove(Node *f, Node *t)
-{
-       int ft, tt;
-       Node n1, n2, n3, n4, tmp;
-
-       if(debug['g']) {
-               dump("\ncomplexmove-f", f);
-               dump("complexmove-t", t);
-       }
-
-       if(!t->addable)
-               fatal("complexmove: to not addable");
-
-       ft = simsimtype(f->type);
-       tt = simsimtype(t->type);
-       switch(CASE(ft,tt)) {
-
-       default:
-               fatal("complexmove: unknown conversion: %T -> %T\n",
-                       f->type, t->type);
-
-       case CASE(TCOMPLEX64,TCOMPLEX64):
-       case CASE(TCOMPLEX64,TCOMPLEX128):
-       case CASE(TCOMPLEX128,TCOMPLEX64):
-       case CASE(TCOMPLEX128,TCOMPLEX128):
-               // complex to complex move/convert.
-               // make f addable.
-               // also use temporary if possible stack overlap.
-               if(!f->addable || overlap(f, t)) {
-                       tempname(&tmp, f->type);
-                       complexmove(f, &tmp);
-                       f = &tmp;
-               }
-
-               subnode(&n1, &n2, f);
-               subnode(&n3, &n4, t);
-
-               thearch.cgen(&n1, &n3);
-               thearch.cgen(&n2, &n4);
-               break;
-       }
-}
-
-int
-complexop(Node *n, Node *res)
-{
-       if(n != N && n->type != T)
-       if(iscomplex[n->type->etype]) {
-               goto maybe;
-       }
-       if(res != N && res->type != T)
-       if(iscomplex[res->type->etype]) {
-               goto maybe;
-       }
-
-       if(n->op == OREAL || n->op == OIMAG)
-               goto yes;
-
-       goto no;
-
-maybe:
-       switch(n->op) {
-       case OCONV:     // implemented ops
-       case OADD:
-       case OSUB:
-       case OMUL:
-       case OMINUS:
-       case OCOMPLEX:
-       case OREAL:
-       case OIMAG:
-               goto yes;
-
-       case ODOT:
-       case ODOTPTR:
-       case OINDEX:
-       case OIND:
-       case ONAME:
-               goto yes;
-       }
-
-no:
-//dump("\ncomplex-no", n);
-       return 0;
-yes:
-//dump("\ncomplex-yes", n);
-       return 1;
-}
-
-void
-complexgen(Node *n, Node *res)
-{
-       Node *nl, *nr;
-       Node tnl, tnr;
-       Node n1, n2, tmp;
-       int tl, tr;
-
-       if(debug['g']) {
-               dump("\ncomplexgen-n", n);
-               dump("complexgen-res", res);
-       }
-       
-       while(n->op == OCONVNOP)
-               n = n->left;
-
-       // pick off float/complex opcodes
-       switch(n->op) {
-       case OCOMPLEX:
-               if(res->addable) {
-                       subnode(&n1, &n2, res);
-                       tempname(&tmp, n1.type);
-                       thearch.cgen(n->left, &tmp);
-                       thearch.cgen(n->right, &n2);
-                       thearch.cgen(&tmp, &n1);
-                       return;
-               }
-               break;
-
-       case OREAL:
-       case OIMAG:
-               nl = n->left;
-               if(!nl->addable) {
-                       tempname(&tmp, nl->type);
-                       complexgen(nl, &tmp);
-                       nl = &tmp;
-               }
-               subnode(&n1, &n2, nl);
-               if(n->op == OREAL) {
-                       thearch.cgen(&n1, res);
-                       return;
-               }
-               thearch.cgen(&n2, res);
-               return;
-       }
-
-       // perform conversion from n to res
-       tl = simsimtype(res->type);
-       tl = cplxsubtype(tl);
-       tr = simsimtype(n->type);
-       tr = cplxsubtype(tr);
-       if(tl != tr) {
-               if(!n->addable) {
-                       tempname(&n1, n->type);
-                       complexmove(n, &n1);
-                       n = &n1;
-               }
-               complexmove(n, res);
-               return;
-       }
-
-       if(!res->addable) {
-               thearch.igen(res, &n1, N);
-               thearch.cgen(n, &n1);
-               thearch.regfree(&n1);
-               return;
-       }
-       if(n->addable) {
-               complexmove(n, res);
-               return;
-       }
-
-       switch(n->op) {
-       default:
-               dump("complexgen: unknown op", n);
-               fatal("complexgen: unknown op %O", n->op);
-
-       case ODOT:
-       case ODOTPTR:
-       case OINDEX:
-       case OIND:
-       case ONAME:     // PHEAP or PPARAMREF var
-       case OCALLFUNC:
-       case OCALLMETH:
-       case OCALLINTER:
-               thearch.igen(n, &n1, res);
-               complexmove(&n1, res);
-               thearch.regfree(&n1);
-               return;
-
-       case OCONV:
-       case OADD:
-       case OSUB:
-       case OMUL:
-       case OMINUS:
-       case OCOMPLEX:
-       case OREAL:
-       case OIMAG:
-               break;
-       }
-
-       nl = n->left;
-       if(nl == N)
-               return;
-       nr = n->right;
-
-       // make both sides addable in ullman order
-       if(nr != N) {
-               if(nl->ullman > nr->ullman && !nl->addable) {
-                       tempname(&tnl, nl->type);
-                       thearch.cgen(nl, &tnl);
-                       nl = &tnl;
-               }
-               if(!nr->addable) {
-                       tempname(&tnr, nr->type);
-                       thearch.cgen(nr, &tnr);
-                       nr = &tnr;
-               }
-       }
-       if(!nl->addable) {
-               tempname(&tnl, nl->type);
-               thearch.cgen(nl, &tnl);
-               nl = &tnl;
-       }
-
-       switch(n->op) {
-       default:
-               fatal("complexgen: unknown op %O", n->op);
-               break;
-
-       case OCONV:
-               complexmove(nl, res);
-               break;
-
-       case OMINUS:
-               complexminus(nl, res);
-               break;
-
-       case OADD:
-       case OSUB:
-               complexadd(n->op, nl, nr, res);
-               break;
-
-       case OMUL:
-               complexmul(nl, nr, res);
-               break;
-       }
-}
-
-void
-complexbool(int op, Node *nl, Node *nr, int true, int likely, Prog *to)
-{
-       Node tnl, tnr;
-       Node n1, n2, n3, n4;
-       Node na, nb, nc;
-
-       // make both sides addable in ullman order
-       if(nr != N) {
-               if(nl->ullman > nr->ullman && !nl->addable) {
-                       tempname(&tnl, nl->type);
-                       thearch.cgen(nl, &tnl);
-                       nl = &tnl;
-               }
-               if(!nr->addable) {
-                       tempname(&tnr, nr->type);
-                       thearch.cgen(nr, &tnr);
-                       nr = &tnr;
-               }
-       }
-       if(!nl->addable) {
-               tempname(&tnl, nl->type);
-               thearch.cgen(nl, &tnl);
-               nl = &tnl;
-       }
-
-       // build tree
-       // real(l) == real(r) && imag(l) == imag(r)
-
-       subnode(&n1, &n2, nl);
-       subnode(&n3, &n4, nr);
-
-       memset(&na, 0, sizeof(na));
-       na.op = OANDAND;
-       na.left = &nb;
-       na.right = &nc;
-       na.type = types[TBOOL];
-
-       memset(&nb, 0, sizeof(nb));
-       nb.op = OEQ;
-       nb.left = &n1;
-       nb.right = &n3;
-       nb.type = types[TBOOL];
-
-       memset(&nc, 0, sizeof(nc));
-       nc.op = OEQ;
-       nc.left = &n2;
-       nc.right = &n4;
-       nc.type = types[TBOOL];
-
-       if(op == ONE)
-               true = !true;
-
-       thearch.bgen(&na, true, likely, to);
-}
-
-void
-nodfconst(Node *n, Type *t, Mpflt* fval)
-{
-       memset(n, 0, sizeof(*n));
-       n->op = OLITERAL;
-       n->addable = 1;
-       ullmancalc(n);
-       n->val.u.fval = fval;
-       n->val.ctype = CTFLT;
-       n->type = t;
-
-       if(!isfloat[t->etype])
-               fatal("nodfconst: bad type %T", t);
-}
-
-// break addable nc-complex into nr-real and ni-imaginary
-static void
-subnode(Node *nr, Node *ni, Node *nc)
-{
-       int tc;
-       Type *t;
-
-       if(!nc->addable)
-               fatal("subnode not addable");
-
-       tc = simsimtype(nc->type);
-       tc = cplxsubtype(tc);
-       t = types[tc];
-
-       if(nc->op == OLITERAL) {
-               nodfconst(nr, t, &nc->val.u.cval->real);
-               nodfconst(ni, t, &nc->val.u.cval->imag);
-               return;
-       }
-
-       *nr = *nc;
-       nr->type = t;
-
-       *ni = *nc;
-       ni->type = t;
-       ni->xoffset += t->width;
-}
-
-// generate code res = -nl
-static void
-minus(Node *nl, Node *res)
-{
-       Node ra;
-
-       memset(&ra, 0, sizeof(ra));
-       ra.op = OMINUS;
-       ra.left = nl;
-       ra.type = nl->type;
-       thearch.cgen(&ra, res);
-}
-
-// build and execute tree
-//     real(res) = -real(nl)
-//     imag(res) = -imag(nl)
-void
-complexminus(Node *nl, Node *res)
-{
-       Node n1, n2, n5, n6;
-
-       subnode(&n1, &n2, nl);
-       subnode(&n5, &n6, res);
-
-       minus(&n1, &n5);
-       minus(&n2, &n6);
-}
-
-
-// build and execute tree
-//     real(res) = real(nl) op real(nr)
-//     imag(res) = imag(nl) op imag(nr)
-void
-complexadd(int op, Node *nl, Node *nr, Node *res)
-{
-       Node n1, n2, n3, n4, n5, n6;
-       Node ra;
-
-       subnode(&n1, &n2, nl);
-       subnode(&n3, &n4, nr);
-       subnode(&n5, &n6, res);
-
-       memset(&ra, 0, sizeof(ra));
-       ra.op = op;
-       ra.left = &n1;
-       ra.right = &n3;
-       ra.type = n1.type;
-       thearch.cgen(&ra, &n5);
-
-       memset(&ra, 0, sizeof(ra));
-       ra.op = op;
-       ra.left = &n2;
-       ra.right = &n4;
-       ra.type = n2.type;
-       thearch.cgen(&ra, &n6);
-}
-
-// build and execute tree
-//     tmp       = real(nl)*real(nr) - imag(nl)*imag(nr)
-//     imag(res) = real(nl)*imag(nr) + imag(nl)*real(nr)
-//     real(res) = tmp
-void
-complexmul(Node *nl, Node *nr, Node *res)
-{
-       Node n1, n2, n3, n4, n5, n6;
-       Node rm1, rm2, ra, tmp;
-
-       subnode(&n1, &n2, nl);
-       subnode(&n3, &n4, nr);
-       subnode(&n5, &n6, res);
-       tempname(&tmp, n5.type);
-
-       // real part -> tmp
-       memset(&rm1, 0, sizeof(rm1));
-       rm1.op = OMUL;
-       rm1.left = &n1;
-       rm1.right = &n3;
-       rm1.type = n1.type;
-
-       memset(&rm2, 0, sizeof(rm2));
-       rm2.op = OMUL;
-       rm2.left = &n2;
-       rm2.right = &n4;
-       rm2.type = n2.type;
-
-       memset(&ra, 0, sizeof(ra));
-       ra.op = OSUB;
-       ra.left = &rm1;
-       ra.right = &rm2;
-       ra.type = rm1.type;
-       thearch.cgen(&ra, &tmp);
-
-       // imag part
-       memset(&rm1, 0, sizeof(rm1));
-       rm1.op = OMUL;
-       rm1.left = &n1;
-       rm1.right = &n4;
-       rm1.type = n1.type;
-
-       memset(&rm2, 0, sizeof(rm2));
-       rm2.op = OMUL;
-       rm2.left = &n2;
-       rm2.right = &n3;
-       rm2.type = n2.type;
-
-       memset(&ra, 0, sizeof(ra));
-       ra.op = OADD;
-       ra.left = &rm1;
-       ra.right = &rm2;
-       ra.type = rm1.type;
-       thearch.cgen(&ra, &n6);
-
-       // tmp ->real part
-       thearch.cgen(&tmp, &n5);
-}
diff --git a/src/cmd/gc/dcl.c b/src/cmd/gc/dcl.c
deleted file mode 100644 (file)
index 9a6c002..0000000
+++ /dev/null
@@ -1,1479 +0,0 @@
-// Copyright 2009 The Go Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style
-// license that can be found in the LICENSE file.
-
-#include       <u.h>
-#include       <libc.h>
-#include       "go.h"
-#include       "y.tab.h"
-
-static void    funcargs(Node*);
-static void    funcargs2(Type*);
-
-static int
-dflag(void)
-{
-       if(!debug['d'])
-               return 0;
-       if(debug['y'])
-               return 1;
-       if(incannedimport)
-               return 0;
-       return 1;
-}
-
-/*
- * declaration stack & operations
- */
-
-static void
-dcopy(Sym *a, Sym *b)
-{
-       a->pkg = b->pkg;
-       a->name = b->name;
-       a->def = b->def;
-       a->block = b->block;
-       a->lastlineno = b->lastlineno;
-}
-
-static Sym*
-push(void)
-{
-       Sym *d;
-
-       d = mal(sizeof(*d));
-       d->lastlineno = lineno;
-       d->link = dclstack;
-       dclstack = d;
-       return d;
-}
-
-static Sym*
-pushdcl(Sym *s)
-{
-       Sym *d;
-
-       d = push();
-       dcopy(d, s);
-       if(dflag())
-               print("\t%L push %S %p\n", lineno, s, s->def);
-       return d;
-}
-
-void
-popdcl(void)
-{
-       Sym *d, *s;
-       int lno;
-
-//     if(dflag())
-//             print("revert\n");
-
-       for(d=dclstack; d!=S; d=d->link) {
-               if(d->name == nil)
-                       break;
-               s = pkglookup(d->name, d->pkg);
-               lno = s->lastlineno;
-               dcopy(s, d);
-               d->lastlineno = lno;
-               if(dflag())
-                       print("\t%L pop %S %p\n", lineno, s, s->def);
-       }
-       if(d == S)
-               fatal("popdcl: no mark");
-       dclstack = d->link;
-       block = d->block;
-}
-
-void
-poptodcl(void)
-{
-       // pop the old marker and push a new one
-       // (cannot reuse the existing one)
-       // because we use the markers to identify blocks
-       // for the goto restriction checks.
-       popdcl();
-       markdcl();
-}
-
-void
-markdcl(void)
-{
-       Sym *d;
-
-       d = push();
-       d->name = nil;          // used as a mark in fifo
-       d->block = block;
-
-       blockgen++;
-       block = blockgen;
-
-//     if(dflag())
-//             print("markdcl\n");
-}
-
-void
-dumpdcl(char *st)
-{
-       Sym *s, *d;
-       int i;
-
-       USED(st);
-
-       i = 0;
-       for(d=dclstack; d!=S; d=d->link) {
-               i++;
-               print("    %.2d %p", i, d);
-               if(d->name == nil) {
-                       print("\n");
-                       continue;
-               }
-               print(" '%s'", d->name);
-               s = pkglookup(d->name, d->pkg);
-               print(" %S\n", s);
-       }
-}
-
-void
-testdclstack(void)
-{
-       Sym *d;
-
-       for(d=dclstack; d!=S; d=d->link) {
-               if(d->name == nil) {
-                       if(nerrors != 0)
-                               errorexit();
-                       yyerror("mark left on the stack");
-                       continue;
-               }
-       }
-}
-
-void
-redeclare(Sym *s, char *where)
-{
-       Strlit *pkgstr;
-       int line1, line2;
-
-       if(s->lastlineno == 0) {
-               pkgstr = s->origpkg ? s->origpkg->path : s->pkg->path;
-               yyerror("%S redeclared %s\n"
-                       "\tprevious declaration during import \"%Z\"",
-                       s, where, pkgstr);
-       } else {
-               line1 = parserline();
-               line2 = s->lastlineno;
-               
-               // When an import and a declaration collide in separate files,
-               // present the import as the "redeclared", because the declaration
-               // is visible where the import is, but not vice versa.
-               // See issue 4510.
-               if(s->def == N) {
-                       line2 = line1;
-                       line1 = s->lastlineno;
-               }
-
-               yyerrorl(line1, "%S redeclared %s\n"
-                       "\tprevious declaration at %L",
-                       s, where, line2);
-       }
-}
-
-static int vargen;
-
-/*
- * declare individual names - var, typ, const
- */
-void
-declare(Node *n, int ctxt)
-{
-       Sym *s;
-       int gen;
-       static int typegen;
-       
-       if(ctxt == PDISCARD)
-               return;
-
-       if(isblank(n))
-               return;
-
-       n->lineno = parserline();
-       s = n->sym;
-
-       // kludgy: typecheckok means we're past parsing.  Eg genwrapper may declare out of package names later.
-       if(importpkg == nil && !typecheckok && s->pkg != localpkg)
-               yyerror("cannot declare name %S", s);
-
-       if(ctxt == PEXTERN && strcmp(s->name, "init") == 0)
-               yyerror("cannot declare init - must be func", s);
-
-       gen = 0;
-       if(ctxt == PEXTERN) {
-               externdcl = list(externdcl, n);
-               if(dflag())
-                       print("\t%L global decl %S %p\n", lineno, s, n);
-       } else {
-               if(curfn == nil && ctxt == PAUTO)
-                       fatal("automatic outside function");
-               if(curfn != nil)
-                       curfn->dcl = list(curfn->dcl, n);
-               if(n->op == OTYPE)
-                       gen = ++typegen;
-               else if(n->op == ONAME && ctxt == PAUTO && strstr(s->name, "·") == nil)
-                       gen = ++vargen;
-               pushdcl(s);
-               n->curfn = curfn;
-       }
-       if(ctxt == PAUTO)
-               n->xoffset = 0;
-
-       if(s->block == block) {
-               // functype will print errors about duplicate function arguments.
-               // Don't repeat the error here.
-               if(ctxt != PPARAM && ctxt != PPARAMOUT)
-                       redeclare(s, "in this block");
-       }
-
-       s->block = block;
-       s->lastlineno = parserline();
-       s->def = n;
-       n->vargen = gen;
-       n->funcdepth = funcdepth;
-       n->class = ctxt;
-
-       autoexport(n, ctxt);
-}
-
-void
-addvar(Node *n, Type *t, int ctxt)
-{
-       if(n==N || n->sym == S || (n->op != ONAME && n->op != ONONAME) || t == T)
-               fatal("addvar: n=%N t=%T nil", n, t);
-
-       n->op = ONAME;
-       declare(n, ctxt);
-       n->type = t;
-}
-
-/*
- * declare variables from grammar
- * new_name_list (type | [type] = expr_list)
- */
-NodeList*
-variter(NodeList *vl, Node *t, NodeList *el)
-{
-       int doexpr;
-       Node *v, *e, *as2;
-       NodeList *init;
-
-       init = nil;
-       doexpr = el != nil;
-
-       if(count(el) == 1 && count(vl) > 1) {
-               e = el->n;
-               as2 = nod(OAS2, N, N);
-               as2->list = vl;
-               as2->rlist = list1(e);
-               for(; vl; vl=vl->next) {
-                       v = vl->n;
-                       v->op = ONAME;
-                       declare(v, dclcontext);
-                       v->ntype = t;
-                       v->defn = as2;
-                       if(funcdepth > 0)
-                               init = list(init, nod(ODCL, v, N));
-               }
-               return list(init, as2);
-       }
-       
-       for(; vl; vl=vl->next) {
-               if(doexpr) {
-                       if(el == nil) {
-                               yyerror("missing expression in var declaration");
-                               break;
-                       }
-                       e = el->n;
-                       el = el->next;
-               } else
-                       e = N;
-
-               v = vl->n;
-               v->op = ONAME;
-               declare(v, dclcontext);
-               v->ntype = t;
-
-               if(e != N || funcdepth > 0 || isblank(v)) {
-                       if(funcdepth > 0)
-                               init = list(init, nod(ODCL, v, N));
-                       e = nod(OAS, v, e);
-                       init = list(init, e);
-                       if(e->right != N)
-                               v->defn = e;
-               }
-       }
-       if(el != nil)
-               yyerror("extra expression in var declaration");
-       return init;
-}
-
-/*
- * declare constants from grammar
- * new_name_list [[type] = expr_list]
- */
-NodeList*
-constiter(NodeList *vl, Node *t, NodeList *cl)
-{
-       Node *v, *c;
-       NodeList *vv;
-
-       vv = nil;
-       if(cl == nil) {
-               if(t != N)
-                       yyerror("const declaration cannot have type without expression");
-               cl = lastconst;
-               t = lasttype;
-       } else {
-               lastconst = cl;
-               lasttype = t;
-       }
-       cl = listtreecopy(cl);
-
-       for(; vl; vl=vl->next) {
-               if(cl == nil) {
-                       yyerror("missing value in const declaration");
-                       break;
-               }
-               c = cl->n;
-               cl = cl->next;
-
-               v = vl->n;
-               v->op = OLITERAL;
-               declare(v, dclcontext);
-
-               v->ntype = t;
-               v->defn = c;
-
-               vv = list(vv, nod(ODCLCONST, v, N));
-       }
-       if(cl != nil)
-               yyerror("extra expression in const declaration");
-       iota += 1;
-       return vv;
-}
-
-/*
- * this generates a new name node,
- * typically for labels or other one-off names.
- */
-Node*
-newname(Sym *s)
-{
-       Node *n;
-
-       if(s == S)
-               fatal("newname nil");
-
-       n = nod(ONAME, N, N);
-       n->sym = s;
-       n->type = T;
-       n->addable = 1;
-       n->ullman = 1;
-       n->xoffset = 0;
-       return n;
-}
-
-/*
- * this generates a new name node for a name
- * being declared.
- */
-Node*
-dclname(Sym *s)
-{
-       Node *n;
-
-       n = newname(s);
-       n->op = ONONAME;        // caller will correct it
-       return n;
-}
-
-Node*
-typenod(Type *t)
-{
-       // if we copied another type with *t = *u
-       // then t->nod might be out of date, so
-       // check t->nod->type too
-       if(t->nod == N || t->nod->type != t) {
-               t->nod = nod(OTYPE, N, N);
-               t->nod->type = t;
-               t->nod->sym = t->sym;
-       }
-       return t->nod;
-}
-
-
-/*
- * this will return an old name
- * that has already been pushed on the
- * declaration list. a diagnostic is
- * generated if no name has been defined.
- */
-Node*
-oldname(Sym *s)
-{
-       Node *n;
-       Node *c;
-
-       n = s->def;
-       if(n == N) {
-               // maybe a top-level name will come along
-               // to give this a definition later.
-               // walkdef will check s->def again once
-               // all the input source has been processed.
-               n = newname(s);
-               n->op = ONONAME;
-               n->iota = iota; // save current iota value in const declarations
-       }
-       if(curfn != nil && n->funcdepth > 0 && n->funcdepth != funcdepth && n->op == ONAME) {
-               // inner func is referring to var in outer func.
-               //
-               // TODO(rsc): If there is an outer variable x and we
-               // are parsing x := 5 inside the closure, until we get to
-               // the := it looks like a reference to the outer x so we'll
-               // make x a closure variable unnecessarily.
-               if(n->closure == N || n->closure->funcdepth != funcdepth) {
-                       // create new closure var.
-                       c = nod(ONAME, N, N);
-                       c->sym = s;
-                       c->class = PPARAMREF;
-                       c->isddd = n->isddd;
-                       c->defn = n;
-                       c->addable = 0;
-                       c->ullman = 2;
-                       c->funcdepth = funcdepth;
-                       c->outer = n->closure;
-                       n->closure = c;
-                       c->closure = n;
-                       c->xoffset = 0;
-                       curfn->cvars = list(curfn->cvars, c);
-               }
-               // return ref to closure var, not original
-               return n->closure;
-       }
-       return n;
-}
-
-/*
- * := declarations
- */
-
-static int
-colasname(Node *n)
-{
-       switch(n->op) {
-       case ONAME:
-       case ONONAME:
-       case OPACK:
-       case OTYPE:
-       case OLITERAL:
-               return n->sym != S;
-       }
-       return 0;
-}
-
-void
-colasdefn(NodeList *left, Node *defn)
-{
-       int nnew, nerr;
-       NodeList *l;
-       Node *n;
-
-       for(l=left; l; l=l->next)
-               if(l->n->sym != S)
-                       l->n->sym->flags |= SymUniq;
-
-       nnew = 0;
-       nerr = 0;
-       for(l=left; l; l=l->next) {
-               n = l->n;
-               if(isblank(n))
-                       continue;
-               if(!colasname(n)) {
-                       yyerrorl(defn->lineno, "non-name %N on left side of :=", n);
-                       nerr++;
-                       continue;
-               }
-               if((n->sym->flags & SymUniq) == 0) {
-                       yyerrorl(defn->lineno, "%S repeated on left side of :=", n->sym);
-                       n->diag++;
-                       nerr++;
-                       continue;
-               }
-               n->sym->flags &= ~SymUniq;
-               if(n->sym->block == block)
-                       continue;
-
-               nnew++;
-               n = newname(n->sym);
-               declare(n, dclcontext);
-               n->defn = defn;
-               defn->ninit = list(defn->ninit, nod(ODCL, n, N));
-               l->n = n;
-       }
-       if(nnew == 0 && nerr == 0)
-               yyerrorl(defn->lineno, "no new variables on left side of :=");
-}
-
-Node*
-colas(NodeList *left, NodeList *right, int32 lno)
-{
-       Node *as;
-
-       as = nod(OAS2, N, N);
-       as->list = left;
-       as->rlist = right;
-       as->colas = 1;
-       as->lineno = lno;
-       colasdefn(left, as);
-
-       // make the tree prettier; not necessary
-       if(count(left) == 1 && count(right) == 1) {
-               as->left = as->list->n;
-               as->right = as->rlist->n;
-               as->list = nil;
-               as->rlist = nil;
-               as->op = OAS;
-       }
-
-       return as;
-}
-
-/*
- * declare the arguments in an
- * interface field declaration.
- */
-void
-ifacedcl(Node *n)
-{
-       if(n->op != ODCLFIELD || n->right == N)
-               fatal("ifacedcl");
-
-       if(isblank(n->left))
-               yyerror("methods must have a unique non-blank name");
-
-       dclcontext = PPARAM;
-       markdcl();
-       funcdepth++;
-       n->outer = curfn;
-       curfn = n;
-       funcargs(n->right);
-
-       // funcbody is normally called after the parser has
-       // seen the body of a function but since an interface
-       // field declaration does not have a body, we must
-       // call it now to pop the current declaration context.
-       dclcontext = PAUTO;
-       funcbody(n);
-}
-
-/*
- * declare the function proper
- * and declare the arguments.
- * called in extern-declaration context
- * returns in auto-declaration context.
- */
-void
-funchdr(Node *n)
-{
-       // change the declaration context from extern to auto
-       if(funcdepth == 0 && dclcontext != PEXTERN)
-               fatal("funchdr: dclcontext");
-
-       dclcontext = PAUTO;
-       markdcl();
-       funcdepth++;
-
-       n->outer = curfn;
-       curfn = n;
-
-       if(n->nname)
-               funcargs(n->nname->ntype);
-       else if (n->ntype)
-               funcargs(n->ntype);
-       else
-               funcargs2(n->type);
-}
-
-static void
-funcargs(Node *nt)
-{
-       Node *n, *nn;
-       NodeList *l;
-       int gen;
-
-       if(nt->op != OTFUNC)
-               fatal("funcargs %O", nt->op);
-
-       // re-start the variable generation number
-       // we want to use small numbers for the return variables,
-       // so let them have the chunk starting at 1.
-       vargen = count(nt->rlist);
-
-       // declare the receiver and in arguments.
-       // no n->defn because type checking of func header
-       // will not fill in the types until later
-       if(nt->left != N) {
-               n = nt->left;
-               if(n->op != ODCLFIELD)
-                       fatal("funcargs receiver %O", n->op);
-               if(n->left != N) {
-                       n->left->op = ONAME;
-                       n->left->ntype = n->right;
-                       declare(n->left, PPARAM);
-                       if(dclcontext == PAUTO)
-                               n->left->vargen = ++vargen;
-               }
-       }
-       for(l=nt->list; l; l=l->next) {
-               n = l->n;
-               if(n->op != ODCLFIELD)
-                       fatal("funcargs in %O", n->op);
-               if(n->left != N) {
-                       n->left->op = ONAME;
-                       n->left->ntype = n->right;
-                       declare(n->left, PPARAM);
-                       if(dclcontext == PAUTO)
-                               n->left->vargen = ++vargen;
-               }
-       }
-
-       // declare the out arguments.
-       gen = count(nt->list);
-       int i = 0;
-       for(l=nt->rlist; l; l=l->next) {
-               n = l->n;
-
-               if(n->op != ODCLFIELD)
-                       fatal("funcargs out %O", n->op);
-
-               if(n->left == N) {
-                       // Name so that escape analysis can track it. ~r stands for 'result'.
-                       snprint(namebuf, sizeof(namebuf), "~r%d", gen++);
-                       n->left = newname(lookup(namebuf));
-                       // TODO: n->left->missing = 1;
-               } 
-
-               n->left->op = ONAME;
-
-               if(isblank(n->left)) {
-                       // Give it a name so we can assign to it during return. ~b stands for 'blank'.
-                       // The name must be different from ~r above because if you have
-                       //      func f() (_ int)
-                       //      func g() int
-                       // f is allowed to use a plain 'return' with no arguments, while g is not.
-                       // So the two cases must be distinguished.
-                       // We do not record a pointer to the original node (n->orig).
-                       // Having multiple names causes too much confusion in later passes.
-                       nn = nod(OXXX, N, N);
-                       *nn = *n->left;
-                       nn->orig = nn;
-                       snprint(namebuf, sizeof(namebuf), "~b%d", gen++);
-                       nn->sym = lookup(namebuf);
-                       n->left = nn;
-               }
-
-               n->left->ntype = n->right;
-               declare(n->left, PPARAMOUT);
-               if(dclcontext == PAUTO)
-                       n->left->vargen = ++i;
-       }
-}
-
-/*
- * Same as funcargs, except run over an already constructed TFUNC.
- * This happens during import, where the hidden_fndcl rule has
- * used functype directly to parse the function's type.
- */
-static void
-funcargs2(Type *t)
-{
-       Type *ft;
-       Node *n;
-
-       if(t->etype != TFUNC)
-               fatal("funcargs2 %T", t);
-       
-       if(t->thistuple)
-               for(ft=getthisx(t)->type; ft; ft=ft->down) {
-                       if(!ft->nname || !ft->nname->sym)
-                               continue;
-                       n = ft->nname;  // no need for newname(ft->nname->sym)
-                       n->type = ft->type;
-                       declare(n, PPARAM);
-               }
-
-       if(t->intuple)
-               for(ft=getinargx(t)->type; ft; ft=ft->down) {
-                       if(!ft->nname || !ft->nname->sym)
-                               continue;
-                       n = ft->nname;
-                       n->type = ft->type;
-                       declare(n, PPARAM);
-               }
-
-       if(t->outtuple)
-               for(ft=getoutargx(t)->type; ft; ft=ft->down) {
-                       if(!ft->nname || !ft->nname->sym)
-                               continue;
-                       n = ft->nname;
-                       n->type = ft->type;
-                       declare(n, PPARAMOUT);
-               }
-}
-
-/*
- * finish the body.
- * called in auto-declaration context.
- * returns in extern-declaration context.
- */
-void
-funcbody(Node *n)
-{
-       // change the declaration context from auto to extern
-       if(dclcontext != PAUTO)
-               fatal("funcbody: dclcontext");
-       popdcl();
-       funcdepth--;
-       curfn = n->outer;
-       n->outer = N;
-       if(funcdepth == 0)
-               dclcontext = PEXTERN;
-}
-
-/*
- * new type being defined with name s.
- */
-Node*
-typedcl0(Sym *s)
-{
-       Node *n;
-
-       n = newname(s);
-       n->op = OTYPE;
-       declare(n, dclcontext);
-       return n;
-}
-
-/*
- * node n, which was returned by typedcl0
- * is being declared to have uncompiled type t.
- * return the ODCLTYPE node to use.
- */
-Node*
-typedcl1(Node *n, Node *t, int local)
-{
-       n->ntype = t;
-       n->local = local;
-       return nod(ODCLTYPE, n, N);
-}
-
-/*
- * structs, functions, and methods.
- * they don't belong here, but where do they belong?
- */
-
-static void
-checkembeddedtype(Type *t)
-{
-       if (t == T)
-               return;
-
-       if(t->sym == S && isptr[t->etype]) {
-               t = t->type;
-               if(t->etype == TINTER)
-                       yyerror("embedded type cannot be a pointer to interface");
-       }
-       if(isptr[t->etype])
-               yyerror("embedded type cannot be a pointer");
-       else if(t->etype == TFORW && t->embedlineno == 0)
-               t->embedlineno = lineno;
-}
-
-static Type*
-structfield(Node *n)
-{
-       Type *f;
-       int lno;
-
-       lno = lineno;
-       lineno = n->lineno;
-
-       if(n->op != ODCLFIELD)
-               fatal("structfield: oops %N\n", n);
-
-       f = typ(TFIELD);
-       f->isddd = n->isddd;
-
-       if(n->right != N) {
-               typecheck(&n->right, Etype);
-               n->type = n->right->type;
-               if(n->left != N)
-                       n->left->type = n->type;
-               if(n->embedded)
-                       checkembeddedtype(n->type);
-       }
-       n->right = N;
-               
-       f->type = n->type;
-       if(f->type == T)
-               f->broke = 1;
-
-       switch(n->val.ctype) {
-       case CTSTR:
-               f->note = n->val.u.sval;
-               break;
-       default:
-               yyerror("field annotation must be string");
-               // fallthrough
-       case CTxxx:
-               f->note = nil;
-               break;
-       }
-
-       if(n->left && n->left->op == ONAME) {
-               f->nname = n->left;
-               f->embedded = n->embedded;
-               f->sym = f->nname->sym;
-       }
-
-       lineno = lno;
-       return f;
-}
-
-static uint32 uniqgen;
-
-static void
-checkdupfields(Type *t, char* what)
-{
-       int lno;
-
-       lno = lineno;
-
-       for( ; t; t=t->down) {
-               if(t->sym && t->nname && !isblank(t->nname)) {
-                       if(t->sym->uniqgen == uniqgen) {
-                               lineno = t->nname->lineno;
-                               yyerror("duplicate %s %s", what, t->sym->name);
-                       } else
-                               t->sym->uniqgen = uniqgen;
-               }
-       }
-
-       lineno = lno;
-}
-
-/*
- * convert a parsed id/type list into
- * a type for struct/interface/arglist
- */
-Type*
-tostruct(NodeList *l)
-{
-       Type *t, *f, **tp;
-       t = typ(TSTRUCT);
-
-       for(tp = &t->type; l; l=l->next) {
-               f = structfield(l->n);
-
-               *tp = f;
-               tp = &f->down;
-       }
-
-       for(f=t->type; f && !t->broke; f=f->down)
-               if(f->broke)
-                       t->broke = 1;
-
-       uniqgen++;
-       checkdupfields(t->type, "field");
-
-       if (!t->broke)
-               checkwidth(t);
-
-       return t;
-}
-
-static Type*
-tofunargs(NodeList *l)
-{
-       Type *t, *f, **tp;
-
-       t = typ(TSTRUCT);
-       t->funarg = 1;
-
-       for(tp = &t->type; l; l=l->next) {
-               f = structfield(l->n);
-               f->funarg = 1;
-
-               // esc.c needs to find f given a PPARAM to add the tag.
-               if(l->n->left && l->n->left->class == PPARAM)
-                       l->n->left->paramfld = f;
-
-               *tp = f;
-               tp = &f->down;
-       }
-
-       for(f=t->type; f && !t->broke; f=f->down)
-               if(f->broke)
-                       t->broke = 1;
-
-       return t;
-}
-
-static Type*
-interfacefield(Node *n)
-{
-       Type *f;
-       int lno;
-
-       lno = lineno;
-       lineno = n->lineno;
-
-       if(n->op != ODCLFIELD)
-               fatal("interfacefield: oops %N\n", n);
-
-       if (n->val.ctype != CTxxx)
-               yyerror("interface method cannot have annotation");
-
-       f = typ(TFIELD);
-       f->isddd = n->isddd;
-       
-       if(n->right != N) {
-               if(n->left != N) {
-                       // queue resolution of method type for later.
-                       // right now all we need is the name list.
-                       // avoids cycles for recursive interface types.
-                       n->type = typ(TINTERMETH);
-                       n->type->nname = n->right;
-                       n->left->type = n->type;
-                       queuemethod(n);
-
-                       if(n->left->op == ONAME) {
-                               f->nname = n->left;
-                               f->embedded = n->embedded;
-                               f->sym = f->nname->sym;
-                       }
-
-               } else {
-
-                       typecheck(&n->right, Etype);
-                       n->type = n->right->type;
-
-                       if(n->embedded)
-                               checkembeddedtype(n->type);
-
-                       if(n->type)
-                               switch(n->type->etype) {
-                               case TINTER:
-                                       break;
-                               case TFORW:
-                                       yyerror("interface type loop involving %T", n->type);
-                                       f->broke = 1;
-                                       break;
-                               default:
-                                       yyerror("interface contains embedded non-interface %T", n->type);
-                                       f->broke = 1;
-                                       break;
-                               }
-               }
-       }
-
-       n->right = N;
-       
-       f->type = n->type;
-       if(f->type == T)
-               f->broke = 1;
-       
-       lineno = lno;
-       return f;
-}
-
-Type*
-tointerface(NodeList *l)
-{
-       Type *t, *f, **tp, *t1;
-
-       t = typ(TINTER);
-
-       tp = &t->type;
-       for(; l; l=l->next) {
-               f = interfacefield(l->n);
-
-               if (l->n->left == N && f->type->etype == TINTER) {
-                       // embedded interface, inline methods
-                       for(t1=f->type->type; t1; t1=t1->down) {
-                               f = typ(TFIELD);
-                               f->type = t1->type;
-                               f->broke = t1->broke;
-                               f->sym = t1->sym;
-                               if(f->sym)
-                                       f->nname = newname(f->sym);
-                               *tp = f;
-                               tp = &f->down;
-                       }
-               } else {
-                       *tp = f;
-                       tp = &f->down;
-               }
-       }
-
-       for(f=t->type; f && !t->broke; f=f->down)
-               if(f->broke)
-                       t->broke = 1;
-
-       uniqgen++;
-       checkdupfields(t->type, "method");
-       t = sortinter(t);
-       checkwidth(t);
-
-       return t;
-}
-
-Node*
-embedded(Sym *s, Pkg *pkg)
-{
-       Node *n;
-       char *name;
-
-       // Names sometimes have disambiguation junk
-       // appended after a center dot.  Discard it when
-       // making the name for the embedded struct field.
-       enum { CenterDot = 0xB7 };
-       name = s->name;
-       if(utfrune(s->name, CenterDot)) {
-               name = strdup(s->name);
-               *utfrune(name, CenterDot) = 0;
-       }
-
-       if(exportname(name))
-               n = newname(lookup(name));
-       else if(s->pkg == builtinpkg)
-               // The name of embedded builtins belongs to pkg.
-               n = newname(pkglookup(name, pkg));
-       else
-               n = newname(pkglookup(name, s->pkg));
-       n = nod(ODCLFIELD, n, oldname(s));
-       n->embedded = 1;
-       return n;
-}
-
-/*
- * check that the list of declarations is either all anonymous or all named
- */
-
-static Node*
-findtype(NodeList *l)
-{
-       for(; l; l=l->next)
-               if(l->n->op == OKEY)
-                       return l->n->right;
-       return N;
-}
-
-NodeList*
-checkarglist(NodeList *all, int input)
-{
-       int named;
-       Node *n, *t, *nextt;
-       NodeList *l;
-
-       named = 0;
-       for(l=all; l; l=l->next) {
-               if(l->n->op == OKEY) {
-                       named = 1;
-                       break;
-               }
-       }
-       if(named) {
-               n = N;
-               for(l=all; l; l=l->next) {
-                       n = l->n;
-                       if(n->op != OKEY && n->sym == S) {
-                               yyerror("mixed named and unnamed function parameters");
-                               break;
-                       }
-               }
-               if(l == nil && n != N && n->op != OKEY)
-                       yyerror("final function parameter must have type");
-       }
-
-       nextt = nil;
-       for(l=all; l; l=l->next) {
-               // can cache result from findtype to avoid
-               // quadratic behavior here, but unlikely to matter.
-               n = l->n;
-               if(named) {
-                       if(n->op == OKEY) {
-                               t = n->right;
-                               n = n->left;
-                               nextt = nil;
-                       } else {
-                               if(nextt == nil)
-                                       nextt = findtype(l);
-                               t = nextt;
-                       }
-               } else {
-                       t = n;
-                       n = N;
-               }
-
-               // during import l->n->op is OKEY, but l->n->left->sym == S
-               // means it was a '?', not that it was
-               // a lone type This doesn't matter for the exported
-               // declarations, which are parsed by rules that don't
-               // use checkargs, but can happen for func literals in
-               // the inline bodies.
-               // TODO(rsc) this can go when typefmt case TFIELD in exportmode fmt.c prints _ instead of ?
-               if(importpkg && n->sym == S)
-                       n = N;
-
-               if(n != N && n->sym == S) {
-                       t = n;
-                       n = N;
-               }
-               if(n != N)
-                       n = newname(n->sym);
-               n = nod(ODCLFIELD, n, t);
-               if(n->right != N && n->right->op == ODDD) {
-                       if(!input)
-                               yyerror("cannot use ... in output argument list");
-                       else if(l->next != nil)
-                               yyerror("can only use ... as final argument in list");
-                       n->right->op = OTARRAY;
-                       n->right->right = n->right->left;
-                       n->right->left = N;
-                       n->isddd = 1;
-                       if(n->left != N)
-                               n->left->isddd = 1;
-               }
-               l->n = n;
-       }
-       return all;
-}
-
-
-Node*
-fakethis(void)
-{
-       Node *n;
-
-       n = nod(ODCLFIELD, N, typenod(ptrto(typ(TSTRUCT))));
-       return n;
-}
-
-/*
- * Is this field a method on an interface?
- * Those methods have an anonymous
- * *struct{} as the receiver.
- * (See fakethis above.)
- */
-int
-isifacemethod(Type *f)
-{
-       Type *rcvr;
-       Type *t;
-
-       rcvr = getthisx(f)->type;
-       if(rcvr->sym != S)
-               return 0;
-       t = rcvr->type;
-       if(!isptr[t->etype])
-               return 0;
-       t = t->type;
-       if(t->sym != S || t->etype != TSTRUCT || t->type != T)
-               return 0;
-       return 1;
-}
-
-/*
- * turn a parsed function declaration
- * into a type
- */
-Type*
-functype(Node *this, NodeList *in, NodeList *out)
-{
-       Type *t;
-       NodeList *rcvr;
-       Sym *s;
-
-       t = typ(TFUNC);
-
-       rcvr = nil;
-       if(this)
-               rcvr = list1(this);
-       t->type = tofunargs(rcvr);
-       t->type->down = tofunargs(out);
-       t->type->down->down = tofunargs(in);
-
-       uniqgen++;
-       checkdupfields(t->type->type, "argument");
-       checkdupfields(t->type->down->type, "argument");
-       checkdupfields(t->type->down->down->type, "argument");
-
-       if (t->type->broke || t->type->down->broke || t->type->down->down->broke)
-               t->broke = 1;
-
-       if(this)
-               t->thistuple = 1;
-       t->outtuple = count(out);
-       t->intuple = count(in);
-       t->outnamed = 0;
-       if(t->outtuple > 0 && out->n->left != N && out->n->left->orig != N) {
-               s = out->n->left->orig->sym;
-               if(s != S && (s->name[0] != '~' || s->name[1] != 'r')) // ~r%d is the name invented for an unnamed result
-                       t->outnamed = 1;
-       }
-
-       return t;
-}
-
-Sym*
-methodsym(Sym *nsym, Type *t0, int iface)
-{
-       Sym *s;
-       char *p;
-       Type *t;
-       char *suffix;
-       Pkg *spkg;
-       static Pkg *toppkg;
-
-       t = t0;
-       if(t == T)
-               goto bad;
-       s = t->sym;
-       if(s == S && isptr[t->etype]) {
-               t = t->type;
-               if(t == T)
-                       goto bad;
-               s = t->sym;
-       }
-       spkg = nil;
-       if(s != S)
-               spkg = s->pkg;
-
-       // if t0 == *t and t0 has a sym,
-       // we want to see *t, not t0, in the method name.
-       if(t != t0 && t0->sym)
-               t0 = ptrto(t);
-
-       suffix = "";
-       if(iface) {
-               dowidth(t0);
-               if(t0->width < types[tptr]->width)
-                       suffix = "·i";
-       }
-       if((spkg == nil || nsym->pkg != spkg) && !exportname(nsym->name)) {
-               if(t0->sym == S && isptr[t0->etype])
-                       p = smprint("(%-hT).%s.%s%s", t0, nsym->pkg->prefix, nsym->name, suffix);
-               else
-                       p = smprint("%-hT.%s.%s%s", t0, nsym->pkg->prefix, nsym->name, suffix);
-       } else {
-               if(t0->sym == S && isptr[t0->etype])
-                       p = smprint("(%-hT).%s%s", t0, nsym->name, suffix);
-               else
-                       p = smprint("%-hT.%s%s", t0, nsym->name, suffix);
-       }
-       if(spkg == nil) {
-               if(toppkg == nil)
-                       toppkg = mkpkg(newstrlit("go"));
-               spkg = toppkg;
-       }
-       s = pkglookup(p, spkg);
-       free(p);
-       return s;
-
-bad:
-       yyerror("illegal receiver type: %T", t0);
-       return S;
-}
-
-Node*
-methodname(Node *n, Type *t)
-{
-       Sym *s;
-
-       s = methodsym(n->sym, t, 0);
-       if(s == S)
-               return n;
-       return newname(s);
-}
-
-Node*
-methodname1(Node *n, Node *t)
-{
-       char *star;
-       char *p;
-
-       star = nil;
-       if(t->op == OIND) {
-               star = "*";
-               t = t->left;
-       }
-       if(t->sym == S || isblank(n))
-               return newname(n->sym);
-
-       if(star)
-               p = smprint("(%s%S).%S", star, t->sym, n->sym);
-       else
-               p = smprint("%S.%S", t->sym, n->sym);
-
-       if(exportname(t->sym->name))
-               n = newname(lookup(p));
-       else
-               n = newname(pkglookup(p, t->sym->pkg));
-       free(p);
-       return n;
-}
-
-/*
- * add a method, declared as a function,
- * n is fieldname, pa is base type, t is function type
- */
-void
-addmethod(Sym *sf, Type *t, int local, int nointerface)
-{
-       Type *f, *d, *pa;
-       Node *n;
-
-       // get field sym
-       if(sf == S)
-               fatal("no method symbol");
-
-       // get parent type sym
-       pa = getthisx(t)->type; // ptr to this structure
-       if(pa == T) {
-               yyerror("missing receiver");
-               return;
-       }
-
-       pa = pa->type;
-       f = methtype(pa, 1);
-       if(f == T) {
-               t = pa;
-               if(t == T) // rely on typecheck having complained before
-                       return;
-               if(t != T) {
-                       if(isptr[t->etype]) {
-                               if(t->sym != S) {
-                                       yyerror("invalid receiver type %T (%T is a pointer type)", pa, t);
-                                       return;
-                               }
-                               t = t->type;
-                       }
-                       if(t->broke) // rely on typecheck having complained before
-                               return;
-                       if(t->sym == S) {
-                               yyerror("invalid receiver type %T (%T is an unnamed type)", pa, t);
-                               return;
-                       }
-                       if(isptr[t->etype]) {
-                               yyerror("invalid receiver type %T (%T is a pointer type)", pa, t);
-                               return;
-                       }
-                       if(t->etype == TINTER) {
-                               yyerror("invalid receiver type %T (%T is an interface type)", pa, t);
-                               return;
-                       }
-               }
-               // Should have picked off all the reasons above,
-               // but just in case, fall back to generic error.
-               yyerror("invalid receiver type %T (%lT / %lT)", pa, pa, t);
-               return;
-       }
-
-       pa = f;
-       if(pa->etype == TSTRUCT) {
-               for(f=pa->type; f; f=f->down) {
-                       if(f->sym == sf) {
-                               yyerror("type %T has both field and method named %S", pa, sf);
-                               return;
-                       }
-               }
-       }
-
-       if(local && !pa->local) {
-               // defining method on non-local type.
-               yyerror("cannot define new methods on non-local type %T", pa);
-               return;
-       }
-
-       n = nod(ODCLFIELD, newname(sf), N);
-       n->type = t;
-
-       d = T;  // last found
-       for(f=pa->method; f!=T; f=f->down) {
-               d = f;
-               if(f->etype != TFIELD)
-                       fatal("addmethod: not TFIELD: %lT", f);
-               if(strcmp(sf->name, f->sym->name) != 0)
-                       continue;
-               if(!eqtype(t, f->type))
-                       yyerror("method redeclared: %T.%S\n\t%T\n\t%T", pa, sf, f->type, t);
-               return;
-       }
-
-       f = structfield(n);
-       f->nointerface = nointerface;
-
-       // during import unexported method names should be in the type's package
-       if(importpkg && f->sym && !exportname(f->sym->name) && f->sym->pkg != structpkg)
-               fatal("imported method name %+S in wrong package %s\n", f->sym, structpkg->name);
-
-       if(d == T)
-               pa->method = f;
-       else
-               d->down = f;
-       return;
-}
-
-void
-funccompile(Node *n)
-{
-       stksize = BADWIDTH;
-       maxarg = 0;
-
-       if(n->type == T) {
-               if(nerrors == 0)
-                       fatal("funccompile missing type");
-               return;
-       }
-
-       // assign parameter offsets
-       checkwidth(n->type);
-       
-       if(curfn)
-               fatal("funccompile %S inside %S", n->nname->sym, curfn->nname->sym);
-
-       stksize = 0;
-       dclcontext = PAUTO;
-       funcdepth = n->funcdepth + 1;
-       compile(n);
-       curfn = nil;
-       funcdepth = 0;
-       dclcontext = PEXTERN;
-}
-
-Sym*
-funcsym(Sym *s)
-{
-       char *p;
-       Sym *s1;
-       
-       p = smprint("%s·f", s->name);
-       s1 = pkglookup(p, s->pkg);
-       free(p);
-       if(s1->def == N) {
-               s1->def = newname(s1);
-               s1->def->shortname = newname(s);
-               funcsyms = list(funcsyms, s1->def);
-       }
-       return s1;
-}
diff --git a/src/cmd/gc/doc.go b/src/cmd/gc/doc.go
deleted file mode 100644 (file)
index 03df93a..0000000
+++ /dev/null
@@ -1,95 +0,0 @@
-// Copyright 2009 The Go Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style
-// license that can be found in the LICENSE file.
-
-// +build ignore
-
-/*
-
-Gc is the generic label for the family of Go compilers
-that function as part of the (modified) Plan 9 tool chain.  The C compiler
-documentation at
-
-       http://plan9.bell-labs.com/sys/doc/comp.pdf     (Tools overview)
-       http://plan9.bell-labs.com/sys/doc/compiler.pdf (C compiler architecture)
-
-gives the overall design of the tool chain.  Aside from a few adapted pieces,
-such as the optimizer, the Go compilers are wholly new programs.
-
-The compiler reads in a set of Go files, typically suffixed ".go".  They
-must all be part of one package.  The output is a single intermediate file
-representing the "binary assembly" of the compiled package, ready as input
-for the linker (6l, etc.).
-
-The generated files contain type information about the symbols exported by
-the package and about types used by symbols imported by the package from
-other packages. It is therefore not necessary when compiling client C of
-package P to read the files of P's dependencies, only the compiled output
-of P.
-
-Command Line
-
-Usage:
-       go tool 6g [flags] file...
-The specified files must be Go source files and all part of the same package.
-Substitute 6g with 8g or 5g where appropriate.
-
-Flags:
-       -o file
-               output file, default file.6 for 6g, etc.
-       -pack
-               write an archive file rather than an object file
-       -e
-               normally the compiler quits after 10 errors; -e prints all errors
-       -p path
-               assume that path is the eventual import path for this code,
-               and diagnose any attempt to import a package that depends on it.
-       -D path
-               treat a relative import as relative to path
-       -L
-               show entire file path when printing line numbers in errors
-       -I dir1 -I dir2
-               add dir1 and dir2 to the list of paths to check for imported packages
-       -N
-               disable optimizations
-       -nolocalimports
-               disallow local (relative) imports
-       -S
-               write assembly language text to standard output (code only)
-       -S -S
-               write assembly language text to standard output (code and data)
-       -u
-               disallow importing packages not marked as safe; implies -nolocalimports
-       -V
-               print the compiler version
-       -race
-               compile with race detection enabled
-
-There are also a number of debugging flags; run the command with no arguments
-to get a usage message.
-
-Compiler Directives
-
-The compiler accepts two compiler directives in the form of // comments at the
-beginning of a line. To distinguish them from non-directive comments, the directives
-require no space between the slashes and the name of the directive. However, since
-they are comments, tools unaware of the directive convention or of a particular
-directive can skip over a directive like any other comment.
-
-    //line path/to/file:linenumber
-
-The //line directive specifies that the source line that follows should be recorded
-as having come from the given file path and line number. Successive lines are
-recorded using increasing line numbers, until the next directive. This directive
-typically appears in machine-generated code, so that compilers and debuggers
-will show lines in the original input to the generator.
-
-    //go:noescape
-
-The //go:noescape directive specifies that the next declaration in the file, which
-must be a func without a body (meaning that it has an implementation not written
-in Go) does not allow any of the pointers passed as arguments to escape into the
-heap or into the values returned from the function. This information can be used as
-during the compiler's escape analysis of Go code calling the function.
-*/
-package main
diff --git a/src/cmd/gc/esc.c b/src/cmd/gc/esc.c
deleted file mode 100644 (file)
index 5b09c0b..0000000
+++ /dev/null
@@ -1,1342 +0,0 @@
-// Copyright 2011 The Go Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style
-// license that can be found in the LICENSE file.
-
-// Escape analysis.
-
-#include <u.h>
-#include <libc.h>
-#include "go.h"
-
-// Run analysis on minimal sets of mutually recursive functions
-// or single non-recursive functions, bottom up.
-//
-// Finding these sets is finding strongly connected components
-// in the static call graph.  The algorithm for doing that is taken
-// from Sedgewick, Algorithms, Second Edition, p. 482, with two
-// adaptations.
-//
-// First, a hidden closure function (n->curfn != N) cannot be the
-// root of a connected component. Refusing to use it as a root
-// forces it into the component of the function in which it appears.
-// The analysis assumes that closures and the functions in which they
-// appear are analyzed together, so that the aliasing between their
-// variables can be modeled more precisely.
-//
-// Second, each function becomes two virtual nodes in the graph,
-// with numbers n and n+1. We record the function's node number as n
-// but search from node n+1. If the search tells us that the component
-// number (min) is n+1, we know that this is a trivial component: one function
-// plus its closures. If the search tells us that the component number is
-// n, then there was a path from node n+1 back to node n, meaning that
-// the function set is mutually recursive. The escape analysis can be
-// more precise when analyzing a single non-recursive function than
-// when analyzing a set of mutually recursive functions.
-
-static NodeList *stack;
-static uint32 visitgen;
-static uint32 visit(Node*);
-static uint32 visitcode(Node*, uint32);
-static uint32 visitcodelist(NodeList*, uint32);
-
-static void analyze(NodeList*, int);
-
-enum
-{
-       EscFuncUnknown = 0,
-       EscFuncPlanned,
-       EscFuncStarted,
-       EscFuncTagged,
-};
-
-void
-escapes(NodeList *all)
-{
-       NodeList *l;
-
-       for(l=all; l; l=l->next)
-               l->n->walkgen = 0;
-
-       visitgen = 0;
-       for(l=all; l; l=l->next)
-               if(l->n->op == ODCLFUNC && l->n->curfn == N)
-                       visit(l->n);
-
-       for(l=all; l; l=l->next)
-               l->n->walkgen = 0;
-}
-
-static uint32
-visit(Node *n)
-{
-       uint32 min, recursive;
-       NodeList *l, *block;
-
-       if(n->walkgen > 0) {
-               // already visited
-               return n->walkgen;
-       }
-       
-       visitgen++;
-       n->walkgen = visitgen;
-       visitgen++;
-       min = visitgen;
-
-       l = mal(sizeof *l);
-       l->next = stack;
-       l->n = n;
-       stack = l;
-       min = visitcodelist(n->nbody, min);
-       if((min == n->walkgen || min == n->walkgen+1) && n->curfn == N) {
-               // This node is the root of a strongly connected component.
-
-               // The original min passed to visitcodelist was n->walkgen+1.
-               // If visitcodelist found its way back to n->walkgen, then this
-               // block is a set of mutually recursive functions.
-               // Otherwise it's just a lone function that does not recurse.
-               recursive = min == n->walkgen;
-
-               // Remove connected component from stack.
-               // Mark walkgen so that future visits return a large number
-               // so as not to affect the caller's min.
-               block = stack;
-               for(l=stack; l->n != n; l=l->next)
-                       l->n->walkgen = (uint32)~0U;
-               n->walkgen = (uint32)~0U;
-               stack = l->next;
-               l->next = nil;
-
-               // Run escape analysis on this set of functions.
-               analyze(block, recursive);
-       }
-
-       return min;
-}
-
-static uint32
-visitcodelist(NodeList *l, uint32 min)
-{
-       for(; l; l=l->next)
-               min = visitcode(l->n, min);
-       return min;
-}
-
-static uint32
-visitcode(Node *n, uint32 min)
-{
-       Node *fn;
-       uint32 m;
-
-       if(n == N)
-               return min;
-
-       min = visitcodelist(n->ninit, min);
-       min = visitcode(n->left, min);
-       min = visitcode(n->right, min);
-       min = visitcodelist(n->list, min);
-       min = visitcode(n->ntest, min);
-       min = visitcode(n->nincr, min);
-       min = visitcodelist(n->nbody, min);
-       min = visitcodelist(n->nelse, min);
-       min = visitcodelist(n->rlist, min);
-       
-       if(n->op == OCALLFUNC || n->op == OCALLMETH) {
-               fn = n->left;
-               if(n->op == OCALLMETH)
-                       fn = n->left->right->sym->def;
-               if(fn && fn->op == ONAME && fn->class == PFUNC && fn->defn)
-                       if((m = visit(fn->defn)) < min)
-                               min = m;
-       }
-       
-       if(n->op == OCLOSURE)
-               if((m = visit(n->closure)) < min)
-                       min = m;
-
-       return min;
-}
-
-// An escape analysis pass for a set of functions.
-//
-// First escfunc, esc and escassign recurse over the ast of each
-// function to dig out flow(dst,src) edges between any
-// pointer-containing nodes and store them in dst->escflowsrc.  For
-// variables assigned to a variable in an outer scope or used as a
-// return value, they store a flow(theSink, src) edge to a fake node
-// 'the Sink'.  For variables referenced in closures, an edge
-// flow(closure, &var) is recorded and the flow of a closure itself to
-// an outer scope is tracked the same way as other variables.
-//
-// Then escflood walks the graph starting at theSink and tags all
-// variables of it can reach an & node as escaping and all function
-// parameters it can reach as leaking.
-//
-// If a value's address is taken but the address does not escape,
-// then the value can stay on the stack.  If the value new(T) does
-// not escape, then new(T) can be rewritten into a stack allocation.
-// The same is true of slice literals.
-//
-// If optimizations are disabled (-N), this code is not used.
-// Instead, the compiler assumes that any value whose address
-// is taken without being immediately dereferenced
-// needs to be moved to the heap, and new(T) and slice
-// literals are always real allocations.
-
-typedef struct EscState EscState;
-
-static void escfunc(EscState*, Node *func);
-static void esclist(EscState*, NodeList *l, Node *up);
-static void esc(EscState*, Node *n, Node *up);
-static void escloopdepthlist(EscState*, NodeList *l);
-static void escloopdepth(EscState*, Node *n);
-static void escassign(EscState*, Node *dst, Node *src);
-static void esccall(EscState*, Node*, Node *up);
-static void escflows(EscState*, Node *dst, Node *src);
-static void escflood(EscState*, Node *dst);
-static void escwalk(EscState*, int level, Node *dst, Node *src);
-static void esctag(EscState*, Node *func);
-
-struct EscState {
-       // Fake node that all
-       //   - return values and output variables
-       //   - parameters on imported functions not marked 'safe'
-       //   - assignments to global variables
-       // flow to.
-       Node    theSink;
-       
-       // If an analyzed function is recorded to return
-       // pieces obtained via indirection from a parameter,
-       // and later there is a call f(x) to that function,
-       // we create a link funcParam <- x to record that fact.
-       // The funcParam node is handled specially in escflood.
-       Node    funcParam;      
-       
-       NodeList*       dsts;           // all dst nodes
-       int     loopdepth;      // for detecting nested loop scopes
-       int     pdepth;         // for debug printing in recursions.
-       int     dstcount, edgecount;    // diagnostic
-       NodeList*       noesc;  // list of possible non-escaping nodes, for printing
-       int     recursive;      // recursive function or group of mutually recursive functions.
-};
-
-static Strlit *tags[16];
-
-static Strlit*
-mktag(int mask)
-{
-       Strlit *s;
-       char buf[40];
-
-       switch(mask&EscMask) {
-       case EscNone:
-       case EscReturn:
-               break;
-       default:
-               fatal("escape mktag");
-       }
-
-       mask >>= EscBits;
-
-       if(mask < nelem(tags) && tags[mask] != nil)
-               return tags[mask];
-
-       snprint(buf, sizeof buf, "esc:0x%x", mask);
-       s = newstrlit(buf);
-       if(mask < nelem(tags))
-               tags[mask] = s;
-       return s;
-}
-
-static int
-parsetag(Strlit *note)
-{
-       int em;
-
-       if(note == nil)
-               return EscUnknown;
-       if(strncmp(note->s, "esc:", 4) != 0)
-               return EscUnknown;
-       em = atoi(note->s + 4);
-       if (em == 0)
-               return EscNone;
-       return EscReturn | (em << EscBits);
-}
-
-static void
-analyze(NodeList *all, int recursive)
-{
-       NodeList *l;
-       EscState es, *e;
-       
-       memset(&es, 0, sizeof es);
-       e = &es;
-       e->theSink.op = ONAME;
-       e->theSink.orig = &e->theSink;
-       e->theSink.class = PEXTERN;
-       e->theSink.sym = lookup(".sink");
-       e->theSink.escloopdepth = -1;
-       e->recursive = recursive;
-       
-       e->funcParam.op = ONAME;
-       e->funcParam.orig = &e->funcParam;
-       e->funcParam.class = PAUTO;
-       e->funcParam.sym = lookup(".param");
-       e->funcParam.escloopdepth = 10000000;
-       
-       for(l=all; l; l=l->next)
-               if(l->n->op == ODCLFUNC)
-                       l->n->esc = EscFuncPlanned;
-
-       // flow-analyze functions
-       for(l=all; l; l=l->next)
-               if(l->n->op == ODCLFUNC)
-                       escfunc(e, l->n);
-
-       // print("escapes: %d e->dsts, %d edges\n", e->dstcount, e->edgecount);
-
-       // visit the upstream of each dst, mark address nodes with
-       // addrescapes, mark parameters unsafe
-       for(l = e->dsts; l; l=l->next)
-               escflood(e, l->n);
-
-       // for all top level functions, tag the typenodes corresponding to the param nodes
-       for(l=all; l; l=l->next)
-               if(l->n->op == ODCLFUNC)
-                       esctag(e, l->n);
-
-       if(debug['m']) {
-               for(l=e->noesc; l; l=l->next)
-                       if(l->n->esc == EscNone)
-                               warnl(l->n->lineno, "%S %hN does not escape",
-                                       (l->n->curfn && l->n->curfn->nname) ? l->n->curfn->nname->sym : S,
-                                       l->n);
-       }
-}
-
-
-static void
-escfunc(EscState *e, Node *func)
-{
-       Node *savefn;
-       NodeList *ll;
-       int saveld;
-
-//     print("escfunc %N %s\n", func->nname, e->recursive?"(recursive)":"");
-
-       if(func->esc != 1)
-               fatal("repeat escfunc %N", func->nname);
-       func->esc = EscFuncStarted;
-
-       saveld = e->loopdepth;
-       e->loopdepth = 1;
-       savefn = curfn;
-       curfn = func;
-
-       for(ll=curfn->dcl; ll; ll=ll->next) {
-               if(ll->n->op != ONAME)
-                       continue;
-               switch (ll->n->class) {
-               case PPARAMOUT:
-                       // out params are in a loopdepth between the sink and all local variables
-                       ll->n->escloopdepth = 0;
-                       break;
-               case PPARAM:
-                       ll->n->escloopdepth = 1; 
-                       if(ll->n->type && !haspointers(ll->n->type))
-                               break;
-                       if(curfn->nbody == nil && !curfn->noescape)
-                               ll->n->esc = EscHeap;
-                       else
-                               ll->n->esc = EscNone;   // prime for escflood later
-                       e->noesc = list(e->noesc, ll->n);
-                       break;
-               }
-       }
-
-       // in a mutually recursive group we lose track of the return values
-       if(e->recursive)
-               for(ll=curfn->dcl; ll; ll=ll->next)
-                       if(ll->n->op == ONAME && ll->n->class == PPARAMOUT)
-                               escflows(e, &e->theSink, ll->n);
-
-       escloopdepthlist(e, curfn->nbody);
-       esclist(e, curfn->nbody, curfn);
-       curfn = savefn;
-       e->loopdepth = saveld;
-}
-
-// Mark labels that have no backjumps to them as not increasing e->loopdepth.
-// Walk hasn't generated (goto|label)->left->sym->label yet, so we'll cheat
-// and set it to one of the following two.  Then in esc we'll clear it again.
-static Label looping;
-static Label nonlooping;
-
-static void
-escloopdepthlist(EscState *e, NodeList *l)
-{
-       for(; l; l=l->next)
-               escloopdepth(e, l->n);
-}
-
-static void
-escloopdepth(EscState *e, Node *n)
-{
-       if(n == N)
-               return;
-
-       escloopdepthlist(e, n->ninit);
-
-       switch(n->op) {
-       case OLABEL:
-               if(!n->left || !n->left->sym)
-                       fatal("esc:label without label: %+N", n);
-               // Walk will complain about this label being already defined, but that's not until
-               // after escape analysis. in the future, maybe pull label & goto analysis out of walk and put before esc
-               // if(n->left->sym->label != nil)
-               //      fatal("escape analysis messed up analyzing label: %+N", n);
-               n->left->sym->label = &nonlooping;
-               break;
-       case OGOTO:
-               if(!n->left || !n->left->sym)
-                       fatal("esc:goto without label: %+N", n);
-               // If we come past one that's uninitialized, this must be a (harmless) forward jump
-               // but if it's set to nonlooping the label must have preceded this goto.
-               if(n->left->sym->label == &nonlooping)
-                       n->left->sym->label = &looping;
-               break;
-       }
-
-       escloopdepth(e, n->left);
-       escloopdepth(e, n->right);
-       escloopdepthlist(e, n->list);
-       escloopdepth(e, n->ntest);
-       escloopdepth(e, n->nincr);
-       escloopdepthlist(e, n->nbody);
-       escloopdepthlist(e, n->nelse);
-       escloopdepthlist(e, n->rlist);
-
-}
-
-static void
-esclist(EscState *e, NodeList *l, Node *up)
-{
-       for(; l; l=l->next)
-               esc(e, l->n, up);
-}
-
-static void
-esc(EscState *e, Node *n, Node *up)
-{
-       int lno;
-       NodeList *ll, *lr;
-       Node *a, *v;
-
-       if(n == N)
-               return;
-
-       lno = setlineno(n);
-
-       // ninit logically runs at a different loopdepth than the rest of the for loop.
-       esclist(e, n->ninit, n);
-
-       if(n->op == OFOR || n->op == ORANGE)
-               e->loopdepth++;
-
-       // type switch variables have no ODCL.
-       // process type switch as declaration.
-       // must happen before processing of switch body,
-       // so before recursion.
-       if(n->op == OSWITCH && n->ntest && n->ntest->op == OTYPESW) {
-               for(ll=n->list; ll; ll=ll->next) {  // cases
-                       // ll->n->nname is the variable per case
-                       if(ll->n->nname)
-                               ll->n->nname->escloopdepth = e->loopdepth;
-               }
-       }
-
-       esc(e, n->left, n);
-       esc(e, n->right, n);
-       esc(e, n->ntest, n);
-       esc(e, n->nincr, n);
-       esclist(e, n->nbody, n);
-       esclist(e, n->nelse, n);
-       esclist(e, n->list, n);
-       esclist(e, n->rlist, n);
-
-       if(n->op == OFOR || n->op == ORANGE)
-               e->loopdepth--;
-
-       if(debug['m'] > 1)
-               print("%L:[%d] %S esc: %N\n", lineno, e->loopdepth,
-                     (curfn && curfn->nname) ? curfn->nname->sym : S, n);
-
-       switch(n->op) {
-       case ODCL:
-               // Record loop depth at declaration.
-               if(n->left)
-                       n->left->escloopdepth = e->loopdepth;
-               break;
-
-       case OLABEL:
-               if(n->left->sym->label == &nonlooping) {
-                       if(debug['m'] > 1)
-                               print("%L:%N non-looping label\n", lineno, n);
-               } else if(n->left->sym->label == &looping) {
-                       if(debug['m'] > 1)
-                               print("%L: %N looping label\n", lineno, n);
-                       e->loopdepth++;
-               }
-               // See case OLABEL in escloopdepth above
-               // else if(n->left->sym->label == nil)
-               //      fatal("escape analysis missed or messed up a label: %+N", n);
-
-               n->left->sym->label = nil;
-               break;
-
-       case ORANGE:
-               // Everything but fixed array is a dereference.
-               if(isfixedarray(n->type) && n->list && n->list->next)
-                       escassign(e, n->list->next->n, n->right);
-               break;
-
-       case OSWITCH:
-               if(n->ntest && n->ntest->op == OTYPESW) {
-                       for(ll=n->list; ll; ll=ll->next) {  // cases
-                               // ntest->right is the argument of the .(type),
-                               // ll->n->nname is the variable per case
-                               escassign(e, ll->n->nname, n->ntest->right);
-                       }
-               }
-               break;
-
-       case OAS:
-       case OASOP:
-               // Filter out the following special case.
-               //
-               //      func (b *Buffer) Foo() {
-               //              n, m := ...
-               //              b.buf = b.buf[n:m]
-               //      }
-               //
-               // This assignment is a no-op for escape analysis,
-               // it does not store any new pointers into b that were not already there.
-               // However, without this special case b will escape, because we assign to OIND/ODOTPTR.
-               if((n->left->op == OIND || n->left->op == ODOTPTR) && n->left->left->op == ONAME && // dst is ONAME dereference
-                       (n->right->op == OSLICE || n->right->op == OSLICE3 || n->right->op == OSLICESTR) && // src is slice operation
-                       (n->right->left->op == OIND || n->right->left->op == ODOTPTR) && n->right->left->left->op == ONAME && // slice is applied to ONAME dereference
-                       n->left->left == n->right->left->left) { // dst and src reference the same base ONAME
-                       // Here we also assume that the statement will not contain calls,
-                       // that is, that order will move any calls to init.
-                       // Otherwise base ONAME value could change between the moments
-                       // when we evaluate it for dst and for src.
-                       //
-                       // Note, this optimization does not apply to OSLICEARR,
-                       // because it does introduce a new pointer into b that was not already there
-                       // (pointer to b itself). After such assignment, if b contents escape,
-                       // b escapes as well. If we ignore such OSLICEARR, we will conclude
-                       // that b does not escape when b contents do.
-                       if(debug['m']) {
-                               warnl(n->lineno, "%S ignoring self-assignment to %hN",
-                                       (n->curfn && n->curfn->nname) ? n->curfn->nname->sym : S, n->left);
-                       }
-                       break;
-               }
-               escassign(e, n->left, n->right);
-               break;
-
-       case OAS2:      // x,y = a,b
-               if(count(n->list) == count(n->rlist))
-                       for(ll=n->list, lr=n->rlist; ll; ll=ll->next, lr=lr->next)
-                               escassign(e, ll->n, lr->n);
-               break;
-
-       case OAS2RECV:          // v, ok = <-ch
-       case OAS2MAPR:          // v, ok = m[k]
-       case OAS2DOTTYPE:       // v, ok = x.(type)
-               escassign(e, n->list->n, n->rlist->n);
-               break;
-
-       case OSEND:             // ch <- x
-               escassign(e, &e->theSink, n->right);
-               break;
-
-       case ODEFER:
-               if(e->loopdepth == 1)  // top level
-                       break;
-               // arguments leak out of scope
-               // TODO: leak to a dummy node instead
-               // fallthrough
-       case OPROC:
-               // go f(x) - f and x escape
-               escassign(e, &e->theSink, n->left->left);
-               escassign(e, &e->theSink, n->left->right);  // ODDDARG for call
-               for(ll=n->left->list; ll; ll=ll->next)
-                       escassign(e, &e->theSink, ll->n);
-               break;
-
-       case OCALLMETH:
-       case OCALLFUNC:
-       case OCALLINTER:
-               esccall(e, n, up);
-               break;
-
-       case OAS2FUNC:  // x,y = f()
-               // esccall already done on n->rlist->n. tie it's escretval to n->list
-               lr=n->rlist->n->escretval;
-               for(ll=n->list; lr && ll; lr=lr->next, ll=ll->next)
-                       escassign(e, ll->n, lr->n);
-               if(lr || ll)
-                       fatal("esc oas2func");
-               break;
-
-       case ORETURN:
-               ll=n->list;
-               if(count(n->list) == 1 && curfn->type->outtuple > 1) {
-                       // OAS2FUNC in disguise
-                       // esccall already done on n->list->n
-                       // tie n->list->n->escretval to curfn->dcl PPARAMOUT's
-                       ll = n->list->n->escretval;
-               }
-
-               for(lr = curfn->dcl; lr && ll; lr=lr->next) {
-                       if (lr->n->op != ONAME || lr->n->class != PPARAMOUT)
-                               continue;
-                       escassign(e, lr->n, ll->n);
-                       ll = ll->next;
-               }
-               if (ll != nil)
-                       fatal("esc return list");
-               break;
-
-       case OPANIC:
-               // Argument could leak through recover.
-               escassign(e, &e->theSink, n->left);
-               break;
-
-       case OAPPEND:
-               if(!n->isddd)
-                       for(ll=n->list->next; ll; ll=ll->next)
-                               escassign(e, &e->theSink, ll->n);  // lose track of assign to dereference
-               break;
-
-       case OCONV:
-       case OCONVNOP:
-       case OCONVIFACE:
-               escassign(e, n, n->left);
-               break;
-
-       case OARRAYLIT:
-               if(isslice(n->type)) {
-                       n->esc = EscNone;  // until proven otherwise
-                       e->noesc = list(e->noesc, n);
-                       n->escloopdepth = e->loopdepth;
-                       // Values make it to memory, lose track.
-                       for(ll=n->list; ll; ll=ll->next)
-                               escassign(e, &e->theSink, ll->n->right);
-               } else {
-                       // Link values to array.
-                       for(ll=n->list; ll; ll=ll->next)
-                               escassign(e, n, ll->n->right);
-               }
-               break;
-
-       case OSTRUCTLIT:
-               // Link values to struct.
-               for(ll=n->list; ll; ll=ll->next)
-                       escassign(e, n, ll->n->right);
-               break;
-
-       case OPTRLIT:
-               n->esc = EscNone;  // until proven otherwise
-               e->noesc = list(e->noesc, n);
-               n->escloopdepth = e->loopdepth;
-               // Link OSTRUCTLIT to OPTRLIT; if OPTRLIT escapes, OSTRUCTLIT elements do too.
-               escassign(e, n, n->left);
-               break;
-
-       case OCALLPART:
-               n->esc = EscNone; // until proven otherwise
-               e->noesc = list(e->noesc, n);
-               n->escloopdepth = e->loopdepth;
-               // Contents make it to memory, lose track.
-               escassign(e, &e->theSink, n->left);
-               break;
-
-       case OMAPLIT:
-               n->esc = EscNone;  // until proven otherwise
-               e->noesc = list(e->noesc, n);
-               n->escloopdepth = e->loopdepth;
-               // Keys and values make it to memory, lose track.
-               for(ll=n->list; ll; ll=ll->next) {
-                       escassign(e, &e->theSink, ll->n->left);
-                       escassign(e, &e->theSink, ll->n->right);
-               }
-               break;
-       
-       case OCLOSURE:
-               // Link addresses of captured variables to closure.
-               for(ll=n->cvars; ll; ll=ll->next) {
-                       v = ll->n;
-                       if(v->op == OXXX)  // unnamed out argument; see dcl.c:/^funcargs
-                               continue;
-                       a = v->closure;
-                       if(!v->byval) {
-                               a = nod(OADDR, a, N);
-                               a->lineno = v->lineno;
-                               a->escloopdepth = e->loopdepth;
-                               typecheck(&a, Erv);
-                       }
-                       escassign(e, n, a);
-               }
-               // fallthrough
-       case OMAKECHAN:
-       case OMAKEMAP:
-       case OMAKESLICE:
-       case ONEW:
-       case OARRAYRUNESTR:
-       case OARRAYBYTESTR:
-       case OSTRARRAYRUNE:
-       case OSTRARRAYBYTE:
-       case ORUNESTR:
-               n->escloopdepth = e->loopdepth;
-               n->esc = EscNone;  // until proven otherwise
-               e->noesc = list(e->noesc, n);
-               break;
-
-       case OADDSTR:
-               n->escloopdepth = e->loopdepth;
-               n->esc = EscNone;  // until proven otherwise
-               e->noesc = list(e->noesc, n);
-               // Arguments of OADDSTR do not escape.
-               break;
-
-       case OADDR:
-               n->esc = EscNone;  // until proven otherwise
-               e->noesc = list(e->noesc, n);
-               // current loop depth is an upper bound on actual loop depth
-               // of addressed value.
-               n->escloopdepth = e->loopdepth;
-               // for &x, use loop depth of x if known.
-               // it should always be known, but if not, be conservative
-               // and keep the current loop depth.
-               if(n->left->op == ONAME) {
-                       switch(n->left->class) {
-                       case PAUTO:
-                               if(n->left->escloopdepth != 0)
-                                       n->escloopdepth = n->left->escloopdepth;
-                               break;
-                       case PPARAM:
-                       case PPARAMOUT:
-                               // PPARAM is loop depth 1 always.
-                               // PPARAMOUT is loop depth 0 for writes
-                               // but considered loop depth 1 for address-of,
-                               // so that writing the address of one result
-                               // to another (or the same) result makes the
-                               // first result move to the heap.
-                               n->escloopdepth = 1;
-                               break;
-                       }
-               }
-               break;
-       }
-
-       lineno = lno;
-}
-
-// Assert that expr somehow gets assigned to dst, if non nil.  for
-// dst==nil, any name node expr still must be marked as being
-// evaluated in curfn. For expr==nil, dst must still be examined for
-// evaluations inside it (e.g *f(x) = y)
-static void
-escassign(EscState *e, Node *dst, Node *src)
-{
-       int lno;
-       NodeList *ll;
-
-       if(isblank(dst) || dst == N || src == N || src->op == ONONAME || src->op == OXXX)
-               return;
-
-       if(debug['m'] > 1)
-               print("%L:[%d] %S escassign: %hN(%hJ) = %hN(%hJ)\n", lineno, e->loopdepth,
-                     (curfn && curfn->nname) ? curfn->nname->sym : S, dst, dst, src, src);
-
-       setlineno(dst);
-       
-       // Analyze lhs of assignment.
-       // Replace dst with e->theSink if we can't track it.
-       switch(dst->op) {
-       default:
-               dump("dst", dst);
-               fatal("escassign: unexpected dst");
-
-       case OARRAYLIT:
-       case OCLOSURE:
-       case OCONV:
-       case OCONVIFACE:
-       case OCONVNOP:
-       case OMAPLIT:
-       case OSTRUCTLIT:
-       case OPTRLIT:
-       case OCALLPART:
-               break;
-
-       case ONAME:
-               if(dst->class == PEXTERN)
-                       dst = &e->theSink;
-               break;
-       case ODOT:            // treat "dst.x  = src" as "dst = src"
-               escassign(e, dst->left, src);
-               return;
-       case OINDEX:
-               if(isfixedarray(dst->left->type)) {
-                       escassign(e, dst->left, src);
-                       return;
-               }
-               dst = &e->theSink;  // lose track of dereference
-               break;
-       case OIND:
-       case ODOTPTR:
-               dst = &e->theSink;  // lose track of dereference
-               break;
-       case OINDEXMAP:
-               // lose track of key and value
-               escassign(e, &e->theSink, dst->right);
-               dst = &e->theSink;
-               break;
-       }
-
-       lno = setlineno(src);
-       e->pdepth++;
-
-       switch(src->op) {
-       case OADDR:     // dst = &x
-       case OIND:      // dst = *x
-       case ODOTPTR:   // dst = (*x).f
-       case ONAME:
-       case OPARAM:
-       case ODDDARG:
-       case OPTRLIT:
-       case OARRAYLIT:
-       case OMAPLIT:
-       case OSTRUCTLIT:
-       case OMAKECHAN:
-       case OMAKEMAP:
-       case OMAKESLICE:
-       case OARRAYRUNESTR:
-       case OARRAYBYTESTR:
-       case OSTRARRAYRUNE:
-       case OSTRARRAYBYTE:
-       case OADDSTR:
-       case ONEW:
-       case OCLOSURE:
-       case OCALLPART:
-       case ORUNESTR:
-               escflows(e, dst, src);
-               break;
-
-       case OCALLMETH:
-       case OCALLFUNC:
-       case OCALLINTER:
-               // Flowing multiple returns to a single dst happens when
-               // analyzing "go f(g())": here g() flows to sink (issue 4529).
-               for(ll=src->escretval; ll; ll=ll->next)
-                       escflows(e, dst, ll->n);
-               break;
-
-       case ODOT:
-               // A non-pointer escaping from a struct does not concern us.
-               if(src->type && !haspointers(src->type))
-                       break;
-               // fallthrough
-       case OCONV:
-       case OCONVIFACE:
-       case OCONVNOP:
-       case ODOTMETH:  // treat recv.meth as a value with recv in it, only happens in ODEFER and OPROC
-                       // iface.method already leaks iface in esccall, no need to put in extra ODOTINTER edge here
-       case ODOTTYPE:
-       case ODOTTYPE2:
-       case OSLICE:
-       case OSLICE3:
-       case OSLICEARR:
-       case OSLICE3ARR:
-       case OSLICESTR:
-               // Conversions, field access, slice all preserve the input value.
-               escassign(e, dst, src->left);
-               break;
-
-       case OAPPEND:
-               // Append returns first argument.
-               escassign(e, dst, src->list->n);
-               break;
-       
-       case OINDEX:
-               // Index of array preserves input value.
-               if(isfixedarray(src->left->type))
-                       escassign(e, dst, src->left);
-               break;
-
-       case OADD:
-       case OSUB:
-       case OOR:
-       case OXOR:
-       case OMUL:
-       case ODIV:
-       case OMOD:
-       case OLSH:
-       case ORSH:
-       case OAND:
-       case OANDNOT:
-       case OPLUS:
-       case OMINUS:
-       case OCOM:
-               // Might be pointer arithmetic, in which case
-               // the operands flow into the result.
-               // TODO(rsc): Decide what the story is here.  This is unsettling.
-               escassign(e, dst, src->left);
-               escassign(e, dst, src->right);
-               break;
-       }
-
-       e->pdepth--;
-       lineno = lno;
-}
-
-static int
-escassignfromtag(EscState *e, Strlit *note, NodeList *dsts, Node *src)
-{
-       int em, em0;
-       
-       em = parsetag(note);
-
-       if(em == EscUnknown) {
-               escassign(e, &e->theSink, src);
-               return em;
-       }
-
-       if(em == EscNone)
-               return em;
-       
-       // If content inside parameter (reached via indirection)
-       // escapes back to results, mark as such.
-       if(em & EscContentEscapes)
-               escassign(e, &e->funcParam, src);
-
-       em0 = em;
-       for(em >>= EscReturnBits; em && dsts; em >>= 1, dsts=dsts->next)
-               if(em & 1)
-                       escassign(e, dsts->n, src);
-
-       if (em != 0 && dsts == nil)
-               fatal("corrupt esc tag %Z or messed up escretval list\n", note);
-       return em0;
-}
-
-// This is a bit messier than fortunate, pulled out of esc's big
-// switch for clarity. We either have the paramnodes, which may be
-// connected to other things through flows or we have the parameter type
-// nodes, which may be marked "noescape". Navigating the ast is slightly
-// different for methods vs plain functions and for imported vs
-// this-package
-static void
-esccall(EscState *e, Node *n, Node *up)
-{
-       NodeList *ll, *lr;
-       Node *a, *fn, *src;
-       Type *t, *fntype;
-       char buf[40];
-       int i;
-
-       fn = N;
-       switch(n->op) {
-       default:
-               fatal("esccall");
-
-       case OCALLFUNC:
-               fn = n->left;
-               fntype = fn->type;
-               break;
-
-       case OCALLMETH:
-               fn = n->left->right->sym->def;
-               if(fn)
-                       fntype = fn->type;
-               else
-                       fntype = n->left->type;
-               break;
-
-       case OCALLINTER:
-               fntype = n->left->type;
-               break;
-       }
-
-       ll = n->list;
-       if(n->list != nil && n->list->next == nil) {
-               a = n->list->n;
-               if(a->type->etype == TSTRUCT && a->type->funarg) // f(g()).
-                       ll = a->escretval;
-       }
-
-       if(fn && fn->op == ONAME && fn->class == PFUNC && fn->defn && fn->defn->nbody && fn->ntype && fn->defn->esc < EscFuncTagged) {
-               // function in same mutually recursive group.  Incorporate into flow graph.
-//             print("esc local fn: %N\n", fn->ntype);
-               if(fn->defn->esc == EscFuncUnknown || n->escretval != nil)
-                       fatal("graph inconsistency");
-
-               // set up out list on this call node
-               for(lr=fn->ntype->rlist; lr; lr=lr->next)
-                       n->escretval = list(n->escretval, lr->n->left);  // type.rlist ->  dclfield -> ONAME (PPARAMOUT)
-
-               // Receiver.
-               if(n->op != OCALLFUNC)
-                       escassign(e, fn->ntype->left->left, n->left->left);
-
-               for(lr=fn->ntype->list; ll && lr; ll=ll->next, lr=lr->next) {
-                       src = ll->n;
-                       if(lr->n->isddd && !n->isddd) {
-                               // Introduce ODDDARG node to represent ... allocation.
-                               src = nod(ODDDARG, N, N);
-                               src->type = typ(TARRAY);
-                               src->type->type = lr->n->type->type;
-                               src->type->bound = count(ll);
-                               src->type = ptrto(src->type); // make pointer so it will be tracked
-                               src->escloopdepth = e->loopdepth;
-                               src->lineno = n->lineno;
-                               src->esc = EscNone;  // until we find otherwise
-                               e->noesc = list(e->noesc, src);
-                               n->right = src;
-                       }
-                       if(lr->n->left != N)
-                               escassign(e, lr->n->left, src);
-                       if(src != ll->n)
-                               break;
-               }
-               // "..." arguments are untracked
-               for(; ll; ll=ll->next)
-                       escassign(e, &e->theSink, ll->n);
-
-               return;
-       }
-
-       // Imported or completely analyzed function.  Use the escape tags.
-       if(n->escretval != nil)
-               fatal("esc already decorated call %+N\n", n);
-
-       // set up out list on this call node with dummy auto ONAMES in the current (calling) function.
-       i = 0;
-       for(t=getoutargx(fntype)->type; t; t=t->down) {
-               src = nod(ONAME, N, N);
-               snprint(buf, sizeof buf, ".dum%d", i++);
-               src->sym = lookup(buf);
-               src->type = t->type;
-               src->class = PAUTO;
-               src->curfn = curfn;
-               src->escloopdepth = e->loopdepth;
-               src->used = 1;
-               src->lineno = n->lineno;
-               n->escretval = list(n->escretval, src); 
-       }
-
-//     print("esc analyzed fn: %#N (%+T) returning (%+H)\n", fn, fntype, n->escretval);
-
-       // Receiver.
-       if(n->op != OCALLFUNC) {
-               t = getthisx(fntype)->type;
-               src = n->left->left;
-               if(haspointers(t->type))
-                       escassignfromtag(e, t->note, n->escretval, src);
-       }
-       
-       for(t=getinargx(fntype)->type; ll; ll=ll->next) {
-               src = ll->n;
-               if(t->isddd && !n->isddd) {
-                       // Introduce ODDDARG node to represent ... allocation.
-                       src = nod(ODDDARG, N, N);
-                       src->escloopdepth = e->loopdepth;
-                       src->lineno = n->lineno;
-                       src->type = typ(TARRAY);
-                       src->type->type = t->type->type;
-                       src->type->bound = count(ll);
-                       src->type = ptrto(src->type); // make pointer so it will be tracked
-                       src->esc = EscNone;  // until we find otherwise
-                       e->noesc = list(e->noesc, src);
-                       n->right = src;
-               }
-               if(haspointers(t->type)) {
-                       if(escassignfromtag(e, t->note, n->escretval, src) == EscNone && up->op != ODEFER && up->op != OPROC) {
-                               a = src;
-                               while(a->op == OCONVNOP)
-                                       a = a->left;
-                               switch(a->op) {
-                               case OCALLPART:
-                               case OCLOSURE:
-                               case ODDDARG:
-                               case OARRAYLIT:
-                               case OPTRLIT:
-                               case OSTRUCTLIT:
-                                       // The callee has already been analyzed, so its arguments have esc tags.
-                                       // The argument is marked as not escaping at all.
-                                       // Record that fact so that any temporary used for
-                                       // synthesizing this expression can be reclaimed when
-                                       // the function returns.
-                                       // This 'noescape' is even stronger than the usual esc == EscNone.
-                                       // src->esc == EscNone means that src does not escape the current function.
-                                       // src->noescape = 1 here means that src does not escape this statement
-                                       // in the current function.
-                                       a->noescape = 1;
-                                       break;
-                               }
-                       }
-               }
-               if(src != ll->n)
-                       break;
-               t = t->down;
-       }
-       // "..." arguments are untracked
-       for(; ll; ll=ll->next)
-               escassign(e, &e->theSink, ll->n);
-}
-
-// Store the link src->dst in dst, throwing out some quick wins.
-static void
-escflows(EscState *e, Node *dst, Node *src)
-{
-       if(dst == nil || src == nil || dst == src)
-               return;
-
-       // Don't bother building a graph for scalars.
-       if(src->type && !haspointers(src->type))
-               return;
-
-       if(debug['m']>2)
-               print("%L::flows:: %hN <- %hN\n", lineno, dst, src);
-
-       if(dst->escflowsrc == nil) {
-               e->dsts = list(e->dsts, dst);
-               e->dstcount++;
-       }
-       e->edgecount++;
-
-       dst->escflowsrc = list(dst->escflowsrc, src);
-}
-
-// Whenever we hit a reference node, the level goes up by one, and whenever
-// we hit an OADDR, the level goes down by one. as long as we're on a level > 0
-// finding an OADDR just means we're following the upstream of a dereference,
-// so this address doesn't leak (yet).
-// If level == 0, it means the /value/ of this node can reach the root of this flood.
-// so if this node is an OADDR, it's argument should be marked as escaping iff
-// it's currfn/e->loopdepth are different from the flood's root.
-// Once an object has been moved to the heap, all of it's upstream should be considered
-// escaping to the global scope.
-static void
-escflood(EscState *e, Node *dst)
-{
-       NodeList *l;
-
-       switch(dst->op) {
-       case ONAME:
-       case OCLOSURE:
-               break;
-       default:
-               return;
-       }
-
-       if(debug['m']>1)
-               print("\nescflood:%d: dst %hN scope:%S[%d]\n", walkgen, dst,
-                     (dst->curfn && dst->curfn->nname) ? dst->curfn->nname->sym : S,
-                     dst->escloopdepth);
-
-       for(l = dst->escflowsrc; l; l=l->next) {
-               walkgen++;
-               escwalk(e, 0, dst, l->n);
-       }
-}
-
-// There appear to be some loops in the escape graph, causing
-// arbitrary recursion into deeper and deeper levels.
-// Cut this off safely by making minLevel sticky: once you
-// get that deep, you cannot go down any further but you also
-// cannot go up any further. This is a conservative fix.
-// Making minLevel smaller (more negative) would handle more
-// complex chains of indirections followed by address-of operations,
-// at the cost of repeating the traversal once for each additional
-// allowed level when a loop is encountered. Using -2 suffices to
-// pass all the tests we have written so far, which we assume matches
-// the level of complexity we want the escape analysis code to handle.
-#define MinLevel (-2)
-/*c2go enum { MinLevel = -2 };*/
-
-static void
-escwalk(EscState *e, int level, Node *dst, Node *src)
-{
-       NodeList *ll;
-       int leaks, newlevel;
-
-       if(src->walkgen == walkgen && src->esclevel <= level)
-               return;
-       src->walkgen = walkgen;
-       src->esclevel = level;
-
-       if(debug['m']>1)
-               print("escwalk: level:%d depth:%d %.*s %hN(%hJ) scope:%S[%d]\n",
-                     level, e->pdepth, e->pdepth, "\t\t\t\t\t\t\t\t\t\t", src, src,
-                     (src->curfn && src->curfn->nname) ? src->curfn->nname->sym : S, src->escloopdepth);
-
-       e->pdepth++;
-
-       // Input parameter flowing to output parameter?
-       if(dst->op == ONAME && dst->class == PPARAMOUT && dst->vargen <= 20) {
-               if(src->op == ONAME && src->class == PPARAM && src->curfn == dst->curfn && src->esc != EscScope && src->esc != EscHeap) {
-                       if(level == 0) {
-                               if(debug['m'])
-                                       warnl(src->lineno, "leaking param: %hN to result %S", src, dst->sym);
-                               if((src->esc&EscMask) != EscReturn)
-                                       src->esc = EscReturn;
-                               src->esc |= 1<<((dst->vargen-1) + EscReturnBits);
-                               goto recurse;
-                       } else if(level > 0) {
-                               if(debug['m'])
-                                       warnl(src->lineno, "%N leaking param %hN content to result %S", src->curfn->nname, src, dst->sym);
-                               if((src->esc&EscMask) != EscReturn)
-                                       src->esc = EscReturn;
-                               src->esc |= EscContentEscapes;
-                               goto recurse;
-                       }
-               }
-       }
-
-       // The second clause is for values pointed at by an object passed to a call
-       // that returns something reached via indirect from the object.
-       // We don't know which result it is or how many indirects, so we treat it as leaking.
-       leaks = level <= 0 && dst->escloopdepth < src->escloopdepth ||
-               level < 0 && dst == &e->funcParam && haspointers(src->type);
-
-       switch(src->op) {
-       case ONAME:
-               if(src->class == PPARAM && (leaks || dst->escloopdepth < 0) && src->esc != EscHeap) {
-                       src->esc = EscScope;
-                       if(debug['m'])
-                               warnl(src->lineno, "leaking param: %hN", src);
-               }
-
-               // Treat a PPARAMREF closure variable as equivalent to the
-               // original variable.
-               if(src->class == PPARAMREF) {
-                       if(leaks && debug['m'])
-                               warnl(src->lineno, "leaking closure reference %hN", src);
-                       escwalk(e, level, dst, src->closure);
-               }
-               break;
-
-       case OPTRLIT:
-       case OADDR:
-               if(leaks) {
-                       src->esc = EscHeap;
-                       addrescapes(src->left);
-                       if(debug['m'])
-                               warnl(src->lineno, "%hN escapes to heap", src);
-               }
-               newlevel = level;
-               if(level > MinLevel)
-                       newlevel--;
-               escwalk(e, newlevel, dst, src->left);
-               break;
-
-       case OARRAYLIT:
-               if(isfixedarray(src->type))
-                       break;
-               // fall through
-       case ODDDARG:
-       case OMAKECHAN:
-       case OMAKEMAP:
-       case OMAKESLICE:
-       case OARRAYRUNESTR:
-       case OARRAYBYTESTR:
-       case OSTRARRAYRUNE:
-       case OSTRARRAYBYTE:
-       case OADDSTR:
-       case OMAPLIT:
-       case ONEW:
-       case OCLOSURE:
-       case OCALLPART:
-       case ORUNESTR:
-               if(leaks) {
-                       src->esc = EscHeap;
-                       if(debug['m'])
-                               warnl(src->lineno, "%hN escapes to heap", src);
-               }
-               break;
-
-       case ODOT:
-       case OSLICE:
-       case OSLICEARR:
-       case OSLICE3:
-       case OSLICE3ARR:
-       case OSLICESTR:
-               escwalk(e, level, dst, src->left);
-               break;
-
-       case OINDEX:
-               if(isfixedarray(src->left->type)) {
-                       escwalk(e, level, dst, src->left);
-                       break;
-               }
-               // fall through
-       case ODOTPTR:
-       case OINDEXMAP:
-       case OIND:
-               newlevel = level;
-               if(level > MinLevel)
-                       newlevel++;
-               escwalk(e, newlevel, dst, src->left);
-       }
-
-recurse:
-       for(ll=src->escflowsrc; ll; ll=ll->next)
-               escwalk(e, level, dst, ll->n);
-
-       e->pdepth--;
-}
-
-static void
-esctag(EscState *e, Node *func)
-{
-       Node *savefn;
-       NodeList *ll;
-       Type *t;
-
-       USED(e);
-       func->esc = EscFuncTagged;
-       
-       // External functions are assumed unsafe,
-       // unless //go:noescape is given before the declaration.
-       if(func->nbody == nil) {
-               if(func->noescape) {
-                       for(t=getinargx(func->type)->type; t; t=t->down)
-                               if(haspointers(t->type))
-                                       t->note = mktag(EscNone);
-               }
-               return;
-       }
-
-       savefn = curfn;
-       curfn = func;
-
-       for(ll=curfn->dcl; ll; ll=ll->next) {
-               if(ll->n->op != ONAME || ll->n->class != PPARAM)
-                       continue;
-
-               switch (ll->n->esc&EscMask) {
-               case EscNone:   // not touched by escflood
-               case EscReturn: 
-                       if(haspointers(ll->n->type)) // don't bother tagging for scalars
-                               ll->n->paramfld->note = mktag(ll->n->esc);
-                       break;
-               case EscHeap:   // touched by escflood, moved to heap
-               case EscScope:  // touched by escflood, value leaves scope
-                       break;
-               }
-       }
-
-       curfn = savefn;
-}
diff --git a/src/cmd/gc/export.c b/src/cmd/gc/export.c
deleted file mode 100644 (file)
index 91f4957..0000000
+++ /dev/null
@@ -1,563 +0,0 @@
-// Copyright 2009 The Go Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style
-// license that can be found in the LICENSE file.
-
-#include       <u.h>
-#include       <libc.h>
-#include       "go.h"
-#include       "y.tab.h"
-
-static NodeList *asmlist;
-
-static void    dumpexporttype(Type *t);
-
-// Mark n's symbol as exported
-void
-exportsym(Node *n)
-{
-       if(n == N || n->sym == S)
-               return;
-       if(n->sym->flags & (SymExport|SymPackage)) {
-               if(n->sym->flags & SymPackage)
-                       yyerror("export/package mismatch: %S", n->sym);
-               return;
-       }
-       n->sym->flags |= SymExport;
-
-       if(debug['E'])
-               print("export symbol %S\n", n->sym);
-       exportlist = list(exportlist, n);
-}
-
-int
-exportname(char *s)
-{
-       Rune r;
-
-       if((uchar)s[0] < Runeself)
-               return 'A' <= s[0] && s[0] <= 'Z';
-       chartorune(&r, s);
-       return isupperrune(r);
-}
-
-static int
-initname(char *s)
-{
-       return strcmp(s, "init") == 0;
-}
-
-// exportedsym reports whether a symbol will be visible
-// to files that import our package.
-static int
-exportedsym(Sym *sym)
-{
-       // Builtins are visible everywhere.
-       if(sym->pkg == builtinpkg || sym->origpkg == builtinpkg)
-               return 1;
-
-       return sym->pkg == localpkg && exportname(sym->name);
-}
-
-void
-autoexport(Node *n, int ctxt)
-{
-       if(n == N || n->sym == S)
-               return;
-       if((ctxt != PEXTERN && ctxt != PFUNC) || dclcontext != PEXTERN)
-               return;
-       if(n->ntype && n->ntype->op == OTFUNC && n->ntype->left)        // method
-               return;
-       // -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
-dumppkg(Pkg *p)
-{
-       char *suffix;
-
-       if(p == nil || p == localpkg || p->exported || p == builtinpkg)
-               return;
-       p->exported = 1;
-       suffix = "";
-       if(!p->direct)
-               suffix = " // indirect";
-       Bprint(bout, "\timport %s \"%Z\"%s\n", p->name, p->path, suffix);
-}
-
-// Look for anything we need for the inline body
-static void reexportdep(Node *n);
-static void
-reexportdeplist(NodeList *ll)
-{
-       for(; ll ;ll=ll->next)
-               reexportdep(ll->n);
-}
-
-static void
-reexportdep(Node *n)
-{
-       Type *t;
-
-       if(!n)
-               return;
-
-       //print("reexportdep %+hN\n", n);
-       switch(n->op) {
-       case ONAME:
-               switch(n->class&~PHEAP) {
-               case PFUNC:
-                       // methods will be printed along with their type
-                       // nodes for T.Method expressions
-                       if(n->left && n->left->op == OTYPE)
-                               break;
-                       // nodes for method calls.
-                       if(!n->type || n->type->thistuple > 0)
-                               break;
-                       // fallthrough
-               case PEXTERN:
-                       if(n->sym && !exportedsym(n->sym)) {
-                               if(debug['E'])
-                                       print("reexport name %S\n", n->sym);
-                               exportlist = list(exportlist, n);
-                       }
-               }
-               break;
-
-       case ODCL:
-               // Local variables in the bodies need their type.
-               t = n->left->type;
-               if(t != types[t->etype] && t != idealbool && t != idealstring) {
-                       if(isptr[t->etype])
-                               t = t->type;
-                       if(t && t->sym && t->sym->def && !exportedsym(t->sym)) {
-                               if(debug['E'])
-                                       print("reexport type %S from declaration\n", t->sym);
-                               exportlist = list(exportlist, t->sym->def);
-                       }
-               }
-               break;
-
-       case OLITERAL:
-               t = n->type;
-               if(t != types[n->type->etype] && t != idealbool && t != idealstring) {
-                       if(isptr[t->etype])
-                               t = t->type;
-                       if(t && t->sym && t->sym->def && !exportedsym(t->sym)) {
-                               if(debug['E'])
-                                       print("reexport literal type %S\n", t->sym);
-                               exportlist = list(exportlist, t->sym->def);
-                       }
-               }
-               // fallthrough
-       case OTYPE:
-               if(n->sym && !exportedsym(n->sym)) {
-                       if(debug['E'])
-                               print("reexport literal/type %S\n", n->sym);
-                       exportlist = list(exportlist, n);
-               }
-               break;
-
-       // for operations that need a type when rendered, put the type on the export list.
-       case OCONV:
-       case OCONVIFACE:
-       case OCONVNOP:
-       case ORUNESTR:
-       case OARRAYBYTESTR:
-       case OARRAYRUNESTR:
-       case OSTRARRAYBYTE:
-       case OSTRARRAYRUNE:
-       case ODOTTYPE:
-       case ODOTTYPE2:
-       case OSTRUCTLIT:
-       case OARRAYLIT:
-       case OPTRLIT:
-       case OMAKEMAP:
-       case OMAKESLICE:
-       case OMAKECHAN:
-               t = n->type;
-               if(!t->sym && t->type)
-                       t = t->type;
-               if(t && t->sym && t->sym->def && !exportedsym(t->sym)) {
-                       if(debug['E'])
-                               print("reexport type for expression %S\n", t->sym);
-                       exportlist = list(exportlist, t->sym->def);
-               }
-               break;
-       }
-
-       reexportdep(n->left);
-       reexportdep(n->right);
-       reexportdeplist(n->list);
-       reexportdeplist(n->rlist);
-       reexportdeplist(n->ninit);
-       reexportdep(n->ntest);
-       reexportdep(n->nincr);
-       reexportdeplist(n->nbody);
-       reexportdeplist(n->nelse);
-}
-
-
-static void
-dumpexportconst(Sym *s)
-{
-       Node *n;
-       Type *t;
-
-       n = s->def;
-       typecheck(&n, Erv);
-       if(n == N || n->op != OLITERAL)
-               fatal("dumpexportconst: oconst nil: %S", s);
-
-       t = n->type;    // may or may not be specified
-       dumpexporttype(t);
-
-       if(t != T && !isideal(t))
-               Bprint(bout, "\tconst %#S %#T = %#V\n", s, t, &n->val);
-       else
-               Bprint(bout, "\tconst %#S = %#V\n", s, &n->val);
-}
-
-static void
-dumpexportvar(Sym *s)
-{
-       Node *n;
-       Type *t;
-
-       n = s->def;
-       typecheck(&n, Erv|Ecall);
-       if(n == N || n->type == T) {
-               yyerror("variable exported but not defined: %S", s);
-               return;
-       }
-
-       t = n->type;
-       dumpexporttype(t);
-
-       if(t->etype == TFUNC && n->class == PFUNC) {
-               if (n->inl) {
-                       // when lazily typechecking inlined bodies, some re-exported ones may not have been typechecked yet.
-                       // currently that can leave unresolved ONONAMEs in import-dot-ed packages in the wrong package
-                       if(debug['l'] < 2)
-                               typecheckinl(n);
-                       // NOTE: The space after %#S here is necessary for ld's export data parser.
-                       Bprint(bout, "\tfunc %#S %#hT { %#H }\n", s, t, n->inl);
-                       reexportdeplist(n->inl);
-               } else
-                       Bprint(bout, "\tfunc %#S %#hT\n", s, t);
-       } else
-               Bprint(bout, "\tvar %#S %#T\n", s, t);
-}
-
-static int
-methodbyname(const void *va, const void *vb)
-{
-       Type *a, *b;
-       
-       a = *(Type**)va;
-       b = *(Type**)vb;
-       return strcmp(a->sym->name, b->sym->name);
-}
-
-static void
-dumpexporttype(Type *t)
-{
-       Type *f;
-       Type **m;
-       int i, n;
-
-       if(t == T)
-               return;
-       if(t->printed || t == types[t->etype] || t == bytetype || t == runetype || t == errortype)
-               return;
-       t->printed = 1;
-
-       if(t->sym != S && t->etype != TFIELD)
-               dumppkg(t->sym->pkg);
-
-       dumpexporttype(t->type);
-       dumpexporttype(t->down);
-
-       if (t->sym == S || t->etype == TFIELD)
-               return;
-
-       n = 0;
-       for(f=t->method; f!=T; f=f->down) {     
-               dumpexporttype(f);
-               n++;
-       }
-
-       m = mal(n*sizeof m[0]);
-       i = 0;
-       for(f=t->method; f!=T; f=f->down)
-               m[i++] = f;
-       qsort(m, n, sizeof m[0], methodbyname);
-
-       Bprint(bout, "\ttype %#S %#lT\n", t->sym, t);
-       for(i=0; i<n; i++) {
-               f = m[i];
-               if(f->nointerface)
-                       Bprint(bout, "\t//go:nointerface\n");
-               if (f->type->nname && f->type->nname->inl) { // nname was set by caninl
-                       // when lazily typechecking inlined bodies, some re-exported ones may not have been typechecked yet.
-                       // currently that can leave unresolved ONONAMEs in import-dot-ed packages in the wrong package
-                       if(debug['l'] < 2)
-                               typecheckinl(f->type->nname);
-                       Bprint(bout, "\tfunc (%#T) %#hhS %#hT { %#H }\n", getthisx(f->type)->type, f->sym, f->type, f->type->nname->inl);
-                       reexportdeplist(f->type->nname->inl);
-               } else
-                       Bprint(bout, "\tfunc (%#T) %#hhS %#hT\n", getthisx(f->type)->type, f->sym, f->type);
-       }
-}
-
-static void
-dumpsym(Sym *s)
-{
-       if(s->flags & SymExported)
-               return;
-       s->flags |= SymExported;
-
-       if(s->def == N) {
-               yyerror("unknown export symbol: %S", s);
-               return;
-       }
-//     print("dumpsym %O %+S\n", s->def->op, s);
-       dumppkg(s->pkg);
-
-       switch(s->def->op) {
-       default:
-               yyerror("unexpected export symbol: %O %S", s->def->op, s);
-               break;
-
-       case OLITERAL:
-               dumpexportconst(s);
-               break;
-
-       case OTYPE:
-               if(s->def->type->etype == TFORW)
-                       yyerror("export of incomplete type %S", s);
-               else
-                       dumpexporttype(s->def->type);
-               break;
-
-       case ONAME:
-               dumpexportvar(s);
-               break;
-       }
-}
-
-void
-dumpexport(void)
-{
-       NodeList *l;
-       int32 i, lno;
-       Pkg *p;
-
-       lno = lineno;
-
-       Bprint(bout, "\n$$\npackage %s", localpkg->name);
-       if(safemode)
-               Bprint(bout, " safe");
-       Bprint(bout, "\n");
-
-       for(i=0; i<nelem(phash); i++)
-               for(p=phash[i]; p; p=p->link)
-                       if(p->direct)
-                               dumppkg(p);
-
-       for(l=exportlist; l; l=l->next) {
-               lineno = l->n->lineno;
-               dumpsym(l->n->sym);
-       }
-
-       Bprint(bout, "\n$$\n");
-       lineno = lno;
-}
-
-/*
- * import
- */
-
-/*
- * return the sym for ss, which should match lexical
- */
-Sym*
-importsym(Sym *s, int op)
-{
-       char *pkgstr;
-
-       if(s->def != N && s->def->op != op) {
-               pkgstr = smprint("during import \"%Z\"", importpkg->path);
-               redeclare(s, pkgstr);
-       }
-
-       // mark the symbol so it is not reexported
-       if(s->def == N) {
-               if(exportname(s->name) || initname(s->name))
-                       s->flags |= SymExport;
-               else
-                       s->flags |= SymPackage; // package scope
-       }
-       return s;
-}
-
-/*
- * return the type pkg.name, forward declaring if needed
- */
-Type*
-pkgtype(Sym *s)
-{
-       Type *t;
-
-       importsym(s, OTYPE);
-       if(s->def == N || s->def->op != OTYPE) {
-               t = typ(TFORW);
-               t->sym = s;
-               s->def = typenod(t);
-       }
-       if(s->def->type == T)
-               yyerror("pkgtype %S", s);
-       return s->def->type;
-}
-
-void
-importimport(Sym *s, Strlit *z)
-{
-       // Informational: record package name
-       // associated with import path, for use in
-       // human-readable messages.
-       Pkg *p;
-
-       if(isbadimport(z))
-               errorexit();
-       p = mkpkg(z);
-       if(p->name == nil) {
-               p->name = s->name;
-               pkglookup(s->name, nil)->npkg++;
-       } else if(strcmp(p->name, s->name) != 0)
-               yyerror("conflicting names %s and %s for package \"%Z\"", p->name, s->name, p->path);
-       
-       if(!incannedimport && myimportpath != nil && strcmp(z->s, myimportpath) == 0) {
-               yyerror("import \"%Z\": package depends on \"%Z\" (import cycle)", importpkg->path, z);
-               errorexit();
-       }
-}
-
-void
-importconst(Sym *s, Type *t, Node *n)
-{
-       Node *n1;
-
-       importsym(s, OLITERAL);
-       convlit(&n, t);
-
-       if(s->def != N)  // TODO: check if already the same.
-               return;
-
-       if(n->op != OLITERAL) {
-               yyerror("expression must be a constant");
-               return;
-       }
-
-       if(n->sym != S) {
-               n1 = nod(OXXX, N, N);
-               *n1 = *n;
-               n = n1;
-       }
-       n->orig = newname(s);
-       n->sym = s;
-       declare(n, PEXTERN);
-
-       if(debug['E'])
-               print("import const %S\n", s);
-}
-
-void
-importvar(Sym *s, Type *t)
-{
-       Node *n;
-
-       importsym(s, ONAME);
-       if(s->def != N && s->def->op == ONAME) {
-               if(eqtype(t, s->def->type))
-                       return;
-               yyerror("inconsistent definition for var %S during import\n\t%T (in \"%Z\")\n\t%T (in \"%Z\")", s, s->def->type, s->importdef->path, t, importpkg->path);
-       }
-       n = newname(s);
-       s->importdef = importpkg;
-       n->type = t;
-       declare(n, PEXTERN);
-
-       if(debug['E'])
-               print("import var %S %lT\n", s, t);
-}
-
-void
-importtype(Type *pt, Type *t)
-{
-       Node *n;
-
-       // override declaration in unsafe.go for Pointer.
-       // there is no way in Go code to define unsafe.Pointer
-       // so we have to supply it.
-       if(incannedimport &&
-          strcmp(importpkg->name, "unsafe") == 0 &&
-          strcmp(pt->nod->sym->name, "Pointer") == 0) {
-               t = types[TUNSAFEPTR];
-       }
-
-       if(pt->etype == TFORW) {
-               n = pt->nod;
-               copytype(pt->nod, t);
-               pt->nod = n;            // unzero nod
-               pt->sym->importdef = importpkg;
-               pt->sym->lastlineno = parserline();
-               declare(n, PEXTERN);
-               checkwidth(pt);
-       } else if(!eqtype(pt->orig, t))
-               yyerror("inconsistent definition for type %S during import\n\t%lT (in \"%Z\")\n\t%lT (in \"%Z\")", pt->sym, pt, pt->sym->importdef->path, t, importpkg->path);
-
-       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", thearch.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;
-                       Bprint(b, "#define %s__size %d\n", t->sym->name, (int)t->width);
-                       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/fmt.c b/src/cmd/gc/fmt.c
deleted file mode 100644 (file)
index bd0a29f..0000000
+++ /dev/null
@@ -1,1697 +0,0 @@
-// Copyright 2011 The Go Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style
-// license that can be found in the LICENSE file.
-
-#include       <u.h>
-#include       <libc.h>
-#include       "go.h"
-#include       "opnames.h"
-
-//
-// Format conversions
-//     %L int          Line numbers
-//
-//     %E int          etype values (aka 'Kind')
-//
-//     %O int          Node Opcodes
-//             Flags: "%#O": print go syntax. (automatic unless fmtmode == FDbg)
-//
-//     %J Node*        Node details
-//             Flags: "%hJ" suppresses things not relevant until walk.
-//
-//     %V Val*         Constant values
-//
-//     %S Sym*         Symbols
-//             Flags: +,- #: mode (see below)
-//                     "%hS"   unqualified identifier in any mode
-//                     "%hhS"  in export mode: unqualified identifier if exported, qualified if not
-//
-//     %T Type*        Types
-//             Flags: +,- #: mode (see below)
-//                     'l' definition instead of name.
-//                     'h' omit "func" and receiver in function types
-//                     'u' (only in -/Sym mode) print type identifiers wit package name instead of prefix.
-//
-//     %N Node*        Nodes
-//             Flags: +,- #: mode (see below)
-//                     'h' (only in +/debug mode) suppress recursion
-//                     'l' (only in Error mode) print "foo (type Bar)"
-//
-//     %H NodeList*    NodeLists
-//             Flags: those of %N
-//                     ','  separate items with ',' instead of ';'
-//
-//     %Z Strlit*      String literals
-//
-//   In mparith1.c:
-//      %B Mpint*      Big integers
-//     %F Mpflt*       Big floats
-//
-//   %S, %T and %N obey use the following flags to set the format mode:
-enum {
-       FErr,   //     error mode (default)
-       FDbg,   //     "%+N" debug mode
-       FExp,   //     "%#N" export mode
-       FTypeId,  //   "%-N" turning-types-into-symbols-mode: identical types give identical strings
-};
-static int fmtmode;
-static int fmtpkgpfx;  // %uT stickyness
-//
-// E.g. for %S:        %+S %#S %-S     print an identifier properly qualified for debug/export/internal mode.
-//
-// The mode flags  +, - and # are sticky, meaning they persist through
-// recursions of %N, %T and %S, but not the h and l flags.  The u flag is
-// sticky only on %T recursions and only used in %-/Sym mode.
-
-//
-// Useful format combinations:
-//
-//     %+N   %+H       multiline recursive debug dump of node/nodelist
-//     %+hN  %+hH      non recursive debug dump
-//
-//     %#N   %#T       export format
-//     %#lT            type definition instead of name
-//     %#hT            omit"func" and receiver in function signature
-//
-//     %lN             "foo (type Bar)" for error messages
-//
-//     %-T             type identifiers
-//     %-hT            type identifiers without "func" and arg names in type signatures (methodsym)
-//     %-uT            type identifiers with package name instead of prefix (typesym, dcommontype, typehash)
-//
-
-
-static int
-setfmode(unsigned long *flags)
-{
-       int fm;
-
-       fm = fmtmode;
-       if(*flags & FmtSign)
-               fmtmode = FDbg;
-       else if(*flags & FmtSharp)
-               fmtmode = FExp;
-       else if(*flags & FmtLeft)
-               fmtmode = FTypeId;
-
-       *flags &= ~(FmtSharp|FmtLeft|FmtSign);
-       return fm;
-}
-
-// Fmt "%L": Linenumbers
-static int
-Lconv(Fmt *fp)
-{
-       return linklinefmt(ctxt, fp);
-}
-
-static char*
-goopnames[] =
-{
-       [OADDR]         = "&",
-       [OADD]          = "+",
-       [OADDSTR]       = "+",
-       [OANDAND]       = "&&",
-       [OANDNOT]       = "&^",
-       [OAND]          = "&",
-       [OAPPEND]       = "append",
-       [OAS]           = "=",
-       [OAS2]          = "=",
-       [OBREAK]        = "break",
-       [OCALL]         = "function call",      // not actual syntax
-       [OCAP]          = "cap",
-       [OCASE]         = "case",
-       [OCLOSE]        = "close",
-       [OCOMPLEX]      = "complex",
-       [OCOM]          = "^",
-       [OCONTINUE]     = "continue",
-       [OCOPY]         = "copy",
-       [ODEC]          = "--",
-       [ODELETE]       = "delete",
-       [ODEFER]        = "defer",
-       [ODIV]          = "/",
-       [OEQ]           = "==",
-       [OFALL]         = "fallthrough",
-       [OFOR]          = "for",
-       [OGE]           = ">=",
-       [OGOTO]         = "goto",
-       [OGT]           = ">",
-       [OIF]           = "if",
-       [OIMAG]         = "imag",
-       [OINC]          = "++",
-       [OIND]          = "*",
-       [OLEN]          = "len",
-       [OLE]           = "<=",
-       [OLSH]          = "<<",
-       [OLT]           = "<",
-       [OMAKE]         = "make",
-       [OMINUS]        = "-",
-       [OMOD]          = "%",
-       [OMUL]          = "*",
-       [ONEW]          = "new",
-       [ONE]           = "!=",
-       [ONOT]          = "!",
-       [OOROR]         = "||",
-       [OOR]           = "|",
-       [OPANIC]        = "panic",
-       [OPLUS]         = "+",
-       [OPRINTN]       = "println",
-       [OPRINT]        = "print",
-       [ORANGE]        = "range",
-       [OREAL]         = "real",
-       [ORECV]         = "<-",
-       [ORECOVER]      = "recover",
-       [ORETURN]       = "return",
-       [ORSH]          = ">>",
-       [OSELECT]       = "select",
-       [OSEND]         = "<-",
-       [OSUB]          = "-",
-       [OSWITCH]       = "switch",
-       [OXOR]          = "^",
-};
-
-// Fmt "%O":  Node opcodes
-int
-Oconv(Fmt *fp)
-{
-       int o;
-
-       o = va_arg(fp->args, int);
-       if((fp->flags & FmtSharp) || fmtmode != FDbg)
-               if(o >= 0 && o < nelem(goopnames) && goopnames[o] != nil)
-                       return fmtstrcpy(fp, goopnames[o]);
-
-       if(o >= 0 && o < nelem(opnames) && opnames[o] != nil)
-               return fmtstrcpy(fp, opnames[o]);
-
-       return fmtprint(fp, "O-%d", o);
-}
-
-static const char* classnames[] = {
-       "Pxxx",
-       "PEXTERN",
-       "PAUTO",
-       "PPARAM",
-       "PPARAMOUT",
-       "PPARAMREF",
-       "PFUNC",
-};
-
-// Fmt "%J": Node details.
-static int
-Jconv(Fmt *fp)
-{
-       Node *n;
-       char *s;
-       int c;
-
-       n = va_arg(fp->args, Node*);
-
-       c = fp->flags&FmtShort;
-
-       if(!c && n->ullman != 0)
-               fmtprint(fp, " u(%d)", n->ullman);
-
-       if(!c && n->addable != 0)
-               fmtprint(fp, " a(%d)", n->addable);
-
-       if(!c && n->vargen != 0)
-               fmtprint(fp, " g(%d)", n->vargen);
-
-       if(n->lineno != 0)
-               fmtprint(fp, " l(%d)", n->lineno);
-
-       if(!c && n->xoffset != BADWIDTH)
-               fmtprint(fp, " x(%lld%+lld)", n->xoffset, n->stkdelta);
-
-       if(n->class != 0) {
-               s = "";
-               if(n->class & PHEAP) s = ",heap";
-               if((n->class & ~PHEAP) < nelem(classnames))
-                       fmtprint(fp, " class(%s%s)", classnames[n->class&~PHEAP], s);
-               else
-                       fmtprint(fp, " class(%d?%s)", n->class&~PHEAP, s);
-       }
-
-       if(n->colas != 0)
-               fmtprint(fp, " colas(%d)", n->colas);
-
-       if(n->funcdepth != 0)
-               fmtprint(fp, " f(%d)", n->funcdepth);
-
-       switch(n->esc) {
-       case EscUnknown:
-               break;
-       case EscHeap:
-               fmtprint(fp, " esc(h)");
-               break;
-       case EscScope:
-               fmtprint(fp, " esc(s)");
-               break;
-       case EscNone:
-               fmtprint(fp, " esc(no)");
-               break;
-       case EscNever:
-               if(!c)
-                       fmtprint(fp, " esc(N)");
-               break;
-       default:
-               fmtprint(fp, " esc(%d)", n->esc);
-               break;
-       }
-
-       if(n->escloopdepth)
-               fmtprint(fp, " ld(%d)", n->escloopdepth);
-
-       if(!c && n->typecheck != 0)
-               fmtprint(fp, " tc(%d)", n->typecheck);
-
-       if(!c && n->dodata != 0)
-               fmtprint(fp, " dd(%d)", n->dodata);
-
-       if(n->isddd != 0)
-               fmtprint(fp, " isddd(%d)", n->isddd);
-
-       if(n->implicit != 0)
-               fmtprint(fp, " implicit(%d)", n->implicit);
-
-       if(n->embedded != 0)
-               fmtprint(fp, " embedded(%d)", n->embedded);
-
-       if(n->addrtaken != 0)
-               fmtprint(fp, " addrtaken");
-
-       if(n->assigned != 0)
-               fmtprint(fp, " assigned");
-
-       if(!c && n->used != 0)
-               fmtprint(fp, " used(%d)", n->used);
-       return 0;
-}
-
-// Fmt "%V": Values
-static int
-Vconv(Fmt *fp)
-{
-       Val *v;
-       vlong x;
-
-       v = va_arg(fp->args, Val*);
-
-       switch(v->ctype) {
-       case CTINT:
-               if((fp->flags & FmtSharp) || fmtmode == FExp)
-                       return fmtprint(fp, "%#B", v->u.xval);
-               return fmtprint(fp, "%B", v->u.xval);
-       case CTRUNE:
-               x = mpgetfix(v->u.xval);
-               if(' ' <= x && x < 0x80 && x != '\\' && x != '\'')
-                       return fmtprint(fp, "'%c'", (int)x);
-               if(0 <= x && x < (1<<16))
-                       return fmtprint(fp, "'\\u%04ux'", (int)x);
-               if(0 <= x && x <= Runemax)
-                       return fmtprint(fp, "'\\U%08llux'", x);
-               return fmtprint(fp, "('\\x00' + %B)", v->u.xval);
-       case CTFLT:
-               if((fp->flags & FmtSharp) || fmtmode == FExp)
-                       return fmtprint(fp, "%F", v->u.fval);
-               return fmtprint(fp, "%#F", v->u.fval);
-       case CTCPLX:
-               if((fp->flags & FmtSharp) || fmtmode == FExp)
-                       return fmtprint(fp, "(%F+%Fi)", &v->u.cval->real, &v->u.cval->imag);
-               if(mpcmpfltc(&v->u.cval->real, 0) == 0)
-                       return fmtprint(fp, "%#Fi", &v->u.cval->imag);
-               if(mpcmpfltc(&v->u.cval->imag, 0) == 0)
-                       return fmtprint(fp, "%#F", &v->u.cval->real);
-               if(mpcmpfltc(&v->u.cval->imag, 0) < 0)
-                       return fmtprint(fp, "(%#F%#Fi)", &v->u.cval->real, &v->u.cval->imag);
-               return fmtprint(fp, "(%#F+%#Fi)", &v->u.cval->real, &v->u.cval->imag);
-       case CTSTR:
-               return fmtprint(fp, "\"%Z\"", v->u.sval);
-       case CTBOOL:
-               if( v->u.bval)
-                       return fmtstrcpy(fp, "true");
-               return fmtstrcpy(fp, "false");
-       case CTNIL:
-               return fmtstrcpy(fp, "nil");
-       }
-       return fmtprint(fp, "<ctype=%d>", v->ctype);
-}
-
-// Fmt "%Z": escaped string literals
-static int
-Zconv(Fmt *fp)
-{
-       Rune r;
-       Strlit *sp;
-       char *s, *se;
-       int n;
-
-       sp = va_arg(fp->args, Strlit*);
-       if(sp == nil)
-               return fmtstrcpy(fp, "<nil>");
-
-       s = sp->s;
-       se = s + sp->len;
-
-       // NOTE: Keep in sync with ../ld/go.c:/^Zconv.
-       while(s < se) {
-               n = chartorune(&r, s);
-               s += n;
-               switch(r) {
-               case Runeerror:
-                       if(n == 1) {
-                               fmtprint(fp, "\\x%02x", (uchar)*(s-1));
-                               break;
-                       }
-                       // fall through
-               default:
-                       if(r < ' ') {
-                               fmtprint(fp, "\\x%02x", r);
-                               break;
-                       }
-                       fmtrune(fp, r);
-                       break;
-               case '\t':
-                       fmtstrcpy(fp, "\\t");
-                       break;
-               case '\n':
-                       fmtstrcpy(fp, "\\n");
-                       break;
-               case '\"':
-               case '\\':
-                       fmtrune(fp, '\\');
-                       fmtrune(fp, r);
-                       break;
-               case 0xFEFF: // BOM, basically disallowed in source code
-                       fmtstrcpy(fp, "\\uFEFF");
-                       break;
-               }
-       }
-       return 0;
-}
-
-/*
-s%,%,\n%g
-s%\n+%\n%g
-s%^[   ]*T%%g
-s%,.*%%g
-s%.+%  [T&]            = "&",%g
-s%^    ........*\]%&~%g
-s%~    %%g
-*/
-
-static char*
-etnames[] =
-{
-       [TINT]          = "INT",
-       [TUINT]         = "UINT",
-       [TINT8]         = "INT8",
-       [TUINT8]        = "UINT8",
-       [TINT16]        = "INT16",
-       [TUINT16]       = "UINT16",
-       [TINT32]        = "INT32",
-       [TUINT32]       = "UINT32",
-       [TINT64]        = "INT64",
-       [TUINT64]       = "UINT64",
-       [TUINTPTR]      = "UINTPTR",
-       [TFLOAT32]      = "FLOAT32",
-       [TFLOAT64]      = "FLOAT64",
-       [TCOMPLEX64]    = "COMPLEX64",
-       [TCOMPLEX128]   = "COMPLEX128",
-       [TBOOL]         = "BOOL",
-       [TPTR32]        = "PTR32",
-       [TPTR64]        = "PTR64",
-       [TFUNC]         = "FUNC",
-       [TARRAY]        = "ARRAY",
-       [TSTRUCT]       = "STRUCT",
-       [TCHAN]         = "CHAN",
-       [TMAP]          = "MAP",
-       [TINTER]        = "INTER",
-       [TFORW]         = "FORW",
-       [TFIELD]        = "FIELD",
-       [TSTRING]       = "STRING",
-       [TANY]          = "ANY",
-};
-
-// Fmt "%E": etype
-static int
-Econv(Fmt *fp)
-{
-       int et;
-
-       et = va_arg(fp->args, int);
-       if(et >= 0 && et < nelem(etnames) && etnames[et] != nil)
-               return fmtstrcpy(fp, etnames[et]);
-       return fmtprint(fp, "E-%d", et);
-}
-
-// Fmt "%S": syms
-static int
-symfmt(Fmt *fp, Sym *s)
-{
-       char *p;
-
-       if(s->pkg && !(fp->flags&FmtShort)) {
-               switch(fmtmode) {
-               case FErr:      // This is for the user
-                       if(s->pkg == localpkg)
-                               return fmtstrcpy(fp, s->name);
-                       // If the name was used by multiple packages, display the full path,
-                       if(s->pkg->name && pkglookup(s->pkg->name, nil)->npkg > 1)
-                               return fmtprint(fp, "\"%Z\".%s", s->pkg->path, s->name);
-                       return fmtprint(fp, "%s.%s", s->pkg->name, s->name);
-               case FDbg:
-                       return fmtprint(fp, "%s.%s", s->pkg->name, s->name);
-               case FTypeId:
-                       if(fp->flags&FmtUnsigned)
-                               return fmtprint(fp, "%s.%s", s->pkg->name, s->name);    // dcommontype, typehash
-                       return fmtprint(fp, "%s.%s", s->pkg->prefix, s->name);  // (methodsym), typesym, weaksym
-               case FExp:
-                       if(s->name && s->name[0] == '.')
-                               fatal("exporting synthetic symbol %s", s->name);
-                       if(s->pkg != builtinpkg)
-                               return fmtprint(fp, "@\"%Z\".%s", s->pkg->path, s->name);
-               }
-       }
-
-       if(fp->flags&FmtByte) {  // FmtByte (hh) implies FmtShort (h)
-               // skip leading "type." in method name
-               p = utfrrune(s->name, '.');
-               if(p)
-                       p++;
-               else
-                       p = s->name;
-
-               // exportname needs to see the name without the prefix too.
-               if((fmtmode == FExp && !exportname(p)) || fmtmode == FDbg)
-                       return fmtprint(fp, "@\"%Z\".%s", s->pkg->path, p);
-
-               return fmtstrcpy(fp, p);
-       }
-
-       return fmtstrcpy(fp, s->name);
-}
-
-static char*
-basicnames[] =
-{
-       [TINT]          = "int",
-       [TUINT]         = "uint",
-       [TINT8]         = "int8",
-       [TUINT8]        = "uint8",
-       [TINT16]        = "int16",
-       [TUINT16]       = "uint16",
-       [TINT32]        = "int32",
-       [TUINT32]       = "uint32",
-       [TINT64]        = "int64",
-       [TUINT64]       = "uint64",
-       [TUINTPTR]      = "uintptr",
-       [TFLOAT32]      = "float32",
-       [TFLOAT64]      = "float64",
-       [TCOMPLEX64]    = "complex64",
-       [TCOMPLEX128]   = "complex128",
-       [TBOOL]         = "bool",
-       [TANY]          = "any",
-       [TSTRING]       = "string",
-       [TNIL]          = "nil",
-       [TIDEAL]        = "untyped number",
-       [TBLANK]        = "blank",
-};
-
-static int
-typefmt(Fmt *fp, Type *t)
-{
-       Type *t1;
-       Sym *s;
-
-       if(t == T)
-               return fmtstrcpy(fp, "<T>");
-
-       if (t == bytetype || t == runetype) {
-               // in %-T mode collapse rune and byte with their originals.
-               if(fmtmode != FTypeId)
-                       return fmtprint(fp, "%hS", t->sym);
-               t = types[t->etype];
-       }
-
-       if(t == errortype)
-               return fmtstrcpy(fp, "error");
-
-       // Unless the 'l' flag was specified, if the type has a name, just print that name.
-       if(!(fp->flags&FmtLong) && t->sym && t->etype != TFIELD && t != types[t->etype]) {
-               switch(fmtmode) {
-               case FTypeId:
-                       if(fp->flags&FmtShort) {
-                               if(t->vargen)
-                                       return fmtprint(fp, "%hS·%d", t->sym, t->vargen);
-                               return fmtprint(fp, "%hS", t->sym);
-                       }
-                       if(fp->flags&FmtUnsigned)
-                               return fmtprint(fp, "%uS", t->sym);
-                       // fallthrough
-               case FExp:
-                       if(t->sym->pkg == localpkg && t->vargen)
-                               return fmtprint(fp, "%S·%d", t->sym, t->vargen);
-                       break;
-               }
-               return fmtprint(fp, "%S", t->sym);
-       }
-
-       if(t->etype < nelem(basicnames) && basicnames[t->etype] != nil) {
-               if(fmtmode == FErr && (t == idealbool || t == idealstring))
-                       fmtstrcpy(fp, "untyped ");
-               return fmtstrcpy(fp, basicnames[t->etype]);
-       }
-
-       if(fmtmode == FDbg)
-               fmtprint(fp, "%E-", t->etype);
-
-       switch(t->etype) {
-       case TPTR32:
-       case TPTR64:
-               if(fmtmode == FTypeId && (fp->flags&FmtShort))
-                       return fmtprint(fp, "*%hT", t->type);
-               return fmtprint(fp, "*%T", t->type);
-
-       case TARRAY:
-               if(t->bound >= 0)
-                       return fmtprint(fp, "[%lld]%T", t->bound, t->type);
-               if(t->bound == -100)
-                       return fmtprint(fp, "[...]%T", t->type);
-               return fmtprint(fp, "[]%T", t->type);
-
-       case TCHAN:
-               switch(t->chan) {
-               case Crecv:
-                       return fmtprint(fp, "<-chan %T", t->type);
-               case Csend:
-                       return fmtprint(fp, "chan<- %T", t->type);
-               }
-
-               if(t->type != T && t->type->etype == TCHAN && t->type->sym == S && t->type->chan == Crecv)
-                       return fmtprint(fp, "chan (%T)", t->type);
-               return fmtprint(fp, "chan %T", t->type);
-
-       case TMAP:
-               return fmtprint(fp, "map[%T]%T", t->down, t->type);
-
-       case TINTER:
-               fmtstrcpy(fp, "interface {");
-               for(t1=t->type; t1!=T; t1=t1->down)
-                       if(exportname(t1->sym->name)) {
-                               if(t1->down)
-                                       fmtprint(fp, " %hS%hT;", t1->sym, t1->type);
-                               else
-                                       fmtprint(fp, " %hS%hT ", t1->sym, t1->type);
-                       } else {
-                               // non-exported method names must be qualified
-                               if(t1->down)
-                                       fmtprint(fp, " %uS%hT;", t1->sym, t1->type);
-                               else
-                                       fmtprint(fp, " %uS%hT ", t1->sym, t1->type);
-                       }
-               fmtstrcpy(fp, "}");
-               return 0;
-
-       case TFUNC:
-               if(fp->flags & FmtShort) {
-                       fmtprint(fp, "%T", getinargx(t));
-               } else {
-                       if(t->thistuple)
-                               fmtprint(fp, "method%T func%T", getthisx(t), getinargx(t));
-                       else
-                               fmtprint(fp, "func%T", getinargx(t));
-               }
-               switch(t->outtuple) {
-               case 0:
-                       break;
-               case 1:
-                       if(fmtmode != FExp) {
-                               fmtprint(fp, " %T", getoutargx(t)->type->type);  // struct->field->field's type
-                               break;
-                       }
-               default:
-                       fmtprint(fp, " %T", getoutargx(t));
-                       break;
-               }
-               return 0;
-
-       case TSTRUCT:
-               // Format the bucket struct for map[x]y as map.bucket[x]y.
-               // This avoids a recursive print that generates very long names.
-               if(t->map != T) {
-                       if(t->map->bucket == t) {
-                               return fmtprint(fp, "map.bucket[%T]%T", t->map->down, t->map->type);
-                       }
-                       if(t->map->hmap == t) {
-                               return fmtprint(fp, "map.hdr[%T]%T", t->map->down, t->map->type);
-                       }
-                       if(t->map->hiter == t) {
-                               return fmtprint(fp, "map.iter[%T]%T", t->map->down, t->map->type);
-                       }
-                       yyerror("unknown internal map type");
-               }
-
-               if(t->funarg) {
-                       fmtstrcpy(fp, "(");
-                       if(fmtmode == FTypeId || fmtmode == FErr) {     // no argument names on function signature, and no "noescape"/"nosplit" tags
-                               for(t1=t->type; t1!=T; t1=t1->down)
-                                       if(t1->down)
-                                               fmtprint(fp, "%hT, ", t1);
-                                       else
-                                               fmtprint(fp, "%hT", t1);
-                       } else {
-                               for(t1=t->type; t1!=T; t1=t1->down)
-                                       if(t1->down)
-                                               fmtprint(fp, "%T, ", t1);
-                                       else
-                                               fmtprint(fp, "%T", t1);
-                       }
-                       fmtstrcpy(fp, ")");
-               } else {
-                       fmtstrcpy(fp, "struct {");
-                       for(t1=t->type; t1!=T; t1=t1->down)
-                               if(t1->down)
-                                       fmtprint(fp, " %lT;", t1);
-                               else
-                                       fmtprint(fp, " %lT ", t1);
-                       fmtstrcpy(fp, "}");
-               }
-               return 0;
-
-       case TFIELD:
-               if(!(fp->flags&FmtShort)) {
-                       s = t->sym;
-
-                       // Take the name from the original, lest we substituted it with ~r%d or ~b%d.
-                       // ~r%d is a (formerly) unnamed result.
-                       if ((fmtmode == FErr || fmtmode == FExp) && t->nname != N) {
-                               if(t->nname->orig != N) {
-                                       s = t->nname->orig->sym;
-                                       if(s != S && s->name[0] == '~') {
-                                               if(s->name[1] == 'r') // originally an unnamed result
-                                                       s = S;
-                                               else if(s->name[1] == 'b') // originally the blank identifier _
-                                                       s = lookup("_");
-                                       }
-                               } else 
-                                       s = S;
-                       }
-                       
-                       if(s != S && !t->embedded) {
-                               if(t->funarg)
-                                       fmtprint(fp, "%N ", t->nname);
-                               else if(fp->flags&FmtLong)
-                                       fmtprint(fp, "%hhS ", s);  // qualify non-exported names (used on structs, not on funarg)
-                               else 
-                                       fmtprint(fp, "%S ", s);
-                       } else if(fmtmode == FExp) {
-                               // TODO(rsc) this breaks on the eliding of unused arguments in the backend
-                               // when this is fixed, the special case in dcl.c checkarglist can go.
-                               //if(t->funarg)
-                               //      fmtstrcpy(fp, "_ ");
-                               //else
-                               if(t->embedded && s->pkg != nil && s->pkg->path->len > 0)
-                                       fmtprint(fp, "@\"%Z\".? ", s->pkg->path);
-                               else
-                                       fmtstrcpy(fp, "? ");
-                       }
-               }
-
-               if(t->isddd)
-                       fmtprint(fp, "...%T", t->type->type);
-               else
-                       fmtprint(fp, "%T", t->type);
-
-               if(!(fp->flags&FmtShort) && t->note)
-                       fmtprint(fp, " \"%Z\"", t->note);
-               return 0;
-
-       case TFORW:
-               if(t->sym)
-                       return fmtprint(fp, "undefined %S", t->sym);
-               return fmtstrcpy(fp, "undefined");
-
-       case TUNSAFEPTR:
-               if(fmtmode == FExp)
-                       return fmtprint(fp, "@\"unsafe\".Pointer");
-               return fmtprint(fp, "unsafe.Pointer");
-       }
-
-       if(fmtmode == FExp)
-               fatal("missing %E case during export", t->etype);
-       // Don't know how to handle - fall back to detailed prints.
-       return fmtprint(fp, "%E <%S> %T", t->etype, t->sym, t->type);
-}
-
-// Statements which may be rendered with a simplestmt as init.
-static int
-stmtwithinit(int op)
-{
-       switch(op) {
-       case OIF:
-       case OFOR:
-       case OSWITCH:
-               return 1;
-       }
-       return 0;
-}
-
-static int
-stmtfmt(Fmt *f, Node *n)
-{
-       int complexinit, simpleinit, extrablock;
-
-       // some statements allow for an init, but at most one,
-       // but we may have an arbitrary number added, eg by typecheck
-       // and inlining.  If it doesn't fit the syntax, emit an enclosing
-       // block starting with the init statements.
-
-       // if we can just say "for" n->ninit; ... then do so
-       simpleinit = n->ninit && !n->ninit->next && !n->ninit->n->ninit && stmtwithinit(n->op);
-       // otherwise, print the inits as separate statements
-       complexinit = n->ninit && !simpleinit && (fmtmode != FErr);
-       // but if it was for if/for/switch, put in an extra surrounding block to limit the scope
-       extrablock = complexinit && stmtwithinit(n->op);
-
-       if(extrablock)
-               fmtstrcpy(f, "{");
-
-       if(complexinit)
-               fmtprint(f, " %H; ", n->ninit);
-
-       switch(n->op){
-       case ODCL:
-               if(fmtmode == FExp) {
-                       switch(n->left->class&~PHEAP) {
-                       case PPARAM:
-                       case PPARAMOUT:
-                       case PAUTO:
-                               fmtprint(f, "var %N %T", n->left, n->left->type);
-                               goto ret;
-                       }
-               }                       
-               fmtprint(f, "var %S %T", n->left->sym, n->left->type);
-               break;
-
-       case ODCLFIELD:
-               if(n->left)
-                       fmtprint(f, "%N %N", n->left, n->right);
-               else
-                       fmtprint(f, "%N", n->right);
-               break;
-
-       case OAS:
-               // Don't export "v = <N>" initializing statements, hope they're always 
-               // preceded by the DCL which will be re-parsed and typecheck to reproduce
-               // the "v = <N>" again.
-               if(fmtmode == FExp && n->right == N)
-                       break;
-
-               if(n->colas && !complexinit)
-                       fmtprint(f, "%N := %N", n->left, n->right);
-               else
-                       fmtprint(f, "%N = %N", n->left, n->right);
-               break;
-
-       case OASOP:
-               if(n->implicit) {
-                       if(n->etype == OADD)
-                               fmtprint(f, "%N++", n->left);
-                       else
-                               fmtprint(f, "%N--", n->left);
-                       break;
-               }
-               fmtprint(f, "%N %#O= %N", n->left, n->etype, n->right);
-               break;
-
-       case OAS2:
-               if(n->colas && !complexinit) {
-                       fmtprint(f, "%,H := %,H", n->list, n->rlist);
-                       break;
-               }
-               // fallthrough
-       case OAS2DOTTYPE:
-       case OAS2FUNC:
-       case OAS2MAPR:
-       case OAS2RECV:
-               fmtprint(f, "%,H = %,H", n->list, n->rlist);
-               break;
-
-       case ORETURN:
-               fmtprint(f, "return %,H", n->list);
-               break;
-
-       case ORETJMP:
-               fmtprint(f, "retjmp %S", n->sym);
-               break;
-       
-       case OPROC:
-               fmtprint(f, "go %N", n->left);
-               break;
-
-       case ODEFER:
-               fmtprint(f, "defer %N", n->left);
-               break;
-
-       case OIF:
-               if(simpleinit)
-                       fmtprint(f, "if %N; %N { %H }", n->ninit->n, n->ntest, n->nbody);
-               else
-                       fmtprint(f, "if %N { %H }", n->ntest, n->nbody);
-               if(n->nelse)
-                       fmtprint(f, " else { %H }", n->nelse);
-               break;
-
-       case OFOR:
-               if(fmtmode == FErr) {   // TODO maybe only if FmtShort, same below
-                       fmtstrcpy(f, "for loop");
-                       break;
-               }
-
-               fmtstrcpy(f, "for");
-               if(simpleinit)
-                       fmtprint(f, " %N;", n->ninit->n);
-               else if(n->nincr)
-                       fmtstrcpy(f, " ;");
-
-               if(n->ntest)
-                       fmtprint(f, " %N", n->ntest);
-
-               if(n->nincr)
-                       fmtprint(f, "; %N", n->nincr);
-               else if(simpleinit)
-                       fmtstrcpy(f, ";");
-
-
-               fmtprint(f, " { %H }", n->nbody);
-               break;
-
-       case ORANGE:
-               if(fmtmode == FErr) {
-                       fmtstrcpy(f, "for loop");
-                       break;
-               }
-               
-               if(n->list == nil) {
-                       fmtprint(f, "for range %N { %H }", n->right, n->nbody);
-                       break;
-               }
-               fmtprint(f, "for %,H = range %N { %H }", n->list, n->right, n->nbody);
-               break;
-
-       case OSELECT:
-       case OSWITCH:
-               if(fmtmode == FErr) {
-                       fmtprint(f, "%O statement", n->op);
-                       break;
-               }
-
-               fmtprint(f, "%#O", n->op);
-               if(simpleinit)
-                       fmtprint(f, " %N;", n->ninit->n);
-               if(n->ntest)
-                       fmtprint(f, "%N", n->ntest);
-
-               fmtprint(f, " { %H }", n->list);
-               break;
-
-       case OCASE:
-       case OXCASE:
-               if(n->list)
-                       fmtprint(f, "case %,H: %H", n->list, n->nbody);
-               else
-                       fmtprint(f, "default: %H", n->nbody);
-               break;
-
-       case OBREAK:
-       case OCONTINUE:
-       case OGOTO:
-       case OFALL:
-       case OXFALL:
-               if(n->left)
-                       fmtprint(f, "%#O %N", n->op, n->left);
-               else
-                       fmtprint(f, "%#O", n->op);
-               break;
-
-       case OEMPTY:
-               break;
-
-       case OLABEL:
-               fmtprint(f, "%N: ", n->left);
-               break;
-         
-       }
-ret:
-
-       if(extrablock)
-               fmtstrcpy(f, "}");
-
-       return 0;
-}
-
-
-static int opprec[] = {
-       [OAPPEND] = 8,
-       [OARRAYBYTESTR] = 8,
-       [OARRAYLIT] = 8,
-       [OARRAYRUNESTR] = 8,
-       [OCALLFUNC] = 8,
-       [OCALLINTER] = 8,
-       [OCALLMETH] = 8,
-       [OCALL] = 8,
-       [OCAP] = 8,
-       [OCLOSE] = 8,
-       [OCONVIFACE] = 8,
-       [OCONVNOP] = 8,
-       [OCONV] = 8,
-       [OCOPY] = 8,
-       [ODELETE] = 8,
-       [OLEN] = 8,
-       [OLITERAL] = 8,
-       [OMAKESLICE] = 8,
-       [OMAKE] = 8,
-       [OMAPLIT] = 8,
-       [ONAME] = 8,
-       [ONEW] = 8,
-       [ONONAME] = 8,
-       [OPACK] = 8,
-       [OPANIC] = 8,
-       [OPAREN] = 8,
-       [OPRINTN] = 8,
-       [OPRINT] = 8,
-       [ORUNESTR] = 8,
-       [OSTRARRAYBYTE] = 8,
-       [OSTRARRAYRUNE] = 8,
-       [OSTRUCTLIT] = 8,
-       [OTARRAY] = 8,
-       [OTCHAN] = 8,
-       [OTFUNC] = 8,
-       [OTINTER] = 8,
-       [OTMAP] = 8,
-       [OTSTRUCT] = 8,
-
-       [OINDEXMAP] = 8,
-       [OINDEX] = 8,
-       [OSLICE] = 8,
-       [OSLICESTR] = 8,
-       [OSLICEARR] = 8,
-       [OSLICE3] = 8,
-       [OSLICE3ARR] = 8,
-       [ODOTINTER] = 8,
-       [ODOTMETH] = 8,
-       [ODOTPTR] = 8,
-       [ODOTTYPE2] = 8,
-       [ODOTTYPE] = 8,
-       [ODOT] = 8,
-       [OXDOT] = 8,
-       [OCALLPART] = 8,
-
-       [OPLUS] = 7,
-       [ONOT] = 7,
-       [OCOM] = 7,
-       [OMINUS] = 7,
-       [OADDR] = 7,
-       [OIND] = 7,
-       [ORECV] = 7,
-
-       [OMUL] = 6,
-       [ODIV] = 6,
-       [OMOD] = 6,
-       [OLSH] = 6,
-       [ORSH] = 6,
-       [OAND] = 6,
-       [OANDNOT] = 6,
-
-       [OADD] = 5,
-       [OSUB] = 5,
-       [OOR] = 5,
-       [OXOR] = 5,
-
-       [OEQ] = 4,
-       [OLT] = 4,
-       [OLE] = 4,
-       [OGE] = 4,
-       [OGT] = 4,
-       [ONE] = 4,
-       [OCMPSTR] = 4,
-       [OCMPIFACE] = 4,
-
-       [OSEND] = 3,
-       [OANDAND] = 2,
-       [OOROR] = 1,
-
-       // Statements handled by stmtfmt
-       [OAS] = -1,
-       [OAS2] = -1,
-       [OAS2DOTTYPE] = -1,
-       [OAS2FUNC] = -1,
-       [OAS2MAPR] = -1,
-       [OAS2RECV] = -1,
-       [OASOP] = -1,
-       [OBREAK] = -1,
-       [OCASE] = -1,
-       [OCONTINUE] = -1,
-       [ODCL] = -1,
-       [ODCLFIELD] = -1,
-       [ODEFER] = -1,
-       [OEMPTY] = -1,
-       [OFALL] = -1,
-       [OFOR] = -1,
-       [OGOTO] = -1,
-       [OIF] = -1,
-       [OLABEL] = -1,
-       [OPROC] = -1,
-       [ORANGE] = -1,
-       [ORETURN] = -1,
-       [OSELECT] = -1,
-       [OSWITCH] = -1,
-       [OXCASE] = -1,
-       [OXFALL] = -1,
-
-       [OEND] = 0
-};
-
-static int
-exprfmt(Fmt *f, Node *n, int prec)
-{
-       int nprec;
-       int ptrlit;
-       NodeList *l;
-
-       while(n && n->implicit && (n->op == OIND || n->op == OADDR))
-               n = n->left;
-
-       if(n == N)
-               return fmtstrcpy(f, "<N>");
-
-       nprec = opprec[n->op];
-       if(n->op == OTYPE && n->sym != S)
-               nprec = 8;
-
-       if(prec > nprec)
-               return fmtprint(f, "(%N)", n);
-
-       switch(n->op) {
-       case OPAREN:
-               return fmtprint(f, "(%N)", n->left);
-
-       case ODDDARG:
-               return fmtprint(f, "... argument");
-
-       case OREGISTER:
-               return fmtprint(f, "%R", n->val.u.reg);
-
-       case OLITERAL:  // this is a bit of a mess
-               if(fmtmode == FErr && n->sym != S)
-                       return fmtprint(f, "%S", n->sym);
-               if(n->val.ctype == CTNIL && n->orig != N && n->orig != n)
-                       return exprfmt(f, n->orig, prec);
-               if(n->type != T && n->type != types[n->type->etype] && n->type != idealbool && n->type != idealstring) {
-                       // Need parens when type begins with what might
-                       // be misinterpreted as a unary operator: * or <-.
-                       if(isptr[n->type->etype] || (n->type->etype == TCHAN && n->type->chan == Crecv))
-                               return fmtprint(f, "(%T)(%V)", n->type, &n->val);
-                       else 
-                               return fmtprint(f, "%T(%V)", n->type, &n->val);
-               }
-               return fmtprint(f, "%V", &n->val);
-
-       case ONAME:
-               // Special case: name used as local variable in export.
-               // _ becomes ~b%d internally; print as _ for export
-               if(fmtmode == FExp && n->sym && n->sym->name[0] == '~' && n->sym->name[1] == 'b')
-                       return fmtprint(f, "_");
-               if(fmtmode == FExp && n->sym && !isblank(n) && n->vargen > 0)
-                       return fmtprint(f, "%S·%d", n->sym, n->vargen);
-
-               // Special case: explicit name of func (*T) method(...) is turned into pkg.(*T).method,
-               // but for export, this should be rendered as (*pkg.T).meth.
-               // These nodes have the special property that they are names with a left OTYPE and a right ONAME.
-               if(fmtmode == FExp && n->left && n->left->op == OTYPE && n->right && n->right->op == ONAME) {
-                       if(isptr[n->left->type->etype])
-                               return fmtprint(f, "(%T).%hhS", n->left->type, n->right->sym);
-                       else
-                               return fmtprint(f, "%T.%hhS", n->left->type, n->right->sym);
-               }
-               //fallthrough
-       case OPACK:
-       case ONONAME:
-               return fmtprint(f, "%S", n->sym);
-
-       case OTYPE:
-               if(n->type == T && n->sym != S)
-                       return fmtprint(f, "%S", n->sym);
-               return fmtprint(f, "%T", n->type);
-
-       case OTARRAY:
-               if(n->left)
-                       return fmtprint(f, "[]%N", n->left);
-               return fmtprint(f, "[]%N", n->right);  // happens before typecheck
-
-       case OTMAP:
-               return fmtprint(f, "map[%N]%N", n->left, n->right);
-
-       case OTCHAN:
-               switch(n->etype) {
-               case Crecv:
-                       return fmtprint(f, "<-chan %N", n->left);
-               case Csend:
-                       return fmtprint(f, "chan<- %N", n->left);
-               default:
-                       if(n->left != N && n->left->op == OTCHAN && n->left->sym == S && n->left->etype == Crecv)
-                               return fmtprint(f, "chan (%N)", n->left);
-                       else
-                               return fmtprint(f, "chan %N", n->left);
-               }
-
-       case OTSTRUCT:
-               return fmtprint(f, "<struct>");
-
-       case OTINTER:
-               return fmtprint(f, "<inter>");
-
-       case OTFUNC:
-               return fmtprint(f, "<func>");
-
-       case OCLOSURE:
-               if(fmtmode == FErr)
-                       return fmtstrcpy(f, "func literal");
-               if(n->nbody)
-                       return fmtprint(f, "%T { %H }", n->type, n->nbody);
-               return fmtprint(f, "%T { %H }", n->type, n->closure->nbody);
-
-       case OCOMPLIT:
-               ptrlit = n->right != N && n->right->implicit && n->right->type && isptr[n->right->type->etype];
-               if(fmtmode == FErr) {
-                       if(n->right != N && n->right->type != T && !n->implicit) {
-                               if(ptrlit)
-                                       return fmtprint(f, "&%T literal", n->right->type->type);
-                               else
-                                       return fmtprint(f, "%T literal", n->right->type);
-                       }
-                       return fmtstrcpy(f, "composite literal");
-               }
-               if(fmtmode == FExp && ptrlit)
-                       // typecheck has overwritten OIND by OTYPE with pointer type.
-                       return fmtprint(f, "(&%T{ %,H })", n->right->type->type, n->list);
-               return fmtprint(f, "(%N{ %,H })", n->right, n->list);
-
-       case OPTRLIT:
-               if(fmtmode == FExp && n->left->implicit)
-                       return fmtprint(f, "%N", n->left);
-               return fmtprint(f, "&%N", n->left);
-
-       case OSTRUCTLIT:
-               if(fmtmode == FExp) {   // requires special handling of field names
-                       if(n->implicit)
-                               fmtstrcpy(f, "{");
-                       else
-                               fmtprint(f, "(%T{", n->type);
-                       for(l=n->list; l; l=l->next) {
-                               fmtprint(f, " %hhS:%N", l->n->left->sym, l->n->right);
-
-                               if(l->next)
-                                       fmtstrcpy(f, ",");
-                               else
-                                       fmtstrcpy(f, " ");
-                       }
-                       if(!n->implicit)
-                               return fmtstrcpy(f, "})");
-                       return fmtstrcpy(f, "}");
-               }
-               // fallthrough
-
-       case OARRAYLIT:
-       case OMAPLIT:
-               if(fmtmode == FErr)
-                       return fmtprint(f, "%T literal", n->type);
-               if(fmtmode == FExp && n->implicit)
-                       return fmtprint(f, "{ %,H }", n->list);
-               return fmtprint(f, "(%T{ %,H })", n->type, n->list);
-
-       case OKEY:
-               if(n->left && n->right) {
-                       if(fmtmode == FExp && n->left->type && n->left->type->etype == TFIELD) {
-                               // requires special handling of field names
-                               return fmtprint(f, "%hhS:%N", n->left->sym, n->right);
-                       } else
-                               return fmtprint(f, "%N:%N", n->left, n->right);
-               }
-               if(!n->left && n->right)
-                       return fmtprint(f, ":%N", n->right);
-               if(n->left && !n->right)
-                       return fmtprint(f, "%N:", n->left);
-               return fmtstrcpy(f, ":");
-
-       case OXDOT:
-       case ODOT:
-       case ODOTPTR:
-       case ODOTINTER:
-       case ODOTMETH:
-       case OCALLPART:
-               exprfmt(f, n->left, nprec);
-               if(n->right == N || n->right->sym == S)
-                       return fmtstrcpy(f, ".<nil>");
-               return fmtprint(f, ".%hhS", n->right->sym);
-
-       case ODOTTYPE:
-       case ODOTTYPE2:
-               exprfmt(f, n->left, nprec);
-               if(n->right != N)
-                       return fmtprint(f, ".(%N)", n->right);
-               return fmtprint(f, ".(%T)", n->type);
-
-       case OINDEX:
-       case OINDEXMAP:
-       case OSLICE:
-       case OSLICESTR:
-       case OSLICEARR:
-       case OSLICE3:
-       case OSLICE3ARR:
-               exprfmt(f, n->left, nprec);
-               return fmtprint(f, "[%N]", n->right);
-
-       case OCOPY:
-       case OCOMPLEX:
-               return fmtprint(f, "%#O(%N, %N)", n->op, n->left, n->right);
-
-       case OCONV:
-       case OCONVIFACE:
-       case OCONVNOP:
-       case OARRAYBYTESTR:
-       case OARRAYRUNESTR:
-       case OSTRARRAYBYTE:
-       case OSTRARRAYRUNE:
-       case ORUNESTR:
-               if(n->type == T || n->type->sym == S)
-                       return fmtprint(f, "(%T)(%N)", n->type, n->left);
-               if(n->left)
-                       return fmtprint(f, "%T(%N)", n->type, n->left);
-               return fmtprint(f, "%T(%,H)", n->type, n->list);
-
-       case OREAL:
-       case OIMAG:
-       case OAPPEND:
-       case OCAP:
-       case OCLOSE:
-       case ODELETE:
-       case OLEN:
-       case OMAKE:
-       case ONEW:
-       case OPANIC:
-       case ORECOVER:
-       case OPRINT:
-       case OPRINTN:
-               if(n->left)
-                       return fmtprint(f, "%#O(%N)", n->op, n->left);
-               if(n->isddd)
-                       return fmtprint(f, "%#O(%,H...)", n->op, n->list);
-               return fmtprint(f, "%#O(%,H)", n->op, n->list);
-
-       case OCALL:
-       case OCALLFUNC:
-       case OCALLINTER:
-       case OCALLMETH:
-               exprfmt(f, n->left, nprec);
-               if(n->isddd)
-                       return fmtprint(f, "(%,H...)", n->list);
-               return fmtprint(f, "(%,H)", n->list);
-
-       case OMAKEMAP:
-       case OMAKECHAN:
-       case OMAKESLICE:
-               if(n->list) // pre-typecheck
-                       return fmtprint(f, "make(%T, %,H)", n->type, n->list);
-               if(n->right)
-                       return fmtprint(f, "make(%T, %N, %N)", n->type, n->left, n->right);
-               if(n->left)
-                       return fmtprint(f, "make(%T, %N)", n->type, n->left);
-               return fmtprint(f, "make(%T)", n->type);
-
-       // Unary
-       case OPLUS:
-       case OMINUS:
-       case OADDR:
-       case OCOM:
-       case OIND:
-       case ONOT:
-       case ORECV:
-               if(n->left->op == n->op)
-                       fmtprint(f, "%#O ", n->op);
-               else
-                       fmtprint(f, "%#O", n->op);
-               return exprfmt(f, n->left, nprec+1);
-
-       // Binary
-       case OADD:
-       case OAND:
-       case OANDAND:
-       case OANDNOT:
-       case ODIV:
-       case OEQ:
-       case OGE:
-       case OGT:
-       case OLE:
-       case OLT:
-       case OLSH:
-       case OMOD:
-       case OMUL:
-       case ONE:
-       case OOR:
-       case OOROR:
-       case ORSH:
-       case OSEND:
-       case OSUB:
-       case OXOR:
-               exprfmt(f, n->left, nprec);
-               fmtprint(f, " %#O ", n->op);
-               exprfmt(f, n->right, nprec+1);
-               return 0;
-
-       case OADDSTR:
-               for(l=n->list; l; l=l->next) {
-                       if(l != n->list)
-                               fmtprint(f, " + ");
-                       exprfmt(f, l->n, nprec);
-               }
-               return 0;
-
-       case OCMPSTR:
-       case OCMPIFACE:
-               exprfmt(f, n->left, nprec);
-               fmtprint(f, " %#O ", n->etype);
-               exprfmt(f, n->right, nprec+1);
-               return 0;
-       }
-
-       return fmtprint(f, "<node %O>", n->op);
-}
-
-static int
-nodefmt(Fmt *f, Node *n)
-{
-       Type *t;
-
-       t = n->type;
-
-       // we almost always want the original, except in export mode for literals
-       // this saves the importer some work, and avoids us having to redo some
-       // special casing for package unsafe
-       if((fmtmode != FExp || n->op != OLITERAL) && n->orig != N)
-               n = n->orig;
-
-       if(f->flags&FmtLong && t != T) {
-               if(t->etype == TNIL)
-                       return fmtprint(f, "nil");
-               else
-                       return fmtprint(f, "%N (type %T)", n, t);
-       }
-
-       // TODO inlining produces expressions with ninits. we can't print these yet.
-
-       if(opprec[n->op] < 0)
-               return stmtfmt(f, n);
-
-       return exprfmt(f, n, 0);
-}
-
-static int dumpdepth;
-
-static void
-indent(Fmt *fp)
-{
-       int i;
-
-       fmtstrcpy(fp, "\n");
-       for(i = 0; i < dumpdepth; ++i)
-               fmtstrcpy(fp, ".   ");
-}
-
-static int
-nodedump(Fmt *fp, Node *n)
-{
-       int recur;
-
-       if(n == N)
-               return 0;
-
-       recur = !(fp->flags&FmtShort);
-
-       if(recur) {
-               indent(fp);
-               if(dumpdepth > 10)
-                       return fmtstrcpy(fp, "...");
-
-               if(n->ninit != nil) {
-                       fmtprint(fp, "%O-init%H", n->op, n->ninit);
-                       indent(fp);
-               }
-       }
-
-//     fmtprint(fp, "[%p]", n);
-
-       switch(n->op) {
-       default:
-               fmtprint(fp, "%O%J", n->op, n);
-               break;
-       case OREGISTER:
-       case OINDREG:
-               fmtprint(fp, "%O-%R%J", n->op, n->val.u.reg, n);
-               break;
-       case OLITERAL:
-               fmtprint(fp, "%O-%V%J", n->op, &n->val, n);
-               break;
-       case ONAME:
-       case ONONAME:
-               if(n->sym != S)
-                       fmtprint(fp, "%O-%S%J", n->op, n->sym, n);
-               else
-                       fmtprint(fp, "%O%J", n->op, n);
-               if(recur && n->type == T && n->ntype) {
-                       indent(fp);
-                       fmtprint(fp, "%O-ntype%N", n->op, n->ntype);
-               }
-               break;
-       case OASOP:
-               fmtprint(fp, "%O-%O%J", n->op, n->etype, n);
-               break;
-       case OTYPE:
-               fmtprint(fp, "%O %S%J type=%T", n->op, n->sym, n, n->type);
-               if(recur && n->type == T && n->ntype) {
-                       indent(fp);
-                       fmtprint(fp, "%O-ntype%N", n->op, n->ntype);
-               }
-               break;
-       }
-
-       if(n->sym != S && n->op != ONAME)
-               fmtprint(fp, " %S G%d", n->sym, n->vargen);
-
-       if(n->type != T)
-               fmtprint(fp, " %T", n->type);
-
-       if(recur) {
-               if(n->left)
-                       fmtprint(fp, "%N", n->left);
-               if(n->right)
-                       fmtprint(fp, "%N", n->right);
-               if(n->list) {
-                       indent(fp);
-                       fmtprint(fp, "%O-list%H", n->op, n->list);
-               }
-               if(n->rlist) {
-                       indent(fp);
-                       fmtprint(fp, "%O-rlist%H", n->op, n->rlist);
-               }
-               if(n->ntest) {
-                       indent(fp);
-                       fmtprint(fp, "%O-test%N", n->op, n->ntest);
-               }
-               if(n->nbody) {
-                       indent(fp);
-                       fmtprint(fp, "%O-body%H", n->op, n->nbody);
-               }
-               if(n->nelse) {
-                       indent(fp);
-                       fmtprint(fp, "%O-else%H", n->op, n->nelse);
-               }
-               if(n->nincr) {
-                       indent(fp);
-                       fmtprint(fp, "%O-incr%N", n->op, n->nincr);
-               }
-       }
-
-       return 0;
-}
-
-// Fmt "%S": syms
-// Flags:  "%hS" suppresses qualifying with package
-static int
-Sconv(Fmt *fp)
-{
-       Sym *s;
-       int r, sm;
-       unsigned long sf;
-
-       if(fp->flags&FmtLong)
-               return linksymfmt(fp);
-
-       s = va_arg(fp->args, Sym*);
-       if(s == S)
-               return fmtstrcpy(fp, "<S>");
-
-       if(s->name && s->name[0] == '_' && s->name[1] == '\0')
-               return fmtstrcpy(fp, "_");
-
-       sf = fp->flags;
-       sm = setfmode(&fp->flags);
-       r = symfmt(fp, s);
-       fp->flags = sf;
-       fmtmode = sm;
-       return r;
-}
-
-// Fmt "%T": types.
-// Flags: 'l' print definition, not name
-//       'h' omit 'func' and receiver from function types, short type names
-//       'u' package name, not prefix (FTypeId mode, sticky)
-int
-Tconv(Fmt *fp)
-{
-       Type *t;
-       int r, sm;
-       unsigned long sf;
-
-       t = va_arg(fp->args, Type*);
-       if(t == T)
-               return fmtstrcpy(fp, "<T>");
-
-       if(t->trecur > 4)
-               return fmtstrcpy(fp, "<...>");
-
-       t->trecur++;
-       sf = fp->flags;
-       sm = setfmode(&fp->flags);
-
-       if(fmtmode == FTypeId && (sf&FmtUnsigned))
-               fmtpkgpfx++;
-       if(fmtpkgpfx)
-               fp->flags |= FmtUnsigned;
-
-       r = typefmt(fp, t);
-
-       if(fmtmode == FTypeId && (sf&FmtUnsigned))
-               fmtpkgpfx--;
-
-       fp->flags = sf;
-       fmtmode = sm;
-       t->trecur--;
-       return r;
-}
-
-// Fmt '%N': Nodes.
-// Flags: 'l' suffix with "(type %T)" where possible
-//       '+h' in debug mode, don't recurse, no multiline output
-static int
-Nconv(Fmt *fp)
-{
-       Node *n;
-       int r, sm;
-       unsigned long sf;
-
-       n = va_arg(fp->args, Node*);
-       if(n == N)
-               return fmtstrcpy(fp, "<N>");
-       sf = fp->flags;
-       sm = setfmode(&fp->flags);
-
-       r = -1;
-       switch(fmtmode) {
-       case FErr:
-       case FExp:
-               r = nodefmt(fp, n);
-               break;
-       case FDbg:
-               dumpdepth++;
-               r = nodedump(fp, n);
-               dumpdepth--;
-               break;
-       default:
-               fatal("unhandled %%N mode");
-       }
-
-       fp->flags = sf;
-       fmtmode = sm;
-       return r;
-}
-
-// Fmt '%H': NodeList.
-// Flags: all those of %N plus ',': separate with comma's instead of semicolons.
-static int
-Hconv(Fmt *fp)
-{
-       NodeList *l;
-       int r, sm;
-       unsigned long sf;
-       char *sep;
-
-       l = va_arg(fp->args, NodeList*);
-
-       if(l == nil && fmtmode == FDbg)
-               return fmtstrcpy(fp, "<nil>");
-
-       sf = fp->flags;
-       sm = setfmode(&fp->flags);
-       r = 0;
-       sep = "; ";
-       if(fmtmode == FDbg)
-               sep = "\n";
-       else if(fp->flags & FmtComma)
-               sep = ", ";
-
-       for(;l; l=l->next) {
-               r += fmtprint(fp, "%N", l->n);
-               if(l->next)
-                       r += fmtstrcpy(fp, sep);
-       }
-
-       fp->flags = sf;
-       fmtmode = sm;
-       return r;
-}
-
-void
-fmtinstallgo(void)
-{
-       fmtmode = FErr;
-       fmtinstall('E', Econv);         // etype opcodes
-       fmtinstall('J', Jconv);         // all the node flags
-       fmtinstall('H', Hconv);         // node lists
-       fmtinstall('L', Lconv);         // line number
-       fmtinstall('N', Nconv);         // node pointer
-       fmtinstall('O', Oconv);         // node opcodes
-       fmtinstall('S', Sconv);         // sym pointer
-       fmtinstall('T', Tconv);         // type pointer
-       fmtinstall('V', Vconv);         // val pointer
-       fmtinstall('Z', Zconv);         // escaped string
-
-       // These are in mparith1.c
-       fmtinstall('B', Bconv); // big numbers
-       fmtinstall('F', Fconv); // big float numbers
-
-}
-
-void
-dumplist(char *s, NodeList *l)
-{
-       print("%s%+H\n", s, l);
-}
-
-void
-dump(char *s, Node *n)
-{
-       print("%s [%p]%+N\n", s, n, n);
-}
diff --git a/src/cmd/gc/gen.c b/src/cmd/gc/gen.c
deleted file mode 100644 (file)
index 72bcc49..0000000
+++ /dev/null
@@ -1,987 +0,0 @@
-// Copyright 2009 The Go Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style
-// license that can be found in the LICENSE file.
-
-/*
- * portable half of code generator.
- * mainly statements and control flow.
- */
-
-#include <u.h>
-#include <libc.h>
-#include "go.h"
-
-static void    cgen_dcl(Node *n);
-static void    cgen_proc(Node *n, int proc);
-static void    checkgoto(Node*, Node*);
-
-static Label *labellist;
-static Label *lastlabel;
-
-Node*
-sysfunc(char *name)
-{
-       Node *n;
-
-       n = newname(pkglookup(name, runtimepkg));
-       n->class = PFUNC;
-       return n;
-}
-
-/*
- * the address of n has been taken and might be used after
- * the current function returns.  mark any local vars
- * as needing to move to the heap.
- */
-void
-addrescapes(Node *n)
-{
-       char buf[100];
-       Node *oldfn;
-
-       switch(n->op) {
-       default:
-               // probably a type error already.
-               // dump("addrescapes", n);
-               break;
-
-       case ONAME:
-               if(n == nodfp)
-                       break;
-
-               // if this is a tmpname (PAUTO), it was tagged by tmpname as not escaping.
-               // on PPARAM it means something different.
-               if(n->class == PAUTO && n->esc == EscNever)
-                       break;
-
-               switch(n->class) {
-               case PPARAMREF:
-                       addrescapes(n->defn);
-                       break;
-               case PPARAM:
-               case PPARAMOUT:
-                       // if func param, need separate temporary
-                       // to hold heap pointer.
-                       // the function type has already been checked
-                       // (we're in the function body)
-                       // so the param already has a valid xoffset.
-
-                       // expression to refer to stack copy
-                       n->stackparam = nod(OPARAM, n, N);
-                       n->stackparam->type = n->type;
-                       n->stackparam->addable = 1;
-                       if(n->xoffset == BADWIDTH)
-                               fatal("addrescapes before param assignment");
-                       n->stackparam->xoffset = n->xoffset;
-                       // fallthrough
-
-               case PAUTO:
-                       n->class |= PHEAP;
-                       n->addable = 0;
-                       n->ullman = 2;
-                       n->xoffset = 0;
-
-                       // create stack variable to hold pointer to heap
-                       oldfn = curfn;
-                       curfn = n->curfn;
-                       n->heapaddr = temp(ptrto(n->type));
-                       snprint(buf, sizeof buf, "&%S", n->sym);
-                       n->heapaddr->sym = lookup(buf);
-                       n->heapaddr->orig->sym = n->heapaddr->sym;
-                       n->esc = EscHeap;
-                       if(debug['m'])
-                               print("%L: moved to heap: %N\n", n->lineno, n);
-                       curfn = oldfn;
-                       break;
-               }
-               break;
-
-       case OIND:
-       case ODOTPTR:
-               break;
-
-       case ODOT:
-       case OINDEX:
-               // ODOTPTR has already been introduced,
-               // so these are the non-pointer ODOT and OINDEX.
-               // In &x[0], if x is a slice, then x does not
-               // escape--the pointer inside x does, but that
-               // is always a heap pointer anyway.
-               if(!isslice(n->left->type))
-                       addrescapes(n->left);
-               break;
-       }
-}
-
-void
-clearlabels(void)
-{
-       Label *l;
-
-       for(l=labellist; l!=L; l=l->link)
-               l->sym->label = L;
-       
-       labellist = L;
-       lastlabel = L;
-}
-
-static Label*
-newlab(Node *n)
-{
-       Sym *s;
-       Label *lab;
-       
-       s = n->left->sym;
-       if((lab = s->label) == L) {
-               lab = mal(sizeof(*lab));
-               if(lastlabel == nil)
-                       labellist = lab;
-               else
-                       lastlabel->link = lab;
-               lastlabel = lab;
-               lab->sym = s;
-               s->label = lab;
-       }
-       
-       if(n->op == OLABEL) {
-               if(lab->def != N)
-                       yyerror("label %S already defined at %L", s, lab->def->lineno);
-               else
-                       lab->def = n;
-       } else
-               lab->use = list(lab->use, n);
-
-       return lab;
-}
-
-void
-checklabels(void)
-{
-       Label *lab;
-       NodeList *l;
-
-       for(lab=labellist; lab!=L; lab=lab->link) {
-               if(lab->def == N) {
-                       for(l=lab->use; l; l=l->next)
-                               yyerrorl(l->n->lineno, "label %S not defined", lab->sym);
-                       continue;
-               }
-               if(lab->use == nil && !lab->used) {
-                       yyerrorl(lab->def->lineno, "label %S defined and not used", lab->sym);
-                       continue;
-               }
-               if(lab->gotopc != P)
-                       fatal("label %S never resolved", lab->sym);
-               for(l=lab->use; l; l=l->next)
-                       checkgoto(l->n, lab->def);
-       }
-}
-
-static void
-checkgoto(Node *from, Node *to)
-{
-       int nf, nt;
-       Sym *block, *dcl, *fs, *ts;
-       int lno;
-
-       if(from->sym == to->sym)
-               return;
-
-       nf = 0;
-       for(fs=from->sym; fs; fs=fs->link)
-               nf++;
-       nt = 0;
-       for(fs=to->sym; fs; fs=fs->link)
-               nt++;
-       fs = from->sym;
-       for(; nf > nt; nf--)
-               fs = fs->link;
-       if(fs != to->sym) {
-               lno = lineno;
-               setlineno(from);
-
-               // decide what to complain about.
-               // prefer to complain about 'into block' over declarations,
-               // so scan backward to find most recent block or else dcl.
-               block = S;
-               dcl = S;
-               ts = to->sym;
-               for(; nt > nf; nt--) {
-                       if(ts->pkg == nil)
-                               block = ts;
-                       else
-                               dcl = ts;
-                       ts = ts->link;
-               }
-               while(ts != fs) {
-                       if(ts->pkg == nil)
-                               block = ts;
-                       else
-                               dcl = ts;
-                       ts = ts->link;
-                       fs = fs->link;
-               }
-
-               if(block)
-                       yyerror("goto %S jumps into block starting at %L", from->left->sym, block->lastlineno);
-               else
-                       yyerror("goto %S jumps over declaration of %S at %L", from->left->sym, dcl, dcl->lastlineno);
-               lineno = lno;
-       }
-}
-
-static Label*
-stmtlabel(Node *n)
-{
-       Label *lab;
-
-       if(n->sym != S)
-       if((lab = n->sym->label) != L)
-       if(lab->def != N)
-       if(lab->def->defn == n)
-               return lab;
-       return L;
-}
-
-/*
- * compile statements
- */
-void
-genlist(NodeList *l)
-{
-       for(; l; l=l->next)
-               gen(l->n);
-}
-
-void
-gen(Node *n)
-{
-       int32 lno;
-       Prog *scontin, *sbreak;
-       Prog *p1, *p2, *p3;
-       Label *lab;
-       int32 wasregalloc;
-
-//dump("gen", n);
-
-       lno = setlineno(n);
-       wasregalloc = thearch.anyregalloc();
-
-       if(n == N)
-               goto ret;
-
-       if(n->ninit)
-               genlist(n->ninit);
-
-       setlineno(n);
-
-       switch(n->op) {
-       default:
-               fatal("gen: unknown op %+hN", n);
-               break;
-
-       case OCASE:
-       case OFALL:
-       case OXCASE:
-       case OXFALL:
-       case ODCLCONST:
-       case ODCLFUNC:
-       case ODCLTYPE:
-               break;
-
-       case OEMPTY:
-               break;
-
-       case OBLOCK:
-               genlist(n->list);
-               break;
-
-       case OLABEL:
-               if(isblanksym(n->left->sym))
-                       break;
-               
-               lab = newlab(n);
-
-               // if there are pending gotos, resolve them all to the current pc.
-               for(p1=lab->gotopc; p1; p1=p2) {
-                       p2 = unpatch(p1);
-                       patch(p1, pc);
-               }
-               lab->gotopc = P;
-               if(lab->labelpc == P)
-                       lab->labelpc = pc;
-
-               if(n->defn) {
-                       switch(n->defn->op) {
-                       case OFOR:
-                       case OSWITCH:
-                       case OSELECT:
-                               // so stmtlabel can find the label
-                               n->defn->sym = lab->sym;
-                       }
-               }
-               break;
-
-       case OGOTO:
-               // if label is defined, emit jump to it.
-               // otherwise save list of pending gotos in lab->gotopc.
-               // the list is linked through the normal jump target field
-               // to avoid a second list.  (the jumps are actually still
-               // valid code, since they're just going to another goto
-               // to the same label.  we'll unwind it when we learn the pc
-               // of the label in the OLABEL case above.)
-               lab = newlab(n);
-               if(lab->labelpc != P)
-                       gjmp(lab->labelpc);
-               else
-                       lab->gotopc = gjmp(lab->gotopc);
-               break;
-
-       case OBREAK:
-               if(n->left != N) {
-                       lab = n->left->sym->label;
-                       if(lab == L) {
-                               yyerror("break label not defined: %S", n->left->sym);
-                               break;
-                       }
-                       lab->used = 1;
-                       if(lab->breakpc == P) {
-                               yyerror("invalid break label %S", n->left->sym);
-                               break;
-                       }
-                       gjmp(lab->breakpc);
-                       break;
-               }
-               if(breakpc == P) {
-                       yyerror("break is not in a loop");
-                       break;
-               }
-               gjmp(breakpc);
-               break;
-
-       case OCONTINUE:
-               if(n->left != N) {
-                       lab = n->left->sym->label;
-                       if(lab == L) {
-                               yyerror("continue label not defined: %S", n->left->sym);
-                               break;
-                       }
-                       lab->used = 1;
-                       if(lab->continpc == P) {
-                               yyerror("invalid continue label %S", n->left->sym);
-                               break;
-                       }
-                       gjmp(lab->continpc);
-                       break;
-               }
-               if(continpc == P) {
-                       yyerror("continue is not in a loop");
-                       break;
-               }
-               gjmp(continpc);
-               break;
-
-       case OFOR:
-               sbreak = breakpc;
-               p1 = gjmp(P);                   //              goto test
-               breakpc = gjmp(P);              // break:       goto done
-               scontin = continpc;
-               continpc = pc;
-
-               // define break and continue labels
-               if((lab = stmtlabel(n)) != L) {
-                       lab->breakpc = breakpc;
-                       lab->continpc = continpc;
-               }
-               gen(n->nincr);                          // contin:      incr
-               patch(p1, pc);                          // test:
-               thearch.bgen(n->ntest, 0, -1, breakpc);         //              if(!test) goto break
-               genlist(n->nbody);                              //              body
-               gjmp(continpc);
-               patch(breakpc, pc);                     // done:
-               continpc = scontin;
-               breakpc = sbreak;
-               if(lab) {
-                       lab->breakpc = P;
-                       lab->continpc = P;
-               }
-               break;
-
-       case OIF:
-               p1 = gjmp(P);                   //              goto test
-               p2 = gjmp(P);                   // p2:          goto else
-               patch(p1, pc);                          // test:
-               thearch.bgen(n->ntest, 0, -n->likely, p2);              //              if(!test) goto p2
-               genlist(n->nbody);                              //              then
-               p3 = gjmp(P);                   //              goto done
-               patch(p2, pc);                          // else:
-               genlist(n->nelse);                              //              else
-               patch(p3, pc);                          // done:
-               break;
-
-       case OSWITCH:
-               sbreak = breakpc;
-               p1 = gjmp(P);                   //              goto test
-               breakpc = gjmp(P);              // break:       goto done
-
-               // define break label
-               if((lab = stmtlabel(n)) != L)
-                       lab->breakpc = breakpc;
-
-               patch(p1, pc);                          // test:
-               genlist(n->nbody);                              //              switch(test) body
-               patch(breakpc, pc);                     // done:
-               breakpc = sbreak;
-               if(lab != L)
-                       lab->breakpc = P;
-               break;
-
-       case OSELECT:
-               sbreak = breakpc;
-               p1 = gjmp(P);                   //              goto test
-               breakpc = gjmp(P);              // break:       goto done
-
-               // define break label
-               if((lab = stmtlabel(n)) != L)
-                       lab->breakpc = breakpc;
-
-               patch(p1, pc);                          // test:
-               genlist(n->nbody);                              //              select() body
-               patch(breakpc, pc);                     // done:
-               breakpc = sbreak;
-               if(lab != L)
-                       lab->breakpc = P;
-               break;
-
-       case ODCL:
-               cgen_dcl(n->left);
-               break;
-
-       case OAS:
-               if(gen_as_init(n))
-                       break;
-               cgen_as(n->left, n->right);
-               break;
-
-       case OCALLMETH:
-               cgen_callmeth(n, 0);
-               break;
-
-       case OCALLINTER:
-               thearch.cgen_callinter(n, N, 0);
-               break;
-
-       case OCALLFUNC:
-               thearch.cgen_call(n, 0);
-               break;
-
-       case OPROC:
-               cgen_proc(n, 1);
-               break;
-
-       case ODEFER:
-               cgen_proc(n, 2);
-               break;
-
-       case ORETURN:
-       case ORETJMP:
-               thearch.cgen_ret(n);
-               break;
-       
-       case OCHECKNIL:
-               cgen_checknil(n->left);
-               break;
-       
-       case OVARKILL:
-               gvarkill(n->left);
-               break;
-       }
-
-ret:
-       if(thearch.anyregalloc() != wasregalloc) {
-               dump("node", n);
-               fatal("registers left allocated");
-       }
-
-       lineno = lno;
-}
-
-/*
- * generate call to non-interface method
- *     proc=0  normal call
- *     proc=1  goroutine run in new proc
- *     proc=2  defer call save away stack
- */
-void
-cgen_callmeth(Node *n, int proc)
-{
-       Node n2;
-       Node *l;
-
-       // generate a rewrite in n2 for the method call
-       // (p.f)(...) goes to (f)(p,...)
-
-       l = n->left;
-       if(l->op != ODOTMETH)
-               fatal("cgen_callmeth: not dotmethod: %N");
-
-       n2 = *n;
-       n2.op = OCALLFUNC;
-       n2.left = l->right;
-       n2.left->type = l->type;
-
-       if(n2.left->op == ONAME)
-               n2.left->class = PFUNC;
-       thearch.cgen_call(&n2, proc);
-}
-
-/*
- * generate code to start new proc running call n.
- */
-static void
-cgen_proc(Node *n, int proc)
-{
-       switch(n->left->op) {
-       default:
-               fatal("cgen_proc: unknown call %O", n->left->op);
-
-       case OCALLMETH:
-               cgen_callmeth(n->left, proc);
-               break;
-
-       case OCALLINTER:
-               thearch.cgen_callinter(n->left, N, proc);
-               break;
-
-       case OCALLFUNC:
-               thearch.cgen_call(n->left, proc);
-               break;
-       }
-
-}
-
-/*
- * generate declaration.
- * have to allocate heap copy
- * for escaped variables.
- */
-static void
-cgen_dcl(Node *n)
-{
-       if(debug['g'])
-               dump("\ncgen-dcl", n);
-       if(n->op != ONAME) {
-               dump("cgen_dcl", n);
-               fatal("cgen_dcl");
-       }
-       if(!(n->class & PHEAP))
-               return;
-       if(compiling_runtime)
-               yyerror("%N escapes to heap, not allowed in runtime.", n);
-       if(n->alloc == nil)
-               n->alloc = callnew(n->type);
-       cgen_as(n->heapaddr, n->alloc);
-}
-
-/*
- * generate discard of value
- */
-static void
-cgen_discard(Node *nr)
-{
-       Node tmp;
-
-       if(nr == N)
-               return;
-
-       switch(nr->op) {
-       case ONAME:
-               if(!(nr->class & PHEAP) && nr->class != PEXTERN && nr->class != PFUNC && nr->class != PPARAMREF)
-                       gused(nr);
-               break;
-
-       // unary
-       case OADD:
-       case OAND:
-       case ODIV:
-       case OEQ:
-       case OGE:
-       case OGT:
-       case OLE:
-       case OLSH:
-       case OLT:
-       case OMOD:
-       case OMUL:
-       case ONE:
-       case OOR:
-       case ORSH:
-       case OSUB:
-       case OXOR:
-               cgen_discard(nr->left);
-               cgen_discard(nr->right);
-               break;
-
-       // binary
-       case OCAP:
-       case OCOM:
-       case OLEN:
-       case OMINUS:
-       case ONOT:
-       case OPLUS:
-               cgen_discard(nr->left);
-               break;
-       
-       case OIND:
-               cgen_checknil(nr->left);
-               break;
-
-       // special enough to just evaluate
-       default:
-               tempname(&tmp, nr->type);
-               cgen_as(&tmp, nr);
-               gused(&tmp);
-       }
-}
-
-/*
- * clearslim generates code to zero a slim node.
- */
-void
-clearslim(Node *n)
-{
-       Node z;
-       Mpflt zero;
-
-       memset(&z, 0, sizeof(z));
-       z.op = OLITERAL;
-       z.type = n->type;
-       z.addable = 1;
-
-       switch(simtype[n->type->etype]) {
-       case TCOMPLEX64:
-       case TCOMPLEX128:
-               z.val.u.cval = mal(sizeof(*z.val.u.cval));
-               mpmovecflt(&z.val.u.cval->real, 0.0);
-               mpmovecflt(&z.val.u.cval->imag, 0.0);
-               break;
-
-       case TFLOAT32:
-       case TFLOAT64:
-               mpmovecflt(&zero, 0.0);
-               z.val.ctype = CTFLT;
-               z.val.u.fval = &zero;
-               break;
-
-       case TPTR32:
-       case TPTR64:
-       case TCHAN:
-       case TMAP:
-               z.val.ctype = CTNIL;
-               break;
-
-       case TBOOL:
-               z.val.ctype = CTBOOL;
-               break;
-
-       case TINT8:
-       case TINT16:
-       case TINT32:
-       case TINT64:
-       case TUINT8:
-       case TUINT16:
-       case TUINT32:
-       case TUINT64:
-               z.val.ctype = CTINT;
-               z.val.u.xval = mal(sizeof(*z.val.u.xval));
-               mpmovecfix(z.val.u.xval, 0);
-               break;
-
-       default:
-               fatal("clearslim called on type %T", n->type);
-       }
-
-       ullmancalc(&z);
-       thearch.cgen(&z, n);
-}
-
-/*
- * generate assignment:
- *     nl = nr
- * nr == N means zero nl.
- */
-void
-cgen_as(Node *nl, Node *nr)
-{
-       Type *tl;
-
-       if(debug['g']) {
-               dump("cgen_as", nl);
-               dump("cgen_as = ", nr);
-       }
-
-       while(nr != N && nr->op == OCONVNOP)
-               nr = nr->left;
-
-       if(nl == N || isblank(nl)) {
-               cgen_discard(nr);
-               return;
-       }
-
-       if(nr == N || iszero(nr)) {
-               // heaps should already be clear
-               if(nr == N && (nl->class & PHEAP))
-                       return;
-
-               tl = nl->type;
-               if(tl == T)
-                       return;
-               if(isfat(tl)) {
-                       if(nl->op == ONAME)
-                               gvardef(nl);
-                       thearch.clearfat(nl);
-                       return;
-               }
-               clearslim(nl);
-               return;
-       }
-
-       tl = nl->type;
-       if(tl == T)
-               return;
-
-       thearch.cgen(nr, nl);
-}
-
-/*
- * generate:
- *     res = iface{typ, data}
- * n->left is typ
- * n->right is data
- */
-void
-cgen_eface(Node *n, Node *res)
-{
-       /* 
-        * the right node of an eface may contain function calls that uses res as an argument,
-        * so it's important that it is done first
-        */
-       Node dst;
-       Node *tmp;
-
-       tmp = temp(types[tptr]);
-       thearch.cgen(n->right, tmp);
-
-       gvardef(res);
-
-       dst = *res;
-       dst.type = types[tptr];
-       dst.xoffset += widthptr;
-       thearch.cgen(tmp, &dst);
-
-       dst.xoffset -= widthptr;
-       thearch.cgen(n->left, &dst);
-}
-
-/*
- * generate:
- *     res = s[lo, hi];
- * n->left is s
- * n->list is (cap(s)-lo(TUINT), hi-lo(TUINT)[, lo*width(TUINTPTR)])
- * caller (cgen) guarantees res is an addable ONAME.
- *
- * called for OSLICE, OSLICE3, OSLICEARR, OSLICE3ARR, OSLICESTR.
- */
-void
-cgen_slice(Node *n, Node *res)
-{
-       Node src, dst, *cap, *len, *offs, *add, *base, *tmpcap, *tmplen, *cmp, con;
-       Prog *p1, *p2;
-
-       cap = n->list->n;
-       len = n->list->next->n;
-       offs = N;
-       if(n->list->next->next)
-               offs = n->list->next->next->n;
-
-       // evaluate base pointer first, because it is the only
-       // possibly complex expression. once that is evaluated
-       // and stored, updating the len and cap can be done
-       // without making any calls, so without doing anything that
-       // might cause preemption or garbage collection.
-       // this makes the whole slice update atomic as far as the
-       // garbage collector can see.
-       
-       base = temp(types[TUINTPTR]);
-       tmplen = temp(types[TINT]);
-       if(n->op != OSLICESTR)
-               tmpcap = temp(types[TINT]);
-       else
-               tmpcap = tmplen;
-
-       if(isnil(n->left)) {
-               tempname(&src, n->left->type);
-               thearch.cgen(n->left, &src);
-       } else
-               src = *n->left;
-       if(n->op == OSLICE || n->op == OSLICE3 || n->op == OSLICESTR)
-               src.xoffset += Array_array;
-
-       if(n->op == OSLICEARR || n->op == OSLICE3ARR) {
-               if(!isptr[n->left->type->etype])
-                       fatal("slicearr is supposed to work on pointer: %+N\n", n);
-               thearch.cgen(&src, base);
-               cgen_checknil(base);
-       } else {
-               src.type = types[tptr];
-               thearch.cgen(&src, base);
-       }
-       
-       // committed to the update
-       gvardef(res);
-
-       // compute len and cap.
-       // len = n-i, cap = m-i, and offs = i*width.
-       // computing offs last lets the multiply overwrite i.
-       thearch.cgen(len, tmplen);
-       if(n->op != OSLICESTR)
-               thearch.cgen(cap, tmpcap);
-
-       // if new cap != 0 { base += add }
-       // This avoids advancing base past the end of the underlying array/string,
-       // so that it cannot point at the next object in memory.
-       // If cap == 0, the base doesn't matter except insofar as it is 0 or non-zero.
-       // In essence we are replacing x[i:j:k] where i == j == k
-       // or x[i:j] where i == j == cap(x) with x[0:0:0].
-       if(offs != N) {
-               p1 = gjmp(P);
-               p2 = gjmp(P);
-               patch(p1, pc);
-
-               nodconst(&con, tmpcap->type, 0);
-               cmp = nod(OEQ, tmpcap, &con);
-               typecheck(&cmp, Erv);
-               thearch.bgen(cmp, 1, -1, p2);
-
-               add = nod(OADD, base, offs);
-               typecheck(&add, Erv);
-               thearch.cgen(add, base);
-
-               patch(p2, pc);
-       }
-
-       // dst.array = src.array  [ + lo *width ]
-       dst = *res;
-       dst.xoffset += Array_array;
-       dst.type = types[tptr];
-       thearch.cgen(base, &dst);
-
-       // dst.len = hi [ - lo ]
-       dst = *res;
-       dst.xoffset += Array_nel;
-       dst.type = types[simtype[TUINT]];
-       thearch.cgen(tmplen, &dst);
-
-       if(n->op != OSLICESTR) {
-               // dst.cap = cap [ - lo ]
-               dst = *res;
-               dst.xoffset += Array_cap;
-               dst.type = types[simtype[TUINT]];
-               thearch.cgen(tmpcap, &dst);
-       }
-}
-
-/*
- * gather series of offsets
- * >=0 is direct addressed field
- * <0 is pointer to next field (+1)
- */
-int
-dotoffset(Node *n, int64 *oary, Node **nn)
-{
-       int i;
-
-       switch(n->op) {
-       case ODOT:
-               if(n->xoffset == BADWIDTH) {
-                       dump("bad width in dotoffset", n);
-                       fatal("bad width in dotoffset");
-               }
-               i = dotoffset(n->left, oary, nn);
-               if(i > 0) {
-                       if(oary[i-1] >= 0)
-                               oary[i-1] += n->xoffset;
-                       else
-                               oary[i-1] -= n->xoffset;
-                       break;
-               }
-               if(i < 10)
-                       oary[i++] = n->xoffset;
-               break;
-
-       case ODOTPTR:
-               if(n->xoffset == BADWIDTH) {
-                       dump("bad width in dotoffset", n);
-                       fatal("bad width in dotoffset");
-               }
-               i = dotoffset(n->left, oary, nn);
-               if(i < 10)
-                       oary[i++] = -(n->xoffset+1);
-               break;
-
-       default:
-               *nn = n;
-               return 0;
-       }
-       if(i >= 10)
-               *nn = N;
-       return i;
-}
-
-/*
- * make a new off the books
- */
-void
-tempname(Node *nn, Type *t)
-{
-       Node *n;
-       Sym *s;
-
-       if(curfn == N)
-               fatal("no curfn for tempname");
-
-       if(t == T) {
-               yyerror("tempname called with nil type");
-               t = types[TINT32];
-       }
-
-       // give each tmp a different name so that there
-       // a chance to registerizer them
-       snprint(namebuf, sizeof(namebuf), "autotmp_%.4d", statuniqgen);
-       statuniqgen++;
-       s = lookup(namebuf);
-       n = nod(ONAME, N, N);
-       n->sym = s;
-       s->def = n;
-       n->type = t;
-       n->class = PAUTO;
-       n->addable = 1;
-       n->ullman = 1;
-       n->esc = EscNever;
-       n->curfn = curfn;
-       curfn->dcl = list(curfn->dcl, n);
-
-       dowidth(t);
-       n->xoffset = 0;
-       *nn = *n;
-}
-
-Node*
-temp(Type *t)
-{
-       Node *n;
-       
-       n = nod(OXXX, N, N);
-       tempname(n, t);
-       n->sym->def->used = 1;
-       return n->orig;
-}
diff --git a/src/cmd/gc/go.errors b/src/cmd/gc/go.errors
deleted file mode 100644 (file)
index f90d619..0000000
+++ /dev/null
@@ -1,79 +0,0 @@
-// Copyright 2010 The Go Authors.  All rights reserved.
-// Use of this source code is governed by a BSD-style
-// license that can be found in the LICENSE file.
-
-// Example-based syntax error messages.
-// See bisonerrors, Makefile, go.y.
-
-static struct {
-       int yystate;
-       int yychar;
-       char *msg;
-} yymsg[] = {
-       // Each line of the form % token list
-       // is converted by bisonerrors into the yystate and yychar caused
-       // by that token list.
-
-       % loadsys package LIMPORT '(' LLITERAL import_package import_there ','
-       "unexpected comma during import block",
-
-       % loadsys package LIMPORT LNAME ';'
-       "missing import path; require quoted string",
-
-       % loadsys package imports LFUNC LNAME '(' ')' '{' LIF if_header ';'
-       "missing { after if clause",
-
-       % loadsys package imports LFUNC LNAME '(' ')' '{' LSWITCH if_header ';'
-       "missing { after switch clause",
-
-       % loadsys package imports LFUNC LNAME '(' ')' '{' LFOR for_header ';'
-       "missing { after for clause",
-
-       % loadsys package imports LFUNC LNAME '(' ')' '{' LFOR ';' LBODY
-       "missing { after for clause",
-
-       % loadsys package imports LFUNC LNAME '(' ')' ';' '{'
-       "unexpected semicolon or newline before {",
-
-       % loadsys package imports LTYPE LNAME ';'
-       "unexpected semicolon or newline in type declaration",
-
-       % loadsys package imports LCHAN '}'
-       "unexpected } in channel type",
-       
-       % loadsys package imports LCHAN ')'
-       "unexpected ) in channel type",
-       
-       % loadsys package imports LCHAN ','
-       "unexpected comma in channel type",
-
-       % loadsys package imports LFUNC LNAME '(' ')' '{' if_stmt ';' LELSE
-       "unexpected semicolon or newline before else",
-
-       % loadsys package imports LTYPE LNAME LINTERFACE '{' LNAME ',' LNAME
-       "name list not allowed in interface type",
-
-       % loadsys package imports LFUNC LNAME '(' ')' '{' LFOR LVAR LNAME '=' LNAME
-       "var declaration not allowed in for initializer",
-
-       % loadsys package imports LVAR LNAME '[' ']' LNAME '{'
-       "unexpected { at end of statement",
-
-       % loadsys package imports LFUNC LNAME '(' ')' '{' LVAR LNAME '[' ']' LNAME '{'
-       "unexpected { at end of statement",
-       
-       % loadsys package imports LFUNC LNAME '(' ')' '{' LDEFER LNAME ';'
-       "argument to go/defer must be function call",
-       
-       % loadsys package imports LVAR LNAME '=' LNAME '{' LNAME ';'
-       "need trailing comma before newline in composite literal",
-       
-       % loadsys package imports LVAR LNAME '=' comptype '{' LNAME ';'
-       "need trailing comma before newline in composite literal",
-       
-       % loadsys package imports LFUNC LNAME '(' ')' '{' LFUNC LNAME
-       "nested func not allowed",
-
-       % loadsys package imports LFUNC LNAME '(' ')' '{' LIF if_header loop_body LELSE ';'
-       "else must be followed by if or statement block"
-};
diff --git a/src/cmd/gc/go.h b/src/cmd/gc/go.h
deleted file mode 100644 (file)
index 92584f6..0000000
+++ /dev/null
@@ -1,1757 +0,0 @@
-// Copyright 2009 The Go Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style
-// license that can be found in the LICENSE file.
-
-#include       <bio.h>
-#include       <link.h>
-
-#undef OAPPEND
-
-// avoid <ctype.h>
-#undef isblank
-#define isblank goisblank
-
-#ifndef        EXTERN
-#define        EXTERN  extern
-#endif
-
-#undef BUFSIZ
-
-// The parser's maximum stack size.
-// We have to use a #define macro here since yacc
-// or bison will check for its definition and use
-// a potentially smaller value if it is undefined.
-#define YYMAXDEPTH 500
-
-enum
-{
-       NHUNK           = 50000,
-       BUFSIZ          = 8192,
-       NSYMB           = 500,
-       NHASH           = 1024,
-       STRINGSZ        = 200,
-       MAXALIGN        = 7,
-       UINF            = 100,
-
-       PRIME1          = 3,
-
-       AUNK            = 100,
-
-       // These values are known by runtime.
-       // The MEMx and NOEQx values must run in parallel.  See algtype.
-       AMEM            = 0,
-       AMEM0,
-       AMEM8,
-       AMEM16,
-       AMEM32,
-       AMEM64,
-       AMEM128,
-       ANOEQ,
-       ANOEQ0,
-       ANOEQ8,
-       ANOEQ16,
-       ANOEQ32,
-       ANOEQ64,
-       ANOEQ128,
-       ASTRING,
-       AINTER,
-       ANILINTER,
-       ASLICE,
-       AFLOAT32,
-       AFLOAT64,
-       ACPLX64,
-       ACPLX128,
-
-       BADWIDTH        = -1000000000,
-       
-       MaxStackVarSize = 10*1024*1024,
-};
-
-/*
- * note this is the representation
- * of the compilers string literals,
- * it is not the runtime representation
- */
-typedef        struct  Strlit  Strlit;
-struct Strlit
-{
-       int32   len;
-       char    s[1]; // variable
-};
-
-enum
-{
-       Mpscale = 29,           // safely smaller than bits in a long
-       Mpprec  = 16,           // Mpscale*Mpprec is max number of bits
-       Mpnorm  = Mpprec - 1,   // significant words in a normalized float
-       Mpbase  = 1L << Mpscale,
-       Mpsign  = Mpbase >> 1,
-       Mpmask  = Mpbase - 1,
-       Mpdebug = 0,
-};
-
-typedef        struct  Mpint   Mpint;
-struct Mpint
-{
-       long    a[Mpprec];
-       uchar   neg;
-       uchar   ovf;
-};
-
-typedef        struct  Mpflt   Mpflt;
-struct Mpflt
-{
-       Mpint   val;
-       short   exp;
-};
-
-typedef        struct  Mpcplx  Mpcplx;
-struct Mpcplx
-{
-       Mpflt   real;
-       Mpflt   imag;
-};
-
-typedef        struct  Val     Val;
-struct Val
-{
-       short   ctype;
-       union
-       {
-               short   reg;            // OREGISTER
-               short   bval;           // bool value CTBOOL
-               Mpint*  xval;           // int CTINT, rune CTRUNE
-               Mpflt*  fval;           // float CTFLT
-               Mpcplx* cval;           // float CTCPLX
-               Strlit* sval;           // string CTSTR
-       } u;
-};
-typedef        struct  Array   Array;
-typedef        struct  Bvec    Bvec;
-typedef        struct  Pkg Pkg;
-typedef        struct  Sym     Sym;
-typedef        struct  Node    Node;
-typedef        struct  NodeList        NodeList;
-typedef        struct  Type    Type;
-typedef        struct  Label   Label;
-
-struct Array
-{
-       int32   length;  // number of elements
-       int32   size;  // element size
-       int32   capacity;  // size of data in elements
-       char    *data;  // element storage
-};
-
-struct Type
-{
-       uchar   etype;
-       uchar   nointerface;
-       uchar   noalg;
-       uchar   chan;
-       uchar   trecur;         // to detect loops
-       uchar   printed;
-       uchar   embedded;       // TFIELD embedded type
-       uchar   siggen;
-       uchar   funarg;         // on TSTRUCT and TFIELD
-       uchar   copyany;
-       uchar   local;          // created in this file
-       uchar   deferwidth;
-       uchar   broke;          // broken type definition.
-       uchar   isddd;          // TFIELD is ... argument
-       uchar   align;
-       uchar   haspointers;    // 0 unknown, 1 no, 2 yes
-
-       Node*   nod;            // canonical OTYPE node
-       Type*   orig;           // original type (type literal or predefined type)
-       int             lineno;
-
-       // TFUNC
-       int     thistuple;
-       int     outtuple;
-       int     intuple;
-       uchar   outnamed;
-
-       Type*   method;
-       Type*   xmethod;
-
-       Sym*    sym;
-       int32   vargen;         // unique name for OTYPE/ONAME
-
-       Node*   nname;
-       vlong   argwid;
-
-       // most nodes
-       Type*   type;           // actual type for TFIELD, element type for TARRAY, TCHAN, TMAP, TPTRxx
-       vlong   width;          // offset in TFIELD, width in all others
-
-       // TFIELD
-       Type*   down;           // next struct field, also key type in TMAP
-       Type*   outer;          // outer struct
-       Strlit* note;           // literal string annotation
-
-       // TARRAY
-       vlong   bound;          // negative is dynamic array
-
-       // TMAP
-       Type*   bucket;         // internal type representing a hash bucket
-       Type*   hmap;           // internal type representing a Hmap (map header object)
-       Type*   hiter;          // internal type representing hash iterator state
-       Type*   map;            // link from the above 3 internal types back to the map type.
-
-       int32   maplineno;      // first use of TFORW as map key
-       int32   embedlineno;    // first use of TFORW as embedded type
-       
-       // for TFORW, where to copy the eventual value to
-       NodeList        *copyto;
-       
-       Node    *lastfn;        // for usefield
-};
-#define        T       ((Type*)0)
-
-typedef struct InitEntry InitEntry;
-typedef struct InitPlan InitPlan;
-
-struct InitEntry
-{
-       vlong xoffset;  // struct, array only
-       Node *key;  // map only
-       Node *expr;
-};
-
-struct InitPlan
-{
-       vlong lit;  // bytes of initialized non-zero literals
-       vlong zero;  // bytes of zeros
-       vlong expr;  // bytes of run-time computed expressions
-
-       InitEntry *e;
-       int len;
-       int cap;
-};
-
-enum
-{
-       EscUnknown,
-       EscHeap,
-       EscScope,
-       EscNone,
-       EscReturn,
-       EscNever,
-       EscBits = 3,
-       EscMask = (1<<EscBits) - 1,
-       EscContentEscapes = 1<<EscBits, // value obtained by indirect of parameter escapes to some returned result
-       EscReturnBits = EscBits+1,
-};
-
-struct Node
-{
-       // Tree structure.
-       // Generic recursive walks should follow these fields.
-       Node*   left;
-       Node*   right;
-       Node*   ntest;
-       Node*   nincr;
-       NodeList*       ninit;
-       NodeList*       nbody;
-       NodeList*       nelse;
-       NodeList*       list;
-       NodeList*       rlist;
-
-       uchar   op;
-       uchar   nointerface;
-       uchar   ullman;         // sethi/ullman number
-       uchar   addable;        // type of addressability - 0 is not addressable
-       uchar   trecur;         // to detect loops
-       uchar   etype;          // op for OASOP, etype for OTYPE, exclam for export
-       uchar   bounded;        // bounds check unnecessary
-       uchar   class;          // PPARAM, PAUTO, PEXTERN, etc
-       uchar   method;         // OCALLMETH name
-       uchar   embedded;       // ODCLFIELD embedded type
-       uchar   colas;          // OAS resulting from :=
-       uchar   diag;           // already printed error about this
-       uchar   noescape;       // func arguments do not escape
-       uchar   nosplit;        // func should not execute on separate stack
-       uchar   builtin;        // built-in name, like len or close
-       uchar   nowritebarrier; // emit compiler error instead of write barrier
-       uchar   walkdef;
-       uchar   typecheck;
-       uchar   local;
-       uchar   dodata;
-       uchar   initorder;
-       uchar   used;
-       uchar   isddd;
-       uchar   readonly;
-       uchar   implicit;
-       uchar   addrtaken;      // address taken, even if not moved to heap
-       uchar   assigned;       // is the variable ever assigned to
-       uchar   captured;       // is the variable captured by a closure
-       uchar   byval;          // is the variable captured by value or by reference
-       uchar   dupok;  // duplicate definitions ok (for func)
-       uchar   wrapper;        // is method wrapper (for func)
-       uchar   reslice;        // this is a reslice x = x[0:y] or x = append(x, ...)
-       schar   likely; // likeliness of if statement
-       uchar   hasbreak;       // has break statement
-       uchar   needzero; // if it contains pointers, needs to be zeroed on function entry
-       uchar   needctxt;       // function uses context register (has closure variables)
-       uint    esc;            // EscXXX
-       int     funcdepth;
-
-       // most nodes
-       Type*   type;
-       Node*   orig;           // original form, for printing, and tracking copies of ONAMEs
-
-       // func
-       Node*   nname;
-       Node*   shortname;
-       NodeList*       enter;
-       NodeList*       exit;
-       NodeList*       cvars;  // closure params
-       NodeList*       dcl;    // autodcl for this func/closure
-       NodeList*       inl;    // copy of the body for use in inlining
-       NodeList*       inldcl; // copy of dcl for use in inlining
-       int     closgen;
-       Node*   outerfunc;
-
-       // OLITERAL/OREGISTER
-       Val     val;
-
-       // ONAME
-       Node*   ntype;
-       Node*   defn;   // ONAME: initializing assignment; OLABEL: labeled statement
-       Node*   pack;   // real package for import . names
-       Node*   curfn;  // function for local variables
-       Type*   paramfld; // TFIELD for this PPARAM; also for ODOT, curfn
-       int     decldepth;      // declaration loop depth, increased for every loop or label
-
-       // ONAME func param with PHEAP
-       Node*   heapaddr;       // temp holding heap address of param
-       Node*   outerexpr;      // expression copied into closure for variable
-       Node*   stackparam;     // OPARAM node referring to stack copy of param
-       Node*   alloc;  // allocation call
-
-       // ONAME closure param with PPARAMREF
-       Node*   outer;  // outer PPARAMREF in nested closure
-       Node*   closure;        // ONAME/PHEAP <-> ONAME/PPARAMREF
-       int     top;    // top context (Ecall, Eproc, etc)
-
-       // ONAME substitute while inlining
-       Node* inlvar;
-
-       // OPACK
-       Pkg*    pkg;
-       
-       // OARRAYLIT, OMAPLIT, OSTRUCTLIT.
-       InitPlan*       initplan;
-
-       // Escape analysis.
-       NodeList* escflowsrc;   // flow(this, src)
-       NodeList* escretval;    // on OCALLxxx, list of dummy return values
-       int     escloopdepth;   // -1: global, 0: return variables, 1:function top level, increased inside function for every loop or label to mark scopes
-
-       Sym*    sym;            // various
-       int32   vargen;         // unique name for OTYPE/ONAME
-       int32   lineno;
-       int32   endlineno;
-       vlong   xoffset;
-       vlong   stkdelta;       // offset added by stack frame compaction phase.
-       int32   ostk;
-       int32   iota;
-       uint32  walkgen;
-       int32   esclevel;
-       void*   opt;    // for optimization passes
-};
-#define        N       ((Node*)0)
-
-/*
- * Every node has a walkgen field.
- * If you want to do a traversal of a node graph that
- * might contain duplicates and want to avoid
- * visiting the same nodes twice, increment walkgen
- * before starting.  Then before processing a node, do
- *
- *     if(n->walkgen == walkgen)
- *             return;
- *     n->walkgen = walkgen;
- *
- * Such a walk cannot call another such walk recursively,
- * because of the use of the global walkgen.
- */
-EXTERN uint32  walkgen;
-
-struct NodeList
-{
-       Node*   n;
-       NodeList*       next;
-       NodeList*       end;
-};
-
-enum
-{
-       SymExport       = 1<<0, // to be exported
-       SymPackage      = 1<<1,
-       SymExported     = 1<<2, // already written out by export
-       SymUniq         = 1<<3,
-       SymSiggen       = 1<<4,
-       SymAsm          = 1<<5,
-       SymAlgGen       = 1<<6,
-};
-
-struct Sym
-{
-       ushort  lexical;
-       uchar   flags;
-       uchar   sym;            // huffman encoding in object file
-       Sym*    link;
-       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;
-       char*   name;           // variable name
-       Node*   def;            // definition: ONAME OTYPE OPACK or OLITERAL
-       Label*  label;  // corresponding label (ephemeral)
-       int32   block;          // blocknumber to catch redeclaration
-       int32   lastlineno;     // last declaration for diagnostic
-       Pkg*    origpkg;        // original package for . import
-       LSym*   lsym;
-};
-#define        S       ((Sym*)0)
-
-EXTERN Sym*    dclstack;
-
-struct Pkg
-{
-       char*   name;           // package name
-       Strlit* path;           // string literal used in import statement
-       Sym*    pathsym;
-       char*   prefix;         // escaped path for use in symbol table
-       Pkg*    link;
-       uchar   imported;       // export data of this package was parsed
-       char    exported;       // import line written in export data
-       char    direct; // imported directly
-       char    safe;   // whether the package is marked as safe
-};
-
-typedef        struct  Iter    Iter;
-struct Iter
-{
-       int     done;
-       Type*   tfunc;
-       Type*   t;
-       Node**  an;
-       Node*   n;
-};
-
-// Node ops.
-enum
-{
-       OXXX,
-
-       // names
-       ONAME,  // var, const or func name
-       ONONAME,        // unnamed arg or return value: f(int, string) (int, error) { etc }
-       OTYPE,  // type name
-       OPACK,  // import
-       OLITERAL, // literal
-
-       // expressions
-       OADD,   // x + y
-       OSUB,   // x - y
-       OOR,    // x | y
-       OXOR,   // x ^ y
-       OADDSTR,        // s + "foo"
-       OADDR,  // &x
-       OANDAND,        // b0 && b1
-       OAPPEND,        // append
-       OARRAYBYTESTR,  // string(bytes)
-       OARRAYBYTESTRTMP, // string(bytes) ephemeral
-       OARRAYRUNESTR,  // string(runes)
-       OSTRARRAYBYTE,  // []byte(s)
-       OSTRARRAYBYTETMP,       // []byte(s) ephemeral
-       OSTRARRAYRUNE,  // []rune(s)
-       OAS,    // x = y or x := y
-       OAS2,   // x, y, z = xx, yy, zz
-       OAS2FUNC,       // x, y = f()
-       OAS2RECV,       // x, ok = <-c
-       OAS2MAPR,       // x, ok = m["foo"]
-       OAS2DOTTYPE,    // x, ok = I.(int)
-       OASOP,  // x += y
-       OCALL,  // function call, method call or type conversion, possibly preceded by defer or go.
-       OCALLFUNC,      // f()
-       OCALLMETH,      // t.Method()
-       OCALLINTER,     // err.Error()
-       OCALLPART,      // t.Method (without ())
-       OCAP,   // cap
-       OCLOSE, // close
-       OCLOSURE,       // f = func() { etc }
-       OCMPIFACE,      // err1 == err2
-       OCMPSTR,        // s1 == s2
-       OCOMPLIT,       // composite literal, typechecking may convert to a more specific OXXXLIT.
-       OMAPLIT,        // M{"foo":3, "bar":4}
-       OSTRUCTLIT,     // T{x:3, y:4}
-       OARRAYLIT,      // [2]int{3, 4}
-       OPTRLIT,        // &T{x:3, y:4}
-       OCONV,  // var i int; var u uint; i = int(u)
-       OCONVIFACE,     // I(t)
-       OCONVNOP,       // type Int int; var i int; var j Int; i = int(j)
-       OCOPY,  // copy
-       ODCL,   // var x int
-       ODCLFUNC,       // func f() or func (r) f()
-       ODCLFIELD,      // struct field, interface field, or func/method argument/return value.
-       ODCLCONST,      // const pi = 3.14
-       ODCLTYPE,       // type Int int
-       ODELETE,        // delete
-       ODOT,   // t.x
-       ODOTPTR,        // p.x that is implicitly (*p).x
-       ODOTMETH,       // t.Method
-       ODOTINTER,      // err.Error
-       OXDOT,  // t.x, typechecking may convert to a more specific ODOTXXX.
-       ODOTTYPE,       // e = err.(MyErr)
-       ODOTTYPE2,      // e, ok = err.(MyErr)
-       OEQ,    // x == y
-       ONE,    // x != y
-       OLT,    // x < y
-       OLE,    // x <= y
-       OGE,    // x >= y
-       OGT,    // x > y
-       OIND,   // *p
-       OINDEX, // a[i]
-       OINDEXMAP,      // m[s]
-       OKEY,   // The x:3 in t{x:3, y:4}, the 1:2 in a[1:2], the 2:20 in [3]int{2:20}, etc.
-       OPARAM, // The on-stack copy of a parameter or return value that escapes.
-       OLEN,   // len
-       OMAKE,  // make, typechecking may convert to a more specific OMAKEXXX.
-       OMAKECHAN,      // make(chan int)
-       OMAKEMAP,       // make(map[string]int)
-       OMAKESLICE,     // make([]int, 0)
-       OMUL,   // x * y
-       ODIV,   // x / y
-       OMOD,   // x % y
-       OLSH,   // x << u
-       ORSH,   // x >> u
-       OAND,   // x & y
-       OANDNOT,        // x &^ y
-       ONEW,   // new
-       ONOT,   // !b
-       OCOM,   // ^x
-       OPLUS,  // +x
-       OMINUS, // -y
-       OOROR,  // b1 || b2
-       OPANIC, // panic
-       OPRINT, // print
-       OPRINTN,        // println
-       OPAREN, // (x)
-       OSEND,  // c <- x
-       OSLICE, // v[1:2], typechecking may convert to a more specific OSLICEXXX.
-       OSLICEARR,      // a[1:2]
-       OSLICESTR,      // s[1:2]
-       OSLICE3,        // v[1:2:3], typechecking may convert to OSLICE3ARR.
-       OSLICE3ARR,     // a[1:2:3]
-       ORECOVER,       // recover
-       ORECV,  // <-c
-       ORUNESTR,       // string(i)
-       OSELRECV,       // case x = <-c:
-       OSELRECV2,      // case x, ok = <-c:
-       OIOTA,  // iota
-       OREAL,  // real
-       OIMAG,  // imag
-       OCOMPLEX,       // complex
-
-       // statements
-       OBLOCK, // block of code
-       OBREAK, // break
-       OCASE,  // case, after being verified by swt.c's casebody.
-       OXCASE, // case, before verification.
-       OCONTINUE,      // continue
-       ODEFER, // defer
-       OEMPTY, // no-op
-       OFALL,  // fallthrough, after being verified by swt.c's casebody.
-       OXFALL, // fallthrough, before verification.
-       OFOR,   // for
-       OGOTO,  // goto
-       OIF,    // if
-       OLABEL, // label:
-       OPROC,  // go
-       ORANGE, // range
-       ORETURN,        // return
-       OSELECT,        // select
-       OSWITCH,        // switch x
-       OTYPESW,        // switch err.(type)
-
-       // types
-       OTCHAN, // chan int
-       OTMAP,  // map[string]int
-       OTSTRUCT,       // struct{}
-       OTINTER,        // interface{}
-       OTFUNC, // func()
-       OTARRAY,        // []int, [8]int, [N]int or [...]int
-
-       // misc
-       ODDD,   // func f(args ...int) or f(l...) or var a = [...]int{0, 1, 2}.
-       ODDDARG,        // func f(args ...int), introduced by escape analysis.
-       OINLCALL,       // intermediary representation of an inlined call.
-       OEFACE, // itable and data words of an empty-interface value.
-       OITAB,  // itable word of an interface value.
-       OSPTR,  // base pointer of a slice or string.
-       OCLOSUREVAR, // variable reference at beginning of closure function
-       OCFUNC, // reference to c function pointer (not go func value)
-       OCHECKNIL, // emit code to ensure pointer/interface not nil
-       OVARKILL, // variable is dead
-
-       // thearch-specific registers
-       OREGISTER,      // a register, such as AX.
-       OINDREG,        // offset plus indirect of a register, such as 8(SP).
-
-       // 386/amd64-specific opcodes
-       OCMP,   // compare: ACMP.
-       ODEC,   // decrement: ADEC.
-       OINC,   // increment: AINC.
-       OEXTEND,        // extend: ACWD/ACDQ/ACQO.
-       OHMUL, // high mul: AMUL/AIMUL for unsigned/signed (OMUL uses AIMUL for both).
-       OLROT,  // left rotate: AROL.
-       ORROTC, // right rotate-carry: ARCR.
-       ORETJMP,        // return to other function
-
-       OEND,
-};
-
-enum
-{
-       Txxx,                   // 0
-
-       TINT8,  TUINT8,         // 1
-       TINT16, TUINT16,
-       TINT32, TUINT32,
-       TINT64, TUINT64,
-       TINT, TUINT, TUINTPTR,
-
-       TCOMPLEX64,             // 12
-       TCOMPLEX128,
-
-       TFLOAT32,               // 14
-       TFLOAT64,
-
-       TBOOL,                  // 16
-
-       TPTR32, TPTR64,         // 17
-
-       TFUNC,                  // 19
-       TARRAY,
-       T_old_DARRAY,
-       TSTRUCT,                // 22
-       TCHAN,
-       TMAP,
-       TINTER,                 // 25
-       TFORW,
-       TFIELD,
-       TANY,
-       TSTRING,
-       TUNSAFEPTR,
-
-       // pseudo-types for literals
-       TIDEAL,                 // 31
-       TNIL,
-       TBLANK,
-
-       // pseudo-type for frame layout
-       TFUNCARGS,
-       TCHANARGS,
-       TINTERMETH,
-
-       NTYPE,
-};
-
-enum
-{
-       CTxxx,
-
-       CTINT,
-       CTRUNE,
-       CTFLT,
-       CTCPLX,
-       CTSTR,
-       CTBOOL,
-       CTNIL,
-};
-
-enum
-{
-       /* types of channel */
-       /* must match ../../pkg/nreflect/type.go:/Chandir */
-       Cxxx,
-       Crecv = 1<<0,
-       Csend = 1<<1,
-       Cboth = Crecv | Csend,
-};
-
-// declaration context
-enum
-{
-       Pxxx,
-
-       PEXTERN,        // global variable
-       PAUTO,          // local variables
-       PPARAM,         // input arguments
-       PPARAMOUT,      // output results
-       PPARAMREF,      // closure variable reference
-       PFUNC,          // global function
-
-       PDISCARD,       // discard during parse of duplicate import
-
-       PHEAP = 1<<7,   // an extra bit to identify an escaped variable
-};
-
-enum
-{
-       Etop = 1<<1,            // evaluated at statement level
-       Erv = 1<<2,             // evaluated in value context
-       Etype = 1<<3,
-       Ecall = 1<<4,           // call-only expressions are ok
-       Efnstruct = 1<<5,       // multivalue function returns are ok
-       Eiota = 1<<6,           // iota is ok
-       Easgn = 1<<7,           // assigning to expression
-       Eindir = 1<<8,          // indirecting through expression
-       Eaddr = 1<<9,           // taking address of expression
-       Eproc = 1<<10,          // inside a go statement
-       Ecomplit = 1<<11,       // type in composite literal
-};
-
-enum {
-       BITS = 3,
-       NVAR =  (BITS*64)
-};
-
-typedef        struct  Bits    Bits;
-struct Bits
-{
-       uint64  b[BITS];
-};
-
-EXTERN Bits    zbits;
-
-struct Bvec
-{
-       int32   n;      // number of bits
-       uint32  b[];
-};
-
-typedef        struct  Var     Var;
-struct Var
-{
-       vlong   offset;
-       Node*   node;
-       Var*    nextinnode;
-       int     width;
-       int     id;
-       char    name;
-       char    etype;
-       char    addr;
-};
-
-EXTERN Var     var[NVAR];
-
-typedef        struct  Typedef Typedef;
-struct Typedef
-{
-       char*   name;
-       int     etype;
-       int     sameas;
-};
-
-typedef        struct  Sig     Sig;
-struct Sig
-{
-       char*   name;
-       Pkg*    pkg;
-       Sym*    isym;
-       Sym*    tsym;
-       Type*   type;
-       Type*   mtype;
-       int32   offset;
-       Sig*    link;
-};
-
-typedef        struct  Io      Io;
-struct Io
-{
-       char*   infile;
-       Biobuf* bin;
-       int32   ilineno;
-       int     nlsemi;
-       int     eofnl;
-       int     last;
-       int     peekc;
-       int     peekc1; // second peekc for ...
-       char*   cp;     // used for content when bin==nil
-       int     importsafe;
-};
-
-typedef        struct  Dlist   Dlist;
-struct Dlist
-{
-       Type*   field;
-};
-
-typedef        struct  Idir    Idir;
-struct Idir
-{
-       Idir*   link;
-       char*   dir;
-};
-
-/*
- * argument passing to/from
- * smagic and umagic
- */
-typedef        struct  Magic Magic;
-struct Magic
-{
-       int     w;      // input for both - width
-       int     s;      // output for both - shift
-       int     bad;    // output for both - unexpected failure
-
-       // magic multiplier for signed literal divisors
-       int64   sd;     // input - literal divisor
-       int64   sm;     // output - multiplier
-
-       // magic multiplier for unsigned literal divisors
-       uint64  ud;     // input - literal divisor
-       uint64  um;     // output - multiplier
-       int     ua;     // output - adder
-};
-
-struct Label
-{
-       uchar   used;
-       Sym*    sym;
-       Node*   def;
-       NodeList*       use;
-       Label*  link;
-       
-       // for use during gen
-       Prog*   gotopc; // pointer to unresolved gotos
-       Prog*   labelpc;        // pointer to code
-       Prog*   breakpc;        // pointer to code
-       Prog*   continpc;       // pointer to code
-};
-#define        L       ((Label*)0)
-
-/*
- * note this is the runtime representation
- * of the compilers arrays.
- *
- * typedef     struct
- * {                           // must not move anything
- *     uchar   array[8];       // pointer to data
- *     uchar   nel[4];         // number of elements
- *     uchar   cap[4];         // allocated number of elements
- * } Array;
- */
-EXTERN int     Array_array;    // runtime offsetof(Array,array) - same for String
-EXTERN int     Array_nel;      // runtime offsetof(Array,nel) - same for String
-EXTERN int     Array_cap;      // runtime offsetof(Array,cap)
-EXTERN int     sizeof_Array;   // runtime sizeof(Array)
-
-
-/*
- * note this is the runtime representation
- * of the compilers strings.
- *
- * typedef     struct
- * {                           // must not move anything
- *     uchar   array[8];       // pointer to data
- *     uchar   nel[4];         // number of elements
- * } String;
- */
-EXTERN int     sizeof_String;  // runtime sizeof(String)
-
-EXTERN Dlist   dotlist[10];    // size is max depth of embeddeds
-
-EXTERN Io      curio;
-EXTERN Io      pushedio;
-EXTERN int32   lexlineno;
-EXTERN int32   lineno;
-EXTERN int32   prevlineno;
-
-EXTERN Fmt     pragcgobuf;
-
-EXTERN char*   infile;
-EXTERN char*   outfile;
-EXTERN Biobuf* bout;
-EXTERN int     nerrors;
-EXTERN int     nsavederrors;
-EXTERN int     nsyntaxerrors;
-EXTERN int     decldepth;
-EXTERN int     safemode;
-EXTERN int     nolocalimports;
-EXTERN char    namebuf[NSYMB];
-EXTERN char    lexbuf[NSYMB];
-EXTERN char    litbuf[NSYMB];
-EXTERN int     debug[256];
-EXTERN char*   debugstr;
-EXTERN int     debug_checknil;
-EXTERN Sym*    hash[NHASH];
-EXTERN Sym*    importmyname;   // my name for package
-EXTERN Pkg*    localpkg;       // package being compiled
-EXTERN Pkg*    importpkg;      // package being imported
-EXTERN Pkg*    structpkg;      // package that declared struct, during import
-EXTERN Pkg*    builtinpkg;     // fake package for builtins
-EXTERN Pkg*    gostringpkg;    // fake pkg for Go strings
-EXTERN Pkg*    itabpkg;        // fake pkg for itab cache
-EXTERN Pkg*    runtimepkg;     // package runtime
-EXTERN Pkg*    racepkg;        // package runtime/race
-EXTERN Pkg*    stringpkg;      // fake package for C strings
-EXTERN Pkg*    typepkg;        // fake package for runtime type info (headers)
-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;
-extern char*   unsafeimport;
-EXTERN char*   myimportpath;
-EXTERN Idir*   idirs;
-EXTERN char*   localimport;
-EXTERN char*   asmhdr;
-
-EXTERN Type*   types[NTYPE];
-EXTERN Type*   idealstring;
-EXTERN Type*   idealbool;
-EXTERN Type*   bytetype;
-EXTERN Type*   runetype;
-EXTERN Type*   errortype;
-EXTERN uchar   simtype[NTYPE];
-EXTERN uchar   isptr[NTYPE];
-EXTERN uchar   isforw[NTYPE];
-EXTERN uchar   isint[NTYPE];
-EXTERN uchar   isfloat[NTYPE];
-EXTERN uchar   iscomplex[NTYPE];
-EXTERN uchar   issigned[NTYPE];
-EXTERN uchar   issimple[NTYPE];
-
-EXTERN uchar   okforeq[NTYPE];
-EXTERN uchar   okforadd[NTYPE];
-EXTERN uchar   okforand[NTYPE];
-EXTERN uchar   okfornone[NTYPE];
-EXTERN uchar   okforcmp[NTYPE];
-EXTERN uchar   okforbool[NTYPE];
-EXTERN uchar   okforcap[NTYPE];
-EXTERN uchar   okforlen[NTYPE];
-EXTERN uchar   okforarith[NTYPE];
-EXTERN uchar   okforconst[NTYPE];
-EXTERN uchar*  okfor[OEND];
-EXTERN uchar   iscmp[OEND];
-
-EXTERN Mpint*  minintval[NTYPE];
-EXTERN Mpint*  maxintval[NTYPE];
-EXTERN Mpflt*  minfltval[NTYPE];
-EXTERN Mpflt*  maxfltval[NTYPE];
-
-EXTERN NodeList*       xtop;
-EXTERN NodeList*       externdcl;
-EXTERN NodeList*       exportlist;
-EXTERN NodeList*       importlist;     // imported functions and methods with inlinable bodies
-EXTERN NodeList*       funcsyms;
-EXTERN int     dclcontext;             // PEXTERN/PAUTO
-EXTERN int     incannedimport;
-EXTERN int     statuniqgen;            // name generator for static temps
-EXTERN int     loophack;
-
-EXTERN int32   iota;
-EXTERN NodeList*       lastconst;
-EXTERN Node*   lasttype;
-EXTERN vlong   maxarg;
-EXTERN vlong   stksize;                // stack size for current frame
-EXTERN vlong   stkptrsize;             // prefix of stack containing pointers
-EXTERN int32   blockgen;               // max block number
-EXTERN int32   block;                  // current block number
-EXTERN int     hasdefer;               // flag that curfn has defer statetment
-
-EXTERN Node*   curfn;
-
-EXTERN int     widthptr;
-EXTERN int     widthint;
-EXTERN int     widthreg;
-
-EXTERN Node*   typesw;
-EXTERN Node*   nblank;
-
-EXTERN int     use_sse;
-
-EXTERN char*   hunk;
-EXTERN int32   nhunk;
-EXTERN int32   thunk;
-
-EXTERN int     funcdepth;
-EXTERN int     typecheckok;
-EXTERN int     compiling_runtime;
-EXTERN int     compiling_wrappers;
-EXTERN int     inl_nonlocal;
-EXTERN int     use_writebarrier;
-EXTERN int     pure_go;
-EXTERN char*   flag_installsuffix;
-EXTERN int     flag_race;
-EXTERN int     flag_largemodel;
-EXTERN int     noescape;
-EXTERN int     nosplit;
-EXTERN int     nowritebarrier;
-EXTERN int     debuglive;
-EXTERN Link*   ctxt;
-
-EXTERN int     nointerface;
-EXTERN int     writearchive;
-
-EXTERN Biobuf  bstdout;
-
-EXTERN int     nacl;
-
-/*
- *     y.tab.c
- */
-int    yyparse(void);
-
-/*
- *     align.c
- */
-int    argsize(Type *t);
-void   checkwidth(Type *t);
-void   defercheckwidth(void);
-void   dowidth(Type *t);
-void   resumecheckwidth(void);
-vlong  rnd(vlong o, vlong r);
-void   typeinit(void);
-
-/*
- *     array.c
- */
-Array* arraynew(int32 capacity, int32 size);
-void   arrayfree(Array *array);
-int32  arraylength(Array *array);
-void*  arrayget(Array *array, int32 index);
-void   arrayset(Array *array, int32 index, void *element);
-void   arrayadd(Array *array, void *element);
-void   arraysort(Array* array, int (*cmp)(const void*, const void*));
-
-/*
- *     bits.c
- */
-int    Qconv(Fmt *fp);
-Bits   band(Bits a, Bits b);
-int    bany(Bits *a);
-int    beq(Bits a, Bits b);
-int    bitno(uint64 b);
-Bits   blsh(uint n);
-Bits   bnot(Bits a);
-int    bnum(Bits a);
-Bits   bor(Bits a, Bits b);
-int    btest(Bits *a, uint n);
-void   biset(Bits *a, uint n);
-void   biclr(Bits *a, uint n);
-
-/*
- *     bv.c
- */
-Bvec*  bvalloc(int32 n);
-void   bvandnot(Bvec *dst, Bvec *src1, Bvec *src2);
-int    bvcmp(Bvec *bv1, Bvec *bv2);
-void   bvcopy(Bvec *dst, Bvec *src);
-Bvec*  bvconcat(Bvec *src1, Bvec *src2);
-int    bvget(Bvec *bv, int32 i);
-int32  bvnext(Bvec *bv, int32 i);
-int    bvisempty(Bvec *bv);
-void   bvnot(Bvec *bv);
-void   bvor(Bvec *dst, Bvec *src1, Bvec *src2);
-void   bvand(Bvec *dst, Bvec *src1, Bvec *src2);
-void   bvprint(Bvec *bv);
-void   bvreset(Bvec *bv, int32 i);
-void   bvresetall(Bvec *bv);
-void   bvset(Bvec *bv, int32 i);
-
-/*
- *     closure.c
- */
-Node*  closurebody(NodeList *body);
-void   closurehdr(Node *ntype);
-void   typecheckclosure(Node *func, int top);
-void   capturevars(Node *func);
-void   transformclosure(Node *func);
-Node*  walkclosure(Node *func, NodeList **init);
-void   typecheckpartialcall(Node*, Node*);
-Node*  walkpartialcall(Node*, NodeList**);
-
-/*
- *     const.c
- */
-int    cmpslit(Node *l, Node *r);
-int    consttype(Node *n);
-void   convconst(Node *con, Type *t, Val *val);
-void   convlit(Node **np, Type *t);
-void   convlit1(Node **np, Type *t, int explicit);
-void   defaultlit(Node **np, Type *t);
-void   defaultlit2(Node **lp, Node **rp, int force);
-void   evconst(Node *n);
-int    isconst(Node *n, int ct);
-int    isgoconst(Node *n);
-Node*  nodcplxlit(Val r, Val i);
-Node*  nodlit(Val v);
-long   nonnegconst(Node *n);
-int    doesoverflow(Val v, Type *t);
-void   overflow(Val v, Type *t);
-int    smallintconst(Node *n);
-Val    toint(Val v);
-Mpflt* truncfltlit(Mpflt *oldv, Type *t);
-
-/*
- *     cplx.c
- */
-void   complexadd(int op, Node *nl, Node *nr, Node *res);
-void   complexbool(int op, Node *nl, Node *nr, int true, int likely, Prog *to);
-void   complexgen(Node *n, Node *res);
-void   complexminus(Node *nl, Node *res);
-void   complexmove(Node *f, Node *t);
-void   complexmul(Node *nl, Node *nr, Node *res);
-int    complexop(Node *n, Node *res);
-void   nodfconst(Node *n, Type *t, Mpflt* fval);
-
-/*
- *     dcl.c
- */
-void   addmethod(Sym *sf, Type *t, int local, int nointerface);
-void   addvar(Node *n, Type *t, int ctxt);
-NodeList*      checkarglist(NodeList *all, int input);
-Node*  colas(NodeList *left, NodeList *right, int32 lno);
-void   colasdefn(NodeList *left, Node *defn);
-NodeList*      constiter(NodeList *vl, Node *t, NodeList *cl);
-Node*  dclname(Sym *s);
-void   declare(Node *n, int ctxt);
-void   dumpdcl(char *st);
-Node*  embedded(Sym *s, Pkg *pkg);
-Node*  fakethis(void);
-void   funcbody(Node *n);
-void   funccompile(Node *n);
-void   funchdr(Node *n);
-Type*  functype(Node *this, NodeList *in, NodeList *out);
-void   ifacedcl(Node *n);
-int    isifacemethod(Type *f);
-void   markdcl(void);
-Node*  methodname(Node *n, Type *t);
-Node*  methodname1(Node *n, Node *t);
-Sym*   methodsym(Sym *nsym, Type *t0, int iface);
-Node*  newname(Sym *s);
-Node*  oldname(Sym *s);
-void   popdcl(void);
-void   poptodcl(void);
-void   redeclare(Sym *s, char *where);
-void   testdclstack(void);
-Type*  tointerface(NodeList *l);
-Type*  tostruct(NodeList *l);
-Node*  typedcl0(Sym *s);
-Node*  typedcl1(Node *n, Node *t, int local);
-Node*  typenod(Type *t);
-NodeList*      variter(NodeList *vl, Node *t, NodeList *el);
-Sym*   funcsym(Sym*);
-
-/*
- *     esc.c
- */
-void   escapes(NodeList*);
-
-/*
- *     export.c
- */
-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);
-void   importimport(Sym *s, Strlit *z);
-Sym*    importsym(Sym *s, int op);
-void    importtype(Type *pt, Type *t);
-void    importvar(Sym *s, Type *t);
-Type*  pkgtype(Sym *s);
-
-/*
- *     fmt.c
- */
-void   fmtinstallgo(void);
-void   dump(char *s, Node *n);
-void   dumplist(char *s, NodeList *l);
-
-/*
- *     gen.c
- */
-void   addrescapes(Node *n);
-void   cgen_as(Node *nl, Node *nr);
-void   cgen_callmeth(Node *n, int proc);
-void   cgen_eface(Node* n, Node* res);
-void   cgen_slice(Node* n, Node* res);
-void   clearlabels(void);
-void   clearslim(Node*);
-void   checklabels(void);
-int    dotoffset(Node *n, int64 *oary, Node **nn);
-void   gen(Node *n);
-void   genlist(NodeList *l);
-Node*  sysfunc(char *name);
-void   tempname(Node *n, Type *t);
-Node*  temp(Type*);
-
-/*
- *     init.c
- */
-void   fninit(NodeList *n);
-Sym*   renameinit(void);
-
-/*
- *     inl.c
- */
-void   caninl(Node *fn);
-void   inlcalls(Node *fn);
-void   typecheckinl(Node *fn);
-
-/*
- *     lex.c
- */
-void   cannedimports(char *file, char *cp);
-void   importfile(Val *f, int line);
-char*  lexname(int lex);
-char*  expstring(void);
-void   mkpackage(char* pkgname);
-void   unimportfile(void);
-int32  yylex(void);
-extern int     yylast;
-extern int     yyprev;
-
-/*
- *     mparith1.c
- */
-int    Bconv(Fmt *fp);
-int    Fconv(Fmt *fp);
-void   mpaddcfix(Mpint *a, vlong c);
-void   mpaddcflt(Mpflt *a, double c);
-void   mpatofix(Mpint *a, char *as);
-void   mpatoflt(Mpflt *a, char *as);
-int    mpcmpfixc(Mpint *b, vlong c);
-int    mpcmpfixfix(Mpint *a, Mpint *b);
-int    mpcmpfixflt(Mpint *a, Mpflt *b);
-int    mpcmpfltc(Mpflt *b, double c);
-int    mpcmpfltfix(Mpflt *a, Mpint *b);
-int    mpcmpfltflt(Mpflt *a, Mpflt *b);
-void   mpcomfix(Mpint *a);
-void   mpdivfixfix(Mpint *a, Mpint *b);
-void   mpmodfixfix(Mpint *a, Mpint *b);
-void   mpmovefixfix(Mpint *a, Mpint *b);
-void   mpmovefixflt(Mpflt *a, Mpint *b);
-int    mpmovefltfix(Mpint *a, Mpflt *b);
-void   mpmovefltflt(Mpflt *a, Mpflt *b);
-void   mpmulcfix(Mpint *a, vlong c);
-void   mpmulcflt(Mpflt *a, double c);
-void   mpsubfixfix(Mpint *a, Mpint *b);
-void   mpsubfltflt(Mpflt *a, Mpflt *b);
-
-/*
- *     mparith2.c
- */
-void   mpaddfixfix(Mpint *a, Mpint *b, int);
-void   mpandfixfix(Mpint *a, Mpint *b);
-void   mpandnotfixfix(Mpint *a, Mpint *b);
-void   mpdivfract(Mpint *a, Mpint *b);
-void   mpdivmodfixfix(Mpint *q, Mpint *r, Mpint *n, Mpint *d);
-vlong  mpgetfix(Mpint *a);
-void   mplshfixfix(Mpint *a, Mpint *b);
-void   mpmovecfix(Mpint *a, vlong c);
-void   mpmulfixfix(Mpint *a, Mpint *b);
-void   mpmulfract(Mpint *a, Mpint *b);
-void   mpnegfix(Mpint *a);
-void   mporfixfix(Mpint *a, Mpint *b);
-void   mprshfixfix(Mpint *a, Mpint *b);
-void   mpshiftfix(Mpint *a, int s);
-int    mptestfix(Mpint *a);
-void   mpxorfixfix(Mpint *a, Mpint *b);
-
-/*
- *     mparith3.c
- */
-void   mpaddfltflt(Mpflt *a, Mpflt *b);
-void   mpdivfltflt(Mpflt *a, Mpflt *b);
-double mpgetflt(Mpflt *a);
-double mpgetflt32(Mpflt *a);
-void   mpmovecflt(Mpflt *a, double c);
-void   mpmulfltflt(Mpflt *a, Mpflt *b);
-void   mpnegflt(Mpflt *a);
-void   mpnorm(Mpflt *a);
-void   mpsetexp(Mpflt *a, int exp);
-int    mptestflt(Mpflt *a);
-int    sigfig(Mpflt *a);
-
-/*
- *     obj.c
- */
-void   Bputname(Biobuf *b, LSym *s);
-int    duint16(Sym *s, int off, uint16 v);
-int    duint32(Sym *s, int off, uint32 v);
-int    duint64(Sym *s, int off, uint64 v);
-int    duint8(Sym *s, int off, uint8 v);
-int    duintptr(Sym *s, int off, uint64 v);
-void   dumpobj(void);
-Sym*   stringsym(char*, int);
-void   slicebytes(Node*, char*, int);
-LSym*  linksym(Sym*);
-
-/*
- *     order.c
- */
-void   order(Node *fn);
-void   orderstmtinplace(Node **stmt);
-
-/*
- *     range.c
- */
-void   typecheckrange(Node *n);
-void   walkrange(Node *n);
-
-/*
- *     reflect.c
- */
-void   dumptypestructs(void);
-Type*  methodfunc(Type *f, Type*);
-Node*  typename(Type *t);
-Sym*   typesym(Type *t);
-Sym*   typenamesym(Type *t);
-Sym*   tracksym(Type *t);
-Sym*   typesymprefix(char *prefix, Type *t);
-int    haspointers(Type *t);
-Type*  hmap(Type *t);
-Type*  hiter(Type* t);
-Type*  mapbucket(Type *t);
-
-/*
- *     select.c
- */
-void   typecheckselect(Node *sel);
-void   walkselect(Node *sel);
-
-/*
- *     sinit.c
- */
-void   anylit(int, Node *n, Node *var, NodeList **init);
-int    gen_as_init(Node *n);
-NodeList*      initfix(NodeList *l);
-int    oaslit(Node *n, NodeList **init);
-int    stataddr(Node *nam, Node *n);
-
-/*
- *     subr.c
- */
-Node*  adddot(Node *n);
-int    adddot1(Sym *s, Type *t, int d, Type **save, int ignorecase);
-void   addinit(Node**, NodeList*);
-Type*  aindex(Node *b, Type *t);
-int    algtype(Type *t);
-int    algtype1(Type *t, Type **bad);
-void   argtype(Node *on, Type *t);
-Node*  assignconv(Node *n, Type *t, char *context);
-int    assignop(Type *src, Type *dst, char **why);
-void   badtype(int o, Type *tl, Type *tr);
-int    brcom(int a);
-int    brrev(int a);
-NodeList*      concat(NodeList *a, NodeList *b);
-int    convertop(Type *src, Type *dst, char **why);
-Node*  copyexpr(Node*, Type*, NodeList**);
-int    count(NodeList *l);
-int    cplxsubtype(int et);
-int    eqtype(Type *t1, Type *t2);
-int    eqtypenoname(Type *t1, Type *t2);
-void   errorexit(void);
-void   expandmeth(Type *t);
-void   fatal(char *fmt, ...);
-void   flusherrors(void);
-void   frame(int context);
-Type*  funcfirst(Iter *s, Type *t);
-Type*  funcnext(Iter *s);
-void   genwrapper(Type *rcvr, Type *method, Sym *newnam, int iface);
-void   genhash(Sym *sym, Type *t);
-void   geneq(Sym *sym, Type *t);
-Type** getinarg(Type *t);
-Type*  getinargx(Type *t);
-Type** getoutarg(Type *t);
-Type*  getoutargx(Type *t);
-Type** getthis(Type *t);
-Type*  getthisx(Type *t);
-int    implements(Type *t, Type *iface, Type **missing, Type **have, int *ptr);
-void   importdot(Pkg *opkg, Node *pack);
-int    is64(Type *t);
-int    isbadimport(Strlit *s);
-int    isblank(Node *n);
-int    isblanksym(Sym *s);
-int    isdirectiface(Type*);
-int    isfixedarray(Type *t);
-int    isideal(Type *t);
-int    isinter(Type *t);
-int    isnil(Node *n);
-int    isnilinter(Type *t);
-int    isptrto(Type *t, int et);
-int    isslice(Type *t);
-int    istype(Type *t, int et);
-int    iszero(Node *n);
-void   linehist(char *file, int32 off, int relative);
-NodeList*      list(NodeList *l, Node *n);
-NodeList*      list1(Node *n);
-void   listsort(NodeList**, int(*f)(Node*, Node*));
-Node*  liststmt(NodeList *l);
-NodeList*      listtreecopy(NodeList *l);
-Sym*   lookup(char *name);
-void*  mal(int32 n);
-Type*  maptype(Type *key, Type *val);
-Type*  methtype(Type *t, int mustname);
-Pkg*   mkpkg(Strlit *path);
-Sym*   ngotype(Node *n);
-int    noconv(Type *t1, Type *t2);
-Node*  nod(int op, Node *nleft, Node *nright);
-Node*  nodbool(int b);
-void   nodconst(Node *n, Type *t, int64 v);
-Node*  nodintconst(int64 v);
-Node*  nodfltconst(Mpflt *v);
-Node*  nodnil(void);
-int    parserline(void);
-Sym*   pkglookup(char *name, Pkg *pkg);
-int    powtwo(Node *n);
-Type*  ptrto(Type *t);
-void*  remal(void *p, int32 on, int32 n);
-Sym*   restrictlookup(char *name, Pkg *pkg);
-Node*  safeexpr(Node *n, NodeList **init);
-void   saveerrors(void);
-Node*  cheapexpr(Node *n, NodeList **init);
-Node*  localexpr(Node *n, Type *t, NodeList **init);
-void   saveorignode(Node *n);
-int32  setlineno(Node *n);
-void   setmaxarg(Type *t, int32 extra);
-Type*  shallow(Type *t);
-int    simsimtype(Type *t);
-void   smagic(Magic *m);
-Type*  sortinter(Type *t);
-uint32 stringhash(char *p);
-Strlit*        newstrlit(char *s);
-int    structcount(Type *t);
-Type*  structfirst(Iter *s, Type **nn);
-Type*  structnext(Iter *s);
-Node*  syslook(char *name, int copy);
-Type*  tounsigned(Type *t);
-Node*  treecopy(Node *n);
-Type*  typ(int et);
-uint32 typehash(Type *t);
-void   ullmancalc(Node *n);
-void   umagic(Magic *m);
-void   warn(char *fmt, ...);
-void   warnl(int line, char *fmt, ...);
-void   yyerror(char *fmt, ...);
-void   yyerrorl(int line, char *fmt, ...);
-void   adderrorname(Node*);
-
-/*
- *     swt.c
- */
-void   typecheckswitch(Node *n);
-void   walkswitch(Node *sw);
-
-/*
- *     typecheck.c
- */
-int    islvalue(Node *n);
-int    samesafeexpr(Node *l, Node *r);
-Node*  typecheck(Node **np, int top);
-void   typechecklist(NodeList *l, int top);
-Node*  typecheckdef(Node *n);
-void   copytype(Node *n, Type *t);
-void   checkreturn(Node*);
-void   checkassign(Node *stmt, Node*);
-void   queuemethod(Node *n);
-
-/*
- *     unsafe.c
- */
-int    isunsafebuiltin(Node *n);
-Node*  unsafenmagic(Node *n);
-
-/*
- *     walk.c
- */
-Node*  callnew(Type *t);
-Node*  chanfn(char *name, int n, Type *t);
-Node*  mkcall(char *name, Type *t, NodeList **init, ...);
-Node*  mkcall1(Node *fn, Type *t, NodeList **init, ...);
-int    vmatch1(Node *l, Node *r);
-void   walk(Node *fn);
-void   walkexpr(Node **np, NodeList **init);
-void   walkexprlist(NodeList *l, NodeList **init);
-void   walkexprlistsafe(NodeList *l, NodeList **init);
-void   walkexprlistcheap(NodeList *l, NodeList **init);
-void   walkstmt(Node **np);
-void   walkstmtlist(NodeList *l);
-Node*  conv(Node*, Type*);
-int    candiscard(Node*);
-int    needwritebarrier(Node*, Node*);
-Node*  outervalue(Node*);
-void   usefield(Node*);
-
-/*
- *     thearch-specific ggen.c/gsubr.c/gobj.c/pgen.c/plive.c
- */
-#define        P       ((Prog*)0)
-
-EXTERN Prog*   continpc;
-EXTERN Prog*   breakpc;
-EXTERN Prog*   pc;
-EXTERN Prog*   firstpc;
-
-EXTERN Node*   nodfp;
-EXTERN int     disable_checknil;
-EXTERN vlong   zerosize;
-
-void   checknil(Node*, NodeList**);
-void   cgen_checknil(Node*);
-void   compile(Node*);
-int    duintxx(Sym *s, int off, uint64 v, int wid);
-void   gvardef(Node*);
-void   gvarkill(Node*);
-void   movelarge(NodeList*);
-void   liveness(Node*, Prog*, Sym*, Sym*);
-void   twobitwalktype1(Type*, vlong*, Bvec*);
-
-#pragma        varargck        type    "B"     Mpint*
-#pragma        varargck        type    "E"     int
-#pragma        varargck        type    "E"     uint
-#pragma        varargck        type    "F"     Mpflt*
-#pragma        varargck        type    "H"     NodeList*
-#pragma        varargck        type    "J"     Node*
-#pragma        varargck        type    "lL"    int32
-#pragma        varargck        type    "L"     int32
-#pragma        varargck        type    "N"     Node*
-#pragma        varargck        type    "lN"    Node*
-#pragma        varargck        type    "O"     int
-#pragma        varargck        type    "O"     uint
-#pragma        varargck        type    "Q"     Bits
-#pragma        varargck        type    "S"     Sym*
-#pragma        varargck        type    "lS"    LSym*
-#pragma        varargck        type    "T"     Type*
-#pragma        varargck        type    "lT"    Type*
-#pragma        varargck        type    "V"     Val*
-#pragma        varargck        type    "Z"     Strlit*
-
-/*
- *     racewalk.c
- */
-void   racewalk(Node *fn);
-
-/*
- *     flow.c
- */
-typedef struct Flow Flow;
-typedef struct Graph Graph;
-
-struct Flow {
-       Prog*   prog;           // actual instruction
-       Flow*   p1;             // predecessors of this instruction: p1,
-       Flow*   p2;             // and then p2 linked though p2link.
-       Flow*   p2link;
-       Flow*   s1;             // successors of this instruction (at most two: s1 and s2).
-       Flow*   s2;
-       Flow*   link;           // next instruction in function code
-       
-       int32   active; // usable by client
-
-       int32   id;             // sequence number in flow graph
-       int32   rpo;            // reverse post ordering
-       uint16  loop;           // x5 for every loop
-       uchar   refset;         // diagnostic generated
-       
-       void*   data;   // for use by client
-};
-
-struct Graph
-{
-       Flow*   start;
-       int     num;
-       
-       // After calling flowrpo, rpo lists the flow nodes in reverse postorder,
-       // and each non-dead Flow node f has g->rpo[f->rpo] == f.
-       Flow**  rpo;
-};
-
-void   fixjmp(Prog*);
-Graph* flowstart(Prog*, int);
-void   flowrpo(Graph*);
-void   flowend(Graph*);
-void   mergetemp(Prog*);
-void   nilopt(Prog*);
-int    noreturn(Prog*);
-Flow*  uniqp(Flow*);
-Flow*  uniqs(Flow*);
-
-/*
- *     interface to back end
- */
-
-typedef struct ProgInfo ProgInfo;
-struct ProgInfo
-{
-       uint32 flags; // the bits below
-       uint64 reguse; // registers implicitly used by this instruction
-       uint64 regset; // registers implicitly set by this instruction
-       uint64 regindex; // registers used by addressing mode
-};
-
-enum
-{
-       // Pseudo-op, like TEXT, GLOBL, TYPE, PCDATA, FUNCDATA.
-       Pseudo = 1<<1,
-       
-       // There's nothing to say about the instruction,
-       // but it's still okay to see.
-       OK = 1<<2,
-
-       // Size of right-side write, or right-side read if no write.
-       SizeB = 1<<3,
-       SizeW = 1<<4,
-       SizeL = 1<<5,
-       SizeQ = 1<<6,
-       SizeF = 1<<7, // float aka float32
-       SizeD = 1<<8, // double aka float64
-
-       // Left side (Prog.from): address taken, read, write.
-       LeftAddr = 1<<9,
-       LeftRead = 1<<10,
-       LeftWrite = 1<<11,
-       
-       // Register in middle (Prog.reg); only ever read. (arm, ppc64)
-       RegRead = 1<<12,
-       CanRegRead = 1<<13,
-       
-       // Right side (Prog.to): address taken, read, write.
-       RightAddr = 1<<14,
-       RightRead = 1<<15,
-       RightWrite = 1<<16,
-
-       // Instruction kinds
-       Move = 1<<17, // straight move
-       Conv = 1<<18, // size conversion
-       Cjmp = 1<<19, // conditional jump
-       Break = 1<<20, // breaks control flow (no fallthrough)
-       Call = 1<<21, // function call
-       Jump = 1<<22, // jump
-       Skip = 1<<23, // data instruction
-
-       // Set, use, or kill of carry bit.
-       // Kill means we never look at the carry bit after this kind of instruction.
-       SetCarry = 1<<24,
-       UseCarry = 1<<25,
-       KillCarry = 1<<26,
-
-       // Special cases for register use. (amd64, 386)
-       ShiftCX = 1<<27, // possible shift by CX
-       ImulAXDX = 1<<28, // possible multiply into DX:AX
-
-       // Instruction updates whichever of from/to is type D_OREG. (ppc64)
-       PostInc = 1<<29,
-};
-
-typedef struct Arch Arch;
-
-struct Arch
-{
-       int thechar;
-       char *thestring;
-       LinkArch *thelinkarch;
-       Typedef *typedefs;
-
-       int     REGSP;
-       int     REGCTXT;
-       vlong MAXWIDTH;
-
-       int (*anyregalloc)(void);
-       void (*betypeinit)(void);
-       void (*bgen)(Node*, int, int, Prog*);
-       void (*cgen)(Node*, Node*);
-       void (*cgen_call)(Node*, int);
-       void (*cgen_callinter)(Node*, Node*, int);
-       void (*cgen_ret)(Node*);
-       void (*clearfat)(Node*);
-       void (*defframe)(Prog*);
-       void (*excise)(Flow*);
-       void (*expandchecks)(Prog*);
-       void (*gclean)(void);
-       void (*ginit)(void);
-       Prog*   (*gins)(int, Node*, Node*);
-       void    (*ginscall)(Node*, int);
-       void    (*igen)(Node*, Node*, Node*);
-       void (*linkarchinit)(void);
-       void (*peep)(Prog*);
-       void (*proginfo)(ProgInfo*, Prog*);
-       void (*regalloc)(Node*, Type*, Node*);
-       void (*regfree)(Node*);
-       int (*regtyp)(Addr*);
-       int (*sameaddr)(Addr*, Addr*);
-       int (*smallindir)(Addr*, Addr*);
-       int (*stackaddr)(Addr*);
-       uint64 (*excludedregs)(void);
-       uint64 (*RtoB)(int);
-       uint64 (*FtoB)(int);
-       int (*BtoR)(uint64);
-       int (*BtoF)(uint64);
-       int (*optoas)(int, Type*);
-       uint64 (*doregbits)(int);
-       char **(*regnames)(int*);
-};
-
-void afunclit(Addr*, Node*);
-void clearp(Prog*);
-int dgostringptr(Sym*, int, char*);
-int dgostrlitptr(Sym*, int, Strlit*);
-int dsname(Sym*, int, char*, int);
-int dsymptr(Sym*, int, Sym*, int);
-void dumpdata(void);
-void fixautoused(Prog*);
-void   gdata(Node*, Node*, int);
-void   gdatacomplex(Node*, Mpcplx*);
-void   gdatastring(Node*, Strlit*);
-void   ggloblnod(Node*);
-void   ggloblsym(Sym*, int32, int8);
-Prog*  gjmp(Prog*);
-void gtrack(Sym*);
-void   gused(Node*);
-int isfat(Type*);
-void markautoused(Prog*);
-void naddr(Node*, Addr*, int);
-Plist* newplist(void);
-Node* nodarg(Type*, int);
-void patch(Prog*, Prog*);
-Prog* unpatch(Prog*);
-void datagostring(Strlit *sval, Addr *a);
-int ismem(Node*);
-int samereg(Node*, Node*);
-void   regopt(Prog*);
-int    Tconv(Fmt*);
-int    Oconv(Fmt*);
-Prog*  gbranch(int as, Type *t, int likely);
-void   nodindreg(Node *n, Type *t, int r);
-void   nodreg(Node *n, Type *t, int r);
-Prog*  prog(int as);
-void   datastring(char*, int, Addr*);
-
-EXTERN int32   pcloc;
-
-EXTERN Arch thearch;
-
-EXTERN Node *newproc;
-EXTERN Node *deferproc;
-EXTERN Node *deferreturn;
-EXTERN Node *panicindex;
-EXTERN Node *panicslice;
-EXTERN Node *throwreturn;
-
-int    gcmain(int, char**);
diff --git a/src/cmd/gc/go.y b/src/cmd/gc/go.y
deleted file mode 100644 (file)
index dc8b530..0000000
+++ /dev/null
@@ -1,2225 +0,0 @@
-// Copyright 2009 The Go Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style
-// license that can be found in the LICENSE file.
-
-/*
- * Go language grammar.
- *
- * The Go semicolon rules are:
- *
- *  1. all statements and declarations are terminated by semicolons.
- *  2. semicolons can be omitted before a closing ) or }.
- *  3. semicolons are inserted by the lexer before a newline
- *      following a specific list of tokens.
- *
- * Rules #1 and #2 are accomplished by writing the lists as
- * semicolon-separated lists with an optional trailing semicolon.
- * Rule #3 is implemented in yylex.
- */
-
-%{
-#include <u.h>
-#include <stdio.h>     /* if we don't, bison will, and go.h re-#defines getc */
-#include <libc.h>
-#include "go.h"
-
-static void fixlbrace(int);
-%}
-%union {
-       Node*           node;
-       NodeList*               list;
-       Type*           type;
-       Sym*            sym;
-       struct  Val     val;
-       int             i;
-}
-
-// |sed 's/.*  //' |9 fmt -l1 |sort |9 fmt -l50 | sed 's/^/%xxx                /'
-
-%token <val>   LLITERAL
-%token <i>     LASOP LCOLAS
-%token <sym>   LBREAK LCASE LCHAN LCONST LCONTINUE LDDD
-%token <sym>   LDEFAULT LDEFER LELSE LFALL LFOR LFUNC LGO LGOTO
-%token <sym>   LIF LIMPORT LINTERFACE LMAP LNAME
-%token <sym>   LPACKAGE LRANGE LRETURN LSELECT LSTRUCT LSWITCH
-%token <sym>   LTYPE LVAR
-
-%token         LANDAND LANDNOT LBODY LCOMM LDEC LEQ LGE LGT
-%token         LIGNORE LINC LLE LLSH LLT LNE LOROR LRSH
-
-%type  <i>     lbrace import_here
-%type  <sym>   sym packname
-%type  <val>   oliteral
-
-%type  <node>  stmt ntype
-%type  <node>  arg_type
-%type  <node>  case caseblock
-%type  <node>  compound_stmt dotname embed expr complitexpr bare_complitexpr
-%type  <node>  expr_or_type
-%type  <node>  fndcl hidden_fndcl fnliteral
-%type  <node>  for_body for_header for_stmt if_header if_stmt non_dcl_stmt
-%type  <node>  interfacedcl keyval labelname name
-%type  <node>  name_or_type non_expr_type
-%type  <node>  new_name dcl_name oexpr typedclname
-%type  <node>  onew_name
-%type  <node>  osimple_stmt pexpr pexpr_no_paren
-%type  <node>  pseudocall range_stmt select_stmt
-%type  <node>  simple_stmt
-%type  <node>  switch_stmt uexpr
-%type  <node>  xfndcl typedcl start_complit
-
-%type  <list>  xdcl fnbody fnres loop_body dcl_name_list
-%type  <list>  new_name_list expr_list keyval_list braced_keyval_list expr_or_type_list xdcl_list
-%type  <list>  oexpr_list caseblock_list elseif elseif_list else stmt_list oarg_type_list_ocomma arg_type_list
-%type  <list>  interfacedcl_list vardcl vardcl_list structdcl structdcl_list
-%type  <list>  common_dcl constdcl constdcl1 constdcl_list typedcl_list
-
-%type  <node>  convtype comptype dotdotdot
-%type  <node>  indcl interfacetype structtype ptrtype
-%type  <node>  recvchantype non_recvchantype othertype fnret_type fntype
-
-%type  <sym>   hidden_importsym hidden_pkg_importsym
-
-%type  <node>  hidden_constant hidden_literal hidden_funarg
-%type  <node>  hidden_interfacedcl hidden_structdcl
-
-%type  <list>  hidden_funres
-%type  <list>  ohidden_funres
-%type  <list>  hidden_funarg_list ohidden_funarg_list
-%type  <list>  hidden_interfacedcl_list ohidden_interfacedcl_list
-%type  <list>  hidden_structdcl_list ohidden_structdcl_list
-
-%type  <type>  hidden_type hidden_type_misc hidden_pkgtype
-%type  <type>  hidden_type_func
-%type  <type>  hidden_type_recv_chan hidden_type_non_recv_chan
-
-%left          LCOMM   /* outside the usual hierarchy; here for good error messages */
-
-%left          LOROR
-%left          LANDAND
-%left          LEQ LNE LLE LGE LLT LGT
-%left          '+' '-' '|' '^'
-%left          '*' '/' '%' '&' LLSH LRSH LANDNOT
-
-/*
- * manual override of shift/reduce conflicts.
- * the general form is that we assign a precedence
- * to the token being shifted and then introduce
- * NotToken with lower precedence or PreferToToken with higher
- * and annotate the reducing rule accordingly.
- */
-%left          NotPackage
-%left          LPACKAGE
-
-%left          NotParen
-%left          '('
-
-%left          ')'
-%left          PreferToRightParen
-
-%error-verbose
-
-%%
-file:
-       loadsys
-       package
-       imports
-       xdcl_list
-       {
-               xtop = concat(xtop, $4);
-       }
-
-package:
-       %prec NotPackage
-       {
-               prevlineno = lineno;
-               yyerror("package statement must be first");
-               errorexit();
-       }
-|      LPACKAGE sym ';'
-       {
-               mkpackage($2->name);
-       }
-
-/*
- * this loads the definitions for the low-level runtime functions,
- * so that the compiler can generate calls to them,
- * but does not make the name "runtime" visible as a package.
- */
-loadsys:
-       {
-               importpkg = runtimepkg;
-
-               if(debug['A'])
-                       cannedimports("runtime.builtin", "package runtime\n\n$$\n\n");
-               else
-                       cannedimports("runtime.builtin", runtimeimport);
-               curio.importsafe = 1;
-       }
-       import_package
-       import_there
-       {
-               importpkg = nil;
-       }
-
-imports:
-|      imports import ';'
-
-import:
-       LIMPORT import_stmt
-|      LIMPORT '(' import_stmt_list osemi ')'
-|      LIMPORT '(' ')'
-
-import_stmt:
-       import_here import_package import_there
-       {
-               Pkg *ipkg;
-               Sym *my;
-               Node *pack;
-               
-               ipkg = importpkg;
-               my = importmyname;
-               importpkg = nil;
-               importmyname = S;
-
-               if(my == nil)
-                       my = lookup(ipkg->name);
-
-               pack = nod(OPACK, N, N);
-               pack->sym = my;
-               pack->pkg = ipkg;
-               pack->lineno = $1;
-
-               if(my->name[0] == '.') {
-                       importdot(ipkg, pack);
-                       break;
-               }
-               if(strcmp(my->name, "init") == 0) {
-                       yyerror("cannot import package as init - init must be a func");
-                       break;
-               }
-               if(my->name[0] == '_' && my->name[1] == '\0')
-                       break;
-               if(my->def) {
-                       lineno = $1;
-                       redeclare(my, "as imported package name");
-               }
-               my->def = pack;
-               my->lastlineno = $1;
-               my->block = 1;  // at top level
-       }
-|      import_here import_there
-       {
-               // When an invalid import path is passed to importfile,
-               // it calls yyerror and then sets up a fake import with
-               // no package statement. This allows us to test more
-               // than one invalid import statement in a single file.
-               if(nerrors == 0)
-                       fatal("phase error in import");
-       }
-
-import_stmt_list:
-       import_stmt
-|      import_stmt_list ';' import_stmt
-
-import_here:
-       LLITERAL
-       {
-               // import with original name
-               $$ = parserline();
-               importmyname = S;
-               importfile(&$1, $$);
-       }
-|      sym LLITERAL
-       {
-               // import with given name
-               $$ = parserline();
-               importmyname = $1;
-               importfile(&$2, $$);
-       }
-|      '.' LLITERAL
-       {
-               // import into my name space
-               $$ = parserline();
-               importmyname = lookup(".");
-               importfile(&$2, $$);
-       }
-
-import_package:
-       LPACKAGE LNAME import_safety ';'
-       {
-               if(importpkg->name == nil) {
-                       importpkg->name = $2->name;
-                       pkglookup($2->name, nil)->npkg++;
-               } else if(strcmp(importpkg->name, $2->name) != 0)
-                       yyerror("conflicting names %s and %s for package \"%Z\"", importpkg->name, $2->name, importpkg->path);
-               importpkg->direct = 1;
-               importpkg->safe = curio.importsafe;
-
-               if(safemode && !curio.importsafe)
-                       yyerror("cannot import unsafe package \"%Z\"", importpkg->path);
-       }
-
-import_safety:
-|      LNAME
-       {
-               if(strcmp($1->name, "safe") == 0)
-                       curio.importsafe = 1;
-       }
-
-import_there:
-       {
-               defercheckwidth();
-       }
-       hidden_import_list '$' '$'
-       {
-               resumecheckwidth();
-               unimportfile();
-       }
-
-/*
- * declarations
- */
-xdcl:
-       {
-               yyerror("empty top-level declaration");
-               $$ = nil;
-       }
-|      common_dcl
-|      xfndcl
-       {
-               $$ = list1($1);
-       }
-|      non_dcl_stmt
-       {
-               yyerror("non-declaration statement outside function body");
-               $$ = nil;
-       }
-|      error
-       {
-               $$ = nil;
-       }
-
-common_dcl:
-       LVAR vardcl
-       {
-               $$ = $2;
-       }
-|      LVAR '(' vardcl_list osemi ')'
-       {
-               $$ = $3;
-       }
-|      LVAR '(' ')'
-       {
-               $$ = nil;
-       }
-|      lconst constdcl
-       {
-               $$ = $2;
-               iota = -100000;
-               lastconst = nil;
-       }
-|      lconst '(' constdcl osemi ')'
-       {
-               $$ = $3;
-               iota = -100000;
-               lastconst = nil;
-       }
-|      lconst '(' constdcl ';' constdcl_list osemi ')'
-       {
-               $$ = concat($3, $5);
-               iota = -100000;
-               lastconst = nil;
-       }
-|      lconst '(' ')'
-       {
-               $$ = nil;
-               iota = -100000;
-       }
-|      LTYPE typedcl
-       {
-               $$ = list1($2);
-       }
-|      LTYPE '(' typedcl_list osemi ')'
-       {
-               $$ = $3;
-       }
-|      LTYPE '(' ')'
-       {
-               $$ = nil;
-       }
-
-lconst:
-       LCONST
-       {
-               iota = 0;
-       }
-
-vardcl:
-       dcl_name_list ntype
-       {
-               $$ = variter($1, $2, nil);
-       }
-|      dcl_name_list ntype '=' expr_list
-       {
-               $$ = variter($1, $2, $4);
-       }
-|      dcl_name_list '=' expr_list
-       {
-               $$ = variter($1, nil, $3);
-       }
-
-constdcl:
-       dcl_name_list ntype '=' expr_list
-       {
-               $$ = constiter($1, $2, $4);
-       }
-|      dcl_name_list '=' expr_list
-       {
-               $$ = constiter($1, N, $3);
-       }
-
-constdcl1:
-       constdcl
-|      dcl_name_list ntype
-       {
-               $$ = constiter($1, $2, nil);
-       }
-|      dcl_name_list
-       {
-               $$ = constiter($1, N, nil);
-       }
-
-typedclname:
-       sym
-       {
-               // different from dclname because the name
-               // becomes visible right here, not at the end
-               // of the declaration.
-               $$ = typedcl0($1);
-       }
-
-typedcl:
-       typedclname ntype
-       {
-               $$ = typedcl1($1, $2, 1);
-       }
-
-simple_stmt:
-       expr
-       {
-               $$ = $1;
-
-               // These nodes do not carry line numbers.
-               // Since a bare name used as an expression is an error,
-               // introduce a wrapper node to give the correct line.
-               switch($$->op) {
-               case ONAME:
-               case ONONAME:
-               case OTYPE:
-               case OPACK:
-               case OLITERAL:
-                       $$ = nod(OPAREN, $$, N);
-                       $$->implicit = 1;
-                       break;
-               }
-       }
-|      expr LASOP expr
-       {
-               $$ = nod(OASOP, $1, $3);
-               $$->etype = $2;                 // rathole to pass opcode
-       }
-|      expr_list '=' expr_list
-       {
-               if($1->next == nil && $3->next == nil) {
-                       // simple
-                       $$ = nod(OAS, $1->n, $3->n);
-                       break;
-               }
-               // multiple
-               $$ = nod(OAS2, N, N);
-               $$->list = $1;
-               $$->rlist = $3;
-       }
-|      expr_list LCOLAS expr_list
-       {
-               if($3->n->op == OTYPESW) {
-                       $$ = nod(OTYPESW, N, $3->n->right);
-                       if($3->next != nil)
-                               yyerror("expr.(type) must be alone in list");
-                       if($1->next != nil)
-                               yyerror("argument count mismatch: %d = %d", count($1), 1);
-                       else if(($1->n->op != ONAME && $1->n->op != OTYPE && $1->n->op != ONONAME) || isblank($1->n))
-                               yyerror("invalid variable name %N in type switch", $1->n);
-                       else
-                               $$->left = dclname($1->n->sym);  // it's a colas, so must not re-use an oldname.
-                       break;
-               }
-               $$ = colas($1, $3, $2);
-       }
-|      expr LINC
-       {
-               $$ = nod(OASOP, $1, nodintconst(1));
-               $$->implicit = 1;
-               $$->etype = OADD;
-       }
-|      expr LDEC
-       {
-               $$ = nod(OASOP, $1, nodintconst(1));
-               $$->implicit = 1;
-               $$->etype = OSUB;
-       }
-
-case:
-       LCASE expr_or_type_list ':'
-       {
-               Node *n, *nn;
-
-               // will be converted to OCASE
-               // right will point to next case
-               // done in casebody()
-               markdcl();
-               $$ = nod(OXCASE, N, N);
-               $$->list = $2;
-               if(typesw != N && typesw->right != N && (n=typesw->right->left) != N) {
-                       // type switch - declare variable
-                       nn = newname(n->sym);
-                       declare(nn, dclcontext);
-                       $$->nname = nn;
-
-                       // keep track of the instances for reporting unused
-                       nn->defn = typesw->right;
-               }
-       }
-|      LCASE expr_or_type_list '=' expr ':'
-       {
-               Node *n;
-
-               // will be converted to OCASE
-               // right will point to next case
-               // done in casebody()
-               markdcl();
-               $$ = nod(OXCASE, N, N);
-               if($2->next == nil)
-                       n = nod(OAS, $2->n, $4);
-               else {
-                       n = nod(OAS2, N, N);
-                       n->list = $2;
-                       n->rlist = list1($4);
-               }
-               $$->list = list1(n);
-       }
-|      LCASE expr_or_type_list LCOLAS expr ':'
-       {
-               // will be converted to OCASE
-               // right will point to next case
-               // done in casebody()
-               markdcl();
-               $$ = nod(OXCASE, N, N);
-               $$->list = list1(colas($2, list1($4), $3));
-       }
-|      LDEFAULT ':'
-       {
-               Node *n, *nn;
-
-               markdcl();
-               $$ = nod(OXCASE, N, N);
-               if(typesw != N && typesw->right != N && (n=typesw->right->left) != N) {
-                       // type switch - declare variable
-                       nn = newname(n->sym);
-                       declare(nn, dclcontext);
-                       $$->nname = nn;
-
-                       // keep track of the instances for reporting unused
-                       nn->defn = typesw->right;
-               }
-       }
-
-compound_stmt:
-       '{'
-       {
-               markdcl();
-       }
-       stmt_list '}'
-       {
-               if($3 == nil)
-                       $$ = nod(OEMPTY, N, N);
-               else
-                       $$ = liststmt($3);
-               popdcl();
-       }
-
-caseblock:
-       case
-       {
-               // If the last token read by the lexer was consumed
-               // as part of the case, clear it (parser has cleared yychar).
-               // If the last token read by the lexer was the lookahead
-               // leave it alone (parser has it cached in yychar).
-               // This is so that the stmt_list action doesn't look at
-               // the case tokens if the stmt_list is empty.
-               yylast = yychar;
-               $1->xoffset = block;
-       }
-       stmt_list
-       {
-               int last;
-
-               // This is the only place in the language where a statement
-               // list is not allowed to drop the final semicolon, because
-               // it's the only place where a statement list is not followed 
-               // by a closing brace.  Handle the error for pedantry.
-
-               // Find the final token of the statement list.
-               // yylast is lookahead; yyprev is last of stmt_list
-               last = yyprev;
-
-               if(last > 0 && last != ';' && yychar != '}')
-                       yyerror("missing statement after label");
-               $$ = $1;
-               $$->nbody = $3;
-               popdcl();
-       }
-
-caseblock_list:
-       {
-               $$ = nil;
-       }
-|      caseblock_list caseblock
-       {
-               $$ = list($1, $2);
-       }
-
-loop_body:
-       LBODY
-       {
-               markdcl();
-       }
-       stmt_list '}'
-       {
-               $$ = $3;
-               popdcl();
-       }
-
-range_stmt:
-       expr_list '=' LRANGE expr
-       {
-               $$ = nod(ORANGE, N, $4);
-               $$->list = $1;
-               $$->etype = 0;  // := flag
-       }
-|      expr_list LCOLAS LRANGE expr
-       {
-               $$ = nod(ORANGE, N, $4);
-               $$->list = $1;
-               $$->colas = 1;
-               colasdefn($1, $$);
-       }
-|      LRANGE expr
-       {
-               $$ = nod(ORANGE, N, $2);
-               $$->etype = 0; // := flag
-       }
-
-for_header:
-       osimple_stmt ';' osimple_stmt ';' osimple_stmt
-       {
-               // init ; test ; incr
-               if($5 != N && $5->colas != 0)
-                       yyerror("cannot declare in the for-increment");
-               $$ = nod(OFOR, N, N);
-               if($1 != N)
-                       $$->ninit = list1($1);
-               $$->ntest = $3;
-               $$->nincr = $5;
-       }
-|      osimple_stmt
-       {
-               // normal test
-               $$ = nod(OFOR, N, N);
-               $$->ntest = $1;
-       }
-|      range_stmt
-
-for_body:
-       for_header loop_body
-       {
-               $$ = $1;
-               $$->nbody = concat($$->nbody, $2);
-       }
-
-for_stmt:
-       LFOR
-       {
-               markdcl();
-       }
-       for_body
-       {
-               $$ = $3;
-               popdcl();
-       }
-
-if_header:
-       osimple_stmt
-       {
-               // test
-               $$ = nod(OIF, N, N);
-               $$->ntest = $1;
-       }
-|      osimple_stmt ';' osimple_stmt
-       {
-               // init ; test
-               $$ = nod(OIF, N, N);
-               if($1 != N)
-                       $$->ninit = list1($1);
-               $$->ntest = $3;
-       }
-
-/* IF cond body (ELSE IF cond body)* (ELSE block)? */
-if_stmt:
-       LIF
-       {
-               markdcl();
-       }
-       if_header
-       {
-               if($3->ntest == N)
-                       yyerror("missing condition in if statement");
-       }
-       loop_body
-       {
-               $3->nbody = $5;
-       }
-       elseif_list else
-       {
-               Node *n;
-               NodeList *nn;
-
-               $$ = $3;
-               n = $3;
-               popdcl();
-               for(nn = concat($7, $8); nn; nn = nn->next) {
-                       if(nn->n->op == OIF)
-                               popdcl();
-                       n->nelse = list1(nn->n);
-                       n = nn->n;
-               }
-       }
-
-elseif:
-       LELSE LIF 
-       {
-               markdcl();
-       }
-       if_header loop_body
-       {
-               if($4->ntest == N)
-                       yyerror("missing condition in if statement");
-               $4->nbody = $5;
-               $$ = list1($4);
-       }
-
-elseif_list:
-       {
-               $$ = nil;
-       }
-|      elseif_list elseif
-       {
-               $$ = concat($1, $2);
-       }
-
-else:
-       {
-               $$ = nil;
-       }
-|      LELSE compound_stmt
-       {
-               NodeList *node;
-               
-               node = mal(sizeof *node);
-               node->n = $2;
-               node->end = node;
-               $$ = node;
-       }
-
-switch_stmt:
-       LSWITCH
-       {
-               markdcl();
-       }
-       if_header
-       {
-               Node *n;
-               n = $3->ntest;
-               if(n != N && n->op != OTYPESW)
-                       n = N;
-               typesw = nod(OXXX, typesw, n);
-       }
-       LBODY caseblock_list '}'
-       {
-               $$ = $3;
-               $$->op = OSWITCH;
-               $$->list = $6;
-               typesw = typesw->left;
-               popdcl();
-       }
-
-select_stmt:
-       LSELECT
-       {
-               typesw = nod(OXXX, typesw, N);
-       }
-       LBODY caseblock_list '}'
-       {
-               $$ = nod(OSELECT, N, N);
-               $$->lineno = typesw->lineno;
-               $$->list = $4;
-               typesw = typesw->left;
-       }
-
-/*
- * expressions
- */
-expr:
-       uexpr
-|      expr LOROR expr
-       {
-               $$ = nod(OOROR, $1, $3);
-       }
-|      expr LANDAND expr
-       {
-               $$ = nod(OANDAND, $1, $3);
-       }
-|      expr LEQ expr
-       {
-               $$ = nod(OEQ, $1, $3);
-       }
-|      expr LNE expr
-       {
-               $$ = nod(ONE, $1, $3);
-       }
-|      expr LLT expr
-       {
-               $$ = nod(OLT, $1, $3);
-       }
-|      expr LLE expr
-       {
-               $$ = nod(OLE, $1, $3);
-       }
-|      expr LGE expr
-       {
-               $$ = nod(OGE, $1, $3);
-       }
-|      expr LGT expr
-       {
-               $$ = nod(OGT, $1, $3);
-       }
-|      expr '+' expr
-       {
-               $$ = nod(OADD, $1, $3);
-       }
-|      expr '-' expr
-       {
-               $$ = nod(OSUB, $1, $3);
-       }
-|      expr '|' expr
-       {
-               $$ = nod(OOR, $1, $3);
-       }
-|      expr '^' expr
-       {
-               $$ = nod(OXOR, $1, $3);
-       }
-|      expr '*' expr
-       {
-               $$ = nod(OMUL, $1, $3);
-       }
-|      expr '/' expr
-       {
-               $$ = nod(ODIV, $1, $3);
-       }
-|      expr '%' expr
-       {
-               $$ = nod(OMOD, $1, $3);
-       }
-|      expr '&' expr
-       {
-               $$ = nod(OAND, $1, $3);
-       }
-|      expr LANDNOT expr
-       {
-               $$ = nod(OANDNOT, $1, $3);
-       }
-|      expr LLSH expr
-       {
-               $$ = nod(OLSH, $1, $3);
-       }
-|      expr LRSH expr
-       {
-               $$ = nod(ORSH, $1, $3);
-       }
-       /* not an expression anymore, but left in so we can give a good error */
-|      expr LCOMM expr
-       {
-               $$ = nod(OSEND, $1, $3);
-       }
-
-uexpr:
-       pexpr
-|      '*' uexpr
-       {
-               $$ = nod(OIND, $2, N);
-       }
-|      '&' uexpr
-       {
-               if($2->op == OCOMPLIT) {
-                       // Special case for &T{...}: turn into (*T){...}.
-                       $$ = $2;
-                       $$->right = nod(OIND, $$->right, N);
-                       $$->right->implicit = 1;
-               } else {
-                       $$ = nod(OADDR, $2, N);
-               }
-       }
-|      '+' uexpr
-       {
-               $$ = nod(OPLUS, $2, N);
-       }
-|      '-' uexpr
-       {
-               $$ = nod(OMINUS, $2, N);
-       }
-|      '!' uexpr
-       {
-               $$ = nod(ONOT, $2, N);
-       }
-|      '~' uexpr
-       {
-               yyerror("the bitwise complement operator is ^");
-               $$ = nod(OCOM, $2, N);
-       }
-|      '^' uexpr
-       {
-               $$ = nod(OCOM, $2, N);
-       }
-|      LCOMM uexpr
-       {
-               $$ = nod(ORECV, $2, N);
-       }
-
-/*
- * call-like statements that
- * can be preceded by 'defer' and 'go'
- */
-pseudocall:
-       pexpr '(' ')'
-       {
-               $$ = nod(OCALL, $1, N);
-       }
-|      pexpr '(' expr_or_type_list ocomma ')'
-       {
-               $$ = nod(OCALL, $1, N);
-               $$->list = $3;
-       }
-|      pexpr '(' expr_or_type_list LDDD ocomma ')'
-       {
-               $$ = nod(OCALL, $1, N);
-               $$->list = $3;
-               $$->isddd = 1;
-       }
-
-pexpr_no_paren:
-       LLITERAL
-       {
-               $$ = nodlit($1);
-       }
-|      name
-|      pexpr '.' sym
-       {
-               if($1->op == OPACK) {
-                       Sym *s;
-                       s = restrictlookup($3->name, $1->pkg);
-                       $1->used = 1;
-                       $$ = oldname(s);
-                       break;
-               }
-               $$ = nod(OXDOT, $1, newname($3));
-       }
-|      pexpr '.' '(' expr_or_type ')'
-       {
-               $$ = nod(ODOTTYPE, $1, $4);
-       }
-|      pexpr '.' '(' LTYPE ')'
-       {
-               $$ = nod(OTYPESW, N, $1);
-       }
-|      pexpr '[' expr ']'
-       {
-               $$ = nod(OINDEX, $1, $3);
-       }
-|      pexpr '[' oexpr ':' oexpr ']'
-       {
-               $$ = nod(OSLICE, $1, nod(OKEY, $3, $5));
-       }
-|      pexpr '[' oexpr ':' oexpr ':' oexpr ']'
-       {
-               if($5 == N)
-                       yyerror("middle index required in 3-index slice");
-               if($7 == N)
-                       yyerror("final index required in 3-index slice");
-               $$ = nod(OSLICE3, $1, nod(OKEY, $3, nod(OKEY, $5, $7)));
-       }
-|      pseudocall
-|      convtype '(' expr ocomma ')'
-       {
-               // conversion
-               $$ = nod(OCALL, $1, N);
-               $$->list = list1($3);
-       }
-|      comptype lbrace start_complit braced_keyval_list '}'
-       {
-               $$ = $3;
-               $$->right = $1;
-               $$->list = $4;
-               fixlbrace($2);
-       }
-|      pexpr_no_paren '{' start_complit braced_keyval_list '}'
-       {
-               $$ = $3;
-               $$->right = $1;
-               $$->list = $4;
-       }
-|      '(' expr_or_type ')' '{' start_complit braced_keyval_list '}'
-       {
-               yyerror("cannot parenthesize type in composite literal");
-               $$ = $5;
-               $$->right = $2;
-               $$->list = $6;
-       }
-|      fnliteral
-
-start_complit:
-       {
-               // composite expression.
-               // make node early so we get the right line number.
-               $$ = nod(OCOMPLIT, N, N);
-       }
-
-keyval:
-       expr ':' complitexpr
-       {
-               $$ = nod(OKEY, $1, $3);
-       }
-
-bare_complitexpr:
-       expr
-       {
-               // These nodes do not carry line numbers.
-               // Since a composite literal commonly spans several lines,
-               // the line number on errors may be misleading.
-               // Introduce a wrapper node to give the correct line.
-               $$ = $1;
-               switch($$->op) {
-               case ONAME:
-               case ONONAME:
-               case OTYPE:
-               case OPACK:
-               case OLITERAL:
-                       $$ = nod(OPAREN, $$, N);
-                       $$->implicit = 1;
-               }
-       }
-|      '{' start_complit braced_keyval_list '}'
-       {
-               $$ = $2;
-               $$->list = $3;
-       }
-
-complitexpr:
-       expr
-|      '{' start_complit braced_keyval_list '}'
-       {
-               $$ = $2;
-               $$->list = $3;
-       }
-
-pexpr:
-       pexpr_no_paren
-|      '(' expr_or_type ')'
-       {
-               $$ = $2;
-               
-               // Need to know on lhs of := whether there are ( ).
-               // Don't bother with the OPAREN in other cases:
-               // it's just a waste of memory and time.
-               switch($$->op) {
-               case ONAME:
-               case ONONAME:
-               case OPACK:
-               case OTYPE:
-               case OLITERAL:
-               case OTYPESW:
-                       $$ = nod(OPAREN, $$, N);
-               }
-       }
-
-expr_or_type:
-       expr
-|      non_expr_type   %prec PreferToRightParen
-
-name_or_type:
-       ntype
-
-lbrace:
-       LBODY
-       {
-               $$ = LBODY;
-       }
-|      '{'
-       {
-               $$ = '{';
-       }
-
-/*
- * names and types
- *     newname is used before declared
- *     oldname is used after declared
- */
-new_name:
-       sym
-       {
-               if($1 == S)
-                       $$ = N;
-               else
-                       $$ = newname($1);
-       }
-
-dcl_name:
-       sym
-       {
-               $$ = dclname($1);
-       }
-
-onew_name:
-       {
-               $$ = N;
-       }
-|      new_name
-
-sym:
-       LNAME
-       {
-               $$ = $1;
-               // during imports, unqualified non-exported identifiers are from builtinpkg
-               if(importpkg != nil && !exportname($1->name))
-                       $$ = pkglookup($1->name, builtinpkg);
-       }
-|      hidden_importsym
-|      '?'
-       {
-               $$ = S;
-       }
-
-hidden_importsym:
-       '@' LLITERAL '.' LNAME
-       {
-               Pkg *p;
-
-               if($2.u.sval->len == 0)
-                       p = importpkg;
-               else {
-                       if(isbadimport($2.u.sval))
-                               errorexit();
-                       p = mkpkg($2.u.sval);
-               }
-               $$ = pkglookup($4->name, p);
-       }
-|      '@' LLITERAL '.' '?'
-       {
-               Pkg *p;
-
-               if($2.u.sval->len == 0)
-                       p = importpkg;
-               else {
-                       if(isbadimport($2.u.sval))
-                               errorexit();
-                       p = mkpkg($2.u.sval);
-               }
-               $$ = pkglookup("?", p);
-       }
-
-name:
-       sym     %prec NotParen
-       {
-               $$ = oldname($1);
-               if($$->pack != N)
-                       $$->pack->used = 1;
-       }
-
-labelname:
-       new_name
-
-/*
- * to avoid parsing conflicts, type is split into
- *     channel types
- *     function types
- *     parenthesized types
- *     any other type
- * the type system makes additional restrictions,
- * but those are not implemented in the grammar.
- */
-dotdotdot:
-       LDDD
-       {
-               yyerror("final argument in variadic function missing type");
-               $$ = nod(ODDD, typenod(typ(TINTER)), N);
-       }
-|      LDDD ntype
-       {
-               $$ = nod(ODDD, $2, N);
-       }
-
-ntype:
-       recvchantype
-|      fntype
-|      othertype
-|      ptrtype
-|      dotname
-|      '(' ntype ')'
-       {
-               $$ = $2;
-       }
-
-non_expr_type:
-       recvchantype
-|      fntype
-|      othertype
-|      '*' non_expr_type
-       {
-               $$ = nod(OIND, $2, N);
-       }
-
-non_recvchantype:
-       fntype
-|      othertype
-|      ptrtype
-|      dotname
-|      '(' ntype ')'
-       {
-               $$ = $2;
-       }
-
-convtype:
-       fntype
-|      othertype
-
-comptype:
-       othertype
-
-fnret_type:
-       recvchantype
-|      fntype
-|      othertype
-|      ptrtype
-|      dotname
-
-dotname:
-       name
-|      name '.' sym
-       {
-               if($1->op == OPACK) {
-                       Sym *s;
-                       s = restrictlookup($3->name, $1->pkg);
-                       $1->used = 1;
-                       $$ = oldname(s);
-                       break;
-               }
-               $$ = nod(OXDOT, $1, newname($3));
-       }
-
-othertype:
-       '[' oexpr ']' ntype
-       {
-               $$ = nod(OTARRAY, $2, $4);
-       }
-|      '[' LDDD ']' ntype
-       {
-               // array literal of nelem
-               $$ = nod(OTARRAY, nod(ODDD, N, N), $4);
-       }
-|      LCHAN non_recvchantype
-       {
-               $$ = nod(OTCHAN, $2, N);
-               $$->etype = Cboth;
-       }
-|      LCHAN LCOMM ntype
-       {
-               $$ = nod(OTCHAN, $3, N);
-               $$->etype = Csend;
-       }
-|      LMAP '[' ntype ']' ntype
-       {
-               $$ = nod(OTMAP, $3, $5);
-       }
-|      structtype
-|      interfacetype
-
-ptrtype:
-       '*' ntype
-       {
-               $$ = nod(OIND, $2, N);
-       }
-
-recvchantype:
-       LCOMM LCHAN ntype
-       {
-               $$ = nod(OTCHAN, $3, N);
-               $$->etype = Crecv;
-       }
-
-structtype:
-       LSTRUCT lbrace structdcl_list osemi '}'
-       {
-               $$ = nod(OTSTRUCT, N, N);
-               $$->list = $3;
-               fixlbrace($2);
-       }
-|      LSTRUCT lbrace '}'
-       {
-               $$ = nod(OTSTRUCT, N, N);
-               fixlbrace($2);
-       }
-
-interfacetype:
-       LINTERFACE lbrace interfacedcl_list osemi '}'
-       {
-               $$ = nod(OTINTER, N, N);
-               $$->list = $3;
-               fixlbrace($2);
-       }
-|      LINTERFACE lbrace '}'
-       {
-               $$ = nod(OTINTER, N, N);
-               fixlbrace($2);
-       }
-
-/*
- * function stuff
- * all in one place to show how crappy it all is
- */
-xfndcl:
-       LFUNC fndcl fnbody
-       {
-               $$ = $2;
-               if($$ == N)
-                       break;
-               if(noescape && $3 != nil)
-                       yyerror("can only use //go:noescape with external func implementations");
-               $$->nbody = $3;
-               $$->endlineno = lineno;
-               $$->noescape = noescape;
-               $$->nosplit = nosplit;
-               $$->nowritebarrier = nowritebarrier;
-               funcbody($$);
-       }
-
-fndcl:
-       sym '(' oarg_type_list_ocomma ')' fnres
-       {
-               Node *t;
-
-               $$ = N;
-               $3 = checkarglist($3, 1);
-
-               if(strcmp($1->name, "init") == 0) {
-                       $1 = renameinit();
-                       if($3 != nil || $5 != nil)
-                               yyerror("func init must have no arguments and no return values");
-               }
-               if(strcmp(localpkg->name, "main") == 0 && strcmp($1->name, "main") == 0) {
-                       if($3 != nil || $5 != nil)
-                               yyerror("func main must have no arguments and no return values");
-               }
-
-               t = nod(OTFUNC, N, N);
-               t->list = $3;
-               t->rlist = $5;
-
-               $$ = nod(ODCLFUNC, N, N);
-               $$->nname = newname($1);
-               $$->nname->defn = $$;
-               $$->nname->ntype = t;           // TODO: check if nname already has an ntype
-               declare($$->nname, PFUNC);
-
-               funchdr($$);
-       }
-|      '(' oarg_type_list_ocomma ')' sym '(' oarg_type_list_ocomma ')' fnres
-       {
-               Node *rcvr, *t;
-
-               $$ = N;
-               $2 = checkarglist($2, 0);
-               $6 = checkarglist($6, 1);
-
-               if($2 == nil) {
-                       yyerror("method has no receiver");
-                       break;
-               }
-               if($2->next != nil) {
-                       yyerror("method has multiple receivers");
-                       break;
-               }
-               rcvr = $2->n;
-               if(rcvr->op != ODCLFIELD) {
-                       yyerror("bad receiver in method");
-                       break;
-               }
-
-               t = nod(OTFUNC, rcvr, N);
-               t->list = $6;
-               t->rlist = $8;
-
-               $$ = nod(ODCLFUNC, N, N);
-               $$->shortname = newname($4);
-               $$->nname = methodname1($$->shortname, rcvr->right);
-               $$->nname->defn = $$;
-               $$->nname->ntype = t;
-               $$->nname->nointerface = nointerface;
-               declare($$->nname, PFUNC);
-
-               funchdr($$);
-       }
-
-hidden_fndcl:
-       hidden_pkg_importsym '(' ohidden_funarg_list ')' ohidden_funres
-       {
-               Sym *s;
-               Type *t;
-
-               $$ = N;
-
-               s = $1;
-               t = functype(N, $3, $5);
-
-               importsym(s, ONAME);
-               if(s->def != N && s->def->op == ONAME) {
-                       if(eqtype(t, s->def->type)) {
-                               dclcontext = PDISCARD;  // since we skip funchdr below
-                               break;
-                       }
-                       yyerror("inconsistent definition for func %S during import\n\t%T\n\t%T", s, s->def->type, t);
-               }
-
-               $$ = newname(s);
-               $$->type = t;
-               declare($$, PFUNC);
-
-               funchdr($$);
-       }
-|      '(' hidden_funarg_list ')' sym '(' ohidden_funarg_list ')' ohidden_funres
-       {
-               $$ = methodname1(newname($4), $2->n->right); 
-               $$->type = functype($2->n, $6, $8);
-
-               checkwidth($$->type);
-               addmethod($4, $$->type, 0, nointerface);
-               nointerface = 0;
-               funchdr($$);
-               
-               // inl.c's inlnode in on a dotmeth node expects to find the inlineable body as
-               // (dotmeth's type)->nname->inl, and dotmeth's type has been pulled
-               // out by typecheck's lookdot as this $$->ttype.  So by providing
-               // this back link here we avoid special casing there.
-               $$->type->nname = $$;
-       }
-
-fntype:
-       LFUNC '(' oarg_type_list_ocomma ')' fnres
-       {
-               $3 = checkarglist($3, 1);
-               $$ = nod(OTFUNC, N, N);
-               $$->list = $3;
-               $$->rlist = $5;
-       }
-
-fnbody:
-       {
-               $$ = nil;
-       }
-|      '{' stmt_list '}'
-       {
-               $$ = $2;
-               if($$ == nil)
-                       $$ = list1(nod(OEMPTY, N, N));
-       }
-
-fnres:
-       %prec NotParen
-       {
-               $$ = nil;
-       }
-|      fnret_type
-       {
-               $$ = list1(nod(ODCLFIELD, N, $1));
-       }
-|      '(' oarg_type_list_ocomma ')'
-       {
-               $2 = checkarglist($2, 0);
-               $$ = $2;
-       }
-
-fnlitdcl:
-       fntype
-       {
-               closurehdr($1);
-       }
-
-fnliteral:
-       fnlitdcl lbrace stmt_list '}'
-       {
-               $$ = closurebody($3);
-               fixlbrace($2);
-       }
-|      fnlitdcl error
-       {
-               $$ = closurebody(nil);
-       }
-
-/*
- * lists of things
- * note that they are left recursive
- * to conserve yacc stack. they need to
- * be reversed to interpret correctly
- */
-xdcl_list:
-       {
-               $$ = nil;
-       }
-|      xdcl_list xdcl ';'
-       {
-               $$ = concat($1, $2);
-               if(nsyntaxerrors == 0)
-                       testdclstack();
-               nointerface = 0;
-               noescape = 0;
-               nosplit = 0;
-               nowritebarrier = 0;
-       }
-
-vardcl_list:
-       vardcl
-|      vardcl_list ';' vardcl
-       {
-               $$ = concat($1, $3);
-       }
-
-constdcl_list:
-       constdcl1
-|      constdcl_list ';' constdcl1
-       {
-               $$ = concat($1, $3);
-       }
-
-typedcl_list:
-       typedcl
-       {
-               $$ = list1($1);
-       }
-|      typedcl_list ';' typedcl
-       {
-               $$ = list($1, $3);
-       }
-
-structdcl_list:
-       structdcl
-|      structdcl_list ';' structdcl
-       {
-               $$ = concat($1, $3);
-       }
-
-interfacedcl_list:
-       interfacedcl
-       {
-               $$ = list1($1);
-       }
-|      interfacedcl_list ';' interfacedcl
-       {
-               $$ = list($1, $3);
-       }
-
-structdcl:
-       new_name_list ntype oliteral
-       {
-               NodeList *l;
-
-               Node *n;
-               l = $1;
-               if(l == nil) {
-                       // ? symbol, during import (list1(N) == nil)
-                       n = $2;
-                       if(n->op == OIND)
-                               n = n->left;
-                       n = embedded(n->sym, importpkg);
-                       n->right = $2;
-                       n->val = $3;
-                       $$ = list1(n);
-                       break;
-               }
-
-               for(l=$1; l; l=l->next) {
-                       l->n = nod(ODCLFIELD, l->n, $2);
-                       l->n->val = $3;
-               }
-       }
-|      embed oliteral
-       {
-               $1->val = $2;
-               $$ = list1($1);
-       }
-|      '(' embed ')' oliteral
-       {
-               $2->val = $4;
-               $$ = list1($2);
-               yyerror("cannot parenthesize embedded type");
-       }
-|      '*' embed oliteral
-       {
-               $2->right = nod(OIND, $2->right, N);
-               $2->val = $3;
-               $$ = list1($2);
-       }
-|      '(' '*' embed ')' oliteral
-       {
-               $3->right = nod(OIND, $3->right, N);
-               $3->val = $5;
-               $$ = list1($3);
-               yyerror("cannot parenthesize embedded type");
-       }
-|      '*' '(' embed ')' oliteral
-       {
-               $3->right = nod(OIND, $3->right, N);
-               $3->val = $5;
-               $$ = list1($3);
-               yyerror("cannot parenthesize embedded type");
-       }
-
-packname:
-       LNAME
-       {
-               Node *n;
-
-               $$ = $1;
-               n = oldname($1);
-               if(n->pack != N)
-                       n->pack->used = 1;
-       }
-|      LNAME '.' sym
-       {
-               Pkg *pkg;
-
-               if($1->def == N || $1->def->op != OPACK) {
-                       yyerror("%S is not a package", $1);
-                       pkg = localpkg;
-               } else {
-                       $1->def->used = 1;
-                       pkg = $1->def->pkg;
-               }
-               $$ = restrictlookup($3->name, pkg);
-       }
-
-embed:
-       packname
-       {
-               $$ = embedded($1, localpkg);
-       }
-
-interfacedcl:
-       new_name indcl
-       {
-               $$ = nod(ODCLFIELD, $1, $2);
-               ifacedcl($$);
-       }
-|      packname
-       {
-               $$ = nod(ODCLFIELD, N, oldname($1));
-       }
-|      '(' packname ')'
-       {
-               $$ = nod(ODCLFIELD, N, oldname($2));
-               yyerror("cannot parenthesize embedded type");
-       }
-
-indcl:
-       '(' oarg_type_list_ocomma ')' fnres
-       {
-               // without func keyword
-               $2 = checkarglist($2, 1);
-               $$ = nod(OTFUNC, fakethis(), N);
-               $$->list = $2;
-               $$->rlist = $4;
-       }
-
-/*
- * function arguments.
- */
-arg_type:
-       name_or_type
-|      sym name_or_type
-       {
-               $$ = nod(ONONAME, N, N);
-               $$->sym = $1;
-               $$ = nod(OKEY, $$, $2);
-       }
-|      sym dotdotdot
-       {
-               $$ = nod(ONONAME, N, N);
-               $$->sym = $1;
-               $$ = nod(OKEY, $$, $2);
-       }
-|      dotdotdot
-
-arg_type_list:
-       arg_type
-       {
-               $$ = list1($1);
-       }
-|      arg_type_list ',' arg_type
-       {
-               $$ = list($1, $3);
-       }
-
-oarg_type_list_ocomma:
-       {
-               $$ = nil;
-       }
-|      arg_type_list ocomma
-       {
-               $$ = $1;
-       }
-
-/*
- * statement
- */
-stmt:
-       {
-               $$ = N;
-       }
-|      compound_stmt
-|      common_dcl
-       {
-               $$ = liststmt($1);
-       }
-|      non_dcl_stmt
-|      error
-       {
-               $$ = N;
-       }
-
-non_dcl_stmt:
-       simple_stmt
-|      for_stmt
-|      switch_stmt
-|      select_stmt
-|      if_stmt
-|      labelname ':'
-       {
-               $1 = nod(OLABEL, $1, N);
-               $1->sym = dclstack;  // context, for goto restrictions
-       }
-       stmt
-       {
-               NodeList *l;
-
-               $1->defn = $4;
-               l = list1($1);
-               if($4)
-                       l = list(l, $4);
-               $$ = liststmt(l);
-       }
-|      LFALL
-       {
-               // will be converted to OFALL
-               $$ = nod(OXFALL, N, N);
-               $$->xoffset = block;
-       }
-|      LBREAK onew_name
-       {
-               $$ = nod(OBREAK, $2, N);
-       }
-|      LCONTINUE onew_name
-       {
-               $$ = nod(OCONTINUE, $2, N);
-       }
-|      LGO pseudocall
-       {
-               $$ = nod(OPROC, $2, N);
-       }
-|      LDEFER pseudocall
-       {
-               $$ = nod(ODEFER, $2, N);
-       }
-|      LGOTO new_name
-       {
-               $$ = nod(OGOTO, $2, N);
-               $$->sym = dclstack;  // context, for goto restrictions
-       }
-|      LRETURN oexpr_list
-       {
-               $$ = nod(ORETURN, N, N);
-               $$->list = $2;
-               if($$->list == nil && curfn != N) {
-                       NodeList *l;
-
-                       for(l=curfn->dcl; l; l=l->next) {
-                               if(l->n->class == PPARAM)
-                                       continue;
-                               if(l->n->class != PPARAMOUT)
-                                       break;
-                               if(l->n->sym->def != l->n)
-                                       yyerror("%s is shadowed during return", l->n->sym->name);
-                       }
-               }
-       }
-
-stmt_list:
-       stmt
-       {
-               $$ = nil;
-               if($1 != N)
-                       $$ = list1($1);
-       }
-|      stmt_list ';' stmt
-       {
-               $$ = $1;
-               if($3 != N)
-                       $$ = list($$, $3);
-       }
-
-new_name_list:
-       new_name
-       {
-               $$ = list1($1);
-       }
-|      new_name_list ',' new_name
-       {
-               $$ = list($1, $3);
-       }
-
-dcl_name_list:
-       dcl_name
-       {
-               $$ = list1($1);
-       }
-|      dcl_name_list ',' dcl_name
-       {
-               $$ = list($1, $3);
-       }
-
-expr_list:
-       expr
-       {
-               $$ = list1($1);
-       }
-|      expr_list ',' expr
-       {
-               $$ = list($1, $3);
-       }
-
-expr_or_type_list:
-       expr_or_type
-       {
-               $$ = list1($1);
-       }
-|      expr_or_type_list ',' expr_or_type
-       {
-               $$ = list($1, $3);
-       }
-
-/*
- * list of combo of keyval and val
- */
-keyval_list:
-       keyval
-       {
-               $$ = list1($1);
-       }
-|      bare_complitexpr
-       {
-               $$ = list1($1);
-       }
-|      keyval_list ',' keyval
-       {
-               $$ = list($1, $3);
-       }
-|      keyval_list ',' bare_complitexpr
-       {
-               $$ = list($1, $3);
-       }
-
-braced_keyval_list:
-       {
-               $$ = nil;
-       }
-|      keyval_list ocomma
-       {
-               $$ = $1;
-       }
-
-/*
- * optional things
- */
-osemi:
-|      ';'
-
-ocomma:
-|      ','
-
-oexpr:
-       {
-               $$ = N;
-       }
-|      expr
-
-oexpr_list:
-       {
-               $$ = nil;
-       }
-|      expr_list
-
-osimple_stmt:
-       {
-               $$ = N;
-       }
-|      simple_stmt
-
-ohidden_funarg_list:
-       {
-               $$ = nil;
-       }
-|      hidden_funarg_list
-
-ohidden_structdcl_list:
-       {
-               $$ = nil;
-       }
-|      hidden_structdcl_list
-
-ohidden_interfacedcl_list:
-       {
-               $$ = nil;
-       }
-|      hidden_interfacedcl_list
-
-oliteral:
-       {
-               $$.ctype = CTxxx;
-       }
-|      LLITERAL
-
-/*
- * import syntax from package header
- */
-hidden_import:
-       LIMPORT LNAME LLITERAL ';'
-       {
-               importimport($2, $3.u.sval);
-       }
-|      LVAR hidden_pkg_importsym hidden_type ';'
-       {
-               importvar($2, $3);
-       }
-|      LCONST hidden_pkg_importsym '=' hidden_constant ';'
-       {
-               importconst($2, types[TIDEAL], $4);
-       }
-|      LCONST hidden_pkg_importsym hidden_type '=' hidden_constant ';'
-       {
-               importconst($2, $3, $5);
-       }
-|      LTYPE hidden_pkgtype hidden_type ';'
-       {
-               importtype($2, $3);
-       }
-|      LFUNC hidden_fndcl fnbody ';'
-       {
-               if($2 == N) {
-                       dclcontext = PEXTERN;  // since we skip the funcbody below
-                       break;
-               }
-
-               $2->inl = $3;
-
-               funcbody($2);
-               importlist = list(importlist, $2);
-
-               if(debug['E']) {
-                       print("import [%Z] func %lN \n", importpkg->path, $2);
-                       if(debug['m'] > 2 && $2->inl)
-                               print("inl body:%+H\n", $2->inl);
-               }
-       }
-
-hidden_pkg_importsym:
-       hidden_importsym
-       {
-               $$ = $1;
-               structpkg = $$->pkg;
-       }
-
-hidden_pkgtype:
-       hidden_pkg_importsym
-       {
-               $$ = pkgtype($1);
-               importsym($1, OTYPE);
-       }
-
-/*
- *  importing types
- */
-
-hidden_type:
-       hidden_type_misc
-|      hidden_type_recv_chan
-|      hidden_type_func
-
-hidden_type_non_recv_chan:
-       hidden_type_misc
-|      hidden_type_func
-
-hidden_type_misc:
-       hidden_importsym
-       {
-               $$ = pkgtype($1);
-       }
-|      LNAME
-       {
-               // predefined name like uint8
-               $1 = pkglookup($1->name, builtinpkg);
-               if($1->def == N || $1->def->op != OTYPE) {
-                       yyerror("%s is not a type", $1->name);
-                       $$ = T;
-               } else
-                       $$ = $1->def->type;
-       }
-|      '[' ']' hidden_type
-       {
-               $$ = aindex(N, $3);
-       }
-|      '[' LLITERAL ']' hidden_type
-       {
-               $$ = aindex(nodlit($2), $4);
-       }
-|      LMAP '[' hidden_type ']' hidden_type
-       {
-               $$ = maptype($3, $5);
-       }
-|      LSTRUCT '{' ohidden_structdcl_list '}'
-       {
-               $$ = tostruct($3);
-       }
-|      LINTERFACE '{' ohidden_interfacedcl_list '}'
-       {
-               $$ = tointerface($3);
-       }
-|      '*' hidden_type
-       {
-               $$ = ptrto($2);
-       }
-|      LCHAN hidden_type_non_recv_chan
-       {
-               $$ = typ(TCHAN);
-               $$->type = $2;
-               $$->chan = Cboth;
-       }
-|      LCHAN '(' hidden_type_recv_chan ')'
-       {
-               $$ = typ(TCHAN);
-               $$->type = $3;
-               $$->chan = Cboth;
-       }
-|      LCHAN LCOMM hidden_type
-       {
-               $$ = typ(TCHAN);
-               $$->type = $3;
-               $$->chan = Csend;
-       }
-
-hidden_type_recv_chan:
-       LCOMM LCHAN hidden_type
-       {
-               $$ = typ(TCHAN);
-               $$->type = $3;
-               $$->chan = Crecv;
-       }
-
-hidden_type_func:
-       LFUNC '(' ohidden_funarg_list ')' ohidden_funres
-       {
-               $$ = functype(nil, $3, $5);
-       }
-
-hidden_funarg:
-       sym hidden_type oliteral
-       {
-               $$ = nod(ODCLFIELD, N, typenod($2));
-               if($1)
-                       $$->left = newname($1);
-               $$->val = $3;
-       }
-|      sym LDDD hidden_type oliteral
-       {
-               Type *t;
-       
-               t = typ(TARRAY);
-               t->bound = -1;
-               t->type = $3;
-
-               $$ = nod(ODCLFIELD, N, typenod(t));
-               if($1)
-                       $$->left = newname($1);
-               $$->isddd = 1;
-               $$->val = $4;
-       }
-
-hidden_structdcl:
-       sym hidden_type oliteral
-       {
-               Sym *s;
-               Pkg *p;
-
-               if($1 != S && strcmp($1->name, "?") != 0) {
-                       $$ = nod(ODCLFIELD, newname($1), typenod($2));
-                       $$->val = $3;
-               } else {
-                       s = $2->sym;
-                       if(s == S && isptr[$2->etype])
-                               s = $2->type->sym;
-                       p = importpkg;
-                       if($1 != S)
-                               p = $1->pkg;
-                       $$ = embedded(s, p);
-                       $$->right = typenod($2);
-                       $$->val = $3;
-               }
-       }
-
-hidden_interfacedcl:
-       sym '(' ohidden_funarg_list ')' ohidden_funres
-       {
-               $$ = nod(ODCLFIELD, newname($1), typenod(functype(fakethis(), $3, $5)));
-       }
-|      hidden_type
-       {
-               $$ = nod(ODCLFIELD, N, typenod($1));
-       }
-
-ohidden_funres:
-       {
-               $$ = nil;
-       }
-|      hidden_funres
-
-hidden_funres:
-       '(' ohidden_funarg_list ')'
-       {
-               $$ = $2;
-       }
-|      hidden_type
-       {
-               $$ = list1(nod(ODCLFIELD, N, typenod($1)));
-       }
-
-/*
- *  importing constants
- */
-
-hidden_literal:
-       LLITERAL
-       {
-               $$ = nodlit($1);
-       }
-|      '-' LLITERAL
-       {
-               $$ = nodlit($2);
-               switch($$->val.ctype){
-               case CTINT:
-               case CTRUNE:
-                       mpnegfix($$->val.u.xval);
-                       break;
-               case CTFLT:
-                       mpnegflt($$->val.u.fval);
-                       break;
-               case CTCPLX:
-                       mpnegflt(&$$->val.u.cval->real);
-                       mpnegflt(&$$->val.u.cval->imag);
-                       break;
-               default:
-                       yyerror("bad negated constant");
-               }
-       }
-|      sym
-       {
-               $$ = oldname(pkglookup($1->name, builtinpkg));
-               if($$->op != OLITERAL)
-                       yyerror("bad constant %S", $$->sym);
-       }
-
-hidden_constant:
-       hidden_literal
-|      '(' hidden_literal '+' hidden_literal ')'
-       {
-               if($2->val.ctype == CTRUNE && $4->val.ctype == CTINT) {
-                       $$ = $2;
-                       mpaddfixfix($2->val.u.xval, $4->val.u.xval, 0);
-                       break;
-               }
-               $4->val.u.cval->real = $4->val.u.cval->imag;
-               mpmovecflt(&$4->val.u.cval->imag, 0.0);
-               $$ = nodcplxlit($2->val, $4->val);
-       }
-
-hidden_import_list:
-|      hidden_import_list hidden_import
-
-hidden_funarg_list:
-       hidden_funarg
-       {
-               $$ = list1($1);
-       }
-|      hidden_funarg_list ',' hidden_funarg
-       {
-               $$ = list($1, $3);
-       }
-
-hidden_structdcl_list:
-       hidden_structdcl
-       {
-               $$ = list1($1);
-       }
-|      hidden_structdcl_list ';' hidden_structdcl
-       {
-               $$ = list($1, $3);
-       }
-
-hidden_interfacedcl_list:
-       hidden_interfacedcl
-       {
-               $$ = list1($1);
-       }
-|      hidden_interfacedcl_list ';' hidden_interfacedcl
-       {
-               $$ = list($1, $3);
-       }
-
-%%
-
-static void
-fixlbrace(int lbr)
-{
-       // If the opening brace was an LBODY,
-       // set up for another one now that we're done.
-       // See comment in lex.c about loophack.
-       if(lbr == LBODY)
-               loophack = 1;
-}
-
diff --git a/src/cmd/gc/gsubr.c b/src/cmd/gc/gsubr.c
deleted file mode 100644 (file)
index 5175ae3..0000000
+++ /dev/null
@@ -1,654 +0,0 @@
-// Derived from Inferno utils/6c/txt.c
-// http://code.google.com/p/inferno-os/source/browse/utils/6c/txt.c
-//
-//     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 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 <u.h>
-#include <libc.h>
-#include "go.h"
-#include "../../runtime/funcdata.h"
-#include "../ld/textflag.h"
-
-void
-ggloblnod(Node *nam)
-{
-       Prog *p;
-
-       p = thearch.gins(AGLOBL, nam, N);
-       p->lineno = nam->lineno;
-       p->from.sym->gotype = linksym(ngotype(nam));
-       p->to.sym = nil;
-       p->to.type = TYPE_CONST;
-       p->to.offset = nam->type->width;
-       if(nam->readonly)
-               p->from3.offset = RODATA;
-       if(nam->type != T && !haspointers(nam->type))
-               p->from3.offset |= NOPTR;
-}
-
-void
-gtrack(Sym *s)
-{
-       Prog *p;
-       
-       p = thearch.gins(AUSEFIELD, N, N);
-       p->from.type = TYPE_MEM;
-       p->from.name = NAME_EXTERN;
-       p->from.sym = linksym(s);
-}
-
-void
-ggloblsym(Sym *s, int32 width, int8 flags)
-{
-       Prog *p;
-
-       p = thearch.gins(AGLOBL, N, N);
-       p->from.type = TYPE_MEM;
-       p->from.name = NAME_EXTERN;
-       p->from.sym = linksym(s);
-       p->to.type = TYPE_CONST;
-       p->to.offset = width;
-       p->from3.offset = flags;
-}
-
-void
-clearp(Prog *p)
-{
-       nopout(p);
-       p->as = AEND;
-       p->pc = pcloc;
-       pcloc++;
-}
-
-static int ddumped;
-static Prog *dfirst;
-static Prog *dpc;
-
-/*
- * generate and return proc with p->as = as,
- * linked into program. pc is next instruction.
- */
-Prog*
-prog(int as)
-{
-       Prog *p;
-
-       if(as == ADATA || as == AGLOBL) {
-               if(ddumped)
-                       fatal("already dumped data");
-               if(dpc == nil) {
-                       dpc = mal(sizeof(*dpc));
-                       dfirst = dpc;
-               }
-               p = dpc;
-               dpc = mal(sizeof(*dpc));
-               p->link = dpc;
-       } else {
-               p = pc;
-               pc = mal(sizeof(*pc));
-               clearp(pc);
-               p->link = pc;
-       }
-
-       if(lineno == 0) {
-               if(debug['K'])
-                       warn("prog: line 0");
-       }
-
-       p->as = as;
-       p->lineno = lineno;
-       return p;
-}
-
-void
-dumpdata(void)
-{
-       ddumped = 1;
-       if(dfirst == nil)
-               return;
-       newplist();
-       *pc = *dfirst;
-       pc = dpc;
-       clearp(pc);
-}
-
-/*
- * generate a branch.
- * t is ignored.
- * likely values are for branch prediction:
- *     -1 unlikely
- *     0 no opinion
- *     +1 likely
- */
-Prog*
-gbranch(int as, Type *t, int likely)
-{
-       Prog *p;
-       
-       USED(t);
-
-       p = prog(as);
-       p->to.type = TYPE_BRANCH;
-       p->to.u.branch = P;
-       if(as != AJMP && likely != 0 && thearch.thechar != '9') {
-               p->from.type = TYPE_CONST;
-               p->from.offset = likely > 0;
-       }
-       return p;
-}
-
-/*
- * patch previous branch to jump to to.
- */
-void
-patch(Prog *p, Prog *to)
-{
-       if(p->to.type != TYPE_BRANCH)
-               fatal("patch: not a branch");
-       p->to.u.branch = to;
-       p->to.offset = to->pc;
-}
-
-Prog*
-unpatch(Prog *p)
-{
-       Prog *q;
-
-       if(p->to.type != TYPE_BRANCH)
-               fatal("unpatch: not a branch");
-       q = p->to.u.branch;
-       p->to.u.branch = P;
-       p->to.offset = 0;
-       return q;
-}
-
-/*
- * start a new Prog list.
- */
-Plist*
-newplist(void)
-{
-       Plist *pl;
-
-       pl = linknewplist(ctxt);
-
-       pc = mal(sizeof(*pc));
-       clearp(pc);
-       pl->firstpc = pc;
-
-       return pl;
-}
-
-void
-gused(Node *n)
-{
-       thearch.gins(ANOP, n, N);       // used
-}
-
-Prog*
-gjmp(Prog *to)
-{
-       Prog *p;
-
-       p = gbranch(AJMP, T, 0);
-       if(to != P)
-               patch(p, to);
-       return p;
-}
-
-int
-isfat(Type *t)
-{
-       if(t != T)
-       switch(t->etype) {
-       case TSTRUCT:
-       case TARRAY:
-       case TSTRING:
-       case TINTER:    // maybe remove later
-               return 1;
-       }
-       return 0;
-}
-
-/*
- * naddr of func generates code for address of func.
- * if using opcode that can take address implicitly,
- * call afunclit to fix up the argument.
- */
-void
-afunclit(Addr *a, Node *n)
-{
-       if(a->type == TYPE_ADDR && a->name == NAME_EXTERN) {
-               a->type = TYPE_MEM;
-               a->sym = linksym(n->sym);
-       }
-}
-
-/*
- * initialize n to be register r of type t.
- */
-void
-nodreg(Node *n, Type *t, int r)
-{
-       if(t == T)
-               fatal("nodreg: t nil");
-
-       memset(n, 0, sizeof(*n));
-       n->op = OREGISTER;
-       n->addable = 1;
-       ullmancalc(n);
-       n->val.u.reg = r;
-       n->type = t;
-}
-
-/*
- * initialize n to be indirect of register r; n is type t.
- */
-void
-nodindreg(Node *n, Type *t, int r)
-{
-       nodreg(n, t, r);
-       n->op = OINDREG;
-}
-
-/*
- * Is this node a memory operand?
- */
-int
-ismem(Node *n)
-{
-       switch(n->op) {
-       case OITAB:
-       case OSPTR:
-       case OLEN:
-       case OCAP:
-       case OINDREG:
-       case ONAME:
-       case OPARAM:
-       case OCLOSUREVAR:
-               return 1;
-       case OADDR:
-               return thearch.thechar == '6' || thearch.thechar == '9'; // because 6g uses PC-relative addressing; TODO(rsc): not sure why 9g too
-       }
-       return 0;
-}
-
-// Sweep the prog list to mark any used nodes.
-void
-markautoused(Prog* p)
-{
-       for (; p; p = p->link) {
-               if (p->as == ATYPE || p->as == AVARDEF || p->as == AVARKILL)
-                       continue;
-
-               if (p->from.node)
-                       ((Node*)(p->from.node))->used = 1;
-
-               if (p->to.node)
-                       ((Node*)(p->to.node))->used = 1;
-       }
-}
-
-// Fixup instructions after allocauto (formerly compactframe) has moved all autos around.
-void
-fixautoused(Prog *p)
-{
-       Prog **lp;
-
-       for (lp=&p; (p=*lp) != P; ) {
-               if (p->as == ATYPE && p->from.node && p->from.name == NAME_AUTO && !((Node*)(p->from.node))->used) {
-                       *lp = p->link;
-                       continue;
-               }
-               if ((p->as == AVARDEF || p->as == AVARKILL) && p->to.node && !((Node*)(p->to.node))->used) {
-                       // Cannot remove VARDEF instruction, because - unlike TYPE handled above -
-                       // VARDEFs are interspersed with other code, and a jump might be using the
-                       // VARDEF as a target. Replace with a no-op instead. A later pass will remove
-                       // the no-ops.
-                       nopout(p);
-                       continue;
-               }
-               if (p->from.name == NAME_AUTO && p->from.node)
-                       p->from.offset += ((Node*)(p->from.node))->stkdelta;
-
-               if (p->to.name == NAME_AUTO && p->to.node)
-                       p->to.offset += ((Node*)(p->to.node))->stkdelta;
-
-               lp = &p->link;
-       }
-}
-
-int
-samereg(Node *a, Node *b)
-{
-       if(a == N || b == N)
-               return 0;
-       if(a->op != OREGISTER)
-               return 0;
-       if(b->op != OREGISTER)
-               return 0;
-       if(a->val.u.reg != b->val.u.reg)
-               return 0;
-       return 1;
-}
-
-Node*
-nodarg(Type *t, int fp)
-{
-       Node *n;
-       NodeList *l;
-       Type *first;
-       Iter savet;
-
-       // entire argument struct, not just one arg
-       if(t->etype == TSTRUCT && t->funarg) {
-               n = nod(ONAME, N, N);
-               n->sym = lookup(".args");
-               n->type = t;
-               first = structfirst(&savet, &t);
-               if(first == nil)
-                       fatal("nodarg: bad struct");
-               if(first->width == BADWIDTH)
-                       fatal("nodarg: offset not computed for %T", t);
-               n->xoffset = first->width;
-               n->addable = 1;
-               goto fp;
-       }
-
-       if(t->etype != TFIELD)
-               fatal("nodarg: not field %T", t);
-       
-       if(fp == 1) {
-               for(l=curfn->dcl; l; l=l->next) {
-                       n = l->n;
-                       if((n->class == PPARAM || n->class == PPARAMOUT) && !isblanksym(t->sym) && n->sym == t->sym)
-                               return n;
-               }
-       }
-
-       n = nod(ONAME, N, N);
-       n->type = t->type;
-       n->sym = t->sym;
-       
-       if(t->width == BADWIDTH)
-               fatal("nodarg: offset not computed for %T", t);
-       n->xoffset = t->width;
-       n->addable = 1;
-       n->orig = t->nname;
-
-fp:
-       // Rewrite argument named _ to __,
-       // or else the assignment to _ will be
-       // discarded during code generation.
-       if(isblank(n))
-               n->sym = lookup("__");
-
-       switch(fp) {
-       case 0:         // output arg
-               n->op = OINDREG;
-               n->val.u.reg = thearch.REGSP;
-               if(thearch.thechar == '5')
-                       n->xoffset += 4;
-               if(thearch.thechar == '9')
-                       n->xoffset += 8;
-               break;
-
-       case 1:         // input arg
-               n->class = PPARAM;
-               break;
-
-       case 2:         // offset output arg
-fatal("shouldn't be used");
-               n->op = OINDREG;
-               n->val.u.reg = thearch.REGSP;
-               n->xoffset += types[tptr]->width;
-               break;
-       }
-       n->typecheck = 1;
-       return n;
-}
-
-/*
- * generate code to compute n;
- * make a refer to result.
- */
-void
-naddr(Node *n, Addr *a, int canemitcode)
-{
-       Sym *s;
-
-       *a = zprog.from;
-       if(n == N)
-               return;
-
-       if(n->type != T && n->type->etype != TIDEAL) {
-               // TODO(rsc): This is undone by the selective clearing of width below,
-               // to match architectures that were not as aggressive in setting width
-               // during naddr. Those widths must be cleared to avoid triggering
-               // failures in gins when it detects real but heretofore latent (and one
-               // hopes innocuous) type mismatches.
-               // The type mismatches should be fixed and the clearing below removed.
-               dowidth(n->type);
-               a->width = n->type->width;
-       }
-
-       switch(n->op) {
-       default:
-               fatal("naddr: bad %O %D", n->op, a);
-               break;
-
-       case OREGISTER:
-               a->type = TYPE_REG;
-               a->reg = n->val.u.reg;
-               a->sym = nil;
-               if(thearch.thechar == '8') // TODO(rsc): Never clear a->width.
-                       a->width = 0;
-               break;
-
-       case OINDREG:
-               a->type = TYPE_MEM;
-               a->reg = n->val.u.reg;
-               a->sym = linksym(n->sym);
-               a->offset = n->xoffset;
-               if(a->offset != (int32)a->offset)
-                       yyerror("offset %lld too large for OINDREG", a->offset);
-               if(thearch.thechar == '8') // TODO(rsc): Never clear a->width.
-                       a->width = 0;
-               break;
-
-       case OPARAM:
-               // n->left is PHEAP ONAME for stack parameter.
-               // compute address of actual parameter on stack.
-               a->etype = simtype[n->left->type->etype];
-               a->width = n->left->type->width;
-               a->offset = n->xoffset;
-               a->sym = linksym(n->left->sym);
-               a->type = TYPE_MEM;
-               a->name = NAME_PARAM;
-               a->node = n->left->orig;
-               break;
-       
-       case OCLOSUREVAR:
-               if(!curfn->needctxt)
-                       fatal("closurevar without needctxt");
-               a->type = TYPE_MEM;
-               a->reg = thearch.REGCTXT;
-               a->sym = nil;
-               a->offset = n->xoffset;
-               break;
-       
-       case OCFUNC:
-               naddr(n->left, a, canemitcode);
-               a->sym = linksym(n->left->sym);
-               break;
-
-       case ONAME:
-               a->etype = 0;
-               if(n->type != T)
-                       a->etype = simtype[n->type->etype];
-               a->offset = n->xoffset;
-               s = n->sym;
-               a->node = n->orig;
-               //if(a->node >= (Node*)&n)
-               //      fatal("stack node");
-               if(s == S)
-                       s = lookup(".noname");
-               if(n->method) {
-                       if(n->type != T)
-                       if(n->type->sym != S)
-                       if(n->type->sym->pkg != nil)
-                               s = pkglookup(s->name, n->type->sym->pkg);
-               }
-
-               a->type = TYPE_MEM;
-               switch(n->class) {
-               default:
-                       fatal("naddr: ONAME class %S %d\n", n->sym, n->class);
-               case PEXTERN:
-                       a->name = NAME_EXTERN;
-                       break;
-               case PAUTO:
-                       a->name = NAME_AUTO;
-                       break;
-               case PPARAM:
-               case PPARAMOUT:
-                       a->name = NAME_PARAM;
-                       break;
-               case PFUNC:
-                       a->name = NAME_EXTERN;
-                       a->type = TYPE_ADDR;
-                       a->width = widthptr;
-                       s = funcsym(s);                 
-                       break;
-               }
-               a->sym = linksym(s);
-               break;
-
-       case OLITERAL:
-               if(thearch.thechar == '8')
-                       a->width = 0;
-               switch(n->val.ctype) {
-               default:
-                       fatal("naddr: const %lT", n->type);
-                       break;
-               case CTFLT:
-                       a->type = TYPE_FCONST;
-                       a->u.dval = mpgetflt(n->val.u.fval);
-                       break;
-               case CTINT:
-               case CTRUNE:
-                       a->sym = nil;
-                       a->type = TYPE_CONST;
-                       a->offset = mpgetfix(n->val.u.xval);
-                       break;
-               case CTSTR:
-                       datagostring(n->val.u.sval, a);
-                       break;
-               case CTBOOL:
-                       a->sym = nil;
-                       a->type = TYPE_CONST;
-                       a->offset = n->val.u.bval;
-                       break;
-               case CTNIL:
-                       a->sym = nil;
-                       a->type = TYPE_CONST;
-                       a->offset = 0;
-                       break;
-               }
-               break;
-
-       case OADDR:
-               naddr(n->left, a, canemitcode);
-               a->etype = tptr;
-               if(thearch.thechar != '5' && thearch.thechar != '9') // TODO(rsc): Do this even for arm, ppc64.
-                       a->width = widthptr;
-               if(a->type != TYPE_MEM)
-                       fatal("naddr: OADDR %D (from %O)", a, n->left->op);
-               a->type = TYPE_ADDR;
-               break;
-       
-       case OITAB:
-               // itable of interface value
-               naddr(n->left, a, canemitcode);
-               if(a->type == TYPE_CONST && a->offset == 0)
-                       break;  // itab(nil)
-               a->etype = tptr;
-               a->width = widthptr;
-               break;
-
-       case OSPTR:
-               // pointer in a string or slice
-               naddr(n->left, a, canemitcode);
-               if(a->type == TYPE_CONST && a->offset == 0)
-                       break;  // ptr(nil)
-               a->etype = simtype[tptr];
-               a->offset += Array_array;
-               a->width = widthptr;
-               break;
-
-       case OLEN:
-               // len of string or slice
-               naddr(n->left, a, canemitcode);
-               if(a->type == TYPE_CONST && a->offset == 0)
-                       break;  // len(nil)
-               a->etype = simtype[TUINT];
-               if(thearch.thechar == '9')
-                       a->etype = simtype[TINT];
-               a->offset += Array_nel;
-               if(thearch.thechar != '5') // TODO(rsc): Do this even on arm.
-                       a->width = widthint;
-               break;
-
-       case OCAP:
-               // cap of string or slice
-               naddr(n->left, a, canemitcode);
-               if(a->type == TYPE_CONST && a->offset == 0)
-                       break;  // cap(nil)
-               a->etype = simtype[TUINT];
-               if(thearch.thechar == '9')
-                       a->etype = simtype[TINT];
-               a->offset += Array_cap;
-               if(thearch.thechar != '5') // TODO(rsc): Do this even on arm.
-                       a->width = widthint;
-               break;
-
-//     case OADD:
-//             if(n->right->op == OLITERAL) {
-//                     v = n->right->vconst;
-//                     naddr(n->left, a, canemitcode);
-//             } else
-//             if(n->left->op == OLITERAL) {
-//                     v = n->left->vconst;
-//                     naddr(n->right, a, canemitcode);
-//             } else
-//                     goto bad;
-//             a->offset += v;
-//             break;
-
-       }
-}
diff --git a/src/cmd/gc/init.c b/src/cmd/gc/init.c
deleted file mode 100644 (file)
index f1484ea..0000000
+++ /dev/null
@@ -1,194 +0,0 @@
-// Copyright 2009 The Go Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style
-// license that can be found in the LICENSE file.
-
-#include <u.h>
-#include <libc.h>
-#include "go.h"
-
-/*
- * a function named init is a special case.
- * it is called by the initialization before
- * main is run. to make it unique within a
- * package and also uncallable, the name,
- * normally "pkg.init", is altered to "pkg.init.1".
- */
-Sym*
-renameinit(void)
-{
-       static int initgen;
-
-       snprint(namebuf, sizeof(namebuf), "init.%d", ++initgen);
-       return lookup(namebuf);
-}
-
-/*
- * hand-craft the following initialization code
- *     var initdone· uint8                            (1)
- *     func init()                                     (2)
- *             if initdone· != 0 {                    (3)
- *                     if initdone· == 2              (4)
- *                             return
- *                     throw();                        (5)
- *             }
- *             initdone· = 1;                         (6)
- *             // over all matching imported symbols
- *                     <pkg>.init()                    (7)
- *             { <init stmts> }                        (8)
- *             init.<n>() // if any                    (9)
- *             initdone· = 2;                         (10)
- *             return                                  (11)
- *     }
- */
-static int
-anyinit(NodeList *n)
-{
-       uint32 h;
-       Sym *s;
-       NodeList *l;
-
-       // are there any interesting init statements
-       for(l=n; l; l=l->next) {
-               switch(l->n->op) {
-               case ODCLFUNC:
-               case ODCLCONST:
-               case ODCLTYPE:
-               case OEMPTY:
-                       break;
-               case OAS:
-                       if(isblank(l->n->left) && candiscard(l->n->right))
-                               break;
-                       // fall through
-               default:
-                       return 1;
-               }
-       }
-
-       // is this main
-       if(strcmp(localpkg->name, "main") == 0)
-               return 1;
-
-       // is there an explicit init function
-       s = lookup("init.1");
-       if(s->def != N)
-               return 1;
-
-       // are there any imported init functions
-       for(h=0; h<NHASH; h++)
-       for(s = hash[h]; s != S; s = s->link) {
-               if(s->name[0] != 'i' || strcmp(s->name, "init") != 0)
-                       continue;
-               if(s->def == N)
-                       continue;
-               return 1;
-       }
-
-       // then none
-       return 0;
-}
-
-void
-fninit(NodeList *n)
-{
-       int i;
-       Node *gatevar;
-       Node *a, *b, *fn;
-       NodeList *r;
-       uint32 h;
-       Sym *s, *initsym;
-
-       if(debug['A']) {
-               // sys.go or unsafe.go during compiler build
-               return;
-       }
-
-       n = initfix(n);
-       if(!anyinit(n))
-               return;
-
-       r = nil;
-
-       // (1)
-       snprint(namebuf, sizeof(namebuf), "initdone·");
-       gatevar = newname(lookup(namebuf));
-       addvar(gatevar, types[TUINT8], PEXTERN);
-
-       // (2)
-       maxarg = 0;
-       snprint(namebuf, sizeof(namebuf), "init");
-
-       fn = nod(ODCLFUNC, N, N);
-       initsym = lookup(namebuf);
-       fn->nname = newname(initsym);
-       fn->nname->defn = fn;
-       fn->nname->ntype = nod(OTFUNC, N, N);
-       declare(fn->nname, PFUNC);
-       funchdr(fn);
-
-       // (3)
-       a = nod(OIF, N, N);
-       a->ntest = nod(ONE, gatevar, nodintconst(0));
-       r = list(r, a);
-
-       // (4)
-       b = nod(OIF, N, N);
-       b->ntest = nod(OEQ, gatevar, nodintconst(2));
-       b->nbody = list1(nod(ORETURN, N, N));
-       a->nbody = list1(b);
-
-       // (5)
-       b = syslook("throwinit", 0);
-       b = nod(OCALL, b, N);
-       a->nbody = list(a->nbody, b);
-
-       // (6)
-       a = nod(OAS, gatevar, nodintconst(1));
-       r = list(r, a);
-
-       // (7)
-       for(h=0; h<NHASH; h++)
-       for(s = hash[h]; s != S; s = s->link) {
-               if(s->name[0] != 'i' || strcmp(s->name, "init") != 0)
-                       continue;
-               if(s->def == N)
-                       continue;
-               if(s == initsym)
-                       continue;
-
-               // could check that it is fn of no args/returns
-               a = nod(OCALL, s->def, N);
-               r = list(r, a);
-       }
-
-       // (8)
-       r = concat(r, n);
-
-       // (9)
-       // could check that it is fn of no args/returns
-       for(i=1;; i++) {
-               snprint(namebuf, sizeof(namebuf), "init.%d", i);
-               s = lookup(namebuf);
-               if(s->def == N)
-                       break;
-               a = nod(OCALL, s->def, N);
-               r = list(r, a);
-       }
-
-       // (10)
-       a = nod(OAS, gatevar, nodintconst(2));
-       r = list(r, a);
-
-       // (11)
-       a = nod(ORETURN, N, N);
-       r = list(r, a);
-       exportsym(fn->nname);
-
-       fn->nbody = r;
-       funcbody(fn);
-
-       curfn = fn;
-       typecheck(&fn, Etop);
-       typechecklist(r, Etop);
-       curfn = nil;
-       funccompile(fn);
-}
diff --git a/src/cmd/gc/inl.c b/src/cmd/gc/inl.c
deleted file mode 100644 (file)
index 45e15bb..0000000
+++ /dev/null
@@ -1,986 +0,0 @@
-// Copyright 2011 The Go Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style
-// license that can be found in the LICENSE file.
-//
-// The inlining facility makes 2 passes: first caninl determines which
-// functions are suitable for inlining, and for those that are it
-// saves a copy of the body. Then inlcalls walks each function body to
-// expand calls to inlinable functions.
-//
-// The debug['l'] flag controls the agressiveness. Note that main() swaps level 0 and 1,
-// making 1 the default and -l disable.  -ll and more is useful to flush out bugs.
-// These additional levels (beyond -l) may be buggy and are not supported.
-//      0: disabled
-//      1: 40-nodes leaf functions, oneliners, lazy typechecking (default)
-//      2: early typechecking of all imported bodies 
-//      3: allow variadic functions
-//      4: allow non-leaf functions , (breaks runtime.Caller)
-//      5: transitive inlining
-//
-//  At some point this may get another default and become switch-offable with -N.
-//
-//  The debug['m'] flag enables diagnostic output.  a single -m is useful for verifying
-//  which calls get inlined or not, more is for debugging, and may go away at any point.
-//
-// TODO:
-//   - inline functions with ... args
-//   - handle T.meth(f()) with func f() (t T, arg, arg, )
-
-#include <u.h>
-#include <libc.h>
-#include "go.h"
-
-// Used by caninl.
-static Node*   inlcopy(Node *n);
-static NodeList* inlcopylist(NodeList *ll);
-static int     ishairy(Node *n, int *budget);
-static int     ishairylist(NodeList *ll, int *budget); 
-
-// Used by inlcalls
-static void    inlnodelist(NodeList *l);
-static void    inlnode(Node **np);
-static void    mkinlcall(Node **np, Node *fn, int isddd);
-static Node*   inlvar(Node *n);
-static Node*   retvar(Type *n, int i);
-static Node*   argvar(Type *n, int i);
-static Node*   newlabel(void);
-static Node*   inlsubst(Node *n);
-static NodeList* inlsubstlist(NodeList *l);
-
-static void    setlno(Node*, int);
-
-// Used during inlsubst[list]
-static Node *inlfn;            // function currently being inlined
-static Node *inlretlabel;      // target of the goto substituted in place of a return
-static NodeList *inlretvars;   // temp out variables
-
-// Get the function's package.  For ordinary functions it's on the ->sym, but for imported methods
-// the ->sym can be re-used in the local package, so peel it off the receiver's type.
-static Pkg*
-fnpkg(Node *fn)
-{
-       Type *rcvr;
-       
-       if(fn->type->thistuple) {
-               // method
-               rcvr = getthisx(fn->type)->type->type;
-               if(isptr[rcvr->etype])
-                       rcvr = rcvr->type;
-               if(!rcvr->sym)
-                       fatal("receiver with no sym: [%S] %lN  (%T)", fn->sym, fn, rcvr);
-               return rcvr->sym->pkg;
-       }
-       // non-method
-       return fn->sym->pkg;
-}
-
-// Lazy typechecking of imported bodies.  For local functions, caninl will set ->typecheck
-// because they're a copy of an already checked body. 
-void
-typecheckinl(Node *fn)
-{
-       Node *savefn;
-       Pkg *pkg;
-       int save_safemode, lno;
-
-       lno = setlineno(fn);
-
-       // typecheckinl is only for imported functions;
-       // their bodies may refer to unsafe as long as the package
-       // was marked safe during import (which was checked then).
-       // the ->inl of a local function has been typechecked before caninl copied it.
-       pkg = fnpkg(fn);
-       if (pkg == localpkg || pkg == nil)
-               return; // typecheckinl on local function
-
-       if (debug['m']>2)
-               print("typecheck import [%S] %lN { %#H }\n", fn->sym, fn, fn->inl);
-
-       save_safemode = safemode;
-       safemode = 0;
-
-       savefn = curfn;
-       curfn = fn;
-       typechecklist(fn->inl, Etop);
-       curfn = savefn;
-
-       safemode = save_safemode;
-
-       lineno = lno;
-}
-
-// Caninl determines whether fn is inlineable.
-// If so, caninl saves fn->nbody in fn->inl and substitutes it with a copy.
-// fn and ->nbody will already have been typechecked.
-void
-caninl(Node *fn)
-{
-       Node *savefn;
-       Type *t;
-       int budget;
-
-       if(fn->op != ODCLFUNC)
-               fatal("caninl %N", fn);
-       if(!fn->nname)
-               fatal("caninl no nname %+N", fn);
-
-       // If fn has no body (is defined outside of Go), cannot inline it.
-       if(fn->nbody == nil)
-               return;
-
-       if(fn->typecheck == 0)
-               fatal("caninl on non-typechecked function %N", fn);
-
-       // can't handle ... args yet
-       if(debug['l'] < 3)
-               for(t=fn->type->type->down->down->type; t; t=t->down)
-                       if(t->isddd)
-                               return;
-
-       budget = 40;  // allowed hairyness
-       if(ishairylist(fn->nbody, &budget))
-               return;
-
-       savefn = curfn;
-       curfn = fn;
-
-       fn->nname->inl = fn->nbody;
-       fn->nbody = inlcopylist(fn->nname->inl);
-       fn->nname->inldcl = inlcopylist(fn->nname->defn->dcl);
-
-       // hack, TODO, check for better way to link method nodes back to the thing with the ->inl
-       // this is so export can find the body of a method
-       fn->type->nname = fn->nname;
-
-       if(debug['m'] > 1)
-               print("%L: can inline %#N as: %#T { %#H }\n", fn->lineno, fn->nname, fn->type, fn->nname->inl);
-       else if(debug['m'])
-               print("%L: can inline %N\n", fn->lineno, fn->nname);
-
-       curfn = savefn;
-}
-
-// Look for anything we want to punt on.
-static int
-ishairylist(NodeList *ll, int* budget)
-{
-       for(;ll;ll=ll->next)
-               if(ishairy(ll->n, budget))
-                       return 1;
-       return 0;
-}
-
-static int
-ishairy(Node *n, int *budget)
-{
-       if(!n)
-               return 0;
-
-       // Things that are too hairy, irrespective of the budget
-       switch(n->op) {
-       case OCALL:
-       case OCALLFUNC:
-       case OCALLINTER:
-       case OCALLMETH:
-       case OPANIC:
-       case ORECOVER:
-               if(debug['l'] < 4)
-                       return 1;
-               break;
-
-       case OCLOSURE:
-       case OCALLPART:
-       case ORANGE:
-       case OFOR:
-       case OSELECT:
-       case OSWITCH:
-       case OPROC:
-       case ODEFER:
-       case ODCLTYPE:  // can't print yet
-       case ODCLCONST:  // can't print yet
-       case ORETJMP:
-               return 1;
-
-               break;
-       }
-
-       (*budget)--;
-
-       return  *budget < 0 ||
-               ishairy(n->left, budget) ||
-               ishairy(n->right, budget) ||
-               ishairylist(n->list, budget) ||
-               ishairylist(n->rlist, budget) ||
-               ishairylist(n->ninit, budget) ||
-               ishairy(n->ntest, budget) ||
-               ishairy(n->nincr, budget) ||
-               ishairylist(n->nbody, budget) ||
-               ishairylist(n->nelse, budget);
-}
-
-// Inlcopy and inlcopylist recursively copy the body of a function.
-// Any name-like node of non-local class is marked for re-export by adding it to
-// the exportlist.
-static NodeList*
-inlcopylist(NodeList *ll)
-{
-       NodeList *l;
-
-       l = nil;
-       for(; ll; ll=ll->next)
-               l = list(l, inlcopy(ll->n));
-       return l;
-}
-
-static Node*
-inlcopy(Node *n)
-{
-       Node *m;
-
-       if(n == N)
-               return N;
-
-       switch(n->op) {
-       case ONAME:
-       case OTYPE:
-       case OLITERAL:
-               return n;
-       }
-
-       m = nod(OXXX, N, N);
-       *m = *n;
-       m->inl = nil;
-       m->left   = inlcopy(n->left);
-       m->right  = inlcopy(n->right);
-       m->list   = inlcopylist(n->list);
-       m->rlist  = inlcopylist(n->rlist);
-       m->ninit  = inlcopylist(n->ninit);
-       m->ntest  = inlcopy(n->ntest);
-       m->nincr  = inlcopy(n->nincr);
-       m->nbody  = inlcopylist(n->nbody);
-       m->nelse  = inlcopylist(n->nelse);
-
-       return m;
-}
-
-
-// Inlcalls/nodelist/node walks fn's statements and expressions and substitutes any
-// calls made to inlineable functions.  This is the external entry point.
-void
-inlcalls(Node *fn)
-{
-       Node *savefn;
-
-       savefn = curfn;
-       curfn = fn;
-       inlnode(&fn);
-       if(fn != curfn)
-               fatal("inlnode replaced curfn");
-       curfn = savefn;
-}
-
-// Turn an OINLCALL into a statement.
-static void
-inlconv2stmt(Node *n)
-{
-       n->op = OBLOCK;
-       // n->ninit stays
-       n->list = n->nbody;
-       n->nbody = nil;
-       n->rlist = nil;
-}
-
-// Turn an OINLCALL into a single valued expression.
-static void
-inlconv2expr(Node **np)
-{
-       Node *n, *r;
-       n = *np;
-       r = n->rlist->n;
-       addinit(&r, concat(n->ninit, n->nbody));
-       *np = r;
-}
-
-// Turn the rlist (with the return values) of the OINLCALL in
-// n into an expression list lumping the ninit and body
-// containing the inlined statements on the first list element so
-// order will be preserved Used in return, oas2func and call
-// statements.
-static NodeList*
-inlconv2list(Node *n)
-{
-       NodeList *l;
-
-       if(n->op != OINLCALL || n->rlist == nil)
-               fatal("inlconv2list %+N\n", n);
-       
-       l = n->rlist;
-       addinit(&l->n, concat(n->ninit, n->nbody));
-       return l;
-} 
-static void
-inlnodelist(NodeList *l)
-{
-       for(; l; l=l->next)
-               inlnode(&l->n);
-}
-
-// inlnode recurses over the tree to find inlineable calls, which will
-// be turned into OINLCALLs by mkinlcall.  When the recursion comes
-// back up will examine left, right, list, rlist, ninit, ntest, nincr,
-// nbody and nelse and use one of the 4 inlconv/glue functions above
-// to turn the OINLCALL into an expression, a statement, or patch it
-// in to this nodes list or rlist as appropriate.
-// NOTE it makes no sense to pass the glue functions down the
-// recursion to the level where the OINLCALL gets created because they
-// have to edit /this/ n, so you'd have to push that one down as well,
-// but then you may as well do it here.  so this is cleaner and
-// shorter and less complicated.
-static void
-inlnode(Node **np)
-{
-       Node *n;
-       NodeList *l;
-       int lno;
-
-       if(*np == nil)
-               return;
-
-       n = *np;
-       
-       switch(n->op) {
-       case ODEFER:
-       case OPROC:
-               // inhibit inlining of their argument
-               switch(n->left->op) {
-               case OCALLFUNC:
-               case OCALLMETH:
-                       n->left->etype = n->op;
-               }
-
-       case OCLOSURE:
-               // TODO do them here (or earlier),
-               // so escape analysis can avoid more heapmoves.
-               return;
-       }
-
-       lno = setlineno(n);
-
-       inlnodelist(n->ninit);
-       for(l=n->ninit; l; l=l->next)
-               if(l->n->op == OINLCALL)
-                       inlconv2stmt(l->n);
-
-       inlnode(&n->left);
-       if(n->left && n->left->op == OINLCALL)
-               inlconv2expr(&n->left);
-
-       inlnode(&n->right);
-       if(n->right && n->right->op == OINLCALL)
-               inlconv2expr(&n->right);
-
-       inlnodelist(n->list);
-       switch(n->op) {
-       case OBLOCK:
-               for(l=n->list; l; l=l->next)
-                       if(l->n->op == OINLCALL)
-                               inlconv2stmt(l->n);
-               break;
-
-       case ORETURN:
-       case OCALLFUNC:
-       case OCALLMETH:
-       case OCALLINTER:
-       case OAPPEND:
-       case OCOMPLEX:
-               // if we just replaced arg in f(arg()) or return arg with an inlined call
-               // and arg returns multiple values, glue as list
-               if(count(n->list) == 1 && n->list->n->op == OINLCALL && count(n->list->n->rlist) > 1) {
-                       n->list = inlconv2list(n->list->n);
-                       break;
-               }
-
-               // fallthrough
-       default:
-               for(l=n->list; l; l=l->next)
-                       if(l->n->op == OINLCALL)
-                               inlconv2expr(&l->n);
-       }
-
-       inlnodelist(n->rlist);
-       switch(n->op) {
-       case OAS2FUNC:
-               if(n->rlist->n->op == OINLCALL) {
-                       n->rlist = inlconv2list(n->rlist->n);
-                       n->op = OAS2;
-                       n->typecheck = 0;
-                       typecheck(np, Etop);
-                       break;
-               }
-
-               // fallthrough
-       default:
-               for(l=n->rlist; l; l=l->next)
-                       if(l->n->op == OINLCALL)
-                               inlconv2expr(&l->n);
-
-       }
-
-       inlnode(&n->ntest);
-       if(n->ntest && n->ntest->op == OINLCALL)
-               inlconv2expr(&n->ntest);
-
-       inlnode(&n->nincr);
-       if(n->nincr && n->nincr->op == OINLCALL)
-               inlconv2stmt(n->nincr);
-
-       inlnodelist(n->nbody);
-       for(l=n->nbody; l; l=l->next)
-               if(l->n->op == OINLCALL)
-                       inlconv2stmt(l->n);
-
-       inlnodelist(n->nelse);
-       for(l=n->nelse; l; l=l->next)
-               if(l->n->op == OINLCALL)
-                       inlconv2stmt(l->n);
-
-       // with all the branches out of the way, it is now time to
-       // transmogrify this node itself unless inhibited by the
-       // switch at the top of this function.
-       switch(n->op) {
-       case OCALLFUNC:
-       case OCALLMETH:
-               if (n->etype == OPROC || n->etype == ODEFER)
-                       return;
-       }
-
-       switch(n->op) {
-       case OCALLFUNC:
-               if(debug['m']>3)
-                       print("%L:call to func %+N\n", n->lineno, n->left);
-               if(n->left->inl)        // normal case
-                       mkinlcall(np, n->left, n->isddd);
-               else if(n->left->op == ONAME && n->left->left && n->left->left->op == OTYPE && n->left->right &&  n->left->right->op == ONAME)  // methods called as functions
-                       if(n->left->sym->def)
-                               mkinlcall(np, n->left->sym->def, n->isddd);
-               break;
-
-       case OCALLMETH:
-               if(debug['m']>3)
-                       print("%L:call to meth %lN\n", n->lineno, n->left->right);
-               // typecheck should have resolved ODOTMETH->type, whose nname points to the actual function.
-               if(n->left->type == T) 
-                       fatal("no function type for [%p] %+N\n", n->left, n->left);
-
-               if(n->left->type->nname == N) 
-                       fatal("no function definition for [%p] %+T\n", n->left->type, n->left->type);
-
-               mkinlcall(np, n->left->type->nname, n->isddd);
-
-               break;
-       }
-       
-       lineno = lno;
-}
-
-static void    mkinlcall1(Node **np, Node *fn, int isddd);
-
-static void
-mkinlcall(Node **np, Node *fn, int isddd)
-{
-       int save_safemode;
-       Pkg *pkg;
-
-       save_safemode = safemode;
-
-       // imported functions may refer to unsafe as long as the
-       // package was marked safe during import (already checked).
-       pkg = fnpkg(fn);
-       if(pkg != localpkg && pkg != nil)
-               safemode = 0;
-       mkinlcall1(np, fn, isddd);
-       safemode = save_safemode;
-}
-
-static Node*
-tinlvar(Type *t)
-{
-       if(t->nname && !isblank(t->nname)) {
-               if(!t->nname->inlvar)
-                       fatal("missing inlvar for %N\n", t->nname);
-               return t->nname->inlvar;
-       }
-       typecheck(&nblank, Erv | Easgn);
-       return nblank;
-}
-
-static int inlgen;
-
-// if *np is a call, and fn is a function with an inlinable body, substitute *np with an OINLCALL.
-// On return ninit has the parameter assignments, the nbody is the
-// inlined function body and list, rlist contain the input, output
-// parameters.
-static void
-mkinlcall1(Node **np, Node *fn, int isddd)
-{
-       int i;
-       int chkargcount;
-       Node *n, *call, *saveinlfn, *as, *m;
-       NodeList *dcl, *ll, *ninit, *body;
-       Type *t;
-       // For variadic fn.
-       int variadic, varargcount, multiret;
-       Node *vararg;
-       NodeList *varargs;
-       Type *varargtype, *vararrtype;
-
-       if (fn->inl == nil)
-               return;
-
-       if (fn == curfn || fn->defn == curfn)
-               return;
-
-       if(debug['l']<2)
-               typecheckinl(fn);
-
-       n = *np;
-
-       // Bingo, we have a function node, and it has an inlineable body
-       if(debug['m']>1)
-               print("%L: inlining call to %S %#T { %#H }\n", n->lineno, fn->sym, fn->type, fn->inl);
-       else if(debug['m'])
-               print("%L: inlining call to %N\n", n->lineno, fn);
-
-       if(debug['m']>2)
-               print("%L: Before inlining: %+N\n", n->lineno, n);
-
-       saveinlfn = inlfn;
-       inlfn = fn;
-
-       ninit = n->ninit;
-
-//dumplist("ninit pre", ninit);
-
-       if(fn->defn) // local function
-               dcl = fn->inldcl;
-       else // imported function
-               dcl = fn->dcl;
-
-       inlretvars = nil;
-       i = 0;
-       // Make temp names to use instead of the originals
-       for(ll = dcl; ll; ll=ll->next) {
-               if(ll->n->class == PPARAMOUT)  // return values handled below.
-                       continue;
-               if(ll->n->op == ONAME) {
-                       ll->n->inlvar = inlvar(ll->n);
-                       // Typecheck because inlvar is not necessarily a function parameter.
-                       typecheck(&ll->n->inlvar, Erv);
-                       if ((ll->n->class&~PHEAP) != PAUTO)
-                               ninit = list(ninit, nod(ODCL, ll->n->inlvar, N));  // otherwise gen won't emit the allocations for heapallocs
-               }
-       }
-
-       // temporaries for return values.
-       for(t = getoutargx(fn->type)->type; t; t = t->down) {
-               if(t != T && t->nname != N && !isblank(t->nname)) {
-                       m = inlvar(t->nname);
-                       typecheck(&m, Erv);
-                       t->nname->inlvar = m;
-               } else {
-                       // anonymous return values, synthesize names for use in assignment that replaces return
-                       m = retvar(t, i++);
-               }
-               ninit = list(ninit, nod(ODCL, m, N));
-               inlretvars = list(inlretvars, m);
-       }
-
-       // assign receiver.
-       if(fn->type->thistuple && n->left->op == ODOTMETH) {
-               // method call with a receiver.
-               t = getthisx(fn->type)->type;
-               if(t != T && t->nname != N && !isblank(t->nname) && !t->nname->inlvar)
-                       fatal("missing inlvar for %N\n", t->nname);
-               if(!n->left->left)
-                       fatal("method call without receiver: %+N", n);
-               if(t == T)
-                       fatal("method call unknown receiver type: %+N", n);
-               as = nod(OAS, tinlvar(t), n->left->left);
-               if(as != N) {
-                       typecheck(&as, Etop);
-                       ninit = list(ninit, as);
-               }
-       }
-
-       // check if inlined function is variadic.
-       variadic = 0;
-       varargtype = T;
-       varargcount = 0;
-       for(t=fn->type->type->down->down->type; t; t=t->down) {
-               if(t->isddd) {
-                       variadic = 1;
-                       varargtype = t->type;
-               }
-       }
-       // but if argument is dotted too forget about variadicity.
-       if(variadic && isddd)
-               variadic = 0;
-
-       // check if argument is actually a returned tuple from call.
-       multiret = 0;
-       if(n->list && !n->list->next) {
-               switch(n->list->n->op) {
-               case OCALL:
-               case OCALLFUNC:
-               case OCALLINTER:
-               case OCALLMETH:
-                       if(n->list->n->left->type->outtuple > 1)
-                               multiret = n->list->n->left->type->outtuple-1;
-               }
-       }
-
-       if(variadic) {
-               varargcount = count(n->list) + multiret;
-               if(n->left->op != ODOTMETH)
-                       varargcount -= fn->type->thistuple;
-               varargcount -= fn->type->intuple - 1;
-       }
-
-       // assign arguments to the parameters' temp names
-       as = nod(OAS2, N, N);
-       as->rlist = n->list;
-       ll = n->list;
-
-       // TODO: if len(nlist) == 1 but multiple args, check that n->list->n is a call?
-       if(fn->type->thistuple && n->left->op != ODOTMETH) {
-               // non-method call to method
-               if(!n->list)
-                       fatal("non-method call to method without first arg: %+N", n);
-               // append receiver inlvar to LHS.
-               t = getthisx(fn->type)->type;
-               if(t != T && t->nname != N && !isblank(t->nname) && !t->nname->inlvar)
-                       fatal("missing inlvar for %N\n", t->nname);
-               if(t == T)
-                       fatal("method call unknown receiver type: %+N", n);
-               as->list = list(as->list, tinlvar(t));
-               ll = ll->next; // track argument count.
-       }
-
-       // append ordinary arguments to LHS.
-       chkargcount = n->list && n->list->next;
-       vararg = N;    // the slice argument to a variadic call
-       varargs = nil; // the list of LHS names to put in vararg.
-       if(!chkargcount) {
-               // 0 or 1 expression on RHS.
-               for(t = getinargx(fn->type)->type; t; t=t->down) {
-                       if(variadic && t->isddd) {
-                               vararg = tinlvar(t);
-                               for(i=0; i<varargcount && ll; i++) {
-                                       m = argvar(varargtype, i);
-                                       varargs = list(varargs, m);
-                                       as->list = list(as->list, m);
-                               }
-                               break;
-                       }
-                       as->list = list(as->list, tinlvar(t));
-               }
-       } else {
-               // match arguments except final variadic (unless the call is dotted itself)
-               for(t = getinargx(fn->type)->type; t;) {
-                       if(!ll)
-                               break;
-                       if(variadic && t->isddd)
-                               break;
-                       as->list = list(as->list, tinlvar(t));
-                       t=t->down;
-                       ll=ll->next;
-               }
-               // match varargcount arguments with variadic parameters.
-               if(variadic && t && t->isddd) {
-                       vararg = tinlvar(t);
-                       for(i=0; i<varargcount && ll; i++) {
-                               m = argvar(varargtype, i);
-                               varargs = list(varargs, m);
-                               as->list = list(as->list, m);
-                               ll=ll->next;
-                       }
-                       if(i==varargcount)
-                               t=t->down;
-               }
-               if(ll || t)
-                       fatal("arg count mismatch: %#T  vs %,H\n",  getinargx(fn->type), n->list);
-       }
-
-       if (as->rlist) {
-               typecheck(&as, Etop);
-               ninit = list(ninit, as);
-       }
-
-       // turn the variadic args into a slice.
-       if(variadic) {
-               as = nod(OAS, vararg, N);
-               if(!varargcount) {
-                       as->right = nodnil();
-                       as->right->type = varargtype;
-               } else {
-                       vararrtype = typ(TARRAY);
-                       vararrtype->type = varargtype->type;
-                       vararrtype->bound = varargcount;
-
-                       as->right = nod(OCOMPLIT, N, typenod(varargtype));
-                       as->right->list = varargs;
-                       as->right = nod(OSLICE, as->right, nod(OKEY, N, N));
-               }
-               typecheck(&as, Etop);
-               ninit = list(ninit, as);
-       }
-
-       // zero the outparams
-       for(ll = inlretvars; ll; ll=ll->next) {
-               as = nod(OAS, ll->n, N);
-               typecheck(&as, Etop);
-               ninit = list(ninit, as);
-       }
-
-       inlretlabel = newlabel();
-       inlgen++;
-       body = inlsubstlist(fn->inl);
-
-       body = list(body, nod(OGOTO, inlretlabel, N));  // avoid 'not used' when function doesnt have return
-       body = list(body, nod(OLABEL, inlretlabel, N));
-
-       typechecklist(body, Etop);
-//dumplist("ninit post", ninit);
-
-       call = nod(OINLCALL, N, N);
-       call->ninit = ninit;
-       call->nbody = body;
-       call->rlist = inlretvars;
-       call->type = n->type;
-       call->typecheck = 1;
-
-       setlno(call, n->lineno);
-//dumplist("call body", body);
-
-       *np = call;
-
-       inlfn = saveinlfn;
-
-       // transitive inlining
-       // TODO do this pre-expansion on fn->inl directly.  requires
-       // either supporting exporting statemetns with complex ninits
-       // or saving inl and making inlinl
-       if(debug['l'] >= 5) {
-               body = fn->inl;
-               fn->inl = nil;  // prevent infinite recursion
-               inlnodelist(call->nbody);
-               for(ll=call->nbody; ll; ll=ll->next)
-                       if(ll->n->op == OINLCALL)
-                               inlconv2stmt(ll->n);
-               fn->inl = body;
-       }
-
-       if(debug['m']>2)
-               print("%L: After inlining %+N\n\n", n->lineno, *np);
-
-}
-
-// Every time we expand a function we generate a new set of tmpnames,
-// PAUTO's in the calling functions, and link them off of the
-// PPARAM's, PAUTOS and PPARAMOUTs of the called function. 
-static Node*
-inlvar(Node *var)
-{
-       Node *n;
-
-       if(debug['m']>3)
-               print("inlvar %+N\n", var);
-
-       n = newname(var->sym);
-       n->type = var->type;
-       n->class = PAUTO;
-       n->used = 1;
-       n->curfn = curfn;   // the calling function, not the called one
-       n->addrtaken = var->addrtaken;
-
-       // Esc pass wont run if we're inlining into a iface wrapper.
-       // Luckily, we can steal the results from the target func.
-       // If inlining a function defined in another package after
-       // escape analysis is done, treat all local vars as escaping.
-       // See issue 9537.
-       if(var->esc == EscHeap || (inl_nonlocal && var->op == ONAME))
-               addrescapes(n);
-
-       curfn->dcl = list(curfn->dcl, n);
-       return n;
-}
-
-// Synthesize a variable to store the inlined function's results in.
-static Node*
-retvar(Type *t, int i)
-{
-       Node *n;
-
-       snprint(namebuf, sizeof(namebuf), "~r%d", i);
-       n = newname(lookup(namebuf));
-       n->type = t->type;
-       n->class = PAUTO;
-       n->used = 1;
-       n->curfn = curfn;   // the calling function, not the called one
-       curfn->dcl = list(curfn->dcl, n);
-       return n;
-}
-
-// Synthesize a variable to store the inlined function's arguments
-// when they come from a multiple return call.
-static Node*
-argvar(Type *t, int i)
-{
-       Node *n;
-
-       snprint(namebuf, sizeof(namebuf), "~arg%d", i);
-       n = newname(lookup(namebuf));
-       n->type = t->type;
-       n->class = PAUTO;
-       n->used = 1;
-       n->curfn = curfn;   // the calling function, not the called one
-       curfn->dcl = list(curfn->dcl, n);
-       return n;
-}
-
-static Node*
-newlabel(void)
-{
-       Node *n;
-       static int label;
-       
-       label++;
-       snprint(namebuf, sizeof(namebuf), ".inlret%.6d", label);
-       n = newname(lookup(namebuf));
-       n->etype = 1;  // flag 'safe' for escape analysis (no backjumps)
-       return n;
-}
-
-// inlsubst and inlsubstlist recursively copy the body of the saved
-// pristine ->inl body of the function while substituting references
-// to input/output parameters with ones to the tmpnames, and
-// substituting returns with assignments to the output.
-static NodeList*
-inlsubstlist(NodeList *ll)
-{
-       NodeList *l;
-
-       l = nil;
-       for(; ll; ll=ll->next)
-               l = list(l, inlsubst(ll->n));
-       return l;
-}
-
-static Node*
-inlsubst(Node *n)
-{
-       char *p;
-       Node *m, *as;
-       NodeList *ll;
-
-       if(n == N)
-               return N;
-
-       switch(n->op) {
-       case ONAME:
-               if(n->inlvar) { // These will be set during inlnode
-                       if (debug['m']>2)
-                               print ("substituting name %+N  ->  %+N\n", n, n->inlvar);
-                       return n->inlvar;
-               }
-               if (debug['m']>2)
-                       print ("not substituting name %+N\n", n);
-               return n;
-
-       case OLITERAL:
-       case OTYPE:
-               return n;
-
-       case ORETURN:
-               // Since we don't handle bodies with closures, this return is guaranteed to belong to the current inlined function.
-
-//             dump("Return before substitution", n);
-               m = nod(OGOTO, inlretlabel, N);
-               m->ninit  = inlsubstlist(n->ninit);
-
-               if(inlretvars && n->list) {
-                       as = nod(OAS2, N, N);
-                       // shallow copy or OINLCALL->rlist will be the same list, and later walk and typecheck may clobber that.
-                       for(ll=inlretvars; ll; ll=ll->next)
-                               as->list = list(as->list, ll->n);
-                       as->rlist = inlsubstlist(n->list);
-                       typecheck(&as, Etop);
-                       m->ninit = list(m->ninit, as);
-               }
-
-               typechecklist(m->ninit, Etop);
-               typecheck(&m, Etop);
-//             dump("Return after substitution", m);
-               return m;
-       
-       case OGOTO:
-       case OLABEL:
-               m = nod(OXXX, N, N);
-               *m = *n;
-               m->ninit = nil;
-               p = smprint("%s·%d", n->left->sym->name, inlgen);      
-               m->left = newname(lookup(p));
-               free(p);
-               return m;       
-       }
-
-
-       m = nod(OXXX, N, N);
-       *m = *n;
-       m->ninit = nil;
-       
-       if(n->op == OCLOSURE)
-               fatal("cannot inline function containing closure: %+N", n);
-
-       m->left   = inlsubst(n->left);
-       m->right  = inlsubst(n->right);
-       m->list   = inlsubstlist(n->list);
-       m->rlist  = inlsubstlist(n->rlist);
-       m->ninit  = concat(m->ninit, inlsubstlist(n->ninit));
-       m->ntest  = inlsubst(n->ntest);
-       m->nincr  = inlsubst(n->nincr);
-       m->nbody  = inlsubstlist(n->nbody);
-       m->nelse  = inlsubstlist(n->nelse);
-
-       return m;
-}
-
-// Plaster over linenumbers
-static void
-setlnolist(NodeList *ll, int lno)
-{
-       for(;ll;ll=ll->next)
-               setlno(ll->n, lno);
-}
-
-static void
-setlno(Node *n, int lno)
-{
-       if(!n)
-               return;
-
-       // don't clobber names, unless they're freshly synthesized
-       if(n->op != ONAME || n->lineno == 0)
-               n->lineno = lno;
-       
-       setlno(n->left, lno);
-       setlno(n->right, lno);
-       setlnolist(n->list, lno);
-       setlnolist(n->rlist, lno);
-       setlnolist(n->ninit, lno);
-       setlno(n->ntest, lno);
-       setlno(n->nincr, lno);
-       setlnolist(n->nbody, lno);
-       setlnolist(n->nelse, lno);
-}
diff --git a/src/cmd/gc/lex.c b/src/cmd/gc/lex.c
deleted file mode 100644 (file)
index a4b832a..0000000
+++ /dev/null
@@ -1,2590 +0,0 @@
-// Copyright 2009 The Go Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style
-// license that can be found in the LICENSE file.
-
-#include       <u.h>
-#include       <libc.h>
-#include       "go.h"
-#include       "y.tab.h"
-#include       <ar.h>
-
-#ifndef PLAN9
-#include       <signal.h>
-#endif
-
-#undef getc
-#undef ungetc
-#define        getc    ccgetc
-#define        ungetc  ccungetc
-
-extern int yychar;
-int yyprev;
-int yylast;
-
-static int     imported_unsafe;
-
-static void    lexinit(void);
-static void    lexinit1(void);
-static void    lexfini(void);
-static void    yytinit(void);
-static int     getc(void);
-static void    ungetc(int);
-static int32   getr(void);
-static int     escchar(int, int*, vlong*);
-static void    addidir(char*);
-static int     getlinepragma(void);
-static char *goos, *goarch, *goroot;
-
-#define        BOM     0xFEFF
-
-// Debug arguments.
-// These can be specified with the -d flag, as in "-d nil"
-// to set the debug_checknil variable. In general the list passed
-// to -d can be comma-separated.
-static struct {
-       char *name;
-       int *val;
-} debugtab[] = {
-       {"nil", &debug_checknil},
-};
-
-// Our own isdigit, isspace, isalpha, isalnum that take care 
-// of EOF and other out of range arguments.
-static int
-yy_isdigit(int c)
-{
-       return c >= 0 && c <= 0xFF && isdigit(c);
-}
-
-static int
-yy_isspace(int c)
-{
-       return c == ' ' || c == '\t' || c == '\n' || c == '\r';
-}
-
-static int
-yy_isalpha(int c)
-{
-       return c >= 0 && c <= 0xFF && isalpha(c);
-}
-
-static int
-yy_isalnum(int c)
-{
-       return c >= 0 && c <= 0xFF && isalnum(c);
-}
-
-// Disallow use of isdigit etc.
-#undef isdigit
-#undef isspace
-#undef isalpha
-#undef isalnum
-#define isdigit use_yy_isdigit_instead_of_isdigit
-#define isspace use_yy_isspace_instead_of_isspace
-#define isalpha use_yy_isalpha_instead_of_isalpha
-#define isalnum use_yy_isalnum_instead_of_isalnum
-
-#define        DBG     if(!debug['x']){}else print
-/*c2go void DBG(char*, ...); */
-
-enum
-{
-       EOF             = -1,
-};
-
-void
-usage(void)
-{
-       print("usage: %cg [options] file.go...\n", thearch.thechar);
-       flagprint(1);
-       exits("usage");
-}
-
-void
-fault(int s)
-{
-       USED(s);
-
-       // If we've already complained about things
-       // in the program, don't bother complaining
-       // about the seg fault too; let the user clean up
-       // the code and try again.
-       if(nsavederrors + nerrors > 0)
-               errorexit();
-       fatal("fault");
-}
-
-#ifdef PLAN9
-void
-catcher(void *v, char *s)
-{
-       USED(v);
-
-       if(strncmp(s, "sys: trap: fault read", 21) == 0) {
-               if(nsavederrors + nerrors > 0)
-                       errorexit();
-               fatal("fault");
-       }
-       noted(NDFLT);
-}
-#endif
-
-void
-doversion(void)
-{
-       char *p, *sep;
-
-       p = expstring();
-       if(strcmp(p, "X:none") == 0)
-               p = "";
-       sep = "";
-       if(*p)
-               sep = " ";
-       print("%cg version %s%s%s\n", thearch.thechar, getgoversion(), sep, p);
-       exits(0);
-}
-
-int
-gcmain(int argc, char *argv[])
-{
-       int i;
-       NodeList *l;
-       char *p;
-       
-#ifdef SIGBUS  
-       signal(SIGBUS, fault);
-       signal(SIGSEGV, fault);
-#endif
-
-#ifdef PLAN9
-       notify(catcher);
-       // Tell the FPU to handle all exceptions.
-       setfcr(FPPDBL|FPRNR);
-#endif
-       // Allow GOARCH=thearch.thestring or GOARCH=thearch.thestringsuffix,
-       // but not other values.        
-       p = getgoarch();
-       if(strncmp(p, thearch.thestring, strlen(thearch.thestring)) != 0)
-               sysfatal("cannot use %cg with GOARCH=%s", thearch.thechar, p);
-       goarch = p;
-
-       thearch.linkarchinit();
-       ctxt = linknew(thearch.thelinkarch);
-       ctxt->diag = yyerror;
-       ctxt->bso = &bstdout;
-       Binit(&bstdout, 1, OWRITE);
-
-       localpkg = mkpkg(newstrlit(""));
-       localpkg->prefix = "\"\"";
-       
-       // pseudo-package, for scoping
-       builtinpkg = mkpkg(newstrlit("go.builtin"));
-       builtinpkg->prefix = "go.builtin"; // not go%2ebuiltin
-
-       // pseudo-package, accessed by import "unsafe"
-       unsafepkg = mkpkg(newstrlit("unsafe"));
-       unsafepkg->name = "unsafe";
-
-       // real package, referred to by generated runtime calls
-       runtimepkg = mkpkg(newstrlit("runtime"));
-       runtimepkg->name = "runtime";
-
-       // pseudo-packages used in symbol tables
-       gostringpkg = mkpkg(newstrlit("go.string"));
-       gostringpkg->name = "go.string";
-       gostringpkg->prefix = "go.string";      // not go%2estring
-
-       itabpkg = mkpkg(newstrlit("go.itab"));
-       itabpkg->name = "go.itab";
-       itabpkg->prefix = "go.itab";    // not go%2eitab
-
-       weaktypepkg = mkpkg(newstrlit("go.weak.type"));
-       weaktypepkg->name = "go.weak.type";
-       weaktypepkg->prefix = "go.weak.type";  // not go%2eweak%2etype
-       
-       typelinkpkg = mkpkg(newstrlit("go.typelink"));
-       typelinkpkg->name = "go.typelink";
-       typelinkpkg->prefix = "go.typelink"; // not go%2etypelink
-
-       trackpkg = mkpkg(newstrlit("go.track"));
-       trackpkg->name = "go.track";
-       trackpkg->prefix = "go.track";  // not go%2etrack
-
-       typepkg = mkpkg(newstrlit("type"));
-       typepkg->name = "type";
-
-       goroot = getgoroot();
-       goos = getgoos();
-
-       nacl = strcmp(goos, "nacl") == 0;
-       if(nacl)
-               flag_largemodel = 1;
-
-       fmtstrinit(&pragcgobuf);
-       quotefmtinstall();
-
-       outfile = nil;
-       flagcount("+", "compiling runtime", &compiling_runtime);
-       flagcount("%", "debug non-static initializers", &debug['%']);
-       flagcount("A", "for bootstrapping, allow 'any' type", &debug['A']);
-       flagcount("B", "disable bounds checking", &debug['B']);
-       flagstr("D", "path: set relative path for local imports", &localimport);
-       flagcount("E", "debug symbol export", &debug['E']);
-       flagfn1("I", "dir: add dir to import search path", addidir);
-       flagcount("K", "debug missing line numbers", &debug['K']);
-       flagcount("L", "use full (long) path in error messages", &debug['L']);
-       flagcount("M", "debug move generation", &debug['M']);
-       flagcount("N", "disable optimizations", &debug['N']);
-       flagcount("P", "debug peephole optimizer", &debug['P']);
-       flagcount("R", "debug register optimizer", &debug['R']);
-       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']);
-       flagcount("f", "debug stack frames", &debug['f']);
-       flagcount("g", "debug code generation", &debug['g']);
-       flagcount("h", "halt on error", &debug['h']);
-       flagcount("i", "debug line number stack", &debug['i']);
-       flagstr("installsuffix", "pkg directory suffix", &flag_installsuffix);
-       flagcount("j", "debug runtime-initialized variables", &debug['j']);
-       flagcount("l", "disable inlining", &debug['l']);
-       flagcount("live", "debug liveness analysis", &debuglive);
-       flagcount("m", "print optimization decisions", &debug['m']);
-       flagcount("nolocalimports", "reject local (relative) imports", &nolocalimports);
-       flagstr("o", "obj: set output file", &outfile);
-       flagstr("p", "path: set expected package import path", &myimportpath);
-       flagcount("pack", "write package file instead of object file", &writearchive);
-       flagcount("r", "debug generated wrappers", &debug['r']);
-       flagcount("race", "enable race detector", &flag_race);
-       flagcount("s", "warn about composite literals that can be simplified", &debug['s']);
-       flagstr("trimpath", "prefix: remove prefix from recorded source file paths", &ctxt->trimpath);
-       flagcount("u", "reject unsafe code", &safemode);
-       flagcount("v", "increase debug verbosity", &debug['v']);
-       flagcount("w", "debug type checking", &debug['w']);
-       use_writebarrier = 1;
-       flagcount("wb", "enable write barrier", &use_writebarrier);
-       flagcount("x", "debug lexer", &debug['x']);
-       flagcount("y", "debug declarations in canned imports (with -d)", &debug['y']);
-       if(thearch.thechar == '6')
-               flagcount("largemodel", "generate code that assumes a large memory model", &flag_largemodel);
-
-       flagparse(&argc, &argv, usage);
-       ctxt->debugasm = debug['S'];
-       ctxt->debugvlog = debug['v'];
-
-       if(argc < 1)
-               usage();
-
-       if(flag_race) {
-               racepkg = mkpkg(newstrlit("runtime/race"));
-               racepkg->name = "race";
-       }
-       
-       // parse -d argument
-       if(debugstr) {
-               char *f[100];
-               int i, j, nf;
-               
-               nf = getfields(debugstr, f, nelem(f), 1, ",");
-               for(i=0; i<nf; i++) {
-                       for(j=0; j<nelem(debugtab); j++) {
-                               if(strcmp(debugtab[j].name, f[i]) == 0) {
-                                       if(debugtab[j].val != nil)
-                                               *debugtab[j].val = 1;
-                                       break;
-                               }
-                       }
-                       if(j >= nelem(debugtab))
-                               sysfatal("unknown debug information -d '%s'\n", f[i]);
-               }
-       }
-
-       // enable inlining.  for now:
-       //      default: inlining on.  (debug['l'] == 1)
-       //      -l: inlining off  (debug['l'] == 0)
-       //      -ll, -lll: inlining on again, with extra debugging (debug['l'] > 1)
-       if(debug['l'] <= 1)
-               debug['l'] = 1 - debug['l'];
-
-       if(thearch.thechar == '8') {
-               p = getgo386();
-               if(strcmp(p, "387") == 0)
-                       use_sse = 0;
-               else if(strcmp(p, "sse2") == 0)
-                       use_sse = 1;
-               else
-                       sysfatal("unsupported setting GO386=%s", p);
-       }
-
-       fmtinstallgo();
-       thearch.betypeinit();
-       if(widthptr == 0)
-               fatal("betypeinit failed");
-
-       lexinit();
-       typeinit();
-       lexinit1();
-       yytinit();
-
-       blockgen = 1;
-       dclcontext = PEXTERN;
-       nerrors = 0;
-       lexlineno = 1;
-
-       for(i=0; i<argc; i++) {
-               infile = argv[i];
-               linehist(infile, 0, 0);
-
-               curio.infile = infile;
-               curio.bin = Bopen(infile, OREAD);
-               if(curio.bin == nil) {
-                       print("open %s: %r\n", infile);
-                       errorexit();
-               }
-               curio.peekc = 0;
-               curio.peekc1 = 0;
-               curio.nlsemi = 0;
-               curio.eofnl = 0;
-               curio.last = 0;
-
-               // Skip initial BOM if present.
-               if(Bgetrune(curio.bin) != BOM)
-                       Bungetrune(curio.bin);
-
-               block = 1;
-               iota = -1000000;
-               
-               imported_unsafe = 0;
-
-               yyparse();
-               if(nsyntaxerrors != 0)
-                       errorexit();
-
-               linehist(nil, 0, 0);
-               if(curio.bin != nil)
-                       Bterm(curio.bin);
-       }
-       testdclstack();
-       mkpackage(localpkg->name);      // final import not used checks
-       lexfini();
-
-       typecheckok = 1;
-       if(debug['f'])
-               frame(1);
-
-       // Process top-level declarations in phases.
-
-       // Phase 1: const, type, and names and types of funcs.
-       //   This will gather all the information about types
-       //   and methods but doesn't depend on any of it.
-       defercheckwidth();
-       for(l=xtop; l; l=l->next)
-               if(l->n->op != ODCL && l->n->op != OAS)
-                       typecheck(&l->n, Etop);
-
-       // Phase 2: Variable assignments.
-       //   To check interface assignments, depends on phase 1.
-       for(l=xtop; l; l=l->next)
-               if(l->n->op == ODCL || l->n->op == OAS)
-                       typecheck(&l->n, Etop);
-       resumecheckwidth();
-
-       // Phase 3: Type check function bodies.
-       for(l=xtop; l; l=l->next) {
-               if(l->n->op == ODCLFUNC || l->n->op == OCLOSURE) {
-                       curfn = l->n;
-                       decldepth = 1;
-                       saveerrors();
-                       typechecklist(l->n->nbody, Etop);
-                       checkreturn(l->n);
-                       if(nerrors != 0)
-                               l->n->nbody = nil;  // type errors; do not compile
-               }
-       }
-
-       // Phase 4: Decide how to capture closed variables.
-       // This needs to run before escape analysis,
-       // because variables captured by value do not escape.
-       for(l=xtop; l; l=l->next) {
-               if(l->n->op == ODCLFUNC && l->n->closure) {
-                       curfn = l->n;
-                       capturevars(l->n);
-               }
-       }
-
-       curfn = nil;
-       
-       if(nsavederrors+nerrors)
-               errorexit();
-
-       // Phase 5: Inlining
-       if(debug['l'] > 1) {
-               // Typecheck imported function bodies if debug['l'] > 1,
-               // otherwise lazily when used or re-exported.
-               for(l=importlist; l; l=l->next)
-                       if (l->n->inl) {
-                               saveerrors();
-                               typecheckinl(l->n);
-                       }
-               
-               if(nsavederrors+nerrors)
-                       errorexit();
-       }
-
-       if(debug['l']) {
-               // Find functions that can be inlined and clone them before walk expands them.
-               for(l=xtop; l; l=l->next)
-                       if(l->n->op == ODCLFUNC)
-                               caninl(l->n);
-               
-               // Expand inlineable calls in all functions
-               for(l=xtop; l; l=l->next)
-                       if(l->n->op == ODCLFUNC)
-                               inlcalls(l->n);
-       }
-
-       // Phase 6: Escape analysis.
-       // Required for moving heap allocations onto stack,
-       // which in turn is required by the closure implementation,
-       // which stores the addresses of stack variables into the closure.
-       // If the closure does not escape, it needs to be on the stack
-       // or else the stack copier will not update it.
-       escapes(xtop);
-       
-       // Escape analysis moved escaped values off stack.
-       // Move large values off stack too.
-       movelarge(xtop);
-
-       // Phase 7: Transform closure bodies to properly reference captured variables.
-       // This needs to happen before walk, because closures must be transformed
-       // before walk reaches a call of a closure.
-       for(l=xtop; l; l=l->next) {
-               if(l->n->op == ODCLFUNC && l->n->closure) {
-                       curfn = l->n;
-                       transformclosure(l->n);
-               }
-       }
-       curfn = N;
-
-       // Phase 8: Compile top level functions.
-       for(l=xtop; l; l=l->next)
-               if(l->n->op == ODCLFUNC)
-                       funccompile(l->n);
-
-       if(nsavederrors+nerrors == 0)
-               fninit(xtop);
-
-       // Phase 9: Check external declarations.
-       for(l=externdcl; l; l=l->next)
-               if(l->n->op == ONAME)
-                       typecheck(&l->n, Erv);
-
-       if(nerrors+nsavederrors)
-               errorexit();
-
-       dumpobj();
-       
-       if(asmhdr)
-               dumpasmhdr();
-
-       if(nerrors+nsavederrors)
-               errorexit();
-
-       flusherrors();
-       exits(0);
-       return 0;
-}
-
-void
-saveerrors(void)
-{
-       nsavederrors += nerrors;
-       nerrors = 0;
-}
-
-static int
-arsize(Biobuf *b, char *name)
-{
-       struct ar_hdr a;
-
-       if(Bread(b, a.name, sizeof(a.name)) != sizeof(a.name) ||
-          Bread(b, a.date, sizeof(a.date)) != sizeof(a.date) ||
-          Bread(b, a.uid, sizeof(a.uid)) != sizeof(a.uid) ||
-          Bread(b, a.gid, sizeof(a.gid)) != sizeof(a.gid) ||
-          Bread(b, a.mode, sizeof(a.mode)) != sizeof(a.mode) ||
-          Bread(b, a.size, sizeof(a.size)) != sizeof(a.size) ||
-          Bread(b, a.fmag, sizeof(a.fmag)) != sizeof(a.fmag))
-               return -1;
-
-       if(strncmp(a.name, name, strlen(name)) != 0)
-               return -1;
-
-       return atoi(a.size);
-}
-
-static int
-skiptopkgdef(Biobuf *b)
-{
-       char *p;
-       int sz;
-
-       /* archive header */
-       if((p = Brdline(b, '\n')) == nil)
-               return 0;
-       if(Blinelen(b) != 8)
-               return 0;
-       if(memcmp(p, "!<arch>\n", 8) != 0)
-               return 0;
-       /* symbol table may be first; skip it */
-       sz = arsize(b, "__.GOSYMDEF");
-       if(sz >= 0)
-               Bseek(b, sz, 1);
-       else
-               Bseek(b, 8, 0);
-       /* package export block is next */
-       sz = arsize(b, "__.PKGDEF");
-       if(sz <= 0)
-               return 0;
-       return 1;
-}
-
-static void
-addidir(char* dir)
-{
-       Idir** pp;
-
-       if(dir == nil)
-               return;
-
-       for(pp = &idirs; *pp != nil; pp = &(*pp)->link)
-               ;
-       *pp = mal(sizeof(Idir));
-       (*pp)->link = nil;
-       (*pp)->dir = dir;
-}
-
-// is this path a local name?  begins with ./ or ../ or /
-static int
-islocalname(Strlit *name)
-{
-       if(name->len >= 1 && name->s[0] == '/')
-               return 1;
-       if(ctxt->windows && name->len >= 3 &&
-          yy_isalpha(name->s[0]) && name->s[1] == ':' && name->s[2] == '/')
-               return 1;
-       if(name->len >= 2 && strncmp(name->s, "./", 2) == 0)
-               return 1;
-       if(name->len == 1 && strncmp(name->s, ".", 1) == 0)
-               return 1;
-       if(name->len >= 3 && strncmp(name->s, "../", 3) == 0)
-               return 1;
-       if(name->len == 2 && strncmp(name->s, "..", 2) == 0)
-               return 1;
-       return 0;
-}
-
-static int
-findpkg(Strlit *name)
-{
-       Idir *p;
-       char *q, *suffix, *suffixsep;
-
-       if(islocalname(name)) {
-               if(safemode || nolocalimports)
-                       return 0;
-               // try .a before .6.  important for building libraries:
-               // if there is an array.6 in the array.a library,
-               // want to find all of array.a, not just array.6.
-               snprint(namebuf, sizeof(namebuf), "%Z.a", name);
-               if(access(namebuf, 0) >= 0)
-                       return 1;
-               snprint(namebuf, sizeof(namebuf), "%Z.%c", name, thearch.thechar);
-               if(access(namebuf, 0) >= 0)
-                       return 1;
-               return 0;
-       }
-
-       // local imports should be canonicalized already.
-       // don't want to see "encoding/../encoding/base64"
-       // as different from "encoding/base64".
-       q = mal(name->len+1);
-       memmove(q, name->s, name->len);
-       q[name->len] = '\0';
-       cleanname(q);
-       if(strlen(q) != name->len || memcmp(q, name->s, name->len) != 0) {
-               yyerror("non-canonical import path %Z (should be %s)", name, q);
-               return 0;
-       }
-
-       for(p = idirs; p != nil; p = p->link) {
-               snprint(namebuf, sizeof(namebuf), "%s/%Z.a", p->dir, name);
-               if(access(namebuf, 0) >= 0)
-                       return 1;
-               snprint(namebuf, sizeof(namebuf), "%s/%Z.%c", p->dir, name, thearch.thechar);
-               if(access(namebuf, 0) >= 0)
-                       return 1;
-       }
-       if(goroot != nil) {
-               suffix = "";
-               suffixsep = "";
-               if(flag_installsuffix != nil) {
-                       suffixsep = "_";
-                       suffix = flag_installsuffix;
-               } else if(flag_race) {
-                       suffixsep = "_";
-                       suffix = "race";
-               }
-               snprint(namebuf, sizeof(namebuf), "%s/pkg/%s_%s%s%s/%Z.a", goroot, goos, goarch, suffixsep, suffix, name);
-               if(access(namebuf, 0) >= 0)
-                       return 1;
-               snprint(namebuf, sizeof(namebuf), "%s/pkg/%s_%s%s%s/%Z.%c", goroot, goos, goarch, suffixsep, suffix, name, thearch.thechar);
-               if(access(namebuf, 0) >= 0)
-                       return 1;
-       }
-       return 0;
-}
-
-static void
-fakeimport(void)
-{
-       importpkg = mkpkg(newstrlit("fake"));
-       cannedimports("fake.6", "$$\n");
-}
-
-void
-importfile(Val *f, int line)
-{
-       Biobuf *imp;
-       char *file, *p, *q, *tag;
-       int32 c;
-       int n;
-       Strlit *path;
-       char *cleanbuf, *prefix;
-
-       USED(line);
-
-       if(f->ctype != CTSTR) {
-               yyerror("import statement not a string");
-               fakeimport();
-               return;
-       }
-
-       if(f->u.sval->len == 0) {
-               yyerror("import path is empty");
-               fakeimport();
-               return;
-       }
-
-       if(isbadimport(f->u.sval)) {
-               fakeimport();
-               return;
-       }
-
-       // The package name main is no longer reserved,
-       // but we reserve the import path "main" to identify
-       // the main package, just as we reserve the import 
-       // path "math" to identify the standard math package.
-       if(strcmp(f->u.sval->s, "main") == 0) {
-               yyerror("cannot import \"main\"");
-               errorexit();
-       }
-
-       if(myimportpath != nil && strcmp(f->u.sval->s, myimportpath) == 0) {
-               yyerror("import \"%Z\" while compiling that package (import cycle)", f->u.sval);
-               errorexit();
-       }
-
-       if(strcmp(f->u.sval->s, "unsafe") == 0) {
-               if(safemode) {
-                       yyerror("cannot import package unsafe");
-                       errorexit();
-               }
-               importpkg = mkpkg(f->u.sval);
-               cannedimports("unsafe.6", unsafeimport);
-               imported_unsafe = 1;
-               return;
-       }
-       
-       path = f->u.sval;
-       if(islocalname(path)) {
-               if(path->s[0] == '/') {
-                       yyerror("import path cannot be absolute path");
-                       fakeimport();
-                       return;
-               }
-               prefix = ctxt->pathname;
-               if(localimport != nil)
-                       prefix = localimport;
-               cleanbuf = mal(strlen(prefix) + strlen(path->s) + 2);
-               strcpy(cleanbuf, prefix);
-               strcat(cleanbuf, "/");
-               strcat(cleanbuf, path->s);
-               cleanname(cleanbuf);
-               path = newstrlit(cleanbuf);
-               
-               if(isbadimport(path)) {
-                       fakeimport();
-                       return;
-               }
-       }
-
-       if(!findpkg(path)) {
-               yyerror("can't find import: \"%Z\"", f->u.sval);
-               errorexit();
-       }
-       importpkg = mkpkg(path);
-
-       // If we already saw that package, feed a dummy statement
-       // to the lexer to avoid parsing export data twice.
-       if(importpkg->imported) {
-               file = strdup(namebuf);
-               tag = "";
-               if(importpkg->safe) {
-                       tag = "safe";
-               }
-               p = smprint("package %s %s\n$$\n", importpkg->name, tag);
-               cannedimports(file, p);
-               return;
-       }
-       importpkg->imported = 1;
-
-       imp = Bopen(namebuf, OREAD);
-       if(imp == nil) {
-               yyerror("can't open import: \"%Z\": %r", f->u.sval);
-               errorexit();
-       }
-       file = strdup(namebuf);
-
-       n = strlen(namebuf);
-       if(n > 2 && namebuf[n-2] == '.' && namebuf[n-1] == 'a') {
-               if(!skiptopkgdef(imp)) {
-                       yyerror("import %s: not a package file", file);
-                       errorexit();
-               }
-       }
-       
-       // check object header
-       p = Brdstr(imp, '\n', 1);
-       if(strcmp(p, "empty archive") != 0) {
-               if(strncmp(p, "go object ", 10) != 0) {
-                       yyerror("import %s: not a go object file", file);
-                       errorexit();
-               }
-               q = smprint("%s %s %s %s", getgoos(), getgoarch(), getgoversion(), expstring());
-               if(strcmp(p+10, q) != 0) {
-                       yyerror("import %s: object is [%s] expected [%s]", file, p+10, q);
-                       errorexit();
-               }
-               free(q);
-       }
-
-       // assume files move (get installed)
-       // so don't record the full path.
-       linehist(file + n - path->len - 2, -1, 1);      // acts as #pragma lib
-
-       /*
-        * position the input right
-        * after $$ and return
-        */
-       pushedio = curio;
-       curio.bin = imp;
-       curio.peekc = 0;
-       curio.peekc1 = 0;
-       curio.infile = file;
-       curio.nlsemi = 0;
-       typecheckok = 1;
-
-       for(;;) {
-               c = getc();
-               if(c == EOF)
-                       break;
-               if(c != '$')
-                       continue;
-               c = getc();
-               if(c == EOF)
-                       break;
-               if(c != '$')
-                       continue;
-               return;
-       }
-       yyerror("no import in \"%Z\"", f->u.sval);
-       unimportfile();
-}
-
-void
-unimportfile(void)
-{
-       if(curio.bin != nil) {
-               Bterm(curio.bin);
-               curio.bin = nil;
-       } else
-               lexlineno--;    // re correct sys.6 line number
-
-       curio = pushedio;
-       pushedio.bin = nil;
-       incannedimport = 0;
-       typecheckok = 0;
-}
-
-void
-cannedimports(char *file, char *cp)
-{
-       lexlineno++;            // if sys.6 is included on line 1,
-
-       pushedio = curio;
-       curio.bin = nil;
-       curio.peekc = 0;
-       curio.peekc1 = 0;
-       curio.infile = file;
-       curio.cp = cp;
-       curio.nlsemi = 0;
-       curio.importsafe = 0;
-
-       typecheckok = 1;
-       incannedimport = 1;
-}
-
-static int
-isfrog(int c)
-{
-       // complain about possibly invisible control characters
-       if(c < ' ') {
-               return !yy_isspace(c);  // exclude good white space
-       }
-       if(0x7f <= c && c <= 0xa0)      // DEL, unicode block including unbreakable space.
-               return 1;
-       return 0;
-}
-
-typedef struct Loophack Loophack;
-struct Loophack {
-       int v;
-       Loophack *next;
-};
-
-static int32
-_yylex(void)
-{
-       int c, c1, clen, escflag, ncp;
-       vlong v;
-       char *cp, *ep;
-       Rune rune;
-       Sym *s;
-       static Loophack *lstk;
-       Loophack *h;
-
-       prevlineno = lineno;
-
-l0:
-       c = getc();
-       if(yy_isspace(c)) {
-               if(c == '\n' && curio.nlsemi) {
-                       ungetc(c);
-                       DBG("lex: implicit semi\n");
-                       return ';';
-               }
-               goto l0;
-       }
-
-       lineno = lexlineno;     /* start of token */
-
-       if(c >= Runeself) {
-               /* all multibyte runes are alpha */
-               cp = lexbuf;
-               ep = lexbuf+sizeof lexbuf;
-               goto talph;
-       }
-
-       if(yy_isalpha(c)) {
-               cp = lexbuf;
-               ep = lexbuf+sizeof lexbuf;
-               goto talph;
-       }
-
-       if(yy_isdigit(c))
-               goto tnum;
-
-       switch(c) {
-       case EOF:
-               lineno = prevlineno;
-               ungetc(EOF);
-               return -1;
-
-       case '_':
-               cp = lexbuf;
-               ep = lexbuf+sizeof lexbuf;
-               goto talph;
-
-       case '.':
-               c1 = getc();
-               if(yy_isdigit(c1)) {
-                       cp = lexbuf;
-                       ep = lexbuf+sizeof lexbuf;
-                       *cp++ = c;
-                       c = c1;
-                       goto casedot;
-               }
-               if(c1 == '.') {
-                       c1 = getc();
-                       if(c1 == '.') {
-                               c = LDDD;
-                               goto lx;
-                       }
-                       ungetc(c1);
-                       c1 = '.';
-               }
-               break;
-
-       case '"':
-               /* "..." */
-               strcpy(lexbuf, "\"<string>\"");
-               cp = mal(8);
-               clen = sizeof(int32);
-               ncp = 8;
-
-               for(;;) {
-                       if(clen+UTFmax > ncp) {
-                               cp = remal(cp, ncp, ncp);
-                               ncp += ncp;
-                       }
-                       if(escchar('"', &escflag, &v))
-                               break;
-                       if(v < Runeself || escflag) {
-                               cp[clen++] = v;
-                       } else {
-                               rune = v;
-                               c = runelen(rune);
-                               runetochar(cp+clen, &rune);
-                               clen += c;
-                       }
-               }
-               goto strlit;
-       
-       case '`':
-               /* `...` */
-               strcpy(lexbuf, "`<string>`");
-               cp = mal(8);
-               clen = sizeof(int32);
-               ncp = 8;
-
-               for(;;) {
-                       if(clen+UTFmax > ncp) {
-                               cp = remal(cp, ncp, ncp);
-                               ncp += ncp;
-                       }
-                       c = getr();
-                       if(c == '\r')
-                               continue;
-                       if(c == EOF) {
-                               yyerror("eof in string");
-                               break;
-                       }
-                       if(c == '`')
-                               break;
-                       rune = c;
-                       clen += runetochar(cp+clen, &rune);
-               }
-               goto strlit;
-
-       case '\'':
-               /* '.' */
-               if(escchar('\'', &escflag, &v)) {
-                       yyerror("empty character literal or unescaped ' in character literal");
-                       v = '\'';
-               }
-               if(!escchar('\'', &escflag, &v)) {
-                       yyerror("missing '");
-                       ungetc(v);
-               }
-               yylval.val.u.xval = mal(sizeof(*yylval.val.u.xval));
-               mpmovecfix(yylval.val.u.xval, v);
-               yylval.val.ctype = CTRUNE;
-               DBG("lex: codepoint literal\n");
-               strcpy(litbuf, "string literal");
-               return LLITERAL;
-
-       case '/':
-               c1 = getc();
-               if(c1 == '*') {
-                       int nl;
-                       
-                       nl = 0;
-                       for(;;) {
-                               c = getr();
-                               if(c == '\n')
-                                       nl = 1;
-                               while(c == '*') {
-                                       c = getr();
-                                       if(c == '/') {
-                                               if(nl)
-                                                       ungetc('\n');
-                                               goto l0;
-                                       }
-                                       if(c == '\n')
-                                               nl = 1;
-                               }
-                               if(c == EOF) {
-                                       yyerror("eof in comment");
-                                       errorexit();
-                               }
-                       }
-               }
-               if(c1 == '/') {
-                       c = getlinepragma();
-                       for(;;) {
-                               if(c == '\n' || c == EOF) {
-                                       ungetc(c);
-                                       goto l0;
-                               }
-                               c = getr();
-                       }
-               }
-               if(c1 == '=') {
-                       c = ODIV;
-                       goto asop;
-               }
-               break;
-
-       case ':':
-               c1 = getc();
-               if(c1 == '=') {
-                       c = LCOLAS;
-                       yylval.i = lexlineno;
-                       goto lx;
-               }
-               break;
-
-       case '*':
-               c1 = getc();
-               if(c1 == '=') {
-                       c = OMUL;
-                       goto asop;
-               }
-               break;
-
-       case '%':
-               c1 = getc();
-               if(c1 == '=') {
-                       c = OMOD;
-                       goto asop;
-               }
-               break;
-
-       case '+':
-               c1 = getc();
-               if(c1 == '+') {
-                       c = LINC;
-                       goto lx;
-               }
-               if(c1 == '=') {
-                       c = OADD;
-                       goto asop;
-               }
-               break;
-
-       case '-':
-               c1 = getc();
-               if(c1 == '-') {
-                       c = LDEC;
-                       goto lx;
-               }
-               if(c1 == '=') {
-                       c = OSUB;
-                       goto asop;
-               }
-               break;
-
-       case '>':
-               c1 = getc();
-               if(c1 == '>') {
-                       c = LRSH;
-                       c1 = getc();
-                       if(c1 == '=') {
-                               c = ORSH;
-                               goto asop;
-                       }
-                       break;
-               }
-               if(c1 == '=') {
-                       c = LGE;
-                       goto lx;
-               }
-               c = LGT;
-               break;
-
-       case '<':
-               c1 = getc();
-               if(c1 == '<') {
-                       c = LLSH;
-                       c1 = getc();
-                       if(c1 == '=') {
-                               c = OLSH;
-                               goto asop;
-                       }
-                       break;
-               }
-               if(c1 == '=') {
-                       c = LLE;
-                       goto lx;
-               }
-               if(c1 == '-') {
-                       c = LCOMM;
-                       goto lx;
-               }
-               c = LLT;
-               break;
-
-       case '=':
-               c1 = getc();
-               if(c1 == '=') {
-                       c = LEQ;
-                       goto lx;
-               }
-               break;
-
-       case '!':
-               c1 = getc();
-               if(c1 == '=') {
-                       c = LNE;
-                       goto lx;
-               }
-               break;
-
-       case '&':
-               c1 = getc();
-               if(c1 == '&') {
-                       c = LANDAND;
-                       goto lx;
-               }
-               if(c1 == '^') {
-                       c = LANDNOT;
-                       c1 = getc();
-                       if(c1 == '=') {
-                               c = OANDNOT;
-                               goto asop;
-                       }
-                       break;
-               }
-               if(c1 == '=') {
-                       c = OAND;
-                       goto asop;
-               }
-               break;
-
-       case '|':
-               c1 = getc();
-               if(c1 == '|') {
-                       c = LOROR;
-                       goto lx;
-               }
-               if(c1 == '=') {
-                       c = OOR;
-                       goto asop;
-               }
-               break;
-
-       case '^':
-               c1 = getc();
-               if(c1 == '=') {
-                       c = OXOR;
-                       goto asop;
-               }
-               break;
-
-       /*
-        * clumsy dance:
-        * to implement rule that disallows
-        *      if T{1}[0] { ... }
-        * but allows
-        *      if (T{1}[0]) { ... }
-        * the block bodies for if/for/switch/select
-        * begin with an LBODY token, not '{'.
-        *
-        * when we see the keyword, the next
-        * non-parenthesized '{' becomes an LBODY.
-        * loophack is normally 0.
-        * a keyword makes it go up to 1.
-        * parens push loophack onto a stack and go back to 0.
-        * a '{' with loophack == 1 becomes LBODY and disables loophack.
-        *
-        * i said it was clumsy.
-        */
-       case '(':
-       case '[':
-               if(loophack || lstk != nil) {
-                       h = malloc(sizeof *h);
-                       if(h == nil) {
-                               flusherrors();
-                               yyerror("out of memory");
-                               errorexit();
-                       }
-                       h->v = loophack;
-                       h->next = lstk;
-                       lstk = h;
-                       loophack = 0;
-               }
-               goto lx;
-       case ')':
-       case ']':
-               if(lstk != nil) {
-                       h = lstk;
-                       loophack = h->v;
-                       lstk = h->next;
-                       free(h);
-               }
-               goto lx;
-       case '{':
-               if(loophack == 1) {
-                       DBG("%L lex: LBODY\n", lexlineno);
-                       loophack = 0;
-                       return LBODY;
-               }
-               goto lx;
-
-       default:
-               goto lx;
-       }
-       ungetc(c1);
-
-lx:
-       if(c > 0xff)
-               DBG("%L lex: TOKEN %s\n", lexlineno, lexname(c));
-       else
-               DBG("%L lex: TOKEN '%c'\n", lexlineno, c);
-       if(isfrog(c)) {
-               yyerror("illegal character 0x%ux", c);
-               goto l0;
-       }
-       if(importpkg == nil && (c == '#' || c == '$' || c == '?' || c == '@' || c == '\\')) {
-               yyerror("%s: unexpected %c", "syntax error", c);
-               goto l0;
-       }
-       return c;
-
-asop:
-       yylval.i = c;   // rathole to hold which asop
-       DBG("lex: TOKEN ASOP %c\n", c);
-       return LASOP;
-
-talph:
-       /*
-        * cp is set to lexbuf and some
-        * prefix has been stored
-        */
-       for(;;) {
-               if(cp+10 >= ep) {
-                       yyerror("identifier too long");
-                       errorexit();
-               }
-               if(c >= Runeself) {
-                       ungetc(c);
-                       rune = getr();
-                       // 0xb7 Â· is used for internal names
-                       if(!isalpharune(rune) && !isdigitrune(rune) && (importpkg == nil || rune != 0xb7))
-                               yyerror("invalid identifier character U+%04x", rune);
-                       cp += runetochar(cp, &rune);
-               } else if(!yy_isalnum(c) && c != '_')
-                       break;
-               else
-                       *cp++ = c;
-               c = getc();
-       }
-       *cp = 0;
-       ungetc(c);
-
-       s = lookup(lexbuf);
-       switch(s->lexical) {
-       case LIGNORE:
-               goto l0;
-
-       case LFOR:
-       case LIF:
-       case LSWITCH:
-       case LSELECT:
-               loophack = 1;   // see comment about loophack above
-               break;
-       }
-
-       DBG("lex: %S %s\n", s, lexname(s->lexical));
-       yylval.sym = s;
-       return s->lexical;
-
-tnum:
-       cp = lexbuf;
-       ep = lexbuf+sizeof lexbuf;
-       if(c != '0') {
-               for(;;) {
-                       if(cp+10 >= ep) {
-                               yyerror("identifier too long");
-                               errorexit();
-                       }
-                       *cp++ = c;
-                       c = getc();
-                       if(yy_isdigit(c))
-                               continue;
-                       goto dc;
-               }
-       }
-       *cp++ = c;
-       c = getc();
-       if(c == 'x' || c == 'X') {
-               for(;;) {
-                       if(cp+10 >= ep) {
-                               yyerror("identifier too long");
-                               errorexit();
-                       }
-                       *cp++ = c;
-                       c = getc();
-                       if(yy_isdigit(c))
-                               continue;
-                       if(c >= 'a' && c <= 'f')
-                               continue;
-                       if(c >= 'A' && c <= 'F')
-                               continue;
-                       if(cp == lexbuf+2)
-                               yyerror("malformed hex constant");
-                       if(c == 'p')
-                               goto caseep;
-                       goto ncu;
-               }
-       }
-
-       if(c == 'p')    // 0p begins floating point zero
-               goto caseep;
-
-       c1 = 0;
-       for(;;) {
-               if(cp+10 >= ep) {
-                       yyerror("identifier too long");
-                       errorexit();
-               }
-               if(!yy_isdigit(c))
-                       break;
-               if(c < '0' || c > '7')
-                       c1 = 1;         // not octal
-               *cp++ = c;
-               c = getc();
-       }
-       if(c == '.')
-               goto casedot;
-       if(c == 'e' || c == 'E')
-               goto caseep;
-       if(c == 'i')
-               goto casei;
-       if(c1)
-               yyerror("malformed octal constant");
-       goto ncu;
-
-dc:
-       if(c == '.')
-               goto casedot;
-       if(c == 'e' || c == 'E' || c == 'p' || c == 'P')
-               goto caseep;
-       if(c == 'i')
-               goto casei;
-
-ncu:
-       *cp = 0;
-       ungetc(c);
-
-       yylval.val.u.xval = mal(sizeof(*yylval.val.u.xval));
-       mpatofix(yylval.val.u.xval, lexbuf);
-       if(yylval.val.u.xval->ovf) {
-               yyerror("overflow in constant");
-               mpmovecfix(yylval.val.u.xval, 0);
-       }
-       yylval.val.ctype = CTINT;
-       DBG("lex: integer literal\n");
-       strcpy(litbuf, "literal ");
-       strcat(litbuf, lexbuf);
-       return LLITERAL;
-
-casedot:
-       for(;;) {
-               if(cp+10 >= ep) {
-                       yyerror("identifier too long");
-                       errorexit();
-               }
-               *cp++ = c;
-               c = getc();
-               if(!yy_isdigit(c))
-                       break;
-       }
-       if(c == 'i')
-               goto casei;
-       if(c != 'e' && c != 'E')
-               goto caseout;
-
-caseep:
-       *cp++ = c;
-       c = getc();
-       if(c == '+' || c == '-') {
-               *cp++ = c;
-               c = getc();
-       }
-       if(!yy_isdigit(c))
-               yyerror("malformed fp constant exponent");
-       while(yy_isdigit(c)) {
-               if(cp+10 >= ep) {
-                       yyerror("identifier too long");
-                       errorexit();
-               }
-               *cp++ = c;
-               c = getc();
-       }
-       if(c == 'i')
-               goto casei;
-       goto caseout;
-
-casei:
-       // imaginary constant
-       *cp = 0;
-       yylval.val.u.cval = mal(sizeof(*yylval.val.u.cval));
-       mpmovecflt(&yylval.val.u.cval->real, 0.0);
-       mpatoflt(&yylval.val.u.cval->imag, lexbuf);
-       if(yylval.val.u.cval->imag.val.ovf) {
-               yyerror("overflow in imaginary constant");
-               mpmovecflt(&yylval.val.u.cval->real, 0.0);
-       }
-       yylval.val.ctype = CTCPLX;
-       DBG("lex: imaginary literal\n");
-       strcpy(litbuf, "literal ");
-       strcat(litbuf, lexbuf);
-       return LLITERAL;
-
-caseout:
-       *cp = 0;
-       ungetc(c);
-
-       yylval.val.u.fval = mal(sizeof(*yylval.val.u.fval));
-       mpatoflt(yylval.val.u.fval, lexbuf);
-       if(yylval.val.u.fval->val.ovf) {
-               yyerror("overflow in float constant");
-               mpmovecflt(yylval.val.u.fval, 0.0);
-       }
-       yylval.val.ctype = CTFLT;
-       DBG("lex: floating literal\n");
-       strcpy(litbuf, "literal ");
-       strcat(litbuf, lexbuf);
-       return LLITERAL;
-
-strlit:
-       *(int32*)cp = clen-sizeof(int32);       // length
-       do {
-               cp[clen++] = 0;
-       } while(clen & MAXALIGN);
-       yylval.val.u.sval = (Strlit*)cp;
-       yylval.val.ctype = CTSTR;
-       DBG("lex: string literal\n");
-       strcpy(litbuf, "string literal");
-       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
- * as a discontinuity in sequential line numbers.
- * the next line of input comes from parse.y:15
- */
-static int
-getlinepragma(void)
-{
-       int i, c, n;
-       char *cp, *ep, *linep;
-       Hist *h;
-
-       c = getr();
-       if(c == 'g')
-               goto go;
-       if(c != 'l')    
-               goto out;
-       for(i=1; i<5; i++) {
-               c = getr();
-               if(c != "line "[i])
-                       goto out;
-       }
-
-       cp = lexbuf;
-       ep = lexbuf+sizeof(lexbuf)-5;
-       linep = nil;
-       for(;;) {
-               c = getr();
-               if(c == EOF)
-                       goto out;
-               if(c == '\n')
-                       break;
-               if(c == ' ')
-                       continue;
-               if(c == ':')
-                       linep = cp;
-               if(cp < ep)
-                       *cp++ = c;
-       }
-       *cp = 0;
-
-       if(linep == nil || linep >= ep)
-               goto out;
-       *linep++ = '\0';
-       n = 0;
-       for(cp=linep; *cp; cp++) {
-               if(*cp < '0' || *cp > '9')
-                       goto out;
-               n = n*10 + *cp - '0';
-               if(n > 1e8) {
-                       yyerror("line number out of range");
-                       errorexit();
-               }
-       }
-       if(n <= 0)
-               goto out;
-
-       // try to avoid allocating file name over and over
-       for(h=ctxt->hist; h!=nil; h=h->link) {
-               if(h->name != nil && strcmp(h->name, lexbuf) == 0) {
-                       linehist(h->name, n, 0);
-                       goto out;
-               }
-       }
-       linehist(strdup(lexbuf), n, 0);
-       goto out;
-
-go:
-       cp = lexbuf;
-       ep = lexbuf+sizeof(lexbuf)-5;
-       *cp++ = 'g'; // already read
-       for(;;) {
-               c = getr();
-               if(c == EOF || c >= Runeself)
-                       goto out;
-               if(c == '\n')
-                       break;
-               if(cp < ep)
-                       *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;
-               goto out;
-       }
-       if(strcmp(lexbuf, "go:noescape") == 0) {
-               noescape = 1;
-               goto out;
-       }
-       if(strcmp(lexbuf, "go:nosplit") == 0) {
-               nosplit = 1;
-               goto out;
-       }
-       if(strcmp(lexbuf, "go:nowritebarrier") == 0) {
-               if(!compiling_runtime)
-                       yyerror("//go:nowritebarrier only allowed in runtime");
-               nowritebarrier = 1;
-               goto out;
-       }
-       
-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)
-{
-       int lx;
-       
-       lx = _yylex();
-       
-       if(curio.nlsemi && lx == EOF) {
-               // Treat EOF as "end of line" for the purposes
-               // of inserting a semicolon.
-               lx = ';';
-       }
-
-       switch(lx) {
-       case LNAME:
-       case LLITERAL:
-       case LBREAK:
-       case LCONTINUE:
-       case LFALL:
-       case LRETURN:
-       case LINC:
-       case LDEC:
-       case ')':
-       case '}':
-       case ']':
-               curio.nlsemi = 1;
-               break;
-       default:
-               curio.nlsemi = 0;
-               break;
-       }
-
-       // Track last two tokens returned by yylex.
-       yyprev = yylast;
-       yylast = lx;
-       return lx;
-}
-
-static int
-getc(void)
-{
-       int c, c1, c2;
-
-       c = curio.peekc;
-       if(c != 0) {
-               curio.peekc = curio.peekc1;
-               curio.peekc1 = 0;
-               goto check;
-       }
-       
-       if(curio.bin == nil) {
-               c = *curio.cp & 0xff;
-               if(c != 0)
-                       curio.cp++;
-       } else {
-       loop:
-               c = BGETC(curio.bin);
-               if(c == 0xef) {
-                       c1 = BGETC(curio.bin);
-                       c2 = BGETC(curio.bin);
-                       if(c1 == 0xbb && c2 == 0xbf) {
-                               yyerrorl(lexlineno, "Unicode (UTF-8) BOM in middle of file");
-                               goto loop;
-                       }
-                       Bungetc(curio.bin);
-                       Bungetc(curio.bin);
-               }
-       }
-
-check:
-       switch(c) {
-       case 0:
-               if(curio.bin != nil) {
-                       yyerror("illegal NUL byte");
-                       break;
-               }
-       case EOF:
-               // insert \n at EOF
-               if(curio.eofnl || curio.last == '\n')
-                       return EOF;
-               curio.eofnl = 1;
-               c = '\n';
-       case '\n':
-               if(pushedio.bin == nil)
-                       lexlineno++;
-               break;
-       }
-       curio.last = c;
-       return c;
-}
-
-static void
-ungetc(int c)
-{
-       curio.peekc1 = curio.peekc;
-       curio.peekc = c;
-       if(c == '\n' && pushedio.bin == nil)
-               lexlineno--;
-}
-
-static int32
-getr(void)
-{
-       int c, i;
-       char str[UTFmax+1];
-       Rune rune;
-
-       c = getc();
-       if(c < Runeself)
-               return c;
-       i = 0;
-       str[i++] = c;
-
-loop:
-       c = getc();
-       str[i++] = c;
-       if(!fullrune(str, i))
-               goto loop;
-       c = chartorune(&rune, str);
-       if(rune == Runeerror && c == 1) {
-               lineno = lexlineno;
-               yyerror("illegal UTF-8 sequence");
-               flusherrors();
-               print("\t");
-               for(c=0; c<i; c++)
-                       print("%s%.2x", c > 0 ? " " : "", *(uchar*)(str+c));
-               print("\n");
-       }
-       return rune;
-}
-
-static int
-escchar(int e, int *escflg, vlong *val)
-{
-       int i, u, c;
-       vlong l;
-
-       *escflg = 0;
-
-       c = getr();
-       switch(c) {
-       case EOF:
-               yyerror("eof in string");
-               return 1;
-       case '\n':
-               yyerror("newline in string");
-               return 1;
-       case '\\':
-               break;
-       default:
-               if(c == e)
-                       return 1;
-               *val = c;
-               return 0;
-       }
-
-       u = 0;
-       c = getr();
-       switch(c) {
-       case 'x':
-               *escflg = 1;    // it's a byte
-               i = 2;
-               goto hex;
-
-       case 'u':
-               i = 4;
-               u = 1;
-               goto hex;
-
-       case 'U':
-               i = 8;
-               u = 1;
-               goto hex;
-
-       case '0':
-       case '1':
-       case '2':
-       case '3':
-       case '4':
-       case '5':
-       case '6':
-       case '7':
-               *escflg = 1;    // it's a byte
-               goto oct;
-
-       case 'a': c = '\a'; break;
-       case 'b': c = '\b'; break;
-       case 'f': c = '\f'; break;
-       case 'n': c = '\n'; break;
-       case 'r': c = '\r'; break;
-       case 't': c = '\t'; break;
-       case 'v': c = '\v'; break;
-       case '\\': c = '\\'; break;
-
-       default:
-               if(c != e)
-                       yyerror("unknown escape sequence: %c", c);
-       }
-       *val = c;
-       return 0;
-
-hex:
-       l = 0;
-       for(; i>0; i--) {
-               c = getc();
-               if(c >= '0' && c <= '9') {
-                       l = l*16 + c-'0';
-                       continue;
-               }
-               if(c >= 'a' && c <= 'f') {
-                       l = l*16 + c-'a' + 10;
-                       continue;
-               }
-               if(c >= 'A' && c <= 'F') {
-                       l = l*16 + c-'A' + 10;
-                       continue;
-               }
-               yyerror("non-hex character in escape sequence: %c", c);
-               ungetc(c);
-               break;
-       }
-       if(u && (l > Runemax || (0xd800 <= l && l < 0xe000))) {
-               yyerror("invalid Unicode code point in escape sequence: %#llx", l);
-               l = Runeerror;
-       }
-       *val = l;
-       return 0;
-
-oct:
-       l = c - '0';
-       for(i=2; i>0; i--) {
-               c = getc();
-               if(c >= '0' && c <= '7') {
-                       l = l*8 + c-'0';
-                       continue;
-               }
-               yyerror("non-octal character in escape sequence: %c", c);
-               ungetc(c);
-       }
-       if(l > 255)
-               yyerror("octal escape value > 255: %d", l);
-
-       *val = l;
-       return 0;
-}
-
-static struct
-{
-       char*   name;
-       int     lexical;
-       int     etype;
-       int     op;
-} syms[] =
-{
-/*     name            lexical         etype           op
- */
-/* basic types */
-       {"int8",                LNAME,          TINT8,          OXXX},
-       {"int16",       LNAME,          TINT16,         OXXX},
-       {"int32",       LNAME,          TINT32,         OXXX},
-       {"int64",       LNAME,          TINT64,         OXXX},
-
-       {"uint8",       LNAME,          TUINT8,         OXXX},
-       {"uint16",      LNAME,          TUINT16,        OXXX},
-       {"uint32",      LNAME,          TUINT32,        OXXX},
-       {"uint64",      LNAME,          TUINT64,        OXXX},
-
-       {"float32",     LNAME,          TFLOAT32,       OXXX},
-       {"float64",     LNAME,          TFLOAT64,       OXXX},
-
-       {"complex64",   LNAME,          TCOMPLEX64,     OXXX},
-       {"complex128",  LNAME,          TCOMPLEX128,    OXXX},
-
-       {"bool",                LNAME,          TBOOL,          OXXX},
-       {"string",      LNAME,          TSTRING,        OXXX},
-
-       {"any",         LNAME,          TANY,           OXXX},
-
-       {"break",       LBREAK,         Txxx,           OXXX},
-       {"case",                LCASE,          Txxx,           OXXX},
-       {"chan",                LCHAN,          Txxx,           OXXX},
-       {"const",       LCONST,         Txxx,           OXXX},
-       {"continue",    LCONTINUE,      Txxx,           OXXX},
-       {"default",     LDEFAULT,       Txxx,           OXXX},
-       {"else",                LELSE,          Txxx,           OXXX},
-       {"defer",       LDEFER,         Txxx,           OXXX},
-       {"fallthrough", LFALL,          Txxx,           OXXX},
-       {"for",         LFOR,           Txxx,           OXXX},
-       {"func",                LFUNC,          Txxx,           OXXX},
-       {"go",          LGO,            Txxx,           OXXX},
-       {"goto",                LGOTO,          Txxx,           OXXX},
-       {"if",          LIF,            Txxx,           OXXX},
-       {"import",      LIMPORT,        Txxx,           OXXX},
-       {"interface",   LINTERFACE,     Txxx,           OXXX},
-       {"map",         LMAP,           Txxx,           OXXX},
-       {"package",     LPACKAGE,       Txxx,           OXXX},
-       {"range",       LRANGE,         Txxx,           OXXX},
-       {"return",      LRETURN,        Txxx,           OXXX},
-       {"select",      LSELECT,        Txxx,           OXXX},
-       {"struct",      LSTRUCT,        Txxx,           OXXX},
-       {"switch",      LSWITCH,        Txxx,           OXXX},
-       {"type",                LTYPE,          Txxx,           OXXX},
-       {"var",         LVAR,           Txxx,           OXXX},
-
-       {"append",      LNAME,          Txxx,           OAPPEND},
-       {"cap",         LNAME,          Txxx,           OCAP},
-       {"close",       LNAME,          Txxx,           OCLOSE},
-       {"complex",     LNAME,          Txxx,           OCOMPLEX},
-       {"copy",                LNAME,          Txxx,           OCOPY},
-       {"delete",      LNAME,          Txxx,           ODELETE},
-       {"imag",                LNAME,          Txxx,           OIMAG},
-       {"len",         LNAME,          Txxx,           OLEN},
-       {"make",                LNAME,          Txxx,           OMAKE},
-       {"new",         LNAME,          Txxx,           ONEW},
-       {"panic",       LNAME,          Txxx,           OPANIC},
-       {"print",       LNAME,          Txxx,           OPRINT},
-       {"println",     LNAME,          Txxx,           OPRINTN},
-       {"real",                LNAME,          Txxx,           OREAL},
-       {"recover",     LNAME,          Txxx,           ORECOVER},
-
-       {"notwithstanding",             LIGNORE,        Txxx,           OXXX},
-       {"thetruthofthematter",         LIGNORE,        Txxx,           OXXX},
-       {"despiteallobjections",                LIGNORE,        Txxx,           OXXX},
-       {"whereas",                     LIGNORE,        Txxx,           OXXX},
-       {"insofaras",                   LIGNORE,        Txxx,           OXXX},
-};
-
-static void
-lexinit(void)
-{
-       int i, lex;
-       Sym *s, *s1;
-       Type *t;
-       int etype;
-       Val v;
-
-       /*
-        * initialize basic types array
-        * initialize known symbols
-        */
-       for(i=0; i<nelem(syms); i++) {
-               lex = syms[i].lexical;
-               s = lookup(syms[i].name);
-               s->lexical = lex;
-
-               etype = syms[i].etype;
-               if(etype != Txxx) {
-                       if(etype < 0 || etype >= nelem(types))
-                               fatal("lexinit: %s bad etype", s->name);
-                       s1 = pkglookup(syms[i].name, builtinpkg);
-                       t = types[etype];
-                       if(t == T) {
-                               t = typ(etype);
-                               t->sym = s1;
-
-                               if(etype != TANY && etype != TSTRING)
-                                       dowidth(t);
-                               types[etype] = t;
-                       }
-                       s1->lexical = LNAME;
-                       s1->def = typenod(t);
-                       continue;
-               }
-
-               etype = syms[i].op;
-               if(etype != OXXX) {
-                       s1 = pkglookup(syms[i].name, builtinpkg);
-                       s1->lexical = LNAME;
-                       s1->def = nod(ONAME, N, N);
-                       s1->def->sym = s1;
-                       s1->def->etype = etype;
-                       s1->def->builtin = 1;
-               }
-       }
-
-       // logically, the type of a string literal.
-       // types[TSTRING] is the named type string
-       // (the type of x in var x string or var x = "hello").
-       // this is the ideal form
-       // (the type of x in const x = "hello").
-       idealstring = typ(TSTRING);
-       idealbool = typ(TBOOL);
-
-       s = pkglookup("true", builtinpkg);
-       s->def = nodbool(1);
-       s->def->sym = lookup("true");
-       s->def->type = idealbool;
-
-       s = pkglookup("false", builtinpkg);
-       s->def = nodbool(0);
-       s->def->sym = lookup("false");
-       s->def->type = idealbool;
-
-       s = lookup("_");
-       s->block = -100;
-       s->def = nod(ONAME, N, N);
-       s->def->sym = s;
-       types[TBLANK] = typ(TBLANK);
-       s->def->type = types[TBLANK];
-       nblank = s->def;
-
-       s = pkglookup("_", builtinpkg);
-       s->block = -100;
-       s->def = nod(ONAME, N, N);
-       s->def->sym = s;
-       types[TBLANK] = typ(TBLANK);
-       s->def->type = types[TBLANK];
-
-       types[TNIL] = typ(TNIL);
-       s = pkglookup("nil", builtinpkg);
-       v.ctype = CTNIL;
-       s->def = nodlit(v);
-       s->def->sym = s;
-}
-
-static void
-lexinit1(void)
-{
-       Sym *s, *s1;
-       Type *t, *f, *rcvr, *in, *out;
-
-       // t = interface { Error() string }
-       rcvr = typ(TSTRUCT);
-       rcvr->type = typ(TFIELD);
-       rcvr->type->type = ptrto(typ(TSTRUCT));
-       rcvr->funarg = 1;
-       in = typ(TSTRUCT);
-       in->funarg = 1;
-       out = typ(TSTRUCT);
-       out->type = typ(TFIELD);
-       out->type->type = types[TSTRING];
-       out->funarg = 1;
-       f = typ(TFUNC);
-       *getthis(f) = rcvr;
-       *getoutarg(f) = out;
-       *getinarg(f) = in;
-       f->thistuple = 1;
-       f->intuple = 0;
-       f->outnamed = 0;
-       f->outtuple = 1;
-       t = typ(TINTER);
-       t->type = typ(TFIELD);
-       t->type->sym = lookup("Error");
-       t->type->type = f;
-
-       // error type
-       s = lookup("error");
-       s->lexical = LNAME;
-       s1 = pkglookup("error", builtinpkg);
-       errortype = t;
-       errortype->sym = s1;
-       s1->lexical = LNAME;
-       s1->def = typenod(errortype);
-
-       // byte alias
-       s = lookup("byte");
-       s->lexical = LNAME;
-       s1 = pkglookup("byte", builtinpkg);
-       bytetype = typ(TUINT8);
-       bytetype->sym = s1;
-       s1->lexical = LNAME;
-       s1->def = typenod(bytetype);
-
-       // rune alias
-       s = lookup("rune");
-       s->lexical = LNAME;
-       s1 = pkglookup("rune", builtinpkg);
-       runetype = typ(TINT32);
-       runetype->sym = s1;
-       s1->lexical = LNAME;
-       s1->def = typenod(runetype);
-}
-
-static void
-lexfini(void)
-{
-       Sym *s;
-       int lex, etype, i;
-       Val v;
-
-       for(i=0; i<nelem(syms); i++) {
-               lex = syms[i].lexical;
-               if(lex != LNAME)
-                       continue;
-               s = lookup(syms[i].name);
-               s->lexical = lex;
-
-               etype = syms[i].etype;
-               if(etype != Txxx && (etype != TANY || debug['A']) && s->def == N) {
-                       s->def = typenod(types[etype]);
-                       s->origpkg = builtinpkg;
-               }
-
-               etype = syms[i].op;
-               if(etype != OXXX && s->def == N) {
-                       s->def = nod(ONAME, N, N);
-                       s->def->sym = s;
-                       s->def->etype = etype;
-                       s->def->builtin = 1;
-                       s->origpkg = builtinpkg;
-               }
-       }
-
-       // backend-specific builtin types (e.g. int).
-       for(i=0; thearch.typedefs[i].name; i++) {
-               s = lookup(thearch.typedefs[i].name);
-               if(s->def == N) {
-                       s->def = typenod(types[thearch.typedefs[i].etype]);
-                       s->origpkg = builtinpkg;
-               }
-       }
-
-       // there's only so much table-driven we can handle.
-       // these are special cases.
-       s = lookup("byte");
-       if(s->def == N) {
-               s->def = typenod(bytetype);
-               s->origpkg = builtinpkg;
-       }
-
-       s = lookup("error");
-       if(s->def == N) {
-               s->def = typenod(errortype);
-               s->origpkg = builtinpkg;
-       }
-
-       s = lookup("rune");
-       if(s->def == N) {
-               s->def = typenod(runetype);
-               s->origpkg = builtinpkg;
-       }
-
-       s = lookup("nil");
-       if(s->def == N) {
-               v.ctype = CTNIL;
-               s->def = nodlit(v);
-               s->def->sym = s;
-               s->origpkg = builtinpkg;
-       }
-
-       s = lookup("iota");
-       if(s->def == N) {
-               s->def = nod(OIOTA, N, N);
-               s->def->sym = s;
-               s->origpkg = builtinpkg;
-       }
-
-       s = lookup("true");
-       if(s->def == N) {
-               s->def = nodbool(1);
-               s->def->sym = s;
-               s->origpkg = builtinpkg;
-       }
-
-       s = lookup("false");
-       if(s->def == N) {
-               s->def = nodbool(0);
-               s->def->sym = s;
-               s->origpkg = builtinpkg;
-       }
-
-       nodfp = nod(ONAME, N, N);
-       nodfp->type = types[TINT32];
-       nodfp->xoffset = 0;
-       nodfp->class = PPARAM;
-       nodfp->sym = lookup(".fp");
-}
-
-struct
-{
-       int     lex;
-       char*   name;
-} lexn[] =
-{
-       {LANDAND,       "ANDAND"},
-       {LANDNOT,       "ANDNOT"},
-       {LASOP,         "ASOP"},
-       {LBREAK,                "BREAK"},
-       {LCASE,         "CASE"},
-       {LCHAN,         "CHAN"},
-       {LCOLAS,                "COLAS"},
-       {LCOMM,         "<-"},
-       {LCONST,                "CONST"},
-       {LCONTINUE,     "CONTINUE"},
-       {LDDD,          "..."},
-       {LDEC,          "DEC"},
-       {LDEFAULT,      "DEFAULT"},
-       {LDEFER,                "DEFER"},
-       {LELSE,         "ELSE"},
-       {LEQ,           "EQ"},
-       {LFALL,         "FALL"},
-       {LFOR,          "FOR"},
-       {LFUNC,         "FUNC"},
-       {LGE,           "GE"},
-       {LGO,           "GO"},
-       {LGOTO,         "GOTO"},
-       {LGT,           "GT"},
-       {LIF,           "IF"},
-       {LIMPORT,       "IMPORT"},
-       {LINC,          "INC"},
-       {LINTERFACE,    "INTERFACE"},
-       {LLE,           "LE"},
-       {LLITERAL,      "LITERAL"},
-       {LLSH,          "LSH"},
-       {LLT,           "LT"},
-       {LMAP,          "MAP"},
-       {LNAME,         "NAME"},
-       {LNE,           "NE"},
-       {LOROR,         "OROR"},
-       {LPACKAGE,      "PACKAGE"},
-       {LRANGE,                "RANGE"},
-       {LRETURN,       "RETURN"},
-       {LRSH,          "RSH"},
-       {LSELECT,       "SELECT"},
-       {LSTRUCT,       "STRUCT"},
-       {LSWITCH,       "SWITCH"},
-       {LTYPE,         "TYPE"},
-       {LVAR,          "VAR"},
-};
-
-char*
-lexname(int lex)
-{
-       int i;
-       static char buf[100];
-
-       for(i=0; i<nelem(lexn); i++)
-               if(lexn[i].lex == lex)
-                       return lexn[i].name;
-       snprint(buf, sizeof(buf), "LEX-%d", lex);
-       return buf;
-}
-
-struct
-{
-       char *have;
-       char *want;
-} yytfix[] =
-{
-       {"$end",        "EOF"},
-       {"LLITERAL",    "literal"},
-       {"LASOP",       "op="},
-       {"LBREAK",      "break"},
-       {"LCASE",       "case"},
-       {"LCHAN",       "chan"},
-       {"LCOLAS",      ":="},
-       {"LCONST",      "const"},
-       {"LCONTINUE",   "continue"},
-       {"LDDD",        "..."},
-       {"LDEFAULT",    "default"},
-       {"LDEFER",      "defer"},
-       {"LELSE",       "else"},
-       {"LFALL",       "fallthrough"},
-       {"LFOR",        "for"},
-       {"LFUNC",       "func"},
-       {"LGO", "go"},
-       {"LGOTO",       "goto"},
-       {"LIF", "if"},
-       {"LIMPORT",     "import"},
-       {"LINTERFACE",  "interface"},
-       {"LMAP",        "map"},
-       {"LNAME",       "name"},
-       {"LPACKAGE",    "package"},
-       {"LRANGE",      "range"},
-       {"LRETURN",     "return"},
-       {"LSELECT",     "select"},
-       {"LSTRUCT",     "struct"},
-       {"LSWITCH",     "switch"},
-       {"LTYPE",       "type"},
-       {"LVAR",        "var"},
-       {"LANDAND",     "&&"},
-       {"LANDNOT",     "&^"},
-       {"LBODY",       "{"},
-       {"LCOMM",       "<-"},
-       {"LDEC",        "--"},
-       {"LINC",        "++"},
-       {"LEQ", "=="},
-       {"LGE", ">="},
-       {"LGT", ">"},
-       {"LLE", "<="},
-       {"LLT", "<"},
-       {"LLSH",        "<<"},
-       {"LRSH",        ">>"},
-       {"LOROR",       "||"},
-       {"LNE", "!="},
-       
-       // spell out to avoid confusion with punctuation in error messages
-       {"';'", "semicolon or newline"},
-       {"','", "comma"},
-};
-
-static void
-yytinit(void)
-{
-       int i, j;
-       extern char *yytname[];
-       char *s, *t;
-
-       for(i=0; yytname[i] != nil; i++) {
-               s = yytname[i];
-               
-               if(strcmp(s, "LLITERAL") == 0) {
-                       strcpy(litbuf, "literal");
-                       yytname[i] = litbuf;
-                       goto loop;
-               }
-               
-               // apply yytfix if possible
-               for(j=0; j<nelem(yytfix); j++) {
-                       if(strcmp(s, yytfix[j].have) == 0) {
-                               yytname[i] = yytfix[j].want;
-                               goto loop;
-                       }
-               }
-
-               // turn 'x' into x.
-               if(s[0] == '\'') {
-                       t = strdup(s+1);
-                       t[strlen(t)-1] = '\0';
-                       yytname[i] = t;
-               }
-       loop:;
-       }               
-}
-
-static void
-pkgnotused(int lineno, Strlit *path, char *name)
-{
-       char *elem;
-       
-       // If the package was imported with a name other than the final
-       // import path element, show it explicitly in the error message.
-       // Note that this handles both renamed imports and imports of
-       // packages containing unconventional package declarations.
-       // Note that this uses / always, even on Windows, because Go import
-       // paths always use forward slashes.
-       elem = strrchr(path->s, '/');
-       if(elem != nil)
-               elem++;
-       else
-               elem = path->s;
-       if(name == nil || strcmp(elem, name) == 0)
-               yyerrorl(lineno, "imported and not used: \"%Z\"", path);
-       else
-               yyerrorl(lineno, "imported and not used: \"%Z\" as %s", path, name);
-}
-
-void
-mkpackage(char* pkgname)
-{
-       Sym *s;
-       int32 h;
-       char *p, *q;
-
-       if(localpkg->name == nil) {
-               if(strcmp(pkgname, "_") == 0)
-                       yyerror("invalid package name _");
-               localpkg->name = pkgname;
-       } else {
-               if(strcmp(pkgname, localpkg->name) != 0)
-                       yyerror("package %s; expected %s", pkgname, localpkg->name);
-               for(h=0; h<NHASH; h++) {
-                       for(s = hash[h]; s != S; s = s->link) {
-                               if(s->def == N || s->pkg != localpkg)
-                                       continue;
-                               if(s->def->op == OPACK) {
-                                       // throw away top-level package name leftover
-                                       // from previous file.
-                                       // leave s->block set to cause redeclaration
-                                       // errors if a conflicting top-level name is
-                                       // introduced by a different file.
-                                       if(!s->def->used && !nsyntaxerrors)
-                                               pkgnotused(s->def->lineno, s->def->pkg->path, s->name);
-                                       s->def = N;
-                                       continue;
-                               }
-                               if(s->def->sym != s) {
-                                       // throw away top-level name left over
-                                       // from previous import . "x"
-                                       if(s->def->pack != N && !s->def->pack->used && !nsyntaxerrors) {
-                                               pkgnotused(s->def->pack->lineno, s->def->pack->pkg->path, nil);
-                                               s->def->pack->used = 1;
-                                       }
-                                       s->def = N;
-                                       continue;
-                               }
-                       }
-               }
-       }
-
-       if(outfile == nil) {
-               p = strrchr(infile, '/');
-               if(ctxt->windows) {
-                       q = strrchr(infile, '\\');
-                       if(q > p)
-                               p = q;
-               }
-               if(p == nil)
-                       p = infile;
-               else
-                       p = p+1;
-               snprint(namebuf, sizeof(namebuf), "%s", p);
-               p = strrchr(namebuf, '.');
-               if(p != nil)
-                       *p = 0;
-               outfile = smprint("%s.%c", namebuf, thearch.thechar);
-       }
-}
diff --git a/src/cmd/gc/md5.c b/src/cmd/gc/md5.c
deleted file mode 100644 (file)
index 46cb6b7..0000000
+++ /dev/null
@@ -1,302 +0,0 @@
-// Copyright 2009 The Go Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style
-// license that can be found in the LICENSE file.
-
-// 64-bit MD5 (does full MD5 but returns 64 bits only).
-// Translation of ../../crypto/md5/md5*.go.
-
-#include <u.h>
-#include <libc.h>
-#include "go.h"
-#include "md5.h"
-
-static int md5block(MD5 *dig, uchar *p, int nn);
-
-enum {
-       _Chunk = 64
-};
-
-#define _Init0 0x67452301
-#define _Init1 0xEFCDAB89
-#define _Init2 0x98BADCFE
-#define _Init3 0x10325476
-/*c2go
-enum {
-       _Init0 = 0x67452301,
-       _Init1 = 0xEFCDAB89,
-       _Init2 = 0x98BADCFE,
-       _Init3 = 0x10325476
-};
-*/
-       
-void
-md5reset(MD5 *d)
-{
-       d->s[0] = _Init0;
-       d->s[1] = _Init1;
-       d->s[2] = _Init2;
-       d->s[3] = _Init3;
-       d->nx = 0;
-       d->len = 0;
-}
-
-void
-md5write(MD5 *d, uchar *p, int nn)
-{
-       int i, n;
-
-       d->len += nn;
-       if(d->nx > 0) {
-               n = nn;
-               if(n > _Chunk - d->nx)
-                       n = _Chunk - d->nx;
-               for(i=0; i<n; i++)
-                       d->x[d->nx+i] = p[i];
-               d->nx += n;
-               if(d->nx == _Chunk) {
-                       md5block(d, d->x, _Chunk);
-                       d->nx = 0;
-               }
-               p += n;
-               nn -= n;
-       }
-       n = md5block(d, p, nn);
-       p += n;
-       nn -= n;
-       if(nn > 0) {
-               for(i=0; i<nn; i++)
-                       d->x[i] = p[i];
-               d->nx = nn;
-       }
-}
-
-uint64
-md5sum(MD5 *d, uint64 *hi)
-{
-       uchar tmp[64];
-       int i;
-       uint64 len;
-
-       // Padding.  Add a 1 bit and 0 bits until 56 bytes mod 64.
-       len = d->len;
-       memset(tmp, 0, sizeof tmp);
-       tmp[0] = 0x80;
-       if(len%64 < 56)
-               md5write(d, tmp, 56-len%64);
-       else
-               md5write(d, tmp, 64+56-len%64);
-
-       // Length in bits.
-       len <<= 3;
-       for(i=0; i<8; i++)
-               tmp[i] = len>>(8*i);
-       md5write(d, tmp, 8);
-
-       if(d->nx != 0)
-               fatal("md5sum");
-
-       if(hi != nil)
-               *hi = d->s[2] | ((uint64)d->s[3]<<32);
-       return d->s[0] | ((uint64)d->s[1]<<32);
-}
-
-
-// MD5 block step.
-// In its own file so that a faster assembly or C version
-// can be substituted easily.
-
-// table[i] = int((1<<32) * abs(sin(i+1 radians))).
-static uint32 table[64] = {
-       // round 1
-       0xd76aa478,
-       0xe8c7b756,
-       0x242070db,
-       0xc1bdceee,
-       0xf57c0faf,
-       0x4787c62a,
-       0xa8304613,
-       0xfd469501,
-       0x698098d8,
-       0x8b44f7af,
-       0xffff5bb1,
-       0x895cd7be,
-       0x6b901122,
-       0xfd987193,
-       0xa679438e,
-       0x49b40821,
-
-       // round 2
-       0xf61e2562,
-       0xc040b340,
-       0x265e5a51,
-       0xe9b6c7aa,
-       0xd62f105d,
-       0x2441453,
-       0xd8a1e681,
-       0xe7d3fbc8,
-       0x21e1cde6,
-       0xc33707d6,
-       0xf4d50d87,
-       0x455a14ed,
-       0xa9e3e905,
-       0xfcefa3f8,
-       0x676f02d9,
-       0x8d2a4c8a,
-
-       // round3
-       0xfffa3942,
-       0x8771f681,
-       0x6d9d6122,
-       0xfde5380c,
-       0xa4beea44,
-       0x4bdecfa9,
-       0xf6bb4b60,
-       0xbebfbc70,
-       0x289b7ec6,
-       0xeaa127fa,
-       0xd4ef3085,
-       0x4881d05,
-       0xd9d4d039,
-       0xe6db99e5,
-       0x1fa27cf8,
-       0xc4ac5665,
-
-       // round 4
-       0xf4292244,
-       0x432aff97,
-       0xab9423a7,
-       0xfc93a039,
-       0x655b59c3,
-       0x8f0ccc92,
-       0xffeff47d,
-       0x85845dd1,
-       0x6fa87e4f,
-       0xfe2ce6e0,
-       0xa3014314,
-       0x4e0811a1,
-       0xf7537e82,
-       0xbd3af235,
-       0x2ad7d2bb,
-       0xeb86d391,
-};
-
-static uint32 shift1[] = { 7, 12, 17, 22 };
-static uint32 shift2[] = { 5, 9, 14, 20 };
-static uint32 shift3[] = { 4, 11, 16, 23 };
-static uint32 shift4[] = { 6, 10, 15, 21 };
-
-static int
-md5block(MD5 *dig, uchar *p, int nn)
-{
-       uint32 a, b, c, d, aa, bb, cc, dd;
-       int i, j, n;
-       uint32 X[16];
-
-       a = dig->s[0];
-       b = dig->s[1];
-       c = dig->s[2];
-       d = dig->s[3];
-       n = 0;
-
-       while(nn >= _Chunk) {
-               aa = a;
-               bb = b;
-               cc = c;
-               dd = d;
-
-               for(i=0; i<16; i++) {
-                       j = i*4;
-                       X[i] = p[j] | (p[j+1]<<8) | (p[j+2]<<16) | ((uint32)p[j+3]<<24);
-               }
-
-               // Round 1.
-               for(i=0; i<16; i++) {
-                       uint32 x, t, s, f;
-                       x = i;
-                       t = i;
-                       s = shift1[i%4];
-                       f = ((c ^ d) & b) ^ d;
-                       a += f + X[x] + table[t];
-                       a = a<<s | a>>(32-s);
-                       a += b;
-
-                       t = d;
-                       d = c;
-                       c = b;
-                       b = a;
-                       a = t;
-               }
-
-               // Round 2.
-               for(i=0; i<16; i++) {
-                       uint32 x, t, s, g;
-
-                       x = (1+5*i)%16;
-                       t = 16+i;
-                       s = shift2[i%4];
-                       g = ((b ^ c) & d) ^ c;
-                       a += g + X[x] + table[t];
-                       a = a<<s | a>>(32-s);
-                       a += b;
-
-                       t = d;
-                       d = c;
-                       c = b;
-                       b = a;
-                       a = t;
-               }
-
-               // Round 3.
-               for(i=0; i<16; i++) {
-                       uint32 x, t, s, h;
-
-                       x = (5+3*i)%16;
-                       t = 32+i;
-                       s = shift3[i%4];
-                       h = b ^ c ^ d;
-                       a += h + X[x] + table[t];
-                       a = a<<s | a>>(32-s);
-                       a += b;
-
-                       t = d;
-                       d = c;
-                       c = b;
-                       b = a;
-                       a = t;
-               }
-
-               // Round 4.
-               for(i=0; i<16; i++) {
-                       uint32 x, s, t, ii;
-
-                       x = (7*i)%16;
-                       s = shift4[i%4];
-                       t = 48+i;
-                       ii = c ^ (b | ~d);
-                       a += ii + X[x] + table[t];
-                       a = a<<s | a>>(32-s);
-                       a += b;
-
-                       t = d;
-                       d = c;
-                       c = b;
-                       b = a;
-                       a = t;
-               }
-
-               a += aa;
-               b += bb;
-               c += cc;
-               d += dd;
-
-               p += _Chunk;
-               n += _Chunk;
-               nn -= _Chunk;
-       }
-
-       dig->s[0] = a;
-       dig->s[1] = b;
-       dig->s[2] = c;
-       dig->s[3] = d;
-       return n;
-}
diff --git a/src/cmd/gc/md5.h b/src/cmd/gc/md5.h
deleted file mode 100644 (file)
index 5a60106..0000000
+++ /dev/null
@@ -1,16 +0,0 @@
-// Copyright 2009 The Go Authors.  All rights reserved.
-// Use of this source code is governed by a BSD-style
-// license that can be found in the LICENSE file.
-
-typedef struct MD5 MD5;
-struct MD5
-{
-       uint32 s[4];
-       uchar x[64];
-       int nx;
-       uint64 len;
-};
-
-void md5reset(MD5*);
-void md5write(MD5*, uchar*, int);
-uint64 md5sum(MD5*, uint64*);
diff --git a/src/cmd/gc/mkbuiltin b/src/cmd/gc/mkbuiltin
deleted file mode 100755 (executable)
index 696aa82..0000000
+++ /dev/null
@@ -1,36 +0,0 @@
-#!/bin/sh
-# Copyright 2009 The Go Authors. All rights reserved.
-# Use of this source code is governed by a BSD-style
-# license that can be found in the LICENSE file.
-
-# Generate builtin.c from $* (runtime.go and unsafe.go).
-# Run this after changing runtime.go and unsafe.go
-# or after changing the export metadata format in the compiler.
-# Either way, you need to have a working compiler binary first.
-
-set -e
-
-eval $(go tool dist env)
-if [ -z "$GOCHAR" ]; then
-       echo 'missing $GOCHAR - go tool dist failed?' 1>&2
-       exit 1
-fi
-
-GC=${GOCHAR}g
-gcc -o mkbuiltin1 mkbuiltin1.c
-rm -f _builtin.c
-echo "// AUTO-GENERATED by mkbuiltin; DO NOT EDIT" >>_builtin.c
-echo "#include <u.h>" >>_builtin.c
-echo "#include <libc.h>" >>_builtin.c
-echo '#include "go.h"' >>_builtin.c
-
-for i in runtime unsafe
-do
-       go tool $GC -A $i.go
-       O=$GOCHAR ./mkbuiltin1 $i >>_builtin.c
-done
-
-# If _builtin.c has changed vs builtin.c,
-# check in the new change.
-cmp -s _builtin.c builtin.c || cp _builtin.c builtin.c
-rm _builtin.c mkbuiltin1 unsafe.$GOCHAR runtime.$GOCHAR
diff --git a/src/cmd/gc/mkbuiltin1.c b/src/cmd/gc/mkbuiltin1.c
deleted file mode 100644 (file)
index 69027fd..0000000
+++ /dev/null
@@ -1,102 +0,0 @@
-// Copyright 2009 The Go Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style
-// license that can be found in the LICENSE file.
-
-// +build ignore
-
-// Compile .go file, import data from .6 file, and generate C string version.
-
-#include <stdio.h>
-#include <stdlib.h>
-#include <unistd.h>
-#include <string.h>
-#include <errno.h>
-#include <stdarg.h>
-
-void esc(char*);
-void fatal(char*, ...);
-
-int
-main(int argc, char **argv)
-{
-       char *name;
-       FILE *fin;
-       char buf[1024], initfunc[1024], *p, *q;
-
-       if(argc != 2) {
-               fprintf(stderr, "usage: mkbuiltin1 sys\n");
-               fatal("in file $1.6 s/PACKAGE/$1/");
-       }
-
-       name = argv[1];
-       snprintf(initfunc, sizeof(initfunc), "init_%s_function", name);
-
-       snprintf(buf, sizeof(buf), "%s.%s", name, getenv("O"));
-       if((fin = fopen(buf, "r")) == NULL) {
-               fatal("open %s: %s", buf, strerror(errno));
-       }
-
-       // look for $$ that introduces imports
-       while(fgets(buf, sizeof buf, fin) != NULL)
-               if(strstr(buf, "$$"))
-                       goto begin;
-       fatal("did not find beginning of imports");
-
-begin:
-       printf("char *%simport =\n", name);
-
-       // process imports, stopping at $$ that closes them
-       while(fgets(buf, sizeof buf, fin) != NULL) {
-               buf[strlen(buf)-1] = 0; // chop \n
-               if(strstr(buf, "$$"))
-                       goto end;
-
-               // chop leading white space
-               for(p=buf; *p==' ' || *p == '\t'; p++)
-                       ;
-
-               // cut out decl of init_$1_function - it doesn't exist
-               if(strstr(buf, initfunc))
-                       continue;
-
-               // sys.go claims to be in package PACKAGE to avoid
-               // conflicts during "6g sys.go".  rename PACKAGE to $2.
-               printf("\t\"");
-               while((q = strstr(p, "PACKAGE")) != NULL) {
-                       *q = 0;
-                       esc(p); // up to the substitution
-                       printf("%s", name);     // the sub name
-                       p = q+7;                // continue with rest
-               }
-
-               esc(p);
-               printf("\\n\"\n");
-       }
-       fatal("did not find end of imports");
-
-end:
-       printf("\t\"$$\\n\";\n");
-       return 0;
-}
-
-void
-esc(char *p)
-{
-       for(; *p; p++) {
-               if(*p == '\\' || *p == '\"')
-                       printf("\\");
-               putchar(*p);
-       }
-}
-
-void
-fatal(char *msg, ...)
-{
-       va_list arg;
-       
-       va_start(arg, msg);
-       fprintf(stderr, "fatal: ");
-       vfprintf(stderr, msg, arg);
-       fprintf(stderr, "\n");
-       exit(2);
-}
diff --git a/src/cmd/gc/mkopnames b/src/cmd/gc/mkopnames
deleted file mode 100755 (executable)
index d3f27e8..0000000
+++ /dev/null
@@ -1,24 +0,0 @@
-#!/bin/sh
-# Copyright 2009 The Go Authors. All rights reserved.
-# Use of this source code is governed by a BSD-style
-# license that can be found in the LICENSE file.
-
-# Disable colored grep if user has it set to --color=always.
-# (Arguably user error.)
-export GREP_OPTIONS=""
-
-echo '// auto generated by mkopnames'
-echo 'static char*'
-echo 'opnames[] = '
-echo '{'
-sed -n '/OXXX/,/OEND/p' go.h |
-       cpp |
-       sed 's!//.*!!; /^#/d'  |
-       tr ' ' '\012' |
-       tr -d ' \011,' |
-       grep . |
-       sort |
-       grep -v '^OEND$' |
-       sed 's/O//; s/.*/       [O&] =  "&",/'
-echo '};'
-
diff --git a/src/cmd/gc/mparith1.c b/src/cmd/gc/mparith1.c
deleted file mode 100644 (file)
index 6a0eb2d..0000000
+++ /dev/null
@@ -1,655 +0,0 @@
-// Copyright 2009 The Go Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style
-// license that can be found in the LICENSE file.
-
-#include       <u.h>
-#include       <libc.h>
-#include       "go.h"
-
-/// uses arithmetic
-
-int
-mpcmpfixflt(Mpint *a, Mpflt *b)
-{
-       char buf[500];
-       Mpflt c;
-
-       snprint(buf, sizeof(buf), "%B", a);
-       mpatoflt(&c, buf);
-       return mpcmpfltflt(&c, b);
-}
-
-int
-mpcmpfltfix(Mpflt *a, Mpint *b)
-{
-       char buf[500];
-       Mpflt c;
-
-       snprint(buf, sizeof(buf), "%B", b);
-       mpatoflt(&c, buf);
-       return mpcmpfltflt(a, &c);
-}
-
-int
-mpcmpfixfix(Mpint *a, Mpint *b)
-{
-       Mpint c;
-
-       mpmovefixfix(&c, a);
-       mpsubfixfix(&c, b);
-       return mptestfix(&c);
-}
-
-int
-mpcmpfixc(Mpint *b, vlong c)
-{
-       Mpint c1;
-
-       mpmovecfix(&c1, c);
-       return mpcmpfixfix(b, &c1);
-}
-
-int
-mpcmpfltflt(Mpflt *a, Mpflt *b)
-{
-       Mpflt c;
-
-       mpmovefltflt(&c, a);
-       mpsubfltflt(&c, b);
-       return mptestflt(&c);
-}
-
-int
-mpcmpfltc(Mpflt *b, double c)
-{
-       Mpflt a;
-
-       mpmovecflt(&a, c);
-       return mpcmpfltflt(b, &a);
-}
-
-void
-mpsubfixfix(Mpint *a, Mpint *b)
-{
-       mpnegfix(a);
-       mpaddfixfix(a, b, 0);
-       mpnegfix(a);
-}
-
-void
-mpsubfltflt(Mpflt *a, Mpflt *b)
-{
-       mpnegflt(a);
-       mpaddfltflt(a, b);
-       mpnegflt(a);
-}
-
-void
-mpaddcfix(Mpint *a, vlong c)
-{
-       Mpint b;
-
-       mpmovecfix(&b, c);
-       mpaddfixfix(a, &b, 0);
-}
-
-void
-mpaddcflt(Mpflt *a, double c)
-{
-       Mpflt b;
-
-       mpmovecflt(&b, c);
-       mpaddfltflt(a, &b);
-}
-
-void
-mpmulcfix(Mpint *a, vlong c)
-{
-       Mpint b;
-
-       mpmovecfix(&b, c);
-       mpmulfixfix(a, &b);
-}
-
-void
-mpmulcflt(Mpflt *a, double c)
-{
-       Mpflt b;
-
-       mpmovecflt(&b, c);
-       mpmulfltflt(a, &b);
-}
-
-void
-mpdivfixfix(Mpint *a, Mpint *b)
-{
-       Mpint q, r;
-
-       mpdivmodfixfix(&q, &r, a, b);
-       mpmovefixfix(a, &q);
-}
-
-void
-mpmodfixfix(Mpint *a, Mpint *b)
-{
-       Mpint q, r;
-
-       mpdivmodfixfix(&q, &r, a, b);
-       mpmovefixfix(a, &r);
-}
-
-void
-mpcomfix(Mpint *a)
-{
-       Mpint b;
-
-       mpmovecfix(&b, 1);
-       mpnegfix(a);
-       mpsubfixfix(a, &b);
-}
-
-void
-mpmovefixflt(Mpflt *a, Mpint *b)
-{
-       a->val = *b;
-       a->exp = 0;
-       mpnorm(a);
-}
-
-// convert (truncate) b to a.
-// return -1 (but still convert) if b was non-integer.
-static int
-mpexactfltfix(Mpint *a, Mpflt *b)
-{
-       Mpflt f;
-
-       *a = b->val;
-       mpshiftfix(a, b->exp);
-       if(b->exp < 0) {
-               f.val = *a;
-               f.exp = 0;
-               mpnorm(&f);
-               if(mpcmpfltflt(b, &f) != 0)
-                       return -1;
-       }
-       return 0;
-}
-
-int
-mpmovefltfix(Mpint *a, Mpflt *b)
-{
-       Mpflt f;
-       int i;
-
-       if(mpexactfltfix(a, b) == 0)
-               return 0;
-
-       // try rounding down a little
-       f = *b;
-       f.val.a[0] = 0;
-       if(mpexactfltfix(a, &f) == 0)
-               return 0;
-
-       // try rounding up a little
-       for(i=1; i<Mpprec; i++) {
-               f.val.a[i]++;
-               if(f.val.a[i] != Mpbase)
-                       break;
-               f.val.a[i] = 0;
-       }
-       mpnorm(&f);
-       if(mpexactfltfix(a, &f) == 0)
-               return 0;
-
-       return -1;
-}
-
-void
-mpmovefixfix(Mpint *a, Mpint *b)
-{
-       *a = *b;
-}
-
-void
-mpmovefltflt(Mpflt *a, Mpflt *b)
-{
-       *a = *b;
-}
-
-static double  tab[] = { 1e0, 1e1, 1e2, 1e3, 1e4, 1e5, 1e6, 1e7 };
-static void
-mppow10flt(Mpflt *a, int p)
-{
-       if(p < 0)
-               abort();
-       if(p < nelem(tab)) {
-               mpmovecflt(a, tab[p]);
-               return;
-       }
-       mppow10flt(a, p>>1);
-       mpmulfltflt(a, a);
-       if(p & 1)
-               mpmulcflt(a, 10);
-}
-
-static void
-mphextofix(Mpint *a, char *s, int n)
-{
-       char c;
-       long d;
-       int bit, hexdigitp, end;
-
-       while(*s == '0') {
-               s++;
-               n--;
-       }
-
-       // overflow
-       if(4*n > Mpscale*Mpprec) {
-               a->ovf = 1;
-               return;
-       }
-
-       end = n-1;
-       for(hexdigitp=end; hexdigitp>=0; hexdigitp--) {
-               c = s[hexdigitp];
-               if(c >= '0' && c <= '9')
-                       d = c-'0';
-               else if(c >= 'A' && c <= 'F')
-                       d = c-'A'+10;
-               else
-                       d = c-'a'+10;
-
-               bit = 4*(end - hexdigitp);
-               while(d > 0) {
-                       if(d & 1)
-                               a->a[bit/Mpscale] |= (long)1 << (bit%Mpscale);
-                       bit++;
-                       d = d >> 1;
-               }
-       }
-}
-
-//
-// floating point input
-// required syntax is [+-]d*[.]d*[e[+-]d*] or [+-]0xH*[e[+-]d*]
-//
-void
-mpatoflt(Mpflt *a, char *as)
-{
-       Mpflt b;
-       int dp, c, f, ef, ex, eb, base;
-       char *s, *start;
-
-       while(*as == ' ' || *as == '\t')
-               as++;
-
-       /* determine base */
-       s = as;
-       base = -1;
-       while(base == -1) {
-               switch(*s++) {
-               case '-':
-               case '+':
-                       break;
-
-               case '0':
-                       if(*s == 'x')
-                               base = 16;
-                       else
-                               base = 10;
-                       break;
-
-               default:
-                       base = 10;
-               }
-       }
-
-       s = as;
-       dp = 0;         /* digits after decimal point */
-       f = 0;          /* sign */
-       ex = 0;         /* exponent */
-       eb = 0;         /* binary point */
-
-       mpmovecflt(a, 0.0);
-       if(base == 16) {
-               start = nil;
-               for(;;) {
-                       c = *s;
-                       if(c == '-') {
-                               f = 1;
-                               s++;
-                       }
-                       else if(c == '+') {
-                               s++;
-                       }
-                       else if(c == '0' && s[1] == 'x') {
-                               s += 2;
-                               start = s;
-                       }
-                       else if((c >= '0' && c <= '9') || (c >= 'a' && c <= 'f') || (c >= 'A' && c <= 'F')) {
-                               s++;
-                       }
-                       else {
-                               break;
-                       }
-               }
-               if(start == nil) {
-                       yyerror("malformed hex constant: %s", as);
-                       goto bad;
-               }
-
-               mphextofix(&a->val, start, s-start);
-               if(a->val.ovf) {
-                       yyerror("constant too large: %s", as);
-                       goto bad;
-               }
-               a->exp = 0;
-               mpnorm(a);
-       }
-       for(;;) {
-               c = *s++;
-               switch(c) {
-               default:
-                       yyerror("malformed constant: %s (at %c)", as, c);
-                       goto bad;
-
-               case '-':
-                       f = 1;
-
-               case ' ':
-               case '\t':
-               case '+':
-                       continue;
-
-               case '.':
-                       if(base == 16) {
-                               yyerror("decimal point in hex constant: %s", as);
-                               goto bad;
-                       }
-                       dp = 1;
-                       continue;
-
-               case '1':
-               case '2':
-               case '3':
-               case '4':
-               case '5':
-               case '6':
-               case '7':
-               case '8':
-               case '9':
-               case '0':
-                       mpmulcflt(a, 10);
-                       mpaddcflt(a, c-'0');
-                       if(dp)
-                               dp++;
-                       continue;
-
-               case 'P':
-               case 'p':
-                       eb = 1;
-
-               case 'E':
-               case 'e':
-                       ex = 0;
-                       ef = 0;
-                       for(;;) {
-                               c = *s++;
-                               if(c == '+' || c == ' ' || c == '\t')
-                                       continue;
-                               if(c == '-') {
-                                       ef = 1;
-                                       continue;
-                               }
-                               if(c >= '0' && c <= '9') {
-                                       ex = ex*10 + (c-'0');
-                                       if(ex > 1e8) {
-                                               yyerror("constant exponent out of range: %s", as);
-                                               errorexit();
-                                       }
-                                       continue;
-                               }
-                               break;
-                       }
-                       if(ef)
-                               ex = -ex;
-
-               case 0:
-                       break;
-               }
-               break;
-       }
-
-       if(eb) {
-               if(dp) {
-                       yyerror("decimal point and binary point in constant: %s", as);
-                       goto bad;
-               }
-               mpsetexp(a, a->exp+ex);
-               goto out;
-       }
-
-       if(dp)
-               dp--;
-       if(mpcmpfltc(a, 0.0) != 0) {
-               if(ex >= dp) {
-                       mppow10flt(&b, ex-dp);
-                       mpmulfltflt(a, &b);
-               } else {
-                       // 4 approximates least_upper_bound(log2(10)).
-                       if(dp-ex >= (1<<(8*sizeof(dp)-3)) || (short)(4*(dp-ex)) != 4*(dp-ex)) {
-                               mpmovecflt(a, 0.0);
-                       }
-                       else {
-                               mppow10flt(&b, dp-ex);
-                               mpdivfltflt(a, &b);
-                       }
-               }
-       }
-
-out:
-       if(f)
-               mpnegflt(a);
-       return;
-
-bad:
-       mpmovecflt(a, 0.0);
-}
-
-//
-// fixed point input
-// required syntax is [+-][0[x]]d*
-//
-void
-mpatofix(Mpint *a, char *as)
-{
-       int c, f;
-       char *s, *s0;
-
-       s = as;
-       f = 0;
-       mpmovecfix(a, 0);
-
-       c = *s++;
-       switch(c) {
-       case '-':
-               f = 1;
-
-       case '+':
-               c = *s++;
-               if(c != '0')
-                       break;
-
-       case '0':
-               goto oct;
-       }
-
-       while(c) {
-               if(c >= '0' && c <= '9') {
-                       mpmulcfix(a, 10);
-                       mpaddcfix(a, c-'0');
-                       c = *s++;
-                       continue;
-               }
-               yyerror("malformed decimal constant: %s", as);
-               goto bad;
-       }
-       goto out;
-
-oct:
-       c = *s++;
-       if(c == 'x' || c == 'X')
-               goto hex;
-       while(c) {
-               if(c >= '0' && c <= '7') {
-                       mpmulcfix(a, 8);
-                       mpaddcfix(a, c-'0');
-                       c = *s++;
-                       continue;
-               }
-               yyerror("malformed octal constant: %s", as);
-               goto bad;
-       }
-       goto out;
-
-hex:
-       s0 = s;
-       c = *s;
-       while(c) {
-               if((c >= '0' && c <= '9') || (c >= 'a' && c <= 'f') || (c >= 'A' && c <= 'F')) {
-                       s++;
-                       c = *s;
-                       continue;
-               }
-               yyerror("malformed hex constant: %s", as);
-               goto bad;
-       }
-       mphextofix(a, s0, s-s0);
-       if(a->ovf) {
-               yyerror("constant too large: %s", as);
-               goto bad;
-       }
-
-out:
-       if(f)
-               mpnegfix(a);
-       return;
-
-bad:
-       mpmovecfix(a, 0);
-}
-
-int
-Bconv(Fmt *fp)
-{
-       char buf[500];
-       int p;
-       Mpint *xval, q, r, ten, sixteen;
-       int f, digit;
-
-       xval = va_arg(fp->args, Mpint*);
-       mpmovefixfix(&q, xval);
-       f = 0;
-       if(mptestfix(&q) < 0) {
-               f = 1;
-               mpnegfix(&q);
-       }
-
-       p = sizeof(buf);
-       buf[--p] = 0;
-       if(fp->flags & FmtSharp) {
-               // Hexadecimal
-               mpmovecfix(&sixteen, 16);
-               for(;;) {
-                       mpdivmodfixfix(&q, &r, &q, &sixteen);
-                       digit = mpgetfix(&r);
-                       if(digit < 10)
-                               buf[--p] = digit + '0';
-                       else
-                               buf[--p] = digit - 10 + 'A';
-                       if(mptestfix(&q) <= 0)
-                               break;
-               }
-               buf[--p] = 'x';
-               buf[--p] = '0';
-       } else {
-               // Decimal
-               mpmovecfix(&ten, 10);
-               for(;;) {
-                       mpdivmodfixfix(&q, &r, &q, &ten);
-                       buf[--p] = mpgetfix(&r) + '0';
-                       if(mptestfix(&q) <= 0)
-                               break;
-               }
-       }
-       if(f)
-               buf[--p] = '-';
-       return fmtstrcpy(fp, &buf[p]);
-}
-
-int
-Fconv(Fmt *fp)
-{
-       char buf[500];
-       Mpflt *fvp, fv;
-       double d, dexp;
-       int exp;
-
-       fvp = va_arg(fp->args, Mpflt*);
-       if(fp->flags & FmtSharp) {
-               // alternate form - decimal for error messages.
-               // for well in range, convert to double and use print's %g
-               exp = fvp->exp + sigfig(fvp)*Mpscale;
-               if(-900 < exp && exp < 900) {
-                       d = mpgetflt(fvp);
-                       if(d >= 0 && (fp->flags & FmtSign))
-                               fmtprint(fp, "+");
-                       return fmtprint(fp, "%g", d);
-               }
-               
-               // very out of range. compute decimal approximation by hand.
-               // decimal exponent
-               dexp = fvp->exp * 0.301029995663981195; // log_10(2)
-               exp = (int)dexp;
-               // decimal mantissa
-               fv = *fvp;
-               fv.val.neg = 0;
-               fv.exp = 0;
-               d = mpgetflt(&fv);
-               d *= pow(10, dexp-exp);
-               while(d >= 9.99995) {
-                       d /= 10;
-                       exp++;
-               }
-               if(fvp->val.neg)
-                       fmtprint(fp, "-");
-               else if(fp->flags & FmtSign)
-                       fmtprint(fp, "+");
-               return fmtprint(fp, "%.5fe+%d", d, exp);
-       }
-
-       if(sigfig(fvp) == 0) {
-               snprint(buf, sizeof(buf), "0p+0");
-               goto out;
-       }
-       fv = *fvp;
-
-       while(fv.val.a[0] == 0) {
-               mpshiftfix(&fv.val, -Mpscale);
-               fv.exp += Mpscale;
-       }
-       while((fv.val.a[0]&1) == 0) {
-               mpshiftfix(&fv.val, -1);
-               fv.exp += 1;
-       }
-
-       if(fv.exp >= 0) {
-               snprint(buf, sizeof(buf), "%#Bp+%d", &fv.val, fv.exp);
-               goto out;
-       }
-       snprint(buf, sizeof(buf), "%#Bp-%d", &fv.val, -fv.exp);
-
-out:
-       return fmtstrcpy(fp, buf);
-}
diff --git a/src/cmd/gc/mparith2.c b/src/cmd/gc/mparith2.c
deleted file mode 100644 (file)
index 37aafbb..0000000
+++ /dev/null
@@ -1,689 +0,0 @@
-// Copyright 2009 The Go Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style
-// license that can be found in the LICENSE file.
-
-#include       <u.h>
-#include       <libc.h>
-#include       "go.h"
-
-//
-// return the significant
-// words of the argument
-//
-static int
-mplen(Mpint *a)
-{
-       int i, n;
-
-       n = -1;
-       for(i=0; i<Mpprec; i++) {
-               if(a->a[i] != 0)
-                       n = i;
-       }
-       return n+1;
-}
-
-//
-// left shift mpint by one
-// ignores sign
-//
-static void
-mplsh(Mpint *a, int quiet)
-{
-       long x;
-       int i, c;
-
-       c = 0;
-       for(i=0; i<Mpprec; i++) {
-               x = (a->a[i] << 1) + c;
-               c = 0;
-               if(x >= Mpbase) {
-                       x -= Mpbase;
-                       c = 1;
-               }
-               a->a[i] = x;
-       }
-       a->ovf = c;
-       if(a->ovf && !quiet)
-               yyerror("constant shift overflow");
-}
-
-//
-// left shift mpint by Mpscale
-// ignores sign
-//
-static void
-mplshw(Mpint *a, int quiet)
-{
-       int i;
-
-       i = Mpprec-1;
-       if(a->a[i]) {
-               a->ovf = 1;
-               if(!quiet)
-                       yyerror("constant shift overflow");
-       }
-       for(; i > 0; i--)
-               a->a[i] = a->a[i-1];
-       a->a[i] = 0;
-}
-
-//
-// right shift mpint by one
-// ignores sign and overflow
-//
-static void
-mprsh(Mpint *a)
-{
-       long x, lo;
-       int i, c;
-
-       c = 0;
-       lo = a->a[0] & 1;
-       for(i=Mpprec-1; i>=0; i--) {
-               x = a->a[i];
-               a->a[i] = (x + c) >> 1;
-               c = 0;
-               if(x & 1)
-                       c = Mpbase;
-       }
-       if(a->neg && lo != 0)
-               mpaddcfix(a, -1);
-}
-
-//
-// right shift mpint by Mpscale
-// ignores sign and overflow
-//
-static void
-mprshw(Mpint *a)
-{
-       long lo;
-       int i;
-
-       lo = a->a[0];
-       for(i=0; i<Mpprec-1; i++) {
-               a->a[i] = a->a[i+1];
-       }
-       a->a[i] = 0;
-       if(a->neg && lo != 0)
-               mpaddcfix(a, -1);
-}
-
-//
-// return the sign of (abs(a)-abs(b))
-//
-static int
-mpcmp(Mpint *a, Mpint *b)
-{
-       long x;
-       int i;
-
-       if(a->ovf || b->ovf) {
-               if(nsavederrors+nerrors == 0)
-                       yyerror("ovf in cmp");
-               return 0;
-       }
-
-       for(i=Mpprec-1; i>=0; i--) {
-               x = a->a[i] - b->a[i];
-               if(x > 0)
-                       return +1;
-               if(x < 0)
-                       return -1;
-       }
-       return 0;
-}
-
-//
-// negate a
-// ignore sign and ovf
-//
-static void
-mpneg(Mpint *a)
-{
-       long x;
-       int i, c;
-
-       c = 0;
-       for(i=0; i<Mpprec; i++) {
-               x = -a->a[i] -c;
-               c = 0;
-               if(x < 0) {
-                       x += Mpbase;
-                       c = 1;
-               }
-               a->a[i] = x;
-       }
-}
-
-// shift left by s (or right by -s)
-void
-mpshiftfix(Mpint *a, int s)
-{
-       if(s >= 0) {
-               while(s >= Mpscale) {
-                       mplshw(a, 0);
-                       s -= Mpscale;
-               }
-               while(s > 0) {
-                       mplsh(a, 0);
-                       s--;
-               }
-       } else {
-               s = -s;
-               while(s >= Mpscale) {
-                       mprshw(a);
-                       s -= Mpscale;
-               }
-               while(s > 0) {
-                       mprsh(a);
-                       s--;
-               }
-       }
-}
-
-/// implements fix arihmetic
-
-void
-mpaddfixfix(Mpint *a, Mpint *b, int quiet)
-{
-       int i, c;
-       long x;
-
-       if(a->ovf || b->ovf) {
-               if(nsavederrors+nerrors == 0)
-                       yyerror("ovf in mpaddxx");
-               a->ovf = 1;
-               return;
-       }
-
-       c = 0;
-       if(a->neg != b->neg)
-               goto sub;
-
-       // perform a+b
-       for(i=0; i<Mpprec; i++) {
-               x = a->a[i] + b->a[i] + c;
-               c = 0;
-               if(x >= Mpbase) {
-                       x -= Mpbase;
-                       c = 1;
-               }
-               a->a[i] = x;
-       }
-       a->ovf = c;
-       if(a->ovf && !quiet)
-               yyerror("constant addition overflow");
-
-       return;
-
-sub:
-       // perform a-b
-       switch(mpcmp(a, b)) {
-       case 0:
-               mpmovecfix(a, 0);
-               break;
-
-       case 1:
-               for(i=0; i<Mpprec; i++) {
-                       x = a->a[i] - b->a[i] - c;
-                       c = 0;
-                       if(x < 0) {
-                               x += Mpbase;
-                               c = 1;
-                       }
-                       a->a[i] = x;
-               }
-               break;
-
-       case -1:
-               a->neg ^= 1;
-               for(i=0; i<Mpprec; i++) {
-                       x = b->a[i] - a->a[i] - c;
-                       c = 0;
-                       if(x < 0) {
-                               x += Mpbase;
-                               c = 1;
-                       }
-                       a->a[i] = x;
-               }
-               break;
-       }
-}
-
-void
-mpmulfixfix(Mpint *a, Mpint *b)
-{
-
-       int i, j, na, nb;
-       long x;
-       Mpint s, q;
-       Mpint *c;
-
-       if(a->ovf || b->ovf) {
-               if(nsavederrors+nerrors == 0)
-                       yyerror("ovf in mpmulfixfix");
-               a->ovf = 1;
-               return;
-       }
-
-       // pick the smaller
-       // to test for bits
-       na = mplen(a);
-       nb = mplen(b);
-       if(na > nb) {
-               mpmovefixfix(&s, a);
-               c = b;
-               na = nb;
-       } else {
-               mpmovefixfix(&s, b);
-               c = a;
-       }
-       s.neg = 0;
-
-       mpmovecfix(&q, 0);
-       for(i=0; i<na; i++) {
-               x = c->a[i];
-               for(j=0; j<Mpscale; j++) {
-                       if(x & 1) {
-                               if(s.ovf) {
-                                       q.ovf = 1;
-                                       goto out;
-                               }
-                               mpaddfixfix(&q, &s, 1);
-                               if(q.ovf)
-                                       goto out;
-                       }
-                       mplsh(&s, 1);
-                       x >>= 1;
-               }
-       }
-
-out:
-       q.neg = a->neg ^ b->neg;
-       mpmovefixfix(a, &q);
-       if(a->ovf)
-               yyerror("constant multiplication overflow");
-}
-
-void
-mpmulfract(Mpint *a, Mpint *b)
-{
-
-       int i, j;
-       long x;
-       Mpint s, q;
-
-       if(a->ovf || b->ovf) {
-               if(nsavederrors+nerrors == 0)
-                       yyerror("ovf in mpmulflt");
-               a->ovf = 1;
-               return;
-       }
-
-       mpmovefixfix(&s, b);
-       s.neg = 0;
-       mpmovecfix(&q, 0);
-
-       i = Mpprec-1;
-       x = a->a[i];
-       if(x != 0)
-               yyerror("mpmulfract not normal");
-
-       for(i--; i >= 0; i--) {
-               x = a->a[i];
-               if(x == 0) {
-                       mprshw(&s);
-                       continue;
-               }
-               for(j=0; j<Mpscale; j++) {
-                       x <<= 1;
-                       if(x & Mpbase)
-                               mpaddfixfix(&q, &s, 1);
-                       mprsh(&s);
-               }
-       }
-
-       q.neg = a->neg ^ b->neg;
-       mpmovefixfix(a, &q);
-       if(a->ovf)
-               yyerror("constant multiplication overflow");
-}
-
-void
-mporfixfix(Mpint *a, Mpint *b)
-{
-       int i;
-       long x;
-
-       x = 0;
-       if(a->ovf || b->ovf) {
-               if(nsavederrors+nerrors == 0)
-                       yyerror("ovf in mporfixfix");
-               mpmovecfix(a, 0);
-               a->ovf = 1;
-               return;
-       }
-       if(a->neg) {
-               a->neg = 0;
-               mpneg(a);
-       }
-       if(b->neg)
-               mpneg(b);
-
-       for(i=0; i<Mpprec; i++) {
-               x = a->a[i] | b->a[i];
-               a->a[i] = x;
-       }
-
-       if(b->neg)
-               mpneg(b);
-       if(x & Mpsign) {
-               a->neg = 1;
-               mpneg(a);
-       }
-}
-
-void
-mpandfixfix(Mpint *a, Mpint *b)
-{
-       int i;
-       long x;
-
-       x = 0;
-       if(a->ovf || b->ovf) {
-               if(nsavederrors+nerrors == 0)
-                       yyerror("ovf in mpandfixfix");
-               mpmovecfix(a, 0);
-               a->ovf = 1;
-               return;
-       }
-       if(a->neg) {
-               a->neg = 0;
-               mpneg(a);
-       }
-       if(b->neg)
-               mpneg(b);
-
-       for(i=0; i<Mpprec; i++) {
-               x = a->a[i] & b->a[i];
-               a->a[i] = x;
-       }
-
-       if(b->neg)
-               mpneg(b);
-       if(x & Mpsign) {
-               a->neg = 1;
-               mpneg(a);
-       }
-}
-
-void
-mpandnotfixfix(Mpint *a, Mpint *b)
-{
-       int i;
-       long x;
-
-       x = 0;
-       if(a->ovf || b->ovf) {
-               if(nsavederrors+nerrors == 0)
-                       yyerror("ovf in mpandnotfixfix");
-               mpmovecfix(a, 0);
-               a->ovf = 1;
-               return;
-       }
-       if(a->neg) {
-               a->neg = 0;
-               mpneg(a);
-       }
-       if(b->neg)
-               mpneg(b);
-
-       for(i=0; i<Mpprec; i++) {
-               x = a->a[i] & ~b->a[i];
-               a->a[i] = x;
-       }
-
-       if(b->neg)
-               mpneg(b);
-       if(x & Mpsign) {
-               a->neg = 1;
-               mpneg(a);
-       }
-}
-
-void
-mpxorfixfix(Mpint *a, Mpint *b)
-{
-       int i;
-       long x;
-
-       x = 0;
-       if(a->ovf || b->ovf) {
-               if(nsavederrors+nerrors == 0)
-                       yyerror("ovf in mporfixfix");
-               mpmovecfix(a, 0);
-               a->ovf = 1;
-               return;
-       }
-       if(a->neg) {
-               a->neg = 0;
-               mpneg(a);
-       }
-       if(b->neg)
-               mpneg(b);
-
-       for(i=0; i<Mpprec; i++) {
-               x = a->a[i] ^ b->a[i];
-               a->a[i] = x;
-       }
-
-       if(b->neg)
-               mpneg(b);
-       if(x & Mpsign) {
-               a->neg = 1;
-               mpneg(a);
-       }
-}
-
-void
-mplshfixfix(Mpint *a, Mpint *b)
-{
-       vlong s;
-
-       if(a->ovf || b->ovf) {
-               if(nsavederrors+nerrors == 0)
-                       yyerror("ovf in mporfixfix");
-               mpmovecfix(a, 0);
-               a->ovf = 1;
-               return;
-       }
-       s = mpgetfix(b);
-       if(s < 0 || s >= Mpprec*Mpscale) {
-               yyerror("stupid shift: %lld", s);
-               mpmovecfix(a, 0);
-               return;
-       }
-
-       mpshiftfix(a, s);
-}
-
-void
-mprshfixfix(Mpint *a, Mpint *b)
-{
-       vlong s;
-
-       if(a->ovf || b->ovf) {
-               if(nsavederrors+nerrors == 0)
-                       yyerror("ovf in mprshfixfix");
-               mpmovecfix(a, 0);
-               a->ovf = 1;
-               return;
-       }
-       s = mpgetfix(b);
-       if(s < 0 || s >= Mpprec*Mpscale) {
-               yyerror("stupid shift: %lld", s);
-               if(a->neg)
-                       mpmovecfix(a, -1);
-               else
-                       mpmovecfix(a, 0);
-               return;
-       }
-
-       mpshiftfix(a, -s);
-}
-
-void
-mpnegfix(Mpint *a)
-{
-       a->neg ^= 1;
-}
-
-vlong
-mpgetfix(Mpint *a)
-{
-       vlong v;
-
-       if(a->ovf) {
-               if(nsavederrors+nerrors == 0)
-                       yyerror("constant overflow");
-               return 0;
-       }
-
-       v = (uvlong)a->a[0];
-       v |= (uvlong)a->a[1] << Mpscale;
-       v |= (uvlong)a->a[2] << (Mpscale+Mpscale);
-       if(a->neg)
-               v = -(uvlong)v;
-       return v;
-}
-
-void
-mpmovecfix(Mpint *a, vlong c)
-{
-       int i;
-       vlong x;
-
-       a->neg = 0;
-       a->ovf = 0;
-
-       x = c;
-       if(x < 0) {
-               a->neg = 1;
-               x = -(uvlong)x;
-       }
-
-       for(i=0; i<Mpprec; i++) {
-               a->a[i] = x&Mpmask;
-               x >>= Mpscale;
-       }
-}
-
-void
-mpdivmodfixfix(Mpint *q, Mpint *r, Mpint *n, Mpint *d)
-{
-       int i, ns, ds;
-
-       ns = n->neg;
-       ds = d->neg;
-       n->neg = 0;
-       d->neg = 0;
-
-       mpmovefixfix(r, n);
-       mpmovecfix(q, 0);
-
-       // shift denominator until it
-       // is larger than numerator
-       for(i=0; i<Mpprec*Mpscale; i++) {
-               if(mpcmp(d, r) > 0)
-                       break;
-               mplsh(d, 1);
-       }
-
-       // if it never happens
-       // denominator is probably zero
-       if(i >= Mpprec*Mpscale) {
-               q->ovf = 1;
-               r->ovf = 1;
-               n->neg = ns;
-               d->neg = ds;
-               yyerror("constant division overflow");
-               return;
-       }
-
-       // shift denominator back creating
-       // quotient a bit at a time
-       // when done the remaining numerator
-       // will be the remainder
-       for(; i>0; i--) {
-               mplsh(q, 1);
-               mprsh(d);
-               if(mpcmp(d, r) <= 0) {
-                       mpaddcfix(q, 1);
-                       mpsubfixfix(r, d);
-               }
-       }
-
-       n->neg = ns;
-       d->neg = ds;
-       r->neg = ns;
-       q->neg = ns^ds;
-}
-
-static int
-mpiszero(Mpint *a)
-{
-       int i;
-
-       for(i=Mpprec-1; i>=0; i--)
-               if(a->a[i] != 0)
-                       return 0;
-       return 1;
-}
-
-void
-mpdivfract(Mpint *a, Mpint *b)
-{
-       Mpint n, d;
-       int i, j, neg;
-       long x;
-
-       mpmovefixfix(&n, a);    // numerator
-       mpmovefixfix(&d, b);    // denominator
-
-       neg = n.neg ^ d.neg;
-       n.neg = 0;
-       d.neg = 0;
-       for(i=Mpprec-1; i >= 0; i--) {
-               x = 0;
-               for(j=0; j<Mpscale; j++) {
-                       x <<= 1;
-                       if(mpcmp(&d, &n) <= 0) {
-                               if(!mpiszero(&d))
-                                       x |= 1;
-                               mpsubfixfix(&n, &d);
-                       }
-                       mprsh(&d);
-               }
-               a->a[i] = x;
-       }
-       a->neg = neg;
-}
-
-int
-mptestfix(Mpint *a)
-{
-       Mpint b;
-       int r;
-
-       mpmovecfix(&b, 0);
-       r = mpcmp(a, &b);
-       if(a->neg) {
-               if(r > 0)
-                       return -1;
-               if(r < 0)
-                       return +1;
-       }
-       return r;
-}
diff --git a/src/cmd/gc/mparith3.c b/src/cmd/gc/mparith3.c
deleted file mode 100644 (file)
index 6afd75c..0000000
+++ /dev/null
@@ -1,346 +0,0 @@
-// Copyright 2009 The Go Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style
-// license that can be found in the LICENSE file.
-
-#include       <u.h>
-#include       <libc.h>
-#include       "go.h"
-
-/*
- * returns the leading non-zero
- * word of the number
- */
-int
-sigfig(Mpflt *a)
-{
-       int i;
-
-       for(i=Mpprec-1; i>=0; i--)
-               if(a->val.a[i] != 0)
-                       break;
-//print("sigfig %d %d\n", i-z+1, z);
-       return i+1;
-}
-
-/*
- * sets the exponent.
- * a too large exponent is an error.
- * a too small exponent rounds the number to zero.
- */
-void
-mpsetexp(Mpflt *a, int exp) {
-       if((short)exp != exp) {
-               if(exp > 0) {
-                       yyerror("float constant is too large");
-                       a->exp = 0x7fff;
-               }
-               else {
-                       mpmovecflt(a, 0);
-               }
-       }
-       else {
-               a->exp = exp;
-       }
-}
-
-/*
- * shifts the leading non-zero
- * word of the number to Mpnorm
- */
-void
-mpnorm(Mpflt *a)
-{
-       int s, os;
-       long x;
-
-       os = sigfig(a);
-       if(os == 0) {
-               // zero
-               a->exp = 0;
-               a->val.neg = 0;
-               return;
-       }
-
-       // this will normalize to the nearest word
-       x = a->val.a[os-1];
-       s = (Mpnorm-os) * Mpscale;
-
-       // further normalize to the nearest bit
-       for(;;) {
-               x <<= 1;
-               if(x & Mpbase)
-                       break;
-               s++;
-               if(x == 0) {
-                       // this error comes from trying to
-                       // convert an Inf or something
-                       // where the initial x=0x80000000
-                       s = (Mpnorm-os) * Mpscale;
-                       break;
-               }
-       }
-
-       mpshiftfix(&a->val, s);
-       mpsetexp(a, a->exp-s);
-}
-
-/// implements float arihmetic
-
-void
-mpaddfltflt(Mpflt *a, Mpflt *b)
-{
-       int sa, sb, s;
-       Mpflt c;
-
-       if(Mpdebug)
-               print("\n%F + %F", a, b);
-
-       sa = sigfig(a);
-       if(sa == 0) {
-               mpmovefltflt(a, b);
-               goto out;
-       }
-
-       sb = sigfig(b);
-       if(sb == 0)
-               goto out;
-
-       s = a->exp - b->exp;
-       if(s > 0) {
-               // a is larger, shift b right
-               mpmovefltflt(&c, b);
-               mpshiftfix(&c.val, -s);
-               mpaddfixfix(&a->val, &c.val, 0);
-               goto out;
-       }
-       if(s < 0) {
-               // b is larger, shift a right
-               mpshiftfix(&a->val, s);
-               mpsetexp(a, a->exp-s);
-               mpaddfixfix(&a->val, &b->val, 0);
-               goto out;
-       }
-       mpaddfixfix(&a->val, &b->val, 0);
-
-out:
-       mpnorm(a);
-       if(Mpdebug)
-               print(" = %F\n\n", a);
-}
-
-void
-mpmulfltflt(Mpflt *a, Mpflt *b)
-{
-       int sa, sb;
-
-       if(Mpdebug)
-               print("%F\n * %F\n", a, b);
-
-       sa = sigfig(a);
-       if(sa == 0) {
-               // zero
-               a->exp = 0;
-               a->val.neg = 0;
-               return;
-       }
-
-       sb = sigfig(b);
-       if(sb == 0) {
-               // zero
-               mpmovefltflt(a, b);
-               return;
-       }
-
-       mpmulfract(&a->val, &b->val);
-       mpsetexp(a, (a->exp + b->exp) + Mpscale*Mpprec - Mpscale - 1);
-
-       mpnorm(a);
-       if(Mpdebug)
-               print(" = %F\n\n", a);
-}
-
-void
-mpdivfltflt(Mpflt *a, Mpflt *b)
-{
-       int sa, sb;
-       Mpflt c;
-
-       if(Mpdebug)
-               print("%F\n / %F\n", a, b);
-
-       sb = sigfig(b);
-       if(sb == 0) {
-               // zero and ovfl
-               a->exp = 0;
-               a->val.neg = 0;
-               a->val.ovf = 1;
-               yyerror("constant division by zero");
-               return;
-       }
-
-       sa = sigfig(a);
-       if(sa == 0) {
-               // zero
-               a->exp = 0;
-               a->val.neg = 0;
-               return;
-       }
-
-       // adjust b to top
-       mpmovefltflt(&c, b);
-       mpshiftfix(&c.val, Mpscale);
-
-       // divide
-       mpdivfract(&a->val, &c.val);
-       mpsetexp(a, (a->exp-c.exp) - Mpscale*(Mpprec-1) + 1);
-
-       mpnorm(a);
-       if(Mpdebug)
-               print(" = %F\n\n", a);
-}
-
-static double
-mpgetfltN(Mpflt *a, int prec, int bias)
-{
-       int s, i, e, minexp;
-       uvlong v;
-       double f;
-
-       if(a->val.ovf && nsavederrors+nerrors == 0)
-               yyerror("mpgetflt ovf");
-
-       s = sigfig(a);
-       if(s == 0)
-               return 0;
-
-       if(s != Mpnorm) {
-               yyerror("mpgetflt norm");
-               mpnorm(a);
-       }
-
-       while((a->val.a[Mpnorm-1] & Mpsign) == 0) {
-               mpshiftfix(&a->val, 1);
-               mpsetexp(a, a->exp-1);  // can set 'a' to zero
-               s = sigfig(a);
-               if(s == 0)
-                       return 0;
-       }
-
-       // pick up the mantissa, a rounding bit, and a tie-breaking bit in a uvlong
-       s = prec+2;
-       v = 0;
-       for(i=Mpnorm-1; s>=Mpscale; i--) {
-               v = (v<<Mpscale) | a->val.a[i];
-               s -= Mpscale;
-       }
-       if(s > 0) {
-               v = (v<<s) | (a->val.a[i]>>(Mpscale-s));
-               if((a->val.a[i]&((1<<(Mpscale-s))-1)) != 0)
-                       v |= 1;
-               i--;
-       }
-       for(; i >= 0; i--) {
-               if(a->val.a[i] != 0)
-                       v |= 1;
-       }
-
-       // gradual underflow
-       e = Mpnorm*Mpscale + a->exp - prec;
-       minexp = bias+1-prec+1;
-       if(e < minexp) {
-               s = minexp - e;
-               if(s > prec+1)
-                       s = prec+1;
-               if((v & ((1ULL<<s)-1)) != 0)
-                       v |= 1ULL<<s;
-               v >>= s;
-               e = minexp;
-       }
-       
-       // round to even
-       v |= (v&4)>>2;
-       v += v&1;
-       v >>= 2;
-
-       f = (double)(v);
-       f = ldexp(f, e);
-
-       if(a->val.neg)
-               f = -f;
-
-       return f;
-}
-
-double
-mpgetflt(Mpflt *a)
-{
-       return mpgetfltN(a, 53, -1023);
-}
-
-double
-mpgetflt32(Mpflt *a)
-{
-       return mpgetfltN(a, 24, -127);
-}
-
-void
-mpmovecflt(Mpflt *a, double c)
-{
-       int i;
-       double f;
-       long l;
-
-       if(Mpdebug)
-               print("\nconst %g", c);
-       mpmovecfix(&a->val, 0);
-       a->exp = 0;
-       if(c == 0)
-               goto out;
-       if(c < 0) {
-               a->val.neg = 1;
-               c = -c;
-       }
-
-       f = frexp(c, &i);
-       a->exp = i;
-
-       for(i=0; i<10; i++) {
-               f = f*Mpbase;
-               l = floor(f);
-               f = f - l;
-               a->exp -= Mpscale;
-               a->val.a[0] = l;
-               if(f == 0)
-                       break;
-               mpshiftfix(&a->val, Mpscale);
-       }
-
-out:
-       mpnorm(a);
-       if(Mpdebug)
-               print(" = %F\n", a);
-}
-
-void
-mpnegflt(Mpflt *a)
-{
-       a->val.neg ^= 1;
-}
-
-int
-mptestflt(Mpflt *a)
-{
-       int s;
-
-       if(Mpdebug)
-               print("\n%F?", a);
-       s = sigfig(a);
-       if(s != 0) {
-               s = +1;
-               if(a->val.neg)
-                       s = -1;
-       }
-       if(Mpdebug)
-               print(" = %d\n", s);
-       return s;
-}
diff --git a/src/cmd/gc/obj.c b/src/cmd/gc/obj.c
deleted file mode 100644 (file)
index 3983f99..0000000
+++ /dev/null
@@ -1,498 +0,0 @@
-// Copyright 2009 The Go Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style
-// license that can be found in the LICENSE file.
-
-#include <u.h>
-#include <libc.h>
-#include "go.h"
-#include "../ld/textflag.h"
-
-/*
- * architecture-independent object file output
- */
-
-static void    dumpglobls(void);
-
-enum
-{
-       ArhdrSize = 60
-};
-
-static void
-formathdr(char *arhdr, char *name, vlong size)
-{
-       snprint(arhdr, ArhdrSize, "%-16s%-12d%-6d%-6d%-8o%-10lld`",
-               name, 0, 0, 0, 0644, size);
-       arhdr[ArhdrSize-1] = '\n'; // overwrite \0 written by snprint
-}
-
-void
-dumpobj(void)
-{
-       NodeList *externs, *tmp;
-       char arhdr[ArhdrSize];
-       vlong startobj, size;
-       Sym *zero;
-
-       bout = Bopen(outfile, OWRITE);
-       if(bout == nil) {
-               flusherrors();
-               print("can't create %s: %r\n", outfile);
-               errorexit();
-       }
-
-       startobj = 0;
-       if(writearchive) {
-               Bwrite(bout, "!<arch>\n", 8);
-               memset(arhdr, 0, sizeof arhdr);
-               Bwrite(bout, arhdr, sizeof arhdr);
-               startobj = Boffset(bout);
-       }
-       Bprint(bout, "go object %s %s %s %s\n", getgoos(), getgoarch(), getgoversion(), expstring());
-       dumpexport();
-       
-       if(writearchive) {
-               Bflush(bout);
-               size = Boffset(bout) - startobj;
-               if(size&1)
-                       Bputc(bout, 0);
-               Bseek(bout, startobj - ArhdrSize, 0);
-               formathdr(arhdr, "__.PKGDEF", size);
-               Bwrite(bout, arhdr, ArhdrSize);
-               Bflush(bout);
-
-               Bseek(bout, startobj + size + (size&1), 0);
-               memset(arhdr, 0, ArhdrSize);
-               Bwrite(bout, arhdr, ArhdrSize);
-               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");
-
-       externs = nil;
-       if(externdcl != nil)
-               externs = externdcl->end;
-
-       dumpglobls();
-       dumptypestructs();
-
-       // Dump extra globals.
-       tmp = externdcl;
-       if(externs != nil)
-               externdcl = externs->next;
-       dumpglobls();
-       externdcl = tmp;
-
-       zero = pkglookup("zerovalue", runtimepkg);
-       ggloblsym(zero, zerosize, DUPOK|RODATA);
-
-       dumpdata();
-       writeobj(ctxt, bout);
-
-       if(writearchive) {
-               Bflush(bout);
-               size = Boffset(bout) - startobj;
-               if(size&1)
-                       Bputc(bout, 0);
-               Bseek(bout, startobj - ArhdrSize, 0);
-               snprint(namebuf, sizeof namebuf, "_go_.%c", thearch.thechar);
-               formathdr(arhdr, namebuf, size);
-               Bwrite(bout, arhdr, ArhdrSize);
-       }
-       Bterm(bout);
-}
-
-static void
-dumpglobls(void)
-{
-       Node *n;
-       NodeList *l;
-
-       // add globals
-       for(l=externdcl; l; l=l->next) {
-               n = l->n;
-               if(n->op != ONAME)
-                       continue;
-
-               if(n->type == T)
-                       fatal("external %N nil type\n", n);
-               if(n->class == PFUNC)
-                       continue;
-               if(n->sym->pkg != localpkg)
-                       continue;
-               dowidth(n->type);
-
-               ggloblnod(n);
-       }
-       
-       for(l=funcsyms; l; l=l->next) {
-               n = l->n;
-               dsymptr(n->sym, 0, n->sym->def->shortname->sym, 0);
-               ggloblsym(n->sym, widthptr, DUPOK|RODATA);
-       }
-       
-       // Do not reprocess funcsyms on next dumpglobls call.
-       funcsyms = nil;
-}
-
-void
-Bputname(Biobuf *b, LSym *s)
-{
-       Bwrite(b, s->name, strlen(s->name)+1);
-}
-
-LSym*
-linksym(Sym *s)
-{
-       char *p;
-
-       if(s == nil)
-               return nil;
-       if(s->lsym != nil)
-               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);
-               free(p);
-       }
-       return s->lsym; 
-}
-
-int
-duintxx(Sym *s, int off, uint64 v, int wid)
-{
-       // Update symbol data directly instead of generating a
-       // DATA instruction that liblink will have to interpret later.
-       // This reduces compilation time and memory usage.
-       off = rnd(off, wid);
-       return setuintxx(ctxt, linksym(s), off, v, wid);
-}
-
-int
-duint8(Sym *s, int off, uint8 v)
-{
-       return duintxx(s, off, v, 1);
-}
-
-int
-duint16(Sym *s, int off, uint16 v)
-{
-       return duintxx(s, off, v, 2);
-}
-
-int
-duint32(Sym *s, int off, uint32 v)
-{
-       return duintxx(s, off, v, 4);
-}
-
-int
-duint64(Sym *s, int off, uint64 v)
-{
-       return duintxx(s, off, v, 8);
-}
-
-int
-duintptr(Sym *s, int off, uint64 v)
-{
-       return duintxx(s, off, v, widthptr);
-}
-
-Sym*
-stringsym(char *s, int len)
-{
-       static int gen;
-       Sym *sym;
-       int off, n, m;
-       struct {
-               Strlit lit;
-               char buf[110];
-       } tmp;
-       Pkg *pkg;
-
-       if(len > 100) {
-               // huge strings are made static to avoid long names
-               snprint(namebuf, sizeof(namebuf), ".gostring.%d", ++gen);
-               pkg = localpkg;
-       } else {
-               // small strings get named by their contents,
-               // so that multiple modules using the same string
-               // can share it.
-               tmp.lit.len = len;
-               memmove(tmp.lit.s, s, len);
-               tmp.lit.s[len] = '\0';
-               snprint(namebuf, sizeof(namebuf), "\"%Z\"", &tmp.lit);
-               pkg = gostringpkg;
-       }
-       sym = pkglookup(namebuf, pkg);
-       
-       // SymUniq flag indicates that data is generated already
-       if(sym->flags & SymUniq)
-               return sym;
-       sym->flags |= SymUniq;
-       sym->def = newname(sym);
-
-       off = 0;
-       
-       // string header
-       off = dsymptr(sym, off, sym, widthptr+widthint);
-       off = duintxx(sym, off, len, widthint);
-       
-       // string data
-       for(n=0; n<len; n+=m) {
-               m = 8;
-               if(m > len-n)
-                       m = len-n;
-               off = dsname(sym, off, s+n, m);
-       }
-       off = duint8(sym, off, 0);  // terminating NUL for runtime
-       off = (off+widthptr-1)&~(widthptr-1);  // round to pointer alignment
-       ggloblsym(sym, off, DUPOK|RODATA);
-
-       return sym;     
-}
-
-void
-slicebytes(Node *nam, char *s, int len)
-{
-       int off, n, m;
-       static int gen;
-       Sym *sym;
-
-       snprint(namebuf, sizeof(namebuf), ".gobytes.%d", ++gen);
-       sym = pkglookup(namebuf, localpkg);
-       sym->def = newname(sym);
-
-       off = 0;
-       for(n=0; n<len; n+=m) {
-               m = 8;
-               if(m > len-n)
-                       m = len-n;
-               off = dsname(sym, off, s+n, m);
-       }
-       ggloblsym(sym, off, NOPTR);
-       
-       if(nam->op != ONAME)
-               fatal("slicebytes %N", nam);
-       off = nam->xoffset;
-       off = dsymptr(nam->sym, off, sym, 0);
-       off = duintxx(nam->sym, off, len, widthint);
-       duintxx(nam->sym, off, len, widthint);
-}
-
-int
-dsname(Sym *s, int off, char *t, int n)
-{
-       Prog *p;
-
-       p = thearch.gins(ADATA, N, N);
-       p->from.type = TYPE_MEM;
-       p->from.name = NAME_EXTERN;
-       p->from.offset = off;
-       p->from.sym = linksym(s);
-       p->from3.type = TYPE_CONST;
-       p->from3.offset = n;
-       
-       p->to.type = TYPE_SCONST;
-       memmove(p->to.u.sval, t, n);
-       return off + n;
-}
-
-/*
- * make a refer to the data s, s+len
- * emitting DATA if needed.
- */
-void
-datastring(char *s, int len, Addr *a)
-{
-       Sym *sym;
-       
-       sym = stringsym(s, len);
-       a->type = TYPE_MEM;
-       a->name = NAME_EXTERN;
-       a->sym = linksym(sym);
-       a->node = sym->def;
-       a->offset = widthptr+widthint;  // skip header
-       a->etype = simtype[TINT];
-}
-
-/*
- * make a refer to the string sval,
- * emitting DATA if needed.
- */
-void
-datagostring(Strlit *sval, Addr *a)
-{
-       Sym *sym;
-
-       sym = stringsym(sval->s, sval->len);
-       a->type = TYPE_MEM;
-       a->name = NAME_EXTERN;
-       a->sym = linksym(sym);
-       a->node = sym->def;
-       a->offset = 0;  // header
-       a->etype = TSTRING;
-}
-
-void
-gdata(Node *nam, Node *nr, int wid)
-{
-       Prog *p;
-
-       if(nr->op == OLITERAL) {
-               switch(nr->val.ctype) {
-               case CTCPLX:
-                       gdatacomplex(nam, nr->val.u.cval);
-                       return;
-               case CTSTR:
-                       gdatastring(nam, nr->val.u.sval);
-                       return;
-               }
-       }
-       p = thearch.gins(ADATA, nam, nr);
-       p->from3.type = TYPE_CONST;
-       p->from3.offset = wid;
-}
-
-void
-gdatacomplex(Node *nam, Mpcplx *cval)
-{
-       Prog *p;
-       int w;
-
-       w = cplxsubtype(nam->type->etype);
-       w = types[w]->width;
-
-       p = thearch.gins(ADATA, nam, N);
-       p->from3.type = TYPE_CONST;
-       p->from3.offset = w;
-       p->to.type = TYPE_FCONST;
-       p->to.u.dval = mpgetflt(&cval->real);
-
-       p = thearch.gins(ADATA, nam, N);
-       p->from3.type = TYPE_CONST;
-       p->from3.offset = w;
-       p->from.offset += w;
-       p->to.type = TYPE_FCONST;
-       p->to.u.dval = mpgetflt(&cval->imag);
-}
-
-void
-gdatastring(Node *nam, Strlit *sval)
-{
-       Prog *p;
-       Node nod1;
-
-       p = thearch.gins(ADATA, nam, N);
-       datastring(sval->s, sval->len, &p->to);
-       p->from3.type = TYPE_CONST;
-       p->from3.offset = types[tptr]->width;
-       p->to.type = TYPE_ADDR;
-//print("%P\n", p);
-
-       nodconst(&nod1, types[TINT], sval->len);
-       p = thearch.gins(ADATA, nam, &nod1);
-       p->from3.type = TYPE_CONST;
-       p->from3.offset = widthint;
-       p->from.offset += widthptr;
-}
-
-int
-dstringptr(Sym *s, int off, char *str)
-{
-       Prog *p;
-
-       off = rnd(off, widthptr);
-       p = thearch.gins(ADATA, N, N);
-       p->from.type = TYPE_MEM;
-       p->from.name = NAME_EXTERN;
-       p->from.sym = linksym(s);
-       p->from.offset = off;
-       p->from3.type = TYPE_CONST;
-       p->from3.offset = widthptr;
-
-       datastring(str, strlen(str)+1, &p->to);
-       p->to.type = TYPE_ADDR;
-       p->to.etype = simtype[TINT];
-       off += widthptr;
-
-       return off;
-}
-
-int
-dgostrlitptr(Sym *s, int off, Strlit *lit)
-{
-       Prog *p;
-
-       if(lit == nil)
-               return duintptr(s, off, 0);
-
-       off = rnd(off, widthptr);
-       p = thearch.gins(ADATA, N, N);
-       p->from.type = TYPE_MEM;
-       p->from.name = NAME_EXTERN;
-       p->from.sym = linksym(s);
-       p->from.offset = off;
-       p->from3.type = TYPE_CONST;
-       p->from3.offset = widthptr;
-       datagostring(lit, &p->to);
-       p->to.type = TYPE_ADDR;
-       p->to.etype = simtype[TINT];
-       off += widthptr;
-
-       return off;
-}
-
-int
-dgostringptr(Sym *s, int off, char *str)
-{
-       int n;
-       Strlit *lit;
-
-       if(str == nil)
-               return duintptr(s, off, 0);
-
-       n = strlen(str);
-       lit = mal(sizeof *lit + n);
-       strcpy(lit->s, str);
-       lit->len = n;
-       return dgostrlitptr(s, off, lit);
-}
-
-int
-dsymptr(Sym *s, int off, Sym *x, int xoff)
-{
-       Prog *p;
-
-       off = rnd(off, widthptr);
-
-       p = thearch.gins(ADATA, N, N);
-       p->from.type = TYPE_MEM;
-       p->from.name = NAME_EXTERN;
-       p->from.sym = linksym(s);
-       p->from.offset = off;
-       p->from3.type = TYPE_CONST;
-       p->from3.offset = widthptr;
-       p->to.type = TYPE_ADDR;
-       p->to.name = NAME_EXTERN;
-       p->to.sym = linksym(x);
-       p->to.offset = xoff;
-       off += widthptr;
-
-       return off;
-}
diff --git a/src/cmd/gc/order.c b/src/cmd/gc/order.c
deleted file mode 100644 (file)
index 8e670bd..0000000
+++ /dev/null
@@ -1,1164 +0,0 @@
-// Copyright 2012 The Go Authors.  All rights reserved.
-// Use of this source code is governed by a BSD-style
-// license that can be found in the LICENSE file.
-
-// Rewrite tree to use separate statements to enforce
-// order of evaluation.  Makes walk easier, because it
-// can (after this runs) reorder at will within an expression.
-//
-// Rewrite x op= y into x = x op y.
-//
-// Introduce temporaries as needed by runtime routines.
-// For example, the map runtime routines take the map key
-// by reference, so make sure all map keys are addressable
-// by copying them to temporaries as needed.
-// The same is true for channel operations.
-//
-// Arrange that map index expressions only appear in direct
-// assignments x = m[k] or m[k] = x, never in larger expressions.
-//
-// Arrange that receive expressions only appear in direct assignments
-// x = <-c or as standalone statements <-c, never in larger expressions.
-
-// TODO(rsc): The temporary introduction during multiple assignments
-// should be moved into this file, so that the temporaries can be cleaned
-// and so that conversions implicit in the OAS2FUNC and OAS2RECV
-// nodes can be made explicit and then have their temporaries cleaned.
-
-// TODO(rsc): Goto and multilevel break/continue can jump over
-// inserted VARKILL annotations. Work out a way to handle these.
-// The current implementation is safe, in that it will execute correctly.
-// But it won't reuse temporaries as aggressively as it might, and
-// it can result in unnecessary zeroing of those variables in the function
-// prologue.
-
-#include       <u.h>
-#include       <libc.h>
-#include       "go.h"
-
-// Order holds state during the ordering process.
-typedef struct Order Order;
-struct Order
-{
-       NodeList *out; // list of generated statements
-       NodeList *temp; // head of stack of temporary variables
-       NodeList *free; // free list of NodeList* structs (for use in temp)
-};
-
-static void    orderstmt(Node*, Order*);
-static void    orderstmtlist(NodeList*, Order*);
-static void    orderblock(NodeList **l);
-static void    orderexpr(Node**, Order*);
-static void orderexprinplace(Node**, Order*);
-static void    orderexprlist(NodeList*, Order*);
-static void    orderexprlistinplace(NodeList*, Order*);
-
-// Order rewrites fn->nbody to apply the ordering constraints
-// described in the comment at the top of the file.
-void
-order(Node *fn)
-{
-       char s[50];
-
-       if(debug['W'] > 1) {
-               snprint(s, sizeof(s), "\nbefore order %S", fn->nname->sym);
-               dumplist(s, fn->nbody);
-       }
-
-       orderblock(&fn->nbody);
-}
-
-// Ordertemp allocates a new temporary with the given type,
-// pushes it onto the temp stack, and returns it.
-// If clear is true, ordertemp emits code to zero the temporary.
-static Node*
-ordertemp(Type *t, Order *order, int clear)
-{
-       Node *var, *a;
-       NodeList *l;
-
-       var = temp(t);
-       if(clear) {
-               a = nod(OAS, var, N);
-               typecheck(&a, Etop);
-               order->out = list(order->out, a);
-       }
-       if((l = order->free) == nil)
-               l = mal(sizeof *l);
-       order->free = l->next;
-       l->next = order->temp;
-       l->n = var;
-       order->temp = l;
-       return var;
-}
-
-// Ordercopyexpr behaves like ordertemp but also emits
-// code to initialize the temporary to the value n.
-//
-// The clear argument is provided for use when the evaluation
-// of tmp = n turns into a function call that is passed a pointer
-// to the temporary as the output space. If the call blocks before
-// tmp has been written, the garbage collector will still treat the
-// temporary as live, so we must zero it before entering that call.
-// Today, this only happens for channel receive operations.
-// (The other candidate would be map access, but map access
-// returns a pointer to the result data instead of taking a pointer
-// to be filled in.)
-static Node*
-ordercopyexpr(Node *n, Type *t, Order *order, int clear)
-{
-       Node *a, *var;
-
-       var = ordertemp(t, order, clear);
-       a = nod(OAS, var, n);
-       typecheck(&a, Etop);
-       order->out = list(order->out, a);
-       return var;
-}
-
-// Ordercheapexpr returns a cheap version of n.
-// The definition of cheap is that n is a variable or constant.
-// If not, ordercheapexpr allocates a new tmp, emits tmp = n,
-// and then returns tmp.
-static Node*
-ordercheapexpr(Node *n, Order *order)
-{
-       switch(n->op) {
-       case ONAME:
-       case OLITERAL:
-               return n;
-       }
-       return ordercopyexpr(n, n->type, order, 0);
-}
-
-// Ordersafeexpr returns a safe version of n.
-// The definition of safe is that n can appear multiple times
-// without violating the semantics of the original program,
-// and that assigning to the safe version has the same effect
-// as assigning to the original n.
-//
-// The intended use is to apply to x when rewriting x += y into x = x + y.
-static Node*
-ordersafeexpr(Node *n, Order *order)
-{
-       Node *l, *r, *a;
-       
-       switch(n->op) {
-       case ONAME:
-       case OLITERAL:
-               return n;
-
-       case ODOT:
-               l = ordersafeexpr(n->left, order);
-               if(l == n->left)
-                       return n;
-               a = nod(OXXX, N, N);
-               *a = *n;
-               a->orig = a;
-               a->left = l;
-               typecheck(&a, Erv);
-               return a;
-
-       case ODOTPTR:
-       case OIND:
-               l = ordercheapexpr(n->left, order);
-               if(l == n->left)
-                       return n;
-               a = nod(OXXX, N, N);
-               *a = *n;
-               a->orig = a;
-               a->left = l;
-               typecheck(&a, Erv);
-               return a;
-               
-       case OINDEX:
-       case OINDEXMAP:
-               if(isfixedarray(n->left->type))
-                       l = ordersafeexpr(n->left, order);
-               else
-                       l = ordercheapexpr(n->left, order);
-               r = ordercheapexpr(n->right, order);
-               if(l == n->left && r == n->right)
-                       return n;
-               a = nod(OXXX, N, N);
-               *a = *n;
-               a->orig = a;
-               a->left = l;
-               a->right = r;
-               typecheck(&a, Erv);
-               return a;
-       }
-
-       fatal("ordersafeexpr %O", n->op);
-       return nil; // not reached
-}              
-
-// Istemp reports whether n is a temporary variable.
-static int
-istemp(Node *n)
-{
-       if(n->op != ONAME)
-               return 0;
-       return strncmp(n->sym->name, "autotmp_", 8) == 0;
-}
-
-// Isaddrokay reports whether it is okay to pass n's address to runtime routines.
-// Taking the address of a variable makes the liveness and optimization analyses
-// lose track of where the variable's lifetime ends. To avoid hurting the analyses
-// of ordinary stack variables, those are not 'isaddrokay'. Temporaries are okay,
-// because we emit explicit VARKILL instructions marking the end of those
-// temporaries' lifetimes.
-static int
-isaddrokay(Node *n)
-{
-       return islvalue(n) && (n->op != ONAME || n->class == PEXTERN || istemp(n));
-}
-
-// Orderaddrtemp ensures that *np is okay to pass by address to runtime routines.
-// If the original argument *np is not okay, orderaddrtemp creates a tmp, emits
-// tmp = *np, and then sets *np to the tmp variable.
-static void
-orderaddrtemp(Node **np, Order *order)
-{
-       Node *n;
-       
-       n = *np;
-       if(isaddrokay(n))
-               return;
-       *np = ordercopyexpr(n, n->type, order, 0);
-}
-
-// Marktemp returns the top of the temporary variable stack.
-static NodeList*
-marktemp(Order *order)
-{
-       return order->temp;
-}
-
-// Poptemp pops temporaries off the stack until reaching the mark,
-// which must have been returned by marktemp.
-static void
-poptemp(NodeList *mark, Order *order)
-{
-       NodeList *l;
-
-       while((l = order->temp) != mark) {
-               order->temp = l->next;
-               l->next = order->free;
-               order->free = l;
-       }
-}
-
-// Cleantempnopop emits to *out VARKILL instructions for each temporary
-// above the mark on the temporary stack, but it does not pop them
-// from the stack.
-static void
-cleantempnopop(NodeList *mark, Order *order, NodeList **out)
-{
-       NodeList *l;
-       Node *kill;
-
-       for(l=order->temp; l != mark; l=l->next) {
-               kill = nod(OVARKILL, l->n, N);
-               typecheck(&kill, Etop);
-               *out = list(*out, kill);
-       }
-}
-
-// Cleantemp emits VARKILL instructions for each temporary above the
-// mark on the temporary stack and removes them from the stack.
-static void
-cleantemp(NodeList *top, Order *order)
-{
-       cleantempnopop(top, order, &order->out);
-       poptemp(top, order);
-}
-
-// Orderstmtlist orders each of the statements in the list.
-static void
-orderstmtlist(NodeList *l, Order *order)
-{
-       for(; l; l=l->next)
-               orderstmt(l->n, order);
-}
-
-// Orderblock orders the block of statements *l onto a new list,
-// and then replaces *l with that list.
-static void
-orderblock(NodeList **l)
-{
-       Order order;
-       NodeList *mark;
-       
-       memset(&order, 0, sizeof order);
-       mark = marktemp(&order);
-       orderstmtlist(*l, &order);
-       cleantemp(mark, &order);
-       *l = order.out;
-}
-
-// Orderexprinplace orders the side effects in *np and
-// leaves them as the init list of the final *np.
-static void
-orderexprinplace(Node **np, Order *outer)
-{
-       Node *n;
-       NodeList **lp;
-       Order order;
-       
-       n = *np;
-       memset(&order, 0, sizeof order);
-       orderexpr(&n, &order);
-       addinit(&n, order.out);
-       
-       // insert new temporaries from order
-       // at head of outer list.
-       lp = &order.temp;
-       while(*lp != nil)
-               lp = &(*lp)->next;
-       *lp = outer->temp;
-       outer->temp = order.temp;
-
-       *np = n;
-}
-
-// Orderstmtinplace orders the side effects of the single statement *np
-// and replaces it with the resulting statement list.
-void
-orderstmtinplace(Node **np)
-{
-       Node *n;
-       Order order;
-       NodeList *mark;
-       
-       n = *np;
-       memset(&order, 0, sizeof order);
-       mark = marktemp(&order);
-       orderstmt(n, &order);
-       cleantemp(mark, &order);
-       *np = liststmt(order.out);
-}
-
-// Orderinit moves n's init list to order->out.
-static void
-orderinit(Node *n, Order *order)
-{
-       orderstmtlist(n->ninit, order);
-       n->ninit = nil;
-}
-
-// Ismulticall reports whether the list l is f() for a multi-value function.
-// Such an f() could appear as the lone argument to a multi-arg function.
-static int
-ismulticall(NodeList *l)
-{
-       Node *n;
-       
-       // one arg only
-       if(l == nil || l->next != nil)
-               return 0;
-       n = l->n;
-       
-       // must be call
-       switch(n->op) {
-       default:
-               return 0;
-       case OCALLFUNC:
-       case OCALLMETH:
-       case OCALLINTER:
-               break;
-       }
-       
-       // call must return multiple values
-       return n->left->type->outtuple > 1;
-}
-
-// Copyret emits t1, t2, ... = n, where n is a function call,
-// and then returns the list t1, t2, ....
-static NodeList*
-copyret(Node *n, Order *order)
-{
-       Type *t;
-       Node *tmp, *as;
-       NodeList *l1, *l2;
-       Iter tl;
-       
-       if(n->type->etype != TSTRUCT || !n->type->funarg)
-               fatal("copyret %T %d", n->type, n->left->type->outtuple);
-
-       l1 = nil;
-       l2 = nil;
-       for(t=structfirst(&tl, &n->type); t; t=structnext(&tl)) {
-               tmp = temp(t->type);
-               l1 = list(l1, tmp);
-               l2 = list(l2, tmp);
-       }
-       
-       as = nod(OAS2, N, N);
-       as->list = l1;
-       as->rlist = list1(n);
-       typecheck(&as, Etop);
-       orderstmt(as, order);
-
-       return l2;
-}
-
-// Ordercallargs orders the list of call arguments *l.
-static void
-ordercallargs(NodeList **l, Order *order)
-{
-       if(ismulticall(*l)) {
-               // return f() where f() is multiple values.
-               *l = copyret((*l)->n, order);
-       } else {
-               orderexprlist(*l, order);
-       }
-}
-
-// Ordercall orders the call expression n.
-// n->op is OCALLMETH/OCALLFUNC/OCALLINTER or a builtin like OCOPY.
-static void
-ordercall(Node *n, Order *order)
-{
-       orderexpr(&n->left, order);
-       orderexpr(&n->right, order); // ODDDARG temp
-       ordercallargs(&n->list, order);
-}
-
-// Ordermapassign appends n to order->out, introducing temporaries
-// to make sure that all map assignments have the form m[k] = x,
-// where x is adressable.
-// (Orderexpr has already been called on n, so we know k is addressable.)
-//
-// If n is m[k] = x where x is not addressable, the rewrite is:
-//     tmp = x
-//     m[k] = tmp
-//
-// If n is the multiple assignment form ..., m[k], ... = ..., the rewrite is
-//     t1 = m
-//     t2 = k
-//     ...., t3, ... = x
-//     t1[t2] = t3
-//
-// The temporaries t1, t2 are needed in case the ... being assigned
-// contain m or k. They are usually unnecessary, but in the unnecessary
-// cases they are also typically registerizable, so not much harm done.
-// And this only applies to the multiple-assignment form.
-// We could do a more precise analysis if needed, like in walk.c.
-//
-// Ordermapassign also inserts these temporaries if needed for
-// calling writebarrierfat with a pointer to n->right.
-static void
-ordermapassign(Node *n, Order *order)
-{
-       Node *m, *a;
-       NodeList *l;
-       NodeList *post;
-
-       switch(n->op) {
-       default:
-               fatal("ordermapassign %O", n->op);
-
-       case OAS:
-               order->out = list(order->out, n);
-               // We call writebarrierfat only for values > 4 pointers long. See walk.c.
-               if((n->left->op == OINDEXMAP || (needwritebarrier(n->left, n->right) && n->left->type->width > 4*widthptr)) && !isaddrokay(n->right)) {
-                       m = n->left;
-                       n->left = ordertemp(m->type, order, 0);
-                       a = nod(OAS, m, n->left);
-                       typecheck(&a, Etop);
-                       order->out = list(order->out, a);
-               }
-               break;
-
-       case OAS2:
-       case OAS2DOTTYPE:
-       case OAS2MAPR:
-       case OAS2FUNC:
-               post = nil;
-               for(l=n->list; l != nil; l=l->next) {
-                       if(l->n->op == OINDEXMAP) {
-                               m = l->n;
-                               if(!istemp(m->left))
-                                       m->left = ordercopyexpr(m->left, m->left->type, order, 0);
-                               if(!istemp(m->right))
-                                       m->right = ordercopyexpr(m->right, m->right->type, order, 0);
-                               l->n = ordertemp(m->type, order, 0);
-                               a = nod(OAS, m, l->n);
-                               typecheck(&a, Etop);
-                               post = list(post, a);
-                       }
-               }
-               order->out = list(order->out, n);
-               order->out = concat(order->out, post);
-               break;
-       }
-}
-
-// Orderstmt orders the statement n, appending to order->out.
-// Temporaries created during the statement are cleaned
-// up using VARKILL instructions as possible.
-static void
-orderstmt(Node *n, Order *order)
-{
-       int lno;
-       NodeList *l, *t, *t1;
-       Node *r, *tmp1, *tmp2, **np;
-       Type *ch, *typ;
-
-       if(n == N)
-               return;
-
-       lno = setlineno(n);
-
-       orderinit(n, order);
-
-       switch(n->op) {
-       default:
-               fatal("orderstmt %O", n->op);
-
-       case OVARKILL:
-               order->out = list(order->out, n);
-               break;
-
-       case OAS:
-       case OAS2:
-       case OCLOSE:
-       case OCOPY:
-       case OPRINT:
-       case OPRINTN:
-       case ORECOVER:
-       case ORECV:
-               t = marktemp(order);
-               orderexpr(&n->left, order);
-               orderexpr(&n->right, order);
-               orderexprlist(n->list, order);
-               orderexprlist(n->rlist, order);
-               switch(n->op) {
-               case OAS:
-               case OAS2:
-               case OAS2DOTTYPE:
-                       ordermapassign(n, order);
-                       break;
-               default:
-                       order->out = list(order->out, n);
-                       break;
-               }
-               cleantemp(t, order);
-               break;
-
-       case OASOP:
-               // Special: rewrite l op= r into l = l op r.
-               // This simplies quite a few operations;
-               // most important is that it lets us separate
-               // out map read from map write when l is
-               // a map index expression.
-               t = marktemp(order);
-               orderexpr(&n->left, order);
-               n->left = ordersafeexpr(n->left, order);
-               tmp1 = treecopy(n->left);
-               if(tmp1->op == OINDEXMAP)
-                       tmp1->etype = 0; // now an rvalue not an lvalue
-               tmp1 = ordercopyexpr(tmp1, n->left->type, order, 0);
-               n->right = nod(n->etype, tmp1, n->right);
-               typecheck(&n->right, Erv);
-               orderexpr(&n->right, order);
-               n->etype = 0;
-               n->op = OAS;
-               ordermapassign(n, order);
-               cleantemp(t, order);
-               break;
-
-       case OAS2MAPR:
-               // Special: make sure key is addressable,
-               // and make sure OINDEXMAP is not copied out.
-               t = marktemp(order);
-               orderexprlist(n->list, order);
-               r = n->rlist->n;
-               orderexpr(&r->left, order);
-               orderexpr(&r->right, order);
-               // See case OINDEXMAP below.
-               if(r->right->op == OARRAYBYTESTR)
-                       r->right->op = OARRAYBYTESTRTMP;
-               orderaddrtemp(&r->right, order);
-               ordermapassign(n, order);
-               cleantemp(t, order);
-               break;
-
-       case OAS2FUNC:
-               // Special: avoid copy of func call n->rlist->n.
-               t = marktemp(order);
-               orderexprlist(n->list, order);
-               ordercall(n->rlist->n, order);
-               ordermapassign(n, order);
-               cleantemp(t, order);
-               break;
-
-       case OAS2DOTTYPE:
-               // Special: use temporary variables to hold result,
-               // so that assertI2Tetc can take address of temporary.
-               // No temporary for blank assignment.
-               t = marktemp(order);
-               orderexprlist(n->list, order);
-               orderexpr(&n->rlist->n->left, order);  // i in i.(T)
-               if(isblank(n->list->n))
-                       order->out = list(order->out, n);
-               else {
-                       typ = n->rlist->n->type;
-                       tmp1 = ordertemp(typ, order, haspointers(typ));
-                       order->out = list(order->out, n);
-                       r = nod(OAS, n->list->n, tmp1);
-                       typecheck(&r, Etop);
-                       ordermapassign(r, order);
-                       n->list = list(list1(tmp1), n->list->next->n);
-               }
-               cleantemp(t, order);
-               break;
-
-       case OAS2RECV:
-               // Special: use temporary variables to hold result,
-               // so that chanrecv can take address of temporary.
-               t = marktemp(order);
-               orderexprlist(n->list, order);
-               orderexpr(&n->rlist->n->left, order);  // arg to recv
-               ch = n->rlist->n->left->type;
-               tmp1 = ordertemp(ch->type, order, haspointers(ch->type));
-               if(!isblank(n->list->next->n))
-                       tmp2 = ordertemp(n->list->next->n->type, order, 0);
-               else
-                       tmp2 = ordertemp(types[TBOOL], order, 0);
-               order->out = list(order->out, n);
-               r = nod(OAS, n->list->n, tmp1);
-               typecheck(&r, Etop);
-               ordermapassign(r, order);
-               r = nod(OAS, n->list->next->n, tmp2);
-               typecheck(&r, Etop);
-               ordermapassign(r, order);
-               n->list = list(list1(tmp1), tmp2);
-               cleantemp(t, order);
-               break;
-
-       case OBLOCK:
-       case OEMPTY:
-               // Special: does not save n onto out.
-               orderstmtlist(n->list, order);
-               break;
-
-       case OBREAK:
-       case OCONTINUE:
-       case ODCL:
-       case ODCLCONST:
-       case ODCLTYPE:
-       case OFALL:
-       case OXFALL:
-       case OGOTO:
-       case OLABEL:
-       case ORETJMP:
-               // Special: n->left is not an expression; save as is.
-               order->out = list(order->out, n);
-               break;
-
-       case OCALLFUNC:
-       case OCALLINTER:
-       case OCALLMETH:
-               // Special: handle call arguments.
-               t = marktemp(order);
-               ordercall(n, order);
-               order->out = list(order->out, n);
-               cleantemp(t, order);
-               break;
-
-       case ODEFER:
-       case OPROC:
-               // Special: order arguments to inner call but not call itself.
-               t = marktemp(order);
-               switch(n->left->op) {
-               case ODELETE:
-                       // Delete will take the address of the key.
-                       // Copy key into new temp and do not clean it
-                       // (it persists beyond the statement).
-                       orderexprlist(n->left->list, order);
-                       t1 = marktemp(order);
-                       np = &n->left->list->next->n; // map key
-                       *np = ordercopyexpr(*np, (*np)->type, order, 0);
-                       poptemp(t1, order);
-                       break;
-               default:
-                       ordercall(n->left, order);
-                       break;
-               }
-               order->out = list(order->out, n);
-               cleantemp(t, order);
-               break;
-
-       case ODELETE:
-               t = marktemp(order);
-               orderexpr(&n->list->n, order);
-               orderexpr(&n->list->next->n, order);
-               orderaddrtemp(&n->list->next->n, order); // map key
-               order->out = list(order->out, n);
-               cleantemp(t, order);
-               break;
-
-       case OFOR:
-               // Clean temporaries from condition evaluation at
-               // beginning of loop body and after for statement.
-               t = marktemp(order);
-               orderexprinplace(&n->ntest, order);
-               l = nil;
-               cleantempnopop(t, order, &l);
-               n->nbody = concat(l, n->nbody);
-               orderblock(&n->nbody);
-               orderstmtinplace(&n->nincr);
-               order->out = list(order->out, n);
-               cleantemp(t, order);
-               break;
-               
-       case OIF:
-               // Clean temporaries from condition at
-               // beginning of both branches.
-               t = marktemp(order);
-               orderexprinplace(&n->ntest, order);
-               l = nil;
-               cleantempnopop(t, order, &l);
-               n->nbody = concat(l, n->nbody);
-               l = nil;
-               cleantempnopop(t, order, &l);
-               n->nelse = concat(l, n->nelse);
-               poptemp(t, order);
-               orderblock(&n->nbody);
-               orderblock(&n->nelse);
-               order->out = list(order->out, n);
-               break;
-
-       case OPANIC:
-               // Special: argument will be converted to interface using convT2E
-               // so make sure it is an addressable temporary.
-               t = marktemp(order);
-               orderexpr(&n->left, order);
-               if(!isinter(n->left->type))
-                       orderaddrtemp(&n->left, order);
-               order->out = list(order->out, n);
-               cleantemp(t, order);
-               break;
-
-       case ORANGE:
-               // n->right is the expression being ranged over.
-               // order it, and then make a copy if we need one.
-               // We almost always do, to ensure that we don't
-               // see any value changes made during the loop.
-               // Usually the copy is cheap (e.g., array pointer, chan, slice, string are all tiny).
-               // The exception is ranging over an array value (not a slice, not a pointer to array),
-               // which must make a copy to avoid seeing updates made during
-               // the range body. Ranging over an array value is uncommon though.
-               t = marktemp(order);
-               orderexpr(&n->right, order);
-               switch(n->type->etype) {
-               default:
-                       fatal("orderstmt range %T", n->type);
-               case TARRAY:
-                       // Mark []byte(str) range expression to reuse string backing storage.
-                       // It is safe because the storage cannot be mutated.
-                       if(n->right->op == OSTRARRAYBYTE)
-                               n->right->op = OSTRARRAYBYTETMP;
-                       if(count(n->list) < 2 || isblank(n->list->next->n)) {
-                               // for i := range x will only use x once, to compute len(x).
-                               // No need to copy it.
-                               break;
-                       }
-                       // fall through
-               case TCHAN:
-               case TSTRING:
-                       // chan, string, slice, array ranges use value multiple times.
-                       // make copy.
-                       r = n->right;
-                       if(r->type->etype == TSTRING && r->type != types[TSTRING]) {
-                               r = nod(OCONV, r, N);
-                               r->type = types[TSTRING];
-                               typecheck(&r, Erv);
-                       }
-                       n->right = ordercopyexpr(r, r->type, order, 0);
-                       break;
-               case TMAP:
-                       // copy the map value in case it is a map literal.
-                       // TODO(rsc): Make tmp = literal expressions reuse tmp.
-                       // For maps tmp is just one word so it hardly matters.
-                       r = n->right;
-                       n->right = ordercopyexpr(r, r->type, order, 0);
-                       // n->alloc is the temp for the iterator.
-                       n->alloc = ordertemp(types[TUINT8], order, 1);
-                       break;
-               }
-               for(l=n->list; l; l=l->next)
-                       orderexprinplace(&l->n, order);
-               orderblock(&n->nbody);
-               order->out = list(order->out, n);
-               cleantemp(t, order);
-               break;
-
-       case ORETURN:
-               ordercallargs(&n->list, order);
-               order->out = list(order->out, n);
-               break;
-       
-       case OSELECT:
-               // Special: clean case temporaries in each block entry.
-               // Select must enter one of its blocks, so there is no
-               // need for a cleaning at the end.
-               // Doubly special: evaluation order for select is stricter
-               // than ordinary expressions. Even something like p.c
-               // has to be hoisted into a temporary, so that it cannot be
-               // reordered after the channel evaluation for a different
-               // case (if p were nil, then the timing of the fault would
-               // give this away).
-               t = marktemp(order);
-               for(l=n->list; l; l=l->next) {
-                       if(l->n->op != OXCASE)
-                               fatal("order select case %O", l->n->op);
-                       r = l->n->left;
-                       setlineno(l->n);
-                       // Append any new body prologue to ninit.
-                       // The next loop will insert ninit into nbody.
-                       if(l->n->ninit != nil)
-                               fatal("order select ninit");
-                       if(r != nil) {
-                               switch(r->op) {
-                               default:
-                                       yyerror("unknown op in select %O", r->op);
-                                       dump("select case", r);
-                                       break;
-
-                               case OSELRECV:
-                               case OSELRECV2:
-                                       // If this is case x := <-ch or case x, y := <-ch, the case has
-                                       // the ODCL nodes to declare x and y. We want to delay that
-                                       // declaration (and possible allocation) until inside the case body.
-                                       // Delete the ODCL nodes here and recreate them inside the body below.
-                                       if(r->colas) {
-                                               t = r->ninit;
-                                               if(t != nil && t->n->op == ODCL && t->n->left == r->left)
-                                                       t = t->next;
-                                               if(t != nil && t->n->op == ODCL && t->n->left == r->ntest)
-                                                       t = t->next;
-                                               if(t == nil)
-                                                       r->ninit = nil;
-                                       }
-                                       if(r->ninit != nil) {
-                                               yyerror("ninit on select recv");
-                                               dumplist("ninit", r->ninit);
-                                       }
-                                       // case x = <-c
-                                       // case x, ok = <-c
-                                       // r->left is x, r->ntest is ok, r->right is ORECV, r->right->left is c.
-                                       // r->left == N means 'case <-c'.
-                                       // c is always evaluated; x and ok are only evaluated when assigned.
-                                       orderexpr(&r->right->left, order);
-                                       if(r->right->left->op != ONAME)
-                                               r->right->left = ordercopyexpr(r->right->left, r->right->left->type, order, 0);
-
-                                       // Introduce temporary for receive and move actual copy into case body.
-                                       // avoids problems with target being addressed, as usual.
-                                       // NOTE: If we wanted to be clever, we could arrange for just one
-                                       // temporary per distinct type, sharing the temp among all receives
-                                       // with that temp. Similarly one ok bool could be shared among all
-                                       // the x,ok receives. Not worth doing until there's a clear need.
-                                       if(r->left != N && isblank(r->left))
-                                               r->left = N;
-                                       if(r->left != N) {
-                                               // use channel element type for temporary to avoid conversions,
-                                               // such as in case interfacevalue = <-intchan.
-                                               // the conversion happens in the OAS instead.
-                                               tmp1 = r->left;
-                                               if(r->colas) {
-                                                       tmp2 = nod(ODCL, tmp1, N);
-                                                       typecheck(&tmp2, Etop);
-                                                       l->n->ninit = list(l->n->ninit, tmp2);
-                                               }
-                                               r->left = ordertemp(r->right->left->type->type, order, haspointers(r->right->left->type->type));
-                                               tmp2 = nod(OAS, tmp1, r->left);
-                                               typecheck(&tmp2, Etop);
-                                               l->n->ninit = list(l->n->ninit, tmp2);
-                                       }
-                                       if(r->ntest != N && isblank(r->ntest))
-                                               r->ntest = N;
-                                       if(r->ntest != N) {
-                                               tmp1 = r->ntest;
-                                               if(r->colas) {
-                                                       tmp2 = nod(ODCL, tmp1, N);
-                                                       typecheck(&tmp2, Etop);
-                                                       l->n->ninit = list(l->n->ninit, tmp2);
-                                               }
-                                               r->ntest = ordertemp(tmp1->type, order, 0);
-                                               tmp2 = nod(OAS, tmp1, r->ntest);
-                                               typecheck(&tmp2, Etop);
-                                               l->n->ninit = list(l->n->ninit, tmp2);
-                                       }
-                                       orderblock(&l->n->ninit);
-                                       break;
-
-                               case OSEND:
-                                       if(r->ninit != nil) {
-                                               yyerror("ninit on select send");
-                                               dumplist("ninit", r->ninit);
-                                       }
-                                       // case c <- x
-                                       // r->left is c, r->right is x, both are always evaluated.
-                                       orderexpr(&r->left, order);
-                                       if(!istemp(r->left))
-                                               r->left = ordercopyexpr(r->left, r->left->type, order, 0);
-                                       orderexpr(&r->right, order);
-                                       if(!istemp(r->right))
-                                               r->right = ordercopyexpr(r->right, r->right->type, order, 0);
-                                       break;
-                               }
-                       }
-                       orderblock(&l->n->nbody);
-               }
-               // Now that we have accumulated all the temporaries, clean them.
-               // Also insert any ninit queued during the previous loop.
-               // (The temporary cleaning must follow that ninit work.)
-               for(l=n->list; l; l=l->next) {
-                       cleantempnopop(t, order, &l->n->ninit);
-                       l->n->nbody = concat(l->n->ninit, l->n->nbody);
-                       l->n->ninit = nil;
-               }
-               order->out = list(order->out, n);
-               poptemp(t, order);
-               break;
-
-       case OSEND:
-               // Special: value being sent is passed as a pointer; make it addressable.
-               t = marktemp(order);
-               orderexpr(&n->left, order);
-               orderexpr(&n->right, order);
-               orderaddrtemp(&n->right, order);
-               order->out = list(order->out, n);
-               cleantemp(t, order);
-               break;
-
-       case OSWITCH:
-               // TODO(rsc): Clean temporaries more aggressively.
-               // Note that because walkswitch will rewrite some of the
-               // switch into a binary search, this is not as easy as it looks.
-               // (If we ran that code here we could invoke orderstmt on
-               // the if-else chain instead.)
-               // For now just clean all the temporaries at the end.
-               // In practice that's fine.
-               t = marktemp(order);
-               orderexpr(&n->ntest, order);
-               for(l=n->list; l; l=l->next) {
-                       if(l->n->op != OXCASE)
-                               fatal("order switch case %O", l->n->op);
-                       orderexprlistinplace(l->n->list, order);
-                       orderblock(&l->n->nbody);
-               }
-               order->out = list(order->out, n);
-               cleantemp(t, order);
-               break;
-       }
-       
-       lineno = lno;
-}
-
-// Orderexprlist orders the expression list l into order.
-static void
-orderexprlist(NodeList *l, Order *order)
-{
-       for(; l; l=l->next)
-               orderexpr(&l->n, order);
-}
-
-// Orderexprlist orders the expression list l but saves
-// the side effects on the individual expression ninit lists.
-static void
-orderexprlistinplace(NodeList *l, Order *order)
-{
-       for(; l; l=l->next)
-               orderexprinplace(&l->n, order);
-}
-
-// Orderexpr orders a single expression, appending side
-// effects to order->out as needed.
-static void
-orderexpr(Node **np, Order *order)
-{
-       Node *n;
-       NodeList *mark, *l;
-       Type *t;
-       int lno, haslit, hasbyte;
-
-       n = *np;
-       if(n == N)
-               return;
-
-       lno = setlineno(n);
-       orderinit(n, order);
-
-       switch(n->op) {
-       default:
-               orderexpr(&n->left, order);
-               orderexpr(&n->right, order);
-               orderexprlist(n->list, order);
-               orderexprlist(n->rlist, order);
-               break;
-       
-       case OADDSTR:
-               // Addition of strings turns into a function call.
-               // Allocate a temporary to hold the strings.
-               // Fewer than 5 strings use direct runtime helpers.
-               orderexprlist(n->list, order);
-               if(count(n->list) > 5) {
-                       t = typ(TARRAY);
-                       t->bound = count(n->list);
-                       t->type = types[TSTRING];
-                       n->alloc = ordertemp(t, order, 0);
-               }
-
-               // Mark string(byteSlice) arguments to reuse byteSlice backing
-               // buffer during conversion. String concatenation does not
-               // memorize the strings for later use, so it is safe.
-               // However, we can do it only if there is at least one non-empty string literal.
-               // Otherwise if all other arguments are empty strings,
-               // concatstrings will return the reference to the temp string
-               // to the caller.
-               hasbyte = 0;
-               haslit = 0;
-               for(l=n->list; l != nil; l=l->next) {
-                       hasbyte |= l->n->op == OARRAYBYTESTR;
-                       haslit |= l->n->op == OLITERAL && l->n->val.u.sval->len != 0;
-               }
-               if(haslit && hasbyte) {
-                       for(l=n->list; l != nil; l=l->next) {
-                               if(l->n->op == OARRAYBYTESTR)
-                                       l->n->op = OARRAYBYTESTRTMP;
-                       }
-               }
-               break;
-
-       case OCMPSTR:
-               orderexpr(&n->left, order);
-               orderexpr(&n->right, order);
-               // Mark string(byteSlice) arguments to reuse byteSlice backing
-               // buffer during conversion. String comparison does not
-               // memorize the strings for later use, so it is safe.
-               if(n->left->op == OARRAYBYTESTR)
-                       n->left->op = OARRAYBYTESTRTMP;
-               if(n->right->op == OARRAYBYTESTR)
-                       n->right->op = OARRAYBYTESTRTMP;
-               break;
-
-       case OINDEXMAP:
-               // key must be addressable
-               orderexpr(&n->left, order);
-               orderexpr(&n->right, order);
-
-               // For x = m[string(k)] where k is []byte, the allocation of
-               // backing bytes for the string can be avoided by reusing
-               // the []byte backing array. This is a special case that it
-               // would be nice to handle more generally, but because
-               // there are no []byte-keyed maps, this specific case comes
-               // up in important cases in practice. See issue 3512.
-               // Nothing can change the []byte we are not copying before
-               // the map index, because the map access is going to
-               // be forced to happen immediately following this
-               // conversion (by the ordercopyexpr a few lines below).
-               if(n->etype == 0 && n->right->op == OARRAYBYTESTR)
-                       n->right->op = OARRAYBYTESTRTMP;
-
-               orderaddrtemp(&n->right, order);
-               if(n->etype == 0) {
-                       // use of value (not being assigned);
-                       // make copy in temporary.
-                       n = ordercopyexpr(n, n->type, order, 0);
-               }
-               break;
-       
-       case OCONVIFACE:
-               // concrete type (not interface) argument must be addressable
-               // temporary to pass to runtime.
-               orderexpr(&n->left, order);
-               if(!isinter(n->left->type))
-                       orderaddrtemp(&n->left, order);
-               break;
-       
-       case OANDAND:
-       case OOROR:
-               mark = marktemp(order);
-               orderexpr(&n->left, order);
-               // Clean temporaries from first branch at beginning of second.
-               // Leave them on the stack so that they can be killed in the outer
-               // context in case the short circuit is taken.
-               l = nil;
-               cleantempnopop(mark, order, &l);
-               n->right->ninit = concat(l, n->right->ninit);
-               orderexprinplace(&n->right, order);
-               break;
-       
-       case OAPPEND:
-       case OCALLFUNC:
-       case OCALLINTER:
-       case OCALLMETH:
-       case OCAP:
-       case OCOMPLEX:
-       case OCOPY:
-       case OIMAG:
-       case OLEN:
-       case OMAKECHAN:
-       case OMAKEMAP:
-       case OMAKESLICE:
-       case ONEW:
-       case OREAL:
-       case ORECOVER:
-               ordercall(n, order);
-               n = ordercopyexpr(n, n->type, order, 0);
-               break;
-
-       case OCLOSURE:
-               if(n->noescape && n->cvars != nil)
-                       n->alloc = ordertemp(types[TUINT8], order, 0); // walk will fill in correct type
-               break;
-
-       case OARRAYLIT:
-       case OCALLPART:
-               orderexpr(&n->left, order);
-               orderexpr(&n->right, order);
-               orderexprlist(n->list, order);
-               orderexprlist(n->rlist, order);
-               if(n->noescape)
-                       n->alloc = ordertemp(types[TUINT8], order, 0); // walk will fill in correct type
-               break;
-
-       case ODDDARG:
-               if(n->noescape) {
-                       // The ddd argument does not live beyond the call it is created for.
-                       // Allocate a temporary that will be cleaned up when this statement
-                       // completes. We could be more aggressive and try to arrange for it
-                       // to be cleaned up when the call completes.
-                       n->alloc = ordertemp(n->type->type, order, 0);
-               }
-               break;
-
-       case ORECV:
-       case ODOTTYPE:
-               orderexpr(&n->left, order);
-               n = ordercopyexpr(n, n->type, order, 1);
-               break;
-
-       case OEQ:
-       case ONE:
-               orderexpr(&n->left, order);
-               orderexpr(&n->right, order);
-               t = n->left->type;
-               if(t->etype == TSTRUCT || isfixedarray(t)) {
-                       // for complex comparisons, we need both args to be
-                       // addressable so we can pass them to the runtime.
-                       orderaddrtemp(&n->left, order);
-                       orderaddrtemp(&n->right, order);
-               }
-               break;
-       }
-       
-       lineno = lno;
-
-       *np = n;
-}
diff --git a/src/cmd/gc/pgen.c b/src/cmd/gc/pgen.c
deleted file mode 100644 (file)
index 16a8691..0000000
+++ /dev/null
@@ -1,547 +0,0 @@
-// Copyright 2011 The Go Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style
-// license that can be found in the LICENSE file.
-
-// "Portable" code generation.
-// Compiled separately for 5g, 6g, and 8g, so allowed to use gg.h, opt.h.
-// Must code to the intersection of the three back ends.
-
-#include       <u.h>
-#include       <libc.h>
-#include       "md5.h"
-#include       "go.h"
-//#include     "opt.h"
-#include       "../../runtime/funcdata.h"
-#include       "../ld/textflag.h"
-
-static void allocauto(Prog* p);
-static void emitptrargsmap(void);
-
-static Sym*
-makefuncdatasym(char *namefmt, int64 funcdatakind)
-{
-       Node nod;
-       Node *pnod;
-       Sym *sym;
-       static int32 nsym;
-
-       snprint(namebuf, sizeof(namebuf), namefmt, nsym++);
-       sym = lookup(namebuf);
-       pnod = newname(sym);
-       pnod->class = PEXTERN;
-       nodconst(&nod, types[TINT32], funcdatakind);
-       thearch.gins(AFUNCDATA, &nod, pnod);
-       return sym;
-}
-
-// gvardef inserts a VARDEF for n into the instruction stream.
-// VARDEF is an annotation for the liveness analysis, marking a place
-// where a complete initialization (definition) of a variable begins.
-// Since the liveness analysis can see initialization of single-word
-// variables quite easy, gvardef is usually only called for multi-word
-// or 'fat' variables, those satisfying isfat(n->type).
-// However, gvardef is also called when a non-fat variable is initialized
-// via a block move; the only time this happens is when you have
-//     return f()
-// for a function with multiple return values exactly matching the return
-// types of the current function.
-//
-// A 'VARDEF x' annotation in the instruction stream tells the liveness
-// analysis to behave as though the variable x is being initialized at that
-// point in the instruction stream. The VARDEF must appear before the
-// actual (multi-instruction) initialization, and it must also appear after
-// any uses of the previous value, if any. For example, if compiling:
-//
-//     x = x[1:]
-//
-// it is important to generate code like:
-//
-//     base, len, cap = pieces of x[1:]
-//     VARDEF x
-//     x = {base, len, cap}
-//
-// If instead the generated code looked like:
-//
-//     VARDEF x
-//     base, len, cap = pieces of x[1:]
-//     x = {base, len, cap}
-//
-// then the liveness analysis would decide the previous value of x was
-// unnecessary even though it is about to be used by the x[1:] computation.
-// Similarly, if the generated code looked like:
-//
-//     base, len, cap = pieces of x[1:]
-//     x = {base, len, cap}
-//     VARDEF x
-//
-// then the liveness analysis will not preserve the new value of x, because
-// the VARDEF appears to have "overwritten" it.
-//
-// VARDEF is a bit of a kludge to work around the fact that the instruction
-// stream is working on single-word values but the liveness analysis
-// wants to work on individual variables, which might be multi-word
-// aggregates. It might make sense at some point to look into letting
-// the liveness analysis work on single-word values as well, although
-// there are complications around interface values, slices, and strings,
-// all of which cannot be treated as individual words.
-//
-// VARKILL is the opposite of VARDEF: it marks a value as no longer needed,
-// even if its address has been taken. That is, a VARKILL annotation asserts
-// that its argument is certainly dead, for use when the liveness analysis
-// would not otherwise be able to deduce that fact.
-
-static void
-gvardefx(Node *n, int as)
-{
-       if(n == N)
-               fatal("gvardef nil");
-       if(n->op != ONAME) {
-               yyerror("gvardef %#O; %N", n->op, n);
-               return;
-       }
-       switch(n->class) {
-       case PAUTO:
-       case PPARAM:
-       case PPARAMOUT:
-               thearch.gins(as, N, n);
-       }
-}
-
-void
-gvardef(Node *n)
-{
-       gvardefx(n, AVARDEF);
-}
-
-void
-gvarkill(Node *n)
-{
-       gvardefx(n, AVARKILL);
-}
-
-static void
-removevardef(Prog *firstp)
-{
-       Prog *p;
-
-       for(p = firstp; p != P; p = p->link) {
-               while(p->link != P && (p->link->as == AVARDEF || p->link->as == AVARKILL))
-                       p->link = p->link->link;
-               if(p->to.type == TYPE_BRANCH)
-                       while(p->to.u.branch != P && (p->to.u.branch->as == AVARDEF || p->to.u.branch->as == AVARKILL))
-                               p->to.u.branch = p->to.u.branch->link;
-       }
-}
-
-static void
-gcsymdup(Sym *s)
-{
-       LSym *ls;
-       uint64 lo, hi;
-       
-       ls = linksym(s);
-       if(ls->nr > 0)
-               fatal("cannot rosymdup %s with relocations", ls->name);
-       MD5 d;
-       md5reset(&d);
-       md5write(&d, ls->p, ls->np);
-       lo = md5sum(&d, &hi);
-       ls->name = smprint("gclocals·%016llux%016llux", lo, hi);
-       ls->dupok = 1;
-}
-
-void
-compile(Node *fn)
-{
-       Plist *pl;
-       Node nod1, *n;
-       Prog *ptxt, *p;
-       int32 lno;
-       Type *t;
-       Iter save;
-       vlong oldstksize;
-       NodeList *l;
-       Node *nam;
-       Sym *gcargs;
-       Sym *gclocals;
-
-       if(newproc == N) {
-               newproc = sysfunc("newproc");
-               deferproc = sysfunc("deferproc");
-               deferreturn = sysfunc("deferreturn");
-               panicindex = sysfunc("panicindex");
-               panicslice = sysfunc("panicslice");
-               throwreturn = sysfunc("throwreturn");
-       }
-
-       lno = setlineno(fn);
-
-       curfn = fn;
-       dowidth(curfn->type);
-
-       if(fn->nbody == nil) {
-               if(pure_go || strncmp(fn->nname->sym->name, "init.", 5) == 0) {
-                       yyerror("missing function body", fn);
-                       goto ret;
-               }
-               if(debug['A'])
-                       goto ret;
-               emitptrargsmap();
-               goto ret;
-       }
-
-       saveerrors();
-
-       // set up domain for labels
-       clearlabels();
-
-       if(curfn->type->outnamed) {
-               // add clearing of the output parameters
-               t = structfirst(&save, getoutarg(curfn->type));
-               while(t != T) {
-                       if(t->nname != N) {
-                               n = nod(OAS, t->nname, N);
-                               typecheck(&n, Etop);
-                               curfn->nbody = concat(list1(n), curfn->nbody);
-                       }
-                       t = structnext(&save);
-               }
-       }
-       
-       order(curfn);
-       if(nerrors != 0)
-               goto ret;
-       
-       hasdefer = 0;
-       walk(curfn);
-       if(nerrors != 0)
-               goto ret;
-       if(flag_race)
-               racewalk(curfn);
-       if(nerrors != 0)
-               goto ret;
-
-       continpc = P;
-       breakpc = P;
-
-       pl = newplist();
-       pl->name = linksym(curfn->nname->sym);
-
-       setlineno(curfn);
-
-       nodconst(&nod1, types[TINT32], 0);
-       nam = curfn->nname;
-       if(isblank(nam))
-               nam = N;
-       ptxt = thearch.gins(ATEXT, nam, &nod1);
-       if(fn->dupok)
-               ptxt->from3.offset |= DUPOK;
-       if(fn->wrapper)
-               ptxt->from3.offset |= WRAPPER;
-       if(fn->needctxt)
-               ptxt->from3.offset |= NEEDCTXT;
-       if(fn->nosplit)
-               ptxt->from3.offset |= NOSPLIT;
-
-       // Clumsy but important.
-       // See test/recover.go for test cases and src/reflect/value.go
-       // for the actual functions being considered.
-       if(myimportpath != nil && strcmp(myimportpath, "reflect") == 0) {
-               if(strcmp(curfn->nname->sym->name, "callReflect") == 0 || strcmp(curfn->nname->sym->name, "callMethod") == 0)
-                       ptxt->from3.offset |= WRAPPER;
-       }       
-       
-       afunclit(&ptxt->from, curfn->nname);
-
-       thearch.ginit();
-
-       gcargs = makefuncdatasym("gcargs·%d", FUNCDATA_ArgsPointerMaps);
-       gclocals = makefuncdatasym("gclocals·%d", FUNCDATA_LocalsPointerMaps);
-
-       for(t=curfn->paramfld; t; t=t->down)
-               gtrack(tracksym(t->type));
-
-       for(l=fn->dcl; l; l=l->next) {
-               n = l->n;
-               if(n->op != ONAME) // might be OTYPE or OLITERAL
-                       continue;
-               switch(n->class) {
-               case PAUTO:
-               case PPARAM:
-               case PPARAMOUT:
-                       nodconst(&nod1, types[TUINTPTR], l->n->type->width);
-                       p = thearch.gins(ATYPE, l->n, &nod1);
-                       p->from.gotype = linksym(ngotype(l->n));
-                       break;
-               }
-       }
-
-       genlist(curfn->enter);
-       genlist(curfn->nbody);
-       thearch.gclean();
-       checklabels();
-       if(nerrors != 0)
-               goto ret;
-       if(curfn->endlineno)
-               lineno = curfn->endlineno;
-
-       if(curfn->type->outtuple != 0)
-               thearch.ginscall(throwreturn, 0);
-
-       thearch.ginit();
-       // TODO: Determine when the final cgen_ret can be omitted. Perhaps always?
-       thearch.cgen_ret(nil);
-       if(hasdefer) {
-               // deferreturn pretends to have one uintptr argument.
-               // Reserve space for it so stack scanner is happy.
-               if(maxarg < widthptr)
-                       maxarg = widthptr;
-       }
-       thearch.gclean();
-       if(nerrors != 0)
-               goto ret;
-
-       pc->as = ARET;  // overwrite AEND
-       pc->lineno = lineno;
-
-       fixjmp(ptxt);
-       if(!debug['N'] || debug['R'] || debug['P']) {
-               regopt(ptxt);
-               nilopt(ptxt);
-       }
-       thearch.expandchecks(ptxt);
-
-       oldstksize = stksize;
-       allocauto(ptxt);
-
-       if(0)
-               print("allocauto: %lld to %lld\n", oldstksize, (vlong)stksize);
-       USED(oldstksize);
-
-       setlineno(curfn);
-       if((int64)stksize+maxarg > (1ULL<<31)) {
-               yyerror("stack frame too large (>2GB)");
-               goto ret;
-       }
-
-       // Emit garbage collection symbols.
-       liveness(curfn, ptxt, gcargs, gclocals);
-       gcsymdup(gcargs);
-       gcsymdup(gclocals);
-
-       thearch.defframe(ptxt);
-
-       if(debug['f'])
-               frame(0);
-
-       // Remove leftover instrumentation from the instruction stream.
-       removevardef(ptxt);
-ret:
-       lineno = lno;
-}
-
-static void
-emitptrargsmap(void)
-{
-       int nptr, nbitmap, j, off;
-       vlong xoffset;
-       Bvec *bv;
-       Sym *sym;
-       
-       sym = lookup(smprint("%s.args_stackmap", curfn->nname->sym->name));
-
-       nptr = curfn->type->argwid / widthptr;
-       bv = bvalloc(nptr*2);
-       nbitmap = 1;
-       if(curfn->type->outtuple > 0)
-               nbitmap = 2;
-       off = duint32(sym, 0, nbitmap);
-       off = duint32(sym, off, bv->n);
-       if(curfn->type->thistuple > 0) {
-               xoffset = 0;
-               twobitwalktype1(getthisx(curfn->type), &xoffset, bv);
-       }
-       if(curfn->type->intuple > 0) {
-               xoffset = 0;
-               twobitwalktype1(getinargx(curfn->type), &xoffset, bv);
-       }
-       for(j = 0; j < bv->n; j += 32)
-               off = duint32(sym, off, bv->b[j/32]);
-       if(curfn->type->outtuple > 0) {
-               xoffset = 0;
-               twobitwalktype1(getoutargx(curfn->type), &xoffset, bv);
-               for(j = 0; j < bv->n; j += 32)
-                       off = duint32(sym, off, bv->b[j/32]);
-       }
-       ggloblsym(sym, off, RODATA);
-       free(bv);
-}
-
-// Sort the list of stack variables. Autos after anything else,
-// within autos, unused after used, within used, things with
-// pointers first, zeroed things first, and then decreasing size.
-// Because autos are laid out in decreasing addresses
-// on the stack, pointers first, zeroed things first and decreasing size
-// really means, in memory, things with pointers needing zeroing at
-// the top of the stack and increasing in size.
-// Non-autos sort on offset.
-static int
-cmpstackvar(Node *a, Node *b)
-{
-       int ap, bp;
-
-       if (a->class != b->class) {
-               if(a->class == PAUTO)
-                       return +1;
-               return -1;
-       }
-       if (a->class != PAUTO) {
-               if (a->xoffset < b->xoffset)
-                       return -1;
-               if (a->xoffset > b->xoffset)
-                       return +1;
-               return 0;
-       }
-       if ((a->used == 0) != (b->used == 0))
-               return b->used - a->used;
-
-       ap = haspointers(a->type);
-       bp = haspointers(b->type);
-       if(ap != bp)
-               return bp - ap;
-
-       ap = a->needzero;
-       bp = b->needzero;
-       if(ap != bp)
-               return bp - ap;
-
-       if(a->type->width < b->type->width)
-               return +1;
-       if(a->type->width > b->type->width)
-               return -1;
-
-       return strcmp(a->sym->name, b->sym->name);
-}
-
-// TODO(lvd) find out where the PAUTO/OLITERAL nodes come from.
-static void
-allocauto(Prog* ptxt)
-{
-       NodeList *ll;
-       Node* n;
-       vlong w;
-
-       stksize = 0;
-       stkptrsize = 0;
-
-       if(curfn->dcl == nil)
-               return;
-
-       // Mark the PAUTO's unused.
-       for(ll=curfn->dcl; ll != nil; ll=ll->next)
-               if (ll->n->class == PAUTO)
-                       ll->n->used = 0;
-
-       markautoused(ptxt);
-
-       listsort(&curfn->dcl, cmpstackvar);
-
-       // Unused autos are at the end, chop 'em off.
-       ll = curfn->dcl;
-       n = ll->n;
-       if (n->class == PAUTO && n->op == ONAME && !n->used) {
-               // No locals used at all
-               curfn->dcl = nil;
-               fixautoused(ptxt);
-               return;
-       }
-
-       for(ll = curfn->dcl; ll->next != nil; ll=ll->next) {
-               n = ll->next->n;
-               if (n->class == PAUTO && n->op == ONAME && !n->used) {
-                       ll->next = nil;
-                       curfn->dcl->end = ll;
-                       break;
-               }
-       }
-
-       // Reassign stack offsets of the locals that are still there.
-       for(ll = curfn->dcl; ll != nil; ll=ll->next) {
-               n = ll->n;
-               if (n->class != PAUTO || n->op != ONAME)
-                       continue;
-
-               dowidth(n->type);
-               w = n->type->width;
-               if(w >= thearch.MAXWIDTH || w < 0)
-                       fatal("bad width");
-               stksize += w;
-               stksize = rnd(stksize, n->type->align);
-               if(haspointers(n->type))
-                       stkptrsize = stksize;
-               if(thearch.thechar == '5' || thearch.thechar == '9')
-                       stksize = rnd(stksize, widthptr);
-               if(stksize >= (1ULL<<31)) {
-                       setlineno(curfn);
-                       yyerror("stack frame too large (>2GB)");
-               }
-               n->stkdelta = -stksize - n->xoffset;
-       }
-       stksize = rnd(stksize, widthreg);
-       stkptrsize = rnd(stkptrsize, widthreg);
-
-       fixautoused(ptxt);
-
-       // The debug information needs accurate offsets on the symbols.
-       for(ll = curfn->dcl; ll != nil; ll=ll->next) {
-               if (ll->n->class != PAUTO || ll->n->op != ONAME)
-                       continue;
-               ll->n->xoffset += ll->n->stkdelta;
-               ll->n->stkdelta = 0;
-       }
-}
-
-static void movelargefn(Node*);
-
-void
-movelarge(NodeList *l)
-{
-       for(; l; l=l->next)
-               if(l->n->op == ODCLFUNC)
-                       movelargefn(l->n);
-}
-
-static void
-movelargefn(Node *fn)
-{
-       NodeList *l;
-       Node *n;
-
-       for(l=fn->dcl; l != nil; l=l->next) {
-               n = l->n;
-               if(n->class == PAUTO && n->type != T && n->type->width > MaxStackVarSize)
-                       addrescapes(n);
-       }
-}
-
-void
-cgen_checknil(Node *n)
-{
-       Node reg;
-
-       if(disable_checknil)
-               return;
-       // Ideally we wouldn't see any integer types here, but we do.
-       if(n->type == T || (!isptr[n->type->etype] && !isint[n->type->etype] && n->type->etype != TUNSAFEPTR)) {
-               dump("checknil", n);
-               fatal("bad checknil");
-       }
-       if(((thearch.thechar == '5' || thearch.thechar == '9') && n->op != OREGISTER) || !n->addable || n->op == OLITERAL) {
-               thearch.regalloc(&reg, types[tptr], n);
-               thearch.cgen(n, &reg);
-               thearch.gins(ACHECKNIL, &reg, N);
-               thearch.regfree(&reg);
-               return;
-       }
-       thearch.gins(ACHECKNIL, n, N);
-}
diff --git a/src/cmd/gc/plive.c b/src/cmd/gc/plive.c
deleted file mode 100644 (file)
index c0d1e57..0000000
+++ /dev/null
@@ -1,2005 +0,0 @@
-// Copyright 2013 The Go Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style
-// license that can be found in the LICENSE file.
-
-// Garbage collector liveness bitmap generation.
-
-// The command line flag -live causes this code to print debug information.
-// The levels are:
-//
-//     -live (aka -live=1): print liveness lists as code warnings at safe points
-//     -live=2: print an assembly listing with liveness annotations
-//     -live=3: print information during each computation phase (much chattier)
-//
-// Each level includes the earlier output as well.
-
-#include <u.h>
-#include <libc.h>
-#include "go.h"
-#include "../ld/textflag.h"
-#include "../../runtime/funcdata.h"
-#include "../../runtime/mgc0.h"
-
-enum {
-       UNVISITED = 0,
-       VISITED = 1,
-};
-
-// An ordinary basic block.
-//
-// Instructions are threaded together in a doubly-linked list.  To iterate in
-// program order follow the link pointer from the first node and stop after the
-// last node has been visited
-//
-//   for(p = bb->first;; p = p->link) {
-//     ...
-//     if(p == bb->last)
-//       break;
-//   }
-//
-// To iterate in reverse program order by following the opt pointer from the
-// last node
-//
-//   for(p = bb->last; p != nil; p = p->opt) {
-//     ...
-//   }
-typedef struct BasicBlock BasicBlock;
-struct BasicBlock {
-       // An array of preceding blocks.  If the length of this array is 0 the
-       // block is probably the start block of the CFG.
-       Array *pred;
-
-       // An array out succeeding blocks.  If the length of this array is zero,
-       // the block probably ends in a return instruction.
-       Array *succ;
-
-       // First instruction in the block.  When part of a fully initialized
-       // control flow graph, the opt member will be nil.
-       Prog *first;
-
-       // Last instruction in the basic block.
-       Prog *last;
-
-       // The reverse post order number.  This value is initialized to -1 and
-       // will be replaced by a non-negative value when the CFG is constructed.
-       // After CFG construction, if rpo is -1 this block is unreachable.
-       int rpo;
-
-       // State to denote whether the block has been visited during a
-       // traversal.
-       int mark;
-       
-       // For use during livenessepilogue.
-       int lastbitmapindex;
-};
-
-// A collection of global state used by liveness analysis.
-typedef struct Liveness Liveness;
-struct Liveness {
-       // A pointer to the node corresponding to the function being analyzed.
-       Node *fn;
-
-       // A linked list of instructions for this function.
-       Prog *ptxt;
-
-       // A list of arguments and local variables in this function.
-       Array *vars;
-
-       // A list of basic blocks that are overlayed on the instruction list.
-       // The blocks are roughly in the same order as the instructions
-       // in the function (first block has TEXT instruction, and so on).
-       Array *cfg;
-
-       // Summary sets of block effects.
-       // The Bvec** is indexed by bb->rpo to yield a single Bvec*.
-       // That bit vector is indexed by variable number (same as lv->vars).
-       //
-       // Computed during livenessprologue using only the content of
-       // individual blocks:
-       //
-       //      uevar: upward exposed variables (used before set in block)
-       //      varkill: killed variables (set in block)
-       //      avarinit: addrtaken variables set or used (proof of initialization)
-       //
-       // Computed during livenesssolve using control flow information:
-       //
-       //      livein: variables live at block entry
-       //      liveout: variables live at block exit
-       //      avarinitany: addrtaken variables possibly initialized at block exit
-       //              (initialized in block or at exit from any predecessor block)
-       //      avarinitall: addrtaken variables certainly initialized at block exit
-       //              (initialized in block or at exit from all predecessor blocks)
-       Bvec **uevar;
-       Bvec **varkill;
-       Bvec **livein;
-       Bvec **liveout;
-       Bvec **avarinit;
-       Bvec **avarinitany;
-       Bvec **avarinitall;
-
-       // An array with a bit vector for each safe point tracking live pointers
-       // in the arguments and locals area, indexed by bb->rpo.
-       Array *argslivepointers;
-       Array *livepointers;
-};
-
-static void*
-xmalloc(uintptr size)
-{
-       void *result;
-
-       result = malloc(size);
-       if(result == nil)
-               fatal("malloc failed");
-       return result;
-}
-
-// Constructs a new basic block containing a single instruction.
-static BasicBlock*
-newblock(Prog *prog)
-{
-       BasicBlock *result;
-
-       if(prog == nil)
-               fatal("newblock: prog cannot be nil");
-       result = xmalloc(sizeof(*result));
-       result->rpo = -1;
-       result->mark = UNVISITED;
-       result->first = prog;
-       result->last = prog;
-       result->pred = arraynew(2, sizeof(BasicBlock*));
-       result->succ = arraynew(2, sizeof(BasicBlock*));
-       return result;
-}
-
-// Frees a basic block and all of its leaf data structures.
-static void
-freeblock(BasicBlock *bb)
-{
-       if(bb == nil)
-               fatal("freeblock: cannot free nil");
-       arrayfree(bb->pred);
-       arrayfree(bb->succ);
-       free(bb);
-}
-
-// Adds an edge between two basic blocks by making from a predecessor of to and
-// to a successor of from.
-static void
-addedge(BasicBlock *from, BasicBlock *to)
-{
-       if(from == nil)
-               fatal("addedge: from is nil");
-       if(to == nil)
-               fatal("addedge: to is nil");
-       arrayadd(from->succ, &to);
-       arrayadd(to->pred, &from);
-}
-
-// Inserts prev before curr in the instruction
-// stream.  Any control flow, such as branches or fall throughs, that target the
-// existing instruction are adjusted to target the new instruction.
-static void
-splicebefore(Liveness *lv, BasicBlock *bb, Prog *prev, Prog *curr)
-{
-       Prog *next, tmp;
-
-       USED(lv);
-
-       // There may be other instructions pointing at curr,
-       // and we want them to now point at prev. Instead of
-       // trying to find all such instructions, swap the contents
-       // so that the problem becomes inserting next after curr.
-       // The "opt" field is the backward link in the linked list.
-
-       // Overwrite curr's data with prev, but keep the list links.
-       tmp = *curr;
-       *curr = *prev;
-       curr->opt = tmp.opt;
-       curr->link = tmp.link;
-       
-       // Overwrite prev (now next) with curr's old data.
-       next = prev;
-       *next = tmp;
-       next->opt = nil;
-       next->link = nil;
-
-       // Now insert next after curr.
-       next->link = curr->link;
-       next->opt = curr;
-       curr->link = next;
-       if(next->link && next->link->opt == curr)
-               next->link->opt = next;
-
-       if(bb->last == curr)
-               bb->last = next;
-}
-
-// A pretty printer for basic blocks.
-static void
-printblock(BasicBlock *bb)
-{
-       BasicBlock *pred;
-       BasicBlock *succ;
-       Prog *prog;
-       int i;
-
-       print("basic block %d\n", bb->rpo);
-       print("\tpred:");
-       for(i = 0; i < arraylength(bb->pred); i++) {
-               pred = *(BasicBlock**)arrayget(bb->pred, i);
-               print(" %d", pred->rpo);
-       }
-       print("\n");
-       print("\tsucc:");
-       for(i = 0; i < arraylength(bb->succ); i++) {
-               succ = *(BasicBlock**)arrayget(bb->succ, i);
-               print(" %d", succ->rpo);
-       }
-       print("\n");
-       print("\tprog:\n");
-       for(prog = bb->first;; prog=prog->link) {
-               print("\t\t%P\n", prog);
-               if(prog == bb->last)
-                       break;
-       }
-}
-
-
-// Iterates over a basic block applying a callback to each instruction.  There
-// are two criteria for termination.  If the end of basic block is reached a
-// value of zero is returned.  If the callback returns a non-zero value, the
-// iteration is stopped and the value of the callback is returned.
-static int
-blockany(BasicBlock *bb, int (*callback)(Prog*))
-{
-       Prog *p;
-       int result;
-
-       for(p = bb->last; p != nil; p = p->opt) {
-               result = (*callback)(p);
-               if(result != 0)
-                       return result;
-       }
-       return 0;
-}
-
-// Collects and returns and array of Node*s for functions arguments and local
-// variables.
-static Array*
-getvariables(Node *fn)
-{
-       Array *result;
-       NodeList *ll;
-
-       result = arraynew(0, sizeof(Node*));
-       for(ll = fn->dcl; ll != nil; ll = ll->next) {
-               if(ll->n->op == ONAME) {
-                       // In order for GODEBUG=gcdead=1 to work, each bitmap needs
-                       // to contain information about all variables covered by the bitmap.
-                       // For local variables, the bitmap only covers the stkptrsize
-                       // bytes in the frame where variables containing pointers live.
-                       // For arguments and results, the bitmap covers all variables,
-                       // so we must include all the variables, even the ones without
-                       // pointers.
-                       //
-                       // The Node.opt field is available for use by optimization passes.
-                       // We use it to hold the index of the node in the variables array, plus 1
-                       // (so that 0 means the Node is not in the variables array).
-                       // Each pass should clear opt when done, but you never know,
-                       // so clear them all ourselves too.
-                       // The Node.curfn field is supposed to be set to the current function
-                       // already, but for some compiler-introduced names it seems not to be,
-                       // so fix that here.
-                       // Later, when we want to find the index of a node in the variables list,
-                       // we will check that n->curfn == curfn and n->opt > 0. Then n->opt - 1
-                       // is the index in the variables list.
-                       ll->n->opt = nil;
-                       ll->n->curfn = curfn;
-                       switch(ll->n->class) {
-                       case PAUTO:
-                               if(haspointers(ll->n->type)) {
-                                       ll->n->opt = (void*)(uintptr)(arraylength(result)+1);
-                                       arrayadd(result, &ll->n);
-                               }
-                               break;
-                       case PPARAM:
-                       case PPARAMOUT:
-                               ll->n->opt = (void*)(uintptr)(arraylength(result)+1);
-                               arrayadd(result, &ll->n);
-                               break;
-                       }
-               }
-       }
-       return result;
-}
-
-// A pretty printer for control flow graphs.  Takes an array of BasicBlock*s.
-static void
-printcfg(Array *cfg)
-{
-       BasicBlock *bb;
-       int32 i;
-
-       for(i = 0; i < arraylength(cfg); i++) {
-               bb = *(BasicBlock**)arrayget(cfg, i);
-               printblock(bb);
-       }
-}
-
-// Assigns a reverse post order number to each connected basic block using the
-// standard algorithm.  Unconnected blocks will not be affected.
-static void
-reversepostorder(BasicBlock *root, int32 *rpo)
-{
-       BasicBlock *bb;
-       int i;
-
-       root->mark = VISITED;
-       for(i = 0; i < arraylength(root->succ); i++) {
-               bb = *(BasicBlock**)arrayget(root->succ, i);
-               if(bb->mark == UNVISITED)
-                       reversepostorder(bb, rpo);
-       }
-       *rpo -= 1;
-       root->rpo = *rpo;
-}
-
-// Comparison predicate used for sorting basic blocks by their rpo in ascending
-// order.
-static int
-blockrpocmp(const void *p1, const void *p2)
-{
-       BasicBlock *bb1;
-       BasicBlock *bb2;
-
-       bb1 = *(BasicBlock**)p1;
-       bb2 = *(BasicBlock**)p2;
-       if(bb1->rpo < bb2->rpo)
-               return -1;
-       if(bb1->rpo > bb2->rpo)
-               return 1;
-       return 0;
-}
-
-// A pattern matcher for call instructions.  Returns true when the instruction
-// is a call to a specific package qualified function name.
-static int
-iscall(Prog *prog, LSym *name)
-{
-       if(prog == nil)
-               fatal("iscall: prog is nil");
-       if(name == nil)
-               fatal("iscall: function name is nil");
-       if(prog->as != ACALL)
-               return 0;
-       return name == prog->to.sym;
-}
-
-// Returns true for instructions that call a runtime function implementing a
-// select communication clause.
-static int
-isselectcommcasecall(Prog *prog)
-{
-       static LSym* names[5];
-       int32 i;
-
-       if(names[0] == nil) {
-               names[0] = linksym(pkglookup("selectsend", runtimepkg));
-               names[1] = linksym(pkglookup("selectrecv", runtimepkg));
-               names[2] = linksym(pkglookup("selectrecv2", runtimepkg));
-               names[3] = linksym(pkglookup("selectdefault", runtimepkg));
-       }
-       for(i = 0; names[i] != nil; i++)
-               if(iscall(prog, names[i]))
-                       return 1;
-       return 0;
-}
-
-// Returns true for call instructions that target runtime·newselect.
-static int
-isnewselect(Prog *prog)
-{
-       static LSym *sym;
-
-       if(sym == nil)
-               sym = linksym(pkglookup("newselect", runtimepkg));
-       return iscall(prog, sym);
-}
-
-// Returns true for call instructions that target runtime·selectgo.
-static int
-isselectgocall(Prog *prog)
-{
-       static LSym *sym;
-
-       if(sym == nil)
-               sym = linksym(pkglookup("selectgo", runtimepkg));
-       return iscall(prog, sym);
-}
-
-static int
-isdeferreturn(Prog *prog)
-{
-       static LSym *sym;
-
-       if(sym == nil)
-               sym = linksym(pkglookup("deferreturn", runtimepkg));
-       return iscall(prog, sym);
-}
-
-// Walk backwards from a runtime·selectgo call up to its immediately dominating
-// runtime·newselect call.  Any successor nodes of communication clause nodes
-// are implicit successors of the runtime·selectgo call node.  The goal of this
-// analysis is to add these missing edges to complete the control flow graph.
-static void
-addselectgosucc(BasicBlock *selectgo)
-{
-       BasicBlock *pred;
-       BasicBlock *succ;
-
-       pred = selectgo;
-       for(;;) {
-               if(arraylength(pred->pred) == 0)
-                       fatal("selectgo does not have a newselect");
-               pred = *(BasicBlock**)arrayget(pred->pred, 0);
-               if(blockany(pred, isselectcommcasecall)) {
-                       // A select comm case block should have exactly one
-                       // successor.
-                       if(arraylength(pred->succ) != 1)
-                               fatal("select comm case has too many successors");
-                       succ = *(BasicBlock**)arrayget(pred->succ, 0);
-                       // Its successor should have exactly two successors.
-                       // The drop through should flow to the selectgo block
-                       // and the branch should lead to the select case
-                       // statements block.
-                       if(arraylength(succ->succ) != 2)
-                               fatal("select comm case successor has too many successors");
-                       // Add the block as a successor of the selectgo block.
-                       addedge(selectgo, succ);
-               }
-               if(blockany(pred, isnewselect)) {
-                       // Reached the matching newselect.
-                       break;
-               }
-       }
-}
-
-// The entry point for the missing selectgo control flow algorithm.  Takes an
-// array of BasicBlock*s containing selectgo calls.
-static void
-fixselectgo(Array *selectgo)
-{
-       BasicBlock *bb;
-       int32 i;
-
-       for(i = 0; i < arraylength(selectgo); i++) {
-               bb = *(BasicBlock**)arrayget(selectgo, i);
-               addselectgosucc(bb);
-       }
-}
-
-// Constructs a control flow graph from a sequence of instructions.  This
-// procedure is complicated by various sources of implicit control flow that are
-// not accounted for using the standard cfg construction algorithm.  Returns an
-// array of BasicBlock*s in control flow graph form (basic blocks ordered by
-// their RPO number).
-static Array*
-newcfg(Prog *firstp)
-{
-       Prog *p;
-       Prog *prev;
-       BasicBlock *bb;
-       Array *cfg;
-       Array *selectgo;
-       int32 i;
-       int32 rpo;
-
-       // Reset the opt field of each prog to nil.  In the first and second
-       // passes, instructions that are labels temporarily use the opt field to
-       // point to their basic block.  In the third pass, the opt field reset
-       // to point to the predecessor of an instruction in its basic block.
-       for(p = firstp; p != P; p = p->link)
-               p->opt = nil;
-
-       // Allocate an array to remember where we have seen selectgo calls.
-       // These blocks will be revisited to add successor control flow edges.
-       selectgo = arraynew(0, sizeof(BasicBlock*));
-
-       // Loop through all instructions identifying branch targets
-       // and fall-throughs and allocate basic blocks.
-       cfg = arraynew(0, sizeof(BasicBlock*));
-       bb = newblock(firstp);
-       arrayadd(cfg, &bb);
-       for(p = firstp; p != P; p = p->link) {
-               if(p->to.type == TYPE_BRANCH) {
-                       if(p->to.u.branch == nil)
-                               fatal("prog branch to nil");
-                       if(p->to.u.branch->opt == nil) {
-                               p->to.u.branch->opt = newblock(p->to.u.branch);
-                               arrayadd(cfg, &p->to.u.branch->opt);
-                       }
-                       if(p->as != AJMP && p->link != nil && p->link->opt == nil) {
-                               p->link->opt = newblock(p->link);
-                               arrayadd(cfg, &p->link->opt);
-                       }
-               } else if(isselectcommcasecall(p) || isselectgocall(p)) {
-                       // Accommodate implicit selectgo control flow.
-                       if(p->link->opt == nil) {
-                               p->link->opt = newblock(p->link);
-                               arrayadd(cfg, &p->link->opt);
-                       }
-               }
-       }
-
-       // Loop through all basic blocks maximally growing the list of
-       // contained instructions until a label is reached.  Add edges
-       // for branches and fall-through instructions.
-       for(i = 0; i < arraylength(cfg); i++) {
-               bb = *(BasicBlock**)arrayget(cfg, i);
-               for(p = bb->last; p != nil; p = p->link) {
-                       if(p->opt != nil && p != bb->last)
-                               break;
-                       bb->last = p;
-
-                       // Stop before an unreachable RET, to avoid creating
-                       // unreachable control flow nodes.
-                       if(p->link != nil && p->link->as == ARET && p->link->mode == 1)
-                               break;
-
-                       // Collect basic blocks with selectgo calls.
-                       if(isselectgocall(p))
-                               arrayadd(selectgo, &bb);
-               }
-               if(bb->last->to.type == TYPE_BRANCH)
-                       addedge(bb, bb->last->to.u.branch->opt);
-               if(bb->last->link != nil) {
-                       // Add a fall-through when the instruction is
-                       // not an unconditional control transfer.
-                       if(bb->last->as != AJMP && bb->last->as != ARET && bb->last->as != AUNDEF)
-                               addedge(bb, bb->last->link->opt);
-               }
-       }
-
-       // Add back links so the instructions in a basic block can be traversed
-       // backward.  This is the final state of the instruction opt field.
-       for(i = 0; i < arraylength(cfg); i++) {
-               bb = *(BasicBlock**)arrayget(cfg, i);
-               p = bb->first;
-               prev = nil;
-               for(;;) {
-                       p->opt = prev;
-                       if(p == bb->last)
-                               break;
-                       prev = p;
-                       p = p->link;
-               }
-       }
-
-       // Add missing successor edges to the selectgo blocks.
-       if(arraylength(selectgo))
-               fixselectgo(selectgo);
-       arrayfree(selectgo);
-
-       // Find a depth-first order and assign a depth-first number to
-       // all basic blocks.
-       for(i = 0; i < arraylength(cfg); i++) {
-               bb = *(BasicBlock**)arrayget(cfg, i);
-               bb->mark = UNVISITED;
-       }
-       bb = *(BasicBlock**)arrayget(cfg, 0);
-       rpo = arraylength(cfg);
-       reversepostorder(bb, &rpo);
-
-       // Sort the basic blocks by their depth first number.  The
-       // array is now a depth-first spanning tree with the first
-       // node being the root.
-       arraysort(cfg, blockrpocmp);
-       bb = *(BasicBlock**)arrayget(cfg, 0);
-
-       // Unreachable control flow nodes are indicated by a -1 in the rpo
-       // field.  If we see these nodes something must have gone wrong in an
-       // upstream compilation phase.
-       if(bb->rpo == -1) {
-               print("newcfg: unreachable basic block for %P\n", bb->last);
-               printcfg(cfg);
-               fatal("newcfg: invalid control flow graph");
-       }
-
-       return cfg;
-}
-
-// Frees a control flow graph (an array of BasicBlock*s) and all of its leaf
-// data structures.
-static void
-freecfg(Array *cfg)
-{
-       BasicBlock *bb;
-       BasicBlock *bb0;
-       Prog *p;
-       int32 i;
-       int32 n;
-
-       n = arraylength(cfg);
-       if(n > 0) {
-               bb0 = *(BasicBlock**)arrayget(cfg, 0);
-               for(p = bb0->first; p != P; p = p->link) {
-                       p->opt = nil;
-               }
-               for(i = 0; i < n; i++) {
-                       bb = *(BasicBlock**)arrayget(cfg, i);
-                       freeblock(bb);
-               }
-       }
-       arrayfree(cfg);
-}
-
-// Returns true if the node names a variable that is otherwise uninteresting to
-// the liveness computation.
-static int
-isfunny(Node *node)
-{
-       char *names[] = { ".fp", ".args", nil };
-       int i;
-
-       if(node->sym != nil && node->sym->name != nil)
-               for(i = 0; names[i] != nil; i++)
-                       if(strcmp(node->sym->name, names[i]) == 0)
-                               return 1;
-       return 0;
-}
-
-// Computes the effects of an instruction on a set of
-// variables.  The vars argument is an array of Node*s.
-//
-// The output vectors give bits for variables:
-//     uevar - used by this instruction
-//     varkill - killed by this instruction
-//             for variables without address taken, means variable was set
-//             for variables with address taken, means variable was marked dead
-//     avarinit - initialized or referred to by this instruction,
-//             only for variables with address taken but not escaping to heap
-//
-// The avarinit output serves as a signal that the data has been
-// initialized, because any use of a variable must come after its
-// initialization.
-static void
-progeffects(Prog *prog, Array *vars, Bvec *uevar, Bvec *varkill, Bvec *avarinit)
-{
-       ProgInfo info;
-       Addr *from;
-       Addr *to;
-       Node *node;
-       int32 i;
-       int32 pos;
-
-       bvresetall(uevar);
-       bvresetall(varkill);
-       bvresetall(avarinit);
-
-       thearch.proginfo(&info, prog);
-       if(prog->as == ARET) {
-               // Return instructions implicitly read all the arguments.  For
-               // the sake of correctness, out arguments must be read.  For the
-               // sake of backtrace quality, we read in arguments as well.
-               //
-               // A return instruction with a p->to is a tail return, which brings
-               // the stack pointer back up (if it ever went down) and then jumps
-               // to a new function entirely. That form of instruction must read
-               // all the parameters for correctness, and similarly it must not
-               // read the out arguments - they won't be set until the new
-               // function runs.
-               for(i = 0; i < arraylength(vars); i++) {
-                       node = *(Node**)arrayget(vars, i);
-                       switch(node->class & ~PHEAP) {
-                       case PPARAM:
-                               bvset(uevar, i);
-                               break;
-                       case PPARAMOUT:
-                               // If the result had its address taken, it is being tracked
-                               // by the avarinit code, which does not use uevar.
-                               // If we added it to uevar too, we'd not see any kill
-                               // and decide that the varible was live entry, which it is not.
-                               // So only use uevar in the non-addrtaken case.
-                               // The p->to.type == thearch.D_NONE limits the bvset to
-                               // non-tail-call return instructions; see note above
-                               // the for loop for details.
-                               if(!node->addrtaken && prog->to.type == TYPE_NONE)
-                                       bvset(uevar, i);
-                               break;
-                       }
-               }
-               return;
-       }
-       if(prog->as == ATEXT) {
-               // A text instruction marks the entry point to a function and
-               // the definition point of all in arguments.
-               for(i = 0; i < arraylength(vars); i++) {
-                       node = *(Node**)arrayget(vars, i);
-                       switch(node->class & ~PHEAP) {
-                       case PPARAM:
-                               if(node->addrtaken)
-                                       bvset(avarinit, i);
-                               bvset(varkill, i);
-                               break;
-                       }
-               }
-               return;
-       }
-       if(info.flags & (LeftRead | LeftWrite | LeftAddr)) {
-               from = &prog->from;
-               if (from->node != nil && from->sym != nil && ((Node*)(from->node))->curfn == curfn) {
-                       switch(((Node*)(from->node))->class & ~PHEAP) {
-                       case PAUTO:
-                       case PPARAM:
-                       case PPARAMOUT:
-                               pos = (int)(uintptr)((Node*)(from->node))->opt - 1; // index in vars
-                               if(pos == -1)
-                                       goto Next;
-                               if(pos >= arraylength(vars) || *(Node**)arrayget(vars, pos) != from->node)
-                                       fatal("bad bookkeeping in liveness %N %d", from->node, pos);
-                               if(((Node*)(from->node))->addrtaken) {
-                                       bvset(avarinit, pos);
-                               } else {
-                                       if(info.flags & (LeftRead | LeftAddr))
-                                               bvset(uevar, pos);
-                                       if(info.flags & LeftWrite)
-                                               if(from->node != nil && !isfat(((Node*)(from->node))->type))
-                                                       bvset(varkill, pos);
-                               }
-                       }
-               }
-       }
-Next:
-       if(info.flags & (RightRead | RightWrite | RightAddr)) {
-               to = &prog->to;
-               if (to->node != nil && to->sym != nil && ((Node*)(to->node))->curfn == curfn) {
-                       switch(((Node*)(to->node))->class & ~PHEAP) {
-                       case PAUTO:
-                       case PPARAM:
-                       case PPARAMOUT:
-                               pos = (int)(uintptr)((Node*)(to->node))->opt - 1; // index in vars
-                               if(pos == -1)
-                                       goto Next1;
-                               if(pos >= arraylength(vars) || *(Node**)arrayget(vars, pos) != to->node)
-                                       fatal("bad bookkeeping in liveness %N %d", to->node, pos);
-                               if(((Node*)(to->node))->addrtaken) {
-                                       if(prog->as != AVARKILL)
-                                               bvset(avarinit, pos);
-                                       if(prog->as == AVARDEF || prog->as == AVARKILL)
-                                               bvset(varkill, pos);
-                               } else {
-                                       // RightRead is a read, obviously.
-                                       // RightAddr by itself is also implicitly a read.
-                                       //
-                                       // RightAddr|RightWrite means that the address is being taken
-                                       // but only so that the instruction can write to the value.
-                                       // It is not a read. It is equivalent to RightWrite except that
-                                       // having the RightAddr bit set keeps the registerizer from
-                                       // trying to substitute a register for the memory location.
-                                       if((info.flags & RightRead) || (info.flags & (RightAddr|RightWrite)) == RightAddr)
-                                               bvset(uevar, pos);
-                                       if(info.flags & RightWrite)
-                                               if(to->node != nil && (!isfat(((Node*)(to->node))->type) || prog->as == AVARDEF))
-                                                       bvset(varkill, pos);
-                               }
-                       }
-               }
-       }
-Next1:;
-}
-
-// Constructs a new liveness structure used to hold the global state of the
-// liveness computation.  The cfg argument is an array of BasicBlock*s and the
-// vars argument is an array of Node*s.
-static Liveness*
-newliveness(Node *fn, Prog *ptxt, Array *cfg, Array *vars)
-{
-       Liveness *result;
-       int32 i;
-       int32 nblocks;
-       int32 nvars;
-
-       result = xmalloc(sizeof(*result));
-       result->fn = fn;
-       result->ptxt = ptxt;
-       result->cfg = cfg;
-       result->vars = vars;
-
-       nblocks = arraylength(cfg);
-       result->uevar = xmalloc(sizeof(Bvec*) * nblocks);
-       result->varkill = xmalloc(sizeof(Bvec*) * nblocks);
-       result->livein = xmalloc(sizeof(Bvec*) * nblocks);
-       result->liveout = xmalloc(sizeof(Bvec*) * nblocks);
-       result->avarinit = xmalloc(sizeof(Bvec*) * nblocks);
-       result->avarinitany = xmalloc(sizeof(Bvec*) * nblocks);
-       result->avarinitall = xmalloc(sizeof(Bvec*) * nblocks);
-
-       nvars = arraylength(vars);
-       for(i = 0; i < nblocks; i++) {
-               result->uevar[i] = bvalloc(nvars);
-               result->varkill[i] = bvalloc(nvars);
-               result->livein[i] = bvalloc(nvars);
-               result->liveout[i] = bvalloc(nvars);
-               result->avarinit[i] = bvalloc(nvars);
-               result->avarinitany[i] = bvalloc(nvars);
-               result->avarinitall[i] = bvalloc(nvars);
-       }
-
-       result->livepointers = arraynew(0, sizeof(Bvec*));
-       result->argslivepointers = arraynew(0, sizeof(Bvec*));
-       return result;
-}
-
-// Frees the liveness structure and all of its leaf data structures.
-static void
-freeliveness(Liveness *lv)
-{
-       int32 i;
-
-       if(lv == nil)
-               fatal("freeliveness: cannot free nil");
-
-       for(i = 0; i < arraylength(lv->livepointers); i++)
-               free(*(Bvec**)arrayget(lv->livepointers, i));
-       arrayfree(lv->livepointers);
-
-       for(i = 0; i < arraylength(lv->argslivepointers); i++)
-               free(*(Bvec**)arrayget(lv->argslivepointers, i));
-       arrayfree(lv->argslivepointers);
-
-       for(i = 0; i < arraylength(lv->cfg); i++) {
-               free(lv->uevar[i]);
-               free(lv->varkill[i]);
-               free(lv->livein[i]);
-               free(lv->liveout[i]);
-               free(lv->avarinit[i]);
-               free(lv->avarinitany[i]);
-               free(lv->avarinitall[i]);
-       }
-
-       free(lv->uevar);
-       free(lv->varkill);
-       free(lv->livein);
-       free(lv->liveout);
-       free(lv->avarinit);
-       free(lv->avarinitany);
-       free(lv->avarinitall);
-
-       free(lv);
-}
-
-static void
-printeffects(Prog *p, Bvec *uevar, Bvec *varkill, Bvec *avarinit)
-{
-       print("effects of %P", p);
-       print("\nuevar: ");
-       bvprint(uevar);
-       print("\nvarkill: ");
-       bvprint(varkill);
-       print("\navarinit: ");
-       bvprint(avarinit);
-       print("\n");
-}
-
-// Pretty print a variable node.  Uses Pascal like conventions for pointers and
-// addresses to avoid confusing the C like conventions used in the node variable
-// names.
-static void
-printnode(Node *node)
-{
-       char *p;
-       char *a;
-
-       p = "";
-       if(haspointers(node->type))
-               p = "^";
-       a = "";
-       if(node->addrtaken)
-               a = "@";
-       print(" %N%s%s", node, p, a);
-}
-
-// Pretty print a list of variables.  The vars argument is an array of Node*s.
-static void
-printvars(char *name, Bvec *bv, Array *vars)
-{
-       int32 i;
-
-       print("%s:", name);
-       for(i = 0; i < arraylength(vars); i++)
-               if(bvget(bv, i))
-                       printnode(*(Node**)arrayget(vars, i));
-       print("\n");
-}
-
-// Prints a basic block annotated with the information computed by liveness
-// analysis.
-static void
-livenessprintblock(Liveness *lv, BasicBlock *bb)
-{
-       BasicBlock *pred;
-       BasicBlock *succ;
-       Prog *prog;
-       Bvec *live;
-       int i;
-       int32 pos;
-
-       print("basic block %d\n", bb->rpo);
-
-       print("\tpred:");
-       for(i = 0; i < arraylength(bb->pred); i++) {
-               pred = *(BasicBlock**)arrayget(bb->pred, i);
-               print(" %d", pred->rpo);
-       }
-       print("\n");
-
-       print("\tsucc:");
-       for(i = 0; i < arraylength(bb->succ); i++) {
-               succ = *(BasicBlock**)arrayget(bb->succ, i);
-               print(" %d", succ->rpo);
-       }
-       print("\n");
-
-       printvars("\tuevar", lv->uevar[bb->rpo], lv->vars);
-       printvars("\tvarkill", lv->varkill[bb->rpo], lv->vars);
-       printvars("\tlivein", lv->livein[bb->rpo], lv->vars);
-       printvars("\tliveout", lv->liveout[bb->rpo], lv->vars);
-       printvars("\tavarinit", lv->avarinit[bb->rpo], lv->vars);
-       printvars("\tavarinitany", lv->avarinitany[bb->rpo], lv->vars);
-       printvars("\tavarinitall", lv->avarinitall[bb->rpo], lv->vars);
-
-       print("\tprog:\n");
-       for(prog = bb->first;; prog = prog->link) {
-               print("\t\t%P", prog);
-               if(prog->as == APCDATA && prog->from.offset == PCDATA_StackMapIndex) {
-                       pos = prog->to.offset;
-                       live = *(Bvec**)arrayget(lv->livepointers, pos);
-                       print(" ");
-                       bvprint(live);
-               }
-               print("\n");
-               if(prog == bb->last)
-                       break;
-       }
-}
-
-// Prints a control flow graph annotated with any information computed by
-// liveness analysis.
-static void
-livenessprintcfg(Liveness *lv)
-{
-       BasicBlock *bb;
-       int32 i;
-
-       for(i = 0; i < arraylength(lv->cfg); i++) {
-               bb = *(BasicBlock**)arrayget(lv->cfg, i);
-               livenessprintblock(lv, bb);
-       }
-}
-
-static void
-checkauto(Node *fn, Prog *p, Node *n)
-{
-       NodeList *l;
-
-       for(l = fn->dcl; l != nil; l = l->next)
-               if(l->n->op == ONAME && l->n->class == PAUTO && l->n == n)
-                       return;
-
-       if(n == nil) {
-               print("%L: checkauto %N: nil node in %P\n", p->lineno, curfn, p);
-               return;
-       }
-       print("checkauto %N: %N (%p; class=%d) not found in %P\n", curfn, n, n, n->class, p);
-       for(l = fn->dcl; l != nil; l = l->next)
-               print("\t%N (%p; class=%d)\n", l->n, l->n, l->n->class);
-       yyerror("checkauto: invariant lost");
-}
-
-static void
-checkparam(Node *fn, Prog *p, Node *n)
-{
-       NodeList *l;
-       Node *a;
-       int class;
-
-       if(isfunny(n))
-               return;
-       for(l = fn->dcl; l != nil; l = l->next) {
-               a = l->n;
-               class = a->class & ~PHEAP;
-               if(a->op == ONAME && (class == PPARAM || class == PPARAMOUT) && a == n)
-                       return;
-       }
-
-       print("checkparam %N: %N (%p; class=%d) not found in %P\n", curfn, n, n, n->class, p);
-       for(l = fn->dcl; l != nil; l = l->next)
-               print("\t%N (%p; class=%d)\n", l->n, l->n, l->n->class);
-       yyerror("checkparam: invariant lost");
-}
-
-static void
-checkprog(Node *fn, Prog *p)
-{
-       if(p->from.name == NAME_AUTO)
-               checkauto(fn, p, p->from.node);
-       if(p->from.name == NAME_PARAM)
-               checkparam(fn, p, p->from.node);
-       if(p->to.name == NAME_AUTO)
-               checkauto(fn, p, p->to.node);
-       if(p->to.name == NAME_PARAM)
-               checkparam(fn, p, p->to.node);
-}
-
-// Check instruction invariants.  We assume that the nodes corresponding to the
-// sources and destinations of memory operations will be declared in the
-// function.  This is not strictly true, as is the case for the so-called funny
-// nodes and there are special cases to skip over that stuff.  The analysis will
-// fail if this invariant blindly changes.
-static void
-checkptxt(Node *fn, Prog *firstp)
-{
-       Prog *p;
-
-       if(debuglive == 0)
-               return;
-
-       for(p = firstp; p != P; p = p->link) {
-               if(0)
-                       print("analyzing '%P'\n", p);
-               if(p->as != ADATA && p->as != AGLOBL && p->as != ATYPE)
-                       checkprog(fn, p);
-       }
-}
-
-// NOTE: The bitmap for a specific type t should be cached in t after the first run
-// and then simply copied into bv at the correct offset on future calls with
-// the same type t. On https://rsc.googlecode.com/hg/testdata/slow.go, twobitwalktype1
-// accounts for 40% of the 6g execution time.
-void
-twobitwalktype1(Type *t, vlong *xoffset, Bvec *bv)
-{
-       vlong fieldoffset;
-       vlong i;
-       vlong o;
-       Type *t1;
-
-       if(t->align > 0 && (*xoffset & (t->align - 1)) != 0)
-               fatal("twobitwalktype1: invalid initial alignment, %T", t);
-
-       switch(t->etype) {
-       case TINT8:
-       case TUINT8:
-       case TINT16:
-       case TUINT16:
-       case TINT32:
-       case TUINT32:
-       case TINT64:
-       case TUINT64:
-       case TINT:
-       case TUINT:
-       case TUINTPTR:
-       case TBOOL:
-       case TFLOAT32:
-       case TFLOAT64:
-       case TCOMPLEX64:
-       case TCOMPLEX128:
-               for(i = 0; i < t->width; i++) {
-                       bvset(bv, ((*xoffset + i) / widthptr) * BitsPerPointer); // 1 = live scalar (BitsScalar)
-               }
-               *xoffset += t->width;
-               break;
-
-       case TPTR32:
-       case TPTR64:
-       case TUNSAFEPTR:
-       case TFUNC:
-       case TCHAN:
-       case TMAP:
-               if((*xoffset & (widthptr-1)) != 0)
-                       fatal("twobitwalktype1: invalid alignment, %T", t);
-               bvset(bv, (*xoffset / widthptr) * BitsPerPointer + 1); // 2 = live ptr (BitsPointer)
-               *xoffset += t->width;
-               break;
-
-       case TSTRING:
-               // 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 (BitsPointer)
-               *xoffset += t->width;
-               break;
-
-       case TINTER:
-               // struct { Itab *tab;  union { void *ptr, uintptr val } data; }
-               // or, when isnilinter(t)==true:
-               // 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 + 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;
-
-       case TARRAY:
-               // The value of t->bound is -1 for slices types and >0 for
-               // for fixed array types.  All other values are invalid.
-               if(t->bound < -1)
-                       fatal("twobitwalktype1: invalid bound, %T", t);
-               if(isslice(t)) {
-                       // 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 (BitsPointer)
-                       *xoffset += t->width;
-               } else
-                       for(i = 0; i < t->bound; i++)
-                               twobitwalktype1(t->type, xoffset, bv);
-               break;
-
-       case TSTRUCT:
-               o = 0;
-               for(t1 = t->type; t1 != T; t1 = t1->down) {
-                       fieldoffset = t1->width;
-                       *xoffset += fieldoffset - o;
-                       twobitwalktype1(t1->type, xoffset, bv);
-                       o = fieldoffset + t1->type->width;
-               }
-               *xoffset += t->width - o;
-               break;
-
-       default:
-               fatal("twobitwalktype1: unexpected type, %T", t);
-       }
-}
-
-// Returns the number of words of local variables.
-static int32
-localswords(void)
-{
-       return stkptrsize / widthptr;
-}
-
-// Returns the number of words of in and out arguments.
-static int32
-argswords(void)
-{
-       return curfn->type->argwid / widthptr;
-}
-
-// Generates live pointer value maps for arguments and local variables.  The
-// this argument and the in arguments are always assumed live.  The vars
-// argument is an array of Node*s.
-static void
-twobitlivepointermap(Liveness *lv, Bvec *liveout, Array *vars, Bvec *args, Bvec *locals)
-{
-       Node *node;
-       Type *thisargtype;
-       Type *inargtype;
-       vlong xoffset;
-       int32 i;
-
-       for(i = 0; (i = bvnext(liveout, i)) >= 0; i++) {
-               node = *(Node**)arrayget(vars, i);
-               switch(node->class) {
-               case PAUTO:
-                       xoffset = node->xoffset + stkptrsize;
-                       twobitwalktype1(node->type, &xoffset, locals);
-                       break;
-               case PPARAM:
-               case PPARAMOUT:
-                       xoffset = node->xoffset;
-                       twobitwalktype1(node->type, &xoffset, args);
-                       break;
-               }
-       }
-       
-       // The node list only contains declared names.
-       // If the receiver or arguments are unnamed, they will be omitted
-       // from the list above. Preserve those values - even though they are unused -
-       // in order to keep their addresses live for use in stack traces.
-       thisargtype = getthisx(lv->fn->type);
-       if(thisargtype != nil) {
-               xoffset = 0;
-               twobitwalktype1(thisargtype, &xoffset, args);
-       }
-       inargtype = getinargx(lv->fn->type);
-       if(inargtype != nil) {
-               xoffset = 0;
-               twobitwalktype1(inargtype, &xoffset, args);
-       }
-}
-
-// Construct a disembodied instruction.
-static Prog*
-unlinkedprog(int as)
-{
-       Prog *p;
-
-       p = mal(sizeof(*p));
-       clearp(p);
-       p->as = as;
-       return p;
-}
-
-// Construct a new PCDATA instruction associated with and for the purposes of
-// covering an existing instruction.
-static Prog*
-newpcdataprog(Prog *prog, int32 index)
-{
-       Node from, to;
-       Prog *pcdata;
-
-       nodconst(&from, types[TINT32], PCDATA_StackMapIndex);
-       nodconst(&to, types[TINT32], index);
-       pcdata = unlinkedprog(APCDATA);
-       pcdata->lineno = prog->lineno;
-       naddr(&from, &pcdata->from, 0);
-       naddr(&to, &pcdata->to, 0);
-       return pcdata;
-}
-
-// Returns true for instructions that are safe points that must be annotated
-// with liveness information.
-static int
-issafepoint(Prog *prog)
-{
-       return prog->as == ATEXT || prog->as == ACALL;
-}
-
-// Initializes the sets for solving the live variables.  Visits all the
-// instructions in each basic block to summarizes the information at each basic
-// block
-static void
-livenessprologue(Liveness *lv)
-{
-       BasicBlock *bb;
-       Bvec *uevar, *varkill, *avarinit;
-       Prog *p;
-       int32 i;
-       int32 nvars;
-
-       nvars = arraylength(lv->vars);
-       uevar = bvalloc(nvars);
-       varkill = bvalloc(nvars);
-       avarinit = bvalloc(nvars);
-       for(i = 0; i < arraylength(lv->cfg); i++) {
-               bb = *(BasicBlock**)arrayget(lv->cfg, i);
-               // Walk the block instructions backward and update the block
-               // effects with the each prog effects.
-               for(p = bb->last; p != nil; p = p->opt) {
-                       progeffects(p, lv->vars, uevar, varkill, avarinit);
-                       if(debuglive >= 3)
-                               printeffects(p, uevar, varkill, avarinit);
-                       bvor(lv->varkill[i], lv->varkill[i], varkill);
-                       bvandnot(lv->uevar[i], lv->uevar[i], varkill);
-                       bvor(lv->uevar[i], lv->uevar[i], uevar);                        
-               }
-               // Walk the block instructions forward to update avarinit bits.
-               // avarinit describes the effect at the end of the block, not the beginning.
-               bvresetall(varkill);
-               for(p = bb->first;; p = p->link) {
-                       progeffects(p, lv->vars, uevar, varkill, avarinit);
-                       if(debuglive >= 3)
-                               printeffects(p, uevar, varkill, avarinit);
-                       bvandnot(lv->avarinit[i], lv->avarinit[i], varkill);
-                       bvor(lv->avarinit[i], lv->avarinit[i], avarinit);
-                       if(p == bb->last)
-                               break;
-               }
-       }
-       free(uevar);
-       free(varkill);
-       free(avarinit);
-}
-
-// Solve the liveness dataflow equations.
-static void
-livenesssolve(Liveness *lv)
-{
-       BasicBlock *bb, *succ, *pred;
-       Bvec *newlivein, *newliveout, *any, *all;
-       int32 rpo, i, j, change;
-
-       // These temporary bitvectors exist to avoid successive allocations and
-       // frees within the loop.
-       newlivein = bvalloc(arraylength(lv->vars));
-       newliveout = bvalloc(arraylength(lv->vars));
-       any = bvalloc(arraylength(lv->vars));
-       all = bvalloc(arraylength(lv->vars));
-
-       // Push avarinitall, avarinitany forward.
-       // avarinitall says the addressed var is initialized along all paths reaching the block exit.
-       // avarinitany says the addressed var is initialized along some path reaching the block exit.
-       for(i = 0; i < arraylength(lv->cfg); i++) {
-               bb = *(BasicBlock**)arrayget(lv->cfg, i);
-               rpo = bb->rpo;
-               if(i == 0)
-                       bvcopy(lv->avarinitall[rpo], lv->avarinit[rpo]);
-               else {
-                       bvresetall(lv->avarinitall[rpo]);
-                       bvnot(lv->avarinitall[rpo]);
-               }
-               bvcopy(lv->avarinitany[rpo], lv->avarinit[rpo]);
-       }
-
-       change = 1;
-       while(change != 0) {
-               change = 0;
-               for(i = 0; i < arraylength(lv->cfg); i++) {
-                       bb = *(BasicBlock**)arrayget(lv->cfg, i);
-                       rpo = bb->rpo;
-                       bvresetall(any);
-                       bvresetall(all);
-                       for(j = 0; j < arraylength(bb->pred); j++) {
-                               pred = *(BasicBlock**)arrayget(bb->pred, j);
-                               if(j == 0) {
-                                       bvcopy(any, lv->avarinitany[pred->rpo]);
-                                       bvcopy(all, lv->avarinitall[pred->rpo]);
-                               } else {
-                                       bvor(any, any, lv->avarinitany[pred->rpo]);
-                                       bvand(all, all, lv->avarinitall[pred->rpo]);
-                               }
-                       }
-                       bvandnot(any, any, lv->varkill[rpo]);
-                       bvandnot(all, all, lv->varkill[rpo]);
-                       bvor(any, any, lv->avarinit[rpo]);
-                       bvor(all, all, lv->avarinit[rpo]);
-                       if(bvcmp(any, lv->avarinitany[rpo])) {
-                               change = 1;
-                               bvcopy(lv->avarinitany[rpo], any);
-                       }
-                       if(bvcmp(all, lv->avarinitall[rpo])) {
-                               change = 1;
-                               bvcopy(lv->avarinitall[rpo], all);
-                       }
-               }
-       }
-
-       // Iterate through the blocks in reverse round-robin fashion.  A work
-       // queue might be slightly faster.  As is, the number of iterations is
-       // so low that it hardly seems to be worth the complexity.
-       change = 1;
-       while(change != 0) {
-               change = 0;
-               // Walk blocks in the general direction of propagation.  This
-               // improves convergence.
-               for(i = arraylength(lv->cfg) - 1; i >= 0; i--) {
-                       // A variable is live on output from this block
-                       // if it is live on input to some successor.
-                       //
-                       // out[b] = \bigcup_{s \in succ[b]} in[s]
-                       bb = *(BasicBlock**)arrayget(lv->cfg, i);
-                       rpo = bb->rpo;
-                       bvresetall(newliveout);
-                       for(j = 0; j < arraylength(bb->succ); j++) {
-                               succ = *(BasicBlock**)arrayget(bb->succ, j);
-                               bvor(newliveout, newliveout, lv->livein[succ->rpo]);
-                       }
-                       if(bvcmp(lv->liveout[rpo], newliveout)) {
-                               change = 1;
-                               bvcopy(lv->liveout[rpo], newliveout);
-                       }
-
-                       // A variable is live on input to this block
-                       // if it is live on output from this block and
-                       // not set by the code in this block.
-                       //
-                       // in[b] = uevar[b] \cup (out[b] \setminus varkill[b])
-                       bvandnot(newlivein, lv->liveout[rpo], lv->varkill[rpo]);
-                       bvor(lv->livein[rpo], newlivein, lv->uevar[rpo]);
-               }
-       }
-
-       free(newlivein);
-       free(newliveout);
-       free(any);
-       free(all);
-}
-
-// This function is slow but it is only used for generating debug prints.
-// Check whether n is marked live in args/locals.
-static int
-islive(Node *n, Bvec *args, Bvec *locals)
-{
-       int i;
-
-       switch(n->class) {
-       case PPARAM:
-       case PPARAMOUT:
-               for(i = 0; i < n->type->width/widthptr*BitsPerPointer; i++)
-                       if(bvget(args, n->xoffset/widthptr*BitsPerPointer + i))
-                               return 1;
-               break;
-       case PAUTO:
-               for(i = 0; i < n->type->width/widthptr*BitsPerPointer; i++)
-                       if(bvget(locals, (n->xoffset + stkptrsize)/widthptr*BitsPerPointer + i))
-                               return 1;
-               break;
-       }
-       return 0;
-}
-
-// Visits all instructions in a basic block and computes a bit vector of live
-// variables at each safe point locations.
-static void
-livenessepilogue(Liveness *lv)
-{
-       BasicBlock *bb, *pred;
-       Bvec *ambig, *livein, *liveout, *uevar, *varkill, *args, *locals, *avarinit, *any, *all;
-       Node *n;
-       Prog *p, *next;
-       int32 i, j, numlive, startmsg, nmsg, nvars, pos;
-       vlong xoffset;
-       char **msg;
-       Fmt fmt;
-
-       nvars = arraylength(lv->vars);
-       livein = bvalloc(nvars);
-       liveout = bvalloc(nvars);
-       uevar = bvalloc(nvars);
-       varkill = bvalloc(nvars);
-       avarinit = bvalloc(nvars);
-       any = bvalloc(nvars);
-       all = bvalloc(nvars);
-       ambig = bvalloc(localswords() * BitsPerPointer);
-       msg = nil;
-       nmsg = 0;
-       startmsg = 0;
-
-       for(i = 0; i < arraylength(lv->cfg); i++) {
-               bb = *(BasicBlock**)arrayget(lv->cfg, i);
-               
-               // Compute avarinitany and avarinitall for entry to block.
-               // This duplicates information known during livenesssolve
-               // but avoids storing two more vectors for each block.
-               bvresetall(any);
-               bvresetall(all);
-               for(j = 0; j < arraylength(bb->pred); j++) {
-                       pred = *(BasicBlock**)arrayget(bb->pred, j);
-                       if(j == 0) {
-                               bvcopy(any, lv->avarinitany[pred->rpo]);
-                               bvcopy(all, lv->avarinitall[pred->rpo]);
-                       } else {
-                               bvor(any, any, lv->avarinitany[pred->rpo]);
-                               bvand(all, all, lv->avarinitall[pred->rpo]);
-                       }
-               }
-
-               // Walk forward through the basic block instructions and
-               // allocate liveness maps for those instructions that need them.
-               // Seed the maps with information about the addrtaken variables.
-               for(p = bb->first;; p = p->link) {
-                       progeffects(p, lv->vars, uevar, varkill, avarinit);
-                       bvandnot(any, any, varkill);
-                       bvandnot(all, all, varkill);
-                       bvor(any, any, avarinit);
-                       bvor(all, all, avarinit);
-
-                       if(issafepoint(p)) {
-                               // Annotate ambiguously live variables so that they can
-                               // be zeroed at function entry.
-                               // livein and liveout are dead here and used as temporaries.
-                               bvresetall(livein);
-                               bvandnot(liveout, any, all);
-                               if(!bvisempty(liveout)) {
-                                       for(pos = 0; pos < liveout->n; pos++) {
-                                               if(!bvget(liveout, pos))
-                                                       continue;
-                                               bvset(all, pos); // silence future warnings in this block
-                                               n = *(Node**)arrayget(lv->vars, pos);
-                                               if(!n->needzero) {
-                                                       n->needzero = 1;
-                                                       if(debuglive >= 1)
-                                                               warnl(p->lineno, "%N: %lN is ambiguously live", curfn->nname, n);
-                                                       // Record in 'ambiguous' bitmap.
-                                                       xoffset = n->xoffset + stkptrsize;
-                                                       twobitwalktype1(n->type, &xoffset, ambig);
-                                               }
-                                       }
-                               }
-       
-                               // Allocate a bit vector for each class and facet of
-                               // value we are tracking.
-       
-                               // Live stuff first.
-                               args = bvalloc(argswords() * BitsPerPointer);
-                               arrayadd(lv->argslivepointers, &args);
-                               locals = bvalloc(localswords() * BitsPerPointer);
-                               arrayadd(lv->livepointers, &locals);
-
-                               if(debuglive >= 3) {
-                                       print("%P\n", p);
-                                       printvars("avarinitany", any, lv->vars);
-                               }
-
-                               // Record any values with an "address taken" reaching
-                               // this code position as live. Must do now instead of below
-                               // because the any/all calculation requires walking forward
-                               // over the block (as this loop does), while the liveout
-                               // requires walking backward (as the next loop does).
-                               twobitlivepointermap(lv, any, lv->vars, args, locals);
-                       }
-                       
-                       if(p == bb->last)
-                               break;
-               }
-               bb->lastbitmapindex = arraylength(lv->livepointers) - 1;
-       }
-       
-       for(i = 0; i < arraylength(lv->cfg); i++) {
-               bb = *(BasicBlock**)arrayget(lv->cfg, i);
-               
-               if(debuglive >= 1 && strcmp(curfn->nname->sym->name, "init") != 0 && curfn->nname->sym->name[0] != '.') {
-                       nmsg = arraylength(lv->livepointers);
-                       startmsg = nmsg;
-                       msg = xmalloc(nmsg*sizeof msg[0]);
-                       for(j=0; j<nmsg; j++)
-                               msg[j] = nil;
-               }
-
-               // walk backward, emit pcdata and populate the maps
-               pos = bb->lastbitmapindex;
-               if(pos < 0) {
-                       // the first block we encounter should have the ATEXT so
-                       // at no point should pos ever be less than zero.
-                       fatal("livenessepilogue");
-               }
-
-               bvcopy(livein, lv->liveout[bb->rpo]);
-               for(p = bb->last; p != nil; p = next) {
-                       next = p->opt; // splicebefore modifies p->opt
-                       // Propagate liveness information
-                       progeffects(p, lv->vars, uevar, varkill, avarinit);
-                       bvcopy(liveout, livein);
-                       bvandnot(livein, liveout, varkill);
-                       bvor(livein, livein, uevar);
-                       if(debuglive >= 3 && issafepoint(p)){
-                               print("%P\n", p);
-                               printvars("uevar", uevar, lv->vars);
-                               printvars("varkill", varkill, lv->vars);
-                               printvars("livein", livein, lv->vars);
-                               printvars("liveout", liveout, lv->vars);
-                       }
-                       if(issafepoint(p)) {
-                               // Found an interesting instruction, record the
-                               // corresponding liveness information.  
-                               
-                               // Useful sanity check: on entry to the function,
-                               // the only things that can possibly be live are the
-                               // input parameters.
-                               if(p->as == ATEXT) {
-                                       for(j = 0; j < liveout->n; j++) {
-                                               if(!bvget(liveout, j))
-                                                       continue;
-                                               n = *(Node**)arrayget(lv->vars, j);
-                                               if(n->class != PPARAM)
-                                                       yyerrorl(p->lineno, "internal error: %N %lN recorded as live on entry", curfn->nname, n);
-                                       }
-                               }
-
-                               // Record live pointers.
-                               args = *(Bvec**)arrayget(lv->argslivepointers, pos);
-                               locals = *(Bvec**)arrayget(lv->livepointers, pos);
-                               twobitlivepointermap(lv, liveout, lv->vars, args, locals);
-                               
-                               // Ambiguously live variables are zeroed immediately after
-                               // function entry. Mark them live for all the non-entry bitmaps
-                               // so that GODEBUG=gcdead=1 mode does not poison them.
-                               if(p->as == ACALL)
-                                       bvor(locals, locals, ambig);
-
-                               // Show live pointer bitmaps.
-                               // We're interpreting the args and locals bitmap instead of liveout so that we
-                               // include the bits added by the avarinit logic in the
-                               // previous loop.
-                               if(msg != nil) {
-                                       fmtstrinit(&fmt);
-                                       fmtprint(&fmt, "%L: live at ", p->lineno);
-                                       if(p->as == ACALL && p->to.node)
-                                               fmtprint(&fmt, "call to %s:", ((Node*)(p->to.node))->sym->name);
-                                       else if(p->as == ACALL)
-                                               fmtprint(&fmt, "indirect call:");
-                                       else
-                                               fmtprint(&fmt, "entry to %s:", ((Node*)(p->from.node))->sym->name);
-                                       numlive = 0;
-                                       for(j = 0; j < arraylength(lv->vars); j++) {
-                                               n = *(Node**)arrayget(lv->vars, j);
-                                               if(islive(n, args, locals)) {
-                                                       fmtprint(&fmt, " %N", n);
-                                                       numlive++;
-                                               }
-                                       }
-                                       fmtprint(&fmt, "\n");
-                                       if(numlive == 0) // squelch message
-                                               free(fmtstrflush(&fmt));
-                                       else
-                                               msg[--startmsg] = fmtstrflush(&fmt);
-                               }
-
-                               // Only CALL instructions need a PCDATA annotation.
-                               // The TEXT instruction annotation is implicit.
-                               if(p->as == ACALL) {
-                                       if(isdeferreturn(p)) {
-                                               // runtime.deferreturn modifies its return address to return
-                                               // back to the CALL, not to the subsequent instruction.
-                                               // Because the return comes back one instruction early,
-                                               // the PCDATA must begin one instruction early too.
-                                               // The instruction before a call to deferreturn is always a
-                                               // no-op, to keep PC-specific data unambiguous.
-                                               splicebefore(lv, bb, newpcdataprog(p->opt, pos), p->opt);
-                                       } else {
-                                               splicebefore(lv, bb, newpcdataprog(p, pos), p);
-                                       }
-                               }
-
-                               pos--;
-                       }
-               }
-               if(msg != nil) {
-                       for(j=startmsg; j<nmsg; j++) 
-                               if(msg[j] != nil)
-                                       print("%s", msg[j]);
-                       free(msg);
-                       msg = nil;
-                       nmsg = 0;
-                       startmsg = 0;
-               }
-       }
-
-       free(livein);
-       free(liveout);
-       free(uevar);
-       free(varkill);
-       free(avarinit);
-       free(any);
-       free(all);
-       free(ambig);
-       
-       flusherrors();
-}
-
-// FNV-1 hash function constants.
-#define H0 2166136261UL
-#define Hp 16777619UL
-/*c2go
-enum
-{
-       H0 = 2166136261,
-       Hp = 16777619,
-};
-*/
-
-static uint32
-hashbitmap(uint32 h, Bvec *bv)
-{
-       int i, n;
-       uint32 w;
-       
-       n = (bv->n+31)/32;
-       for(i=0; i<n; i++) {
-               w = bv->b[i];
-               h = (h*Hp) ^ (w&0xff);
-               h = (h*Hp) ^ ((w>>8)&0xff);
-               h = (h*Hp) ^ ((w>>16)&0xff);
-               h = (h*Hp) ^ ((w>>24)&0xff);
-       }
-       return h;
-}
-
-// Compact liveness information by coalescing identical per-call-site bitmaps.
-// The merging only happens for a single function, not across the entire binary.
-//
-// There are actually two lists of bitmaps, one list for the local variables and one
-// list for the function arguments. Both lists are indexed by the same PCDATA
-// index, so the corresponding pairs must be considered together when
-// merging duplicates. The argument bitmaps change much less often during
-// function execution than the local variable bitmaps, so it is possible that
-// we could introduce a separate PCDATA index for arguments vs locals and
-// then compact the set of argument bitmaps separately from the set of
-// local variable bitmaps. As of 2014-04-02, doing this to the godoc binary
-// is actually a net loss: we save about 50k of argument bitmaps but the new
-// PCDATA tables cost about 100k. So for now we keep using a single index for
-// both bitmap lists.
-static void
-livenesscompact(Liveness *lv)
-{
-       int *table, *remap, i, j, n, tablesize, uniq;
-       uint32 h;
-       Bvec *local, *arg, *jlocal, *jarg;
-       Prog *p;
-
-       // Linear probing hash table of bitmaps seen so far.
-       // The hash table has 4n entries to keep the linear
-       // scan short. An entry of -1 indicates an empty slot.
-       n = arraylength(lv->livepointers);
-       tablesize = 4*n;
-       table = xmalloc(tablesize*sizeof table[0]);
-       memset(table, 0xff, tablesize*sizeof table[0]);
-       
-       // remap[i] = the new index of the old bit vector #i.
-       remap = xmalloc(n*sizeof remap[0]);
-       memset(remap, 0xff, n*sizeof remap[0]);
-       uniq = 0; // unique tables found so far
-
-       // Consider bit vectors in turn.
-       // If new, assign next number using uniq,
-       // record in remap, record in lv->livepointers and lv->argslivepointers
-       // under the new index, and add entry to hash table.
-       // If already seen, record earlier index in remap and free bitmaps.
-       for(i=0; i<n; i++) {
-               local = *(Bvec**)arrayget(lv->livepointers, i);
-               arg = *(Bvec**)arrayget(lv->argslivepointers, i);
-               h = hashbitmap(hashbitmap(H0, local), arg) % tablesize;
-
-               for(;;) {
-                       j = table[h];
-                       if(j < 0)
-                               break;
-                       jlocal = *(Bvec**)arrayget(lv->livepointers, j);
-                       jarg = *(Bvec**)arrayget(lv->argslivepointers, j);
-                       if(bvcmp(local, jlocal) == 0 && bvcmp(arg, jarg) == 0) {
-                               free(local);
-                               free(arg);
-                               remap[i] = j;
-                               goto Next;
-                       }
-                       if(++h == tablesize)
-                               h = 0;
-               }
-               table[h] = uniq;
-               remap[i] = uniq;
-               *(Bvec**)arrayget(lv->livepointers, uniq) = local;
-               *(Bvec**)arrayget(lv->argslivepointers, uniq) = arg;
-               uniq++;
-       Next:;
-       }
-
-       // We've already reordered lv->livepointers[0:uniq]
-       // and lv->argslivepointers[0:uniq] and freed the bitmaps
-       // we don't need anymore. Clear the pointers later in the
-       // array so that we can tell where the coalesced bitmaps stop
-       // and so that we don't double-free when cleaning up.
-       for(j=uniq; j<n; j++) {
-               *(Bvec**)arrayget(lv->livepointers, j) = nil;
-               *(Bvec**)arrayget(lv->argslivepointers, j) = nil;
-       }
-       
-       // Rewrite PCDATA instructions to use new numbering.
-       for(p=lv->ptxt; p != P; p=p->link) {
-               if(p->as == APCDATA && p->from.offset == PCDATA_StackMapIndex) {
-                       i = p->to.offset;
-                       if(i >= 0)
-                               p->to.offset = remap[i];
-               }
-       }
-
-       free(table);
-       free(remap);
-}
-
-static int
-printbitset(int printed, char *name, Array *vars, Bvec *bits)
-{
-       int i, started;
-       Node *n;
-
-       started = 0;    
-       for(i=0; i<arraylength(vars); i++) {
-               if(!bvget(bits, i))
-                       continue;
-               if(!started) {
-                       if(!printed)
-                               print("\t");
-                       else
-                               print(" ");
-                       started = 1;
-                       printed = 1;
-                       print("%s=", name);
-               } else {
-                       print(",");
-               }
-               n = *(Node**)arrayget(vars, i);
-               print("%s", n->sym->name);
-       }
-       return printed;
-}
-
-// Prints the computed liveness information and inputs, for debugging.
-// This format synthesizes the information used during the multiple passes
-// into a single presentation.
-static void
-livenessprintdebug(Liveness *lv)
-{
-       int i, j, pcdata, printed;
-       BasicBlock *bb;
-       Prog *p;
-       Bvec *uevar, *varkill, *avarinit, *args, *locals;
-       Node *n;
-
-       print("liveness: %s\n", curfn->nname->sym->name);
-
-       uevar = bvalloc(arraylength(lv->vars));
-       varkill = bvalloc(arraylength(lv->vars));
-       avarinit = bvalloc(arraylength(lv->vars));
-
-       pcdata = 0;
-       for(i = 0; i < arraylength(lv->cfg); i++) {
-               if(i > 0)
-                       print("\n");
-               bb = *(BasicBlock**)arrayget(lv->cfg, i);
-
-               // bb#0 pred=1,2 succ=3,4
-               print("bb#%d pred=", i);
-               for(j = 0; j < arraylength(bb->pred); j++) {
-                       if(j > 0)
-                               print(",");
-                       print("%d", (*(BasicBlock**)arrayget(bb->pred, j))->rpo);
-               }
-               print(" succ=");
-               for(j = 0; j < arraylength(bb->succ); j++) {
-                       if(j > 0)
-                               print(",");
-                       print("%d", (*(BasicBlock**)arrayget(bb->succ, j))->rpo);
-               }
-               print("\n");
-               
-               // initial settings
-               printed = 0;
-               printed = printbitset(printed, "uevar", lv->vars, lv->uevar[bb->rpo]);
-               printed = printbitset(printed, "livein", lv->vars, lv->livein[bb->rpo]);
-               if(printed)
-                       print("\n");
-               
-               // program listing, with individual effects listed
-               for(p = bb->first;; p = p->link) {
-                       print("%P\n", p);
-                       if(p->as == APCDATA && p->from.offset == PCDATA_StackMapIndex)
-                               pcdata = p->to.offset;
-                       progeffects(p, lv->vars, uevar, varkill, avarinit);
-                       printed = 0;
-                       printed = printbitset(printed, "uevar", lv->vars, uevar);
-                       printed = printbitset(printed, "varkill", lv->vars, varkill);
-                       printed = printbitset(printed, "avarinit", lv->vars, avarinit);
-                       if(printed)
-                               print("\n");
-                       if(issafepoint(p)) {
-                               args = *(Bvec**)arrayget(lv->argslivepointers, pcdata);
-                               locals = *(Bvec**)arrayget(lv->livepointers, pcdata);
-                               print("\tlive=");
-                               printed = 0;
-                               for(j = 0; j < arraylength(lv->vars); j++) {
-                                       n = *(Node**)arrayget(lv->vars, j);
-                                       if(islive(n, args, locals)) {
-                                               if(printed++)
-                                                       print(",");
-                                               print("%N", n);
-                                       }
-                               }
-                               print("\n");
-                       }
-                       if(p == bb->last)
-                               break;
-               }
-               
-               // bb bitsets
-               print("end\n");
-               printed = printbitset(printed, "varkill", lv->vars, lv->varkill[bb->rpo]);
-               printed = printbitset(printed, "liveout", lv->vars, lv->liveout[bb->rpo]);
-               printed = printbitset(printed, "avarinit", lv->vars, lv->avarinit[bb->rpo]);
-               printed = printbitset(printed, "avarinitany", lv->vars, lv->avarinitany[bb->rpo]);
-               printed = printbitset(printed, "avarinitall", lv->vars, lv->avarinitall[bb->rpo]);
-               if(printed)
-                       print("\n");
-       }
-       print("\n");
-
-       free(uevar);
-       free(varkill);
-       free(avarinit);
-}
-
-// Dumps an array of bitmaps to a symbol as a sequence of uint32 values.  The
-// first word dumped is the total number of bitmaps.  The second word is the
-// length of the bitmaps.  All bitmaps are assumed to be of equal length.  The
-// words that are followed are the raw bitmap words.  The arr argument is an
-// array of Node*s.
-static void
-twobitwritesymbol(Array *arr, Sym *sym)
-{
-       Bvec *bv;
-       int off, i, j, n;
-       uint32 word;
-
-       n = arraylength(arr);
-       off = 0;
-       off += 4; // number of bitmaps, to fill in later
-       bv = *(Bvec**)arrayget(arr, 0);
-       off = duint32(sym, off, bv->n); // number of bits in each bitmap
-       for(i = 0; i < n; i++) {
-               // bitmap words
-               bv = *(Bvec**)arrayget(arr, i);
-               if(bv == nil)
-                       break;
-               for(j = 0; j < bv->n; j += 32) {
-                       word = bv->b[j/32];
-                       // Runtime reads the bitmaps as byte arrays. Oblige.
-                       off = duint8(sym, off, word);
-                       off = duint8(sym, off, word>>8);
-                       off = duint8(sym, off, word>>16);
-                       off = duint8(sym, off, word>>24);
-               }
-       }
-       duint32(sym, 0, i); // number of bitmaps
-       ggloblsym(sym, off, RODATA);
-}
-
-static void
-printprog(Prog *p)
-{
-       while(p != nil) {
-               print("%P\n", p);
-               p = p->link;
-       }
-}
-
-// Entry pointer for liveness analysis.  Constructs a complete CFG, solves for
-// the liveness of pointer variables in the function, and emits a runtime data
-// structure read by the garbage collector.
-void
-liveness(Node *fn, Prog *firstp, Sym *argssym, Sym *livesym)
-{
-       Array *cfg, *vars;
-       Liveness *lv;
-       int debugdelta;
-       NodeList *l;
-
-       // Change name to dump debugging information only for a specific function.
-       debugdelta = 0;
-       if(strcmp(curfn->nname->sym->name, "!") == 0)
-               debugdelta = 2;
-       
-       debuglive += debugdelta;
-       if(debuglive >= 3) {
-               print("liveness: %s\n", curfn->nname->sym->name);
-               printprog(firstp);
-       }
-       checkptxt(fn, firstp);
-
-       // Construct the global liveness state.
-       cfg = newcfg(firstp);
-       if(debuglive >= 3)
-               printcfg(cfg);
-       vars = getvariables(fn);
-       lv = newliveness(fn, firstp, cfg, vars);
-
-       // Run the dataflow framework.
-       livenessprologue(lv);
-       if(debuglive >= 3)
-               livenessprintcfg(lv);
-       livenesssolve(lv);
-       if(debuglive >= 3)
-               livenessprintcfg(lv);
-       livenessepilogue(lv);
-       if(debuglive >= 3)
-               livenessprintcfg(lv);
-       livenesscompact(lv);
-
-       if(debuglive >= 2)
-               livenessprintdebug(lv);
-
-       // Emit the live pointer map data structures
-       twobitwritesymbol(lv->livepointers, livesym);
-       twobitwritesymbol(lv->argslivepointers, argssym);
-
-       // Free everything.
-       for(l=fn->dcl; l != nil; l = l->next)
-               if(l->n != N)
-                       l->n->opt = nil;
-       freeliveness(lv);
-       arrayfree(vars);
-       freecfg(cfg);
-       
-       debuglive -= debugdelta;
-}
diff --git a/src/cmd/gc/popt.c b/src/cmd/gc/popt.c
deleted file mode 100644 (file)
index b02d58e..0000000
+++ /dev/null
@@ -1,1022 +0,0 @@
-// Derived from Inferno utils/6c/reg.c
-// http://code.google.com/p/inferno-os/source/browse/utils/6c/reg.c
-//
-//     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 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.
-
-// "Portable" optimizations.
-// Compiled separately for 5g, 6g, and 8g, so allowed to use gg.h, opt.h.
-// Must code to the intersection of the three back ends.
-
-#include       <u.h>
-#include       <libc.h>
-#include       "go.h"
-#include       "popt.h"
-
-// p is a call instruction. Does the call fail to return?
-int
-noreturn(Prog *p)
-{
-       Sym *s;
-       int i;
-       static Sym*     symlist[10];
-
-       if(symlist[0] == S) {
-               symlist[0] = pkglookup("panicindex", runtimepkg);
-               symlist[1] = pkglookup("panicslice", runtimepkg);
-               symlist[2] = pkglookup("throwinit", runtimepkg);
-               symlist[3] = pkglookup("gopanic", runtimepkg);
-               symlist[4] = pkglookup("panicwrap", runtimepkg);
-               symlist[5] = pkglookup("throwreturn", runtimepkg);
-               symlist[6] = pkglookup("selectgo", runtimepkg);
-               symlist[7] = pkglookup("block", runtimepkg);
-       }
-
-       if(p->to.node == nil)
-               return 0;
-       s = ((Node*)(p->to.node))->sym;
-       if(s == S)
-               return 0;
-       for(i=0; symlist[i]!=S; i++)
-               if(s == symlist[i])
-                       return 1;
-       return 0;
-}
-
-// JMP chasing and removal.
-//
-// The code generator depends on being able to write out jump
-// instructions that it can jump to now but fill in later.
-// the linker will resolve them nicely, but they make the code
-// longer and more difficult to follow during debugging.
-// Remove them.
-
-/* what instruction does a JMP to p eventually land on? */
-static Prog*
-chasejmp(Prog *p, int *jmploop)
-{
-       int n;
-
-       n = 0;
-       while(p != P && p->as == AJMP && p->to.type == TYPE_BRANCH) {
-               if(++n > 10) {
-                       *jmploop = 1;
-                       break;
-               }
-               p = p->to.u.branch;
-       }
-       return p;
-}
-
-/*
- * reuse reg pointer for mark/sweep state.
- * leave reg==nil at end because alive==nil.
- */
-#define alive ((void*)0)
-#define dead ((void*)1)
-/*c2go
-extern void *alive;
-extern void *dead;
-*/
-
-/* mark all code reachable from firstp as alive */
-static void
-mark(Prog *firstp)
-{
-       Prog *p;
-       
-       for(p=firstp; p; p=p->link) {
-               if(p->opt != dead)
-                       break;
-               p->opt = alive;
-               if(p->as != ACALL && p->to.type == TYPE_BRANCH && p->to.u.branch)
-                       mark(p->to.u.branch);
-               if(p->as == AJMP || p->as == ARET || p->as == AUNDEF)
-                       break;
-       }
-}
-
-void
-fixjmp(Prog *firstp)
-{
-       int jmploop;
-       Prog *p, *last;
-       
-       if(debug['R'] && debug['v'])
-               print("\nfixjmp\n");
-
-       // pass 1: resolve jump to jump, mark all code as dead.
-       jmploop = 0;
-       for(p=firstp; p; p=p->link) {
-               if(debug['R'] && debug['v'])
-                       print("%P\n", p);
-               if(p->as != ACALL && p->to.type == TYPE_BRANCH && p->to.u.branch && p->to.u.branch->as == AJMP) {
-                       p->to.u.branch = chasejmp(p->to.u.branch, &jmploop);
-                       if(debug['R'] && debug['v'])
-                               print("->%P\n", p);
-               }
-               p->opt = dead;
-       }
-       if(debug['R'] && debug['v'])
-               print("\n");
-
-       // pass 2: mark all reachable code alive
-       mark(firstp);
-       
-       // pass 3: delete dead code (mostly JMPs).
-       last = nil;
-       for(p=firstp; p; p=p->link) {
-               if(p->opt == dead) {
-                       if(p->link == P && p->as == ARET && last && last->as != ARET) {
-                               // This is the final ARET, and the code so far doesn't have one.
-                               // Let it stay. The register allocator assumes that all live code in
-                               // the function can be traversed by starting at all the RET instructions
-                               // and following predecessor links. If we remove the final RET,
-                               // this assumption will not hold in the case of an infinite loop
-                               // at the end of a function.
-                               // Keep the RET but mark it dead for the liveness analysis.
-                               p->mode = 1;
-                       } else {
-                               if(debug['R'] && debug['v'])
-                                       print("del %P\n", p);
-                               continue;
-                       }
-               }
-               if(last)
-                       last->link = p;
-               last = p;
-       }
-       last->link = P;
-       
-       // pass 4: elide JMP to next instruction.
-       // only safe if there are no jumps to JMPs anymore.
-       if(!jmploop) {
-               last = nil;
-               for(p=firstp; p; p=p->link) {
-                       if(p->as == AJMP && p->to.type == TYPE_BRANCH && p->to.u.branch == p->link) {
-                               if(debug['R'] && debug['v'])
-                                       print("del %P\n", p);
-                               continue;
-                       }
-                       if(last)
-                               last->link = p;
-                       last = p;
-               }
-               last->link = P;
-       }
-       
-       if(debug['R'] && debug['v']) {
-               print("\n");
-               for(p=firstp; p; p=p->link)
-                       print("%P\n", p);
-               print("\n");
-       }
-}
-
-#undef alive
-#undef dead
-
-// Control flow analysis. The Flow structures hold predecessor and successor
-// information as well as basic loop analysis.
-//
-//     graph = flowstart(firstp, 0);
-//     ... use flow graph ...
-//     flowend(graph); // free graph
-//
-// Typical uses of the flow graph are to iterate over all the flow-relevant instructions:
-//
-//     for(f = graph->start; f != nil; f = f->link)
-//
-// or, given an instruction f, to iterate over all the predecessors, which is
-// f->p1 and this list:
-//
-//     for(f2 = f->p2; f2 != nil; f2 = f2->p2link)
-//
-// The size argument to flowstart specifies an amount of zeroed memory
-// to allocate in every f->data field, for use by the client.
-// If size == 0, f->data will be nil.
-
-Graph*
-flowstart(Prog *firstp, int size)
-{
-       int id, nf;
-       Flow *f, *f1, *start, *last;
-       Graph *graph;
-       Prog *p;
-       ProgInfo info;
-       char *data;
-
-       // Count and mark instructions to annotate.
-       nf = 0;
-       for(p = firstp; p != P; p = p->link) {
-               p->opt = nil; // should be already, but just in case
-               thearch.proginfo(&info, p);
-               if(info.flags & Skip)
-                       continue;
-               p->opt = (void*)1;
-               nf++;
-       }
-       
-       if(nf == 0)
-               return nil;
-
-       if(nf >= 20000) {
-               // fatal("%S is too big (%d instructions)", curfn->nname->sym, nf);
-               return nil;
-       }
-
-       // Allocate annotations and assign to instructions.
-       graph = calloc(sizeof *graph + sizeof(Flow)*nf + size*nf, 1);
-       if(graph == nil)
-               fatal("out of memory");
-       start = (Flow*)(graph+1);
-       last = nil;
-       f = start;
-       data = (char*)(f+nf);
-       if(size == 0)
-               data = nil;
-       id = 0;
-       for(p = firstp; p != P; p = p->link) {
-               if(p->opt == nil)
-                       continue;
-               p->opt = f;
-               f->prog = p;
-               if(last)
-                       last->link = f;
-               last = f;
-               f->data = data;
-               f->id = id;
-               f++;
-               id++;
-               data += size;
-       }
-
-       // Fill in pred/succ information.
-       for(f = start; f != nil; f = f->link) {
-               p = f->prog;
-               thearch.proginfo(&info, p);
-               if(!(info.flags & Break)) {
-                       f1 = f->link;
-                       f->s1 = f1;
-                       f1->p1 = f;
-               }
-               if(p->to.type == TYPE_BRANCH) {
-                       if(p->to.u.branch == P)
-                               fatal("pnil %P", p);
-                       f1 = p->to.u.branch->opt;
-                       if(f1 == nil)
-                               fatal("fnil %P / %P", p, p->to.u.branch);
-                       if(f1 == f) {
-                               //fatal("self loop %P", p);
-                               continue;
-                       }
-                       f->s2 = f1;
-                       f->p2link = f1->p2;
-                       f1->p2 = f;
-               }
-       }
-       
-       graph->start = start;
-       graph->num = nf;
-       return graph;
-}
-
-void
-flowend(Graph *graph)
-{
-       Flow *f;
-       
-       for(f = graph->start; f != nil; f = f->link)
-               f->prog->opt = nil;
-       free(graph);
-}
-
-/*
- * find looping structure
- *
- * 1) find reverse postordering
- * 2) find approximate dominators,
- *     the actual dominators if the flow graph is reducible
- *     otherwise, dominators plus some other non-dominators.
- *     See Matthew S. Hecht and Jeffrey D. Ullman,
- *     "Analysis of a Simple Algorithm for Global Data Flow Problems",
- *     Conf.  Record of ACM Symp. on Principles of Prog. Langs, Boston, Massachusetts,
- *     Oct. 1-3, 1973, pp.  207-217.
- * 3) find all nodes with a predecessor dominated by the current node.
- *     such a node is a loop head.
- *     recursively, all preds with a greater rpo number are in the loop
- */
-static int32
-postorder(Flow *r, Flow **rpo2r, int32 n)
-{
-       Flow *r1;
-
-       r->rpo = 1;
-       r1 = r->s1;
-       if(r1 && !r1->rpo)
-               n = postorder(r1, rpo2r, n);
-       r1 = r->s2;
-       if(r1 && !r1->rpo)
-               n = postorder(r1, rpo2r, n);
-       rpo2r[n] = r;
-       n++;
-       return n;
-}
-
-static int32
-rpolca(int32 *idom, int32 rpo1, int32 rpo2)
-{
-       int32 t;
-
-       if(rpo1 == -1)
-               return rpo2;
-       while(rpo1 != rpo2){
-               if(rpo1 > rpo2){
-                       t = rpo2;
-                       rpo2 = rpo1;
-                       rpo1 = t;
-               }
-               while(rpo1 < rpo2){
-                       t = idom[rpo2];
-                       if(t >= rpo2)
-                               fatal("bad idom");
-                       rpo2 = t;
-               }
-       }
-       return rpo1;
-}
-
-static int
-doms(int32 *idom, int32 r, int32 s)
-{
-       while(s > r)
-               s = idom[s];
-       return s == r;
-}
-
-static int
-loophead(int32 *idom, Flow *r)
-{
-       int32 src;
-
-       src = r->rpo;
-       if(r->p1 != nil && doms(idom, src, r->p1->rpo))
-               return 1;
-       for(r = r->p2; r != nil; r = r->p2link)
-               if(doms(idom, src, r->rpo))
-                       return 1;
-       return 0;
-}
-
-static void
-loopmark(Flow **rpo2r, int32 head, Flow *r)
-{
-       if(r->rpo < head || r->active == head)
-               return;
-       r->active = head;
-       r->loop += LOOP;
-       if(r->p1 != nil)
-               loopmark(rpo2r, head, r->p1);
-       for(r = r->p2; r != nil; r = r->p2link)
-               loopmark(rpo2r, head, r);
-}
-
-void
-flowrpo(Graph *g)
-{
-       Flow *r1;
-       int32 i, d, me, nr, *idom;
-       Flow **rpo2r;
-
-       free(g->rpo);
-       g->rpo = calloc(g->num*sizeof g->rpo[0], 1);
-       idom = calloc(g->num*sizeof idom[0], 1);
-       if(g->rpo == nil || idom == nil)
-               fatal("out of memory");
-
-       for(r1 = g->start; r1 != nil; r1 = r1->link)
-               r1->active = 0;
-
-       rpo2r = g->rpo;
-       d = postorder(g->start, rpo2r, 0);
-       nr = g->num;
-       if(d > nr)
-               fatal("too many reg nodes %d %d", d, nr);
-       nr = d;
-       for(i = 0; i < nr / 2; i++) {
-               r1 = rpo2r[i];
-               rpo2r[i] = rpo2r[nr - 1 - i];
-               rpo2r[nr - 1 - i] = r1;
-       }
-       for(i = 0; i < nr; i++)
-               rpo2r[i]->rpo = i;
-
-       idom[0] = 0;
-       for(i = 0; i < nr; i++) {
-               r1 = rpo2r[i];
-               me = r1->rpo;
-               d = -1;
-               // rpo2r[r->rpo] == r protects against considering dead code,
-               // which has r->rpo == 0.
-               if(r1->p1 != nil && rpo2r[r1->p1->rpo] == r1->p1 && r1->p1->rpo < me)
-                       d = r1->p1->rpo;
-               for(r1 = r1->p2; r1 != nil; r1 = r1->p2link)
-                       if(rpo2r[r1->rpo] == r1 && r1->rpo < me)
-                               d = rpolca(idom, d, r1->rpo);
-               idom[i] = d;
-       }
-
-       for(i = 0; i < nr; i++) {
-               r1 = rpo2r[i];
-               r1->loop++;
-               if(r1->p2 != nil && loophead(idom, r1))
-                       loopmark(rpo2r, i, r1);
-       }
-       free(idom);
-
-       for(r1 = g->start; r1 != nil; r1 = r1->link)
-               r1->active = 0;
-}
-
-Flow*
-uniqp(Flow *r)
-{
-       Flow *r1;
-
-       r1 = r->p1;
-       if(r1 == nil) {
-               r1 = r->p2;
-               if(r1 == nil || r1->p2link != nil)
-                       return nil;
-       } else
-               if(r->p2 != nil)
-                       return nil;
-       return r1;
-}
-
-Flow*
-uniqs(Flow *r)
-{
-       Flow *r1;
-
-       r1 = r->s1;
-       if(r1 == nil) {
-               r1 = r->s2;
-               if(r1 == nil)
-                       return nil;
-       } else
-               if(r->s2 != nil)
-                       return nil;
-       return r1;
-}
-
-// The compilers assume they can generate temporary variables
-// as needed to preserve the right semantics or simplify code
-// generation and the back end will still generate good code.
-// This results in a large number of ephemeral temporary variables.
-// Merge temps with non-overlapping lifetimes and equal types using the
-// greedy algorithm in Poletto and Sarkar, "Linear Scan Register Allocation",
-// ACM TOPLAS 1999.
-
-typedef struct TempVar TempVar;
-
-struct TempVar
-{
-       Node *node;
-       Flow *def; // definition of temp var
-       Flow *use; // use list, chained through Flow.data
-       TempVar *freelink; // next free temp in Type.opt list
-       TempVar *merge; // merge var with this one
-       vlong start; // smallest Prog.pc in live range
-       vlong end; // largest Prog.pc in live range
-       uchar addr; // address taken - no accurate end
-       uchar removed; // removed from program
-};
-
-static int
-startcmp(const void *va, const void *vb)
-{
-       TempVar *a, *b;
-       
-       a = *(TempVar**)va;
-       b = *(TempVar**)vb;
-
-       if(a->start < b->start)
-               return -1;
-       if(a->start > b->start)
-               return +1;
-       // Order what's left by id or symbol name,
-       // just so that sort is forced into a specific ordering,
-       // so that the result of the sort does not depend on
-       // the sort implementation.
-       if(a->def != b->def)
-               return a->def->id - b->def->id;
-       if(a->node != b->node)
-               return strcmp(a->node->sym->name, b->node->sym->name);
-       return 0;
-}
-
-// Is n available for merging?
-static int
-canmerge(Node *n)
-{
-       return n->class == PAUTO && strncmp(n->sym->name, "autotmp", 7) == 0;
-}
-
-static void mergewalk(TempVar*, Flow*, uint32);
-static void varkillwalk(TempVar*, Flow*, uint32);
-
-void
-mergetemp(Prog *firstp)
-{
-       int i, j, nvar, ninuse, nfree, nkill;
-       TempVar *var, *v, *v1, **bystart, **inuse;
-       Flow *f;
-       NodeList *l, **lp;
-       Node *n;
-       Prog *p, *p1;
-       Type *t;
-       ProgInfo info, info1;
-       int32 gen;
-       Graph *g;
-
-       enum { debugmerge = 1 };
-
-       g = flowstart(firstp, 0);
-       if(g == nil)
-               return;
-       
-       // Build list of all mergeable variables.
-       nvar = 0;
-       for(l = curfn->dcl; l != nil; l = l->next)
-               if(canmerge(l->n))
-                       nvar++;
-       
-       var = calloc(nvar*sizeof var[0], 1);
-       nvar = 0;
-       for(l = curfn->dcl; l != nil; l = l->next) {
-               n = l->n;
-               if(canmerge(n)) {
-                       v = &var[nvar++];
-                       n->opt = v;
-                       v->node = n;
-               }
-       }
-       
-       // Build list of uses.
-       // We assume that the earliest reference to a temporary is its definition.
-       // This is not true of variables in general but our temporaries are all
-       // single-use (that's why we have so many!).
-       for(f = g->start; f != nil; f = f->link) {
-               p = f->prog;
-               thearch.proginfo(&info, p);
-
-               if(p->from.node != N && ((Node*)(p->from.node))->opt && p->to.node != N && ((Node*)(p->to.node))->opt)
-                       fatal("double node %P", p);
-               v = nil;
-               if((n = p->from.node) != N)
-                       v = n->opt;
-               if(v == nil && (n = p->to.node) != N)
-                       v = n->opt;
-               if(v != nil) {
-                       if(v->def == nil)
-                               v->def = f;
-                       f->data = v->use;
-                       v->use = f;
-                       if(n == p->from.node && (info.flags & LeftAddr))
-                               v->addr = 1;
-               }
-       }
-       
-       if(debugmerge > 1 && debug['v'])
-               dumpit("before", g->start, 0);
-       
-       nkill = 0;
-
-       // Special case.
-       for(i = 0; i < nvar; i++) {
-               v = &var[i];
-               if(v->addr)
-                       continue;
-               // Used in only one instruction, which had better be a write.
-               if((f = v->use) != nil && (Flow*)f->data == nil) {
-                       p = f->prog;
-                       thearch.proginfo(&info, p);
-                       if(p->to.node == v->node && (info.flags & RightWrite) && !(info.flags & RightRead)) {
-                               p->as = ANOP;
-                               p->to = zprog.to;
-                               v->removed = 1;
-                               if(debugmerge > 0 && debug['v'])
-                                       print("drop write-only %S\n", v->node->sym);
-                       } else
-                               fatal("temp used and not set: %P", p);
-                       nkill++;
-                       continue;
-               }
-               
-               // Written in one instruction, read in the next, otherwise unused,
-               // no jumps to the next instruction. Happens mainly in 386 compiler.
-               if((f = v->use) != nil && f->link == (Flow*)f->data && (Flow*)((Flow*)f->data)->data == nil && uniqp(f->link) == f) {
-                       p = f->prog;
-                       thearch.proginfo(&info, p);
-                       p1 = f->link->prog;
-                       thearch.proginfo(&info1, p1);
-                       enum {
-                               SizeAny = SizeB | SizeW | SizeL | SizeQ | SizeF | SizeD,
-                       };
-                       if(p->from.node == v->node && p1->to.node == v->node && (info.flags & Move) &&
-                          !((info.flags|info1.flags) & (LeftAddr|RightAddr)) &&
-                          (info.flags & SizeAny) == (info1.flags & SizeAny)) {
-                               p1->from = p->from;
-                               thearch.excise(f);
-                               v->removed = 1;
-                               if(debugmerge > 0 && debug['v'])
-                                       print("drop immediate-use %S\n", v->node->sym);
-                       }
-                       nkill++;
-                       continue;
-               }                          
-       }
-
-       // Traverse live range of each variable to set start, end.
-       // Each flood uses a new value of gen so that we don't have
-       // to clear all the r->active words after each variable.
-       gen = 0;
-       for(i = 0; i < nvar; i++) {
-               v = &var[i];
-               gen++;
-               for(f = v->use; f != nil; f = (Flow*)f->data)
-                       mergewalk(v, f, gen);
-               if(v->addr) {
-                       gen++;
-                       for(f = v->use; f != nil; f = (Flow*)f->data)
-                               varkillwalk(v, f, gen);
-               }
-       }
-
-       // Sort variables by start.
-       bystart = malloc(nvar*sizeof bystart[0]);
-       for(i=0; i<nvar; i++)
-               bystart[i] = &var[i];
-       qsort(bystart, nvar, sizeof bystart[0], startcmp);
-
-       // List of in-use variables, sorted by end, so that the ones that
-       // will last the longest are the earliest ones in the array.
-       // The tail inuse[nfree:] holds no-longer-used variables.
-       // In theory we should use a sorted tree so that insertions are
-       // guaranteed O(log n) and then the loop is guaranteed O(n log n).
-       // In practice, it doesn't really matter.
-       inuse = malloc(nvar*sizeof inuse[0]);
-       ninuse = 0;
-       nfree = nvar;
-       for(i=0; i<nvar; i++) {
-               v = bystart[i];
-               if(debugmerge > 0 && debug['v'])
-                       print("consider %#N: removed=%d\n", v->node, v->removed);
-                       
-               if(v->removed)
-                       continue;
-
-               // Expire no longer in use.
-               while(ninuse > 0 && inuse[ninuse-1]->end < v->start) {
-                       v1 = inuse[--ninuse];
-                       inuse[--nfree] = v1;
-               }
-
-               if(debugmerge > 0 && debug['v'])
-                       print("consider %#N: removed=%d nfree=%d nvar=%d\n", v->node, v->removed, nfree, nvar);
-               // Find old temp to reuse if possible.
-               t = v->node->type;
-               for(j=nfree; j<nvar; j++) {
-                       v1 = inuse[j];
-                       if(debugmerge > 0 && debug['v'])
-                               print("consider %#N: maybe %#N: type=%T,%T addrtaken=%d,%d\n", v->node, v1->node, t, v1->node->type, v->node->addrtaken, v1->node->addrtaken);
-                       // Require the types to match but also require the addrtaken bits to match.
-                       // If a variable's address is taken, that disables registerization for the individual
-                       // words of the variable (for example, the base,len,cap of a slice).
-                       // We don't want to merge a non-addressed var with an addressed one and
-                       // inhibit registerization of the former.
-                       if(eqtype(t, v1->node->type) && v->node->addrtaken == v1->node->addrtaken) {
-                               inuse[j] = inuse[nfree++];
-                               if(v1->merge)
-                                       v->merge = v1->merge;
-                               else
-                                       v->merge = v1;
-                               nkill++;
-                               break;
-                       }
-               }
-
-               // Sort v into inuse.
-               j = ninuse++;
-               while(j > 0 && inuse[j-1]->end < v->end) {
-                       inuse[j] = inuse[j-1];
-                       j--;
-               }
-               inuse[j] = v;
-       }
-
-       if(debugmerge > 0 && debug['v']) {
-               print("%S [%d - %d]\n", curfn->nname->sym, nvar, nkill);
-               for(i = 0; i < nvar; i++) {
-                       v = &var[i];
-                       print("var %#N %T %lld-%lld", v->node, v->node->type, v->start, v->end);
-                       if(v->addr)
-                               print(" addr=1");
-                       if(v->removed)
-                               print(" dead=1");
-                       if(v->merge)
-                               print(" merge %#N", v->merge->node);
-                       if(v->start == v->end && v->def != nil)
-                               print(" %P", v->def->prog);
-                       print("\n");
-               }
-       
-               if(debugmerge > 1 && debug['v'])
-                       dumpit("after", g->start, 0);
-       }
-
-       // Update node references to use merged temporaries.
-       for(f = g->start; f != nil; f = f->link) {
-               p = f->prog;
-               if((n = p->from.node) != N && (v = n->opt) != nil && v->merge != nil)
-                       p->from.node = v->merge->node;
-               if((n = p->to.node) != N && (v = n->opt) != nil && v->merge != nil)
-                       p->to.node = v->merge->node;
-       }
-
-       // Delete merged nodes from declaration list.
-       for(lp = &curfn->dcl; (l = *lp); ) {
-               curfn->dcl->end = l;
-               n = l->n;
-               v = n->opt;
-               if(v && (v->merge || v->removed)) {
-                       *lp = l->next;
-                       continue;
-               }
-               lp = &l->next;
-       }
-
-       // Clear aux structures.
-       for(i = 0; i < nvar; i++)
-               var[i].node->opt = nil;
-
-       free(var);
-       free(bystart);
-       free(inuse);
-       flowend(g);
-}
-
-static void
-mergewalk(TempVar *v, Flow *f0, uint32 gen)
-{
-       Prog *p;
-       Flow *f1, *f, *f2;
-       
-       for(f1 = f0; f1 != nil; f1 = f1->p1) {
-               if(f1->active == gen)
-                       break;
-               f1->active = gen;
-               p = f1->prog;
-               if(v->end < p->pc)
-                       v->end = p->pc;
-               if(f1 == v->def) {
-                       v->start = p->pc;
-                       break;
-               }
-       }
-       
-       for(f = f0; f != f1; f = f->p1)
-               for(f2 = f->p2; f2 != nil; f2 = f2->p2link)
-                       mergewalk(v, f2, gen);
-}
-
-static void
-varkillwalk(TempVar *v, Flow *f0, uint32 gen)
-{
-       Prog *p;
-       Flow *f1, *f;
-       
-       for(f1 = f0; f1 != nil; f1 = f1->s1) {
-               if(f1->active == gen)
-                       break;
-               f1->active = gen;
-               p = f1->prog;
-               if(v->end < p->pc)
-                       v->end = p->pc;
-               if(v->start > p->pc)
-                       v->start = p->pc;
-               if(p->as == ARET || (p->as == AVARKILL && p->to.node == v->node))
-                       break;
-       }
-       
-       for(f = f0; f != f1; f = f->s1)
-               varkillwalk(v, f->s2, gen);
-}
-
-// Eliminate redundant nil pointer checks.
-//
-// The code generation pass emits a CHECKNIL for every possibly nil pointer.
-// This pass removes a CHECKNIL if every predecessor path has already
-// checked this value for nil.
-//
-// Simple backwards flood from check to definition.
-// Run prog loop backward from end of program to beginning to avoid quadratic
-// behavior removing a run of checks.
-//
-// Assume that stack variables with address not taken can be loaded multiple times
-// from memory without being rechecked. Other variables need to be checked on
-// each load.
-       
-typedef struct NilVar NilVar;
-
-static void nilwalkback(Flow *rcheck);
-static void nilwalkfwd(Flow *rcheck);
-
-static int killed; // f->data is either nil or &killed
-
-void
-nilopt(Prog *firstp)
-{
-       Flow *f;
-       Prog *p;
-       Graph *g;
-       int ncheck, nkill;
-
-       g = flowstart(firstp, 0);
-       if(g == nil)
-               return;
-
-       if(debug_checknil > 1 /* || strcmp(curfn->nname->sym->name, "f1") == 0 */)
-               dumpit("nilopt", g->start, 0);
-
-       ncheck = 0;
-       nkill = 0;
-       for(f = g->start; f != nil; f = f->link) {
-               p = f->prog;
-               if(p->as != ACHECKNIL || !thearch.regtyp(&p->from))
-                       continue;
-               ncheck++;
-               if(thearch.stackaddr(&p->from)) {
-                       if(debug_checknil && p->lineno > 1)
-                               warnl(p->lineno, "removed nil check of SP address");
-                       f->data = &killed;
-                       continue;
-               }
-               nilwalkfwd(f);
-               if(f->data != nil) {
-                       if(debug_checknil && p->lineno > 1)
-                               warnl(p->lineno, "removed nil check before indirect");
-                       continue;
-               }
-               nilwalkback(f);
-               if(f->data != nil) {
-                       if(debug_checknil && p->lineno > 1)
-                               warnl(p->lineno, "removed repeated nil check");
-                       continue;
-               }
-       }
-       
-       for(f = g->start; f != nil; f = f->link) {
-               if(f->data != nil) {
-                       nkill++;
-                       thearch.excise(f);
-               }
-       }
-
-       flowend(g);
-       
-       if(debug_checknil > 1)
-               print("%S: removed %d of %d nil checks\n", curfn->nname->sym, nkill, ncheck);
-}
-
-static void
-nilwalkback(Flow *fcheck)
-{
-       Prog *p;
-       ProgInfo info;
-       Flow *f;
-       
-       for(f = fcheck; f != nil; f = uniqp(f)) {
-               p = f->prog;
-               thearch.proginfo(&info, p);
-               if((info.flags & RightWrite) && thearch.sameaddr(&p->to, &fcheck->prog->from)) {
-                       // Found initialization of value we're checking for nil.
-                       // without first finding the check, so this one is unchecked.
-                       return;
-               }
-               if(f != fcheck && p->as == ACHECKNIL && thearch.sameaddr(&p->from, &fcheck->prog->from)) {
-                       fcheck->data = &killed;
-                       return;
-               }
-       }
-
-       // Here is a more complex version that scans backward across branches.
-       // It assumes fcheck->kill = 1 has been set on entry, and its job is to find a reason
-       // to keep the check (setting fcheck->kill = 0).
-       // It doesn't handle copying of aggregates as well as I would like,
-       // nor variables with their address taken,
-       // and it's too subtle to turn on this late in Go 1.2. Perhaps for Go 1.3.
-       /*
-       for(f1 = f0; f1 != nil; f1 = f1->p1) {
-               if(f1->active == gen)
-                       break;
-               f1->active = gen;
-               p = f1->prog;
-               
-               // If same check, stop this loop but still check
-               // alternate predecessors up to this point.
-               if(f1 != fcheck && p->as == ACHECKNIL && thearch.sameaddr(&p->from, &fcheck->prog->from))
-                       break;
-
-               thearch.proginfo(&info, p);
-               if((info.flags & RightWrite) && thearch.sameaddr(&p->to, &fcheck->prog->from)) {
-                       // Found initialization of value we're checking for nil.
-                       // without first finding the check, so this one is unchecked.
-                       fcheck->kill = 0;
-                       return;
-               }
-               
-               if(f1->p1 == nil && f1->p2 == nil) {
-                       print("lost pred for %P\n", fcheck->prog);
-                       for(f1=f0; f1!=nil; f1=f1->p1) {
-                               thearch.proginfo(&info, f1->prog);
-                               print("\t%P %d %d %D %D\n", r1->prog, info.flags&RightWrite, thearch.sameaddr(&f1->prog->to, &fcheck->prog->from), &f1->prog->to, &fcheck->prog->from);
-                       }
-                       fatal("lost pred trail");
-               }
-       }
-
-       for(f = f0; f != f1; f = f->p1)
-               for(f2 = f->p2; f2 != nil; f2 = f2->p2link)
-                       nilwalkback(fcheck, f2, gen);
-       */
-}
-
-static void
-nilwalkfwd(Flow *fcheck)
-{
-       Flow *f, *last;
-       Prog *p;
-       ProgInfo info;
-       
-       // If the path down from rcheck dereferences the address
-       // (possibly with a small offset) before writing to memory
-       // and before any subsequent checks, it's okay to wait for
-       // that implicit check. Only consider this basic block to
-       // avoid problems like:
-       //      _ = *x // should panic
-       //      for {} // no writes but infinite loop may be considered visible
-       last = nil;
-       for(f = uniqs(fcheck); f != nil; f = uniqs(f)) {
-               p = f->prog;
-               thearch.proginfo(&info, p);
-               
-               if((info.flags & LeftRead) && thearch.smallindir(&p->from, &fcheck->prog->from)) {
-                       fcheck->data = &killed;
-                       return;
-               }
-               if((info.flags & (RightRead|RightWrite)) && thearch.smallindir(&p->to, &fcheck->prog->from)) {
-                       fcheck->data = &killed;
-                       return;
-               }
-               
-               // Stop if another nil check happens.
-               if(p->as == ACHECKNIL)
-                       return;
-               // Stop if value is lost.
-               if((info.flags & RightWrite) && thearch.sameaddr(&p->to, &fcheck->prog->from))
-                       return;
-               // Stop if memory write.
-               if((info.flags & RightWrite) && !thearch.regtyp(&p->to))
-                       return;
-               // Stop if we jump backward.
-               if(last != nil && f->id <= last->id)
-                       return;
-               last = f;
-       }
-}
diff --git a/src/cmd/gc/popt.h b/src/cmd/gc/popt.h
deleted file mode 100644 (file)
index 4e89dbd..0000000
+++ /dev/null
@@ -1,152 +0,0 @@
-// Derived from Inferno utils/6c/gc.h
-// http://code.google.com/p/inferno-os/source/browse/utils/6c/gc.h
-//
-//     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 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.
-
-#define        Z       N
-#define        Adr     Addr
-
-#define        BLOAD(r)        band(bnot(r->refbehind), r->refahead)
-#define        BSTORE(r)       band(bnot(r->calbehind), r->calahead)
-#define        LOAD(r)         (~r->refbehind.b[z] & r->refahead.b[z])
-#define        STORE(r)        (~r->calbehind.b[z] & r->calahead.b[z])
-
-enum
-{
-       CLOAD = 5,
-       CREF = 5,
-       CINF = 1000,
-       LOOP = 3,
-};
-
-typedef        struct  Reg     Reg;
-typedef        struct  Rgn     Rgn;
-
-/*c2go
-extern Node *Z;
-
-uint32 BLOAD(Reg*);
-uint32 BSTORE(Reg*);
-uint64 LOAD(Reg*);
-uint64 STORE(Reg*);
-*/
-
-// A Reg is a wrapper around a single Prog (one instruction) that holds
-// register optimization information while the optimizer runs.
-// r->prog is the instruction.
-struct Reg
-{
-       Bits    set;            // regopt variables written by this instruction.
-       Bits    use1;           // regopt variables read by prog->from.
-       Bits    use2;           // regopt variables read by prog->to.
-
-       // refahead/refbehind are the regopt variables whose current
-       // value may be used in the following/preceding instructions
-       // up to a CALL (or the value is clobbered).
-       Bits    refbehind;
-       Bits    refahead;
-       // calahead/calbehind are similar, but for variables in
-       // instructions that are reachable after hitting at least one
-       // CALL.
-       Bits    calbehind;
-       Bits    calahead;
-       Bits    regdiff;
-       Bits    act;
-
-       uint64  regu;           // register used bitmap
-};
-#define        R       ((Reg*)0)
-/*c2go extern Reg *R; */
-
-#define        NRGN    600
-/*c2go enum { NRGN = 600 }; */
-
-// A Rgn represents a single regopt variable over a region of code
-// where a register could potentially be dedicated to that variable.
-// The code encompassed by a Rgn is defined by the flow graph,
-// starting at enter, flood-filling forward while varno is refahead
-// and backward while varno is refbehind, and following branches.  A
-// single variable may be represented by multiple disjoint Rgns and
-// each Rgn may choose a different register for that variable.
-// Registers are allocated to regions greedily in order of descending
-// cost.
-struct Rgn
-{
-       Flow*   enter;
-       short   cost;
-       short   varno;
-       short   regno;
-};
-
-EXTERN Reg     zreg;
-EXTERN Rgn     region[NRGN];
-EXTERN Rgn*    rgp;
-EXTERN int     nregion;
-EXTERN int     nvar;
-EXTERN uint64  regbits;
-EXTERN Bits    externs;
-EXTERN Bits    params;
-EXTERN Bits    consts;
-EXTERN Bits    addrs;
-EXTERN Bits    ivar;
-EXTERN Bits    ovar;
-EXTERN int     change;
-EXTERN int32   maxnr;
-
-typedef struct OptStats OptStats;
-struct OptStats
-{
-       int32   ncvtreg;
-       int32   nspill;
-       int32   nreload;
-       int32   ndelmov;
-       int32   nvar;
-       int32   naddr;
-};
-
-EXTERN OptStats ostats;
-
-/*
- * reg.c
- */
-void   regopt(Prog*);
-void   dumpone(Flow*, int);
-void   dumpit(char*, Flow*, int);
-
-/*
- * peep.c
-void   peep(Prog*);
-void   excise(Flow*);
-int    copyu(Prog*, Adr*, Adr*);
- */
-
-/*
- * prog.c
-
-void proginfo(ProgInfo*, Prog*);
- */
diff --git a/src/cmd/gc/racewalk.c b/src/cmd/gc/racewalk.c
deleted file mode 100644 (file)
index 3aa7e36..0000000
+++ /dev/null
@@ -1,653 +0,0 @@
-// Copyright 2012 The Go Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style
-// license that can be found in the LICENSE file.
-
-// The racewalk pass modifies the code tree for the function as follows:
-//
-// 1. It inserts a call to racefuncenter at the beginning of each function.
-// 2. It inserts a call to racefuncexit at the end of each function.
-// 3. It inserts a call to raceread before each memory read.
-// 4. It inserts a call to racewrite before each memory write.
-//
-// The rewriting is not yet complete. Certain nodes are not rewritten
-// but should be.
-
-#include <u.h>
-#include <libc.h>
-#include "go.h"
-
-// TODO(dvyukov): do not instrument initialization as writes:
-// a := make([]int, 10)
-
-static void racewalklist(NodeList *l, NodeList **init);
-static void racewalknode(Node **np, NodeList **init, int wr, int skip);
-static int callinstr(Node **n, NodeList **init, int wr, int skip);
-static Node* uintptraddr(Node *n);
-static void makeaddable(Node *n);
-static void foreach(Node *n, void(*f)(Node*, void*), void *c);
-static void hascallspred(Node *n, void *c);
-static void appendinit(Node **np, NodeList *init);
-static Node* detachexpr(Node *n, NodeList **init);
-
-// Do not instrument the following packages at all,
-// at best instrumentation would cause infinite recursion.
-static const char *omit_pkgs[] = {"runtime", "runtime/race"};
-// Only insert racefuncenter/racefuncexit into the following packages.
-// Memory accesses in the packages are either uninteresting or will cause false positives.
-static const char *noinst_pkgs[] = {"sync", "sync/atomic"};
-
-static int
-ispkgin(const char **pkgs, int n)
-{
-       int i;
-
-       if(myimportpath) {
-               for(i=0; i<n; i++) {
-                       if(strcmp(myimportpath, pkgs[i]) == 0)
-                               return 1;
-               }
-       }
-       return 0;
-}
-
-static int
-isforkfunc(Node *fn)
-{
-       // Special case for syscall.forkAndExecInChild.
-       // In the child, this function must not acquire any locks, because
-       // they might have been locked at the time of the fork.  This means
-       // no rescheduling, no malloc calls, and no new stack segments.
-       // Race instrumentation does all of the above.
-       return myimportpath != nil && strcmp(myimportpath, "syscall") == 0 &&
-               strcmp(fn->nname->sym->name, "forkAndExecInChild") == 0;
-}
-
-void
-racewalk(Node *fn)
-{
-       Node *nd;
-       Node *nodpc;
-       char s[1024];
-
-       if(ispkgin(omit_pkgs, nelem(omit_pkgs)) || isforkfunc(fn))
-               return;
-
-       if(!ispkgin(noinst_pkgs, nelem(noinst_pkgs))) {
-               racewalklist(fn->nbody, nil);
-               // nothing interesting for race detector in fn->enter
-               racewalklist(fn->exit, nil);
-       }
-
-       // nodpc is the PC of the caller as extracted by
-       // getcallerpc. We use -widthptr(FP) for x86.
-       // BUG: this will not work on arm.
-       nodpc = nod(OXXX, nil, nil);
-       *nodpc = *nodfp;
-       nodpc->type = types[TUINTPTR];
-       nodpc->xoffset = -widthptr;
-       nd = mkcall("racefuncenter", T, nil, nodpc);
-       fn->enter = concat(list1(nd), fn->enter);
-       nd = mkcall("racefuncexit", T, nil);
-       fn->exit = list(fn->exit, nd);
-
-       if(debug['W']) {
-               snprint(s, sizeof(s), "after racewalk %S", fn->nname->sym);
-               dumplist(s, fn->nbody);
-               snprint(s, sizeof(s), "enter %S", fn->nname->sym);
-               dumplist(s, fn->enter);
-               snprint(s, sizeof(s), "exit %S", fn->nname->sym);
-               dumplist(s, fn->exit);
-       }
-}
-
-static void
-racewalklist(NodeList *l, NodeList **init)
-{
-       NodeList *instr;
-
-       for(; l; l = l->next) {
-               instr = nil;
-               racewalknode(&l->n, &instr, 0, 0);
-               if(init == nil)
-                       l->n->ninit = concat(l->n->ninit, instr);
-               else
-                       *init = concat(*init, instr);
-       }
-}
-
-// walkexpr and walkstmt combined
-// walks the tree and adds calls to the
-// instrumentation code to top-level (statement) nodes' init
-static void
-racewalknode(Node **np, NodeList **init, int wr, int skip)
-{
-       Node *n, *n1;
-       NodeList *l;
-       NodeList *fini;
-
-       n = *np;
-
-       if(n == N)
-               return;
-
-       if(debug['w'] > 1)
-               dump("racewalk-before", n);
-       setlineno(n);
-       if(init == nil)
-               fatal("racewalk: bad init list");
-       if(init == &n->ninit) {
-               // If init == &n->ninit and n->ninit is non-nil,
-               // racewalknode might append it to itself.
-               // nil it out and handle it separately before putting it back.
-               l = n->ninit;
-               n->ninit = nil;
-               racewalklist(l, nil);
-               racewalknode(&n, &l, wr, skip);  // recurse with nil n->ninit
-               appendinit(&n, l);
-               *np = n;
-               return;
-       }
-
-       racewalklist(n->ninit, nil);
-
-       switch(n->op) {
-       default:
-               fatal("racewalk: unknown node type %O", n->op);
-
-       case OAS:
-       case OAS2FUNC:
-               racewalknode(&n->left, init, 1, 0);
-               racewalknode(&n->right, init, 0, 0);
-               goto ret;
-
-       case OCFUNC:
-       case OVARKILL:
-               // can't matter
-               goto ret;
-
-       case OBLOCK:
-               if(n->list == nil)
-                       goto ret;
-
-               switch(n->list->n->op) {
-               case OCALLFUNC:
-               case OCALLMETH:
-               case OCALLINTER:
-                       // Blocks are used for multiple return function calls.
-                       // x, y := f() becomes BLOCK{CALL f, AS x [SP+0], AS y [SP+n]}
-                       // We don't want to instrument between the statements because it will
-                       // smash the results.
-                       racewalknode(&n->list->n, &n->list->n->ninit, 0, 0);
-                       fini = nil;
-                       racewalklist(n->list->next, &fini);
-                       n->list = concat(n->list, fini);
-                       break;
-
-               default:
-                       // Ordinary block, for loop initialization or inlined bodies.
-                       racewalklist(n->list, nil);
-                       break;
-               }
-               goto ret;
-
-       case ODEFER:
-               racewalknode(&n->left, init, 0, 0);
-               goto ret;
-
-       case OPROC:
-               racewalknode(&n->left, init, 0, 0);
-               goto ret;
-
-       case OCALLINTER:
-               racewalknode(&n->left, init, 0, 0);
-               goto ret;
-
-       case OCALLFUNC:
-               // Instrument dst argument of runtime.writebarrier* calls
-               // as we do not instrument runtime code.
-               // typedslicecopy is instrumented in runtime.
-               if(n->left->sym != S && n->left->sym->pkg == runtimepkg && 
-               (strncmp(n->left->sym->name, "writebarrier", 12) == 0 || strcmp(n->left->sym->name, "typedmemmove") == 0)) {
-                       // Find the dst argument.
-                       // The list can be reordered, so it's not necessary just the first or the second element.
-                       for(l = n->list; l; l = l->next) {
-                               if(strcmp(n->left->sym->name, "typedmemmove") == 0) {
-                                       if(l->n->left->xoffset == widthptr)
-                                               break;
-                               } else {
-                                       if(l->n->left->xoffset == 0)
-                                               break;
-                               }
-                       }
-                       if(l == nil)
-                               fatal("racewalk: writebarrier no arg");
-                       if(l->n->right->op != OADDR)
-                               fatal("racewalk: writebarrier bad arg");
-                       callinstr(&l->n->right->left, init, 1, 0);
-               }
-               racewalknode(&n->left, init, 0, 0);
-               goto ret;
-
-       case ONOT:
-       case OMINUS:
-       case OPLUS:
-       case OREAL:
-       case OIMAG:
-       case OCOM:
-               racewalknode(&n->left, init, wr, 0);
-               goto ret;
-
-       case ODOTINTER:
-               racewalknode(&n->left, init, 0, 0);
-               goto ret;
-
-       case ODOT:
-               racewalknode(&n->left, init, 0, 1);
-               callinstr(&n, init, wr, skip);
-               goto ret;
-
-       case ODOTPTR: // dst = (*x).f with implicit *; otherwise it's ODOT+OIND
-               racewalknode(&n->left, init, 0, 0);
-               callinstr(&n, init, wr, skip);
-               goto ret;
-
-       case OIND: // *p
-               racewalknode(&n->left, init, 0, 0);
-               callinstr(&n, init, wr, skip);
-               goto ret;
-
-       case OSPTR:
-       case OLEN:
-       case OCAP:
-               racewalknode(&n->left, init, 0, 0);
-               if(istype(n->left->type, TMAP)) {
-                       n1 = nod(OCONVNOP, n->left, N);
-                       n1->type = ptrto(types[TUINT8]);
-                       n1 = nod(OIND, n1, N);
-                       typecheck(&n1, Erv);
-                       callinstr(&n1, init, 0, skip);
-               }
-               goto ret;
-
-       case OLSH:
-       case ORSH:
-       case OLROT:
-       case OAND:
-       case OANDNOT:
-       case OOR:
-       case OXOR:
-       case OSUB:
-       case OMUL:
-       case OHMUL:
-       case OEQ:
-       case ONE:
-       case OLT:
-       case OLE:
-       case OGE:
-       case OGT:
-       case OADD:
-       case OCOMPLEX:
-               racewalknode(&n->left, init, wr, 0);
-               racewalknode(&n->right, init, wr, 0);
-               goto ret;
-
-       case OANDAND:
-       case OOROR:
-               racewalknode(&n->left, init, wr, 0);
-               // walk has ensured the node has moved to a location where
-               // side effects are safe.
-               // n->right may not be executed,
-               // so instrumentation goes to n->right->ninit, not init.
-               racewalknode(&n->right, &n->right->ninit, wr, 0);
-               goto ret;
-
-       case ONAME:
-               callinstr(&n, init, wr, skip);
-               goto ret;
-
-       case OCONV:
-               racewalknode(&n->left, init, wr, 0);
-               goto ret;
-
-       case OCONVNOP:
-               racewalknode(&n->left, init, wr, 0);
-               goto ret;
-
-       case ODIV:
-       case OMOD:
-               racewalknode(&n->left, init, wr, 0);
-               racewalknode(&n->right, init, wr, 0);
-               goto ret;
-
-       case OINDEX:
-               if(!isfixedarray(n->left->type))
-                       racewalknode(&n->left, init, 0, 0);
-               else if(!islvalue(n->left)) {
-                       // index of unaddressable array, like Map[k][i].
-                       racewalknode(&n->left, init, wr, 0);
-                       racewalknode(&n->right, init, 0, 0);
-                       goto ret;
-               }
-               racewalknode(&n->right, init, 0, 0);
-               if(n->left->type->etype != TSTRING)
-                       callinstr(&n, init, wr, skip);
-               goto ret;
-
-       case OSLICE:
-       case OSLICEARR:
-       case OSLICE3:
-       case OSLICE3ARR:
-               // Seems to only lead to double instrumentation.
-               //racewalknode(&n->left, init, 0, 0);
-               goto ret;
-
-       case OADDR:
-               racewalknode(&n->left, init, 0, 1);
-               goto ret;
-
-       case OEFACE:
-               // n->left is Type* which is not interesting.
-               racewalknode(&n->right, init, 0, 0);
-               goto ret;
-
-       case OITAB:
-               racewalknode(&n->left, init, 0, 0);
-               goto ret;
-
-       // should not appear in AST by now
-       case OSEND:
-       case ORECV:
-       case OCLOSE:
-       case ONEW:
-       case OXCASE:
-       case OXFALL:
-       case OCASE:
-       case OPANIC:
-       case ORECOVER:
-       case OCONVIFACE:
-       case OCMPIFACE:
-       case OMAKECHAN:
-       case OMAKEMAP:
-       case OMAKESLICE:
-       case OCALL:
-       case OCOPY:
-       case OAPPEND:
-       case ORUNESTR:
-       case OARRAYBYTESTR:
-       case OARRAYRUNESTR:
-       case OSTRARRAYBYTE:
-       case OSTRARRAYRUNE:
-       case OINDEXMAP:  // lowered to call
-       case OCMPSTR:
-       case OADDSTR:
-       case ODOTTYPE:
-       case ODOTTYPE2:
-       case OAS2DOTTYPE:
-       case OCALLPART: // lowered to PTRLIT
-       case OCLOSURE:  // lowered to PTRLIT
-       case ORANGE:    // lowered to ordinary for loop
-       case OARRAYLIT: // lowered to assignments
-       case OMAPLIT:
-       case OSTRUCTLIT:
-       case OAS2:
-       case OAS2RECV:
-       case OAS2MAPR:
-       case OASOP:
-               yyerror("racewalk: %O must be lowered by now", n->op);
-               goto ret;
-
-       // impossible nodes: only appear in backend.
-       case ORROTC:
-       case OEXTEND:
-               yyerror("racewalk: %O cannot exist now", n->op);
-               goto ret;
-
-       // just do generic traversal
-       case OFOR:
-       case OIF:
-       case OCALLMETH:
-       case ORETURN:
-       case ORETJMP:
-       case OSWITCH:
-       case OSELECT:
-       case OEMPTY:
-       case OBREAK:
-       case OCONTINUE:
-       case OFALL:
-       case OGOTO:
-       case OLABEL:
-               goto ret;
-
-       // does not require instrumentation
-       case OPRINT:     // don't bother instrumenting it
-       case OPRINTN:    // don't bother instrumenting it
-       case OCHECKNIL: // always followed by a read.
-       case OPARAM:     // it appears only in fn->exit to copy heap params back
-       case OCLOSUREVAR:// immutable pointer to captured variable
-       case ODOTMETH:   // either part of CALLMETH or CALLPART (lowered to PTRLIT)
-       case OINDREG:    // at this stage, only n(SP) nodes from nodarg
-       case ODCL:       // declarations (without value) cannot be races
-       case ODCLCONST:
-       case ODCLTYPE:
-       case OTYPE:
-       case ONONAME:
-       case OLITERAL:
-       case OSLICESTR:  // always preceded by bounds checking, avoid double instrumentation.
-       case OTYPESW:    // ignored by code generation, do not instrument.
-               goto ret;
-       }
-
-ret:
-       if(n->op != OBLOCK)  // OBLOCK is handled above in a special way.
-               racewalklist(n->list, init);
-       if(n->ntest != N)
-               racewalknode(&n->ntest, &n->ntest->ninit, 0, 0);
-       if(n->nincr != N)
-               racewalknode(&n->nincr, &n->nincr->ninit, 0, 0);
-       racewalklist(n->nbody, nil);
-       racewalklist(n->nelse, nil);
-       racewalklist(n->rlist, nil);
-       *np = n;
-}
-
-static int
-isartificial(Node *n)
-{
-       // compiler-emitted artificial things that we do not want to instrument,
-       // cant' possibly participate in a data race.
-       if(n->op == ONAME && n->sym != S && n->sym->name != nil) {
-               if(strcmp(n->sym->name, "_") == 0)
-                       return 1;
-               // autotmp's are always local
-               if(strncmp(n->sym->name, "autotmp_", sizeof("autotmp_")-1) == 0)
-                       return 1;
-               // statictmp's are read-only
-               if(strncmp(n->sym->name, "statictmp_", sizeof("statictmp_")-1) == 0)
-                       return 1;
-               // go.itab is accessed only by the compiler and runtime (assume safe)
-               if(n->sym->pkg && n->sym->pkg->name && strcmp(n->sym->pkg->name, "go.itab") == 0)
-                       return 1;
-       }
-       return 0;
-}
-
-static int
-callinstr(Node **np, NodeList **init, int wr, int skip)
-{
-       char *name;
-       Node *f, *b, *n;
-       Type *t;
-       int class, hascalls;
-
-       n = *np;
-       //print("callinstr for %+N [ %O ] etype=%E class=%d\n",
-       //        n, n->op, n->type ? n->type->etype : -1, n->class);
-
-       if(skip || n->type == T || n->type->etype >= TIDEAL)
-               return 0;
-       t = n->type;
-       if(isartificial(n))
-               return 0;
-
-       b = outervalue(n);
-       // it skips e.g. stores to ... parameter array
-       if(isartificial(b))
-               return 0;
-       class = b->class;
-       // BUG: we _may_ want to instrument PAUTO sometimes
-       // e.g. if we've got a local variable/method receiver
-       // that has got a pointer inside. Whether it points to
-       // the heap or not is impossible to know at compile time
-       if((class&PHEAP) || class == PPARAMREF || class == PEXTERN
-               || b->op == OINDEX || b->op == ODOTPTR || b->op == OIND) {
-               hascalls = 0;
-               foreach(n, hascallspred, &hascalls);
-               if(hascalls) {
-                       n = detachexpr(n, init);
-                       *np = n;
-               }
-               n = treecopy(n);
-               makeaddable(n);
-               if(t->etype == TSTRUCT || isfixedarray(t)) {
-                       name = "racereadrange";
-                       if(wr)
-                               name = "racewriterange";
-                       f = mkcall(name, T, init, uintptraddr(n), nodintconst(t->width));
-               } else {
-                       name = "raceread";
-                       if(wr)
-                               name = "racewrite";
-                       f = mkcall(name, T, init, uintptraddr(n));
-               }
-               *init = list(*init, f);
-               return 1;
-       }
-       return 0;
-}
-
-// makeaddable returns a node whose memory location is the
-// same as n, but which is addressable in the Go language
-// sense.
-// This is different from functions like cheapexpr that may make
-// a copy of their argument.
-static void
-makeaddable(Node *n)
-{
-       // The arguments to uintptraddr technically have an address but
-       // may not be addressable in the Go sense: for example, in the case
-       // of T(v).Field where T is a struct type and v is
-       // an addressable value.
-       switch(n->op) {
-       case OINDEX:
-               if(isfixedarray(n->left->type))
-                       makeaddable(n->left);
-               break;
-       case ODOT:
-       case OXDOT:
-               // Turn T(v).Field into v.Field
-               if(n->left->op == OCONVNOP)
-                       n->left = n->left->left;
-               makeaddable(n->left);
-               break;
-       case ODOTPTR:
-       default:
-               // nothing to do
-               break;
-       }
-}
-
-static Node*
-uintptraddr(Node *n)
-{
-       Node *r;
-
-       r = nod(OADDR, n, N);
-       r->bounded = 1;
-       r = conv(r, types[TUNSAFEPTR]);
-       r = conv(r, types[TUINTPTR]);
-       return r;
-}
-
-static Node*
-detachexpr(Node *n, NodeList **init)
-{
-       Node *addr, *as, *ind, *l;
-
-       addr = nod(OADDR, n, N);
-       l = temp(ptrto(n->type));
-       as = nod(OAS, l, addr);
-       typecheck(&as, Etop);
-       walkexpr(&as, init);
-       *init = list(*init, as);
-       ind = nod(OIND, l, N);
-       typecheck(&ind, Erv);
-       walkexpr(&ind, init);
-       return ind;
-}
-
-static void
-foreachnode(Node *n, void(*f)(Node*, void*), void *c)
-{
-       if(n)
-               f(n, c);
-}
-
-static void
-foreachlist(NodeList *l, void(*f)(Node*, void*), void *c)
-{
-       for(; l; l = l->next)
-               foreachnode(l->n, f, c);
-}
-
-static void
-foreach(Node *n, void(*f)(Node*, void*), void *c)
-{
-       foreachlist(n->ninit, f, c);
-       foreachnode(n->left, f, c);
-       foreachnode(n->right, f, c);
-       foreachlist(n->list, f, c);
-       foreachnode(n->ntest, f, c);
-       foreachnode(n->nincr, f, c);
-       foreachlist(n->nbody, f, c);
-       foreachlist(n->nelse, f, c);
-       foreachlist(n->rlist, f, c);
-}
-
-static void
-hascallspred(Node *n, void *c)
-{
-       switch(n->op) {
-       case OCALL:
-       case OCALLFUNC:
-       case OCALLMETH:
-       case OCALLINTER:
-               (*(int*)c)++;
-       }
-}
-
-// appendinit is like addinit in subr.c
-// but appends rather than prepends.
-static void
-appendinit(Node **np, NodeList *init)
-{
-       Node *n;
-
-       if(init == nil)
-               return;
-
-       n = *np;
-       switch(n->op) {
-       case ONAME:
-       case OLITERAL:
-               // There may be multiple refs to this node;
-               // introduce OCONVNOP to hold init list.
-               n = nod(OCONVNOP, n, N);
-               n->type = n->left->type;
-               n->typecheck = 1;
-               *np = n;
-               break;
-       }
-       n->ninit = concat(n->ninit, init);
-       n->ullman = UINF;
-}
-
diff --git a/src/cmd/gc/range.c b/src/cmd/gc/range.c
deleted file mode 100644 (file)
index ff9de6c..0000000
+++ /dev/null
@@ -1,378 +0,0 @@
-// Copyright 2009 The Go Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style
-// license that can be found in the LICENSE file.
-
-/*
- * range
- */
-
-#include <u.h>
-#include <libc.h>
-#include "go.h"
-
-void
-typecheckrange(Node *n)
-{
-       int toomany;
-       char *why;
-       Type *t, *t1, *t2;
-       Node *v1, *v2;
-       NodeList *ll;
-
-       // Typechecking order is important here:
-       // 0. first typecheck range expression (slice/map/chan),
-       //      it is evaluated only once and so logically it is not part of the loop.
-       // 1. typcheck produced values,
-       //      this part can declare new vars and so it must be typechecked before body,
-       //      because body can contain a closure that captures the vars.
-       // 2. decldepth++ to denote loop body.
-       // 3. typecheck body.
-       // 4. decldepth--.
-
-       typecheck(&n->right, Erv);
-       if((t = n->right->type) == T)
-               goto out;
-
-       // delicate little dance.  see typecheckas2
-       for(ll=n->list; ll; ll=ll->next)
-               if(ll->n->defn != n)
-                       typecheck(&ll->n, Erv | Easgn);
-
-       if(isptr[t->etype] && isfixedarray(t->type))
-               t = t->type;
-       n->type = t;
-
-       toomany = 0;
-       switch(t->etype) {
-       default:
-               yyerror("cannot range over %lN", n->right);
-               goto out;
-
-       case TARRAY:
-               t1 = types[TINT];
-               t2 = t->type;
-               break;
-
-       case TMAP:
-               t1 = t->down;
-               t2 = t->type;
-               break;
-
-       case TCHAN:
-               if(!(t->chan & Crecv)) {
-                       yyerror("invalid operation: range %N (receive from send-only type %T)", n->right, n->right->type);
-                       goto out;
-               }
-               t1 = t->type;
-               t2 = nil;
-               if(count(n->list) == 2)
-                       toomany = 1;
-               break;
-
-       case TSTRING:
-               t1 = types[TINT];
-               t2 = runetype;
-               break;
-       }
-
-       if(count(n->list) > 2 || toomany)
-               yyerror("too many variables in range");
-
-       v1 = N;
-       if(n->list)
-               v1 = n->list->n;
-       v2 = N;
-       if(n->list && n->list->next)
-               v2 = n->list->next->n;
-
-       // this is not only a optimization but also a requirement in the spec.
-       // "if the second iteration variable is the blank identifier, the range
-       // clause is equivalent to the same clause with only the first variable
-       // present."
-       if(isblank(v2)) {
-               if(v1 != N)
-                       n->list = list1(v1);
-               v2 = N;
-       }
-
-       if(v1) {
-               if(v1->defn == n)
-                       v1->type = t1;
-               else if(v1->type != T && assignop(t1, v1->type, &why) == 0)
-                       yyerror("cannot assign type %T to %lN in range%s", t1, v1, why);
-               checkassign(n, v1);
-       }
-       if(v2) {
-               if(v2->defn == n)
-                       v2->type = t2;
-               else if(v2->type != T && assignop(t2, v2->type, &why) == 0)
-                       yyerror("cannot assign type %T to %lN in range%s", t2, v2, why);
-               checkassign(n, v2);
-       }
-
-out:
-       // second half of dance
-       n->typecheck = 1;
-       for(ll=n->list; ll; ll=ll->next)
-               if(ll->n->typecheck == 0)
-                       typecheck(&ll->n, Erv | Easgn);
-
-       decldepth++;
-       typechecklist(n->nbody, Etop);
-       decldepth--;
-}
-
-void
-walkrange(Node *n)
-{
-       Node *ohv1, *hv1, *hv2; // hidden (old) val 1, 2
-       Node *ha, *hit; // hidden aggregate, iterator
-       Node *hn, *hp;  // hidden len, pointer
-       Node *hb;  // hidden bool
-       Node *a, *v1, *v2;      // not hidden aggregate, val 1, 2
-       Node *fn, *tmp;
-       Node *keyname, *valname;
-       Node *key, *val;
-       NodeList *body, *init;
-       Type *th, *t;
-       int lno;
-
-       t = n->type;
-       init = nil;
-
-       a = n->right;
-       lno = setlineno(a);
-
-       v1 = N;
-       if(n->list)
-               v1 = n->list->n;
-       v2 = N;
-       if(n->list && n->list->next && !isblank(n->list->next->n))
-               v2 = n->list->next->n;
-       // n->list has no meaning anymore, clear it
-       // to avoid erroneous processing by racewalk.
-       n->list = nil;
-       hv2 = N;
-
-       switch(t->etype) {
-       default:
-               fatal("walkrange");
-
-       case TARRAY:
-               // Lower n into runtime·memclr if possible, for
-               // fast zeroing of slices and arrays (issue 5373).
-               // Look for instances of
-               //
-               // for i := range a {
-               //      a[i] = zero
-               // }
-               //
-               // in which the evaluation of a is side-effect-free.
-               if(!debug['N'])
-               if(!flag_race)
-               if(v1 != N)
-               if(v2 == N)
-               if(n->nbody != nil)
-               if(n->nbody->n != N)    // at least one statement in body
-               if(n->nbody->next == nil) {     // at most one statement in body
-                       tmp = n->nbody->n;      // first statement of body
-                       if(tmp->op == OAS)
-                       if(tmp->left->op == OINDEX)
-                       if(samesafeexpr(tmp->left->left, a))
-                       if(samesafeexpr(tmp->left->right, v1))
-                       if(t->type->width > 0)
-                       if(iszero(tmp->right)) {
-                               // Convert to
-                               // if len(a) != 0 {
-                               //      hp = &a[0]
-                               //      hn = len(a)*sizeof(elem(a))
-                               //      memclr(hp, hn)
-                               //      i = len(a) - 1
-                               // }
-                               n->op = OIF;
-                               n->nbody = nil;
-                               n->ntest = nod(ONE, nod(OLEN, a, N), nodintconst(0));
-                               n->nincr = nil;
-
-                               // hp = &a[0]
-                               hp = temp(ptrto(types[TUINT8]));
-                               tmp = nod(OINDEX, a, nodintconst(0));
-                               tmp->bounded = 1;
-                               tmp = nod(OADDR, tmp, N);
-                               tmp = nod(OCONVNOP, tmp, N);
-                               tmp->type = ptrto(types[TUINT8]);
-                               n->nbody = list(n->nbody, nod(OAS, hp, tmp));
-
-                               // hn = len(a) * sizeof(elem(a))
-                               hn = temp(types[TUINTPTR]);
-                               tmp = nod(OLEN, a, N);
-                               tmp = nod(OMUL, tmp, nodintconst(t->type->width));
-                               tmp = conv(tmp, types[TUINTPTR]);
-                               n->nbody = list(n->nbody, nod(OAS, hn, tmp));
-
-                               // memclr(hp, hn)
-                               fn = mkcall("memclr", T, nil, hp, hn);
-                               n->nbody = list(n->nbody, fn);
-
-                               // i = len(a) - 1
-                               v1 = nod(OAS, v1, nod(OSUB, nod(OLEN, a, N), nodintconst(1)));
-                               n->nbody = list(n->nbody, v1);
-
-                               typecheck(&n->ntest, Erv);
-                               typechecklist(n->nbody, Etop);
-                               walkstmt(&n);
-                               lineno = lno;
-                               return;
-                       }
-               }
-
-               // orderstmt arranged for a copy of the array/slice variable if needed.
-               ha = a;
-               hv1 = temp(types[TINT]);
-               hn = temp(types[TINT]);
-               hp = nil;
-
-               init = list(init, nod(OAS, hv1, N));
-               init = list(init, nod(OAS, hn, nod(OLEN, ha, N)));
-               if(v2) {
-                       hp = temp(ptrto(n->type->type));
-                       tmp = nod(OINDEX, ha, nodintconst(0));
-                       tmp->bounded = 1;
-                       init = list(init, nod(OAS, hp, nod(OADDR, tmp, N)));
-               }
-
-               n->ntest = nod(OLT, hv1, hn);
-               n->nincr = nod(OAS, hv1, nod(OADD, hv1, nodintconst(1)));
-               if(v1 == N)
-                       body = nil;
-               else if(v2 == N)
-                       body = list1(nod(OAS, v1, hv1));
-               else {
-                       a = nod(OAS2, N, N);
-                       a->list = list(list1(v1), v2);
-                       a->rlist = list(list1(hv1), nod(OIND, hp, N));
-                       body = list1(a);
-                       
-                       // Advance pointer as part of increment.
-                       // We used to advance the pointer before executing the loop body,
-                       // but doing so would make the pointer point past the end of the
-                       // array during the final iteration, possibly causing another unrelated
-                       // piece of memory not to be garbage collected until the loop finished.
-                       // Advancing during the increment ensures that the pointer p only points
-                       // pass the end of the array during the final "p++; i++; if(i >= len(x)) break;",
-                       // after which p is dead, so it cannot confuse the collector.
-                       tmp = nod(OADD, hp, nodintconst(t->type->width));
-                       tmp->type = hp->type;
-                       tmp->typecheck = 1;
-                       tmp->right->type = types[tptr];
-                       tmp->right->typecheck = 1;
-                       a = nod(OAS, hp, tmp);
-                       typecheck(&a, Etop);
-                       n->nincr->ninit = list1(a);
-               }
-               break;
-
-       case TMAP:
-               // orderstmt allocated the iterator for us.
-               // we only use a once, so no copy needed.
-               ha = a;
-               th = hiter(t);
-               hit = n->alloc;
-               hit->type = th;
-               n->left = N;
-               keyname = newname(th->type->sym);  // depends on layout of iterator struct.  See reflect.c:hiter
-               valname = newname(th->type->down->sym); // ditto
-
-               fn = syslook("mapiterinit", 1);
-               argtype(fn, t->down);
-               argtype(fn, t->type);
-               argtype(fn, th);
-               init = list(init, mkcall1(fn, T, nil, typename(t), ha, nod(OADDR, hit, N)));
-               n->ntest = nod(ONE, nod(ODOT, hit, keyname), nodnil());
-
-               fn = syslook("mapiternext", 1);
-               argtype(fn, th);
-               n->nincr = mkcall1(fn, T, nil, nod(OADDR, hit, N));
-
-               key = nod(ODOT, hit, keyname);
-               key = nod(OIND, key, N);
-               if(v1 == N)
-                       body = nil;
-               else if(v2 == N) {
-                       body = list1(nod(OAS, v1, key));
-               } else {
-                       val = nod(ODOT, hit, valname);
-                       val = nod(OIND, val, N);
-                       a = nod(OAS2, N, N);
-                       a->list = list(list1(v1), v2);
-                       a->rlist = list(list1(key), val);
-                       body = list1(a);
-               }
-               break;
-
-       case TCHAN:
-               // orderstmt arranged for a copy of the channel variable.
-               ha = a;
-               n->ntest = N;
-               
-               hv1 = temp(t->type);
-               hv1->typecheck = 1;
-               if(haspointers(t->type))
-                       init = list(init, nod(OAS, hv1, N));
-               hb = temp(types[TBOOL]);
-
-               n->ntest = nod(ONE, hb, nodbool(0));
-               a = nod(OAS2RECV, N, N);
-               a->typecheck = 1;
-               a->list = list(list1(hv1), hb);
-               a->rlist = list1(nod(ORECV, ha, N));
-               n->ntest->ninit = list1(a);
-               if(v1 == N)
-                       body = nil;
-               else
-                       body = list1(nod(OAS, v1, hv1));
-               break;
-
-       case TSTRING:
-               // orderstmt arranged for a copy of the string variable.
-               ha = a;
-
-               ohv1 = temp(types[TINT]);
-
-               hv1 = temp(types[TINT]);
-               init = list(init, nod(OAS, hv1, N));
-
-               if(v2 == N)
-                       a = nod(OAS, hv1, mkcall("stringiter", types[TINT], nil, ha, hv1));
-               else {
-                       hv2 = temp(runetype);
-                       a = nod(OAS2, N, N);
-                       a->list = list(list1(hv1), hv2);
-                       fn = syslook("stringiter2", 0);
-                       a->rlist = list1(mkcall1(fn, getoutargx(fn->type), nil, ha, hv1));
-               }
-               n->ntest = nod(ONE, hv1, nodintconst(0));
-               n->ntest->ninit = list(list1(nod(OAS, ohv1, hv1)), a);
-
-               
-               body = nil;
-               if(v1 != N)
-                       body = list1(nod(OAS, v1, ohv1));
-               if(v2 != N)
-                       body = list(body, nod(OAS, v2, hv2));
-               break;
-       }
-
-       n->op = OFOR;
-       typechecklist(init, Etop);
-       n->ninit = concat(n->ninit, init);
-       typechecklist(n->ntest->ninit, Etop);
-       typecheck(&n->ntest, Erv);
-       typecheck(&n->nincr, Etop);
-       typechecklist(body, Etop);
-       n->nbody = concat(body, n->nbody);
-       walkstmt(&n);
-       
-       lineno = lno;
-}
-
diff --git a/src/cmd/gc/reflect.c b/src/cmd/gc/reflect.c
deleted file mode 100644 (file)
index 9390ab9..0000000
+++ /dev/null
@@ -1,1609 +0,0 @@
-// Copyright 2009 The Go Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style
-// license that can be found in the LICENSE file.
-
-#include <u.h>
-#include <libc.h>
-#include "go.h"
-#include "../ld/textflag.h"
-#include "../../runtime/mgc0.h"
-#include "../../runtime/typekind.h"
-
-/*
- * runtime interface and reflection data structures
- */
-
-static NodeList*       signatlist;
-static Sym*    dtypesym(Type*);
-static Sym*    weaktypesym(Type*);
-static Sym*    dalgsym(Type*);
-static int     usegcprog(Type*);
-static void    gengcprog(Type*, Sym**, Sym**);
-static void    gengcmask(Type*, uint8[16]);
-
-static int
-sigcmp(Sig *a, Sig *b)
-{
-       int i;
-
-       i = strcmp(a->name, b->name);
-       if(i != 0)
-               return i;
-       if(a->pkg == b->pkg)
-               return 0;
-       if(a->pkg == nil)
-               return -1;
-       if(b->pkg == nil)
-               return +1;
-       return strcmp(a->pkg->path->s, b->pkg->path->s);
-}
-
-static Sig*
-lsort(Sig *l, int(*f)(Sig*, Sig*))
-{
-       Sig *l1, *l2, *le;
-
-       if(l == 0 || l->link == 0)
-               return l;
-
-       l1 = l;
-       l2 = l;
-       for(;;) {
-               l2 = l2->link;
-               if(l2 == 0)
-                       break;
-               l2 = l2->link;
-               if(l2 == 0)
-                       break;
-               l1 = l1->link;
-       }
-
-       l2 = l1->link;
-       l1->link = 0;
-       l1 = lsort(l, f);
-       l2 = lsort(l2, f);
-
-       /* set up lead element */
-       if((*f)(l1, l2) < 0) {
-               l = l1;
-               l1 = l1->link;
-       } else {
-               l = l2;
-               l2 = l2->link;
-       }
-       le = l;
-
-       for(;;) {
-               if(l1 == 0) {
-                       while(l2) {
-                               le->link = l2;
-                               le = l2;
-                               l2 = l2->link;
-                       }
-                       le->link = 0;
-                       break;
-               }
-               if(l2 == 0) {
-                       while(l1) {
-                               le->link = l1;
-                               le = l1;
-                               l1 = l1->link;
-                       }
-                       break;
-               }
-               if((*f)(l1, l2) < 0) {
-                       le->link = l1;
-                       le = l1;
-                       l1 = l1->link;
-               } else {
-                       le->link = l2;
-                       le = l2;
-                       l2 = l2->link;
-               }
-       }
-       le->link = 0;
-       return l;
-}
-
-// Builds a type respresenting a Bucket structure for
-// the given map type.  This type is not visible to users -
-// we include only enough information to generate a correct GC
-// program for it.
-// Make sure this stays in sync with ../../runtime/hashmap.c!
-enum {
-       BUCKETSIZE = 8,
-       MAXKEYSIZE = 128,
-       MAXVALSIZE = 128,
-};
-
-static Type*
-makefield(char *name, Type *t)
-{
-       Type *f;
-
-       f = typ(TFIELD);
-       f->type = t;
-       f->sym = mal(sizeof(Sym));
-       f->sym->name = name;
-       return f;
-}
-
-Type*
-mapbucket(Type *t)
-{
-       Type *keytype, *valtype;
-       Type *bucket, *arr;
-       Type *field[4];
-       int32 n;
-
-       if(t->bucket != T)
-               return t->bucket;
-
-       bucket = typ(TSTRUCT);
-       keytype = t->down;
-       valtype = t->type;
-       dowidth(keytype);
-       dowidth(valtype);
-       if(keytype->width > MAXKEYSIZE)
-               keytype = ptrto(keytype);
-       if(valtype->width > MAXVALSIZE)
-               valtype = ptrto(valtype);
-
-       // The first field is: uint8 topbits[BUCKETSIZE].
-       arr = typ(TARRAY);
-       arr->type = types[TUINT8];
-       arr->bound = BUCKETSIZE;
-       field[0] = makefield("topbits", arr);
-       arr = typ(TARRAY);
-       arr->type = keytype;
-       arr->bound = BUCKETSIZE;
-       field[1] = makefield("keys", arr);
-       arr = typ(TARRAY);
-       arr->type = valtype;
-       arr->bound = BUCKETSIZE;
-       field[2] = makefield("values", arr);
-       field[3] = makefield("overflow", ptrto(bucket));
-
-       // link up fields
-       bucket->noalg = 1;
-       bucket->local = t->local;
-       bucket->type = field[0];
-       for(n = 0; n < nelem(field)-1; n++)
-               field[n]->down = field[n+1];
-       field[nelem(field)-1]->down = T;
-       dowidth(bucket);
-
-       // Pad to the native integer alignment.
-       // This is usually the same as widthptr; the exception (as usual) is amd64p32.
-       if(widthreg > widthptr)
-               bucket->width += widthreg - widthptr;
-
-       // See comment on hmap.overflow in ../../runtime/hashmap.go.
-       if(!haspointers(t->type) && !haspointers(t->down) &&
-               t->type->width <= MAXKEYSIZE && t->down->width <= MAXVALSIZE)
-               bucket->haspointers = 1;  // no pointers
-
-       t->bucket = bucket;
-       bucket->map = t;
-       return bucket;
-}
-
-// Builds a type representing a Hmap structure for the given map type.
-// Make sure this stays in sync with ../../runtime/hashmap.go!
-Type*
-hmap(Type *t)
-{
-       Type *h, *bucket;
-       Type *field[8];
-       int32 n;
-
-       if(t->hmap != T)
-               return t->hmap;
-
-       bucket = mapbucket(t);
-       field[0] = makefield("count", types[TINT]);
-       field[1] = makefield("flags", types[TUINT8]);
-       field[2] = makefield("B", types[TUINT8]);
-       field[3] = makefield("hash0", types[TUINT32]);
-       field[4] = makefield("buckets", ptrto(bucket));
-       field[5] = makefield("oldbuckets", ptrto(bucket));
-       field[6] = makefield("nevacuate", types[TUINTPTR]);
-       field[7] = makefield("overflow", types[TUNSAFEPTR]);
-
-       h = typ(TSTRUCT);
-       h->noalg = 1;
-       h->local = t->local;
-       h->type = field[0];
-       for(n = 0; n < nelem(field)-1; n++)
-               field[n]->down = field[n+1];
-       field[nelem(field)-1]->down = T;
-       dowidth(h);
-       t->hmap = h;
-       h->map = t;
-       return h;
-}
-
-Type*
-hiter(Type *t)
-{
-       int32 n;
-       Type *field[12];
-       Type *i;
-
-       if(t->hiter != T)
-               return t->hiter;
-
-       // build a struct:
-       // hash_iter {
-       //    key *Key
-       //    val *Value
-       //    t *MapType
-       //    h *Hmap
-       //    buckets *Bucket
-       //    bptr *Bucket
-       //    overflow0 unsafe.Pointer
-       //    overflow1 unsafe.Pointer
-       //    startBucket uintptr
-       //    stuff uintptr
-       //    bucket uintptr
-       //    checkBucket uintptr
-       // }
-       // must match ../../runtime/hashmap.c:hash_iter.
-       field[0] = makefield("key", ptrto(t->down));
-       field[1] = makefield("val", ptrto(t->type));
-       field[2] = makefield("t", ptrto(types[TUINT8]));
-       field[3] = makefield("h", ptrto(hmap(t)));
-       field[4] = makefield("buckets", ptrto(mapbucket(t)));
-       field[5] = makefield("bptr", ptrto(mapbucket(t)));
-       field[6] = makefield("overflow0", types[TUNSAFEPTR]);
-       field[7] = makefield("overflow1", types[TUNSAFEPTR]);
-       field[8] = makefield("startBucket", types[TUINTPTR]);
-       field[9] = makefield("stuff", types[TUINTPTR]); // offset+wrapped+B+I
-       field[10] = makefield("bucket", types[TUINTPTR]);
-       field[11] = makefield("checkBucket", types[TUINTPTR]);
-       
-       // build iterator struct holding the above fields
-       i = typ(TSTRUCT);
-       i->noalg = 1;
-       i->type = field[0];
-       for(n = 0; n < nelem(field)-1; n++)
-               field[n]->down = field[n+1];
-       field[nelem(field)-1]->down = T;
-       dowidth(i);
-       if(i->width != 12 * widthptr)
-               yyerror("hash_iter size not correct %d %d", i->width, 12 * widthptr);
-       t->hiter = i;
-       i->map = t;
-       return i;
-}
-
-/*
- * f is method type, with receiver.
- * return function type, receiver as first argument (or not).
- */
-Type*
-methodfunc(Type *f, Type *receiver)
-{
-       NodeList *in, *out;
-       Node *d;
-       Type *t;
-
-       in = nil;
-       if(receiver) {
-               d = nod(ODCLFIELD, N, N);
-               d->type = receiver;
-               in = list(in, d);
-       }
-       for(t=getinargx(f)->type; t; t=t->down) {
-               d = nod(ODCLFIELD, N, N);
-               d->type = t->type;
-               d->isddd = t->isddd;
-               in = list(in, d);
-       }
-
-       out = nil;
-       for(t=getoutargx(f)->type; t; t=t->down) {
-               d = nod(ODCLFIELD, N, N);
-               d->type = t->type;
-               out = list(out, d);
-       }
-
-       t = functype(N, in, out);
-       if(f->nname) {
-               // Link to name of original method function.
-               t->nname = f->nname;
-       }
-       return t;
-}
-
-/*
- * return methods of non-interface type t, sorted by name.
- * generates stub functions as needed.
- */
-static Sig*
-methods(Type *t)
-{
-       Type *f, *mt, *it, *this;
-       Sig *a, *b;
-       Sym *method;
-
-       // method type
-       mt = methtype(t, 0);
-       if(mt == T)
-               return nil;
-       expandmeth(mt);
-
-       // type stored in interface word
-       it = t;
-       if(!isdirectiface(it))
-               it = ptrto(t);
-
-       // make list of methods for t,
-       // generating code if necessary.
-       a = nil;
-       for(f=mt->xmethod; f; f=f->down) {
-               if(f->etype != TFIELD)
-                       fatal("methods: not field %T", f);
-               if (f->type->etype != TFUNC || f->type->thistuple == 0)
-                       fatal("non-method on %T method %S %T\n", mt, f->sym, f);
-               if (!getthisx(f->type)->type)
-                       fatal("receiver with no type on %T method %S %T\n", mt, f->sym, f);
-               if(f->nointerface)
-                       continue;
-
-               method = f->sym;
-               if(method == nil)
-                       continue;
-
-               // get receiver type for this particular method.
-               // if pointer receiver but non-pointer t and
-               // this is not an embedded pointer inside a struct,
-               // method does not apply.
-               this = getthisx(f->type)->type->type;
-               if(isptr[this->etype] && this->type == t)
-                       continue;
-               if(isptr[this->etype] && !isptr[t->etype]
-               && f->embedded != 2 && !isifacemethod(f->type))
-                       continue;
-
-               b = mal(sizeof(*b));
-               b->link = a;
-               a = b;
-
-               a->name = method->name;
-               if(!exportname(method->name)) {
-                       if(method->pkg == nil)
-                               fatal("methods: missing package");
-                       a->pkg = method->pkg;
-               }
-               a->isym = methodsym(method, it, 1);
-               a->tsym = methodsym(method, t, 0);
-               a->type = methodfunc(f->type, t);
-               a->mtype = methodfunc(f->type, nil);
-
-               if(!(a->isym->flags & SymSiggen)) {
-                       a->isym->flags |= SymSiggen;
-                       if(!eqtype(this, it) || this->width < types[tptr]->width) {
-                               compiling_wrappers = 1;
-                               genwrapper(it, f, a->isym, 1);
-                               compiling_wrappers = 0;
-                       }
-               }
-
-               if(!(a->tsym->flags & SymSiggen)) {
-                       a->tsym->flags |= SymSiggen;
-                       if(!eqtype(this, t)) {
-                               compiling_wrappers = 1;
-                               genwrapper(t, f, a->tsym, 0);
-                               compiling_wrappers = 0;
-                       }
-               }
-       }
-
-       return lsort(a, sigcmp);
-}
-
-/*
- * return methods of interface type t, sorted by name.
- */
-static Sig*
-imethods(Type *t)
-{
-       Sig *a, *all, *last;
-       Type *f;
-       Sym *method, *isym;
-
-       all = nil;
-       last = nil;
-       for(f=t->type; f; f=f->down) {
-               if(f->etype != TFIELD)
-                       fatal("imethods: not field");
-               if(f->type->etype != TFUNC || f->sym == nil)
-                       continue;
-               method = f->sym;
-               a = mal(sizeof(*a));
-               a->name = method->name;
-               if(!exportname(method->name)) {
-                       if(method->pkg == nil)
-                               fatal("imethods: missing package");
-                       a->pkg = method->pkg;
-               }
-               a->mtype = f->type;
-               a->offset = 0;
-               a->type = methodfunc(f->type, nil);
-
-               if(last && sigcmp(last, a) >= 0)
-                       fatal("sigcmp vs sortinter %s %s", last->name, a->name);
-               if(last == nil)
-                       all = a;
-               else
-                       last->link = a;
-               last = a;
-
-               // Compiler can only refer to wrappers for non-blank methods.
-               if(isblanksym(method))
-                       continue;
-
-               // NOTE(rsc): Perhaps an oversight that
-               // IfaceType.Method is not in the reflect data.
-               // Generate the method body, so that compiled
-               // code can refer to it.
-               isym = methodsym(method, t, 0);
-               if(!(isym->flags & SymSiggen)) {
-                       isym->flags |= SymSiggen;
-                       genwrapper(t, f, isym, 0);
-               }
-       }
-       return all;
-}
-
-static void
-dimportpath(Pkg *p)
-{
-       static Pkg *gopkg;
-       char *nam;
-       Node *n;
-
-       if(p->pathsym != S)
-               return;
-
-       if(gopkg == nil) {
-               gopkg = mkpkg(newstrlit("go"));
-               gopkg->name = "go";
-       }
-       nam = smprint("importpath.%s.", p->prefix);
-
-       n = nod(ONAME, N, N);
-       n->sym = pkglookup(nam, gopkg);
-       free(nam);
-       n->class = PEXTERN;
-       n->xoffset = 0;
-       p->pathsym = n->sym;
-
-       gdatastring(n, p->path);
-       ggloblsym(n->sym, types[TSTRING]->width, DUPOK|RODATA);
-}
-
-static int
-dgopkgpath(Sym *s, int ot, Pkg *pkg)
-{
-       if(pkg == nil)
-               return dgostringptr(s, ot, nil);
-
-       // Emit reference to go.importpath.""., which 6l will
-       // rewrite using the correct import path.  Every package
-       // that imports this one directly defines the symbol.
-       if(pkg == localpkg) {
-               static Sym *ns;
-
-               if(ns == nil)
-                       ns = pkglookup("importpath.\"\".", mkpkg(newstrlit("go")));
-               return dsymptr(s, ot, ns, 0);
-       }
-
-       dimportpath(pkg);
-       return dsymptr(s, ot, pkg->pathsym, 0);
-}
-
-/*
- * uncommonType
- * ../../runtime/type.go:/uncommonType
- */
-static int
-dextratype(Sym *sym, int off, Type *t, int ptroff)
-{
-       int ot, n;
-       Sym *s;
-       Sig *a, *m;
-
-       m = methods(t);
-       if(t->sym == nil && m == nil)
-               return off;
-
-       // fill in *extraType pointer in header
-       off = rnd(off, widthptr);
-       dsymptr(sym, ptroff, sym, off);
-
-       n = 0;
-       for(a=m; a; a=a->link) {
-               dtypesym(a->type);
-               n++;
-       }
-
-       ot = off;
-       s = sym;
-       if(t->sym) {
-               ot = dgostringptr(s, ot, t->sym->name);
-               if(t != types[t->etype] && t != errortype)
-                       ot = dgopkgpath(s, ot, t->sym->pkg);
-               else
-                       ot = dgostringptr(s, ot, nil);
-       } else {
-               ot = dgostringptr(s, ot, nil);
-               ot = dgostringptr(s, ot, nil);
-       }
-
-       // slice header
-       ot = dsymptr(s, ot, s, ot + widthptr + 2*widthint);
-       ot = duintxx(s, ot, n, widthint);
-       ot = duintxx(s, ot, n, widthint);
-
-       // methods
-       for(a=m; a; a=a->link) {
-               // method
-               // ../../runtime/type.go:/method
-               ot = dgostringptr(s, ot, a->name);
-               ot = dgopkgpath(s, ot, a->pkg);
-               ot = dsymptr(s, ot, dtypesym(a->mtype), 0);
-               ot = dsymptr(s, ot, dtypesym(a->type), 0);
-               if(a->isym)
-                       ot = dsymptr(s, ot, a->isym, 0);
-               else
-                       ot = duintptr(s, ot, 0);
-               if(a->tsym)
-                       ot = dsymptr(s, ot, a->tsym, 0);
-               else
-                       ot = duintptr(s, ot, 0);
-       }
-
-       return ot;
-}
-
-static int
-kinds[] =
-{
-       [TINT]          = KindInt,
-       [TUINT]         = KindUint,
-       [TINT8]         = KindInt8,
-       [TUINT8]        = KindUint8,
-       [TINT16]        = KindInt16,
-       [TUINT16]       = KindUint16,
-       [TINT32]        = KindInt32,
-       [TUINT32]       = KindUint32,
-       [TINT64]        = KindInt64,
-       [TUINT64]       = KindUint64,
-       [TUINTPTR]      = KindUintptr,
-       [TFLOAT32]      = KindFloat32,
-       [TFLOAT64]      = KindFloat64,
-       [TBOOL]         = KindBool,
-       [TSTRING]               = KindString,
-       [TPTR32]                = KindPtr,
-       [TPTR64]                = KindPtr,
-       [TSTRUCT]       = KindStruct,
-       [TINTER]                = KindInterface,
-       [TCHAN]         = KindChan,
-       [TMAP]          = KindMap,
-       [TARRAY]                = KindArray,
-       [TFUNC]         = KindFunc,
-       [TCOMPLEX64]    = KindComplex64,
-       [TCOMPLEX128]   = KindComplex128,
-       [TUNSAFEPTR]    = KindUnsafePointer,
-};
-
-int
-haspointers(Type *t)
-{
-       Type *t1;
-       int ret;
-
-       if(t->haspointers != 0)
-               return t->haspointers - 1;
-
-       switch(t->etype) {
-       case TINT:
-       case TUINT:
-       case TINT8:
-       case TUINT8:
-       case TINT16:
-       case TUINT16:
-       case TINT32:
-       case TUINT32:
-       case TINT64:
-       case TUINT64:
-       case TUINTPTR:
-       case TFLOAT32:
-       case TFLOAT64:
-       case TCOMPLEX64:
-       case TCOMPLEX128:
-       case TBOOL:
-               ret = 0;
-               break;
-       case TARRAY:
-               if(t->bound < 0) {      // slice
-                       ret = 1;
-                       break;
-               }
-               if(t->bound == 0) {     // empty array
-                       ret = 0;
-                       break;
-               }
-               ret = haspointers(t->type);
-               break;
-       case TSTRUCT:
-               ret = 0;
-               for(t1=t->type; t1!=T; t1=t1->down) {
-                       if(haspointers(t1->type)) {
-                               ret = 1;
-                               break;
-                       }
-               }
-               break;
-       case TSTRING:
-       case TPTR32:
-       case TPTR64:
-       case TUNSAFEPTR:
-       case TINTER:
-       case TCHAN:
-       case TMAP:
-       case TFUNC:
-       default:
-               ret = 1;
-               break;
-       }
-       
-       t->haspointers = 1+ret;
-       return ret;
-}
-
-/*
- * commonType
- * ../../runtime/type.go:/commonType
- */
-static int
-dcommontype(Sym *s, int ot, Type *t)
-{
-       int i, alg, sizeofAlg, gcprog;
-       Sym *sptr, *algsym, *zero, *gcprog0, *gcprog1, *sbits;
-       uint8 gcmask[16];
-       static Sym *algarray;
-       uint64 x1, x2;
-       char *p;
-       
-       if(ot != 0)
-               fatal("dcommontype %d", ot);
-
-       sizeofAlg = 2*widthptr;
-       if(algarray == nil)
-               algarray = pkglookup("algarray", runtimepkg);
-       dowidth(t);
-       alg = algtype(t);
-       algsym = S;
-       if(alg < 0 || alg == AMEM)
-               algsym = dalgsym(t);
-
-       if(t->sym != nil && !isptr[t->etype])
-               sptr = dtypesym(ptrto(t));
-       else
-               sptr = weaktypesym(ptrto(t));
-
-       // All (non-reflect-allocated) Types share the same zero object.
-       // Each place in the compiler where a pointer to the zero object
-       // might be returned by a runtime call (map access return value,
-       // 2-arg type cast) declares the size of the zerovalue it needs.
-       // The linker magically takes the max of all the sizes.
-       zero = pkglookup("zerovalue", runtimepkg);
-
-       // We use size 0 here so we get the pointer to the zero value,
-       // but don't allocate space for the zero value unless we need it.
-       // TODO: how do we get this symbol into bss?  We really want
-       // a read-only bss, but I don't think such a thing exists.
-
-       // ../../pkg/reflect/type.go:/^type.commonType
-       // actual type structure
-       //      type commonType struct {
-       //              size          uintptr
-       //              hash          uint32
-       //              _             uint8
-       //              align         uint8
-       //              fieldAlign    uint8
-       //              kind          uint8
-       //              alg           unsafe.Pointer
-       //              gc            unsafe.Pointer
-       //              string        *string
-       //              *extraType
-       //              ptrToThis     *Type
-       //              zero          unsafe.Pointer
-       //      }
-       ot = duintptr(s, ot, t->width);
-       ot = duint32(s, ot, typehash(t));
-       ot = duint8(s, ot, 0);  // unused
-
-       // runtime (and common sense) expects alignment to be a power of two.
-       i = t->align;
-       if(i == 0)
-               i = 1;
-       if((i&(i-1)) != 0)
-               fatal("invalid alignment %d for %T", t->align, t);
-       ot = duint8(s, ot, t->align);   // align
-       ot = duint8(s, ot, t->align);   // fieldAlign
-
-       gcprog = usegcprog(t);
-       i = kinds[t->etype];
-       if(t->etype == TARRAY && t->bound < 0)
-               i = KindSlice;
-       if(!haspointers(t))
-               i |= KindNoPointers;
-       if(isdirectiface(t))
-               i |= KindDirectIface;
-       if(gcprog)
-               i |= KindGCProg;
-       ot = duint8(s, ot, i);  // kind
-       if(algsym == S)
-               ot = dsymptr(s, ot, algarray, alg*sizeofAlg);
-       else
-               ot = dsymptr(s, ot, algsym, 0);
-       // gc
-       if(gcprog) {
-               gengcprog(t, &gcprog0, &gcprog1);
-               if(gcprog0 != S)
-                       ot = dsymptr(s, ot, gcprog0, 0);
-               else
-                       ot = duintptr(s, ot, 0);
-               ot = dsymptr(s, ot, gcprog1, 0);
-       } else {
-               gengcmask(t, gcmask);
-               x1 = 0;
-               for(i=0; i<8; i++)
-                       x1 = x1<<8 | gcmask[i];
-               if(widthptr == 4) {
-                       p = smprint("gcbits.0x%016llux", x1);
-               } else {
-                       x2 = 0;
-                       for(i=0; i<8; i++)
-                               x2 = x2<<8 | gcmask[i+8];
-                       p = smprint("gcbits.0x%016llux%016llux", x1, x2);
-               }
-               sbits = pkglookup(p, runtimepkg);
-               if((sbits->flags & SymUniq) == 0) {
-                       sbits->flags |= SymUniq;
-                       for(i = 0; i < 2*widthptr; i++)
-                               duint8(sbits, i, gcmask[i]);
-                       ggloblsym(sbits, 2*widthptr, DUPOK|RODATA);
-               }
-               ot = dsymptr(s, ot, sbits, 0);
-               ot = duintptr(s, ot, 0);
-       }
-       p = smprint("%-uT", t);
-       //print("dcommontype: %s\n", p);
-       ot = dgostringptr(s, ot, p);    // string
-       free(p);
-
-       // skip pointer to extraType,
-       // which follows the rest of this type structure.
-       // caller will fill in if needed.
-       // otherwise linker will assume 0.
-       ot += widthptr;
-
-       ot = dsymptr(s, ot, sptr, 0);  // ptrto type
-       ot = dsymptr(s, ot, zero, 0);  // ptr to zero value
-       return ot;
-}
-
-Sym*
-typesym(Type *t)
-{
-       char *p;
-       Sym *s;
-
-       p = smprint("%-T", t);
-       s = pkglookup(p, typepkg);
-       //print("typesym: %s -> %+S\n", p, s);
-       free(p);
-       return s;
-}
-
-Sym*
-tracksym(Type *t)
-{
-       char *p;
-       Sym *s;
-
-       p = smprint("%-T.%s", t->outer, t->sym->name);
-       s = pkglookup(p, trackpkg);
-       free(p);
-       return s;
-}
-
-Sym*
-typelinksym(Type *t)
-{
-       char *p;
-       Sym *s;
-
-       // %-uT is what the generated Type's string field says.
-       // It uses (ambiguous) package names instead of import paths.
-       // %-T is the complete, unambiguous type name.
-       // We want the types to end up sorted by string field,
-       // so use that first in the name, and then add :%-T to
-       // disambiguate. The names are a little long but they are
-       // discarded by the linker and do not end up in the symbol
-       // table of the final binary.
-       p = smprint("%-uT/%-T", t, t);
-       s = pkglookup(p, typelinkpkg);
-       //print("typelinksym: %s -> %+S\n", p, s);
-       free(p);
-       return s;
-}
-
-Sym*
-typesymprefix(char *prefix, Type *t)
-{
-       char *p;
-       Sym *s;
-
-       p = smprint("%s.%-T", prefix, t);
-       s = pkglookup(p, typepkg);
-       //print("algsym: %s -> %+S\n", p, s);
-       free(p);
-       return s;
-}
-
-Sym*
-typenamesym(Type *t)
-{
-       Sym *s;
-       Node *n;
-
-       if(t == T || (isptr[t->etype] && t->type == T) || isideal(t))
-               fatal("typename %T", t);
-       s = typesym(t);
-       if(s->def == N) {
-               n = nod(ONAME, N, N);
-               n->sym = s;
-               n->type = types[TUINT8];
-               n->addable = 1;
-               n->ullman = 1;
-               n->class = PEXTERN;
-               n->xoffset = 0;
-               n->typecheck = 1;
-               s->def = n;
-
-               signatlist = list(signatlist, typenod(t));
-       }
-       return s->def->sym;
-}
-
-Node*
-typename(Type *t)
-{
-       Sym *s;
-       Node *n;
-
-       s = typenamesym(t);
-       n = nod(OADDR, s->def, N);
-       n->type = ptrto(s->def->type);
-       n->addable = 1;
-       n->ullman = 2;
-       n->typecheck = 1;
-       return n;
-}
-
-static Sym*
-weaktypesym(Type *t)
-{
-       char *p;
-       Sym *s;
-
-       p = smprint("%-T", t);
-       s = pkglookup(p, weaktypepkg);
-       //print("weaktypesym: %s -> %+S\n", p, s);
-       free(p);
-       return s;
-}
-
-/*
- * Returns 1 if t has a reflexive equality operator.
- * That is, if x==x for all x of type t.
- */
-static int
-isreflexive(Type *t)
-{
-       Type *t1;
-       switch(t->etype) {
-               case TBOOL:
-               case TINT:
-               case TUINT:
-               case TINT8:
-               case TUINT8:
-               case TINT16:
-               case TUINT16:
-               case TINT32:
-               case TUINT32:
-               case TINT64:
-               case TUINT64:
-               case TUINTPTR:
-               case TPTR32:
-               case TPTR64:
-               case TUNSAFEPTR:
-               case TSTRING:
-               case TCHAN:
-                       return 1;
-               case TFLOAT32:
-               case TFLOAT64:
-               case TCOMPLEX64:
-               case TCOMPLEX128:
-               case TINTER:
-                       return 0;
-               case TARRAY:
-                       if(isslice(t))
-                               fatal("slice can't be a map key: %T", t);
-                       return isreflexive(t->type);
-               case TSTRUCT:
-                       for(t1=t->type; t1!=T; t1=t1->down) {
-                               if(!isreflexive(t1->type))
-                                       return 0;
-                       }
-                       return 1;
-               default:
-                       fatal("bad type for map key: %T", t);
-                       return 0;
-       }
-}
-
-static Sym*
-dtypesym(Type *t)
-{
-       int ot, xt, n, isddd, dupok;
-       Sym *s, *s1, *s2, *s3, *s4, *slink;
-       Sig *a, *m;
-       Type *t1, *tbase, *t2;
-
-       // Replace byte, rune aliases with real type.
-       // They've been separate internally to make error messages
-       // better, but we have to merge them in the reflect tables.
-       if(t == bytetype || t == runetype)
-               t = types[t->etype];
-
-       if(isideal(t))
-               fatal("dtypesym %T", t);
-
-       s = typesym(t);
-       if(s->flags & SymSiggen)
-               return s;
-       s->flags |= SymSiggen;
-
-       // special case (look for runtime below):
-       // when compiling package runtime,
-       // emit the type structures for int, float, etc.
-       tbase = t;
-       if(isptr[t->etype] && t->sym == S && t->type->sym != S)
-               tbase = t->type;
-       dupok = 0;
-       if(tbase->sym == S)
-               dupok = DUPOK;
-
-       if(compiling_runtime &&
-                       (tbase == types[tbase->etype] ||
-                       tbase == bytetype ||
-                       tbase == runetype ||
-                       tbase == errortype)) { // int, float, etc
-               goto ok;
-       }
-
-       // named types from other files are defined only by those files
-       if(tbase->sym && !tbase->local)
-               return s;
-       if(isforw[tbase->etype])
-               return s;
-
-ok:
-       ot = 0;
-       xt = 0;
-       switch(t->etype) {
-       default:
-               ot = dcommontype(s, ot, t);
-               xt = ot - 3*widthptr;
-               break;
-
-       case TARRAY:
-               if(t->bound >= 0) {
-                       // ../../runtime/type.go:/ArrayType
-                       s1 = dtypesym(t->type);
-                       t2 = typ(TARRAY);
-                       t2->type = t->type;
-                       t2->bound = -1;  // slice
-                       s2 = dtypesym(t2);
-                       ot = dcommontype(s, ot, t);
-                       xt = ot - 3*widthptr;
-                       ot = dsymptr(s, ot, s1, 0);
-                       ot = dsymptr(s, ot, s2, 0);
-                       ot = duintptr(s, ot, t->bound);
-               } else {
-                       // ../../runtime/type.go:/SliceType
-                       s1 = dtypesym(t->type);
-                       ot = dcommontype(s, ot, t);
-                       xt = ot - 3*widthptr;
-                       ot = dsymptr(s, ot, s1, 0);
-               }
-               break;
-
-       case TCHAN:
-               // ../../runtime/type.go:/ChanType
-               s1 = dtypesym(t->type);
-               ot = dcommontype(s, ot, t);
-               xt = ot - 3*widthptr;
-               ot = dsymptr(s, ot, s1, 0);
-               ot = duintptr(s, ot, t->chan);
-               break;
-
-       case TFUNC:
-               for(t1=getthisx(t)->type; t1; t1=t1->down)
-                       dtypesym(t1->type);
-               isddd = 0;
-               for(t1=getinargx(t)->type; t1; t1=t1->down) {
-                       isddd = t1->isddd;
-                       dtypesym(t1->type);
-               }
-               for(t1=getoutargx(t)->type; t1; t1=t1->down)
-                       dtypesym(t1->type);
-
-               ot = dcommontype(s, ot, t);
-               xt = ot - 3*widthptr;
-               ot = duint8(s, ot, isddd);
-
-               // two slice headers: in and out.
-               ot = rnd(ot, widthptr);
-               ot = dsymptr(s, ot, s, ot+2*(widthptr+2*widthint));
-               n = t->thistuple + t->intuple;
-               ot = duintxx(s, ot, n, widthint);
-               ot = duintxx(s, ot, n, widthint);
-               ot = dsymptr(s, ot, s, ot+1*(widthptr+2*widthint)+n*widthptr);
-               ot = duintxx(s, ot, t->outtuple, widthint);
-               ot = duintxx(s, ot, t->outtuple, widthint);
-
-               // slice data
-               for(t1=getthisx(t)->type; t1; t1=t1->down, n++)
-                       ot = dsymptr(s, ot, dtypesym(t1->type), 0);
-               for(t1=getinargx(t)->type; t1; t1=t1->down, n++)
-                       ot = dsymptr(s, ot, dtypesym(t1->type), 0);
-               for(t1=getoutargx(t)->type; t1; t1=t1->down, n++)
-                       ot = dsymptr(s, ot, dtypesym(t1->type), 0);
-               break;
-
-       case TINTER:
-               m = imethods(t);
-               n = 0;
-               for(a=m; a; a=a->link) {
-                       dtypesym(a->type);
-                       n++;
-               }
-
-               // ../../runtime/type.go:/InterfaceType
-               ot = dcommontype(s, ot, t);
-               xt = ot - 3*widthptr;
-               ot = dsymptr(s, ot, s, ot+widthptr+2*widthint);
-               ot = duintxx(s, ot, n, widthint);
-               ot = duintxx(s, ot, n, widthint);
-               for(a=m; a; a=a->link) {
-                       // ../../runtime/type.go:/imethod
-                       ot = dgostringptr(s, ot, a->name);
-                       ot = dgopkgpath(s, ot, a->pkg);
-                       ot = dsymptr(s, ot, dtypesym(a->type), 0);
-               }
-               break;
-
-       case TMAP:
-               // ../../runtime/type.go:/MapType
-               s1 = dtypesym(t->down);
-               s2 = dtypesym(t->type);
-               s3 = dtypesym(mapbucket(t));
-               s4 = dtypesym(hmap(t));
-               ot = dcommontype(s, ot, t);
-               xt = ot - 3*widthptr;
-               ot = dsymptr(s, ot, s1, 0);
-               ot = dsymptr(s, ot, s2, 0);
-               ot = dsymptr(s, ot, s3, 0);
-               ot = dsymptr(s, ot, s4, 0);
-               if(t->down->width > MAXKEYSIZE) {
-                       ot = duint8(s, ot, widthptr);
-                       ot = duint8(s, ot, 1); // indirect
-               } else {
-                       ot = duint8(s, ot, t->down->width);
-                       ot = duint8(s, ot, 0); // not indirect
-               }
-               if(t->type->width > MAXVALSIZE) {
-                       ot = duint8(s, ot, widthptr);
-                       ot = duint8(s, ot, 1); // indirect
-               } else {
-                       ot = duint8(s, ot, t->type->width);
-                       ot = duint8(s, ot, 0); // not indirect
-               }
-               ot = duint16(s, ot, mapbucket(t)->width);
-                ot = duint8(s, ot, isreflexive(t->down));
-               break;
-
-       case TPTR32:
-       case TPTR64:
-               if(t->type->etype == TANY) {
-                       // ../../runtime/type.go:/UnsafePointerType
-                       ot = dcommontype(s, ot, t);
-                       break;
-               }
-               // ../../runtime/type.go:/PtrType
-               s1 = dtypesym(t->type);
-               ot = dcommontype(s, ot, t);
-               xt = ot - 3*widthptr;
-               ot = dsymptr(s, ot, s1, 0);
-               break;
-
-       case TSTRUCT:
-               // ../../runtime/type.go:/StructType
-               // for security, only the exported fields.
-               n = 0;
-               for(t1=t->type; t1!=T; t1=t1->down) {
-                       dtypesym(t1->type);
-                       n++;
-               }
-               ot = dcommontype(s, ot, t);
-               xt = ot - 3*widthptr;
-               ot = dsymptr(s, ot, s, ot+widthptr+2*widthint);
-               ot = duintxx(s, ot, n, widthint);
-               ot = duintxx(s, ot, n, widthint);
-               for(t1=t->type; t1!=T; t1=t1->down) {
-                       // ../../runtime/type.go:/structField
-                       if(t1->sym && !t1->embedded) {
-                               ot = dgostringptr(s, ot, t1->sym->name);
-                               if(exportname(t1->sym->name))
-                                       ot = dgostringptr(s, ot, nil);
-                               else
-                                       ot = dgopkgpath(s, ot, t1->sym->pkg);
-                       } else {
-                               ot = dgostringptr(s, ot, nil);
-                               if(t1->type->sym != S && t1->type->sym->pkg == builtinpkg)
-                                       ot = dgopkgpath(s, ot, localpkg);
-                               else
-                                       ot = dgostringptr(s, ot, nil);
-                       }
-                       ot = dsymptr(s, ot, dtypesym(t1->type), 0);
-                       ot = dgostrlitptr(s, ot, t1->note);
-                       ot = duintptr(s, ot, t1->width);        // field offset
-               }
-               break;
-       }
-       ot = dextratype(s, ot, t, xt);
-       ggloblsym(s, ot, dupok|RODATA);
-
-       // generate typelink.foo pointing at s = type.foo.
-       // The linker will leave a table of all the typelinks for
-       // types in the binary, so reflect can find them.
-       // We only need the link for unnamed composites that
-       // we want be able to find.
-       if(t->sym == S) {
-               switch(t->etype) {
-               case TARRAY:
-               case TCHAN:
-               case TMAP:
-                       slink = typelinksym(t);
-                       dsymptr(slink, 0, s, 0);
-                       ggloblsym(slink, widthptr, dupok|RODATA);
-               }
-       }
-
-       return s;
-}
-
-void
-dumptypestructs(void)
-{
-       int i;
-       NodeList *l;
-       Node *n;
-       Type *t;
-       Pkg *p;
-
-       // copy types from externdcl list to signatlist
-       for(l=externdcl; l; l=l->next) {
-               n = l->n;
-               if(n->op != OTYPE)
-                       continue;
-               signatlist = list(signatlist, n);
-       }
-
-       // process signatlist
-       for(l=signatlist; l; l=l->next) {
-               n = l->n;
-               if(n->op != OTYPE)
-                       continue;
-               t = n->type;
-               dtypesym(t);
-               if(t->sym)
-                       dtypesym(ptrto(t));
-       }
-
-       // generate import strings for imported packages
-       for(i=0; i<nelem(phash); i++)
-               for(p=phash[i]; p; p=p->link)
-                       if(p->direct)
-                               dimportpath(p);
-
-       // do basic types if compiling package runtime.
-       // they have to be in at least one package,
-       // and runtime is always loaded implicitly,
-       // so this is as good as any.
-       // another possible choice would be package main,
-       // but using runtime means fewer copies in .6 files.
-       if(compiling_runtime) {
-               for(i=1; i<=TBOOL; i++)
-                       dtypesym(ptrto(types[i]));
-               dtypesym(ptrto(types[TSTRING]));
-               dtypesym(ptrto(types[TUNSAFEPTR]));
-
-               // emit type structs for error and func(error) string.
-               // The latter is the type of an auto-generated wrapper.
-               dtypesym(ptrto(errortype));
-               dtypesym(functype(nil,
-                       list1(nod(ODCLFIELD, N, typenod(errortype))),
-                       list1(nod(ODCLFIELD, N, typenod(types[TSTRING])))));
-
-               // add paths for runtime and main, which 6l imports implicitly.
-               dimportpath(runtimepkg);
-               if(flag_race)
-                       dimportpath(racepkg);
-               dimportpath(mkpkg(newstrlit("main")));
-       }
-}
-
-static Sym*
-dalgsym(Type *t)
-{
-       int ot;
-       Sym *s, *hash, *hashfunc, *eq, *eqfunc;
-       char *p;
-
-       // dalgsym is only called for a type that needs an algorithm table,
-       // which implies that the type is comparable (or else it would use ANOEQ).
-
-       if(algtype(t) == AMEM) {
-               // we use one algorithm table for all AMEM types of a given size
-               p = smprint(".alg%lld", t->width);
-               s = pkglookup(p, typepkg);
-               free(p);
-               if(s->flags & SymAlgGen)
-                       return s;
-               s->flags |= SymAlgGen;
-
-               // make hash closure
-               p = smprint(".hashfunc%lld", t->width);
-               hashfunc = pkglookup(p, typepkg);
-               free(p);
-               ot = 0;
-               ot = dsymptr(hashfunc, ot, pkglookup("memhash_varlen", runtimepkg), 0);
-               ot = duintxx(hashfunc, ot, t->width, widthptr); // size encoded in closure
-               ggloblsym(hashfunc, ot, DUPOK|RODATA);
-
-               // make equality closure
-               p = smprint(".eqfunc%lld", t->width);
-               eqfunc = pkglookup(p, typepkg);
-               free(p);
-               ot = 0;
-               ot = dsymptr(eqfunc, ot, pkglookup("memequal_varlen", runtimepkg), 0);
-               ot = duintxx(eqfunc, ot, t->width, widthptr);
-               ggloblsym(eqfunc, ot, DUPOK|RODATA);
-       } else {
-               // generate an alg table specific to this type
-               s = typesymprefix(".alg", t);
-               hash = typesymprefix(".hash", t);
-               eq = typesymprefix(".eq", t);
-               hashfunc = typesymprefix(".hashfunc", t);
-               eqfunc = typesymprefix(".eqfunc", t);
-
-               genhash(hash, t);
-               geneq(eq, t);
-
-               // make Go funcs (closures) for calling hash and equal from Go
-               dsymptr(hashfunc, 0, hash, 0);
-               ggloblsym(hashfunc, widthptr, DUPOK|RODATA);
-               dsymptr(eqfunc, 0, eq, 0);
-               ggloblsym(eqfunc, widthptr, DUPOK|RODATA);
-       }
-       // ../../runtime/alg.go:/typeAlg
-       ot = 0;
-       ot = dsymptr(s, ot, hashfunc, 0);
-       ot = dsymptr(s, ot, eqfunc, 0);
-       ggloblsym(s, ot, DUPOK|RODATA);
-       return s;
-}
-
-static int
-usegcprog(Type *t)
-{
-       vlong size, nptr;
-
-       if(!haspointers(t))
-               return 0;
-       if(t->width == BADWIDTH)
-               dowidth(t);
-       // Calculate size of the unrolled GC mask.
-       nptr = (t->width+widthptr-1)/widthptr;
-       size = nptr;
-       if(size%2)
-               size *= 2;      // repeated
-       size = size*gcBits/8;   // 4 bits per word
-       // Decide whether to use unrolled GC mask or GC program.
-       // We could use a more elaborate condition, but this seems to work well in practice.
-       // For small objects GC program can't give significant reduction.
-       // While large objects usually contain arrays; and even if it don't
-       // the program uses 2-bits per word while mask uses 4-bits per word,
-       // so the program is still smaller.
-       return size > 2*widthptr;
-}
-
-// Generates sparse GC bitmask (4 bits per word).
-static void
-gengcmask(Type *t, uint8 *gcmask)
-{
-       Bvec *vec;
-       vlong xoffset, nptr, i, j;
-       int  half;
-       uint8 bits, *pos;
-
-       memset(gcmask, 0, 16);
-       if(!haspointers(t))
-               return;
-
-       // Generate compact mask as stacks use.
-       xoffset = 0;
-       vec = bvalloc(2*widthptr*8);
-       twobitwalktype1(t, &xoffset, vec);
-
-       // Unfold the mask for the GC bitmap format:
-       // 4 bits per word, 2 high bits encode pointer info.
-       pos = gcmask;
-       nptr = (t->width+widthptr-1)/widthptr;
-       half = 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++) {
-               for(i=0; i<nptr; i++) {
-                       bits = bvget(vec, i*BitsPerPointer) | bvget(vec, i*BitsPerPointer+1)<<1;
-                       // Some fake types (e.g. Hmap) has missing fileds.
-                       // twobitwalktype1 generates BitsDead for that holes,
-                       // replace BitsDead with BitsScalar.
-                       if(bits == BitsDead)
-                               bits = BitsScalar;
-                       bits <<= 2;
-                       if(half)
-                               bits <<= 4;
-                       *pos |= bits;
-                       half = !half;
-                       if(!half)
-                               pos++;
-               }
-       }
-}
-
-// Helper object for generation of GC programs.
-typedef struct ProgGen ProgGen;
-struct ProgGen
-{
-       Sym*    s;
-       int32   datasize;
-       uint8   data[256/PointersPerByte];
-       vlong   ot;
-};
-
-static void
-proggeninit(ProgGen *g, Sym *s)
-{
-       g->s = s;
-       g->datasize = 0;
-       g->ot = 0;
-       memset(g->data, 0, sizeof(g->data));
-}
-
-static void
-proggenemit(ProgGen *g, uint8 v)
-{
-       g->ot = duint8(g->s, g->ot, v);
-}
-
-// Emits insData block from g->data.
-static void
-proggendataflush(ProgGen *g)
-{
-       int32 i, s;
-
-       if(g->datasize == 0)
-               return;
-       proggenemit(g, insData);
-       proggenemit(g, g->datasize);
-       s = (g->datasize + PointersPerByte - 1)/PointersPerByte;
-       for(i = 0; i < s; i++)
-               proggenemit(g, g->data[i]);
-       g->datasize = 0;
-       memset(g->data, 0, sizeof(g->data));
-}
-
-static void
-proggendata(ProgGen *g, uint8 d)
-{
-       g->data[g->datasize/PointersPerByte] |= d << ((g->datasize%PointersPerByte)*BitsPerPointer);
-       g->datasize++;
-       if(g->datasize == 255)
-               proggendataflush(g);
-}
-
-// Skip v bytes due to alignment, etc.
-static void
-proggenskip(ProgGen *g, vlong off, vlong v)
-{
-       vlong i;
-
-       for(i = off; i < off+v; i++) {
-               if((i%widthptr) == 0)
-                       proggendata(g, BitsScalar);
-       }
-}
-
-// Emit insArray instruction.
-static void
-proggenarray(ProgGen *g, vlong len)
-{
-       int32 i;
-
-       proggendataflush(g);
-       proggenemit(g, insArray);
-       for(i = 0; i < widthptr; i++, len >>= 8)
-               proggenemit(g, len);
-}
-
-static void
-proggenarrayend(ProgGen *g)
-{
-       proggendataflush(g);
-       proggenemit(g, insArrayEnd);
-}
-
-static vlong
-proggenfini(ProgGen *g)
-{
-       proggendataflush(g);
-       proggenemit(g, insEnd);
-       return g->ot;
-}
-
-static void gengcprog1(ProgGen *g, Type *t, vlong *xoffset);
-
-// Generates GC program for large types.
-static void
-gengcprog(Type *t, Sym **pgc0, Sym **pgc1)
-{
-       Sym *gc0, *gc1;
-       vlong nptr, size, ot, xoffset;
-       ProgGen g;
-
-       nptr = (t->width+widthptr-1)/widthptr;
-       size = nptr;
-       if(size%2)
-               size *= 2;      // repeated twice
-       size = size*PointersPerByte/8;  // 4 bits per word
-       size++; // unroll flag in the beginning, used by runtime (see runtime.markallocated)
-       // emity space in BSS for unrolled program
-       *pgc0 = S;
-       // Don't generate it if it's too large, runtime will unroll directly into GC bitmap.
-       if(size <= MaxGCMask) {
-               gc0 = typesymprefix(".gc", t);
-               ggloblsym(gc0, size, DUPOK|NOPTR);
-               *pgc0 = gc0;
-       }
-
-       // program in RODATA
-       gc1 = typesymprefix(".gcprog", t);
-       proggeninit(&g, gc1);
-       xoffset = 0;
-       gengcprog1(&g, t, &xoffset);
-       ot = proggenfini(&g);
-       ggloblsym(gc1, ot, DUPOK|RODATA);
-       *pgc1 = gc1;
-}
-
-// Recursively walks type t and writes GC program into g.
-static void
-gengcprog1(ProgGen *g, Type *t, vlong *xoffset)
-{
-       vlong fieldoffset, i, o, n;
-       Type *t1;
-
-       switch(t->etype) {
-       case TINT8:
-       case TUINT8:
-       case TINT16:
-       case TUINT16:
-       case TINT32:
-       case TUINT32:
-       case TINT64:
-       case TUINT64:
-       case TINT:
-       case TUINT:
-       case TUINTPTR:
-       case TBOOL:
-       case TFLOAT32:
-       case TFLOAT64:
-       case TCOMPLEX64:
-       case TCOMPLEX128:
-               proggenskip(g, *xoffset, t->width);
-               *xoffset += t->width;
-               break;
-       case TPTR32:
-       case TPTR64:
-       case TUNSAFEPTR:
-       case TFUNC:
-       case TCHAN:
-       case TMAP:
-               proggendata(g, BitsPointer);
-               *xoffset += t->width;
-               break;
-       case TSTRING:
-               proggendata(g, BitsPointer);
-               proggendata(g, BitsScalar);
-               *xoffset += t->width;
-               break;
-       case TINTER:
-               // Assuming IfacePointerOnly=1.
-               proggendata(g, BitsPointer);
-               proggendata(g, BitsPointer);
-               *xoffset += t->width;
-               break;
-       case TARRAY:
-               if(isslice(t)) {
-                       proggendata(g, BitsPointer);
-                       proggendata(g, BitsScalar);
-                       proggendata(g, BitsScalar);
-               } else {
-                       t1 = t->type;
-                       if(t1->width == 0) {
-                               // ignore
-                       } if(t->bound <= 1 || t->bound*t1->width < 32*widthptr) {
-                               for(i = 0; i < t->bound; i++)
-                                       gengcprog1(g, t1, xoffset);
-                       } else if(!haspointers(t1)) {
-                               n = t->width;
-                               n -= -*xoffset&(widthptr-1); // skip to next ptr boundary
-                               proggenarray(g, (n+widthptr-1)/widthptr);
-                               proggendata(g, BitsScalar);
-                               proggenarrayend(g);
-                               *xoffset -= (n+widthptr-1)/widthptr*widthptr - t->width;
-                       } else {
-                               proggenarray(g, t->bound);
-                               gengcprog1(g, t1, xoffset);
-                               *xoffset += (t->bound-1)*t1->width;
-                               proggenarrayend(g);
-                       }
-               }
-               break;
-       case TSTRUCT:
-               o = 0;
-               for(t1 = t->type; t1 != T; t1 = t1->down) {
-                       fieldoffset = t1->width;
-                       proggenskip(g, *xoffset, fieldoffset - o);
-                       *xoffset += fieldoffset - o;
-                       gengcprog1(g, t1->type, xoffset);
-                       o = fieldoffset + t1->type->width;
-               }
-               proggenskip(g, *xoffset, t->width - o);
-               *xoffset += t->width - o;
-               break;
-       default:
-               fatal("gengcprog1: unexpected type, %T", t);
-       }
-}
diff --git a/src/cmd/gc/reg.c b/src/cmd/gc/reg.c
deleted file mode 100644 (file)
index 67409c2..0000000
+++ /dev/null
@@ -1,1233 +0,0 @@
-// Derived from Inferno utils/6c/reg.c
-// http://code.google.com/p/inferno-os/source/browse/utils/6c/reg.c
-//
-//     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 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 <u.h>
-#include <libc.h>
-#include "go.h"
-#include "popt.h"
-
-static Flow*   firstf;
-static int     first   = 1;
-
-static void    addmove(Flow*, int, int, int);
-static Bits    mkvar(Flow*, Adr*);
-static void    prop(Flow*, Bits, Bits);
-static void    synch(Flow*, Bits);
-static uint64  allreg(uint64, Rgn*);
-static void    paint1(Flow*, int);
-static uint64  paint2(Flow*, int, int);
-static void    paint3(Flow*, int, uint64, int);
-static void    addreg(Adr*, int);
-
-static int
-rcmp(const void *a1, const void *a2)
-{
-       Rgn *p1, *p2;
-
-       p1 = (Rgn*)a1;
-       p2 = (Rgn*)a2;
-       if(p1->cost != p2->cost)
-               return p2->cost - p1->cost;
-       if(p1->varno != p2->varno)
-               return p2->varno - p1->varno;
-       if(p1->enter != p2->enter)
-               return p2->enter->id - p1->enter->id;
-       return 0;
-}
-
-static void
-setaddrs(Bits bit)
-{
-       int i, n;
-       Var *v;
-       Node *node;
-
-       while(bany(&bit)) {
-               // convert each bit to a variable
-               i = bnum(bit);
-               node = var[i].node;
-               n = var[i].name;
-               biclr(&bit, i);
-
-               // disable all pieces of that variable
-               for(i=0; i<nvar; i++) {
-                       v = var+i;
-                       if(v->node == node && v->name == n)
-                               v->addr = 2;
-               }
-       }
-}
-
-static Node* regnodes[64];
-
-static void walkvardef(Node *n, Flow *r, int active);
-
-void
-regopt(Prog *firstp)
-{
-       Flow *f, *f1;
-       Reg *r;
-       Prog *p;
-       Graph *g;
-       ProgInfo info;
-       int i, z, active;
-       uint64 vreg, usedreg;
-       uint64 mask;
-       int nreg;
-       char **regnames;
-       Bits bit;
-       Rgn *rgp;
-
-       if(first) {
-               fmtinstall('Q', Qconv);
-               first = 0;
-       }
-
-       mergetemp(firstp);
-
-       /*
-        * control flow is more complicated in generated go code
-        * than in generated c code.  define pseudo-variables for
-        * registers, so we have complete register usage information.
-        */
-       regnames = thearch.regnames(&nreg);
-       nvar = nreg;
-       memset(var, 0, nreg*sizeof var[0]);
-       for(i=0; i<nreg; i++) {
-               if(regnodes[i] == N)
-                       regnodes[i] = newname(lookup(regnames[i]));
-               var[i].node = regnodes[i];
-       }
-
-       regbits = thearch.excludedregs();
-       externs = zbits;
-       params = zbits;
-       consts = zbits;
-       addrs = zbits;
-       ivar = zbits;
-       ovar = zbits;
-
-       /*
-        * pass 1
-        * build aux data structure
-        * allocate pcs
-        * find use and set of variables
-        */
-       g = flowstart(firstp, sizeof(Reg));
-       if(g == nil) {
-               for(i=0; i<nvar; i++)
-                       var[i].node->opt = nil;
-               return;
-       }
-
-       firstf = g->start;
-
-       for(f = firstf; f != nil; f = f->link) {
-               p = f->prog;
-               if(p->as == AVARDEF || p->as == AVARKILL)
-                       continue;
-               thearch.proginfo(&info, p);
-
-               // Avoid making variables for direct-called functions.
-               if(p->as == ACALL && p->to.type == TYPE_MEM && p->to.name == NAME_EXTERN)
-                       continue;
-
-               // from vs to doesn't matter for registers.
-               r = (Reg*)f->data;
-               r->use1.b[0] |= info.reguse | info.regindex;
-               r->set.b[0] |= info.regset;
-
-               bit = mkvar(f, &p->from);
-               if(bany(&bit)) {
-                       if(info.flags & LeftAddr)
-                               setaddrs(bit);
-                       if(info.flags & LeftRead)
-                               for(z=0; z<BITS; z++)
-                                       r->use1.b[z] |= bit.b[z];
-                       if(info.flags & LeftWrite)
-                               for(z=0; z<BITS; z++)
-                                       r->set.b[z] |= bit.b[z];
-               }
-
-               // Compute used register for reg
-               if(info.flags & RegRead)
-                       r->use1.b[0] |= thearch.RtoB(p->reg);
-
-               // Currently we never generate three register forms.
-               // If we do, this will need to change.
-               if(p->from3.type != TYPE_NONE)
-                       fatal("regopt not implemented for from3");
-
-               bit = mkvar(f, &p->to);
-               if(bany(&bit)) {        
-                       if(info.flags & RightAddr)
-                               setaddrs(bit);
-                       if(info.flags & RightRead)
-                               for(z=0; z<BITS; z++)
-                                       r->use2.b[z] |= bit.b[z];
-                       if(info.flags & RightWrite)
-                               for(z=0; z<BITS; z++)
-                                       r->set.b[z] |= bit.b[z];
-               }
-       }
-
-       for(i=0; i<nvar; i++) {
-               Var *v;
-               v = var+i;
-               if(v->addr) {
-                       bit = blsh(i);
-                       for(z=0; z<BITS; z++)
-                               addrs.b[z] |= bit.b[z];
-               }
-
-               if(debug['R'] && debug['v'])
-                       print("bit=%2d addr=%d et=%E w=%-2d s=%N + %lld\n",
-                               i, v->addr, v->etype, v->width, v->node, v->offset);
-       }
-
-       if(debug['R'] && debug['v'])
-               dumpit("pass1", firstf, 1);
-
-       /*
-        * pass 2
-        * find looping structure
-        */
-       flowrpo(g);
-
-       if(debug['R'] && debug['v'])
-               dumpit("pass2", firstf, 1);
-
-       /*
-        * pass 2.5
-        * iterate propagating fat vardef covering forward
-        * r->act records vars with a VARDEF since the last CALL.
-        * (r->act will be reused in pass 5 for something else,
-        * but we'll be done with it by then.)
-        */
-       active = 0;
-       for(f = firstf; f != nil; f = f->link) {
-               f->active = 0;
-               r = (Reg*)f->data;
-               r->act = zbits;
-       }
-       for(f = firstf; f != nil; f = f->link) {
-               p = f->prog;
-               if(p->as == AVARDEF && isfat(((Node*)(p->to.node))->type) && ((Node*)(p->to.node))->opt != nil) {
-                       active++;
-                       walkvardef(p->to.node, f, active);
-               }
-       }
-
-       /*
-        * pass 3
-        * iterate propagating usage
-        *      back until flow graph is complete
-        */
-loop1:
-       change = 0;
-       for(f = firstf; f != nil; f = f->link)
-               f->active = 0;
-       for(f = firstf; f != nil; f = f->link)
-               if(f->prog->as == ARET)
-                       prop(f, zbits, zbits);
-loop11:
-       /* pick up unreachable code */
-       i = 0;
-       for(f = firstf; f != nil; f = f1) {
-               f1 = f->link;
-               if(f1 && f1->active && !f->active) {
-                       prop(f, zbits, zbits);
-                       i = 1;
-               }
-       }
-       if(i)
-               goto loop11;
-       if(change)
-               goto loop1;
-
-       if(debug['R'] && debug['v'])
-               dumpit("pass3", firstf, 1);
-
-       /*
-        * pass 4
-        * iterate propagating register/variable synchrony
-        *      forward until graph is complete
-        */
-loop2:
-       change = 0;
-       for(f = firstf; f != nil; f = f->link)
-               f->active = 0;
-       synch(firstf, zbits);
-       if(change)
-               goto loop2;
-
-       if(debug['R'] && debug['v'])
-               dumpit("pass4", firstf, 1);
-
-       /*
-        * pass 4.5
-        * move register pseudo-variables into regu.
-        */
-       if(nreg == 64)
-               mask = ~0ULL; // can't rely on C to shift by 64
-       else
-               mask = (1ULL<<nreg) - 1;
-       for(f = firstf; f != nil; f = f->link) {
-               r = (Reg*)f->data;
-               r->regu = (r->refbehind.b[0] | r->set.b[0]) & mask;
-               r->set.b[0] &= ~mask;
-               r->use1.b[0] &= ~mask;
-               r->use2.b[0] &= ~mask;
-               r->refbehind.b[0] &= ~mask;
-               r->refahead.b[0] &= ~mask;
-               r->calbehind.b[0] &= ~mask;
-               r->calahead.b[0] &= ~mask;
-               r->regdiff.b[0] &= ~mask;
-               r->act.b[0] &= ~mask;
-       }
-
-       if(debug['R'] && debug['v'])
-               dumpit("pass4.5", firstf, 1);
-
-       /*
-        * pass 5
-        * isolate regions
-        * calculate costs (paint1)
-        */
-       f = firstf;
-       if(f) {
-               r = (Reg*)f->data;
-               for(z=0; z<BITS; z++)
-                       bit.b[z] = (r->refahead.b[z] | r->calahead.b[z]) &
-                         ~(externs.b[z] | params.b[z] | addrs.b[z] | consts.b[z]);
-               if(bany(&bit) && !f->refset) {
-                       // should never happen - all variables are preset
-                       if(debug['w'])
-                               print("%L: used and not set: %Q\n", f->prog->lineno, bit);
-                       f->refset = 1;
-               }
-       }
-       for(f = firstf; f != nil; f = f->link)
-               ((Reg*)f->data)->act = zbits;
-       nregion = 0;
-       for(f = firstf; f != nil; f = f->link) {
-               r = (Reg*)f->data;
-               for(z=0; z<BITS; z++)
-                       bit.b[z] = r->set.b[z] &
-                         ~(r->refahead.b[z] | r->calahead.b[z] | addrs.b[z]);
-               if(bany(&bit) && !f->refset) {
-                       if(debug['w'])
-                               print("%L: set and not used: %Q\n", f->prog->lineno, bit);
-                       f->refset = 1;
-                       thearch.excise(f);
-               }
-               for(z=0; z<BITS; z++)
-                       bit.b[z] = LOAD(r) & ~(r->act.b[z] | addrs.b[z]);
-               while(bany(&bit)) {
-                       i = bnum(bit);
-                       change = 0;
-                       paint1(f, i);
-                       biclr(&bit, i);
-                       if(change <= 0)
-                               continue;
-                       if(nregion >= NRGN) {
-                               if(debug['R'] && debug['v'])
-                                       print("too many regions\n");
-                               goto brk;
-                       }
-                       rgp = &region[nregion];
-                       rgp->enter = f;
-                       rgp->varno = i;
-                       rgp->cost = change;
-                       nregion++;
-               }
-       }
-brk:
-       qsort(region, nregion, sizeof(region[0]), rcmp);
-
-       if(debug['R'] && debug['v'])
-               dumpit("pass5", firstf, 1);
-
-       /*
-        * pass 6
-        * determine used registers (paint2)
-        * replace code (paint3)
-        */
-       if(debug['R'] && debug['v'])
-               print("\nregisterizing\n");
-       for(i=0; i<nregion; i++) {
-               rgp = &region[i];
-               if(debug['R'] && debug['v'])
-                       print("region %d: cost %d varno %d enter %lld\n", i, rgp->cost, rgp->varno, rgp->enter->prog->pc);
-               bit = blsh(rgp->varno);
-               usedreg = paint2(rgp->enter, rgp->varno, 0);
-               vreg = allreg(usedreg, rgp);
-               if(rgp->regno != 0) {
-                       if(debug['R'] && debug['v']) {
-                               Var *v;
-
-                               v = var + rgp->varno;
-                               print("registerize %N+%lld (bit=%2d et=%E) in %R usedreg=%#llx vreg=%#llx\n",
-                                               v->node, v->offset, rgp->varno, v->etype, rgp->regno, usedreg, vreg);
-                       }
-                       paint3(rgp->enter, rgp->varno, vreg, rgp->regno);
-               }
-       }
-
-       /*
-        * free aux structures. peep allocates new ones.
-        */
-       for(i=0; i<nvar; i++)
-               var[i].node->opt = nil;
-       flowend(g);
-       firstf = nil;
-
-       if(debug['R'] && debug['v']) {
-               // Rebuild flow graph, since we inserted instructions
-               g = flowstart(firstp, 0);
-               firstf = g->start;
-               dumpit("pass6", firstf, 0);
-               flowend(g);
-               firstf = nil;
-       }
-
-       /*
-        * pass 7
-        * peep-hole on basic block
-        */
-       if(!debug['R'] || debug['P'])
-               thearch.peep(firstp);
-
-       /*
-        * eliminate nops
-        */
-       for(p=firstp; p!=P; p=p->link) {
-               while(p->link != P && p->link->as == ANOP)
-                       p->link = p->link->link;
-               if(p->to.type == TYPE_BRANCH)
-                       while(p->to.u.branch != P && p->to.u.branch->as == ANOP)
-                               p->to.u.branch = p->to.u.branch->link;
-       }
-
-       if(debug['R']) {
-               if(ostats.ncvtreg ||
-                  ostats.nspill ||
-                  ostats.nreload ||
-                  ostats.ndelmov ||
-                  ostats.nvar ||
-                  ostats.naddr ||
-                  0)
-                       print("\nstats\n");
-
-               if(ostats.ncvtreg)
-                       print(" %4d cvtreg\n", ostats.ncvtreg);
-               if(ostats.nspill)
-                       print(" %4d spill\n", ostats.nspill);
-               if(ostats.nreload)
-                       print(" %4d reload\n", ostats.nreload);
-               if(ostats.ndelmov)
-                       print(" %4d delmov\n", ostats.ndelmov);
-               if(ostats.nvar)
-                       print(" %4d var\n", ostats.nvar);
-               if(ostats.naddr)
-                       print(" %4d addr\n", ostats.naddr);
-
-               memset(&ostats, 0, sizeof(ostats));
-       }
-}
-
-static void
-walkvardef(Node *n, Flow *f, int active)
-{
-       Flow *f1, *f2;
-       int bn;
-       Var *v;
-       
-       for(f1=f; f1!=nil; f1=f1->s1) {
-               if(f1->active == active)
-                       break;
-               f1->active = active;
-               if(f1->prog->as == AVARKILL && f1->prog->to.node == n)
-                       break;
-               for(v=n->opt; v!=nil; v=v->nextinnode) {
-                       bn = v->id;
-                       biset(&((Reg*)f1->data)->act, bn);
-               }
-               if(f1->prog->as == ACALL)
-                       break;
-       }
-
-       for(f2=f; f2!=f1; f2=f2->s1)
-               if(f2->s2 != nil)
-                       walkvardef(n, f2->s2, active);
-}
-
-/*
- * add mov b,rn
- * just after r
- */
-static void
-addmove(Flow *r, int bn, int rn, int f)
-{
-       Prog *p, *p1;
-       Adr *a;
-       Var *v;
-
-       p1 = mal(sizeof(*p1));
-       clearp(p1);
-       p1->pc = 9999;
-
-       p = r->prog;
-       p1->link = p->link;
-       p->link = p1;
-       p1->lineno = p->lineno;
-
-       v = var + bn;
-
-       a = &p1->to;
-       a->offset = v->offset;
-       a->etype = v->etype;
-       a->type = TYPE_MEM;
-       a->name = v->name;
-       a->node = v->node;
-       a->sym = linksym(v->node->sym);
-       /* NOTE(rsc): 9g did
-       if(a->etype == TARRAY)
-               a->type = TYPE_ADDR;
-       else if(a->sym == nil)
-               a->type = TYPE_CONST;
-       */
-
-       p1->as = thearch.optoas(OAS, types[(uchar)v->etype]);
-       // TODO(rsc): Remove special case here.
-       if((thearch.thechar == '9' || thearch.thechar == '5') && v->etype == TBOOL)
-               p1->as = thearch.optoas(OAS, types[TUINT8]);
-       p1->from.type = TYPE_REG;
-       p1->from.reg = rn;
-       p1->from.name = NAME_NONE;
-       if(!f) {
-               p1->from = *a;
-               *a = zprog.from;
-               a->type = TYPE_REG;
-               a->reg = rn;
-       }
-       if(debug['R'] && debug['v'])
-               print("%P ===add=== %P\n", p, p1);
-       ostats.nspill++;
-}
-
-static int
-overlap(int64 o1, int w1, int64 o2, int w2)
-{
-       int64 t1, t2;
-
-       t1 = o1+w1;
-       t2 = o2+w2;
-
-       if(!(t1 > o2 && t2 > o1))
-               return 0;
-
-       return 1;
-}
-
-static Bits
-mkvar(Flow *f, Adr *a)
-{
-       Var *v;
-       int i, n, et, z, flag;
-       int64 w;
-       uint64 regu;
-       int64 o;
-       Bits bit;
-       Node *node;
-       Reg *r;
-       
-
-       /*
-        * mark registers used
-        */
-       if(a->type == TYPE_NONE)
-               goto none;
-
-       r = (Reg*)f->data;
-       r->use1.b[0] |= thearch.doregbits(a->index); // TODO: Use RtoB
-
-       switch(a->type) {
-       default:
-               regu = thearch.doregbits(a->reg) | thearch.RtoB(a->reg); // TODO: Use RtoB
-               if(regu == 0)
-                       goto none;
-               bit = zbits;
-               bit.b[0] = regu;
-               return bit;
-
-       case TYPE_ADDR:
-               // TODO(rsc): Remove special case here.
-               if(thearch.thechar == '9' || thearch.thechar == '5')
-                       goto memcase;
-               a->type = TYPE_MEM;
-               bit = mkvar(f, a);
-               setaddrs(bit);
-               a->type = TYPE_ADDR;
-               ostats.naddr++;
-               goto none;
-
-       case TYPE_MEM:
-       memcase:
-               if(r != R) {
-                       r->use1.b[0] |= thearch.RtoB(a->reg);
-                       /* NOTE: 5g did
-                               if(r->f.prog->scond & (C_PBIT|C_WBIT))
-                                       r->set.b[0] |= RtoB(a->reg);
-                       */
-               }
-               switch(a->name) {
-               default:
-                       goto none;
-               case NAME_EXTERN:
-               case NAME_STATIC:
-               case NAME_PARAM:
-               case NAME_AUTO:
-                       n = a->name;
-                       break;
-               }
-       }
-
-       node = a->node;
-       if(node == N || node->op != ONAME || node->orig == N)
-               goto none;
-       node = node->orig;
-       if(node->orig != node)
-               fatal("%D: bad node", a);
-       if(node->sym == S || node->sym->name[0] == '.')
-               goto none;
-       et = a->etype;
-       o = a->offset;
-       w = a->width;
-       if(w < 0)
-               fatal("bad width %lld for %D", w, a);
-
-       flag = 0;
-       for(i=0; i<nvar; i++) {
-               v = var+i;
-               if(v->node == node && v->name == n) {
-                       if(v->offset == o)
-                       if(v->etype == et)
-                       if(v->width == w) {
-                               // TODO(rsc): Remove special case for arm here.
-                               if(!flag || thearch.thechar != '5')
-                                       return blsh(i);
-                       }
-
-                       // if they overlap, disable both
-                       if(overlap(v->offset, v->width, o, w)) {
-//                             print("disable overlap %s %d %d %d %d, %E != %E\n", s->name, v->offset, v->width, o, w, v->etype, et);
-                               v->addr = 1;
-                               flag = 1;
-                       }
-               }
-       }
-
-       switch(et) {
-       case 0:
-       case TFUNC:
-               goto none;
-       }
-
-       if(nvar >= NVAR) {
-               if(debug['w'] > 1 && node != N)
-                       fatal("variable not optimized: %#N", node);
-               
-               // If we're not tracking a word in a variable, mark the rest as
-               // having its address taken, so that we keep the whole thing
-               // live at all calls. otherwise we might optimize away part of
-               // a variable but not all of it.
-               for(i=0; i<nvar; i++) {
-                       v = var+i;
-                       if(v->node == node)
-                               v->addr = 1;
-               }
-               goto none;
-       }
-
-       i = nvar;
-       nvar++;
-       v = var+i;
-       v->id = i;
-       v->offset = o;
-       v->name = n;
-       v->etype = et;
-       v->width = w;
-       v->addr = flag;         // funny punning
-       v->node = node;
-       
-       // node->opt is the head of a linked list
-       // of Vars within the given Node, so that
-       // we can start at a Var and find all the other
-       // Vars in the same Go variable.
-       v->nextinnode = node->opt;
-       node->opt = v;
-
-       bit = blsh(i);
-       if(n == NAME_EXTERN || n == NAME_STATIC)
-               for(z=0; z<BITS; z++)
-                       externs.b[z] |= bit.b[z];
-       if(n == NAME_PARAM)
-               for(z=0; z<BITS; z++)
-                       params.b[z] |= bit.b[z];
-
-       if(node->class == PPARAM)
-               for(z=0; z<BITS; z++)
-                       ivar.b[z] |= bit.b[z];
-       if(node->class == PPARAMOUT)
-               for(z=0; z<BITS; z++)
-                       ovar.b[z] |= bit.b[z];
-
-       // Treat values with their address taken as live at calls,
-       // because the garbage collector's liveness analysis in ../gc/plive.c does.
-       // These must be consistent or else we will elide stores and the garbage
-       // collector will see uninitialized data.
-       // The typical case where our own analysis is out of sync is when the
-       // node appears to have its address taken but that code doesn't actually
-       // get generated and therefore doesn't show up as an address being
-       // taken when we analyze the instruction stream.
-       // One instance of this case is when a closure uses the same name as
-       // an outer variable for one of its own variables declared with :=.
-       // The parser flags the outer variable as possibly shared, and therefore
-       // sets addrtaken, even though it ends up not being actually shared.
-       // If we were better about _ elision, _ = &x would suffice too.
-       // The broader := in a closure problem is mentioned in a comment in
-       // closure.c:/^typecheckclosure and dcl.c:/^oldname.
-       if(node->addrtaken)
-               v->addr = 1;
-
-       // Disable registerization for globals, because:
-       // (1) we might panic at any time and we want the recovery code
-       // to see the latest values (issue 1304).
-       // (2) we don't know what pointers might point at them and we want
-       // loads via those pointers to see updated values and vice versa (issue 7995).
-       //
-       // Disable registerization for results if using defer, because the deferred func
-       // might recover and return, causing the current values to be used.
-       if(node->class == PEXTERN || (hasdefer && node->class == PPARAMOUT))
-               v->addr = 1;
-
-       if(debug['R'])
-               print("bit=%2d et=%E w=%lld+%lld %#N %D flag=%d\n", i, et, o, w, node, a, v->addr);
-       ostats.nvar++;
-
-       return bit;
-
-none:
-       return zbits;
-}
-
-static void
-prop(Flow *f, Bits ref, Bits cal)
-{
-       Flow *f1, *f2;
-       Reg *r, *r1;
-       int z, i;
-       Var *v, *v1;
-
-       for(f1 = f; f1 != nil; f1 = f1->p1) {
-               r1 = (Reg*)f1->data;
-               for(z=0; z<BITS; z++) {
-                       ref.b[z] |= r1->refahead.b[z];
-                       if(ref.b[z] != r1->refahead.b[z]) {
-                               r1->refahead.b[z] = ref.b[z];
-                               change++;
-                       }
-                       cal.b[z] |= r1->calahead.b[z];
-                       if(cal.b[z] != r1->calahead.b[z]) {
-                               r1->calahead.b[z] = cal.b[z];
-                               change++;
-                       }
-               }
-               switch(f1->prog->as) {
-               case ACALL:
-                       if(noreturn(f1->prog))
-                               break;
-
-                       // Mark all input variables (ivar) as used, because that's what the
-                       // liveness bitmaps say. The liveness bitmaps say that so that a
-                       // panic will not show stale values in the parameter dump.
-                       // Mark variables with a recent VARDEF (r1->act) as used,
-                       // so that the optimizer flushes initializations to memory,
-                       // so that if a garbage collection happens during this CALL,
-                       // the collector will see initialized memory. Again this is to
-                       // match what the liveness bitmaps say.
-                       for(z=0; z<BITS; z++) {
-                               cal.b[z] |= ref.b[z] | externs.b[z] | ivar.b[z] | r1->act.b[z];
-                               ref.b[z] = 0;
-                       }
-                       
-                       // cal.b is the current approximation of what's live across the call.
-                       // Every bit in cal.b is a single stack word. For each such word,
-                       // find all the other tracked stack words in the same Go variable
-                       // (struct/slice/string/interface) and mark them live too.
-                       // This is necessary because the liveness analysis for the garbage
-                       // collector works at variable granularity, not at word granularity.
-                       // It is fundamental for slice/string/interface: the garbage collector
-                       // needs the whole value, not just some of the words, in order to
-                       // interpret the other bits correctly. Specifically, slice needs a consistent
-                       // ptr and cap, string needs a consistent ptr and len, and interface
-                       // needs a consistent type word and data word.
-                       for(z=0; z<BITS; z++) {
-                               if(cal.b[z] == 0)
-                                       continue;
-                               for(i=0; i<64; i++) {
-                                       if(z*64+i >= nvar || ((cal.b[z]>>i)&1) == 0)
-                                               continue;
-                                       v = var+z*64+i;
-                                       if(v->node->opt == nil) // v represents fixed register, not Go variable
-                                               continue;
-
-                                       // v->node->opt is the head of a linked list of Vars
-                                       // corresponding to tracked words from the Go variable v->node.
-                                       // Walk the list and set all the bits.
-                                       // For a large struct this could end up being quadratic:
-                                       // after the first setting, the outer loop (for z, i) would see a 1 bit
-                                       // for all of the remaining words in the struct, and for each such
-                                       // word would go through and turn on all the bits again.
-                                       // To avoid the quadratic behavior, we only turn on the bits if
-                                       // v is the head of the list or if the head's bit is not yet turned on.
-                                       // This will set the bits at most twice, keeping the overall loop linear.
-                                       v1 = v->node->opt;
-                                       if(v == v1 || !btest(&cal, v1->id)) {
-                                               for(; v1 != nil; v1 = v1->nextinnode) {
-                                                       biset(&cal, v1->id);
-                                               }
-                                       }
-                               }
-                       }
-                       break;
-
-               case ATEXT:
-                       for(z=0; z<BITS; z++) {
-                               cal.b[z] = 0;
-                               ref.b[z] = 0;
-                       }
-                       break;
-
-               case ARET:
-                       for(z=0; z<BITS; z++) {
-                               cal.b[z] = externs.b[z] | ovar.b[z];
-                               ref.b[z] = 0;
-                       }
-                       break;
-               }
-               for(z=0; z<BITS; z++) {
-                       ref.b[z] = (ref.b[z] & ~r1->set.b[z]) |
-                               r1->use1.b[z] | r1->use2.b[z];
-                       cal.b[z] &= ~(r1->set.b[z] | r1->use1.b[z] | r1->use2.b[z]);
-                       r1->refbehind.b[z] = ref.b[z];
-                       r1->calbehind.b[z] = cal.b[z];
-               }
-               if(f1->active)
-                       break;
-               f1->active = 1;
-       }
-
-       for(; f != f1; f = f->p1) {
-               r = (Reg*)f->data;
-               for(f2 = f->p2; f2 != nil; f2 = f2->p2link)
-                       prop(f2, r->refbehind, r->calbehind);
-       }
-}
-
-static void
-synch(Flow *f, Bits dif)
-{
-       Flow *f1;
-       Reg *r1;
-       int z;
-
-       for(f1 = f; f1 != nil; f1 = f1->s1) {
-               r1 = (Reg*)f1->data;
-               for(z=0; z<BITS; z++) {
-                       dif.b[z] = (dif.b[z] &
-                               ~(~r1->refbehind.b[z] & r1->refahead.b[z])) |
-                                       r1->set.b[z] | r1->regdiff.b[z];
-                       if(dif.b[z] != r1->regdiff.b[z]) {
-                               r1->regdiff.b[z] = dif.b[z];
-                               change++;
-                       }
-               }
-               if(f1->active)
-                       break;
-               f1->active = 1;
-               for(z=0; z<BITS; z++)
-                       dif.b[z] &= ~(~r1->calbehind.b[z] & r1->calahead.b[z]);
-               if(f1->s2 != nil)
-                       synch(f1->s2, dif);
-       }
-}
-
-static uint64
-allreg(uint64 b, Rgn *r)
-{
-       Var *v;
-       int i;
-
-       v = var + r->varno;
-       r->regno = 0;
-       switch(v->etype) {
-
-       default:
-               fatal("unknown etype %d/%E", bitno(b), v->etype);
-               break;
-
-       case TINT8:
-       case TUINT8:
-       case TINT16:
-       case TUINT16:
-       case TINT32:
-       case TUINT32:
-       case TINT64:
-       case TUINT64:
-       case TINT:
-       case TUINT:
-       case TUINTPTR:
-       case TBOOL:
-       case TPTR32:
-       case TPTR64:
-               i = thearch.BtoR(~b);
-               if(i && r->cost > 0) {
-                       r->regno = i;
-                       return thearch.RtoB(i);
-               }
-               break;
-
-       case TFLOAT32:
-       case TFLOAT64:
-               i = thearch.BtoF(~b);
-               if(i && r->cost > 0) {
-                       r->regno = i;
-                       return thearch.FtoB(i);
-               }
-               break;
-       }
-       return 0;
-}
-
-static void
-paint1(Flow *f, int bn)
-{
-       Flow *f1;
-       Reg *r, *r1;
-       int z;
-       uint64 bb;
-
-       z = bn/64;
-       bb = 1LL<<(bn%64);
-       r = (Reg*)f->data;
-       if(r->act.b[z] & bb)
-               return;
-       for(;;) {
-               if(!(r->refbehind.b[z] & bb))
-                       break;
-               f1 = f->p1;
-               if(f1 == nil)
-                       break;
-               r1 = (Reg*)f1->data;
-               if(!(r1->refahead.b[z] & bb))
-                       break;
-               if(r1->act.b[z] & bb)
-                       break;
-               f = f1;
-               r = r1;
-       }
-
-       if(LOAD(r) & ~(r->set.b[z]&~(r->use1.b[z]|r->use2.b[z])) & bb) {
-               change -= CLOAD * f->loop;
-       }
-       for(;;) {
-               r->act.b[z] |= bb;
-
-               if(f->prog->as != ANOP) { // don't give credit for NOPs
-                       if(r->use1.b[z] & bb)
-                               change += CREF * f->loop;
-                       if((r->use2.b[z]|r->set.b[z]) & bb)
-                               change += CREF * f->loop;
-               }
-
-               if(STORE(r) & r->regdiff.b[z] & bb) {
-                       change -= CLOAD * f->loop;
-               }
-
-               if(r->refbehind.b[z] & bb)
-                       for(f1 = f->p2; f1 != nil; f1 = f1->p2link)
-                               if(((Reg*)f1->data)->refahead.b[z] & bb)
-                                       paint1(f1, bn);
-
-               if(!(r->refahead.b[z] & bb))
-                       break;
-               f1 = f->s2;
-               if(f1 != nil)
-                       if(((Reg*)f1->data)->refbehind.b[z] & bb)
-                               paint1(f1, bn);
-               f = f->s1;
-               if(f == nil)
-                       break;
-               r = (Reg*)f->data;
-               if(r->act.b[z] & bb)
-                       break;
-               if(!(r->refbehind.b[z] & bb))
-                       break;
-       }
-}
-
-static uint64
-paint2(Flow *f, int bn, int depth)
-{
-       Flow *f1;
-       Reg *r, *r1;
-       int z;
-       uint64 bb, vreg;
-
-       z = bn/64;
-       bb = 1LL << (bn%64);
-       vreg = regbits;
-       r = (Reg*)f->data;
-       if(!(r->act.b[z] & bb))
-               return vreg;
-       for(;;) {
-               if(!(r->refbehind.b[z] & bb))
-                       break;
-               f1 = f->p1;
-               if(f1 == nil)
-                       break;
-               r1 = (Reg*)f1->data;
-               if(!(r1->refahead.b[z] & bb))
-                       break;
-               if(!(r1->act.b[z] & bb))
-                       break;
-               f = f1;
-               r = r1;
-       }
-       for(;;) {
-               if(debug['R'] && debug['v'])
-                       print("  paint2 %d %P\n", depth, f->prog);
-
-               r->act.b[z] &= ~bb;
-
-               vreg |= r->regu;
-
-               if(r->refbehind.b[z] & bb)
-                       for(f1 = f->p2; f1 != nil; f1 = f1->p2link)
-                               if(((Reg*)f1->data)->refahead.b[z] & bb)
-                                       vreg |= paint2(f1, bn, depth+1);
-
-               if(!(r->refahead.b[z] & bb))
-                       break;
-               f1 = f->s2;
-               if(f1 != nil)
-                       if(((Reg*)f1->data)->refbehind.b[z] & bb)
-                               vreg |= paint2(f1, bn, depth+1);
-               f = f->s1;
-               if(f == nil)
-                       break;
-               r = (Reg*)f->data;
-               if(!(r->act.b[z] & bb))
-                       break;
-               if(!(r->refbehind.b[z] & bb))
-                       break;
-       }
-
-       return vreg;
-}
-
-static void
-paint3(Flow *f, int bn, uint64 rb, int rn)
-{
-       Flow *f1;
-       Reg *r, *r1;
-       Prog *p;
-       int z;
-       uint64 bb;
-
-       z = bn/64;
-       bb = 1LL << (bn%64);
-       r = (Reg*)f->data;
-       if(r->act.b[z] & bb)
-               return;
-       for(;;) {
-               if(!(r->refbehind.b[z] & bb))
-                       break;
-               f1 = f->p1;
-               if(f1 == nil)
-                       break;
-               r1 = (Reg*)f1->data;
-               if(!(r1->refahead.b[z] & bb))
-                       break;
-               if(r1->act.b[z] & bb)
-                       break;
-               f = f1;
-               r = r1;
-       }
-
-       if(LOAD(r) & ~(r->set.b[z] & ~(r->use1.b[z]|r->use2.b[z])) & bb)
-               addmove(f, bn, rn, 0);
-       for(;;) {
-               r->act.b[z] |= bb;
-               p = f->prog;
-
-               if(r->use1.b[z] & bb) {
-                       if(debug['R'] && debug['v'])
-                               print("%P", p);
-                       addreg(&p->from, rn);
-                       if(debug['R'] && debug['v'])
-                               print(" ===change== %P\n", p);
-               }
-               if((r->use2.b[z]|r->set.b[z]) & bb) {
-                       if(debug['R'] && debug['v'])
-                               print("%P", p);
-                       addreg(&p->to, rn);
-                       if(debug['R'] && debug['v'])
-                               print(" ===change== %P\n", p);
-               }
-
-               if(STORE(r) & r->regdiff.b[z] & bb)
-                       addmove(f, bn, rn, 1);
-               r->regu |= rb;
-
-               if(r->refbehind.b[z] & bb)
-                       for(f1 = f->p2; f1 != nil; f1 = f1->p2link)
-                               if(((Reg*)f1->data)->refahead.b[z] & bb)
-                                       paint3(f1, bn, rb, rn);
-
-               if(!(r->refahead.b[z] & bb))
-                       break;
-               f1 = f->s2;
-               if(f1 != nil)
-                       if(((Reg*)f1->data)->refbehind.b[z] & bb)
-                               paint3(f1, bn, rb, rn);
-               f = f->s1;
-               if(f == nil)
-                       break;
-               r = (Reg*)f->data;
-               if(r->act.b[z] & bb)
-                       break;
-               if(!(r->refbehind.b[z] & bb))
-                       break;
-       }
-}
-
-static void
-addreg(Adr *a, int rn)
-{
-       a->sym = nil;
-       a->node = nil;
-       a->offset = 0;
-       a->type = TYPE_REG;
-       a->reg = rn;
-       a->name = 0;
-
-       ostats.ncvtreg++;
-}
-
-void
-dumpone(Flow *f, int isreg)
-{
-       int z;
-       Bits bit;
-       Reg *r;
-
-       print("%d:%P", f->loop, f->prog);
-       if(isreg) {     
-               r = (Reg*)f->data;
-               for(z=0; z<BITS; z++)
-                       bit.b[z] =
-                               r->set.b[z] |
-                               r->use1.b[z] |
-                               r->use2.b[z] |
-                               r->refbehind.b[z] |
-                               r->refahead.b[z] |
-                               r->calbehind.b[z] |
-                               r->calahead.b[z] |
-                               r->regdiff.b[z] |
-                               r->act.b[z] |
-                                       0;
-               if(bany(&bit)) {
-                       print("\t");
-                       if(bany(&r->set))
-                               print(" s:%Q", r->set);
-                       if(bany(&r->use1))
-                               print(" u1:%Q", r->use1);
-                       if(bany(&r->use2))
-                               print(" u2:%Q", r->use2);
-                       if(bany(&r->refbehind))
-                               print(" rb:%Q ", r->refbehind);
-                       if(bany(&r->refahead))
-                               print(" ra:%Q ", r->refahead);
-                       if(bany(&r->calbehind))
-                               print(" cb:%Q ", r->calbehind);
-                       if(bany(&r->calahead))
-                               print(" ca:%Q ", r->calahead);
-                       if(bany(&r->regdiff))
-                               print(" d:%Q ", r->regdiff);
-                       if(bany(&r->act))
-                               print(" a:%Q ", r->act);
-               }
-       }
-       print("\n");
-}
-
-void
-dumpit(char *str, Flow *r0, int isreg)
-{
-       Flow *r, *r1;
-
-       print("\n%s\n", str);
-       for(r = r0; r != nil; r = r->link) {
-               dumpone(r, isreg);
-               r1 = r->p2;
-               if(r1 != nil) {
-                       print(" pred:");
-                       for(; r1 != nil; r1 = r1->p2link)
-                               print(" %.4ud", (int)r1->prog->pc);
-                       if(r->p1 != nil)
-                               print(" (and %.4ud)", (int)r->p1->prog->pc);
-                       else
-                               print(" (only)");
-                       print("\n");
-               }
-               // Print successors if it's not just the next one
-               if(r->s1 != r->link || r->s2 != nil) {
-                       print(" succ:");
-                       if(r->s1 != nil)
-                               print(" %.4ud", (int)r->s1->prog->pc);
-                       if(r->s2 != nil)
-                               print(" %.4ud", (int)r->s2->prog->pc);
-                       print("\n");
-               }
-       }
-}
diff --git a/src/cmd/gc/runtime.go b/src/cmd/gc/runtime.go
deleted file mode 100644 (file)
index 0a4c1b8..0000000
+++ /dev/null
@@ -1,191 +0,0 @@
-// Copyright 2009 The Go Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style
-// license that can be found in the LICENSE file.
-
-// NOTE: If you change this file you must run "./mkbuiltin"
-// to update builtin.c.  This is not done automatically
-// to avoid depending on having a working compiler binary.
-
-// +build ignore
-
-package PACKAGE
-
-// emitted by compiler, not referred to by go programs
-
-func newobject(typ *byte) *any
-func panicindex()
-func panicslice()
-func panicdivide()
-func throwreturn()
-func throwinit()
-func panicwrap(string, string, string)
-
-func gopanic(interface{})
-func gorecover(*int32) interface{}
-
-func printbool(bool)
-func printfloat(float64)
-func printint(int64)
-func printhex(uint64)
-func printuint(uint64)
-func printcomplex(complex128)
-func printstring(string)
-func printpointer(any)
-func printiface(any)
-func printeface(any)
-func printslice(any)
-func printnl()
-func printsp()
-func printlock()
-func printunlock()
-
-func concatstring2(*[32]byte, string, string) string
-func concatstring3(*[32]byte, string, string, string) string
-func concatstring4(*[32]byte, string, string, string, string) string
-func concatstring5(*[32]byte, string, string, string, string, string) string
-func concatstrings(*[32]byte, []string) string
-
-func cmpstring(string, string) int
-func eqstring(string, string) bool
-func intstring(*[4]byte, int64) string
-func slicebytetostring(*[32]byte, []byte) string
-func slicebytetostringtmp([]byte) string
-func slicerunetostring(*[32]byte, []rune) string
-func stringtoslicebyte(*[32]byte, string) []byte
-func stringtoslicebytetmp(string) []byte
-func stringtoslicerune(*[32]rune, string) []rune
-func stringiter(string, int) int
-func stringiter2(string, int) (retk int, retv rune)
-func slicecopy(to any, fr any, wid uintptr) int
-func slicestringcopy(to any, fr any) int
-
-// interface conversions
-func typ2Itab(typ *byte, typ2 *byte, cache **byte) (ret *byte)
-func convI2E(elem any) (ret any)
-func convI2I(typ *byte, elem any) (ret any)
-func convT2E(typ *byte, elem *any) (ret any)
-func convT2I(typ *byte, typ2 *byte, cache **byte, elem *any) (ret any)
-
-// interface type assertions  x.(T)
-func assertE2E(typ *byte, iface any, ret *any)
-func assertE2E2(typ *byte, iface any, ret *any) bool
-func assertE2I(typ *byte, iface any, ret *any)
-func assertE2I2(typ *byte, iface any, ret *any) bool
-func assertE2T(typ *byte, iface any, ret *any)
-func assertE2T2(typ *byte, iface any, ret *any) bool
-func assertI2E(typ *byte, iface any, ret *any)
-func assertI2E2(typ *byte, iface any, ret *any) bool
-func assertI2I(typ *byte, iface any, ret *any)
-func assertI2I2(typ *byte, iface any, ret *any) bool
-func assertI2T(typ *byte, iface any, ret *any)
-func assertI2T2(typ *byte, iface any, ret *any) bool
-
-func ifaceeq(i1 any, i2 any) (ret bool)
-func efaceeq(i1 any, i2 any) (ret bool)
-func ifacethash(i1 any) (ret uint32)
-func efacethash(i1 any) (ret uint32)
-
-// *byte is really *runtime.Type
-func makemap(mapType *byte, hint int64, mapbuf *any, bucketbuf *any) (hmap map[any]any)
-func mapaccess1(mapType *byte, hmap map[any]any, key *any) (val *any)
-func mapaccess1_fast32(mapType *byte, hmap map[any]any, key any) (val *any)
-func mapaccess1_fast64(mapType *byte, hmap map[any]any, key any) (val *any)
-func mapaccess1_faststr(mapType *byte, hmap map[any]any, key any) (val *any)
-func mapaccess2(mapType *byte, hmap map[any]any, key *any) (val *any, pres bool)
-func mapaccess2_fast32(mapType *byte, hmap map[any]any, key any) (val *any, pres bool)
-func mapaccess2_fast64(mapType *byte, hmap map[any]any, key any) (val *any, pres bool)
-func mapaccess2_faststr(mapType *byte, hmap map[any]any, key any) (val *any, pres bool)
-func mapassign1(mapType *byte, hmap map[any]any, key *any, val *any)
-func mapiterinit(mapType *byte, hmap map[any]any, hiter *any)
-func mapdelete(mapType *byte, hmap map[any]any, key *any)
-func mapiternext(hiter *any)
-
-// *byte is really *runtime.Type
-func makechan(chanType *byte, hint int64) (hchan chan any)
-func chanrecv1(chanType *byte, hchan <-chan any, elem *any)
-func chanrecv2(chanType *byte, hchan <-chan any, elem *any) bool
-func chansend1(chanType *byte, hchan chan<- any, elem *any)
-func closechan(hchan any)
-
-// *byte is really *runtime.Type
-func writebarrierptr(dst *any, src any)
-func writebarrierstring(dst *any, src any)
-func writebarrierslice(dst *any, src any)
-func writebarrieriface(dst *any, src any)
-
-// The unused *byte argument makes sure that src is 2-pointer-aligned,
-// which is the maximum alignment on NaCl amd64p32
-// (and possibly on 32-bit systems if we start 64-bit aligning uint64s).
-// The bitmap in the name tells which words being copied are pointers.
-func writebarrierfat01(dst *any, _ *byte, src any)
-func writebarrierfat10(dst *any, _ *byte, src any)
-func writebarrierfat11(dst *any, _ *byte, src any)
-func writebarrierfat001(dst *any, _ *byte, src any)
-func writebarrierfat010(dst *any, _ *byte, src any)
-func writebarrierfat011(dst *any, _ *byte, src any)
-func writebarrierfat100(dst *any, _ *byte, src any)
-func writebarrierfat101(dst *any, _ *byte, src any)
-func writebarrierfat110(dst *any, _ *byte, src any)
-func writebarrierfat111(dst *any, _ *byte, src any)
-func writebarrierfat0001(dst *any, _ *byte, src any)
-func writebarrierfat0010(dst *any, _ *byte, src any)
-func writebarrierfat0011(dst *any, _ *byte, src any)
-func writebarrierfat0100(dst *any, _ *byte, src any)
-func writebarrierfat0101(dst *any, _ *byte, src any)
-func writebarrierfat0110(dst *any, _ *byte, src any)
-func writebarrierfat0111(dst *any, _ *byte, src any)
-func writebarrierfat1000(dst *any, _ *byte, src any)
-func writebarrierfat1001(dst *any, _ *byte, src any)
-func writebarrierfat1010(dst *any, _ *byte, src any)
-func writebarrierfat1011(dst *any, _ *byte, src any)
-func writebarrierfat1100(dst *any, _ *byte, src any)
-func writebarrierfat1101(dst *any, _ *byte, src any)
-func writebarrierfat1110(dst *any, _ *byte, src any)
-func writebarrierfat1111(dst *any, _ *byte, src any)
-
-func typedmemmove(typ *byte, dst *any, src *any)
-func typedslicecopy(typ *byte, dst any, src any) int
-
-func selectnbsend(chanType *byte, hchan chan<- any, elem *any) bool
-func selectnbrecv(chanType *byte, elem *any, hchan <-chan any) bool
-func selectnbrecv2(chanType *byte, elem *any, received *bool, hchan <-chan any) bool
-
-func newselect(sel *byte, selsize int64, size int32)
-func selectsend(sel *byte, hchan chan<- any, elem *any) (selected bool)
-func selectrecv(sel *byte, hchan <-chan any, elem *any) (selected bool)
-func selectrecv2(sel *byte, hchan <-chan any, elem *any, received *bool) (selected bool)
-func selectdefault(sel *byte) (selected bool)
-func selectgo(sel *byte)
-func block()
-
-func makeslice(typ *byte, nel int64, cap int64) (ary []any)
-func growslice(typ *byte, old []any, n int64) (ary []any)
-func memmove(to *any, frm *any, length uintptr)
-func memclr(ptr *byte, length uintptr)
-
-func memequal(x, y *any, size uintptr) bool
-func memequal8(x, y *any) bool
-func memequal16(x, y *any) bool
-func memequal32(x, y *any) bool
-func memequal64(x, y *any) bool
-func memequal128(x, y *any) bool
-
-// only used on 32-bit
-func int64div(int64, int64) int64
-func uint64div(uint64, uint64) uint64
-func int64mod(int64, int64) int64
-func uint64mod(uint64, uint64) uint64
-func float64toint64(float64) int64
-func float64touint64(float64) uint64
-func int64tofloat64(int64) float64
-func uint64tofloat64(uint64) float64
-
-func complex128div(num complex128, den complex128) (quo complex128)
-
-// race detection
-func racefuncenter(uintptr)
-func racefuncexit()
-func raceread(uintptr)
-func racewrite(uintptr)
-func racereadrange(addr, size uintptr)
-func racewriterange(addr, size uintptr)
diff --git a/src/cmd/gc/select.c b/src/cmd/gc/select.c
deleted file mode 100644 (file)
index 537d0ca..0000000
+++ /dev/null
@@ -1,375 +0,0 @@
-// Copyright 2009 The Go Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style
-// license that can be found in the LICENSE file.
-
-/*
- * select
- */
-
-#include <u.h>
-#include <libc.h>
-#include "go.h"
-
-static Type* selecttype(int32 size);
-
-void
-typecheckselect(Node *sel)
-{
-       Node *ncase, *n, *def;
-       NodeList *l;
-       int lno, count;
-
-       def = nil;
-       lno = setlineno(sel);
-       count = 0;
-       typechecklist(sel->ninit, Etop);
-       for(l=sel->list; l; l=l->next) {
-               count++;
-               ncase = l->n;
-               setlineno(ncase);
-               if(ncase->op != OXCASE)
-                       fatal("typecheckselect %O", ncase->op);
-
-               if(ncase->list == nil) {
-                       // default
-                       if(def != N)
-                               yyerror("multiple defaults in select (first at %L)", def->lineno);
-                       else
-                               def = ncase;
-               } else if(ncase->list->next) {
-                       yyerror("select cases cannot be lists");
-               } else {
-                       n = typecheck(&ncase->list->n, Etop);
-                       ncase->left = n;
-                       ncase->list = nil;
-                       setlineno(n);
-                       switch(n->op) {
-                       default:
-                               yyerror("select case must be receive, send or assign recv");
-                               break;
-
-                       case OAS:
-                               // convert x = <-c into OSELRECV(x, <-c).
-                               // remove implicit conversions; the eventual assignment
-                               // will reintroduce them.
-                               if((n->right->op == OCONVNOP || n->right->op == OCONVIFACE) && n->right->implicit)
-                                       n->right = n->right->left;
-
-                               if(n->right->op != ORECV) {
-                                       yyerror("select assignment must have receive on right hand side");
-                                       break;
-                               }
-                               n->op = OSELRECV;
-                               break;
-
-                       case OAS2RECV:
-                               // convert x, ok = <-c into OSELRECV2(x, <-c) with ntest=ok
-                               if(n->rlist->n->op != ORECV) {
-                                       yyerror("select assignment must have receive on right hand side");
-                                       break;
-                               }
-                               n->op = OSELRECV2;
-                               n->left = n->list->n;
-                               n->ntest = n->list->next->n;
-                               n->list = nil;
-                               n->right = n->rlist->n;
-                               n->rlist = nil;
-                               break;
-
-                       case ORECV:
-                               // convert <-c into OSELRECV(N, <-c)
-                               n = nod(OSELRECV, N, n);
-                               n->typecheck = 1;
-                               ncase->left = n;
-                               break;
-
-                       case OSEND:
-                               break;
-                       }
-               }
-               typechecklist(ncase->nbody, Etop);
-       }
-       sel->xoffset = count;
-       lineno = lno;
-}
-
-void
-walkselect(Node *sel)
-{
-       int lno, i;
-       Node *n, *r, *a, *var, *selv, *cas, *dflt, *ch;
-       NodeList *l, *init;
-       
-       if(sel->list == nil && sel->xoffset != 0)
-               fatal("double walkselect");     // already rewrote
-       
-       lno = setlineno(sel);
-       i = count(sel->list);
-       
-       // optimization: zero-case select
-       if(i == 0) {
-               sel->nbody = list1(mkcall("block", nil, nil));
-               goto out;
-       }
-
-       // optimization: one-case select: single op.
-       // TODO(rsc): Reenable optimization once order.c can handle it.
-       // golang.org/issue/7672.
-       if(i == 1) {
-               cas = sel->list->n;
-               setlineno(cas);
-               l = cas->ninit;
-               if(cas->left != N) {  // not default:
-                       n = cas->left;
-                       l = concat(l, n->ninit);
-                       n->ninit = nil;
-                       switch(n->op) {
-                       default:
-                               fatal("select %O", n->op);
-
-                       case OSEND:
-                               // ok already
-                               ch = n->left;
-                               break;
-
-                       case OSELRECV:
-                       case OSELRECV2:
-                               ch = n->right->left;
-                               if(n->op == OSELRECV || n->ntest == N) {
-                                       if(n->left == N)
-                                               n = n->right;
-                                       else
-                                               n->op = OAS;
-                                       break;
-                               }
-                       
-                               if(n->left == N) {
-                                       typecheck(&nblank, Erv | Easgn);
-                                       n->left = nblank;
-                               }
-                               n->op = OAS2;
-                               n->list = list(list1(n->left), n->ntest);
-                               n->rlist = list1(n->right);
-                               n->right = N;
-                               n->left = N;
-                               n->ntest = N;
-                               n->typecheck = 0;
-                               typecheck(&n, Etop);
-                               break;
-                       }
-
-                       // if ch == nil { block() }; n;
-                       a = nod(OIF, N, N);
-                       a->ntest = nod(OEQ, ch, nodnil());
-                       a->nbody = list1(mkcall("block", nil, &l));
-                       typecheck(&a, Etop);
-                       l = list(l, a);
-                       l = list(l, n);
-               }
-               l = concat(l, cas->nbody);
-               sel->nbody = l;
-               goto out;
-       }
-
-       // convert case value arguments to addresses.
-       // this rewrite is used by both the general code and the next optimization.
-       for(l=sel->list; l; l=l->next) {
-               cas = l->n;
-               setlineno(cas);
-               n = cas->left;
-               if(n == N)
-                       continue;
-               switch(n->op) {
-               case OSEND:
-                       n->right = nod(OADDR, n->right, N);
-                       typecheck(&n->right, Erv);
-                       break;
-               case OSELRECV:
-               case OSELRECV2:
-                       if(n->op == OSELRECV2 && n->ntest == N)
-                               n->op = OSELRECV;
-                       if(n->op == OSELRECV2) {
-                               n->ntest = nod(OADDR, n->ntest, N);
-                               typecheck(&n->ntest, Erv);
-                       }
-                       if(n->left == N)
-                               n->left = nodnil();
-                       else {
-                               n->left = nod(OADDR, n->left, N);
-                               typecheck(&n->left, Erv);
-                       }                       
-                       break;
-               }
-       }
-
-       // optimization: two-case select but one is default: single non-blocking op.
-       if(i == 2 && (sel->list->n->left == nil || sel->list->next->n->left == nil)) {
-               if(sel->list->n->left == nil) {
-                       cas = sel->list->next->n;
-                       dflt = sel->list->n;
-               } else {
-                       dflt = sel->list->next->n;
-                       cas = sel->list->n;
-               }
-               
-               n = cas->left;
-               setlineno(n);
-               r = nod(OIF, N, N);
-               r->ninit = cas->ninit;
-               switch(n->op) {
-               default:
-                       fatal("select %O", n->op);
-
-               case OSEND:
-                       // if selectnbsend(c, v) { body } else { default body }
-                       ch = n->left;
-                       r->ntest = mkcall1(chanfn("selectnbsend", 2, ch->type),
-                                       types[TBOOL], &r->ninit, typename(ch->type), ch, n->right);
-                       break;
-                       
-               case OSELRECV:
-                       // if c != nil && selectnbrecv(&v, c) { body } else { default body }
-                       r = nod(OIF, N, N);
-                       r->ninit = cas->ninit;
-                       ch = n->right->left;
-                       r->ntest = mkcall1(chanfn("selectnbrecv", 2, ch->type),
-                                       types[TBOOL], &r->ninit, typename(ch->type), n->left, ch);
-                       break;
-
-               case OSELRECV2:
-                       // if c != nil && selectnbrecv2(&v, c) { body } else { default body }
-                       r = nod(OIF, N, N);
-                       r->ninit = cas->ninit;
-                       ch = n->right->left;
-                       r->ntest = mkcall1(chanfn("selectnbrecv2", 2, ch->type),
-                                       types[TBOOL], &r->ninit, typename(ch->type), n->left, n->ntest, ch);
-                       break;
-               }
-               typecheck(&r->ntest, Erv);
-               r->nbody = cas->nbody;
-               r->nelse = concat(dflt->ninit, dflt->nbody);
-               sel->nbody = list1(r);
-               goto out;
-       }               
-
-       init = sel->ninit;
-       sel->ninit = nil;
-
-       // generate sel-struct
-       setlineno(sel);
-       selv = temp(selecttype(sel->xoffset));
-       r = nod(OAS, selv, N);
-       typecheck(&r, Etop);
-       init = list(init, r);
-       var = conv(conv(nod(OADDR, selv, N), types[TUNSAFEPTR]), ptrto(types[TUINT8]));
-       r = mkcall("newselect", T, nil, var, nodintconst(selv->type->width), nodintconst(sel->xoffset));
-       typecheck(&r, Etop);
-       init = list(init, r);
-
-       // register cases
-       for(l=sel->list; l; l=l->next) {
-               cas = l->n;
-               setlineno(cas);
-               n = cas->left;
-               r = nod(OIF, N, N);
-               r->ninit = cas->ninit;
-               cas->ninit = nil;
-               if(n != nil) {
-                       r->ninit = concat(r->ninit, n->ninit);
-                       n->ninit = nil;
-               }
-               if(n == nil) {
-                       // selectdefault(sel *byte);
-                       r->ntest = mkcall("selectdefault", types[TBOOL], &r->ninit, var);
-               } else {
-                       switch(n->op) {
-                       default:
-                               fatal("select %O", n->op);
-       
-                       case OSEND:
-                               // selectsend(sel *byte, hchan *chan any, elem *any) (selected bool);
-                               r->ntest = mkcall1(chanfn("selectsend", 2, n->left->type), types[TBOOL],
-                                       &r->ninit, var, n->left, n->right);
-                               break;
-
-                       case OSELRECV:
-                               // selectrecv(sel *byte, hchan *chan any, elem *any) (selected bool);
-                               r->ntest = mkcall1(chanfn("selectrecv", 2, n->right->left->type), types[TBOOL],
-                                       &r->ninit, var, n->right->left, n->left);
-                               break;
-
-                       case OSELRECV2:
-                               // selectrecv2(sel *byte, hchan *chan any, elem *any, received *bool) (selected bool);
-                               r->ntest = mkcall1(chanfn("selectrecv2", 2, n->right->left->type), types[TBOOL],
-                                       &r->ninit, var, n->right->left, n->left, n->ntest);
-                               break;
-                       }
-               }
-               // selv is no longer alive after use.
-               r->nbody = list(r->nbody, nod(OVARKILL, selv, N));
-               r->nbody = concat(r->nbody, cas->nbody);
-               r->nbody = list(r->nbody, nod(OBREAK, N, N));
-               init = list(init, r);
-       }
-
-       // run the select
-       setlineno(sel);
-       init = list(init, mkcall("selectgo", T, nil, var));
-       sel->nbody = init;
-
-out:
-       sel->list = nil;
-       walkstmtlist(sel->nbody);
-       lineno = lno;
-}
-
-// Keep in sync with src/runtime/chan.h.
-static Type*
-selecttype(int32 size)
-{
-       Node *sel, *sudog, *scase, *arr;
-
-       // TODO(dvyukov): it's possible to generate SudoG and Scase only once
-       // and then cache; and also cache Select per size.
-       sudog = nod(OTSTRUCT, N, N);
-       sudog->list = list(sudog->list, nod(ODCLFIELD, newname(lookup("g")), typenod(ptrto(types[TUINT8]))));
-       sudog->list = list(sudog->list, nod(ODCLFIELD, newname(lookup("selectdone")), typenod(ptrto(types[TUINT8]))));
-       sudog->list = list(sudog->list, nod(ODCLFIELD, newname(lookup("next")), typenod(ptrto(types[TUINT8]))));
-       sudog->list = list(sudog->list, nod(ODCLFIELD, newname(lookup("prev")), typenod(ptrto(types[TUINT8]))));
-       sudog->list = list(sudog->list, nod(ODCLFIELD, newname(lookup("elem")), typenod(ptrto(types[TUINT8]))));
-       sudog->list = list(sudog->list, nod(ODCLFIELD, newname(lookup("releasetime")), typenod(types[TUINT64])));
-       sudog->list = list(sudog->list, nod(ODCLFIELD, newname(lookup("nrelease")), typenod(types[TINT32])));
-       sudog->list = list(sudog->list, nod(ODCLFIELD, newname(lookup("waitlink")), typenod(ptrto(types[TUINT8]))));
-       typecheck(&sudog, Etype);
-       sudog->type->noalg = 1;
-       sudog->type->local = 1;
-
-       scase = nod(OTSTRUCT, N, N);
-       scase->list = list(scase->list, nod(ODCLFIELD, newname(lookup("elem")), typenod(ptrto(types[TUINT8]))));
-       scase->list = list(scase->list, nod(ODCLFIELD, newname(lookup("chan")), typenod(ptrto(types[TUINT8]))));
-       scase->list = list(scase->list, nod(ODCLFIELD, newname(lookup("pc")), typenod(types[TUINTPTR])));
-       scase->list = list(scase->list, nod(ODCLFIELD, newname(lookup("kind")), typenod(types[TUINT16])));
-       scase->list = list(scase->list, nod(ODCLFIELD, newname(lookup("so")), typenod(types[TUINT16])));
-       scase->list = list(scase->list, nod(ODCLFIELD, newname(lookup("receivedp")), typenod(ptrto(types[TUINT8]))));
-       scase->list = list(scase->list, nod(ODCLFIELD, newname(lookup("releasetime")), typenod(types[TUINT64])));
-       typecheck(&scase, Etype);
-       scase->type->noalg = 1;
-       scase->type->local = 1;
-
-       sel = nod(OTSTRUCT, N, N);
-       sel->list = list(sel->list, nod(ODCLFIELD, newname(lookup("tcase")), typenod(types[TUINT16])));
-       sel->list = list(sel->list, nod(ODCLFIELD, newname(lookup("ncase")), typenod(types[TUINT16])));
-       sel->list = list(sel->list, nod(ODCLFIELD, newname(lookup("pollorder")), typenod(ptrto(types[TUINT8]))));
-       sel->list = list(sel->list, nod(ODCLFIELD, newname(lookup("lockorder")), typenod(ptrto(types[TUINT8]))));
-       arr = nod(OTARRAY, nodintconst(size), scase);
-       sel->list = list(sel->list, nod(ODCLFIELD, newname(lookup("scase")), arr));
-       arr = nod(OTARRAY, nodintconst(size), typenod(ptrto(types[TUINT8])));
-       sel->list = list(sel->list, nod(ODCLFIELD, newname(lookup("lockorderarr")), arr));
-       arr = nod(OTARRAY, nodintconst(size), typenod(types[TUINT16]));
-       sel->list = list(sel->list, nod(ODCLFIELD, newname(lookup("pollorderarr")), arr));
-       typecheck(&sel, Etype);
-       sel->type->noalg = 1;
-       sel->type->local = 1;
-
-       return sel->type;
-}
diff --git a/src/cmd/gc/sinit.c b/src/cmd/gc/sinit.c
deleted file mode 100644 (file)
index 1015950..0000000
+++ /dev/null
@@ -1,1502 +0,0 @@
-// Copyright 2009 The Go Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style
-// license that can be found in the LICENSE file.
-
-/*
- * static initialization
- */
-
-#include       <u.h>
-#include       <libc.h>
-#include       "go.h"
-
-enum
-{
-       InitNotStarted = 0,
-       InitDone = 1,
-       InitPending = 2,
-};
-
-static void initplan(Node*);
-static NodeList *initlist;
-static void init2(Node*, NodeList**);
-static void init2list(NodeList*, NodeList**);
-static int staticinit(Node*, NodeList**);
-static Node *staticname(Type*, int);
-
-// init1 walks the AST starting at n, and accumulates in out
-// the list of definitions needing init code in dependency order.
-static void
-init1(Node *n, NodeList **out)
-{
-       NodeList *l;
-       Node *nv;
-
-       if(n == N)
-               return;
-       init1(n->left, out);
-       init1(n->right, out);
-       for(l=n->list; l; l=l->next)
-               init1(l->n, out);
-
-       if(n->left && n->type && n->left->op == OTYPE && n->class == PFUNC) {
-               // Methods called as Type.Method(receiver, ...).
-               // Definitions for method expressions are stored in type->nname.
-               init1(n->type->nname, out);
-       }
-
-       if(n->op != ONAME)
-               return;
-       switch(n->class) {
-       case PEXTERN:
-       case PFUNC:
-               break;
-       default:
-               if(isblank(n) && n->curfn == N && n->defn != N && n->defn->initorder == InitNotStarted) {
-                       // blank names initialization is part of init() but not
-                       // when they are inside a function.
-                       break;
-               }
-               return;
-       }
-
-       if(n->initorder == InitDone)
-               return;
-       if(n->initorder == InitPending) {
-               // Since mutually recursive sets of functions are allowed,
-               // we don't necessarily raise an error if n depends on a node
-               // which is already waiting for its dependencies to be visited.
-               //
-               // initlist contains a cycle of identifiers referring to each other.
-               // If this cycle contains a variable, then this variable refers to itself.
-               // Conversely, if there exists an initialization cycle involving
-               // a variable in the program, the tree walk will reach a cycle
-               // involving that variable.
-               if(n->class != PFUNC) {
-                       nv = n;
-                       goto foundinitloop;
-               }
-               for(l=initlist; l->n!=n; l=l->next) {
-                       if(l->n->class != PFUNC) {
-                               nv = l->n;
-                               goto foundinitloop;
-                       }
-               }
-               // The loop involves only functions, ok.
-               return;
-
-       foundinitloop:
-               // if there have already been errors printed,
-               // those errors probably confused us and
-               // there might not be a loop.  let the user
-               // fix those first.
-               flusherrors();
-               if(nerrors > 0)
-                       errorexit();
-
-               // There is a loop involving nv. We know about
-               // n and initlist = n1 <- ... <- nv <- ... <- n <- ...
-               print("%L: initialization loop:\n", nv->lineno);
-               // Build back pointers in initlist.
-               for(l=initlist; l; l=l->next)
-                       if(l->next != nil)
-                               l->next->end = l;
-               // Print nv -> ... -> n1 -> n.
-               for(l=initlist; l->n!=nv; l=l->next);
-               for(; l; l=l->end)
-                       print("\t%L %S refers to\n", l->n->lineno, l->n->sym);
-               // Print n -> ... -> nv.
-               for(l=initlist; l->n!=n; l=l->next);
-               for(; l->n != nv; l=l->end)
-                       print("\t%L %S refers to\n", l->n->lineno, l->n->sym);
-               print("\t%L %S\n", nv->lineno, nv->sym);
-               errorexit();
-       }
-
-       // reached a new unvisited node.
-       n->initorder = InitPending;
-       l = malloc(sizeof *l);
-       if(l == nil) {
-               flusherrors();
-               yyerror("out of memory");
-               errorexit();
-       }
-       l->next = initlist;
-       l->n = n;
-       l->end = nil;
-       initlist = l;
-
-       // make sure that everything n depends on is initialized.
-       // n->defn is an assignment to n
-       if(n->defn != N) {
-               switch(n->defn->op) {
-               default:
-                       goto bad;
-
-               case ODCLFUNC:
-                       init2list(n->defn->nbody, out);
-                       break;
-
-               case OAS:
-                       if(n->defn->left != n)
-                               goto bad;
-                       if(isblank(n->defn->left) && candiscard(n->defn->right)) {
-                               n->defn->op = OEMPTY;
-                               n->defn->left = N;
-                               n->defn->right = N;
-                               break;
-                       }
-
-                       init2(n->defn->right, out);
-                       if(debug['j'])
-                               print("%S\n", n->sym);
-                       if(isblank(n) || !staticinit(n, out)) {
-                               if(debug['%'])
-                                       dump("nonstatic", n->defn);
-                               *out = list(*out, n->defn);
-                       }
-                       break;
-
-               case OAS2FUNC:
-               case OAS2MAPR:
-               case OAS2DOTTYPE:
-               case OAS2RECV:
-                       if(n->defn->initorder != InitNotStarted)
-                               break;
-                       n->defn->initorder = InitDone;
-                       for(l=n->defn->rlist; l; l=l->next)
-                               init1(l->n, out);
-                       if(debug['%']) dump("nonstatic", n->defn);
-                       *out = list(*out, n->defn);
-                       break;
-               }
-       }
-       l = initlist;
-       initlist = l->next;
-       if(l->n != n)
-               fatal("bad initlist");
-       free(l);
-       n->initorder = InitDone;
-       return;
-
-bad:
-       dump("defn", n->defn);
-       fatal("init1: bad defn");
-}
-
-// recurse over n, doing init1 everywhere.
-static void
-init2(Node *n, NodeList **out)
-{
-       if(n == N || n->initorder == InitDone)
-               return;
-
-       if(n->op == ONAME && n->ninit)
-               fatal("name %S with ninit: %+N\n", n->sym, n);
-
-       init1(n, out);
-       init2(n->left, out);
-       init2(n->right, out);
-       init2(n->ntest, out);
-       init2list(n->ninit, out);
-       init2list(n->list, out);
-       init2list(n->rlist, out);
-       init2list(n->nbody, out);
-       init2list(n->nelse, out);
-       
-       if(n->op == OCLOSURE)
-               init2list(n->closure->nbody, out);
-       if(n->op == ODOTMETH || n->op == OCALLPART)
-               init2(n->type->nname, out);
-}
-
-static void
-init2list(NodeList *l, NodeList **out)
-{
-       for(; l; l=l->next)
-               init2(l->n, out);
-}
-
-static void
-initreorder(NodeList *l, NodeList **out)
-{
-       Node *n;
-
-       for(; l; l=l->next) {
-               n = l->n;
-               switch(n->op) {
-               case ODCLFUNC:
-               case ODCLCONST:
-               case ODCLTYPE:
-                       continue;
-               }
-               initreorder(n->ninit, out);
-               n->ninit = nil;
-               init1(n, out);
-       }
-}
-
-// initfix computes initialization order for a list l of top-level
-// declarations and outputs the corresponding list of statements
-// to include in the init() function body.
-NodeList*
-initfix(NodeList *l)
-{
-       NodeList *lout;
-       int lno;
-
-       lout = nil;
-       lno = lineno;
-       initreorder(l, &lout);
-       lineno = lno;
-       return lout;
-}
-
-/*
- * compilation of top-level (static) assignments
- * into DATA statements if at all possible.
- */
-
-static int staticassign(Node*, Node*, NodeList**);
-
-static int
-staticinit(Node *n, NodeList **out)
-{
-       Node *l, *r;
-
-       if(n->op != ONAME || n->class != PEXTERN || n->defn == N || n->defn->op != OAS)
-               fatal("staticinit");
-
-       lineno = n->lineno;
-       l = n->defn->left;
-       r = n->defn->right;
-       return staticassign(l, r, out);
-}
-
-// like staticassign but we are copying an already
-// initialized value r.
-static int
-staticcopy(Node *l, Node *r, NodeList **out)
-{
-       int i;
-       InitEntry *e;
-       InitPlan *p;
-       Node *a, *ll, *rr, *orig, n1;
-
-       if(r->op != ONAME || r->class != PEXTERN || r->sym->pkg != localpkg)
-               return 0;
-       if(r->defn == N)        // probably zeroed but perhaps supplied externally and of unknown value
-               return 0;
-       if(r->defn->op != OAS)
-               return 0;
-       orig = r;
-       r = r->defn->right;
-       
-       switch(r->op) {
-       case ONAME:
-               if(staticcopy(l, r, out))
-                       return 1;
-               *out = list(*out, nod(OAS, l, r));
-               return 1;
-       
-       case OLITERAL:
-               if(iszero(r))
-                       return 1;
-               gdata(l, r, l->type->width);
-               return 1;
-
-       case OADDR:
-               switch(r->left->op) {
-               case ONAME:
-                       gdata(l, r, l->type->width);
-                       return 1;
-               }
-               break;
-       
-       case OPTRLIT:
-               switch(r->left->op) {
-               default:
-                       //dump("not static addr", r);
-                       break;
-               case OARRAYLIT:
-               case OSTRUCTLIT:
-               case OMAPLIT:
-                       // copy pointer
-                       gdata(l, nod(OADDR, r->nname, N), l->type->width);
-                       return 1;
-               }
-               break;
-
-       case OARRAYLIT:
-               if(isslice(r->type)) {
-                       // copy slice
-                       a = r->nname;
-                       n1 = *l;
-                       n1.xoffset = l->xoffset + Array_array;
-                       gdata(&n1, nod(OADDR, a, N), widthptr);
-                       n1.xoffset = l->xoffset + Array_nel;
-                       gdata(&n1, r->right, widthint);
-                       n1.xoffset = l->xoffset + Array_cap;
-                       gdata(&n1, r->right, widthint);
-                       return 1;
-               }
-               // fall through
-       case OSTRUCTLIT:
-               p = r->initplan;
-               n1 = *l;
-               for(i=0; i<p->len; i++) {
-                       e = &p->e[i];
-                       n1.xoffset = l->xoffset + e->xoffset;
-                       n1.type = e->expr->type;
-                       if(e->expr->op == OLITERAL)
-                               gdata(&n1, e->expr, n1.type->width);
-                       else {
-                               ll = nod(OXXX, N, N);
-                               *ll = n1;
-                               ll->orig = ll; // completely separate copy
-                               if(!staticassign(ll, e->expr, out)) {
-                                       // Requires computation, but we're
-                                       // copying someone else's computation.
-                                       rr = nod(OXXX, N, N);
-                                       *rr = *orig;
-                                       rr->orig = rr; // completely separate copy
-                                       rr->type = ll->type;
-                                       rr->xoffset += e->xoffset;
-                                       *out = list(*out, nod(OAS, ll, rr));
-                               }
-                       }
-               }
-               return 1;
-       }
-       return 0;
-}
-
-static int
-staticassign(Node *l, Node *r, NodeList **out)
-{
-       Node *a, n1, nam;
-       Type *ta;
-       InitPlan *p;
-       InitEntry *e;
-       int i;
-       Strlit *sval;
-       
-       switch(r->op) {
-       default:
-               //dump("not static", r);
-               break;
-       
-       case ONAME:
-               if(r->class == PEXTERN && r->sym->pkg == localpkg)
-                       return staticcopy(l, r, out);
-               break;
-
-       case OLITERAL:
-               if(iszero(r))
-                       return 1;
-               gdata(l, r, l->type->width);
-               return 1;
-
-       case OADDR:
-               if(stataddr(&nam, r->left)) {
-                       n1 = *r;
-                       n1.left = &nam;
-                       gdata(l, &n1, l->type->width);
-                       return 1;
-               }
-       
-       case OPTRLIT:
-               switch(r->left->op) {
-               default:
-                       //dump("not static ptrlit", r);
-                       break;
-
-               case OARRAYLIT:
-               case OMAPLIT:
-               case OSTRUCTLIT:
-                       // Init pointer.
-                       a = staticname(r->left->type, 1);
-                       r->nname = a;
-                       gdata(l, nod(OADDR, a, N), l->type->width);
-                       // Init underlying literal.
-                       if(!staticassign(a, r->left, out))
-                               *out = list(*out, nod(OAS, a, r->left));
-                       return 1;
-               }
-               break;
-
-       case OSTRARRAYBYTE:
-               if(l->class == PEXTERN && r->left->op == OLITERAL) {
-                       sval = r->left->val.u.sval;
-                       slicebytes(l, sval->s, sval->len);
-                       return 1;
-               }
-               break;
-
-       case OARRAYLIT:
-               initplan(r);
-               if(isslice(r->type)) {
-                       // Init slice.
-                       ta = typ(TARRAY);
-                       ta->type = r->type->type;
-                       ta->bound = mpgetfix(r->right->val.u.xval);
-                       a = staticname(ta, 1);
-                       r->nname = a;
-                       n1 = *l;
-                       n1.xoffset = l->xoffset + Array_array;
-                       gdata(&n1, nod(OADDR, a, N), widthptr);
-                       n1.xoffset = l->xoffset + Array_nel;
-                       gdata(&n1, r->right, widthint);
-                       n1.xoffset = l->xoffset + Array_cap;
-                       gdata(&n1, r->right, widthint);
-                       // Fall through to init underlying array.
-                       l = a;
-               }
-               // fall through
-       case OSTRUCTLIT:
-               initplan(r);
-               p = r->initplan;
-               n1 = *l;
-               for(i=0; i<p->len; i++) {
-                       e = &p->e[i];
-                       n1.xoffset = l->xoffset + e->xoffset;
-                       n1.type = e->expr->type;
-                       if(e->expr->op == OLITERAL)
-                               gdata(&n1, e->expr, n1.type->width);
-                       else {
-                               a = nod(OXXX, N, N);
-                               *a = n1;
-                               a->orig = a; // completely separate copy
-                               if(!staticassign(a, e->expr, out))
-                                       *out = list(*out, nod(OAS, a, e->expr));
-                       }
-               }
-               return 1;
-
-       case OMAPLIT:
-               // TODO: Table-driven map insert.
-               break;
-       }
-       return 0;
-}
-
-/*
- * from here down is the walk analysis
- * of composite literals.
- * most of the work is to generate
- * data statements for the constant
- * part of the composite literal.
- */
-
-static void    structlit(int ctxt, int pass, Node *n, Node *var, NodeList **init);
-static void    arraylit(int ctxt, int pass, Node *n, Node *var, NodeList **init);
-static void    slicelit(int ctxt, Node *n, Node *var, NodeList **init);
-static void    maplit(int ctxt, Node *n, Node *var, NodeList **init);
-
-static Node*
-staticname(Type *t, int ctxt)
-{
-       Node *n;
-
-       snprint(namebuf, sizeof(namebuf), "statictmp_%.4d", statuniqgen);
-       statuniqgen++;
-       n = newname(lookup(namebuf));
-       if(!ctxt)
-               n->readonly = 1;
-       addvar(n, t, PEXTERN);
-       return n;
-}
-
-static int
-isliteral(Node *n)
-{
-       if(n->op == OLITERAL)
-               if(n->val.ctype != CTNIL)
-                       return 1;
-       return 0;
-}
-
-static int
-simplename(Node *n)
-{
-       if(n->op != ONAME)
-               goto no;
-       if(!n->addable)
-               goto no;
-       if(n->class & PHEAP)
-               goto no;
-       if(n->class == PPARAMREF)
-               goto no;
-       return 1;
-
-no:
-       return 0;
-}
-
-static void
-litas(Node *l, Node *r, NodeList **init)
-{
-       Node *a;
-
-       a = nod(OAS, l, r);
-       typecheck(&a, Etop);
-       walkexpr(&a, init);
-       *init = list(*init, a);
-}
-
-enum
-{
-       MODEDYNAM       = 1,
-       MODECONST       = 2,
-};
-
-static int
-getdyn(Node *n, int top)
-{
-       NodeList *nl;
-       Node *value;
-       int mode;
-
-       mode = 0;
-       switch(n->op) {
-       default:
-               if(isliteral(n))
-                       return MODECONST;
-               return MODEDYNAM;
-       case OARRAYLIT:
-               if(!top && n->type->bound < 0)
-                       return MODEDYNAM;
-       case OSTRUCTLIT:
-               break;
-       }
-
-       for(nl=n->list; nl; nl=nl->next) {
-               value = nl->n->right;
-               mode |= getdyn(value, 0);
-               if(mode == (MODEDYNAM|MODECONST))
-                       break;
-       }
-       return mode;
-}
-
-static void
-structlit(int ctxt, int pass, Node *n, Node *var, NodeList **init)
-{
-       Node *r, *a;
-       NodeList *nl;
-       Node *index, *value;
-
-       for(nl=n->list; nl; nl=nl->next) {
-               r = nl->n;
-               if(r->op != OKEY)
-                       fatal("structlit: rhs not OKEY: %N", r);
-               index = r->left;
-               value = r->right;
-
-               switch(value->op) {
-               case OARRAYLIT:
-                       if(value->type->bound < 0) {
-                               if(pass == 1 && ctxt != 0) {
-                                       a = nod(ODOT, var, newname(index->sym));
-                                       slicelit(ctxt, value, a, init);
-                               } else
-                               if(pass == 2 && ctxt == 0) {
-                                       a = nod(ODOT, var, newname(index->sym));
-                                       slicelit(ctxt, value, a, init);
-                               } else
-                               if(pass == 3)
-                                       break;
-                               continue;
-                       }
-                       a = nod(ODOT, var, newname(index->sym));
-                       arraylit(ctxt, pass, value, a, init);
-                       continue;
-
-               case OSTRUCTLIT:
-                       a = nod(ODOT, var, newname(index->sym));
-                       structlit(ctxt, pass, value, a, init);
-                       continue;
-               }
-
-               if(isliteral(value)) {
-                       if(pass == 2)
-                               continue;
-               } else
-                       if(pass == 1)
-                               continue;
-
-               // build list of var.field = expr
-               a = nod(ODOT, var, newname(index->sym));
-               a = nod(OAS, a, value);
-               typecheck(&a, Etop);
-               if(pass == 1) {
-                       walkexpr(&a, init);     // add any assignments in r to top
-                       if(a->op != OAS)
-                               fatal("structlit: not as");
-                       a->dodata = 2;
-               } else {
-                       orderstmtinplace(&a);
-                       walkstmt(&a);
-               }
-               *init = list(*init, a);
-       }
-}
-
-static void
-arraylit(int ctxt, int pass, Node *n, Node *var, NodeList **init)
-{
-       Node *r, *a;
-       NodeList *l;
-       Node *index, *value;
-
-       for(l=n->list; l; l=l->next) {
-               r = l->n;
-               if(r->op != OKEY)
-                       fatal("arraylit: rhs not OKEY: %N", r);
-               index = r->left;
-               value = r->right;
-
-               switch(value->op) {
-               case OARRAYLIT:
-                       if(value->type->bound < 0) {
-                               if(pass == 1 && ctxt != 0) {
-                                       a = nod(OINDEX, var, index);
-                                       slicelit(ctxt, value, a, init);
-                               } else
-                               if(pass == 2 && ctxt == 0) {
-                                       a = nod(OINDEX, var, index);
-                                       slicelit(ctxt, value, a, init);
-                               } else
-                               if(pass == 3)
-                                       break;
-                               continue;
-                       }
-                       a = nod(OINDEX, var, index);
-                       arraylit(ctxt, pass, value, a, init);
-                       continue;
-
-               case OSTRUCTLIT:
-                       a = nod(OINDEX, var, index);
-                       structlit(ctxt, pass, value, a, init);
-                       continue;
-               }
-
-               if(isliteral(index) && isliteral(value)) {
-                       if(pass == 2)
-                               continue;
-               } else
-                       if(pass == 1)
-                               continue;
-
-               // build list of var[index] = value
-               a = nod(OINDEX, var, index);
-               a = nod(OAS, a, value);
-               typecheck(&a, Etop);
-               if(pass == 1) {
-                       walkexpr(&a, init);
-                       if(a->op != OAS)
-                               fatal("arraylit: not as");
-                       a->dodata = 2;
-               } else {
-                       orderstmtinplace(&a);
-                       walkstmt(&a);
-               }
-               *init = list(*init, a);
-       }
-}
-
-static void
-slicelit(int ctxt, Node *n, Node *var, NodeList **init)
-{
-       Node *r, *a;
-       NodeList *l;
-       Type *t;
-       Node *vstat, *vauto;
-       Node *index, *value;
-       int mode;
-
-       // make an array type
-       t = shallow(n->type);
-       t->bound = mpgetfix(n->right->val.u.xval);
-       t->width = 0;
-       t->sym = nil;
-       t->haspointers = 0;
-       dowidth(t);
-
-       if(ctxt != 0) {
-               // put everything into static array
-               vstat = staticname(t, ctxt);
-               arraylit(ctxt, 1, n, vstat, init);
-               arraylit(ctxt, 2, n, vstat, init);
-
-               // copy static to slice
-               a = nod(OSLICE, vstat, nod(OKEY, N, N));
-               a = nod(OAS, var, a);
-               typecheck(&a, Etop);
-               a->dodata = 2;
-               *init = list(*init, a);
-               return;
-       }
-
-       // recipe for var = []t{...}
-       // 1. make a static array
-       //      var vstat [...]t
-       // 2. assign (data statements) the constant part
-       //      vstat = constpart{}
-       // 3. make an auto pointer to array and allocate heap to it
-       //      var vauto *[...]t = new([...]t)
-       // 4. copy the static array to the auto array
-       //      *vauto = vstat
-       // 5. assign slice of allocated heap to var
-       //      var = [0:]*auto
-       // 6. for each dynamic part assign to the slice
-       //      var[i] = dynamic part
-       //
-       // an optimization is done if there is no constant part
-       //      3. var vauto *[...]t = new([...]t)
-       //      5. var = [0:]*auto
-       //      6. var[i] = dynamic part
-
-       // if the literal contains constants,
-       // make static initialized array (1),(2)
-       vstat = N;
-       mode = getdyn(n, 1);
-       if(mode & MODECONST) {
-               vstat = staticname(t, ctxt);
-               arraylit(ctxt, 1, n, vstat, init);
-       }
-
-       // make new auto *array (3 declare)
-       vauto = temp(ptrto(t));
-
-       // set auto to point at new temp or heap (3 assign)
-       if(n->alloc != N) {
-               // temp allocated during order.c for dddarg
-               n->alloc->type = t;
-               if(vstat == N) {
-                       a = nod(OAS, n->alloc, N);
-                       typecheck(&a, Etop);
-                       *init = list(*init, a);  // zero new temp
-               }
-               a = nod(OADDR, n->alloc, N);
-       } else if(n->esc == EscNone) {
-               a = temp(t);
-               if(vstat == N) {
-                       a = nod(OAS, temp(t), N);
-                       typecheck(&a, Etop);
-                       *init = list(*init, a);  // zero new temp
-                       a = a->left;
-               }
-               a = nod(OADDR, a, N);
-       } else {
-               a = nod(ONEW, N, N);
-               a->list = list1(typenod(t));
-       }
-       a = nod(OAS, vauto, a);
-       typecheck(&a, Etop);
-       walkexpr(&a, init);
-       *init = list(*init, a);
-
-       if(vstat != N) {
-               // copy static to heap (4)
-               a = nod(OIND, vauto, N);
-               a = nod(OAS, a, vstat);
-               typecheck(&a, Etop);
-               walkexpr(&a, init);
-               *init = list(*init, a);
-       }
-
-       // make slice out of heap (5)
-       a = nod(OAS, var, nod(OSLICE, vauto, nod(OKEY, N, N)));
-       typecheck(&a, Etop);
-       orderstmtinplace(&a);
-       walkstmt(&a);
-       *init = list(*init, a);
-
-       // put dynamics into slice (6)
-       for(l=n->list; l; l=l->next) {
-               r = l->n;
-               if(r->op != OKEY)
-                       fatal("slicelit: rhs not OKEY: %N", r);
-               index = r->left;
-               value = r->right;
-               a = nod(OINDEX, var, index);
-               a->bounded = 1;
-               // TODO need to check bounds?
-
-               switch(value->op) {
-               case OARRAYLIT:
-                       if(value->type->bound < 0)
-                               break;
-                       arraylit(ctxt, 2, value, a, init);
-                       continue;
-
-               case OSTRUCTLIT:
-                       structlit(ctxt, 2, value, a, init);
-                       continue;
-               }
-
-               if(isliteral(index) && isliteral(value))
-                       continue;
-
-               // build list of var[c] = expr
-               a = nod(OAS, a, value);
-               typecheck(&a, Etop);
-               orderstmtinplace(&a);
-               walkstmt(&a);
-               *init = list(*init, a);
-       }
-}
-
-static void
-maplit(int ctxt, Node *n, Node *var, NodeList **init)
-{
-       Node *r, *a;
-       NodeList *l;
-       int nerr;
-       int64 b;
-       Type *t, *tk, *tv, *t1;
-       Node *vstat, *index, *value, *key, *val;
-       Sym *syma, *symb;
-
-USED(ctxt);
-ctxt = 0;
-
-       // make the map var
-       nerr = nerrors;
-
-       a = nod(OMAKE, N, N);
-       a->list = list1(typenod(n->type));
-       litas(var, a, init);
-
-       // count the initializers
-       b = 0;
-       for(l=n->list; l; l=l->next) {
-               r = l->n;
-
-               if(r->op != OKEY)
-                       fatal("maplit: rhs not OKEY: %N", r);
-               index = r->left;
-               value = r->right;
-
-               if(isliteral(index) && isliteral(value))
-                       b++;
-       }
-
-       if(b != 0) {
-               // build type [count]struct { a Tindex, b Tvalue }
-               t = n->type;
-               tk = t->down;
-               tv = t->type;
-
-               symb = lookup("b");
-               t = typ(TFIELD);
-               t->type = tv;
-               t->sym = symb;
-
-               syma = lookup("a");
-               t1 = t;
-               t = typ(TFIELD);
-               t->type = tk;
-               t->sym = syma;
-               t->down = t1;
-
-               t1 = t;
-               t = typ(TSTRUCT);
-               t->type = t1;
-
-               t1 = t;
-               t = typ(TARRAY);
-               t->bound = b;
-               t->type = t1;
-
-               dowidth(t);
-
-               // make and initialize static array
-               vstat = staticname(t, ctxt);
-               b = 0;
-               for(l=n->list; l; l=l->next) {
-                       r = l->n;
-
-                       if(r->op != OKEY)
-                               fatal("maplit: rhs not OKEY: %N", r);
-                       index = r->left;
-                       value = r->right;
-
-                       if(isliteral(index) && isliteral(value)) {
-                               // build vstat[b].a = key;
-                               a = nodintconst(b);
-                               a = nod(OINDEX, vstat, a);
-                               a = nod(ODOT, a, newname(syma));
-                               a = nod(OAS, a, index);
-                               typecheck(&a, Etop);
-                               walkexpr(&a, init);
-                               a->dodata = 2;
-                               *init = list(*init, a);
-
-                               // build vstat[b].b = value;
-                               a = nodintconst(b);
-                               a = nod(OINDEX, vstat, a);
-                               a = nod(ODOT, a, newname(symb));
-                               a = nod(OAS, a, value);
-                               typecheck(&a, Etop);
-                               walkexpr(&a, init);
-                               a->dodata = 2;
-                               *init = list(*init, a);
-
-                               b++;
-                       }
-               }
-
-               // loop adding structure elements to map
-               // for i = 0; i < len(vstat); i++ {
-               //      map[vstat[i].a] = vstat[i].b
-               // }
-               index = temp(types[TINT]);
-
-               a = nod(OINDEX, vstat, index);
-               a->bounded = 1;
-               a = nod(ODOT, a, newname(symb));
-
-               r = nod(OINDEX, vstat, index);
-               r->bounded = 1;
-               r = nod(ODOT, r, newname(syma));
-               r = nod(OINDEX, var, r);
-
-               r = nod(OAS, r, a);
-
-               a = nod(OFOR, N, N);
-               a->nbody = list1(r);
-
-               a->ninit = list1(nod(OAS, index, nodintconst(0)));
-               a->ntest = nod(OLT, index, nodintconst(t->bound));
-               a->nincr = nod(OAS, index, nod(OADD, index, nodintconst(1)));
-
-               typecheck(&a, Etop);
-               walkstmt(&a);
-               *init = list(*init, a);
-       }
-
-       // put in dynamic entries one-at-a-time
-       key = nil;
-       val = nil;
-       for(l=n->list; l; l=l->next) {
-               r = l->n;
-
-               if(r->op != OKEY)
-                       fatal("maplit: rhs not OKEY: %N", r);
-               index = r->left;
-               value = r->right;
-
-               if(isliteral(index) && isliteral(value))
-                       continue;
-                       
-               // build list of var[c] = expr.
-               // use temporary so that mapassign1 can have addressable key, val.
-               if(key == nil) {
-                       key = temp(var->type->down);
-                       val = temp(var->type->type);
-               }
-               a = nod(OAS, key, r->left);
-               typecheck(&a, Etop);
-               walkstmt(&a);
-               *init = list(*init, a);
-               a = nod(OAS, val, r->right);
-               typecheck(&a, Etop);
-               walkstmt(&a);
-               *init = list(*init, a);
-
-               a = nod(OAS, nod(OINDEX, var, key), val);
-               typecheck(&a, Etop);
-               walkstmt(&a);
-               *init = list(*init, a);
-
-               if(nerr != nerrors)
-                       break;
-       }
-       
-       if(key != nil) {
-               a = nod(OVARKILL, key, N);
-               typecheck(&a, Etop);
-               *init = list(*init, a);
-               a = nod(OVARKILL, val, N);
-               typecheck(&a, Etop);
-               *init = list(*init, a);
-       }
-}
-
-void
-anylit(int ctxt, Node *n, Node *var, NodeList **init)
-{
-       Type *t;
-       Node *a, *vstat, *r;
-
-       t = n->type;
-       switch(n->op) {
-       default:
-               fatal("anylit: not lit");
-
-       case OPTRLIT:
-               if(!isptr[t->etype])
-                       fatal("anylit: not ptr");
-
-               if(n->right != N) {
-                       r = nod(OADDR, n->right, N);
-                       typecheck(&r, Erv);
-               } else {
-                       r = nod(ONEW, N, N);
-                       r->typecheck = 1;
-                       r->type = t;
-                       r->esc = n->esc;
-               }
-               walkexpr(&r, init);
-               a = nod(OAS, var, r);
-
-               typecheck(&a, Etop);
-               *init = list(*init, a);
-
-               var = nod(OIND, var, N);
-               typecheck(&var, Erv | Easgn);
-               anylit(ctxt, n->left, var, init);
-               break;
-
-       case OSTRUCTLIT:
-               if(t->etype != TSTRUCT)
-                       fatal("anylit: not struct");
-
-               if(simplename(var) && count(n->list) > 4) {
-
-                       if(ctxt == 0) {
-                               // lay out static data
-                               vstat = staticname(t, ctxt);
-                               structlit(ctxt, 1, n, vstat, init);
-
-                               // copy static to var
-                               a = nod(OAS, var, vstat);
-                               typecheck(&a, Etop);
-                               walkexpr(&a, init);
-                               *init = list(*init, a);
-
-                               // add expressions to automatic
-                               structlit(ctxt, 2, n, var, init);
-                               break;
-                       }
-                       structlit(ctxt, 1, n, var, init);
-                       structlit(ctxt, 2, n, var, init);
-                       break;
-               }
-
-               // initialize of not completely specified
-               if(simplename(var) || count(n->list) < structcount(t)) {
-                       a = nod(OAS, var, N);
-                       typecheck(&a, Etop);
-                       walkexpr(&a, init);
-                       *init = list(*init, a);
-               }
-               structlit(ctxt, 3, n, var, init);
-               break;
-
-       case OARRAYLIT:
-               if(t->etype != TARRAY)
-                       fatal("anylit: not array");
-               if(t->bound < 0) {
-                       slicelit(ctxt, n, var, init);
-                       break;
-               }
-
-               if(simplename(var) && count(n->list) > 4) {
-
-                       if(ctxt == 0) {
-                               // lay out static data
-                               vstat = staticname(t, ctxt);
-                               arraylit(1, 1, n, vstat, init);
-
-                               // copy static to automatic
-                               a = nod(OAS, var, vstat);
-                               typecheck(&a, Etop);
-                               walkexpr(&a, init);
-                               *init = list(*init, a);
-
-                               // add expressions to automatic
-                               arraylit(ctxt, 2, n, var, init);
-                               break;
-                       }
-                       arraylit(ctxt, 1, n, var, init);
-                       arraylit(ctxt, 2, n, var, init);
-                       break;
-               }
-
-               // initialize of not completely specified
-               if(simplename(var) || count(n->list) < t->bound) {
-                       a = nod(OAS, var, N);
-                       typecheck(&a, Etop);
-                       walkexpr(&a, init);
-                       *init = list(*init, a);
-               }
-               arraylit(ctxt, 3, n, var, init);
-               break;
-
-       case OMAPLIT:
-               if(t->etype != TMAP)
-                       fatal("anylit: not map");
-               maplit(ctxt, n, var, init);
-               break;
-       }
-}
-
-int
-oaslit(Node *n, NodeList **init)
-{
-       int ctxt;
-
-       if(n->left == N || n->right == N)
-               goto no;
-       if(n->left->type == T || n->right->type == T)
-               goto no;
-       if(!simplename(n->left))
-               goto no;
-       if(!eqtype(n->left->type, n->right->type))
-               goto no;
-
-       // context is init() function.
-       // implies generated data executed
-       // exactly once and not subject to races.
-       ctxt = 0;
-//     if(n->dodata == 1)
-//             ctxt = 1;
-
-       switch(n->right->op) {
-       default:
-               goto no;
-
-       case OSTRUCTLIT:
-       case OARRAYLIT:
-       case OMAPLIT:
-               if(vmatch1(n->left, n->right))
-                       goto no;
-               anylit(ctxt, n->right, n->left, init);
-               break;
-       }
-       n->op = OEMPTY;
-       return 1;
-
-no:
-       // not a special composit literal assignment
-       return 0;
-}
-
-static int
-getlit(Node *lit)
-{
-       if(smallintconst(lit))
-               return mpgetfix(lit->val.u.xval);
-       return -1;
-}
-
-int
-stataddr(Node *nam, Node *n)
-{
-       int l;
-
-       if(n == N)
-               goto no;
-
-       switch(n->op) {
-
-       case ONAME:
-               *nam = *n;
-               return n->addable;
-
-       case ODOT:
-               if(!stataddr(nam, n->left))
-                       break;
-               nam->xoffset += n->xoffset;
-               nam->type = n->type;
-               return 1;
-
-       case OINDEX:
-               if(n->left->type->bound < 0)
-                       break;
-               if(!stataddr(nam, n->left))
-                       break;
-               l = getlit(n->right);
-               if(l < 0)
-                       break;
-               // Check for overflow.
-               if(n->type->width != 0 && thearch.MAXWIDTH/n->type->width <= l)
-                       break;
-               nam->xoffset += l*n->type->width;
-               nam->type = n->type;
-               return 1;
-       }
-
-no:
-       return 0;
-}
-
-int
-gen_as_init(Node *n)
-{
-       Node *nr, *nl;
-       Node nam, nod1;
-
-       if(n->dodata == 0)
-               goto no;
-
-       nr = n->right;
-       nl = n->left;
-       if(nr == N) {
-               if(!stataddr(&nam, nl))
-                       goto no;
-               if(nam.class != PEXTERN)
-                       goto no;
-               goto yes;
-       }
-
-       if(nr->type == T || !eqtype(nl->type, nr->type))
-               goto no;
-
-       if(!stataddr(&nam, nl))
-               goto no;
-
-       if(nam.class != PEXTERN)
-               goto no;
-
-       switch(nr->op) {
-       default:
-               goto no;
-
-       case OCONVNOP:
-               nr = nr->left;
-               if(nr == N || nr->op != OSLICEARR)
-                       goto no;
-               // fall through
-       
-       case OSLICEARR:
-               if(nr->right->op == OKEY && nr->right->left == N && nr->right->right == N) {
-                       nr = nr->left;
-                       goto slice;
-               }
-               goto no;
-
-       case OLITERAL:
-               break;
-       }
-
-       switch(nr->type->etype) {
-       default:
-               goto no;
-
-       case TBOOL:
-       case TINT8:
-       case TUINT8:
-       case TINT16:
-       case TUINT16:
-       case TINT32:
-       case TUINT32:
-       case TINT64:
-       case TUINT64:
-       case TINT:
-       case TUINT:
-       case TUINTPTR:
-       case TPTR32:
-       case TPTR64:
-       case TFLOAT32:
-       case TFLOAT64:
-               gdata(&nam, nr, nr->type->width);
-               break;
-
-       case TCOMPLEX64:
-       case TCOMPLEX128:
-               gdatacomplex(&nam, nr->val.u.cval);
-               break;
-
-       case TSTRING:
-               gdatastring(&nam, nr->val.u.sval);
-               break;
-       }
-
-yes:
-       return 1;
-
-slice:
-       gused(N); // in case the data is the dest of a goto
-       nl = nr;
-       if(nr == N || nr->op != OADDR)
-               goto no;
-       nr = nr->left;
-       if(nr == N || nr->op != ONAME)
-               goto no;
-
-       // nr is the array being converted to a slice
-       if(nr->type == T || nr->type->etype != TARRAY || nr->type->bound < 0)
-               goto no;
-
-       nam.xoffset += Array_array;
-       gdata(&nam, nl, types[tptr]->width);
-
-       nam.xoffset += Array_nel-Array_array;
-       nodconst(&nod1, types[TINT], nr->type->bound);
-       gdata(&nam, &nod1, widthint);
-
-       nam.xoffset += Array_cap-Array_nel;
-       gdata(&nam, &nod1, widthint);
-
-       goto yes;
-
-no:
-       if(n->dodata == 2) {
-               dump("\ngen_as_init", n);
-               fatal("gen_as_init couldnt make data statement");
-       }
-       return 0;
-}
-
-static int isvaluelit(Node*);
-static InitEntry* entry(InitPlan*);
-static void addvalue(InitPlan*, vlong, Node*, Node*);
-
-static void
-initplan(Node *n)
-{
-       InitPlan *p;
-       Node *a;
-       NodeList *l;
-
-       if(n->initplan != nil)
-               return;
-       p = mal(sizeof *p);
-       n->initplan = p;
-       switch(n->op) {
-       default:
-               fatal("initplan");
-       case OARRAYLIT:
-               for(l=n->list; l; l=l->next) {
-                       a = l->n;
-                       if(a->op != OKEY || !smallintconst(a->left))
-                               fatal("initplan arraylit");
-                       addvalue(p, n->type->type->width*mpgetfix(a->left->val.u.xval), N, a->right);
-               }
-               break;
-       case OSTRUCTLIT:
-               for(l=n->list; l; l=l->next) {
-                       a = l->n;
-                       if(a->op != OKEY || a->left->type == T)
-                               fatal("initplan structlit");
-                       addvalue(p, a->left->type->width, N, a->right);
-               }
-               break;
-       case OMAPLIT:
-               for(l=n->list; l; l=l->next) {
-                       a = l->n;
-                       if(a->op != OKEY)
-                               fatal("initplan maplit");
-                       addvalue(p, -1, a->left, a->right);
-               }
-               break;
-       }
-}
-
-static void
-addvalue(InitPlan *p, vlong xoffset, Node *key, Node *n)
-{
-       int i;
-       InitPlan *q;
-       InitEntry *e;
-
-       USED(key);
-
-       // special case: zero can be dropped entirely
-       if(iszero(n)) {
-               p->zero += n->type->width;
-               return;
-       }
-       
-       // special case: inline struct and array (not slice) literals
-       if(isvaluelit(n)) {
-               initplan(n);
-               q = n->initplan;
-               for(i=0; i<q->len; i++) {
-                       e = entry(p);
-                       *e = q->e[i];
-                       e->xoffset += xoffset;
-               }
-               return;
-       }
-       
-       // add to plan
-       if(n->op == OLITERAL)
-               p->lit += n->type->width;
-       else
-               p->expr += n->type->width;
-
-       e = entry(p);
-       e->xoffset = xoffset;
-       e->expr = n;
-}
-
-int
-iszero(Node *n)
-{
-       NodeList *l;
-
-       switch(n->op) {
-       case OLITERAL:
-               switch(n->val.ctype) {
-               default:
-                       dump("unexpected literal", n);
-                       fatal("iszero");
-       
-               case CTNIL:
-                       return 1;
-               
-               case CTSTR:
-                       return n->val.u.sval == nil || n->val.u.sval->len == 0;
-       
-               case CTBOOL:
-                       return n->val.u.bval == 0;
-                       
-               case CTINT:
-               case CTRUNE:
-                       return mpcmpfixc(n->val.u.xval, 0) == 0;
-       
-               case CTFLT:
-                       return mpcmpfltc(n->val.u.fval, 0) == 0;
-       
-               case CTCPLX:
-                       return mpcmpfltc(&n->val.u.cval->real, 0) == 0 && mpcmpfltc(&n->val.u.cval->imag, 0) == 0;
-               }
-               break;
-       case OARRAYLIT:
-               if(isslice(n->type))
-                       break;
-               // fall through
-       case OSTRUCTLIT:
-               for(l=n->list; l; l=l->next)
-                       if(!iszero(l->n->right))
-                               return 0;
-               return 1;
-       }
-       return 0;
-}
-
-static int
-isvaluelit(Node *n)
-{
-       return (n->op == OARRAYLIT && isfixedarray(n->type)) || n->op == OSTRUCTLIT;
-}
-
-static InitEntry*
-entry(InitPlan *p)
-{
-       if(p->len >= p->cap) {
-               if(p->cap == 0)
-                       p->cap = 4;
-               else
-                       p->cap *= 2;
-               p->e = realloc(p->e, p->cap*sizeof p->e[0]);
-               if(p->e == nil)
-                       fatal("out of memory");
-       }
-       return &p->e[p->len++];
-}
diff --git a/src/cmd/gc/subr.c b/src/cmd/gc/subr.c
deleted file mode 100644 (file)
index f739a72..0000000
+++ /dev/null
@@ -1,3856 +0,0 @@
-// Copyright 2009 The Go Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style
-// license that can be found in the LICENSE file.
-
-#include       <u.h>
-#include       <libc.h>
-#include       "go.h"
-#include       "md5.h"
-#include       "y.tab.h"
-#include       "yerr.h"
-
-typedef struct Error Error;
-struct Error
-{
-       int lineno;
-       int seq;
-       char *msg;
-};
-static Error *err;
-static int nerr;
-static int merr;
-
-void
-errorexit(void)
-{
-       flusherrors();
-       if(outfile)
-               remove(outfile);
-       exits("error");
-}
-
-extern int yychar;
-int
-parserline(void)
-{
-       if(yychar != 0 && yychar != -2) // parser has one symbol lookahead
-               return prevlineno;
-       return lineno;
-}
-
-void
-adderrorname(Node *n)
-{
-       char *old;
-       
-       if(n->op != ODOT)
-               return;
-       old = smprint("%L: undefined: %N\n", n->lineno, n->left);
-       if(nerr > 0 && err[nerr-1].lineno == n->lineno && strcmp(err[nerr-1].msg, old) == 0)
-               err[nerr-1].msg = smprint("%L: undefined: %N in %N\n", n->lineno, n->left, n);
-       free(old);
-}
-
-static void
-adderr(int line, char *fmt, va_list arg)
-{
-       Fmt f;
-       Error *p;
-
-       fmtstrinit(&f);
-       fmtprint(&f, "%L: ", line);
-       fmtvprint(&f, fmt, arg);
-       fmtprint(&f, "\n");
-
-       if(nerr >= merr) {
-               if(merr == 0)
-                       merr = 16;
-               else
-                       merr *= 2;
-               p = realloc(err, merr*sizeof err[0]);
-               if(p == nil) {
-                       merr = nerr;
-                       flusherrors();
-                       print("out of memory\n");
-                       errorexit();
-               }
-               err = p;
-       }
-       err[nerr].seq = nerr;
-       err[nerr].lineno = line;
-       err[nerr].msg = fmtstrflush(&f);
-       nerr++;
-}
-
-static int
-errcmp(const void *va, const void *vb)
-{
-       Error *a, *b;
-
-       a = (Error*)va;
-       b = (Error*)vb;
-       if(a->lineno != b->lineno)
-               return a->lineno - b->lineno;
-       if(a->seq != b->seq)
-               return a->seq - b->seq;
-       return strcmp(a->msg, b->msg);
-}
-
-void
-flusherrors(void)
-{
-       int i;
-
-       Bflush(&bstdout);
-       if(nerr == 0)
-               return;
-       qsort(err, nerr, sizeof err[0], errcmp);
-       for(i=0; i<nerr; i++)
-               if(i==0 || strcmp(err[i].msg, err[i-1].msg) != 0)
-                       print("%s", err[i].msg);
-       nerr = 0;
-}
-
-static void
-hcrash(void)
-{
-       if(debug['h']) {
-               flusherrors();
-               if(outfile)
-                       remove(outfile);
-               *(volatile int*)0 = 0;
-       }
-}
-
-void
-yyerrorl(int line, char *fmt, ...)
-{
-       va_list arg;
-
-       va_start(arg, fmt);
-       adderr(line, fmt, arg);
-       va_end(arg);
-
-       hcrash();
-       nerrors++;
-       if(nsavederrors+nerrors >= 10 && !debug['e']) {
-               flusherrors();
-               print("%L: too many errors\n", line);
-               errorexit();
-       }
-}
-
-extern int yystate, yychar;
-
-void
-yyerror(char *fmt, ...)
-{
-       int i;
-       static int lastsyntax;
-       va_list arg;
-       char buf[512], *p;
-
-       if(strncmp(fmt, "syntax error", 12) == 0) {
-               nsyntaxerrors++;
-               
-               if(debug['x'])  
-                       print("yyerror: yystate=%d yychar=%d\n", yystate, yychar);
-
-               // An unexpected EOF caused a syntax error. Use the previous
-               // line number since getc generated a fake newline character.
-               if(curio.eofnl)
-                       lexlineno = prevlineno;
-
-               // only one syntax error per line
-               if(lastsyntax == lexlineno)
-                       return;
-               lastsyntax = lexlineno;
-                       
-               if(strstr(fmt, "{ or {") || strstr(fmt, " or ?") || strstr(fmt, " or @")) {
-                       // The grammar has { and LBRACE but both show up as {.
-                       // Rewrite syntax error referring to "{ or {" to say just "{".
-                       strecpy(buf, buf+sizeof buf, fmt);
-                       p = strstr(buf, "{ or {");
-                       if(p)
-                               memmove(p+1, p+6, strlen(p+6)+1);
-                       
-                       // The grammar has ? and @ but only for reading imports.
-                       // Silence them in ordinary errors.
-                       p = strstr(buf, " or ?");
-                       if(p)
-                               memmove(p, p+5, strlen(p+5)+1);
-                       p = strstr(buf, " or @");
-                       if(p)
-                               memmove(p, p+5, strlen(p+5)+1);
-                       fmt = buf;
-               }
-               
-               // look for parse state-specific errors in list (see go.errors).
-               for(i=0; i<nelem(yymsg); i++) {
-                       if(yymsg[i].yystate == yystate && yymsg[i].yychar == yychar) {
-                               yyerrorl(lexlineno, "syntax error: %s", yymsg[i].msg);
-                               return;
-                       }
-               }
-               
-               // plain "syntax error" gets "near foo" added
-               if(strcmp(fmt, "syntax error") == 0) {
-                       yyerrorl(lexlineno, "syntax error near %s", lexbuf);
-                       return;
-               }
-               
-               // if bison says "syntax error, more info"; print "syntax error: more info".
-               if(fmt[12] == ',') {
-                       yyerrorl(lexlineno, "syntax error:%s", fmt+13);
-                       return;
-               }
-
-               yyerrorl(lexlineno, "%s", fmt);
-               return;
-       }
-
-       va_start(arg, fmt);
-       adderr(parserline(), fmt, arg);
-       va_end(arg);
-
-       hcrash();
-       nerrors++;
-       if(nsavederrors+nerrors >= 10 && !debug['e']) {
-               flusherrors();
-               print("%L: too many errors\n", parserline());
-               errorexit();
-       }
-}
-
-void
-warn(char *fmt, ...)
-{
-       va_list arg;
-
-       va_start(arg, fmt);
-       adderr(parserline(), fmt, arg);
-       va_end(arg);
-
-       hcrash();
-}
-
-void
-warnl(int line, char *fmt, ...)
-{
-       va_list arg;
-
-       va_start(arg, fmt);
-       adderr(line, fmt, arg);
-       va_end(arg);
-       if(debug['m'])
-               flusherrors();
-}
-
-void
-fatal(char *fmt, ...)
-{
-       va_list arg;
-
-       flusherrors();
-
-       print("%L: internal compiler error: ", lineno);
-       va_start(arg, fmt);
-       vfprint(1, fmt, arg);
-       va_end(arg);
-       print("\n");
-       
-       // If this is a released compiler version, ask for a bug report.
-       if(strncmp(getgoversion(), "release", 7) == 0) {
-               print("\n");
-               print("Please file a bug report including a short program that triggers the error.\n");
-               print("https://golang.org/issue/new\n");
-       }
-       hcrash();
-       errorexit();
-}
-
-void
-linehist(char *file, int32 off, int relative)
-{
-       if(debug['i']) {
-               if(file != nil) {
-                       if(off < 0)
-                               print("pragma %s", file);
-                       else
-                       if(off > 0)
-                               print("line %s", file);
-                       else
-                               print("import %s", file);
-               } else
-                       print("end of import");
-               print(" at line %L\n", lexlineno);
-       }
-       
-       if(off < 0 && file[0] != '/' && !relative)
-               file = smprint("%s/%s", ctxt->pathname, file);
-       linklinehist(ctxt, lexlineno, file, off);
-}
-
-int32
-setlineno(Node *n)
-{
-       int32 lno;
-
-       lno = lineno;
-       if(n != N)
-       switch(n->op) {
-       case ONAME:
-       case OTYPE:
-       case OPACK:
-       case OLITERAL:
-               break;
-       default:
-               lineno = n->lineno;
-               if(lineno == 0) {
-                       if(debug['K'])
-                               warn("setlineno: line 0");
-                       lineno = lno;
-               }
-       }
-       return lno;
-}
-
-uint32
-stringhash(char *p)
-{
-       uint32 h;
-       int c;
-
-       h = 0;
-       for(;;) {
-               c = *p++;
-               if(c == 0)
-                       break;
-               h = h*PRIME1 + c;
-       }
-
-       if((int32)h < 0) {
-               h = -h;
-               if((int32)h < 0)
-                       h = 0;
-       }
-       return h;
-}
-
-Sym*
-lookup(char *name)
-{
-       return pkglookup(name, localpkg);
-}
-
-Sym*
-pkglookup(char *name, Pkg *pkg)
-{
-       Sym *s;
-       uint32 h;
-       int c;
-
-       h = stringhash(name) % NHASH;
-       c = name[0];
-       for(s = hash[h]; s != S; s = s->link) {
-               if(s->name[0] != c || s->pkg != pkg)
-                       continue;
-               if(strcmp(s->name, name) == 0)
-                       return s;
-       }
-
-       s = mal(sizeof(*s));
-       s->name = mal(strlen(name)+1);
-       strcpy(s->name, name);
-
-       s->pkg = pkg;
-
-       s->link = hash[h];
-       hash[h] = s;
-       s->lexical = LNAME;
-
-       return s;
-}
-
-Sym*
-restrictlookup(char *name, Pkg *pkg)
-{
-       if(!exportname(name) && pkg != localpkg)
-               yyerror("cannot refer to unexported name %s.%s", pkg->name, name);
-       return pkglookup(name, pkg);
-}
-
-
-// find all the exported symbols in package opkg
-// and make them available in the current package
-void
-importdot(Pkg *opkg, Node *pack)
-{
-       Sym *s, *s1;
-       uint32 h;
-       int n;
-       char *pkgerror;
-
-       n = 0;
-       for(h=0; h<NHASH; h++) {
-               for(s = hash[h]; s != S; s = s->link) {
-                       if(s->pkg != opkg)
-                               continue;
-                       if(s->def == N)
-                               continue;
-                       if(!exportname(s->name) || utfrune(s->name, 0xb7))      // 0xb7 = center dot
-                               continue;
-                       s1 = lookup(s->name);
-                       if(s1->def != N) {
-                               pkgerror = smprint("during import \"%Z\"", opkg->path);
-                               redeclare(s1, pkgerror);
-                               continue;
-                       }
-                       s1->def = s->def;
-                       s1->block = s->block;
-                       s1->def->pack = pack;
-                       s1->origpkg = opkg;
-                       n++;
-               }
-       }
-       if(n == 0) {
-               // can't possibly be used - there were no symbols
-               yyerrorl(pack->lineno, "imported and not used: \"%Z\"", opkg->path);
-       }
-}
-
-static void
-gethunk(void)
-{
-       char *h;
-       int32 nh;
-
-       nh = NHUNK;
-       if(thunk >= 10L*NHUNK)
-               nh = 10L*NHUNK;
-       h = (char*)malloc(nh);
-       if(h == nil) {
-               flusherrors();
-               yyerror("out of memory");
-               errorexit();
-       }
-       hunk = h;
-       nhunk = nh;
-       thunk += nh;
-}
-
-void*
-mal(int32 n)
-{
-       void *p;
-
-       if(n >= NHUNK) {
-               p = malloc(n);
-               if(p == nil) {
-                       flusherrors();
-                       yyerror("out of memory");
-                       errorexit();
-               }
-               memset(p, 0, n);
-               return p;
-       }
-
-       while((uintptr)hunk & MAXALIGN) {
-               hunk++;
-               nhunk--;
-       }
-       if(nhunk < n)
-               gethunk();
-
-       p = hunk;
-       nhunk -= n;
-       hunk += n;
-       memset(p, 0, n);
-       return p;
-}
-
-void*
-remal(void *p, int32 on, int32 n)
-{
-       void *q;
-
-       q = (uchar*)p + on;
-       if(q != hunk || nhunk < n) {
-               if(on+n >= NHUNK) {
-                       q = mal(on+n);
-                       memmove(q, p, on);
-                       return q;
-               }
-               if(nhunk < on+n)
-                       gethunk();
-               memmove(hunk, p, on);
-               p = hunk;
-               hunk += on;
-               nhunk -= on;
-       }
-       hunk += n;
-       nhunk -= n;
-       return p;
-}
-
-Node*
-nod(int op, Node *nleft, Node *nright)
-{
-       Node *n;
-
-       n = mal(sizeof(*n));
-       n->op = op;
-       n->left = nleft;
-       n->right = nright;
-       n->lineno = parserline();
-       n->xoffset = BADWIDTH;
-       n->orig = n;
-       n->curfn = curfn;
-       return n;
-}
-
-void
-saveorignode(Node *n)
-{
-       Node *norig;
-
-       if(n->orig != N)
-               return;
-       norig = nod(n->op, N, N);
-       *norig = *n;
-       n->orig = norig;
-}
-
-// ispaddedfield reports whether the given field
-// is followed by padding. For the case where t is
-// the last field, total gives the size of the enclosing struct.
-static int
-ispaddedfield(Type *t, vlong total)
-{
-       if(t->etype != TFIELD)
-               fatal("ispaddedfield called non-field %T", t);
-       if(t->down == T)
-               return t->width + t->type->width != total;
-       return t->width + t->type->width != t->down->width;
-}
-
-int
-algtype1(Type *t, Type **bad)
-{
-       int a, ret;
-       Type *t1;
-       
-       if(bad)
-               *bad = T;
-       if(t->broke)
-               return AMEM;
-       if(t->noalg)
-               return ANOEQ;
-
-       switch(t->etype) {
-       case TANY:
-       case TFORW:
-               // will be defined later.
-               *bad = t;
-               return -1;
-
-       case TINT8:
-       case TUINT8:
-       case TINT16:
-       case TUINT16:
-       case TINT32:
-       case TUINT32:
-       case TINT64:
-       case TUINT64:
-       case TINT:
-       case TUINT:
-       case TUINTPTR:
-       case TBOOL:
-       case TPTR32:
-       case TPTR64:
-       case TCHAN:
-       case TUNSAFEPTR:
-               return AMEM;
-
-       case TFUNC:
-       case TMAP:
-               if(bad)
-                       *bad = t;
-               return ANOEQ;
-
-       case TFLOAT32:
-               return AFLOAT32;
-
-       case TFLOAT64:
-               return AFLOAT64;
-
-       case TCOMPLEX64:
-               return ACPLX64;
-
-       case TCOMPLEX128:
-               return ACPLX128;
-
-       case TSTRING:
-               return ASTRING;
-       
-       case TINTER:
-               if(isnilinter(t))
-                       return ANILINTER;
-               return AINTER;
-       
-       case TARRAY:
-               if(isslice(t)) {
-                       if(bad)
-                               *bad = t;
-                       return ANOEQ;
-               }
-               a = algtype1(t->type, bad);
-               if(a == ANOEQ || a == AMEM) {
-                       if(a == ANOEQ && bad)
-                               *bad = t;
-                       return a;
-               }
-               return -1;  // needs special compare
-
-       case TSTRUCT:
-               if(t->type != T && t->type->down == T && !isblanksym(t->type->sym)) {
-                       // One-field struct is same as that one field alone.
-                       return algtype1(t->type->type, bad);
-               }
-               ret = AMEM;
-               for(t1=t->type; t1!=T; t1=t1->down) {
-                       // All fields must be comparable.
-                       a = algtype1(t1->type, bad);
-                       if(a == ANOEQ)
-                               return ANOEQ;
-
-                       // Blank fields, padded fields, fields with non-memory
-                       // equality need special compare.
-                       if(a != AMEM || isblanksym(t1->sym) || ispaddedfield(t1, t->width)) {
-                               ret = -1;
-                               continue;
-                       }
-               }
-               return ret;
-       }
-
-       fatal("algtype1: unexpected type %T", t);
-       return 0;
-}
-
-int
-algtype(Type *t)
-{
-       int a;
-       
-       a = algtype1(t, nil);
-       if(a == AMEM || a == ANOEQ) {
-               if(isslice(t))
-                       return ASLICE;
-               switch(t->width) {
-               case 0:
-                       return a + AMEM0 - AMEM;
-               case 1:
-                       return a + AMEM8 - AMEM;
-               case 2:
-                       return a + AMEM16 - AMEM;
-               case 4:
-                       return a + AMEM32 - AMEM;
-               case 8:
-                       return a + AMEM64 - AMEM;
-               case 16:
-                       return a + AMEM128 - AMEM;
-               }
-       }
-       return a;
-}
-
-Type*
-maptype(Type *key, Type *val)
-{
-       Type *t;
-       Type *bad;
-       int atype, mtype;
-
-       if(key != nil) {
-               atype = algtype1(key, &bad);
-               if(bad == T)
-                       mtype = key->etype;
-               else
-                       mtype = bad->etype;
-               switch(mtype) {
-               default:
-                       if(atype == ANOEQ)
-                               yyerror("invalid map key type %T", key);
-                       break;
-               case TANY:
-                       // will be resolved later.
-                       break;
-               case TFORW:
-                       // map[key] used during definition of key.
-                       // postpone check until key is fully defined.
-                       // if there are multiple uses of map[key]
-                       // before key is fully defined, the error
-                       // will only be printed for the first one.
-                       // good enough.
-                       if(key->maplineno == 0)
-                               key->maplineno = lineno;
-                       break;
-               }
-       }
-       t = typ(TMAP);
-       t->down = key;
-       t->type = val;
-       return t;
-}
-
-Type*
-typ(int et)
-{
-       Type *t;
-
-       t = mal(sizeof(*t));
-       t->etype = et;
-       t->width = BADWIDTH;
-       t->lineno = lineno;
-       t->orig = t;
-       return t;
-}
-
-static int
-methcmp(const void *va, const void *vb)
-{
-       Type *a, *b;
-       int k;
-       
-       a = *(Type**)va;
-       b = *(Type**)vb;
-       if(a->sym == S && b->sym == S)
-               return 0;
-       if(a->sym == S)
-               return -1;
-       if(b->sym == S)
-               return 1;
-       k = strcmp(a->sym->name, b->sym->name);
-       if(k != 0)
-               return k;
-       if(!exportname(a->sym->name)) {
-               k = strcmp(a->sym->pkg->path->s, b->sym->pkg->path->s);
-               if(k != 0)
-                       return k;
-       }
-       return 0;
-}
-
-Type*
-sortinter(Type *t)
-{
-       Type *f;
-       int i;
-       Type **a;
-       
-       if(t->type == nil || t->type->down == nil)
-               return t;
-
-       i=0;
-       for(f=t->type; f; f=f->down)
-               i++;
-       a = mal(i*sizeof f);
-       i = 0;
-       for(f=t->type; f; f=f->down)
-               a[i++] = f;
-       qsort(a, i, sizeof a[0], methcmp);
-       while(i-- > 0) {
-               a[i]->down = f;
-               f = a[i];
-       }
-       t->type = f;
-       return t;
-}
-
-Node*
-nodintconst(int64 v)
-{
-       Node *c;
-
-       c = nod(OLITERAL, N, N);
-       c->addable = 1;
-       c->val.u.xval = mal(sizeof(*c->val.u.xval));
-       mpmovecfix(c->val.u.xval, v);
-       c->val.ctype = CTINT;
-       c->type = types[TIDEAL];
-       ullmancalc(c);
-       return c;
-}
-
-Node*
-nodfltconst(Mpflt* v)
-{
-       Node *c;
-
-       c = nod(OLITERAL, N, N);
-       c->addable = 1;
-       c->val.u.fval = mal(sizeof(*c->val.u.fval));
-       mpmovefltflt(c->val.u.fval, v);
-       c->val.ctype = CTFLT;
-       c->type = types[TIDEAL];
-       ullmancalc(c);
-       return c;
-}
-
-void
-nodconst(Node *n, Type *t, int64 v)
-{
-       memset(n, 0, sizeof(*n));
-       n->op = OLITERAL;
-       n->addable = 1;
-       ullmancalc(n);
-       n->val.u.xval = mal(sizeof(*n->val.u.xval));
-       mpmovecfix(n->val.u.xval, v);
-       n->val.ctype = CTINT;
-       n->type = t;
-
-       if(isfloat[t->etype])
-               fatal("nodconst: bad type %T", t);
-}
-
-Node*
-nodnil(void)
-{
-       Node *c;
-
-       c = nodintconst(0);
-       c->val.ctype = CTNIL;
-       c->type = types[TNIL];
-       return c;
-}
-
-Node*
-nodbool(int b)
-{
-       Node *c;
-
-       c = nodintconst(0);
-       c->val.ctype = CTBOOL;
-       c->val.u.bval = b;
-       c->type = idealbool;
-       return c;
-}
-
-Type*
-aindex(Node *b, Type *t)
-{
-       Type *r;
-       int64 bound;
-
-       bound = -1;     // open bound
-       typecheck(&b, Erv);
-       if(b != nil) {
-               switch(consttype(b)) {
-               default:
-                       yyerror("array bound must be an integer expression");
-                       break;
-               case CTINT:
-               case CTRUNE:
-                       bound = mpgetfix(b->val.u.xval);
-                       if(bound < 0)
-                               yyerror("array bound must be non negative");
-                       break;
-               }
-       }
-
-       // fixed array
-       r = typ(TARRAY);
-       r->type = t;
-       r->bound = bound;
-       return r;
-}
-
-Node*
-treecopy(Node *n)
-{
-       Node *m;
-
-       if(n == N)
-               return N;
-
-       switch(n->op) {
-       default:
-               m = nod(OXXX, N, N);
-               *m = *n;
-               m->orig = m;
-               m->left = treecopy(n->left);
-               m->right = treecopy(n->right);
-               m->list = listtreecopy(n->list);
-               if(m->defn)
-                       abort();
-               break;
-
-       case ONONAME:
-               if(n->sym == lookup("iota")) {
-                       // Not sure yet whether this is the real iota,
-                       // but make a copy of the Node* just in case,
-                       // so that all the copies of this const definition
-                       // don't have the same iota value.
-                       m = nod(OXXX, N, N);
-                       *m = *n;
-                       m->iota = iota;
-                       break;
-               }
-               // fall through
-       case ONAME:
-       case OLITERAL:
-       case OTYPE:
-               m = n;
-               break;
-       }
-       return m;
-}
-
-
-int
-isnil(Node *n)
-{
-       if(n == N)
-               return 0;
-       if(n->op != OLITERAL)
-               return 0;
-       if(n->val.ctype != CTNIL)
-               return 0;
-       return 1;
-}
-
-int
-isptrto(Type *t, int et)
-{
-       if(t == T)
-               return 0;
-       if(!isptr[t->etype])
-               return 0;
-       t = t->type;
-       if(t == T)
-               return 0;
-       if(t->etype != et)
-               return 0;
-       return 1;
-}
-
-int
-istype(Type *t, int et)
-{
-       return t != T && t->etype == et;
-}
-
-int
-isfixedarray(Type *t)
-{
-       return t != T && t->etype == TARRAY && t->bound >= 0;
-}
-
-int
-isslice(Type *t)
-{
-       return t != T && t->etype == TARRAY && t->bound < 0;
-}
-
-int
-isblank(Node *n)
-{
-       if(n == N)
-               return 0;
-       return isblanksym(n->sym);
-}
-
-int
-isblanksym(Sym *s)
-{
-       char *p;
-
-       if(s == S)
-               return 0;
-       p = s->name;
-       if(p == nil)
-               return 0;
-       return p[0] == '_' && p[1] == '\0';
-}
-
-int
-isinter(Type *t)
-{
-       return t != T && t->etype == TINTER;
-}
-
-int
-isnilinter(Type *t)
-{
-       if(!isinter(t))
-               return 0;
-       if(t->type != T)
-               return 0;
-       return 1;
-}
-
-int
-isideal(Type *t)
-{
-       if(t == T)
-               return 0;
-       if(t == idealstring || t == idealbool)
-               return 1;
-       switch(t->etype) {
-       case TNIL:
-       case TIDEAL:
-               return 1;
-       }
-       return 0;
-}
-
-/*
- * given receiver of type t (t == r or t == *r)
- * return type to hang methods off (r).
- */
-Type*
-methtype(Type *t, int mustname)
-{
-       if(t == T)
-               return T;
-
-       // strip away pointer if it's there
-       if(isptr[t->etype]) {
-               if(t->sym != S)
-                       return T;
-               t = t->type;
-               if(t == T)
-                       return T;
-       }
-
-       // need a type name
-       if(t->sym == S && (mustname || t->etype != TSTRUCT))
-               return T;
-
-       // check types
-       if(!issimple[t->etype])
-       switch(t->etype) {
-       default:
-               return T;
-       case TSTRUCT:
-       case TARRAY:
-       case TMAP:
-       case TCHAN:
-       case TSTRING:
-       case TFUNC:
-               break;
-       }
-
-       return t;
-}
-
-int
-cplxsubtype(int et)
-{
-       switch(et) {
-       case TCOMPLEX64:
-               return TFLOAT32;
-       case TCOMPLEX128:
-               return TFLOAT64;
-       }
-       fatal("cplxsubtype: %E\n", et);
-       return 0;
-}
-
-static int
-eqnote(Strlit *a, Strlit *b)
-{
-       if(a == b)
-               return 1;
-       if(a == nil || b == nil)
-               return 0;
-       if(a->len != b->len)
-               return 0;
-       return memcmp(a->s, b->s, a->len) == 0;
-}
-
-typedef struct TypePairList TypePairList;
-struct TypePairList
-{
-       Type *t1;
-       Type *t2;
-       TypePairList *next;
-};
-
-static int
-onlist(TypePairList *l, Type *t1, Type *t2) 
-{
-       for(; l; l=l->next)
-               if((l->t1 == t1 && l->t2 == t2) || (l->t1 == t2 && l->t2 == t1))
-                       return 1;
-       return 0;
-}
-
-static int eqtype1(Type*, Type*, TypePairList*);
-
-// Return 1 if t1 and t2 are identical, following the spec rules.
-//
-// Any cyclic type must go through a named type, and if one is
-// named, it is only identical to the other if they are the same
-// pointer (t1 == t2), so there's no chance of chasing cycles
-// ad infinitum, so no need for a depth counter.
-int
-eqtype(Type *t1, Type *t2)
-{
-       return eqtype1(t1, t2, nil);
-}
-
-static int
-eqtype1(Type *t1, Type *t2, TypePairList *assumed_equal)
-{
-       TypePairList l;
-
-       if(t1 == t2)
-               return 1;
-       if(t1 == T || t2 == T || t1->etype != t2->etype)
-               return 0;
-       if(t1->sym || t2->sym) {
-               // Special case: we keep byte and uint8 separate
-               // for error messages.  Treat them as equal.
-               switch(t1->etype) {
-               case TUINT8:
-                       if((t1 == types[TUINT8] || t1 == bytetype) && (t2 == types[TUINT8] || t2 == bytetype))
-                               return 1;
-                       break;
-               case TINT:
-               case TINT32:
-                       if((t1 == types[runetype->etype] || t1 == runetype) && (t2 == types[runetype->etype] || t2 == runetype))
-                               return 1;
-                       break;
-               }
-               return 0;
-       }
-
-       if(onlist(assumed_equal, t1, t2))
-               return 1;
-       l.next = assumed_equal;
-       l.t1 = t1;
-       l.t2 = t2;
-
-       switch(t1->etype) {
-       case TINTER:
-       case TSTRUCT:
-               for(t1=t1->type, t2=t2->type; t1 && t2; t1=t1->down, t2=t2->down) {
-                       if(t1->etype != TFIELD || t2->etype != TFIELD)
-                               fatal("struct/interface missing field: %T %T", t1, t2);
-                       if(t1->sym != t2->sym || t1->embedded != t2->embedded || !eqtype1(t1->type, t2->type, &l) || !eqnote(t1->note, t2->note))
-                               goto no;
-               }
-               if(t1 == T && t2 == T)
-                       goto yes;
-               goto no;
-
-       case TFUNC:
-               // Loop over structs: receiver, in, out.
-               for(t1=t1->type, t2=t2->type; t1 && t2; t1=t1->down, t2=t2->down) {
-                       Type *ta, *tb;
-
-                       if(t1->etype != TSTRUCT || t2->etype != TSTRUCT)
-                               fatal("func missing struct: %T %T", t1, t2);
-
-                       // Loop over fields in structs, ignoring argument names.
-                       for(ta=t1->type, tb=t2->type; ta && tb; ta=ta->down, tb=tb->down) {
-                               if(ta->etype != TFIELD || tb->etype != TFIELD)
-                                       fatal("func struct missing field: %T %T", ta, tb);
-                               if(ta->isddd != tb->isddd || !eqtype1(ta->type, tb->type, &l))
-                                       goto no;
-                       }
-                       if(ta != T || tb != T)
-                               goto no;
-               }
-               if(t1 == T && t2 == T)
-                       goto yes;
-               goto no;
-       
-       case TARRAY:
-               if(t1->bound != t2->bound)
-                       goto no;
-               break;
-       
-       case TCHAN:
-               if(t1->chan != t2->chan)
-                       goto no;
-               break;
-       }
-
-       if(eqtype1(t1->down, t2->down, &l) && eqtype1(t1->type, t2->type, &l))
-               goto yes;
-       goto no;
-
-yes:
-       return 1;
-
-no:
-       return 0;
-}
-
-// Are t1 and t2 equal struct types when field names are ignored?
-// For deciding whether the result struct from g can be copied
-// directly when compiling f(g()).
-int
-eqtypenoname(Type *t1, Type *t2)
-{
-       if(t1 == T || t2 == T || t1->etype != TSTRUCT || t2->etype != TSTRUCT)
-               return 0;
-
-       t1 = t1->type;
-       t2 = t2->type;
-       for(;;) {
-               if(!eqtype(t1, t2))
-                       return 0;
-               if(t1 == T)
-                       return 1;
-               t1 = t1->down;
-               t2 = t2->down;
-       }
-}
-
-// Is type src assignment compatible to type dst?
-// If so, return op code to use in conversion.
-// If not, return 0.
-int
-assignop(Type *src, Type *dst, char **why)
-{
-       Type *missing, *have;
-       int ptr;
-
-       if(why != nil)
-               *why = "";
-
-       // TODO(rsc,lvd): This behaves poorly in the presence of inlining.
-       // https://golang.org/issue/2795
-       if(safemode && importpkg == nil && src != T && src->etype == TUNSAFEPTR) {
-               yyerror("cannot use unsafe.Pointer");
-               errorexit();
-       }
-
-       if(src == dst)
-               return OCONVNOP;
-       if(src == T || dst == T || src->etype == TFORW || dst->etype == TFORW || src->orig == T || dst->orig == T)
-               return 0;
-
-       // 1. src type is identical to dst.
-       if(eqtype(src, dst))
-               return OCONVNOP;
-       
-       // 2. src and dst have identical underlying types
-       // and either src or dst is not a named type or
-       // both are empty interface types.
-       // For assignable but different non-empty interface types,
-       // we want to recompute the itab.
-       if(eqtype(src->orig, dst->orig) && (src->sym == S || dst->sym == S || isnilinter(src)))
-               return OCONVNOP;
-
-       // 3. dst is an interface type and src implements dst.
-       if(dst->etype == TINTER && src->etype != TNIL) {
-               if(implements(src, dst, &missing, &have, &ptr))
-                       return OCONVIFACE;
-
-               // we'll have complained about this method anyway, suppress spurious messages.
-               if(have && have->sym == missing->sym && (have->type->broke || missing->type->broke))
-                       return OCONVIFACE;
-
-               if(why != nil) {
-                       if(isptrto(src, TINTER))
-                               *why = smprint(":\n\t%T is pointer to interface, not interface", src);
-                       else if(have && have->sym == missing->sym && have->nointerface)
-                               *why = smprint(":\n\t%T does not implement %T (%S method is marked 'nointerface')",
-                                       src, dst, missing->sym);
-                       else if(have && have->sym == missing->sym)
-                               *why = smprint(":\n\t%T does not implement %T (wrong type for %S method)\n"
-                                       "\t\thave %S%hhT\n\t\twant %S%hhT", src, dst, missing->sym,
-                                       have->sym, have->type, missing->sym, missing->type);
-                       else if(ptr)
-                               *why = smprint(":\n\t%T does not implement %T (%S method has pointer receiver)",
-                                       src, dst, missing->sym);
-                       else if(have)
-                               *why = smprint(":\n\t%T does not implement %T (missing %S method)\n"
-                                       "\t\thave %S%hhT\n\t\twant %S%hhT", src, dst, missing->sym,
-                                       have->sym, have->type, missing->sym, missing->type);
-                       else
-                               *why = smprint(":\n\t%T does not implement %T (missing %S method)",
-                                       src, dst, missing->sym);
-               }
-               return 0;
-       }
-       if(isptrto(dst, TINTER)) {
-               if(why != nil)
-                       *why = smprint(":\n\t%T is pointer to interface, not interface", dst);
-               return 0;
-       }
-       if(src->etype == TINTER && dst->etype != TBLANK) {
-               if(why != nil && implements(dst, src, &missing, &have, &ptr))
-                       *why = ": need type assertion";
-               return 0;
-       }
-
-       // 4. src is a bidirectional channel value, dst is a channel type,
-       // src and dst have identical element types, and
-       // either src or dst is not a named type.
-       if(src->etype == TCHAN && src->chan == Cboth && dst->etype == TCHAN)
-       if(eqtype(src->type, dst->type) && (src->sym == S || dst->sym == S))
-               return OCONVNOP;
-
-       // 5. src is the predeclared identifier nil and dst is a nillable type.
-       if(src->etype == TNIL) {
-               switch(dst->etype) {
-               case TARRAY:
-                       if(dst->bound != -100)  // not slice
-                               break;
-               case TPTR32:
-               case TPTR64:
-               case TFUNC:
-               case TMAP:
-               case TCHAN:
-               case TINTER:
-                       return OCONVNOP;
-               }
-       }
-
-       // 6. rule about untyped constants - already converted by defaultlit.
-       
-       // 7. Any typed value can be assigned to the blank identifier.
-       if(dst->etype == TBLANK)
-               return OCONVNOP;
-
-       return 0;
-}
-
-// Can we convert a value of type src to a value of type dst?
-// If so, return op code to use in conversion (maybe OCONVNOP).
-// If not, return 0.
-int
-convertop(Type *src, Type *dst, char **why)
-{
-       int op;
-       
-       if(why != nil)
-               *why = "";
-
-       if(src == dst)
-               return OCONVNOP;
-       if(src == T || dst == T)
-               return 0;
-       
-       // 1. src can be assigned to dst.
-       if((op = assignop(src, dst, why)) != 0)
-               return op;
-
-       // The rules for interfaces are no different in conversions
-       // than assignments.  If interfaces are involved, stop now
-       // with the good message from assignop.
-       // Otherwise clear the error.
-       if(src->etype == TINTER || dst->etype == TINTER)
-               return 0;
-       if(why != nil)
-               *why = "";
-
-       // 2. src and dst have identical underlying types.
-       if(eqtype(src->orig, dst->orig))
-               return OCONVNOP;
-       
-       // 3. src and dst are unnamed pointer types 
-       // and their base types have identical underlying types.
-       if(isptr[src->etype] && isptr[dst->etype] && src->sym == S && dst->sym == S)
-       if(eqtype(src->type->orig, dst->type->orig))
-               return OCONVNOP;
-
-       // 4. src and dst are both integer or floating point types.
-       if((isint[src->etype] || isfloat[src->etype]) && (isint[dst->etype] || isfloat[dst->etype])) {
-               if(simtype[src->etype] == simtype[dst->etype])
-                       return OCONVNOP;
-               return OCONV;
-       }
-
-       // 5. src and dst are both complex types.
-       if(iscomplex[src->etype] && iscomplex[dst->etype]) {
-               if(simtype[src->etype] == simtype[dst->etype])
-                       return OCONVNOP;
-               return OCONV;
-       }
-
-       // 6. src is an integer or has type []byte or []rune
-       // and dst is a string type.
-       if(isint[src->etype] && dst->etype == TSTRING)
-               return ORUNESTR;
-
-       if(isslice(src) && dst->etype == TSTRING) {
-               if(src->type->etype == bytetype->etype)
-                       return OARRAYBYTESTR;
-               if(src->type->etype == runetype->etype)
-                       return OARRAYRUNESTR;
-       }
-       
-       // 7. src is a string and dst is []byte or []rune.
-       // String to slice.
-       if(src->etype == TSTRING && isslice(dst)) {
-               if(dst->type->etype == bytetype->etype)
-                       return OSTRARRAYBYTE;
-               if(dst->type->etype == runetype->etype)
-                       return OSTRARRAYRUNE;
-       }
-       
-       // 8. src is a pointer or uintptr and dst is unsafe.Pointer.
-       if((isptr[src->etype] || src->etype == TUINTPTR) && dst->etype == TUNSAFEPTR)
-               return OCONVNOP;
-
-       // 9. src is unsafe.Pointer and dst is a pointer or uintptr.
-       if(src->etype == TUNSAFEPTR && (isptr[dst->etype] || dst->etype == TUINTPTR))
-               return OCONVNOP;
-
-       return 0;
-}
-
-// Convert node n for assignment to type t.
-Node*
-assignconv(Node *n, Type *t, char *context)
-{
-       int op;
-       Node *r, *old;
-       char *why;
-       
-       if(n == N || n->type == T || n->type->broke)
-               return n;
-
-       if(t->etype == TBLANK && n->type->etype == TNIL)
-               yyerror("use of untyped nil");
-
-       old = n;
-       old->diag++;  // silence errors about n; we'll issue one below
-       defaultlit(&n, t);
-       old->diag--;
-       if(t->etype == TBLANK)
-               return n;
-
-       // Convert ideal bool from comparison to plain bool
-       // if the next step is non-bool (like interface{}).
-       if(n->type == idealbool && t->etype != TBOOL) {
-               if(n->op == ONAME || n->op == OLITERAL) {
-                       r = nod(OCONVNOP, n, N);
-                       r->type = types[TBOOL];
-                       r->typecheck = 1;
-                       r->implicit = 1;
-                       n = r;
-               }
-       }
-
-       if(eqtype(n->type, t))
-               return n;
-
-       op = assignop(n->type, t, &why);
-       if(op == 0) {
-               yyerror("cannot use %lN as type %T in %s%s", n, t, context, why);
-               op = OCONV;
-       }
-
-       r = nod(op, n, N);
-       r->type = t;
-       r->typecheck = 1;
-       r->implicit = 1;
-       r->orig = n->orig;
-       return r;
-}
-
-static int
-subtype(Type **stp, Type *t, int d)
-{
-       Type *st;
-
-loop:
-       st = *stp;
-       if(st == T)
-               return 0;
-
-       d++;
-       if(d >= 10)
-               return 0;
-
-       switch(st->etype) {
-       default:
-               return 0;
-
-       case TPTR32:
-       case TPTR64:
-       case TCHAN:
-       case TARRAY:
-               stp = &st->type;
-               goto loop;
-
-       case TANY:
-               if(!st->copyany)
-                       return 0;
-               *stp = t;
-               break;
-
-       case TMAP:
-               if(subtype(&st->down, t, d))
-                       break;
-               stp = &st->type;
-               goto loop;
-
-       case TFUNC:
-               for(;;) {
-                       if(subtype(&st->type, t, d))
-                               break;
-                       if(subtype(&st->type->down->down, t, d))
-                               break;
-                       if(subtype(&st->type->down, t, d))
-                               break;
-                       return 0;
-               }
-               break;
-
-       case TSTRUCT:
-               for(st=st->type; st!=T; st=st->down)
-                       if(subtype(&st->type, t, d))
-                               return 1;
-               return 0;
-       }
-       return 1;
-}
-
-/*
- * Is this a 64-bit type?
- */
-int
-is64(Type *t)
-{
-       if(t == T)
-               return 0;
-       switch(simtype[t->etype]) {
-       case TINT64:
-       case TUINT64:
-       case TPTR64:
-               return 1;
-       }
-       return 0;
-}
-
-/*
- * Is a conversion between t1 and t2 a no-op?
- */
-int
-noconv(Type *t1, Type *t2)
-{
-       int e1, e2;
-
-       e1 = simtype[t1->etype];
-       e2 = simtype[t2->etype];
-
-       switch(e1) {
-       case TINT8:
-       case TUINT8:
-               return e2 == TINT8 || e2 == TUINT8;
-
-       case TINT16:
-       case TUINT16:
-               return e2 == TINT16 || e2 == TUINT16;
-
-       case TINT32:
-       case TUINT32:
-       case TPTR32:
-               return e2 == TINT32 || e2 == TUINT32 || e2 == TPTR32;
-
-       case TINT64:
-       case TUINT64:
-       case TPTR64:
-               return e2 == TINT64 || e2 == TUINT64 || e2 == TPTR64;
-
-       case TFLOAT32:
-               return e2 == TFLOAT32;
-
-       case TFLOAT64:
-               return e2 == TFLOAT64;
-       }
-       return 0;
-}
-
-void
-argtype(Node *on, Type *t)
-{
-       dowidth(t);
-       if(!subtype(&on->type, t, 0))
-               fatal("argtype: failed %N %T\n", on, t);
-}
-
-Type*
-shallow(Type *t)
-{
-       Type *nt;
-
-       if(t == T)
-               return T;
-       nt = typ(0);
-       *nt = *t;
-       if(t->orig == t)
-               nt->orig = nt;
-       return nt;
-}
-
-static Type*
-deep(Type *t)
-{
-       Type *nt, *xt;
-
-       if(t == T)
-               return T;
-
-       switch(t->etype) {
-       default:
-               nt = t; // share from here down
-               break;
-
-       case TANY:
-               nt = shallow(t);
-               nt->copyany = 1;
-               break;
-
-       case TPTR32:
-       case TPTR64:
-       case TCHAN:
-       case TARRAY:
-               nt = shallow(t);
-               nt->type = deep(t->type);
-               break;
-
-       case TMAP:
-               nt = shallow(t);
-               nt->down = deep(t->down);
-               nt->type = deep(t->type);
-               break;
-
-       case TFUNC:
-               nt = shallow(t);
-               nt->type = deep(t->type);
-               nt->type->down = deep(t->type->down);
-               nt->type->down->down = deep(t->type->down->down);
-               break;
-
-       case TSTRUCT:
-               nt = shallow(t);
-               nt->type = shallow(t->type);
-               xt = nt->type;
-
-               for(t=t->type; t!=T; t=t->down) {
-                       xt->type = deep(t->type);
-                       xt->down = shallow(t->down);
-                       xt = xt->down;
-               }
-               break;
-       }
-       return nt;
-}
-
-Node*
-syslook(char *name, int copy)
-{
-       Sym *s;
-       Node *n;
-
-       s = pkglookup(name, runtimepkg);
-       if(s == S || s->def == N)
-               fatal("syslook: can't find runtime.%s", name);
-
-       if(!copy)
-               return s->def;
-
-       n = nod(0, N, N);
-       *n = *s->def;
-       n->type = deep(s->def->type);
-
-       return n;
-}
-
-/*
- * compute a hash value for type t.
- * if t is a method type, ignore the receiver
- * so that the hash can be used in interface checks.
- * %T already contains
- * all the necessary logic to generate a representation
- * of the type that completely describes it.
- * using smprint here avoids duplicating that code.
- * using md5 here is overkill, but i got tired of
- * accidental collisions making the runtime think
- * two types are equal when they really aren't.
- */
-uint32
-typehash(Type *t)
-{
-       char *p;
-       MD5 d;
-
-       if(t->thistuple) {
-               // hide method receiver from Tpretty
-               t->thistuple = 0;
-               p = smprint("%-uT", t);
-               t->thistuple = 1;
-       } else
-               p = smprint("%-uT", t);
-       //print("typehash: %s\n", p);
-       md5reset(&d);
-       md5write(&d, (uchar*)p, strlen(p));
-       free(p);
-       return md5sum(&d, nil);
-}
-
-Type*
-ptrto(Type *t)
-{
-       Type *t1;
-
-       if(tptr == 0)
-               fatal("ptrto: no tptr");
-       t1 = typ(tptr);
-       t1->type = t;
-       t1->width = widthptr;
-       t1->align = widthptr;
-       return t1;
-}
-
-void
-frame(int context)
-{
-       NodeList *l;
-       Node *n;
-       vlong w;
-
-       if(context) {
-               print("--- external frame ---\n");
-               l = externdcl;
-       } else if(curfn) {
-               print("--- %S frame ---\n", curfn->nname->sym);
-               l = curfn->dcl;
-       } else
-               return;
-
-       for(; l; l=l->next) {
-               n = l->n;
-               w = -1;
-               if(n->type)
-                       w = n->type->width;
-               switch(n->op) {
-               case ONAME:
-                       print("%O %S G%d %T width=%lld\n", n->op, n->sym, n->vargen, n->type, w);
-                       break;
-
-               case OTYPE:
-                       print("%O %T width=%lld\n", n->op, n->type, w);
-                       break;
-               }
-       }
-}
-
-/*
- * calculate sethi/ullman number
- * roughly how many registers needed to
- * compile a node. used to compile the
- * hardest side first to minimize registers.
- */
-void
-ullmancalc(Node *n)
-{
-       int ul, ur;
-
-       if(n == N)
-               return;
-
-       if(n->ninit != nil) {
-               ul = UINF;
-               goto out;
-       }
-
-       switch(n->op) {
-       case OREGISTER:
-       case OLITERAL:
-       case ONAME:
-               ul = 1;
-               if(n->class == PPARAMREF || (n->class & PHEAP))
-                       ul++;
-               goto out;
-       case OCALL:
-       case OCALLFUNC:
-       case OCALLMETH:
-       case OCALLINTER:
-               ul = UINF;
-               goto out;
-       case OANDAND:
-       case OOROR:
-               // hard with race detector
-               if(flag_race) {
-                       ul = UINF;
-                       goto out;
-               }
-       }
-       ul = 1;
-       if(n->left != N)
-               ul = n->left->ullman;
-       ur = 1;
-       if(n->right != N)
-               ur = n->right->ullman;
-       if(ul == ur)
-               ul += 1;
-       if(ur > ul)
-               ul = ur;
-
-out:
-       if(ul > 200)
-               ul = 200; // clamp to uchar with room to grow
-       n->ullman = ul;
-}
-
-void
-badtype(int o, Type *tl, Type *tr)
-{
-       Fmt fmt;
-       char *s;
-       
-       fmtstrinit(&fmt);
-       if(tl != T)
-               fmtprint(&fmt, "\n      %T", tl);
-       if(tr != T)
-               fmtprint(&fmt, "\n      %T", tr);
-
-       // common mistake: *struct and *interface.
-       if(tl && tr && isptr[tl->etype] && isptr[tr->etype]) {
-               if(tl->type->etype == TSTRUCT && tr->type->etype == TINTER)
-                       fmtprint(&fmt, "\n      (*struct vs *interface)");
-               else if(tl->type->etype == TINTER && tr->type->etype == TSTRUCT)
-                       fmtprint(&fmt, "\n      (*interface vs *struct)");
-       }
-       s = fmtstrflush(&fmt);
-       yyerror("illegal types for operand: %O%s", o, s);
-}
-
-/*
- * iterator to walk a structure declaration
- */
-Type*
-structfirst(Iter *s, Type **nn)
-{
-       Type *n, *t;
-
-       n = *nn;
-       if(n == T)
-               goto bad;
-
-       switch(n->etype) {
-       default:
-               goto bad;
-
-       case TSTRUCT:
-       case TINTER:
-       case TFUNC:
-               break;
-       }
-
-       t = n->type;
-       if(t == T)
-               goto rnil;
-
-       if(t->etype != TFIELD)
-               fatal("structfirst: not field %T", t);
-
-       s->t = t;
-       return t;
-
-bad:
-       fatal("structfirst: not struct %T", n);
-
-rnil:
-       return T;
-}
-
-Type*
-structnext(Iter *s)
-{
-       Type *n, *t;
-
-       n = s->t;
-       t = n->down;
-       if(t == T)
-               goto rnil;
-
-       if(t->etype != TFIELD)
-               goto bad;
-
-       s->t = t;
-       return t;
-
-bad:
-       fatal("structnext: not struct %T", n);
-
-rnil:
-       return T;
-}
-
-/*
- * iterator to this and inargs in a function
- */
-Type*
-funcfirst(Iter *s, Type *t)
-{
-       Type *fp;
-
-       if(t == T)
-               goto bad;
-
-       if(t->etype != TFUNC)
-               goto bad;
-
-       s->tfunc = t;
-       s->done = 0;
-       fp = structfirst(s, getthis(t));
-       if(fp == T) {
-               s->done = 1;
-               fp = structfirst(s, getinarg(t));
-       }
-       return fp;
-
-bad:
-       fatal("funcfirst: not func %T", t);
-       return T;
-}
-
-Type*
-funcnext(Iter *s)
-{
-       Type *fp;
-
-       fp = structnext(s);
-       if(fp == T && !s->done) {
-               s->done = 1;
-               fp = structfirst(s, getinarg(s->tfunc));
-       }
-       return fp;
-}
-
-Type**
-getthis(Type *t)
-{
-       if(t->etype != TFUNC)
-               fatal("getthis: not a func %T", t);
-       return &t->type;
-}
-
-Type**
-getoutarg(Type *t)
-{
-       if(t->etype != TFUNC)
-               fatal("getoutarg: not a func %T", t);
-       return &t->type->down;
-}
-
-Type**
-getinarg(Type *t)
-{
-       if(t->etype != TFUNC)
-               fatal("getinarg: not a func %T", t);
-       return &t->type->down->down;
-}
-
-Type*
-getthisx(Type *t)
-{
-       return *getthis(t);
-}
-
-Type*
-getoutargx(Type *t)
-{
-       return *getoutarg(t);
-}
-
-Type*
-getinargx(Type *t)
-{
-       return *getinarg(t);
-}
-
-/*
- * return !(op)
- * eg == <=> !=
- */
-int
-brcom(int a)
-{
-       switch(a) {
-       case OEQ:       return ONE;
-       case ONE:       return OEQ;
-       case OLT:       return OGE;
-       case OGT:       return OLE;
-       case OLE:       return OGT;
-       case OGE:       return OLT;
-       }
-       fatal("brcom: no com for %O\n", a);
-       return a;
-}
-
-/*
- * return reverse(op)
- * eg a op b <=> b r(op) a
- */
-int
-brrev(int a)
-{
-       switch(a) {
-       case OEQ:       return OEQ;
-       case ONE:       return ONE;
-       case OLT:       return OGT;
-       case OGT:       return OLT;
-       case OLE:       return OGE;
-       case OGE:       return OLE;
-       }
-       fatal("brcom: no rev for %O\n", a);
-       return a;
-}
-
-/*
- * return side effect-free n, appending side effects to init.
- * result is assignable if n is.
- */
-Node*
-safeexpr(Node *n, NodeList **init)
-{
-       Node *l;
-       Node *r;
-       Node *a;
-
-       if(n == N)
-               return N;
-
-       if(n->ninit) {
-               walkstmtlist(n->ninit);
-               *init = concat(*init, n->ninit);
-               n->ninit = nil;
-       }
-
-       switch(n->op) {
-       case ONAME:
-       case OLITERAL:
-               return n;
-
-       case ODOT:
-               l = safeexpr(n->left, init);
-               if(l == n->left)
-                       return n;
-               r = nod(OXXX, N, N);
-               *r = *n;
-               r->left = l;
-               typecheck(&r, Erv);
-               walkexpr(&r, init);
-               return r;
-
-       case ODOTPTR:
-       case OIND:
-               l = safeexpr(n->left, init);
-               if(l == n->left)
-                       return n;
-               a = nod(OXXX, N, N);
-               *a = *n;
-               a->left = l;
-               walkexpr(&a, init);
-               return a;
-
-       case OINDEX:
-       case OINDEXMAP:
-               l = safeexpr(n->left, init);
-               r = safeexpr(n->right, init);
-               if(l == n->left && r == n->right)
-                       return n;
-               a = nod(OXXX, N, N);
-               *a = *n;
-               a->left = l;
-               a->right = r;
-               walkexpr(&a, init);
-               return a;
-       }
-
-       // make a copy; must not be used as an lvalue
-       if(islvalue(n))
-               fatal("missing lvalue case in safeexpr: %N", n);
-       return cheapexpr(n, init);
-}
-
-Node*
-copyexpr(Node *n, Type *t, NodeList **init)
-{
-       Node *a, *l;
-       
-       l = temp(t);
-       a = nod(OAS, l, n);
-       typecheck(&a, Etop);
-       walkexpr(&a, init);
-       *init = list(*init, a);
-       return l;
-}
-
-/*
- * return side-effect free and cheap n, appending side effects to init.
- * result may not be assignable.
- */
-Node*
-cheapexpr(Node *n, NodeList **init)
-{
-       switch(n->op) {
-       case ONAME:
-       case OLITERAL:
-               return n;
-       }
-
-       return copyexpr(n, n->type, init);
-}
-
-/*
- * return n in a local variable of type t if it is not already.
- * the value is guaranteed not to change except by direct
- * assignment to it.
- */
-Node*
-localexpr(Node *n, Type *t, NodeList **init)
-{
-       if(n->op == ONAME && (!n->addrtaken || strncmp(n->sym->name, "autotmp_", 8) == 0) &&
-               (n->class == PAUTO || n->class == PPARAM || n->class == PPARAMOUT) &&
-               convertop(n->type, t, nil) == OCONVNOP)
-               return n;
-       
-       return copyexpr(n, t, init);
-}
-
-void
-setmaxarg(Type *t, int32 extra)
-{
-       int64 w;
-
-       dowidth(t);
-       w = t->argwid;
-       if(w >= thearch.MAXWIDTH)
-               fatal("bad argwid %T", t);
-       w += extra;
-       if(w >= thearch.MAXWIDTH)
-               fatal("bad argwid %d + %T", extra, t);
-       if(w > maxarg)
-               maxarg = w;
-}
-
-/*
- * unicode-aware case-insensitive strcmp
- */
-
-static int
-ucistrcmp(char *p, char *q)
-{
-       Rune rp, rq;
-
-       while(*p || *q) {
-               if(*p == 0)
-                       return +1;
-               if(*q == 0)
-                       return -1;
-               p += chartorune(&rp, p);
-               q += chartorune(&rq, q);
-               rp = tolowerrune(rp);
-               rq = tolowerrune(rq);
-               if(rp < rq)
-                       return -1;
-               if(rp > rq)
-                       return +1;
-       }
-       return 0;
-}
-
-/*
- * code to resolve elided DOTs
- * in embedded types
- */
-
-// search depth 0 --
-// return count of fields+methods
-// found with a given name
-static int
-lookdot0(Sym *s, Type *t, Type **save, int ignorecase)
-{
-       Type *f, *u;
-       int c;
-
-       u = t;
-       if(isptr[u->etype])
-               u = u->type;
-
-       c = 0;
-       if(u->etype == TSTRUCT || u->etype == TINTER) {
-               for(f=u->type; f!=T; f=f->down)
-                       if(f->sym == s || (ignorecase && f->type->etype == TFUNC && f->type->thistuple > 0 && ucistrcmp(f->sym->name, s->name) == 0)) {
-                               if(save)
-                                       *save = f;
-                               c++;
-                       }
-       }
-       u = methtype(t, 0);
-       if(u != T) {
-               for(f=u->method; f!=T; f=f->down)
-                       if(f->embedded == 0 && (f->sym == s || (ignorecase && ucistrcmp(f->sym->name, s->name) == 0))) {
-                               if(save)
-                                       *save = f;
-                               c++;
-                       }
-       }
-       return c;
-}
-
-// search depth d for field/method s --
-// return count of fields+methods
-// found at search depth.
-// answer is in dotlist array and
-// count of number of ways is returned.
-int
-adddot1(Sym *s, Type *t, int d, Type **save, int ignorecase)
-{
-       Type *f, *u;
-       int c, a;
-
-       if(t->trecur)
-               return 0;
-       t->trecur = 1;
-
-       if(d == 0) {
-               c = lookdot0(s, t, save, ignorecase);
-               goto out;
-       }
-
-       c = 0;
-       u = t;
-       if(isptr[u->etype])
-               u = u->type;
-       if(u->etype != TSTRUCT && u->etype != TINTER)
-               goto out;
-
-       d--;
-       for(f=u->type; f!=T; f=f->down) {
-               if(!f->embedded)
-                       continue;
-               if(f->sym == S)
-                       continue;
-               a = adddot1(s, f->type, d, save, ignorecase);
-               if(a != 0 && c == 0)
-                       dotlist[d].field = f;
-               c += a;
-       }
-
-out:
-       t->trecur = 0;
-       return c;
-}
-
-// in T.field
-// find missing fields that
-// will give shortest unique addressing.
-// modify the tree with missing type names.
-Node*
-adddot(Node *n)
-{
-       Type *t;
-       Sym *s;
-       int c, d;
-
-       typecheck(&n->left, Etype|Erv);
-       n->diag |= n->left->diag;
-       t = n->left->type;
-       if(t == T)
-               goto ret;
-       
-       if(n->left->op == OTYPE)
-               goto ret;
-
-       if(n->right->op != ONAME)
-               goto ret;
-       s = n->right->sym;
-       if(s == S)
-               goto ret;
-
-       for(d=0; d<nelem(dotlist); d++) {
-               c = adddot1(s, t, d, nil, 0);
-               if(c > 0)
-                       goto out;
-       }
-       goto ret;
-
-out:
-       if(c > 1) {
-               yyerror("ambiguous selector %N", n);
-               n->left = N;
-               return n;
-       }
-
-       // rebuild elided dots
-       for(c=d-1; c>=0; c--)
-               n->left = nod(ODOT, n->left, newname(dotlist[c].field->sym));
-ret:
-       return n;
-}
-
-
-/*
- * code to help generate trampoline
- * functions for methods on embedded
- * subtypes.
- * these are approx the same as
- * the corresponding adddot routines
- * except that they expect to be called
- * with unique tasks and they return
- * the actual methods.
- */
-
-typedef        struct  Symlink Symlink;
-struct Symlink
-{
-       Type*           field;
-       uchar           good;
-       uchar           followptr;
-       Symlink*        link;
-};
-static Symlink*        slist;
-
-static void
-expand0(Type *t, int followptr)
-{
-       Type *f, *u;
-       Symlink *sl;
-
-       u = t;
-       if(isptr[u->etype]) {
-               followptr = 1;
-               u = u->type;
-       }
-
-       if(u->etype == TINTER) {
-               for(f=u->type; f!=T; f=f->down) {
-                       if(f->sym->flags & SymUniq)
-                               continue;
-                       f->sym->flags |= SymUniq;
-                       sl = mal(sizeof(*sl));
-                       sl->field = f;
-                       sl->link = slist;
-                       sl->followptr = followptr;
-                       slist = sl;
-               }
-               return;
-       }
-
-       u = methtype(t, 0);
-       if(u != T) {
-               for(f=u->method; f!=T; f=f->down) {
-                       if(f->sym->flags & SymUniq)
-                               continue;
-                       f->sym->flags |= SymUniq;
-                       sl = mal(sizeof(*sl));
-                       sl->field = f;
-                       sl->link = slist;
-                       sl->followptr = followptr;
-                       slist = sl;
-               }
-       }
-}
-
-static void
-expand1(Type *t, int d, int followptr)
-{
-       Type *f, *u;
-
-       if(t->trecur)
-               return;
-       if(d == 0)
-               return;
-       t->trecur = 1;
-
-       if(d != nelem(dotlist)-1)
-               expand0(t, followptr);
-
-       u = t;
-       if(isptr[u->etype]) {
-               followptr = 1;
-               u = u->type;
-       }
-       if(u->etype != TSTRUCT && u->etype != TINTER)
-               goto out;
-
-       for(f=u->type; f!=T; f=f->down) {
-               if(!f->embedded)
-                       continue;
-               if(f->sym == S)
-                       continue;
-               expand1(f->type, d-1, followptr);
-       }
-
-out:
-       t->trecur = 0;
-}
-
-void
-expandmeth(Type *t)
-{
-       Symlink *sl;
-       Type *f;
-       int c, d;
-
-       if(t == T || t->xmethod != nil)
-               return;
-
-       // mark top-level method symbols
-       // so that expand1 doesn't consider them.
-       for(f=t->method; f != nil; f=f->down)
-               f->sym->flags |= SymUniq;
-
-       // generate all reachable methods
-       slist = nil;
-       expand1(t, nelem(dotlist)-1, 0);
-
-       // check each method to be uniquely reachable
-       for(sl=slist; sl!=nil; sl=sl->link) {
-               sl->field->sym->flags &= ~SymUniq;
-               for(d=0; d<nelem(dotlist); d++) {
-                       c = adddot1(sl->field->sym, t, d, &f, 0);
-                       if(c == 0)
-                               continue;
-                       if(c == 1) {
-                               // addot1 may have dug out arbitrary fields, we only want methods.
-                               if(f->type->etype == TFUNC && f->type->thistuple > 0) {
-                                       sl->good = 1;
-                                       sl->field = f;
-                               }
-                       }
-                       break;
-               }
-       }
-
-       for(f=t->method; f != nil; f=f->down)
-               f->sym->flags &= ~SymUniq;
-
-       t->xmethod = t->method;
-       for(sl=slist; sl!=nil; sl=sl->link) {
-               if(sl->good) {
-                       // add it to the base type method list
-                       f = typ(TFIELD);
-                       *f = *sl->field;
-                       f->embedded = 1;        // needs a trampoline
-                       if(sl->followptr)
-                               f->embedded = 2;
-                       f->down = t->xmethod;
-                       t->xmethod = f;
-               }
-       }
-}
-
-/*
- * Given funarg struct list, return list of ODCLFIELD Node fn args.
- */
-static NodeList*
-structargs(Type **tl, int mustname)
-{
-       Iter savet;
-       Node *a, *n;
-       NodeList *args;
-       Type *t;
-       char buf[100];
-       int gen;
-
-       args = nil;
-       gen = 0;
-       for(t = structfirst(&savet, tl); t != T; t = structnext(&savet)) {
-               n = N;
-               if(mustname && (t->sym == nil || strcmp(t->sym->name, "_") == 0)) {
-                       // invent a name so that we can refer to it in the trampoline
-                       snprint(buf, sizeof buf, ".anon%d", gen++);
-                       n = newname(lookup(buf));
-               } else if(t->sym)
-                       n = newname(t->sym);
-               a = nod(ODCLFIELD, n, typenod(t->type));
-               a->isddd = t->isddd;
-               if(n != N)
-                       n->isddd = t->isddd;
-               args = list(args, a);
-       }
-       return args;
-}
-
-/*
- * Generate a wrapper function to convert from
- * a receiver of type T to a receiver of type U.
- * That is,
- *
- *     func (t T) M() {
- *             ...
- *     }
- *
- * already exists; this function generates
- *
- *     func (u U) M() {
- *             u.M()
- *     }
- *
- * where the types T and U are such that u.M() is valid
- * and calls the T.M method.
- * The resulting function is for use in method tables.
- *
- *     rcvr - U
- *     method - M func (t T)(), a TFIELD type struct
- *     newnam - the eventual mangled name of this function
- */
-void
-genwrapper(Type *rcvr, Type *method, Sym *newnam, int iface)
-{
-       Node *this, *fn, *call, *n, *t, *pad, *dot, *as;
-       NodeList *l, *args, *in, *out;
-       Type *tpad, *methodrcvr;
-       int isddd;
-       Val v;
-       static int linehistdone = 0;
-
-       if(0 && debug['r'])
-               print("genwrapper rcvrtype=%T method=%T newnam=%S\n",
-                       rcvr, method, newnam);
-
-       lexlineno++;
-       lineno = lexlineno;
-       if (linehistdone == 0) {
-               // All the wrappers can share the same linehist entry.
-               linehist("<autogenerated>", 0, 0);
-               linehistdone = 1;
-       }
-
-       dclcontext = PEXTERN;
-       markdcl();
-
-       this = nod(ODCLFIELD, newname(lookup(".this")), typenod(rcvr));
-       this->left->ntype = this->right;
-       in = structargs(getinarg(method->type), 1);
-       out = structargs(getoutarg(method->type), 0);
-
-       t = nod(OTFUNC, N, N);
-       l = list1(this);
-       if(iface && rcvr->width < types[tptr]->width) {
-               // Building method for interface table and receiver
-               // is smaller than the single pointer-sized word
-               // that the interface call will pass in.
-               // Add a dummy padding argument after the
-               // receiver to make up the difference.
-               tpad = typ(TARRAY);
-               tpad->type = types[TUINT8];
-               tpad->bound = types[tptr]->width - rcvr->width;
-               pad = nod(ODCLFIELD, newname(lookup(".pad")), typenod(tpad));
-               l = list(l, pad);
-       }
-       t->list = concat(l, in);
-       t->rlist = out;
-
-       fn = nod(ODCLFUNC, N, N);
-       fn->nname = newname(newnam);
-       fn->nname->defn = fn;
-       fn->nname->ntype = t;
-       declare(fn->nname, PFUNC);
-       funchdr(fn);
-
-       // arg list
-       args = nil;
-       isddd = 0;
-       for(l=in; l; l=l->next) {
-               args = list(args, l->n->left);
-               isddd = l->n->left->isddd;
-       }
-       
-       methodrcvr = getthisx(method->type)->type->type;
-
-       // generate nil pointer check for better error
-       if(isptr[rcvr->etype] && rcvr->type == methodrcvr) {
-               // generating wrapper from *T to T.
-               n = nod(OIF, N, N);
-               n->ntest = nod(OEQ, this->left, nodnil());
-               // these strings are already in the reflect tables,
-               // so no space cost to use them here.
-               l = nil;
-               v.ctype = CTSTR;
-               v.u.sval = newstrlit(rcvr->type->sym->pkg->name);  // package name
-               l = list(l, nodlit(v));
-               v.u.sval = newstrlit(rcvr->type->sym->name);  // type name
-               l = list(l, nodlit(v));
-               v.u.sval = newstrlit(method->sym->name);
-               l = list(l, nodlit(v));  // method name
-               call = nod(OCALL, syslook("panicwrap", 0), N);
-               call->list = l;
-               n->nbody = list1(call);
-               fn->nbody = list(fn->nbody, n);
-       }
-       
-       dot = adddot(nod(OXDOT, this->left, newname(method->sym)));
-       
-       // generate call
-       if(!flag_race && isptr[rcvr->etype] && isptr[methodrcvr->etype] && method->embedded && !isifacemethod(method->type)) {
-               // generate tail call: adjust pointer receiver and jump to embedded method.
-               dot = dot->left;        // skip final .M
-               if(!isptr[dotlist[0].field->type->etype])
-                       dot = nod(OADDR, dot, N);
-               as = nod(OAS, this->left, nod(OCONVNOP, dot, N));
-               as->right->type = rcvr;
-               fn->nbody = list(fn->nbody, as);
-               n = nod(ORETJMP, N, N);
-               n->left = newname(methodsym(method->sym, methodrcvr, 0));
-               fn->nbody = list(fn->nbody, n);
-       } else {
-               fn->wrapper = 1; // ignore frame for panic+recover matching
-               call = nod(OCALL, dot, N);
-               call->list = args;
-               call->isddd = isddd;
-               if(method->type->outtuple > 0) {
-                       n = nod(ORETURN, N, N);
-                       n->list = list1(call);
-                       call = n;
-               }
-               fn->nbody = list(fn->nbody, call);
-       }
-
-       if(0 && debug['r'])
-               dumplist("genwrapper body", fn->nbody);
-
-       funcbody(fn);
-       curfn = fn;
-       // wrappers where T is anonymous (struct or interface) can be duplicated.
-       if(rcvr->etype == TSTRUCT ||
-               rcvr->etype == TINTER ||
-               isptr[rcvr->etype] && rcvr->type->etype == TSTRUCT)
-               fn->dupok = 1;
-       typecheck(&fn, Etop);
-       typechecklist(fn->nbody, Etop);
-
-       // Set inl_nonlocal to whether we are calling a method on a
-       // type defined in a different package.  Checked in inlvar.
-       if(!methodrcvr->local)
-               inl_nonlocal = 1;
-
-       inlcalls(fn);
-
-       inl_nonlocal = 0;
-
-       curfn = nil;
-       funccompile(fn);
-}
-
-static Node*
-hashmem(Type *t)
-{
-       Node *tfn, *n;
-       Sym *sym;
-
-       sym = pkglookup("memhash", runtimepkg);
-
-       n = newname(sym);
-       n->class = PFUNC;
-       tfn = nod(OTFUNC, N, N);
-       tfn->list = list(tfn->list, nod(ODCLFIELD, N, typenod(ptrto(t))));
-       tfn->list = list(tfn->list, nod(ODCLFIELD, N, typenod(types[TUINTPTR])));
-       tfn->list = list(tfn->list, nod(ODCLFIELD, N, typenod(types[TUINTPTR])));
-       tfn->rlist = list(tfn->rlist, nod(ODCLFIELD, N, typenod(types[TUINTPTR])));
-       typecheck(&tfn, Etype);
-       n->type = tfn->type;
-       return n;
-}
-
-static Node*
-hashfor(Type *t)
-{
-       int a;
-       Sym *sym;
-       Node *tfn, *n;
-
-       a = algtype1(t, nil);
-       switch(a) {
-       case AMEM:
-               fatal("hashfor with AMEM type");
-       case AINTER:
-               sym = pkglookup("interhash", runtimepkg);
-               break;
-       case ANILINTER:
-               sym = pkglookup("nilinterhash", runtimepkg);
-               break;
-       case ASTRING:
-               sym = pkglookup("strhash", runtimepkg);
-               break;
-       case AFLOAT32:
-               sym = pkglookup("f32hash", runtimepkg);
-               break;
-       case AFLOAT64:
-               sym = pkglookup("f64hash", runtimepkg);
-               break;
-       case ACPLX64:
-               sym = pkglookup("c64hash", runtimepkg);
-               break;
-       case ACPLX128:
-               sym = pkglookup("c128hash", runtimepkg);
-               break;
-       default:
-               sym = typesymprefix(".hash", t);
-               break;
-       }
-
-       n = newname(sym);
-       n->class = PFUNC;
-       tfn = nod(OTFUNC, N, N);
-       tfn->list = list(tfn->list, nod(ODCLFIELD, N, typenod(ptrto(t))));
-       tfn->list = list(tfn->list, nod(ODCLFIELD, N, typenod(types[TUINTPTR])));
-       tfn->rlist = list(tfn->rlist, nod(ODCLFIELD, N, typenod(types[TUINTPTR])));
-       typecheck(&tfn, Etype);
-       n->type = tfn->type;
-       return n;
-}
-
-/*
- * Generate a helper function to compute the hash of a value of type t.
- */
-void
-genhash(Sym *sym, Type *t)
-{
-       Node *n, *fn, *np, *nh, *ni, *call, *nx, *na, *tfn, *r;
-       Node *hashel;
-       Type *first, *t1;
-       int old_safemode;
-       int64 size, mul, offend;
-
-       if(debug['r'])
-               print("genhash %S %T\n", sym, t);
-
-       lineno = 1;  // less confusing than end of input
-       dclcontext = PEXTERN;
-       markdcl();
-
-       // func sym(p *T, h uintptr) uintptr
-       fn = nod(ODCLFUNC, N, N);
-       fn->nname = newname(sym);
-       fn->nname->class = PFUNC;
-       tfn = nod(OTFUNC, N, N);
-       fn->nname->ntype = tfn;
-
-       n = nod(ODCLFIELD, newname(lookup("p")), typenod(ptrto(t)));
-       tfn->list = list(tfn->list, n);
-       np = n->left;
-       n = nod(ODCLFIELD, newname(lookup("h")), typenod(types[TUINTPTR]));
-       tfn->list = list(tfn->list, n);
-       nh = n->left;
-       n = nod(ODCLFIELD, N, typenod(types[TUINTPTR])); // return value
-       tfn->rlist = list(tfn->rlist, n);
-
-       funchdr(fn);
-       typecheck(&fn->nname->ntype, Etype);
-
-       // genhash is only called for types that have equality but
-       // cannot be handled by the standard algorithms,
-       // so t must be either an array or a struct.
-       switch(t->etype) {
-       default:
-               fatal("genhash %T", t);
-       case TARRAY:
-               if(isslice(t))
-                       fatal("genhash %T", t);
-               // An array of pure memory would be handled by the
-               // standard algorithm, so the element type must not be
-               // pure memory.
-               hashel = hashfor(t->type);
-               n = nod(ORANGE, N, nod(OIND, np, N));
-               ni = newname(lookup("i"));
-               ni->type = types[TINT];
-               n->list = list1(ni);
-               n->colas = 1;
-               colasdefn(n->list, n);
-               ni = n->list->n;
-
-               // TODO: with aeshash we don't need these shift/mul parts
-
-               // h = h<<3 | h>>61
-               n->nbody = list(n->nbody,
-                       nod(OAS,
-                           nh,
-                               nod(OOR,
-                                       nod(OLSH, nh, nodintconst(3)),
-                                       nod(ORSH, nh, nodintconst(widthptr*8-3)))));
-
-               // h *= mul
-               // Same multipliers as in runtime.memhash.
-               if(widthptr == 4)
-                       mul = 3267000013LL;
-               else
-                       mul = 23344194077549503LL;
-               n->nbody = list(n->nbody,
-                       nod(OAS,
-                               nh,
-                               nod(OMUL, nh, nodintconst(mul))));
-
-               // h = hashel(&p[i], h)
-               call = nod(OCALL, hashel, N);
-               nx = nod(OINDEX, np, ni);
-               nx->bounded = 1;
-               na = nod(OADDR, nx, N);
-               na->etype = 1;  // no escape to heap
-               call->list = list(call->list, na);
-               call->list = list(call->list, nh);
-               n->nbody = list(n->nbody, nod(OAS, nh, call));
-
-               fn->nbody = list(fn->nbody, n);
-               break;
-
-       case TSTRUCT:
-               // Walk the struct using memhash for runs of AMEM
-               // and calling specific hash functions for the others.
-               first = T;
-               offend = 0;
-               for(t1=t->type;; t1=t1->down) {
-                       if(t1 != T && algtype1(t1->type, nil) == AMEM && !isblanksym(t1->sym)) {
-                               offend = t1->width + t1->type->width;
-                               if(first == T)
-                                       first = t1;
-                               // If it's a memory field but it's padded, stop here.
-                               if(ispaddedfield(t1, t->width))
-                                       t1 = t1->down;
-                               else
-                                       continue;
-                       }
-                       // Run memhash for fields up to this one.
-                       if(first != T) {
-                               size = offend - first->width; // first->width is offset
-                               hashel = hashmem(first->type);
-                               // h = hashel(&p.first, size, h)
-                               call = nod(OCALL, hashel, N);
-                               nx = nod(OXDOT, np, newname(first->sym));  // TODO: fields from other packages?
-                               na = nod(OADDR, nx, N);
-                               na->etype = 1;  // no escape to heap
-                               call->list = list(call->list, na);
-                               call->list = list(call->list, nh);
-                               call->list = list(call->list, nodintconst(size));
-                               fn->nbody = list(fn->nbody, nod(OAS, nh, call));
-
-                               first = T;
-                       }
-                       if(t1 == T)
-                               break;
-                       if(isblanksym(t1->sym))
-                               continue;
-
-                       // Run hash for this field.
-                       if(algtype1(t1->type, nil) == AMEM) {
-                               hashel = hashmem(t1->type);
-                               // h = memhash(&p.t1, h, size)
-                               call = nod(OCALL, hashel, N);
-                               nx = nod(OXDOT, np, newname(t1->sym));  // TODO: fields from other packages?
-                               na = nod(OADDR, nx, N);
-                               na->etype = 1;  // no escape to heap
-                               call->list = list(call->list, na);
-                               call->list = list(call->list, nh);
-                               call->list = list(call->list, nodintconst(t1->type->width));
-                               fn->nbody = list(fn->nbody, nod(OAS, nh, call));
-                       } else {
-                               hashel = hashfor(t1->type);
-                               // h = hashel(&p.t1, h)
-                               call = nod(OCALL, hashel, N);
-                               nx = nod(OXDOT, np, newname(t1->sym));  // TODO: fields from other packages?
-                               na = nod(OADDR, nx, N);
-                               na->etype = 1;  // no escape to heap
-                               call->list = list(call->list, na);
-                               call->list = list(call->list, nh);
-                               fn->nbody = list(fn->nbody, nod(OAS, nh, call));
-                       }
-               }
-               break;
-       }
-       r = nod(ORETURN, N, N);
-       r->list = list(r->list, nh);
-       fn->nbody = list(fn->nbody, r);
-
-       if(debug['r'])
-               dumplist("genhash body", fn->nbody);
-
-       funcbody(fn);
-       curfn = fn;
-       fn->dupok = 1;
-       typecheck(&fn, Etop);
-       typechecklist(fn->nbody, Etop);
-       curfn = nil;
-
-       // Disable safemode while compiling this code: the code we
-       // generate internally can refer to unsafe.Pointer.
-       // In this case it can happen if we need to generate an ==
-       // for a struct containing a reflect.Value, which itself has
-       // an unexported field of type unsafe.Pointer.
-       old_safemode = safemode;
-       safemode = 0;
-       funccompile(fn);
-       safemode = old_safemode;
-}
-
-// Return node for
-//     if p.field != q.field { return false }
-static Node*
-eqfield(Node *p, Node *q, Node *field)
-{
-       Node *nif, *nx, *ny, *r;
-
-       nx = nod(OXDOT, p, field);
-       ny = nod(OXDOT, q, field);
-       nif = nod(OIF, N, N);
-       nif->ntest = nod(ONE, nx, ny);
-       r = nod(ORETURN, N, N);
-       r->list = list(r->list, nodbool(0));
-       nif->nbody = list(nif->nbody, r);
-       return nif;
-}
-
-static Node*
-eqmemfunc(vlong size, Type *type, int *needsize)
-{
-       char buf[30];
-       Node *fn;
-
-       switch(size) {
-       default:
-               fn = syslook("memequal", 1);
-               *needsize = 1;
-               break;
-       case 1:
-       case 2:
-       case 4:
-       case 8:
-       case 16:
-               snprint(buf, sizeof buf, "memequal%d", (int)size*8);
-               fn = syslook(buf, 1);
-               *needsize = 0;
-               break;
-       }
-       argtype(fn, type);
-       argtype(fn, type);
-       return fn;
-}
-
-// Return node for
-//     if !memequal(&p.field, &q.field [, size]) { return false }
-static Node*
-eqmem(Node *p, Node *q, Node *field, vlong size)
-{
-       Node *nif, *nx, *ny, *call, *r;
-       int needsize;
-
-       nx = nod(OADDR, nod(OXDOT, p, field), N);
-       nx->etype = 1;  // does not escape
-       ny = nod(OADDR, nod(OXDOT, q, field), N);
-       ny->etype = 1;  // does not escape
-       typecheck(&nx, Erv);
-       typecheck(&ny, Erv);
-
-       call = nod(OCALL, eqmemfunc(size, nx->type->type, &needsize), N);
-       call->list = list(call->list, nx);
-       call->list = list(call->list, ny);
-       if(needsize)
-               call->list = list(call->list, nodintconst(size));
-
-       nif = nod(OIF, N, N);
-       nif->ninit = list(nif->ninit, call);
-       nif->ntest = nod(ONOT, call, N);
-       r = nod(ORETURN, N, N);
-       r->list = list(r->list, nodbool(0));
-       nif->nbody = list(nif->nbody, r);
-       return nif;
-}
-
-/*
- * Generate a helper function to check equality of two values of type t.
- */
-void
-geneq(Sym *sym, Type *t)
-{
-       Node *n, *fn, *np, *nq, *tfn, *nif, *ni, *nx, *ny, *nrange, *r;
-       Type *t1, *first;
-       int old_safemode;
-       int64 size;
-       int64 offend;
-
-       if(debug['r'])
-               print("geneq %S %T\n", sym, t);
-
-       lineno = 1;  // less confusing than end of input
-       dclcontext = PEXTERN;
-       markdcl();
-
-       // func sym(p, q *T) bool
-       fn = nod(ODCLFUNC, N, N);
-       fn->nname = newname(sym);
-       fn->nname->class = PFUNC;
-       tfn = nod(OTFUNC, N, N);
-       fn->nname->ntype = tfn;
-
-       n = nod(ODCLFIELD, newname(lookup("p")), typenod(ptrto(t)));
-       tfn->list = list(tfn->list, n);
-       np = n->left;
-       n = nod(ODCLFIELD, newname(lookup("q")), typenod(ptrto(t)));
-       tfn->list = list(tfn->list, n);
-       nq = n->left;
-       n = nod(ODCLFIELD, N, typenod(types[TBOOL]));
-       tfn->rlist = list(tfn->rlist, n);
-
-       funchdr(fn);
-
-       // geneq is only called for types that have equality but
-       // cannot be handled by the standard algorithms,
-       // so t must be either an array or a struct.
-       switch(t->etype) {
-       default:
-               fatal("geneq %T", t);
-       case TARRAY:
-               if(isslice(t))
-                       fatal("geneq %T", t);
-               // An array of pure memory would be handled by the
-               // standard memequal, so the element type must not be
-               // pure memory.  Even if we unrolled the range loop,
-               // each iteration would be a function call, so don't bother
-               // unrolling.
-               nrange = nod(ORANGE, N, nod(OIND, np, N));
-               ni = newname(lookup("i"));
-               ni->type = types[TINT];
-               nrange->list = list1(ni);
-               nrange->colas = 1;
-               colasdefn(nrange->list, nrange);
-               ni = nrange->list->n;
-               
-               // if p[i] != q[i] { return false }
-               nx = nod(OINDEX, np, ni);
-               nx->bounded = 1;
-               ny = nod(OINDEX, nq, ni);
-               ny->bounded = 1;
-
-               nif = nod(OIF, N, N);
-               nif->ntest = nod(ONE, nx, ny);
-               r = nod(ORETURN, N, N);
-               r->list = list(r->list, nodbool(0));
-               nif->nbody = list(nif->nbody, r);
-               nrange->nbody = list(nrange->nbody, nif);
-               fn->nbody = list(fn->nbody, nrange);
-               break;
-
-       case TSTRUCT:
-               // Walk the struct using memequal for runs of AMEM
-               // and calling specific equality tests for the others.
-               // Skip blank-named fields.
-               first = T;
-               offend = 0;
-               for(t1=t->type;; t1=t1->down) {
-                       if(t1 != T && algtype1(t1->type, nil) == AMEM && !isblanksym(t1->sym)) {
-                               offend = t1->width + t1->type->width;
-                               if(first == T)
-                                       first = t1;
-                               // If it's a memory field but it's padded, stop here.
-                               if(ispaddedfield(t1, t->width))
-                                       t1 = t1->down;
-                               else
-                                       continue;
-                       }
-                       // Run memequal for fields up to this one.
-                       // TODO(rsc): All the calls to newname are wrong for
-                       // cross-package unexported fields.
-                       if(first != T) {
-                               if(first->down == t1) {
-                                       fn->nbody = list(fn->nbody, eqfield(np, nq, newname(first->sym)));
-                               } else if(first->down->down == t1) {
-                                       fn->nbody = list(fn->nbody, eqfield(np, nq, newname(first->sym)));
-                                       first = first->down;
-                                       if(!isblanksym(first->sym))
-                                               fn->nbody = list(fn->nbody, eqfield(np, nq, newname(first->sym)));
-                               } else {
-                                       // More than two fields: use memequal.
-                                       size = offend - first->width; // first->width is offset
-                                       fn->nbody = list(fn->nbody, eqmem(np, nq, newname(first->sym), size));
-                               }
-                               first = T;
-                       }
-                       if(t1 == T)
-                               break;
-                       if(isblanksym(t1->sym))
-                               continue;
-
-                       // Check this field, which is not just memory.
-                       fn->nbody = list(fn->nbody, eqfield(np, nq, newname(t1->sym)));
-               }
-
-               break;
-       }
-
-       // return true
-       r = nod(ORETURN, N, N);
-       r->list = list(r->list, nodbool(1));
-       fn->nbody = list(fn->nbody, r);
-
-       if(debug['r'])
-               dumplist("geneq body", fn->nbody);
-
-       funcbody(fn);
-       curfn = fn;
-       fn->dupok = 1;
-       typecheck(&fn, Etop);
-       typechecklist(fn->nbody, Etop);
-       curfn = nil;
-       
-       // Disable safemode while compiling this code: the code we
-       // generate internally can refer to unsafe.Pointer.
-       // In this case it can happen if we need to generate an ==
-       // for a struct containing a reflect.Value, which itself has
-       // an unexported field of type unsafe.Pointer.
-       old_safemode = safemode;
-       safemode = 0;
-       funccompile(fn);
-       safemode = old_safemode;
-}
-
-static Type*
-ifacelookdot(Sym *s, Type *t, int *followptr, int ignorecase)
-{
-       int i, c, d;
-       Type *m;
-
-       *followptr = 0;
-
-       if(t == T)
-               return T;
-
-       for(d=0; d<nelem(dotlist); d++) {
-               c = adddot1(s, t, d, &m, ignorecase);
-               if(c > 1) {
-                       yyerror("%T.%S is ambiguous", t, s);
-                       return T;
-               }
-               if(c == 1) {
-                       for(i=0; i<d; i++) {
-                               if(isptr[dotlist[i].field->type->etype]) {
-                                       *followptr = 1;
-                                       break;
-                               }
-                       }
-                       if(m->type->etype != TFUNC || m->type->thistuple == 0) {
-                               yyerror("%T.%S is a field, not a method", t, s);
-                               return T;
-                       }
-                       return m;
-               }
-       }
-       return T;
-}
-
-int
-implements(Type *t, Type *iface, Type **m, Type **samename, int *ptr)
-{
-       Type *t0, *im, *tm, *rcvr, *imtype;
-       int followptr;
-
-       t0 = t;
-       if(t == T)
-               return 0;
-
-       // if this is too slow,
-       // could sort these first
-       // and then do one loop.
-
-       if(t->etype == TINTER) {
-               for(im=iface->type; im; im=im->down) {
-                       for(tm=t->type; tm; tm=tm->down) {
-                               if(tm->sym == im->sym) {
-                                       if(eqtype(tm->type, im->type))
-                                               goto found;
-                                       *m = im;
-                                       *samename = tm;
-                                       *ptr = 0;
-                                       return 0;
-                               }
-                       }
-                       *m = im;
-                       *samename = nil;
-                       *ptr = 0;
-                       return 0;
-               found:;
-               }
-               return 1;
-       }
-
-       t = methtype(t, 0);
-       if(t != T)
-               expandmeth(t);
-       for(im=iface->type; im; im=im->down) {
-               imtype = methodfunc(im->type, 0);
-               tm = ifacelookdot(im->sym, t, &followptr, 0);
-               if(tm == T || tm->nointerface || !eqtype(methodfunc(tm->type, 0), imtype)) {
-                       if(tm == T)
-                               tm = ifacelookdot(im->sym, t, &followptr, 1);
-                       *m = im;
-                       *samename = tm;
-                       *ptr = 0;
-                       return 0;
-               }
-               // if pointer receiver in method,
-               // the method does not exist for value types.
-               rcvr = getthisx(tm->type)->type->type;
-               if(isptr[rcvr->etype] && !isptr[t0->etype] && !followptr && !isifacemethod(tm->type)) {
-                       if(0 && debug['r'])
-                               yyerror("interface pointer mismatch");
-
-                       *m = im;
-                       *samename = nil;
-                       *ptr = 1;
-                       return 0;
-               }
-       }
-       return 1;
-}
-
-/*
- * even simpler simtype; get rid of ptr, bool.
- * assuming that the front end has rejected
- * all the invalid conversions (like ptr -> bool)
- */
-int
-simsimtype(Type *t)
-{
-       int et;
-
-       if(t == 0)
-               return 0;
-
-       et = simtype[t->etype];
-       switch(et) {
-       case TPTR32:
-               et = TUINT32;
-               break;
-       case TPTR64:
-               et = TUINT64;
-               break;
-       case TBOOL:
-               et = TUINT8;
-               break;
-       }
-       return et;
-}
-
-NodeList*
-concat(NodeList *a, NodeList *b)
-{
-       if(a == nil)
-               return b;
-       if(b == nil)
-               return a;
-
-       a->end->next = b;
-       a->end = b->end;
-       b->end = nil;
-       return a;
-}
-
-NodeList*
-list1(Node *n)
-{
-       NodeList *l;
-
-       if(n == nil)
-               return nil;
-       if(n->op == OBLOCK && n->ninit == nil) {
-               // Flatten list and steal storage.
-               // Poison pointer to catch errant uses.
-               l = n->list;
-               n->list = (NodeList*)1;
-               return l;
-       }
-       l = mal(sizeof *l);
-       l->n = n;
-       l->end = l;
-       return l;
-}
-
-NodeList*
-list(NodeList *l, Node *n)
-{
-       return concat(l, list1(n));
-}
-
-void
-listsort(NodeList** l, int(*f)(Node*, Node*))
-{
-       NodeList *l1, *l2, *le;
-
-       if(*l == nil || (*l)->next == nil)
-               return;
-
-       l1 = *l;
-       l2 = *l;
-       for(;;) {
-               l2 = l2->next;
-               if(l2 == nil)
-                       break;
-               l2 = l2->next;
-               if(l2 == nil)
-                       break;
-               l1 = l1->next;
-       }
-
-       l2 = l1->next;
-       l1->next = nil;
-       l2->end = (*l)->end;
-       (*l)->end = l1;
-
-       l1 = *l;
-       listsort(&l1, f);
-       listsort(&l2, f);
-
-       if((*f)(l1->n, l2->n) < 0) {
-               *l = l1;
-       } else {
-               *l = l2;
-               l2 = l1;
-               l1 = *l;
-       }
-
-       // now l1 == *l; and l1 < l2
-
-       while ((l1 != nil) && (l2 != nil)) {
-               while ((l1->next != nil) && (*f)(l1->next->n, l2->n) < 0)
-                       l1 = l1->next;
-               
-               // l1 is last one from l1 that is < l2
-               le = l1->next;          // le is the rest of l1, first one that is >= l2
-               if(le != nil)
-                       le->end = (*l)->end;
-
-               (*l)->end = l1;         // cut *l at l1
-               *l = concat(*l, l2);    // glue l2 to *l's tail
-
-               l1 = l2;                // l1 is the first element of *l that is < the new l2
-               l2 = le;                // ... because l2 now is the old tail of l1
-       }
-
-       *l = concat(*l, l2);            // any remainder 
-}
-
-NodeList*
-listtreecopy(NodeList *l)
-{
-       NodeList *out;
-
-       out = nil;
-       for(; l; l=l->next)
-               out = list(out, treecopy(l->n));
-       return out;
-}
-
-Node*
-liststmt(NodeList *l)
-{
-       Node *n;
-
-       n = nod(OBLOCK, N, N);
-       n->list = l;
-       if(l)
-               n->lineno = l->n->lineno;
-       return n;
-}
-
-/*
- * return nelem of list
- */
-int
-count(NodeList *l)
-{
-       vlong n;
-
-       n = 0;
-       for(; l; l=l->next)
-               n++;
-       if((int)n != n) { // Overflow.
-               yyerror("too many elements in list");
-       }
-       return n;
-}
-
-/*
- * return nelem of list
- */
-int
-structcount(Type *t)
-{
-       int v;
-       Iter s;
-
-       v = 0;
-       for(t = structfirst(&s, &t); t != T; t = structnext(&s))
-               v++;
-       return v;
-}
-
-/*
- * return power of 2 of the constant
- * operand. -1 if it is not a power of 2.
- * 1000+ if it is a -(power of 2)
- */
-int
-powtwo(Node *n)
-{
-       uvlong v, b;
-       int i;
-
-       if(n == N || n->op != OLITERAL || n->type == T)
-               goto no;
-       if(!isint[n->type->etype])
-               goto no;
-
-       v = mpgetfix(n->val.u.xval);
-       b = 1ULL;
-       for(i=0; i<64; i++) {
-               if(b == v)
-                       return i;
-               b = b<<1;
-       }
-
-       if(!issigned[n->type->etype])
-               goto no;
-
-       v = -v;
-       b = 1ULL;
-       for(i=0; i<64; i++) {
-               if(b == v)
-                       return i+1000;
-               b = b<<1;
-       }
-
-no:
-       return -1;
-}
-
-/*
- * return the unsigned type for
- * a signed integer type.
- * returns T if input is not a
- * signed integer type.
- */
-Type*
-tounsigned(Type *t)
-{
-
-       // this is types[et+1], but not sure
-       // that this relation is immutable
-       switch(t->etype) {
-       default:
-               print("tounsigned: unknown type %T\n", t);
-               t = T;
-               break;
-       case TINT:
-               t = types[TUINT];
-               break;
-       case TINT8:
-               t = types[TUINT8];
-               break;
-       case TINT16:
-               t = types[TUINT16];
-               break;
-       case TINT32:
-               t = types[TUINT32];
-               break;
-       case TINT64:
-               t = types[TUINT64];
-               break;
-       }
-       return t;
-}
-
-/*
- * magic number for signed division
- * see hacker's delight chapter 10
- */
-void
-smagic(Magic *m)
-{
-       int p;
-       uint64 ad, anc, delta, q1, r1, q2, r2, t;
-       uint64 mask, two31;
-
-       m->bad = 0;
-       switch(m->w) {
-       default:
-               m->bad = 1;
-               return;
-       case 8:
-               mask = 0xffLL;
-               break;
-       case 16:
-               mask = 0xffffLL;
-               break;
-       case 32:
-               mask = 0xffffffffLL;
-               break;
-       case 64:
-               mask = 0xffffffffffffffffULL;
-               break;
-       }
-       two31 = mask ^ (mask>>1);
-
-       p = m->w-1;
-       ad = m->sd;
-       if(m->sd < 0)
-               ad = -(uvlong)m->sd;
-
-       // bad denominators
-       if(ad == 0 || ad == 1 || ad == two31) {
-               m->bad = 1;
-               return;
-       }
-
-       t = two31;
-       ad &= mask;
-
-       anc = t - 1 - t%ad;
-       anc &= mask;
-
-       q1 = two31/anc;
-       r1 = two31 - q1*anc;
-       q1 &= mask;
-       r1 &= mask;
-
-       q2 = two31/ad;
-       r2 = two31 - q2*ad;
-       q2 &= mask;
-       r2 &= mask;
-
-       for(;;) {
-               p++;
-               q1 <<= 1;
-               r1 <<= 1;
-               q1 &= mask;
-               r1 &= mask;
-               if(r1 >= anc) {
-                       q1++;
-                       r1 -= anc;
-                       q1 &= mask;
-                       r1 &= mask;
-               }
-
-               q2 <<= 1;
-               r2 <<= 1;
-               q2 &= mask;
-               r2 &= mask;
-               if(r2 >= ad) {
-                       q2++;
-                       r2 -= ad;
-                       q2 &= mask;
-                       r2 &= mask;
-               }
-
-               delta = ad - r2;
-               delta &= mask;
-               if(q1 < delta || (q1 == delta && r1 == 0)) {
-                       continue;
-               }
-               break;
-       }
-
-       m->sm = q2+1;
-       if(m->sm & two31)
-               m->sm |= ~mask;
-       m->s = p-m->w;
-}
-
-/*
- * magic number for unsigned division
- * see hacker's delight chapter 10
- */
-void
-umagic(Magic *m)
-{
-       int p;
-       uint64 nc, delta, q1, r1, q2, r2;
-       uint64 mask, two31;
-
-       m->bad = 0;
-       m->ua = 0;
-
-       switch(m->w) {
-       default:
-               m->bad = 1;
-               return;
-       case 8:
-               mask = 0xffLL;
-               break;
-       case 16:
-               mask = 0xffffLL;
-               break;
-       case 32:
-               mask = 0xffffffffLL;
-               break;
-       case 64:
-               mask = 0xffffffffffffffffULL;
-               break;
-       }
-       two31 = mask ^ (mask>>1);
-
-       m->ud &= mask;
-       if(m->ud == 0 || m->ud == two31) {
-               m->bad = 1;
-               return;
-       }
-       nc = mask - (-m->ud&mask)%m->ud;
-       p = m->w-1;
-
-       q1 = two31/nc;
-       r1 = two31 - q1*nc;
-       q1 &= mask;
-       r1 &= mask;
-
-       q2 = (two31-1) / m->ud;
-       r2 = (two31-1) - q2*m->ud;
-       q2 &= mask;
-       r2 &= mask;
-
-       for(;;) {
-               p++;
-               if(r1 >= nc-r1) {
-                       q1 <<= 1;
-                       q1++;
-                       r1 <<= 1;
-                       r1 -= nc;
-               } else {
-                       q1 <<= 1;
-                       r1 <<= 1;
-               }
-               q1 &= mask;
-               r1 &= mask;
-               if(r2+1 >= m->ud-r2) {
-                       if(q2 >= two31-1) {
-                               m->ua = 1;
-                       }
-                       q2 <<= 1;
-                       q2++;
-                       r2 <<= 1;
-                       r2++;
-                       r2 -= m->ud;
-               } else {
-                       if(q2 >= two31) {
-                               m->ua = 1;
-                       }
-                       q2 <<= 1;
-                       r2 <<= 1;
-                       r2++;
-               }
-               q2 &= mask;
-               r2 &= mask;
-
-               delta = m->ud - 1 - r2;
-               delta &= mask;
-
-               if(p < m->w+m->w)
-               if(q1 < delta || (q1 == delta && r1 == 0)) {
-                       continue;
-               }
-               break;
-       }
-       m->um = q2+1;
-       m->s = p-m->w;
-}
-
-Sym*
-ngotype(Node *n)
-{
-       if(n->type != T)
-               return typenamesym(n->type);
-       return S;
-}
-
-/*
- * Convert raw string to the prefix that will be used in the symbol
- * table.  All control characters, space, '%' and '"', as well as
- * non-7-bit clean bytes turn into %xx.  The period needs escaping
- * only in the last segment of the path, and it makes for happier
- * users if we escape that as little as possible.
- *
- * If you edit this, edit ../ld/lib.c:/^pathtoprefix too.
- * If you edit this, edit ../../debug/goobj/read.go:/importPathToPrefix too.
- */
-static char*
-pathtoprefix(char *s)
-{
-       static char hex[] = "0123456789abcdef";
-       char *p, *r, *w, *l;
-       int n;
-
-       // find first character past the last slash, if any.
-       l = s;
-       for(r=s; *r; r++)
-               if(*r == '/')
-                       l = r+1;
-
-       // check for chars that need escaping
-       n = 0;
-       for(r=s; *r; r++)
-               if(*r <= ' ' || (*r == '.' && r >= l) || *r == '%' || *r == '"' || *r >= 0x7f)
-                       n++;
-
-       // quick exit
-       if(n == 0)
-               return s;
-
-       // escape
-       p = mal((r-s)+1+2*n);
-       for(r=s, w=p; *r; r++) {
-               if(*r <= ' ' || (*r == '.' && r >= l) || *r == '%' || *r == '"' || *r >= 0x7f) {
-                       *w++ = '%';
-                       *w++ = hex[(*r>>4)&0xF];
-                       *w++ = hex[*r&0xF];
-               } else
-                       *w++ = *r;
-       }
-       *w = '\0';
-       return p;
-}
-
-Pkg*
-mkpkg(Strlit *path)
-{
-       Pkg *p;
-       int h;
-
-       h = stringhash(path->s) & (nelem(phash)-1);
-       for(p=phash[h]; p; p=p->link)
-               if(p->path->len == path->len && memcmp(path->s, p->path->s, path->len) == 0)
-                       return p;
-
-       p = mal(sizeof *p);
-       p->path = path;
-       p->prefix = pathtoprefix(path->s);
-       p->link = phash[h];
-       phash[h] = p;
-       return p;
-}
-
-Strlit*
-newstrlit(char *s)
-{
-       Strlit *t;
-       
-       t = mal(sizeof *t + strlen(s));
-       strcpy(t->s, s);
-       t->len = strlen(s);
-       return t;
-}
-
-void
-addinit(Node **np, NodeList *init)
-{
-       Node *n;
-       
-       if(init == nil)
-               return;
-
-       n = *np;
-       switch(n->op) {
-       case ONAME:
-       case OLITERAL:
-               // There may be multiple refs to this node;
-               // introduce OCONVNOP to hold init list.
-               n = nod(OCONVNOP, n, N);
-               n->type = n->left->type;
-               n->typecheck = 1;
-               *np = n;
-               break;
-       }
-       n->ninit = concat(init, n->ninit);
-       n->ullman = UINF;
-}
-
-static char* reservedimports[] = {
-       "go",
-       "type",
-};
-
-int
-isbadimport(Strlit *path)
-{
-       int i;
-       char *s;
-       Rune r;
-
-       if(strlen(path->s) != path->len) {
-               yyerror("import path contains NUL");
-               return 1;
-       }
-       
-       for(i=0; i<nelem(reservedimports); i++) {
-               if(strcmp(path->s, reservedimports[i]) == 0) {
-                       yyerror("import path \"%s\" is reserved and cannot be used", path->s);
-                       return 1;
-               }
-       }
-
-       s = path->s;
-       while(*s) {
-               s += chartorune(&r, s);
-               if(r == Runeerror) {
-                       yyerror("import path contains invalid UTF-8 sequence: \"%Z\"", path);
-                       return 1;
-               }
-               if(r < 0x20 || r == 0x7f) {
-                       yyerror("import path contains control character: \"%Z\"", path);
-                       return 1;
-               }
-               if(r == '\\') {
-                       yyerror("import path contains backslash; use slash: \"%Z\"", path);
-                       return 1;
-               }
-               if(isspacerune(r)) {
-                       yyerror("import path contains space character: \"%Z\"", path);
-                       return 1;
-               }
-               if(utfrune("!\"#$%&'()*,:;<=>?[]^`{|}", r)) {
-                       yyerror("import path contains invalid character '%C': \"%Z\"", r, path);
-                       return 1;
-               }
-       }
-       return 0;
-}
-
-void
-checknil(Node *x, NodeList **init)
-{
-       Node *n;
-       
-       if(isinter(x->type)) {
-               x = nod(OITAB, x, N);
-               typecheck(&x, Erv);
-       }
-       n = nod(OCHECKNIL, x, N);
-       n->typecheck = 1;
-       *init = list(*init, n);
-}
-
-/*
- * Can this type be stored directly in an interface word?
- * Yes, if the representation is a single pointer.
- */
-int
-isdirectiface(Type *t)
-{
-       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;
-}
diff --git a/src/cmd/gc/swt.c b/src/cmd/gc/swt.c
deleted file mode 100644 (file)
index 0dc0065..0000000
+++ /dev/null
@@ -1,944 +0,0 @@
-// Copyright 2009 The Go Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style
-// license that can be found in the LICENSE file.
-
-#include       <u.h>
-#include       <libc.h>
-#include       "go.h"
-
-enum
-{
-       Snorm           = 0,
-       Strue,
-       Sfalse,
-       Stype,
-
-       Tdefault,       // default case
-       Texprconst,     // normal constant case
-       Texprvar,       // normal variable case
-       Ttypenil,       // case nil
-       Ttypeconst,     // type hashes
-       Ttypevar,       // interface type
-
-       Ncase   = 4,    // count needed to split
-};
-
-typedef        struct  Case    Case;
-struct Case
-{
-       Node*   node;           // points at case statement
-       uint32  hash;           // hash of a type switch
-       uint8   type;           // type of case
-       uint8   diag;           // suppress multiple diagnostics
-       uint16  ordinal;        // position in switch
-       Case*   link;           // linked list to link
-};
-#define        C       ((Case*)nil)
-/*c2go Case *C; */
-
-void
-dumpcase(Case *c0)
-{
-       Case *c;
-
-       for(c=c0; c!=C; c=c->link) {
-               switch(c->type) {
-               case Tdefault:
-                       print("case-default\n");
-                       print(" ord=%d\n", c->ordinal);
-                       break;
-               case Texprconst:
-                       print("case-exprconst\n");
-                       print(" ord=%d\n", c->ordinal);
-                       break;
-               case Texprvar:
-                       print("case-exprvar\n");
-                       print(" ord=%d\n", c->ordinal);
-                       print(" op=%O\n", c->node->left->op);
-                       break;
-               case Ttypenil:
-                       print("case-typenil\n");
-                       print(" ord=%d\n", c->ordinal);
-                       break;
-               case Ttypeconst:
-                       print("case-typeconst\n");
-                       print(" ord=%d\n", c->ordinal);
-                       print(" hash=%ux\n", c->hash);
-                       break;
-               case Ttypevar:
-                       print("case-typevar\n");
-                       print(" ord=%d\n", c->ordinal);
-                       break;
-               default:
-                       print("case-???\n");
-                       print(" ord=%d\n", c->ordinal);
-                       print(" op=%O\n", c->node->left->op);
-                       print(" hash=%ux\n", c->hash);
-                       break;
-               }
-       }
-       print("\n");
-}
-
-static int
-ordlcmp(Case *c1, Case *c2)
-{
-       // sort default first
-       if(c1->type == Tdefault)
-               return -1;
-       if(c2->type == Tdefault)
-               return +1;
-
-       // sort nil second
-       if(c1->type == Ttypenil)
-               return -1;
-       if(c2->type == Ttypenil)
-               return +1;
-
-       // sort by ordinal
-       if(c1->ordinal > c2->ordinal)
-               return +1;
-       if(c1->ordinal < c2->ordinal)
-               return -1;
-       return 0;
-}
-
-static int
-exprcmp(Case *c1, Case *c2)
-{
-       int ct, n;
-       Node *n1, *n2;
-
-       // sort non-constants last
-       if(c1->type != Texprconst)
-               return +1;
-       if(c2->type != Texprconst)
-               return -1;
-
-       n1 = c1->node->left;
-       n2 = c2->node->left;
-
-       // sort by type (for switches on interface)
-       ct = n1->val.ctype;
-       if(ct != n2->val.ctype)
-               return ct - n2->val.ctype;
-       if(!eqtype(n1->type, n2->type)) {
-               if(n1->type->vargen > n2->type->vargen)
-                       return +1;
-               else
-                       return -1;
-       }
-
-       // sort by constant value
-       n = 0;
-       switch(ct) {
-       case CTFLT:
-               n = mpcmpfltflt(n1->val.u.fval, n2->val.u.fval);
-               break;
-       case CTINT:
-       case CTRUNE:
-               n = mpcmpfixfix(n1->val.u.xval, n2->val.u.xval);
-               break;
-       case CTSTR:
-               n = cmpslit(n1, n2);
-               break;
-       }
-
-       return n;
-}
-
-static int
-typecmp(Case *c1, Case *c2)
-{
-
-       // sort non-constants last
-       if(c1->type != Ttypeconst)
-               return +1;
-       if(c2->type != Ttypeconst)
-               return -1;
-
-       // sort by hash code
-       if(c1->hash > c2->hash)
-               return +1;
-       if(c1->hash < c2->hash)
-               return -1;
-
-       // sort by ordinal so duplicate error
-       // happens on later case.
-       if(c1->ordinal > c2->ordinal)
-               return +1;
-       if(c1->ordinal < c2->ordinal)
-               return -1;
-       return 0;
-}
-
-static Case*
-csort(Case *l, int(*f)(Case*, Case*))
-{
-       Case *l1, *l2, *le;
-
-       if(l == C || l->link == C)
-               return l;
-
-       l1 = l;
-       l2 = l;
-       for(;;) {
-               l2 = l2->link;
-               if(l2 == C)
-                       break;
-               l2 = l2->link;
-               if(l2 == C)
-                       break;
-               l1 = l1->link;
-       }
-
-       l2 = l1->link;
-       l1->link = C;
-       l1 = csort(l, f);
-       l2 = csort(l2, f);
-
-       /* set up lead element */
-       if((*f)(l1, l2) < 0) {
-               l = l1;
-               l1 = l1->link;
-       } else {
-               l = l2;
-               l2 = l2->link;
-       }
-       le = l;
-
-       for(;;) {
-               if(l1 == C) {
-                       while(l2) {
-                               le->link = l2;
-                               le = l2;
-                               l2 = l2->link;
-                       }
-                       le->link = C;
-                       break;
-               }
-               if(l2 == C) {
-                       while(l1) {
-                               le->link = l1;
-                               le = l1;
-                               l1 = l1->link;
-                       }
-                       break;
-               }
-               if((*f)(l1, l2) < 0) {
-                       le->link = l1;
-                       le = l1;
-                       l1 = l1->link;
-               } else {
-                       le->link = l2;
-                       le = l2;
-                       l2 = l2->link;
-               }
-       }
-       le->link = C;
-       return l;
-}
-
-static Node*
-newlabel(void)
-{
-       static int label;
-
-       label++;
-       snprint(namebuf, sizeof(namebuf), "%.6d", label);
-       return newname(lookup(namebuf));
-}
-
-/*
- * build separate list of statements and cases
- * make labels between cases and statements
- * deal with fallthrough, break, unreachable statements
- */
-static void
-casebody(Node *sw, Node *typeswvar)
-{
-       Node *n, *c, *last;
-       Node *def;
-       NodeList *cas, *stat, *l, *lc;
-       Node *go, *br;
-       int32 lno, needvar;
-
-       if(sw->list == nil)
-               return;
-
-       lno = setlineno(sw);
-
-       cas = nil;      // cases
-       stat = nil;     // statements
-       def = N;        // defaults
-       br = nod(OBREAK, N, N);
-
-       for(l=sw->list; l; l=l->next) {
-               n = l->n;
-               setlineno(n);
-               if(n->op != OXCASE)
-                       fatal("casebody %O", n->op);
-               n->op = OCASE;
-               needvar = count(n->list) != 1 || n->list->n->op == OLITERAL;
-
-               go = nod(OGOTO, newlabel(), N);
-               if(n->list == nil) {
-                       if(def != N)
-                               yyerror("more than one default case");
-                       // reuse original default case
-                       n->right = go;
-                       def = n;
-               }
-
-               if(n->list != nil && n->list->next == nil) {
-                       // one case - reuse OCASE node.
-                       c = n->list->n;
-                       n->left = c;
-                       n->right = go;
-                       n->list = nil;
-                       cas = list(cas, n);
-               } else {
-                       // expand multi-valued cases
-                       for(lc=n->list; lc; lc=lc->next) {
-                               c = lc->n;
-                               cas = list(cas, nod(OCASE, c, go));
-                       }
-               }
-
-               stat = list(stat, nod(OLABEL, go->left, N));
-               if(typeswvar && needvar && n->nname != N) {
-                       NodeList *l;
-
-                       l = list1(nod(ODCL, n->nname, N));
-                       l = list(l, nod(OAS, n->nname, typeswvar));
-                       typechecklist(l, Etop);
-                       stat = concat(stat, l);
-               }
-               stat = concat(stat, n->nbody);
-
-               // botch - shouldn't fall thru declaration
-               last = stat->end->n;
-               if(last->xoffset == n->xoffset && last->op == OXFALL) {
-                       if(typeswvar) {
-                               setlineno(last);
-                               yyerror("cannot fallthrough in type switch");
-                       }
-                       if(l->next == nil) {
-                               setlineno(last);
-                               yyerror("cannot fallthrough final case in switch");
-                       }
-                       last->op = OFALL;
-               } else
-                       stat = list(stat, br);
-       }
-
-       stat = list(stat, br);
-       if(def)
-               cas = list(cas, def);
-
-       sw->list = cas;
-       sw->nbody = stat;
-       lineno = lno;
-}
-
-static Case*
-mkcaselist(Node *sw, int arg)
-{
-       Node *n;
-       Case *c, *c1, *c2;
-       NodeList *l;
-       int ord;
-
-       c = C;
-       ord = 0;
-
-       for(l=sw->list; l; l=l->next) {
-               n = l->n;
-               c1 = mal(sizeof(*c1));
-               c1->link = c;
-               c = c1;
-
-               ord++;
-               if((uint16)ord != ord)
-                       fatal("too many cases in switch");
-               c->ordinal = ord;
-               c->node = n;
-
-               if(n->left == N) {
-                       c->type = Tdefault;
-                       continue;
-               }
-
-               switch(arg) {
-               case Stype:
-                       c->hash = 0;
-                       if(n->left->op == OLITERAL) {
-                               c->type = Ttypenil;
-                               continue;
-                       }
-                       if(istype(n->left->type, TINTER)) {
-                               c->type = Ttypevar;
-                               continue;
-                       }
-
-                       c->hash = typehash(n->left->type);
-                       c->type = Ttypeconst;
-                       continue;
-
-               case Snorm:
-               case Strue:
-               case Sfalse:
-                       c->type = Texprvar;
-                       c->hash = typehash(n->left->type);
-                       switch(consttype(n->left)) {
-                       case CTFLT:
-                       case CTINT:
-                       case CTRUNE:
-                       case CTSTR:
-                               c->type = Texprconst;
-                       }
-                       continue;
-               }
-       }
-
-       if(c == C)
-               return C;
-
-       // sort by value and diagnose duplicate cases
-       switch(arg) {
-       case Stype:
-               c = csort(c, typecmp);
-               for(c1=c; c1!=C; c1=c1->link) {
-                       for(c2=c1->link; c2!=C && c2->hash==c1->hash; c2=c2->link) {
-                               if(c1->type == Ttypenil || c1->type == Tdefault)
-                                       break;
-                               if(c2->type == Ttypenil || c2->type == Tdefault)
-                                       break;
-                               if(!eqtype(c1->node->left->type, c2->node->left->type))
-                                       continue;
-                               yyerrorl(c2->node->lineno, "duplicate case %T in type switch\n\tprevious case at %L", c2->node->left->type, c1->node->lineno);
-                       }
-               }
-               break;
-       case Snorm:
-       case Strue:
-       case Sfalse:
-               c = csort(c, exprcmp);
-               for(c1=c; c1->link!=C; c1=c1->link) {
-                       if(exprcmp(c1, c1->link) != 0)
-                               continue;
-                       setlineno(c1->link->node);
-                       yyerror("duplicate case %N in switch\n\tprevious case at %L", c1->node->left, c1->node->lineno);
-               }
-               break;
-       }
-
-       // put list back in processing order
-       c = csort(c, ordlcmp);
-       return c;
-}
-
-static Node*   exprname;
-
-static Node*
-exprbsw(Case *c0, int ncase, int arg)
-{
-       NodeList *cas;
-       Node *a, *n;
-       Case *c;
-       int i, half, lno;
-
-       cas = nil;
-       if(ncase < Ncase) {
-               for(i=0; i<ncase; i++) {
-                       n = c0->node;
-                       lno = setlineno(n);
-
-                       if((arg != Strue && arg != Sfalse) ||
-                          assignop(n->left->type, exprname->type, nil) == OCONVIFACE ||
-                          assignop(exprname->type, n->left->type, nil) == OCONVIFACE) {
-                               a = nod(OIF, N, N);
-                               a->ntest = nod(OEQ, exprname, n->left); // if name == val
-                               typecheck(&a->ntest, Erv);
-                               a->nbody = list1(n->right);                     // then goto l
-                       } else if(arg == Strue) {
-                               a = nod(OIF, N, N);
-                               a->ntest = n->left;                     // if val
-                               a->nbody = list1(n->right);                     // then goto l
-                       } else { // arg == Sfalse
-                               a = nod(OIF, N, N);
-                               a->ntest = nod(ONOT, n->left, N);       // if !val
-                               typecheck(&a->ntest, Erv);
-                               a->nbody = list1(n->right);                     // then goto l
-                       }
-
-                       cas = list(cas, a);
-                       c0 = c0->link;
-                       lineno = lno;
-               }
-               return liststmt(cas);
-       }
-
-       // find the middle and recur
-       c = c0;
-       half = ncase>>1;
-       for(i=1; i<half; i++)
-               c = c->link;
-       a = nod(OIF, N, N);
-       a->ntest = nod(OLE, exprname, c->node->left);
-       typecheck(&a->ntest, Erv);
-       a->nbody = list1(exprbsw(c0, half, arg));
-       a->nelse = list1(exprbsw(c->link, ncase-half, arg));
-       return a;
-}
-
-/*
- * normal (expression) switch.
- * rebuild case statements into if .. goto
- */
-static void
-exprswitch(Node *sw)
-{
-       Node *def;
-       NodeList *cas;
-       Node *a;
-       Case *c0, *c, *c1;
-       Type *t;
-       int arg, ncase;
-
-       casebody(sw, N);
-
-       arg = Snorm;
-       if(isconst(sw->ntest, CTBOOL)) {
-               arg = Strue;
-               if(sw->ntest->val.u.bval == 0)
-                       arg = Sfalse;
-       }
-       walkexpr(&sw->ntest, &sw->ninit);
-       t = sw->type;
-       if(t == T)
-               return;
-
-       /*
-        * convert the switch into OIF statements
-        */
-       exprname = N;
-       cas = nil;
-       if(arg == Strue || arg == Sfalse)
-               exprname = nodbool(arg == Strue);
-       else if(consttype(sw->ntest) >= 0)
-               // leave constants to enable dead code elimination (issue 9608)
-               exprname = sw->ntest;
-       else {
-               exprname = temp(sw->ntest->type);
-               cas = list1(nod(OAS, exprname, sw->ntest));
-               typechecklist(cas, Etop);
-       }
-
-       c0 = mkcaselist(sw, arg);
-       if(c0 != C && c0->type == Tdefault) {
-               def = c0->node->right;
-               c0 = c0->link;
-       } else {
-               def = nod(OBREAK, N, N);
-       }
-
-loop:
-       if(c0 == C) {
-               cas = list(cas, def);
-               sw->nbody = concat(cas, sw->nbody);
-               sw->list = nil;
-               walkstmtlist(sw->nbody);
-               return;
-       }
-
-       // deal with the variables one-at-a-time
-       if(!okforcmp[t->etype] || c0->type != Texprconst) {
-               a = exprbsw(c0, 1, arg);
-               cas = list(cas, a);
-               c0 = c0->link;
-               goto loop;
-       }
-
-       // do binary search on run of constants
-       ncase = 1;
-       for(c=c0; c->link!=C; c=c->link) {
-               if(c->link->type != Texprconst)
-                       break;
-               ncase++;
-       }
-
-       // break the chain at the count
-       c1 = c->link;
-       c->link = C;
-
-       // sort and compile constants
-       c0 = csort(c0, exprcmp);
-       a = exprbsw(c0, ncase, arg);
-       cas = list(cas, a);
-
-       c0 = c1;
-       goto loop;
-
-}
-
-static Node*   hashname;
-static Node*   facename;
-static Node*   boolname;
-
-static Node*
-typeone(Node *t)
-{
-       NodeList *init;
-       Node *a, *b, *var;
-
-       var = t->nname;
-       init = nil;
-       if(var == N) {
-               typecheck(&nblank, Erv | Easgn);
-               var = nblank;
-       } else
-               init = list1(nod(ODCL, var, N));
-
-       a = nod(OAS2, N, N);
-       a->list = list(list1(var), boolname);   // var,bool =
-       b = nod(ODOTTYPE, facename, N);
-       b->type = t->left->type;                // interface.(type)
-       a->rlist = list1(b);
-       typecheck(&a, Etop);
-       init = list(init, a);
-
-       b = nod(OIF, N, N);
-       b->ntest = boolname;
-       b->nbody = list1(t->right);             // if bool { goto l }
-       a = liststmt(list(init, b));
-       return a;
-}
-
-static Node*
-typebsw(Case *c0, int ncase)
-{
-       NodeList *cas;
-       Node *a, *n;
-       Case *c;
-       int i, half;
-
-       cas = nil;
-
-       if(ncase < Ncase) {
-               for(i=0; i<ncase; i++) {
-                       n = c0->node;
-                       if(c0->type != Ttypeconst)
-                               fatal("typebsw");
-                       a = nod(OIF, N, N);
-                       a->ntest = nod(OEQ, hashname, nodintconst(c0->hash));
-                       typecheck(&a->ntest, Erv);
-                       a->nbody = list1(n->right);
-                       cas = list(cas, a);
-                       c0 = c0->link;
-               }
-               return liststmt(cas);
-       }
-
-       // find the middle and recur
-       c = c0;
-       half = ncase>>1;
-       for(i=1; i<half; i++)
-               c = c->link;
-       a = nod(OIF, N, N);
-       a->ntest = nod(OLE, hashname, nodintconst(c->hash));
-       typecheck(&a->ntest, Erv);
-       a->nbody = list1(typebsw(c0, half));
-       a->nelse = list1(typebsw(c->link, ncase-half));
-       return a;
-}
-
-/*
- * convert switch of the form
- *     switch v := i.(type) { case t1: ..; case t2: ..; }
- * into if statements
- */
-static void
-typeswitch(Node *sw)
-{
-       Node *def;
-       NodeList *cas, *hash;
-       Node *a, *n;
-       Case *c, *c0, *c1;
-       int ncase;
-       Type *t;
-       Val v;
-
-       if(sw->ntest == nil)
-               return;
-       if(sw->ntest->right == nil) {
-               setlineno(sw);
-               yyerror("type switch must have an assignment");
-               return;
-       }
-       walkexpr(&sw->ntest->right, &sw->ninit);
-       if(!istype(sw->ntest->right->type, TINTER)) {
-               yyerror("type switch must be on an interface");
-               return;
-       }
-       cas = nil;
-
-       /*
-        * predeclare temporary variables
-        * and the boolean var
-        */
-       facename = temp(sw->ntest->right->type);
-       a = nod(OAS, facename, sw->ntest->right);
-       typecheck(&a, Etop);
-       cas = list(cas, a);
-
-       casebody(sw, facename);
-
-       boolname = temp(types[TBOOL]);
-       typecheck(&boolname, Erv);
-
-       hashname = temp(types[TUINT32]);
-       typecheck(&hashname, Erv);
-
-       t = sw->ntest->right->type;
-       if(isnilinter(t))
-               a = syslook("efacethash", 1);
-       else
-               a = syslook("ifacethash", 1);
-       argtype(a, t);
-       a = nod(OCALL, a, N);
-       a->list = list1(facename);
-       a = nod(OAS, hashname, a);
-       typecheck(&a, Etop);
-       cas = list(cas, a);
-
-       c0 = mkcaselist(sw, Stype);
-       if(c0 != C && c0->type == Tdefault) {
-               def = c0->node->right;
-               c0 = c0->link;
-       } else {
-               def = nod(OBREAK, N, N);
-       }
-       
-       /*
-        * insert if statement into each case block
-        */
-       for(c=c0; c!=C; c=c->link) {
-               n = c->node;
-               switch(c->type) {
-
-               case Ttypenil:
-                       v.ctype = CTNIL;
-                       a = nod(OIF, N, N);
-                       a->ntest = nod(OEQ, facename, nodlit(v));
-                       typecheck(&a->ntest, Erv);
-                       a->nbody = list1(n->right);             // if i==nil { goto l }
-                       n->right = a;
-                       break;
-               
-               case Ttypevar:
-               case Ttypeconst:
-                       n->right = typeone(n);
-                       break;
-               }
-       }
-
-       /*
-        * generate list of if statements, binary search for constant sequences
-        */
-       while(c0 != C) {
-               if(c0->type != Ttypeconst) {
-                       n = c0->node;
-                       cas = list(cas, n->right);
-                       c0=c0->link;
-                       continue;
-               }
-               
-               // identify run of constants
-               c1 = c = c0;
-               while(c->link!=C && c->link->type==Ttypeconst)
-                       c = c->link;
-               c0 = c->link;
-               c->link = nil;
-
-               // sort by hash
-               c1 = csort(c1, typecmp);
-               
-               // for debugging: linear search
-               if(0) {
-                       for(c=c1; c!=C; c=c->link) {
-                               n = c->node;
-                               cas = list(cas, n->right);
-                       }
-                       continue;
-               }
-
-               // combine adjacent cases with the same hash
-               ncase = 0;
-               for(c=c1; c!=C; c=c->link) {
-                       ncase++;
-                       hash = list1(c->node->right);
-                       while(c->link != C && c->link->hash == c->hash) {
-                               hash = list(hash, c->link->node->right);
-                               c->link = c->link->link;
-                       }
-                       c->node->right = liststmt(hash);
-               }
-               
-               // binary search among cases to narrow by hash
-               cas = list(cas, typebsw(c1, ncase));
-       }
-       if(nerrors == 0) {
-               cas = list(cas, def);
-               sw->nbody = concat(cas, sw->nbody);
-               sw->list = nil;
-               walkstmtlist(sw->nbody);
-       }
-}
-
-void
-walkswitch(Node *sw)
-{
-       /*
-        * reorder the body into (OLIST, cases, statements)
-        * cases have OGOTO into statements.
-        * both have inserted OBREAK statements
-        */
-       if(sw->ntest == N) {
-               sw->ntest = nodbool(1);
-               typecheck(&sw->ntest, Erv);
-       }
-
-       if(sw->ntest->op == OTYPESW) {
-               typeswitch(sw);
-//dump("sw", sw);
-               return;
-       }
-       exprswitch(sw);
-       // Discard old AST elements after a walk. They can confuse racewealk.
-       sw->ntest = nil;
-       sw->list = nil;
-}
-
-/*
- * type check switch statement
- */
-void
-typecheckswitch(Node *n)
-{
-       int top, lno, ptr;
-       char *nilonly;
-       Type *t, *badtype, *missing, *have;
-       NodeList *l, *ll;
-       Node *ncase, *nvar;
-       Node *def;
-
-       lno = lineno;
-       typechecklist(n->ninit, Etop);
-       nilonly = nil;
-
-       if(n->ntest != N && n->ntest->op == OTYPESW) {
-               // type switch
-               top = Etype;
-               typecheck(&n->ntest->right, Erv);
-               t = n->ntest->right->type;
-               if(t != T && t->etype != TINTER)
-                       yyerror("cannot type switch on non-interface value %lN", n->ntest->right);
-       } else {
-               // value switch
-               top = Erv;
-               if(n->ntest) {
-                       typecheck(&n->ntest, Erv);
-                       defaultlit(&n->ntest, T);
-                       t = n->ntest->type;
-               } else
-                       t = types[TBOOL];
-               if(t) {
-                       if(!okforeq[t->etype])
-                               yyerror("cannot switch on %lN", n->ntest);
-                       else if(t->etype == TARRAY && !isfixedarray(t))
-                               nilonly = "slice";
-                       else if(t->etype == TARRAY && isfixedarray(t) && algtype1(t, nil) == ANOEQ)
-                               yyerror("cannot switch on %lN", n->ntest);
-                       else if(t->etype == TSTRUCT && algtype1(t, &badtype) == ANOEQ)
-                               yyerror("cannot switch on %lN (struct containing %T cannot be compared)", n->ntest, badtype);
-                       else if(t->etype == TFUNC)
-                               nilonly = "func";
-                       else if(t->etype == TMAP)
-                               nilonly = "map";
-               }
-       }
-       n->type = t;
-
-       def = N;
-       for(l=n->list; l; l=l->next) {
-               ncase = l->n;
-               setlineno(n);
-               if(ncase->list == nil) {
-                       // default
-                       if(def != N)
-                               yyerror("multiple defaults in switch (first at %L)", def->lineno);
-                       else
-                               def = ncase;
-               } else {
-                       for(ll=ncase->list; ll; ll=ll->next) {
-                               setlineno(ll->n);
-                               typecheck(&ll->n, Erv | Etype);
-                               if(ll->n->type == T || t == T)
-                                       continue;
-                               setlineno(ncase);
-                               switch(top) {
-                               case Erv:       // expression switch
-                                       defaultlit(&ll->n, t);
-                                       if(ll->n->op == OTYPE)
-                                               yyerror("type %T is not an expression", ll->n->type);
-                                       else if(ll->n->type != T && !assignop(ll->n->type, t, nil) && !assignop(t, ll->n->type, nil)) {
-                                               if(n->ntest)
-                                                       yyerror("invalid case %N in switch on %N (mismatched types %T and %T)", ll->n, n->ntest, ll->n->type, t);
-                                               else
-                                                       yyerror("invalid case %N in switch (mismatched types %T and bool)", ll->n, ll->n->type);
-                                       } else if(nilonly && !isconst(ll->n, CTNIL)) {
-                                               yyerror("invalid case %N in switch (can only compare %s %N to nil)", ll->n, nilonly, n->ntest);
-                                       }
-                                       break;
-                               case Etype:     // type switch
-                                       if(ll->n->op == OLITERAL && istype(ll->n->type, TNIL)) {
-                                               ;
-                                       } else if(ll->n->op != OTYPE && ll->n->type != T) {  // should this be ||?
-                                               yyerror("%lN is not a type", ll->n);
-                                               // reset to original type
-                                               ll->n = n->ntest->right;
-                                       } else if(ll->n->type->etype != TINTER && t->etype == TINTER && !implements(ll->n->type, t, &missing, &have, &ptr)) {
-                                               if(have && !missing->broke && !have->broke)
-                                                       yyerror("impossible type switch case: %lN cannot have dynamic type %T"
-                                                               " (wrong type for %S method)\n\thave %S%hT\n\twant %S%hT",
-                                                               n->ntest->right, ll->n->type, missing->sym, have->sym, have->type,
-                                                               missing->sym, missing->type);
-                                               else if(!missing->broke)
-                                                       yyerror("impossible type switch case: %lN cannot have dynamic type %T"
-                                                               " (missing %S method)", n->ntest->right, ll->n->type, missing->sym);
-                                       }
-                                       break;
-                               }
-                       }
-               }
-               if(top == Etype && n->type != T) {
-                       ll = ncase->list;
-                       nvar = ncase->nname;
-                       if(nvar != N) {
-                               if(ll && ll->next == nil && ll->n->type != T && !istype(ll->n->type, TNIL)) {
-                                       // single entry type switch
-                                       nvar->ntype = typenod(ll->n->type);
-                               } else {
-                                       // multiple entry type switch or default
-                                       nvar->ntype = typenod(n->type);
-                               }
-                               typecheck(&nvar, Erv | Easgn);
-                               ncase->nname = nvar;
-                       }
-               }
-               typechecklist(ncase->nbody, Etop);
-       }
-
-       lineno = lno;
-}
diff --git a/src/cmd/gc/typecheck.c b/src/cmd/gc/typecheck.c
deleted file mode 100644 (file)
index 649f1c5..0000000
+++ /dev/null
@@ -1,3649 +0,0 @@
-// Copyright 2009 The Go Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style
-// license that can be found in the LICENSE file.
-
-/*
- * type check the whole tree of an expression.
- * calculates expression types.
- * evaluates compile time constants.
- * marks variables that escape the local frame.
- * rewrites n->op to be more specific in some cases.
- */
-
-#include <u.h>
-#include <libc.h>
-#include "go.h"
-
-static void    implicitstar(Node**);
-static int     onearg(Node*, char*, ...);
-static int     twoarg(Node*);
-static int     lookdot(Node*, Type*, int);
-static int     looktypedot(Node*, Type*, int);
-static void    typecheckaste(int, Node*, int, Type*, NodeList*, char*);
-static Type*   lookdot1(Node*, Sym *s, Type *t, Type *f, int);
-static int     nokeys(NodeList*);
-static void    typecheckcomplit(Node**);
-static void    typecheckas2(Node*);
-static void    typecheckas(Node*);
-static void    typecheckfunc(Node*);
-static void    checklvalue(Node*, char*);
-static void    checkassignlist(Node*, NodeList*);
-static void    stringtoarraylit(Node**);
-static Node*   resolve(Node*);
-static void    checkdefergo(Node*);
-static int     checkmake(Type*, char*, Node*);
-static int     checksliceindex(Node*, Node*, Type*);
-static int     checksliceconst(Node*, Node*);
-
-static NodeList*       typecheckdefstack;
-
-/*
- * resolve ONONAME to definition, if any.
- */
-static Node*
-resolve(Node *n)
-{
-       Node *r;
-
-       if(n != N && n->op == ONONAME && n->sym != S && (r = n->sym->def) != N) {
-               if(r->op != OIOTA)
-                       n = r;
-               else if(n->iota >= 0)
-                       n = nodintconst(n->iota);
-       }
-       return n;
-}
-
-void
-typechecklist(NodeList *l, int top)
-{
-       for(; l; l=l->next)
-               typecheck(&l->n, top);
-}
-
-static char* _typekind[] = {
-       [TINT]          = "int",
-       [TUINT]         = "uint",
-       [TINT8]         = "int8",
-       [TUINT8]        = "uint8",
-       [TINT16]        = "int16",
-       [TUINT16]       = "uint16",
-       [TINT32]        = "int32",
-       [TUINT32]       = "uint32",
-       [TINT64]        = "int64",
-       [TUINT64]       = "uint64",
-       [TUINTPTR]      = "uintptr",
-       [TCOMPLEX64]    = "complex64",
-       [TCOMPLEX128]   = "complex128",
-       [TFLOAT32]      = "float32",
-       [TFLOAT64]      = "float64",
-       [TBOOL]         = "bool",
-       [TSTRING]       = "string",
-       [TPTR32]        = "pointer",
-       [TPTR64]        = "pointer",
-       [TUNSAFEPTR]    = "unsafe.Pointer",
-       [TSTRUCT]       = "struct",
-       [TINTER]        = "interface",
-       [TCHAN]         = "chan",
-       [TMAP]          = "map",
-       [TARRAY]        = "array",
-       [TFUNC]         = "func",
-       [TNIL]          = "nil",
-       [TIDEAL]        = "untyped number",
-};
-
-static char*
-typekind(Type *t)
-{
-       int et;
-       static char buf[50];
-       char *s;
-       
-       if(isslice(t))
-               return "slice";
-       et = t->etype;
-       if(0 <= et && et < nelem(_typekind) && (s=_typekind[et]) != nil)
-               return s;
-       snprint(buf, sizeof buf, "etype=%d", et);
-       return buf;
-}
-
-/*
- * sprint_depchain prints a dependency chain
- * of nodes into fmt.
- * It is used by typecheck in the case of OLITERAL nodes
- * to print constant definition loops.
- */
-static void
-sprint_depchain(Fmt *fmt, NodeList *stack, Node *cur, Node *first)
-{
-       NodeList *l;
-
-       for(l = stack; l; l=l->next) {
-               if(l->n->op == cur->op) {
-                       if(l->n != first)
-                               sprint_depchain(fmt, l->next, l->n, first);
-                       fmtprint(fmt, "\n\t%L: %N uses %N", l->n->lineno, l->n, cur);
-                       return;
-               }
-       }
-}
-
-/*
- * type check node *np.
- * replaces *np with a new pointer in some cases.
- * returns the final value of *np as a convenience.
- */
-static void typecheck1(Node **, int);
-Node*
-typecheck(Node **np, int top)
-{
-       Node *n;
-       int lno;
-       Fmt fmt;
-       NodeList *l;
-       static NodeList *tcstack, *tcfree;
-
-       // cannot type check until all the source has been parsed
-       if(!typecheckok)
-               fatal("early typecheck");
-
-       n = *np;
-       if(n == N)
-               return N;
-       
-       lno = setlineno(n);
-
-       // Skip over parens.
-       while(n->op == OPAREN)
-               n = n->left;
-
-       // Resolve definition of name and value of iota lazily.
-       n = resolve(n);
-
-       *np = n;
-
-       // Skip typecheck if already done.
-       // But re-typecheck ONAME/OTYPE/OLITERAL/OPACK node in case context has changed.
-       if(n->typecheck == 1) {
-               switch(n->op) {
-               case ONAME:
-               case OTYPE:
-               case OLITERAL:
-               case OPACK:
-                       break;
-               default:
-                       lineno = lno;
-                       return n;
-               }
-       }
-
-       if(n->typecheck == 2) {
-               // Typechecking loop. Trying printing a meaningful message,
-               // otherwise a stack trace of typechecking.
-               switch(n->op) {
-               case ONAME:
-                       // We can already diagnose variables used as types.
-                       if((top & (Erv|Etype)) == Etype)
-                               yyerror("%N is not a type", n);
-                       break;
-               case OLITERAL:
-                       if((top & (Erv|Etype)) == Etype) {
-                               yyerror("%N is not a type", n);
-                               break;
-                       }
-                       fmtstrinit(&fmt);
-                       sprint_depchain(&fmt, tcstack, n, n);
-                       yyerrorl(n->lineno, "constant definition loop%s", fmtstrflush(&fmt));
-                       break;
-               }
-               if(nsavederrors+nerrors == 0) {
-                       fmtstrinit(&fmt);
-                       for(l=tcstack; l; l=l->next)
-                               fmtprint(&fmt, "\n\t%L %N", l->n->lineno, l->n);
-                       yyerror("typechecking loop involving %N%s", n, fmtstrflush(&fmt));
-               }
-               lineno = lno;
-               return n;
-       }
-       n->typecheck = 2;
-
-       if(tcfree != nil) {
-               l = tcfree;
-               tcfree = l->next;
-       } else
-               l = mal(sizeof *l);
-       l->next = tcstack;
-       l->n = n;
-       tcstack = l;
-
-       typecheck1(&n, top);
-       *np = n;
-       n->typecheck = 1;
-
-       if(tcstack != l)
-               fatal("typecheck stack out of sync");
-       tcstack = l->next;
-       l->next = tcfree;
-       tcfree = l;
-
-       lineno = lno;
-       return n;
-}
-
-/*
- * does n contain a call or receive operation?
- */
-static int callrecvlist(NodeList*);
-
-static int
-callrecv(Node *n)
-{
-       if(n == nil)
-               return 0;
-       
-       switch(n->op) {
-       case OCALL:
-       case OCALLMETH:
-       case OCALLINTER:
-       case OCALLFUNC:
-       case ORECV:
-       case OCAP:
-       case OLEN:
-       case OCOPY:
-       case ONEW:
-       case OAPPEND:
-       case ODELETE:
-               return 1;
-       }
-
-       return callrecv(n->left) ||
-               callrecv(n->right) ||
-               callrecv(n->ntest) ||
-               callrecv(n->nincr) ||
-               callrecvlist(n->ninit) ||
-               callrecvlist(n->nbody) ||
-               callrecvlist(n->nelse) ||
-               callrecvlist(n->list) ||
-               callrecvlist(n->rlist);
-}
-
-static int
-callrecvlist(NodeList *l)
-{
-       for(; l; l=l->next)
-               if(callrecv(l->n))
-                       return 1;
-       return 0;
-}
-
-// indexlit implements typechecking of untyped values as
-// array/slice indexes. It is equivalent to defaultlit
-// except for constants of numerical kind, which are acceptable
-// whenever they can be represented by a value of type int.
-static void
-indexlit(Node **np)
-{
-       Node *n;
-
-       n = *np;
-       if(n == N || !isideal(n->type))
-               return;
-       switch(consttype(n)) {
-       case CTINT:
-       case CTRUNE:
-       case CTFLT:
-       case CTCPLX:
-               defaultlit(np, types[TINT]);
-               break;
-       }
-       defaultlit(np, T);
-}
-
-static void
-typecheck1(Node **np, int top)
-{
-       int et, aop, op, ptr;
-       Node *n, *l, *r, *lo, *mid, *hi;
-       NodeList *args;
-       int ok, ntop;
-       Type *t, *tp, *missing, *have, *badtype;
-       Val v;
-       char *why, *desc, descbuf[64];
-       vlong x;
-       
-       n = *np;
-
-       if(n->sym) {
-               if(n->op == ONAME && n->etype != 0 && !(top & Ecall)) {
-                       yyerror("use of builtin %S not in function call", n->sym);
-                       goto error;
-               }
-
-               typecheckdef(n);
-               if(n->op == ONONAME)
-                       goto error;
-       }
-       *np = n;
-
-reswitch:
-       ok = 0;
-       switch(n->op) {
-       default:
-               // until typecheck is complete, do nothing.
-               dump("typecheck", n);
-               fatal("typecheck %O", n->op);
-
-       /*
-        * names
-        */
-       case OLITERAL:
-               ok |= Erv;
-               if(n->type == T && n->val.ctype == CTSTR)
-                       n->type = idealstring;
-               goto ret;
-
-       case ONONAME:
-               ok |= Erv;
-               goto ret;
-
-       case ONAME:
-               if(n->decldepth == 0)
-                       n->decldepth = decldepth;
-               if(n->etype != 0) {
-                       ok |= Ecall;
-                       goto ret;
-               }
-               if(!(top & Easgn)) {
-                       // not a write to the variable
-                       if(isblank(n)) {
-                               yyerror("cannot use _ as value");
-                               goto error;
-                       }
-                       n->used = 1;
-               }
-               if(!(top &Ecall) && isunsafebuiltin(n)) {
-                       yyerror("%N is not an expression, must be called", n);
-                       goto error;
-               }
-               ok |= Erv;
-               goto ret;
-
-       case OPACK:
-               yyerror("use of package %S without selector", n->sym);
-               goto error;
-
-       case ODDD:
-               break;
-
-       /*
-        * types (OIND is with exprs)
-        */
-       case OTYPE:
-               ok |= Etype;
-               if(n->type == T)
-                       goto error;
-               break;
-       
-       case OTARRAY:
-               ok |= Etype;
-               t = typ(TARRAY);
-               l = n->left;
-               r = n->right;
-               if(l == nil) {
-                       t->bound = -1;  // slice
-               } else if(l->op == ODDD) {
-                       t->bound = -100;        // to be filled in
-                       if(!(top&Ecomplit) && !n->diag) {
-                               t->broke = 1;
-                               n->diag = 1;
-                               yyerror("use of [...] array outside of array literal");
-                       }
-               } else {
-                       l = typecheck(&n->left, Erv);
-                       switch(consttype(l)) {
-                       case CTINT:
-                       case CTRUNE:
-                               v = l->val;
-                               break;
-                       case CTFLT:
-                               v = toint(l->val);
-                               break;
-                       default:
-                               if(l->type != T && isint[l->type->etype] && l->op != OLITERAL)
-                                       yyerror("non-constant array bound %N", l);
-                               else
-                                       yyerror("invalid array bound %N", l);
-                               goto error;
-                       }
-                       t->bound = mpgetfix(v.u.xval);
-                       if(doesoverflow(v, types[TINT])) {
-                               yyerror("array bound is too large"); 
-                               goto error;
-                       } else if(t->bound < 0) {
-                               yyerror("array bound must be non-negative");
-                               goto error;
-                       }
-               }
-               typecheck(&r, Etype);
-               if(r->type == T)
-                       goto error;
-               t->type = r->type;
-               n->op = OTYPE;
-               n->type = t;
-               n->left = N;
-               n->right = N;
-               if(t->bound != -100)
-                       checkwidth(t);
-               break;
-
-       case OTMAP:
-               ok |= Etype;
-               l = typecheck(&n->left, Etype);
-               r = typecheck(&n->right, Etype);
-               if(l->type == T || r->type == T)
-                       goto error;
-               n->op = OTYPE;
-               n->type = maptype(l->type, r->type);
-               n->left = N;
-               n->right = N;
-               break;
-
-       case OTCHAN:
-               ok |= Etype;
-               l = typecheck(&n->left, Etype);
-               if(l->type == T)
-                       goto error;
-               t = typ(TCHAN);
-               t->type = l->type;
-               t->chan = n->etype;
-               n->op = OTYPE;
-               n->type = t;
-               n->left = N;
-               n->etype = 0;
-               break;
-
-       case OTSTRUCT:
-               ok |= Etype;
-               n->op = OTYPE;
-               n->type = tostruct(n->list);
-               if(n->type == T || n->type->broke)
-                       goto error;
-               n->list = nil;
-               break;
-
-       case OTINTER:
-               ok |= Etype;
-               n->op = OTYPE;
-               n->type = tointerface(n->list);
-               if(n->type == T)
-                       goto error;
-               break;
-
-       case OTFUNC:
-               ok |= Etype;
-               n->op = OTYPE;
-               n->type = functype(n->left, n->list, n->rlist);
-               if(n->type == T)
-                       goto error;
-               break;
-
-       /*
-        * type or expr
-        */
-       case OIND:
-               ntop = Erv | Etype;
-               if(!(top & Eaddr))              // The *x in &*x is not an indirect.
-                       ntop |= Eindir;
-               ntop |= top & Ecomplit;
-               l = typecheck(&n->left, ntop);
-               if((t = l->type) == T)
-                       goto error;
-               if(l->op == OTYPE) {
-                       ok |= Etype;
-                       n->op = OTYPE;
-                       n->type = ptrto(l->type);
-                       n->left = N;
-                       goto ret;
-               }
-               if(!isptr[t->etype]) {
-                       if(top & (Erv | Etop)) {
-                               yyerror("invalid indirect of %lN", n->left);
-                               goto error;
-                       }
-                       goto ret;
-               }
-               ok |= Erv;
-               n->type = t->type;
-               goto ret;
-
-       /*
-        * arithmetic exprs
-        */
-       case OASOP:
-               ok |= Etop;
-               l = typecheck(&n->left, Erv);
-               r = typecheck(&n->right, Erv);
-               checkassign(n, n->left);
-               if(l->type == T || r->type == T)
-                       goto error;
-               op = n->etype;
-               goto arith;
-
-       case OADD:
-       case OAND:
-       case OANDAND:
-       case OANDNOT:
-       case ODIV:
-       case OEQ:
-       case OGE:
-       case OGT:
-       case OLE:
-       case OLT:
-       case OLSH:
-       case ORSH:
-       case OMOD:
-       case OMUL:
-       case ONE:
-       case OOR:
-       case OOROR:
-       case OSUB:
-       case OXOR:
-               ok |= Erv;
-               l = typecheck(&n->left, Erv | (top & Eiota));
-               r = typecheck(&n->right, Erv | (top & Eiota));
-               if(l->type == T || r->type == T)
-                       goto error;
-               op = n->op;
-               goto arith;
-
-       case OCOM:
-       case OMINUS:
-       case ONOT:
-       case OPLUS:
-               ok |= Erv;
-               l = typecheck(&n->left, Erv | (top & Eiota));
-               if((t = l->type) == T)
-                       goto error;
-               if(!okfor[n->op][t->etype]) {
-                       yyerror("invalid operation: %O %T", n->op, t);
-                       goto error;
-               }
-               n->type = t;
-               goto ret;
-
-       /*
-        * exprs
-        */
-       case OADDR:
-               ok |= Erv;
-               typecheck(&n->left, Erv | Eaddr);
-               if(n->left->type == T)
-                       goto error;
-               checklvalue(n->left, "take the address of");
-               r = outervalue(n->left);
-               for(l = n->left; l != r; l = l->left) {
-                       l->addrtaken = 1;
-                       if(l->closure)
-                               l->closure->addrtaken = 1;
-               }
-               if(l->orig != l && l->op == ONAME)
-                       fatal("found non-orig name node %N", l);
-               l->addrtaken = 1;
-               if(l->closure)
-                       l->closure->addrtaken = 1;
-               defaultlit(&n->left, T);
-               l = n->left;
-               if((t = l->type) == T)
-                       goto error;
-               n->type = ptrto(t);
-               goto ret;
-
-       case OCOMPLIT:
-               ok |= Erv;
-               typecheckcomplit(&n);
-               if(n->type == T)
-                       goto error;
-               goto ret;
-
-       case OXDOT:
-               n = adddot(n);
-               n->op = ODOT;
-               if(n->left == N)
-                       goto error;
-               // fall through
-       case ODOT:
-               typecheck(&n->left, Erv|Etype);
-               defaultlit(&n->left, T);
-               if(n->right->op != ONAME) {
-                       yyerror("rhs of . must be a name");     // impossible
-                       goto error;
-               }
-               if((t = n->left->type) == T) {
-                       adderrorname(n);
-                       goto error;
-               }
-               r = n->right;
-
-               if(n->left->op == OTYPE) {
-                       if(!looktypedot(n, t, 0)) {
-                               if(looktypedot(n, t, 1))
-                                       yyerror("%N undefined (cannot refer to unexported method %S)", n, n->right->sym);
-                               else
-                                       yyerror("%N undefined (type %T has no method %S)", n, t, n->right->sym);
-                               goto error;
-                       }
-                       if(n->type->etype != TFUNC || n->type->thistuple != 1) {
-                               yyerror("type %T has no method %hS", n->left->type, n->right->sym);
-                               n->type = T;
-                               goto error;
-                       }
-                       n->op = ONAME;
-                       n->sym = n->right->sym;
-                       n->type = methodfunc(n->type, n->left->type);
-                       n->xoffset = 0;
-                       n->class = PFUNC;
-                       ok = Erv;
-                       goto ret;
-               }
-               if(isptr[t->etype] && t->type->etype != TINTER) {
-                       t = t->type;
-                       if(t == T)
-                               goto error;
-                       n->op = ODOTPTR;
-                       checkwidth(t);
-               }
-               if(isblank(n->right)) {
-                       yyerror("cannot refer to blank field or method");
-                       goto error;
-               }
-               if(!lookdot(n, t, 0)) {
-                       if(lookdot(n, t, 1))
-                               yyerror("%N undefined (cannot refer to unexported field or method %S)", n, n->right->sym);
-                       else
-                               yyerror("%N undefined (type %T has no field or method %S)", n, n->left->type, n->right->sym);
-                       goto error;
-               }
-               switch(n->op) {
-               case ODOTINTER:
-               case ODOTMETH:
-                       if(top&Ecall)
-                               ok |= Ecall;
-                       else {
-                               typecheckpartialcall(n, r);
-                               ok |= Erv;
-                       }
-                       break;
-               default:
-                       ok |= Erv;
-                       break;
-               }
-               goto ret;
-
-       case ODOTTYPE:
-               ok |= Erv;
-               typecheck(&n->left, Erv);
-               defaultlit(&n->left, T);
-               l = n->left;
-               if((t = l->type) == T)
-                       goto error;
-               if(!isinter(t)) {
-                       yyerror("invalid type assertion: %N (non-interface type %T on left)", n, t);
-                       goto error;
-               }
-               if(n->right != N) {
-                       typecheck(&n->right, Etype);
-                       n->type = n->right->type;
-                       n->right = N;
-                       if(n->type == T)
-                               goto error;
-               }
-               if(n->type != T && n->type->etype != TINTER)
-               if(!implements(n->type, t, &missing, &have, &ptr)) {
-                       if(have && have->sym == missing->sym)
-                               yyerror("impossible type assertion:\n\t%T does not implement %T (wrong type for %S method)\n"
-                                       "\t\thave %S%hhT\n\t\twant %S%hhT", n->type, t, missing->sym,
-                                       have->sym, have->type, missing->sym, missing->type);
-                       else if(ptr)
-                               yyerror("impossible type assertion:\n\t%T does not implement %T (%S method has pointer receiver)",
-                                       n->type, t, missing->sym);
-                       else if(have)
-                               yyerror("impossible type assertion:\n\t%T does not implement %T (missing %S method)\n"
-                                       "\t\thave %S%hhT\n\t\twant %S%hhT", n->type, t, missing->sym,
-                                       have->sym, have->type, missing->sym, missing->type);
-                       else
-                               yyerror("impossible type assertion:\n\t%T does not implement %T (missing %S method)",
-                                       n->type, t, missing->sym);
-                       goto error;
-               }
-               goto ret;
-
-       case OINDEX:
-               ok |= Erv;
-               typecheck(&n->left, Erv);
-               defaultlit(&n->left, T);
-               implicitstar(&n->left);
-               l = n->left;
-               typecheck(&n->right, Erv);
-               r = n->right;
-               if((t = l->type) == T || r->type == T)
-                       goto error;
-               switch(t->etype) {
-               default:
-                       yyerror("invalid operation: %N (type %T does not support indexing)", n, t);
-                       goto error;
-
-
-               case TSTRING:
-               case TARRAY:
-                       indexlit(&n->right);
-                       if(t->etype == TSTRING)
-                               n->type = types[TUINT8];
-                       else
-                               n->type = t->type;
-                       why = "string";
-                       if(t->etype == TARRAY) {
-                               if(isfixedarray(t))
-                                       why = "array";
-                               else
-                                       why = "slice";
-                       }
-                       if(n->right->type != T && !isint[n->right->type->etype]) {
-                               yyerror("non-integer %s index %N", why, n->right);
-                               break;
-                       }
-                       if(isconst(n->right, CTINT)) {
-                               x = mpgetfix(n->right->val.u.xval);
-                               if(x < 0)
-                                       yyerror("invalid %s index %N (index must be non-negative)", why, n->right);
-                               else if(isfixedarray(t) && t->bound > 0 && x >= t->bound)
-                                       yyerror("invalid array index %N (out of bounds for %d-element array)", n->right, t->bound);
-                               else if(isconst(n->left, CTSTR) && x >= n->left->val.u.sval->len)
-                                       yyerror("invalid string index %N (out of bounds for %d-byte string)", n->right, n->left->val.u.sval->len);
-                               else if(mpcmpfixfix(n->right->val.u.xval, maxintval[TINT]) > 0)
-                                       yyerror("invalid %s index %N (index too large)", why, n->right);
-                       }
-                       break;
-
-               case TMAP:
-                       n->etype = 0;
-                       defaultlit(&n->right, t->down);
-                       if(n->right->type != T)
-                               n->right = assignconv(n->right, t->down, "map index");
-                       n->type = t->type;
-                       n->op = OINDEXMAP;
-                       break;
-               }
-               goto ret;
-
-       case ORECV:
-               ok |= Etop | Erv;
-               typecheck(&n->left, Erv);
-               defaultlit(&n->left, T);
-               l = n->left;
-               if((t = l->type) == T)
-                       goto error;
-               if(t->etype != TCHAN) {
-                       yyerror("invalid operation: %N (receive from non-chan type %T)", n, t);
-                       goto error;
-               }
-               if(!(t->chan & Crecv)) {
-                       yyerror("invalid operation: %N (receive from send-only type %T)", n, t);
-                       goto error;
-               }
-               n->type = t->type;
-               goto ret;
-
-       case OSEND:
-               ok |= Etop;
-               l = typecheck(&n->left, Erv);
-               typecheck(&n->right, Erv);
-               defaultlit(&n->left, T);
-               l = n->left;
-               if((t = l->type) == T)
-                       goto error;
-               if(t->etype != TCHAN) {
-                       yyerror("invalid operation: %N (send to non-chan type %T)", n, t);
-                       goto error;
-               }
-               if(!(t->chan & Csend)) {
-                       yyerror("invalid operation: %N (send to receive-only type %T)", n, t);
-                       goto error;
-               }
-               defaultlit(&n->right, t->type);
-               r = n->right;
-               if(r->type == T)
-                       goto error;
-               n->right = assignconv(r, l->type->type, "send");
-               // TODO: more aggressive
-               n->etype = 0;
-               n->type = T;
-               goto ret;
-
-       case OSLICE:
-               ok |= Erv;
-               typecheck(&n->left, top);
-               typecheck(&n->right->left, Erv);
-               typecheck(&n->right->right, Erv);
-               defaultlit(&n->left, T);
-               indexlit(&n->right->left);
-               indexlit(&n->right->right);
-               l = n->left;
-               if(isfixedarray(l->type)) {
-                       if(!islvalue(n->left)) {
-                               yyerror("invalid operation %N (slice of unaddressable value)", n);
-                               goto error;
-                       }
-                       n->left = nod(OADDR, n->left, N);
-                       n->left->implicit = 1;
-                       typecheck(&n->left, Erv);
-                       l = n->left;
-               }
-               if((t = l->type) == T)
-                       goto error;
-               tp = nil;
-               if(istype(t, TSTRING)) {
-                       n->type = t;
-                       n->op = OSLICESTR;
-               } else if(isptr[t->etype] && isfixedarray(t->type)) {
-                       tp = t->type;
-                       n->type = typ(TARRAY);
-                       n->type->type = tp->type;
-                       n->type->bound = -1;
-                       dowidth(n->type);
-                       n->op = OSLICEARR;
-               } else if(isslice(t)) {
-                       n->type = t;
-               } else {
-                       yyerror("cannot slice %N (type %T)", l, t);
-                       goto error;
-               }
-               if((lo = n->right->left) != N && checksliceindex(l, lo, tp) < 0)
-                       goto error;
-               if((hi = n->right->right) != N && checksliceindex(l, hi, tp) < 0)
-                       goto error;
-               if(checksliceconst(lo, hi) < 0)
-                       goto error;
-               goto ret;
-
-       case OSLICE3:
-               ok |= Erv;
-               typecheck(&n->left, top);
-               typecheck(&n->right->left, Erv);
-               typecheck(&n->right->right->left, Erv);
-               typecheck(&n->right->right->right, Erv);
-               defaultlit(&n->left, T);
-               indexlit(&n->right->left);
-               indexlit(&n->right->right->left);
-               indexlit(&n->right->right->right);
-               l = n->left;
-               if(isfixedarray(l->type)) {
-                       if(!islvalue(n->left)) {
-                               yyerror("invalid operation %N (slice of unaddressable value)", n);
-                               goto error;
-                       }
-                       n->left = nod(OADDR, n->left, N);
-                       n->left->implicit = 1;
-                       typecheck(&n->left, Erv);
-                       l = n->left;
-               }
-               if((t = l->type) == T)
-                       goto error;
-               tp = nil;
-               if(istype(t, TSTRING)) {
-                       yyerror("invalid operation %N (3-index slice of string)", n);
-                       goto error;
-               }
-               if(isptr[t->etype] && isfixedarray(t->type)) {
-                       tp = t->type;
-                       n->type = typ(TARRAY);
-                       n->type->type = tp->type;
-                       n->type->bound = -1;
-                       dowidth(n->type);
-                       n->op = OSLICE3ARR;
-               } else if(isslice(t)) {
-                       n->type = t;
-               } else {
-                       yyerror("cannot slice %N (type %T)", l, t);
-                       goto error;
-               }
-               if((lo = n->right->left) != N && checksliceindex(l, lo, tp) < 0)
-                       goto error;
-               if((mid = n->right->right->left) != N && checksliceindex(l, mid, tp) < 0)
-                       goto error;
-               if((hi = n->right->right->right) != N && checksliceindex(l, hi, tp) < 0)
-                       goto error;
-               if(checksliceconst(lo, hi) < 0 || checksliceconst(lo, mid) < 0 || checksliceconst(mid, hi) < 0)
-                       goto error;
-               goto ret;
-
-       /*
-        * call and call like
-        */
-       case OCALL:
-               l = n->left;
-               if(l->op == ONAME && (r = unsafenmagic(n)) != N) {
-                       if(n->isddd)
-                               yyerror("invalid use of ... with builtin %N", l);
-                       n = r;
-                       goto reswitch;
-               }
-               typecheck(&n->left, Erv | Etype | Ecall |(top&Eproc));
-               n->diag |= n->left->diag;
-               l = n->left;
-               if(l->op == ONAME && l->etype != 0) {
-                       if(n->isddd && l->etype != OAPPEND)
-                               yyerror("invalid use of ... with builtin %N", l);
-                       // builtin: OLEN, OCAP, etc.
-                       n->op = l->etype;
-                       n->left = n->right;
-                       n->right = N;
-                       goto reswitch;
-               }
-               defaultlit(&n->left, T);
-               l = n->left;
-               if(l->op == OTYPE) {
-                       if(n->isddd || l->type->bound == -100) {
-                               if(!l->type->broke)
-                                       yyerror("invalid use of ... in type conversion", l);
-                               n->diag = 1;
-                       }
-                       // pick off before type-checking arguments
-                       ok |= Erv;
-                       // turn CALL(type, arg) into CONV(arg) w/ type
-                       n->left = N;
-                       n->op = OCONV;
-                       n->type = l->type;
-                       if(onearg(n, "conversion to %T", l->type) < 0)
-                               goto error;
-                       goto doconv;
-               }
-
-               if(count(n->list) == 1 && !n->isddd)
-                       typecheck(&n->list->n, Erv | Efnstruct);
-               else
-                       typechecklist(n->list, Erv);
-               if((t = l->type) == T)
-                       goto error;
-               checkwidth(t);
-
-               switch(l->op) {
-               case ODOTINTER:
-                       n->op = OCALLINTER;
-                       break;
-
-               case ODOTMETH:
-                       n->op = OCALLMETH;
-                       // typecheckaste was used here but there wasn't enough
-                       // information further down the call chain to know if we
-                       // were testing a method receiver for unexported fields.
-                       // It isn't necessary, so just do a sanity check.
-                       tp = getthisx(t)->type->type;
-                       if(l->left == N || !eqtype(l->left->type, tp))
-                               fatal("method receiver");
-                       break;
-
-               default:
-                       n->op = OCALLFUNC;
-                       if(t->etype != TFUNC) {
-                               yyerror("cannot call non-function %N (type %T)", l, t);
-                               goto error;
-                       }
-                       break;
-               }
-               if(snprint(descbuf, sizeof descbuf, "argument to %N", n->left) < sizeof descbuf)
-                       desc = descbuf;
-               else
-                       desc = "function argument";
-               typecheckaste(OCALL, n->left, n->isddd, getinargx(t), n->list, desc);
-               ok |= Etop;
-               if(t->outtuple == 0)
-                       goto ret;
-               ok |= Erv;
-               if(t->outtuple == 1) {
-                       t = getoutargx(l->type)->type;
-                       if(t == T)
-                               goto error;
-                       if(t->etype == TFIELD)
-                               t = t->type;
-                       n->type = t;
-                       goto ret;
-               }
-               // multiple return
-               if(!(top & (Efnstruct | Etop))) {
-                       yyerror("multiple-value %N() in single-value context", l);
-                       goto ret;
-               }
-               n->type = getoutargx(l->type);
-               goto ret;
-
-       case OCAP:
-       case OLEN:
-       case OREAL:
-       case OIMAG:
-               ok |= Erv;
-               if(onearg(n, "%O", n->op) < 0)
-                       goto error;
-               typecheck(&n->left, Erv);
-               defaultlit(&n->left, T);
-               implicitstar(&n->left);
-               l = n->left;
-               t = l->type;
-               if(t == T)
-                       goto error;
-               switch(n->op) {
-               case OCAP:
-                       if(!okforcap[t->etype])
-                               goto badcall1;
-                       break;
-               case OLEN:
-                       if(!okforlen[t->etype])
-                               goto badcall1;
-                       break;
-               case OREAL:
-               case OIMAG:
-                       if(!iscomplex[t->etype])
-                               goto badcall1;
-                       if(isconst(l, CTCPLX)){
-                               r = n;
-                               if(n->op == OREAL)
-                                       n = nodfltconst(&l->val.u.cval->real);
-                               else
-                                       n = nodfltconst(&l->val.u.cval->imag);
-                               n->orig = r;
-                       }
-                       n->type = types[cplxsubtype(t->etype)];
-                       goto ret;
-               }
-               // might be constant
-               switch(t->etype) {
-               case TSTRING:
-                       if(isconst(l, CTSTR)) {
-                               r = nod(OXXX, N, N);
-                               nodconst(r, types[TINT], l->val.u.sval->len);
-                               r->orig = n;
-                               n = r;
-                       }
-                       break;
-               case TARRAY:
-                       if(t->bound < 0) // slice
-                               break;
-                       if(callrecv(l)) // has call or receive
-                               break;
-                       r = nod(OXXX, N, N);
-                       nodconst(r, types[TINT], t->bound);
-                       r->orig = n;
-                       n = r;
-                       break;
-               }
-               n->type = types[TINT];
-               goto ret;
-
-       case OCOMPLEX:
-               ok |= Erv;
-               if(count(n->list) == 1) {
-                       typechecklist(n->list, Efnstruct);
-                       if(n->list->n->op != OCALLFUNC && n->list->n->op != OCALLMETH) {
-                               yyerror("invalid operation: complex expects two arguments");
-                               goto error;
-                       }
-                       t = n->list->n->left->type;
-                       if(t->outtuple != 2) {
-                               yyerror("invalid operation: complex expects two arguments, %N returns %d results", n->list->n, t->outtuple);
-                               goto error;
-                       }
-                       t = n->list->n->type->type;
-                       l = t->nname;
-                       r = t->down->nname;
-               } else {
-                       if(twoarg(n) < 0)
-                               goto error;
-                       l = typecheck(&n->left, Erv | (top & Eiota));
-                       r = typecheck(&n->right, Erv | (top & Eiota));
-                       if(l->type == T || r->type == T)
-                               goto error;
-                       defaultlit2(&l, &r, 0);
-                       if(l->type == T || r->type == T)
-                               goto error;
-                       n->left = l;
-                       n->right = r;
-               }
-               if(!eqtype(l->type, r->type)) {
-                       yyerror("invalid operation: %N (mismatched types %T and %T)", n, l->type, r->type);
-                       goto error;
-               }
-               switch(l->type->etype) {
-               default:
-                       yyerror("invalid operation: %N (arguments have type %T, expected floating-point)", n, l->type, r->type);
-                       goto error;
-               case TIDEAL:
-                       t = types[TIDEAL];
-                       break;
-               case TFLOAT32:
-                       t = types[TCOMPLEX64];
-                       break;
-               case TFLOAT64:
-                       t = types[TCOMPLEX128];
-                       break;
-               }
-               if(l->op == OLITERAL && r->op == OLITERAL) {
-                       // make it a complex literal
-                       r = nodcplxlit(l->val, r->val);
-                       r->orig = n;
-                       n = r;
-               }
-               n->type = t;
-               goto ret;
-
-       case OCLOSE:
-               if(onearg(n, "%O", n->op) < 0)
-                       goto error;
-               typecheck(&n->left, Erv);
-               defaultlit(&n->left, T);
-               l = n->left;
-               if((t = l->type) == T)
-                       goto error;
-               if(t->etype != TCHAN) {
-                       yyerror("invalid operation: %N (non-chan type %T)", n, t);
-                       goto error;
-               }
-               if(!(t->chan & Csend)) {
-                       yyerror("invalid operation: %N (cannot close receive-only channel)", n);
-                       goto error;
-               }
-               ok |= Etop;
-               goto ret;
-
-       case ODELETE:
-               args = n->list;
-               if(args == nil) {
-                       yyerror("missing arguments to delete");
-                       goto error;
-               }
-               if(args->next == nil) {
-                       yyerror("missing second (key) argument to delete");
-                       goto error;
-               }
-               if(args->next->next != nil) {
-                       yyerror("too many arguments to delete");
-                       goto error;
-               }
-               ok |= Etop;
-               typechecklist(args, Erv);
-               l = args->n;
-               r = args->next->n;
-               if(l->type != T && l->type->etype != TMAP) {
-                       yyerror("first argument to delete must be map; have %lT", l->type);
-                       goto error;
-               }
-               args->next->n = assignconv(r, l->type->down, "delete");
-               goto ret;
-
-       case OAPPEND:
-               ok |= Erv;
-               args = n->list;
-               if(args == nil) {
-                       yyerror("missing arguments to append");
-                       goto error;
-               }
-
-               if(count(args) == 1 && !n->isddd)
-                       typecheck(&args->n, Erv | Efnstruct);
-               else
-                       typechecklist(args, Erv);
-
-               if((t = args->n->type) == T)
-                       goto error;
-
-               // Unpack multiple-return result before type-checking.
-               if(istype(t, TSTRUCT) && t->funarg) {
-                       t = t->type;
-                       if(istype(t, TFIELD))
-                               t = t->type;
-               }
-
-               n->type = t;
-               if(!isslice(t)) {
-                       if(isconst(args->n, CTNIL)) {
-                               yyerror("first argument to append must be typed slice; have untyped nil", t);
-                               goto error;
-                       }
-                       yyerror("first argument to append must be slice; have %lT", t);
-                       goto error;
-               }
-
-               if(n->isddd) {
-                       if(args->next == nil) {
-                               yyerror("cannot use ... on first argument to append");
-                               goto error;
-                       }
-                       if(args->next->next != nil) {
-                               yyerror("too many arguments to append");
-                               goto error;
-                       }
-                       if(istype(t->type, TUINT8) && istype(args->next->n->type, TSTRING)) {
-                               defaultlit(&args->next->n, types[TSTRING]);
-                               goto ret;
-                       }
-                       args->next->n = assignconv(args->next->n, t->orig, "append");
-                       goto ret;
-               }
-               for(args=args->next; args != nil; args=args->next) {
-                       if(args->n->type == T)
-                               continue;
-                       args->n = assignconv(args->n, t->type, "append");
-               }
-               goto ret;
-
-       case OCOPY:
-               ok |= Etop|Erv;
-               args = n->list;
-               if(args == nil || args->next == nil) {
-                       yyerror("missing arguments to copy");
-                       goto error;
-               }
-               if(args->next->next != nil) {
-                       yyerror("too many arguments to copy");
-                       goto error;
-               }
-               n->left = args->n;
-               n->right = args->next->n;
-               n->list = nil;
-               n->type = types[TINT];
-               typecheck(&n->left, Erv);
-               typecheck(&n->right, Erv);
-               if(n->left->type == T || n->right->type == T)
-                       goto error;
-               defaultlit(&n->left, T);
-               defaultlit(&n->right, T);
-               if(n->left->type == T || n->right->type == T)
-                       goto error;
-
-               // copy([]byte, string)
-               if(isslice(n->left->type) && n->right->type->etype == TSTRING) {
-                       if(eqtype(n->left->type->type, bytetype))
-                               goto ret;
-                       yyerror("arguments to copy have different element types: %lT and string", n->left->type);
-                       goto error;
-               }
-
-               if(!isslice(n->left->type) || !isslice(n->right->type)) {
-                       if(!isslice(n->left->type) && !isslice(n->right->type))
-                               yyerror("arguments to copy must be slices; have %lT, %lT", n->left->type, n->right->type);
-                       else if(!isslice(n->left->type))
-                               yyerror("first argument to copy should be slice; have %lT", n->left->type);
-                       else
-                               yyerror("second argument to copy should be slice or string; have %lT", n->right->type);
-                       goto error;
-               }
-               if(!eqtype(n->left->type->type, n->right->type->type)) {
-                       yyerror("arguments to copy have different element types: %lT and %lT", n->left->type, n->right->type);
-                       goto error;
-               }
-               goto ret;
-
-       case OCONV:
-               goto doconv;
-
-       case OMAKE:
-               ok |= Erv;
-               args = n->list;
-               if(args == nil) {
-                       yyerror("missing argument to make");
-                       goto error;
-               }
-               n->list = nil;
-               l = args->n;
-               args = args->next;
-               typecheck(&l, Etype);
-               if((t = l->type) == T)
-                       goto error;
-
-               switch(t->etype) {
-               default:
-                       yyerror("cannot make type %T", t);
-                       goto error;
-
-               case TARRAY:
-                       if(!isslice(t)) {
-                               yyerror("cannot make type %T", t);
-                               goto error;
-                       }
-                       if(args == nil) {
-                               yyerror("missing len argument to make(%T)", t);
-                               goto error;
-                       }
-                       l = args->n;
-                       args = args->next;
-                       typecheck(&l, Erv);
-                       r = N;
-                       if(args != nil) {
-                               r = args->n;
-                               args = args->next;
-                               typecheck(&r, Erv);
-                       }
-                       if(l->type == T || (r && r->type == T))
-                               goto error;
-                       et = checkmake(t, "len", l) < 0;
-                       et |= r && checkmake(t, "cap", r) < 0;
-                       if(et)
-                               goto error;
-                       if(isconst(l, CTINT) && r && isconst(r, CTINT) && mpcmpfixfix(l->val.u.xval, r->val.u.xval) > 0) {
-                               yyerror("len larger than cap in make(%T)", t);
-                               goto error;
-                       }
-                       n->left = l;
-                       n->right = r;
-                       n->op = OMAKESLICE;
-                       break;
-
-               case TMAP:
-                       if(args != nil) {
-                               l = args->n;
-                               args = args->next;
-                               typecheck(&l, Erv);
-                               defaultlit(&l, types[TINT]);
-                               if(l->type == T)
-                                       goto error;
-                               if(checkmake(t, "size", l) < 0)
-                                       goto error;
-                               n->left = l;
-                       } else
-                               n->left = nodintconst(0);
-                       n->op = OMAKEMAP;
-                       break;
-
-               case TCHAN:
-                       l = N;
-                       if(args != nil) {
-                               l = args->n;
-                               args = args->next;
-                               typecheck(&l, Erv);
-                               defaultlit(&l, types[TINT]);
-                               if(l->type == T)
-                                       goto error;
-                               if(checkmake(t, "buffer", l) < 0)
-                                       goto error;
-                               n->left = l;
-                       } else
-                               n->left = nodintconst(0);
-                       n->op = OMAKECHAN;
-                       break;
-               }
-               if(args != nil) {
-                       yyerror("too many arguments to make(%T)", t);
-                       n->op = OMAKE;
-                       goto error;
-               }
-               n->type = t;
-               goto ret;
-
-       case ONEW:
-               ok |= Erv;
-               args = n->list;
-               if(args == nil) {
-                       yyerror("missing argument to new");
-                       goto error;
-               }
-               l = args->n;
-               typecheck(&l, Etype);
-               if((t = l->type) == T)
-                       goto error;
-               if(args->next != nil) {
-                       yyerror("too many arguments to new(%T)", t);
-                       goto error;
-               }
-               n->left = l;
-               n->type = ptrto(t);
-               goto ret;
-
-       case OPRINT:
-       case OPRINTN:
-               ok |= Etop;
-               typechecklist(n->list, Erv | Eindir);  // Eindir: address does not escape
-               for(args=n->list; args; args=args->next) {
-                       // Special case for print: int constant is int64, not int.
-                       if(isconst(args->n, CTINT))
-                               defaultlit(&args->n, types[TINT64]);
-                       else
-                               defaultlit(&args->n, T);
-               }
-               goto ret;
-
-       case OPANIC:
-               ok |= Etop;
-               if(onearg(n, "panic") < 0)
-                       goto error;
-               typecheck(&n->left, Erv);
-               defaultlit(&n->left, types[TINTER]);
-               if(n->left->type == T)
-                       goto error;
-               goto ret;
-       
-       case ORECOVER:
-               ok |= Erv|Etop;
-               if(n->list != nil) {
-                       yyerror("too many arguments to recover");
-                       goto error;
-               }
-               n->type = types[TINTER];
-               goto ret;
-
-       case OCLOSURE:
-               ok |= Erv;
-               typecheckclosure(n, top);
-               if(n->type == T)
-                       goto error;
-               goto ret;
-       
-       case OITAB:
-               ok |= Erv;
-               typecheck(&n->left, Erv);
-               if((t = n->left->type) == T)
-                       goto error;
-               if(t->etype != TINTER)
-                       fatal("OITAB of %T", t);
-               n->type = ptrto(types[TUINTPTR]);
-               goto ret;
-
-       case OSPTR:
-               ok |= Erv;
-               typecheck(&n->left, Erv);
-               if((t = n->left->type) == T)
-                       goto error;
-               if(!isslice(t) && t->etype != TSTRING)
-                       fatal("OSPTR of %T", t);
-               if(t->etype == TSTRING)
-                       n->type = ptrto(types[TUINT8]);
-               else
-                       n->type = ptrto(t->type);
-               goto ret;
-
-       case OCLOSUREVAR:
-               ok |= Erv;
-               goto ret;
-       
-       case OCFUNC:
-               ok |= Erv;
-               typecheck(&n->left, Erv);
-               n->type = types[TUINTPTR];
-               goto ret;
-
-       case OCONVNOP:
-               ok |= Erv;
-               typecheck(&n->left, Erv);
-               goto ret;
-
-       /*
-        * statements
-        */
-       case OAS:
-               ok |= Etop;
-               typecheckas(n);
-               // Code that creates temps does not bother to set defn, so do it here.
-               if(n->left->op == ONAME && strncmp(n->left->sym->name, "autotmp_", 8) == 0)
-                       n->left->defn = n;
-               goto ret;
-
-       case OAS2:
-               ok |= Etop;
-               typecheckas2(n);
-               goto ret;
-
-       case OBREAK:
-       case OCONTINUE:
-       case ODCL:
-       case OEMPTY:
-       case OGOTO:
-       case OXFALL:
-       case OVARKILL:
-               ok |= Etop;
-               goto ret;
-
-       case OLABEL:
-               ok |= Etop;
-               decldepth++;
-               goto ret;
-
-       case ODEFER:
-               ok |= Etop;
-               typecheck(&n->left, Etop|Erv);
-               if(!n->left->diag)
-                       checkdefergo(n);
-               goto ret;
-
-       case OPROC:
-               ok |= Etop;
-               typecheck(&n->left, Etop|Eproc|Erv);
-               checkdefergo(n);
-               goto ret;
-
-       case OFOR:
-               ok |= Etop;
-               typechecklist(n->ninit, Etop);
-               decldepth++;
-               typecheck(&n->ntest, Erv);
-               if(n->ntest != N && (t = n->ntest->type) != T && t->etype != TBOOL)
-                       yyerror("non-bool %lN used as for condition", n->ntest);
-               typecheck(&n->nincr, Etop);
-               typechecklist(n->nbody, Etop);
-               decldepth--;
-               goto ret;
-
-       case OIF:
-               ok |= Etop;
-               typechecklist(n->ninit, Etop);
-               typecheck(&n->ntest, Erv);
-               if(n->ntest != N && (t = n->ntest->type) != T && t->etype != TBOOL)
-                       yyerror("non-bool %lN used as if condition", n->ntest);
-               typechecklist(n->nbody, Etop);
-               typechecklist(n->nelse, Etop);
-               goto ret;
-
-       case ORETURN:
-               ok |= Etop;
-               if(count(n->list) == 1)
-                       typechecklist(n->list, Erv | Efnstruct);
-               else
-                       typechecklist(n->list, Erv);
-               if(curfn == N) {
-                       yyerror("return outside function");
-                       goto error;
-               }
-               if(curfn->type->outnamed && n->list == nil)
-                       goto ret;
-               typecheckaste(ORETURN, nil, 0, getoutargx(curfn->type), n->list, "return argument");
-               goto ret;
-       
-       case ORETJMP:
-               ok |= Etop;
-               goto ret;
-
-       case OSELECT:
-               ok |= Etop;
-               typecheckselect(n);
-               goto ret;
-
-       case OSWITCH:
-               ok |= Etop;
-               typecheckswitch(n);
-               goto ret;
-
-       case ORANGE:
-               ok |= Etop;
-               typecheckrange(n);
-               goto ret;
-
-       case OTYPESW:
-               yyerror("use of .(type) outside type switch");
-               goto error;
-
-       case OXCASE:
-               ok |= Etop;
-               typechecklist(n->list, Erv);
-               typechecklist(n->nbody, Etop);
-               goto ret;
-
-       case ODCLFUNC:
-               ok |= Etop;
-               typecheckfunc(n);
-               goto ret;
-
-       case ODCLCONST:
-               ok |= Etop;
-               typecheck(&n->left, Erv);
-               goto ret;
-
-       case ODCLTYPE:
-               ok |= Etop;
-               typecheck(&n->left, Etype);
-               if(!incannedimport)
-                       checkwidth(n->left->type);
-               goto ret;
-       }
-       goto ret;
-
-arith:
-       if(op == OLSH || op == ORSH)
-               goto shift;
-       // ideal mixed with non-ideal
-       defaultlit2(&l, &r, 0);
-       n->left = l;
-       n->right = r;
-       if(l->type == T || r->type == T)
-               goto error;
-       t = l->type;
-       if(t->etype == TIDEAL)
-               t = r->type;
-       et = t->etype;
-       if(et == TIDEAL)
-               et = TINT;
-       aop = 0;
-       if(iscmp[n->op] && t->etype != TIDEAL && !eqtype(l->type, r->type)) {
-               // comparison is okay as long as one side is
-               // assignable to the other.  convert so they have
-               // the same type.
-               //
-               // the only conversion that isn't a no-op is concrete == interface.
-               // in that case, check comparability of the concrete type.
-               // The conversion allocates, so only do it if the concrete type is huge.
-               if(r->type->etype != TBLANK && (aop = assignop(l->type, r->type, nil)) != 0) {
-                       if(isinter(r->type) && !isinter(l->type) && algtype1(l->type, nil) == ANOEQ) {
-                               yyerror("invalid operation: %N (operator %O not defined on %s)", n, op, typekind(l->type));
-                               goto error;
-                       }
-                       dowidth(l->type);
-                       if(isinter(r->type) == isinter(l->type) || l->type->width >= 1<<16) {
-                               l = nod(aop, l, N);
-                               l->type = r->type;
-                               l->typecheck = 1;
-                               n->left = l;
-                       }
-                       t = r->type;
-                       goto converted;
-               }
-               if(l->type->etype != TBLANK && (aop = assignop(r->type, l->type, nil)) != 0) {
-                       if(isinter(l->type) && !isinter(r->type) && algtype1(r->type, nil) == ANOEQ) {
-                               yyerror("invalid operation: %N (operator %O not defined on %s)", n, op, typekind(r->type));
-                               goto error;
-                       }
-                       dowidth(r->type);
-                       if(isinter(r->type) == isinter(l->type) || r->type->width >= 1<<16) {
-                               r = nod(aop, r, N);
-                               r->type = l->type;
-                               r->typecheck = 1;
-                               n->right = r;
-                       }
-                       t = l->type;
-               }
-       converted:
-               et = t->etype;
-       }
-       if(t->etype != TIDEAL && !eqtype(l->type, r->type)) {
-               defaultlit2(&l, &r, 1);
-               if(n->op == OASOP && n->implicit) {
-                       yyerror("invalid operation: %N (non-numeric type %T)", n, l->type);
-                       goto error;
-               }
-               if(isinter(r->type) == isinter(l->type) || aop == 0) {
-                       yyerror("invalid operation: %N (mismatched types %T and %T)", n, l->type, r->type);
-                       goto error;
-               }
-       }
-       if(!okfor[op][et]) {
-               yyerror("invalid operation: %N (operator %O not defined on %s)", n, op, typekind(t));
-               goto error;
-       }
-       // okfor allows any array == array, map == map, func == func.
-       // restrict to slice/map/func == nil and nil == slice/map/func.
-       if(isfixedarray(l->type) && algtype1(l->type, nil) == ANOEQ) {
-               yyerror("invalid operation: %N (%T cannot be compared)", n, l->type);
-               goto error;
-       }
-       if(isslice(l->type) && !isnil(l) && !isnil(r)) {
-               yyerror("invalid operation: %N (slice can only be compared to nil)", n);
-               goto error;
-       }
-       if(l->type->etype == TMAP && !isnil(l) && !isnil(r)) {
-               yyerror("invalid operation: %N (map can only be compared to nil)", n);
-               goto error;
-       }
-       if(l->type->etype == TFUNC && !isnil(l) && !isnil(r)) {
-               yyerror("invalid operation: %N (func can only be compared to nil)", n);
-               goto error;
-       }
-       if(l->type->etype == TSTRUCT && algtype1(l->type, &badtype) == ANOEQ) {
-               yyerror("invalid operation: %N (struct containing %T cannot be compared)", n, badtype);
-               goto error;
-       }
-       
-       t = l->type;
-       if(iscmp[n->op]) {
-               evconst(n);
-               t = idealbool;
-               if(n->op != OLITERAL) {
-                       defaultlit2(&l, &r, 1);
-                       n->left = l;
-                       n->right = r;
-               }
-       } else if(n->op == OANDAND || n->op == OOROR) {
-               if(l->type == r->type)
-                       t = l->type;
-               else if(l->type == idealbool)
-                       t = r->type;
-               else if(r->type == idealbool)
-                       t = l->type;
-       // non-comparison operators on ideal bools should make them lose their ideal-ness
-       } else if(t == idealbool)
-               t = types[TBOOL];
-
-       if(et == TSTRING) {
-               if(iscmp[n->op]) {
-                       n->etype = n->op;
-                       n->op = OCMPSTR;
-               } else if(n->op == OADD) {
-                       // create OADDSTR node with list of strings in x + y + z + (w + v) + ...
-                       n->op = OADDSTR;
-                       if(l->op == OADDSTR)
-                               n->list = l->list;
-                       else
-                               n->list = list1(l);
-                       if(r->op == OADDSTR)
-                               n->list = concat(n->list, r->list);
-                       else
-                               n->list = list(n->list, r);
-                       n->left = N;
-                       n->right = N;
-               }
-       }
-       if(et == TINTER) {
-               if(l->op == OLITERAL && l->val.ctype == CTNIL) {
-                       // swap for back end
-                       n->left = r;
-                       n->right = l;
-               } else if(r->op == OLITERAL && r->val.ctype == CTNIL) {
-                       // leave alone for back end
-               } else if(isinter(r->type) == isinter(l->type)) {
-                       n->etype = n->op;
-                       n->op = OCMPIFACE;
-               }
-       }
-
-       if((op == ODIV || op == OMOD) && isconst(r, CTINT))
-       if(mpcmpfixc(r->val.u.xval, 0) == 0) {
-               yyerror("division by zero");
-               goto error;
-       } 
-
-       n->type = t;
-       goto ret;
-
-shift:
-       defaultlit(&r, types[TUINT]);
-       n->right = r;
-       t = r->type;
-       if(!isint[t->etype] || issigned[t->etype]) {
-               yyerror("invalid operation: %N (shift count type %T, must be unsigned integer)", n, r->type);
-               goto error;
-       }
-       t = l->type;
-       if(t != T && t->etype != TIDEAL && !isint[t->etype]) {
-               yyerror("invalid operation: %N (shift of type %T)", n, t);
-               goto error;
-       }
-       // no defaultlit for left
-       // the outer context gives the type
-       n->type = l->type;
-       goto ret;
-
-doconv:
-       ok |= Erv;
-       saveorignode(n);
-       typecheck(&n->left, Erv | (top & (Eindir | Eiota)));
-       convlit1(&n->left, n->type, 1);
-       if((t = n->left->type) == T || n->type == T)
-               goto error;
-       if((n->op = convertop(t, n->type, &why)) == 0) {
-               if(!n->diag && !n->type->broke) {
-                       yyerror("cannot convert %lN to type %T%s", n->left, n->type, why);
-                       n->diag = 1;
-               }
-               n->op = OCONV;
-       }
-       switch(n->op) {
-       case OCONVNOP:
-               if(n->left->op == OLITERAL && n->type != types[TBOOL]) {
-                       r = nod(OXXX, N, N);
-                       n->op = OCONV;
-                       n->orig = r;
-                       *r = *n;
-                       n->op = OLITERAL;
-                       n->val = n->left->val;
-               }
-               break;
-       case OSTRARRAYBYTE:
-               // do not use stringtoarraylit.
-               // generated code and compiler memory footprint is better without it.
-               break;
-       case OSTRARRAYRUNE:
-               if(n->left->op == OLITERAL)
-                       stringtoarraylit(&n);
-               break;
-       }
-       goto ret;
-
-ret:
-       t = n->type;
-       if(t && !t->funarg && n->op != OTYPE) {
-               switch(t->etype) {
-               case TFUNC:     // might have TANY; wait until its called
-               case TANY:
-               case TFORW:
-               case TIDEAL:
-               case TNIL:
-               case TBLANK:
-                       break;
-               default:
-                       checkwidth(t);
-               }
-       }
-
-       if(safemode && !incannedimport && !importpkg && !compiling_wrappers && t && t->etype == TUNSAFEPTR)
-               yyerror("cannot use unsafe.Pointer");
-
-       evconst(n);
-       if(n->op == OTYPE && !(top & Etype)) {
-               yyerror("type %T is not an expression", n->type);
-               goto error;
-       }
-       if((top & (Erv|Etype)) == Etype && n->op != OTYPE) {
-               yyerror("%N is not a type", n);
-               goto error;
-       }
-       // TODO(rsc): simplify
-       if((top & (Ecall|Erv|Etype)) && !(top & Etop) && !(ok & (Erv|Etype|Ecall))) {
-               yyerror("%N used as value", n);
-               goto error;
-       }
-       if((top & Etop) && !(top & (Ecall|Erv|Etype)) && !(ok & Etop)) {
-               if(n->diag == 0) {
-                       yyerror("%N evaluated but not used", n);
-                       n->diag = 1;
-               }
-               goto error;
-       }
-
-       /* TODO
-       if(n->type == T)
-               fatal("typecheck nil type");
-       */
-       goto out;
-
-badcall1:
-       yyerror("invalid argument %lN for %O", n->left, n->op);
-       goto error;
-
-error:
-       n->type = T;
-
-out:
-       *np = n;
-}
-
-static int
-checksliceindex(Node *l, Node *r, Type *tp)
-{
-       Type *t;
-
-       if((t = r->type) == T)
-               return -1;
-       if(!isint[t->etype]) {
-               yyerror("invalid slice index %N (type %T)", r, t);
-               return -1;
-       }
-       if(r->op == OLITERAL) {
-               if(mpgetfix(r->val.u.xval) < 0) {
-                       yyerror("invalid slice index %N (index must be non-negative)", r);
-                       return -1;
-               } else if(tp != nil && tp->bound > 0 && mpgetfix(r->val.u.xval) > tp->bound) {
-                       yyerror("invalid slice index %N (out of bounds for %d-element array)", r, tp->bound);
-                       return -1;
-               } else if(isconst(l, CTSTR) && mpgetfix(r->val.u.xval) > l->val.u.sval->len) {
-                       yyerror("invalid slice index %N (out of bounds for %d-byte string)", r, l->val.u.sval->len);
-                       return -1;
-               } else if(mpcmpfixfix(r->val.u.xval, maxintval[TINT]) > 0) {
-                       yyerror("invalid slice index %N (index too large)", r);
-                       return -1;
-               }
-       }
-       return 0;
-}
-
-static int
-checksliceconst(Node *lo, Node *hi)
-{
-       if(lo != N && hi != N && lo->op == OLITERAL && hi->op == OLITERAL
-          && mpcmpfixfix(lo->val.u.xval, hi->val.u.xval) > 0) {
-               yyerror("invalid slice index: %N > %N", lo, hi);
-               return -1;
-       }
-       return 0;
-}
-
-static void
-checkdefergo(Node *n)
-{
-       char *what;
-       
-       what = "defer";
-       if(n->op == OPROC)
-               what = "go";
-
-       switch(n->left->op) {
-       case OCALLINTER:
-       case OCALLMETH:
-       case OCALLFUNC:
-       case OCLOSE:
-       case OCOPY:
-       case ODELETE:
-       case OPANIC:
-       case OPRINT:
-       case OPRINTN:
-       case ORECOVER:
-               // ok
-               return;
-       case OAPPEND:
-       case OCAP:
-       case OCOMPLEX:
-       case OIMAG:
-       case OLEN:
-       case OMAKE:
-       case OMAKESLICE:
-       case OMAKECHAN:
-       case OMAKEMAP:
-       case ONEW:
-       case OREAL:
-       case OLITERAL: // conversion or unsafe.Alignof, Offsetof, Sizeof
-               if(n->left->orig != N && n->left->orig->op == OCONV)
-                       break;
-               yyerror("%s discards result of %N", what, n->left);
-               return;
-       }
-
-       // type is broken or missing, most likely a method call on a broken type
-       // we will warn about the broken type elsewhere. no need to emit a potentially confusing error
-       if(n->left->type == T || n->left->type->broke)
-               return;
-
-       if(!n->diag) {
-               // The syntax made sure it was a call, so this must be
-               // a conversion.
-               n->diag = 1;
-               yyerror("%s requires function call, not conversion", what);
-       }
-}
-
-static void
-implicitstar(Node **nn)
-{
-       Type *t;
-       Node *n;
-
-       // insert implicit * if needed for fixed array
-       n = *nn;
-       t = n->type;
-       if(t == T || !isptr[t->etype])
-               return;
-       t = t->type;
-       if(t == T)
-               return;
-       if(!isfixedarray(t))
-               return;
-       n = nod(OIND, n, N);
-       n->implicit = 1;
-       typecheck(&n, Erv);
-       *nn = n;
-}
-
-static int
-onearg(Node *n, char *f, ...)
-{
-       va_list arg;
-       char *p;
-
-       if(n->left != N)
-               return 0;
-       if(n->list == nil) {
-               va_start(arg, f);
-               p = vsmprint(f, arg);
-               va_end(arg);
-               yyerror("missing argument to %s: %N", p, n);
-               return -1;
-       }
-       if(n->list->next != nil) {
-               va_start(arg, f);
-               p = vsmprint(f, arg);
-               va_end(arg);
-               yyerror("too many arguments to %s: %N", p, n);
-               n->left = n->list->n;
-               n->list = nil;
-               return -1;
-       }
-       n->left = n->list->n;
-       n->list = nil;
-       return 0;
-}
-
-static int
-twoarg(Node *n)
-{
-       if(n->left != N)
-               return 0;
-       if(n->list == nil) {
-               yyerror("missing argument to %O - %N", n->op, n);
-               return -1;
-       }
-       n->left = n->list->n;
-       if(n->list->next == nil) {
-               yyerror("missing argument to %O - %N", n->op, n);
-               n->list = nil;
-               return -1;
-       }
-       if(n->list->next->next != nil) {
-               yyerror("too many arguments to %O - %N", n->op, n);
-               n->list = nil;
-               return -1;
-       }
-       n->right = n->list->next->n;
-       n->list = nil;
-       return 0;
-}
-
-static Type*
-lookdot1(Node *errnode, Sym *s, Type *t, Type *f, int dostrcmp)
-{
-       Type *r;
-
-       r = T;
-       for(; f!=T; f=f->down) {
-               if(dostrcmp && strcmp(f->sym->name, s->name) == 0)
-                       return f;
-               if(f->sym != s)
-                       continue;
-               if(r != T) {
-                       if(errnode)
-                               yyerror("ambiguous selector %N", errnode);
-                       else if(isptr[t->etype])
-                               yyerror("ambiguous selector (%T).%S", t, s);
-                       else
-                               yyerror("ambiguous selector %T.%S", t, s);
-                       break;
-               }
-               r = f;
-       }
-       return r;
-}
-
-static int
-looktypedot(Node *n, Type *t, int dostrcmp)
-{
-       Type *f1, *f2;
-       Sym *s;
-       
-       s = n->right->sym;
-
-       if(t->etype == TINTER) {
-               f1 = lookdot1(n, s, t, t->type, dostrcmp);
-               if(f1 == T)
-                       return 0;
-
-               n->right = methodname(n->right, t);
-               n->xoffset = f1->width;
-               n->type = f1->type;
-               n->op = ODOTINTER;
-               return 1;
-       }
-
-       // Find the base type: methtype will fail if t
-       // is not of the form T or *T.
-       f2 = methtype(t, 0);
-       if(f2 == T)
-               return 0;
-
-       expandmeth(f2);
-       f2 = lookdot1(n, s, f2, f2->xmethod, dostrcmp);
-       if(f2 == T)
-               return 0;
-
-       // disallow T.m if m requires *T receiver
-       if(isptr[getthisx(f2->type)->type->type->etype]
-       && !isptr[t->etype]
-       && f2->embedded != 2
-       && !isifacemethod(f2->type)) {
-               yyerror("invalid method expression %N (needs pointer receiver: (*%T).%hS)", n, t, f2->sym);
-               return 0;
-       }
-
-       n->right = methodname(n->right, t);
-       n->xoffset = f2->width;
-       n->type = f2->type;
-       n->op = ODOTMETH;
-       return 1;
-}
-
-static Type*
-derefall(Type* t)
-{
-       while(t && t->etype == tptr)
-               t = t->type;
-       return t;
-}
-
-static int
-lookdot(Node *n, Type *t, int dostrcmp)
-{
-       Type *f1, *f2, *tt, *rcvr;
-       Sym *s;
-
-       s = n->right->sym;
-
-       dowidth(t);
-       f1 = T;
-       if(t->etype == TSTRUCT || t->etype == TINTER)
-               f1 = lookdot1(n, s, t, t->type, dostrcmp);
-
-       f2 = T;
-       if(n->left->type == t || n->left->type->sym == S) {
-               f2 = methtype(t, 0);
-               if(f2 != T) {
-                       // Use f2->method, not f2->xmethod: adddot has
-                       // already inserted all the necessary embedded dots.
-                       f2 = lookdot1(n, s, f2, f2->method, dostrcmp);
-               }
-       }
-
-       if(f1 != T) {
-               if(f2 != T)
-                       yyerror("%S is both field and method",
-                               n->right->sym);
-               if(f1->width == BADWIDTH)
-                       fatal("lookdot badwidth %T %p", f1, f1);
-               n->xoffset = f1->width;
-               n->type = f1->type;
-               n->paramfld = f1;
-               if(t->etype == TINTER) {
-                       if(isptr[n->left->type->etype]) {
-                               n->left = nod(OIND, n->left, N);        // implicitstar
-                               n->left->implicit = 1;
-                               typecheck(&n->left, Erv);
-                       }
-                       n->op = ODOTINTER;
-               }
-               return 1;
-       }
-
-       if(f2 != T) {
-               tt = n->left->type;
-               dowidth(tt);
-               rcvr = getthisx(f2->type)->type->type;
-               if(!eqtype(rcvr, tt)) {
-                       if(rcvr->etype == tptr && eqtype(rcvr->type, tt)) {
-                               checklvalue(n->left, "call pointer method on");
-                               n->left = nod(OADDR, n->left, N);
-                               n->left->implicit = 1;
-                               typecheck(&n->left, Etype|Erv);
-                       } else if(tt->etype == tptr && rcvr->etype != tptr && eqtype(tt->type, rcvr)) {
-                               n->left = nod(OIND, n->left, N);
-                               n->left->implicit = 1;
-                               typecheck(&n->left, Etype|Erv);
-                       } else if(tt->etype == tptr && tt->type->etype == tptr && eqtype(derefall(tt), derefall(rcvr))) {
-                               yyerror("calling method %N with receiver %lN requires explicit dereference", n->right, n->left);
-                               while(tt->etype == tptr) {
-                                       // Stop one level early for method with pointer receiver.
-                                       if(rcvr->etype == tptr && tt->type->etype != tptr)
-                                               break;
-                                       n->left = nod(OIND, n->left, N);
-                                       n->left->implicit = 1;
-                                       typecheck(&n->left, Etype|Erv);
-                                       tt = tt->type;
-                               }
-                       } else {
-                               fatal("method mismatch: %T for %T", rcvr, tt);
-                       }
-               }
-               n->right = methodname(n->right, n->left->type);
-               n->xoffset = f2->width;
-               n->type = f2->type;
-//             print("lookdot found [%p] %T\n", f2->type, f2->type);
-               n->op = ODOTMETH;
-               return 1;
-       }
-
-       return 0;
-}
-
-static int
-nokeys(NodeList *l)
-{
-       for(; l; l=l->next)
-               if(l->n->op == OKEY)
-                       return 0;
-       return 1;
-}
-
-static int
-hasddd(Type *t)
-{
-       Type *tl;
-
-       for(tl=t->type; tl; tl=tl->down) {
-               if(tl->isddd)
-                       return 1;
-       }
-       return 0;
-}
-
-static int
-downcount(Type *t)
-{
-       Type *tl;
-       int n;
-
-       n = 0;
-       for(tl=t->type; tl; tl=tl->down) {
-               n++;
-       }
-       return n;
-}
-
-/*
- * typecheck assignment: type list = expression list
- */
-static void
-typecheckaste(int op, Node *call, int isddd, Type *tstruct, NodeList *nl, char *desc)
-{
-       Type *t, *tl, *tn;
-       Node *n;
-       int lno;
-       char *why;
-       int n1, n2;
-
-       lno = lineno;
-
-       if(tstruct->broke)
-               goto out;
-
-       n = N;
-       if(nl != nil && nl->next == nil && (n = nl->n)->type != T)
-       if(n->type->etype == TSTRUCT && n->type->funarg) {
-               if(!hasddd(tstruct)) {
-                       n1 = downcount(tstruct);
-                       n2 = downcount(n->type);
-                       if(n2 > n1)
-                               goto toomany;
-                       if(n2 < n1)
-                               goto notenough;
-               }
-               
-               tn = n->type->type;
-               for(tl=tstruct->type; tl; tl=tl->down) {
-                       if(tl->isddd) {
-                               for(; tn; tn=tn->down) {
-                                       if(assignop(tn->type, tl->type->type, &why) == 0) {
-                                               if(call != N)
-                                                       yyerror("cannot use %T as type %T in argument to %N%s", tn->type, tl->type->type, call, why);
-                                               else
-                                                       yyerror("cannot use %T as type %T in %s%s", tn->type, tl->type->type, desc, why);
-                                       }
-                               }
-                               goto out;
-                       }
-                       if(tn == T)
-                               goto notenough;
-                       if(assignop(tn->type, tl->type, &why) == 0) {
-                               if(call != N)
-                                       yyerror("cannot use %T as type %T in argument to %N%s", tn->type, tl->type, call, why);
-                               else
-                                       yyerror("cannot use %T as type %T in %s%s", tn->type, tl->type, desc, why);
-                       }
-                       tn = tn->down;
-               }
-               if(tn != T)
-                       goto toomany;
-               goto out;
-       }
-
-       n1 = downcount(tstruct);
-       n2 = count(nl);
-       if(!hasddd(tstruct)) {
-               if(n2 > n1)
-                       goto toomany;
-               if(n2 < n1)
-                       goto notenough;
-       }
-       else {
-               if(!isddd) {
-                       if(n2 < n1-1)
-                               goto notenough;
-               } else {
-                       if(n2 > n1)
-                               goto toomany;
-                       if(n2 < n1)
-                               goto notenough;
-               }
-       }
-
-       for(tl=tstruct->type; tl; tl=tl->down) {
-               t = tl->type;
-               if(tl->isddd) {
-                       if(isddd) {
-                               if(nl == nil)
-                                       goto notenough;
-                               if(nl->next != nil)
-                                       goto toomany;
-                               n = nl->n;
-                               setlineno(n);
-                               if(n->type != T)
-                                       nl->n = assignconv(n, t, desc);
-                               goto out;
-                       }
-                       for(; nl; nl=nl->next) {
-                               n = nl->n;
-                               setlineno(nl->n);
-                               if(n->type != T)
-                                       nl->n = assignconv(n, t->type, desc);
-                       }
-                       goto out;
-               }
-               if(nl == nil)
-                       goto notenough;
-               n = nl->n;
-               setlineno(n);
-               if(n->type != T)
-                       nl->n = assignconv(n, t, desc);
-               nl = nl->next;
-       }
-       if(nl != nil)
-               goto toomany;
-       if(isddd) {
-               if(call != N)
-                       yyerror("invalid use of ... in call to %N", call);
-               else
-                       yyerror("invalid use of ... in %O", op);
-       }
-
-out:
-       lineno = lno;
-       return;
-
-notenough:
-       if(n == N || !n->diag) {
-               if(call != N)
-                       yyerror("not enough arguments in call to %N", call);
-               else
-                       yyerror("not enough arguments to %O", op);
-               if(n != N)
-                       n->diag = 1;
-       }
-       goto out;
-
-toomany:
-       if(call != N)
-               yyerror("too many arguments in call to %N", call);
-       else
-               yyerror("too many arguments to %O", op);
-       goto out;
-}
-
-/*
- * type check composite
- */
-
-static void
-fielddup(Node *n, Node **hash, ulong nhash)
-{
-       uint h;
-       char *s;
-       Node *a;
-
-       if(n->op != ONAME)
-               fatal("fielddup: not ONAME");
-       s = n->sym->name;
-       h = stringhash(s)%nhash;
-       for(a=hash[h]; a!=N; a=a->ntest) {
-               if(strcmp(a->sym->name, s) == 0) {
-                       yyerror("duplicate field name in struct literal: %s", s);
-                       return;
-               }
-       }
-       n->ntest = hash[h];
-       hash[h] = n;
-}
-
-static void
-keydup(Node *n, Node **hash, ulong nhash)
-{
-       uint h;
-       ulong b;
-       double d;
-       int i;
-       Node *a, *orign;
-       Node cmp;
-       char *s;
-
-       orign = n;
-       if(n->op == OCONVIFACE)
-               n = n->left;
-       evconst(n);
-       if(n->op != OLITERAL)
-               return; // we dont check variables
-
-       switch(n->val.ctype) {
-       default:        // unknown, bool, nil
-               b = 23;
-               break;
-       case CTINT:
-       case CTRUNE:
-               b = mpgetfix(n->val.u.xval);
-               break;
-       case CTFLT:
-               d = mpgetflt(n->val.u.fval);
-               s = (char*)&d;
-               b = 0;
-               for(i=sizeof(d); i>0; i--)
-                       b = b*PRIME1 + *s++;
-               break;
-       case CTSTR:
-               b = 0;
-               s = n->val.u.sval->s;
-               for(i=n->val.u.sval->len; i>0; i--)
-                       b = b*PRIME1 + *s++;
-               break;
-       }
-
-       h = b%nhash;
-       memset(&cmp, 0, sizeof(cmp));
-       for(a=hash[h]; a!=N; a=a->ntest) {
-               cmp.op = OEQ;
-               cmp.left = n;
-               b = 0;
-               if(a->op == OCONVIFACE && orign->op == OCONVIFACE) {
-                       if(eqtype(a->left->type, n->type)) {
-                               cmp.right = a->left;
-                               evconst(&cmp);
-                               b = cmp.val.u.bval;
-                       }
-               } else if(eqtype(a->type, n->type)) {
-                       cmp.right = a;
-                       evconst(&cmp);
-                       b = cmp.val.u.bval;
-               }
-               if(b) {
-                       yyerror("duplicate key %N in map literal", n);
-                       return;
-               }
-       }
-       orign->ntest = hash[h];
-       hash[h] = orign;
-}
-
-static void
-indexdup(Node *n, Node **hash, ulong nhash)
-{
-       uint h;
-       Node *a;
-       ulong b, c;
-
-       if(n->op != OLITERAL)
-               fatal("indexdup: not OLITERAL");
-
-       b = mpgetfix(n->val.u.xval);
-       h = b%nhash;
-       for(a=hash[h]; a!=N; a=a->ntest) {
-               c = mpgetfix(a->val.u.xval);
-               if(b == c) {
-                       yyerror("duplicate index in array literal: %ld", b);
-                       return;
-               }
-       }
-       n->ntest = hash[h];
-       hash[h] = n;
-}
-
-static int
-prime(ulong h, ulong sr)
-{
-       ulong n;
-
-       for(n=3; n<=sr; n+=2)
-               if(h%n == 0)
-                       return 0;
-       return 1;
-}
-
-static ulong
-inithash(Node *n, Node ***hash, Node **autohash, ulong nautohash)
-{
-       ulong h, sr;
-       NodeList *ll;
-       int i;
-
-       // count the number of entries
-       h = 0;
-       for(ll=n->list; ll; ll=ll->next)
-               h++;
-
-       // if the auto hash table is
-       // large enough use it.
-       if(h <= nautohash) {
-               *hash = autohash;
-               memset(*hash, 0, nautohash * sizeof(**hash));
-               return nautohash;
-       }
-
-       // make hash size odd and 12% larger than entries
-       h += h/8;
-       h |= 1;
-
-       // calculate sqrt of h
-       sr = h/2;
-       for(i=0; i<5; i++)
-               sr = (sr + h/sr)/2;
-
-       // check for primeality
-       while(!prime(h, sr))
-               h += 2;
-
-       // build and return a throw-away hash table
-       *hash = mal(h * sizeof(**hash));
-       memset(*hash, 0, h * sizeof(**hash));
-       return h;
-}
-
-static int
-iscomptype(Type *t)
-{
-       switch(t->etype) {
-       case TARRAY:
-       case TSTRUCT:
-       case TMAP:
-               return 1;
-       case TPTR32:
-       case TPTR64:
-               switch(t->type->etype) {
-               case TARRAY:
-               case TSTRUCT:
-               case TMAP:
-                       return 1;
-               }
-               break;
-       }
-       return 0;
-}
-
-static void
-pushtype(Node *n, Type *t)
-{
-       if(n == N || n->op != OCOMPLIT || !iscomptype(t))
-               return;
-       
-       if(n->right == N) {
-               n->right = typenod(t);
-               n->implicit = 1;  // don't print
-               n->right->implicit = 1;  // * is okay
-       }
-       else if(debug['s']) {
-               typecheck(&n->right, Etype);
-               if(n->right->type != T && eqtype(n->right->type, t))
-                       print("%L: redundant type: %T\n", n->lineno, t);
-       }
-}
-
-static void
-typecheckcomplit(Node **np)
-{
-       int bad, i, nerr;
-       int64 length;
-       Node *l, *n, *norig, *r, **hash;
-       NodeList *ll;
-       Type *t, *f;
-       Sym *s, *s1;
-       int32 lno;
-       ulong nhash;
-       Node *autohash[101];
-
-       n = *np;
-       lno = lineno;
-
-       if(n->right == N) {
-               if(n->list != nil)
-                       setlineno(n->list->n);
-               yyerror("missing type in composite literal");
-               goto error;
-       }
-
-       // Save original node (including n->right)
-       norig = nod(n->op, N, N);
-       *norig = *n;
-
-       setlineno(n->right);
-       l = typecheck(&n->right /* sic */, Etype|Ecomplit);
-       if((t = l->type) == T)
-               goto error;
-       nerr = nerrors;
-       n->type = t;
-
-       if(isptr[t->etype]) {
-               // For better or worse, we don't allow pointers as the composite literal type,
-               // except when using the &T syntax, which sets implicit on the OIND.
-               if(!n->right->implicit) {
-                       yyerror("invalid pointer type %T for composite literal (use &%T instead)", t, t->type);
-                       goto error;
-               }
-               // Also, the underlying type must be a struct, map, slice, or array.
-               if(!iscomptype(t)) {
-                       yyerror("invalid pointer type %T for composite literal", t);
-                       goto error;
-               }
-               t = t->type;
-       }
-
-       switch(t->etype) {
-       default:
-               yyerror("invalid type for composite literal: %T", t);
-               n->type = T;
-               break;
-
-       case TARRAY:
-               nhash = inithash(n, &hash, autohash, nelem(autohash));
-
-               length = 0;
-               i = 0;
-               for(ll=n->list; ll; ll=ll->next) {
-                       l = ll->n;
-                       setlineno(l);
-                       if(l->op != OKEY) {
-                               l = nod(OKEY, nodintconst(i), l);
-                               l->left->type = types[TINT];
-                               l->left->typecheck = 1;
-                               ll->n = l;
-                       }
-
-                       typecheck(&l->left, Erv);
-                       evconst(l->left);
-                       i = nonnegconst(l->left);
-                       if(i < 0 && !l->left->diag) {
-                               yyerror("array index must be non-negative integer constant");
-                               l->left->diag = 1;
-                               i = -(1<<30);   // stay negative for a while
-                       }
-                       if(i >= 0)
-                               indexdup(l->left, hash, nhash);
-                       i++;
-                       if(i > length) {
-                               length = i;
-                               if(t->bound >= 0 && length > t->bound) {
-                                       setlineno(l);
-                                       yyerror("array index %lld out of bounds [0:%lld]", length-1, t->bound);
-                                       t->bound = -1;  // no more errors
-                               }
-                       }
-
-                       r = l->right;
-                       pushtype(r, t->type);
-                       typecheck(&r, Erv);
-                       defaultlit(&r, t->type);
-                       l->right = assignconv(r, t->type, "array element");
-               }
-               if(t->bound == -100)
-                       t->bound = length;
-               if(t->bound < 0)
-                       n->right = nodintconst(length);
-               n->op = OARRAYLIT;
-               break;
-
-       case TMAP:
-               nhash = inithash(n, &hash, autohash, nelem(autohash));
-
-               for(ll=n->list; ll; ll=ll->next) {
-                       l = ll->n;
-                       setlineno(l);
-                       if(l->op != OKEY) {
-                               typecheck(&ll->n, Erv);
-                               yyerror("missing key in map literal");
-                               continue;
-                       }
-
-                       typecheck(&l->left, Erv);
-                       defaultlit(&l->left, t->down);
-                       l->left = assignconv(l->left, t->down, "map key");
-                       if (l->left->op != OCONV)
-                               keydup(l->left, hash, nhash);
-
-                       r = l->right;
-                       pushtype(r, t->type);
-                       typecheck(&r, Erv);
-                       defaultlit(&r, t->type);
-                       l->right = assignconv(r, t->type, "map value");
-               }
-               n->op = OMAPLIT;
-               break;
-
-       case TSTRUCT:
-               bad = 0;
-               if(n->list != nil && nokeys(n->list)) {
-                       // simple list of variables
-                       f = t->type;
-                       for(ll=n->list; ll; ll=ll->next) {
-                               setlineno(ll->n);
-                               typecheck(&ll->n, Erv);
-                               if(f == nil) {
-                                       if(!bad++)
-                                               yyerror("too many values in struct initializer");
-                                       continue;
-                               }
-                               s = f->sym;
-                               if(s != nil && !exportname(s->name) && s->pkg != localpkg)
-                                       yyerror("implicit assignment of unexported field '%s' in %T literal", s->name, t);
-                               // No pushtype allowed here.  Must name fields for that.
-                               ll->n = assignconv(ll->n, f->type, "field value");
-                               ll->n = nod(OKEY, newname(f->sym), ll->n);
-                               ll->n->left->type = f;
-                               ll->n->left->typecheck = 1;
-                               f = f->down;
-                       }
-                       if(f != nil)
-                               yyerror("too few values in struct initializer");
-               } else {
-                       nhash = inithash(n, &hash, autohash, nelem(autohash));
-
-                       // keyed list
-                       for(ll=n->list; ll; ll=ll->next) {
-                               l = ll->n;
-                               setlineno(l);
-                               if(l->op != OKEY) {
-                                       if(!bad++)
-                                               yyerror("mixture of field:value and value initializers");
-                                       typecheck(&ll->n, Erv);
-                                       continue;
-                               }
-                               s = l->left->sym;
-                               if(s == S) {
-                                       yyerror("invalid field name %N in struct initializer", l->left);
-                                       typecheck(&l->right, Erv);
-                                       continue;
-                               }
-
-                               // Sym might have resolved to name in other top-level
-                               // package, because of import dot.  Redirect to correct sym
-                               // before we do the lookup.
-                               if(s->pkg != localpkg && exportname(s->name)) {
-                                       s1 = lookup(s->name);
-                                       if(s1->origpkg == s->pkg)
-                                               s = s1;
-                               }
-                               f = lookdot1(nil, s, t, t->type, 0);
-                               if(f == nil) {
-                                       yyerror("unknown %T field '%S' in struct literal", t, s);
-                                       continue;
-                               }
-                               l->left = newname(s);
-                               l->left->typecheck = 1;
-                               l->left->type = f;
-                               s = f->sym;
-                               fielddup(newname(s), hash, nhash);
-                               r = l->right;
-                               // No pushtype allowed here.  Tried and rejected.
-                               typecheck(&r, Erv);
-                               l->right = assignconv(r, f->type, "field value");
-                       }
-               }
-               n->op = OSTRUCTLIT;
-               break;
-       }
-       if(nerr != nerrors)
-               goto error;
-       
-       n->orig = norig;
-       if(isptr[n->type->etype]) {
-               n = nod(OPTRLIT, n, N);
-               n->typecheck = 1;
-               n->type = n->left->type;
-               n->left->type = t;
-               n->left->typecheck = 1;
-       }
-
-       n->orig = norig;
-       *np = n;
-       lineno = lno;
-       return;
-
-error:
-       n->type = T;
-       *np = n;
-       lineno = lno;
-}
-
-/*
- * lvalue etc
- */
-int
-islvalue(Node *n)
-{
-       switch(n->op) {
-       case OINDEX:
-               if(isfixedarray(n->left->type))
-                       return islvalue(n->left);
-               if(n->left->type != T && n->left->type->etype == TSTRING)
-                       return 0;
-               // fall through
-       case OIND:
-       case ODOTPTR:
-       case OCLOSUREVAR:
-       case OPARAM:
-               return 1;
-       case ODOT:
-               return islvalue(n->left);
-       case ONAME:
-               if(n->class == PFUNC)
-                       return 0;
-               return 1;
-       }
-       return 0;
-}
-
-static void
-checklvalue(Node *n, char *verb)
-{
-       if(!islvalue(n))
-               yyerror("cannot %s %N", verb, n);
-}
-
-void
-checkassign(Node *stmt, Node *n)
-{
-       Node *r, *l;
-
-       // Variables declared in ORANGE are assigned on every iteration.
-       if(n->defn != stmt || stmt->op == ORANGE) {
-               r = outervalue(n);
-               for(l = n; l != r; l = l->left) {
-                       l->assigned = 1;
-                       if(l->closure)
-                               l->closure->assigned = 1;
-               }
-               l->assigned = 1;
-               if(l->closure)
-                       l->closure->assigned = 1;
-       }
-
-       if(islvalue(n))
-               return;
-       if(n->op == OINDEXMAP) {
-               n->etype = 1;
-               return;
-       }
-
-       // have already complained about n being undefined
-       if(n->op == ONONAME)
-               return;
-
-       yyerror("cannot assign to %N", n);
-}
-
-static void
-checkassignlist(Node *stmt, NodeList *l)
-{
-       for(; l; l=l->next)
-               checkassign(stmt, l->n);
-}
-
-// Check whether l and r are the same side effect-free expression,
-// so that it is safe to reuse one instead of computing both.
-int
-samesafeexpr(Node *l, Node *r)
-{
-       if(l->op != r->op || !eqtype(l->type, r->type))
-               return 0;
-       
-       switch(l->op) {
-       case ONAME:
-       case OCLOSUREVAR:
-               return l == r;
-       
-       case ODOT:
-       case ODOTPTR:
-               return l->right != nil && r->right != nil && l->right->sym == r->right->sym && samesafeexpr(l->left, r->left);
-       
-       case OIND:
-               return samesafeexpr(l->left, r->left);
-       
-       case OINDEX:
-               return samesafeexpr(l->left, r->left) && samesafeexpr(l->right, r->right);
-       }
-       
-       return 0;
-}
-
-/*
- * type check assignment.
- * if this assignment is the definition of a var on the left side,
- * fill in the var's type.
- */
-
-static void
-typecheckas(Node *n)
-{
-       // delicate little dance.
-       // the definition of n may refer to this assignment
-       // as its definition, in which case it will call typecheckas.
-       // in that case, do not call typecheck back, or it will cycle.
-       // if the variable has a type (ntype) then typechecking
-       // will not look at defn, so it is okay (and desirable,
-       // so that the conversion below happens).
-       n->left = resolve(n->left);
-       if(n->left->defn != n || n->left->ntype)
-               typecheck(&n->left, Erv | Easgn);
-
-       typecheck(&n->right, Erv);
-       checkassign(n, n->left);
-       if(n->right && n->right->type != T) {
-               if(n->left->type != T)
-                       n->right = assignconv(n->right, n->left->type, "assignment");
-       }
-       if(n->left->defn == n && n->left->ntype == N) {
-               defaultlit(&n->right, T);
-               n->left->type = n->right->type;
-       }
-
-       // second half of dance.
-       // now that right is done, typecheck the left
-       // just to get it over with.  see dance above.
-       n->typecheck = 1;
-       if(n->left->typecheck == 0)
-               typecheck(&n->left, Erv | Easgn);
-       
-       // Recognize slices being updated in place, for better code generation later.
-       // Don't rewrite if using race detector, to avoid needing to teach race detector
-       // about this optimization.
-       if(n->left && n->left->op != OINDEXMAP && n->right && !flag_race) {
-               switch(n->right->op) {
-               case OSLICE:
-               case OSLICE3:
-               case OSLICESTR:
-                       // For x = x[0:y], x can be updated in place, without touching pointer.
-                       // TODO(rsc): Reenable once it is actually updated in place without touching the pointer.
-                       if(0 && samesafeexpr(n->left, n->right->left) && (n->right->right->left == N || iszero(n->right->right->left)))
-                               n->right->reslice = 1;
-                       break;
-               
-               case OAPPEND:
-                       // For x = append(x, ...), x can be updated in place when there is capacity,
-                       // without touching the pointer; otherwise the emitted code to growslice
-                       // can take care of updating the pointer, and only in that case.
-                       // TODO(rsc): Reenable once the emitted code does update the pointer.
-                       if(0 && n->right->list != nil && samesafeexpr(n->left, n->right->list->n))
-                               n->right->reslice = 1;
-                       break;
-               }
-       }
-}
-
-static void
-checkassignto(Type *src, Node *dst)
-{
-       char *why;
-
-       if(assignop(src, dst->type, &why) == 0) {
-               yyerror("cannot assign %T to %lN in multiple assignment%s", src, dst, why);
-               return;
-       }
-}
-
-static void
-typecheckas2(Node *n)
-{
-       int cl, cr;
-       NodeList *ll, *lr;
-       Node *l, *r;
-       Iter s;
-       Type *t;
-
-       for(ll=n->list; ll; ll=ll->next) {
-               // delicate little dance.
-               ll->n = resolve(ll->n);
-               if(ll->n->defn != n || ll->n->ntype)
-                       typecheck(&ll->n, Erv | Easgn);
-       }
-       cl = count(n->list);
-       cr = count(n->rlist);
-       if(cl > 1 && cr == 1)
-               typecheck(&n->rlist->n, Erv | Efnstruct);
-       else
-               typechecklist(n->rlist, Erv);
-       checkassignlist(n, n->list);
-
-       if(cl == cr) {
-               // easy
-               for(ll=n->list, lr=n->rlist; ll; ll=ll->next, lr=lr->next) {
-                       if(ll->n->type != T && lr->n->type != T)
-                               lr->n = assignconv(lr->n, ll->n->type, "assignment");
-                       if(ll->n->defn == n && ll->n->ntype == N) {
-                               defaultlit(&lr->n, T);
-                               ll->n->type = lr->n->type;
-                       }
-               }
-               goto out;
-       }
-
-
-       l = n->list->n;
-       r = n->rlist->n;
-
-       // x,y,z = f()
-       if(cr == 1) {
-               if(r->type == T)
-                       goto out;
-               switch(r->op) {
-               case OCALLMETH:
-               case OCALLINTER:
-               case OCALLFUNC:
-                       if(r->type->etype != TSTRUCT || r->type->funarg == 0)
-                               break;
-                       cr = structcount(r->type);
-                       if(cr != cl)
-                               goto mismatch;
-                       n->op = OAS2FUNC;
-                       t = structfirst(&s, &r->type);
-                       for(ll=n->list; ll; ll=ll->next) {
-                               if(t->type != T && ll->n->type != T)
-                                       checkassignto(t->type, ll->n);
-                               if(ll->n->defn == n && ll->n->ntype == N)
-                                       ll->n->type = t->type;
-                               t = structnext(&s);
-                       }
-                       goto out;
-               }
-       }
-
-       // x, ok = y
-       if(cl == 2 && cr == 1) {
-               if(r->type == T)
-                       goto out;
-               switch(r->op) {
-               case OINDEXMAP:
-               case ORECV:
-               case ODOTTYPE:
-                       switch(r->op) {
-                       case OINDEXMAP:
-                               n->op = OAS2MAPR;
-                               break;
-                       case ORECV:
-                               n->op = OAS2RECV;
-                               break;
-                       case ODOTTYPE:
-                               n->op = OAS2DOTTYPE;
-                               r->op = ODOTTYPE2;
-                               break;
-                       }
-                       if(l->type != T)
-                               checkassignto(r->type, l);
-                       if(l->defn == n)
-                               l->type = r->type;
-                       l = n->list->next->n;
-                       if(l->type != T && l->type->etype != TBOOL)
-                               checkassignto(types[TBOOL], l);
-                       if(l->defn == n && l->ntype == N)
-                               l->type = types[TBOOL];
-                       goto out;
-               }
-       }
-
-mismatch:
-       yyerror("assignment count mismatch: %d = %d", cl, cr);
-
-out:
-       // second half of dance
-       n->typecheck = 1;
-       for(ll=n->list; ll; ll=ll->next)
-               if(ll->n->typecheck == 0)
-                       typecheck(&ll->n, Erv | Easgn);
-}
-
-/*
- * type check function definition
- */
-static void
-typecheckfunc(Node *n)
-{
-       Type *t, *rcvr;
-       NodeList *l;
-
-       typecheck(&n->nname, Erv | Easgn);
-       if((t = n->nname->type) == T)
-               return;
-       n->type = t;
-       t->nname = n->nname;
-       rcvr = getthisx(t)->type;
-       if(rcvr != nil && n->shortname != N && !isblank(n->shortname))
-               addmethod(n->shortname->sym, t, 1, n->nname->nointerface);
-
-       for(l=n->dcl; l; l=l->next)
-               if(l->n->op == ONAME && (l->n->class == PPARAM || l->n->class == PPARAMOUT))
-                       l->n->decldepth = 1;
-}
-
-static void
-stringtoarraylit(Node **np)
-{
-       int32 i;
-       NodeList *l;
-       Strlit *s;
-       char *p, *ep;
-       Rune r;
-       Node *nn, *n;
-
-       n = *np;
-       if(n->left->op != OLITERAL || n->left->val.ctype != CTSTR)
-               fatal("stringtoarraylit %N", n);
-
-       s = n->left->val.u.sval;
-       l = nil;
-       p = s->s;
-       ep = s->s + s->len;
-       i = 0;
-       if(n->type->type->etype == TUINT8) {
-               // raw []byte
-               while(p < ep)
-                       l = list(l, nod(OKEY, nodintconst(i++), nodintconst((uchar)*p++)));
-       } else {
-               // utf-8 []rune
-               while(p < ep) {
-                       p += chartorune(&r, p);
-                       l = list(l, nod(OKEY, nodintconst(i++), nodintconst(r)));
-               }
-       }
-       nn = nod(OCOMPLIT, N, typenod(n->type));
-       nn->list = l;
-       typecheck(&nn, Erv);
-       *np = nn;
-}
-
-
-static int ntypecheckdeftype;
-static NodeList *methodqueue;
-
-static void
-domethod(Node *n)
-{
-       Node *nt;
-       Type *t;
-
-       nt = n->type->nname;
-       typecheck(&nt, Etype);
-       if(nt->type == T) {
-               // type check failed; leave empty func
-               n->type->etype = TFUNC;
-               n->type->nod = N;
-               return;
-       }
-       
-       // If we have
-       //      type I interface {
-       //              M(_ int)
-       //      }
-       // then even though I.M looks like it doesn't care about the
-       // value of its argument, a specific implementation of I may
-       // care.  The _ would suppress the assignment to that argument
-       // while generating a call, so remove it.
-       for(t=getinargx(nt->type)->type; t; t=t->down) {
-               if(t->sym != nil && strcmp(t->sym->name, "_") == 0)
-                       t->sym = nil;
-       }
-
-       *n->type = *nt->type;
-       n->type->nod = N;
-       checkwidth(n->type);
-}
-
-static NodeList *mapqueue;
-
-void
-copytype(Node *n, Type *t)
-{
-       int maplineno, embedlineno, lno;
-       NodeList *l;
-
-       if(t->etype == TFORW) {
-               // This type isn't computed yet; when it is, update n.
-               t->copyto = list(t->copyto, n);
-               return;
-       }
-
-       maplineno = n->type->maplineno;
-       embedlineno = n->type->embedlineno;
-
-       l = n->type->copyto;
-       *n->type = *t;
-
-       t = n->type;
-       t->sym = n->sym;
-       t->local = n->local;
-       t->vargen = n->vargen;
-       t->siggen = 0;
-       t->method = nil;
-       t->xmethod = nil;
-       t->nod = N;
-       t->printed = 0;
-       t->deferwidth = 0;
-       t->copyto = nil;
-       
-       // Update nodes waiting on this type.
-       for(; l; l=l->next)
-               copytype(l->n, t);
-
-       // Double-check use of type as embedded type.
-       lno = lineno;
-       if(embedlineno) {
-               lineno = embedlineno;
-               if(isptr[t->etype])
-                       yyerror("embedded type cannot be a pointer");
-       }
-       lineno = lno;
-       
-       // Queue check for map until all the types are done settling.
-       if(maplineno) {
-               t->maplineno = maplineno;
-               mapqueue = list(mapqueue, n);
-       }
-}
-
-static void
-typecheckdeftype(Node *n)
-{
-       int lno;
-       Type *t;
-       NodeList *l;
-
-       ntypecheckdeftype++;
-       lno = lineno;
-       setlineno(n);
-       n->type->sym = n->sym;
-       n->typecheck = 1;
-       typecheck(&n->ntype, Etype);
-       if((t = n->ntype->type) == T) {
-               n->diag = 1;
-               n->type = T;
-               goto ret;
-       }
-       if(n->type == T) {
-               n->diag = 1;
-               goto ret;
-       }
-
-       // copy new type and clear fields
-       // that don't come along.
-       // anything zeroed here must be zeroed in
-       // typedcl2 too.
-       copytype(n, t);
-
-ret:
-       lineno = lno;
-
-       // if there are no type definitions going on, it's safe to
-       // try to resolve the method types for the interfaces
-       // we just read.
-       if(ntypecheckdeftype == 1) {
-               while((l = methodqueue) != nil) {
-                       methodqueue = nil;
-                       for(; l; l=l->next)
-                               domethod(l->n);
-               }
-               for(l=mapqueue; l; l=l->next) {
-                       lineno = l->n->type->maplineno;
-                       maptype(l->n->type, types[TBOOL]);
-               }
-               lineno = lno;
-       }
-       ntypecheckdeftype--;
-}
-
-void
-queuemethod(Node *n)
-{
-       if(ntypecheckdeftype == 0) {
-               domethod(n);
-               return;
-       }
-       methodqueue = list(methodqueue, n);
-}
-
-Node*
-typecheckdef(Node *n)
-{
-       int lno, nerrors0;
-       Node *e;
-       Type *t;
-       NodeList *l;
-
-       lno = lineno;
-       setlineno(n);
-
-       if(n->op == ONONAME) {
-               if(!n->diag) {
-                       n->diag = 1;
-                       if(n->lineno != 0)
-                               lineno = n->lineno;
-                       // Note: adderrorname looks for this string and
-                       // adds context about the outer expression
-                       yyerror("undefined: %S", n->sym);
-               }
-               return n;
-       }
-
-       if(n->walkdef == 1)
-               return n;
-
-       l = mal(sizeof *l);
-       l->n = n;
-       l->next = typecheckdefstack;
-       typecheckdefstack = l;
-
-       if(n->walkdef == 2) {
-               flusherrors();
-               print("typecheckdef loop:");
-               for(l=typecheckdefstack; l; l=l->next)
-                       print(" %S", l->n->sym);
-               print("\n");
-               fatal("typecheckdef loop");
-       }
-       n->walkdef = 2;
-
-       if(n->type != T || n->sym == S) // builtin or no name
-               goto ret;
-
-       switch(n->op) {
-       default:
-               fatal("typecheckdef %O", n->op);
-
-       case OGOTO:
-       case OLABEL:
-               // not really syms
-               break;
-
-       case OLITERAL:
-               if(n->ntype != N) {
-                       typecheck(&n->ntype, Etype);
-                       n->type = n->ntype->type;
-                       n->ntype = N;
-                       if(n->type == T) {
-                               n->diag = 1;
-                               goto ret;
-                       }
-               }
-               e = n->defn;
-               n->defn = N;
-               if(e == N) {
-                       lineno = n->lineno;
-                       dump("typecheckdef nil defn", n);
-                       yyerror("xxx");
-               }
-               typecheck(&e, Erv | Eiota);
-               if(isconst(e, CTNIL)) {
-                       yyerror("const initializer cannot be nil");
-                       goto ret;
-               }
-               if(e->type != T && e->op != OLITERAL || !isgoconst(e)) {
-                       if(!e->diag) {
-                               yyerror("const initializer %N is not a constant", e);
-                               e->diag = 1;
-                       }
-                       goto ret;
-               }
-               t = n->type;
-               if(t != T) {
-                       if(!okforconst[t->etype]) {
-                               yyerror("invalid constant type %T", t);
-                               goto ret;
-                       }
-                       if(!isideal(e->type) && !eqtype(t, e->type)) {
-                               yyerror("cannot use %lN as type %T in const initializer", e, t);
-                               goto ret;
-                       }
-                       convlit(&e, t);
-               }
-               n->val = e->val;
-               n->type = e->type;
-               break;
-
-       case ONAME:
-               if(n->ntype != N) {
-                       typecheck(&n->ntype, Etype);
-                       n->type = n->ntype->type;
-
-                       if(n->type == T) {
-                               n->diag = 1;
-                               goto ret;
-                       }
-               }
-               if(n->type != T)
-                       break;
-               if(n->defn == N) {
-                       if(n->etype != 0)       // like OPRINTN
-                               break;
-                       if(nsavederrors+nerrors > 0) {
-                               // Can have undefined variables in x := foo
-                               // that make x have an n->ndefn == nil.
-                               // If there are other errors anyway, don't
-                               // bother adding to the noise.
-                               break;
-                       }
-                       fatal("var without type, init: %S", n->sym);
-               }
-               if(n->defn->op == ONAME) {
-                       typecheck(&n->defn, Erv);
-                       n->type = n->defn->type;
-                       break;
-               }
-               typecheck(&n->defn, Etop);      // fills in n->type
-               break;
-
-       case OTYPE:
-               if(curfn)
-                       defercheckwidth();
-               n->walkdef = 1;
-               n->type = typ(TFORW);
-               n->type->sym = n->sym;
-               nerrors0 = nerrors;
-               typecheckdeftype(n);
-               if(n->type->etype == TFORW && nerrors > nerrors0) {
-                       // Something went wrong during type-checking,
-                       // but it was reported. Silence future errors.
-                       n->type->broke = 1;
-               }
-               if(curfn)
-                       resumecheckwidth();
-               break;
-
-       case OPACK:
-               // nothing to see here
-               break;
-       }
-
-ret:
-       if(n->op != OLITERAL && n->type != T && isideal(n->type))
-               fatal("got %T for %N", n->type, n);
-       if(typecheckdefstack->n != n)
-               fatal("typecheckdefstack mismatch");
-       l = typecheckdefstack;
-       typecheckdefstack = l->next;
-
-       lineno = lno;
-       n->walkdef = 1;
-       return n;
-}
-
-static int
-checkmake(Type *t, char *arg, Node *n)
-{
-       if(n->op == OLITERAL) {
-               switch(n->val.ctype) {
-               case CTINT:
-               case CTRUNE:
-               case CTFLT:
-               case CTCPLX:
-                       n->val = toint(n->val);
-                       if(mpcmpfixc(n->val.u.xval, 0) < 0) {
-                               yyerror("negative %s argument in make(%T)", arg, t);
-                               return -1;
-                       }
-                       if(mpcmpfixfix(n->val.u.xval, maxintval[TINT]) > 0) {
-                               yyerror("%s argument too large in make(%T)", arg, t);
-                               return -1;
-                       }
-                       
-                       // Delay defaultlit until after we've checked range, to avoid
-                       // a redundant "constant NNN overflows int" error.
-                       defaultlit(&n, types[TINT]);
-                       return 0;
-               default:
-                       break;
-               }
-       }
-
-       if(!isint[n->type->etype] && n->type->etype != TIDEAL) {
-               yyerror("non-integer %s argument in make(%T) - %T", arg, t, n->type);
-               return -1;
-       }
-
-       // Defaultlit still necessary for non-constant: n might be 1<<k.
-       defaultlit(&n, types[TINT]);
-
-       return 0;
-}
-
-static void    markbreaklist(NodeList*, Node*);
-
-static void
-markbreak(Node *n, Node *implicit)
-{
-       Label *lab;
-
-       if(n == N)
-               return;
-
-       switch(n->op) {
-       case OBREAK:
-               if(n->left == N) {
-                       if(implicit)
-                               implicit->hasbreak = 1;
-               } else {
-                       lab = n->left->sym->label;
-                       if(lab != L)
-                               lab->def->hasbreak = 1;
-               }
-               break;
-       
-       case OFOR:
-       case OSWITCH:
-       case OTYPESW:
-       case OSELECT:
-       case ORANGE:
-               implicit = n;
-               // fall through
-       
-       default:
-               markbreak(n->left, implicit);
-               markbreak(n->right, implicit);
-               markbreak(n->ntest, implicit);
-               markbreak(n->nincr, implicit);
-               markbreaklist(n->ninit, implicit);
-               markbreaklist(n->nbody, implicit);
-               markbreaklist(n->nelse, implicit);
-               markbreaklist(n->list, implicit);
-               markbreaklist(n->rlist, implicit);
-               break;
-       }
-}
-
-static void
-markbreaklist(NodeList *l, Node *implicit)
-{
-       Node *n;
-       Label *lab;
-
-       for(; l; l=l->next) {
-               n = l->n;
-               if(n->op == OLABEL && l->next && n->defn == l->next->n) {
-                       switch(n->defn->op) {
-                       case OFOR:
-                       case OSWITCH:
-                       case OTYPESW:
-                       case OSELECT:
-                       case ORANGE:
-                               lab = mal(sizeof *lab);
-                               lab->def = n->defn;
-                               n->left->sym->label = lab;
-                               markbreak(n->defn, n->defn);
-                               n->left->sym->label = L;
-                               l = l->next;
-                               continue;
-                       }
-               }
-               markbreak(n, implicit);
-       }
-}
-
-static int
-isterminating(NodeList *l, int top)
-{
-       int def;
-       Node *n;
-
-       if(l == nil)
-               return 0;
-       if(top) {
-               while(l->next && l->n->op != OLABEL)
-                       l = l->next;
-               markbreaklist(l, nil);
-       }
-       while(l->next)
-               l = l->next;
-       n = l->n;
-
-       if(n == N)
-               return 0;
-
-       switch(n->op) {
-       // NOTE: OLABEL is treated as a separate statement,
-       // not a separate prefix, so skipping to the last statement
-       // in the block handles the labeled statement case by
-       // skipping over the label. No case OLABEL here.
-
-       case OBLOCK:
-               return isterminating(n->list, 0);
-
-       case OGOTO:
-       case ORETURN:
-       case ORETJMP:
-       case OPANIC:
-       case OXFALL:
-               return 1;
-
-       case OFOR:
-               if(n->ntest != N)
-                       return 0;
-               if(n->hasbreak)
-                       return 0;
-               return 1;
-
-       case OIF:
-               return isterminating(n->nbody, 0) && isterminating(n->nelse, 0);
-
-       case OSWITCH:
-       case OTYPESW:
-       case OSELECT:
-               if(n->hasbreak)
-                       return 0;
-               def = 0;
-               for(l=n->list; l; l=l->next) {
-                       if(!isterminating(l->n->nbody, 0))
-                               return 0;
-                       if(l->n->list == nil) // default
-                               def = 1;
-               }
-               if(n->op != OSELECT && !def)
-                       return 0;
-               return 1;
-       }
-       
-       return 0;
-}
-
-void
-checkreturn(Node *fn)
-{
-       if(fn->type->outtuple && fn->nbody != nil)
-               if(!isterminating(fn->nbody, 1))
-                       yyerrorl(fn->endlineno, "missing return at end of function");
-}
diff --git a/src/cmd/gc/unsafe.c b/src/cmd/gc/unsafe.c
deleted file mode 100644 (file)
index 95d212e..0000000
+++ /dev/null
@@ -1,150 +0,0 @@
-// Copyright 2009 The Go Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style
-// license that can be found in the LICENSE file.
-
-#include <u.h>
-#include <libc.h>
-#include "go.h"
-
-/*
- * look for
- *     unsafe.Sizeof
- *     unsafe.Offsetof
- *     unsafe.Alignof
- * rewrite with a constant
- */
-Node*
-unsafenmagic(Node *nn)
-{
-       Node *r, *n, *base, *r1;
-       Sym *s;
-       Type *t, *tr;
-       vlong v;
-       Val val;
-       Node *fn;
-       NodeList *args;
-
-       fn = nn->left;
-       args = nn->list;
-
-       if(safemode || fn == N || fn->op != ONAME)
-               goto no;
-       if((s = fn->sym) == S)
-               goto no;
-       if(s->pkg != unsafepkg)
-               goto no;
-
-       if(args == nil) {
-               yyerror("missing argument for %S", s);
-               goto no;
-       }
-       r = args->n;
-
-       if(strcmp(s->name, "Sizeof") == 0) {
-               typecheck(&r, Erv);
-               defaultlit(&r, T);
-               tr = r->type;
-               if(tr == T)
-                       goto bad;
-               dowidth(tr);
-               v = tr->width;
-               goto yes;
-       }
-       if(strcmp(s->name, "Offsetof") == 0) {
-               // must be a selector.
-               if(r->op != OXDOT)
-                       goto bad;
-               // Remember base of selector to find it back after dot insertion.
-               // Since r->left may be mutated by typechecking, check it explicitly
-               // first to track it correctly.
-               typecheck(&r->left, Erv);
-               base = r->left;
-               typecheck(&r, Erv);
-               switch(r->op) {
-               case ODOT:
-               case ODOTPTR:
-                       break;
-               case OCALLPART:
-                       yyerror("invalid expression %N: argument is a method value", nn);
-                       v = 0;
-                       goto ret;
-               default:
-                       goto bad;
-               }
-               v = 0;
-               // add offsets for inserted dots.
-               for(r1=r; r1->left!=base; r1=r1->left) {
-                       switch(r1->op) {
-                       case ODOT:
-                               v += r1->xoffset;
-                               break;
-                       case ODOTPTR:
-                               yyerror("invalid expression %N: selector implies indirection of embedded %N", nn, r1->left);
-                               goto ret;
-                       default:
-                               dump("unsafenmagic", r);
-                               fatal("impossible %#O node after dot insertion", r1->op);
-                               goto bad;
-                       }
-               }
-               v += r1->xoffset;
-               goto yes;
-       }
-       if(strcmp(s->name, "Alignof") == 0) {
-               typecheck(&r, Erv);
-               defaultlit(&r, T);
-               tr = r->type;
-               if(tr == T)
-                       goto bad;
-
-               // make struct { byte; T; }
-               t = typ(TSTRUCT);
-               t->type = typ(TFIELD);
-               t->type->type = types[TUINT8];
-               t->type->down = typ(TFIELD);
-               t->type->down->type = tr;
-               // compute struct widths
-               dowidth(t);
-
-               // the offset of T is its required alignment
-               v = t->type->down->width;
-               goto yes;
-       }
-
-no:
-       return N;
-
-bad:
-       yyerror("invalid expression %N", nn);
-       v = 0;
-       goto ret;
-
-yes:
-       if(args->next != nil)
-               yyerror("extra arguments for %S", s);
-ret:
-       // any side effects disappear; ignore init
-       val.ctype = CTINT;
-       val.u.xval = mal(sizeof(*n->val.u.xval));
-       mpmovecfix(val.u.xval, v);
-       n = nod(OLITERAL, N, N);
-       n->orig = nn;
-       n->val = val;
-       n->type = types[TUINTPTR];
-       nn->type = types[TUINTPTR];
-       return n;
-}
-
-int
-isunsafebuiltin(Node *n)
-{
-       if(n == N || n->op != ONAME || n->sym == S || n->sym->pkg != unsafepkg)
-               return 0;
-       if(strcmp(n->sym->name, "Sizeof") == 0)
-               return 1;
-       if(strcmp(n->sym->name, "Offsetof") == 0)
-               return 1;
-       if(strcmp(n->sym->name, "Alignof") == 0)
-               return 1;
-       return 0;
-}
diff --git a/src/cmd/gc/unsafe.go b/src/cmd/gc/unsafe.go
deleted file mode 100644 (file)
index c3c6278..0000000
+++ /dev/null
@@ -1,18 +0,0 @@
-// Copyright 2009 The Go Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style
-// license that can be found in the LICENSE file.
-
-// NOTE: If you change this file you must run "./mkbuiltin"
-// to update builtin.c.boot.  This is not done automatically
-// to avoid depending on having a working compiler binary.
-
-// +build ignore
-
-package PACKAGE
-
-type Pointer uintptr // not really; filled in by compiler
-
-// return types here are ignored; see unsafe.c
-func Offsetof(any) uintptr
-func Sizeof(any) uintptr
-func Alignof(any) uintptr
diff --git a/src/cmd/gc/walk.c b/src/cmd/gc/walk.c
deleted file mode 100644 (file)
index 50dae8c..0000000
+++ /dev/null
@@ -1,4189 +0,0 @@
-// Copyright 2009 The Go Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style
-// license that can be found in the LICENSE file.
-
-#include       <u.h>
-#include       <libc.h>
-#include       "go.h"
-#include       "../ld/textflag.h"
-#include       "../../runtime/mgc0.h"
-
-static Node*   walkprint(Node*, NodeList**);
-static Node*   writebarrierfn(char*, Type*, Type*);
-static Node*   applywritebarrier(Node*, NodeList**);
-static Node*   mapfn(char*, Type*);
-static Node*   mapfndel(char*, Type*);
-static Node*   ascompatee1(int, Node*, Node*, NodeList**);
-static NodeList*       ascompatee(int, NodeList*, NodeList*, NodeList**);
-static NodeList*       ascompatet(int, NodeList*, Type**, int, NodeList**);
-static NodeList*       ascompatte(int, Node*, int, Type**, NodeList*, int, NodeList**);
-static Node*   convas(Node*, NodeList**);
-static void    heapmoves(void);
-static NodeList*       paramstoheap(Type **argin, int out);
-static NodeList*       reorder1(NodeList*);
-static NodeList*       reorder3(NodeList*);
-static Node*   addstr(Node*, NodeList**);
-static Node*   appendslice(Node*, NodeList**);
-static Node*   append(Node*, NodeList**);
-static Node*   copyany(Node*, NodeList**, int);
-static Node*   sliceany(Node*, NodeList**);
-static void    walkcompare(Node**, NodeList**);
-static void    walkrotate(Node**);
-static void    walkmul(Node**, NodeList**);
-static void    walkdiv(Node**, NodeList**);
-static int     bounded(Node*, int64);
-static Mpint   mpzero;
-static void    walkprintfunc(Node**, NodeList**);
-
-// The constant is known to runtime.
-enum
-{
-       tmpstringbufsize = 32,
-};
-
-void
-walk(Node *fn)
-{
-       char s[50];
-       NodeList *l;
-       int lno;
-
-       curfn = fn;
-
-       if(debug['W']) {
-               snprint(s, sizeof(s), "\nbefore %S", curfn->nname->sym);
-               dumplist(s, curfn->nbody);
-       }
-
-       lno = lineno;
-
-       // Final typecheck for any unused variables.
-       // It's hard to be on the heap when not-used, but best to be consistent about &~PHEAP here and below.
-       for(l=fn->dcl; l; l=l->next)
-               if(l->n->op == ONAME && (l->n->class&~PHEAP) == PAUTO)
-                       typecheck(&l->n, Erv | Easgn);
-
-       // Propagate the used flag for typeswitch variables up to the NONAME in it's definition.
-       for(l=fn->dcl; l; l=l->next)
-               if(l->n->op == ONAME && (l->n->class&~PHEAP) == PAUTO && l->n->defn && l->n->defn->op == OTYPESW && l->n->used)
-                       l->n->defn->left->used++;
-       
-       for(l=fn->dcl; l; l=l->next) {
-               if(l->n->op != ONAME || (l->n->class&~PHEAP) != PAUTO || l->n->sym->name[0] == '&' || l->n->used)
-                       continue;
-               if(l->n->defn && l->n->defn->op == OTYPESW) {
-                       if(l->n->defn->left->used)
-                               continue;
-                       lineno = l->n->defn->left->lineno;
-                       yyerror("%S declared and not used", l->n->sym);
-                       l->n->defn->left->used = 1; // suppress repeats
-               } else {
-                       lineno = l->n->lineno;
-                       yyerror("%S declared and not used", l->n->sym);
-               }
-       }       
-
-       lineno = lno;
-       if(nerrors != 0)
-               return;
-       walkstmtlist(curfn->nbody);
-       if(debug['W']) {
-               snprint(s, sizeof(s), "after walk %S", curfn->nname->sym);
-               dumplist(s, curfn->nbody);
-       }
-       heapmoves();
-       if(debug['W'] && curfn->enter != nil) {
-               snprint(s, sizeof(s), "enter %S", curfn->nname->sym);
-               dumplist(s, curfn->enter);
-       }
-}
-
-
-void
-walkstmtlist(NodeList *l)
-{
-       for(; l; l=l->next)
-               walkstmt(&l->n);
-}
-
-static int
-samelist(NodeList *a, NodeList *b)
-{
-       for(; a && b; a=a->next, b=b->next)
-               if(a->n != b->n)
-                       return 0;
-       return a == b;
-}
-
-static int
-paramoutheap(Node *fn)
-{
-       NodeList *l;
-
-       for(l=fn->dcl; l; l=l->next) {
-               switch(l->n->class) {
-               case PPARAMOUT:
-               case PPARAMOUT|PHEAP:
-                       return l->n->addrtaken;
-               case PAUTO:
-               case PAUTO|PHEAP:
-                       // stop early - parameters are over
-                       return 0;
-               }
-       }
-       return 0;
-}
-
-// adds "adjust" to all the argument locations for the call n.
-// n must be a defer or go node that has already been walked.
-static void
-adjustargs(Node *n, int adjust)
-{
-       Node *callfunc, *arg, *lhs;
-       NodeList *args;
-
-       callfunc = n->left;
-       for(args = callfunc->list; args != 0; args = args->next) {
-               arg = args->n;
-               if(arg->op != OAS)
-                       yyerror("call arg not assignment");
-               lhs = arg->left;
-               if(lhs->op == ONAME) {
-                       // This is a temporary introduced by reorder1.
-                       // The real store to the stack appears later in the arg list.
-                       continue;
-               }
-               if(lhs->op != OINDREG) {
-                       yyerror("call argument store does not use OINDREG");
-               }
-               // can't really check this in machine-indep code.
-               //if(lhs->val.u.reg != D_SP)
-               //      yyerror("call arg assign not indreg(SP)");
-               lhs->xoffset += adjust;
-       }
-}
-
-void
-walkstmt(Node **np)
-{
-       NodeList *init;
-       NodeList *ll, *rl;
-       int cl;
-       Node *n, *f;
-
-       n = *np;
-       if(n == N)
-               return;
-       if(n->dodata == 2) // don't walk, generated by anylit.
-               return;
-
-       setlineno(n);
-
-       walkstmtlist(n->ninit);
-
-       switch(n->op) {
-       default:
-               if(n->op == ONAME)
-                       yyerror("%S is not a top level statement", n->sym);
-               else
-                       yyerror("%O is not a top level statement", n->op);
-               dump("nottop", n);
-               break;
-
-       case OAS:
-       case OASOP:
-       case OAS2:
-       case OAS2DOTTYPE:
-       case OAS2RECV:
-       case OAS2FUNC:
-       case OAS2MAPR:
-       case OCLOSE:
-       case OCOPY:
-       case OCALLMETH:
-       case OCALLINTER:
-       case OCALL:
-       case OCALLFUNC:
-       case ODELETE:
-       case OSEND:
-       case OPRINT:
-       case OPRINTN:
-       case OPANIC:
-       case OEMPTY:
-       case ORECOVER:
-               if(n->typecheck == 0)
-                       fatal("missing typecheck: %+N", n);
-               init = n->ninit;
-               n->ninit = nil;
-               walkexpr(&n, &init);
-               addinit(&n, init);
-               if((*np)->op == OCOPY && n->op == OCONVNOP)
-                       n->op = OEMPTY; // don't leave plain values as statements.
-               break;
-
-       case ORECV:
-               // special case for a receive where we throw away
-               // the value received.
-               if(n->typecheck == 0)
-                       fatal("missing typecheck: %+N", n);
-               init = n->ninit;
-               n->ninit = nil;
-
-               walkexpr(&n->left, &init);
-               n = mkcall1(chanfn("chanrecv1", 2, n->left->type), T, &init, typename(n->left->type), n->left, nodnil());
-               walkexpr(&n, &init);
-
-               addinit(&n, init);
-               break;
-
-       case OBREAK:
-       case ODCL:
-       case OCONTINUE:
-       case OFALL:
-       case OGOTO:
-       case OLABEL:
-       case ODCLCONST:
-       case ODCLTYPE:
-       case OCHECKNIL:
-       case OVARKILL:
-               break;
-
-       case OBLOCK:
-               walkstmtlist(n->list);
-               break;
-
-       case OXCASE:
-               yyerror("case statement out of place");
-               n->op = OCASE;
-       case OCASE:
-               walkstmt(&n->right);
-               break;
-
-       case ODEFER:
-               hasdefer = 1;
-               switch(n->left->op) {
-               case OPRINT:
-               case OPRINTN:
-                       walkprintfunc(&n->left, &n->ninit);
-                       break;
-               case OCOPY:
-                       n->left = copyany(n->left, &n->ninit, 1);
-                       break;
-               default:
-                       walkexpr(&n->left, &n->ninit);
-                       break;
-               }
-               // make room for size & fn arguments.
-               adjustargs(n, 2 * widthptr);
-               break;
-
-       case OFOR:
-               if(n->ntest != N) {
-                       walkstmtlist(n->ntest->ninit);
-                       init = n->ntest->ninit;
-                       n->ntest->ninit = nil;
-                       walkexpr(&n->ntest, &init);
-                       addinit(&n->ntest, init);
-               }
-               walkstmt(&n->nincr);
-               walkstmtlist(n->nbody);
-               break;
-
-       case OIF:
-               walkexpr(&n->ntest, &n->ninit);
-               walkstmtlist(n->nbody);
-               walkstmtlist(n->nelse);
-               break;
-
-       case OPROC:
-               switch(n->left->op) {
-               case OPRINT:
-               case OPRINTN:
-                       walkprintfunc(&n->left, &n->ninit);
-                       break;
-               case OCOPY:
-                       n->left = copyany(n->left, &n->ninit, 1);
-                       break;
-               default:
-                       walkexpr(&n->left, &n->ninit);
-                       break;
-               }
-               // make room for size & fn arguments.
-               adjustargs(n, 2 * widthptr);
-               break;
-
-       case ORETURN:
-               walkexprlist(n->list, &n->ninit);
-               if(n->list == nil)
-                       break;
-               if((curfn->type->outnamed && count(n->list) > 1) || paramoutheap(curfn)) {
-                       // assign to the function out parameters,
-                       // so that reorder3 can fix up conflicts
-                       rl = nil;
-                       for(ll=curfn->dcl; ll != nil; ll=ll->next) {
-                               cl = ll->n->class & ~PHEAP;
-                               if(cl == PAUTO)
-                                       break;
-                               if(cl == PPARAMOUT)
-                                       rl = list(rl, ll->n);
-                       }
-                       if(samelist(rl, n->list)) {
-                               // special return in disguise
-                               n->list = nil;
-                               break;
-                       }
-                       if(count(n->list) == 1 && count(rl) > 1) {
-                               // OAS2FUNC in disguise
-                               f = n->list->n;
-                               if(f->op != OCALLFUNC && f->op != OCALLMETH && f->op != OCALLINTER)
-                                       fatal("expected return of call, have %N", f);
-                               n->list = concat(list1(f), ascompatet(n->op, rl, &f->type, 0, &n->ninit));
-                               break;
-                       }
-
-                       // move function calls out, to make reorder3's job easier.
-                       walkexprlistsafe(n->list, &n->ninit);
-                       ll = ascompatee(n->op, rl, n->list, &n->ninit);
-                       n->list = reorder3(ll);
-                       break;
-               }
-               ll = ascompatte(n->op, nil, 0, getoutarg(curfn->type), n->list, 1, &n->ninit);
-               n->list = ll;
-               break;
-
-       case ORETJMP:
-               break;
-
-       case OSELECT:
-               walkselect(n);
-               break;
-
-       case OSWITCH:
-               walkswitch(n);
-               break;
-
-       case ORANGE:
-               walkrange(n);
-               break;
-
-       case OXFALL:
-               yyerror("fallthrough statement out of place");
-               n->op = OFALL;
-               break;
-       }
-
-       if(n->op == ONAME)
-               fatal("walkstmt ended up with name: %+N", n);
-       
-       *np = n;
-}
-
-
-/*
- * walk the whole tree of the body of an
- * expression or simple statement.
- * the types expressions are calculated.
- * compile-time constants are evaluated.
- * complex side effects like statements are appended to init
- */
-
-void
-walkexprlist(NodeList *l, NodeList **init)
-{
-       for(; l; l=l->next)
-               walkexpr(&l->n, init);
-}
-
-void
-walkexprlistsafe(NodeList *l, NodeList **init)
-{
-       for(; l; l=l->next) {
-               l->n = safeexpr(l->n, init);
-               walkexpr(&l->n, init);
-       }
-}
-
-void
-walkexprlistcheap(NodeList *l, NodeList **init)
-{
-       for(; l; l=l->next) {
-               l->n = cheapexpr(l->n, init);
-               walkexpr(&l->n, init);
-       }
-}
-
-void
-walkexpr(Node **np, NodeList **init)
-{
-       Node *r, *l, *var, *a, *ok;
-       Node *map, *key;
-       NodeList *ll, *lr;
-       Type *t;
-       int et, old_safemode;
-       int64 v;
-       int32 lno;
-       Node *n, *fn, *n1, *n2;
-       Sym *sym;
-       char buf[100], *p, *from, *to;
-
-       n = *np;
-
-       if(n == N)
-               return;
-
-       if(init == &n->ninit) {
-               // not okay to use n->ninit when walking n,
-               // because we might replace n with some other node
-               // and would lose the init list.
-               fatal("walkexpr init == &n->ninit");
-       }
-
-       if(n->ninit != nil) {
-               walkstmtlist(n->ninit);
-               *init = concat(*init, n->ninit);
-               n->ninit = nil;
-       }
-
-       // annoying case - not typechecked
-       if(n->op == OKEY) {
-               walkexpr(&n->left, init);
-               walkexpr(&n->right, init);
-               return;
-       }
-
-       lno = setlineno(n);
-
-       if(debug['w'] > 1)
-               dump("walk-before", n);
-
-       if(n->typecheck != 1)
-               fatal("missed typecheck: %+N\n", n);
-
-       switch(n->op) {
-       default:
-               dump("walk", n);
-               fatal("walkexpr: switch 1 unknown op %+hN", n);
-               break;
-
-       case OTYPE:
-       case ONONAME:
-       case OINDREG:
-       case OEMPTY:
-       case OPARAM:
-               goto ret;
-
-       case ONOT:
-       case OMINUS:
-       case OPLUS:
-       case OCOM:
-       case OREAL:
-       case OIMAG:
-       case ODOTMETH:
-       case ODOTINTER:
-               walkexpr(&n->left, init);
-               goto ret;
-
-       case OIND:
-               walkexpr(&n->left, init);
-               goto ret;
-
-       case ODOT:
-               usefield(n);
-               walkexpr(&n->left, init);
-               goto ret;
-
-       case ODOTPTR:
-               usefield(n);
-               if(n->op == ODOTPTR && n->left->type->type->width == 0) {
-                       // No actual copy will be generated, so emit an explicit nil check.
-                       n->left = cheapexpr(n->left, init);
-                       checknil(n->left, init);
-               }
-               walkexpr(&n->left, init);
-               goto ret;
-
-       case OEFACE:
-               walkexpr(&n->left, init);
-               walkexpr(&n->right, init);
-               goto ret;
-
-       case OSPTR:
-       case OITAB:
-               walkexpr(&n->left, init);
-               goto ret;
-
-       case OLEN:
-       case OCAP:
-               walkexpr(&n->left, init);
-
-               // replace len(*[10]int) with 10.
-               // delayed until now to preserve side effects.
-               t = n->left->type;
-               if(isptr[t->etype])
-                       t = t->type;
-               if(isfixedarray(t)) {
-                       safeexpr(n->left, init);
-                       nodconst(n, n->type, t->bound);
-                       n->typecheck = 1;
-               }
-               goto ret;
-
-       case OLSH:
-       case ORSH:
-               walkexpr(&n->left, init);
-               walkexpr(&n->right, init);
-               t = n->left->type;
-               n->bounded = bounded(n->right, 8*t->width);
-               if(debug['m'] && n->etype && !isconst(n->right, CTINT))
-                       warn("shift bounds check elided");
-               goto ret;
-
-       case OAND:
-       case OSUB:
-       case OHMUL:
-       case OLT:
-       case OLE:
-       case OGE:
-       case OGT:
-       case OADD:
-       case OCOMPLEX:
-       case OLROT:
-               // Use results from call expression as arguments for complex.
-               if(n->op == OCOMPLEX && n->left == N && n->right == N) {
-                       n->left = n->list->n;
-                       n->right = n->list->next->n;
-               }
-               walkexpr(&n->left, init);
-               walkexpr(&n->right, init);
-               goto ret;
-
-       case OOR:
-       case OXOR:
-               walkexpr(&n->left, init);
-               walkexpr(&n->right, init);
-               walkrotate(&n);
-               goto ret;
-
-       case OEQ:
-       case ONE:
-               walkexpr(&n->left, init);
-               walkexpr(&n->right, init);
-               // Disable safemode while compiling this code: the code we
-               // generate internally can refer to unsafe.Pointer.
-               // In this case it can happen if we need to generate an ==
-               // for a struct containing a reflect.Value, which itself has
-               // an unexported field of type unsafe.Pointer.
-               old_safemode = safemode;
-               safemode = 0;
-               walkcompare(&n, init);
-               safemode = old_safemode;
-               goto ret;
-
-       case OANDAND:
-       case OOROR:
-               walkexpr(&n->left, init);
-               // cannot put side effects from n->right on init,
-               // because they cannot run before n->left is checked.
-               // save elsewhere and store on the eventual n->right.
-               ll = nil;
-               walkexpr(&n->right, &ll);
-               addinit(&n->right, ll);
-               goto ret;
-
-       case OPRINT:
-       case OPRINTN:
-               walkexprlist(n->list, init);
-               n = walkprint(n, init);
-               goto ret;
-
-       case OPANIC:
-               n = mkcall("gopanic", T, init, n->left);
-               goto ret;
-
-       case ORECOVER:
-               n = mkcall("gorecover", n->type, init, nod(OADDR, nodfp, N));
-               goto ret;
-
-       case OLITERAL:
-               n->addable = 1;
-               goto ret;
-
-       case OCLOSUREVAR:
-       case OCFUNC:
-               n->addable = 1;
-               goto ret;
-
-       case ONAME:
-               if(!(n->class & PHEAP) && n->class != PPARAMREF)
-                       n->addable = 1;
-               goto ret;
-
-       case OCALLINTER:
-               t = n->left->type;
-               if(n->list && n->list->n->op == OAS)
-                       goto ret;
-               walkexpr(&n->left, init);
-               walkexprlist(n->list, init);
-               ll = ascompatte(n->op, n, n->isddd, getinarg(t), n->list, 0, init);
-               n->list = reorder1(ll);
-               goto ret;
-
-       case OCALLFUNC:
-               if(n->left->op == OCLOSURE) {
-                       // Transform direct call of a closure to call of a normal function.
-                       // transformclosure already did all preparation work.
-
-                       // Append captured variables to argument list.
-                       n->list = concat(n->list, n->left->enter);
-                       n->left->enter = nil;
-                       // Replace OCLOSURE with ONAME/PFUNC.
-                       n->left = n->left->closure->nname;
-                       // Update type of OCALLFUNC node.
-                       // Output arguments had not changed, but their offsets could.
-                       if(n->left->type->outtuple == 1) {
-                               t = getoutargx(n->left->type)->type;
-                               if(t->etype == TFIELD)
-                                       t = t->type;
-                               n->type = t;
-                       } else
-                               n->type = getoutargx(n->left->type);
-               }
-
-               t = n->left->type;
-               if(n->list && n->list->n->op == OAS)
-                       goto ret;
-
-               walkexpr(&n->left, init);
-               walkexprlist(n->list, init);
-
-               ll = ascompatte(n->op, n, n->isddd, getinarg(t), n->list, 0, init);
-               n->list = reorder1(ll);
-               goto ret;
-
-       case OCALLMETH:
-               t = n->left->type;
-               if(n->list && n->list->n->op == OAS)
-                       goto ret;
-               walkexpr(&n->left, init);
-               walkexprlist(n->list, init);
-               ll = ascompatte(n->op, n, 0, getthis(t), list1(n->left->left), 0, init);
-               lr = ascompatte(n->op, n, n->isddd, getinarg(t), n->list, 0, init);
-               ll = concat(ll, lr);
-               n->left->left = N;
-               ullmancalc(n->left);
-               n->list = reorder1(ll);
-               goto ret;
-
-       case OAS:
-               *init = concat(*init, n->ninit);
-               n->ninit = nil;
-
-               walkexpr(&n->left, init);
-               n->left = safeexpr(n->left, init);
-
-               if(oaslit(n, init))
-                       goto ret;
-
-               if(n->right == N || iszero(n->right) && !flag_race)
-                       goto ret;
-
-               switch(n->right->op) {
-               default:
-                       walkexpr(&n->right, init);
-                       break;
-               
-               case ODOTTYPE:
-                       // x = i.(T); n->left is x, n->right->left is i.
-                       // orderstmt made sure x is addressable.
-                       walkexpr(&n->right->left, init);
-                       n1 = nod(OADDR, n->left, N);
-                       r = n->right; // i.(T)
-
-                       from = "I";
-                       to = "T";
-                       if(isnilinter(r->left->type))
-                               from = "E";
-                       if(isnilinter(r->type))
-                               to = "E";
-                       else if(isinter(r->type))
-                               to = "I";
-                       
-                       snprint(buf, sizeof buf, "assert%s2%s", from, to);
-
-                       fn = syslook(buf, 1);
-                       argtype(fn, r->left->type);
-                       argtype(fn, r->type);
-               
-                       n = mkcall1(fn, T, init, typename(r->type), r->left, n1);
-                       walkexpr(&n, init);
-                       goto ret;
-
-               case ORECV:
-                       // x = <-c; n->left is x, n->right->left is c.
-                       // orderstmt made sure x is addressable.
-                       walkexpr(&n->right->left, init);
-                       n1 = nod(OADDR, n->left, N);
-                       r = n->right->left; // the channel
-                       n = mkcall1(chanfn("chanrecv1", 2, r->type), T, init, typename(r->type), r, n1);
-                       walkexpr(&n, init);
-                       goto ret;
-               }
-
-               if(n->left != N && n->right != N) {
-                       r = convas(nod(OAS, n->left, n->right), init);
-                       r->dodata = n->dodata;
-                       n = r;
-                       n = applywritebarrier(n, init);
-               }
-
-               goto ret;
-
-       case OAS2:
-               *init = concat(*init, n->ninit);
-               n->ninit = nil;
-               walkexprlistsafe(n->list, init);
-               walkexprlistsafe(n->rlist, init);
-               ll = ascompatee(OAS, n->list, n->rlist, init);
-               ll = reorder3(ll);
-               for(lr = ll; lr != nil; lr = lr->next)
-                       lr->n = applywritebarrier(lr->n, init);
-               n = liststmt(ll);
-               goto ret;
-
-       case OAS2FUNC:
-               // a,b,... = fn()
-               *init = concat(*init, n->ninit);
-               n->ninit = nil;
-               r = n->rlist->n;
-               walkexprlistsafe(n->list, init);
-               walkexpr(&r, init);
-
-               ll = ascompatet(n->op, n->list, &r->type, 0, init);
-               for(lr = ll; lr != nil; lr = lr->next)
-                       lr->n = applywritebarrier(lr->n, init);
-               n = liststmt(concat(list1(r), ll));
-               goto ret;
-
-       case OAS2RECV:
-               // x, y = <-c
-               // orderstmt made sure x is addressable.
-               *init = concat(*init, n->ninit);
-               n->ninit = nil;
-               r = n->rlist->n;
-               walkexprlistsafe(n->list, init);
-               walkexpr(&r->left, init);
-               if(isblank(n->list->n))
-                       n1 = nodnil();
-               else
-                       n1 = nod(OADDR, n->list->n, N);
-               n1->etype = 1; // addr does not escape
-               fn = chanfn("chanrecv2", 2, r->left->type);
-               r = mkcall1(fn, n->list->next->n->type, init, typename(r->left->type), r->left, n1);
-               n = nod(OAS, n->list->next->n, r);
-               typecheck(&n, Etop);
-               goto ret;
-
-       case OAS2MAPR:
-               // a,b = m[i];
-               *init = concat(*init, n->ninit);
-               n->ninit = nil;
-               r = n->rlist->n;
-               walkexprlistsafe(n->list, init);
-               walkexpr(&r->left, init);
-               walkexpr(&r->right, init);
-               t = r->left->type;
-               p = nil;
-               if(t->type->width <= 128) { // Check ../../runtime/hashmap.go:maxValueSize before changing.
-                       switch(simsimtype(t->down)) {
-                       case TINT32:
-                       case TUINT32:
-                               p = "mapaccess2_fast32";
-                               break;
-                       case TINT64:
-                       case TUINT64:
-                               p = "mapaccess2_fast64";
-                               break;
-                       case TSTRING:
-                               p = "mapaccess2_faststr";
-                               break;
-                       }
-               }
-               if(p != nil) {
-                       // fast versions take key by value
-                       key = r->right;
-               } else {
-                       // standard version takes key by reference
-                       // orderexpr made sure key is addressable.
-                       key = nod(OADDR, r->right, N);
-                       p = "mapaccess2";
-               }
-
-               // from:
-               //   a,b = m[i]
-               // to:
-               //   var,b = mapaccess2*(t, m, i)
-               //   a = *var
-               a = n->list->n;
-               fn = mapfn(p, t);
-               r = mkcall1(fn, getoutargx(fn->type), init, typename(t), r->left, key);
-
-               // mapaccess2* returns a typed bool, but due to spec changes,
-               // the boolean result of i.(T) is now untyped so we make it the
-               // same type as the variable on the lhs.
-               if(!isblank(n->list->next->n))
-                       r->type->type->down->type = n->list->next->n->type;
-               n->rlist = list1(r);
-               n->op = OAS2FUNC;
-
-               // don't generate a = *var if a is _
-               if(!isblank(a)) {
-                       var = temp(ptrto(t->type));
-                       var->typecheck = 1;
-                       n->list->n = var;
-                       walkexpr(&n, init);
-                       *init = list(*init, n);
-                       n = nod(OAS, a, nod(OIND, var, N));
-               }
-
-               typecheck(&n, Etop);
-               walkexpr(&n, init);
-               // mapaccess needs a zero value to be at least this big.
-               if(zerosize < t->type->width)
-                       zerosize = t->type->width;
-               // TODO: ptr is always non-nil, so disable nil check for this OIND op.
-               goto ret;
-
-       case ODELETE:
-               *init = concat(*init, n->ninit);
-               n->ninit = nil;
-               map = n->list->n;
-               key = n->list->next->n;
-               walkexpr(&map, init);
-               walkexpr(&key, init);
-               // orderstmt made sure key is addressable.
-               key = nod(OADDR, key, N);
-               t = map->type;
-               n = mkcall1(mapfndel("mapdelete", t), T, init, typename(t), map, key);
-               goto ret;
-
-       case OAS2DOTTYPE:
-               // a,b = i.(T)
-               // orderstmt made sure a is addressable.
-               *init = concat(*init, n->ninit);
-               n->ninit = nil;
-               r = n->rlist->n;
-               walkexprlistsafe(n->list, init);
-               walkexpr(&r->left, init);
-               if(isblank(n->list->n))
-                       n1 = nodnil();
-               else
-                       n1 = nod(OADDR, n->list->n, N);
-               n1->etype = 1; // addr does not escape
-
-               from = "I";
-               to = "T";
-               if(isnilinter(r->left->type))
-                       from = "E";
-               if(isnilinter(r->type))
-                       to = "E";
-               else if(isinter(r->type))
-                       to = "I";
-               snprint(buf, sizeof buf, "assert%s2%s2", from, to);
-               
-               fn = syslook(buf, 1);
-               argtype(fn, r->left->type);
-               argtype(fn, r->type);
-               
-               t = types[TBOOL];
-               ok = n->list->next->n;
-               if(!isblank(ok))
-                       t = ok->type;
-               r = mkcall1(fn, t, init, typename(r->type), r->left, n1);
-               n = nod(OAS, ok, r);
-               typecheck(&n, Etop);
-               goto ret;
-
-       case ODOTTYPE:
-       case ODOTTYPE2:
-               fatal("walkexpr ODOTTYPE"); // should see inside OAS or OAS2 only
-
-       case OCONVIFACE:
-               walkexpr(&n->left, init);
-
-               // Optimize convT2E as a two-word copy when T is pointer-shaped.
-               if(isnilinter(n->type) && isdirectiface(n->left->type)) {
-                       l = nod(OEFACE, typename(n->left->type), n->left);
-                       l->type = n->type;
-                       l->typecheck = n->typecheck;
-                       n = l;
-                       goto ret;
-               }
-
-               // Build name of function: convI2E etc.
-               // Not all names are possible
-               // (e.g., we'll never generate convE2E or convE2I).
-               from = "T";
-               to = "I";
-               if(isnilinter(n->left->type))
-                       from = "E";
-               else if(isinter(n->left->type))
-                       from = "I";
-               if(isnilinter(n->type))
-                       to = "E";
-               snprint(buf, sizeof buf, "conv%s2%s", from, to);
-
-               fn = syslook(buf, 1);
-               ll = nil;
-               if(!isinter(n->left->type))
-                       ll = list(ll, typename(n->left->type));
-               if(!isnilinter(n->type))
-                       ll = list(ll, typename(n->type));
-               if(!isinter(n->left->type) && !isnilinter(n->type)){
-                       sym = pkglookup(smprint("%-T.%-T", n->left->type, n->type), itabpkg);
-                       if(sym->def == N) {
-                               l = nod(ONAME, N, N);
-                               l->sym = sym;
-                               l->type = ptrto(types[TUINT8]);
-                               l->addable = 1;
-                               l->class = PEXTERN;
-                               l->xoffset = 0;
-                               sym->def = l;
-                               ggloblsym(sym, widthptr, DUPOK|NOPTR);
-                       }
-                       l = nod(OADDR, sym->def, N);
-                       l->addable = 1;
-                       ll = list(ll, l);
-
-                       if(isdirectiface(n->left->type)) {
-                               /* For pointer types, we can make a special form of optimization
-                                *
-                                * These statements are put onto the expression init list:
-                                *      Itab *tab = atomicloadtype(&cache);
-                                *      if(tab == nil)
-                                *              tab = typ2Itab(type, itype, &cache);
-                                *
-                                * The CONVIFACE expression is replaced with this:
-                                *      OEFACE{tab, ptr};
-                                */
-                               l = temp(ptrto(types[TUINT8]));
-
-                               n1 = nod(OAS, l, sym->def);
-                               typecheck(&n1, Etop);
-                               *init = list(*init, n1);
-
-                               fn = syslook("typ2Itab", 1);
-                               n1 = nod(OCALL, fn, N);
-                               n1->list = ll;
-                               typecheck(&n1, Erv);
-                               walkexpr(&n1, init);
-
-                               n2 = nod(OIF, N, N);
-                               n2->ntest = nod(OEQ, l, nodnil());
-                               n2->nbody = list1(nod(OAS, l, n1));
-                               n2->likely = -1;
-                               typecheck(&n2, Etop);
-                               *init = list(*init, n2);
-
-                               l = nod(OEFACE, l, n->left);
-                               l->typecheck = n->typecheck; 
-                               l->type = n->type;
-                               n = l;
-                               goto ret;
-                       }
-               }
-               if(isinter(n->left->type)) {
-                       ll = list(ll, n->left);
-               } else {
-                       // regular types are passed by reference to avoid C vararg calls
-                       // orderexpr arranged for n->left to be a temporary for all
-                       // the conversions it could see. comparison of an interface
-                       // with a non-interface, especially in a switch on interface value
-                       // with non-interface cases, is not visible to orderstmt, so we
-                       // have to fall back on allocating a temp here.
-                       if(islvalue(n->left))
-                               ll = list(ll, nod(OADDR, n->left, N));
-                       else
-                               ll = list(ll, nod(OADDR, copyexpr(n->left, n->left->type, init), N));
-               }
-               argtype(fn, n->left->type);
-               argtype(fn, n->type);
-               dowidth(fn->type);
-               n = nod(OCALL, fn, N);
-               n->list = ll;
-               typecheck(&n, Erv);
-               walkexpr(&n, init);
-               goto ret;
-
-       case OCONV:
-       case OCONVNOP:
-               if(thearch.thechar == '5') {
-                       if(isfloat[n->left->type->etype]) {
-                               if(n->type->etype == TINT64) {
-                                       n = mkcall("float64toint64", n->type, init, conv(n->left, types[TFLOAT64]));
-                                       goto ret;
-                               }
-                               if(n->type->etype == TUINT64) {
-                                       n = mkcall("float64touint64", n->type, init, conv(n->left, types[TFLOAT64]));
-                                       goto ret;
-                               }
-                       }
-                       if(isfloat[n->type->etype]) {
-                               if(n->left->type->etype == TINT64) {
-                                       n = mkcall("int64tofloat64", n->type, init, conv(n->left, types[TINT64]));
-                                       goto ret;
-                               }
-                               if(n->left->type->etype == TUINT64) {
-                                       n = mkcall("uint64tofloat64", n->type, init, conv(n->left, types[TUINT64]));
-                                       goto ret;
-                               }
-                       }
-               }
-               walkexpr(&n->left, init);
-               goto ret;
-
-       case OANDNOT:
-               walkexpr(&n->left, init);
-               n->op = OAND;
-               n->right = nod(OCOM, n->right, N);
-               typecheck(&n->right, Erv);
-               walkexpr(&n->right, init);
-               goto ret;
-
-       case OMUL:
-               walkexpr(&n->left, init);
-               walkexpr(&n->right, init);
-               walkmul(&n, init);
-               goto ret;
-
-       case ODIV:
-       case OMOD:
-               walkexpr(&n->left, init);
-               walkexpr(&n->right, init);
-               /*
-                * rewrite complex div into function call.
-                */
-               et = n->left->type->etype;
-               if(iscomplex[et] && n->op == ODIV) {
-                       t = n->type;
-                       n = mkcall("complex128div", types[TCOMPLEX128], init,
-                               conv(n->left, types[TCOMPLEX128]),
-                               conv(n->right, types[TCOMPLEX128]));
-                       n = conv(n, t);
-                       goto ret;
-               }
-               // Nothing to do for float divisions.
-               if(isfloat[et])
-                       goto ret;
-
-               // Try rewriting as shifts or magic multiplies.
-               walkdiv(&n, init);
-
-               /*
-                * rewrite 64-bit div and mod into function calls
-                * on 32-bit architectures.
-                */
-               switch(n->op) {
-               case OMOD:
-               case ODIV:
-                       if(widthreg >= 8 || (et != TUINT64 && et != TINT64))
-                               goto ret;
-                       if(et == TINT64)
-                               strcpy(namebuf, "int64");
-                       else
-                               strcpy(namebuf, "uint64");
-                       if(n->op == ODIV)
-                               strcat(namebuf, "div");
-                       else
-                               strcat(namebuf, "mod");
-                       n = mkcall(namebuf, n->type, init,
-                               conv(n->left, types[et]), conv(n->right, types[et]));
-                       break;
-               default:
-                       break;
-               }
-               goto ret;
-
-       case OINDEX:
-               walkexpr(&n->left, init);
-               // save the original node for bounds checking elision.
-               // If it was a ODIV/OMOD walk might rewrite it.
-               r = n->right;
-               walkexpr(&n->right, init);
-
-               // if range of type cannot exceed static array bound,
-               // disable bounds check.
-               if(n->bounded)
-                       goto ret;
-               t = n->left->type;
-               if(t != T && isptr[t->etype])
-                       t = t->type;
-               if(isfixedarray(t)) {
-                       n->bounded = bounded(r, t->bound);
-                       if(debug['m'] && n->bounded && !isconst(n->right, CTINT))
-                               warn("index bounds check elided");
-                       if(smallintconst(n->right) && !n->bounded)
-                               yyerror("index out of bounds");
-               } else if(isconst(n->left, CTSTR)) {
-                       n->bounded = bounded(r, n->left->val.u.sval->len);
-                       if(debug['m'] && n->bounded && !isconst(n->right, CTINT))
-                               warn("index bounds check elided");
-                       if(smallintconst(n->right)) {
-                               if(!n->bounded)
-                                       yyerror("index out of bounds");
-                               else {
-                                       // replace "abc"[1] with 'b'.
-                                       // delayed until now because "abc"[1] is not
-                                       // an ideal constant.
-                                       v = mpgetfix(n->right->val.u.xval);
-                                       nodconst(n, n->type, n->left->val.u.sval->s[v]);
-                                       n->typecheck = 1;
-                               }
-                       }
-               }
-
-               if(isconst(n->right, CTINT))
-               if(mpcmpfixfix(n->right->val.u.xval, &mpzero) < 0 ||
-                  mpcmpfixfix(n->right->val.u.xval, maxintval[TINT]) > 0)
-                       yyerror("index out of bounds");
-               goto ret;
-
-       case OINDEXMAP:
-               if(n->etype == 1)
-                       goto ret;
-               walkexpr(&n->left, init);
-               walkexpr(&n->right, init);
-
-               t = n->left->type;
-               p = nil;
-               if(t->type->width <= 128) {  // Check ../../runtime/hashmap.go:maxValueSize before changing.
-                       switch(simsimtype(t->down)) {
-                       case TINT32:
-                       case TUINT32:
-                               p = "mapaccess1_fast32";
-                               break;
-                       case TINT64:
-                       case TUINT64:
-                               p = "mapaccess1_fast64";
-                               break;
-                       case TSTRING:
-                               p = "mapaccess1_faststr";
-                               break;
-                       }
-               }
-               if(p != nil) {
-                       // fast versions take key by value
-                       key = n->right;
-               } else {
-                       // standard version takes key by reference.
-                       // orderexpr made sure key is addressable.
-                       key = nod(OADDR, n->right, N);
-                       p = "mapaccess1";
-               }
-               n = mkcall1(mapfn(p, t), ptrto(t->type), init, typename(t), n->left, key);
-               n = nod(OIND, n, N);
-               n->type = t->type;
-               n->typecheck = 1;
-               // mapaccess needs a zero value to be at least this big.
-               if(zerosize < t->type->width)
-                       zerosize = t->type->width;
-               goto ret;
-
-       case ORECV:
-               fatal("walkexpr ORECV"); // should see inside OAS only
-
-       case OSLICE:
-               if(n->right != N && n->right->left == N && n->right->right == N) { // noop
-                       walkexpr(&n->left, init);
-                       n = n->left;
-                       goto ret;
-               }
-               // fallthrough
-       case OSLICEARR:
-       case OSLICESTR:
-               if(n->right == N) // already processed
-                       goto ret;
-
-               walkexpr(&n->left, init);
-               // cgen_slice can't handle string literals as source
-               // TODO the OINDEX case is a bug elsewhere that needs to be traced.  it causes a crash on ([2][]int{ ... })[1][lo:hi]
-               if((n->op == OSLICESTR && n->left->op == OLITERAL) || (n->left->op == OINDEX))
-                       n->left = copyexpr(n->left, n->left->type, init);
-               else
-                       n->left = safeexpr(n->left, init);
-               walkexpr(&n->right->left, init);
-               n->right->left = safeexpr(n->right->left, init);
-               walkexpr(&n->right->right, init);
-               n->right->right = safeexpr(n->right->right, init);
-               n = sliceany(n, init);  // chops n->right, sets n->list
-               goto ret;
-       
-       case OSLICE3:
-       case OSLICE3ARR:
-               if(n->right == N) // already processed
-                       goto ret;
-
-               walkexpr(&n->left, init);
-               // TODO the OINDEX case is a bug elsewhere that needs to be traced.  it causes a crash on ([2][]int{ ... })[1][lo:hi]
-               // TODO the comment on the previous line was copied from case OSLICE. it might not even be true.
-               if(n->left->op == OINDEX)
-                       n->left = copyexpr(n->left, n->left->type, init);
-               else
-                       n->left = safeexpr(n->left, init);
-               walkexpr(&n->right->left, init);
-               n->right->left = safeexpr(n->right->left, init);
-               walkexpr(&n->right->right->left, init);
-               n->right->right->left = safeexpr(n->right->right->left, init);
-               walkexpr(&n->right->right->right, init);
-               n->right->right->right = safeexpr(n->right->right->right, init);
-               n = sliceany(n, init);  // chops n->right, sets n->list
-               goto ret;
-
-       case OADDR:
-               walkexpr(&n->left, init);
-               goto ret;
-
-       case ONEW:
-               if(n->esc == EscNone && n->type->type->width < (1<<16)) {
-                       r = temp(n->type->type);
-                       r = nod(OAS, r, N);  // zero temp
-                       typecheck(&r, Etop);
-                       *init = list(*init, r);
-                       r = nod(OADDR, r->left, N);
-                       typecheck(&r, Erv);
-                       n = r;
-               } else {
-                       n = callnew(n->type->type);
-               }
-               goto ret;
-
-       case OCMPSTR:
-               // If one argument to the comparison is an empty string,
-               // comparing the lengths instead will yield the same result
-               // without the function call.
-               if((isconst(n->left, CTSTR) && n->left->val.u.sval->len == 0) ||
-                  (isconst(n->right, CTSTR) && n->right->val.u.sval->len == 0)) {
-                       r = nod(n->etype, nod(OLEN, n->left, N), nod(OLEN, n->right, N));
-                       typecheck(&r, Erv);
-                       walkexpr(&r, init);
-                       r->type = n->type;
-                       n = r;
-                       goto ret;
-               }
-
-               // s + "badgerbadgerbadger" == "badgerbadgerbadger"
-               if((n->etype == OEQ || n->etype == ONE) &&
-                  isconst(n->right, CTSTR) &&
-                  n->left->op == OADDSTR && count(n->left->list) == 2 &&
-                  isconst(n->left->list->next->n, CTSTR) &&
-                  cmpslit(n->right, n->left->list->next->n) == 0) {
-                       r = nod(n->etype, nod(OLEN, n->left->list->n, N), nodintconst(0));
-                       typecheck(&r, Erv);
-                       walkexpr(&r, init);
-                       r->type = n->type;
-                       n = r;
-                       goto ret;
-               }
-
-               if(n->etype == OEQ || n->etype == ONE) {
-                       // prepare for rewrite below
-                       n->left = cheapexpr(n->left, init);
-                       n->right = cheapexpr(n->right, init);
-
-                       r = mkcall("eqstring", types[TBOOL], init,
-                               conv(n->left, types[TSTRING]),
-                               conv(n->right, types[TSTRING]));
-
-                       // quick check of len before full compare for == or !=
-                       // eqstring assumes that the lengths are equal
-                       if(n->etype == OEQ) {
-                               // len(left) == len(right) && eqstring(left, right)
-                               r = nod(OANDAND, nod(OEQ, nod(OLEN, n->left, N), nod(OLEN, n->right, N)), r);
-                       } else {
-                               // len(left) != len(right) || !eqstring(left, right)
-                               r = nod(ONOT, r, N);
-                               r = nod(OOROR, nod(ONE, nod(OLEN, n->left, N), nod(OLEN, n->right, N)), r);
-                       }
-                       typecheck(&r, Erv);
-                       walkexpr(&r, nil);
-               } else {
-                       // sys_cmpstring(s1, s2) :: 0
-                       r = mkcall("cmpstring", types[TINT], init,
-                               conv(n->left, types[TSTRING]),
-                               conv(n->right, types[TSTRING]));
-                       r = nod(n->etype, r, nodintconst(0));
-               }
-
-               typecheck(&r, Erv);
-               if(n->type->etype != TBOOL) fatal("cmp %T", n->type);
-               r->type = n->type;
-               n = r;
-               goto ret;
-
-       case OADDSTR:
-               n = addstr(n, init);
-               goto ret;
-       
-       case OAPPEND:
-               if(n->isddd)
-                       n = appendslice(n, init); // also works for append(slice, string).
-               else
-                       n = append(n, init);
-               goto ret;
-
-       case OCOPY:
-               n = copyany(n, init, flag_race);
-               goto ret;
-
-       case OCLOSE:
-               // cannot use chanfn - closechan takes any, not chan any
-               fn = syslook("closechan", 1);
-               argtype(fn, n->left->type);
-               n = mkcall1(fn, T, init, n->left);
-               goto ret;
-
-       case OMAKECHAN:
-               n = mkcall1(chanfn("makechan", 1, n->type), n->type, init,
-                       typename(n->type),
-                       conv(n->left, types[TINT64]));
-               goto ret;
-
-       case OMAKEMAP:
-               t = n->type;
-
-               fn = syslook("makemap", 1);
-
-               a = nodnil(); // hmap buffer
-               r = nodnil(); // bucket buffer
-               if(n->esc == EscNone) {
-                       // Allocate hmap buffer on stack.
-                       var = temp(hmap(t));
-                       a = nod(OAS, var, N); // zero temp
-                       typecheck(&a, Etop);
-                       *init = list(*init, a);
-                       a = nod(OADDR, var, N);
-
-                       // Allocate one bucket on stack.
-                       // Maximum key/value size is 128 bytes, larger objects
-                       // are stored with an indirection. So max bucket size is 2048+eps.
-                       var = temp(mapbucket(t));
-                       r = nod(OAS, var, N); // zero temp
-                       typecheck(&r, Etop);
-                       *init = list(*init, r);
-                       r = nod(OADDR, var, N);
-               }
-
-               argtype(fn, hmap(t));   // hmap buffer
-               argtype(fn, mapbucket(t));      // bucket buffer
-               argtype(fn, t->down);   // key type
-               argtype(fn, t->type);   // value type
-               n = mkcall1(fn, n->type, init, typename(n->type), conv(n->left, types[TINT64]), a, r);
-               goto ret;
-
-       case OMAKESLICE:
-               l = n->left;
-               r = n->right;
-               if(r == nil)
-                       l = r = safeexpr(l, init);
-               t = n->type;
-               if(n->esc == EscNone
-                       && smallintconst(l) && smallintconst(r)
-                       && (t->type->width == 0 || mpgetfix(r->val.u.xval) < (1ULL<<16) / t->type->width)) {
-                       // var arr [r]T
-                       // n = arr[:l]
-                       t = aindex(r, t->type); // [r]T
-                       var = temp(t);
-                       a = nod(OAS, var, N); // zero temp
-                       typecheck(&a, Etop);
-                       *init = list(*init, a);
-                       r = nod(OSLICE, var, nod(OKEY, N, l)); // arr[:l]
-                       r = conv(r, n->type); // in case n->type is named.
-                       typecheck(&r, Erv);
-                       walkexpr(&r, init);
-                       n = r;
-               } else {
-                       // makeslice(t *Type, nel int64, max int64) (ary []any)
-                       fn = syslook("makeslice", 1);
-                       argtype(fn, t->type);                   // any-1
-                       n = mkcall1(fn, n->type, init,
-                               typename(n->type),
-                               conv(l, types[TINT64]),
-                               conv(r, types[TINT64]));
-               }
-               goto ret;
-
-       case ORUNESTR:
-               a = nodnil();
-               if(n->esc == EscNone) {
-                       t = aindex(nodintconst(4), types[TUINT8]);
-                       var = temp(t);
-                       a = nod(OADDR, var, N);
-               }
-               // intstring(*[4]byte, rune)
-               n = mkcall("intstring", n->type, init, a, conv(n->left, types[TINT64]));
-               goto ret;
-
-       case OARRAYBYTESTR:
-               a = nodnil();
-               if(n->esc == EscNone) {
-                       // Create temporary buffer for string on stack.
-                       t = aindex(nodintconst(tmpstringbufsize), types[TUINT8]);
-                       a = nod(OADDR, temp(t), N);
-               }
-               // slicebytetostring(*[32]byte, []byte) string;
-               n = mkcall("slicebytetostring", n->type, init, a, n->left);
-               goto ret;
-
-       case OARRAYBYTESTRTMP:
-               // slicebytetostringtmp([]byte) string;
-               n = mkcall("slicebytetostringtmp", n->type, init, n->left);
-               goto ret;
-
-       case OARRAYRUNESTR:
-               // slicerunetostring(*[32]byte, []rune) string;
-               a = nodnil();
-               if(n->esc == EscNone) {
-                       // Create temporary buffer for string on stack.
-                       t = aindex(nodintconst(tmpstringbufsize), types[TUINT8]);
-                       a = nod(OADDR, temp(t), N);
-               }
-               n = mkcall("slicerunetostring", n->type, init, a, n->left);
-               goto ret;
-
-       case OSTRARRAYBYTE:
-               // stringtoslicebyte(*32[byte], string) []byte;
-               a = nodnil();
-               if(n->esc == EscNone) {
-                       // Create temporary buffer for slice on stack.
-                       t = aindex(nodintconst(tmpstringbufsize), types[TUINT8]);
-                       a = nod(OADDR, temp(t), N);
-               }
-               n = mkcall("stringtoslicebyte", n->type, init, a, conv(n->left, types[TSTRING]));
-               goto ret;
-
-       case OSTRARRAYBYTETMP:
-               // stringtoslicebytetmp(string) []byte;
-               n = mkcall("stringtoslicebytetmp", n->type, init, conv(n->left, types[TSTRING]));
-               goto ret;
-
-       case OSTRARRAYRUNE:
-               // stringtoslicerune(*[32]rune, string) []rune
-               a = nodnil();
-               if(n->esc == EscNone) {
-                       // Create temporary buffer for slice on stack.
-                       t = aindex(nodintconst(tmpstringbufsize), types[TINT32]);
-                       a = nod(OADDR, temp(t), N);
-               }
-               n = mkcall("stringtoslicerune", n->type, init, a, n->left);
-               goto ret;
-
-       case OCMPIFACE:
-               // ifaceeq(i1 any-1, i2 any-2) (ret bool);
-               if(!eqtype(n->left->type, n->right->type))
-                       fatal("ifaceeq %O %T %T", n->op, n->left->type, n->right->type);
-               if(isnilinter(n->left->type))
-                       fn = syslook("efaceeq", 1);
-               else
-                       fn = syslook("ifaceeq", 1);
-
-               n->right = cheapexpr(n->right, init);
-               n->left = cheapexpr(n->left, init);
-               argtype(fn, n->right->type);
-               argtype(fn, n->left->type);
-               r = mkcall1(fn, n->type, init, n->left, n->right);
-               if(n->etype == ONE)
-                       r = nod(ONOT, r, N);
-               
-               // check itable/type before full compare.
-               if(n->etype == OEQ)
-                       r = nod(OANDAND, nod(OEQ, nod(OITAB, n->left, N), nod(OITAB, n->right, N)), r);
-               else
-                       r = nod(OOROR, nod(ONE, nod(OITAB, n->left, N), nod(OITAB, n->right, N)), r);
-               typecheck(&r, Erv);
-               walkexpr(&r, init);
-               r->type = n->type;
-               n = r;
-               goto ret;
-
-       case OARRAYLIT:
-       case OMAPLIT:
-       case OSTRUCTLIT:
-       case OPTRLIT:
-               var = temp(n->type);
-               anylit(0, n, var, init);
-               n = var;
-               goto ret;
-
-       case OSEND:
-               n1 = n->right;
-               n1 = assignconv(n1, n->left->type->type, "chan send");
-               walkexpr(&n1, init);
-               n1 = nod(OADDR, n1, N);
-               n = mkcall1(chanfn("chansend1", 2, n->left->type), T, init, typename(n->left->type), n->left, n1);
-               goto ret;
-
-       case OCLOSURE:
-               n = walkclosure(n, init);
-               goto ret;
-       
-       case OCALLPART:
-               n = walkpartialcall(n, init);
-               goto ret;
-       }
-       fatal("missing switch %O", n->op);
-
-ret:
-       // Expressions that are constant at run time but not
-       // considered const by the language spec are not turned into
-       // constants until walk. For example, if n is y%1 == 0, the
-       // walk of y%1 may have replaced it by 0.
-       // Check whether n with its updated args is itself now a constant.
-       t = n->type;
-       evconst(n);
-       n->type = t;
-       if(n->op == OLITERAL)
-               typecheck(&n, Erv);
-
-       ullmancalc(n);
-
-       if(debug['w'] && n != N)
-               dump("walk", n);
-
-       lineno = lno;
-       *np = n;
-}
-
-static Node*
-ascompatee1(int op, Node *l, Node *r, NodeList **init)
-{
-       Node *n;
-       USED(op);
-       
-       // convas will turn map assigns into function calls,
-       // making it impossible for reorder3 to work.
-       n = nod(OAS, l, r);
-       if(l->op == OINDEXMAP)
-               return n;
-
-       return convas(n, init);
-}
-
-static NodeList*
-ascompatee(int op, NodeList *nl, NodeList *nr, NodeList **init)
-{
-       NodeList *ll, *lr, *nn;
-
-       /*
-        * check assign expression list to
-        * a expression list. called in
-        *      expr-list = expr-list
-        */
-
-       // ensure order of evaluation for function calls
-       for(ll=nl; ll; ll=ll->next)
-               ll->n = safeexpr(ll->n, init);
-       for(lr=nr; lr; lr=lr->next)
-               lr->n = safeexpr(lr->n, init);
-
-       nn = nil;
-       for(ll=nl, lr=nr; ll && lr; ll=ll->next, lr=lr->next) {
-               // Do not generate 'x = x' during return. See issue 4014.
-               if(op == ORETURN && ll->n == lr->n)
-                       continue;
-               nn = list(nn, ascompatee1(op, ll->n, lr->n, init));
-       }
-
-       // cannot happen: caller checked that lists had same length
-       if(ll || lr)
-               yyerror("error in shape across %+H %O %+H / %d %d [%s]", nl, op, nr, count(nl), count(nr), curfn->nname->sym->name);
-       return nn;
-}
-
-/*
- * l is an lv and rt is the type of an rv
- * return 1 if this implies a function call
- * evaluating the lv or a function call
- * in the conversion of the types
- */
-static int
-fncall(Node *l, Type *rt)
-{
-       Node r;
-
-       if(l->ullman >= UINF || l->op == OINDEXMAP)
-               return 1;
-       memset(&r, 0, sizeof r);
-       if(needwritebarrier(l, &r))
-               return 1;
-       if(eqtype(l->type, rt))
-               return 0;
-       return 1;
-}
-
-static NodeList*
-ascompatet(int op, NodeList *nl, Type **nr, int fp, NodeList **init)
-{
-       Node *l, *tmp, *a;
-       NodeList *ll;
-       Type *r;
-       Iter saver;
-       int ucount;
-       NodeList *nn, *mm;
-
-       USED(op);
-
-       /*
-        * check assign type list to
-        * a expression list. called in
-        *      expr-list = func()
-        */
-       r = structfirst(&saver, nr);
-       nn = nil;
-       mm = nil;
-       ucount = 0;
-       for(ll=nl; ll; ll=ll->next) {
-               if(r == T)
-                       break;
-               l = ll->n;
-               if(isblank(l)) {
-                       r = structnext(&saver);
-                       continue;
-               }
-
-               // any lv that causes a fn call must be
-               // deferred until all the return arguments
-               // have been pulled from the output arguments
-               if(fncall(l, r->type)) {
-                       tmp = temp(r->type);
-                       typecheck(&tmp, Erv);
-                       a = nod(OAS, l, tmp);
-                       a = convas(a, init);
-                       mm = list(mm, a);
-                       l = tmp;
-               }
-
-               a = nod(OAS, l, nodarg(r, fp));
-               a = convas(a, init);
-               ullmancalc(a);
-               if(a->ullman >= UINF) {
-                       dump("ascompatet ucount", a);
-                       ucount++;
-               }
-               nn = list(nn, a);
-               r = structnext(&saver);
-       }
-
-       if(ll != nil || r != T)
-               yyerror("ascompatet: assignment count mismatch: %d = %d",
-                       count(nl), structcount(*nr));
-
-       if(ucount)
-               fatal("ascompatet: too many function calls evaluating parameters");
-       return concat(nn, mm);
-}
-
- /*
- * package all the arguments that match a ... T parameter into a []T.
- */
-static NodeList*
-mkdotargslice(NodeList *lr0, NodeList *nn, Type *l, int fp, NodeList **init, Node *ddd)
-{
-       Node *a, *n;
-       Type *tslice;
-       int esc;
-       
-       esc = EscUnknown;
-       if(ddd != nil)
-               esc = ddd->esc;
-       
-       tslice = typ(TARRAY);
-       tslice->type = l->type->type;
-       tslice->bound = -1;
-
-       if(count(lr0) == 0) {
-               n = nodnil();
-               n->type = tslice;
-       } else {
-               n = nod(OCOMPLIT, N, typenod(tslice));
-               if(ddd != nil)
-                       n->alloc = ddd->alloc; // temporary to use
-               n->list = lr0;
-               n->esc = esc;
-               typecheck(&n, Erv);
-               if(n->type == T)
-                       fatal("mkdotargslice: typecheck failed");
-               walkexpr(&n, init);
-       }
-
-       a = nod(OAS, nodarg(l, fp), n);
-       nn = list(nn, convas(a, init));
-       return nn;
-}
-
-/*
- * helpers for shape errors
- */
-static char*
-dumptypes(Type **nl, char *what)
-{
-       int first;
-       Type *l;
-       Iter savel;
-       Fmt fmt;
-
-       fmtstrinit(&fmt);
-       fmtprint(&fmt, "\t");
-       first = 1;
-       for(l = structfirst(&savel, nl); l != T; l = structnext(&savel)) {
-               if(first)
-                       first = 0;
-               else
-                       fmtprint(&fmt, ", ");
-               fmtprint(&fmt, "%T", l);
-       }
-       if(first)
-               fmtprint(&fmt, "[no arguments %s]", what);
-       return fmtstrflush(&fmt);
-}
-
-static char*
-dumpnodetypes(NodeList *l, char *what)
-{
-       int first;
-       Node *r;
-       Fmt fmt;
-
-       fmtstrinit(&fmt);
-       fmtprint(&fmt, "\t");
-       first = 1;
-       for(; l; l=l->next) {
-               r = l->n;
-               if(first)
-                       first = 0;
-               else
-                       fmtprint(&fmt, ", ");
-               fmtprint(&fmt, "%T", r->type);
-       }
-       if(first)
-               fmtprint(&fmt, "[no arguments %s]", what);
-       return fmtstrflush(&fmt);
-}
-
-/*
- * check assign expression list to
- * a type list. called in
- *     return expr-list
- *     func(expr-list)
- */
-static NodeList*
-ascompatte(int op, Node *call, int isddd, Type **nl, NodeList *lr, int fp, NodeList **init)
-{
-       Type *l, *ll;
-       Node *r, *a;
-       NodeList *nn, *lr0, *alist;
-       Iter savel;
-       char *l1, *l2;
-
-       lr0 = lr;
-       l = structfirst(&savel, nl);
-       r = N;
-       if(lr)
-               r = lr->n;
-       nn = nil;
-
-       // f(g()) where g has multiple return values
-       if(r != N && lr->next == nil && r->type->etype == TSTRUCT && r->type->funarg) {
-               // optimization - can do block copy
-               if(eqtypenoname(r->type, *nl)) {
-                       a = nodarg(*nl, fp);
-                       r = nod(OCONVNOP, r, N);
-                       r->type = a->type;
-                       nn = list1(convas(nod(OAS, a, r), init));
-                       goto ret;
-               }
-
-               // conversions involved.
-               // copy into temporaries.
-               alist = nil;
-               for(l=structfirst(&savel, &r->type); l; l=structnext(&savel)) {
-                       a = temp(l->type);
-                       alist = list(alist, a);
-               }
-               a = nod(OAS2, N, N);
-               a->list = alist;
-               a->rlist = lr;
-               typecheck(&a, Etop);
-               walkstmt(&a);
-               *init = list(*init, a);
-               lr = alist;
-               r = lr->n;
-               l = structfirst(&savel, nl);
-       }
-
-loop:
-       if(l != T && l->isddd) {
-               // the ddd parameter must be last
-               ll = structnext(&savel);
-               if(ll != T)
-                       yyerror("... must be last argument");
-
-               // special case --
-               // only if we are assigning a single ddd
-               // argument to a ddd parameter then it is
-               // passed thru unencapsulated
-               if(r != N && lr->next == nil && isddd && eqtype(l->type, r->type)) {
-                       a = nod(OAS, nodarg(l, fp), r);
-                       a = convas(a, init);
-                       nn = list(nn, a);
-                       goto ret;
-               }
-
-               // normal case -- make a slice of all
-               // remaining arguments and pass it to
-               // the ddd parameter.
-               nn = mkdotargslice(lr, nn, l, fp, init, call->right);
-               goto ret;
-       }
-
-       if(l == T || r == N) {
-               if(l != T || r != N) {
-                       l1 = dumptypes(nl, "expected");
-                       l2 = dumpnodetypes(lr0, "given");
-                       if(l != T)
-                               yyerror("not enough arguments to %O\n%s\n%s", op, l1, l2);
-                       else
-                               yyerror("too many arguments to %O\n%s\n%s", op, l1, l2);
-               }
-               goto ret;
-       }
-
-       a = nod(OAS, nodarg(l, fp), r);
-       a = convas(a, init);
-       nn = list(nn, a);
-
-       l = structnext(&savel);
-       r = N;
-       lr = lr->next;
-       if(lr != nil)
-               r = lr->n;
-       goto loop;
-
-ret:
-       for(lr=nn; lr; lr=lr->next)
-               lr->n->typecheck = 1;
-       return nn;
-}
-
-// generate code for print
-static Node*
-walkprint(Node *nn, NodeList **init)
-{
-       Node *r;
-       Node *n;
-       NodeList *l, *all;
-       Node *on;
-       Type *t;
-       int notfirst, et, op;
-       NodeList *calls;
-
-       op = nn->op;
-       all = nn->list;
-       calls = nil;
-       notfirst = 0;
-
-       // Hoist all the argument evaluation up before the lock.
-       walkexprlistcheap(all, init);
-
-       calls = list(calls, mkcall("printlock", T, init));
-
-       for(l=all; l; l=l->next) {
-               if(notfirst) {
-                       calls = list(calls, mkcall("printsp", T, init));
-               }
-               notfirst = op == OPRINTN;
-
-               n = l->n;
-               if(n->op == OLITERAL) {
-                       switch(n->val.ctype) {
-                       case CTRUNE:
-                               defaultlit(&n, runetype);
-                               break;
-                       case CTINT:
-                               defaultlit(&n, types[TINT64]);
-                               break;
-                       case CTFLT:
-                               defaultlit(&n, types[TFLOAT64]);
-                               break;
-                       }
-               }
-               if(n->op != OLITERAL && n->type && n->type->etype == TIDEAL)
-                       defaultlit(&n, types[TINT64]);
-               defaultlit(&n, nil);
-               l->n = n;
-               if(n->type == T || n->type->etype == TFORW)
-                       continue;
-
-               t = n->type;
-               et = n->type->etype;
-               if(isinter(n->type)) {
-                       if(isnilinter(n->type))
-                               on = syslook("printeface", 1);
-                       else
-                               on = syslook("printiface", 1);
-                       argtype(on, n->type);           // any-1
-               } else if(isptr[et] || et == TCHAN || et == TMAP || et == TFUNC || et == TUNSAFEPTR) {
-                       on = syslook("printpointer", 1);
-                       argtype(on, n->type);   // any-1
-               } else if(isslice(n->type)) {
-                       on = syslook("printslice", 1);
-                       argtype(on, n->type);   // any-1
-               } else if(isint[et]) {
-                       if(et == TUINT64) {
-                               if((t->sym->pkg == runtimepkg || compiling_runtime) && strcmp(t->sym->name, "hex") == 0)
-                                       on = syslook("printhex", 0);
-                               else
-                                       on = syslook("printuint", 0);
-                       } else
-                               on = syslook("printint", 0);
-               } else if(isfloat[et]) {
-                       on = syslook("printfloat", 0);
-               } else if(iscomplex[et]) {
-                       on = syslook("printcomplex", 0);
-               } else if(et == TBOOL) {
-                       on = syslook("printbool", 0);
-               } else if(et == TSTRING) {
-                       on = syslook("printstring", 0);
-               } else {
-                       badtype(OPRINT, n->type, T);
-                       continue;
-               }
-
-               t = *getinarg(on->type);
-               if(t != nil)
-                       t = t->type;
-               if(t != nil)
-                       t = t->type;
-
-               if(!eqtype(t, n->type)) {
-                       n = nod(OCONV, n, N);
-                       n->type = t;
-               }
-
-               r = nod(OCALL, on, N);
-               r->list = list1(n);
-               calls = list(calls, r);
-       }
-
-       if(op == OPRINTN)
-               calls = list(calls, mkcall("printnl", T, nil));
-
-       calls = list(calls, mkcall("printunlock", T, init));
-
-       typechecklist(calls, Etop);
-       walkexprlist(calls, init);
-
-       r = nod(OEMPTY, N, N);
-       typecheck(&r, Etop);
-       walkexpr(&r, init);
-       r->ninit = calls;
-       return r;
-}
-
-Node*
-callnew(Type *t)
-{
-       Node *fn;
-
-       dowidth(t);
-       fn = syslook("newobject", 1);
-       argtype(fn, t);
-       return mkcall1(fn, ptrto(t), nil, typename(t));
-}
-
-static int
-isstack(Node *n)
-{
-       Node *defn;
-
-       n = outervalue(n);
-
-       // If n is *autotmp and autotmp = &foo, replace n with foo.
-       // We introduce such temps when initializing struct literals.
-       if(n->op == OIND && n->left->op == ONAME && strncmp(n->left->sym->name, "autotmp_", 8) == 0) {
-               defn = n->left->defn;
-               if(defn != N && defn->op == OAS && defn->right->op == OADDR)
-                       n = defn->right->left;
-       }
-
-       switch(n->op) {
-       case OINDREG:
-               // OINDREG only ends up in walk if it's indirect of SP.
-               return 1;
-
-       case ONAME:
-               switch(n->class) {
-               case PAUTO:
-               case PPARAM:
-               case PPARAMOUT:
-                       return 1;
-               }
-               break;
-       }
-       
-       return 0;
-}
-
-static int
-isglobal(Node *n)
-{
-       n = outervalue(n);
-
-       switch(n->op) {
-       case ONAME:
-               switch(n->class) {
-               case PEXTERN:
-                       return 1;
-               }
-               break;
-       }
-       
-       return 0;
-}
-
-// Do we need a write barrier for the assignment l = r?
-int
-needwritebarrier(Node *l, Node *r)
-{
-       if(!use_writebarrier)
-               return 0;
-
-       if(l == N || isblank(l))
-               return 0;
-
-       // No write barrier for write of non-pointers.
-       dowidth(l->type);
-       if(!haspointers(l->type))
-               return 0;
-
-       // No write barrier for write to stack.
-       if(isstack(l))
-               return 0;
-
-       // No write barrier for implicit or explicit zeroing.
-       if(r == N || iszero(r))
-               return 0;
-
-       // No write barrier for initialization to constant.
-       if(r->op == OLITERAL)
-               return 0;
-
-       // No write barrier for storing static (read-only) data.
-       if(r->op == ONAME && strncmp(r->sym->name, "statictmp_", 10) == 0)
-               return 0;
-
-       // No write barrier for storing address of stack values,
-       // which are guaranteed only to be written to the stack.
-       if(r->op == OADDR && isstack(r->left))
-               return 0;
-
-       // No write barrier for storing address of global, which
-       // is live no matter what.
-       if(r->op == OADDR && isglobal(r->left))
-               return 0;
-
-       // No write barrier for reslice: x = x[0:y] or x = append(x, ...).
-       // Both are compiled to modify x directly.
-       // In the case of append, a write barrier may still be needed
-       // if the underlying array grows, but the append code can
-       // generate the write barrier directly in that case.
-       // (It does not yet, but the cost of the write barrier will be
-       // small compared to the cost of the allocation.)
-       if(r->reslice) {
-               switch(r->op) {
-               case OSLICE:
-               case OSLICE3:
-               case OSLICESTR:
-               case OAPPEND:
-                       break;
-               default:
-                       dump("bad reslice-l", l);
-                       dump("bad reslice-r", r);
-                       break;
-               }
-               return 0;
-       }
-
-       // Otherwise, be conservative and use write barrier.
-       return 1;
-}
-
-// TODO(rsc): Perhaps componentgen should run before this.
-static Node*
-applywritebarrier(Node *n, NodeList **init)
-{
-       Node *l, *r;
-       Type *t;
-       vlong x;
-       static Bvec *bv;
-       char name[32];
-
-       if(n->left && n->right && needwritebarrier(n->left, n->right)) {
-               if(curfn && curfn->nowritebarrier)
-                       yyerror("write barrier prohibited");
-               t = n->left->type;
-               l = nod(OADDR, n->left, N);
-               l->etype = 1; // addr does not escape
-               if(t->width == widthptr) {
-                       n = mkcall1(writebarrierfn("writebarrierptr", t, n->right->type), T, init,
-                               l, n->right);
-               } else if(t->etype == TSTRING) {
-                       n = mkcall1(writebarrierfn("writebarrierstring", t, n->right->type), T, init,
-                               l, n->right);
-               } else if(isslice(t)) {
-                       n = mkcall1(writebarrierfn("writebarrierslice", t, n->right->type), T, init,
-                               l, n->right);
-               } else if(isinter(t)) {
-                       n = mkcall1(writebarrierfn("writebarrieriface", t, n->right->type), T, init,
-                               l, n->right);
-               } else if(t->width <= 4*widthptr) {
-                       x = 0;
-                       if(bv == nil)
-                               bv = bvalloc(BitsPerPointer*4);
-                       bvresetall(bv);
-                       twobitwalktype1(t, &x, bv);
-                       // The bvgets are looking for BitsPointer in successive slots.
-                       enum {
-                               PtrBit = 1,
-                       };
-                       if(BitsPointer != (1<<PtrBit))
-                               fatal("wrong PtrBit");
-                       switch(t->width/widthptr) {
-                       default:
-                               fatal("found writebarrierfat for %d-byte object of type %T", (int)t->width, t);
-                       case 2:
-                               snprint(name, sizeof name, "writebarrierfat%d%d",
-                                       bvget(bv, PtrBit), bvget(bv, BitsPerPointer+PtrBit));
-                               break;
-                       case 3:
-                               snprint(name, sizeof name, "writebarrierfat%d%d%d",
-                                       bvget(bv, PtrBit), bvget(bv, BitsPerPointer+PtrBit), bvget(bv, 2*BitsPerPointer+PtrBit));
-                               break;
-                       case 4:
-                               snprint(name, sizeof name, "writebarrierfat%d%d%d%d",
-                                       bvget(bv, PtrBit), bvget(bv, BitsPerPointer+PtrBit), bvget(bv, 2*BitsPerPointer+PtrBit), bvget(bv, 3*BitsPerPointer+PtrBit));
-                               break;
-                       }
-                       n = mkcall1(writebarrierfn(name, t, n->right->type), T, init,
-                               l, nodnil(), n->right);
-               } else {
-                       r = n->right;
-                       while(r->op == OCONVNOP)
-                               r = r->left;
-                       r = nod(OADDR, r, N);
-                       r->etype = 1; // addr does not escape
-                       //warnl(n->lineno, "typedmemmove %T %N", t, r);
-                       n = mkcall1(writebarrierfn("typedmemmove", t, r->left->type), T, init,
-                               typename(t), l, r);
-               }
-       }
-       return n;
-}
-
-static Node*
-convas(Node *n, NodeList **init)
-{
-       Type *lt, *rt;
-       Node *map, *key, *val;
-
-       if(n->op != OAS)
-               fatal("convas: not OAS %O", n->op);
-
-       n->typecheck = 1;
-
-       if(n->left == N || n->right == N)
-               goto out;
-
-       lt = n->left->type;
-       rt = n->right->type;
-       if(lt == T || rt == T)
-               goto out;
-
-       if(isblank(n->left)) {
-               defaultlit(&n->right, T);
-               goto out;
-       }
-
-       if(n->left->op == OINDEXMAP) {
-               map = n->left->left;
-               key = n->left->right;
-               val = n->right;
-               walkexpr(&map, init);
-               walkexpr(&key, init);
-               walkexpr(&val, init);
-               // orderexpr made sure key and val are addressable.
-               key = nod(OADDR, key, N);
-               val = nod(OADDR, val, N);
-               n = mkcall1(mapfn("mapassign1", map->type), T, init,
-                       typename(map->type), map, key, val);
-               goto out;
-       }
-
-       if(!eqtype(lt, rt)) {
-               n->right = assignconv(n->right, lt, "assignment");
-               walkexpr(&n->right, init);
-       }
-
-out:
-       ullmancalc(n);
-       return n;
-}
-
-/*
- * from ascompat[te]
- * evaluating actual function arguments.
- *     f(a,b)
- * if there is exactly one function expr,
- * then it is done first. otherwise must
- * make temp variables
- */
-static NodeList*
-reorder1(NodeList *all)
-{
-       Node *f, *a, *n;
-       NodeList *l, *r, *g;
-       int c, d, t;
-
-       c = 0;  // function calls
-       t = 0;  // total parameters
-
-       for(l=all; l; l=l->next) {
-               n = l->n;
-               t++;
-               ullmancalc(n);
-               if(n->ullman >= UINF)
-                       c++;
-       }
-       if(c == 0 || t == 1)
-               return all;
-
-       g = nil;        // fncalls assigned to tempnames
-       f = N;  // last fncall assigned to stack
-       r = nil;        // non fncalls and tempnames assigned to stack
-       d = 0;
-       for(l=all; l; l=l->next) {
-               n = l->n;
-               if(n->ullman < UINF) {
-                       r = list(r, n);
-                       continue;
-               }
-               d++;
-               if(d == c) {
-                       f = n;
-                       continue;
-               }
-
-               // make assignment of fncall to tempname
-               a = temp(n->right->type);
-               a = nod(OAS, a, n->right);
-               g = list(g, a);
-
-               // put normal arg assignment on list
-               // with fncall replaced by tempname
-               n->right = a->left;
-               r = list(r, n);
-       }
-
-       if(f != N)
-               g = list(g, f);
-       return concat(g, r);
-}
-
-static void reorder3save(Node**, NodeList*, NodeList*, NodeList**);
-static int aliased(Node*, NodeList*, NodeList*);
-
-/*
- * from ascompat[ee]
- *     a,b = c,d
- * simultaneous assignment. there cannot
- * be later use of an earlier lvalue.
- *
- * function calls have been removed.
- */
-static NodeList*
-reorder3(NodeList *all)
-{
-       NodeList *list, *early, *mapinit;
-       Node *l;
-
-       // If a needed expression may be affected by an
-       // earlier assignment, make an early copy of that
-       // expression and use the copy instead.
-       early = nil;
-       mapinit = nil;
-       for(list=all; list; list=list->next) {
-               l = list->n->left;
-
-               // Save subexpressions needed on left side.
-               // Drill through non-dereferences.
-               for(;;) {
-                       if(l->op == ODOT || l->op == OPAREN) {
-                               l = l->left;
-                               continue;
-                       }
-                       if(l->op == OINDEX && isfixedarray(l->left->type)) {
-                               reorder3save(&l->right, all, list, &early);
-                               l = l->left;
-                               continue;
-                       }
-                       break;
-               }
-               switch(l->op) {
-               default:
-                       fatal("reorder3 unexpected lvalue %#O", l->op);
-               case ONAME:
-                       break;
-               case OINDEX:
-               case OINDEXMAP:
-                       reorder3save(&l->left, all, list, &early);
-                       reorder3save(&l->right, all, list, &early);
-                       if(l->op == OINDEXMAP)
-                               list->n = convas(list->n, &mapinit);
-                       break;
-               case OIND:
-               case ODOTPTR:
-                       reorder3save(&l->left, all, list, &early);
-               }
-
-               // Save expression on right side.
-               reorder3save(&list->n->right, all, list, &early);
-       }
-
-       early = concat(mapinit, early);
-       return concat(early, all);
-}
-
-static int vmatch2(Node*, Node*);
-static int varexpr(Node*);
-
-/*
- * if the evaluation of *np would be affected by the 
- * assignments in all up to but not including stop,
- * copy into a temporary during *early and
- * replace *np with that temp.
- */
-static void
-reorder3save(Node **np, NodeList *all, NodeList *stop, NodeList **early)
-{
-       Node *n, *q;
-
-       n = *np;
-       if(!aliased(n, all, stop))
-               return;
-       
-       q = temp(n->type);
-       q = nod(OAS, q, n);
-       typecheck(&q, Etop);
-       *early = list(*early, q);
-       *np = q->left;
-}
-
-/*
- * what's the outer value that a write to n affects?
- * outer value means containing struct or array.
- */
-Node*
-outervalue(Node *n)
-{      
-       for(;;) {
-               if(n->op == OXDOT)
-                       fatal("OXDOT in walk");
-               if(n->op == ODOT || n->op == OPAREN || n->op == OCONVNOP) {
-                       n = n->left;
-                       continue;
-               }
-               if(n->op == OINDEX && isfixedarray(n->left->type)) {
-                       n = n->left;
-                       continue;
-               }
-               break;
-       }
-       return n;
-}
-
-/*
- * Is it possible that the computation of n might be
- * affected by writes in as up to but not including stop?
- */
-static int
-aliased(Node *n, NodeList *all, NodeList *stop)
-{
-       int memwrite, varwrite;
-       Node *a;
-       NodeList *l;
-
-       if(n == N)
-               return 0;
-
-       // Look for obvious aliasing: a variable being assigned
-       // during the all list and appearing in n.
-       // Also record whether there are any writes to main memory.
-       // Also record whether there are any writes to variables
-       // whose addresses have been taken.
-       memwrite = 0;
-       varwrite = 0;
-       for(l=all; l!=stop; l=l->next) {
-               a = outervalue(l->n->left);
-               if(a->op != ONAME) {
-                       memwrite = 1;
-                       continue;
-               }
-               switch(n->class) {
-               default:
-                       varwrite = 1;
-                       continue;
-               case PAUTO:
-               case PPARAM:
-               case PPARAMOUT:
-                       if(n->addrtaken) {
-                               varwrite = 1;
-                               continue;
-                       }
-                       if(vmatch2(a, n)) {
-                               // Direct hit.
-                               return 1;
-                       }
-               }
-       }
-
-       // The variables being written do not appear in n.
-       // However, n might refer to computed addresses
-       // that are being written.
-       
-       // If no computed addresses are affected by the writes, no aliasing.
-       if(!memwrite && !varwrite)
-               return 0;
-
-       // If n does not refer to computed addresses
-       // (that is, if n only refers to variables whose addresses
-       // have not been taken), no aliasing.
-       if(varexpr(n))
-               return 0;
-
-       // Otherwise, both the writes and n refer to computed memory addresses.
-       // Assume that they might conflict.
-       return 1;
-}
-
-/*
- * does the evaluation of n only refer to variables
- * whose addresses have not been taken?
- * (and no other memory)
- */
-static int
-varexpr(Node *n)
-{
-       if(n == N)
-               return 1;
-
-       switch(n->op) {
-       case OLITERAL:  
-               return 1;
-       case ONAME:
-               switch(n->class) {
-               case PAUTO:
-               case PPARAM:
-               case PPARAMOUT:
-                       if(!n->addrtaken)
-                               return 1;
-               }
-               return 0;
-
-       case OADD:
-       case OSUB:
-       case OOR:
-       case OXOR:
-       case OMUL:
-       case ODIV:
-       case OMOD:
-       case OLSH:
-       case ORSH:
-       case OAND:
-       case OANDNOT:
-       case OPLUS:
-       case OMINUS:
-       case OCOM:
-       case OPAREN:
-       case OANDAND:
-       case OOROR:
-       case ODOT:  // but not ODOTPTR
-       case OCONV:
-       case OCONVNOP:
-       case OCONVIFACE:
-       case ODOTTYPE:
-               return varexpr(n->left) && varexpr(n->right);
-       }
-
-       // Be conservative.
-       return 0;
-}
-
-/*
- * is the name l mentioned in r?
- */
-static int
-vmatch2(Node *l, Node *r)
-{
-       NodeList *ll;
-
-       if(r == N)
-               return 0;
-       switch(r->op) {
-       case ONAME:
-               // match each right given left
-               return l == r;
-       case OLITERAL:
-               return 0;
-       }
-       if(vmatch2(l, r->left))
-               return 1;
-       if(vmatch2(l, r->right))
-               return 1;
-       for(ll=r->list; ll; ll=ll->next)
-               if(vmatch2(l, ll->n))
-                       return 1;
-       return 0;
-}
-
-/*
- * is any name mentioned in l also mentioned in r?
- * called by sinit.c
- */
-int
-vmatch1(Node *l, Node *r)
-{
-       NodeList *ll;
-
-       /*
-        * isolate all left sides
-        */
-       if(l == N || r == N)
-               return 0;
-       switch(l->op) {
-       case ONAME:
-               switch(l->class) {
-               case PPARAM:
-               case PPARAMREF:
-               case PAUTO:
-                       break;
-               default:
-                       // assignment to non-stack variable
-                       // must be delayed if right has function calls.
-                       if(r->ullman >= UINF)
-                               return 1;
-                       break;
-               }
-               return vmatch2(l, r);
-       case OLITERAL:
-               return 0;
-       }
-       if(vmatch1(l->left, r))
-               return 1;
-       if(vmatch1(l->right, r))
-               return 1;
-       for(ll=l->list; ll; ll=ll->next)
-               if(vmatch1(ll->n, r))
-                       return 1;
-       return 0;
-}
-
-/*
- * walk through argin parameters.
- * generate and return code to allocate
- * copies of escaped parameters to the heap.
- */
-static NodeList*
-paramstoheap(Type **argin, int out)
-{
-       Type *t;
-       Iter savet;
-       Node *v, *as;
-       NodeList *nn;
-
-       nn = nil;
-       for(t = structfirst(&savet, argin); t != T; t = structnext(&savet)) {
-               v = t->nname;
-               if(v && v->sym && v->sym->name[0] == '~' && v->sym->name[1] == 'r') // unnamed result
-                       v = N;
-               // For precise stacks, the garbage collector assumes results
-               // are always live, so zero them always.
-               if(out) {
-                       // Defer might stop a panic and show the
-                       // return values as they exist at the time of panic.
-                       // Make sure to zero them on entry to the function.
-                       nn = list(nn, nod(OAS, nodarg(t, 1), N));
-               }
-               if(v == N || !(v->class & PHEAP))
-                       continue;
-
-               // generate allocation & copying code
-               if(compiling_runtime)
-                       yyerror("%N escapes to heap, not allowed in runtime.", v);
-               if(v->alloc == nil)
-                       v->alloc = callnew(v->type);
-               nn = list(nn, nod(OAS, v->heapaddr, v->alloc));
-               if((v->class & ~PHEAP) != PPARAMOUT) {
-                       as = nod(OAS, v, v->stackparam);
-                       v->stackparam->typecheck = 1;
-                       typecheck(&as, Etop);
-                       as = applywritebarrier(as, &nn);
-                       nn = list(nn, as);
-               }
-       }
-       return nn;
-}
-
-/*
- * walk through argout parameters copying back to stack
- */
-static NodeList*
-returnsfromheap(Type **argin)
-{
-       Type *t;
-       Iter savet;
-       Node *v;
-       NodeList *nn;
-
-       nn = nil;
-       for(t = structfirst(&savet, argin); t != T; t = structnext(&savet)) {
-               v = t->nname;
-               if(v == N || v->class != (PHEAP|PPARAMOUT))
-                       continue;
-               nn = list(nn, nod(OAS, v->stackparam, v));
-       }
-       return nn;
-}
-
-/*
- * take care of migrating any function in/out args
- * between the stack and the heap.  adds code to
- * curfn's before and after lists.
- */
-static void
-heapmoves(void)
-{
-       NodeList *nn;
-       int32 lno;
-
-       lno = lineno;
-       lineno = curfn->lineno;
-       nn = paramstoheap(getthis(curfn->type), 0);
-       nn = concat(nn, paramstoheap(getinarg(curfn->type), 0));
-       nn = concat(nn, paramstoheap(getoutarg(curfn->type), 1));
-       curfn->enter = concat(curfn->enter, nn);
-       lineno = curfn->endlineno;
-       curfn->exit = returnsfromheap(getoutarg(curfn->type));
-       lineno = lno;
-}
-
-static Node*
-vmkcall(Node *fn, Type *t, NodeList **init, va_list va)
-{
-       int i, n;
-       Node *r;
-       NodeList *args;
-
-       if(fn->type == T || fn->type->etype != TFUNC)
-               fatal("mkcall %N %T", fn, fn->type);
-
-       args = nil;
-       n = fn->type->intuple;
-       for(i=0; i<n; i++)
-               args = list(args, va_arg(va, Node*));
-
-       r = nod(OCALL, fn, N);
-       r->list = args;
-       if(fn->type->outtuple > 0)
-               typecheck(&r, Erv | Efnstruct);
-       else
-               typecheck(&r, Etop);
-       walkexpr(&r, init);
-       r->type = t;
-       return r;
-}
-
-Node*
-mkcall(char *name, Type *t, NodeList **init, ...)
-{
-       Node *r;
-       va_list va;
-
-       va_start(va, init);
-       r = vmkcall(syslook(name, 0), t, init, va);
-       va_end(va);
-       return r;
-}
-
-Node*
-mkcall1(Node *fn, Type *t, NodeList **init, ...)
-{
-       Node *r;
-       va_list va;
-
-       va_start(va, init);
-       r = vmkcall(fn, t, init, va);
-       va_end(va);
-       return r;
-}
-
-Node*
-conv(Node *n, Type *t)
-{
-       if(eqtype(n->type, t))
-               return n;
-       n = nod(OCONV, n, N);
-       n->type = t;
-       typecheck(&n, Erv);
-       return n;
-}
-
-Node*
-chanfn(char *name, int n, Type *t)
-{
-       Node *fn;
-       int i;
-
-       if(t->etype != TCHAN)
-               fatal("chanfn %T", t);
-       fn = syslook(name, 1);
-       for(i=0; i<n; i++)
-               argtype(fn, t->type);
-       return fn;
-}
-
-static Node*
-mapfn(char *name, Type *t)
-{
-       Node *fn;
-
-       if(t->etype != TMAP)
-               fatal("mapfn %T", t);
-       fn = syslook(name, 1);
-       argtype(fn, t->down);
-       argtype(fn, t->type);
-       argtype(fn, t->down);
-       argtype(fn, t->type);
-       return fn;
-}
-
-static Node*
-mapfndel(char *name, Type *t)
-{
-       Node *fn;
-
-       if(t->etype != TMAP)
-               fatal("mapfn %T", t);
-       fn = syslook(name, 1);
-       argtype(fn, t->down);
-       argtype(fn, t->type);
-       argtype(fn, t->down);
-       return fn;
-}
-
-static Node*
-writebarrierfn(char *name, Type *l, Type *r)
-{
-       Node *fn;
-
-       fn = syslook(name, 1);
-       argtype(fn, l);
-       argtype(fn, r);
-       return fn;
-}
-
-static Node*
-addstr(Node *n, NodeList **init)
-{
-       Node *r, *cat, *slice, *buf;
-       NodeList *args, *l;
-       int c;
-       vlong sz;
-       Type *t;
-
-       // orderexpr rewrote OADDSTR to have a list of strings.
-       c = count(n->list);
-       if(c < 2)
-               yyerror("addstr count %d too small", c);
-
-       buf = nodnil();
-       if(n->esc == EscNone) {
-               sz = 0;
-               for(l=n->list; l != nil; l=l->next) {
-                       if(n->op == OLITERAL)
-                               sz += n->val.u.sval->len;
-               }
-               // Don't allocate the buffer if the result won't fit.
-               if(sz < tmpstringbufsize) {
-                       // Create temporary buffer for result string on stack.
-                       t = aindex(nodintconst(tmpstringbufsize), types[TUINT8]);
-                       buf = nod(OADDR, temp(t), N);
-               }
-       }
-
-       // build list of string arguments
-       args = list1(buf);
-       for(l=n->list; l != nil; l=l->next)
-               args = list(args, conv(l->n, types[TSTRING]));
-
-       if(c <= 5) {
-               // small numbers of strings use direct runtime helpers.
-               // note: orderexpr knows this cutoff too.
-               snprint(namebuf, sizeof(namebuf), "concatstring%d", c);
-       } else {
-               // large numbers of strings are passed to the runtime as a slice.
-               strcpy(namebuf, "concatstrings");
-               t = typ(TARRAY);
-               t->type = types[TSTRING];
-               t->bound = -1;
-               slice = nod(OCOMPLIT, N, typenod(t));
-               slice->alloc = n->alloc;
-               slice->list = args->next; // skip buf arg
-               args = list1(buf);
-               args = list(args, slice);
-               slice->esc = EscNone;
-       }
-       cat = syslook(namebuf, 1);
-       r = nod(OCALL, cat, N);
-       r->list = args;
-       typecheck(&r, Erv);
-       walkexpr(&r, init);
-       r->type = n->type;
-
-       return r;
-}
-
-// expand append(l1, l2...) to
-//   init {
-//     s := l1
-//     if n := len(l1) + len(l2) - cap(s); n > 0 {
-//       s = growslice(s, n)
-//     }
-//     s = s[:len(l1)+len(l2)]
-//     memmove(&s[len(l1)], &l2[0], len(l2)*sizeof(T))
-//   }
-//   s
-//
-// l2 is allowed to be a string.
-static Node*
-appendslice(Node *n, NodeList **init)
-{
-       NodeList *l;
-       Node *l1, *l2, *nt, *nif, *fn;
-       Node *nptr1, *nptr2, *nwid;
-       Node *s;
-
-       walkexprlistsafe(n->list, init);
-
-       // walkexprlistsafe will leave OINDEX (s[n]) alone if both s
-       // and n are name or literal, but those may index the slice we're
-       // modifying here.  Fix explicitly.
-       for(l=n->list; l; l=l->next)
-               l->n = cheapexpr(l->n, init);
-
-       l1 = n->list->n;
-       l2 = n->list->next->n;
-
-       s = temp(l1->type); // var s []T
-       l = nil;
-       l = list(l, nod(OAS, s, l1)); // s = l1
-
-       nt = temp(types[TINT]);
-       nif = nod(OIF, N, N);
-       // n := len(s) + len(l2) - cap(s)
-       nif->ninit = list1(nod(OAS, nt,
-               nod(OSUB, nod(OADD, nod(OLEN, s, N), nod(OLEN, l2, N)), nod(OCAP, s, N))));
-       nif->ntest = nod(OGT, nt, nodintconst(0));
-       // instantiate growslice(Type*, []any, int64) []any
-       fn = syslook("growslice", 1);
-       argtype(fn, s->type->type);
-       argtype(fn, s->type->type);
-
-       // s = growslice(T, s, n)
-       nif->nbody = list1(nod(OAS, s, mkcall1(fn, s->type, &nif->ninit,
-                                              typename(s->type),
-                                              s,
-                                              conv(nt, types[TINT64]))));
-
-       l = list(l, nif);
-
-       if(haspointers(l1->type->type)) {
-               // copy(s[len(l1):len(l1)+len(l2)], l2)
-               nptr1 = nod(OSLICE, s, nod(OKEY,
-                       nod(OLEN, l1, N),
-                       nod(OADD, nod(OLEN, l1, N), nod(OLEN, l2, N))));
-               nptr1->etype = 1;
-               nptr2 = l2;
-               fn = syslook("typedslicecopy", 1);
-               argtype(fn, l1->type);
-               argtype(fn, l2->type);
-               nt = mkcall1(fn, types[TINT], &l,
-                               typename(l1->type->type),
-                               nptr1, nptr2);
-               l = list(l, nt);
-       } else if(flag_race) {
-               // rely on runtime to instrument copy.
-               // copy(s[len(l1):len(l1)+len(l2)], l2)
-               nptr1 = nod(OSLICE, s, nod(OKEY,
-                       nod(OLEN, l1, N),
-                       nod(OADD, nod(OLEN, l1, N), nod(OLEN, l2, N))));
-               nptr1->etype = 1;
-               nptr2 = l2;
-               if(l2->type->etype == TSTRING)
-                       fn = syslook("slicestringcopy", 1);
-               else
-                       fn = syslook("slicecopy", 1);
-               argtype(fn, l1->type);
-               argtype(fn, l2->type);
-               nt = mkcall1(fn, types[TINT], &l,
-                               nptr1, nptr2,
-                               nodintconst(s->type->type->width));
-               l = list(l, nt);
-       } else {
-               // memmove(&s[len(l1)], &l2[0], len(l2)*sizeof(T))
-               nptr1 = nod(OINDEX, s, nod(OLEN, l1, N));
-               nptr1->bounded = 1;
-               nptr1 = nod(OADDR, nptr1, N);
-
-               nptr2 = nod(OSPTR, l2, N);
-
-               fn = syslook("memmove", 1);
-               argtype(fn, s->type->type);     // 1 old []any
-               argtype(fn, s->type->type);     // 2 ret []any
-
-               nwid = cheapexpr(conv(nod(OLEN, l2, N), types[TUINTPTR]), &l);
-               nwid = nod(OMUL, nwid, nodintconst(s->type->type->width));
-               nt = mkcall1(fn, T, &l, nptr1, nptr2, nwid);
-               l = list(l, nt);
-       }
-
-       // s = s[:len(l1)+len(l2)]
-       nt = nod(OADD, nod(OLEN, l1, N), nod(OLEN, l2, N));
-       nt = nod(OSLICE, s, nod(OKEY, N, nt));
-       nt->etype = 1;
-       l = list(l, nod(OAS, s, nt));
-
-       typechecklist(l, Etop);
-       walkstmtlist(l);
-       *init = concat(*init, l);
-       return s;
-}
-
-// expand append(src, a [, b]* ) to
-//
-//   init {
-//     s := src
-//     const argc = len(args) - 1
-//     if cap(s) - len(s) < argc {
-//         s = growslice(s, argc)
-//     }
-//     n := len(s)
-//     s = s[:n+argc]
-//     s[n] = a
-//     s[n+1] = b
-//     ...
-//   }
-//   s
-static Node*
-append(Node *n, NodeList **init)
-{
-       NodeList *l, *a;
-       Node *nsrc, *ns, *nn, *na, *nx, *fn;
-       int argc;
-
-       walkexprlistsafe(n->list, init);
-
-       // walkexprlistsafe will leave OINDEX (s[n]) alone if both s
-       // and n are name or literal, but those may index the slice we're
-       // modifying here.  Fix explicitly.
-       for(l=n->list; l; l=l->next)
-               l->n = cheapexpr(l->n, init);
-
-       nsrc = n->list->n;
-
-       // Resolve slice type of multi-valued return.
-       if(istype(nsrc->type, TSTRUCT))
-               nsrc->type = nsrc->type->type->type;
-       argc = count(n->list) - 1;
-       if (argc < 1) {
-               return nsrc;
-       }
-
-       l = nil;
-
-       ns = temp(nsrc->type);
-       l = list(l, nod(OAS, ns, nsrc));  // s = src
-
-       na = nodintconst(argc);         // const argc
-       nx = nod(OIF, N, N);            // if cap(s) - len(s) < argc
-       nx->ntest = nod(OLT, nod(OSUB, nod(OCAP, ns, N), nod(OLEN, ns, N)), na);
-
-       fn = syslook("growslice", 1);   //   growslice(<type>, old []T, n int64) (ret []T)
-       argtype(fn, ns->type->type);    // 1 old []any
-       argtype(fn, ns->type->type);    // 2 ret []any
-
-       nx->nbody = list1(nod(OAS, ns, mkcall1(fn,  ns->type, &nx->ninit,
-                                              typename(ns->type),
-                                              ns,
-                                              conv(na, types[TINT64]))));
-       l = list(l, nx);
-
-       nn = temp(types[TINT]);
-       l = list(l, nod(OAS, nn, nod(OLEN, ns, N)));     // n = len(s)
-
-       nx = nod(OSLICE, ns, nod(OKEY, N, nod(OADD, nn, na)));   // ...s[:n+argc]
-       nx->etype = 1;
-       l = list(l, nod(OAS, ns, nx));                  // s = s[:n+argc]
-
-       for (a = n->list->next;  a != nil; a = a->next) {
-               nx = nod(OINDEX, ns, nn);               // s[n] ...
-               nx->bounded = 1;
-               l = list(l, nod(OAS, nx, a->n));        // s[n] = arg
-               if (a->next != nil)
-                       l = list(l, nod(OAS, nn, nod(OADD, nn, nodintconst(1))));  // n = n + 1
-       }
-
-       typechecklist(l, Etop);
-       walkstmtlist(l);
-       *init = concat(*init, l);
-       return ns;
-}
-
-// Lower copy(a, b) to a memmove call or a runtime call.
-//
-// init {
-//   n := len(a)
-//   if n > len(b) { n = len(b) }
-//   memmove(a.ptr, b.ptr, n*sizeof(elem(a)))
-// }
-// n;
-//
-// Also works if b is a string.
-//
-static Node*
-copyany(Node *n, NodeList **init, int runtimecall)
-{
-       Node *nl, *nr, *nfrm, *nto, *nif, *nlen, *nwid, *fn;
-       NodeList *l;
-       
-       if(haspointers(n->left->type->type)) {
-               fn = writebarrierfn("typedslicecopy", n->left->type, n->right->type);
-               return mkcall1(fn, n->type, init, typename(n->left->type->type), n->left, n->right);
-       }
-
-       if(runtimecall) {
-               if(n->right->type->etype == TSTRING)
-                       fn = syslook("slicestringcopy", 1);
-               else
-                       fn = syslook("slicecopy", 1);
-               argtype(fn, n->left->type);
-               argtype(fn, n->right->type);
-               return mkcall1(fn, n->type, init,
-                               n->left, n->right,
-                               nodintconst(n->left->type->type->width));
-       }
-       walkexpr(&n->left, init);
-       walkexpr(&n->right, init);
-       nl = temp(n->left->type);
-       nr = temp(n->right->type);
-       l = nil;
-       l = list(l, nod(OAS, nl, n->left));
-       l = list(l, nod(OAS, nr, n->right));
-
-       nfrm = nod(OSPTR, nr, N);
-       nto = nod(OSPTR, nl, N);
-
-       nlen = temp(types[TINT]);
-       // n = len(to)
-       l = list(l, nod(OAS, nlen, nod(OLEN, nl, N)));
-       // if n > len(frm) { n = len(frm) }
-       nif = nod(OIF, N, N);
-       nif->ntest = nod(OGT, nlen, nod(OLEN, nr, N));
-       nif->nbody = list(nif->nbody,
-               nod(OAS, nlen, nod(OLEN, nr, N)));
-       l = list(l, nif);
-
-       // Call memmove.
-       fn = syslook("memmove", 1);
-       argtype(fn, nl->type->type);
-       argtype(fn, nl->type->type);
-       nwid = temp(types[TUINTPTR]);
-       l = list(l, nod(OAS, nwid, conv(nlen, types[TUINTPTR])));
-       nwid = nod(OMUL, nwid, nodintconst(nl->type->type->width));
-       l = list(l, mkcall1(fn, T, init, nto, nfrm, nwid));
-
-       typechecklist(l, Etop);
-       walkstmtlist(l);
-       *init = concat(*init, l);
-       return nlen;
-}
-
-// Generate frontend part for OSLICE[3][ARR|STR]
-// 
-static Node*
-sliceany(Node* n, NodeList **init)
-{
-       int bounded, slice3;
-       Node *src, *lb, *hb, *cb, *bound, *chk, *chk0, *chk1, *chk2;
-       int64 lbv, hbv, cbv, bv, w;
-       Type *bt;
-
-//     print("before sliceany: %+N\n", n);
-
-       src = n->left;
-       lb = n->right->left;
-       slice3 = n->op == OSLICE3 || n->op == OSLICE3ARR;
-       if(slice3) {
-               hb = n->right->right->left;
-               cb = n->right->right->right;
-       } else {
-               hb = n->right->right;
-               cb = N;
-       }
-
-       bounded = n->etype;
-       
-       if(n->op == OSLICESTR)
-               bound = nod(OLEN, src, N);
-       else
-               bound = nod(OCAP, src, N);
-
-       typecheck(&bound, Erv);
-       walkexpr(&bound, init);  // if src is an array, bound will be a const now.
-
-       // static checks if possible
-       bv = 1LL<<50;
-       if(isconst(bound, CTINT)) {
-               if(!smallintconst(bound))
-                       yyerror("array len too large");
-               else
-                       bv = mpgetfix(bound->val.u.xval);
-       }
-
-       if(isconst(cb, CTINT)) {
-               cbv = mpgetfix(cb->val.u.xval);
-               if(cbv < 0 || cbv > bv)
-                       yyerror("slice index out of bounds");
-       }
-       if(isconst(hb, CTINT)) {
-               hbv = mpgetfix(hb->val.u.xval);
-               if(hbv < 0 || hbv > bv)
-                       yyerror("slice index out of bounds");
-       }
-       if(isconst(lb, CTINT)) {
-               lbv = mpgetfix(lb->val.u.xval);
-               if(lbv < 0 || lbv > bv) {
-                       yyerror("slice index out of bounds");
-                       lbv = -1;
-               }
-               if(lbv == 0)
-                       lb = N;
-       }
-
-       // Checking src[lb:hb:cb] or src[lb:hb].
-       // if chk0 || chk1 || chk2 { panicslice() }
-       chk = N;
-       chk0 = N; // cap(src) < cb
-       chk1 = N; // cb < hb for src[lb:hb:cb]; cap(src) < hb for src[lb:hb]
-       chk2 = N; // hb < lb
-
-       // All comparisons are unsigned to avoid testing < 0.
-       bt = types[simtype[TUINT]];
-       if(cb != N && cb->type->width > 4)
-               bt = types[TUINT64];
-       if(hb != N && hb->type->width > 4)
-               bt = types[TUINT64];
-       if(lb != N && lb->type->width > 4)
-               bt = types[TUINT64];
-
-       bound = cheapexpr(conv(bound, bt), init);
-
-       if(cb != N) {
-               cb = cheapexpr(conv(cb, bt), init);
-               if(!bounded)
-                       chk0 = nod(OLT, bound, cb);
-       } else if(slice3) {
-               // When we figure out what this means, implement it.
-               fatal("slice3 with cb == N"); // rejected by parser
-       }
-               
-       if(hb != N) {
-               hb = cheapexpr(conv(hb, bt), init);
-               if(!bounded) {
-                       if(cb != N)
-                               chk1 = nod(OLT, cb, hb);
-                       else
-                               chk1 = nod(OLT, bound, hb);
-               }
-       } else if(slice3) {
-               // When we figure out what this means, implement it.
-               fatal("slice3 with hb == N"); // rejected by parser
-       } else if(n->op == OSLICEARR) {
-               hb = bound;
-       } else {
-               hb = nod(OLEN, src, N);
-               typecheck(&hb, Erv);
-               walkexpr(&hb, init);
-               hb = cheapexpr(conv(hb, bt), init);
-       }
-
-       if(lb != N) {
-               lb = cheapexpr(conv(lb, bt), init);
-               if(!bounded)
-                       chk2 = nod(OLT, hb, lb);  
-       }
-
-       if(chk0 != N || chk1 != N || chk2 != N) {
-               chk = nod(OIF, N, N);
-               chk->nbody = list1(mkcall("panicslice", T, init));
-               chk->likely = -1;
-               if(chk0 != N)
-                       chk->ntest = chk0;
-               if(chk1 != N) {
-                       if(chk->ntest == N)
-                               chk->ntest = chk1;
-                       else
-                               chk->ntest = nod(OOROR, chk->ntest, chk1);
-               }
-               if(chk2 != N) {
-                       if(chk->ntest == N)
-                               chk->ntest = chk2;
-                       else
-                               chk->ntest = nod(OOROR, chk->ntest, chk2);
-               }
-               typecheck(&chk, Etop);
-               walkstmt(&chk);
-               *init = concat(*init, chk->ninit);
-               chk->ninit = nil;
-               *init = list(*init, chk);
-       }
-       
-       // prepare new cap, len and offs for backend cgen_slice
-       // cap = bound [ - lo ]
-       n->right = N;
-       n->list = nil;
-       if(!slice3)
-               cb = bound;
-       if(lb == N)
-               bound = conv(cb, types[simtype[TUINT]]);
-       else
-               bound = nod(OSUB, conv(cb, types[simtype[TUINT]]), conv(lb, types[simtype[TUINT]]));
-       typecheck(&bound, Erv);
-       walkexpr(&bound, init);
-       n->list = list(n->list, bound);
-
-       // len = hi [ - lo]
-       if(lb == N)
-               hb = conv(hb, types[simtype[TUINT]]);
-       else
-               hb = nod(OSUB, conv(hb, types[simtype[TUINT]]), conv(lb, types[simtype[TUINT]]));
-       typecheck(&hb, Erv);
-       walkexpr(&hb, init);
-       n->list = list(n->list, hb);
-
-       // offs = [width *] lo, but omit if zero
-       if(lb != N) {
-               if(n->op == OSLICESTR)
-                       w = 1;
-               else
-                       w = n->type->type->width;
-               lb = conv(lb, types[TUINTPTR]);
-               if(w > 1)
-                       lb = nod(OMUL, nodintconst(w), lb);
-               typecheck(&lb, Erv);
-               walkexpr(&lb, init);
-               n->list = list(n->list, lb);
-       }
-
-//     print("after sliceany: %+N\n", n);
-
-       return n;
-}
-
-static Node*
-eqfor(Type *t, int *needsize)
-{
-       int a;
-       Node *n;
-       Node *ntype;
-       Sym *sym;
-
-       // Should only arrive here with large memory or
-       // a struct/array containing a non-memory field/element.
-       // Small memory is handled inline, and single non-memory
-       // is handled during type check (OCMPSTR etc).
-       a = algtype1(t, nil);
-       if(a != AMEM && a != -1)
-               fatal("eqfor %T", t);
-
-       if(a == AMEM) {
-               n = syslook("memequal", 1);
-               argtype(n, t);
-               argtype(n, t);
-               *needsize = 1;
-               return n;
-       }
-
-       sym = typesymprefix(".eq", t);
-       n = newname(sym);
-       n->class = PFUNC;
-       ntype = nod(OTFUNC, N, N);
-       ntype->list = list(ntype->list, nod(ODCLFIELD, N, typenod(ptrto(t))));
-       ntype->list = list(ntype->list, nod(ODCLFIELD, N, typenod(ptrto(t))));
-       ntype->rlist = list(ntype->rlist, nod(ODCLFIELD, N, typenod(types[TBOOL])));
-       typecheck(&ntype, Etype);
-       n->type = ntype->type;
-       *needsize = 0;
-       return n;
-}
-
-static int
-countfield(Type *t)
-{
-       Type *t1;
-       int n;
-       
-       n = 0;
-       for(t1=t->type; t1!=T; t1=t1->down)
-               n++;
-       return n;
-}
-
-static void
-walkcompare(Node **np, NodeList **init)
-{
-       Node *n, *l, *r, *call, *a, *li, *ri, *expr, *cmpl, *cmpr;
-       Node *x, *ok;
-       int andor, i, needsize;
-       Type *t, *t1;
-       
-       n = *np;
-
-       // Given interface value l and concrete value r, rewrite
-       //   l == r
-       // to
-       //   x, ok := l.(type(r)); ok && x == r
-       // Handle != similarly.
-       // This avoids the allocation that would be required
-       // to convert r to l for comparison.
-       l = N;
-       r = N;
-       if(isinter(n->left->type) && !isinter(n->right->type)) {
-               l = n->left;
-               r = n->right;
-       } else if(!isinter(n->left->type) && isinter(n->right->type)) {
-               l = n->right;
-               r = n->left;
-       }
-       if(l != N) {
-               x = temp(r->type);
-               ok = temp(types[TBOOL]);
-
-               // l.(type(r))
-               a = nod(ODOTTYPE, l, N);
-               a->type = r->type;
-
-               // x, ok := l.(type(r))
-               expr = nod(OAS2, N, N);
-               expr->list = list1(x);
-               expr->list = list(expr->list, ok);
-               expr->rlist = list1(a);
-               typecheck(&expr, Etop);
-               walkexpr(&expr, init);
-
-               if(n->op == OEQ)
-                       r = nod(OANDAND, ok, nod(OEQ, x, r));
-               else
-                       r = nod(OOROR, nod(ONOT, ok, N), nod(ONE, x, r));
-               *init = list(*init, expr);
-               goto ret;
-       }
-       
-       // Must be comparison of array or struct.
-       // Otherwise back end handles it.
-       t = n->left->type;
-       switch(t->etype) {
-       default:
-               return;
-       case TARRAY:
-               if(isslice(t))
-                       return;
-               break;
-       case TSTRUCT:
-               break;
-       }
-       
-       cmpl = n->left;
-       while(cmpl != N && cmpl->op == OCONVNOP)
-               cmpl = cmpl->left;
-       cmpr = n->right;
-       while(cmpr != N && cmpr->op == OCONVNOP)
-               cmpr = cmpr->left;
-       
-       if(!islvalue(cmpl) || !islvalue(cmpr)) {
-               fatal("arguments of comparison must be lvalues - %N %N", cmpl, cmpr);
-       }
-
-       l = temp(ptrto(t));
-       a = nod(OAS, l, nod(OADDR, cmpl, N));
-       a->right->etype = 1;  // addr does not escape
-       typecheck(&a, Etop);
-       *init = list(*init, a);
-
-       r = temp(ptrto(t));
-       a = nod(OAS, r, nod(OADDR, cmpr, N));
-       a->right->etype = 1;  // addr does not escape
-       typecheck(&a, Etop);
-       *init = list(*init, a);
-
-       expr = N;
-       andor = OANDAND;
-       if(n->op == ONE)
-               andor = OOROR;
-
-       if(t->etype == TARRAY &&
-               t->bound <= 4 &&
-               issimple[t->type->etype]) {
-               // Four or fewer elements of a basic type.
-               // Unroll comparisons.
-               for(i=0; i<t->bound; i++) {
-                       li = nod(OINDEX, l, nodintconst(i));
-                       ri = nod(OINDEX, r, nodintconst(i));
-                       a = nod(n->op, li, ri);
-                       if(expr == N)
-                               expr = a;
-                       else
-                               expr = nod(andor, expr, a);
-               }
-               if(expr == N)
-                       expr = nodbool(n->op == OEQ);
-               r = expr;
-               goto ret;
-       }
-
-       if(t->etype == TSTRUCT && countfield(t) <= 4) {
-               // Struct of four or fewer fields.
-               // Inline comparisons.
-               for(t1=t->type; t1; t1=t1->down) {
-                       if(isblanksym(t1->sym))
-                               continue;
-                       li = nod(OXDOT, l, newname(t1->sym));
-                       ri = nod(OXDOT, r, newname(t1->sym));
-                       a = nod(n->op, li, ri);
-                       if(expr == N)
-                               expr = a;
-                       else
-                               expr = nod(andor, expr, a);
-               }
-               if(expr == N)
-                       expr = nodbool(n->op == OEQ);
-               r = expr;
-               goto ret;
-       }
-
-       // Chose not to inline.  Call equality function directly.
-       call = nod(OCALL, eqfor(t, &needsize), N);
-       call->list = list(call->list, l);
-       call->list = list(call->list, r);
-       if(needsize)
-               call->list = list(call->list, nodintconst(t->width));
-       r = call;
-       if(n->op != OEQ)
-               r = nod(ONOT, r, N);
-       goto ret;
-
-ret:
-       typecheck(&r, Erv);
-       walkexpr(&r, init);
-       if(r->type != n->type) {
-               r = nod(OCONVNOP, r, N);
-               r->type = n->type;
-               r->typecheck = 1;
-       }
-       *np = r;
-       return;
-}
-
-static int
-samecheap(Node *a, Node *b)
-{
-       Node *ar, *br;
-       while(a != N && b != N && a->op == b->op) {
-               switch(a->op) {
-               default:
-                       return 0;
-               case ONAME:
-                       return a == b;
-               case ODOT:
-               case ODOTPTR:
-                       ar = a->right;
-                       br = b->right;
-                       if(ar->op != ONAME || br->op != ONAME || ar->sym != br->sym)
-                               return 0;
-                       break;
-               case OINDEX:
-                       ar = a->right;
-                       br = b->right;
-                       if(!isconst(ar, CTINT) || !isconst(br, CTINT) || mpcmpfixfix(ar->val.u.xval, br->val.u.xval) != 0)
-                               return 0;
-                       break;
-               }
-               a = a->left;
-               b = b->left;
-       }
-       return 0;
-}
-
-static void
-walkrotate(Node **np)
-{
-       int w, sl, sr, s;
-       Node *l, *r;
-       Node *n;
-
-       if(thearch.thechar == '9')
-               return;
-       
-       n = *np;
-
-       // Want << | >> or >> | << or << ^ >> or >> ^ << on unsigned value.
-       l = n->left;
-       r = n->right;
-       if((n->op != OOR && n->op != OXOR) ||
-          (l->op != OLSH && l->op != ORSH) ||
-          (r->op != OLSH && r->op != ORSH) ||
-          n->type == T || issigned[n->type->etype] ||
-          l->op == r->op) {
-               return;
-       }
-
-       // Want same, side effect-free expression on lhs of both shifts.
-       if(!samecheap(l->left, r->left))
-               return;
-       
-       // Constants adding to width?
-       w = l->type->width * 8;
-       if(smallintconst(l->right) && smallintconst(r->right)) {
-               if((sl=mpgetfix(l->right->val.u.xval)) >= 0 && (sr=mpgetfix(r->right->val.u.xval)) >= 0 && sl+sr == w)
-                       goto yes;
-               return;
-       }
-       
-       // TODO: Could allow s and 32-s if s is bounded (maybe s&31 and 32-s&31).
-       return;
-       
-yes:
-       // Rewrite left shift half to left rotate.
-       if(l->op == OLSH)
-               n = l;
-       else
-               n = r;
-       n->op = OLROT;
-       
-       // Remove rotate 0 and rotate w.
-       s = mpgetfix(n->right->val.u.xval);
-       if(s == 0 || s == w)
-               n = n->left;
-
-       *np = n;
-       return;
-}
-
-/*
- * walkmul rewrites integer multiplication by powers of two as shifts.
- */
-static void
-walkmul(Node **np, NodeList **init)
-{
-       Node *n, *nl, *nr;
-       int pow, neg, w;
-       
-       n = *np;
-       if(!isint[n->type->etype])
-               return;
-
-       if(n->right->op == OLITERAL) {
-               nl = n->left;
-               nr = n->right;
-       } else if(n->left->op == OLITERAL) {
-               nl = n->right;
-               nr = n->left;
-       } else
-               return;
-
-       neg = 0;
-
-       // x*0 is 0 (and side effects of x).
-       if(mpgetfix(nr->val.u.xval) == 0) {
-               cheapexpr(nl, init);
-               nodconst(n, n->type, 0);
-               goto ret;
-       }
-
-       // nr is a constant.
-       pow = powtwo(nr);
-       if(pow < 0)
-               return;
-       if(pow >= 1000) {
-               // negative power of 2, like -16
-               neg = 1;
-               pow -= 1000;
-       }
-
-       w = nl->type->width*8;
-       if(pow+1 >= w)// too big, shouldn't happen
-               return;
-
-       nl = cheapexpr(nl, init);
-
-       if(pow == 0) {
-               // x*1 is x
-               n = nl;
-               goto ret;
-       }
-       
-       n = nod(OLSH, nl, nodintconst(pow));
-
-ret:
-       if(neg)
-               n = nod(OMINUS, n, N);
-
-       typecheck(&n, Erv);
-       walkexpr(&n, init);
-       *np = n;
-}
-
-/*
- * walkdiv rewrites division by a constant as less expensive
- * operations.
- */
-static void
-walkdiv(Node **np, NodeList **init)
-{
-       Node *n, *nl, *nr, *nc;
-       Node *n1, *n2, *n3, *n4;
-       int pow; // if >= 0, nr is 1<<pow
-       int s; // 1 if nr is negative.
-       int w;
-       Type *twide;
-       Magic m;
-
-       // TODO(minux)
-       if(thearch.thechar == '9')
-               return;
-
-       n = *np;
-       if(n->right->op != OLITERAL)
-               return;
-       // nr is a constant.
-       nl = cheapexpr(n->left, init);
-       nr = n->right;
-
-       // special cases of mod/div
-       // by a constant
-       w = nl->type->width*8;
-       s = 0;
-       pow = powtwo(nr);
-       if(pow >= 1000) {
-               // negative power of 2
-               s = 1;
-               pow -= 1000;
-       }
-
-       if(pow+1 >= w) {
-               // divisor too large.
-               return;
-       }
-       if(pow < 0) {
-               goto divbymul;
-       }
-
-       switch(pow) {
-       case 0:
-               if(n->op == OMOD) {
-                       // nl % 1 is zero.
-                       nodconst(n, n->type, 0);
-               } else if(s) {
-                       // divide by -1
-                       n->op = OMINUS;
-                       n->right = N;
-               } else {
-                       // divide by 1
-                       n = nl;
-               }
-               break;
-       default:
-               if(issigned[n->type->etype]) {
-                       if(n->op == OMOD) {
-                               // signed modulo 2^pow is like ANDing
-                               // with the last pow bits, but if nl < 0,
-                               // nl & (2^pow-1) is (nl+1)%2^pow - 1.
-                               nc = nod(OXXX, N, N);
-                               nodconst(nc, types[simtype[TUINT]], w-1);
-                               n1 = nod(ORSH, nl, nc); // n1 = -1 iff nl < 0.
-                               if(pow == 1) {
-                                       typecheck(&n1, Erv);
-                                       n1 = cheapexpr(n1, init);
-                                       // n = (nl+ε)&1 -ε where Îµ=1 iff nl<0.
-                                       n2 = nod(OSUB, nl, n1);
-                                       nc = nod(OXXX, N, N);
-                                       nodconst(nc, nl->type, 1);
-                                       n3 = nod(OAND, n2, nc);
-                                       n = nod(OADD, n3, n1);
-                               } else {
-                                       // n = (nl+ε)&(nr-1) - Îµ where Îµ=2^pow-1 iff nl<0.
-                                       nc = nod(OXXX, N, N);
-                                       nodconst(nc, nl->type, (1LL<<pow)-1);
-                                       n2 = nod(OAND, n1, nc); // n2 = 2^pow-1 iff nl<0.
-                                       typecheck(&n2, Erv);
-                                       n2 = cheapexpr(n2, init);
-
-                                       n3 = nod(OADD, nl, n2);
-                                       n4 = nod(OAND, n3, nc);
-                                       n = nod(OSUB, n4, n2);
-                               }
-                               break;
-                       } else {
-                               // arithmetic right shift does not give the correct rounding.
-                               // if nl >= 0, nl >> n == nl / nr
-                               // if nl < 0, we want to add 2^n-1 first.
-                               nc = nod(OXXX, N, N);
-                               nodconst(nc, types[simtype[TUINT]], w-1);
-                               n1 = nod(ORSH, nl, nc); // n1 = -1 iff nl < 0.
-                               if(pow == 1) {
-                                       // nl+1 is nl-(-1)
-                                       n->left = nod(OSUB, nl, n1);
-                               } else {
-                                       // Do a logical right right on -1 to keep pow bits.
-                                       nc = nod(OXXX, N, N);
-                                       nodconst(nc, types[simtype[TUINT]], w-pow);
-                                       n2 = nod(ORSH, conv(n1, tounsigned(nl->type)), nc);
-                                       n->left = nod(OADD, nl, conv(n2, nl->type));
-                               }
-                               // n = (nl + 2^pow-1) >> pow
-                               n->op = ORSH;
-                               nc = nod(OXXX, N, N);
-                               nodconst(nc, types[simtype[TUINT]], pow);
-                               n->right = nc;
-                               n->typecheck = 0;
-                       }
-                       if(s)
-                               n = nod(OMINUS, n, N);
-                       break;
-               }
-               nc = nod(OXXX, N, N);
-               if(n->op == OMOD) {
-                       // n = nl & (nr-1)
-                       n->op = OAND;
-                       nodconst(nc, nl->type, mpgetfix(nr->val.u.xval)-1);
-               } else {
-                       // n = nl >> pow
-                       n->op = ORSH;
-                       nodconst(nc, types[simtype[TUINT]], pow);
-               }
-               n->typecheck = 0;
-               n->right = nc;
-               break;
-       }
-       goto ret;
-
-divbymul:
-       // try to do division by multiply by (2^w)/d
-       // see hacker's delight chapter 10
-       // TODO: support 64-bit magic multiply here.
-       m.w = w;
-       if(issigned[nl->type->etype]) {
-               m.sd = mpgetfix(nr->val.u.xval);
-               smagic(&m);
-       } else {
-               m.ud = mpgetfix(nr->val.u.xval);
-               umagic(&m);
-       }
-       if(m.bad)
-               return;
-
-       // We have a quick division method so use it
-       // for modulo too.
-       if(n->op == OMOD)
-               goto longmod;
-
-       switch(simtype[nl->type->etype]) {
-       default:
-               return;
-
-       case TUINT8:
-       case TUINT16:
-       case TUINT32:
-               // n1 = nl * magic >> w (HMUL)
-               nc = nod(OXXX, N, N);
-               nodconst(nc, nl->type, m.um);
-               n1 = nod(OMUL, nl, nc);
-               typecheck(&n1, Erv);
-               n1->op = OHMUL;
-               if(m.ua) {
-                       // Select a Go type with (at least) twice the width.
-                       switch(simtype[nl->type->etype]) {
-                       default:
-                               return;
-                       case TUINT8:
-                       case TUINT16:
-                               twide = types[TUINT32];
-                               break;
-                       case TUINT32:
-                               twide = types[TUINT64];
-                               break;
-                       case TINT8:
-                       case TINT16:
-                               twide = types[TINT32];
-                               break;
-                       case TINT32:
-                               twide = types[TINT64];
-                               break;
-                       }
-
-                       // add numerator (might overflow).
-                       // n2 = (n1 + nl)
-                       n2 = nod(OADD, conv(n1, twide), conv(nl, twide));
-
-                       // shift by m.s
-                       nc = nod(OXXX, N, N);
-                       nodconst(nc, types[TUINT], m.s);
-                       n = conv(nod(ORSH, n2, nc), nl->type);
-               } else {
-                       // n = n1 >> m.s
-                       nc = nod(OXXX, N, N);
-                       nodconst(nc, types[TUINT], m.s);
-                       n = nod(ORSH, n1, nc);
-               }
-               break;
-
-       case TINT8:
-       case TINT16:
-       case TINT32:
-               // n1 = nl * magic >> w
-               nc = nod(OXXX, N, N);
-               nodconst(nc, nl->type, m.sm);
-               n1 = nod(OMUL, nl, nc);
-               typecheck(&n1, Erv);
-               n1->op = OHMUL;
-               if(m.sm < 0) {
-                       // add the numerator.
-                       n1 = nod(OADD, n1, nl);
-               }
-               // shift by m.s
-               nc = nod(OXXX, N, N);
-               nodconst(nc, types[TUINT], m.s);
-               n2 = conv(nod(ORSH, n1, nc), nl->type);
-               // add 1 iff n1 is negative.
-               nc = nod(OXXX, N, N);
-               nodconst(nc, types[TUINT], w-1);
-               n3 = nod(ORSH, nl, nc); // n4 = -1 iff n1 is negative.
-               n = nod(OSUB, n2, n3);
-               // apply sign.
-               if(m.sd < 0)
-                       n = nod(OMINUS, n, N);
-               break;
-       }
-       goto ret;
-
-longmod:
-       // rewrite as A%B = A - (A/B*B).
-       n1 = nod(ODIV, nl, nr);
-       n2 = nod(OMUL, n1, nr);
-       n = nod(OSUB, nl, n2);
-       goto ret;
-
-ret:
-       typecheck(&n, Erv);
-       walkexpr(&n, init);
-       *np = n;
-}
-
-// return 1 if integer n must be in range [0, max), 0 otherwise
-static int
-bounded(Node *n, int64 max)
-{
-       int64 v;
-       int32 bits;
-       int sign;
-
-       if(n->type == T || !isint[n->type->etype])
-               return 0;
-
-       sign = issigned[n->type->etype];
-       bits = 8*n->type->width;
-
-       if(smallintconst(n)) {
-               v = mpgetfix(n->val.u.xval);
-               return 0 <= v && v < max;
-       }
-
-       switch(n->op) {
-       case OAND:
-               v = -1;
-               if(smallintconst(n->left)) {
-                       v = mpgetfix(n->left->val.u.xval);
-               } else if(smallintconst(n->right)) {
-                       v = mpgetfix(n->right->val.u.xval);
-               }
-               if(0 <= v && v < max)
-                       return 1;
-               break;
-
-       case OMOD:
-               if(!sign && smallintconst(n->right)) {
-                       v = mpgetfix(n->right->val.u.xval);
-                       if(0 <= v && v <= max)
-                               return 1;
-               }
-               break;
-       
-       case ODIV:
-               if(!sign && smallintconst(n->right)) {
-                       v = mpgetfix(n->right->val.u.xval);
-                       while(bits > 0 && v >= 2) {
-                               bits--;
-                               v >>= 1;
-                       }
-               }
-               break;
-       
-       case ORSH:
-               if(!sign && smallintconst(n->right)) {
-                       v = mpgetfix(n->right->val.u.xval);
-                       if(v > bits)
-                               return 1;
-                       bits -= v;
-               }
-               break;
-       }
-       
-       if(!sign && bits <= 62 && (1LL<<bits) <= max)
-               return 1;
-       
-       return 0;
-}
-
-void
-usefield(Node *n)
-{
-       Type *field, *l;
-
-       if(!fieldtrack_enabled)
-               return;
-
-       switch(n->op) {
-       default:
-               fatal("usefield %O", n->op);
-       case ODOT:
-       case ODOTPTR:
-               break;
-       }
-       
-       field = n->paramfld;
-       if(field == T)
-               fatal("usefield %T %S without paramfld", n->left->type, n->right->sym);
-       if(field->note == nil || strstr(field->note->s, "go:\"track\"") == nil)
-               return;
-
-       // dedup on list
-       if(field->lastfn == curfn)
-               return;
-       field->lastfn = curfn;
-       field->outer = n->left->type;
-       if(isptr[field->outer->etype])
-               field->outer = field->outer->type;
-       if(field->outer->sym == S)
-               yyerror("tracked field must be in named struct type");
-       if(!exportname(field->sym->name))
-               yyerror("tracked field must be exported (upper case)");
-
-       l = typ(0);
-       l->type = field;
-       l->down = curfn->paramfld;
-       curfn->paramfld = l;
-}
-
-static int
-candiscardlist(NodeList *l)
-{
-       for(; l; l=l->next)
-               if(!candiscard(l->n))
-                       return 0;
-       return 1;
-}
-
-int
-candiscard(Node *n)
-{
-       if(n == N)
-               return 1;
-       
-       switch(n->op) {
-       default:
-               return 0;
-
-       case ONAME:
-       case ONONAME:
-       case OTYPE:
-       case OPACK:
-       case OLITERAL:
-       case OADD:
-       case OSUB:
-       case OOR:
-       case OXOR:
-       case OADDSTR:
-       case OADDR:
-       case OANDAND:
-       case OARRAYBYTESTR:
-       case OARRAYRUNESTR:
-       case OSTRARRAYBYTE:
-       case OSTRARRAYRUNE:
-       case OCAP:
-       case OCMPIFACE:
-       case OCMPSTR:
-       case OCOMPLIT:
-       case OMAPLIT:
-       case OSTRUCTLIT:
-       case OARRAYLIT:
-       case OPTRLIT:
-       case OCONV:
-       case OCONVIFACE:
-       case OCONVNOP:
-       case ODOT:
-       case OEQ:
-       case ONE:
-       case OLT:
-       case OLE:
-       case OGT:
-       case OGE:
-       case OKEY:
-       case OLEN:
-       case OMUL:
-       case OLSH:
-       case ORSH:
-       case OAND:
-       case OANDNOT:
-       case ONEW:
-       case ONOT:
-       case OCOM:
-       case OPLUS:
-       case OMINUS:
-       case OOROR:
-       case OPAREN:
-       case ORUNESTR:
-       case OREAL:
-       case OIMAG:
-       case OCOMPLEX:
-               // Discardable as long as the subpieces are.
-               break;
-
-       case ODIV:
-       case OMOD:
-               // Discardable as long as we know it's not division by zero.
-               if(isconst(n->right, CTINT) && mpcmpfixc(n->right->val.u.xval, 0) != 0)
-                       break;
-               if(isconst(n->right, CTFLT) && mpcmpfltc(n->right->val.u.fval, 0) != 0)
-                       break;
-               return 0;
-
-       case OMAKECHAN:
-       case OMAKEMAP:
-               // Discardable as long as we know it won't fail because of a bad size.
-               if(isconst(n->left, CTINT) && mpcmpfixc(n->left->val.u.xval, 0) == 0)
-                       break;
-               return 0;
-       
-       case OMAKESLICE:
-               // Difficult to tell what sizes are okay.
-               return 0;               
-       }
-       
-       if(!candiscard(n->left) ||
-          !candiscard(n->right) ||
-          !candiscard(n->ntest) ||
-          !candiscard(n->nincr) ||
-          !candiscardlist(n->ninit) ||
-          !candiscardlist(n->nbody) ||
-          !candiscardlist(n->nelse) ||
-          !candiscardlist(n->list) ||
-          !candiscardlist(n->rlist)) {
-               return 0;
-       }
-       
-       return 1;
-}
-
-// rewrite
-//     print(x, y, z)
-// into
-//     func(a1, a2, a3) {
-//             print(a1, a2, a3)
-//     }(x, y, z)
-// and same for println.
-static void
-walkprintfunc(Node **np, NodeList **init)
-{
-       Node *n;
-       Node *a, *fn, *t, *oldfn;
-       NodeList *l, *printargs;
-       int num;
-       char buf[100];
-       static int prgen;
-       
-       n = *np;
-
-       if(n->ninit != nil) {
-               walkstmtlist(n->ninit);
-               *init = concat(*init, n->ninit);
-               n->ninit = nil;
-       }
-
-       t = nod(OTFUNC, N, N);
-       num = 0;
-       printargs = nil;
-       for(l=n->list; l != nil; l=l->next) {
-               snprint(buf, sizeof buf, "a%d", num++);
-               a = nod(ODCLFIELD, newname(lookup(buf)), typenod(l->n->type));
-               t->list = list(t->list, a);
-               printargs = list(printargs, a->left);
-       }
-
-       fn = nod(ODCLFUNC, N, N);
-       snprint(buf, sizeof buf, "print·%d", ++prgen);
-       fn->nname = newname(lookup(buf));
-       fn->nname->defn = fn;
-       fn->nname->ntype = t;
-       declare(fn->nname, PFUNC);
-
-       oldfn = curfn;
-       curfn = nil;
-       funchdr(fn);
-       
-       a = nod(n->op, N, N);
-       a->list = printargs;
-       typecheck(&a, Etop);
-       walkstmt(&a);
-       
-       fn->nbody = list1(a);
-
-       funcbody(fn);
-       
-       typecheck(&fn, Etop);
-       typechecklist(fn->nbody, Etop);
-       xtop = list(xtop, fn);
-       curfn = oldfn;
-
-       a = nod(OCALL, N, N);
-       a->left = fn->nname;
-       a->list = n->list;
-       typecheck(&a, Etop);
-       walkexpr(&a, init);
-       *np = a;
-}
diff --git a/src/cmd/gc/y.tab.c b/src/cmd/gc/y.tab.c
deleted file mode 100644 (file)
index d45623a..0000000
+++ /dev/null
@@ -1,5134 +0,0 @@
-/* A Bison parser, made by GNU Bison 2.3.  */
-
-/* Skeleton implementation for Bison's Yacc-like parsers in C
-
-   Copyright (C) 1984, 1989, 1990, 2000, 2001, 2002, 2003, 2004, 2005, 2006
-   Free Software Foundation, Inc.
-
-   This program is free software; you can redistribute it and/or modify
-   it under the terms of the GNU General Public License as published by
-   the Free Software Foundation; either version 2, or (at your option)
-   any later version.
-
-   This program is distributed in the hope that it will be useful,
-   but WITHOUT ANY WARRANTY; without even the implied warranty of
-   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-   GNU General Public License for more details.
-
-   You should have received a copy of the GNU General Public License
-   along with this program; if not, write to the Free Software
-   Foundation, Inc., 51 Franklin Street, Fifth Floor,
-   Boston, MA 02110-1301, USA.  */
-
-/* As a special exception, you may create a larger work that contains
-   part or all of the Bison parser skeleton and distribute that work
-   under terms of your choice, so long as that work isn't itself a
-   parser generator using the skeleton or a modified version thereof
-   as a parser skeleton.  Alternatively, if you modify or redistribute
-   the parser skeleton itself, you may (at your option) remove this
-   special exception, which will cause the skeleton and the resulting
-   Bison output files to be licensed under the GNU General Public
-   License without this special exception.
-
-   This special exception was added by the Free Software Foundation in
-   version 2.2 of Bison.  */
-
-/* C LALR(1) parser skeleton written by Richard Stallman, by
-   simplifying the original so-called "semantic" parser.  */
-
-/* All symbols defined below should begin with yy or YY, to avoid
-   infringing on user name space.  This should be done even for local
-   variables, as they might otherwise be expanded by user macros.
-   There are some unavoidable exceptions within include files to
-   define necessary library symbols; they are noted "INFRINGES ON
-   USER NAME SPACE" below.  */
-
-/* Identify Bison output.  */
-#define YYBISON 1
-
-/* Bison version.  */
-#define YYBISON_VERSION "2.3"
-
-/* Skeleton name.  */
-#define YYSKELETON_NAME "yacc.c"
-
-/* Pure parsers.  */
-#define YYPURE 0
-
-/* Using locations.  */
-#define YYLSP_NEEDED 0
-
-
-
-/* Tokens.  */
-#ifndef YYTOKENTYPE
-# define YYTOKENTYPE
-   /* Put the tokens into the symbol table, so that GDB and other debuggers
-      know about them.  */
-   enum yytokentype {
-     LLITERAL = 258,
-     LASOP = 259,
-     LCOLAS = 260,
-     LBREAK = 261,
-     LCASE = 262,
-     LCHAN = 263,
-     LCONST = 264,
-     LCONTINUE = 265,
-     LDDD = 266,
-     LDEFAULT = 267,
-     LDEFER = 268,
-     LELSE = 269,
-     LFALL = 270,
-     LFOR = 271,
-     LFUNC = 272,
-     LGO = 273,
-     LGOTO = 274,
-     LIF = 275,
-     LIMPORT = 276,
-     LINTERFACE = 277,
-     LMAP = 278,
-     LNAME = 279,
-     LPACKAGE = 280,
-     LRANGE = 281,
-     LRETURN = 282,
-     LSELECT = 283,
-     LSTRUCT = 284,
-     LSWITCH = 285,
-     LTYPE = 286,
-     LVAR = 287,
-     LANDAND = 288,
-     LANDNOT = 289,
-     LBODY = 290,
-     LCOMM = 291,
-     LDEC = 292,
-     LEQ = 293,
-     LGE = 294,
-     LGT = 295,
-     LIGNORE = 296,
-     LINC = 297,
-     LLE = 298,
-     LLSH = 299,
-     LLT = 300,
-     LNE = 301,
-     LOROR = 302,
-     LRSH = 303,
-     NotPackage = 304,
-     NotParen = 305,
-     PreferToRightParen = 306
-   };
-#endif
-/* Tokens.  */
-#define LLITERAL 258
-#define LASOP 259
-#define LCOLAS 260
-#define LBREAK 261
-#define LCASE 262
-#define LCHAN 263
-#define LCONST 264
-#define LCONTINUE 265
-#define LDDD 266
-#define LDEFAULT 267
-#define LDEFER 268
-#define LELSE 269
-#define LFALL 270
-#define LFOR 271
-#define LFUNC 272
-#define LGO 273
-#define LGOTO 274
-#define LIF 275
-#define LIMPORT 276
-#define LINTERFACE 277
-#define LMAP 278
-#define LNAME 279
-#define LPACKAGE 280
-#define LRANGE 281
-#define LRETURN 282
-#define LSELECT 283
-#define LSTRUCT 284
-#define LSWITCH 285
-#define LTYPE 286
-#define LVAR 287
-#define LANDAND 288
-#define LANDNOT 289
-#define LBODY 290
-#define LCOMM 291
-#define LDEC 292
-#define LEQ 293
-#define LGE 294
-#define LGT 295
-#define LIGNORE 296
-#define LINC 297
-#define LLE 298
-#define LLSH 299
-#define LLT 300
-#define LNE 301
-#define LOROR 302
-#define LRSH 303
-#define NotPackage 304
-#define NotParen 305
-#define PreferToRightParen 306
-
-
-
-
-/* Copy the first part of user declarations.  */
-#line 20 "go.y"
-
-#include <u.h>
-#include <stdio.h>     /* if we don't, bison will, and go.h re-#defines getc */
-#include <libc.h>
-#include "go.h"
-
-static void fixlbrace(int);
-
-
-/* Enabling traces.  */
-#ifndef YYDEBUG
-# define YYDEBUG 0
-#endif
-
-/* Enabling verbose error messages.  */
-#ifdef YYERROR_VERBOSE
-# undef YYERROR_VERBOSE
-# define YYERROR_VERBOSE 1
-#else
-# define YYERROR_VERBOSE 1
-#endif
-
-/* Enabling the token table.  */
-#ifndef YYTOKEN_TABLE
-# define YYTOKEN_TABLE 0
-#endif
-
-#if ! defined YYSTYPE && ! defined YYSTYPE_IS_DECLARED
-typedef union YYSTYPE
-#line 28 "go.y"
-{
-       Node*           node;
-       NodeList*               list;
-       Type*           type;
-       Sym*            sym;
-       struct  Val     val;
-       int             i;
-}
-/* Line 193 of yacc.c.  */
-#line 216 "y.tab.c"
-       YYSTYPE;
-# define yystype YYSTYPE /* obsolescent; will be withdrawn */
-# define YYSTYPE_IS_DECLARED 1
-# define YYSTYPE_IS_TRIVIAL 1
-#endif
-
-
-
-/* Copy the second part of user declarations.  */
-
-
-/* Line 216 of yacc.c.  */
-#line 229 "y.tab.c"
-
-#ifdef short
-# undef short
-#endif
-
-#ifdef YYTYPE_UINT8
-typedef YYTYPE_UINT8 yytype_uint8;
-#else
-typedef unsigned char yytype_uint8;
-#endif
-
-#ifdef YYTYPE_INT8
-typedef YYTYPE_INT8 yytype_int8;
-#elif (defined __STDC__ || defined __C99__FUNC__ \
-     || defined __cplusplus || defined _MSC_VER)
-typedef signed char yytype_int8;
-#else
-typedef short int yytype_int8;
-#endif
-
-#ifdef YYTYPE_UINT16
-typedef YYTYPE_UINT16 yytype_uint16;
-#else
-typedef unsigned short int yytype_uint16;
-#endif
-
-#ifdef YYTYPE_INT16
-typedef YYTYPE_INT16 yytype_int16;
-#else
-typedef short int yytype_int16;
-#endif
-
-#ifndef YYSIZE_T
-# ifdef __SIZE_TYPE__
-#  define YYSIZE_T __SIZE_TYPE__
-# elif defined size_t
-#  define YYSIZE_T size_t
-# elif ! defined YYSIZE_T && (defined __STDC__ || defined __C99__FUNC__ \
-     || defined __cplusplus || defined _MSC_VER)
-#  include <stddef.h> /* INFRINGES ON USER NAME SPACE */
-#  define YYSIZE_T size_t
-# else
-#  define YYSIZE_T unsigned int
-# endif
-#endif
-
-#define YYSIZE_MAXIMUM ((YYSIZE_T) -1)
-
-#ifndef YY_
-# if defined YYENABLE_NLS && YYENABLE_NLS
-#  if ENABLE_NLS
-#   include <libintl.h> /* INFRINGES ON USER NAME SPACE */
-#   define YY_(msgid) dgettext ("bison-runtime", msgid)
-#  endif
-# endif
-# ifndef YY_
-#  define YY_(msgid) msgid
-# endif
-#endif
-
-/* Suppress unused-variable warnings by "using" E.  */
-#if ! defined lint || defined __GNUC__
-# define YYUSE(e) ((void) (e))
-#else
-# define YYUSE(e) /* empty */
-#endif
-
-/* Identity function, used to suppress warnings about constant conditions.  */
-#ifndef lint
-# define YYID(n) (n)
-#else
-#if (defined __STDC__ || defined __C99__FUNC__ \
-     || defined __cplusplus || defined _MSC_VER)
-static int
-YYID (int i)
-#else
-static int
-YYID (i)
-    int i;
-#endif
-{
-  return i;
-}
-#endif
-
-#if ! defined yyoverflow || YYERROR_VERBOSE
-
-/* The parser invokes alloca or malloc; define the necessary symbols.  */
-
-# ifdef YYSTACK_USE_ALLOCA
-#  if YYSTACK_USE_ALLOCA
-#   ifdef __GNUC__
-#    define YYSTACK_ALLOC __builtin_alloca
-#   elif defined __BUILTIN_VA_ARG_INCR
-#    include <alloca.h> /* INFRINGES ON USER NAME SPACE */
-#   elif defined _AIX
-#    define YYSTACK_ALLOC __alloca
-#   elif defined _MSC_VER
-#    include <malloc.h> /* INFRINGES ON USER NAME SPACE */
-#    define alloca _alloca
-#   else
-#    define YYSTACK_ALLOC alloca
-#    if ! defined _ALLOCA_H && ! defined _STDLIB_H && (defined __STDC__ || defined __C99__FUNC__ \
-     || defined __cplusplus || defined _MSC_VER)
-#     include <stdlib.h> /* INFRINGES ON USER NAME SPACE */
-#     ifndef _STDLIB_H
-#      define _STDLIB_H 1
-#     endif
-#    endif
-#   endif
-#  endif
-# endif
-
-# ifdef YYSTACK_ALLOC
-   /* Pacify GCC's `empty if-body' warning.  */
-#  define YYSTACK_FREE(Ptr) do { /* empty */; } while (YYID (0))
-#  ifndef YYSTACK_ALLOC_MAXIMUM
-    /* The OS might guarantee only one guard page at the bottom of the stack,
-       and a page size can be as small as 4096 bytes.  So we cannot safely
-       invoke alloca (N) if N exceeds 4096.  Use a slightly smaller number
-       to allow for a few compiler-allocated temporary stack slots.  */
-#   define YYSTACK_ALLOC_MAXIMUM 4032 /* reasonable circa 2006 */
-#  endif
-# else
-#  define YYSTACK_ALLOC YYMALLOC
-#  define YYSTACK_FREE YYFREE
-#  ifndef YYSTACK_ALLOC_MAXIMUM
-#   define YYSTACK_ALLOC_MAXIMUM YYSIZE_MAXIMUM
-#  endif
-#  if (defined __cplusplus && ! defined _STDLIB_H \
-       && ! ((defined YYMALLOC || defined malloc) \
-            && (defined YYFREE || defined free)))
-#   include <stdlib.h> /* INFRINGES ON USER NAME SPACE */
-#   ifndef _STDLIB_H
-#    define _STDLIB_H 1
-#   endif
-#  endif
-#  ifndef YYMALLOC
-#   define YYMALLOC malloc
-#   if ! defined malloc && ! defined _STDLIB_H && (defined __STDC__ || defined __C99__FUNC__ \
-     || defined __cplusplus || defined _MSC_VER)
-void *malloc (YYSIZE_T); /* INFRINGES ON USER NAME SPACE */
-#   endif
-#  endif
-#  ifndef YYFREE
-#   define YYFREE free
-#   if ! defined free && ! defined _STDLIB_H && (defined __STDC__ || defined __C99__FUNC__ \
-     || defined __cplusplus || defined _MSC_VER)
-void free (void *); /* INFRINGES ON USER NAME SPACE */
-#   endif
-#  endif
-# endif
-#endif /* ! defined yyoverflow || YYERROR_VERBOSE */
-
-
-#if (! defined yyoverflow \
-     && (! defined __cplusplus \
-        || (defined YYSTYPE_IS_TRIVIAL && YYSTYPE_IS_TRIVIAL)))
-
-/* A type that is properly aligned for any stack member.  */
-union yyalloc
-{
-  yytype_int16 yyss;
-  YYSTYPE yyvs;
-  };
-
-/* The size of the maximum gap between one aligned stack and the next.  */
-# define YYSTACK_GAP_MAXIMUM (sizeof (union yyalloc) - 1)
-
-/* The size of an array large to enough to hold all stacks, each with
-   N elements.  */
-# define YYSTACK_BYTES(N) \
-     ((N) * (sizeof (yytype_int16) + sizeof (YYSTYPE)) \
-      + YYSTACK_GAP_MAXIMUM)
-
-/* Copy COUNT objects from FROM to TO.  The source and destination do
-   not overlap.  */
-# ifndef YYCOPY
-#  if defined __GNUC__ && 1 < __GNUC__
-#   define YYCOPY(To, From, Count) \
-      __builtin_memcpy (To, From, (Count) * sizeof (*(From)))
-#  else
-#   define YYCOPY(To, From, Count)             \
-      do                                       \
-       {                                       \
-         YYSIZE_T yyi;                         \
-         for (yyi = 0; yyi < (Count); yyi++)   \
-           (To)[yyi] = (From)[yyi];            \
-       }                                       \
-      while (YYID (0))
-#  endif
-# endif
-
-/* Relocate STACK from its old location to the new one.  The
-   local variables YYSIZE and YYSTACKSIZE give the old and new number of
-   elements in the stack, and YYPTR gives the new location of the
-   stack.  Advance YYPTR to a properly aligned location for the next
-   stack.  */
-# define YYSTACK_RELOCATE(Stack)                                       \
-    do                                                                 \
-      {                                                                        \
-       YYSIZE_T yynewbytes;                                            \
-       YYCOPY (&yyptr->Stack, Stack, yysize);                          \
-       Stack = &yyptr->Stack;                                          \
-       yynewbytes = yystacksize * sizeof (*Stack) + YYSTACK_GAP_MAXIMUM; \
-       yyptr += yynewbytes / sizeof (*yyptr);                          \
-      }                                                                        \
-    while (YYID (0))
-
-#endif
-
-/* YYFINAL -- State number of the termination state.  */
-#define YYFINAL  4
-/* YYLAST -- Last index in YYTABLE.  */
-#define YYLAST   2201
-
-/* YYNTOKENS -- Number of terminals.  */
-#define YYNTOKENS  76
-/* YYNNTS -- Number of nonterminals.  */
-#define YYNNTS  142
-/* YYNRULES -- Number of rules.  */
-#define YYNRULES  352
-/* YYNRULES -- Number of states.  */
-#define YYNSTATES  669
-
-/* YYTRANSLATE(YYLEX) -- Bison symbol number corresponding to YYLEX.  */
-#define YYUNDEFTOK  2
-#define YYMAXUTOK   306
-
-#define YYTRANSLATE(YYX)                                               \
-  ((unsigned int) (YYX) <= YYMAXUTOK ? yytranslate[YYX] : YYUNDEFTOK)
-
-/* YYTRANSLATE[YYLEX] -- Bison symbol number corresponding to YYLEX.  */
-static const yytype_uint8 yytranslate[] =
-{
-       0,     2,     2,     2,     2,     2,     2,     2,     2,     2,
-       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
-       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
-       2,     2,     2,    69,     2,     2,    64,    55,    56,     2,
-      59,    60,    53,    49,    75,    50,    63,    54,     2,     2,
-       2,     2,     2,     2,     2,     2,     2,     2,    66,    62,
-       2,    65,     2,    73,    74,     2,     2,     2,     2,     2,
-       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
-       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
-       2,    71,     2,    72,    52,     2,     2,     2,     2,     2,
-       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
-       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
-       2,     2,     2,    67,    51,    68,    70,     2,     2,     2,
-       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
-       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
-       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
-       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
-       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
-       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
-       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
-       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
-       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
-       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
-       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
-       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
-       2,     2,     2,     2,     2,     2,     1,     2,     3,     4,
-       5,     6,     7,     8,     9,    10,    11,    12,    13,    14,
-      15,    16,    17,    18,    19,    20,    21,    22,    23,    24,
-      25,    26,    27,    28,    29,    30,    31,    32,    33,    34,
-      35,    36,    37,    38,    39,    40,    41,    42,    43,    44,
-      45,    46,    47,    48,    57,    58,    61
-};
-
-#if YYDEBUG
-/* YYPRHS[YYN] -- Index of the first RHS symbol of rule number YYN in
-   YYRHS.  */
-static const yytype_uint16 yyprhs[] =
-{
-       0,     0,     3,     8,     9,    13,    14,    18,    19,    23,
-      26,    32,    36,    40,    43,    45,    49,    51,    54,    57,
-      62,    63,    65,    66,    71,    72,    74,    76,    78,    80,
-      83,    89,    93,    96,   102,   110,   114,   117,   123,   127,
-     129,   132,   137,   141,   146,   150,   152,   155,   157,   159,
-     162,   164,   168,   172,   176,   179,   182,   186,   192,   198,
-     201,   202,   207,   208,   212,   213,   216,   217,   222,   227,
-     232,   235,   241,   243,   245,   248,   249,   253,   255,   259,
-     260,   261,   262,   271,   272,   278,   279,   282,   283,   286,
-     287,   288,   296,   297,   303,   305,   309,   313,   317,   321,
-     325,   329,   333,   337,   341,   345,   349,   353,   357,   361,
-     365,   369,   373,   377,   381,   385,   387,   390,   393,   396,
-     399,   402,   405,   408,   411,   415,   421,   428,   430,   432,
-     436,   442,   448,   453,   460,   469,   471,   477,   483,   489,
-     497,   499,   500,   504,   506,   511,   513,   518,   520,   524,
-     526,   528,   530,   532,   534,   536,   538,   539,   541,   543,
-     545,   547,   552,   557,   559,   561,   563,   566,   568,   570,
-     572,   574,   576,   580,   582,   584,   586,   589,   591,   593,
-     595,   597,   601,   603,   605,   607,   609,   611,   613,   615,
-     617,   619,   623,   628,   633,   636,   640,   646,   648,   650,
-     653,   657,   663,   667,   673,   677,   681,   687,   696,   702,
-     711,   717,   718,   722,   723,   725,   729,   731,   736,   739,
-     740,   744,   746,   750,   752,   756,   758,   762,   764,   768,
-     770,   774,   778,   781,   786,   790,   796,   802,   804,   808,
-     810,   813,   815,   819,   824,   826,   829,   832,   834,   836,
-     840,   841,   844,   845,   847,   849,   851,   853,   855,   857,
-     859,   861,   863,   864,   869,   871,   874,   877,   880,   883,
-     886,   889,   891,   895,   897,   901,   903,   907,   909,   913,
-     915,   919,   921,   923,   927,   931,   932,   935,   936,   938,
-     939,   941,   942,   944,   945,   947,   948,   950,   951,   953,
-     954,   956,   957,   959,   960,   962,   967,   972,   978,   985,
-     990,   995,   997,   999,  1001,  1003,  1005,  1007,  1009,  1011,
-    1013,  1017,  1022,  1028,  1033,  1038,  1041,  1044,  1049,  1053,
-    1057,  1063,  1067,  1072,  1076,  1082,  1084,  1085,  1087,  1091,
-    1093,  1095,  1098,  1100,  1102,  1108,  1109,  1112,  1114,  1118,
-    1120,  1124,  1126
-};
-
-/* YYRHS -- A `-1'-separated list of the rules' RHS.  */
-static const yytype_int16 yyrhs[] =
-{
-      77,     0,    -1,    79,    78,    81,   166,    -1,    -1,    25,
-     141,    62,    -1,    -1,    80,    86,    88,    -1,    -1,    81,
-      82,    62,    -1,    21,    83,    -1,    21,    59,    84,   190,
-      60,    -1,    21,    59,    60,    -1,    85,    86,    88,    -1,
-      85,    88,    -1,    83,    -1,    84,    62,    83,    -1,     3,
-      -1,   141,     3,    -1,    63,     3,    -1,    25,    24,    87,
-      62,    -1,    -1,    24,    -1,    -1,    89,   214,    64,    64,
-      -1,    -1,    91,    -1,   158,    -1,   181,    -1,     1,    -1,
-      32,    93,    -1,    32,    59,   167,   190,    60,    -1,    32,
-      59,    60,    -1,    92,    94,    -1,    92,    59,    94,   190,
-      60,    -1,    92,    59,    94,    62,   168,   190,    60,    -1,
-      92,    59,    60,    -1,    31,    97,    -1,    31,    59,   169,
-     190,    60,    -1,    31,    59,    60,    -1,     9,    -1,   185,
-     146,    -1,   185,   146,    65,   186,    -1,   185,    65,   186,
-      -1,   185,   146,    65,   186,    -1,   185,    65,   186,    -1,
-      94,    -1,   185,   146,    -1,   185,    -1,   141,    -1,    96,
-     146,    -1,   126,    -1,   126,     4,   126,    -1,   186,    65,
-     186,    -1,   186,     5,   186,    -1,   126,    42,    -1,   126,
-      37,    -1,     7,   187,    66,    -1,     7,   187,    65,   126,
-      66,    -1,     7,   187,     5,   126,    66,    -1,    12,    66,
-      -1,    -1,    67,   101,   183,    68,    -1,    -1,    99,   103,
-     183,    -1,    -1,   104,   102,    -1,    -1,    35,   106,   183,
-      68,    -1,   186,    65,    26,   126,    -1,   186,     5,    26,
-     126,    -1,    26,   126,    -1,   194,    62,   194,    62,   194,
-      -1,   194,    -1,   107,    -1,   108,   105,    -1,    -1,    16,
-     111,   109,    -1,   194,    -1,   194,    62,   194,    -1,    -1,
-      -1,    -1,    20,   114,   112,   115,   105,   116,   119,   120,
-      -1,    -1,    14,    20,   118,   112,   105,    -1,    -1,   119,
-     117,    -1,    -1,    14,   100,    -1,    -1,    -1,    30,   122,
-     112,   123,    35,   104,    68,    -1,    -1,    28,   125,    35,
-     104,    68,    -1,   127,    -1,   126,    47,   126,    -1,   126,
-      33,   126,    -1,   126,    38,   126,    -1,   126,    46,   126,
-      -1,   126,    45,   126,    -1,   126,    43,   126,    -1,   126,
-      39,   126,    -1,   126,    40,   126,    -1,   126,    49,   126,
-      -1,   126,    50,   126,    -1,   126,    51,   126,    -1,   126,
-      52,   126,    -1,   126,    53,   126,    -1,   126,    54,   126,
-      -1,   126,    55,   126,    -1,   126,    56,   126,    -1,   126,
-      34,   126,    -1,   126,    44,   126,    -1,   126,    48,   126,
-      -1,   126,    36,   126,    -1,   134,    -1,    53,   127,    -1,
-      56,   127,    -1,    49,   127,    -1,    50,   127,    -1,    69,
-     127,    -1,    70,   127,    -1,    52,   127,    -1,    36,   127,
-      -1,   134,    59,    60,    -1,   134,    59,   187,   191,    60,
-      -1,   134,    59,   187,    11,   191,    60,    -1,     3,    -1,
-     143,    -1,   134,    63,   141,    -1,   134,    63,    59,   135,
-      60,    -1,   134,    63,    59,    31,    60,    -1,   134,    71,
-     126,    72,    -1,   134,    71,   192,    66,   192,    72,    -1,
-     134,    71,   192,    66,   192,    66,   192,    72,    -1,   128,
-      -1,   149,    59,   126,   191,    60,    -1,   150,   137,   130,
-     189,    68,    -1,   129,    67,   130,   189,    68,    -1,    59,
-     135,    60,    67,   130,   189,    68,    -1,   165,    -1,    -1,
-     126,    66,   133,    -1,   126,    -1,    67,   130,   189,    68,
-      -1,   126,    -1,    67,   130,   189,    68,    -1,   129,    -1,
-      59,   135,    60,    -1,   126,    -1,   147,    -1,   146,    -1,
-      35,    -1,    67,    -1,   141,    -1,   141,    -1,    -1,   138,
-      -1,    24,    -1,   142,    -1,    73,    -1,    74,     3,    63,
-      24,    -1,    74,     3,    63,    73,    -1,   141,    -1,   138,
-      -1,    11,    -1,    11,   146,    -1,   155,    -1,   161,    -1,
-     153,    -1,   154,    -1,   152,    -1,    59,   146,    60,    -1,
-     155,    -1,   161,    -1,   153,    -1,    53,   147,    -1,   161,
-      -1,   153,    -1,   154,    -1,   152,    -1,    59,   146,    60,
-      -1,   161,    -1,   153,    -1,   153,    -1,   155,    -1,   161,
-      -1,   153,    -1,   154,    -1,   152,    -1,   143,    -1,   143,
-      63,   141,    -1,    71,   192,    72,   146,    -1,    71,    11,
-      72,   146,    -1,     8,   148,    -1,     8,    36,   146,    -1,
-      23,    71,   146,    72,   146,    -1,   156,    -1,   157,    -1,
-      53,   146,    -1,    36,     8,   146,    -1,    29,   137,   170,
-     190,    68,    -1,    29,   137,    68,    -1,    22,   137,   171,
-     190,    68,    -1,    22,   137,    68,    -1,    17,   159,   162,
-      -1,   141,    59,   179,    60,   163,    -1,    59,   179,    60,
-     141,    59,   179,    60,   163,    -1,   200,    59,   195,    60,
-     210,    -1,    59,   215,    60,   141,    59,   195,    60,   210,
-      -1,    17,    59,   179,    60,   163,    -1,    -1,    67,   183,
-      68,    -1,    -1,   151,    -1,    59,   179,    60,    -1,   161,
-      -1,   164,   137,   183,    68,    -1,   164,     1,    -1,    -1,
-     166,    90,    62,    -1,    93,    -1,   167,    62,    93,    -1,
-      95,    -1,   168,    62,    95,    -1,    97,    -1,   169,    62,
-      97,    -1,   172,    -1,   170,    62,   172,    -1,   175,    -1,
-     171,    62,   175,    -1,   184,   146,   198,    -1,   174,   198,
-      -1,    59,   174,    60,   198,    -1,    53,   174,   198,    -1,
-      59,    53,   174,    60,   198,    -1,    53,    59,   174,    60,
-     198,    -1,    24,    -1,    24,    63,   141,    -1,   173,    -1,
-     138,   176,    -1,   173,    -1,    59,   173,    60,    -1,    59,
-     179,    60,   163,    -1,   136,    -1,   141,   136,    -1,   141,
-     145,    -1,   145,    -1,   177,    -1,   178,    75,   177,    -1,
-      -1,   178,   191,    -1,    -1,   100,    -1,    91,    -1,   181,
-      -1,     1,    -1,    98,    -1,   110,    -1,   121,    -1,   124,
-      -1,   113,    -1,    -1,   144,    66,   182,   180,    -1,    15,
-      -1,     6,   140,    -1,    10,   140,    -1,    18,   128,    -1,
-      13,   128,    -1,    19,   138,    -1,    27,   193,    -1,   180,
-      -1,   183,    62,   180,    -1,   138,    -1,   184,    75,   138,
-      -1,   139,    -1,   185,    75,   139,    -1,   126,    -1,   186,
-      75,   126,    -1,   135,    -1,   187,    75,   135,    -1,   131,
-      -1,   132,    -1,   188,    75,   131,    -1,   188,    75,   132,
-      -1,    -1,   188,   191,    -1,    -1,    62,    -1,    -1,    75,
-      -1,    -1,   126,    -1,    -1,   186,    -1,    -1,    98,    -1,
-      -1,   215,    -1,    -1,   216,    -1,    -1,   217,    -1,    -1,
-       3,    -1,    21,    24,     3,    62,    -1,    32,   200,   202,
-      62,    -1,     9,   200,    65,   213,    62,    -1,     9,   200,
-     202,    65,   213,    62,    -1,    31,   201,   202,    62,    -1,
-      17,   160,   162,    62,    -1,   142,    -1,   200,    -1,   204,
-      -1,   205,    -1,   206,    -1,   204,    -1,   206,    -1,   142,
-      -1,    24,    -1,    71,    72,   202,    -1,    71,     3,    72,
-     202,    -1,    23,    71,   202,    72,   202,    -1,    29,    67,
-     196,    68,    -1,    22,    67,   197,    68,    -1,    53,   202,
-      -1,     8,   203,    -1,     8,    59,   205,    60,    -1,     8,
-      36,   202,    -1,    36,     8,   202,    -1,    17,    59,   195,
-      60,   210,    -1,   141,   202,   198,    -1,   141,    11,   202,
-     198,    -1,   141,   202,   198,    -1,   141,    59,   195,    60,
-     210,    -1,   202,    -1,    -1,   211,    -1,    59,   195,    60,
-      -1,   202,    -1,     3,    -1,    50,     3,    -1,   141,    -1,
-     212,    -1,    59,   212,    49,   212,    60,    -1,    -1,   214,
-     199,    -1,   207,    -1,   215,    75,   207,    -1,   208,    -1,
-     216,    62,   208,    -1,   209,    -1,   217,    62,   209,    -1
-};
-
-/* YYRLINE[YYN] -- source line where rule number YYN was defined.  */
-static const yytype_uint16 yyrline[] =
-{
-       0,   124,   124,   133,   139,   150,   150,   165,   166,   169,
-     170,   171,   174,   211,   222,   223,   226,   233,   240,   249,
-     263,   264,   271,   271,   284,   288,   289,   293,   298,   304,
-     308,   312,   316,   322,   328,   334,   339,   343,   347,   353,
-     359,   363,   367,   373,   377,   383,   384,   388,   394,   403,
-     409,   427,   432,   444,   460,   466,   474,   494,   512,   521,
-     540,   539,   554,   553,   585,   588,   595,   594,   605,   611,
-     618,   625,   636,   642,   645,   653,   652,   663,   669,   681,
-     685,   690,   680,   711,   710,   723,   726,   732,   735,   747,
-     751,   746,   769,   768,   784,   785,   789,   793,   797,   801,
-     805,   809,   813,   817,   821,   825,   829,   833,   837,   841,
-     845,   849,   853,   857,   862,   868,   869,   873,   884,   888,
-     892,   896,   901,   905,   915,   919,   924,   932,   936,   937,
-     948,   952,   956,   960,   964,   972,   973,   979,   986,   992,
-     999,  1002,  1009,  1015,  1032,  1039,  1040,  1047,  1048,  1067,
-    1068,  1071,  1074,  1078,  1089,  1098,  1104,  1107,  1110,  1117,
-    1118,  1124,  1137,  1152,  1160,  1172,  1177,  1183,  1184,  1185,
-    1186,  1187,  1188,  1194,  1195,  1196,  1197,  1203,  1204,  1205,
-    1206,  1207,  1213,  1214,  1217,  1220,  1221,  1222,  1223,  1224,
-    1227,  1228,  1241,  1245,  1250,  1255,  1260,  1264,  1265,  1268,
-    1274,  1281,  1287,  1294,  1300,  1311,  1327,  1356,  1394,  1419,
-    1437,  1446,  1449,  1457,  1461,  1465,  1472,  1478,  1483,  1495,
-    1498,  1510,  1511,  1517,  1518,  1524,  1528,  1534,  1535,  1541,
-    1545,  1551,  1574,  1579,  1585,  1591,  1598,  1607,  1616,  1631,
-    1637,  1642,  1646,  1653,  1666,  1667,  1673,  1679,  1682,  1686,
-    1692,  1695,  1704,  1707,  1708,  1712,  1713,  1719,  1720,  1721,
-    1722,  1723,  1725,  1724,  1739,  1745,  1749,  1753,  1757,  1761,
-    1766,  1785,  1791,  1799,  1803,  1809,  1813,  1819,  1823,  1829,
-    1833,  1842,  1846,  1850,  1854,  1860,  1863,  1871,  1872,  1874,
-    1875,  1878,  1881,  1884,  1887,  1890,  1893,  1896,  1899,  1902,
-    1905,  1908,  1911,  1914,  1917,  1923,  1927,  1931,  1935,  1939,
-    1943,  1963,  1970,  1981,  1982,  1983,  1986,  1987,  1990,  1994,
-    2004,  2008,  2012,  2016,  2020,  2024,  2028,  2034,  2040,  2048,
-    2056,  2062,  2069,  2085,  2107,  2111,  2117,  2120,  2123,  2127,
-    2137,  2141,  2160,  2168,  2169,  2181,  2182,  2185,  2189,  2195,
-    2199,  2205,  2209
-};
-#endif
-
-#if YYDEBUG || YYERROR_VERBOSE || YYTOKEN_TABLE
-/* YYTNAME[SYMBOL-NUM] -- String name of the symbol SYMBOL-NUM.
-   First, the terminals, then, starting at YYNTOKENS, nonterminals.  */
-const char *yytname[] =
-{
-  "$end", "error", "$undefined", "LLITERAL", "LASOP", "LCOLAS", "LBREAK",
-  "LCASE", "LCHAN", "LCONST", "LCONTINUE", "LDDD", "LDEFAULT", "LDEFER",
-  "LELSE", "LFALL", "LFOR", "LFUNC", "LGO", "LGOTO", "LIF", "LIMPORT",
-  "LINTERFACE", "LMAP", "LNAME", "LPACKAGE", "LRANGE", "LRETURN",
-  "LSELECT", "LSTRUCT", "LSWITCH", "LTYPE", "LVAR", "LANDAND", "LANDNOT",
-  "LBODY", "LCOMM", "LDEC", "LEQ", "LGE", "LGT", "LIGNORE", "LINC", "LLE",
-  "LLSH", "LLT", "LNE", "LOROR", "LRSH", "'+'", "'-'", "'|'", "'^'", "'*'",
-  "'/'", "'%'", "'&'", "NotPackage", "NotParen", "'('", "')'",
-  "PreferToRightParen", "';'", "'.'", "'$'", "'='", "':'", "'{'", "'}'",
-  "'!'", "'~'", "'['", "']'", "'?'", "'@'", "','", "$accept", "file",
-  "package", "loadsys", "@1", "imports", "import", "import_stmt",
-  "import_stmt_list", "import_here", "import_package", "import_safety",
-  "import_there", "@2", "xdcl", "common_dcl", "lconst", "vardcl",
-  "constdcl", "constdcl1", "typedclname", "typedcl", "simple_stmt", "case",
-  "compound_stmt", "@3", "caseblock", "@4", "caseblock_list", "loop_body",
-  "@5", "range_stmt", "for_header", "for_body", "for_stmt", "@6",
-  "if_header", "if_stmt", "@7", "@8", "@9", "elseif", "@10", "elseif_list",
-  "else", "switch_stmt", "@11", "@12", "select_stmt", "@13", "expr",
-  "uexpr", "pseudocall", "pexpr_no_paren", "start_complit", "keyval",
-  "bare_complitexpr", "complitexpr", "pexpr", "expr_or_type",
-  "name_or_type", "lbrace", "new_name", "dcl_name", "onew_name", "sym",
-  "hidden_importsym", "name", "labelname", "dotdotdot", "ntype",
-  "non_expr_type", "non_recvchantype", "convtype", "comptype",
-  "fnret_type", "dotname", "othertype", "ptrtype", "recvchantype",
-  "structtype", "interfacetype", "xfndcl", "fndcl", "hidden_fndcl",
-  "fntype", "fnbody", "fnres", "fnlitdcl", "fnliteral", "xdcl_list",
-  "vardcl_list", "constdcl_list", "typedcl_list", "structdcl_list",
-  "interfacedcl_list", "structdcl", "packname", "embed", "interfacedcl",
-  "indcl", "arg_type", "arg_type_list", "oarg_type_list_ocomma", "stmt",
-  "non_dcl_stmt", "@14", "stmt_list", "new_name_list", "dcl_name_list",
-  "expr_list", "expr_or_type_list", "keyval_list", "braced_keyval_list",
-  "osemi", "ocomma", "oexpr", "oexpr_list", "osimple_stmt",
-  "ohidden_funarg_list", "ohidden_structdcl_list",
-  "ohidden_interfacedcl_list", "oliteral", "hidden_import",
-  "hidden_pkg_importsym", "hidden_pkgtype", "hidden_type",
-  "hidden_type_non_recv_chan", "hidden_type_misc", "hidden_type_recv_chan",
-  "hidden_type_func", "hidden_funarg", "hidden_structdcl",
-  "hidden_interfacedcl", "ohidden_funres", "hidden_funres",
-  "hidden_literal", "hidden_constant", "hidden_import_list",
-  "hidden_funarg_list", "hidden_structdcl_list",
-  "hidden_interfacedcl_list", 0
-};
-#endif
-
-# ifdef YYPRINT
-/* YYTOKNUM[YYLEX-NUM] -- Internal token number corresponding to
-   token YYLEX-NUM.  */
-static const yytype_uint16 yytoknum[] =
-{
-       0,   256,   257,   258,   259,   260,   261,   262,   263,   264,
-     265,   266,   267,   268,   269,   270,   271,   272,   273,   274,
-     275,   276,   277,   278,   279,   280,   281,   282,   283,   284,
-     285,   286,   287,   288,   289,   290,   291,   292,   293,   294,
-     295,   296,   297,   298,   299,   300,   301,   302,   303,    43,
-      45,   124,    94,    42,    47,    37,    38,   304,   305,    40,
-      41,   306,    59,    46,    36,    61,    58,   123,   125,    33,
-     126,    91,    93,    63,    64,    44
-};
-# endif
-
-/* YYR1[YYN] -- Symbol number of symbol that rule YYN derives.  */
-static const yytype_uint8 yyr1[] =
-{
-       0,    76,    77,    78,    78,    80,    79,    81,    81,    82,
-      82,    82,    83,    83,    84,    84,    85,    85,    85,    86,
-      87,    87,    89,    88,    90,    90,    90,    90,    90,    91,
-      91,    91,    91,    91,    91,    91,    91,    91,    91,    92,
-      93,    93,    93,    94,    94,    95,    95,    95,    96,    97,
-      98,    98,    98,    98,    98,    98,    99,    99,    99,    99,
-     101,   100,   103,   102,   104,   104,   106,   105,   107,   107,
-     107,   108,   108,   108,   109,   111,   110,   112,   112,   114,
-     115,   116,   113,   118,   117,   119,   119,   120,   120,   122,
-     123,   121,   125,   124,   126,   126,   126,   126,   126,   126,
-     126,   126,   126,   126,   126,   126,   126,   126,   126,   126,
-     126,   126,   126,   126,   126,   127,   127,   127,   127,   127,
-     127,   127,   127,   127,   128,   128,   128,   129,   129,   129,
-     129,   129,   129,   129,   129,   129,   129,   129,   129,   129,
-     129,   130,   131,   132,   132,   133,   133,   134,   134,   135,
-     135,   136,   137,   137,   138,   139,   140,   140,   141,   141,
-     141,   142,   142,   143,   144,   145,   145,   146,   146,   146,
-     146,   146,   146,   147,   147,   147,   147,   148,   148,   148,
-     148,   148,   149,   149,   150,   151,   151,   151,   151,   151,
-     152,   152,   153,   153,   153,   153,   153,   153,   153,   154,
-     155,   156,   156,   157,   157,   158,   159,   159,   160,   160,
-     161,   162,   162,   163,   163,   163,   164,   165,   165,   166,
-     166,   167,   167,   168,   168,   169,   169,   170,   170,   171,
-     171,   172,   172,   172,   172,   172,   172,   173,   173,   174,
-     175,   175,   175,   176,   177,   177,   177,   177,   178,   178,
-     179,   179,   180,   180,   180,   180,   180,   181,   181,   181,
-     181,   181,   182,   181,   181,   181,   181,   181,   181,   181,
-     181,   183,   183,   184,   184,   185,   185,   186,   186,   187,
-     187,   188,   188,   188,   188,   189,   189,   190,   190,   191,
-     191,   192,   192,   193,   193,   194,   194,   195,   195,   196,
-     196,   197,   197,   198,   198,   199,   199,   199,   199,   199,
-     199,   200,   201,   202,   202,   202,   203,   203,   204,   204,
-     204,   204,   204,   204,   204,   204,   204,   204,   204,   205,
-     206,   207,   207,   208,   209,   209,   210,   210,   211,   211,
-     212,   212,   212,   213,   213,   214,   214,   215,   215,   216,
-     216,   217,   217
-};
-
-/* YYR2[YYN] -- Number of symbols composing right hand side of rule YYN.  */
-static const yytype_uint8 yyr2[] =
-{
-       0,     2,     4,     0,     3,     0,     3,     0,     3,     2,
-       5,     3,     3,     2,     1,     3,     1,     2,     2,     4,
-       0,     1,     0,     4,     0,     1,     1,     1,     1,     2,
-       5,     3,     2,     5,     7,     3,     2,     5,     3,     1,
-       2,     4,     3,     4,     3,     1,     2,     1,     1,     2,
-       1,     3,     3,     3,     2,     2,     3,     5,     5,     2,
-       0,     4,     0,     3,     0,     2,     0,     4,     4,     4,
-       2,     5,     1,     1,     2,     0,     3,     1,     3,     0,
-       0,     0,     8,     0,     5,     0,     2,     0,     2,     0,
-       0,     7,     0,     5,     1,     3,     3,     3,     3,     3,
-       3,     3,     3,     3,     3,     3,     3,     3,     3,     3,
-       3,     3,     3,     3,     3,     1,     2,     2,     2,     2,
-       2,     2,     2,     2,     3,     5,     6,     1,     1,     3,
-       5,     5,     4,     6,     8,     1,     5,     5,     5,     7,
-       1,     0,     3,     1,     4,     1,     4,     1,     3,     1,
-       1,     1,     1,     1,     1,     1,     0,     1,     1,     1,
-       1,     4,     4,     1,     1,     1,     2,     1,     1,     1,
-       1,     1,     3,     1,     1,     1,     2,     1,     1,     1,
-       1,     3,     1,     1,     1,     1,     1,     1,     1,     1,
-       1,     3,     4,     4,     2,     3,     5,     1,     1,     2,
-       3,     5,     3,     5,     3,     3,     5,     8,     5,     8,
-       5,     0,     3,     0,     1,     3,     1,     4,     2,     0,
-       3,     1,     3,     1,     3,     1,     3,     1,     3,     1,
-       3,     3,     2,     4,     3,     5,     5,     1,     3,     1,
-       2,     1,     3,     4,     1,     2,     2,     1,     1,     3,
-       0,     2,     0,     1,     1,     1,     1,     1,     1,     1,
-       1,     1,     0,     4,     1,     2,     2,     2,     2,     2,
-       2,     1,     3,     1,     3,     1,     3,     1,     3,     1,
-       3,     1,     1,     3,     3,     0,     2,     0,     1,     0,
-       1,     0,     1,     0,     1,     0,     1,     0,     1,     0,
-       1,     0,     1,     0,     1,     4,     4,     5,     6,     4,
-       4,     1,     1,     1,     1,     1,     1,     1,     1,     1,
-       3,     4,     5,     4,     4,     2,     2,     4,     3,     3,
-       5,     3,     4,     3,     5,     1,     0,     1,     3,     1,
-       1,     2,     1,     1,     5,     0,     2,     1,     3,     1,
-       3,     1,     3
-};
-
-/* YYDEFACT[STATE-NAME] -- Default rule to reduce with in state
-   STATE-NUM when YYTABLE doesn't specify something else to do.  Zero
-   means the default is an error.  */
-static const yytype_uint16 yydefact[] =
-{
-       5,     0,     3,     0,     1,     0,     7,     0,    22,   158,
-     160,     0,     0,   159,   219,    20,     6,   345,     0,     4,
-       0,     0,     0,    21,     0,     0,     0,    16,     0,     0,
-       9,    22,     0,     8,    28,   127,   156,     0,    39,   156,
-       0,   264,    75,     0,     0,     0,    79,     0,     0,   293,
-      92,     0,    89,     0,     0,     0,     0,     0,     0,     0,
-       0,     0,     0,     0,   291,     0,    25,     0,   257,   258,
-     261,   259,   260,    50,    94,   135,   147,   115,   164,   163,
-     128,     0,     0,     0,   184,   197,   198,    26,   216,     0,
-     140,    27,     0,    19,     0,     0,     0,     0,     0,     0,
-     346,   161,   162,    11,    14,   287,    18,    22,    13,    17,
-     157,   265,   154,     0,     0,     0,     0,   163,   190,   194,
-     180,   178,   179,   177,   266,   135,     0,   295,   250,     0,
-     211,   135,   269,   295,   152,   153,     0,     0,   277,   294,
-     270,     0,     0,   295,     0,     0,    36,    48,     0,    29,
-     275,   155,     0,   123,   118,   119,   122,   116,   117,     0,
-       0,   149,     0,   150,   175,   173,   174,   120,   121,     0,
-     292,     0,   220,     0,    32,     0,     0,     0,     0,     0,
-      55,     0,     0,     0,    54,     0,     0,     0,     0,     0,
-       0,     0,     0,     0,     0,     0,     0,     0,     0,   141,
-       0,     0,   291,   262,     0,   141,   218,     0,     0,     0,
-       0,   311,     0,     0,   211,     0,     0,   312,     0,     0,
-      23,   288,     0,    12,   250,     0,     0,   195,   171,   169,
-     170,   167,   168,   199,     0,     0,     0,   296,    73,     0,
-      76,     0,    72,   165,   244,   163,   247,   151,   248,   289,
-       0,   250,     0,   205,    80,    77,   158,     0,   204,     0,
-     287,   241,   229,     0,    64,     0,     0,   202,   273,   287,
-     227,   239,   303,     0,    90,    38,   225,   287,    49,    31,
-     221,   287,     0,     0,    40,     0,   176,   148,     0,     0,
-      35,   287,     0,     0,    51,    96,   111,   114,    97,   101,
-     102,   100,   112,    99,    98,    95,   113,   103,   104,   105,
-     106,   107,   108,   109,   110,   285,   124,   279,   289,     0,
-     129,   292,     0,     0,   289,   285,   256,    60,   254,   253,
-     271,   255,     0,    53,    52,   278,     0,     0,     0,     0,
-     319,     0,     0,     0,     0,     0,   318,     0,   313,   314,
-     315,     0,   347,     0,     0,   297,     0,     0,     0,    15,
-      10,     0,     0,     0,   181,   191,    70,    66,    74,     0,
-       0,   295,   166,   245,   246,   290,   251,   213,     0,     0,
-       0,   295,     0,   237,     0,   250,   240,   288,     0,     0,
-       0,     0,   303,     0,     0,   288,     0,   304,   232,     0,
-     303,     0,   288,     0,   288,     0,    42,   276,     0,     0,
-       0,   200,   171,   169,   170,   168,   141,   193,   192,   288,
-       0,    44,     0,   141,   143,   281,   282,   289,     0,   289,
-     290,     0,     0,     0,   132,   291,   263,   290,     0,     0,
-       0,     0,   217,     0,     0,   326,   316,   317,   297,   301,
-       0,   299,     0,   325,   340,     0,     0,   342,   343,     0,
-       0,     0,     0,     0,   303,     0,     0,   310,     0,   298,
-     305,   309,   306,   213,   172,     0,     0,     0,     0,   249,
-     250,   163,   214,   189,   187,   188,   185,   186,   210,   213,
-     212,    81,    78,   238,   242,     0,   230,   203,   196,     0,
-       0,    93,    62,    65,     0,   234,     0,   303,   228,   201,
-     274,   231,    64,   226,    37,   222,    30,    41,     0,   285,
-      45,   223,   287,    47,    33,    43,   285,     0,   290,   286,
-     138,     0,   280,   125,   131,   130,     0,   136,   137,     0,
-     272,   328,     0,     0,   319,     0,   318,     0,   335,   351,
-     302,     0,     0,     0,   349,   300,   329,   341,     0,   307,
-       0,   320,     0,   303,   331,     0,   348,   336,     0,    69,
-      68,   295,     0,   250,   206,    85,   213,     0,    59,     0,
-     303,   303,   233,     0,   172,     0,   288,     0,    46,     0,
-     141,   145,   142,   283,   284,   126,   291,   133,    61,   327,
-     336,   297,   324,     0,     0,   303,   323,     0,     0,   321,
-     308,   332,   297,   297,   339,   208,   337,    67,    71,   215,
-       0,    87,   243,     0,     0,    56,     0,    63,   236,   235,
-      91,   139,   224,    34,   144,   285,     0,   330,     0,   352,
-     322,   333,   350,     0,     0,     0,   213,     0,    86,    82,
-       0,     0,     0,   134,   336,   344,   336,   338,   207,    83,
-      88,    58,    57,   146,   334,   209,   295,     0,    84
-};
-
-/* YYDEFGOTO[NTERM-NUM].  */
-static const yytype_int16 yydefgoto[] =
-{
-      -1,     1,     6,     2,     3,    14,    21,    30,   105,    31,
-       8,    24,    16,    17,    65,   328,    67,   149,   520,   521,
-     145,   146,    68,   502,   329,   440,   503,   579,   390,   368,
-     475,   238,   239,   240,    69,   127,   254,    70,   133,   380,
-     575,   648,   666,   621,   649,    71,   143,   401,    72,   141,
-      73,    74,    75,    76,   315,   425,   426,   592,    77,   317,
-     244,   136,    78,   150,   111,   117,    13,    80,    81,   246,
-     247,   163,   119,    82,    83,   482,   228,    84,   230,   231,
-      85,    86,    87,   130,   214,    88,   253,   488,    89,    90,
-      22,   281,   522,   277,   269,   260,   270,   271,   272,   262,
-     386,   248,   249,   250,   330,   331,   323,   332,   273,   152,
-      92,   318,   427,   428,   222,   376,   171,   140,   255,   468,
-     553,   547,   398,   100,   212,   218,   614,   445,   348,   349,
-     350,   352,   554,   549,   615,   616,   458,   459,    25,   469,
-     555,   550
-};
-
-/* YYPACT[STATE-NUM] -- Index in YYTABLE of the portion describing
-   STATE-NUM.  */
-#define YYPACT_NINF -473
-static const yytype_int16 yypact[] =
-{
-    -473,    65,    22,    49,  -473,   261,  -473,    64,  -473,  -473,
-    -473,    95,    52,  -473,   143,   145,  -473,  -473,   104,  -473,
-      68,   128,  1049,  -473,   142,   305,    16,  -473,    56,   204,
-    -473,    49,   220,  -473,  -473,  -473,   261,   974,  -473,   261,
-     562,  -473,  -473,   288,   562,   261,  -473,    14,   147,  1615,
-    -473,    14,  -473,   395,   401,  1615,  1615,  1615,  1615,  1615,
-    1615,  1658,  1615,  1615,   737,   168,  -473,   414,  -473,  -473,
-    -473,  -473,  -473,   649,  -473,  -473,   165,   122,  -473,   169,
-    -473,   177,   218,    14,   219,  -473,  -473,  -473,   235,    89,
-    -473,  -473,    34,  -473,   206,   124,   286,   206,   206,   260,
-    -473,  -473,  -473,  -473,  -473,   265,  -473,  -473,  -473,  -473,
-    -473,  -473,  -473,   270,  1803,  1803,  1803,  -473,   269,  -473,
-    -473,  -473,  -473,  -473,  -473,    39,   122,   882,  1777,   283,
-     277,   230,  -473,  1615,  -473,  -473,   292,  1803,  2097,   280,
-    -473,   332,   315,  1615,   215,  1803,  -473,  -473,   244,  -473,
-    -473,  -473,   949,  -473,  -473,  -473,  -473,  -473,  -473,  1701,
-    1658,  2097,   298,  -473,     9,  -473,    59,  -473,  -473,   303,
-    2097,   319,  -473,   330,  -473,  1744,  1615,  1615,  1615,  1615,
-    -473,  1615,  1615,  1615,  -473,  1615,  1615,  1615,  1615,  1615,
-    1615,  1615,  1615,  1615,  1615,  1615,  1615,  1615,  1615,  -473,
-    1297,   455,  1615,  -473,  1615,  -473,  -473,  1225,  1615,  1615,
-    1615,  -473,   594,   261,   277,   328,   403,  -473,  1308,  1308,
-    -473,   152,   352,  -473,  1777,   405,  1803,  -473,  -473,  -473,
-    -473,  -473,  -473,  -473,   354,   261,  1615,  -473,  -473,   382,
-    -473,    47,   360,  1803,  -473,  1777,  -473,  -473,  -473,   351,
-     367,  1777,  1225,  -473,  -473,   366,    84,   407,  -473,   374,
-     373,  -473,  -473,   372,  -473,   138,    42,  -473,  -473,   377,
-    -473,  -473,   442,  1769,  -473,  -473,  -473,   384,  -473,  -473,
-    -473,   389,  1615,   261,   391,  1830,  -473,   394,  1803,  1803,
-    -473,   409,  1615,   411,  2097,  1935,  -473,  2121,  1080,  1080,
-    1080,  1080,  -473,  1080,  1080,  2145,  -473,   503,   503,   503,
-     503,  -473,  -473,  -473,  -473,  1352,  -473,  -473,    27,  1407,
-    -473,  1995,   412,  1147,  1962,  1352,  -473,  -473,  -473,  -473,
-    -473,  -473,     7,   280,   280,  2097,   698,   418,   415,   413,
-    -473,   416,   477,  1308,   188,    31,  -473,   425,  -473,  -473,
-    -473,  1897,  -473,   221,   433,   261,   434,   436,   439,  -473,
-    -473,   432,  1803,   452,  -473,  -473,  2097,  -473,  -473,  1462,
-    1517,  1615,  -473,  -473,  -473,  1777,  -473,  1856,   453,    91,
-     382,  1615,   261,   454,   456,  1777,  -473,   475,   451,  1803,
-     133,   407,   442,   407,   460,   326,   462,  -473,  -473,   261,
-     442,   467,   261,   478,   261,   486,   280,  -473,  1615,  1864,
-    1803,  -473,    26,   248,   264,   430,  -473,  -473,  -473,   261,
-     492,   280,  1615,  -473,  2025,  -473,  -473,   485,   493,   487,
-    1658,   504,   506,   508,  -473,  1615,  -473,  -473,   512,   505,
-    1225,  1147,  -473,  1308,   517,  -473,  -473,  -473,   261,  1889,
-    1308,   261,  1308,  -473,  -473,   571,   155,  -473,  -473,   514,
-     509,  1308,   188,  1308,   442,   261,   261,  -473,   518,   507,
-    -473,  -473,  -473,  1856,  -473,  1225,  1615,  1615,   521,  -473,
-    1777,   528,  -473,  -473,  -473,  -473,  -473,  -473,  -473,  1856,
-    -473,  -473,  -473,  -473,  -473,   520,  -473,  -473,  -473,  1658,
-     522,  -473,  -473,  -473,   530,  -473,   532,   442,  -473,  -473,
-    -473,  -473,  -473,  -473,  -473,  -473,  -473,   280,   535,  1352,
-    -473,  -473,   536,  1744,  -473,   280,  1352,  1560,  1352,  -473,
-    -473,   539,  -473,  -473,  -473,  -473,   247,  -473,  -473,   308,
-    -473,  -473,   541,   543,   545,   546,   547,   544,  -473,  -473,
-     551,   548,  1308,   554,  -473,   557,  -473,  -473,   576,  -473,
-    1308,  -473,   564,   442,  -473,   568,  -473,  1923,   318,  2097,
-    2097,  1615,   569,  1777,  -473,  -473,  1856,   156,  -473,  1147,
-     442,   442,  -473,   243,   483,   563,   261,   577,   411,   570,
-    -473,  2097,  -473,  -473,  -473,  -473,  1615,  -473,  -473,  -473,
-    1923,   261,  -473,  1889,  1308,   442,  -473,   261,   155,  -473,
-    -473,  -473,   261,   261,  -473,  -473,  -473,  -473,  -473,  -473,
-     579,   627,  -473,  1615,  1615,  -473,  1658,   580,  -473,  -473,
-    -473,  -473,  -473,  -473,  -473,  1352,   572,  -473,   583,  -473,
-    -473,  -473,  -473,   585,   586,   590,  1856,    77,  -473,  -473,
-    2049,  2073,   584,  -473,  1923,  -473,  1923,  -473,  -473,  -473,
-    -473,  -473,  -473,  -473,  -473,  -473,  1615,   382,  -473
-};
-
-/* YYPGOTO[NTERM-NUM].  */
-static const yytype_int16 yypgoto[] =
-{
-    -473,  -473,  -473,  -473,  -473,  -473,  -473,   -12,  -473,  -473,
-     624,  -473,    -1,  -473,  -473,   635,  -473,  -137,   -48,    74,
-    -473,  -130,  -112,  -473,    11,  -473,  -473,  -473,   149,  -372,
-    -473,  -473,  -473,  -473,  -473,  -473,  -140,  -473,  -473,  -473,
-    -473,  -473,  -473,  -473,  -473,  -473,  -473,  -473,  -473,  -473,
-     662,   448,   257,  -473,  -196,   135,   139,  -473,   262,   -59,
-     424,   -16,    -3,   387,   632,   427,   313,    20,  -473,   428,
-     -89,   524,  -473,  -473,  -473,  -473,   -36,   -37,   -31,   -49,
-    -473,  -473,  -473,  -473,  -473,   -32,   458,  -472,  -473,  -473,
-    -473,  -473,  -473,  -473,  -473,  -473,   279,  -108,  -211,   290,
-    -473,   306,  -473,  -214,  -291,   658,  -473,  -230,  -473,   -63,
-      -6,   191,  -473,  -302,  -219,  -254,  -195,  -473,  -107,  -435,
-    -473,  -473,  -347,  -473,   323,  -473,    72,  -473,   371,   268,
-     380,   242,   102,   110,  -468,  -473,  -438,   255,  -473,   515,
-    -473,  -473
-};
-
-/* YYTABLE[YYPACT[STATE-NUM]].  What to do in state STATE-NUM.  If
-   positive, shift that token.  If negative, reduce the rule which
-   number is the opposite.  If zero, do what YYDEFACT says.
-   If YYTABLE_NINF, syntax error.  */
-#define YYTABLE_NINF -278
-static const yytype_int16 yytable[] =
-{
-     121,   120,   162,   274,   175,   123,   122,   322,   491,   325,
-     361,   280,   165,   543,   276,   237,   104,   574,   558,   174,
-     242,   237,   379,   439,   164,   227,   233,   234,   261,   166,
-     108,   237,   436,   110,   460,   142,   110,   378,   429,   208,
-     101,   388,   132,   139,  -184,   505,  -268,     5,   263,   134,
-     396,  -268,   369,   511,   392,   394,   278,   118,   403,    27,
-    -216,  -180,   405,   284,   431,     4,   383,   205,  -183,   441,
-     438,    27,   420,   207,     7,   442,  -184,   229,   229,   229,
-       9,   135,   232,   232,   232,  -180,   293,  -237,    15,   102,
-     206,   229,     9,  -180,  -216,   393,   232,   659,    18,   209,
-     229,  -268,   430,   461,   622,   232,   223,  -268,   229,   210,
-     175,   165,   370,   232,    19,   229,   103,   564,  -182,    29,
-     232,   241,   210,   164,   134,   291,  -216,    28,   166,    10,
-      11,    29,   637,   259,   118,   118,   118,   363,   229,   268,
-     499,    10,    11,   232,   327,   500,  -237,   382,   118,   384,
-     540,   165,  -237,   441,   372,    27,   135,   118,   454,   490,
-     582,   623,   383,   164,    20,   118,   638,    26,   166,    23,
-     643,   495,   118,   529,   658,   531,     9,   644,   645,     9,
-     504,   200,   506,   213,   400,   201,   664,   229,   665,   229,
-      33,   454,   232,   202,   232,   118,   411,   391,    11,   417,
-     418,   501,   333,   334,    93,   455,   229,   106,   229,   359,
-     539,   232,     9,   232,   229,    29,   611,   585,   137,   232,
-     519,   624,   625,   109,   589,    10,    11,   526,    10,    11,
-     172,   626,   199,   628,   629,  -154,   229,  -267,   455,     9,
-     536,   232,  -267,   203,   118,   568,   118,   456,   413,   412,
-     499,   229,   229,   415,   414,   500,   232,   232,   641,   237,
-     433,    10,    11,   118,   478,   118,   572,   515,     9,   237,
-     165,   118,   513,   411,   492,   275,   406,   204,  -183,   261,
-      11,   465,   164,  -178,   347,     9,   421,   166,    10,    11,
-     357,   358,  -267,   118,  -182,   668,   466,   125,  -267,  -179,
-     498,   131,   126,   587,   279,   118,   126,  -178,   118,   118,
-     216,   630,     9,   596,    94,  -178,   256,    10,    11,   597,
-     227,   518,    95,  -179,   220,   229,    96,   221,   486,   224,
-     232,  -179,   235,   652,    10,    11,    97,    98,   229,   256,
-     484,   483,   251,   232,   252,   487,   485,   128,   229,   627,
-     256,   257,   229,   232,     9,   210,   523,   232,   287,   620,
-     258,    10,    11,   333,   334,    10,    11,   264,   265,    99,
-     441,   532,   229,   229,   266,   288,   598,   232,   232,   265,
-     441,   165,   118,   267,   259,   266,   617,   355,    10,    11,
-     290,   289,   268,   164,   635,   118,   510,   118,   166,    10,
-      11,   636,   517,    10,    11,   118,   356,   211,   211,   118,
-     211,   211,   360,   362,   364,   453,   525,   367,   215,     9,
-     217,   219,   371,   464,   486,     9,   375,   377,   381,   118,
-     118,   383,    12,   385,   588,   387,   484,   483,     9,   395,
-     486,   487,   485,   229,   389,   397,   402,    32,   232,    79,
-     165,   404,   484,   483,   144,    32,   408,   487,   485,   237,
-     148,   416,   164,   112,   618,  -177,   112,   166,    10,    11,
-     129,   419,   112,   173,    10,    11,   422,   448,   435,     9,
-     147,   151,   449,   451,   450,   452,   229,    10,    11,  -177,
-     462,   232,   473,   118,   151,   467,   470,  -177,   471,   256,
-     118,   472,   512,   153,   154,   155,   156,   157,   158,   118,
-     167,   168,   474,   489,   319,   541,   494,   382,  -181,   497,
-     507,   548,   551,   523,   556,   346,   667,   486,    10,    11,
-     509,   346,   346,   561,   257,   563,   229,   178,   514,   484,
-     483,   232,  -181,   118,   487,   485,   516,   186,    10,    11,
-    -181,   190,   524,   342,   237,   245,   195,   196,   197,   198,
-     528,   530,   437,   112,   533,    35,   534,   532,   535,   112,
-      37,   147,   537,   538,   557,   151,   559,   165,   567,   113,
-     576,   560,   466,   571,    47,    48,     9,   573,   578,   164,
-     580,    51,   581,   118,   166,   584,   118,   486,   586,   595,
-     151,   599,   336,   600,  -158,   601,  -159,   153,   157,   484,
-     483,   337,   602,   603,   487,   485,   338,   339,   340,   607,
-     604,    61,   606,   341,   605,   608,   610,   612,   320,   619,
-     342,   631,   609,    64,    79,    10,    11,   633,   634,   646,
-     351,   647,   441,   654,   653,   655,   656,   343,    32,   346,
-     657,   245,   663,   176,  -277,   107,   346,    66,   660,   344,
-     632,   583,   365,   593,   346,   345,   118,   594,    11,   373,
-     407,   124,   354,   374,   508,   548,   640,   496,   245,    79,
-      91,   479,   177,   178,   286,   179,   180,   181,   182,   183,
-     577,   184,   185,   186,   187,   188,   189,   190,   191,   192,
-     193,   194,   195,   196,   197,   198,   336,   446,   566,   642,
-     151,   138,   542,   639,  -277,   337,   447,   562,     0,     0,
-     338,   339,   340,   161,  -277,     0,   170,   341,   353,     0,
-       0,     0,     0,     0,   443,     0,     0,     0,     0,     0,
-      35,     0,     0,     0,     0,    37,     0,     0,   169,     0,
-      79,   343,     0,     0,   113,     0,   346,   444,     0,    47,
-      48,     9,   546,   346,     0,   346,    51,     0,     0,   345,
-       0,   457,    11,    55,   346,     0,   346,     0,     0,     0,
-       0,     0,   351,     0,     0,     0,    56,    57,     0,    58,
-      59,     0,     0,    60,     0,     0,    61,     0,     0,     0,
-       0,     0,   245,     0,   481,     0,    62,    63,    64,   493,
-      10,    11,   245,     0,   112,     0,     0,     0,     0,     0,
-       0,     0,   112,     0,     0,     0,   112,     0,     0,   147,
-       0,   151,     0,     0,     0,     0,     0,     0,   294,   295,
-     296,   297,     0,   298,   299,   300,   151,   301,   302,   303,
-     304,   305,   306,   307,   308,   309,   310,   311,   312,   313,
-     314,     0,   161,     0,   321,   346,   324,    79,    79,     0,
-     138,   138,   335,   346,     0,   351,   545,     0,   552,     0,
-     346,     0,     0,   457,     0,    35,     0,     0,     0,   457,
-      37,     0,   565,   351,     0,     0,     0,     0,   366,   113,
-       0,     0,    79,     0,    47,    48,     9,   245,   236,     0,
-       0,    51,     0,   346,     0,     0,   546,   346,    55,     0,
-       0,     0,     0,     0,     0,     0,     0,     0,     0,     0,
-       0,    56,    57,     0,    58,    59,     0,     0,    60,     0,
-       0,    61,     0,     0,   138,     0,     0,     0,     0,     0,
-       0,    62,    63,    64,   138,    10,    11,    37,     0,     0,
-       0,     0,     0,     0,     0,     0,   113,   346,     0,   346,
-       0,    47,    48,     9,     0,     0,     0,   424,    51,     0,
-       0,   161,    37,     0,     0,   225,     0,   424,     0,     0,
-       0,   113,     0,     0,     0,     0,    47,    48,     9,     0,
-     245,     0,   115,    51,     0,     0,    79,     0,   226,     0,
-     114,     0,     0,   151,   282,     0,     0,     0,     0,     0,
-      64,     0,    10,    11,   283,     0,     0,   115,   351,     0,
-     545,   138,   138,   116,   552,   457,     0,     0,     0,   351,
-     351,     0,     0,     0,     0,    64,     0,    10,    11,    -2,
-      34,     0,    35,     0,     0,    36,     0,    37,    38,    39,
-       0,     0,    40,     0,    41,    42,    43,    44,    45,    46,
-     138,    47,    48,     9,     0,     0,    49,    50,    51,    52,
-      53,    54,     0,     0,   138,    55,     0,     0,     0,     0,
-       0,     0,   161,     0,     0,     0,     0,   170,    56,    57,
-       0,    58,    59,     0,     0,    60,     0,     0,    61,     0,
-       0,   -24,     0,     0,   178,     0,     0,     0,    62,    63,
-      64,     0,    10,    11,   186,     0,     0,     0,   190,   191,
-     192,   193,   194,   195,   196,   197,   198,     0,   569,   570,
-       0,     0,     0,     0,     0,     0,     0,     0,   326,     0,
-      35,     0,     0,    36,  -252,    37,    38,    39,     0,  -252,
-      40,   161,    41,    42,   113,    44,    45,    46,     0,    47,
-      48,     9,     0,     0,    49,    50,    51,    52,    53,    54,
-       0,   424,     0,    55,     0,     0,     0,     0,   424,   591,
-     424,     0,     0,     0,     0,     0,    56,    57,     0,    58,
-      59,     0,     0,    60,     0,     0,    61,     0,     0,  -252,
-       0,     0,     0,     0,   327,  -252,    62,    63,    64,     0,
-      10,    11,     0,     0,     0,     0,   326,     0,    35,     0,
-       0,    36,     0,    37,    38,    39,     0,     0,    40,     0,
-      41,    42,   113,    44,    45,    46,     0,    47,    48,     9,
-       0,     0,    49,    50,    51,    52,    53,    54,   170,     0,
-       0,    55,     0,     0,     0,     0,     0,     0,     0,     0,
-       0,     0,     0,     0,    56,    57,     0,    58,    59,     0,
-       0,    60,     0,     0,    61,   650,   651,  -252,   161,     0,
-       0,     0,   327,  -252,    62,    63,    64,   424,    10,    11,
-      35,     0,     0,     0,     0,    37,     0,     0,     0,     0,
-       0,     0,     0,     0,   113,     0,   336,     0,     0,    47,
-      48,     9,     0,     0,     0,   337,    51,     0,     0,     0,
-     338,   339,   340,   159,     0,     0,     0,   341,     0,     0,
-       0,     0,     0,     0,   342,     0,    56,    57,     0,    58,
-     160,     0,     0,    60,     0,    35,    61,   316,     0,     0,
-      37,   343,     0,     0,     0,     0,    62,    63,    64,   113,
-      10,    11,     0,     0,    47,    48,     9,     0,     0,   345,
-       0,    51,    11,     0,     0,     0,     0,     0,    55,     0,
-       0,     0,     0,     0,     0,     0,     0,     0,     0,     0,
-       0,    56,    57,     0,    58,    59,     0,     0,    60,     0,
-      35,    61,     0,     0,     0,    37,     0,     0,     0,   423,
-       0,    62,    63,    64,   113,    10,    11,     0,     0,    47,
-      48,     9,     0,     0,     0,     0,    51,     0,   432,     0,
-       0,     0,     0,   159,     0,     0,     0,     0,     0,     0,
-       0,     0,     0,     0,     0,     0,    56,    57,     0,    58,
-     160,     0,     0,    60,     0,    35,    61,     0,     0,     0,
-      37,     0,     0,     0,     0,     0,    62,    63,    64,   113,
-      10,    11,     0,     0,    47,    48,     9,     0,   476,     0,
-       0,    51,     0,     0,     0,     0,     0,     0,    55,     0,
-       0,     0,     0,     0,     0,     0,     0,     0,     0,     0,
-       0,    56,    57,     0,    58,    59,     0,     0,    60,     0,
-      35,    61,     0,     0,     0,    37,     0,     0,     0,     0,
-       0,    62,    63,    64,   113,    10,    11,     0,     0,    47,
-      48,     9,     0,   477,     0,     0,    51,     0,     0,     0,
-       0,     0,     0,    55,     0,     0,     0,     0,     0,     0,
-       0,     0,     0,    35,     0,     0,    56,    57,    37,    58,
-      59,     0,     0,    60,     0,     0,    61,   113,     0,     0,
-       0,     0,    47,    48,     9,     0,    62,    63,    64,    51,
-      10,    11,     0,     0,     0,     0,    55,     0,     0,     0,
-       0,     0,     0,     0,     0,     0,     0,     0,     0,    56,
-      57,     0,    58,    59,     0,     0,    60,     0,    35,    61,
-       0,     0,     0,    37,     0,     0,     0,   590,     0,    62,
-      63,    64,   113,    10,    11,     0,     0,    47,    48,     9,
-       0,     0,     0,     0,    51,     0,     0,     0,     0,     0,
-       0,    55,     0,     0,     0,     0,     0,     0,     0,     0,
-       0,    35,     0,     0,    56,    57,    37,    58,    59,     0,
-       0,    60,     0,     0,    61,   113,     0,     0,     0,     0,
-      47,    48,     9,     0,    62,    63,    64,    51,    10,    11,
-       0,     0,     0,     0,   159,     0,     0,     0,     0,     0,
-       0,     0,     0,     0,    35,     0,     0,    56,    57,   285,
-      58,   160,     0,     0,    60,     0,     0,    61,   113,     0,
-       0,     0,     0,    47,    48,     9,     0,    62,    63,    64,
-      51,    10,    11,     0,     0,     0,     0,    55,     0,     0,
-       0,     0,     0,     0,     0,     0,     0,     0,     0,     0,
-      56,    57,    37,    58,    59,     0,     0,    60,     0,     0,
-      61,   113,     0,     0,     0,     0,    47,    48,     9,     0,
-      62,    63,    64,    51,    10,    11,     0,    37,     0,     0,
-     225,     0,     0,     0,     0,    37,   113,     0,   243,     0,
-       0,    47,    48,     9,   113,     0,     0,   115,    51,    47,
-      48,     9,     0,   226,     0,   225,    51,     0,     0,   292,
-       0,    37,     0,   225,     0,    64,     0,    10,    11,   283,
-     113,     0,   115,     0,     0,    47,    48,     9,   226,     0,
-     115,     0,    51,     0,     0,     0,   226,     0,    37,   225,
-      64,     0,    10,    11,   399,     0,     0,   113,    64,     0,
-      10,    11,    47,    48,     9,     0,   115,     0,     0,    51,
-       0,     0,   226,     0,    37,     0,   409,     0,     0,     0,
-       0,     0,   285,   113,    64,     0,    10,    11,    47,    48,
-       9,   113,     0,   115,     0,    51,    47,    48,     9,   410,
-       0,     0,   225,    51,     0,     0,     0,   336,     0,     0,
-     225,    64,     0,    10,    11,   336,   337,     0,   463,   115,
-       0,   338,   339,   544,   337,   480,     0,   115,   341,   338,
-     339,   340,     0,   226,     0,   342,   341,    64,     0,    10,
-      11,   336,     0,   342,     0,    64,     0,    10,    11,     0,
-     337,     0,   343,     0,     0,   338,   339,   340,     0,     0,
-     343,     0,   341,     0,     0,     0,     0,     0,     0,   342,
-     345,     0,    10,    11,     0,     0,     0,     0,   345,   178,
-       0,    11,     0,   181,   182,   183,   343,     0,   185,   186,
-     187,   188,   613,   190,   191,   192,   193,   194,   195,   196,
-     197,   198,     0,     0,   345,   177,   178,    11,   179,     0,
-     181,   182,   183,     0,     0,   185,   186,   187,   188,   189,
-     190,   191,   192,   193,   194,   195,   196,   197,   198,     0,
-       0,     0,     0,     0,     0,     0,     0,     0,   177,   178,
-       0,   179,     0,   181,   182,   183,     0,   437,   185,   186,
-     187,   188,   189,   190,   191,   192,   193,   194,   195,   196,
-     197,   198,     0,     0,     0,     0,     0,     0,   177,   178,
-       0,   179,     0,   181,   182,   183,     0,   434,   185,   186,
-     187,   188,   189,   190,   191,   192,   193,   194,   195,   196,
-     197,   198,   177,   178,     0,   179,     0,   181,   182,   183,
-       0,   527,   185,   186,   187,   188,   189,   190,   191,   192,
-     193,   194,   195,   196,   197,   198,   177,   178,     0,   179,
-       0,   181,   182,   183,     0,   661,   185,   186,   187,   188,
-     189,   190,   191,   192,   193,   194,   195,   196,   197,   198,
-     177,   178,     0,   179,     0,   181,   182,   183,     0,   662,
-     185,   186,   187,   188,   189,   190,   191,   192,   193,   194,
-     195,   196,   197,   198,   177,   178,     0,     0,     0,   181,
-     182,   183,     0,     0,   185,   186,   187,   188,   189,   190,
-     191,   192,   193,   194,   195,   196,   197,   198,   177,   178,
-       0,     0,     0,   181,   182,   183,     0,     0,   185,   186,
-     187,   188,     0,   190,   191,   192,   193,   194,   195,   196,
-     197,   198
-};
-
-static const yytype_int16 yycheck[] =
-{
-      37,    37,    61,   143,    67,    37,    37,   202,   380,   205,
-     224,   148,    61,   448,   144,   127,    28,   489,   456,    67,
-     127,   133,   252,   325,    61,   114,   115,   116,   136,    61,
-      31,   143,   323,    36,     3,    51,    39,   251,    11,     5,
-      24,   260,    45,    49,    35,   392,     7,    25,   137,    35,
-     269,    12,     5,   400,   265,   266,   145,    37,   277,     3,
-       1,    35,   281,   152,   318,     0,    24,    83,    59,    62,
-     324,     3,   291,    89,    25,    68,    67,   114,   115,   116,
-      24,    67,   114,   115,   116,    59,   175,     3,    24,    73,
-       1,   128,    24,    67,    35,    53,   128,    20,     3,    65,
-     137,    62,    75,    72,   576,   137,   107,    68,   145,    75,
-     173,   160,    65,   145,    62,   152,    60,   464,    59,    63,
-     152,   127,    75,   160,    35,   173,    67,    59,   160,    73,
-      74,    63,   600,   136,   114,   115,   116,   226,   175,   142,
-       7,    73,    74,   175,    67,    12,    62,    63,   128,   257,
-     441,   200,    68,    62,   243,     3,    67,   137,     3,    68,
-     507,     5,    24,   200,    21,   145,   601,    63,   200,    24,
-     608,   385,   152,   427,   646,   429,    24,   612,   613,    24,
-     391,    59,   393,    59,   273,    63,   654,   224,   656,   226,
-      62,     3,   224,    71,   226,   175,   285,    59,    74,   288,
-     289,    68,   208,   209,    62,    50,   243,     3,   245,   221,
-     440,   243,    24,   245,   251,    63,   563,   519,    71,   251,
-     416,    65,    66,     3,   526,    73,    74,   423,    73,    74,
-      62,    75,    67,   580,   581,    66,   273,     7,    50,    24,
-     435,   273,    12,    66,   224,   475,   226,    59,   285,   285,
-       7,   288,   289,   285,   285,    12,   288,   289,   605,   371,
-     319,    73,    74,   243,   371,   245,   480,   404,    24,   381,
-     319,   251,   402,   362,   381,    60,   282,    59,    59,   387,
-      74,    60,   319,    35,   212,    24,   292,   319,    73,    74,
-     218,   219,    62,   273,    59,   667,    75,    40,    68,    35,
-     389,    44,    40,   522,    60,   285,    44,    59,   288,   289,
-      24,    68,    24,    66,     9,    67,    24,    73,    74,    72,
-     409,   410,    17,    59,    64,   362,    21,    62,   377,    59,
-     362,    67,    63,   635,    73,    74,    31,    32,   375,    24,
-     377,   377,    59,   375,    67,   377,   377,    59,   385,   579,
-      24,    59,   389,   385,    24,    75,   419,   389,    60,   573,
-      68,    73,    74,   369,   370,    73,    74,    35,    53,    64,
-      62,   430,   409,   410,    59,    72,    68,   409,   410,    53,
-      62,   430,   362,    68,   387,    59,    68,    59,    73,    74,
-      60,    72,   395,   430,   590,   375,   399,   377,   430,    73,
-      74,   596,   408,    73,    74,   385,     3,    94,    95,   389,
-      97,    98,    60,     8,    60,   343,   422,    35,    95,    24,
-      97,    98,    62,   351,   473,    24,    75,    60,    62,   409,
-     410,    24,     5,    59,   523,    62,   473,   473,    24,    62,
-     489,   473,   473,   480,    72,     3,    62,    20,   480,    22,
-     499,    62,   489,   489,    59,    28,    65,   489,   489,   571,
-      59,    67,   499,    36,   571,    35,    39,   499,    73,    74,
-      43,    62,    45,    59,    73,    74,    65,    59,    66,    24,
-      53,    54,    67,    67,    71,     8,   523,    73,    74,    59,
-      65,   523,    60,   473,    67,    62,    62,    67,    62,    24,
-     480,    62,    35,    55,    56,    57,    58,    59,    60,   489,
-      62,    63,    60,    60,    59,   443,    60,    63,    35,    68,
-      60,   449,   450,   586,   452,   212,   666,   576,    73,    74,
-      68,   218,   219,   461,    59,   463,   573,    34,    60,   576,
-     576,   573,    59,   523,   576,   576,    60,    44,    73,    74,
-      67,    48,    60,    36,   666,   128,    53,    54,    55,    56,
-      75,    68,    75,   136,    60,     3,    60,   626,    60,   142,
-       8,   144,    60,    68,     3,   148,    62,   626,    60,    17,
-      60,    72,    75,    62,    22,    23,    24,    59,    66,   626,
-      60,    29,    60,   573,   626,    60,   576,   646,    62,    60,
-     173,    60,     8,    60,    59,    59,    59,   159,   160,   646,
-     646,    17,    68,    62,   646,   646,    22,    23,    24,    62,
-      72,    59,    68,    29,   552,    49,    62,    59,   201,    60,
-      36,    68,   560,    71,   207,    73,    74,    60,    68,    60,
-     213,    14,    62,    60,    72,    60,    60,    53,   221,   336,
-      60,   224,    68,     4,     5,    31,   343,    22,   647,    65,
-     586,   512,   235,   528,   351,    71,   646,   528,    74,   245,
-     283,    39,   214,   245,   395,   603,   604,   387,   251,   252,
-      22,   375,    33,    34,   160,    36,    37,    38,    39,    40,
-     499,    42,    43,    44,    45,    46,    47,    48,    49,    50,
-      51,    52,    53,    54,    55,    56,     8,   336,   466,   607,
-     283,    49,   444,   603,    65,    17,   336,   462,    -1,    -1,
-      22,    23,    24,    61,    75,    -1,    64,    29,   213,    -1,
-      -1,    -1,    -1,    -1,    36,    -1,    -1,    -1,    -1,    -1,
-       3,    -1,    -1,    -1,    -1,     8,    -1,    -1,    11,    -1,
-     323,    53,    -1,    -1,    17,    -1,   443,    59,    -1,    22,
-      23,    24,   449,   450,    -1,   452,    29,    -1,    -1,    71,
-      -1,   344,    74,    36,   461,    -1,   463,    -1,    -1,    -1,
-      -1,    -1,   355,    -1,    -1,    -1,    49,    50,    -1,    52,
-      53,    -1,    -1,    56,    -1,    -1,    59,    -1,    -1,    -1,
-      -1,    -1,   375,    -1,   377,    -1,    69,    70,    71,   382,
-      73,    74,   385,    -1,   387,    -1,    -1,    -1,    -1,    -1,
-      -1,    -1,   395,    -1,    -1,    -1,   399,    -1,    -1,   402,
-      -1,   404,    -1,    -1,    -1,    -1,    -1,    -1,   176,   177,
-     178,   179,    -1,   181,   182,   183,   419,   185,   186,   187,
-     188,   189,   190,   191,   192,   193,   194,   195,   196,   197,
-     198,    -1,   200,    -1,   202,   552,   204,   440,   441,    -1,
-     208,   209,   210,   560,    -1,   448,   449,    -1,   451,    -1,
-     567,    -1,    -1,   456,    -1,     3,    -1,    -1,    -1,   462,
-       8,    -1,   465,   466,    -1,    -1,    -1,    -1,   236,    17,
-      -1,    -1,   475,    -1,    22,    23,    24,   480,    26,    -1,
-      -1,    29,    -1,   600,    -1,    -1,   603,   604,    36,    -1,
-      -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,
-      -1,    49,    50,    -1,    52,    53,    -1,    -1,    56,    -1,
-      -1,    59,    -1,    -1,   282,    -1,    -1,    -1,    -1,    -1,
-      -1,    69,    70,    71,   292,    73,    74,     8,    -1,    -1,
-      -1,    -1,    -1,    -1,    -1,    -1,    17,   654,    -1,   656,
-      -1,    22,    23,    24,    -1,    -1,    -1,   315,    29,    -1,
-      -1,   319,     8,    -1,    -1,    36,    -1,   325,    -1,    -1,
-      -1,    17,    -1,    -1,    -1,    -1,    22,    23,    24,    -1,
-     573,    -1,    53,    29,    -1,    -1,   579,    -1,    59,    -1,
-      36,    -1,    -1,   586,    65,    -1,    -1,    -1,    -1,    -1,
-      71,    -1,    73,    74,    75,    -1,    -1,    53,   601,    -1,
-     603,   369,   370,    59,   607,   608,    -1,    -1,    -1,   612,
-     613,    -1,    -1,    -1,    -1,    71,    -1,    73,    74,     0,
-       1,    -1,     3,    -1,    -1,     6,    -1,     8,     9,    10,
-      -1,    -1,    13,    -1,    15,    16,    17,    18,    19,    20,
-     408,    22,    23,    24,    -1,    -1,    27,    28,    29,    30,
-      31,    32,    -1,    -1,   422,    36,    -1,    -1,    -1,    -1,
-      -1,    -1,   430,    -1,    -1,    -1,    -1,   435,    49,    50,
-      -1,    52,    53,    -1,    -1,    56,    -1,    -1,    59,    -1,
-      -1,    62,    -1,    -1,    34,    -1,    -1,    -1,    69,    70,
-      71,    -1,    73,    74,    44,    -1,    -1,    -1,    48,    49,
-      50,    51,    52,    53,    54,    55,    56,    -1,   476,   477,
-      -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,     1,    -1,
-       3,    -1,    -1,     6,     7,     8,     9,    10,    -1,    12,
-      13,   499,    15,    16,    17,    18,    19,    20,    -1,    22,
-      23,    24,    -1,    -1,    27,    28,    29,    30,    31,    32,
-      -1,   519,    -1,    36,    -1,    -1,    -1,    -1,   526,   527,
-     528,    -1,    -1,    -1,    -1,    -1,    49,    50,    -1,    52,
-      53,    -1,    -1,    56,    -1,    -1,    59,    -1,    -1,    62,
-      -1,    -1,    -1,    -1,    67,    68,    69,    70,    71,    -1,
-      73,    74,    -1,    -1,    -1,    -1,     1,    -1,     3,    -1,
-      -1,     6,    -1,     8,     9,    10,    -1,    -1,    13,    -1,
-      15,    16,    17,    18,    19,    20,    -1,    22,    23,    24,
-      -1,    -1,    27,    28,    29,    30,    31,    32,   596,    -1,
-      -1,    36,    -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,
-      -1,    -1,    -1,    -1,    49,    50,    -1,    52,    53,    -1,
-      -1,    56,    -1,    -1,    59,   623,   624,    62,   626,    -1,
-      -1,    -1,    67,    68,    69,    70,    71,   635,    73,    74,
-       3,    -1,    -1,    -1,    -1,     8,    -1,    -1,    -1,    -1,
-      -1,    -1,    -1,    -1,    17,    -1,     8,    -1,    -1,    22,
-      23,    24,    -1,    -1,    -1,    17,    29,    -1,    -1,    -1,
-      22,    23,    24,    36,    -1,    -1,    -1,    29,    -1,    -1,
-      -1,    -1,    -1,    -1,    36,    -1,    49,    50,    -1,    52,
-      53,    -1,    -1,    56,    -1,     3,    59,    60,    -1,    -1,
-       8,    53,    -1,    -1,    -1,    -1,    69,    70,    71,    17,
-      73,    74,    -1,    -1,    22,    23,    24,    -1,    -1,    71,
-      -1,    29,    74,    -1,    -1,    -1,    -1,    -1,    36,    -1,
-      -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,
-      -1,    49,    50,    -1,    52,    53,    -1,    -1,    56,    -1,
-       3,    59,    -1,    -1,    -1,     8,    -1,    -1,    -1,    67,
-      -1,    69,    70,    71,    17,    73,    74,    -1,    -1,    22,
-      23,    24,    -1,    -1,    -1,    -1,    29,    -1,    31,    -1,
-      -1,    -1,    -1,    36,    -1,    -1,    -1,    -1,    -1,    -1,
-      -1,    -1,    -1,    -1,    -1,    -1,    49,    50,    -1,    52,
-      53,    -1,    -1,    56,    -1,     3,    59,    -1,    -1,    -1,
-       8,    -1,    -1,    -1,    -1,    -1,    69,    70,    71,    17,
-      73,    74,    -1,    -1,    22,    23,    24,    -1,    26,    -1,
-      -1,    29,    -1,    -1,    -1,    -1,    -1,    -1,    36,    -1,
-      -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,
-      -1,    49,    50,    -1,    52,    53,    -1,    -1,    56,    -1,
-       3,    59,    -1,    -1,    -1,     8,    -1,    -1,    -1,    -1,
-      -1,    69,    70,    71,    17,    73,    74,    -1,    -1,    22,
-      23,    24,    -1,    26,    -1,    -1,    29,    -1,    -1,    -1,
-      -1,    -1,    -1,    36,    -1,    -1,    -1,    -1,    -1,    -1,
-      -1,    -1,    -1,     3,    -1,    -1,    49,    50,     8,    52,
-      53,    -1,    -1,    56,    -1,    -1,    59,    17,    -1,    -1,
-      -1,    -1,    22,    23,    24,    -1,    69,    70,    71,    29,
-      73,    74,    -1,    -1,    -1,    -1,    36,    -1,    -1,    -1,
-      -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,    49,
-      50,    -1,    52,    53,    -1,    -1,    56,    -1,     3,    59,
-      -1,    -1,    -1,     8,    -1,    -1,    -1,    67,    -1,    69,
-      70,    71,    17,    73,    74,    -1,    -1,    22,    23,    24,
-      -1,    -1,    -1,    -1,    29,    -1,    -1,    -1,    -1,    -1,
-      -1,    36,    -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,
-      -1,     3,    -1,    -1,    49,    50,     8,    52,    53,    -1,
-      -1,    56,    -1,    -1,    59,    17,    -1,    -1,    -1,    -1,
-      22,    23,    24,    -1,    69,    70,    71,    29,    73,    74,
-      -1,    -1,    -1,    -1,    36,    -1,    -1,    -1,    -1,    -1,
-      -1,    -1,    -1,    -1,     3,    -1,    -1,    49,    50,     8,
-      52,    53,    -1,    -1,    56,    -1,    -1,    59,    17,    -1,
-      -1,    -1,    -1,    22,    23,    24,    -1,    69,    70,    71,
-      29,    73,    74,    -1,    -1,    -1,    -1,    36,    -1,    -1,
-      -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,
-      49,    50,     8,    52,    53,    -1,    -1,    56,    -1,    -1,
-      59,    17,    -1,    -1,    -1,    -1,    22,    23,    24,    -1,
-      69,    70,    71,    29,    73,    74,    -1,     8,    -1,    -1,
-      36,    -1,    -1,    -1,    -1,     8,    17,    -1,    11,    -1,
-      -1,    22,    23,    24,    17,    -1,    -1,    53,    29,    22,
-      23,    24,    -1,    59,    -1,    36,    29,    -1,    -1,    65,
-      -1,     8,    -1,    36,    -1,    71,    -1,    73,    74,    75,
-      17,    -1,    53,    -1,    -1,    22,    23,    24,    59,    -1,
-      53,    -1,    29,    -1,    -1,    -1,    59,    -1,     8,    36,
-      71,    -1,    73,    74,    75,    -1,    -1,    17,    71,    -1,
-      73,    74,    22,    23,    24,    -1,    53,    -1,    -1,    29,
-      -1,    -1,    59,    -1,     8,    -1,    36,    -1,    -1,    -1,
-      -1,    -1,     8,    17,    71,    -1,    73,    74,    22,    23,
-      24,    17,    -1,    53,    -1,    29,    22,    23,    24,    59,
-      -1,    -1,    36,    29,    -1,    -1,    -1,     8,    -1,    -1,
-      36,    71,    -1,    73,    74,     8,    17,    -1,    11,    53,
-      -1,    22,    23,    24,    17,    59,    -1,    53,    29,    22,
-      23,    24,    -1,    59,    -1,    36,    29,    71,    -1,    73,
-      74,     8,    -1,    36,    -1,    71,    -1,    73,    74,    -1,
-      17,    -1,    53,    -1,    -1,    22,    23,    24,    -1,    -1,
-      53,    -1,    29,    -1,    -1,    -1,    -1,    -1,    -1,    36,
-      71,    -1,    73,    74,    -1,    -1,    -1,    -1,    71,    34,
-      -1,    74,    -1,    38,    39,    40,    53,    -1,    43,    44,
-      45,    46,    59,    48,    49,    50,    51,    52,    53,    54,
-      55,    56,    -1,    -1,    71,    33,    34,    74,    36,    -1,
-      38,    39,    40,    -1,    -1,    43,    44,    45,    46,    47,
-      48,    49,    50,    51,    52,    53,    54,    55,    56,    -1,
-      -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,    33,    34,
-      -1,    36,    -1,    38,    39,    40,    -1,    75,    43,    44,
-      45,    46,    47,    48,    49,    50,    51,    52,    53,    54,
-      55,    56,    -1,    -1,    -1,    -1,    -1,    -1,    33,    34,
-      -1,    36,    -1,    38,    39,    40,    -1,    72,    43,    44,
-      45,    46,    47,    48,    49,    50,    51,    52,    53,    54,
-      55,    56,    33,    34,    -1,    36,    -1,    38,    39,    40,
-      -1,    66,    43,    44,    45,    46,    47,    48,    49,    50,
-      51,    52,    53,    54,    55,    56,    33,    34,    -1,    36,
-      -1,    38,    39,    40,    -1,    66,    43,    44,    45,    46,
-      47,    48,    49,    50,    51,    52,    53,    54,    55,    56,
-      33,    34,    -1,    36,    -1,    38,    39,    40,    -1,    66,
-      43,    44,    45,    46,    47,    48,    49,    50,    51,    52,
-      53,    54,    55,    56,    33,    34,    -1,    -1,    -1,    38,
-      39,    40,    -1,    -1,    43,    44,    45,    46,    47,    48,
-      49,    50,    51,    52,    53,    54,    55,    56,    33,    34,
-      -1,    -1,    -1,    38,    39,    40,    -1,    -1,    43,    44,
-      45,    46,    -1,    48,    49,    50,    51,    52,    53,    54,
-      55,    56
-};
-
-/* YYSTOS[STATE-NUM] -- The (internal number of the) accessing
-   symbol of state STATE-NUM.  */
-static const yytype_uint8 yystos[] =
-{
-       0,    77,    79,    80,     0,    25,    78,    25,    86,    24,
-      73,    74,   141,   142,    81,    24,    88,    89,     3,    62,
-      21,    82,   166,    24,    87,   214,    63,     3,    59,    63,
-      83,    85,   141,    62,     1,     3,     6,     8,     9,    10,
-      13,    15,    16,    17,    18,    19,    20,    22,    23,    27,
-      28,    29,    30,    31,    32,    36,    49,    50,    52,    53,
-      56,    59,    69,    70,    71,    90,    91,    92,    98,   110,
-     113,   121,   124,   126,   127,   128,   129,   134,   138,   141,
-     143,   144,   149,   150,   153,   156,   157,   158,   161,   164,
-     165,   181,   186,    62,     9,    17,    21,    31,    32,    64,
-     199,    24,    73,    60,    83,    84,     3,    86,    88,     3,
-     138,   140,   141,    17,    36,    53,    59,   141,   143,   148,
-     152,   153,   154,   161,   140,   128,   134,   111,    59,   141,
-     159,   128,   138,   114,    35,    67,   137,    71,   126,   186,
-     193,   125,   137,   122,    59,    96,    97,   141,    59,    93,
-     139,   141,   185,   127,   127,   127,   127,   127,   127,    36,
-      53,   126,   135,   147,   153,   155,   161,   127,   127,    11,
-     126,   192,    62,    59,    94,   185,     4,    33,    34,    36,
-      37,    38,    39,    40,    42,    43,    44,    45,    46,    47,
-      48,    49,    50,    51,    52,    53,    54,    55,    56,    67,
-      59,    63,    71,    66,    59,   137,     1,   137,     5,    65,
-      75,   142,   200,    59,   160,   200,    24,   200,   201,   200,
-      64,    62,   190,    88,    59,    36,    59,   146,   152,   153,
-     154,   155,   161,   146,   146,    63,    26,    98,   107,   108,
-     109,   186,   194,    11,   136,   141,   145,   146,   177,   178,
-     179,    59,    67,   162,   112,   194,    24,    59,    68,   138,
-     171,   173,   175,   146,    35,    53,    59,    68,   138,   170,
-     172,   173,   174,   184,   112,    60,    97,   169,   146,    60,
-      93,   167,    65,    75,   146,     8,   147,    60,    72,    72,
-      60,    94,    65,   146,   126,   126,   126,   126,   126,   126,
-     126,   126,   126,   126,   126,   126,   126,   126,   126,   126,
-     126,   126,   126,   126,   126,   130,    60,   135,   187,    59,
-     141,   126,   192,   182,   126,   130,     1,    67,    91,   100,
-     180,   181,   183,   186,   186,   126,     8,    17,    22,    23,
-      24,    29,    36,    53,    65,    71,   142,   202,   204,   205,
-     206,   141,   207,   215,   162,    59,     3,   202,   202,    83,
-      60,   179,     8,   146,    60,   141,   126,    35,   105,     5,
-      65,    62,   146,   136,   145,    75,   191,    60,   179,   183,
-     115,    62,    63,    24,   173,    59,   176,    62,   190,    72,
-     104,    59,   174,    53,   174,    62,   190,     3,   198,    75,
-     146,   123,    62,   190,    62,   190,   186,   139,    65,    36,
-      59,   146,   152,   153,   154,   161,    67,   146,   146,    62,
-     190,   186,    65,    67,   126,   131,   132,   188,   189,    11,
-      75,   191,    31,   135,    72,    66,   180,    75,   191,   189,
-     101,    62,    68,    36,    59,   203,   204,   206,    59,    67,
-      71,    67,     8,   202,     3,    50,    59,   141,   212,   213,
-       3,    72,    65,    11,   202,    60,    75,    62,   195,   215,
-      62,    62,    62,    60,    60,   106,    26,    26,   194,   177,
-      59,   141,   151,   152,   153,   154,   155,   161,   163,    60,
-      68,   105,   194,   141,    60,   179,   175,    68,   146,     7,
-      12,    68,    99,   102,   174,   198,   174,    60,   172,    68,
-     138,   198,    35,    97,    60,    93,    60,   186,   146,   130,
-      94,    95,   168,   185,    60,   186,   130,    66,    75,   191,
-      68,   191,   135,    60,    60,    60,   192,    60,    68,   183,
-     180,   202,   205,   195,    24,   141,   142,   197,   202,   209,
-     217,   202,   141,   196,   208,   216,   202,     3,   212,    62,
-      72,   202,   213,   202,   198,   141,   207,    60,   183,   126,
-     126,    62,   179,    59,   163,   116,    60,   187,    66,   103,
-      60,    60,   198,   104,    60,   189,    62,   190,   146,   189,
-      67,   126,   133,   131,   132,    60,    66,    72,    68,    60,
-      60,    59,    68,    62,    72,   202,    68,    62,    49,   202,
-      62,   198,    59,    59,   202,   210,   211,    68,   194,    60,
-     179,   119,   163,     5,    65,    66,    75,   183,   198,   198,
-      68,    68,    95,    60,    68,   130,   192,   210,   195,   209,
-     202,   198,   208,   212,   195,   195,    60,    14,   117,   120,
-     126,   126,   189,    72,    60,    60,    60,    60,   163,    20,
-     100,    66,    66,    68,   210,   210,   118,   112,   105
-};
-
-#define yyerrok                (yyerrstatus = 0)
-#define yyclearin      (yychar = YYEMPTY)
-#define YYEMPTY                (-2)
-#define YYEOF          0
-
-#define YYACCEPT       goto yyacceptlab
-#define YYABORT                goto yyabortlab
-#define YYERROR                goto yyerrorlab
-
-
-/* Like YYERROR except do call yyerror.  This remains here temporarily
-   to ease the transition to the new meaning of YYERROR, for GCC.
-   Once GCC version 2 has supplanted version 1, this can go.  */
-
-#define YYFAIL         goto yyerrlab
-
-#define YYRECOVERING()  (!!yyerrstatus)
-
-#define YYBACKUP(Token, Value)                                 \
-do                                                             \
-  if (yychar == YYEMPTY && yylen == 1)                         \
-    {                                                          \
-      yychar = (Token);                                                \
-      yylval = (Value);                                                \
-      yytoken = YYTRANSLATE (yychar);                          \
-      YYPOPSTACK (1);                                          \
-      goto yybackup;                                           \
-    }                                                          \
-  else                                                         \
-    {                                                          \
-      yyerror (YY_("syntax error: cannot back up")); \
-      YYERROR;                                                 \
-    }                                                          \
-while (YYID (0))
-
-
-#define YYTERROR       1
-#define YYERRCODE      256
-
-
-/* YYLLOC_DEFAULT -- Set CURRENT to span from RHS[1] to RHS[N].
-   If N is 0, then set CURRENT to the empty location which ends
-   the previous symbol: RHS[0] (always defined).  */
-
-#define YYRHSLOC(Rhs, K) ((Rhs)[K])
-#ifndef YYLLOC_DEFAULT
-# define YYLLOC_DEFAULT(Current, Rhs, N)                               \
-    do                                                                 \
-      if (YYID (N))                                                    \
-       {                                                               \
-         (Current).first_line   = YYRHSLOC (Rhs, 1).first_line;        \
-         (Current).first_column = YYRHSLOC (Rhs, 1).first_column;      \
-         (Current).last_line    = YYRHSLOC (Rhs, N).last_line;         \
-         (Current).last_column  = YYRHSLOC (Rhs, N).last_column;       \
-       }                                                               \
-      else                                                             \
-       {                                                               \
-         (Current).first_line   = (Current).last_line   =              \
-           YYRHSLOC (Rhs, 0).last_line;                                \
-         (Current).first_column = (Current).last_column =              \
-           YYRHSLOC (Rhs, 0).last_column;                              \
-       }                                                               \
-    while (YYID (0))
-#endif
-
-
-/* YY_LOCATION_PRINT -- Print the location on the stream.
-   This macro was not mandated originally: define only if we know
-   we won't break user code: when these are the locations we know.  */
-
-#ifndef YY_LOCATION_PRINT
-# if defined YYLTYPE_IS_TRIVIAL && YYLTYPE_IS_TRIVIAL
-#  define YY_LOCATION_PRINT(File, Loc)                 \
-     fprintf (File, "%d.%d-%d.%d",                     \
-             (Loc).first_line, (Loc).first_column,     \
-             (Loc).last_line,  (Loc).last_column)
-# else
-#  define YY_LOCATION_PRINT(File, Loc) ((void) 0)
-# endif
-#endif
-
-
-/* YYLEX -- calling `yylex' with the right arguments.  */
-
-#ifdef YYLEX_PARAM
-# define YYLEX yylex (YYLEX_PARAM)
-#else
-# define YYLEX yylex ()
-#endif
-
-/* Enable debugging if requested.  */
-#if YYDEBUG
-
-# ifndef YYFPRINTF
-#  include <stdio.h> /* INFRINGES ON USER NAME SPACE */
-#  define YYFPRINTF fprintf
-# endif
-
-# define YYDPRINTF(Args)                       \
-do {                                           \
-  if (yydebug)                                 \
-    YYFPRINTF Args;                            \
-} while (YYID (0))
-
-# define YY_SYMBOL_PRINT(Title, Type, Value, Location)                   \
-do {                                                                     \
-  if (yydebug)                                                           \
-    {                                                                    \
-      YYFPRINTF (stderr, "%s ", Title);                                          \
-      yy_symbol_print (stderr,                                           \
-                 Type, Value); \
-      YYFPRINTF (stderr, "\n");                                                  \
-    }                                                                    \
-} while (YYID (0))
-
-
-/*--------------------------------.
-| Print this symbol on YYOUTPUT.  |
-`--------------------------------*/
-
-/*ARGSUSED*/
-#if (defined __STDC__ || defined __C99__FUNC__ \
-     || defined __cplusplus || defined _MSC_VER)
-static void
-yy_symbol_value_print (FILE *yyoutput, int yytype, YYSTYPE const * const yyvaluep)
-#else
-static void
-yy_symbol_value_print (yyoutput, yytype, yyvaluep)
-    FILE *yyoutput;
-    int yytype;
-    YYSTYPE const * const yyvaluep;
-#endif
-{
-  if (!yyvaluep)
-    return;
-# ifdef YYPRINT
-  if (yytype < YYNTOKENS)
-    YYPRINT (yyoutput, yytoknum[yytype], *yyvaluep);
-# else
-  YYUSE (yyoutput);
-# endif
-  switch (yytype)
-    {
-      default:
-       break;
-    }
-}
-
-
-/*--------------------------------.
-| Print this symbol on YYOUTPUT.  |
-`--------------------------------*/
-
-#if (defined __STDC__ || defined __C99__FUNC__ \
-     || defined __cplusplus || defined _MSC_VER)
-static void
-yy_symbol_print (FILE *yyoutput, int yytype, YYSTYPE const * const yyvaluep)
-#else
-static void
-yy_symbol_print (yyoutput, yytype, yyvaluep)
-    FILE *yyoutput;
-    int yytype;
-    YYSTYPE const * const yyvaluep;
-#endif
-{
-  if (yytype < YYNTOKENS)
-    YYFPRINTF (yyoutput, "token %s (", yytname[yytype]);
-  else
-    YYFPRINTF (yyoutput, "nterm %s (", yytname[yytype]);
-
-  yy_symbol_value_print (yyoutput, yytype, yyvaluep);
-  YYFPRINTF (yyoutput, ")");
-}
-
-/*------------------------------------------------------------------.
-| yy_stack_print -- Print the state stack from its BOTTOM up to its |
-| TOP (included).                                                   |
-`------------------------------------------------------------------*/
-
-#if (defined __STDC__ || defined __C99__FUNC__ \
-     || defined __cplusplus || defined _MSC_VER)
-static void
-yy_stack_print (yytype_int16 *bottom, yytype_int16 *top)
-#else
-static void
-yy_stack_print (bottom, top)
-    yytype_int16 *bottom;
-    yytype_int16 *top;
-#endif
-{
-  YYFPRINTF (stderr, "Stack now");
-  for (; bottom <= top; ++bottom)
-    YYFPRINTF (stderr, " %d", *bottom);
-  YYFPRINTF (stderr, "\n");
-}
-
-# define YY_STACK_PRINT(Bottom, Top)                           \
-do {                                                           \
-  if (yydebug)                                                 \
-    yy_stack_print ((Bottom), (Top));                          \
-} while (YYID (0))
-
-
-/*------------------------------------------------.
-| Report that the YYRULE is going to be reduced.  |
-`------------------------------------------------*/
-
-#if (defined __STDC__ || defined __C99__FUNC__ \
-     || defined __cplusplus || defined _MSC_VER)
-static void
-yy_reduce_print (YYSTYPE *yyvsp, int yyrule)
-#else
-static void
-yy_reduce_print (yyvsp, yyrule)
-    YYSTYPE *yyvsp;
-    int yyrule;
-#endif
-{
-  int yynrhs = yyr2[yyrule];
-  int yyi;
-  unsigned long int yylno = yyrline[yyrule];
-  YYFPRINTF (stderr, "Reducing stack by rule %d (line %lu):\n",
-            yyrule - 1, yylno);
-  /* The symbols being reduced.  */
-  for (yyi = 0; yyi < yynrhs; yyi++)
-    {
-      fprintf (stderr, "   $%d = ", yyi + 1);
-      yy_symbol_print (stderr, yyrhs[yyprhs[yyrule] + yyi],
-                      &(yyvsp[(yyi + 1) - (yynrhs)])
-                                      );
-      fprintf (stderr, "\n");
-    }
-}
-
-# define YY_REDUCE_PRINT(Rule)         \
-do {                                   \
-  if (yydebug)                         \
-    yy_reduce_print (yyvsp, Rule); \
-} while (YYID (0))
-
-/* Nonzero means print parse trace.  It is left uninitialized so that
-   multiple parsers can coexist.  */
-int yydebug;
-#else /* !YYDEBUG */
-# define YYDPRINTF(Args)
-# define YY_SYMBOL_PRINT(Title, Type, Value, Location)
-# define YY_STACK_PRINT(Bottom, Top)
-# define YY_REDUCE_PRINT(Rule)
-#endif /* !YYDEBUG */
-
-
-/* YYINITDEPTH -- initial size of the parser's stacks.  */
-#ifndef        YYINITDEPTH
-# define YYINITDEPTH 200
-#endif
-
-/* YYMAXDEPTH -- maximum size the stacks can grow to (effective only
-   if the built-in stack extension method is used).
-
-   Do not make this value too large; the results are undefined if
-   YYSTACK_ALLOC_MAXIMUM < YYSTACK_BYTES (YYMAXDEPTH)
-   evaluated with infinite-precision integer arithmetic.  */
-
-#ifndef YYMAXDEPTH
-# define YYMAXDEPTH 10000
-#endif
-
-\f
-
-#if YYERROR_VERBOSE
-
-# ifndef yystrlen
-#  if defined __GLIBC__ && defined _STRING_H
-#   define yystrlen strlen
-#  else
-/* Return the length of YYSTR.  */
-#if (defined __STDC__ || defined __C99__FUNC__ \
-     || defined __cplusplus || defined _MSC_VER)
-static YYSIZE_T
-yystrlen (const char *yystr)
-#else
-static YYSIZE_T
-yystrlen (yystr)
-    const char *yystr;
-#endif
-{
-  YYSIZE_T yylen;
-  for (yylen = 0; yystr[yylen]; yylen++)
-    continue;
-  return yylen;
-}
-#  endif
-# endif
-
-# ifndef yystpcpy
-#  if defined __GLIBC__ && defined _STRING_H && defined _GNU_SOURCE
-#   define yystpcpy stpcpy
-#  else
-/* Copy YYSRC to YYDEST, returning the address of the terminating '\0' in
-   YYDEST.  */
-#if (defined __STDC__ || defined __C99__FUNC__ \
-     || defined __cplusplus || defined _MSC_VER)
-static char *
-yystpcpy (char *yydest, const char *yysrc)
-#else
-static char *
-yystpcpy (yydest, yysrc)
-    char *yydest;
-    const char *yysrc;
-#endif
-{
-  char *yyd = yydest;
-  const char *yys = yysrc;
-
-  while ((*yyd++ = *yys++) != '\0')
-    continue;
-
-  return yyd - 1;
-}
-#  endif
-# endif
-
-# ifndef yytnamerr
-/* Copy to YYRES the contents of YYSTR after stripping away unnecessary
-   quotes and backslashes, so that it's suitable for yyerror.  The
-   heuristic is that double-quoting is unnecessary unless the string
-   contains an apostrophe, a comma, or backslash (other than
-   backslash-backslash).  YYSTR is taken from yytname.  If YYRES is
-   null, do not copy; instead, return the length of what the result
-   would have been.  */
-static YYSIZE_T
-yytnamerr (char *yyres, const char *yystr)
-{
-  if (*yystr == '"')
-    {
-      YYSIZE_T yyn = 0;
-      char const *yyp = yystr;
-
-      for (;;)
-       switch (*++yyp)
-         {
-         case '\'':
-         case ',':
-           goto do_not_strip_quotes;
-
-         case '\\':
-           if (*++yyp != '\\')
-             goto do_not_strip_quotes;
-           /* Fall through.  */
-         default:
-           if (yyres)
-             yyres[yyn] = *yyp;
-           yyn++;
-           break;
-
-         case '"':
-           if (yyres)
-             yyres[yyn] = '\0';
-           return yyn;
-         }
-    do_not_strip_quotes: ;
-    }
-
-  if (! yyres)
-    return yystrlen (yystr);
-
-  return yystpcpy (yyres, yystr) - yyres;
-}
-# endif
-
-/* Copy into YYRESULT an error message about the unexpected token
-   YYCHAR while in state YYSTATE.  Return the number of bytes copied,
-   including the terminating null byte.  If YYRESULT is null, do not
-   copy anything; just return the number of bytes that would be
-   copied.  As a special case, return 0 if an ordinary "syntax error"
-   message will do.  Return YYSIZE_MAXIMUM if overflow occurs during
-   size calculation.  */
-static YYSIZE_T
-yysyntax_error (char *yyresult, int yystate, int yychar)
-{
-  int yyn = yypact[yystate];
-
-  if (! (YYPACT_NINF < yyn && yyn <= YYLAST))
-    return 0;
-  else
-    {
-      int yytype = YYTRANSLATE (yychar);
-      YYSIZE_T yysize0 = yytnamerr (0, yytname[yytype]);
-      YYSIZE_T yysize = yysize0;
-      YYSIZE_T yysize1;
-      int yysize_overflow = 0;
-      enum { YYERROR_VERBOSE_ARGS_MAXIMUM = 5 };
-      char const *yyarg[YYERROR_VERBOSE_ARGS_MAXIMUM];
-      int yyx;
-
-# if 0
-      /* This is so xgettext sees the translatable formats that are
-        constructed on the fly.  */
-      YY_("syntax error, unexpected %s");
-      YY_("syntax error, unexpected %s, expecting %s");
-      YY_("syntax error, unexpected %s, expecting %s or %s");
-      YY_("syntax error, unexpected %s, expecting %s or %s or %s");
-      YY_("syntax error, unexpected %s, expecting %s or %s or %s or %s");
-# endif
-      char *yyfmt;
-      char const *yyf;
-      static char const yyunexpected[] = "syntax error, unexpected %s";
-      static char const yyexpecting[] = ", expecting %s";
-      static char const yyor[] = " or %s";
-      char yyformat[sizeof yyunexpected
-                   + sizeof yyexpecting - 1
-                   + ((YYERROR_VERBOSE_ARGS_MAXIMUM - 2)
-                      * (sizeof yyor - 1))];
-      char const *yyprefix = yyexpecting;
-
-      /* Start YYX at -YYN if negative to avoid negative indexes in
-        YYCHECK.  */
-      int yyxbegin = yyn < 0 ? -yyn : 0;
-
-      /* Stay within bounds of both yycheck and yytname.  */
-      int yychecklim = YYLAST - yyn + 1;
-      int yyxend = yychecklim < YYNTOKENS ? yychecklim : YYNTOKENS;
-      int yycount = 1;
-
-      yyarg[0] = yytname[yytype];
-      yyfmt = yystpcpy (yyformat, yyunexpected);
-
-      for (yyx = yyxbegin; yyx < yyxend; ++yyx)
-       if (yycheck[yyx + yyn] == yyx && yyx != YYTERROR)
-         {
-           if (yycount == YYERROR_VERBOSE_ARGS_MAXIMUM)
-             {
-               yycount = 1;
-               yysize = yysize0;
-               yyformat[sizeof yyunexpected - 1] = '\0';
-               break;
-             }
-           yyarg[yycount++] = yytname[yyx];
-           yysize1 = yysize + yytnamerr (0, yytname[yyx]);
-           yysize_overflow |= (yysize1 < yysize);
-           yysize = yysize1;
-           yyfmt = yystpcpy (yyfmt, yyprefix);
-           yyprefix = yyor;
-         }
-
-      yyf = YY_(yyformat);
-      yysize1 = yysize + yystrlen (yyf);
-      yysize_overflow |= (yysize1 < yysize);
-      yysize = yysize1;
-
-      if (yysize_overflow)
-       return YYSIZE_MAXIMUM;
-
-      if (yyresult)
-       {
-         /* Avoid sprintf, as that infringes on the user's name space.
-            Don't have undefined behavior even if the translation
-            produced a string with the wrong number of "%s"s.  */
-         char *yyp = yyresult;
-         int yyi = 0;
-         while ((*yyp = *yyf) != '\0')
-           {
-             if (*yyp == '%' && yyf[1] == 's' && yyi < yycount)
-               {
-                 yyp += yytnamerr (yyp, yyarg[yyi++]);
-                 yyf += 2;
-               }
-             else
-               {
-                 yyp++;
-                 yyf++;
-               }
-           }
-       }
-      return yysize;
-    }
-}
-#endif /* YYERROR_VERBOSE */
-\f
-
-/*-----------------------------------------------.
-| Release the memory associated to this symbol.  |
-`-----------------------------------------------*/
-
-/*ARGSUSED*/
-#if (defined __STDC__ || defined __C99__FUNC__ \
-     || defined __cplusplus || defined _MSC_VER)
-static void
-yydestruct (const char *yymsg, int yytype, YYSTYPE *yyvaluep)
-#else
-static void
-yydestruct (yymsg, yytype, yyvaluep)
-    const char *yymsg;
-    int yytype;
-    YYSTYPE *yyvaluep;
-#endif
-{
-  YYUSE (yyvaluep);
-
-  if (!yymsg)
-    yymsg = "Deleting";
-  YY_SYMBOL_PRINT (yymsg, yytype, yyvaluep, yylocationp);
-
-  switch (yytype)
-    {
-
-      default:
-       break;
-    }
-}
-\f
-
-/* Prevent warnings from -Wmissing-prototypes.  */
-
-#ifdef YYPARSE_PARAM
-#if defined __STDC__ || defined __cplusplus
-int yyparse (void *YYPARSE_PARAM);
-#else
-int yyparse ();
-#endif
-#else /* ! YYPARSE_PARAM */
-#if defined __STDC__ || defined __cplusplus
-int yyparse (void);
-#else
-int yyparse ();
-#endif
-#endif /* ! YYPARSE_PARAM */
-
-
-
-/* The look-ahead symbol.  */
-int yychar, yystate;
-
-/* The semantic value of the look-ahead symbol.  */
-YYSTYPE yylval;
-
-/* Number of syntax errors so far.  */
-int yynerrs;
-
-
-
-/*----------.
-| yyparse.  |
-`----------*/
-
-#ifdef YYPARSE_PARAM
-#if (defined __STDC__ || defined __C99__FUNC__ \
-     || defined __cplusplus || defined _MSC_VER)
-int
-yyparse (void *YYPARSE_PARAM)
-#else
-int
-yyparse (YYPARSE_PARAM)
-    void *YYPARSE_PARAM;
-#endif
-#else /* ! YYPARSE_PARAM */
-#if (defined __STDC__ || defined __C99__FUNC__ \
-     || defined __cplusplus || defined _MSC_VER)
-int
-yyparse (void)
-#else
-int
-yyparse ()
-
-#endif
-#endif
-{
-  
-  int yyn;
-  int yyresult;
-  /* Number of tokens to shift before error messages enabled.  */
-  int yyerrstatus;
-  /* Look-ahead token as an internal (translated) token number.  */
-  int yytoken = 0;
-#if YYERROR_VERBOSE
-  /* Buffer for error messages, and its allocated size.  */
-  char yymsgbuf[128];
-  char *yymsg = yymsgbuf;
-  YYSIZE_T yymsg_alloc = sizeof yymsgbuf;
-#endif
-
-  /* Three stacks and their tools:
-     `yyss': related to states,
-     `yyvs': related to semantic values,
-     `yyls': related to locations.
-
-     Refer to the stacks thru separate pointers, to allow yyoverflow
-     to reallocate them elsewhere.  */
-
-  /* The state stack.  */
-  yytype_int16 yyssa[YYINITDEPTH];
-  yytype_int16 *yyss = yyssa;
-  yytype_int16 *yyssp;
-
-  /* The semantic value stack.  */
-  YYSTYPE yyvsa[YYINITDEPTH];
-  YYSTYPE *yyvs = yyvsa;
-  YYSTYPE *yyvsp;
-
-
-
-#define YYPOPSTACK(N)   (yyvsp -= (N), yyssp -= (N))
-
-  YYSIZE_T yystacksize = YYINITDEPTH;
-
-  /* The variables used to return semantic value and location from the
-     action routines.  */
-  YYSTYPE yyval;
-
-
-  /* The number of symbols on the RHS of the reduced rule.
-     Keep to zero when no symbol should be popped.  */
-  int yylen = 0;
-
-  YYDPRINTF ((stderr, "Starting parse\n"));
-
-  yystate = 0;
-  yyerrstatus = 0;
-  yynerrs = 0;
-  yychar = YYEMPTY;            /* Cause a token to be read.  */
-
-  /* Initialize stack pointers.
-     Waste one element of value and location stack
-     so that they stay on the same level as the state stack.
-     The wasted elements are never initialized.  */
-
-  yyssp = yyss;
-  yyvsp = yyvs;
-
-  goto yysetstate;
-
-/*------------------------------------------------------------.
-| yynewstate -- Push a new state, which is found in yystate.  |
-`------------------------------------------------------------*/
- yynewstate:
-  /* In all cases, when you get here, the value and location stacks
-     have just been pushed.  So pushing a state here evens the stacks.  */
-  yyssp++;
-
- yysetstate:
-  *yyssp = yystate;
-
-  if (yyss + yystacksize - 1 <= yyssp)
-    {
-      /* Get the current used size of the three stacks, in elements.  */
-      YYSIZE_T yysize = yyssp - yyss + 1;
-
-#ifdef yyoverflow
-      {
-       /* Give user a chance to reallocate the stack.  Use copies of
-          these so that the &'s don't force the real ones into
-          memory.  */
-       YYSTYPE *yyvs1 = yyvs;
-       yytype_int16 *yyss1 = yyss;
-
-
-       /* Each stack pointer address is followed by the size of the
-          data in use in that stack, in bytes.  This used to be a
-          conditional around just the two extra args, but that might
-          be undefined if yyoverflow is a macro.  */
-       yyoverflow (YY_("memory exhausted"),
-                   &yyss1, yysize * sizeof (*yyssp),
-                   &yyvs1, yysize * sizeof (*yyvsp),
-
-                   &yystacksize);
-
-       yyss = yyss1;
-       yyvs = yyvs1;
-      }
-#else /* no yyoverflow */
-# ifndef YYSTACK_RELOCATE
-      goto yyexhaustedlab;
-# else
-      /* Extend the stack our own way.  */
-      if (YYMAXDEPTH <= yystacksize)
-       goto yyexhaustedlab;
-      yystacksize *= 2;
-      if (YYMAXDEPTH < yystacksize)
-       yystacksize = YYMAXDEPTH;
-
-      {
-       yytype_int16 *yyss1 = yyss;
-       union yyalloc *yyptr =
-         (union yyalloc *) YYSTACK_ALLOC (YYSTACK_BYTES (yystacksize));
-       if (! yyptr)
-         goto yyexhaustedlab;
-       YYSTACK_RELOCATE (yyss);
-       YYSTACK_RELOCATE (yyvs);
-
-#  undef YYSTACK_RELOCATE
-       if (yyss1 != yyssa)
-         YYSTACK_FREE (yyss1);
-      }
-# endif
-#endif /* no yyoverflow */
-
-      yyssp = yyss + yysize - 1;
-      yyvsp = yyvs + yysize - 1;
-
-
-      YYDPRINTF ((stderr, "Stack size increased to %lu\n",
-                 (unsigned long int) yystacksize));
-
-      if (yyss + yystacksize - 1 <= yyssp)
-       YYABORT;
-    }
-
-  YYDPRINTF ((stderr, "Entering state %d\n", yystate));
-
-  goto yybackup;
-
-/*-----------.
-| yybackup.  |
-`-----------*/
-yybackup:
-
-  /* Do appropriate processing given the current state.  Read a
-     look-ahead token if we need one and don't already have one.  */
-
-  /* First try to decide what to do without reference to look-ahead token.  */
-  yyn = yypact[yystate];
-  if (yyn == YYPACT_NINF)
-    goto yydefault;
-
-  /* Not known => get a look-ahead token if don't already have one.  */
-
-  /* YYCHAR is either YYEMPTY or YYEOF or a valid look-ahead symbol.  */
-  if (yychar == YYEMPTY)
-    {
-      YYDPRINTF ((stderr, "Reading a token: "));
-      yychar = YYLEX;
-    }
-
-  if (yychar <= YYEOF)
-    {
-      yychar = yytoken = YYEOF;
-      YYDPRINTF ((stderr, "Now at end of input.\n"));
-    }
-  else
-    {
-      yytoken = YYTRANSLATE (yychar);
-      YY_SYMBOL_PRINT ("Next token is", yytoken, &yylval, &yylloc);
-    }
-
-  /* If the proper action on seeing token YYTOKEN is to reduce or to
-     detect an error, take that action.  */
-  yyn += yytoken;
-  if (yyn < 0 || YYLAST < yyn || yycheck[yyn] != yytoken)
-    goto yydefault;
-  yyn = yytable[yyn];
-  if (yyn <= 0)
-    {
-      if (yyn == 0 || yyn == YYTABLE_NINF)
-       goto yyerrlab;
-      yyn = -yyn;
-      goto yyreduce;
-    }
-
-  if (yyn == YYFINAL)
-    YYACCEPT;
-
-  /* Count tokens shifted since error; after three, turn off error
-     status.  */
-  if (yyerrstatus)
-    yyerrstatus--;
-
-  /* Shift the look-ahead token.  */
-  YY_SYMBOL_PRINT ("Shifting", yytoken, &yylval, &yylloc);
-
-  /* Discard the shifted token unless it is eof.  */
-  if (yychar != YYEOF)
-    yychar = YYEMPTY;
-
-  yystate = yyn;
-  *++yyvsp = yylval;
-
-  goto yynewstate;
-
-
-/*-----------------------------------------------------------.
-| yydefault -- do the default action for the current state.  |
-`-----------------------------------------------------------*/
-yydefault:
-  yyn = yydefact[yystate];
-  if (yyn == 0)
-    goto yyerrlab;
-  goto yyreduce;
-
-
-/*-----------------------------.
-| yyreduce -- Do a reduction.  |
-`-----------------------------*/
-yyreduce:
-  /* yyn is the number of a rule to reduce with.  */
-  yylen = yyr2[yyn];
-
-  /* If YYLEN is nonzero, implement the default value of the action:
-     `$$ = $1'.
-
-     Otherwise, the following line sets YYVAL to garbage.
-     This behavior is undocumented and Bison
-     users should not rely upon it.  Assigning to YYVAL
-     unconditionally makes the parser a bit smaller, and it avoids a
-     GCC warning that YYVAL may be used uninitialized.  */
-  yyval = yyvsp[1-yylen];
-
-
-  YY_REDUCE_PRINT (yyn);
-  switch (yyn)
-    {
-        case 2:
-#line 128 "go.y"
-    {
-               xtop = concat(xtop, (yyvsp[(4) - (4)].list));
-       }
-    break;
-
-  case 3:
-#line 134 "go.y"
-    {
-               prevlineno = lineno;
-               yyerror("package statement must be first");
-               errorexit();
-       }
-    break;
-
-  case 4:
-#line 140 "go.y"
-    {
-               mkpackage((yyvsp[(2) - (3)].sym)->name);
-       }
-    break;
-
-  case 5:
-#line 150 "go.y"
-    {
-               importpkg = runtimepkg;
-
-               if(debug['A'])
-                       cannedimports("runtime.builtin", "package runtime\n\n$$\n\n");
-               else
-                       cannedimports("runtime.builtin", runtimeimport);
-               curio.importsafe = 1;
-       }
-    break;
-
-  case 6:
-#line 161 "go.y"
-    {
-               importpkg = nil;
-       }
-    break;
-
-  case 12:
-#line 175 "go.y"
-    {
-               Pkg *ipkg;
-               Sym *my;
-               Node *pack;
-               
-               ipkg = importpkg;
-               my = importmyname;
-               importpkg = nil;
-               importmyname = S;
-
-               if(my == nil)
-                       my = lookup(ipkg->name);
-
-               pack = nod(OPACK, N, N);
-               pack->sym = my;
-               pack->pkg = ipkg;
-               pack->lineno = (yyvsp[(1) - (3)].i);
-
-               if(my->name[0] == '.') {
-                       importdot(ipkg, pack);
-                       break;
-               }
-               if(strcmp(my->name, "init") == 0) {
-                       yyerror("cannot import package as init - init must be a func");
-                       break;
-               }
-               if(my->name[0] == '_' && my->name[1] == '\0')
-                       break;
-               if(my->def) {
-                       lineno = (yyvsp[(1) - (3)].i);
-                       redeclare(my, "as imported package name");
-               }
-               my->def = pack;
-               my->lastlineno = (yyvsp[(1) - (3)].i);
-               my->block = 1;  // at top level
-       }
-    break;
-
-  case 13:
-#line 212 "go.y"
-    {
-               // When an invalid import path is passed to importfile,
-               // it calls yyerror and then sets up a fake import with
-               // no package statement. This allows us to test more
-               // than one invalid import statement in a single file.
-               if(nerrors == 0)
-                       fatal("phase error in import");
-       }
-    break;
-
-  case 16:
-#line 227 "go.y"
-    {
-               // import with original name
-               (yyval.i) = parserline();
-               importmyname = S;
-               importfile(&(yyvsp[(1) - (1)].val), (yyval.i));
-       }
-    break;
-
-  case 17:
-#line 234 "go.y"
-    {
-               // import with given name
-               (yyval.i) = parserline();
-               importmyname = (yyvsp[(1) - (2)].sym);
-               importfile(&(yyvsp[(2) - (2)].val), (yyval.i));
-       }
-    break;
-
-  case 18:
-#line 241 "go.y"
-    {
-               // import into my name space
-               (yyval.i) = parserline();
-               importmyname = lookup(".");
-               importfile(&(yyvsp[(2) - (2)].val), (yyval.i));
-       }
-    break;
-
-  case 19:
-#line 250 "go.y"
-    {
-               if(importpkg->name == nil) {
-                       importpkg->name = (yyvsp[(2) - (4)].sym)->name;
-                       pkglookup((yyvsp[(2) - (4)].sym)->name, nil)->npkg++;
-               } else if(strcmp(importpkg->name, (yyvsp[(2) - (4)].sym)->name) != 0)
-                       yyerror("conflicting names %s and %s for package \"%Z\"", importpkg->name, (yyvsp[(2) - (4)].sym)->name, importpkg->path);
-               importpkg->direct = 1;
-               importpkg->safe = curio.importsafe;
-
-               if(safemode && !curio.importsafe)
-                       yyerror("cannot import unsafe package \"%Z\"", importpkg->path);
-       }
-    break;
-
-  case 21:
-#line 265 "go.y"
-    {
-               if(strcmp((yyvsp[(1) - (1)].sym)->name, "safe") == 0)
-                       curio.importsafe = 1;
-       }
-    break;
-
-  case 22:
-#line 271 "go.y"
-    {
-               defercheckwidth();
-       }
-    break;
-
-  case 23:
-#line 275 "go.y"
-    {
-               resumecheckwidth();
-               unimportfile();
-       }
-    break;
-
-  case 24:
-#line 284 "go.y"
-    {
-               yyerror("empty top-level declaration");
-               (yyval.list) = nil;
-       }
-    break;
-
-  case 26:
-#line 290 "go.y"
-    {
-               (yyval.list) = list1((yyvsp[(1) - (1)].node));
-       }
-    break;
-
-  case 27:
-#line 294 "go.y"
-    {
-               yyerror("non-declaration statement outside function body");
-               (yyval.list) = nil;
-       }
-    break;
-
-  case 28:
-#line 299 "go.y"
-    {
-               (yyval.list) = nil;
-       }
-    break;
-
-  case 29:
-#line 305 "go.y"
-    {
-               (yyval.list) = (yyvsp[(2) - (2)].list);
-       }
-    break;
-
-  case 30:
-#line 309 "go.y"
-    {
-               (yyval.list) = (yyvsp[(3) - (5)].list);
-       }
-    break;
-
-  case 31:
-#line 313 "go.y"
-    {
-               (yyval.list) = nil;
-       }
-    break;
-
-  case 32:
-#line 317 "go.y"
-    {
-               (yyval.list) = (yyvsp[(2) - (2)].list);
-               iota = -100000;
-               lastconst = nil;
-       }
-    break;
-
-  case 33:
-#line 323 "go.y"
-    {
-               (yyval.list) = (yyvsp[(3) - (5)].list);
-               iota = -100000;
-               lastconst = nil;
-       }
-    break;
-
-  case 34:
-#line 329 "go.y"
-    {
-               (yyval.list) = concat((yyvsp[(3) - (7)].list), (yyvsp[(5) - (7)].list));
-               iota = -100000;
-               lastconst = nil;
-       }
-    break;
-
-  case 35:
-#line 335 "go.y"
-    {
-               (yyval.list) = nil;
-               iota = -100000;
-       }
-    break;
-
-  case 36:
-#line 340 "go.y"
-    {
-               (yyval.list) = list1((yyvsp[(2) - (2)].node));
-       }
-    break;
-
-  case 37:
-#line 344 "go.y"
-    {
-               (yyval.list) = (yyvsp[(3) - (5)].list);
-       }
-    break;
-
-  case 38:
-#line 348 "go.y"
-    {
-               (yyval.list) = nil;
-       }
-    break;
-
-  case 39:
-#line 354 "go.y"
-    {
-               iota = 0;
-       }
-    break;
-
-  case 40:
-#line 360 "go.y"
-    {
-               (yyval.list) = variter((yyvsp[(1) - (2)].list), (yyvsp[(2) - (2)].node), nil);
-       }
-    break;
-
-  case 41:
-#line 364 "go.y"
-    {
-               (yyval.list) = variter((yyvsp[(1) - (4)].list), (yyvsp[(2) - (4)].node), (yyvsp[(4) - (4)].list));
-       }
-    break;
-
-  case 42:
-#line 368 "go.y"
-    {
-               (yyval.list) = variter((yyvsp[(1) - (3)].list), nil, (yyvsp[(3) - (3)].list));
-       }
-    break;
-
-  case 43:
-#line 374 "go.y"
-    {
-               (yyval.list) = constiter((yyvsp[(1) - (4)].list), (yyvsp[(2) - (4)].node), (yyvsp[(4) - (4)].list));
-       }
-    break;
-
-  case 44:
-#line 378 "go.y"
-    {
-               (yyval.list) = constiter((yyvsp[(1) - (3)].list), N, (yyvsp[(3) - (3)].list));
-       }
-    break;
-
-  case 46:
-#line 385 "go.y"
-    {
-               (yyval.list) = constiter((yyvsp[(1) - (2)].list), (yyvsp[(2) - (2)].node), nil);
-       }
-    break;
-
-  case 47:
-#line 389 "go.y"
-    {
-               (yyval.list) = constiter((yyvsp[(1) - (1)].list), N, nil);
-       }
-    break;
-
-  case 48:
-#line 395 "go.y"
-    {
-               // different from dclname because the name
-               // becomes visible right here, not at the end
-               // of the declaration.
-               (yyval.node) = typedcl0((yyvsp[(1) - (1)].sym));
-       }
-    break;
-
-  case 49:
-#line 404 "go.y"
-    {
-               (yyval.node) = typedcl1((yyvsp[(1) - (2)].node), (yyvsp[(2) - (2)].node), 1);
-       }
-    break;
-
-  case 50:
-#line 410 "go.y"
-    {
-               (yyval.node) = (yyvsp[(1) - (1)].node);
-
-               // These nodes do not carry line numbers.
-               // Since a bare name used as an expression is an error,
-               // introduce a wrapper node to give the correct line.
-               switch((yyval.node)->op) {
-               case ONAME:
-               case ONONAME:
-               case OTYPE:
-               case OPACK:
-               case OLITERAL:
-                       (yyval.node) = nod(OPAREN, (yyval.node), N);
-                       (yyval.node)->implicit = 1;
-                       break;
-               }
-       }
-    break;
-
-  case 51:
-#line 428 "go.y"
-    {
-               (yyval.node) = nod(OASOP, (yyvsp[(1) - (3)].node), (yyvsp[(3) - (3)].node));
-               (yyval.node)->etype = (yyvsp[(2) - (3)].i);                     // rathole to pass opcode
-       }
-    break;
-
-  case 52:
-#line 433 "go.y"
-    {
-               if((yyvsp[(1) - (3)].list)->next == nil && (yyvsp[(3) - (3)].list)->next == nil) {
-                       // simple
-                       (yyval.node) = nod(OAS, (yyvsp[(1) - (3)].list)->n, (yyvsp[(3) - (3)].list)->n);
-                       break;
-               }
-               // multiple
-               (yyval.node) = nod(OAS2, N, N);
-               (yyval.node)->list = (yyvsp[(1) - (3)].list);
-               (yyval.node)->rlist = (yyvsp[(3) - (3)].list);
-       }
-    break;
-
-  case 53:
-#line 445 "go.y"
-    {
-               if((yyvsp[(3) - (3)].list)->n->op == OTYPESW) {
-                       (yyval.node) = nod(OTYPESW, N, (yyvsp[(3) - (3)].list)->n->right);
-                       if((yyvsp[(3) - (3)].list)->next != nil)
-                               yyerror("expr.(type) must be alone in list");
-                       if((yyvsp[(1) - (3)].list)->next != nil)
-                               yyerror("argument count mismatch: %d = %d", count((yyvsp[(1) - (3)].list)), 1);
-                       else if(((yyvsp[(1) - (3)].list)->n->op != ONAME && (yyvsp[(1) - (3)].list)->n->op != OTYPE && (yyvsp[(1) - (3)].list)->n->op != ONONAME) || isblank((yyvsp[(1) - (3)].list)->n))
-                               yyerror("invalid variable name %N in type switch", (yyvsp[(1) - (3)].list)->n);
-                       else
-                               (yyval.node)->left = dclname((yyvsp[(1) - (3)].list)->n->sym);  // it's a colas, so must not re-use an oldname.
-                       break;
-               }
-               (yyval.node) = colas((yyvsp[(1) - (3)].list), (yyvsp[(3) - (3)].list), (yyvsp[(2) - (3)].i));
-       }
-    break;
-
-  case 54:
-#line 461 "go.y"
-    {
-               (yyval.node) = nod(OASOP, (yyvsp[(1) - (2)].node), nodintconst(1));
-               (yyval.node)->implicit = 1;
-               (yyval.node)->etype = OADD;
-       }
-    break;
-
-  case 55:
-#line 467 "go.y"
-    {
-               (yyval.node) = nod(OASOP, (yyvsp[(1) - (2)].node), nodintconst(1));
-               (yyval.node)->implicit = 1;
-               (yyval.node)->etype = OSUB;
-       }
-    break;
-
-  case 56:
-#line 475 "go.y"
-    {
-               Node *n, *nn;
-
-               // will be converted to OCASE
-               // right will point to next case
-               // done in casebody()
-               markdcl();
-               (yyval.node) = nod(OXCASE, N, N);
-               (yyval.node)->list = (yyvsp[(2) - (3)].list);
-               if(typesw != N && typesw->right != N && (n=typesw->right->left) != N) {
-                       // type switch - declare variable
-                       nn = newname(n->sym);
-                       declare(nn, dclcontext);
-                       (yyval.node)->nname = nn;
-
-                       // keep track of the instances for reporting unused
-                       nn->defn = typesw->right;
-               }
-       }
-    break;
-
-  case 57:
-#line 495 "go.y"
-    {
-               Node *n;
-
-               // will be converted to OCASE
-               // right will point to next case
-               // done in casebody()
-               markdcl();
-               (yyval.node) = nod(OXCASE, N, N);
-               if((yyvsp[(2) - (5)].list)->next == nil)
-                       n = nod(OAS, (yyvsp[(2) - (5)].list)->n, (yyvsp[(4) - (5)].node));
-               else {
-                       n = nod(OAS2, N, N);
-                       n->list = (yyvsp[(2) - (5)].list);
-                       n->rlist = list1((yyvsp[(4) - (5)].node));
-               }
-               (yyval.node)->list = list1(n);
-       }
-    break;
-
-  case 58:
-#line 513 "go.y"
-    {
-               // will be converted to OCASE
-               // right will point to next case
-               // done in casebody()
-               markdcl();
-               (yyval.node) = nod(OXCASE, N, N);
-               (yyval.node)->list = list1(colas((yyvsp[(2) - (5)].list), list1((yyvsp[(4) - (5)].node)), (yyvsp[(3) - (5)].i)));
-       }
-    break;
-
-  case 59:
-#line 522 "go.y"
-    {
-               Node *n, *nn;
-
-               markdcl();
-               (yyval.node) = nod(OXCASE, N, N);
-               if(typesw != N && typesw->right != N && (n=typesw->right->left) != N) {
-                       // type switch - declare variable
-                       nn = newname(n->sym);
-                       declare(nn, dclcontext);
-                       (yyval.node)->nname = nn;
-
-                       // keep track of the instances for reporting unused
-                       nn->defn = typesw->right;
-               }
-       }
-    break;
-
-  case 60:
-#line 540 "go.y"
-    {
-               markdcl();
-       }
-    break;
-
-  case 61:
-#line 544 "go.y"
-    {
-               if((yyvsp[(3) - (4)].list) == nil)
-                       (yyval.node) = nod(OEMPTY, N, N);
-               else
-                       (yyval.node) = liststmt((yyvsp[(3) - (4)].list));
-               popdcl();
-       }
-    break;
-
-  case 62:
-#line 554 "go.y"
-    {
-               // If the last token read by the lexer was consumed
-               // as part of the case, clear it (parser has cleared yychar).
-               // If the last token read by the lexer was the lookahead
-               // leave it alone (parser has it cached in yychar).
-               // This is so that the stmt_list action doesn't look at
-               // the case tokens if the stmt_list is empty.
-               yylast = yychar;
-               (yyvsp[(1) - (1)].node)->xoffset = block;
-       }
-    break;
-
-  case 63:
-#line 565 "go.y"
-    {
-               int last;
-
-               // This is the only place in the language where a statement
-               // list is not allowed to drop the final semicolon, because
-               // it's the only place where a statement list is not followed 
-               // by a closing brace.  Handle the error for pedantry.
-
-               // Find the final token of the statement list.
-               // yylast is lookahead; yyprev is last of stmt_list
-               last = yyprev;
-
-               if(last > 0 && last != ';' && yychar != '}')
-                       yyerror("missing statement after label");
-               (yyval.node) = (yyvsp[(1) - (3)].node);
-               (yyval.node)->nbody = (yyvsp[(3) - (3)].list);
-               popdcl();
-       }
-    break;
-
-  case 64:
-#line 585 "go.y"
-    {
-               (yyval.list) = nil;
-       }
-    break;
-
-  case 65:
-#line 589 "go.y"
-    {
-               (yyval.list) = list((yyvsp[(1) - (2)].list), (yyvsp[(2) - (2)].node));
-       }
-    break;
-
-  case 66:
-#line 595 "go.y"
-    {
-               markdcl();
-       }
-    break;
-
-  case 67:
-#line 599 "go.y"
-    {
-               (yyval.list) = (yyvsp[(3) - (4)].list);
-               popdcl();
-       }
-    break;
-
-  case 68:
-#line 606 "go.y"
-    {
-               (yyval.node) = nod(ORANGE, N, (yyvsp[(4) - (4)].node));
-               (yyval.node)->list = (yyvsp[(1) - (4)].list);
-               (yyval.node)->etype = 0;        // := flag
-       }
-    break;
-
-  case 69:
-#line 612 "go.y"
-    {
-               (yyval.node) = nod(ORANGE, N, (yyvsp[(4) - (4)].node));
-               (yyval.node)->list = (yyvsp[(1) - (4)].list);
-               (yyval.node)->colas = 1;
-               colasdefn((yyvsp[(1) - (4)].list), (yyval.node));
-       }
-    break;
-
-  case 70:
-#line 619 "go.y"
-    {
-               (yyval.node) = nod(ORANGE, N, (yyvsp[(2) - (2)].node));
-               (yyval.node)->etype = 0; // := flag
-       }
-    break;
-
-  case 71:
-#line 626 "go.y"
-    {
-               // init ; test ; incr
-               if((yyvsp[(5) - (5)].node) != N && (yyvsp[(5) - (5)].node)->colas != 0)
-                       yyerror("cannot declare in the for-increment");
-               (yyval.node) = nod(OFOR, N, N);
-               if((yyvsp[(1) - (5)].node) != N)
-                       (yyval.node)->ninit = list1((yyvsp[(1) - (5)].node));
-               (yyval.node)->ntest = (yyvsp[(3) - (5)].node);
-               (yyval.node)->nincr = (yyvsp[(5) - (5)].node);
-       }
-    break;
-
-  case 72:
-#line 637 "go.y"
-    {
-               // normal test
-               (yyval.node) = nod(OFOR, N, N);
-               (yyval.node)->ntest = (yyvsp[(1) - (1)].node);
-       }
-    break;
-
-  case 74:
-#line 646 "go.y"
-    {
-               (yyval.node) = (yyvsp[(1) - (2)].node);
-               (yyval.node)->nbody = concat((yyval.node)->nbody, (yyvsp[(2) - (2)].list));
-       }
-    break;
-
-  case 75:
-#line 653 "go.y"
-    {
-               markdcl();
-       }
-    break;
-
-  case 76:
-#line 657 "go.y"
-    {
-               (yyval.node) = (yyvsp[(3) - (3)].node);
-               popdcl();
-       }
-    break;
-
-  case 77:
-#line 664 "go.y"
-    {
-               // test
-               (yyval.node) = nod(OIF, N, N);
-               (yyval.node)->ntest = (yyvsp[(1) - (1)].node);
-       }
-    break;
-
-  case 78:
-#line 670 "go.y"
-    {
-               // init ; test
-               (yyval.node) = nod(OIF, N, N);
-               if((yyvsp[(1) - (3)].node) != N)
-                       (yyval.node)->ninit = list1((yyvsp[(1) - (3)].node));
-               (yyval.node)->ntest = (yyvsp[(3) - (3)].node);
-       }
-    break;
-
-  case 79:
-#line 681 "go.y"
-    {
-               markdcl();
-       }
-    break;
-
-  case 80:
-#line 685 "go.y"
-    {
-               if((yyvsp[(3) - (3)].node)->ntest == N)
-                       yyerror("missing condition in if statement");
-       }
-    break;
-
-  case 81:
-#line 690 "go.y"
-    {
-               (yyvsp[(3) - (5)].node)->nbody = (yyvsp[(5) - (5)].list);
-       }
-    break;
-
-  case 82:
-#line 694 "go.y"
-    {
-               Node *n;
-               NodeList *nn;
-
-               (yyval.node) = (yyvsp[(3) - (8)].node);
-               n = (yyvsp[(3) - (8)].node);
-               popdcl();
-               for(nn = concat((yyvsp[(7) - (8)].list), (yyvsp[(8) - (8)].list)); nn; nn = nn->next) {
-                       if(nn->n->op == OIF)
-                               popdcl();
-                       n->nelse = list1(nn->n);
-                       n = nn->n;
-               }
-       }
-    break;
-
-  case 83:
-#line 711 "go.y"
-    {
-               markdcl();
-       }
-    break;
-
-  case 84:
-#line 715 "go.y"
-    {
-               if((yyvsp[(4) - (5)].node)->ntest == N)
-                       yyerror("missing condition in if statement");
-               (yyvsp[(4) - (5)].node)->nbody = (yyvsp[(5) - (5)].list);
-               (yyval.list) = list1((yyvsp[(4) - (5)].node));
-       }
-    break;
-
-  case 85:
-#line 723 "go.y"
-    {
-               (yyval.list) = nil;
-       }
-    break;
-
-  case 86:
-#line 727 "go.y"
-    {
-               (yyval.list) = concat((yyvsp[(1) - (2)].list), (yyvsp[(2) - (2)].list));
-       }
-    break;
-
-  case 87:
-#line 732 "go.y"
-    {
-               (yyval.list) = nil;
-       }
-    break;
-
-  case 88:
-#line 736 "go.y"
-    {
-               NodeList *node;
-               
-               node = mal(sizeof *node);
-               node->n = (yyvsp[(2) - (2)].node);
-               node->end = node;
-               (yyval.list) = node;
-       }
-    break;
-
-  case 89:
-#line 747 "go.y"
-    {
-               markdcl();
-       }
-    break;
-
-  case 90:
-#line 751 "go.y"
-    {
-               Node *n;
-               n = (yyvsp[(3) - (3)].node)->ntest;
-               if(n != N && n->op != OTYPESW)
-                       n = N;
-               typesw = nod(OXXX, typesw, n);
-       }
-    break;
-
-  case 91:
-#line 759 "go.y"
-    {
-               (yyval.node) = (yyvsp[(3) - (7)].node);
-               (yyval.node)->op = OSWITCH;
-               (yyval.node)->list = (yyvsp[(6) - (7)].list);
-               typesw = typesw->left;
-               popdcl();
-       }
-    break;
-
-  case 92:
-#line 769 "go.y"
-    {
-               typesw = nod(OXXX, typesw, N);
-       }
-    break;
-
-  case 93:
-#line 773 "go.y"
-    {
-               (yyval.node) = nod(OSELECT, N, N);
-               (yyval.node)->lineno = typesw->lineno;
-               (yyval.node)->list = (yyvsp[(4) - (5)].list);
-               typesw = typesw->left;
-       }
-    break;
-
-  case 95:
-#line 786 "go.y"
-    {
-               (yyval.node) = nod(OOROR, (yyvsp[(1) - (3)].node), (yyvsp[(3) - (3)].node));
-       }
-    break;
-
-  case 96:
-#line 790 "go.y"
-    {
-               (yyval.node) = nod(OANDAND, (yyvsp[(1) - (3)].node), (yyvsp[(3) - (3)].node));
-       }
-    break;
-
-  case 97:
-#line 794 "go.y"
-    {
-               (yyval.node) = nod(OEQ, (yyvsp[(1) - (3)].node), (yyvsp[(3) - (3)].node));
-       }
-    break;
-
-  case 98:
-#line 798 "go.y"
-    {
-               (yyval.node) = nod(ONE, (yyvsp[(1) - (3)].node), (yyvsp[(3) - (3)].node));
-       }
-    break;
-
-  case 99:
-#line 802 "go.y"
-    {
-               (yyval.node) = nod(OLT, (yyvsp[(1) - (3)].node), (yyvsp[(3) - (3)].node));
-       }
-    break;
-
-  case 100:
-#line 806 "go.y"
-    {
-               (yyval.node) = nod(OLE, (yyvsp[(1) - (3)].node), (yyvsp[(3) - (3)].node));
-       }
-    break;
-
-  case 101:
-#line 810 "go.y"
-    {
-               (yyval.node) = nod(OGE, (yyvsp[(1) - (3)].node), (yyvsp[(3) - (3)].node));
-       }
-    break;
-
-  case 102:
-#line 814 "go.y"
-    {
-               (yyval.node) = nod(OGT, (yyvsp[(1) - (3)].node), (yyvsp[(3) - (3)].node));
-       }
-    break;
-
-  case 103:
-#line 818 "go.y"
-    {
-               (yyval.node) = nod(OADD, (yyvsp[(1) - (3)].node), (yyvsp[(3) - (3)].node));
-       }
-    break;
-
-  case 104:
-#line 822 "go.y"
-    {
-               (yyval.node) = nod(OSUB, (yyvsp[(1) - (3)].node), (yyvsp[(3) - (3)].node));
-       }
-    break;
-
-  case 105:
-#line 826 "go.y"
-    {
-               (yyval.node) = nod(OOR, (yyvsp[(1) - (3)].node), (yyvsp[(3) - (3)].node));
-       }
-    break;
-
-  case 106:
-#line 830 "go.y"
-    {
-               (yyval.node) = nod(OXOR, (yyvsp[(1) - (3)].node), (yyvsp[(3) - (3)].node));
-       }
-    break;
-
-  case 107:
-#line 834 "go.y"
-    {
-               (yyval.node) = nod(OMUL, (yyvsp[(1) - (3)].node), (yyvsp[(3) - (3)].node));
-       }
-    break;
-
-  case 108:
-#line 838 "go.y"
-    {
-               (yyval.node) = nod(ODIV, (yyvsp[(1) - (3)].node), (yyvsp[(3) - (3)].node));
-       }
-    break;
-
-  case 109:
-#line 842 "go.y"
-    {
-               (yyval.node) = nod(OMOD, (yyvsp[(1) - (3)].node), (yyvsp[(3) - (3)].node));
-       }
-    break;
-
-  case 110:
-#line 846 "go.y"
-    {
-               (yyval.node) = nod(OAND, (yyvsp[(1) - (3)].node), (yyvsp[(3) - (3)].node));
-       }
-    break;
-
-  case 111:
-#line 850 "go.y"
-    {
-               (yyval.node) = nod(OANDNOT, (yyvsp[(1) - (3)].node), (yyvsp[(3) - (3)].node));
-       }
-    break;
-
-  case 112:
-#line 854 "go.y"
-    {
-               (yyval.node) = nod(OLSH, (yyvsp[(1) - (3)].node), (yyvsp[(3) - (3)].node));
-       }
-    break;
-
-  case 113:
-#line 858 "go.y"
-    {
-               (yyval.node) = nod(ORSH, (yyvsp[(1) - (3)].node), (yyvsp[(3) - (3)].node));
-       }
-    break;
-
-  case 114:
-#line 863 "go.y"
-    {
-               (yyval.node) = nod(OSEND, (yyvsp[(1) - (3)].node), (yyvsp[(3) - (3)].node));
-       }
-    break;
-
-  case 116:
-#line 870 "go.y"
-    {
-               (yyval.node) = nod(OIND, (yyvsp[(2) - (2)].node), N);
-       }
-    break;
-
-  case 117:
-#line 874 "go.y"
-    {
-               if((yyvsp[(2) - (2)].node)->op == OCOMPLIT) {
-                       // Special case for &T{...}: turn into (*T){...}.
-                       (yyval.node) = (yyvsp[(2) - (2)].node);
-                       (yyval.node)->right = nod(OIND, (yyval.node)->right, N);
-                       (yyval.node)->right->implicit = 1;
-               } else {
-                       (yyval.node) = nod(OADDR, (yyvsp[(2) - (2)].node), N);
-               }
-       }
-    break;
-
-  case 118:
-#line 885 "go.y"
-    {
-               (yyval.node) = nod(OPLUS, (yyvsp[(2) - (2)].node), N);
-       }
-    break;
-
-  case 119:
-#line 889 "go.y"
-    {
-               (yyval.node) = nod(OMINUS, (yyvsp[(2) - (2)].node), N);
-       }
-    break;
-
-  case 120:
-#line 893 "go.y"
-    {
-               (yyval.node) = nod(ONOT, (yyvsp[(2) - (2)].node), N);
-       }
-    break;
-
-  case 121:
-#line 897 "go.y"
-    {
-               yyerror("the bitwise complement operator is ^");
-               (yyval.node) = nod(OCOM, (yyvsp[(2) - (2)].node), N);
-       }
-    break;
-
-  case 122:
-#line 902 "go.y"
-    {
-               (yyval.node) = nod(OCOM, (yyvsp[(2) - (2)].node), N);
-       }
-    break;
-
-  case 123:
-#line 906 "go.y"
-    {
-               (yyval.node) = nod(ORECV, (yyvsp[(2) - (2)].node), N);
-       }
-    break;
-
-  case 124:
-#line 916 "go.y"
-    {
-               (yyval.node) = nod(OCALL, (yyvsp[(1) - (3)].node), N);
-       }
-    break;
-
-  case 125:
-#line 920 "go.y"
-    {
-               (yyval.node) = nod(OCALL, (yyvsp[(1) - (5)].node), N);
-               (yyval.node)->list = (yyvsp[(3) - (5)].list);
-       }
-    break;
-
-  case 126:
-#line 925 "go.y"
-    {
-               (yyval.node) = nod(OCALL, (yyvsp[(1) - (6)].node), N);
-               (yyval.node)->list = (yyvsp[(3) - (6)].list);
-               (yyval.node)->isddd = 1;
-       }
-    break;
-
-  case 127:
-#line 933 "go.y"
-    {
-               (yyval.node) = nodlit((yyvsp[(1) - (1)].val));
-       }
-    break;
-
-  case 129:
-#line 938 "go.y"
-    {
-               if((yyvsp[(1) - (3)].node)->op == OPACK) {
-                       Sym *s;
-                       s = restrictlookup((yyvsp[(3) - (3)].sym)->name, (yyvsp[(1) - (3)].node)->pkg);
-                       (yyvsp[(1) - (3)].node)->used = 1;
-                       (yyval.node) = oldname(s);
-                       break;
-               }
-               (yyval.node) = nod(OXDOT, (yyvsp[(1) - (3)].node), newname((yyvsp[(3) - (3)].sym)));
-       }
-    break;
-
-  case 130:
-#line 949 "go.y"
-    {
-               (yyval.node) = nod(ODOTTYPE, (yyvsp[(1) - (5)].node), (yyvsp[(4) - (5)].node));
-       }
-    break;
-
-  case 131:
-#line 953 "go.y"
-    {
-               (yyval.node) = nod(OTYPESW, N, (yyvsp[(1) - (5)].node));
-       }
-    break;
-
-  case 132:
-#line 957 "go.y"
-    {
-               (yyval.node) = nod(OINDEX, (yyvsp[(1) - (4)].node), (yyvsp[(3) - (4)].node));
-       }
-    break;
-
-  case 133:
-#line 961 "go.y"
-    {
-               (yyval.node) = nod(OSLICE, (yyvsp[(1) - (6)].node), nod(OKEY, (yyvsp[(3) - (6)].node), (yyvsp[(5) - (6)].node)));
-       }
-    break;
-
-  case 134:
-#line 965 "go.y"
-    {
-               if((yyvsp[(5) - (8)].node) == N)
-                       yyerror("middle index required in 3-index slice");
-               if((yyvsp[(7) - (8)].node) == N)
-                       yyerror("final index required in 3-index slice");
-               (yyval.node) = nod(OSLICE3, (yyvsp[(1) - (8)].node), nod(OKEY, (yyvsp[(3) - (8)].node), nod(OKEY, (yyvsp[(5) - (8)].node), (yyvsp[(7) - (8)].node))));
-       }
-    break;
-
-  case 136:
-#line 974 "go.y"
-    {
-               // conversion
-               (yyval.node) = nod(OCALL, (yyvsp[(1) - (5)].node), N);
-               (yyval.node)->list = list1((yyvsp[(3) - (5)].node));
-       }
-    break;
-
-  case 137:
-#line 980 "go.y"
-    {
-               (yyval.node) = (yyvsp[(3) - (5)].node);
-               (yyval.node)->right = (yyvsp[(1) - (5)].node);
-               (yyval.node)->list = (yyvsp[(4) - (5)].list);
-               fixlbrace((yyvsp[(2) - (5)].i));
-       }
-    break;
-
-  case 138:
-#line 987 "go.y"
-    {
-               (yyval.node) = (yyvsp[(3) - (5)].node);
-               (yyval.node)->right = (yyvsp[(1) - (5)].node);
-               (yyval.node)->list = (yyvsp[(4) - (5)].list);
-       }
-    break;
-
-  case 139:
-#line 993 "go.y"
-    {
-               yyerror("cannot parenthesize type in composite literal");
-               (yyval.node) = (yyvsp[(5) - (7)].node);
-               (yyval.node)->right = (yyvsp[(2) - (7)].node);
-               (yyval.node)->list = (yyvsp[(6) - (7)].list);
-       }
-    break;
-
-  case 141:
-#line 1002 "go.y"
-    {
-               // composite expression.
-               // make node early so we get the right line number.
-               (yyval.node) = nod(OCOMPLIT, N, N);
-       }
-    break;
-
-  case 142:
-#line 1010 "go.y"
-    {
-               (yyval.node) = nod(OKEY, (yyvsp[(1) - (3)].node), (yyvsp[(3) - (3)].node));
-       }
-    break;
-
-  case 143:
-#line 1016 "go.y"
-    {
-               // These nodes do not carry line numbers.
-               // Since a composite literal commonly spans several lines,
-               // the line number on errors may be misleading.
-               // Introduce a wrapper node to give the correct line.
-               (yyval.node) = (yyvsp[(1) - (1)].node);
-               switch((yyval.node)->op) {
-               case ONAME:
-               case ONONAME:
-               case OTYPE:
-               case OPACK:
-               case OLITERAL:
-                       (yyval.node) = nod(OPAREN, (yyval.node), N);
-                       (yyval.node)->implicit = 1;
-               }
-       }
-    break;
-
-  case 144:
-#line 1033 "go.y"
-    {
-               (yyval.node) = (yyvsp[(2) - (4)].node);
-               (yyval.node)->list = (yyvsp[(3) - (4)].list);
-       }
-    break;
-
-  case 146:
-#line 1041 "go.y"
-    {
-               (yyval.node) = (yyvsp[(2) - (4)].node);
-               (yyval.node)->list = (yyvsp[(3) - (4)].list);
-       }
-    break;
-
-  case 148:
-#line 1049 "go.y"
-    {
-               (yyval.node) = (yyvsp[(2) - (3)].node);
-               
-               // Need to know on lhs of := whether there are ( ).
-               // Don't bother with the OPAREN in other cases:
-               // it's just a waste of memory and time.
-               switch((yyval.node)->op) {
-               case ONAME:
-               case ONONAME:
-               case OPACK:
-               case OTYPE:
-               case OLITERAL:
-               case OTYPESW:
-                       (yyval.node) = nod(OPAREN, (yyval.node), N);
-               }
-       }
-    break;
-
-  case 152:
-#line 1075 "go.y"
-    {
-               (yyval.i) = LBODY;
-       }
-    break;
-
-  case 153:
-#line 1079 "go.y"
-    {
-               (yyval.i) = '{';
-       }
-    break;
-
-  case 154:
-#line 1090 "go.y"
-    {
-               if((yyvsp[(1) - (1)].sym) == S)
-                       (yyval.node) = N;
-               else
-                       (yyval.node) = newname((yyvsp[(1) - (1)].sym));
-       }
-    break;
-
-  case 155:
-#line 1099 "go.y"
-    {
-               (yyval.node) = dclname((yyvsp[(1) - (1)].sym));
-       }
-    break;
-
-  case 156:
-#line 1104 "go.y"
-    {
-               (yyval.node) = N;
-       }
-    break;
-
-  case 158:
-#line 1111 "go.y"
-    {
-               (yyval.sym) = (yyvsp[(1) - (1)].sym);
-               // during imports, unqualified non-exported identifiers are from builtinpkg
-               if(importpkg != nil && !exportname((yyvsp[(1) - (1)].sym)->name))
-                       (yyval.sym) = pkglookup((yyvsp[(1) - (1)].sym)->name, builtinpkg);
-       }
-    break;
-
-  case 160:
-#line 1119 "go.y"
-    {
-               (yyval.sym) = S;
-       }
-    break;
-
-  case 161:
-#line 1125 "go.y"
-    {
-               Pkg *p;
-
-               if((yyvsp[(2) - (4)].val).u.sval->len == 0)
-                       p = importpkg;
-               else {
-                       if(isbadimport((yyvsp[(2) - (4)].val).u.sval))
-                               errorexit();
-                       p = mkpkg((yyvsp[(2) - (4)].val).u.sval);
-               }
-               (yyval.sym) = pkglookup((yyvsp[(4) - (4)].sym)->name, p);
-       }
-    break;
-
-  case 162:
-#line 1138 "go.y"
-    {
-               Pkg *p;
-
-               if((yyvsp[(2) - (4)].val).u.sval->len == 0)
-                       p = importpkg;
-               else {
-                       if(isbadimport((yyvsp[(2) - (4)].val).u.sval))
-                               errorexit();
-                       p = mkpkg((yyvsp[(2) - (4)].val).u.sval);
-               }
-               (yyval.sym) = pkglookup("?", p);
-       }
-    break;
-
-  case 163:
-#line 1153 "go.y"
-    {
-               (yyval.node) = oldname((yyvsp[(1) - (1)].sym));
-               if((yyval.node)->pack != N)
-                       (yyval.node)->pack->used = 1;
-       }
-    break;
-
-  case 165:
-#line 1173 "go.y"
-    {
-               yyerror("final argument in variadic function missing type");
-               (yyval.node) = nod(ODDD, typenod(typ(TINTER)), N);
-       }
-    break;
-
-  case 166:
-#line 1178 "go.y"
-    {
-               (yyval.node) = nod(ODDD, (yyvsp[(2) - (2)].node), N);
-       }
-    break;
-
-  case 172:
-#line 1189 "go.y"
-    {
-               (yyval.node) = (yyvsp[(2) - (3)].node);
-       }
-    break;
-
-  case 176:
-#line 1198 "go.y"
-    {
-               (yyval.node) = nod(OIND, (yyvsp[(2) - (2)].node), N);
-       }
-    break;
-
-  case 181:
-#line 1208 "go.y"
-    {
-               (yyval.node) = (yyvsp[(2) - (3)].node);
-       }
-    break;
-
-  case 191:
-#line 1229 "go.y"
-    {
-               if((yyvsp[(1) - (3)].node)->op == OPACK) {
-                       Sym *s;
-                       s = restrictlookup((yyvsp[(3) - (3)].sym)->name, (yyvsp[(1) - (3)].node)->pkg);
-                       (yyvsp[(1) - (3)].node)->used = 1;
-                       (yyval.node) = oldname(s);
-                       break;
-               }
-               (yyval.node) = nod(OXDOT, (yyvsp[(1) - (3)].node), newname((yyvsp[(3) - (3)].sym)));
-       }
-    break;
-
-  case 192:
-#line 1242 "go.y"
-    {
-               (yyval.node) = nod(OTARRAY, (yyvsp[(2) - (4)].node), (yyvsp[(4) - (4)].node));
-       }
-    break;
-
-  case 193:
-#line 1246 "go.y"
-    {
-               // array literal of nelem
-               (yyval.node) = nod(OTARRAY, nod(ODDD, N, N), (yyvsp[(4) - (4)].node));
-       }
-    break;
-
-  case 194:
-#line 1251 "go.y"
-    {
-               (yyval.node) = nod(OTCHAN, (yyvsp[(2) - (2)].node), N);
-               (yyval.node)->etype = Cboth;
-       }
-    break;
-
-  case 195:
-#line 1256 "go.y"
-    {
-               (yyval.node) = nod(OTCHAN, (yyvsp[(3) - (3)].node), N);
-               (yyval.node)->etype = Csend;
-       }
-    break;
-
-  case 196:
-#line 1261 "go.y"
-    {
-               (yyval.node) = nod(OTMAP, (yyvsp[(3) - (5)].node), (yyvsp[(5) - (5)].node));
-       }
-    break;
-
-  case 199:
-#line 1269 "go.y"
-    {
-               (yyval.node) = nod(OIND, (yyvsp[(2) - (2)].node), N);
-       }
-    break;
-
-  case 200:
-#line 1275 "go.y"
-    {
-               (yyval.node) = nod(OTCHAN, (yyvsp[(3) - (3)].node), N);
-               (yyval.node)->etype = Crecv;
-       }
-    break;
-
-  case 201:
-#line 1282 "go.y"
-    {
-               (yyval.node) = nod(OTSTRUCT, N, N);
-               (yyval.node)->list = (yyvsp[(3) - (5)].list);
-               fixlbrace((yyvsp[(2) - (5)].i));
-       }
-    break;
-
-  case 202:
-#line 1288 "go.y"
-    {
-               (yyval.node) = nod(OTSTRUCT, N, N);
-               fixlbrace((yyvsp[(2) - (3)].i));
-       }
-    break;
-
-  case 203:
-#line 1295 "go.y"
-    {
-               (yyval.node) = nod(OTINTER, N, N);
-               (yyval.node)->list = (yyvsp[(3) - (5)].list);
-               fixlbrace((yyvsp[(2) - (5)].i));
-       }
-    break;
-
-  case 204:
-#line 1301 "go.y"
-    {
-               (yyval.node) = nod(OTINTER, N, N);
-               fixlbrace((yyvsp[(2) - (3)].i));
-       }
-    break;
-
-  case 205:
-#line 1312 "go.y"
-    {
-               (yyval.node) = (yyvsp[(2) - (3)].node);
-               if((yyval.node) == N)
-                       break;
-               if(noescape && (yyvsp[(3) - (3)].list) != nil)
-                       yyerror("can only use //go:noescape with external func implementations");
-               (yyval.node)->nbody = (yyvsp[(3) - (3)].list);
-               (yyval.node)->endlineno = lineno;
-               (yyval.node)->noescape = noescape;
-               (yyval.node)->nosplit = nosplit;
-               (yyval.node)->nowritebarrier = nowritebarrier;
-               funcbody((yyval.node));
-       }
-    break;
-
-  case 206:
-#line 1328 "go.y"
-    {
-               Node *t;
-
-               (yyval.node) = N;
-               (yyvsp[(3) - (5)].list) = checkarglist((yyvsp[(3) - (5)].list), 1);
-
-               if(strcmp((yyvsp[(1) - (5)].sym)->name, "init") == 0) {
-                       (yyvsp[(1) - (5)].sym) = renameinit();
-                       if((yyvsp[(3) - (5)].list) != nil || (yyvsp[(5) - (5)].list) != nil)
-                               yyerror("func init must have no arguments and no return values");
-               }
-               if(strcmp(localpkg->name, "main") == 0 && strcmp((yyvsp[(1) - (5)].sym)->name, "main") == 0) {
-                       if((yyvsp[(3) - (5)].list) != nil || (yyvsp[(5) - (5)].list) != nil)
-                               yyerror("func main must have no arguments and no return values");
-               }
-
-               t = nod(OTFUNC, N, N);
-               t->list = (yyvsp[(3) - (5)].list);
-               t->rlist = (yyvsp[(5) - (5)].list);
-
-               (yyval.node) = nod(ODCLFUNC, N, N);
-               (yyval.node)->nname = newname((yyvsp[(1) - (5)].sym));
-               (yyval.node)->nname->defn = (yyval.node);
-               (yyval.node)->nname->ntype = t;         // TODO: check if nname already has an ntype
-               declare((yyval.node)->nname, PFUNC);
-
-               funchdr((yyval.node));
-       }
-    break;
-
-  case 207:
-#line 1357 "go.y"
-    {
-               Node *rcvr, *t;
-
-               (yyval.node) = N;
-               (yyvsp[(2) - (8)].list) = checkarglist((yyvsp[(2) - (8)].list), 0);
-               (yyvsp[(6) - (8)].list) = checkarglist((yyvsp[(6) - (8)].list), 1);
-
-               if((yyvsp[(2) - (8)].list) == nil) {
-                       yyerror("method has no receiver");
-                       break;
-               }
-               if((yyvsp[(2) - (8)].list)->next != nil) {
-                       yyerror("method has multiple receivers");
-                       break;
-               }
-               rcvr = (yyvsp[(2) - (8)].list)->n;
-               if(rcvr->op != ODCLFIELD) {
-                       yyerror("bad receiver in method");
-                       break;
-               }
-
-               t = nod(OTFUNC, rcvr, N);
-               t->list = (yyvsp[(6) - (8)].list);
-               t->rlist = (yyvsp[(8) - (8)].list);
-
-               (yyval.node) = nod(ODCLFUNC, N, N);
-               (yyval.node)->shortname = newname((yyvsp[(4) - (8)].sym));
-               (yyval.node)->nname = methodname1((yyval.node)->shortname, rcvr->right);
-               (yyval.node)->nname->defn = (yyval.node);
-               (yyval.node)->nname->ntype = t;
-               (yyval.node)->nname->nointerface = nointerface;
-               declare((yyval.node)->nname, PFUNC);
-
-               funchdr((yyval.node));
-       }
-    break;
-
-  case 208:
-#line 1395 "go.y"
-    {
-               Sym *s;
-               Type *t;
-
-               (yyval.node) = N;
-
-               s = (yyvsp[(1) - (5)].sym);
-               t = functype(N, (yyvsp[(3) - (5)].list), (yyvsp[(5) - (5)].list));
-
-               importsym(s, ONAME);
-               if(s->def != N && s->def->op == ONAME) {
-                       if(eqtype(t, s->def->type)) {
-                               dclcontext = PDISCARD;  // since we skip funchdr below
-                               break;
-                       }
-                       yyerror("inconsistent definition for func %S during import\n\t%T\n\t%T", s, s->def->type, t);
-               }
-
-               (yyval.node) = newname(s);
-               (yyval.node)->type = t;
-               declare((yyval.node), PFUNC);
-
-               funchdr((yyval.node));
-       }
-    break;
-
-  case 209:
-#line 1420 "go.y"
-    {
-               (yyval.node) = methodname1(newname((yyvsp[(4) - (8)].sym)), (yyvsp[(2) - (8)].list)->n->right); 
-               (yyval.node)->type = functype((yyvsp[(2) - (8)].list)->n, (yyvsp[(6) - (8)].list), (yyvsp[(8) - (8)].list));
-
-               checkwidth((yyval.node)->type);
-               addmethod((yyvsp[(4) - (8)].sym), (yyval.node)->type, 0, nointerface);
-               nointerface = 0;
-               funchdr((yyval.node));
-               
-               // inl.c's inlnode in on a dotmeth node expects to find the inlineable body as
-               // (dotmeth's type)->nname->inl, and dotmeth's type has been pulled
-               // out by typecheck's lookdot as this $$->ttype.  So by providing
-               // this back link here we avoid special casing there.
-               (yyval.node)->type->nname = (yyval.node);
-       }
-    break;
-
-  case 210:
-#line 1438 "go.y"
-    {
-               (yyvsp[(3) - (5)].list) = checkarglist((yyvsp[(3) - (5)].list), 1);
-               (yyval.node) = nod(OTFUNC, N, N);
-               (yyval.node)->list = (yyvsp[(3) - (5)].list);
-               (yyval.node)->rlist = (yyvsp[(5) - (5)].list);
-       }
-    break;
-
-  case 211:
-#line 1446 "go.y"
-    {
-               (yyval.list) = nil;
-       }
-    break;
-
-  case 212:
-#line 1450 "go.y"
-    {
-               (yyval.list) = (yyvsp[(2) - (3)].list);
-               if((yyval.list) == nil)
-                       (yyval.list) = list1(nod(OEMPTY, N, N));
-       }
-    break;
-
-  case 213:
-#line 1458 "go.y"
-    {
-               (yyval.list) = nil;
-       }
-    break;
-
-  case 214:
-#line 1462 "go.y"
-    {
-               (yyval.list) = list1(nod(ODCLFIELD, N, (yyvsp[(1) - (1)].node)));
-       }
-    break;
-
-  case 215:
-#line 1466 "go.y"
-    {
-               (yyvsp[(2) - (3)].list) = checkarglist((yyvsp[(2) - (3)].list), 0);
-               (yyval.list) = (yyvsp[(2) - (3)].list);
-       }
-    break;
-
-  case 216:
-#line 1473 "go.y"
-    {
-               closurehdr((yyvsp[(1) - (1)].node));
-       }
-    break;
-
-  case 217:
-#line 1479 "go.y"
-    {
-               (yyval.node) = closurebody((yyvsp[(3) - (4)].list));
-               fixlbrace((yyvsp[(2) - (4)].i));
-       }
-    break;
-
-  case 218:
-#line 1484 "go.y"
-    {
-               (yyval.node) = closurebody(nil);
-       }
-    break;
-
-  case 219:
-#line 1495 "go.y"
-    {
-               (yyval.list) = nil;
-       }
-    break;
-
-  case 220:
-#line 1499 "go.y"
-    {
-               (yyval.list) = concat((yyvsp[(1) - (3)].list), (yyvsp[(2) - (3)].list));
-               if(nsyntaxerrors == 0)
-                       testdclstack();
-               nointerface = 0;
-               noescape = 0;
-               nosplit = 0;
-               nowritebarrier = 0;
-       }
-    break;
-
-  case 222:
-#line 1512 "go.y"
-    {
-               (yyval.list) = concat((yyvsp[(1) - (3)].list), (yyvsp[(3) - (3)].list));
-       }
-    break;
-
-  case 224:
-#line 1519 "go.y"
-    {
-               (yyval.list) = concat((yyvsp[(1) - (3)].list), (yyvsp[(3) - (3)].list));
-       }
-    break;
-
-  case 225:
-#line 1525 "go.y"
-    {
-               (yyval.list) = list1((yyvsp[(1) - (1)].node));
-       }
-    break;
-
-  case 226:
-#line 1529 "go.y"
-    {
-               (yyval.list) = list((yyvsp[(1) - (3)].list), (yyvsp[(3) - (3)].node));
-       }
-    break;
-
-  case 228:
-#line 1536 "go.y"
-    {
-               (yyval.list) = concat((yyvsp[(1) - (3)].list), (yyvsp[(3) - (3)].list));
-       }
-    break;
-
-  case 229:
-#line 1542 "go.y"
-    {
-               (yyval.list) = list1((yyvsp[(1) - (1)].node));
-       }
-    break;
-
-  case 230:
-#line 1546 "go.y"
-    {
-               (yyval.list) = list((yyvsp[(1) - (3)].list), (yyvsp[(3) - (3)].node));
-       }
-    break;
-
-  case 231:
-#line 1552 "go.y"
-    {
-               NodeList *l;
-
-               Node *n;
-               l = (yyvsp[(1) - (3)].list);
-               if(l == nil) {
-                       // ? symbol, during import (list1(N) == nil)
-                       n = (yyvsp[(2) - (3)].node);
-                       if(n->op == OIND)
-                               n = n->left;
-                       n = embedded(n->sym, importpkg);
-                       n->right = (yyvsp[(2) - (3)].node);
-                       n->val = (yyvsp[(3) - (3)].val);
-                       (yyval.list) = list1(n);
-                       break;
-               }
-
-               for(l=(yyvsp[(1) - (3)].list); l; l=l->next) {
-                       l->n = nod(ODCLFIELD, l->n, (yyvsp[(2) - (3)].node));
-                       l->n->val = (yyvsp[(3) - (3)].val);
-               }
-       }
-    break;
-
-  case 232:
-#line 1575 "go.y"
-    {
-               (yyvsp[(1) - (2)].node)->val = (yyvsp[(2) - (2)].val);
-               (yyval.list) = list1((yyvsp[(1) - (2)].node));
-       }
-    break;
-
-  case 233:
-#line 1580 "go.y"
-    {
-               (yyvsp[(2) - (4)].node)->val = (yyvsp[(4) - (4)].val);
-               (yyval.list) = list1((yyvsp[(2) - (4)].node));
-               yyerror("cannot parenthesize embedded type");
-       }
-    break;
-
-  case 234:
-#line 1586 "go.y"
-    {
-               (yyvsp[(2) - (3)].node)->right = nod(OIND, (yyvsp[(2) - (3)].node)->right, N);
-               (yyvsp[(2) - (3)].node)->val = (yyvsp[(3) - (3)].val);
-               (yyval.list) = list1((yyvsp[(2) - (3)].node));
-       }
-    break;
-
-  case 235:
-#line 1592 "go.y"
-    {
-               (yyvsp[(3) - (5)].node)->right = nod(OIND, (yyvsp[(3) - (5)].node)->right, N);
-               (yyvsp[(3) - (5)].node)->val = (yyvsp[(5) - (5)].val);
-               (yyval.list) = list1((yyvsp[(3) - (5)].node));
-               yyerror("cannot parenthesize embedded type");
-       }
-    break;
-
-  case 236:
-#line 1599 "go.y"
-    {
-               (yyvsp[(3) - (5)].node)->right = nod(OIND, (yyvsp[(3) - (5)].node)->right, N);
-               (yyvsp[(3) - (5)].node)->val = (yyvsp[(5) - (5)].val);
-               (yyval.list) = list1((yyvsp[(3) - (5)].node));
-               yyerror("cannot parenthesize embedded type");
-       }
-    break;
-
-  case 237:
-#line 1608 "go.y"
-    {
-               Node *n;
-
-               (yyval.sym) = (yyvsp[(1) - (1)].sym);
-               n = oldname((yyvsp[(1) - (1)].sym));
-               if(n->pack != N)
-                       n->pack->used = 1;
-       }
-    break;
-
-  case 238:
-#line 1617 "go.y"
-    {
-               Pkg *pkg;
-
-               if((yyvsp[(1) - (3)].sym)->def == N || (yyvsp[(1) - (3)].sym)->def->op != OPACK) {
-                       yyerror("%S is not a package", (yyvsp[(1) - (3)].sym));
-                       pkg = localpkg;
-               } else {
-                       (yyvsp[(1) - (3)].sym)->def->used = 1;
-                       pkg = (yyvsp[(1) - (3)].sym)->def->pkg;
-               }
-               (yyval.sym) = restrictlookup((yyvsp[(3) - (3)].sym)->name, pkg);
-       }
-    break;
-
-  case 239:
-#line 1632 "go.y"
-    {
-               (yyval.node) = embedded((yyvsp[(1) - (1)].sym), localpkg);
-       }
-    break;
-
-  case 240:
-#line 1638 "go.y"
-    {
-               (yyval.node) = nod(ODCLFIELD, (yyvsp[(1) - (2)].node), (yyvsp[(2) - (2)].node));
-               ifacedcl((yyval.node));
-       }
-    break;
-
-  case 241:
-#line 1643 "go.y"
-    {
-               (yyval.node) = nod(ODCLFIELD, N, oldname((yyvsp[(1) - (1)].sym)));
-       }
-    break;
-
-  case 242:
-#line 1647 "go.y"
-    {
-               (yyval.node) = nod(ODCLFIELD, N, oldname((yyvsp[(2) - (3)].sym)));
-               yyerror("cannot parenthesize embedded type");
-       }
-    break;
-
-  case 243:
-#line 1654 "go.y"
-    {
-               // without func keyword
-               (yyvsp[(2) - (4)].list) = checkarglist((yyvsp[(2) - (4)].list), 1);
-               (yyval.node) = nod(OTFUNC, fakethis(), N);
-               (yyval.node)->list = (yyvsp[(2) - (4)].list);
-               (yyval.node)->rlist = (yyvsp[(4) - (4)].list);
-       }
-    break;
-
-  case 245:
-#line 1668 "go.y"
-    {
-               (yyval.node) = nod(ONONAME, N, N);
-               (yyval.node)->sym = (yyvsp[(1) - (2)].sym);
-               (yyval.node) = nod(OKEY, (yyval.node), (yyvsp[(2) - (2)].node));
-       }
-    break;
-
-  case 246:
-#line 1674 "go.y"
-    {
-               (yyval.node) = nod(ONONAME, N, N);
-               (yyval.node)->sym = (yyvsp[(1) - (2)].sym);
-               (yyval.node) = nod(OKEY, (yyval.node), (yyvsp[(2) - (2)].node));
-       }
-    break;
-
-  case 248:
-#line 1683 "go.y"
-    {
-               (yyval.list) = list1((yyvsp[(1) - (1)].node));
-       }
-    break;
-
-  case 249:
-#line 1687 "go.y"
-    {
-               (yyval.list) = list((yyvsp[(1) - (3)].list), (yyvsp[(3) - (3)].node));
-       }
-    break;
-
-  case 250:
-#line 1692 "go.y"
-    {
-               (yyval.list) = nil;
-       }
-    break;
-
-  case 251:
-#line 1696 "go.y"
-    {
-               (yyval.list) = (yyvsp[(1) - (2)].list);
-       }
-    break;
-
-  case 252:
-#line 1704 "go.y"
-    {
-               (yyval.node) = N;
-       }
-    break;
-
-  case 254:
-#line 1709 "go.y"
-    {
-               (yyval.node) = liststmt((yyvsp[(1) - (1)].list));
-       }
-    break;
-
-  case 256:
-#line 1714 "go.y"
-    {
-               (yyval.node) = N;
-       }
-    break;
-
-  case 262:
-#line 1725 "go.y"
-    {
-               (yyvsp[(1) - (2)].node) = nod(OLABEL, (yyvsp[(1) - (2)].node), N);
-               (yyvsp[(1) - (2)].node)->sym = dclstack;  // context, for goto restrictions
-       }
-    break;
-
-  case 263:
-#line 1730 "go.y"
-    {
-               NodeList *l;
-
-               (yyvsp[(1) - (4)].node)->defn = (yyvsp[(4) - (4)].node);
-               l = list1((yyvsp[(1) - (4)].node));
-               if((yyvsp[(4) - (4)].node))
-                       l = list(l, (yyvsp[(4) - (4)].node));
-               (yyval.node) = liststmt(l);
-       }
-    break;
-
-  case 264:
-#line 1740 "go.y"
-    {
-               // will be converted to OFALL
-               (yyval.node) = nod(OXFALL, N, N);
-               (yyval.node)->xoffset = block;
-       }
-    break;
-
-  case 265:
-#line 1746 "go.y"
-    {
-               (yyval.node) = nod(OBREAK, (yyvsp[(2) - (2)].node), N);
-       }
-    break;
-
-  case 266:
-#line 1750 "go.y"
-    {
-               (yyval.node) = nod(OCONTINUE, (yyvsp[(2) - (2)].node), N);
-       }
-    break;
-
-  case 267:
-#line 1754 "go.y"
-    {
-               (yyval.node) = nod(OPROC, (yyvsp[(2) - (2)].node), N);
-       }
-    break;
-
-  case 268:
-#line 1758 "go.y"
-    {
-               (yyval.node) = nod(ODEFER, (yyvsp[(2) - (2)].node), N);
-       }
-    break;
-
-  case 269:
-#line 1762 "go.y"
-    {
-               (yyval.node) = nod(OGOTO, (yyvsp[(2) - (2)].node), N);
-               (yyval.node)->sym = dclstack;  // context, for goto restrictions
-       }
-    break;
-
-  case 270:
-#line 1767 "go.y"
-    {
-               (yyval.node) = nod(ORETURN, N, N);
-               (yyval.node)->list = (yyvsp[(2) - (2)].list);
-               if((yyval.node)->list == nil && curfn != N) {
-                       NodeList *l;
-
-                       for(l=curfn->dcl; l; l=l->next) {
-                               if(l->n->class == PPARAM)
-                                       continue;
-                               if(l->n->class != PPARAMOUT)
-                                       break;
-                               if(l->n->sym->def != l->n)
-                                       yyerror("%s is shadowed during return", l->n->sym->name);
-                       }
-               }
-       }
-    break;
-
-  case 271:
-#line 1786 "go.y"
-    {
-               (yyval.list) = nil;
-               if((yyvsp[(1) - (1)].node) != N)
-                       (yyval.list) = list1((yyvsp[(1) - (1)].node));
-       }
-    break;
-
-  case 272:
-#line 1792 "go.y"
-    {
-               (yyval.list) = (yyvsp[(1) - (3)].list);
-               if((yyvsp[(3) - (3)].node) != N)
-                       (yyval.list) = list((yyval.list), (yyvsp[(3) - (3)].node));
-       }
-    break;
-
-  case 273:
-#line 1800 "go.y"
-    {
-               (yyval.list) = list1((yyvsp[(1) - (1)].node));
-       }
-    break;
-
-  case 274:
-#line 1804 "go.y"
-    {
-               (yyval.list) = list((yyvsp[(1) - (3)].list), (yyvsp[(3) - (3)].node));
-       }
-    break;
-
-  case 275:
-#line 1810 "go.y"
-    {
-               (yyval.list) = list1((yyvsp[(1) - (1)].node));
-       }
-    break;
-
-  case 276:
-#line 1814 "go.y"
-    {
-               (yyval.list) = list((yyvsp[(1) - (3)].list), (yyvsp[(3) - (3)].node));
-       }
-    break;
-
-  case 277:
-#line 1820 "go.y"
-    {
-               (yyval.list) = list1((yyvsp[(1) - (1)].node));
-       }
-    break;
-
-  case 278:
-#line 1824 "go.y"
-    {
-               (yyval.list) = list((yyvsp[(1) - (3)].list), (yyvsp[(3) - (3)].node));
-       }
-    break;
-
-  case 279:
-#line 1830 "go.y"
-    {
-               (yyval.list) = list1((yyvsp[(1) - (1)].node));
-       }
-    break;
-
-  case 280:
-#line 1834 "go.y"
-    {
-               (yyval.list) = list((yyvsp[(1) - (3)].list), (yyvsp[(3) - (3)].node));
-       }
-    break;
-
-  case 281:
-#line 1843 "go.y"
-    {
-               (yyval.list) = list1((yyvsp[(1) - (1)].node));
-       }
-    break;
-
-  case 282:
-#line 1847 "go.y"
-    {
-               (yyval.list) = list1((yyvsp[(1) - (1)].node));
-       }
-    break;
-
-  case 283:
-#line 1851 "go.y"
-    {
-               (yyval.list) = list((yyvsp[(1) - (3)].list), (yyvsp[(3) - (3)].node));
-       }
-    break;
-
-  case 284:
-#line 1855 "go.y"
-    {
-               (yyval.list) = list((yyvsp[(1) - (3)].list), (yyvsp[(3) - (3)].node));
-       }
-    break;
-
-  case 285:
-#line 1860 "go.y"
-    {
-               (yyval.list) = nil;
-       }
-    break;
-
-  case 286:
-#line 1864 "go.y"
-    {
-               (yyval.list) = (yyvsp[(1) - (2)].list);
-       }
-    break;
-
-  case 291:
-#line 1878 "go.y"
-    {
-               (yyval.node) = N;
-       }
-    break;
-
-  case 293:
-#line 1884 "go.y"
-    {
-               (yyval.list) = nil;
-       }
-    break;
-
-  case 295:
-#line 1890 "go.y"
-    {
-               (yyval.node) = N;
-       }
-    break;
-
-  case 297:
-#line 1896 "go.y"
-    {
-               (yyval.list) = nil;
-       }
-    break;
-
-  case 299:
-#line 1902 "go.y"
-    {
-               (yyval.list) = nil;
-       }
-    break;
-
-  case 301:
-#line 1908 "go.y"
-    {
-               (yyval.list) = nil;
-       }
-    break;
-
-  case 303:
-#line 1914 "go.y"
-    {
-               (yyval.val).ctype = CTxxx;
-       }
-    break;
-
-  case 305:
-#line 1924 "go.y"
-    {
-               importimport((yyvsp[(2) - (4)].sym), (yyvsp[(3) - (4)].val).u.sval);
-       }
-    break;
-
-  case 306:
-#line 1928 "go.y"
-    {
-               importvar((yyvsp[(2) - (4)].sym), (yyvsp[(3) - (4)].type));
-       }
-    break;
-
-  case 307:
-#line 1932 "go.y"
-    {
-               importconst((yyvsp[(2) - (5)].sym), types[TIDEAL], (yyvsp[(4) - (5)].node));
-       }
-    break;
-
-  case 308:
-#line 1936 "go.y"
-    {
-               importconst((yyvsp[(2) - (6)].sym), (yyvsp[(3) - (6)].type), (yyvsp[(5) - (6)].node));
-       }
-    break;
-
-  case 309:
-#line 1940 "go.y"
-    {
-               importtype((yyvsp[(2) - (4)].type), (yyvsp[(3) - (4)].type));
-       }
-    break;
-
-  case 310:
-#line 1944 "go.y"
-    {
-               if((yyvsp[(2) - (4)].node) == N) {
-                       dclcontext = PEXTERN;  // since we skip the funcbody below
-                       break;
-               }
-
-               (yyvsp[(2) - (4)].node)->inl = (yyvsp[(3) - (4)].list);
-
-               funcbody((yyvsp[(2) - (4)].node));
-               importlist = list(importlist, (yyvsp[(2) - (4)].node));
-
-               if(debug['E']) {
-                       print("import [%Z] func %lN \n", importpkg->path, (yyvsp[(2) - (4)].node));
-                       if(debug['m'] > 2 && (yyvsp[(2) - (4)].node)->inl)
-                               print("inl body:%+H\n", (yyvsp[(2) - (4)].node)->inl);
-               }
-       }
-    break;
-
-  case 311:
-#line 1964 "go.y"
-    {
-               (yyval.sym) = (yyvsp[(1) - (1)].sym);
-               structpkg = (yyval.sym)->pkg;
-       }
-    break;
-
-  case 312:
-#line 1971 "go.y"
-    {
-               (yyval.type) = pkgtype((yyvsp[(1) - (1)].sym));
-               importsym((yyvsp[(1) - (1)].sym), OTYPE);
-       }
-    break;
-
-  case 318:
-#line 1991 "go.y"
-    {
-               (yyval.type) = pkgtype((yyvsp[(1) - (1)].sym));
-       }
-    break;
-
-  case 319:
-#line 1995 "go.y"
-    {
-               // predefined name like uint8
-               (yyvsp[(1) - (1)].sym) = pkglookup((yyvsp[(1) - (1)].sym)->name, builtinpkg);
-               if((yyvsp[(1) - (1)].sym)->def == N || (yyvsp[(1) - (1)].sym)->def->op != OTYPE) {
-                       yyerror("%s is not a type", (yyvsp[(1) - (1)].sym)->name);
-                       (yyval.type) = T;
-               } else
-                       (yyval.type) = (yyvsp[(1) - (1)].sym)->def->type;
-       }
-    break;
-
-  case 320:
-#line 2005 "go.y"
-    {
-               (yyval.type) = aindex(N, (yyvsp[(3) - (3)].type));
-       }
-    break;
-
-  case 321:
-#line 2009 "go.y"
-    {
-               (yyval.type) = aindex(nodlit((yyvsp[(2) - (4)].val)), (yyvsp[(4) - (4)].type));
-       }
-    break;
-
-  case 322:
-#line 2013 "go.y"
-    {
-               (yyval.type) = maptype((yyvsp[(3) - (5)].type), (yyvsp[(5) - (5)].type));
-       }
-    break;
-
-  case 323:
-#line 2017 "go.y"
-    {
-               (yyval.type) = tostruct((yyvsp[(3) - (4)].list));
-       }
-    break;
-
-  case 324:
-#line 2021 "go.y"
-    {
-               (yyval.type) = tointerface((yyvsp[(3) - (4)].list));
-       }
-    break;
-
-  case 325:
-#line 2025 "go.y"
-    {
-               (yyval.type) = ptrto((yyvsp[(2) - (2)].type));
-       }
-    break;
-
-  case 326:
-#line 2029 "go.y"
-    {
-               (yyval.type) = typ(TCHAN);
-               (yyval.type)->type = (yyvsp[(2) - (2)].type);
-               (yyval.type)->chan = Cboth;
-       }
-    break;
-
-  case 327:
-#line 2035 "go.y"
-    {
-               (yyval.type) = typ(TCHAN);
-               (yyval.type)->type = (yyvsp[(3) - (4)].type);
-               (yyval.type)->chan = Cboth;
-       }
-    break;
-
-  case 328:
-#line 2041 "go.y"
-    {
-               (yyval.type) = typ(TCHAN);
-               (yyval.type)->type = (yyvsp[(3) - (3)].type);
-               (yyval.type)->chan = Csend;
-       }
-    break;
-
-  case 329:
-#line 2049 "go.y"
-    {
-               (yyval.type) = typ(TCHAN);
-               (yyval.type)->type = (yyvsp[(3) - (3)].type);
-               (yyval.type)->chan = Crecv;
-       }
-    break;
-
-  case 330:
-#line 2057 "go.y"
-    {
-               (yyval.type) = functype(nil, (yyvsp[(3) - (5)].list), (yyvsp[(5) - (5)].list));
-       }
-    break;
-
-  case 331:
-#line 2063 "go.y"
-    {
-               (yyval.node) = nod(ODCLFIELD, N, typenod((yyvsp[(2) - (3)].type)));
-               if((yyvsp[(1) - (3)].sym))
-                       (yyval.node)->left = newname((yyvsp[(1) - (3)].sym));
-               (yyval.node)->val = (yyvsp[(3) - (3)].val);
-       }
-    break;
-
-  case 332:
-#line 2070 "go.y"
-    {
-               Type *t;
-       
-               t = typ(TARRAY);
-               t->bound = -1;
-               t->type = (yyvsp[(3) - (4)].type);
-
-               (yyval.node) = nod(ODCLFIELD, N, typenod(t));
-               if((yyvsp[(1) - (4)].sym))
-                       (yyval.node)->left = newname((yyvsp[(1) - (4)].sym));
-               (yyval.node)->isddd = 1;
-               (yyval.node)->val = (yyvsp[(4) - (4)].val);
-       }
-    break;
-
-  case 333:
-#line 2086 "go.y"
-    {
-               Sym *s;
-               Pkg *p;
-
-               if((yyvsp[(1) - (3)].sym) != S && strcmp((yyvsp[(1) - (3)].sym)->name, "?") != 0) {
-                       (yyval.node) = nod(ODCLFIELD, newname((yyvsp[(1) - (3)].sym)), typenod((yyvsp[(2) - (3)].type)));
-                       (yyval.node)->val = (yyvsp[(3) - (3)].val);
-               } else {
-                       s = (yyvsp[(2) - (3)].type)->sym;
-                       if(s == S && isptr[(yyvsp[(2) - (3)].type)->etype])
-                               s = (yyvsp[(2) - (3)].type)->type->sym;
-                       p = importpkg;
-                       if((yyvsp[(1) - (3)].sym) != S)
-                               p = (yyvsp[(1) - (3)].sym)->pkg;
-                       (yyval.node) = embedded(s, p);
-                       (yyval.node)->right = typenod((yyvsp[(2) - (3)].type));
-                       (yyval.node)->val = (yyvsp[(3) - (3)].val);
-               }
-       }
-    break;
-
-  case 334:
-#line 2108 "go.y"
-    {
-               (yyval.node) = nod(ODCLFIELD, newname((yyvsp[(1) - (5)].sym)), typenod(functype(fakethis(), (yyvsp[(3) - (5)].list), (yyvsp[(5) - (5)].list))));
-       }
-    break;
-
-  case 335:
-#line 2112 "go.y"
-    {
-               (yyval.node) = nod(ODCLFIELD, N, typenod((yyvsp[(1) - (1)].type)));
-       }
-    break;
-
-  case 336:
-#line 2117 "go.y"
-    {
-               (yyval.list) = nil;
-       }
-    break;
-
-  case 338:
-#line 2124 "go.y"
-    {
-               (yyval.list) = (yyvsp[(2) - (3)].list);
-       }
-    break;
-
-  case 339:
-#line 2128 "go.y"
-    {
-               (yyval.list) = list1(nod(ODCLFIELD, N, typenod((yyvsp[(1) - (1)].type))));
-       }
-    break;
-
-  case 340:
-#line 2138 "go.y"
-    {
-               (yyval.node) = nodlit((yyvsp[(1) - (1)].val));
-       }
-    break;
-
-  case 341:
-#line 2142 "go.y"
-    {
-               (yyval.node) = nodlit((yyvsp[(2) - (2)].val));
-               switch((yyval.node)->val.ctype){
-               case CTINT:
-               case CTRUNE:
-                       mpnegfix((yyval.node)->val.u.xval);
-                       break;
-               case CTFLT:
-                       mpnegflt((yyval.node)->val.u.fval);
-                       break;
-               case CTCPLX:
-                       mpnegflt(&(yyval.node)->val.u.cval->real);
-                       mpnegflt(&(yyval.node)->val.u.cval->imag);
-                       break;
-               default:
-                       yyerror("bad negated constant");
-               }
-       }
-    break;
-
-  case 342:
-#line 2161 "go.y"
-    {
-               (yyval.node) = oldname(pkglookup((yyvsp[(1) - (1)].sym)->name, builtinpkg));
-               if((yyval.node)->op != OLITERAL)
-                       yyerror("bad constant %S", (yyval.node)->sym);
-       }
-    break;
-
-  case 344:
-#line 2170 "go.y"
-    {
-               if((yyvsp[(2) - (5)].node)->val.ctype == CTRUNE && (yyvsp[(4) - (5)].node)->val.ctype == CTINT) {
-                       (yyval.node) = (yyvsp[(2) - (5)].node);
-                       mpaddfixfix((yyvsp[(2) - (5)].node)->val.u.xval, (yyvsp[(4) - (5)].node)->val.u.xval, 0);
-                       break;
-               }
-               (yyvsp[(4) - (5)].node)->val.u.cval->real = (yyvsp[(4) - (5)].node)->val.u.cval->imag;
-               mpmovecflt(&(yyvsp[(4) - (5)].node)->val.u.cval->imag, 0.0);
-               (yyval.node) = nodcplxlit((yyvsp[(2) - (5)].node)->val, (yyvsp[(4) - (5)].node)->val);
-       }
-    break;
-
-  case 347:
-#line 2186 "go.y"
-    {
-               (yyval.list) = list1((yyvsp[(1) - (1)].node));
-       }
-    break;
-
-  case 348:
-#line 2190 "go.y"
-    {
-               (yyval.list) = list((yyvsp[(1) - (3)].list), (yyvsp[(3) - (3)].node));
-       }
-    break;
-
-  case 349:
-#line 2196 "go.y"
-    {
-               (yyval.list) = list1((yyvsp[(1) - (1)].node));
-       }
-    break;
-
-  case 350:
-#line 2200 "go.y"
-    {
-               (yyval.list) = list((yyvsp[(1) - (3)].list), (yyvsp[(3) - (3)].node));
-       }
-    break;
-
-  case 351:
-#line 2206 "go.y"
-    {
-               (yyval.list) = list1((yyvsp[(1) - (1)].node));
-       }
-    break;
-
-  case 352:
-#line 2210 "go.y"
-    {
-               (yyval.list) = list((yyvsp[(1) - (3)].list), (yyvsp[(3) - (3)].node));
-       }
-    break;
-
-
-/* Line 1267 of yacc.c.  */
-#line 4909 "y.tab.c"
-      default: break;
-    }
-  YY_SYMBOL_PRINT ("-> $$ =", yyr1[yyn], &yyval, &yyloc);
-
-  YYPOPSTACK (yylen);
-  yylen = 0;
-  YY_STACK_PRINT (yyss, yyssp);
-
-  *++yyvsp = yyval;
-
-
-  /* Now `shift' the result of the reduction.  Determine what state
-     that goes to, based on the state we popped back to and the rule
-     number reduced by.  */
-
-  yyn = yyr1[yyn];
-
-  yystate = yypgoto[yyn - YYNTOKENS] + *yyssp;
-  if (0 <= yystate && yystate <= YYLAST && yycheck[yystate] == *yyssp)
-    yystate = yytable[yystate];
-  else
-    yystate = yydefgoto[yyn - YYNTOKENS];
-
-  goto yynewstate;
-
-
-/*------------------------------------.
-| yyerrlab -- here on detecting error |
-`------------------------------------*/
-yyerrlab:
-  /* If not already recovering from an error, report this error.  */
-  if (!yyerrstatus)
-    {
-      ++yynerrs;
-#if ! YYERROR_VERBOSE
-      yyerror (YY_("syntax error"));
-#else
-      {
-       YYSIZE_T yysize = yysyntax_error (0, yystate, yychar);
-       if (yymsg_alloc < yysize && yymsg_alloc < YYSTACK_ALLOC_MAXIMUM)
-         {
-           YYSIZE_T yyalloc = 2 * yysize;
-           if (! (yysize <= yyalloc && yyalloc <= YYSTACK_ALLOC_MAXIMUM))
-             yyalloc = YYSTACK_ALLOC_MAXIMUM;
-           if (yymsg != yymsgbuf)
-             YYSTACK_FREE (yymsg);
-           yymsg = (char *) YYSTACK_ALLOC (yyalloc);
-           if (yymsg)
-             yymsg_alloc = yyalloc;
-           else
-             {
-               yymsg = yymsgbuf;
-               yymsg_alloc = sizeof yymsgbuf;
-             }
-         }
-
-       if (0 < yysize && yysize <= yymsg_alloc)
-         {
-           (void) yysyntax_error (yymsg, yystate, yychar);
-           yyerror (yymsg);
-         }
-       else
-         {
-           yyerror (YY_("syntax error"));
-           if (yysize != 0)
-             goto yyexhaustedlab;
-         }
-      }
-#endif
-    }
-
-
-
-  if (yyerrstatus == 3)
-    {
-      /* If just tried and failed to reuse look-ahead token after an
-        error, discard it.  */
-
-      if (yychar <= YYEOF)
-       {
-         /* Return failure if at end of input.  */
-         if (yychar == YYEOF)
-           YYABORT;
-       }
-      else
-       {
-         yydestruct ("Error: discarding",
-                     yytoken, &yylval);
-         yychar = YYEMPTY;
-       }
-    }
-
-  /* Else will try to reuse look-ahead token after shifting the error
-     token.  */
-  goto yyerrlab1;
-
-
-/*---------------------------------------------------.
-| yyerrorlab -- error raised explicitly by YYERROR.  |
-`---------------------------------------------------*/
-yyerrorlab:
-
-  /* Pacify compilers like GCC when the user code never invokes
-     YYERROR and the label yyerrorlab therefore never appears in user
-     code.  */
-  if (/*CONSTCOND*/ 0)
-     goto yyerrorlab;
-
-  /* Do not reclaim the symbols of the rule which action triggered
-     this YYERROR.  */
-  YYPOPSTACK (yylen);
-  yylen = 0;
-  YY_STACK_PRINT (yyss, yyssp);
-  yystate = *yyssp;
-  goto yyerrlab1;
-
-
-/*-------------------------------------------------------------.
-| yyerrlab1 -- common code for both syntax error and YYERROR.  |
-`-------------------------------------------------------------*/
-yyerrlab1:
-  yyerrstatus = 3;     /* Each real token shifted decrements this.  */
-
-  for (;;)
-    {
-      yyn = yypact[yystate];
-      if (yyn != YYPACT_NINF)
-       {
-         yyn += YYTERROR;
-         if (0 <= yyn && yyn <= YYLAST && yycheck[yyn] == YYTERROR)
-           {
-             yyn = yytable[yyn];
-             if (0 < yyn)
-               break;
-           }
-       }
-
-      /* Pop the current state because it cannot handle the error token.  */
-      if (yyssp == yyss)
-       YYABORT;
-
-
-      yydestruct ("Error: popping",
-                 yystos[yystate], yyvsp);
-      YYPOPSTACK (1);
-      yystate = *yyssp;
-      YY_STACK_PRINT (yyss, yyssp);
-    }
-
-  if (yyn == YYFINAL)
-    YYACCEPT;
-
-  *++yyvsp = yylval;
-
-
-  /* Shift the error token.  */
-  YY_SYMBOL_PRINT ("Shifting", yystos[yyn], yyvsp, yylsp);
-
-  yystate = yyn;
-  goto yynewstate;
-
-
-/*-------------------------------------.
-| yyacceptlab -- YYACCEPT comes here.  |
-`-------------------------------------*/
-yyacceptlab:
-  yyresult = 0;
-  goto yyreturn;
-
-/*-----------------------------------.
-| yyabortlab -- YYABORT comes here.  |
-`-----------------------------------*/
-yyabortlab:
-  yyresult = 1;
-  goto yyreturn;
-
-#ifndef yyoverflow
-/*-------------------------------------------------.
-| yyexhaustedlab -- memory exhaustion comes here.  |
-`-------------------------------------------------*/
-yyexhaustedlab:
-  yyerror (YY_("memory exhausted"));
-  yyresult = 2;
-  /* Fall through.  */
-#endif
-
-yyreturn:
-  if (yychar != YYEOF && yychar != YYEMPTY)
-     yydestruct ("Cleanup: discarding lookahead",
-                yytoken, &yylval);
-  /* Do not reclaim the symbols of the rule which action triggered
-     this YYABORT or YYACCEPT.  */
-  YYPOPSTACK (yylen);
-  YY_STACK_PRINT (yyss, yyssp);
-  while (yyssp != yyss)
-    {
-      yydestruct ("Cleanup: popping",
-                 yystos[*yyssp], yyvsp);
-      YYPOPSTACK (1);
-    }
-#ifndef yyoverflow
-  if (yyss != yyssa)
-    YYSTACK_FREE (yyss);
-#endif
-#if YYERROR_VERBOSE
-  if (yymsg != yymsgbuf)
-    YYSTACK_FREE (yymsg);
-#endif
-  /* Make sure YYID is used.  */
-  return YYID (yyresult);
-}
-
-
-#line 2214 "go.y"
-
-
-static void
-fixlbrace(int lbr)
-{
-       // If the opening brace was an LBODY,
-       // set up for another one now that we're done.
-       // See comment in lex.c about loophack.
-       if(lbr == LBODY)
-               loophack = 1;
-}
-
-
diff --git a/src/cmd/gc/y.tab.h b/src/cmd/gc/y.tab.h
deleted file mode 100644 (file)
index d01fbe1..0000000
+++ /dev/null
@@ -1,167 +0,0 @@
-/* A Bison parser, made by GNU Bison 2.3.  */
-
-/* Skeleton interface for Bison's Yacc-like parsers in C
-
-   Copyright (C) 1984, 1989, 1990, 2000, 2001, 2002, 2003, 2004, 2005, 2006
-   Free Software Foundation, Inc.
-
-   This program is free software; you can redistribute it and/or modify
-   it under the terms of the GNU General Public License as published by
-   the Free Software Foundation; either version 2, or (at your option)
-   any later version.
-
-   This program is distributed in the hope that it will be useful,
-   but WITHOUT ANY WARRANTY; without even the implied warranty of
-   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-   GNU General Public License for more details.
-
-   You should have received a copy of the GNU General Public License
-   along with this program; if not, write to the Free Software
-   Foundation, Inc., 51 Franklin Street, Fifth Floor,
-   Boston, MA 02110-1301, USA.  */
-
-/* As a special exception, you may create a larger work that contains
-   part or all of the Bison parser skeleton and distribute that work
-   under terms of your choice, so long as that work isn't itself a
-   parser generator using the skeleton or a modified version thereof
-   as a parser skeleton.  Alternatively, if you modify or redistribute
-   the parser skeleton itself, you may (at your option) remove this
-   special exception, which will cause the skeleton and the resulting
-   Bison output files to be licensed under the GNU General Public
-   License without this special exception.
-
-   This special exception was added by the Free Software Foundation in
-   version 2.2 of Bison.  */
-
-/* Tokens.  */
-#ifndef YYTOKENTYPE
-# define YYTOKENTYPE
-   /* Put the tokens into the symbol table, so that GDB and other debuggers
-      know about them.  */
-   enum yytokentype {
-     LLITERAL = 258,
-     LASOP = 259,
-     LCOLAS = 260,
-     LBREAK = 261,
-     LCASE = 262,
-     LCHAN = 263,
-     LCONST = 264,
-     LCONTINUE = 265,
-     LDDD = 266,
-     LDEFAULT = 267,
-     LDEFER = 268,
-     LELSE = 269,
-     LFALL = 270,
-     LFOR = 271,
-     LFUNC = 272,
-     LGO = 273,
-     LGOTO = 274,
-     LIF = 275,
-     LIMPORT = 276,
-     LINTERFACE = 277,
-     LMAP = 278,
-     LNAME = 279,
-     LPACKAGE = 280,
-     LRANGE = 281,
-     LRETURN = 282,
-     LSELECT = 283,
-     LSTRUCT = 284,
-     LSWITCH = 285,
-     LTYPE = 286,
-     LVAR = 287,
-     LANDAND = 288,
-     LANDNOT = 289,
-     LBODY = 290,
-     LCOMM = 291,
-     LDEC = 292,
-     LEQ = 293,
-     LGE = 294,
-     LGT = 295,
-     LIGNORE = 296,
-     LINC = 297,
-     LLE = 298,
-     LLSH = 299,
-     LLT = 300,
-     LNE = 301,
-     LOROR = 302,
-     LRSH = 303,
-     NotPackage = 304,
-     NotParen = 305,
-     PreferToRightParen = 306
-   };
-#endif
-/* Tokens.  */
-#define LLITERAL 258
-#define LASOP 259
-#define LCOLAS 260
-#define LBREAK 261
-#define LCASE 262
-#define LCHAN 263
-#define LCONST 264
-#define LCONTINUE 265
-#define LDDD 266
-#define LDEFAULT 267
-#define LDEFER 268
-#define LELSE 269
-#define LFALL 270
-#define LFOR 271
-#define LFUNC 272
-#define LGO 273
-#define LGOTO 274
-#define LIF 275
-#define LIMPORT 276
-#define LINTERFACE 277
-#define LMAP 278
-#define LNAME 279
-#define LPACKAGE 280
-#define LRANGE 281
-#define LRETURN 282
-#define LSELECT 283
-#define LSTRUCT 284
-#define LSWITCH 285
-#define LTYPE 286
-#define LVAR 287
-#define LANDAND 288
-#define LANDNOT 289
-#define LBODY 290
-#define LCOMM 291
-#define LDEC 292
-#define LEQ 293
-#define LGE 294
-#define LGT 295
-#define LIGNORE 296
-#define LINC 297
-#define LLE 298
-#define LLSH 299
-#define LLT 300
-#define LNE 301
-#define LOROR 302
-#define LRSH 303
-#define NotPackage 304
-#define NotParen 305
-#define PreferToRightParen 306
-
-
-
-
-#if ! defined YYSTYPE && ! defined YYSTYPE_IS_DECLARED
-typedef union YYSTYPE
-#line 28 "go.y"
-{
-       Node*           node;
-       NodeList*               list;
-       Type*           type;
-       Sym*            sym;
-       struct  Val     val;
-       int             i;
-}
-/* Line 1529 of yacc.c.  */
-#line 160 "y.tab.h"
-       YYSTYPE;
-# define yystype YYSTYPE /* obsolescent; will be withdrawn */
-# define YYSTYPE_IS_DECLARED 1
-# define YYSTYPE_IS_TRIVIAL 1
-#endif
-
-extern YYSTYPE yylval;
-
diff --git a/src/cmd/gc/yerr.h b/src/cmd/gc/yerr.h
deleted file mode 100644 (file)
index d0dd639..0000000
+++ /dev/null
@@ -1,79 +0,0 @@
-// Copyright 2010 The Go Authors.  All rights reserved.
-// Use of this source code is governed by a BSD-style
-// license that can be found in the LICENSE file.
-
-// Example-based syntax error messages.
-// See bisonerrors, Makefile, go.y.
-
-static struct {
-       int yystate;
-       int yychar;
-       char *msg;
-} yymsg[] = {
-       // Each line of the form % token list
-       // is converted by bisonerrors into the yystate and yychar caused
-       // by that token list.
-
-       {222, ',',
-       "unexpected comma during import block"},
-
-       {32, ';',
-       "missing import path; require quoted string"},
-
-       {380, ';',
-       "missing { after if clause"},
-
-       {401, ';',
-       "missing { after switch clause"},
-
-       {239, ';',
-       "missing { after for clause"},
-
-       {478, LBODY,
-       "missing { after for clause"},
-
-       {22, '{',
-       "unexpected semicolon or newline before {"},
-
-       {145, ';',
-       "unexpected semicolon or newline in type declaration"},
-
-       {37, '}',
-       "unexpected } in channel type"},
-       
-       {37, ')',
-       "unexpected ) in channel type"},
-       
-       {37, ',',
-       "unexpected comma in channel type"},
-
-       {441, LELSE,
-       "unexpected semicolon or newline before else"},
-
-       {259, ',',
-       "name list not allowed in interface type"},
-
-       {239, LVAR,
-       "var declaration not allowed in for initializer"},
-
-       {65, '{',
-       "unexpected { at end of statement"},
-
-       {379, '{',
-       "unexpected { at end of statement"},
-       
-       {126, ';',
-       "argument to go/defer must be function call"},
-       
-       {428, ';',
-       "need trailing comma before newline in composite literal"},
-       
-       {439, ';',
-       "need trailing comma before newline in composite literal"},
-       
-       {113, LNAME,
-       "nested func not allowed"},
-
-       {647, ';',
-       "else must be followed by if or statement block"}
-};
diff --git a/src/cmd/new5a/a.y b/src/cmd/new5a/a.y
deleted file mode 100644 (file)
index 39fab8f..0000000
+++ /dev/null
@@ -1,795 +0,0 @@
-// Inferno utils/5a/a.y
-// http://code.google.com/p/inferno-os/source/browse/utils/5a/a.y
-//
-//     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 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.
-
-%{
-package main
-
-import (
-       "cmd/internal/asm"
-       "cmd/internal/obj"
-       . "cmd/internal/obj/arm"
-)
-%}
-
-%union {
-       sym *asm.Sym
-       lval int32
-       dval float64
-       sval string
-       addr obj.Addr
-}
-
-%left  '|'
-%left  '^'
-%left  '&'
-%left  '<' '>'
-%left  '+' '-'
-%left  '*' '/' '%'
-%token <lval>  LTYPE1 LTYPE2 LTYPE3 LTYPE4 LTYPE5
-%token <lval>  LTYPE6 LTYPE7 LTYPE8 LTYPE9 LTYPEA
-%token <lval>  LTYPEB LTYPEC LTYPED LTYPEE
-%token <lval>  LTYPEG LTYPEH LTYPEI LTYPEJ LTYPEK
-%token <lval>  LTYPEL LTYPEM LTYPEN LTYPEBX LTYPEPLD
-%token <lval>  LCONST LSP LSB LFP LPC
-%token <lval>  LTYPEX LTYPEPC LTYPEF LR LREG LF LFREG LC LCREG LPSR LFCR
-%token <lval>  LCOND LS LAT LGLOBL
-%token <dval>  LFCONST
-%token <sval>  LSCONST
-%token <sym>   LNAME LLAB LVAR
-%type  <lval>  con expr oexpr pointer offset sreg spreg creg
-%type  <lval>  rcon cond reglist
-%type  <addr>  gen rel reg regreg freg shift fcon frcon textsize
-%type  <addr>  imm ximm name oreg ireg nireg ioreg imsr
-%%
-prog:
-|      prog
-       {
-               stmtline = asm.Lineno;
-       }
-       line
-
-line:
-       LNAME ':'
-       {
-               $1 = asm.LabelLookup($1);
-               if $1.Type == LLAB && $1.Value != int64(asm.PC) {
-                       yyerror("redeclaration of %s", $1.Labelname)
-               }
-               $1.Type = LLAB;
-               $1.Value = int64(asm.PC)
-       }
-       line
-|      LNAME '=' expr ';'
-       {
-               $1.Type = LVAR;
-               $1.Value = int64($3);
-       }
-|      LVAR '=' expr ';'
-       {
-               if $1.Value != int64($3) {
-                       yyerror("redeclaration of %s", $1.Name)
-               }
-               $1.Value = int64($3);
-       }
-|      ';'
-|      inst ';'
-|      error ';'
-
-inst:
-/*
- * ADD
- */
-       LTYPE1 cond imsr ',' spreg ',' reg
-       {
-               outcode($1, $2, &$3, $5, &$7);
-       }
-|      LTYPE1 cond imsr ',' spreg ','
-       {
-               outcode($1, $2, &$3, $5, &nullgen);
-       }
-|      LTYPE1 cond imsr ',' reg
-       {
-               outcode($1, $2, &$3, 0, &$5);
-       }
-/*
- * MVN
- */
-|      LTYPE2 cond imsr ',' reg
-       {
-               outcode($1, $2, &$3, 0, &$5);
-       }
-/*
- * MOVW
- */
-|      LTYPE3 cond gen ',' gen
-       {
-               outcode($1, $2, &$3, 0, &$5);
-       }
-/*
- * B/BL
- */
-|      LTYPE4 cond comma rel
-       {
-               outcode($1, $2, &nullgen, 0, &$4);
-       }
-|      LTYPE4 cond comma nireg
-       {
-               outcode($1, $2, &nullgen, 0, &$4);
-       }
-/*
- * BX
- */
-|      LTYPEBX comma ireg
-       {
-               outcode($1, Always, &nullgen, 0, &$3);
-       }
-/*
- * BEQ
- */
-|      LTYPE5 comma rel
-       {
-               outcode($1, Always, &nullgen, 0, &$3);
-       }
-/*
- * SWI
- */
-|      LTYPE6 cond comma gen
-       {
-               outcode($1, $2, &nullgen, 0, &$4);
-       }
-/*
- * CMP
- */
-|      LTYPE7 cond imsr ',' spreg comma
-       {
-               outcode($1, $2, &$3, $5, &nullgen);
-       }
-/*
- * MOVM
- */
-|      LTYPE8 cond ioreg ',' '[' reglist ']'
-       {
-               var g obj.Addr
-
-               g = nullgen;
-               g.Type = obj.TYPE_CONST;
-               g.Offset = int64($6);
-               outcode($1, $2, &$3, 0, &g);
-       }
-|      LTYPE8 cond '[' reglist ']' ',' ioreg
-       {
-               var g obj.Addr
-
-               g = nullgen;
-               g.Type = obj.TYPE_CONST;
-               g.Offset = int64($4);
-               outcode($1, $2, &g, 0, &$7);
-       }
-/*
- * SWAP
- */
-|      LTYPE9 cond reg ',' ireg ',' reg
-       {
-               outcode($1, $2, &$5, int32($3.Reg), &$7);
-       }
-|      LTYPE9 cond reg ',' ireg comma
-       {
-               outcode($1, $2, &$5, int32($3.Reg), &$3);
-       }
-|      LTYPE9 cond comma ireg ',' reg
-       {
-               outcode($1, $2, &$4, int32($6.Reg), &$6);
-       }
-/*
- * RET
- */
-|      LTYPEA cond comma
-       {
-               outcode($1, $2, &nullgen, 0, &nullgen);
-       }
-/*
- * TEXT
- */
-|      LTYPEB name ',' '$' textsize
-       {
-               asm.Settext($2.Sym);
-               outcode($1, Always, &$2, 0, &$5);
-       }
-|      LTYPEB name ',' con ',' '$' textsize
-       {
-               asm.Settext($2.Sym);
-               outcode($1, Always, &$2, 0, &$7);
-               if asm.Pass > 1 {
-                       lastpc.From3.Type = obj.TYPE_CONST;
-                       lastpc.From3.Offset = int64($4)
-               }
-       }
-/*
- * GLOBL
- */
-|      LGLOBL name ',' imm
-       {
-               asm.Settext($2.Sym)
-               outcode($1, Always, &$2, 0, &$4)
-       }
-|      LGLOBL name ',' con ',' imm
-       {
-               asm.Settext($2.Sym)
-               outcode($1, Always, &$2, 0, &$6)
-               if asm.Pass > 1 {
-                       lastpc.From3.Type = obj.TYPE_CONST
-                       lastpc.From3.Offset = int64($4)
-               }
-       }
-
-/*
- * DATA
- */
-|      LTYPEC name '/' con ',' ximm
-       {
-               outcode($1, Always, &$2, 0, &$6)
-               if asm.Pass > 1 {
-                       lastpc.From3.Type = obj.TYPE_CONST
-                       lastpc.From3.Offset = int64($4)
-               }
-       }
-/*
- * CASE
- */
-|      LTYPED cond reg comma
-       {
-               outcode($1, $2, &$3, 0, &nullgen);
-       }
-/*
- * word
- */
-|      LTYPEH comma ximm
-       {
-               outcode($1, Always, &nullgen, 0, &$3);
-       }
-/*
- * floating-point coprocessor
- */
-|      LTYPEI cond freg ',' freg
-       {
-               outcode($1, $2, &$3, 0, &$5);
-       }
-|      LTYPEK cond frcon ',' freg
-       {
-               outcode($1, $2, &$3, 0, &$5);
-       }
-|      LTYPEK cond frcon ',' LFREG ',' freg
-       {
-               outcode($1, $2, &$3, $5, &$7);
-       }
-|      LTYPEL cond freg ',' freg comma
-       {
-               outcode($1, $2, &$3, int32($5.Reg), &nullgen);
-       }
-/*
- * MCR MRC
- */
-|      LTYPEJ cond con ',' expr ',' spreg ',' creg ',' creg oexpr
-       {
-               var g obj.Addr
-
-               g = nullgen;
-               g.Type = obj.TYPE_CONST;
-               g.Offset = int64(
-                       (0xe << 24) |           /* opcode */
-                       ($1 << 20) |            /* MCR/MRC */
-                       (($2^C_SCOND_XOR) << 28) |              /* scond */
-                       (($3 & 15) << 8) |      /* coprocessor number */
-                       (($5 & 7) << 21) |      /* coprocessor operation */
-                       (($7 & 15) << 12) |     /* arm register */
-                       (($9 & 15) << 16) |     /* Crn */
-                       (($11 & 15) << 0) |     /* Crm */
-                       (($12 & 7) << 5) |      /* coprocessor information */
-                       (1<<4));                        /* must be set */
-               outcode(AMRC, Always, &nullgen, 0, &g);
-       }
-/*
- * MULL r1,r2,(hi,lo)
- */
-|      LTYPEM cond reg ',' reg ',' regreg
-       {
-               outcode($1, $2, &$3, int32($5.Reg), &$7);
-       }
-/*
- * MULA r1,r2,r3,r4: (r1*r2+r3) & 0xffffffff . r4
- * MULAW{T,B} r1,r2,r3,r4
- */
-|      LTYPEN cond reg ',' reg ',' reg ',' spreg
-       {
-               $7.Type = obj.TYPE_REGREG2;
-               $7.Offset = int64($9);
-               outcode($1, $2, &$3, int32($5.Reg), &$7);
-       }
-/*
- * PLD
- */
-|      LTYPEPLD oreg
-       {
-               outcode($1, Always, &$2, 0, &nullgen);
-       }
-/*
- * PCDATA
- */
-|      LTYPEPC gen ',' gen
-       {
-               if $2.Type != obj.TYPE_CONST || $4.Type != obj.TYPE_CONST {
-                       yyerror("arguments to PCDATA must be integer constants")
-               }
-               outcode($1, Always, &$2, 0, &$4);
-       }
-/*
- * FUNCDATA
- */
-|      LTYPEF gen ',' gen
-       {
-               if $2.Type != obj.TYPE_CONST {
-                       yyerror("index for FUNCDATA must be integer constant")
-               }
-               if $4.Type != obj.NAME_EXTERN && $4.Type != obj.NAME_STATIC && $4.Type != obj.TYPE_MEM {
-                       yyerror("value for FUNCDATA must be symbol reference")
-               }
-               outcode($1, Always, &$2, 0, &$4);
-       }
-/*
- * END
- */
-|      LTYPEE comma
-       {
-               outcode($1, Always, &nullgen, 0, &nullgen);
-       }
-
-textsize:
-       LCONST
-       {
-               $$ = nullgen;
-               $$.Type = obj.TYPE_TEXTSIZE;
-               $$.Offset = int64($1)
-               $$.U.Argsize = obj.ArgsSizeUnknown;
-       }
-|      '-' LCONST
-       {
-               $$ = nullgen;
-               $$.Type = obj.TYPE_TEXTSIZE;
-               $$.Offset = -int64($2)
-               $$.U.Argsize = obj.ArgsSizeUnknown;
-       }
-|      LCONST '-' LCONST
-       {
-               $$ = nullgen;
-               $$.Type = obj.TYPE_TEXTSIZE;
-               $$.Offset = int64($1)
-               $$.U.Argsize = int32($3);
-       }
-|      '-' LCONST '-' LCONST
-       {
-               $$ = nullgen;
-               $$.Type = obj.TYPE_TEXTSIZE;
-               $$.Offset = -int64($2)
-               $$.U.Argsize = int32($4);
-       }
-
-cond:
-       {
-               $$ = Always;
-       }
-|      cond LCOND
-       {
-               $$ = ($1 & ^ C_SCOND) | $2;
-       }
-|      cond LS
-       {
-               $$ = $1 | $2;
-       }
-
-comma:
-|      ',' comma
-
-rel:
-       con '(' LPC ')'
-       {
-               $$ = nullgen;
-               $$.Type = obj.TYPE_BRANCH;
-               $$.Offset = int64($1) + int64(asm.PC);
-       }
-|      LNAME offset
-       {
-               $1 = asm.LabelLookup($1);
-               $$ = nullgen;
-               if asm.Pass == 2 && $1.Type != LLAB {
-                       yyerror("undefined label: %s", $1.Labelname)
-               }
-               $$.Type = obj.TYPE_BRANCH;
-               $$.Offset = $1.Value + int64($2);
-       }
-
-ximm:  '$' con
-       {
-               $$ = nullgen;
-               $$.Type = obj.TYPE_CONST;
-               $$.Offset = int64($2);
-       }
-|      '$' oreg
-       {
-               $$ = $2;
-               $$.Type = obj.TYPE_ADDR;
-       }
-|      '$' LSCONST
-       {
-               $$ = nullgen;
-               $$.Type = obj.TYPE_SCONST;
-               $$.U.Sval = $2
-       }
-|      fcon
-
-fcon:
-       '$' LFCONST
-       {
-               $$ = nullgen;
-               $$.Type = obj.TYPE_FCONST;
-               $$.U.Dval = $2;
-       }
-|      '$' '-' LFCONST
-       {
-               $$ = nullgen;
-               $$.Type = obj.TYPE_FCONST;
-               $$.U.Dval = -$3;
-       }
-
-reglist:
-       spreg
-       {
-               $$ = 1 << uint($1&15);
-       }
-|      spreg '-' spreg
-       {
-               $$=0;
-               for i:=$1; i<=$3; i++ {
-                       $$ |= 1<<uint(i&15)
-               }
-               for i:=$3; i<=$1; i++ {
-                       $$ |= 1<<uint(i&15)
-               }
-       }
-|      spreg comma reglist
-       {
-               $$ = (1<<uint($1&15)) | $3;
-       }
-
-gen:
-       reg
-|      ximm
-|      shift
-|      shift '(' spreg ')'
-       {
-               $$ = $1;
-               $$.Reg = int16($3);
-       }
-|      LPSR
-       {
-               $$ = nullgen;
-               $$.Type = obj.TYPE_REG
-               $$.Reg = int16($1);
-       }
-|      LFCR
-       {
-               $$ = nullgen;
-               $$.Type = obj.TYPE_REG
-               $$.Reg = int16($1);
-       }
-|      con
-       {
-               $$ = nullgen;
-               $$.Type = obj.TYPE_MEM;
-               $$.Offset = int64($1);
-       }
-|      oreg
-|      freg
-
-nireg:
-       ireg
-|      name
-       {
-               $$ = $1;
-               if($1.Name != obj.NAME_EXTERN && $1.Name != obj.NAME_STATIC) {
-               }
-       }
-
-ireg:
-       '(' spreg ')'
-       {
-               $$ = nullgen;
-               $$.Type = obj.TYPE_MEM;
-               $$.Reg = int16($2);
-               $$.Offset = 0;
-       }
-
-ioreg:
-       ireg
-|      con '(' sreg ')'
-       {
-               $$ = nullgen;
-               $$.Type = obj.TYPE_MEM;
-               $$.Reg = int16($3);
-               $$.Offset = int64($1);
-       }
-
-oreg:
-       name
-|      name '(' sreg ')'
-       {
-               $$ = $1;
-               $$.Type = obj.TYPE_MEM;
-               $$.Reg = int16($3);
-       }
-|      ioreg
-
-imsr:
-       reg
-|      imm
-|      shift
-
-imm:   '$' con
-       {
-               $$ = nullgen;
-               $$.Type = obj.TYPE_CONST;
-               $$.Offset = int64($2);
-       }
-
-reg:
-       spreg
-       {
-               $$ = nullgen;
-               $$.Type = obj.TYPE_REG;
-               $$.Reg = int16($1);
-       }
-
-regreg:
-       '(' spreg ',' spreg ')'
-       {
-               $$ = nullgen;
-               $$.Type = obj.TYPE_REGREG;
-               $$.Reg = int16($2);
-               $$.Offset = int64($4);
-       }
-
-shift:
-       spreg '<' '<' rcon
-       {
-               $$ = nullgen;
-               $$.Type = obj.TYPE_SHIFT;
-               $$.Offset = int64($1&15) | int64($4) | (0 << 5);
-       }
-|      spreg '>' '>' rcon
-       {
-               $$ = nullgen;
-               $$.Type = obj.TYPE_SHIFT;
-               $$.Offset = int64($1&15) | int64($4) | (1 << 5);
-       }
-|      spreg '-' '>' rcon
-       {
-               $$ = nullgen;
-               $$.Type = obj.TYPE_SHIFT;
-               $$.Offset = int64($1&15) | int64($4) | (2 << 5);
-       }
-|      spreg LAT '>' rcon
-       {
-               $$ = nullgen;
-               $$.Type = obj.TYPE_SHIFT;
-               $$.Offset = int64($1&15) | int64($4) | (3 << 5);
-       }
-
-rcon:
-       spreg
-       {
-               if $$ < REG_R0 || $$ > REG_R15 {
-                       print("register value out of range\n")
-               }
-               $$ = (($1&15) << 8) | (1 << 4);
-       }
-|      con
-       {
-               if $$ < 0 || $$ >= 32 {
-                       print("shift value out of range\n")
-               }
-               $$ = ($1&31) << 7;
-       }
-
-sreg:
-       LREG
-|      LPC
-       {
-               $$ = REGPC;
-       }
-|      LR '(' expr ')'
-       {
-               if $3 < 0 || $3 >= NREG {
-                       print("register value out of range\n")
-               }
-               $$ = REG_R0 + $3;
-       }
-
-spreg:
-       sreg
-|      LSP
-       {
-               $$ = REGSP;
-       }
-
-creg:
-       LCREG
-|      LC '(' expr ')'
-       {
-               if $3 < 0 || $3 >= NREG {
-                       print("register value out of range\n")
-               }
-               $$ = $3; // TODO(rsc): REG_C0+$3
-       }
-
-frcon:
-       freg
-|      fcon
-
-freg:
-       LFREG
-       {
-               $$ = nullgen;
-               $$.Type = obj.TYPE_REG;
-               $$.Reg = int16($1);
-       }
-|      LF '(' con ')'
-       {
-               $$ = nullgen;
-               $$.Type = obj.TYPE_REG;
-               $$.Reg = int16(REG_F0 + $3);
-       }
-
-name:
-       con '(' pointer ')'
-       {
-               $$ = nullgen;
-               $$.Type = obj.TYPE_MEM;
-               $$.Name = int8($3);
-               $$.Sym = nil;
-               $$.Offset = int64($1);
-       }
-|      LNAME offset '(' pointer ')'
-       {
-               $$ = nullgen;
-               $$.Type = obj.TYPE_MEM;
-               $$.Name = int8($4);
-               $$.Sym = obj.Linklookup(asm.Ctxt, $1.Name, 0);
-               $$.Offset = int64($2);
-       }
-|      LNAME '<' '>' offset '(' LSB ')'
-       {
-               $$ = nullgen;
-               $$.Type = obj.TYPE_MEM;
-               $$.Name = obj.NAME_STATIC;
-               $$.Sym = obj.Linklookup(asm.Ctxt, $1.Name, 1);
-               $$.Offset = int64($4);
-       }
-
-offset:
-       {
-               $$ = 0;
-       }
-|      '+' con
-       {
-               $$ = $2;
-       }
-|      '-' con
-       {
-               $$ = -$2;
-       }
-
-pointer:
-       LSB
-|      LSP
-|      LFP
-
-con:
-       LCONST
-|      LVAR
-       {
-               $$ = int32($1.Value);
-       }
-|      '-' con
-       {
-               $$ = -$2;
-       }
-|      '+' con
-       {
-               $$ = $2;
-       }
-|      '~' con
-       {
-               $$ = ^$2;
-       }
-|      '(' expr ')'
-       {
-               $$ = $2;
-       }
-
-oexpr:
-       {
-               $$ = 0;
-       }
-|      ',' expr
-       {
-               $$ = $2;
-       }
-
-expr:
-       con
-|      expr '+' expr
-       {
-               $$ = $1 + $3;
-       }
-|      expr '-' expr
-       {
-               $$ = $1 - $3;
-       }
-|      expr '*' expr
-       {
-               $$ = $1 * $3;
-       }
-|      expr '/' expr
-       {
-               $$ = $1 / $3;
-       }
-|      expr '%' expr
-       {
-               $$ = $1 % $3;
-       }
-|      expr '<' '<' expr
-       {
-               $$ = $1 << uint($4);
-       }
-|      expr '>' '>' expr
-       {
-               $$ = $1 >> uint($4);
-       }
-|      expr '&' expr
-       {
-               $$ = $1 & $3;
-       }
-|      expr '^' expr
-       {
-               $$ = $1 ^ $3;
-       }
-|      expr '|' expr
-       {
-               $$ = $1 | $3;
-       }
diff --git a/src/cmd/new6a/a.y b/src/cmd/new6a/a.y
deleted file mode 100644 (file)
index bd59a1f..0000000
+++ /dev/null
@@ -1,723 +0,0 @@
-// Inferno utils/6a/a.y
-// http://code.google.com/p/inferno-os/source/browse/utils/6a/a.y
-//
-//     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 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.
-
-%{
-package main
-
-import (
-       "cmd/internal/asm"
-       "cmd/internal/obj"
-       "cmd/internal/obj/x86"
-)
-%}
-
-%union {
-       sym *asm.Sym
-       lval int64
-       dval float64
-       sval string
-       addr obj.Addr
-       addr2 Addr2
-}
-
-%left  '|'
-%left  '^'
-%left  '&'
-%left  '<' '>'
-%left  '+' '-'
-%left  '*' '/' '%'
-%token <lval>  LTYPE0 LTYPE1 LTYPE2 LTYPE3 LTYPE4
-%token <lval>  LTYPEC LTYPED LTYPEN LTYPER LTYPET LTYPEG LTYPEPC
-%token <lval>  LTYPES LTYPEM LTYPEI LTYPEXC LTYPEX LTYPERT LTYPEF
-%token <lval>  LCONST LFP LPC LSB
-%token <lval>  LBREG LLREG LSREG LFREG LMREG LXREG
-%token <dval>  LFCONST
-%token <sval>  LSCONST LSP
-%token <sym>   LNAME LLAB LVAR
-%type  <lval>  con expr pointer offset
-%type  <addr>  mem imm textsize reg nam rel rem rim rom omem nmem
-%type  <addr2> nonnon nonrel nonrem rimnon rimrem remrim
-%type  <addr2> spec3 spec4 spec5 spec6 spec7 spec8 spec9
-%type  <addr2> spec10 spec12 spec13
-%%
-prog:
-|      prog 
-       {
-               stmtline = asm.Lineno;
-       }
-       line
-
-line:
-       LNAME ':'
-       {
-               $1 = asm.LabelLookup($1);
-               if $1.Type == LLAB && $1.Value != int64(asm.PC) {
-                       yyerror("redeclaration of %s (%s)", $1.Labelname, $1.Name);
-               }
-               $1.Type = LLAB;
-               $1.Value = int64(asm.PC)
-       }
-       line
-|      ';'
-|      inst ';'
-|      error ';'
-
-inst:
-       LNAME '=' expr
-       {
-               $1.Type = LVAR;
-               $1.Value = $3;
-       }
-|      LVAR '=' expr
-       {
-               if $1.Value != $3 {
-                       yyerror("redeclaration of %s", $1.Name);
-               }
-               $1.Value = $3;
-       }
-|      LTYPE0 nonnon   { outcode(int($1), &$2); }
-|      LTYPE1 nonrem   { outcode(int($1), &$2); }
-|      LTYPE2 rimnon   { outcode(int($1), &$2); }
-|      LTYPE3 rimrem   { outcode(int($1), &$2); }
-|      LTYPE4 remrim   { outcode(int($1), &$2); }
-|      LTYPER nonrel   { outcode(int($1), &$2); }
-|      spec1
-|      spec2
-|      LTYPEC spec3    { outcode(int($1), &$2); }
-|      LTYPEN spec4    { outcode(int($1), &$2); }
-|      LTYPES spec5    { outcode(int($1), &$2); }
-|      LTYPEM spec6    { outcode(int($1), &$2); }
-|      LTYPEI spec7    { outcode(int($1), &$2); }
-|      LTYPEXC spec8   { outcode(int($1), &$2); }
-|      LTYPEX spec9    { outcode(int($1), &$2); }
-|      LTYPERT spec10  { outcode(int($1), &$2); }
-|      spec11
-|      LTYPEPC spec12  { outcode(int($1), &$2); }
-|      LTYPEF spec13   { outcode(int($1), &$2); }
-
-nonnon:
-       {
-               $$.from = nullgen;
-               $$.to = nullgen;
-       }
-|      ','
-       {
-               $$.from = nullgen;
-               $$.to = nullgen;
-       }
-
-rimrem:
-       rim ',' rem
-       {
-               $$.from = $1;
-               $$.to = $3;
-       }
-
-remrim:
-       rem ',' rim
-       {
-               $$.from = $1;
-               $$.to = $3;
-       }
-
-rimnon:
-       rim ','
-       {
-               $$.from = $1;
-               $$.to = nullgen;
-       }
-|      rim
-       {
-               $$.from = $1;
-               $$.to = nullgen;
-       }
-
-nonrem:
-       ',' rem
-       {
-               $$.from = nullgen;
-               $$.to = $2;
-       }
-|      rem
-       {
-               $$.from = nullgen;
-               $$.to = $1;
-       }
-
-nonrel:
-       ',' rel
-       {
-               $$.from = nullgen;
-               $$.to = $2;
-       }
-|      rel
-       {
-               $$.from = nullgen;
-               $$.to = $1;
-       }
-|      imm ',' rel
-       {
-               $$.from = $1;
-               $$.to = $3;
-       }
-
-spec1: /* DATA */
-       LTYPED nam '/' con ',' imm
-       {
-               var a Addr2
-               a.from = $2
-               a.to = $6
-               outcode(obj.ADATA, &a)
-               if asm.Pass > 1 {
-                       lastpc.From3.Type = obj.TYPE_CONST
-                       lastpc.From3.Offset = $4
-               }
-       }
-
-spec2: /* TEXT */
-       LTYPET mem ',' '$' textsize
-       {
-               asm.Settext($2.Sym);
-               outcode(obj.ATEXT, &Addr2{$2, $5})
-       }
-|      LTYPET mem ',' con ',' '$' textsize
-       {
-               asm.Settext($2.Sym);
-               outcode(obj.ATEXT, &Addr2{$2, $7})
-               if asm.Pass > 1 {
-                       lastpc.From3.Type = obj.TYPE_CONST
-                       lastpc.From3.Offset = $4
-               }
-       }
-
-spec11:        /* GLOBL */
-       LTYPEG mem ',' imm
-       {
-               asm.Settext($2.Sym)
-               outcode(obj.AGLOBL, &Addr2{$2, $4})
-       }
-|      LTYPEG mem ',' con ',' imm
-       {
-               asm.Settext($2.Sym)
-               outcode(obj.AGLOBL, &Addr2{$2, $6})
-               if asm.Pass > 1 {
-                       lastpc.From3.Type = obj.TYPE_CONST
-                       lastpc.From3.Offset = $4
-               }
-       }
-
-spec3: /* JMP/CALL */
-       ',' rom
-       {
-               $$.from = nullgen;
-               $$.to = $2;
-       }
-|      rom
-       {
-               $$.from = nullgen;
-               $$.to = $1;
-       }
-
-spec4: /* NOP */
-       nonnon
-|      nonrem
-
-spec5: /* SHL/SHR */
-       rim ',' rem
-       {
-               $$.from = $1;
-               $$.to = $3;
-       }
-|      rim ',' rem ':' LLREG
-       {
-               $$.from = $1;
-               $$.to = $3;
-               if $$.from.Index != obj.TYPE_NONE {
-                       yyerror("dp shift with lhs index");
-               }
-               $$.from.Index = int16($5);
-       }
-
-spec6: /* MOVW/MOVL */
-       rim ',' rem
-       {
-               $$.from = $1;
-               $$.to = $3;
-       }
-|      rim ',' rem ':' LSREG
-       {
-               $$.from = $1;
-               $$.to = $3;
-               if $$.to.Index != obj.TYPE_NONE {
-                       yyerror("dp move with lhs index");
-               }
-               $$.to.Index = int16($5);
-       }
-
-spec7:
-       rim ','
-       {
-               $$.from = $1;
-               $$.to = nullgen;
-       }
-|      rim
-       {
-               $$.from = $1;
-               $$.to = nullgen;
-       }
-|      rim ',' rem
-       {
-               $$.from = $1;
-               $$.to = $3;
-       }
-
-spec8: /* CMPPS/CMPPD */
-       reg ',' rem ',' con
-       {
-               $$.from = $1;
-               $$.to = $3;
-               $$.to.Offset = $5;
-       }
-
-spec9: /* shufl */
-       imm ',' rem ',' reg
-       {
-               $$.from = $3;
-               $$.to = $5;
-               if $1.Type != obj.TYPE_CONST {
-                       yyerror("illegal constant");
-               }
-               $$.to.Offset = $1.Offset;
-       }
-
-spec10:        /* RET/RETF */
-       {
-               $$.from = nullgen;
-               $$.to = nullgen;
-       }
-|      imm
-       {
-               $$.from = $1;
-               $$.to = nullgen;
-       }
-
-spec12:        /* asm.PCDATA */
-       rim ',' rim
-       {
-               if $1.Type != obj.TYPE_CONST || $3.Type != obj.TYPE_CONST {
-                       yyerror("arguments to asm.PCDATA must be integer constants");
-               }
-               $$.from = $1;
-               $$.to = $3;
-       }
-
-spec13:        /* FUNCDATA */
-       rim ',' rim
-       {
-               if $1.Type != obj.TYPE_CONST {
-                       yyerror("index for FUNCDATA must be integer constant");
-               }
-               if $3.Type != obj.TYPE_MEM || ($3.Name != obj.NAME_EXTERN && $3.Name != obj.NAME_STATIC) {
-                       yyerror("value for FUNCDATA must be symbol reference");
-               }
-               $$.from = $1;
-               $$.to = $3;
-       }
-
-rem:
-       reg
-|      mem
-
-rom:
-       rel
-|      nmem
-|      '*' reg
-       {
-               $$ = $2;
-       }
-|      '*' omem
-       {
-               $$ = $2;
-       }
-|      reg
-|      omem
-
-rim:
-       rem
-|      imm
-
-rel:
-       con '(' LPC ')'
-       {
-               $$ = nullgen;
-               $$.Type = obj.TYPE_BRANCH;
-               $$.Offset = $1 + int64(asm.PC);
-       }
-|      LNAME offset
-       {
-               $1 = asm.LabelLookup($1);
-               $$ = nullgen;
-               if asm.Pass == 2 && $1.Type != LLAB {
-                       yyerror("undefined label: %s", $1.Labelname);
-               }
-               $$.Type = obj.TYPE_BRANCH;
-               $$.Offset = $1.Value + $2;
-       }
-
-reg:
-       LBREG
-       {
-               $$ = nullgen;
-               $$.Type = obj.TYPE_REG
-               $$.Reg = int16($1);
-       }
-|      LFREG
-       {
-               $$ = nullgen;
-               $$.Type = obj.TYPE_REG
-               $$.Reg = int16($1);
-       }
-|      LLREG
-       {
-               $$ = nullgen;
-               $$.Type = obj.TYPE_REG
-               $$.Reg = int16($1);
-       }
-|      LMREG
-       {
-               $$ = nullgen;
-               $$.Type = obj.TYPE_REG
-               $$.Reg = int16($1);
-       }
-|      LSP
-       {
-               $$ = nullgen;
-               $$.Type = obj.TYPE_REG
-               $$.Reg = x86.REG_SP;
-       }
-|      LSREG
-       {
-               $$ = nullgen;
-               $$.Type = obj.TYPE_REG
-               $$.Reg = int16($1);
-       }
-|      LXREG
-       {
-               $$ = nullgen;
-               $$.Type = obj.TYPE_REG
-               $$.Reg = int16($1);
-       }
-
-imm:
-       '$' con
-       {
-               $$ = nullgen;
-               $$.Type = obj.TYPE_CONST;
-               $$.Offset = $2;
-       }
-|      '$' nam
-       {
-               $$ = $2;
-               $$.Type = obj.TYPE_ADDR;
-               /*
-               if($2.Type == x86.D_AUTO || $2.Type == x86.D_PARAM)
-                       yyerror("constant cannot be automatic: %s",
-                               $2.sym.Name);
-                */
-       }
-|      '$' LSCONST
-       {
-               $$ = nullgen;
-               $$.Type = obj.TYPE_SCONST;
-               $$.U.Sval = ($2+"\x00\x00\x00\x00\x00\x00\x00\x00")[:8]
-       }
-|      '$' LFCONST
-       {
-               $$ = nullgen;
-               $$.Type = obj.TYPE_FCONST;
-               $$.U.Dval = $2;
-       }
-|      '$' '(' LFCONST ')'
-       {
-               $$ = nullgen;
-               $$.Type = obj.TYPE_FCONST;
-               $$.U.Dval = $3;
-       }
-|      '$' '(' '-' LFCONST ')'
-       {
-               $$ = nullgen;
-               $$.Type = obj.TYPE_FCONST;
-               $$.U.Dval = -$4;
-       }
-|      '$' '-' LFCONST
-       {
-               $$ = nullgen;
-               $$.Type = obj.TYPE_FCONST;
-               $$.U.Dval = -$3;
-       }
-
-mem:
-       omem
-|      nmem
-
-omem:
-       con
-       {
-               $$ = nullgen;
-               $$.Type = obj.TYPE_MEM
-               $$.Offset = $1;
-       }
-|      con '(' LLREG ')'
-       {
-               $$ = nullgen;
-               $$.Type = obj.TYPE_MEM
-               $$.Reg = int16($3)
-               $$.Offset = $1;
-       }
-|      con '(' LSP ')'
-       {
-               $$ = nullgen;
-               $$.Type = obj.TYPE_MEM
-               $$.Reg = x86.REG_SP
-               $$.Offset = $1;
-       }
-|      con '(' LSREG ')'
-       {
-               $$ = nullgen;
-               $$.Type = obj.TYPE_MEM
-               $$.Reg = int16($3)
-               $$.Offset = $1;
-       }
-|      con '(' LLREG '*' con ')'
-       {
-               $$ = nullgen;
-               $$.Type = obj.TYPE_MEM
-               $$.Offset = $1;
-               $$.Index = int16($3);
-               $$.Scale = int8($5);
-               checkscale($$.Scale);
-       }
-|      con '(' LLREG ')' '(' LLREG '*' con ')'
-       {
-               $$ = nullgen;
-               $$.Type = obj.TYPE_MEM
-               $$.Reg = int16($3)
-               $$.Offset = $1;
-               $$.Index = int16($6);
-               $$.Scale = int8($8);
-               checkscale($$.Scale);
-       }
-|      con '(' LLREG ')' '(' LSREG '*' con ')'
-       {
-               $$ = nullgen;
-               $$.Type = obj.TYPE_MEM
-               $$.Reg = int16($3)
-               $$.Offset = $1;
-               $$.Index = int16($6);
-               $$.Scale = int8($8);
-               checkscale($$.Scale);
-       }
-|      '(' LLREG ')'
-       {
-               $$ = nullgen;
-               $$.Type = obj.TYPE_MEM
-               $$.Reg = int16($2)
-       }
-|      '(' LSP ')'
-       {
-               $$ = nullgen;
-               $$.Type = obj.TYPE_MEM
-               $$.Reg = x86.REG_SP
-       }
-|      '(' LLREG '*' con ')'
-       {
-               $$ = nullgen;
-               $$.Type = obj.TYPE_MEM
-               $$.Index = int16($2);
-               $$.Scale = int8($4);
-               checkscale($$.Scale);
-       }
-|      '(' LLREG ')' '(' LLREG '*' con ')'
-       {
-               $$ = nullgen;
-               $$.Type = obj.TYPE_MEM
-               $$.Reg = int16($2)
-               $$.Index = int16($5);
-               $$.Scale = int8($7);
-               checkscale($$.Scale);
-       }
-
-nmem:
-       nam
-       {
-               $$ = $1;
-       }
-|      nam '(' LLREG '*' con ')'
-       {
-               $$ = $1;
-               $$.Index = int16($3);
-               $$.Scale = int8($5);
-               checkscale($$.Scale);
-       }
-
-nam:
-       LNAME offset '(' pointer ')'
-       {
-               $$ = nullgen;
-               $$.Type = obj.TYPE_MEM
-               $$.Name = int8($4)
-               $$.Sym = obj.Linklookup(asm.Ctxt, $1.Name, 0);
-               $$.Offset = $2;
-       }
-|      LNAME '<' '>' offset '(' LSB ')'
-       {
-               $$ = nullgen;
-               $$.Type = obj.TYPE_MEM
-               $$.Name = obj.NAME_STATIC
-               $$.Sym = obj.Linklookup(asm.Ctxt, $1.Name, 1);
-               $$.Offset = $4;
-       }
-
-offset:
-       {
-               $$ = 0;
-       }
-|      '+' con
-       {
-               $$ = $2;
-       }
-|      '-' con
-       {
-               $$ = -$2;
-       }
-
-pointer:
-       LSB
-|      LSP
-       {
-               $$ = obj.NAME_AUTO;
-       }
-|      LFP
-
-con:
-       LCONST
-|      LVAR
-       {
-               $$ = $1.Value;
-       }
-|      '-' con
-       {
-               $$ = -$2;
-       }
-|      '+' con
-       {
-               $$ = $2;
-       }
-|      '~' con
-       {
-               $$ = ^$2;
-       }
-|      '(' expr ')'
-       {
-               $$ = $2;
-       }
-
-textsize:
-       LCONST
-       {
-               $$ = nullgen;
-               $$.Type = obj.TYPE_TEXTSIZE;
-               $$.Offset = $1;
-               $$.U.Argsize = obj.ArgsSizeUnknown;
-       }
-|      '-' LCONST
-       {
-               $$ = nullgen;
-               $$.Type = obj.TYPE_TEXTSIZE;
-               $$.Offset = -$2;
-               $$.U.Argsize = obj.ArgsSizeUnknown;
-       }
-|      LCONST '-' LCONST
-       {
-               $$ = nullgen;
-               $$.Type = obj.TYPE_TEXTSIZE;
-               $$.Offset = $1;
-               $$.U.Argsize = int32($3);
-       }
-|      '-' LCONST '-' LCONST
-       {
-               $$ = nullgen;
-               $$.Type = obj.TYPE_TEXTSIZE;
-               $$.Offset = -$2;
-               $$.U.Argsize = int32($4);
-       }
-
-expr:
-       con
-|      expr '+' expr
-       {
-               $$ = $1 + $3;
-       }
-|      expr '-' expr
-       {
-               $$ = $1 - $3;
-       }
-|      expr '*' expr
-       {
-               $$ = $1 * $3;
-       }
-|      expr '/' expr
-       {
-               $$ = $1 / $3;
-       }
-|      expr '%' expr
-       {
-               $$ = $1 % $3;
-       }
-|      expr '<' '<' expr
-       {
-               $$ = $1 << uint($4);
-       }
-|      expr '>' '>' expr
-       {
-               $$ = $1 >> uint($4);
-       }
-|      expr '&' expr
-       {
-               $$ = $1 & $3;
-       }
-|      expr '^' expr
-       {
-               $$ = $1 ^ $3;
-       }
-|      expr '|' expr
-       {
-               $$ = $1 | $3;
-       }
diff --git a/src/cmd/new8a/a.y b/src/cmd/new8a/a.y
deleted file mode 100644 (file)
index 906ad33..0000000
+++ /dev/null
@@ -1,713 +0,0 @@
-// Inferno utils/8a/a.y
-// http://code.google.com/p/inferno-os/source/browse/utils/8a/a.y
-//
-//     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 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.
-
-%{
-package main
-
-import (
-       "cmd/internal/asm"
-       "cmd/internal/obj"
-       . "cmd/internal/obj/i386"
-)
-%}
-
-%union {
-       sym *asm.Sym
-       lval int64
-       con2 struct {
-               v1 int32
-               v2 int32
-       }
-       dval float64
-       sval string
-       addr obj.Addr
-       addr2 Addr2
-}
-
-%left  '|'
-%left  '^'
-%left  '&'
-%left  '<' '>'
-%left  '+' '-'
-%left  '*' '/' '%'
-%token <lval>  LTYPE0 LTYPE1 LTYPE2 LTYPE3 LTYPE4
-%token <lval>  LTYPEC LTYPED LTYPEN LTYPER LTYPET LTYPES LTYPEM LTYPEI LTYPEG LTYPEXC
-%token <lval>  LTYPEX LTYPEPC LTYPEF LCONST LFP LPC LSB
-%token <lval>  LBREG LLREG LSREG LFREG LXREG
-%token <dval>  LFCONST
-%token <sval>  LSCONST LSP
-%token <sym>   LNAME LLAB LVAR
-%type  <lval>  con expr pointer offset
-%type  <addr>  mem imm reg nam rel rem rim rom omem nmem textsize
-%type  <addr2> nonnon nonrel nonrem rimnon rimrem remrim
-%type  <addr2> spec3 spec4 spec5 spec6 spec7 spec9 spec10 spec11 spec12
-%%
-prog:
-|      prog
-       {
-               stmtline = asm.Lineno;
-       }
-       line
-
-line:
-       LNAME ':'
-       {
-               $1 = asm.LabelLookup($1);
-               if $1.Type == LLAB && $1.Value != int64(asm.PC) {
-                       yyerror("redeclaration of %s", $1.Labelname)
-               }
-               $1.Type = LLAB;
-               $1.Value = int64(asm.PC)
-       }
-       line
-|      ';'
-|      inst ';'
-|      error ';'
-
-inst:
-       LNAME '=' expr
-       {
-               $1.Type = LVAR;
-               $1.Value = $3;
-       }
-|      LVAR '=' expr
-       {
-               if $1.Value != int64($3) {
-                       yyerror("redeclaration of %s", $1.Name);
-               }
-               $1.Value = $3;
-       }
-|      LTYPE0 nonnon   { outcode(int($1), &$2); }
-|      LTYPE1 nonrem   { outcode(int($1), &$2); }
-|      LTYPE2 rimnon   { outcode(int($1), &$2); }
-|      LTYPE3 rimrem   { outcode(int($1), &$2); }
-|      LTYPE4 remrim   { outcode(int($1), &$2); }
-|      LTYPER nonrel   { outcode(int($1), &$2); }
-|      spec1
-|      spec2
-|      LTYPEC spec3    { outcode(int($1), &$2); }
-|      LTYPEN spec4    { outcode(int($1), &$2); }
-|      LTYPES spec5    { outcode(int($1), &$2); }
-|      LTYPEM spec6    { outcode(int($1), &$2); }
-|      LTYPEI spec7    { outcode(int($1), &$2); }
-|      spec8
-|      LTYPEXC spec9   { outcode(int($1), &$2); }
-|      LTYPEX spec10   { outcode(int($1), &$2); }
-|      LTYPEPC spec11  { outcode(int($1), &$2); }
-|      LTYPEF spec12   { outcode(int($1), &$2); }
-
-nonnon:
-       {
-               $$.from = nullgen;
-               $$.to = nullgen;
-       }
-|      ','
-       {
-               $$.from = nullgen;
-               $$.to = nullgen;
-       }
-
-rimrem:
-       rim ',' rem
-       {
-               $$.from = $1;
-               $$.to = $3;
-       }
-
-remrim:
-       rem ',' rim
-       {
-               $$.from = $1;
-               $$.to = $3;
-       }
-
-rimnon:
-       rim ','
-       {
-               $$.from = $1;
-               $$.to = nullgen;
-       }
-|      rim
-       {
-               $$.from = $1;
-               $$.to = nullgen;
-       }
-
-nonrem:
-       ',' rem
-       {
-               $$.from = nullgen;
-               $$.to = $2;
-       }
-|      rem
-       {
-               $$.from = nullgen;
-               $$.to = $1;
-       }
-
-nonrel:
-       ',' rel
-       {
-               $$.from = nullgen;
-               $$.to = $2;
-       }
-|      rel
-       {
-               $$.from = nullgen;
-               $$.to = $1;
-       }
-|      imm ',' rel
-       {
-               $$.from = $1;
-               $$.to = $3;
-       }
-
-spec1: /* DATA */
-       LTYPED nam '/' con ',' imm
-       {
-               outcode(obj.ADATA, &Addr2{$2, $6})
-               if asm.Pass > 1 {
-                       lastpc.From3.Type = obj.TYPE_CONST
-                       lastpc.From3.Offset = $4
-               }
-       }
-
-spec2: /* TEXT */
-       LTYPET mem ',' '$' textsize
-       {
-               asm.Settext($2.Sym);
-               outcode(obj.ATEXT, &Addr2{$2, $5})
-       }
-|      LTYPET mem ',' con ',' '$' textsize
-       {
-               asm.Settext($2.Sym);
-               outcode(obj.ATEXT, &Addr2{$2, $7})
-               if asm.Pass > 1 {
-                       lastpc.From3.Type = obj.TYPE_CONST
-                       lastpc.From3.Offset = $4
-               }
-       }
-
-spec8: /* GLOBL */
-       LTYPEG mem ',' imm
-       {
-               asm.Settext($2.Sym);
-               outcode(obj.AGLOBL, &Addr2{$2, $4})
-       }
-|      LTYPEG mem ',' con ',' imm
-       {
-               asm.Settext($2.Sym);
-               outcode(obj.AGLOBL, &Addr2{$2, $6})
-               if asm.Pass > 1 {
-                       lastpc.From3.Type = obj.TYPE_CONST
-                       lastpc.From3.Offset = $4
-               }
-       }
-
-
-spec3: /* JMP/CALL */
-       ',' rom
-       {
-               $$.from = nullgen;
-               $$.to = $2;
-       }
-|      rom
-       {
-               $$.from = nullgen;
-               $$.to = $1;
-       }
-|      '*' nam
-       {
-               $$.from = nullgen;
-               $$.to = $2;
-               $$.to.Type = obj.TYPE_INDIR
-       }
-
-spec4: /* NOP */
-       nonnon
-|      nonrem
-
-spec5: /* SHL/SHR */
-       rim ',' rem
-       {
-               $$.from = $1;
-               $$.to = $3;
-       }
-|      rim ',' rem ':' LLREG
-       {
-               $$.from = $1;
-               $$.to = $3;
-               if $$.from.Index != obj.TYPE_NONE {
-                       yyerror("dp shift with lhs index");
-               }
-               $$.from.Index = int16($5);
-       }
-
-spec6: /* MOVW/MOVL */
-       rim ',' rem
-       {
-               $$.from = $1;
-               $$.to = $3;
-       }
-|      rim ',' rem ':' LSREG
-       {
-               $$.from = $1;
-               $$.to = $3;
-               if $$.to.Index != obj.TYPE_NONE {
-                       yyerror("dp move with lhs index");
-               }
-               $$.to.Index = int16($5);
-       }
-
-spec7:
-       rim ','
-       {
-               $$.from = $1;
-               $$.to = nullgen;
-       }
-|      rim
-       {
-               $$.from = $1;
-               $$.to = nullgen;
-       }
-|      rim ',' rem
-       {
-               $$.from = $1;
-               $$.to = $3;
-       }
-
-spec9: /* CMPPS/CMPPD */
-       reg ',' rem ',' con
-       {
-               $$.from = $1;
-               $$.to = $3;
-               $$.to.Offset = $5;
-       }
-
-spec10:        /* PINSRD */
-       imm ',' rem ',' reg
-       {
-               $$.from = $3;
-               $$.to = $5;
-               if $1.Type != obj.TYPE_CONST {
-                       yyerror("illegal constant")
-               }
-               $$.to.Offset = $1.Offset;
-       }
-
-spec11:        /* PCDATA */
-       rim ',' rim
-       {
-               if $1.Type != obj.TYPE_CONST || $3.Type != obj.TYPE_CONST {
-                       yyerror("arguments to PCDATA must be integer constants");
-               }
-               $$.from = $1;
-               $$.to = $3;
-       }
-
-spec12:        /* FUNCDATA */
-       rim ',' rim
-       {
-               if $1.Type != obj.TYPE_CONST {
-                       yyerror("index for FUNCDATA must be integer constant");
-               }
-               if $3.Type != obj.TYPE_MEM || ($3.Name != obj.NAME_EXTERN && $3.Name != obj.NAME_STATIC) {
-                       yyerror("value for FUNCDATA must be symbol reference");
-               }
-               $$.from = $1;
-               $$.to = $3;
-       }
-
-rem:
-       reg
-|      mem
-
-rom:
-       rel
-|      nmem
-|      '*' reg
-       {
-               $$ = $2;
-       }
-|      '*' omem
-       {
-               $$ = $2;
-       }
-|      reg
-|      omem
-|      imm
-
-rim:
-       rem
-|      imm
-
-rel:
-       con '(' LPC ')'
-       {
-               $$ = nullgen;
-               $$.Type = obj.TYPE_BRANCH;
-               $$.Offset = $1 + int64(asm.PC);
-       }
-|      LNAME offset
-       {
-               $1 = asm.LabelLookup($1);
-               $$ = nullgen;
-               if asm.Pass == 2 && $1.Type != LLAB {
-                       yyerror("undefined label: %s", $1.Labelname);
-               }
-               $$.Type = obj.TYPE_BRANCH;
-               $$.Offset = $1.Value + $2;
-       }
-
-reg:
-       LBREG
-       {
-               $$ = nullgen;
-               $$.Type = obj.TYPE_REG
-               $$.Reg = int16($1);
-       }
-|      LFREG
-       {
-               $$ = nullgen;
-               $$.Type = obj.TYPE_REG
-               $$.Reg = int16($1);
-       }
-|      LLREG
-       {
-               $$ = nullgen;
-               $$.Type = obj.TYPE_REG
-               $$.Reg = int16($1);
-       }
-|      LXREG
-       {
-               $$ = nullgen;
-               $$.Type = obj.TYPE_REG
-               $$.Reg = int16($1);
-       }
-|      LSP
-       {
-               $$ = nullgen;
-               $$.Type = obj.TYPE_REG
-               $$.Reg = REG_SP;
-       }
-|      LSREG
-       {
-               $$ = nullgen;
-               $$.Type = obj.TYPE_REG
-               $$.Reg = int16($1);
-       }
-
-imm:
-       '$' con
-       {
-               $$ = nullgen;
-               $$.Type = obj.TYPE_CONST;
-               $$.Offset = $2;
-       }
-|      '$' nam
-       {
-               $$ = $2;
-               $$.Type = obj.TYPE_ADDR
-               /*
-               if($2.Type == D_AUTO || $2.Type == D_PARAM)
-                       yyerror("constant cannot be automatic: %s",
-                               $2.Sym.name);
-                */
-       }
-|      '$' LSCONST
-       {
-               $$ = nullgen;
-               $$.Type = obj.TYPE_SCONST;
-               $$.U.Sval = $2
-       }
-|      '$' LFCONST
-       {
-               $$ = nullgen;
-               $$.Type = obj.TYPE_FCONST;
-               $$.U.Dval = $2;
-       }
-|      '$' '(' LFCONST ')'
-       {
-               $$ = nullgen;
-               $$.Type = obj.TYPE_FCONST;
-               $$.U.Dval = $3;
-       }
-|      '$' '(' '-' LFCONST ')'
-       {
-               $$ = nullgen;
-               $$.Type = obj.TYPE_FCONST;
-               $$.U.Dval = -$4;
-       }
-|      '$' '-' LFCONST
-       {
-               $$ = nullgen;
-               $$.Type = obj.TYPE_FCONST;
-               $$.U.Dval = -$3;
-       }
-
-textsize:
-       LCONST
-       {
-               $$ = nullgen;
-               $$.Type = obj.TYPE_TEXTSIZE;
-               $$.Offset = $1;
-               $$.U.Argsize = obj.ArgsSizeUnknown;
-       }
-|      '-' LCONST
-       {
-               $$ = nullgen;
-               $$.Type = obj.TYPE_TEXTSIZE;
-               $$.Offset = -$2;
-               $$.U.Argsize = obj.ArgsSizeUnknown;
-       }
-|      LCONST '-' LCONST
-       {
-               $$ = nullgen;
-               $$.Type = obj.TYPE_TEXTSIZE;
-               $$.Offset = $1;
-               $$.U.Argsize = int32($3);
-       }
-|      '-' LCONST '-' LCONST
-       {
-               $$ = nullgen;
-               $$.Type = obj.TYPE_TEXTSIZE;
-               $$.Offset = -$2;
-               $$.U.Argsize = int32($4);
-       }
-
-
-mem:
-       omem
-|      nmem
-
-omem:
-       con
-       {
-               $$ = nullgen;
-               $$.Type = obj.TYPE_MEM
-               $$.Offset = $1;
-       }
-|      con '(' LLREG ')'
-       {
-               $$ = nullgen;
-               $$.Type = obj.TYPE_MEM
-               $$.Reg = int16($3)
-               $$.Offset = $1;
-       }
-|      con '(' LSP ')'
-       {
-               $$ = nullgen;
-               $$.Type = obj.TYPE_MEM
-               $$.Reg = REG_SP
-               $$.Offset = $1;
-       }
-|      con '(' LLREG '*' con ')'
-       {
-               $$ = nullgen;
-               $$.Type = obj.TYPE_MEM
-               $$.Offset = $1;
-               $$.Index = int16($3);
-               $$.Scale = int8($5);
-               checkscale($$.Scale);
-       }
-|      con '(' LLREG ')' '(' LLREG '*' con ')'
-       {
-               $$ = nullgen;
-               $$.Type = obj.TYPE_MEM
-               $$.Reg = int16($3)
-               $$.Offset = $1;
-               $$.Index = int16($6);
-               $$.Scale = int8($8);
-               checkscale($$.Scale);
-       }
-|      con '(' LLREG ')' '(' LSREG '*' con ')'
-       {
-               $$ = nullgen;
-               $$.Type = obj.TYPE_MEM
-               $$.Reg = int16($3)
-               $$.Offset = $1;
-               $$.Index = int16($6);
-               $$.Scale = int8($8);
-               checkscale($$.Scale);
-       }
-|      '(' LLREG ')'
-       {
-               $$ = nullgen;
-               $$.Type = obj.TYPE_MEM
-               $$.Reg = int16($2);
-       }
-|      '(' LSP ')'
-       {
-               $$ = nullgen;
-               $$.Type = obj.TYPE_MEM
-               $$.Reg = REG_SP
-       }
-|      con '(' LSREG ')'
-       {
-               $$ = nullgen;
-               $$.Type = obj.TYPE_MEM
-               $$.Reg = int16($3)
-               $$.Offset = $1;
-       }
-|      '(' LLREG '*' con ')'
-       {
-               $$ = nullgen;
-               $$.Type = obj.TYPE_MEM
-               $$.Index = int16($2);
-               $$.Scale = int8($4);
-               checkscale($$.Scale);
-       }
-|      '(' LLREG ')' '(' LLREG '*' con ')'
-       {
-               $$ = nullgen;
-               $$.Type = obj.TYPE_MEM
-               $$.Reg = int16($2)
-               $$.Index = int16($5);
-               $$.Scale = int8($7);
-               checkscale($$.Scale);
-       }
-
-nmem:
-       nam
-       {
-               $$ = $1;
-       }
-|      nam '(' LLREG '*' con ')'
-       {
-               $$ = $1;
-               $$.Index = int16($3);
-               $$.Scale = int8($5);
-               checkscale($$.Scale);
-       }
-
-nam:
-       LNAME offset '(' pointer ')'
-       {
-               $$ = nullgen;
-               $$.Type = obj.TYPE_MEM
-               $$.Name = int8($4);
-               $$.Sym = obj.Linklookup(asm.Ctxt, $1.Name, 0);
-               $$.Offset = $2;
-       }
-|      LNAME '<' '>' offset '(' LSB ')'
-       {
-               $$ = nullgen;
-               $$.Type = obj.TYPE_MEM
-               $$.Name = obj.NAME_STATIC
-               $$.Sym = obj.Linklookup(asm.Ctxt, $1.Name, 1);
-               $$.Offset = $4;
-       }
-
-offset:
-       {
-               $$ = 0;
-       }
-|      '+' con
-       {
-               $$ = $2;
-       }
-|      '-' con
-       {
-               $$ = -$2;
-       }
-
-pointer:
-       LSB
-|      LSP
-       {
-               $$ = obj.NAME_AUTO;
-       }
-|      LFP
-
-con:
-       LCONST
-|      LVAR
-       {
-               $$ = $1.Value;
-       }
-|      '-' con
-       {
-               $$ = -$2;
-       }
-|      '+' con
-       {
-               $$ = $2;
-       }
-|      '~' con
-       {
-               $$ = ^$2;
-       }
-|      '(' expr ')'
-       {
-               $$ = $2;
-       }
-
-expr:
-       con
-|      expr '+' expr
-       {
-               $$ = $1 + $3;
-       }
-|      expr '-' expr
-       {
-               $$ = $1 - $3;
-       }
-|      expr '*' expr
-       {
-               $$ = $1 * $3;
-       }
-|      expr '/' expr
-       {
-               $$ = $1 / $3;
-       }
-|      expr '%' expr
-       {
-               $$ = $1 % $3;
-       }
-|      expr '<' '<' expr
-       {
-               $$ = $1 << uint($4);
-       }
-|      expr '>' '>' expr
-       {
-               $$ = $1 >> uint($4);
-       }
-|      expr '&' expr
-       {
-               $$ = $1 & $3;
-       }
-|      expr '^' expr
-       {
-               $$ = $1 ^ $3;
-       }
-|      expr '|' expr
-       {
-               $$ = $1 | $3;
-       }
diff --git a/src/cmd/new9a/a.y b/src/cmd/new9a/a.y
deleted file mode 100644 (file)
index db733c5..0000000
+++ /dev/null
@@ -1,1055 +0,0 @@
-// cmd/9a/a.y from Vita Nuova.
-//
-//     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-2008 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-2008 Lucent Technologies Inc. and others
-//     Portions Copyright Â© 2009 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.
-
-%{
-package main
-
-import (
-       "cmd/internal/asm"
-       "cmd/internal/obj"
-       . "cmd/internal/obj/ppc64"
-)
-%}
-
-%union
-{
-       sym *asm.Sym
-       lval int64
-       dval float64
-       sval string
-       addr obj.Addr
-}
-
-%left  '|'
-%left  '^'
-%left  '&'
-%left  '<' '>'
-%left  '+' '-'
-%left  '*' '/' '%'
-%token <lval>  LMOVW LMOVB LABS LLOGW LSHW LADDW LCMP LCROP
-%token <lval>  LBRA LFMOV LFCONV LFCMP LFADD LFMA LTRAP LXORW
-%token <lval>  LNOP LEND LRETT LWORD LTEXT LDATA LGLOBL LRETRN
-%token <lval>  LCONST LSP LSB LFP LPC LCREG LFLUSH
-%token <lval>  LREG LFREG LR LCR LF LFPSCR
-%token <lval>  LLR LCTR LSPR LSPREG LSEG LMSR
-%token <lval>  LPCDAT LFUNCDAT LSCHED LXLD LXST LXOP LXMV
-%token <lval>  LRLWM LMOVMW LMOVEM LMOVFL LMTFSB LMA
-%token <dval>  LFCONST
-%token <sval>  LSCONST
-%token <sym>   LNAME LLAB LVAR
-%type  <lval>  con expr pointer offset sreg
-%type  <addr>  addr rreg regaddr name creg freg xlreg lr ctr textsize
-%type  <addr>  imm ximm fimm rel psr lcr cbit fpscr msr mask
-%%
-prog:
-|      prog
-       {
-               stmtline = asm.Lineno
-       }
-       line
-
-line:
-       LNAME ':'
-       {
-               $1 = asm.LabelLookup($1);
-               if $1.Type == LLAB && $1.Value != int64(asm.PC) {
-                       yyerror("redeclaration of %s", $1.Labelname)
-               }
-               $1.Type = LLAB;
-               $1.Value = int64(asm.PC);
-       }
-       line
-|      LNAME '=' expr ';'
-       {
-               $1.Type = LVAR;
-               $1.Value = $3;
-       }
-|      LVAR '=' expr ';'
-       {
-               if $1.Value != $3 {
-                       yyerror("redeclaration of %s", $1.Name)
-               }
-               $1.Value = $3;
-       }
-|      LSCHED ';'
-       {
-               nosched = int($1);
-       }
-|      ';'
-|      inst ';'
-|      error ';'
-
-inst:
-/*
- * load ints and bytes
- */
-       LMOVW rreg ',' rreg
-       {
-               outcode(int($1), &$2, 0, &$4);
-       }
-|      LMOVW addr ',' rreg
-       {
-               outcode(int($1), &$2, 0, &$4);
-       }
-|      LMOVW regaddr ',' rreg
-       {
-               outcode(int($1), &$2, 0, &$4);
-       }
-|      LMOVB rreg ',' rreg
-       {
-               outcode(int($1), &$2, 0, &$4);
-       }
-|      LMOVB addr ',' rreg
-       {
-               outcode(int($1), &$2, 0, &$4);
-       }
-|      LMOVB regaddr ',' rreg
-       {
-               outcode(int($1), &$2, 0, &$4);
-       }
-/*
- * load floats
- */
-|      LFMOV addr ',' freg
-       {
-               outcode(int($1), &$2, 0, &$4);
-       }
-|      LFMOV regaddr ',' freg
-       {
-               outcode(int($1), &$2, 0, &$4);
-       }
-|      LFMOV fimm ',' freg
-       {
-               outcode(int($1), &$2, 0, &$4);
-       }
-|      LFMOV freg ',' freg
-       {
-               outcode(int($1), &$2, 0, &$4);
-       }
-|      LFMOV freg ',' addr
-       {
-               outcode(int($1), &$2, 0, &$4);
-       }
-|      LFMOV freg ',' regaddr
-       {
-               outcode(int($1), &$2, 0, &$4);
-       }
-/*
- * store ints and bytes
- */
-|      LMOVW rreg ',' addr
-       {
-               outcode(int($1), &$2, 0, &$4);
-       }
-|      LMOVW rreg ',' regaddr
-       {
-               outcode(int($1), &$2, 0, &$4);
-       }
-|      LMOVB rreg ',' addr
-       {
-               outcode(int($1), &$2, 0, &$4);
-       }
-|      LMOVB rreg ',' regaddr
-       {
-               outcode(int($1), &$2, 0, &$4);
-       }
-/*
- * store floats
- */
-|      LMOVW freg ',' addr
-       {
-               outcode(int($1), &$2, 0, &$4);
-       }
-|      LMOVW freg ',' regaddr
-       {
-               outcode(int($1), &$2, 0, &$4);
-       }
-/*
- * floating point status
- */
-|      LMOVW fpscr ',' freg
-       {
-               outcode(int($1), &$2, 0, &$4);
-       }
-|      LMOVW freg ','  fpscr
-       {
-               outcode(int($1), &$2, 0, &$4);
-       }
-|      LMOVW freg ',' imm ',' fpscr
-       {
-               outgcode(int($1), &$2, 0, &$4, &$6);
-       }
-|      LMOVW fpscr ',' creg
-       {
-               outcode(int($1), &$2, 0, &$4);
-       }
-|      LMTFSB imm ',' con
-       {
-               outcode(int($1), &$2, int($4), &nullgen);
-       }
-/*
- * field moves (mtcrf)
- */
-|      LMOVW rreg ',' imm ',' lcr
-       {
-               outgcode(int($1), &$2, 0, &$4, &$6);
-       }
-|      LMOVW rreg ',' creg
-       {
-               outcode(int($1), &$2, 0, &$4);
-       }
-|      LMOVW rreg ',' lcr
-       {
-               outcode(int($1), &$2, 0, &$4);
-       }
-/*
- * integer operations
- * logical instructions
- * shift instructions
- * unary instructions
- */
-|      LADDW rreg ',' sreg ',' rreg
-       {
-               outcode(int($1), &$2, int($4), &$6);
-       }
-|      LADDW imm ',' sreg ',' rreg
-       {
-               outcode(int($1), &$2, int($4), &$6);
-       }
-|      LADDW rreg ',' imm ',' rreg
-       {
-               outgcode(int($1), &$2, 0, &$4, &$6);
-       }
-|      LADDW rreg ',' rreg
-       {
-               outcode(int($1), &$2, 0, &$4);
-       }
-|      LADDW imm ',' rreg
-       {
-               outcode(int($1), &$2, 0, &$4);
-       }
-|      LLOGW rreg ',' sreg ',' rreg
-       {
-               outcode(int($1), &$2, int($4), &$6);
-       }
-|      LLOGW rreg ',' rreg
-       {
-               outcode(int($1), &$2, 0, &$4);
-       }
-|      LSHW rreg ',' sreg ',' rreg
-       {
-               outcode(int($1), &$2, int($4), &$6);
-       }
-|      LSHW rreg ',' rreg
-       {
-               outcode(int($1), &$2, 0, &$4);
-       }
-|      LSHW imm ',' sreg ',' rreg
-       {
-               outcode(int($1), &$2, int($4), &$6);
-       }
-|      LSHW imm ',' rreg
-       {
-               outcode(int($1), &$2, 0, &$4);
-       }
-|      LABS rreg ',' rreg
-       {
-               outcode(int($1), &$2, 0, &$4);
-       }
-|      LABS rreg
-       {
-               outcode(int($1), &$2, 0, &$2);
-       }
-/*
- * multiply-accumulate
- */
-|      LMA rreg ',' sreg ',' rreg
-       {
-               outcode(int($1), &$2, int($4), &$6);
-       }
-/*
- * move immediate: macro for cau+or, addi, addis, and other combinations
- */
-|      LMOVW imm ',' rreg
-       {
-               outcode(int($1), &$2, 0, &$4);
-       }
-|      LMOVW ximm ',' rreg
-       {
-               outcode(int($1), &$2, 0, &$4);
-       }
-/*
- * condition register operations
- */
-|      LCROP cbit ',' cbit
-       {
-               outcode(int($1), &$2, int($4.Reg), &$4);
-       }
-|      LCROP cbit ',' con ',' cbit
-       {
-               outcode(int($1), &$2, int($4), &$6);
-       }
-/*
- * condition register moves
- * move from machine state register
- */
-|      LMOVW creg ',' creg
-       {
-               outcode(int($1), &$2, 0, &$4);
-       }
-|      LMOVW psr ',' creg
-       {
-               outcode(int($1), &$2, 0, &$4);
-       }
-|      LMOVW lcr ',' rreg
-       {
-               outcode(int($1), &$2, 0, &$4);
-       }
-|      LMOVW psr ',' rreg
-       {
-               outcode(int($1), &$2, 0, &$4);
-       }
-|      LMOVW xlreg ',' rreg
-       {
-               outcode(int($1), &$2, 0, &$4);
-       }
-|      LMOVW rreg ',' xlreg
-       {
-               outcode(int($1), &$2, 0, &$4);
-       }
-|      LMOVW creg ',' psr
-       {
-               outcode(int($1), &$2, 0, &$4);
-       }
-|      LMOVW rreg ',' psr
-       {
-               outcode(int($1), &$2, 0, &$4);
-       }
-/*
- * branch, branch conditional
- * branch conditional register
- * branch conditional to count register
- */
-|      LBRA rel
-       {
-               outcode(int($1), &nullgen, 0, &$2);
-       }
-|      LBRA addr
-       {
-               outcode(int($1), &nullgen, 0, &$2);
-       }
-|      LBRA '(' xlreg ')'
-       {
-               outcode(int($1), &nullgen, 0, &$3);
-       }
-|      LBRA ',' rel
-       {
-               outcode(int($1), &nullgen, 0, &$3);
-       }
-|      LBRA ',' addr
-       {
-               outcode(int($1), &nullgen, 0, &$3);
-       }
-|      LBRA ',' '(' xlreg ')'
-       {
-               outcode(int($1), &nullgen, 0, &$4);
-       }
-|      LBRA creg ',' rel
-       {
-               outcode(int($1), &$2, 0, &$4);
-       }
-|      LBRA creg ',' addr
-       {
-               outcode(int($1), &$2, 0, &$4);
-       }
-|      LBRA creg ',' '(' xlreg ')'
-       {
-               outcode(int($1), &$2, 0, &$5);
-       }
-|      LBRA con ',' rel
-       {
-               outcode(int($1), &nullgen, int($2), &$4);
-       }
-|      LBRA con ',' addr
-       {
-               outcode(int($1), &nullgen, int($2), &$4);
-       }
-|      LBRA con ',' '(' xlreg ')'
-       {
-               outcode(int($1), &nullgen, int($2), &$5);
-       }
-|      LBRA con ',' con ',' rel
-       {
-               var g obj.Addr
-               g = nullgen;
-               g.Type = obj.TYPE_CONST;
-               g.Offset = $2;
-               outcode(int($1), &g, int(REG_R0+$4), &$6);
-       }
-|      LBRA con ',' con ',' addr
-       {
-               var g obj.Addr
-               g = nullgen;
-               g.Type = obj.TYPE_CONST;
-               g.Offset = $2;
-               outcode(int($1), &g, int(REG_R0+$4), &$6);
-       }
-|      LBRA con ',' con ',' '(' xlreg ')'
-       {
-               var g obj.Addr
-               g = nullgen;
-               g.Type = obj.TYPE_CONST;
-               g.Offset = $2;
-               outcode(int($1), &g, int(REG_R0+$4), &$7);
-       }
-/*
- * conditional trap
- */
-|      LTRAP rreg ',' sreg
-       {
-               outcode(int($1), &$2, int($4), &nullgen);
-       }
-|      LTRAP imm ',' sreg
-       {
-               outcode(int($1), &$2, int($4), &nullgen);
-       }
-|      LTRAP rreg comma
-       {
-               outcode(int($1), &$2, 0, &nullgen);
-       }
-|      LTRAP comma
-       {
-               outcode(int($1), &nullgen, 0, &nullgen);
-       }
-/*
- * floating point operate
- */
-|      LFCONV freg ',' freg
-       {
-               outcode(int($1), &$2, 0, &$4);
-       }
-|      LFADD freg ',' freg
-       {
-               outcode(int($1), &$2, 0, &$4);
-       }
-|      LFADD freg ',' freg ',' freg
-       {
-               outcode(int($1), &$2, int($4.Reg), &$6);
-       }
-|      LFMA freg ',' freg ',' freg ',' freg
-       {
-               outgcode(int($1), &$2, int($4.Reg), &$6, &$8);
-       }
-|      LFCMP freg ',' freg
-       {
-               outcode(int($1), &$2, 0, &$4);
-       }
-|      LFCMP freg ',' freg ',' creg
-       {
-               outcode(int($1), &$2, int($6.Reg), &$4);
-       }
-/*
- * CMP
- */
-|      LCMP rreg ',' rreg
-       {
-               outcode(int($1), &$2, 0, &$4);
-       }
-|      LCMP rreg ',' imm
-       {
-               outcode(int($1), &$2, 0, &$4);
-       }
-|      LCMP rreg ',' rreg ',' creg
-       {
-               outcode(int($1), &$2, int($6.Reg), &$4);
-       }
-|      LCMP rreg ',' imm ',' creg
-       {
-               outcode(int($1), &$2, int($6.Reg), &$4);
-       }
-/*
- * rotate and mask
- */
-|      LRLWM  imm ',' rreg ',' imm ',' rreg
-       {
-               outgcode(int($1), &$2, int($4.Reg), &$6, &$8);
-       }
-|      LRLWM  imm ',' rreg ',' mask ',' rreg
-       {
-               outgcode(int($1), &$2, int($4.Reg), &$6, &$8);
-       }
-|      LRLWM  rreg ',' rreg ',' imm ',' rreg
-       {
-               outgcode(int($1), &$2, int($4.Reg), &$6, &$8);
-       }
-|      LRLWM  rreg ',' rreg ',' mask ',' rreg
-       {
-               outgcode(int($1), &$2, int($4.Reg), &$6, &$8);
-       }
-/*
- * load/store multiple
- */
-|      LMOVMW addr ',' rreg
-       {
-               outcode(int($1), &$2, 0, &$4);
-       }
-|      LMOVMW rreg ',' addr
-       {
-               outcode(int($1), &$2, 0, &$4);
-       }
-/*
- * various indexed load/store
- * indexed unary (eg, cache clear)
- */
-|      LXLD regaddr ',' rreg
-       {
-               outcode(int($1), &$2, 0, &$4);
-       }
-|      LXLD regaddr ',' imm ',' rreg
-       {
-               outgcode(int($1), &$2, 0, &$4, &$6);
-       }
-|      LXST rreg ',' regaddr
-       {
-               outcode(int($1), &$2, 0, &$4);
-       }
-|      LXST rreg ',' imm ',' regaddr
-       {
-               outgcode(int($1), &$2, 0, &$4, &$6);
-       }
-|      LXMV regaddr ',' rreg
-       {
-               outcode(int($1), &$2, 0, &$4);
-       }
-|      LXMV rreg ',' regaddr
-       {
-               outcode(int($1), &$2, 0, &$4);
-       }
-|      LXOP regaddr
-       {
-               outcode(int($1), &$2, 0, &nullgen);
-       }
-/*
- * NOP
- */
-|      LNOP comma
-       {
-               outcode(int($1), &nullgen, 0, &nullgen);
-       }
-|      LNOP rreg comma
-       {
-               outcode(int($1), &$2, 0, &nullgen);
-       }
-|      LNOP freg comma
-       {
-               outcode(int($1), &$2, 0, &nullgen);
-       }
-|      LNOP ',' rreg
-       {
-               outcode(int($1), &nullgen, 0, &$3);
-       }
-|      LNOP ',' freg
-       {
-               outcode(int($1), &nullgen, 0, &$3);
-       }
-|      LNOP imm /* SYSCALL $num: load $num to R0 before syscall and restore R0 to 0 afterwards. */
-       {
-               outcode(int($1), &$2, 0, &nullgen);
-       }
-/*
- * word
- */
-|      LWORD imm comma
-       {
-               outcode(int($1), &$2, 0, &nullgen);
-       }
-|      LWORD ximm comma
-       {
-               outcode(int($1), &$2, 0, &nullgen);
-       }
-/*
- * PCDATA
- */
-|      LPCDAT imm ',' imm
-       {
-               if $2.Type != obj.TYPE_CONST || $4.Type != obj.TYPE_CONST {
-                       yyerror("arguments to PCDATA must be integer constants")
-               }
-               outcode(int($1), &$2, 0, &$4);
-       }
-/*
- * FUNCDATA
- */
-|      LFUNCDAT imm ',' addr
-       {
-               if $2.Type != obj.TYPE_CONST {
-                       yyerror("index for FUNCDATA must be integer constant")
-               }
-               if $4.Type != obj.TYPE_MEM || ($4.Name != obj.NAME_EXTERN && $4.Name != obj.NAME_STATIC) {
-                       yyerror("value for FUNCDATA must be symbol reference")
-               }
-               outcode(int($1), &$2, 0, &$4);
-       }
-/*
- * END
- */
-|      LEND comma
-       {
-               outcode(int($1), &nullgen, 0, &nullgen);
-       }
-/*
- * TEXT
- */
-|      LTEXT name ',' '$' textsize
-       {
-               asm.Settext($2.Sym);
-               outcode(int($1), &$2, 0, &$5);
-       }
-|      LTEXT name ',' con ',' '$' textsize
-       {
-               asm.Settext($2.Sym);
-               outcode(int($1), &$2, int($4), &$7);
-               if asm.Pass > 1 {
-                       lastpc.From3.Type = obj.TYPE_CONST
-                       lastpc.From3.Offset = $4
-               }
-       }
-/*
- * GLOBL
- */
-|      LGLOBL name ',' imm
-       {
-               asm.Settext($2.Sym)
-               outcode(int($1), &$2, 0, &$4)
-       }
-|      LGLOBL name ',' con ',' imm
-       {
-               asm.Settext($2.Sym)
-               outcode(int($1), &$2, 0, &$6)
-               if asm.Pass > 1 {
-                       lastpc.From3.Type = obj.TYPE_CONST
-                       lastpc.From3.Offset = $4
-               }
-       }
-
-/*
- * DATA
- */
-|      LDATA name '/' con ',' imm
-       {
-               outcode(int($1), &$2, 0, &$6);
-               if asm.Pass > 1 {
-                       lastpc.From3.Type = obj.TYPE_CONST
-                       lastpc.From3.Offset = $4
-               }
-       }
-|      LDATA name '/' con ',' ximm
-       {
-               outcode(int($1), &$2, 0, &$6);
-               if asm.Pass > 1 {
-                       lastpc.From3.Type = obj.TYPE_CONST
-                       lastpc.From3.Offset = $4
-               }
-       }
-|      LDATA name '/' con ',' fimm
-       {
-               outcode(int($1), &$2, 0, &$6);
-               if asm.Pass > 1 {
-                       lastpc.From3.Type = obj.TYPE_CONST
-                       lastpc.From3.Offset = $4
-               }
-       }
-/*
- * RETURN
- */
-|      LRETRN  comma
-       {
-               outcode(int($1), &nullgen, 0, &nullgen);
-       }
-
-rel:
-       con '(' LPC ')'
-       {
-               $$ = nullgen;
-               $$.Type = obj.TYPE_BRANCH;
-               $$.Offset = $1 + int64(asm.PC);
-       }
-|      LNAME offset
-       {
-               $1 = asm.LabelLookup($1);
-               $$ = nullgen;
-               if asm.Pass == 2 && $1.Type != LLAB {
-                       yyerror("undefined label: %s", $1.Labelname)
-               }
-               $$.Type = obj.TYPE_BRANCH;
-               $$.Offset = $1.Value + $2;
-       }
-
-rreg:
-       sreg
-       {
-               $$ = nullgen;
-               $$.Type = obj.TYPE_REG;
-               $$.Reg = int16($1);
-       }
-
-xlreg:
-       lr
-|      ctr
-
-lr:
-       LLR
-       {
-               $$ = nullgen;
-               $$.Type = obj.TYPE_REG;
-               $$.Reg = int16($1);
-       }
-
-lcr:
-       LCR
-       {
-               $$ = nullgen;
-               $$.Type = obj.TYPE_REG;
-               $$.Reg = int16($1);     /* whole register */
-       }
-
-ctr:
-       LCTR
-       {
-               $$ = nullgen;
-               $$.Type = obj.TYPE_REG;
-               $$.Reg = int16($1);
-       }
-
-msr:
-       LMSR
-       {
-               $$ = nullgen;
-               $$.Type = obj.TYPE_REG;
-               $$.Reg = int16($1)
-       }
-
-psr:
-       LSPREG
-       {
-               $$ = nullgen;
-               $$.Type = obj.TYPE_REG;
-               $$.Reg = int16($1);
-       }
-|      LSPR '(' con ')'
-       {
-               if $3 < 0 || $3 >= 1024 {
-                       yyerror("SPR/DCR out of range")
-               }
-               $$ = nullgen;
-               $$.Type = obj.TYPE_REG
-               $$.Reg = int16($1 + $3);
-       }
-|      msr
-
-fpscr:
-       LFPSCR
-       {
-               $$ = nullgen;
-               $$.Type = obj.TYPE_REG;
-               $$.Reg = int16($1);
-       }
-
-freg:
-       LFREG
-       {
-               $$ = nullgen;
-               $$.Type = obj.TYPE_REG;
-               $$.Reg = int16($1);
-       }
-|      LF '(' con ')'
-       {
-               $$ = nullgen;
-               $$.Type = obj.TYPE_REG;
-               $$.Reg = int16(REG_F0 + $3);
-       }
-
-creg:
-       LCREG
-       {
-               $$ = nullgen;
-               $$.Type = obj.TYPE_REG;
-               $$.Reg = int16($1);
-       }
-|      LCR '(' con ')'
-       {
-               $$ = nullgen;
-               $$.Type = obj.TYPE_REG;
-               $$.Reg = int16(REG_C0 + $3);
-       }
-
-
-cbit:  con
-       {
-               $$ = nullgen;
-               $$.Type = obj.TYPE_REG;
-               $$.Reg = int16($1);
-       }
-
-mask:
-       con ',' con
-       {
-               var mb, me int
-               var v uint32
-
-               $$ = nullgen;
-               $$.Type = obj.TYPE_CONST;
-               mb = int($1);
-               me = int($3);
-               if(mb < 0 || mb > 31 || me < 0 || me > 31){
-                       yyerror("illegal mask start/end value(s)");
-                       mb = 0
-                       me = 0;
-               }
-               if mb <= me {
-                       v = (^uint32(0)>>uint(mb)) & (^uint32(0)<<uint(31-me))
-               } else {
-                       v = (^uint32(0)>>uint(me+1)) & (^uint32(0)<<uint(31-(mb-1)))
-               }
-               $$.Offset = int64(v);
-       }
-
-textsize:
-       LCONST
-       {
-               $$ = nullgen;
-               $$.Type = obj.TYPE_TEXTSIZE;
-               $$.Offset = int64($1)
-               $$.U.Argsize = obj.ArgsSizeUnknown;
-       }
-|      '-' LCONST
-       {
-               $$ = nullgen;
-               $$.Type = obj.TYPE_TEXTSIZE;
-               $$.Offset = -int64($2)
-               $$.U.Argsize = obj.ArgsSizeUnknown;
-       }
-|      LCONST '-' LCONST
-       {
-               $$ = nullgen;
-               $$.Type = obj.TYPE_TEXTSIZE;
-               $$.Offset = int64($1)
-               $$.U.Argsize = int32($3);
-       }
-|      '-' LCONST '-' LCONST
-       {
-               $$ = nullgen;
-               $$.Type = obj.TYPE_TEXTSIZE;
-               $$.Offset = -int64($2)
-               $$.U.Argsize = int32($4);
-       }
-
-ximm:
-       '$' addr
-       {
-               $$ = $2;
-               $$.Type = obj.TYPE_ADDR;
-       }
-|      '$' LSCONST
-       {
-               $$ = nullgen;
-               $$.Type = obj.TYPE_SCONST;
-               $$.U.Sval = $2
-       }
-
-fimm:
-       '$' LFCONST
-       {
-               $$ = nullgen;
-               $$.Type = obj.TYPE_FCONST;
-               $$.U.Dval = $2;
-       }
-|      '$' '-' LFCONST
-       {
-               $$ = nullgen;
-               $$.Type = obj.TYPE_FCONST;
-               $$.U.Dval = -$3;
-       }
-
-imm:   '$' con
-       {
-               $$ = nullgen;
-               $$.Type = obj.TYPE_CONST;
-               $$.Offset = $2;
-       }
-
-sreg:
-       LREG
-|      LR '(' con ')'
-       {
-               if $$ < 0 || $$ >= NREG {
-                       print("register value out of range\n")
-               }
-               $$ = REG_R0 + $3;
-       }
-
-regaddr:
-       '(' sreg ')'
-       {
-               $$ = nullgen;
-               $$.Type = obj.TYPE_MEM;
-               $$.Reg = int16($2);
-               $$.Offset = 0;
-       }
-|      '(' sreg '+' sreg ')'
-       {
-               $$ = nullgen;
-               $$.Type = obj.TYPE_MEM;
-               $$.Reg = int16($2);
-               $$.Scale = int8($4);
-               $$.Offset = 0;
-       }
-
-addr:
-       name
-|      con '(' sreg ')'
-       {
-               $$ = nullgen;
-               $$.Type = obj.TYPE_MEM;
-               $$.Reg = int16($3);
-               $$.Offset = $1;
-       }
-
-name:
-       con '(' pointer ')'
-       {
-               $$ = nullgen;
-               $$.Type = obj.TYPE_MEM;
-               $$.Name = int8($3);
-               $$.Sym = nil;
-               $$.Offset = $1;
-       }
-|      LNAME offset '(' pointer ')'
-       {
-               $$ = nullgen;
-               $$.Type = obj.TYPE_MEM;
-               $$.Name = int8($4);
-               $$.Sym = obj.Linklookup(asm.Ctxt, $1.Name, 0);
-               $$.Offset = $2;
-       }
-|      LNAME '<' '>' offset '(' LSB ')'
-       {
-               $$ = nullgen;
-               $$.Type = obj.TYPE_MEM;
-               $$.Name = obj.NAME_STATIC;
-               $$.Sym = obj.Linklookup(asm.Ctxt, $1.Name, 1);
-               $$.Offset = $4;
-       }
-
-comma:
-|      ','
-
-offset:
-       {
-               $$ = 0;
-       }
-|      '+' con
-       {
-               $$ = $2;
-       }
-|      '-' con
-       {
-               $$ = -$2;
-       }
-
-pointer:
-       LSB
-|      LSP
-|      LFP
-
-con:
-       LCONST
-|      LVAR
-       {
-               $$ = $1.Value;
-       }
-|      '-' con
-       {
-               $$ = -$2;
-       }
-|      '+' con
-       {
-               $$ = $2;
-       }
-|      '~' con
-       {
-               $$ = ^$2;
-       }
-|      '(' expr ')'
-       {
-               $$ = $2;
-       }
-
-expr:
-       con
-|      expr '+' expr
-       {
-               $$ = $1 + $3;
-       }
-|      expr '-' expr
-       {
-               $$ = $1 - $3;
-       }
-|      expr '*' expr
-       {
-               $$ = $1 * $3;
-       }
-|      expr '/' expr
-       {
-               $$ = $1 / $3;
-       }
-|      expr '%' expr
-       {
-               $$ = $1 % $3;
-       }
-|      expr '<' '<' expr
-       {
-               $$ = $1 << uint($4);
-       }
-|      expr '>' '>' expr
-       {
-               $$ = $1 >> uint($4);
-       }
-|      expr '&' expr
-       {
-               $$ = $1 & $3;
-       }
-|      expr '^' expr
-       {
-               $$ = $1 ^ $3;
-       }
-|      expr '|' expr
-       {
-               $$ = $1 | $3;
-       }
diff --git a/src/cmd/objwriter/main.go b/src/cmd/objwriter/main.go
deleted file mode 100644 (file)
index df83298..0000000
+++ /dev/null
@@ -1,411 +0,0 @@
-// Copyright 2015 The Go Authors.  All rights reserved.
-// Use of this source code is governed by a BSD-style
-// license that can be found in the LICENSE file.
-
-// Objwriter reads an object file description in an unspecified format
-// and writes a Go object file. It is invoked by parts of the toolchain
-// that have not yet been converted from C to Go and should not be
-// used otherwise.
-package main
-
-import (
-       "bufio"
-       "bytes"
-       "flag"
-       "fmt"
-       "io"
-       "io/ioutil"
-       "log"
-       "math"
-       "os"
-       "runtime/pprof"
-       "strconv"
-       "strings"
-
-       "cmd/internal/obj"
-       "cmd/internal/obj/arm"
-       "cmd/internal/obj/i386"
-       "cmd/internal/obj/ppc64"
-       "cmd/internal/obj/x86"
-)
-
-var arch *obj.LinkArch
-var cpuprofile = flag.String("cpuprofile", "", "write cpu profile to this file")
-var memprofile = flag.String("memprofile", "", "write memory profile to this file")
-
-func main() {
-       log.SetPrefix("goobj: ")
-       log.SetFlags(0)
-       flag.Parse()
-
-       if flag.NArg() == 1 && flag.Arg(0) == "ping" {
-               // old invocation from liblink, just testing that objwriter exists
-               return
-       }
-
-       if flag.NArg() != 4 {
-               fmt.Fprintf(os.Stderr, "usage: goobj infile objfile offset goarch\n")
-               os.Exit(2)
-       }
-
-       if *cpuprofile != "" {
-               f, err := os.Create(*cpuprofile)
-               if err != nil {
-                       log.Fatal(err)
-               }
-               pprof.StartCPUProfile(f)
-               defer pprof.StopCPUProfile()
-       }
-       if *memprofile != "" {
-               f, err := os.Create(*memprofile)
-               if err != nil {
-                       log.Fatal(err)
-               }
-               defer pprof.WriteHeapProfile(f)
-       }
-
-       switch flag.Arg(3) {
-       case "amd64":
-               arch = &x86.Linkamd64
-       case "amd64p32":
-               arch = &x86.Linkamd64p32
-       case "386":
-               // TODO(rsc): Move Link386 to package x86.
-               arch = &i386.Link386
-       case "arm":
-               arch = &arm.Linkarm
-       case "ppc64":
-               arch = &ppc64.Linkppc64
-       case "ppc64le":
-               arch = &ppc64.Linkppc64le
-       }
-
-       input()
-}
-
-const (
-       // must match liblink/objfilego.c
-       TypeEnd = iota
-       TypeCtxt
-       TypePlist
-       TypeSym
-       TypeProg
-       TypeAddr
-       TypeHist
-)
-
-var (
-       ctxt   *obj.Link
-       plists = map[int64]*obj.Plist{}
-       syms   = map[int64]*obj.LSym{}
-       progs  = map[int64]*obj.Prog{}
-       hists  = map[int64]*obj.Hist{}
-       undef  = map[interface{}]bool{}
-)
-
-func input() {
-       args := flag.Args()
-       ctxt = obj.Linknew(arch)
-       ctxt.Debugasm = 1
-       ctxt.Bso = obj.Binitw(os.Stdout)
-       defer obj.Bflush(ctxt.Bso)
-       ctxt.Diag = log.Fatalf
-       f, err := os.Open(args[0])
-       if err != nil {
-               log.Fatal(err)
-       }
-
-       b := bufio.NewReaderSize(f, 1<<20)
-       if v := rdint(b); v != TypeCtxt {
-               log.Fatalf("invalid input - missing ctxt - got %d", v)
-       }
-       name := rdstring(b)
-       if name != ctxt.Arch.Name {
-               log.Fatalf("bad arch %s - want %s", name, ctxt.Arch.Name)
-       }
-
-       ctxt.Goarm = int32(rdint(b))
-       ctxt.Debugasm = int32(rdint(b))
-       ctxt.Trimpath = rdstring(b)
-       ctxt.Plist = rdplist(b)
-       ctxt.Plast = rdplist(b)
-       ctxt.Hist = rdhist(b)
-       ctxt.Ehist = rdhist(b)
-       for {
-               i := rdint(b)
-               if i < 0 {
-                       break
-               }
-               ctxt.Hash[i] = rdsym(b)
-       }
-       last := int64(TypeCtxt)
-
-Loop:
-       for {
-               t := rdint(b)
-               switch t {
-               default:
-                       log.Fatalf("unexpected input after type %d: %v", last, t)
-               case TypeEnd:
-                       break Loop
-               case TypePlist:
-                       readplist(b, rdplist(b))
-               case TypeSym:
-                       readsym(b, rdsym(b))
-               case TypeProg:
-                       readprog(b, rdprog(b))
-               case TypeHist:
-                       readhist(b, rdhist(b))
-               }
-               last = t
-       }
-
-       if len(undef) > 0 {
-               panic("missing definitions")
-       }
-
-       var buf bytes.Buffer
-       obuf := obj.Binitw(&buf)
-       obj.Writeobjdirect(ctxt, obuf)
-       obj.Bflush(obuf)
-
-       data, err := ioutil.ReadFile(args[1])
-       if err != nil {
-               log.Fatal(err)
-       }
-
-       offset, err := strconv.Atoi(args[2])
-       if err != nil {
-               log.Fatalf("bad offset: %v", err)
-       }
-       if offset > len(data) {
-               log.Fatalf("offset too large: %v > %v", offset, len(data))
-       }
-
-       old := data[offset:]
-       if len(old) > 0 && !bytes.Equal(old, buf.Bytes()) {
-               out := strings.TrimSuffix(args[0], ".in") + ".out"
-               if err := ioutil.WriteFile(out, append(data[:offset:offset], buf.Bytes()...), 0666); err != nil {
-                       log.Fatal(err)
-               }
-               log.Fatalf("goobj produced different output:\n\toriginal: %s\n\tgoobj: %s", args[1], out)
-       }
-
-       if len(old) == 0 {
-               data = append(data, buf.Bytes()...)
-               if err := ioutil.WriteFile(args[1], data, 0666); err != nil {
-                       log.Fatal(err)
-               }
-       }
-}
-
-func rdstring(b *bufio.Reader) string {
-       v := rdint(b)
-       buf := make([]byte, v)
-       io.ReadFull(b, buf)
-       return string(buf)
-}
-
-func rdint(b *bufio.Reader) int64 {
-       var v uint64
-       shift := uint(0)
-       for {
-               b, err := b.ReadByte()
-               if err != nil {
-                       log.Fatal(err)
-               }
-               v |= uint64(b&0x7F) << shift
-               shift += 7
-               if b&0x80 == 0 {
-                       break
-               }
-       }
-       return int64(v>>1) ^ int64(v<<63)>>63
-}
-
-func rdplist(b *bufio.Reader) *obj.Plist {
-       id := rdint(b)
-       if id == 0 {
-               return nil
-       }
-       pl := plists[id]
-       if pl == nil {
-               pl = new(obj.Plist)
-               plists[id] = pl
-               undef[pl] = true
-       }
-       return pl
-}
-
-func rdsym(b *bufio.Reader) *obj.LSym {
-       id := rdint(b)
-       if id == 0 {
-               return nil
-       }
-       sym := syms[id]
-       if sym == nil {
-               sym = new(obj.LSym)
-               syms[id] = sym
-               undef[sym] = true
-       }
-       return sym
-}
-
-func rdprog(b *bufio.Reader) *obj.Prog {
-       id := rdint(b)
-       if id == 0 {
-               return nil
-       }
-       prog := progs[id]
-       if prog == nil {
-               prog = new(obj.Prog)
-               prog.Ctxt = ctxt
-               progs[id] = prog
-               undef[prog] = true
-       }
-       return prog
-}
-
-func rdhist(b *bufio.Reader) *obj.Hist {
-       id := rdint(b)
-       if id == 0 {
-               return nil
-       }
-       h := hists[id]
-       if h == nil {
-               h = new(obj.Hist)
-               hists[id] = h
-               undef[h] = true
-       }
-       return h
-}
-
-func readplist(b *bufio.Reader, pl *obj.Plist) {
-       if !undef[pl] {
-               panic("double-def")
-       }
-       delete(undef, pl)
-       pl.Recur = int(rdint(b))
-       pl.Name = rdsym(b)
-       pl.Firstpc = rdprog(b)
-       pl.Link = rdplist(b)
-}
-
-func readsym(b *bufio.Reader, s *obj.LSym) {
-       if !undef[s] {
-               panic("double-def")
-       }
-       delete(undef, s)
-       s.Name = rdstring(b)
-       s.Extname = rdstring(b)
-       s.Type = int16(rdint(b))
-       s.Version = int16(rdint(b))
-       s.Dupok = uint8(rdint(b))
-       s.External = uint8(rdint(b))
-       s.Nosplit = uint8(rdint(b))
-       s.Reachable = uint8(rdint(b))
-       s.Cgoexport = uint8(rdint(b))
-       s.Special = uint8(rdint(b))
-       s.Stkcheck = uint8(rdint(b))
-       s.Hide = uint8(rdint(b))
-       s.Leaf = uint8(rdint(b))
-       s.Fnptr = uint8(rdint(b))
-       s.Seenglobl = uint8(rdint(b))
-       s.Onlist = uint8(rdint(b))
-       s.Symid = int16(rdint(b))
-       s.Dynid = int32(rdint(b))
-       s.Sig = int32(rdint(b))
-       s.Plt = int32(rdint(b))
-       s.Got = int32(rdint(b))
-       s.Align = int32(rdint(b))
-       s.Elfsym = int32(rdint(b))
-       s.Args = int32(rdint(b))
-       s.Locals = int32(rdint(b))
-       s.Value = rdint(b)
-       s.Size = rdint(b)
-       s.Hash = rdsym(b)
-       s.Allsym = rdsym(b)
-       s.Next = rdsym(b)
-       s.Sub = rdsym(b)
-       s.Outer = rdsym(b)
-       s.Gotype = rdsym(b)
-       s.Reachparent = rdsym(b)
-       s.Queue = rdsym(b)
-       s.File = rdstring(b)
-       s.Dynimplib = rdstring(b)
-       s.Dynimpvers = rdstring(b)
-       s.Text = rdprog(b)
-       s.Etext = rdprog(b)
-       n := int(rdint(b))
-       if n > 0 {
-               s.P = make([]byte, n)
-               io.ReadFull(b, s.P)
-       }
-       s.R = make([]obj.Reloc, int(rdint(b)))
-       for i := range s.R {
-               r := &s.R[i]
-               r.Off = int32(rdint(b))
-               r.Siz = uint8(rdint(b))
-               r.Done = uint8(rdint(b))
-               r.Type = int32(rdint(b))
-               r.Add = rdint(b)
-               r.Xadd = rdint(b)
-               r.Sym = rdsym(b)
-               r.Xsym = rdsym(b)
-       }
-}
-
-func readprog(b *bufio.Reader, p *obj.Prog) {
-       if !undef[p] {
-               panic("double-def")
-       }
-       delete(undef, p)
-       p.Pc = rdint(b)
-       p.Lineno = int32(rdint(b))
-       p.Link = rdprog(b)
-       p.As = int16(rdint(b))
-       p.Reg = int16(rdint(b))
-       p.Scond = uint8(rdint(b))
-       p.Width = int8(rdint(b))
-       readaddr(b, &p.From)
-       readaddr(b, &p.From3)
-       readaddr(b, &p.To)
-}
-
-func readaddr(b *bufio.Reader, a *obj.Addr) {
-       if rdint(b) != TypeAddr {
-               log.Fatal("out of sync")
-       }
-       a.Offset = rdint(b)
-       a.U.Dval = rdfloat(b)
-       buf := make([]byte, 8)
-       io.ReadFull(b, buf)
-       a.U.Sval = string(buf)
-       a.U.Branch = rdprog(b)
-       a.Sym = rdsym(b)
-       a.Gotype = rdsym(b)
-       a.Type = int16(rdint(b))
-       a.Index = int16(rdint(b))
-       a.Scale = int8(rdint(b))
-       a.Reg = int16(rdint(b))
-       a.Name = int8(rdint(b))
-       a.Class = int8(rdint(b))
-       a.Etype = uint8(rdint(b))
-       a.U.Argsize = int32(rdint(b))
-       a.Width = rdint(b)
-}
-
-func readhist(b *bufio.Reader, h *obj.Hist) {
-       if !undef[h] {
-               panic("double-def")
-       }
-       delete(undef, h)
-       h.Link = rdhist(b)
-       h.Name = rdstring(b)
-       h.Line = int32(rdint(b))
-       h.Offset = int32(rdint(b))
-}
-
-func rdfloat(b *bufio.Reader) float64 {
-       return math.Float64frombits(uint64(rdint(b)))
-}