github.com/corona10/go@v0.0.0-20180224231303-7a218942be57/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 } 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 IsSynthetic() bool 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 // Returns clobber BP on nacl/386, so the write 296 // barrier does. 297 opcodeTable[Op386LoweredWB].reg.clobbers |= 1 << 5 // BP 298 299 // ... and SI on nacl/amd64. 300 opcodeTable[OpAMD64LoweredWB].reg.clobbers |= 1 << 6 // SI 301 } 302 303 if ctxt.Flag_shared { 304 // LoweredWB is secretly a CALL and CALLs on 386 in 305 // shared mode get rewritten by obj6.go to go through 306 // the GOT, which clobbers BX. 307 opcodeTable[Op386LoweredWB].reg.clobbers |= 1 << 3 // BX 308 } 309 310 // cutoff is compared with product of numblocks and numvalues, 311 // if product is smaller than cutoff, use old non-sparse method. 312 // cutoff == 0 implies all sparse. 313 // cutoff == -1 implies none sparse. 314 // Good cutoff values seem to be O(million) depending on constant factor cost of sparse. 315 // TODO: get this from a flag, not an environment variable 316 c.sparsePhiCutoff = 2500000 // 0 for testing. // 2500000 determined with crude experiments w/ make.bash 317 ev := os.Getenv("GO_SSA_PHI_LOC_CUTOFF") 318 if ev != "" { 319 v, err := strconv.ParseInt(ev, 10, 64) 320 if err != nil { 321 ctxt.Diag("Environment variable GO_SSA_PHI_LOC_CUTOFF (value '%s') did not parse as a number", ev) 322 } 323 c.sparsePhiCutoff = uint64(v) // convert -1 to maxint, for never use sparse 324 } 325 326 return c 327 } 328 329 func (c *Config) Set387(b bool) { 330 c.NeedsFpScratch = b 331 c.use387 = b 332 } 333 334 func (c *Config) SparsePhiCutoff() uint64 { return c.sparsePhiCutoff } 335 func (c *Config) Ctxt() *obj.Link { return c.ctxt }