1 //===- X86Operand.h - Parsed X86 machine instruction ------------*- C++ -*-===//
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
7 //===----------------------------------------------------------------------===//
9 #ifndef LLVM_LIB_TARGET_X86_ASMPARSER_X86OPERAND_H
10 #define LLVM_LIB_TARGET_X86_ASMPARSER_X86OPERAND_H
12 #include "InstPrinter/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"
29 /// X86Operand - Instances of this class represent a parsed X86 machine
31 struct X86Operand final
: public MCParsedAsmOperand
{
32 enum KindTy
{ Token
, Register
, Immediate
, Memory
, Prefix
, DXRegister
} Kind
;
34 SMLoc StartLoc
, EndLoc
;
66 /// If the memory operand is unsized and there are multiple instruction
67 /// matches, prefer the one with this size.
68 unsigned FrontendSize
;
79 X86Operand(KindTy K
, SMLoc Start
, SMLoc End
)
80 : Kind(K
), StartLoc(Start
), EndLoc(End
) {}
82 StringRef
getSymName() override
{ return SymName
; }
83 void *getOpDecl() override
{ return OpDecl
; }
85 /// getStartLoc - Get the location of the first token of this operand.
86 SMLoc
getStartLoc() const override
{ return StartLoc
; }
88 /// getEndLoc - Get the location of the last token of this operand.
89 SMLoc
getEndLoc() const override
{ return EndLoc
; }
91 /// getLocRange - Get the range between the first and last token of this
93 SMRange
getLocRange() const { return SMRange(StartLoc
, EndLoc
); }
95 /// getOffsetOfLoc - Get the location of the offset operator.
96 SMLoc
getOffsetOfLoc() const override
{ return OffsetOfLoc
; }
98 void print(raw_ostream
&OS
) const override
{
100 auto PrintImmValue
= [&](const MCExpr
*Val
, const char *VName
) {
101 if (Val
->getKind() == MCExpr::Constant
) {
102 if (auto Imm
= cast
<MCConstantExpr
>(Val
)->getValue())
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
;
118 OS
<< "Reg:" << X86IntelInstPrinter::getRegisterName(Reg
.RegNo
);
124 PrintImmValue(Imm
.Val
, "Imm:");
127 OS
<< "Prefix:" << Pref
.Prefixes
;
130 OS
<< "Memory: ModeSize=" << Mem
.ModeSize
;
132 OS
<< ",Size=" << Mem
.Size
;
134 OS
<< ",BaseReg=" << X86IntelInstPrinter::getRegisterName(Mem
.BaseReg
);
137 << X86IntelInstPrinter::getRegisterName(Mem
.IndexReg
);
139 OS
<< ",Scale=" << Mem
.Scale
;
141 PrintImmValue(Mem
.Disp
, ",Disp=");
143 OS
<< ",SegReg=" << X86IntelInstPrinter::getRegisterName(Mem
.SegReg
);
148 StringRef
getToken() const {
149 assert(Kind
== Token
&& "Invalid access!");
150 return StringRef(Tok
.Data
, Tok
.Length
);
152 void setTokenValue(StringRef Value
) {
153 assert(Kind
== Token
&& "Invalid access!");
154 Tok
.Data
= Value
.data();
155 Tok
.Length
= Value
.size();
158 unsigned getReg() const override
{
159 assert(Kind
== Register
&& "Invalid access!");
163 unsigned getPrefix() const {
164 assert(Kind
== Prefix
&& "Invalid access!");
165 return Pref
.Prefixes
;
168 const MCExpr
*getImm() const {
169 assert(Kind
== Immediate
&& "Invalid access!");
173 const MCExpr
*getMemDisp() const {
174 assert(Kind
== Memory
&& "Invalid access!");
177 unsigned getMemSegReg() const {
178 assert(Kind
== Memory
&& "Invalid access!");
181 unsigned getMemBaseReg() const {
182 assert(Kind
== Memory
&& "Invalid access!");
185 unsigned getMemIndexReg() const {
186 assert(Kind
== Memory
&& "Invalid access!");
189 unsigned getMemScale() const {
190 assert(Kind
== Memory
&& "Invalid access!");
193 unsigned getMemModeSize() const {
194 assert(Kind
== Memory
&& "Invalid access!");
197 unsigned getMemFrontendSize() const {
198 assert(Kind
== Memory
&& "Invalid access!");
199 return Mem
.FrontendSize
;
202 bool isToken() const override
{return Kind
== Token
; }
204 bool isImm() const override
{ return Kind
== Immediate
; }
206 bool isImmSExti16i8() const {
210 // If this isn't a constant expr, just assume it fits and let relaxation
212 const MCConstantExpr
*CE
= dyn_cast
<MCConstantExpr
>(getImm());
216 // Otherwise, check the value is in a range that makes sense for this
218 return isImmSExti16i8Value(CE
->getValue());
220 bool isImmSExti32i8() const {
224 // If this isn't a constant expr, just assume it fits and let relaxation
226 const MCConstantExpr
*CE
= dyn_cast
<MCConstantExpr
>(getImm());
230 // Otherwise, check the value is in a range that makes sense for this
232 return isImmSExti32i8Value(CE
->getValue());
234 bool isImmSExti64i8() const {
238 // If this isn't a constant expr, just assume it fits and let relaxation
240 const MCConstantExpr
*CE
= dyn_cast
<MCConstantExpr
>(getImm());
244 // Otherwise, check the value is in a range that makes sense for this
246 return isImmSExti64i8Value(CE
->getValue());
248 bool isImmSExti64i32() const {
252 // If this isn't a constant expr, just assume it fits and let relaxation
254 const MCConstantExpr
*CE
= dyn_cast
<MCConstantExpr
>(getImm());
258 // Otherwise, check the value is in a range that makes sense for this
260 return isImmSExti64i32Value(CE
->getValue());
263 bool isImmUnsignedi8() const {
264 if (!isImm()) return false;
265 // If this isn't a constant expr, just assume it fits and let relaxation
267 const MCConstantExpr
*CE
= dyn_cast
<MCConstantExpr
>(getImm());
268 if (!CE
) return true;
269 return isImmUnsignedi8Value(CE
->getValue());
272 bool isOffsetOf() const override
{
273 return OffsetOfLoc
.getPointer();
276 bool needAddressOf() const override
{
280 bool isMem() const override
{ return Kind
== Memory
; }
281 bool isMemUnsized() const {
282 return Kind
== Memory
&& Mem
.Size
== 0;
284 bool isMem8() const {
285 return Kind
== Memory
&& (!Mem
.Size
|| Mem
.Size
== 8);
287 bool isMem16() const {
288 return Kind
== Memory
&& (!Mem
.Size
|| Mem
.Size
== 16);
290 bool isMem32() const {
291 return Kind
== Memory
&& (!Mem
.Size
|| Mem
.Size
== 32);
293 bool isMem64() const {
294 return Kind
== Memory
&& (!Mem
.Size
|| Mem
.Size
== 64);
296 bool isMem80() const {
297 return Kind
== Memory
&& (!Mem
.Size
|| Mem
.Size
== 80);
299 bool isMem128() const {
300 return Kind
== Memory
&& (!Mem
.Size
|| Mem
.Size
== 128);
302 bool isMem256() const {
303 return Kind
== Memory
&& (!Mem
.Size
|| Mem
.Size
== 256);
305 bool isMem512() const {
306 return Kind
== Memory
&& (!Mem
.Size
|| Mem
.Size
== 512);
308 bool isMemIndexReg(unsigned LowR
, unsigned HighR
) const {
309 assert(Kind
== Memory
&& "Invalid access!");
310 return Mem
.IndexReg
>= LowR
&& Mem
.IndexReg
<= HighR
;
313 bool isMem64_RC128() const {
314 return isMem64() && isMemIndexReg(X86::XMM0
, X86::XMM15
);
316 bool isMem128_RC128() const {
317 return isMem128() && isMemIndexReg(X86::XMM0
, X86::XMM15
);
319 bool isMem128_RC256() const {
320 return isMem128() && isMemIndexReg(X86::YMM0
, X86::YMM15
);
322 bool isMem256_RC128() const {
323 return isMem256() && isMemIndexReg(X86::XMM0
, X86::XMM15
);
325 bool isMem256_RC256() const {
326 return isMem256() && isMemIndexReg(X86::YMM0
, X86::YMM15
);
329 bool isMem64_RC128X() const {
330 return isMem64() && isMemIndexReg(X86::XMM0
, X86::XMM31
);
332 bool isMem128_RC128X() const {
333 return isMem128() && isMemIndexReg(X86::XMM0
, X86::XMM31
);
335 bool isMem128_RC256X() const {
336 return isMem128() && isMemIndexReg(X86::YMM0
, X86::YMM31
);
338 bool isMem256_RC128X() const {
339 return isMem256() && isMemIndexReg(X86::XMM0
, X86::XMM31
);
341 bool isMem256_RC256X() const {
342 return isMem256() && isMemIndexReg(X86::YMM0
, X86::YMM31
);
344 bool isMem256_RC512() const {
345 return isMem256() && isMemIndexReg(X86::ZMM0
, X86::ZMM31
);
347 bool isMem512_RC256X() const {
348 return isMem512() && isMemIndexReg(X86::YMM0
, X86::YMM31
);
350 bool isMem512_RC512() const {
351 return isMem512() && isMemIndexReg(X86::ZMM0
, X86::ZMM31
);
354 bool isAbsMem() const {
355 return Kind
== Memory
&& !getMemSegReg() && !getMemBaseReg() &&
356 !getMemIndexReg() && getMemScale() == 1;
358 bool isAVX512RC() const{
362 bool isAbsMem16() const {
363 return isAbsMem() && Mem
.ModeSize
== 16;
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;
372 bool isSrcIdx8() const {
373 return isMem8() && isSrcIdx();
375 bool isSrcIdx16() const {
376 return isMem16() && isSrcIdx();
378 bool isSrcIdx32() const {
379 return isMem32() && isSrcIdx();
381 bool isSrcIdx64() const {
382 return isMem64() && isSrcIdx();
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;
392 bool isDstIdx8() const {
393 return isMem8() && isDstIdx();
395 bool isDstIdx16() const {
396 return isMem16() && isDstIdx();
398 bool isDstIdx32() const {
399 return isMem32() && isDstIdx();
401 bool isDstIdx64() const {
402 return isMem64() && isDstIdx();
405 bool isMemOffs() const {
406 return Kind
== Memory
&& !getMemBaseReg() && !getMemIndexReg() &&
410 bool isMemOffs16_8() const {
411 return isMemOffs() && Mem
.ModeSize
== 16 && (!Mem
.Size
|| Mem
.Size
== 8);
413 bool isMemOffs16_16() const {
414 return isMemOffs() && Mem
.ModeSize
== 16 && (!Mem
.Size
|| Mem
.Size
== 16);
416 bool isMemOffs16_32() const {
417 return isMemOffs() && Mem
.ModeSize
== 16 && (!Mem
.Size
|| Mem
.Size
== 32);
419 bool isMemOffs32_8() const {
420 return isMemOffs() && Mem
.ModeSize
== 32 && (!Mem
.Size
|| Mem
.Size
== 8);
422 bool isMemOffs32_16() const {
423 return isMemOffs() && Mem
.ModeSize
== 32 && (!Mem
.Size
|| Mem
.Size
== 16);
425 bool isMemOffs32_32() const {
426 return isMemOffs() && Mem
.ModeSize
== 32 && (!Mem
.Size
|| Mem
.Size
== 32);
428 bool isMemOffs32_64() const {
429 return isMemOffs() && Mem
.ModeSize
== 32 && (!Mem
.Size
|| Mem
.Size
== 64);
431 bool isMemOffs64_8() const {
432 return isMemOffs() && Mem
.ModeSize
== 64 && (!Mem
.Size
|| Mem
.Size
== 8);
434 bool isMemOffs64_16() const {
435 return isMemOffs() && Mem
.ModeSize
== 64 && (!Mem
.Size
|| Mem
.Size
== 16);
437 bool isMemOffs64_32() const {
438 return isMemOffs() && Mem
.ModeSize
== 64 && (!Mem
.Size
|| Mem
.Size
== 32);
440 bool isMemOffs64_64() const {
441 return isMemOffs() && Mem
.ModeSize
== 64 && (!Mem
.Size
|| Mem
.Size
== 64);
444 bool isPrefix() const { return Kind
== Prefix
; }
445 bool isReg() const override
{ return Kind
== Register
; }
446 bool isDXReg() const { return Kind
== DXRegister
; }
448 bool isGR32orGR64() const {
449 return Kind
== Register
&&
450 (X86MCRegisterClasses
[X86::GR32RegClassID
].contains(getReg()) ||
451 X86MCRegisterClasses
[X86::GR64RegClassID
].contains(getReg()));
454 void addExpr(MCInst
&Inst
, const MCExpr
*Expr
) const {
455 // Add as immediates when possible.
456 if (const MCConstantExpr
*CE
= dyn_cast
<MCConstantExpr
>(Expr
))
457 Inst
.addOperand(MCOperand::createImm(CE
->getValue()));
459 Inst
.addOperand(MCOperand::createExpr(Expr
));
462 void addRegOperands(MCInst
&Inst
, unsigned N
) const {
463 assert(N
== 1 && "Invalid number of operands!");
464 Inst
.addOperand(MCOperand::createReg(getReg()));
467 void addGR32orGR64Operands(MCInst
&Inst
, unsigned N
) const {
468 assert(N
== 1 && "Invalid number of operands!");
469 unsigned RegNo
= getReg();
470 if (X86MCRegisterClasses
[X86::GR64RegClassID
].contains(RegNo
))
471 RegNo
= getX86SubSuperRegister(RegNo
, 32);
472 Inst
.addOperand(MCOperand::createReg(RegNo
));
475 void addAVX512RCOperands(MCInst
&Inst
, unsigned N
) const {
476 assert(N
== 1 && "Invalid number of operands!");
477 addExpr(Inst
, getImm());
480 void addImmOperands(MCInst
&Inst
, unsigned N
) const {
481 assert(N
== 1 && "Invalid number of operands!");
482 addExpr(Inst
, getImm());
485 void addMemOperands(MCInst
&Inst
, unsigned N
) const {
486 assert((N
== 5) && "Invalid number of operands!");
487 Inst
.addOperand(MCOperand::createReg(getMemBaseReg()));
488 Inst
.addOperand(MCOperand::createImm(getMemScale()));
489 Inst
.addOperand(MCOperand::createReg(getMemIndexReg()));
490 addExpr(Inst
, getMemDisp());
491 Inst
.addOperand(MCOperand::createReg(getMemSegReg()));
494 void addAbsMemOperands(MCInst
&Inst
, unsigned N
) const {
495 assert((N
== 1) && "Invalid number of operands!");
496 // Add as immediates when possible.
497 if (const MCConstantExpr
*CE
= dyn_cast
<MCConstantExpr
>(getMemDisp()))
498 Inst
.addOperand(MCOperand::createImm(CE
->getValue()));
500 Inst
.addOperand(MCOperand::createExpr(getMemDisp()));
503 void addSrcIdxOperands(MCInst
&Inst
, unsigned N
) const {
504 assert((N
== 2) && "Invalid number of operands!");
505 Inst
.addOperand(MCOperand::createReg(getMemBaseReg()));
506 Inst
.addOperand(MCOperand::createReg(getMemSegReg()));
509 void addDstIdxOperands(MCInst
&Inst
, unsigned N
) const {
510 assert((N
== 1) && "Invalid number of operands!");
511 Inst
.addOperand(MCOperand::createReg(getMemBaseReg()));
514 void addMemOffsOperands(MCInst
&Inst
, unsigned N
) const {
515 assert((N
== 2) && "Invalid number of operands!");
516 // Add as immediates when possible.
517 if (const MCConstantExpr
*CE
= dyn_cast
<MCConstantExpr
>(getMemDisp()))
518 Inst
.addOperand(MCOperand::createImm(CE
->getValue()));
520 Inst
.addOperand(MCOperand::createExpr(getMemDisp()));
521 Inst
.addOperand(MCOperand::createReg(getMemSegReg()));
524 static std::unique_ptr
<X86Operand
> CreateToken(StringRef Str
, SMLoc Loc
) {
525 SMLoc EndLoc
= SMLoc::getFromPointer(Loc
.getPointer() + Str
.size());
526 auto Res
= llvm::make_unique
<X86Operand
>(Token
, Loc
, EndLoc
);
527 Res
->Tok
.Data
= Str
.data();
528 Res
->Tok
.Length
= Str
.size();
532 static std::unique_ptr
<X86Operand
>
533 CreateReg(unsigned RegNo
, SMLoc StartLoc
, SMLoc EndLoc
,
534 bool AddressOf
= false, SMLoc OffsetOfLoc
= SMLoc(),
535 StringRef SymName
= StringRef(), void *OpDecl
= nullptr) {
536 auto Res
= llvm::make_unique
<X86Operand
>(Register
, StartLoc
, EndLoc
);
537 Res
->Reg
.RegNo
= RegNo
;
538 Res
->AddressOf
= AddressOf
;
539 Res
->OffsetOfLoc
= OffsetOfLoc
;
540 Res
->SymName
= SymName
;
541 Res
->OpDecl
= OpDecl
;
545 static std::unique_ptr
<X86Operand
>
546 CreateDXReg(SMLoc StartLoc
, SMLoc EndLoc
) {
547 return llvm::make_unique
<X86Operand
>(DXRegister
, StartLoc
, EndLoc
);
550 static std::unique_ptr
<X86Operand
>
551 CreatePrefix(unsigned Prefixes
, SMLoc StartLoc
, SMLoc EndLoc
) {
552 auto Res
= llvm::make_unique
<X86Operand
>(Prefix
, StartLoc
, EndLoc
);
553 Res
->Pref
.Prefixes
= Prefixes
;
557 static std::unique_ptr
<X86Operand
> CreateImm(const MCExpr
*Val
,
558 SMLoc StartLoc
, SMLoc EndLoc
) {
559 auto Res
= llvm::make_unique
<X86Operand
>(Immediate
, StartLoc
, EndLoc
);
564 /// Create an absolute memory operand.
565 static std::unique_ptr
<X86Operand
>
566 CreateMem(unsigned ModeSize
, const MCExpr
*Disp
, SMLoc StartLoc
, SMLoc EndLoc
,
567 unsigned Size
= 0, StringRef SymName
= StringRef(),
568 void *OpDecl
= nullptr, unsigned FrontendSize
= 0) {
569 auto Res
= llvm::make_unique
<X86Operand
>(Memory
, StartLoc
, EndLoc
);
571 Res
->Mem
.Disp
= Disp
;
572 Res
->Mem
.BaseReg
= 0;
573 Res
->Mem
.IndexReg
= 0;
575 Res
->Mem
.Size
= Size
;
576 Res
->Mem
.ModeSize
= ModeSize
;
577 Res
->Mem
.FrontendSize
= FrontendSize
;
578 Res
->SymName
= SymName
;
579 Res
->OpDecl
= OpDecl
;
580 Res
->AddressOf
= false;
584 /// Create a generalized memory operand.
585 static std::unique_ptr
<X86Operand
>
586 CreateMem(unsigned ModeSize
, unsigned SegReg
, const MCExpr
*Disp
,
587 unsigned BaseReg
, unsigned IndexReg
, unsigned Scale
, SMLoc StartLoc
,
588 SMLoc EndLoc
, unsigned Size
= 0, StringRef SymName
= StringRef(),
589 void *OpDecl
= nullptr, unsigned FrontendSize
= 0) {
590 // We should never just have a displacement, that should be parsed as an
591 // absolute memory operand.
592 assert((SegReg
|| BaseReg
|| IndexReg
) && "Invalid memory operand!");
594 // The scale should always be one of {1,2,4,8}.
595 assert(((Scale
== 1 || Scale
== 2 || Scale
== 4 || Scale
== 8)) &&
597 auto Res
= llvm::make_unique
<X86Operand
>(Memory
, StartLoc
, EndLoc
);
598 Res
->Mem
.SegReg
= SegReg
;
599 Res
->Mem
.Disp
= Disp
;
600 Res
->Mem
.BaseReg
= BaseReg
;
601 Res
->Mem
.IndexReg
= IndexReg
;
602 Res
->Mem
.Scale
= Scale
;
603 Res
->Mem
.Size
= Size
;
604 Res
->Mem
.ModeSize
= ModeSize
;
605 Res
->Mem
.FrontendSize
= FrontendSize
;
606 Res
->SymName
= SymName
;
607 Res
->OpDecl
= OpDecl
;
608 Res
->AddressOf
= false;
613 } // end namespace llvm
615 #endif // LLVM_LIB_TARGET_X86_ASMPARSER_X86OPERAND_H