47 "x86-experimental-lvi-inline-asm-hardening",
48 cl::desc(
"Harden inline assembly code that may be vulnerable to Load Value"
49 " Injection (LVI). This feature is experimental."),
cl::Hidden);
52 if (Scale != 1 && Scale != 2 && Scale != 4 && Scale != 8) {
53 ErrMsg =
"scale factor in address must be 1, 2, 4 or 8";
61static const char OpPrecedence[] = {
89 unsigned ForcedDataPrefix = 0;
99 VEXEncoding ForcedVEXEncoding = VEXEncoding_Default;
102 DispEncoding_Default,
107 DispEncoding ForcedDispEncoding = DispEncoding_Default;
110 bool UseApxExtendedReg =
false;
112 bool ForcedNoFlag =
false;
115 SMLoc consumeToken() {
124 "do not have a target streamer");
131 bool matchingInlineAsm,
unsigned VariantID = 0) {
134 SwitchMode(X86::Is32Bit);
136 MissingFeatures, matchingInlineAsm,
139 SwitchMode(X86::Is16Bit);
143 enum InfixCalculatorTok {
168 enum IntelOperatorKind {
175 enum MasmOperatorKind {
182 class InfixCalculator {
183 typedef std::pair< InfixCalculatorTok, int64_t > ICToken;
187 bool isUnaryOperator(InfixCalculatorTok
Op)
const {
188 return Op == IC_NEG ||
Op == IC_NOT;
192 int64_t popOperand() {
193 assert (!PostfixStack.
empty() &&
"Poped an empty stack!");
195 if (!(
Op.first == IC_IMM ||
Op.first == IC_REGISTER))
199 void pushOperand(InfixCalculatorTok
Op, int64_t Val = 0) {
200 assert ((
Op == IC_IMM ||
Op == IC_REGISTER) &&
201 "Unexpected operand!");
205 void popOperator() { InfixOperatorStack.
pop_back(); }
206 void pushOperator(InfixCalculatorTok
Op) {
208 if (InfixOperatorStack.
empty()) {
216 unsigned Idx = InfixOperatorStack.
size() - 1;
217 InfixCalculatorTok StackOp = InfixOperatorStack[
Idx];
218 if (OpPrecedence[
Op] > OpPrecedence[StackOp] || StackOp == IC_LPAREN) {
225 unsigned ParenCount = 0;
228 if (InfixOperatorStack.
empty())
231 Idx = InfixOperatorStack.
size() - 1;
232 StackOp = InfixOperatorStack[
Idx];
233 if (!(OpPrecedence[StackOp] >= OpPrecedence[
Op] || ParenCount))
238 if (!ParenCount && StackOp == IC_LPAREN)
241 if (StackOp == IC_RPAREN) {
244 }
else if (StackOp == IC_LPAREN) {
249 PostfixStack.
push_back(std::make_pair(StackOp, 0));
258 while (!InfixOperatorStack.
empty()) {
259 InfixCalculatorTok StackOp = InfixOperatorStack.
pop_back_val();
260 if (StackOp != IC_LPAREN && StackOp != IC_RPAREN)
261 PostfixStack.
push_back(std::make_pair(StackOp, 0));
264 if (PostfixStack.
empty())
268 for (
const ICToken &
Op : PostfixStack) {
269 if (
Op.first == IC_IMM ||
Op.first == IC_REGISTER) {
271 }
else if (isUnaryOperator(
Op.first)) {
272 assert (OperandStack.
size() > 0 &&
"Too few operands.");
274 assert (Operand.first == IC_IMM &&
275 "Unary operation with a register!");
281 OperandStack.
push_back(std::make_pair(IC_IMM, -Operand.second));
284 OperandStack.
push_back(std::make_pair(IC_IMM, ~Operand.second));
288 assert (OperandStack.
size() > 1 &&
"Too few operands.");
297 Val = Op1.second + Op2.second;
298 OperandStack.
push_back(std::make_pair(IC_IMM, Val));
301 Val = Op1.second - Op2.second;
302 OperandStack.
push_back(std::make_pair(IC_IMM, Val));
305 assert (Op1.first == IC_IMM && Op2.first == IC_IMM &&
306 "Multiply operation with an immediate and a register!");
307 Val = Op1.second * Op2.second;
308 OperandStack.
push_back(std::make_pair(IC_IMM, Val));
311 assert (Op1.first == IC_IMM && Op2.first == IC_IMM &&
312 "Divide operation with an immediate and a register!");
313 assert (Op2.second != 0 &&
"Division by zero!");
314 Val = Op1.second / Op2.second;
315 OperandStack.
push_back(std::make_pair(IC_IMM, Val));
318 assert (Op1.first == IC_IMM && Op2.first == IC_IMM &&
319 "Modulo operation with an immediate and a register!");
320 Val = Op1.second % Op2.second;
321 OperandStack.
push_back(std::make_pair(IC_IMM, Val));
324 assert (Op1.first == IC_IMM && Op2.first == IC_IMM &&
325 "Or operation with an immediate and a register!");
326 Val = Op1.second | Op2.second;
327 OperandStack.
push_back(std::make_pair(IC_IMM, Val));
330 assert(Op1.first == IC_IMM && Op2.first == IC_IMM &&
331 "Xor operation with an immediate and a register!");
332 Val = Op1.second ^ Op2.second;
333 OperandStack.
push_back(std::make_pair(IC_IMM, Val));
336 assert (Op1.first == IC_IMM && Op2.first == IC_IMM &&
337 "And operation with an immediate and a register!");
338 Val = Op1.second & Op2.second;
339 OperandStack.
push_back(std::make_pair(IC_IMM, Val));
342 assert (Op1.first == IC_IMM && Op2.first == IC_IMM &&
343 "Left shift operation with an immediate and a register!");
344 Val = Op1.second << Op2.second;
345 OperandStack.
push_back(std::make_pair(IC_IMM, Val));
348 assert (Op1.first == IC_IMM && Op2.first == IC_IMM &&
349 "Right shift operation with an immediate and a register!");
350 Val = Op1.second >> Op2.second;
351 OperandStack.
push_back(std::make_pair(IC_IMM, Val));
354 assert(Op1.first == IC_IMM && Op2.first == IC_IMM &&
355 "Equals operation with an immediate and a register!");
356 Val = (Op1.second == Op2.second) ? -1 : 0;
357 OperandStack.
push_back(std::make_pair(IC_IMM, Val));
360 assert(Op1.first == IC_IMM && Op2.first == IC_IMM &&
361 "Not-equals operation with an immediate and a register!");
362 Val = (Op1.second != Op2.second) ? -1 : 0;
363 OperandStack.
push_back(std::make_pair(IC_IMM, Val));
366 assert(Op1.first == IC_IMM && Op2.first == IC_IMM &&
367 "Less-than operation with an immediate and a register!");
368 Val = (Op1.second < Op2.second) ? -1 : 0;
369 OperandStack.
push_back(std::make_pair(IC_IMM, Val));
372 assert(Op1.first == IC_IMM && Op2.first == IC_IMM &&
373 "Less-than-or-equal operation with an immediate and a "
375 Val = (Op1.second <= Op2.second) ? -1 : 0;
376 OperandStack.
push_back(std::make_pair(IC_IMM, Val));
379 assert(Op1.first == IC_IMM && Op2.first == IC_IMM &&
380 "Greater-than operation with an immediate and a register!");
381 Val = (Op1.second > Op2.second) ? -1 : 0;
382 OperandStack.
push_back(std::make_pair(IC_IMM, Val));
385 assert(Op1.first == IC_IMM && Op2.first == IC_IMM &&
386 "Greater-than-or-equal operation with an immediate and a "
388 Val = (Op1.second >= Op2.second) ? -1 : 0;
389 OperandStack.
push_back(std::make_pair(IC_IMM, Val));
394 assert (OperandStack.
size() == 1 &&
"Expected a single result.");
399 enum IntelExprState {
429 class IntelExprStateMachine {
430 IntelExprState State = IES_INIT, PrevState = IES_ERROR;
431 unsigned BaseReg = 0, IndexReg = 0, TmpReg = 0, Scale = 0;
438 bool MemExpr =
false;
439 bool BracketUsed =
false;
440 bool OffsetOperator =
false;
441 bool AttachToOperandIdx =
false;
443 SMLoc OffsetOperatorLoc;
448 ErrMsg =
"cannot use more than one symbol in memory operand";
457 IntelExprStateMachine() =
default;
459 void addImm(int64_t imm) {
Imm += imm; }
460 short getBracCount()
const {
return BracCount; }
461 bool isMemExpr()
const {
return MemExpr; }
462 bool isBracketUsed()
const {
return BracketUsed; }
463 bool isOffsetOperator()
const {
return OffsetOperator; }
464 SMLoc getOffsetLoc()
const {
return OffsetOperatorLoc; }
465 unsigned getBaseReg()
const {
return BaseReg; }
466 unsigned getIndexReg()
const {
return IndexReg; }
467 unsigned getScale()
const {
return Scale; }
469 StringRef getSymName()
const {
return SymName; }
472 unsigned getElementSize()
const {
return CurType.
ElementSize; }
473 unsigned getLength()
const {
return CurType.
Length; }
474 int64_t getImm() {
return Imm + IC.execute(); }
475 bool isValidEndState()
const {
476 return State == IES_RBRAC || State == IES_INTEGER;
483 void setAppendAfterOperand() { AttachToOperandIdx =
true; }
485 bool isPIC()
const {
return IsPIC; }
486 void setPIC() { IsPIC =
true; }
488 bool hadError()
const {
return State == IES_ERROR; }
494 if (IsPIC && AttachToOperandIdx)
495 ErrMsg =
"Don't use 2 or more regs for mem offset in PIC model!";
497 ErrMsg =
"BaseReg/IndexReg already set!";
502 IntelExprState CurrState = State;
511 IC.pushOperator(IC_OR);
514 PrevState = CurrState;
517 IntelExprState CurrState = State;
526 IC.pushOperator(IC_XOR);
529 PrevState = CurrState;
532 IntelExprState CurrState = State;
541 IC.pushOperator(IC_AND);
544 PrevState = CurrState;
547 IntelExprState CurrState = State;
556 IC.pushOperator(IC_EQ);
559 PrevState = CurrState;
562 IntelExprState CurrState = State;
571 IC.pushOperator(IC_NE);
574 PrevState = CurrState;
577 IntelExprState CurrState = State;
586 IC.pushOperator(IC_LT);
589 PrevState = CurrState;
592 IntelExprState CurrState = State;
601 IC.pushOperator(IC_LE);
604 PrevState = CurrState;
607 IntelExprState CurrState = State;
616 IC.pushOperator(IC_GT);
619 PrevState = CurrState;
622 IntelExprState CurrState = State;
631 IC.pushOperator(IC_GE);
634 PrevState = CurrState;
637 IntelExprState CurrState = State;
646 IC.pushOperator(IC_LSHIFT);
649 PrevState = CurrState;
652 IntelExprState CurrState = State;
661 IC.pushOperator(IC_RSHIFT);
664 PrevState = CurrState;
667 IntelExprState CurrState = State;
677 IC.pushOperator(IC_PLUS);
678 if (CurrState == IES_REGISTER && PrevState != IES_MULTIPLY) {
685 return regsUseUpError(ErrMsg);
692 PrevState = CurrState;
696 IntelExprState CurrState = State;
727 if (CurrState == IES_REGISTER || CurrState == IES_RPAREN ||
728 CurrState == IES_INTEGER || CurrState == IES_RBRAC ||
729 CurrState == IES_OFFSET)
730 IC.pushOperator(IC_MINUS);
731 else if (PrevState == IES_REGISTER && CurrState == IES_MULTIPLY) {
733 ErrMsg =
"Scale can't be negative";
736 IC.pushOperator(IC_NEG);
737 if (CurrState == IES_REGISTER && PrevState != IES_MULTIPLY) {
744 return regsUseUpError(ErrMsg);
751 PrevState = CurrState;
755 IntelExprState CurrState = State;
781 IC.pushOperator(IC_NOT);
784 PrevState = CurrState;
786 bool onRegister(
unsigned Reg,
StringRef &ErrMsg) {
787 IntelExprState CurrState = State;
795 State = IES_REGISTER;
797 IC.pushOperand(IC_REGISTER);
801 if (PrevState == IES_INTEGER) {
803 return regsUseUpError(ErrMsg);
804 State = IES_REGISTER;
807 Scale = IC.popOperand();
810 IC.pushOperand(IC_IMM);
817 PrevState = CurrState;
825 if (ParsingMSInlineAsm)
829 if (
auto *CE = dyn_cast<MCConstantExpr>(SymRef))
830 return onInteger(
CE->getValue(), ErrMsg);
843 if (setSymRef(SymRef, SymRefName, ErrMsg))
847 IC.pushOperand(IC_IMM);
848 if (ParsingMSInlineAsm)
855 bool onInteger(int64_t TmpInt,
StringRef &ErrMsg) {
856 IntelExprState CurrState = State;
882 if (PrevState == IES_REGISTER && CurrState == IES_MULTIPLY) {
885 return regsUseUpError(ErrMsg);
893 IC.pushOperand(IC_IMM, TmpInt);
897 PrevState = CurrState;
909 State = IES_MULTIPLY;
910 IC.pushOperator(IC_MULTIPLY);
923 IC.pushOperator(IC_DIVIDE);
936 IC.pushOperator(IC_MOD);
952 IC.pushOperator(IC_PLUS);
958 assert(!BracCount &&
"BracCount should be zero on parsing's start");
968 IntelExprState CurrState = State;
977 if (BracCount-- != 1) {
978 ErrMsg =
"unexpected bracket encountered";
982 if (CurrState == IES_REGISTER && PrevState != IES_MULTIPLY) {
989 return regsUseUpError(ErrMsg);
996 PrevState = CurrState;
1000 IntelExprState CurrState = State;
1026 IC.pushOperator(IC_LPAREN);
1029 PrevState = CurrState;
1043 IC.pushOperator(IC_RPAREN);
1049 bool ParsingMSInlineAsm,
StringRef &ErrMsg) {
1053 ErrMsg =
"unexpected offset operator expression";
1058 if (setSymRef(Val,
ID, ErrMsg))
1060 OffsetOperator =
true;
1061 OffsetOperatorLoc = OffsetLoc;
1065 IC.pushOperand(IC_IMM);
1066 if (ParsingMSInlineAsm) {
1089 bool MatchingInlineAsm =
false) {
1091 if (MatchingInlineAsm) {
1092 if (!
getLexer().isAtStartOfStatement())
1096 return Parser.
Error(L, Msg, Range);
1102 bool RestoreOnFailure);
1104 std::unique_ptr<X86Operand> DefaultMemSIOperand(
SMLoc Loc);
1105 std::unique_ptr<X86Operand> DefaultMemDIOperand(
SMLoc Loc);
1106 bool IsSIReg(
unsigned Reg);
1107 unsigned GetSIDIForRegClass(
unsigned RegClassID,
unsigned Reg,
bool IsSIReg);
1110 std::unique_ptr<llvm::MCParsedAsmOperand> &&Src,
1111 std::unique_ptr<llvm::MCParsedAsmOperand> &&Dst);
1119 bool ParseIntelDotOperator(IntelExprStateMachine &SM,
SMLoc &
End);
1121 unsigned ParseIntelInlineAsmOperator(
unsigned OpKind);
1123 bool ParseMasmOperator(
unsigned OpKind, int64_t &Val);
1126 bool ParseIntelNamedOperator(
StringRef Name, IntelExprStateMachine &SM,
1128 bool ParseMasmNamedOperator(
StringRef Name, IntelExprStateMachine &SM,
1130 void RewriteIntelExpression(IntelExprStateMachine &SM,
SMLoc Start,
1132 bool ParseIntelExpression(IntelExprStateMachine &SM,
SMLoc &
End);
1133 bool ParseIntelInlineAsmIdentifier(
const MCExpr *&Val,
StringRef &Identifier,
1135 bool IsUnevaluatedOperand,
SMLoc &
End,
1136 bool IsParsingOffsetOperator =
false);
1138 IntelExprStateMachine &SM);
1140 bool ParseMemOperand(
unsigned SegReg,
const MCExpr *Disp,
SMLoc StartLoc,
1145 bool ParseIntelMemoryOperandSize(
unsigned &
Size);
1146 bool CreateMemForMSInlineAsm(
unsigned SegReg,
const MCExpr *Disp,
1147 unsigned BaseReg,
unsigned IndexReg,
1148 unsigned Scale,
bool NonAbsMem,
SMLoc Start,
1153 bool parseDirectiveArch();
1154 bool parseDirectiveNops(
SMLoc L);
1155 bool parseDirectiveEven(
SMLoc L);
1159 bool parseDirectiveFPOProc(
SMLoc L);
1160 bool parseDirectiveFPOSetFrame(
SMLoc L);
1161 bool parseDirectiveFPOPushReg(
SMLoc L);
1162 bool parseDirectiveFPOStackAlloc(
SMLoc L);
1163 bool parseDirectiveFPOStackAlign(
SMLoc L);
1164 bool parseDirectiveFPOEndPrologue(
SMLoc L);
1165 bool parseDirectiveFPOEndProc(
SMLoc L);
1168 bool parseSEHRegisterNumber(
unsigned RegClassID,
MCRegister &RegNo);
1169 bool parseDirectiveSEHPushReg(
SMLoc);
1170 bool parseDirectiveSEHSetFrame(
SMLoc);
1171 bool parseDirectiveSEHSaveReg(
SMLoc);
1172 bool parseDirectiveSEHSaveXMM(
SMLoc);
1173 bool parseDirectiveSEHPushFrame(
SMLoc);
1181 void emitWarningForSpecialLVIInstruction(
SMLoc Loc);
1192 bool MatchingInlineAsm)
override;
1198 bool MatchingInlineAsm);
1200 bool MatchAndEmitATTInstruction(
SMLoc IDLoc,
unsigned &Opcode,
1203 bool MatchingInlineAsm);
1205 bool MatchAndEmitIntelInstruction(
SMLoc IDLoc,
unsigned &Opcode,
1208 bool MatchingInlineAsm);
1217 bool ParseZ(std::unique_ptr<X86Operand> &Z,
const SMLoc &StartLoc);
1219 bool is64BitMode()
const {
1223 bool is32BitMode()
const {
1227 bool is16BitMode()
const {
1231 void SwitchMode(
unsigned mode) {
1233 FeatureBitset AllModes({X86::Is64Bit, X86::Is32Bit, X86::Is16Bit});
1242 unsigned getPointerWidth() {
1243 if (is16BitMode())
return 16;
1244 if (is32BitMode())
return 32;
1245 if (is64BitMode())
return 64;
1249 bool isParsingIntelSyntax() {
1256#define GET_ASSEMBLER_HEADER
1257#include "X86GenAsmMatcher.inc"
1262 enum X86MatchResultTy {
1264#define GET_OPERAND_DIAGNOSTIC_TYPES
1265#include "X86GenAsmMatcher.inc"
1281 SMLoc &EndLoc)
override;
1292#define GET_REGISTER_MATCHER
1293#define GET_SUBTARGET_FEATURE_NAME
1294#include "X86GenAsmMatcher.inc"
1297 unsigned Scale,
bool Is64BitMode,
1304 !(BaseReg == X86::RIP || BaseReg == X86::EIP ||
1305 X86MCRegisterClasses[X86::GR16RegClassID].
contains(BaseReg) ||
1306 X86MCRegisterClasses[X86::GR32RegClassID].
contains(BaseReg) ||
1307 X86MCRegisterClasses[X86::GR64RegClassID].
contains(BaseReg))) {
1308 ErrMsg =
"invalid base+index expression";
1312 if (IndexReg != 0 &&
1313 !(IndexReg == X86::EIZ || IndexReg == X86::RIZ ||
1314 X86MCRegisterClasses[X86::GR16RegClassID].
contains(IndexReg) ||
1315 X86MCRegisterClasses[X86::GR32RegClassID].
contains(IndexReg) ||
1316 X86MCRegisterClasses[X86::GR64RegClassID].
contains(IndexReg) ||
1317 X86MCRegisterClasses[X86::VR128XRegClassID].
contains(IndexReg) ||
1318 X86MCRegisterClasses[X86::VR256XRegClassID].
contains(IndexReg) ||
1319 X86MCRegisterClasses[X86::VR512RegClassID].
contains(IndexReg))) {
1320 ErrMsg =
"invalid base+index expression";
1324 if (((BaseReg == X86::RIP || BaseReg == X86::EIP) && IndexReg != 0) ||
1325 IndexReg == X86::EIP || IndexReg == X86::RIP ||
1326 IndexReg == X86::ESP || IndexReg == X86::RSP) {
1327 ErrMsg =
"invalid base+index expression";
1333 if (X86MCRegisterClasses[X86::GR16RegClassID].
contains(BaseReg) &&
1334 (Is64BitMode || (BaseReg != X86::BX && BaseReg != X86::BP &&
1335 BaseReg != X86::SI && BaseReg != X86::DI))) {
1336 ErrMsg =
"invalid 16-bit base register";
1341 X86MCRegisterClasses[X86::GR16RegClassID].
contains(IndexReg)) {
1342 ErrMsg =
"16-bit memory operand may not include only index register";
1346 if (BaseReg != 0 && IndexReg != 0) {
1347 if (X86MCRegisterClasses[X86::GR64RegClassID].
contains(BaseReg) &&
1348 (X86MCRegisterClasses[X86::GR16RegClassID].
contains(IndexReg) ||
1349 X86MCRegisterClasses[X86::GR32RegClassID].
contains(IndexReg) ||
1350 IndexReg == X86::EIZ)) {
1351 ErrMsg =
"base register is 64-bit, but index register is not";
1354 if (X86MCRegisterClasses[X86::GR32RegClassID].
contains(BaseReg) &&
1355 (X86MCRegisterClasses[X86::GR16RegClassID].
contains(IndexReg) ||
1356 X86MCRegisterClasses[X86::GR64RegClassID].
contains(IndexReg) ||
1357 IndexReg == X86::RIZ)) {
1358 ErrMsg =
"base register is 32-bit, but index register is not";
1361 if (X86MCRegisterClasses[X86::GR16RegClassID].
contains(BaseReg)) {
1362 if (X86MCRegisterClasses[X86::GR32RegClassID].
contains(IndexReg) ||
1363 X86MCRegisterClasses[X86::GR64RegClassID].
contains(IndexReg)) {
1364 ErrMsg =
"base register is 16-bit, but index register is not";
1367 if ((BaseReg != X86::BX && BaseReg != X86::BP) ||
1368 (IndexReg != X86::SI && IndexReg != X86::DI)) {
1369 ErrMsg =
"invalid 16-bit base/index register combination";
1376 if (!Is64BitMode && BaseReg != 0 &&
1377 (BaseReg == X86::RIP || BaseReg == X86::EIP)) {
1378 ErrMsg =
"IP-relative addressing requires 64-bit mode";
1399 if (isParsingMSInlineAsm() && isParsingIntelSyntax() &&
1400 (RegNo == X86::EFLAGS || RegNo == X86::MXCSR))
1403 if (!is64BitMode()) {
1407 if (RegNo == X86::RIZ || RegNo == X86::RIP ||
1408 X86MCRegisterClasses[X86::GR64RegClassID].
contains(RegNo) ||
1411 return Error(StartLoc,
1412 "register %" +
RegName +
" is only available in 64-bit mode",
1418 UseApxExtendedReg =
true;
1422 if (RegNo == 0 &&
RegName.starts_with(
"db")) {
1481 if (isParsingIntelSyntax())
1483 return Error(StartLoc,
"invalid register name",
SMRange(StartLoc, EndLoc));
1489 SMLoc &EndLoc,
bool RestoreOnFailure) {
1495 auto OnFailure = [RestoreOnFailure, &Lexer, &Tokens]() {
1496 if (RestoreOnFailure) {
1497 while (!Tokens.
empty()) {
1504 StartLoc = PercentTok.
getLoc();
1518 if (isParsingIntelSyntax())
return true;
1519 return Error(StartLoc,
"invalid register name",
1523 if (MatchRegisterByName(RegNo, Tok.
getString(), StartLoc, EndLoc)) {
1529 if (RegNo == X86::ST0) {
1543 return Error(IntTok.
getLoc(),
"expected stack index");
1546 case 0: RegNo = X86::ST0;
break;
1547 case 1: RegNo = X86::ST1;
break;
1548 case 2: RegNo = X86::ST2;
break;
1549 case 3: RegNo = X86::ST3;
break;
1550 case 4: RegNo = X86::ST4;
break;
1551 case 5: RegNo = X86::ST5;
break;
1552 case 6: RegNo = X86::ST6;
break;
1553 case 7: RegNo = X86::ST7;
break;
1556 return Error(IntTok.
getLoc(),
"invalid stack index");
1576 if (isParsingIntelSyntax())
return true;
1577 return Error(StartLoc,
"invalid register name",
1587 return ParseRegister(Reg, StartLoc, EndLoc,
false);
1592 bool Result = ParseRegister(Reg, StartLoc, EndLoc,
true);
1593 bool PendingErrors = getParser().hasPendingError();
1594 getParser().clearPendingErrors();
1602std::unique_ptr<X86Operand> X86AsmParser::DefaultMemSIOperand(
SMLoc Loc) {
1603 bool Parse32 = is32BitMode() || Code16GCC;
1604 unsigned Basereg = is64BitMode() ? X86::RSI : (Parse32 ? X86::ESI : X86::SI);
1611std::unique_ptr<X86Operand> X86AsmParser::DefaultMemDIOperand(
SMLoc Loc) {
1612 bool Parse32 = is32BitMode() || Code16GCC;
1613 unsigned Basereg = is64BitMode() ? X86::RDI : (Parse32 ? X86::EDI : X86::DI);
1620bool X86AsmParser::IsSIReg(
unsigned Reg) {
1634unsigned X86AsmParser::GetSIDIForRegClass(
unsigned RegClassID,
unsigned Reg,
1636 switch (RegClassID) {
1638 case X86::GR64RegClassID:
1639 return IsSIReg ? X86::RSI : X86::RDI;
1640 case X86::GR32RegClassID:
1641 return IsSIReg ? X86::ESI : X86::EDI;
1642 case X86::GR16RegClassID:
1643 return IsSIReg ? X86::SI : X86::DI;
1647void X86AsmParser::AddDefaultSrcDestOperands(
1649 std::unique_ptr<llvm::MCParsedAsmOperand> &&Dst) {
1650 if (isParsingIntelSyntax()) {
1651 Operands.push_back(std::move(Dst));
1652 Operands.push_back(std::move(Src));
1655 Operands.push_back(std::move(Src));
1656 Operands.push_back(std::move(Dst));
1660bool X86AsmParser::VerifyAndAdjustOperands(
OperandVector &OrigOperands,
1663 if (OrigOperands.
size() > 1) {
1666 "Operand size mismatch");
1670 int RegClassID = -1;
1671 for (
unsigned int i = 0; i < FinalOperands.
size(); ++i) {
1675 if (FinalOp.
isReg() &&
1680 if (FinalOp.
isMem()) {
1682 if (!OrigOp.
isMem())
1691 if (RegClassID != -1 &&
1692 !X86MCRegisterClasses[RegClassID].
contains(OrigReg)) {
1694 "mismatching source and destination index registers");
1697 if (X86MCRegisterClasses[X86::GR64RegClassID].
contains(OrigReg))
1698 RegClassID = X86::GR64RegClassID;
1699 else if (X86MCRegisterClasses[X86::GR32RegClassID].
contains(OrigReg))
1700 RegClassID = X86::GR32RegClassID;
1701 else if (X86MCRegisterClasses[X86::GR16RegClassID].
contains(OrigReg))
1702 RegClassID = X86::GR16RegClassID;
1708 bool IsSI = IsSIReg(FinalReg);
1709 FinalReg = GetSIDIForRegClass(RegClassID, FinalReg, IsSI);
1711 if (FinalReg != OrigReg) {
1712 std::string
RegName = IsSI ?
"ES:(R|E)SI" :
"ES:(R|E)DI";
1715 "memory operand is only for determining the size, " +
RegName +
1716 " will be used for the location"));
1727 for (
auto &WarningMsg : Warnings) {
1728 Warning(WarningMsg.first, WarningMsg.second);
1732 for (
unsigned int i = 0; i < FinalOperands.
size(); ++i)
1736 for (
auto &
Op : FinalOperands)
1743 if (isParsingIntelSyntax())
1749bool X86AsmParser::CreateMemForMSInlineAsm(
unsigned SegReg,
const MCExpr *Disp,
1750 unsigned BaseReg,
unsigned IndexReg,
1751 unsigned Scale,
bool NonAbsMem,
1769 unsigned FrontendSize = 0;
1770 void *Decl =
nullptr;
1771 bool IsGlobalLV =
false;
1774 FrontendSize =
Info.Var.Type * 8;
1775 Decl =
Info.Var.Decl;
1776 IsGlobalLV =
Info.Var.IsGlobalLV;
1781 if (BaseReg || IndexReg) {
1783 End,
Size, Identifier, Decl, 0,
1784 BaseReg && IndexReg));
1791 getPointerWidth(), SegReg, Disp, BaseReg, IndexReg, Scale, Start,
End,
1793 X86::RIP, Identifier, Decl, FrontendSize));
1801 IntelExprStateMachine &SM,
1806 !getParser().isParsingMasm())
1808 if (
Name.equals_insensitive(
"not")) {
1810 }
else if (
Name.equals_insensitive(
"or")) {
1812 }
else if (
Name.equals_insensitive(
"shl")) {
1814 }
else if (
Name.equals_insensitive(
"shr")) {
1816 }
else if (
Name.equals_insensitive(
"xor")) {
1818 }
else if (
Name.equals_insensitive(
"and")) {
1820 }
else if (
Name.equals_insensitive(
"mod")) {
1822 }
else if (
Name.equals_insensitive(
"offset")) {
1823 SMLoc OffsetLoc = getTok().getLoc();
1824 const MCExpr *Val =
nullptr;
1827 ParseError = ParseIntelOffsetOperator(Val,
ID, Info,
End);
1832 SM.onOffset(Val, OffsetLoc,
ID, Info, isParsingMSInlineAsm(), ErrMsg);
1838 if (!
Name.equals_insensitive(
"offset"))
1839 End = consumeToken();
1843 IntelExprStateMachine &SM,
1845 if (
Name.equals_insensitive(
"eq")) {
1847 }
else if (
Name.equals_insensitive(
"ne")) {
1849 }
else if (
Name.equals_insensitive(
"lt")) {
1851 }
else if (
Name.equals_insensitive(
"le")) {
1853 }
else if (
Name.equals_insensitive(
"gt")) {
1855 }
else if (
Name.equals_insensitive(
"ge")) {
1860 End = consumeToken();
1867 IntelExprStateMachine &SM) {
1871 SM.setAppendAfterOperand();
1874bool X86AsmParser::ParseIntelExpression(IntelExprStateMachine &SM,
SMLoc &
End) {
1880 if (getContext().getObjectFileInfo()->isPositionIndependent())
1889 bool UpdateLocLex =
true;
1894 if ((
Done = SM.isValidEndState()))
1896 return Error(Tok.
getLoc(),
"unknown token in expression");
1898 return Error(getLexer().getErrLoc(), getLexer().getErr());
1905 UpdateLocLex =
false;
1906 if (ParseIntelDotOperator(SM,
End))
1911 if ((
Done = SM.isValidEndState()))
1913 return Error(Tok.
getLoc(),
"unknown token in expression");
1917 UpdateLocLex =
false;
1918 if (ParseIntelDotOperator(SM,
End))
1923 if ((
Done = SM.isValidEndState()))
1925 return Error(Tok.
getLoc(),
"unknown token in expression");
1936 UpdateLocLex =
false;
1937 if (!Val->evaluateAsAbsolute(Res, getStreamer().getAssemblerPtr()))
1938 return Error(ValueLoc,
"expected absolute value");
1939 if (SM.onInteger(Res, ErrMsg))
1940 return Error(ValueLoc, ErrMsg);
1949 UpdateLocLex =
false;
1951 size_t DotOffset =
Identifier.find_first_of(
'.');
1969 const AsmToken &NextTok = getLexer().peekTok();
1978 End = consumeToken();
1985 if (!ParseRegister(Reg, IdentLoc,
End,
true)) {
1986 if (SM.onRegister(Reg, ErrMsg))
1987 return Error(IdentLoc, ErrMsg);
1991 const std::pair<StringRef, StringRef> IDField =
1995 if (!
Field.empty() &&
1996 !MatchRegisterByName(Reg,
ID, IdentLoc, IDEndLoc)) {
1997 if (SM.onRegister(Reg, ErrMsg))
1998 return Error(IdentLoc, ErrMsg);
2003 return Error(FieldStartLoc,
"unknown offset");
2004 else if (SM.onPlus(ErrMsg))
2005 return Error(getTok().getLoc(), ErrMsg);
2006 else if (SM.onInteger(
Info.Offset, ErrMsg))
2007 return Error(IdentLoc, ErrMsg);
2008 SM.setTypeInfo(
Info.Type);
2010 End = consumeToken();
2016 bool ParseError =
false;
2017 if (ParseIntelNamedOperator(Identifier, SM, ParseError,
End)) {
2023 ParseMasmNamedOperator(Identifier, SM, ParseError,
End)) {
2036 if (ParseIntelDotOperator(SM,
End))
2041 if (isParsingMSInlineAsm()) {
2043 if (
unsigned OpKind = IdentifyIntelInlineAsmOperator(Identifier)) {
2044 if (int64_t Val = ParseIntelInlineAsmOperator(OpKind)) {
2045 if (SM.onInteger(Val, ErrMsg))
2046 return Error(IdentLoc, ErrMsg);
2055 return Error(IdentLoc,
"expected identifier");
2056 if (ParseIntelInlineAsmIdentifier(Val, Identifier, Info,
false,
End))
2058 else if (SM.onIdentifierExpr(Val, Identifier, Info, FieldInfo.
Type,
2060 return Error(IdentLoc, ErrMsg);
2064 if (
unsigned OpKind = IdentifyMasmOperator(Identifier)) {
2066 if (ParseMasmOperator(OpKind, Val))
2068 if (SM.onInteger(Val, ErrMsg))
2069 return Error(IdentLoc, ErrMsg);
2072 if (!getParser().lookUpType(Identifier, FieldInfo.
Type)) {
2078 getParser().parseIdentifier(Identifier);
2082 if (getParser().lookUpField(FieldInfo.
Type.
Name, Identifier,
2086 return Error(IdentLoc,
"Unable to lookup field reference!",
2092 if (SM.onInteger(FieldInfo.
Offset, ErrMsg))
2093 return Error(IdentLoc, ErrMsg);
2097 if (getParser().parsePrimaryExpr(Val,
End, &FieldInfo.
Type)) {
2098 return Error(Tok.
getLoc(),
"Unexpected identifier!");
2099 }
else if (SM.onIdentifierExpr(Val, Identifier, Info, FieldInfo.
Type,
2101 return Error(IdentLoc, ErrMsg);
2107 SMLoc Loc = getTok().getLoc();
2108 int64_t
IntVal = getTok().getIntVal();
2109 End = consumeToken();
2110 UpdateLocLex =
false;
2113 if (IDVal ==
"f" || IDVal ==
"b") {
2115 getContext().getDirectionalLocalSymbol(IntVal, IDVal ==
"b");
2119 if (IDVal ==
"b" &&
Sym->isUndefined())
2120 return Error(Loc,
"invalid reference to undefined symbol");
2124 if (SM.onIdentifierExpr(Val, Identifier, Info,
Type,
2125 isParsingMSInlineAsm(), ErrMsg))
2126 return Error(Loc, ErrMsg);
2127 End = consumeToken();
2129 if (SM.onInteger(IntVal, ErrMsg))
2130 return Error(Loc, ErrMsg);
2133 if (SM.onInteger(IntVal, ErrMsg))
2134 return Error(Loc, ErrMsg);
2139 if (SM.onPlus(ErrMsg))
2140 return Error(getTok().getLoc(), ErrMsg);
2143 if (SM.onMinus(ErrMsg))
2144 return Error(getTok().getLoc(), ErrMsg);
2154 SM.onLShift();
break;
2156 SM.onRShift();
break;
2159 return Error(Tok.
getLoc(),
"unexpected bracket encountered");
2160 tryParseOperandIdx(PrevTK, SM);
2163 if (SM.onRBrac(ErrMsg)) {
2171 return Error(Tok.
getLoc(),
"unknown token in expression");
2173 if (!
Done && UpdateLocLex)
2174 End = consumeToken();
2181void X86AsmParser::RewriteIntelExpression(IntelExprStateMachine &SM,
2184 unsigned ExprLen =
End.getPointer() - Start.getPointer();
2186 if (SM.getSym() && !SM.isOffsetOperator()) {
2188 if (
unsigned Len = SymName.
data() - Start.getPointer())
2191 ExprLen =
End.getPointer() - (SymName.
data() + SymName.
size());
2194 if (!(SM.getBaseReg() || SM.getIndexReg() || SM.getImm())) {
2204 if (SM.getBaseReg())
2206 if (SM.getIndexReg())
2208 if (SM.isOffsetOperator())
2209 OffsetNameStr = SM.getSymName();
2211 IntelExpr Expr(BaseRegStr, IndexRegStr, SM.getScale(), OffsetNameStr,
2212 SM.getImm(), SM.isMemExpr());
2213 InstInfo->
AsmRewrites->emplace_back(Loc, ExprLen, Expr);
2217bool X86AsmParser::ParseIntelInlineAsmIdentifier(
2219 bool IsUnevaluatedOperand,
SMLoc &
End,
bool IsParsingOffsetOperator) {
2221 assert(isParsingMSInlineAsm() &&
"Expected to be parsing inline assembly.");
2225 SemaCallback->LookupInlineAsmIdentifier(LineBuf, Info, IsUnevaluatedOperand);
2236 }
while (
End.getPointer() < EndPtr);
2243 "frontend claimed part of a token?");
2249 SemaCallback->LookupInlineAsmLabel(Identifier, getSourceManager(),
2251 assert(InternalName.
size() &&
"We should have an internal name here.");
2254 if (!IsParsingOffsetOperator)
2262 MCSymbol *
Sym = getContext().getOrCreateSymbol(Identifier);
2273 const SMLoc consumedToken = consumeToken();
2275 return Error(Tok.
getLoc(),
"Expected an identifier after {");
2278 .
Case(
"rn", X86::STATIC_ROUNDING::TO_NEAREST_INT)
2279 .
Case(
"rd", X86::STATIC_ROUNDING::TO_NEG_INF)
2280 .
Case(
"ru", X86::STATIC_ROUNDING::TO_POS_INF)
2281 .
Case(
"rz", X86::STATIC_ROUNDING::TO_ZERO)
2284 return Error(Tok.
getLoc(),
"Invalid rounding mode.");
2287 return Error(Tok.
getLoc(),
"Expected - at this point");
2291 return Error(Tok.
getLoc(),
"Expected } at this point");
2294 const MCExpr *RndModeOp =
2302 return Error(Tok.
getLoc(),
"Expected } at this point");
2307 return Error(Tok.
getLoc(),
"unknown token in expression");
2317 return Error(Tok.
getLoc(),
"Expected { at this point");
2321 return Error(Tok.
getLoc(),
"Expected dfv at this point");
2325 return Error(Tok.
getLoc(),
"Expected = at this point");
2337 unsigned CFlags = 0;
2338 for (
unsigned I = 0;
I < 4; ++
I) {
2347 return Error(Tok.
getLoc(),
"Invalid conditional flags");
2350 return Error(Tok.
getLoc(),
"Duplicated conditional flag");
2361 }
else if (
I == 3) {
2362 return Error(Tok.
getLoc(),
"Expected } at this point");
2364 return Error(Tok.
getLoc(),
"Expected } or , at this point");
2372bool X86AsmParser::ParseIntelDotOperator(IntelExprStateMachine &SM,
2388 }
else if ((isParsingMSInlineAsm() || getParser().isParsingMasm()) &&
2391 TrailingDot = DotDispStr.
substr(DotDispStr.
size() - 1);
2394 const std::pair<StringRef, StringRef> BaseMember = DotDispStr.
split(
'.');
2396 if (getParser().lookUpField(SM.getType(), DotDispStr, Info) &&
2397 getParser().lookUpField(SM.getSymName(), DotDispStr, Info) &&
2398 getParser().lookUpField(DotDispStr, Info) &&
2400 SemaCallback->LookupInlineAsmField(
Base, Member,
Info.Offset)))
2401 return Error(Tok.
getLoc(),
"Unable to lookup field reference!");
2403 return Error(Tok.
getLoc(),
"Unexpected token type!");
2408 const char *DotExprEndLoc = DotDispStr.
data() + DotDispStr.
size();
2411 if (!TrailingDot.
empty())
2413 SM.addImm(
Info.Offset);
2414 SM.setTypeInfo(
Info.Type);
2424 SMLoc Start = Lex().getLoc();
2425 ID = getTok().getString();
2426 if (!isParsingMSInlineAsm()) {
2429 getParser().parsePrimaryExpr(Val,
End,
nullptr))
2430 return Error(Start,
"unexpected token!");
2431 }
else if (ParseIntelInlineAsmIdentifier(Val,
ID, Info,
false,
End,
true)) {
2432 return Error(Start,
"unable to lookup expression");
2434 return Error(Start,
"offset operator cannot yet handle constants");
2441unsigned X86AsmParser::IdentifyIntelInlineAsmOperator(
StringRef Name) {
2443 .
Cases(
"TYPE",
"type",IOK_TYPE)
2444 .
Cases(
"SIZE",
"size",IOK_SIZE)
2445 .
Cases(
"LENGTH",
"length",IOK_LENGTH)
2455unsigned X86AsmParser::ParseIntelInlineAsmOperator(
unsigned OpKind) {
2460 const MCExpr *Val =
nullptr;
2464 if (ParseIntelInlineAsmIdentifier(Val, Identifier, Info,
2469 Error(Start,
"unable to lookup expression");
2476 case IOK_LENGTH: CVal =
Info.Var.Length;
break;
2477 case IOK_SIZE: CVal =
Info.Var.Size;
break;
2478 case IOK_TYPE: CVal =
Info.Var.Type;
break;
2486unsigned X86AsmParser::IdentifyMasmOperator(
StringRef Name) {
2488 .
Case(
"type", MOK_TYPE)
2489 .
Cases(
"size",
"sizeof", MOK_SIZEOF)
2490 .
Cases(
"length",
"lengthof", MOK_LENGTHOF)
2500bool X86AsmParser::ParseMasmOperator(
unsigned OpKind, int64_t &Val) {
2506 if (OpKind == MOK_SIZEOF || OpKind == MOK_TYPE) {
2509 const AsmToken &IDTok = InParens ? getLexer().peekTok() : Parser.
getTok();
2525 IntelExprStateMachine SM;
2527 if (ParseIntelExpression(SM,
End))
2537 Val = SM.getLength();
2540 Val = SM.getElementSize();
2545 return Error(OpLoc,
"expression has unknown type",
SMRange(Start,
End));
2551bool X86AsmParser::ParseIntelMemoryOperandSize(
unsigned &
Size) {
2553 .
Cases(
"BYTE",
"byte", 8)
2554 .
Cases(
"WORD",
"word", 16)
2555 .
Cases(
"DWORD",
"dword", 32)
2556 .
Cases(
"FLOAT",
"float", 32)
2557 .
Cases(
"LONG",
"long", 32)
2558 .
Cases(
"FWORD",
"fword", 48)
2559 .
Cases(
"DOUBLE",
"double", 64)
2560 .
Cases(
"QWORD",
"qword", 64)
2561 .
Cases(
"MMWORD",
"mmword", 64)
2562 .
Cases(
"XWORD",
"xword", 80)
2563 .
Cases(
"TBYTE",
"tbyte", 80)
2564 .
Cases(
"XMMWORD",
"xmmword", 128)
2565 .
Cases(
"YMMWORD",
"ymmword", 256)
2566 .
Cases(
"ZMMWORD",
"zmmword", 512)
2571 return Error(Tok.
getLoc(),
"Expected 'PTR' or 'ptr' token!");
2584 if (ParseIntelMemoryOperandSize(
Size))
2592 return ParseRoundingModeOp(Start,
Operands);
2597 if (RegNo == X86::RIP)
2598 return Error(Start,
"rip can only be used as a base register");
2602 return Error(Start,
"expected memory operand after 'ptr', "
2603 "found register operand instead");
2608 if (!X86MCRegisterClasses[X86::SEGMENT_REGRegClassID].
contains(RegNo))
2609 return Error(Start,
"invalid segment register");
2611 Start = Lex().getLoc();
2615 IntelExprStateMachine SM;
2616 if (ParseIntelExpression(SM,
End))
2619 if (isParsingMSInlineAsm())
2620 RewriteIntelExpression(SM, Start, Tok.
getLoc());
2622 int64_t
Imm = SM.getImm();
2623 const MCExpr *Disp = SM.getSym();
2632 if (!SM.isMemExpr() && !RegNo) {
2633 if (isParsingMSInlineAsm() && SM.isOffsetOperator()) {
2639 SM.getSymName(),
Info.Var.Decl,
2640 Info.Var.IsGlobalLV));
2650 unsigned BaseReg = SM.getBaseReg();
2651 unsigned IndexReg = SM.getIndexReg();
2652 if (IndexReg && BaseReg == X86::RIP)
2654 unsigned Scale = SM.getScale();
2656 Size = SM.getElementSize() << 3;
2658 if (Scale == 0 && BaseReg != X86::ESP && BaseReg != X86::RSP &&
2659 (IndexReg == X86::ESP || IndexReg == X86::RSP))
2665 !(X86MCRegisterClasses[X86::VR128XRegClassID].
contains(IndexReg) ||
2666 X86MCRegisterClasses[X86::VR256XRegClassID].
contains(IndexReg) ||
2667 X86MCRegisterClasses[X86::VR512RegClassID].
contains(IndexReg)) &&
2668 (X86MCRegisterClasses[X86::VR128XRegClassID].
contains(BaseReg) ||
2669 X86MCRegisterClasses[X86::VR256XRegClassID].
contains(BaseReg) ||
2670 X86MCRegisterClasses[X86::VR512RegClassID].
contains(BaseReg)))
2674 X86MCRegisterClasses[X86::GR16RegClassID].
contains(IndexReg))
2675 return Error(Start,
"16-bit addresses cannot have a scale");
2684 if ((BaseReg == X86::SI || BaseReg == X86::DI) &&
2685 (IndexReg == X86::BX || IndexReg == X86::BP))
2688 if ((BaseReg || IndexReg) &&
2691 return Error(Start, ErrMsg);
2692 bool IsUnconditionalBranch =
2693 Name.equals_insensitive(
"jmp") ||
Name.equals_insensitive(
"call");
2694 if (isParsingMSInlineAsm())
2695 return CreateMemForMSInlineAsm(RegNo, Disp, BaseReg, IndexReg, Scale,
2696 IsUnconditionalBranch && is64BitMode(),
2697 Start,
End,
Size, SM.getSymName(),
2702 unsigned DefaultBaseReg = X86::NoRegister;
2703 bool MaybeDirectBranchDest =
true;
2706 if (is64BitMode() && SM.getElementSize() > 0) {
2707 DefaultBaseReg = X86::RIP;
2709 if (IsUnconditionalBranch) {
2711 MaybeDirectBranchDest =
false;
2713 DefaultBaseReg = X86::RIP;
2714 }
else if (!BaseReg && !IndexReg && Disp &&
2716 if (is64BitMode()) {
2717 if (SM.getSize() == 8) {
2718 MaybeDirectBranchDest =
false;
2719 DefaultBaseReg = X86::RIP;
2722 if (SM.getSize() == 4 || SM.getSize() == 2)
2723 MaybeDirectBranchDest =
false;
2727 }
else if (IsUnconditionalBranch) {
2729 if (!PtrInOperand && SM.isOffsetOperator())
2731 Start,
"`OFFSET` operator cannot be used in an unconditional branch");
2732 if (PtrInOperand || SM.isBracketUsed())
2733 MaybeDirectBranchDest =
false;
2736 if ((BaseReg || IndexReg || RegNo || DefaultBaseReg != X86::NoRegister))
2738 getPointerWidth(), RegNo, Disp, BaseReg, IndexReg, Scale, Start,
End,
2740 0,
false, MaybeDirectBranchDest));
2745 MaybeDirectBranchDest));
2751 switch (getLexer().getKind()) {
2761 "expected immediate expression") ||
2762 getParser().parseExpression(Val,
End) ||
2763 check(isa<X86MCExpr>(Val), L,
"expected immediate expression"))
2770 return ParseRoundingModeOp(Start,
Operands);
2779 const MCExpr *Expr =
nullptr;
2785 if (
auto *RE = dyn_cast<X86MCExpr>(Expr)) {
2788 Reg = RE->getRegNo();
2791 if (Reg == X86::EIZ || Reg == X86::RIZ)
2793 Loc,
"%eiz and %riz can only be used as index registers",
2795 if (Reg == X86::RIP)
2796 return Error(Loc,
"%rip can only be used as a base register",
2803 if (!X86MCRegisterClasses[X86::SEGMENT_REGRegClassID].
contains(Reg))
2804 return Error(Loc,
"invalid segment register");
2812 return ParseMemOperand(Reg, Expr, Loc, EndLoc,
Operands);
2842bool X86AsmParser::ParseZ(std::unique_ptr<X86Operand> &Z,
2843 const SMLoc &StartLoc) {
2849 (getLexer().getTok().getIdentifier() ==
"z")))
2854 return Error(getLexer().getLoc(),
"Expected } at this point");
2866 const SMLoc consumedToken = consumeToken();
2870 if (getLexer().getTok().getIntVal() != 1)
2871 return TokError(
"Expected 1to<NUM> at this point");
2875 return TokError(
"Expected 1to<NUM> at this point");
2878 StringRef BroadcastString = (
Prefix + getLexer().getTok().getIdentifier())
2881 return TokError(
"Expected 1to<NUM> at this point");
2882 const char *BroadcastPrimitive =
2884 .
Case(
"1to2",
"{1to2}")
2885 .
Case(
"1to4",
"{1to4}")
2886 .
Case(
"1to8",
"{1to8}")
2887 .
Case(
"1to16",
"{1to16}")
2888 .
Case(
"1to32",
"{1to32}")
2890 if (!BroadcastPrimitive)
2891 return TokError(
"Invalid memory broadcast primitive.");
2894 return TokError(
"Expected } at this point");
2905 std::unique_ptr<X86Operand>
Z;
2906 if (ParseZ(Z, consumedToken))
2912 SMLoc StartLoc =
Z ? consumeToken() : consumedToken;
2917 if (!parseRegister(RegNo, RegLoc, StartLoc) &&
2918 X86MCRegisterClasses[X86::VK1RegClassID].
contains(RegNo)) {
2919 if (RegNo == X86::K0)
2920 return Error(RegLoc,
"Register k0 can't be used as write mask");
2922 return Error(getLexer().getLoc(),
"Expected } at this point");
2928 return Error(getLexer().getLoc(),
2929 "Expected an op-mask register at this point");
2934 if (ParseZ(Z, consumeToken()) || !Z)
2935 return Error(getLexer().getLoc(),
2936 "Expected a {z} mark at this point");
2952bool X86AsmParser::ParseMemOperand(
unsigned SegReg,
const MCExpr *Disp,
2973 auto isAtMemOperand = [
this]() {
2978 auto TokCount = this->getLexer().peekTokens(Buf,
true);
2981 switch (Buf[0].getKind()) {
2988 if ((TokCount > 1) &&
2990 (Buf[0].getLoc().getPointer() + 1 == Buf[1].getLoc().getPointer()))
2992 Buf[1].getIdentifier().
size() + 1);
3003 MCSymbol *
Sym = this->getContext().getOrCreateSymbol(Id);
3004 if (
Sym->isVariable()) {
3005 auto V =
Sym->getVariableValue(
false);
3006 return isa<X86MCExpr>(V);
3014 if (!isAtMemOperand()) {
3017 assert(!isa<X86MCExpr>(Disp) &&
"Expected non-register here.");
3033 0, 0, 1, StartLoc, EndLoc));
3039 unsigned BaseReg = 0, IndexReg = 0, Scale = 1;
3040 SMLoc BaseLoc = getLexer().getLoc();
3047 check(!isa<X86MCExpr>(E), BaseLoc,
"expected register here"))
3051 BaseReg = cast<X86MCExpr>(E)->getRegNo();
3052 if (BaseReg == X86::EIZ || BaseReg == X86::RIZ)
3053 return Error(BaseLoc,
"eiz and riz can only be used as index registers",
3068 if (!isa<X86MCExpr>(E)) {
3072 if (!E->evaluateAsAbsolute(ScaleVal, getStreamer().getAssemblerPtr()))
3073 return Error(Loc,
"expected absolute expression");
3075 Warning(Loc,
"scale factor without index register is ignored");
3078 IndexReg = cast<X86MCExpr>(E)->getRegNo();
3080 if (BaseReg == X86::RIP)
3082 "%rip as base register can not have an index register");
3083 if (IndexReg == X86::RIP)
3084 return Error(Loc,
"%rip is not allowed as an index register");
3095 return Error(Loc,
"expected scale expression");
3098 if (X86MCRegisterClasses[X86::GR16RegClassID].
contains(BaseReg) &&
3100 return Error(Loc,
"scale factor in 16-bit address must be 1");
3102 return Error(Loc, ErrMsg);
3116 if (BaseReg == X86::DX && IndexReg == 0 && Scale == 1 && SegReg == 0 &&
3117 isa<MCConstantExpr>(Disp) &&
3118 cast<MCConstantExpr>(Disp)->getValue() == 0) {
3125 return Error(BaseLoc, ErrMsg);
3132 if (BaseReg || IndexReg) {
3133 if (
auto CE = dyn_cast<MCConstantExpr>(Disp)) {
3134 auto Imm =
CE->getValue();
3135 bool Is64 = X86MCRegisterClasses[X86::GR64RegClassID].contains(BaseReg) ||
3136 X86MCRegisterClasses[X86::GR64RegClassID].contains(IndexReg);
3137 bool Is16 = X86MCRegisterClasses[X86::GR16RegClassID].contains(BaseReg);
3139 if (!isInt<32>(Imm))
3140 return Error(BaseLoc,
"displacement " +
Twine(Imm) +
3141 " is not within [-2147483648, 2147483647]");
3145 " shortened to 32-bit signed " +
3146 Twine(
static_cast<int32_t
>(Imm)));
3150 " shortened to 16-bit signed " +
3151 Twine(
static_cast<int16_t
>(Imm)));
3156 if (SegReg || BaseReg || IndexReg)
3158 BaseReg, IndexReg, Scale, StartLoc,
3167bool X86AsmParser::parsePrimaryExpr(
const MCExpr *&Res,
SMLoc &EndLoc) {
3175 if (parseRegister(RegNo, StartLoc, EndLoc))
3189 ForcedVEXEncoding = VEXEncoding_Default;
3190 ForcedDispEncoding = DispEncoding_Default;
3191 UseApxExtendedReg =
false;
3192 ForcedNoFlag =
false;
3205 if (Prefix ==
"vex")
3206 ForcedVEXEncoding = VEXEncoding_VEX;
3207 else if (Prefix ==
"vex2")
3208 ForcedVEXEncoding = VEXEncoding_VEX2;
3209 else if (Prefix ==
"vex3")
3210 ForcedVEXEncoding = VEXEncoding_VEX3;
3211 else if (Prefix ==
"evex")
3212 ForcedVEXEncoding = VEXEncoding_EVEX;
3213 else if (Prefix ==
"disp8")
3214 ForcedDispEncoding = DispEncoding_Disp8;
3215 else if (Prefix ==
"disp32")
3216 ForcedDispEncoding = DispEncoding_Disp32;
3217 else if (Prefix ==
"nf")
3218 ForcedNoFlag =
true;
3220 return Error(NameLoc,
"unknown prefix");
3236 if (isParsingMSInlineAsm()) {
3237 if (
Name.equals_insensitive(
"vex"))
3238 ForcedVEXEncoding = VEXEncoding_VEX;
3239 else if (
Name.equals_insensitive(
"vex2"))
3240 ForcedVEXEncoding = VEXEncoding_VEX2;
3241 else if (
Name.equals_insensitive(
"vex3"))
3242 ForcedVEXEncoding = VEXEncoding_VEX3;
3243 else if (
Name.equals_insensitive(
"evex"))
3244 ForcedVEXEncoding = VEXEncoding_EVEX;
3246 if (ForcedVEXEncoding != VEXEncoding_Default) {
3259 if (
Name.consume_back(
".d32")) {
3260 ForcedDispEncoding = DispEncoding_Disp32;
3261 }
else if (
Name.consume_back(
".d8")) {
3262 ForcedDispEncoding = DispEncoding_Disp8;
3268 if (isParsingIntelSyntax() &&
3269 (PatchedName ==
"jmp" || PatchedName ==
"jc" || PatchedName ==
"jnc" ||
3270 PatchedName ==
"jcxz" || PatchedName ==
"jecxz" ||
3275 : NextTok ==
"short") {
3284 NextTok.
size() + 1);
3290 PatchedName !=
"setzub" && PatchedName !=
"setzunb" &&
3291 PatchedName !=
"setb" && PatchedName !=
"setnb")
3292 PatchedName = PatchedName.
substr(0,
Name.size()-1);
3294 unsigned ComparisonPredicate = ~0
U;
3301 bool IsVCMP = PatchedName[0] ==
'v';
3302 unsigned CCIdx =
IsVCMP ? 4 : 3;
3304 PatchedName.
slice(CCIdx, PatchedName.
size() - 2))
3306 .
Case(
"eq_oq", 0x00)
3308 .
Case(
"lt_os", 0x01)
3310 .
Case(
"le_os", 0x02)
3311 .
Case(
"unord", 0x03)
3312 .
Case(
"unord_q", 0x03)
3314 .
Case(
"neq_uq", 0x04)
3316 .
Case(
"nlt_us", 0x05)
3318 .
Case(
"nle_us", 0x06)
3320 .
Case(
"ord_q", 0x07)
3322 .
Case(
"eq_uq", 0x08)
3324 .
Case(
"nge_us", 0x09)
3326 .
Case(
"ngt_us", 0x0A)
3327 .
Case(
"false", 0x0B)
3328 .
Case(
"false_oq", 0x0B)
3329 .
Case(
"neq_oq", 0x0C)
3331 .
Case(
"ge_os", 0x0D)
3333 .
Case(
"gt_os", 0x0E)
3335 .
Case(
"true_uq", 0x0F)
3336 .
Case(
"eq_os", 0x10)
3337 .
Case(
"lt_oq", 0x11)
3338 .
Case(
"le_oq", 0x12)
3339 .
Case(
"unord_s", 0x13)
3340 .
Case(
"neq_us", 0x14)
3341 .
Case(
"nlt_uq", 0x15)
3342 .
Case(
"nle_uq", 0x16)
3343 .
Case(
"ord_s", 0x17)
3344 .
Case(
"eq_us", 0x18)
3345 .
Case(
"nge_uq", 0x19)
3346 .
Case(
"ngt_uq", 0x1A)
3347 .
Case(
"false_os", 0x1B)
3348 .
Case(
"neq_os", 0x1C)
3349 .
Case(
"ge_oq", 0x1D)
3350 .
Case(
"gt_oq", 0x1E)
3351 .
Case(
"true_us", 0x1F)
3356 PatchedName =
IsVCMP ?
"vcmpss" :
"cmpss";
3358 PatchedName =
IsVCMP ?
"vcmpsd" :
"cmpsd";
3360 PatchedName =
IsVCMP ?
"vcmpps" :
"cmpps";
3362 PatchedName =
IsVCMP ?
"vcmppd" :
"cmppd";
3364 PatchedName =
"vcmpsh";
3366 PatchedName =
"vcmpph";
3370 ComparisonPredicate =
CC;
3376 (PatchedName.
back() ==
'b' || PatchedName.
back() ==
'w' ||
3377 PatchedName.
back() ==
'd' || PatchedName.
back() ==
'q')) {
3378 unsigned SuffixSize = PatchedName.
drop_back().
back() ==
'u' ? 2 : 1;
3380 PatchedName.
slice(5, PatchedName.
size() - SuffixSize))
3390 if (
CC != ~0U && (
CC != 0 || SuffixSize == 2)) {
3391 switch (PatchedName.
back()) {
3393 case 'b': PatchedName = SuffixSize == 2 ?
"vpcmpub" :
"vpcmpb";
break;
3394 case 'w': PatchedName = SuffixSize == 2 ?
"vpcmpuw" :
"vpcmpw";
break;
3395 case 'd': PatchedName = SuffixSize == 2 ?
"vpcmpud" :
"vpcmpd";
break;
3396 case 'q': PatchedName = SuffixSize == 2 ?
"vpcmpuq" :
"vpcmpq";
break;
3399 ComparisonPredicate =
CC;
3405 (PatchedName.
back() ==
'b' || PatchedName.
back() ==
'w' ||
3406 PatchedName.
back() ==
'd' || PatchedName.
back() ==
'q')) {
3407 unsigned SuffixSize = PatchedName.
drop_back().
back() ==
'u' ? 2 : 1;
3409 PatchedName.
slice(5, PatchedName.
size() - SuffixSize))
3420 switch (PatchedName.
back()) {
3422 case 'b': PatchedName = SuffixSize == 2 ?
"vpcomub" :
"vpcomb";
break;
3423 case 'w': PatchedName = SuffixSize == 2 ?
"vpcomuw" :
"vpcomw";
break;
3424 case 'd': PatchedName = SuffixSize == 2 ?
"vpcomud" :
"vpcomd";
break;
3425 case 'q': PatchedName = SuffixSize == 2 ?
"vpcomuq" :
"vpcomq";
break;
3428 ComparisonPredicate =
CC;
3441 .
Cases(
"cs",
"ds",
"es",
"fs",
"gs",
"ss",
true)
3442 .
Cases(
"rex64",
"data32",
"data16",
"addr32",
"addr16",
true)
3443 .
Cases(
"xacquire",
"xrelease",
true)
3444 .
Cases(
"acquire",
"release", isParsingIntelSyntax())
3447 auto isLockRepeatNtPrefix = [](
StringRef N) {
3449 .
Cases(
"lock",
"rep",
"repe",
"repz",
"repne",
"repnz",
"notrack",
true)
3453 bool CurlyAsEndOfStatement =
false;
3456 while (isLockRepeatNtPrefix(
Name.lower())) {
3477 while (
Name.starts_with(
";") ||
Name.starts_with(
"\n") ||
3478 Name.starts_with(
"#") ||
Name.starts_with(
"\t") ||
3479 Name.starts_with(
"/")) {
3490 if (PatchedName ==
"data16" && is16BitMode()) {
3491 return Error(NameLoc,
"redundant data16 prefix");
3493 if (PatchedName ==
"data32") {
3495 return Error(NameLoc,
"redundant data32 prefix");
3497 return Error(NameLoc,
"'data32' is not supported in 64-bit mode");
3499 PatchedName =
"data16";
3506 if (Next ==
"callw")
3508 if (Next ==
"ljmpw")
3513 ForcedDataPrefix = X86::Is32Bit;
3521 if (ComparisonPredicate != ~0U && !isParsingIntelSyntax()) {
3523 getParser().getContext());
3528 if ((
Name.starts_with(
"ccmp") ||
Name.starts_with(
"ctest")) &&
3557 CurlyAsEndOfStatement =
3558 isParsingIntelSyntax() && isParsingMSInlineAsm() &&
3561 return TokError(
"unexpected token in argument list");
3565 if (ComparisonPredicate != ~0U && isParsingIntelSyntax()) {
3567 getParser().getContext());
3575 else if (CurlyAsEndOfStatement)
3578 getLexer().getTok().getLoc(), 0);
3585 if (IsFp &&
Operands.size() == 1) {
3587 .
Case(
"fsub",
"fsubp")
3588 .
Case(
"fdiv",
"fdivp")
3589 .
Case(
"fsubr",
"fsubrp")
3590 .
Case(
"fdivr",
"fdivrp");
3594 if ((
Name ==
"mov" ||
Name ==
"movw" ||
Name ==
"movl") &&
3602 X86MCRegisterClasses[X86::SEGMENT_REGRegClassID].contains(
3604 (X86MCRegisterClasses[X86::GR16RegClassID].
contains(Op1.
getReg()) ||
3605 X86MCRegisterClasses[X86::GR32RegClassID].
contains(Op1.
getReg()))) {
3607 if (
Name !=
"mov" &&
Name[3] == (is16BitMode() ?
'l' :
'w')) {
3608 Name = is16BitMode() ?
"movw" :
"movl";
3621 if ((
Name ==
"outb" ||
Name ==
"outsb" ||
Name ==
"outw" ||
Name ==
"outsw" ||
3640 bool HadVerifyError =
false;
3643 if (
Name.starts_with(
"ins") &&
3648 AddDefaultSrcDestOperands(TmpOperands,
3650 DefaultMemDIOperand(NameLoc));
3651 HadVerifyError = VerifyAndAdjustOperands(
Operands, TmpOperands);
3655 if (
Name.starts_with(
"outs") &&
3657 (
Name ==
"outsb" ||
Name ==
"outsw" ||
Name ==
"outsl" ||
3658 Name ==
"outsd" ||
Name ==
"outs")) {
3659 AddDefaultSrcDestOperands(TmpOperands, DefaultMemSIOperand(NameLoc),
3661 HadVerifyError = VerifyAndAdjustOperands(
Operands, TmpOperands);
3667 if (
Name.starts_with(
"lods") &&
3669 (
Name ==
"lods" ||
Name ==
"lodsb" ||
Name ==
"lodsw" ||
3670 Name ==
"lodsl" ||
Name ==
"lodsd" ||
Name ==
"lodsq")) {
3671 TmpOperands.
push_back(DefaultMemSIOperand(NameLoc));
3672 HadVerifyError = VerifyAndAdjustOperands(
Operands, TmpOperands);
3678 if (
Name.starts_with(
"stos") &&
3680 (
Name ==
"stos" ||
Name ==
"stosb" ||
Name ==
"stosw" ||
3681 Name ==
"stosl" ||
Name ==
"stosd" ||
Name ==
"stosq")) {
3682 TmpOperands.
push_back(DefaultMemDIOperand(NameLoc));
3683 HadVerifyError = VerifyAndAdjustOperands(
Operands, TmpOperands);
3689 if (
Name.starts_with(
"scas") &&
3691 (
Name ==
"scas" ||
Name ==
"scasb" ||
Name ==
"scasw" ||
3692 Name ==
"scasl" ||
Name ==
"scasd" ||
Name ==
"scasq")) {
3693 TmpOperands.
push_back(DefaultMemDIOperand(NameLoc));
3694 HadVerifyError = VerifyAndAdjustOperands(
Operands, TmpOperands);
3698 if (
Name.starts_with(
"cmps") &&
3700 (
Name ==
"cmps" ||
Name ==
"cmpsb" ||
Name ==
"cmpsw" ||
3701 Name ==
"cmpsl" ||
Name ==
"cmpsd" ||
Name ==
"cmpsq")) {
3702 AddDefaultSrcDestOperands(TmpOperands, DefaultMemDIOperand(NameLoc),
3703 DefaultMemSIOperand(NameLoc));
3704 HadVerifyError = VerifyAndAdjustOperands(
Operands, TmpOperands);
3708 if (((
Name.starts_with(
"movs") &&
3709 (
Name ==
"movs" ||
Name ==
"movsb" ||
Name ==
"movsw" ||
3710 Name ==
"movsl" ||
Name ==
"movsd" ||
Name ==
"movsq")) ||
3711 (
Name.starts_with(
"smov") &&
3712 (
Name ==
"smov" ||
Name ==
"smovb" ||
Name ==
"smovw" ||
3713 Name ==
"smovl" ||
Name ==
"smovd" ||
Name ==
"smovq"))) &&
3715 if (
Name ==
"movsd" &&
Operands.size() == 1 && !isParsingIntelSyntax())
3717 AddDefaultSrcDestOperands(TmpOperands, DefaultMemSIOperand(NameLoc),
3718 DefaultMemDIOperand(NameLoc));
3719 HadVerifyError = VerifyAndAdjustOperands(
Operands, TmpOperands);
3723 if (HadVerifyError) {
3724 return HadVerifyError;
3732 "size, (R|E)BX will be used for the location");
3744 if (ForcedVEXEncoding != VEXEncoding_VEX3 &&
3752 default:
return false;
3757 if (ForcedDispEncoding == DispEncoding_Disp32) {
3758 Inst.
setOpcode(is16BitMode() ? X86::JMP_2 : X86::JMP_4);
3767 if (ForcedDispEncoding == DispEncoding_Disp32) {
3768 Inst.
setOpcode(is16BitMode() ? X86::JCC_2 : X86::JCC_4);
3786 using namespace X86;
3789 uint64_t TSFlags = MII.get(Opcode).TSFlags;
3790 if (isVFCMADDCPH(Opcode) || isVFCMADDCSH(Opcode) || isVFMADDCPH(Opcode) ||
3791 isVFMADDCSH(Opcode)) {
3795 return Warning(Ops[0]->getStartLoc(),
"Destination register should be "
3796 "distinct from source registers");
3797 }
else if (isVFCMULCPH(Opcode) || isVFCMULCSH(Opcode) || isVFMULCPH(Opcode) ||
3798 isVFMULCSH(Opcode)) {
3808 return Warning(Ops[0]->getStartLoc(),
"Destination register should be "
3809 "distinct from source registers");
3810 }
else if (isV4FMADDPS(Opcode) || isV4FMADDSS(Opcode) ||
3811 isV4FNMADDPS(Opcode) || isV4FNMADDSS(Opcode) ||
3812 isVP4DPWSSDS(Opcode) || isVP4DPWSSD(Opcode)) {
3815 unsigned Src2Enc =
MRI->getEncodingValue(Src2);
3816 if (Src2Enc % 4 != 0) {
3818 unsigned GroupStart = (Src2Enc / 4) * 4;
3819 unsigned GroupEnd = GroupStart + 3;
3820 return Warning(Ops[0]->getStartLoc(),
3821 "source register '" +
RegName +
"' implicitly denotes '" +
3826 }
else if (isVGATHERDPD(Opcode) || isVGATHERDPS(Opcode) ||
3827 isVGATHERQPD(Opcode) || isVGATHERQPS(Opcode) ||
3828 isVPGATHERDD(Opcode) || isVPGATHERDQ(Opcode) ||
3829 isVPGATHERQD(Opcode) || isVPGATHERQQ(Opcode)) {
3833 unsigned Index =
MRI->getEncodingValue(
3836 return Warning(Ops[0]->getStartLoc(),
"index and destination registers "
3837 "should be distinct");
3841 unsigned Index =
MRI->getEncodingValue(
3843 if (Dest == Mask || Dest ==
Index || Mask ==
Index)
3844 return Warning(Ops[0]->getStartLoc(),
"mask, index, and destination "
3845 "registers should be distinct");
3855 for (
unsigned i = 0; i != NumOps; ++i) {
3860 if (Reg == X86::AH || Reg == X86::BH || Reg == X86::CH || Reg == X86::DH)
3867 if (UsesRex && HReg != X86::NoRegister) {
3869 return Error(Ops[0]->getStartLoc(),
3870 "can't encode '" +
RegName +
"' in an instruction requiring "
3875 if ((Opcode == X86::PREFETCHIT0 || Opcode == X86::PREFETCHIT1)) {
3879 Ops[0]->getStartLoc(),
3881 :
"'prefetchit1'")) +
3882 " only supports RIP-relative address");
3887void X86AsmParser::emitWarningForSpecialLVIInstruction(
SMLoc Loc) {
3888 Warning(Loc,
"Instruction may be vulnerable to LVI and "
3889 "requires manual mitigation");
3890 Note(
SMLoc(),
"See https://software.intel.com/"
3891 "security-software-guidance/insights/"
3892 "deep-dive-load-value-injection#specialinstructions"
3893 " for more information");
3917 bool Parse32 = is32BitMode() || Code16GCC;
3919 is64BitMode() ? X86::RSP : (Parse32 ? X86::ESP : X86::SP);
3925 ShlMemOp->addMemOperands(ShlInst, 5);
3938 emitWarningForSpecialLVIInstruction(Inst.
getLoc());
3950void X86AsmParser::applyLVILoadHardeningMitigation(
MCInst &Inst,
3967 emitWarningForSpecialLVIInstruction(Inst.
getLoc());
3970 }
else if (Opcode == X86::REP_PREFIX || Opcode == X86::REPNE_PREFIX) {
3973 emitWarningForSpecialLVIInstruction(Inst.
getLoc());
3995 getSTI().hasFeature(X86::FeatureLVIControlFlowIntegrity))
3996 applyLVICFIMitigation(Inst, Out);
4001 getSTI().hasFeature(X86::FeatureLVILoadHardening))
4002 applyLVILoadHardeningMitigation(Inst, Out);
4005bool X86AsmParser::MatchAndEmitInstruction(
SMLoc IDLoc,
unsigned &Opcode,
4008 bool MatchingInlineAsm) {
4009 if (isParsingIntelSyntax())
4018 bool MatchingInlineAsm) {
4023 .
Case(
"finit",
"fninit")
4024 .
Case(
"fsave",
"fnsave")
4025 .
Case(
"fstcw",
"fnstcw")
4026 .
Case(
"fstcww",
"fnstcw")
4027 .
Case(
"fstenv",
"fnstenv")
4028 .
Case(
"fstsw",
"fnstsw")
4029 .
Case(
"fstsww",
"fnstsw")
4030 .
Case(
"fclex",
"fnclex")
4036 if (!MatchingInlineAsm)
4037 emitInstruction(Inst,
Operands, Out);
4042bool X86AsmParser::ErrorMissingFeature(
SMLoc IDLoc,
4044 bool MatchingInlineAsm) {
4045 assert(MissingFeatures.
any() &&
"Unknown missing feature!");
4048 OS <<
"instruction requires:";
4049 for (
unsigned i = 0, e = MissingFeatures.
size(); i != e; ++i) {
4050 if (MissingFeatures[i])
4057 unsigned Result = 0;
4059 if (Prefix.isPrefix()) {
4060 Result = Prefix.getPrefix();
4066unsigned X86AsmParser::checkTargetMatchPredicate(
MCInst &Inst) {
4071 return Match_Unsupported;
4073 return Match_Unsupported;
4075 if (ForcedVEXEncoding == VEXEncoding_EVEX &&
4077 return Match_Unsupported;
4079 if ((ForcedVEXEncoding == VEXEncoding_VEX ||
4080 ForcedVEXEncoding == VEXEncoding_VEX2 ||
4081 ForcedVEXEncoding == VEXEncoding_VEX3) &&
4083 return Match_Unsupported;
4087 (ForcedVEXEncoding != VEXEncoding_VEX &&
4088 ForcedVEXEncoding != VEXEncoding_VEX2 &&
4089 ForcedVEXEncoding != VEXEncoding_VEX3))
4090 return Match_Unsupported;
4092 return Match_Success;
4095bool X86AsmParser::MatchAndEmitATTInstruction(
SMLoc IDLoc,
unsigned &Opcode,
4099 bool MatchingInlineAsm) {
4101 assert((*
Operands[0]).isToken() &&
"Leading operand should always be a mnemonic!");
4102 SMRange EmptyRange = std::nullopt;
4106 Out, MatchingInlineAsm);
4114 if (ForcedVEXEncoding == VEXEncoding_VEX)
4116 else if (ForcedVEXEncoding == VEXEncoding_VEX2)
4118 else if (ForcedVEXEncoding == VEXEncoding_VEX3)
4120 else if (ForcedVEXEncoding == VEXEncoding_EVEX)
4124 if (ForcedDispEncoding == DispEncoding_Disp8)
4126 else if (ForcedDispEncoding == DispEncoding_Disp32)
4134 if (ForcedDataPrefix == X86::Is32Bit)
4135 SwitchMode(X86::Is32Bit);
4139 MissingFeatures, MatchingInlineAsm,
4140 isParsingIntelSyntax());
4141 if (ForcedDataPrefix == X86::Is32Bit) {
4142 SwitchMode(X86::Is16Bit);
4143 ForcedDataPrefix = 0;
4145 switch (OriginalError) {
4148 if (!MatchingInlineAsm && validateInstruction(Inst,
Operands))
4153 if (!MatchingInlineAsm)
4154 while (processInstruction(Inst,
Operands))
4158 if (!MatchingInlineAsm)
4159 emitInstruction(Inst,
Operands, Out);
4162 case Match_InvalidImmUnsignedi4: {
4164 if (ErrorLoc ==
SMLoc())
4166 return Error(ErrorLoc,
"immediate must be an integer in range [0, 15]",
4167 EmptyRange, MatchingInlineAsm);
4169 case Match_MissingFeature:
4170 return ErrorMissingFeature(IDLoc, MissingFeatures, MatchingInlineAsm);
4171 case Match_InvalidOperand:
4172 case Match_MnemonicFail:
4173 case Match_Unsupported:
4176 if (
Op.getToken().empty()) {
4177 Error(IDLoc,
"instruction must have size higher than 0", EmptyRange,
4192 Op.setTokenValue(Tmp);
4200 const char *Suffixes =
Base[0] !=
'f' ?
"bwlq" :
"slt\0";
4202 const char *MemSize =
Base[0] !=
'f' ?
"\x08\x10\x20\x40" :
"\x20\x40\x50\0";
4214 bool HasVectorReg =
false;
4219 HasVectorReg =
true;
4220 else if (X86Op->
isMem()) {
4222 assert(
MemOp->Mem.Size == 0 &&
"Memory size always 0 under ATT syntax");
4229 for (
unsigned I = 0, E = std::size(
Match);
I != E; ++
I) {
4230 Tmp.
back() = Suffixes[
I];
4231 if (
MemOp && HasVectorReg)
4232 MemOp->Mem.Size = MemSize[
I];
4233 Match[
I] = Match_MnemonicFail;
4234 if (
MemOp || !HasVectorReg) {
4236 MatchInstruction(
Operands, Inst, ErrorInfoIgnore, MissingFeatures,
4237 MatchingInlineAsm, isParsingIntelSyntax());
4239 if (
Match[
I] == Match_MissingFeature)
4240 ErrorInfoMissingFeatures = MissingFeatures;
4251 if (NumSuccessfulMatches == 1) {
4252 if (!MatchingInlineAsm && validateInstruction(Inst,
Operands))
4257 if (!MatchingInlineAsm)
4258 while (processInstruction(Inst,
Operands))
4262 if (!MatchingInlineAsm)
4263 emitInstruction(Inst,
Operands, Out);
4272 if (NumSuccessfulMatches > 1) {
4274 unsigned NumMatches = 0;
4275 for (
unsigned I = 0, E = std::size(
Match);
I != E; ++
I)
4276 if (
Match[
I] == Match_Success)
4277 MatchChars[NumMatches++] = Suffixes[
I];
4281 OS <<
"ambiguous instructions require an explicit suffix (could be ";
4282 for (
unsigned i = 0; i != NumMatches; ++i) {
4285 if (i + 1 == NumMatches)
4287 OS <<
"'" <<
Base << MatchChars[i] <<
"'";
4290 Error(IDLoc,
OS.str(), EmptyRange, MatchingInlineAsm);
4299 if (OriginalError == Match_MnemonicFail)
4300 return Error(IDLoc,
"invalid instruction mnemonic '" +
Base +
"'",
4301 Op.getLocRange(), MatchingInlineAsm);
4303 if (OriginalError == Match_Unsupported)
4304 return Error(IDLoc,
"unsupported instruction", EmptyRange,
4307 assert(OriginalError == Match_InvalidOperand &&
"Unexpected error");
4311 return Error(IDLoc,
"too few operands for instruction", EmptyRange,
4318 OperandRange, MatchingInlineAsm);
4322 return Error(IDLoc,
"invalid operand for instruction", EmptyRange,
4328 return Error(IDLoc,
"unsupported instruction", EmptyRange,
4336 return ErrorMissingFeature(IDLoc, ErrorInfoMissingFeatures,
4343 return Error(IDLoc,
"invalid operand for instruction", EmptyRange,
4348 Error(IDLoc,
"unknown use of instruction mnemonic without a size suffix",
4349 EmptyRange, MatchingInlineAsm);
4353bool X86AsmParser::MatchAndEmitIntelInstruction(
SMLoc IDLoc,
unsigned &Opcode,
4357 bool MatchingInlineAsm) {
4359 assert((*
Operands[0]).isToken() &&
"Leading operand should always be a mnemonic!");
4361 SMRange EmptyRange = std::nullopt;
4373 if (ForcedVEXEncoding == VEXEncoding_VEX)
4375 else if (ForcedVEXEncoding == VEXEncoding_VEX2)
4377 else if (ForcedVEXEncoding == VEXEncoding_VEX3)
4379 else if (ForcedVEXEncoding == VEXEncoding_EVEX)
4383 if (ForcedDispEncoding == DispEncoding_Disp8)
4385 else if (ForcedDispEncoding == DispEncoding_Disp32)
4396 UnsizedMemOp = X86Op;
4406 static const char *
const PtrSizedInstrs[] = {
"call",
"jmp",
"push"};
4407 for (
const char *Instr : PtrSizedInstrs) {
4408 if (Mnemonic == Instr) {
4409 UnsizedMemOp->
Mem.
Size = getPointerWidth();
4421 if (Mnemonic ==
"push" &&
Operands.size() == 2) {
4423 if (X86Op->
isImm()) {
4425 const auto *
CE = dyn_cast<MCConstantExpr>(X86Op->
getImm());
4426 unsigned Size = getPointerWidth();
4431 Tmp += (is64BitMode())
4433 : (is32BitMode()) ?
"l" : (is16BitMode()) ?
"w" :
" ";
4434 Op.setTokenValue(Tmp);
4437 MissingFeatures, MatchingInlineAsm,
4448 static const unsigned MopSizes[] = {8, 16, 32, 64, 80, 128, 256, 512};
4449 for (
unsigned Size : MopSizes) {
4453 unsigned M = MatchInstruction(
Operands, Inst, ErrorInfoIgnore,
4454 MissingFeatures, MatchingInlineAsm,
4455 isParsingIntelSyntax());
4460 if (
Match.back() == Match_MissingFeature)
4461 ErrorInfoMissingFeatures = MissingFeatures;
4471 if (
Match.empty()) {
4472 Match.push_back(MatchInstruction(
4474 isParsingIntelSyntax()));
4476 if (
Match.back() == Match_MissingFeature)
4477 ErrorInfoMissingFeatures = MissingFeatures;
4485 if (
Match.back() == Match_MnemonicFail) {
4486 return Error(IDLoc,
"invalid instruction mnemonic '" + Mnemonic +
"'",
4487 Op.getLocRange(), MatchingInlineAsm);
4494 if (UnsizedMemOp && NumSuccessfulMatches > 1 &&
4497 unsigned M = MatchInstruction(
4499 isParsingIntelSyntax());
4500 if (M == Match_Success)
4501 NumSuccessfulMatches = 1;
4513 if (NumSuccessfulMatches == 1) {
4514 if (!MatchingInlineAsm && validateInstruction(Inst,
Operands))
4519 if (!MatchingInlineAsm)
4520 while (processInstruction(Inst,
Operands))
4523 if (!MatchingInlineAsm)
4524 emitInstruction(Inst,
Operands, Out);
4527 }
else if (NumSuccessfulMatches > 1) {
4529 "multiple matches only possible with unsized memory operands");
4531 "ambiguous operand size for instruction '" + Mnemonic +
"\'",
4537 return Error(IDLoc,
"unsupported instruction", EmptyRange,
4545 return ErrorMissingFeature(IDLoc, ErrorInfoMissingFeatures,
4552 return Error(IDLoc,
"invalid operand for instruction", EmptyRange,
4558 if (ErrorLoc ==
SMLoc())
4560 return Error(ErrorLoc,
"immediate must be an integer in range [0, 15]",
4561 EmptyRange, MatchingInlineAsm);
4565 return Error(IDLoc,
"unknown instruction mnemonic", EmptyRange,
4569bool X86AsmParser::OmitRegisterFromClobberLists(
unsigned RegNo) {
4570 return X86MCRegisterClasses[X86::SEGMENT_REGRegClassID].contains(RegNo);
4573bool X86AsmParser::ParseDirective(
AsmToken DirectiveID) {
4577 return parseDirectiveArch();
4579 return ParseDirectiveCode(IDVal, DirectiveID.
getLoc());
4585 return Error(DirectiveID.
getLoc(),
"'.att_syntax noprefix' is not "
4586 "supported: registers must have a "
4587 "'%' prefix in .att_syntax");
4589 getParser().setAssemblerDialect(0);
4592 getParser().setAssemblerDialect(1);
4597 return Error(DirectiveID.
getLoc(),
"'.intel_syntax prefix' is not "
4598 "supported: registers must not have "
4599 "a '%' prefix in .intel_syntax");
4602 }
else if (IDVal ==
".nops")
4603 return parseDirectiveNops(DirectiveID.
getLoc());
4604 else if (IDVal ==
".even")
4605 return parseDirectiveEven(DirectiveID.
getLoc());
4606 else if (IDVal ==
".cv_fpo_proc")
4607 return parseDirectiveFPOProc(DirectiveID.
getLoc());
4608 else if (IDVal ==
".cv_fpo_setframe")
4609 return parseDirectiveFPOSetFrame(DirectiveID.
getLoc());
4610 else if (IDVal ==
".cv_fpo_pushreg")
4611 return parseDirectiveFPOPushReg(DirectiveID.
getLoc());
4612 else if (IDVal ==
".cv_fpo_stackalloc")
4613 return parseDirectiveFPOStackAlloc(DirectiveID.
getLoc());
4614 else if (IDVal ==
".cv_fpo_stackalign")
4615 return parseDirectiveFPOStackAlign(DirectiveID.
getLoc());
4616 else if (IDVal ==
".cv_fpo_endprologue")
4617 return parseDirectiveFPOEndPrologue(DirectiveID.
getLoc());
4618 else if (IDVal ==
".cv_fpo_endproc")
4619 return parseDirectiveFPOEndProc(DirectiveID.
getLoc());
4620 else if (IDVal ==
".seh_pushreg" ||
4622 return parseDirectiveSEHPushReg(DirectiveID.
getLoc());
4623 else if (IDVal ==
".seh_setframe" ||
4625 return parseDirectiveSEHSetFrame(DirectiveID.
getLoc());
4626 else if (IDVal ==
".seh_savereg" ||
4628 return parseDirectiveSEHSaveReg(DirectiveID.
getLoc());
4629 else if (IDVal ==
".seh_savexmm" ||
4631 return parseDirectiveSEHSaveXMM(DirectiveID.
getLoc());
4632 else if (IDVal ==
".seh_pushframe" ||
4634 return parseDirectiveSEHPushFrame(DirectiveID.
getLoc());
4639bool X86AsmParser::parseDirectiveArch() {
4641 getParser().parseStringToEndOfStatement();
4647bool X86AsmParser::parseDirectiveNops(
SMLoc L) {
4648 int64_t NumBytes = 0, Control = 0;
4649 SMLoc NumBytesLoc, ControlLoc;
4651 NumBytesLoc = getTok().getLoc();
4652 if (getParser().checkForValidSection() ||
4653 getParser().parseAbsoluteExpression(NumBytes))
4657 ControlLoc = getTok().getLoc();
4658 if (getParser().parseAbsoluteExpression(Control))
4661 if (getParser().parseEOL())
4664 if (NumBytes <= 0) {
4665 Error(NumBytesLoc,
"'.nops' directive with non-positive size");
4670 Error(ControlLoc,
"'.nops' directive with negative NOP size");
4675 getParser().getStreamer().emitNops(NumBytes, Control, L, STI);
4682bool X86AsmParser::parseDirectiveEven(
SMLoc L) {
4688 getStreamer().initSections(
false, getSTI());
4689 Section = getStreamer().getCurrentSectionOnly();
4692 getStreamer().emitCodeAlignment(
Align(2), &getSTI(), 0);
4694 getStreamer().emitValueToAlignment(
Align(2), 0, 1, 0);
4703 if (IDVal ==
".code16") {
4705 if (!is16BitMode()) {
4706 SwitchMode(X86::Is16Bit);
4707 getParser().getStreamer().emitAssemblerFlag(
MCAF_Code16);
4709 }
else if (IDVal ==
".code16gcc") {
4713 if (!is16BitMode()) {
4714 SwitchMode(X86::Is16Bit);
4715 getParser().getStreamer().emitAssemblerFlag(
MCAF_Code16);
4717 }
else if (IDVal ==
".code32") {
4719 if (!is32BitMode()) {
4720 SwitchMode(X86::Is32Bit);
4721 getParser().getStreamer().emitAssemblerFlag(
MCAF_Code32);
4723 }
else if (IDVal ==
".code64") {
4725 if (!is64BitMode()) {
4726 SwitchMode(X86::Is64Bit);
4727 getParser().getStreamer().emitAssemblerFlag(
MCAF_Code64);
4730 Error(L,
"unknown directive " + IDVal);
4738bool X86AsmParser::parseDirectiveFPOProc(
SMLoc L) {
4743 return Parser.
TokError(
"expected symbol name");
4744 if (Parser.
parseIntToken(ParamsSize,
"expected parameter byte count"))
4747 return Parser.
TokError(
"parameters size out of range");
4750 MCSymbol *ProcSym = getContext().getOrCreateSymbol(ProcName);
4751 return getTargetStreamer().emitFPOProc(ProcSym, ParamsSize, L);
4755bool X86AsmParser::parseDirectiveFPOSetFrame(
SMLoc L) {
4758 if (parseRegister(Reg, DummyLoc, DummyLoc) || parseEOL())
4760 return getTargetStreamer().emitFPOSetFrame(Reg, L);
4764bool X86AsmParser::parseDirectiveFPOPushReg(
SMLoc L) {
4767 if (parseRegister(Reg, DummyLoc, DummyLoc) || parseEOL())
4769 return getTargetStreamer().emitFPOPushReg(Reg, L);
4773bool X86AsmParser::parseDirectiveFPOStackAlloc(
SMLoc L) {
4778 return getTargetStreamer().emitFPOStackAlloc(
Offset, L);
4782bool X86AsmParser::parseDirectiveFPOStackAlign(
SMLoc L) {
4787 return getTargetStreamer().emitFPOStackAlign(
Offset, L);
4791bool X86AsmParser::parseDirectiveFPOEndPrologue(
SMLoc L) {
4795 return getTargetStreamer().emitFPOEndPrologue(L);
4799bool X86AsmParser::parseDirectiveFPOEndProc(
SMLoc L) {
4803 return getTargetStreamer().emitFPOEndProc(L);
4806bool X86AsmParser::parseSEHRegisterNumber(
unsigned RegClassID,
4808 SMLoc startLoc = getLexer().getLoc();
4814 if (parseRegister(RegNo, startLoc, endLoc))
4817 if (!X86MCRegisterClasses[RegClassID].
contains(RegNo)) {
4818 return Error(startLoc,
4819 "register is not supported for use with this directive");
4825 if (getParser().parseAbsoluteExpression(EncodedReg))
4831 for (
MCPhysReg Reg : X86MCRegisterClasses[RegClassID]) {
4832 if (
MRI->getEncodingValue(Reg) == EncodedReg) {
4838 return Error(startLoc,
4839 "incorrect register number for use with this directive");
4846bool X86AsmParser::parseDirectiveSEHPushReg(
SMLoc Loc) {
4848 if (parseSEHRegisterNumber(X86::GR64RegClassID, Reg))
4852 return TokError(
"expected end of directive");
4855 getStreamer().emitWinCFIPushReg(Reg, Loc);
4859bool X86AsmParser::parseDirectiveSEHSetFrame(
SMLoc Loc) {
4862 if (parseSEHRegisterNumber(X86::GR64RegClassID, Reg))
4865 return TokError(
"you must specify a stack pointer offset");
4868 if (getParser().parseAbsoluteExpression(Off))
4872 return TokError(
"expected end of directive");
4875 getStreamer().emitWinCFISetFrame(Reg, Off, Loc);
4879bool X86AsmParser::parseDirectiveSEHSaveReg(
SMLoc Loc) {
4882 if (parseSEHRegisterNumber(X86::GR64RegClassID, Reg))
4885 return TokError(
"you must specify an offset on the stack");
4888 if (getParser().parseAbsoluteExpression(Off))
4892 return TokError(
"expected end of directive");
4895 getStreamer().emitWinCFISaveReg(Reg, Off, Loc);
4899bool X86AsmParser::parseDirectiveSEHSaveXMM(
SMLoc Loc) {
4902 if (parseSEHRegisterNumber(X86::VR128XRegClassID, Reg))
4905 return TokError(
"you must specify an offset on the stack");
4908 if (getParser().parseAbsoluteExpression(Off))
4912 return TokError(
"expected end of directive");
4915 getStreamer().emitWinCFISaveXMM(Reg, Off, Loc);
4919bool X86AsmParser::parseDirectiveSEHPushFrame(
SMLoc Loc) {
4923 SMLoc startLoc = getLexer().getLoc();
4925 if (!getParser().parseIdentifier(CodeID)) {
4926 if (CodeID !=
"code")
4927 return Error(startLoc,
"expected @code");
4933 return TokError(
"expected end of directive");
4936 getStreamer().emitWinCFIPushFrame(Code, Loc);
4946#define GET_MATCHER_IMPLEMENTATION
4947#include "X86GenAsmMatcher.inc"
unsigned const MachineRegisterInfo * MRI
static MCRegister MatchRegisterName(StringRef Name)
static const char * getSubtargetFeatureName(uint64_t Val)
static bool isNot(const MachineRegisterInfo &MRI, const MachineInstr &MI)
Analysis containing CSE Info
#define LLVM_EXTERNAL_VISIBILITY
Returns the sub type a function will return at a given Idx Should correspond to the result type of an ExtractValue instruction executed with just that one unsigned Idx
static GCMetadataPrinterRegistry::Add< ErlangGCPrinter > X("erlang", "erlang-compatible garbage collector")
amode Optimize addressing mode
static ModuleSymbolTable::Symbol getSym(DataRefImpl &Symb)
mir Rename Register Operands
static bool IsVCMP(unsigned Opcode)
static GCMetadataPrinterRegistry::Add< OcamlGCMetadataPrinter > Y("ocaml", "ocaml 3.10-compatible collector")
assert(ImpDefSCC.getReg()==AMDGPU::SCC &&ImpDefSCC.isDef())
This file defines the SmallString class.
This file defines the SmallVector class.
This file implements the StringSwitch template, which mimics a switch() statement whose cases are str...
static SymbolRef::Type getType(const Symbol *Sym)
static bool contains(SmallPtrSetImpl< ConstantExpr * > &Cache, ConstantExpr *Expr, Constant *C)
static cl::opt< bool > LVIInlineAsmHardening("x86-experimental-lvi-inline-asm-hardening", cl::desc("Harden inline assembly code that may be vulnerable to Load Value" " Injection (LVI). This feature is experimental."), cl::Hidden)
static bool checkScale(unsigned Scale, StringRef &ErrMsg)
LLVM_EXTERNAL_VISIBILITY void LLVMInitializeX86AsmParser()
static unsigned getPrefixes(OperandVector &Operands)
static bool CheckBaseRegAndIndexRegAndScale(unsigned BaseReg, unsigned IndexReg, unsigned Scale, bool Is64BitMode, StringRef &ErrMsg)
static unsigned getSize(unsigned Kind)
Class for arbitrary precision integers.
uint64_t getZExtValue() const
Get zero extended value.
Target independent representation for an assembler token.
int64_t getIntVal() const
bool isNot(TokenKind K) const
StringRef getString() const
Get the string for the current token, this includes all characters (for example, the quotes on string...
bool is(TokenKind K) const
TokenKind getKind() const
StringRef getIdentifier() const
Get the identifier string for the current token, which should be an identifier or a string.
This class represents an Operation in the Expression.
Base class for user error types.
Lightweight error class with error context and mandatory checking.
Container class for subtarget features.
constexpr size_t size() const
An instruction for ordering other memory operations.
Generic assembler lexer interface, for use by target specific assembly lexers.
void UnLex(AsmToken const &Token)
bool isNot(AsmToken::TokenKind K) const
Check if the current token has kind K.
MCStreamer & getStreamer()
MCAsmParser & getParser()
Generic assembler parser interface, for use by target specific assembly parsers.
virtual void eatToEndOfStatement()=0
Skip to the end of the current statement, for error recovery.
virtual MCStreamer & getStreamer()=0
Return the output streamer for the assembler.
virtual bool parseExpression(const MCExpr *&Res, SMLoc &EndLoc)=0
Parse an arbitrary expression.
virtual bool parsePrimaryExpr(const MCExpr *&Res, SMLoc &EndLoc, AsmTypeInfo *TypeInfo)=0
Parse a primary expression.
const AsmToken & getTok() const
Get the current AsmToken from the stream.
virtual bool isParsingMasm() const
virtual bool parseIdentifier(StringRef &Res)=0
Parse an identifier or string (as a quoted identifier) and set Res to the identifier contents.
bool parseOptionalToken(AsmToken::TokenKind T)
Attempt to parse and consume token, returning true on success.
bool parseIntToken(int64_t &V, const Twine &ErrMsg)
virtual const AsmToken & Lex()=0
Get the next AsmToken in the stream, possibly handling file inclusion first.
virtual unsigned getAssemblerDialect()
virtual void addAliasForDirective(StringRef Directive, StringRef Alias)=0
virtual bool lookUpType(StringRef Name, AsmTypeInfo &Info) const
bool TokError(const Twine &Msg, SMRange Range=std::nullopt)
Report an error at the current lexer location.
virtual bool parseAbsoluteExpression(int64_t &Res)=0
Parse an expression which must evaluate to an absolute value.
virtual bool lookUpField(StringRef Name, AsmFieldInfo &Info) const
bool parseTokenLoc(SMLoc &Loc)
virtual MCContext & getContext()=0
bool Error(SMLoc L, const Twine &Msg, SMRange Range=std::nullopt)
Return an error at the location L, with the message Msg.
static const MCBinaryExpr * createAdd(const MCExpr *LHS, const MCExpr *RHS, MCContext &Ctx)
static const MCConstantExpr * create(int64_t Value, MCContext &Ctx, bool PrintInHex=false, unsigned SizeInBytes=0)
Base class for the full range of assembler expressions which are needed for parsing.
@ SymbolRef
References to labels and assigned expressions.
Instances of this class represent a single low-level machine instruction.
unsigned getNumOperands() const
unsigned getFlags() const
unsigned getOpcode() const
void setFlags(unsigned F)
void addOperand(const MCOperand Op)
void setOpcode(unsigned Op)
const MCOperand & getOperand(unsigned i) const
Describe properties that are true of each instruction in the target description file.
bool mayLoad() const
Return true if this instruction could possibly read memory.
bool isCall() const
Return true if the instruction is a call.
bool isTerminator() const
Returns true if this instruction part of the terminator for a basic block.
Interface to description of machine instruction set.
Instances of this class represent operands of the MCInst class.
static MCOperand createImm(int64_t Val)
unsigned getReg() const
Returns the register number.
MCRegisterInfo base class - We assume that the target defines a static array of MCRegisterDesc object...
Wrapper class representing physical registers. Should be passed by value.
Instances of this class represent a uniqued identifier for a section in the current translation unit.
Streaming machine code generation interface.
virtual void emitInstruction(const MCInst &Inst, const MCSubtargetInfo &STI)
Emit the given Instruction into the current section.
MCTargetStreamer * getTargetStreamer()
Generic base class for all target subtargets.
bool hasFeature(unsigned Feature) const
const FeatureBitset & getFeatureBits() const
FeatureBitset ToggleFeature(uint64_t FB)
Toggle a feature and return the re-computed feature bits.
static const MCSymbolRefExpr * create(const MCSymbol *Symbol, MCContext &Ctx)
MCSymbol - Instances of this class represent a symbol name in the MC file, and MCSymbols are created ...
MCTargetAsmParser - Generic interface to target specific assembly parsers.
MCSubtargetInfo & copySTI()
Create a copy of STI and return a non-const reference to it.
@ FIRST_TARGET_MATCH_RESULT_TY
virtual bool parseRegister(MCRegister &Reg, SMLoc &StartLoc, SMLoc &EndLoc)=0
virtual bool ParseDirective(AsmToken DirectiveID)
ParseDirective - Parse a target specific assembler directive This method is deprecated,...
virtual bool parsePrimaryExpr(const MCExpr *&Res, SMLoc &EndLoc)
virtual ParseStatus tryParseRegister(MCRegister &Reg, SMLoc &StartLoc, SMLoc &EndLoc)=0
tryParseRegister - parse one register if possible
void setAvailableFeatures(const FeatureBitset &Value)
const MCSubtargetInfo & getSTI() const
virtual bool OmitRegisterFromClobberLists(unsigned RegNo)
Allows targets to let registers opt out of clobber lists.
virtual bool ParseInstruction(ParseInstructionInfo &Info, StringRef Name, SMLoc NameLoc, OperandVector &Operands)=0
ParseInstruction - Parse one assembly instruction.
virtual unsigned checkTargetMatchPredicate(MCInst &Inst)
checkTargetMatchPredicate - Validate the instruction match against any complex target predicates not ...
virtual bool MatchAndEmitInstruction(SMLoc IDLoc, unsigned &Opcode, OperandVector &Operands, MCStreamer &Out, uint64_t &ErrorInfo, bool MatchingInlineAsm)=0
MatchAndEmitInstruction - Recognize a series of operands of a parsed instruction as an actual MCInst ...
Target specific streamer interface.
Ternary parse status returned by various parse* methods.
static constexpr StatusTy Failure
static constexpr StatusTy Success
static constexpr StatusTy NoMatch
Represents a location in source code.
static SMLoc getFromPointer(const char *Ptr)
constexpr const char * getPointer() const
constexpr bool isValid() const
Represents a range in source code.
SmallString - A SmallString is just a SmallVector with methods and accessors that make it work better...
This class consists of common code factored out of the SmallVector class to reduce code duplication b...
void push_back(const T &Elt)
This is a 'vector' (really, a variable-sized array), optimized for the case when the array is small.
StringRef - Represent a constant reference to a string, i.e.
std::pair< StringRef, StringRef > split(char Separator) const
Split into two substrings around the first occurrence of a separator character.
bool getAsInteger(unsigned Radix, T &Result) const
Parse the current string as an integer of the specified radix.
constexpr StringRef substr(size_t Start, size_t N=npos) const
Return a reference to the substring from [Start, Start + N).
bool starts_with(StringRef Prefix) const
Check if this string starts with the given Prefix.
constexpr bool empty() const
empty - Check if the string is empty.
char back() const
back - Get the last character in the string.
StringRef slice(size_t Start, size_t End) const
Return a reference to the substring from [Start, End).
constexpr size_t size() const
size - Get the string size.
constexpr const char * data() const
data - Get a pointer to the start of the string (which may not be null terminated).
bool consume_front(StringRef Prefix)
Returns true if this StringRef has the given prefix and removes that prefix.
bool equals(StringRef RHS) const
equals - Check for string equality, this is more efficient than compare() when the relative ordering ...
std::string lower() const
bool ends_with(StringRef Suffix) const
Check if this string ends with the given Suffix.
static constexpr size_t npos
StringRef drop_back(size_t N=1) const
Return a StringRef equal to 'this' but with the last N elements dropped.
bool equals_insensitive(StringRef RHS) const
Check for string equality, ignoring case.
A switch()-like statement whose cases are string literals.
StringSwitch & Case(StringLiteral S, T Value)
StringSwitch & Cases(StringLiteral S0, StringLiteral S1, T Value)
Twine - A lightweight data structure for efficiently representing the concatenation of temporary valu...
The instances of the Type class are immutable: once they are created, they are never changed.
static const char * getRegisterName(MCRegister Reg)
static const X86MCExpr * create(int64_t RegNo, MCContext &Ctx)
X86 target streamer implementing x86-only assembly directives.
A raw_ostream that writes to an SmallVector or SmallString.
#define llvm_unreachable(msg)
Marks that the current location is not supposed to be reachable.
const CustomOperand< const MCSubtargetInfo & > Msg[]
constexpr std::underlying_type_t< E > Mask()
Get a bitmask with 1s in all places up to the high-order bit of E's largest value.
unsigned ID
LLVM IR allows to use arbitrary numbers as calling convention identifiers.
std::variant< std::monostate, Loc::Single, Loc::Multi, Loc::MMI, Loc::EntryValue > Variant
Alias for the std::variant specialization base class of DbgVariable.
@ CE
Windows NT (Windows on ARM)
@ X86
Windows x64, Windows Itanium (IA-64)
Reg
All possible values of the reg field in the ModR/M byte.
bool isX86_64ExtendedReg(unsigned RegNo)
bool isX86_64NonExtLowByteReg(unsigned reg)
bool canUseApxExtendedReg(const MCInstrDesc &Desc)
bool isApxExtendedReg(unsigned RegNo)
@ EVEX
EVEX - Specifies that this instruction use EVEX form which provides syntax support up to 32 512-bit r...
@ VEX
VEX - encoding using 0xC4/0xC5.
@ ExplicitVEXPrefix
For instructions that use VEX encoding only when {vex}, {vex2} or {vex3} is present.
bool optimizeShiftRotateWithImmediateOne(MCInst &MI)
bool optimizeInstFromVEX3ToVEX2(MCInst &MI, const MCInstrDesc &Desc)
StringRef toStringRef(const std::optional< DWARFFormValue > &V, StringRef Default={})
Take an optional DWARFFormValue and try to extract a string value from it.
NodeAddr< CodeNode * > Code
This is an optimization pass for GlobalISel generic memory operations.
auto size(R &&Range, std::enable_if_t< std::is_base_of< std::random_access_iterator_tag, typename std::iterator_traits< decltype(Range.begin())>::iterator_category >::value, void > *=nullptr)
Get the size of a range.
bool isUIntN(unsigned N, uint64_t x)
Checks if an unsigned integer fits into the given (dynamic) bit width.
MCRegister getX86SubSuperRegister(MCRegister Reg, unsigned Size, bool High=false)
Target & getTheX86_32Target()
void report_fatal_error(Error Err, bool gen_crash_diag=true)
Report a serious error, calling any installed error handler.
@ MCAF_Code64
.code64 (X86)
@ MCAF_Code16
.code16 (X86) / .code 16 (ARM)
@ MCAF_Code32
.code32 (X86) / .code 32 (ARM)
bool isIntN(unsigned N, int64_t x)
Checks if an signed integer fits into the given (dynamic) bit width.
auto count(R &&Range, const E &Element)
Wrapper function around std::count to count the number of times an element Element occurs in the give...
Target & getTheX86_64Target()
void swap(llvm::BitVector &LHS, llvm::BitVector &RHS)
Implement std::swap in terms of BitVector swap.
This struct is a compact representation of a valid (non-zero power of two) alignment.
bool isKind(IdKind kind) const
SmallVectorImpl< AsmRewrite > * AsmRewrites
RegisterMCAsmParser - Helper template for registering a target specific assembly parser,...
X86Operand - Instances of this class represent a parsed X86 machine instruction.
SMLoc getStartLoc() const override
getStartLoc - Get the location of the first token of this operand.
bool isImm() const override
isImm - Is this an immediate operand?
static std::unique_ptr< X86Operand > CreateImm(const MCExpr *Val, SMLoc StartLoc, SMLoc EndLoc, StringRef SymName=StringRef(), void *OpDecl=nullptr, bool GlobalRef=true)
static std::unique_ptr< X86Operand > CreatePrefix(unsigned Prefixes, SMLoc StartLoc, SMLoc EndLoc)
static std::unique_ptr< X86Operand > CreateDXReg(SMLoc StartLoc, SMLoc EndLoc)
SMRange getLocRange() const
getLocRange - Get the range between the first and last token of this operand.
SMLoc getEndLoc() const override
getEndLoc - Get the location of the last token of this operand.
bool isReg() const override
isReg - Is this a register operand?
bool isMem() const override
isMem - Is this a memory operand?
static std::unique_ptr< X86Operand > CreateMem(unsigned ModeSize, const MCExpr *Disp, SMLoc StartLoc, SMLoc EndLoc, unsigned Size=0, StringRef SymName=StringRef(), void *OpDecl=nullptr, unsigned FrontendSize=0, bool UseUpRegs=false, bool MaybeDirectBranchDest=true)
Create an absolute memory operand.
static std::unique_ptr< X86Operand > CreateToken(StringRef Str, SMLoc Loc)
bool isMemUnsized() const
const MCExpr * getImm() const
unsigned getMemFrontendSize() const
MCRegister getReg() const override
static std::unique_ptr< X86Operand > CreateReg(unsigned RegNo, SMLoc StartLoc, SMLoc EndLoc, bool AddressOf=false, SMLoc OffsetOfLoc=SMLoc(), StringRef SymName=StringRef(), void *OpDecl=nullptr)