1 // [AsmJit]
2 // Complete JIT Assembler for C++ Language.
3 //
4 // [License]
5 // Zlib - See COPYING file in this package.
6 
7 #define ASMJIT_EXPORTS
8 
9 // [Dependencies - AsmJit]
10 #include "../core/intutil.h"
11 #include "../core/stringutil.h"
12 
13 #include "../x86/x86assembler.h"
14 #include "../x86/x86compiler.h"
15 #include "../x86/x86compilercontext.h"
16 #include "../x86/x86compilerfunc.h"
17 #include "../x86/x86compileritem.h"
18 #include "../x86/x86util.h"
19 
20 // [Api-Begin]
21 #include "../core/apibegin.h"
22 
23 namespace AsmJit {
24 
25 // ============================================================================
26 // [AsmJit::CompilerContext - Construction / Destruction]
27 // ============================================================================
28 
X86CompilerContext(X86Compiler * x86Compiler)29 X86CompilerContext::X86CompilerContext(X86Compiler* x86Compiler) :
30   CompilerContext(x86Compiler)
31 {
32   _state = &_x86State;
33 
34   _clear();
35   _emitComments = x86Compiler->getLogger() != NULL;
36 }
37 
~X86CompilerContext()38 X86CompilerContext::~X86CompilerContext()
39 {
40 }
41 
42 // ============================================================================
43 // [AsmJit::CompilerContext - Clear]
44 // ============================================================================
45 
_clear()46 void X86CompilerContext::_clear()
47 {
48   _zoneMemory.clear();
49   _func = NULL;
50 
51   _start = NULL;
52   _stop = NULL;
53 
54   _x86State.clear();
55   _active = NULL;
56 
57   _forwardJumps = NULL;
58 
59   _currentOffset = 0;
60   _isUnreachable = 0;
61 
62   _modifiedGpRegisters = 0;
63   _modifiedMmRegisters = 0;
64   _modifiedXmmRegisters = 0;
65 
66   _allocableEBP = false;
67 
68   _adjustESP = 0;
69 
70   _argumentsBaseReg = kRegIndexInvalid; // Used by patcher.
71   _argumentsBaseOffset = 0;             // Used by patcher.
72   _argumentsActualDisp = 0;             // Used by translate().
73 
74   _variablesBaseReg = kRegIndexInvalid; // Used by patcher.
75   _variablesBaseOffset = 0;             // Used by patcher.
76   _variablesActualDisp = 0;             // Used by translate()
77 
78   _memUsed = NULL;
79   _memFree = NULL;
80 
81   _mem4BlocksCount = 0;
82   _mem8BlocksCount = 0;
83   _mem16BlocksCount = 0;
84 
85   _memBytesTotal = 0;
86 
87   _backCode.clear();
88   _backPos = 0;
89 }
90 
91 // ============================================================================
92 // [AsmJit::CompilerContext - Construction / Destruction]
93 // ============================================================================
94 
allocVar(X86CompilerVar * var,uint32_t regMask,uint32_t vflags)95 void X86CompilerContext::allocVar(X86CompilerVar* var, uint32_t regMask, uint32_t vflags)
96 {
97   switch (var->getType())
98   {
99     case kX86VarTypeGpd:
100 #if defined(ASMJIT_X64)
101     case kX86VarTypeGpq:
102 #endif // ASMJIT_X64
103       allocGpVar(var, regMask, vflags);
104       break;
105 
106     case kX86VarTypeX87:
107     case kX86VarTypeX87SS:
108     case kX86VarTypeX87SD:
109       // TODO: X87 Support.
110       break;
111 
112     case kX86VarTypeMm:
113       allocMmVar(var, regMask, vflags);
114       break;
115 
116     case kX86VarTypeXmm:
117     case kX86VarTypeXmmSS:
118     case kX86VarTypeXmmPS:
119     case kX86VarTypeXmmSD:
120     case kX86VarTypeXmmPD:
121       allocXmmVar(var, regMask, vflags);
122       break;
123   }
124 
125   _postAlloc(var, vflags);
126 }
127 
saveVar(X86CompilerVar * var)128 void X86CompilerContext::saveVar(X86CompilerVar* var)
129 {
130   switch (var->getType())
131   {
132     case kX86VarTypeGpd:
133 #if defined(ASMJIT_X64)
134     case kX86VarTypeGpq:
135 #endif // ASMJIT_X64
136       saveGpVar(var);
137       break;
138 
139     case kX86VarTypeX87:
140     case kX86VarTypeX87SS:
141     case kX86VarTypeX87SD:
142       // TODO: X87 Support.
143       break;
144 
145     case kX86VarTypeMm:
146       saveMmVar(var);
147       break;
148 
149     case kX86VarTypeXmm:
150     case kX86VarTypeXmmSS:
151     case kX86VarTypeXmmPS:
152     case kX86VarTypeXmmSD:
153     case kX86VarTypeXmmPD:
154       saveXmmVar(var);
155       break;
156   }
157 }
158 
spillVar(X86CompilerVar * var)159 void X86CompilerContext::spillVar(X86CompilerVar* var)
160 {
161   switch (var->getType())
162   {
163     case kX86VarTypeGpd:
164 #if defined(ASMJIT_X64)
165     case kX86VarTypeGpq:
166 #endif // ASMJIT_X64
167       spillGpVar(var);
168       break;
169 
170     case kX86VarTypeX87:
171     case kX86VarTypeX87SS:
172     case kX86VarTypeX87SD:
173       // TODO: X87 Support.
174       break;
175 
176     case kX86VarTypeMm:
177       spillMmVar(var);
178       break;
179 
180     case kX86VarTypeXmm:
181     case kX86VarTypeXmmSS:
182     case kX86VarTypeXmmPS:
183     case kX86VarTypeXmmSD:
184     case kX86VarTypeXmmPD:
185       spillXmmVar(var);
186       break;
187   }
188 }
189 
unuseVar(X86CompilerVar * var,uint32_t toState)190 void X86CompilerContext::unuseVar(X86CompilerVar* var, uint32_t toState)
191 {
192   ASMJIT_ASSERT(toState != kVarStateReg);
193 
194   if (var->state == kVarStateReg)
195   {
196     uint32_t regIndex = var->regIndex;
197     switch (var->getType())
198     {
199       case kX86VarTypeGpd:
200 #if defined(ASMJIT_X64)
201       case kX86VarTypeGpq:
202 #endif // ASMJIT_X64
203         _x86State.gp[regIndex] = NULL;
204         _freedGpRegister(regIndex);
205         break;
206 
207       case kX86VarTypeX87:
208       case kX86VarTypeX87SS:
209       case kX86VarTypeX87SD:
210         // TODO: X87 Support.
211         break;
212 
213       case kX86VarTypeMm:
214         _x86State.mm[regIndex] = NULL;
215         _freedMmRegister(regIndex);
216         break;
217 
218       case kX86VarTypeXmm:
219       case kX86VarTypeXmmSS:
220       case kX86VarTypeXmmPS:
221       case kX86VarTypeXmmSD:
222       case kX86VarTypeXmmPD:
223         _x86State.xmm[regIndex] = NULL;
224         _freedXmmRegister(regIndex);
225         break;
226     }
227   }
228 
229   var->state = toState;
230   var->changed = false;
231   var->regIndex = kRegIndexInvalid;
232 }
233 
allocGpVar(X86CompilerVar * var,uint32_t regMask,uint32_t vflags)234 void X86CompilerContext::allocGpVar(X86CompilerVar* var, uint32_t regMask, uint32_t vflags)
235 {
236   uint32_t fullMask = IntUtil::maskUpToIndex(kX86RegNumGp) & ~IntUtil::maskFromIndex(kX86RegIndexEsp);
237   if (!_allocableEBP)
238     fullMask &= ~IntUtil::maskFromIndex(kX86RegIndexEbp);
239 
240   // Fix the regMask (0 or full bit-array means that any register may be used).
241   if (regMask == 0)
242     regMask = 0xFFFFFFFF;
243   regMask &= fullMask;
244 
245   // Working variables.
246   uint32_t i;
247   uint32_t mask;
248 
249   // Last register code (aka home).
250   uint32_t home = var->homeRegisterIndex;
251   // New register code.
252   uint32_t idx = kRegIndexInvalid;
253 
254   // Preserved GP variables.
255   uint32_t preservedGP = var->funcScope->getDecl()->getGpPreservedMask();
256 
257   // Spill candidate.
258   X86CompilerVar* spillCandidate = NULL;
259 
260   // Whether to alloc the non-preserved variables first.
261   bool nonPreservedFirst = true;
262 
263   if (getFunc()->isCaller())
264     nonPreservedFirst = (var->funcCall == NULL) || (var->funcCall->getOffset() >= var->lastItem->getOffset());
265 
266   // --------------------------------------------------------------------------
267   // [Already Allocated]
268   // --------------------------------------------------------------------------
269 
270   // Go away if variable is already allocated.
271   if (var->state == kVarStateReg)
272   {
273     uint32_t oldIndex = var->regIndex;
274 
275     // Already allocated in the right register.
276     if (IntUtil::maskFromIndex(oldIndex) & regMask)
277       return;
278 
279     // Try to find unallocated register first.
280     mask = regMask & ~_x86State.usedGP;
281     if (mask != 0)
282     {
283       idx = IntUtil::findFirstBit((nonPreservedFirst && (mask & ~preservedGP) != 0) ? mask & ~preservedGP : mask);
284     }
285     // Then find the allocated and exchange later.
286     else
287     {
288       idx = IntUtil::findFirstBit(regMask & _x86State.usedGP);
289     }
290     ASMJIT_ASSERT(idx != kRegIndexInvalid);
291 
292     X86CompilerVar* other = _x86State.gp[idx];
293     emitExchangeVar(var, idx, vflags, other);
294 
295     _x86State.gp[oldIndex] = other;
296     _x86State.gp[idx     ] = var;
297 
298     if (other)
299       other->regIndex = oldIndex;
300     else
301       _freedGpRegister(oldIndex);
302 
303     // Update X86CompilerVar.
304     var->state = kVarStateReg;
305     var->regIndex = idx;
306     var->homeRegisterIndex = idx;
307 
308     _allocatedGpRegister(idx);
309     return;
310   }
311 
312   // --------------------------------------------------------------------------
313   // [Find Unused GP]
314   // --------------------------------------------------------------------------
315 
316   // Home register code.
317   if ((idx == kRegIndexInvalid) &&
318       (home != kRegIndexInvalid) &&
319       (regMask          & IntUtil::maskFromIndex(home)) != 0 &&
320       (_x86State.usedGP & IntUtil::maskFromIndex(home)) == 0)
321   {
322     idx = home;
323     goto _Alloc;
324   }
325 
326   // We start from 1, because EAX/RAX register is sometimes explicitly
327   // needed. So we trying to prevent reallocation in near future.
328   if (idx == kRegIndexInvalid)
329   {
330     for (i = 1, mask = (1 << i); i < kX86RegNumGp; i++, mask <<= 1)
331     {
332       if ((regMask & mask) != 0 && (_x86State.usedGP & mask) == 0)
333       {
334         // Convenience to alloc non-preserved first or non-preserved last.
335         if (nonPreservedFirst)
336         {
337           if (idx != kRegIndexInvalid && (preservedGP & mask) != 0)
338             continue;
339 
340           idx = i;
341           // If current register is preserved, we should try to find different
342           // one that is not. This can save one push / pop in prolog / epilog.
343           if ((preservedGP & mask) == 0)
344             break;
345         }
346         else
347         {
348           if (idx != kRegIndexInvalid && (preservedGP & mask) == 0)
349             continue;
350 
351           idx = i;
352           // The opposite.
353           if ((preservedGP & mask) != 0)
354             break;
355         }
356       }
357     }
358   }
359 
360   // If not found, try EAX/RAX.
361   if ((idx == kRegIndexInvalid) &&
362       (regMask          & IntUtil::maskFromIndex(kX86RegIndexEax)) != 0 &&
363       (_x86State.usedGP & IntUtil::maskFromIndex(kX86RegIndexEax)) == 0)
364   {
365     idx = kX86RegIndexEax;
366     goto _Alloc;
367   }
368 
369   // If regMask contains restricted registers which may be used then everything
370   // is handled inside this block.
371   if ((idx == kRegIndexInvalid) && (regMask != fullMask))
372   {
373     // Try to find unallocated register first.
374     mask = regMask & ~_x86State.usedGP;
375     if (mask != 0)
376     {
377       idx = IntUtil::findFirstBit((nonPreservedFirst && (mask & ~preservedGP) != 0) ? (mask & ~preservedGP) : mask);
378       ASMJIT_ASSERT(idx != kRegIndexInvalid);
379     }
380     // Then find the allocated and spill later.
381     else
382     {
383       idx = IntUtil::findFirstBit(regMask & _x86State.usedGP);
384       ASMJIT_ASSERT(idx != kRegIndexInvalid);
385 
386       // Spill register we need.
387       spillCandidate = _x86State.gp[idx];
388 
389       // Jump to spill part of allocation.
390       goto L_Spill;
391     }
392   }
393 
394   // --------------------------------------------------------------------------
395   // [Spill]
396   // --------------------------------------------------------------------------
397 
398   // If register is still not found, spill other variable.
399   if (idx == kRegIndexInvalid)
400   {
401     if (spillCandidate == NULL)
402     {
403       spillCandidate = _getSpillCandidateGP();
404     }
405 
406     // Spill candidate not found?
407     if (spillCandidate == NULL)
408     {
409       _compiler->setError(kErrorNoRegisters);
410       return;
411     }
412 
413 L_Spill:
414     // Prevented variables can't be spilled. _getSpillCandidate() never returns
415     // prevented variables, but when jumping to L_Spill it could happen.
416     if (spillCandidate->workOffset == _currentOffset)
417     {
418       _compiler->setError(kErrorOverlappedRegisters);
419       return;
420     }
421 
422     idx = spillCandidate->regIndex;
423     spillGpVar(spillCandidate);
424   }
425 
426   // --------------------------------------------------------------------------
427   // [Alloc]
428   // --------------------------------------------------------------------------
429 
430 _Alloc:
431   if (var->state == kVarStateMem && (vflags & kVarAllocRead) != 0)
432   {
433     emitLoadVar(var, idx);
434   }
435 
436   // Update X86CompilerVar.
437   var->state = kVarStateReg;
438   var->regIndex = idx;
439   var->homeRegisterIndex = idx;
440 
441   // Update CompilerState.
442   _allocatedVariable(var);
443 }
444 
saveGpVar(X86CompilerVar * var)445 void X86CompilerContext::saveGpVar(X86CompilerVar* var)
446 {
447   // Can't save variable that isn't allocated.
448   ASMJIT_ASSERT(var->state == kVarStateReg);
449   ASMJIT_ASSERT(var->regIndex != kRegIndexInvalid);
450 
451   uint32_t idx = var->regIndex;
452   emitSaveVar(var, idx);
453 
454   // Update X86CompilerVar.
455   var->changed = false;
456 }
457 
spillGpVar(X86CompilerVar * var)458 void X86CompilerContext::spillGpVar(X86CompilerVar* var)
459 {
460   // Can't spill variable that isn't allocated.
461   ASMJIT_ASSERT(var->state == kVarStateReg);
462   ASMJIT_ASSERT(var->regIndex != kRegIndexInvalid);
463 
464   uint32_t idx = var->regIndex;
465 
466   if (var->changed) emitSaveVar(var, idx);
467 
468   // Update X86CompilerVar.
469   var->regIndex = kRegIndexInvalid;
470   var->state = kVarStateMem;
471   var->changed = false;
472 
473   // Update CompilerState.
474   _x86State.gp[idx] = NULL;
475   _freedGpRegister(idx);
476 }
477 
allocMmVar(X86CompilerVar * var,uint32_t regMask,uint32_t vflags)478 void X86CompilerContext::allocMmVar(X86CompilerVar* var, uint32_t regMask, uint32_t vflags)
479 {
480   // Fix the regMask (0 or full bit-array means that any register may be used).
481   if (regMask == 0) regMask = IntUtil::maskUpToIndex(kX86RegNumMm);
482   regMask &= IntUtil::maskUpToIndex(kX86RegNumMm);
483 
484   // Working variables.
485   uint32_t i;
486   uint32_t mask;
487 
488   // Last register code (aka home).
489   uint32_t home = var->homeRegisterIndex;
490   // New register code.
491   uint32_t idx = kRegIndexInvalid;
492 
493   // Preserved MM variables.
494   //
495   // NOTE: Currently MM variables are not preserved and there is no calling
496   // convention known to me that does that. But on the other side it's possible
497   // to write such calling convention.
498   uint32_t preservedMM = var->funcScope->getDecl()->getMmPreservedMask();
499 
500   // Spill candidate.
501   X86CompilerVar* spillCandidate = NULL;
502 
503   // Whether to alloc non-preserved first or last.
504   bool nonPreservedFirst = true;
505   if (this->getFunc()->isCaller())
506   {
507     nonPreservedFirst = var->funcCall == NULL || var->funcCall->getOffset() >= var->lastItem->getOffset();
508   }
509 
510   // --------------------------------------------------------------------------
511   // [Already Allocated]
512   // --------------------------------------------------------------------------
513 
514   // Go away if variable is already allocated.
515   if (var->state == kVarStateReg)
516   {
517     uint32_t oldIndex = var->regIndex;
518 
519     // Already allocated in the right register.
520     if (IntUtil::maskFromIndex(oldIndex) & regMask) return;
521 
522     // Try to find unallocated register first.
523     mask = regMask & ~_x86State.usedMM;
524     if (mask != 0)
525     {
526       idx = IntUtil::findFirstBit(
527         (nonPreservedFirst && (mask & ~preservedMM) != 0) ? mask & ~preservedMM : mask);
528     }
529     // Then find the allocated and exchange later.
530     else
531     {
532       idx = IntUtil::findFirstBit(regMask & _x86State.usedMM);
533     }
534     ASMJIT_ASSERT(idx != kRegIndexInvalid);
535 
536     X86CompilerVar* other = _x86State.mm[idx];
537     if (other) spillMmVar(other);
538 
539     emitMoveVar(var, idx, vflags);
540     _freedMmRegister(oldIndex);
541     _x86State.mm[idx] = var;
542 
543     // Update X86CompilerVar.
544     var->state = kVarStateReg;
545     var->regIndex = idx;
546     var->homeRegisterIndex = idx;
547 
548     _allocatedMmRegister(idx);
549     return;
550   }
551 
552   // --------------------------------------------------------------------------
553   // [Find Unused MM]
554   // --------------------------------------------------------------------------
555 
556   // If regMask contains restricted registers which may be used then everything
557   // is handled in this block.
558   if (regMask != IntUtil::maskUpToIndex(kX86RegNumMm))
559   {
560     // Try to find unallocated register first.
561     mask = regMask & ~_x86State.usedMM;
562     if (mask != 0)
563     {
564       idx = IntUtil::findFirstBit(
565         (nonPreservedFirst && (mask & ~preservedMM) != 0) ? mask & ~preservedMM : mask);
566       ASMJIT_ASSERT(idx != kRegIndexInvalid);
567     }
568     // Then find the allocated and spill later.
569     else
570     {
571       idx = IntUtil::findFirstBit(regMask & _x86State.usedMM);
572       ASMJIT_ASSERT(idx != kRegIndexInvalid);
573 
574       // Spill register we need.
575       spillCandidate = _x86State.mm[idx];
576 
577       // Jump to spill part of allocation.
578       goto L_Spill;
579     }
580   }
581 
582   // Home register code.
583   if (idx == kRegIndexInvalid && home != kRegIndexInvalid)
584   {
585     if ((_x86State.usedMM & (1U << home)) == 0) idx = home;
586   }
587 
588   if (idx == kRegIndexInvalid)
589   {
590     for (i = 0, mask = (1 << i); i < kX86RegNumMm; i++, mask <<= 1)
591     {
592       if ((_x86State.usedMM & mask) == 0)
593       {
594         // Convenience to alloc non-preserved first or non-preserved last.
595         if (nonPreservedFirst)
596         {
597           if (idx != kRegIndexInvalid && (preservedMM & mask) != 0) continue;
598           idx = i;
599           // If current register is preserved, we should try to find different
600           // one that is not. This can save one push / pop in prolog / epilog.
601           if ((preservedMM & mask) == 0) break;
602         }
603         else
604         {
605           if (idx != kRegIndexInvalid && (preservedMM & mask) == 0) continue;
606           idx = i;
607           // The opposite.
608           if ((preservedMM & mask) != 0) break;
609         }
610       }
611     }
612   }
613 
614   // --------------------------------------------------------------------------
615   // [Spill]
616   // --------------------------------------------------------------------------
617 
618   // If register is still not found, spill other variable.
619   if (idx == kRegIndexInvalid)
620   {
621     if (spillCandidate == NULL) spillCandidate = _getSpillCandidateMM();
622 
623     // Spill candidate not found?
624     if (spillCandidate == NULL)
625     {
626       _compiler->setError(kErrorNoRegisters);
627       return;
628     }
629 
630 L_Spill:
631 
632     // Prevented variables can't be spilled. _getSpillCandidate() never returns
633     // prevented variables, but when jumping to L_spill it can happen.
634     if (spillCandidate->workOffset == _currentOffset)
635     {
636       _compiler->setError(kErrorOverlappedRegisters);
637       return;
638     }
639 
640     idx = spillCandidate->regIndex;
641     spillMmVar(spillCandidate);
642   }
643 
644   // --------------------------------------------------------------------------
645   // [Alloc]
646   // --------------------------------------------------------------------------
647 
648   if (var->state == kVarStateMem && (vflags & kVarAllocRead) != 0)
649   {
650     emitLoadVar(var, idx);
651   }
652 
653   // Update X86CompilerVar.
654   var->state = kVarStateReg;
655   var->regIndex = idx;
656   var->homeRegisterIndex = idx;
657 
658   // Update CompilerState.
659   _allocatedVariable(var);
660 }
661 
saveMmVar(X86CompilerVar * var)662 void X86CompilerContext::saveMmVar(X86CompilerVar* var)
663 {
664   // Can't save variable that isn't allocated.
665   ASMJIT_ASSERT(var->state == kVarStateReg);
666   ASMJIT_ASSERT(var->regIndex != kRegIndexInvalid);
667 
668   uint32_t idx = var->regIndex;
669   emitSaveVar(var, idx);
670 
671   // Update X86CompilerVar.
672   var->changed = false;
673 }
674 
spillMmVar(X86CompilerVar * var)675 void X86CompilerContext::spillMmVar(X86CompilerVar* var)
676 {
677   // Can't spill variable that isn't allocated.
678   ASMJIT_ASSERT(var->state == kVarStateReg);
679   ASMJIT_ASSERT(var->regIndex != kRegIndexInvalid);
680 
681   uint32_t idx = var->regIndex;
682 
683   if (var->changed) emitSaveVar(var, idx);
684 
685   // Update X86CompilerVar.
686   var->regIndex = kRegIndexInvalid;
687   var->state = kVarStateMem;
688   var->changed = false;
689 
690   // Update CompilerState.
691   _x86State.mm[idx] = NULL;
692   _freedMmRegister(idx);
693 }
694 
allocXmmVar(X86CompilerVar * var,uint32_t regMask,uint32_t vflags)695 void X86CompilerContext::allocXmmVar(X86CompilerVar* var, uint32_t regMask, uint32_t vflags)
696 {
697   // Fix the regMask (0 or full bit-array means that any register may be used).
698   if (regMask == 0) regMask = IntUtil::maskUpToIndex(kX86RegNumXmm);
699   regMask &= IntUtil::maskUpToIndex(kX86RegNumXmm);
700 
701   // Working variables.
702   uint32_t i;
703   uint32_t mask;
704 
705   // Last register code (aka home).
706   uint32_t home = var->homeRegisterIndex;
707   // New register code.
708   uint32_t idx = kRegIndexInvalid;
709 
710   // Preserved XMM variables.
711   uint32_t preservedXMM = var->funcScope->getDecl()->getXmmPreservedMask();
712 
713   // Spill candidate.
714   X86CompilerVar* spillCandidate = NULL;
715 
716   // Whether to alloc non-preserved first or last.
717   bool nonPreservedFirst = true;
718 
719   if (this->getFunc()->isCaller())
720     nonPreservedFirst = (var->funcCall == NULL) || (var->funcCall->getOffset() >= var->lastItem->getOffset());
721 
722   // --------------------------------------------------------------------------
723   // [Already Allocated]
724   // --------------------------------------------------------------------------
725 
726   // Go away if variable is already allocated.
727   if (var->state == kVarStateReg)
728   {
729     uint32_t oldIndex = var->regIndex;
730 
731     // Already allocated in the right register.
732     if (IntUtil::maskFromIndex(oldIndex) & regMask) return;
733 
734     // Try to find unallocated register first.
735     mask = regMask & ~_x86State.usedXMM;
736     if (mask != 0)
737     {
738       idx = IntUtil::findFirstBit(
739         (nonPreservedFirst && (mask & ~preservedXMM) != 0) ? mask & ~preservedXMM : mask);
740     }
741     // Then find the allocated and exchange later.
742     else
743     {
744       idx = IntUtil::findFirstBit(regMask & _x86State.usedXMM);
745     }
746     ASMJIT_ASSERT(idx != kRegIndexInvalid);
747 
748     X86CompilerVar* other = _x86State.xmm[idx];
749     if (other) spillXmmVar(other);
750 
751     emitMoveVar(var, idx, vflags);
752     _freedXmmRegister(oldIndex);
753     _x86State.xmm[idx] = var;
754 
755     // Update X86CompilerVar.
756     var->state = kVarStateReg;
757     var->regIndex = idx;
758     var->homeRegisterIndex = idx;
759 
760     _allocatedXmmRegister(idx);
761     return;
762   }
763 
764   // --------------------------------------------------------------------------
765   // [Find Unused XMM]
766   // --------------------------------------------------------------------------
767 
768   // If regMask contains restricted registers which may be used then everything
769   // is handled in this block.
770   if (regMask != IntUtil::maskUpToIndex(kX86RegNumXmm))
771   {
772     // Try to find unallocated register first.
773     mask = regMask & ~_x86State.usedXMM;
774     if (mask != 0)
775     {
776       idx = IntUtil::findFirstBit(
777         (nonPreservedFirst && (mask & ~preservedXMM) != 0) ? mask & ~preservedXMM : mask);
778       ASMJIT_ASSERT(idx != kRegIndexInvalid);
779     }
780     // Then find the allocated and spill later.
781     else
782     {
783       idx = IntUtil::findFirstBit(regMask & _x86State.usedXMM);
784       ASMJIT_ASSERT(idx != kRegIndexInvalid);
785 
786       // Spill register we need.
787       spillCandidate = _x86State.xmm[idx];
788 
789       // Jump to spill part of allocation.
790       goto L_Spill;
791     }
792   }
793 
794   // Home register code.
795   if (idx == kRegIndexInvalid && home != kRegIndexInvalid)
796   {
797     if ((_x86State.usedXMM & (1U << home)) == 0) idx = home;
798   }
799 
800   if (idx == kRegIndexInvalid)
801   {
802     for (i = 0, mask = (1 << i); i < kX86RegNumXmm; i++, mask <<= 1)
803     {
804       if ((_x86State.usedXMM & mask) == 0)
805       {
806         // Convenience to alloc non-preserved first or non-preserved last.
807         if (nonPreservedFirst)
808         {
809           if (idx != kRegIndexInvalid && (preservedXMM & mask) != 0) continue;
810           idx = i;
811           // If current register is preserved, we should try to find different
812           // one that is not. This can save one push / pop in prolog / epilog.
813           if ((preservedXMM & mask) == 0) break;
814         }
815         else
816         {
817           if (idx != kRegIndexInvalid && (preservedXMM & mask) == 0) continue;
818           idx = i;
819           // The opposite.
820           if ((preservedXMM & mask) != 0) break;
821         }
822       }
823     }
824   }
825 
826   // --------------------------------------------------------------------------
827   // [Spill]
828   // --------------------------------------------------------------------------
829 
830   // If register is still not found, spill other variable.
831   if (idx == kRegIndexInvalid)
832   {
833     if (spillCandidate == NULL)
834       spillCandidate = _getSpillCandidateXMM();
835 
836     // Spill candidate not found?
837     if (spillCandidate == NULL)
838     {
839       _compiler->setError(kErrorNoRegisters);
840       return;
841     }
842 
843 L_Spill:
844 
845     // Prevented variables can't be spilled. _getSpillCandidate() never returns
846     // prevented variables, but when jumping to L_spill it can happen.
847     if (spillCandidate->workOffset == _currentOffset)
848     {
849       _compiler->setError(kErrorOverlappedRegisters);
850       return;
851     }
852 
853     idx = spillCandidate->regIndex;
854     spillXmmVar(spillCandidate);
855   }
856 
857   // --------------------------------------------------------------------------
858   // [Alloc]
859   // --------------------------------------------------------------------------
860 
861   if (var->state == kVarStateMem && (vflags & kVarAllocRead) != 0)
862   {
863     emitLoadVar(var, idx);
864   }
865 
866   // Update X86CompilerVar.
867   var->state = kVarStateReg;
868   var->regIndex = idx;
869   var->homeRegisterIndex = idx;
870 
871   // Update CompilerState.
872   _allocatedVariable(var);
873 }
874 
saveXmmVar(X86CompilerVar * var)875 void X86CompilerContext::saveXmmVar(X86CompilerVar* var)
876 {
877   // Can't save variable that isn't allocated.
878   ASMJIT_ASSERT(var->state == kVarStateReg);
879   ASMJIT_ASSERT(var->regIndex != kRegIndexInvalid);
880 
881   uint32_t idx = var->regIndex;
882   emitSaveVar(var, idx);
883 
884   // Update X86CompilerVar.
885   var->changed = false;
886 }
887 
spillXmmVar(X86CompilerVar * var)888 void X86CompilerContext::spillXmmVar(X86CompilerVar* var)
889 {
890   // Can't spill variable that isn't allocated.
891   ASMJIT_ASSERT(var->state == kVarStateReg);
892   ASMJIT_ASSERT(var->regIndex != kRegIndexInvalid);
893 
894   uint32_t idx = var->regIndex;
895 
896   if (var->changed) emitSaveVar(var, idx);
897 
898   // Update CompilerVar.
899   var->regIndex = kRegIndexInvalid;
900   var->state = kVarStateMem;
901   var->changed = false;
902 
903   // Update CompilerState.
904   _x86State.xmm[idx] = NULL;
905   _freedXmmRegister(idx);
906 }
907 
emitLoadVar(X86CompilerVar * var,uint32_t regIndex)908 void X86CompilerContext::emitLoadVar(X86CompilerVar* var, uint32_t regIndex)
909 {
910   X86Compiler* x86Compiler = getCompiler();
911   Mem m = _getVarMem(var);
912 
913   switch (var->getType())
914   {
915     case kX86VarTypeGpd:
916       x86Compiler->emit(kX86InstMov, gpd(regIndex), m);
917       if (_emitComments) goto _AddComment;
918       break;
919 #if defined(ASMJIT_X64)
920     case kX86VarTypeGpq:
921       x86Compiler->emit(kX86InstMov, gpq(regIndex), m);
922       if (_emitComments) goto _AddComment;
923       break;
924 #endif // ASMJIT_X64
925 
926     case kX86VarTypeX87:
927     case kX86VarTypeX87SS:
928     case kX86VarTypeX87SD:
929       // TODO: X87 Support.
930       break;
931 
932     case kX86VarTypeMm:
933       x86Compiler->emit(kX86InstMovQ, mm(regIndex), m);
934       if (_emitComments) goto _AddComment;
935       break;
936 
937     case kX86VarTypeXmm:
938       x86Compiler->emit(kX86InstMovDQA, xmm(regIndex), m);
939       if (_emitComments) goto _AddComment;
940       break;
941     case kX86VarTypeXmmSS:
942       x86Compiler->emit(kX86InstMovSS, xmm(regIndex), m);
943       if (_emitComments) goto _AddComment;
944       break;
945     case kX86VarTypeXmmSD:
946       x86Compiler->emit(kX86InstMovSD, xmm(regIndex), m);
947       if (_emitComments) goto _AddComment;
948       break;
949     case kX86VarTypeXmmPS:
950       x86Compiler->emit(kX86InstMovAPS, xmm(regIndex), m);
951       if (_emitComments) goto _AddComment;
952       break;
953     case kX86VarTypeXmmPD:
954       x86Compiler->emit(kX86InstMovAPD, xmm(regIndex), m);
955       if (_emitComments) goto _AddComment;
956       break;
957   }
958   return;
959 
960 _AddComment:
961   x86Compiler->getCurrentItem()->formatComment("Alloc %s", var->getName());
962 }
963 
emitSaveVar(X86CompilerVar * var,uint32_t regIndex)964 void X86CompilerContext::emitSaveVar(X86CompilerVar* var, uint32_t regIndex)
965 {
966   // Caller must ensure that variable is allocated.
967   ASMJIT_ASSERT(regIndex != kRegIndexInvalid);
968 
969   X86Compiler* x86Compiler = getCompiler();
970   Mem m = _getVarMem(var);
971 
972   switch (var->getType())
973   {
974     case kX86VarTypeGpd:
975       x86Compiler->emit(kX86InstMov, m, gpd(regIndex));
976       if (_emitComments) goto _AddComment;
977       break;
978 #if defined(ASMJIT_X64)
979     case kX86VarTypeGpq:
980       x86Compiler->emit(kX86InstMov, m, gpq(regIndex));
981       if (_emitComments) goto _AddComment;
982       break;
983 #endif // ASMJIT_X64
984 
985     case kX86VarTypeX87:
986     case kX86VarTypeX87SS:
987     case kX86VarTypeX87SD:
988       // TODO: X87 Support.
989       break;
990 
991     case kX86VarTypeMm:
992       x86Compiler->emit(kX86InstMovQ, m, mm(regIndex));
993       if (_emitComments) goto _AddComment;
994       break;
995 
996     case kX86VarTypeXmm:
997       x86Compiler->emit(kX86InstMovDQA, m, xmm(regIndex));
998       if (_emitComments) goto _AddComment;
999       break;
1000     case kX86VarTypeXmmSS:
1001       x86Compiler->emit(kX86InstMovSS, m, xmm(regIndex));
1002       if (_emitComments) goto _AddComment;
1003       break;
1004     case kX86VarTypeXmmSD:
1005       x86Compiler->emit(kX86InstMovSD, m, xmm(regIndex));
1006       if (_emitComments) goto _AddComment;
1007       break;
1008     case kX86VarTypeXmmPS:
1009       x86Compiler->emit(kX86InstMovAPS, m, xmm(regIndex));
1010       if (_emitComments) goto _AddComment;
1011       break;
1012     case kX86VarTypeXmmPD:
1013       x86Compiler->emit(kX86InstMovAPD, m, xmm(regIndex));
1014       if (_emitComments) goto _AddComment;
1015       break;
1016   }
1017   return;
1018 
1019 _AddComment:
1020   x86Compiler->getCurrentItem()->formatComment("Spill %s", var->getName());
1021 }
1022 
emitMoveVar(X86CompilerVar * var,uint32_t regIndex,uint32_t vflags)1023 void X86CompilerContext::emitMoveVar(X86CompilerVar* var, uint32_t regIndex, uint32_t vflags)
1024 {
1025   // Caller must ensure that the given variable is allocated.
1026   ASMJIT_ASSERT(var->regIndex != kRegIndexInvalid);
1027 
1028   X86Compiler* x86Compiler = getCompiler();
1029   if ((vflags & kVarAllocRead) == 0) return;
1030 
1031   switch (var->getType())
1032   {
1033     case kX86VarTypeGpd:
1034       x86Compiler->emit(kX86InstMov, gpd(regIndex), gpd(var->regIndex));
1035       break;
1036 #if defined(ASMJIT_X64)
1037     case kX86VarTypeGpq:
1038       x86Compiler->emit(kX86InstMov, gpq(regIndex), gpq(var->regIndex));
1039       break;
1040 #endif // ASMJIT_X64
1041 
1042     case kX86VarTypeX87:
1043     case kX86VarTypeX87SS:
1044     case kX86VarTypeX87SD:
1045       // TODO: X87 Support.
1046       break;
1047 
1048     case kX86VarTypeMm:
1049       x86Compiler->emit(kX86InstMovQ, mm(regIndex), mm(var->regIndex));
1050       break;
1051 
1052     case kX86VarTypeXmm:
1053       x86Compiler->emit(kX86InstMovDQA, xmm(regIndex), xmm(var->regIndex));
1054       break;
1055     case kX86VarTypeXmmSS:
1056       x86Compiler->emit(kX86InstMovSS, xmm(regIndex), xmm(var->regIndex));
1057       break;
1058     case kX86VarTypeXmmSD:
1059       x86Compiler->emit(kX86InstMovSD, xmm(regIndex), xmm(var->regIndex));
1060       break;
1061     case kX86VarTypeXmmPS:
1062       x86Compiler->emit(kX86InstMovAPS, xmm(regIndex), xmm(var->regIndex));
1063       break;
1064     case kX86VarTypeXmmPD:
1065       x86Compiler->emit(kX86InstMovAPD, xmm(regIndex), xmm(var->regIndex));
1066       break;
1067   }
1068 }
1069 
emitExchangeVar(X86CompilerVar * var,uint32_t regIndex,uint32_t vflags,X86CompilerVar * other)1070 void X86CompilerContext::emitExchangeVar(X86CompilerVar* var, uint32_t regIndex, uint32_t vflags, X86CompilerVar* other)
1071 {
1072   // Caller must ensure that the given variable is allocated.
1073   ASMJIT_ASSERT(var->regIndex != kRegIndexInvalid);
1074 
1075   X86Compiler* x86Compiler = getCompiler();
1076 
1077   // If other is not valid then we can just emit MOV (or other similar instruction).
1078   if (other == NULL)
1079   {
1080     emitMoveVar(var, regIndex, vflags);
1081     return;
1082   }
1083 
1084   // If we need to alloc for write-only operation then we can move other
1085   // variable away instead of exchanging them.
1086   if ((vflags & kVarAllocRead) == 0)
1087   {
1088     emitMoveVar(other, var->regIndex, kVarAllocRead);
1089     return;
1090   }
1091 
1092   switch (var->getType())
1093   {
1094     case kX86VarTypeGpd:
1095       x86Compiler->emit(kX86InstXchg, gpd(regIndex), gpd(var->regIndex));
1096       break;
1097 #if defined(ASMJIT_X64)
1098     case kX86VarTypeGpq:
1099       x86Compiler->emit(kX86InstXchg, gpq(regIndex), gpq(var->regIndex));
1100       break;
1101 #endif // ASMJIT_X64
1102 
1103     case kX86VarTypeX87:
1104     case kX86VarTypeX87SS:
1105     case kX86VarTypeX87SD:
1106       // TODO: X87 Support.
1107       break;
1108 
1109     // NOTE: MM and XMM registers shoudln't be exchanged using this way, it's
1110     // correct, but instead of using one instruction we need three.
1111 
1112     case kX86VarTypeMm:
1113     {
1114       MmReg a = mm(regIndex);
1115       MmReg b = mm(var->regIndex);
1116 
1117       x86Compiler->emit(kX86InstPXor, a, b);
1118       x86Compiler->emit(kX86InstPXor, b, a);
1119       x86Compiler->emit(kX86InstPXor, a, b);
1120       break;
1121     }
1122 
1123     case kX86VarTypeXmmSS:
1124     case kX86VarTypeXmmPS:
1125     {
1126       XmmReg a = xmm(regIndex);
1127       XmmReg b = xmm(var->regIndex);
1128 
1129       x86Compiler->emit(kX86InstXorPS, a, b);
1130       x86Compiler->emit(kX86InstXorPS, b, a);
1131       x86Compiler->emit(kX86InstXorPS, a, b);
1132       break;
1133     }
1134 
1135     case kX86VarTypeXmmSD:
1136     case kX86VarTypeXmmPD:
1137     {
1138       XmmReg a = xmm(regIndex);
1139       XmmReg b = xmm(var->regIndex);
1140 
1141       x86Compiler->emit(kX86InstXorPD, a, b);
1142       x86Compiler->emit(kX86InstXorPD, b, a);
1143       x86Compiler->emit(kX86InstXorPD, a, b);
1144       break;
1145     }
1146 
1147     case kX86VarTypeXmm:
1148     {
1149       XmmReg a = xmm(regIndex);
1150       XmmReg b = xmm(var->regIndex);
1151 
1152       x86Compiler->emit(kX86InstPXor, a, b);
1153       x86Compiler->emit(kX86InstPXor, b, a);
1154       x86Compiler->emit(kX86InstPXor, a, b);
1155       break;
1156     }
1157   }
1158 }
1159 
_postAlloc(X86CompilerVar * var,uint32_t vflags)1160 void X86CompilerContext::_postAlloc(X86CompilerVar* var, uint32_t vflags)
1161 {
1162   if (vflags & kVarAllocWrite)
1163     var->changed = true;
1164 }
1165 
_markMemoryUsed(X86CompilerVar * var)1166 void X86CompilerContext::_markMemoryUsed(X86CompilerVar* var)
1167 {
1168   if (var->homeMemoryData != NULL) return;
1169 
1170   VarMemBlock* mem = _allocMemBlock(var->getSize());
1171   if (!mem) return;
1172 
1173   var->homeMemoryData = mem;
1174 }
1175 
_getVarMem(X86CompilerVar * var)1176 Mem X86CompilerContext::_getVarMem(X86CompilerVar* var)
1177 {
1178   Mem m;
1179   m._mem.id = var->getId();
1180 
1181   if (!var->isMemArgument())
1182     m._mem.displacement = _adjustESP;
1183 
1184   _markMemoryUsed(var);
1185   return m;
1186 }
1187 
getSpillScore(X86CompilerVar * var,uint32_t currentOffset)1188 static int32_t getSpillScore(X86CompilerVar* var, uint32_t currentOffset)
1189 {
1190   int32_t score = 0;
1191 
1192   ASMJIT_ASSERT(var->lastItem != NULL);
1193   uint32_t lastOffset = var->lastItem->getOffset();
1194 
1195   if (lastOffset >= currentOffset)
1196     score += (int32_t)(lastOffset - currentOffset);
1197 
1198   // Each write access decreases probability of spill.
1199   score -= static_cast<int32_t>(var->regWriteCount) + static_cast<int32_t>(var->regRwCount);
1200   // Each read-only access increases probability of spill.
1201   score += static_cast<int32_t>(var->regReadCount);
1202 
1203   // Each memory access increases probability of spill.
1204   score += static_cast<int32_t>(var->memWriteCount) + static_cast<int32_t>(var->memRwCount);
1205   score += static_cast<int32_t>(var->memReadCount);
1206 
1207   return score;
1208 }
1209 
_getSpillCandidateGP()1210 X86CompilerVar* X86CompilerContext::_getSpillCandidateGP()
1211 {
1212   return _getSpillCandidateGeneric(_x86State.gp, kX86RegNumGp);
1213 }
1214 
_getSpillCandidateMM()1215 X86CompilerVar* X86CompilerContext::_getSpillCandidateMM()
1216 {
1217   return _getSpillCandidateGeneric(_x86State.mm, kX86RegNumMm);
1218 }
1219 
_getSpillCandidateXMM()1220 X86CompilerVar* X86CompilerContext::_getSpillCandidateXMM()
1221 {
1222   return _getSpillCandidateGeneric(_x86State.xmm, kX86RegNumXmm);
1223 }
1224 
_getSpillCandidateGeneric(X86CompilerVar ** varArray,uint32_t count)1225 X86CompilerVar* X86CompilerContext::_getSpillCandidateGeneric(X86CompilerVar** varArray, uint32_t count)
1226 {
1227   uint32_t i;
1228 
1229   X86CompilerVar* candidate = NULL;
1230   uint32_t candidatePriority = 0;
1231   int32_t candidateScore = 0;
1232 
1233   uint32_t currentOffset = _compiler->getCurrentItem()->getOffset();
1234 
1235   for (i = 0; i < count; i++)
1236   {
1237     // Get variable.
1238     X86CompilerVar* cv = varArray[i];
1239 
1240     // Never spill variables needed for next instruction.
1241     if (cv == NULL || cv->workOffset == _currentOffset) continue;
1242 
1243     uint32_t variablePriority = cv->getPriority();
1244     int32_t variableScore = getSpillScore(cv, currentOffset);
1245 
1246     if ((candidate == NULL) ||
1247         (variablePriority > candidatePriority) ||
1248         (variablePriority == candidatePriority && variableScore > candidateScore))
1249     {
1250       candidate = cv;
1251       candidatePriority = variablePriority;
1252       candidateScore = variableScore;
1253     }
1254   }
1255 
1256   return candidate;
1257 }
1258 
_addActive(X86CompilerVar * var)1259 void X86CompilerContext::_addActive(X86CompilerVar* var)
1260 {
1261   // Never call with variable that is already in active list.
1262   ASMJIT_ASSERT(var->nextActive == NULL);
1263   ASMJIT_ASSERT(var->prevActive == NULL);
1264 
1265   if (_active == NULL)
1266   {
1267     var->nextActive = var;
1268     var->prevActive = var;
1269 
1270     _active = var;
1271   }
1272   else
1273   {
1274     X86CompilerVar* vlast = static_cast<X86CompilerVar*>(_active)->prevActive;
1275 
1276     vlast->nextActive = var;
1277     static_cast<X86CompilerVar*>(_active)->prevActive = var;
1278 
1279     var->nextActive = static_cast<X86CompilerVar*>(_active);
1280     var->prevActive = vlast;
1281   }
1282 }
1283 
_freeActive(X86CompilerVar * var)1284 void X86CompilerContext::_freeActive(X86CompilerVar* var)
1285 {
1286   X86CompilerVar* next = var->nextActive;
1287   X86CompilerVar* prev = var->prevActive;
1288 
1289   if (prev == next)
1290   {
1291     _active = NULL;
1292   }
1293   else
1294   {
1295     if (_active == var)
1296       _active = next;
1297 
1298     prev->nextActive = next;
1299     next->prevActive = prev;
1300   }
1301 
1302   var->nextActive = NULL;
1303   var->prevActive = NULL;
1304 }
1305 
_freeAllActive()1306 void X86CompilerContext::_freeAllActive()
1307 {
1308   if (_active == NULL)
1309     return;
1310 
1311   X86CompilerVar* cur = static_cast<X86CompilerVar*>(_active);
1312   for (;;)
1313   {
1314     X86CompilerVar* next = cur->nextActive;
1315 
1316     cur->nextActive = NULL;
1317     cur->prevActive = NULL;
1318 
1319     if (next == _active)
1320       break;
1321   }
1322 
1323   _active = NULL;
1324 }
1325 
_allocatedVariable(X86CompilerVar * var)1326 void X86CompilerContext::_allocatedVariable(X86CompilerVar* var)
1327 {
1328   uint32_t idx = var->regIndex;
1329 
1330   switch (var->getType())
1331   {
1332     case kX86VarTypeGpd:
1333     case kX86VarTypeGpq:
1334       _x86State.gp[idx] = var;
1335       _allocatedGpRegister(idx);
1336       break;
1337 
1338     case kX86VarTypeMm:
1339       _x86State.mm[idx] = var;
1340       _allocatedMmRegister(idx);
1341       break;
1342 
1343     case kX86VarTypeXmm:
1344     case kX86VarTypeXmmSS:
1345     case kX86VarTypeXmmPS:
1346     case kX86VarTypeXmmSD:
1347     case kX86VarTypeXmmPD:
1348       _x86State.xmm[idx] = var;
1349       _allocatedXmmRegister(idx);
1350       break;
1351 
1352     default:
1353       ASMJIT_ASSERT(0);
1354       break;
1355   }
1356 }
1357 
translateOperands(Operand * operands,uint32_t count)1358 void X86CompilerContext::translateOperands(Operand* operands, uint32_t count)
1359 {
1360   X86Compiler* x86Compiler = getCompiler();
1361   uint32_t i;
1362 
1363   // Translate variables to registers.
1364   for (i = 0; i < count; i++)
1365   {
1366     Operand& o = operands[i];
1367 
1368     if (o.isVar())
1369     {
1370       X86CompilerVar* cv = x86Compiler->_getVar(o.getId());
1371       ASMJIT_ASSERT(cv != NULL);
1372 
1373       o._reg.op = kOperandReg;
1374       o._reg.code |= cv->regIndex;
1375     }
1376     else if (o.isMem())
1377     {
1378       if ((o.getId() & kOperandIdTypeMask) == kOperandIdTypeVar)
1379       {
1380         // Memory access. We just increment here actual displacement.
1381         X86CompilerVar* cv = x86Compiler->_getVar(o.getId());
1382         ASMJIT_ASSERT(cv != NULL);
1383 
1384         o._mem.displacement += cv->isMemArgument()
1385           ? _argumentsActualDisp
1386           : _variablesActualDisp;
1387         // NOTE: This is not enough, variable position will be patched later
1388         // by X86CompilerContext::_patchMemoryOperands().
1389       }
1390       else if ((o._mem.base & kOperandIdTypeMask) == kOperandIdTypeVar)
1391       {
1392         X86CompilerVar* cv = x86Compiler->_getVar(o._mem.base);
1393         ASMJIT_ASSERT(cv != NULL);
1394 
1395         o._mem.base = cv->regIndex;
1396       }
1397 
1398       if ((o._mem.index & kOperandIdTypeMask) == kOperandIdTypeVar)
1399       {
1400         X86CompilerVar* cv = x86Compiler->_getVar(o._mem.index);
1401         ASMJIT_ASSERT(cv != NULL);
1402 
1403         o._mem.index = cv->regIndex;
1404       }
1405     }
1406   }
1407 }
1408 
addBackwardCode(X86CompilerJmpInst * from)1409 void X86CompilerContext::addBackwardCode(X86CompilerJmpInst* from)
1410 {
1411   _backCode.append(from);
1412 }
1413 
addForwardJump(X86CompilerJmpInst * inst)1414 void X86CompilerContext::addForwardJump(X86CompilerJmpInst* inst)
1415 {
1416   ForwardJumpData* j =
1417     reinterpret_cast<ForwardJumpData*>(_zoneMemory.alloc(sizeof(ForwardJumpData)));
1418   if (j == NULL) { _compiler->setError(kErrorNoHeapMemory); return; }
1419 
1420   j->inst = inst;
1421   j->state = _saveState();
1422   j->next = _forwardJumps;
1423   _forwardJumps = j;
1424 }
1425 
_saveState()1426 X86CompilerState* X86CompilerContext::_saveState()
1427 {
1428   X86Compiler* x86Compiler = getCompiler();
1429 
1430   // Get count of variables stored in memory.
1431   uint32_t memVarsCount = 0;
1432   X86CompilerVar* cur = static_cast<X86CompilerVar*>(_active);
1433 
1434   if (cur)
1435   {
1436     do {
1437       if (cur->state == kVarStateMem) memVarsCount++;
1438       cur = cur->nextActive;
1439     } while (cur != _active);
1440   }
1441 
1442   // Alloc X86CompilerState structure (using zone allocator) and copy current
1443   // state into it.
1444   X86CompilerState* state = x86Compiler->_newState(memVarsCount);
1445   memcpy(state, &_x86State, sizeof(X86CompilerState));
1446 
1447   // Clear changed flags.
1448   state->changedGP = 0;
1449   state->changedMM = 0;
1450   state->changedXMM = 0;
1451 
1452   uint i;
1453   uint mask;
1454 
1455   // Save variables stored in REGISTERs and CHANGE flag.
1456   for (i = 0, mask = 1; i < kX86RegNumGp; i++, mask <<= 1)
1457   {
1458     if (state->gp[i] && state->gp[i]->changed)
1459       state->changedGP |= mask;
1460   }
1461 
1462   for (i = 0, mask = 1; i < kX86RegNumMm; i++, mask <<= 1)
1463   {
1464     if (state->mm[i] && state->mm[i]->changed)
1465       state->changedMM |= mask;
1466   }
1467 
1468   for (i = 0, mask = 1; i < kX86RegNumXmm; i++, mask <<= 1)
1469   {
1470     if (state->xmm[i] && state->xmm[i]->changed)
1471       state->changedXMM |= mask;
1472   }
1473 
1474   // Save variables stored in MEMORY.
1475   state->memVarsCount = memVarsCount;
1476   memVarsCount = 0;
1477 
1478   cur = static_cast<X86CompilerVar*>(_active);
1479   if (cur)
1480   {
1481     do {
1482       if (cur->state == kVarStateMem) state->memVarsData[memVarsCount++] = cur;
1483       cur = cur->nextActive;
1484     } while (cur != _active);
1485   }
1486 
1487   // Finished.
1488   return state;
1489 }
1490 
_assignState(X86CompilerState * state)1491 void X86CompilerContext::_assignState(X86CompilerState* state)
1492 {
1493   Compiler* compiler = getCompiler();
1494 
1495   memcpy(&_x86State, state, sizeof(X86CompilerState));
1496   _x86State.memVarsCount = 0;
1497 
1498   uint i, mask;
1499   X86CompilerVar* cv;
1500 
1501   // Unuse all variables first.
1502   cv = static_cast<X86CompilerVar*>(_active);
1503   if (cv)
1504   {
1505     do {
1506       cv->state = kVarStateUnused;
1507       cv = cv->nextActive;
1508     } while (cv != _active);
1509   }
1510 
1511   // Assign variables stored in memory which are not unused.
1512   for (i = 0; i < state->memVarsCount; i++)
1513   {
1514     state->memVarsData[i]->state = kVarStateMem;
1515   }
1516 
1517   // Assign allocated variables.
1518   for (i = 0, mask = 1; i < kX86RegNumGp; i++, mask <<= 1)
1519   {
1520     if ((cv = _x86State.gp[i]) != NULL)
1521     {
1522       cv->state = kVarStateReg;
1523       cv->regIndex = i;
1524       cv->changed = (_x86State.changedGP & mask) != 0;
1525     }
1526   }
1527 
1528   for (i = 0, mask = 1; i < kX86RegNumMm; i++, mask <<= 1)
1529   {
1530     if ((cv = _x86State.mm[i]) != NULL)
1531     {
1532       cv->state = kVarStateReg;
1533       cv->regIndex = i;
1534       cv->changed = (_x86State.changedMM & mask) != 0;
1535     }
1536   }
1537 
1538   for (i = 0, mask = 1; i < kX86RegNumXmm; i++, mask <<= 1)
1539   {
1540     if ((cv = _x86State.xmm[i]) != NULL)
1541     {
1542       cv->state = kVarStateReg;
1543       cv->regIndex = i;
1544       cv->changed = (_x86State.changedXMM & mask) != 0;
1545     }
1546   }
1547 }
1548 
_restoreState(X86CompilerState * state,uint32_t targetOffset)1549 void X86CompilerContext::_restoreState(X86CompilerState* state, uint32_t targetOffset)
1550 {
1551   X86CompilerState* fromState = &_x86State;
1552   X86CompilerState* toState = state;
1553 
1554   // No change, rare...
1555   if (fromState == toState)
1556     return;
1557 
1558   uint base;
1559   uint i;
1560 
1561   // --------------------------------------------------------------------------
1562   // Set target state to all variables. cv->tInt is target state in this func.
1563   // --------------------------------------------------------------------------
1564 
1565   {
1566     // UNUSED.
1567     X86CompilerVar* cv = static_cast<X86CompilerVar*>(_active);
1568     if (cv)
1569     {
1570       do {
1571         cv->tInt = kVarStateUnused;
1572         cv = cv->nextActive;
1573       } while (cv != _active);
1574     }
1575 
1576     // MEMORY.
1577     for (i = 0; i < toState->memVarsCount; i++)
1578     {
1579       toState->memVarsData[i]->tInt = kVarStateMem;
1580     }
1581 
1582     // REGISTER.
1583     for (i = 0; i < X86CompilerState::kStateRegCount; i++)
1584     {
1585       if ((cv = toState->regs[i]) != NULL) cv->tInt = kVarStateReg;
1586     }
1587   }
1588 
1589   // --------------------------------------------------------------------------
1590   // [GP-Registers Switch]
1591   // --------------------------------------------------------------------------
1592 
1593   // TODO.
1594 #if 0
1595   for (i = 0; i < kX86RegNumGp; i++)
1596   {
1597     X86CompilerVar* fromVar = fromState->gp[i];
1598     X86CompilerVar* toVar = toState->gp[i];
1599 
1600     if (fromVar != toVar)
1601     {
1602       if (fromVar != NULL)
1603       {
1604         if (toVar != NULL)
1605         {
1606           if (fromState->gp[to
1607         }
1608         else
1609         {
1610           // It is possible that variable that was saved in state currently not
1611           // exists (tInt is target scope!).
1612           if (fromVar->tInt == kVarStateUnused)
1613           {
1614             unuseVar(fromVar, kVarStateUnused);
1615           }
1616           else
1617           {
1618             spillVar(fromVar);
1619           }
1620         }
1621       }
1622     }
1623     else if (fromVar != NULL)
1624     {
1625       uint32_t mask = IntUtil::maskFromIndex(i);
1626       // Variables are the same, we just need to compare changed flags.
1627       if ((fromState->changedGP & mask) && !(toState->changedGP & mask)) saveVar(fromVar);
1628     }
1629   }
1630 #endif
1631 
1632   // Spill.
1633   for (base = 0, i = 0; i < X86CompilerState::kStateRegCount; i++)
1634   {
1635     // Change the base offset (from base offset so the register index can be calculated).
1636     if (i == X86CompilerState::kStateRegMmBase || i == X86CompilerState::kStateRegXmmBase)
1637       base = i;
1638 
1639     uint32_t regIndex = i - base;
1640     X86CompilerVar* fromVar = fromState->regs[i];
1641     X86CompilerVar* toVar = toState->regs[i];
1642 
1643     if (fromVar != toVar)
1644     {
1645       // Spill the register.
1646       if (fromVar != NULL)
1647       {
1648         // It is possible that variable that was saved in state currently not
1649         // exists (tInt is target scope!).
1650         if (fromVar->tInt == kVarStateUnused)
1651           unuseVar(fromVar, kVarStateUnused);
1652         else
1653           spillVar(fromVar);
1654       }
1655     }
1656     else if (fromVar != NULL)
1657     {
1658       // Variables are the same, we just need to compare changed flags.
1659       uint32_t mask = IntUtil::maskFromIndex(regIndex);
1660 
1661       if ((fromState->changedGP & mask) && !(toState->changedGP & mask))
1662         saveVar(fromVar);
1663     }
1664   }
1665 
1666   // Alloc.
1667   for (base = 0, i = 0; i < X86CompilerState::kStateRegCount; i++)
1668   {
1669     // Change the base offset (from base offset so the register index can be calculated).
1670     if (i == X86CompilerState::kStateRegMmBase || i == X86CompilerState::kStateRegXmmBase)
1671       base = i;
1672 
1673     X86CompilerVar* fromVar = fromState->regs[i];
1674     X86CompilerVar* toVar = toState->regs[i];
1675 
1676     if (fromVar != toVar)
1677     {
1678       // Alloc register.
1679       uint32_t regIndex = i - base;
1680 
1681       if (toVar != NULL)
1682         allocVar(toVar, IntUtil::maskFromIndex(regIndex), kVarAllocRead);
1683     }
1684 
1685     // TODO:
1686     //if (toVar)
1687     //{
1688       // toVar->changed = to->changed;
1689     //}
1690   }
1691 
1692   // --------------------------------------------------------------------------
1693   // Update used masks.
1694   // --------------------------------------------------------------------------
1695 
1696   _x86State.usedGP = state->usedGP;
1697   _x86State.usedMM = state->usedMM;
1698   _x86State.usedXMM = state->usedXMM;
1699 
1700   // --------------------------------------------------------------------------
1701   // Update changed masks and cleanup.
1702   // --------------------------------------------------------------------------
1703 
1704   {
1705     X86CompilerVar* cv = static_cast<X86CompilerVar*>(_active);
1706     if (cv)
1707     {
1708       do {
1709         if (cv->tInt != kVarStateReg)
1710         {
1711           cv->state = (int)cv->tInt;
1712           cv->changed = false;
1713         }
1714 
1715         cv->tInt = 0;
1716         cv = cv->nextActive;
1717       } while (cv != _active);
1718     }
1719   }
1720 }
1721 
_allocMemBlock(uint32_t size)1722 VarMemBlock* X86CompilerContext::_allocMemBlock(uint32_t size)
1723 {
1724   ASMJIT_ASSERT(size != 0);
1725 
1726   // First try to find mem blocks.
1727   VarMemBlock* mem = _memFree;
1728   VarMemBlock* prev = NULL;
1729 
1730   while (mem)
1731   {
1732     VarMemBlock* next = mem->nextFree;
1733 
1734     if (mem->size == size)
1735     {
1736       if (prev)
1737         prev->nextFree = next;
1738       else
1739         _memFree = next;
1740 
1741       mem->nextFree = NULL;
1742       return mem;
1743     }
1744 
1745     prev = mem;
1746     mem = next;
1747   }
1748 
1749   // Never mind, create new.
1750   mem = reinterpret_cast<VarMemBlock*>(_zoneMemory.alloc(sizeof(VarMemBlock)));
1751   if (mem == NULL)
1752   {
1753     _compiler->setError(kErrorNoHeapMemory);
1754     return NULL;
1755   }
1756 
1757   mem->offset = 0;
1758   mem->size = size;
1759 
1760   mem->nextUsed = _memUsed;
1761   mem->nextFree = NULL;
1762 
1763   _memUsed = mem;
1764 
1765   switch (size)
1766   {
1767     case 16: _mem16BlocksCount++; break;
1768     case 8: _mem8BlocksCount++; break;
1769     case 4: _mem4BlocksCount++; break;
1770   }
1771 
1772   return mem;
1773 }
1774 
_freeMemBlock(VarMemBlock * mem)1775 void X86CompilerContext::_freeMemBlock(VarMemBlock* mem)
1776 {
1777   // Add mem to free blocks.
1778   mem->nextFree = _memFree;
1779   _memFree = mem;
1780 }
1781 
_allocMemoryOperands()1782 void X86CompilerContext::_allocMemoryOperands()
1783 {
1784   VarMemBlock* mem;
1785 
1786   // Variables are allocated in this order:
1787   // 1. 16-byte variables.
1788   // 2. 8-byte variables.
1789   // 3. 4-byte variables.
1790   // 4. All others.
1791 
1792   uint32_t start16 = 0;
1793   uint32_t start8 = start16 + _mem16BlocksCount * 16;
1794   uint32_t start4 = start8  + _mem8BlocksCount * 8;
1795   uint32_t startX = IntUtil::align<uint32_t>(start4 + _mem4BlocksCount * 4, 16);
1796 
1797   for (mem = _memUsed; mem; mem = mem->nextUsed)
1798   {
1799     uint32_t size = mem->size;
1800     uint32_t offset;
1801 
1802     switch (size)
1803     {
1804       case 16:
1805         offset = start16;
1806         start16 += 16;
1807         break;
1808 
1809       case 8:
1810         offset = start8;
1811         start8 += 8;
1812         break;
1813 
1814       case 4:
1815         offset = start4;
1816         start4 += 4;
1817         break;
1818 
1819       default:
1820         // Align to 16 bytes if size is 16 or more.
1821         if (size >= 16)
1822         {
1823           size = IntUtil::align<uint32_t>(size, 16);
1824           startX = IntUtil::align<uint32_t>(startX, 16);
1825         }
1826 
1827         offset = startX;
1828         startX += size;
1829         break;
1830     }
1831 
1832     mem->offset = (int32_t)offset;
1833     _memBytesTotal += size;
1834   }
1835 }
1836 
_patchMemoryOperands(CompilerItem * start,CompilerItem * stop)1837 void X86CompilerContext::_patchMemoryOperands(CompilerItem* start, CompilerItem* stop)
1838 {
1839   CompilerItem* cur;
1840 
1841   for (cur = start;; cur = cur->getNext())
1842   {
1843     if (cur->getType() == kCompilerItemInst)
1844     {
1845       Mem* mem = reinterpret_cast<X86CompilerInst*>(cur)->_memOp;
1846 
1847       if (mem && (mem->_mem.id & kOperandIdTypeMask) == kOperandIdTypeVar)
1848       {
1849         X86CompilerVar* cv = getCompiler()->_getVar(mem->_mem.id);
1850         ASMJIT_ASSERT(cv != NULL);
1851 
1852         if (cv->isMemArgument())
1853         {
1854           mem->_mem.base = _argumentsBaseReg;
1855           mem->_mem.displacement += cv->homeMemoryOffset;
1856           mem->_mem.displacement += _argumentsBaseOffset;
1857         }
1858         else
1859         {
1860           VarMemBlock* mb = reinterpret_cast<VarMemBlock*>(cv->homeMemoryData);
1861           ASMJIT_ASSERT(mb != NULL);
1862 
1863           mem->_mem.base = _variablesBaseReg;
1864           mem->_mem.displacement += mb->offset;
1865           mem->_mem.displacement += _variablesBaseOffset;
1866         }
1867       }
1868     }
1869     if (cur == stop) break;
1870   }
1871 }
1872 
1873 } // AsmJit namespace
1874 
1875 // [Api-End]
1876 #include "../core/apiend.h"
1877