Coverage Report

Created: 2026-02-14 07:25

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/keystone/llvm/lib/Target/X86/AsmParser/X86Operand.h
Line
Count
Source
1
//===-- X86Operand.h - Parsed X86 machine instruction --------------------===//
2
//
3
//                     The LLVM Compiler Infrastructure
4
//
5
// This file is distributed under the University of Illinois Open Source
6
// License. See LICENSE.TXT for details.
7
//
8
//===----------------------------------------------------------------------===//
9
10
#ifndef LLVM_LIB_TARGET_X86_ASMPARSER_X86OPERAND_H
11
#define LLVM_LIB_TARGET_X86_ASMPARSER_X86OPERAND_H
12
13
#include "X86AsmParserCommon.h"
14
#include "llvm/MC/MCExpr.h"
15
#include "llvm/MC/MCInst.h"
16
#include "llvm/MC/MCRegisterInfo.h"
17
#include "llvm/MC/MCParser/MCParsedAsmOperand.h"
18
#include "llvm/ADT/STLExtras.h"
19
#include "MCTargetDesc/X86MCTargetDesc.h"
20
21
namespace llvm_ks {
22
23
/// X86Operand - Instances of this class represent a parsed X86 machine
24
/// instruction.
25
struct X86Operand : public MCParsedAsmOperand {
26
  enum KindTy {
27
    Token,
28
    Register,
29
    Immediate,
30
    Memory
31
  } Kind;
32
33
  SMLoc StartLoc, EndLoc;
34
  SMLoc OffsetOfLoc;
35
  StringRef SymName;
36
  void *OpDecl;
37
  bool AddressOf;
38
39
  struct TokOp {
40
    const char *Data;
41
    unsigned Length;
42
  };
43
44
  struct RegOp {
45
    unsigned RegNo;
46
  };
47
48
  struct ImmOp {
49
    const MCExpr *Val;
50
  };
51
52
  struct MemOp {
53
    unsigned SegReg;
54
    const MCExpr *Disp;
55
    unsigned BaseReg;
56
    unsigned IndexReg;
57
    unsigned Scale;
58
    unsigned Size;
59
    unsigned ModeSize;
60
  };
61
62
  union {
63
    struct TokOp Tok;
64
    struct RegOp Reg;
65
    struct ImmOp Imm;
66
    struct MemOp Mem;
67
  };
68
69
  X86Operand(KindTy K, SMLoc Start, SMLoc End)
70
240k
    : Kind(K), StartLoc(Start), EndLoc(End) {}
71
72
0
  StringRef getSymName() override { return SymName; }
73
0
  void *getOpDecl() override { return OpDecl; }
74
75
  /// getStartLoc - Get the location of the first token of this operand.
76
136
  SMLoc getStartLoc() const override { return StartLoc; }
77
  /// getEndLoc - Get the location of the last token of this operand.
78
0
  SMLoc getEndLoc() const override { return EndLoc; }
79
  /// getLocRange - Get the range between the first and last token of this
80
  /// operand.
81
0
  SMRange getLocRange() const { return SMRange(StartLoc, EndLoc); }
82
  /// getOffsetOfLoc - Get the location of the offset operator.
83
0
  SMLoc getOffsetOfLoc() const override { return OffsetOfLoc; }
84
85
0
  void print(raw_ostream &OS) const override {}
86
87
414k
  StringRef getToken() const {
88
414k
    assert(Kind == Token && "Invalid access!");
89
414k
    return StringRef(Tok.Data, Tok.Length);
90
414k
  }
91
6.63k
  void setTokenValue(StringRef Value) {
92
6.63k
    assert(Kind == Token && "Invalid access!");
93
6.63k
    Tok.Data = Value.data();
94
6.63k
    Tok.Length = Value.size();
95
6.63k
  }
96
97
371k
  unsigned getReg() const override {
98
371k
    assert(Kind == Register && "Invalid access!");
99
371k
    return Reg.RegNo;
100
371k
  }
101
102
2.19k
  const MCExpr *getImm() const {
103
2.19k
    assert(Kind == Immediate && "Invalid access!");
104
2.19k
    return Imm.Val;
105
2.19k
  }
106
107
226k
  const MCExpr *getMemDisp() const {
108
226k
    assert(Kind == Memory && "Invalid access!");
109
226k
    return Mem.Disp;
110
226k
  }
111
182k
  unsigned getMemSegReg() const {
112
182k
    assert(Kind == Memory && "Invalid access!");
113
182k
    return Mem.SegReg;
114
182k
  }
115
266k
  unsigned getMemBaseReg() const {
116
266k
    assert(Kind == Memory && "Invalid access!");
117
266k
    return Mem.BaseReg;
118
266k
  }
119
199k
  unsigned getMemIndexReg() const {
120
199k
    assert(Kind == Memory && "Invalid access!");
121
199k
    return Mem.IndexReg;
122
199k
  }
123
198k
  unsigned getMemScale() const {
124
198k
    assert(Kind == Memory && "Invalid access!");
125
198k
    return Mem.Scale;
126
198k
  }
127
0
  unsigned getMemModeSize() const {
128
0
    assert(Kind == Memory && "Invalid access!");
129
0
    return Mem.ModeSize;
130
0
  }
131
132
913k
  bool isToken() const override {return Kind == Token; }
133
134
17.5k
  bool isImm() const override { return Kind == Immediate; }
135
136
965
  bool isImmSExti16i8() const {
137
965
    if (!isImm())
138
520
      return false;
139
140
    // If this isn't a constant expr, just assume it fits and let relaxation
141
    // handle it.
142
445
    const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
143
445
    if (!CE)
144
248
      return true;
145
146
    // Otherwise, check the value is in a range that makes sense for this
147
    // extension.
148
197
    return isImmSExti16i8Value(CE->getValue());
149
445
  }
150
722
  bool isImmSExti32i8() const {
151
722
    if (!isImm())
152
494
      return false;
153
154
    // If this isn't a constant expr, just assume it fits and let relaxation
155
    // handle it.
156
228
    const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
157
228
    if (!CE)
158
72
      return true;
159
160
    // Otherwise, check the value is in a range that makes sense for this
161
    // extension.
162
156
    return isImmSExti32i8Value(CE->getValue());
163
228
  }
164
654
  bool isImmSExti64i8() const {
165
654
    if (!isImm())
166
304
      return false;
167
168
    // If this isn't a constant expr, just assume it fits and let relaxation
169
    // handle it.
170
350
    const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
171
350
    if (!CE)
172
168
      return true;
173
174
    // Otherwise, check the value is in a range that makes sense for this
175
    // extension.
176
182
    return isImmSExti64i8Value(CE->getValue());
177
350
  }
178
563
  bool isImmSExti64i32() const {
179
563
    if (!isImm())
180
397
      return false;
181
182
    // If this isn't a constant expr, just assume it fits and let relaxation
183
    // handle it.
184
166
    const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
185
166
    if (!CE)
186
30
      return true;
187
188
    // Otherwise, check the value is in a range that makes sense for this
189
    // extension.
190
136
    return isImmSExti64i32Value(CE->getValue());
191
166
  }
192
193
723
  bool isImmUnsignedi8() const {
194
723
    if (!isImm()) return false;
195
305
    const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
196
305
    if (!CE) return false;
197
220
    return isImmUnsignedi8Value(CE->getValue());
198
305
  }
199
200
0
  bool isOffsetOf() const override {
201
0
    return OffsetOfLoc.getPointer();
202
0
  }
203
204
0
  bool needAddressOf() const override {
205
0
    return AddressOf;
206
0
  }
207
208
3.03k
  bool isMem() const override { return Kind == Memory; }
209
162k
  bool isMemUnsized() const {
210
162k
    return Kind == Memory && Mem.Size == 0;
211
162k
  }
212
67.5k
  bool isMem8() const {
213
67.5k
    return Kind == Memory && (!Mem.Size || Mem.Size == 8);
214
67.5k
  }
215
58.3k
  bool isMem16() const {
216
58.3k
    return Kind == Memory && (!Mem.Size || Mem.Size == 16);
217
58.3k
  }
218
75.5k
  bool isMem32() const {
219
75.5k
    return Kind == Memory && (!Mem.Size || Mem.Size == 32);
220
75.5k
  }
221
61.5k
  bool isMem64() const {
222
61.5k
    return Kind == Memory && (!Mem.Size || Mem.Size == 64);
223
61.5k
  }
224
16
  bool isMem80() const {
225
16
    return Kind == Memory && (!Mem.Size || Mem.Size == 80);
226
16
  }
227
42
  bool isMem128() const {
228
42
    return Kind == Memory && (!Mem.Size || Mem.Size == 128);
229
42
  }
230
37
  bool isMem256() const {
231
37
    return Kind == Memory && (!Mem.Size || Mem.Size == 256);
232
37
  }
233
16
  bool isMem512() const {
234
16
    return Kind == Memory && (!Mem.Size || Mem.Size == 512);
235
16
  }
236
237
0
  bool isMemVX32() const {
238
0
    return Kind == Memory && (!Mem.Size || Mem.Size == 32) &&
239
0
      getMemIndexReg() >= X86::XMM0 && getMemIndexReg() <= X86::XMM15;
240
0
  }
241
0
  bool isMemVX32X() const {
242
0
    return Kind == Memory && (!Mem.Size || Mem.Size == 32) &&
243
0
      getMemIndexReg() >= X86::XMM0 && getMemIndexReg() <= X86::XMM31;
244
0
  }
245
0
  bool isMemVY32() const {
246
0
    return Kind == Memory && (!Mem.Size || Mem.Size == 32) &&
247
0
      getMemIndexReg() >= X86::YMM0 && getMemIndexReg() <= X86::YMM15;
248
0
  }
249
0
  bool isMemVY32X() const {
250
0
    return Kind == Memory && (!Mem.Size || Mem.Size == 32) &&
251
0
      getMemIndexReg() >= X86::YMM0 && getMemIndexReg() <= X86::YMM31;
252
0
  }
253
0
  bool isMemVX64() const {
254
0
    return Kind == Memory && (!Mem.Size || Mem.Size == 64) &&
255
0
      getMemIndexReg() >= X86::XMM0 && getMemIndexReg() <= X86::XMM15;
256
0
  }
257
0
  bool isMemVX64X() const {
258
0
    return Kind == Memory && (!Mem.Size || Mem.Size == 64) &&
259
0
      getMemIndexReg() >= X86::XMM0 && getMemIndexReg() <= X86::XMM31;
260
0
  }
261
0
  bool isMemVY64() const {
262
0
    return Kind == Memory && (!Mem.Size || Mem.Size == 64) &&
263
0
      getMemIndexReg() >= X86::YMM0 && getMemIndexReg() <= X86::YMM15;
264
0
  }
265
0
  bool isMemVY64X() const {
266
0
    return Kind == Memory && (!Mem.Size || Mem.Size == 64) &&
267
0
      getMemIndexReg() >= X86::YMM0 && getMemIndexReg() <= X86::YMM31;
268
0
  }
269
0
  bool isMemVZ32() const {
270
0
    return Kind == Memory && (!Mem.Size || Mem.Size == 32) &&
271
0
      getMemIndexReg() >= X86::ZMM0 && getMemIndexReg() <= X86::ZMM31;
272
0
  }
273
0
  bool isMemVZ64() const {
274
0
    return Kind == Memory && (!Mem.Size || Mem.Size == 64) &&
275
0
      getMemIndexReg() >= X86::ZMM0 && getMemIndexReg() <= X86::ZMM31;
276
0
  }
277
278
129k
  bool isAbsMem() const {
279
129k
    return (Kind == Memory) && !getMemSegReg() && !getMemBaseReg() &&
280
127k
      !getMemIndexReg() && (getMemScale() == 1) && (Mem.ModeSize == 0 || Mem.Size == 0);
281
129k
  }
282
3
  bool isAVX512RC() const{
283
3
      return isImm();
284
3
  }
285
286
0
  bool isAbsMem16() const {
287
0
    return isAbsMem() && Mem.ModeSize == 16;
288
0
  }
289
290
19.6k
  bool isSrcIdx() const {
291
19.6k
    return !getMemIndexReg() && getMemScale() == 1 &&
292
19.6k
      (getMemBaseReg() == X86::RSI || getMemBaseReg() == X86::ESI ||
293
19.5k
       getMemBaseReg() == X86::SI) && isa<MCConstantExpr>(getMemDisp()) &&
294
19.5k
      cast<MCConstantExpr>(getMemDisp())->getValue() == 0;
295
19.6k
  }
296
54.2k
  bool isSrcIdx8() const {
297
54.2k
    return isMem8() && isSrcIdx();
298
54.2k
  }
299
1.46k
  bool isSrcIdx16() const {
300
1.46k
    return isMem16() && isSrcIdx();
301
1.46k
  }
302
53.0k
  bool isSrcIdx32() const {
303
53.0k
    return isMem32() && isSrcIdx();
304
53.0k
  }
305
24.4k
  bool isSrcIdx64() const {
306
24.4k
    return isMem64() && isSrcIdx();
307
24.4k
  }
308
309
25.3k
  bool isDstIdx() const {
310
25.3k
    return !getMemIndexReg() && getMemScale() == 1 &&
311
25.3k
      (getMemSegReg() == 0 || getMemSegReg() == X86::ES) &&
312
25.3k
      (getMemBaseReg() == X86::RDI || getMemBaseReg() == X86::EDI ||
313
25.0k
       getMemBaseReg() == X86::DI) && isa<MCConstantExpr>(getMemDisp()) &&
314
25.0k
      cast<MCConstantExpr>(getMemDisp())->getValue() == 0;
315
25.3k
  }
316
1.23k
  bool isDstIdx8() const {
317
1.23k
    return isMem8() && isDstIdx();
318
1.23k
  }
319
5.41k
  bool isDstIdx16() const {
320
5.41k
    return isMem16() && isDstIdx();
321
5.41k
  }
322
2.32k
  bool isDstIdx32() const {
323
2.32k
    return isMem32() && isDstIdx();
324
2.32k
  }
325
24.8k
  bool isDstIdx64() const {
326
24.8k
    return isMem64() && isDstIdx();
327
24.8k
  }
328
329
57.5k
  bool isMemOffs() const {
330
57.5k
    return Kind == Memory && !getMemBaseReg() && !getMemIndexReg() &&
331
15.7k
      getMemScale() == 1;
332
57.5k
  }
333
334
4.73k
  bool isMemOffs16_8() const {
335
4.73k
    return isMemOffs() && Mem.ModeSize == 16 && (!Mem.Size || Mem.Size == 8);
336
4.73k
  }
337
7.21k
  bool isMemOffs16_16() const {
338
7.21k
    return isMemOffs() && Mem.ModeSize == 16 && (!Mem.Size || Mem.Size == 16);
339
7.21k
  }
340
4.47k
  bool isMemOffs16_32() const {
341
4.47k
    return isMemOffs() && Mem.ModeSize == 16 && (!Mem.Size || Mem.Size == 32);
342
4.47k
  }
343
4.72k
  bool isMemOffs32_8() const {
344
4.72k
    return isMemOffs() && Mem.ModeSize == 32 && (!Mem.Size || Mem.Size == 8);
345
4.72k
  }
346
6.88k
  bool isMemOffs32_16() const {
347
6.88k
    return isMemOffs() && Mem.ModeSize == 32 && (!Mem.Size || Mem.Size == 16);
348
6.88k
  }
349
4.47k
  bool isMemOffs32_32() const {
350
4.47k
    return isMemOffs() && Mem.ModeSize == 32 && (!Mem.Size || Mem.Size == 32);
351
4.47k
  }
352
4.47k
  bool isMemOffs32_64() const {
353
4.47k
    return isMemOffs() && Mem.ModeSize == 32 && (!Mem.Size || Mem.Size == 64);
354
4.47k
  }
355
4.71k
  bool isMemOffs64_8() const {
356
4.71k
    return isMemOffs() && Mem.ModeSize == 64 && (!Mem.Size || Mem.Size == 8);
357
4.71k
  }
358
6.88k
  bool isMemOffs64_16() const {
359
6.88k
    return isMemOffs() && Mem.ModeSize == 64 && (!Mem.Size || Mem.Size == 16);
360
6.88k
  }
361
4.47k
  bool isMemOffs64_32() const {
362
4.47k
    return isMemOffs() && Mem.ModeSize == 64 && (!Mem.Size || Mem.Size == 32);
363
4.47k
  }
364
4.47k
  bool isMemOffs64_64() const {
365
4.47k
    return isMemOffs() && Mem.ModeSize == 64 && (!Mem.Size || Mem.Size == 64);
366
4.47k
  }
367
368
675k
  bool isReg() const override { return Kind == Register; }
369
370
0
  bool isGR32orGR64() const {
371
0
    return Kind == Register &&
372
0
      (X86MCRegisterClasses[X86::GR32RegClassID].contains(getReg()) ||
373
0
      X86MCRegisterClasses[X86::GR64RegClassID].contains(getReg()));
374
0
  }
375
376
11.6k
  void addExpr(MCInst &Inst, const MCExpr *Expr) const {
377
    // Add as immediates when possible.
378
11.6k
    if (const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(Expr))
379
1.94k
      Inst.addOperand(MCOperand::createImm(CE->getValue()));
380
9.74k
    else
381
9.74k
      Inst.addOperand(MCOperand::createExpr(Expr));
382
11.6k
  }
383
384
485
  void addRegOperands(MCInst &Inst, unsigned N) const {
385
485
    assert(N == 1 && "Invalid number of operands!");
386
485
    Inst.addOperand(MCOperand::createReg(getReg()));
387
485
  }
388
389
0
  static unsigned getGR32FromGR64(unsigned RegNo) {
390
0
    switch (RegNo) {
391
0
    default: llvm_unreachable("Unexpected register");
392
0
    case X86::RAX: return X86::EAX;
393
0
    case X86::RCX: return X86::ECX;
394
0
    case X86::RDX: return X86::EDX;
395
0
    case X86::RBX: return X86::EBX;
396
0
    case X86::RBP: return X86::EBP;
397
0
    case X86::RSP: return X86::ESP;
398
0
    case X86::RSI: return X86::ESI;
399
0
    case X86::RDI: return X86::EDI;
400
0
    case X86::R8: return X86::R8D;
401
0
    case X86::R9: return X86::R9D;
402
0
    case X86::R10: return X86::R10D;
403
0
    case X86::R11: return X86::R11D;
404
0
    case X86::R12: return X86::R12D;
405
0
    case X86::R13: return X86::R13D;
406
0
    case X86::R14: return X86::R14D;
407
0
    case X86::R15: return X86::R15D;
408
0
    case X86::RIP: return X86::EIP;
409
0
    }
410
0
  }
411
412
0
  void addGR32orGR64Operands(MCInst &Inst, unsigned N) const {
413
0
    assert(N == 1 && "Invalid number of operands!");
414
0
    unsigned RegNo = getReg();
415
0
    if (X86MCRegisterClasses[X86::GR64RegClassID].contains(RegNo))
416
0
      RegNo = getGR32FromGR64(RegNo);
417
0
    Inst.addOperand(MCOperand::createReg(RegNo));
418
0
  }
419
0
  void addAVX512RCOperands(MCInst &Inst, unsigned N) const {
420
0
    assert(N == 1 && "Invalid number of operands!");
421
0
    addExpr(Inst, getImm());
422
0
  }
423
587
  void addImmOperands(MCInst &Inst, unsigned N) const {
424
587
    assert(N == 1 && "Invalid number of operands!");
425
587
    addExpr(Inst, getImm());
426
587
  }
427
428
11.0k
  void addMemOperands(MCInst &Inst, unsigned N) const {
429
11.0k
    assert((N == 5) && "Invalid number of operands!");
430
11.0k
    Inst.addOperand(MCOperand::createReg(getMemBaseReg()));
431
11.0k
    Inst.addOperand(MCOperand::createImm(getMemScale()));
432
11.0k
    Inst.addOperand(MCOperand::createReg(getMemIndexReg()));
433
11.0k
    addExpr(Inst, getMemDisp());
434
11.0k
    Inst.addOperand(MCOperand::createReg(getMemSegReg()));
435
11.0k
  }
436
437
106k
  void addAbsMemOperands(MCInst &Inst, unsigned N) const {
438
106k
    assert((N == 1) && "Invalid number of operands!");
439
    // Add as immediates when possible.
440
106k
    if (const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getMemDisp()))
441
87.2k
      Inst.addOperand(MCOperand::createImm(CE->getValue()));
442
18.8k
    else
443
18.8k
      Inst.addOperand(MCOperand::createExpr(getMemDisp()));
444
106k
  }
445
446
17.1k
  void addSrcIdxOperands(MCInst &Inst, unsigned N) const {
447
17.1k
    assert((N == 2) && "Invalid number of operands!");
448
17.1k
    Inst.addOperand(MCOperand::createReg(getMemBaseReg()));
449
17.1k
    Inst.addOperand(MCOperand::createReg(getMemSegReg()));
450
17.1k
  }
451
4.33k
  void addDstIdxOperands(MCInst &Inst, unsigned N) const {
452
4.33k
    assert((N == 1) && "Invalid number of operands!");
453
4.33k
    Inst.addOperand(MCOperand::createReg(getMemBaseReg()));
454
4.33k
  }
455
456
368
  void addMemOffsOperands(MCInst &Inst, unsigned N) const {
457
368
    assert((N == 2) && "Invalid number of operands!");
458
    // Add as immediates when possible.
459
368
    if (const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getMemDisp()))
460
16
      Inst.addOperand(MCOperand::createImm(CE->getValue()));
461
352
    else
462
352
      Inst.addOperand(MCOperand::createExpr(getMemDisp()));
463
368
    Inst.addOperand(MCOperand::createReg(getMemSegReg()));
464
368
  }
465
466
150k
  static std::unique_ptr<X86Operand> CreateToken(StringRef Str, SMLoc Loc) {
467
150k
    SMLoc EndLoc = SMLoc::getFromPointer(Loc.getPointer() + Str.size());
468
150k
    auto Res = llvm_ks::make_unique<X86Operand>(Token, Loc, EndLoc);
469
150k
    Res->Tok.Data = Str.data();
470
150k
    Res->Tok.Length = Str.size();
471
150k
    return Res;
472
150k
  }
473
474
  static std::unique_ptr<X86Operand>
475
  CreateReg(unsigned RegNo, SMLoc StartLoc, SMLoc EndLoc,
476
            bool AddressOf = false, SMLoc OffsetOfLoc = SMLoc(),
477
15.9k
            StringRef SymName = StringRef(), void *OpDecl = nullptr) {
478
15.9k
    auto Res = llvm_ks::make_unique<X86Operand>(Register, StartLoc, EndLoc);
479
15.9k
    Res->Reg.RegNo = RegNo;
480
15.9k
    Res->AddressOf = AddressOf;
481
15.9k
    Res->OffsetOfLoc = OffsetOfLoc;
482
15.9k
    Res->SymName = SymName;
483
15.9k
    Res->OpDecl = OpDecl;
484
15.9k
    return Res;
485
15.9k
  }
486
487
  static std::unique_ptr<X86Operand> CreateImm(const MCExpr *Val,
488
19.2k
                                               SMLoc StartLoc, SMLoc EndLoc) {
489
19.2k
    auto Res = llvm_ks::make_unique<X86Operand>(Immediate, StartLoc, EndLoc);
490
19.2k
    Res->Imm.Val = Val;
491
19.2k
    return Res;
492
19.2k
  }
493
494
  /// Create an absolute memory operand.
495
  static std::unique_ptr<X86Operand>
496
  CreateMem(unsigned ModeSize, const MCExpr *Disp, SMLoc StartLoc, SMLoc EndLoc,
497
            unsigned Size = 0, StringRef SymName = StringRef(),
498
20.7k
            void *OpDecl = nullptr) {
499
20.7k
    auto Res = llvm_ks::make_unique<X86Operand>(Memory, StartLoc, EndLoc);
500
20.7k
    Res->Mem.SegReg   = 0;
501
20.7k
    Res->Mem.Disp     = Disp;
502
20.7k
    Res->Mem.BaseReg  = 0;
503
20.7k
    Res->Mem.IndexReg = 0;
504
20.7k
    Res->Mem.Scale    = 1;
505
20.7k
    Res->Mem.Size     = Size;
506
20.7k
    Res->Mem.ModeSize = ModeSize;
507
20.7k
    Res->SymName      = SymName;
508
20.7k
    Res->OpDecl       = OpDecl;
509
20.7k
    Res->AddressOf    = false;
510
20.7k
    return Res;
511
20.7k
  }
512
513
  /// Create a generalized memory operand.
514
  static std::unique_ptr<X86Operand>
515
  CreateMem(unsigned ModeSize, unsigned SegReg, const MCExpr *Disp,
516
            unsigned BaseReg, unsigned IndexReg, unsigned Scale, SMLoc StartLoc,
517
            SMLoc EndLoc, unsigned Size = 0, StringRef SymName = StringRef(),
518
34.2k
            void *OpDecl = nullptr) {
519
    // We should never just have a displacement, that should be parsed as an
520
    // absolute memory operand.
521
    // assert((SegReg || BaseReg || IndexReg) && "Invalid memory operand!");
522
523
    // The scale should always be one of {1,2,4,8}.
524
34.2k
    assert(((Scale == 1 || Scale == 2 || Scale == 4 || Scale == 8)) &&
525
34.2k
           "Invalid scale!");
526
34.2k
    auto Res = llvm_ks::make_unique<X86Operand>(Memory, StartLoc, EndLoc);
527
34.2k
    Res->Mem.SegReg   = SegReg;
528
34.2k
    Res->Mem.Disp     = Disp;
529
34.2k
    Res->Mem.BaseReg  = BaseReg;
530
34.2k
    Res->Mem.IndexReg = IndexReg;
531
34.2k
    Res->Mem.Scale    = Scale;
532
34.2k
    Res->Mem.Size     = Size;
533
34.2k
    Res->Mem.ModeSize = ModeSize;
534
34.2k
    Res->SymName      = SymName;
535
34.2k
    Res->OpDecl       = OpDecl;
536
34.2k
    Res->AddressOf    = false;
537
34.2k
    return Res;
538
34.2k
  }
539
};
540
541
} // End of namespace llvm_ks
542
543
#endif