]> Cypherpunks.ru repositories - gostls13.git/blob - src/cmd/compile/internal/ssa/config.go
75fa71ce353db13df93e4f7a9094ea033eceae73
[gostls13.git] / src / cmd / compile / internal / ssa / config.go
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/abi"
9         "cmd/compile/internal/ir"
10         "cmd/compile/internal/types"
11         "cmd/internal/obj"
12         "cmd/internal/objabi"
13         "cmd/internal/src"
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  // 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
36         ABI0           *abi.ABIConfig
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
47         SoftFloat      bool        //
48         Race           bool        // race detector enabled
49         BigEndian      bool        //
50         UseFMA         bool        // Use hardware FMA operation
51 }
52
53 type (
54         blockRewriter func(*Block) bool
55         valueRewriter func(*Value) bool
56 )
57
58 type Types struct {
59         Bool       *types.Type
60         Int8       *types.Type
61         Int16      *types.Type
62         Int32      *types.Type
63         Int64      *types.Type
64         UInt8      *types.Type
65         UInt16     *types.Type
66         UInt32     *types.Type
67         UInt64     *types.Type
68         Int        *types.Type
69         Float32    *types.Type
70         Float64    *types.Type
71         UInt       *types.Type
72         Uintptr    *types.Type
73         String     *types.Type
74         BytePtr    *types.Type // TODO: use unsafe.Pointer instead?
75         Int32Ptr   *types.Type
76         UInt32Ptr  *types.Type
77         IntPtr     *types.Type
78         UintptrPtr *types.Type
79         Float32Ptr *types.Type
80         Float64Ptr *types.Type
81         BytePtrPtr *types.Type
82 }
83
84 // NewTypes creates and populates a Types.
85 func NewTypes() *Types {
86         t := new(Types)
87         t.SetTypPtrs()
88         return t
89 }
90
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]))
116 }
117
118 type Logger interface {
119         // Logf logs a message from the compiler.
120         Logf(string, ...interface{})
121
122         // Log reports whether logging is not a no-op
123         // some logging calls account for more than a few heap allocations.
124         Log() bool
125
126         // Fatal reports a compiler error and exits.
127         Fatalf(pos src.XPos, msg string, args ...interface{})
128
129         // Warnl writes compiler messages in the form expected by "errorcheck" tests
130         Warnl(pos src.XPos, fmt_ string, args ...interface{})
131
132         // Forwards the Debug flags from gc
133         Debug_checknil() bool
134 }
135
136 type Frontend interface {
137         CanSSA(t *types.Type) bool
138
139         Logger
140
141         // StringData returns a symbol pointing to the given string's contents.
142         StringData(string) *obj.LSym
143
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
147
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
158
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
164
165         // Line returns a string describing the given position.
166         Line(src.XPos) string
167
168         // AllocFrame assigns frame offsets to all live auto variables.
169         AllocFrame(f *Func)
170
171         // Syslook returns a symbol of the runtime function/variable with the
172         // given name.
173         Syslook(string) *obj.LSym
174
175         // UseWriteBarrier reports whether write barrier is enabled
176         UseWriteBarrier() bool
177
178         // SetWBPos indicates that a write barrier has been inserted
179         // in this function at position pos.
180         SetWBPos(pos src.XPos)
181
182         // MyImportPath provides the import name (roughly, the package) for the function being compiled.
183         MyImportPath() string
184 }
185
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}
189         c.useAvg = true
190         c.useHmul = true
191         switch arch {
192         case "amd64":
193                 c.PtrSize = 8
194                 c.RegSize = 8
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 = objabi.Experiment.RegabiG
207         case "386":
208                 c.PtrSize = 4
209                 c.RegSize = 4
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
218                 c.hasGReg = false
219         case "arm":
220                 c.PtrSize = 4
221                 c.RegSize = 4
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
229                 c.hasGReg = true
230         case "arm64":
231                 c.PtrSize = 8
232                 c.RegSize = 8
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
240                 c.hasGReg = true
241                 c.noDuffDevice = objabi.GOOS == "darwin" || objabi.GOOS == "ios" // darwin linker cannot handle BR26 reloc with non-zero addend
242         case "ppc64":
243                 c.BigEndian = true
244                 fallthrough
245         case "ppc64le":
246                 c.PtrSize = 8
247                 c.RegSize = 8
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)
256                 c.hasGReg = true
257         case "mips64":
258                 c.BigEndian = true
259                 fallthrough
260         case "mips64le":
261                 c.PtrSize = 8
262                 c.RegSize = 8
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
271                 c.hasGReg = true
272         case "s390x":
273                 c.PtrSize = 8
274                 c.RegSize = 8
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
282                 c.hasGReg = true
283                 c.noDuffDevice = true
284                 c.BigEndian = true
285         case "mips":
286                 c.BigEndian = true
287                 fallthrough
288         case "mipsle":
289                 c.PtrSize = 4
290                 c.RegSize = 4
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
299                 c.hasGReg = true
300                 c.noDuffDevice = true
301         case "riscv64":
302                 c.PtrSize = 8
303                 c.RegSize = 8
304                 c.lowerBlock = rewriteBlockRISCV64
305                 c.lowerValue = rewriteValueRISCV64
306                 c.registers = registersRISCV64[:]
307                 c.gpRegMask = gpRegMaskRISCV64
308                 c.fpRegMask = fpRegMaskRISCV64
309                 c.FPReg = framepointerRegRISCV64
310                 c.hasGReg = true
311         case "wasm":
312                 c.PtrSize = 8
313                 c.RegSize = 8
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
323                 c.hasGReg = true
324                 c.noDuffDevice = true
325                 c.useAvg = false
326                 c.useHmul = false
327         default:
328                 ctxt.Diag("arch %s not implemented", arch)
329         }
330         c.ctxt = ctxt
331         c.optimize = optimize
332         c.useSSE = true
333         c.UseFMA = true
334
335         c.ABI0 = abi.NewABIConfig(0, 0, ctxt.FixedFrameSize())
336         c.ABI1 = abi.NewABIConfig(len(c.intParamRegs), len(c.floatParamRegs), ctxt.FixedFrameSize())
337
338         // On Plan 9, floating point operations are not allowed in note handler.
339         if objabi.GOOS == "plan9" {
340                 // Don't use FMA on Plan 9
341                 c.UseFMA = false
342
343                 // Don't use Duff's device and SSE on Plan 9 AMD64.
344                 if arch == "amd64" {
345                         c.noDuffDevice = true
346                         c.useSSE = false
347                 }
348         }
349
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
355         }
356
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
363                 }
364         }
365         c.GCRegMap = make([]*Register, gcRegMapSize)
366         for i, r := range c.registers {
367                 if r.gcNum != -1 {
368                         c.GCRegMap[r.gcNum] = &c.registers[i]
369                 }
370         }
371
372         return c
373 }
374
375 func (c *Config) Ctxt() *obj.Link { return c.ctxt }