// 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. package gc import ( "bytes" "cmd/compile/internal/big" "cmd/internal/obj" ) // avoid <ctype.h> // 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. const ( NHUNK = 50000 BUFSIZ = 8192 NSYMB = 500 NHASH = 1024 MAXALIGN = 7 UINF = 100 PRIME1 = 3 BADWIDTH = -1000000000 MaxStackVarSize = 10 * 1024 * 1024 ) const ( // These values are known by runtime. // The MEMx and NOEQx values must run in parallel. See algtype. AMEM = iota AMEM0 AMEM8 AMEM16 AMEM32 AMEM64 AMEM128 ANOEQ ANOEQ0 ANOEQ8 ANOEQ16 ANOEQ32 ANOEQ64 ANOEQ128 ASTRING AINTER ANILINTER ASLICE AFLOAT32 AFLOAT64 ACPLX64 ACPLX128 AUNK = 100 ) const ( // Maximum size in bits for Mpints before signalling // overflow and also mantissa precision for Mpflts. Mpprec = 512 // Turn on for constant arithmetic debugging output. Mpdebug = false ) // Mpint represents an integer constant. type Mpint struct { Val big.Int Ovf bool // set if Val overflowed compiler limit (sticky) Rune bool // set if syntax indicates default type rune } // Mpflt represents a floating-point constant. type Mpflt struct { Val big.Float } // Mpcplx represents a complex constant. type Mpcplx struct { Real Mpflt Imag Mpflt } type Val struct { // U contains one of: // bool bool when n.ValCtype() == CTBOOL // *Mpint int when n.ValCtype() == CTINT, rune when n.ValCtype() == CTRUNE // *Mpflt float when n.ValCtype() == CTFLT // *Mpcplx pair of floats when n.ValCtype() == CTCPLX // string string when n.ValCtype() == CTSTR // *Nilval when n.ValCtype() == CTNIL U interface{} } type NilVal struct{} func (v Val) Ctype() int { switch x := v.U.(type) { default: Fatal("unexpected Ctype for %T", v.U) panic("not reached") case nil: return 0 case *NilVal: return CTNIL case bool: return CTBOOL case *Mpint: if x.Rune { return CTRUNE } return CTINT case *Mpflt: return CTFLT case *Mpcplx: return CTCPLX case string: return CTSTR } } type Pkg struct { Name string // package name Path string // string literal used in import statement Pathsym *Sym Prefix string // escaped path for use in symbol table Imported uint8 // export data of this package was parsed Exported int8 // import line written in export data Direct int8 // imported directly Safe bool // whether the package is marked as safe Syms map[string]*Sym } type Sym struct { Lexical uint16 Flags uint8 Link *Sym Uniqgen uint32 Importdef *Pkg // where imported definition was found Linkname string // link name // saved and restored by dcopy Pkg *Pkg Name string // variable name Def *Node // definition: ONAME OTYPE OPACK or OLITERAL Label *Label // corresponding label (ephemeral) Block int32 // blocknumber to catch redeclaration Lastlineno int32 // last declaration for diagnostic Origpkg *Pkg // original package for . import Lsym *obj.LSym Fsym *Sym // funcsym } type Type struct { Etype uint8 Nointerface bool Noalg uint8 Chan uint8 Trecur uint8 // to detect loops Printed uint8 Embedded uint8 // TFIELD embedded type Siggen uint8 Funarg uint8 // on TSTRUCT and TFIELD Copyany uint8 Local bool // created in this file Deferwidth uint8 Broke uint8 // broken type definition. Isddd bool // TFIELD is ... argument Align uint8 Haspointers uint8 // 0 unknown, 1 no, 2 yes Nod *Node // canonical OTYPE node Orig *Type // original type (type literal or predefined type) Lineno int // TFUNC Thistuple int Outtuple int Intuple int Outnamed uint8 Method *Type Xmethod *Type Sym *Sym Vargen int32 // unique name for OTYPE/ONAME Nname *Node Argwid int64 // most nodes Type *Type // actual type for TFIELD, element type for TARRAY, TCHAN, TMAP, TPTRxx Width int64 // offset in TFIELD, width in all others // TFIELD Down *Type // next struct field, also key type in TMAP Outer *Type // outer struct Note *string // literal string annotation // TARRAY Bound int64 // negative is dynamic array // TMAP Bucket *Type // internal type representing a hash bucket Hmap *Type // internal type representing a Hmap (map header object) Hiter *Type // internal type representing hash iterator state Map *Type // link from the above 3 internal types back to the map type. Maplineno int32 // first use of TFORW as map key Embedlineno int32 // first use of TFORW as embedded type // for TFORW, where to copy the eventual value to Copyto *NodeList Lastfn *Node // for usefield } type Label struct { Used uint8 Sym *Sym Def *Node Use *NodeList Link *Label // for use during gen Gotopc *obj.Prog // pointer to unresolved gotos Labelpc *obj.Prog // pointer to code Breakpc *obj.Prog // pointer to code Continpc *obj.Prog // pointer to code } type InitEntry struct { Xoffset int64 // struct, array only Expr *Node // bytes of run-time computed expressions } type InitPlan struct { Lit int64 Zero int64 Expr int64 E []InitEntry } const ( 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 ) var dclstack *Sym type Iter struct { Done int Tfunc *Type T *Type } const ( Txxx = iota TINT8 TUINT8 TINT16 TUINT16 TINT32 TUINT32 TINT64 TUINT64 TINT TUINT TUINTPTR TCOMPLEX64 TCOMPLEX128 TFLOAT32 TFLOAT64 TBOOL TPTR32 TPTR64 TFUNC TARRAY T_old_DARRAY TSTRUCT TCHAN TMAP TINTER TFORW TFIELD TANY TSTRING TUNSAFEPTR // pseudo-types for literals TIDEAL TNIL TBLANK // pseudo-type for frame layout TFUNCARGS TCHANARGS TINTERMETH NTYPE ) const ( CTxxx = iota CTINT CTRUNE CTFLT CTCPLX CTSTR CTBOOL CTNIL ) const ( /* types of channel */ /* must match ../../pkg/nreflect/type.go:/Chandir */ Cxxx = 0 Crecv = 1 << 0 Csend = 1 << 1 Cboth = Crecv | Csend ) // declaration context const ( Pxxx = uint8(iota) 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 = uint8(1 << 7) // an extra bit to identify an escaped variable ) const ( 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 ) type Typedef struct { Name string Etype int Sameas int } type Sig struct { name string pkg *Pkg isym *Sym tsym *Sym type_ *Type mtype *Type offset int32 link *Sig } type Io struct { infile string bin *obj.Biobuf nlsemi int eofnl int last int peekc int peekc1 int // second peekc for ... cp string // used for content when bin==nil importsafe bool } type Dlist struct { field *Type } type Idir struct { link *Idir dir string } /* * argument passing to/from * smagic and umagic */ type Magic struct { W int // input for both - width S int // output for both - shift Bad int // output for both - unexpected failure // magic multiplier for signed literal divisors Sd int64 // input - literal divisor Sm int64 // output - multiplier // magic multiplier for unsigned literal divisors Ud uint64 // input - literal divisor Um uint64 // output - multiplier Ua int // output - adder } /* * 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; */ var Array_array int // runtime offsetof(Array,array) - same for String var Array_nel int // runtime offsetof(Array,nel) - same for String var Array_cap int // runtime offsetof(Array,cap) var sizeof_Array int // 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; */ var sizeof_String int // runtime sizeof(String) var dotlist [10]Dlist // size is max depth of embeddeds var curio Io var pushedio Io var lexlineno int32 var lineno int32 var prevlineno int32 var pragcgobuf string var infile string var outfile string var bout *obj.Biobuf var nerrors int var nsavederrors int var nsyntaxerrors int var decldepth int32 var safemode int var nolocalimports int var lexbuf bytes.Buffer var strbuf bytes.Buffer var litbuf string var Debug [256]int var debugstr string var Debug_checknil int var Debug_typeassert int var importmyname *Sym // my name for package var localpkg *Pkg // package being compiled var importpkg *Pkg // package being imported var structpkg *Pkg // package that declared struct, during import var builtinpkg *Pkg // fake package for builtins var gostringpkg *Pkg // fake pkg for Go strings var itabpkg *Pkg // fake pkg for itab cache var Runtimepkg *Pkg // package runtime var racepkg *Pkg // package runtime/race var typepkg *Pkg // fake package for runtime type info (headers) var typelinkpkg *Pkg // fake package for runtime type info (data) var weaktypepkg *Pkg // weak references to runtime type info var unsafepkg *Pkg // package unsafe var trackpkg *Pkg // fake package for field tracking var Tptr int // either TPTR32 or TPTR64 var myimportpath string var idirs *Idir var localimport string var asmhdr string var Types [NTYPE]*Type var idealstring *Type var idealbool *Type var bytetype *Type var runetype *Type var errortype *Type var Simtype [NTYPE]uint8 var ( Isptr [NTYPE]bool isforw [NTYPE]bool Isint [NTYPE]bool Isfloat [NTYPE]bool Iscomplex [NTYPE]bool Issigned [NTYPE]bool issimple [NTYPE]bool ) var ( okforeq [NTYPE]bool okforadd [NTYPE]bool okforand [NTYPE]bool okfornone [NTYPE]bool okforcmp [NTYPE]bool okforbool [NTYPE]bool okforcap [NTYPE]bool okforlen [NTYPE]bool okforarith [NTYPE]bool okforconst [NTYPE]bool ) var ( okfor [OEND][]bool iscmp [OEND]bool ) var Minintval [NTYPE]*Mpint var Maxintval [NTYPE]*Mpint var minfltval [NTYPE]*Mpflt var maxfltval [NTYPE]*Mpflt var xtop *NodeList var externdcl *NodeList var exportlist *NodeList var importlist *NodeList // imported functions and methods with inlinable bodies var funcsyms *NodeList var dclcontext uint8 // PEXTERN/PAUTO var incannedimport int var statuniqgen int // name generator for static temps var loophack int var iota_ int32 var lastconst *NodeList var lasttype *Node var Maxarg int64 var Stksize int64 // stack size for current frame var stkptrsize int64 // prefix of stack containing pointers var blockgen int32 // max block number var block int32 // current block number var Hasdefer int // flag that curfn has defer statetment var Curfn *Node var Widthptr int var Widthint int var Widthreg int var typesw *Node var nblank *Node var hunk string var nhunk int32 var thunk int32 var Funcdepth int32 var typecheckok int var compiling_runtime int var compiling_wrappers int var use_writebarrier int var pure_go int var flag_installsuffix string var flag_race int var flag_largemodel int // Pending annotations for next func declaration. var ( noescape bool nosplit bool nowritebarrier bool systemstack bool norace bool ) var debuglive int var Ctxt *obj.Link var nointerface bool var writearchive int var bstdout obj.Biobuf var Nacl bool var continpc *obj.Prog var breakpc *obj.Prog var Pc *obj.Prog var nodfp *Node var Disable_checknil int var zerosize int64 type Flow struct { Prog *obj.Prog // actual instruction P1 *Flow // predecessors of this instruction: p1, P2 *Flow // and then p2 linked though p2link. P2link *Flow S1 *Flow // successors of this instruction (at most two: s1 and s2). S2 *Flow Link *Flow // next instruction in function code Active int32 // usable by client Id int32 // sequence number in flow graph Rpo int32 // reverse post ordering Loop uint16 // x5 for every loop Refset uint8 // diagnostic generated Data interface{} // for use by client } type Graph struct { Start *Flow Num int // After calling flowrpo, rpo lists the flow nodes in reverse postorder, // and each non-dead Flow node f has g->rpo[f->rpo] == f. Rpo []*Flow } /* * interface to back end */ const ( // 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 SizeD = 1 << 8 // 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 ) type Arch struct { Thechar int Thestring string Thelinkarch *obj.LinkArch Typedefs []Typedef REGSP int REGCTXT int REGCALLX int // BX REGCALLX2 int // AX REGRETURN int // AX REGMIN int REGMAX int REGZERO int // architectural zero register, if available FREGMIN int FREGMAX int MAXWIDTH int64 ReservedRegs []int AddIndex func(*Node, int64, *Node) bool // optional Betypeinit func() Bgen_float func(*Node, bool, int, *obj.Prog) // optional Cgen64 func(*Node, *Node) // only on 32-bit systems Cgenindex func(*Node, *Node, bool) *obj.Prog Cgen_bmul func(int, *Node, *Node, *Node) bool Cgen_float func(*Node, *Node) // optional Cgen_hmul func(*Node, *Node, *Node) Cgen_shift func(int, bool, *Node, *Node, *Node) Clearfat func(*Node) Cmp64 func(*Node, *Node, int, int, *obj.Prog) // only on 32-bit systems Defframe func(*obj.Prog) Dodiv func(int, *Node, *Node, *Node) Excise func(*Flow) Expandchecks func(*obj.Prog) Getg func(*Node) Gins func(int, *Node, *Node) *obj.Prog // Ginscmp generates code comparing n1 to n2 and jumping away if op is satisfied. // The returned prog should be Patch'ed with the jump target. // If op is not satisfied, code falls through to the next emitted instruction. // Likely is the branch prediction hint: +1 for likely, -1 for unlikely, 0 for no opinion. // // Ginscmp must be able to handle all kinds of arguments for n1 and n2, // not just simple registers, although it can assume that there are no // function calls needed during the evaluation, and on 32-bit systems // the values are guaranteed not to be 64-bit values, so no in-memory // temporaries are necessary. Ginscmp func(op int, t *Type, n1, n2 *Node, likely int) *obj.Prog // Ginsboolval inserts instructions to convert the result // of a just-completed comparison to a boolean value. // The first argument is the conditional jump instruction // corresponding to the desired value. // The second argument is the destination. // If not present, Ginsboolval will be emulated with jumps. Ginsboolval func(int, *Node) Ginscon func(int, int64, *Node) Ginsnop func() Gmove func(*Node, *Node) Igenindex func(*Node, *Node, bool) *obj.Prog Linkarchinit func() Peep func(*obj.Prog) Proginfo func(*obj.Prog) // fills in Prog.Info Regtyp func(*obj.Addr) bool Sameaddr func(*obj.Addr, *obj.Addr) bool Smallindir func(*obj.Addr, *obj.Addr) bool Stackaddr func(*obj.Addr) bool Blockcopy func(*Node, *Node, int64, int64, int64) Sudoaddable func(int, *Node, *obj.Addr) bool Sudoclean func() Excludedregs func() uint64 RtoB func(int) uint64 FtoB func(int) uint64 BtoR func(uint64) int BtoF func(uint64) int Optoas func(int, *Type) int Doregbits func(int) uint64 Regnames func(*int) []string Use387 bool // should 8g use 387 FP instructions instead of sse2. } var pcloc int32 var Thearch Arch var Newproc *Node var Deferproc *Node var Deferreturn *Node var Panicindex *Node var panicslice *Node var throwreturn *Node