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