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