1 //===-- X86AsmParser.cpp - Parse X86 assembly to MCInst instructions ------===//
3 // The LLVM Compiler Infrastructure
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
8 //===----------------------------------------------------------------------===//
10 #include "InstPrinter/X86IntelInstPrinter.h"
11 #include "MCTargetDesc/X86BaseInfo.h"
12 #include "MCTargetDesc/X86MCExpr.h"
13 #include "MCTargetDesc/X86TargetStreamer.h"
14 #include "X86AsmInstrumentation.h"
15 #include "X86AsmParserCommon.h"
16 #include "X86Operand.h"
17 #include "llvm/ADT/STLExtras.h"
18 #include "llvm/ADT/SmallString.h"
19 #include "llvm/ADT/SmallVector.h"
20 #include "llvm/ADT/StringSwitch.h"
21 #include "llvm/ADT/Twine.h"
22 #include "llvm/MC/MCContext.h"
23 #include "llvm/MC/MCExpr.h"
24 #include "llvm/MC/MCInst.h"
25 #include "llvm/MC/MCInstrInfo.h"
26 #include "llvm/MC/MCParser/MCAsmLexer.h"
27 #include "llvm/MC/MCParser/MCAsmParser.h"
28 #include "llvm/MC/MCParser/MCParsedAsmOperand.h"
29 #include "llvm/MC/MCParser/MCTargetAsmParser.h"
30 #include "llvm/MC/MCRegisterInfo.h"
31 #include "llvm/MC/MCSection.h"
32 #include "llvm/MC/MCStreamer.h"
33 #include "llvm/MC/MCSubtargetInfo.h"
34 #include "llvm/MC/MCSymbol.h"
35 #include "llvm/Support/SourceMgr.h"
36 #include "llvm/Support/TargetRegistry.h"
37 #include "llvm/Support/raw_ostream.h"
43 static bool checkScale(unsigned Scale, StringRef &ErrMsg) {
44 if (Scale != 1 && Scale != 2 && Scale != 4 && Scale != 8) {
45 ErrMsg = "scale factor in address must be 1, 2, 4 or 8";
53 static const char OpPrecedence[] = {
72 class X86AsmParser : public MCTargetAsmParser {
73 ParseInstructionInfo *InstInfo;
74 std::unique_ptr<X86AsmInstrumentation> Instrumentation;
78 SMLoc consumeToken() {
79 MCAsmParser &Parser = getParser();
80 SMLoc Result = Parser.getTok().getLoc();
85 X86TargetStreamer &getTargetStreamer() {
86 assert(getParser().getStreamer().getTargetStreamer() &&
87 "do not have a target streamer");
88 MCTargetStreamer &TS = *getParser().getStreamer().getTargetStreamer();
89 return static_cast<X86TargetStreamer &>(TS);
92 unsigned MatchInstruction(const OperandVector &Operands, MCInst &Inst,
93 uint64_t &ErrorInfo, bool matchingInlineAsm,
94 unsigned VariantID = 0) {
95 // In Code16GCC mode, match as 32-bit.
97 SwitchMode(X86::Mode32Bit);
98 unsigned rv = MatchInstructionImpl(Operands, Inst, ErrorInfo,
99 matchingInlineAsm, VariantID);
101 SwitchMode(X86::Mode16Bit);
105 enum InfixCalculatorTok {
124 enum IntelOperatorKind {
132 class InfixCalculator {
133 typedef std::pair< InfixCalculatorTok, int64_t > ICToken;
134 SmallVector<InfixCalculatorTok, 4> InfixOperatorStack;
135 SmallVector<ICToken, 4> PostfixStack;
137 bool isUnaryOperator(const InfixCalculatorTok Op) {
138 return Op == IC_NEG || Op == IC_NOT;
142 int64_t popOperand() {
143 assert (!PostfixStack.empty() && "Poped an empty stack!");
144 ICToken Op = PostfixStack.pop_back_val();
145 if (!(Op.first == IC_IMM || Op.first == IC_REGISTER))
146 return -1; // The invalid Scale value will be caught later by checkScale
149 void pushOperand(InfixCalculatorTok Op, int64_t Val = 0) {
150 assert ((Op == IC_IMM || Op == IC_REGISTER) &&
151 "Unexpected operand!");
152 PostfixStack.push_back(std::make_pair(Op, Val));
155 void popOperator() { InfixOperatorStack.pop_back(); }
156 void pushOperator(InfixCalculatorTok Op) {
157 // Push the new operator if the stack is empty.
158 if (InfixOperatorStack.empty()) {
159 InfixOperatorStack.push_back(Op);
163 // Push the new operator if it has a higher precedence than the operator
164 // on the top of the stack or the operator on the top of the stack is a
166 unsigned Idx = InfixOperatorStack.size() - 1;
167 InfixCalculatorTok StackOp = InfixOperatorStack[Idx];
168 if (OpPrecedence[Op] > OpPrecedence[StackOp] || StackOp == IC_LPAREN) {
169 InfixOperatorStack.push_back(Op);
173 // The operator on the top of the stack has higher precedence than the
175 unsigned ParenCount = 0;
177 // Nothing to process.
178 if (InfixOperatorStack.empty())
181 Idx = InfixOperatorStack.size() - 1;
182 StackOp = InfixOperatorStack[Idx];
183 if (!(OpPrecedence[StackOp] >= OpPrecedence[Op] || ParenCount))
186 // If we have an even parentheses count and we see a left parentheses,
187 // then stop processing.
188 if (!ParenCount && StackOp == IC_LPAREN)
191 if (StackOp == IC_RPAREN) {
193 InfixOperatorStack.pop_back();
194 } else if (StackOp == IC_LPAREN) {
196 InfixOperatorStack.pop_back();
198 InfixOperatorStack.pop_back();
199 PostfixStack.push_back(std::make_pair(StackOp, 0));
202 // Push the new operator.
203 InfixOperatorStack.push_back(Op);
207 // Push any remaining operators onto the postfix stack.
208 while (!InfixOperatorStack.empty()) {
209 InfixCalculatorTok StackOp = InfixOperatorStack.pop_back_val();
210 if (StackOp != IC_LPAREN && StackOp != IC_RPAREN)
211 PostfixStack.push_back(std::make_pair(StackOp, 0));
214 if (PostfixStack.empty())
217 SmallVector<ICToken, 16> OperandStack;
218 for (unsigned i = 0, e = PostfixStack.size(); i != e; ++i) {
219 ICToken Op = PostfixStack[i];
220 if (Op.first == IC_IMM || Op.first == IC_REGISTER) {
221 OperandStack.push_back(Op);
222 } else if (isUnaryOperator(Op.first)) {
223 assert (OperandStack.size() > 0 && "Too few operands.");
224 ICToken Operand = OperandStack.pop_back_val();
225 assert (Operand.first == IC_IMM &&
226 "Unary operation with a register!");
229 report_fatal_error("Unexpected operator!");
232 OperandStack.push_back(std::make_pair(IC_IMM, -Operand.second));
235 OperandStack.push_back(std::make_pair(IC_IMM, ~Operand.second));
239 assert (OperandStack.size() > 1 && "Too few operands.");
241 ICToken Op2 = OperandStack.pop_back_val();
242 ICToken Op1 = OperandStack.pop_back_val();
245 report_fatal_error("Unexpected operator!");
248 Val = Op1.second + Op2.second;
249 OperandStack.push_back(std::make_pair(IC_IMM, Val));
252 Val = Op1.second - Op2.second;
253 OperandStack.push_back(std::make_pair(IC_IMM, Val));
256 assert (Op1.first == IC_IMM && Op2.first == IC_IMM &&
257 "Multiply operation with an immediate and a register!");
258 Val = Op1.second * Op2.second;
259 OperandStack.push_back(std::make_pair(IC_IMM, Val));
262 assert (Op1.first == IC_IMM && Op2.first == IC_IMM &&
263 "Divide operation with an immediate and a register!");
264 assert (Op2.second != 0 && "Division by zero!");
265 Val = Op1.second / Op2.second;
266 OperandStack.push_back(std::make_pair(IC_IMM, Val));
269 assert (Op1.first == IC_IMM && Op2.first == IC_IMM &&
270 "Modulo operation with an immediate and a register!");
271 Val = Op1.second % Op2.second;
272 OperandStack.push_back(std::make_pair(IC_IMM, Val));
275 assert (Op1.first == IC_IMM && Op2.first == IC_IMM &&
276 "Or operation with an immediate and a register!");
277 Val = Op1.second | Op2.second;
278 OperandStack.push_back(std::make_pair(IC_IMM, Val));
281 assert(Op1.first == IC_IMM && Op2.first == IC_IMM &&
282 "Xor operation with an immediate and a register!");
283 Val = Op1.second ^ Op2.second;
284 OperandStack.push_back(std::make_pair(IC_IMM, Val));
287 assert (Op1.first == IC_IMM && Op2.first == IC_IMM &&
288 "And operation with an immediate and a register!");
289 Val = Op1.second & Op2.second;
290 OperandStack.push_back(std::make_pair(IC_IMM, Val));
293 assert (Op1.first == IC_IMM && Op2.first == IC_IMM &&
294 "Left shift operation with an immediate and a register!");
295 Val = Op1.second << Op2.second;
296 OperandStack.push_back(std::make_pair(IC_IMM, Val));
299 assert (Op1.first == IC_IMM && Op2.first == IC_IMM &&
300 "Right shift operation with an immediate and a register!");
301 Val = Op1.second >> Op2.second;
302 OperandStack.push_back(std::make_pair(IC_IMM, Val));
307 assert (OperandStack.size() == 1 && "Expected a single result.");
308 return OperandStack.pop_back_val().second;
312 enum IntelExprState {
335 class IntelExprStateMachine {
336 IntelExprState State, PrevState;
337 unsigned BaseReg, IndexReg, TmpReg, Scale;
342 InlineAsmIdentifierInfo Info;
347 IntelExprStateMachine()
348 : State(IES_INIT), PrevState(IES_ERROR), BaseReg(0), IndexReg(0),
349 TmpReg(0), Scale(0), Imm(0), Sym(nullptr), BracCount(0),
352 void addImm(int64_t imm) { Imm += imm; }
353 short getBracCount() { return BracCount; }
354 bool isMemExpr() { return MemExpr; }
355 unsigned getBaseReg() { return BaseReg; }
356 unsigned getIndexReg() { return IndexReg; }
357 unsigned getScale() { return Scale; }
358 const MCExpr *getSym() { return Sym; }
359 StringRef getSymName() { return SymName; }
360 int64_t getImm() { return Imm + IC.execute(); }
361 bool isValidEndState() {
362 return State == IES_RBRAC || State == IES_INTEGER;
364 bool hadError() { return State == IES_ERROR; }
365 InlineAsmIdentifierInfo &getIdentifierInfo() { return Info; }
368 IntelExprState CurrState = State;
377 IC.pushOperator(IC_OR);
380 PrevState = CurrState;
383 IntelExprState CurrState = State;
392 IC.pushOperator(IC_XOR);
395 PrevState = CurrState;
398 IntelExprState CurrState = State;
407 IC.pushOperator(IC_AND);
410 PrevState = CurrState;
413 IntelExprState CurrState = State;
422 IC.pushOperator(IC_LSHIFT);
425 PrevState = CurrState;
428 IntelExprState CurrState = State;
437 IC.pushOperator(IC_RSHIFT);
440 PrevState = CurrState;
442 bool onPlus(StringRef &ErrMsg) {
443 IntelExprState CurrState = State;
452 IC.pushOperator(IC_PLUS);
453 if (CurrState == IES_REGISTER && PrevState != IES_MULTIPLY) {
454 // If we already have a BaseReg, then assume this is the IndexReg with
455 // no explicit scale.
460 ErrMsg = "BaseReg/IndexReg already set!";
469 PrevState = CurrState;
472 bool onMinus(StringRef &ErrMsg) {
473 IntelExprState CurrState = State;
496 // push minus operator if it is not a negate operator
497 if (CurrState == IES_REGISTER || CurrState == IES_RPAREN ||
498 CurrState == IES_INTEGER || CurrState == IES_RBRAC)
499 IC.pushOperator(IC_MINUS);
500 else if (PrevState == IES_REGISTER && CurrState == IES_MULTIPLY) {
501 // We have negate operator for Scale: it's illegal
502 ErrMsg = "Scale can't be negative";
505 IC.pushOperator(IC_NEG);
506 if (CurrState == IES_REGISTER && PrevState != IES_MULTIPLY) {
507 // If we already have a BaseReg, then assume this is the IndexReg with
508 // no explicit scale.
513 ErrMsg = "BaseReg/IndexReg already set!";
522 PrevState = CurrState;
526 IntelExprState CurrState = State;
546 IC.pushOperator(IC_NOT);
549 PrevState = CurrState;
552 bool onRegister(unsigned Reg, StringRef &ErrMsg) {
553 IntelExprState CurrState = State;
561 State = IES_REGISTER;
563 IC.pushOperand(IC_REGISTER);
566 // Index Register - Scale * Register
567 if (PrevState == IES_INTEGER) {
569 ErrMsg = "BaseReg/IndexReg already set!";
572 State = IES_REGISTER;
574 // Get the scale and replace the 'Scale * Register' with '0'.
575 Scale = IC.popOperand();
576 if (checkScale(Scale, ErrMsg))
578 IC.pushOperand(IC_IMM);
585 PrevState = CurrState;
588 bool onIdentifierExpr(const MCExpr *SymRef, StringRef SymRefName,
589 const InlineAsmIdentifierInfo &IDInfo,
590 bool ParsingInlineAsm, StringRef &ErrMsg) {
591 // InlineAsm: Treat an enum value as an integer
592 if (ParsingInlineAsm)
593 if (IDInfo.isKind(InlineAsmIdentifierInfo::IK_EnumVal))
594 return onInteger(IDInfo.Enum.EnumVal, ErrMsg);
595 // Treat a symbolic constant like an integer
596 if (auto *CE = dyn_cast<MCConstantExpr>(SymRef))
597 return onInteger(CE->getValue(), ErrMsg);
599 bool HasSymbol = Sym != nullptr;
612 SymName = SymRefName;
613 IC.pushOperand(IC_IMM);
614 if (ParsingInlineAsm)
619 ErrMsg = "cannot use more than one symbol in memory operand";
622 bool onInteger(int64_t TmpInt, StringRef &ErrMsg) {
623 IntelExprState CurrState = State;
643 if (PrevState == IES_REGISTER && CurrState == IES_MULTIPLY) {
644 // Index Register - Register * Scale
646 ErrMsg = "BaseReg/IndexReg already set!";
651 if (checkScale(Scale, ErrMsg))
653 // Get the scale and replace the 'Register * Scale' with '0'.
656 IC.pushOperand(IC_IMM, TmpInt);
660 PrevState = CurrState;
672 State = IES_MULTIPLY;
673 IC.pushOperator(IC_MULTIPLY);
686 IC.pushOperator(IC_DIVIDE);
699 IC.pushOperator(IC_MOD);
715 IC.pushOperator(IC_PLUS);
718 assert(!BracCount && "BracCount should be zero on parsing's start");
727 IntelExprState CurrState = State;
735 if (BracCount-- != 1)
738 if (CurrState == IES_REGISTER && PrevState != IES_MULTIPLY) {
739 // If we already have a BaseReg, then assume this is the IndexReg with
740 // no explicit scale.
744 assert (!IndexReg && "BaseReg/IndexReg already set!");
751 PrevState = CurrState;
755 IntelExprState CurrState = State;
775 IC.pushOperator(IC_LPAREN);
778 PrevState = CurrState;
790 IC.pushOperator(IC_RPAREN);
796 bool Error(SMLoc L, const Twine &Msg, SMRange Range = None,
797 bool MatchingInlineAsm = false) {
798 MCAsmParser &Parser = getParser();
799 if (MatchingInlineAsm) {
800 if (!getLexer().isAtStartOfStatement())
801 Parser.eatToEndOfStatement();
804 return Parser.Error(L, Msg, Range);
807 std::nullptr_t ErrorOperand(SMLoc Loc, StringRef Msg) {
812 std::unique_ptr<X86Operand> DefaultMemSIOperand(SMLoc Loc);
813 std::unique_ptr<X86Operand> DefaultMemDIOperand(SMLoc Loc);
814 bool IsSIReg(unsigned Reg);
815 unsigned GetSIDIForRegClass(unsigned RegClassID, unsigned Reg, bool IsSIReg);
817 AddDefaultSrcDestOperands(OperandVector &Operands,
818 std::unique_ptr<llvm::MCParsedAsmOperand> &&Src,
819 std::unique_ptr<llvm::MCParsedAsmOperand> &&Dst);
820 bool VerifyAndAdjustOperands(OperandVector &OrigOperands,
821 OperandVector &FinalOperands);
822 std::unique_ptr<X86Operand> ParseOperand();
823 std::unique_ptr<X86Operand> ParseATTOperand();
824 std::unique_ptr<X86Operand> ParseIntelOperand();
825 std::unique_ptr<X86Operand> ParseIntelOffsetOfOperator();
826 bool ParseIntelDotOperator(IntelExprStateMachine &SM, SMLoc &End);
827 unsigned IdentifyIntelInlineAsmOperator(StringRef Name);
828 unsigned ParseIntelInlineAsmOperator(unsigned OpKind);
829 std::unique_ptr<X86Operand> ParseRoundingModeOp(SMLoc Start);
830 bool ParseIntelNamedOperator(StringRef Name, IntelExprStateMachine &SM);
831 void RewriteIntelExpression(IntelExprStateMachine &SM, SMLoc Start,
833 bool ParseIntelExpression(IntelExprStateMachine &SM, SMLoc &End);
834 bool ParseIntelInlineAsmIdentifier(const MCExpr *&Val, StringRef &Identifier,
835 InlineAsmIdentifierInfo &Info,
836 bool IsUnevaluatedOperand, SMLoc &End);
838 std::unique_ptr<X86Operand> ParseMemOperand(unsigned SegReg, SMLoc MemStart);
840 bool ParseIntelMemoryOperandSize(unsigned &Size);
841 std::unique_ptr<X86Operand>
842 CreateMemForInlineAsm(unsigned SegReg, const MCExpr *Disp, unsigned BaseReg,
843 unsigned IndexReg, unsigned Scale, SMLoc Start,
844 SMLoc End, unsigned Size, StringRef Identifier,
845 const InlineAsmIdentifierInfo &Info);
847 bool parseDirectiveEven(SMLoc L);
848 bool ParseDirectiveCode(StringRef IDVal, SMLoc L);
850 /// CodeView FPO data directives.
851 bool parseDirectiveFPOProc(SMLoc L);
852 bool parseDirectiveFPOSetFrame(SMLoc L);
853 bool parseDirectiveFPOPushReg(SMLoc L);
854 bool parseDirectiveFPOStackAlloc(SMLoc L);
855 bool parseDirectiveFPOEndPrologue(SMLoc L);
856 bool parseDirectiveFPOEndProc(SMLoc L);
857 bool parseDirectiveFPOData(SMLoc L);
859 bool validateInstruction(MCInst &Inst, const OperandVector &Ops);
860 bool processInstruction(MCInst &Inst, const OperandVector &Ops);
862 /// Wrapper around MCStreamer::EmitInstruction(). Possibly adds
863 /// instrumentation around Inst.
864 void EmitInstruction(MCInst &Inst, OperandVector &Operands, MCStreamer &Out);
866 bool MatchAndEmitInstruction(SMLoc IDLoc, unsigned &Opcode,
867 OperandVector &Operands, MCStreamer &Out,
869 bool MatchingInlineAsm) override;
871 void MatchFPUWaitAlias(SMLoc IDLoc, X86Operand &Op, OperandVector &Operands,
872 MCStreamer &Out, bool MatchingInlineAsm);
874 bool ErrorMissingFeature(SMLoc IDLoc, uint64_t ErrorInfo,
875 bool MatchingInlineAsm);
877 bool MatchAndEmitATTInstruction(SMLoc IDLoc, unsigned &Opcode,
878 OperandVector &Operands, MCStreamer &Out,
880 bool MatchingInlineAsm);
882 bool MatchAndEmitIntelInstruction(SMLoc IDLoc, unsigned &Opcode,
883 OperandVector &Operands, MCStreamer &Out,
885 bool MatchingInlineAsm);
887 bool OmitRegisterFromClobberLists(unsigned RegNo) override;
889 /// Parses AVX512 specific operand primitives: masked registers ({%k<NUM>}, {z})
890 /// and memory broadcasting ({1to<NUM>}) primitives, updating Operands vector if required.
891 /// return false if no parsing errors occurred, true otherwise.
892 bool HandleAVX512Operand(OperandVector &Operands,
893 const MCParsedAsmOperand &Op);
895 bool ParseZ(std::unique_ptr<X86Operand> &Z, const SMLoc &StartLoc);
897 bool is64BitMode() const {
898 // FIXME: Can tablegen auto-generate this?
899 return getSTI().getFeatureBits()[X86::Mode64Bit];
901 bool is32BitMode() const {
902 // FIXME: Can tablegen auto-generate this?
903 return getSTI().getFeatureBits()[X86::Mode32Bit];
905 bool is16BitMode() const {
906 // FIXME: Can tablegen auto-generate this?
907 return getSTI().getFeatureBits()[X86::Mode16Bit];
909 void SwitchMode(unsigned mode) {
910 MCSubtargetInfo &STI = copySTI();
911 FeatureBitset AllModes({X86::Mode64Bit, X86::Mode32Bit, X86::Mode16Bit});
912 FeatureBitset OldMode = STI.getFeatureBits() & AllModes;
913 uint64_t FB = ComputeAvailableFeatures(
914 STI.ToggleFeature(OldMode.flip(mode)));
915 setAvailableFeatures(FB);
917 assert(FeatureBitset({mode}) == (STI.getFeatureBits() & AllModes));
920 unsigned getPointerWidth() {
921 if (is16BitMode()) return 16;
922 if (is32BitMode()) return 32;
923 if (is64BitMode()) return 64;
924 llvm_unreachable("invalid mode");
927 bool isParsingIntelSyntax() {
928 return getParser().getAssemblerDialect();
931 /// @name Auto-generated Matcher Functions
934 #define GET_ASSEMBLER_HEADER
935 #include "X86GenAsmMatcher.inc"
941 X86AsmParser(const MCSubtargetInfo &sti, MCAsmParser &Parser,
942 const MCInstrInfo &mii, const MCTargetOptions &Options)
943 : MCTargetAsmParser(Options, sti, mii), InstInfo(nullptr),
946 Parser.addAliasForDirective(".word", ".2byte");
948 // Initialize the set of available features.
949 setAvailableFeatures(ComputeAvailableFeatures(getSTI().getFeatureBits()));
950 Instrumentation.reset(
951 CreateX86AsmInstrumentation(Options, Parser.getContext(), STI));
954 bool ParseRegister(unsigned &RegNo, SMLoc &StartLoc, SMLoc &EndLoc) override;
956 void SetFrameRegister(unsigned RegNo) override;
958 bool parseAssignmentExpression(const MCExpr *&Res, SMLoc &EndLoc) override;
960 bool ParseInstruction(ParseInstructionInfo &Info, StringRef Name,
961 SMLoc NameLoc, OperandVector &Operands) override;
963 bool ParseDirective(AsmToken DirectiveID) override;
965 } // end anonymous namespace
967 /// @name Auto-generated Match Functions
970 static unsigned MatchRegisterName(StringRef Name);
974 static bool CheckBaseRegAndIndexRegAndScale(unsigned BaseReg, unsigned IndexReg,
975 unsigned Scale, bool Is64BitMode,
977 // If we have both a base register and an index register make sure they are
978 // both 64-bit or 32-bit registers.
979 // To support VSIB, IndexReg can be 128-bit or 256-bit registers.
982 !(BaseReg == X86::RIP || BaseReg == X86::EIP ||
983 X86MCRegisterClasses[X86::GR16RegClassID].contains(BaseReg) ||
984 X86MCRegisterClasses[X86::GR32RegClassID].contains(BaseReg) ||
985 X86MCRegisterClasses[X86::GR64RegClassID].contains(BaseReg))) {
986 ErrMsg = "invalid base+index expression";
991 !(IndexReg == X86::EIZ || IndexReg == X86::RIZ ||
992 X86MCRegisterClasses[X86::GR16RegClassID].contains(IndexReg) ||
993 X86MCRegisterClasses[X86::GR32RegClassID].contains(IndexReg) ||
994 X86MCRegisterClasses[X86::GR64RegClassID].contains(IndexReg) ||
995 X86MCRegisterClasses[X86::VR128XRegClassID].contains(IndexReg) ||
996 X86MCRegisterClasses[X86::VR256XRegClassID].contains(IndexReg) ||
997 X86MCRegisterClasses[X86::VR512RegClassID].contains(IndexReg))) {
998 ErrMsg = "invalid base+index expression";
1002 if (((BaseReg == X86::RIP || BaseReg == X86::EIP) && IndexReg != 0) ||
1003 IndexReg == X86::EIP || IndexReg == X86::RIP ||
1004 IndexReg == X86::ESP || IndexReg == X86::RSP) {
1005 ErrMsg = "invalid base+index expression";
1009 // Check for use of invalid 16-bit registers. Only BX/BP/SI/DI are allowed,
1010 // and then only in non-64-bit modes.
1011 if (X86MCRegisterClasses[X86::GR16RegClassID].contains(BaseReg) &&
1012 (Is64BitMode || (BaseReg != X86::BX && BaseReg != X86::BP &&
1013 BaseReg != X86::SI && BaseReg != X86::DI)) &&
1014 BaseReg != X86::DX) {
1015 ErrMsg = "invalid 16-bit base register";
1020 X86MCRegisterClasses[X86::GR16RegClassID].contains(IndexReg)) {
1021 ErrMsg = "16-bit memory operand may not include only index register";
1025 if (BaseReg != 0 && IndexReg != 0) {
1026 if (X86MCRegisterClasses[X86::GR64RegClassID].contains(BaseReg) &&
1027 (X86MCRegisterClasses[X86::GR16RegClassID].contains(IndexReg) ||
1028 X86MCRegisterClasses[X86::GR32RegClassID].contains(IndexReg) ||
1029 IndexReg == X86::EIZ)) {
1030 ErrMsg = "base register is 64-bit, but index register is not";
1033 if (X86MCRegisterClasses[X86::GR32RegClassID].contains(BaseReg) &&
1034 (X86MCRegisterClasses[X86::GR16RegClassID].contains(IndexReg) ||
1035 X86MCRegisterClasses[X86::GR64RegClassID].contains(IndexReg) ||
1036 IndexReg == X86::RIZ)) {
1037 ErrMsg = "base register is 32-bit, but index register is not";
1040 if (X86MCRegisterClasses[X86::GR16RegClassID].contains(BaseReg)) {
1041 if (X86MCRegisterClasses[X86::GR32RegClassID].contains(IndexReg) ||
1042 X86MCRegisterClasses[X86::GR64RegClassID].contains(IndexReg)) {
1043 ErrMsg = "base register is 16-bit, but index register is not";
1046 if ((BaseReg != X86::BX && BaseReg != X86::BP) ||
1047 (IndexReg != X86::SI && IndexReg != X86::DI)) {
1048 ErrMsg = "invalid 16-bit base/index register combination";
1054 // RIP/EIP-relative addressing is only supported in 64-bit mode.
1055 if (!Is64BitMode && BaseReg != 0 &&
1056 (BaseReg == X86::RIP || BaseReg == X86::EIP)) {
1057 ErrMsg = "RIP-relative addressing requires 64-bit mode";
1061 return checkScale(Scale, ErrMsg);
1064 bool X86AsmParser::ParseRegister(unsigned &RegNo,
1065 SMLoc &StartLoc, SMLoc &EndLoc) {
1066 MCAsmParser &Parser = getParser();
1068 const AsmToken &PercentTok = Parser.getTok();
1069 StartLoc = PercentTok.getLoc();
1071 // If we encounter a %, ignore it. This code handles registers with and
1072 // without the prefix, unprefixed registers can occur in cfi directives.
1073 if (!isParsingIntelSyntax() && PercentTok.is(AsmToken::Percent))
1074 Parser.Lex(); // Eat percent token.
1076 const AsmToken &Tok = Parser.getTok();
1077 EndLoc = Tok.getEndLoc();
1079 if (Tok.isNot(AsmToken::Identifier)) {
1080 if (isParsingIntelSyntax()) return true;
1081 return Error(StartLoc, "invalid register name",
1082 SMRange(StartLoc, EndLoc));
1085 RegNo = MatchRegisterName(Tok.getString());
1087 // If the match failed, try the register name as lowercase.
1089 RegNo = MatchRegisterName(Tok.getString().lower());
1091 // The "flags" register cannot be referenced directly.
1092 // Treat it as an identifier instead.
1093 if (isParsingInlineAsm() && isParsingIntelSyntax() && RegNo == X86::EFLAGS)
1096 if (!is64BitMode()) {
1097 // FIXME: This should be done using Requires<Not64BitMode> and
1098 // Requires<In64BitMode> so "eiz" usage in 64-bit instructions can be also
1100 // FIXME: Check AH, CH, DH, BH cannot be used in an instruction requiring a
1102 if (RegNo == X86::RIZ || RegNo == X86::RIP || RegNo == X86::EIP ||
1103 X86MCRegisterClasses[X86::GR64RegClassID].contains(RegNo) ||
1104 X86II::isX86_64NonExtLowByteReg(RegNo) ||
1105 X86II::isX86_64ExtendedReg(RegNo))
1106 return Error(StartLoc, "register %"
1107 + Tok.getString() + " is only available in 64-bit mode",
1108 SMRange(StartLoc, EndLoc));
1111 // Parse "%st" as "%st(0)" and "%st(1)", which is multiple tokens.
1112 if (RegNo == 0 && (Tok.getString() == "st" || Tok.getString() == "ST")) {
1114 Parser.Lex(); // Eat 'st'
1116 // Check to see if we have '(4)' after %st.
1117 if (getLexer().isNot(AsmToken::LParen))
1122 const AsmToken &IntTok = Parser.getTok();
1123 if (IntTok.isNot(AsmToken::Integer))
1124 return Error(IntTok.getLoc(), "expected stack index");
1125 switch (IntTok.getIntVal()) {
1126 case 0: RegNo = X86::ST0; break;
1127 case 1: RegNo = X86::ST1; break;
1128 case 2: RegNo = X86::ST2; break;
1129 case 3: RegNo = X86::ST3; break;
1130 case 4: RegNo = X86::ST4; break;
1131 case 5: RegNo = X86::ST5; break;
1132 case 6: RegNo = X86::ST6; break;
1133 case 7: RegNo = X86::ST7; break;
1134 default: return Error(IntTok.getLoc(), "invalid stack index");
1137 if (getParser().Lex().isNot(AsmToken::RParen))
1138 return Error(Parser.getTok().getLoc(), "expected ')'");
1140 EndLoc = Parser.getTok().getEndLoc();
1141 Parser.Lex(); // Eat ')'
1145 EndLoc = Parser.getTok().getEndLoc();
1147 // If this is "db[0-15]", match it as an alias
1149 if (RegNo == 0 && Tok.getString().startswith("db")) {
1150 if (Tok.getString().size() == 3) {
1151 switch (Tok.getString()[2]) {
1152 case '0': RegNo = X86::DR0; break;
1153 case '1': RegNo = X86::DR1; break;
1154 case '2': RegNo = X86::DR2; break;
1155 case '3': RegNo = X86::DR3; break;
1156 case '4': RegNo = X86::DR4; break;
1157 case '5': RegNo = X86::DR5; break;
1158 case '6': RegNo = X86::DR6; break;
1159 case '7': RegNo = X86::DR7; break;
1160 case '8': RegNo = X86::DR8; break;
1161 case '9': RegNo = X86::DR9; break;
1163 } else if (Tok.getString().size() == 4 && Tok.getString()[2] == '1') {
1164 switch (Tok.getString()[3]) {
1165 case '0': RegNo = X86::DR10; break;
1166 case '1': RegNo = X86::DR11; break;
1167 case '2': RegNo = X86::DR12; break;
1168 case '3': RegNo = X86::DR13; break;
1169 case '4': RegNo = X86::DR14; break;
1170 case '5': RegNo = X86::DR15; break;
1175 EndLoc = Parser.getTok().getEndLoc();
1176 Parser.Lex(); // Eat it.
1182 if (isParsingIntelSyntax()) return true;
1183 return Error(StartLoc, "invalid register name",
1184 SMRange(StartLoc, EndLoc));
1187 Parser.Lex(); // Eat identifier token.
1191 void X86AsmParser::SetFrameRegister(unsigned RegNo) {
1192 Instrumentation->SetInitialFrameRegister(RegNo);
1195 std::unique_ptr<X86Operand> X86AsmParser::DefaultMemSIOperand(SMLoc Loc) {
1196 bool Parse32 = is32BitMode() || Code16GCC;
1197 unsigned Basereg = is64BitMode() ? X86::RSI : (Parse32 ? X86::ESI : X86::SI);
1198 const MCExpr *Disp = MCConstantExpr::create(0, getContext());
1199 return X86Operand::CreateMem(getPointerWidth(), /*SegReg=*/0, Disp,
1200 /*BaseReg=*/Basereg, /*IndexReg=*/0, /*Scale=*/1,
1204 std::unique_ptr<X86Operand> X86AsmParser::DefaultMemDIOperand(SMLoc Loc) {
1205 bool Parse32 = is32BitMode() || Code16GCC;
1206 unsigned Basereg = is64BitMode() ? X86::RDI : (Parse32 ? X86::EDI : X86::DI);
1207 const MCExpr *Disp = MCConstantExpr::create(0, getContext());
1208 return X86Operand::CreateMem(getPointerWidth(), /*SegReg=*/0, Disp,
1209 /*BaseReg=*/Basereg, /*IndexReg=*/0, /*Scale=*/1,
1213 bool X86AsmParser::IsSIReg(unsigned Reg) {
1215 default: llvm_unreachable("Only (R|E)SI and (R|E)DI are expected!");
1227 unsigned X86AsmParser::GetSIDIForRegClass(unsigned RegClassID, unsigned Reg,
1229 switch (RegClassID) {
1230 default: llvm_unreachable("Unexpected register class");
1231 case X86::GR64RegClassID:
1232 return IsSIReg ? X86::RSI : X86::RDI;
1233 case X86::GR32RegClassID:
1234 return IsSIReg ? X86::ESI : X86::EDI;
1235 case X86::GR16RegClassID:
1236 return IsSIReg ? X86::SI : X86::DI;
1240 void X86AsmParser::AddDefaultSrcDestOperands(
1241 OperandVector& Operands, std::unique_ptr<llvm::MCParsedAsmOperand> &&Src,
1242 std::unique_ptr<llvm::MCParsedAsmOperand> &&Dst) {
1243 if (isParsingIntelSyntax()) {
1244 Operands.push_back(std::move(Dst));
1245 Operands.push_back(std::move(Src));
1248 Operands.push_back(std::move(Src));
1249 Operands.push_back(std::move(Dst));
1253 bool X86AsmParser::VerifyAndAdjustOperands(OperandVector &OrigOperands,
1254 OperandVector &FinalOperands) {
1256 if (OrigOperands.size() > 1) {
1257 // Check if sizes match, OrigOperands also contains the instruction name
1258 assert(OrigOperands.size() == FinalOperands.size() + 1 &&
1259 "Operand size mismatch");
1261 SmallVector<std::pair<SMLoc, std::string>, 2> Warnings;
1262 // Verify types match
1263 int RegClassID = -1;
1264 for (unsigned int i = 0; i < FinalOperands.size(); ++i) {
1265 X86Operand &OrigOp = static_cast<X86Operand &>(*OrigOperands[i + 1]);
1266 X86Operand &FinalOp = static_cast<X86Operand &>(*FinalOperands[i]);
1268 if (FinalOp.isReg() &&
1269 (!OrigOp.isReg() || FinalOp.getReg() != OrigOp.getReg()))
1270 // Return false and let a normal complaint about bogus operands happen
1273 if (FinalOp.isMem()) {
1275 if (!OrigOp.isMem())
1276 // Return false and let a normal complaint about bogus operands happen
1279 unsigned OrigReg = OrigOp.Mem.BaseReg;
1280 unsigned FinalReg = FinalOp.Mem.BaseReg;
1282 // If we've already encounterd a register class, make sure all register
1283 // bases are of the same register class
1284 if (RegClassID != -1 &&
1285 !X86MCRegisterClasses[RegClassID].contains(OrigReg)) {
1286 return Error(OrigOp.getStartLoc(),
1287 "mismatching source and destination index registers");
1290 if (X86MCRegisterClasses[X86::GR64RegClassID].contains(OrigReg))
1291 RegClassID = X86::GR64RegClassID;
1292 else if (X86MCRegisterClasses[X86::GR32RegClassID].contains(OrigReg))
1293 RegClassID = X86::GR32RegClassID;
1294 else if (X86MCRegisterClasses[X86::GR16RegClassID].contains(OrigReg))
1295 RegClassID = X86::GR16RegClassID;
1297 // Unexpected register class type
1298 // Return false and let a normal complaint about bogus operands happen
1301 bool IsSI = IsSIReg(FinalReg);
1302 FinalReg = GetSIDIForRegClass(RegClassID, FinalReg, IsSI);
1304 if (FinalReg != OrigReg) {
1305 std::string RegName = IsSI ? "ES:(R|E)SI" : "ES:(R|E)DI";
1306 Warnings.push_back(std::make_pair(
1307 OrigOp.getStartLoc(),
1308 "memory operand is only for determining the size, " + RegName +
1309 " will be used for the location"));
1312 FinalOp.Mem.Size = OrigOp.Mem.Size;
1313 FinalOp.Mem.SegReg = OrigOp.Mem.SegReg;
1314 FinalOp.Mem.BaseReg = FinalReg;
1318 // Produce warnings only if all the operands passed the adjustment - prevent
1319 // legal cases like "movsd (%rax), %xmm0" mistakenly produce warnings
1320 for (auto &WarningMsg : Warnings) {
1321 Warning(WarningMsg.first, WarningMsg.second);
1324 // Remove old operands
1325 for (unsigned int i = 0; i < FinalOperands.size(); ++i)
1326 OrigOperands.pop_back();
1328 // OrigOperands.append(FinalOperands.begin(), FinalOperands.end());
1329 for (unsigned int i = 0; i < FinalOperands.size(); ++i)
1330 OrigOperands.push_back(std::move(FinalOperands[i]));
1335 std::unique_ptr<X86Operand> X86AsmParser::ParseOperand() {
1336 if (isParsingIntelSyntax())
1337 return ParseIntelOperand();
1338 return ParseATTOperand();
1341 std::unique_ptr<X86Operand> X86AsmParser::CreateMemForInlineAsm(
1342 unsigned SegReg, const MCExpr *Disp, unsigned BaseReg, unsigned IndexReg,
1343 unsigned Scale, SMLoc Start, SMLoc End, unsigned Size, StringRef Identifier,
1344 const InlineAsmIdentifierInfo &Info) {
1345 // If we found a decl other than a VarDecl, then assume it is a FuncDecl or
1346 // some other label reference.
1347 if (Info.isKind(InlineAsmIdentifierInfo::IK_Label)) {
1348 // Insert an explicit size if the user didn't have one.
1350 Size = getPointerWidth();
1351 InstInfo->AsmRewrites->emplace_back(AOK_SizeDirective, Start,
1354 // Create an absolute memory reference in order to match against
1355 // instructions taking a PC relative operand.
1356 return X86Operand::CreateMem(getPointerWidth(), Disp, Start, End, Size,
1357 Identifier, Info.Label.Decl);
1359 // We either have a direct symbol reference, or an offset from a symbol. The
1360 // parser always puts the symbol on the LHS, so look there for size
1361 // calculation purposes.
1362 unsigned FrontendSize = 0;
1363 void *Decl = nullptr;
1364 bool IsGlobalLV = false;
1365 if (Info.isKind(InlineAsmIdentifierInfo::IK_Var)) {
1366 // Size is in terms of bits in this context.
1367 FrontendSize = Info.Var.Type * 8;
1368 Decl = Info.Var.Decl;
1369 IsGlobalLV = Info.Var.IsGlobalLV;
1371 // It is widely common for MS InlineAsm to use a global variable and one/two
1372 // registers in a mmory expression, and though unaccessible via rip/eip.
1373 if (IsGlobalLV && (BaseReg || IndexReg)) {
1374 return X86Operand::CreateMem(getPointerWidth(), Disp, Start, End);
1375 // Otherwise, we set the base register to a non-zero value
1376 // if we don't know the actual value at this time. This is necessary to
1377 // get the matching correct in some cases.
1379 BaseReg = BaseReg ? BaseReg : 1;
1380 return X86Operand::CreateMem(getPointerWidth(), SegReg, Disp, BaseReg,
1381 IndexReg, Scale, Start, End, Size, Identifier,
1382 Decl, FrontendSize);
1386 // Some binary bitwise operators have a named synonymous
1387 // Query a candidate string for being such a named operator
1388 // and if so - invoke the appropriate handler
1389 bool X86AsmParser::ParseIntelNamedOperator(StringRef Name, IntelExprStateMachine &SM) {
1390 // A named operator should be either lower or upper case, but not a mix
1391 if (Name.compare(Name.lower()) && Name.compare(Name.upper()))
1393 if (Name.equals_lower("not"))
1395 else if (Name.equals_lower("or"))
1397 else if (Name.equals_lower("shl"))
1399 else if (Name.equals_lower("shr"))
1401 else if (Name.equals_lower("xor"))
1403 else if (Name.equals_lower("and"))
1405 else if (Name.equals_lower("mod"))
1412 bool X86AsmParser::ParseIntelExpression(IntelExprStateMachine &SM, SMLoc &End) {
1413 MCAsmParser &Parser = getParser();
1414 const AsmToken &Tok = Parser.getTok();
1417 AsmToken::TokenKind PrevTK = AsmToken::Error;
1420 bool UpdateLocLex = true;
1421 AsmToken::TokenKind TK = getLexer().getKind();
1425 if ((Done = SM.isValidEndState()))
1427 return Error(Tok.getLoc(), "unknown token in expression");
1428 case AsmToken::EndOfStatement:
1431 case AsmToken::Real:
1432 // DotOperator: [ebx].0
1433 UpdateLocLex = false;
1434 if (ParseIntelDotOperator(SM, End))
1438 case AsmToken::String:
1439 case AsmToken::Identifier: {
1440 SMLoc IdentLoc = Tok.getLoc();
1441 StringRef Identifier = Tok.getString();
1442 UpdateLocLex = false;
1445 if (Tok.is(AsmToken::Identifier) && !ParseRegister(Reg, IdentLoc, End)) {
1446 if (SM.onRegister(Reg, ErrMsg))
1447 return Error(Tok.getLoc(), ErrMsg);
1450 // Operator synonymous ("not", "or" etc.)
1451 if ((UpdateLocLex = ParseIntelNamedOperator(Identifier, SM)))
1453 // Symbol reference, when parsing assembly content
1454 InlineAsmIdentifierInfo Info;
1456 if (!isParsingInlineAsm()) {
1457 if (getParser().parsePrimaryExpr(Val, End)) {
1458 return Error(Tok.getLoc(), "Unexpected identifier!");
1459 } else if (SM.onIdentifierExpr(Val, Identifier, Info, false, ErrMsg)) {
1460 return Error(IdentLoc, ErrMsg);
1464 // MS InlineAsm operators (TYPE/LENGTH/SIZE)
1465 if (unsigned OpKind = IdentifyIntelInlineAsmOperator(Identifier)) {
1466 if (OpKind == IOK_OFFSET)
1467 return Error(IdentLoc, "Dealing OFFSET operator as part of"
1468 "a compound immediate expression is yet to be supported");
1469 if (int64_t Val = ParseIntelInlineAsmOperator(OpKind)) {
1470 if (SM.onInteger(Val, ErrMsg))
1471 return Error(IdentLoc, ErrMsg);
1476 // MS Dot Operator expression
1477 if (Identifier.count('.') && PrevTK == AsmToken::RBrac) {
1478 if (ParseIntelDotOperator(SM, End))
1482 // MS InlineAsm identifier
1483 // Call parseIdentifier() to combine @ with the identifier behind it.
1484 if (TK == AsmToken::At && Parser.parseIdentifier(Identifier))
1485 return Error(IdentLoc, "expected identifier");
1486 if (ParseIntelInlineAsmIdentifier(Val, Identifier, Info, false, End))
1488 else if (SM.onIdentifierExpr(Val, Identifier, Info, true, ErrMsg))
1489 return Error(IdentLoc, ErrMsg);
1492 case AsmToken::Integer: {
1493 // Look for 'b' or 'f' following an Integer as a directional label
1494 SMLoc Loc = getTok().getLoc();
1495 int64_t IntVal = getTok().getIntVal();
1496 End = consumeToken();
1497 UpdateLocLex = false;
1498 if (getLexer().getKind() == AsmToken::Identifier) {
1499 StringRef IDVal = getTok().getString();
1500 if (IDVal == "f" || IDVal == "b") {
1502 getContext().getDirectionalLocalSymbol(IntVal, IDVal == "b");
1503 MCSymbolRefExpr::VariantKind Variant = MCSymbolRefExpr::VK_None;
1505 MCSymbolRefExpr::create(Sym, Variant, getContext());
1506 if (IDVal == "b" && Sym->isUndefined())
1507 return Error(Loc, "invalid reference to undefined symbol");
1508 StringRef Identifier = Sym->getName();
1509 InlineAsmIdentifierInfo Info;
1510 if (SM.onIdentifierExpr(Val, Identifier, Info,
1511 isParsingInlineAsm(), ErrMsg))
1512 return Error(Loc, ErrMsg);
1513 End = consumeToken();
1515 if (SM.onInteger(IntVal, ErrMsg))
1516 return Error(Loc, ErrMsg);
1519 if (SM.onInteger(IntVal, ErrMsg))
1520 return Error(Loc, ErrMsg);
1524 case AsmToken::Plus:
1525 if (SM.onPlus(ErrMsg))
1526 return Error(getTok().getLoc(), ErrMsg);
1528 case AsmToken::Minus:
1529 if (SM.onMinus(ErrMsg))
1530 return Error(getTok().getLoc(), ErrMsg);
1532 case AsmToken::Tilde: SM.onNot(); break;
1533 case AsmToken::Star: SM.onStar(); break;
1534 case AsmToken::Slash: SM.onDivide(); break;
1535 case AsmToken::Percent: SM.onMod(); break;
1536 case AsmToken::Pipe: SM.onOr(); break;
1537 case AsmToken::Caret: SM.onXor(); break;
1538 case AsmToken::Amp: SM.onAnd(); break;
1539 case AsmToken::LessLess:
1540 SM.onLShift(); break;
1541 case AsmToken::GreaterGreater:
1542 SM.onRShift(); break;
1543 case AsmToken::LBrac:
1545 return Error(Tok.getLoc(), "unexpected bracket encountered");
1547 case AsmToken::RBrac:
1549 return Error(Tok.getLoc(), "unexpected bracket encountered");
1551 case AsmToken::LParen: SM.onLParen(); break;
1552 case AsmToken::RParen: SM.onRParen(); break;
1555 return Error(Tok.getLoc(), "unknown token in expression");
1557 if (!Done && UpdateLocLex)
1558 End = consumeToken();
1565 void X86AsmParser::RewriteIntelExpression(IntelExprStateMachine &SM,
1566 SMLoc Start, SMLoc End) {
1568 unsigned ExprLen = End.getPointer() - Start.getPointer();
1569 // Skip everything before a symbol displacement (if we have one)
1571 StringRef SymName = SM.getSymName();
1572 if (unsigned Len = SymName.data() - Start.getPointer())
1573 InstInfo->AsmRewrites->emplace_back(AOK_Skip, Start, Len);
1574 Loc = SMLoc::getFromPointer(SymName.data() + SymName.size());
1575 ExprLen = End.getPointer() - (SymName.data() + SymName.size());
1576 // If we have only a symbol than there's no need for complex rewrite,
1577 // simply skip everything after it
1578 if (!(SM.getBaseReg() || SM.getIndexReg() || SM.getImm())) {
1580 InstInfo->AsmRewrites->emplace_back(AOK_Skip, Loc, ExprLen);
1584 // Build an Intel Expression rewrite
1585 StringRef BaseRegStr;
1586 StringRef IndexRegStr;
1587 if (SM.getBaseReg())
1588 BaseRegStr = X86IntelInstPrinter::getRegisterName(SM.getBaseReg());
1589 if (SM.getIndexReg())
1590 IndexRegStr = X86IntelInstPrinter::getRegisterName(SM.getIndexReg());
1592 IntelExpr Expr(BaseRegStr, IndexRegStr, SM.getScale(), SM.getImm(), SM.isMemExpr());
1593 InstInfo->AsmRewrites->emplace_back(Loc, ExprLen, Expr);
1596 // Inline assembly may use variable names with namespace alias qualifiers.
1597 bool X86AsmParser::ParseIntelInlineAsmIdentifier(const MCExpr *&Val,
1598 StringRef &Identifier,
1599 InlineAsmIdentifierInfo &Info,
1600 bool IsUnevaluatedOperand,
1602 MCAsmParser &Parser = getParser();
1603 assert(isParsingInlineAsm() && "Expected to be parsing inline assembly.");
1606 StringRef LineBuf(Identifier.data());
1607 SemaCallback->LookupInlineAsmIdentifier(LineBuf, Info, IsUnevaluatedOperand);
1609 const AsmToken &Tok = Parser.getTok();
1610 SMLoc Loc = Tok.getLoc();
1612 // Advance the token stream until the end of the current token is
1613 // after the end of what the frontend claimed.
1614 const char *EndPtr = Tok.getLoc().getPointer() + LineBuf.size();
1616 End = Tok.getEndLoc();
1618 } while (End.getPointer() < EndPtr);
1619 Identifier = LineBuf;
1621 // The frontend should end parsing on an assembler token boundary, unless it
1623 assert((End.getPointer() == EndPtr ||
1624 Info.isKind(InlineAsmIdentifierInfo::IK_Invalid)) &&
1625 "frontend claimed part of a token?");
1627 // If the identifier lookup was unsuccessful, assume that we are dealing with
1629 if (Info.isKind(InlineAsmIdentifierInfo::IK_Invalid)) {
1630 StringRef InternalName =
1631 SemaCallback->LookupInlineAsmLabel(Identifier, getSourceManager(),
1633 assert(InternalName.size() && "We should have an internal name here.");
1634 // Push a rewrite for replacing the identifier name with the internal name.
1635 InstInfo->AsmRewrites->emplace_back(AOK_Label, Loc, Identifier.size(),
1637 } else if (Info.isKind(InlineAsmIdentifierInfo::IK_EnumVal))
1639 // Create the symbol reference.
1640 MCSymbol *Sym = getContext().getOrCreateSymbol(Identifier);
1641 MCSymbolRefExpr::VariantKind Variant = MCSymbolRefExpr::VK_None;
1642 Val = MCSymbolRefExpr::create(Sym, Variant, getParser().getContext());
1646 //ParseRoundingModeOp - Parse AVX-512 rounding mode operand
1647 std::unique_ptr<X86Operand>
1648 X86AsmParser::ParseRoundingModeOp(SMLoc Start) {
1649 MCAsmParser &Parser = getParser();
1650 const AsmToken &Tok = Parser.getTok();
1651 // Eat "{" and mark the current place.
1652 const SMLoc consumedToken = consumeToken();
1653 if (Tok.getIdentifier().startswith("r")){
1654 int rndMode = StringSwitch<int>(Tok.getIdentifier())
1655 .Case("rn", X86::STATIC_ROUNDING::TO_NEAREST_INT)
1656 .Case("rd", X86::STATIC_ROUNDING::TO_NEG_INF)
1657 .Case("ru", X86::STATIC_ROUNDING::TO_POS_INF)
1658 .Case("rz", X86::STATIC_ROUNDING::TO_ZERO)
1661 return ErrorOperand(Tok.getLoc(), "Invalid rounding mode.");
1662 Parser.Lex(); // Eat "r*" of r*-sae
1663 if (!getLexer().is(AsmToken::Minus))
1664 return ErrorOperand(Tok.getLoc(), "Expected - at this point");
1665 Parser.Lex(); // Eat "-"
1666 Parser.Lex(); // Eat the sae
1667 if (!getLexer().is(AsmToken::RCurly))
1668 return ErrorOperand(Tok.getLoc(), "Expected } at this point");
1669 SMLoc End = Tok.getEndLoc();
1670 Parser.Lex(); // Eat "}"
1671 const MCExpr *RndModeOp =
1672 MCConstantExpr::create(rndMode, Parser.getContext());
1673 return X86Operand::CreateImm(RndModeOp, Start, End);
1675 if(Tok.getIdentifier().equals("sae")){
1676 Parser.Lex(); // Eat the sae
1677 if (!getLexer().is(AsmToken::RCurly))
1678 return ErrorOperand(Tok.getLoc(), "Expected } at this point");
1679 Parser.Lex(); // Eat "}"
1680 return X86Operand::CreateToken("{sae}", consumedToken);
1682 return ErrorOperand(Tok.getLoc(), "unknown token in expression");
1685 /// Parse the '.' operator.
1686 bool X86AsmParser::ParseIntelDotOperator(IntelExprStateMachine &SM, SMLoc &End) {
1687 const AsmToken &Tok = getTok();
1690 // Drop the optional '.'.
1691 StringRef DotDispStr = Tok.getString();
1692 if (DotDispStr.startswith("."))
1693 DotDispStr = DotDispStr.drop_front(1);
1695 // .Imm gets lexed as a real.
1696 if (Tok.is(AsmToken::Real)) {
1698 DotDispStr.getAsInteger(10, DotDisp);
1699 Offset = DotDisp.getZExtValue();
1700 } else if (isParsingInlineAsm() && Tok.is(AsmToken::Identifier)) {
1701 std::pair<StringRef, StringRef> BaseMember = DotDispStr.split('.');
1702 if (SemaCallback->LookupInlineAsmField(BaseMember.first, BaseMember.second,
1704 return Error(Tok.getLoc(), "Unable to lookup field reference!");
1706 return Error(Tok.getLoc(), "Unexpected token type!");
1708 // Eat the DotExpression and update End
1709 End = SMLoc::getFromPointer(DotDispStr.data());
1710 const char *DotExprEndLoc = DotDispStr.data() + DotDispStr.size();
1711 while (Tok.getLoc().getPointer() < DotExprEndLoc)
1717 /// Parse the 'offset' operator. This operator is used to specify the
1718 /// location rather then the content of a variable.
1719 std::unique_ptr<X86Operand> X86AsmParser::ParseIntelOffsetOfOperator() {
1720 MCAsmParser &Parser = getParser();
1721 const AsmToken &Tok = Parser.getTok();
1722 SMLoc OffsetOfLoc = Tok.getLoc();
1723 Parser.Lex(); // Eat offset.
1726 InlineAsmIdentifierInfo Info;
1727 SMLoc Start = Tok.getLoc(), End;
1728 StringRef Identifier = Tok.getString();
1729 if (ParseIntelInlineAsmIdentifier(Val, Identifier, Info,
1730 /*Unevaluated=*/false, End))
1733 void *Decl = nullptr;
1734 // FIXME: MS evaluates "offset <Constant>" to the underlying integral
1735 if (Info.isKind(InlineAsmIdentifierInfo::IK_EnumVal))
1736 return ErrorOperand(Start, "offset operator cannot yet handle constants");
1737 else if (Info.isKind(InlineAsmIdentifierInfo::IK_Var))
1738 Decl = Info.Var.Decl;
1739 // Don't emit the offset operator.
1740 InstInfo->AsmRewrites->emplace_back(AOK_Skip, OffsetOfLoc, 7);
1742 // The offset operator will have an 'r' constraint, thus we need to create
1743 // register operand to ensure proper matching. Just pick a GPR based on
1744 // the size of a pointer.
1745 bool Parse32 = is32BitMode() || Code16GCC;
1746 unsigned RegNo = is64BitMode() ? X86::RBX : (Parse32 ? X86::EBX : X86::BX);
1748 return X86Operand::CreateReg(RegNo, Start, End, /*GetAddress=*/true,
1749 OffsetOfLoc, Identifier, Decl);
1752 // Query a candidate string for being an Intel assembly operator
1753 // Report back its kind, or IOK_INVALID if does not evaluated as a known one
1754 unsigned X86AsmParser::IdentifyIntelInlineAsmOperator(StringRef Name) {
1755 return StringSwitch<unsigned>(Name)
1756 .Cases("TYPE","type",IOK_TYPE)
1757 .Cases("SIZE","size",IOK_SIZE)
1758 .Cases("LENGTH","length",IOK_LENGTH)
1759 .Cases("OFFSET","offset",IOK_OFFSET)
1760 .Default(IOK_INVALID);
1763 /// Parse the 'LENGTH', 'TYPE' and 'SIZE' operators. The LENGTH operator
1764 /// returns the number of elements in an array. It returns the value 1 for
1765 /// non-array variables. The SIZE operator returns the size of a C or C++
1766 /// variable. A variable's size is the product of its LENGTH and TYPE. The
1767 /// TYPE operator returns the size of a C or C++ type or variable. If the
1768 /// variable is an array, TYPE returns the size of a single element.
1769 unsigned X86AsmParser::ParseIntelInlineAsmOperator(unsigned OpKind) {
1770 MCAsmParser &Parser = getParser();
1771 const AsmToken &Tok = Parser.getTok();
1772 Parser.Lex(); // Eat operator.
1774 const MCExpr *Val = nullptr;
1775 InlineAsmIdentifierInfo Info;
1776 SMLoc Start = Tok.getLoc(), End;
1777 StringRef Identifier = Tok.getString();
1778 if (ParseIntelInlineAsmIdentifier(Val, Identifier, Info,
1779 /*Unevaluated=*/true, End))
1782 if (!Info.isKind(InlineAsmIdentifierInfo::IK_Var)) {
1783 Error(Start, "unable to lookup expression");
1789 default: llvm_unreachable("Unexpected operand kind!");
1790 case IOK_LENGTH: CVal = Info.Var.Length; break;
1791 case IOK_SIZE: CVal = Info.Var.Size; break;
1792 case IOK_TYPE: CVal = Info.Var.Type; break;
1798 bool X86AsmParser::ParseIntelMemoryOperandSize(unsigned &Size) {
1799 Size = StringSwitch<unsigned>(getTok().getString())
1800 .Cases("BYTE", "byte", 8)
1801 .Cases("WORD", "word", 16)
1802 .Cases("DWORD", "dword", 32)
1803 .Cases("FLOAT", "float", 32)
1804 .Cases("LONG", "long", 32)
1805 .Cases("FWORD", "fword", 48)
1806 .Cases("DOUBLE", "double", 64)
1807 .Cases("QWORD", "qword", 64)
1808 .Cases("MMWORD","mmword", 64)
1809 .Cases("XWORD", "xword", 80)
1810 .Cases("TBYTE", "tbyte", 80)
1811 .Cases("XMMWORD", "xmmword", 128)
1812 .Cases("YMMWORD", "ymmword", 256)
1813 .Cases("ZMMWORD", "zmmword", 512)
1816 const AsmToken &Tok = Lex(); // Eat operand size (e.g., byte, word).
1817 if (!(Tok.getString().equals("PTR") || Tok.getString().equals("ptr")))
1818 return Error(Tok.getLoc(), "Expected 'PTR' or 'ptr' token!");
1824 std::unique_ptr<X86Operand> X86AsmParser::ParseIntelOperand() {
1825 MCAsmParser &Parser = getParser();
1826 const AsmToken &Tok = Parser.getTok();
1829 // FIXME: Offset operator
1830 // Should be handled as part of immediate expression, as other operators
1831 // Currently, only supported as a stand-alone operand
1832 if (isParsingInlineAsm())
1833 if (IdentifyIntelInlineAsmOperator(Tok.getString()) == IOK_OFFSET)
1834 return ParseIntelOffsetOfOperator();
1836 // Parse optional Size directive.
1838 if (ParseIntelMemoryOperandSize(Size))
1840 bool PtrInOperand = bool(Size);
1842 Start = Tok.getLoc();
1844 // Rounding mode operand.
1845 if (getLexer().is(AsmToken::LCurly))
1846 return ParseRoundingModeOp(Start);
1848 // Register operand.
1850 if (Tok.is(AsmToken::Identifier) && !ParseRegister(RegNo, Start, End)) {
1851 if (RegNo == X86::RIP)
1852 return ErrorOperand(Start, "rip can only be used as a base register");
1853 // A Register followed by ':' is considered a segment override
1854 if (Tok.isNot(AsmToken::Colon))
1855 return !PtrInOperand ? X86Operand::CreateReg(RegNo, Start, End) :
1856 ErrorOperand(Start, "expected memory operand after 'ptr', "
1857 "found register operand instead");
1858 // An alleged segment override. check if we have a valid segment register
1859 if (!X86MCRegisterClasses[X86::SEGMENT_REGRegClassID].contains(RegNo))
1860 return ErrorOperand(Start, "invalid segment register");
1861 // Eat ':' and update Start location
1862 Start = Lex().getLoc();
1865 // Immediates and Memory
1866 IntelExprStateMachine SM;
1867 if (ParseIntelExpression(SM, End))
1870 if (isParsingInlineAsm())
1871 RewriteIntelExpression(SM, Start, Tok.getLoc());
1873 int64_t Imm = SM.getImm();
1874 const MCExpr *Disp = SM.getSym();
1875 const MCExpr *ImmDisp = MCConstantExpr::create(Imm, getContext());
1877 Disp = MCBinaryExpr::createAdd(Disp, ImmDisp, getContext());
1881 // RegNo != 0 specifies a valid segment register,
1882 // and we are parsing a segment override
1883 if (!SM.isMemExpr() && !RegNo)
1884 return X86Operand::CreateImm(Disp, Start, End);
1887 unsigned BaseReg = SM.getBaseReg();
1888 unsigned IndexReg = SM.getIndexReg();
1889 unsigned Scale = SM.getScale();
1891 if (Scale == 0 && BaseReg != X86::ESP && BaseReg != X86::RSP &&
1892 (IndexReg == X86::ESP || IndexReg == X86::RSP))
1893 std::swap(BaseReg, IndexReg);
1895 // If BaseReg is a vector register and IndexReg is not, swap them unless
1896 // Scale was specified in which case it would be an error.
1898 !(X86MCRegisterClasses[X86::VR128XRegClassID].contains(IndexReg) ||
1899 X86MCRegisterClasses[X86::VR256XRegClassID].contains(IndexReg) ||
1900 X86MCRegisterClasses[X86::VR512RegClassID].contains(IndexReg)) &&
1901 (X86MCRegisterClasses[X86::VR128XRegClassID].contains(BaseReg) ||
1902 X86MCRegisterClasses[X86::VR256XRegClassID].contains(BaseReg) ||
1903 X86MCRegisterClasses[X86::VR512RegClassID].contains(BaseReg)))
1904 std::swap(BaseReg, IndexReg);
1907 X86MCRegisterClasses[X86::GR16RegClassID].contains(IndexReg))
1908 return ErrorOperand(Start, "16-bit addresses cannot have a scale");
1910 // If there was no explicit scale specified, change it to 1.
1914 // If this is a 16-bit addressing mode with the base and index in the wrong
1915 // order, swap them so CheckBaseRegAndIndexRegAndScale doesn't fail. It is
1916 // shared with att syntax where order matters.
1917 if ((BaseReg == X86::SI || BaseReg == X86::DI) &&
1918 (IndexReg == X86::BX || IndexReg == X86::BP))
1919 std::swap(BaseReg, IndexReg);
1921 if ((BaseReg || IndexReg) &&
1922 CheckBaseRegAndIndexRegAndScale(BaseReg, IndexReg, Scale, is64BitMode(),
1924 return ErrorOperand(Start, ErrMsg);
1925 if (isParsingInlineAsm())
1926 return CreateMemForInlineAsm(RegNo, Disp, BaseReg, IndexReg,
1927 Scale, Start, End, Size, SM.getSymName(),
1928 SM.getIdentifierInfo());
1929 if (!(BaseReg || IndexReg || RegNo))
1930 return X86Operand::CreateMem(getPointerWidth(), Disp, Start, End, Size);
1931 return X86Operand::CreateMem(getPointerWidth(), RegNo, Disp,
1932 BaseReg, IndexReg, Scale, Start, End, Size);
1935 std::unique_ptr<X86Operand> X86AsmParser::ParseATTOperand() {
1936 MCAsmParser &Parser = getParser();
1937 switch (getLexer().getKind()) {
1939 // Parse a memory operand with no segment register.
1940 return ParseMemOperand(0, Parser.getTok().getLoc());
1941 case AsmToken::Percent: {
1942 // Read the register.
1945 if (ParseRegister(RegNo, Start, End)) return nullptr;
1946 if (RegNo == X86::EIZ || RegNo == X86::RIZ) {
1947 Error(Start, "%eiz and %riz can only be used as index registers",
1948 SMRange(Start, End));
1951 if (RegNo == X86::RIP) {
1952 Error(Start, "%rip can only be used as a base register",
1953 SMRange(Start, End));
1957 // If this is a segment register followed by a ':', then this is the start
1958 // of a memory reference, otherwise this is a normal register reference.
1959 if (getLexer().isNot(AsmToken::Colon))
1960 return X86Operand::CreateReg(RegNo, Start, End);
1962 if (!X86MCRegisterClasses[X86::SEGMENT_REGRegClassID].contains(RegNo))
1963 return ErrorOperand(Start, "invalid segment register");
1965 getParser().Lex(); // Eat the colon.
1966 return ParseMemOperand(RegNo, Start);
1968 case AsmToken::Dollar: {
1969 // $42 -> immediate.
1970 SMLoc Start = Parser.getTok().getLoc(), End;
1973 if (getParser().parseExpression(Val, End))
1975 return X86Operand::CreateImm(Val, Start, End);
1977 case AsmToken::LCurly:{
1978 SMLoc Start = Parser.getTok().getLoc();
1979 return ParseRoundingModeOp(Start);
1984 // true on failure, false otherwise
1985 // If no {z} mark was found - Parser doesn't advance
1986 bool X86AsmParser::ParseZ(std::unique_ptr<X86Operand> &Z,
1987 const SMLoc &StartLoc) {
1988 MCAsmParser &Parser = getParser();
1989 // Assuming we are just pass the '{' mark, quering the next token
1990 // Searched for {z}, but none was found. Return false, as no parsing error was
1992 if (!(getLexer().is(AsmToken::Identifier) &&
1993 (getLexer().getTok().getIdentifier() == "z")))
1995 Parser.Lex(); // Eat z
1996 // Query and eat the '}' mark
1997 if (!getLexer().is(AsmToken::RCurly))
1998 return Error(getLexer().getLoc(), "Expected } at this point");
1999 Parser.Lex(); // Eat '}'
2000 // Assign Z with the {z} mark opernad
2001 Z = X86Operand::CreateToken("{z}", StartLoc);
2005 // true on failure, false otherwise
2006 bool X86AsmParser::HandleAVX512Operand(OperandVector &Operands,
2007 const MCParsedAsmOperand &Op) {
2008 MCAsmParser &Parser = getParser();
2009 if (getLexer().is(AsmToken::LCurly)) {
2010 // Eat "{" and mark the current place.
2011 const SMLoc consumedToken = consumeToken();
2012 // Distinguish {1to<NUM>} from {%k<NUM>}.
2013 if(getLexer().is(AsmToken::Integer)) {
2014 // Parse memory broadcasting ({1to<NUM>}).
2015 if (getLexer().getTok().getIntVal() != 1)
2016 return TokError("Expected 1to<NUM> at this point");
2017 Parser.Lex(); // Eat "1" of 1to8
2018 if (!getLexer().is(AsmToken::Identifier) ||
2019 !getLexer().getTok().getIdentifier().startswith("to"))
2020 return TokError("Expected 1to<NUM> at this point");
2021 // Recognize only reasonable suffixes.
2022 const char *BroadcastPrimitive =
2023 StringSwitch<const char*>(getLexer().getTok().getIdentifier())
2024 .Case("to2", "{1to2}")
2025 .Case("to4", "{1to4}")
2026 .Case("to8", "{1to8}")
2027 .Case("to16", "{1to16}")
2029 if (!BroadcastPrimitive)
2030 return TokError("Invalid memory broadcast primitive.");
2031 Parser.Lex(); // Eat "toN" of 1toN
2032 if (!getLexer().is(AsmToken::RCurly))
2033 return TokError("Expected } at this point");
2034 Parser.Lex(); // Eat "}"
2035 Operands.push_back(X86Operand::CreateToken(BroadcastPrimitive,
2037 // No AVX512 specific primitives can pass
2038 // after memory broadcasting, so return.
2041 // Parse either {k}{z}, {z}{k}, {k} or {z}
2042 // last one have no meaning, but GCC accepts it
2043 // Currently, we're just pass a '{' mark
2044 std::unique_ptr<X86Operand> Z;
2045 if (ParseZ(Z, consumedToken))
2047 // Reaching here means that parsing of the allegadly '{z}' mark yielded
2049 // Query for the need of further parsing for a {%k<NUM>} mark
2050 if (!Z || getLexer().is(AsmToken::LCurly)) {
2051 SMLoc StartLoc = Z ? consumeToken() : consumedToken;
2052 // Parse an op-mask register mark ({%k<NUM>}), which is now to be
2056 if (!ParseRegister(RegNo, RegLoc, StartLoc) &&
2057 X86MCRegisterClasses[X86::VK1RegClassID].contains(RegNo)) {
2058 if (RegNo == X86::K0)
2059 return Error(RegLoc, "Register k0 can't be used as write mask");
2060 if (!getLexer().is(AsmToken::RCurly))
2061 return Error(getLexer().getLoc(), "Expected } at this point");
2062 Operands.push_back(X86Operand::CreateToken("{", StartLoc));
2064 X86Operand::CreateReg(RegNo, StartLoc, StartLoc));
2065 Operands.push_back(X86Operand::CreateToken("}", consumeToken()));
2067 return Error(getLexer().getLoc(),
2068 "Expected an op-mask register at this point");
2069 // {%k<NUM>} mark is found, inquire for {z}
2070 if (getLexer().is(AsmToken::LCurly) && !Z) {
2071 // Have we've found a parsing error, or found no (expected) {z} mark
2072 // - report an error
2073 if (ParseZ(Z, consumeToken()) || !Z)
2074 return Error(getLexer().getLoc(),
2075 "Expected a {z} mark at this point");
2078 // '{z}' on its own is meaningless, hence should be ignored.
2079 // on the contrary - have it been accompanied by a K register,
2082 Operands.push_back(std::move(Z));
2089 /// ParseMemOperand: segment: disp(basereg, indexreg, scale). The '%ds:' prefix
2090 /// has already been parsed if present.
2091 std::unique_ptr<X86Operand> X86AsmParser::ParseMemOperand(unsigned SegReg,
2094 MCAsmParser &Parser = getParser();
2095 // We have to disambiguate a parenthesized expression "(4+5)" from the start
2096 // of a memory operand with a missing displacement "(%ebx)" or "(,%eax)". The
2097 // only way to do this without lookahead is to eat the '(' and see what is
2099 const MCExpr *Disp = MCConstantExpr::create(0, getParser().getContext());
2100 if (getLexer().isNot(AsmToken::LParen)) {
2102 if (getParser().parseExpression(Disp, ExprEnd)) return nullptr;
2103 // Disp may be a variable, handle register values.
2104 if (auto *RE = dyn_cast<X86MCExpr>(Disp))
2105 return X86Operand::CreateReg(RE->getRegNo(), MemStart, ExprEnd);
2107 // After parsing the base expression we could either have a parenthesized
2108 // memory address or not. If not, return now. If so, eat the (.
2109 if (getLexer().isNot(AsmToken::LParen)) {
2110 // Unless we have a segment register, treat this as an immediate.
2112 return X86Operand::CreateMem(getPointerWidth(), Disp, MemStart, ExprEnd);
2113 return X86Operand::CreateMem(getPointerWidth(), SegReg, Disp, 0, 0, 1,
2120 // Okay, we have a '('. We don't know if this is an expression or not, but
2121 // so we have to eat the ( to see beyond it.
2122 SMLoc LParenLoc = Parser.getTok().getLoc();
2123 Parser.Lex(); // Eat the '('.
2125 if (getLexer().is(AsmToken::Percent) || getLexer().is(AsmToken::Comma)) {
2126 // Nothing to do here, fall into the code below with the '(' part of the
2127 // memory operand consumed.
2130 getLexer().UnLex(AsmToken(AsmToken::LParen, "("));
2132 // It must be either an parenthesized expression, or an expression that
2133 // begins from a parenthesized expression, parse it now. Example: (1+2) or
2135 if (getParser().parseExpression(Disp, ExprEnd))
2138 // After parsing the base expression we could either have a parenthesized
2139 // memory address or not. If not, return now. If so, eat the (.
2140 if (getLexer().isNot(AsmToken::LParen)) {
2141 // Unless we have a segment register, treat this as an immediate.
2143 return X86Operand::CreateMem(getPointerWidth(), Disp, LParenLoc,
2145 return X86Operand::CreateMem(getPointerWidth(), SegReg, Disp, 0, 0, 1,
2154 // If we reached here, then we just ate the ( of the memory operand. Process
2155 // the rest of the memory operand.
2156 unsigned BaseReg = 0, IndexReg = 0, Scale = 1;
2157 SMLoc IndexLoc, BaseLoc;
2159 if (getLexer().is(AsmToken::Percent)) {
2160 SMLoc StartLoc, EndLoc;
2161 BaseLoc = Parser.getTok().getLoc();
2162 if (ParseRegister(BaseReg, StartLoc, EndLoc)) return nullptr;
2163 if (BaseReg == X86::EIZ || BaseReg == X86::RIZ) {
2164 Error(StartLoc, "eiz and riz can only be used as index registers",
2165 SMRange(StartLoc, EndLoc));
2170 if (getLexer().is(AsmToken::Comma)) {
2171 Parser.Lex(); // Eat the comma.
2172 IndexLoc = Parser.getTok().getLoc();
2174 // Following the comma we should have either an index register, or a scale
2175 // value. We don't support the later form, but we want to parse it
2178 // Not that even though it would be completely consistent to support syntax
2179 // like "1(%eax,,1)", the assembler doesn't. Use "eiz" or "riz" for this.
2180 if (getLexer().is(AsmToken::Percent)) {
2182 if (ParseRegister(IndexReg, L, L))
2184 if (BaseReg == X86::RIP) {
2185 Error(IndexLoc, "%rip as base register can not have an index register");
2188 if (IndexReg == X86::RIP) {
2189 Error(IndexLoc, "%rip is not allowed as an index register");
2193 if (getLexer().isNot(AsmToken::RParen)) {
2194 // Parse the scale amount:
2195 // ::= ',' [scale-expression]
2196 if (parseToken(AsmToken::Comma, "expected comma in scale expression"))
2199 if (getLexer().isNot(AsmToken::RParen)) {
2200 SMLoc Loc = Parser.getTok().getLoc();
2203 if (getParser().parseAbsoluteExpression(ScaleVal)){
2204 Error(Loc, "expected scale expression");
2208 // Validate the scale amount.
2209 if (X86MCRegisterClasses[X86::GR16RegClassID].contains(BaseReg) &&
2211 Error(Loc, "scale factor in 16-bit address must be 1");
2214 if (ScaleVal != 1 && ScaleVal != 2 && ScaleVal != 4 &&
2216 Error(Loc, "scale factor in address must be 1, 2, 4 or 8");
2219 Scale = (unsigned)ScaleVal;
2222 } else if (getLexer().isNot(AsmToken::RParen)) {
2223 // A scale amount without an index is ignored.
2225 SMLoc Loc = Parser.getTok().getLoc();
2228 if (getParser().parseAbsoluteExpression(Value))
2232 Warning(Loc, "scale factor without index register is ignored");
2237 // Ok, we've eaten the memory operand, verify we have a ')' and eat it too.
2238 SMLoc MemEnd = Parser.getTok().getEndLoc();
2239 if (parseToken(AsmToken::RParen, "unexpected token in memory operand"))
2242 // This is a terrible hack to handle "out[s]?[bwl]? %al, (%dx)" ->
2243 // "outb %al, %dx". Out doesn't take a memory form, but this is a widely
2244 // documented form in various unofficial manuals, so a lot of code uses it.
2245 if (BaseReg == X86::DX && IndexReg == 0 && Scale == 1 &&
2246 SegReg == 0 && isa<MCConstantExpr>(Disp) &&
2247 cast<MCConstantExpr>(Disp)->getValue() == 0)
2248 return X86Operand::CreateDXReg(BaseLoc, BaseLoc);
2251 if (CheckBaseRegAndIndexRegAndScale(BaseReg, IndexReg, Scale, is64BitMode(),
2253 Error(BaseLoc, ErrMsg);
2257 if (SegReg || BaseReg || IndexReg)
2258 return X86Operand::CreateMem(getPointerWidth(), SegReg, Disp, BaseReg,
2259 IndexReg, Scale, MemStart, MemEnd);
2260 return X86Operand::CreateMem(getPointerWidth(), Disp, MemStart, MemEnd);
2263 // Parse either a standard expression or a register.
2264 bool X86AsmParser::parseAssignmentExpression(const MCExpr *&Res,
2266 MCAsmParser &Parser = getParser();
2267 if (Parser.parseExpression(Res, EndLoc)) {
2268 SMLoc StartLoc = Parser.getTok().getLoc();
2269 // Normal Expression parse fails, check if it could be a register.
2271 if (Parser.getTargetParser().ParseRegister(RegNo, StartLoc, EndLoc))
2273 // Clear previous parse error and return correct expression.
2274 Parser.clearPendingErrors();
2275 Res = X86MCExpr::create(RegNo, Parser.getContext());
2282 bool X86AsmParser::ParseInstruction(ParseInstructionInfo &Info, StringRef Name,
2283 SMLoc NameLoc, OperandVector &Operands) {
2284 MCAsmParser &Parser = getParser();
2286 StringRef PatchedName = Name;
2288 if ((Name.equals("jmp") || Name.equals("jc") || Name.equals("jz")) &&
2289 isParsingIntelSyntax() && isParsingInlineAsm()) {
2290 StringRef NextTok = Parser.getTok().getString();
2291 if (NextTok == "short") {
2293 NameLoc.getFromPointer(NameLoc.getPointer() + Name.size());
2294 // Eat the short keyword
2296 // MS ignores the short keyword, it determines the jmp type based
2297 // on the distance of the label
2298 InstInfo->AsmRewrites->emplace_back(AOK_Skip, NameEndLoc,
2299 NextTok.size() + 1);
2303 // FIXME: Hack to recognize setneb as setne.
2304 if (PatchedName.startswith("set") && PatchedName.endswith("b") &&
2305 PatchedName != "setb" && PatchedName != "setnb")
2306 PatchedName = PatchedName.substr(0, Name.size()-1);
2308 // FIXME: Hack to recognize cmp<comparison code>{ss,sd,ps,pd}.
2309 if ((PatchedName.startswith("cmp") || PatchedName.startswith("vcmp")) &&
2310 (PatchedName.endswith("ss") || PatchedName.endswith("sd") ||
2311 PatchedName.endswith("ps") || PatchedName.endswith("pd"))) {
2312 bool IsVCMP = PatchedName[0] == 'v';
2313 unsigned CCIdx = IsVCMP ? 4 : 3;
2314 unsigned ComparisonCode = StringSwitch<unsigned>(
2315 PatchedName.slice(CCIdx, PatchedName.size() - 2))
2317 .Case("eq_oq", 0x00)
2319 .Case("lt_os", 0x01)
2321 .Case("le_os", 0x02)
2322 .Case("unord", 0x03)
2323 .Case("unord_q", 0x03)
2325 .Case("neq_uq", 0x04)
2327 .Case("nlt_us", 0x05)
2329 .Case("nle_us", 0x06)
2331 .Case("ord_q", 0x07)
2332 /* AVX only from here */
2333 .Case("eq_uq", 0x08)
2335 .Case("nge_us", 0x09)
2337 .Case("ngt_us", 0x0A)
2338 .Case("false", 0x0B)
2339 .Case("false_oq", 0x0B)
2340 .Case("neq_oq", 0x0C)
2342 .Case("ge_os", 0x0D)
2344 .Case("gt_os", 0x0E)
2346 .Case("true_uq", 0x0F)
2347 .Case("eq_os", 0x10)
2348 .Case("lt_oq", 0x11)
2349 .Case("le_oq", 0x12)
2350 .Case("unord_s", 0x13)
2351 .Case("neq_us", 0x14)
2352 .Case("nlt_uq", 0x15)
2353 .Case("nle_uq", 0x16)
2354 .Case("ord_s", 0x17)
2355 .Case("eq_us", 0x18)
2356 .Case("nge_uq", 0x19)
2357 .Case("ngt_uq", 0x1A)
2358 .Case("false_os", 0x1B)
2359 .Case("neq_os", 0x1C)
2360 .Case("ge_oq", 0x1D)
2361 .Case("gt_oq", 0x1E)
2362 .Case("true_us", 0x1F)
2364 if (ComparisonCode != ~0U && (IsVCMP || ComparisonCode < 8)) {
2366 Operands.push_back(X86Operand::CreateToken(PatchedName.slice(0, CCIdx),
2369 const MCExpr *ImmOp = MCConstantExpr::create(ComparisonCode,
2370 getParser().getContext());
2371 Operands.push_back(X86Operand::CreateImm(ImmOp, NameLoc, NameLoc));
2373 PatchedName = PatchedName.substr(PatchedName.size() - 2);
2377 // FIXME: Hack to recognize vpcmp<comparison code>{ub,uw,ud,uq,b,w,d,q}.
2378 if (PatchedName.startswith("vpcmp") &&
2379 (PatchedName.endswith("b") || PatchedName.endswith("w") ||
2380 PatchedName.endswith("d") || PatchedName.endswith("q"))) {
2381 unsigned CCIdx = PatchedName.drop_back().back() == 'u' ? 2 : 1;
2382 unsigned ComparisonCode = StringSwitch<unsigned>(
2383 PatchedName.slice(5, PatchedName.size() - CCIdx))
2384 .Case("eq", 0x0) // Only allowed on unsigned. Checked below.
2387 //.Case("false", 0x3) // Not a documented alias.
2391 //.Case("true", 0x7) // Not a documented alias.
2393 if (ComparisonCode != ~0U && (ComparisonCode != 0 || CCIdx == 2)) {
2394 Operands.push_back(X86Operand::CreateToken("vpcmp", NameLoc));
2396 const MCExpr *ImmOp = MCConstantExpr::create(ComparisonCode,
2397 getParser().getContext());
2398 Operands.push_back(X86Operand::CreateImm(ImmOp, NameLoc, NameLoc));
2400 PatchedName = PatchedName.substr(PatchedName.size() - CCIdx);
2404 // FIXME: Hack to recognize vpcom<comparison code>{ub,uw,ud,uq,b,w,d,q}.
2405 if (PatchedName.startswith("vpcom") &&
2406 (PatchedName.endswith("b") || PatchedName.endswith("w") ||
2407 PatchedName.endswith("d") || PatchedName.endswith("q"))) {
2408 unsigned CCIdx = PatchedName.drop_back().back() == 'u' ? 2 : 1;
2409 unsigned ComparisonCode = StringSwitch<unsigned>(
2410 PatchedName.slice(5, PatchedName.size() - CCIdx))
2420 if (ComparisonCode != ~0U) {
2421 Operands.push_back(X86Operand::CreateToken("vpcom", NameLoc));
2423 const MCExpr *ImmOp = MCConstantExpr::create(ComparisonCode,
2424 getParser().getContext());
2425 Operands.push_back(X86Operand::CreateImm(ImmOp, NameLoc, NameLoc));
2427 PatchedName = PatchedName.substr(PatchedName.size() - CCIdx);
2432 // Determine whether this is an instruction prefix.
2434 // Enhance prefixes integrity robustness. for example, following forms
2435 // are currently tolerated:
2436 // repz repnz <insn> ; GAS errors for the use of two similar prefixes
2437 // lock addq %rax, %rbx ; Destination operand must be of memory type
2438 // xacquire <insn> ; xacquire must be accompanied by 'lock'
2439 bool isPrefix = StringSwitch<bool>(Name)
2440 .Cases("rex64", "data32", "data16", true)
2441 .Cases("xacquire", "xrelease", true)
2442 .Cases("acquire", "release", isParsingIntelSyntax())
2445 auto isLockRepeatNtPrefix = [](StringRef N) {
2446 return StringSwitch<bool>(N)
2447 .Cases("lock", "rep", "repe", "repz", "repne", "repnz", "notrack", true)
2451 bool CurlyAsEndOfStatement = false;
2453 unsigned Flags = X86::IP_NO_PREFIX;
2454 while (isLockRepeatNtPrefix(Name.lower())) {
2456 StringSwitch<unsigned>(Name)
2457 .Cases("lock", "lock", X86::IP_HAS_LOCK)
2458 .Cases("rep", "repe", "repz", X86::IP_HAS_REPEAT)
2459 .Cases("repne", "repnz", X86::IP_HAS_REPEAT_NE)
2460 .Cases("notrack", "notrack", X86::IP_HAS_NOTRACK)
2461 .Default(X86::IP_NO_PREFIX); // Invalid prefix (impossible)
2463 if (getLexer().is(AsmToken::EndOfStatement)) {
2464 // We don't have real instr with the given prefix
2465 // let's use the prefix as the instr.
2466 // TODO: there could be several prefixes one after another
2467 Flags = X86::IP_NO_PREFIX;
2470 Name = Parser.getTok().getString();
2471 Parser.Lex(); // eat the prefix
2472 // Hack: we could have something like "rep # some comment" or
2473 // "lock; cmpxchg16b $1" or "lock\0A\09incl" or "lock/incl"
2474 while (Name.startswith(";") || Name.startswith("\n") ||
2475 Name.startswith("#") || Name.startswith("\t") ||
2476 Name.startswith("/")) {
2477 Name = Parser.getTok().getString();
2478 Parser.Lex(); // go to next prefix or instr
2485 // Hacks to handle 'data16' and 'data32'
2486 if (PatchedName == "data16" && is16BitMode()) {
2487 return Error(NameLoc, "redundant data16 prefix");
2489 if (PatchedName == "data32") {
2491 return Error(NameLoc, "redundant data32 prefix");
2493 return Error(NameLoc, "'data32' is not supported in 64-bit mode");
2494 // Hack to 'data16' for the table lookup.
2495 PatchedName = "data16";
2498 Operands.push_back(X86Operand::CreateToken(PatchedName, NameLoc));
2500 // This does the actual operand parsing. Don't parse any more if we have a
2501 // prefix juxtaposed with an operation like "lock incl 4(%rax)", because we
2502 // just want to parse the "lock" as the first instruction and the "incl" as
2504 if (getLexer().isNot(AsmToken::EndOfStatement) && !isPrefix) {
2505 // Parse '*' modifier.
2506 if (getLexer().is(AsmToken::Star))
2507 Operands.push_back(X86Operand::CreateToken("*", consumeToken()));
2509 // Read the operands.
2511 if (std::unique_ptr<X86Operand> Op = ParseOperand()) {
2512 Operands.push_back(std::move(Op));
2513 if (HandleAVX512Operand(Operands, *Operands.back()))
2518 // check for comma and eat it
2519 if (getLexer().is(AsmToken::Comma))
2525 // In MS inline asm curly braces mark the beginning/end of a block,
2526 // therefore they should be interepreted as end of statement
2527 CurlyAsEndOfStatement =
2528 isParsingIntelSyntax() && isParsingInlineAsm() &&
2529 (getLexer().is(AsmToken::LCurly) || getLexer().is(AsmToken::RCurly));
2530 if (getLexer().isNot(AsmToken::EndOfStatement) && !CurlyAsEndOfStatement)
2531 return TokError("unexpected token in argument list");
2534 // Consume the EndOfStatement or the prefix separator Slash
2535 if (getLexer().is(AsmToken::EndOfStatement) ||
2536 (isPrefix && getLexer().is(AsmToken::Slash)))
2538 else if (CurlyAsEndOfStatement)
2539 // Add an actual EndOfStatement before the curly brace
2540 Info.AsmRewrites->emplace_back(AOK_EndOfStatement,
2541 getLexer().getTok().getLoc(), 0);
2543 // This is for gas compatibility and cannot be done in td.
2544 // Adding "p" for some floating point with no argument.
2545 // For example: fsub --> fsubp
2547 Name == "fsub" || Name == "fdiv" || Name == "fsubr" || Name == "fdivr";
2548 if (IsFp && Operands.size() == 1) {
2549 const char *Repl = StringSwitch<const char *>(Name)
2550 .Case("fsub", "fsubp")
2551 .Case("fdiv", "fdivp")
2552 .Case("fsubr", "fsubrp")
2553 .Case("fdivr", "fdivrp");
2554 static_cast<X86Operand &>(*Operands[0]).setTokenValue(Repl);
2557 // Moving a 32 or 16 bit value into a segment register has the same
2558 // behavior. Modify such instructions to always take shorter form.
2559 if ((Name == "mov" || Name == "movw" || Name == "movl") &&
2560 (Operands.size() == 3)) {
2561 X86Operand &Op1 = (X86Operand &)*Operands[1];
2562 X86Operand &Op2 = (X86Operand &)*Operands[2];
2563 SMLoc Loc = Op1.getEndLoc();
2564 if (Op1.isReg() && Op2.isReg() &&
2565 X86MCRegisterClasses[X86::SEGMENT_REGRegClassID].contains(
2567 (X86MCRegisterClasses[X86::GR16RegClassID].contains(Op1.getReg()) ||
2568 X86MCRegisterClasses[X86::GR32RegClassID].contains(Op1.getReg()))) {
2569 // Change instruction name to match new instruction.
2570 if (Name != "mov" && Name[3] == (is16BitMode() ? 'l' : 'w')) {
2571 Name = is16BitMode() ? "movw" : "movl";
2572 Operands[0] = X86Operand::CreateToken(Name, NameLoc);
2574 // Select the correct equivalent 16-/32-bit source register.
2576 getX86SubSuperRegisterOrZero(Op1.getReg(), is16BitMode() ? 16 : 32);
2577 Operands[1] = X86Operand::CreateReg(Reg, Loc, Loc);
2581 // This is a terrible hack to handle "out[s]?[bwl]? %al, (%dx)" ->
2582 // "outb %al, %dx". Out doesn't take a memory form, but this is a widely
2583 // documented form in various unofficial manuals, so a lot of code uses it.
2584 if ((Name == "outb" || Name == "outsb" || Name == "outw" || Name == "outsw" ||
2585 Name == "outl" || Name == "outsl" || Name == "out" || Name == "outs") &&
2586 Operands.size() == 3) {
2587 X86Operand &Op = (X86Operand &)*Operands.back();
2589 Operands.back() = X86Operand::CreateReg(X86::DX, Op.getStartLoc(),
2592 // Same hack for "in[s]?[bwl]? (%dx), %al" -> "inb %dx, %al".
2593 if ((Name == "inb" || Name == "insb" || Name == "inw" || Name == "insw" ||
2594 Name == "inl" || Name == "insl" || Name == "in" || Name == "ins") &&
2595 Operands.size() == 3) {
2596 X86Operand &Op = (X86Operand &)*Operands[1];
2598 Operands[1] = X86Operand::CreateReg(X86::DX, Op.getStartLoc(),
2602 SmallVector<std::unique_ptr<MCParsedAsmOperand>, 2> TmpOperands;
2603 bool HadVerifyError = false;
2605 // Append default arguments to "ins[bwld]"
2606 if (Name.startswith("ins") &&
2607 (Operands.size() == 1 || Operands.size() == 3) &&
2608 (Name == "insb" || Name == "insw" || Name == "insl" || Name == "insd" ||
2611 AddDefaultSrcDestOperands(TmpOperands,
2612 X86Operand::CreateReg(X86::DX, NameLoc, NameLoc),
2613 DefaultMemDIOperand(NameLoc));
2614 HadVerifyError = VerifyAndAdjustOperands(Operands, TmpOperands);
2617 // Append default arguments to "outs[bwld]"
2618 if (Name.startswith("outs") &&
2619 (Operands.size() == 1 || Operands.size() == 3) &&
2620 (Name == "outsb" || Name == "outsw" || Name == "outsl" ||
2621 Name == "outsd" || Name == "outs")) {
2622 AddDefaultSrcDestOperands(TmpOperands, DefaultMemSIOperand(NameLoc),
2623 X86Operand::CreateReg(X86::DX, NameLoc, NameLoc));
2624 HadVerifyError = VerifyAndAdjustOperands(Operands, TmpOperands);
2627 // Transform "lods[bwlq]" into "lods[bwlq] ($SIREG)" for appropriate
2628 // values of $SIREG according to the mode. It would be nice if this
2629 // could be achieved with InstAlias in the tables.
2630 if (Name.startswith("lods") &&
2631 (Operands.size() == 1 || Operands.size() == 2) &&
2632 (Name == "lods" || Name == "lodsb" || Name == "lodsw" ||
2633 Name == "lodsl" || Name == "lodsd" || Name == "lodsq")) {
2634 TmpOperands.push_back(DefaultMemSIOperand(NameLoc));
2635 HadVerifyError = VerifyAndAdjustOperands(Operands, TmpOperands);
2638 // Transform "stos[bwlq]" into "stos[bwlq] ($DIREG)" for appropriate
2639 // values of $DIREG according to the mode. It would be nice if this
2640 // could be achieved with InstAlias in the tables.
2641 if (Name.startswith("stos") &&
2642 (Operands.size() == 1 || Operands.size() == 2) &&
2643 (Name == "stos" || Name == "stosb" || Name == "stosw" ||
2644 Name == "stosl" || Name == "stosd" || Name == "stosq")) {
2645 TmpOperands.push_back(DefaultMemDIOperand(NameLoc));
2646 HadVerifyError = VerifyAndAdjustOperands(Operands, TmpOperands);
2649 // Transform "scas[bwlq]" into "scas[bwlq] ($DIREG)" for appropriate
2650 // values of $DIREG according to the mode. It would be nice if this
2651 // could be achieved with InstAlias in the tables.
2652 if (Name.startswith("scas") &&
2653 (Operands.size() == 1 || Operands.size() == 2) &&
2654 (Name == "scas" || Name == "scasb" || Name == "scasw" ||
2655 Name == "scasl" || Name == "scasd" || Name == "scasq")) {
2656 TmpOperands.push_back(DefaultMemDIOperand(NameLoc));
2657 HadVerifyError = VerifyAndAdjustOperands(Operands, TmpOperands);
2660 // Add default SI and DI operands to "cmps[bwlq]".
2661 if (Name.startswith("cmps") &&
2662 (Operands.size() == 1 || Operands.size() == 3) &&
2663 (Name == "cmps" || Name == "cmpsb" || Name == "cmpsw" ||
2664 Name == "cmpsl" || Name == "cmpsd" || Name == "cmpsq")) {
2665 AddDefaultSrcDestOperands(TmpOperands, DefaultMemDIOperand(NameLoc),
2666 DefaultMemSIOperand(NameLoc));
2667 HadVerifyError = VerifyAndAdjustOperands(Operands, TmpOperands);
2670 // Add default SI and DI operands to "movs[bwlq]".
2671 if (((Name.startswith("movs") &&
2672 (Name == "movs" || Name == "movsb" || Name == "movsw" ||
2673 Name == "movsl" || Name == "movsd" || Name == "movsq")) ||
2674 (Name.startswith("smov") &&
2675 (Name == "smov" || Name == "smovb" || Name == "smovw" ||
2676 Name == "smovl" || Name == "smovd" || Name == "smovq"))) &&
2677 (Operands.size() == 1 || Operands.size() == 3)) {
2678 if (Name == "movsd" && Operands.size() == 1 && !isParsingIntelSyntax())
2679 Operands.back() = X86Operand::CreateToken("movsl", NameLoc);
2680 AddDefaultSrcDestOperands(TmpOperands, DefaultMemSIOperand(NameLoc),
2681 DefaultMemDIOperand(NameLoc));
2682 HadVerifyError = VerifyAndAdjustOperands(Operands, TmpOperands);
2685 // Check if we encountered an error for one the string insturctions
2686 if (HadVerifyError) {
2687 return HadVerifyError;
2690 // FIXME: Hack to handle recognize s{hr,ar,hl} $1, <op>. Canonicalize to
2692 if ((Name.startswith("shr") || Name.startswith("sar") ||
2693 Name.startswith("shl") || Name.startswith("sal") ||
2694 Name.startswith("rcl") || Name.startswith("rcr") ||
2695 Name.startswith("rol") || Name.startswith("ror")) &&
2696 Operands.size() == 3) {
2697 if (isParsingIntelSyntax()) {
2699 X86Operand &Op1 = static_cast<X86Operand &>(*Operands[2]);
2700 if (Op1.isImm() && isa<MCConstantExpr>(Op1.getImm()) &&
2701 cast<MCConstantExpr>(Op1.getImm())->getValue() == 1)
2702 Operands.pop_back();
2704 X86Operand &Op1 = static_cast<X86Operand &>(*Operands[1]);
2705 if (Op1.isImm() && isa<MCConstantExpr>(Op1.getImm()) &&
2706 cast<MCConstantExpr>(Op1.getImm())->getValue() == 1)
2707 Operands.erase(Operands.begin() + 1);
2711 // Transforms "int $3" into "int3" as a size optimization. We can't write an
2712 // instalias with an immediate operand yet.
2713 if (Name == "int" && Operands.size() == 2) {
2714 X86Operand &Op1 = static_cast<X86Operand &>(*Operands[1]);
2716 if (auto *CE = dyn_cast<MCConstantExpr>(Op1.getImm()))
2717 if (CE->getValue() == 3) {
2718 Operands.erase(Operands.begin() + 1);
2719 static_cast<X86Operand &>(*Operands[0]).setTokenValue("int3");
2723 // Transforms "xlat mem8" into "xlatb"
2724 if ((Name == "xlat" || Name == "xlatb") && Operands.size() == 2) {
2725 X86Operand &Op1 = static_cast<X86Operand &>(*Operands[1]);
2727 Warning(Op1.getStartLoc(), "memory operand is only for determining the "
2728 "size, (R|E)BX will be used for the location");
2729 Operands.pop_back();
2730 static_cast<X86Operand &>(*Operands[0]).setTokenValue("xlatb");
2735 Operands.push_back(X86Operand::CreatePrefix(Flags, NameLoc, NameLoc));
2739 bool X86AsmParser::processInstruction(MCInst &Inst, const OperandVector &Ops) {
2743 bool X86AsmParser::validateInstruction(MCInst &Inst, const OperandVector &Ops) {
2744 const MCRegisterInfo *MRI = getContext().getRegisterInfo();
2746 switch (Inst.getOpcode()) {
2747 case X86::VGATHERDPDYrm:
2748 case X86::VGATHERDPDrm:
2749 case X86::VGATHERDPSYrm:
2750 case X86::VGATHERDPSrm:
2751 case X86::VGATHERQPDYrm:
2752 case X86::VGATHERQPDrm:
2753 case X86::VGATHERQPSYrm:
2754 case X86::VGATHERQPSrm:
2755 case X86::VPGATHERDDYrm:
2756 case X86::VPGATHERDDrm:
2757 case X86::VPGATHERDQYrm:
2758 case X86::VPGATHERDQrm:
2759 case X86::VPGATHERQDYrm:
2760 case X86::VPGATHERQDrm:
2761 case X86::VPGATHERQQYrm:
2762 case X86::VPGATHERQQrm: {
2763 unsigned Dest = MRI->getEncodingValue(Inst.getOperand(0).getReg());
2764 unsigned Mask = MRI->getEncodingValue(Inst.getOperand(1).getReg());
2766 MRI->getEncodingValue(Inst.getOperand(3 + X86::AddrIndexReg).getReg());
2767 if (Dest == Mask || Dest == Index || Mask == Index)
2768 return Warning(Ops[0]->getStartLoc(), "mask, index, and destination "
2769 "registers should be distinct");
2772 case X86::VGATHERDPDZ128rm:
2773 case X86::VGATHERDPDZ256rm:
2774 case X86::VGATHERDPDZrm:
2775 case X86::VGATHERDPSZ128rm:
2776 case X86::VGATHERDPSZ256rm:
2777 case X86::VGATHERDPSZrm:
2778 case X86::VGATHERQPDZ128rm:
2779 case X86::VGATHERQPDZ256rm:
2780 case X86::VGATHERQPDZrm:
2781 case X86::VGATHERQPSZ128rm:
2782 case X86::VGATHERQPSZ256rm:
2783 case X86::VGATHERQPSZrm:
2784 case X86::VPGATHERDDZ128rm:
2785 case X86::VPGATHERDDZ256rm:
2786 case X86::VPGATHERDDZrm:
2787 case X86::VPGATHERDQZ128rm:
2788 case X86::VPGATHERDQZ256rm:
2789 case X86::VPGATHERDQZrm:
2790 case X86::VPGATHERQDZ128rm:
2791 case X86::VPGATHERQDZ256rm:
2792 case X86::VPGATHERQDZrm:
2793 case X86::VPGATHERQQZ128rm:
2794 case X86::VPGATHERQQZ256rm:
2795 case X86::VPGATHERQQZrm: {
2796 unsigned Dest = MRI->getEncodingValue(Inst.getOperand(0).getReg());
2798 MRI->getEncodingValue(Inst.getOperand(4 + X86::AddrIndexReg).getReg());
2800 return Warning(Ops[0]->getStartLoc(), "index and destination registers "
2801 "should be distinct");
2804 case X86::V4FMADDPSrm:
2805 case X86::V4FMADDPSrmk:
2806 case X86::V4FMADDPSrmkz:
2807 case X86::V4FMADDSSrm:
2808 case X86::V4FMADDSSrmk:
2809 case X86::V4FMADDSSrmkz:
2810 case X86::V4FNMADDPSrm:
2811 case X86::V4FNMADDPSrmk:
2812 case X86::V4FNMADDPSrmkz:
2813 case X86::V4FNMADDSSrm:
2814 case X86::V4FNMADDSSrmk:
2815 case X86::V4FNMADDSSrmkz:
2816 case X86::VP4DPWSSDSrm:
2817 case X86::VP4DPWSSDSrmk:
2818 case X86::VP4DPWSSDSrmkz:
2819 case X86::VP4DPWSSDrm:
2820 case X86::VP4DPWSSDrmk:
2821 case X86::VP4DPWSSDrmkz: {
2822 unsigned Src2 = Inst.getOperand(Inst.getNumOperands() -
2823 X86::AddrNumOperands - 1).getReg();
2824 unsigned Src2Enc = MRI->getEncodingValue(Src2);
2825 if (Src2Enc % 4 != 0) {
2826 StringRef RegName = X86IntelInstPrinter::getRegisterName(Src2);
2827 unsigned GroupStart = (Src2Enc / 4) * 4;
2828 unsigned GroupEnd = GroupStart + 3;
2829 return Warning(Ops[0]->getStartLoc(),
2830 "source register '" + RegName + "' implicitly denotes '" +
2831 RegName.take_front(3) + Twine(GroupStart) + "' to '" +
2832 RegName.take_front(3) + Twine(GroupEnd) +
2842 static const char *getSubtargetFeatureName(uint64_t Val);
2844 void X86AsmParser::EmitInstruction(MCInst &Inst, OperandVector &Operands,
2846 Instrumentation->InstrumentAndEmitInstruction(
2847 Inst, Operands, getContext(), MII, Out,
2848 getParser().shouldPrintSchedInfo());
2851 bool X86AsmParser::MatchAndEmitInstruction(SMLoc IDLoc, unsigned &Opcode,
2852 OperandVector &Operands,
2853 MCStreamer &Out, uint64_t &ErrorInfo,
2854 bool MatchingInlineAsm) {
2855 if (isParsingIntelSyntax())
2856 return MatchAndEmitIntelInstruction(IDLoc, Opcode, Operands, Out, ErrorInfo,
2858 return MatchAndEmitATTInstruction(IDLoc, Opcode, Operands, Out, ErrorInfo,
2862 void X86AsmParser::MatchFPUWaitAlias(SMLoc IDLoc, X86Operand &Op,
2863 OperandVector &Operands, MCStreamer &Out,
2864 bool MatchingInlineAsm) {
2865 // FIXME: This should be replaced with a real .td file alias mechanism.
2866 // Also, MatchInstructionImpl should actually *do* the EmitInstruction
2868 const char *Repl = StringSwitch<const char *>(Op.getToken())
2869 .Case("finit", "fninit")
2870 .Case("fsave", "fnsave")
2871 .Case("fstcw", "fnstcw")
2872 .Case("fstcww", "fnstcw")
2873 .Case("fstenv", "fnstenv")
2874 .Case("fstsw", "fnstsw")
2875 .Case("fstsww", "fnstsw")
2876 .Case("fclex", "fnclex")
2880 Inst.setOpcode(X86::WAIT);
2882 if (!MatchingInlineAsm)
2883 EmitInstruction(Inst, Operands, Out);
2884 Operands[0] = X86Operand::CreateToken(Repl, IDLoc);
2888 bool X86AsmParser::ErrorMissingFeature(SMLoc IDLoc, uint64_t ErrorInfo,
2889 bool MatchingInlineAsm) {
2890 assert(ErrorInfo && "Unknown missing feature!");
2891 SmallString<126> Msg;
2892 raw_svector_ostream OS(Msg);
2893 OS << "instruction requires:";
2895 for (unsigned i = 0; i < (sizeof(ErrorInfo)*8-1); ++i) {
2896 if (ErrorInfo & Mask)
2897 OS << ' ' << getSubtargetFeatureName(ErrorInfo & Mask);
2900 return Error(IDLoc, OS.str(), SMRange(), MatchingInlineAsm);
2903 static unsigned getPrefixes(OperandVector &Operands) {
2904 unsigned Result = 0;
2905 X86Operand &Prefix = static_cast<X86Operand &>(*Operands.back());
2906 if (Prefix.isPrefix()) {
2907 Result = Prefix.getPrefix();
2908 Operands.pop_back();
2913 bool X86AsmParser::MatchAndEmitATTInstruction(SMLoc IDLoc, unsigned &Opcode,
2914 OperandVector &Operands,
2916 uint64_t &ErrorInfo,
2917 bool MatchingInlineAsm) {
2918 assert(!Operands.empty() && "Unexpect empty operand list!");
2919 X86Operand &Op = static_cast<X86Operand &>(*Operands[0]);
2920 assert(Op.isToken() && "Leading operand should always be a mnemonic!");
2921 SMRange EmptyRange = None;
2923 // First, handle aliases that expand to multiple instructions.
2924 MatchFPUWaitAlias(IDLoc, Op, Operands, Out, MatchingInlineAsm);
2926 bool WasOriginallyInvalidOperand = false;
2927 unsigned Prefixes = getPrefixes(Operands);
2932 Inst.setFlags(Prefixes);
2934 // First, try a direct match.
2935 switch (MatchInstruction(Operands, Inst, ErrorInfo, MatchingInlineAsm,
2936 isParsingIntelSyntax())) {
2937 default: llvm_unreachable("Unexpected match result!");
2939 if (!MatchingInlineAsm && validateInstruction(Inst, Operands))
2941 // Some instructions need post-processing to, for example, tweak which
2942 // encoding is selected. Loop on it while changes happen so the
2943 // individual transformations can chain off each other.
2944 if (!MatchingInlineAsm)
2945 while (processInstruction(Inst, Operands))
2949 if (!MatchingInlineAsm)
2950 EmitInstruction(Inst, Operands, Out);
2951 Opcode = Inst.getOpcode();
2953 case Match_MissingFeature:
2954 return ErrorMissingFeature(IDLoc, ErrorInfo, MatchingInlineAsm);
2955 case Match_InvalidOperand:
2956 WasOriginallyInvalidOperand = true;
2958 case Match_MnemonicFail:
2962 // FIXME: Ideally, we would only attempt suffix matches for things which are
2963 // valid prefixes, and we could just infer the right unambiguous
2964 // type. However, that requires substantially more matcher support than the
2967 // Change the operand to point to a temporary token.
2968 StringRef Base = Op.getToken();
2969 SmallString<16> Tmp;
2972 Op.setTokenValue(Tmp);
2974 // If this instruction starts with an 'f', then it is a floating point stack
2975 // instruction. These come in up to three forms for 32-bit, 64-bit, and
2976 // 80-bit floating point, which use the suffixes s,l,t respectively.
2978 // Otherwise, we assume that this may be an integer instruction, which comes
2979 // in 8/16/32/64-bit forms using the b,w,l,q suffixes respectively.
2980 const char *Suffixes = Base[0] != 'f' ? "bwlq" : "slt\0";
2982 // Check for the various suffix matches.
2983 uint64_t ErrorInfoIgnore;
2984 uint64_t ErrorInfoMissingFeature = 0; // Init suppresses compiler warnings.
2987 for (unsigned I = 0, E = array_lengthof(Match); I != E; ++I) {
2988 Tmp.back() = Suffixes[I];
2989 Match[I] = MatchInstruction(Operands, Inst, ErrorInfoIgnore,
2990 MatchingInlineAsm, isParsingIntelSyntax());
2991 // If this returned as a missing feature failure, remember that.
2992 if (Match[I] == Match_MissingFeature)
2993 ErrorInfoMissingFeature = ErrorInfoIgnore;
2996 // Restore the old token.
2997 Op.setTokenValue(Base);
2999 // If exactly one matched, then we treat that as a successful match (and the
3000 // instruction will already have been filled in correctly, since the failing
3001 // matches won't have modified it).
3002 unsigned NumSuccessfulMatches =
3003 std::count(std::begin(Match), std::end(Match), Match_Success);
3004 if (NumSuccessfulMatches == 1) {
3006 if (!MatchingInlineAsm)
3007 EmitInstruction(Inst, Operands, Out);
3008 Opcode = Inst.getOpcode();
3012 // Otherwise, the match failed, try to produce a decent error message.
3014 // If we had multiple suffix matches, then identify this as an ambiguous
3016 if (NumSuccessfulMatches > 1) {
3018 unsigned NumMatches = 0;
3019 for (unsigned I = 0, E = array_lengthof(Match); I != E; ++I)
3020 if (Match[I] == Match_Success)
3021 MatchChars[NumMatches++] = Suffixes[I];
3023 SmallString<126> Msg;
3024 raw_svector_ostream OS(Msg);
3025 OS << "ambiguous instructions require an explicit suffix (could be ";
3026 for (unsigned i = 0; i != NumMatches; ++i) {
3029 if (i + 1 == NumMatches)
3031 OS << "'" << Base << MatchChars[i] << "'";
3034 Error(IDLoc, OS.str(), EmptyRange, MatchingInlineAsm);
3038 // Okay, we know that none of the variants matched successfully.
3040 // If all of the instructions reported an invalid mnemonic, then the original
3041 // mnemonic was invalid.
3042 if (std::count(std::begin(Match), std::end(Match), Match_MnemonicFail) == 4) {
3043 if (!WasOriginallyInvalidOperand) {
3044 return Error(IDLoc, "invalid instruction mnemonic '" + Base + "'",
3045 Op.getLocRange(), MatchingInlineAsm);
3048 // Recover location info for the operand if we know which was the problem.
3049 if (ErrorInfo != ~0ULL) {
3050 if (ErrorInfo >= Operands.size())
3051 return Error(IDLoc, "too few operands for instruction", EmptyRange,
3054 X86Operand &Operand = (X86Operand &)*Operands[ErrorInfo];
3055 if (Operand.getStartLoc().isValid()) {
3056 SMRange OperandRange = Operand.getLocRange();
3057 return Error(Operand.getStartLoc(), "invalid operand for instruction",
3058 OperandRange, MatchingInlineAsm);
3062 return Error(IDLoc, "invalid operand for instruction", EmptyRange,
3066 // If one instruction matched with a missing feature, report this as a
3068 if (std::count(std::begin(Match), std::end(Match),
3069 Match_MissingFeature) == 1) {
3070 ErrorInfo = ErrorInfoMissingFeature;
3071 return ErrorMissingFeature(IDLoc, ErrorInfoMissingFeature,
3075 // If one instruction matched with an invalid operand, report this as an
3077 if (std::count(std::begin(Match), std::end(Match),
3078 Match_InvalidOperand) == 1) {
3079 return Error(IDLoc, "invalid operand for instruction", EmptyRange,
3083 // If all of these were an outright failure, report it in a useless way.
3084 Error(IDLoc, "unknown use of instruction mnemonic without a size suffix",
3085 EmptyRange, MatchingInlineAsm);
3089 bool X86AsmParser::MatchAndEmitIntelInstruction(SMLoc IDLoc, unsigned &Opcode,
3090 OperandVector &Operands,
3092 uint64_t &ErrorInfo,
3093 bool MatchingInlineAsm) {
3094 assert(!Operands.empty() && "Unexpect empty operand list!");
3095 X86Operand &Op = static_cast<X86Operand &>(*Operands[0]);
3096 assert(Op.isToken() && "Leading operand should always be a mnemonic!");
3097 StringRef Mnemonic = Op.getToken();
3098 SMRange EmptyRange = None;
3099 StringRef Base = Op.getToken();
3100 unsigned Prefixes = getPrefixes(Operands);
3102 // First, handle aliases that expand to multiple instructions.
3103 MatchFPUWaitAlias(IDLoc, Op, Operands, Out, MatchingInlineAsm);
3108 Inst.setFlags(Prefixes);
3110 // Find one unsized memory operand, if present.
3111 X86Operand *UnsizedMemOp = nullptr;
3112 for (const auto &Op : Operands) {
3113 X86Operand *X86Op = static_cast<X86Operand *>(Op.get());
3114 if (X86Op->isMemUnsized()) {
3115 UnsizedMemOp = X86Op;
3116 // Have we found an unqualified memory operand,
3117 // break. IA allows only one memory operand.
3122 // Allow some instructions to have implicitly pointer-sized operands. This is
3123 // compatible with gas.
3125 static const char *const PtrSizedInstrs[] = {"call", "jmp", "push"};
3126 for (const char *Instr : PtrSizedInstrs) {
3127 if (Mnemonic == Instr) {
3128 UnsizedMemOp->Mem.Size = getPointerWidth();
3134 SmallVector<unsigned, 8> Match;
3135 uint64_t ErrorInfoMissingFeature = 0;
3137 // If unsized push has immediate operand we should default the default pointer
3138 // size for the size.
3139 if (Mnemonic == "push" && Operands.size() == 2) {
3140 auto *X86Op = static_cast<X86Operand *>(Operands[1].get());
3141 if (X86Op->isImm()) {
3142 // If it's not a constant fall through and let remainder take care of it.
3143 const auto *CE = dyn_cast<MCConstantExpr>(X86Op->getImm());
3144 unsigned Size = getPointerWidth();
3146 (isIntN(Size, CE->getValue()) || isUIntN(Size, CE->getValue()))) {
3147 SmallString<16> Tmp;
3149 Tmp += (is64BitMode())
3151 : (is32BitMode()) ? "l" : (is16BitMode()) ? "w" : " ";
3152 Op.setTokenValue(Tmp);
3153 // Do match in ATT mode to allow explicit suffix usage.
3154 Match.push_back(MatchInstruction(Operands, Inst, ErrorInfo,
3156 false /*isParsingIntelSyntax()*/));
3157 Op.setTokenValue(Base);
3162 // If an unsized memory operand is present, try to match with each memory
3163 // operand size. In Intel assembly, the size is not part of the instruction
3165 if (UnsizedMemOp && UnsizedMemOp->isMemUnsized()) {
3166 static const unsigned MopSizes[] = {8, 16, 32, 64, 80, 128, 256, 512};
3167 for (unsigned Size : MopSizes) {
3168 UnsizedMemOp->Mem.Size = Size;
3169 uint64_t ErrorInfoIgnore;
3170 unsigned LastOpcode = Inst.getOpcode();
3171 unsigned M = MatchInstruction(Operands, Inst, ErrorInfoIgnore,
3172 MatchingInlineAsm, isParsingIntelSyntax());
3173 if (Match.empty() || LastOpcode != Inst.getOpcode())
3176 // If this returned as a missing feature failure, remember that.
3177 if (Match.back() == Match_MissingFeature)
3178 ErrorInfoMissingFeature = ErrorInfoIgnore;
3181 // Restore the size of the unsized memory operand if we modified it.
3182 UnsizedMemOp->Mem.Size = 0;
3185 // If we haven't matched anything yet, this is not a basic integer or FPU
3186 // operation. There shouldn't be any ambiguity in our mnemonic table, so try
3187 // matching with the unsized operand.
3188 if (Match.empty()) {
3189 Match.push_back(MatchInstruction(
3190 Operands, Inst, ErrorInfo, MatchingInlineAsm, isParsingIntelSyntax()));
3191 // If this returned as a missing feature failure, remember that.
3192 if (Match.back() == Match_MissingFeature)
3193 ErrorInfoMissingFeature = ErrorInfo;
3196 // Restore the size of the unsized memory operand if we modified it.
3198 UnsizedMemOp->Mem.Size = 0;
3200 // If it's a bad mnemonic, all results will be the same.
3201 if (Match.back() == Match_MnemonicFail) {
3202 return Error(IDLoc, "invalid instruction mnemonic '" + Mnemonic + "'",
3203 Op.getLocRange(), MatchingInlineAsm);
3206 unsigned NumSuccessfulMatches =
3207 std::count(std::begin(Match), std::end(Match), Match_Success);
3209 // If matching was ambiguous and we had size information from the frontend,
3210 // try again with that. This handles cases like "movxz eax, m8/m16".
3211 if (UnsizedMemOp && NumSuccessfulMatches > 1 &&
3212 UnsizedMemOp->getMemFrontendSize()) {
3213 UnsizedMemOp->Mem.Size = UnsizedMemOp->getMemFrontendSize();
3214 unsigned M = MatchInstruction(
3215 Operands, Inst, ErrorInfo, MatchingInlineAsm, isParsingIntelSyntax());
3216 if (M == Match_Success)
3217 NumSuccessfulMatches = 1;
3219 // Add a rewrite that encodes the size information we used from the
3221 InstInfo->AsmRewrites->emplace_back(
3222 AOK_SizeDirective, UnsizedMemOp->getStartLoc(),
3223 /*Len=*/0, UnsizedMemOp->getMemFrontendSize());
3226 // If exactly one matched, then we treat that as a successful match (and the
3227 // instruction will already have been filled in correctly, since the failing
3228 // matches won't have modified it).
3229 if (NumSuccessfulMatches == 1) {
3230 if (!MatchingInlineAsm && validateInstruction(Inst, Operands))
3232 // Some instructions need post-processing to, for example, tweak which
3233 // encoding is selected. Loop on it while changes happen so the individual
3234 // transformations can chain off each other.
3235 if (!MatchingInlineAsm)
3236 while (processInstruction(Inst, Operands))
3239 if (!MatchingInlineAsm)
3240 EmitInstruction(Inst, Operands, Out);
3241 Opcode = Inst.getOpcode();
3243 } else if (NumSuccessfulMatches > 1) {
3244 assert(UnsizedMemOp &&
3245 "multiple matches only possible with unsized memory operands");
3246 return Error(UnsizedMemOp->getStartLoc(),
3247 "ambiguous operand size for instruction '" + Mnemonic + "\'",
3248 UnsizedMemOp->getLocRange());
3251 // If one instruction matched with a missing feature, report this as a
3253 if (std::count(std::begin(Match), std::end(Match),
3254 Match_MissingFeature) == 1) {
3255 ErrorInfo = ErrorInfoMissingFeature;
3256 return ErrorMissingFeature(IDLoc, ErrorInfoMissingFeature,
3260 // If one instruction matched with an invalid operand, report this as an
3262 if (std::count(std::begin(Match), std::end(Match),
3263 Match_InvalidOperand) == 1) {
3264 return Error(IDLoc, "invalid operand for instruction", EmptyRange,
3268 // If all of these were an outright failure, report it in a useless way.
3269 return Error(IDLoc, "unknown instruction mnemonic", EmptyRange,
3273 bool X86AsmParser::OmitRegisterFromClobberLists(unsigned RegNo) {
3274 return X86MCRegisterClasses[X86::SEGMENT_REGRegClassID].contains(RegNo);
3277 bool X86AsmParser::ParseDirective(AsmToken DirectiveID) {
3278 MCAsmParser &Parser = getParser();
3279 StringRef IDVal = DirectiveID.getIdentifier();
3280 if (IDVal.startswith(".code"))
3281 return ParseDirectiveCode(IDVal, DirectiveID.getLoc());
3282 else if (IDVal.startswith(".att_syntax")) {
3283 getParser().setParsingInlineAsm(false);
3284 if (getLexer().isNot(AsmToken::EndOfStatement)) {
3285 if (Parser.getTok().getString() == "prefix")
3287 else if (Parser.getTok().getString() == "noprefix")
3288 return Error(DirectiveID.getLoc(), "'.att_syntax noprefix' is not "
3289 "supported: registers must have a "
3290 "'%' prefix in .att_syntax");
3292 getParser().setAssemblerDialect(0);
3294 } else if (IDVal.startswith(".intel_syntax")) {
3295 getParser().setAssemblerDialect(1);
3296 getParser().setParsingInlineAsm(true);
3297 if (getLexer().isNot(AsmToken::EndOfStatement)) {
3298 if (Parser.getTok().getString() == "noprefix")
3300 else if (Parser.getTok().getString() == "prefix")
3301 return Error(DirectiveID.getLoc(), "'.intel_syntax prefix' is not "
3302 "supported: registers must not have "
3303 "a '%' prefix in .intel_syntax");
3306 } else if (IDVal == ".even")
3307 return parseDirectiveEven(DirectiveID.getLoc());
3308 else if (IDVal == ".cv_fpo_proc")
3309 return parseDirectiveFPOProc(DirectiveID.getLoc());
3310 else if (IDVal == ".cv_fpo_setframe")
3311 return parseDirectiveFPOSetFrame(DirectiveID.getLoc());
3312 else if (IDVal == ".cv_fpo_pushreg")
3313 return parseDirectiveFPOPushReg(DirectiveID.getLoc());
3314 else if (IDVal == ".cv_fpo_stackalloc")
3315 return parseDirectiveFPOStackAlloc(DirectiveID.getLoc());
3316 else if (IDVal == ".cv_fpo_endprologue")
3317 return parseDirectiveFPOEndPrologue(DirectiveID.getLoc());
3318 else if (IDVal == ".cv_fpo_endproc")
3319 return parseDirectiveFPOEndProc(DirectiveID.getLoc());
3324 /// parseDirectiveEven
3326 bool X86AsmParser::parseDirectiveEven(SMLoc L) {
3327 if (parseToken(AsmToken::EndOfStatement, "unexpected token in directive"))
3330 const MCSection *Section = getStreamer().getCurrentSectionOnly();
3332 getStreamer().InitSections(false);
3333 Section = getStreamer().getCurrentSectionOnly();
3335 if (Section->UseCodeAlign())
3336 getStreamer().EmitCodeAlignment(2, 0);
3338 getStreamer().EmitValueToAlignment(2, 0, 1, 0);
3342 /// ParseDirectiveCode
3343 /// ::= .code16 | .code32 | .code64
3344 bool X86AsmParser::ParseDirectiveCode(StringRef IDVal, SMLoc L) {
3345 MCAsmParser &Parser = getParser();
3347 if (IDVal == ".code16") {
3349 if (!is16BitMode()) {
3350 SwitchMode(X86::Mode16Bit);
3351 getParser().getStreamer().EmitAssemblerFlag(MCAF_Code16);
3353 } else if (IDVal == ".code16gcc") {
3354 // .code16gcc parses as if in 32-bit mode, but emits code in 16-bit mode.
3357 if (!is16BitMode()) {
3358 SwitchMode(X86::Mode16Bit);
3359 getParser().getStreamer().EmitAssemblerFlag(MCAF_Code16);
3361 } else if (IDVal == ".code32") {
3363 if (!is32BitMode()) {
3364 SwitchMode(X86::Mode32Bit);
3365 getParser().getStreamer().EmitAssemblerFlag(MCAF_Code32);
3367 } else if (IDVal == ".code64") {
3369 if (!is64BitMode()) {
3370 SwitchMode(X86::Mode64Bit);
3371 getParser().getStreamer().EmitAssemblerFlag(MCAF_Code64);
3374 Error(L, "unknown directive " + IDVal);
3382 bool X86AsmParser::parseDirectiveFPOProc(SMLoc L) {
3383 MCAsmParser &Parser = getParser();
3386 if (Parser.parseIdentifier(ProcName))
3387 return Parser.TokError("expected symbol name");
3388 if (Parser.parseIntToken(ParamsSize, "expected parameter byte count"))
3390 if (!isUIntN(32, ParamsSize))
3391 return Parser.TokError("parameters size out of range");
3392 if (Parser.parseEOL("unexpected tokens"))
3393 return addErrorSuffix(" in '.cv_fpo_proc' directive");
3394 MCSymbol *ProcSym = getContext().getOrCreateSymbol(ProcName);
3395 return getTargetStreamer().emitFPOProc(ProcSym, ParamsSize, L);
3398 // .cv_fpo_setframe ebp
3399 bool X86AsmParser::parseDirectiveFPOSetFrame(SMLoc L) {
3400 MCAsmParser &Parser = getParser();
3403 if (ParseRegister(Reg, DummyLoc, DummyLoc) ||
3404 Parser.parseEOL("unexpected tokens"))
3405 return addErrorSuffix(" in '.cv_fpo_setframe' directive");
3406 return getTargetStreamer().emitFPOSetFrame(Reg, L);
3409 // .cv_fpo_pushreg ebx
3410 bool X86AsmParser::parseDirectiveFPOPushReg(SMLoc L) {
3411 MCAsmParser &Parser = getParser();
3414 if (ParseRegister(Reg, DummyLoc, DummyLoc) ||
3415 Parser.parseEOL("unexpected tokens"))
3416 return addErrorSuffix(" in '.cv_fpo_pushreg' directive");
3417 return getTargetStreamer().emitFPOPushReg(Reg, L);
3420 // .cv_fpo_stackalloc 20
3421 bool X86AsmParser::parseDirectiveFPOStackAlloc(SMLoc L) {
3422 MCAsmParser &Parser = getParser();
3424 if (Parser.parseIntToken(Offset, "expected offset") ||
3425 Parser.parseEOL("unexpected tokens"))
3426 return addErrorSuffix(" in '.cv_fpo_stackalloc' directive");
3427 return getTargetStreamer().emitFPOStackAlloc(Offset, L);
3430 // .cv_fpo_endprologue
3431 bool X86AsmParser::parseDirectiveFPOEndPrologue(SMLoc L) {
3432 MCAsmParser &Parser = getParser();
3433 if (Parser.parseEOL("unexpected tokens"))
3434 return addErrorSuffix(" in '.cv_fpo_endprologue' directive");
3435 return getTargetStreamer().emitFPOEndPrologue(L);
3439 bool X86AsmParser::parseDirectiveFPOEndProc(SMLoc L) {
3440 MCAsmParser &Parser = getParser();
3441 if (Parser.parseEOL("unexpected tokens"))
3442 return addErrorSuffix(" in '.cv_fpo_endproc' directive");
3443 return getTargetStreamer().emitFPOEndProc(L);
3446 // Force static initialization.
3447 extern "C" void LLVMInitializeX86AsmParser() {
3448 RegisterMCAsmParser<X86AsmParser> X(getTheX86_32Target());
3449 RegisterMCAsmParser<X86AsmParser> Y(getTheX86_64Target());
3452 #define GET_REGISTER_MATCHER
3453 #define GET_MATCHER_IMPLEMENTATION
3454 #define GET_SUBTARGET_FEATURE_NAME
3455 #include "X86GenAsmMatcher.inc"