Line data Source code
1 : /* +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
2 : Copyright (c) 2008-2017, Petr Kobalicek
3 :
4 : This software is provided 'as-is', without any express or implied
5 : warranty. In no event will the authors be held liable for any damages
6 : arising from the use of this software.
7 :
8 : Permission is granted to anyone to use this software for any purpose,
9 : including commercial applications, and to alter it and redistribute it
10 : freely, subject to the following restrictions:
11 :
12 : 1. The origin of this software must not be misrepresented; you must not
13 : claim that you wrote the original software. If you use this software
14 : in a product, an acknowledgment in the product documentation would be
15 : appreciated but is not required.
16 : 2. Altered source versions must be plainly marked as such, and must not be
17 : misrepresented as being the original software.
18 : 3. This notice may not be removed or altered from any source distribution.
19 : +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ */
20 : #ifndef __PLUMED_asmjit_x86regalloc_p_h
21 : #define __PLUMED_asmjit_x86regalloc_p_h
22 : #ifdef __PLUMED_HAS_ASMJIT
23 : #pragma GCC diagnostic push
24 : #pragma GCC diagnostic ignored "-Wpedantic"
25 : // [AsmJit]
26 : // Complete x86/x64 JIT and Remote Assembler for C++.
27 : //
28 : // [License]
29 : // Zlib - See LICENSE.md file in the package.
30 :
31 : // [Guard]
32 : #ifndef _ASMJIT_X86_X86REGALLOC_P_H
33 : #define _ASMJIT_X86_X86REGALLOC_P_H
34 :
35 : #include "./asmjit_build.h"
36 : #if !defined(ASMJIT_DISABLE_COMPILER)
37 :
38 : // [Dependencies]
39 : #include "./codecompiler.h"
40 : #include "./regalloc_p.h"
41 : #include "./utils.h"
42 : #include "./x86assembler.h"
43 : #include "./x86compiler.h"
44 : #include "./x86misc.h"
45 :
46 : // [Api-Begin]
47 : #include "./asmjit_apibegin.h"
48 :
49 : namespace PLMD {
50 : namespace asmjit {
51 :
52 : //! \addtogroup asmjit_x86
53 : //! \{
54 :
55 : // ============================================================================
56 : // [asmjit::X86RAData]
57 : // ============================================================================
58 :
59 : struct X86RAData : public RAData {
60 81036 : ASMJIT_INLINE X86RAData(uint32_t tiedTotal) noexcept : RAData(tiedTotal) {
61 : inRegs.reset();
62 : outRegs.reset();
63 : clobberedRegs.reset();
64 : tiedIndex.reset();
65 : tiedCount.reset();
66 : }
67 :
68 : // --------------------------------------------------------------------------
69 : // [Accessors]
70 : // --------------------------------------------------------------------------
71 :
72 : //! Get TiedReg array.
73 : ASMJIT_INLINE TiedReg* getTiedArray() const noexcept {
74 36630 : return const_cast<TiedReg*>(tiedArray);
75 : }
76 :
77 : //! Get TiedReg array for a given register `kind`.
78 : ASMJIT_INLINE TiedReg* getTiedArrayByKind(uint32_t kind) const noexcept {
79 99048 : return const_cast<TiedReg*>(tiedArray) + tiedIndex.get(kind);
80 : }
81 :
82 : //! Get TiedReg index for a given register `kind`.
83 : ASMJIT_INLINE uint32_t getTiedStart(uint32_t kind) const noexcept {
84 : return tiedIndex.get(kind);
85 : }
86 :
87 : //! Get TiedReg count for a given register `kind`.
88 : ASMJIT_INLINE uint32_t getTiedCountByKind(uint32_t kind) const noexcept {
89 : return tiedCount.get(kind);
90 : }
91 :
92 : //! Get TiedReg at the specified `index`.
93 : ASMJIT_INLINE TiedReg* getTiedAt(uint32_t index) const noexcept {
94 : ASMJIT_ASSERT(index < tiedTotal);
95 : return getTiedArray() + index;
96 : }
97 :
98 : //! Get TiedReg at the specified index for a given register `kind`.
99 : ASMJIT_INLINE TiedReg* getTiedAtByKind(uint32_t kind, uint32_t index) const noexcept {
100 : ASMJIT_ASSERT(index < tiedCount._regs[kind]);
101 : return getTiedArrayByKind(kind) + index;
102 : }
103 :
104 : ASMJIT_INLINE void setTiedAt(uint32_t index, TiedReg& tied) noexcept {
105 : ASMJIT_ASSERT(index < tiedTotal);
106 61374 : tiedArray[index] = tied;
107 : }
108 :
109 : // --------------------------------------------------------------------------
110 : // [Utils]
111 : // --------------------------------------------------------------------------
112 :
113 : //! Find TiedReg.
114 : ASMJIT_INLINE TiedReg* findTied(VirtReg* vreg) const noexcept {
115 : TiedReg* tiedArray = getTiedArray();
116 : uint32_t tiedCount = tiedTotal;
117 :
118 : for (uint32_t i = 0; i < tiedCount; i++)
119 : if (tiedArray[i].vreg == vreg)
120 : return &tiedArray[i];
121 :
122 : return nullptr;
123 : }
124 :
125 : //! Find TiedReg (by class).
126 : ASMJIT_INLINE TiedReg* findTiedByKind(uint32_t kind, VirtReg* vreg) const noexcept {
127 : TiedReg* tiedArray = getTiedArrayByKind(kind);
128 : uint32_t tiedCount = getTiedCountByKind(kind);
129 :
130 209446 : for (uint32_t i = 0; i < tiedCount; i++)
131 140266 : if (tiedArray[i].vreg == vreg)
132 : return &tiedArray[i];
133 :
134 : return nullptr;
135 : }
136 :
137 : // --------------------------------------------------------------------------
138 : // [Members]
139 : // --------------------------------------------------------------------------
140 :
141 : //! Special registers on input.
142 : //!
143 : //! Special register(s) restricted to one or more physical register. If there
144 : //! is more than one special register it means that we have to duplicate the
145 : //! variable content to all of them (it means that the same variable was used
146 : //! by two or more operands). We forget about duplicates after the register
147 : //! allocation finishes and marks all duplicates as non-assigned.
148 : X86RegMask inRegs;
149 :
150 : //! Special registers on output.
151 : //!
152 : //! Special register(s) used on output. Each variable can have only one
153 : //! special register on the output, 'X86RAData' contains all registers from
154 : //! all 'TiedReg's.
155 : X86RegMask outRegs;
156 :
157 : //! Clobbered registers (by a function call).
158 : X86RegMask clobberedRegs;
159 :
160 : //! Start indexes of `TiedReg`s per register kind.
161 : X86RegCount tiedIndex;
162 : //! Count of variables per register kind.
163 : X86RegCount tiedCount;
164 :
165 : //! Linked registers.
166 : TiedReg tiedArray[1];
167 : };
168 :
169 : // ============================================================================
170 : // [asmjit::X86StateCell]
171 : // ============================================================================
172 :
173 : //! X86/X64 state-cell.
174 : union X86StateCell {
175 : // --------------------------------------------------------------------------
176 : // [Accessors]
177 : // --------------------------------------------------------------------------
178 :
179 0 : ASMJIT_INLINE uint32_t getState() const noexcept { return _state; }
180 0 : ASMJIT_INLINE void setState(uint32_t state) noexcept { _state = static_cast<uint8_t>(state); }
181 :
182 : // --------------------------------------------------------------------------
183 : // [Reset]
184 : // --------------------------------------------------------------------------
185 :
186 0 : ASMJIT_INLINE void reset() noexcept { _packed = 0; }
187 :
188 : // --------------------------------------------------------------------------
189 : // [Members]
190 : // --------------------------------------------------------------------------
191 :
192 : uint8_t _packed;
193 :
194 : struct {
195 : uint8_t _state : 2;
196 : uint8_t _unused : 6;
197 : };
198 : };
199 :
200 : // ============================================================================
201 : // [asmjit::X86RAState]
202 : // ============================================================================
203 :
204 : //! X86/X64 state.
205 : struct X86RAState : RAState {
206 : enum {
207 : //! Base index of GP registers.
208 : kGpIndex = 0,
209 : //! Count of GP registers.
210 : kGpCount = 16,
211 :
212 : //! Base index of MMX registers.
213 : kMmIndex = kGpIndex + kGpCount,
214 : //! Count of Mm registers.
215 : kMmCount = 8,
216 :
217 : //! Base index of XMM registers.
218 : kXmmIndex = kMmIndex + kMmCount,
219 : //! Count of XMM registers.
220 : kXmmCount = 16,
221 :
222 : //! Count of all registers in `X86RAState`.
223 : kAllCount = kXmmIndex + kXmmCount
224 : };
225 :
226 : // --------------------------------------------------------------------------
227 : // [Accessors]
228 : // --------------------------------------------------------------------------
229 :
230 : ASMJIT_INLINE VirtReg** getList() {
231 : return _list;
232 : }
233 :
234 : ASMJIT_INLINE VirtReg** getListByKind(uint32_t kind) {
235 : switch (kind) {
236 3272 : case X86Reg::kKindGp : return _listGp;
237 3272 : case X86Reg::kKindMm : return _listMm;
238 8896 : case X86Reg::kKindVec: return _listXmm;
239 :
240 : default:
241 : return nullptr;
242 : }
243 : }
244 :
245 : // --------------------------------------------------------------------------
246 : // [Clear]
247 : // --------------------------------------------------------------------------
248 :
249 : ASMJIT_INLINE void reset(size_t numCells) {
250 : ::memset(this, 0, kAllCount * sizeof(VirtReg*) +
251 : 2 * sizeof(X86RegMask) +
252 : numCells * sizeof(X86StateCell));
253 : }
254 :
255 : // --------------------------------------------------------------------------
256 : // [Members]
257 : // --------------------------------------------------------------------------
258 :
259 : union {
260 : //! List of all allocated variables in one array.
261 : VirtReg* _list[kAllCount];
262 :
263 : struct {
264 : //! Allocated GP registers.
265 : VirtReg* _listGp[kGpCount];
266 : //! Allocated MMX registers.
267 : VirtReg* _listMm[kMmCount];
268 : //! Allocated XMM registers.
269 : VirtReg* _listXmm[kXmmCount];
270 : };
271 : };
272 :
273 : //! Occupied registers (mask).
274 : X86RegMask _occupied;
275 : //! Modified registers (mask).
276 : X86RegMask _modified;
277 :
278 : //! Variables data, the length is stored in `X86RAPass`.
279 : X86StateCell _cells[1];
280 : };
281 :
282 : // ============================================================================
283 : // [asmjit::X86RAPass]
284 : // ============================================================================
285 :
286 : #if defined(ASMJIT_DEBUG)
287 : # define ASMJIT_X86_CHECK_STATE _checkState();
288 : #else
289 : # define ASMJIT_X86_CHECK_STATE
290 : #endif // ASMJIT_DEBUG
291 :
292 : //! \internal
293 : //!
294 : //! X86 register allocator pipeline.
295 : //!
296 : //! Takes care of generating function prologs and epilogs, and also performs
297 : //! register allocation.
298 : class X86RAPass : public RAPass {
299 : public:
300 : ASMJIT_NONCOPYABLE(X86RAPass)
301 : typedef RAPass Base;
302 :
303 : enum RegOp {
304 : kRegOpMove,
305 : kRegOpLoad,
306 : kRegOpSave
307 : };
308 :
309 : // --------------------------------------------------------------------------
310 : // [Construction / Destruction]
311 : // --------------------------------------------------------------------------
312 :
313 : X86RAPass() noexcept;
314 : virtual ~X86RAPass() noexcept;
315 :
316 : // --------------------------------------------------------------------------
317 : // [Interface]
318 : // --------------------------------------------------------------------------
319 :
320 : virtual Error process(Zone* zone) noexcept override;
321 : virtual Error prepare(CCFunc* func) noexcept override;
322 :
323 : // --------------------------------------------------------------------------
324 : // [ArchInfo]
325 : // --------------------------------------------------------------------------
326 :
327 : ASMJIT_INLINE uint32_t getGpSize() const noexcept { return _zsp.getSize(); }
328 :
329 : // --------------------------------------------------------------------------
330 : // [Accessors]
331 : // --------------------------------------------------------------------------
332 :
333 : //! Get compiler as `X86Compiler`.
334 119408 : ASMJIT_INLINE X86Compiler* cc() const noexcept { return static_cast<X86Compiler*>(_cb); }
335 : //! Get clobbered registers (global).
336 : ASMJIT_INLINE uint32_t getClobberedRegs(uint32_t kind) noexcept { return _clobberedRegs.get(kind); }
337 :
338 : // --------------------------------------------------------------------------
339 : // [Helpers]
340 : // --------------------------------------------------------------------------
341 :
342 : ASMJIT_INLINE X86RAData* newRAData(uint32_t tiedTotal) noexcept {
343 40518 : return new(_zone->alloc(sizeof(X86RAData) + tiedTotal * sizeof(TiedReg))) X86RAData(tiedTotal);
344 : }
345 :
346 : // --------------------------------------------------------------------------
347 : // [Emit]
348 : // --------------------------------------------------------------------------
349 :
350 : // Tiny wrappers that call `X86Internal::emit...()`.
351 : Error emitMove(VirtReg* vreg, uint32_t dstId, uint32_t srcId, const char* reason);
352 : Error emitLoad(VirtReg* vreg, uint32_t id, const char* reason);
353 : Error emitSave(VirtReg* vreg, uint32_t id, const char* reason);
354 : Error emitSwapGp(VirtReg* aVReg, VirtReg* bVReg, uint32_t aId, uint32_t bId, const char* reason) noexcept;
355 :
356 : Error emitImmToReg(uint32_t dstTypeId, uint32_t dstPhysId, const Imm* src) noexcept;
357 : Error emitImmToStack(uint32_t dstTypeId, const X86Mem* dst, const Imm* src) noexcept;
358 : Error emitRegToStack(uint32_t dstTypeId, const X86Mem* dst, uint32_t srcTypeId, uint32_t srcPhysId) noexcept;
359 :
360 : // --------------------------------------------------------------------------
361 : // [Register Management]
362 : // --------------------------------------------------------------------------
363 :
364 : void _checkState();
365 :
366 : // --------------------------------------------------------------------------
367 : // [Attach / Detach]
368 : // --------------------------------------------------------------------------
369 :
370 : //! Attach.
371 : //!
372 : //! Attach a register to the 'VirtReg', changing 'VirtReg' members to show
373 : //! that the variable is currently alive and linking variable with the
374 : //! current 'X86RAState'.
375 : template<int C>
376 : ASMJIT_INLINE void attach(VirtReg* vreg, uint32_t physId, bool modified) {
377 : ASMJIT_ASSERT(vreg->getKind() == C);
378 : ASMJIT_ASSERT(physId != Globals::kInvalidRegId);
379 :
380 : // Prevent Esp allocation if C==Gp.
381 : ASMJIT_ASSERT(C != X86Reg::kKindGp || physId != X86Gp::kIdSp);
382 :
383 : uint32_t regMask = Utils::mask(physId);
384 :
385 : vreg->setState(VirtReg::kStateReg);
386 : vreg->setModified(modified);
387 : vreg->setPhysId(physId);
388 : vreg->addHomeId(physId);
389 :
390 23740 : _x86State.getListByKind(C)[physId] = vreg;
391 : _x86State._occupied.or_(C, regMask);
392 : _x86State._modified.or_(C, static_cast<uint32_t>(modified) << physId);
393 :
394 : ASMJIT_X86_CHECK_STATE
395 23740 : }
396 :
397 : //! Detach.
398 : //!
399 : //! The opposite of 'Attach'. Detach resets the members in 'VirtReg'
400 : //! (physId, state and changed flags) and unlinks the variable with the
401 : //! current 'X86RAState'.
402 : template<int C>
403 : ASMJIT_INLINE void detach(VirtReg* vreg, uint32_t physId, uint32_t vState) {
404 : ASMJIT_ASSERT(vreg->getKind() == C);
405 : ASMJIT_ASSERT(vreg->getPhysId() == physId);
406 : ASMJIT_ASSERT(vState != VirtReg::kStateReg);
407 :
408 : uint32_t regMask = Utils::mask(physId);
409 :
410 : vreg->setState(vState);
411 : vreg->resetPhysId();
412 : vreg->setModified(false);
413 :
414 26220 : _x86State.getListByKind(C)[physId] = nullptr;
415 : _x86State._occupied.andNot(C, regMask);
416 : _x86State._modified.andNot(C, regMask);
417 :
418 : ASMJIT_X86_CHECK_STATE
419 26220 : }
420 :
421 : // --------------------------------------------------------------------------
422 : // [Rebase]
423 : // --------------------------------------------------------------------------
424 :
425 : //! Rebase.
426 : //!
427 : //! Change the register of the 'VirtReg' changing also the current 'X86RAState'.
428 : //! Rebase is nearly identical to 'Detach' and 'Attach' sequence, but doesn't
429 : //! change the `VirtReg`s modified flag.
430 : template<int C>
431 : ASMJIT_INLINE void rebase(VirtReg* vreg, uint32_t newPhysId, uint32_t oldPhysId) {
432 : ASMJIT_ASSERT(vreg->getKind() == C);
433 :
434 : uint32_t newRegMask = Utils::mask(newPhysId);
435 : uint32_t oldRegMask = Utils::mask(oldPhysId);
436 656 : uint32_t bothRegMask = newRegMask ^ oldRegMask;
437 :
438 : vreg->setPhysId(newPhysId);
439 :
440 656 : _x86State.getListByKind(C)[oldPhysId] = nullptr;
441 656 : _x86State.getListByKind(C)[newPhysId] = vreg;
442 :
443 : _x86State._occupied.xor_(C, bothRegMask);
444 656 : _x86State._modified.xor_(C, bothRegMask & -static_cast<int32_t>(vreg->isModified()));
445 :
446 : ASMJIT_X86_CHECK_STATE
447 656 : }
448 :
449 : // --------------------------------------------------------------------------
450 : // [Load / Save]
451 : // --------------------------------------------------------------------------
452 :
453 : //! Load.
454 : //!
455 : //! Load variable from its memory slot to a register, emitting 'Load'
456 : //! instruction and changing the variable state to allocated.
457 : template<int C>
458 : ASMJIT_INLINE void load(VirtReg* vreg, uint32_t physId) {
459 : // Can be only called if variable is not allocated.
460 : ASMJIT_ASSERT(vreg->getKind() == C);
461 : ASMJIT_ASSERT(vreg->getState() != VirtReg::kStateReg);
462 : ASMJIT_ASSERT(vreg->getPhysId() == Globals::kInvalidRegId);
463 :
464 0 : emitLoad(vreg, physId, "Load");
465 : attach<C>(vreg, physId, false);
466 :
467 : ASMJIT_X86_CHECK_STATE
468 0 : }
469 :
470 : //! Save.
471 : //!
472 : //! Save the variable into its home location, but keep it as allocated.
473 : template<int C>
474 : ASMJIT_INLINE void save(VirtReg* vreg) {
475 : ASMJIT_ASSERT(vreg->getKind() == C);
476 : ASMJIT_ASSERT(vreg->getState() == VirtReg::kStateReg);
477 : ASMJIT_ASSERT(vreg->getPhysId() != Globals::kInvalidRegId);
478 :
479 : uint32_t physId = vreg->getPhysId();
480 : uint32_t regMask = Utils::mask(physId);
481 :
482 3468 : emitSave(vreg, physId, "Save");
483 : vreg->setModified(false);
484 : _x86State._modified.andNot(C, regMask);
485 :
486 : ASMJIT_X86_CHECK_STATE
487 3468 : }
488 :
489 : // --------------------------------------------------------------------------
490 : // [Move / Swap]
491 : // --------------------------------------------------------------------------
492 :
493 : //! Move a register.
494 : //!
495 : //! Move register from one index to another, emitting 'Move' if needed. This
496 : //! function does nothing if register is already at the given index.
497 : template<int C>
498 : ASMJIT_INLINE void move(VirtReg* vreg, uint32_t newPhysId) {
499 : ASMJIT_ASSERT(vreg->getKind() == C);
500 : ASMJIT_ASSERT(vreg->getState() == VirtReg::kStateReg);
501 : ASMJIT_ASSERT(vreg->getPhysId() != Globals::kInvalidRegId);
502 :
503 : uint32_t oldPhysId = vreg->getPhysId();
504 656 : if (newPhysId != oldPhysId) {
505 656 : emitMove(vreg, newPhysId, oldPhysId, "Move");
506 : rebase<C>(vreg, newPhysId, oldPhysId);
507 : }
508 :
509 : ASMJIT_X86_CHECK_STATE
510 : }
511 :
512 : //! Swap two registers
513 : //!
514 : //! It's only possible to swap Gp registers.
515 : ASMJIT_INLINE void swapGp(VirtReg* aVReg, VirtReg* bVReg) {
516 : ASMJIT_ASSERT(aVReg != bVReg);
517 :
518 : ASMJIT_ASSERT(aVReg->getKind() == X86Reg::kKindGp);
519 : ASMJIT_ASSERT(aVReg->getState() == VirtReg::kStateReg);
520 : ASMJIT_ASSERT(aVReg->getPhysId() != Globals::kInvalidRegId);
521 :
522 : ASMJIT_ASSERT(bVReg->getKind() == X86Reg::kKindGp);
523 : ASMJIT_ASSERT(bVReg->getState() == VirtReg::kStateReg);
524 : ASMJIT_ASSERT(bVReg->getPhysId() != Globals::kInvalidRegId);
525 :
526 : uint32_t aIndex = aVReg->getPhysId();
527 : uint32_t bIndex = bVReg->getPhysId();
528 :
529 0 : emitSwapGp(aVReg, bVReg, aIndex, bIndex, "Swap");
530 :
531 : aVReg->setPhysId(bIndex);
532 : bVReg->setPhysId(aIndex);
533 :
534 0 : _x86State.getListByKind(X86Reg::kKindGp)[aIndex] = bVReg;
535 0 : _x86State.getListByKind(X86Reg::kKindGp)[bIndex] = aVReg;
536 :
537 0 : uint32_t m = aVReg->isModified() ^ bVReg->isModified();
538 0 : _x86State._modified.xor_(X86Reg::kKindGp, (m << aIndex) | (m << bIndex));
539 :
540 : ASMJIT_X86_CHECK_STATE
541 : }
542 :
543 : // --------------------------------------------------------------------------
544 : // [Alloc / Spill]
545 : // --------------------------------------------------------------------------
546 :
547 : //! Alloc.
548 : template<int C>
549 : ASMJIT_INLINE void alloc(VirtReg* vreg, uint32_t physId) {
550 : ASMJIT_ASSERT(vreg->getKind() == C);
551 : ASMJIT_ASSERT(physId != Globals::kInvalidRegId);
552 :
553 : uint32_t oldPhysId = vreg->getPhysId();
554 : uint32_t oldState = vreg->getState();
555 : uint32_t regMask = Utils::mask(physId);
556 :
557 : ASMJIT_ASSERT(_x86State.getListByKind(C)[physId] == nullptr || physId == oldPhysId);
558 :
559 4424 : if (oldState != VirtReg::kStateReg) {
560 4424 : if (oldState == VirtReg::kStateMem)
561 4424 : emitLoad(vreg, physId, "Alloc");
562 : vreg->setModified(false);
563 : }
564 0 : else if (oldPhysId != physId) {
565 0 : emitMove(vreg, physId, oldPhysId, "Alloc");
566 :
567 0 : _x86State.getListByKind(C)[oldPhysId] = nullptr;
568 0 : regMask ^= Utils::mask(oldPhysId);
569 : }
570 : else {
571 : ASMJIT_X86_CHECK_STATE
572 : return;
573 : }
574 :
575 : vreg->setState(VirtReg::kStateReg);
576 : vreg->setPhysId(physId);
577 : vreg->addHomeId(physId);
578 :
579 4424 : _x86State.getListByKind(C)[physId] = vreg;
580 : _x86State._occupied.xor_(C, regMask);
581 4424 : _x86State._modified.xor_(C, regMask & -static_cast<int32_t>(vreg->isModified()));
582 :
583 : ASMJIT_X86_CHECK_STATE
584 : }
585 :
586 : //! Spill.
587 : //!
588 : //! Spill variable/register, saves the content to the memory-home if modified.
589 : template<int C>
590 : ASMJIT_INLINE void spill(VirtReg* vreg) {
591 : ASMJIT_ASSERT(vreg->getKind() == C);
592 :
593 548 : if (vreg->getState() != VirtReg::kStateReg) {
594 : ASMJIT_X86_CHECK_STATE
595 : return;
596 : }
597 :
598 : uint32_t physId = vreg->getPhysId();
599 : ASMJIT_ASSERT(physId != Globals::kInvalidRegId);
600 : ASMJIT_ASSERT(_x86State.getListByKind(C)[physId] == vreg);
601 :
602 548 : if (vreg->isModified())
603 536 : emitSave(vreg, physId, "Spill");
604 : detach<C>(vreg, physId, VirtReg::kStateMem);
605 :
606 : ASMJIT_X86_CHECK_STATE
607 : }
608 :
609 : // --------------------------------------------------------------------------
610 : // [Modify]
611 : // --------------------------------------------------------------------------
612 :
613 : template<int C>
614 : ASMJIT_INLINE void modify(VirtReg* vreg) {
615 : ASMJIT_ASSERT(vreg->getKind() == C);
616 :
617 : uint32_t physId = vreg->getPhysId();
618 : uint32_t regMask = Utils::mask(physId);
619 :
620 : vreg->setModified(true);
621 : _x86State._modified.or_(C, regMask);
622 :
623 : ASMJIT_X86_CHECK_STATE
624 : }
625 :
626 : // --------------------------------------------------------------------------
627 : // [Unuse]
628 : // --------------------------------------------------------------------------
629 :
630 : //! Unuse.
631 : //!
632 : //! Unuse variable, it will be detached it if it's allocated then its state
633 : //! will be changed to VirtReg::kStateNone.
634 : template<int C>
635 : ASMJIT_INLINE void unuse(VirtReg* vreg, uint32_t vState = VirtReg::kStateNone) {
636 : ASMJIT_ASSERT(vreg->getKind() == C);
637 : ASMJIT_ASSERT(vState != VirtReg::kStateReg);
638 :
639 : uint32_t physId = vreg->getPhysId();
640 50366 : if (physId != Globals::kInvalidRegId)
641 : detach<C>(vreg, physId, vState);
642 : else
643 : vreg->setState(vState);
644 :
645 : ASMJIT_X86_CHECK_STATE
646 : }
647 :
648 : // --------------------------------------------------------------------------
649 : // [State]
650 : // --------------------------------------------------------------------------
651 :
652 : //! Get state as `X86RAState`.
653 0 : ASMJIT_INLINE X86RAState* getState() const { return const_cast<X86RAState*>(&_x86State); }
654 :
655 : virtual void loadState(RAState* src) override;
656 : virtual RAState* saveState() override;
657 :
658 : virtual void switchState(RAState* src) override;
659 : virtual void intersectStates(RAState* a, RAState* b) override;
660 :
661 : // --------------------------------------------------------------------------
662 : // [Memory]
663 : // --------------------------------------------------------------------------
664 :
665 : ASMJIT_INLINE X86Mem getVarMem(VirtReg* vreg) {
666 8428 : (void)getVarCell(vreg);
667 : return X86Mem(Init,
668 : cc()->_nativeGpReg.getType(), vreg->getId(),
669 : Reg::kRegNone, kInvalidValue,
670 : 0, 0, Mem::kSignatureMemRegHomeFlag);
671 : }
672 :
673 : // --------------------------------------------------------------------------
674 : // [Fetch]
675 : // --------------------------------------------------------------------------
676 :
677 : virtual Error fetch() override;
678 :
679 : // --------------------------------------------------------------------------
680 : // [Annotate]
681 : // --------------------------------------------------------------------------
682 :
683 : virtual Error annotate() override;
684 :
685 : // --------------------------------------------------------------------------
686 : // [Translate]
687 : // --------------------------------------------------------------------------
688 :
689 : virtual Error translate() override;
690 :
691 : // --------------------------------------------------------------------------
692 : // [Members]
693 : // --------------------------------------------------------------------------
694 :
695 : //! Count of X86/X64 registers.
696 : X86RegCount _regCount;
697 : //! X86/X64 stack-pointer (esp or rsp).
698 : X86Gp _zsp;
699 : //! X86/X64 frame-pointer (ebp or rbp).
700 : X86Gp _zbp;
701 :
702 : //! X86/X64 specific compiler state, linked to `_state`.
703 : X86RAState _x86State;
704 : //! Clobbered registers (for the whole function).
705 : X86RegMask _clobberedRegs;
706 :
707 : //! Global allocable registers mask.
708 : uint32_t _gaRegs[Globals::kMaxVRegKinds];
709 :
710 : bool _avxEnabled;
711 :
712 : //! Function variables base pointer (register).
713 : uint8_t _varBaseRegId;
714 : //! Function variables base offset.
715 : int32_t _varBaseOffset;
716 :
717 : //! Temporary string builder used for logging.
718 : StringBuilderTmp<256> _stringBuilder;
719 : };
720 :
721 : //! \}
722 :
723 : } // asmjit namespace
724 : } // namespace PLMD
725 :
726 : // [Api-End]
727 : #include "./asmjit_apiend.h"
728 :
729 : // [Guard]
730 : #endif // !ASMJIT_DISABLE_COMPILER
731 : #endif // _ASMJIT_X86_X86REGALLOC_P_H
732 : #pragma GCC diagnostic pop
733 : #endif // __PLUMED_HAS_ASMJIT
734 : #endif
|