github.com/megatontech/mynoteforgo@v0.0.0-20200507084910-5d0c6ea6e890/源码/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 ) 13 14 // A Config holds readonly compilation information. 15 // It is created once, early during compilation, 16 // and shared across all compilations. 17 type Config struct { 18 arch string // "amd64", etc. 19 PtrSize int64 // 4 or 8; copy of cmd/internal/sys.Arch.PtrSize 20 RegSize int64 // 4 or 8; copy of cmd/internal/sys.Arch.RegSize 21 Types Types 22 lowerBlock blockRewriter // lowering function 23 lowerValue valueRewriter // lowering function 24 registers []Register // machine registers 25 gpRegMask regMask // general purpose integer register mask 26 fpRegMask regMask // floating point register mask 27 specialRegMask regMask // special register mask 28 GCRegMap []*Register // garbage collector register map, by GC register index 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 useSSE bool // Use SSE for non-float operations 36 useAvg bool // Use optimizations that need Avg* operations 37 useHmul bool // Use optimizations that need Hmul* operations 38 nacl bool // GOOS=nacl 39 use387 bool // GO386=387 40 SoftFloat bool // 41 Race bool // race detector enabled 42 NeedsFpScratch bool // No direct move between GP and FP register sets 43 BigEndian bool // 44 } 45 46 type ( 47 blockRewriter func(*Block) bool 48 valueRewriter func(*Value) bool 49 ) 50 51 type Types struct { 52 Bool *types.Type 53 Int8 *types.Type 54 Int16 *types.Type 55 Int32 *types.Type 56 Int64 *types.Type 57 UInt8 *types.Type 58 UInt16 *types.Type 59 UInt32 *types.Type 60 UInt64 *types.Type 61 Int *types.Type 62 Float32 *types.Type 63 Float64 *types.Type 64 UInt *types.Type 65 Uintptr *types.Type 66 String *types.Type 67 BytePtr *types.Type // TODO: use unsafe.Pointer instead? 68 Int32Ptr *types.Type 69 UInt32Ptr *types.Type 70 IntPtr *types.Type 71 UintptrPtr *types.Type 72 Float32Ptr *types.Type 73 Float64Ptr *types.Type 74 BytePtrPtr *types.Type 75 } 76 77 // NewTypes creates and populates a Types. 78 func NewTypes() *Types { 79 t := new(Types) 80 t.SetTypPtrs() 81 return t 82 } 83 84 // SetTypPtrs populates t. 85 func (t *Types) SetTypPtrs() { 86 t.Bool = types.Types[types.TBOOL] 87 t.Int8 = types.Types[types.TINT8] 88 t.Int16 = types.Types[types.TINT16] 89 t.Int32 = types.Types[types.TINT32] 90 t.Int64 = types.Types[types.TINT64] 91 t.UInt8 = types.Types[types.TUINT8] 92 t.UInt16 = types.Types[types.TUINT16] 93 t.UInt32 = types.Types[types.TUINT32] 94 t.UInt64 = types.Types[types.TUINT64] 95 t.Int = types.Types[types.TINT] 96 t.Float32 = types.Types[types.TFLOAT32] 97 t.Float64 = types.Types[types.TFLOAT64] 98 t.UInt = types.Types[types.TUINT] 99 t.Uintptr = types.Types[types.TUINTPTR] 100 t.String = types.Types[types.TSTRING] 101 t.BytePtr = types.NewPtr(types.Types[types.TUINT8]) 102 t.Int32Ptr = types.NewPtr(types.Types[types.TINT32]) 103 t.UInt32Ptr = types.NewPtr(types.Types[types.TUINT32]) 104 t.IntPtr = types.NewPtr(types.Types[types.TINT]) 105 t.UintptrPtr = types.NewPtr(types.Types[types.TUINTPTR]) 106 t.Float32Ptr = types.NewPtr(types.Types[types.TFLOAT32]) 107 t.Float64Ptr = types.NewPtr(types.Types[types.TFLOAT64]) 108 t.BytePtrPtr = types.NewPtr(types.NewPtr(types.Types[types.TUINT8])) 109 } 110 111 type Logger interface { 112 // Logf logs a message from the compiler. 113 Logf(string, ...interface{}) 114 115 // Log reports whether logging is not a no-op 116 // some logging calls account for more than a few heap allocations. 117 Log() bool 118 119 // Fatal reports a compiler error and exits. 120 Fatalf(pos src.XPos, msg string, args ...interface{}) 121 122 // Warnl writes compiler messages in the form expected by "errorcheck" tests 123 Warnl(pos src.XPos, fmt_ string, args ...interface{}) 124 125 // Forwards the Debug flags from gc 126 Debug_checknil() bool 127 } 128 129 type Frontend interface { 130 CanSSA(t *types.Type) bool 131 132 Logger 133 134 // StringData returns a symbol pointing to the given string's contents. 135 StringData(string) interface{} // returns *gc.Sym 136 137 // Auto returns a Node for an auto variable of the given type. 138 // The SSA compiler uses this function to allocate space for spills. 139 Auto(src.XPos, *types.Type) GCNode 140 141 // Given the name for a compound type, returns the name we should use 142 // for the parts of that compound type. 143 SplitString(LocalSlot) (LocalSlot, LocalSlot) 144 SplitInterface(LocalSlot) (LocalSlot, LocalSlot) 145 SplitSlice(LocalSlot) (LocalSlot, LocalSlot, LocalSlot) 146 SplitComplex(LocalSlot) (LocalSlot, LocalSlot) 147 SplitStruct(LocalSlot, int) LocalSlot 148 SplitArray(LocalSlot) LocalSlot // array must be length 1 149 SplitInt64(LocalSlot) (LocalSlot, LocalSlot) // returns (hi, lo) 150 151 // DerefItab dereferences an itab function 152 // entry, given the symbol of the itab and 153 // the byte offset of the function pointer. 154 // It may return nil. 155 DerefItab(sym *obj.LSym, offset int64) *obj.LSym 156 157 // Line returns a string describing the given position. 158 Line(src.XPos) string 159 160 // AllocFrame assigns frame offsets to all live auto variables. 161 AllocFrame(f *Func) 162 163 // Syslook returns a symbol of the runtime function/variable with the 164 // given name. 165 Syslook(string) *obj.LSym 166 167 // UseWriteBarrier reports whether write barrier is enabled 168 UseWriteBarrier() bool 169 170 // SetWBPos indicates that a write barrier has been inserted 171 // in this function at position pos. 172 SetWBPos(pos src.XPos) 173 } 174 175 // interface used to hold a *gc.Node (a stack variable). 176 // We'd use *gc.Node directly but that would lead to an import cycle. 177 type GCNode interface { 178 Typ() *types.Type 179 String() string 180 IsSynthetic() bool 181 IsAutoTmp() bool 182 StorageClass() StorageClass 183 } 184 185 type StorageClass uint8 186 187 const ( 188 ClassAuto StorageClass = iota // local stack variable 189 ClassParam // argument 190 ClassParamOut // return value 191 ) 192 193 // NewConfig returns a new configuration object for the given architecture. 194 func NewConfig(arch string, types Types, ctxt *obj.Link, optimize bool) *Config { 195 c := &Config{arch: arch, Types: types} 196 c.useAvg = true 197 c.useHmul = true 198 switch arch { 199 case "amd64": 200 c.PtrSize = 8 201 c.RegSize = 8 202 c.lowerBlock = rewriteBlockAMD64 203 c.lowerValue = rewriteValueAMD64 204 c.registers = registersAMD64[:] 205 c.gpRegMask = gpRegMaskAMD64 206 c.fpRegMask = fpRegMaskAMD64 207 c.FPReg = framepointerRegAMD64 208 c.LinkReg = linkRegAMD64 209 c.hasGReg = false 210 case "amd64p32": 211 c.PtrSize = 4 212 c.RegSize = 8 213 c.lowerBlock = rewriteBlockAMD64 214 c.lowerValue = rewriteValueAMD64 215 c.registers = registersAMD64[:] 216 c.gpRegMask = gpRegMaskAMD64 217 c.fpRegMask = fpRegMaskAMD64 218 c.FPReg = framepointerRegAMD64 219 c.LinkReg = linkRegAMD64 220 c.hasGReg = false 221 c.noDuffDevice = true 222 case "386": 223 c.PtrSize = 4 224 c.RegSize = 4 225 c.lowerBlock = rewriteBlock386 226 c.lowerValue = rewriteValue386 227 c.registers = registers386[:] 228 c.gpRegMask = gpRegMask386 229 c.fpRegMask = fpRegMask386 230 c.FPReg = framepointerReg386 231 c.LinkReg = linkReg386 232 c.hasGReg = false 233 case "arm": 234 c.PtrSize = 4 235 c.RegSize = 4 236 c.lowerBlock = rewriteBlockARM 237 c.lowerValue = rewriteValueARM 238 c.registers = registersARM[:] 239 c.gpRegMask = gpRegMaskARM 240 c.fpRegMask = fpRegMaskARM 241 c.FPReg = framepointerRegARM 242 c.LinkReg = linkRegARM 243 c.hasGReg = true 244 case "arm64": 245 c.PtrSize = 8 246 c.RegSize = 8 247 c.lowerBlock = rewriteBlockARM64 248 c.lowerValue = rewriteValueARM64 249 c.registers = registersARM64[:] 250 c.gpRegMask = gpRegMaskARM64 251 c.fpRegMask = fpRegMaskARM64 252 c.FPReg = framepointerRegARM64 253 c.LinkReg = linkRegARM64 254 c.hasGReg = true 255 c.noDuffDevice = objabi.GOOS == "darwin" // darwin linker cannot handle BR26 reloc with non-zero addend 256 case "ppc64": 257 c.BigEndian = true 258 fallthrough 259 case "ppc64le": 260 c.PtrSize = 8 261 c.RegSize = 8 262 c.lowerBlock = rewriteBlockPPC64 263 c.lowerValue = rewriteValuePPC64 264 c.registers = registersPPC64[:] 265 c.gpRegMask = gpRegMaskPPC64 266 c.fpRegMask = fpRegMaskPPC64 267 c.FPReg = framepointerRegPPC64 268 c.LinkReg = linkRegPPC64 269 c.noDuffDevice = true // TODO: Resolve PPC64 DuffDevice (has zero, but not copy) 270 c.hasGReg = true 271 case "mips64": 272 c.BigEndian = true 273 fallthrough 274 case "mips64le": 275 c.PtrSize = 8 276 c.RegSize = 8 277 c.lowerBlock = rewriteBlockMIPS64 278 c.lowerValue = rewriteValueMIPS64 279 c.registers = registersMIPS64[:] 280 c.gpRegMask = gpRegMaskMIPS64 281 c.fpRegMask = fpRegMaskMIPS64 282 c.specialRegMask = specialRegMaskMIPS64 283 c.FPReg = framepointerRegMIPS64 284 c.LinkReg = linkRegMIPS64 285 c.hasGReg = true 286 case "s390x": 287 c.PtrSize = 8 288 c.RegSize = 8 289 c.lowerBlock = rewriteBlockS390X 290 c.lowerValue = rewriteValueS390X 291 c.registers = registersS390X[:] 292 c.gpRegMask = gpRegMaskS390X 293 c.fpRegMask = fpRegMaskS390X 294 c.FPReg = framepointerRegS390X 295 c.LinkReg = linkRegS390X 296 c.hasGReg = true 297 c.noDuffDevice = true 298 c.BigEndian = true 299 case "mips": 300 c.BigEndian = true 301 fallthrough 302 case "mipsle": 303 c.PtrSize = 4 304 c.RegSize = 4 305 c.lowerBlock = rewriteBlockMIPS 306 c.lowerValue = rewriteValueMIPS 307 c.registers = registersMIPS[:] 308 c.gpRegMask = gpRegMaskMIPS 309 c.fpRegMask = fpRegMaskMIPS 310 c.specialRegMask = specialRegMaskMIPS 311 c.FPReg = framepointerRegMIPS 312 c.LinkReg = linkRegMIPS 313 c.hasGReg = true 314 c.noDuffDevice = true 315 case "wasm": 316 c.PtrSize = 8 317 c.RegSize = 8 318 c.lowerBlock = rewriteBlockWasm 319 c.lowerValue = rewriteValueWasm 320 c.registers = registersWasm[:] 321 c.gpRegMask = gpRegMaskWasm 322 c.fpRegMask = fpRegMaskWasm 323 c.FPReg = framepointerRegWasm 324 c.LinkReg = linkRegWasm 325 c.hasGReg = true 326 c.noDuffDevice = true 327 c.useAvg = false 328 c.useHmul = false 329 default: 330 ctxt.Diag("arch %s not implemented", arch) 331 } 332 c.ctxt = ctxt 333 c.optimize = optimize 334 c.nacl = objabi.GOOS == "nacl" 335 c.useSSE = true 336 337 // Don't use Duff's device nor SSE on Plan 9 AMD64, because 338 // floating point operations are not allowed in note handler. 339 if objabi.GOOS == "plan9" && arch == "amd64" { 340 c.noDuffDevice = true 341 c.useSSE = false 342 } 343 344 if c.nacl { 345 c.noDuffDevice = true // Don't use Duff's device on NaCl 346 347 // Returns clobber BP on nacl/386, so the write 348 // barrier does. 349 opcodeTable[Op386LoweredWB].reg.clobbers |= 1 << 5 // BP 350 351 // ... and SI on nacl/amd64. 352 opcodeTable[OpAMD64LoweredWB].reg.clobbers |= 1 << 6 // SI 353 } 354 355 if ctxt.Flag_shared { 356 // LoweredWB is secretly a CALL and CALLs on 386 in 357 // shared mode get rewritten by obj6.go to go through 358 // the GOT, which clobbers BX. 359 opcodeTable[Op386LoweredWB].reg.clobbers |= 1 << 3 // BX 360 } 361 362 // Create the GC register map index. 363 // TODO: This is only used for debug printing. Maybe export config.registers? 364 gcRegMapSize := int16(0) 365 for _, r := range c.registers { 366 if r.gcNum+1 > gcRegMapSize { 367 gcRegMapSize = r.gcNum + 1 368 } 369 } 370 c.GCRegMap = make([]*Register, gcRegMapSize) 371 for i, r := range c.registers { 372 if r.gcNum != -1 { 373 c.GCRegMap[r.gcNum] = &c.registers[i] 374 } 375 } 376 377 return c 378 } 379 380 func (c *Config) Set387(b bool) { 381 c.NeedsFpScratch = b 382 c.use387 = b 383 } 384 385 func (c *Config) Ctxt() *obj.Link { return c.ctxt }