github.com/bir3/gocompiler@v0.9.2202/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 "github.com/bir3/gocompiler/src/cmd/compile/internal/abi" 9 "github.com/bir3/gocompiler/src/cmd/compile/internal/base" 10 "github.com/bir3/gocompiler/src/cmd/compile/internal/ir" 11 "github.com/bir3/gocompiler/src/cmd/compile/internal/types" 12 "github.com/bir3/gocompiler/src/cmd/internal/obj" 13 "github.com/bir3/gocompiler/src/cmd/internal/src" 14 "github.com/bir3/gocompiler/src/internal/buildcfg" 15 ) 16 17 // A Config holds readonly compilation information. 18 // It is created once, early during compilation, 19 // and shared across all compilations. 20 type Config struct { 21 arch string // "amd64", etc. 22 PtrSize int64 // 4 or 8; copy of cmd/internal/sys.Arch.PtrSize 23 RegSize int64 // 4 or 8; copy of cmd/internal/sys.Arch.RegSize 24 Types Types 25 lowerBlock blockRewriter // block lowering function, first round 26 lowerValue valueRewriter // value lowering function, first round 27 lateLowerBlock blockRewriter // block lowering function that needs to be run after the first round; only used on some architectures 28 lateLowerValue valueRewriter // value lowering function that needs to be run after the first round; only used on some architectures 29 splitLoad valueRewriter // function for splitting merged load ops; only used on some architectures 30 registers []Register // machine registers 31 gpRegMask regMask // general purpose integer register mask 32 fpRegMask regMask // floating point register mask 33 fp32RegMask regMask // floating point register mask 34 fp64RegMask regMask // floating point register mask 35 specialRegMask regMask // special register mask 36 intParamRegs []int8 // register numbers of integer param (in/out) registers 37 floatParamRegs []int8 // register numbers of floating param (in/out) registers 38 ABI1 *abi.ABIConfig // "ABIInternal" under development // TODO change comment when this becomes current 39 ABI0 *abi.ABIConfig 40 GCRegMap []*Register // garbage collector register map, by GC register index 41 FPReg int8 // register number of frame pointer, -1 if not used 42 LinkReg int8 // register number of link register if it is a general purpose register, -1 if not used 43 hasGReg bool // has hardware g register 44 ctxt *obj.Link // Generic arch information 45 optimize bool // Do optimization 46 noDuffDevice bool // Don't use Duff's device 47 useSSE bool // Use SSE for non-float operations 48 useAvg bool // Use optimizations that need Avg* operations 49 useHmul bool // Use optimizations that need Hmul* operations 50 SoftFloat bool // 51 Race bool // race detector enabled 52 BigEndian bool // 53 UseFMA bool // Use hardware FMA operation 54 unalignedOK bool // Unaligned loads/stores are ok 55 haveBswap64 bool // architecture implements Bswap64 56 haveBswap32 bool // architecture implements Bswap32 57 haveBswap16 bool // architecture implements Bswap16 58 } 59 60 type ( 61 blockRewriter func(*Block) bool 62 valueRewriter func(*Value) bool 63 ) 64 65 type Types struct { 66 Bool *types.Type 67 Int8 *types.Type 68 Int16 *types.Type 69 Int32 *types.Type 70 Int64 *types.Type 71 UInt8 *types.Type 72 UInt16 *types.Type 73 UInt32 *types.Type 74 UInt64 *types.Type 75 Int *types.Type 76 Float32 *types.Type 77 Float64 *types.Type 78 UInt *types.Type 79 Uintptr *types.Type 80 String *types.Type 81 BytePtr *types.Type // TODO: use unsafe.Pointer instead? 82 Int32Ptr *types.Type 83 UInt32Ptr *types.Type 84 IntPtr *types.Type 85 UintptrPtr *types.Type 86 Float32Ptr *types.Type 87 Float64Ptr *types.Type 88 BytePtrPtr *types.Type 89 } 90 91 // NewTypes creates and populates a Types. 92 func NewTypes() *Types { 93 t := new(Types) 94 t.SetTypPtrs() 95 return t 96 } 97 98 // SetTypPtrs populates t. 99 func (t *Types) SetTypPtrs() { 100 t.Bool = types.Types[types.TBOOL] 101 t.Int8 = types.Types[types.TINT8] 102 t.Int16 = types.Types[types.TINT16] 103 t.Int32 = types.Types[types.TINT32] 104 t.Int64 = types.Types[types.TINT64] 105 t.UInt8 = types.Types[types.TUINT8] 106 t.UInt16 = types.Types[types.TUINT16] 107 t.UInt32 = types.Types[types.TUINT32] 108 t.UInt64 = types.Types[types.TUINT64] 109 t.Int = types.Types[types.TINT] 110 t.Float32 = types.Types[types.TFLOAT32] 111 t.Float64 = types.Types[types.TFLOAT64] 112 t.UInt = types.Types[types.TUINT] 113 t.Uintptr = types.Types[types.TUINTPTR] 114 t.String = types.Types[types.TSTRING] 115 t.BytePtr = types.NewPtr(types.Types[types.TUINT8]) 116 t.Int32Ptr = types.NewPtr(types.Types[types.TINT32]) 117 t.UInt32Ptr = types.NewPtr(types.Types[types.TUINT32]) 118 t.IntPtr = types.NewPtr(types.Types[types.TINT]) 119 t.UintptrPtr = types.NewPtr(types.Types[types.TUINTPTR]) 120 t.Float32Ptr = types.NewPtr(types.Types[types.TFLOAT32]) 121 t.Float64Ptr = types.NewPtr(types.Types[types.TFLOAT64]) 122 t.BytePtrPtr = types.NewPtr(types.NewPtr(types.Types[types.TUINT8])) 123 } 124 125 type Logger interface { 126 // Logf logs a message from the compiler. 127 Logf(string, ...interface{}) 128 129 // Log reports whether logging is not a no-op 130 // some logging calls account for more than a few heap allocations. 131 Log() bool 132 133 // Fatal reports a compiler error and exits. 134 Fatalf(pos src.XPos, msg string, args ...interface{}) 135 136 // Warnl writes compiler messages in the form expected by "errorcheck" tests 137 Warnl(pos src.XPos, fmt_ string, args ...interface{}) 138 139 // Forwards the Debug flags from gc 140 Debug_checknil() bool 141 } 142 143 type Frontend interface { 144 Logger 145 146 // StringData returns a symbol pointing to the given string's contents. 147 StringData(string) *obj.LSym 148 149 // Given the name for a compound type, returns the name we should use 150 // for the parts of that compound type. 151 SplitSlot(parent *LocalSlot, suffix string, offset int64, t *types.Type) LocalSlot 152 153 // Syslook returns a symbol of the runtime function/variable with the 154 // given name. 155 Syslook(string) *obj.LSym 156 157 // UseWriteBarrier reports whether write barrier is enabled 158 UseWriteBarrier() bool 159 160 // Func returns the ir.Func of the function being compiled. 161 Func() *ir.Func 162 } 163 164 // NewConfig returns a new configuration object for the given architecture. 165 func NewConfig(arch string, types Types, ctxt *obj.Link, optimize, softfloat bool) *Config { 166 c := &Config{arch: arch, Types: types} 167 c.useAvg = true 168 c.useHmul = true 169 switch arch { 170 case "amd64": 171 c.PtrSize = 8 172 c.RegSize = 8 173 c.lowerBlock = rewriteBlockAMD64 174 c.lowerValue = rewriteValueAMD64 175 c.lateLowerBlock = rewriteBlockAMD64latelower 176 c.lateLowerValue = rewriteValueAMD64latelower 177 c.splitLoad = rewriteValueAMD64splitload 178 c.registers = registersAMD64[:] 179 c.gpRegMask = gpRegMaskAMD64 180 c.fpRegMask = fpRegMaskAMD64 181 c.specialRegMask = specialRegMaskAMD64 182 c.intParamRegs = paramIntRegAMD64 183 c.floatParamRegs = paramFloatRegAMD64 184 c.FPReg = framepointerRegAMD64 185 c.LinkReg = linkRegAMD64 186 c.hasGReg = true 187 c.unalignedOK = true 188 c.haveBswap64 = true 189 c.haveBswap32 = true 190 c.haveBswap16 = true 191 case "386": 192 c.PtrSize = 4 193 c.RegSize = 4 194 c.lowerBlock = rewriteBlock386 195 c.lowerValue = rewriteValue386 196 c.splitLoad = rewriteValue386splitload 197 c.registers = registers386[:] 198 c.gpRegMask = gpRegMask386 199 c.fpRegMask = fpRegMask386 200 c.FPReg = framepointerReg386 201 c.LinkReg = linkReg386 202 c.hasGReg = false 203 c.unalignedOK = true 204 c.haveBswap32 = true 205 c.haveBswap16 = true 206 case "arm": 207 c.PtrSize = 4 208 c.RegSize = 4 209 c.lowerBlock = rewriteBlockARM 210 c.lowerValue = rewriteValueARM 211 c.registers = registersARM[:] 212 c.gpRegMask = gpRegMaskARM 213 c.fpRegMask = fpRegMaskARM 214 c.FPReg = framepointerRegARM 215 c.LinkReg = linkRegARM 216 c.hasGReg = true 217 case "arm64": 218 c.PtrSize = 8 219 c.RegSize = 8 220 c.lowerBlock = rewriteBlockARM64 221 c.lowerValue = rewriteValueARM64 222 c.lateLowerBlock = rewriteBlockARM64latelower 223 c.lateLowerValue = rewriteValueARM64latelower 224 c.registers = registersARM64[:] 225 c.gpRegMask = gpRegMaskARM64 226 c.fpRegMask = fpRegMaskARM64 227 c.intParamRegs = paramIntRegARM64 228 c.floatParamRegs = paramFloatRegARM64 229 c.FPReg = framepointerRegARM64 230 c.LinkReg = linkRegARM64 231 c.hasGReg = true 232 c.unalignedOK = true 233 c.haveBswap64 = true 234 c.haveBswap32 = true 235 c.haveBswap16 = true 236 case "ppc64": 237 c.BigEndian = true 238 fallthrough 239 case "ppc64le": 240 c.PtrSize = 8 241 c.RegSize = 8 242 c.lowerBlock = rewriteBlockPPC64 243 c.lowerValue = rewriteValuePPC64 244 c.lateLowerBlock = rewriteBlockPPC64latelower 245 c.lateLowerValue = rewriteValuePPC64latelower 246 c.registers = registersPPC64[:] 247 c.gpRegMask = gpRegMaskPPC64 248 c.fpRegMask = fpRegMaskPPC64 249 c.specialRegMask = specialRegMaskPPC64 250 c.intParamRegs = paramIntRegPPC64 251 c.floatParamRegs = paramFloatRegPPC64 252 c.FPReg = framepointerRegPPC64 253 c.LinkReg = linkRegPPC64 254 c.hasGReg = true 255 c.unalignedOK = true 256 // Note: ppc64 has register bswap ops only when GOPPC64>=10. 257 // But it has bswap+load and bswap+store ops for all ppc64 variants. 258 // That is the sense we're using them here - they are only used 259 // in contexts where they can be merged with a load or store. 260 c.haveBswap64 = true 261 c.haveBswap32 = true 262 c.haveBswap16 = true 263 case "mips64": 264 c.BigEndian = true 265 fallthrough 266 case "mips64le": 267 c.PtrSize = 8 268 c.RegSize = 8 269 c.lowerBlock = rewriteBlockMIPS64 270 c.lowerValue = rewriteValueMIPS64 271 c.registers = registersMIPS64[:] 272 c.gpRegMask = gpRegMaskMIPS64 273 c.fpRegMask = fpRegMaskMIPS64 274 c.specialRegMask = specialRegMaskMIPS64 275 c.FPReg = framepointerRegMIPS64 276 c.LinkReg = linkRegMIPS64 277 c.hasGReg = true 278 case "loong64": 279 c.PtrSize = 8 280 c.RegSize = 8 281 c.lowerBlock = rewriteBlockLOONG64 282 c.lowerValue = rewriteValueLOONG64 283 c.registers = registersLOONG64[:] 284 c.gpRegMask = gpRegMaskLOONG64 285 c.fpRegMask = fpRegMaskLOONG64 286 c.intParamRegs = paramIntRegLOONG64 287 c.floatParamRegs = paramFloatRegLOONG64 288 c.FPReg = framepointerRegLOONG64 289 c.LinkReg = linkRegLOONG64 290 c.hasGReg = true 291 case "s390x": 292 c.PtrSize = 8 293 c.RegSize = 8 294 c.lowerBlock = rewriteBlockS390X 295 c.lowerValue = rewriteValueS390X 296 c.registers = registersS390X[:] 297 c.gpRegMask = gpRegMaskS390X 298 c.fpRegMask = fpRegMaskS390X 299 c.FPReg = framepointerRegS390X 300 c.LinkReg = linkRegS390X 301 c.hasGReg = true 302 c.noDuffDevice = true 303 c.BigEndian = true 304 c.unalignedOK = true 305 c.haveBswap64 = true 306 c.haveBswap32 = true 307 c.haveBswap16 = true // only for loads&stores, see ppc64 comment 308 case "mips": 309 c.BigEndian = true 310 fallthrough 311 case "mipsle": 312 c.PtrSize = 4 313 c.RegSize = 4 314 c.lowerBlock = rewriteBlockMIPS 315 c.lowerValue = rewriteValueMIPS 316 c.registers = registersMIPS[:] 317 c.gpRegMask = gpRegMaskMIPS 318 c.fpRegMask = fpRegMaskMIPS 319 c.specialRegMask = specialRegMaskMIPS 320 c.FPReg = framepointerRegMIPS 321 c.LinkReg = linkRegMIPS 322 c.hasGReg = true 323 c.noDuffDevice = true 324 case "riscv64": 325 c.PtrSize = 8 326 c.RegSize = 8 327 c.lowerBlock = rewriteBlockRISCV64 328 c.lowerValue = rewriteValueRISCV64 329 c.lateLowerBlock = rewriteBlockRISCV64latelower 330 c.lateLowerValue = rewriteValueRISCV64latelower 331 c.registers = registersRISCV64[:] 332 c.gpRegMask = gpRegMaskRISCV64 333 c.fpRegMask = fpRegMaskRISCV64 334 c.intParamRegs = paramIntRegRISCV64 335 c.floatParamRegs = paramFloatRegRISCV64 336 c.FPReg = framepointerRegRISCV64 337 c.hasGReg = true 338 case "wasm": 339 c.PtrSize = 8 340 c.RegSize = 8 341 c.lowerBlock = rewriteBlockWasm 342 c.lowerValue = rewriteValueWasm 343 c.registers = registersWasm[:] 344 c.gpRegMask = gpRegMaskWasm 345 c.fpRegMask = fpRegMaskWasm 346 c.fp32RegMask = fp32RegMaskWasm 347 c.fp64RegMask = fp64RegMaskWasm 348 c.FPReg = framepointerRegWasm 349 c.LinkReg = linkRegWasm 350 c.hasGReg = true 351 c.noDuffDevice = true 352 c.useAvg = false 353 c.useHmul = false 354 default: 355 ctxt.Diag("arch %s not implemented", arch) 356 } 357 c.ctxt = ctxt 358 c.optimize = optimize 359 c.useSSE = true 360 c.UseFMA = true 361 c.SoftFloat = softfloat 362 if softfloat { 363 c.floatParamRegs = nil // no FP registers in softfloat mode 364 } 365 366 c.ABI0 = abi.NewABIConfig(0, 0, ctxt.Arch.FixedFrameSize, 0) 367 c.ABI1 = abi.NewABIConfig(len(c.intParamRegs), len(c.floatParamRegs), ctxt.Arch.FixedFrameSize, 1) 368 369 // On Plan 9, floating point operations are not allowed in note handler. 370 if buildcfg.GOOS == "plan9" { 371 // Don't use FMA on Plan 9 372 c.UseFMA = false 373 374 // Don't use Duff's device and SSE on Plan 9 AMD64. 375 if arch == "amd64" { 376 c.noDuffDevice = true 377 c.useSSE = false 378 } 379 } 380 381 if ctxt.Flag_shared { 382 // LoweredWB is secretly a CALL and CALLs on 386 in 383 // shared mode get rewritten by obj6.go to go through 384 // the GOT, which clobbers BX. 385 opcodeTable[Op386LoweredWB].reg.clobbers |= 1 << 3 // BX 386 } 387 388 // Create the GC register map index. 389 // TODO: This is only used for debug printing. Maybe export config.registers? 390 gcRegMapSize := int16(0) 391 for _, r := range c.registers { 392 if r.gcNum+1 > gcRegMapSize { 393 gcRegMapSize = r.gcNum + 1 394 } 395 } 396 c.GCRegMap = make([]*Register, gcRegMapSize) 397 for i, r := range c.registers { 398 if r.gcNum != -1 { 399 c.GCRegMap[r.gcNum] = &c.registers[i] 400 } 401 } 402 403 return c 404 } 405 406 func (c *Config) Ctxt() *obj.Link { return c.ctxt } 407 408 func (c *Config) haveByteSwap(size int64) bool { 409 switch size { 410 case 8: 411 return c.haveBswap64 412 case 4: 413 return c.haveBswap32 414 case 2: 415 return c.haveBswap16 416 default: 417 base.Fatalf("bad size %d\n", size) 418 return false 419 } 420 }