xref: /aosp_15_r20/external/swiftshader/third_party/subzero/src/IceInstX8632.cpp (revision 03ce13f70fcc45d86ee91b7ee4cab1936a95046e)
1 //===- subzero/src/IceInstX8632.cpp - X86-32 instruction implementation ---===//
2 //
3 //                        The Subzero Code Generator
4 //
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
7 //
8 //===----------------------------------------------------------------------===//
9 ///
10 /// \file
11 /// \brief Defines X8632 specific data related to X8632 Instructions.
12 ///
13 //===----------------------------------------------------------------------===//
14 
15 #include "IceInstX8632.h"
16 
17 #include "IceAssemblerX8632.h"
18 #include "IceCfg.h"
19 #include "IceCfgNode.h"
20 #include "IceConditionCodesX86.h"
21 #include "IceDefs.h"
22 #include "IceInst.h"
23 #include "IceInstX8632.def"
24 #include "IceOperand.h"
25 #include "IceRegistersX8632.h"
26 #include "IceTargetLowering.h"
27 #include "IceTargetLoweringX8632.h"
28 
29 namespace Ice {
30 namespace X8632 {
31 
32 struct InstBrAttributesType {
33   CondX86::BrCond Opposite;
34   const char *const DisplayString;
35   const char *const EmitString;
36 };
37 
38 struct InstCmppsAttributesType {
39   const char *const EmitString;
40 };
41 
42 struct TypeAttributesType {
43   const Type InVectorElementType;
44   const char *const CvtString;      // i (integer), s (single FP), d (double FP)
45   const char *const SdSsString;     // ss, sd, or <blank>
46   const char *const PdPsString;     // ps, pd, or <blank>
47   const char *const SpSdString;     // ss, sd, ps, pd, or <blank>
48   const char *const IntegralString; // b, w, d, or <blank>
49   const char *const UnpackString;   // bw, wd, dq, or <blank>
50   const char *const PackString;     // wb, dw, or <blank>
51   const char *const WidthString;    // b, w, l, q, or <blank>
52   const char *const FldString;      // s, l, or <blank>
53 };
54 
55 constexpr InstBrAttributesType InstBrAttributes[] = {
56 #define X(val, encode, opp, dump, emit) {CondX86::opp, dump, emit},
57     ICEINSTX86BR_TABLE
58 #undef X
59 };
60 
61 constexpr InstCmppsAttributesType InstCmppsAttributes[] = {
62 #define X(val, emit) {emit},
63     ICEINSTX86CMPPS_TABLE
64 #undef X
65 };
66 
67 constexpr TypeAttributesType TypeAttributes[] = {
68 #define X(tag, elty, cvt, sdss, pdps, spsd, int_, unpack, pack, width, fld)    \
69   {IceType_##elty, cvt, sdss, pdps, spsd, int_, unpack, pack, width, fld},
70     ICETYPEX86_TABLE
71 #undef X
72 };
73 
74 constexpr const char *InstSegmentRegNames[] = {
75 #define X(val, name, prefix) name,
76     SEG_REGX8632_TABLE
77 #undef X
78 };
79 
80 constexpr uint8_t InstSegmentPrefixes[] = {
81 #define X(val, name, prefix) prefix,
82     SEG_REGX8632_TABLE
83 #undef X
84 };
85 
getWidthString(Type Ty)86 const char *InstX86Base::getWidthString(Type Ty) {
87   return TypeAttributes[Ty].WidthString;
88 }
89 
getFldString(Type Ty)90 const char *InstX86Base::getFldString(Type Ty) {
91   return TypeAttributes[Ty].FldString;
92 }
93 
getSseSuffixString(Type DestTy,SseSuffix Suffix)94 const char *InstX86Base::getSseSuffixString(Type DestTy, SseSuffix Suffix) {
95   switch (Suffix) {
96   default:
97   case InstX86Base::SseSuffix::None:
98     return "";
99   case InstX86Base::SseSuffix::Packed:
100     return TypeAttributes[DestTy].PdPsString;
101   case InstX86Base::SseSuffix::Unpack:
102     return TypeAttributes[DestTy].UnpackString;
103   case InstX86Base::SseSuffix::Scalar:
104     return TypeAttributes[DestTy].SdSsString;
105   case InstX86Base::SseSuffix::Integral:
106     return TypeAttributes[DestTy].IntegralString;
107   case InstX86Base::SseSuffix::Pack:
108     return TypeAttributes[DestTy].PackString;
109   }
110 }
111 
112 /// Return the type which the elements of the vector have in the X86
113 /// representation of the vector.
getInVectorElementType(Type Ty)114 Type InstX86Base::getInVectorElementType(Type Ty) {
115   assert(isVectorType(Ty));
116   assert(static_cast<size_t>(Ty) < std::size(TypeAttributes));
117   return TypeAttributes[Ty].InVectorElementType;
118 }
119 
getOppositeCondition(BrCond Cond)120 Cond::BrCond InstX86Base::getOppositeCondition(BrCond Cond) {
121   return InstBrAttributes[Cond].Opposite;
122 }
123 
InstX86FakeRMW(Cfg * Func,Operand * Data,Operand * Addr,InstArithmetic::OpKind Op,Variable * Beacon)124 InstX86FakeRMW::InstX86FakeRMW(Cfg *Func, Operand *Data, Operand *Addr,
125                                InstArithmetic::OpKind Op, Variable *Beacon)
126     : InstX86Base(Func, InstX86Base::FakeRMW, 3, nullptr), Op(Op) {
127   this->addSource(Data);
128   this->addSource(Addr);
129   this->addSource(Beacon);
130 }
131 
InstX86Mul(Cfg * Func,Variable * Dest,Variable * Source1,Operand * Source2)132 InstX86Mul::InstX86Mul(Cfg *Func, Variable *Dest, Variable *Source1,
133                        Operand *Source2)
134     : InstX86Base(Func, InstX86Base::Mul, 2, Dest) {
135   this->addSource(Source1);
136   this->addSource(Source2);
137 }
138 
InstX86Shld(Cfg * Func,Variable * Dest,Variable * Source1,Operand * Source2)139 InstX86Shld::InstX86Shld(Cfg *Func, Variable *Dest, Variable *Source1,
140                          Operand *Source2)
141     : InstX86Base(Func, InstX86Base::Shld, 3, Dest) {
142   this->addSource(Dest);
143   this->addSource(Source1);
144   this->addSource(Source2);
145 }
146 
InstX86Shrd(Cfg * Func,Variable * Dest,Variable * Source1,Operand * Source2)147 InstX86Shrd::InstX86Shrd(Cfg *Func, Variable *Dest, Variable *Source1,
148                          Operand *Source2)
149     : InstX86Base(Func, InstX86Base::Shrd, 3, Dest) {
150   this->addSource(Dest);
151   this->addSource(Source1);
152   this->addSource(Source2);
153 }
154 
InstX86Label(Cfg * Func,TargetLowering * Target)155 InstX86Label::InstX86Label(Cfg *Func, TargetLowering *Target)
156     : InstX86Base(Func, InstX86Base::Label, 0, nullptr),
157       LabelNumber(Target->makeNextLabelNumber()) {
158   if (BuildDefs::dump()) {
159     Name = GlobalString::createWithString(
160         Func->getContext(), ".L" + Func->getFunctionName() + "$local$__" +
161                                 std::to_string(LabelNumber));
162   } else {
163     Name = GlobalString::createWithoutString(Func->getContext());
164   }
165 }
166 
InstX86Br(Cfg * Func,const CfgNode * TargetTrue,const CfgNode * TargetFalse,const InstX86Label * Label,BrCond Condition,Mode Kind)167 InstX86Br::InstX86Br(Cfg *Func, const CfgNode *TargetTrue,
168                      const CfgNode *TargetFalse, const InstX86Label *Label,
169                      BrCond Condition, Mode Kind)
170     : InstX86Base(Func, InstX86Base::Br, 0, nullptr), Condition(Condition),
171       TargetTrue(TargetTrue), TargetFalse(TargetFalse), Label(Label),
172       Kind(Kind) {}
173 
optimizeBranch(const CfgNode * NextNode)174 bool InstX86Br::optimizeBranch(const CfgNode *NextNode) {
175   // If there is no next block, then there can be no fallthrough to optimize.
176   if (NextNode == nullptr)
177     return false;
178   // Intra-block conditional branches can't be optimized.
179   if (Label)
180     return false;
181   // If there is no fallthrough node, such as a non-default case label for a
182   // switch instruction, then there is no opportunity to optimize.
183   if (getTargetFalse() == nullptr)
184     return false;
185 
186   // Unconditional branch to the next node can be removed.
187   if (Condition == Cond::Br_None && getTargetFalse() == NextNode) {
188     assert(getTargetTrue() == nullptr);
189     this->setDeleted();
190     return true;
191   }
192   // If the fallthrough is to the next node, set fallthrough to nullptr to
193   // indicate.
194   if (getTargetFalse() == NextNode) {
195     TargetFalse = nullptr;
196     return true;
197   }
198   // If TargetTrue is the next node, and TargetFalse is not nullptr (which was
199   // already tested above), then invert the branch condition, swap the targets,
200   // and set new fallthrough to nullptr.
201   if (getTargetTrue() == NextNode) {
202     assert(Condition != Cond::Br_None);
203     Condition = this->getOppositeCondition(Condition);
204     TargetTrue = getTargetFalse();
205     TargetFalse = nullptr;
206     return true;
207   }
208   return false;
209 }
210 
repointEdges(CfgNode * OldNode,CfgNode * NewNode)211 bool InstX86Br::repointEdges(CfgNode *OldNode, CfgNode *NewNode) {
212   bool Found = false;
213   if (TargetFalse == OldNode) {
214     TargetFalse = NewNode;
215     Found = true;
216   }
217   if (TargetTrue == OldNode) {
218     TargetTrue = NewNode;
219     Found = true;
220   }
221   return Found;
222 }
223 
InstX86Jmp(Cfg * Func,Operand * Target)224 InstX86Jmp::InstX86Jmp(Cfg *Func, Operand *Target)
225     : InstX86Base(Func, InstX86Base::Jmp, 1, nullptr) {
226   this->addSource(Target);
227 }
228 
InstX86Call(Cfg * Func,Variable * Dest,Operand * CallTarget)229 InstX86Call::InstX86Call(Cfg *Func, Variable *Dest, Operand *CallTarget)
230     : InstX86Base(Func, InstX86Base::Call, 1, Dest) {
231   this->HasSideEffects = true;
232   this->addSource(CallTarget);
233 }
234 
InstX86Movmsk(Cfg * Func,Variable * Dest,Operand * Source)235 InstX86Movmsk::InstX86Movmsk(Cfg *Func, Variable *Dest, Operand *Source)
236     : InstX86Base(Func, InstX86Base::Movmsk, 1, Dest) {
237   this->addSource(Source);
238 }
239 
InstX86Cmov(Cfg * Func,Variable * Dest,Operand * Source,BrCond Condition)240 InstX86Cmov::InstX86Cmov(Cfg *Func, Variable *Dest, Operand *Source,
241                          BrCond Condition)
242     : InstX86Base(Func, InstX86Base::Cmov, 2, Dest), Condition(Condition) {
243   // The final result is either the original Dest, or Source, so mark both as
244   // sources.
245   this->addSource(Dest);
246   this->addSource(Source);
247 }
248 
InstX86Cmpps(Cfg * Func,Variable * Dest,Operand * Source,CmppsCond Condition)249 InstX86Cmpps::InstX86Cmpps(Cfg *Func, Variable *Dest, Operand *Source,
250                            CmppsCond Condition)
251     : InstX86Base(Func, InstX86Base::Cmpps, 2, Dest), Condition(Condition) {
252   this->addSource(Dest);
253   this->addSource(Source);
254 }
255 
InstX86Cmpxchg(Cfg * Func,Operand * DestOrAddr,Variable * Eax,Variable * Desired,bool Locked)256 InstX86Cmpxchg::InstX86Cmpxchg(Cfg *Func, Operand *DestOrAddr, Variable *Eax,
257                                Variable *Desired, bool Locked)
258     : InstX86BaseLockable(Func, InstX86Base::Cmpxchg, 3,
259                           llvm::dyn_cast<Variable>(DestOrAddr), Locked) {
260   constexpr uint16_t Encoded_rAX = 0;
261   (void)Encoded_rAX;
262   assert(RegX8632::getEncodedGPR(Eax->getRegNum()) == Encoded_rAX);
263   this->addSource(DestOrAddr);
264   this->addSource(Eax);
265   this->addSource(Desired);
266 }
267 
InstX86Cmpxchg8b(Cfg * Func,X86OperandMem * Addr,Variable * Edx,Variable * Eax,Variable * Ecx,Variable * Ebx,bool Locked)268 InstX86Cmpxchg8b::InstX86Cmpxchg8b(Cfg *Func, X86OperandMem *Addr,
269                                    Variable *Edx, Variable *Eax, Variable *Ecx,
270                                    Variable *Ebx, bool Locked)
271     : InstX86BaseLockable(Func, InstX86Base::Cmpxchg, 5, nullptr, Locked) {
272   assert(Edx->getRegNum() == RegisterSet::Reg_edx);
273   assert(Eax->getRegNum() == RegisterSet::Reg_eax);
274   assert(Ecx->getRegNum() == RegisterSet::Reg_ecx);
275   assert(Ebx->getRegNum() == RegisterSet::Reg_ebx);
276   this->addSource(Addr);
277   this->addSource(Edx);
278   this->addSource(Eax);
279   this->addSource(Ecx);
280   this->addSource(Ebx);
281 }
282 
InstX86Cvt(Cfg * Func,Variable * Dest,Operand * Source,CvtVariant Variant)283 InstX86Cvt::InstX86Cvt(Cfg *Func, Variable *Dest, Operand *Source,
284                        CvtVariant Variant)
285     : InstX86Base(Func, InstX86Base::Cvt, 1, Dest), Variant(Variant) {
286   this->addSource(Source);
287 }
288 
InstX86Icmp(Cfg * Func,Operand * Src0,Operand * Src1)289 InstX86Icmp::InstX86Icmp(Cfg *Func, Operand *Src0, Operand *Src1)
290     : InstX86Base(Func, InstX86Base::Icmp, 2, nullptr) {
291   this->addSource(Src0);
292   this->addSource(Src1);
293 }
294 
InstX86Ucomiss(Cfg * Func,Operand * Src0,Operand * Src1)295 InstX86Ucomiss::InstX86Ucomiss(Cfg *Func, Operand *Src0, Operand *Src1)
296     : InstX86Base(Func, InstX86Base::Ucomiss, 2, nullptr) {
297   this->addSource(Src0);
298   this->addSource(Src1);
299 }
300 
InstX86UD2(Cfg * Func)301 InstX86UD2::InstX86UD2(Cfg *Func)
302     : InstX86Base(Func, InstX86Base::UD2, 0, nullptr) {}
303 
InstX86Int3(Cfg * Func)304 InstX86Int3::InstX86Int3(Cfg *Func)
305     : InstX86Base(Func, InstX86Base::Int3, 0, nullptr) {}
306 
InstX86Test(Cfg * Func,Operand * Src1,Operand * Src2)307 InstX86Test::InstX86Test(Cfg *Func, Operand *Src1, Operand *Src2)
308     : InstX86Base(Func, InstX86Base::Test, 2, nullptr) {
309   this->addSource(Src1);
310   this->addSource(Src2);
311 }
312 
InstX86Mfence(Cfg * Func)313 InstX86Mfence::InstX86Mfence(Cfg *Func)
314     : InstX86Base(Func, InstX86Base::Mfence, 0, nullptr) {
315   this->HasSideEffects = true;
316 }
317 
InstX86Store(Cfg * Func,Operand * Value,X86Operand * Mem)318 InstX86Store::InstX86Store(Cfg *Func, Operand *Value, X86Operand *Mem)
319     : InstX86Base(Func, InstX86Base::Store, 2, nullptr) {
320   this->addSource(Value);
321   this->addSource(Mem);
322 }
323 
InstX86StoreP(Cfg * Func,Variable * Value,X86OperandMem * Mem)324 InstX86StoreP::InstX86StoreP(Cfg *Func, Variable *Value, X86OperandMem *Mem)
325     : InstX86Base(Func, InstX86Base::StoreP, 2, nullptr) {
326   this->addSource(Value);
327   this->addSource(Mem);
328 }
329 
InstX86StoreQ(Cfg * Func,Operand * Value,X86OperandMem * Mem)330 InstX86StoreQ::InstX86StoreQ(Cfg *Func, Operand *Value, X86OperandMem *Mem)
331     : InstX86Base(Func, InstX86Base::StoreQ, 2, nullptr) {
332   this->addSource(Value);
333   this->addSource(Mem);
334 }
335 
InstX86StoreD(Cfg * Func,Operand * Value,X86OperandMem * Mem)336 InstX86StoreD::InstX86StoreD(Cfg *Func, Operand *Value, X86OperandMem *Mem)
337     : InstX86Base(Func, InstX86Base::StoreD, 2, nullptr) {
338   this->addSource(Value);
339   this->addSource(Mem);
340 }
341 
InstX86Nop(Cfg * Func,NopVariant Variant)342 InstX86Nop::InstX86Nop(Cfg *Func, NopVariant Variant)
343     : InstX86Base(Func, InstX86Base::Nop, 0, nullptr), Variant(Variant) {}
344 
InstX86Fld(Cfg * Func,Operand * Src)345 InstX86Fld::InstX86Fld(Cfg *Func, Operand *Src)
346     : InstX86Base(Func, InstX86Base::Fld, 1, nullptr) {
347   this->addSource(Src);
348 }
349 
InstX86Fstp(Cfg * Func,Variable * Dest)350 InstX86Fstp::InstX86Fstp(Cfg *Func, Variable *Dest)
351     : InstX86Base(Func, InstX86Base::Fstp, 0, Dest) {}
352 
InstX86Pop(Cfg * Func,Variable * Dest)353 InstX86Pop::InstX86Pop(Cfg *Func, Variable *Dest)
354     : InstX86Base(Func, InstX86Base::Pop, 0, Dest) {
355   // A pop instruction affects the stack pointer and so it should not be
356   // allowed to be automatically dead-code eliminated. (The corresponding push
357   // instruction doesn't need this treatment because it has no dest variable
358   // and therefore won't be dead-code eliminated.) This is needed for
359   // late-stage liveness analysis (e.g. asm-verbose mode).
360   this->HasSideEffects = true;
361 }
362 
InstX86Push(Cfg * Func,Operand * Source)363 InstX86Push::InstX86Push(Cfg *Func, Operand *Source)
364     : InstX86Base(Func, InstX86Base::Push, 1, nullptr) {
365   this->addSource(Source);
366 }
367 
InstX86Ret(Cfg * Func,Variable * Source)368 InstX86Ret::InstX86Ret(Cfg *Func, Variable *Source)
369     : InstX86Base(Func, InstX86Base::Ret, Source ? 1 : 0, nullptr) {
370   if (Source)
371     this->addSource(Source);
372 }
373 
InstX86Setcc(Cfg * Func,Variable * Dest,BrCond Cond)374 InstX86Setcc::InstX86Setcc(Cfg *Func, Variable *Dest, BrCond Cond)
375     : InstX86Base(Func, InstX86Base::Setcc, 0, Dest), Condition(Cond) {}
376 
InstX86Xadd(Cfg * Func,Operand * Dest,Variable * Source,bool Locked)377 InstX86Xadd::InstX86Xadd(Cfg *Func, Operand *Dest, Variable *Source,
378                          bool Locked)
379     : InstX86BaseLockable(Func, InstX86Base::Xadd, 2,
380                           llvm::dyn_cast<Variable>(Dest), Locked) {
381   this->addSource(Dest);
382   this->addSource(Source);
383 }
384 
InstX86Xchg(Cfg * Func,Operand * Dest,Variable * Source)385 InstX86Xchg::InstX86Xchg(Cfg *Func, Operand *Dest, Variable *Source)
386     : InstX86Base(Func, InstX86Base::Xchg, 2, llvm::dyn_cast<Variable>(Dest)) {
387   this->addSource(Dest);
388   this->addSource(Source);
389 }
390 
InstX86IacaStart(Cfg * Func)391 InstX86IacaStart::InstX86IacaStart(Cfg *Func)
392     : InstX86Base(Func, InstX86Base::IacaStart, 0, nullptr) {
393   assert(getFlags().getAllowIacaMarks());
394 }
395 
InstX86IacaEnd(Cfg * Func)396 InstX86IacaEnd::InstX86IacaEnd(Cfg *Func)
397     : InstX86Base(Func, InstX86Base::IacaEnd, 0, nullptr) {
398   assert(getFlags().getAllowIacaMarks());
399 }
400 
401 // ======================== Dump routines ======================== //
402 
dump(const Cfg * Func) const403 void InstX86Base::dump(const Cfg *Func) const {
404   if (!BuildDefs::dump())
405     return;
406   Ostream &Str = Func->getContext()->getStrDump();
407   Str << "[X8632] ";
408   Inst::dump(Func);
409 }
410 
dump(const Cfg * Func) const411 void InstX86FakeRMW::dump(const Cfg *Func) const {
412   if (!BuildDefs::dump())
413     return;
414   Ostream &Str = Func->getContext()->getStrDump();
415   Type Ty = getData()->getType();
416   Str << "rmw " << InstArithmetic::getOpName(getOp()) << " " << Ty << " *";
417   getAddr()->dump(Func);
418   Str << ", ";
419   getData()->dump(Func);
420   Str << ", beacon=";
421   getBeacon()->dump(Func);
422 }
423 
emit(const Cfg * Func) const424 void InstX86Label::emit(const Cfg *Func) const {
425   if (!BuildDefs::dump())
426     return;
427   Ostream &Str = Func->getContext()->getStrEmit();
428   Str << getLabelName() << ":";
429 }
430 
emitIAS(const Cfg * Func) const431 void InstX86Label::emitIAS(const Cfg *Func) const {
432   Assembler *Asm = Func->getAssembler<Assembler>();
433   Asm->bindLocalLabel(LabelNumber);
434   if (OffsetReloc != nullptr) {
435     Asm->bindRelocOffset(OffsetReloc);
436   }
437 }
438 
dump(const Cfg * Func) const439 void InstX86Label::dump(const Cfg *Func) const {
440   if (!BuildDefs::dump())
441     return;
442   Ostream &Str = Func->getContext()->getStrDump();
443   Str << getLabelName() << ":";
444 }
445 
emit(const Cfg * Func) const446 void InstX86Br::emit(const Cfg *Func) const {
447   if (!BuildDefs::dump())
448     return;
449   Ostream &Str = Func->getContext()->getStrEmit();
450   Str << "\t";
451 
452   if (Condition == Cond::Br_None) {
453     Str << "jmp";
454   } else {
455     Str << InstBrAttributes[Condition].EmitString;
456   }
457 
458   if (Label) {
459     Str << "\t" << Label->getLabelName();
460   } else {
461     if (Condition == Cond::Br_None) {
462       Str << "\t" << getTargetFalse()->getAsmName();
463     } else {
464       Str << "\t" << getTargetTrue()->getAsmName();
465       if (getTargetFalse()) {
466         Str << "\n\t"
467                "jmp\t"
468             << getTargetFalse()->getAsmName();
469       }
470     }
471   }
472 }
473 
emitIAS(const Cfg * Func) const474 void InstX86Br::emitIAS(const Cfg *Func) const {
475   Assembler *Asm = Func->getAssembler<Assembler>();
476   if (Label) {
477     auto *L = Asm->getOrCreateLocalLabel(Label->getLabelNumber());
478     if (Condition == Cond::Br_None) {
479       Asm->jmp(L, isNear());
480     } else {
481       Asm->j(Condition, L, isNear());
482     }
483   } else {
484     if (Condition == Cond::Br_None) {
485       auto *L = Asm->getOrCreateCfgNodeLabel(getTargetFalse()->getIndex());
486       assert(!getTargetTrue());
487       Asm->jmp(L, isNear());
488     } else {
489       auto *L = Asm->getOrCreateCfgNodeLabel(getTargetTrue()->getIndex());
490       Asm->j(Condition, L, isNear());
491       if (getTargetFalse()) {
492         auto *L2 = Asm->getOrCreateCfgNodeLabel(getTargetFalse()->getIndex());
493         Asm->jmp(L2, isNear());
494       }
495     }
496   }
497 }
498 
dump(const Cfg * Func) const499 void InstX86Br::dump(const Cfg *Func) const {
500   if (!BuildDefs::dump())
501     return;
502   Ostream &Str = Func->getContext()->getStrDump();
503   Str << "br ";
504 
505   if (Condition == Cond::Br_None) {
506     if (Label) {
507       Str << "label %" << Label->getLabelName();
508     } else {
509       Str << "label %" << getTargetFalse()->getName();
510     }
511     return;
512   }
513 
514   Str << InstBrAttributes[Condition].DisplayString;
515   if (Label) {
516     Str << ", label %" << Label->getLabelName();
517   } else {
518     Str << ", label %" << getTargetTrue()->getName();
519     if (getTargetFalse()) {
520       Str << ", label %" << getTargetFalse()->getName();
521     }
522   }
523 
524   Str << " // (" << (isNear() ? "near" : "far") << " jump)";
525 }
526 
emit(const Cfg * Func) const527 void InstX86Jmp::emit(const Cfg *Func) const {
528   if (!BuildDefs::dump())
529     return;
530   Ostream &Str = Func->getContext()->getStrEmit();
531   assert(this->getSrcSize() == 1);
532   const Operand *Src = this->getSrc(0);
533   Str << "\t"
534          "jmp"
535          "\t*";
536   getJmpTarget()->emit(Func);
537 }
538 
emitIAS(const Cfg * Func) const539 void InstX86Jmp::emitIAS(const Cfg *Func) const {
540   // Note: Adapted (mostly copied) from
541   // InstX86Call::emitIAS().
542   Assembler *Asm = Func->getAssembler<Assembler>();
543   Operand *Target = getJmpTarget();
544   if (const auto *Var = llvm::dyn_cast<Variable>(Target)) {
545     if (Var->hasReg()) {
546       Asm->jmp(RegX8632::getEncodedGPR(Var->getRegNum()));
547     } else {
548       // The jmp instruction with a memory operand should be possible to
549       // encode, but it isn't a valid sandboxed instruction, and there
550       // shouldn't be a register allocation issue to jump through a scratch
551       // register, so we don't really need to bother implementing it.
552       llvm::report_fatal_error("Assembler can't jmp to memory operand");
553     }
554   } else if (const auto *Mem = llvm::dyn_cast<X86OperandMem>(Target)) {
555     (void)Mem;
556     assert(Mem->getSegmentRegister() == X86OperandMem::DefaultSegment);
557     llvm::report_fatal_error("Assembler can't jmp to memory operand");
558   } else if (const auto *CR = llvm::dyn_cast<ConstantRelocatable>(Target)) {
559     Asm->jmp(CR);
560   } else if (const auto *Imm = llvm::dyn_cast<ConstantInteger32>(Target)) {
561     // NaCl trampoline calls refer to an address within the sandbox directly.
562     // This is usually only needed for non-IRT builds and otherwise not very
563     // portable or stable. Usually this is only done for "calls" and not jumps.
564     Asm->jmp(AssemblerImmediate(Imm->getValue()));
565   } else {
566     llvm::report_fatal_error("Unexpected operand type");
567   }
568 }
569 
dump(const Cfg * Func) const570 void InstX86Jmp::dump(const Cfg *Func) const {
571   if (!BuildDefs::dump())
572     return;
573   Ostream &Str = Func->getContext()->getStrDump();
574   Str << "jmp ";
575   getJmpTarget()->dump(Func);
576 }
577 
emit(const Cfg * Func) const578 void InstX86Call::emit(const Cfg *Func) const {
579   if (!BuildDefs::dump())
580     return;
581   Ostream &Str = Func->getContext()->getStrEmit();
582   assert(this->getSrcSize() == 1);
583   Str << "\t"
584          "call\t";
585   Operand *CallTarget = getCallTarget();
586   auto *Target = InstX86Base::getTarget(Func);
587   if (const auto *CI = llvm::dyn_cast<ConstantInteger32>(CallTarget)) {
588     // Emit without a leading '$'.
589     Str << CI->getValue();
590   } else if (const auto DirectCallTarget =
591                  llvm::dyn_cast<ConstantRelocatable>(CallTarget)) {
592     DirectCallTarget->emitWithoutPrefix(Target);
593   } else {
594     Str << "*";
595     CallTarget->emit(Func);
596   }
597 }
598 
emitIAS(const Cfg * Func) const599 void InstX86Call::emitIAS(const Cfg *Func) const {
600   Assembler *Asm = Func->getAssembler<Assembler>();
601   Operand *CallTarget = getCallTarget();
602   auto *Target = InstX86Base::getTarget(Func);
603   if (const auto *Var = llvm::dyn_cast<Variable>(CallTarget)) {
604     if (Var->hasReg()) {
605       Asm->call(RegX8632::getEncodedGPR(Var->getRegNum()));
606     } else {
607       Asm->call(AsmAddress(Var, Target));
608     }
609   } else if (const auto *Mem = llvm::dyn_cast<X86OperandMem>(CallTarget)) {
610     assert(Mem->getSegmentRegister() == X86OperandMem::DefaultSegment);
611     Asm->call(AsmAddress(Mem, Asm, Target));
612   } else if (const auto *CR = llvm::dyn_cast<ConstantRelocatable>(CallTarget)) {
613     Asm->call(CR);
614   } else if (const auto *Imm = llvm::dyn_cast<ConstantInteger32>(CallTarget)) {
615     Asm->call(AssemblerImmediate(Imm->getValue()));
616   } else {
617     llvm_unreachable("Unexpected operand type");
618   }
619 }
620 
dump(const Cfg * Func) const621 void InstX86Call::dump(const Cfg *Func) const {
622   if (!BuildDefs::dump())
623     return;
624   Ostream &Str = Func->getContext()->getStrDump();
625   if (this->getDest()) {
626     this->dumpDest(Func);
627     Str << " = ";
628   }
629   Str << "call ";
630   getCallTarget()->dump(Func);
631 }
632 
633 // The this->Opcode parameter needs to be char* and not std::string because of
634 // template issues.
635 
emitTwoAddress(const Cfg * Func,const char * Opcode,const char * Suffix) const636 void InstX86Base::emitTwoAddress(const Cfg *Func, const char *Opcode,
637                                  const char *Suffix) const {
638   if (!BuildDefs::dump())
639     return;
640   Ostream &Str = Func->getContext()->getStrEmit();
641   assert(getSrcSize() == 2);
642   Operand *Dest = getDest();
643   if (Dest == nullptr)
644     Dest = getSrc(0);
645   assert(Dest == getSrc(0));
646   Operand *Src1 = getSrc(1);
647   Str << "\t" << Opcode << Suffix
648       << InstX86Base::getWidthString(Dest->getType()) << "\t";
649   Src1->emit(Func);
650   Str << ", ";
651   Dest->emit(Func);
652 }
653 
emitIASOpTyGPR(const Cfg * Func,Type Ty,const Operand * Op,const GPREmitterOneOp & Emitter)654 void emitIASOpTyGPR(const Cfg *Func, Type Ty, const Operand *Op,
655                     const GPREmitterOneOp &Emitter) {
656   auto *Target = InstX86Base::getTarget(Func);
657   Assembler *Asm = Func->getAssembler<Assembler>();
658   if (const auto *Var = llvm::dyn_cast<Variable>(Op)) {
659     if (Var->hasReg()) {
660       // We cheat a little and use GPRRegister even for byte operations.
661       GPRRegister VarReg = RegX8632::getEncodedGPR(Var->getRegNum());
662       (Asm->*(Emitter.Reg))(Ty, VarReg);
663     } else {
664       AsmAddress StackAddr(AsmAddress(Var, Target));
665       (Asm->*(Emitter.Addr))(Ty, StackAddr);
666     }
667   } else if (const auto *Mem = llvm::dyn_cast<X86OperandMem>(Op)) {
668     Mem->emitSegmentOverride(Asm);
669     (Asm->*(Emitter.Addr))(Ty, AsmAddress(Mem, Asm, Target));
670   } else {
671     llvm_unreachable("Unexpected operand type");
672   }
673 }
674 
675 template <bool VarCanBeByte, bool SrcCanBeByte>
emitIASRegOpTyGPR(const Cfg * Func,Type Ty,const Variable * Var,const Operand * Src,const GPREmitterRegOp & Emitter)676 void emitIASRegOpTyGPR(const Cfg *Func, Type Ty, const Variable *Var,
677                        const Operand *Src, const GPREmitterRegOp &Emitter) {
678   auto *Target = InstX86Base::getTarget(Func);
679   Assembler *Asm = Func->getAssembler<Assembler>();
680   assert(Var->hasReg());
681   // We cheat a little and use GPRRegister even for byte operations.
682   GPRRegister VarReg = VarCanBeByte ? RegX8632::getEncodedGPR(Var->getRegNum())
683                                     : RegX8632::getEncodedGPR(Var->getRegNum());
684   if (const auto *SrcVar = llvm::dyn_cast<Variable>(Src)) {
685     if (SrcVar->hasReg()) {
686       GPRRegister SrcReg = SrcCanBeByte
687                                ? RegX8632::getEncodedGPR(SrcVar->getRegNum())
688                                : RegX8632::getEncodedGPR(SrcVar->getRegNum());
689       (Asm->*(Emitter.GPRGPR))(Ty, VarReg, SrcReg);
690     } else {
691       AsmAddress SrcStackAddr = AsmAddress(SrcVar, Target);
692       (Asm->*(Emitter.GPRAddr))(Ty, VarReg, SrcStackAddr);
693     }
694   } else if (const auto *Mem = llvm::dyn_cast<X86OperandMem>(Src)) {
695     Mem->emitSegmentOverride(Asm);
696     (Asm->*(Emitter.GPRAddr))(Ty, VarReg, AsmAddress(Mem, Asm, Target));
697   } else if (const auto *Imm = llvm::dyn_cast<ConstantInteger32>(Src)) {
698     (Asm->*(Emitter.GPRImm))(Ty, VarReg, AssemblerImmediate(Imm->getValue()));
699   } else if (const auto *Reloc = llvm::dyn_cast<ConstantRelocatable>(Src)) {
700     const auto FixupKind = (Reloc->getName().hasStdString() &&
701                             Reloc->getName().toString() == GlobalOffsetTable)
702                                ? FK_GotPC
703                                : FK_Abs;
704     AssemblerFixup *Fixup = Asm->createFixup(FixupKind, Reloc);
705     (Asm->*(Emitter.GPRImm))(Ty, VarReg, AssemblerImmediate(Fixup));
706   } else if (const auto *Split = llvm::dyn_cast<VariableSplit>(Src)) {
707     (Asm->*(Emitter.GPRAddr))(Ty, VarReg, AsmAddress(Split, Func));
708   } else {
709     llvm_unreachable("Unexpected operand type");
710   }
711 }
712 
713 template void emitIASRegOpTyGPR<true, true>(const Cfg *Func, Type Ty,
714                                             const Variable *Var,
715                                             const Operand *Src,
716                                             const GPREmitterRegOp &Emitter);
717 
emitIASAddrOpTyGPR(const Cfg * Func,Type Ty,const AsmAddress & Addr,const Operand * Src,const GPREmitterAddrOp & Emitter)718 void emitIASAddrOpTyGPR(const Cfg *Func, Type Ty, const AsmAddress &Addr,
719                         const Operand *Src, const GPREmitterAddrOp &Emitter) {
720   Assembler *Asm = Func->getAssembler<Assembler>();
721   // Src can only be Reg or AssemblerImmediate.
722   if (const auto *SrcVar = llvm::dyn_cast<Variable>(Src)) {
723     assert(SrcVar->hasReg());
724     GPRRegister SrcReg = RegX8632::getEncodedGPR(SrcVar->getRegNum());
725     (Asm->*(Emitter.AddrGPR))(Ty, Addr, SrcReg);
726   } else if (const auto *Imm = llvm::dyn_cast<ConstantInteger32>(Src)) {
727     (Asm->*(Emitter.AddrImm))(Ty, Addr, AssemblerImmediate(Imm->getValue()));
728   } else if (const auto *Reloc = llvm::dyn_cast<ConstantRelocatable>(Src)) {
729     const auto FixupKind = (Reloc->getName().hasStdString() &&
730                             Reloc->getName().toString() == GlobalOffsetTable)
731                                ? FK_GotPC
732                                : FK_Abs;
733     AssemblerFixup *Fixup = Asm->createFixup(FixupKind, Reloc);
734     (Asm->*(Emitter.AddrImm))(Ty, Addr, AssemblerImmediate(Fixup));
735   } else {
736     llvm_unreachable("Unexpected operand type");
737   }
738 }
739 
emitIASAsAddrOpTyGPR(const Cfg * Func,Type Ty,const Operand * Op0,const Operand * Op1,const GPREmitterAddrOp & Emitter)740 void emitIASAsAddrOpTyGPR(const Cfg *Func, Type Ty, const Operand *Op0,
741                           const Operand *Op1, const GPREmitterAddrOp &Emitter) {
742   auto *Target = InstX86Base::getTarget(Func);
743   if (const auto *Op0Var = llvm::dyn_cast<Variable>(Op0)) {
744     assert(!Op0Var->hasReg());
745     AsmAddress StackAddr(AsmAddress(Op0Var, Target));
746     emitIASAddrOpTyGPR(Func, Ty, StackAddr, Op1, Emitter);
747   } else if (const auto *Op0Mem = llvm::dyn_cast<X86OperandMem>(Op0)) {
748     Assembler *Asm = Func->getAssembler<Assembler>();
749     Op0Mem->emitSegmentOverride(Asm);
750     emitIASAddrOpTyGPR(Func, Ty, AsmAddress(Op0Mem, Asm, Target), Op1, Emitter);
751   } else if (const auto *Split = llvm::dyn_cast<VariableSplit>(Op0)) {
752     emitIASAddrOpTyGPR(Func, Ty, AsmAddress(Split, Func), Op1, Emitter);
753   } else {
754     llvm_unreachable("Unexpected operand type");
755   }
756 }
757 
emitIASGPRShift(const Cfg * Func,Type Ty,const Variable * Var,const Operand * Src,const GPREmitterShiftOp & Emitter)758 void emitIASGPRShift(const Cfg *Func, Type Ty, const Variable *Var,
759                      const Operand *Src, const GPREmitterShiftOp &Emitter) {
760   Assembler *Asm = Func->getAssembler<Assembler>();
761   // Technically, the Dest Var can be mem as well, but we only use Reg. We can
762   // extend this to check Dest if we decide to use that form.
763   assert(Var->hasReg());
764   // We cheat a little and use GPRRegister even for byte operations.
765   GPRRegister VarReg = RegX8632::getEncodedGPR(Var->getRegNum());
766   // Src must be reg == ECX or an Imm8. This is asserted by the assembler.
767   if (const auto *SrcVar = llvm::dyn_cast<Variable>(Src)) {
768     assert(SrcVar->hasReg());
769     GPRRegister SrcReg = RegX8632::getEncodedGPR(SrcVar->getRegNum());
770     (Asm->*(Emitter.GPRGPR))(Ty, VarReg, SrcReg);
771   } else if (const auto *Imm = llvm::dyn_cast<ConstantInteger32>(Src)) {
772     (Asm->*(Emitter.GPRImm))(Ty, VarReg, AssemblerImmediate(Imm->getValue()));
773   } else {
774     llvm_unreachable("Unexpected operand type");
775   }
776 }
777 
emitIASGPRShiftDouble(const Cfg * Func,const Variable * Dest,const Operand * Src1Op,const Operand * Src2Op,const GPREmitterShiftD & Emitter)778 void emitIASGPRShiftDouble(const Cfg *Func, const Variable *Dest,
779                            const Operand *Src1Op, const Operand *Src2Op,
780                            const GPREmitterShiftD &Emitter) {
781   Assembler *Asm = Func->getAssembler<Assembler>();
782   // Dest can be reg or mem, but we only use the reg variant.
783   assert(Dest->hasReg());
784   GPRRegister DestReg = RegX8632::getEncodedGPR(Dest->getRegNum());
785   // SrcVar1 must be reg.
786   const auto *SrcVar1 = llvm::cast<Variable>(Src1Op);
787   assert(SrcVar1->hasReg());
788   GPRRegister SrcReg = RegX8632::getEncodedGPR(SrcVar1->getRegNum());
789   Type Ty = SrcVar1->getType();
790   // Src2 can be the implicit CL register or an immediate.
791   if (const auto *Imm = llvm::dyn_cast<ConstantInteger32>(Src2Op)) {
792     (Asm->*(Emitter.GPRGPRImm))(Ty, DestReg, SrcReg,
793                                 AssemblerImmediate(Imm->getValue()));
794   } else {
795     assert(llvm::cast<Variable>(Src2Op)->getRegNum() == RegisterSet::Reg_cl);
796     (Asm->*(Emitter.GPRGPR))(Ty, DestReg, SrcReg);
797   }
798 }
799 
emitIASXmmShift(const Cfg * Func,Type Ty,const Variable * Var,const Operand * Src,const XmmEmitterShiftOp & Emitter)800 void emitIASXmmShift(const Cfg *Func, Type Ty, const Variable *Var,
801                      const Operand *Src, const XmmEmitterShiftOp &Emitter) {
802   auto *Target = InstX86Base::getTarget(Func);
803   Assembler *Asm = Func->getAssembler<Assembler>();
804   assert(Var->hasReg());
805   XmmRegister VarReg = RegX8632::getEncodedXmm(Var->getRegNum());
806   if (const auto *SrcVar = llvm::dyn_cast<Variable>(Src)) {
807     if (SrcVar->hasReg()) {
808       XmmRegister SrcReg = RegX8632::getEncodedXmm(SrcVar->getRegNum());
809       (Asm->*(Emitter.XmmXmm))(Ty, VarReg, SrcReg);
810     } else {
811       AsmAddress SrcStackAddr = AsmAddress(SrcVar, Target);
812       (Asm->*(Emitter.XmmAddr))(Ty, VarReg, SrcStackAddr);
813     }
814   } else if (const auto *Mem = llvm::dyn_cast<X86OperandMem>(Src)) {
815     assert(Mem->getSegmentRegister() == X86OperandMem::DefaultSegment);
816     (Asm->*(Emitter.XmmAddr))(Ty, VarReg, AsmAddress(Mem, Asm, Target));
817   } else if (const auto *Imm = llvm::dyn_cast<ConstantInteger32>(Src)) {
818     (Asm->*(Emitter.XmmImm))(Ty, VarReg, AssemblerImmediate(Imm->getValue()));
819   } else {
820     llvm_unreachable("Unexpected operand type");
821   }
822 }
823 
emitIASRegOpTyXMM(const Cfg * Func,Type Ty,const Variable * Var,const Operand * Src,const XmmEmitterRegOp & Emitter)824 void emitIASRegOpTyXMM(const Cfg *Func, Type Ty, const Variable *Var,
825                        const Operand *Src, const XmmEmitterRegOp &Emitter) {
826   auto *Target = InstX86Base::getTarget(Func);
827   Assembler *Asm = Func->getAssembler<Assembler>();
828   assert(Var->hasReg());
829   XmmRegister VarReg = RegX8632::getEncodedXmm(Var->getRegNum());
830   if (const auto *SrcVar = llvm::dyn_cast<Variable>(Src)) {
831     if (SrcVar->hasReg()) {
832       XmmRegister SrcReg = RegX8632::getEncodedXmm(SrcVar->getRegNum());
833       (Asm->*(Emitter.XmmXmm))(Ty, VarReg, SrcReg);
834     } else {
835       AsmAddress SrcStackAddr = AsmAddress(SrcVar, Target);
836       (Asm->*(Emitter.XmmAddr))(Ty, VarReg, SrcStackAddr);
837     }
838   } else if (const auto *Mem = llvm::dyn_cast<X86OperandMem>(Src)) {
839     assert(Mem->getSegmentRegister() == X86OperandMem::DefaultSegment);
840     (Asm->*(Emitter.XmmAddr))(Ty, VarReg, AsmAddress(Mem, Asm, Target));
841   } else if (const auto *Imm = llvm::dyn_cast<Constant>(Src)) {
842     (Asm->*(Emitter.XmmAddr))(Ty, VarReg, AsmAddress(Imm, Asm));
843   } else {
844     llvm_unreachable("Unexpected operand type");
845   }
846 }
847 
848 template <typename DReg_t, typename SReg_t, DReg_t (*destEnc)(RegNumT),
849           SReg_t (*srcEnc)(RegNumT)>
emitIASCastRegOp(const Cfg * Func,Type DestTy,const Variable * Dest,Type SrcTy,const Operand * Src,const CastEmitterRegOp<DReg_t,SReg_t> & Emitter)850 void emitIASCastRegOp(const Cfg *Func, Type DestTy, const Variable *Dest,
851                       Type SrcTy, const Operand *Src,
852                       const CastEmitterRegOp<DReg_t, SReg_t> &Emitter) {
853   auto *Target = InstX86Base::getTarget(Func);
854   Assembler *Asm = Func->getAssembler<Assembler>();
855   assert(Dest->hasReg());
856   DReg_t DestReg = destEnc(Dest->getRegNum());
857   if (const auto *SrcVar = llvm::dyn_cast<Variable>(Src)) {
858     if (SrcVar->hasReg()) {
859       SReg_t SrcReg = srcEnc(SrcVar->getRegNum());
860       (Asm->*(Emitter.RegReg))(DestTy, DestReg, SrcTy, SrcReg);
861     } else {
862       AsmAddress SrcStackAddr = AsmAddress(SrcVar, Target);
863       (Asm->*(Emitter.RegAddr))(DestTy, DestReg, SrcTy, SrcStackAddr);
864     }
865   } else if (const auto *Mem = llvm::dyn_cast<X86OperandMem>(Src)) {
866     Mem->emitSegmentOverride(Asm);
867     (Asm->*(Emitter.RegAddr))(DestTy, DestReg, SrcTy,
868                               AsmAddress(Mem, Asm, Target));
869   } else {
870     llvm_unreachable("Unexpected operand type");
871   }
872 }
873 
874 template <typename DReg_t, typename SReg_t, DReg_t (*destEnc)(RegNumT),
875           SReg_t (*srcEnc)(RegNumT)>
emitIASThreeOpImmOps(const Cfg * Func,Type DispatchTy,const Variable * Dest,const Operand * Src0,const Operand * Src1,const ThreeOpImmEmitter<DReg_t,SReg_t> Emitter)876 void emitIASThreeOpImmOps(const Cfg *Func, Type DispatchTy,
877                           const Variable *Dest, const Operand *Src0,
878                           const Operand *Src1,
879                           const ThreeOpImmEmitter<DReg_t, SReg_t> Emitter) {
880   auto *Target = InstX86Base::getTarget(Func);
881   Assembler *Asm = Func->getAssembler<Assembler>();
882   // This only handles Dest being a register, and Src1 being an immediate.
883   assert(Dest->hasReg());
884   DReg_t DestReg = destEnc(Dest->getRegNum());
885   AssemblerImmediate Imm(llvm::cast<ConstantInteger32>(Src1)->getValue());
886   if (const auto *SrcVar = llvm::dyn_cast<Variable>(Src0)) {
887     if (SrcVar->hasReg()) {
888       SReg_t SrcReg = srcEnc(SrcVar->getRegNum());
889       (Asm->*(Emitter.RegRegImm))(DispatchTy, DestReg, SrcReg, Imm);
890     } else {
891       AsmAddress SrcStackAddr = AsmAddress(SrcVar, Target);
892       (Asm->*(Emitter.RegAddrImm))(DispatchTy, DestReg, SrcStackAddr, Imm);
893     }
894   } else if (const auto *Mem = llvm::dyn_cast<X86OperandMem>(Src0)) {
895     Mem->emitSegmentOverride(Asm);
896     (Asm->*(Emitter.RegAddrImm))(DispatchTy, DestReg,
897                                  AsmAddress(Mem, Asm, Target), Imm);
898   } else {
899     llvm_unreachable("Unexpected operand type");
900   }
901 }
902 
emitIASMovlikeXMM(const Cfg * Func,const Variable * Dest,const Operand * Src,const XmmEmitterMovOps Emitter)903 void emitIASMovlikeXMM(const Cfg *Func, const Variable *Dest,
904                        const Operand *Src, const XmmEmitterMovOps Emitter) {
905   auto *Target = InstX86Base::getTarget(Func);
906   Assembler *Asm = Func->getAssembler<Assembler>();
907   if (Dest->hasReg()) {
908     XmmRegister DestReg = RegX8632::getEncodedXmm(Dest->getRegNum());
909     if (const auto *SrcVar = llvm::dyn_cast<Variable>(Src)) {
910       if (SrcVar->hasReg()) {
911         (Asm->*(Emitter.XmmXmm))(DestReg,
912                                  RegX8632::getEncodedXmm(SrcVar->getRegNum()));
913       } else {
914         AsmAddress StackAddr(AsmAddress(SrcVar, Target));
915         (Asm->*(Emitter.XmmAddr))(DestReg, StackAddr);
916       }
917     } else if (const auto *SrcMem = llvm::dyn_cast<X86OperandMem>(Src)) {
918       assert(SrcMem->getSegmentRegister() == X86OperandMem::DefaultSegment);
919       (Asm->*(Emitter.XmmAddr))(DestReg, AsmAddress(SrcMem, Asm, Target));
920     } else {
921       llvm_unreachable("Unexpected operand type");
922     }
923   } else {
924     AsmAddress StackAddr(AsmAddress(Dest, Target));
925     // Src must be a register in this case.
926     const auto *SrcVar = llvm::cast<Variable>(Src);
927     assert(SrcVar->hasReg());
928     (Asm->*(Emitter.AddrXmm))(StackAddr,
929                               RegX8632::getEncodedXmm(SrcVar->getRegNum()));
930   }
931 }
932 
dump(const Cfg * Func) const933 void InstX86Movmsk::dump(const Cfg *Func) const {
934   if (!BuildDefs::dump())
935     return;
936   Ostream &Str = Func->getContext()->getStrDump();
937   this->dumpDest(Func);
938   Str << " = movmsk." << this->getSrc(0)->getType() << " ";
939   this->dumpSources(Func);
940 }
941 
emit(const Cfg * Func) const942 void InstX86Movmsk::emit(const Cfg *Func) const {
943   if (!BuildDefs::dump())
944     return;
945   Ostream &Str = Func->getContext()->getStrEmit();
946   assert(this->getSrcSize() == 1);
947   Type SrcTy = this->getSrc(0)->getType();
948   assert(isVectorType(SrcTy));
949   switch (SrcTy) {
950   case IceType_v16i8:
951     Str << "\t"
952            "pmovmskb"
953            "\t";
954     break;
955   case IceType_v4i32:
956   case IceType_v4f32:
957     Str << "\t"
958            "movmskps"
959            "\t";
960     break;
961   default:
962     llvm_unreachable("Unexpected operand type");
963   }
964   this->getSrc(0)->emit(Func);
965   Str << ", ";
966   this->getDest()->emit(Func);
967 }
968 
emitIAS(const Cfg * Func) const969 void InstX86Movmsk::emitIAS(const Cfg *Func) const {
970   assert(this->getSrcSize() == 1);
971   Assembler *Asm = Func->getAssembler<Assembler>();
972   const Variable *Dest = this->getDest();
973   const Variable *Src = llvm::cast<Variable>(this->getSrc(0));
974   const Type DestTy = Dest->getType();
975   (void)DestTy;
976   const Type SrcTy = Src->getType();
977   assert(isVectorType(SrcTy));
978   assert(isScalarIntegerType(DestTy));
979   assert(typeWidthInBytes(DestTy) <= 4);
980   XmmRegister SrcReg = RegX8632::getEncodedXmm(Src->getRegNum());
981   GPRRegister DestReg = RegX8632::getEncodedGPR(Dest->getRegNum());
982   Asm->movmsk(SrcTy, DestReg, SrcReg);
983 }
984 
emit(const Cfg * Func) const985 void InstX86Sqrt::emit(const Cfg *Func) const {
986   if (!BuildDefs::dump())
987     return;
988   Ostream &Str = Func->getContext()->getStrEmit();
989   assert(this->getSrcSize() == 1);
990   Type Ty = this->getSrc(0)->getType();
991   assert(isScalarFloatingType(Ty));
992   Str << "\t"
993          "sqrt"
994       << TypeAttributes[Ty].SpSdString << "\t";
995   this->getSrc(0)->emit(Func);
996   Str << ", ";
997   this->getDest()->emit(Func);
998 }
999 
emit(const Cfg * Func) const1000 void InstX86Div::emit(const Cfg *Func) const {
1001   if (!BuildDefs::dump())
1002     return;
1003   Ostream &Str = Func->getContext()->getStrEmit();
1004   assert(this->getSrcSize() == 3);
1005   Operand *Src1 = this->getSrc(1);
1006   Str << "\t" << this->Opcode << this->getWidthString(Src1->getType()) << "\t";
1007   Src1->emit(Func);
1008 }
1009 
emitIAS(const Cfg * Func) const1010 void InstX86Div::emitIAS(const Cfg *Func) const {
1011   assert(this->getSrcSize() == 3);
1012   const Operand *Src = this->getSrc(1);
1013   Type Ty = Src->getType();
1014   static GPREmitterOneOp Emitter = {&Assembler::div, &Assembler::div};
1015   emitIASOpTyGPR(Func, Ty, Src, Emitter);
1016 }
1017 
emit(const Cfg * Func) const1018 void InstX86Idiv::emit(const Cfg *Func) const {
1019   if (!BuildDefs::dump())
1020     return;
1021   Ostream &Str = Func->getContext()->getStrEmit();
1022   assert(this->getSrcSize() == 3);
1023   Operand *Src1 = this->getSrc(1);
1024   Str << "\t" << this->Opcode << this->getWidthString(Src1->getType()) << "\t";
1025   Src1->emit(Func);
1026 }
1027 
emitIAS(const Cfg * Func) const1028 void InstX86Idiv::emitIAS(const Cfg *Func) const {
1029   assert(this->getSrcSize() == 3);
1030   const Operand *Src = this->getSrc(1);
1031   Type Ty = Src->getType();
1032   static const GPREmitterOneOp Emitter = {&Assembler::idiv, &Assembler::idiv};
1033   emitIASOpTyGPR(Func, Ty, Src, Emitter);
1034 }
1035 
1036 // pblendvb and blendvps take xmm0 as a final implicit argument.
1037 
emitVariableBlendInst(const char * Opcode,const Inst * Instr,const Cfg * Func)1038 void emitVariableBlendInst(const char *Opcode, const Inst *Instr,
1039                            const Cfg *Func) {
1040   if (!BuildDefs::dump())
1041     return;
1042   Ostream &Str = Func->getContext()->getStrEmit();
1043   assert(Instr->getSrcSize() == 3);
1044   assert(llvm::cast<Variable>(Instr->getSrc(2))->getRegNum() ==
1045          RegisterSet::Reg_xmm0);
1046   Str << "\t" << Opcode << "\t";
1047   Instr->getSrc(1)->emit(Func);
1048   Str << ", ";
1049   Instr->getDest()->emit(Func);
1050 }
1051 
emitIASVariableBlendInst(const Inst * Instr,const Cfg * Func,const XmmEmitterRegOp & Emitter)1052 void emitIASVariableBlendInst(const Inst *Instr, const Cfg *Func,
1053                               const XmmEmitterRegOp &Emitter) {
1054   assert(Instr->getSrcSize() == 3);
1055   assert(llvm::cast<Variable>(Instr->getSrc(2))->getRegNum() ==
1056          RegisterSet::Reg_xmm0);
1057   const Variable *Dest = Instr->getDest();
1058   const Operand *Src = Instr->getSrc(1);
1059   emitIASRegOpTyXMM(Func, Dest->getType(), Dest, Src, Emitter);
1060 }
1061 
emit(const Cfg * Func) const1062 void InstX86Blendvps::emit(const Cfg *Func) const {
1063   if (!BuildDefs::dump())
1064     return;
1065   emitVariableBlendInst(this->Opcode, this, Func);
1066 }
1067 
emitIAS(const Cfg * Func) const1068 void InstX86Blendvps::emitIAS(const Cfg *Func) const {
1069   static const XmmEmitterRegOp Emitter = {&Assembler::blendvps,
1070                                           &Assembler::blendvps};
1071   emitIASVariableBlendInst(this, Func, Emitter);
1072 }
1073 
emit(const Cfg * Func) const1074 void InstX86Pblendvb::emit(const Cfg *Func) const {
1075   if (!BuildDefs::dump())
1076     return;
1077   emitVariableBlendInst(this->Opcode, this, Func);
1078 }
1079 
emitIAS(const Cfg * Func) const1080 void InstX86Pblendvb::emitIAS(const Cfg *Func) const {
1081   static const XmmEmitterRegOp Emitter = {&Assembler::pblendvb,
1082                                           &Assembler::pblendvb};
1083   emitIASVariableBlendInst(this, Func, Emitter);
1084 }
1085 
emit(const Cfg * Func) const1086 void InstX86Imul::emit(const Cfg *Func) const {
1087   if (!BuildDefs::dump())
1088     return;
1089   Ostream &Str = Func->getContext()->getStrEmit();
1090   assert(this->getSrcSize() == 2);
1091   Variable *Dest = this->getDest();
1092   if (isByteSizedArithType(Dest->getType())) {
1093     // The 8-bit version of imul only allows the form "imul r/m8".
1094     const auto *Src0Var = llvm::dyn_cast<Variable>(this->getSrc(0));
1095     (void)Src0Var;
1096     assert(Src0Var->getRegNum() == RegisterSet::Reg_al);
1097     Str << "\t"
1098            "imulb\t";
1099     this->getSrc(1)->emit(Func);
1100   } else if (llvm::isa<Constant>(this->getSrc(1))) {
1101     Str << "\t"
1102            "imul"
1103         << this->getWidthString(Dest->getType()) << "\t";
1104     this->getSrc(1)->emit(Func);
1105     Str << ", ";
1106     this->getSrc(0)->emit(Func);
1107     Str << ", ";
1108     Dest->emit(Func);
1109   } else {
1110     this->emitTwoAddress(Func, this->Opcode);
1111   }
1112 }
1113 
emitIAS(const Cfg * Func) const1114 void InstX86Imul::emitIAS(const Cfg *Func) const {
1115   assert(this->getSrcSize() == 2);
1116   const Variable *Var = this->getDest();
1117   Type Ty = Var->getType();
1118   const Operand *Src = this->getSrc(1);
1119   if (isByteSizedArithType(Ty)) {
1120     // The 8-bit version of imul only allows the form "imul r/m8".
1121     const auto *Src0Var = llvm::dyn_cast<Variable>(this->getSrc(0));
1122     (void)Src0Var;
1123     assert(Src0Var->getRegNum() == RegisterSet::Reg_al);
1124     static const GPREmitterOneOp Emitter = {&Assembler::imul, &Assembler::imul};
1125     emitIASOpTyGPR(Func, Ty, this->getSrc(1), Emitter);
1126   } else {
1127     // The two-address version is used when multiplying by a non-constant
1128     // or doing an 8-bit multiply.
1129     assert(Var == this->getSrc(0));
1130     static const GPREmitterRegOp Emitter = {&Assembler::imul, &Assembler::imul,
1131                                             &Assembler::imul};
1132     emitIASRegOpTyGPR(Func, Ty, Var, Src, Emitter);
1133   }
1134 }
1135 
emit(const Cfg * Func) const1136 void InstX86ImulImm::emit(const Cfg *Func) const {
1137   if (!BuildDefs::dump())
1138     return;
1139   Ostream &Str = Func->getContext()->getStrEmit();
1140   assert(this->getSrcSize() == 2);
1141   Variable *Dest = this->getDest();
1142   assert(Dest->getType() == IceType_i16 || Dest->getType() == IceType_i32);
1143   assert(llvm::isa<Constant>(this->getSrc(1)));
1144   Str << "\t"
1145          "imul"
1146       << this->getWidthString(Dest->getType()) << "\t";
1147   this->getSrc(1)->emit(Func);
1148   Str << ", ";
1149   this->getSrc(0)->emit(Func);
1150   Str << ", ";
1151   Dest->emit(Func);
1152 }
1153 
emitIAS(const Cfg * Func) const1154 void InstX86ImulImm::emitIAS(const Cfg *Func) const {
1155   assert(this->getSrcSize() == 2);
1156   const Variable *Dest = this->getDest();
1157   Type Ty = Dest->getType();
1158   assert(llvm::isa<Constant>(this->getSrc(1)));
1159   static const ThreeOpImmEmitter<GPRRegister, GPRRegister> Emitter = {
1160       &Assembler::imul, &Assembler::imul};
1161   emitIASThreeOpImmOps<GPRRegister, GPRRegister, RegX8632::getEncodedGPR,
1162                        RegX8632::getEncodedGPR>(Func, Ty, Dest, this->getSrc(0),
1163                                                 this->getSrc(1), Emitter);
1164 }
1165 
emitIAS(const Cfg * Func) const1166 void InstX86Insertps::emitIAS(const Cfg *Func) const {
1167   assert(this->getSrcSize() == 3);
1168   assert(InstX86Base::getTarget(Func)->getInstructionSet() >= SSE4_1);
1169   const Variable *Dest = this->getDest();
1170   assert(Dest == this->getSrc(0));
1171   Type Ty = Dest->getType();
1172   static const ThreeOpImmEmitter<XmmRegister, XmmRegister> Emitter = {
1173       &Assembler::insertps, &Assembler::insertps};
1174   emitIASThreeOpImmOps<XmmRegister, XmmRegister, RegX8632::getEncodedXmm,
1175                        RegX8632::getEncodedXmm>(Func, Ty, Dest, this->getSrc(1),
1176                                                 this->getSrc(2), Emitter);
1177 }
1178 
emit(const Cfg * Func) const1179 void InstX86Cbwdq::emit(const Cfg *Func) const {
1180   if (!BuildDefs::dump())
1181     return;
1182   Ostream &Str = Func->getContext()->getStrEmit();
1183   assert(this->getSrcSize() == 1);
1184   Operand *Src0 = this->getSrc(0);
1185   const auto DestReg = this->getDest()->getRegNum();
1186   const auto SrcReg = llvm::cast<Variable>(Src0)->getRegNum();
1187   (void)DestReg;
1188   (void)SrcReg;
1189   switch (Src0->getType()) {
1190   default:
1191     llvm_unreachable("unexpected source type!");
1192     break;
1193   case IceType_i8:
1194     assert(SrcReg == RegisterSet::Reg_al);
1195     assert(DestReg == RegisterSet::Reg_ax || DestReg == RegisterSet::Reg_ah);
1196     Str << "\t"
1197            "cbtw";
1198     break;
1199   case IceType_i16:
1200     assert(SrcReg == RegisterSet::Reg_ax);
1201     assert(DestReg == RegisterSet::Reg_dx);
1202     Str << "\t"
1203            "cwtd";
1204     break;
1205   case IceType_i32:
1206     assert(SrcReg == RegisterSet::Reg_eax);
1207     assert(DestReg == RegisterSet::Reg_edx);
1208     Str << "\t"
1209            "cltd";
1210     break;
1211   }
1212 }
1213 
emitIAS(const Cfg * Func) const1214 void InstX86Cbwdq::emitIAS(const Cfg *Func) const {
1215   Assembler *Asm = Func->getAssembler<Assembler>();
1216   assert(this->getSrcSize() == 1);
1217   Operand *Src0 = this->getSrc(0);
1218   const auto DestReg = this->getDest()->getRegNum();
1219   const auto SrcReg = llvm::cast<Variable>(Src0)->getRegNum();
1220   (void)DestReg;
1221   (void)SrcReg;
1222   switch (Src0->getType()) {
1223   default:
1224     llvm_unreachable("unexpected source type!");
1225     break;
1226   case IceType_i8:
1227     assert(SrcReg == RegisterSet::Reg_al);
1228     assert(DestReg == RegisterSet::Reg_ax || DestReg == RegisterSet::Reg_ah);
1229     Asm->cbw();
1230     break;
1231   case IceType_i16:
1232     assert(SrcReg == RegisterSet::Reg_ax);
1233     assert(DestReg == RegisterSet::Reg_dx);
1234     Asm->cwd();
1235     break;
1236   case IceType_i32:
1237     assert(SrcReg == RegisterSet::Reg_eax);
1238     assert(DestReg == RegisterSet::Reg_edx);
1239     Asm->cdq();
1240     break;
1241   }
1242 }
1243 
emit(const Cfg * Func) const1244 void InstX86Mul::emit(const Cfg *Func) const {
1245   if (!BuildDefs::dump())
1246     return;
1247   Ostream &Str = Func->getContext()->getStrEmit();
1248   assert(this->getSrcSize() == 2);
1249   assert(llvm::isa<Variable>(this->getSrc(0)));
1250   assert(llvm::cast<Variable>(this->getSrc(0))->getRegNum() ==
1251          RegisterSet::Reg_eax);
1252   assert(this->getDest()->getRegNum() == RegisterSet::Reg_eax); // TODO:
1253                                                                 // allow
1254                                                                 // edx?
1255   Str << "\t"
1256          "mul"
1257       << this->getWidthString(this->getDest()->getType()) << "\t";
1258   this->getSrc(1)->emit(Func);
1259 }
1260 
emitIAS(const Cfg * Func) const1261 void InstX86Mul::emitIAS(const Cfg *Func) const {
1262   assert(this->getSrcSize() == 2);
1263   assert(llvm::isa<Variable>(this->getSrc(0)));
1264   assert(llvm::cast<Variable>(this->getSrc(0))->getRegNum() ==
1265          RegisterSet::Reg_eax);
1266   assert(this->getDest()->getRegNum() == RegisterSet::Reg_eax); // TODO:
1267                                                                 // allow
1268                                                                 // edx?
1269   const Operand *Src = this->getSrc(1);
1270   Type Ty = Src->getType();
1271   static const GPREmitterOneOp Emitter = {&Assembler::mul, &Assembler::mul};
1272   emitIASOpTyGPR(Func, Ty, Src, Emitter);
1273 }
1274 
dump(const Cfg * Func) const1275 void InstX86Mul::dump(const Cfg *Func) const {
1276   if (!BuildDefs::dump())
1277     return;
1278   Ostream &Str = Func->getContext()->getStrDump();
1279   this->dumpDest(Func);
1280   Str << " = mul." << this->getDest()->getType() << " ";
1281   this->dumpSources(Func);
1282 }
1283 
emit(const Cfg * Func) const1284 void InstX86Shld::emit(const Cfg *Func) const {
1285   if (!BuildDefs::dump())
1286     return;
1287   Ostream &Str = Func->getContext()->getStrEmit();
1288   Variable *Dest = this->getDest();
1289   assert(this->getSrcSize() == 3);
1290   assert(Dest == this->getSrc(0));
1291   Str << "\t"
1292          "shld"
1293       << this->getWidthString(Dest->getType()) << "\t";
1294   this->getSrc(2)->emit(Func);
1295   Str << ", ";
1296   this->getSrc(1)->emit(Func);
1297   Str << ", ";
1298   Dest->emit(Func);
1299 }
1300 
emitIAS(const Cfg * Func) const1301 void InstX86Shld::emitIAS(const Cfg *Func) const {
1302   assert(this->getSrcSize() == 3);
1303   assert(this->getDest() == this->getSrc(0));
1304   const Variable *Dest = this->getDest();
1305   const Operand *Src1 = this->getSrc(1);
1306   const Operand *Src2 = this->getSrc(2);
1307   static const GPREmitterShiftD Emitter = {&Assembler::shld, &Assembler::shld};
1308   emitIASGPRShiftDouble(Func, Dest, Src1, Src2, Emitter);
1309 }
1310 
dump(const Cfg * Func) const1311 void InstX86Shld::dump(const Cfg *Func) const {
1312   if (!BuildDefs::dump())
1313     return;
1314   Ostream &Str = Func->getContext()->getStrDump();
1315   this->dumpDest(Func);
1316   Str << " = shld." << this->getDest()->getType() << " ";
1317   this->dumpSources(Func);
1318 }
1319 
emit(const Cfg * Func) const1320 void InstX86Shrd::emit(const Cfg *Func) const {
1321   if (!BuildDefs::dump())
1322     return;
1323   Ostream &Str = Func->getContext()->getStrEmit();
1324   Variable *Dest = this->getDest();
1325   assert(this->getSrcSize() == 3);
1326   assert(Dest == this->getSrc(0));
1327   Str << "\t"
1328          "shrd"
1329       << this->getWidthString(Dest->getType()) << "\t";
1330   this->getSrc(2)->emit(Func);
1331   Str << ", ";
1332   this->getSrc(1)->emit(Func);
1333   Str << ", ";
1334   Dest->emit(Func);
1335 }
1336 
emitIAS(const Cfg * Func) const1337 void InstX86Shrd::emitIAS(const Cfg *Func) const {
1338   assert(this->getSrcSize() == 3);
1339   assert(this->getDest() == this->getSrc(0));
1340   const Variable *Dest = this->getDest();
1341   const Operand *Src1 = this->getSrc(1);
1342   const Operand *Src2 = this->getSrc(2);
1343   static const GPREmitterShiftD Emitter = {&Assembler::shrd, &Assembler::shrd};
1344   emitIASGPRShiftDouble(Func, Dest, Src1, Src2, Emitter);
1345 }
1346 
dump(const Cfg * Func) const1347 void InstX86Shrd::dump(const Cfg *Func) const {
1348   if (!BuildDefs::dump())
1349     return;
1350   Ostream &Str = Func->getContext()->getStrDump();
1351   this->dumpDest(Func);
1352   Str << " = shrd." << this->getDest()->getType() << " ";
1353   this->dumpSources(Func);
1354 }
1355 
emit(const Cfg * Func) const1356 void InstX86Cmov::emit(const Cfg *Func) const {
1357   if (!BuildDefs::dump())
1358     return;
1359   Ostream &Str = Func->getContext()->getStrEmit();
1360   Variable *Dest = this->getDest();
1361   Str << "\t";
1362   assert(Condition != Cond::Br_None);
1363   assert(this->getDest()->hasReg());
1364   Str << "cmov" << InstBrAttributes[Condition].DisplayString
1365       << this->getWidthString(Dest->getType()) << "\t";
1366   this->getSrc(1)->emit(Func);
1367   Str << ", ";
1368   Dest->emit(Func);
1369 }
1370 
emitIAS(const Cfg * Func) const1371 void InstX86Cmov::emitIAS(const Cfg *Func) const {
1372   assert(Condition != Cond::Br_None);
1373   assert(this->getDest()->hasReg());
1374   assert(this->getSrcSize() == 2);
1375   Operand *Src = this->getSrc(1);
1376   Type SrcTy = Src->getType();
1377   assert(SrcTy == IceType_i16 || SrcTy == IceType_i32);
1378   Assembler *Asm = Func->getAssembler<Assembler>();
1379   auto *Target = InstX86Base::getTarget(Func);
1380   if (const auto *SrcVar = llvm::dyn_cast<Variable>(Src)) {
1381     if (SrcVar->hasReg()) {
1382       Asm->cmov(SrcTy, Condition,
1383                 RegX8632::getEncodedGPR(this->getDest()->getRegNum()),
1384                 RegX8632::getEncodedGPR(SrcVar->getRegNum()));
1385     } else {
1386       Asm->cmov(SrcTy, Condition,
1387                 RegX8632::getEncodedGPR(this->getDest()->getRegNum()),
1388                 AsmAddress(SrcVar, Target));
1389     }
1390   } else if (const auto *Mem = llvm::dyn_cast<X86OperandMem>(Src)) {
1391     assert(Mem->getSegmentRegister() == X86OperandMem::DefaultSegment);
1392     Asm->cmov(SrcTy, Condition,
1393               RegX8632::getEncodedGPR(this->getDest()->getRegNum()),
1394               AsmAddress(Mem, Asm, Target));
1395   } else {
1396     llvm_unreachable("Unexpected operand type");
1397   }
1398 }
1399 
dump(const Cfg * Func) const1400 void InstX86Cmov::dump(const Cfg *Func) const {
1401   if (!BuildDefs::dump())
1402     return;
1403   Ostream &Str = Func->getContext()->getStrDump();
1404   Str << "cmov" << InstBrAttributes[Condition].DisplayString << ".";
1405   Str << this->getDest()->getType() << " ";
1406   this->dumpDest(Func);
1407   Str << ", ";
1408   this->dumpSources(Func);
1409 }
1410 
emit(const Cfg * Func) const1411 void InstX86Cmpps::emit(const Cfg *Func) const {
1412   if (!BuildDefs::dump())
1413     return;
1414   Ostream &Str = Func->getContext()->getStrEmit();
1415   assert(this->getSrcSize() == 2);
1416   assert(Condition < Cond::Cmpps_Invalid);
1417   Type DestTy = this->Dest->getType();
1418   Str << "\t"
1419          "cmp"
1420       << InstCmppsAttributes[Condition].EmitString
1421       << TypeAttributes[DestTy].PdPsString << "\t";
1422   this->getSrc(1)->emit(Func);
1423   Str << ", ";
1424   this->getDest()->emit(Func);
1425 }
1426 
emitIAS(const Cfg * Func) const1427 void InstX86Cmpps::emitIAS(const Cfg *Func) const {
1428   Assembler *Asm = Func->getAssembler<Assembler>();
1429   assert(this->getSrcSize() == 2);
1430   assert(Condition < Cond::Cmpps_Invalid);
1431   // Assuming there isn't any load folding for cmpps, and vector constants are
1432   // not allowed in PNaCl.
1433   assert(llvm::isa<Variable>(this->getSrc(1)));
1434   auto *Target = InstX86Base::getTarget(Func);
1435   const auto *SrcVar = llvm::cast<Variable>(this->getSrc(1));
1436   if (SrcVar->hasReg()) {
1437     Asm->cmpps(this->getDest()->getType(),
1438                RegX8632::getEncodedXmm(this->getDest()->getRegNum()),
1439                RegX8632::getEncodedXmm(SrcVar->getRegNum()), Condition);
1440   } else {
1441     AsmAddress SrcStackAddr = AsmAddress(SrcVar, Target);
1442     Asm->cmpps(this->getDest()->getType(),
1443                RegX8632::getEncodedXmm(this->getDest()->getRegNum()),
1444                SrcStackAddr, Condition);
1445   }
1446 }
1447 
dump(const Cfg * Func) const1448 void InstX86Cmpps::dump(const Cfg *Func) const {
1449   if (!BuildDefs::dump())
1450     return;
1451   Ostream &Str = Func->getContext()->getStrDump();
1452   assert(Condition < Cond::Cmpps_Invalid);
1453   this->dumpDest(Func);
1454   Str << " = cmp" << InstCmppsAttributes[Condition].EmitString
1455       << "ps"
1456          "\t";
1457   this->dumpSources(Func);
1458 }
1459 
emit(const Cfg * Func) const1460 void InstX86Cmpxchg::emit(const Cfg *Func) const {
1461   if (!BuildDefs::dump())
1462     return;
1463   Ostream &Str = Func->getContext()->getStrEmit();
1464   assert(this->getSrcSize() == 3);
1465   if (this->Locked) {
1466     Str << "\t"
1467            "lock";
1468   }
1469   Str << "\t"
1470          "cmpxchg"
1471       << this->getWidthString(this->getSrc(0)->getType()) << "\t";
1472   this->getSrc(2)->emit(Func);
1473   Str << ", ";
1474   this->getSrc(0)->emit(Func);
1475 }
1476 
emitIAS(const Cfg * Func) const1477 void InstX86Cmpxchg::emitIAS(const Cfg *Func) const {
1478   assert(this->getSrcSize() == 3);
1479   Assembler *Asm = Func->getAssembler<Assembler>();
1480   Type Ty = this->getSrc(0)->getType();
1481   auto *Target = InstX86Base::getTarget(Func);
1482   const auto Mem = llvm::cast<X86OperandMem>(this->getSrc(0));
1483   assert(Mem->getSegmentRegister() == X86OperandMem::DefaultSegment);
1484   const AsmAddress Addr = AsmAddress(Mem, Asm, Target);
1485   const auto *VarReg = llvm::cast<Variable>(this->getSrc(2));
1486   assert(VarReg->hasReg());
1487   const GPRRegister Reg = RegX8632::getEncodedGPR(VarReg->getRegNum());
1488   Asm->cmpxchg(Ty, Addr, Reg, this->Locked);
1489 }
1490 
dump(const Cfg * Func) const1491 void InstX86Cmpxchg::dump(const Cfg *Func) const {
1492   if (!BuildDefs::dump())
1493     return;
1494   Ostream &Str = Func->getContext()->getStrDump();
1495   if (this->Locked) {
1496     Str << "lock ";
1497   }
1498   Str << "cmpxchg." << this->getSrc(0)->getType() << " ";
1499   this->dumpSources(Func);
1500 }
1501 
emit(const Cfg * Func) const1502 void InstX86Cmpxchg8b::emit(const Cfg *Func) const {
1503   if (!BuildDefs::dump())
1504     return;
1505   Ostream &Str = Func->getContext()->getStrEmit();
1506   assert(this->getSrcSize() == 5);
1507   if (this->Locked) {
1508     Str << "\t"
1509            "lock";
1510   }
1511   Str << "\t"
1512          "cmpxchg8b\t";
1513   this->getSrc(0)->emit(Func);
1514 }
1515 
emitIAS(const Cfg * Func) const1516 void InstX86Cmpxchg8b::emitIAS(const Cfg *Func) const {
1517   assert(this->getSrcSize() == 5);
1518   Assembler *Asm = Func->getAssembler<Assembler>();
1519   const auto Mem = llvm::cast<X86OperandMem>(this->getSrc(0));
1520   assert(Mem->getSegmentRegister() == X86OperandMem::DefaultSegment);
1521   auto *Target = InstX86Base::getTarget(Func);
1522   const AsmAddress Addr = AsmAddress(Mem, Asm, Target);
1523   Asm->cmpxchg8b(Addr, this->Locked);
1524 }
1525 
dump(const Cfg * Func) const1526 void InstX86Cmpxchg8b::dump(const Cfg *Func) const {
1527   if (!BuildDefs::dump())
1528     return;
1529   Ostream &Str = Func->getContext()->getStrDump();
1530   if (this->Locked) {
1531     Str << "lock ";
1532   }
1533   Str << "cmpxchg8b ";
1534   this->dumpSources(Func);
1535 }
1536 
emit(const Cfg * Func) const1537 void InstX86Cvt::emit(const Cfg *Func) const {
1538   if (!BuildDefs::dump())
1539     return;
1540   Ostream &Str = Func->getContext()->getStrEmit();
1541   assert(this->getSrcSize() == 1);
1542   Str << "\t"
1543          "cvt";
1544   if (isTruncating())
1545     Str << "t";
1546   Str << TypeAttributes[this->getSrc(0)->getType()].CvtString << "2"
1547       << TypeAttributes[this->getDest()->getType()].CvtString << "\t";
1548   this->getSrc(0)->emit(Func);
1549   Str << ", ";
1550   this->getDest()->emit(Func);
1551 }
1552 
emitIAS(const Cfg * Func) const1553 void InstX86Cvt::emitIAS(const Cfg *Func) const {
1554   assert(this->getSrcSize() == 1);
1555   const Variable *Dest = this->getDest();
1556   const Operand *Src = this->getSrc(0);
1557   Type DestTy = Dest->getType();
1558   Type SrcTy = Src->getType();
1559   switch (Variant) {
1560   case Si2ss: {
1561     assert(isScalarIntegerType(SrcTy));
1562     assert(typeWidthInBytes(SrcTy) <= 4);
1563     assert(isScalarFloatingType(DestTy));
1564     static const CastEmitterRegOp<XmmRegister, GPRRegister> Emitter = {
1565         &Assembler::cvtsi2ss, &Assembler::cvtsi2ss};
1566     emitIASCastRegOp<XmmRegister, GPRRegister, RegX8632::getEncodedXmm,
1567                      RegX8632::getEncodedGPR>(Func, DestTy, Dest, SrcTy, Src,
1568                                               Emitter);
1569     return;
1570   }
1571   case Tss2si: {
1572     assert(isScalarFloatingType(SrcTy));
1573     assert(isScalarIntegerType(DestTy));
1574     assert(typeWidthInBytes(DestTy) <= 4);
1575     static const CastEmitterRegOp<GPRRegister, XmmRegister> Emitter = {
1576         &Assembler::cvttss2si, &Assembler::cvttss2si};
1577     emitIASCastRegOp<GPRRegister, XmmRegister, RegX8632::getEncodedGPR,
1578                      RegX8632::getEncodedXmm>(Func, DestTy, Dest, SrcTy, Src,
1579                                               Emitter);
1580     return;
1581   }
1582   case Ss2si: {
1583     assert(isScalarFloatingType(SrcTy));
1584     assert(isScalarIntegerType(DestTy));
1585     assert(typeWidthInBytes(DestTy) <= 4);
1586     static const CastEmitterRegOp<GPRRegister, XmmRegister> Emitter = {
1587         &Assembler::cvtss2si, &Assembler::cvtss2si};
1588     emitIASCastRegOp<GPRRegister, XmmRegister, RegX8632::getEncodedGPR,
1589                      RegX8632::getEncodedXmm>(Func, DestTy, Dest, SrcTy, Src,
1590                                               Emitter);
1591     return;
1592   }
1593   case Float2float: {
1594     assert(isScalarFloatingType(SrcTy));
1595     assert(isScalarFloatingType(DestTy));
1596     assert(DestTy != SrcTy);
1597     static const XmmEmitterRegOp Emitter = {&Assembler::cvtfloat2float,
1598                                             &Assembler::cvtfloat2float};
1599     emitIASRegOpTyXMM(Func, SrcTy, Dest, Src, Emitter);
1600     return;
1601   }
1602   case Dq2ps: {
1603     assert(isVectorIntegerType(SrcTy));
1604     assert(isVectorFloatingType(DestTy));
1605     static const XmmEmitterRegOp Emitter = {&Assembler::cvtdq2ps,
1606                                             &Assembler::cvtdq2ps};
1607     emitIASRegOpTyXMM(Func, DestTy, Dest, Src, Emitter);
1608     return;
1609   }
1610   case Tps2dq: {
1611     assert(isVectorFloatingType(SrcTy));
1612     assert(isVectorIntegerType(DestTy));
1613     static const XmmEmitterRegOp Emitter = {&Assembler::cvttps2dq,
1614                                             &Assembler::cvttps2dq};
1615     emitIASRegOpTyXMM(Func, DestTy, Dest, Src, Emitter);
1616     return;
1617   }
1618   case Ps2dq: {
1619     assert(isVectorFloatingType(SrcTy));
1620     assert(isVectorIntegerType(DestTy));
1621     static const XmmEmitterRegOp Emitter = {&Assembler::cvtps2dq,
1622                                             &Assembler::cvtps2dq};
1623     emitIASRegOpTyXMM(Func, DestTy, Dest, Src, Emitter);
1624     return;
1625   }
1626   }
1627 }
1628 
dump(const Cfg * Func) const1629 void InstX86Cvt::dump(const Cfg *Func) const {
1630   if (!BuildDefs::dump())
1631     return;
1632   Ostream &Str = Func->getContext()->getStrDump();
1633   this->dumpDest(Func);
1634   Str << " = cvt";
1635   if (isTruncating())
1636     Str << "t";
1637   Str << TypeAttributes[this->getSrc(0)->getType()].CvtString << "2"
1638       << TypeAttributes[this->getDest()->getType()].CvtString << " ";
1639   this->dumpSources(Func);
1640 }
1641 
emit(const Cfg * Func) const1642 void InstX86Round::emit(const Cfg *Func) const {
1643   if (!BuildDefs::dump())
1644     return;
1645   Ostream &Str = Func->getContext()->getStrEmit();
1646   assert(this->getSrcSize() == 3);
1647   Str << "\t" << this->Opcode
1648       << TypeAttributes[this->getDest()->getType()].SpSdString << "\t";
1649   this->getSrc(1)->emit(Func);
1650   Str << ", ";
1651   this->getSrc(0)->emit(Func);
1652   Str << ", ";
1653   this->getDest()->emit(Func);
1654 }
1655 
emitIAS(const Cfg * Func) const1656 void InstX86Round::emitIAS(const Cfg *Func) const {
1657   assert(this->getSrcSize() == 2);
1658   assert(InstX86Base::getTarget(Func)->getInstructionSet() >= SSE4_1);
1659   const Variable *Dest = this->getDest();
1660   Type Ty = Dest->getType();
1661   static const ThreeOpImmEmitter<XmmRegister, XmmRegister> Emitter = {
1662       &Assembler::round, &Assembler::round};
1663   emitIASThreeOpImmOps<XmmRegister, XmmRegister, RegX8632::getEncodedXmm,
1664                        RegX8632::getEncodedXmm>(Func, Ty, Dest, this->getSrc(0),
1665                                                 this->getSrc(1), Emitter);
1666 }
1667 
emit(const Cfg * Func) const1668 void InstX86Icmp::emit(const Cfg *Func) const {
1669   if (!BuildDefs::dump())
1670     return;
1671   Ostream &Str = Func->getContext()->getStrEmit();
1672   assert(this->getSrcSize() == 2);
1673   Str << "\t"
1674          "cmp"
1675       << this->getWidthString(this->getSrc(0)->getType()) << "\t";
1676   this->getSrc(1)->emit(Func);
1677   Str << ", ";
1678   this->getSrc(0)->emit(Func);
1679 }
1680 
emitIAS(const Cfg * Func) const1681 void InstX86Icmp::emitIAS(const Cfg *Func) const {
1682   assert(this->getSrcSize() == 2);
1683   const Operand *Src0 = this->getSrc(0);
1684   const Operand *Src1 = this->getSrc(1);
1685   Type Ty = Src0->getType();
1686   static const GPREmitterRegOp RegEmitter = {&Assembler::cmp, &Assembler::cmp,
1687                                              &Assembler::cmp};
1688   static const GPREmitterAddrOp AddrEmitter = {&Assembler::cmp,
1689                                                &Assembler::cmp};
1690   if (const auto *SrcVar0 = llvm::dyn_cast<Variable>(Src0)) {
1691     if (SrcVar0->hasReg()) {
1692       emitIASRegOpTyGPR(Func, Ty, SrcVar0, Src1, RegEmitter);
1693       return;
1694     }
1695   }
1696   emitIASAsAddrOpTyGPR(Func, Ty, Src0, Src1, AddrEmitter);
1697 }
1698 
dump(const Cfg * Func) const1699 void InstX86Icmp::dump(const Cfg *Func) const {
1700   if (!BuildDefs::dump())
1701     return;
1702   Ostream &Str = Func->getContext()->getStrDump();
1703   Str << "cmp." << this->getSrc(0)->getType() << " ";
1704   this->dumpSources(Func);
1705 }
1706 
emit(const Cfg * Func) const1707 void InstX86Ucomiss::emit(const Cfg *Func) const {
1708   if (!BuildDefs::dump())
1709     return;
1710   Ostream &Str = Func->getContext()->getStrEmit();
1711   assert(this->getSrcSize() == 2);
1712   Str << "\t"
1713          "ucomi"
1714       << TypeAttributes[this->getSrc(0)->getType()].SdSsString << "\t";
1715   this->getSrc(1)->emit(Func);
1716   Str << ", ";
1717   this->getSrc(0)->emit(Func);
1718 }
1719 
emitIAS(const Cfg * Func) const1720 void InstX86Ucomiss::emitIAS(const Cfg *Func) const {
1721   assert(this->getSrcSize() == 2);
1722   // Currently src0 is always a variable by convention, to avoid having two
1723   // memory operands.
1724   assert(llvm::isa<Variable>(this->getSrc(0)));
1725   const auto *Src0Var = llvm::cast<Variable>(this->getSrc(0));
1726   Type Ty = Src0Var->getType();
1727   static const XmmEmitterRegOp Emitter = {&Assembler::ucomiss,
1728                                           &Assembler::ucomiss};
1729   emitIASRegOpTyXMM(Func, Ty, Src0Var, this->getSrc(1), Emitter);
1730 }
1731 
dump(const Cfg * Func) const1732 void InstX86Ucomiss::dump(const Cfg *Func) const {
1733   if (!BuildDefs::dump())
1734     return;
1735   Ostream &Str = Func->getContext()->getStrDump();
1736   Str << "ucomiss." << this->getSrc(0)->getType() << " ";
1737   this->dumpSources(Func);
1738 }
1739 
emit(const Cfg * Func) const1740 void InstX86UD2::emit(const Cfg *Func) const {
1741   if (!BuildDefs::dump())
1742     return;
1743   Ostream &Str = Func->getContext()->getStrEmit();
1744   assert(this->getSrcSize() == 0);
1745   Str << "\t"
1746          "ud2";
1747 }
1748 
emitIAS(const Cfg * Func) const1749 void InstX86UD2::emitIAS(const Cfg *Func) const {
1750   Assembler *Asm = Func->getAssembler<Assembler>();
1751   Asm->ud2();
1752 }
1753 
dump(const Cfg * Func) const1754 void InstX86UD2::dump(const Cfg *Func) const {
1755   if (!BuildDefs::dump())
1756     return;
1757   Ostream &Str = Func->getContext()->getStrDump();
1758   Str << "ud2";
1759 }
1760 
emit(const Cfg * Func) const1761 void InstX86Int3::emit(const Cfg *Func) const {
1762   if (!BuildDefs::dump())
1763     return;
1764   Ostream &Str = Func->getContext()->getStrEmit();
1765   assert(this->getSrcSize() == 0);
1766   Str << "\t"
1767          "int 3";
1768 }
1769 
emitIAS(const Cfg * Func) const1770 void InstX86Int3::emitIAS(const Cfg *Func) const {
1771   Assembler *Asm = Func->getAssembler<Assembler>();
1772   Asm->int3();
1773 }
1774 
dump(const Cfg * Func) const1775 void InstX86Int3::dump(const Cfg *Func) const {
1776   if (!BuildDefs::dump())
1777     return;
1778   Ostream &Str = Func->getContext()->getStrDump();
1779   Str << "int 3";
1780 }
1781 
emit(const Cfg * Func) const1782 void InstX86Test::emit(const Cfg *Func) const {
1783   if (!BuildDefs::dump())
1784     return;
1785   Ostream &Str = Func->getContext()->getStrEmit();
1786   assert(this->getSrcSize() == 2);
1787   Str << "\t"
1788          "test"
1789       << this->getWidthString(this->getSrc(0)->getType()) << "\t";
1790   this->getSrc(1)->emit(Func);
1791   Str << ", ";
1792   this->getSrc(0)->emit(Func);
1793 }
1794 
emitIAS(const Cfg * Func) const1795 void InstX86Test::emitIAS(const Cfg *Func) const {
1796   assert(this->getSrcSize() == 2);
1797   const Operand *Src0 = this->getSrc(0);
1798   const Operand *Src1 = this->getSrc(1);
1799   Type Ty = Src0->getType();
1800   // The Reg/Addr form of test is not encodeable.
1801   static const GPREmitterRegOp RegEmitter = {&Assembler::test, nullptr,
1802                                              &Assembler::test};
1803   static const GPREmitterAddrOp AddrEmitter = {&Assembler::test,
1804                                                &Assembler::test};
1805   if (const auto *SrcVar0 = llvm::dyn_cast<Variable>(Src0)) {
1806     if (SrcVar0->hasReg()) {
1807       emitIASRegOpTyGPR(Func, Ty, SrcVar0, Src1, RegEmitter);
1808       return;
1809     }
1810   }
1811   emitIASAsAddrOpTyGPR(Func, Ty, Src0, Src1, AddrEmitter);
1812 }
1813 
dump(const Cfg * Func) const1814 void InstX86Test::dump(const Cfg *Func) const {
1815   if (!BuildDefs::dump())
1816     return;
1817   Ostream &Str = Func->getContext()->getStrDump();
1818   Str << "test." << this->getSrc(0)->getType() << " ";
1819   this->dumpSources(Func);
1820 }
1821 
emit(const Cfg * Func) const1822 void InstX86Mfence::emit(const Cfg *Func) const {
1823   if (!BuildDefs::dump())
1824     return;
1825   Ostream &Str = Func->getContext()->getStrEmit();
1826   assert(this->getSrcSize() == 0);
1827   Str << "\t"
1828          "mfence";
1829 }
1830 
emitIAS(const Cfg * Func) const1831 void InstX86Mfence::emitIAS(const Cfg *Func) const {
1832   Assembler *Asm = Func->getAssembler<Assembler>();
1833   Asm->mfence();
1834 }
1835 
dump(const Cfg * Func) const1836 void InstX86Mfence::dump(const Cfg *Func) const {
1837   if (!BuildDefs::dump())
1838     return;
1839   Ostream &Str = Func->getContext()->getStrDump();
1840   Str << "mfence";
1841 }
1842 
emit(const Cfg * Func) const1843 void InstX86Store::emit(const Cfg *Func) const {
1844   if (!BuildDefs::dump())
1845     return;
1846   Ostream &Str = Func->getContext()->getStrEmit();
1847   assert(this->getSrcSize() == 2);
1848   Type Ty = this->getSrc(0)->getType();
1849   Str << "\t"
1850          "mov"
1851       << this->getWidthString(Ty) << TypeAttributes[Ty].SdSsString << "\t";
1852   this->getSrc(0)->emit(Func);
1853   Str << ", ";
1854   this->getSrc(1)->emit(Func);
1855 }
1856 
emitIAS(const Cfg * Func) const1857 void InstX86Store::emitIAS(const Cfg *Func) const {
1858   assert(this->getSrcSize() == 2);
1859   const Operand *Dest = this->getSrc(1);
1860   const Operand *Src = this->getSrc(0);
1861   Type DestTy = Dest->getType();
1862   if (isScalarFloatingType(DestTy)) {
1863     // Src must be a register, since Dest is a Mem operand of some kind.
1864     const auto *SrcVar = llvm::cast<Variable>(Src);
1865     assert(SrcVar->hasReg());
1866     XmmRegister SrcReg = RegX8632::getEncodedXmm(SrcVar->getRegNum());
1867     Assembler *Asm = Func->getAssembler<Assembler>();
1868     auto *Target = InstX86Base::getTarget(Func);
1869     if (const auto *DestVar = llvm::dyn_cast<Variable>(Dest)) {
1870       assert(!DestVar->hasReg());
1871       AsmAddress StackAddr(AsmAddress(DestVar, Target));
1872       Asm->movss(DestTy, StackAddr, SrcReg);
1873     } else {
1874       const auto DestMem = llvm::cast<X86OperandMem>(Dest);
1875       assert(DestMem->getSegmentRegister() == X86OperandMem::DefaultSegment);
1876       Asm->movss(DestTy, AsmAddress(DestMem, Asm, Target), SrcReg);
1877     }
1878     return;
1879   } else {
1880     assert(isScalarIntegerType(DestTy));
1881     static const GPREmitterAddrOp GPRAddrEmitter = {&Assembler::mov,
1882                                                     &Assembler::mov};
1883     emitIASAsAddrOpTyGPR(Func, DestTy, Dest, Src, GPRAddrEmitter);
1884   }
1885 }
1886 
dump(const Cfg * Func) const1887 void InstX86Store::dump(const Cfg *Func) const {
1888   if (!BuildDefs::dump())
1889     return;
1890   Ostream &Str = Func->getContext()->getStrDump();
1891   Str << "mov." << this->getSrc(0)->getType() << " ";
1892   this->getSrc(1)->dump(Func);
1893   Str << ", ";
1894   this->getSrc(0)->dump(Func);
1895 }
1896 
emit(const Cfg * Func) const1897 void InstX86StoreP::emit(const Cfg *Func) const {
1898   if (!BuildDefs::dump())
1899     return;
1900   Ostream &Str = Func->getContext()->getStrEmit();
1901   assert(this->getSrcSize() == 2);
1902   assert(isVectorType(this->getSrc(1)->getType()));
1903   Str << "\t"
1904          "movups\t";
1905   this->getSrc(0)->emit(Func);
1906   Str << ", ";
1907   this->getSrc(1)->emit(Func);
1908 }
1909 
emitIAS(const Cfg * Func) const1910 void InstX86StoreP::emitIAS(const Cfg *Func) const {
1911   Assembler *Asm = Func->getAssembler<Assembler>();
1912   assert(this->getSrcSize() == 2);
1913   const auto *SrcVar = llvm::cast<Variable>(this->getSrc(0));
1914   const auto DestMem = llvm::cast<X86OperandMem>(this->getSrc(1));
1915   assert(DestMem->getSegmentRegister() == X86OperandMem::DefaultSegment);
1916   assert(SrcVar->hasReg());
1917   auto *Target = InstX86Base::getTarget(Func);
1918   Asm->movups(AsmAddress(DestMem, Asm, Target),
1919               RegX8632::getEncodedXmm(SrcVar->getRegNum()));
1920 }
1921 
dump(const Cfg * Func) const1922 void InstX86StoreP::dump(const Cfg *Func) const {
1923   if (!BuildDefs::dump())
1924     return;
1925   Ostream &Str = Func->getContext()->getStrDump();
1926   Str << "storep." << this->getSrc(0)->getType() << " ";
1927   this->getSrc(1)->dump(Func);
1928   Str << ", ";
1929   this->getSrc(0)->dump(Func);
1930 }
1931 
emit(const Cfg * Func) const1932 void InstX86StoreQ::emit(const Cfg *Func) const {
1933   if (!BuildDefs::dump())
1934     return;
1935   Ostream &Str = Func->getContext()->getStrEmit();
1936   assert(this->getSrcSize() == 2);
1937   assert(this->getSrc(1)->getType() == IceType_i64 ||
1938          this->getSrc(1)->getType() == IceType_f64 ||
1939          isVectorType(this->getSrc(1)->getType()));
1940   Str << "\t"
1941          "movq\t";
1942   this->getSrc(0)->emit(Func);
1943   Str << ", ";
1944   this->getSrc(1)->emit(Func);
1945 }
1946 
emitIAS(const Cfg * Func) const1947 void InstX86StoreQ::emitIAS(const Cfg *Func) const {
1948   Assembler *Asm = Func->getAssembler<Assembler>();
1949   assert(this->getSrcSize() == 2);
1950   const auto *SrcVar = llvm::cast<Variable>(this->getSrc(0));
1951   const auto DestMem = llvm::cast<X86OperandMem>(this->getSrc(1));
1952   assert(DestMem->getSegmentRegister() == X86OperandMem::DefaultSegment);
1953   assert(SrcVar->hasReg());
1954   auto *Target = InstX86Base::getTarget(Func);
1955   Asm->movq(AsmAddress(DestMem, Asm, Target),
1956             RegX8632::getEncodedXmm(SrcVar->getRegNum()));
1957 }
1958 
dump(const Cfg * Func) const1959 void InstX86StoreQ::dump(const Cfg *Func) const {
1960   if (!BuildDefs::dump())
1961     return;
1962   Ostream &Str = Func->getContext()->getStrDump();
1963   Str << "storeq." << this->getSrc(0)->getType() << " ";
1964   this->getSrc(1)->dump(Func);
1965   Str << ", ";
1966   this->getSrc(0)->dump(Func);
1967 }
1968 
emit(const Cfg * Func) const1969 void InstX86StoreD::emit(const Cfg *Func) const {
1970   if (!BuildDefs::dump())
1971     return;
1972   Ostream &Str = Func->getContext()->getStrEmit();
1973   assert(this->getSrcSize() == 2);
1974   assert(this->getSrc(1)->getType() == IceType_i64 ||
1975          this->getSrc(1)->getType() == IceType_f64 ||
1976          isVectorType(this->getSrc(1)->getType()));
1977   Str << "\t"
1978          "movd\t";
1979   this->getSrc(0)->emit(Func);
1980   Str << ", ";
1981   this->getSrc(1)->emit(Func);
1982 }
1983 
emitIAS(const Cfg * Func) const1984 void InstX86StoreD::emitIAS(const Cfg *Func) const {
1985   Assembler *Asm = Func->getAssembler<Assembler>();
1986   assert(this->getSrcSize() == 2);
1987   const auto *SrcVar = llvm::cast<Variable>(this->getSrc(0));
1988   const auto DestMem = llvm::cast<X86OperandMem>(this->getSrc(1));
1989   assert(DestMem->getSegmentRegister() == X86OperandMem::DefaultSegment);
1990   assert(SrcVar->hasReg());
1991   auto *Target = InstX86Base::getTarget(Func);
1992   Asm->movd(SrcVar->getType(), AsmAddress(DestMem, Asm, Target),
1993             RegX8632::getEncodedXmm(SrcVar->getRegNum()));
1994 }
1995 
dump(const Cfg * Func) const1996 void InstX86StoreD::dump(const Cfg *Func) const {
1997   if (!BuildDefs::dump())
1998     return;
1999   Ostream &Str = Func->getContext()->getStrDump();
2000   Str << "stored." << this->getSrc(0)->getType() << " ";
2001   this->getSrc(1)->dump(Func);
2002   Str << ", ";
2003   this->getSrc(0)->dump(Func);
2004 }
2005 
emit(const Cfg * Func) const2006 void InstX86Lea::emit(const Cfg *Func) const {
2007   if (!BuildDefs::dump())
2008     return;
2009   if (auto *Add = this->deoptToAddOrNull(Func)) {
2010     Add->emit(Func);
2011     return;
2012   }
2013 
2014   Ostream &Str = Func->getContext()->getStrEmit();
2015   assert(this->getSrcSize() == 1);
2016   assert(this->getDest()->hasReg());
2017   Str << "\t"
2018          "lea"
2019       << this->getWidthString(this->getDest()->getType()) << "\t";
2020   Operand *Src0 = this->getSrc(0);
2021   if (const auto *Src0Var = llvm::dyn_cast<Variable>(Src0)) {
2022     Type Ty = Src0Var->getType();
2023     // lea on x86-32 doesn't accept mem128 operands, so cast VSrc0 to an
2024     // acceptable type.
2025     Src0Var->asType(Func, isVectorType(Ty) ? IceType_i32 : Ty, RegNumT())
2026         ->emit(Func);
2027   } else {
2028     Src0->emit(Func);
2029   }
2030   Str << ", ";
2031   this->getDest()->emit(Func);
2032 }
2033 
emitIAS(const Cfg * Func) const2034 void InstX86Lea::emitIAS(const Cfg *Func) const {
2035   assert(this->getSrcSize() == 1);
2036   const Variable *Var = this->getDest();
2037   Type Ty = Var->getType();
2038   const Operand *Src = this->getSrc(0);
2039 
2040   if (auto *Add = this->deoptToAddOrNull(Func)) {
2041     Add->emitIAS(Func);
2042     return;
2043   }
2044 
2045   emitIASRegOpTyGPR(Func, Ty, Var, Src, Emitter);
2046 }
2047 
deoptToAddOrNull(const Cfg * Func) const2048 Inst *InstX86Lea::deoptToAddOrNull(const Cfg *Func) const {
2049   // Revert back to Add when the Lea is a 2-address instruction.
2050   // Caller has to emit, this just produces the add instruction.
2051   if (auto *MemOp = llvm::dyn_cast<X86OperandMem>(this->getSrc(0))) {
2052     if (getFlags().getAggressiveLea() &&
2053         MemOp->getBase()->getRegNum() == this->getDest()->getRegNum() &&
2054         MemOp->getIndex() == nullptr && MemOp->getShift() == 0) {
2055       auto *Add = InstX86Add::create(const_cast<Cfg *>(Func), this->getDest(),
2056                                      MemOp->getOffset());
2057       // TODO(manasijm): Remove const_cast by emitting code for add
2058       // directly.
2059       return Add;
2060     }
2061   }
2062   return nullptr;
2063 }
2064 
emit(const Cfg * Func) const2065 void InstX86Mov::emit(const Cfg *Func) const {
2066   if (!BuildDefs::dump())
2067     return;
2068   Ostream &Str = Func->getContext()->getStrEmit();
2069   assert(this->getSrcSize() == 1);
2070   Operand *Src = this->getSrc(0);
2071   Type SrcTy = Src->getType();
2072   Type DestTy = this->getDest()->getType();
2073   Str << "\t"
2074          "mov"
2075       << (!isScalarFloatingType(DestTy) ? this->getWidthString(DestTy)
2076                                         : TypeAttributes[DestTy].SdSsString)
2077       << "\t";
2078   // For an integer truncation operation, src is wider than dest. In this case,
2079   // we use a mov instruction whose data width matches the narrower dest.
2080   // TODO: This assert disallows usages such as copying a floating
2081   // point value between a vector and a scalar (which movss is used for). Clean
2082   // this up.
2083   assert(InstX86Base::getTarget(Func)->typeWidthInBytesOnStack(DestTy) ==
2084          InstX86Base::getTarget(Func)->typeWidthInBytesOnStack(SrcTy));
2085   const Operand *NewSrc = Src;
2086   if (auto *SrcVar = llvm::dyn_cast<Variable>(Src)) {
2087     RegNumT NewRegNum;
2088     if (SrcVar->hasReg())
2089       NewRegNum = RegX8632::getGprForType(DestTy, SrcVar->getRegNum());
2090     if (SrcTy != DestTy)
2091       NewSrc = SrcVar->asType(Func, DestTy, NewRegNum);
2092   }
2093   NewSrc->emit(Func);
2094   Str << ", ";
2095   this->getDest()->emit(Func);
2096 }
2097 
emitIAS(const Cfg * Func) const2098 void InstX86Mov::emitIAS(const Cfg *Func) const {
2099   assert(this->getSrcSize() == 1);
2100   const Variable *Dest = this->getDest();
2101   const Operand *Src = this->getSrc(0);
2102   Type DestTy = Dest->getType();
2103   Type SrcTy = Src->getType();
2104   // Mov can be used for GPRs or XMM registers. Also, the type does not
2105   // necessarily match (Mov can be used for bitcasts). However, when the type
2106   // does not match, one of the operands must be a register. Thus, the strategy
2107   // is to find out if Src or Dest are a register, then use that register's
2108   // type to decide on which emitter set to use. The emitter set will include
2109   // reg-reg movs, but that case should be unused when the types don't match.
2110   static const XmmEmitterRegOp XmmRegEmitter = {&Assembler::movss,
2111                                                 &Assembler::movss};
2112   static const GPREmitterRegOp GPRRegEmitter = {
2113       &Assembler::mov, &Assembler::mov, &Assembler::mov};
2114   static const GPREmitterAddrOp GPRAddrEmitter = {&Assembler::mov,
2115                                                   &Assembler::mov};
2116   // For an integer truncation operation, src is wider than dest. In this case,
2117   // we use a mov instruction whose data width matches the narrower dest.
2118   // TODO: This assert disallows usages such as copying a floating
2119   // point value between a vector and a scalar (which movss is used for). Clean
2120   // this up.
2121   auto *Target = InstX86Base::getTarget(Func);
2122   assert(Target->typeWidthInBytesOnStack(this->getDest()->getType()) ==
2123          Target->typeWidthInBytesOnStack(Src->getType()));
2124   if (Dest->hasReg()) {
2125     if (isScalarFloatingType(DestTy)) {
2126       emitIASRegOpTyXMM(Func, DestTy, Dest, Src, XmmRegEmitter);
2127       return;
2128     } else {
2129       assert(isScalarIntegerType(DestTy));
2130       // Widen DestTy for truncation (see above note). We should only do this
2131       // when both Src and Dest are integer types.
2132       if (isScalarIntegerType(SrcTy)) {
2133         SrcTy = DestTy;
2134       }
2135       emitIASRegOpTyGPR(Func, DestTy, Dest, Src, GPRRegEmitter);
2136       return;
2137     }
2138   } else {
2139     // Dest must be Stack and Src *could* be a register. Use Src's type to
2140     // decide on the emitters.
2141     AsmAddress StackAddr(AsmAddress(Dest, Target));
2142     if (isScalarFloatingType(SrcTy)) {
2143       // Src must be a register.
2144       const auto *SrcVar = llvm::cast<Variable>(Src);
2145       assert(SrcVar->hasReg());
2146       Assembler *Asm = Func->getAssembler<Assembler>();
2147       Asm->movss(SrcTy, StackAddr,
2148                  RegX8632::getEncodedXmm(SrcVar->getRegNum()));
2149       return;
2150     } else if (isVectorType(SrcTy)) {
2151       // Src must be a register
2152       const auto *SrcVar = llvm::cast<Variable>(Src);
2153       assert(SrcVar->hasReg());
2154       Assembler *Asm = Func->getAssembler<Assembler>();
2155       Asm->movups(StackAddr, RegX8632::getEncodedXmm(SrcVar->getRegNum()));
2156     } else {
2157       // Src can be a register or immediate.
2158       assert(isScalarIntegerType(SrcTy));
2159       emitIASAddrOpTyGPR(Func, SrcTy, StackAddr, Src, GPRAddrEmitter);
2160       return;
2161     }
2162     return;
2163   }
2164 }
2165 
emit(const Cfg * Func) const2166 void InstX86Movd::emit(const Cfg *Func) const {
2167   if (!BuildDefs::dump())
2168     return;
2169   assert(this->getSrcSize() == 1);
2170   Variable *Dest = this->getDest();
2171   Operand *Src = this->getSrc(0);
2172 
2173   if (Dest->getType() == IceType_i64 || Src->getType() == IceType_i64) {
2174     assert(Dest->getType() == IceType_f64 || Src->getType() == IceType_f64);
2175     assert(Dest->getType() != Src->getType());
2176     Ostream &Str = Func->getContext()->getStrEmit();
2177     Str << "\t"
2178            "movq"
2179            "\t";
2180     Src->emit(Func);
2181     Str << ", ";
2182     Dest->emit(Func);
2183     return;
2184   }
2185 
2186   InstX86BaseUnaryopXmm<InstX86Base::Movd>::emit(Func);
2187 }
2188 
emitIAS(const Cfg * Func) const2189 void InstX86Movd::emitIAS(const Cfg *Func) const {
2190   Assembler *Asm = Func->getAssembler<Assembler>();
2191   assert(this->getSrcSize() == 1);
2192   const Variable *Dest = this->getDest();
2193   auto *Target = InstX86Base::getTarget(Func);
2194   // For insert/extract element (one of Src/Dest is an Xmm vector and the other
2195   // is an int type).
2196   if (const auto *SrcVar = llvm::dyn_cast<Variable>(this->getSrc(0))) {
2197     if (SrcVar->getType() == IceType_i32) {
2198       assert(isVectorType(Dest->getType()) ||
2199              (isScalarFloatingType(Dest->getType()) &&
2200               typeWidthInBytes(SrcVar->getType()) ==
2201                   typeWidthInBytes(Dest->getType())));
2202       assert(Dest->hasReg());
2203       XmmRegister DestReg = RegX8632::getEncodedXmm(Dest->getRegNum());
2204       if (SrcVar->hasReg()) {
2205         Asm->movd(SrcVar->getType(), DestReg,
2206                   RegX8632::getEncodedGPR(SrcVar->getRegNum()));
2207       } else {
2208         AsmAddress StackAddr(AsmAddress(SrcVar, Target));
2209         Asm->movd(SrcVar->getType(), DestReg, StackAddr);
2210       }
2211     } else {
2212       assert(isVectorType(SrcVar->getType()) ||
2213              (isScalarFloatingType(SrcVar->getType()) &&
2214               typeWidthInBytes(SrcVar->getType()) ==
2215                   typeWidthInBytes(Dest->getType())));
2216       assert(SrcVar->hasReg());
2217       assert(Dest->getType() == IceType_i32);
2218       XmmRegister SrcReg = RegX8632::getEncodedXmm(SrcVar->getRegNum());
2219       if (Dest->hasReg()) {
2220         Asm->movd(Dest->getType(), RegX8632::getEncodedGPR(Dest->getRegNum()),
2221                   SrcReg);
2222       } else {
2223         AsmAddress StackAddr(AsmAddress(Dest, Target));
2224         Asm->movd(Dest->getType(), StackAddr, SrcReg);
2225       }
2226     }
2227   } else {
2228     assert(Dest->hasReg());
2229     XmmRegister DestReg = RegX8632::getEncodedXmm(Dest->getRegNum());
2230     auto *Mem = llvm::cast<X86OperandMem>(this->getSrc(0));
2231     Asm->movd(Mem->getType(), DestReg, AsmAddress(Mem, Asm, Target));
2232   }
2233 }
2234 
emit(const Cfg * Func) const2235 void InstX86Movp::emit(const Cfg *Func) const {
2236   if (!BuildDefs::dump())
2237     return;
2238   // TODO(wala,stichnot): movups works with all vector operands, but there
2239   // exist other instructions (movaps, movdqa, movdqu) that may perform better,
2240   // depending on the data type and alignment of the operands.
2241   Ostream &Str = Func->getContext()->getStrEmit();
2242   assert(this->getSrcSize() == 1);
2243   Str << "\t"
2244          "movups\t";
2245   this->getSrc(0)->emit(Func);
2246   Str << ", ";
2247   this->getDest()->emit(Func);
2248 }
2249 
emitIAS(const Cfg * Func) const2250 void InstX86Movp::emitIAS(const Cfg *Func) const {
2251   assert(this->getSrcSize() == 1);
2252   assert(isVectorType(this->getDest()->getType()));
2253   const Variable *Dest = this->getDest();
2254   const Operand *Src = this->getSrc(0);
2255   static const XmmEmitterMovOps Emitter = {
2256       &Assembler::movups, &Assembler::movups, &Assembler::movups};
2257   emitIASMovlikeXMM(Func, Dest, Src, Emitter);
2258 }
2259 
emit(const Cfg * Func) const2260 void InstX86Movq::emit(const Cfg *Func) const {
2261   if (!BuildDefs::dump())
2262     return;
2263   Ostream &Str = Func->getContext()->getStrEmit();
2264   assert(this->getSrcSize() == 1);
2265   assert(this->getDest()->getType() == IceType_i64 ||
2266          this->getDest()->getType() == IceType_f64);
2267   Str << "\t"
2268          "movq"
2269          "\t";
2270   this->getSrc(0)->emit(Func);
2271   Str << ", ";
2272   this->getDest()->emit(Func);
2273 }
2274 
emitIAS(const Cfg * Func) const2275 void InstX86Movq::emitIAS(const Cfg *Func) const {
2276   assert(this->getSrcSize() == 1);
2277   assert(this->getDest()->getType() == IceType_i64 ||
2278          this->getDest()->getType() == IceType_f64 ||
2279          isVectorType(this->getDest()->getType()));
2280   const Variable *Dest = this->getDest();
2281   const Operand *Src = this->getSrc(0);
2282   static const XmmEmitterMovOps Emitter = {&Assembler::movq, &Assembler::movq,
2283                                            &Assembler::movq};
2284   emitIASMovlikeXMM(Func, Dest, Src, Emitter);
2285 }
2286 
emitIAS(const Cfg * Func) const2287 void InstX86MovssRegs::emitIAS(const Cfg *Func) const {
2288   // This is Binop variant is only intended to be used for reg-reg moves where
2289   // part of the Dest register is untouched.
2290   assert(this->getSrcSize() == 2);
2291   const Variable *Dest = this->getDest();
2292   assert(Dest == this->getSrc(0));
2293   const auto *SrcVar = llvm::cast<Variable>(this->getSrc(1));
2294   assert(Dest->hasReg() && SrcVar->hasReg());
2295   Assembler *Asm = Func->getAssembler<Assembler>();
2296   Asm->movss(IceType_f32, RegX8632::getEncodedXmm(Dest->getRegNum()),
2297              RegX8632::getEncodedXmm(SrcVar->getRegNum()));
2298 }
2299 
emitIAS(const Cfg * Func) const2300 void InstX86Movsx::emitIAS(const Cfg *Func) const {
2301   assert(this->getSrcSize() == 1);
2302   const Variable *Dest = this->getDest();
2303   const Operand *Src = this->getSrc(0);
2304   // Dest must be a > 8-bit register, but Src can be 8-bit. In practice we just
2305   // use the full register for Dest to avoid having an OperandSizeOverride
2306   // prefix. It also allows us to only dispatch on SrcTy.
2307   Type SrcTy = Src->getType();
2308   assert(typeWidthInBytes(Dest->getType()) > 1);
2309   assert(typeWidthInBytes(Dest->getType()) > typeWidthInBytes(SrcTy));
2310   emitIASRegOpTyGPR<false, true>(Func, SrcTy, Dest, Src, this->Emitter);
2311 }
2312 
emit(const Cfg * Func) const2313 void InstX86Movzx::emit(const Cfg *Func) const {
2314   if (!BuildDefs::dump())
2315     return;
2316   InstX86BaseUnaryopGPR<InstX86Base::Movzx>::emit(Func);
2317 }
2318 
emitIAS(const Cfg * Func) const2319 void InstX86Movzx::emitIAS(const Cfg *Func) const {
2320   assert(this->getSrcSize() == 1);
2321   const Variable *Dest = this->getDest();
2322   const Operand *Src = this->getSrc(0);
2323   Type SrcTy = Src->getType();
2324   assert(typeWidthInBytes(Dest->getType()) > 1);
2325   assert(typeWidthInBytes(Dest->getType()) > typeWidthInBytes(SrcTy));
2326   emitIASRegOpTyGPR<false, true>(Func, SrcTy, Dest, Src, this->Emitter);
2327 }
2328 
emit(const Cfg * Func) const2329 void InstX86Nop::emit(const Cfg *Func) const {
2330   if (!BuildDefs::dump())
2331     return;
2332   Ostream &Str = Func->getContext()->getStrEmit();
2333   // TODO: Emit the right code for each variant.
2334   Str << "\t"
2335          "nop\t/* variant = "
2336       << Variant << " */";
2337 }
2338 
emitIAS(const Cfg * Func) const2339 void InstX86Nop::emitIAS(const Cfg *Func) const {
2340   Assembler *Asm = Func->getAssembler<Assembler>();
2341   // TODO: Emit the right code for the variant.
2342   Asm->nop();
2343 }
2344 
dump(const Cfg * Func) const2345 void InstX86Nop::dump(const Cfg *Func) const {
2346   if (!BuildDefs::dump())
2347     return;
2348   Ostream &Str = Func->getContext()->getStrDump();
2349   Str << "nop (variant = " << Variant << ")";
2350 }
2351 
emit(const Cfg * Func) const2352 void InstX86Fld::emit(const Cfg *Func) const {
2353   if (!BuildDefs::dump())
2354     return;
2355   Ostream &Str = Func->getContext()->getStrEmit();
2356   assert(this->getSrcSize() == 1);
2357   Type Ty = this->getSrc(0)->getType();
2358   const auto *Var = llvm::dyn_cast<Variable>(this->getSrc(0));
2359   if (Var && Var->hasReg()) {
2360     // This is a physical xmm register, so we need to spill it to a temporary
2361     // stack slot.  Function prolog emission guarantees that there is sufficient
2362     // space to do this.
2363     Str << "\t"
2364            "mov"
2365         << TypeAttributes[Ty].SdSsString << "\t";
2366     Var->emit(Func);
2367     Str << ", (%esp)\n"
2368            "\t"
2369            "fld"
2370         << this->getFldString(Ty)
2371         << "\t"
2372            "(%esp)";
2373     return;
2374   }
2375   Str << "\t"
2376          "fld"
2377       << this->getFldString(Ty) << "\t";
2378   this->getSrc(0)->emit(Func);
2379 }
2380 
emitIAS(const Cfg * Func) const2381 void InstX86Fld::emitIAS(const Cfg *Func) const {
2382   Assembler *Asm = Func->getAssembler<Assembler>();
2383   assert(this->getSrcSize() == 1);
2384   const Operand *Src = this->getSrc(0);
2385   auto *Target = InstX86Base::getTarget(Func);
2386   Type Ty = Src->getType();
2387   if (const auto *Var = llvm::dyn_cast<Variable>(Src)) {
2388     if (Var->hasReg()) {
2389       // This is a physical xmm register, so we need to spill it to a temporary
2390       // stack slot.  Function prolog emission guarantees that there is
2391       // sufficient space to do this.
2392       AsmAddress StackSlot = AsmAddress(RegisterSet::Encoded_Reg_esp, 0);
2393       Asm->movss(Ty, StackSlot, RegX8632::getEncodedXmm(Var->getRegNum()));
2394       Asm->fld(Ty, StackSlot);
2395     } else {
2396       AsmAddress StackAddr(AsmAddress(Var, Target));
2397       Asm->fld(Ty, StackAddr);
2398     }
2399   } else if (const auto *Mem = llvm::dyn_cast<X86OperandMem>(Src)) {
2400     assert(Mem->getSegmentRegister() == X86OperandMem::DefaultSegment);
2401     Asm->fld(Ty, AsmAddress(Mem, Asm, Target));
2402   } else if (const auto *Imm = llvm::dyn_cast<Constant>(Src)) {
2403     Asm->fld(Ty, AsmAddress(Imm, Asm));
2404   } else {
2405     llvm_unreachable("Unexpected operand type");
2406   }
2407 }
2408 
dump(const Cfg * Func) const2409 void InstX86Fld::dump(const Cfg *Func) const {
2410   if (!BuildDefs::dump())
2411     return;
2412   Ostream &Str = Func->getContext()->getStrDump();
2413   Str << "fld." << this->getSrc(0)->getType() << " ";
2414   this->dumpSources(Func);
2415 }
2416 
emit(const Cfg * Func) const2417 void InstX86Fstp::emit(const Cfg *Func) const {
2418   if (!BuildDefs::dump())
2419     return;
2420   Ostream &Str = Func->getContext()->getStrEmit();
2421   assert(this->getSrcSize() == 0);
2422   // TODO(jvoung,stichnot): Utilize this by setting Dest to nullptr to
2423   // "partially" delete the fstp if the Dest is unused. Even if Dest is unused,
2424   // the fstp should be kept for the SideEffects of popping the stack.
2425   if (!this->getDest()) {
2426     Str << "\t"
2427            "fstp\t"
2428            "st(0)";
2429     return;
2430   }
2431   Type Ty = this->getDest()->getType();
2432   if (!this->getDest()->hasReg()) {
2433     Str << "\t"
2434            "fstp"
2435         << this->getFldString(Ty) << "\t";
2436     this->getDest()->emit(Func);
2437     return;
2438   }
2439   // Dest is a physical (xmm) register, so st(0) needs to go through memory.
2440   // Hack this by using caller-reserved memory at the top of stack, spilling
2441   // st(0) there, and loading it into the xmm register.
2442   Str << "\t"
2443          "fstp"
2444       << this->getFldString(Ty)
2445       << "\t"
2446          "(%esp)\n";
2447   Str << "\t"
2448          "mov"
2449       << TypeAttributes[Ty].SdSsString
2450       << "\t"
2451          "(%esp), ";
2452   this->getDest()->emit(Func);
2453 }
2454 
emitIAS(const Cfg * Func) const2455 void InstX86Fstp::emitIAS(const Cfg *Func) const {
2456   Assembler *Asm = Func->getAssembler<Assembler>();
2457   assert(this->getSrcSize() == 0);
2458   const Variable *Dest = this->getDest();
2459   // TODO(jvoung,stichnot): Utilize this by setting Dest to nullptr to
2460   // "partially" delete the fstp if the Dest is unused. Even if Dest is unused,
2461   // the fstp should be kept for the SideEffects of popping the stack.
2462   if (!Dest) {
2463     Asm->fstp(RegisterSet::getEncodedSTReg(0));
2464     return;
2465   }
2466   auto *Target = InstX86Base::getTarget(Func);
2467   Type Ty = Dest->getType();
2468   if (!Dest->hasReg()) {
2469     AsmAddress StackAddr(AsmAddress(Dest, Target));
2470     Asm->fstp(Ty, StackAddr);
2471   } else {
2472     // Dest is a physical (xmm) register, so st(0) needs to go through memory.
2473     // Hack this by using caller-reserved memory at the top of stack, spilling
2474     // st(0) there, and loading it into the xmm register.
2475     AsmAddress StackSlot = AsmAddress(RegisterSet::Encoded_Reg_esp, 0);
2476     Asm->fstp(Ty, StackSlot);
2477     Asm->movss(Ty, RegX8632::getEncodedXmm(Dest->getRegNum()), StackSlot);
2478   }
2479 }
2480 
dump(const Cfg * Func) const2481 void InstX86Fstp::dump(const Cfg *Func) const {
2482   if (!BuildDefs::dump())
2483     return;
2484   Ostream &Str = Func->getContext()->getStrDump();
2485   this->dumpDest(Func);
2486   Str << " = fstp." << this->getDest()->getType() << ", st(0)";
2487 }
2488 
emit(const Cfg * Func) const2489 void InstX86Pextr::emit(const Cfg *Func) const {
2490   if (!BuildDefs::dump())
2491     return;
2492   Ostream &Str = Func->getContext()->getStrEmit();
2493   assert(this->getSrcSize() == 2);
2494   // pextrb and pextrd are SSE4.1 instructions.
2495   Str << "\t" << this->Opcode
2496       << TypeAttributes[this->getSrc(0)->getType()].IntegralString << "\t";
2497   this->getSrc(1)->emit(Func);
2498   Str << ", ";
2499   this->getSrc(0)->emit(Func);
2500   Str << ", ";
2501   Variable *Dest = this->getDest();
2502   // pextrw must take a register dest. There is an SSE4.1 version that takes a
2503   // memory dest, but we aren't using it. For uniformity, just restrict them
2504   // all to have a register dest for now.
2505   assert(Dest->hasReg());
2506   Dest->asType(Func, IceType_i32, Dest->getRegNum())->emit(Func);
2507 }
2508 
emitIAS(const Cfg * Func) const2509 void InstX86Pextr::emitIAS(const Cfg *Func) const {
2510   assert(this->getSrcSize() == 2);
2511   // pextrb and pextrd are SSE4.1 instructions.
2512   const Variable *Dest = this->getDest();
2513   Type DispatchTy = getInVectorElementType(this->getSrc(0)->getType());
2514   // pextrw must take a register dest. There is an SSE4.1 version that takes a
2515   // memory dest, but we aren't using it. For uniformity, just restrict them
2516   // all to have a register dest for now.
2517   assert(Dest->hasReg());
2518   // pextrw's Src(0) must be a register (both SSE4.1 and SSE2).
2519   assert(llvm::cast<Variable>(this->getSrc(0))->hasReg());
2520   static const ThreeOpImmEmitter<GPRRegister, XmmRegister> Emitter = {
2521       &Assembler::pextr, nullptr};
2522   emitIASThreeOpImmOps<GPRRegister, XmmRegister, RegX8632::getEncodedGPR,
2523                        RegX8632::getEncodedXmm>(
2524       Func, DispatchTy, Dest, this->getSrc(0), this->getSrc(1), Emitter);
2525 }
2526 
emit(const Cfg * Func) const2527 void InstX86Pinsr::emit(const Cfg *Func) const {
2528   if (!BuildDefs::dump())
2529     return;
2530   Ostream &Str = Func->getContext()->getStrEmit();
2531   assert(this->getSrcSize() == 3);
2532   Str << "\t" << this->Opcode
2533       << TypeAttributes[this->getDest()->getType()].IntegralString << "\t";
2534   this->getSrc(2)->emit(Func);
2535   Str << ", ";
2536   Operand *Src1 = this->getSrc(1);
2537   if (const auto *Src1Var = llvm::dyn_cast<Variable>(Src1)) {
2538     // If src1 is a register, it should always be r32.
2539     if (Src1Var->hasReg()) {
2540       const auto NewRegNum = RegX8632::getBaseReg(Src1Var->getRegNum());
2541       const Variable *NewSrc = Src1Var->asType(Func, IceType_i32, NewRegNum);
2542       NewSrc->emit(Func);
2543     } else {
2544       Src1Var->emit(Func);
2545     }
2546   } else {
2547     Src1->emit(Func);
2548   }
2549   Str << ", ";
2550   this->getDest()->emit(Func);
2551 }
2552 
emitIAS(const Cfg * Func) const2553 void InstX86Pinsr::emitIAS(const Cfg *Func) const {
2554   assert(this->getSrcSize() == 3);
2555   assert(this->getDest() == this->getSrc(0));
2556   // pinsrb and pinsrd are SSE4.1 instructions.
2557   const Operand *Src0 = this->getSrc(1);
2558   Type DispatchTy = Src0->getType();
2559   // If src1 is a register, it should always be r32 (this should fall out from
2560   // the encodings for ByteRegs overlapping the encodings for r32), but we have
2561   // to make sure the register allocator didn't choose an 8-bit high register
2562   // like "ah".
2563   if (BuildDefs::asserts()) {
2564     if (auto *Src0Var = llvm::dyn_cast<Variable>(Src0)) {
2565       if (Src0Var->hasReg()) {
2566         const auto RegNum = Src0Var->getRegNum();
2567         const auto BaseRegNum = RegX8632::getBaseReg(RegNum);
2568         (void)BaseRegNum;
2569         assert(RegX8632::getEncodedGPR(RegNum) ==
2570                RegX8632::getEncodedGPR(BaseRegNum));
2571       }
2572     }
2573   }
2574   static const ThreeOpImmEmitter<XmmRegister, GPRRegister> Emitter = {
2575       &Assembler::pinsr, &Assembler::pinsr};
2576   emitIASThreeOpImmOps<XmmRegister, GPRRegister, RegX8632::getEncodedXmm,
2577                        RegX8632::getEncodedGPR>(
2578       Func, DispatchTy, this->getDest(), Src0, this->getSrc(2), Emitter);
2579 }
2580 
emitIAS(const Cfg * Func) const2581 void InstX86Pshufd::emitIAS(const Cfg *Func) const {
2582   assert(this->getSrcSize() == 2);
2583   const Variable *Dest = this->getDest();
2584   Type Ty = Dest->getType();
2585   static const ThreeOpImmEmitter<XmmRegister, XmmRegister> Emitter = {
2586       &Assembler::pshufd, &Assembler::pshufd};
2587   emitIASThreeOpImmOps<XmmRegister, XmmRegister, RegX8632::getEncodedXmm,
2588                        RegX8632::getEncodedXmm>(Func, Ty, Dest, this->getSrc(0),
2589                                                 this->getSrc(1), Emitter);
2590 }
2591 
emitIAS(const Cfg * Func) const2592 void InstX86Shufps::emitIAS(const Cfg *Func) const {
2593   assert(this->getSrcSize() == 3);
2594   const Variable *Dest = this->getDest();
2595   assert(Dest == this->getSrc(0));
2596   Type Ty = Dest->getType();
2597   static const ThreeOpImmEmitter<XmmRegister, XmmRegister> Emitter = {
2598       &Assembler::shufps, &Assembler::shufps};
2599   emitIASThreeOpImmOps<XmmRegister, XmmRegister, RegX8632::getEncodedXmm,
2600                        RegX8632::getEncodedXmm>(Func, Ty, Dest, this->getSrc(1),
2601                                                 this->getSrc(2), Emitter);
2602 }
2603 
emit(const Cfg * Func) const2604 void InstX86Pop::emit(const Cfg *Func) const {
2605   if (!BuildDefs::dump())
2606     return;
2607   Ostream &Str = Func->getContext()->getStrEmit();
2608   assert(this->getSrcSize() == 0);
2609   Str << "\t"
2610          "pop\t";
2611   this->getDest()->emit(Func);
2612 }
2613 
emitIAS(const Cfg * Func) const2614 void InstX86Pop::emitIAS(const Cfg *Func) const {
2615   assert(this->getSrcSize() == 0);
2616   Assembler *Asm = Func->getAssembler<Assembler>();
2617   if (this->getDest()->hasReg()) {
2618     Asm->popl(RegX8632::getEncodedGPR(this->getDest()->getRegNum()));
2619   } else {
2620     auto *Target = InstX86Base::getTarget(Func);
2621     Asm->popl(AsmAddress(this->getDest(), Target));
2622   }
2623 }
2624 
dump(const Cfg * Func) const2625 void InstX86Pop::dump(const Cfg *Func) const {
2626   if (!BuildDefs::dump())
2627     return;
2628   Ostream &Str = Func->getContext()->getStrDump();
2629   this->dumpDest(Func);
2630   Str << " = pop." << this->getDest()->getType() << " ";
2631 }
2632 
emit(const Cfg * Func) const2633 void InstX86Push::emit(const Cfg *Func) const {
2634   if (!BuildDefs::dump())
2635     return;
2636   Ostream &Str = Func->getContext()->getStrEmit();
2637   Str << "\t"
2638          "push"
2639          "\t";
2640   assert(this->getSrcSize() == 1);
2641   const Operand *Src = this->getSrc(0);
2642   Src->emit(Func);
2643 }
2644 
emitIAS(const Cfg * Func) const2645 void InstX86Push::emitIAS(const Cfg *Func) const {
2646   Assembler *Asm = Func->getAssembler<Assembler>();
2647 
2648   assert(this->getSrcSize() == 1);
2649   const Operand *Src = this->getSrc(0);
2650 
2651   if (const auto *Var = llvm::dyn_cast<Variable>(Src)) {
2652     Asm->pushl(RegX8632::getEncodedGPR(Var->getRegNum()));
2653   } else if (const auto *Const32 = llvm::dyn_cast<ConstantInteger32>(Src)) {
2654     Asm->pushl(AssemblerImmediate(Const32->getValue()));
2655   } else if (auto *CR = llvm::dyn_cast<ConstantRelocatable>(Src)) {
2656     Asm->pushl(CR);
2657   } else {
2658     llvm_unreachable("Unexpected operand type");
2659   }
2660 }
2661 
dump(const Cfg * Func) const2662 void InstX86Push::dump(const Cfg *Func) const {
2663   if (!BuildDefs::dump())
2664     return;
2665   Ostream &Str = Func->getContext()->getStrDump();
2666   Str << "push." << this->getSrc(0)->getType() << " ";
2667   this->dumpSources(Func);
2668 }
2669 
emit(const Cfg * Func) const2670 void InstX86Ret::emit(const Cfg *Func) const {
2671   if (!BuildDefs::dump())
2672     return;
2673   Ostream &Str = Func->getContext()->getStrEmit();
2674   Str << "\t"
2675          "ret";
2676 }
2677 
emitIAS(const Cfg * Func) const2678 void InstX86Ret::emitIAS(const Cfg *Func) const {
2679   Assembler *Asm = Func->getAssembler<Assembler>();
2680   Asm->ret();
2681 }
2682 
dump(const Cfg * Func) const2683 void InstX86Ret::dump(const Cfg *Func) const {
2684   if (!BuildDefs::dump())
2685     return;
2686   Ostream &Str = Func->getContext()->getStrDump();
2687   Type Ty =
2688       (this->getSrcSize() == 0 ? IceType_void : this->getSrc(0)->getType());
2689   Str << "ret." << Ty << " ";
2690   this->dumpSources(Func);
2691 }
2692 
emit(const Cfg * Func) const2693 void InstX86Setcc::emit(const Cfg *Func) const {
2694   if (!BuildDefs::dump())
2695     return;
2696   Ostream &Str = Func->getContext()->getStrEmit();
2697   Str << "\t"
2698          "set"
2699       << InstBrAttributes[Condition].DisplayString << "\t";
2700   this->Dest->emit(Func);
2701 }
2702 
emitIAS(const Cfg * Func) const2703 void InstX86Setcc::emitIAS(const Cfg *Func) const {
2704   assert(Condition != Cond::Br_None);
2705   assert(this->getDest()->getType() == IceType_i1);
2706   assert(this->getSrcSize() == 0);
2707   Assembler *Asm = Func->getAssembler<Assembler>();
2708   auto *Target = InstX86Base::getTarget(Func);
2709   if (this->getDest()->hasReg())
2710     Asm->setcc(Condition,
2711                RegX8632::getEncodedByteReg(this->getDest()->getRegNum()));
2712   else
2713     Asm->setcc(Condition, AsmAddress(this->getDest(), Target));
2714   return;
2715 }
2716 
dump(const Cfg * Func) const2717 void InstX86Setcc::dump(const Cfg *Func) const {
2718   if (!BuildDefs::dump())
2719     return;
2720   Ostream &Str = Func->getContext()->getStrDump();
2721   Str << "setcc." << InstBrAttributes[Condition].DisplayString << " ";
2722   this->dumpDest(Func);
2723 }
2724 
emit(const Cfg * Func) const2725 void InstX86Xadd::emit(const Cfg *Func) const {
2726   if (!BuildDefs::dump())
2727     return;
2728   Ostream &Str = Func->getContext()->getStrEmit();
2729   if (this->Locked) {
2730     Str << "\t"
2731            "lock";
2732   }
2733   Str << "\t"
2734          "xadd"
2735       << this->getWidthString(this->getSrc(0)->getType()) << "\t";
2736   this->getSrc(1)->emit(Func);
2737   Str << ", ";
2738   this->getSrc(0)->emit(Func);
2739 }
2740 
emitIAS(const Cfg * Func) const2741 void InstX86Xadd::emitIAS(const Cfg *Func) const {
2742   assert(this->getSrcSize() == 2);
2743   Assembler *Asm = Func->getAssembler<Assembler>();
2744   Type Ty = this->getSrc(0)->getType();
2745   const auto Mem = llvm::cast<X86OperandMem>(this->getSrc(0));
2746   assert(Mem->getSegmentRegister() == X86OperandMem::DefaultSegment);
2747   auto *Target = InstX86Base::getTarget(Func);
2748   const AsmAddress Addr = AsmAddress(Mem, Asm, Target);
2749   const auto *VarReg = llvm::cast<Variable>(this->getSrc(1));
2750   assert(VarReg->hasReg());
2751   const GPRRegister Reg = RegX8632::getEncodedGPR(VarReg->getRegNum());
2752   Asm->xadd(Ty, Addr, Reg, this->Locked);
2753 }
2754 
dump(const Cfg * Func) const2755 void InstX86Xadd::dump(const Cfg *Func) const {
2756   if (!BuildDefs::dump())
2757     return;
2758   Ostream &Str = Func->getContext()->getStrDump();
2759   if (this->Locked) {
2760     Str << "lock ";
2761   }
2762   Type Ty = this->getSrc(0)->getType();
2763   Str << "xadd." << Ty << " ";
2764   this->dumpSources(Func);
2765 }
2766 
emit(const Cfg * Func) const2767 void InstX86Xchg::emit(const Cfg *Func) const {
2768   if (!BuildDefs::dump())
2769     return;
2770   Ostream &Str = Func->getContext()->getStrEmit();
2771   Str << "\t"
2772          "xchg"
2773       << this->getWidthString(this->getSrc(0)->getType()) << "\t";
2774   this->getSrc(1)->emit(Func);
2775   Str << ", ";
2776   this->getSrc(0)->emit(Func);
2777 }
2778 
emitIAS(const Cfg * Func) const2779 void InstX86Xchg::emitIAS(const Cfg *Func) const {
2780   assert(this->getSrcSize() == 2);
2781   Assembler *Asm = Func->getAssembler<Assembler>();
2782   Type Ty = this->getSrc(0)->getType();
2783   const auto *VarReg1 = llvm::cast<Variable>(this->getSrc(1));
2784   assert(VarReg1->hasReg());
2785   const GPRRegister Reg1 = RegX8632::getEncodedGPR(VarReg1->getRegNum());
2786 
2787   if (const auto *VarReg0 = llvm::dyn_cast<Variable>(this->getSrc(0))) {
2788     assert(VarReg0->hasReg());
2789     const GPRRegister Reg0 = RegX8632::getEncodedGPR(VarReg0->getRegNum());
2790     Asm->xchg(Ty, Reg0, Reg1);
2791     return;
2792   }
2793 
2794   const auto *Mem = llvm::cast<X86OperandMem>(this->getSrc(0));
2795   assert(Mem->getSegmentRegister() == X86OperandMem::DefaultSegment);
2796   auto *Target = InstX86Base::getTarget(Func);
2797   const AsmAddress Addr = AsmAddress(Mem, Asm, Target);
2798   Asm->xchg(Ty, Addr, Reg1);
2799 }
2800 
dump(const Cfg * Func) const2801 void InstX86Xchg::dump(const Cfg *Func) const {
2802   if (!BuildDefs::dump())
2803     return;
2804   Ostream &Str = Func->getContext()->getStrDump();
2805   Type Ty = this->getSrc(0)->getType();
2806   Str << "xchg." << Ty << " ";
2807   this->dumpSources(Func);
2808 }
2809 
emit(const Cfg * Func) const2810 void InstX86IacaStart::emit(const Cfg *Func) const {
2811   if (!BuildDefs::dump())
2812     return;
2813   Ostream &Str = Func->getContext()->getStrEmit();
2814   Str << "\t# IACA_START\n"
2815          "\t.byte 0x0F, 0x0B\n"
2816          "\t"
2817          "movl\t$111, %ebx\n"
2818          "\t.byte 0x64, 0x67, 0x90";
2819 }
2820 
emitIAS(const Cfg * Func) const2821 void InstX86IacaStart::emitIAS(const Cfg *Func) const {
2822   Assembler *Asm = Func->getAssembler<Assembler>();
2823   Asm->iaca_start();
2824 }
2825 
dump(const Cfg * Func) const2826 void InstX86IacaStart::dump(const Cfg *Func) const {
2827   if (!BuildDefs::dump())
2828     return;
2829   Ostream &Str = Func->getContext()->getStrDump();
2830   Str << "IACA_START";
2831 }
2832 
emit(const Cfg * Func) const2833 void InstX86IacaEnd::emit(const Cfg *Func) const {
2834   if (!BuildDefs::dump())
2835     return;
2836   Ostream &Str = Func->getContext()->getStrEmit();
2837   Str << "\t# IACA_END\n"
2838          "\t"
2839          "movl\t$222, %ebx\n"
2840          "\t.byte 0x64, 0x67, 0x90\n"
2841          "\t.byte 0x0F, 0x0B";
2842 }
2843 
emitIAS(const Cfg * Func) const2844 void InstX86IacaEnd::emitIAS(const Cfg *Func) const {
2845   Assembler *Asm = Func->getAssembler<Assembler>();
2846   Asm->iaca_end();
2847 }
2848 
dump(const Cfg * Func) const2849 void InstX86IacaEnd::dump(const Cfg *Func) const {
2850   if (!BuildDefs::dump())
2851     return;
2852   Ostream &Str = Func->getContext()->getStrDump();
2853   Str << "IACA_END";
2854 }
2855 
dump(const Cfg *,Ostream & Str) const2856 void X86Operand::dump(const Cfg *, Ostream &Str) const {
2857   if (BuildDefs::dump())
2858     Str << "<OperandX8632>";
2859 }
2860 
X86OperandMem(Cfg * Func,Type Ty,Variable * Base,Constant * Offset,Variable * Index,uint16_t Shift,SegmentRegisters SegmentReg,bool IsRebased)2861 X86OperandMem::X86OperandMem(Cfg *Func, Type Ty, Variable *Base,
2862                              Constant *Offset, Variable *Index, uint16_t Shift,
2863                              SegmentRegisters SegmentReg, bool IsRebased)
2864     : X86Operand(kMem, Ty), Base(Base), Offset(Offset), Index(Index),
2865       Shift(Shift), SegmentReg(SegmentReg), IsRebased(IsRebased) {
2866   assert(Shift <= 3);
2867   Vars = nullptr;
2868   NumVars = 0;
2869   if (Base)
2870     ++NumVars;
2871   if (Index)
2872     ++NumVars;
2873   if (NumVars) {
2874     Vars = Func->allocateArrayOf<Variable *>(NumVars);
2875     SizeT I = 0;
2876     if (Base)
2877       Vars[I++] = Base;
2878     if (Index)
2879       Vars[I++] = Index;
2880     assert(I == NumVars);
2881   }
2882 }
2883 
emit(const Cfg * Func) const2884 void X86OperandMem::emit(const Cfg *Func) const {
2885   if (!BuildDefs::dump())
2886     return;
2887   validateMemOperandPIC();
2888   const auto *Target =
2889       static_cast<const ::Ice::X8632::TargetX8632 *>(Func->getTarget());
2890   // If the base is rematerializable, we need to replace it with the correct
2891   // physical register (esp or ebp), and update the Offset.
2892   int32_t Disp = 0;
2893   if (getBase() && getBase()->isRematerializable()) {
2894     Disp += getBase()->getRematerializableOffset(Target);
2895   }
2896   // The index should never be rematerializable.  But if we ever allow it, then
2897   // we should make sure the rematerialization offset is shifted by the Shift
2898   // value.
2899   if (getIndex())
2900     assert(!getIndex()->isRematerializable());
2901   Ostream &Str = Func->getContext()->getStrEmit();
2902   if (SegmentReg != DefaultSegment) {
2903     assert(SegmentReg >= 0 && SegmentReg < SegReg_NUM);
2904     Str << "%" << InstSegmentRegNames[SegmentReg] << ":";
2905   }
2906   // Emit as Offset(Base,Index,1<<Shift). Offset is emitted without the leading
2907   // '$'. Omit the (Base,Index,1<<Shift) part if Base==nullptr.
2908   if (getOffset() == nullptr && Disp == 0) {
2909     // No offset, emit nothing.
2910   } else if (getOffset() == nullptr && Disp != 0) {
2911     Str << Disp;
2912   } else if (const auto *CI = llvm::dyn_cast<ConstantInteger32>(getOffset())) {
2913     if (getBase() == nullptr || CI->getValue() || Disp != 0)
2914       // Emit a non-zero offset without a leading '$'.
2915       Str << CI->getValue() + Disp;
2916   } else if (const auto *CR =
2917                  llvm::dyn_cast<ConstantRelocatable>(getOffset())) {
2918     // TODO(sehr): ConstantRelocatable still needs updating for
2919     // rematerializable base/index and Disp.
2920     assert(Disp == 0);
2921     CR->emitWithoutPrefix(Target);
2922   } else {
2923     llvm_unreachable("Invalid offset type for x86 mem operand");
2924   }
2925 
2926   if (getBase() || getIndex()) {
2927     Str << "(";
2928     if (getBase())
2929       getBase()->emit(Func);
2930     if (getIndex()) {
2931       Str << ",";
2932       getIndex()->emit(Func);
2933       if (getShift())
2934         Str << "," << (1u << getShift());
2935     }
2936     Str << ")";
2937   }
2938 }
2939 
dump(const Cfg * Func,Ostream & Str) const2940 void X86OperandMem::dump(const Cfg *Func, Ostream &Str) const {
2941   if (!BuildDefs::dump())
2942     return;
2943   if (SegmentReg != DefaultSegment) {
2944     assert(SegmentReg >= 0 && SegmentReg < SegReg_NUM);
2945     Str << InstSegmentRegNames[SegmentReg] << ":";
2946   }
2947   bool Dumped = false;
2948   Str << "[";
2949   int32_t Disp = 0;
2950   const auto *Target =
2951       static_cast<const ::Ice::X8632::TargetX8632 *>(Func->getTarget());
2952   if (getBase() && getBase()->isRematerializable()) {
2953     Disp += getBase()->getRematerializableOffset(Target);
2954   }
2955   if (getBase()) {
2956     if (Func)
2957       getBase()->dump(Func);
2958     else
2959       getBase()->dump(Str);
2960     Dumped = true;
2961   }
2962   if (getIndex()) {
2963     assert(!getIndex()->isRematerializable());
2964     if (getBase())
2965       Str << "+";
2966     if (getShift() > 0)
2967       Str << (1u << getShift()) << "*";
2968     if (Func)
2969       getIndex()->dump(Func);
2970     else
2971       getIndex()->dump(Str);
2972     Dumped = true;
2973   }
2974   if (Disp) {
2975     if (Disp > 0)
2976       Str << "+";
2977     Str << Disp;
2978     Dumped = true;
2979   }
2980   // Pretty-print the Offset.
2981   bool OffsetIsZero = false;
2982   bool OffsetIsNegative = false;
2983   if (getOffset() == nullptr) {
2984     OffsetIsZero = true;
2985   } else if (const auto *CI = llvm::dyn_cast<ConstantInteger32>(getOffset())) {
2986     OffsetIsZero = (CI->getValue() == 0);
2987     OffsetIsNegative = (static_cast<int32_t>(CI->getValue()) < 0);
2988   } else {
2989     assert(llvm::isa<ConstantRelocatable>(getOffset()));
2990   }
2991   if (Dumped) {
2992     if (!OffsetIsZero) {     // Suppress if Offset is known to be 0
2993       if (!OffsetIsNegative) // Suppress if Offset is known to be negative
2994         Str << "+";
2995       getOffset()->dump(Func, Str);
2996     }
2997   } else {
2998     // There is only the offset.
2999     getOffset()->dump(Func, Str);
3000   }
3001   Str << "]";
3002 }
3003 
emitSegmentOverride(Assembler * Asm) const3004 void X86OperandMem::emitSegmentOverride(Assembler *Asm) const {
3005   if (SegmentReg != DefaultSegment) {
3006     assert(SegmentReg >= 0 && SegmentReg < SegReg_NUM);
3007     Asm->emitSegmentOverride(InstSegmentPrefixes[SegmentReg]);
3008   }
3009 }
3010 
emit(const Cfg * Func) const3011 void VariableSplit::emit(const Cfg *Func) const {
3012   if (!BuildDefs::dump())
3013     return;
3014   Ostream &Str = Func->getContext()->getStrEmit();
3015   assert(!Var->hasReg());
3016   // The following is copied/adapted from TargetX8632::emitVariable().
3017   const ::Ice::TargetLowering *Target = Func->getTarget();
3018   constexpr Type Ty = IceType_i32;
3019   int32_t Offset = Var->getStackOffset() + getOffset();
3020   if (Offset)
3021     Str << Offset;
3022   Str << "(%" << Target->getRegName(Target->getFrameOrStackReg(), Ty) << ")";
3023 }
3024 
dump(const Cfg * Func,Ostream & Str) const3025 void VariableSplit::dump(const Cfg *Func, Ostream &Str) const {
3026   if (!BuildDefs::dump())
3027     return;
3028   switch (Part) {
3029   case Low:
3030     Str << "low";
3031     break;
3032   case High:
3033     Str << "high";
3034     break;
3035   }
3036   Str << "(";
3037   if (Func)
3038     Var->dump(Func);
3039   else
3040     Var->dump(Str);
3041   Str << ")";
3042 }
3043 
3044 } // namespace X8632
3045 } // end of namespace Ice
3046