Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(107)

Side by Side Diff: src/IceTargetLoweringX8632Traits.h

Issue 1216933015: X8632 Templatization completed. (Closed) Base URL: https://chromium.googlesource.com/native_client/pnacl-subzero.git@master
Patch Set: Eliminates all references to X8632 from Impl files. Created 5 years, 5 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
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
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
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
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
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698