github.com/yukk001/go1.10.8@v0.0.0-20190813125351-6df2d3982e20/src/cmd/compile/internal/ssa/config.go (about)

     1  // Copyright 2015 The Go Authors. All rights reserved.
     2  // Use of this source code is governed by a BSD-style
     3  // license that can be found in the LICENSE file.
     4  
     5  package ssa
     6  
     7  import (
     8  	"cmd/compile/internal/types"
     9  	"cmd/internal/obj"
    10  	"cmd/internal/objabi"
    11  	"cmd/internal/src"
    12  	"os"
    13  	"strconv"
    14  )
    15  
    16  // A Config holds readonly compilation information.
    17  // It is created once, early during compilation,
    18  // and shared across all compilations.
    19  type Config struct {
    20  	arch            string // "amd64", etc.
    21  	PtrSize         int64  // 4 or 8; copy of cmd/internal/sys.Arch.PtrSize
    22  	RegSize         int64  // 4 or 8; copy of cmd/internal/sys.Arch.RegSize
    23  	Types           Types
    24  	lowerBlock      blockRewriter // lowering function
    25  	lowerValue      valueRewriter // lowering function
    26  	registers       []Register    // machine registers
    27  	gpRegMask       regMask       // general purpose integer register mask
    28  	fpRegMask       regMask       // floating point register mask
    29  	specialRegMask  regMask       // special register mask
    30  	FPReg           int8          // register number of frame pointer, -1 if not used
    31  	LinkReg         int8          // register number of link register if it is a general purpose register, -1 if not used
    32  	hasGReg         bool          // has hardware g register
    33  	ctxt            *obj.Link     // Generic arch information
    34  	optimize        bool          // Do optimization
    35  	noDuffDevice    bool          // Don't use Duff's device
    36  	useSSE          bool          // Use SSE for non-float operations
    37  	nacl            bool          // GOOS=nacl
    38  	use387          bool          // GO386=387
    39  	SoftFloat       bool          //
    40  	NeedsFpScratch  bool          // No direct move between GP and FP register sets
    41  	BigEndian       bool          //
    42  	sparsePhiCutoff uint64        // Sparse phi location algorithm used above this #blocks*#variables score
    43  }
    44  
    45  type (
    46  	blockRewriter func(*Block) bool
    47  	valueRewriter func(*Value) bool
    48  )
    49  
    50  type Types struct {
    51  	Bool       *types.Type
    52  	Int8       *types.Type
    53  	Int16      *types.Type
    54  	Int32      *types.Type
    55  	Int64      *types.Type
    56  	UInt8      *types.Type
    57  	UInt16     *types.Type
    58  	UInt32     *types.Type
    59  	UInt64     *types.Type
    60  	Int        *types.Type
    61  	Float32    *types.Type
    62  	Float64    *types.Type
    63  	UInt       *types.Type
    64  	Uintptr    *types.Type
    65  	String     *types.Type
    66  	BytePtr    *types.Type // TODO: use unsafe.Pointer instead?
    67  	Int32Ptr   *types.Type
    68  	UInt32Ptr  *types.Type
    69  	IntPtr     *types.Type
    70  	UintptrPtr *types.Type
    71  	Float32Ptr *types.Type
    72  	Float64Ptr *types.Type
    73  	BytePtrPtr *types.Type
    74  }
    75  
    76  type Logger interface {
    77  	// Logf logs a message from the compiler.
    78  	Logf(string, ...interface{})
    79  
    80  	// Log returns true if logging is not a no-op
    81  	// some logging calls account for more than a few heap allocations.
    82  	Log() bool
    83  
    84  	// Fatal reports a compiler error and exits.
    85  	Fatalf(pos src.XPos, msg string, args ...interface{})
    86  
    87  	// Warnl writes compiler messages in the form expected by "errorcheck" tests
    88  	Warnl(pos src.XPos, fmt_ string, args ...interface{})
    89  
    90  	// Forwards the Debug flags from gc
    91  	Debug_checknil() bool
    92  	Debug_eagerwb() bool
    93  }
    94  
    95  type Frontend interface {
    96  	CanSSA(t *types.Type) bool
    97  
    98  	Logger
    99  
   100  	// StringData returns a symbol pointing to the given string's contents.
   101  	StringData(string) interface{} // returns *gc.Sym
   102  
   103  	// Auto returns a Node for an auto variable of the given type.
   104  	// The SSA compiler uses this function to allocate space for spills.
   105  	Auto(src.XPos, *types.Type) GCNode
   106  
   107  	// Given the name for a compound type, returns the name we should use
   108  	// for the parts of that compound type.
   109  	SplitString(LocalSlot) (LocalSlot, LocalSlot)
   110  	SplitInterface(LocalSlot) (LocalSlot, LocalSlot)
   111  	SplitSlice(LocalSlot) (LocalSlot, LocalSlot, LocalSlot)
   112  	SplitComplex(LocalSlot) (LocalSlot, LocalSlot)
   113  	SplitStruct(LocalSlot, int) LocalSlot
   114  	SplitArray(LocalSlot) LocalSlot              // array must be length 1
   115  	SplitInt64(LocalSlot) (LocalSlot, LocalSlot) // returns (hi, lo)
   116  
   117  	// DerefItab dereferences an itab function
   118  	// entry, given the symbol of the itab and
   119  	// the byte offset of the function pointer.
   120  	// It may return nil.
   121  	DerefItab(sym *obj.LSym, offset int64) *obj.LSym
   122  
   123  	// Line returns a string describing the given position.
   124  	Line(src.XPos) string
   125  
   126  	// AllocFrame assigns frame offsets to all live auto variables.
   127  	AllocFrame(f *Func)
   128  
   129  	// Syslook returns a symbol of the runtime function/variable with the
   130  	// given name.
   131  	Syslook(string) *obj.LSym
   132  
   133  	// UseWriteBarrier returns whether write barrier is enabled
   134  	UseWriteBarrier() bool
   135  
   136  	// SetWBPos indicates that a write barrier has been inserted
   137  	// in this function at position pos.
   138  	SetWBPos(pos src.XPos)
   139  }
   140  
   141  // interface used to hold a *gc.Node (a stack variable).
   142  // We'd use *gc.Node directly but that would lead to an import cycle.
   143  type GCNode interface {
   144  	Typ() *types.Type
   145  	String() string
   146  	StorageClass() StorageClass
   147  }
   148  
   149  type StorageClass uint8
   150  
   151  const (
   152  	ClassAuto     StorageClass = iota // local stack variable
   153  	ClassParam                        // argument
   154  	ClassParamOut                     // return value
   155  )
   156  
   157  // NewConfig returns a new configuration object for the given architecture.
   158  func NewConfig(arch string, types Types, ctxt *obj.Link, optimize bool) *Config {
   159  	c := &Config{arch: arch, Types: types}
   160  	switch arch {
   161  	case "amd64":
   162  		c.PtrSize = 8
   163  		c.RegSize = 8
   164  		c.lowerBlock = rewriteBlockAMD64
   165  		c.lowerValue = rewriteValueAMD64
   166  		c.registers = registersAMD64[:]
   167  		c.gpRegMask = gpRegMaskAMD64
   168  		c.fpRegMask = fpRegMaskAMD64
   169  		c.FPReg = framepointerRegAMD64
   170  		c.LinkReg = linkRegAMD64
   171  		c.hasGReg = false
   172  	case "amd64p32":
   173  		c.PtrSize = 4
   174  		c.RegSize = 8
   175  		c.lowerBlock = rewriteBlockAMD64
   176  		c.lowerValue = rewriteValueAMD64
   177  		c.registers = registersAMD64[:]
   178  		c.gpRegMask = gpRegMaskAMD64
   179  		c.fpRegMask = fpRegMaskAMD64
   180  		c.FPReg = framepointerRegAMD64
   181  		c.LinkReg = linkRegAMD64
   182  		c.hasGReg = false
   183  		c.noDuffDevice = true
   184  	case "386":
   185  		c.PtrSize = 4
   186  		c.RegSize = 4
   187  		c.lowerBlock = rewriteBlock386
   188  		c.lowerValue = rewriteValue386
   189  		c.registers = registers386[:]
   190  		c.gpRegMask = gpRegMask386
   191  		c.fpRegMask = fpRegMask386
   192  		c.FPReg = framepointerReg386
   193  		c.LinkReg = linkReg386
   194  		c.hasGReg = false
   195  	case "arm":
   196  		c.PtrSize = 4
   197  		c.RegSize = 4
   198  		c.lowerBlock = rewriteBlockARM
   199  		c.lowerValue = rewriteValueARM
   200  		c.registers = registersARM[:]
   201  		c.gpRegMask = gpRegMaskARM
   202  		c.fpRegMask = fpRegMaskARM
   203  		c.FPReg = framepointerRegARM
   204  		c.LinkReg = linkRegARM
   205  		c.hasGReg = true
   206  	case "arm64":
   207  		c.PtrSize = 8
   208  		c.RegSize = 8
   209  		c.lowerBlock = rewriteBlockARM64
   210  		c.lowerValue = rewriteValueARM64
   211  		c.registers = registersARM64[:]
   212  		c.gpRegMask = gpRegMaskARM64
   213  		c.fpRegMask = fpRegMaskARM64
   214  		c.FPReg = framepointerRegARM64
   215  		c.LinkReg = linkRegARM64
   216  		c.hasGReg = true
   217  		c.noDuffDevice = objabi.GOOS == "darwin" // darwin linker cannot handle BR26 reloc with non-zero addend
   218  	case "ppc64":
   219  		c.BigEndian = true
   220  		fallthrough
   221  	case "ppc64le":
   222  		c.PtrSize = 8
   223  		c.RegSize = 8
   224  		c.lowerBlock = rewriteBlockPPC64
   225  		c.lowerValue = rewriteValuePPC64
   226  		c.registers = registersPPC64[:]
   227  		c.gpRegMask = gpRegMaskPPC64
   228  		c.fpRegMask = fpRegMaskPPC64
   229  		c.FPReg = framepointerRegPPC64
   230  		c.LinkReg = linkRegPPC64
   231  		c.noDuffDevice = true // TODO: Resolve PPC64 DuffDevice (has zero, but not copy)
   232  		c.hasGReg = true
   233  	case "mips64":
   234  		c.BigEndian = true
   235  		fallthrough
   236  	case "mips64le":
   237  		c.PtrSize = 8
   238  		c.RegSize = 8
   239  		c.lowerBlock = rewriteBlockMIPS64
   240  		c.lowerValue = rewriteValueMIPS64
   241  		c.registers = registersMIPS64[:]
   242  		c.gpRegMask = gpRegMaskMIPS64
   243  		c.fpRegMask = fpRegMaskMIPS64
   244  		c.specialRegMask = specialRegMaskMIPS64
   245  		c.FPReg = framepointerRegMIPS64
   246  		c.LinkReg = linkRegMIPS64
   247  		c.hasGReg = true
   248  	case "s390x":
   249  		c.PtrSize = 8
   250  		c.RegSize = 8
   251  		c.lowerBlock = rewriteBlockS390X
   252  		c.lowerValue = rewriteValueS390X
   253  		c.registers = registersS390X[:]
   254  		c.gpRegMask = gpRegMaskS390X
   255  		c.fpRegMask = fpRegMaskS390X
   256  		c.FPReg = framepointerRegS390X
   257  		c.LinkReg = linkRegS390X
   258  		c.hasGReg = true
   259  		c.noDuffDevice = true
   260  		c.BigEndian = true
   261  	case "mips":
   262  		c.BigEndian = true
   263  		fallthrough
   264  	case "mipsle":
   265  		c.PtrSize = 4
   266  		c.RegSize = 4
   267  		c.lowerBlock = rewriteBlockMIPS
   268  		c.lowerValue = rewriteValueMIPS
   269  		c.registers = registersMIPS[:]
   270  		c.gpRegMask = gpRegMaskMIPS
   271  		c.fpRegMask = fpRegMaskMIPS
   272  		c.specialRegMask = specialRegMaskMIPS
   273  		c.FPReg = framepointerRegMIPS
   274  		c.LinkReg = linkRegMIPS
   275  		c.hasGReg = true
   276  		c.noDuffDevice = true
   277  	default:
   278  		ctxt.Diag("arch %s not implemented", arch)
   279  	}
   280  	c.ctxt = ctxt
   281  	c.optimize = optimize
   282  	c.nacl = objabi.GOOS == "nacl"
   283  	c.useSSE = true
   284  
   285  	// Don't use Duff's device nor SSE on Plan 9 AMD64, because
   286  	// floating point operations are not allowed in note handler.
   287  	if objabi.GOOS == "plan9" && arch == "amd64" {
   288  		c.noDuffDevice = true
   289  		c.useSSE = false
   290  	}
   291  
   292  	if c.nacl {
   293  		c.noDuffDevice = true // Don't use Duff's device on NaCl
   294  
   295  		// runtime call clobber R12 on nacl
   296  		opcodeTable[OpARMCALLudiv].reg.clobbers |= 1 << 12 // R12
   297  	}
   298  
   299  	// cutoff is compared with product of numblocks and numvalues,
   300  	// if product is smaller than cutoff, use old non-sparse method.
   301  	// cutoff == 0 implies all sparse.
   302  	// cutoff == -1 implies none sparse.
   303  	// Good cutoff values seem to be O(million) depending on constant factor cost of sparse.
   304  	// TODO: get this from a flag, not an environment variable
   305  	c.sparsePhiCutoff = 2500000 // 0 for testing. // 2500000 determined with crude experiments w/ make.bash
   306  	ev := os.Getenv("GO_SSA_PHI_LOC_CUTOFF")
   307  	if ev != "" {
   308  		v, err := strconv.ParseInt(ev, 10, 64)
   309  		if err != nil {
   310  			ctxt.Diag("Environment variable GO_SSA_PHI_LOC_CUTOFF (value '%s') did not parse as a number", ev)
   311  		}
   312  		c.sparsePhiCutoff = uint64(v) // convert -1 to maxint, for never use sparse
   313  	}
   314  
   315  	return c
   316  }
   317  
   318  func (c *Config) Set387(b bool) {
   319  	c.NeedsFpScratch = b
   320  	c.use387 = b
   321  }
   322  
   323  func (c *Config) SparsePhiCutoff() uint64 { return c.sparsePhiCutoff }
   324  func (c *Config) Ctxt() *obj.Link         { return c.ctxt }