OLD | NEW |
---|---|
1 //===- subzero/src/IceTargetLoweringX8632Traits.h - x86-32 traits -*- C++ -*-=// | 1 //===- subzero/src/IceTargetLoweringX8632Traits.h - x86-32 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 // This file defines the X8632 Target Lowering Traits. | 10 // This file declares the X8632 Target Lowering Traits. |
11 // | 11 // |
12 //===----------------------------------------------------------------------===// | 12 //===----------------------------------------------------------------------===// |
13 | 13 |
14 #ifndef SUBZERO_SRC_ICETARGETLOWERINGX8632TRAITS_H | 14 #ifndef SUBZERO_SRC_ICETARGETLOWERINGX8632TRAITS_H |
15 #define SUBZERO_SRC_ICETARGETLOWERINGX8632TRAITS_H | 15 #define SUBZERO_SRC_ICETARGETLOWERINGX8632TRAITS_H |
16 | 16 |
17 #include "IceAssembler.h" | 17 #include "IceAssembler.h" |
18 #include "IceConditionCodesX8632.h" | 18 #include "IceConditionCodesX8632.h" |
19 #include "IceDefs.h" | 19 #include "IceDefs.h" |
20 #include "IceInst.h" | 20 #include "IceInst.h" |
21 #include "IceInstX8632.def" | 21 #include "IceInstX8632.def" |
22 #include "IceOperand.h" | |
22 #include "IceRegistersX8632.h" | 23 #include "IceRegistersX8632.h" |
23 #include "IceTargetLoweringX8632.def" | 24 #include "IceTargetLoweringX8632.def" |
25 #include "IceTargetLowering.h" | |
24 | 26 |
25 namespace Ice { | 27 namespace Ice { |
26 | 28 |
27 class TargetX8632; | 29 class TargetX8632; |
28 | 30 |
31 namespace X8632 { | |
32 class AssemblerX8632; | |
33 } // end of namespace X8632 | |
34 | |
29 namespace X86Internal { | 35 namespace X86Internal { |
30 | 36 |
37 template <class Machine> struct Insts; | |
31 template <class Machine> struct MachineTraits; | 38 template <class Machine> struct MachineTraits; |
32 | 39 |
33 template <> struct MachineTraits<TargetX8632> { | 40 template <> struct MachineTraits<TargetX8632> { |
34 //---------------------------------------------------------------------------- | 41 //---------------------------------------------------------------------------- |
35 // ______ ______ __ __ | 42 // ______ ______ __ __ |
36 // /\ __ \/\ ___\/\ "-./ \ | 43 // /\ __ \/\ ___\/\ "-./ \ |
37 // \ \ __ \ \___ \ \ \-./\ \ | 44 // \ \ __ \ \___ \ \ \-./\ \ |
38 // \ \_\ \_\/\_____\ \_\ \ \_\ | 45 // \ \_\ \_\/\_____\ \_\ \ \_\ |
39 // \/_/\/_/\/_____/\/_/ \/_/ | 46 // \/_/\/_/\/_____/\/_/ \/_/ |
40 // | 47 // |
41 //---------------------------------------------------------------------------- | 48 //---------------------------------------------------------------------------- |
42 enum ScaleFactor { TIMES_1 = 0, TIMES_2 = 1, TIMES_4 = 2, TIMES_8 = 3 }; | 49 enum ScaleFactor { TIMES_1 = 0, TIMES_2 = 1, TIMES_4 = 2, TIMES_8 = 3 }; |
43 | 50 |
44 using GPRRegister = ::Ice::RegX8632::GPRRegister; | 51 using GPRRegister = ::Ice::RegX8632::GPRRegister; |
45 using XmmRegister = ::Ice::RegX8632::XmmRegister; | 52 using XmmRegister = ::Ice::RegX8632::XmmRegister; |
46 using ByteRegister = ::Ice::RegX8632::ByteRegister; | 53 using ByteRegister = ::Ice::RegX8632::ByteRegister; |
47 using X87STRegister = ::Ice::RegX8632::X87STRegister; | 54 using X87STRegister = ::Ice::RegX8632::X87STRegister; |
48 | 55 |
49 using Cond = ::Ice::CondX86; | 56 using Cond = ::Ice::CondX86; |
50 | 57 |
51 using RegisterSet = ::Ice::RegX8632; | 58 using RegisterSet = ::Ice::RegX8632; |
52 static const GPRRegister Encoded_Reg_Accumulator = RegX8632::Encoded_Reg_eax; | 59 static const GPRRegister Encoded_Reg_Accumulator = RegX8632::Encoded_Reg_eax; |
53 static const GPRRegister Encoded_Reg_Counter = RegX8632::Encoded_Reg_ecx; | 60 static const GPRRegister Encoded_Reg_Counter = RegX8632::Encoded_Reg_ecx; |
54 static const FixupKind PcRelFixup = llvm::ELF::R_386_PC32; | 61 static const FixupKind PcRelFixup = llvm::ELF::R_386_PC32; |
55 | 62 |
56 class Operand { | 63 class Operand { |
57 public: | 64 public: |
58 Operand(const Operand &other) | 65 Operand(const Operand &other) |
59 : length_(other.length_), fixup_(other.fixup_) { | 66 : fixup_(other.fixup_), length_(other.length_) { |
60 memmove(&encoding_[0], &other.encoding_[0], other.length_); | 67 memmove(&encoding_[0], &other.encoding_[0], other.length_); |
61 } | 68 } |
62 | 69 |
63 Operand &operator=(const Operand &other) { | 70 Operand &operator=(const Operand &other) { |
64 length_ = other.length_; | 71 length_ = other.length_; |
65 fixup_ = other.fixup_; | 72 fixup_ = other.fixup_; |
66 memmove(&encoding_[0], &other.encoding_[0], other.length_); | 73 memmove(&encoding_[0], &other.encoding_[0], other.length_); |
67 return *this; | 74 return *this; |
68 } | 75 } |
69 | 76 |
(...skipping 21 matching lines...) Expand all Loading... | |
91 } | 98 } |
92 | 99 |
93 int32_t disp32() const { | 100 int32_t disp32() const { |
94 assert(length_ >= 5); | 101 assert(length_ >= 5); |
95 return bit_copy<int32_t>(encoding_[length_ - 4]); | 102 return bit_copy<int32_t>(encoding_[length_ - 4]); |
96 } | 103 } |
97 | 104 |
98 AssemblerFixup *fixup() const { return fixup_; } | 105 AssemblerFixup *fixup() const { return fixup_; } |
99 | 106 |
100 protected: | 107 protected: |
101 Operand() : length_(0), fixup_(nullptr) {} // Needed by subclass Address. | 108 Operand() : fixup_(nullptr), length_(0) {} // Needed by subclass Address. |
102 | 109 |
103 void SetModRM(int mod, GPRRegister rm) { | 110 void SetModRM(int mod, GPRRegister rm) { |
104 assert((mod & ~3) == 0); | 111 assert((mod & ~3) == 0); |
105 encoding_[0] = (mod << 6) | rm; | 112 encoding_[0] = (mod << 6) | rm; |
106 length_ = 1; | 113 length_ = 1; |
107 } | 114 } |
108 | 115 |
109 void SetSIB(ScaleFactor scale, GPRRegister index, GPRRegister base) { | 116 void SetSIB(ScaleFactor scale, GPRRegister index, GPRRegister base) { |
110 assert(length_ == 1); | 117 assert(length_ == 1); |
111 assert((scale & ~3) == 0); | 118 assert((scale & ~3) == 0); |
112 encoding_[1] = (scale << 6) | (index << 3) | base; | 119 encoding_[1] = (scale << 6) | (index << 3) | base; |
113 length_ = 2; | 120 length_ = 2; |
114 } | 121 } |
115 | 122 |
116 void SetDisp8(int8_t disp) { | 123 void SetDisp8(int8_t disp) { |
117 assert(length_ == 1 || length_ == 2); | 124 assert(length_ == 1 || length_ == 2); |
118 encoding_[length_++] = static_cast<uint8_t>(disp); | 125 encoding_[length_++] = static_cast<uint8_t>(disp); |
119 } | 126 } |
120 | 127 |
121 void SetDisp32(int32_t disp) { | 128 void SetDisp32(int32_t disp) { |
122 assert(length_ == 1 || length_ == 2); | 129 assert(length_ == 1 || length_ == 2); |
123 intptr_t disp_size = sizeof(disp); | 130 intptr_t disp_size = sizeof(disp); |
124 memmove(&encoding_[length_], &disp, disp_size); | 131 memmove(&encoding_[length_], &disp, disp_size); |
125 length_ += disp_size; | 132 length_ += disp_size; |
126 } | 133 } |
127 | 134 |
128 void SetFixup(AssemblerFixup *fixup) { fixup_ = fixup; } | 135 void SetFixup(AssemblerFixup *fixup) { fixup_ = fixup; } |
129 | 136 |
130 private: | 137 private: |
138 AssemblerFixup *fixup_; | |
139 uint8_t encoding_[6]; | |
131 uint8_t length_; | 140 uint8_t length_; |
132 uint8_t encoding_[6]; | |
133 AssemblerFixup *fixup_; | |
134 | 141 |
135 explicit Operand(GPRRegister reg) : fixup_(nullptr) { SetModRM(3, reg); } | 142 explicit Operand(GPRRegister reg) : fixup_(nullptr) { SetModRM(3, reg); } |
136 | 143 |
137 // Get the operand encoding byte at the given index. | 144 // Get the operand encoding byte at the given index. |
138 uint8_t encoding_at(intptr_t index) const { | 145 uint8_t encoding_at(intptr_t index) const { |
139 assert(index >= 0 && index < length_); | 146 assert(index >= 0 && index < length_); |
140 return encoding_[index]; | 147 return encoding_[index]; |
141 } | 148 } |
142 | 149 |
143 // Returns whether or not this operand is really the given register in | 150 // Returns whether or not this operand is really the given register in |
(...skipping 104 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
248 // | 255 // |
249 //---------------------------------------------------------------------------- | 256 //---------------------------------------------------------------------------- |
250 enum InstructionSet { | 257 enum InstructionSet { |
251 Begin, | 258 Begin, |
252 // SSE2 is the PNaCl baseline instruction set. | 259 // SSE2 is the PNaCl baseline instruction set. |
253 SSE2 = Begin, | 260 SSE2 = Begin, |
254 SSE4_1, | 261 SSE4_1, |
255 End | 262 End |
256 }; | 263 }; |
257 | 264 |
265 static const char *TargetName; | |
266 | |
267 static IceString getRegName(SizeT RegNum, Type Ty) { | |
268 assert(RegNum < RegisterSet::Reg_NUM); | |
269 static const char *RegNames8[] = { | |
270 #define X(val, encode, name, name16, name8, scratch, preserved, stackptr, \ | |
271 frameptr, isI8, isInt, isFP) \ | |
272 name8, | |
273 REGX8632_TABLE | |
274 #undef X | |
275 }; | |
276 | |
277 static const char *RegNames16[] = { | |
278 #define X(val, encode, name, name16, name8, scratch, preserved, stackptr, \ | |
279 frameptr, isI8, isInt, isFP) \ | |
280 name16, | |
281 REGX8632_TABLE | |
282 #undef X | |
283 }; | |
284 | |
285 static const char *RegNames[] = { | |
286 #define X(val, encode, name, name16, name8, scratch, preserved, stackptr, \ | |
287 frameptr, isI8, isInt, isFP) \ | |
288 name, | |
289 REGX8632_TABLE | |
290 #undef X | |
291 }; | |
292 | |
293 switch (Ty) { | |
294 case IceType_i1: | |
295 case IceType_i8: | |
296 return RegNames8[RegNum]; | |
297 case IceType_i16: | |
298 return RegNames16[RegNum]; | |
299 default: | |
300 return RegNames[RegNum]; | |
301 } | |
302 } | |
303 | |
304 static void InitRegisterSet(llvm::SmallBitVector *IntegerRegisters, | |
jvoung (off chromium)
2015/07/06 18:58:46
LLVM functions usually begin with lower case lette
John
2015/07/06 22:30:09
Done.
| |
305 llvm::SmallBitVector *IntegerRegistersI8, | |
306 llvm::SmallBitVector *FloatRegisters, | |
307 llvm::SmallBitVector *VectorRegisters, | |
308 llvm::SmallBitVector *ScratchRegs) { | |
309 #define X(val, encode, name, name16, name8, scratch, preserved, stackptr, \ | |
310 frameptr, isI8, isInt, isFP) \ | |
311 (*IntegerRegisters)[RegisterSet::val] = isInt; \ | |
312 (*IntegerRegistersI8)[RegisterSet::val] = isI8; \ | |
313 (*FloatRegisters)[RegisterSet::val] = isFP; \ | |
314 (*VectorRegisters)[RegisterSet::val] = isFP; \ | |
315 (*ScratchRegs)[RegisterSet::val] = scratch; | |
316 REGX8632_TABLE; | |
317 #undef X | |
318 } | |
319 | |
320 static llvm::SmallBitVector | |
321 getRegisterSet(TargetLowering::RegSetMask Include, | |
322 TargetLowering::RegSetMask Exclude) { | |
323 llvm::SmallBitVector Registers(RegisterSet::Reg_NUM); | |
324 | |
325 #define X(val, encode, name, name16, name8, scratch, preserved, stackptr, \ | |
326 frameptr, isI8, isInt, isFP) \ | |
327 if (scratch && (Include & ::Ice::TargetLowering::RegSet_CallerSave)) \ | |
328 Registers[RegisterSet::val] = true; \ | |
329 if (preserved && (Include & ::Ice::TargetLowering::RegSet_CalleeSave)) \ | |
330 Registers[RegisterSet::val] = true; \ | |
331 if (stackptr && (Include & ::Ice::TargetLowering::RegSet_StackPointer)) \ | |
332 Registers[RegisterSet::val] = true; \ | |
333 if (frameptr && (Include & ::Ice::TargetLowering::RegSet_FramePointer)) \ | |
334 Registers[RegisterSet::val] = true; \ | |
335 if (scratch && (Exclude & ::Ice::TargetLowering::RegSet_CallerSave)) \ | |
336 Registers[RegisterSet::val] = false; \ | |
337 if (preserved && (Exclude & ::Ice::TargetLowering::RegSet_CalleeSave)) \ | |
338 Registers[RegisterSet::val] = false; \ | |
339 if (stackptr && (Exclude & ::Ice::TargetLowering::RegSet_StackPointer)) \ | |
340 Registers[RegisterSet::val] = false; \ | |
341 if (frameptr && (Exclude & ::Ice::TargetLowering::RegSet_FramePointer)) \ | |
342 Registers[RegisterSet::val] = false; | |
343 | |
344 REGX8632_TABLE | |
345 | |
346 #undef X | |
347 | |
348 return Registers; | |
349 } | |
350 | |
351 static void | |
352 makeRandomRegisterPermutation(GlobalContext *Ctx, Cfg *Func, | |
353 llvm::SmallVectorImpl<int32_t> &Permutation, | |
354 const llvm::SmallBitVector &ExcludeRegisters) { | |
355 // TODO(stichnot): Declaring Permutation this way loses type/size | |
356 // information. Fix this in conjunction with the caller-side TODO. | |
357 assert(Permutation.size() >= RegisterSet::Reg_NUM); | |
358 // Expected upper bound on the number of registers in a single | |
359 // equivalence class. For x86-32, this would comprise the 8 XMM | |
360 // registers. This is for performance, not correctness. | |
361 static const unsigned MaxEquivalenceClassSize = 8; | |
362 typedef llvm::SmallVector<int32_t, MaxEquivalenceClassSize> RegisterList; | |
363 typedef std::map<uint32_t, RegisterList> EquivalenceClassMap; | |
364 EquivalenceClassMap EquivalenceClasses; | |
365 SizeT NumShuffled = 0, NumPreserved = 0; | |
366 | |
367 // Build up the equivalence classes of registers by looking at the | |
368 // register properties as well as whether the registers should be | |
369 // explicitly excluded from shuffling. | |
370 #define X(val, encode, name, name16, name8, scratch, preserved, stackptr, \ | |
371 frameptr, isI8, isInt, isFP) \ | |
372 if (ExcludeRegisters[RegisterSet::val]) { \ | |
373 /* val stays the same in the resulting permutation. */ \ | |
374 Permutation[RegisterSet::val] = RegisterSet::val; \ | |
375 ++NumPreserved; \ | |
376 } else { \ | |
377 const uint32_t Index = (scratch << 0) | (preserved << 1) | (isI8 << 2) | \ | |
378 (isInt << 3) | (isFP << 4); \ | |
379 /* val is assigned to an equivalence class based on its properties. */ \ | |
380 EquivalenceClasses[Index].push_back(RegisterSet::val); \ | |
381 } | |
382 REGX8632_TABLE | |
383 #undef X | |
384 | |
385 RandomNumberGeneratorWrapper RNG(Ctx->getRNG()); | |
386 | |
387 // Shuffle the resulting equivalence classes. | |
388 for (auto I : EquivalenceClasses) { | |
389 const RegisterList &List = I.second; | |
390 RegisterList Shuffled(List); | |
391 RandomShuffle(Shuffled.begin(), Shuffled.end(), RNG); | |
392 for (size_t SI = 0, SE = Shuffled.size(); SI < SE; ++SI) { | |
393 Permutation[List[SI]] = Shuffled[SI]; | |
394 ++NumShuffled; | |
395 } | |
396 } | |
397 | |
398 assert(NumShuffled + NumPreserved == RegisterSet::Reg_NUM); | |
399 | |
400 if (Func->isVerbose(IceV_Random)) { | |
401 OstreamLocker L(Func->getContext()); | |
402 Ostream &Str = Func->getContext()->getStrDump(); | |
403 Str << "Register equivalence classes:\n"; | |
404 for (auto I : EquivalenceClasses) { | |
405 Str << "{"; | |
406 const RegisterList &List = I.second; | |
407 bool First = true; | |
408 for (int32_t Register : List) { | |
409 if (!First) | |
410 Str << " "; | |
411 First = false; | |
412 Str << getRegName(Register, IceType_i32); | |
413 } | |
414 Str << "}\n"; | |
415 } | |
416 } | |
417 } | |
418 | |
258 // The maximum number of arguments to pass in XMM registers | 419 // The maximum number of arguments to pass in XMM registers |
259 static const uint32_t X86_MAX_XMM_ARGS = 4; | 420 static const uint32_t X86_MAX_XMM_ARGS = 4; |
260 // The number of bits in a byte | 421 // The number of bits in a byte |
261 static const uint32_t X86_CHAR_BIT = 8; | 422 static const uint32_t X86_CHAR_BIT = 8; |
262 // Stack alignment. This is defined in IceTargetLoweringX8632.cpp because it | 423 // Stack alignment. This is defined in IceTargetLoweringX8632.cpp because it |
263 // is used as an argument to std::max(), and the default std::less<T> has an | 424 // is used as an argument to std::max(), and the default std::less<T> has an |
264 // operator(T const&, T const&) which requires this member to have an address. | 425 // operator(T const&, T const&) which requires this member to have an |
426 // address. | |
265 static const uint32_t X86_STACK_ALIGNMENT_BYTES; | 427 static const uint32_t X86_STACK_ALIGNMENT_BYTES; |
266 // Size of the return address on the stack | 428 // Size of the return address on the stack |
267 static const uint32_t X86_RET_IP_SIZE_BYTES = 4; | 429 static const uint32_t X86_RET_IP_SIZE_BYTES = 4; |
268 // The number of different NOP instructions | 430 // The number of different NOP instructions |
269 static const uint32_t X86_NUM_NOP_VARIANTS = 5; | 431 static const uint32_t X86_NUM_NOP_VARIANTS = 5; |
270 | 432 |
271 // Value is in bytes. Return Value adjusted to the next highest multiple | 433 // Value is in bytes. Return Value adjusted to the next highest multiple |
272 // of the stack alignment. | 434 // of the stack alignment. |
273 static uint32_t applyStackAlignment(uint32_t Value) { | 435 static uint32_t applyStackAlignment(uint32_t Value) { |
274 return Utils::applyAlignment(Value, X86_STACK_ALIGNMENT_BYTES); | 436 return Utils::applyAlignment(Value, X86_STACK_ALIGNMENT_BYTES); |
(...skipping 25 matching lines...) Expand all Loading... | |
300 // table by hand, good execution tests are helpful. | 462 // table by hand, good execution tests are helpful. |
301 // | 463 // |
302 // The last two columns describe the case when the operands are vectors | 464 // The last two columns describe the case when the operands are vectors |
303 // of floating point values. For most fcmp conditions, there is a clear | 465 // of floating point values. For most fcmp conditions, there is a clear |
304 // mapping to a single x86 cmpps instruction variant. Some fcmp | 466 // mapping to a single x86 cmpps instruction variant. Some fcmp |
305 // conditions require special code to handle and these are marked in the | 467 // conditions require special code to handle and these are marked in the |
306 // table with a Cmpps_Invalid predicate. | 468 // table with a Cmpps_Invalid predicate. |
307 static const struct TableFcmpType { | 469 static const struct TableFcmpType { |
308 uint32_t Default; | 470 uint32_t Default; |
309 bool SwapScalarOperands; | 471 bool SwapScalarOperands; |
310 CondX86::BrCond C1, C2; | 472 Cond::BrCond C1, C2; |
311 bool SwapVectorOperands; | 473 bool SwapVectorOperands; |
312 CondX86::CmppsCond Predicate; | 474 Cond::CmppsCond Predicate; |
313 } TableFcmp[]; | 475 } TableFcmp[]; |
314 static const size_t TableFcmpSize; | 476 static const size_t TableFcmpSize; |
315 | 477 |
316 // The following table summarizes the logic for lowering the icmp instruction | 478 // The following table summarizes the logic for lowering the icmp |
317 // for i32 and narrower types. Each icmp condition has a clear mapping to an | 479 // instruction |
jvoung (off chromium)
2015/07/06 18:58:45
reflow comment (has a bunch of widowed words)?
John
2015/07/06 22:30:09
Done.
| |
480 // for i32 and narrower types. Each icmp condition has a clear mapping to | |
481 // an | |
318 // x86 conditional branch instruction. | 482 // x86 conditional branch instruction. |
319 | 483 |
320 static const struct TableIcmp32Type { | 484 static const struct TableIcmp32Type { Cond::BrCond Mapping; } TableIcmp32[]; |
321 CondX86::BrCond Mapping; | |
322 } TableIcmp32[]; | |
323 static const size_t TableIcmp32Size; | 485 static const size_t TableIcmp32Size; |
324 | 486 |
325 // The following table summarizes the logic for lowering the icmp instruction | 487 // The following table summarizes the logic for lowering the icmp |
488 // instruction | |
jvoung (off chromium)
2015/07/06 18:58:45
similar -- reflow comment block
John
2015/07/06 22:30:09
Done.
| |
326 // for the i64 type. For Eq and Ne, two separate 32-bit comparisons and | 489 // for the i64 type. For Eq and Ne, two separate 32-bit comparisons and |
327 // conditional branches are needed. For the other conditions, three separate | 490 // conditional branches are needed. For the other conditions, three |
491 // separate | |
328 // conditional branches are needed. | 492 // conditional branches are needed. |
329 static const struct TableIcmp64Type { | 493 static const struct TableIcmp64Type { |
330 CondX86::BrCond C1, C2, C3; | 494 Cond::BrCond C1, C2, C3; |
331 } TableIcmp64[]; | 495 } TableIcmp64[]; |
332 static const size_t TableIcmp64Size; | 496 static const size_t TableIcmp64Size; |
333 | 497 |
334 static CondX86::BrCond getIcmp32Mapping(InstIcmp::ICond Cond) { | 498 static Cond::BrCond getIcmp32Mapping(InstIcmp::ICond Cond) { |
335 size_t Index = static_cast<size_t>(Cond); | 499 size_t Index = static_cast<size_t>(Cond); |
336 assert(Index < TableIcmp32Size); | 500 assert(Index < TableIcmp32Size); |
337 return TableIcmp32[Index].Mapping; | 501 return TableIcmp32[Index].Mapping; |
338 } | 502 } |
339 | 503 |
340 static const struct TableTypeX8632AttributesType { | 504 static const struct TableTypeX8632AttributesType { |
341 Type InVectorElementType; | 505 Type InVectorElementType; |
342 } TableTypeX8632Attributes[]; | 506 } TableTypeX8632Attributes[]; |
343 static const size_t TableTypeX8632AttributesSize; | 507 static const size_t TableTypeX8632AttributesSize; |
508 | |
509 //---------------------------------------------------------------------------- | |
510 // __ __ __ ______ ______ | |
511 // /\ \/\ "-.\ \/\ ___\/\__ _\ | |
512 // \ \ \ \ \-. \ \___ \/_/\ \/ | |
513 // \ \_\ \_\\"\_\/\_____\ \ \_\ | |
514 // \/_/\/_/ \/_/\/_____/ \/_/ | |
515 // | |
516 //---------------------------------------------------------------------------- | |
517 using Insts = ::Ice::X86Internal::Insts<TargetX8632>; | |
518 | |
519 using TargetLowering = TargetX8632; | |
520 using Assembler = X8632::AssemblerX8632; | |
521 | |
522 // X86Operand extends the Operand hierarchy. Its subclasses are | |
523 // X86OperandMem and VariableSplit. | |
524 class X86Operand : public ::Ice::Operand { | |
525 X86Operand() = delete; | |
526 X86Operand(const X86Operand &) = delete; | |
527 X86Operand &operator=(const X86Operand &) = delete; | |
528 | |
529 public: | |
530 enum OperandKindX8632 { k__Start = ::Ice::Operand::kTarget, kMem, kSplit }; | |
531 using ::Ice::Operand::dump; | |
532 | |
533 void dump(const Cfg *, Ostream &Str) const override; | |
534 | |
535 protected: | |
536 X86Operand(OperandKindX8632 Kind, Type Ty) | |
537 : Operand(static_cast<::Ice::Operand::OperandKind>(Kind), Ty) {} | |
538 }; | |
539 | |
540 // X86OperandMem represents the m32 addressing mode, with optional | |
541 // base and index registers, a constant offset, and a fixed shift | |
542 // value for the index register. | |
543 class X86OperandMem : public X86Operand { | |
544 X86OperandMem() = delete; | |
545 X86OperandMem(const X86OperandMem &) = delete; | |
546 X86OperandMem &operator=(const X86OperandMem &) = delete; | |
547 | |
548 public: | |
549 enum SegmentRegisters { | |
550 DefaultSegment = -1, | |
551 #define X(val, name, prefix) val, | |
552 SEG_REGX8632_TABLE | |
553 #undef X | |
554 SegReg_NUM | |
555 }; | |
556 static X86OperandMem *create(Cfg *Func, Type Ty, Variable *Base, | |
557 Constant *Offset, Variable *Index = nullptr, | |
558 uint16_t Shift = 0, | |
559 SegmentRegisters SegmentReg = DefaultSegment) { | |
560 return new (Func->allocate<X86OperandMem>()) | |
561 X86OperandMem(Func, Ty, Base, Offset, Index, Shift, SegmentReg); | |
562 } | |
563 Variable *getBase() const { return Base; } | |
564 Constant *getOffset() const { return Offset; } | |
565 Variable *getIndex() const { return Index; } | |
566 uint16_t getShift() const { return Shift; } | |
567 SegmentRegisters getSegmentRegister() const { return SegmentReg; } | |
568 void emitSegmentOverride(X8632::AssemblerX8632 *Asm) const; | |
jvoung (off chromium)
2015/07/06 18:58:45
"Assembler *" instead of "X8632::AssemblerX8632 *"
John
2015/07/06 22:30:09
Done.
| |
569 Address toAsmAddress(Assembler *Asm) const; | |
570 | |
571 void emit(const Cfg *Func) const override; | |
572 using X86Operand::dump; | |
573 void dump(const Cfg *Func, Ostream &Str) const override; | |
574 | |
575 static bool classof(const Operand *Operand) { | |
576 return Operand->getKind() == static_cast<OperandKind>(kMem); | |
577 } | |
578 | |
579 void setRandomized(bool R) { Randomized = R; } | |
580 | |
581 bool getRandomized() const { return Randomized; } | |
582 | |
583 private: | |
584 X86OperandMem(Cfg *Func, Type Ty, Variable *Base, Constant *Offset, | |
585 Variable *Index, uint16_t Shift, SegmentRegisters SegmentReg); | |
586 | |
587 Variable *Base; | |
588 Constant *Offset; | |
589 Variable *Index; | |
590 uint16_t Shift; | |
591 SegmentRegisters SegmentReg : 16; | |
592 // A flag to show if this memory operand is a randomized one. | |
593 // Randomized memory operands are generated in | |
594 // TargetX8632::randomizeOrPoolImmediate() | |
595 bool Randomized; | |
596 }; | |
597 | |
598 // VariableSplit is a way to treat an f64 memory location as a pair | |
599 // of i32 locations (Low and High). This is needed for some cases | |
600 // of the Bitcast instruction. Since it's not possible for integer | |
601 // registers to access the XMM registers and vice versa, the | |
602 // lowering forces the f64 to be spilled to the stack and then | |
603 // accesses through the VariableSplit. | |
604 class VariableSplit : public X86Operand { | |
605 VariableSplit() = delete; | |
606 VariableSplit(const VariableSplit &) = delete; | |
607 VariableSplit &operator=(const VariableSplit &) = delete; | |
608 | |
609 public: | |
610 enum Portion { Low, High }; | |
611 static VariableSplit *create(Cfg *Func, Variable *Var, Portion Part) { | |
612 return new (Func->allocate<VariableSplit>()) | |
613 VariableSplit(Func, Var, Part); | |
614 } | |
615 int32_t getOffset() const { return Part == High ? 4 : 0; } | |
616 | |
617 Address toAsmAddress(const Cfg *Func) const; | |
618 void emit(const Cfg *Func) const override; | |
619 using X86Operand::dump; | |
620 void dump(const Cfg *Func, Ostream &Str) const override; | |
621 | |
622 static bool classof(const Operand *Operand) { | |
623 return Operand->getKind() == static_cast<OperandKind>(kSplit); | |
624 } | |
625 | |
626 private: | |
627 VariableSplit(Cfg *Func, Variable *Var, Portion Part) | |
628 : X86Operand(kSplit, IceType_i32), Var(Var), Part(Part) { | |
629 assert(Var->getType() == IceType_f64); | |
630 Vars = Func->allocateArrayOf<Variable *>(1); | |
631 Vars[0] = Var; | |
632 NumVars = 1; | |
633 } | |
634 | |
635 Variable *Var; | |
636 Portion Part; | |
637 }; | |
638 | |
639 // SpillVariable decorates a Variable by linking it to another | |
640 // Variable. When stack frame offsets are computed, the SpillVariable | |
641 // is given a distinct stack slot only if its linked Variable has a | |
642 // register. If the linked Variable has a stack slot, then the | |
643 // Variable and SpillVariable share that slot. | |
644 // TODO(jpp): remove references to SpillVariable from IceInstX86Base. | |
jvoung (off chromium)
2015/07/06 18:58:46
Is this TODO about whether some construct is neede
John
2015/07/06 22:30:09
It was poorly placed, as you noticed. Done.
| |
645 class SpillVariable : public Variable { | |
646 SpillVariable() = delete; | |
647 SpillVariable(const SpillVariable &) = delete; | |
648 SpillVariable &operator=(const SpillVariable &) = delete; | |
649 | |
650 public: | |
651 static SpillVariable *create(Cfg *Func, Type Ty, SizeT Index) { | |
652 return new (Func->allocate<SpillVariable>()) SpillVariable(Ty, Index); | |
653 } | |
654 const static OperandKind SpillVariableKind = | |
655 static_cast<OperandKind>(kVariable_Target); | |
656 static bool classof(const Operand *Operand) { | |
657 return Operand->getKind() == SpillVariableKind; | |
658 } | |
659 void setLinkedTo(Variable *Var) { LinkedTo = Var; } | |
660 Variable *getLinkedTo() const { return LinkedTo; } | |
661 // Inherit dump() and emit() from Variable. | |
662 private: | |
663 SpillVariable(Type Ty, SizeT Index) | |
664 : Variable(SpillVariableKind, Ty, Index), LinkedTo(nullptr) {} | |
665 Variable *LinkedTo; | |
666 }; | |
667 | |
668 // Note: The following data structures are defined in IceInstX8632.cpp. | |
669 | |
670 static const struct InstBrAttributesType { | |
671 Cond::BrCond Opposite; | |
672 const char *DisplayString; | |
673 const char *EmitString; | |
674 } InstBrAttributes[]; | |
675 | |
676 static const struct InstCmppsAttributesType { | |
677 const char *EmitString; | |
678 } InstCmppsAttributes[]; | |
679 | |
680 static const struct TypeAttributesType { | |
681 const char *CvtString; // i (integer), s (single FP), d (double FP) | |
682 const char *SdSsString; // ss, sd, or <blank> | |
683 const char *PackString; // b, w, d, or <blank> | |
684 const char *WidthString; // b, w, l, q, or <blank> | |
685 const char *FldString; // s, l, or <blank> | |
686 } TypeAttributes[]; | |
687 | |
688 static const char *InstSegmentRegNames[]; | |
689 | |
690 static uint8_t InstSegmentPrefixes[]; | |
344 }; | 691 }; |
345 | 692 |
346 } // end of namespace X86Internal | 693 } // end of namespace X86Internal |
347 | 694 |
348 namespace X8632 { | 695 namespace X8632 { |
349 using Traits = ::Ice::X86Internal::MachineTraits<TargetX8632>; | 696 using Traits = ::Ice::X86Internal::MachineTraits<TargetX8632>; |
350 } // end of namespace X8632 | 697 } // end of namespace X8632 |
351 | 698 |
352 } // end of namespace Ice | 699 } // end of namespace Ice |
353 | 700 |
354 #endif // SUBZERO_SRC_ICETARGETLOWERINGX8632TRAITS_H | 701 #endif // SUBZERO_SRC_ICETARGETLOWERINGX8632TRAITS_H |
OLD | NEW |