github.com/mattn/go@v0.0.0-20171011075504-07f7db3ea99f/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_wb() 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 136 // interface used to hold a *gc.Node (a stack variable). 137 // We'd use *gc.Node directly but that would lead to an import cycle. 138 type GCNode interface { 139 Typ() *types.Type 140 String() string 141 StorageClass() StorageClass 142 } 143 144 type StorageClass uint8 145 146 const ( 147 ClassAuto StorageClass = iota // local stack variable 148 ClassParam // argument 149 ClassParamOut // return value 150 ) 151 152 // NewConfig returns a new configuration object for the given architecture. 153 func NewConfig(arch string, types Types, ctxt *obj.Link, optimize bool) *Config { 154 c := &Config{arch: arch, Types: types} 155 switch arch { 156 case "amd64": 157 c.PtrSize = 8 158 c.RegSize = 8 159 c.lowerBlock = rewriteBlockAMD64 160 c.lowerValue = rewriteValueAMD64 161 c.registers = registersAMD64[:] 162 c.gpRegMask = gpRegMaskAMD64 163 c.fpRegMask = fpRegMaskAMD64 164 c.FPReg = framepointerRegAMD64 165 c.LinkReg = linkRegAMD64 166 c.hasGReg = false 167 case "amd64p32": 168 c.PtrSize = 4 169 c.RegSize = 8 170 c.lowerBlock = rewriteBlockAMD64 171 c.lowerValue = rewriteValueAMD64 172 c.registers = registersAMD64[:] 173 c.gpRegMask = gpRegMaskAMD64 174 c.fpRegMask = fpRegMaskAMD64 175 c.FPReg = framepointerRegAMD64 176 c.LinkReg = linkRegAMD64 177 c.hasGReg = false 178 c.noDuffDevice = true 179 case "386": 180 c.PtrSize = 4 181 c.RegSize = 4 182 c.lowerBlock = rewriteBlock386 183 c.lowerValue = rewriteValue386 184 c.registers = registers386[:] 185 c.gpRegMask = gpRegMask386 186 c.fpRegMask = fpRegMask386 187 c.FPReg = framepointerReg386 188 c.LinkReg = linkReg386 189 c.hasGReg = false 190 case "arm": 191 c.PtrSize = 4 192 c.RegSize = 4 193 c.lowerBlock = rewriteBlockARM 194 c.lowerValue = rewriteValueARM 195 c.registers = registersARM[:] 196 c.gpRegMask = gpRegMaskARM 197 c.fpRegMask = fpRegMaskARM 198 c.FPReg = framepointerRegARM 199 c.LinkReg = linkRegARM 200 c.hasGReg = true 201 case "arm64": 202 c.PtrSize = 8 203 c.RegSize = 8 204 c.lowerBlock = rewriteBlockARM64 205 c.lowerValue = rewriteValueARM64 206 c.registers = registersARM64[:] 207 c.gpRegMask = gpRegMaskARM64 208 c.fpRegMask = fpRegMaskARM64 209 c.FPReg = framepointerRegARM64 210 c.LinkReg = linkRegARM64 211 c.hasGReg = true 212 c.noDuffDevice = objabi.GOOS == "darwin" // darwin linker cannot handle BR26 reloc with non-zero addend 213 case "ppc64": 214 c.BigEndian = true 215 fallthrough 216 case "ppc64le": 217 c.PtrSize = 8 218 c.RegSize = 8 219 c.lowerBlock = rewriteBlockPPC64 220 c.lowerValue = rewriteValuePPC64 221 c.registers = registersPPC64[:] 222 c.gpRegMask = gpRegMaskPPC64 223 c.fpRegMask = fpRegMaskPPC64 224 c.FPReg = framepointerRegPPC64 225 c.LinkReg = linkRegPPC64 226 c.noDuffDevice = true // TODO: Resolve PPC64 DuffDevice (has zero, but not copy) 227 c.hasGReg = true 228 case "mips64": 229 c.BigEndian = true 230 fallthrough 231 case "mips64le": 232 c.PtrSize = 8 233 c.RegSize = 8 234 c.lowerBlock = rewriteBlockMIPS64 235 c.lowerValue = rewriteValueMIPS64 236 c.registers = registersMIPS64[:] 237 c.gpRegMask = gpRegMaskMIPS64 238 c.fpRegMask = fpRegMaskMIPS64 239 c.specialRegMask = specialRegMaskMIPS64 240 c.FPReg = framepointerRegMIPS64 241 c.LinkReg = linkRegMIPS64 242 c.hasGReg = true 243 case "s390x": 244 c.PtrSize = 8 245 c.RegSize = 8 246 c.lowerBlock = rewriteBlockS390X 247 c.lowerValue = rewriteValueS390X 248 c.registers = registersS390X[:] 249 c.gpRegMask = gpRegMaskS390X 250 c.fpRegMask = fpRegMaskS390X 251 c.FPReg = framepointerRegS390X 252 c.LinkReg = linkRegS390X 253 c.hasGReg = true 254 c.noDuffDevice = true 255 c.BigEndian = true 256 case "mips": 257 c.BigEndian = true 258 fallthrough 259 case "mipsle": 260 c.PtrSize = 4 261 c.RegSize = 4 262 c.lowerBlock = rewriteBlockMIPS 263 c.lowerValue = rewriteValueMIPS 264 c.registers = registersMIPS[:] 265 c.gpRegMask = gpRegMaskMIPS 266 c.fpRegMask = fpRegMaskMIPS 267 c.specialRegMask = specialRegMaskMIPS 268 c.FPReg = framepointerRegMIPS 269 c.LinkReg = linkRegMIPS 270 c.hasGReg = true 271 c.noDuffDevice = true 272 default: 273 ctxt.Diag("arch %s not implemented", arch) 274 } 275 c.ctxt = ctxt 276 c.optimize = optimize 277 c.nacl = objabi.GOOS == "nacl" 278 c.useSSE = true 279 280 // Don't use Duff's device nor SSE on Plan 9 AMD64, because 281 // floating point operations are not allowed in note handler. 282 if objabi.GOOS == "plan9" && arch == "amd64" { 283 c.noDuffDevice = true 284 c.useSSE = false 285 } 286 287 if c.nacl { 288 c.noDuffDevice = true // Don't use Duff's device on NaCl 289 290 // runtime call clobber R12 on nacl 291 opcodeTable[OpARMCALLudiv].reg.clobbers |= 1 << 12 // R12 292 } 293 294 // cutoff is compared with product of numblocks and numvalues, 295 // if product is smaller than cutoff, use old non-sparse method. 296 // cutoff == 0 implies all sparse. 297 // cutoff == -1 implies none sparse. 298 // Good cutoff values seem to be O(million) depending on constant factor cost of sparse. 299 // TODO: get this from a flag, not an environment variable 300 c.sparsePhiCutoff = 2500000 // 0 for testing. // 2500000 determined with crude experiments w/ make.bash 301 ev := os.Getenv("GO_SSA_PHI_LOC_CUTOFF") 302 if ev != "" { 303 v, err := strconv.ParseInt(ev, 10, 64) 304 if err != nil { 305 ctxt.Diag("Environment variable GO_SSA_PHI_LOC_CUTOFF (value '%s') did not parse as a number", ev) 306 } 307 c.sparsePhiCutoff = uint64(v) // convert -1 to maxint, for never use sparse 308 } 309 310 return c 311 } 312 313 func (c *Config) Set387(b bool) { 314 c.NeedsFpScratch = b 315 c.use387 = b 316 } 317 318 func (c *Config) SparsePhiCutoff() uint64 { return c.sparsePhiCutoff } 319 func (c *Config) Ctxt() *obj.Link { return c.ctxt }