xref: /freebsd/contrib/llvm-project/llvm/lib/Target/X86/AsmParser/X86Operand.h (revision 6966ac055c3b7a39266fb982493330df7a097997)
1 //===- X86Operand.h - Parsed X86 machine instruction ------------*- C++ -*-===//
2 //
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6 //
7 //===----------------------------------------------------------------------===//
8 
9 #ifndef LLVM_LIB_TARGET_X86_ASMPARSER_X86OPERAND_H
10 #define LLVM_LIB_TARGET_X86_ASMPARSER_X86OPERAND_H
11 
12 #include "MCTargetDesc/X86IntelInstPrinter.h"
13 #include "MCTargetDesc/X86MCTargetDesc.h"
14 #include "X86AsmParserCommon.h"
15 #include "llvm/ADT/STLExtras.h"
16 #include "llvm/ADT/StringRef.h"
17 #include "llvm/MC/MCExpr.h"
18 #include "llvm/MC/MCInst.h"
19 #include "llvm/MC/MCParser/MCParsedAsmOperand.h"
20 #include "llvm/MC/MCRegisterInfo.h"
21 #include "llvm/Support/Casting.h"
22 #include "llvm/Support/ErrorHandling.h"
23 #include "llvm/Support/SMLoc.h"
24 #include <cassert>
25 #include <memory>
26 
27 namespace llvm {
28 
29 /// X86Operand - Instances of this class represent a parsed X86 machine
30 /// instruction.
31 struct X86Operand final : public MCParsedAsmOperand {
32   enum KindTy { Token, Register, Immediate, Memory, Prefix, DXRegister } Kind;
33 
34   SMLoc StartLoc, EndLoc;
35   SMLoc OffsetOfLoc;
36   StringRef SymName;
37   void *OpDecl;
38   bool AddressOf;
39 
40   struct TokOp {
41     const char *Data;
42     unsigned Length;
43   };
44 
45   struct RegOp {
46     unsigned RegNo;
47   };
48 
49   struct PrefOp {
50     unsigned Prefixes;
51   };
52 
53   struct ImmOp {
54     const MCExpr *Val;
55   };
56 
57   struct MemOp {
58     unsigned SegReg;
59     const MCExpr *Disp;
60     unsigned BaseReg;
61     unsigned IndexReg;
62     unsigned Scale;
63     unsigned Size;
64     unsigned ModeSize;
65 
66     /// If the memory operand is unsized and there are multiple instruction
67     /// matches, prefer the one with this size.
68     unsigned FrontendSize;
69   };
70 
71   union {
72     struct TokOp Tok;
73     struct RegOp Reg;
74     struct ImmOp Imm;
75     struct MemOp Mem;
76     struct PrefOp Pref;
77   };
78 
79   X86Operand(KindTy K, SMLoc Start, SMLoc End)
80       : Kind(K), StartLoc(Start), EndLoc(End) {}
81 
82   StringRef getSymName() override { return SymName; }
83   void *getOpDecl() override { return OpDecl; }
84 
85   /// getStartLoc - Get the location of the first token of this operand.
86   SMLoc getStartLoc() const override { return StartLoc; }
87 
88   /// getEndLoc - Get the location of the last token of this operand.
89   SMLoc getEndLoc() const override { return EndLoc; }
90 
91   /// getLocRange - Get the range between the first and last token of this
92   /// operand.
93   SMRange getLocRange() const { return SMRange(StartLoc, EndLoc); }
94 
95   /// getOffsetOfLoc - Get the location of the offset operator.
96   SMLoc getOffsetOfLoc() const override { return OffsetOfLoc; }
97 
98   void print(raw_ostream &OS) const override {
99 
100     auto PrintImmValue = [&](const MCExpr *Val, const char *VName) {
101       if (Val->getKind() == MCExpr::Constant) {
102         if (auto Imm = cast<MCConstantExpr>(Val)->getValue())
103           OS << VName << Imm;
104       } else if (Val->getKind() == MCExpr::SymbolRef) {
105         if (auto *SRE = dyn_cast<MCSymbolRefExpr>(Val)) {
106           const MCSymbol &Sym = SRE->getSymbol();
107           if (auto SymName = Sym.getName().data())
108             OS << VName << SymName;
109         }
110       }
111     };
112 
113     switch (Kind) {
114     case Token:
115       OS << Tok.Data;
116       break;
117     case Register:
118       OS << "Reg:" << X86IntelInstPrinter::getRegisterName(Reg.RegNo);
119       break;
120     case DXRegister:
121       OS << "DXReg";
122       break;
123     case Immediate:
124       PrintImmValue(Imm.Val, "Imm:");
125       break;
126     case Prefix:
127       OS << "Prefix:" << Pref.Prefixes;
128       break;
129     case Memory:
130       OS << "Memory: ModeSize=" << Mem.ModeSize;
131       if (Mem.Size)
132         OS << ",Size=" << Mem.Size;
133       if (Mem.BaseReg)
134         OS << ",BaseReg=" << X86IntelInstPrinter::getRegisterName(Mem.BaseReg);
135       if (Mem.IndexReg)
136         OS << ",IndexReg="
137            << X86IntelInstPrinter::getRegisterName(Mem.IndexReg);
138       if (Mem.Scale)
139         OS << ",Scale=" << Mem.Scale;
140       if (Mem.Disp)
141         PrintImmValue(Mem.Disp, ",Disp=");
142       if (Mem.SegReg)
143         OS << ",SegReg=" << X86IntelInstPrinter::getRegisterName(Mem.SegReg);
144       break;
145     }
146   }
147 
148   StringRef getToken() const {
149     assert(Kind == Token && "Invalid access!");
150     return StringRef(Tok.Data, Tok.Length);
151   }
152   void setTokenValue(StringRef Value) {
153     assert(Kind == Token && "Invalid access!");
154     Tok.Data = Value.data();
155     Tok.Length = Value.size();
156   }
157 
158   unsigned getReg() const override {
159     assert(Kind == Register && "Invalid access!");
160     return Reg.RegNo;
161   }
162 
163   unsigned getPrefix() const {
164     assert(Kind == Prefix && "Invalid access!");
165     return Pref.Prefixes;
166   }
167 
168   const MCExpr *getImm() const {
169     assert(Kind == Immediate && "Invalid access!");
170     return Imm.Val;
171   }
172 
173   const MCExpr *getMemDisp() const {
174     assert(Kind == Memory && "Invalid access!");
175     return Mem.Disp;
176   }
177   unsigned getMemSegReg() const {
178     assert(Kind == Memory && "Invalid access!");
179     return Mem.SegReg;
180   }
181   unsigned getMemBaseReg() const {
182     assert(Kind == Memory && "Invalid access!");
183     return Mem.BaseReg;
184   }
185   unsigned getMemIndexReg() const {
186     assert(Kind == Memory && "Invalid access!");
187     return Mem.IndexReg;
188   }
189   unsigned getMemScale() const {
190     assert(Kind == Memory && "Invalid access!");
191     return Mem.Scale;
192   }
193   unsigned getMemModeSize() const {
194     assert(Kind == Memory && "Invalid access!");
195     return Mem.ModeSize;
196   }
197   unsigned getMemFrontendSize() const {
198     assert(Kind == Memory && "Invalid access!");
199     return Mem.FrontendSize;
200   }
201 
202   bool isToken() const override {return Kind == Token; }
203 
204   bool isImm() const override { return Kind == Immediate; }
205 
206   bool isImmSExti16i8() const {
207     if (!isImm())
208       return false;
209 
210     // If this isn't a constant expr, just assume it fits and let relaxation
211     // handle it.
212     const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
213     if (!CE)
214       return true;
215 
216     // Otherwise, check the value is in a range that makes sense for this
217     // extension.
218     return isImmSExti16i8Value(CE->getValue());
219   }
220   bool isImmSExti32i8() const {
221     if (!isImm())
222       return false;
223 
224     // If this isn't a constant expr, just assume it fits and let relaxation
225     // handle it.
226     const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
227     if (!CE)
228       return true;
229 
230     // Otherwise, check the value is in a range that makes sense for this
231     // extension.
232     return isImmSExti32i8Value(CE->getValue());
233   }
234   bool isImmSExti64i8() const {
235     if (!isImm())
236       return false;
237 
238     // If this isn't a constant expr, just assume it fits and let relaxation
239     // handle it.
240     const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
241     if (!CE)
242       return true;
243 
244     // Otherwise, check the value is in a range that makes sense for this
245     // extension.
246     return isImmSExti64i8Value(CE->getValue());
247   }
248   bool isImmSExti64i32() const {
249     if (!isImm())
250       return false;
251 
252     // If this isn't a constant expr, just assume it fits and let relaxation
253     // handle it.
254     const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
255     if (!CE)
256       return true;
257 
258     // Otherwise, check the value is in a range that makes sense for this
259     // extension.
260     return isImmSExti64i32Value(CE->getValue());
261   }
262 
263   bool isImmUnsignedi8() const {
264     if (!isImm()) return false;
265     // If this isn't a constant expr, just assume it fits and let relaxation
266     // handle it.
267     const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
268     if (!CE) return true;
269     return isImmUnsignedi8Value(CE->getValue());
270   }
271 
272   bool isOffsetOf() const override {
273     return OffsetOfLoc.getPointer();
274   }
275 
276   bool needAddressOf() const override {
277     return AddressOf;
278   }
279 
280   bool isMem() const override { return Kind == Memory; }
281   bool isMemUnsized() const {
282     return Kind == Memory && Mem.Size == 0;
283   }
284   bool isMem8() const {
285     return Kind == Memory && (!Mem.Size || Mem.Size == 8);
286   }
287   bool isMem16() const {
288     return Kind == Memory && (!Mem.Size || Mem.Size == 16);
289   }
290   bool isMem32() const {
291     return Kind == Memory && (!Mem.Size || Mem.Size == 32);
292   }
293   bool isMem64() const {
294     return Kind == Memory && (!Mem.Size || Mem.Size == 64);
295   }
296   bool isMem80() const {
297     return Kind == Memory && (!Mem.Size || Mem.Size == 80);
298   }
299   bool isMem128() const {
300     return Kind == Memory && (!Mem.Size || Mem.Size == 128);
301   }
302   bool isMem256() const {
303     return Kind == Memory && (!Mem.Size || Mem.Size == 256);
304   }
305   bool isMem512() const {
306     return Kind == Memory && (!Mem.Size || Mem.Size == 512);
307   }
308   bool isMemIndexReg(unsigned LowR, unsigned HighR) const {
309     assert(Kind == Memory && "Invalid access!");
310     return Mem.IndexReg >= LowR && Mem.IndexReg <= HighR;
311   }
312 
313   bool isMem64_RC128() const {
314     return isMem64() && isMemIndexReg(X86::XMM0, X86::XMM15);
315   }
316   bool isMem128_RC128() const {
317     return isMem128() && isMemIndexReg(X86::XMM0, X86::XMM15);
318   }
319   bool isMem128_RC256() const {
320     return isMem128() && isMemIndexReg(X86::YMM0, X86::YMM15);
321   }
322   bool isMem256_RC128() const {
323     return isMem256() && isMemIndexReg(X86::XMM0, X86::XMM15);
324   }
325   bool isMem256_RC256() const {
326     return isMem256() && isMemIndexReg(X86::YMM0, X86::YMM15);
327   }
328 
329   bool isMem64_RC128X() const {
330     return isMem64() && isMemIndexReg(X86::XMM0, X86::XMM31);
331   }
332   bool isMem128_RC128X() const {
333     return isMem128() && isMemIndexReg(X86::XMM0, X86::XMM31);
334   }
335   bool isMem128_RC256X() const {
336     return isMem128() && isMemIndexReg(X86::YMM0, X86::YMM31);
337   }
338   bool isMem256_RC128X() const {
339     return isMem256() && isMemIndexReg(X86::XMM0, X86::XMM31);
340   }
341   bool isMem256_RC256X() const {
342     return isMem256() && isMemIndexReg(X86::YMM0, X86::YMM31);
343   }
344   bool isMem256_RC512() const {
345     return isMem256() && isMemIndexReg(X86::ZMM0, X86::ZMM31);
346   }
347   bool isMem512_RC256X() const {
348     return isMem512() && isMemIndexReg(X86::YMM0, X86::YMM31);
349   }
350   bool isMem512_RC512() const {
351     return isMem512() && isMemIndexReg(X86::ZMM0, X86::ZMM31);
352   }
353 
354   bool isAbsMem() const {
355     return Kind == Memory && !getMemSegReg() && !getMemBaseReg() &&
356       !getMemIndexReg() && getMemScale() == 1;
357   }
358   bool isAVX512RC() const{
359       return isImm();
360   }
361 
362   bool isAbsMem16() const {
363     return isAbsMem() && Mem.ModeSize == 16;
364   }
365 
366   bool isSrcIdx() const {
367     return !getMemIndexReg() && getMemScale() == 1 &&
368       (getMemBaseReg() == X86::RSI || getMemBaseReg() == X86::ESI ||
369        getMemBaseReg() == X86::SI) && isa<MCConstantExpr>(getMemDisp()) &&
370       cast<MCConstantExpr>(getMemDisp())->getValue() == 0;
371   }
372   bool isSrcIdx8() const {
373     return isMem8() && isSrcIdx();
374   }
375   bool isSrcIdx16() const {
376     return isMem16() && isSrcIdx();
377   }
378   bool isSrcIdx32() const {
379     return isMem32() && isSrcIdx();
380   }
381   bool isSrcIdx64() const {
382     return isMem64() && isSrcIdx();
383   }
384 
385   bool isDstIdx() const {
386     return !getMemIndexReg() && getMemScale() == 1 &&
387       (getMemSegReg() == 0 || getMemSegReg() == X86::ES) &&
388       (getMemBaseReg() == X86::RDI || getMemBaseReg() == X86::EDI ||
389        getMemBaseReg() == X86::DI) && isa<MCConstantExpr>(getMemDisp()) &&
390       cast<MCConstantExpr>(getMemDisp())->getValue() == 0;
391   }
392   bool isDstIdx8() const {
393     return isMem8() && isDstIdx();
394   }
395   bool isDstIdx16() const {
396     return isMem16() && isDstIdx();
397   }
398   bool isDstIdx32() const {
399     return isMem32() && isDstIdx();
400   }
401   bool isDstIdx64() const {
402     return isMem64() && isDstIdx();
403   }
404 
405   bool isMemOffs() const {
406     return Kind == Memory && !getMemBaseReg() && !getMemIndexReg() &&
407       getMemScale() == 1;
408   }
409 
410   bool isMemOffs16_8() const {
411     return isMemOffs() && Mem.ModeSize == 16 && (!Mem.Size || Mem.Size == 8);
412   }
413   bool isMemOffs16_16() const {
414     return isMemOffs() && Mem.ModeSize == 16 && (!Mem.Size || Mem.Size == 16);
415   }
416   bool isMemOffs16_32() const {
417     return isMemOffs() && Mem.ModeSize == 16 && (!Mem.Size || Mem.Size == 32);
418   }
419   bool isMemOffs32_8() const {
420     return isMemOffs() && Mem.ModeSize == 32 && (!Mem.Size || Mem.Size == 8);
421   }
422   bool isMemOffs32_16() const {
423     return isMemOffs() && Mem.ModeSize == 32 && (!Mem.Size || Mem.Size == 16);
424   }
425   bool isMemOffs32_32() const {
426     return isMemOffs() && Mem.ModeSize == 32 && (!Mem.Size || Mem.Size == 32);
427   }
428   bool isMemOffs32_64() const {
429     return isMemOffs() && Mem.ModeSize == 32 && (!Mem.Size || Mem.Size == 64);
430   }
431   bool isMemOffs64_8() const {
432     return isMemOffs() && Mem.ModeSize == 64 && (!Mem.Size || Mem.Size == 8);
433   }
434   bool isMemOffs64_16() const {
435     return isMemOffs() && Mem.ModeSize == 64 && (!Mem.Size || Mem.Size == 16);
436   }
437   bool isMemOffs64_32() const {
438     return isMemOffs() && Mem.ModeSize == 64 && (!Mem.Size || Mem.Size == 32);
439   }
440   bool isMemOffs64_64() const {
441     return isMemOffs() && Mem.ModeSize == 64 && (!Mem.Size || Mem.Size == 64);
442   }
443 
444   bool isPrefix() const { return Kind == Prefix; }
445   bool isReg() const override { return Kind == Register; }
446   bool isDXReg() const { return Kind == DXRegister; }
447 
448   bool isGR32orGR64() const {
449     return Kind == Register &&
450       (X86MCRegisterClasses[X86::GR32RegClassID].contains(getReg()) ||
451       X86MCRegisterClasses[X86::GR64RegClassID].contains(getReg()));
452   }
453 
454   bool isVK1Pair() const {
455     return Kind == Register &&
456       X86MCRegisterClasses[X86::VK1RegClassID].contains(getReg());
457   }
458 
459   bool isVK2Pair() const {
460     return Kind == Register &&
461       X86MCRegisterClasses[X86::VK2RegClassID].contains(getReg());
462   }
463 
464   bool isVK4Pair() const {
465     return Kind == Register &&
466       X86MCRegisterClasses[X86::VK4RegClassID].contains(getReg());
467   }
468 
469   bool isVK8Pair() const {
470     return Kind == Register &&
471       X86MCRegisterClasses[X86::VK8RegClassID].contains(getReg());
472   }
473 
474   bool isVK16Pair() const {
475     return Kind == Register &&
476       X86MCRegisterClasses[X86::VK16RegClassID].contains(getReg());
477   }
478 
479   void addExpr(MCInst &Inst, const MCExpr *Expr) const {
480     // Add as immediates when possible.
481     if (const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(Expr))
482       Inst.addOperand(MCOperand::createImm(CE->getValue()));
483     else
484       Inst.addOperand(MCOperand::createExpr(Expr));
485   }
486 
487   void addRegOperands(MCInst &Inst, unsigned N) const {
488     assert(N == 1 && "Invalid number of operands!");
489     Inst.addOperand(MCOperand::createReg(getReg()));
490   }
491 
492   void addGR32orGR64Operands(MCInst &Inst, unsigned N) const {
493     assert(N == 1 && "Invalid number of operands!");
494     unsigned RegNo = getReg();
495     if (X86MCRegisterClasses[X86::GR64RegClassID].contains(RegNo))
496       RegNo = getX86SubSuperRegister(RegNo, 32);
497     Inst.addOperand(MCOperand::createReg(RegNo));
498   }
499 
500   void addAVX512RCOperands(MCInst &Inst, unsigned N) const {
501     assert(N == 1 && "Invalid number of operands!");
502     addExpr(Inst, getImm());
503   }
504 
505   void addImmOperands(MCInst &Inst, unsigned N) const {
506     assert(N == 1 && "Invalid number of operands!");
507     addExpr(Inst, getImm());
508   }
509 
510   void addMaskPairOperands(MCInst &Inst, unsigned N) const {
511     assert(N == 1 && "Invalid number of operands!");
512     unsigned Reg = getReg();
513     switch (Reg) {
514     case X86::K0:
515     case X86::K1:
516       Reg = X86::K0_K1;
517       break;
518     case X86::K2:
519     case X86::K3:
520       Reg = X86::K2_K3;
521       break;
522     case X86::K4:
523     case X86::K5:
524       Reg = X86::K4_K5;
525       break;
526     case X86::K6:
527     case X86::K7:
528       Reg = X86::K6_K7;
529       break;
530     }
531     Inst.addOperand(MCOperand::createReg(Reg));
532   }
533 
534   void addMemOperands(MCInst &Inst, unsigned N) const {
535     assert((N == 5) && "Invalid number of operands!");
536     Inst.addOperand(MCOperand::createReg(getMemBaseReg()));
537     Inst.addOperand(MCOperand::createImm(getMemScale()));
538     Inst.addOperand(MCOperand::createReg(getMemIndexReg()));
539     addExpr(Inst, getMemDisp());
540     Inst.addOperand(MCOperand::createReg(getMemSegReg()));
541   }
542 
543   void addAbsMemOperands(MCInst &Inst, unsigned N) const {
544     assert((N == 1) && "Invalid number of operands!");
545     // Add as immediates when possible.
546     if (const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getMemDisp()))
547       Inst.addOperand(MCOperand::createImm(CE->getValue()));
548     else
549       Inst.addOperand(MCOperand::createExpr(getMemDisp()));
550   }
551 
552   void addSrcIdxOperands(MCInst &Inst, unsigned N) const {
553     assert((N == 2) && "Invalid number of operands!");
554     Inst.addOperand(MCOperand::createReg(getMemBaseReg()));
555     Inst.addOperand(MCOperand::createReg(getMemSegReg()));
556   }
557 
558   void addDstIdxOperands(MCInst &Inst, unsigned N) const {
559     assert((N == 1) && "Invalid number of operands!");
560     Inst.addOperand(MCOperand::createReg(getMemBaseReg()));
561   }
562 
563   void addMemOffsOperands(MCInst &Inst, unsigned N) const {
564     assert((N == 2) && "Invalid number of operands!");
565     // Add as immediates when possible.
566     if (const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getMemDisp()))
567       Inst.addOperand(MCOperand::createImm(CE->getValue()));
568     else
569       Inst.addOperand(MCOperand::createExpr(getMemDisp()));
570     Inst.addOperand(MCOperand::createReg(getMemSegReg()));
571   }
572 
573   static std::unique_ptr<X86Operand> CreateToken(StringRef Str, SMLoc Loc) {
574     SMLoc EndLoc = SMLoc::getFromPointer(Loc.getPointer() + Str.size());
575     auto Res = llvm::make_unique<X86Operand>(Token, Loc, EndLoc);
576     Res->Tok.Data = Str.data();
577     Res->Tok.Length = Str.size();
578     return Res;
579   }
580 
581   static std::unique_ptr<X86Operand>
582   CreateReg(unsigned RegNo, SMLoc StartLoc, SMLoc EndLoc,
583             bool AddressOf = false, SMLoc OffsetOfLoc = SMLoc(),
584             StringRef SymName = StringRef(), void *OpDecl = nullptr) {
585     auto Res = llvm::make_unique<X86Operand>(Register, StartLoc, EndLoc);
586     Res->Reg.RegNo = RegNo;
587     Res->AddressOf = AddressOf;
588     Res->OffsetOfLoc = OffsetOfLoc;
589     Res->SymName = SymName;
590     Res->OpDecl = OpDecl;
591     return Res;
592   }
593 
594   static std::unique_ptr<X86Operand>
595   CreateDXReg(SMLoc StartLoc, SMLoc EndLoc) {
596     return llvm::make_unique<X86Operand>(DXRegister, StartLoc, EndLoc);
597   }
598 
599   static std::unique_ptr<X86Operand>
600   CreatePrefix(unsigned Prefixes, SMLoc StartLoc, SMLoc EndLoc) {
601     auto Res = llvm::make_unique<X86Operand>(Prefix, StartLoc, EndLoc);
602     Res->Pref.Prefixes = Prefixes;
603     return Res;
604   }
605 
606   static std::unique_ptr<X86Operand> CreateImm(const MCExpr *Val,
607                                                SMLoc StartLoc, SMLoc EndLoc) {
608     auto Res = llvm::make_unique<X86Operand>(Immediate, StartLoc, EndLoc);
609     Res->Imm.Val = Val;
610     return Res;
611   }
612 
613   /// Create an absolute memory operand.
614   static std::unique_ptr<X86Operand>
615   CreateMem(unsigned ModeSize, const MCExpr *Disp, SMLoc StartLoc, SMLoc EndLoc,
616             unsigned Size = 0, StringRef SymName = StringRef(),
617             void *OpDecl = nullptr, unsigned FrontendSize = 0) {
618     auto Res = llvm::make_unique<X86Operand>(Memory, StartLoc, EndLoc);
619     Res->Mem.SegReg   = 0;
620     Res->Mem.Disp     = Disp;
621     Res->Mem.BaseReg  = 0;
622     Res->Mem.IndexReg = 0;
623     Res->Mem.Scale    = 1;
624     Res->Mem.Size     = Size;
625     Res->Mem.ModeSize = ModeSize;
626     Res->Mem.FrontendSize = FrontendSize;
627     Res->SymName      = SymName;
628     Res->OpDecl       = OpDecl;
629     Res->AddressOf    = false;
630     return Res;
631   }
632 
633   /// Create a generalized memory operand.
634   static std::unique_ptr<X86Operand>
635   CreateMem(unsigned ModeSize, unsigned SegReg, const MCExpr *Disp,
636             unsigned BaseReg, unsigned IndexReg, unsigned Scale, SMLoc StartLoc,
637             SMLoc EndLoc, unsigned Size = 0, StringRef SymName = StringRef(),
638             void *OpDecl = nullptr, unsigned FrontendSize = 0) {
639     // We should never just have a displacement, that should be parsed as an
640     // absolute memory operand.
641     assert((SegReg || BaseReg || IndexReg) && "Invalid memory operand!");
642 
643     // The scale should always be one of {1,2,4,8}.
644     assert(((Scale == 1 || Scale == 2 || Scale == 4 || Scale == 8)) &&
645            "Invalid scale!");
646     auto Res = llvm::make_unique<X86Operand>(Memory, StartLoc, EndLoc);
647     Res->Mem.SegReg   = SegReg;
648     Res->Mem.Disp     = Disp;
649     Res->Mem.BaseReg  = BaseReg;
650     Res->Mem.IndexReg = IndexReg;
651     Res->Mem.Scale    = Scale;
652     Res->Mem.Size     = Size;
653     Res->Mem.ModeSize = ModeSize;
654     Res->Mem.FrontendSize = FrontendSize;
655     Res->SymName      = SymName;
656     Res->OpDecl       = OpDecl;
657     Res->AddressOf    = false;
658     return Res;
659   }
660 };
661 
662 } // end namespace llvm
663 
664 #endif // LLVM_LIB_TARGET_X86_ASMPARSER_X86OPERAND_H
665