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