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.
8 "cmd/compile/internal/abi"
9 "cmd/compile/internal/ir"
10 "cmd/compile/internal/types"
16 // A Config holds readonly compilation information.
17 // It is created once, early during compilation,
18 // and shared across all compilations.
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
24 lowerBlock blockRewriter // lowering function
25 lowerValue valueRewriter // lowering function
26 splitLoad valueRewriter // function for splitting merged load ops; only used on some architectures
27 registers []Register // machine registers
28 gpRegMask regMask // general purpose integer register mask
29 fpRegMask regMask // floating point register mask
30 fp32RegMask regMask // floating point register mask
31 fp64RegMask regMask // floating point register mask
32 specialRegMask regMask // special register mask
33 intParamRegs []int8 // register numbers of integer param (in/out) registers
34 floatParamRegs []int8 // register numbers of floating param (in/out) registers
35 ABI1 *abi.ABIConfig // "ABIInternal" under development // TODO change comment when this becomes current
37 GCRegMap []*Register // garbage collector register map, by GC register index
38 FPReg int8 // register number of frame pointer, -1 if not used
39 LinkReg int8 // register number of link register if it is a general purpose register, -1 if not used
40 hasGReg bool // has hardware g register
41 ctxt *obj.Link // Generic arch information
42 optimize bool // Do optimization
43 noDuffDevice bool // Don't use Duff's device
44 useSSE bool // Use SSE for non-float operations
45 useAvg bool // Use optimizations that need Avg* operations
46 useHmul bool // Use optimizations that need Hmul* operations
48 Race bool // race detector enabled
50 UseFMA bool // Use hardware FMA operation
54 blockRewriter func(*Block) bool
55 valueRewriter func(*Value) bool
74 BytePtr *types.Type // TODO: use unsafe.Pointer instead?
78 UintptrPtr *types.Type
79 Float32Ptr *types.Type
80 Float64Ptr *types.Type
81 BytePtrPtr *types.Type
84 // NewTypes creates and populates a Types.
85 func NewTypes() *Types {
91 // SetTypPtrs populates t.
92 func (t *Types) SetTypPtrs() {
93 t.Bool = types.Types[types.TBOOL]
94 t.Int8 = types.Types[types.TINT8]
95 t.Int16 = types.Types[types.TINT16]
96 t.Int32 = types.Types[types.TINT32]
97 t.Int64 = types.Types[types.TINT64]
98 t.UInt8 = types.Types[types.TUINT8]
99 t.UInt16 = types.Types[types.TUINT16]
100 t.UInt32 = types.Types[types.TUINT32]
101 t.UInt64 = types.Types[types.TUINT64]
102 t.Int = types.Types[types.TINT]
103 t.Float32 = types.Types[types.TFLOAT32]
104 t.Float64 = types.Types[types.TFLOAT64]
105 t.UInt = types.Types[types.TUINT]
106 t.Uintptr = types.Types[types.TUINTPTR]
107 t.String = types.Types[types.TSTRING]
108 t.BytePtr = types.NewPtr(types.Types[types.TUINT8])
109 t.Int32Ptr = types.NewPtr(types.Types[types.TINT32])
110 t.UInt32Ptr = types.NewPtr(types.Types[types.TUINT32])
111 t.IntPtr = types.NewPtr(types.Types[types.TINT])
112 t.UintptrPtr = types.NewPtr(types.Types[types.TUINTPTR])
113 t.Float32Ptr = types.NewPtr(types.Types[types.TFLOAT32])
114 t.Float64Ptr = types.NewPtr(types.Types[types.TFLOAT64])
115 t.BytePtrPtr = types.NewPtr(types.NewPtr(types.Types[types.TUINT8]))
118 type Logger interface {
119 // Logf logs a message from the compiler.
120 Logf(string, ...interface{})
122 // Log reports whether logging is not a no-op
123 // some logging calls account for more than a few heap allocations.
126 // Fatal reports a compiler error and exits.
127 Fatalf(pos src.XPos, msg string, args ...interface{})
129 // Warnl writes compiler messages in the form expected by "errorcheck" tests
130 Warnl(pos src.XPos, fmt_ string, args ...interface{})
132 // Forwards the Debug flags from gc
133 Debug_checknil() bool
136 type Frontend interface {
137 CanSSA(t *types.Type) bool
141 // StringData returns a symbol pointing to the given string's contents.
142 StringData(string) *obj.LSym
144 // Auto returns a Node for an auto variable of the given type.
145 // The SSA compiler uses this function to allocate space for spills.
146 Auto(src.XPos, *types.Type) *ir.Name
148 // Given the name for a compound type, returns the name we should use
149 // for the parts of that compound type.
150 SplitString(LocalSlot) (LocalSlot, LocalSlot)
151 SplitInterface(LocalSlot) (LocalSlot, LocalSlot)
152 SplitSlice(LocalSlot) (LocalSlot, LocalSlot, LocalSlot)
153 SplitComplex(LocalSlot) (LocalSlot, LocalSlot)
154 SplitStruct(LocalSlot, int) LocalSlot
155 SplitArray(LocalSlot) LocalSlot // array must be length 1
156 SplitInt64(LocalSlot) (LocalSlot, LocalSlot) // returns (hi, lo)
157 SplitSlot(parent *LocalSlot, suffix string, offset int64, t *types.Type) LocalSlot
159 // DerefItab dereferences an itab function
160 // entry, given the symbol of the itab and
161 // the byte offset of the function pointer.
162 // It may return nil.
163 DerefItab(sym *obj.LSym, offset int64) *obj.LSym
165 // Line returns a string describing the given position.
166 Line(src.XPos) string
168 // AllocFrame assigns frame offsets to all live auto variables.
171 // Syslook returns a symbol of the runtime function/variable with the
173 Syslook(string) *obj.LSym
175 // UseWriteBarrier reports whether write barrier is enabled
176 UseWriteBarrier() bool
178 // SetWBPos indicates that a write barrier has been inserted
179 // in this function at position pos.
180 SetWBPos(pos src.XPos)
182 // MyImportPath provides the import name (roughly, the package) for the function being compiled.
183 MyImportPath() string
186 // NewConfig returns a new configuration object for the given architecture.
187 func NewConfig(arch string, types Types, ctxt *obj.Link, optimize bool) *Config {
188 c := &Config{arch: arch, Types: types}
195 c.lowerBlock = rewriteBlockAMD64
196 c.lowerValue = rewriteValueAMD64
197 c.splitLoad = rewriteValueAMD64splitload
198 c.registers = registersAMD64[:]
199 c.gpRegMask = gpRegMaskAMD64
200 c.fpRegMask = fpRegMaskAMD64
201 c.specialRegMask = specialRegMaskAMD64
202 c.intParamRegs = paramIntRegAMD64
203 c.floatParamRegs = paramFloatRegAMD64
204 c.FPReg = framepointerRegAMD64
205 c.LinkReg = linkRegAMD64
206 c.hasGReg = buildcfg.Experiment.RegabiG
210 c.lowerBlock = rewriteBlock386
211 c.lowerValue = rewriteValue386
212 c.splitLoad = rewriteValue386splitload
213 c.registers = registers386[:]
214 c.gpRegMask = gpRegMask386
215 c.fpRegMask = fpRegMask386
216 c.FPReg = framepointerReg386
217 c.LinkReg = linkReg386
222 c.lowerBlock = rewriteBlockARM
223 c.lowerValue = rewriteValueARM
224 c.registers = registersARM[:]
225 c.gpRegMask = gpRegMaskARM
226 c.fpRegMask = fpRegMaskARM
227 c.FPReg = framepointerRegARM
228 c.LinkReg = linkRegARM
233 c.lowerBlock = rewriteBlockARM64
234 c.lowerValue = rewriteValueARM64
235 c.registers = registersARM64[:]
236 c.gpRegMask = gpRegMaskARM64
237 c.fpRegMask = fpRegMaskARM64
238 c.FPReg = framepointerRegARM64
239 c.LinkReg = linkRegARM64
241 c.noDuffDevice = buildcfg.GOOS == "darwin" || buildcfg.GOOS == "ios" // darwin linker cannot handle BR26 reloc with non-zero addend
248 c.lowerBlock = rewriteBlockPPC64
249 c.lowerValue = rewriteValuePPC64
250 c.registers = registersPPC64[:]
251 c.gpRegMask = gpRegMaskPPC64
252 c.fpRegMask = fpRegMaskPPC64
253 c.FPReg = framepointerRegPPC64
254 c.LinkReg = linkRegPPC64
255 c.noDuffDevice = true // TODO: Resolve PPC64 DuffDevice (has zero, but not copy)
263 c.lowerBlock = rewriteBlockMIPS64
264 c.lowerValue = rewriteValueMIPS64
265 c.registers = registersMIPS64[:]
266 c.gpRegMask = gpRegMaskMIPS64
267 c.fpRegMask = fpRegMaskMIPS64
268 c.specialRegMask = specialRegMaskMIPS64
269 c.FPReg = framepointerRegMIPS64
270 c.LinkReg = linkRegMIPS64
275 c.lowerBlock = rewriteBlockS390X
276 c.lowerValue = rewriteValueS390X
277 c.registers = registersS390X[:]
278 c.gpRegMask = gpRegMaskS390X
279 c.fpRegMask = fpRegMaskS390X
280 c.FPReg = framepointerRegS390X
281 c.LinkReg = linkRegS390X
283 c.noDuffDevice = true
291 c.lowerBlock = rewriteBlockMIPS
292 c.lowerValue = rewriteValueMIPS
293 c.registers = registersMIPS[:]
294 c.gpRegMask = gpRegMaskMIPS
295 c.fpRegMask = fpRegMaskMIPS
296 c.specialRegMask = specialRegMaskMIPS
297 c.FPReg = framepointerRegMIPS
298 c.LinkReg = linkRegMIPS
300 c.noDuffDevice = true
304 c.lowerBlock = rewriteBlockRISCV64
305 c.lowerValue = rewriteValueRISCV64
306 c.registers = registersRISCV64[:]
307 c.gpRegMask = gpRegMaskRISCV64
308 c.fpRegMask = fpRegMaskRISCV64
309 c.FPReg = framepointerRegRISCV64
314 c.lowerBlock = rewriteBlockWasm
315 c.lowerValue = rewriteValueWasm
316 c.registers = registersWasm[:]
317 c.gpRegMask = gpRegMaskWasm
318 c.fpRegMask = fpRegMaskWasm
319 c.fp32RegMask = fp32RegMaskWasm
320 c.fp64RegMask = fp64RegMaskWasm
321 c.FPReg = framepointerRegWasm
322 c.LinkReg = linkRegWasm
324 c.noDuffDevice = true
328 ctxt.Diag("arch %s not implemented", arch)
331 c.optimize = optimize
335 c.ABI0 = abi.NewABIConfig(0, 0, ctxt.FixedFrameSize())
336 c.ABI1 = abi.NewABIConfig(len(c.intParamRegs), len(c.floatParamRegs), ctxt.FixedFrameSize())
338 // On Plan 9, floating point operations are not allowed in note handler.
339 if buildcfg.GOOS == "plan9" {
340 // Don't use FMA on Plan 9
343 // Don't use Duff's device and SSE on Plan 9 AMD64.
345 c.noDuffDevice = true
350 if ctxt.Flag_shared {
351 // LoweredWB is secretly a CALL and CALLs on 386 in
352 // shared mode get rewritten by obj6.go to go through
353 // the GOT, which clobbers BX.
354 opcodeTable[Op386LoweredWB].reg.clobbers |= 1 << 3 // BX
357 // Create the GC register map index.
358 // TODO: This is only used for debug printing. Maybe export config.registers?
359 gcRegMapSize := int16(0)
360 for _, r := range c.registers {
361 if r.gcNum+1 > gcRegMapSize {
362 gcRegMapSize = r.gcNum + 1
365 c.GCRegMap = make([]*Register, gcRegMapSize)
366 for i, r := range c.registers {
368 c.GCRegMap[r.gcNum] = &c.registers[i]
375 func (c *Config) Ctxt() *obj.Link { return c.ctxt }