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