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