mirror of
https://github.com/golang/go.git
synced 2025-05-28 02:41:30 +00:00
This flag is experimental and the semantics may change even after Go 1.7 is released. There are no changes to code not using the flag. The first part is for reading by future compiles. The second part is for reading by the final link step. Splitting the file this way allows distributed build systems to ship the compile-input part only to compile steps and the linker-input part only to linker steps. The first part is basically just the export data, and the second part is basically everything else. The overall files still have the same broad structure, so that existing tools will work with both halves. It's just that various pieces are empty in the two halves. This also copies the two bits of data the linker needed from export data into the object header proper, so that the linker doesn't need any export data at all. That eliminates a TODO that was left for switching to the binary export data. (Now the linker doesn't need to know about the switch.) The default is still to write out a combined output file. Nothing changes unless you pass -linkobj to the compiler. There is no support in the go command for -linkobj, since the go command doesn't copy objects around. The expectation is that other build systems (like bazel, say) might take advantage of this. The header adjustment and the option for the split output was intended as part of the zip archives, but the zip archives have been cut from Go 1.7. Doing this to the current archives both unblocks one step in the switch to binary export data and enables alternate build systems to experiment with the new flag using the Go 1.7 release. Change-Id: I8b6eab25b8a22b0a266ba0ac6d31e594f3d117f3 Reviewed-on: https://go-review.googlesource.com/22500 Run-TryBot: Russ Cox <rsc@golang.org> TryBot-Result: Gobot Gobot <gobot@golang.org> Reviewed-by: Ian Lance Taylor <iant@golang.org> Reviewed-by: Robert Griesemer <gri@golang.org>
483 lines
12 KiB
Go
483 lines
12 KiB
Go
// 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 (
|
|
"bufio"
|
|
"cmd/compile/internal/ssa"
|
|
"cmd/internal/bio"
|
|
"cmd/internal/obj"
|
|
)
|
|
|
|
const (
|
|
UINF = 100
|
|
BADWIDTH = -1000000000
|
|
MaxStackVarSize = 10 * 1024 * 1024
|
|
)
|
|
|
|
type Pkg struct {
|
|
Name string // package name, e.g. "sys"
|
|
Path string // string literal used in import statement, e.g. "runtime/internal/sys"
|
|
Pathsym *obj.LSym
|
|
Prefix string // escaped path for use in symbol table
|
|
Imported bool // export data of this package was parsed
|
|
Exported bool // import line written in export data
|
|
Direct bool // imported directly
|
|
Safe bool // whether the package is marked as safe
|
|
Syms map[string]*Sym
|
|
}
|
|
|
|
// Sym represents an object name. Most commonly, this is a Go identifier naming
|
|
// an object declared within a package, but Syms are also used to name internal
|
|
// synthesized objects.
|
|
//
|
|
// As a special exception, field and method names that are exported use the Sym
|
|
// associated with localpkg instead of the package that declared them. This
|
|
// allows using Sym pointer equality to test for Go identifier uniqueness when
|
|
// handling selector expressions.
|
|
type Sym struct {
|
|
Flags SymFlags
|
|
Link *Sym
|
|
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
|
|
Block int32 // blocknumber to catch redeclaration
|
|
Lastlineno int32 // last declaration for diagnostic
|
|
|
|
Label *Label // corresponding label (ephemeral)
|
|
Origpkg *Pkg // original package for . import
|
|
Lsym *obj.LSym
|
|
Fsym *Sym // funcsym
|
|
}
|
|
|
|
type Label struct {
|
|
Sym *Sym
|
|
Def *Node
|
|
Use []*Node
|
|
|
|
// 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
|
|
|
|
Used bool
|
|
}
|
|
|
|
type SymFlags uint8
|
|
|
|
const (
|
|
SymExport SymFlags = 1 << iota // to be exported
|
|
SymPackage
|
|
SymExported // already written out by export
|
|
SymUniq
|
|
SymSiggen
|
|
SymAsm
|
|
SymAlgGen
|
|
)
|
|
|
|
// The Class of a variable/function describes the "storage class"
|
|
// of a variable or function. During parsing, storage classes are
|
|
// called declaration contexts.
|
|
type Class uint8
|
|
|
|
const (
|
|
Pxxx Class = 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 = 1 << 7 // an extra bit to identify an escaped variable
|
|
)
|
|
|
|
// 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 pragcgobuf string
|
|
|
|
var infile string
|
|
|
|
var outfile string
|
|
var linkobj string
|
|
|
|
var bout *bio.Writer
|
|
|
|
var nerrors int
|
|
|
|
var nsavederrors int
|
|
|
|
var nsyntaxerrors int
|
|
|
|
var decldepth int32
|
|
|
|
var safemode bool
|
|
|
|
var nolocalimports bool
|
|
|
|
var Debug [256]int
|
|
|
|
var debugstr string
|
|
|
|
var Debug_checknil int
|
|
var Debug_typeassert int
|
|
|
|
var localpkg *Pkg // package being compiled
|
|
|
|
var importpkg *Pkg // package being imported
|
|
|
|
var itabpkg *Pkg // fake pkg for itab entries
|
|
|
|
var itablinkpkg *Pkg // fake package for runtime itab entries
|
|
|
|
var Runtimepkg *Pkg // package runtime
|
|
|
|
var racepkg *Pkg // package runtime/race
|
|
|
|
var msanpkg *Pkg // package runtime/msan
|
|
|
|
var typepkg *Pkg // fake package for runtime type info (headers)
|
|
|
|
var unsafepkg *Pkg // package unsafe
|
|
|
|
var trackpkg *Pkg // fake package for field tracking
|
|
|
|
var mappkg *Pkg // fake package for map zero value
|
|
var zerosize int64
|
|
|
|
var Tptr EType // either TPTR32 or TPTR64
|
|
|
|
var myimportpath string
|
|
|
|
var localimport string
|
|
|
|
var asmhdr string
|
|
|
|
var Simtype [NTYPE]EType
|
|
|
|
var (
|
|
isforw [NTYPE]bool
|
|
Isint [NTYPE]bool
|
|
Isfloat [NTYPE]bool
|
|
Iscomplex [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 []*Node
|
|
|
|
var exportlist []*Node
|
|
|
|
var importlist []*Node // imported functions and methods with inlinable bodies
|
|
|
|
var funcsyms []*Node
|
|
|
|
var dclcontext Class // PEXTERN/PAUTO
|
|
|
|
var incannedimport int
|
|
|
|
var statuniqgen int // name generator for static temps
|
|
|
|
var iota_ int32
|
|
|
|
var lastconst []*Node
|
|
|
|
var lasttype *Node
|
|
|
|
var Maxarg int64
|
|
|
|
var Stksize int64 // stack size for current frame
|
|
|
|
var stkptrsize int64 // prefix of stack containing pointers
|
|
|
|
var hasdefer bool // flag that curfn has defer statement
|
|
|
|
var Curfn *Node
|
|
|
|
var Widthptr int
|
|
|
|
var Widthint int
|
|
|
|
var Widthreg int
|
|
|
|
var nblank *Node
|
|
|
|
var Funcdepth int32
|
|
|
|
var typecheckok bool
|
|
|
|
var compiling_runtime bool
|
|
|
|
var compiling_wrappers int
|
|
|
|
var use_writebarrier bool
|
|
|
|
var pure_go bool
|
|
|
|
var flag_installsuffix string
|
|
|
|
var flag_race bool
|
|
|
|
var flag_msan bool
|
|
|
|
var flag_largemodel bool
|
|
|
|
// Whether we are adding any sort of code instrumentation, such as
|
|
// when the race detector is enabled.
|
|
var instrumenting bool
|
|
|
|
var debuglive int
|
|
|
|
var Ctxt *obj.Link
|
|
|
|
var writearchive bool
|
|
|
|
var bstdout *bufio.Writer
|
|
|
|
var Nacl bool
|
|
|
|
var continpc *obj.Prog
|
|
|
|
var breakpc *obj.Prog
|
|
|
|
var Pc *obj.Prog
|
|
|
|
var nodfp *Node
|
|
|
|
var Disable_checknil int
|
|
|
|
// 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.
|
|
// Originally for understanding ADC, RCR, and so on, but now also
|
|
// tracks set, use, and kill of the zero and overflow bits as well.
|
|
// TODO rename to {Set,Use,Kill}Flags
|
|
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 {
|
|
LinkArch *obj.LinkArch
|
|
|
|
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(Op, *Node, *Node, *Node) bool
|
|
Cgen_float func(*Node, *Node) // optional
|
|
Cgen_hmul func(*Node, *Node, *Node)
|
|
RightShiftWithCarry func(*Node, uint, *Node) // only on systems without RROTC instruction
|
|
AddSetCarry func(*Node, *Node, *Node) // only on systems when ADD does not update carry flag
|
|
Cgen_shift func(Op, bool, *Node, *Node, *Node)
|
|
Clearfat func(*Node)
|
|
Cmp64 func(*Node, *Node, Op, int, *obj.Prog) // only on 32-bit systems
|
|
Defframe func(*obj.Prog)
|
|
Dodiv func(Op, *Node, *Node, *Node)
|
|
Excise func(*Flow)
|
|
Expandchecks func(*obj.Prog)
|
|
Getg func(*Node)
|
|
Gins func(obj.As, *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 Op, 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(obj.As, *Node)
|
|
|
|
Ginscon func(obj.As, int64, *Node)
|
|
Ginsnop func()
|
|
Gmove func(*Node, *Node)
|
|
Igenindex func(*Node, *Node, bool) *obj.Prog
|
|
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(obj.As, *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(Op, *Type) obj.As
|
|
Doregbits func(int) uint64
|
|
Regnames func(*int) []string
|
|
Use387 bool // should 8g use 387 FP instructions instead of sse2.
|
|
|
|
// SSARegToReg maps ssa register numbers to obj register numbers.
|
|
SSARegToReg []int16
|
|
|
|
// SSAMarkMoves marks any MOVXconst ops that need to avoid clobbering flags.
|
|
SSAMarkMoves func(*SSAGenState, *ssa.Block)
|
|
|
|
// SSAGenValue emits Prog(s) for the Value.
|
|
SSAGenValue func(*SSAGenState, *ssa.Value)
|
|
|
|
// SSAGenBlock emits end-of-block Progs. SSAGenValue should be called
|
|
// for all values in the block before SSAGenBlock.
|
|
SSAGenBlock func(s *SSAGenState, b, next *ssa.Block)
|
|
}
|
|
|
|
var pcloc int32
|
|
|
|
var Thearch Arch
|
|
|
|
var Newproc *Node
|
|
|
|
var Deferproc *Node
|
|
|
|
var Deferreturn *Node
|
|
|
|
var Panicindex *Node
|
|
|
|
var panicslice *Node
|
|
|
|
var panicdivide *Node
|
|
|
|
var throwreturn *Node
|
|
|
|
var growslice *Node
|
|
|
|
var writebarrierptr *Node
|
|
var typedmemmove *Node
|
|
|
|
var panicdottype *Node
|