LLVM 24.0.0git
X86AsmParser.cpp
Go to the documentation of this file.
1//===-- X86AsmParser.cpp - Parse X86 assembly to MCInst instructions ------===//
2//
3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4// See https://llvm.org/LICENSE.txt for license information.
5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6//
7//===----------------------------------------------------------------------===//
8
17#include "X86Operand.h"
18#include "X86RegisterInfo.h"
19#include "llvm-c/Visibility.h"
20#include "llvm/ADT/STLExtras.h"
23#include "llvm/ADT/StringRef.h"
25#include "llvm/ADT/Twine.h"
26#include "llvm/MC/MCContext.h"
27#include "llvm/MC/MCExpr.h"
28#include "llvm/MC/MCInst.h"
29#include "llvm/MC/MCInstrInfo.h"
34#include "llvm/MC/MCRegister.h"
36#include "llvm/MC/MCSection.h"
37#include "llvm/MC/MCStreamer.h"
39#include "llvm/MC/MCSymbol.h"
45#include <algorithm>
46#include <cstdint>
47#include <memory>
48
49using namespace llvm;
50
52 "x86-experimental-lvi-inline-asm-hardening",
53 cl::desc("Harden inline assembly code that may be vulnerable to Load Value"
54 " Injection (LVI). This feature is experimental."), cl::Hidden);
55
56static bool checkScale(unsigned Scale, StringRef &ErrMsg) {
57 if (Scale != 1 && Scale != 2 && Scale != 4 && Scale != 8) {
58 ErrMsg = "scale factor in address must be 1, 2, 4 or 8";
59 return true;
60 }
61 return false;
62}
63
64namespace {
65
66// Including the generated SSE2AVX compression tables.
67#define GET_X86_SSE2AVX_TABLE
68#include "X86GenInstrMapping.inc"
69
70static const char OpPrecedence[] = {
71 0, // IC_OR
72 1, // IC_XOR
73 2, // IC_AND
74 4, // IC_LSHIFT
75 4, // IC_RSHIFT
76 5, // IC_PLUS
77 5, // IC_MINUS
78 6, // IC_MULTIPLY
79 6, // IC_DIVIDE
80 6, // IC_MOD
81 7, // IC_NOT
82 8, // IC_NEG
83 9, // IC_RPAREN
84 10, // IC_LPAREN
85 0, // IC_IMM
86 0, // IC_REGISTER
87 3, // IC_EQ
88 3, // IC_NE
89 3, // IC_LT
90 3, // IC_LE
91 3, // IC_GT
92 3 // IC_GE
93};
94
95class X86AsmParser : public MCTargetAsmParser {
96 ParseInstructionInfo *InstInfo;
97 bool Code16GCC;
98 unsigned ForcedDataPrefix = 0;
99
100 enum OpcodePrefix {
101 OpcodePrefix_Default,
102 OpcodePrefix_REX,
103 OpcodePrefix_REX2,
104 OpcodePrefix_VEX,
105 OpcodePrefix_VEX2,
106 OpcodePrefix_VEX3,
107 OpcodePrefix_EVEX,
108 };
109
110 OpcodePrefix ForcedOpcodePrefix = OpcodePrefix_Default;
111
112 enum DispEncoding {
113 DispEncoding_Default,
114 DispEncoding_Disp8,
115 DispEncoding_Disp32,
116 };
117
118 DispEncoding ForcedDispEncoding = DispEncoding_Default;
119
120 // Does this instruction use apx extended register?
121 bool UseApxExtendedReg = false;
122 // Is this instruction explicitly required not to update flags?
123 bool ForcedNoFlag = false;
124
125private:
126 SMLoc consumeToken() {
127 MCAsmParser &Parser = getParser();
128 SMLoc Result = Parser.getTok().getLoc();
129 Parser.Lex();
130 return Result;
131 }
132
133 bool tokenIsStartOfStatement(AsmToken::TokenKind Token) override {
134 return Token == AsmToken::LCurly;
135 }
136
137 X86TargetStreamer &getTargetStreamer() {
138 assert(getParser().getStreamer().getTargetStreamer() &&
139 "do not have a target streamer");
140 MCTargetStreamer &TS = *getParser().getStreamer().getTargetStreamer();
141 return static_cast<X86TargetStreamer &>(TS);
142 }
143
144 unsigned MatchInstruction(const OperandVector &Operands, MCInst &Inst,
145 uint64_t &ErrorInfo, FeatureBitset &MissingFeatures,
146 bool matchingInlineAsm, unsigned VariantID = 0) {
147 // In Code16GCC mode, match as 32-bit.
148 if (Code16GCC)
149 SwitchMode(X86::Is32Bit);
150 unsigned rv = MatchInstructionImpl(Operands, Inst, ErrorInfo,
151 MissingFeatures, matchingInlineAsm,
152 VariantID);
153 if (Code16GCC)
154 SwitchMode(X86::Is16Bit);
155 return rv;
156 }
157
158 enum InfixCalculatorTok {
159 IC_OR = 0,
160 IC_XOR,
161 IC_AND,
162 IC_LSHIFT,
163 IC_RSHIFT,
164 IC_PLUS,
165 IC_MINUS,
166 IC_MULTIPLY,
167 IC_DIVIDE,
168 IC_MOD,
169 IC_NOT,
170 IC_NEG,
171 IC_RPAREN,
172 IC_LPAREN,
173 IC_IMM,
174 IC_REGISTER,
175 IC_EQ,
176 IC_NE,
177 IC_LT,
178 IC_LE,
179 IC_GT,
180 IC_GE
181 };
182
183 enum IntelOperatorKind {
184 IOK_INVALID = 0,
185 IOK_LENGTH,
186 IOK_SIZE,
187 IOK_TYPE,
188 };
189
190 enum MasmOperatorKind {
191 MOK_INVALID = 0,
192 MOK_LENGTHOF,
193 MOK_SIZEOF,
194 MOK_TYPE,
195 };
196
197 class InfixCalculator {
198 typedef std::pair< InfixCalculatorTok, int64_t > ICToken;
199 SmallVector<InfixCalculatorTok, 4> InfixOperatorStack;
200 SmallVector<ICToken, 4> PostfixStack;
201
202 bool isUnaryOperator(InfixCalculatorTok Op) const {
203 return Op == IC_NEG || Op == IC_NOT;
204 }
205
206 public:
207 int64_t popOperand() {
208 assert (!PostfixStack.empty() && "Poped an empty stack!");
209 ICToken Op = PostfixStack.pop_back_val();
210 if (!(Op.first == IC_IMM || Op.first == IC_REGISTER))
211 return -1; // The invalid Scale value will be caught later by checkScale
212 return Op.second;
213 }
214 void pushOperand(InfixCalculatorTok Op, int64_t Val = 0) {
215 assert ((Op == IC_IMM || Op == IC_REGISTER) &&
216 "Unexpected operand!");
217 PostfixStack.push_back(std::make_pair(Op, Val));
218 }
219
220 void popOperator() { InfixOperatorStack.pop_back(); }
221 void pushOperator(InfixCalculatorTok Op) {
222 // Push the new operator if the stack is empty.
223 if (InfixOperatorStack.empty()) {
224 InfixOperatorStack.push_back(Op);
225 return;
226 }
227
228 // Push the new operator if it has a higher precedence than the operator
229 // on the top of the stack or the operator on the top of the stack is a
230 // left parentheses.
231 unsigned Idx = InfixOperatorStack.size() - 1;
232 InfixCalculatorTok StackOp = InfixOperatorStack[Idx];
233 if (OpPrecedence[Op] > OpPrecedence[StackOp] || StackOp == IC_LPAREN) {
234 InfixOperatorStack.push_back(Op);
235 return;
236 }
237
238 // The operator on the top of the stack has higher precedence than the
239 // new operator.
240 unsigned ParenCount = 0;
241 while (true) {
242 // Nothing to process.
243 if (InfixOperatorStack.empty())
244 break;
245
246 Idx = InfixOperatorStack.size() - 1;
247 StackOp = InfixOperatorStack[Idx];
248 if (!(OpPrecedence[StackOp] >= OpPrecedence[Op] || ParenCount))
249 break;
250
251 // If we have an even parentheses count and we see a left parentheses,
252 // then stop processing.
253 if (!ParenCount && StackOp == IC_LPAREN)
254 break;
255
256 if (StackOp == IC_RPAREN) {
257 ++ParenCount;
258 InfixOperatorStack.pop_back();
259 } else if (StackOp == IC_LPAREN) {
260 --ParenCount;
261 InfixOperatorStack.pop_back();
262 } else {
263 InfixOperatorStack.pop_back();
264 PostfixStack.push_back(std::make_pair(StackOp, 0));
265 }
266 }
267 // Push the new operator.
268 InfixOperatorStack.push_back(Op);
269 }
270
271 int64_t execute() {
272 // Push any remaining operators onto the postfix stack.
273 while (!InfixOperatorStack.empty()) {
274 InfixCalculatorTok StackOp = InfixOperatorStack.pop_back_val();
275 if (StackOp != IC_LPAREN && StackOp != IC_RPAREN)
276 PostfixStack.push_back(std::make_pair(StackOp, 0));
277 }
278
279 if (PostfixStack.empty())
280 return 0;
281
282 SmallVector<ICToken, 16> OperandStack;
283 for (const ICToken &Op : PostfixStack) {
284 if (Op.first == IC_IMM || Op.first == IC_REGISTER) {
285 OperandStack.push_back(Op);
286 } else if (isUnaryOperator(Op.first)) {
287 assert (OperandStack.size() > 0 && "Too few operands.");
288 ICToken Operand = OperandStack.pop_back_val();
289 assert (Operand.first == IC_IMM &&
290 "Unary operation with a register!");
291 switch (Op.first) {
292 default:
293 report_fatal_error("Unexpected operator!");
294 break;
295 case IC_NEG:
296 OperandStack.push_back(std::make_pair(IC_IMM, -Operand.second));
297 break;
298 case IC_NOT:
299 OperandStack.push_back(std::make_pair(IC_IMM, ~Operand.second));
300 break;
301 }
302 } else {
303 assert (OperandStack.size() > 1 && "Too few operands.");
304 int64_t Val;
305 ICToken Op2 = OperandStack.pop_back_val();
306 ICToken Op1 = OperandStack.pop_back_val();
307 switch (Op.first) {
308 default:
309 report_fatal_error("Unexpected operator!");
310 break;
311 case IC_PLUS:
312 Val = Op1.second + Op2.second;
313 OperandStack.push_back(std::make_pair(IC_IMM, Val));
314 break;
315 case IC_MINUS:
316 Val = Op1.second - Op2.second;
317 OperandStack.push_back(std::make_pair(IC_IMM, Val));
318 break;
319 case IC_MULTIPLY:
320 assert (Op1.first == IC_IMM && Op2.first == IC_IMM &&
321 "Multiply operation with an immediate and a register!");
322 Val = Op1.second * Op2.second;
323 OperandStack.push_back(std::make_pair(IC_IMM, Val));
324 break;
325 case IC_DIVIDE:
326 assert (Op1.first == IC_IMM && Op2.first == IC_IMM &&
327 "Divide operation with an immediate and a register!");
328 assert (Op2.second != 0 && "Division by zero!");
329 Val = Op1.second / Op2.second;
330 OperandStack.push_back(std::make_pair(IC_IMM, Val));
331 break;
332 case IC_MOD:
333 assert (Op1.first == IC_IMM && Op2.first == IC_IMM &&
334 "Modulo operation with an immediate and a register!");
335 Val = Op1.second % Op2.second;
336 OperandStack.push_back(std::make_pair(IC_IMM, Val));
337 break;
338 case IC_OR:
339 assert (Op1.first == IC_IMM && Op2.first == IC_IMM &&
340 "Or operation with an immediate and a register!");
341 Val = Op1.second | Op2.second;
342 OperandStack.push_back(std::make_pair(IC_IMM, Val));
343 break;
344 case IC_XOR:
345 assert(Op1.first == IC_IMM && Op2.first == IC_IMM &&
346 "Xor operation with an immediate and a register!");
347 Val = Op1.second ^ Op2.second;
348 OperandStack.push_back(std::make_pair(IC_IMM, Val));
349 break;
350 case IC_AND:
351 assert (Op1.first == IC_IMM && Op2.first == IC_IMM &&
352 "And operation with an immediate and a register!");
353 Val = Op1.second & Op2.second;
354 OperandStack.push_back(std::make_pair(IC_IMM, Val));
355 break;
356 case IC_LSHIFT:
357 assert (Op1.first == IC_IMM && Op2.first == IC_IMM &&
358 "Left shift operation with an immediate and a register!");
359 Val = Op1.second << Op2.second;
360 OperandStack.push_back(std::make_pair(IC_IMM, Val));
361 break;
362 case IC_RSHIFT:
363 assert (Op1.first == IC_IMM && Op2.first == IC_IMM &&
364 "Right shift operation with an immediate and a register!");
365 Val = Op1.second >> Op2.second;
366 OperandStack.push_back(std::make_pair(IC_IMM, Val));
367 break;
368 case IC_EQ:
369 assert(Op1.first == IC_IMM && Op2.first == IC_IMM &&
370 "Equals operation with an immediate and a register!");
371 Val = (Op1.second == Op2.second) ? -1 : 0;
372 OperandStack.push_back(std::make_pair(IC_IMM, Val));
373 break;
374 case IC_NE:
375 assert(Op1.first == IC_IMM && Op2.first == IC_IMM &&
376 "Not-equals operation with an immediate and a register!");
377 Val = (Op1.second != Op2.second) ? -1 : 0;
378 OperandStack.push_back(std::make_pair(IC_IMM, Val));
379 break;
380 case IC_LT:
381 assert(Op1.first == IC_IMM && Op2.first == IC_IMM &&
382 "Less-than operation with an immediate and a register!");
383 Val = (Op1.second < Op2.second) ? -1 : 0;
384 OperandStack.push_back(std::make_pair(IC_IMM, Val));
385 break;
386 case IC_LE:
387 assert(Op1.first == IC_IMM && Op2.first == IC_IMM &&
388 "Less-than-or-equal operation with an immediate and a "
389 "register!");
390 Val = (Op1.second <= Op2.second) ? -1 : 0;
391 OperandStack.push_back(std::make_pair(IC_IMM, Val));
392 break;
393 case IC_GT:
394 assert(Op1.first == IC_IMM && Op2.first == IC_IMM &&
395 "Greater-than operation with an immediate and a register!");
396 Val = (Op1.second > Op2.second) ? -1 : 0;
397 OperandStack.push_back(std::make_pair(IC_IMM, Val));
398 break;
399 case IC_GE:
400 assert(Op1.first == IC_IMM && Op2.first == IC_IMM &&
401 "Greater-than-or-equal operation with an immediate and a "
402 "register!");
403 Val = (Op1.second >= Op2.second) ? -1 : 0;
404 OperandStack.push_back(std::make_pair(IC_IMM, Val));
405 break;
406 }
407 }
408 }
409 assert (OperandStack.size() == 1 && "Expected a single result.");
410 return OperandStack.pop_back_val().second;
411 }
412 };
413
414 enum IntelExprState {
415 IES_INIT,
416 IES_OR,
417 IES_XOR,
418 IES_AND,
419 IES_EQ,
420 IES_NE,
421 IES_LT,
422 IES_LE,
423 IES_GT,
424 IES_GE,
425 IES_LSHIFT,
426 IES_RSHIFT,
427 IES_PLUS,
428 IES_MINUS,
429 IES_OFFSET,
430 IES_CAST,
431 IES_NOT,
432 IES_MULTIPLY,
433 IES_DIVIDE,
434 IES_MOD,
435 IES_LBRAC,
436 IES_RBRAC,
437 IES_LPAREN,
438 IES_RPAREN,
439 IES_REGISTER,
440 IES_INTEGER,
441 IES_ERROR
442 };
443
444 class IntelExprStateMachine {
445 IntelExprState State = IES_INIT, PrevState = IES_ERROR;
446 MCRegister BaseReg, IndexReg, TmpReg;
447 unsigned Scale = 0;
448 int64_t Imm = 0;
449 const MCExpr *Sym = nullptr;
450 StringRef SymName;
451 InfixCalculator IC;
452 InlineAsmIdentifierInfo Info;
453 short BracCount = 0;
454 bool MemExpr = false;
455 bool BracketUsed = false;
456 bool NegativeAdditiveTerm = false;
457 SMLoc NegativeAdditiveTermLoc;
458 bool OffsetOperator = false;
459 bool AttachToOperandIdx = false;
460 bool IsPIC = false;
461 SMLoc OffsetOperatorLoc;
462 AsmTypeInfo CurType;
463
464 bool setSymRef(const MCExpr *Val, StringRef ID, StringRef &ErrMsg) {
465 if (Sym) {
466 ErrMsg = "cannot use more than one symbol in memory operand";
467 return true;
468 }
469 Sym = Val;
470 SymName = ID;
471 return false;
472 }
473
474 public:
475 IntelExprStateMachine() = default;
476
477 void addImm(int64_t imm) { Imm += imm; }
478 short getBracCount() const { return BracCount; }
479 bool isMemExpr() const { return MemExpr; }
480 bool isBracketUsed() const { return BracketUsed; }
481 bool isOffsetOperator() const { return OffsetOperator; }
482 SMLoc getOffsetLoc() const { return OffsetOperatorLoc; }
483 MCRegister getBaseReg() const { return BaseReg; }
484 MCRegister getIndexReg() const { return IndexReg; }
485 unsigned getScale() const { return Scale; }
486 const MCExpr *getSym() const { return Sym; }
487 StringRef getSymName() const { return SymName; }
488 StringRef getType() const { return CurType.Name; }
489 unsigned getSize() const { return CurType.Size; }
490 unsigned getElementSize() const { return CurType.ElementSize; }
491 unsigned getLength() const { return CurType.Length; }
492 int64_t getImm() { return Imm + IC.execute(); }
493 bool isValidEndState() const {
494 return State == IES_RBRAC || State == IES_RPAREN ||
495 State == IES_INTEGER || State == IES_REGISTER ||
496 State == IES_OFFSET;
497 }
498
499 // Is the intel expression appended after an operand index.
500 // [OperandIdx][Intel Expression]
501 // This is neccessary for checking if it is an independent
502 // intel expression at back end when parse inline asm.
503 void setAppendAfterOperand() { AttachToOperandIdx = true; }
504
505 bool isPIC() const { return IsPIC; }
506 void setPIC() { IsPIC = true; }
507
508 bool hadError() const { return State == IES_ERROR; }
509 SMLoc getErrorLoc(SMLoc DefaultLoc) const {
510 return NegativeAdditiveTerm ? NegativeAdditiveTermLoc : DefaultLoc;
511 }
512 const InlineAsmIdentifierInfo &getIdentifierInfo() const { return Info; }
513
514 bool regsUseUpError(StringRef &ErrMsg) {
515 // This case mostly happen in inline asm, e.g. Arr[BaseReg + IndexReg]
516 // can not intruduce additional register in inline asm in PIC model.
517 if (IsPIC && AttachToOperandIdx)
518 ErrMsg = "Don't use 2 or more regs for mem offset in PIC model!";
519 else
520 ErrMsg = "BaseReg/IndexReg already set!";
521 return true;
522 }
523
524 void onOr() {
525 IntelExprState CurrState = State;
526 switch (State) {
527 default:
528 State = IES_ERROR;
529 break;
530 case IES_INTEGER:
531 case IES_RPAREN:
532 case IES_REGISTER:
533 State = IES_OR;
534 IC.pushOperator(IC_OR);
535 break;
536 }
537 PrevState = CurrState;
538 }
539 void onXor() {
540 IntelExprState CurrState = State;
541 switch (State) {
542 default:
543 State = IES_ERROR;
544 break;
545 case IES_INTEGER:
546 case IES_RPAREN:
547 case IES_REGISTER:
548 State = IES_XOR;
549 IC.pushOperator(IC_XOR);
550 break;
551 }
552 PrevState = CurrState;
553 }
554 void onAnd() {
555 IntelExprState CurrState = State;
556 switch (State) {
557 default:
558 State = IES_ERROR;
559 break;
560 case IES_INTEGER:
561 case IES_RPAREN:
562 case IES_REGISTER:
563 State = IES_AND;
564 IC.pushOperator(IC_AND);
565 break;
566 }
567 PrevState = CurrState;
568 }
569 void onEq() {
570 IntelExprState CurrState = State;
571 switch (State) {
572 default:
573 State = IES_ERROR;
574 break;
575 case IES_INTEGER:
576 case IES_RPAREN:
577 case IES_REGISTER:
578 State = IES_EQ;
579 IC.pushOperator(IC_EQ);
580 break;
581 }
582 PrevState = CurrState;
583 }
584 void onNE() {
585 IntelExprState CurrState = State;
586 switch (State) {
587 default:
588 State = IES_ERROR;
589 break;
590 case IES_INTEGER:
591 case IES_RPAREN:
592 case IES_REGISTER:
593 State = IES_NE;
594 IC.pushOperator(IC_NE);
595 break;
596 }
597 PrevState = CurrState;
598 }
599 void onLT() {
600 IntelExprState CurrState = State;
601 switch (State) {
602 default:
603 State = IES_ERROR;
604 break;
605 case IES_INTEGER:
606 case IES_RPAREN:
607 case IES_REGISTER:
608 State = IES_LT;
609 IC.pushOperator(IC_LT);
610 break;
611 }
612 PrevState = CurrState;
613 }
614 void onLE() {
615 IntelExprState CurrState = State;
616 switch (State) {
617 default:
618 State = IES_ERROR;
619 break;
620 case IES_INTEGER:
621 case IES_RPAREN:
622 case IES_REGISTER:
623 State = IES_LE;
624 IC.pushOperator(IC_LE);
625 break;
626 }
627 PrevState = CurrState;
628 }
629 void onGT() {
630 IntelExprState CurrState = State;
631 switch (State) {
632 default:
633 State = IES_ERROR;
634 break;
635 case IES_INTEGER:
636 case IES_RPAREN:
637 case IES_REGISTER:
638 State = IES_GT;
639 IC.pushOperator(IC_GT);
640 break;
641 }
642 PrevState = CurrState;
643 }
644 void onGE() {
645 IntelExprState CurrState = State;
646 switch (State) {
647 default:
648 State = IES_ERROR;
649 break;
650 case IES_INTEGER:
651 case IES_RPAREN:
652 case IES_REGISTER:
653 State = IES_GE;
654 IC.pushOperator(IC_GE);
655 break;
656 }
657 PrevState = CurrState;
658 }
659 void onLShift() {
660 IntelExprState CurrState = State;
661 switch (State) {
662 default:
663 State = IES_ERROR;
664 break;
665 case IES_INTEGER:
666 case IES_RPAREN:
667 case IES_REGISTER:
668 State = IES_LSHIFT;
669 IC.pushOperator(IC_LSHIFT);
670 break;
671 }
672 PrevState = CurrState;
673 }
674 void onRShift() {
675 IntelExprState CurrState = State;
676 switch (State) {
677 default:
678 State = IES_ERROR;
679 break;
680 case IES_INTEGER:
681 case IES_RPAREN:
682 case IES_REGISTER:
683 State = IES_RSHIFT;
684 IC.pushOperator(IC_RSHIFT);
685 break;
686 }
687 PrevState = CurrState;
688 }
689 bool onPlus(StringRef &ErrMsg) {
690 IntelExprState CurrState = State;
691 switch (State) {
692 default:
693 State = IES_ERROR;
694 break;
695 case IES_INTEGER:
696 case IES_RPAREN:
697 case IES_REGISTER:
698 case IES_OFFSET:
699 State = IES_PLUS;
700 IC.pushOperator(IC_PLUS);
701 NegativeAdditiveTerm = false;
702 NegativeAdditiveTermLoc = SMLoc();
703 if (CurrState == IES_REGISTER && PrevState != IES_MULTIPLY) {
704 // If we already have a BaseReg, then assume this is the IndexReg with
705 // no explicit scale.
706 if (!BaseReg) {
707 BaseReg = TmpReg;
708 } else {
709 if (IndexReg)
710 return regsUseUpError(ErrMsg);
711 IndexReg = TmpReg;
712 Scale = 0;
713 }
714 }
715 break;
716 }
717 PrevState = CurrState;
718 return false;
719 }
720 bool onMinus(SMLoc MinusLoc, StringRef &ErrMsg) {
721 IntelExprState CurrState = State;
722 switch (State) {
723 default:
724 State = IES_ERROR;
725 break;
726 case IES_OR:
727 case IES_XOR:
728 case IES_AND:
729 case IES_EQ:
730 case IES_NE:
731 case IES_LT:
732 case IES_LE:
733 case IES_GT:
734 case IES_GE:
735 case IES_LSHIFT:
736 case IES_RSHIFT:
737 case IES_PLUS:
738 case IES_NOT:
739 case IES_MULTIPLY:
740 case IES_DIVIDE:
741 case IES_MOD:
742 case IES_LPAREN:
743 case IES_RPAREN:
744 case IES_LBRAC:
745 case IES_RBRAC:
746 case IES_INTEGER:
747 case IES_REGISTER:
748 case IES_INIT:
749 case IES_OFFSET:
750 State = IES_MINUS;
751 // push minus operator if it is not a negate operator
752 if (CurrState == IES_REGISTER || CurrState == IES_RPAREN ||
753 CurrState == IES_INTEGER || CurrState == IES_RBRAC ||
754 CurrState == IES_OFFSET) {
755 IC.pushOperator(IC_MINUS);
756 NegativeAdditiveTerm = true;
757 NegativeAdditiveTermLoc = MinusLoc;
758 } else if (PrevState == IES_REGISTER && CurrState == IES_MULTIPLY) {
759 // We have negate operator for Scale: it's illegal
760 ErrMsg = "Scale can't be negative";
761 return true;
762 } else
763 IC.pushOperator(IC_NEG);
764 if (CurrState == IES_REGISTER && PrevState != IES_MULTIPLY) {
765 // If we already have a BaseReg, then assume this is the IndexReg with
766 // no explicit scale.
767 if (!BaseReg) {
768 BaseReg = TmpReg;
769 } else {
770 if (IndexReg)
771 return regsUseUpError(ErrMsg);
772 IndexReg = TmpReg;
773 Scale = 0;
774 }
775 }
776 break;
777 }
778 PrevState = CurrState;
779 return false;
780 }
781 void onNot() {
782 IntelExprState CurrState = State;
783 switch (State) {
784 default:
785 State = IES_ERROR;
786 break;
787 case IES_OR:
788 case IES_XOR:
789 case IES_AND:
790 case IES_EQ:
791 case IES_NE:
792 case IES_LT:
793 case IES_LE:
794 case IES_GT:
795 case IES_GE:
796 case IES_LSHIFT:
797 case IES_RSHIFT:
798 case IES_PLUS:
799 case IES_MINUS:
800 case IES_NOT:
801 case IES_MULTIPLY:
802 case IES_DIVIDE:
803 case IES_MOD:
804 case IES_LPAREN:
805 case IES_LBRAC:
806 case IES_INIT:
807 State = IES_NOT;
808 IC.pushOperator(IC_NOT);
809 break;
810 }
811 PrevState = CurrState;
812 }
813 bool onRegister(MCRegister Reg, StringRef &ErrMsg) {
814 IntelExprState CurrState = State;
815 switch (State) {
816 default:
817 State = IES_ERROR;
818 break;
819 case IES_PLUS:
820 case IES_MINUS:
821 case IES_LPAREN:
822 case IES_LBRAC:
823 State = IES_REGISTER;
824 TmpReg = Reg;
825 IC.pushOperand(IC_REGISTER);
826 break;
827 case IES_MULTIPLY:
828 // Index Register - Scale * Register
829 if (PrevState == IES_INTEGER) {
830 if (IndexReg)
831 return regsUseUpError(ErrMsg);
832 if (NegativeAdditiveTerm) {
833 ErrMsg = "Scale can't be negative";
834 return true;
835 }
836 State = IES_REGISTER;
837 IndexReg = Reg;
838 // Get the scale and replace the 'Scale * Register' with '0'.
839 Scale = IC.popOperand();
840 if (checkScale(Scale, ErrMsg))
841 return true;
842 IC.pushOperand(IC_IMM);
843 IC.popOperator();
844 } else {
845 State = IES_ERROR;
846 }
847 break;
848 }
849 PrevState = CurrState;
850 return false;
851 }
852 bool onIdentifierExpr(const MCExpr *SymRef, StringRef SymRefName,
853 const InlineAsmIdentifierInfo &IDInfo,
854 const AsmTypeInfo &Type, bool ParsingMSInlineAsm,
855 StringRef &ErrMsg) {
856 // InlineAsm: Treat an enum value as an integer
857 if (ParsingMSInlineAsm)
859 return onInteger(IDInfo.Enum.EnumVal, ErrMsg);
860 // Treat a symbolic constant like an integer
861 if (auto *CE = dyn_cast<MCConstantExpr>(SymRef))
862 return onInteger(CE->getValue(), ErrMsg);
863 PrevState = State;
864 switch (State) {
865 default:
866 State = IES_ERROR;
867 break;
868 case IES_CAST:
869 case IES_PLUS:
870 case IES_MINUS:
871 case IES_NOT:
872 case IES_INIT:
873 case IES_LBRAC:
874 case IES_LPAREN:
875 if (setSymRef(SymRef, SymRefName, ErrMsg))
876 return true;
877 MemExpr = true;
878 State = IES_INTEGER;
879 IC.pushOperand(IC_IMM);
880 if (ParsingMSInlineAsm)
881 Info = IDInfo;
882 setTypeInfo(Type);
883 break;
884 }
885 return false;
886 }
887 bool onInteger(int64_t TmpInt, StringRef &ErrMsg) {
888 IntelExprState CurrState = State;
889 switch (State) {
890 default:
891 State = IES_ERROR;
892 break;
893 case IES_DIVIDE:
894 if (TmpInt == 0) {
895 ErrMsg = "division by zero in assembly expression";
896 State = IES_ERROR;
897 return true;
898 }
899 [[fallthrough]];
900 case IES_MOD:
901 if (TmpInt == 0) {
902 ErrMsg = "modulo by zero in assembly expression";
903 State = IES_ERROR;
904 return true;
905 }
906 [[fallthrough]];
907 case IES_PLUS:
908 case IES_MINUS:
909 case IES_NOT:
910 case IES_OR:
911 case IES_XOR:
912 case IES_AND:
913 case IES_EQ:
914 case IES_NE:
915 case IES_LT:
916 case IES_LE:
917 case IES_GT:
918 case IES_GE:
919 case IES_LSHIFT:
920 case IES_RSHIFT:
921 case IES_MULTIPLY:
922 case IES_LPAREN:
923 case IES_INIT:
924 case IES_LBRAC:
925 State = IES_INTEGER;
926 if (PrevState == IES_REGISTER && CurrState == IES_MULTIPLY) {
927 // Index Register - Register * Scale
928 if (IndexReg)
929 return regsUseUpError(ErrMsg);
930 if (NegativeAdditiveTerm) {
931 ErrMsg = "Scale can't be negative";
932 return true;
933 }
934 IndexReg = TmpReg;
935 Scale = TmpInt;
936 if (checkScale(Scale, ErrMsg))
937 return true;
938 // Get the scale and replace the 'Register * Scale' with '0'.
939 IC.popOperator();
940 } else {
941 IC.pushOperand(IC_IMM, TmpInt);
942 }
943 break;
944 }
945 PrevState = CurrState;
946 return false;
947 }
948 void onStar() {
949 PrevState = State;
950 switch (State) {
951 default:
952 State = IES_ERROR;
953 break;
954 case IES_INTEGER:
955 case IES_REGISTER:
956 case IES_RPAREN:
957 State = IES_MULTIPLY;
958 IC.pushOperator(IC_MULTIPLY);
959 break;
960 }
961 }
962 void onDivide() {
963 PrevState = State;
964 switch (State) {
965 default:
966 State = IES_ERROR;
967 break;
968 case IES_INTEGER:
969 case IES_RPAREN:
970 State = IES_DIVIDE;
971 IC.pushOperator(IC_DIVIDE);
972 break;
973 }
974 }
975 void onMod() {
976 PrevState = State;
977 switch (State) {
978 default:
979 State = IES_ERROR;
980 break;
981 case IES_INTEGER:
982 case IES_RPAREN:
983 State = IES_MOD;
984 IC.pushOperator(IC_MOD);
985 break;
986 }
987 }
988 bool onLBrac() {
989 if (BracCount)
990 return true;
991 PrevState = State;
992 switch (State) {
993 default:
994 State = IES_ERROR;
995 break;
996 case IES_RBRAC:
997 case IES_INTEGER:
998 case IES_RPAREN:
999 State = IES_PLUS;
1000 IC.pushOperator(IC_PLUS);
1001 CurType.Length = 1;
1002 CurType.Size = CurType.ElementSize;
1003 break;
1004 case IES_INIT:
1005 case IES_CAST:
1006 assert(!BracCount && "BracCount should be zero on parsing's start");
1007 State = IES_LBRAC;
1008 break;
1009 }
1010 MemExpr = true;
1011 BracketUsed = true;
1012 BracCount++;
1013 return false;
1014 }
1015 bool onRBrac(StringRef &ErrMsg) {
1016 IntelExprState CurrState = State;
1017 switch (State) {
1018 default:
1019 State = IES_ERROR;
1020 break;
1021 case IES_INTEGER:
1022 case IES_OFFSET:
1023 case IES_REGISTER:
1024 case IES_RPAREN:
1025 if (BracCount-- != 1) {
1026 ErrMsg = "unexpected bracket encountered";
1027 return true;
1028 }
1029 State = IES_RBRAC;
1030 if (CurrState == IES_REGISTER && PrevState != IES_MULTIPLY) {
1031 // If we already have a BaseReg, then assume this is the IndexReg with
1032 // no explicit scale.
1033 if (!BaseReg) {
1034 BaseReg = TmpReg;
1035 } else {
1036 if (IndexReg)
1037 return regsUseUpError(ErrMsg);
1038 if (NegativeAdditiveTerm) {
1039 ErrMsg = "Scale can't be negative";
1040 return true;
1041 }
1042 IndexReg = TmpReg;
1043 Scale = 0;
1044 }
1045 }
1046 NegativeAdditiveTerm = false;
1047 NegativeAdditiveTermLoc = SMLoc();
1048 break;
1049 }
1050 PrevState = CurrState;
1051 return false;
1052 }
1053 void onLParen() {
1054 IntelExprState CurrState = State;
1055 switch (State) {
1056 default:
1057 State = IES_ERROR;
1058 break;
1059 case IES_PLUS:
1060 case IES_MINUS:
1061 case IES_NOT:
1062 case IES_OR:
1063 case IES_XOR:
1064 case IES_AND:
1065 case IES_EQ:
1066 case IES_NE:
1067 case IES_LT:
1068 case IES_LE:
1069 case IES_GT:
1070 case IES_GE:
1071 case IES_LSHIFT:
1072 case IES_RSHIFT:
1073 case IES_MULTIPLY:
1074 case IES_DIVIDE:
1075 case IES_MOD:
1076 case IES_LPAREN:
1077 case IES_INIT:
1078 case IES_LBRAC:
1079 State = IES_LPAREN;
1080 IC.pushOperator(IC_LPAREN);
1081 break;
1082 }
1083 PrevState = CurrState;
1084 }
1085 bool onRParen(StringRef &ErrMsg) {
1086 IntelExprState CurrState = State;
1087 switch (State) {
1088 default:
1089 State = IES_ERROR;
1090 break;
1091 case IES_INTEGER:
1092 case IES_OFFSET:
1093 case IES_REGISTER:
1094 case IES_RBRAC:
1095 case IES_RPAREN:
1096 State = IES_RPAREN;
1097 // In the case of a multiply, onRegister has already set IndexReg
1098 // directly, with appropriate scale.
1099 // Otherwise if we just saw a register it has only been stored in
1100 // TmpReg, so we need to store it into the state machine.
1101 if (CurrState == IES_REGISTER && PrevState != IES_MULTIPLY) {
1102 // If we already have a BaseReg, then assume this is the IndexReg with
1103 // no explicit scale.
1104 if (!BaseReg) {
1105 BaseReg = TmpReg;
1106 } else {
1107 if (IndexReg)
1108 return regsUseUpError(ErrMsg);
1109 if (NegativeAdditiveTerm) {
1110 ErrMsg = "Scale can't be negative";
1111 return true;
1112 }
1113 IndexReg = TmpReg;
1114 Scale = 0;
1115 }
1116 }
1117 IC.pushOperator(IC_RPAREN);
1118 break;
1119 }
1120 PrevState = CurrState;
1121 return false;
1122 }
1123 bool onOffset(const MCExpr *Val, SMLoc OffsetLoc, StringRef ID,
1124 const InlineAsmIdentifierInfo &IDInfo,
1125 bool ParsingMSInlineAsm, StringRef &ErrMsg) {
1126 PrevState = State;
1127 switch (State) {
1128 default:
1129 ErrMsg = "unexpected offset operator expression";
1130 return true;
1131 case IES_PLUS:
1132 case IES_INIT:
1133 case IES_LBRAC:
1134 if (setSymRef(Val, ID, ErrMsg))
1135 return true;
1136 OffsetOperator = true;
1137 OffsetOperatorLoc = OffsetLoc;
1138 State = IES_OFFSET;
1139 // As we cannot yet resolve the actual value (offset), we retain
1140 // the requested semantics by pushing a '0' to the operands stack
1141 IC.pushOperand(IC_IMM);
1142 if (ParsingMSInlineAsm) {
1143 Info = IDInfo;
1144 }
1145 break;
1146 }
1147 return false;
1148 }
1149 void onCast(AsmTypeInfo Info) {
1150 PrevState = State;
1151 switch (State) {
1152 default:
1153 State = IES_ERROR;
1154 break;
1155 case IES_LPAREN:
1156 setTypeInfo(Info);
1157 State = IES_CAST;
1158 break;
1159 }
1160 }
1161 void setTypeInfo(AsmTypeInfo Type) { CurType = Type; }
1162 };
1163
1164 bool Error(SMLoc L, const Twine &Msg, SMRange Range = {},
1165 bool MatchingInlineAsm = false) {
1166 MCAsmParser &Parser = getParser();
1167 if (MatchingInlineAsm) {
1168 return false;
1169 }
1170 return Parser.Error(L, Msg, Range);
1171 }
1172
1173 bool MatchRegisterByName(MCRegister &RegNo, StringRef RegName, SMLoc StartLoc,
1174 SMLoc EndLoc);
1175 bool ParseRegister(MCRegister &RegNo, SMLoc &StartLoc, SMLoc &EndLoc,
1176 bool RestoreOnFailure);
1177
1178 std::unique_ptr<X86Operand> DefaultMemSIOperand(SMLoc Loc);
1179 std::unique_ptr<X86Operand> DefaultMemDIOperand(SMLoc Loc);
1180 bool IsSIReg(MCRegister Reg);
1181 MCRegister GetSIDIForRegClass(unsigned RegClassID, bool IsSIReg);
1182 void
1183 AddDefaultSrcDestOperands(OperandVector &Operands,
1184 std::unique_ptr<llvm::MCParsedAsmOperand> &&Src,
1185 std::unique_ptr<llvm::MCParsedAsmOperand> &&Dst);
1186 bool VerifyAndAdjustOperands(OperandVector &OrigOperands,
1187 OperandVector &FinalOperands);
1188 bool parseOperand(OperandVector &Operands, StringRef Name);
1189 bool parseATTOperand(OperandVector &Operands);
1190 bool parseIntelOperand(OperandVector &Operands, StringRef Name);
1191 bool ParseIntelOffsetOperator(const MCExpr *&Val, StringRef &ID,
1192 InlineAsmIdentifierInfo &Info, SMLoc &End);
1193 bool ParseIntelDotOperator(IntelExprStateMachine &SM, SMLoc &End);
1194 unsigned IdentifyIntelInlineAsmOperator(StringRef Name);
1195 unsigned ParseIntelInlineAsmOperator(unsigned OpKind);
1196 unsigned IdentifyMasmOperator(StringRef Name);
1197 bool ParseMasmOperator(unsigned OpKind, int64_t &Val);
1198 bool ParseRoundingModeOp(SMLoc Start, OperandVector &Operands);
1199 bool parseCFlagsOp(OperandVector &Operands);
1200 bool ParseIntelNamedOperator(StringRef Name, IntelExprStateMachine &SM,
1201 bool &ParseError, SMLoc &End);
1202 bool ParseMasmNamedOperator(StringRef Name, IntelExprStateMachine &SM,
1203 bool &ParseError, SMLoc &End);
1204 void RewriteIntelExpression(IntelExprStateMachine &SM, SMLoc Start,
1205 SMLoc End);
1206 bool ParseIntelExpression(IntelExprStateMachine &SM, SMLoc &End);
1207 bool ParseIntelInlineAsmIdentifier(const MCExpr *&Val, StringRef &Identifier,
1208 InlineAsmIdentifierInfo &Info,
1209 bool IsUnevaluatedOperand, SMLoc &End,
1210 bool IsParsingOffsetOperator = false);
1211 void tryParseOperandIdx(AsmToken::TokenKind PrevTK,
1212 IntelExprStateMachine &SM);
1213
1214 bool CheckDispOverflow(MCRegister BaseReg, MCRegister IndexReg,
1215 const MCExpr *Disp, SMLoc Loc);
1216
1217 bool ParseMemOperand(MCRegister SegReg, const MCExpr *Disp, SMLoc StartLoc,
1218 SMLoc EndLoc, OperandVector &Operands);
1219
1220 X86::CondCode ParseConditionCode(StringRef CCode);
1221
1222 bool ParseIntelMemoryOperandSize(unsigned &Size, StringRef *SizeStr);
1223 bool CreateMemForMSInlineAsm(MCRegister SegReg, const MCExpr *Disp,
1224 MCRegister BaseReg, MCRegister IndexReg,
1225 unsigned Scale, bool NonAbsMem, SMLoc Start,
1226 SMLoc End, unsigned Size, StringRef Identifier,
1227 const InlineAsmIdentifierInfo &Info,
1228 OperandVector &Operands);
1229
1230 bool parseDirectiveArch();
1231 bool parseDirectiveNops(SMLoc L);
1232 bool parseDirectiveEven(SMLoc L);
1233 bool ParseDirectiveCode(StringRef IDVal, SMLoc L);
1234
1235 /// CodeView FPO data directives.
1236 bool parseDirectiveFPOProc(SMLoc L);
1237 bool parseDirectiveFPOSetFrame(SMLoc L);
1238 bool parseDirectiveFPOPushReg(SMLoc L);
1239 bool parseDirectiveFPOStackAlloc(SMLoc L);
1240 bool parseDirectiveFPOStackAlign(SMLoc L);
1241 bool parseDirectiveFPOEndPrologue(SMLoc L);
1242 bool parseDirectiveFPOEndProc(SMLoc L);
1243
1244 /// SEH directives.
1245 bool parseSEHRegisterNumber(unsigned RegClassID, MCRegister &RegNo);
1246 bool parseDirectiveSEHPushReg(SMLoc);
1247 bool parseDirectiveSEHPush2Regs(SMLoc, bool SwapRegs = false);
1248 bool parseDirectiveSEHSetFrame(SMLoc);
1249 bool parseDirectiveSEHSaveReg(SMLoc);
1250 bool parseDirectiveSEHSaveXMM(SMLoc);
1251 bool parseDirectiveSEHPushFrame(SMLoc);
1252
1253 bool ensureMasmEpilogContext(SMLoc Loc);
1254 bool ensureMasmPrologContext(SMLoc Loc);
1255
1256 unsigned checkTargetMatchPredicate(MCInst &Inst) override;
1257
1258 bool validateInstruction(MCInst &Inst, const OperandVector &Ops);
1259 bool processInstruction(MCInst &Inst, const OperandVector &Ops);
1260
1261 // Load Value Injection (LVI) Mitigations for machine code
1262 void emitWarningForSpecialLVIInstruction(SMLoc Loc);
1263 void applyLVICFIMitigation(MCInst &Inst, MCStreamer &Out);
1264 void applyLVILoadHardeningMitigation(MCInst &Inst, MCStreamer &Out);
1265
1266 /// Wrapper around MCStreamer::emitInstruction(). Possibly adds
1267 /// instrumentation around Inst.
1268 void emitInstruction(MCInst &Inst, OperandVector &Operands, MCStreamer &Out);
1269
1270 bool matchAndEmitInstruction(SMLoc IDLoc, unsigned &Opcode,
1271 OperandVector &Operands, MCStreamer &Out,
1272 uint64_t &ErrorInfo,
1273 bool MatchingInlineAsm) override;
1274
1275 void MatchFPUWaitAlias(SMLoc IDLoc, X86Operand &Op, OperandVector &Operands,
1276 MCStreamer &Out, bool MatchingInlineAsm);
1277
1278 bool ErrorMissingFeature(SMLoc IDLoc, const FeatureBitset &MissingFeatures,
1279 bool MatchingInlineAsm);
1280
1281 bool matchAndEmitATTInstruction(SMLoc IDLoc, unsigned &Opcode, MCInst &Inst,
1282 OperandVector &Operands, MCStreamer &Out,
1283 uint64_t &ErrorInfo, bool MatchingInlineAsm);
1284
1285 bool matchAndEmitIntelInstruction(SMLoc IDLoc, unsigned &Opcode, MCInst &Inst,
1286 OperandVector &Operands, MCStreamer &Out,
1287 uint64_t &ErrorInfo,
1288 bool MatchingInlineAsm);
1289
1290 bool omitRegisterFromClobberLists(MCRegister Reg) override;
1291
1292 /// Parses AVX512 specific operand primitives: masked registers ({%k<NUM>}, {z})
1293 /// and memory broadcasting ({1to<NUM>}) primitives, updating Operands vector if required.
1294 /// return false if no parsing errors occurred, true otherwise.
1295 bool HandleAVX512Operand(OperandVector &Operands);
1296
1297 bool ParseZ(std::unique_ptr<X86Operand> &Z, SMLoc StartLoc);
1298
1299 bool is64BitMode() const {
1300 // FIXME: Can tablegen auto-generate this?
1301 return getSTI().hasFeature(X86::Is64Bit);
1302 }
1303 bool is32BitMode() const {
1304 // FIXME: Can tablegen auto-generate this?
1305 return getSTI().hasFeature(X86::Is32Bit);
1306 }
1307 bool is16BitMode() const {
1308 // FIXME: Can tablegen auto-generate this?
1309 return getSTI().hasFeature(X86::Is16Bit);
1310 }
1311 void SwitchMode(unsigned mode) {
1312 MCSubtargetInfo &STI = copySTI();
1313 FeatureBitset AllModes({X86::Is64Bit, X86::Is32Bit, X86::Is16Bit});
1314 FeatureBitset OldMode = STI.getFeatureBits() & AllModes;
1315 FeatureBitset FB = ComputeAvailableFeatures(
1316 STI.ToggleFeature(OldMode.flip(mode)));
1317 setAvailableFeatures(FB);
1318
1319 assert(FeatureBitset({mode}) == (STI.getFeatureBits() & AllModes));
1320 }
1321
1322 unsigned getPointerWidth() {
1323 if (is16BitMode()) return 16;
1324 if (is32BitMode()) return 32;
1325 if (is64BitMode()) return 64;
1326 llvm_unreachable("invalid mode");
1327 }
1328
1329 bool isParsingIntelSyntax() {
1330 return getParser().getAssemblerDialect();
1331 }
1332
1333 /// @name Auto-generated Matcher Functions
1334 /// {
1335
1336#define GET_ASSEMBLER_HEADER
1337#include "X86GenAsmMatcher.inc"
1338
1339 /// }
1340
1341public:
1342 enum X86MatchResultTy {
1343 Match_Unsupported = FIRST_TARGET_MATCH_RESULT_TY,
1344#define GET_OPERAND_DIAGNOSTIC_TYPES
1345#include "X86GenAsmMatcher.inc"
1346 };
1347
1348 X86AsmParser(const MCSubtargetInfo &sti, MCAsmParser &Parser,
1349 const MCInstrInfo &mii)
1350 : MCTargetAsmParser(sti, mii), InstInfo(nullptr), Code16GCC(false) {
1351
1352 Parser.addAliasForDirective(".word", ".2byte");
1353
1354 // Initialize the set of available features.
1355 setAvailableFeatures(ComputeAvailableFeatures(getSTI().getFeatureBits()));
1356 }
1357
1358 bool parseRegister(MCRegister &Reg, SMLoc &StartLoc, SMLoc &EndLoc) override;
1359 ParseStatus tryParseRegister(MCRegister &Reg, SMLoc &StartLoc,
1360 SMLoc &EndLoc) override;
1361
1362 bool parsePrimaryExpr(const MCExpr *&Res, SMLoc &EndLoc) override;
1363
1364 bool parseInstruction(ParseInstructionInfo &Info, StringRef Name,
1365 SMLoc NameLoc, OperandVector &Operands) override;
1366
1367 bool ParseDirective(AsmToken DirectiveID) override;
1368};
1369} // end anonymous namespace
1370
1371#define GET_REGISTER_MATCHER
1372#define GET_SUBTARGET_FEATURE_NAME
1373#include "X86GenAsmMatcher.inc"
1374
1376 MCRegister IndexReg, unsigned Scale,
1377 bool Is64BitMode,
1378 StringRef &ErrMsg) {
1379 // If we have both a base register and an index register make sure they are
1380 // both 64-bit or 32-bit registers.
1381 // To support VSIB, IndexReg can be 128-bit or 256-bit registers.
1382
1383 if (BaseReg &&
1384 !(BaseReg == X86::RIP || BaseReg == X86::EIP ||
1385 getX86MCRegisterClass(X86::GR16RegClassID).contains(BaseReg) ||
1386 getX86MCRegisterClass(X86::GR32RegClassID).contains(BaseReg) ||
1387 getX86MCRegisterClass(X86::GR64RegClassID).contains(BaseReg))) {
1388 ErrMsg = "invalid base+index expression";
1389 return true;
1390 }
1391
1392 if (IndexReg &&
1393 !(IndexReg == X86::EIZ || IndexReg == X86::RIZ ||
1394 getX86MCRegisterClass(X86::GR16RegClassID).contains(IndexReg) ||
1395 getX86MCRegisterClass(X86::GR32RegClassID).contains(IndexReg) ||
1396 getX86MCRegisterClass(X86::GR64RegClassID).contains(IndexReg) ||
1397 getX86MCRegisterClass(X86::VR128XRegClassID).contains(IndexReg) ||
1398 getX86MCRegisterClass(X86::VR256XRegClassID).contains(IndexReg) ||
1399 getX86MCRegisterClass(X86::VR512RegClassID).contains(IndexReg))) {
1400 ErrMsg = "invalid base+index expression";
1401 return true;
1402 }
1403
1404 if (((BaseReg == X86::RIP || BaseReg == X86::EIP) && IndexReg) ||
1405 IndexReg == X86::EIP || IndexReg == X86::RIP || IndexReg == X86::ESP ||
1406 IndexReg == X86::RSP) {
1407 ErrMsg = "invalid base+index expression";
1408 return true;
1409 }
1410
1411 // Check for use of invalid 16-bit registers. Only BX/BP/SI/DI are allowed,
1412 // and then only in non-64-bit modes.
1413 if (getX86MCRegisterClass(X86::GR16RegClassID).contains(BaseReg) &&
1414 (Is64BitMode || (BaseReg != X86::BX && BaseReg != X86::BP &&
1415 BaseReg != X86::SI && BaseReg != X86::DI))) {
1416 ErrMsg = "invalid 16-bit base register";
1417 return true;
1418 }
1419
1420 if (!BaseReg &&
1421 getX86MCRegisterClass(X86::GR16RegClassID).contains(IndexReg)) {
1422 ErrMsg = "16-bit memory operand may not include only index register";
1423 return true;
1424 }
1425
1426 if (BaseReg && IndexReg) {
1427 if (getX86MCRegisterClass(X86::GR64RegClassID).contains(BaseReg) &&
1428 (getX86MCRegisterClass(X86::GR16RegClassID).contains(IndexReg) ||
1429 getX86MCRegisterClass(X86::GR32RegClassID).contains(IndexReg) ||
1430 IndexReg == X86::EIZ)) {
1431 ErrMsg = "base register is 64-bit, but index register is not";
1432 return true;
1433 }
1434 if (getX86MCRegisterClass(X86::GR32RegClassID).contains(BaseReg) &&
1435 (getX86MCRegisterClass(X86::GR16RegClassID).contains(IndexReg) ||
1436 getX86MCRegisterClass(X86::GR64RegClassID).contains(IndexReg) ||
1437 IndexReg == X86::RIZ)) {
1438 ErrMsg = "base register is 32-bit, but index register is not";
1439 return true;
1440 }
1441 if (getX86MCRegisterClass(X86::GR16RegClassID).contains(BaseReg)) {
1442 if (getX86MCRegisterClass(X86::GR32RegClassID).contains(IndexReg) ||
1443 getX86MCRegisterClass(X86::GR64RegClassID).contains(IndexReg)) {
1444 ErrMsg = "base register is 16-bit, but index register is not";
1445 return true;
1446 }
1447 if ((BaseReg != X86::BX && BaseReg != X86::BP) ||
1448 (IndexReg != X86::SI && IndexReg != X86::DI)) {
1449 ErrMsg = "invalid 16-bit base/index register combination";
1450 return true;
1451 }
1452 }
1453 }
1454
1455 // RIP/EIP-relative addressing is only supported in 64-bit mode.
1456 if (!Is64BitMode && (BaseReg == X86::RIP || BaseReg == X86::EIP)) {
1457 ErrMsg = "IP-relative addressing requires 64-bit mode";
1458 return true;
1459 }
1460
1461 return checkScale(Scale, ErrMsg);
1462}
1463
1464bool X86AsmParser::MatchRegisterByName(MCRegister &RegNo, StringRef RegName,
1465 SMLoc StartLoc, SMLoc EndLoc) {
1466 // If we encounter a %, ignore it. This code handles registers with and
1467 // without the prefix, unprefixed registers can occur in cfi directives.
1468 RegName.consume_front("%");
1469
1470 RegNo = MatchRegisterName(RegName);
1471
1472 // If the match failed, try the register name as lowercase.
1473 if (!RegNo)
1474 RegNo = MatchRegisterName(RegName.lower());
1475
1476 // The "flags" and "mxcsr" registers cannot be referenced directly.
1477 // Treat it as an identifier instead.
1478 if (isParsingMSInlineAsm() && isParsingIntelSyntax() &&
1479 (RegNo == X86::EFLAGS || RegNo == X86::MXCSR))
1480 RegNo = MCRegister();
1481
1482 if (!is64BitMode()) {
1483 // FIXME: This should be done using Requires<Not64BitMode> and
1484 // Requires<In64BitMode> so "eiz" usage in 64-bit instructions can be also
1485 // checked.
1486 if (RegNo == X86::RIZ || RegNo == X86::RIP ||
1487 getX86MCRegisterClass(X86::GR64RegClassID).contains(RegNo) ||
1490 return Error(StartLoc,
1491 "register %" + RegName + " is only available in 64-bit mode",
1492 SMRange(StartLoc, EndLoc));
1493 }
1494 }
1495
1496 if (X86II::isApxExtendedReg(RegNo))
1497 UseApxExtendedReg = true;
1498
1499 // If this is "db[0-15]", match it as an alias
1500 // for dr[0-15].
1501 if (!RegNo && RegName.starts_with("db")) {
1502 if (RegName.size() == 3) {
1503 switch (RegName[2]) {
1504 case '0':
1505 RegNo = X86::DR0;
1506 break;
1507 case '1':
1508 RegNo = X86::DR1;
1509 break;
1510 case '2':
1511 RegNo = X86::DR2;
1512 break;
1513 case '3':
1514 RegNo = X86::DR3;
1515 break;
1516 case '4':
1517 RegNo = X86::DR4;
1518 break;
1519 case '5':
1520 RegNo = X86::DR5;
1521 break;
1522 case '6':
1523 RegNo = X86::DR6;
1524 break;
1525 case '7':
1526 RegNo = X86::DR7;
1527 break;
1528 case '8':
1529 RegNo = X86::DR8;
1530 break;
1531 case '9':
1532 RegNo = X86::DR9;
1533 break;
1534 }
1535 } else if (RegName.size() == 4 && RegName[2] == '1') {
1536 switch (RegName[3]) {
1537 case '0':
1538 RegNo = X86::DR10;
1539 break;
1540 case '1':
1541 RegNo = X86::DR11;
1542 break;
1543 case '2':
1544 RegNo = X86::DR12;
1545 break;
1546 case '3':
1547 RegNo = X86::DR13;
1548 break;
1549 case '4':
1550 RegNo = X86::DR14;
1551 break;
1552 case '5':
1553 RegNo = X86::DR15;
1554 break;
1555 }
1556 }
1557 }
1558
1559 if (!RegNo) {
1560 if (isParsingIntelSyntax())
1561 return true;
1562 return Error(StartLoc, "invalid register name", SMRange(StartLoc, EndLoc));
1563 }
1564 return false;
1565}
1566
1567bool X86AsmParser::ParseRegister(MCRegister &RegNo, SMLoc &StartLoc,
1568 SMLoc &EndLoc, bool RestoreOnFailure) {
1569 MCAsmParser &Parser = getParser();
1570 AsmLexer &Lexer = getLexer();
1571 RegNo = MCRegister();
1572
1574 auto OnFailure = [RestoreOnFailure, &Lexer, &Tokens]() {
1575 if (RestoreOnFailure) {
1576 while (!Tokens.empty()) {
1577 Lexer.UnLex(Tokens.pop_back_val());
1578 }
1579 }
1580 };
1581
1582 const AsmToken &PercentTok = Parser.getTok();
1583 StartLoc = PercentTok.getLoc();
1584
1585 // If we encounter a %, ignore it. This code handles registers with and
1586 // without the prefix, unprefixed registers can occur in cfi directives.
1587 if (!isParsingIntelSyntax() && PercentTok.is(AsmToken::Percent)) {
1588 Tokens.push_back(PercentTok);
1589 Parser.Lex(); // Eat percent token.
1590 }
1591
1592 const AsmToken &Tok = Parser.getTok();
1593 EndLoc = Tok.getEndLoc();
1594
1595 if (Tok.isNot(AsmToken::Identifier)) {
1596 OnFailure();
1597 if (isParsingIntelSyntax()) return true;
1598 return Error(StartLoc, "invalid register name",
1599 SMRange(StartLoc, EndLoc));
1600 }
1601
1602 if (MatchRegisterByName(RegNo, Tok.getString(), StartLoc, EndLoc)) {
1603 OnFailure();
1604 return true;
1605 }
1606
1607 // Parse "%st" as "%st(0)" and "%st(1)", which is multiple tokens.
1608 if (RegNo == X86::ST0) {
1609 Tokens.push_back(Tok);
1610 Parser.Lex(); // Eat 'st'
1611
1612 // Check to see if we have '(4)' after %st.
1613 if (Lexer.isNot(AsmToken::LParen))
1614 return false;
1615 // Lex the paren.
1616 Tokens.push_back(Parser.getTok());
1617 Parser.Lex();
1618
1619 const AsmToken &IntTok = Parser.getTok();
1620 if (IntTok.isNot(AsmToken::Integer)) {
1621 OnFailure();
1622 return Error(IntTok.getLoc(), "expected stack index");
1623 }
1624 switch (IntTok.getIntVal()) {
1625 case 0: RegNo = X86::ST0; break;
1626 case 1: RegNo = X86::ST1; break;
1627 case 2: RegNo = X86::ST2; break;
1628 case 3: RegNo = X86::ST3; break;
1629 case 4: RegNo = X86::ST4; break;
1630 case 5: RegNo = X86::ST5; break;
1631 case 6: RegNo = X86::ST6; break;
1632 case 7: RegNo = X86::ST7; break;
1633 default:
1634 OnFailure();
1635 return Error(IntTok.getLoc(), "invalid stack index");
1636 }
1637
1638 // Lex IntTok
1639 Tokens.push_back(IntTok);
1640 Parser.Lex();
1641 if (Lexer.isNot(AsmToken::RParen)) {
1642 OnFailure();
1643 return Error(Parser.getTok().getLoc(), "expected ')'");
1644 }
1645
1646 EndLoc = Parser.getTok().getEndLoc();
1647 Parser.Lex(); // Eat ')'
1648 return false;
1649 }
1650
1651 EndLoc = Parser.getTok().getEndLoc();
1652
1653 if (!RegNo) {
1654 OnFailure();
1655 if (isParsingIntelSyntax()) return true;
1656 return Error(StartLoc, "invalid register name",
1657 SMRange(StartLoc, EndLoc));
1658 }
1659
1660 Parser.Lex(); // Eat identifier token.
1661 return false;
1662}
1663
1664bool X86AsmParser::parseRegister(MCRegister &Reg, SMLoc &StartLoc,
1665 SMLoc &EndLoc) {
1666 return ParseRegister(Reg, StartLoc, EndLoc, /*RestoreOnFailure=*/false);
1667}
1668
1669ParseStatus X86AsmParser::tryParseRegister(MCRegister &Reg, SMLoc &StartLoc,
1670 SMLoc &EndLoc) {
1671 bool Result = ParseRegister(Reg, StartLoc, EndLoc, /*RestoreOnFailure=*/true);
1672 bool PendingErrors = getParser().hasPendingError();
1673 getParser().clearPendingErrors();
1674 if (PendingErrors)
1675 return ParseStatus::Failure;
1676 if (Result)
1677 return ParseStatus::NoMatch;
1678 return ParseStatus::Success;
1679}
1680
1681std::unique_ptr<X86Operand> X86AsmParser::DefaultMemSIOperand(SMLoc Loc) {
1682 bool Parse32 = is32BitMode() || Code16GCC;
1683 MCRegister Basereg =
1684 is64BitMode() ? X86::RSI : (Parse32 ? X86::ESI : X86::SI);
1685 const MCExpr *Disp = MCConstantExpr::create(0, getContext());
1686 return X86Operand::CreateMem(getPointerWidth(), /*SegReg=*/0, Disp,
1687 /*BaseReg=*/Basereg, /*IndexReg=*/0, /*Scale=*/1,
1688 Loc, Loc, 0);
1689}
1690
1691std::unique_ptr<X86Operand> X86AsmParser::DefaultMemDIOperand(SMLoc Loc) {
1692 bool Parse32 = is32BitMode() || Code16GCC;
1693 MCRegister Basereg =
1694 is64BitMode() ? X86::RDI : (Parse32 ? X86::EDI : X86::DI);
1695 const MCExpr *Disp = MCConstantExpr::create(0, getContext());
1696 return X86Operand::CreateMem(getPointerWidth(), /*SegReg=*/0, Disp,
1697 /*BaseReg=*/Basereg, /*IndexReg=*/0, /*Scale=*/1,
1698 Loc, Loc, 0);
1699}
1700
1701bool X86AsmParser::IsSIReg(MCRegister Reg) {
1702 switch (Reg.id()) {
1703 default: llvm_unreachable("Only (R|E)SI and (R|E)DI are expected!");
1704 case X86::RSI:
1705 case X86::ESI:
1706 case X86::SI:
1707 return true;
1708 case X86::RDI:
1709 case X86::EDI:
1710 case X86::DI:
1711 return false;
1712 }
1713}
1714
1715MCRegister X86AsmParser::GetSIDIForRegClass(unsigned RegClassID, bool IsSIReg) {
1716 switch (RegClassID) {
1717 default: llvm_unreachable("Unexpected register class");
1718 case X86::GR64RegClassID:
1719 return IsSIReg ? X86::RSI : X86::RDI;
1720 case X86::GR32RegClassID:
1721 return IsSIReg ? X86::ESI : X86::EDI;
1722 case X86::GR16RegClassID:
1723 return IsSIReg ? X86::SI : X86::DI;
1724 }
1725}
1726
1727void X86AsmParser::AddDefaultSrcDestOperands(
1728 OperandVector& Operands, std::unique_ptr<llvm::MCParsedAsmOperand> &&Src,
1729 std::unique_ptr<llvm::MCParsedAsmOperand> &&Dst) {
1730 if (isParsingIntelSyntax()) {
1731 Operands.push_back(std::move(Dst));
1732 Operands.push_back(std::move(Src));
1733 }
1734 else {
1735 Operands.push_back(std::move(Src));
1736 Operands.push_back(std::move(Dst));
1737 }
1738}
1739
1740bool X86AsmParser::VerifyAndAdjustOperands(OperandVector &OrigOperands,
1741 OperandVector &FinalOperands) {
1742
1743 if (OrigOperands.size() > 1) {
1744 // Check if sizes match, OrigOperands also contains the instruction name
1745 assert(OrigOperands.size() == FinalOperands.size() + 1 &&
1746 "Operand size mismatch");
1747
1749 // Verify types match
1750 int RegClassID = -1;
1751 for (unsigned int i = 0; i < FinalOperands.size(); ++i) {
1752 X86Operand &OrigOp = static_cast<X86Operand &>(*OrigOperands[i + 1]);
1753 X86Operand &FinalOp = static_cast<X86Operand &>(*FinalOperands[i]);
1754
1755 if (FinalOp.isReg() &&
1756 (!OrigOp.isReg() || FinalOp.getReg() != OrigOp.getReg()))
1757 // Return false and let a normal complaint about bogus operands happen
1758 return false;
1759
1760 if (FinalOp.isMem()) {
1761
1762 if (!OrigOp.isMem())
1763 // Return false and let a normal complaint about bogus operands happen
1764 return false;
1765
1766 MCRegister OrigReg = OrigOp.Mem.BaseReg;
1767 MCRegister FinalReg = FinalOp.Mem.BaseReg;
1768
1769 // If we've already encounterd a register class, make sure all register
1770 // bases are of the same register class
1771 if (RegClassID != -1 &&
1772 !getX86MCRegisterClass(RegClassID).contains(OrigReg)) {
1773 return Error(OrigOp.getStartLoc(),
1774 "mismatching source and destination index registers");
1775 }
1776
1777 if (getX86MCRegisterClass(X86::GR64RegClassID).contains(OrigReg))
1778 RegClassID = X86::GR64RegClassID;
1779 else if (getX86MCRegisterClass(X86::GR32RegClassID).contains(OrigReg))
1780 RegClassID = X86::GR32RegClassID;
1781 else if (getX86MCRegisterClass(X86::GR16RegClassID).contains(OrigReg))
1782 RegClassID = X86::GR16RegClassID;
1783 else
1784 // Unexpected register class type
1785 // Return false and let a normal complaint about bogus operands happen
1786 return false;
1787
1788 bool IsSI = IsSIReg(FinalReg);
1789 FinalReg = GetSIDIForRegClass(RegClassID, IsSI);
1790
1791 if (FinalReg != OrigReg) {
1792 std::string RegName = IsSI ? "ES:(R|E)SI" : "ES:(R|E)DI";
1793 Warnings.push_back(std::make_pair(
1794 OrigOp.getStartLoc(),
1795 "memory operand is only for determining the size, " + RegName +
1796 " will be used for the location"));
1797 }
1798
1799 FinalOp.Mem.Size = OrigOp.Mem.Size;
1800 FinalOp.Mem.SegReg = OrigOp.Mem.SegReg;
1801 FinalOp.Mem.BaseReg = FinalReg;
1802 }
1803 }
1804
1805 // Produce warnings only if all the operands passed the adjustment - prevent
1806 // legal cases like "movsd (%rax), %xmm0" mistakenly produce warnings
1807 for (auto &WarningMsg : Warnings) {
1808 Warning(WarningMsg.first, WarningMsg.second);
1809 }
1810
1811 // Remove old operands
1812 for (unsigned int i = 0; i < FinalOperands.size(); ++i)
1813 OrigOperands.pop_back();
1814 }
1815 // OrigOperands.append(FinalOperands.begin(), FinalOperands.end());
1816 for (auto &Op : FinalOperands)
1817 OrigOperands.push_back(std::move(Op));
1818
1819 return false;
1820}
1821
1822bool X86AsmParser::parseOperand(OperandVector &Operands, StringRef Name) {
1823 if (isParsingIntelSyntax())
1824 return parseIntelOperand(Operands, Name);
1825
1826 return parseATTOperand(Operands);
1827}
1828
1829bool X86AsmParser::CreateMemForMSInlineAsm(
1830 MCRegister SegReg, const MCExpr *Disp, MCRegister BaseReg,
1831 MCRegister IndexReg, unsigned Scale, bool NonAbsMem, SMLoc Start, SMLoc End,
1832 unsigned Size, StringRef Identifier, const InlineAsmIdentifierInfo &Info,
1833 OperandVector &Operands) {
1834 // If we found a decl other than a VarDecl, then assume it is a FuncDecl or
1835 // some other label reference.
1837 // Create an absolute memory reference in order to match against
1838 // instructions taking a PC relative operand.
1839 Operands.push_back(X86Operand::CreateMem(getPointerWidth(), Disp, Start,
1840 End, Size, Identifier,
1841 Info.Label.Decl));
1842 return false;
1843 }
1844 // We either have a direct symbol reference, or an offset from a symbol. The
1845 // parser always puts the symbol on the LHS, so look there for size
1846 // calculation purposes.
1847 unsigned FrontendSize = 0;
1848 void *Decl = nullptr;
1849 bool IsGlobalLV = false;
1851 // Size is in terms of bits in this context.
1852 FrontendSize = Info.Var.Type * 8;
1853 Decl = Info.Var.Decl;
1854 IsGlobalLV = Info.Var.IsGlobalLV;
1855 }
1856 // It is widely common for MS InlineAsm to use a global variable and one/two
1857 // registers in a mmory expression, and though unaccessible via rip/eip.
1858 if (IsGlobalLV) {
1859 if (BaseReg || IndexReg) {
1860 Operands.push_back(X86Operand::CreateMem(getPointerWidth(), Disp, Start,
1861 End, Size, Identifier, Decl, 0,
1862 BaseReg && IndexReg));
1863 return false;
1864 }
1865 if (NonAbsMem)
1866 BaseReg = 1; // Make isAbsMem() false
1867 }
1869 getPointerWidth(), SegReg, Disp, BaseReg, IndexReg, Scale, Start, End,
1870 Size,
1871 /*DefaultBaseReg=*/X86::RIP, Identifier, Decl, FrontendSize));
1872 return false;
1873}
1874
1875// Some binary bitwise operators have a named synonymous
1876// Query a candidate string for being such a named operator
1877// and if so - invoke the appropriate handler
1878bool X86AsmParser::ParseIntelNamedOperator(StringRef Name,
1879 IntelExprStateMachine &SM,
1880 bool &ParseError, SMLoc &End) {
1881 // A named operator should be either lower or upper case, but not a mix...
1882 // except in MASM, which uses full case-insensitivity.
1883 if (Name != Name.lower() && Name != Name.upper() &&
1884 !getParser().isParsingMasm())
1885 return false;
1886 if (Name.equals_insensitive("not")) {
1887 SM.onNot();
1888 } else if (Name.equals_insensitive("or")) {
1889 SM.onOr();
1890 } else if (Name.equals_insensitive("shl")) {
1891 SM.onLShift();
1892 } else if (Name.equals_insensitive("shr")) {
1893 SM.onRShift();
1894 } else if (Name.equals_insensitive("xor")) {
1895 SM.onXor();
1896 } else if (Name.equals_insensitive("and")) {
1897 SM.onAnd();
1898 } else if (Name.equals_insensitive("mod")) {
1899 SM.onMod();
1900 } else if (Name.equals_insensitive("offset")) {
1901 SMLoc OffsetLoc = getTok().getLoc();
1902 const MCExpr *Val = nullptr;
1903 StringRef ID;
1904 InlineAsmIdentifierInfo Info;
1905 ParseError = ParseIntelOffsetOperator(Val, ID, Info, End);
1906 if (ParseError)
1907 return true;
1908 StringRef ErrMsg;
1909 ParseError =
1910 SM.onOffset(Val, OffsetLoc, ID, Info, isParsingMSInlineAsm(), ErrMsg);
1911 if (ParseError)
1912 return Error(SMLoc::getFromPointer(Name.data()), ErrMsg);
1913 } else {
1914 return false;
1915 }
1916 if (!Name.equals_insensitive("offset"))
1917 End = consumeToken();
1918 return true;
1919}
1920bool X86AsmParser::ParseMasmNamedOperator(StringRef Name,
1921 IntelExprStateMachine &SM,
1922 bool &ParseError, SMLoc &End) {
1923 if (Name.equals_insensitive("eq")) {
1924 SM.onEq();
1925 } else if (Name.equals_insensitive("ne")) {
1926 SM.onNE();
1927 } else if (Name.equals_insensitive("lt")) {
1928 SM.onLT();
1929 } else if (Name.equals_insensitive("le")) {
1930 SM.onLE();
1931 } else if (Name.equals_insensitive("gt")) {
1932 SM.onGT();
1933 } else if (Name.equals_insensitive("ge")) {
1934 SM.onGE();
1935 } else {
1936 return false;
1937 }
1938 End = consumeToken();
1939 return true;
1940}
1941
1942// Check if current intel expression append after an operand.
1943// Like: [Operand][Intel Expression]
1944void X86AsmParser::tryParseOperandIdx(AsmToken::TokenKind PrevTK,
1945 IntelExprStateMachine &SM) {
1946 if (PrevTK != AsmToken::RBrac)
1947 return;
1948
1949 SM.setAppendAfterOperand();
1950}
1951
1952bool X86AsmParser::ParseIntelExpression(IntelExprStateMachine &SM, SMLoc &End) {
1953 MCAsmParser &Parser = getParser();
1954 StringRef ErrMsg;
1955
1957
1958 if (getContext().getObjectFileInfo()->isPositionIndependent())
1959 SM.setPIC();
1960
1961 bool Done = false;
1962 while (!Done) {
1963 // Get a fresh reference on each loop iteration in case the previous
1964 // iteration moved the token storage during UnLex().
1965 const AsmToken &Tok = Parser.getTok();
1966
1967 bool UpdateLocLex = true;
1968 AsmToken::TokenKind TK = getLexer().getKind();
1969
1970 switch (TK) {
1971 default:
1972 if ((Done = SM.isValidEndState()))
1973 break;
1974 return Error(Tok.getLoc(), "unknown token in expression");
1975 case AsmToken::Error:
1976 return Error(getLexer().getErrLoc(), getLexer().getErr());
1977 break;
1978 case AsmToken::Real:
1979 // DotOperator: [ebx].0
1980 UpdateLocLex = false;
1981 if (ParseIntelDotOperator(SM, End))
1982 return true;
1983 break;
1984 case AsmToken::Dot:
1985 if (!Parser.isParsingMasm()) {
1986 if ((Done = SM.isValidEndState()))
1987 break;
1988 return Error(Tok.getLoc(), "unknown token in expression");
1989 }
1990 // MASM allows spaces around the dot operator (e.g., "var . x")
1991 Lex();
1992 UpdateLocLex = false;
1993 if (ParseIntelDotOperator(SM, End))
1994 return true;
1995 break;
1996 case AsmToken::Dollar:
1997 if (!Parser.isParsingMasm()) {
1998 if ((Done = SM.isValidEndState()))
1999 break;
2000 return Error(Tok.getLoc(), "unknown token in expression");
2001 }
2002 [[fallthrough]];
2003 case AsmToken::String: {
2004 if (Parser.isParsingMasm()) {
2005 // MASM parsers handle strings in expressions as constants.
2006 SMLoc ValueLoc = Tok.getLoc();
2007 int64_t Res;
2008 const MCExpr *Val;
2009 if (Parser.parsePrimaryExpr(Val, End, nullptr))
2010 return true;
2011 UpdateLocLex = false;
2012 if (!Val->evaluateAsAbsolute(Res, getStreamer().getAssemblerPtr()))
2013 return Error(ValueLoc, "expected absolute value");
2014 if (SM.onInteger(Res, ErrMsg))
2015 return Error(SM.getErrorLoc(ValueLoc), ErrMsg);
2016 break;
2017 }
2018 [[fallthrough]];
2019 }
2020 case AsmToken::At:
2021 case AsmToken::Identifier: {
2022 SMLoc IdentLoc = Tok.getLoc();
2023 StringRef Identifier = Tok.getString();
2024 UpdateLocLex = false;
2025 if (Parser.isParsingMasm()) {
2026 size_t DotOffset = Identifier.find_first_of('.');
2027 if (DotOffset != StringRef::npos) {
2028 consumeToken();
2029 StringRef LHS = Identifier.slice(0, DotOffset);
2030 StringRef Dot = Identifier.substr(DotOffset, 1);
2031 StringRef RHS = Identifier.substr(DotOffset + 1);
2032 if (!RHS.empty()) {
2033 getLexer().UnLex(AsmToken(AsmToken::Identifier, RHS));
2034 }
2035 getLexer().UnLex(AsmToken(AsmToken::Dot, Dot));
2036 if (!LHS.empty()) {
2037 getLexer().UnLex(AsmToken(AsmToken::Identifier, LHS));
2038 }
2039 break;
2040 }
2041 }
2042 // (MASM only) <TYPE> PTR operator
2043 if (Parser.isParsingMasm()) {
2044 const AsmToken &NextTok = getLexer().peekTok();
2045 if (NextTok.is(AsmToken::Identifier) &&
2046 NextTok.getIdentifier().equals_insensitive("ptr")) {
2047 AsmTypeInfo Info;
2048 if (Parser.lookUpType(Identifier, Info))
2049 return Error(Tok.getLoc(), "unknown type");
2050 SM.onCast(Info);
2051 // Eat type and PTR.
2052 consumeToken();
2053 End = consumeToken();
2054 break;
2055 }
2056 }
2057 // Register, or (MASM only) <register>.<field>
2058 MCRegister Reg;
2059 if (Tok.is(AsmToken::Identifier)) {
2060 if (!ParseRegister(Reg, IdentLoc, End, /*RestoreOnFailure=*/true)) {
2061 if (SM.onRegister(Reg, ErrMsg))
2062 return Error(SM.getErrorLoc(IdentLoc), ErrMsg);
2063 break;
2064 }
2065 if (Parser.isParsingMasm()) {
2066 const std::pair<StringRef, StringRef> IDField =
2067 Tok.getString().split('.');
2068 const StringRef ID = IDField.first, Field = IDField.second;
2069 SMLoc IDEndLoc = SMLoc::getFromPointer(ID.data() + ID.size());
2070 if (!Field.empty() &&
2071 !MatchRegisterByName(Reg, ID, IdentLoc, IDEndLoc)) {
2072 if (SM.onRegister(Reg, ErrMsg))
2073 return Error(SM.getErrorLoc(IdentLoc), ErrMsg);
2074
2075 AsmFieldInfo Info;
2076 SMLoc FieldStartLoc = SMLoc::getFromPointer(Field.data());
2077 if (Parser.lookUpField(Field, Info))
2078 return Error(FieldStartLoc, "unknown offset");
2079 else if (SM.onPlus(ErrMsg))
2080 return Error(getTok().getLoc(), ErrMsg);
2081 else if (SM.onInteger(Info.Offset, ErrMsg))
2082 return Error(SM.getErrorLoc(IdentLoc), ErrMsg);
2083 SM.setTypeInfo(Info.Type);
2084
2085 End = consumeToken();
2086 break;
2087 }
2088 }
2089 }
2090 // Operator synonymous ("not", "or" etc.)
2091 bool ParseError = false;
2092 if (ParseIntelNamedOperator(Identifier, SM, ParseError, End)) {
2093 if (ParseError)
2094 return true;
2095 break;
2096 }
2097 if (Parser.isParsingMasm() &&
2098 ParseMasmNamedOperator(Identifier, SM, ParseError, End)) {
2099 if (ParseError)
2100 return true;
2101 break;
2102 }
2103 // Symbol reference, when parsing assembly content
2104 InlineAsmIdentifierInfo Info;
2105 AsmFieldInfo FieldInfo;
2106 const MCExpr *Val;
2107 if (isParsingMSInlineAsm() || Parser.isParsingMasm()) {
2108 // MS Dot Operator expression
2109 if (Identifier.contains('.') &&
2110 (PrevTK == AsmToken::RBrac || PrevTK == AsmToken::RParen)) {
2111 if (ParseIntelDotOperator(SM, End))
2112 return true;
2113 break;
2114 }
2115 }
2116 if (isParsingMSInlineAsm()) {
2117 // MS InlineAsm operators (TYPE/LENGTH/SIZE)
2118 if (unsigned OpKind = IdentifyIntelInlineAsmOperator(Identifier)) {
2119 if (int64_t Val = ParseIntelInlineAsmOperator(OpKind)) {
2120 if (SM.onInteger(Val, ErrMsg))
2121 return Error(SM.getErrorLoc(IdentLoc), ErrMsg);
2122 } else {
2123 return true;
2124 }
2125 break;
2126 }
2127 // MS InlineAsm identifier
2128 // Call parseIdentifier() to combine @ with the identifier behind it.
2129 if (TK == AsmToken::At && Parser.parseIdentifier(Identifier))
2130 return Error(IdentLoc, "expected identifier");
2131 if (ParseIntelInlineAsmIdentifier(Val, Identifier, Info, false, End))
2132 return true;
2133 else if (SM.onIdentifierExpr(Val, Identifier, Info, FieldInfo.Type,
2134 true, ErrMsg))
2135 return Error(SM.getErrorLoc(IdentLoc), ErrMsg);
2136 break;
2137 }
2138 if (Parser.isParsingMasm()) {
2139 if (unsigned OpKind = IdentifyMasmOperator(Identifier)) {
2140 int64_t Val;
2141 if (ParseMasmOperator(OpKind, Val))
2142 return true;
2143 if (SM.onInteger(Val, ErrMsg))
2144 return Error(SM.getErrorLoc(IdentLoc), ErrMsg);
2145 break;
2146 }
2147 if (!getParser().lookUpType(Identifier, FieldInfo.Type)) {
2148 // Field offset immediate; <TYPE>.<field specification>
2149 Lex(); // eat type
2150 bool EndDot = parseOptionalToken(AsmToken::Dot);
2151 while (EndDot || (getTok().is(AsmToken::Identifier) &&
2152 getTok().getString().starts_with("."))) {
2153 getParser().parseIdentifier(Identifier);
2154 if (!EndDot)
2155 Identifier.consume_front(".");
2156 EndDot = Identifier.consume_back(".");
2157 if (getParser().lookUpField(FieldInfo.Type.Name, Identifier,
2158 FieldInfo)) {
2159 SMLoc IDEnd =
2161 return Error(IdentLoc, "Unable to lookup field reference!",
2162 SMRange(IdentLoc, IDEnd));
2163 }
2164 if (!EndDot)
2165 EndDot = parseOptionalToken(AsmToken::Dot);
2166 }
2167 if (SM.onInteger(FieldInfo.Offset, ErrMsg))
2168 return Error(SM.getErrorLoc(IdentLoc), ErrMsg);
2169 break;
2170 }
2171 }
2172 if (getParser().parsePrimaryExpr(Val, End, &FieldInfo.Type)) {
2173 return Error(Tok.getLoc(), "Unexpected identifier!");
2174 } else if (SM.onIdentifierExpr(Val, Identifier, Info, FieldInfo.Type,
2175 false, ErrMsg)) {
2176 return Error(SM.getErrorLoc(IdentLoc), ErrMsg);
2177 }
2178 break;
2179 }
2180 case AsmToken::Integer: {
2181 // Look for 'b' or 'f' following an Integer as a directional label
2182 SMLoc Loc = getTok().getLoc();
2183 int64_t IntVal = getTok().getIntVal();
2184 End = consumeToken();
2185 UpdateLocLex = false;
2186 if (getLexer().getKind() == AsmToken::Identifier) {
2187 StringRef IDVal = getTok().getString();
2188 if (IDVal == "f" || IDVal == "b") {
2189 MCSymbol *Sym =
2190 getContext().getDirectionalLocalSymbol(IntVal, IDVal == "b");
2191 auto Variant = X86::S_None;
2192 const MCExpr *Val =
2193 MCSymbolRefExpr::create(Sym, Variant, getContext());
2194 if (IDVal == "b" && Sym->isUndefined())
2195 return Error(Loc, "invalid reference to undefined symbol");
2196 StringRef Identifier = Sym->getName();
2197 InlineAsmIdentifierInfo Info;
2198 AsmTypeInfo Type;
2199 if (SM.onIdentifierExpr(Val, Identifier, Info, Type,
2200 isParsingMSInlineAsm(), ErrMsg))
2201 return Error(SM.getErrorLoc(Loc), ErrMsg);
2202 End = consumeToken();
2203 } else {
2204 if (SM.onInteger(IntVal, ErrMsg))
2205 return Error(SM.getErrorLoc(Loc), ErrMsg);
2206 }
2207 } else {
2208 if (SM.onInteger(IntVal, ErrMsg))
2209 return Error(SM.getErrorLoc(Loc), ErrMsg);
2210 }
2211 break;
2212 }
2213 case AsmToken::Plus:
2214 if (SM.onPlus(ErrMsg))
2215 return Error(getTok().getLoc(), ErrMsg);
2216 break;
2217 case AsmToken::Minus:
2218 if (SM.onMinus(getTok().getLoc(), ErrMsg))
2219 return Error(SM.getErrorLoc(getTok().getLoc()), ErrMsg);
2220 break;
2221 case AsmToken::Tilde: SM.onNot(); break;
2222 case AsmToken::Star: SM.onStar(); break;
2223 case AsmToken::Slash: SM.onDivide(); break;
2224 case AsmToken::Percent: SM.onMod(); break;
2225 case AsmToken::Pipe: SM.onOr(); break;
2226 case AsmToken::Caret: SM.onXor(); break;
2227 case AsmToken::Amp: SM.onAnd(); break;
2228 case AsmToken::LessLess:
2229 SM.onLShift(); break;
2231 SM.onRShift(); break;
2232 case AsmToken::LBrac:
2233 if (SM.onLBrac())
2234 return Error(Tok.getLoc(), "unexpected bracket encountered");
2235 tryParseOperandIdx(PrevTK, SM);
2236 break;
2237 case AsmToken::RBrac:
2238 if (SM.onRBrac(ErrMsg)) {
2239 return Error(SM.getErrorLoc(Tok.getLoc()), ErrMsg);
2240 }
2241 break;
2242 case AsmToken::LParen: SM.onLParen(); break;
2243 case AsmToken::RParen:
2244 if (SM.onRParen(ErrMsg)) {
2245 return Error(SM.getErrorLoc(Tok.getLoc()), ErrMsg);
2246 }
2247 break;
2248 }
2249 if (SM.hadError())
2250 return Error(Tok.getLoc(), "unknown token in expression");
2251
2252 if (!Done && UpdateLocLex)
2253 End = consumeToken();
2254
2255 PrevTK = TK;
2256 }
2257 return false;
2258}
2259
2260void X86AsmParser::RewriteIntelExpression(IntelExprStateMachine &SM,
2261 SMLoc Start, SMLoc End) {
2262 SMLoc Loc = Start;
2263 unsigned ExprLen = End.getPointer() - Start.getPointer();
2264 // Skip everything before a symbol displacement (if we have one)
2265 if (SM.getSym() && !SM.isOffsetOperator()) {
2266 StringRef SymName = SM.getSymName();
2267 if (unsigned Len = SymName.data() - Start.getPointer())
2268 InstInfo->AsmRewrites->emplace_back(AOK_Skip, Start, Len);
2269 Loc = SMLoc::getFromPointer(SymName.data() + SymName.size());
2270 ExprLen = End.getPointer() - (SymName.data() + SymName.size());
2271 // If we have only a symbol than there's no need for complex rewrite,
2272 // simply skip everything after it
2273 if (!(SM.getBaseReg() || SM.getIndexReg() || SM.getImm())) {
2274 if (ExprLen)
2275 InstInfo->AsmRewrites->emplace_back(AOK_Skip, Loc, ExprLen);
2276 return;
2277 }
2278 }
2279 // Build an Intel Expression rewrite
2280 StringRef BaseRegStr;
2281 StringRef IndexRegStr;
2282 StringRef OffsetNameStr;
2283 if (SM.getBaseReg())
2284 BaseRegStr = X86IntelInstPrinter::getRegisterName(SM.getBaseReg());
2285 if (SM.getIndexReg())
2286 IndexRegStr = X86IntelInstPrinter::getRegisterName(SM.getIndexReg());
2287 if (SM.isOffsetOperator())
2288 OffsetNameStr = SM.getSymName();
2289 // Emit it
2290 IntelExpr Expr(BaseRegStr, IndexRegStr, SM.getScale(), OffsetNameStr,
2291 SM.getImm(), SM.isMemExpr());
2292 InstInfo->AsmRewrites->emplace_back(Loc, ExprLen, Expr);
2293}
2294
2295// Inline assembly may use variable names with namespace alias qualifiers.
2296bool X86AsmParser::ParseIntelInlineAsmIdentifier(
2297 const MCExpr *&Val, StringRef &Identifier, InlineAsmIdentifierInfo &Info,
2298 bool IsUnevaluatedOperand, SMLoc &End, bool IsParsingOffsetOperator) {
2299 MCAsmParser &Parser = getParser();
2300 assert(isParsingMSInlineAsm() && "Expected to be parsing inline assembly.");
2301 Val = nullptr;
2302
2303 StringRef LineBuf(Identifier.data());
2304 SemaCallback->LookupInlineAsmIdentifier(LineBuf, Info, IsUnevaluatedOperand);
2305
2306 const AsmToken &Tok = Parser.getTok();
2307 SMLoc Loc = Tok.getLoc();
2308
2309 // Advance the token stream until the end of the current token is
2310 // after the end of what the frontend claimed.
2311 const char *EndPtr = Tok.getLoc().getPointer() + LineBuf.size();
2312 do {
2313 End = Tok.getEndLoc();
2314 getLexer().Lex();
2315 } while (End.getPointer() < EndPtr);
2316 Identifier = LineBuf;
2317
2318 // The frontend should end parsing on an assembler token boundary, unless it
2319 // failed parsing.
2320 assert((End.getPointer() == EndPtr ||
2322 "frontend claimed part of a token?");
2323
2324 // If the identifier lookup was unsuccessful, assume that we are dealing with
2325 // a label.
2327 StringRef InternalName =
2328 SemaCallback->LookupInlineAsmLabel(Identifier, getSourceManager(),
2329 Loc, false);
2330 assert(InternalName.size() && "We should have an internal name here.");
2331 // Push a rewrite for replacing the identifier name with the internal name,
2332 // unless we are parsing the operand of an offset operator
2333 if (!IsParsingOffsetOperator)
2334 InstInfo->AsmRewrites->emplace_back(AOK_Label, Loc, Identifier.size(),
2335 InternalName);
2336 else
2337 Identifier = InternalName;
2338 } else if (Info.isKind(InlineAsmIdentifierInfo::IK_EnumVal))
2339 return false;
2340 // Create the symbol reference.
2341 MCSymbol *Sym = getContext().getOrCreateSymbol(Identifier);
2342 auto Variant = X86::S_None;
2343 Val = MCSymbolRefExpr::create(Sym, Variant, getParser().getContext());
2344 return false;
2345}
2346
2347//ParseRoundingModeOp - Parse AVX-512 rounding mode operand
2348bool X86AsmParser::ParseRoundingModeOp(SMLoc Start, OperandVector &Operands) {
2349 MCAsmParser &Parser = getParser();
2350 const AsmToken &Tok = Parser.getTok();
2351 // Eat "{" and mark the current place.
2352 const SMLoc consumedToken = consumeToken();
2353 if (Tok.isNot(AsmToken::Identifier))
2354 return Error(Tok.getLoc(), "Expected an identifier after {");
2355 if (Tok.getIdentifier().starts_with("r")) {
2356 int rndMode = StringSwitch<int>(Tok.getIdentifier())
2357 .Case("rn", X86::STATIC_ROUNDING::TO_NEAREST_INT)
2358 .Case("rd", X86::STATIC_ROUNDING::TO_NEG_INF)
2359 .Case("ru", X86::STATIC_ROUNDING::TO_POS_INF)
2360 .Case("rz", X86::STATIC_ROUNDING::TO_ZERO)
2361 .Default(-1);
2362 if (-1 == rndMode)
2363 return Error(Tok.getLoc(), "Invalid rounding mode.");
2364 Parser.Lex(); // Eat "r*" of r*-sae
2365 if (!getLexer().is(AsmToken::Minus))
2366 return Error(Tok.getLoc(), "Expected - at this point");
2367 Parser.Lex(); // Eat "-"
2368 Parser.Lex(); // Eat the sae
2369 if (!getLexer().is(AsmToken::RCurly))
2370 return Error(Tok.getLoc(), "Expected } at this point");
2371 SMLoc End = Tok.getEndLoc();
2372 Parser.Lex(); // Eat "}"
2373 const MCExpr *RndModeOp =
2374 MCConstantExpr::create(rndMode, Parser.getContext());
2375 Operands.push_back(X86Operand::CreateImm(RndModeOp, Start, End));
2376 return false;
2377 }
2378 if (Tok.getIdentifier() == "sae") {
2379 Parser.Lex(); // Eat the sae
2380 if (!getLexer().is(AsmToken::RCurly))
2381 return Error(Tok.getLoc(), "Expected } at this point");
2382 Parser.Lex(); // Eat "}"
2383 Operands.push_back(X86Operand::CreateToken("{sae}", consumedToken));
2384 return false;
2385 }
2386 return Error(Tok.getLoc(), "unknown token in expression");
2387}
2388
2389/// Parse condtional flags for CCMP/CTEST, e.g {dfv=of,sf,zf,cf} right after
2390/// mnemonic.
2391bool X86AsmParser::parseCFlagsOp(OperandVector &Operands) {
2392 MCAsmParser &Parser = getParser();
2393 AsmToken Tok = Parser.getTok();
2394 const SMLoc Start = Tok.getLoc();
2395 if (!Tok.is(AsmToken::LCurly))
2396 return Error(Tok.getLoc(), "Expected { at this point");
2397 Parser.Lex(); // Eat "{"
2398 Tok = Parser.getTok();
2399 if (Tok.getIdentifier().lower() != "dfv")
2400 return Error(Tok.getLoc(), "Expected dfv at this point");
2401 Parser.Lex(); // Eat "dfv"
2402 Tok = Parser.getTok();
2403 if (!Tok.is(AsmToken::Equal))
2404 return Error(Tok.getLoc(), "Expected = at this point");
2405 Parser.Lex(); // Eat "="
2406
2407 Tok = Parser.getTok();
2408 SMLoc End;
2409 if (Tok.is(AsmToken::RCurly)) {
2410 End = Tok.getEndLoc();
2412 MCConstantExpr::create(0, Parser.getContext()), Start, End));
2413 Parser.Lex(); // Eat "}"
2414 return false;
2415 }
2416 unsigned CFlags = 0;
2417 for (unsigned I = 0; I < 4; ++I) {
2418 Tok = Parser.getTok();
2419 unsigned CFlag = StringSwitch<unsigned>(Tok.getIdentifier().lower())
2420 .Case("of", 0x8)
2421 .Case("sf", 0x4)
2422 .Case("zf", 0x2)
2423 .Case("cf", 0x1)
2424 .Default(~0U);
2425 if (CFlag == ~0U)
2426 return Error(Tok.getLoc(), "Invalid conditional flags");
2427
2428 if (CFlags & CFlag)
2429 return Error(Tok.getLoc(), "Duplicated conditional flag");
2430 CFlags |= CFlag;
2431
2432 Parser.Lex(); // Eat one conditional flag
2433 Tok = Parser.getTok();
2434 if (Tok.is(AsmToken::RCurly)) {
2435 End = Tok.getEndLoc();
2437 MCConstantExpr::create(CFlags, Parser.getContext()), Start, End));
2438 Parser.Lex(); // Eat "}"
2439 return false;
2440 } else if (I == 3) {
2441 return Error(Tok.getLoc(), "Expected } at this point");
2442 } else if (Tok.isNot(AsmToken::Comma)) {
2443 return Error(Tok.getLoc(), "Expected } or , at this point");
2444 }
2445 Parser.Lex(); // Eat ","
2446 }
2447 llvm_unreachable("Unexpected control flow");
2448}
2449
2450/// Parse the '.' operator.
2451bool X86AsmParser::ParseIntelDotOperator(IntelExprStateMachine &SM,
2452 SMLoc &End) {
2453 const AsmToken &Tok = getTok();
2454 AsmFieldInfo Info;
2455
2456 // Drop the optional '.'.
2457 StringRef DotDispStr = Tok.getString();
2458 DotDispStr.consume_front(".");
2459 bool TrailingDot = false;
2460
2461 // .Imm gets lexed as a real.
2462 if (Tok.is(AsmToken::Real)) {
2463 APInt DotDisp;
2464 if (DotDispStr.getAsInteger(10, DotDisp))
2465 return Error(Tok.getLoc(), "Unexpected offset");
2466 Info.Offset = DotDisp.getZExtValue();
2467 } else if ((isParsingMSInlineAsm() || getParser().isParsingMasm()) &&
2468 Tok.is(AsmToken::Identifier)) {
2469 TrailingDot = DotDispStr.consume_back(".");
2470 const std::pair<StringRef, StringRef> BaseMember = DotDispStr.split('.');
2471 const StringRef Base = BaseMember.first, Member = BaseMember.second;
2472 if (getParser().lookUpField(SM.getType(), DotDispStr, Info) &&
2473 getParser().lookUpField(SM.getSymName(), DotDispStr, Info) &&
2474 getParser().lookUpField(DotDispStr, Info) &&
2475 (!SemaCallback ||
2476 SemaCallback->LookupInlineAsmField(Base, Member, Info.Offset)))
2477 return Error(Tok.getLoc(), "Unable to lookup field reference!");
2478 } else {
2479 return Error(Tok.getLoc(), "Unexpected token type!");
2480 }
2481
2482 // Eat the DotExpression and update End
2483 End = SMLoc::getFromPointer(DotDispStr.data());
2484 const char *DotExprEndLoc = DotDispStr.data() + DotDispStr.size();
2485 while (Tok.getLoc().getPointer() < DotExprEndLoc)
2486 Lex();
2487 if (TrailingDot)
2488 getLexer().UnLex(AsmToken(AsmToken::Dot, "."));
2489 SM.addImm(Info.Offset);
2490 SM.setTypeInfo(Info.Type);
2491 return false;
2492}
2493
2494/// Parse the 'offset' operator.
2495/// This operator is used to specify the location of a given operand
2496bool X86AsmParser::ParseIntelOffsetOperator(const MCExpr *&Val, StringRef &ID,
2497 InlineAsmIdentifierInfo &Info,
2498 SMLoc &End) {
2499 // Eat offset, mark start of identifier.
2500 SMLoc Start = Lex().getLoc();
2501 ID = getTok().getString();
2502 if (!isParsingMSInlineAsm()) {
2503 if ((getTok().isNot(AsmToken::Identifier) &&
2504 getTok().isNot(AsmToken::String)) ||
2505 getParser().parsePrimaryExpr(Val, End, nullptr))
2506 return Error(Start, "unexpected token!");
2507 } else if (ParseIntelInlineAsmIdentifier(Val, ID, Info, false, End, true)) {
2508 return Error(Start, "unable to lookup expression");
2509 } else if (Info.isKind(InlineAsmIdentifierInfo::IK_EnumVal)) {
2510 return Error(Start, "offset operator cannot yet handle constants");
2511 }
2512 return false;
2513}
2514
2515// Query a candidate string for being an Intel assembly operator
2516// Report back its kind, or IOK_INVALID if does not evaluated as a known one
2517unsigned X86AsmParser::IdentifyIntelInlineAsmOperator(StringRef Name) {
2518 return StringSwitch<unsigned>(Name)
2519 .Cases({"TYPE", "type"}, IOK_TYPE)
2520 .Cases({"SIZE", "size"}, IOK_SIZE)
2521 .Cases({"LENGTH", "length"}, IOK_LENGTH)
2522 .Default(IOK_INVALID);
2523}
2524
2525/// Parse the 'LENGTH', 'TYPE' and 'SIZE' operators. The LENGTH operator
2526/// returns the number of elements in an array. It returns the value 1 for
2527/// non-array variables. The SIZE operator returns the size of a C or C++
2528/// variable. A variable's size is the product of its LENGTH and TYPE. The
2529/// TYPE operator returns the size of a C or C++ type or variable. If the
2530/// variable is an array, TYPE returns the size of a single element.
2531unsigned X86AsmParser::ParseIntelInlineAsmOperator(unsigned OpKind) {
2532 MCAsmParser &Parser = getParser();
2533 const AsmToken &Tok = Parser.getTok();
2534 Parser.Lex(); // Eat operator.
2535
2536 const MCExpr *Val = nullptr;
2537 InlineAsmIdentifierInfo Info;
2538 SMLoc Start = Tok.getLoc(), End;
2539 StringRef Identifier = Tok.getString();
2540 if (ParseIntelInlineAsmIdentifier(Val, Identifier, Info,
2541 /*IsUnevaluatedOperand=*/true, End))
2542 return 0;
2543
2545 Error(Start, "unable to lookup expression");
2546 return 0;
2547 }
2548
2549 unsigned CVal = 0;
2550 switch(OpKind) {
2551 default: llvm_unreachable("Unexpected operand kind!");
2552 case IOK_LENGTH: CVal = Info.Var.Length; break;
2553 case IOK_SIZE: CVal = Info.Var.Size; break;
2554 case IOK_TYPE: CVal = Info.Var.Type; break;
2555 }
2556
2557 return CVal;
2558}
2559
2560// Query a candidate string for being an Intel assembly operator
2561// Report back its kind, or IOK_INVALID if does not evaluated as a known one
2562unsigned X86AsmParser::IdentifyMasmOperator(StringRef Name) {
2563 return StringSwitch<unsigned>(Name.lower())
2564 .Case("type", MOK_TYPE)
2565 .Cases({"size", "sizeof"}, MOK_SIZEOF)
2566 .Cases({"length", "lengthof"}, MOK_LENGTHOF)
2567 .Default(MOK_INVALID);
2568}
2569
2570/// Parse the 'LENGTHOF', 'SIZEOF', and 'TYPE' operators. The LENGTHOF operator
2571/// returns the number of elements in an array. It returns the value 1 for
2572/// non-array variables. The SIZEOF operator returns the size of a type or
2573/// variable in bytes. A variable's size is the product of its LENGTH and TYPE.
2574/// The TYPE operator returns the size of a variable. If the variable is an
2575/// array, TYPE returns the size of a single element.
2576bool X86AsmParser::ParseMasmOperator(unsigned OpKind, int64_t &Val) {
2577 MCAsmParser &Parser = getParser();
2578 SMLoc OpLoc = Parser.getTok().getLoc();
2579 Parser.Lex(); // Eat operator.
2580
2581 Val = 0;
2582 if (OpKind == MOK_SIZEOF || OpKind == MOK_TYPE) {
2583 // Check for SIZEOF(<type>) and TYPE(<type>).
2584 bool InParens = Parser.getTok().is(AsmToken::LParen);
2585 const AsmToken &IDTok = InParens ? getLexer().peekTok() : Parser.getTok();
2586 AsmTypeInfo Type;
2587 if (IDTok.is(AsmToken::Identifier) &&
2588 !Parser.lookUpType(IDTok.getIdentifier(), Type)) {
2589 Val = Type.Size;
2590
2591 // Eat tokens.
2592 if (InParens)
2593 parseToken(AsmToken::LParen);
2594 parseToken(AsmToken::Identifier);
2595 if (InParens)
2596 parseToken(AsmToken::RParen);
2597 }
2598 }
2599
2600 if (!Val) {
2601 IntelExprStateMachine SM;
2602 SMLoc End, Start = Parser.getTok().getLoc();
2603 if (ParseIntelExpression(SM, End))
2604 return true;
2605
2606 switch (OpKind) {
2607 default:
2608 llvm_unreachable("Unexpected operand kind!");
2609 case MOK_SIZEOF:
2610 Val = SM.getSize();
2611 break;
2612 case MOK_LENGTHOF:
2613 Val = SM.getLength();
2614 break;
2615 case MOK_TYPE:
2616 Val = SM.getElementSize();
2617 break;
2618 }
2619
2620 if (!Val)
2621 return Error(OpLoc, "expression has unknown type", SMRange(Start, End));
2622 }
2623
2624 return false;
2625}
2626
2627bool X86AsmParser::ParseIntelMemoryOperandSize(unsigned &Size,
2628 StringRef *SizeStr) {
2629 Size = StringSwitch<unsigned>(getTok().getString())
2630 .Cases({"BYTE", "byte"}, 8)
2631 .Cases({"WORD", "word"}, 16)
2632 .Cases({"DWORD", "dword"}, 32)
2633 .Cases({"FLOAT", "float"}, 32)
2634 .Cases({"LONG", "long"}, 32)
2635 .Cases({"FWORD", "fword"}, 48)
2636 .Cases({"DOUBLE", "double"}, 64)
2637 .Cases({"QWORD", "qword"}, 64)
2638 .Cases({"MMWORD", "mmword"}, 64)
2639 .Cases({"XWORD", "xword"}, 80)
2640 .Cases({"TBYTE", "tbyte"}, 80)
2641 .Cases({"XMMWORD", "xmmword"}, 128)
2642 .Cases({"YMMWORD", "ymmword"}, 256)
2643 .Cases({"ZMMWORD", "zmmword"}, 512)
2644 .Default(0);
2645 if (Size) {
2646 if (SizeStr)
2647 *SizeStr = getTok().getString();
2648 const AsmToken &Tok = Lex(); // Eat operand size (e.g., byte, word).
2649 if (!(Tok.getString() == "PTR" || Tok.getString() == "ptr"))
2650 return Error(Tok.getLoc(), "Expected 'PTR' or 'ptr' token!");
2651 Lex(); // Eat ptr.
2652 }
2653 return false;
2654}
2655
2657 if (getX86MCRegisterClass(X86::GR8RegClassID).contains(RegNo))
2658 return 8;
2659 if (getX86MCRegisterClass(X86::GR16RegClassID).contains(RegNo))
2660 return 16;
2661 if (getX86MCRegisterClass(X86::GR32RegClassID).contains(RegNo))
2662 return 32;
2663 if (getX86MCRegisterClass(X86::GR64RegClassID).contains(RegNo))
2664 return 64;
2665 // Unknown register size
2666 return 0;
2667}
2668
2669bool X86AsmParser::parseIntelOperand(OperandVector &Operands, StringRef Name) {
2670 MCAsmParser &Parser = getParser();
2671 const AsmToken &Tok = Parser.getTok();
2672 SMLoc Start, End;
2673
2674 // Parse optional Size directive.
2675 unsigned Size;
2676 StringRef SizeStr;
2677 if (ParseIntelMemoryOperandSize(Size, &SizeStr))
2678 return true;
2679 bool PtrInOperand = bool(Size);
2680
2681 Start = Tok.getLoc();
2682
2683 // Rounding mode operand.
2684 if (getLexer().is(AsmToken::LCurly))
2685 return ParseRoundingModeOp(Start, Operands);
2686
2687 // Register operand.
2688 MCRegister RegNo;
2689 if (Tok.is(AsmToken::Identifier) && !parseRegister(RegNo, Start, End)) {
2690 if (RegNo == X86::RIP)
2691 return Error(Start, "rip can only be used as a base register");
2692 // A Register followed by ':' is considered a segment override
2693 if (Tok.isNot(AsmToken::Colon)) {
2694 if (PtrInOperand) {
2695 if (!Parser.isParsingMasm())
2696 return Error(Start, "expected memory operand after 'ptr', "
2697 "found register operand instead");
2698
2699 // If we are parsing MASM, we are allowed to cast registers to their own
2700 // sizes, but not to other types.
2701 uint16_t RegSize =
2702 RegSizeInBits(*getContext().getRegisterInfo(), RegNo);
2703 if (RegSize == 0)
2704 return Error(
2705 Start,
2706 "cannot cast register '" +
2707 StringRef(getContext().getRegisterInfo()->getName(RegNo)) +
2708 "'; its size is not easily defined.");
2709 if (RegSize != Size)
2710 return Error(
2711 Start,
2712 std::to_string(RegSize) + "-bit register '" +
2713 StringRef(getContext().getRegisterInfo()->getName(RegNo)) +
2714 "' cannot be used as a " + std::to_string(Size) + "-bit " +
2715 SizeStr.upper());
2716 }
2717 Operands.push_back(X86Operand::CreateReg(RegNo, Start, End));
2718 return false;
2719 }
2720 // An alleged segment override. check if we have a valid segment register
2721 if (!getX86MCRegisterClass(X86::SEGMENT_REGRegClassID).contains(RegNo))
2722 return Error(Start, "invalid segment register");
2723 // Eat ':' and update Start location
2724 Start = Lex().getLoc();
2725 }
2726
2727 // Immediates and Memory
2728 IntelExprStateMachine SM;
2729 if (ParseIntelExpression(SM, End))
2730 return true;
2731
2732 if (isParsingMSInlineAsm())
2733 RewriteIntelExpression(SM, Start, Tok.getLoc());
2734
2735 int64_t Imm = SM.getImm();
2736 const MCExpr *Disp = SM.getSym();
2737 const MCExpr *ImmDisp = MCConstantExpr::create(Imm, getContext());
2738 if (Disp && Imm)
2739 Disp = MCBinaryExpr::createAdd(Disp, ImmDisp, getContext());
2740 if (!Disp)
2741 Disp = ImmDisp;
2742
2743 // RegNo != 0 specifies a valid segment register,
2744 // and we are parsing a segment override
2745 if (!SM.isMemExpr() && !RegNo) {
2746 if (isParsingMSInlineAsm() && SM.isOffsetOperator()) {
2747 const InlineAsmIdentifierInfo &Info = SM.getIdentifierInfo();
2749 // Disp includes the address of a variable; make sure this is recorded
2750 // for later handling.
2751 Operands.push_back(X86Operand::CreateImm(Disp, Start, End,
2752 SM.getSymName(), Info.Var.Decl,
2753 Info.Var.IsGlobalLV));
2754 return false;
2755 }
2756 }
2757
2758 Operands.push_back(X86Operand::CreateImm(Disp, Start, End));
2759 return false;
2760 }
2761
2762 StringRef ErrMsg;
2763 MCRegister BaseReg = SM.getBaseReg();
2764 MCRegister IndexReg = SM.getIndexReg();
2765 if (IndexReg && BaseReg == X86::RIP)
2766 BaseReg = MCRegister();
2767 unsigned Scale = SM.getScale();
2768 if (!PtrInOperand)
2769 Size = SM.getElementSize() << 3;
2770
2771 if (Scale == 0 && BaseReg != X86::ESP && BaseReg != X86::RSP &&
2772 (IndexReg == X86::ESP || IndexReg == X86::RSP))
2773 std::swap(BaseReg, IndexReg);
2774
2775 // If BaseReg is a vector register and IndexReg is not, swap them unless
2776 // Scale was specified in which case it would be an error.
2777 if (Scale == 0 &&
2778 !(getX86MCRegisterClass(X86::VR128XRegClassID).contains(IndexReg) ||
2779 getX86MCRegisterClass(X86::VR256XRegClassID).contains(IndexReg) ||
2780 getX86MCRegisterClass(X86::VR512RegClassID).contains(IndexReg)) &&
2781 (getX86MCRegisterClass(X86::VR128XRegClassID).contains(BaseReg) ||
2782 getX86MCRegisterClass(X86::VR256XRegClassID).contains(BaseReg) ||
2783 getX86MCRegisterClass(X86::VR512RegClassID).contains(BaseReg)))
2784 std::swap(BaseReg, IndexReg);
2785
2786 if (Scale != 0 &&
2787 getX86MCRegisterClass(X86::GR16RegClassID).contains(IndexReg))
2788 return Error(Start, "16-bit addresses cannot have a scale");
2789
2790 // If there was no explicit scale specified, change it to 1.
2791 if (Scale == 0)
2792 Scale = 1;
2793
2794 // If this is a 16-bit addressing mode with the base and index in the wrong
2795 // order, swap them so CheckBaseRegAndIndexRegAndScale doesn't fail. It is
2796 // shared with att syntax where order matters.
2797 if ((BaseReg == X86::SI || BaseReg == X86::DI) &&
2798 (IndexReg == X86::BX || IndexReg == X86::BP))
2799 std::swap(BaseReg, IndexReg);
2800
2801 if ((BaseReg || IndexReg) &&
2802 CheckBaseRegAndIndexRegAndScale(BaseReg, IndexReg, Scale, is64BitMode(),
2803 ErrMsg))
2804 return Error(Start, ErrMsg);
2805 bool IsUnconditionalBranch =
2806 Name.equals_insensitive("jmp") || Name.equals_insensitive("call");
2807 if (isParsingMSInlineAsm())
2808 return CreateMemForMSInlineAsm(RegNo, Disp, BaseReg, IndexReg, Scale,
2809 IsUnconditionalBranch && is64BitMode(),
2810 Start, End, Size, SM.getSymName(),
2811 SM.getIdentifierInfo(), Operands);
2812
2813 // When parsing x64 MS-style assembly, all non-absolute references to a named
2814 // variable default to RIP-relative.
2815 MCRegister DefaultBaseReg;
2816 bool MaybeDirectBranchDest = true;
2817
2818 if (Parser.isParsingMasm()) {
2819 if (is64BitMode() &&
2820 ((PtrInOperand && !IndexReg) || SM.getElementSize() > 0)) {
2821 DefaultBaseReg = X86::RIP;
2822 }
2823 if (IsUnconditionalBranch) {
2824 if (PtrInOperand) {
2825 MaybeDirectBranchDest = false;
2826 if (is64BitMode())
2827 DefaultBaseReg = X86::RIP;
2828 } else if (!BaseReg && !IndexReg && Disp &&
2829 Disp->getKind() == MCExpr::SymbolRef) {
2830 if (is64BitMode()) {
2831 if (SM.getSize() == 8) {
2832 MaybeDirectBranchDest = false;
2833 DefaultBaseReg = X86::RIP;
2834 }
2835 } else {
2836 if (SM.getSize() == 4 || SM.getSize() == 2)
2837 MaybeDirectBranchDest = false;
2838 }
2839 }
2840 }
2841 } else if (IsUnconditionalBranch) {
2842 // Treat `call [offset fn_ref]` (or `jmp`) syntax as an error.
2843 if (!PtrInOperand && SM.isOffsetOperator())
2844 return Error(
2845 Start, "`OFFSET` operator cannot be used in an unconditional branch");
2846 if (PtrInOperand || SM.isBracketUsed())
2847 MaybeDirectBranchDest = false;
2848 }
2849
2850 if (CheckDispOverflow(BaseReg, IndexReg, Disp, Start))
2851 return true;
2852
2853 if ((BaseReg || IndexReg || RegNo || DefaultBaseReg))
2855 getPointerWidth(), RegNo, Disp, BaseReg, IndexReg, Scale, Start, End,
2856 Size, DefaultBaseReg, /*SymName=*/StringRef(), /*OpDecl=*/nullptr,
2857 /*FrontendSize=*/0, /*UseUpRegs=*/false, MaybeDirectBranchDest));
2858 else
2860 getPointerWidth(), Disp, Start, End, Size, /*SymName=*/StringRef(),
2861 /*OpDecl=*/nullptr, /*FrontendSize=*/0, /*UseUpRegs=*/false,
2862 MaybeDirectBranchDest));
2863 return false;
2864}
2865
2866bool X86AsmParser::parseATTOperand(OperandVector &Operands) {
2867 MCAsmParser &Parser = getParser();
2868 switch (getLexer().getKind()) {
2869 case AsmToken::Dollar: {
2870 // $42 or $ID -> immediate.
2871 SMLoc Start = Parser.getTok().getLoc(), End;
2872 Parser.Lex();
2873 const MCExpr *Val;
2874 // This is an immediate, so we should not parse a register. Do a precheck
2875 // for '%' to supercede intra-register parse errors.
2876 SMLoc L = Parser.getTok().getLoc();
2877 if (check(getLexer().is(AsmToken::Percent), L,
2878 "expected immediate expression") ||
2879 getParser().parseExpression(Val, End) ||
2880 check(isa<X86MCExpr>(Val), L, "expected immediate expression"))
2881 return true;
2882 Operands.push_back(X86Operand::CreateImm(Val, Start, End));
2883 return false;
2884 }
2885 case AsmToken::LCurly: {
2886 SMLoc Start = Parser.getTok().getLoc();
2887 return ParseRoundingModeOp(Start, Operands);
2888 }
2889 default: {
2890 // This a memory operand or a register. We have some parsing complications
2891 // as a '(' may be part of an immediate expression or the addressing mode
2892 // block. This is complicated by the fact that an assembler-level variable
2893 // may refer either to a register or an immediate expression.
2894
2895 SMLoc Loc = Parser.getTok().getLoc(), EndLoc;
2896 const MCExpr *Expr = nullptr;
2897 MCRegister Reg;
2898 if (getLexer().isNot(AsmToken::LParen)) {
2899 // No '(' so this is either a displacement expression or a register.
2900 if (Parser.parseExpression(Expr, EndLoc))
2901 return true;
2902 if (auto *RE = dyn_cast<X86MCExpr>(Expr)) {
2903 // Segment Register. Reset Expr and copy value to register.
2904 Expr = nullptr;
2905 Reg = RE->getReg();
2906
2907 // Check the register.
2908 if (Reg == X86::EIZ || Reg == X86::RIZ)
2909 return Error(
2910 Loc, "%eiz and %riz can only be used as index registers",
2911 SMRange(Loc, EndLoc));
2912 if (Reg == X86::RIP)
2913 return Error(Loc, "%rip can only be used as a base register",
2914 SMRange(Loc, EndLoc));
2915 // Return register that are not segment prefixes immediately.
2916 if (!Parser.parseOptionalToken(AsmToken::Colon)) {
2917 Operands.push_back(X86Operand::CreateReg(Reg, Loc, EndLoc));
2918 return false;
2919 }
2920 if (!getX86MCRegisterClass(X86::SEGMENT_REGRegClassID).contains(Reg))
2921 return Error(Loc, "invalid segment register");
2922 // Accept a '*' absolute memory reference after the segment. Place it
2923 // before the full memory operand.
2924 if (getLexer().is(AsmToken::Star))
2925 Operands.push_back(X86Operand::CreateToken("*", consumeToken()));
2926 }
2927 }
2928 // This is a Memory operand.
2929 return ParseMemOperand(Reg, Expr, Loc, EndLoc, Operands);
2930 }
2931 }
2932}
2933
2934// X86::COND_INVALID if not a recognized condition code or alternate mnemonic,
2935// otherwise the EFLAGS Condition Code enumerator.
2936X86::CondCode X86AsmParser::ParseConditionCode(StringRef CC) {
2937 return StringSwitch<X86::CondCode>(CC)
2938 .Case("o", X86::COND_O) // Overflow
2939 .Case("no", X86::COND_NO) // No Overflow
2940 .Cases({"b", "nae"}, X86::COND_B) // Below/Neither Above nor Equal
2941 .Cases({"ae", "nb"}, X86::COND_AE) // Above or Equal/Not Below
2942 .Cases({"e", "z"}, X86::COND_E) // Equal/Zero
2943 .Cases({"ne", "nz"}, X86::COND_NE) // Not Equal/Not Zero
2944 .Cases({"be", "na"}, X86::COND_BE) // Below or Equal/Not Above
2945 .Cases({"a", "nbe"}, X86::COND_A) // Above/Neither Below nor Equal
2946 .Case("s", X86::COND_S) // Sign
2947 .Case("ns", X86::COND_NS) // No Sign
2948 .Cases({"p", "pe"}, X86::COND_P) // Parity/Parity Even
2949 .Cases({"np", "po"}, X86::COND_NP) // No Parity/Parity Odd
2950 .Cases({"l", "nge"}, X86::COND_L) // Less/Neither Greater nor Equal
2951 .Cases({"ge", "nl"}, X86::COND_GE) // Greater or Equal/Not Less
2952 .Cases({"le", "ng"}, X86::COND_LE) // Less or Equal/Not Greater
2953 .Cases({"g", "nle"}, X86::COND_G) // Greater/Neither Less nor Equal
2955}
2956
2957// true on failure, false otherwise
2958// If no {z} mark was found - Parser doesn't advance
2959bool X86AsmParser::ParseZ(std::unique_ptr<X86Operand> &Z, SMLoc StartLoc) {
2960 MCAsmParser &Parser = getParser();
2961 // Assuming we are just pass the '{' mark, quering the next token
2962 // Searched for {z}, but none was found. Return false, as no parsing error was
2963 // encountered
2964 if (!(getLexer().is(AsmToken::Identifier) &&
2965 (getLexer().getTok().getIdentifier() == "z")))
2966 return false;
2967 Parser.Lex(); // Eat z
2968 // Query and eat the '}' mark
2969 if (!getLexer().is(AsmToken::RCurly))
2970 return Error(getLexer().getLoc(), "Expected } at this point");
2971 Parser.Lex(); // Eat '}'
2972 // Assign Z with the {z} mark operand
2973 Z = X86Operand::CreateToken("{z}", StartLoc);
2974 return false;
2975}
2976
2977// true on failure, false otherwise
2978bool X86AsmParser::HandleAVX512Operand(OperandVector &Operands) {
2979 MCAsmParser &Parser = getParser();
2980 if (getLexer().is(AsmToken::LCurly)) {
2981 // Eat "{" and mark the current place.
2982 const SMLoc consumedToken = consumeToken();
2983 // Distinguish {1to<NUM>} from {%k<NUM>}.
2984 if(getLexer().is(AsmToken::Integer)) {
2985 // Parse memory broadcasting ({1to<NUM>}).
2986 if (getLexer().getTok().getIntVal() != 1)
2987 return TokError("Expected 1to<NUM> at this point");
2988 StringRef Prefix = getLexer().getTok().getString();
2989 Parser.Lex(); // Eat first token of 1to8
2990 if (!getLexer().is(AsmToken::Identifier))
2991 return TokError("Expected 1to<NUM> at this point");
2992 // Recognize only reasonable suffixes.
2993 SmallVector<char, 5> BroadcastVector;
2994 StringRef BroadcastString = (Prefix + getLexer().getTok().getIdentifier())
2995 .toStringRef(BroadcastVector);
2996 if (!BroadcastString.starts_with("1to"))
2997 return TokError("Expected 1to<NUM> at this point");
2998 const char *BroadcastPrimitive =
2999 StringSwitch<const char *>(BroadcastString)
3000 .Case("1to2", "{1to2}")
3001 .Case("1to4", "{1to4}")
3002 .Case("1to8", "{1to8}")
3003 .Case("1to16", "{1to16}")
3004 .Case("1to32", "{1to32}")
3005 .Default(nullptr);
3006 if (!BroadcastPrimitive)
3007 return TokError("Invalid memory broadcast primitive.");
3008 Parser.Lex(); // Eat trailing token of 1toN
3009 if (!getLexer().is(AsmToken::RCurly))
3010 return TokError("Expected } at this point");
3011 Parser.Lex(); // Eat "}"
3012 Operands.push_back(X86Operand::CreateToken(BroadcastPrimitive,
3013 consumedToken));
3014 // No AVX512 specific primitives can pass
3015 // after memory broadcasting, so return.
3016 return false;
3017 } else {
3018 // Parse either {k}{z}, {z}{k}, {k} or {z}
3019 // last one have no meaning, but GCC accepts it
3020 // Currently, we're just pass a '{' mark
3021 std::unique_ptr<X86Operand> Z;
3022 if (ParseZ(Z, consumedToken))
3023 return true;
3024 // Reaching here means that parsing of the allegadly '{z}' mark yielded
3025 // no errors.
3026 // Query for the need of further parsing for a {%k<NUM>} mark
3027 if (!Z || getLexer().is(AsmToken::LCurly)) {
3028 SMLoc StartLoc = Z ? consumeToken() : consumedToken;
3029 // Parse an op-mask register mark ({%k<NUM>}), which is now to be
3030 // expected
3031 MCRegister RegNo;
3032 SMLoc RegLoc;
3033 if (!parseRegister(RegNo, RegLoc, StartLoc) &&
3034 getX86MCRegisterClass(X86::VK1RegClassID).contains(RegNo)) {
3035 if (RegNo == X86::K0)
3036 return Error(RegLoc, "Register k0 can't be used as write mask");
3037 if (!getLexer().is(AsmToken::RCurly))
3038 return Error(getLexer().getLoc(), "Expected } at this point");
3039 Operands.push_back(X86Operand::CreateToken("{", StartLoc));
3040 Operands.push_back(
3041 X86Operand::CreateReg(RegNo, StartLoc, StartLoc));
3042 Operands.push_back(X86Operand::CreateToken("}", consumeToken()));
3043 } else
3044 return Error(getLexer().getLoc(),
3045 "Expected an op-mask register at this point");
3046 // {%k<NUM>} mark is found, inquire for {z}
3047 if (getLexer().is(AsmToken::LCurly) && !Z) {
3048 // Have we've found a parsing error, or found no (expected) {z} mark
3049 // - report an error
3050 if (ParseZ(Z, consumeToken()) || !Z)
3051 return Error(getLexer().getLoc(),
3052 "Expected a {z} mark at this point");
3053
3054 }
3055 // '{z}' on its own is meaningless, hence should be ignored.
3056 // on the contrary - have it been accompanied by a K register,
3057 // allow it.
3058 if (Z)
3059 Operands.push_back(std::move(Z));
3060 }
3061 }
3062 }
3063 return false;
3064}
3065
3066/// Returns false if okay and true if there was an overflow.
3067bool X86AsmParser::CheckDispOverflow(MCRegister BaseReg, MCRegister IndexReg,
3068 const MCExpr *Disp, SMLoc Loc) {
3069 // If the displacement is a constant, check overflows. For 64-bit addressing,
3070 // gas requires isInt<32> and otherwise reports an error. For others, gas
3071 // reports a warning and allows a wider range. E.g. gas allows
3072 // [-0xffffffff,0xffffffff] for 32-bit addressing (e.g. Linux kernel uses
3073 // `leal -__PAGE_OFFSET(%ecx),%esp` where __PAGE_OFFSET is 0xc0000000).
3074 if (BaseReg || IndexReg) {
3075 if (auto CE = dyn_cast<MCConstantExpr>(Disp)) {
3076 auto Imm = CE->getValue();
3077 bool Is64 =
3078 getX86MCRegisterClass(X86::GR64RegClassID).contains(BaseReg) ||
3079 getX86MCRegisterClass(X86::GR64RegClassID).contains(IndexReg);
3080 bool Is16 = getX86MCRegisterClass(X86::GR16RegClassID).contains(BaseReg);
3081 if (Is64) {
3082 if (!isInt<32>(Imm))
3083 return Error(Loc, "displacement " + Twine(Imm) +
3084 " is not within [-2147483648, 2147483647]");
3085 } else if (!Is16) {
3086 if (!isUInt<32>(Imm < 0 ? -uint64_t(Imm) : uint64_t(Imm))) {
3087 Warning(Loc, "displacement " + Twine(Imm) +
3088 " shortened to 32-bit signed " +
3089 Twine(static_cast<int32_t>(Imm)));
3090 }
3091 } else if (!isUInt<16>(Imm < 0 ? -uint64_t(Imm) : uint64_t(Imm))) {
3092 Warning(Loc, "displacement " + Twine(Imm) +
3093 " shortened to 16-bit signed " +
3094 Twine(static_cast<int16_t>(Imm)));
3095 }
3096 }
3097 }
3098 return false;
3099}
3100
3101/// ParseMemOperand: 'seg : disp(basereg, indexreg, scale)'. The '%ds:' prefix
3102/// has already been parsed if present. disp may be provided as well.
3103bool X86AsmParser::ParseMemOperand(MCRegister SegReg, const MCExpr *Disp,
3104 SMLoc StartLoc, SMLoc EndLoc,
3105 OperandVector &Operands) {
3106 MCAsmParser &Parser = getParser();
3107 SMLoc Loc;
3108 // Based on the initial passed values, we may be in any of these cases, we are
3109 // in one of these cases (with current position (*)):
3110
3111 // 1. seg : * disp (base-index-scale-expr)
3112 // 2. seg : *(disp) (base-index-scale-expr)
3113 // 3. seg : *(base-index-scale-expr)
3114 // 4. disp *(base-index-scale-expr)
3115 // 5. *(disp) (base-index-scale-expr)
3116 // 6. *(base-index-scale-expr)
3117 // 7. disp *
3118 // 8. *(disp)
3119
3120 // If we do not have an displacement yet, check if we're in cases 4 or 6 by
3121 // checking if the first object after the parenthesis is a register (or an
3122 // identifier referring to a register) and parse the displacement or default
3123 // to 0 as appropriate.
3124 auto isAtMemOperand = [this]() {
3125 if (this->getLexer().isNot(AsmToken::LParen))
3126 return false;
3127 AsmToken Buf[2];
3128 StringRef Id;
3129 auto TokCount = this->getLexer().peekTokens(Buf, true);
3130 if (TokCount == 0)
3131 return false;
3132 switch (Buf[0].getKind()) {
3133 case AsmToken::Percent:
3134 case AsmToken::Comma:
3135 return true;
3136 // These lower cases are doing a peekIdentifier.
3137 case AsmToken::At:
3138 case AsmToken::Dollar:
3139 if ((TokCount > 1) &&
3140 (Buf[1].is(AsmToken::Identifier) || Buf[1].is(AsmToken::String)) &&
3141 (Buf[0].getLoc().getPointer() + 1 == Buf[1].getLoc().getPointer()))
3142 Id = StringRef(Buf[0].getLoc().getPointer(),
3143 Buf[1].getIdentifier().size() + 1);
3144 break;
3146 case AsmToken::String:
3147 Id = Buf[0].getIdentifier();
3148 break;
3149 default:
3150 return false;
3151 }
3152 // We have an ID. Check if it is bound to a register.
3153 if (!Id.empty()) {
3154 MCSymbol *Sym = this->getContext().getOrCreateSymbol(Id);
3155 if (Sym->isVariable()) {
3156 auto V = Sym->getVariableValue();
3157 return isa<X86MCExpr>(V);
3158 }
3159 }
3160 return false;
3161 };
3162
3163 if (!Disp) {
3164 // Parse immediate if we're not at a mem operand yet.
3165 if (!isAtMemOperand()) {
3166 if (Parser.parseTokenLoc(Loc) || Parser.parseExpression(Disp, EndLoc))
3167 return true;
3168 assert(!isa<X86MCExpr>(Disp) && "Expected non-register here.");
3169 } else {
3170 // Disp is implicitly zero if we haven't parsed it yet.
3171 Disp = MCConstantExpr::create(0, Parser.getContext());
3172 }
3173 }
3174
3175 // We are now either at the end of the operand or at the '(' at the start of a
3176 // base-index-scale-expr.
3177
3178 if (!parseOptionalToken(AsmToken::LParen)) {
3179 if (!SegReg)
3180 Operands.push_back(
3181 X86Operand::CreateMem(getPointerWidth(), Disp, StartLoc, EndLoc));
3182 else
3183 Operands.push_back(X86Operand::CreateMem(getPointerWidth(), SegReg, Disp,
3184 0, 0, 1, StartLoc, EndLoc));
3185 return false;
3186 }
3187
3188 // If we reached here, then eat the '(' and Process
3189 // the rest of the memory operand.
3190 MCRegister BaseReg, IndexReg;
3191 unsigned Scale = 1;
3192 SMLoc BaseLoc = getLexer().getLoc();
3193 const MCExpr *E;
3194 StringRef ErrMsg;
3195
3196 // Parse BaseReg if one is provided.
3197 if (getLexer().isNot(AsmToken::Comma) && getLexer().isNot(AsmToken::RParen)) {
3198 if (Parser.parseExpression(E, EndLoc) ||
3199 check(!isa<X86MCExpr>(E), BaseLoc, "expected register here"))
3200 return true;
3201
3202 // Check the register.
3203 BaseReg = cast<X86MCExpr>(E)->getReg();
3204 if (BaseReg == X86::EIZ || BaseReg == X86::RIZ)
3205 return Error(BaseLoc, "eiz and riz can only be used as index registers",
3206 SMRange(BaseLoc, EndLoc));
3207 }
3208
3209 if (parseOptionalToken(AsmToken::Comma)) {
3210 // Following the comma we should have either an index register, or a scale
3211 // value. We don't support the later form, but we want to parse it
3212 // correctly.
3213 //
3214 // Even though it would be completely consistent to support syntax like
3215 // "1(%eax,,1)", the assembler doesn't. Use "eiz" or "riz" for this.
3216 if (getLexer().isNot(AsmToken::RParen)) {
3217 if (Parser.parseTokenLoc(Loc) || Parser.parseExpression(E, EndLoc))
3218 return true;
3219
3220 if (!isa<X86MCExpr>(E)) {
3221 // We've parsed an unexpected Scale Value instead of an index
3222 // register. Interpret it as an absolute.
3223 int64_t ScaleVal;
3224 if (!E->evaluateAsAbsolute(ScaleVal, getStreamer().getAssemblerPtr()))
3225 return Error(Loc, "expected absolute expression");
3226 if (ScaleVal != 1)
3227 Warning(Loc, "scale factor without index register is ignored");
3228 Scale = 1;
3229 } else { // IndexReg Found.
3230 IndexReg = cast<X86MCExpr>(E)->getReg();
3231
3232 if (BaseReg == X86::RIP)
3233 return Error(Loc,
3234 "%rip as base register can not have an index register");
3235 if (IndexReg == X86::RIP)
3236 return Error(Loc, "%rip is not allowed as an index register");
3237
3238 if (parseOptionalToken(AsmToken::Comma)) {
3239 // Parse the scale amount:
3240 // ::= ',' [scale-expression]
3241
3242 // A scale amount without an index is ignored.
3243 if (getLexer().isNot(AsmToken::RParen)) {
3244 int64_t ScaleVal;
3245 if (Parser.parseTokenLoc(Loc) ||
3246 Parser.parseAbsoluteExpression(ScaleVal))
3247 return Error(Loc, "expected scale expression");
3248 Scale = (unsigned)ScaleVal;
3249 // Validate the scale amount.
3250 if (getX86MCRegisterClass(X86::GR16RegClassID).contains(BaseReg) &&
3251 Scale != 1)
3252 return Error(Loc, "scale factor in 16-bit address must be 1");
3253 if (checkScale(Scale, ErrMsg))
3254 return Error(Loc, ErrMsg);
3255 }
3256 }
3257 }
3258 }
3259 }
3260
3261 // Ok, we've eaten the memory operand, verify we have a ')' and eat it too.
3262 if (parseToken(AsmToken::RParen, "unexpected token in memory operand"))
3263 return true;
3264
3265 // This is to support otherwise illegal operand (%dx) found in various
3266 // unofficial manuals examples (e.g. "out[s]?[bwl]? %al, (%dx)") and must now
3267 // be supported. Mark such DX variants separately fix only in special cases.
3268 if (BaseReg == X86::DX && !IndexReg && Scale == 1 && !SegReg &&
3269 isa<MCConstantExpr>(Disp) &&
3270 cast<MCConstantExpr>(Disp)->getValue() == 0) {
3271 Operands.push_back(X86Operand::CreateDXReg(BaseLoc, BaseLoc));
3272 return false;
3273 }
3274
3275 if (CheckBaseRegAndIndexRegAndScale(BaseReg, IndexReg, Scale, is64BitMode(),
3276 ErrMsg))
3277 return Error(BaseLoc, ErrMsg);
3278
3279 if (CheckDispOverflow(BaseReg, IndexReg, Disp, BaseLoc))
3280 return true;
3281
3282 if (SegReg || BaseReg || IndexReg)
3283 Operands.push_back(X86Operand::CreateMem(getPointerWidth(), SegReg, Disp,
3284 BaseReg, IndexReg, Scale, StartLoc,
3285 EndLoc));
3286 else
3287 Operands.push_back(
3288 X86Operand::CreateMem(getPointerWidth(), Disp, StartLoc, EndLoc));
3289 return false;
3290}
3291
3292// Parse either a standard primary expression or a register.
3293bool X86AsmParser::parsePrimaryExpr(const MCExpr *&Res, SMLoc &EndLoc) {
3294 MCAsmParser &Parser = getParser();
3295 // See if this is a register first.
3296 if (getTok().is(AsmToken::Percent) ||
3297 (isParsingIntelSyntax() && getTok().is(AsmToken::Identifier) &&
3298 MatchRegisterName(Parser.getTok().getString()))) {
3299 SMLoc StartLoc = Parser.getTok().getLoc();
3300 MCRegister RegNo;
3301 if (parseRegister(RegNo, StartLoc, EndLoc))
3302 return true;
3303 Res = X86MCExpr::create(RegNo, Parser.getContext());
3304 return false;
3305 }
3306 return Parser.parsePrimaryExpr(Res, EndLoc, nullptr);
3307}
3308
3309bool X86AsmParser::parseInstruction(ParseInstructionInfo &Info, StringRef Name,
3310 SMLoc NameLoc, OperandVector &Operands) {
3311 MCAsmParser &Parser = getParser();
3312 InstInfo = &Info;
3313
3314 // Reset the forced VEX encoding.
3315 ForcedOpcodePrefix = OpcodePrefix_Default;
3316 ForcedDispEncoding = DispEncoding_Default;
3317 UseApxExtendedReg = false;
3318 ForcedNoFlag = false;
3319
3320 // Parse pseudo prefixes.
3321 while (true) {
3322 if (Name == "{") {
3323 if (getLexer().isNot(AsmToken::Identifier))
3324 return Error(Parser.getTok().getLoc(), "Unexpected token after '{'");
3325 std::string Prefix = Parser.getTok().getString().lower();
3326 Parser.Lex(); // Eat identifier.
3327 if (getLexer().isNot(AsmToken::RCurly))
3328 return Error(Parser.getTok().getLoc(), "Expected '}'");
3329 Parser.Lex(); // Eat curly.
3330
3331 if (Prefix == "rex")
3332 ForcedOpcodePrefix = OpcodePrefix_REX;
3333 else if (Prefix == "rex2")
3334 ForcedOpcodePrefix = OpcodePrefix_REX2;
3335 else if (Prefix == "vex")
3336 ForcedOpcodePrefix = OpcodePrefix_VEX;
3337 else if (Prefix == "vex2")
3338 ForcedOpcodePrefix = OpcodePrefix_VEX2;
3339 else if (Prefix == "vex3")
3340 ForcedOpcodePrefix = OpcodePrefix_VEX3;
3341 else if (Prefix == "evex")
3342 ForcedOpcodePrefix = OpcodePrefix_EVEX;
3343 else if (Prefix == "disp8")
3344 ForcedDispEncoding = DispEncoding_Disp8;
3345 else if (Prefix == "disp32")
3346 ForcedDispEncoding = DispEncoding_Disp32;
3347 else if (Prefix == "nf")
3348 ForcedNoFlag = true;
3349 else
3350 return Error(NameLoc, "unknown prefix");
3351
3352 NameLoc = Parser.getTok().getLoc();
3353 if (getLexer().is(AsmToken::LCurly)) {
3354 Parser.Lex();
3355 Name = "{";
3356 } else {
3357 if (getLexer().isNot(AsmToken::Identifier))
3358 return Error(Parser.getTok().getLoc(), "Expected identifier");
3359 // FIXME: The mnemonic won't match correctly if its not in lower case.
3360 Name = Parser.getTok().getString();
3361 Parser.Lex();
3362 }
3363 continue;
3364 }
3365 // Parse MASM style pseudo prefixes.
3366 if (isParsingMSInlineAsm()) {
3367 if (Name.equals_insensitive("vex"))
3368 ForcedOpcodePrefix = OpcodePrefix_VEX;
3369 else if (Name.equals_insensitive("vex2"))
3370 ForcedOpcodePrefix = OpcodePrefix_VEX2;
3371 else if (Name.equals_insensitive("vex3"))
3372 ForcedOpcodePrefix = OpcodePrefix_VEX3;
3373 else if (Name.equals_insensitive("evex"))
3374 ForcedOpcodePrefix = OpcodePrefix_EVEX;
3375
3376 if (ForcedOpcodePrefix != OpcodePrefix_Default) {
3377 if (getLexer().isNot(AsmToken::Identifier))
3378 return Error(Parser.getTok().getLoc(), "Expected identifier");
3379 // FIXME: The mnemonic won't match correctly if its not in lower case.
3380 Name = Parser.getTok().getString();
3381 NameLoc = Parser.getTok().getLoc();
3382 Parser.Lex();
3383 }
3384 }
3385 break;
3386 }
3387
3388 // Support the suffix syntax for overriding displacement size as well.
3389 if (Name.consume_back(".d32")) {
3390 ForcedDispEncoding = DispEncoding_Disp32;
3391 } else if (Name.consume_back(".d8")) {
3392 ForcedDispEncoding = DispEncoding_Disp8;
3393 }
3394
3395 StringRef PatchedName = Name;
3396
3397 // Hack to skip "short" following Jcc.
3398 if (isParsingIntelSyntax() &&
3399 (PatchedName == "jmp" || PatchedName == "jc" || PatchedName == "jnc" ||
3400 PatchedName == "jcxz" || PatchedName == "jecxz" ||
3401 (PatchedName.starts_with("j") &&
3402 ParseConditionCode(PatchedName.substr(1)) != X86::COND_INVALID))) {
3403 StringRef NextTok = Parser.getTok().getString();
3404 if (Parser.isParsingMasm() ? NextTok.equals_insensitive("short")
3405 : NextTok == "short") {
3406 SMLoc NameEndLoc =
3407 NameLoc.getFromPointer(NameLoc.getPointer() + Name.size());
3408 // Eat the short keyword.
3409 Parser.Lex();
3410 // MS and GAS ignore the short keyword; they both determine the jmp type
3411 // based on the distance of the label. (NASM does emit different code with
3412 // and without "short," though.)
3413 InstInfo->AsmRewrites->emplace_back(AOK_Skip, NameEndLoc,
3414 NextTok.size() + 1);
3415 }
3416 }
3417
3418 // FIXME: Hack to recognize setneb as setne.
3419 if (PatchedName.starts_with("set") && PatchedName.ends_with("b") &&
3420 PatchedName != "setzub" && PatchedName != "setzunb" &&
3421 PatchedName != "setb" && PatchedName != "setnb")
3422 PatchedName = PatchedName.substr(0, Name.size()-1);
3423
3424 unsigned ComparisonPredicate = ~0U;
3425
3426 // FIXME: Hack to recognize cmp<comparison code>{sh,ss,sd,ph,ps,pd}.
3427 if ((PatchedName.starts_with("cmp") || PatchedName.starts_with("vcmp")) &&
3428 (PatchedName.ends_with("ss") || PatchedName.ends_with("sd") ||
3429 PatchedName.ends_with("sh") || PatchedName.ends_with("ph") ||
3430 PatchedName.ends_with("bf16") || PatchedName.ends_with("ps") ||
3431 PatchedName.ends_with("pd"))) {
3432 bool IsVCMP = PatchedName[0] == 'v';
3433 unsigned CCIdx = IsVCMP ? 4 : 3;
3434 unsigned suffixLength = PatchedName.ends_with("bf16") ? 5 : 2;
3435 unsigned CC = StringSwitch<unsigned>(
3436 PatchedName.slice(CCIdx, PatchedName.size() - suffixLength))
3437 .Case("eq", 0x00)
3438 .Case("eq_oq", 0x00)
3439 .Case("lt", 0x01)
3440 .Case("lt_os", 0x01)
3441 .Case("le", 0x02)
3442 .Case("le_os", 0x02)
3443 .Case("unord", 0x03)
3444 .Case("unord_q", 0x03)
3445 .Case("neq", 0x04)
3446 .Case("neq_uq", 0x04)
3447 .Case("nlt", 0x05)
3448 .Case("nlt_us", 0x05)
3449 .Case("nle", 0x06)
3450 .Case("nle_us", 0x06)
3451 .Case("ord", 0x07)
3452 .Case("ord_q", 0x07)
3453 /* AVX only from here */
3454 .Case("eq_uq", 0x08)
3455 .Case("nge", 0x09)
3456 .Case("nge_us", 0x09)
3457 .Case("ngt", 0x0A)
3458 .Case("ngt_us", 0x0A)
3459 .Case("false", 0x0B)
3460 .Case("false_oq", 0x0B)
3461 .Case("neq_oq", 0x0C)
3462 .Case("ge", 0x0D)
3463 .Case("ge_os", 0x0D)
3464 .Case("gt", 0x0E)
3465 .Case("gt_os", 0x0E)
3466 .Case("true", 0x0F)
3467 .Case("true_uq", 0x0F)
3468 .Case("eq_os", 0x10)
3469 .Case("lt_oq", 0x11)
3470 .Case("le_oq", 0x12)
3471 .Case("unord_s", 0x13)
3472 .Case("neq_us", 0x14)
3473 .Case("nlt_uq", 0x15)
3474 .Case("nle_uq", 0x16)
3475 .Case("ord_s", 0x17)
3476 .Case("eq_us", 0x18)
3477 .Case("nge_uq", 0x19)
3478 .Case("ngt_uq", 0x1A)
3479 .Case("false_os", 0x1B)
3480 .Case("neq_os", 0x1C)
3481 .Case("ge_oq", 0x1D)
3482 .Case("gt_oq", 0x1E)
3483 .Case("true_us", 0x1F)
3484 .Default(~0U);
3485 if (CC != ~0U && (IsVCMP || CC < 8) &&
3486 (IsVCMP || PatchedName.back() != 'h')) {
3487 if (PatchedName.ends_with("ss"))
3488 PatchedName = IsVCMP ? "vcmpss" : "cmpss";
3489 else if (PatchedName.ends_with("sd"))
3490 PatchedName = IsVCMP ? "vcmpsd" : "cmpsd";
3491 else if (PatchedName.ends_with("ps"))
3492 PatchedName = IsVCMP ? "vcmpps" : "cmpps";
3493 else if (PatchedName.ends_with("pd"))
3494 PatchedName = IsVCMP ? "vcmppd" : "cmppd";
3495 else if (PatchedName.ends_with("sh"))
3496 PatchedName = "vcmpsh";
3497 else if (PatchedName.ends_with("ph"))
3498 PatchedName = "vcmpph";
3499 else if (PatchedName.ends_with("bf16"))
3500 PatchedName = "vcmpbf16";
3501 else
3502 llvm_unreachable("Unexpected suffix!");
3503
3504 ComparisonPredicate = CC;
3505 }
3506 }
3507
3508 // FIXME: Hack to recognize vpcmp<comparison code>{ub,uw,ud,uq,b,w,d,q}.
3509 if (PatchedName.starts_with("vpcmp") &&
3510 (PatchedName.back() == 'b' || PatchedName.back() == 'w' ||
3511 PatchedName.back() == 'd' || PatchedName.back() == 'q')) {
3512 unsigned SuffixSize = PatchedName.drop_back().back() == 'u' ? 2 : 1;
3513 unsigned CC = StringSwitch<unsigned>(
3514 PatchedName.slice(5, PatchedName.size() - SuffixSize))
3515 .Case("eq", 0x0) // Only allowed on unsigned. Checked below.
3516 .Case("lt", 0x1)
3517 .Case("le", 0x2)
3518 //.Case("false", 0x3) // Not a documented alias.
3519 .Case("neq", 0x4)
3520 .Case("nlt", 0x5)
3521 .Case("nle", 0x6)
3522 //.Case("true", 0x7) // Not a documented alias.
3523 .Default(~0U);
3524 if (CC != ~0U && (CC != 0 || SuffixSize == 2)) {
3525 switch (PatchedName.back()) {
3526 default: llvm_unreachable("Unexpected character!");
3527 case 'b': PatchedName = SuffixSize == 2 ? "vpcmpub" : "vpcmpb"; break;
3528 case 'w': PatchedName = SuffixSize == 2 ? "vpcmpuw" : "vpcmpw"; break;
3529 case 'd': PatchedName = SuffixSize == 2 ? "vpcmpud" : "vpcmpd"; break;
3530 case 'q': PatchedName = SuffixSize == 2 ? "vpcmpuq" : "vpcmpq"; break;
3531 }
3532 // Set up the immediate to push into the operands later.
3533 ComparisonPredicate = CC;
3534 }
3535 }
3536
3537 // FIXME: Hack to recognize vpcom<comparison code>{ub,uw,ud,uq,b,w,d,q}.
3538 if (PatchedName.starts_with("vpcom") &&
3539 (PatchedName.back() == 'b' || PatchedName.back() == 'w' ||
3540 PatchedName.back() == 'd' || PatchedName.back() == 'q')) {
3541 unsigned SuffixSize = PatchedName.drop_back().back() == 'u' ? 2 : 1;
3542 unsigned CC = StringSwitch<unsigned>(
3543 PatchedName.slice(5, PatchedName.size() - SuffixSize))
3544 .Case("lt", 0x0)
3545 .Case("le", 0x1)
3546 .Case("gt", 0x2)
3547 .Case("ge", 0x3)
3548 .Case("eq", 0x4)
3549 .Case("neq", 0x5)
3550 .Case("false", 0x6)
3551 .Case("true", 0x7)
3552 .Default(~0U);
3553 if (CC != ~0U) {
3554 switch (PatchedName.back()) {
3555 default: llvm_unreachable("Unexpected character!");
3556 case 'b': PatchedName = SuffixSize == 2 ? "vpcomub" : "vpcomb"; break;
3557 case 'w': PatchedName = SuffixSize == 2 ? "vpcomuw" : "vpcomw"; break;
3558 case 'd': PatchedName = SuffixSize == 2 ? "vpcomud" : "vpcomd"; break;
3559 case 'q': PatchedName = SuffixSize == 2 ? "vpcomuq" : "vpcomq"; break;
3560 }
3561 // Set up the immediate to push into the operands later.
3562 ComparisonPredicate = CC;
3563 }
3564 }
3565
3566 // Determine whether this is an instruction prefix.
3567 // FIXME:
3568 // Enhance prefixes integrity robustness. for example, following forms
3569 // are currently tolerated:
3570 // repz repnz <insn> ; GAS errors for the use of two similar prefixes
3571 // lock addq %rax, %rbx ; Destination operand must be of memory type
3572 // xacquire <insn> ; xacquire must be accompanied by 'lock'
3573 bool IsPrefix =
3574 StringSwitch<bool>(Name)
3575 .Cases({"cs", "ds", "es", "fs", "gs", "ss"}, true)
3576 .Cases({"rex64", "data32", "data16", "addr32", "addr16"}, true)
3577 .Cases({"xacquire", "xrelease"}, true)
3578 .Cases({"acquire", "release"}, isParsingIntelSyntax())
3579 .Default(false);
3580
3581 auto isLockRepeatNtPrefix = [](StringRef N) {
3582 return StringSwitch<bool>(N)
3583 .Cases({"lock", "rep", "repe", "repz", "repne", "repnz", "notrack"},
3584 true)
3585 .Default(false);
3586 };
3587
3588 bool CurlyAsEndOfStatement = false;
3589
3590 unsigned Flags = X86::IP_NO_PREFIX;
3591 while (isLockRepeatNtPrefix(Name.lower())) {
3592 unsigned Prefix =
3593 StringSwitch<unsigned>(Name)
3594 .Case("lock", X86::IP_HAS_LOCK)
3595 .Cases({"rep", "repe", "repz"}, X86::IP_HAS_REPEAT)
3596 .Cases({"repne", "repnz"}, X86::IP_HAS_REPEAT_NE)
3597 .Case("notrack", X86::IP_HAS_NOTRACK)
3598 .Default(X86::IP_NO_PREFIX); // Invalid prefix (impossible)
3599 Flags |= Prefix;
3600 if (getLexer().is(AsmToken::EndOfStatement)) {
3601 // We don't have real instr with the given prefix
3602 // let's use the prefix as the instr.
3603 // TODO: there could be several prefixes one after another
3605 break;
3606 }
3607 // FIXME: The mnemonic won't match correctly if its not in lower case.
3608 Name = Parser.getTok().getString();
3609 Parser.Lex(); // eat the prefix
3610 // Hack: we could have something like "rep # some comment" or
3611 // "lock; cmpxchg16b $1" or "lock\0A\09incl" or "lock/incl"
3612 while (Name.starts_with(";") || Name.starts_with("\n") ||
3613 Name.starts_with("#") || Name.starts_with("\t") ||
3614 Name.starts_with("/")) {
3615 // FIXME: The mnemonic won't match correctly if its not in lower case.
3616 Name = Parser.getTok().getString();
3617 Parser.Lex(); // go to next prefix or instr
3618 }
3619 }
3620
3621 if (Flags)
3622 PatchedName = Name;
3623
3624 // Hacks to handle 'data16' and 'data32'
3625 if (PatchedName == "data16" && is16BitMode()) {
3626 return Error(NameLoc, "redundant data16 prefix");
3627 }
3628 if (PatchedName == "data32") {
3629 if (is32BitMode())
3630 return Error(NameLoc, "redundant data32 prefix");
3631 if (is64BitMode())
3632 return Error(NameLoc, "'data32' is not supported in 64-bit mode");
3633 // Hack to 'data16' for the table lookup.
3634 PatchedName = "data16";
3635
3636 if (getLexer().isNot(AsmToken::EndOfStatement)) {
3637 StringRef Next = Parser.getTok().getString();
3638 getLexer().Lex();
3639 // data32 effectively changes the instruction suffix.
3640 // TODO Generalize.
3641 if (Next == "callw")
3642 Next = "calll";
3643 if (Next == "ljmpw")
3644 Next = "ljmpl";
3645
3646 Name = Next;
3647 PatchedName = Name;
3648 ForcedDataPrefix = X86::Is32Bit;
3649 IsPrefix = false;
3650 }
3651 }
3652
3653 Operands.push_back(X86Operand::CreateToken(PatchedName, NameLoc));
3654
3655 // Push the immediate if we extracted one from the mnemonic.
3656 if (ComparisonPredicate != ~0U && !isParsingIntelSyntax()) {
3657 const MCExpr *ImmOp = MCConstantExpr::create(ComparisonPredicate,
3658 getParser().getContext());
3659 Operands.push_back(X86Operand::CreateImm(ImmOp, NameLoc, NameLoc));
3660 }
3661
3662 // Parse condtional flags after mnemonic.
3663 if ((Name.starts_with("ccmp") || Name.starts_with("ctest")) &&
3664 parseCFlagsOp(Operands))
3665 return true;
3666
3667 // This does the actual operand parsing. Don't parse any more if we have a
3668 // prefix juxtaposed with an operation like "lock incl 4(%rax)", because we
3669 // just want to parse the "lock" as the first instruction and the "incl" as
3670 // the next one.
3671 if (getLexer().isNot(AsmToken::EndOfStatement) && !IsPrefix) {
3672 // Parse '*' modifier.
3673 if (getLexer().is(AsmToken::Star))
3674 Operands.push_back(X86Operand::CreateToken("*", consumeToken()));
3675
3676 // Read the operands.
3677 while (true) {
3678 if (parseOperand(Operands, Name))
3679 return true;
3680 if (HandleAVX512Operand(Operands))
3681 return true;
3682
3683 // check for comma and eat it
3684 if (getLexer().is(AsmToken::Comma))
3685 Parser.Lex();
3686 else
3687 break;
3688 }
3689
3690 // In MS inline asm curly braces mark the beginning/end of a block,
3691 // therefore they should be interepreted as end of statement
3692 CurlyAsEndOfStatement =
3693 isParsingIntelSyntax() && isParsingMSInlineAsm() &&
3694 (getLexer().is(AsmToken::LCurly) || getLexer().is(AsmToken::RCurly));
3695 if (getLexer().isNot(AsmToken::EndOfStatement) && !CurlyAsEndOfStatement)
3696 return TokError("unexpected token in argument list");
3697 }
3698
3699 // Push the immediate if we extracted one from the mnemonic.
3700 if (ComparisonPredicate != ~0U && isParsingIntelSyntax()) {
3701 const MCExpr *ImmOp = MCConstantExpr::create(ComparisonPredicate,
3702 getParser().getContext());
3703 Operands.push_back(X86Operand::CreateImm(ImmOp, NameLoc, NameLoc));
3704 }
3705
3706 // Consume the EndOfStatement or the prefix separator Slash
3707 if (getLexer().is(AsmToken::EndOfStatement) ||
3708 (IsPrefix && getLexer().is(AsmToken::Slash)))
3709 Parser.Lex();
3710 else if (CurlyAsEndOfStatement)
3711 // Add an actual EndOfStatement before the curly brace
3712 Info.AsmRewrites->emplace_back(AOK_EndOfStatement,
3713 getLexer().getTok().getLoc(), 0);
3714
3715 // This is for gas compatibility and cannot be done in td.
3716 // Adding "p" for some floating point with no argument.
3717 // For example: fsub --> fsubp
3718 bool IsFp =
3719 Name == "fsub" || Name == "fdiv" || Name == "fsubr" || Name == "fdivr";
3720 if (IsFp && Operands.size() == 1) {
3721 const char *Repl = StringSwitch<const char *>(Name)
3722 .Case("fsub", "fsubp")
3723 .Case("fdiv", "fdivp")
3724 .Case("fsubr", "fsubrp")
3725 .Case("fdivr", "fdivrp");
3726 static_cast<X86Operand &>(*Operands[0]).setTokenValue(Repl);
3727 }
3728
3729 if ((Name == "mov" || Name == "movw" || Name == "movl") &&
3730 (Operands.size() == 3)) {
3731 X86Operand &Op1 = (X86Operand &)*Operands[1];
3732 X86Operand &Op2 = (X86Operand &)*Operands[2];
3733 SMLoc Loc = Op1.getEndLoc();
3734 // Moving a 32 or 16 bit value into a segment register has the same
3735 // behavior. Modify such instructions to always take shorter form.
3736 if (Op1.isReg() && Op2.isReg() &&
3737 getX86MCRegisterClass(X86::SEGMENT_REGRegClassID)
3738 .contains(Op2.getReg()) &&
3739 (getX86MCRegisterClass(X86::GR16RegClassID).contains(Op1.getReg()) ||
3740 getX86MCRegisterClass(X86::GR32RegClassID).contains(Op1.getReg()))) {
3741 // Change instruction name to match new instruction.
3742 if (Name != "mov" && Name[3] == (is16BitMode() ? 'l' : 'w')) {
3743 Name = is16BitMode() ? "movw" : "movl";
3744 Operands[0] = X86Operand::CreateToken(Name, NameLoc);
3745 }
3746 // Select the correct equivalent 16-/32-bit source register.
3747 MCRegister Reg =
3748 getX86SubSuperRegister(Op1.getReg(), is16BitMode() ? 16 : 32);
3749 Operands[1] = X86Operand::CreateReg(Reg, Loc, Loc);
3750 }
3751 }
3752
3753 // This is a terrible hack to handle "out[s]?[bwl]? %al, (%dx)" ->
3754 // "outb %al, %dx". Out doesn't take a memory form, but this is a widely
3755 // documented form in various unofficial manuals, so a lot of code uses it.
3756 if ((Name == "outb" || Name == "outsb" || Name == "outw" || Name == "outsw" ||
3757 Name == "outl" || Name == "outsl" || Name == "out" || Name == "outs") &&
3758 Operands.size() == 3) {
3759 X86Operand &Op = (X86Operand &)*Operands.back();
3760 if (Op.isDXReg())
3761 Operands.back() = X86Operand::CreateReg(X86::DX, Op.getStartLoc(),
3762 Op.getEndLoc());
3763 }
3764 // Same hack for "in[s]?[bwl]? (%dx), %al" -> "inb %dx, %al".
3765 if ((Name == "inb" || Name == "insb" || Name == "inw" || Name == "insw" ||
3766 Name == "inl" || Name == "insl" || Name == "in" || Name == "ins") &&
3767 Operands.size() == 3) {
3768 X86Operand &Op = (X86Operand &)*Operands[1];
3769 if (Op.isDXReg())
3770 Operands[1] = X86Operand::CreateReg(X86::DX, Op.getStartLoc(),
3771 Op.getEndLoc());
3772 }
3773
3775 bool HadVerifyError = false;
3776
3777 // Append default arguments to "ins[bwld]"
3778 if (Name.starts_with("ins") &&
3779 (Operands.size() == 1 || Operands.size() == 3) &&
3780 (Name == "insb" || Name == "insw" || Name == "insl" || Name == "insd" ||
3781 Name == "ins")) {
3782
3783 AddDefaultSrcDestOperands(TmpOperands,
3784 X86Operand::CreateReg(X86::DX, NameLoc, NameLoc),
3785 DefaultMemDIOperand(NameLoc));
3786 HadVerifyError = VerifyAndAdjustOperands(Operands, TmpOperands);
3787 }
3788
3789 // Append default arguments to "outs[bwld]"
3790 if (Name.starts_with("outs") &&
3791 (Operands.size() == 1 || Operands.size() == 3) &&
3792 (Name == "outsb" || Name == "outsw" || Name == "outsl" ||
3793 Name == "outsd" || Name == "outs")) {
3794 AddDefaultSrcDestOperands(TmpOperands, DefaultMemSIOperand(NameLoc),
3795 X86Operand::CreateReg(X86::DX, NameLoc, NameLoc));
3796 HadVerifyError = VerifyAndAdjustOperands(Operands, TmpOperands);
3797 }
3798
3799 // Transform "lods[bwlq]" into "lods[bwlq] ($SIREG)" for appropriate
3800 // values of $SIREG according to the mode. It would be nice if this
3801 // could be achieved with InstAlias in the tables.
3802 if (Name.starts_with("lods") &&
3803 (Operands.size() == 1 || Operands.size() == 2) &&
3804 (Name == "lods" || Name == "lodsb" || Name == "lodsw" ||
3805 Name == "lodsl" || Name == "lodsd" || Name == "lodsq")) {
3806 TmpOperands.push_back(DefaultMemSIOperand(NameLoc));
3807 HadVerifyError = VerifyAndAdjustOperands(Operands, TmpOperands);
3808 }
3809
3810 // Transform "stos[bwlq]" into "stos[bwlq] ($DIREG)" for appropriate
3811 // values of $DIREG according to the mode. It would be nice if this
3812 // could be achieved with InstAlias in the tables.
3813 if (Name.starts_with("stos") &&
3814 (Operands.size() == 1 || Operands.size() == 2) &&
3815 (Name == "stos" || Name == "stosb" || Name == "stosw" ||
3816 Name == "stosl" || Name == "stosd" || Name == "stosq")) {
3817 TmpOperands.push_back(DefaultMemDIOperand(NameLoc));
3818 HadVerifyError = VerifyAndAdjustOperands(Operands, TmpOperands);
3819 }
3820
3821 // Transform "scas[bwlq]" into "scas[bwlq] ($DIREG)" for appropriate
3822 // values of $DIREG according to the mode. It would be nice if this
3823 // could be achieved with InstAlias in the tables.
3824 if (Name.starts_with("scas") &&
3825 (Operands.size() == 1 || Operands.size() == 2) &&
3826 (Name == "scas" || Name == "scasb" || Name == "scasw" ||
3827 Name == "scasl" || Name == "scasd" || Name == "scasq")) {
3828 TmpOperands.push_back(DefaultMemDIOperand(NameLoc));
3829 HadVerifyError = VerifyAndAdjustOperands(Operands, TmpOperands);
3830 }
3831
3832 // Add default SI and DI operands to "cmps[bwlq]".
3833 if (Name.starts_with("cmps") &&
3834 (Operands.size() == 1 || Operands.size() == 3) &&
3835 (Name == "cmps" || Name == "cmpsb" || Name == "cmpsw" ||
3836 Name == "cmpsl" || Name == "cmpsd" || Name == "cmpsq")) {
3837 AddDefaultSrcDestOperands(TmpOperands, DefaultMemDIOperand(NameLoc),
3838 DefaultMemSIOperand(NameLoc));
3839 HadVerifyError = VerifyAndAdjustOperands(Operands, TmpOperands);
3840 }
3841
3842 // Add default SI and DI operands to "movs[bwlq]".
3843 if (((Name.starts_with("movs") &&
3844 (Name == "movs" || Name == "movsb" || Name == "movsw" ||
3845 Name == "movsl" || Name == "movsd" || Name == "movsq")) ||
3846 (Name.starts_with("smov") &&
3847 (Name == "smov" || Name == "smovb" || Name == "smovw" ||
3848 Name == "smovl" || Name == "smovd" || Name == "smovq"))) &&
3849 (Operands.size() == 1 || Operands.size() == 3)) {
3850 if (Name == "movsd" && Operands.size() == 1 && !isParsingIntelSyntax())
3851 Operands.back() = X86Operand::CreateToken("movsl", NameLoc);
3852 AddDefaultSrcDestOperands(TmpOperands, DefaultMemSIOperand(NameLoc),
3853 DefaultMemDIOperand(NameLoc));
3854 HadVerifyError = VerifyAndAdjustOperands(Operands, TmpOperands);
3855 }
3856
3857 // Check if we encountered an error for one the string insturctions
3858 if (HadVerifyError) {
3859 return HadVerifyError;
3860 }
3861
3862 // Transforms "xlat mem8" into "xlatb"
3863 if ((Name == "xlat" || Name == "xlatb") && Operands.size() == 2) {
3864 X86Operand &Op1 = static_cast<X86Operand &>(*Operands[1]);
3865 if (Op1.isMem8()) {
3866 Warning(Op1.getStartLoc(), "memory operand is only for determining the "
3867 "size, (R|E)BX will be used for the location");
3868 Operands.pop_back();
3869 static_cast<X86Operand &>(*Operands[0]).setTokenValue("xlatb");
3870 }
3871 }
3872
3873 if (Flags)
3874 Operands.push_back(X86Operand::CreatePrefix(Flags, NameLoc, NameLoc));
3875 return false;
3876}
3877
3878static bool convertSSEToAVX(MCInst &Inst) {
3879 ArrayRef<X86TableEntry> Table{X86SSE2AVXTable};
3880 unsigned Opcode = Inst.getOpcode();
3881 const auto I = llvm::lower_bound(Table, Opcode);
3882 if (I == Table.end() || I->OldOpc != Opcode)
3883 return false;
3884
3885 Inst.setOpcode(I->NewOpc);
3886 // AVX variant of BLENDVPD/BLENDVPS/PBLENDVB instructions has more
3887 // operand compare to SSE variant, which is added below
3888 if (X86::isBLENDVPD(Opcode) || X86::isBLENDVPS(Opcode) ||
3889 X86::isPBLENDVB(Opcode))
3890 Inst.addOperand(Inst.getOperand(2));
3891
3892 return true;
3893}
3894
3895bool X86AsmParser::processInstruction(MCInst &Inst, const OperandVector &Ops) {
3896 if (getTargetOptions().X86Sse2Avx && convertSSEToAVX(Inst))
3897 return true;
3898
3899 if (ForcedOpcodePrefix != OpcodePrefix_VEX3 &&
3900 X86::optimizeInstFromVEX3ToVEX2(Inst, MII.get(Inst.getOpcode())))
3901 return true;
3902
3904 return true;
3905
3906 auto replaceWithCCMPCTEST = [&](unsigned Opcode) -> bool {
3907 if (ForcedOpcodePrefix == OpcodePrefix_EVEX) {
3908 Inst.setFlags(~(X86::IP_USE_EVEX)&Inst.getFlags());
3909 Inst.setOpcode(Opcode);
3912 return true;
3913 }
3914 return false;
3915 };
3916
3917 switch (Inst.getOpcode()) {
3918 default: return false;
3919 case X86::JMP_1:
3920 // {disp32} forces a larger displacement as if the instruction was relaxed.
3921 // NOTE: 16-bit mode uses 16-bit displacement even though it says {disp32}.
3922 // This matches GNU assembler.
3923 if (ForcedDispEncoding == DispEncoding_Disp32) {
3924 Inst.setOpcode(is16BitMode() ? X86::JMP_2 : X86::JMP_4);
3925 return true;
3926 }
3927
3928 return false;
3929 case X86::JCC_1:
3930 // {disp32} forces a larger displacement as if the instruction was relaxed.
3931 // NOTE: 16-bit mode uses 16-bit displacement even though it says {disp32}.
3932 // This matches GNU assembler.
3933 if (ForcedDispEncoding == DispEncoding_Disp32) {
3934 Inst.setOpcode(is16BitMode() ? X86::JCC_2 : X86::JCC_4);
3935 return true;
3936 }
3937
3938 return false;
3939 case X86::INT: {
3940 // Transforms "int $3" into "int3" as a size optimization.
3941 // We can't write this as an InstAlias.
3942 if (!Inst.getOperand(0).isImm() || Inst.getOperand(0).getImm() != 3)
3943 return false;
3944 Inst.clear();
3945 Inst.setOpcode(X86::INT3);
3946 return true;
3947 }
3948 // `{evex} cmp <>, <>` is alias of `ccmpt {dfv=} <>, <>`, and
3949 // `{evex} test <>, <>` is alias of `ctest {dfv=} <>, <>`
3950#define FROM_TO(FROM, TO) \
3951 case X86::FROM: \
3952 return replaceWithCCMPCTEST(X86::TO);
3953 FROM_TO(CMP64rr, CCMP64rr)
3954 FROM_TO(CMP64mi32, CCMP64mi32)
3955 FROM_TO(CMP64mi8, CCMP64mi8)
3956 FROM_TO(CMP64mr, CCMP64mr)
3957 FROM_TO(CMP64ri32, CCMP64ri32)
3958 FROM_TO(CMP64ri8, CCMP64ri8)
3959 FROM_TO(CMP64rm, CCMP64rm)
3960
3961 FROM_TO(CMP32rr, CCMP32rr)
3962 FROM_TO(CMP32mi, CCMP32mi)
3963 FROM_TO(CMP32mi8, CCMP32mi8)
3964 FROM_TO(CMP32mr, CCMP32mr)
3965 FROM_TO(CMP32ri, CCMP32ri)
3966 FROM_TO(CMP32ri8, CCMP32ri8)
3967 FROM_TO(CMP32rm, CCMP32rm)
3968
3969 FROM_TO(CMP16rr, CCMP16rr)
3970 FROM_TO(CMP16mi, CCMP16mi)
3971 FROM_TO(CMP16mi8, CCMP16mi8)
3972 FROM_TO(CMP16mr, CCMP16mr)
3973 FROM_TO(CMP16ri, CCMP16ri)
3974 FROM_TO(CMP16ri8, CCMP16ri8)
3975 FROM_TO(CMP16rm, CCMP16rm)
3976
3977 FROM_TO(CMP8rr, CCMP8rr)
3978 FROM_TO(CMP8mi, CCMP8mi)
3979 FROM_TO(CMP8mr, CCMP8mr)
3980 FROM_TO(CMP8ri, CCMP8ri)
3981 FROM_TO(CMP8rm, CCMP8rm)
3982
3983 FROM_TO(TEST64rr, CTEST64rr)
3984 FROM_TO(TEST64mi32, CTEST64mi32)
3985 FROM_TO(TEST64mr, CTEST64mr)
3986 FROM_TO(TEST64ri32, CTEST64ri32)
3987
3988 FROM_TO(TEST32rr, CTEST32rr)
3989 FROM_TO(TEST32mi, CTEST32mi)
3990 FROM_TO(TEST32mr, CTEST32mr)
3991 FROM_TO(TEST32ri, CTEST32ri)
3992
3993 FROM_TO(TEST16rr, CTEST16rr)
3994 FROM_TO(TEST16mi, CTEST16mi)
3995 FROM_TO(TEST16mr, CTEST16mr)
3996 FROM_TO(TEST16ri, CTEST16ri)
3997
3998 FROM_TO(TEST8rr, CTEST8rr)
3999 FROM_TO(TEST8mi, CTEST8mi)
4000 FROM_TO(TEST8mr, CTEST8mr)
4001 FROM_TO(TEST8ri, CTEST8ri)
4002#undef FROM_TO
4003 }
4004}
4005
4006bool X86AsmParser::validateInstruction(MCInst &Inst, const OperandVector &Ops) {
4007 using namespace X86;
4008 const MCRegisterInfo *MRI = getContext().getRegisterInfo();
4009 unsigned Opcode = Inst.getOpcode();
4010 uint64_t TSFlags = MII.get(Opcode).TSFlags;
4011 if (isVFCMADDCPH(Opcode) || isVFCMADDCSH(Opcode) || isVFMADDCPH(Opcode) ||
4012 isVFMADDCSH(Opcode)) {
4013 MCRegister Dest = Inst.getOperand(0).getReg();
4014 for (unsigned i = 2; i < Inst.getNumOperands(); i++)
4015 if (Inst.getOperand(i).isReg() && Dest == Inst.getOperand(i).getReg())
4016 return Warning(Ops[0]->getStartLoc(), "Destination register should be "
4017 "distinct from source registers");
4018 } else if (isVFCMULCPH(Opcode) || isVFCMULCSH(Opcode) || isVFMULCPH(Opcode) ||
4019 isVFMULCSH(Opcode)) {
4020 MCRegister Dest = Inst.getOperand(0).getReg();
4021 // The mask variants have different operand list. Scan from the third
4022 // operand to avoid emitting incorrect warning.
4023 // VFMULCPHZrr Dest, Src1, Src2
4024 // VFMULCPHZrrk Dest, Dest, Mask, Src1, Src2
4025 // VFMULCPHZrrkz Dest, Mask, Src1, Src2
4026 for (unsigned i = ((TSFlags & X86II::EVEX_K) ? 2 : 1);
4027 i < Inst.getNumOperands(); i++)
4028 if (Inst.getOperand(i).isReg() && Dest == Inst.getOperand(i).getReg())
4029 return Warning(Ops[0]->getStartLoc(), "Destination register should be "
4030 "distinct from source registers");
4031 } else if (isV4FMADDPS(Opcode) || isV4FMADDSS(Opcode) ||
4032 isV4FNMADDPS(Opcode) || isV4FNMADDSS(Opcode) ||
4033 isVP4DPWSSDS(Opcode) || isVP4DPWSSD(Opcode)) {
4034 MCRegister Src2 =
4036 .getReg();
4037 unsigned Src2Enc = MRI->getEncodingValue(Src2);
4038 if (Src2Enc % 4 != 0) {
4040 unsigned GroupStart = (Src2Enc / 4) * 4;
4041 unsigned GroupEnd = GroupStart + 3;
4042 return Warning(Ops[0]->getStartLoc(),
4043 "source register '" + RegName + "' implicitly denotes '" +
4044 RegName.take_front(3) + Twine(GroupStart) + "' to '" +
4045 RegName.take_front(3) + Twine(GroupEnd) +
4046 "' source group");
4047 }
4048 } else if (isVGATHERDPD(Opcode) || isVGATHERDPS(Opcode) ||
4049 isVGATHERQPD(Opcode) || isVGATHERQPS(Opcode) ||
4050 isVPGATHERDD(Opcode) || isVPGATHERDQ(Opcode) ||
4051 isVPGATHERQD(Opcode) || isVPGATHERQQ(Opcode)) {
4052 bool HasEVEX = (TSFlags & X86II::EncodingMask) == X86II::EVEX;
4053 if (HasEVEX) {
4054 unsigned Dest = MRI->getEncodingValue(Inst.getOperand(0).getReg());
4055 unsigned Index = MRI->getEncodingValue(
4056 Inst.getOperand(4 + X86::AddrIndexReg).getReg());
4057 if (Dest == Index)
4058 return Warning(Ops[0]->getStartLoc(), "index and destination registers "
4059 "should be distinct");
4060 } else {
4061 unsigned Dest = MRI->getEncodingValue(Inst.getOperand(0).getReg());
4062 unsigned Mask = MRI->getEncodingValue(Inst.getOperand(1).getReg());
4063 unsigned Index = MRI->getEncodingValue(
4064 Inst.getOperand(3 + X86::AddrIndexReg).getReg());
4065 if (Dest == Mask || Dest == Index || Mask == Index)
4066 return Warning(Ops[0]->getStartLoc(), "mask, index, and destination "
4067 "registers should be distinct");
4068 }
4069 } else if (isTCMMIMFP16PS(Opcode) || isTCMMRLFP16PS(Opcode) ||
4070 isTDPBF16PS(Opcode) || isTDPFP16PS(Opcode) || isTDPBSSD(Opcode) ||
4071 isTDPBSUD(Opcode) || isTDPBUSD(Opcode) || isTDPBUUD(Opcode)) {
4072 MCRegister SrcDest = Inst.getOperand(0).getReg();
4073 MCRegister Src1 = Inst.getOperand(2).getReg();
4074 MCRegister Src2 = Inst.getOperand(3).getReg();
4075 if (SrcDest == Src1 || SrcDest == Src2 || Src1 == Src2)
4076 return Error(Ops[0]->getStartLoc(), "all tmm registers must be distinct");
4077 }
4078
4079 // High 8-bit regs (AH/BH/CH/DH) are incompatible with encodings that imply
4080 // extended prefixes:
4081 // * Legacy path that would emit a REX (e.g. uses r8..r15 or sil/dil/bpl/spl)
4082 // * EVEX
4083 // * REX2
4084 // VEX/XOP don't use REX; they are excluded from the legacy check.
4085 const unsigned Enc = TSFlags & X86II::EncodingMask;
4086 if (Enc != X86II::VEX && Enc != X86II::XOP) {
4087 MCRegister HReg;
4088 bool UsesRex = TSFlags & X86II::REX_W;
4089 unsigned NumOps = Inst.getNumOperands();
4090 for (unsigned i = 0; i != NumOps; ++i) {
4091 const MCOperand &MO = Inst.getOperand(i);
4092 if (!MO.isReg())
4093 continue;
4094 MCRegister Reg = MO.getReg();
4095 if (Reg == X86::AH || Reg == X86::BH || Reg == X86::CH || Reg == X86::DH)
4096 HReg = Reg;
4099 UsesRex = true;
4100 }
4101
4102 if (HReg &&
4103 (Enc == X86II::EVEX || ForcedOpcodePrefix == OpcodePrefix_REX2 ||
4104 ForcedOpcodePrefix == OpcodePrefix_REX || UsesRex)) {
4106 return Error(Ops[0]->getStartLoc(),
4107 "can't encode '" + RegName.str() +
4108 "' in an instruction requiring EVEX/REX2/REX prefix");
4109 }
4110 }
4111
4112 if ((Opcode == X86::PREFETCHIT0 || Opcode == X86::PREFETCHIT1)) {
4113 const MCOperand &MO = Inst.getOperand(X86::AddrBaseReg);
4114 if (!MO.isReg() || MO.getReg() != X86::RIP)
4115 return Warning(
4116 Ops[0]->getStartLoc(),
4117 Twine((Inst.getOpcode() == X86::PREFETCHIT0 ? "'prefetchit0'"
4118 : "'prefetchit1'")) +
4119 " only supports RIP-relative address");
4120 }
4121 return false;
4122}
4123
4124void X86AsmParser::emitWarningForSpecialLVIInstruction(SMLoc Loc) {
4125 Warning(Loc, "Instruction may be vulnerable to LVI and "
4126 "requires manual mitigation");
4127 Note(SMLoc(), "See https://software.intel.com/"
4128 "security-software-guidance/insights/"
4129 "deep-dive-load-value-injection#specialinstructions"
4130 " for more information");
4131}
4132
4133/// RET instructions and also instructions that indirect calls/jumps from memory
4134/// combine a load and a branch within a single instruction. To mitigate these
4135/// instructions against LVI, they must be decomposed into separate load and
4136/// branch instructions, with an LFENCE in between. For more details, see:
4137/// - X86LoadValueInjectionRetHardening.cpp
4138/// - X86LoadValueInjectionIndirectThunks.cpp
4139/// - https://software.intel.com/security-software-guidance/insights/deep-dive-load-value-injection
4140///
4141/// Returns `true` if a mitigation was applied or warning was emitted.
4142void X86AsmParser::applyLVICFIMitigation(MCInst &Inst, MCStreamer &Out) {
4143 // Information on control-flow instructions that require manual mitigation can
4144 // be found here:
4145 // https://software.intel.com/security-software-guidance/insights/deep-dive-load-value-injection#specialinstructions
4146 switch (Inst.getOpcode()) {
4147 case X86::RET16:
4148 case X86::RET32:
4149 case X86::RET64:
4150 case X86::RETI16:
4151 case X86::RETI32:
4152 case X86::RETI64: {
4153 MCInst ShlInst, FenceInst;
4154 bool Parse32 = is32BitMode() || Code16GCC;
4155 MCRegister Basereg =
4156 is64BitMode() ? X86::RSP : (Parse32 ? X86::ESP : X86::SP);
4157 const MCExpr *Disp = MCConstantExpr::create(0, getContext());
4158 auto ShlMemOp = X86Operand::CreateMem(getPointerWidth(), /*SegReg=*/0, Disp,
4159 /*BaseReg=*/Basereg, /*IndexReg=*/0,
4160 /*Scale=*/1, SMLoc{}, SMLoc{}, 0);
4161 ShlInst.setOpcode(X86::SHL64mi);
4162 ShlMemOp->addMemOperands(ShlInst, 5);
4163 ShlInst.addOperand(MCOperand::createImm(0));
4164 FenceInst.setOpcode(X86::LFENCE);
4165 Out.emitInstruction(ShlInst, getSTI());
4166 Out.emitInstruction(FenceInst, getSTI());
4167 return;
4168 }
4169 case X86::JMP16m:
4170 case X86::JMP32m:
4171 case X86::JMP64m:
4172 case X86::CALL16m:
4173 case X86::CALL32m:
4174 case X86::CALL64m:
4175 emitWarningForSpecialLVIInstruction(Inst.getLoc());
4176 return;
4177 }
4178}
4179
4180/// To mitigate LVI, every instruction that performs a load can be followed by
4181/// an LFENCE instruction to squash any potential mis-speculation. There are
4182/// some instructions that require additional considerations, and may requre
4183/// manual mitigation. For more details, see:
4184/// https://software.intel.com/security-software-guidance/insights/deep-dive-load-value-injection
4185///
4186/// Returns `true` if a mitigation was applied or warning was emitted.
4187void X86AsmParser::applyLVILoadHardeningMitigation(MCInst &Inst,
4188 MCStreamer &Out) {
4189 auto Opcode = Inst.getOpcode();
4190 auto Flags = Inst.getFlags();
4191 if ((Flags & X86::IP_HAS_REPEAT) || (Flags & X86::IP_HAS_REPEAT_NE)) {
4192 // Information on REP string instructions that require manual mitigation can
4193 // be found here:
4194 // https://software.intel.com/security-software-guidance/insights/deep-dive-load-value-injection#specialinstructions
4195 switch (Opcode) {
4196 case X86::CMPSB:
4197 case X86::CMPSW:
4198 case X86::CMPSL:
4199 case X86::CMPSQ:
4200 case X86::SCASB:
4201 case X86::SCASW:
4202 case X86::SCASL:
4203 case X86::SCASQ:
4204 emitWarningForSpecialLVIInstruction(Inst.getLoc());
4205 return;
4206 }
4207 } else if (Opcode == X86::REP_PREFIX || Opcode == X86::REPNE_PREFIX) {
4208 // If a REP instruction is found on its own line, it may or may not be
4209 // followed by a vulnerable instruction. Emit a warning just in case.
4210 emitWarningForSpecialLVIInstruction(Inst.getLoc());
4211 return;
4212 }
4213
4214 const MCInstrDesc &MCID = MII.get(Inst.getOpcode());
4215
4216 // Can't mitigate after terminators or calls. A control flow change may have
4217 // already occurred.
4218 if (MCID.isTerminator() || MCID.isCall())
4219 return;
4220
4221 // LFENCE has the mayLoad property, don't double fence.
4222 if (MCID.mayLoad() && Inst.getOpcode() != X86::LFENCE) {
4223 MCInst FenceInst;
4224 FenceInst.setOpcode(X86::LFENCE);
4225 Out.emitInstruction(FenceInst, getSTI());
4226 }
4227}
4228
4229void X86AsmParser::emitInstruction(MCInst &Inst, OperandVector &Operands,
4230 MCStreamer &Out) {
4232 getSTI().hasFeature(X86::FeatureLVIControlFlowIntegrity))
4233 applyLVICFIMitigation(Inst, Out);
4234
4235 Out.emitInstruction(Inst, getSTI());
4236
4238 getSTI().hasFeature(X86::FeatureLVILoadHardening))
4239 applyLVILoadHardeningMitigation(Inst, Out);
4240}
4241
4242static unsigned getPrefixes(OperandVector &Operands) {
4243 unsigned Result = 0;
4244 X86Operand &Prefix = static_cast<X86Operand &>(*Operands.back());
4245 if (Prefix.isPrefix()) {
4246 Result = Prefix.getPrefix();
4247 Operands.pop_back();
4248 }
4249 return Result;
4250}
4251
4252bool X86AsmParser::matchAndEmitInstruction(SMLoc IDLoc, unsigned &Opcode,
4253 OperandVector &Operands,
4254 MCStreamer &Out, uint64_t &ErrorInfo,
4255 bool MatchingInlineAsm) {
4256 assert(!Operands.empty() && "Unexpect empty operand list!");
4257 assert((*Operands[0]).isToken() && "Leading operand should always be a mnemonic!");
4258
4259 // First, handle aliases that expand to multiple instructions.
4260 MatchFPUWaitAlias(IDLoc, static_cast<X86Operand &>(*Operands[0]), Operands,
4261 Out, MatchingInlineAsm);
4262 unsigned Prefixes = getPrefixes(Operands);
4263
4264 MCInst Inst;
4265
4266 // If REX/REX2/VEX/EVEX encoding is forced, we need to pass the USE_* flag to
4267 // the encoder and printer.
4268 if (ForcedOpcodePrefix == OpcodePrefix_REX)
4269 Prefixes |= X86::IP_USE_REX;
4270 else if (ForcedOpcodePrefix == OpcodePrefix_REX2)
4271 Prefixes |= X86::IP_USE_REX2;
4272 else if (ForcedOpcodePrefix == OpcodePrefix_VEX)
4273 Prefixes |= X86::IP_USE_VEX;
4274 else if (ForcedOpcodePrefix == OpcodePrefix_VEX2)
4275 Prefixes |= X86::IP_USE_VEX2;
4276 else if (ForcedOpcodePrefix == OpcodePrefix_VEX3)
4277 Prefixes |= X86::IP_USE_VEX3;
4278 else if (ForcedOpcodePrefix == OpcodePrefix_EVEX)
4279 Prefixes |= X86::IP_USE_EVEX;
4280
4281 // Set encoded flags for {disp8} and {disp32}.
4282 if (ForcedDispEncoding == DispEncoding_Disp8)
4283 Prefixes |= X86::IP_USE_DISP8;
4284 else if (ForcedDispEncoding == DispEncoding_Disp32)
4285 Prefixes |= X86::IP_USE_DISP32;
4286
4287 if (Prefixes)
4288 Inst.setFlags(Prefixes);
4289
4290 return isParsingIntelSyntax()
4291 ? matchAndEmitIntelInstruction(IDLoc, Opcode, Inst, Operands, Out,
4292 ErrorInfo, MatchingInlineAsm)
4293 : matchAndEmitATTInstruction(IDLoc, Opcode, Inst, Operands, Out,
4294 ErrorInfo, MatchingInlineAsm);
4295}
4296
4297void X86AsmParser::MatchFPUWaitAlias(SMLoc IDLoc, X86Operand &Op,
4298 OperandVector &Operands, MCStreamer &Out,
4299 bool MatchingInlineAsm) {
4300 // FIXME: This should be replaced with a real .td file alias mechanism.
4301 // Also, MatchInstructionImpl should actually *do* the EmitInstruction
4302 // call.
4303 const char *Repl = StringSwitch<const char *>(Op.getToken())
4304 .Case("finit", "fninit")
4305 .Case("fsave", "fnsave")
4306 .Case("fstcw", "fnstcw")
4307 .Case("fstcww", "fnstcw")
4308 .Case("fstenv", "fnstenv")
4309 .Case("fstsw", "fnstsw")
4310 .Case("fstsww", "fnstsw")
4311 .Case("fclex", "fnclex")
4312 .Default(nullptr);
4313 if (Repl) {
4314 MCInst Inst;
4315 Inst.setOpcode(X86::WAIT);
4316 Inst.setLoc(IDLoc);
4317 if (!MatchingInlineAsm)
4318 emitInstruction(Inst, Operands, Out);
4319 Operands[0] = X86Operand::CreateToken(Repl, IDLoc);
4320 }
4321}
4322
4323bool X86AsmParser::ErrorMissingFeature(SMLoc IDLoc,
4324 const FeatureBitset &MissingFeatures,
4325 bool MatchingInlineAsm) {
4326 assert(MissingFeatures.any() && "Unknown missing feature!");
4327 SmallString<126> Msg;
4328 raw_svector_ostream OS(Msg);
4329 OS << "instruction requires:";
4330 for (unsigned Feature : MissingFeatures)
4331 OS << ' ' << getSubtargetFeatureName(Feature);
4332 return Error(IDLoc, OS.str(), SMRange(), MatchingInlineAsm);
4333}
4334
4335unsigned X86AsmParser::checkTargetMatchPredicate(MCInst &Inst) {
4336 unsigned Opc = Inst.getOpcode();
4337 const MCInstrDesc &MCID = MII.get(Opc);
4338 uint64_t TSFlags = MCID.TSFlags;
4339
4340 if (UseApxExtendedReg && !X86II::canUseApxExtendedReg(MCID))
4341 return Match_Unsupported;
4342 if (ForcedNoFlag == !(TSFlags & X86II::EVEX_NF) && !X86::isCFCMOVCC(Opc))
4343 return Match_Unsupported;
4344
4345 switch (ForcedOpcodePrefix) {
4346 case OpcodePrefix_Default:
4347 break;
4348 case OpcodePrefix_REX:
4349 case OpcodePrefix_REX2:
4350 if (TSFlags & X86II::EncodingMask)
4351 return Match_Unsupported;
4352 break;
4353 case OpcodePrefix_VEX:
4354 case OpcodePrefix_VEX2:
4355 case OpcodePrefix_VEX3:
4356 if ((TSFlags & X86II::EncodingMask) != X86II::VEX)
4357 return Match_Unsupported;
4358 break;
4359 case OpcodePrefix_EVEX:
4360 if (is64BitMode() && (TSFlags & X86II::EncodingMask) != X86II::EVEX &&
4361 !X86::isCMP(Opc) && !X86::isTEST(Opc))
4362 return Match_Unsupported;
4363 if (!is64BitMode() && (TSFlags & X86II::EncodingMask) != X86II::EVEX)
4364 return Match_Unsupported;
4365 break;
4366 }
4367
4369 (ForcedOpcodePrefix != OpcodePrefix_VEX &&
4370 ForcedOpcodePrefix != OpcodePrefix_VEX2 &&
4371 ForcedOpcodePrefix != OpcodePrefix_VEX3))
4372 return Match_Unsupported;
4373
4374 return Match_Success;
4375}
4376
4377bool X86AsmParser::matchAndEmitATTInstruction(
4378 SMLoc IDLoc, unsigned &Opcode, MCInst &Inst, OperandVector &Operands,
4379 MCStreamer &Out, uint64_t &ErrorInfo, bool MatchingInlineAsm) {
4380 X86Operand &Op = static_cast<X86Operand &>(*Operands[0]);
4381 SMRange EmptyRange;
4382 // In 16-bit mode, if data32 is specified, temporarily switch to 32-bit mode
4383 // when matching the instruction.
4384 if (ForcedDataPrefix == X86::Is32Bit)
4385 SwitchMode(X86::Is32Bit);
4386 // First, try a direct match.
4387 FeatureBitset MissingFeatures;
4388 unsigned OriginalError = MatchInstruction(Operands, Inst, ErrorInfo,
4389 MissingFeatures, MatchingInlineAsm,
4390 isParsingIntelSyntax());
4391 if (ForcedDataPrefix == X86::Is32Bit) {
4392 SwitchMode(X86::Is16Bit);
4393 ForcedDataPrefix = 0;
4394 }
4395 switch (OriginalError) {
4396 default: llvm_unreachable("Unexpected match result!");
4397 case Match_Success:
4398 if (!MatchingInlineAsm && validateInstruction(Inst, Operands))
4399 return true;
4400 // Some instructions need post-processing to, for example, tweak which
4401 // encoding is selected. Loop on it while changes happen so the
4402 // individual transformations can chain off each other.
4403 if (!MatchingInlineAsm)
4404 while (processInstruction(Inst, Operands))
4405 ;
4406
4407 Inst.setLoc(IDLoc);
4408 if (!MatchingInlineAsm)
4409 emitInstruction(Inst, Operands, Out);
4410 Opcode = Inst.getOpcode();
4411 return false;
4412 case Match_InvalidImmUnsignedi4: {
4413 SMLoc ErrorLoc = ((X86Operand &)*Operands[ErrorInfo]).getStartLoc();
4414 if (ErrorLoc == SMLoc())
4415 ErrorLoc = IDLoc;
4416 return Error(ErrorLoc, "immediate must be an integer in range [0, 15]",
4417 EmptyRange, MatchingInlineAsm);
4418 }
4419 case Match_InvalidImmUnsignedi6: {
4420 SMLoc ErrorLoc = ((X86Operand &)*Operands[ErrorInfo]).getStartLoc();
4421 if (ErrorLoc == SMLoc())
4422 ErrorLoc = IDLoc;
4423 return Error(ErrorLoc, "immediate must be an integer in range [0, 63]",
4424 EmptyRange, MatchingInlineAsm);
4425 }
4426 case Match_MissingFeature:
4427 return ErrorMissingFeature(IDLoc, MissingFeatures, MatchingInlineAsm);
4428 case Match_InvalidOperand:
4429 case Match_MnemonicFail:
4430 case Match_Unsupported:
4431 break;
4432 }
4433 if (Op.getToken().empty()) {
4434 Error(IDLoc, "instruction must have size higher than 0", EmptyRange,
4435 MatchingInlineAsm);
4436 return true;
4437 }
4438
4439 // FIXME: Ideally, we would only attempt suffix matches for things which are
4440 // valid prefixes, and we could just infer the right unambiguous
4441 // type. However, that requires substantially more matcher support than the
4442 // following hack.
4443
4444 // Change the operand to point to a temporary token.
4445 StringRef Base = Op.getToken();
4446 SmallString<16> Tmp;
4447 Tmp += Base;
4448 Tmp += ' ';
4449 Op.setTokenValue(Tmp);
4450
4451 // If this instruction starts with an 'f', then it is a floating point stack
4452 // instruction. These come in up to three forms for 32-bit, 64-bit, and
4453 // 80-bit floating point, which use the suffixes s,l,t respectively.
4454 //
4455 // Otherwise, we assume that this may be an integer instruction, which comes
4456 // in 8/16/32/64-bit forms using the b,w,l,q suffixes respectively.
4457 const char *Suffixes = Base[0] != 'f' ? "bwlq" : "slt\0";
4458 // MemSize corresponding to Suffixes. { 8, 16, 32, 64 } { 32, 64, 80, 0 }
4459 const char *MemSize = Base[0] != 'f' ? "\x08\x10\x20\x40" : "\x20\x40\x50\0";
4460
4461 // Check for the various suffix matches.
4462 uint64_t ErrorInfoIgnore;
4463 FeatureBitset ErrorInfoMissingFeatures; // Init suppresses compiler warnings.
4464 unsigned Match[4];
4465
4466 // Some instruction like VPMULDQ is NOT the variant of VPMULD but a new one.
4467 // So we should make sure the suffix matcher only works for memory variant
4468 // that has the same size with the suffix.
4469 // FIXME: This flag is a workaround for legacy instructions that didn't
4470 // declare non suffix variant assembly.
4471 bool HasVectorReg = false;
4472 X86Operand *MemOp = nullptr;
4473 for (const auto &Op : Operands) {
4474 X86Operand *X86Op = static_cast<X86Operand *>(Op.get());
4475 if (X86Op->isVectorReg())
4476 HasVectorReg = true;
4477 else if (X86Op->isMem()) {
4478 MemOp = X86Op;
4479 assert(MemOp->Mem.Size == 0 && "Memory size always 0 under ATT syntax");
4480 // Have we found an unqualified memory operand,
4481 // break. IA allows only one memory operand.
4482 break;
4483 }
4484 }
4485
4486 for (unsigned I = 0, E = std::size(Match); I != E; ++I) {
4487 Tmp.back() = Suffixes[I];
4488 if (MemOp && HasVectorReg)
4489 MemOp->Mem.Size = MemSize[I];
4490 Match[I] = Match_MnemonicFail;
4491 if (MemOp || !HasVectorReg) {
4492 Match[I] =
4493 MatchInstruction(Operands, Inst, ErrorInfoIgnore, MissingFeatures,
4494 MatchingInlineAsm, isParsingIntelSyntax());
4495 // If this returned as a missing feature failure, remember that.
4496 if (Match[I] == Match_MissingFeature)
4497 ErrorInfoMissingFeatures = MissingFeatures;
4498 }
4499 }
4500
4501 // Restore the old token.
4502 Op.setTokenValue(Base);
4503
4504 // If exactly one matched, then we treat that as a successful match (and the
4505 // instruction will already have been filled in correctly, since the failing
4506 // matches won't have modified it).
4507 unsigned NumSuccessfulMatches = llvm::count(Match, Match_Success);
4508 if (NumSuccessfulMatches == 1) {
4509 if (!MatchingInlineAsm && validateInstruction(Inst, Operands))
4510 return true;
4511 // Some instructions need post-processing to, for example, tweak which
4512 // encoding is selected. Loop on it while changes happen so the
4513 // individual transformations can chain off each other.
4514 if (!MatchingInlineAsm)
4515 while (processInstruction(Inst, Operands))
4516 ;
4517
4518 Inst.setLoc(IDLoc);
4519 if (!MatchingInlineAsm)
4520 emitInstruction(Inst, Operands, Out);
4521 Opcode = Inst.getOpcode();
4522 return false;
4523 }
4524
4525 // Otherwise, the match failed, try to produce a decent error message.
4526
4527 // If we had multiple suffix matches, then identify this as an ambiguous
4528 // match.
4529 if (NumSuccessfulMatches > 1) {
4530 char MatchChars[4];
4531 unsigned NumMatches = 0;
4532 for (unsigned I = 0, E = std::size(Match); I != E; ++I)
4533 if (Match[I] == Match_Success)
4534 MatchChars[NumMatches++] = Suffixes[I];
4535
4536 SmallString<126> Msg;
4537 raw_svector_ostream OS(Msg);
4538 OS << "ambiguous instructions require an explicit suffix (could be ";
4539 for (unsigned i = 0; i != NumMatches; ++i) {
4540 if (i != 0)
4541 OS << ", ";
4542 if (i + 1 == NumMatches)
4543 OS << "or ";
4544 OS << "'" << Base << MatchChars[i] << "'";
4545 }
4546 OS << ")";
4547 Error(IDLoc, OS.str(), EmptyRange, MatchingInlineAsm);
4548 return true;
4549 }
4550
4551 // Okay, we know that none of the variants matched successfully.
4552
4553 // If all of the instructions reported an invalid mnemonic, then the original
4554 // mnemonic was invalid.
4555 if (llvm::count(Match, Match_MnemonicFail) == 4) {
4556 if (OriginalError == Match_MnemonicFail)
4557 return Error(IDLoc, "invalid instruction mnemonic '" + Base + "'",
4558 Op.getLocRange(), MatchingInlineAsm);
4559
4560 if (OriginalError == Match_Unsupported)
4561 return Error(IDLoc, "unsupported instruction", EmptyRange,
4562 MatchingInlineAsm);
4563
4564 assert(OriginalError == Match_InvalidOperand && "Unexpected error");
4565 // Recover location info for the operand if we know which was the problem.
4566 if (ErrorInfo != ~0ULL) {
4567 if (ErrorInfo >= Operands.size())
4568 return Error(IDLoc, "too few operands for instruction", EmptyRange,
4569 MatchingInlineAsm);
4570
4571 X86Operand &Operand = (X86Operand &)*Operands[ErrorInfo];
4572 if (Operand.getStartLoc().isValid()) {
4573 SMRange OperandRange = Operand.getLocRange();
4574 return Error(Operand.getStartLoc(), "invalid operand for instruction",
4575 OperandRange, MatchingInlineAsm);
4576 }
4577 }
4578
4579 return Error(IDLoc, "invalid operand for instruction", EmptyRange,
4580 MatchingInlineAsm);
4581 }
4582
4583 // If one instruction matched as unsupported, report this as unsupported.
4584 if (llvm::count(Match, Match_Unsupported) == 1) {
4585 return Error(IDLoc, "unsupported instruction", EmptyRange,
4586 MatchingInlineAsm);
4587 }
4588
4589 // If one instruction matched with a missing feature, report this as a
4590 // missing feature.
4591 if (llvm::count(Match, Match_MissingFeature) == 1) {
4592 ErrorInfo = Match_MissingFeature;
4593 return ErrorMissingFeature(IDLoc, ErrorInfoMissingFeatures,
4594 MatchingInlineAsm);
4595 }
4596
4597 // If one instruction matched with an invalid operand, report this as an
4598 // operand failure.
4599 if (llvm::count(Match, Match_InvalidOperand) == 1) {
4600 return Error(IDLoc, "invalid operand for instruction", EmptyRange,
4601 MatchingInlineAsm);
4602 }
4603
4604 // If all of these were an outright failure, report it in a useless way.
4605 Error(IDLoc, "unknown use of instruction mnemonic without a size suffix",
4606 EmptyRange, MatchingInlineAsm);
4607 return true;
4608}
4609
4610bool X86AsmParser::matchAndEmitIntelInstruction(
4611 SMLoc IDLoc, unsigned &Opcode, MCInst &Inst, OperandVector &Operands,
4612 MCStreamer &Out, uint64_t &ErrorInfo, bool MatchingInlineAsm) {
4613 X86Operand &Op = static_cast<X86Operand &>(*Operands[0]);
4614 SMRange EmptyRange;
4615 // In 16-bit mode, if data32 is specified, temporarily switch to 32-bit mode
4616 // when matching the instruction. The mode must be restored before the
4617 // instruction is emitted, or the 32-bit form loses its 0x66 prefix.
4618 const bool ForcedData32 = ForcedDataPrefix == X86::Is32Bit;
4619 auto RestoreMode = [&] {
4620 if (ForcedData32) {
4621 SwitchMode(X86::Is16Bit);
4622 ForcedDataPrefix = 0;
4623 }
4624 };
4625 if (ForcedData32)
4626 SwitchMode(X86::Is32Bit);
4627 // Find one unsized memory operand, if present.
4628 X86Operand *UnsizedMemOp = nullptr;
4629 for (const auto &Op : Operands) {
4630 X86Operand *X86Op = static_cast<X86Operand *>(Op.get());
4631 if (X86Op->isMemUnsized()) {
4632 UnsizedMemOp = X86Op;
4633 // Have we found an unqualified memory operand,
4634 // break. IA allows only one memory operand.
4635 break;
4636 }
4637 }
4638
4639 // Allow some instructions to have implicitly pointer-sized operands. This is
4640 // compatible with gas.
4641 StringRef Mnemonic = (static_cast<X86Operand &>(*Operands[0])).getToken();
4642 if (UnsizedMemOp) {
4643 static const char *const PtrSizedInstrs[] = {"call", "jmp", "push", "pop"};
4644 for (const char *Instr : PtrSizedInstrs) {
4645 if (Mnemonic == Instr) {
4646 UnsizedMemOp->Mem.Size = getPointerWidth();
4647 break;
4648 }
4649 }
4650 }
4651
4652 SmallVector<unsigned, 8> Match;
4653 FeatureBitset ErrorInfoMissingFeatures;
4654 FeatureBitset MissingFeatures;
4655 StringRef Base = (static_cast<X86Operand &>(*Operands[0])).getToken();
4656
4657 // If unsized push has immediate operand we should default the default pointer
4658 // size for the size.
4659 if (Mnemonic == "push" && Operands.size() == 2) {
4660 auto *X86Op = static_cast<X86Operand *>(Operands[1].get());
4661 if (X86Op->isImm()) {
4662 // If it's not a constant fall through and let remainder take care of it.
4663 const auto *CE = dyn_cast<MCConstantExpr>(X86Op->getImm());
4664 unsigned Size = getPointerWidth();
4665 if (CE &&
4666 (isIntN(Size, CE->getValue()) || isUIntN(Size, CE->getValue()))) {
4667 SmallString<16> Tmp;
4668 Tmp += Base;
4669 Tmp += (is64BitMode())
4670 ? "q"
4671 : (is32BitMode()) ? "l" : (is16BitMode()) ? "w" : " ";
4672 Op.setTokenValue(Tmp);
4673 // Do match in ATT mode to allow explicit suffix usage.
4674 Match.push_back(MatchInstruction(Operands, Inst, ErrorInfo,
4675 MissingFeatures, MatchingInlineAsm,
4676 false /*isParsingIntelSyntax()*/));
4677 Op.setTokenValue(Base);
4678 }
4679 }
4680 }
4681
4682 // If an unsized memory operand is present, try to match with each memory
4683 // operand size. In Intel assembly, the size is not part of the instruction
4684 // mnemonic.
4685 if (UnsizedMemOp && UnsizedMemOp->isMemUnsized()) {
4686 static const unsigned MopSizes[] = {8, 16, 32, 64, 80, 128, 256, 512};
4687 for (unsigned Size : MopSizes) {
4688 UnsizedMemOp->Mem.Size = Size;
4689 uint64_t ErrorInfoIgnore;
4690 unsigned LastOpcode = Inst.getOpcode();
4691 unsigned M = MatchInstruction(Operands, Inst, ErrorInfoIgnore,
4692 MissingFeatures, MatchingInlineAsm,
4693 isParsingIntelSyntax());
4694 if (Match.empty() || LastOpcode != Inst.getOpcode())
4695 Match.push_back(M);
4696
4697 // If this returned as a missing feature failure, remember that.
4698 if (Match.back() == Match_MissingFeature)
4699 ErrorInfoMissingFeatures = MissingFeatures;
4700 }
4701
4702 // Restore the size of the unsized memory operand if we modified it.
4703 UnsizedMemOp->Mem.Size = 0;
4704 }
4705
4706 // If we haven't matched anything yet, this is not a basic integer or FPU
4707 // operation. There shouldn't be any ambiguity in our mnemonic table, so try
4708 // matching with the unsized operand.
4709 if (Match.empty()) {
4710 Match.push_back(MatchInstruction(
4711 Operands, Inst, ErrorInfo, MissingFeatures, MatchingInlineAsm,
4712 isParsingIntelSyntax()));
4713 // If this returned as a missing feature failure, remember that.
4714 if (Match.back() == Match_MissingFeature)
4715 ErrorInfoMissingFeatures = MissingFeatures;
4716 }
4717
4718 // Restore the size of the unsized memory operand if we modified it.
4719 if (UnsizedMemOp)
4720 UnsizedMemOp->Mem.Size = 0;
4721
4722 // If it's a bad mnemonic, all results will be the same.
4723 if (Match.back() == Match_MnemonicFail) {
4724 RestoreMode();
4725 return Error(IDLoc, "invalid instruction mnemonic '" + Mnemonic + "'",
4726 Op.getLocRange(), MatchingInlineAsm);
4727 }
4728
4729 unsigned NumSuccessfulMatches = llvm::count(Match, Match_Success);
4730
4731 // If matching was ambiguous and we had size information from the frontend,
4732 // try again with that. This handles cases like "movxz eax, m8/m16".
4733 if (UnsizedMemOp && NumSuccessfulMatches > 1 &&
4734 UnsizedMemOp->getMemFrontendSize()) {
4735 UnsizedMemOp->Mem.Size = UnsizedMemOp->getMemFrontendSize();
4736 unsigned M = MatchInstruction(
4737 Operands, Inst, ErrorInfo, MissingFeatures, MatchingInlineAsm,
4738 isParsingIntelSyntax());
4739 if (M == Match_Success)
4740 NumSuccessfulMatches = 1;
4741
4742 // Add a rewrite that encodes the size information we used from the
4743 // frontend.
4744 InstInfo->AsmRewrites->emplace_back(
4745 AOK_SizeDirective, UnsizedMemOp->getStartLoc(),
4746 /*Len=*/0, UnsizedMemOp->getMemFrontendSize());
4747 }
4748
4749 // Matching is done, so drop back to 16-bit before anything is emitted.
4750 RestoreMode();
4751
4752 // If exactly one matched, then we treat that as a successful match (and the
4753 // instruction will already have been filled in correctly, since the failing
4754 // matches won't have modified it).
4755 if (NumSuccessfulMatches == 1) {
4756 if (!MatchingInlineAsm && validateInstruction(Inst, Operands))
4757 return true;
4758 // Some instructions need post-processing to, for example, tweak which
4759 // encoding is selected. Loop on it while changes happen so the individual
4760 // transformations can chain off each other.
4761 if (!MatchingInlineAsm)
4762 while (processInstruction(Inst, Operands))
4763 ;
4764 Inst.setLoc(IDLoc);
4765 if (!MatchingInlineAsm)
4766 emitInstruction(Inst, Operands, Out);
4767 Opcode = Inst.getOpcode();
4768 return false;
4769 } else if (NumSuccessfulMatches > 1) {
4770 assert(UnsizedMemOp &&
4771 "multiple matches only possible with unsized memory operands");
4772 return Error(UnsizedMemOp->getStartLoc(),
4773 "ambiguous operand size for instruction '" + Mnemonic + "\'",
4774 UnsizedMemOp->getLocRange());
4775 }
4776
4777 // If one instruction matched as unsupported, report this as unsupported.
4778 if (llvm::count(Match, Match_Unsupported) == 1) {
4779 return Error(IDLoc, "unsupported instruction", EmptyRange,
4780 MatchingInlineAsm);
4781 }
4782
4783 // If one instruction matched with a missing feature, report this as a
4784 // missing feature.
4785 if (llvm::count(Match, Match_MissingFeature) == 1) {
4786 ErrorInfo = Match_MissingFeature;
4787 return ErrorMissingFeature(IDLoc, ErrorInfoMissingFeatures,
4788 MatchingInlineAsm);
4789 }
4790
4791 // If one instruction matched with an invalid operand, report this as an
4792 // operand failure.
4793 if (llvm::count(Match, Match_InvalidOperand) == 1) {
4794 return Error(IDLoc, "invalid operand for instruction", EmptyRange,
4795 MatchingInlineAsm);
4796 }
4797
4798 if (llvm::count(Match, Match_InvalidImmUnsignedi4) == 1) {
4799 SMLoc ErrorLoc = ((X86Operand &)*Operands[ErrorInfo]).getStartLoc();
4800 if (ErrorLoc == SMLoc())
4801 ErrorLoc = IDLoc;
4802 return Error(ErrorLoc, "immediate must be an integer in range [0, 15]",
4803 EmptyRange, MatchingInlineAsm);
4804 }
4805
4806 if (llvm::count(Match, Match_InvalidImmUnsignedi6) == 1) {
4807 SMLoc ErrorLoc = ((X86Operand &)*Operands[ErrorInfo]).getStartLoc();
4808 if (ErrorLoc == SMLoc())
4809 ErrorLoc = IDLoc;
4810 return Error(ErrorLoc, "immediate must be an integer in range [0, 63]",
4811 EmptyRange, MatchingInlineAsm);
4812 }
4813
4814 // If all of these were an outright failure, report it in a useless way.
4815 return Error(IDLoc, "unknown instruction mnemonic", EmptyRange,
4816 MatchingInlineAsm);
4817}
4818
4819bool X86AsmParser::omitRegisterFromClobberLists(MCRegister Reg) {
4820 return getX86MCRegisterClass(X86::SEGMENT_REGRegClassID).contains(Reg);
4821}
4822
4823bool X86AsmParser::ParseDirective(AsmToken DirectiveID) {
4824 MCAsmParser &Parser = getParser();
4825 StringRef IDVal = DirectiveID.getIdentifier();
4826 if (IDVal.starts_with(".arch"))
4827 return parseDirectiveArch();
4828 if (IDVal.starts_with(".code"))
4829 return ParseDirectiveCode(IDVal, DirectiveID.getLoc());
4830 else if (IDVal.starts_with(".att_syntax")) {
4831 if (getLexer().isNot(AsmToken::EndOfStatement)) {
4832 if (Parser.getTok().getString() == "prefix")
4833 Parser.Lex();
4834 else if (Parser.getTok().getString() == "noprefix")
4835 return Error(DirectiveID.getLoc(), "'.att_syntax noprefix' is not "
4836 "supported: registers must have a "
4837 "'%' prefix in .att_syntax");
4838 }
4839 getParser().setAssemblerDialect(0);
4840 return false;
4841 } else if (IDVal.starts_with(".intel_syntax")) {
4842 getParser().setAssemblerDialect(1);
4843 if (getLexer().isNot(AsmToken::EndOfStatement)) {
4844 if (Parser.getTok().getString() == "noprefix")
4845 Parser.Lex();
4846 else if (Parser.getTok().getString() == "prefix")
4847 return Error(DirectiveID.getLoc(), "'.intel_syntax prefix' is not "
4848 "supported: registers must not have "
4849 "a '%' prefix in .intel_syntax");
4850 }
4851 return false;
4852 } else if (IDVal == ".nops")
4853 return parseDirectiveNops(DirectiveID.getLoc());
4854 else if (IDVal == ".even")
4855 return parseDirectiveEven(DirectiveID.getLoc());
4856 else if (IDVal == ".cv_fpo_proc")
4857 return parseDirectiveFPOProc(DirectiveID.getLoc());
4858 else if (IDVal == ".cv_fpo_setframe")
4859 return parseDirectiveFPOSetFrame(DirectiveID.getLoc());
4860 else if (IDVal == ".cv_fpo_pushreg")
4861 return parseDirectiveFPOPushReg(DirectiveID.getLoc());
4862 else if (IDVal == ".cv_fpo_stackalloc")
4863 return parseDirectiveFPOStackAlloc(DirectiveID.getLoc());
4864 else if (IDVal == ".cv_fpo_stackalign")
4865 return parseDirectiveFPOStackAlign(DirectiveID.getLoc());
4866 else if (IDVal == ".cv_fpo_endprologue")
4867 return parseDirectiveFPOEndPrologue(DirectiveID.getLoc());
4868 else if (IDVal == ".cv_fpo_endproc")
4869 return parseDirectiveFPOEndProc(DirectiveID.getLoc());
4870 else if (IDVal == ".seh_pushreg")
4871 return parseDirectiveSEHPushReg(DirectiveID.getLoc());
4872 else if (IDVal == ".seh_push2regs")
4873 return parseDirectiveSEHPush2Regs(DirectiveID.getLoc());
4874 else if (IDVal == ".seh_setframe")
4875 return parseDirectiveSEHSetFrame(DirectiveID.getLoc());
4876 else if (IDVal == ".seh_savereg")
4877 return parseDirectiveSEHSaveReg(DirectiveID.getLoc());
4878 else if (IDVal == ".seh_savexmm")
4879 return parseDirectiveSEHSaveXMM(DirectiveID.getLoc());
4880 else if (IDVal == ".seh_pushframe")
4881 return parseDirectiveSEHPushFrame(DirectiveID.getLoc());
4882 else if (Parser.isParsingMasm()) {
4883 // MASM prolog directives.
4884 if (IDVal.equals_insensitive(".pushreg")) {
4885 return ensureMasmPrologContext(DirectiveID.getLoc()) ||
4886 parseDirectiveSEHPushReg(DirectiveID.getLoc());
4887 } else if (IDVal.equals_insensitive(".push2reg")) {
4888 return ensureMasmPrologContext(DirectiveID.getLoc()) ||
4889 parseDirectiveSEHPush2Regs(DirectiveID.getLoc());
4890 } else if (IDVal.equals_insensitive(".setframe")) {
4891 return ensureMasmPrologContext(DirectiveID.getLoc()) ||
4892 parseDirectiveSEHSetFrame(DirectiveID.getLoc());
4893 } else if (IDVal.equals_insensitive(".savereg")) {
4894 return ensureMasmPrologContext(DirectiveID.getLoc()) ||
4895 parseDirectiveSEHSaveReg(DirectiveID.getLoc());
4896 } else if (IDVal.equals_insensitive(".savexmm128")) {
4897 return ensureMasmPrologContext(DirectiveID.getLoc()) ||
4898 parseDirectiveSEHSaveXMM(DirectiveID.getLoc());
4899 } else if (IDVal.equals_insensitive(".pushframe")) {
4900 return ensureMasmPrologContext(DirectiveID.getLoc()) ||
4901 parseDirectiveSEHPushFrame(DirectiveID.getLoc());
4902 }
4903 // MASM epilog directives
4904 if (IDVal.equals_insensitive(".popreg")) {
4905 return ensureMasmEpilogContext(DirectiveID.getLoc()) ||
4906 parseDirectiveSEHPushReg(DirectiveID.getLoc());
4907 } else if (IDVal.equals_insensitive(".pop2reg")) {
4908 // .pop2reg args are in the order they are popped, so reverse them to get
4909 // the order they were pushed.
4910 return ensureMasmEpilogContext(DirectiveID.getLoc()) ||
4911 parseDirectiveSEHPush2Regs(DirectiveID.getLoc(),
4912 /*SwapRegs=*/true);
4913 } else if (IDVal.equals_insensitive(".unsetframe")) {
4914 return ensureMasmEpilogContext(DirectiveID.getLoc()) ||
4915 parseDirectiveSEHSetFrame(DirectiveID.getLoc());
4916 } else if (IDVal.equals_insensitive(".restorereg")) {
4917 return ensureMasmEpilogContext(DirectiveID.getLoc()) ||
4918 parseDirectiveSEHSaveReg(DirectiveID.getLoc());
4919 } else if (IDVal.equals_insensitive(".restorexmm128")) {
4920 return ensureMasmEpilogContext(DirectiveID.getLoc()) ||
4921 parseDirectiveSEHSaveXMM(DirectiveID.getLoc());
4922 }
4923 }
4924
4925 return true;
4926}
4927
4928bool X86AsmParser::parseDirectiveArch() {
4929 // Ignore .arch for now.
4930 getParser().parseStringToEndOfStatement();
4931 return false;
4932}
4933
4934/// parseDirectiveNops
4935/// ::= .nops size[, control]
4936bool X86AsmParser::parseDirectiveNops(SMLoc L) {
4937 int64_t NumBytes = 0, Control = 0;
4938 SMLoc NumBytesLoc, ControlLoc;
4939 const MCSubtargetInfo& STI = getSTI();
4940 NumBytesLoc = getTok().getLoc();
4941 if (getParser().checkForValidSection() ||
4942 getParser().parseAbsoluteExpression(NumBytes))
4943 return true;
4944
4945 if (parseOptionalToken(AsmToken::Comma)) {
4946 ControlLoc = getTok().getLoc();
4947 if (getParser().parseAbsoluteExpression(Control))
4948 return true;
4949 }
4950 if (getParser().parseEOL())
4951 return true;
4952
4953 if (NumBytes <= 0) {
4954 Error(NumBytesLoc, "'.nops' directive with non-positive size");
4955 return false;
4956 }
4957
4958 if (Control < 0) {
4959 Error(ControlLoc, "'.nops' directive with negative NOP size");
4960 return false;
4961 }
4962
4963 /// Emit nops
4964 getParser().getStreamer().emitNops(NumBytes, Control, L, STI);
4965
4966 return false;
4967}
4968
4969/// parseDirectiveEven
4970/// ::= .even
4971bool X86AsmParser::parseDirectiveEven(SMLoc L) {
4972 if (parseEOL())
4973 return false;
4974
4975 const MCSection *Section = getStreamer().getCurrentSectionOnly();
4976 if (!Section) {
4977 getStreamer().initSections(getSTI());
4978 Section = getStreamer().getCurrentSectionOnly();
4979 }
4980 if (getContext().getAsmInfo().useCodeAlign(*Section))
4981 getStreamer().emitCodeAlignment(Align(2), getSTI(), 0);
4982 else
4983 getStreamer().emitValueToAlignment(Align(2), 0, 1, 0);
4984 return false;
4985}
4986
4987/// ParseDirectiveCode
4988/// ::= .code16 | .code32 | .code64
4989bool X86AsmParser::ParseDirectiveCode(StringRef IDVal, SMLoc L) {
4990 MCAsmParser &Parser = getParser();
4991 Code16GCC = false;
4992 if (IDVal == ".code16") {
4993 Parser.Lex();
4994 if (!is16BitMode()) {
4995 SwitchMode(X86::Is16Bit);
4996 getTargetStreamer().emitCode16();
4997 }
4998 } else if (IDVal == ".code16gcc") {
4999 // .code16gcc parses as if in 32-bit mode, but emits code in 16-bit mode.
5000 Parser.Lex();
5001 Code16GCC = true;
5002 if (!is16BitMode()) {
5003 SwitchMode(X86::Is16Bit);
5004 getTargetStreamer().emitCode16();
5005 }
5006 } else if (IDVal == ".code32") {
5007 Parser.Lex();
5008 if (!is32BitMode()) {
5009 SwitchMode(X86::Is32Bit);
5010 getTargetStreamer().emitCode32();
5011 }
5012 } else if (IDVal == ".code64") {
5013 Parser.Lex();
5014 if (!is64BitMode()) {
5015 SwitchMode(X86::Is64Bit);
5016 getTargetStreamer().emitCode64();
5017 }
5018 } else {
5019 Error(L, "unknown directive " + IDVal);
5020 return false;
5021 }
5022
5023 return false;
5024}
5025
5026// .cv_fpo_proc foo
5027bool X86AsmParser::parseDirectiveFPOProc(SMLoc L) {
5028 MCAsmParser &Parser = getParser();
5029 StringRef ProcName;
5030 int64_t ParamsSize;
5031 if (Parser.parseIdentifier(ProcName))
5032 return Parser.TokError("expected symbol name");
5033 if (Parser.parseIntToken(ParamsSize, "expected parameter byte count"))
5034 return true;
5035 if (!isUIntN(32, ParamsSize))
5036 return Parser.TokError("parameters size out of range");
5037 if (parseEOL())
5038 return true;
5039 MCSymbol *ProcSym = getContext().getOrCreateSymbol(ProcName);
5040 return getTargetStreamer().emitFPOProc(ProcSym, ParamsSize, L);
5041}
5042
5043// .cv_fpo_setframe ebp
5044bool X86AsmParser::parseDirectiveFPOSetFrame(SMLoc L) {
5045 MCRegister Reg;
5046 SMLoc DummyLoc;
5047 if (parseRegister(Reg, DummyLoc, DummyLoc) || parseEOL())
5048 return true;
5049 return getTargetStreamer().emitFPOSetFrame(Reg, L);
5050}
5051
5052// .cv_fpo_pushreg ebx
5053bool X86AsmParser::parseDirectiveFPOPushReg(SMLoc L) {
5054 MCRegister Reg;
5055 SMLoc DummyLoc;
5056 if (parseRegister(Reg, DummyLoc, DummyLoc) || parseEOL())
5057 return true;
5058 return getTargetStreamer().emitFPOPushReg(Reg, L);
5059}
5060
5061// .cv_fpo_stackalloc 20
5062bool X86AsmParser::parseDirectiveFPOStackAlloc(SMLoc L) {
5063 MCAsmParser &Parser = getParser();
5064 int64_t Offset;
5065 if (Parser.parseIntToken(Offset, "expected offset") || parseEOL())
5066 return true;
5067 return getTargetStreamer().emitFPOStackAlloc(Offset, L);
5068}
5069
5070// .cv_fpo_stackalign 8
5071bool X86AsmParser::parseDirectiveFPOStackAlign(SMLoc L) {
5072 MCAsmParser &Parser = getParser();
5073 int64_t Offset;
5074 if (Parser.parseIntToken(Offset, "expected offset") || parseEOL())
5075 return true;
5076 return getTargetStreamer().emitFPOStackAlign(Offset, L);
5077}
5078
5079// .cv_fpo_endprologue
5080bool X86AsmParser::parseDirectiveFPOEndPrologue(SMLoc L) {
5081 MCAsmParser &Parser = getParser();
5082 if (Parser.parseEOL())
5083 return true;
5084 return getTargetStreamer().emitFPOEndPrologue(L);
5085}
5086
5087// .cv_fpo_endproc
5088bool X86AsmParser::parseDirectiveFPOEndProc(SMLoc L) {
5089 MCAsmParser &Parser = getParser();
5090 if (Parser.parseEOL())
5091 return true;
5092 return getTargetStreamer().emitFPOEndProc(L);
5093}
5094
5095bool X86AsmParser::parseSEHRegisterNumber(unsigned RegClassID,
5096 MCRegister &RegNo) {
5097 SMLoc startLoc = getLexer().getLoc();
5098 const MCRegisterInfo *MRI = getContext().getRegisterInfo();
5099
5100 // Try parsing the argument as a register first.
5101 if (getLexer().getTok().isNot(AsmToken::Integer)) {
5102 SMLoc endLoc;
5103 if (parseRegister(RegNo, startLoc, endLoc))
5104 return true;
5105
5106 if (!getX86MCRegisterClass(RegClassID).contains(RegNo)) {
5107 return Error(startLoc,
5108 "register is not supported for use with this directive");
5109 }
5110 } else {
5111 // Otherwise, an integer number matching the encoding of the desired
5112 // register may appear.
5113 int64_t EncodedReg;
5114 if (getParser().parseAbsoluteExpression(EncodedReg))
5115 return true;
5116
5117 // The SEH register number is the same as the encoding register number. Map
5118 // from the encoding back to the LLVM register number.
5119 RegNo = MCRegister();
5120 for (MCPhysReg Reg : getX86MCRegisterClass(RegClassID)) {
5121 if (MRI->getEncodingValue(Reg) == EncodedReg) {
5122 RegNo = Reg;
5123 break;
5124 }
5125 }
5126 if (!RegNo) {
5127 return Error(startLoc,
5128 "incorrect register number for use with this directive");
5129 }
5130 }
5131
5132 return false;
5133}
5134
5135bool X86AsmParser::parseDirectiveSEHPushReg(SMLoc Loc) {
5136 MCRegister Reg;
5137 if (parseSEHRegisterNumber(X86::GR64RegClassID, Reg))
5138 return true;
5139
5140 if (getLexer().isNot(AsmToken::EndOfStatement))
5141 return TokError("expected end of directive");
5142
5143 getParser().Lex();
5144 getStreamer().emitWinCFIPushReg(Reg, Loc);
5145 return false;
5146}
5147
5148bool X86AsmParser::parseDirectiveSEHPush2Regs(SMLoc Loc, bool SwapRegs) {
5149 MCRegister Reg1;
5150 if (parseSEHRegisterNumber(X86::GR64RegClassID, Reg1))
5151 return true;
5152
5153 if (getLexer().isNot(AsmToken::Comma))
5154 return TokError("expected comma between registers");
5155 getParser().Lex();
5156
5157 MCRegister Reg2;
5158 if (parseSEHRegisterNumber(X86::GR64RegClassID, Reg2))
5159 return true;
5160
5161 if (getLexer().isNot(AsmToken::EndOfStatement))
5162 return TokError("expected end of directive");
5163
5164 getParser().Lex();
5165 // Swap regs to go from pop order to push order.
5166 if (SwapRegs)
5167 std::swap(Reg1, Reg2);
5168 getStreamer().emitWinCFIPush2Regs(Reg1, Reg2, Loc);
5169 return false;
5170}
5171
5172bool X86AsmParser::parseDirectiveSEHSetFrame(SMLoc Loc) {
5173 MCRegister Reg;
5174 int64_t Off;
5175 if (parseSEHRegisterNumber(X86::GR64RegClassID, Reg))
5176 return true;
5177 if (getLexer().isNot(AsmToken::Comma))
5178 return TokError("you must specify a stack pointer offset");
5179
5180 getParser().Lex();
5181 if (getParser().parseAbsoluteExpression(Off))
5182 return true;
5183
5184 if (getLexer().isNot(AsmToken::EndOfStatement))
5185 return TokError("expected end of directive");
5186
5187 getParser().Lex();
5188 getStreamer().emitWinCFISetFrame(Reg, Off, Loc);
5189 return false;
5190}
5191
5192bool X86AsmParser::parseDirectiveSEHSaveReg(SMLoc Loc) {
5193 MCRegister Reg;
5194 int64_t Off;
5195 if (parseSEHRegisterNumber(X86::GR64RegClassID, Reg))
5196 return true;
5197 if (getLexer().isNot(AsmToken::Comma))
5198 return TokError("you must specify an offset on the stack");
5199
5200 getParser().Lex();
5201 if (getParser().parseAbsoluteExpression(Off))
5202 return true;
5203
5204 if (getLexer().isNot(AsmToken::EndOfStatement))
5205 return TokError("expected end of directive");
5206
5207 getParser().Lex();
5208 getStreamer().emitWinCFISaveReg(Reg, Off, Loc);
5209 return false;
5210}
5211
5212bool X86AsmParser::parseDirectiveSEHSaveXMM(SMLoc Loc) {
5213 MCRegister Reg;
5214 int64_t Off;
5215 if (parseSEHRegisterNumber(X86::VR128XRegClassID, Reg))
5216 return true;
5217 if (getLexer().isNot(AsmToken::Comma))
5218 return TokError("you must specify an offset on the stack");
5219
5220 getParser().Lex();
5221 if (getParser().parseAbsoluteExpression(Off))
5222 return true;
5223
5224 if (getLexer().isNot(AsmToken::EndOfStatement))
5225 return TokError("expected end of directive");
5226
5227 getParser().Lex();
5228 getStreamer().emitWinCFISaveXMM(Reg, Off, Loc);
5229 return false;
5230}
5231
5232bool X86AsmParser::ensureMasmPrologContext(SMLoc Loc) {
5233 if (getStreamer().isWinCFIPrologEnded()) {
5234 return Error(Loc, "prolog directive must be used inside a prolog");
5235 }
5236 return false;
5237}
5238
5239bool X86AsmParser::ensureMasmEpilogContext(SMLoc Loc) {
5240 if (!getStreamer().isInEpilogCFI()) {
5241 return Error(Loc, "epilog directive must be used inside an epilog");
5242 }
5243 return false;
5244}
5245
5246bool X86AsmParser::parseDirectiveSEHPushFrame(SMLoc Loc) {
5247 bool Code = false;
5248 StringRef CodeID;
5249 if (getLexer().is(AsmToken::At)) {
5250 SMLoc startLoc = getLexer().getLoc();
5251 getParser().Lex();
5252 if (!getParser().parseIdentifier(CodeID)) {
5253 if (CodeID != "code")
5254 return Error(startLoc, "expected @code");
5255 Code = true;
5256 }
5257 } else if (getParser().isParsingMasm() &&
5258 getLexer().is(AsmToken::Identifier) &&
5259 getTok().getString().equals_insensitive("code")) {
5260 getParser().Lex();
5261 Code = true;
5262 }
5263
5264 if (getLexer().isNot(AsmToken::EndOfStatement))
5265 return TokError("expected end of directive");
5266
5267 getParser().Lex();
5268 getStreamer().emitWinCFIPushFrame(Code, Loc);
5269 return false;
5270}
5271
5272// Force static initialization.
5277
5278#define GET_MATCHER_IMPLEMENTATION
5279#include "X86GenAsmMatcher.inc"
static MCRegister MatchRegisterName(StringRef Name)
static const char * getSubtargetFeatureName(uint64_t Val)
unsigned RegSize
assert(UImm &&(UImm !=~static_cast< T >(0)) &&"Invalid immediate!")
static bool isNot(const MachineRegisterInfo &MRI, const MachineInstr &MI)
Function Alias Analysis false
#define X(NUM, ENUM, NAME)
Definition ELF.h:856
static GCRegistry::Add< CoreCLRGC > E("coreclr", "CoreCLR-compatible GC")
@ Default
amode Optimize addressing mode
Value * getPointer(Value *Ptr)
static ModuleSymbolTable::Symbol getSym(DataRefImpl &Symb)
static constexpr Value * getValue(Ty &ValueOrUse)
const size_t AbstractManglingParser< Derived, Alloc >::NumOps
const AbstractManglingParser< Derived, Alloc >::OperatorInfo AbstractManglingParser< Derived, Alloc >::Ops[]
#define RegName(no)
static bool hasFeature(StringRef Feature, const FeatureBitset &FeatureBits, ArrayRef< SubtargetFeatureKV > ProcFeatures)
#define I(x, y, z)
Definition MD5.cpp:57
static bool IsVCMP(unsigned Opcode)
Register Reg
static constexpr unsigned SM(unsigned Version)
ConstantRange Range(APInt(BitWidth, Low), APInt(BitWidth, High))
OptimizedStructLayoutField Field
static StringRef getName(Value *V)
Func getContext().diagnose(DiagnosticInfoUnsupported(Func
const char * Msg
This file contains some templates that are useful if you are working with the STL at all.
static bool contains(SmallPtrSetImpl< ConstantExpr * > &Cache, ConstantExpr *Expr, Constant *C)
Definition Value.cpp:484
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...
DEMANGLE_NAMESPACE_BEGIN bool starts_with(std::string_view self, char C) noexcept
static TableGen::Emitter::Opt Y("gen-skeleton-entry", EmitSkeleton, "Generate example skeleton entry")
static SymbolRef::Type getType(const Symbol *Sym)
Definition TapiFile.cpp:39
#define LLVM_C_ABI
LLVM_C_ABI is the export/visibility macro used to mark symbols declared in llvm-c as exported when bu...
Definition Visibility.h:40
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_C_ABI void LLVMInitializeX86AsmParser()
static bool convertSSEToAVX(MCInst &Inst)
static unsigned getPrefixes(OperandVector &Operands)
static bool CheckBaseRegAndIndexRegAndScale(MCRegister BaseReg, MCRegister IndexReg, unsigned Scale, bool Is64BitMode, StringRef &ErrMsg)
#define FROM_TO(FROM, TO)
uint16_t RegSizeInBits(const MCRegisterInfo &MRI, MCRegister RegNo)
Value * RHS
Value * LHS
static unsigned getSize(unsigned Kind)
uint64_t getZExtValue() const
Get zero extended value.
Definition APInt.h:1565
Represent a constant reference to an array (0 or more elements consecutively in memory),...
Definition ArrayRef.h:40
void UnLex(AsmToken const &Token)
Definition AsmLexer.h:106
bool isNot(AsmToken::TokenKind K) const
Check if the current token has kind K.
Definition AsmLexer.h:150
LLVM_ABI SMLoc getLoc() const
Definition AsmLexer.cpp:31
int64_t getIntVal() const
Definition MCAsmMacro.h:108
bool isNot(TokenKind K) const
Definition MCAsmMacro.h:76
StringRef getString() const
Get the string for the current token, this includes all characters (for example, the quotes on string...
Definition MCAsmMacro.h:103
bool is(TokenKind K) const
Definition MCAsmMacro.h:75
TokenKind getKind() const
Definition MCAsmMacro.h:74
LLVM_ABI SMLoc getEndLoc() const
Definition AsmLexer.cpp:33
StringRef getIdentifier() const
Get the identifier string for the current token, which should be an identifier or a string.
Definition MCAsmMacro.h:92
bool Error(SMLoc L, const Twine &Msg, SMRange Range={})
Return an error at the location L, with the message Msg.
bool parseIntToken(int64_t &V, const Twine &ErrMsg="expected integer")
MCContext & getContext()
virtual bool parseExpression(const MCExpr *&Res, SMLoc &EndLoc)=0
Parse an arbitrary 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.
virtual bool parsePrimaryExpr(const MCExpr *&Res, SMLoc &EndLoc, AsmTypeInfo *TypeInfo=nullptr)=0
Parse a primary expression.
virtual const AsmToken & Lex()=0
Get the next AsmToken in the stream, possibly handling file inclusion first.
bool TokError(const Twine &Msg, SMRange Range={})
Report an error at the current lexer location.
virtual void addAliasForDirective(StringRef Directive, StringRef Alias)=0
virtual bool lookUpType(StringRef Name, AsmTypeInfo &Info) const
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)
static const MCBinaryExpr * createAdd(const MCExpr *LHS, const MCExpr *RHS, MCContext &Ctx, SMLoc Loc=SMLoc())
Definition MCExpr.h:342
static LLVM_ABI const MCConstantExpr * create(int64_t Value, MCContext &Ctx, bool PrintInHex=false, unsigned SizeInBytes=0)
Definition MCExpr.cpp:212
@ SymbolRef
References to labels and assigned expressions.
Definition MCExpr.h:43
ExprKind getKind() const
Definition MCExpr.h:85
Instances of this class represent a single low-level machine instruction.
Definition MCInst.h:188
unsigned getNumOperands() const
Definition MCInst.h:212
SMLoc getLoc() const
Definition MCInst.h:208
unsigned getFlags() const
Definition MCInst.h:205
void setLoc(SMLoc loc)
Definition MCInst.h:207
unsigned getOpcode() const
Definition MCInst.h:202
void setFlags(unsigned F)
Definition MCInst.h:204
void addOperand(const MCOperand Op)
Definition MCInst.h:215
void setOpcode(unsigned Op)
Definition MCInst.h:201
void clear()
Definition MCInst.h:223
const MCOperand & getOperand(unsigned i) const
Definition MCInst.h:210
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.
int64_t getImm() const
Definition MCInst.h:84
static MCOperand createImm(int64_t Val)
Definition MCInst.h:145
bool isImm() const
Definition MCInst.h:66
bool isReg() const
Definition MCInst.h:65
MCRegister getReg() const
Returns the register number.
Definition MCInst.h:73
MCRegisterInfo base class - We assume that the target defines a static array of MCRegisterDesc object...
uint16_t getEncodingValue(MCRegister Reg) const
Returns the encoding for Reg.
Wrapper class representing physical registers. Should be passed by value.
Definition MCRegister.h:41
virtual void emitInstruction(const MCInst &Inst, const MCSubtargetInfo &STI)
Emit the given Instruction into the current section.
const FeatureBitset & getFeatureBits() const
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, SMLoc Loc=SMLoc())
Definition MCExpr.h:213
bool isUndefined() const
isUndefined - Check if this symbol undefined (i.e., implicitly defined).
Definition MCSymbol.h:243
StringRef getName() const
getName - Get the symbol name.
Definition MCSymbol.h:188
bool isVariable() const
isVariable - Check if this is a variable symbol.
Definition MCSymbol.h:267
const MCExpr * getVariableValue() const
Get the expression of the variable symbol.
Definition MCSymbol.h:270
MCTargetAsmParser - Generic interface to target specific assembly parsers.
static constexpr StatusTy Failure
static constexpr StatusTy Success
static constexpr StatusTy NoMatch
constexpr unsigned id() const
Definition Register.h:100
Represents a location in source code.
Definition SMLoc.h:22
static SMLoc getFromPointer(const char *Ptr)
Definition SMLoc.h:35
constexpr const char * getPointer() const
Definition SMLoc.h:33
constexpr bool isValid() const
Definition SMLoc.h:28
void push_back(const T &Elt)
Represent a constant reference to a string, i.e.
Definition StringRef.h:56
std::pair< StringRef, StringRef > split(char Separator) const
Split into two substrings around the first occurrence of a separator character.
Definition StringRef.h:736
static constexpr size_t npos
Definition StringRef.h:58
bool consume_back(StringRef Suffix)
Returns true if this StringRef has the given suffix and removes that suffix.
Definition StringRef.h:691
bool getAsInteger(unsigned Radix, T &Result) const
Parse the current string as an integer of the specified radix.
Definition StringRef.h:490
constexpr StringRef substr(size_t Start, size_t N=npos) const
Return a reference to the substring from [Start, Start + N).
Definition StringRef.h:597
bool starts_with(StringRef Prefix) const
Check if this string starts with the given Prefix.
Definition StringRef.h:258
LLVM_ABI std::string upper() const
Convert the given ASCII string to uppercase.
char back() const
Get the last character in the string.
Definition StringRef.h:153
StringRef slice(size_t Start, size_t End) const
Return a reference to the substring from [Start, End).
Definition StringRef.h:720
constexpr size_t size() const
Get the string size.
Definition StringRef.h:144
constexpr const char * data() const
Get a pointer to the start of the string (which may not be null terminated).
Definition StringRef.h:138
LLVM_ABI std::string lower() const
bool ends_with(StringRef Suffix) const
Check if this string ends with the given Suffix.
Definition StringRef.h:270
bool consume_front(char Prefix)
Returns true if this StringRef has the given prefix and removes that prefix.
Definition StringRef.h:661
StringRef drop_back(size_t N=1) const
Return a StringRef equal to 'this' but with the last N elements dropped.
Definition StringRef.h:642
bool equals_insensitive(StringRef RHS) const
Check for string equality, ignoring case.
Definition StringRef.h:170
static const char * getRegisterName(MCRegister Reg)
static const X86MCExpr * create(MCRegister Reg, MCContext &Ctx)
Definition X86MCExpr.h:34
#define llvm_unreachable(msg)
Marks that the current location is not supposed to be reachable.
constexpr char Align[]
Key for Kernel::Arg::Metadata::mAlign.
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.
std::variant< std::monostate, Loc::Single, Loc::Multi, Loc::MMI, Loc::EntryValue > Variant
Alias for the std::variant specialization base class of DbgVariable.
Definition DwarfDebug.h:190
@ CE
Windows NT (Windows on ARM)
Definition MCAsmInfo.h:51
@ X86
Windows x64, Windows Itanium (IA-64)
Definition MCAsmInfo.h:53
bool isX86_64NonExtLowByteReg(MCRegister Reg)
@ 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.
@ XOP
XOP - Opcode prefix used by XOP instructions.
@ ExplicitVEXPrefix
For instructions that use VEX encoding only when {vex}, {vex2} or {vex3} is present.
bool canUseApxExtendedReg(const MCInstrDesc &Desc)
bool isX86_64ExtendedReg(MCRegister Reg)
bool isApxExtendedReg(MCRegister Reg)
void emitInstruction(MCObjectStreamer &, const MCInst &Inst, const MCSubtargetInfo &STI)
@ AddrNumOperands
Definition X86BaseInfo.h:36
bool optimizeShiftRotateWithImmediateOne(MCInst &MI)
bool optimizeInstFromVEX3ToVEX2(MCInst &MI, const MCInstrDesc &Desc)
@ IP_HAS_REPEAT_NE
Definition X86BaseInfo.h:55
NodeAddr< CodeNode * > Code
Definition RDFGraph.h:388
BaseReg
Stack frame base register. Bit 0 of FREInfo.Info.
Definition SFrame.h:77
This is an optimization pass for GlobalISel generic memory operations.
@ Offset
Definition DWP.cpp:578
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.
Definition STLExtras.h:1669
constexpr bool isInt(int64_t x)
Checks if an integer fits into the given bit width.
Definition MathExtras.h:166
LLVM_ABI std::pair< StringRef, StringRef > getToken(StringRef Source, StringRef Delimiters=" \t\n\v\f\r")
getToken - This function extracts one token from source, ignoring any leading characters that appear ...
decltype(auto) dyn_cast(const From &Val)
dyn_cast<X> - Return the argument parameter cast to the specified type.
Definition Casting.h:643
@ Done
Definition Threading.h:60
@ AOK_EndOfStatement
@ AOK_SizeDirective
MCRegister getX86SubSuperRegister(MCRegister Reg, unsigned Size, bool High=false)
Target & getTheX86_32Target()
constexpr bool isUIntN(unsigned N, uint64_t x)
Checks if an unsigned integer fits into the given (dynamic) bit width.
Definition MathExtras.h:244
SmallVectorImpl< std::unique_ptr< MCParsedAsmOperand > > OperandVector
MachineInstr * getImm(const MachineOperand &MO, const MachineRegisterInfo *MRI)
LLVM_ABI void report_fatal_error(Error Err, bool gen_crash_diag=true)
Definition Error.cpp:163
constexpr bool isUInt(uint64_t x)
Checks if an unsigned integer fits into the given bit width.
Definition MathExtras.h:190
class LLVM_GSL_OWNER SmallVector
Forward declaration of SmallVector so that calculateSmallVectorDefaultInlinedElements can reference s...
bool isa(const From &Val)
isa<X> - Return true if the parameter to the template is an instance of one of the template type argu...
Definition Casting.h:547
auto lower_bound(R &&Range, T &&Value)
Provide wrappers to std::lower_bound which take ranges instead of having to pass begin/end explicitly...
Definition STLExtras.h:2052
uint16_t MCPhysReg
An unsigned integer type large enough to represent all physical registers, but not necessarily virtua...
Definition MCRegister.h:21
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...
Definition STLExtras.h:2012
DWARFExpression::Operation Op
decltype(auto) cast(const From &Val)
cast<X> - Return the argument parameter cast to the specified type.
Definition Casting.h:559
constexpr bool isIntN(unsigned N, int64_t x)
Checks if an signed integer fits into the given (dynamic) bit width.
Definition MathExtras.h:249
RelativeUniformCounterPtr ValuesPtrExpr VTableAddr Next
Definition InstrProf.h:147
Target & getTheX86_64Target()
StringRef toStringRef(bool B)
Construct a string ref from a boolean.
void swap(llvm::BitVector &LHS, llvm::BitVector &RHS)
Implement std::swap in terms of BitVector swap.
Definition BitVector.h:880
#define N
bool isKind(IdKind kind) const
Definition MCAsmParser.h:66
SmallVectorImpl< AsmRewrite > * AsmRewrites
RegisterMCAsmParser - Helper template for registering a target specific assembly parser,...
X86Operand - Instances of this class represent a parsed X86 machine instruction.
Definition X86Operand.h:31
SMLoc getStartLoc() const override
getStartLoc - Get the location of the first token of this operand.
Definition X86Operand.h:98
bool isImm() const override
isImm - Is this an immediate operand?
Definition X86Operand.h:223
static std::unique_ptr< X86Operand > CreateImm(const MCExpr *Val, SMLoc StartLoc, SMLoc EndLoc, StringRef SymName=StringRef(), void *OpDecl=nullptr, bool GlobalRef=true)
Definition X86Operand.h:721
static std::unique_ptr< X86Operand > CreatePrefix(unsigned Prefixes, SMLoc StartLoc, SMLoc EndLoc)
Definition X86Operand.h:715
static std::unique_ptr< X86Operand > CreateDXReg(SMLoc StartLoc, SMLoc EndLoc)
Definition X86Operand.h:710
static std::unique_ptr< X86Operand > CreateReg(MCRegister Reg, SMLoc StartLoc, SMLoc EndLoc, bool AddressOf=false, SMLoc OffsetOfLoc=SMLoc(), StringRef SymName=StringRef(), void *OpDecl=nullptr)
Definition X86Operand.h:697
SMRange getLocRange() const
getLocRange - Get the range between the first and last token of this operand.
Definition X86Operand.h:105
SMLoc getEndLoc() const override
getEndLoc - Get the location of the last token of this operand.
Definition X86Operand.h:101
bool isReg() const override
isReg - Is this a register operand?
Definition X86Operand.h:533
bool isMem() const override
isMem - Is this a memory operand?
Definition X86Operand.h:313
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.
Definition X86Operand.h:737
struct MemOp Mem
Definition X86Operand.h:86
bool isVectorReg() const
Definition X86Operand.h:549
static std::unique_ptr< X86Operand > CreateToken(StringRef Str, SMLoc Loc)
Definition X86Operand.h:688
bool isMemUnsized() const
Definition X86Operand.h:314
const MCExpr * getImm() const
Definition X86Operand.h:179
unsigned getMemFrontendSize() const
Definition X86Operand.h:212
bool isMem8() const
Definition X86Operand.h:317
MCRegister getReg() const override
Definition X86Operand.h:169