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