Path: blob/main/contrib/llvm-project/llvm/lib/Target/X86/AsmParser/X86AsmParser.cpp
35294 views
//===-- X86AsmParser.cpp - Parse X86 assembly to MCInst instructions ------===//1//2// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.3// See https://llvm.org/LICENSE.txt for license information.4// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception5//6//===----------------------------------------------------------------------===//78#include "MCTargetDesc/X86BaseInfo.h"9#include "MCTargetDesc/X86EncodingOptimization.h"10#include "MCTargetDesc/X86IntelInstPrinter.h"11#include "MCTargetDesc/X86MCExpr.h"12#include "MCTargetDesc/X86MCTargetDesc.h"13#include "MCTargetDesc/X86TargetStreamer.h"14#include "TargetInfo/X86TargetInfo.h"15#include "X86AsmParserCommon.h"16#include "X86Operand.h"17#include "llvm/ADT/STLExtras.h"18#include "llvm/ADT/SmallString.h"19#include "llvm/ADT/SmallVector.h"20#include "llvm/ADT/StringSwitch.h"21#include "llvm/ADT/Twine.h"22#include "llvm/MC/MCContext.h"23#include "llvm/MC/MCExpr.h"24#include "llvm/MC/MCInst.h"25#include "llvm/MC/MCInstrInfo.h"26#include "llvm/MC/MCParser/MCAsmLexer.h"27#include "llvm/MC/MCParser/MCAsmParser.h"28#include "llvm/MC/MCParser/MCParsedAsmOperand.h"29#include "llvm/MC/MCParser/MCTargetAsmParser.h"30#include "llvm/MC/MCRegisterInfo.h"31#include "llvm/MC/MCSection.h"32#include "llvm/MC/MCStreamer.h"33#include "llvm/MC/MCSubtargetInfo.h"34#include "llvm/MC/MCSymbol.h"35#include "llvm/MC/TargetRegistry.h"36#include "llvm/Support/CommandLine.h"37#include "llvm/Support/Compiler.h"38#include "llvm/Support/SourceMgr.h"39#include "llvm/Support/raw_ostream.h"40#include <algorithm>41#include <memory>4243using namespace llvm;4445static cl::opt<bool> LVIInlineAsmHardening(46"x86-experimental-lvi-inline-asm-hardening",47cl::desc("Harden inline assembly code that may be vulnerable to Load Value"48" Injection (LVI). This feature is experimental."), cl::Hidden);4950static bool checkScale(unsigned Scale, StringRef &ErrMsg) {51if (Scale != 1 && Scale != 2 && Scale != 4 && Scale != 8) {52ErrMsg = "scale factor in address must be 1, 2, 4 or 8";53return true;54}55return false;56}5758namespace {5960// Including the generated SSE2AVX compression tables.61#define GET_X86_SSE2AVX_TABLE62#include "X86GenInstrMapping.inc"6364static const char OpPrecedence[] = {650, // IC_OR661, // IC_XOR672, // IC_AND684, // IC_LSHIFT694, // IC_RSHIFT705, // IC_PLUS715, // IC_MINUS726, // IC_MULTIPLY736, // IC_DIVIDE746, // IC_MOD757, // IC_NOT768, // IC_NEG779, // IC_RPAREN7810, // IC_LPAREN790, // IC_IMM800, // IC_REGISTER813, // IC_EQ823, // IC_NE833, // IC_LT843, // IC_LE853, // IC_GT863 // IC_GE87};8889class X86AsmParser : public MCTargetAsmParser {90ParseInstructionInfo *InstInfo;91bool Code16GCC;92unsigned ForcedDataPrefix = 0;9394enum OpcodePrefix {95OpcodePrefix_Default,96OpcodePrefix_REX,97OpcodePrefix_REX2,98OpcodePrefix_VEX,99OpcodePrefix_VEX2,100OpcodePrefix_VEX3,101OpcodePrefix_EVEX,102};103104OpcodePrefix ForcedOpcodePrefix = OpcodePrefix_Default;105106enum DispEncoding {107DispEncoding_Default,108DispEncoding_Disp8,109DispEncoding_Disp32,110};111112DispEncoding ForcedDispEncoding = DispEncoding_Default;113114// Does this instruction use apx extended register?115bool UseApxExtendedReg = false;116// Is this instruction explicitly required not to update flags?117bool ForcedNoFlag = false;118119private:120SMLoc consumeToken() {121MCAsmParser &Parser = getParser();122SMLoc Result = Parser.getTok().getLoc();123Parser.Lex();124return Result;125}126127X86TargetStreamer &getTargetStreamer() {128assert(getParser().getStreamer().getTargetStreamer() &&129"do not have a target streamer");130MCTargetStreamer &TS = *getParser().getStreamer().getTargetStreamer();131return static_cast<X86TargetStreamer &>(TS);132}133134unsigned MatchInstruction(const OperandVector &Operands, MCInst &Inst,135uint64_t &ErrorInfo, FeatureBitset &MissingFeatures,136bool matchingInlineAsm, unsigned VariantID = 0) {137// In Code16GCC mode, match as 32-bit.138if (Code16GCC)139SwitchMode(X86::Is32Bit);140unsigned rv = MatchInstructionImpl(Operands, Inst, ErrorInfo,141MissingFeatures, matchingInlineAsm,142VariantID);143if (Code16GCC)144SwitchMode(X86::Is16Bit);145return rv;146}147148enum InfixCalculatorTok {149IC_OR = 0,150IC_XOR,151IC_AND,152IC_LSHIFT,153IC_RSHIFT,154IC_PLUS,155IC_MINUS,156IC_MULTIPLY,157IC_DIVIDE,158IC_MOD,159IC_NOT,160IC_NEG,161IC_RPAREN,162IC_LPAREN,163IC_IMM,164IC_REGISTER,165IC_EQ,166IC_NE,167IC_LT,168IC_LE,169IC_GT,170IC_GE171};172173enum IntelOperatorKind {174IOK_INVALID = 0,175IOK_LENGTH,176IOK_SIZE,177IOK_TYPE,178};179180enum MasmOperatorKind {181MOK_INVALID = 0,182MOK_LENGTHOF,183MOK_SIZEOF,184MOK_TYPE,185};186187class InfixCalculator {188typedef std::pair< InfixCalculatorTok, int64_t > ICToken;189SmallVector<InfixCalculatorTok, 4> InfixOperatorStack;190SmallVector<ICToken, 4> PostfixStack;191192bool isUnaryOperator(InfixCalculatorTok Op) const {193return Op == IC_NEG || Op == IC_NOT;194}195196public:197int64_t popOperand() {198assert (!PostfixStack.empty() && "Poped an empty stack!");199ICToken Op = PostfixStack.pop_back_val();200if (!(Op.first == IC_IMM || Op.first == IC_REGISTER))201return -1; // The invalid Scale value will be caught later by checkScale202return Op.second;203}204void pushOperand(InfixCalculatorTok Op, int64_t Val = 0) {205assert ((Op == IC_IMM || Op == IC_REGISTER) &&206"Unexpected operand!");207PostfixStack.push_back(std::make_pair(Op, Val));208}209210void popOperator() { InfixOperatorStack.pop_back(); }211void pushOperator(InfixCalculatorTok Op) {212// Push the new operator if the stack is empty.213if (InfixOperatorStack.empty()) {214InfixOperatorStack.push_back(Op);215return;216}217218// Push the new operator if it has a higher precedence than the operator219// on the top of the stack or the operator on the top of the stack is a220// left parentheses.221unsigned Idx = InfixOperatorStack.size() - 1;222InfixCalculatorTok StackOp = InfixOperatorStack[Idx];223if (OpPrecedence[Op] > OpPrecedence[StackOp] || StackOp == IC_LPAREN) {224InfixOperatorStack.push_back(Op);225return;226}227228// The operator on the top of the stack has higher precedence than the229// new operator.230unsigned ParenCount = 0;231while (true) {232// Nothing to process.233if (InfixOperatorStack.empty())234break;235236Idx = InfixOperatorStack.size() - 1;237StackOp = InfixOperatorStack[Idx];238if (!(OpPrecedence[StackOp] >= OpPrecedence[Op] || ParenCount))239break;240241// If we have an even parentheses count and we see a left parentheses,242// then stop processing.243if (!ParenCount && StackOp == IC_LPAREN)244break;245246if (StackOp == IC_RPAREN) {247++ParenCount;248InfixOperatorStack.pop_back();249} else if (StackOp == IC_LPAREN) {250--ParenCount;251InfixOperatorStack.pop_back();252} else {253InfixOperatorStack.pop_back();254PostfixStack.push_back(std::make_pair(StackOp, 0));255}256}257// Push the new operator.258InfixOperatorStack.push_back(Op);259}260261int64_t execute() {262// Push any remaining operators onto the postfix stack.263while (!InfixOperatorStack.empty()) {264InfixCalculatorTok StackOp = InfixOperatorStack.pop_back_val();265if (StackOp != IC_LPAREN && StackOp != IC_RPAREN)266PostfixStack.push_back(std::make_pair(StackOp, 0));267}268269if (PostfixStack.empty())270return 0;271272SmallVector<ICToken, 16> OperandStack;273for (const ICToken &Op : PostfixStack) {274if (Op.first == IC_IMM || Op.first == IC_REGISTER) {275OperandStack.push_back(Op);276} else if (isUnaryOperator(Op.first)) {277assert (OperandStack.size() > 0 && "Too few operands.");278ICToken Operand = OperandStack.pop_back_val();279assert (Operand.first == IC_IMM &&280"Unary operation with a register!");281switch (Op.first) {282default:283report_fatal_error("Unexpected operator!");284break;285case IC_NEG:286OperandStack.push_back(std::make_pair(IC_IMM, -Operand.second));287break;288case IC_NOT:289OperandStack.push_back(std::make_pair(IC_IMM, ~Operand.second));290break;291}292} else {293assert (OperandStack.size() > 1 && "Too few operands.");294int64_t Val;295ICToken Op2 = OperandStack.pop_back_val();296ICToken Op1 = OperandStack.pop_back_val();297switch (Op.first) {298default:299report_fatal_error("Unexpected operator!");300break;301case IC_PLUS:302Val = Op1.second + Op2.second;303OperandStack.push_back(std::make_pair(IC_IMM, Val));304break;305case IC_MINUS:306Val = Op1.second - Op2.second;307OperandStack.push_back(std::make_pair(IC_IMM, Val));308break;309case IC_MULTIPLY:310assert (Op1.first == IC_IMM && Op2.first == IC_IMM &&311"Multiply operation with an immediate and a register!");312Val = Op1.second * Op2.second;313OperandStack.push_back(std::make_pair(IC_IMM, Val));314break;315case IC_DIVIDE:316assert (Op1.first == IC_IMM && Op2.first == IC_IMM &&317"Divide operation with an immediate and a register!");318assert (Op2.second != 0 && "Division by zero!");319Val = Op1.second / Op2.second;320OperandStack.push_back(std::make_pair(IC_IMM, Val));321break;322case IC_MOD:323assert (Op1.first == IC_IMM && Op2.first == IC_IMM &&324"Modulo operation with an immediate and a register!");325Val = Op1.second % Op2.second;326OperandStack.push_back(std::make_pair(IC_IMM, Val));327break;328case IC_OR:329assert (Op1.first == IC_IMM && Op2.first == IC_IMM &&330"Or operation with an immediate and a register!");331Val = Op1.second | Op2.second;332OperandStack.push_back(std::make_pair(IC_IMM, Val));333break;334case IC_XOR:335assert(Op1.first == IC_IMM && Op2.first == IC_IMM &&336"Xor operation with an immediate and a register!");337Val = Op1.second ^ Op2.second;338OperandStack.push_back(std::make_pair(IC_IMM, Val));339break;340case IC_AND:341assert (Op1.first == IC_IMM && Op2.first == IC_IMM &&342"And operation with an immediate and a register!");343Val = Op1.second & Op2.second;344OperandStack.push_back(std::make_pair(IC_IMM, Val));345break;346case IC_LSHIFT:347assert (Op1.first == IC_IMM && Op2.first == IC_IMM &&348"Left shift operation with an immediate and a register!");349Val = Op1.second << Op2.second;350OperandStack.push_back(std::make_pair(IC_IMM, Val));351break;352case IC_RSHIFT:353assert (Op1.first == IC_IMM && Op2.first == IC_IMM &&354"Right shift operation with an immediate and a register!");355Val = Op1.second >> Op2.second;356OperandStack.push_back(std::make_pair(IC_IMM, Val));357break;358case IC_EQ:359assert(Op1.first == IC_IMM && Op2.first == IC_IMM &&360"Equals operation with an immediate and a register!");361Val = (Op1.second == Op2.second) ? -1 : 0;362OperandStack.push_back(std::make_pair(IC_IMM, Val));363break;364case IC_NE:365assert(Op1.first == IC_IMM && Op2.first == IC_IMM &&366"Not-equals operation with an immediate and a register!");367Val = (Op1.second != Op2.second) ? -1 : 0;368OperandStack.push_back(std::make_pair(IC_IMM, Val));369break;370case IC_LT:371assert(Op1.first == IC_IMM && Op2.first == IC_IMM &&372"Less-than operation with an immediate and a register!");373Val = (Op1.second < Op2.second) ? -1 : 0;374OperandStack.push_back(std::make_pair(IC_IMM, Val));375break;376case IC_LE:377assert(Op1.first == IC_IMM && Op2.first == IC_IMM &&378"Less-than-or-equal operation with an immediate and a "379"register!");380Val = (Op1.second <= Op2.second) ? -1 : 0;381OperandStack.push_back(std::make_pair(IC_IMM, Val));382break;383case IC_GT:384assert(Op1.first == IC_IMM && Op2.first == IC_IMM &&385"Greater-than operation with an immediate and a register!");386Val = (Op1.second > Op2.second) ? -1 : 0;387OperandStack.push_back(std::make_pair(IC_IMM, Val));388break;389case IC_GE:390assert(Op1.first == IC_IMM && Op2.first == IC_IMM &&391"Greater-than-or-equal operation with an immediate and a "392"register!");393Val = (Op1.second >= Op2.second) ? -1 : 0;394OperandStack.push_back(std::make_pair(IC_IMM, Val));395break;396}397}398}399assert (OperandStack.size() == 1 && "Expected a single result.");400return OperandStack.pop_back_val().second;401}402};403404enum IntelExprState {405IES_INIT,406IES_OR,407IES_XOR,408IES_AND,409IES_EQ,410IES_NE,411IES_LT,412IES_LE,413IES_GT,414IES_GE,415IES_LSHIFT,416IES_RSHIFT,417IES_PLUS,418IES_MINUS,419IES_OFFSET,420IES_CAST,421IES_NOT,422IES_MULTIPLY,423IES_DIVIDE,424IES_MOD,425IES_LBRAC,426IES_RBRAC,427IES_LPAREN,428IES_RPAREN,429IES_REGISTER,430IES_INTEGER,431IES_ERROR432};433434class IntelExprStateMachine {435IntelExprState State = IES_INIT, PrevState = IES_ERROR;436unsigned BaseReg = 0, IndexReg = 0, TmpReg = 0, Scale = 0;437int64_t Imm = 0;438const MCExpr *Sym = nullptr;439StringRef SymName;440InfixCalculator IC;441InlineAsmIdentifierInfo Info;442short BracCount = 0;443bool MemExpr = false;444bool BracketUsed = false;445bool OffsetOperator = false;446bool AttachToOperandIdx = false;447bool IsPIC = false;448SMLoc OffsetOperatorLoc;449AsmTypeInfo CurType;450451bool setSymRef(const MCExpr *Val, StringRef ID, StringRef &ErrMsg) {452if (Sym) {453ErrMsg = "cannot use more than one symbol in memory operand";454return true;455}456Sym = Val;457SymName = ID;458return false;459}460461public:462IntelExprStateMachine() = default;463464void addImm(int64_t imm) { Imm += imm; }465short getBracCount() const { return BracCount; }466bool isMemExpr() const { return MemExpr; }467bool isBracketUsed() const { return BracketUsed; }468bool isOffsetOperator() const { return OffsetOperator; }469SMLoc getOffsetLoc() const { return OffsetOperatorLoc; }470unsigned getBaseReg() const { return BaseReg; }471unsigned getIndexReg() const { return IndexReg; }472unsigned getScale() const { return Scale; }473const MCExpr *getSym() const { return Sym; }474StringRef getSymName() const { return SymName; }475StringRef getType() const { return CurType.Name; }476unsigned getSize() const { return CurType.Size; }477unsigned getElementSize() const { return CurType.ElementSize; }478unsigned getLength() const { return CurType.Length; }479int64_t getImm() { return Imm + IC.execute(); }480bool isValidEndState() const {481return State == IES_RBRAC || State == IES_RPAREN ||482State == IES_INTEGER || State == IES_REGISTER ||483State == IES_OFFSET;484}485486// Is the intel expression appended after an operand index.487// [OperandIdx][Intel Expression]488// This is neccessary for checking if it is an independent489// intel expression at back end when parse inline asm.490void setAppendAfterOperand() { AttachToOperandIdx = true; }491492bool isPIC() const { return IsPIC; }493void setPIC() { IsPIC = true; }494495bool hadError() const { return State == IES_ERROR; }496const InlineAsmIdentifierInfo &getIdentifierInfo() const { return Info; }497498bool regsUseUpError(StringRef &ErrMsg) {499// This case mostly happen in inline asm, e.g. Arr[BaseReg + IndexReg]500// can not intruduce additional register in inline asm in PIC model.501if (IsPIC && AttachToOperandIdx)502ErrMsg = "Don't use 2 or more regs for mem offset in PIC model!";503else504ErrMsg = "BaseReg/IndexReg already set!";505return true;506}507508void onOr() {509IntelExprState CurrState = State;510switch (State) {511default:512State = IES_ERROR;513break;514case IES_INTEGER:515case IES_RPAREN:516case IES_REGISTER:517State = IES_OR;518IC.pushOperator(IC_OR);519break;520}521PrevState = CurrState;522}523void onXor() {524IntelExprState CurrState = State;525switch (State) {526default:527State = IES_ERROR;528break;529case IES_INTEGER:530case IES_RPAREN:531case IES_REGISTER:532State = IES_XOR;533IC.pushOperator(IC_XOR);534break;535}536PrevState = CurrState;537}538void onAnd() {539IntelExprState CurrState = State;540switch (State) {541default:542State = IES_ERROR;543break;544case IES_INTEGER:545case IES_RPAREN:546case IES_REGISTER:547State = IES_AND;548IC.pushOperator(IC_AND);549break;550}551PrevState = CurrState;552}553void onEq() {554IntelExprState CurrState = State;555switch (State) {556default:557State = IES_ERROR;558break;559case IES_INTEGER:560case IES_RPAREN:561case IES_REGISTER:562State = IES_EQ;563IC.pushOperator(IC_EQ);564break;565}566PrevState = CurrState;567}568void onNE() {569IntelExprState CurrState = State;570switch (State) {571default:572State = IES_ERROR;573break;574case IES_INTEGER:575case IES_RPAREN:576case IES_REGISTER:577State = IES_NE;578IC.pushOperator(IC_NE);579break;580}581PrevState = CurrState;582}583void onLT() {584IntelExprState CurrState = State;585switch (State) {586default:587State = IES_ERROR;588break;589case IES_INTEGER:590case IES_RPAREN:591case IES_REGISTER:592State = IES_LT;593IC.pushOperator(IC_LT);594break;595}596PrevState = CurrState;597}598void onLE() {599IntelExprState CurrState = State;600switch (State) {601default:602State = IES_ERROR;603break;604case IES_INTEGER:605case IES_RPAREN:606case IES_REGISTER:607State = IES_LE;608IC.pushOperator(IC_LE);609break;610}611PrevState = CurrState;612}613void onGT() {614IntelExprState CurrState = State;615switch (State) {616default:617State = IES_ERROR;618break;619case IES_INTEGER:620case IES_RPAREN:621case IES_REGISTER:622State = IES_GT;623IC.pushOperator(IC_GT);624break;625}626PrevState = CurrState;627}628void onGE() {629IntelExprState CurrState = State;630switch (State) {631default:632State = IES_ERROR;633break;634case IES_INTEGER:635case IES_RPAREN:636case IES_REGISTER:637State = IES_GE;638IC.pushOperator(IC_GE);639break;640}641PrevState = CurrState;642}643void onLShift() {644IntelExprState CurrState = State;645switch (State) {646default:647State = IES_ERROR;648break;649case IES_INTEGER:650case IES_RPAREN:651case IES_REGISTER:652State = IES_LSHIFT;653IC.pushOperator(IC_LSHIFT);654break;655}656PrevState = CurrState;657}658void onRShift() {659IntelExprState CurrState = State;660switch (State) {661default:662State = IES_ERROR;663break;664case IES_INTEGER:665case IES_RPAREN:666case IES_REGISTER:667State = IES_RSHIFT;668IC.pushOperator(IC_RSHIFT);669break;670}671PrevState = CurrState;672}673bool onPlus(StringRef &ErrMsg) {674IntelExprState CurrState = State;675switch (State) {676default:677State = IES_ERROR;678break;679case IES_INTEGER:680case IES_RPAREN:681case IES_REGISTER:682case IES_OFFSET:683State = IES_PLUS;684IC.pushOperator(IC_PLUS);685if (CurrState == IES_REGISTER && PrevState != IES_MULTIPLY) {686// If we already have a BaseReg, then assume this is the IndexReg with687// no explicit scale.688if (!BaseReg) {689BaseReg = TmpReg;690} else {691if (IndexReg)692return regsUseUpError(ErrMsg);693IndexReg = TmpReg;694Scale = 0;695}696}697break;698}699PrevState = CurrState;700return false;701}702bool onMinus(StringRef &ErrMsg) {703IntelExprState CurrState = State;704switch (State) {705default:706State = IES_ERROR;707break;708case IES_OR:709case IES_XOR:710case IES_AND:711case IES_EQ:712case IES_NE:713case IES_LT:714case IES_LE:715case IES_GT:716case IES_GE:717case IES_LSHIFT:718case IES_RSHIFT:719case IES_PLUS:720case IES_NOT:721case IES_MULTIPLY:722case IES_DIVIDE:723case IES_MOD:724case IES_LPAREN:725case IES_RPAREN:726case IES_LBRAC:727case IES_RBRAC:728case IES_INTEGER:729case IES_REGISTER:730case IES_INIT:731case IES_OFFSET:732State = IES_MINUS;733// push minus operator if it is not a negate operator734if (CurrState == IES_REGISTER || CurrState == IES_RPAREN ||735CurrState == IES_INTEGER || CurrState == IES_RBRAC ||736CurrState == IES_OFFSET)737IC.pushOperator(IC_MINUS);738else if (PrevState == IES_REGISTER && CurrState == IES_MULTIPLY) {739// We have negate operator for Scale: it's illegal740ErrMsg = "Scale can't be negative";741return true;742} else743IC.pushOperator(IC_NEG);744if (CurrState == IES_REGISTER && PrevState != IES_MULTIPLY) {745// If we already have a BaseReg, then assume this is the IndexReg with746// no explicit scale.747if (!BaseReg) {748BaseReg = TmpReg;749} else {750if (IndexReg)751return regsUseUpError(ErrMsg);752IndexReg = TmpReg;753Scale = 0;754}755}756break;757}758PrevState = CurrState;759return false;760}761void onNot() {762IntelExprState CurrState = State;763switch (State) {764default:765State = IES_ERROR;766break;767case IES_OR:768case IES_XOR:769case IES_AND:770case IES_EQ:771case IES_NE:772case IES_LT:773case IES_LE:774case IES_GT:775case IES_GE:776case IES_LSHIFT:777case IES_RSHIFT:778case IES_PLUS:779case IES_MINUS:780case IES_NOT:781case IES_MULTIPLY:782case IES_DIVIDE:783case IES_MOD:784case IES_LPAREN:785case IES_LBRAC:786case IES_INIT:787State = IES_NOT;788IC.pushOperator(IC_NOT);789break;790}791PrevState = CurrState;792}793bool onRegister(unsigned Reg, StringRef &ErrMsg) {794IntelExprState CurrState = State;795switch (State) {796default:797State = IES_ERROR;798break;799case IES_PLUS:800case IES_LPAREN:801case IES_LBRAC:802State = IES_REGISTER;803TmpReg = Reg;804IC.pushOperand(IC_REGISTER);805break;806case IES_MULTIPLY:807// Index Register - Scale * Register808if (PrevState == IES_INTEGER) {809if (IndexReg)810return regsUseUpError(ErrMsg);811State = IES_REGISTER;812IndexReg = Reg;813// Get the scale and replace the 'Scale * Register' with '0'.814Scale = IC.popOperand();815if (checkScale(Scale, ErrMsg))816return true;817IC.pushOperand(IC_IMM);818IC.popOperator();819} else {820State = IES_ERROR;821}822break;823}824PrevState = CurrState;825return false;826}827bool onIdentifierExpr(const MCExpr *SymRef, StringRef SymRefName,828const InlineAsmIdentifierInfo &IDInfo,829const AsmTypeInfo &Type, bool ParsingMSInlineAsm,830StringRef &ErrMsg) {831// InlineAsm: Treat an enum value as an integer832if (ParsingMSInlineAsm)833if (IDInfo.isKind(InlineAsmIdentifierInfo::IK_EnumVal))834return onInteger(IDInfo.Enum.EnumVal, ErrMsg);835// Treat a symbolic constant like an integer836if (auto *CE = dyn_cast<MCConstantExpr>(SymRef))837return onInteger(CE->getValue(), ErrMsg);838PrevState = State;839switch (State) {840default:841State = IES_ERROR;842break;843case IES_CAST:844case IES_PLUS:845case IES_MINUS:846case IES_NOT:847case IES_INIT:848case IES_LBRAC:849case IES_LPAREN:850if (setSymRef(SymRef, SymRefName, ErrMsg))851return true;852MemExpr = true;853State = IES_INTEGER;854IC.pushOperand(IC_IMM);855if (ParsingMSInlineAsm)856Info = IDInfo;857setTypeInfo(Type);858break;859}860return false;861}862bool onInteger(int64_t TmpInt, StringRef &ErrMsg) {863IntelExprState CurrState = State;864switch (State) {865default:866State = IES_ERROR;867break;868case IES_PLUS:869case IES_MINUS:870case IES_NOT:871case IES_OR:872case IES_XOR:873case IES_AND:874case IES_EQ:875case IES_NE:876case IES_LT:877case IES_LE:878case IES_GT:879case IES_GE:880case IES_LSHIFT:881case IES_RSHIFT:882case IES_DIVIDE:883case IES_MOD:884case IES_MULTIPLY:885case IES_LPAREN:886case IES_INIT:887case IES_LBRAC:888State = IES_INTEGER;889if (PrevState == IES_REGISTER && CurrState == IES_MULTIPLY) {890// Index Register - Register * Scale891if (IndexReg)892return regsUseUpError(ErrMsg);893IndexReg = TmpReg;894Scale = TmpInt;895if (checkScale(Scale, ErrMsg))896return true;897// Get the scale and replace the 'Register * Scale' with '0'.898IC.popOperator();899} else {900IC.pushOperand(IC_IMM, TmpInt);901}902break;903}904PrevState = CurrState;905return false;906}907void onStar() {908PrevState = State;909switch (State) {910default:911State = IES_ERROR;912break;913case IES_INTEGER:914case IES_REGISTER:915case IES_RPAREN:916State = IES_MULTIPLY;917IC.pushOperator(IC_MULTIPLY);918break;919}920}921void onDivide() {922PrevState = State;923switch (State) {924default:925State = IES_ERROR;926break;927case IES_INTEGER:928case IES_RPAREN:929State = IES_DIVIDE;930IC.pushOperator(IC_DIVIDE);931break;932}933}934void onMod() {935PrevState = State;936switch (State) {937default:938State = IES_ERROR;939break;940case IES_INTEGER:941case IES_RPAREN:942State = IES_MOD;943IC.pushOperator(IC_MOD);944break;945}946}947bool onLBrac() {948if (BracCount)949return true;950PrevState = State;951switch (State) {952default:953State = IES_ERROR;954break;955case IES_RBRAC:956case IES_INTEGER:957case IES_RPAREN:958State = IES_PLUS;959IC.pushOperator(IC_PLUS);960CurType.Length = 1;961CurType.Size = CurType.ElementSize;962break;963case IES_INIT:964case IES_CAST:965assert(!BracCount && "BracCount should be zero on parsing's start");966State = IES_LBRAC;967break;968}969MemExpr = true;970BracketUsed = true;971BracCount++;972return false;973}974bool onRBrac(StringRef &ErrMsg) {975IntelExprState CurrState = State;976switch (State) {977default:978State = IES_ERROR;979break;980case IES_INTEGER:981case IES_OFFSET:982case IES_REGISTER:983case IES_RPAREN:984if (BracCount-- != 1) {985ErrMsg = "unexpected bracket encountered";986return true;987}988State = IES_RBRAC;989if (CurrState == IES_REGISTER && PrevState != IES_MULTIPLY) {990// If we already have a BaseReg, then assume this is the IndexReg with991// no explicit scale.992if (!BaseReg) {993BaseReg = TmpReg;994} else {995if (IndexReg)996return regsUseUpError(ErrMsg);997IndexReg = TmpReg;998Scale = 0;999}1000}1001break;1002}1003PrevState = CurrState;1004return false;1005}1006void onLParen() {1007IntelExprState CurrState = State;1008switch (State) {1009default:1010State = IES_ERROR;1011break;1012case IES_PLUS:1013case IES_MINUS:1014case IES_NOT:1015case IES_OR:1016case IES_XOR:1017case IES_AND:1018case IES_EQ:1019case IES_NE:1020case IES_LT:1021case IES_LE:1022case IES_GT:1023case IES_GE:1024case IES_LSHIFT:1025case IES_RSHIFT:1026case IES_MULTIPLY:1027case IES_DIVIDE:1028case IES_MOD:1029case IES_LPAREN:1030case IES_INIT:1031case IES_LBRAC:1032State = IES_LPAREN;1033IC.pushOperator(IC_LPAREN);1034break;1035}1036PrevState = CurrState;1037}1038void onRParen() {1039PrevState = State;1040switch (State) {1041default:1042State = IES_ERROR;1043break;1044case IES_INTEGER:1045case IES_OFFSET:1046case IES_REGISTER:1047case IES_RBRAC:1048case IES_RPAREN:1049State = IES_RPAREN;1050IC.pushOperator(IC_RPAREN);1051break;1052}1053}1054bool onOffset(const MCExpr *Val, SMLoc OffsetLoc, StringRef ID,1055const InlineAsmIdentifierInfo &IDInfo,1056bool ParsingMSInlineAsm, StringRef &ErrMsg) {1057PrevState = State;1058switch (State) {1059default:1060ErrMsg = "unexpected offset operator expression";1061return true;1062case IES_PLUS:1063case IES_INIT:1064case IES_LBRAC:1065if (setSymRef(Val, ID, ErrMsg))1066return true;1067OffsetOperator = true;1068OffsetOperatorLoc = OffsetLoc;1069State = IES_OFFSET;1070// As we cannot yet resolve the actual value (offset), we retain1071// the requested semantics by pushing a '0' to the operands stack1072IC.pushOperand(IC_IMM);1073if (ParsingMSInlineAsm) {1074Info = IDInfo;1075}1076break;1077}1078return false;1079}1080void onCast(AsmTypeInfo Info) {1081PrevState = State;1082switch (State) {1083default:1084State = IES_ERROR;1085break;1086case IES_LPAREN:1087setTypeInfo(Info);1088State = IES_CAST;1089break;1090}1091}1092void setTypeInfo(AsmTypeInfo Type) { CurType = Type; }1093};10941095bool Error(SMLoc L, const Twine &Msg, SMRange Range = std::nullopt,1096bool MatchingInlineAsm = false) {1097MCAsmParser &Parser = getParser();1098if (MatchingInlineAsm) {1099if (!getLexer().isAtStartOfStatement())1100Parser.eatToEndOfStatement();1101return false;1102}1103return Parser.Error(L, Msg, Range);1104}11051106bool MatchRegisterByName(MCRegister &RegNo, StringRef RegName, SMLoc StartLoc,1107SMLoc EndLoc);1108bool ParseRegister(MCRegister &RegNo, SMLoc &StartLoc, SMLoc &EndLoc,1109bool RestoreOnFailure);11101111std::unique_ptr<X86Operand> DefaultMemSIOperand(SMLoc Loc);1112std::unique_ptr<X86Operand> DefaultMemDIOperand(SMLoc Loc);1113bool IsSIReg(unsigned Reg);1114unsigned GetSIDIForRegClass(unsigned RegClassID, unsigned Reg, bool IsSIReg);1115void1116AddDefaultSrcDestOperands(OperandVector &Operands,1117std::unique_ptr<llvm::MCParsedAsmOperand> &&Src,1118std::unique_ptr<llvm::MCParsedAsmOperand> &&Dst);1119bool VerifyAndAdjustOperands(OperandVector &OrigOperands,1120OperandVector &FinalOperands);1121bool parseOperand(OperandVector &Operands, StringRef Name);1122bool parseATTOperand(OperandVector &Operands);1123bool parseIntelOperand(OperandVector &Operands, StringRef Name);1124bool ParseIntelOffsetOperator(const MCExpr *&Val, StringRef &ID,1125InlineAsmIdentifierInfo &Info, SMLoc &End);1126bool ParseIntelDotOperator(IntelExprStateMachine &SM, SMLoc &End);1127unsigned IdentifyIntelInlineAsmOperator(StringRef Name);1128unsigned ParseIntelInlineAsmOperator(unsigned OpKind);1129unsigned IdentifyMasmOperator(StringRef Name);1130bool ParseMasmOperator(unsigned OpKind, int64_t &Val);1131bool ParseRoundingModeOp(SMLoc Start, OperandVector &Operands);1132bool parseCFlagsOp(OperandVector &Operands);1133bool ParseIntelNamedOperator(StringRef Name, IntelExprStateMachine &SM,1134bool &ParseError, SMLoc &End);1135bool ParseMasmNamedOperator(StringRef Name, IntelExprStateMachine &SM,1136bool &ParseError, SMLoc &End);1137void RewriteIntelExpression(IntelExprStateMachine &SM, SMLoc Start,1138SMLoc End);1139bool ParseIntelExpression(IntelExprStateMachine &SM, SMLoc &End);1140bool ParseIntelInlineAsmIdentifier(const MCExpr *&Val, StringRef &Identifier,1141InlineAsmIdentifierInfo &Info,1142bool IsUnevaluatedOperand, SMLoc &End,1143bool IsParsingOffsetOperator = false);1144void tryParseOperandIdx(AsmToken::TokenKind PrevTK,1145IntelExprStateMachine &SM);11461147bool ParseMemOperand(unsigned SegReg, const MCExpr *Disp, SMLoc StartLoc,1148SMLoc EndLoc, OperandVector &Operands);11491150X86::CondCode ParseConditionCode(StringRef CCode);11511152bool ParseIntelMemoryOperandSize(unsigned &Size);1153bool CreateMemForMSInlineAsm(unsigned SegReg, const MCExpr *Disp,1154unsigned BaseReg, unsigned IndexReg,1155unsigned Scale, bool NonAbsMem, SMLoc Start,1156SMLoc End, unsigned Size, StringRef Identifier,1157const InlineAsmIdentifierInfo &Info,1158OperandVector &Operands);11591160bool parseDirectiveArch();1161bool parseDirectiveNops(SMLoc L);1162bool parseDirectiveEven(SMLoc L);1163bool ParseDirectiveCode(StringRef IDVal, SMLoc L);11641165/// CodeView FPO data directives.1166bool parseDirectiveFPOProc(SMLoc L);1167bool parseDirectiveFPOSetFrame(SMLoc L);1168bool parseDirectiveFPOPushReg(SMLoc L);1169bool parseDirectiveFPOStackAlloc(SMLoc L);1170bool parseDirectiveFPOStackAlign(SMLoc L);1171bool parseDirectiveFPOEndPrologue(SMLoc L);1172bool parseDirectiveFPOEndProc(SMLoc L);11731174/// SEH directives.1175bool parseSEHRegisterNumber(unsigned RegClassID, MCRegister &RegNo);1176bool parseDirectiveSEHPushReg(SMLoc);1177bool parseDirectiveSEHSetFrame(SMLoc);1178bool parseDirectiveSEHSaveReg(SMLoc);1179bool parseDirectiveSEHSaveXMM(SMLoc);1180bool parseDirectiveSEHPushFrame(SMLoc);11811182unsigned checkTargetMatchPredicate(MCInst &Inst) override;11831184bool validateInstruction(MCInst &Inst, const OperandVector &Ops);1185bool processInstruction(MCInst &Inst, const OperandVector &Ops);11861187// Load Value Injection (LVI) Mitigations for machine code1188void emitWarningForSpecialLVIInstruction(SMLoc Loc);1189void applyLVICFIMitigation(MCInst &Inst, MCStreamer &Out);1190void applyLVILoadHardeningMitigation(MCInst &Inst, MCStreamer &Out);11911192/// Wrapper around MCStreamer::emitInstruction(). Possibly adds1193/// instrumentation around Inst.1194void emitInstruction(MCInst &Inst, OperandVector &Operands, MCStreamer &Out);11951196bool MatchAndEmitInstruction(SMLoc IDLoc, unsigned &Opcode,1197OperandVector &Operands, MCStreamer &Out,1198uint64_t &ErrorInfo,1199bool MatchingInlineAsm) override;12001201void MatchFPUWaitAlias(SMLoc IDLoc, X86Operand &Op, OperandVector &Operands,1202MCStreamer &Out, bool MatchingInlineAsm);12031204bool ErrorMissingFeature(SMLoc IDLoc, const FeatureBitset &MissingFeatures,1205bool MatchingInlineAsm);12061207bool matchAndEmitATTInstruction(SMLoc IDLoc, unsigned &Opcode, MCInst &Inst,1208OperandVector &Operands, MCStreamer &Out,1209uint64_t &ErrorInfo, bool MatchingInlineAsm);12101211bool matchAndEmitIntelInstruction(SMLoc IDLoc, unsigned &Opcode, MCInst &Inst,1212OperandVector &Operands, MCStreamer &Out,1213uint64_t &ErrorInfo,1214bool MatchingInlineAsm);12151216bool OmitRegisterFromClobberLists(unsigned RegNo) override;12171218/// Parses AVX512 specific operand primitives: masked registers ({%k<NUM>}, {z})1219/// and memory broadcasting ({1to<NUM>}) primitives, updating Operands vector if required.1220/// return false if no parsing errors occurred, true otherwise.1221bool HandleAVX512Operand(OperandVector &Operands);12221223bool ParseZ(std::unique_ptr<X86Operand> &Z, const SMLoc &StartLoc);12241225bool is64BitMode() const {1226// FIXME: Can tablegen auto-generate this?1227return getSTI().hasFeature(X86::Is64Bit);1228}1229bool is32BitMode() const {1230// FIXME: Can tablegen auto-generate this?1231return getSTI().hasFeature(X86::Is32Bit);1232}1233bool is16BitMode() const {1234// FIXME: Can tablegen auto-generate this?1235return getSTI().hasFeature(X86::Is16Bit);1236}1237void SwitchMode(unsigned mode) {1238MCSubtargetInfo &STI = copySTI();1239FeatureBitset AllModes({X86::Is64Bit, X86::Is32Bit, X86::Is16Bit});1240FeatureBitset OldMode = STI.getFeatureBits() & AllModes;1241FeatureBitset FB = ComputeAvailableFeatures(1242STI.ToggleFeature(OldMode.flip(mode)));1243setAvailableFeatures(FB);12441245assert(FeatureBitset({mode}) == (STI.getFeatureBits() & AllModes));1246}12471248unsigned getPointerWidth() {1249if (is16BitMode()) return 16;1250if (is32BitMode()) return 32;1251if (is64BitMode()) return 64;1252llvm_unreachable("invalid mode");1253}12541255bool isParsingIntelSyntax() {1256return getParser().getAssemblerDialect();1257}12581259/// @name Auto-generated Matcher Functions1260/// {12611262#define GET_ASSEMBLER_HEADER1263#include "X86GenAsmMatcher.inc"12641265/// }12661267public:1268enum X86MatchResultTy {1269Match_Unsupported = FIRST_TARGET_MATCH_RESULT_TY,1270#define GET_OPERAND_DIAGNOSTIC_TYPES1271#include "X86GenAsmMatcher.inc"1272};12731274X86AsmParser(const MCSubtargetInfo &sti, MCAsmParser &Parser,1275const MCInstrInfo &mii, const MCTargetOptions &Options)1276: MCTargetAsmParser(Options, sti, mii), InstInfo(nullptr),1277Code16GCC(false) {12781279Parser.addAliasForDirective(".word", ".2byte");12801281// Initialize the set of available features.1282setAvailableFeatures(ComputeAvailableFeatures(getSTI().getFeatureBits()));1283}12841285bool parseRegister(MCRegister &Reg, SMLoc &StartLoc, SMLoc &EndLoc) override;1286ParseStatus tryParseRegister(MCRegister &Reg, SMLoc &StartLoc,1287SMLoc &EndLoc) override;12881289bool parsePrimaryExpr(const MCExpr *&Res, SMLoc &EndLoc) override;12901291bool ParseInstruction(ParseInstructionInfo &Info, StringRef Name,1292SMLoc NameLoc, OperandVector &Operands) override;12931294bool ParseDirective(AsmToken DirectiveID) override;1295};1296} // end anonymous namespace12971298#define GET_REGISTER_MATCHER1299#define GET_SUBTARGET_FEATURE_NAME1300#include "X86GenAsmMatcher.inc"13011302static bool CheckBaseRegAndIndexRegAndScale(unsigned BaseReg, unsigned IndexReg,1303unsigned Scale, bool Is64BitMode,1304StringRef &ErrMsg) {1305// If we have both a base register and an index register make sure they are1306// both 64-bit or 32-bit registers.1307// To support VSIB, IndexReg can be 128-bit or 256-bit registers.13081309if (BaseReg != 0 &&1310!(BaseReg == X86::RIP || BaseReg == X86::EIP ||1311X86MCRegisterClasses[X86::GR16RegClassID].contains(BaseReg) ||1312X86MCRegisterClasses[X86::GR32RegClassID].contains(BaseReg) ||1313X86MCRegisterClasses[X86::GR64RegClassID].contains(BaseReg))) {1314ErrMsg = "invalid base+index expression";1315return true;1316}13171318if (IndexReg != 0 &&1319!(IndexReg == X86::EIZ || IndexReg == X86::RIZ ||1320X86MCRegisterClasses[X86::GR16RegClassID].contains(IndexReg) ||1321X86MCRegisterClasses[X86::GR32RegClassID].contains(IndexReg) ||1322X86MCRegisterClasses[X86::GR64RegClassID].contains(IndexReg) ||1323X86MCRegisterClasses[X86::VR128XRegClassID].contains(IndexReg) ||1324X86MCRegisterClasses[X86::VR256XRegClassID].contains(IndexReg) ||1325X86MCRegisterClasses[X86::VR512RegClassID].contains(IndexReg))) {1326ErrMsg = "invalid base+index expression";1327return true;1328}13291330if (((BaseReg == X86::RIP || BaseReg == X86::EIP) && IndexReg != 0) ||1331IndexReg == X86::EIP || IndexReg == X86::RIP ||1332IndexReg == X86::ESP || IndexReg == X86::RSP) {1333ErrMsg = "invalid base+index expression";1334return true;1335}13361337// Check for use of invalid 16-bit registers. Only BX/BP/SI/DI are allowed,1338// and then only in non-64-bit modes.1339if (X86MCRegisterClasses[X86::GR16RegClassID].contains(BaseReg) &&1340(Is64BitMode || (BaseReg != X86::BX && BaseReg != X86::BP &&1341BaseReg != X86::SI && BaseReg != X86::DI))) {1342ErrMsg = "invalid 16-bit base register";1343return true;1344}13451346if (BaseReg == 0 &&1347X86MCRegisterClasses[X86::GR16RegClassID].contains(IndexReg)) {1348ErrMsg = "16-bit memory operand may not include only index register";1349return true;1350}13511352if (BaseReg != 0 && IndexReg != 0) {1353if (X86MCRegisterClasses[X86::GR64RegClassID].contains(BaseReg) &&1354(X86MCRegisterClasses[X86::GR16RegClassID].contains(IndexReg) ||1355X86MCRegisterClasses[X86::GR32RegClassID].contains(IndexReg) ||1356IndexReg == X86::EIZ)) {1357ErrMsg = "base register is 64-bit, but index register is not";1358return true;1359}1360if (X86MCRegisterClasses[X86::GR32RegClassID].contains(BaseReg) &&1361(X86MCRegisterClasses[X86::GR16RegClassID].contains(IndexReg) ||1362X86MCRegisterClasses[X86::GR64RegClassID].contains(IndexReg) ||1363IndexReg == X86::RIZ)) {1364ErrMsg = "base register is 32-bit, but index register is not";1365return true;1366}1367if (X86MCRegisterClasses[X86::GR16RegClassID].contains(BaseReg)) {1368if (X86MCRegisterClasses[X86::GR32RegClassID].contains(IndexReg) ||1369X86MCRegisterClasses[X86::GR64RegClassID].contains(IndexReg)) {1370ErrMsg = "base register is 16-bit, but index register is not";1371return true;1372}1373if ((BaseReg != X86::BX && BaseReg != X86::BP) ||1374(IndexReg != X86::SI && IndexReg != X86::DI)) {1375ErrMsg = "invalid 16-bit base/index register combination";1376return true;1377}1378}1379}13801381// RIP/EIP-relative addressing is only supported in 64-bit mode.1382if (!Is64BitMode && BaseReg != 0 &&1383(BaseReg == X86::RIP || BaseReg == X86::EIP)) {1384ErrMsg = "IP-relative addressing requires 64-bit mode";1385return true;1386}13871388return checkScale(Scale, ErrMsg);1389}13901391bool X86AsmParser::MatchRegisterByName(MCRegister &RegNo, StringRef RegName,1392SMLoc StartLoc, SMLoc EndLoc) {1393// If we encounter a %, ignore it. This code handles registers with and1394// without the prefix, unprefixed registers can occur in cfi directives.1395RegName.consume_front("%");13961397RegNo = MatchRegisterName(RegName);13981399// If the match failed, try the register name as lowercase.1400if (RegNo == 0)1401RegNo = MatchRegisterName(RegName.lower());14021403// The "flags" and "mxcsr" registers cannot be referenced directly.1404// Treat it as an identifier instead.1405if (isParsingMSInlineAsm() && isParsingIntelSyntax() &&1406(RegNo == X86::EFLAGS || RegNo == X86::MXCSR))1407RegNo = 0;14081409if (!is64BitMode()) {1410// FIXME: This should be done using Requires<Not64BitMode> and1411// Requires<In64BitMode> so "eiz" usage in 64-bit instructions can be also1412// checked.1413if (RegNo == X86::RIZ || RegNo == X86::RIP ||1414X86MCRegisterClasses[X86::GR64RegClassID].contains(RegNo) ||1415X86II::isX86_64NonExtLowByteReg(RegNo) ||1416X86II::isX86_64ExtendedReg(RegNo)) {1417return Error(StartLoc,1418"register %" + RegName + " is only available in 64-bit mode",1419SMRange(StartLoc, EndLoc));1420}1421}14221423if (X86II::isApxExtendedReg(RegNo))1424UseApxExtendedReg = true;14251426// If this is "db[0-15]", match it as an alias1427// for dr[0-15].1428if (RegNo == 0 && RegName.starts_with("db")) {1429if (RegName.size() == 3) {1430switch (RegName[2]) {1431case '0':1432RegNo = X86::DR0;1433break;1434case '1':1435RegNo = X86::DR1;1436break;1437case '2':1438RegNo = X86::DR2;1439break;1440case '3':1441RegNo = X86::DR3;1442break;1443case '4':1444RegNo = X86::DR4;1445break;1446case '5':1447RegNo = X86::DR5;1448break;1449case '6':1450RegNo = X86::DR6;1451break;1452case '7':1453RegNo = X86::DR7;1454break;1455case '8':1456RegNo = X86::DR8;1457break;1458case '9':1459RegNo = X86::DR9;1460break;1461}1462} else if (RegName.size() == 4 && RegName[2] == '1') {1463switch (RegName[3]) {1464case '0':1465RegNo = X86::DR10;1466break;1467case '1':1468RegNo = X86::DR11;1469break;1470case '2':1471RegNo = X86::DR12;1472break;1473case '3':1474RegNo = X86::DR13;1475break;1476case '4':1477RegNo = X86::DR14;1478break;1479case '5':1480RegNo = X86::DR15;1481break;1482}1483}1484}14851486if (RegNo == 0) {1487if (isParsingIntelSyntax())1488return true;1489return Error(StartLoc, "invalid register name", SMRange(StartLoc, EndLoc));1490}1491return false;1492}14931494bool X86AsmParser::ParseRegister(MCRegister &RegNo, SMLoc &StartLoc,1495SMLoc &EndLoc, bool RestoreOnFailure) {1496MCAsmParser &Parser = getParser();1497MCAsmLexer &Lexer = getLexer();1498RegNo = 0;14991500SmallVector<AsmToken, 5> Tokens;1501auto OnFailure = [RestoreOnFailure, &Lexer, &Tokens]() {1502if (RestoreOnFailure) {1503while (!Tokens.empty()) {1504Lexer.UnLex(Tokens.pop_back_val());1505}1506}1507};15081509const AsmToken &PercentTok = Parser.getTok();1510StartLoc = PercentTok.getLoc();15111512// If we encounter a %, ignore it. This code handles registers with and1513// without the prefix, unprefixed registers can occur in cfi directives.1514if (!isParsingIntelSyntax() && PercentTok.is(AsmToken::Percent)) {1515Tokens.push_back(PercentTok);1516Parser.Lex(); // Eat percent token.1517}15181519const AsmToken &Tok = Parser.getTok();1520EndLoc = Tok.getEndLoc();15211522if (Tok.isNot(AsmToken::Identifier)) {1523OnFailure();1524if (isParsingIntelSyntax()) return true;1525return Error(StartLoc, "invalid register name",1526SMRange(StartLoc, EndLoc));1527}15281529if (MatchRegisterByName(RegNo, Tok.getString(), StartLoc, EndLoc)) {1530OnFailure();1531return true;1532}15331534// Parse "%st" as "%st(0)" and "%st(1)", which is multiple tokens.1535if (RegNo == X86::ST0) {1536Tokens.push_back(Tok);1537Parser.Lex(); // Eat 'st'15381539// Check to see if we have '(4)' after %st.1540if (Lexer.isNot(AsmToken::LParen))1541return false;1542// Lex the paren.1543Tokens.push_back(Parser.getTok());1544Parser.Lex();15451546const AsmToken &IntTok = Parser.getTok();1547if (IntTok.isNot(AsmToken::Integer)) {1548OnFailure();1549return Error(IntTok.getLoc(), "expected stack index");1550}1551switch (IntTok.getIntVal()) {1552case 0: RegNo = X86::ST0; break;1553case 1: RegNo = X86::ST1; break;1554case 2: RegNo = X86::ST2; break;1555case 3: RegNo = X86::ST3; break;1556case 4: RegNo = X86::ST4; break;1557case 5: RegNo = X86::ST5; break;1558case 6: RegNo = X86::ST6; break;1559case 7: RegNo = X86::ST7; break;1560default:1561OnFailure();1562return Error(IntTok.getLoc(), "invalid stack index");1563}15641565// Lex IntTok1566Tokens.push_back(IntTok);1567Parser.Lex();1568if (Lexer.isNot(AsmToken::RParen)) {1569OnFailure();1570return Error(Parser.getTok().getLoc(), "expected ')'");1571}15721573EndLoc = Parser.getTok().getEndLoc();1574Parser.Lex(); // Eat ')'1575return false;1576}15771578EndLoc = Parser.getTok().getEndLoc();15791580if (RegNo == 0) {1581OnFailure();1582if (isParsingIntelSyntax()) return true;1583return Error(StartLoc, "invalid register name",1584SMRange(StartLoc, EndLoc));1585}15861587Parser.Lex(); // Eat identifier token.1588return false;1589}15901591bool X86AsmParser::parseRegister(MCRegister &Reg, SMLoc &StartLoc,1592SMLoc &EndLoc) {1593return ParseRegister(Reg, StartLoc, EndLoc, /*RestoreOnFailure=*/false);1594}15951596ParseStatus X86AsmParser::tryParseRegister(MCRegister &Reg, SMLoc &StartLoc,1597SMLoc &EndLoc) {1598bool Result = ParseRegister(Reg, StartLoc, EndLoc, /*RestoreOnFailure=*/true);1599bool PendingErrors = getParser().hasPendingError();1600getParser().clearPendingErrors();1601if (PendingErrors)1602return ParseStatus::Failure;1603if (Result)1604return ParseStatus::NoMatch;1605return ParseStatus::Success;1606}16071608std::unique_ptr<X86Operand> X86AsmParser::DefaultMemSIOperand(SMLoc Loc) {1609bool Parse32 = is32BitMode() || Code16GCC;1610unsigned Basereg = is64BitMode() ? X86::RSI : (Parse32 ? X86::ESI : X86::SI);1611const MCExpr *Disp = MCConstantExpr::create(0, getContext());1612return X86Operand::CreateMem(getPointerWidth(), /*SegReg=*/0, Disp,1613/*BaseReg=*/Basereg, /*IndexReg=*/0, /*Scale=*/1,1614Loc, Loc, 0);1615}16161617std::unique_ptr<X86Operand> X86AsmParser::DefaultMemDIOperand(SMLoc Loc) {1618bool Parse32 = is32BitMode() || Code16GCC;1619unsigned Basereg = is64BitMode() ? X86::RDI : (Parse32 ? X86::EDI : X86::DI);1620const MCExpr *Disp = MCConstantExpr::create(0, getContext());1621return X86Operand::CreateMem(getPointerWidth(), /*SegReg=*/0, Disp,1622/*BaseReg=*/Basereg, /*IndexReg=*/0, /*Scale=*/1,1623Loc, Loc, 0);1624}16251626bool X86AsmParser::IsSIReg(unsigned Reg) {1627switch (Reg) {1628default: llvm_unreachable("Only (R|E)SI and (R|E)DI are expected!");1629case X86::RSI:1630case X86::ESI:1631case X86::SI:1632return true;1633case X86::RDI:1634case X86::EDI:1635case X86::DI:1636return false;1637}1638}16391640unsigned X86AsmParser::GetSIDIForRegClass(unsigned RegClassID, unsigned Reg,1641bool IsSIReg) {1642switch (RegClassID) {1643default: llvm_unreachable("Unexpected register class");1644case X86::GR64RegClassID:1645return IsSIReg ? X86::RSI : X86::RDI;1646case X86::GR32RegClassID:1647return IsSIReg ? X86::ESI : X86::EDI;1648case X86::GR16RegClassID:1649return IsSIReg ? X86::SI : X86::DI;1650}1651}16521653void X86AsmParser::AddDefaultSrcDestOperands(1654OperandVector& Operands, std::unique_ptr<llvm::MCParsedAsmOperand> &&Src,1655std::unique_ptr<llvm::MCParsedAsmOperand> &&Dst) {1656if (isParsingIntelSyntax()) {1657Operands.push_back(std::move(Dst));1658Operands.push_back(std::move(Src));1659}1660else {1661Operands.push_back(std::move(Src));1662Operands.push_back(std::move(Dst));1663}1664}16651666bool X86AsmParser::VerifyAndAdjustOperands(OperandVector &OrigOperands,1667OperandVector &FinalOperands) {16681669if (OrigOperands.size() > 1) {1670// Check if sizes match, OrigOperands also contains the instruction name1671assert(OrigOperands.size() == FinalOperands.size() + 1 &&1672"Operand size mismatch");16731674SmallVector<std::pair<SMLoc, std::string>, 2> Warnings;1675// Verify types match1676int RegClassID = -1;1677for (unsigned int i = 0; i < FinalOperands.size(); ++i) {1678X86Operand &OrigOp = static_cast<X86Operand &>(*OrigOperands[i + 1]);1679X86Operand &FinalOp = static_cast<X86Operand &>(*FinalOperands[i]);16801681if (FinalOp.isReg() &&1682(!OrigOp.isReg() || FinalOp.getReg() != OrigOp.getReg()))1683// Return false and let a normal complaint about bogus operands happen1684return false;16851686if (FinalOp.isMem()) {16871688if (!OrigOp.isMem())1689// Return false and let a normal complaint about bogus operands happen1690return false;16911692unsigned OrigReg = OrigOp.Mem.BaseReg;1693unsigned FinalReg = FinalOp.Mem.BaseReg;16941695// If we've already encounterd a register class, make sure all register1696// bases are of the same register class1697if (RegClassID != -1 &&1698!X86MCRegisterClasses[RegClassID].contains(OrigReg)) {1699return Error(OrigOp.getStartLoc(),1700"mismatching source and destination index registers");1701}17021703if (X86MCRegisterClasses[X86::GR64RegClassID].contains(OrigReg))1704RegClassID = X86::GR64RegClassID;1705else if (X86MCRegisterClasses[X86::GR32RegClassID].contains(OrigReg))1706RegClassID = X86::GR32RegClassID;1707else if (X86MCRegisterClasses[X86::GR16RegClassID].contains(OrigReg))1708RegClassID = X86::GR16RegClassID;1709else1710// Unexpected register class type1711// Return false and let a normal complaint about bogus operands happen1712return false;17131714bool IsSI = IsSIReg(FinalReg);1715FinalReg = GetSIDIForRegClass(RegClassID, FinalReg, IsSI);17161717if (FinalReg != OrigReg) {1718std::string RegName = IsSI ? "ES:(R|E)SI" : "ES:(R|E)DI";1719Warnings.push_back(std::make_pair(1720OrigOp.getStartLoc(),1721"memory operand is only for determining the size, " + RegName +1722" will be used for the location"));1723}17241725FinalOp.Mem.Size = OrigOp.Mem.Size;1726FinalOp.Mem.SegReg = OrigOp.Mem.SegReg;1727FinalOp.Mem.BaseReg = FinalReg;1728}1729}17301731// Produce warnings only if all the operands passed the adjustment - prevent1732// legal cases like "movsd (%rax), %xmm0" mistakenly produce warnings1733for (auto &WarningMsg : Warnings) {1734Warning(WarningMsg.first, WarningMsg.second);1735}17361737// Remove old operands1738for (unsigned int i = 0; i < FinalOperands.size(); ++i)1739OrigOperands.pop_back();1740}1741// OrigOperands.append(FinalOperands.begin(), FinalOperands.end());1742for (auto &Op : FinalOperands)1743OrigOperands.push_back(std::move(Op));17441745return false;1746}17471748bool X86AsmParser::parseOperand(OperandVector &Operands, StringRef Name) {1749if (isParsingIntelSyntax())1750return parseIntelOperand(Operands, Name);17511752return parseATTOperand(Operands);1753}17541755bool X86AsmParser::CreateMemForMSInlineAsm(unsigned SegReg, const MCExpr *Disp,1756unsigned BaseReg, unsigned IndexReg,1757unsigned Scale, bool NonAbsMem,1758SMLoc Start, SMLoc End,1759unsigned Size, StringRef Identifier,1760const InlineAsmIdentifierInfo &Info,1761OperandVector &Operands) {1762// If we found a decl other than a VarDecl, then assume it is a FuncDecl or1763// some other label reference.1764if (Info.isKind(InlineAsmIdentifierInfo::IK_Label)) {1765// Create an absolute memory reference in order to match against1766// instructions taking a PC relative operand.1767Operands.push_back(X86Operand::CreateMem(getPointerWidth(), Disp, Start,1768End, Size, Identifier,1769Info.Label.Decl));1770return false;1771}1772// We either have a direct symbol reference, or an offset from a symbol. The1773// parser always puts the symbol on the LHS, so look there for size1774// calculation purposes.1775unsigned FrontendSize = 0;1776void *Decl = nullptr;1777bool IsGlobalLV = false;1778if (Info.isKind(InlineAsmIdentifierInfo::IK_Var)) {1779// Size is in terms of bits in this context.1780FrontendSize = Info.Var.Type * 8;1781Decl = Info.Var.Decl;1782IsGlobalLV = Info.Var.IsGlobalLV;1783}1784// It is widely common for MS InlineAsm to use a global variable and one/two1785// registers in a mmory expression, and though unaccessible via rip/eip.1786if (IsGlobalLV) {1787if (BaseReg || IndexReg) {1788Operands.push_back(X86Operand::CreateMem(getPointerWidth(), Disp, Start,1789End, Size, Identifier, Decl, 0,1790BaseReg && IndexReg));1791return false;1792}1793if (NonAbsMem)1794BaseReg = 1; // Make isAbsMem() false1795}1796Operands.push_back(X86Operand::CreateMem(1797getPointerWidth(), SegReg, Disp, BaseReg, IndexReg, Scale, Start, End,1798Size,1799/*DefaultBaseReg=*/X86::RIP, Identifier, Decl, FrontendSize));1800return false;1801}18021803// Some binary bitwise operators have a named synonymous1804// Query a candidate string for being such a named operator1805// and if so - invoke the appropriate handler1806bool X86AsmParser::ParseIntelNamedOperator(StringRef Name,1807IntelExprStateMachine &SM,1808bool &ParseError, SMLoc &End) {1809// A named operator should be either lower or upper case, but not a mix...1810// except in MASM, which uses full case-insensitivity.1811if (Name != Name.lower() && Name != Name.upper() &&1812!getParser().isParsingMasm())1813return false;1814if (Name.equals_insensitive("not")) {1815SM.onNot();1816} else if (Name.equals_insensitive("or")) {1817SM.onOr();1818} else if (Name.equals_insensitive("shl")) {1819SM.onLShift();1820} else if (Name.equals_insensitive("shr")) {1821SM.onRShift();1822} else if (Name.equals_insensitive("xor")) {1823SM.onXor();1824} else if (Name.equals_insensitive("and")) {1825SM.onAnd();1826} else if (Name.equals_insensitive("mod")) {1827SM.onMod();1828} else if (Name.equals_insensitive("offset")) {1829SMLoc OffsetLoc = getTok().getLoc();1830const MCExpr *Val = nullptr;1831StringRef ID;1832InlineAsmIdentifierInfo Info;1833ParseError = ParseIntelOffsetOperator(Val, ID, Info, End);1834if (ParseError)1835return true;1836StringRef ErrMsg;1837ParseError =1838SM.onOffset(Val, OffsetLoc, ID, Info, isParsingMSInlineAsm(), ErrMsg);1839if (ParseError)1840return Error(SMLoc::getFromPointer(Name.data()), ErrMsg);1841} else {1842return false;1843}1844if (!Name.equals_insensitive("offset"))1845End = consumeToken();1846return true;1847}1848bool X86AsmParser::ParseMasmNamedOperator(StringRef Name,1849IntelExprStateMachine &SM,1850bool &ParseError, SMLoc &End) {1851if (Name.equals_insensitive("eq")) {1852SM.onEq();1853} else if (Name.equals_insensitive("ne")) {1854SM.onNE();1855} else if (Name.equals_insensitive("lt")) {1856SM.onLT();1857} else if (Name.equals_insensitive("le")) {1858SM.onLE();1859} else if (Name.equals_insensitive("gt")) {1860SM.onGT();1861} else if (Name.equals_insensitive("ge")) {1862SM.onGE();1863} else {1864return false;1865}1866End = consumeToken();1867return true;1868}18691870// Check if current intel expression append after an operand.1871// Like: [Operand][Intel Expression]1872void X86AsmParser::tryParseOperandIdx(AsmToken::TokenKind PrevTK,1873IntelExprStateMachine &SM) {1874if (PrevTK != AsmToken::RBrac)1875return;18761877SM.setAppendAfterOperand();1878}18791880bool X86AsmParser::ParseIntelExpression(IntelExprStateMachine &SM, SMLoc &End) {1881MCAsmParser &Parser = getParser();1882StringRef ErrMsg;18831884AsmToken::TokenKind PrevTK = AsmToken::Error;18851886if (getContext().getObjectFileInfo()->isPositionIndependent())1887SM.setPIC();18881889bool Done = false;1890while (!Done) {1891// Get a fresh reference on each loop iteration in case the previous1892// iteration moved the token storage during UnLex().1893const AsmToken &Tok = Parser.getTok();18941895bool UpdateLocLex = true;1896AsmToken::TokenKind TK = getLexer().getKind();18971898switch (TK) {1899default:1900if ((Done = SM.isValidEndState()))1901break;1902return Error(Tok.getLoc(), "unknown token in expression");1903case AsmToken::Error:1904return Error(getLexer().getErrLoc(), getLexer().getErr());1905break;1906case AsmToken::Real:1907// DotOperator: [ebx].01908UpdateLocLex = false;1909if (ParseIntelDotOperator(SM, End))1910return true;1911break;1912case AsmToken::Dot:1913if (!Parser.isParsingMasm()) {1914if ((Done = SM.isValidEndState()))1915break;1916return Error(Tok.getLoc(), "unknown token in expression");1917}1918// MASM allows spaces around the dot operator (e.g., "var . x")1919Lex();1920UpdateLocLex = false;1921if (ParseIntelDotOperator(SM, End))1922return true;1923break;1924case AsmToken::Dollar:1925if (!Parser.isParsingMasm()) {1926if ((Done = SM.isValidEndState()))1927break;1928return Error(Tok.getLoc(), "unknown token in expression");1929}1930[[fallthrough]];1931case AsmToken::String: {1932if (Parser.isParsingMasm()) {1933// MASM parsers handle strings in expressions as constants.1934SMLoc ValueLoc = Tok.getLoc();1935int64_t Res;1936const MCExpr *Val;1937if (Parser.parsePrimaryExpr(Val, End, nullptr))1938return true;1939UpdateLocLex = false;1940if (!Val->evaluateAsAbsolute(Res, getStreamer().getAssemblerPtr()))1941return Error(ValueLoc, "expected absolute value");1942if (SM.onInteger(Res, ErrMsg))1943return Error(ValueLoc, ErrMsg);1944break;1945}1946[[fallthrough]];1947}1948case AsmToken::At:1949case AsmToken::Identifier: {1950SMLoc IdentLoc = Tok.getLoc();1951StringRef Identifier = Tok.getString();1952UpdateLocLex = false;1953if (Parser.isParsingMasm()) {1954size_t DotOffset = Identifier.find_first_of('.');1955if (DotOffset != StringRef::npos) {1956consumeToken();1957StringRef LHS = Identifier.slice(0, DotOffset);1958StringRef Dot = Identifier.slice(DotOffset, DotOffset + 1);1959StringRef RHS = Identifier.slice(DotOffset + 1, StringRef::npos);1960if (!RHS.empty()) {1961getLexer().UnLex(AsmToken(AsmToken::Identifier, RHS));1962}1963getLexer().UnLex(AsmToken(AsmToken::Dot, Dot));1964if (!LHS.empty()) {1965getLexer().UnLex(AsmToken(AsmToken::Identifier, LHS));1966}1967break;1968}1969}1970// (MASM only) <TYPE> PTR operator1971if (Parser.isParsingMasm()) {1972const AsmToken &NextTok = getLexer().peekTok();1973if (NextTok.is(AsmToken::Identifier) &&1974NextTok.getIdentifier().equals_insensitive("ptr")) {1975AsmTypeInfo Info;1976if (Parser.lookUpType(Identifier, Info))1977return Error(Tok.getLoc(), "unknown type");1978SM.onCast(Info);1979// Eat type and PTR.1980consumeToken();1981End = consumeToken();1982break;1983}1984}1985// Register, or (MASM only) <register>.<field>1986MCRegister Reg;1987if (Tok.is(AsmToken::Identifier)) {1988if (!ParseRegister(Reg, IdentLoc, End, /*RestoreOnFailure=*/true)) {1989if (SM.onRegister(Reg, ErrMsg))1990return Error(IdentLoc, ErrMsg);1991break;1992}1993if (Parser.isParsingMasm()) {1994const std::pair<StringRef, StringRef> IDField =1995Tok.getString().split('.');1996const StringRef ID = IDField.first, Field = IDField.second;1997SMLoc IDEndLoc = SMLoc::getFromPointer(ID.data() + ID.size());1998if (!Field.empty() &&1999!MatchRegisterByName(Reg, ID, IdentLoc, IDEndLoc)) {2000if (SM.onRegister(Reg, ErrMsg))2001return Error(IdentLoc, ErrMsg);20022003AsmFieldInfo Info;2004SMLoc FieldStartLoc = SMLoc::getFromPointer(Field.data());2005if (Parser.lookUpField(Field, Info))2006return Error(FieldStartLoc, "unknown offset");2007else if (SM.onPlus(ErrMsg))2008return Error(getTok().getLoc(), ErrMsg);2009else if (SM.onInteger(Info.Offset, ErrMsg))2010return Error(IdentLoc, ErrMsg);2011SM.setTypeInfo(Info.Type);20122013End = consumeToken();2014break;2015}2016}2017}2018// Operator synonymous ("not", "or" etc.)2019bool ParseError = false;2020if (ParseIntelNamedOperator(Identifier, SM, ParseError, End)) {2021if (ParseError)2022return true;2023break;2024}2025if (Parser.isParsingMasm() &&2026ParseMasmNamedOperator(Identifier, SM, ParseError, End)) {2027if (ParseError)2028return true;2029break;2030}2031// Symbol reference, when parsing assembly content2032InlineAsmIdentifierInfo Info;2033AsmFieldInfo FieldInfo;2034const MCExpr *Val;2035if (isParsingMSInlineAsm() || Parser.isParsingMasm()) {2036// MS Dot Operator expression2037if (Identifier.count('.') &&2038(PrevTK == AsmToken::RBrac || PrevTK == AsmToken::RParen)) {2039if (ParseIntelDotOperator(SM, End))2040return true;2041break;2042}2043}2044if (isParsingMSInlineAsm()) {2045// MS InlineAsm operators (TYPE/LENGTH/SIZE)2046if (unsigned OpKind = IdentifyIntelInlineAsmOperator(Identifier)) {2047if (int64_t Val = ParseIntelInlineAsmOperator(OpKind)) {2048if (SM.onInteger(Val, ErrMsg))2049return Error(IdentLoc, ErrMsg);2050} else {2051return true;2052}2053break;2054}2055// MS InlineAsm identifier2056// Call parseIdentifier() to combine @ with the identifier behind it.2057if (TK == AsmToken::At && Parser.parseIdentifier(Identifier))2058return Error(IdentLoc, "expected identifier");2059if (ParseIntelInlineAsmIdentifier(Val, Identifier, Info, false, End))2060return true;2061else if (SM.onIdentifierExpr(Val, Identifier, Info, FieldInfo.Type,2062true, ErrMsg))2063return Error(IdentLoc, ErrMsg);2064break;2065}2066if (Parser.isParsingMasm()) {2067if (unsigned OpKind = IdentifyMasmOperator(Identifier)) {2068int64_t Val;2069if (ParseMasmOperator(OpKind, Val))2070return true;2071if (SM.onInteger(Val, ErrMsg))2072return Error(IdentLoc, ErrMsg);2073break;2074}2075if (!getParser().lookUpType(Identifier, FieldInfo.Type)) {2076// Field offset immediate; <TYPE>.<field specification>2077Lex(); // eat type2078bool EndDot = parseOptionalToken(AsmToken::Dot);2079while (EndDot || (getTok().is(AsmToken::Identifier) &&2080getTok().getString().starts_with("."))) {2081getParser().parseIdentifier(Identifier);2082if (!EndDot)2083Identifier.consume_front(".");2084EndDot = Identifier.consume_back(".");2085if (getParser().lookUpField(FieldInfo.Type.Name, Identifier,2086FieldInfo)) {2087SMLoc IDEnd =2088SMLoc::getFromPointer(Identifier.data() + Identifier.size());2089return Error(IdentLoc, "Unable to lookup field reference!",2090SMRange(IdentLoc, IDEnd));2091}2092if (!EndDot)2093EndDot = parseOptionalToken(AsmToken::Dot);2094}2095if (SM.onInteger(FieldInfo.Offset, ErrMsg))2096return Error(IdentLoc, ErrMsg);2097break;2098}2099}2100if (getParser().parsePrimaryExpr(Val, End, &FieldInfo.Type)) {2101return Error(Tok.getLoc(), "Unexpected identifier!");2102} else if (SM.onIdentifierExpr(Val, Identifier, Info, FieldInfo.Type,2103false, ErrMsg)) {2104return Error(IdentLoc, ErrMsg);2105}2106break;2107}2108case AsmToken::Integer: {2109// Look for 'b' or 'f' following an Integer as a directional label2110SMLoc Loc = getTok().getLoc();2111int64_t IntVal = getTok().getIntVal();2112End = consumeToken();2113UpdateLocLex = false;2114if (getLexer().getKind() == AsmToken::Identifier) {2115StringRef IDVal = getTok().getString();2116if (IDVal == "f" || IDVal == "b") {2117MCSymbol *Sym =2118getContext().getDirectionalLocalSymbol(IntVal, IDVal == "b");2119MCSymbolRefExpr::VariantKind Variant = MCSymbolRefExpr::VK_None;2120const MCExpr *Val =2121MCSymbolRefExpr::create(Sym, Variant, getContext());2122if (IDVal == "b" && Sym->isUndefined())2123return Error(Loc, "invalid reference to undefined symbol");2124StringRef Identifier = Sym->getName();2125InlineAsmIdentifierInfo Info;2126AsmTypeInfo Type;2127if (SM.onIdentifierExpr(Val, Identifier, Info, Type,2128isParsingMSInlineAsm(), ErrMsg))2129return Error(Loc, ErrMsg);2130End = consumeToken();2131} else {2132if (SM.onInteger(IntVal, ErrMsg))2133return Error(Loc, ErrMsg);2134}2135} else {2136if (SM.onInteger(IntVal, ErrMsg))2137return Error(Loc, ErrMsg);2138}2139break;2140}2141case AsmToken::Plus:2142if (SM.onPlus(ErrMsg))2143return Error(getTok().getLoc(), ErrMsg);2144break;2145case AsmToken::Minus:2146if (SM.onMinus(ErrMsg))2147return Error(getTok().getLoc(), ErrMsg);2148break;2149case AsmToken::Tilde: SM.onNot(); break;2150case AsmToken::Star: SM.onStar(); break;2151case AsmToken::Slash: SM.onDivide(); break;2152case AsmToken::Percent: SM.onMod(); break;2153case AsmToken::Pipe: SM.onOr(); break;2154case AsmToken::Caret: SM.onXor(); break;2155case AsmToken::Amp: SM.onAnd(); break;2156case AsmToken::LessLess:2157SM.onLShift(); break;2158case AsmToken::GreaterGreater:2159SM.onRShift(); break;2160case AsmToken::LBrac:2161if (SM.onLBrac())2162return Error(Tok.getLoc(), "unexpected bracket encountered");2163tryParseOperandIdx(PrevTK, SM);2164break;2165case AsmToken::RBrac:2166if (SM.onRBrac(ErrMsg)) {2167return Error(Tok.getLoc(), ErrMsg);2168}2169break;2170case AsmToken::LParen: SM.onLParen(); break;2171case AsmToken::RParen: SM.onRParen(); break;2172}2173if (SM.hadError())2174return Error(Tok.getLoc(), "unknown token in expression");21752176if (!Done && UpdateLocLex)2177End = consumeToken();21782179PrevTK = TK;2180}2181return false;2182}21832184void X86AsmParser::RewriteIntelExpression(IntelExprStateMachine &SM,2185SMLoc Start, SMLoc End) {2186SMLoc Loc = Start;2187unsigned ExprLen = End.getPointer() - Start.getPointer();2188// Skip everything before a symbol displacement (if we have one)2189if (SM.getSym() && !SM.isOffsetOperator()) {2190StringRef SymName = SM.getSymName();2191if (unsigned Len = SymName.data() - Start.getPointer())2192InstInfo->AsmRewrites->emplace_back(AOK_Skip, Start, Len);2193Loc = SMLoc::getFromPointer(SymName.data() + SymName.size());2194ExprLen = End.getPointer() - (SymName.data() + SymName.size());2195// If we have only a symbol than there's no need for complex rewrite,2196// simply skip everything after it2197if (!(SM.getBaseReg() || SM.getIndexReg() || SM.getImm())) {2198if (ExprLen)2199InstInfo->AsmRewrites->emplace_back(AOK_Skip, Loc, ExprLen);2200return;2201}2202}2203// Build an Intel Expression rewrite2204StringRef BaseRegStr;2205StringRef IndexRegStr;2206StringRef OffsetNameStr;2207if (SM.getBaseReg())2208BaseRegStr = X86IntelInstPrinter::getRegisterName(SM.getBaseReg());2209if (SM.getIndexReg())2210IndexRegStr = X86IntelInstPrinter::getRegisterName(SM.getIndexReg());2211if (SM.isOffsetOperator())2212OffsetNameStr = SM.getSymName();2213// Emit it2214IntelExpr Expr(BaseRegStr, IndexRegStr, SM.getScale(), OffsetNameStr,2215SM.getImm(), SM.isMemExpr());2216InstInfo->AsmRewrites->emplace_back(Loc, ExprLen, Expr);2217}22182219// Inline assembly may use variable names with namespace alias qualifiers.2220bool X86AsmParser::ParseIntelInlineAsmIdentifier(2221const MCExpr *&Val, StringRef &Identifier, InlineAsmIdentifierInfo &Info,2222bool IsUnevaluatedOperand, SMLoc &End, bool IsParsingOffsetOperator) {2223MCAsmParser &Parser = getParser();2224assert(isParsingMSInlineAsm() && "Expected to be parsing inline assembly.");2225Val = nullptr;22262227StringRef LineBuf(Identifier.data());2228SemaCallback->LookupInlineAsmIdentifier(LineBuf, Info, IsUnevaluatedOperand);22292230const AsmToken &Tok = Parser.getTok();2231SMLoc Loc = Tok.getLoc();22322233// Advance the token stream until the end of the current token is2234// after the end of what the frontend claimed.2235const char *EndPtr = Tok.getLoc().getPointer() + LineBuf.size();2236do {2237End = Tok.getEndLoc();2238getLexer().Lex();2239} while (End.getPointer() < EndPtr);2240Identifier = LineBuf;22412242// The frontend should end parsing on an assembler token boundary, unless it2243// failed parsing.2244assert((End.getPointer() == EndPtr ||2245Info.isKind(InlineAsmIdentifierInfo::IK_Invalid)) &&2246"frontend claimed part of a token?");22472248// If the identifier lookup was unsuccessful, assume that we are dealing with2249// a label.2250if (Info.isKind(InlineAsmIdentifierInfo::IK_Invalid)) {2251StringRef InternalName =2252SemaCallback->LookupInlineAsmLabel(Identifier, getSourceManager(),2253Loc, false);2254assert(InternalName.size() && "We should have an internal name here.");2255// Push a rewrite for replacing the identifier name with the internal name,2256// unless we are parsing the operand of an offset operator2257if (!IsParsingOffsetOperator)2258InstInfo->AsmRewrites->emplace_back(AOK_Label, Loc, Identifier.size(),2259InternalName);2260else2261Identifier = InternalName;2262} else if (Info.isKind(InlineAsmIdentifierInfo::IK_EnumVal))2263return false;2264// Create the symbol reference.2265MCSymbol *Sym = getContext().getOrCreateSymbol(Identifier);2266MCSymbolRefExpr::VariantKind Variant = MCSymbolRefExpr::VK_None;2267Val = MCSymbolRefExpr::create(Sym, Variant, getParser().getContext());2268return false;2269}22702271//ParseRoundingModeOp - Parse AVX-512 rounding mode operand2272bool X86AsmParser::ParseRoundingModeOp(SMLoc Start, OperandVector &Operands) {2273MCAsmParser &Parser = getParser();2274const AsmToken &Tok = Parser.getTok();2275// Eat "{" and mark the current place.2276const SMLoc consumedToken = consumeToken();2277if (Tok.isNot(AsmToken::Identifier))2278return Error(Tok.getLoc(), "Expected an identifier after {");2279if (Tok.getIdentifier().starts_with("r")) {2280int rndMode = StringSwitch<int>(Tok.getIdentifier())2281.Case("rn", X86::STATIC_ROUNDING::TO_NEAREST_INT)2282.Case("rd", X86::STATIC_ROUNDING::TO_NEG_INF)2283.Case("ru", X86::STATIC_ROUNDING::TO_POS_INF)2284.Case("rz", X86::STATIC_ROUNDING::TO_ZERO)2285.Default(-1);2286if (-1 == rndMode)2287return Error(Tok.getLoc(), "Invalid rounding mode.");2288Parser.Lex(); // Eat "r*" of r*-sae2289if (!getLexer().is(AsmToken::Minus))2290return Error(Tok.getLoc(), "Expected - at this point");2291Parser.Lex(); // Eat "-"2292Parser.Lex(); // Eat the sae2293if (!getLexer().is(AsmToken::RCurly))2294return Error(Tok.getLoc(), "Expected } at this point");2295SMLoc End = Tok.getEndLoc();2296Parser.Lex(); // Eat "}"2297const MCExpr *RndModeOp =2298MCConstantExpr::create(rndMode, Parser.getContext());2299Operands.push_back(X86Operand::CreateImm(RndModeOp, Start, End));2300return false;2301}2302if (Tok.getIdentifier() == "sae") {2303Parser.Lex(); // Eat the sae2304if (!getLexer().is(AsmToken::RCurly))2305return Error(Tok.getLoc(), "Expected } at this point");2306Parser.Lex(); // Eat "}"2307Operands.push_back(X86Operand::CreateToken("{sae}", consumedToken));2308return false;2309}2310return Error(Tok.getLoc(), "unknown token in expression");2311}23122313/// Parse condtional flags for CCMP/CTEST, e.g {dfv=of,sf,zf,cf} right after2314/// mnemonic.2315bool X86AsmParser::parseCFlagsOp(OperandVector &Operands) {2316MCAsmParser &Parser = getParser();2317AsmToken Tok = Parser.getTok();2318const SMLoc Start = Tok.getLoc();2319if (!Tok.is(AsmToken::LCurly))2320return Error(Tok.getLoc(), "Expected { at this point");2321Parser.Lex(); // Eat "{"2322Tok = Parser.getTok();2323if (Tok.getIdentifier().lower() != "dfv")2324return Error(Tok.getLoc(), "Expected dfv at this point");2325Parser.Lex(); // Eat "dfv"2326Tok = Parser.getTok();2327if (!Tok.is(AsmToken::Equal))2328return Error(Tok.getLoc(), "Expected = at this point");2329Parser.Lex(); // Eat "="23302331Tok = Parser.getTok();2332SMLoc End;2333if (Tok.is(AsmToken::RCurly)) {2334End = Tok.getEndLoc();2335Operands.push_back(X86Operand::CreateImm(2336MCConstantExpr::create(0, Parser.getContext()), Start, End));2337Parser.Lex(); // Eat "}"2338return false;2339}2340unsigned CFlags = 0;2341for (unsigned I = 0; I < 4; ++I) {2342Tok = Parser.getTok();2343unsigned CFlag = StringSwitch<unsigned>(Tok.getIdentifier().lower())2344.Case("of", 0x8)2345.Case("sf", 0x4)2346.Case("zf", 0x2)2347.Case("cf", 0x1)2348.Default(~0U);2349if (CFlag == ~0U)2350return Error(Tok.getLoc(), "Invalid conditional flags");23512352if (CFlags & CFlag)2353return Error(Tok.getLoc(), "Duplicated conditional flag");2354CFlags |= CFlag;23552356Parser.Lex(); // Eat one conditional flag2357Tok = Parser.getTok();2358if (Tok.is(AsmToken::RCurly)) {2359End = Tok.getEndLoc();2360Operands.push_back(X86Operand::CreateImm(2361MCConstantExpr::create(CFlags, Parser.getContext()), Start, End));2362Parser.Lex(); // Eat "}"2363return false;2364} else if (I == 3) {2365return Error(Tok.getLoc(), "Expected } at this point");2366} else if (Tok.isNot(AsmToken::Comma)) {2367return Error(Tok.getLoc(), "Expected } or , at this point");2368}2369Parser.Lex(); // Eat ","2370}2371llvm_unreachable("Unexpected control flow");2372}23732374/// Parse the '.' operator.2375bool X86AsmParser::ParseIntelDotOperator(IntelExprStateMachine &SM,2376SMLoc &End) {2377const AsmToken &Tok = getTok();2378AsmFieldInfo Info;23792380// Drop the optional '.'.2381StringRef DotDispStr = Tok.getString();2382DotDispStr.consume_front(".");2383StringRef TrailingDot;23842385// .Imm gets lexed as a real.2386if (Tok.is(AsmToken::Real)) {2387APInt DotDisp;2388if (DotDispStr.getAsInteger(10, DotDisp))2389return Error(Tok.getLoc(), "Unexpected offset");2390Info.Offset = DotDisp.getZExtValue();2391} else if ((isParsingMSInlineAsm() || getParser().isParsingMasm()) &&2392Tok.is(AsmToken::Identifier)) {2393if (DotDispStr.ends_with(".")) {2394TrailingDot = DotDispStr.substr(DotDispStr.size() - 1);2395DotDispStr = DotDispStr.drop_back(1);2396}2397const std::pair<StringRef, StringRef> BaseMember = DotDispStr.split('.');2398const StringRef Base = BaseMember.first, Member = BaseMember.second;2399if (getParser().lookUpField(SM.getType(), DotDispStr, Info) &&2400getParser().lookUpField(SM.getSymName(), DotDispStr, Info) &&2401getParser().lookUpField(DotDispStr, Info) &&2402(!SemaCallback ||2403SemaCallback->LookupInlineAsmField(Base, Member, Info.Offset)))2404return Error(Tok.getLoc(), "Unable to lookup field reference!");2405} else {2406return Error(Tok.getLoc(), "Unexpected token type!");2407}24082409// Eat the DotExpression and update End2410End = SMLoc::getFromPointer(DotDispStr.data());2411const char *DotExprEndLoc = DotDispStr.data() + DotDispStr.size();2412while (Tok.getLoc().getPointer() < DotExprEndLoc)2413Lex();2414if (!TrailingDot.empty())2415getLexer().UnLex(AsmToken(AsmToken::Dot, TrailingDot));2416SM.addImm(Info.Offset);2417SM.setTypeInfo(Info.Type);2418return false;2419}24202421/// Parse the 'offset' operator.2422/// This operator is used to specify the location of a given operand2423bool X86AsmParser::ParseIntelOffsetOperator(const MCExpr *&Val, StringRef &ID,2424InlineAsmIdentifierInfo &Info,2425SMLoc &End) {2426// Eat offset, mark start of identifier.2427SMLoc Start = Lex().getLoc();2428ID = getTok().getString();2429if (!isParsingMSInlineAsm()) {2430if ((getTok().isNot(AsmToken::Identifier) &&2431getTok().isNot(AsmToken::String)) ||2432getParser().parsePrimaryExpr(Val, End, nullptr))2433return Error(Start, "unexpected token!");2434} else if (ParseIntelInlineAsmIdentifier(Val, ID, Info, false, End, true)) {2435return Error(Start, "unable to lookup expression");2436} else if (Info.isKind(InlineAsmIdentifierInfo::IK_EnumVal)) {2437return Error(Start, "offset operator cannot yet handle constants");2438}2439return false;2440}24412442// Query a candidate string for being an Intel assembly operator2443// Report back its kind, or IOK_INVALID if does not evaluated as a known one2444unsigned X86AsmParser::IdentifyIntelInlineAsmOperator(StringRef Name) {2445return StringSwitch<unsigned>(Name)2446.Cases("TYPE","type",IOK_TYPE)2447.Cases("SIZE","size",IOK_SIZE)2448.Cases("LENGTH","length",IOK_LENGTH)2449.Default(IOK_INVALID);2450}24512452/// Parse the 'LENGTH', 'TYPE' and 'SIZE' operators. The LENGTH operator2453/// returns the number of elements in an array. It returns the value 1 for2454/// non-array variables. The SIZE operator returns the size of a C or C++2455/// variable. A variable's size is the product of its LENGTH and TYPE. The2456/// TYPE operator returns the size of a C or C++ type or variable. If the2457/// variable is an array, TYPE returns the size of a single element.2458unsigned X86AsmParser::ParseIntelInlineAsmOperator(unsigned OpKind) {2459MCAsmParser &Parser = getParser();2460const AsmToken &Tok = Parser.getTok();2461Parser.Lex(); // Eat operator.24622463const MCExpr *Val = nullptr;2464InlineAsmIdentifierInfo Info;2465SMLoc Start = Tok.getLoc(), End;2466StringRef Identifier = Tok.getString();2467if (ParseIntelInlineAsmIdentifier(Val, Identifier, Info,2468/*IsUnevaluatedOperand=*/true, End))2469return 0;24702471if (!Info.isKind(InlineAsmIdentifierInfo::IK_Var)) {2472Error(Start, "unable to lookup expression");2473return 0;2474}24752476unsigned CVal = 0;2477switch(OpKind) {2478default: llvm_unreachable("Unexpected operand kind!");2479case IOK_LENGTH: CVal = Info.Var.Length; break;2480case IOK_SIZE: CVal = Info.Var.Size; break;2481case IOK_TYPE: CVal = Info.Var.Type; break;2482}24832484return CVal;2485}24862487// Query a candidate string for being an Intel assembly operator2488// Report back its kind, or IOK_INVALID if does not evaluated as a known one2489unsigned X86AsmParser::IdentifyMasmOperator(StringRef Name) {2490return StringSwitch<unsigned>(Name.lower())2491.Case("type", MOK_TYPE)2492.Cases("size", "sizeof", MOK_SIZEOF)2493.Cases("length", "lengthof", MOK_LENGTHOF)2494.Default(MOK_INVALID);2495}24962497/// Parse the 'LENGTHOF', 'SIZEOF', and 'TYPE' operators. The LENGTHOF operator2498/// returns the number of elements in an array. It returns the value 1 for2499/// non-array variables. The SIZEOF operator returns the size of a type or2500/// variable in bytes. A variable's size is the product of its LENGTH and TYPE.2501/// The TYPE operator returns the size of a variable. If the variable is an2502/// array, TYPE returns the size of a single element.2503bool X86AsmParser::ParseMasmOperator(unsigned OpKind, int64_t &Val) {2504MCAsmParser &Parser = getParser();2505SMLoc OpLoc = Parser.getTok().getLoc();2506Parser.Lex(); // Eat operator.25072508Val = 0;2509if (OpKind == MOK_SIZEOF || OpKind == MOK_TYPE) {2510// Check for SIZEOF(<type>) and TYPE(<type>).2511bool InParens = Parser.getTok().is(AsmToken::LParen);2512const AsmToken &IDTok = InParens ? getLexer().peekTok() : Parser.getTok();2513AsmTypeInfo Type;2514if (IDTok.is(AsmToken::Identifier) &&2515!Parser.lookUpType(IDTok.getIdentifier(), Type)) {2516Val = Type.Size;25172518// Eat tokens.2519if (InParens)2520parseToken(AsmToken::LParen);2521parseToken(AsmToken::Identifier);2522if (InParens)2523parseToken(AsmToken::RParen);2524}2525}25262527if (!Val) {2528IntelExprStateMachine SM;2529SMLoc End, Start = Parser.getTok().getLoc();2530if (ParseIntelExpression(SM, End))2531return true;25322533switch (OpKind) {2534default:2535llvm_unreachable("Unexpected operand kind!");2536case MOK_SIZEOF:2537Val = SM.getSize();2538break;2539case MOK_LENGTHOF:2540Val = SM.getLength();2541break;2542case MOK_TYPE:2543Val = SM.getElementSize();2544break;2545}25462547if (!Val)2548return Error(OpLoc, "expression has unknown type", SMRange(Start, End));2549}25502551return false;2552}25532554bool X86AsmParser::ParseIntelMemoryOperandSize(unsigned &Size) {2555Size = StringSwitch<unsigned>(getTok().getString())2556.Cases("BYTE", "byte", 8)2557.Cases("WORD", "word", 16)2558.Cases("DWORD", "dword", 32)2559.Cases("FLOAT", "float", 32)2560.Cases("LONG", "long", 32)2561.Cases("FWORD", "fword", 48)2562.Cases("DOUBLE", "double", 64)2563.Cases("QWORD", "qword", 64)2564.Cases("MMWORD","mmword", 64)2565.Cases("XWORD", "xword", 80)2566.Cases("TBYTE", "tbyte", 80)2567.Cases("XMMWORD", "xmmword", 128)2568.Cases("YMMWORD", "ymmword", 256)2569.Cases("ZMMWORD", "zmmword", 512)2570.Default(0);2571if (Size) {2572const AsmToken &Tok = Lex(); // Eat operand size (e.g., byte, word).2573if (!(Tok.getString() == "PTR" || Tok.getString() == "ptr"))2574return Error(Tok.getLoc(), "Expected 'PTR' or 'ptr' token!");2575Lex(); // Eat ptr.2576}2577return false;2578}25792580bool X86AsmParser::parseIntelOperand(OperandVector &Operands, StringRef Name) {2581MCAsmParser &Parser = getParser();2582const AsmToken &Tok = Parser.getTok();2583SMLoc Start, End;25842585// Parse optional Size directive.2586unsigned Size;2587if (ParseIntelMemoryOperandSize(Size))2588return true;2589bool PtrInOperand = bool(Size);25902591Start = Tok.getLoc();25922593// Rounding mode operand.2594if (getLexer().is(AsmToken::LCurly))2595return ParseRoundingModeOp(Start, Operands);25962597// Register operand.2598MCRegister RegNo;2599if (Tok.is(AsmToken::Identifier) && !parseRegister(RegNo, Start, End)) {2600if (RegNo == X86::RIP)2601return Error(Start, "rip can only be used as a base register");2602// A Register followed by ':' is considered a segment override2603if (Tok.isNot(AsmToken::Colon)) {2604if (PtrInOperand)2605return Error(Start, "expected memory operand after 'ptr', "2606"found register operand instead");2607Operands.push_back(X86Operand::CreateReg(RegNo, Start, End));2608return false;2609}2610// An alleged segment override. check if we have a valid segment register2611if (!X86MCRegisterClasses[X86::SEGMENT_REGRegClassID].contains(RegNo))2612return Error(Start, "invalid segment register");2613// Eat ':' and update Start location2614Start = Lex().getLoc();2615}26162617// Immediates and Memory2618IntelExprStateMachine SM;2619if (ParseIntelExpression(SM, End))2620return true;26212622if (isParsingMSInlineAsm())2623RewriteIntelExpression(SM, Start, Tok.getLoc());26242625int64_t Imm = SM.getImm();2626const MCExpr *Disp = SM.getSym();2627const MCExpr *ImmDisp = MCConstantExpr::create(Imm, getContext());2628if (Disp && Imm)2629Disp = MCBinaryExpr::createAdd(Disp, ImmDisp, getContext());2630if (!Disp)2631Disp = ImmDisp;26322633// RegNo != 0 specifies a valid segment register,2634// and we are parsing a segment override2635if (!SM.isMemExpr() && !RegNo) {2636if (isParsingMSInlineAsm() && SM.isOffsetOperator()) {2637const InlineAsmIdentifierInfo &Info = SM.getIdentifierInfo();2638if (Info.isKind(InlineAsmIdentifierInfo::IK_Var)) {2639// Disp includes the address of a variable; make sure this is recorded2640// for later handling.2641Operands.push_back(X86Operand::CreateImm(Disp, Start, End,2642SM.getSymName(), Info.Var.Decl,2643Info.Var.IsGlobalLV));2644return false;2645}2646}26472648Operands.push_back(X86Operand::CreateImm(Disp, Start, End));2649return false;2650}26512652StringRef ErrMsg;2653unsigned BaseReg = SM.getBaseReg();2654unsigned IndexReg = SM.getIndexReg();2655if (IndexReg && BaseReg == X86::RIP)2656BaseReg = 0;2657unsigned Scale = SM.getScale();2658if (!PtrInOperand)2659Size = SM.getElementSize() << 3;26602661if (Scale == 0 && BaseReg != X86::ESP && BaseReg != X86::RSP &&2662(IndexReg == X86::ESP || IndexReg == X86::RSP))2663std::swap(BaseReg, IndexReg);26642665// If BaseReg is a vector register and IndexReg is not, swap them unless2666// Scale was specified in which case it would be an error.2667if (Scale == 0 &&2668!(X86MCRegisterClasses[X86::VR128XRegClassID].contains(IndexReg) ||2669X86MCRegisterClasses[X86::VR256XRegClassID].contains(IndexReg) ||2670X86MCRegisterClasses[X86::VR512RegClassID].contains(IndexReg)) &&2671(X86MCRegisterClasses[X86::VR128XRegClassID].contains(BaseReg) ||2672X86MCRegisterClasses[X86::VR256XRegClassID].contains(BaseReg) ||2673X86MCRegisterClasses[X86::VR512RegClassID].contains(BaseReg)))2674std::swap(BaseReg, IndexReg);26752676if (Scale != 0 &&2677X86MCRegisterClasses[X86::GR16RegClassID].contains(IndexReg))2678return Error(Start, "16-bit addresses cannot have a scale");26792680// If there was no explicit scale specified, change it to 1.2681if (Scale == 0)2682Scale = 1;26832684// If this is a 16-bit addressing mode with the base and index in the wrong2685// order, swap them so CheckBaseRegAndIndexRegAndScale doesn't fail. It is2686// shared with att syntax where order matters.2687if ((BaseReg == X86::SI || BaseReg == X86::DI) &&2688(IndexReg == X86::BX || IndexReg == X86::BP))2689std::swap(BaseReg, IndexReg);26902691if ((BaseReg || IndexReg) &&2692CheckBaseRegAndIndexRegAndScale(BaseReg, IndexReg, Scale, is64BitMode(),2693ErrMsg))2694return Error(Start, ErrMsg);2695bool IsUnconditionalBranch =2696Name.equals_insensitive("jmp") || Name.equals_insensitive("call");2697if (isParsingMSInlineAsm())2698return CreateMemForMSInlineAsm(RegNo, Disp, BaseReg, IndexReg, Scale,2699IsUnconditionalBranch && is64BitMode(),2700Start, End, Size, SM.getSymName(),2701SM.getIdentifierInfo(), Operands);27022703// When parsing x64 MS-style assembly, all non-absolute references to a named2704// variable default to RIP-relative.2705unsigned DefaultBaseReg = X86::NoRegister;2706bool MaybeDirectBranchDest = true;27072708if (Parser.isParsingMasm()) {2709if (is64BitMode() &&2710((PtrInOperand && !IndexReg) || SM.getElementSize() > 0)) {2711DefaultBaseReg = X86::RIP;2712}2713if (IsUnconditionalBranch) {2714if (PtrInOperand) {2715MaybeDirectBranchDest = false;2716if (is64BitMode())2717DefaultBaseReg = X86::RIP;2718} else if (!BaseReg && !IndexReg && Disp &&2719Disp->getKind() == MCExpr::SymbolRef) {2720if (is64BitMode()) {2721if (SM.getSize() == 8) {2722MaybeDirectBranchDest = false;2723DefaultBaseReg = X86::RIP;2724}2725} else {2726if (SM.getSize() == 4 || SM.getSize() == 2)2727MaybeDirectBranchDest = false;2728}2729}2730}2731} else if (IsUnconditionalBranch) {2732// Treat `call [offset fn_ref]` (or `jmp`) syntax as an error.2733if (!PtrInOperand && SM.isOffsetOperator())2734return Error(2735Start, "`OFFSET` operator cannot be used in an unconditional branch");2736if (PtrInOperand || SM.isBracketUsed())2737MaybeDirectBranchDest = false;2738}27392740if ((BaseReg || IndexReg || RegNo || DefaultBaseReg != X86::NoRegister))2741Operands.push_back(X86Operand::CreateMem(2742getPointerWidth(), RegNo, Disp, BaseReg, IndexReg, Scale, Start, End,2743Size, DefaultBaseReg, /*SymName=*/StringRef(), /*OpDecl=*/nullptr,2744/*FrontendSize=*/0, /*UseUpRegs=*/false, MaybeDirectBranchDest));2745else2746Operands.push_back(X86Operand::CreateMem(2747getPointerWidth(), Disp, Start, End, Size, /*SymName=*/StringRef(),2748/*OpDecl=*/nullptr, /*FrontendSize=*/0, /*UseUpRegs=*/false,2749MaybeDirectBranchDest));2750return false;2751}27522753bool X86AsmParser::parseATTOperand(OperandVector &Operands) {2754MCAsmParser &Parser = getParser();2755switch (getLexer().getKind()) {2756case AsmToken::Dollar: {2757// $42 or $ID -> immediate.2758SMLoc Start = Parser.getTok().getLoc(), End;2759Parser.Lex();2760const MCExpr *Val;2761// This is an immediate, so we should not parse a register. Do a precheck2762// for '%' to supercede intra-register parse errors.2763SMLoc L = Parser.getTok().getLoc();2764if (check(getLexer().is(AsmToken::Percent), L,2765"expected immediate expression") ||2766getParser().parseExpression(Val, End) ||2767check(isa<X86MCExpr>(Val), L, "expected immediate expression"))2768return true;2769Operands.push_back(X86Operand::CreateImm(Val, Start, End));2770return false;2771}2772case AsmToken::LCurly: {2773SMLoc Start = Parser.getTok().getLoc();2774return ParseRoundingModeOp(Start, Operands);2775}2776default: {2777// This a memory operand or a register. We have some parsing complications2778// as a '(' may be part of an immediate expression or the addressing mode2779// block. This is complicated by the fact that an assembler-level variable2780// may refer either to a register or an immediate expression.27812782SMLoc Loc = Parser.getTok().getLoc(), EndLoc;2783const MCExpr *Expr = nullptr;2784unsigned Reg = 0;2785if (getLexer().isNot(AsmToken::LParen)) {2786// No '(' so this is either a displacement expression or a register.2787if (Parser.parseExpression(Expr, EndLoc))2788return true;2789if (auto *RE = dyn_cast<X86MCExpr>(Expr)) {2790// Segment Register. Reset Expr and copy value to register.2791Expr = nullptr;2792Reg = RE->getRegNo();27932794// Check the register.2795if (Reg == X86::EIZ || Reg == X86::RIZ)2796return Error(2797Loc, "%eiz and %riz can only be used as index registers",2798SMRange(Loc, EndLoc));2799if (Reg == X86::RIP)2800return Error(Loc, "%rip can only be used as a base register",2801SMRange(Loc, EndLoc));2802// Return register that are not segment prefixes immediately.2803if (!Parser.parseOptionalToken(AsmToken::Colon)) {2804Operands.push_back(X86Operand::CreateReg(Reg, Loc, EndLoc));2805return false;2806}2807if (!X86MCRegisterClasses[X86::SEGMENT_REGRegClassID].contains(Reg))2808return Error(Loc, "invalid segment register");2809// Accept a '*' absolute memory reference after the segment. Place it2810// before the full memory operand.2811if (getLexer().is(AsmToken::Star))2812Operands.push_back(X86Operand::CreateToken("*", consumeToken()));2813}2814}2815// This is a Memory operand.2816return ParseMemOperand(Reg, Expr, Loc, EndLoc, Operands);2817}2818}2819}28202821// X86::COND_INVALID if not a recognized condition code or alternate mnemonic,2822// otherwise the EFLAGS Condition Code enumerator.2823X86::CondCode X86AsmParser::ParseConditionCode(StringRef CC) {2824return StringSwitch<X86::CondCode>(CC)2825.Case("o", X86::COND_O) // Overflow2826.Case("no", X86::COND_NO) // No Overflow2827.Cases("b", "nae", X86::COND_B) // Below/Neither Above nor Equal2828.Cases("ae", "nb", X86::COND_AE) // Above or Equal/Not Below2829.Cases("e", "z", X86::COND_E) // Equal/Zero2830.Cases("ne", "nz", X86::COND_NE) // Not Equal/Not Zero2831.Cases("be", "na", X86::COND_BE) // Below or Equal/Not Above2832.Cases("a", "nbe", X86::COND_A) // Above/Neither Below nor Equal2833.Case("s", X86::COND_S) // Sign2834.Case("ns", X86::COND_NS) // No Sign2835.Cases("p", "pe", X86::COND_P) // Parity/Parity Even2836.Cases("np", "po", X86::COND_NP) // No Parity/Parity Odd2837.Cases("l", "nge", X86::COND_L) // Less/Neither Greater nor Equal2838.Cases("ge", "nl", X86::COND_GE) // Greater or Equal/Not Less2839.Cases("le", "ng", X86::COND_LE) // Less or Equal/Not Greater2840.Cases("g", "nle", X86::COND_G) // Greater/Neither Less nor Equal2841.Default(X86::COND_INVALID);2842}28432844// true on failure, false otherwise2845// If no {z} mark was found - Parser doesn't advance2846bool X86AsmParser::ParseZ(std::unique_ptr<X86Operand> &Z,2847const SMLoc &StartLoc) {2848MCAsmParser &Parser = getParser();2849// Assuming we are just pass the '{' mark, quering the next token2850// Searched for {z}, but none was found. Return false, as no parsing error was2851// encountered2852if (!(getLexer().is(AsmToken::Identifier) &&2853(getLexer().getTok().getIdentifier() == "z")))2854return false;2855Parser.Lex(); // Eat z2856// Query and eat the '}' mark2857if (!getLexer().is(AsmToken::RCurly))2858return Error(getLexer().getLoc(), "Expected } at this point");2859Parser.Lex(); // Eat '}'2860// Assign Z with the {z} mark operand2861Z = X86Operand::CreateToken("{z}", StartLoc);2862return false;2863}28642865// true on failure, false otherwise2866bool X86AsmParser::HandleAVX512Operand(OperandVector &Operands) {2867MCAsmParser &Parser = getParser();2868if (getLexer().is(AsmToken::LCurly)) {2869// Eat "{" and mark the current place.2870const SMLoc consumedToken = consumeToken();2871// Distinguish {1to<NUM>} from {%k<NUM>}.2872if(getLexer().is(AsmToken::Integer)) {2873// Parse memory broadcasting ({1to<NUM>}).2874if (getLexer().getTok().getIntVal() != 1)2875return TokError("Expected 1to<NUM> at this point");2876StringRef Prefix = getLexer().getTok().getString();2877Parser.Lex(); // Eat first token of 1to82878if (!getLexer().is(AsmToken::Identifier))2879return TokError("Expected 1to<NUM> at this point");2880// Recognize only reasonable suffixes.2881SmallVector<char, 5> BroadcastVector;2882StringRef BroadcastString = (Prefix + getLexer().getTok().getIdentifier())2883.toStringRef(BroadcastVector);2884if (!BroadcastString.starts_with("1to"))2885return TokError("Expected 1to<NUM> at this point");2886const char *BroadcastPrimitive =2887StringSwitch<const char *>(BroadcastString)2888.Case("1to2", "{1to2}")2889.Case("1to4", "{1to4}")2890.Case("1to8", "{1to8}")2891.Case("1to16", "{1to16}")2892.Case("1to32", "{1to32}")2893.Default(nullptr);2894if (!BroadcastPrimitive)2895return TokError("Invalid memory broadcast primitive.");2896Parser.Lex(); // Eat trailing token of 1toN2897if (!getLexer().is(AsmToken::RCurly))2898return TokError("Expected } at this point");2899Parser.Lex(); // Eat "}"2900Operands.push_back(X86Operand::CreateToken(BroadcastPrimitive,2901consumedToken));2902// No AVX512 specific primitives can pass2903// after memory broadcasting, so return.2904return false;2905} else {2906// Parse either {k}{z}, {z}{k}, {k} or {z}2907// last one have no meaning, but GCC accepts it2908// Currently, we're just pass a '{' mark2909std::unique_ptr<X86Operand> Z;2910if (ParseZ(Z, consumedToken))2911return true;2912// Reaching here means that parsing of the allegadly '{z}' mark yielded2913// no errors.2914// Query for the need of further parsing for a {%k<NUM>} mark2915if (!Z || getLexer().is(AsmToken::LCurly)) {2916SMLoc StartLoc = Z ? consumeToken() : consumedToken;2917// Parse an op-mask register mark ({%k<NUM>}), which is now to be2918// expected2919MCRegister RegNo;2920SMLoc RegLoc;2921if (!parseRegister(RegNo, RegLoc, StartLoc) &&2922X86MCRegisterClasses[X86::VK1RegClassID].contains(RegNo)) {2923if (RegNo == X86::K0)2924return Error(RegLoc, "Register k0 can't be used as write mask");2925if (!getLexer().is(AsmToken::RCurly))2926return Error(getLexer().getLoc(), "Expected } at this point");2927Operands.push_back(X86Operand::CreateToken("{", StartLoc));2928Operands.push_back(2929X86Operand::CreateReg(RegNo, StartLoc, StartLoc));2930Operands.push_back(X86Operand::CreateToken("}", consumeToken()));2931} else2932return Error(getLexer().getLoc(),2933"Expected an op-mask register at this point");2934// {%k<NUM>} mark is found, inquire for {z}2935if (getLexer().is(AsmToken::LCurly) && !Z) {2936// Have we've found a parsing error, or found no (expected) {z} mark2937// - report an error2938if (ParseZ(Z, consumeToken()) || !Z)2939return Error(getLexer().getLoc(),2940"Expected a {z} mark at this point");29412942}2943// '{z}' on its own is meaningless, hence should be ignored.2944// on the contrary - have it been accompanied by a K register,2945// allow it.2946if (Z)2947Operands.push_back(std::move(Z));2948}2949}2950}2951return false;2952}29532954/// ParseMemOperand: 'seg : disp(basereg, indexreg, scale)'. The '%ds:' prefix2955/// has already been parsed if present. disp may be provided as well.2956bool X86AsmParser::ParseMemOperand(unsigned SegReg, const MCExpr *Disp,2957SMLoc StartLoc, SMLoc EndLoc,2958OperandVector &Operands) {2959MCAsmParser &Parser = getParser();2960SMLoc Loc;2961// Based on the initial passed values, we may be in any of these cases, we are2962// in one of these cases (with current position (*)):29632964// 1. seg : * disp (base-index-scale-expr)2965// 2. seg : *(disp) (base-index-scale-expr)2966// 3. seg : *(base-index-scale-expr)2967// 4. disp *(base-index-scale-expr)2968// 5. *(disp) (base-index-scale-expr)2969// 6. *(base-index-scale-expr)2970// 7. disp *2971// 8. *(disp)29722973// If we do not have an displacement yet, check if we're in cases 4 or 6 by2974// checking if the first object after the parenthesis is a register (or an2975// identifier referring to a register) and parse the displacement or default2976// to 0 as appropriate.2977auto isAtMemOperand = [this]() {2978if (this->getLexer().isNot(AsmToken::LParen))2979return false;2980AsmToken Buf[2];2981StringRef Id;2982auto TokCount = this->getLexer().peekTokens(Buf, true);2983if (TokCount == 0)2984return false;2985switch (Buf[0].getKind()) {2986case AsmToken::Percent:2987case AsmToken::Comma:2988return true;2989// These lower cases are doing a peekIdentifier.2990case AsmToken::At:2991case AsmToken::Dollar:2992if ((TokCount > 1) &&2993(Buf[1].is(AsmToken::Identifier) || Buf[1].is(AsmToken::String)) &&2994(Buf[0].getLoc().getPointer() + 1 == Buf[1].getLoc().getPointer()))2995Id = StringRef(Buf[0].getLoc().getPointer(),2996Buf[1].getIdentifier().size() + 1);2997break;2998case AsmToken::Identifier:2999case AsmToken::String:3000Id = Buf[0].getIdentifier();3001break;3002default:3003return false;3004}3005// We have an ID. Check if it is bound to a register.3006if (!Id.empty()) {3007MCSymbol *Sym = this->getContext().getOrCreateSymbol(Id);3008if (Sym->isVariable()) {3009auto V = Sym->getVariableValue(/*SetUsed*/ false);3010return isa<X86MCExpr>(V);3011}3012}3013return false;3014};30153016if (!Disp) {3017// Parse immediate if we're not at a mem operand yet.3018if (!isAtMemOperand()) {3019if (Parser.parseTokenLoc(Loc) || Parser.parseExpression(Disp, EndLoc))3020return true;3021assert(!isa<X86MCExpr>(Disp) && "Expected non-register here.");3022} else {3023// Disp is implicitly zero if we haven't parsed it yet.3024Disp = MCConstantExpr::create(0, Parser.getContext());3025}3026}30273028// We are now either at the end of the operand or at the '(' at the start of a3029// base-index-scale-expr.30303031if (!parseOptionalToken(AsmToken::LParen)) {3032if (SegReg == 0)3033Operands.push_back(3034X86Operand::CreateMem(getPointerWidth(), Disp, StartLoc, EndLoc));3035else3036Operands.push_back(X86Operand::CreateMem(getPointerWidth(), SegReg, Disp,30370, 0, 1, StartLoc, EndLoc));3038return false;3039}30403041// If we reached here, then eat the '(' and Process3042// the rest of the memory operand.3043unsigned BaseReg = 0, IndexReg = 0, Scale = 1;3044SMLoc BaseLoc = getLexer().getLoc();3045const MCExpr *E;3046StringRef ErrMsg;30473048// Parse BaseReg if one is provided.3049if (getLexer().isNot(AsmToken::Comma) && getLexer().isNot(AsmToken::RParen)) {3050if (Parser.parseExpression(E, EndLoc) ||3051check(!isa<X86MCExpr>(E), BaseLoc, "expected register here"))3052return true;30533054// Check the register.3055BaseReg = cast<X86MCExpr>(E)->getRegNo();3056if (BaseReg == X86::EIZ || BaseReg == X86::RIZ)3057return Error(BaseLoc, "eiz and riz can only be used as index registers",3058SMRange(BaseLoc, EndLoc));3059}30603061if (parseOptionalToken(AsmToken::Comma)) {3062// Following the comma we should have either an index register, or a scale3063// value. We don't support the later form, but we want to parse it3064// correctly.3065//3066// Even though it would be completely consistent to support syntax like3067// "1(%eax,,1)", the assembler doesn't. Use "eiz" or "riz" for this.3068if (getLexer().isNot(AsmToken::RParen)) {3069if (Parser.parseTokenLoc(Loc) || Parser.parseExpression(E, EndLoc))3070return true;30713072if (!isa<X86MCExpr>(E)) {3073// We've parsed an unexpected Scale Value instead of an index3074// register. Interpret it as an absolute.3075int64_t ScaleVal;3076if (!E->evaluateAsAbsolute(ScaleVal, getStreamer().getAssemblerPtr()))3077return Error(Loc, "expected absolute expression");3078if (ScaleVal != 1)3079Warning(Loc, "scale factor without index register is ignored");3080Scale = 1;3081} else { // IndexReg Found.3082IndexReg = cast<X86MCExpr>(E)->getRegNo();30833084if (BaseReg == X86::RIP)3085return Error(Loc,3086"%rip as base register can not have an index register");3087if (IndexReg == X86::RIP)3088return Error(Loc, "%rip is not allowed as an index register");30893090if (parseOptionalToken(AsmToken::Comma)) {3091// Parse the scale amount:3092// ::= ',' [scale-expression]30933094// A scale amount without an index is ignored.3095if (getLexer().isNot(AsmToken::RParen)) {3096int64_t ScaleVal;3097if (Parser.parseTokenLoc(Loc) ||3098Parser.parseAbsoluteExpression(ScaleVal))3099return Error(Loc, "expected scale expression");3100Scale = (unsigned)ScaleVal;3101// Validate the scale amount.3102if (X86MCRegisterClasses[X86::GR16RegClassID].contains(BaseReg) &&3103Scale != 1)3104return Error(Loc, "scale factor in 16-bit address must be 1");3105if (checkScale(Scale, ErrMsg))3106return Error(Loc, ErrMsg);3107}3108}3109}3110}3111}31123113// Ok, we've eaten the memory operand, verify we have a ')' and eat it too.3114if (parseToken(AsmToken::RParen, "unexpected token in memory operand"))3115return true;31163117// This is to support otherwise illegal operand (%dx) found in various3118// unofficial manuals examples (e.g. "out[s]?[bwl]? %al, (%dx)") and must now3119// be supported. Mark such DX variants separately fix only in special cases.3120if (BaseReg == X86::DX && IndexReg == 0 && Scale == 1 && SegReg == 0 &&3121isa<MCConstantExpr>(Disp) &&3122cast<MCConstantExpr>(Disp)->getValue() == 0) {3123Operands.push_back(X86Operand::CreateDXReg(BaseLoc, BaseLoc));3124return false;3125}31263127if (CheckBaseRegAndIndexRegAndScale(BaseReg, IndexReg, Scale, is64BitMode(),3128ErrMsg))3129return Error(BaseLoc, ErrMsg);31303131// If the displacement is a constant, check overflows. For 64-bit addressing,3132// gas requires isInt<32> and otherwise reports an error. For others, gas3133// reports a warning and allows a wider range. E.g. gas allows3134// [-0xffffffff,0xffffffff] for 32-bit addressing (e.g. Linux kernel uses3135// `leal -__PAGE_OFFSET(%ecx),%esp` where __PAGE_OFFSET is 0xc0000000).3136if (BaseReg || IndexReg) {3137if (auto CE = dyn_cast<MCConstantExpr>(Disp)) {3138auto Imm = CE->getValue();3139bool Is64 = X86MCRegisterClasses[X86::GR64RegClassID].contains(BaseReg) ||3140X86MCRegisterClasses[X86::GR64RegClassID].contains(IndexReg);3141bool Is16 = X86MCRegisterClasses[X86::GR16RegClassID].contains(BaseReg);3142if (Is64) {3143if (!isInt<32>(Imm))3144return Error(BaseLoc, "displacement " + Twine(Imm) +3145" is not within [-2147483648, 2147483647]");3146} else if (!Is16) {3147if (!isUInt<32>(Imm < 0 ? -uint64_t(Imm) : uint64_t(Imm))) {3148Warning(BaseLoc, "displacement " + Twine(Imm) +3149" shortened to 32-bit signed " +3150Twine(static_cast<int32_t>(Imm)));3151}3152} else if (!isUInt<16>(Imm < 0 ? -uint64_t(Imm) : uint64_t(Imm))) {3153Warning(BaseLoc, "displacement " + Twine(Imm) +3154" shortened to 16-bit signed " +3155Twine(static_cast<int16_t>(Imm)));3156}3157}3158}31593160if (SegReg || BaseReg || IndexReg)3161Operands.push_back(X86Operand::CreateMem(getPointerWidth(), SegReg, Disp,3162BaseReg, IndexReg, Scale, StartLoc,3163EndLoc));3164else3165Operands.push_back(3166X86Operand::CreateMem(getPointerWidth(), Disp, StartLoc, EndLoc));3167return false;3168}31693170// Parse either a standard primary expression or a register.3171bool X86AsmParser::parsePrimaryExpr(const MCExpr *&Res, SMLoc &EndLoc) {3172MCAsmParser &Parser = getParser();3173// See if this is a register first.3174if (getTok().is(AsmToken::Percent) ||3175(isParsingIntelSyntax() && getTok().is(AsmToken::Identifier) &&3176MatchRegisterName(Parser.getTok().getString()))) {3177SMLoc StartLoc = Parser.getTok().getLoc();3178MCRegister RegNo;3179if (parseRegister(RegNo, StartLoc, EndLoc))3180return true;3181Res = X86MCExpr::create(RegNo, Parser.getContext());3182return false;3183}3184return Parser.parsePrimaryExpr(Res, EndLoc, nullptr);3185}31863187bool X86AsmParser::ParseInstruction(ParseInstructionInfo &Info, StringRef Name,3188SMLoc NameLoc, OperandVector &Operands) {3189MCAsmParser &Parser = getParser();3190InstInfo = &Info;31913192// Reset the forced VEX encoding.3193ForcedOpcodePrefix = OpcodePrefix_Default;3194ForcedDispEncoding = DispEncoding_Default;3195UseApxExtendedReg = false;3196ForcedNoFlag = false;31973198// Parse pseudo prefixes.3199while (true) {3200if (Name == "{") {3201if (getLexer().isNot(AsmToken::Identifier))3202return Error(Parser.getTok().getLoc(), "Unexpected token after '{'");3203std::string Prefix = Parser.getTok().getString().lower();3204Parser.Lex(); // Eat identifier.3205if (getLexer().isNot(AsmToken::RCurly))3206return Error(Parser.getTok().getLoc(), "Expected '}'");3207Parser.Lex(); // Eat curly.32083209if (Prefix == "rex")3210ForcedOpcodePrefix = OpcodePrefix_REX;3211else if (Prefix == "rex2")3212ForcedOpcodePrefix = OpcodePrefix_REX2;3213else if (Prefix == "vex")3214ForcedOpcodePrefix = OpcodePrefix_VEX;3215else if (Prefix == "vex2")3216ForcedOpcodePrefix = OpcodePrefix_VEX2;3217else if (Prefix == "vex3")3218ForcedOpcodePrefix = OpcodePrefix_VEX3;3219else if (Prefix == "evex")3220ForcedOpcodePrefix = OpcodePrefix_EVEX;3221else if (Prefix == "disp8")3222ForcedDispEncoding = DispEncoding_Disp8;3223else if (Prefix == "disp32")3224ForcedDispEncoding = DispEncoding_Disp32;3225else if (Prefix == "nf")3226ForcedNoFlag = true;3227else3228return Error(NameLoc, "unknown prefix");32293230NameLoc = Parser.getTok().getLoc();3231if (getLexer().is(AsmToken::LCurly)) {3232Parser.Lex();3233Name = "{";3234} else {3235if (getLexer().isNot(AsmToken::Identifier))3236return Error(Parser.getTok().getLoc(), "Expected identifier");3237// FIXME: The mnemonic won't match correctly if its not in lower case.3238Name = Parser.getTok().getString();3239Parser.Lex();3240}3241continue;3242}3243// Parse MASM style pseudo prefixes.3244if (isParsingMSInlineAsm()) {3245if (Name.equals_insensitive("vex"))3246ForcedOpcodePrefix = OpcodePrefix_VEX;3247else if (Name.equals_insensitive("vex2"))3248ForcedOpcodePrefix = OpcodePrefix_VEX2;3249else if (Name.equals_insensitive("vex3"))3250ForcedOpcodePrefix = OpcodePrefix_VEX3;3251else if (Name.equals_insensitive("evex"))3252ForcedOpcodePrefix = OpcodePrefix_EVEX;32533254if (ForcedOpcodePrefix != OpcodePrefix_Default) {3255if (getLexer().isNot(AsmToken::Identifier))3256return Error(Parser.getTok().getLoc(), "Expected identifier");3257// FIXME: The mnemonic won't match correctly if its not in lower case.3258Name = Parser.getTok().getString();3259NameLoc = Parser.getTok().getLoc();3260Parser.Lex();3261}3262}3263break;3264}32653266// Support the suffix syntax for overriding displacement size as well.3267if (Name.consume_back(".d32")) {3268ForcedDispEncoding = DispEncoding_Disp32;3269} else if (Name.consume_back(".d8")) {3270ForcedDispEncoding = DispEncoding_Disp8;3271}32723273StringRef PatchedName = Name;32743275// Hack to skip "short" following Jcc.3276if (isParsingIntelSyntax() &&3277(PatchedName == "jmp" || PatchedName == "jc" || PatchedName == "jnc" ||3278PatchedName == "jcxz" || PatchedName == "jecxz" ||3279(PatchedName.starts_with("j") &&3280ParseConditionCode(PatchedName.substr(1)) != X86::COND_INVALID))) {3281StringRef NextTok = Parser.getTok().getString();3282if (Parser.isParsingMasm() ? NextTok.equals_insensitive("short")3283: NextTok == "short") {3284SMLoc NameEndLoc =3285NameLoc.getFromPointer(NameLoc.getPointer() + Name.size());3286// Eat the short keyword.3287Parser.Lex();3288// MS and GAS ignore the short keyword; they both determine the jmp type3289// based on the distance of the label. (NASM does emit different code with3290// and without "short," though.)3291InstInfo->AsmRewrites->emplace_back(AOK_Skip, NameEndLoc,3292NextTok.size() + 1);3293}3294}32953296// FIXME: Hack to recognize setneb as setne.3297if (PatchedName.starts_with("set") && PatchedName.ends_with("b") &&3298PatchedName != "setzub" && PatchedName != "setzunb" &&3299PatchedName != "setb" && PatchedName != "setnb")3300PatchedName = PatchedName.substr(0, Name.size()-1);33013302unsigned ComparisonPredicate = ~0U;33033304// FIXME: Hack to recognize cmp<comparison code>{sh,ss,sd,ph,ps,pd}.3305if ((PatchedName.starts_with("cmp") || PatchedName.starts_with("vcmp")) &&3306(PatchedName.ends_with("ss") || PatchedName.ends_with("sd") ||3307PatchedName.ends_with("sh") || PatchedName.ends_with("ph") ||3308PatchedName.ends_with("ps") || PatchedName.ends_with("pd"))) {3309bool IsVCMP = PatchedName[0] == 'v';3310unsigned CCIdx = IsVCMP ? 4 : 3;3311unsigned CC = StringSwitch<unsigned>(3312PatchedName.slice(CCIdx, PatchedName.size() - 2))3313.Case("eq", 0x00)3314.Case("eq_oq", 0x00)3315.Case("lt", 0x01)3316.Case("lt_os", 0x01)3317.Case("le", 0x02)3318.Case("le_os", 0x02)3319.Case("unord", 0x03)3320.Case("unord_q", 0x03)3321.Case("neq", 0x04)3322.Case("neq_uq", 0x04)3323.Case("nlt", 0x05)3324.Case("nlt_us", 0x05)3325.Case("nle", 0x06)3326.Case("nle_us", 0x06)3327.Case("ord", 0x07)3328.Case("ord_q", 0x07)3329/* AVX only from here */3330.Case("eq_uq", 0x08)3331.Case("nge", 0x09)3332.Case("nge_us", 0x09)3333.Case("ngt", 0x0A)3334.Case("ngt_us", 0x0A)3335.Case("false", 0x0B)3336.Case("false_oq", 0x0B)3337.Case("neq_oq", 0x0C)3338.Case("ge", 0x0D)3339.Case("ge_os", 0x0D)3340.Case("gt", 0x0E)3341.Case("gt_os", 0x0E)3342.Case("true", 0x0F)3343.Case("true_uq", 0x0F)3344.Case("eq_os", 0x10)3345.Case("lt_oq", 0x11)3346.Case("le_oq", 0x12)3347.Case("unord_s", 0x13)3348.Case("neq_us", 0x14)3349.Case("nlt_uq", 0x15)3350.Case("nle_uq", 0x16)3351.Case("ord_s", 0x17)3352.Case("eq_us", 0x18)3353.Case("nge_uq", 0x19)3354.Case("ngt_uq", 0x1A)3355.Case("false_os", 0x1B)3356.Case("neq_os", 0x1C)3357.Case("ge_oq", 0x1D)3358.Case("gt_oq", 0x1E)3359.Case("true_us", 0x1F)3360.Default(~0U);3361if (CC != ~0U && (IsVCMP || CC < 8) &&3362(IsVCMP || PatchedName.back() != 'h')) {3363if (PatchedName.ends_with("ss"))3364PatchedName = IsVCMP ? "vcmpss" : "cmpss";3365else if (PatchedName.ends_with("sd"))3366PatchedName = IsVCMP ? "vcmpsd" : "cmpsd";3367else if (PatchedName.ends_with("ps"))3368PatchedName = IsVCMP ? "vcmpps" : "cmpps";3369else if (PatchedName.ends_with("pd"))3370PatchedName = IsVCMP ? "vcmppd" : "cmppd";3371else if (PatchedName.ends_with("sh"))3372PatchedName = "vcmpsh";3373else if (PatchedName.ends_with("ph"))3374PatchedName = "vcmpph";3375else3376llvm_unreachable("Unexpected suffix!");33773378ComparisonPredicate = CC;3379}3380}33813382// FIXME: Hack to recognize vpcmp<comparison code>{ub,uw,ud,uq,b,w,d,q}.3383if (PatchedName.starts_with("vpcmp") &&3384(PatchedName.back() == 'b' || PatchedName.back() == 'w' ||3385PatchedName.back() == 'd' || PatchedName.back() == 'q')) {3386unsigned SuffixSize = PatchedName.drop_back().back() == 'u' ? 2 : 1;3387unsigned CC = StringSwitch<unsigned>(3388PatchedName.slice(5, PatchedName.size() - SuffixSize))3389.Case("eq", 0x0) // Only allowed on unsigned. Checked below.3390.Case("lt", 0x1)3391.Case("le", 0x2)3392//.Case("false", 0x3) // Not a documented alias.3393.Case("neq", 0x4)3394.Case("nlt", 0x5)3395.Case("nle", 0x6)3396//.Case("true", 0x7) // Not a documented alias.3397.Default(~0U);3398if (CC != ~0U && (CC != 0 || SuffixSize == 2)) {3399switch (PatchedName.back()) {3400default: llvm_unreachable("Unexpected character!");3401case 'b': PatchedName = SuffixSize == 2 ? "vpcmpub" : "vpcmpb"; break;3402case 'w': PatchedName = SuffixSize == 2 ? "vpcmpuw" : "vpcmpw"; break;3403case 'd': PatchedName = SuffixSize == 2 ? "vpcmpud" : "vpcmpd"; break;3404case 'q': PatchedName = SuffixSize == 2 ? "vpcmpuq" : "vpcmpq"; break;3405}3406// Set up the immediate to push into the operands later.3407ComparisonPredicate = CC;3408}3409}34103411// FIXME: Hack to recognize vpcom<comparison code>{ub,uw,ud,uq,b,w,d,q}.3412if (PatchedName.starts_with("vpcom") &&3413(PatchedName.back() == 'b' || PatchedName.back() == 'w' ||3414PatchedName.back() == 'd' || PatchedName.back() == 'q')) {3415unsigned SuffixSize = PatchedName.drop_back().back() == 'u' ? 2 : 1;3416unsigned CC = StringSwitch<unsigned>(3417PatchedName.slice(5, PatchedName.size() - SuffixSize))3418.Case("lt", 0x0)3419.Case("le", 0x1)3420.Case("gt", 0x2)3421.Case("ge", 0x3)3422.Case("eq", 0x4)3423.Case("neq", 0x5)3424.Case("false", 0x6)3425.Case("true", 0x7)3426.Default(~0U);3427if (CC != ~0U) {3428switch (PatchedName.back()) {3429default: llvm_unreachable("Unexpected character!");3430case 'b': PatchedName = SuffixSize == 2 ? "vpcomub" : "vpcomb"; break;3431case 'w': PatchedName = SuffixSize == 2 ? "vpcomuw" : "vpcomw"; break;3432case 'd': PatchedName = SuffixSize == 2 ? "vpcomud" : "vpcomd"; break;3433case 'q': PatchedName = SuffixSize == 2 ? "vpcomuq" : "vpcomq"; break;3434}3435// Set up the immediate to push into the operands later.3436ComparisonPredicate = CC;3437}3438}34393440// Determine whether this is an instruction prefix.3441// FIXME:3442// Enhance prefixes integrity robustness. for example, following forms3443// are currently tolerated:3444// repz repnz <insn> ; GAS errors for the use of two similar prefixes3445// lock addq %rax, %rbx ; Destination operand must be of memory type3446// xacquire <insn> ; xacquire must be accompanied by 'lock'3447bool IsPrefix =3448StringSwitch<bool>(Name)3449.Cases("cs", "ds", "es", "fs", "gs", "ss", true)3450.Cases("rex64", "data32", "data16", "addr32", "addr16", true)3451.Cases("xacquire", "xrelease", true)3452.Cases("acquire", "release", isParsingIntelSyntax())3453.Default(false);34543455auto isLockRepeatNtPrefix = [](StringRef N) {3456return StringSwitch<bool>(N)3457.Cases("lock", "rep", "repe", "repz", "repne", "repnz", "notrack", true)3458.Default(false);3459};34603461bool CurlyAsEndOfStatement = false;34623463unsigned Flags = X86::IP_NO_PREFIX;3464while (isLockRepeatNtPrefix(Name.lower())) {3465unsigned Prefix =3466StringSwitch<unsigned>(Name)3467.Cases("lock", "lock", X86::IP_HAS_LOCK)3468.Cases("rep", "repe", "repz", X86::IP_HAS_REPEAT)3469.Cases("repne", "repnz", X86::IP_HAS_REPEAT_NE)3470.Cases("notrack", "notrack", X86::IP_HAS_NOTRACK)3471.Default(X86::IP_NO_PREFIX); // Invalid prefix (impossible)3472Flags |= Prefix;3473if (getLexer().is(AsmToken::EndOfStatement)) {3474// We don't have real instr with the given prefix3475// let's use the prefix as the instr.3476// TODO: there could be several prefixes one after another3477Flags = X86::IP_NO_PREFIX;3478break;3479}3480// FIXME: The mnemonic won't match correctly if its not in lower case.3481Name = Parser.getTok().getString();3482Parser.Lex(); // eat the prefix3483// Hack: we could have something like "rep # some comment" or3484// "lock; cmpxchg16b $1" or "lock\0A\09incl" or "lock/incl"3485while (Name.starts_with(";") || Name.starts_with("\n") ||3486Name.starts_with("#") || Name.starts_with("\t") ||3487Name.starts_with("/")) {3488// FIXME: The mnemonic won't match correctly if its not in lower case.3489Name = Parser.getTok().getString();3490Parser.Lex(); // go to next prefix or instr3491}3492}34933494if (Flags)3495PatchedName = Name;34963497// Hacks to handle 'data16' and 'data32'3498if (PatchedName == "data16" && is16BitMode()) {3499return Error(NameLoc, "redundant data16 prefix");3500}3501if (PatchedName == "data32") {3502if (is32BitMode())3503return Error(NameLoc, "redundant data32 prefix");3504if (is64BitMode())3505return Error(NameLoc, "'data32' is not supported in 64-bit mode");3506// Hack to 'data16' for the table lookup.3507PatchedName = "data16";35083509if (getLexer().isNot(AsmToken::EndOfStatement)) {3510StringRef Next = Parser.getTok().getString();3511getLexer().Lex();3512// data32 effectively changes the instruction suffix.3513// TODO Generalize.3514if (Next == "callw")3515Next = "calll";3516if (Next == "ljmpw")3517Next = "ljmpl";35183519Name = Next;3520PatchedName = Name;3521ForcedDataPrefix = X86::Is32Bit;3522IsPrefix = false;3523}3524}35253526Operands.push_back(X86Operand::CreateToken(PatchedName, NameLoc));35273528// Push the immediate if we extracted one from the mnemonic.3529if (ComparisonPredicate != ~0U && !isParsingIntelSyntax()) {3530const MCExpr *ImmOp = MCConstantExpr::create(ComparisonPredicate,3531getParser().getContext());3532Operands.push_back(X86Operand::CreateImm(ImmOp, NameLoc, NameLoc));3533}35343535// Parse condtional flags after mnemonic.3536if ((Name.starts_with("ccmp") || Name.starts_with("ctest")) &&3537parseCFlagsOp(Operands))3538return true;35393540// This does the actual operand parsing. Don't parse any more if we have a3541// prefix juxtaposed with an operation like "lock incl 4(%rax)", because we3542// just want to parse the "lock" as the first instruction and the "incl" as3543// the next one.3544if (getLexer().isNot(AsmToken::EndOfStatement) && !IsPrefix) {3545// Parse '*' modifier.3546if (getLexer().is(AsmToken::Star))3547Operands.push_back(X86Operand::CreateToken("*", consumeToken()));35483549// Read the operands.3550while (true) {3551if (parseOperand(Operands, Name))3552return true;3553if (HandleAVX512Operand(Operands))3554return true;35553556// check for comma and eat it3557if (getLexer().is(AsmToken::Comma))3558Parser.Lex();3559else3560break;3561}35623563// In MS inline asm curly braces mark the beginning/end of a block,3564// therefore they should be interepreted as end of statement3565CurlyAsEndOfStatement =3566isParsingIntelSyntax() && isParsingMSInlineAsm() &&3567(getLexer().is(AsmToken::LCurly) || getLexer().is(AsmToken::RCurly));3568if (getLexer().isNot(AsmToken::EndOfStatement) && !CurlyAsEndOfStatement)3569return TokError("unexpected token in argument list");3570}35713572// Push the immediate if we extracted one from the mnemonic.3573if (ComparisonPredicate != ~0U && isParsingIntelSyntax()) {3574const MCExpr *ImmOp = MCConstantExpr::create(ComparisonPredicate,3575getParser().getContext());3576Operands.push_back(X86Operand::CreateImm(ImmOp, NameLoc, NameLoc));3577}35783579// Consume the EndOfStatement or the prefix separator Slash3580if (getLexer().is(AsmToken::EndOfStatement) ||3581(IsPrefix && getLexer().is(AsmToken::Slash)))3582Parser.Lex();3583else if (CurlyAsEndOfStatement)3584// Add an actual EndOfStatement before the curly brace3585Info.AsmRewrites->emplace_back(AOK_EndOfStatement,3586getLexer().getTok().getLoc(), 0);35873588// This is for gas compatibility and cannot be done in td.3589// Adding "p" for some floating point with no argument.3590// For example: fsub --> fsubp3591bool IsFp =3592Name == "fsub" || Name == "fdiv" || Name == "fsubr" || Name == "fdivr";3593if (IsFp && Operands.size() == 1) {3594const char *Repl = StringSwitch<const char *>(Name)3595.Case("fsub", "fsubp")3596.Case("fdiv", "fdivp")3597.Case("fsubr", "fsubrp")3598.Case("fdivr", "fdivrp");3599static_cast<X86Operand &>(*Operands[0]).setTokenValue(Repl);3600}36013602if ((Name == "mov" || Name == "movw" || Name == "movl") &&3603(Operands.size() == 3)) {3604X86Operand &Op1 = (X86Operand &)*Operands[1];3605X86Operand &Op2 = (X86Operand &)*Operands[2];3606SMLoc Loc = Op1.getEndLoc();3607// Moving a 32 or 16 bit value into a segment register has the same3608// behavior. Modify such instructions to always take shorter form.3609if (Op1.isReg() && Op2.isReg() &&3610X86MCRegisterClasses[X86::SEGMENT_REGRegClassID].contains(3611Op2.getReg()) &&3612(X86MCRegisterClasses[X86::GR16RegClassID].contains(Op1.getReg()) ||3613X86MCRegisterClasses[X86::GR32RegClassID].contains(Op1.getReg()))) {3614// Change instruction name to match new instruction.3615if (Name != "mov" && Name[3] == (is16BitMode() ? 'l' : 'w')) {3616Name = is16BitMode() ? "movw" : "movl";3617Operands[0] = X86Operand::CreateToken(Name, NameLoc);3618}3619// Select the correct equivalent 16-/32-bit source register.3620MCRegister Reg =3621getX86SubSuperRegister(Op1.getReg(), is16BitMode() ? 16 : 32);3622Operands[1] = X86Operand::CreateReg(Reg, Loc, Loc);3623}3624}36253626// This is a terrible hack to handle "out[s]?[bwl]? %al, (%dx)" ->3627// "outb %al, %dx". Out doesn't take a memory form, but this is a widely3628// documented form in various unofficial manuals, so a lot of code uses it.3629if ((Name == "outb" || Name == "outsb" || Name == "outw" || Name == "outsw" ||3630Name == "outl" || Name == "outsl" || Name == "out" || Name == "outs") &&3631Operands.size() == 3) {3632X86Operand &Op = (X86Operand &)*Operands.back();3633if (Op.isDXReg())3634Operands.back() = X86Operand::CreateReg(X86::DX, Op.getStartLoc(),3635Op.getEndLoc());3636}3637// Same hack for "in[s]?[bwl]? (%dx), %al" -> "inb %dx, %al".3638if ((Name == "inb" || Name == "insb" || Name == "inw" || Name == "insw" ||3639Name == "inl" || Name == "insl" || Name == "in" || Name == "ins") &&3640Operands.size() == 3) {3641X86Operand &Op = (X86Operand &)*Operands[1];3642if (Op.isDXReg())3643Operands[1] = X86Operand::CreateReg(X86::DX, Op.getStartLoc(),3644Op.getEndLoc());3645}36463647SmallVector<std::unique_ptr<MCParsedAsmOperand>, 2> TmpOperands;3648bool HadVerifyError = false;36493650// Append default arguments to "ins[bwld]"3651if (Name.starts_with("ins") &&3652(Operands.size() == 1 || Operands.size() == 3) &&3653(Name == "insb" || Name == "insw" || Name == "insl" || Name == "insd" ||3654Name == "ins")) {36553656AddDefaultSrcDestOperands(TmpOperands,3657X86Operand::CreateReg(X86::DX, NameLoc, NameLoc),3658DefaultMemDIOperand(NameLoc));3659HadVerifyError = VerifyAndAdjustOperands(Operands, TmpOperands);3660}36613662// Append default arguments to "outs[bwld]"3663if (Name.starts_with("outs") &&3664(Operands.size() == 1 || Operands.size() == 3) &&3665(Name == "outsb" || Name == "outsw" || Name == "outsl" ||3666Name == "outsd" || Name == "outs")) {3667AddDefaultSrcDestOperands(TmpOperands, DefaultMemSIOperand(NameLoc),3668X86Operand::CreateReg(X86::DX, NameLoc, NameLoc));3669HadVerifyError = VerifyAndAdjustOperands(Operands, TmpOperands);3670}36713672// Transform "lods[bwlq]" into "lods[bwlq] ($SIREG)" for appropriate3673// values of $SIREG according to the mode. It would be nice if this3674// could be achieved with InstAlias in the tables.3675if (Name.starts_with("lods") &&3676(Operands.size() == 1 || Operands.size() == 2) &&3677(Name == "lods" || Name == "lodsb" || Name == "lodsw" ||3678Name == "lodsl" || Name == "lodsd" || Name == "lodsq")) {3679TmpOperands.push_back(DefaultMemSIOperand(NameLoc));3680HadVerifyError = VerifyAndAdjustOperands(Operands, TmpOperands);3681}36823683// Transform "stos[bwlq]" into "stos[bwlq] ($DIREG)" for appropriate3684// values of $DIREG according to the mode. It would be nice if this3685// could be achieved with InstAlias in the tables.3686if (Name.starts_with("stos") &&3687(Operands.size() == 1 || Operands.size() == 2) &&3688(Name == "stos" || Name == "stosb" || Name == "stosw" ||3689Name == "stosl" || Name == "stosd" || Name == "stosq")) {3690TmpOperands.push_back(DefaultMemDIOperand(NameLoc));3691HadVerifyError = VerifyAndAdjustOperands(Operands, TmpOperands);3692}36933694// Transform "scas[bwlq]" into "scas[bwlq] ($DIREG)" for appropriate3695// values of $DIREG according to the mode. It would be nice if this3696// could be achieved with InstAlias in the tables.3697if (Name.starts_with("scas") &&3698(Operands.size() == 1 || Operands.size() == 2) &&3699(Name == "scas" || Name == "scasb" || Name == "scasw" ||3700Name == "scasl" || Name == "scasd" || Name == "scasq")) {3701TmpOperands.push_back(DefaultMemDIOperand(NameLoc));3702HadVerifyError = VerifyAndAdjustOperands(Operands, TmpOperands);3703}37043705// Add default SI and DI operands to "cmps[bwlq]".3706if (Name.starts_with("cmps") &&3707(Operands.size() == 1 || Operands.size() == 3) &&3708(Name == "cmps" || Name == "cmpsb" || Name == "cmpsw" ||3709Name == "cmpsl" || Name == "cmpsd" || Name == "cmpsq")) {3710AddDefaultSrcDestOperands(TmpOperands, DefaultMemDIOperand(NameLoc),3711DefaultMemSIOperand(NameLoc));3712HadVerifyError = VerifyAndAdjustOperands(Operands, TmpOperands);3713}37143715// Add default SI and DI operands to "movs[bwlq]".3716if (((Name.starts_with("movs") &&3717(Name == "movs" || Name == "movsb" || Name == "movsw" ||3718Name == "movsl" || Name == "movsd" || Name == "movsq")) ||3719(Name.starts_with("smov") &&3720(Name == "smov" || Name == "smovb" || Name == "smovw" ||3721Name == "smovl" || Name == "smovd" || Name == "smovq"))) &&3722(Operands.size() == 1 || Operands.size() == 3)) {3723if (Name == "movsd" && Operands.size() == 1 && !isParsingIntelSyntax())3724Operands.back() = X86Operand::CreateToken("movsl", NameLoc);3725AddDefaultSrcDestOperands(TmpOperands, DefaultMemSIOperand(NameLoc),3726DefaultMemDIOperand(NameLoc));3727HadVerifyError = VerifyAndAdjustOperands(Operands, TmpOperands);3728}37293730// Check if we encountered an error for one the string insturctions3731if (HadVerifyError) {3732return HadVerifyError;3733}37343735// Transforms "xlat mem8" into "xlatb"3736if ((Name == "xlat" || Name == "xlatb") && Operands.size() == 2) {3737X86Operand &Op1 = static_cast<X86Operand &>(*Operands[1]);3738if (Op1.isMem8()) {3739Warning(Op1.getStartLoc(), "memory operand is only for determining the "3740"size, (R|E)BX will be used for the location");3741Operands.pop_back();3742static_cast<X86Operand &>(*Operands[0]).setTokenValue("xlatb");3743}3744}37453746if (Flags)3747Operands.push_back(X86Operand::CreatePrefix(Flags, NameLoc, NameLoc));3748return false;3749}37503751static bool convertSSEToAVX(MCInst &Inst) {3752ArrayRef<X86TableEntry> Table{X86SSE2AVXTable};3753unsigned Opcode = Inst.getOpcode();3754const auto I = llvm::lower_bound(Table, Opcode);3755if (I == Table.end() || I->OldOpc != Opcode)3756return false;37573758Inst.setOpcode(I->NewOpc);3759// AVX variant of BLENDVPD/BLENDVPS/PBLENDVB instructions has more3760// operand compare to SSE variant, which is added below3761if (X86::isBLENDVPD(Opcode) || X86::isBLENDVPS(Opcode) ||3762X86::isPBLENDVB(Opcode))3763Inst.addOperand(Inst.getOperand(2));37643765return true;3766}37673768bool X86AsmParser::processInstruction(MCInst &Inst, const OperandVector &Ops) {3769if (MCOptions.X86Sse2Avx && convertSSEToAVX(Inst))3770return true;37713772if (ForcedOpcodePrefix != OpcodePrefix_VEX3 &&3773X86::optimizeInstFromVEX3ToVEX2(Inst, MII.get(Inst.getOpcode())))3774return true;37753776if (X86::optimizeShiftRotateWithImmediateOne(Inst))3777return true;37783779switch (Inst.getOpcode()) {3780default: return false;3781case X86::JMP_1:3782// {disp32} forces a larger displacement as if the instruction was relaxed.3783// NOTE: 16-bit mode uses 16-bit displacement even though it says {disp32}.3784// This matches GNU assembler.3785if (ForcedDispEncoding == DispEncoding_Disp32) {3786Inst.setOpcode(is16BitMode() ? X86::JMP_2 : X86::JMP_4);3787return true;3788}37893790return false;3791case X86::JCC_1:3792// {disp32} forces a larger displacement as if the instruction was relaxed.3793// NOTE: 16-bit mode uses 16-bit displacement even though it says {disp32}.3794// This matches GNU assembler.3795if (ForcedDispEncoding == DispEncoding_Disp32) {3796Inst.setOpcode(is16BitMode() ? X86::JCC_2 : X86::JCC_4);3797return true;3798}37993800return false;3801case X86::INT: {3802// Transforms "int $3" into "int3" as a size optimization.3803// We can't write this as an InstAlias.3804if (!Inst.getOperand(0).isImm() || Inst.getOperand(0).getImm() != 3)3805return false;3806Inst.clear();3807Inst.setOpcode(X86::INT3);3808return true;3809}3810}3811}38123813bool X86AsmParser::validateInstruction(MCInst &Inst, const OperandVector &Ops) {3814using namespace X86;3815const MCRegisterInfo *MRI = getContext().getRegisterInfo();3816unsigned Opcode = Inst.getOpcode();3817uint64_t TSFlags = MII.get(Opcode).TSFlags;3818if (isVFCMADDCPH(Opcode) || isVFCMADDCSH(Opcode) || isVFMADDCPH(Opcode) ||3819isVFMADDCSH(Opcode)) {3820unsigned Dest = Inst.getOperand(0).getReg();3821for (unsigned i = 2; i < Inst.getNumOperands(); i++)3822if (Inst.getOperand(i).isReg() && Dest == Inst.getOperand(i).getReg())3823return Warning(Ops[0]->getStartLoc(), "Destination register should be "3824"distinct from source registers");3825} else if (isVFCMULCPH(Opcode) || isVFCMULCSH(Opcode) || isVFMULCPH(Opcode) ||3826isVFMULCSH(Opcode)) {3827unsigned Dest = Inst.getOperand(0).getReg();3828// The mask variants have different operand list. Scan from the third3829// operand to avoid emitting incorrect warning.3830// VFMULCPHZrr Dest, Src1, Src23831// VFMULCPHZrrk Dest, Dest, Mask, Src1, Src23832// VFMULCPHZrrkz Dest, Mask, Src1, Src23833for (unsigned i = ((TSFlags & X86II::EVEX_K) ? 2 : 1);3834i < Inst.getNumOperands(); i++)3835if (Inst.getOperand(i).isReg() && Dest == Inst.getOperand(i).getReg())3836return Warning(Ops[0]->getStartLoc(), "Destination register should be "3837"distinct from source registers");3838} else if (isV4FMADDPS(Opcode) || isV4FMADDSS(Opcode) ||3839isV4FNMADDPS(Opcode) || isV4FNMADDSS(Opcode) ||3840isVP4DPWSSDS(Opcode) || isVP4DPWSSD(Opcode)) {3841unsigned Src2 = Inst.getOperand(Inst.getNumOperands() -3842X86::AddrNumOperands - 1).getReg();3843unsigned Src2Enc = MRI->getEncodingValue(Src2);3844if (Src2Enc % 4 != 0) {3845StringRef RegName = X86IntelInstPrinter::getRegisterName(Src2);3846unsigned GroupStart = (Src2Enc / 4) * 4;3847unsigned GroupEnd = GroupStart + 3;3848return Warning(Ops[0]->getStartLoc(),3849"source register '" + RegName + "' implicitly denotes '" +3850RegName.take_front(3) + Twine(GroupStart) + "' to '" +3851RegName.take_front(3) + Twine(GroupEnd) +3852"' source group");3853}3854} else if (isVGATHERDPD(Opcode) || isVGATHERDPS(Opcode) ||3855isVGATHERQPD(Opcode) || isVGATHERQPS(Opcode) ||3856isVPGATHERDD(Opcode) || isVPGATHERDQ(Opcode) ||3857isVPGATHERQD(Opcode) || isVPGATHERQQ(Opcode)) {3858bool HasEVEX = (TSFlags & X86II::EncodingMask) == X86II::EVEX;3859if (HasEVEX) {3860unsigned Dest = MRI->getEncodingValue(Inst.getOperand(0).getReg());3861unsigned Index = MRI->getEncodingValue(3862Inst.getOperand(4 + X86::AddrIndexReg).getReg());3863if (Dest == Index)3864return Warning(Ops[0]->getStartLoc(), "index and destination registers "3865"should be distinct");3866} else {3867unsigned Dest = MRI->getEncodingValue(Inst.getOperand(0).getReg());3868unsigned Mask = MRI->getEncodingValue(Inst.getOperand(1).getReg());3869unsigned Index = MRI->getEncodingValue(3870Inst.getOperand(3 + X86::AddrIndexReg).getReg());3871if (Dest == Mask || Dest == Index || Mask == Index)3872return Warning(Ops[0]->getStartLoc(), "mask, index, and destination "3873"registers should be distinct");3874}3875} else if (isTCMMIMFP16PS(Opcode) || isTCMMRLFP16PS(Opcode) ||3876isTDPBF16PS(Opcode) || isTDPFP16PS(Opcode) || isTDPBSSD(Opcode) ||3877isTDPBSUD(Opcode) || isTDPBUSD(Opcode) || isTDPBUUD(Opcode)) {3878unsigned SrcDest = Inst.getOperand(0).getReg();3879unsigned Src1 = Inst.getOperand(2).getReg();3880unsigned Src2 = Inst.getOperand(3).getReg();3881if (SrcDest == Src1 || SrcDest == Src2 || Src1 == Src2)3882return Error(Ops[0]->getStartLoc(), "all tmm registers must be distinct");3883}38843885// Check that we aren't mixing AH/BH/CH/DH with REX prefix. We only need to3886// check this with the legacy encoding, VEX/EVEX/XOP don't use REX.3887if ((TSFlags & X86II::EncodingMask) == 0) {3888MCPhysReg HReg = X86::NoRegister;3889bool UsesRex = TSFlags & X86II::REX_W;3890unsigned NumOps = Inst.getNumOperands();3891for (unsigned i = 0; i != NumOps; ++i) {3892const MCOperand &MO = Inst.getOperand(i);3893if (!MO.isReg())3894continue;3895unsigned Reg = MO.getReg();3896if (Reg == X86::AH || Reg == X86::BH || Reg == X86::CH || Reg == X86::DH)3897HReg = Reg;3898if (X86II::isX86_64NonExtLowByteReg(Reg) ||3899X86II::isX86_64ExtendedReg(Reg))3900UsesRex = true;3901}39023903if (UsesRex && HReg != X86::NoRegister) {3904StringRef RegName = X86IntelInstPrinter::getRegisterName(HReg);3905return Error(Ops[0]->getStartLoc(),3906"can't encode '" + RegName + "' in an instruction requiring "3907"REX prefix");3908}3909}39103911if ((Opcode == X86::PREFETCHIT0 || Opcode == X86::PREFETCHIT1)) {3912const MCOperand &MO = Inst.getOperand(X86::AddrBaseReg);3913if (!MO.isReg() || MO.getReg() != X86::RIP)3914return Warning(3915Ops[0]->getStartLoc(),3916Twine((Inst.getOpcode() == X86::PREFETCHIT0 ? "'prefetchit0'"3917: "'prefetchit1'")) +3918" only supports RIP-relative address");3919}3920return false;3921}39223923void X86AsmParser::emitWarningForSpecialLVIInstruction(SMLoc Loc) {3924Warning(Loc, "Instruction may be vulnerable to LVI and "3925"requires manual mitigation");3926Note(SMLoc(), "See https://software.intel.com/"3927"security-software-guidance/insights/"3928"deep-dive-load-value-injection#specialinstructions"3929" for more information");3930}39313932/// RET instructions and also instructions that indirect calls/jumps from memory3933/// combine a load and a branch within a single instruction. To mitigate these3934/// instructions against LVI, they must be decomposed into separate load and3935/// branch instructions, with an LFENCE in between. For more details, see:3936/// - X86LoadValueInjectionRetHardening.cpp3937/// - X86LoadValueInjectionIndirectThunks.cpp3938/// - https://software.intel.com/security-software-guidance/insights/deep-dive-load-value-injection3939///3940/// Returns `true` if a mitigation was applied or warning was emitted.3941void X86AsmParser::applyLVICFIMitigation(MCInst &Inst, MCStreamer &Out) {3942// Information on control-flow instructions that require manual mitigation can3943// be found here:3944// https://software.intel.com/security-software-guidance/insights/deep-dive-load-value-injection#specialinstructions3945switch (Inst.getOpcode()) {3946case X86::RET16:3947case X86::RET32:3948case X86::RET64:3949case X86::RETI16:3950case X86::RETI32:3951case X86::RETI64: {3952MCInst ShlInst, FenceInst;3953bool Parse32 = is32BitMode() || Code16GCC;3954unsigned Basereg =3955is64BitMode() ? X86::RSP : (Parse32 ? X86::ESP : X86::SP);3956const MCExpr *Disp = MCConstantExpr::create(0, getContext());3957auto ShlMemOp = X86Operand::CreateMem(getPointerWidth(), /*SegReg=*/0, Disp,3958/*BaseReg=*/Basereg, /*IndexReg=*/0,3959/*Scale=*/1, SMLoc{}, SMLoc{}, 0);3960ShlInst.setOpcode(X86::SHL64mi);3961ShlMemOp->addMemOperands(ShlInst, 5);3962ShlInst.addOperand(MCOperand::createImm(0));3963FenceInst.setOpcode(X86::LFENCE);3964Out.emitInstruction(ShlInst, getSTI());3965Out.emitInstruction(FenceInst, getSTI());3966return;3967}3968case X86::JMP16m:3969case X86::JMP32m:3970case X86::JMP64m:3971case X86::CALL16m:3972case X86::CALL32m:3973case X86::CALL64m:3974emitWarningForSpecialLVIInstruction(Inst.getLoc());3975return;3976}3977}39783979/// To mitigate LVI, every instruction that performs a load can be followed by3980/// an LFENCE instruction to squash any potential mis-speculation. There are3981/// some instructions that require additional considerations, and may requre3982/// manual mitigation. For more details, see:3983/// https://software.intel.com/security-software-guidance/insights/deep-dive-load-value-injection3984///3985/// Returns `true` if a mitigation was applied or warning was emitted.3986void X86AsmParser::applyLVILoadHardeningMitigation(MCInst &Inst,3987MCStreamer &Out) {3988auto Opcode = Inst.getOpcode();3989auto Flags = Inst.getFlags();3990if ((Flags & X86::IP_HAS_REPEAT) || (Flags & X86::IP_HAS_REPEAT_NE)) {3991// Information on REP string instructions that require manual mitigation can3992// be found here:3993// https://software.intel.com/security-software-guidance/insights/deep-dive-load-value-injection#specialinstructions3994switch (Opcode) {3995case X86::CMPSB:3996case X86::CMPSW:3997case X86::CMPSL:3998case X86::CMPSQ:3999case X86::SCASB:4000case X86::SCASW:4001case X86::SCASL:4002case X86::SCASQ:4003emitWarningForSpecialLVIInstruction(Inst.getLoc());4004return;4005}4006} else if (Opcode == X86::REP_PREFIX || Opcode == X86::REPNE_PREFIX) {4007// If a REP instruction is found on its own line, it may or may not be4008// followed by a vulnerable instruction. Emit a warning just in case.4009emitWarningForSpecialLVIInstruction(Inst.getLoc());4010return;4011}40124013const MCInstrDesc &MCID = MII.get(Inst.getOpcode());40144015// Can't mitigate after terminators or calls. A control flow change may have4016// already occurred.4017if (MCID.isTerminator() || MCID.isCall())4018return;40194020// LFENCE has the mayLoad property, don't double fence.4021if (MCID.mayLoad() && Inst.getOpcode() != X86::LFENCE) {4022MCInst FenceInst;4023FenceInst.setOpcode(X86::LFENCE);4024Out.emitInstruction(FenceInst, getSTI());4025}4026}40274028void X86AsmParser::emitInstruction(MCInst &Inst, OperandVector &Operands,4029MCStreamer &Out) {4030if (LVIInlineAsmHardening &&4031getSTI().hasFeature(X86::FeatureLVIControlFlowIntegrity))4032applyLVICFIMitigation(Inst, Out);40334034Out.emitInstruction(Inst, getSTI());40354036if (LVIInlineAsmHardening &&4037getSTI().hasFeature(X86::FeatureLVILoadHardening))4038applyLVILoadHardeningMitigation(Inst, Out);4039}40404041static unsigned getPrefixes(OperandVector &Operands) {4042unsigned Result = 0;4043X86Operand &Prefix = static_cast<X86Operand &>(*Operands.back());4044if (Prefix.isPrefix()) {4045Result = Prefix.getPrefix();4046Operands.pop_back();4047}4048return Result;4049}40504051bool X86AsmParser::MatchAndEmitInstruction(SMLoc IDLoc, unsigned &Opcode,4052OperandVector &Operands,4053MCStreamer &Out, uint64_t &ErrorInfo,4054bool MatchingInlineAsm) {4055assert(!Operands.empty() && "Unexpect empty operand list!");4056assert((*Operands[0]).isToken() && "Leading operand should always be a mnemonic!");40574058// First, handle aliases that expand to multiple instructions.4059MatchFPUWaitAlias(IDLoc, static_cast<X86Operand &>(*Operands[0]), Operands,4060Out, MatchingInlineAsm);4061unsigned Prefixes = getPrefixes(Operands);40624063MCInst Inst;40644065// If REX/REX2/VEX/EVEX encoding is forced, we need to pass the USE_* flag to4066// the encoder and printer.4067if (ForcedOpcodePrefix == OpcodePrefix_REX)4068Prefixes |= X86::IP_USE_REX;4069else if (ForcedOpcodePrefix == OpcodePrefix_REX2)4070Prefixes |= X86::IP_USE_REX2;4071else if (ForcedOpcodePrefix == OpcodePrefix_VEX)4072Prefixes |= X86::IP_USE_VEX;4073else if (ForcedOpcodePrefix == OpcodePrefix_VEX2)4074Prefixes |= X86::IP_USE_VEX2;4075else if (ForcedOpcodePrefix == OpcodePrefix_VEX3)4076Prefixes |= X86::IP_USE_VEX3;4077else if (ForcedOpcodePrefix == OpcodePrefix_EVEX)4078Prefixes |= X86::IP_USE_EVEX;40794080// Set encoded flags for {disp8} and {disp32}.4081if (ForcedDispEncoding == DispEncoding_Disp8)4082Prefixes |= X86::IP_USE_DISP8;4083else if (ForcedDispEncoding == DispEncoding_Disp32)4084Prefixes |= X86::IP_USE_DISP32;40854086if (Prefixes)4087Inst.setFlags(Prefixes);40884089return isParsingIntelSyntax()4090? matchAndEmitIntelInstruction(IDLoc, Opcode, Inst, Operands, Out,4091ErrorInfo, MatchingInlineAsm)4092: matchAndEmitATTInstruction(IDLoc, Opcode, Inst, Operands, Out,4093ErrorInfo, MatchingInlineAsm);4094}40954096void X86AsmParser::MatchFPUWaitAlias(SMLoc IDLoc, X86Operand &Op,4097OperandVector &Operands, MCStreamer &Out,4098bool MatchingInlineAsm) {4099// FIXME: This should be replaced with a real .td file alias mechanism.4100// Also, MatchInstructionImpl should actually *do* the EmitInstruction4101// call.4102const char *Repl = StringSwitch<const char *>(Op.getToken())4103.Case("finit", "fninit")4104.Case("fsave", "fnsave")4105.Case("fstcw", "fnstcw")4106.Case("fstcww", "fnstcw")4107.Case("fstenv", "fnstenv")4108.Case("fstsw", "fnstsw")4109.Case("fstsww", "fnstsw")4110.Case("fclex", "fnclex")4111.Default(nullptr);4112if (Repl) {4113MCInst Inst;4114Inst.setOpcode(X86::WAIT);4115Inst.setLoc(IDLoc);4116if (!MatchingInlineAsm)4117emitInstruction(Inst, Operands, Out);4118Operands[0] = X86Operand::CreateToken(Repl, IDLoc);4119}4120}41214122bool X86AsmParser::ErrorMissingFeature(SMLoc IDLoc,4123const FeatureBitset &MissingFeatures,4124bool MatchingInlineAsm) {4125assert(MissingFeatures.any() && "Unknown missing feature!");4126SmallString<126> Msg;4127raw_svector_ostream OS(Msg);4128OS << "instruction requires:";4129for (unsigned i = 0, e = MissingFeatures.size(); i != e; ++i) {4130if (MissingFeatures[i])4131OS << ' ' << getSubtargetFeatureName(i);4132}4133return Error(IDLoc, OS.str(), SMRange(), MatchingInlineAsm);4134}41354136unsigned X86AsmParser::checkTargetMatchPredicate(MCInst &Inst) {4137unsigned Opc = Inst.getOpcode();4138const MCInstrDesc &MCID = MII.get(Opc);4139uint64_t TSFlags = MCID.TSFlags;41404141if (UseApxExtendedReg && !X86II::canUseApxExtendedReg(MCID))4142return Match_Unsupported;4143if (ForcedNoFlag == !(TSFlags & X86II::EVEX_NF) && !X86::isCFCMOVCC(Opc))4144return Match_Unsupported;41454146switch (ForcedOpcodePrefix) {4147case OpcodePrefix_Default:4148break;4149case OpcodePrefix_REX:4150case OpcodePrefix_REX2:4151if (TSFlags & X86II::EncodingMask)4152return Match_Unsupported;4153break;4154case OpcodePrefix_VEX:4155case OpcodePrefix_VEX2:4156case OpcodePrefix_VEX3:4157if ((TSFlags & X86II::EncodingMask) != X86II::VEX)4158return Match_Unsupported;4159break;4160case OpcodePrefix_EVEX:4161if ((TSFlags & X86II::EncodingMask) != X86II::EVEX)4162return Match_Unsupported;4163break;4164}41654166if ((TSFlags & X86II::ExplicitOpPrefixMask) == X86II::ExplicitVEXPrefix &&4167(ForcedOpcodePrefix != OpcodePrefix_VEX &&4168ForcedOpcodePrefix != OpcodePrefix_VEX2 &&4169ForcedOpcodePrefix != OpcodePrefix_VEX3))4170return Match_Unsupported;41714172return Match_Success;4173}41744175bool X86AsmParser::matchAndEmitATTInstruction(4176SMLoc IDLoc, unsigned &Opcode, MCInst &Inst, OperandVector &Operands,4177MCStreamer &Out, uint64_t &ErrorInfo, bool MatchingInlineAsm) {4178X86Operand &Op = static_cast<X86Operand &>(*Operands[0]);4179SMRange EmptyRange = std::nullopt;4180// In 16-bit mode, if data32 is specified, temporarily switch to 32-bit mode4181// when matching the instruction.4182if (ForcedDataPrefix == X86::Is32Bit)4183SwitchMode(X86::Is32Bit);4184// First, try a direct match.4185FeatureBitset MissingFeatures;4186unsigned OriginalError = MatchInstruction(Operands, Inst, ErrorInfo,4187MissingFeatures, MatchingInlineAsm,4188isParsingIntelSyntax());4189if (ForcedDataPrefix == X86::Is32Bit) {4190SwitchMode(X86::Is16Bit);4191ForcedDataPrefix = 0;4192}4193switch (OriginalError) {4194default: llvm_unreachable("Unexpected match result!");4195case Match_Success:4196if (!MatchingInlineAsm && validateInstruction(Inst, Operands))4197return true;4198// Some instructions need post-processing to, for example, tweak which4199// encoding is selected. Loop on it while changes happen so the4200// individual transformations can chain off each other.4201if (!MatchingInlineAsm)4202while (processInstruction(Inst, Operands))4203;42044205Inst.setLoc(IDLoc);4206if (!MatchingInlineAsm)4207emitInstruction(Inst, Operands, Out);4208Opcode = Inst.getOpcode();4209return false;4210case Match_InvalidImmUnsignedi4: {4211SMLoc ErrorLoc = ((X86Operand &)*Operands[ErrorInfo]).getStartLoc();4212if (ErrorLoc == SMLoc())4213ErrorLoc = IDLoc;4214return Error(ErrorLoc, "immediate must be an integer in range [0, 15]",4215EmptyRange, MatchingInlineAsm);4216}4217case Match_MissingFeature:4218return ErrorMissingFeature(IDLoc, MissingFeatures, MatchingInlineAsm);4219case Match_InvalidOperand:4220case Match_MnemonicFail:4221case Match_Unsupported:4222break;4223}4224if (Op.getToken().empty()) {4225Error(IDLoc, "instruction must have size higher than 0", EmptyRange,4226MatchingInlineAsm);4227return true;4228}42294230// FIXME: Ideally, we would only attempt suffix matches for things which are4231// valid prefixes, and we could just infer the right unambiguous4232// type. However, that requires substantially more matcher support than the4233// following hack.42344235// Change the operand to point to a temporary token.4236StringRef Base = Op.getToken();4237SmallString<16> Tmp;4238Tmp += Base;4239Tmp += ' ';4240Op.setTokenValue(Tmp);42414242// If this instruction starts with an 'f', then it is a floating point stack4243// instruction. These come in up to three forms for 32-bit, 64-bit, and4244// 80-bit floating point, which use the suffixes s,l,t respectively.4245//4246// Otherwise, we assume that this may be an integer instruction, which comes4247// in 8/16/32/64-bit forms using the b,w,l,q suffixes respectively.4248const char *Suffixes = Base[0] != 'f' ? "bwlq" : "slt\0";4249// MemSize corresponding to Suffixes. { 8, 16, 32, 64 } { 32, 64, 80, 0 }4250const char *MemSize = Base[0] != 'f' ? "\x08\x10\x20\x40" : "\x20\x40\x50\0";42514252// Check for the various suffix matches.4253uint64_t ErrorInfoIgnore;4254FeatureBitset ErrorInfoMissingFeatures; // Init suppresses compiler warnings.4255unsigned Match[4];42564257// Some instruction like VPMULDQ is NOT the variant of VPMULD but a new one.4258// So we should make sure the suffix matcher only works for memory variant4259// that has the same size with the suffix.4260// FIXME: This flag is a workaround for legacy instructions that didn't4261// declare non suffix variant assembly.4262bool HasVectorReg = false;4263X86Operand *MemOp = nullptr;4264for (const auto &Op : Operands) {4265X86Operand *X86Op = static_cast<X86Operand *>(Op.get());4266if (X86Op->isVectorReg())4267HasVectorReg = true;4268else if (X86Op->isMem()) {4269MemOp = X86Op;4270assert(MemOp->Mem.Size == 0 && "Memory size always 0 under ATT syntax");4271// Have we found an unqualified memory operand,4272// break. IA allows only one memory operand.4273break;4274}4275}42764277for (unsigned I = 0, E = std::size(Match); I != E; ++I) {4278Tmp.back() = Suffixes[I];4279if (MemOp && HasVectorReg)4280MemOp->Mem.Size = MemSize[I];4281Match[I] = Match_MnemonicFail;4282if (MemOp || !HasVectorReg) {4283Match[I] =4284MatchInstruction(Operands, Inst, ErrorInfoIgnore, MissingFeatures,4285MatchingInlineAsm, isParsingIntelSyntax());4286// If this returned as a missing feature failure, remember that.4287if (Match[I] == Match_MissingFeature)4288ErrorInfoMissingFeatures = MissingFeatures;4289}4290}42914292// Restore the old token.4293Op.setTokenValue(Base);42944295// If exactly one matched, then we treat that as a successful match (and the4296// instruction will already have been filled in correctly, since the failing4297// matches won't have modified it).4298unsigned NumSuccessfulMatches = llvm::count(Match, Match_Success);4299if (NumSuccessfulMatches == 1) {4300if (!MatchingInlineAsm && validateInstruction(Inst, Operands))4301return true;4302// Some instructions need post-processing to, for example, tweak which4303// encoding is selected. Loop on it while changes happen so the4304// individual transformations can chain off each other.4305if (!MatchingInlineAsm)4306while (processInstruction(Inst, Operands))4307;43084309Inst.setLoc(IDLoc);4310if (!MatchingInlineAsm)4311emitInstruction(Inst, Operands, Out);4312Opcode = Inst.getOpcode();4313return false;4314}43154316// Otherwise, the match failed, try to produce a decent error message.43174318// If we had multiple suffix matches, then identify this as an ambiguous4319// match.4320if (NumSuccessfulMatches > 1) {4321char MatchChars[4];4322unsigned NumMatches = 0;4323for (unsigned I = 0, E = std::size(Match); I != E; ++I)4324if (Match[I] == Match_Success)4325MatchChars[NumMatches++] = Suffixes[I];43264327SmallString<126> Msg;4328raw_svector_ostream OS(Msg);4329OS << "ambiguous instructions require an explicit suffix (could be ";4330for (unsigned i = 0; i != NumMatches; ++i) {4331if (i != 0)4332OS << ", ";4333if (i + 1 == NumMatches)4334OS << "or ";4335OS << "'" << Base << MatchChars[i] << "'";4336}4337OS << ")";4338Error(IDLoc, OS.str(), EmptyRange, MatchingInlineAsm);4339return true;4340}43414342// Okay, we know that none of the variants matched successfully.43434344// If all of the instructions reported an invalid mnemonic, then the original4345// mnemonic was invalid.4346if (llvm::count(Match, Match_MnemonicFail) == 4) {4347if (OriginalError == Match_MnemonicFail)4348return Error(IDLoc, "invalid instruction mnemonic '" + Base + "'",4349Op.getLocRange(), MatchingInlineAsm);43504351if (OriginalError == Match_Unsupported)4352return Error(IDLoc, "unsupported instruction", EmptyRange,4353MatchingInlineAsm);43544355assert(OriginalError == Match_InvalidOperand && "Unexpected error");4356// Recover location info for the operand if we know which was the problem.4357if (ErrorInfo != ~0ULL) {4358if (ErrorInfo >= Operands.size())4359return Error(IDLoc, "too few operands for instruction", EmptyRange,4360MatchingInlineAsm);43614362X86Operand &Operand = (X86Operand &)*Operands[ErrorInfo];4363if (Operand.getStartLoc().isValid()) {4364SMRange OperandRange = Operand.getLocRange();4365return Error(Operand.getStartLoc(), "invalid operand for instruction",4366OperandRange, MatchingInlineAsm);4367}4368}43694370return Error(IDLoc, "invalid operand for instruction", EmptyRange,4371MatchingInlineAsm);4372}43734374// If one instruction matched as unsupported, report this as unsupported.4375if (llvm::count(Match, Match_Unsupported) == 1) {4376return Error(IDLoc, "unsupported instruction", EmptyRange,4377MatchingInlineAsm);4378}43794380// If one instruction matched with a missing feature, report this as a4381// missing feature.4382if (llvm::count(Match, Match_MissingFeature) == 1) {4383ErrorInfo = Match_MissingFeature;4384return ErrorMissingFeature(IDLoc, ErrorInfoMissingFeatures,4385MatchingInlineAsm);4386}43874388// If one instruction matched with an invalid operand, report this as an4389// operand failure.4390if (llvm::count(Match, Match_InvalidOperand) == 1) {4391return Error(IDLoc, "invalid operand for instruction", EmptyRange,4392MatchingInlineAsm);4393}43944395// If all of these were an outright failure, report it in a useless way.4396Error(IDLoc, "unknown use of instruction mnemonic without a size suffix",4397EmptyRange, MatchingInlineAsm);4398return true;4399}44004401bool X86AsmParser::matchAndEmitIntelInstruction(4402SMLoc IDLoc, unsigned &Opcode, MCInst &Inst, OperandVector &Operands,4403MCStreamer &Out, uint64_t &ErrorInfo, bool MatchingInlineAsm) {4404X86Operand &Op = static_cast<X86Operand &>(*Operands[0]);4405SMRange EmptyRange = std::nullopt;4406// Find one unsized memory operand, if present.4407X86Operand *UnsizedMemOp = nullptr;4408for (const auto &Op : Operands) {4409X86Operand *X86Op = static_cast<X86Operand *>(Op.get());4410if (X86Op->isMemUnsized()) {4411UnsizedMemOp = X86Op;4412// Have we found an unqualified memory operand,4413// break. IA allows only one memory operand.4414break;4415}4416}44174418// Allow some instructions to have implicitly pointer-sized operands. This is4419// compatible with gas.4420StringRef Mnemonic = (static_cast<X86Operand &>(*Operands[0])).getToken();4421if (UnsizedMemOp) {4422static const char *const PtrSizedInstrs[] = {"call", "jmp", "push"};4423for (const char *Instr : PtrSizedInstrs) {4424if (Mnemonic == Instr) {4425UnsizedMemOp->Mem.Size = getPointerWidth();4426break;4427}4428}4429}44304431SmallVector<unsigned, 8> Match;4432FeatureBitset ErrorInfoMissingFeatures;4433FeatureBitset MissingFeatures;4434StringRef Base = (static_cast<X86Operand &>(*Operands[0])).getToken();44354436// If unsized push has immediate operand we should default the default pointer4437// size for the size.4438if (Mnemonic == "push" && Operands.size() == 2) {4439auto *X86Op = static_cast<X86Operand *>(Operands[1].get());4440if (X86Op->isImm()) {4441// If it's not a constant fall through and let remainder take care of it.4442const auto *CE = dyn_cast<MCConstantExpr>(X86Op->getImm());4443unsigned Size = getPointerWidth();4444if (CE &&4445(isIntN(Size, CE->getValue()) || isUIntN(Size, CE->getValue()))) {4446SmallString<16> Tmp;4447Tmp += Base;4448Tmp += (is64BitMode())4449? "q"4450: (is32BitMode()) ? "l" : (is16BitMode()) ? "w" : " ";4451Op.setTokenValue(Tmp);4452// Do match in ATT mode to allow explicit suffix usage.4453Match.push_back(MatchInstruction(Operands, Inst, ErrorInfo,4454MissingFeatures, MatchingInlineAsm,4455false /*isParsingIntelSyntax()*/));4456Op.setTokenValue(Base);4457}4458}4459}44604461// If an unsized memory operand is present, try to match with each memory4462// operand size. In Intel assembly, the size is not part of the instruction4463// mnemonic.4464if (UnsizedMemOp && UnsizedMemOp->isMemUnsized()) {4465static const unsigned MopSizes[] = {8, 16, 32, 64, 80, 128, 256, 512};4466for (unsigned Size : MopSizes) {4467UnsizedMemOp->Mem.Size = Size;4468uint64_t ErrorInfoIgnore;4469unsigned LastOpcode = Inst.getOpcode();4470unsigned M = MatchInstruction(Operands, Inst, ErrorInfoIgnore,4471MissingFeatures, MatchingInlineAsm,4472isParsingIntelSyntax());4473if (Match.empty() || LastOpcode != Inst.getOpcode())4474Match.push_back(M);44754476// If this returned as a missing feature failure, remember that.4477if (Match.back() == Match_MissingFeature)4478ErrorInfoMissingFeatures = MissingFeatures;4479}44804481// Restore the size of the unsized memory operand if we modified it.4482UnsizedMemOp->Mem.Size = 0;4483}44844485// If we haven't matched anything yet, this is not a basic integer or FPU4486// operation. There shouldn't be any ambiguity in our mnemonic table, so try4487// matching with the unsized operand.4488if (Match.empty()) {4489Match.push_back(MatchInstruction(4490Operands, Inst, ErrorInfo, MissingFeatures, MatchingInlineAsm,4491isParsingIntelSyntax()));4492// If this returned as a missing feature failure, remember that.4493if (Match.back() == Match_MissingFeature)4494ErrorInfoMissingFeatures = MissingFeatures;4495}44964497// Restore the size of the unsized memory operand if we modified it.4498if (UnsizedMemOp)4499UnsizedMemOp->Mem.Size = 0;45004501// If it's a bad mnemonic, all results will be the same.4502if (Match.back() == Match_MnemonicFail) {4503return Error(IDLoc, "invalid instruction mnemonic '" + Mnemonic + "'",4504Op.getLocRange(), MatchingInlineAsm);4505}45064507unsigned NumSuccessfulMatches = llvm::count(Match, Match_Success);45084509// If matching was ambiguous and we had size information from the frontend,4510// try again with that. This handles cases like "movxz eax, m8/m16".4511if (UnsizedMemOp && NumSuccessfulMatches > 1 &&4512UnsizedMemOp->getMemFrontendSize()) {4513UnsizedMemOp->Mem.Size = UnsizedMemOp->getMemFrontendSize();4514unsigned M = MatchInstruction(4515Operands, Inst, ErrorInfo, MissingFeatures, MatchingInlineAsm,4516isParsingIntelSyntax());4517if (M == Match_Success)4518NumSuccessfulMatches = 1;45194520// Add a rewrite that encodes the size information we used from the4521// frontend.4522InstInfo->AsmRewrites->emplace_back(4523AOK_SizeDirective, UnsizedMemOp->getStartLoc(),4524/*Len=*/0, UnsizedMemOp->getMemFrontendSize());4525}45264527// If exactly one matched, then we treat that as a successful match (and the4528// instruction will already have been filled in correctly, since the failing4529// matches won't have modified it).4530if (NumSuccessfulMatches == 1) {4531if (!MatchingInlineAsm && validateInstruction(Inst, Operands))4532return true;4533// Some instructions need post-processing to, for example, tweak which4534// encoding is selected. Loop on it while changes happen so the individual4535// transformations can chain off each other.4536if (!MatchingInlineAsm)4537while (processInstruction(Inst, Operands))4538;4539Inst.setLoc(IDLoc);4540if (!MatchingInlineAsm)4541emitInstruction(Inst, Operands, Out);4542Opcode = Inst.getOpcode();4543return false;4544} else if (NumSuccessfulMatches > 1) {4545assert(UnsizedMemOp &&4546"multiple matches only possible with unsized memory operands");4547return Error(UnsizedMemOp->getStartLoc(),4548"ambiguous operand size for instruction '" + Mnemonic + "\'",4549UnsizedMemOp->getLocRange());4550}45514552// If one instruction matched as unsupported, report this as unsupported.4553if (llvm::count(Match, Match_Unsupported) == 1) {4554return Error(IDLoc, "unsupported instruction", EmptyRange,4555MatchingInlineAsm);4556}45574558// If one instruction matched with a missing feature, report this as a4559// missing feature.4560if (llvm::count(Match, Match_MissingFeature) == 1) {4561ErrorInfo = Match_MissingFeature;4562return ErrorMissingFeature(IDLoc, ErrorInfoMissingFeatures,4563MatchingInlineAsm);4564}45654566// If one instruction matched with an invalid operand, report this as an4567// operand failure.4568if (llvm::count(Match, Match_InvalidOperand) == 1) {4569return Error(IDLoc, "invalid operand for instruction", EmptyRange,4570MatchingInlineAsm);4571}45724573if (llvm::count(Match, Match_InvalidImmUnsignedi4) == 1) {4574SMLoc ErrorLoc = ((X86Operand &)*Operands[ErrorInfo]).getStartLoc();4575if (ErrorLoc == SMLoc())4576ErrorLoc = IDLoc;4577return Error(ErrorLoc, "immediate must be an integer in range [0, 15]",4578EmptyRange, MatchingInlineAsm);4579}45804581// If all of these were an outright failure, report it in a useless way.4582return Error(IDLoc, "unknown instruction mnemonic", EmptyRange,4583MatchingInlineAsm);4584}45854586bool X86AsmParser::OmitRegisterFromClobberLists(unsigned RegNo) {4587return X86MCRegisterClasses[X86::SEGMENT_REGRegClassID].contains(RegNo);4588}45894590bool X86AsmParser::ParseDirective(AsmToken DirectiveID) {4591MCAsmParser &Parser = getParser();4592StringRef IDVal = DirectiveID.getIdentifier();4593if (IDVal.starts_with(".arch"))4594return parseDirectiveArch();4595if (IDVal.starts_with(".code"))4596return ParseDirectiveCode(IDVal, DirectiveID.getLoc());4597else if (IDVal.starts_with(".att_syntax")) {4598if (getLexer().isNot(AsmToken::EndOfStatement)) {4599if (Parser.getTok().getString() == "prefix")4600Parser.Lex();4601else if (Parser.getTok().getString() == "noprefix")4602return Error(DirectiveID.getLoc(), "'.att_syntax noprefix' is not "4603"supported: registers must have a "4604"'%' prefix in .att_syntax");4605}4606getParser().setAssemblerDialect(0);4607return false;4608} else if (IDVal.starts_with(".intel_syntax")) {4609getParser().setAssemblerDialect(1);4610if (getLexer().isNot(AsmToken::EndOfStatement)) {4611if (Parser.getTok().getString() == "noprefix")4612Parser.Lex();4613else if (Parser.getTok().getString() == "prefix")4614return Error(DirectiveID.getLoc(), "'.intel_syntax prefix' is not "4615"supported: registers must not have "4616"a '%' prefix in .intel_syntax");4617}4618return false;4619} else if (IDVal == ".nops")4620return parseDirectiveNops(DirectiveID.getLoc());4621else if (IDVal == ".even")4622return parseDirectiveEven(DirectiveID.getLoc());4623else if (IDVal == ".cv_fpo_proc")4624return parseDirectiveFPOProc(DirectiveID.getLoc());4625else if (IDVal == ".cv_fpo_setframe")4626return parseDirectiveFPOSetFrame(DirectiveID.getLoc());4627else if (IDVal == ".cv_fpo_pushreg")4628return parseDirectiveFPOPushReg(DirectiveID.getLoc());4629else if (IDVal == ".cv_fpo_stackalloc")4630return parseDirectiveFPOStackAlloc(DirectiveID.getLoc());4631else if (IDVal == ".cv_fpo_stackalign")4632return parseDirectiveFPOStackAlign(DirectiveID.getLoc());4633else if (IDVal == ".cv_fpo_endprologue")4634return parseDirectiveFPOEndPrologue(DirectiveID.getLoc());4635else if (IDVal == ".cv_fpo_endproc")4636return parseDirectiveFPOEndProc(DirectiveID.getLoc());4637else if (IDVal == ".seh_pushreg" ||4638(Parser.isParsingMasm() && IDVal.equals_insensitive(".pushreg")))4639return parseDirectiveSEHPushReg(DirectiveID.getLoc());4640else if (IDVal == ".seh_setframe" ||4641(Parser.isParsingMasm() && IDVal.equals_insensitive(".setframe")))4642return parseDirectiveSEHSetFrame(DirectiveID.getLoc());4643else if (IDVal == ".seh_savereg" ||4644(Parser.isParsingMasm() && IDVal.equals_insensitive(".savereg")))4645return parseDirectiveSEHSaveReg(DirectiveID.getLoc());4646else if (IDVal == ".seh_savexmm" ||4647(Parser.isParsingMasm() && IDVal.equals_insensitive(".savexmm128")))4648return parseDirectiveSEHSaveXMM(DirectiveID.getLoc());4649else if (IDVal == ".seh_pushframe" ||4650(Parser.isParsingMasm() && IDVal.equals_insensitive(".pushframe")))4651return parseDirectiveSEHPushFrame(DirectiveID.getLoc());46524653return true;4654}46554656bool X86AsmParser::parseDirectiveArch() {4657// Ignore .arch for now.4658getParser().parseStringToEndOfStatement();4659return false;4660}46614662/// parseDirectiveNops4663/// ::= .nops size[, control]4664bool X86AsmParser::parseDirectiveNops(SMLoc L) {4665int64_t NumBytes = 0, Control = 0;4666SMLoc NumBytesLoc, ControlLoc;4667const MCSubtargetInfo& STI = getSTI();4668NumBytesLoc = getTok().getLoc();4669if (getParser().checkForValidSection() ||4670getParser().parseAbsoluteExpression(NumBytes))4671return true;46724673if (parseOptionalToken(AsmToken::Comma)) {4674ControlLoc = getTok().getLoc();4675if (getParser().parseAbsoluteExpression(Control))4676return true;4677}4678if (getParser().parseEOL())4679return true;46804681if (NumBytes <= 0) {4682Error(NumBytesLoc, "'.nops' directive with non-positive size");4683return false;4684}46854686if (Control < 0) {4687Error(ControlLoc, "'.nops' directive with negative NOP size");4688return false;4689}46904691/// Emit nops4692getParser().getStreamer().emitNops(NumBytes, Control, L, STI);46934694return false;4695}46964697/// parseDirectiveEven4698/// ::= .even4699bool X86AsmParser::parseDirectiveEven(SMLoc L) {4700if (parseEOL())4701return false;47024703const MCSection *Section = getStreamer().getCurrentSectionOnly();4704if (!Section) {4705getStreamer().initSections(false, getSTI());4706Section = getStreamer().getCurrentSectionOnly();4707}4708if (Section->useCodeAlign())4709getStreamer().emitCodeAlignment(Align(2), &getSTI(), 0);4710else4711getStreamer().emitValueToAlignment(Align(2), 0, 1, 0);4712return false;4713}47144715/// ParseDirectiveCode4716/// ::= .code16 | .code32 | .code644717bool X86AsmParser::ParseDirectiveCode(StringRef IDVal, SMLoc L) {4718MCAsmParser &Parser = getParser();4719Code16GCC = false;4720if (IDVal == ".code16") {4721Parser.Lex();4722if (!is16BitMode()) {4723SwitchMode(X86::Is16Bit);4724getParser().getStreamer().emitAssemblerFlag(MCAF_Code16);4725}4726} else if (IDVal == ".code16gcc") {4727// .code16gcc parses as if in 32-bit mode, but emits code in 16-bit mode.4728Parser.Lex();4729Code16GCC = true;4730if (!is16BitMode()) {4731SwitchMode(X86::Is16Bit);4732getParser().getStreamer().emitAssemblerFlag(MCAF_Code16);4733}4734} else if (IDVal == ".code32") {4735Parser.Lex();4736if (!is32BitMode()) {4737SwitchMode(X86::Is32Bit);4738getParser().getStreamer().emitAssemblerFlag(MCAF_Code32);4739}4740} else if (IDVal == ".code64") {4741Parser.Lex();4742if (!is64BitMode()) {4743SwitchMode(X86::Is64Bit);4744getParser().getStreamer().emitAssemblerFlag(MCAF_Code64);4745}4746} else {4747Error(L, "unknown directive " + IDVal);4748return false;4749}47504751return false;4752}47534754// .cv_fpo_proc foo4755bool X86AsmParser::parseDirectiveFPOProc(SMLoc L) {4756MCAsmParser &Parser = getParser();4757StringRef ProcName;4758int64_t ParamsSize;4759if (Parser.parseIdentifier(ProcName))4760return Parser.TokError("expected symbol name");4761if (Parser.parseIntToken(ParamsSize, "expected parameter byte count"))4762return true;4763if (!isUIntN(32, ParamsSize))4764return Parser.TokError("parameters size out of range");4765if (parseEOL())4766return true;4767MCSymbol *ProcSym = getContext().getOrCreateSymbol(ProcName);4768return getTargetStreamer().emitFPOProc(ProcSym, ParamsSize, L);4769}47704771// .cv_fpo_setframe ebp4772bool X86AsmParser::parseDirectiveFPOSetFrame(SMLoc L) {4773MCRegister Reg;4774SMLoc DummyLoc;4775if (parseRegister(Reg, DummyLoc, DummyLoc) || parseEOL())4776return true;4777return getTargetStreamer().emitFPOSetFrame(Reg, L);4778}47794780// .cv_fpo_pushreg ebx4781bool X86AsmParser::parseDirectiveFPOPushReg(SMLoc L) {4782MCRegister Reg;4783SMLoc DummyLoc;4784if (parseRegister(Reg, DummyLoc, DummyLoc) || parseEOL())4785return true;4786return getTargetStreamer().emitFPOPushReg(Reg, L);4787}47884789// .cv_fpo_stackalloc 204790bool X86AsmParser::parseDirectiveFPOStackAlloc(SMLoc L) {4791MCAsmParser &Parser = getParser();4792int64_t Offset;4793if (Parser.parseIntToken(Offset, "expected offset") || parseEOL())4794return true;4795return getTargetStreamer().emitFPOStackAlloc(Offset, L);4796}47974798// .cv_fpo_stackalign 84799bool X86AsmParser::parseDirectiveFPOStackAlign(SMLoc L) {4800MCAsmParser &Parser = getParser();4801int64_t Offset;4802if (Parser.parseIntToken(Offset, "expected offset") || parseEOL())4803return true;4804return getTargetStreamer().emitFPOStackAlign(Offset, L);4805}48064807// .cv_fpo_endprologue4808bool X86AsmParser::parseDirectiveFPOEndPrologue(SMLoc L) {4809MCAsmParser &Parser = getParser();4810if (Parser.parseEOL())4811return true;4812return getTargetStreamer().emitFPOEndPrologue(L);4813}48144815// .cv_fpo_endproc4816bool X86AsmParser::parseDirectiveFPOEndProc(SMLoc L) {4817MCAsmParser &Parser = getParser();4818if (Parser.parseEOL())4819return true;4820return getTargetStreamer().emitFPOEndProc(L);4821}48224823bool X86AsmParser::parseSEHRegisterNumber(unsigned RegClassID,4824MCRegister &RegNo) {4825SMLoc startLoc = getLexer().getLoc();4826const MCRegisterInfo *MRI = getContext().getRegisterInfo();48274828// Try parsing the argument as a register first.4829if (getLexer().getTok().isNot(AsmToken::Integer)) {4830SMLoc endLoc;4831if (parseRegister(RegNo, startLoc, endLoc))4832return true;48334834if (!X86MCRegisterClasses[RegClassID].contains(RegNo)) {4835return Error(startLoc,4836"register is not supported for use with this directive");4837}4838} else {4839// Otherwise, an integer number matching the encoding of the desired4840// register may appear.4841int64_t EncodedReg;4842if (getParser().parseAbsoluteExpression(EncodedReg))4843return true;48444845// The SEH register number is the same as the encoding register number. Map4846// from the encoding back to the LLVM register number.4847RegNo = 0;4848for (MCPhysReg Reg : X86MCRegisterClasses[RegClassID]) {4849if (MRI->getEncodingValue(Reg) == EncodedReg) {4850RegNo = Reg;4851break;4852}4853}4854if (RegNo == 0) {4855return Error(startLoc,4856"incorrect register number for use with this directive");4857}4858}48594860return false;4861}48624863bool X86AsmParser::parseDirectiveSEHPushReg(SMLoc Loc) {4864MCRegister Reg;4865if (parseSEHRegisterNumber(X86::GR64RegClassID, Reg))4866return true;48674868if (getLexer().isNot(AsmToken::EndOfStatement))4869return TokError("expected end of directive");48704871getParser().Lex();4872getStreamer().emitWinCFIPushReg(Reg, Loc);4873return false;4874}48754876bool X86AsmParser::parseDirectiveSEHSetFrame(SMLoc Loc) {4877MCRegister Reg;4878int64_t Off;4879if (parseSEHRegisterNumber(X86::GR64RegClassID, Reg))4880return true;4881if (getLexer().isNot(AsmToken::Comma))4882return TokError("you must specify a stack pointer offset");48834884getParser().Lex();4885if (getParser().parseAbsoluteExpression(Off))4886return true;48874888if (getLexer().isNot(AsmToken::EndOfStatement))4889return TokError("expected end of directive");48904891getParser().Lex();4892getStreamer().emitWinCFISetFrame(Reg, Off, Loc);4893return false;4894}48954896bool X86AsmParser::parseDirectiveSEHSaveReg(SMLoc Loc) {4897MCRegister Reg;4898int64_t Off;4899if (parseSEHRegisterNumber(X86::GR64RegClassID, Reg))4900return true;4901if (getLexer().isNot(AsmToken::Comma))4902return TokError("you must specify an offset on the stack");49034904getParser().Lex();4905if (getParser().parseAbsoluteExpression(Off))4906return true;49074908if (getLexer().isNot(AsmToken::EndOfStatement))4909return TokError("expected end of directive");49104911getParser().Lex();4912getStreamer().emitWinCFISaveReg(Reg, Off, Loc);4913return false;4914}49154916bool X86AsmParser::parseDirectiveSEHSaveXMM(SMLoc Loc) {4917MCRegister Reg;4918int64_t Off;4919if (parseSEHRegisterNumber(X86::VR128XRegClassID, Reg))4920return true;4921if (getLexer().isNot(AsmToken::Comma))4922return TokError("you must specify an offset on the stack");49234924getParser().Lex();4925if (getParser().parseAbsoluteExpression(Off))4926return true;49274928if (getLexer().isNot(AsmToken::EndOfStatement))4929return TokError("expected end of directive");49304931getParser().Lex();4932getStreamer().emitWinCFISaveXMM(Reg, Off, Loc);4933return false;4934}49354936bool X86AsmParser::parseDirectiveSEHPushFrame(SMLoc Loc) {4937bool Code = false;4938StringRef CodeID;4939if (getLexer().is(AsmToken::At)) {4940SMLoc startLoc = getLexer().getLoc();4941getParser().Lex();4942if (!getParser().parseIdentifier(CodeID)) {4943if (CodeID != "code")4944return Error(startLoc, "expected @code");4945Code = true;4946}4947}49484949if (getLexer().isNot(AsmToken::EndOfStatement))4950return TokError("expected end of directive");49514952getParser().Lex();4953getStreamer().emitWinCFIPushFrame(Code, Loc);4954return false;4955}49564957// Force static initialization.4958extern "C" LLVM_EXTERNAL_VISIBILITY void LLVMInitializeX86AsmParser() {4959RegisterMCAsmParser<X86AsmParser> X(getTheX86_32Target());4960RegisterMCAsmParser<X86AsmParser> Y(getTheX86_64Target());4961}49624963#define GET_MATCHER_IMPLEMENTATION4964#include "X86GenAsmMatcher.inc"496549664967