github.com/stingnevermore/go@v0.0.0-20180120041312-3810f5bfed72/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 }