OLD | NEW |
---|---|
1 //===- subzero/src/IceTargetLoweringX8664Traits.h - x86-64 traits -*- C++ -*-=// | 1 //===- subzero/src/IceTargetLoweringX8664Traits.h - x86-64 traits -*- C++ -*-=// |
2 // | 2 // |
3 // The Subzero Code Generator | 3 // The Subzero Code Generator |
4 // | 4 // |
5 // This file is distributed under the University of Illinois Open Source | 5 // This file is distributed under the University of Illinois Open Source |
6 // License. See LICENSE.TXT for details. | 6 // License. See LICENSE.TXT for details. |
7 // | 7 // |
8 //===----------------------------------------------------------------------===// | 8 //===----------------------------------------------------------------------===// |
9 /// | 9 /// |
10 /// \file | 10 /// \file |
11 /// This file declares the X8664 Target Lowering Traits. | 11 /// This file declares the X8664 Target Lowering Traits. |
12 /// | 12 /// |
13 //===----------------------------------------------------------------------===// | 13 //===----------------------------------------------------------------------===// |
14 | 14 |
15 #ifndef SUBZERO_SRC_ICETARGETLOWERINGX8664TRAITS_H | 15 #ifndef SUBZERO_SRC_ICETARGETLOWERINGX8664TRAITS_H |
16 #define SUBZERO_SRC_ICETARGETLOWERINGX8664TRAITS_H | 16 #define SUBZERO_SRC_ICETARGETLOWERINGX8664TRAITS_H |
17 | 17 |
18 #include "IceAssembler.h" | 18 #include "IceAssembler.h" |
19 #include "IceConditionCodesX8664.h" | 19 #include "IceConditionCodesX8664.h" |
20 #include "IceDefs.h" | 20 #include "IceDefs.h" |
21 #include "IceInst.h" | 21 #include "IceInst.h" |
22 #include "IceInstX8664.def" | 22 #include "IceInstX8664.def" |
23 #include "IceOperand.h" | 23 #include "IceOperand.h" |
24 #include "IceRegistersX8664.h" | 24 #include "IceRegistersX8664.h" |
25 #include "IceTargetLowering.h" | 25 #include "IceTargetLowering.h" |
26 #include "IceTargetLoweringX8664.def" | |
26 | 27 |
27 namespace Ice { | 28 namespace Ice { |
28 | 29 |
29 class TargetX8664; | 30 class TargetX8664; |
30 | 31 |
31 namespace X8664 { | 32 namespace X8664 { |
32 class AssemblerX8664; | 33 class AssemblerX8664; |
33 } // end of namespace X8664 | 34 } // end of namespace X8664 |
34 | 35 |
35 namespace X86Internal { | 36 namespace X86Internal { |
36 | 37 |
37 template <class Machine> struct Insts; | 38 template <class Machine> struct Insts; |
38 template <class Machine> struct MachineTraits; | 39 template <class Machine> struct MachineTraits; |
40 template <class Machine> class TargetX86Base; | |
39 | 41 |
40 template <> struct MachineTraits<TargetX8664> { | 42 template <> struct MachineTraits<TargetX8664> { |
41 //---------------------------------------------------------------------------- | 43 //---------------------------------------------------------------------------- |
42 // ______ ______ __ __ | 44 // ______ ______ __ __ |
43 // /\ __ \/\ ___\/\ "-./ \ | 45 // /\ __ \/\ ___\/\ "-./ \ |
44 // \ \ __ \ \___ \ \ \-./\ \ | 46 // \ \ __ \ \___ \ \ \-./\ \ |
45 // \ \_\ \_\/\_____\ \_\ \ \_\ | 47 // \ \_\ \_\/\_____\ \_\ \ \_\ |
46 // \/_/\/_/\/_____/\/_/ \/_/ | 48 // \/_/\/_/\/_____/\/_/ \/_/ |
47 // | 49 // |
48 //---------------------------------------------------------------------------- | 50 //---------------------------------------------------------------------------- |
(...skipping 226 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
275 }; | 277 }; |
276 | 278 |
277 //---------------------------------------------------------------------------- | 279 //---------------------------------------------------------------------------- |
278 // __ ______ __ __ ______ ______ __ __ __ ______ | 280 // __ ______ __ __ ______ ______ __ __ __ ______ |
279 // /\ \ /\ __ \/\ \ _ \ \/\ ___\/\ == \/\ \/\ "-.\ \/\ ___\ | 281 // /\ \ /\ __ \/\ \ _ \ \/\ ___\/\ == \/\ \/\ "-.\ \/\ ___\ |
280 // \ \ \___\ \ \/\ \ \ \/ ".\ \ \ __\\ \ __<\ \ \ \ \-. \ \ \__ \ | 282 // \ \ \___\ \ \/\ \ \ \/ ".\ \ \ __\\ \ __<\ \ \ \ \-. \ \ \__ \ |
281 // \ \_____\ \_____\ \__/".~\_\ \_____\ \_\ \_\ \_\ \_\\"\_\ \_____\ | 283 // \ \_____\ \_____\ \__/".~\_\ \_____\ \_\ \_\ \_\ \_\\"\_\ \_____\ |
282 // \/_____/\/_____/\/_/ \/_/\/_____/\/_/ /_/\/_/\/_/ \/_/\/_____/ | 284 // \/_____/\/_____/\/_/ \/_/\/_____/\/_/ /_/\/_/\/_/ \/_/\/_____/ |
283 // | 285 // |
284 //---------------------------------------------------------------------------- | 286 //---------------------------------------------------------------------------- |
287 enum InstructionSet { | |
288 Begin, | |
289 // SSE2 is the PNaCl baseline instruction set. | |
290 SSE2 = Begin, | |
291 SSE4_1, | |
292 End | |
293 }; | |
294 | |
295 static const char *TargetName; | |
296 | |
297 static IceString getRegName(SizeT RegNum, Type Ty) { | |
298 assert(RegNum < RegisterSet::Reg_NUM); | |
299 static const struct { | |
300 const char *const Name8; | |
301 const char *const Name16; | |
302 const char *const Name /*32*/; | |
303 const char *const Name64; | |
304 } RegNames[] = { | |
305 #define X(val, encode, name64, name32, name16, name8, scratch, preserved, \ | |
306 stackptr, frameptr, isInt, isFP) \ | |
307 { name8, name16, name32, name64 } \ | |
308 , | |
309 REGX8664_TABLE | |
310 #undef X | |
311 }; | |
312 | |
313 switch (Ty) { | |
314 case IceType_i1: | |
315 case IceType_i8: | |
316 return RegNames[RegNum].Name8; | |
317 case IceType_i16: | |
318 return RegNames[RegNum].Name16; | |
319 case IceType_i64: | |
320 return RegNames[RegNum].Name64; | |
321 default: | |
322 return RegNames[RegNum].Name; | |
323 } | |
324 } | |
325 | |
326 static void initRegisterSet(llvm::SmallBitVector *IntegerRegisters, | |
327 llvm::SmallBitVector *IntegerRegistersI8, | |
328 llvm::SmallBitVector *FloatRegisters, | |
329 llvm::SmallBitVector *VectorRegisters, | |
330 llvm::SmallBitVector *ScratchRegs) { | |
331 #define X(val, encode, name64, name32, name16, name8, scratch, preserved, \ | |
332 stackptr, frameptr, isInt, isFP) \ | |
333 (*IntegerRegisters)[RegisterSet::val] = isInt; \ | |
334 (*IntegerRegistersI8)[RegisterSet::val] = 1; \ | |
335 (*FloatRegisters)[RegisterSet::val] = isFP; \ | |
336 (*VectorRegisters)[RegisterSet::val] = isFP; \ | |
337 (*ScratchRegs)[RegisterSet::val] = scratch; | |
338 REGX8664_TABLE; | |
339 #undef X | |
340 } | |
341 | |
342 static llvm::SmallBitVector | |
343 getRegisterSet(TargetLowering::RegSetMask Include, | |
344 TargetLowering::RegSetMask Exclude) { | |
345 llvm::SmallBitVector Registers(RegisterSet::Reg_NUM); | |
346 | |
347 #define X(val, encode, name64, name32, name16, name8, scratch, preserved, \ | |
348 stackptr, frameptr, isInt, isFP) \ | |
349 if (scratch && (Include & ::Ice::TargetLowering::RegSet_CallerSave)) \ | |
350 Registers[RegisterSet::val] = true; \ | |
351 if (preserved && (Include & ::Ice::TargetLowering::RegSet_CalleeSave)) \ | |
352 Registers[RegisterSet::val] = true; \ | |
353 if (stackptr && (Include & ::Ice::TargetLowering::RegSet_StackPointer)) \ | |
354 Registers[RegisterSet::val] = true; \ | |
355 if (frameptr && (Include & ::Ice::TargetLowering::RegSet_FramePointer)) \ | |
356 Registers[RegisterSet::val] = true; \ | |
357 if (scratch && (Exclude & ::Ice::TargetLowering::RegSet_CallerSave)) \ | |
358 Registers[RegisterSet::val] = false; \ | |
359 if (preserved && (Exclude & ::Ice::TargetLowering::RegSet_CalleeSave)) \ | |
360 Registers[RegisterSet::val] = false; \ | |
361 if (stackptr && (Exclude & ::Ice::TargetLowering::RegSet_StackPointer)) \ | |
362 Registers[RegisterSet::val] = false; \ | |
363 if (frameptr && (Exclude & ::Ice::TargetLowering::RegSet_FramePointer)) \ | |
364 Registers[RegisterSet::val] = false; | |
365 | |
366 REGX8664_TABLE | |
367 | |
368 #undef X | |
369 | |
370 return Registers; | |
371 } | |
372 | |
373 static void | |
374 makeRandomRegisterPermutation(GlobalContext *Ctx, Cfg *Func, | |
375 llvm::SmallVectorImpl<int32_t> &Permutation, | |
376 const llvm::SmallBitVector &ExcludeRegisters) { | |
377 // TODO(stichnot): Declaring Permutation this way loses type/size | |
378 // information. Fix this in conjunction with the caller-side TODO. | |
379 assert(Permutation.size() >= RegisterSet::Reg_NUM); | |
380 // Expected upper bound on the number of registers in a single equivalence | |
381 // class. For x86-64, this would comprise the 16 XMM registers. This is | |
382 // for performance, not correctness. | |
383 static const unsigned MaxEquivalenceClassSize = 8; | |
384 typedef llvm::SmallVector<int32_t, MaxEquivalenceClassSize> RegisterList; | |
385 typedef std::map<uint32_t, RegisterList> EquivalenceClassMap; | |
386 EquivalenceClassMap EquivalenceClasses; | |
387 SizeT NumShuffled = 0, NumPreserved = 0; | |
388 | |
389 // Build up the equivalence classes of registers by looking at the register | |
390 // properties as well as whether the registers should be explicitly excluded | |
391 // from shuffling. | |
392 #define X(val, encode, name64, name32, name16, name8, scratch, preserved, \ | |
393 stackptr, frameptr, isInt, isFP) \ | |
394 if (ExcludeRegisters[RegisterSet::val]) { \ | |
395 /* val stays the same in the resulting permutation. */ \ | |
396 Permutation[RegisterSet::val] = RegisterSet::val; \ | |
397 ++NumPreserved; \ | |
398 } else { \ | |
399 const uint32_t Index = (scratch << 0) | (preserved << 1) | \ | |
400 (/*isI8=*/1 << 2) | (isInt << 3) | (isFP << 4); \ | |
401 /* val is assigned to an equivalence class based on its properties. */ \ | |
402 EquivalenceClasses[Index].push_back(RegisterSet::val); \ | |
403 } | |
404 REGX8664_TABLE | |
405 #undef X | |
406 | |
407 RandomNumberGeneratorWrapper RNG(Ctx->getRNG()); | |
408 | |
409 // Shuffle the resulting equivalence classes. | |
410 for (auto I : EquivalenceClasses) { | |
411 const RegisterList &List = I.second; | |
412 RegisterList Shuffled(List); | |
413 RandomShuffle(Shuffled.begin(), Shuffled.end(), RNG); | |
414 for (size_t SI = 0, SE = Shuffled.size(); SI < SE; ++SI) { | |
415 Permutation[List[SI]] = Shuffled[SI]; | |
416 ++NumShuffled; | |
417 } | |
418 } | |
419 | |
420 assert(NumShuffled + NumPreserved == RegisterSet::Reg_NUM); | |
421 | |
422 if (Func->isVerbose(IceV_Random)) { | |
423 OstreamLocker L(Func->getContext()); | |
424 Ostream &Str = Func->getContext()->getStrDump(); | |
425 Str << "Register equivalence classes:\n"; | |
426 for (auto I : EquivalenceClasses) { | |
427 Str << "{"; | |
428 const RegisterList &List = I.second; | |
429 bool First = true; | |
430 for (int32_t Register : List) { | |
431 if (!First) | |
432 Str << " "; | |
433 First = false; | |
434 Str << getRegName(Register, IceType_i32); | |
435 } | |
436 Str << "}\n"; | |
437 } | |
438 } | |
439 } | |
440 | |
441 /// The maximum number of arguments to pass in XMM registers | |
442 static const uint32_t X86_MAX_XMM_ARGS = 4; | |
443 /// The number of bits in a byte | |
444 static const uint32_t X86_CHAR_BIT = 8; | |
445 /// Stack alignment. This is defined in IceTargetLoweringX8664.cpp because it | |
446 /// is used as an argument to std::max(), and the default std::less<T> has an | |
447 /// operator(T const&, T const&) which requires this member to have an | |
448 /// address. | |
449 static const uint32_t X86_STACK_ALIGNMENT_BYTES; | |
450 /// Size of the return address on the stack | |
451 static const uint32_t X86_RET_IP_SIZE_BYTES = 4; | |
452 /// The number of different NOP instructions | |
453 static const uint32_t X86_NUM_NOP_VARIANTS = 5; | |
454 | |
455 /// Value is in bytes. Return Value adjusted to the next highest multiple | |
456 /// of the stack alignment. | |
457 static uint32_t applyStackAlignment(uint32_t Value) { | |
458 return Utils::applyAlignment(Value, X86_STACK_ALIGNMENT_BYTES); | |
459 } | |
460 | |
461 /// Return the type which the elements of the vector have in the X86 | |
462 /// representation of the vector. | |
463 static Type getInVectorElementType(Type Ty) { | |
464 assert(isVectorType(Ty)); | |
465 size_t Index = static_cast<size_t>(Ty); | |
466 (void)Index; | |
467 assert(Index < TableTypeX8664AttributesSize); | |
468 return TableTypeX8664Attributes[Ty].InVectorElementType; | |
469 } | |
470 | |
471 // Note: The following data structures are defined in | |
472 // IceTargetLoweringX8664.cpp. | |
473 | |
474 /// The following table summarizes the logic for lowering the fcmp | |
475 /// instruction. There is one table entry for each of the 16 conditions. | |
476 /// | |
477 /// The first four columns describe the case when the operands are floating | |
478 /// point scalar values. A comment in lowerFcmp() describes the lowering | |
479 /// template. In the most general case, there is a compare followed by two | |
480 /// conditional branches, because some fcmp conditions don't map to a single | |
481 /// x86 conditional branch. However, in many cases it is possible to swap the | |
482 /// operands in the comparison and have a single conditional branch. Since | |
483 /// it's quite tedious to validate the table by hand, good execution tests are | |
484 /// helpful. | |
485 /// | |
486 /// The last two columns describe the case when the operands are vectors of | |
487 /// floating point values. For most fcmp conditions, there is a clear mapping | |
488 /// to a single x86 cmpps instruction variant. Some fcmp conditions require | |
489 /// special code to handle and these are marked in the table with a | |
490 /// Cmpps_Invalid predicate. | |
491 /// {@ | |
492 static const struct TableFcmpType { | |
493 uint32_t Default; | |
494 bool SwapScalarOperands; | |
495 Cond::BrCond C1, C2; | |
496 bool SwapVectorOperands; | |
497 Cond::CmppsCond Predicate; | |
498 } TableFcmp[]; | |
499 static const size_t TableFcmpSize; | |
500 /// @} | |
501 | |
502 /// The following table summarizes the logic for lowering the icmp instruction | |
503 /// for i32 and narrower types. Each icmp condition has a clear mapping to an | |
504 /// x86 conditional branch instruction. | |
505 /// {@ | |
506 static const struct TableIcmp32Type { Cond::BrCond Mapping; } TableIcmp32[]; | |
507 static const size_t TableIcmp32Size; | |
508 /// @} | |
509 | |
510 /// The following table summarizes the logic for lowering the icmp instruction | |
511 /// for the i64 type. For Eq and Ne, two separate 32-bit comparisons and | |
512 /// conditional branches are needed. For the other conditions, three separate | |
513 /// conditional branches are needed. | |
514 /// {@ | |
515 static const struct TableIcmp64Type { | |
516 Cond::BrCond C1, C2, C3; | |
517 } TableIcmp64[]; | |
518 static const size_t TableIcmp64Size; | |
519 /// @} | |
520 | |
521 static Cond::BrCond getIcmp32Mapping(InstIcmp::ICond Cond) { | |
522 size_t Index = static_cast<size_t>(Cond); | |
523 assert(Index < TableIcmp32Size); | |
524 return TableIcmp32[Index].Mapping; | |
525 } | |
526 | |
527 static const struct TableTypeX8664AttributesType { | |
528 Type InVectorElementType; | |
529 } TableTypeX8664Attributes[]; | |
530 static const size_t TableTypeX8664AttributesSize; | |
531 | |
532 //---------------------------------------------------------------------------- | |
533 // __ __ __ ______ ______ | |
534 // /\ \/\ "-.\ \/\ ___\/\__ _\ | |
535 // \ \ \ \ \-. \ \___ \/_/\ \/ | |
536 // \ \_\ \_\\"\_\/\_____\ \ \_\ | |
537 // \/_/\/_/ \/_/\/_____/ \/_/ | |
538 // | |
539 //---------------------------------------------------------------------------- | |
540 using Insts = ::Ice::X86Internal::Insts<TargetX8664>; | |
541 | |
542 using TargetLowering = ::Ice::X86Internal::TargetX86Base<TargetX8664>; | |
285 using Assembler = X8664::AssemblerX8664; | 543 using Assembler = X8664::AssemblerX8664; |
544 | |
545 /// X86Operand extends the Operand hierarchy. Its subclasses are | |
546 /// X86OperandMem and VariableSplit. | |
547 class X86Operand : public ::Ice::Operand { | |
548 X86Operand() = delete; | |
549 X86Operand(const X86Operand &) = delete; | |
550 X86Operand &operator=(const X86Operand &) = delete; | |
551 | |
552 public: | |
553 enum OperandKindX8664 { k__Start = ::Ice::Operand::kTarget, kMem, kSplit }; | |
554 using ::Ice::Operand::dump; | |
555 | |
556 void dump(const Cfg *, Ostream &Str) const override; | |
557 | |
558 protected: | |
559 X86Operand(OperandKindX8664 Kind, Type Ty) | |
560 : Operand(static_cast<::Ice::Operand::OperandKind>(Kind), Ty) {} | |
561 }; | |
562 | |
563 /// X86OperandMem represents the m64 addressing mode, with optional base and | |
564 /// index registers, a constant offset, and a fixed shift value for the index | |
565 /// register. | |
566 class X86OperandMem : public X86Operand { | |
567 X86OperandMem() = delete; | |
568 X86OperandMem(const X86OperandMem &) = delete; | |
569 X86OperandMem &operator=(const X86OperandMem &) = delete; | |
570 | |
571 public: | |
572 enum SegmentRegisters { DefaultSegment = -1, SegReg_NUM }; | |
573 static X86OperandMem * | |
574 create(Cfg *Func, Type Ty, Variable *Base, Constant *Offset, | |
575 Variable *Index = nullptr, uint16_t Shift = 0, | |
576 SegmentRegisters SegmentRegister = DefaultSegment) { | |
577 assert(SegmentRegister == DefaultSegment); | |
578 (void)SegmentRegister; | |
579 return new (Func->allocate<X86OperandMem>()) | |
580 X86OperandMem(Func, Ty, Base, Offset, Index, Shift); | |
581 } | |
582 Variable *getBase() const { return Base; } | |
583 Constant *getOffset() const { return Offset; } | |
584 Variable *getIndex() const { return Index; } | |
585 uint16_t getShift() const { return Shift; } | |
586 SegmentRegisters getSegmentRegister() const { return DefaultSegment; } | |
587 void emitSegmentOverride(Assembler *) const {} | |
588 Address toAsmAddress(Assembler *Asm) const; | |
589 | |
590 void emit(const Cfg *Func) const override; | |
591 using X86Operand::dump; | |
592 void dump(const Cfg *Func, Ostream &Str) const override; | |
593 | |
594 static bool classof(const Operand *Operand) { | |
595 return Operand->getKind() == static_cast<OperandKind>(kMem); | |
596 } | |
597 | |
598 void setRandomized(bool R) { Randomized = R; } | |
599 | |
600 bool getRandomized() const { return Randomized; } | |
601 | |
602 private: | |
603 X86OperandMem(Cfg *Func, Type Ty, Variable *Base, Constant *Offset, | |
604 Variable *Index, uint16_t Shift); | |
605 | |
606 Variable *Base; | |
607 Constant *Offset; | |
608 Variable *Index; | |
609 uint16_t Shift; | |
610 /// A flag to show if this memory operand is a randomized one. Randomized | |
611 /// memory operands are generated in | |
612 /// TargetX86Base::randomizeOrPoolImmediate() | |
613 bool Randomized; | |
Jim Stichnoth
2015/07/30 19:11:08
This should be "bool Randomized = false;" and then
John
2015/07/31 21:05:54
Done.
| |
614 }; | |
615 | |
616 /// VariableSplit is a way to treat an f64 memory location as a pair of i32 | |
617 /// locations (Low and High). This is needed for some cases of the Bitcast | |
618 /// instruction. Since it's not possible for integer registers to access the | |
619 /// XMM registers and vice versa, the lowering forces the f64 to be spilled to | |
620 /// the stack and then accesses through the VariableSplit. | |
621 // TODO(jpp): remove references to VariableSplit from IceInstX86Base as 64bit | |
622 // targets can natively handle these. | |
623 class VariableSplit : public X86Operand { | |
624 VariableSplit() = delete; | |
625 VariableSplit(const VariableSplit &) = delete; | |
626 VariableSplit &operator=(const VariableSplit &) = delete; | |
627 | |
628 public: | |
629 enum Portion { Low, High }; | |
630 static VariableSplit *create(Cfg *Func, Variable *Var, Portion Part) { | |
631 return new (Func->allocate<VariableSplit>()) | |
632 VariableSplit(Func, Var, Part); | |
633 } | |
634 int32_t getOffset() const { return Part == High ? 4 : 0; } | |
635 | |
636 Address toAsmAddress(const Cfg *Func) const; | |
637 void emit(const Cfg *Func) const override; | |
638 using X86Operand::dump; | |
639 void dump(const Cfg *Func, Ostream &Str) const override; | |
640 | |
641 static bool classof(const Operand *Operand) { | |
642 return Operand->getKind() == static_cast<OperandKind>(kSplit); | |
643 } | |
644 | |
645 private: | |
646 VariableSplit(Cfg *Func, Variable *Var, Portion Part) | |
647 : X86Operand(kSplit, IceType_i32), Var(Var), Part(Part) { | |
648 assert(Var->getType() == IceType_f64); | |
649 Vars = Func->allocateArrayOf<Variable *>(1); | |
650 Vars[0] = Var; | |
651 NumVars = 1; | |
652 } | |
653 | |
654 Variable *Var; | |
655 Portion Part; | |
656 }; | |
657 | |
658 /// SpillVariable decorates a Variable by linking it to another Variable. | |
659 /// When stack frame offsets are computed, the SpillVariable is given a | |
660 /// distinct stack slot only if its linked Variable has a register. If the | |
661 /// linked Variable has a stack slot, then the Variable and SpillVariable | |
662 /// share that slot. | |
663 class SpillVariable : public Variable { | |
664 SpillVariable() = delete; | |
665 SpillVariable(const SpillVariable &) = delete; | |
666 SpillVariable &operator=(const SpillVariable &) = delete; | |
667 | |
668 public: | |
669 static SpillVariable *create(Cfg *Func, Type Ty, SizeT Index) { | |
670 return new (Func->allocate<SpillVariable>()) SpillVariable(Ty, Index); | |
671 } | |
672 const static OperandKind SpillVariableKind = | |
673 static_cast<OperandKind>(kVariable_Target); | |
674 static bool classof(const Operand *Operand) { | |
675 return Operand->getKind() == SpillVariableKind; | |
676 } | |
677 void setLinkedTo(Variable *Var) { LinkedTo = Var; } | |
678 Variable *getLinkedTo() const { return LinkedTo; } | |
679 // Inherit dump() and emit() from Variable. | |
680 | |
681 private: | |
682 SpillVariable(Type Ty, SizeT Index) | |
683 : Variable(SpillVariableKind, Ty, Index), LinkedTo(nullptr) {} | |
684 Variable *LinkedTo; | |
685 }; | |
686 | |
687 // Note: The following data structures are defined in IceInstX8664.cpp. | |
688 | |
689 static const struct InstBrAttributesType { | |
690 Cond::BrCond Opposite; | |
691 const char *DisplayString; | |
692 const char *EmitString; | |
693 } InstBrAttributes[]; | |
694 | |
695 static const struct InstCmppsAttributesType { | |
696 const char *EmitString; | |
697 } InstCmppsAttributes[]; | |
698 | |
699 static const struct TypeAttributesType { | |
700 const char *CvtString; // i (integer), s (single FP), d (double FP) | |
701 const char *SdSsString; // ss, sd, or <blank> | |
702 const char *PackString; // b, w, d, or <blank> | |
703 const char *WidthString; // b, w, l, q, or <blank> | |
704 const char *FldString; // s, l, or <blank> | |
705 } TypeAttributes[]; | |
286 }; | 706 }; |
287 | 707 |
288 } // end of namespace X86Internal | 708 } // end of namespace X86Internal |
289 | 709 |
290 namespace X8664 { | 710 namespace X8664 { |
291 using Traits = ::Ice::X86Internal::MachineTraits<TargetX8664>; | 711 using Traits = ::Ice::X86Internal::MachineTraits<TargetX8664>; |
292 } // end of namespace X8664 | 712 } // end of namespace X8664 |
293 | 713 |
294 } // end of namespace Ice | 714 } // end of namespace Ice |
295 | 715 |
296 #endif // SUBZERO_SRC_ICETARGETLOWERINGX8664TRAITS_H | 716 #endif // SUBZERO_SRC_ICETARGETLOWERINGX8664TRAITS_H |
OLD | NEW |