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