109467b48Spatrick //===-- X86AsmParser.cpp - Parse X86 assembly to MCInst instructions ------===//
209467b48Spatrick //
309467b48Spatrick // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
409467b48Spatrick // See https://llvm.org/LICENSE.txt for license information.
509467b48Spatrick // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
609467b48Spatrick //
709467b48Spatrick //===----------------------------------------------------------------------===//
809467b48Spatrick
909467b48Spatrick #include "MCTargetDesc/X86BaseInfo.h"
1009467b48Spatrick #include "MCTargetDesc/X86IntelInstPrinter.h"
1109467b48Spatrick #include "MCTargetDesc/X86MCExpr.h"
12*d415bd75Srobert #include "MCTargetDesc/X86MCTargetDesc.h"
1309467b48Spatrick #include "MCTargetDesc/X86TargetStreamer.h"
1409467b48Spatrick #include "TargetInfo/X86TargetInfo.h"
1509467b48Spatrick #include "X86AsmParserCommon.h"
1609467b48Spatrick #include "X86Operand.h"
1709467b48Spatrick #include "llvm/ADT/STLExtras.h"
1809467b48Spatrick #include "llvm/ADT/SmallString.h"
1909467b48Spatrick #include "llvm/ADT/SmallVector.h"
2009467b48Spatrick #include "llvm/ADT/StringSwitch.h"
2109467b48Spatrick #include "llvm/ADT/Twine.h"
2209467b48Spatrick #include "llvm/MC/MCContext.h"
2309467b48Spatrick #include "llvm/MC/MCExpr.h"
2409467b48Spatrick #include "llvm/MC/MCInst.h"
2509467b48Spatrick #include "llvm/MC/MCInstrInfo.h"
2609467b48Spatrick #include "llvm/MC/MCParser/MCAsmLexer.h"
2709467b48Spatrick #include "llvm/MC/MCParser/MCAsmParser.h"
2809467b48Spatrick #include "llvm/MC/MCParser/MCParsedAsmOperand.h"
2909467b48Spatrick #include "llvm/MC/MCParser/MCTargetAsmParser.h"
3009467b48Spatrick #include "llvm/MC/MCRegisterInfo.h"
3109467b48Spatrick #include "llvm/MC/MCSection.h"
3209467b48Spatrick #include "llvm/MC/MCStreamer.h"
3309467b48Spatrick #include "llvm/MC/MCSubtargetInfo.h"
3409467b48Spatrick #include "llvm/MC/MCSymbol.h"
35*d415bd75Srobert #include "llvm/MC/TargetRegistry.h"
36097a140dSpatrick #include "llvm/Support/CommandLine.h"
3773471bf0Spatrick #include "llvm/Support/Compiler.h"
3809467b48Spatrick #include "llvm/Support/SourceMgr.h"
3909467b48Spatrick #include "llvm/Support/raw_ostream.h"
4009467b48Spatrick #include <algorithm>
4109467b48Spatrick #include <memory>
4209467b48Spatrick
4309467b48Spatrick using namespace llvm;
4409467b48Spatrick
45097a140dSpatrick static cl::opt<bool> LVIInlineAsmHardening(
46097a140dSpatrick "x86-experimental-lvi-inline-asm-hardening",
47097a140dSpatrick cl::desc("Harden inline assembly code that may be vulnerable to Load Value"
48097a140dSpatrick " Injection (LVI). This feature is experimental."), cl::Hidden);
49097a140dSpatrick
checkScale(unsigned Scale,StringRef & ErrMsg)5009467b48Spatrick static bool checkScale(unsigned Scale, StringRef &ErrMsg) {
5109467b48Spatrick if (Scale != 1 && Scale != 2 && Scale != 4 && Scale != 8) {
5209467b48Spatrick ErrMsg = "scale factor in address must be 1, 2, 4 or 8";
5309467b48Spatrick return true;
5409467b48Spatrick }
5509467b48Spatrick return false;
5609467b48Spatrick }
5709467b48Spatrick
5809467b48Spatrick namespace {
5909467b48Spatrick
6009467b48Spatrick static const char OpPrecedence[] = {
6109467b48Spatrick 0, // IC_OR
6209467b48Spatrick 1, // IC_XOR
6309467b48Spatrick 2, // IC_AND
6473471bf0Spatrick 4, // IC_LSHIFT
6573471bf0Spatrick 4, // IC_RSHIFT
6673471bf0Spatrick 5, // IC_PLUS
6773471bf0Spatrick 5, // IC_MINUS
6873471bf0Spatrick 6, // IC_MULTIPLY
6973471bf0Spatrick 6, // IC_DIVIDE
7073471bf0Spatrick 6, // IC_MOD
7173471bf0Spatrick 7, // IC_NOT
7273471bf0Spatrick 8, // IC_NEG
7373471bf0Spatrick 9, // IC_RPAREN
7473471bf0Spatrick 10, // IC_LPAREN
7509467b48Spatrick 0, // IC_IMM
7673471bf0Spatrick 0, // IC_REGISTER
7773471bf0Spatrick 3, // IC_EQ
7873471bf0Spatrick 3, // IC_NE
7973471bf0Spatrick 3, // IC_LT
8073471bf0Spatrick 3, // IC_LE
8173471bf0Spatrick 3, // IC_GT
8273471bf0Spatrick 3 // IC_GE
8309467b48Spatrick };
8409467b48Spatrick
8509467b48Spatrick class X86AsmParser : public MCTargetAsmParser {
8609467b48Spatrick ParseInstructionInfo *InstInfo;
8709467b48Spatrick bool Code16GCC;
8873471bf0Spatrick unsigned ForcedDataPrefix = 0;
8909467b48Spatrick
9009467b48Spatrick enum VEXEncoding {
9109467b48Spatrick VEXEncoding_Default,
92097a140dSpatrick VEXEncoding_VEX,
9373471bf0Spatrick VEXEncoding_VEX2,
9409467b48Spatrick VEXEncoding_VEX3,
9509467b48Spatrick VEXEncoding_EVEX,
9609467b48Spatrick };
9709467b48Spatrick
9809467b48Spatrick VEXEncoding ForcedVEXEncoding = VEXEncoding_Default;
9909467b48Spatrick
10073471bf0Spatrick enum DispEncoding {
10173471bf0Spatrick DispEncoding_Default,
10273471bf0Spatrick DispEncoding_Disp8,
10373471bf0Spatrick DispEncoding_Disp32,
10473471bf0Spatrick };
10573471bf0Spatrick
10673471bf0Spatrick DispEncoding ForcedDispEncoding = DispEncoding_Default;
10773471bf0Spatrick
10809467b48Spatrick private:
consumeToken()10909467b48Spatrick SMLoc consumeToken() {
11009467b48Spatrick MCAsmParser &Parser = getParser();
11109467b48Spatrick SMLoc Result = Parser.getTok().getLoc();
11209467b48Spatrick Parser.Lex();
11309467b48Spatrick return Result;
11409467b48Spatrick }
11509467b48Spatrick
getTargetStreamer()11609467b48Spatrick X86TargetStreamer &getTargetStreamer() {
11709467b48Spatrick assert(getParser().getStreamer().getTargetStreamer() &&
11809467b48Spatrick "do not have a target streamer");
11909467b48Spatrick MCTargetStreamer &TS = *getParser().getStreamer().getTargetStreamer();
12009467b48Spatrick return static_cast<X86TargetStreamer &>(TS);
12109467b48Spatrick }
12209467b48Spatrick
MatchInstruction(const OperandVector & Operands,MCInst & Inst,uint64_t & ErrorInfo,FeatureBitset & MissingFeatures,bool matchingInlineAsm,unsigned VariantID=0)12309467b48Spatrick unsigned MatchInstruction(const OperandVector &Operands, MCInst &Inst,
12409467b48Spatrick uint64_t &ErrorInfo, FeatureBitset &MissingFeatures,
12509467b48Spatrick bool matchingInlineAsm, unsigned VariantID = 0) {
12609467b48Spatrick // In Code16GCC mode, match as 32-bit.
12709467b48Spatrick if (Code16GCC)
128*d415bd75Srobert SwitchMode(X86::Is32Bit);
12909467b48Spatrick unsigned rv = MatchInstructionImpl(Operands, Inst, ErrorInfo,
13009467b48Spatrick MissingFeatures, matchingInlineAsm,
13109467b48Spatrick VariantID);
13209467b48Spatrick if (Code16GCC)
133*d415bd75Srobert SwitchMode(X86::Is16Bit);
13409467b48Spatrick return rv;
13509467b48Spatrick }
13609467b48Spatrick
13709467b48Spatrick enum InfixCalculatorTok {
13809467b48Spatrick IC_OR = 0,
13909467b48Spatrick IC_XOR,
14009467b48Spatrick IC_AND,
14109467b48Spatrick IC_LSHIFT,
14209467b48Spatrick IC_RSHIFT,
14309467b48Spatrick IC_PLUS,
14409467b48Spatrick IC_MINUS,
14509467b48Spatrick IC_MULTIPLY,
14609467b48Spatrick IC_DIVIDE,
14709467b48Spatrick IC_MOD,
14809467b48Spatrick IC_NOT,
14909467b48Spatrick IC_NEG,
15009467b48Spatrick IC_RPAREN,
15109467b48Spatrick IC_LPAREN,
15209467b48Spatrick IC_IMM,
15373471bf0Spatrick IC_REGISTER,
15473471bf0Spatrick IC_EQ,
15573471bf0Spatrick IC_NE,
15673471bf0Spatrick IC_LT,
15773471bf0Spatrick IC_LE,
15873471bf0Spatrick IC_GT,
15973471bf0Spatrick IC_GE
16009467b48Spatrick };
16109467b48Spatrick
16209467b48Spatrick enum IntelOperatorKind {
16309467b48Spatrick IOK_INVALID = 0,
16409467b48Spatrick IOK_LENGTH,
16509467b48Spatrick IOK_SIZE,
16609467b48Spatrick IOK_TYPE,
16709467b48Spatrick };
16809467b48Spatrick
16973471bf0Spatrick enum MasmOperatorKind {
17073471bf0Spatrick MOK_INVALID = 0,
17173471bf0Spatrick MOK_LENGTHOF,
17273471bf0Spatrick MOK_SIZEOF,
17373471bf0Spatrick MOK_TYPE,
17473471bf0Spatrick };
17573471bf0Spatrick
17609467b48Spatrick class InfixCalculator {
17709467b48Spatrick typedef std::pair< InfixCalculatorTok, int64_t > ICToken;
17809467b48Spatrick SmallVector<InfixCalculatorTok, 4> InfixOperatorStack;
17909467b48Spatrick SmallVector<ICToken, 4> PostfixStack;
18009467b48Spatrick
isUnaryOperator(InfixCalculatorTok Op) const18173471bf0Spatrick bool isUnaryOperator(InfixCalculatorTok Op) const {
18209467b48Spatrick return Op == IC_NEG || Op == IC_NOT;
18309467b48Spatrick }
18409467b48Spatrick
18509467b48Spatrick public:
popOperand()18609467b48Spatrick int64_t popOperand() {
18709467b48Spatrick assert (!PostfixStack.empty() && "Poped an empty stack!");
18809467b48Spatrick ICToken Op = PostfixStack.pop_back_val();
18909467b48Spatrick if (!(Op.first == IC_IMM || Op.first == IC_REGISTER))
19009467b48Spatrick return -1; // The invalid Scale value will be caught later by checkScale
19109467b48Spatrick return Op.second;
19209467b48Spatrick }
pushOperand(InfixCalculatorTok Op,int64_t Val=0)19309467b48Spatrick void pushOperand(InfixCalculatorTok Op, int64_t Val = 0) {
19409467b48Spatrick assert ((Op == IC_IMM || Op == IC_REGISTER) &&
19509467b48Spatrick "Unexpected operand!");
19609467b48Spatrick PostfixStack.push_back(std::make_pair(Op, Val));
19709467b48Spatrick }
19809467b48Spatrick
popOperator()19909467b48Spatrick void popOperator() { InfixOperatorStack.pop_back(); }
pushOperator(InfixCalculatorTok Op)20009467b48Spatrick void pushOperator(InfixCalculatorTok Op) {
20109467b48Spatrick // Push the new operator if the stack is empty.
20209467b48Spatrick if (InfixOperatorStack.empty()) {
20309467b48Spatrick InfixOperatorStack.push_back(Op);
20409467b48Spatrick return;
20509467b48Spatrick }
20609467b48Spatrick
20709467b48Spatrick // Push the new operator if it has a higher precedence than the operator
20809467b48Spatrick // on the top of the stack or the operator on the top of the stack is a
20909467b48Spatrick // left parentheses.
21009467b48Spatrick unsigned Idx = InfixOperatorStack.size() - 1;
21109467b48Spatrick InfixCalculatorTok StackOp = InfixOperatorStack[Idx];
21209467b48Spatrick if (OpPrecedence[Op] > OpPrecedence[StackOp] || StackOp == IC_LPAREN) {
21309467b48Spatrick InfixOperatorStack.push_back(Op);
21409467b48Spatrick return;
21509467b48Spatrick }
21609467b48Spatrick
21709467b48Spatrick // The operator on the top of the stack has higher precedence than the
21809467b48Spatrick // new operator.
21909467b48Spatrick unsigned ParenCount = 0;
220*d415bd75Srobert while (true) {
22109467b48Spatrick // Nothing to process.
22209467b48Spatrick if (InfixOperatorStack.empty())
22309467b48Spatrick break;
22409467b48Spatrick
22509467b48Spatrick Idx = InfixOperatorStack.size() - 1;
22609467b48Spatrick StackOp = InfixOperatorStack[Idx];
22709467b48Spatrick if (!(OpPrecedence[StackOp] >= OpPrecedence[Op] || ParenCount))
22809467b48Spatrick break;
22909467b48Spatrick
23009467b48Spatrick // If we have an even parentheses count and we see a left parentheses,
23109467b48Spatrick // then stop processing.
23209467b48Spatrick if (!ParenCount && StackOp == IC_LPAREN)
23309467b48Spatrick break;
23409467b48Spatrick
23509467b48Spatrick if (StackOp == IC_RPAREN) {
23609467b48Spatrick ++ParenCount;
23709467b48Spatrick InfixOperatorStack.pop_back();
23809467b48Spatrick } else if (StackOp == IC_LPAREN) {
23909467b48Spatrick --ParenCount;
24009467b48Spatrick InfixOperatorStack.pop_back();
24109467b48Spatrick } else {
24209467b48Spatrick InfixOperatorStack.pop_back();
24309467b48Spatrick PostfixStack.push_back(std::make_pair(StackOp, 0));
24409467b48Spatrick }
24509467b48Spatrick }
24609467b48Spatrick // Push the new operator.
24709467b48Spatrick InfixOperatorStack.push_back(Op);
24809467b48Spatrick }
24909467b48Spatrick
execute()25009467b48Spatrick int64_t execute() {
25109467b48Spatrick // Push any remaining operators onto the postfix stack.
25209467b48Spatrick while (!InfixOperatorStack.empty()) {
25309467b48Spatrick InfixCalculatorTok StackOp = InfixOperatorStack.pop_back_val();
25409467b48Spatrick if (StackOp != IC_LPAREN && StackOp != IC_RPAREN)
25509467b48Spatrick PostfixStack.push_back(std::make_pair(StackOp, 0));
25609467b48Spatrick }
25709467b48Spatrick
25809467b48Spatrick if (PostfixStack.empty())
25909467b48Spatrick return 0;
26009467b48Spatrick
26109467b48Spatrick SmallVector<ICToken, 16> OperandStack;
26209467b48Spatrick for (unsigned i = 0, e = PostfixStack.size(); i != e; ++i) {
26309467b48Spatrick ICToken Op = PostfixStack[i];
26409467b48Spatrick if (Op.first == IC_IMM || Op.first == IC_REGISTER) {
26509467b48Spatrick OperandStack.push_back(Op);
26609467b48Spatrick } else if (isUnaryOperator(Op.first)) {
26709467b48Spatrick assert (OperandStack.size() > 0 && "Too few operands.");
26809467b48Spatrick ICToken Operand = OperandStack.pop_back_val();
26909467b48Spatrick assert (Operand.first == IC_IMM &&
27009467b48Spatrick "Unary operation with a register!");
27109467b48Spatrick switch (Op.first) {
27209467b48Spatrick default:
27309467b48Spatrick report_fatal_error("Unexpected operator!");
27409467b48Spatrick break;
27509467b48Spatrick case IC_NEG:
27609467b48Spatrick OperandStack.push_back(std::make_pair(IC_IMM, -Operand.second));
27709467b48Spatrick break;
27809467b48Spatrick case IC_NOT:
27909467b48Spatrick OperandStack.push_back(std::make_pair(IC_IMM, ~Operand.second));
28009467b48Spatrick break;
28109467b48Spatrick }
28209467b48Spatrick } else {
28309467b48Spatrick assert (OperandStack.size() > 1 && "Too few operands.");
28409467b48Spatrick int64_t Val;
28509467b48Spatrick ICToken Op2 = OperandStack.pop_back_val();
28609467b48Spatrick ICToken Op1 = OperandStack.pop_back_val();
28709467b48Spatrick switch (Op.first) {
28809467b48Spatrick default:
28909467b48Spatrick report_fatal_error("Unexpected operator!");
29009467b48Spatrick break;
29109467b48Spatrick case IC_PLUS:
29209467b48Spatrick Val = Op1.second + Op2.second;
29309467b48Spatrick OperandStack.push_back(std::make_pair(IC_IMM, Val));
29409467b48Spatrick break;
29509467b48Spatrick case IC_MINUS:
29609467b48Spatrick Val = Op1.second - Op2.second;
29709467b48Spatrick OperandStack.push_back(std::make_pair(IC_IMM, Val));
29809467b48Spatrick break;
29909467b48Spatrick case IC_MULTIPLY:
30009467b48Spatrick assert (Op1.first == IC_IMM && Op2.first == IC_IMM &&
30109467b48Spatrick "Multiply operation with an immediate and a register!");
30209467b48Spatrick Val = Op1.second * Op2.second;
30309467b48Spatrick OperandStack.push_back(std::make_pair(IC_IMM, Val));
30409467b48Spatrick break;
30509467b48Spatrick case IC_DIVIDE:
30609467b48Spatrick assert (Op1.first == IC_IMM && Op2.first == IC_IMM &&
30709467b48Spatrick "Divide operation with an immediate and a register!");
30809467b48Spatrick assert (Op2.second != 0 && "Division by zero!");
30909467b48Spatrick Val = Op1.second / Op2.second;
31009467b48Spatrick OperandStack.push_back(std::make_pair(IC_IMM, Val));
31109467b48Spatrick break;
31209467b48Spatrick case IC_MOD:
31309467b48Spatrick assert (Op1.first == IC_IMM && Op2.first == IC_IMM &&
31409467b48Spatrick "Modulo operation with an immediate and a register!");
31509467b48Spatrick Val = Op1.second % Op2.second;
31609467b48Spatrick OperandStack.push_back(std::make_pair(IC_IMM, Val));
31709467b48Spatrick break;
31809467b48Spatrick case IC_OR:
31909467b48Spatrick assert (Op1.first == IC_IMM && Op2.first == IC_IMM &&
32009467b48Spatrick "Or operation with an immediate and a register!");
32109467b48Spatrick Val = Op1.second | Op2.second;
32209467b48Spatrick OperandStack.push_back(std::make_pair(IC_IMM, Val));
32309467b48Spatrick break;
32409467b48Spatrick case IC_XOR:
32509467b48Spatrick assert(Op1.first == IC_IMM && Op2.first == IC_IMM &&
32609467b48Spatrick "Xor operation with an immediate and a register!");
32709467b48Spatrick Val = Op1.second ^ Op2.second;
32809467b48Spatrick OperandStack.push_back(std::make_pair(IC_IMM, Val));
32909467b48Spatrick break;
33009467b48Spatrick case IC_AND:
33109467b48Spatrick assert (Op1.first == IC_IMM && Op2.first == IC_IMM &&
33209467b48Spatrick "And operation with an immediate and a register!");
33309467b48Spatrick Val = Op1.second & Op2.second;
33409467b48Spatrick OperandStack.push_back(std::make_pair(IC_IMM, Val));
33509467b48Spatrick break;
33609467b48Spatrick case IC_LSHIFT:
33709467b48Spatrick assert (Op1.first == IC_IMM && Op2.first == IC_IMM &&
33809467b48Spatrick "Left shift operation with an immediate and a register!");
33909467b48Spatrick Val = Op1.second << Op2.second;
34009467b48Spatrick OperandStack.push_back(std::make_pair(IC_IMM, Val));
34109467b48Spatrick break;
34209467b48Spatrick case IC_RSHIFT:
34309467b48Spatrick assert (Op1.first == IC_IMM && Op2.first == IC_IMM &&
34409467b48Spatrick "Right shift operation with an immediate and a register!");
34509467b48Spatrick Val = Op1.second >> Op2.second;
34609467b48Spatrick OperandStack.push_back(std::make_pair(IC_IMM, Val));
34709467b48Spatrick break;
34873471bf0Spatrick case IC_EQ:
34973471bf0Spatrick assert(Op1.first == IC_IMM && Op2.first == IC_IMM &&
35073471bf0Spatrick "Equals operation with an immediate and a register!");
35173471bf0Spatrick Val = (Op1.second == Op2.second) ? -1 : 0;
35273471bf0Spatrick OperandStack.push_back(std::make_pair(IC_IMM, Val));
35373471bf0Spatrick break;
35473471bf0Spatrick case IC_NE:
35573471bf0Spatrick assert(Op1.first == IC_IMM && Op2.first == IC_IMM &&
35673471bf0Spatrick "Not-equals operation with an immediate and a register!");
35773471bf0Spatrick Val = (Op1.second != Op2.second) ? -1 : 0;
35873471bf0Spatrick OperandStack.push_back(std::make_pair(IC_IMM, Val));
35973471bf0Spatrick break;
36073471bf0Spatrick case IC_LT:
36173471bf0Spatrick assert(Op1.first == IC_IMM && Op2.first == IC_IMM &&
36273471bf0Spatrick "Less-than operation with an immediate and a register!");
36373471bf0Spatrick Val = (Op1.second < Op2.second) ? -1 : 0;
36473471bf0Spatrick OperandStack.push_back(std::make_pair(IC_IMM, Val));
36573471bf0Spatrick break;
36673471bf0Spatrick case IC_LE:
36773471bf0Spatrick assert(Op1.first == IC_IMM && Op2.first == IC_IMM &&
36873471bf0Spatrick "Less-than-or-equal operation with an immediate and a "
36973471bf0Spatrick "register!");
37073471bf0Spatrick Val = (Op1.second <= Op2.second) ? -1 : 0;
37173471bf0Spatrick OperandStack.push_back(std::make_pair(IC_IMM, Val));
37273471bf0Spatrick break;
37373471bf0Spatrick case IC_GT:
37473471bf0Spatrick assert(Op1.first == IC_IMM && Op2.first == IC_IMM &&
37573471bf0Spatrick "Greater-than operation with an immediate and a register!");
37673471bf0Spatrick Val = (Op1.second > Op2.second) ? -1 : 0;
37773471bf0Spatrick OperandStack.push_back(std::make_pair(IC_IMM, Val));
37873471bf0Spatrick break;
37973471bf0Spatrick case IC_GE:
38073471bf0Spatrick assert(Op1.first == IC_IMM && Op2.first == IC_IMM &&
38173471bf0Spatrick "Greater-than-or-equal operation with an immediate and a "
38273471bf0Spatrick "register!");
38373471bf0Spatrick Val = (Op1.second >= Op2.second) ? -1 : 0;
38473471bf0Spatrick OperandStack.push_back(std::make_pair(IC_IMM, Val));
38573471bf0Spatrick break;
38609467b48Spatrick }
38709467b48Spatrick }
38809467b48Spatrick }
38909467b48Spatrick assert (OperandStack.size() == 1 && "Expected a single result.");
39009467b48Spatrick return OperandStack.pop_back_val().second;
39109467b48Spatrick }
39209467b48Spatrick };
39309467b48Spatrick
39409467b48Spatrick enum IntelExprState {
39509467b48Spatrick IES_INIT,
39609467b48Spatrick IES_OR,
39709467b48Spatrick IES_XOR,
39809467b48Spatrick IES_AND,
39973471bf0Spatrick IES_EQ,
40073471bf0Spatrick IES_NE,
40173471bf0Spatrick IES_LT,
40273471bf0Spatrick IES_LE,
40373471bf0Spatrick IES_GT,
40473471bf0Spatrick IES_GE,
40509467b48Spatrick IES_LSHIFT,
40609467b48Spatrick IES_RSHIFT,
40709467b48Spatrick IES_PLUS,
40809467b48Spatrick IES_MINUS,
40909467b48Spatrick IES_OFFSET,
410097a140dSpatrick IES_CAST,
41109467b48Spatrick IES_NOT,
41209467b48Spatrick IES_MULTIPLY,
41309467b48Spatrick IES_DIVIDE,
41409467b48Spatrick IES_MOD,
41509467b48Spatrick IES_LBRAC,
41609467b48Spatrick IES_RBRAC,
41709467b48Spatrick IES_LPAREN,
41809467b48Spatrick IES_RPAREN,
41909467b48Spatrick IES_REGISTER,
42009467b48Spatrick IES_INTEGER,
42109467b48Spatrick IES_IDENTIFIER,
42209467b48Spatrick IES_ERROR
42309467b48Spatrick };
42409467b48Spatrick
42509467b48Spatrick class IntelExprStateMachine {
426*d415bd75Srobert IntelExprState State = IES_INIT, PrevState = IES_ERROR;
427*d415bd75Srobert unsigned BaseReg = 0, IndexReg = 0, TmpReg = 0, Scale = 0;
428*d415bd75Srobert int64_t Imm = 0;
429*d415bd75Srobert const MCExpr *Sym = nullptr;
43009467b48Spatrick StringRef SymName;
43109467b48Spatrick InfixCalculator IC;
43209467b48Spatrick InlineAsmIdentifierInfo Info;
433*d415bd75Srobert short BracCount = 0;
434*d415bd75Srobert bool MemExpr = false;
435*d415bd75Srobert bool OffsetOperator = false;
436*d415bd75Srobert bool AttachToOperandIdx = false;
437*d415bd75Srobert bool IsPIC = false;
43809467b48Spatrick SMLoc OffsetOperatorLoc;
43973471bf0Spatrick AsmTypeInfo CurType;
44009467b48Spatrick
setSymRef(const MCExpr * Val,StringRef ID,StringRef & ErrMsg)44109467b48Spatrick bool setSymRef(const MCExpr *Val, StringRef ID, StringRef &ErrMsg) {
44209467b48Spatrick if (Sym) {
44309467b48Spatrick ErrMsg = "cannot use more than one symbol in memory operand";
44409467b48Spatrick return true;
44509467b48Spatrick }
44609467b48Spatrick Sym = Val;
44709467b48Spatrick SymName = ID;
44809467b48Spatrick return false;
44909467b48Spatrick }
45009467b48Spatrick
45109467b48Spatrick public:
452*d415bd75Srobert IntelExprStateMachine() = default;
45309467b48Spatrick
addImm(int64_t imm)45409467b48Spatrick void addImm(int64_t imm) { Imm += imm; }
getBracCount() const45573471bf0Spatrick short getBracCount() const { return BracCount; }
isMemExpr() const45673471bf0Spatrick bool isMemExpr() const { return MemExpr; }
isOffsetOperator() const45773471bf0Spatrick bool isOffsetOperator() const { return OffsetOperator; }
getOffsetLoc() const45873471bf0Spatrick SMLoc getOffsetLoc() const { return OffsetOperatorLoc; }
getBaseReg() const45973471bf0Spatrick unsigned getBaseReg() const { return BaseReg; }
getIndexReg() const46073471bf0Spatrick unsigned getIndexReg() const { return IndexReg; }
getScale() const46173471bf0Spatrick unsigned getScale() const { return Scale; }
getSym() const46273471bf0Spatrick const MCExpr *getSym() const { return Sym; }
getSymName() const46373471bf0Spatrick StringRef getSymName() const { return SymName; }
getType() const46473471bf0Spatrick StringRef getType() const { return CurType.Name; }
getSize() const46573471bf0Spatrick unsigned getSize() const { return CurType.Size; }
getElementSize() const46673471bf0Spatrick unsigned getElementSize() const { return CurType.ElementSize; }
getLength() const46773471bf0Spatrick unsigned getLength() const { return CurType.Length; }
getImm()46809467b48Spatrick int64_t getImm() { return Imm + IC.execute(); }
isValidEndState() const46973471bf0Spatrick bool isValidEndState() const {
47009467b48Spatrick return State == IES_RBRAC || State == IES_INTEGER;
47109467b48Spatrick }
472*d415bd75Srobert
473*d415bd75Srobert // Is the intel expression appended after an operand index.
474*d415bd75Srobert // [OperandIdx][Intel Expression]
475*d415bd75Srobert // This is neccessary for checking if it is an independent
476*d415bd75Srobert // intel expression at back end when parse inline asm.
setAppendAfterOperand()477*d415bd75Srobert void setAppendAfterOperand() { AttachToOperandIdx = true; }
478*d415bd75Srobert
isPIC() const479*d415bd75Srobert bool isPIC() const { return IsPIC; }
setPIC()480*d415bd75Srobert void setPIC() { IsPIC = true; }
481*d415bd75Srobert
hadError() const48273471bf0Spatrick bool hadError() const { return State == IES_ERROR; }
getIdentifierInfo() const48373471bf0Spatrick const InlineAsmIdentifierInfo &getIdentifierInfo() const { return Info; }
48409467b48Spatrick
regsUseUpError(StringRef & ErrMsg)485*d415bd75Srobert bool regsUseUpError(StringRef &ErrMsg) {
486*d415bd75Srobert // This case mostly happen in inline asm, e.g. Arr[BaseReg + IndexReg]
487*d415bd75Srobert // can not intruduce additional register in inline asm in PIC model.
488*d415bd75Srobert if (IsPIC && AttachToOperandIdx)
489*d415bd75Srobert ErrMsg = "Don't use 2 or more regs for mem offset in PIC model!";
490*d415bd75Srobert else
491*d415bd75Srobert ErrMsg = "BaseReg/IndexReg already set!";
492*d415bd75Srobert return true;
493*d415bd75Srobert }
494*d415bd75Srobert
onOr()49509467b48Spatrick void onOr() {
49609467b48Spatrick IntelExprState CurrState = State;
49709467b48Spatrick switch (State) {
49809467b48Spatrick default:
49909467b48Spatrick State = IES_ERROR;
50009467b48Spatrick break;
50109467b48Spatrick case IES_INTEGER:
50209467b48Spatrick case IES_RPAREN:
50309467b48Spatrick case IES_REGISTER:
50409467b48Spatrick State = IES_OR;
50509467b48Spatrick IC.pushOperator(IC_OR);
50609467b48Spatrick break;
50709467b48Spatrick }
50809467b48Spatrick PrevState = CurrState;
50909467b48Spatrick }
onXor()51009467b48Spatrick void onXor() {
51109467b48Spatrick IntelExprState CurrState = State;
51209467b48Spatrick switch (State) {
51309467b48Spatrick default:
51409467b48Spatrick State = IES_ERROR;
51509467b48Spatrick break;
51609467b48Spatrick case IES_INTEGER:
51709467b48Spatrick case IES_RPAREN:
51809467b48Spatrick case IES_REGISTER:
51909467b48Spatrick State = IES_XOR;
52009467b48Spatrick IC.pushOperator(IC_XOR);
52109467b48Spatrick break;
52209467b48Spatrick }
52309467b48Spatrick PrevState = CurrState;
52409467b48Spatrick }
onAnd()52509467b48Spatrick void onAnd() {
52609467b48Spatrick IntelExprState CurrState = State;
52709467b48Spatrick switch (State) {
52809467b48Spatrick default:
52909467b48Spatrick State = IES_ERROR;
53009467b48Spatrick break;
53109467b48Spatrick case IES_INTEGER:
53209467b48Spatrick case IES_RPAREN:
53309467b48Spatrick case IES_REGISTER:
53409467b48Spatrick State = IES_AND;
53509467b48Spatrick IC.pushOperator(IC_AND);
53609467b48Spatrick break;
53709467b48Spatrick }
53809467b48Spatrick PrevState = CurrState;
53909467b48Spatrick }
onEq()54073471bf0Spatrick void onEq() {
54173471bf0Spatrick IntelExprState CurrState = State;
54273471bf0Spatrick switch (State) {
54373471bf0Spatrick default:
54473471bf0Spatrick State = IES_ERROR;
54573471bf0Spatrick break;
54673471bf0Spatrick case IES_INTEGER:
54773471bf0Spatrick case IES_RPAREN:
54873471bf0Spatrick case IES_REGISTER:
54973471bf0Spatrick State = IES_EQ;
55073471bf0Spatrick IC.pushOperator(IC_EQ);
55173471bf0Spatrick break;
55273471bf0Spatrick }
55373471bf0Spatrick PrevState = CurrState;
55473471bf0Spatrick }
onNE()55573471bf0Spatrick void onNE() {
55673471bf0Spatrick IntelExprState CurrState = State;
55773471bf0Spatrick switch (State) {
55873471bf0Spatrick default:
55973471bf0Spatrick State = IES_ERROR;
56073471bf0Spatrick break;
56173471bf0Spatrick case IES_INTEGER:
56273471bf0Spatrick case IES_RPAREN:
56373471bf0Spatrick case IES_REGISTER:
56473471bf0Spatrick State = IES_NE;
56573471bf0Spatrick IC.pushOperator(IC_NE);
56673471bf0Spatrick break;
56773471bf0Spatrick }
56873471bf0Spatrick PrevState = CurrState;
56973471bf0Spatrick }
onLT()57073471bf0Spatrick void onLT() {
57173471bf0Spatrick IntelExprState CurrState = State;
57273471bf0Spatrick switch (State) {
57373471bf0Spatrick default:
57473471bf0Spatrick State = IES_ERROR;
57573471bf0Spatrick break;
57673471bf0Spatrick case IES_INTEGER:
57773471bf0Spatrick case IES_RPAREN:
57873471bf0Spatrick case IES_REGISTER:
57973471bf0Spatrick State = IES_LT;
58073471bf0Spatrick IC.pushOperator(IC_LT);
58173471bf0Spatrick break;
58273471bf0Spatrick }
58373471bf0Spatrick PrevState = CurrState;
58473471bf0Spatrick }
onLE()58573471bf0Spatrick void onLE() {
58673471bf0Spatrick IntelExprState CurrState = State;
58773471bf0Spatrick switch (State) {
58873471bf0Spatrick default:
58973471bf0Spatrick State = IES_ERROR;
59073471bf0Spatrick break;
59173471bf0Spatrick case IES_INTEGER:
59273471bf0Spatrick case IES_RPAREN:
59373471bf0Spatrick case IES_REGISTER:
59473471bf0Spatrick State = IES_LE;
59573471bf0Spatrick IC.pushOperator(IC_LE);
59673471bf0Spatrick break;
59773471bf0Spatrick }
59873471bf0Spatrick PrevState = CurrState;
59973471bf0Spatrick }
onGT()60073471bf0Spatrick void onGT() {
60173471bf0Spatrick IntelExprState CurrState = State;
60273471bf0Spatrick switch (State) {
60373471bf0Spatrick default:
60473471bf0Spatrick State = IES_ERROR;
60573471bf0Spatrick break;
60673471bf0Spatrick case IES_INTEGER:
60773471bf0Spatrick case IES_RPAREN:
60873471bf0Spatrick case IES_REGISTER:
60973471bf0Spatrick State = IES_GT;
61073471bf0Spatrick IC.pushOperator(IC_GT);
61173471bf0Spatrick break;
61273471bf0Spatrick }
61373471bf0Spatrick PrevState = CurrState;
61473471bf0Spatrick }
onGE()61573471bf0Spatrick void onGE() {
61673471bf0Spatrick IntelExprState CurrState = State;
61773471bf0Spatrick switch (State) {
61873471bf0Spatrick default:
61973471bf0Spatrick State = IES_ERROR;
62073471bf0Spatrick break;
62173471bf0Spatrick case IES_INTEGER:
62273471bf0Spatrick case IES_RPAREN:
62373471bf0Spatrick case IES_REGISTER:
62473471bf0Spatrick State = IES_GE;
62573471bf0Spatrick IC.pushOperator(IC_GE);
62673471bf0Spatrick break;
62773471bf0Spatrick }
62873471bf0Spatrick PrevState = CurrState;
62973471bf0Spatrick }
onLShift()63009467b48Spatrick void onLShift() {
63109467b48Spatrick IntelExprState CurrState = State;
63209467b48Spatrick switch (State) {
63309467b48Spatrick default:
63409467b48Spatrick State = IES_ERROR;
63509467b48Spatrick break;
63609467b48Spatrick case IES_INTEGER:
63709467b48Spatrick case IES_RPAREN:
63809467b48Spatrick case IES_REGISTER:
63909467b48Spatrick State = IES_LSHIFT;
64009467b48Spatrick IC.pushOperator(IC_LSHIFT);
64109467b48Spatrick break;
64209467b48Spatrick }
64309467b48Spatrick PrevState = CurrState;
64409467b48Spatrick }
onRShift()64509467b48Spatrick void onRShift() {
64609467b48Spatrick IntelExprState CurrState = State;
64709467b48Spatrick switch (State) {
64809467b48Spatrick default:
64909467b48Spatrick State = IES_ERROR;
65009467b48Spatrick break;
65109467b48Spatrick case IES_INTEGER:
65209467b48Spatrick case IES_RPAREN:
65309467b48Spatrick case IES_REGISTER:
65409467b48Spatrick State = IES_RSHIFT;
65509467b48Spatrick IC.pushOperator(IC_RSHIFT);
65609467b48Spatrick break;
65709467b48Spatrick }
65809467b48Spatrick PrevState = CurrState;
65909467b48Spatrick }
onPlus(StringRef & ErrMsg)66009467b48Spatrick bool onPlus(StringRef &ErrMsg) {
66109467b48Spatrick IntelExprState CurrState = State;
66209467b48Spatrick switch (State) {
66309467b48Spatrick default:
66409467b48Spatrick State = IES_ERROR;
66509467b48Spatrick break;
66609467b48Spatrick case IES_INTEGER:
66709467b48Spatrick case IES_RPAREN:
66809467b48Spatrick case IES_REGISTER:
66909467b48Spatrick case IES_OFFSET:
67009467b48Spatrick State = IES_PLUS;
67109467b48Spatrick IC.pushOperator(IC_PLUS);
67209467b48Spatrick if (CurrState == IES_REGISTER && PrevState != IES_MULTIPLY) {
67309467b48Spatrick // If we already have a BaseReg, then assume this is the IndexReg with
67409467b48Spatrick // no explicit scale.
67509467b48Spatrick if (!BaseReg) {
67609467b48Spatrick BaseReg = TmpReg;
67709467b48Spatrick } else {
678*d415bd75Srobert if (IndexReg)
679*d415bd75Srobert return regsUseUpError(ErrMsg);
68009467b48Spatrick IndexReg = TmpReg;
68109467b48Spatrick Scale = 0;
68209467b48Spatrick }
68309467b48Spatrick }
68409467b48Spatrick break;
68509467b48Spatrick }
68609467b48Spatrick PrevState = CurrState;
68709467b48Spatrick return false;
68809467b48Spatrick }
onMinus(StringRef & ErrMsg)68909467b48Spatrick bool onMinus(StringRef &ErrMsg) {
69009467b48Spatrick IntelExprState CurrState = State;
69109467b48Spatrick switch (State) {
69209467b48Spatrick default:
69309467b48Spatrick State = IES_ERROR;
69409467b48Spatrick break;
69509467b48Spatrick case IES_OR:
69609467b48Spatrick case IES_XOR:
69709467b48Spatrick case IES_AND:
69873471bf0Spatrick case IES_EQ:
69973471bf0Spatrick case IES_NE:
70073471bf0Spatrick case IES_LT:
70173471bf0Spatrick case IES_LE:
70273471bf0Spatrick case IES_GT:
70373471bf0Spatrick case IES_GE:
70409467b48Spatrick case IES_LSHIFT:
70509467b48Spatrick case IES_RSHIFT:
70609467b48Spatrick case IES_PLUS:
70709467b48Spatrick case IES_NOT:
70809467b48Spatrick case IES_MULTIPLY:
70909467b48Spatrick case IES_DIVIDE:
71009467b48Spatrick case IES_MOD:
71109467b48Spatrick case IES_LPAREN:
71209467b48Spatrick case IES_RPAREN:
71309467b48Spatrick case IES_LBRAC:
71409467b48Spatrick case IES_RBRAC:
71509467b48Spatrick case IES_INTEGER:
71609467b48Spatrick case IES_REGISTER:
71709467b48Spatrick case IES_INIT:
71809467b48Spatrick case IES_OFFSET:
71909467b48Spatrick State = IES_MINUS;
72009467b48Spatrick // push minus operator if it is not a negate operator
72109467b48Spatrick if (CurrState == IES_REGISTER || CurrState == IES_RPAREN ||
72209467b48Spatrick CurrState == IES_INTEGER || CurrState == IES_RBRAC ||
72309467b48Spatrick CurrState == IES_OFFSET)
72409467b48Spatrick IC.pushOperator(IC_MINUS);
72509467b48Spatrick else if (PrevState == IES_REGISTER && CurrState == IES_MULTIPLY) {
72609467b48Spatrick // We have negate operator for Scale: it's illegal
72709467b48Spatrick ErrMsg = "Scale can't be negative";
72809467b48Spatrick return true;
72909467b48Spatrick } else
73009467b48Spatrick IC.pushOperator(IC_NEG);
73109467b48Spatrick if (CurrState == IES_REGISTER && PrevState != IES_MULTIPLY) {
73209467b48Spatrick // If we already have a BaseReg, then assume this is the IndexReg with
73309467b48Spatrick // no explicit scale.
73409467b48Spatrick if (!BaseReg) {
73509467b48Spatrick BaseReg = TmpReg;
73609467b48Spatrick } else {
737*d415bd75Srobert if (IndexReg)
738*d415bd75Srobert return regsUseUpError(ErrMsg);
73909467b48Spatrick IndexReg = TmpReg;
74009467b48Spatrick Scale = 0;
74109467b48Spatrick }
74209467b48Spatrick }
74309467b48Spatrick break;
74409467b48Spatrick }
74509467b48Spatrick PrevState = CurrState;
74609467b48Spatrick return false;
74709467b48Spatrick }
onNot()74809467b48Spatrick void onNot() {
74909467b48Spatrick IntelExprState CurrState = State;
75009467b48Spatrick switch (State) {
75109467b48Spatrick default:
75209467b48Spatrick State = IES_ERROR;
75309467b48Spatrick break;
75409467b48Spatrick case IES_OR:
75509467b48Spatrick case IES_XOR:
75609467b48Spatrick case IES_AND:
75773471bf0Spatrick case IES_EQ:
75873471bf0Spatrick case IES_NE:
75973471bf0Spatrick case IES_LT:
76073471bf0Spatrick case IES_LE:
76173471bf0Spatrick case IES_GT:
76273471bf0Spatrick case IES_GE:
76309467b48Spatrick case IES_LSHIFT:
76409467b48Spatrick case IES_RSHIFT:
76509467b48Spatrick case IES_PLUS:
76609467b48Spatrick case IES_MINUS:
76709467b48Spatrick case IES_NOT:
76809467b48Spatrick case IES_MULTIPLY:
76909467b48Spatrick case IES_DIVIDE:
77009467b48Spatrick case IES_MOD:
77109467b48Spatrick case IES_LPAREN:
77209467b48Spatrick case IES_LBRAC:
77309467b48Spatrick case IES_INIT:
77409467b48Spatrick State = IES_NOT;
77509467b48Spatrick IC.pushOperator(IC_NOT);
77609467b48Spatrick break;
77709467b48Spatrick }
77809467b48Spatrick PrevState = CurrState;
77909467b48Spatrick }
onRegister(unsigned Reg,StringRef & ErrMsg)78009467b48Spatrick bool onRegister(unsigned Reg, StringRef &ErrMsg) {
78109467b48Spatrick IntelExprState CurrState = State;
78209467b48Spatrick switch (State) {
78309467b48Spatrick default:
78409467b48Spatrick State = IES_ERROR;
78509467b48Spatrick break;
78609467b48Spatrick case IES_PLUS:
78709467b48Spatrick case IES_LPAREN:
78809467b48Spatrick case IES_LBRAC:
78909467b48Spatrick State = IES_REGISTER;
79009467b48Spatrick TmpReg = Reg;
79109467b48Spatrick IC.pushOperand(IC_REGISTER);
79209467b48Spatrick break;
79309467b48Spatrick case IES_MULTIPLY:
79409467b48Spatrick // Index Register - Scale * Register
79509467b48Spatrick if (PrevState == IES_INTEGER) {
796*d415bd75Srobert if (IndexReg)
797*d415bd75Srobert return regsUseUpError(ErrMsg);
79809467b48Spatrick State = IES_REGISTER;
79909467b48Spatrick IndexReg = Reg;
80009467b48Spatrick // Get the scale and replace the 'Scale * Register' with '0'.
80109467b48Spatrick Scale = IC.popOperand();
80209467b48Spatrick if (checkScale(Scale, ErrMsg))
80309467b48Spatrick return true;
80409467b48Spatrick IC.pushOperand(IC_IMM);
80509467b48Spatrick IC.popOperator();
80609467b48Spatrick } else {
80709467b48Spatrick State = IES_ERROR;
80809467b48Spatrick }
80909467b48Spatrick break;
81009467b48Spatrick }
81109467b48Spatrick PrevState = CurrState;
81209467b48Spatrick return false;
81309467b48Spatrick }
onIdentifierExpr(const MCExpr * SymRef,StringRef SymRefName,const InlineAsmIdentifierInfo & IDInfo,const AsmTypeInfo & Type,bool ParsingMSInlineAsm,StringRef & ErrMsg)81409467b48Spatrick bool onIdentifierExpr(const MCExpr *SymRef, StringRef SymRefName,
81509467b48Spatrick const InlineAsmIdentifierInfo &IDInfo,
81673471bf0Spatrick const AsmTypeInfo &Type, bool ParsingMSInlineAsm,
81773471bf0Spatrick StringRef &ErrMsg) {
81809467b48Spatrick // InlineAsm: Treat an enum value as an integer
819097a140dSpatrick if (ParsingMSInlineAsm)
82009467b48Spatrick if (IDInfo.isKind(InlineAsmIdentifierInfo::IK_EnumVal))
82109467b48Spatrick return onInteger(IDInfo.Enum.EnumVal, ErrMsg);
82209467b48Spatrick // Treat a symbolic constant like an integer
82309467b48Spatrick if (auto *CE = dyn_cast<MCConstantExpr>(SymRef))
82409467b48Spatrick return onInteger(CE->getValue(), ErrMsg);
82509467b48Spatrick PrevState = State;
82609467b48Spatrick switch (State) {
82709467b48Spatrick default:
82809467b48Spatrick State = IES_ERROR;
82909467b48Spatrick break;
830097a140dSpatrick case IES_CAST:
83109467b48Spatrick case IES_PLUS:
83209467b48Spatrick case IES_MINUS:
83309467b48Spatrick case IES_NOT:
83409467b48Spatrick case IES_INIT:
83509467b48Spatrick case IES_LBRAC:
83673471bf0Spatrick case IES_LPAREN:
83709467b48Spatrick if (setSymRef(SymRef, SymRefName, ErrMsg))
83809467b48Spatrick return true;
83909467b48Spatrick MemExpr = true;
84009467b48Spatrick State = IES_INTEGER;
84109467b48Spatrick IC.pushOperand(IC_IMM);
842097a140dSpatrick if (ParsingMSInlineAsm)
84309467b48Spatrick Info = IDInfo;
84473471bf0Spatrick setTypeInfo(Type);
84509467b48Spatrick break;
84609467b48Spatrick }
84709467b48Spatrick return false;
84809467b48Spatrick }
onInteger(int64_t TmpInt,StringRef & ErrMsg)84909467b48Spatrick bool onInteger(int64_t TmpInt, StringRef &ErrMsg) {
85009467b48Spatrick IntelExprState CurrState = State;
85109467b48Spatrick switch (State) {
85209467b48Spatrick default:
85309467b48Spatrick State = IES_ERROR;
85409467b48Spatrick break;
85509467b48Spatrick case IES_PLUS:
85609467b48Spatrick case IES_MINUS:
85709467b48Spatrick case IES_NOT:
85809467b48Spatrick case IES_OR:
85909467b48Spatrick case IES_XOR:
86009467b48Spatrick case IES_AND:
86173471bf0Spatrick case IES_EQ:
86273471bf0Spatrick case IES_NE:
86373471bf0Spatrick case IES_LT:
86473471bf0Spatrick case IES_LE:
86573471bf0Spatrick case IES_GT:
86673471bf0Spatrick case IES_GE:
86709467b48Spatrick case IES_LSHIFT:
86809467b48Spatrick case IES_RSHIFT:
86909467b48Spatrick case IES_DIVIDE:
87009467b48Spatrick case IES_MOD:
87109467b48Spatrick case IES_MULTIPLY:
87209467b48Spatrick case IES_LPAREN:
87309467b48Spatrick case IES_INIT:
87409467b48Spatrick case IES_LBRAC:
87509467b48Spatrick State = IES_INTEGER;
87609467b48Spatrick if (PrevState == IES_REGISTER && CurrState == IES_MULTIPLY) {
87709467b48Spatrick // Index Register - Register * Scale
878*d415bd75Srobert if (IndexReg)
879*d415bd75Srobert return regsUseUpError(ErrMsg);
88009467b48Spatrick IndexReg = TmpReg;
88109467b48Spatrick Scale = TmpInt;
88209467b48Spatrick if (checkScale(Scale, ErrMsg))
88309467b48Spatrick return true;
88409467b48Spatrick // Get the scale and replace the 'Register * Scale' with '0'.
88509467b48Spatrick IC.popOperator();
88609467b48Spatrick } else {
88709467b48Spatrick IC.pushOperand(IC_IMM, TmpInt);
88809467b48Spatrick }
88909467b48Spatrick break;
89009467b48Spatrick }
89109467b48Spatrick PrevState = CurrState;
89209467b48Spatrick return false;
89309467b48Spatrick }
onStar()89409467b48Spatrick void onStar() {
89509467b48Spatrick PrevState = State;
89609467b48Spatrick switch (State) {
89709467b48Spatrick default:
89809467b48Spatrick State = IES_ERROR;
89909467b48Spatrick break;
90009467b48Spatrick case IES_INTEGER:
90109467b48Spatrick case IES_REGISTER:
90209467b48Spatrick case IES_RPAREN:
90309467b48Spatrick State = IES_MULTIPLY;
90409467b48Spatrick IC.pushOperator(IC_MULTIPLY);
90509467b48Spatrick break;
90609467b48Spatrick }
90709467b48Spatrick }
onDivide()90809467b48Spatrick void onDivide() {
90909467b48Spatrick PrevState = State;
91009467b48Spatrick switch (State) {
91109467b48Spatrick default:
91209467b48Spatrick State = IES_ERROR;
91309467b48Spatrick break;
91409467b48Spatrick case IES_INTEGER:
91509467b48Spatrick case IES_RPAREN:
91609467b48Spatrick State = IES_DIVIDE;
91709467b48Spatrick IC.pushOperator(IC_DIVIDE);
91809467b48Spatrick break;
91909467b48Spatrick }
92009467b48Spatrick }
onMod()92109467b48Spatrick void onMod() {
92209467b48Spatrick PrevState = State;
92309467b48Spatrick switch (State) {
92409467b48Spatrick default:
92509467b48Spatrick State = IES_ERROR;
92609467b48Spatrick break;
92709467b48Spatrick case IES_INTEGER:
92809467b48Spatrick case IES_RPAREN:
92909467b48Spatrick State = IES_MOD;
93009467b48Spatrick IC.pushOperator(IC_MOD);
93109467b48Spatrick break;
93209467b48Spatrick }
93309467b48Spatrick }
onLBrac()93409467b48Spatrick bool onLBrac() {
93509467b48Spatrick if (BracCount)
93609467b48Spatrick return true;
93709467b48Spatrick PrevState = State;
93809467b48Spatrick switch (State) {
93909467b48Spatrick default:
94009467b48Spatrick State = IES_ERROR;
94109467b48Spatrick break;
94209467b48Spatrick case IES_RBRAC:
94309467b48Spatrick case IES_INTEGER:
94409467b48Spatrick case IES_RPAREN:
94509467b48Spatrick State = IES_PLUS;
94609467b48Spatrick IC.pushOperator(IC_PLUS);
94773471bf0Spatrick CurType.Length = 1;
94873471bf0Spatrick CurType.Size = CurType.ElementSize;
94909467b48Spatrick break;
95009467b48Spatrick case IES_INIT:
951097a140dSpatrick case IES_CAST:
95209467b48Spatrick assert(!BracCount && "BracCount should be zero on parsing's start");
95309467b48Spatrick State = IES_LBRAC;
95409467b48Spatrick break;
95509467b48Spatrick }
95609467b48Spatrick MemExpr = true;
95709467b48Spatrick BracCount++;
95809467b48Spatrick return false;
95909467b48Spatrick }
onRBrac(StringRef & ErrMsg)960*d415bd75Srobert bool onRBrac(StringRef &ErrMsg) {
96109467b48Spatrick IntelExprState CurrState = State;
96209467b48Spatrick switch (State) {
96309467b48Spatrick default:
96409467b48Spatrick State = IES_ERROR;
96509467b48Spatrick break;
96609467b48Spatrick case IES_INTEGER:
96709467b48Spatrick case IES_OFFSET:
96809467b48Spatrick case IES_REGISTER:
96909467b48Spatrick case IES_RPAREN:
970*d415bd75Srobert if (BracCount-- != 1) {
971*d415bd75Srobert ErrMsg = "unexpected bracket encountered";
97209467b48Spatrick return true;
973*d415bd75Srobert }
97409467b48Spatrick State = IES_RBRAC;
97509467b48Spatrick if (CurrState == IES_REGISTER && PrevState != IES_MULTIPLY) {
97609467b48Spatrick // If we already have a BaseReg, then assume this is the IndexReg with
97709467b48Spatrick // no explicit scale.
97809467b48Spatrick if (!BaseReg) {
97909467b48Spatrick BaseReg = TmpReg;
98009467b48Spatrick } else {
981*d415bd75Srobert if (IndexReg)
982*d415bd75Srobert return regsUseUpError(ErrMsg);
98309467b48Spatrick IndexReg = TmpReg;
98409467b48Spatrick Scale = 0;
98509467b48Spatrick }
98609467b48Spatrick }
98709467b48Spatrick break;
98809467b48Spatrick }
98909467b48Spatrick PrevState = CurrState;
99009467b48Spatrick return false;
99109467b48Spatrick }
onLParen()99209467b48Spatrick void onLParen() {
99309467b48Spatrick IntelExprState CurrState = State;
99409467b48Spatrick switch (State) {
99509467b48Spatrick default:
99609467b48Spatrick State = IES_ERROR;
99709467b48Spatrick break;
99809467b48Spatrick case IES_PLUS:
99909467b48Spatrick case IES_MINUS:
100009467b48Spatrick case IES_NOT:
100109467b48Spatrick case IES_OR:
100209467b48Spatrick case IES_XOR:
100309467b48Spatrick case IES_AND:
100473471bf0Spatrick case IES_EQ:
100573471bf0Spatrick case IES_NE:
100673471bf0Spatrick case IES_LT:
100773471bf0Spatrick case IES_LE:
100873471bf0Spatrick case IES_GT:
100973471bf0Spatrick case IES_GE:
101009467b48Spatrick case IES_LSHIFT:
101109467b48Spatrick case IES_RSHIFT:
101209467b48Spatrick case IES_MULTIPLY:
101309467b48Spatrick case IES_DIVIDE:
101409467b48Spatrick case IES_MOD:
101509467b48Spatrick case IES_LPAREN:
101609467b48Spatrick case IES_INIT:
101709467b48Spatrick case IES_LBRAC:
101809467b48Spatrick State = IES_LPAREN;
101909467b48Spatrick IC.pushOperator(IC_LPAREN);
102009467b48Spatrick break;
102109467b48Spatrick }
102209467b48Spatrick PrevState = CurrState;
102309467b48Spatrick }
onRParen()102409467b48Spatrick void onRParen() {
102509467b48Spatrick PrevState = State;
102609467b48Spatrick switch (State) {
102709467b48Spatrick default:
102809467b48Spatrick State = IES_ERROR;
102909467b48Spatrick break;
103009467b48Spatrick case IES_INTEGER:
103109467b48Spatrick case IES_OFFSET:
103209467b48Spatrick case IES_REGISTER:
1033097a140dSpatrick case IES_RBRAC:
103409467b48Spatrick case IES_RPAREN:
103509467b48Spatrick State = IES_RPAREN;
103609467b48Spatrick IC.pushOperator(IC_RPAREN);
103709467b48Spatrick break;
103809467b48Spatrick }
103909467b48Spatrick }
onOffset(const MCExpr * Val,SMLoc OffsetLoc,StringRef ID,const InlineAsmIdentifierInfo & IDInfo,bool ParsingMSInlineAsm,StringRef & ErrMsg)104009467b48Spatrick bool onOffset(const MCExpr *Val, SMLoc OffsetLoc, StringRef ID,
104173471bf0Spatrick const InlineAsmIdentifierInfo &IDInfo,
104273471bf0Spatrick bool ParsingMSInlineAsm, StringRef &ErrMsg) {
104309467b48Spatrick PrevState = State;
104409467b48Spatrick switch (State) {
104509467b48Spatrick default:
104609467b48Spatrick ErrMsg = "unexpected offset operator expression";
104709467b48Spatrick return true;
104809467b48Spatrick case IES_PLUS:
104909467b48Spatrick case IES_INIT:
105009467b48Spatrick case IES_LBRAC:
105109467b48Spatrick if (setSymRef(Val, ID, ErrMsg))
105209467b48Spatrick return true;
105309467b48Spatrick OffsetOperator = true;
105409467b48Spatrick OffsetOperatorLoc = OffsetLoc;
105509467b48Spatrick State = IES_OFFSET;
105609467b48Spatrick // As we cannot yet resolve the actual value (offset), we retain
105709467b48Spatrick // the requested semantics by pushing a '0' to the operands stack
105809467b48Spatrick IC.pushOperand(IC_IMM);
1059097a140dSpatrick if (ParsingMSInlineAsm) {
106009467b48Spatrick Info = IDInfo;
106109467b48Spatrick }
106209467b48Spatrick break;
106309467b48Spatrick }
106409467b48Spatrick return false;
106509467b48Spatrick }
onCast(AsmTypeInfo Info)106673471bf0Spatrick void onCast(AsmTypeInfo Info) {
1067097a140dSpatrick PrevState = State;
1068097a140dSpatrick switch (State) {
1069097a140dSpatrick default:
1070097a140dSpatrick State = IES_ERROR;
1071097a140dSpatrick break;
1072097a140dSpatrick case IES_LPAREN:
107373471bf0Spatrick setTypeInfo(Info);
1074097a140dSpatrick State = IES_CAST;
1075097a140dSpatrick break;
1076097a140dSpatrick }
1077097a140dSpatrick }
setTypeInfo(AsmTypeInfo Type)107873471bf0Spatrick void setTypeInfo(AsmTypeInfo Type) { CurType = Type; }
107909467b48Spatrick };
108009467b48Spatrick
Error(SMLoc L,const Twine & Msg,SMRange Range=std::nullopt,bool MatchingInlineAsm=false)1081*d415bd75Srobert bool Error(SMLoc L, const Twine &Msg, SMRange Range = std::nullopt,
108209467b48Spatrick bool MatchingInlineAsm = false) {
108309467b48Spatrick MCAsmParser &Parser = getParser();
108409467b48Spatrick if (MatchingInlineAsm) {
108509467b48Spatrick if (!getLexer().isAtStartOfStatement())
108609467b48Spatrick Parser.eatToEndOfStatement();
108709467b48Spatrick return false;
108809467b48Spatrick }
108909467b48Spatrick return Parser.Error(L, Msg, Range);
109009467b48Spatrick }
109109467b48Spatrick
1092*d415bd75Srobert bool MatchRegisterByName(MCRegister &RegNo, StringRef RegName, SMLoc StartLoc,
1093097a140dSpatrick SMLoc EndLoc);
1094*d415bd75Srobert bool ParseRegister(MCRegister &RegNo, SMLoc &StartLoc, SMLoc &EndLoc,
1095097a140dSpatrick bool RestoreOnFailure);
1096097a140dSpatrick
109709467b48Spatrick std::unique_ptr<X86Operand> DefaultMemSIOperand(SMLoc Loc);
109809467b48Spatrick std::unique_ptr<X86Operand> DefaultMemDIOperand(SMLoc Loc);
109909467b48Spatrick bool IsSIReg(unsigned Reg);
110009467b48Spatrick unsigned GetSIDIForRegClass(unsigned RegClassID, unsigned Reg, bool IsSIReg);
110109467b48Spatrick void
110209467b48Spatrick AddDefaultSrcDestOperands(OperandVector &Operands,
110309467b48Spatrick std::unique_ptr<llvm::MCParsedAsmOperand> &&Src,
110409467b48Spatrick std::unique_ptr<llvm::MCParsedAsmOperand> &&Dst);
110509467b48Spatrick bool VerifyAndAdjustOperands(OperandVector &OrigOperands,
110609467b48Spatrick OperandVector &FinalOperands);
1107*d415bd75Srobert bool parseOperand(OperandVector &Operands, StringRef Name);
1108*d415bd75Srobert bool parseATTOperand(OperandVector &Operands);
1109*d415bd75Srobert bool parseIntelOperand(OperandVector &Operands, StringRef Name);
111009467b48Spatrick bool ParseIntelOffsetOperator(const MCExpr *&Val, StringRef &ID,
111109467b48Spatrick InlineAsmIdentifierInfo &Info, SMLoc &End);
111209467b48Spatrick bool ParseIntelDotOperator(IntelExprStateMachine &SM, SMLoc &End);
111309467b48Spatrick unsigned IdentifyIntelInlineAsmOperator(StringRef Name);
111409467b48Spatrick unsigned ParseIntelInlineAsmOperator(unsigned OpKind);
111573471bf0Spatrick unsigned IdentifyMasmOperator(StringRef Name);
111673471bf0Spatrick bool ParseMasmOperator(unsigned OpKind, int64_t &Val);
111773471bf0Spatrick bool ParseRoundingModeOp(SMLoc Start, OperandVector &Operands);
111809467b48Spatrick bool ParseIntelNamedOperator(StringRef Name, IntelExprStateMachine &SM,
111909467b48Spatrick bool &ParseError, SMLoc &End);
112073471bf0Spatrick bool ParseMasmNamedOperator(StringRef Name, IntelExprStateMachine &SM,
112173471bf0Spatrick bool &ParseError, SMLoc &End);
112209467b48Spatrick void RewriteIntelExpression(IntelExprStateMachine &SM, SMLoc Start,
112309467b48Spatrick SMLoc End);
112409467b48Spatrick bool ParseIntelExpression(IntelExprStateMachine &SM, SMLoc &End);
112509467b48Spatrick bool ParseIntelInlineAsmIdentifier(const MCExpr *&Val, StringRef &Identifier,
112609467b48Spatrick InlineAsmIdentifierInfo &Info,
112709467b48Spatrick bool IsUnevaluatedOperand, SMLoc &End,
112809467b48Spatrick bool IsParsingOffsetOperator = false);
1129*d415bd75Srobert void tryParseOperandIdx(AsmToken::TokenKind PrevTK,
1130*d415bd75Srobert IntelExprStateMachine &SM);
113109467b48Spatrick
113273471bf0Spatrick bool ParseMemOperand(unsigned SegReg, const MCExpr *Disp, SMLoc StartLoc,
113373471bf0Spatrick SMLoc EndLoc, OperandVector &Operands);
113409467b48Spatrick
113509467b48Spatrick X86::CondCode ParseConditionCode(StringRef CCode);
113609467b48Spatrick
113709467b48Spatrick bool ParseIntelMemoryOperandSize(unsigned &Size);
113873471bf0Spatrick bool CreateMemForMSInlineAsm(unsigned SegReg, const MCExpr *Disp,
113973471bf0Spatrick unsigned BaseReg, unsigned IndexReg,
114073471bf0Spatrick unsigned Scale, SMLoc Start, SMLoc End,
114173471bf0Spatrick unsigned Size, StringRef Identifier,
114273471bf0Spatrick const InlineAsmIdentifierInfo &Info,
114373471bf0Spatrick OperandVector &Operands);
114409467b48Spatrick
114573471bf0Spatrick bool parseDirectiveArch();
114673471bf0Spatrick bool parseDirectiveNops(SMLoc L);
114709467b48Spatrick bool parseDirectiveEven(SMLoc L);
114809467b48Spatrick bool ParseDirectiveCode(StringRef IDVal, SMLoc L);
114909467b48Spatrick
115009467b48Spatrick /// CodeView FPO data directives.
115109467b48Spatrick bool parseDirectiveFPOProc(SMLoc L);
115209467b48Spatrick bool parseDirectiveFPOSetFrame(SMLoc L);
115309467b48Spatrick bool parseDirectiveFPOPushReg(SMLoc L);
115409467b48Spatrick bool parseDirectiveFPOStackAlloc(SMLoc L);
115509467b48Spatrick bool parseDirectiveFPOStackAlign(SMLoc L);
115609467b48Spatrick bool parseDirectiveFPOEndPrologue(SMLoc L);
115709467b48Spatrick bool parseDirectiveFPOEndProc(SMLoc L);
115809467b48Spatrick
115909467b48Spatrick /// SEH directives.
1160*d415bd75Srobert bool parseSEHRegisterNumber(unsigned RegClassID, MCRegister &RegNo);
116109467b48Spatrick bool parseDirectiveSEHPushReg(SMLoc);
116209467b48Spatrick bool parseDirectiveSEHSetFrame(SMLoc);
116309467b48Spatrick bool parseDirectiveSEHSaveReg(SMLoc);
116409467b48Spatrick bool parseDirectiveSEHSaveXMM(SMLoc);
116509467b48Spatrick bool parseDirectiveSEHPushFrame(SMLoc);
116609467b48Spatrick
116709467b48Spatrick unsigned checkTargetMatchPredicate(MCInst &Inst) override;
116809467b48Spatrick
116909467b48Spatrick bool validateInstruction(MCInst &Inst, const OperandVector &Ops);
117009467b48Spatrick bool processInstruction(MCInst &Inst, const OperandVector &Ops);
117109467b48Spatrick
1172097a140dSpatrick // Load Value Injection (LVI) Mitigations for machine code
1173097a140dSpatrick void emitWarningForSpecialLVIInstruction(SMLoc Loc);
1174097a140dSpatrick void applyLVICFIMitigation(MCInst &Inst, MCStreamer &Out);
1175097a140dSpatrick void applyLVILoadHardeningMitigation(MCInst &Inst, MCStreamer &Out);
1176097a140dSpatrick
1177097a140dSpatrick /// Wrapper around MCStreamer::emitInstruction(). Possibly adds
117809467b48Spatrick /// instrumentation around Inst.
1179097a140dSpatrick void emitInstruction(MCInst &Inst, OperandVector &Operands, MCStreamer &Out);
118009467b48Spatrick
118109467b48Spatrick bool MatchAndEmitInstruction(SMLoc IDLoc, unsigned &Opcode,
118209467b48Spatrick OperandVector &Operands, MCStreamer &Out,
118309467b48Spatrick uint64_t &ErrorInfo,
118409467b48Spatrick bool MatchingInlineAsm) override;
118509467b48Spatrick
118609467b48Spatrick void MatchFPUWaitAlias(SMLoc IDLoc, X86Operand &Op, OperandVector &Operands,
118709467b48Spatrick MCStreamer &Out, bool MatchingInlineAsm);
118809467b48Spatrick
118909467b48Spatrick bool ErrorMissingFeature(SMLoc IDLoc, const FeatureBitset &MissingFeatures,
119009467b48Spatrick bool MatchingInlineAsm);
119109467b48Spatrick
119209467b48Spatrick bool MatchAndEmitATTInstruction(SMLoc IDLoc, unsigned &Opcode,
119309467b48Spatrick OperandVector &Operands, MCStreamer &Out,
119409467b48Spatrick uint64_t &ErrorInfo,
119509467b48Spatrick bool MatchingInlineAsm);
119609467b48Spatrick
119709467b48Spatrick bool MatchAndEmitIntelInstruction(SMLoc IDLoc, unsigned &Opcode,
119809467b48Spatrick OperandVector &Operands, MCStreamer &Out,
119909467b48Spatrick uint64_t &ErrorInfo,
120009467b48Spatrick bool MatchingInlineAsm);
120109467b48Spatrick
120209467b48Spatrick bool OmitRegisterFromClobberLists(unsigned RegNo) override;
120309467b48Spatrick
120409467b48Spatrick /// Parses AVX512 specific operand primitives: masked registers ({%k<NUM>}, {z})
120509467b48Spatrick /// and memory broadcasting ({1to<NUM>}) primitives, updating Operands vector if required.
120609467b48Spatrick /// return false if no parsing errors occurred, true otherwise.
120773471bf0Spatrick bool HandleAVX512Operand(OperandVector &Operands);
120809467b48Spatrick
120909467b48Spatrick bool ParseZ(std::unique_ptr<X86Operand> &Z, const SMLoc &StartLoc);
121009467b48Spatrick
is64BitMode() const121109467b48Spatrick bool is64BitMode() const {
121209467b48Spatrick // FIXME: Can tablegen auto-generate this?
1213*d415bd75Srobert return getSTI().getFeatureBits()[X86::Is64Bit];
121409467b48Spatrick }
is32BitMode() const121509467b48Spatrick bool is32BitMode() const {
121609467b48Spatrick // FIXME: Can tablegen auto-generate this?
1217*d415bd75Srobert return getSTI().getFeatureBits()[X86::Is32Bit];
121809467b48Spatrick }
is16BitMode() const121909467b48Spatrick bool is16BitMode() const {
122009467b48Spatrick // FIXME: Can tablegen auto-generate this?
1221*d415bd75Srobert return getSTI().getFeatureBits()[X86::Is16Bit];
122209467b48Spatrick }
SwitchMode(unsigned mode)122309467b48Spatrick void SwitchMode(unsigned mode) {
122409467b48Spatrick MCSubtargetInfo &STI = copySTI();
1225*d415bd75Srobert FeatureBitset AllModes({X86::Is64Bit, X86::Is32Bit, X86::Is16Bit});
122609467b48Spatrick FeatureBitset OldMode = STI.getFeatureBits() & AllModes;
122709467b48Spatrick FeatureBitset FB = ComputeAvailableFeatures(
122809467b48Spatrick STI.ToggleFeature(OldMode.flip(mode)));
122909467b48Spatrick setAvailableFeatures(FB);
123009467b48Spatrick
123109467b48Spatrick assert(FeatureBitset({mode}) == (STI.getFeatureBits() & AllModes));
123209467b48Spatrick }
123309467b48Spatrick
getPointerWidth()123409467b48Spatrick unsigned getPointerWidth() {
123509467b48Spatrick if (is16BitMode()) return 16;
123609467b48Spatrick if (is32BitMode()) return 32;
123709467b48Spatrick if (is64BitMode()) return 64;
123809467b48Spatrick llvm_unreachable("invalid mode");
123909467b48Spatrick }
124009467b48Spatrick
isParsingIntelSyntax()124109467b48Spatrick bool isParsingIntelSyntax() {
124209467b48Spatrick return getParser().getAssemblerDialect();
124309467b48Spatrick }
124409467b48Spatrick
124509467b48Spatrick /// @name Auto-generated Matcher Functions
124609467b48Spatrick /// {
124709467b48Spatrick
124809467b48Spatrick #define GET_ASSEMBLER_HEADER
124909467b48Spatrick #include "X86GenAsmMatcher.inc"
125009467b48Spatrick
125109467b48Spatrick /// }
125209467b48Spatrick
125309467b48Spatrick public:
125409467b48Spatrick enum X86MatchResultTy {
125509467b48Spatrick Match_Unsupported = FIRST_TARGET_MATCH_RESULT_TY,
125609467b48Spatrick #define GET_OPERAND_DIAGNOSTIC_TYPES
125709467b48Spatrick #include "X86GenAsmMatcher.inc"
125809467b48Spatrick };
125909467b48Spatrick
X86AsmParser(const MCSubtargetInfo & sti,MCAsmParser & Parser,const MCInstrInfo & mii,const MCTargetOptions & Options)126009467b48Spatrick X86AsmParser(const MCSubtargetInfo &sti, MCAsmParser &Parser,
126109467b48Spatrick const MCInstrInfo &mii, const MCTargetOptions &Options)
126209467b48Spatrick : MCTargetAsmParser(Options, sti, mii), InstInfo(nullptr),
126309467b48Spatrick Code16GCC(false) {
126409467b48Spatrick
126509467b48Spatrick Parser.addAliasForDirective(".word", ".2byte");
126609467b48Spatrick
126709467b48Spatrick // Initialize the set of available features.
126809467b48Spatrick setAvailableFeatures(ComputeAvailableFeatures(getSTI().getFeatureBits()));
126909467b48Spatrick }
127009467b48Spatrick
1271*d415bd75Srobert bool parseRegister(MCRegister &RegNo, SMLoc &StartLoc,
1272*d415bd75Srobert SMLoc &EndLoc) override;
1273*d415bd75Srobert OperandMatchResultTy tryParseRegister(MCRegister &RegNo, SMLoc &StartLoc,
1274097a140dSpatrick SMLoc &EndLoc) override;
127509467b48Spatrick
127609467b48Spatrick bool parsePrimaryExpr(const MCExpr *&Res, SMLoc &EndLoc) override;
127709467b48Spatrick
127809467b48Spatrick bool ParseInstruction(ParseInstructionInfo &Info, StringRef Name,
127909467b48Spatrick SMLoc NameLoc, OperandVector &Operands) override;
128009467b48Spatrick
128109467b48Spatrick bool ParseDirective(AsmToken DirectiveID) override;
128209467b48Spatrick };
128309467b48Spatrick } // end anonymous namespace
128409467b48Spatrick
128509467b48Spatrick /// @name Auto-generated Match Functions
128609467b48Spatrick /// {
128709467b48Spatrick
128809467b48Spatrick static unsigned MatchRegisterName(StringRef Name);
128909467b48Spatrick
129009467b48Spatrick /// }
129109467b48Spatrick
CheckBaseRegAndIndexRegAndScale(unsigned BaseReg,unsigned IndexReg,unsigned Scale,bool Is64BitMode,StringRef & ErrMsg)129209467b48Spatrick static bool CheckBaseRegAndIndexRegAndScale(unsigned BaseReg, unsigned IndexReg,
129309467b48Spatrick unsigned Scale, bool Is64BitMode,
129409467b48Spatrick StringRef &ErrMsg) {
129509467b48Spatrick // If we have both a base register and an index register make sure they are
129609467b48Spatrick // both 64-bit or 32-bit registers.
129709467b48Spatrick // To support VSIB, IndexReg can be 128-bit or 256-bit registers.
129809467b48Spatrick
129909467b48Spatrick if (BaseReg != 0 &&
130009467b48Spatrick !(BaseReg == X86::RIP || BaseReg == X86::EIP ||
130109467b48Spatrick X86MCRegisterClasses[X86::GR16RegClassID].contains(BaseReg) ||
130209467b48Spatrick X86MCRegisterClasses[X86::GR32RegClassID].contains(BaseReg) ||
130309467b48Spatrick X86MCRegisterClasses[X86::GR64RegClassID].contains(BaseReg))) {
130409467b48Spatrick ErrMsg = "invalid base+index expression";
130509467b48Spatrick return true;
130609467b48Spatrick }
130709467b48Spatrick
130809467b48Spatrick if (IndexReg != 0 &&
130909467b48Spatrick !(IndexReg == X86::EIZ || IndexReg == X86::RIZ ||
131009467b48Spatrick X86MCRegisterClasses[X86::GR16RegClassID].contains(IndexReg) ||
131109467b48Spatrick X86MCRegisterClasses[X86::GR32RegClassID].contains(IndexReg) ||
131209467b48Spatrick X86MCRegisterClasses[X86::GR64RegClassID].contains(IndexReg) ||
131309467b48Spatrick X86MCRegisterClasses[X86::VR128XRegClassID].contains(IndexReg) ||
131409467b48Spatrick X86MCRegisterClasses[X86::VR256XRegClassID].contains(IndexReg) ||
131509467b48Spatrick X86MCRegisterClasses[X86::VR512RegClassID].contains(IndexReg))) {
131609467b48Spatrick ErrMsg = "invalid base+index expression";
131709467b48Spatrick return true;
131809467b48Spatrick }
131909467b48Spatrick
132009467b48Spatrick if (((BaseReg == X86::RIP || BaseReg == X86::EIP) && IndexReg != 0) ||
132109467b48Spatrick IndexReg == X86::EIP || IndexReg == X86::RIP ||
132209467b48Spatrick IndexReg == X86::ESP || IndexReg == X86::RSP) {
132309467b48Spatrick ErrMsg = "invalid base+index expression";
132409467b48Spatrick return true;
132509467b48Spatrick }
132609467b48Spatrick
132709467b48Spatrick // Check for use of invalid 16-bit registers. Only BX/BP/SI/DI are allowed,
132809467b48Spatrick // and then only in non-64-bit modes.
132909467b48Spatrick if (X86MCRegisterClasses[X86::GR16RegClassID].contains(BaseReg) &&
133009467b48Spatrick (Is64BitMode || (BaseReg != X86::BX && BaseReg != X86::BP &&
133109467b48Spatrick BaseReg != X86::SI && BaseReg != X86::DI))) {
133209467b48Spatrick ErrMsg = "invalid 16-bit base register";
133309467b48Spatrick return true;
133409467b48Spatrick }
133509467b48Spatrick
133609467b48Spatrick if (BaseReg == 0 &&
133709467b48Spatrick X86MCRegisterClasses[X86::GR16RegClassID].contains(IndexReg)) {
133809467b48Spatrick ErrMsg = "16-bit memory operand may not include only index register";
133909467b48Spatrick return true;
134009467b48Spatrick }
134109467b48Spatrick
134209467b48Spatrick if (BaseReg != 0 && IndexReg != 0) {
134309467b48Spatrick if (X86MCRegisterClasses[X86::GR64RegClassID].contains(BaseReg) &&
134409467b48Spatrick (X86MCRegisterClasses[X86::GR16RegClassID].contains(IndexReg) ||
134509467b48Spatrick X86MCRegisterClasses[X86::GR32RegClassID].contains(IndexReg) ||
134609467b48Spatrick IndexReg == X86::EIZ)) {
134709467b48Spatrick ErrMsg = "base register is 64-bit, but index register is not";
134809467b48Spatrick return true;
134909467b48Spatrick }
135009467b48Spatrick if (X86MCRegisterClasses[X86::GR32RegClassID].contains(BaseReg) &&
135109467b48Spatrick (X86MCRegisterClasses[X86::GR16RegClassID].contains(IndexReg) ||
135209467b48Spatrick X86MCRegisterClasses[X86::GR64RegClassID].contains(IndexReg) ||
135309467b48Spatrick IndexReg == X86::RIZ)) {
135409467b48Spatrick ErrMsg = "base register is 32-bit, but index register is not";
135509467b48Spatrick return true;
135609467b48Spatrick }
135709467b48Spatrick if (X86MCRegisterClasses[X86::GR16RegClassID].contains(BaseReg)) {
135809467b48Spatrick if (X86MCRegisterClasses[X86::GR32RegClassID].contains(IndexReg) ||
135909467b48Spatrick X86MCRegisterClasses[X86::GR64RegClassID].contains(IndexReg)) {
136009467b48Spatrick ErrMsg = "base register is 16-bit, but index register is not";
136109467b48Spatrick return true;
136209467b48Spatrick }
136309467b48Spatrick if ((BaseReg != X86::BX && BaseReg != X86::BP) ||
136409467b48Spatrick (IndexReg != X86::SI && IndexReg != X86::DI)) {
136509467b48Spatrick ErrMsg = "invalid 16-bit base/index register combination";
136609467b48Spatrick return true;
136709467b48Spatrick }
136809467b48Spatrick }
136909467b48Spatrick }
137009467b48Spatrick
137109467b48Spatrick // RIP/EIP-relative addressing is only supported in 64-bit mode.
137209467b48Spatrick if (!Is64BitMode && BaseReg != 0 &&
137309467b48Spatrick (BaseReg == X86::RIP || BaseReg == X86::EIP)) {
137409467b48Spatrick ErrMsg = "IP-relative addressing requires 64-bit mode";
137509467b48Spatrick return true;
137609467b48Spatrick }
137709467b48Spatrick
137809467b48Spatrick return checkScale(Scale, ErrMsg);
137909467b48Spatrick }
138009467b48Spatrick
MatchRegisterByName(MCRegister & RegNo,StringRef RegName,SMLoc StartLoc,SMLoc EndLoc)1381*d415bd75Srobert bool X86AsmParser::MatchRegisterByName(MCRegister &RegNo, StringRef RegName,
1382097a140dSpatrick SMLoc StartLoc, SMLoc EndLoc) {
138309467b48Spatrick // If we encounter a %, ignore it. This code handles registers with and
138409467b48Spatrick // without the prefix, unprefixed registers can occur in cfi directives.
1385097a140dSpatrick RegName.consume_front("%");
138609467b48Spatrick
1387097a140dSpatrick RegNo = MatchRegisterName(RegName);
138809467b48Spatrick
138909467b48Spatrick // If the match failed, try the register name as lowercase.
139009467b48Spatrick if (RegNo == 0)
1391097a140dSpatrick RegNo = MatchRegisterName(RegName.lower());
139209467b48Spatrick
139309467b48Spatrick // The "flags" and "mxcsr" registers cannot be referenced directly.
139409467b48Spatrick // Treat it as an identifier instead.
1395097a140dSpatrick if (isParsingMSInlineAsm() && isParsingIntelSyntax() &&
139609467b48Spatrick (RegNo == X86::EFLAGS || RegNo == X86::MXCSR))
139709467b48Spatrick RegNo = 0;
139809467b48Spatrick
139909467b48Spatrick if (!is64BitMode()) {
140009467b48Spatrick // FIXME: This should be done using Requires<Not64BitMode> and
140109467b48Spatrick // Requires<In64BitMode> so "eiz" usage in 64-bit instructions can be also
140209467b48Spatrick // checked.
140309467b48Spatrick if (RegNo == X86::RIZ || RegNo == X86::RIP ||
140409467b48Spatrick X86MCRegisterClasses[X86::GR64RegClassID].contains(RegNo) ||
140509467b48Spatrick X86II::isX86_64NonExtLowByteReg(RegNo) ||
140609467b48Spatrick X86II::isX86_64ExtendedReg(RegNo)) {
140709467b48Spatrick return Error(StartLoc,
140809467b48Spatrick "register %" + RegName + " is only available in 64-bit mode",
140909467b48Spatrick SMRange(StartLoc, EndLoc));
141009467b48Spatrick }
141109467b48Spatrick }
141209467b48Spatrick
1413097a140dSpatrick // If this is "db[0-15]", match it as an alias
1414097a140dSpatrick // for dr[0-15].
1415097a140dSpatrick if (RegNo == 0 && RegName.startswith("db")) {
1416097a140dSpatrick if (RegName.size() == 3) {
1417097a140dSpatrick switch (RegName[2]) {
1418097a140dSpatrick case '0':
1419097a140dSpatrick RegNo = X86::DR0;
1420097a140dSpatrick break;
1421097a140dSpatrick case '1':
1422097a140dSpatrick RegNo = X86::DR1;
1423097a140dSpatrick break;
1424097a140dSpatrick case '2':
1425097a140dSpatrick RegNo = X86::DR2;
1426097a140dSpatrick break;
1427097a140dSpatrick case '3':
1428097a140dSpatrick RegNo = X86::DR3;
1429097a140dSpatrick break;
1430097a140dSpatrick case '4':
1431097a140dSpatrick RegNo = X86::DR4;
1432097a140dSpatrick break;
1433097a140dSpatrick case '5':
1434097a140dSpatrick RegNo = X86::DR5;
1435097a140dSpatrick break;
1436097a140dSpatrick case '6':
1437097a140dSpatrick RegNo = X86::DR6;
1438097a140dSpatrick break;
1439097a140dSpatrick case '7':
1440097a140dSpatrick RegNo = X86::DR7;
1441097a140dSpatrick break;
1442097a140dSpatrick case '8':
1443097a140dSpatrick RegNo = X86::DR8;
1444097a140dSpatrick break;
1445097a140dSpatrick case '9':
1446097a140dSpatrick RegNo = X86::DR9;
1447097a140dSpatrick break;
1448097a140dSpatrick }
1449097a140dSpatrick } else if (RegName.size() == 4 && RegName[2] == '1') {
1450097a140dSpatrick switch (RegName[3]) {
1451097a140dSpatrick case '0':
1452097a140dSpatrick RegNo = X86::DR10;
1453097a140dSpatrick break;
1454097a140dSpatrick case '1':
1455097a140dSpatrick RegNo = X86::DR11;
1456097a140dSpatrick break;
1457097a140dSpatrick case '2':
1458097a140dSpatrick RegNo = X86::DR12;
1459097a140dSpatrick break;
1460097a140dSpatrick case '3':
1461097a140dSpatrick RegNo = X86::DR13;
1462097a140dSpatrick break;
1463097a140dSpatrick case '4':
1464097a140dSpatrick RegNo = X86::DR14;
1465097a140dSpatrick break;
1466097a140dSpatrick case '5':
1467097a140dSpatrick RegNo = X86::DR15;
1468097a140dSpatrick break;
1469097a140dSpatrick }
1470097a140dSpatrick }
1471097a140dSpatrick }
1472097a140dSpatrick
1473097a140dSpatrick if (RegNo == 0) {
1474097a140dSpatrick if (isParsingIntelSyntax())
1475097a140dSpatrick return true;
1476097a140dSpatrick return Error(StartLoc, "invalid register name", SMRange(StartLoc, EndLoc));
1477097a140dSpatrick }
1478097a140dSpatrick return false;
1479097a140dSpatrick }
1480097a140dSpatrick
ParseRegister(MCRegister & RegNo,SMLoc & StartLoc,SMLoc & EndLoc,bool RestoreOnFailure)1481*d415bd75Srobert bool X86AsmParser::ParseRegister(MCRegister &RegNo, SMLoc &StartLoc,
1482097a140dSpatrick SMLoc &EndLoc, bool RestoreOnFailure) {
1483097a140dSpatrick MCAsmParser &Parser = getParser();
1484097a140dSpatrick MCAsmLexer &Lexer = getLexer();
1485097a140dSpatrick RegNo = 0;
1486097a140dSpatrick
1487097a140dSpatrick SmallVector<AsmToken, 5> Tokens;
1488097a140dSpatrick auto OnFailure = [RestoreOnFailure, &Lexer, &Tokens]() {
1489097a140dSpatrick if (RestoreOnFailure) {
1490097a140dSpatrick while (!Tokens.empty()) {
1491097a140dSpatrick Lexer.UnLex(Tokens.pop_back_val());
1492097a140dSpatrick }
1493097a140dSpatrick }
1494097a140dSpatrick };
1495097a140dSpatrick
1496097a140dSpatrick const AsmToken &PercentTok = Parser.getTok();
1497097a140dSpatrick StartLoc = PercentTok.getLoc();
1498097a140dSpatrick
1499097a140dSpatrick // If we encounter a %, ignore it. This code handles registers with and
1500097a140dSpatrick // without the prefix, unprefixed registers can occur in cfi directives.
1501097a140dSpatrick if (!isParsingIntelSyntax() && PercentTok.is(AsmToken::Percent)) {
1502097a140dSpatrick Tokens.push_back(PercentTok);
1503097a140dSpatrick Parser.Lex(); // Eat percent token.
1504097a140dSpatrick }
1505097a140dSpatrick
1506097a140dSpatrick const AsmToken &Tok = Parser.getTok();
1507097a140dSpatrick EndLoc = Tok.getEndLoc();
1508097a140dSpatrick
1509097a140dSpatrick if (Tok.isNot(AsmToken::Identifier)) {
1510097a140dSpatrick OnFailure();
1511097a140dSpatrick if (isParsingIntelSyntax()) return true;
1512097a140dSpatrick return Error(StartLoc, "invalid register name",
1513097a140dSpatrick SMRange(StartLoc, EndLoc));
1514097a140dSpatrick }
1515097a140dSpatrick
1516097a140dSpatrick if (MatchRegisterByName(RegNo, Tok.getString(), StartLoc, EndLoc)) {
1517097a140dSpatrick OnFailure();
1518097a140dSpatrick return true;
1519097a140dSpatrick }
1520097a140dSpatrick
152109467b48Spatrick // Parse "%st" as "%st(0)" and "%st(1)", which is multiple tokens.
152209467b48Spatrick if (RegNo == X86::ST0) {
1523097a140dSpatrick Tokens.push_back(Tok);
152409467b48Spatrick Parser.Lex(); // Eat 'st'
152509467b48Spatrick
152609467b48Spatrick // Check to see if we have '(4)' after %st.
1527097a140dSpatrick if (Lexer.isNot(AsmToken::LParen))
152809467b48Spatrick return false;
152909467b48Spatrick // Lex the paren.
1530097a140dSpatrick Tokens.push_back(Parser.getTok());
1531097a140dSpatrick Parser.Lex();
153209467b48Spatrick
153309467b48Spatrick const AsmToken &IntTok = Parser.getTok();
1534097a140dSpatrick if (IntTok.isNot(AsmToken::Integer)) {
1535097a140dSpatrick OnFailure();
153609467b48Spatrick return Error(IntTok.getLoc(), "expected stack index");
1537097a140dSpatrick }
153809467b48Spatrick switch (IntTok.getIntVal()) {
153909467b48Spatrick case 0: RegNo = X86::ST0; break;
154009467b48Spatrick case 1: RegNo = X86::ST1; break;
154109467b48Spatrick case 2: RegNo = X86::ST2; break;
154209467b48Spatrick case 3: RegNo = X86::ST3; break;
154309467b48Spatrick case 4: RegNo = X86::ST4; break;
154409467b48Spatrick case 5: RegNo = X86::ST5; break;
154509467b48Spatrick case 6: RegNo = X86::ST6; break;
154609467b48Spatrick case 7: RegNo = X86::ST7; break;
1547097a140dSpatrick default:
1548097a140dSpatrick OnFailure();
1549097a140dSpatrick return Error(IntTok.getLoc(), "invalid stack index");
155009467b48Spatrick }
155109467b48Spatrick
1552097a140dSpatrick // Lex IntTok
1553097a140dSpatrick Tokens.push_back(IntTok);
1554097a140dSpatrick Parser.Lex();
1555097a140dSpatrick if (Lexer.isNot(AsmToken::RParen)) {
1556097a140dSpatrick OnFailure();
155709467b48Spatrick return Error(Parser.getTok().getLoc(), "expected ')'");
1558097a140dSpatrick }
155909467b48Spatrick
156009467b48Spatrick EndLoc = Parser.getTok().getEndLoc();
156109467b48Spatrick Parser.Lex(); // Eat ')'
156209467b48Spatrick return false;
156309467b48Spatrick }
156409467b48Spatrick
156509467b48Spatrick EndLoc = Parser.getTok().getEndLoc();
156609467b48Spatrick
156709467b48Spatrick if (RegNo == 0) {
1568097a140dSpatrick OnFailure();
156909467b48Spatrick if (isParsingIntelSyntax()) return true;
157009467b48Spatrick return Error(StartLoc, "invalid register name",
157109467b48Spatrick SMRange(StartLoc, EndLoc));
157209467b48Spatrick }
157309467b48Spatrick
157409467b48Spatrick Parser.Lex(); // Eat identifier token.
157509467b48Spatrick return false;
157609467b48Spatrick }
157709467b48Spatrick
parseRegister(MCRegister & RegNo,SMLoc & StartLoc,SMLoc & EndLoc)1578*d415bd75Srobert bool X86AsmParser::parseRegister(MCRegister &RegNo, SMLoc &StartLoc,
1579097a140dSpatrick SMLoc &EndLoc) {
1580097a140dSpatrick return ParseRegister(RegNo, StartLoc, EndLoc, /*RestoreOnFailure=*/false);
1581097a140dSpatrick }
1582097a140dSpatrick
tryParseRegister(MCRegister & RegNo,SMLoc & StartLoc,SMLoc & EndLoc)1583*d415bd75Srobert OperandMatchResultTy X86AsmParser::tryParseRegister(MCRegister &RegNo,
1584097a140dSpatrick SMLoc &StartLoc,
1585097a140dSpatrick SMLoc &EndLoc) {
1586097a140dSpatrick bool Result =
1587097a140dSpatrick ParseRegister(RegNo, StartLoc, EndLoc, /*RestoreOnFailure=*/true);
1588097a140dSpatrick bool PendingErrors = getParser().hasPendingError();
1589097a140dSpatrick getParser().clearPendingErrors();
1590097a140dSpatrick if (PendingErrors)
1591097a140dSpatrick return MatchOperand_ParseFail;
1592097a140dSpatrick if (Result)
1593097a140dSpatrick return MatchOperand_NoMatch;
1594097a140dSpatrick return MatchOperand_Success;
1595097a140dSpatrick }
1596097a140dSpatrick
DefaultMemSIOperand(SMLoc Loc)159709467b48Spatrick std::unique_ptr<X86Operand> X86AsmParser::DefaultMemSIOperand(SMLoc Loc) {
159809467b48Spatrick bool Parse32 = is32BitMode() || Code16GCC;
159909467b48Spatrick unsigned Basereg = is64BitMode() ? X86::RSI : (Parse32 ? X86::ESI : X86::SI);
160009467b48Spatrick const MCExpr *Disp = MCConstantExpr::create(0, getContext());
160109467b48Spatrick return X86Operand::CreateMem(getPointerWidth(), /*SegReg=*/0, Disp,
160209467b48Spatrick /*BaseReg=*/Basereg, /*IndexReg=*/0, /*Scale=*/1,
160309467b48Spatrick Loc, Loc, 0);
160409467b48Spatrick }
160509467b48Spatrick
DefaultMemDIOperand(SMLoc Loc)160609467b48Spatrick std::unique_ptr<X86Operand> X86AsmParser::DefaultMemDIOperand(SMLoc Loc) {
160709467b48Spatrick bool Parse32 = is32BitMode() || Code16GCC;
160809467b48Spatrick unsigned Basereg = is64BitMode() ? X86::RDI : (Parse32 ? X86::EDI : X86::DI);
160909467b48Spatrick const MCExpr *Disp = MCConstantExpr::create(0, getContext());
161009467b48Spatrick return X86Operand::CreateMem(getPointerWidth(), /*SegReg=*/0, Disp,
161109467b48Spatrick /*BaseReg=*/Basereg, /*IndexReg=*/0, /*Scale=*/1,
161209467b48Spatrick Loc, Loc, 0);
161309467b48Spatrick }
161409467b48Spatrick
IsSIReg(unsigned Reg)161509467b48Spatrick bool X86AsmParser::IsSIReg(unsigned Reg) {
161609467b48Spatrick switch (Reg) {
161709467b48Spatrick default: llvm_unreachable("Only (R|E)SI and (R|E)DI are expected!");
161809467b48Spatrick case X86::RSI:
161909467b48Spatrick case X86::ESI:
162009467b48Spatrick case X86::SI:
162109467b48Spatrick return true;
162209467b48Spatrick case X86::RDI:
162309467b48Spatrick case X86::EDI:
162409467b48Spatrick case X86::DI:
162509467b48Spatrick return false;
162609467b48Spatrick }
162709467b48Spatrick }
162809467b48Spatrick
GetSIDIForRegClass(unsigned RegClassID,unsigned Reg,bool IsSIReg)162909467b48Spatrick unsigned X86AsmParser::GetSIDIForRegClass(unsigned RegClassID, unsigned Reg,
163009467b48Spatrick bool IsSIReg) {
163109467b48Spatrick switch (RegClassID) {
163209467b48Spatrick default: llvm_unreachable("Unexpected register class");
163309467b48Spatrick case X86::GR64RegClassID:
163409467b48Spatrick return IsSIReg ? X86::RSI : X86::RDI;
163509467b48Spatrick case X86::GR32RegClassID:
163609467b48Spatrick return IsSIReg ? X86::ESI : X86::EDI;
163709467b48Spatrick case X86::GR16RegClassID:
163809467b48Spatrick return IsSIReg ? X86::SI : X86::DI;
163909467b48Spatrick }
164009467b48Spatrick }
164109467b48Spatrick
AddDefaultSrcDestOperands(OperandVector & Operands,std::unique_ptr<llvm::MCParsedAsmOperand> && Src,std::unique_ptr<llvm::MCParsedAsmOperand> && Dst)164209467b48Spatrick void X86AsmParser::AddDefaultSrcDestOperands(
164309467b48Spatrick OperandVector& Operands, std::unique_ptr<llvm::MCParsedAsmOperand> &&Src,
164409467b48Spatrick std::unique_ptr<llvm::MCParsedAsmOperand> &&Dst) {
164509467b48Spatrick if (isParsingIntelSyntax()) {
164609467b48Spatrick Operands.push_back(std::move(Dst));
164709467b48Spatrick Operands.push_back(std::move(Src));
164809467b48Spatrick }
164909467b48Spatrick else {
165009467b48Spatrick Operands.push_back(std::move(Src));
165109467b48Spatrick Operands.push_back(std::move(Dst));
165209467b48Spatrick }
165309467b48Spatrick }
165409467b48Spatrick
VerifyAndAdjustOperands(OperandVector & OrigOperands,OperandVector & FinalOperands)165509467b48Spatrick bool X86AsmParser::VerifyAndAdjustOperands(OperandVector &OrigOperands,
165609467b48Spatrick OperandVector &FinalOperands) {
165709467b48Spatrick
165809467b48Spatrick if (OrigOperands.size() > 1) {
165909467b48Spatrick // Check if sizes match, OrigOperands also contains the instruction name
166009467b48Spatrick assert(OrigOperands.size() == FinalOperands.size() + 1 &&
166109467b48Spatrick "Operand size mismatch");
166209467b48Spatrick
166309467b48Spatrick SmallVector<std::pair<SMLoc, std::string>, 2> Warnings;
166409467b48Spatrick // Verify types match
166509467b48Spatrick int RegClassID = -1;
166609467b48Spatrick for (unsigned int i = 0; i < FinalOperands.size(); ++i) {
166709467b48Spatrick X86Operand &OrigOp = static_cast<X86Operand &>(*OrigOperands[i + 1]);
166809467b48Spatrick X86Operand &FinalOp = static_cast<X86Operand &>(*FinalOperands[i]);
166909467b48Spatrick
167009467b48Spatrick if (FinalOp.isReg() &&
167109467b48Spatrick (!OrigOp.isReg() || FinalOp.getReg() != OrigOp.getReg()))
167209467b48Spatrick // Return false and let a normal complaint about bogus operands happen
167309467b48Spatrick return false;
167409467b48Spatrick
167509467b48Spatrick if (FinalOp.isMem()) {
167609467b48Spatrick
167709467b48Spatrick if (!OrigOp.isMem())
167809467b48Spatrick // Return false and let a normal complaint about bogus operands happen
167909467b48Spatrick return false;
168009467b48Spatrick
168109467b48Spatrick unsigned OrigReg = OrigOp.Mem.BaseReg;
168209467b48Spatrick unsigned FinalReg = FinalOp.Mem.BaseReg;
168309467b48Spatrick
168409467b48Spatrick // If we've already encounterd a register class, make sure all register
168509467b48Spatrick // bases are of the same register class
168609467b48Spatrick if (RegClassID != -1 &&
168709467b48Spatrick !X86MCRegisterClasses[RegClassID].contains(OrigReg)) {
168809467b48Spatrick return Error(OrigOp.getStartLoc(),
168909467b48Spatrick "mismatching source and destination index registers");
169009467b48Spatrick }
169109467b48Spatrick
169209467b48Spatrick if (X86MCRegisterClasses[X86::GR64RegClassID].contains(OrigReg))
169309467b48Spatrick RegClassID = X86::GR64RegClassID;
169409467b48Spatrick else if (X86MCRegisterClasses[X86::GR32RegClassID].contains(OrigReg))
169509467b48Spatrick RegClassID = X86::GR32RegClassID;
169609467b48Spatrick else if (X86MCRegisterClasses[X86::GR16RegClassID].contains(OrigReg))
169709467b48Spatrick RegClassID = X86::GR16RegClassID;
169809467b48Spatrick else
169909467b48Spatrick // Unexpected register class type
170009467b48Spatrick // Return false and let a normal complaint about bogus operands happen
170109467b48Spatrick return false;
170209467b48Spatrick
170309467b48Spatrick bool IsSI = IsSIReg(FinalReg);
170409467b48Spatrick FinalReg = GetSIDIForRegClass(RegClassID, FinalReg, IsSI);
170509467b48Spatrick
170609467b48Spatrick if (FinalReg != OrigReg) {
170709467b48Spatrick std::string RegName = IsSI ? "ES:(R|E)SI" : "ES:(R|E)DI";
170809467b48Spatrick Warnings.push_back(std::make_pair(
170909467b48Spatrick OrigOp.getStartLoc(),
171009467b48Spatrick "memory operand is only for determining the size, " + RegName +
171109467b48Spatrick " will be used for the location"));
171209467b48Spatrick }
171309467b48Spatrick
171409467b48Spatrick FinalOp.Mem.Size = OrigOp.Mem.Size;
171509467b48Spatrick FinalOp.Mem.SegReg = OrigOp.Mem.SegReg;
171609467b48Spatrick FinalOp.Mem.BaseReg = FinalReg;
171709467b48Spatrick }
171809467b48Spatrick }
171909467b48Spatrick
172009467b48Spatrick // Produce warnings only if all the operands passed the adjustment - prevent
172109467b48Spatrick // legal cases like "movsd (%rax), %xmm0" mistakenly produce warnings
172209467b48Spatrick for (auto &WarningMsg : Warnings) {
172309467b48Spatrick Warning(WarningMsg.first, WarningMsg.second);
172409467b48Spatrick }
172509467b48Spatrick
172609467b48Spatrick // Remove old operands
172709467b48Spatrick for (unsigned int i = 0; i < FinalOperands.size(); ++i)
172809467b48Spatrick OrigOperands.pop_back();
172909467b48Spatrick }
173009467b48Spatrick // OrigOperands.append(FinalOperands.begin(), FinalOperands.end());
173109467b48Spatrick for (unsigned int i = 0; i < FinalOperands.size(); ++i)
173209467b48Spatrick OrigOperands.push_back(std::move(FinalOperands[i]));
173309467b48Spatrick
173409467b48Spatrick return false;
173509467b48Spatrick }
173609467b48Spatrick
parseOperand(OperandVector & Operands,StringRef Name)1737*d415bd75Srobert bool X86AsmParser::parseOperand(OperandVector &Operands, StringRef Name) {
173809467b48Spatrick if (isParsingIntelSyntax())
1739*d415bd75Srobert return parseIntelOperand(Operands, Name);
174073471bf0Spatrick
1741*d415bd75Srobert return parseATTOperand(Operands);
174209467b48Spatrick }
174309467b48Spatrick
CreateMemForMSInlineAsm(unsigned SegReg,const MCExpr * Disp,unsigned BaseReg,unsigned IndexReg,unsigned Scale,SMLoc Start,SMLoc End,unsigned Size,StringRef Identifier,const InlineAsmIdentifierInfo & Info,OperandVector & Operands)174473471bf0Spatrick bool X86AsmParser::CreateMemForMSInlineAsm(
174509467b48Spatrick unsigned SegReg, const MCExpr *Disp, unsigned BaseReg, unsigned IndexReg,
174609467b48Spatrick unsigned Scale, SMLoc Start, SMLoc End, unsigned Size, StringRef Identifier,
174773471bf0Spatrick const InlineAsmIdentifierInfo &Info, OperandVector &Operands) {
174809467b48Spatrick // If we found a decl other than a VarDecl, then assume it is a FuncDecl or
174909467b48Spatrick // some other label reference.
175009467b48Spatrick if (Info.isKind(InlineAsmIdentifierInfo::IK_Label)) {
175109467b48Spatrick // Insert an explicit size if the user didn't have one.
175209467b48Spatrick if (!Size) {
175309467b48Spatrick Size = getPointerWidth();
175409467b48Spatrick InstInfo->AsmRewrites->emplace_back(AOK_SizeDirective, Start,
175509467b48Spatrick /*Len=*/0, Size);
175609467b48Spatrick }
175709467b48Spatrick // Create an absolute memory reference in order to match against
175809467b48Spatrick // instructions taking a PC relative operand.
175973471bf0Spatrick Operands.push_back(X86Operand::CreateMem(getPointerWidth(), Disp, Start,
176073471bf0Spatrick End, Size, Identifier,
176173471bf0Spatrick Info.Label.Decl));
176273471bf0Spatrick return false;
176309467b48Spatrick }
176409467b48Spatrick // We either have a direct symbol reference, or an offset from a symbol. The
176509467b48Spatrick // parser always puts the symbol on the LHS, so look there for size
176609467b48Spatrick // calculation purposes.
176709467b48Spatrick unsigned FrontendSize = 0;
176809467b48Spatrick void *Decl = nullptr;
176909467b48Spatrick bool IsGlobalLV = false;
177009467b48Spatrick if (Info.isKind(InlineAsmIdentifierInfo::IK_Var)) {
177109467b48Spatrick // Size is in terms of bits in this context.
177209467b48Spatrick FrontendSize = Info.Var.Type * 8;
177309467b48Spatrick Decl = Info.Var.Decl;
177409467b48Spatrick IsGlobalLV = Info.Var.IsGlobalLV;
177509467b48Spatrick }
177609467b48Spatrick // It is widely common for MS InlineAsm to use a global variable and one/two
177709467b48Spatrick // registers in a mmory expression, and though unaccessible via rip/eip.
177809467b48Spatrick if (IsGlobalLV && (BaseReg || IndexReg)) {
1779*d415bd75Srobert Operands.push_back(X86Operand::CreateMem(getPointerWidth(), Disp, Start,
1780*d415bd75Srobert End, Size, Identifier, Decl, 0,
1781*d415bd75Srobert BaseReg && IndexReg));
178273471bf0Spatrick return false;
178373471bf0Spatrick }
178409467b48Spatrick // Otherwise, we set the base register to a non-zero value
178509467b48Spatrick // if we don't know the actual value at this time. This is necessary to
178609467b48Spatrick // get the matching correct in some cases.
178709467b48Spatrick BaseReg = BaseReg ? BaseReg : 1;
178873471bf0Spatrick Operands.push_back(X86Operand::CreateMem(
178973471bf0Spatrick getPointerWidth(), SegReg, Disp, BaseReg, IndexReg, Scale, Start, End,
179073471bf0Spatrick Size,
179173471bf0Spatrick /*DefaultBaseReg=*/X86::RIP, Identifier, Decl, FrontendSize));
179273471bf0Spatrick return false;
179309467b48Spatrick }
179409467b48Spatrick
179509467b48Spatrick // Some binary bitwise operators have a named synonymous
179609467b48Spatrick // Query a candidate string for being such a named operator
179709467b48Spatrick // and if so - invoke the appropriate handler
ParseIntelNamedOperator(StringRef Name,IntelExprStateMachine & SM,bool & ParseError,SMLoc & End)179809467b48Spatrick bool X86AsmParser::ParseIntelNamedOperator(StringRef Name,
179909467b48Spatrick IntelExprStateMachine &SM,
180009467b48Spatrick bool &ParseError, SMLoc &End) {
180173471bf0Spatrick // A named operator should be either lower or upper case, but not a mix...
180273471bf0Spatrick // except in MASM, which uses full case-insensitivity.
180373471bf0Spatrick if (Name.compare(Name.lower()) && Name.compare(Name.upper()) &&
180473471bf0Spatrick !getParser().isParsingMasm())
180509467b48Spatrick return false;
180673471bf0Spatrick if (Name.equals_insensitive("not")) {
180709467b48Spatrick SM.onNot();
180873471bf0Spatrick } else if (Name.equals_insensitive("or")) {
180909467b48Spatrick SM.onOr();
181073471bf0Spatrick } else if (Name.equals_insensitive("shl")) {
181109467b48Spatrick SM.onLShift();
181273471bf0Spatrick } else if (Name.equals_insensitive("shr")) {
181309467b48Spatrick SM.onRShift();
181473471bf0Spatrick } else if (Name.equals_insensitive("xor")) {
181509467b48Spatrick SM.onXor();
181673471bf0Spatrick } else if (Name.equals_insensitive("and")) {
181709467b48Spatrick SM.onAnd();
181873471bf0Spatrick } else if (Name.equals_insensitive("mod")) {
181909467b48Spatrick SM.onMod();
182073471bf0Spatrick } else if (Name.equals_insensitive("offset")) {
182109467b48Spatrick SMLoc OffsetLoc = getTok().getLoc();
182209467b48Spatrick const MCExpr *Val = nullptr;
182309467b48Spatrick StringRef ID;
182409467b48Spatrick InlineAsmIdentifierInfo Info;
182509467b48Spatrick ParseError = ParseIntelOffsetOperator(Val, ID, Info, End);
182609467b48Spatrick if (ParseError)
182709467b48Spatrick return true;
182809467b48Spatrick StringRef ErrMsg;
182909467b48Spatrick ParseError =
1830097a140dSpatrick SM.onOffset(Val, OffsetLoc, ID, Info, isParsingMSInlineAsm(), ErrMsg);
183109467b48Spatrick if (ParseError)
183209467b48Spatrick return Error(SMLoc::getFromPointer(Name.data()), ErrMsg);
183309467b48Spatrick } else {
183409467b48Spatrick return false;
183509467b48Spatrick }
183673471bf0Spatrick if (!Name.equals_insensitive("offset"))
183773471bf0Spatrick End = consumeToken();
183873471bf0Spatrick return true;
183973471bf0Spatrick }
ParseMasmNamedOperator(StringRef Name,IntelExprStateMachine & SM,bool & ParseError,SMLoc & End)184073471bf0Spatrick bool X86AsmParser::ParseMasmNamedOperator(StringRef Name,
184173471bf0Spatrick IntelExprStateMachine &SM,
184273471bf0Spatrick bool &ParseError, SMLoc &End) {
184373471bf0Spatrick if (Name.equals_insensitive("eq")) {
184473471bf0Spatrick SM.onEq();
184573471bf0Spatrick } else if (Name.equals_insensitive("ne")) {
184673471bf0Spatrick SM.onNE();
184773471bf0Spatrick } else if (Name.equals_insensitive("lt")) {
184873471bf0Spatrick SM.onLT();
184973471bf0Spatrick } else if (Name.equals_insensitive("le")) {
185073471bf0Spatrick SM.onLE();
185173471bf0Spatrick } else if (Name.equals_insensitive("gt")) {
185273471bf0Spatrick SM.onGT();
185373471bf0Spatrick } else if (Name.equals_insensitive("ge")) {
185473471bf0Spatrick SM.onGE();
185573471bf0Spatrick } else {
185673471bf0Spatrick return false;
185773471bf0Spatrick }
185809467b48Spatrick End = consumeToken();
185909467b48Spatrick return true;
186009467b48Spatrick }
186109467b48Spatrick
1862*d415bd75Srobert // Check if current intel expression append after an operand.
1863*d415bd75Srobert // Like: [Operand][Intel Expression]
tryParseOperandIdx(AsmToken::TokenKind PrevTK,IntelExprStateMachine & SM)1864*d415bd75Srobert void X86AsmParser::tryParseOperandIdx(AsmToken::TokenKind PrevTK,
1865*d415bd75Srobert IntelExprStateMachine &SM) {
1866*d415bd75Srobert if (PrevTK != AsmToken::RBrac)
1867*d415bd75Srobert return;
1868*d415bd75Srobert
1869*d415bd75Srobert SM.setAppendAfterOperand();
1870*d415bd75Srobert }
1871*d415bd75Srobert
ParseIntelExpression(IntelExprStateMachine & SM,SMLoc & End)187209467b48Spatrick bool X86AsmParser::ParseIntelExpression(IntelExprStateMachine &SM, SMLoc &End) {
187309467b48Spatrick MCAsmParser &Parser = getParser();
187409467b48Spatrick StringRef ErrMsg;
187509467b48Spatrick
187609467b48Spatrick AsmToken::TokenKind PrevTK = AsmToken::Error;
1877*d415bd75Srobert
1878*d415bd75Srobert if (getContext().getObjectFileInfo()->isPositionIndependent())
1879*d415bd75Srobert SM.setPIC();
1880*d415bd75Srobert
188109467b48Spatrick bool Done = false;
188209467b48Spatrick while (!Done) {
188373471bf0Spatrick // Get a fresh reference on each loop iteration in case the previous
188473471bf0Spatrick // iteration moved the token storage during UnLex().
188573471bf0Spatrick const AsmToken &Tok = Parser.getTok();
188673471bf0Spatrick
188709467b48Spatrick bool UpdateLocLex = true;
188809467b48Spatrick AsmToken::TokenKind TK = getLexer().getKind();
188909467b48Spatrick
189009467b48Spatrick switch (TK) {
189109467b48Spatrick default:
189209467b48Spatrick if ((Done = SM.isValidEndState()))
189309467b48Spatrick break;
189409467b48Spatrick return Error(Tok.getLoc(), "unknown token in expression");
189573471bf0Spatrick case AsmToken::Error:
189673471bf0Spatrick return Error(getLexer().getErrLoc(), getLexer().getErr());
189773471bf0Spatrick break;
189809467b48Spatrick case AsmToken::EndOfStatement:
189909467b48Spatrick Done = true;
190009467b48Spatrick break;
190109467b48Spatrick case AsmToken::Real:
190209467b48Spatrick // DotOperator: [ebx].0
190309467b48Spatrick UpdateLocLex = false;
190409467b48Spatrick if (ParseIntelDotOperator(SM, End))
190509467b48Spatrick return true;
190609467b48Spatrick break;
190773471bf0Spatrick case AsmToken::Dot:
190873471bf0Spatrick if (!Parser.isParsingMasm()) {
190973471bf0Spatrick if ((Done = SM.isValidEndState()))
191073471bf0Spatrick break;
191173471bf0Spatrick return Error(Tok.getLoc(), "unknown token in expression");
191273471bf0Spatrick }
191373471bf0Spatrick // MASM allows spaces around the dot operator (e.g., "var . x")
191473471bf0Spatrick Lex();
191573471bf0Spatrick UpdateLocLex = false;
191673471bf0Spatrick if (ParseIntelDotOperator(SM, End))
191773471bf0Spatrick return true;
191873471bf0Spatrick break;
191973471bf0Spatrick case AsmToken::Dollar:
192073471bf0Spatrick if (!Parser.isParsingMasm()) {
192173471bf0Spatrick if ((Done = SM.isValidEndState()))
192273471bf0Spatrick break;
192373471bf0Spatrick return Error(Tok.getLoc(), "unknown token in expression");
192473471bf0Spatrick }
1925*d415bd75Srobert [[fallthrough]];
192673471bf0Spatrick case AsmToken::String: {
192773471bf0Spatrick if (Parser.isParsingMasm()) {
192873471bf0Spatrick // MASM parsers handle strings in expressions as constants.
192973471bf0Spatrick SMLoc ValueLoc = Tok.getLoc();
193073471bf0Spatrick int64_t Res;
193173471bf0Spatrick const MCExpr *Val;
193273471bf0Spatrick if (Parser.parsePrimaryExpr(Val, End, nullptr))
193373471bf0Spatrick return true;
193473471bf0Spatrick UpdateLocLex = false;
193573471bf0Spatrick if (!Val->evaluateAsAbsolute(Res, getStreamer().getAssemblerPtr()))
193673471bf0Spatrick return Error(ValueLoc, "expected absolute value");
193773471bf0Spatrick if (SM.onInteger(Res, ErrMsg))
193873471bf0Spatrick return Error(ValueLoc, ErrMsg);
193973471bf0Spatrick break;
194073471bf0Spatrick }
1941*d415bd75Srobert [[fallthrough]];
194273471bf0Spatrick }
194309467b48Spatrick case AsmToken::At:
194409467b48Spatrick case AsmToken::Identifier: {
194509467b48Spatrick SMLoc IdentLoc = Tok.getLoc();
194609467b48Spatrick StringRef Identifier = Tok.getString();
194709467b48Spatrick UpdateLocLex = false;
194873471bf0Spatrick if (Parser.isParsingMasm()) {
194973471bf0Spatrick size_t DotOffset = Identifier.find_first_of('.');
195073471bf0Spatrick if (DotOffset != StringRef::npos) {
195173471bf0Spatrick consumeToken();
195273471bf0Spatrick StringRef LHS = Identifier.slice(0, DotOffset);
195373471bf0Spatrick StringRef Dot = Identifier.slice(DotOffset, DotOffset + 1);
195473471bf0Spatrick StringRef RHS = Identifier.slice(DotOffset + 1, StringRef::npos);
195573471bf0Spatrick if (!RHS.empty()) {
195673471bf0Spatrick getLexer().UnLex(AsmToken(AsmToken::Identifier, RHS));
195773471bf0Spatrick }
195873471bf0Spatrick getLexer().UnLex(AsmToken(AsmToken::Dot, Dot));
195973471bf0Spatrick if (!LHS.empty()) {
196073471bf0Spatrick getLexer().UnLex(AsmToken(AsmToken::Identifier, LHS));
196173471bf0Spatrick }
196273471bf0Spatrick break;
196373471bf0Spatrick }
196473471bf0Spatrick }
1965097a140dSpatrick // (MASM only) <TYPE> PTR operator
1966097a140dSpatrick if (Parser.isParsingMasm()) {
1967097a140dSpatrick const AsmToken &NextTok = getLexer().peekTok();
1968097a140dSpatrick if (NextTok.is(AsmToken::Identifier) &&
196973471bf0Spatrick NextTok.getIdentifier().equals_insensitive("ptr")) {
197073471bf0Spatrick AsmTypeInfo Info;
197173471bf0Spatrick if (Parser.lookUpType(Identifier, Info))
197273471bf0Spatrick return Error(Tok.getLoc(), "unknown type");
197373471bf0Spatrick SM.onCast(Info);
1974097a140dSpatrick // Eat type and PTR.
1975097a140dSpatrick consumeToken();
1976097a140dSpatrick End = consumeToken();
197709467b48Spatrick break;
197809467b48Spatrick }
1979097a140dSpatrick }
1980097a140dSpatrick // Register, or (MASM only) <register>.<field>
1981*d415bd75Srobert MCRegister Reg;
1982097a140dSpatrick if (Tok.is(AsmToken::Identifier)) {
1983097a140dSpatrick if (!ParseRegister(Reg, IdentLoc, End, /*RestoreOnFailure=*/true)) {
1984097a140dSpatrick if (SM.onRegister(Reg, ErrMsg))
1985097a140dSpatrick return Error(IdentLoc, ErrMsg);
1986097a140dSpatrick break;
1987097a140dSpatrick }
1988097a140dSpatrick if (Parser.isParsingMasm()) {
1989097a140dSpatrick const std::pair<StringRef, StringRef> IDField =
1990097a140dSpatrick Tok.getString().split('.');
1991097a140dSpatrick const StringRef ID = IDField.first, Field = IDField.second;
1992097a140dSpatrick SMLoc IDEndLoc = SMLoc::getFromPointer(ID.data() + ID.size());
1993097a140dSpatrick if (!Field.empty() &&
1994097a140dSpatrick !MatchRegisterByName(Reg, ID, IdentLoc, IDEndLoc)) {
1995097a140dSpatrick if (SM.onRegister(Reg, ErrMsg))
1996097a140dSpatrick return Error(IdentLoc, ErrMsg);
1997097a140dSpatrick
199873471bf0Spatrick AsmFieldInfo Info;
1999097a140dSpatrick SMLoc FieldStartLoc = SMLoc::getFromPointer(Field.data());
200073471bf0Spatrick if (Parser.lookUpField(Field, Info))
2001097a140dSpatrick return Error(FieldStartLoc, "unknown offset");
2002097a140dSpatrick else if (SM.onPlus(ErrMsg))
2003097a140dSpatrick return Error(getTok().getLoc(), ErrMsg);
200473471bf0Spatrick else if (SM.onInteger(Info.Offset, ErrMsg))
2005097a140dSpatrick return Error(IdentLoc, ErrMsg);
200673471bf0Spatrick SM.setTypeInfo(Info.Type);
2007097a140dSpatrick
2008097a140dSpatrick End = consumeToken();
2009097a140dSpatrick break;
2010097a140dSpatrick }
2011097a140dSpatrick }
2012097a140dSpatrick }
201309467b48Spatrick // Operator synonymous ("not", "or" etc.)
201409467b48Spatrick bool ParseError = false;
201509467b48Spatrick if (ParseIntelNamedOperator(Identifier, SM, ParseError, End)) {
201609467b48Spatrick if (ParseError)
201709467b48Spatrick return true;
201809467b48Spatrick break;
201909467b48Spatrick }
202073471bf0Spatrick if (Parser.isParsingMasm() &&
202173471bf0Spatrick ParseMasmNamedOperator(Identifier, SM, ParseError, End)) {
202273471bf0Spatrick if (ParseError)
202373471bf0Spatrick return true;
202473471bf0Spatrick break;
202573471bf0Spatrick }
202609467b48Spatrick // Symbol reference, when parsing assembly content
202709467b48Spatrick InlineAsmIdentifierInfo Info;
202873471bf0Spatrick AsmFieldInfo FieldInfo;
202909467b48Spatrick const MCExpr *Val;
2030097a140dSpatrick if (isParsingMSInlineAsm() || Parser.isParsingMasm()) {
2031097a140dSpatrick // MS Dot Operator expression
2032097a140dSpatrick if (Identifier.count('.') &&
2033097a140dSpatrick (PrevTK == AsmToken::RBrac || PrevTK == AsmToken::RParen)) {
2034097a140dSpatrick if (ParseIntelDotOperator(SM, End))
2035097a140dSpatrick return true;
203609467b48Spatrick break;
203709467b48Spatrick }
2038097a140dSpatrick }
2039097a140dSpatrick if (isParsingMSInlineAsm()) {
204009467b48Spatrick // MS InlineAsm operators (TYPE/LENGTH/SIZE)
204109467b48Spatrick if (unsigned OpKind = IdentifyIntelInlineAsmOperator(Identifier)) {
204209467b48Spatrick if (int64_t Val = ParseIntelInlineAsmOperator(OpKind)) {
204309467b48Spatrick if (SM.onInteger(Val, ErrMsg))
204409467b48Spatrick return Error(IdentLoc, ErrMsg);
204573471bf0Spatrick } else {
204609467b48Spatrick return true;
204773471bf0Spatrick }
204809467b48Spatrick break;
204909467b48Spatrick }
205009467b48Spatrick // MS InlineAsm identifier
205109467b48Spatrick // Call parseIdentifier() to combine @ with the identifier behind it.
205209467b48Spatrick if (TK == AsmToken::At && Parser.parseIdentifier(Identifier))
205309467b48Spatrick return Error(IdentLoc, "expected identifier");
205409467b48Spatrick if (ParseIntelInlineAsmIdentifier(Val, Identifier, Info, false, End))
205509467b48Spatrick return true;
205673471bf0Spatrick else if (SM.onIdentifierExpr(Val, Identifier, Info, FieldInfo.Type,
205773471bf0Spatrick true, ErrMsg))
205809467b48Spatrick return Error(IdentLoc, ErrMsg);
205909467b48Spatrick break;
206009467b48Spatrick }
206173471bf0Spatrick if (Parser.isParsingMasm()) {
206273471bf0Spatrick if (unsigned OpKind = IdentifyMasmOperator(Identifier)) {
206373471bf0Spatrick int64_t Val;
206473471bf0Spatrick if (ParseMasmOperator(OpKind, Val))
206573471bf0Spatrick return true;
206673471bf0Spatrick if (SM.onInteger(Val, ErrMsg))
206773471bf0Spatrick return Error(IdentLoc, ErrMsg);
206873471bf0Spatrick break;
206973471bf0Spatrick }
207073471bf0Spatrick if (!getParser().lookUpType(Identifier, FieldInfo.Type)) {
207173471bf0Spatrick // Field offset immediate; <TYPE>.<field specification>
207273471bf0Spatrick Lex(); // eat type
207373471bf0Spatrick bool EndDot = parseOptionalToken(AsmToken::Dot);
207473471bf0Spatrick while (EndDot || (getTok().is(AsmToken::Identifier) &&
207573471bf0Spatrick getTok().getString().startswith("."))) {
207673471bf0Spatrick getParser().parseIdentifier(Identifier);
207773471bf0Spatrick if (!EndDot)
207873471bf0Spatrick Identifier.consume_front(".");
207973471bf0Spatrick EndDot = Identifier.consume_back(".");
208073471bf0Spatrick if (getParser().lookUpField(FieldInfo.Type.Name, Identifier,
208173471bf0Spatrick FieldInfo)) {
208273471bf0Spatrick SMLoc IDEnd =
208373471bf0Spatrick SMLoc::getFromPointer(Identifier.data() + Identifier.size());
208473471bf0Spatrick return Error(IdentLoc, "Unable to lookup field reference!",
208573471bf0Spatrick SMRange(IdentLoc, IDEnd));
208673471bf0Spatrick }
208773471bf0Spatrick if (!EndDot)
208873471bf0Spatrick EndDot = parseOptionalToken(AsmToken::Dot);
208973471bf0Spatrick }
209073471bf0Spatrick if (SM.onInteger(FieldInfo.Offset, ErrMsg))
209173471bf0Spatrick return Error(IdentLoc, ErrMsg);
209273471bf0Spatrick break;
209373471bf0Spatrick }
209473471bf0Spatrick }
209573471bf0Spatrick if (getParser().parsePrimaryExpr(Val, End, &FieldInfo.Type)) {
2096097a140dSpatrick return Error(Tok.getLoc(), "Unexpected identifier!");
209773471bf0Spatrick } else if (SM.onIdentifierExpr(Val, Identifier, Info, FieldInfo.Type,
209873471bf0Spatrick false, ErrMsg)) {
2099097a140dSpatrick return Error(IdentLoc, ErrMsg);
2100097a140dSpatrick }
2101097a140dSpatrick break;
2102097a140dSpatrick }
210309467b48Spatrick case AsmToken::Integer: {
210409467b48Spatrick // Look for 'b' or 'f' following an Integer as a directional label
210509467b48Spatrick SMLoc Loc = getTok().getLoc();
210609467b48Spatrick int64_t IntVal = getTok().getIntVal();
210709467b48Spatrick End = consumeToken();
210809467b48Spatrick UpdateLocLex = false;
210909467b48Spatrick if (getLexer().getKind() == AsmToken::Identifier) {
211009467b48Spatrick StringRef IDVal = getTok().getString();
211109467b48Spatrick if (IDVal == "f" || IDVal == "b") {
211209467b48Spatrick MCSymbol *Sym =
211309467b48Spatrick getContext().getDirectionalLocalSymbol(IntVal, IDVal == "b");
211409467b48Spatrick MCSymbolRefExpr::VariantKind Variant = MCSymbolRefExpr::VK_None;
211509467b48Spatrick const MCExpr *Val =
211609467b48Spatrick MCSymbolRefExpr::create(Sym, Variant, getContext());
211709467b48Spatrick if (IDVal == "b" && Sym->isUndefined())
211809467b48Spatrick return Error(Loc, "invalid reference to undefined symbol");
211909467b48Spatrick StringRef Identifier = Sym->getName();
212009467b48Spatrick InlineAsmIdentifierInfo Info;
212173471bf0Spatrick AsmTypeInfo Type;
212273471bf0Spatrick if (SM.onIdentifierExpr(Val, Identifier, Info, Type,
212373471bf0Spatrick isParsingMSInlineAsm(), ErrMsg))
212409467b48Spatrick return Error(Loc, ErrMsg);
212509467b48Spatrick End = consumeToken();
212609467b48Spatrick } else {
212709467b48Spatrick if (SM.onInteger(IntVal, ErrMsg))
212809467b48Spatrick return Error(Loc, ErrMsg);
212909467b48Spatrick }
213009467b48Spatrick } else {
213109467b48Spatrick if (SM.onInteger(IntVal, ErrMsg))
213209467b48Spatrick return Error(Loc, ErrMsg);
213309467b48Spatrick }
213409467b48Spatrick break;
213509467b48Spatrick }
213609467b48Spatrick case AsmToken::Plus:
213709467b48Spatrick if (SM.onPlus(ErrMsg))
213809467b48Spatrick return Error(getTok().getLoc(), ErrMsg);
213909467b48Spatrick break;
214009467b48Spatrick case AsmToken::Minus:
214109467b48Spatrick if (SM.onMinus(ErrMsg))
214209467b48Spatrick return Error(getTok().getLoc(), ErrMsg);
214309467b48Spatrick break;
214409467b48Spatrick case AsmToken::Tilde: SM.onNot(); break;
214509467b48Spatrick case AsmToken::Star: SM.onStar(); break;
214609467b48Spatrick case AsmToken::Slash: SM.onDivide(); break;
214709467b48Spatrick case AsmToken::Percent: SM.onMod(); break;
214809467b48Spatrick case AsmToken::Pipe: SM.onOr(); break;
214909467b48Spatrick case AsmToken::Caret: SM.onXor(); break;
215009467b48Spatrick case AsmToken::Amp: SM.onAnd(); break;
215109467b48Spatrick case AsmToken::LessLess:
215209467b48Spatrick SM.onLShift(); break;
215309467b48Spatrick case AsmToken::GreaterGreater:
215409467b48Spatrick SM.onRShift(); break;
215509467b48Spatrick case AsmToken::LBrac:
215609467b48Spatrick if (SM.onLBrac())
215709467b48Spatrick return Error(Tok.getLoc(), "unexpected bracket encountered");
2158*d415bd75Srobert tryParseOperandIdx(PrevTK, SM);
215909467b48Spatrick break;
216009467b48Spatrick case AsmToken::RBrac:
2161*d415bd75Srobert if (SM.onRBrac(ErrMsg)) {
2162*d415bd75Srobert return Error(Tok.getLoc(), ErrMsg);
2163*d415bd75Srobert }
216409467b48Spatrick break;
216509467b48Spatrick case AsmToken::LParen: SM.onLParen(); break;
216609467b48Spatrick case AsmToken::RParen: SM.onRParen(); break;
216709467b48Spatrick }
216809467b48Spatrick if (SM.hadError())
216909467b48Spatrick return Error(Tok.getLoc(), "unknown token in expression");
217009467b48Spatrick
217109467b48Spatrick if (!Done && UpdateLocLex)
217209467b48Spatrick End = consumeToken();
217309467b48Spatrick
217409467b48Spatrick PrevTK = TK;
217509467b48Spatrick }
217609467b48Spatrick return false;
217709467b48Spatrick }
217809467b48Spatrick
RewriteIntelExpression(IntelExprStateMachine & SM,SMLoc Start,SMLoc End)217909467b48Spatrick void X86AsmParser::RewriteIntelExpression(IntelExprStateMachine &SM,
218009467b48Spatrick SMLoc Start, SMLoc End) {
218109467b48Spatrick SMLoc Loc = Start;
218209467b48Spatrick unsigned ExprLen = End.getPointer() - Start.getPointer();
218309467b48Spatrick // Skip everything before a symbol displacement (if we have one)
218409467b48Spatrick if (SM.getSym() && !SM.isOffsetOperator()) {
218509467b48Spatrick StringRef SymName = SM.getSymName();
218609467b48Spatrick if (unsigned Len = SymName.data() - Start.getPointer())
218709467b48Spatrick InstInfo->AsmRewrites->emplace_back(AOK_Skip, Start, Len);
218809467b48Spatrick Loc = SMLoc::getFromPointer(SymName.data() + SymName.size());
218909467b48Spatrick ExprLen = End.getPointer() - (SymName.data() + SymName.size());
219009467b48Spatrick // If we have only a symbol than there's no need for complex rewrite,
219109467b48Spatrick // simply skip everything after it
219209467b48Spatrick if (!(SM.getBaseReg() || SM.getIndexReg() || SM.getImm())) {
219309467b48Spatrick if (ExprLen)
219409467b48Spatrick InstInfo->AsmRewrites->emplace_back(AOK_Skip, Loc, ExprLen);
219509467b48Spatrick return;
219609467b48Spatrick }
219709467b48Spatrick }
219809467b48Spatrick // Build an Intel Expression rewrite
219909467b48Spatrick StringRef BaseRegStr;
220009467b48Spatrick StringRef IndexRegStr;
220109467b48Spatrick StringRef OffsetNameStr;
220209467b48Spatrick if (SM.getBaseReg())
220309467b48Spatrick BaseRegStr = X86IntelInstPrinter::getRegisterName(SM.getBaseReg());
220409467b48Spatrick if (SM.getIndexReg())
220509467b48Spatrick IndexRegStr = X86IntelInstPrinter::getRegisterName(SM.getIndexReg());
220609467b48Spatrick if (SM.isOffsetOperator())
220709467b48Spatrick OffsetNameStr = SM.getSymName();
220809467b48Spatrick // Emit it
220909467b48Spatrick IntelExpr Expr(BaseRegStr, IndexRegStr, SM.getScale(), OffsetNameStr,
221009467b48Spatrick SM.getImm(), SM.isMemExpr());
221109467b48Spatrick InstInfo->AsmRewrites->emplace_back(Loc, ExprLen, Expr);
221209467b48Spatrick }
221309467b48Spatrick
221409467b48Spatrick // Inline assembly may use variable names with namespace alias qualifiers.
ParseIntelInlineAsmIdentifier(const MCExpr * & Val,StringRef & Identifier,InlineAsmIdentifierInfo & Info,bool IsUnevaluatedOperand,SMLoc & End,bool IsParsingOffsetOperator)221509467b48Spatrick bool X86AsmParser::ParseIntelInlineAsmIdentifier(
221609467b48Spatrick const MCExpr *&Val, StringRef &Identifier, InlineAsmIdentifierInfo &Info,
221709467b48Spatrick bool IsUnevaluatedOperand, SMLoc &End, bool IsParsingOffsetOperator) {
221809467b48Spatrick MCAsmParser &Parser = getParser();
2219097a140dSpatrick assert(isParsingMSInlineAsm() && "Expected to be parsing inline assembly.");
222009467b48Spatrick Val = nullptr;
222109467b48Spatrick
222209467b48Spatrick StringRef LineBuf(Identifier.data());
222309467b48Spatrick SemaCallback->LookupInlineAsmIdentifier(LineBuf, Info, IsUnevaluatedOperand);
222409467b48Spatrick
222509467b48Spatrick const AsmToken &Tok = Parser.getTok();
222609467b48Spatrick SMLoc Loc = Tok.getLoc();
222709467b48Spatrick
222809467b48Spatrick // Advance the token stream until the end of the current token is
222909467b48Spatrick // after the end of what the frontend claimed.
223009467b48Spatrick const char *EndPtr = Tok.getLoc().getPointer() + LineBuf.size();
223109467b48Spatrick do {
223209467b48Spatrick End = Tok.getEndLoc();
223309467b48Spatrick getLexer().Lex();
223409467b48Spatrick } while (End.getPointer() < EndPtr);
223509467b48Spatrick Identifier = LineBuf;
223609467b48Spatrick
223709467b48Spatrick // The frontend should end parsing on an assembler token boundary, unless it
223809467b48Spatrick // failed parsing.
223909467b48Spatrick assert((End.getPointer() == EndPtr ||
224009467b48Spatrick Info.isKind(InlineAsmIdentifierInfo::IK_Invalid)) &&
224109467b48Spatrick "frontend claimed part of a token?");
224209467b48Spatrick
224309467b48Spatrick // If the identifier lookup was unsuccessful, assume that we are dealing with
224409467b48Spatrick // a label.
224509467b48Spatrick if (Info.isKind(InlineAsmIdentifierInfo::IK_Invalid)) {
224609467b48Spatrick StringRef InternalName =
224709467b48Spatrick SemaCallback->LookupInlineAsmLabel(Identifier, getSourceManager(),
224809467b48Spatrick Loc, false);
224909467b48Spatrick assert(InternalName.size() && "We should have an internal name here.");
225009467b48Spatrick // Push a rewrite for replacing the identifier name with the internal name,
225109467b48Spatrick // unless we are parsing the operand of an offset operator
225209467b48Spatrick if (!IsParsingOffsetOperator)
225309467b48Spatrick InstInfo->AsmRewrites->emplace_back(AOK_Label, Loc, Identifier.size(),
225409467b48Spatrick InternalName);
225509467b48Spatrick else
225609467b48Spatrick Identifier = InternalName;
225709467b48Spatrick } else if (Info.isKind(InlineAsmIdentifierInfo::IK_EnumVal))
225809467b48Spatrick return false;
225909467b48Spatrick // Create the symbol reference.
226009467b48Spatrick MCSymbol *Sym = getContext().getOrCreateSymbol(Identifier);
226109467b48Spatrick MCSymbolRefExpr::VariantKind Variant = MCSymbolRefExpr::VK_None;
226209467b48Spatrick Val = MCSymbolRefExpr::create(Sym, Variant, getParser().getContext());
226309467b48Spatrick return false;
226409467b48Spatrick }
226509467b48Spatrick
226609467b48Spatrick //ParseRoundingModeOp - Parse AVX-512 rounding mode operand
ParseRoundingModeOp(SMLoc Start,OperandVector & Operands)226773471bf0Spatrick bool X86AsmParser::ParseRoundingModeOp(SMLoc Start, OperandVector &Operands) {
226809467b48Spatrick MCAsmParser &Parser = getParser();
226909467b48Spatrick const AsmToken &Tok = Parser.getTok();
227009467b48Spatrick // Eat "{" and mark the current place.
227109467b48Spatrick const SMLoc consumedToken = consumeToken();
227209467b48Spatrick if (Tok.isNot(AsmToken::Identifier))
227373471bf0Spatrick return Error(Tok.getLoc(), "Expected an identifier after {");
227409467b48Spatrick if (Tok.getIdentifier().startswith("r")){
227509467b48Spatrick int rndMode = StringSwitch<int>(Tok.getIdentifier())
227609467b48Spatrick .Case("rn", X86::STATIC_ROUNDING::TO_NEAREST_INT)
227709467b48Spatrick .Case("rd", X86::STATIC_ROUNDING::TO_NEG_INF)
227809467b48Spatrick .Case("ru", X86::STATIC_ROUNDING::TO_POS_INF)
227909467b48Spatrick .Case("rz", X86::STATIC_ROUNDING::TO_ZERO)
228009467b48Spatrick .Default(-1);
228109467b48Spatrick if (-1 == rndMode)
228273471bf0Spatrick return Error(Tok.getLoc(), "Invalid rounding mode.");
228309467b48Spatrick Parser.Lex(); // Eat "r*" of r*-sae
228409467b48Spatrick if (!getLexer().is(AsmToken::Minus))
228573471bf0Spatrick return Error(Tok.getLoc(), "Expected - at this point");
228609467b48Spatrick Parser.Lex(); // Eat "-"
228709467b48Spatrick Parser.Lex(); // Eat the sae
228809467b48Spatrick if (!getLexer().is(AsmToken::RCurly))
228973471bf0Spatrick return Error(Tok.getLoc(), "Expected } at this point");
229009467b48Spatrick SMLoc End = Tok.getEndLoc();
229109467b48Spatrick Parser.Lex(); // Eat "}"
229209467b48Spatrick const MCExpr *RndModeOp =
229309467b48Spatrick MCConstantExpr::create(rndMode, Parser.getContext());
229473471bf0Spatrick Operands.push_back(X86Operand::CreateImm(RndModeOp, Start, End));
229573471bf0Spatrick return false;
229609467b48Spatrick }
229709467b48Spatrick if(Tok.getIdentifier().equals("sae")){
229809467b48Spatrick Parser.Lex(); // Eat the sae
229909467b48Spatrick if (!getLexer().is(AsmToken::RCurly))
230073471bf0Spatrick return Error(Tok.getLoc(), "Expected } at this point");
230109467b48Spatrick Parser.Lex(); // Eat "}"
230273471bf0Spatrick Operands.push_back(X86Operand::CreateToken("{sae}", consumedToken));
230373471bf0Spatrick return false;
230409467b48Spatrick }
230573471bf0Spatrick return Error(Tok.getLoc(), "unknown token in expression");
230609467b48Spatrick }
230709467b48Spatrick
230809467b48Spatrick /// Parse the '.' operator.
ParseIntelDotOperator(IntelExprStateMachine & SM,SMLoc & End)2309097a140dSpatrick bool X86AsmParser::ParseIntelDotOperator(IntelExprStateMachine &SM,
2310097a140dSpatrick SMLoc &End) {
231109467b48Spatrick const AsmToken &Tok = getTok();
231273471bf0Spatrick AsmFieldInfo Info;
231309467b48Spatrick
231409467b48Spatrick // Drop the optional '.'.
231509467b48Spatrick StringRef DotDispStr = Tok.getString();
231609467b48Spatrick if (DotDispStr.startswith("."))
231709467b48Spatrick DotDispStr = DotDispStr.drop_front(1);
231873471bf0Spatrick StringRef TrailingDot;
231909467b48Spatrick
232009467b48Spatrick // .Imm gets lexed as a real.
232109467b48Spatrick if (Tok.is(AsmToken::Real)) {
232209467b48Spatrick APInt DotDisp;
232309467b48Spatrick DotDispStr.getAsInteger(10, DotDisp);
232473471bf0Spatrick Info.Offset = DotDisp.getZExtValue();
2325097a140dSpatrick } else if ((isParsingMSInlineAsm() || getParser().isParsingMasm()) &&
2326097a140dSpatrick Tok.is(AsmToken::Identifier)) {
232773471bf0Spatrick if (DotDispStr.endswith(".")) {
232873471bf0Spatrick TrailingDot = DotDispStr.substr(DotDispStr.size() - 1);
232973471bf0Spatrick DotDispStr = DotDispStr.drop_back(1);
233073471bf0Spatrick }
2331097a140dSpatrick const std::pair<StringRef, StringRef> BaseMember = DotDispStr.split('.');
2332097a140dSpatrick const StringRef Base = BaseMember.first, Member = BaseMember.second;
233373471bf0Spatrick if (getParser().lookUpField(SM.getType(), DotDispStr, Info) &&
233473471bf0Spatrick getParser().lookUpField(SM.getSymName(), DotDispStr, Info) &&
233573471bf0Spatrick getParser().lookUpField(DotDispStr, Info) &&
2336097a140dSpatrick (!SemaCallback ||
233773471bf0Spatrick SemaCallback->LookupInlineAsmField(Base, Member, Info.Offset)))
233809467b48Spatrick return Error(Tok.getLoc(), "Unable to lookup field reference!");
233973471bf0Spatrick } else {
234009467b48Spatrick return Error(Tok.getLoc(), "Unexpected token type!");
234173471bf0Spatrick }
234209467b48Spatrick
234309467b48Spatrick // Eat the DotExpression and update End
234409467b48Spatrick End = SMLoc::getFromPointer(DotDispStr.data());
234509467b48Spatrick const char *DotExprEndLoc = DotDispStr.data() + DotDispStr.size();
234609467b48Spatrick while (Tok.getLoc().getPointer() < DotExprEndLoc)
234709467b48Spatrick Lex();
234873471bf0Spatrick if (!TrailingDot.empty())
234973471bf0Spatrick getLexer().UnLex(AsmToken(AsmToken::Dot, TrailingDot));
235073471bf0Spatrick SM.addImm(Info.Offset);
235173471bf0Spatrick SM.setTypeInfo(Info.Type);
235209467b48Spatrick return false;
235309467b48Spatrick }
235409467b48Spatrick
235509467b48Spatrick /// Parse the 'offset' operator.
235609467b48Spatrick /// This operator is used to specify the location of a given operand
ParseIntelOffsetOperator(const MCExpr * & Val,StringRef & ID,InlineAsmIdentifierInfo & Info,SMLoc & End)235709467b48Spatrick bool X86AsmParser::ParseIntelOffsetOperator(const MCExpr *&Val, StringRef &ID,
235809467b48Spatrick InlineAsmIdentifierInfo &Info,
235909467b48Spatrick SMLoc &End) {
236009467b48Spatrick // Eat offset, mark start of identifier.
236109467b48Spatrick SMLoc Start = Lex().getLoc();
236209467b48Spatrick ID = getTok().getString();
2363097a140dSpatrick if (!isParsingMSInlineAsm()) {
236409467b48Spatrick if ((getTok().isNot(AsmToken::Identifier) &&
236509467b48Spatrick getTok().isNot(AsmToken::String)) ||
236673471bf0Spatrick getParser().parsePrimaryExpr(Val, End, nullptr))
236709467b48Spatrick return Error(Start, "unexpected token!");
236809467b48Spatrick } else if (ParseIntelInlineAsmIdentifier(Val, ID, Info, false, End, true)) {
236909467b48Spatrick return Error(Start, "unable to lookup expression");
237009467b48Spatrick } else if (Info.isKind(InlineAsmIdentifierInfo::IK_EnumVal)) {
237109467b48Spatrick return Error(Start, "offset operator cannot yet handle constants");
237209467b48Spatrick }
237309467b48Spatrick return false;
237409467b48Spatrick }
237509467b48Spatrick
237609467b48Spatrick // Query a candidate string for being an Intel assembly operator
237709467b48Spatrick // Report back its kind, or IOK_INVALID if does not evaluated as a known one
IdentifyIntelInlineAsmOperator(StringRef Name)237809467b48Spatrick unsigned X86AsmParser::IdentifyIntelInlineAsmOperator(StringRef Name) {
237909467b48Spatrick return StringSwitch<unsigned>(Name)
238009467b48Spatrick .Cases("TYPE","type",IOK_TYPE)
238109467b48Spatrick .Cases("SIZE","size",IOK_SIZE)
238209467b48Spatrick .Cases("LENGTH","length",IOK_LENGTH)
238309467b48Spatrick .Default(IOK_INVALID);
238409467b48Spatrick }
238509467b48Spatrick
238609467b48Spatrick /// Parse the 'LENGTH', 'TYPE' and 'SIZE' operators. The LENGTH operator
238709467b48Spatrick /// returns the number of elements in an array. It returns the value 1 for
238809467b48Spatrick /// non-array variables. The SIZE operator returns the size of a C or C++
238909467b48Spatrick /// variable. A variable's size is the product of its LENGTH and TYPE. The
239009467b48Spatrick /// TYPE operator returns the size of a C or C++ type or variable. If the
239109467b48Spatrick /// variable is an array, TYPE returns the size of a single element.
ParseIntelInlineAsmOperator(unsigned OpKind)239209467b48Spatrick unsigned X86AsmParser::ParseIntelInlineAsmOperator(unsigned OpKind) {
239309467b48Spatrick MCAsmParser &Parser = getParser();
239409467b48Spatrick const AsmToken &Tok = Parser.getTok();
239509467b48Spatrick Parser.Lex(); // Eat operator.
239609467b48Spatrick
239709467b48Spatrick const MCExpr *Val = nullptr;
239809467b48Spatrick InlineAsmIdentifierInfo Info;
239909467b48Spatrick SMLoc Start = Tok.getLoc(), End;
240009467b48Spatrick StringRef Identifier = Tok.getString();
240109467b48Spatrick if (ParseIntelInlineAsmIdentifier(Val, Identifier, Info,
240273471bf0Spatrick /*IsUnevaluatedOperand=*/true, End))
240309467b48Spatrick return 0;
240409467b48Spatrick
240509467b48Spatrick if (!Info.isKind(InlineAsmIdentifierInfo::IK_Var)) {
240609467b48Spatrick Error(Start, "unable to lookup expression");
240709467b48Spatrick return 0;
240809467b48Spatrick }
240909467b48Spatrick
241009467b48Spatrick unsigned CVal = 0;
241109467b48Spatrick switch(OpKind) {
241209467b48Spatrick default: llvm_unreachable("Unexpected operand kind!");
241309467b48Spatrick case IOK_LENGTH: CVal = Info.Var.Length; break;
241409467b48Spatrick case IOK_SIZE: CVal = Info.Var.Size; break;
241509467b48Spatrick case IOK_TYPE: CVal = Info.Var.Type; break;
241609467b48Spatrick }
241709467b48Spatrick
241809467b48Spatrick return CVal;
241909467b48Spatrick }
242009467b48Spatrick
242173471bf0Spatrick // Query a candidate string for being an Intel assembly operator
242273471bf0Spatrick // Report back its kind, or IOK_INVALID if does not evaluated as a known one
IdentifyMasmOperator(StringRef Name)242373471bf0Spatrick unsigned X86AsmParser::IdentifyMasmOperator(StringRef Name) {
242473471bf0Spatrick return StringSwitch<unsigned>(Name.lower())
242573471bf0Spatrick .Case("type", MOK_TYPE)
242673471bf0Spatrick .Cases("size", "sizeof", MOK_SIZEOF)
242773471bf0Spatrick .Cases("length", "lengthof", MOK_LENGTHOF)
242873471bf0Spatrick .Default(MOK_INVALID);
242973471bf0Spatrick }
243073471bf0Spatrick
243173471bf0Spatrick /// Parse the 'LENGTHOF', 'SIZEOF', and 'TYPE' operators. The LENGTHOF operator
243273471bf0Spatrick /// returns the number of elements in an array. It returns the value 1 for
243373471bf0Spatrick /// non-array variables. The SIZEOF operator returns the size of a type or
243473471bf0Spatrick /// variable in bytes. A variable's size is the product of its LENGTH and TYPE.
243573471bf0Spatrick /// The TYPE operator returns the size of a variable. If the variable is an
243673471bf0Spatrick /// array, TYPE returns the size of a single element.
ParseMasmOperator(unsigned OpKind,int64_t & Val)243773471bf0Spatrick bool X86AsmParser::ParseMasmOperator(unsigned OpKind, int64_t &Val) {
243873471bf0Spatrick MCAsmParser &Parser = getParser();
243973471bf0Spatrick SMLoc OpLoc = Parser.getTok().getLoc();
244073471bf0Spatrick Parser.Lex(); // Eat operator.
244173471bf0Spatrick
244273471bf0Spatrick Val = 0;
244373471bf0Spatrick if (OpKind == MOK_SIZEOF || OpKind == MOK_TYPE) {
244473471bf0Spatrick // Check for SIZEOF(<type>) and TYPE(<type>).
244573471bf0Spatrick bool InParens = Parser.getTok().is(AsmToken::LParen);
244673471bf0Spatrick const AsmToken &IDTok = InParens ? getLexer().peekTok() : Parser.getTok();
244773471bf0Spatrick AsmTypeInfo Type;
244873471bf0Spatrick if (IDTok.is(AsmToken::Identifier) &&
244973471bf0Spatrick !Parser.lookUpType(IDTok.getIdentifier(), Type)) {
245073471bf0Spatrick Val = Type.Size;
245173471bf0Spatrick
245273471bf0Spatrick // Eat tokens.
245373471bf0Spatrick if (InParens)
245473471bf0Spatrick parseToken(AsmToken::LParen);
245573471bf0Spatrick parseToken(AsmToken::Identifier);
245673471bf0Spatrick if (InParens)
245773471bf0Spatrick parseToken(AsmToken::RParen);
245873471bf0Spatrick }
245973471bf0Spatrick }
246073471bf0Spatrick
246173471bf0Spatrick if (!Val) {
246273471bf0Spatrick IntelExprStateMachine SM;
246373471bf0Spatrick SMLoc End, Start = Parser.getTok().getLoc();
246473471bf0Spatrick if (ParseIntelExpression(SM, End))
246573471bf0Spatrick return true;
246673471bf0Spatrick
246773471bf0Spatrick switch (OpKind) {
246873471bf0Spatrick default:
246973471bf0Spatrick llvm_unreachable("Unexpected operand kind!");
247073471bf0Spatrick case MOK_SIZEOF:
247173471bf0Spatrick Val = SM.getSize();
247273471bf0Spatrick break;
247373471bf0Spatrick case MOK_LENGTHOF:
247473471bf0Spatrick Val = SM.getLength();
247573471bf0Spatrick break;
247673471bf0Spatrick case MOK_TYPE:
247773471bf0Spatrick Val = SM.getElementSize();
247873471bf0Spatrick break;
247973471bf0Spatrick }
248073471bf0Spatrick
248173471bf0Spatrick if (!Val)
248273471bf0Spatrick return Error(OpLoc, "expression has unknown type", SMRange(Start, End));
248373471bf0Spatrick }
248473471bf0Spatrick
248573471bf0Spatrick return false;
248673471bf0Spatrick }
248773471bf0Spatrick
ParseIntelMemoryOperandSize(unsigned & Size)248809467b48Spatrick bool X86AsmParser::ParseIntelMemoryOperandSize(unsigned &Size) {
248909467b48Spatrick Size = StringSwitch<unsigned>(getTok().getString())
249009467b48Spatrick .Cases("BYTE", "byte", 8)
249109467b48Spatrick .Cases("WORD", "word", 16)
249209467b48Spatrick .Cases("DWORD", "dword", 32)
249309467b48Spatrick .Cases("FLOAT", "float", 32)
249409467b48Spatrick .Cases("LONG", "long", 32)
249509467b48Spatrick .Cases("FWORD", "fword", 48)
249609467b48Spatrick .Cases("DOUBLE", "double", 64)
249709467b48Spatrick .Cases("QWORD", "qword", 64)
249809467b48Spatrick .Cases("MMWORD","mmword", 64)
249909467b48Spatrick .Cases("XWORD", "xword", 80)
250009467b48Spatrick .Cases("TBYTE", "tbyte", 80)
250109467b48Spatrick .Cases("XMMWORD", "xmmword", 128)
250209467b48Spatrick .Cases("YMMWORD", "ymmword", 256)
250309467b48Spatrick .Cases("ZMMWORD", "zmmword", 512)
250409467b48Spatrick .Default(0);
250509467b48Spatrick if (Size) {
250609467b48Spatrick const AsmToken &Tok = Lex(); // Eat operand size (e.g., byte, word).
250709467b48Spatrick if (!(Tok.getString().equals("PTR") || Tok.getString().equals("ptr")))
250809467b48Spatrick return Error(Tok.getLoc(), "Expected 'PTR' or 'ptr' token!");
250909467b48Spatrick Lex(); // Eat ptr.
251009467b48Spatrick }
251109467b48Spatrick return false;
251209467b48Spatrick }
251309467b48Spatrick
parseIntelOperand(OperandVector & Operands,StringRef Name)2514*d415bd75Srobert bool X86AsmParser::parseIntelOperand(OperandVector &Operands, StringRef Name) {
251509467b48Spatrick MCAsmParser &Parser = getParser();
251609467b48Spatrick const AsmToken &Tok = Parser.getTok();
251709467b48Spatrick SMLoc Start, End;
251809467b48Spatrick
251909467b48Spatrick // Parse optional Size directive.
252009467b48Spatrick unsigned Size;
252109467b48Spatrick if (ParseIntelMemoryOperandSize(Size))
252273471bf0Spatrick return true;
252309467b48Spatrick bool PtrInOperand = bool(Size);
252409467b48Spatrick
252509467b48Spatrick Start = Tok.getLoc();
252609467b48Spatrick
252709467b48Spatrick // Rounding mode operand.
252809467b48Spatrick if (getLexer().is(AsmToken::LCurly))
252973471bf0Spatrick return ParseRoundingModeOp(Start, Operands);
253009467b48Spatrick
253109467b48Spatrick // Register operand.
2532*d415bd75Srobert MCRegister RegNo;
2533*d415bd75Srobert if (Tok.is(AsmToken::Identifier) && !parseRegister(RegNo, Start, End)) {
253409467b48Spatrick if (RegNo == X86::RIP)
253573471bf0Spatrick return Error(Start, "rip can only be used as a base register");
253609467b48Spatrick // A Register followed by ':' is considered a segment override
253773471bf0Spatrick if (Tok.isNot(AsmToken::Colon)) {
253873471bf0Spatrick if (PtrInOperand)
253973471bf0Spatrick return Error(Start, "expected memory operand after 'ptr', "
254009467b48Spatrick "found register operand instead");
254173471bf0Spatrick Operands.push_back(X86Operand::CreateReg(RegNo, Start, End));
254273471bf0Spatrick return false;
254373471bf0Spatrick }
254409467b48Spatrick // An alleged segment override. check if we have a valid segment register
254509467b48Spatrick if (!X86MCRegisterClasses[X86::SEGMENT_REGRegClassID].contains(RegNo))
254673471bf0Spatrick return Error(Start, "invalid segment register");
254709467b48Spatrick // Eat ':' and update Start location
254809467b48Spatrick Start = Lex().getLoc();
254909467b48Spatrick }
255009467b48Spatrick
255109467b48Spatrick // Immediates and Memory
255209467b48Spatrick IntelExprStateMachine SM;
255309467b48Spatrick if (ParseIntelExpression(SM, End))
255473471bf0Spatrick return true;
255509467b48Spatrick
2556097a140dSpatrick if (isParsingMSInlineAsm())
255709467b48Spatrick RewriteIntelExpression(SM, Start, Tok.getLoc());
255809467b48Spatrick
255909467b48Spatrick int64_t Imm = SM.getImm();
256009467b48Spatrick const MCExpr *Disp = SM.getSym();
256109467b48Spatrick const MCExpr *ImmDisp = MCConstantExpr::create(Imm, getContext());
256209467b48Spatrick if (Disp && Imm)
256309467b48Spatrick Disp = MCBinaryExpr::createAdd(Disp, ImmDisp, getContext());
256409467b48Spatrick if (!Disp)
256509467b48Spatrick Disp = ImmDisp;
256609467b48Spatrick
256709467b48Spatrick // RegNo != 0 specifies a valid segment register,
256809467b48Spatrick // and we are parsing a segment override
256909467b48Spatrick if (!SM.isMemExpr() && !RegNo) {
2570097a140dSpatrick if (isParsingMSInlineAsm() && SM.isOffsetOperator()) {
257173471bf0Spatrick const InlineAsmIdentifierInfo &Info = SM.getIdentifierInfo();
257209467b48Spatrick if (Info.isKind(InlineAsmIdentifierInfo::IK_Var)) {
257309467b48Spatrick // Disp includes the address of a variable; make sure this is recorded
257409467b48Spatrick // for later handling.
257573471bf0Spatrick Operands.push_back(X86Operand::CreateImm(Disp, Start, End,
257673471bf0Spatrick SM.getSymName(), Info.Var.Decl,
257773471bf0Spatrick Info.Var.IsGlobalLV));
257873471bf0Spatrick return false;
257909467b48Spatrick }
258009467b48Spatrick }
258109467b48Spatrick
258273471bf0Spatrick Operands.push_back(X86Operand::CreateImm(Disp, Start, End));
258373471bf0Spatrick return false;
258409467b48Spatrick }
258509467b48Spatrick
258609467b48Spatrick StringRef ErrMsg;
258709467b48Spatrick unsigned BaseReg = SM.getBaseReg();
258809467b48Spatrick unsigned IndexReg = SM.getIndexReg();
2589*d415bd75Srobert if (IndexReg && BaseReg == X86::RIP)
2590*d415bd75Srobert BaseReg = 0;
259109467b48Spatrick unsigned Scale = SM.getScale();
259273471bf0Spatrick if (!PtrInOperand)
259373471bf0Spatrick Size = SM.getElementSize() << 3;
259409467b48Spatrick
259509467b48Spatrick if (Scale == 0 && BaseReg != X86::ESP && BaseReg != X86::RSP &&
259609467b48Spatrick (IndexReg == X86::ESP || IndexReg == X86::RSP))
259709467b48Spatrick std::swap(BaseReg, IndexReg);
259809467b48Spatrick
259909467b48Spatrick // If BaseReg is a vector register and IndexReg is not, swap them unless
260009467b48Spatrick // Scale was specified in which case it would be an error.
260109467b48Spatrick if (Scale == 0 &&
260209467b48Spatrick !(X86MCRegisterClasses[X86::VR128XRegClassID].contains(IndexReg) ||
260309467b48Spatrick X86MCRegisterClasses[X86::VR256XRegClassID].contains(IndexReg) ||
260409467b48Spatrick X86MCRegisterClasses[X86::VR512RegClassID].contains(IndexReg)) &&
260509467b48Spatrick (X86MCRegisterClasses[X86::VR128XRegClassID].contains(BaseReg) ||
260609467b48Spatrick X86MCRegisterClasses[X86::VR256XRegClassID].contains(BaseReg) ||
260709467b48Spatrick X86MCRegisterClasses[X86::VR512RegClassID].contains(BaseReg)))
260809467b48Spatrick std::swap(BaseReg, IndexReg);
260909467b48Spatrick
261009467b48Spatrick if (Scale != 0 &&
261109467b48Spatrick X86MCRegisterClasses[X86::GR16RegClassID].contains(IndexReg))
261273471bf0Spatrick return Error(Start, "16-bit addresses cannot have a scale");
261309467b48Spatrick
261409467b48Spatrick // If there was no explicit scale specified, change it to 1.
261509467b48Spatrick if (Scale == 0)
261609467b48Spatrick Scale = 1;
261709467b48Spatrick
261809467b48Spatrick // If this is a 16-bit addressing mode with the base and index in the wrong
261909467b48Spatrick // order, swap them so CheckBaseRegAndIndexRegAndScale doesn't fail. It is
262009467b48Spatrick // shared with att syntax where order matters.
262109467b48Spatrick if ((BaseReg == X86::SI || BaseReg == X86::DI) &&
262209467b48Spatrick (IndexReg == X86::BX || IndexReg == X86::BP))
262309467b48Spatrick std::swap(BaseReg, IndexReg);
262409467b48Spatrick
262509467b48Spatrick if ((BaseReg || IndexReg) &&
262609467b48Spatrick CheckBaseRegAndIndexRegAndScale(BaseReg, IndexReg, Scale, is64BitMode(),
262709467b48Spatrick ErrMsg))
262873471bf0Spatrick return Error(Start, ErrMsg);
2629097a140dSpatrick if (isParsingMSInlineAsm())
2630097a140dSpatrick return CreateMemForMSInlineAsm(RegNo, Disp, BaseReg, IndexReg, Scale, Start,
2631097a140dSpatrick End, Size, SM.getSymName(),
263273471bf0Spatrick SM.getIdentifierInfo(), Operands);
2633097a140dSpatrick
263473471bf0Spatrick // When parsing x64 MS-style assembly, all non-absolute references to a named
263573471bf0Spatrick // variable default to RIP-relative.
2636*d415bd75Srobert unsigned DefaultBaseReg = X86::NoRegister;
2637*d415bd75Srobert bool MaybeDirectBranchDest = true;
2638*d415bd75Srobert
2639*d415bd75Srobert if (Parser.isParsingMasm()) {
2640*d415bd75Srobert bool IsUnconditionalBranch =
2641*d415bd75Srobert Name.equals_insensitive("jmp") || Name.equals_insensitive("call");
2642*d415bd75Srobert if (is64BitMode() && SM.getElementSize() > 0) {
2643*d415bd75Srobert DefaultBaseReg = X86::RIP;
2644*d415bd75Srobert }
2645*d415bd75Srobert if (IsUnconditionalBranch) {
2646*d415bd75Srobert if (PtrInOperand) {
2647*d415bd75Srobert MaybeDirectBranchDest = false;
2648*d415bd75Srobert if (is64BitMode())
2649*d415bd75Srobert DefaultBaseReg = X86::RIP;
2650*d415bd75Srobert } else if (!BaseReg && !IndexReg && Disp &&
2651*d415bd75Srobert Disp->getKind() == MCExpr::SymbolRef) {
2652*d415bd75Srobert if (is64BitMode()) {
2653*d415bd75Srobert if (SM.getSize() == 8) {
2654*d415bd75Srobert MaybeDirectBranchDest = false;
2655*d415bd75Srobert DefaultBaseReg = X86::RIP;
2656*d415bd75Srobert }
2657*d415bd75Srobert } else {
2658*d415bd75Srobert if (SM.getSize() == 4 || SM.getSize() == 2)
2659*d415bd75Srobert MaybeDirectBranchDest = false;
2660*d415bd75Srobert }
2661*d415bd75Srobert }
2662*d415bd75Srobert }
266309467b48Spatrick }
266409467b48Spatrick
2665*d415bd75Srobert if ((BaseReg || IndexReg || RegNo || DefaultBaseReg != X86::NoRegister))
2666*d415bd75Srobert Operands.push_back(X86Operand::CreateMem(
2667*d415bd75Srobert getPointerWidth(), RegNo, Disp, BaseReg, IndexReg, Scale, Start, End,
2668*d415bd75Srobert Size, DefaultBaseReg, /*SymName=*/StringRef(), /*OpDecl=*/nullptr,
2669*d415bd75Srobert /*FrontendSize=*/0, /*UseUpRegs=*/false, MaybeDirectBranchDest));
267073471bf0Spatrick else
2671*d415bd75Srobert Operands.push_back(X86Operand::CreateMem(
2672*d415bd75Srobert getPointerWidth(), Disp, Start, End, Size, /*SymName=*/StringRef(),
2673*d415bd75Srobert /*OpDecl=*/nullptr, /*FrontendSize=*/0, /*UseUpRegs=*/false,
2674*d415bd75Srobert MaybeDirectBranchDest));
267573471bf0Spatrick return false;
267673471bf0Spatrick }
267773471bf0Spatrick
parseATTOperand(OperandVector & Operands)2678*d415bd75Srobert bool X86AsmParser::parseATTOperand(OperandVector &Operands) {
267909467b48Spatrick MCAsmParser &Parser = getParser();
268009467b48Spatrick switch (getLexer().getKind()) {
268109467b48Spatrick case AsmToken::Dollar: {
268209467b48Spatrick // $42 or $ID -> immediate.
268309467b48Spatrick SMLoc Start = Parser.getTok().getLoc(), End;
268409467b48Spatrick Parser.Lex();
268509467b48Spatrick const MCExpr *Val;
268609467b48Spatrick // This is an immediate, so we should not parse a register. Do a precheck
268709467b48Spatrick // for '%' to supercede intra-register parse errors.
268809467b48Spatrick SMLoc L = Parser.getTok().getLoc();
268909467b48Spatrick if (check(getLexer().is(AsmToken::Percent), L,
269009467b48Spatrick "expected immediate expression") ||
269109467b48Spatrick getParser().parseExpression(Val, End) ||
269209467b48Spatrick check(isa<X86MCExpr>(Val), L, "expected immediate expression"))
269373471bf0Spatrick return true;
269473471bf0Spatrick Operands.push_back(X86Operand::CreateImm(Val, Start, End));
269573471bf0Spatrick return false;
269609467b48Spatrick }
269709467b48Spatrick case AsmToken::LCurly: {
269809467b48Spatrick SMLoc Start = Parser.getTok().getLoc();
269973471bf0Spatrick return ParseRoundingModeOp(Start, Operands);
270009467b48Spatrick }
270109467b48Spatrick default: {
270209467b48Spatrick // This a memory operand or a register. We have some parsing complications
270309467b48Spatrick // as a '(' may be part of an immediate expression or the addressing mode
270409467b48Spatrick // block. This is complicated by the fact that an assembler-level variable
270509467b48Spatrick // may refer either to a register or an immediate expression.
270609467b48Spatrick
270709467b48Spatrick SMLoc Loc = Parser.getTok().getLoc(), EndLoc;
270809467b48Spatrick const MCExpr *Expr = nullptr;
270909467b48Spatrick unsigned Reg = 0;
271009467b48Spatrick if (getLexer().isNot(AsmToken::LParen)) {
271109467b48Spatrick // No '(' so this is either a displacement expression or a register.
271209467b48Spatrick if (Parser.parseExpression(Expr, EndLoc))
271373471bf0Spatrick return true;
271409467b48Spatrick if (auto *RE = dyn_cast<X86MCExpr>(Expr)) {
271509467b48Spatrick // Segment Register. Reset Expr and copy value to register.
271609467b48Spatrick Expr = nullptr;
271709467b48Spatrick Reg = RE->getRegNo();
271809467b48Spatrick
2719*d415bd75Srobert // Check the register.
272009467b48Spatrick if (Reg == X86::EIZ || Reg == X86::RIZ)
272173471bf0Spatrick return Error(
272209467b48Spatrick Loc, "%eiz and %riz can only be used as index registers",
272309467b48Spatrick SMRange(Loc, EndLoc));
272409467b48Spatrick if (Reg == X86::RIP)
272573471bf0Spatrick return Error(Loc, "%rip can only be used as a base register",
272609467b48Spatrick SMRange(Loc, EndLoc));
272709467b48Spatrick // Return register that are not segment prefixes immediately.
272873471bf0Spatrick if (!Parser.parseOptionalToken(AsmToken::Colon)) {
272973471bf0Spatrick Operands.push_back(X86Operand::CreateReg(Reg, Loc, EndLoc));
273073471bf0Spatrick return false;
273173471bf0Spatrick }
273209467b48Spatrick if (!X86MCRegisterClasses[X86::SEGMENT_REGRegClassID].contains(Reg))
273373471bf0Spatrick return Error(Loc, "invalid segment register");
273473471bf0Spatrick // Accept a '*' absolute memory reference after the segment. Place it
273573471bf0Spatrick // before the full memory operand.
273673471bf0Spatrick if (getLexer().is(AsmToken::Star))
273773471bf0Spatrick Operands.push_back(X86Operand::CreateToken("*", consumeToken()));
273809467b48Spatrick }
273909467b48Spatrick }
274009467b48Spatrick // This is a Memory operand.
274173471bf0Spatrick return ParseMemOperand(Reg, Expr, Loc, EndLoc, Operands);
274209467b48Spatrick }
274309467b48Spatrick }
274409467b48Spatrick }
274509467b48Spatrick
274609467b48Spatrick // X86::COND_INVALID if not a recognized condition code or alternate mnemonic,
274709467b48Spatrick // otherwise the EFLAGS Condition Code enumerator.
ParseConditionCode(StringRef CC)274809467b48Spatrick X86::CondCode X86AsmParser::ParseConditionCode(StringRef CC) {
274909467b48Spatrick return StringSwitch<X86::CondCode>(CC)
275009467b48Spatrick .Case("o", X86::COND_O) // Overflow
275109467b48Spatrick .Case("no", X86::COND_NO) // No Overflow
275209467b48Spatrick .Cases("b", "nae", X86::COND_B) // Below/Neither Above nor Equal
275309467b48Spatrick .Cases("ae", "nb", X86::COND_AE) // Above or Equal/Not Below
275409467b48Spatrick .Cases("e", "z", X86::COND_E) // Equal/Zero
275509467b48Spatrick .Cases("ne", "nz", X86::COND_NE) // Not Equal/Not Zero
275609467b48Spatrick .Cases("be", "na", X86::COND_BE) // Below or Equal/Not Above
275709467b48Spatrick .Cases("a", "nbe", X86::COND_A) // Above/Neither Below nor Equal
275809467b48Spatrick .Case("s", X86::COND_S) // Sign
275909467b48Spatrick .Case("ns", X86::COND_NS) // No Sign
276009467b48Spatrick .Cases("p", "pe", X86::COND_P) // Parity/Parity Even
276109467b48Spatrick .Cases("np", "po", X86::COND_NP) // No Parity/Parity Odd
276209467b48Spatrick .Cases("l", "nge", X86::COND_L) // Less/Neither Greater nor Equal
276309467b48Spatrick .Cases("ge", "nl", X86::COND_GE) // Greater or Equal/Not Less
276409467b48Spatrick .Cases("le", "ng", X86::COND_LE) // Less or Equal/Not Greater
276509467b48Spatrick .Cases("g", "nle", X86::COND_G) // Greater/Neither Less nor Equal
276609467b48Spatrick .Default(X86::COND_INVALID);
276709467b48Spatrick }
276809467b48Spatrick
276909467b48Spatrick // true on failure, false otherwise
277009467b48Spatrick // If no {z} mark was found - Parser doesn't advance
ParseZ(std::unique_ptr<X86Operand> & Z,const SMLoc & StartLoc)277109467b48Spatrick bool X86AsmParser::ParseZ(std::unique_ptr<X86Operand> &Z,
277209467b48Spatrick const SMLoc &StartLoc) {
277309467b48Spatrick MCAsmParser &Parser = getParser();
277409467b48Spatrick // Assuming we are just pass the '{' mark, quering the next token
277509467b48Spatrick // Searched for {z}, but none was found. Return false, as no parsing error was
277609467b48Spatrick // encountered
277709467b48Spatrick if (!(getLexer().is(AsmToken::Identifier) &&
277809467b48Spatrick (getLexer().getTok().getIdentifier() == "z")))
277909467b48Spatrick return false;
278009467b48Spatrick Parser.Lex(); // Eat z
278109467b48Spatrick // Query and eat the '}' mark
278209467b48Spatrick if (!getLexer().is(AsmToken::RCurly))
278309467b48Spatrick return Error(getLexer().getLoc(), "Expected } at this point");
278409467b48Spatrick Parser.Lex(); // Eat '}'
2785*d415bd75Srobert // Assign Z with the {z} mark operand
278609467b48Spatrick Z = X86Operand::CreateToken("{z}", StartLoc);
278709467b48Spatrick return false;
278809467b48Spatrick }
278909467b48Spatrick
279009467b48Spatrick // true on failure, false otherwise
HandleAVX512Operand(OperandVector & Operands)279173471bf0Spatrick bool X86AsmParser::HandleAVX512Operand(OperandVector &Operands) {
279209467b48Spatrick MCAsmParser &Parser = getParser();
279309467b48Spatrick if (getLexer().is(AsmToken::LCurly)) {
279409467b48Spatrick // Eat "{" and mark the current place.
279509467b48Spatrick const SMLoc consumedToken = consumeToken();
279609467b48Spatrick // Distinguish {1to<NUM>} from {%k<NUM>}.
279709467b48Spatrick if(getLexer().is(AsmToken::Integer)) {
279809467b48Spatrick // Parse memory broadcasting ({1to<NUM>}).
279909467b48Spatrick if (getLexer().getTok().getIntVal() != 1)
280009467b48Spatrick return TokError("Expected 1to<NUM> at this point");
280173471bf0Spatrick StringRef Prefix = getLexer().getTok().getString();
280273471bf0Spatrick Parser.Lex(); // Eat first token of 1to8
280373471bf0Spatrick if (!getLexer().is(AsmToken::Identifier))
280409467b48Spatrick return TokError("Expected 1to<NUM> at this point");
280509467b48Spatrick // Recognize only reasonable suffixes.
280673471bf0Spatrick SmallVector<char, 5> BroadcastVector;
280773471bf0Spatrick StringRef BroadcastString = (Prefix + getLexer().getTok().getIdentifier())
280873471bf0Spatrick .toStringRef(BroadcastVector);
280973471bf0Spatrick if (!BroadcastString.startswith("1to"))
281073471bf0Spatrick return TokError("Expected 1to<NUM> at this point");
281109467b48Spatrick const char *BroadcastPrimitive =
281273471bf0Spatrick StringSwitch<const char *>(BroadcastString)
281373471bf0Spatrick .Case("1to2", "{1to2}")
281473471bf0Spatrick .Case("1to4", "{1to4}")
281573471bf0Spatrick .Case("1to8", "{1to8}")
281673471bf0Spatrick .Case("1to16", "{1to16}")
2817*d415bd75Srobert .Case("1to32", "{1to32}")
281809467b48Spatrick .Default(nullptr);
281909467b48Spatrick if (!BroadcastPrimitive)
282009467b48Spatrick return TokError("Invalid memory broadcast primitive.");
282173471bf0Spatrick Parser.Lex(); // Eat trailing token of 1toN
282209467b48Spatrick if (!getLexer().is(AsmToken::RCurly))
282309467b48Spatrick return TokError("Expected } at this point");
282409467b48Spatrick Parser.Lex(); // Eat "}"
282509467b48Spatrick Operands.push_back(X86Operand::CreateToken(BroadcastPrimitive,
282609467b48Spatrick consumedToken));
282709467b48Spatrick // No AVX512 specific primitives can pass
282809467b48Spatrick // after memory broadcasting, so return.
282909467b48Spatrick return false;
283009467b48Spatrick } else {
283109467b48Spatrick // Parse either {k}{z}, {z}{k}, {k} or {z}
283209467b48Spatrick // last one have no meaning, but GCC accepts it
283309467b48Spatrick // Currently, we're just pass a '{' mark
283409467b48Spatrick std::unique_ptr<X86Operand> Z;
283509467b48Spatrick if (ParseZ(Z, consumedToken))
283609467b48Spatrick return true;
283709467b48Spatrick // Reaching here means that parsing of the allegadly '{z}' mark yielded
283809467b48Spatrick // no errors.
283909467b48Spatrick // Query for the need of further parsing for a {%k<NUM>} mark
284009467b48Spatrick if (!Z || getLexer().is(AsmToken::LCurly)) {
284109467b48Spatrick SMLoc StartLoc = Z ? consumeToken() : consumedToken;
284209467b48Spatrick // Parse an op-mask register mark ({%k<NUM>}), which is now to be
284309467b48Spatrick // expected
2844*d415bd75Srobert MCRegister RegNo;
284509467b48Spatrick SMLoc RegLoc;
2846*d415bd75Srobert if (!parseRegister(RegNo, RegLoc, StartLoc) &&
284709467b48Spatrick X86MCRegisterClasses[X86::VK1RegClassID].contains(RegNo)) {
284809467b48Spatrick if (RegNo == X86::K0)
284909467b48Spatrick return Error(RegLoc, "Register k0 can't be used as write mask");
285009467b48Spatrick if (!getLexer().is(AsmToken::RCurly))
285109467b48Spatrick return Error(getLexer().getLoc(), "Expected } at this point");
285209467b48Spatrick Operands.push_back(X86Operand::CreateToken("{", StartLoc));
285309467b48Spatrick Operands.push_back(
285409467b48Spatrick X86Operand::CreateReg(RegNo, StartLoc, StartLoc));
285509467b48Spatrick Operands.push_back(X86Operand::CreateToken("}", consumeToken()));
285609467b48Spatrick } else
285709467b48Spatrick return Error(getLexer().getLoc(),
285809467b48Spatrick "Expected an op-mask register at this point");
285909467b48Spatrick // {%k<NUM>} mark is found, inquire for {z}
286009467b48Spatrick if (getLexer().is(AsmToken::LCurly) && !Z) {
286109467b48Spatrick // Have we've found a parsing error, or found no (expected) {z} mark
286209467b48Spatrick // - report an error
286309467b48Spatrick if (ParseZ(Z, consumeToken()) || !Z)
286409467b48Spatrick return Error(getLexer().getLoc(),
286509467b48Spatrick "Expected a {z} mark at this point");
286609467b48Spatrick
286709467b48Spatrick }
286809467b48Spatrick // '{z}' on its own is meaningless, hence should be ignored.
286909467b48Spatrick // on the contrary - have it been accompanied by a K register,
287009467b48Spatrick // allow it.
287109467b48Spatrick if (Z)
287209467b48Spatrick Operands.push_back(std::move(Z));
287309467b48Spatrick }
287409467b48Spatrick }
287509467b48Spatrick }
287609467b48Spatrick return false;
287709467b48Spatrick }
287809467b48Spatrick
287909467b48Spatrick /// ParseMemOperand: 'seg : disp(basereg, indexreg, scale)'. The '%ds:' prefix
288009467b48Spatrick /// has already been parsed if present. disp may be provided as well.
ParseMemOperand(unsigned SegReg,const MCExpr * Disp,SMLoc StartLoc,SMLoc EndLoc,OperandVector & Operands)288173471bf0Spatrick bool X86AsmParser::ParseMemOperand(unsigned SegReg, const MCExpr *Disp,
288273471bf0Spatrick SMLoc StartLoc, SMLoc EndLoc,
288373471bf0Spatrick OperandVector &Operands) {
288409467b48Spatrick MCAsmParser &Parser = getParser();
288509467b48Spatrick SMLoc Loc;
288609467b48Spatrick // Based on the initial passed values, we may be in any of these cases, we are
288709467b48Spatrick // in one of these cases (with current position (*)):
288809467b48Spatrick
288909467b48Spatrick // 1. seg : * disp (base-index-scale-expr)
289009467b48Spatrick // 2. seg : *(disp) (base-index-scale-expr)
289109467b48Spatrick // 3. seg : *(base-index-scale-expr)
289209467b48Spatrick // 4. disp *(base-index-scale-expr)
289309467b48Spatrick // 5. *(disp) (base-index-scale-expr)
289409467b48Spatrick // 6. *(base-index-scale-expr)
289509467b48Spatrick // 7. disp *
289609467b48Spatrick // 8. *(disp)
289709467b48Spatrick
289809467b48Spatrick // If we do not have an displacement yet, check if we're in cases 4 or 6 by
289909467b48Spatrick // checking if the first object after the parenthesis is a register (or an
290009467b48Spatrick // identifier referring to a register) and parse the displacement or default
290109467b48Spatrick // to 0 as appropriate.
290209467b48Spatrick auto isAtMemOperand = [this]() {
290309467b48Spatrick if (this->getLexer().isNot(AsmToken::LParen))
290409467b48Spatrick return false;
290509467b48Spatrick AsmToken Buf[2];
290609467b48Spatrick StringRef Id;
290709467b48Spatrick auto TokCount = this->getLexer().peekTokens(Buf, true);
290809467b48Spatrick if (TokCount == 0)
290909467b48Spatrick return false;
291009467b48Spatrick switch (Buf[0].getKind()) {
291109467b48Spatrick case AsmToken::Percent:
291209467b48Spatrick case AsmToken::Comma:
291309467b48Spatrick return true;
291409467b48Spatrick // These lower cases are doing a peekIdentifier.
291509467b48Spatrick case AsmToken::At:
291609467b48Spatrick case AsmToken::Dollar:
291709467b48Spatrick if ((TokCount > 1) &&
291809467b48Spatrick (Buf[1].is(AsmToken::Identifier) || Buf[1].is(AsmToken::String)) &&
291909467b48Spatrick (Buf[0].getLoc().getPointer() + 1 == Buf[1].getLoc().getPointer()))
292009467b48Spatrick Id = StringRef(Buf[0].getLoc().getPointer(),
292109467b48Spatrick Buf[1].getIdentifier().size() + 1);
292209467b48Spatrick break;
292309467b48Spatrick case AsmToken::Identifier:
292409467b48Spatrick case AsmToken::String:
292509467b48Spatrick Id = Buf[0].getIdentifier();
292609467b48Spatrick break;
292709467b48Spatrick default:
292809467b48Spatrick return false;
292909467b48Spatrick }
293009467b48Spatrick // We have an ID. Check if it is bound to a register.
293109467b48Spatrick if (!Id.empty()) {
293209467b48Spatrick MCSymbol *Sym = this->getContext().getOrCreateSymbol(Id);
293309467b48Spatrick if (Sym->isVariable()) {
293409467b48Spatrick auto V = Sym->getVariableValue(/*SetUsed*/ false);
293509467b48Spatrick return isa<X86MCExpr>(V);
293609467b48Spatrick }
293709467b48Spatrick }
293809467b48Spatrick return false;
293909467b48Spatrick };
294009467b48Spatrick
294109467b48Spatrick if (!Disp) {
294209467b48Spatrick // Parse immediate if we're not at a mem operand yet.
294309467b48Spatrick if (!isAtMemOperand()) {
294409467b48Spatrick if (Parser.parseTokenLoc(Loc) || Parser.parseExpression(Disp, EndLoc))
294573471bf0Spatrick return true;
294609467b48Spatrick assert(!isa<X86MCExpr>(Disp) && "Expected non-register here.");
294709467b48Spatrick } else {
294809467b48Spatrick // Disp is implicitly zero if we haven't parsed it yet.
294909467b48Spatrick Disp = MCConstantExpr::create(0, Parser.getContext());
295009467b48Spatrick }
295109467b48Spatrick }
295209467b48Spatrick
295309467b48Spatrick // We are now either at the end of the operand or at the '(' at the start of a
295409467b48Spatrick // base-index-scale-expr.
295509467b48Spatrick
295609467b48Spatrick if (!parseOptionalToken(AsmToken::LParen)) {
295709467b48Spatrick if (SegReg == 0)
295873471bf0Spatrick Operands.push_back(
295973471bf0Spatrick X86Operand::CreateMem(getPointerWidth(), Disp, StartLoc, EndLoc));
296073471bf0Spatrick else
296173471bf0Spatrick Operands.push_back(X86Operand::CreateMem(getPointerWidth(), SegReg, Disp,
296273471bf0Spatrick 0, 0, 1, StartLoc, EndLoc));
296373471bf0Spatrick return false;
296409467b48Spatrick }
296509467b48Spatrick
296609467b48Spatrick // If we reached here, then eat the '(' and Process
296709467b48Spatrick // the rest of the memory operand.
296809467b48Spatrick unsigned BaseReg = 0, IndexReg = 0, Scale = 1;
296909467b48Spatrick SMLoc BaseLoc = getLexer().getLoc();
297009467b48Spatrick const MCExpr *E;
297109467b48Spatrick StringRef ErrMsg;
297209467b48Spatrick
297309467b48Spatrick // Parse BaseReg if one is provided.
297409467b48Spatrick if (getLexer().isNot(AsmToken::Comma) && getLexer().isNot(AsmToken::RParen)) {
297509467b48Spatrick if (Parser.parseExpression(E, EndLoc) ||
297609467b48Spatrick check(!isa<X86MCExpr>(E), BaseLoc, "expected register here"))
297773471bf0Spatrick return true;
297809467b48Spatrick
2979*d415bd75Srobert // Check the register.
298009467b48Spatrick BaseReg = cast<X86MCExpr>(E)->getRegNo();
298109467b48Spatrick if (BaseReg == X86::EIZ || BaseReg == X86::RIZ)
298273471bf0Spatrick return Error(BaseLoc, "eiz and riz can only be used as index registers",
298309467b48Spatrick SMRange(BaseLoc, EndLoc));
298409467b48Spatrick }
298509467b48Spatrick
298609467b48Spatrick if (parseOptionalToken(AsmToken::Comma)) {
298709467b48Spatrick // Following the comma we should have either an index register, or a scale
298809467b48Spatrick // value. We don't support the later form, but we want to parse it
298909467b48Spatrick // correctly.
299009467b48Spatrick //
299109467b48Spatrick // Even though it would be completely consistent to support syntax like
299209467b48Spatrick // "1(%eax,,1)", the assembler doesn't. Use "eiz" or "riz" for this.
299309467b48Spatrick if (getLexer().isNot(AsmToken::RParen)) {
299409467b48Spatrick if (Parser.parseTokenLoc(Loc) || Parser.parseExpression(E, EndLoc))
299573471bf0Spatrick return true;
299609467b48Spatrick
299709467b48Spatrick if (!isa<X86MCExpr>(E)) {
299809467b48Spatrick // We've parsed an unexpected Scale Value instead of an index
299909467b48Spatrick // register. Interpret it as an absolute.
300009467b48Spatrick int64_t ScaleVal;
300109467b48Spatrick if (!E->evaluateAsAbsolute(ScaleVal, getStreamer().getAssemblerPtr()))
300273471bf0Spatrick return Error(Loc, "expected absolute expression");
300309467b48Spatrick if (ScaleVal != 1)
300409467b48Spatrick Warning(Loc, "scale factor without index register is ignored");
300509467b48Spatrick Scale = 1;
300609467b48Spatrick } else { // IndexReg Found.
300709467b48Spatrick IndexReg = cast<X86MCExpr>(E)->getRegNo();
300809467b48Spatrick
300909467b48Spatrick if (BaseReg == X86::RIP)
301073471bf0Spatrick return Error(Loc,
301173471bf0Spatrick "%rip as base register can not have an index register");
301209467b48Spatrick if (IndexReg == X86::RIP)
301373471bf0Spatrick return Error(Loc, "%rip is not allowed as an index register");
301409467b48Spatrick
301509467b48Spatrick if (parseOptionalToken(AsmToken::Comma)) {
301609467b48Spatrick // Parse the scale amount:
301709467b48Spatrick // ::= ',' [scale-expression]
301809467b48Spatrick
301909467b48Spatrick // A scale amount without an index is ignored.
302009467b48Spatrick if (getLexer().isNot(AsmToken::RParen)) {
302109467b48Spatrick int64_t ScaleVal;
302209467b48Spatrick if (Parser.parseTokenLoc(Loc) ||
302309467b48Spatrick Parser.parseAbsoluteExpression(ScaleVal))
302473471bf0Spatrick return Error(Loc, "expected scale expression");
302509467b48Spatrick Scale = (unsigned)ScaleVal;
302609467b48Spatrick // Validate the scale amount.
302709467b48Spatrick if (X86MCRegisterClasses[X86::GR16RegClassID].contains(BaseReg) &&
302809467b48Spatrick Scale != 1)
302973471bf0Spatrick return Error(Loc, "scale factor in 16-bit address must be 1");
303009467b48Spatrick if (checkScale(Scale, ErrMsg))
303173471bf0Spatrick return Error(Loc, ErrMsg);
303209467b48Spatrick }
303309467b48Spatrick }
303409467b48Spatrick }
303509467b48Spatrick }
303609467b48Spatrick }
303709467b48Spatrick
303809467b48Spatrick // Ok, we've eaten the memory operand, verify we have a ')' and eat it too.
303909467b48Spatrick if (parseToken(AsmToken::RParen, "unexpected token in memory operand"))
304073471bf0Spatrick return true;
304109467b48Spatrick
304209467b48Spatrick // This is to support otherwise illegal operand (%dx) found in various
304309467b48Spatrick // unofficial manuals examples (e.g. "out[s]?[bwl]? %al, (%dx)") and must now
304409467b48Spatrick // be supported. Mark such DX variants separately fix only in special cases.
304509467b48Spatrick if (BaseReg == X86::DX && IndexReg == 0 && Scale == 1 && SegReg == 0 &&
304673471bf0Spatrick isa<MCConstantExpr>(Disp) &&
304773471bf0Spatrick cast<MCConstantExpr>(Disp)->getValue() == 0) {
304873471bf0Spatrick Operands.push_back(X86Operand::CreateDXReg(BaseLoc, BaseLoc));
304973471bf0Spatrick return false;
305073471bf0Spatrick }
305109467b48Spatrick
305209467b48Spatrick if (CheckBaseRegAndIndexRegAndScale(BaseReg, IndexReg, Scale, is64BitMode(),
305309467b48Spatrick ErrMsg))
305473471bf0Spatrick return Error(BaseLoc, ErrMsg);
305509467b48Spatrick
305609467b48Spatrick if (SegReg || BaseReg || IndexReg)
305773471bf0Spatrick Operands.push_back(X86Operand::CreateMem(getPointerWidth(), SegReg, Disp,
305873471bf0Spatrick BaseReg, IndexReg, Scale, StartLoc,
305973471bf0Spatrick EndLoc));
306073471bf0Spatrick else
306173471bf0Spatrick Operands.push_back(
306273471bf0Spatrick X86Operand::CreateMem(getPointerWidth(), Disp, StartLoc, EndLoc));
306373471bf0Spatrick return false;
306409467b48Spatrick }
306509467b48Spatrick
306609467b48Spatrick // Parse either a standard primary expression or a register.
parsePrimaryExpr(const MCExpr * & Res,SMLoc & EndLoc)306709467b48Spatrick bool X86AsmParser::parsePrimaryExpr(const MCExpr *&Res, SMLoc &EndLoc) {
306809467b48Spatrick MCAsmParser &Parser = getParser();
306909467b48Spatrick // See if this is a register first.
307009467b48Spatrick if (getTok().is(AsmToken::Percent) ||
307109467b48Spatrick (isParsingIntelSyntax() && getTok().is(AsmToken::Identifier) &&
307209467b48Spatrick MatchRegisterName(Parser.getTok().getString()))) {
307309467b48Spatrick SMLoc StartLoc = Parser.getTok().getLoc();
3074*d415bd75Srobert MCRegister RegNo;
3075*d415bd75Srobert if (parseRegister(RegNo, StartLoc, EndLoc))
307609467b48Spatrick return true;
307709467b48Spatrick Res = X86MCExpr::create(RegNo, Parser.getContext());
307809467b48Spatrick return false;
307909467b48Spatrick }
308073471bf0Spatrick return Parser.parsePrimaryExpr(Res, EndLoc, nullptr);
308109467b48Spatrick }
308209467b48Spatrick
ParseInstruction(ParseInstructionInfo & Info,StringRef Name,SMLoc NameLoc,OperandVector & Operands)308309467b48Spatrick bool X86AsmParser::ParseInstruction(ParseInstructionInfo &Info, StringRef Name,
308409467b48Spatrick SMLoc NameLoc, OperandVector &Operands) {
308509467b48Spatrick MCAsmParser &Parser = getParser();
308609467b48Spatrick InstInfo = &Info;
308709467b48Spatrick
308809467b48Spatrick // Reset the forced VEX encoding.
308909467b48Spatrick ForcedVEXEncoding = VEXEncoding_Default;
309073471bf0Spatrick ForcedDispEncoding = DispEncoding_Default;
309109467b48Spatrick
309209467b48Spatrick // Parse pseudo prefixes.
3093*d415bd75Srobert while (true) {
309409467b48Spatrick if (Name == "{") {
309509467b48Spatrick if (getLexer().isNot(AsmToken::Identifier))
309609467b48Spatrick return Error(Parser.getTok().getLoc(), "Unexpected token after '{'");
309709467b48Spatrick std::string Prefix = Parser.getTok().getString().lower();
309809467b48Spatrick Parser.Lex(); // Eat identifier.
309909467b48Spatrick if (getLexer().isNot(AsmToken::RCurly))
310009467b48Spatrick return Error(Parser.getTok().getLoc(), "Expected '}'");
310109467b48Spatrick Parser.Lex(); // Eat curly.
310209467b48Spatrick
310373471bf0Spatrick if (Prefix == "vex")
3104097a140dSpatrick ForcedVEXEncoding = VEXEncoding_VEX;
310573471bf0Spatrick else if (Prefix == "vex2")
310673471bf0Spatrick ForcedVEXEncoding = VEXEncoding_VEX2;
310709467b48Spatrick else if (Prefix == "vex3")
310809467b48Spatrick ForcedVEXEncoding = VEXEncoding_VEX3;
310909467b48Spatrick else if (Prefix == "evex")
311009467b48Spatrick ForcedVEXEncoding = VEXEncoding_EVEX;
311173471bf0Spatrick else if (Prefix == "disp8")
311273471bf0Spatrick ForcedDispEncoding = DispEncoding_Disp8;
311373471bf0Spatrick else if (Prefix == "disp32")
311473471bf0Spatrick ForcedDispEncoding = DispEncoding_Disp32;
311509467b48Spatrick else
311609467b48Spatrick return Error(NameLoc, "unknown prefix");
311709467b48Spatrick
311809467b48Spatrick NameLoc = Parser.getTok().getLoc();
311909467b48Spatrick if (getLexer().is(AsmToken::LCurly)) {
312009467b48Spatrick Parser.Lex();
312109467b48Spatrick Name = "{";
312209467b48Spatrick } else {
312309467b48Spatrick if (getLexer().isNot(AsmToken::Identifier))
312409467b48Spatrick return Error(Parser.getTok().getLoc(), "Expected identifier");
312509467b48Spatrick // FIXME: The mnemonic won't match correctly if its not in lower case.
312609467b48Spatrick Name = Parser.getTok().getString();
312709467b48Spatrick Parser.Lex();
312809467b48Spatrick }
312909467b48Spatrick continue;
313009467b48Spatrick }
313173471bf0Spatrick // Parse MASM style pseudo prefixes.
313273471bf0Spatrick if (isParsingMSInlineAsm()) {
313373471bf0Spatrick if (Name.equals_insensitive("vex"))
313473471bf0Spatrick ForcedVEXEncoding = VEXEncoding_VEX;
313573471bf0Spatrick else if (Name.equals_insensitive("vex2"))
313673471bf0Spatrick ForcedVEXEncoding = VEXEncoding_VEX2;
313773471bf0Spatrick else if (Name.equals_insensitive("vex3"))
313873471bf0Spatrick ForcedVEXEncoding = VEXEncoding_VEX3;
313973471bf0Spatrick else if (Name.equals_insensitive("evex"))
314073471bf0Spatrick ForcedVEXEncoding = VEXEncoding_EVEX;
314109467b48Spatrick
314273471bf0Spatrick if (ForcedVEXEncoding != VEXEncoding_Default) {
314373471bf0Spatrick if (getLexer().isNot(AsmToken::Identifier))
314473471bf0Spatrick return Error(Parser.getTok().getLoc(), "Expected identifier");
314573471bf0Spatrick // FIXME: The mnemonic won't match correctly if its not in lower case.
314673471bf0Spatrick Name = Parser.getTok().getString();
314773471bf0Spatrick NameLoc = Parser.getTok().getLoc();
314873471bf0Spatrick Parser.Lex();
314973471bf0Spatrick }
315073471bf0Spatrick }
315109467b48Spatrick break;
315209467b48Spatrick }
315309467b48Spatrick
315473471bf0Spatrick // Support the suffix syntax for overriding displacement size as well.
315573471bf0Spatrick if (Name.consume_back(".d32")) {
315673471bf0Spatrick ForcedDispEncoding = DispEncoding_Disp32;
315773471bf0Spatrick } else if (Name.consume_back(".d8")) {
315873471bf0Spatrick ForcedDispEncoding = DispEncoding_Disp8;
315973471bf0Spatrick }
316073471bf0Spatrick
316109467b48Spatrick StringRef PatchedName = Name;
316209467b48Spatrick
316309467b48Spatrick // Hack to skip "short" following Jcc.
316409467b48Spatrick if (isParsingIntelSyntax() &&
316509467b48Spatrick (PatchedName == "jmp" || PatchedName == "jc" || PatchedName == "jnc" ||
316673471bf0Spatrick PatchedName == "jcxz" || PatchedName == "jecxz" ||
316709467b48Spatrick (PatchedName.startswith("j") &&
316809467b48Spatrick ParseConditionCode(PatchedName.substr(1)) != X86::COND_INVALID))) {
316909467b48Spatrick StringRef NextTok = Parser.getTok().getString();
317073471bf0Spatrick if (Parser.isParsingMasm() ? NextTok.equals_insensitive("short")
317173471bf0Spatrick : NextTok == "short") {
317209467b48Spatrick SMLoc NameEndLoc =
317309467b48Spatrick NameLoc.getFromPointer(NameLoc.getPointer() + Name.size());
317409467b48Spatrick // Eat the short keyword.
317509467b48Spatrick Parser.Lex();
317609467b48Spatrick // MS and GAS ignore the short keyword; they both determine the jmp type
317709467b48Spatrick // based on the distance of the label. (NASM does emit different code with
317809467b48Spatrick // and without "short," though.)
317909467b48Spatrick InstInfo->AsmRewrites->emplace_back(AOK_Skip, NameEndLoc,
318009467b48Spatrick NextTok.size() + 1);
318109467b48Spatrick }
318209467b48Spatrick }
318309467b48Spatrick
318409467b48Spatrick // FIXME: Hack to recognize setneb as setne.
318509467b48Spatrick if (PatchedName.startswith("set") && PatchedName.endswith("b") &&
318609467b48Spatrick PatchedName != "setb" && PatchedName != "setnb")
318709467b48Spatrick PatchedName = PatchedName.substr(0, Name.size()-1);
318809467b48Spatrick
318909467b48Spatrick unsigned ComparisonPredicate = ~0U;
319009467b48Spatrick
3191*d415bd75Srobert // FIXME: Hack to recognize cmp<comparison code>{sh,ss,sd,ph,ps,pd}.
319209467b48Spatrick if ((PatchedName.startswith("cmp") || PatchedName.startswith("vcmp")) &&
319309467b48Spatrick (PatchedName.endswith("ss") || PatchedName.endswith("sd") ||
3194*d415bd75Srobert PatchedName.endswith("sh") || PatchedName.endswith("ph") ||
319509467b48Spatrick PatchedName.endswith("ps") || PatchedName.endswith("pd"))) {
319609467b48Spatrick bool IsVCMP = PatchedName[0] == 'v';
319709467b48Spatrick unsigned CCIdx = IsVCMP ? 4 : 3;
319809467b48Spatrick unsigned CC = StringSwitch<unsigned>(
319909467b48Spatrick PatchedName.slice(CCIdx, PatchedName.size() - 2))
320009467b48Spatrick .Case("eq", 0x00)
320109467b48Spatrick .Case("eq_oq", 0x00)
320209467b48Spatrick .Case("lt", 0x01)
320309467b48Spatrick .Case("lt_os", 0x01)
320409467b48Spatrick .Case("le", 0x02)
320509467b48Spatrick .Case("le_os", 0x02)
320609467b48Spatrick .Case("unord", 0x03)
320709467b48Spatrick .Case("unord_q", 0x03)
320809467b48Spatrick .Case("neq", 0x04)
320909467b48Spatrick .Case("neq_uq", 0x04)
321009467b48Spatrick .Case("nlt", 0x05)
321109467b48Spatrick .Case("nlt_us", 0x05)
321209467b48Spatrick .Case("nle", 0x06)
321309467b48Spatrick .Case("nle_us", 0x06)
321409467b48Spatrick .Case("ord", 0x07)
321509467b48Spatrick .Case("ord_q", 0x07)
321609467b48Spatrick /* AVX only from here */
321709467b48Spatrick .Case("eq_uq", 0x08)
321809467b48Spatrick .Case("nge", 0x09)
321909467b48Spatrick .Case("nge_us", 0x09)
322009467b48Spatrick .Case("ngt", 0x0A)
322109467b48Spatrick .Case("ngt_us", 0x0A)
322209467b48Spatrick .Case("false", 0x0B)
322309467b48Spatrick .Case("false_oq", 0x0B)
322409467b48Spatrick .Case("neq_oq", 0x0C)
322509467b48Spatrick .Case("ge", 0x0D)
322609467b48Spatrick .Case("ge_os", 0x0D)
322709467b48Spatrick .Case("gt", 0x0E)
322809467b48Spatrick .Case("gt_os", 0x0E)
322909467b48Spatrick .Case("true", 0x0F)
323009467b48Spatrick .Case("true_uq", 0x0F)
323109467b48Spatrick .Case("eq_os", 0x10)
323209467b48Spatrick .Case("lt_oq", 0x11)
323309467b48Spatrick .Case("le_oq", 0x12)
323409467b48Spatrick .Case("unord_s", 0x13)
323509467b48Spatrick .Case("neq_us", 0x14)
323609467b48Spatrick .Case("nlt_uq", 0x15)
323709467b48Spatrick .Case("nle_uq", 0x16)
323809467b48Spatrick .Case("ord_s", 0x17)
323909467b48Spatrick .Case("eq_us", 0x18)
324009467b48Spatrick .Case("nge_uq", 0x19)
324109467b48Spatrick .Case("ngt_uq", 0x1A)
324209467b48Spatrick .Case("false_os", 0x1B)
324309467b48Spatrick .Case("neq_os", 0x1C)
324409467b48Spatrick .Case("ge_oq", 0x1D)
324509467b48Spatrick .Case("gt_oq", 0x1E)
324609467b48Spatrick .Case("true_us", 0x1F)
324709467b48Spatrick .Default(~0U);
3248*d415bd75Srobert if (CC != ~0U && (IsVCMP || CC < 8) &&
3249*d415bd75Srobert (IsVCMP || PatchedName.back() != 'h')) {
325009467b48Spatrick if (PatchedName.endswith("ss"))
325109467b48Spatrick PatchedName = IsVCMP ? "vcmpss" : "cmpss";
325209467b48Spatrick else if (PatchedName.endswith("sd"))
325309467b48Spatrick PatchedName = IsVCMP ? "vcmpsd" : "cmpsd";
325409467b48Spatrick else if (PatchedName.endswith("ps"))
325509467b48Spatrick PatchedName = IsVCMP ? "vcmpps" : "cmpps";
325609467b48Spatrick else if (PatchedName.endswith("pd"))
325709467b48Spatrick PatchedName = IsVCMP ? "vcmppd" : "cmppd";
3258*d415bd75Srobert else if (PatchedName.endswith("sh"))
3259*d415bd75Srobert PatchedName = "vcmpsh";
3260*d415bd75Srobert else if (PatchedName.endswith("ph"))
3261*d415bd75Srobert PatchedName = "vcmpph";
326209467b48Spatrick else
326309467b48Spatrick llvm_unreachable("Unexpected suffix!");
326409467b48Spatrick
326509467b48Spatrick ComparisonPredicate = CC;
326609467b48Spatrick }
326709467b48Spatrick }
326809467b48Spatrick
326909467b48Spatrick // FIXME: Hack to recognize vpcmp<comparison code>{ub,uw,ud,uq,b,w,d,q}.
327009467b48Spatrick if (PatchedName.startswith("vpcmp") &&
327109467b48Spatrick (PatchedName.back() == 'b' || PatchedName.back() == 'w' ||
327209467b48Spatrick PatchedName.back() == 'd' || PatchedName.back() == 'q')) {
327309467b48Spatrick unsigned SuffixSize = PatchedName.drop_back().back() == 'u' ? 2 : 1;
327409467b48Spatrick unsigned CC = StringSwitch<unsigned>(
327509467b48Spatrick PatchedName.slice(5, PatchedName.size() - SuffixSize))
327609467b48Spatrick .Case("eq", 0x0) // Only allowed on unsigned. Checked below.
327709467b48Spatrick .Case("lt", 0x1)
327809467b48Spatrick .Case("le", 0x2)
327909467b48Spatrick //.Case("false", 0x3) // Not a documented alias.
328009467b48Spatrick .Case("neq", 0x4)
328109467b48Spatrick .Case("nlt", 0x5)
328209467b48Spatrick .Case("nle", 0x6)
328309467b48Spatrick //.Case("true", 0x7) // Not a documented alias.
328409467b48Spatrick .Default(~0U);
328509467b48Spatrick if (CC != ~0U && (CC != 0 || SuffixSize == 2)) {
328609467b48Spatrick switch (PatchedName.back()) {
328709467b48Spatrick default: llvm_unreachable("Unexpected character!");
328809467b48Spatrick case 'b': PatchedName = SuffixSize == 2 ? "vpcmpub" : "vpcmpb"; break;
328909467b48Spatrick case 'w': PatchedName = SuffixSize == 2 ? "vpcmpuw" : "vpcmpw"; break;
329009467b48Spatrick case 'd': PatchedName = SuffixSize == 2 ? "vpcmpud" : "vpcmpd"; break;
329109467b48Spatrick case 'q': PatchedName = SuffixSize == 2 ? "vpcmpuq" : "vpcmpq"; break;
329209467b48Spatrick }
329309467b48Spatrick // Set up the immediate to push into the operands later.
329409467b48Spatrick ComparisonPredicate = CC;
329509467b48Spatrick }
329609467b48Spatrick }
329709467b48Spatrick
329809467b48Spatrick // FIXME: Hack to recognize vpcom<comparison code>{ub,uw,ud,uq,b,w,d,q}.
329909467b48Spatrick if (PatchedName.startswith("vpcom") &&
330009467b48Spatrick (PatchedName.back() == 'b' || PatchedName.back() == 'w' ||
330109467b48Spatrick PatchedName.back() == 'd' || PatchedName.back() == 'q')) {
330209467b48Spatrick unsigned SuffixSize = PatchedName.drop_back().back() == 'u' ? 2 : 1;
330309467b48Spatrick unsigned CC = StringSwitch<unsigned>(
330409467b48Spatrick PatchedName.slice(5, PatchedName.size() - SuffixSize))
330509467b48Spatrick .Case("lt", 0x0)
330609467b48Spatrick .Case("le", 0x1)
330709467b48Spatrick .Case("gt", 0x2)
330809467b48Spatrick .Case("ge", 0x3)
330909467b48Spatrick .Case("eq", 0x4)
331009467b48Spatrick .Case("neq", 0x5)
331109467b48Spatrick .Case("false", 0x6)
331209467b48Spatrick .Case("true", 0x7)
331309467b48Spatrick .Default(~0U);
331409467b48Spatrick if (CC != ~0U) {
331509467b48Spatrick switch (PatchedName.back()) {
331609467b48Spatrick default: llvm_unreachable("Unexpected character!");
331709467b48Spatrick case 'b': PatchedName = SuffixSize == 2 ? "vpcomub" : "vpcomb"; break;
331809467b48Spatrick case 'w': PatchedName = SuffixSize == 2 ? "vpcomuw" : "vpcomw"; break;
331909467b48Spatrick case 'd': PatchedName = SuffixSize == 2 ? "vpcomud" : "vpcomd"; break;
332009467b48Spatrick case 'q': PatchedName = SuffixSize == 2 ? "vpcomuq" : "vpcomq"; break;
332109467b48Spatrick }
332209467b48Spatrick // Set up the immediate to push into the operands later.
332309467b48Spatrick ComparisonPredicate = CC;
332409467b48Spatrick }
332509467b48Spatrick }
332609467b48Spatrick
332709467b48Spatrick
332809467b48Spatrick // Determine whether this is an instruction prefix.
332909467b48Spatrick // FIXME:
333009467b48Spatrick // Enhance prefixes integrity robustness. for example, following forms
333109467b48Spatrick // are currently tolerated:
333209467b48Spatrick // repz repnz <insn> ; GAS errors for the use of two similar prefixes
333309467b48Spatrick // lock addq %rax, %rbx ; Destination operand must be of memory type
333409467b48Spatrick // xacquire <insn> ; xacquire must be accompanied by 'lock'
333573471bf0Spatrick bool IsPrefix =
333673471bf0Spatrick StringSwitch<bool>(Name)
333773471bf0Spatrick .Cases("cs", "ds", "es", "fs", "gs", "ss", true)
333873471bf0Spatrick .Cases("rex64", "data32", "data16", "addr32", "addr16", true)
333909467b48Spatrick .Cases("xacquire", "xrelease", true)
334009467b48Spatrick .Cases("acquire", "release", isParsingIntelSyntax())
334109467b48Spatrick .Default(false);
334209467b48Spatrick
334309467b48Spatrick auto isLockRepeatNtPrefix = [](StringRef N) {
334409467b48Spatrick return StringSwitch<bool>(N)
334509467b48Spatrick .Cases("lock", "rep", "repe", "repz", "repne", "repnz", "notrack", true)
334609467b48Spatrick .Default(false);
334709467b48Spatrick };
334809467b48Spatrick
334909467b48Spatrick bool CurlyAsEndOfStatement = false;
335009467b48Spatrick
335109467b48Spatrick unsigned Flags = X86::IP_NO_PREFIX;
335209467b48Spatrick while (isLockRepeatNtPrefix(Name.lower())) {
335309467b48Spatrick unsigned Prefix =
335409467b48Spatrick StringSwitch<unsigned>(Name)
335509467b48Spatrick .Cases("lock", "lock", X86::IP_HAS_LOCK)
335609467b48Spatrick .Cases("rep", "repe", "repz", X86::IP_HAS_REPEAT)
335709467b48Spatrick .Cases("repne", "repnz", X86::IP_HAS_REPEAT_NE)
335809467b48Spatrick .Cases("notrack", "notrack", X86::IP_HAS_NOTRACK)
335909467b48Spatrick .Default(X86::IP_NO_PREFIX); // Invalid prefix (impossible)
336009467b48Spatrick Flags |= Prefix;
336109467b48Spatrick if (getLexer().is(AsmToken::EndOfStatement)) {
336209467b48Spatrick // We don't have real instr with the given prefix
336309467b48Spatrick // let's use the prefix as the instr.
336409467b48Spatrick // TODO: there could be several prefixes one after another
336509467b48Spatrick Flags = X86::IP_NO_PREFIX;
336609467b48Spatrick break;
336709467b48Spatrick }
336809467b48Spatrick // FIXME: The mnemonic won't match correctly if its not in lower case.
336909467b48Spatrick Name = Parser.getTok().getString();
337009467b48Spatrick Parser.Lex(); // eat the prefix
337109467b48Spatrick // Hack: we could have something like "rep # some comment" or
337209467b48Spatrick // "lock; cmpxchg16b $1" or "lock\0A\09incl" or "lock/incl"
337309467b48Spatrick while (Name.startswith(";") || Name.startswith("\n") ||
337409467b48Spatrick Name.startswith("#") || Name.startswith("\t") ||
337509467b48Spatrick Name.startswith("/")) {
337609467b48Spatrick // FIXME: The mnemonic won't match correctly if its not in lower case.
337709467b48Spatrick Name = Parser.getTok().getString();
337809467b48Spatrick Parser.Lex(); // go to next prefix or instr
337909467b48Spatrick }
338009467b48Spatrick }
338109467b48Spatrick
338209467b48Spatrick if (Flags)
338309467b48Spatrick PatchedName = Name;
338409467b48Spatrick
338509467b48Spatrick // Hacks to handle 'data16' and 'data32'
338609467b48Spatrick if (PatchedName == "data16" && is16BitMode()) {
338709467b48Spatrick return Error(NameLoc, "redundant data16 prefix");
338809467b48Spatrick }
338909467b48Spatrick if (PatchedName == "data32") {
339009467b48Spatrick if (is32BitMode())
339109467b48Spatrick return Error(NameLoc, "redundant data32 prefix");
339209467b48Spatrick if (is64BitMode())
339309467b48Spatrick return Error(NameLoc, "'data32' is not supported in 64-bit mode");
339409467b48Spatrick // Hack to 'data16' for the table lookup.
339509467b48Spatrick PatchedName = "data16";
339673471bf0Spatrick
339773471bf0Spatrick if (getLexer().isNot(AsmToken::EndOfStatement)) {
339873471bf0Spatrick StringRef Next = Parser.getTok().getString();
339973471bf0Spatrick getLexer().Lex();
340073471bf0Spatrick // data32 effectively changes the instruction suffix.
340173471bf0Spatrick // TODO Generalize.
340273471bf0Spatrick if (Next == "callw")
340373471bf0Spatrick Next = "calll";
340473471bf0Spatrick if (Next == "ljmpw")
340573471bf0Spatrick Next = "ljmpl";
340673471bf0Spatrick
340773471bf0Spatrick Name = Next;
340873471bf0Spatrick PatchedName = Name;
3409*d415bd75Srobert ForcedDataPrefix = X86::Is32Bit;
341073471bf0Spatrick IsPrefix = false;
341173471bf0Spatrick }
341209467b48Spatrick }
341309467b48Spatrick
341409467b48Spatrick Operands.push_back(X86Operand::CreateToken(PatchedName, NameLoc));
341509467b48Spatrick
341609467b48Spatrick // Push the immediate if we extracted one from the mnemonic.
341709467b48Spatrick if (ComparisonPredicate != ~0U && !isParsingIntelSyntax()) {
341809467b48Spatrick const MCExpr *ImmOp = MCConstantExpr::create(ComparisonPredicate,
341909467b48Spatrick getParser().getContext());
342009467b48Spatrick Operands.push_back(X86Operand::CreateImm(ImmOp, NameLoc, NameLoc));
342109467b48Spatrick }
342209467b48Spatrick
342309467b48Spatrick // This does the actual operand parsing. Don't parse any more if we have a
342409467b48Spatrick // prefix juxtaposed with an operation like "lock incl 4(%rax)", because we
342509467b48Spatrick // just want to parse the "lock" as the first instruction and the "incl" as
342609467b48Spatrick // the next one.
342773471bf0Spatrick if (getLexer().isNot(AsmToken::EndOfStatement) && !IsPrefix) {
342809467b48Spatrick // Parse '*' modifier.
342909467b48Spatrick if (getLexer().is(AsmToken::Star))
343009467b48Spatrick Operands.push_back(X86Operand::CreateToken("*", consumeToken()));
343109467b48Spatrick
343209467b48Spatrick // Read the operands.
3433*d415bd75Srobert while (true) {
3434*d415bd75Srobert if (parseOperand(Operands, Name))
343509467b48Spatrick return true;
343673471bf0Spatrick if (HandleAVX512Operand(Operands))
343709467b48Spatrick return true;
343873471bf0Spatrick
343909467b48Spatrick // check for comma and eat it
344009467b48Spatrick if (getLexer().is(AsmToken::Comma))
344109467b48Spatrick Parser.Lex();
344209467b48Spatrick else
344309467b48Spatrick break;
344409467b48Spatrick }
344509467b48Spatrick
344609467b48Spatrick // In MS inline asm curly braces mark the beginning/end of a block,
344709467b48Spatrick // therefore they should be interepreted as end of statement
344809467b48Spatrick CurlyAsEndOfStatement =
3449097a140dSpatrick isParsingIntelSyntax() && isParsingMSInlineAsm() &&
345009467b48Spatrick (getLexer().is(AsmToken::LCurly) || getLexer().is(AsmToken::RCurly));
345109467b48Spatrick if (getLexer().isNot(AsmToken::EndOfStatement) && !CurlyAsEndOfStatement)
345209467b48Spatrick return TokError("unexpected token in argument list");
345309467b48Spatrick }
345409467b48Spatrick
345509467b48Spatrick // Push the immediate if we extracted one from the mnemonic.
345609467b48Spatrick if (ComparisonPredicate != ~0U && isParsingIntelSyntax()) {
345709467b48Spatrick const MCExpr *ImmOp = MCConstantExpr::create(ComparisonPredicate,
345809467b48Spatrick getParser().getContext());
345909467b48Spatrick Operands.push_back(X86Operand::CreateImm(ImmOp, NameLoc, NameLoc));
346009467b48Spatrick }
346109467b48Spatrick
346209467b48Spatrick // Consume the EndOfStatement or the prefix separator Slash
346309467b48Spatrick if (getLexer().is(AsmToken::EndOfStatement) ||
346473471bf0Spatrick (IsPrefix && getLexer().is(AsmToken::Slash)))
346509467b48Spatrick Parser.Lex();
346609467b48Spatrick else if (CurlyAsEndOfStatement)
346709467b48Spatrick // Add an actual EndOfStatement before the curly brace
346809467b48Spatrick Info.AsmRewrites->emplace_back(AOK_EndOfStatement,
346909467b48Spatrick getLexer().getTok().getLoc(), 0);
347009467b48Spatrick
347109467b48Spatrick // This is for gas compatibility and cannot be done in td.
347209467b48Spatrick // Adding "p" for some floating point with no argument.
347309467b48Spatrick // For example: fsub --> fsubp
347409467b48Spatrick bool IsFp =
347509467b48Spatrick Name == "fsub" || Name == "fdiv" || Name == "fsubr" || Name == "fdivr";
347609467b48Spatrick if (IsFp && Operands.size() == 1) {
347709467b48Spatrick const char *Repl = StringSwitch<const char *>(Name)
347809467b48Spatrick .Case("fsub", "fsubp")
347909467b48Spatrick .Case("fdiv", "fdivp")
348009467b48Spatrick .Case("fsubr", "fsubrp")
348109467b48Spatrick .Case("fdivr", "fdivrp");
348209467b48Spatrick static_cast<X86Operand &>(*Operands[0]).setTokenValue(Repl);
348309467b48Spatrick }
348409467b48Spatrick
348509467b48Spatrick if ((Name == "mov" || Name == "movw" || Name == "movl") &&
348609467b48Spatrick (Operands.size() == 3)) {
348709467b48Spatrick X86Operand &Op1 = (X86Operand &)*Operands[1];
348809467b48Spatrick X86Operand &Op2 = (X86Operand &)*Operands[2];
348909467b48Spatrick SMLoc Loc = Op1.getEndLoc();
349009467b48Spatrick // Moving a 32 or 16 bit value into a segment register has the same
349109467b48Spatrick // behavior. Modify such instructions to always take shorter form.
349209467b48Spatrick if (Op1.isReg() && Op2.isReg() &&
349309467b48Spatrick X86MCRegisterClasses[X86::SEGMENT_REGRegClassID].contains(
349409467b48Spatrick Op2.getReg()) &&
349509467b48Spatrick (X86MCRegisterClasses[X86::GR16RegClassID].contains(Op1.getReg()) ||
349609467b48Spatrick X86MCRegisterClasses[X86::GR32RegClassID].contains(Op1.getReg()))) {
349709467b48Spatrick // Change instruction name to match new instruction.
349809467b48Spatrick if (Name != "mov" && Name[3] == (is16BitMode() ? 'l' : 'w')) {
349909467b48Spatrick Name = is16BitMode() ? "movw" : "movl";
350009467b48Spatrick Operands[0] = X86Operand::CreateToken(Name, NameLoc);
350109467b48Spatrick }
350209467b48Spatrick // Select the correct equivalent 16-/32-bit source register.
350309467b48Spatrick unsigned Reg =
350409467b48Spatrick getX86SubSuperRegisterOrZero(Op1.getReg(), is16BitMode() ? 16 : 32);
350509467b48Spatrick Operands[1] = X86Operand::CreateReg(Reg, Loc, Loc);
350609467b48Spatrick }
350709467b48Spatrick }
350809467b48Spatrick
350909467b48Spatrick // This is a terrible hack to handle "out[s]?[bwl]? %al, (%dx)" ->
351009467b48Spatrick // "outb %al, %dx". Out doesn't take a memory form, but this is a widely
351109467b48Spatrick // documented form in various unofficial manuals, so a lot of code uses it.
351209467b48Spatrick if ((Name == "outb" || Name == "outsb" || Name == "outw" || Name == "outsw" ||
351309467b48Spatrick Name == "outl" || Name == "outsl" || Name == "out" || Name == "outs") &&
351409467b48Spatrick Operands.size() == 3) {
351509467b48Spatrick X86Operand &Op = (X86Operand &)*Operands.back();
351609467b48Spatrick if (Op.isDXReg())
351709467b48Spatrick Operands.back() = X86Operand::CreateReg(X86::DX, Op.getStartLoc(),
351809467b48Spatrick Op.getEndLoc());
351909467b48Spatrick }
352009467b48Spatrick // Same hack for "in[s]?[bwl]? (%dx), %al" -> "inb %dx, %al".
352109467b48Spatrick if ((Name == "inb" || Name == "insb" || Name == "inw" || Name == "insw" ||
352209467b48Spatrick Name == "inl" || Name == "insl" || Name == "in" || Name == "ins") &&
352309467b48Spatrick Operands.size() == 3) {
352409467b48Spatrick X86Operand &Op = (X86Operand &)*Operands[1];
352509467b48Spatrick if (Op.isDXReg())
352609467b48Spatrick Operands[1] = X86Operand::CreateReg(X86::DX, Op.getStartLoc(),
352709467b48Spatrick Op.getEndLoc());
352809467b48Spatrick }
352909467b48Spatrick
353009467b48Spatrick SmallVector<std::unique_ptr<MCParsedAsmOperand>, 2> TmpOperands;
353109467b48Spatrick bool HadVerifyError = false;
353209467b48Spatrick
353309467b48Spatrick // Append default arguments to "ins[bwld]"
353409467b48Spatrick if (Name.startswith("ins") &&
353509467b48Spatrick (Operands.size() == 1 || Operands.size() == 3) &&
353609467b48Spatrick (Name == "insb" || Name == "insw" || Name == "insl" || Name == "insd" ||
353709467b48Spatrick Name == "ins")) {
353809467b48Spatrick
353909467b48Spatrick AddDefaultSrcDestOperands(TmpOperands,
354009467b48Spatrick X86Operand::CreateReg(X86::DX, NameLoc, NameLoc),
354109467b48Spatrick DefaultMemDIOperand(NameLoc));
354209467b48Spatrick HadVerifyError = VerifyAndAdjustOperands(Operands, TmpOperands);
354309467b48Spatrick }
354409467b48Spatrick
354509467b48Spatrick // Append default arguments to "outs[bwld]"
354609467b48Spatrick if (Name.startswith("outs") &&
354709467b48Spatrick (Operands.size() == 1 || Operands.size() == 3) &&
354809467b48Spatrick (Name == "outsb" || Name == "outsw" || Name == "outsl" ||
354909467b48Spatrick Name == "outsd" || Name == "outs")) {
355009467b48Spatrick AddDefaultSrcDestOperands(TmpOperands, DefaultMemSIOperand(NameLoc),
355109467b48Spatrick X86Operand::CreateReg(X86::DX, NameLoc, NameLoc));
355209467b48Spatrick HadVerifyError = VerifyAndAdjustOperands(Operands, TmpOperands);
355309467b48Spatrick }
355409467b48Spatrick
355509467b48Spatrick // Transform "lods[bwlq]" into "lods[bwlq] ($SIREG)" for appropriate
355609467b48Spatrick // values of $SIREG according to the mode. It would be nice if this
355709467b48Spatrick // could be achieved with InstAlias in the tables.
355809467b48Spatrick if (Name.startswith("lods") &&
355909467b48Spatrick (Operands.size() == 1 || Operands.size() == 2) &&
356009467b48Spatrick (Name == "lods" || Name == "lodsb" || Name == "lodsw" ||
356109467b48Spatrick Name == "lodsl" || Name == "lodsd" || Name == "lodsq")) {
356209467b48Spatrick TmpOperands.push_back(DefaultMemSIOperand(NameLoc));
356309467b48Spatrick HadVerifyError = VerifyAndAdjustOperands(Operands, TmpOperands);
356409467b48Spatrick }
356509467b48Spatrick
356609467b48Spatrick // Transform "stos[bwlq]" into "stos[bwlq] ($DIREG)" for appropriate
356709467b48Spatrick // values of $DIREG according to the mode. It would be nice if this
356809467b48Spatrick // could be achieved with InstAlias in the tables.
356909467b48Spatrick if (Name.startswith("stos") &&
357009467b48Spatrick (Operands.size() == 1 || Operands.size() == 2) &&
357109467b48Spatrick (Name == "stos" || Name == "stosb" || Name == "stosw" ||
357209467b48Spatrick Name == "stosl" || Name == "stosd" || Name == "stosq")) {
357309467b48Spatrick TmpOperands.push_back(DefaultMemDIOperand(NameLoc));
357409467b48Spatrick HadVerifyError = VerifyAndAdjustOperands(Operands, TmpOperands);
357509467b48Spatrick }
357609467b48Spatrick
357709467b48Spatrick // Transform "scas[bwlq]" into "scas[bwlq] ($DIREG)" for appropriate
357809467b48Spatrick // values of $DIREG according to the mode. It would be nice if this
357909467b48Spatrick // could be achieved with InstAlias in the tables.
358009467b48Spatrick if (Name.startswith("scas") &&
358109467b48Spatrick (Operands.size() == 1 || Operands.size() == 2) &&
358209467b48Spatrick (Name == "scas" || Name == "scasb" || Name == "scasw" ||
358309467b48Spatrick Name == "scasl" || Name == "scasd" || Name == "scasq")) {
358409467b48Spatrick TmpOperands.push_back(DefaultMemDIOperand(NameLoc));
358509467b48Spatrick HadVerifyError = VerifyAndAdjustOperands(Operands, TmpOperands);
358609467b48Spatrick }
358709467b48Spatrick
358809467b48Spatrick // Add default SI and DI operands to "cmps[bwlq]".
358909467b48Spatrick if (Name.startswith("cmps") &&
359009467b48Spatrick (Operands.size() == 1 || Operands.size() == 3) &&
359109467b48Spatrick (Name == "cmps" || Name == "cmpsb" || Name == "cmpsw" ||
359209467b48Spatrick Name == "cmpsl" || Name == "cmpsd" || Name == "cmpsq")) {
359309467b48Spatrick AddDefaultSrcDestOperands(TmpOperands, DefaultMemDIOperand(NameLoc),
359409467b48Spatrick DefaultMemSIOperand(NameLoc));
359509467b48Spatrick HadVerifyError = VerifyAndAdjustOperands(Operands, TmpOperands);
359609467b48Spatrick }
359709467b48Spatrick
359809467b48Spatrick // Add default SI and DI operands to "movs[bwlq]".
359909467b48Spatrick if (((Name.startswith("movs") &&
360009467b48Spatrick (Name == "movs" || Name == "movsb" || Name == "movsw" ||
360109467b48Spatrick Name == "movsl" || Name == "movsd" || Name == "movsq")) ||
360209467b48Spatrick (Name.startswith("smov") &&
360309467b48Spatrick (Name == "smov" || Name == "smovb" || Name == "smovw" ||
360409467b48Spatrick Name == "smovl" || Name == "smovd" || Name == "smovq"))) &&
360509467b48Spatrick (Operands.size() == 1 || Operands.size() == 3)) {
360609467b48Spatrick if (Name == "movsd" && Operands.size() == 1 && !isParsingIntelSyntax())
360709467b48Spatrick Operands.back() = X86Operand::CreateToken("movsl", NameLoc);
360809467b48Spatrick AddDefaultSrcDestOperands(TmpOperands, DefaultMemSIOperand(NameLoc),
360909467b48Spatrick DefaultMemDIOperand(NameLoc));
361009467b48Spatrick HadVerifyError = VerifyAndAdjustOperands(Operands, TmpOperands);
361109467b48Spatrick }
361209467b48Spatrick
361309467b48Spatrick // Check if we encountered an error for one the string insturctions
361409467b48Spatrick if (HadVerifyError) {
361509467b48Spatrick return HadVerifyError;
361609467b48Spatrick }
361709467b48Spatrick
361809467b48Spatrick // Transforms "xlat mem8" into "xlatb"
361909467b48Spatrick if ((Name == "xlat" || Name == "xlatb") && Operands.size() == 2) {
362009467b48Spatrick X86Operand &Op1 = static_cast<X86Operand &>(*Operands[1]);
362109467b48Spatrick if (Op1.isMem8()) {
362209467b48Spatrick Warning(Op1.getStartLoc(), "memory operand is only for determining the "
362309467b48Spatrick "size, (R|E)BX will be used for the location");
362409467b48Spatrick Operands.pop_back();
362509467b48Spatrick static_cast<X86Operand &>(*Operands[0]).setTokenValue("xlatb");
362609467b48Spatrick }
362709467b48Spatrick }
362809467b48Spatrick
362909467b48Spatrick if (Flags)
363009467b48Spatrick Operands.push_back(X86Operand::CreatePrefix(Flags, NameLoc, NameLoc));
363109467b48Spatrick return false;
363209467b48Spatrick }
363309467b48Spatrick
processInstruction(MCInst & Inst,const OperandVector & Ops)363409467b48Spatrick bool X86AsmParser::processInstruction(MCInst &Inst, const OperandVector &Ops) {
363509467b48Spatrick const MCRegisterInfo *MRI = getContext().getRegisterInfo();
363609467b48Spatrick
363709467b48Spatrick switch (Inst.getOpcode()) {
363809467b48Spatrick default: return false;
363973471bf0Spatrick case X86::JMP_1:
364073471bf0Spatrick // {disp32} forces a larger displacement as if the instruction was relaxed.
364173471bf0Spatrick // NOTE: 16-bit mode uses 16-bit displacement even though it says {disp32}.
364273471bf0Spatrick // This matches GNU assembler.
364373471bf0Spatrick if (ForcedDispEncoding == DispEncoding_Disp32) {
364473471bf0Spatrick Inst.setOpcode(is16BitMode() ? X86::JMP_2 : X86::JMP_4);
364573471bf0Spatrick return true;
364673471bf0Spatrick }
364773471bf0Spatrick
364873471bf0Spatrick return false;
364973471bf0Spatrick case X86::JCC_1:
365073471bf0Spatrick // {disp32} forces a larger displacement as if the instruction was relaxed.
365173471bf0Spatrick // NOTE: 16-bit mode uses 16-bit displacement even though it says {disp32}.
365273471bf0Spatrick // This matches GNU assembler.
365373471bf0Spatrick if (ForcedDispEncoding == DispEncoding_Disp32) {
365473471bf0Spatrick Inst.setOpcode(is16BitMode() ? X86::JCC_2 : X86::JCC_4);
365573471bf0Spatrick return true;
365673471bf0Spatrick }
365773471bf0Spatrick
365873471bf0Spatrick return false;
365909467b48Spatrick case X86::VMOVZPQILo2PQIrr:
366009467b48Spatrick case X86::VMOVAPDrr:
366109467b48Spatrick case X86::VMOVAPDYrr:
366209467b48Spatrick case X86::VMOVAPSrr:
366309467b48Spatrick case X86::VMOVAPSYrr:
366409467b48Spatrick case X86::VMOVDQArr:
366509467b48Spatrick case X86::VMOVDQAYrr:
366609467b48Spatrick case X86::VMOVDQUrr:
366709467b48Spatrick case X86::VMOVDQUYrr:
366809467b48Spatrick case X86::VMOVUPDrr:
366909467b48Spatrick case X86::VMOVUPDYrr:
367009467b48Spatrick case X86::VMOVUPSrr:
367109467b48Spatrick case X86::VMOVUPSYrr: {
367209467b48Spatrick // We can get a smaller encoding by using VEX.R instead of VEX.B if one of
367309467b48Spatrick // the registers is extended, but other isn't.
367409467b48Spatrick if (ForcedVEXEncoding == VEXEncoding_VEX3 ||
367509467b48Spatrick MRI->getEncodingValue(Inst.getOperand(0).getReg()) >= 8 ||
367609467b48Spatrick MRI->getEncodingValue(Inst.getOperand(1).getReg()) < 8)
367709467b48Spatrick return false;
367809467b48Spatrick
367909467b48Spatrick unsigned NewOpc;
368009467b48Spatrick switch (Inst.getOpcode()) {
368109467b48Spatrick default: llvm_unreachable("Invalid opcode");
368209467b48Spatrick case X86::VMOVZPQILo2PQIrr: NewOpc = X86::VMOVPQI2QIrr; break;
368309467b48Spatrick case X86::VMOVAPDrr: NewOpc = X86::VMOVAPDrr_REV; break;
368409467b48Spatrick case X86::VMOVAPDYrr: NewOpc = X86::VMOVAPDYrr_REV; break;
368509467b48Spatrick case X86::VMOVAPSrr: NewOpc = X86::VMOVAPSrr_REV; break;
368609467b48Spatrick case X86::VMOVAPSYrr: NewOpc = X86::VMOVAPSYrr_REV; break;
368709467b48Spatrick case X86::VMOVDQArr: NewOpc = X86::VMOVDQArr_REV; break;
368809467b48Spatrick case X86::VMOVDQAYrr: NewOpc = X86::VMOVDQAYrr_REV; break;
368909467b48Spatrick case X86::VMOVDQUrr: NewOpc = X86::VMOVDQUrr_REV; break;
369009467b48Spatrick case X86::VMOVDQUYrr: NewOpc = X86::VMOVDQUYrr_REV; break;
369109467b48Spatrick case X86::VMOVUPDrr: NewOpc = X86::VMOVUPDrr_REV; break;
369209467b48Spatrick case X86::VMOVUPDYrr: NewOpc = X86::VMOVUPDYrr_REV; break;
369309467b48Spatrick case X86::VMOVUPSrr: NewOpc = X86::VMOVUPSrr_REV; break;
369409467b48Spatrick case X86::VMOVUPSYrr: NewOpc = X86::VMOVUPSYrr_REV; break;
369509467b48Spatrick }
369609467b48Spatrick Inst.setOpcode(NewOpc);
369709467b48Spatrick return true;
369809467b48Spatrick }
369909467b48Spatrick case X86::VMOVSDrr:
370009467b48Spatrick case X86::VMOVSSrr: {
370109467b48Spatrick // We can get a smaller encoding by using VEX.R instead of VEX.B if one of
370209467b48Spatrick // the registers is extended, but other isn't.
370309467b48Spatrick if (ForcedVEXEncoding == VEXEncoding_VEX3 ||
370409467b48Spatrick MRI->getEncodingValue(Inst.getOperand(0).getReg()) >= 8 ||
370509467b48Spatrick MRI->getEncodingValue(Inst.getOperand(2).getReg()) < 8)
370609467b48Spatrick return false;
370709467b48Spatrick
370809467b48Spatrick unsigned NewOpc;
370909467b48Spatrick switch (Inst.getOpcode()) {
371009467b48Spatrick default: llvm_unreachable("Invalid opcode");
371109467b48Spatrick case X86::VMOVSDrr: NewOpc = X86::VMOVSDrr_REV; break;
371209467b48Spatrick case X86::VMOVSSrr: NewOpc = X86::VMOVSSrr_REV; break;
371309467b48Spatrick }
371409467b48Spatrick Inst.setOpcode(NewOpc);
371509467b48Spatrick return true;
371609467b48Spatrick }
371773471bf0Spatrick case X86::RCR8ri: case X86::RCR16ri: case X86::RCR32ri: case X86::RCR64ri:
371873471bf0Spatrick case X86::RCL8ri: case X86::RCL16ri: case X86::RCL32ri: case X86::RCL64ri:
371973471bf0Spatrick case X86::ROR8ri: case X86::ROR16ri: case X86::ROR32ri: case X86::ROR64ri:
372073471bf0Spatrick case X86::ROL8ri: case X86::ROL16ri: case X86::ROL32ri: case X86::ROL64ri:
372173471bf0Spatrick case X86::SAR8ri: case X86::SAR16ri: case X86::SAR32ri: case X86::SAR64ri:
372273471bf0Spatrick case X86::SHR8ri: case X86::SHR16ri: case X86::SHR32ri: case X86::SHR64ri:
372373471bf0Spatrick case X86::SHL8ri: case X86::SHL16ri: case X86::SHL32ri: case X86::SHL64ri: {
372473471bf0Spatrick // Optimize s{hr,ar,hl} $1, <op> to "shift <op>". Similar for rotate.
372573471bf0Spatrick // FIXME: It would be great if we could just do this with an InstAlias.
372673471bf0Spatrick if (!Inst.getOperand(2).isImm() || Inst.getOperand(2).getImm() != 1)
372773471bf0Spatrick return false;
372873471bf0Spatrick
372973471bf0Spatrick unsigned NewOpc;
373073471bf0Spatrick switch (Inst.getOpcode()) {
373173471bf0Spatrick default: llvm_unreachable("Invalid opcode");
373273471bf0Spatrick case X86::RCR8ri: NewOpc = X86::RCR8r1; break;
373373471bf0Spatrick case X86::RCR16ri: NewOpc = X86::RCR16r1; break;
373473471bf0Spatrick case X86::RCR32ri: NewOpc = X86::RCR32r1; break;
373573471bf0Spatrick case X86::RCR64ri: NewOpc = X86::RCR64r1; break;
373673471bf0Spatrick case X86::RCL8ri: NewOpc = X86::RCL8r1; break;
373773471bf0Spatrick case X86::RCL16ri: NewOpc = X86::RCL16r1; break;
373873471bf0Spatrick case X86::RCL32ri: NewOpc = X86::RCL32r1; break;
373973471bf0Spatrick case X86::RCL64ri: NewOpc = X86::RCL64r1; break;
374073471bf0Spatrick case X86::ROR8ri: NewOpc = X86::ROR8r1; break;
374173471bf0Spatrick case X86::ROR16ri: NewOpc = X86::ROR16r1; break;
374273471bf0Spatrick case X86::ROR32ri: NewOpc = X86::ROR32r1; break;
374373471bf0Spatrick case X86::ROR64ri: NewOpc = X86::ROR64r1; break;
374473471bf0Spatrick case X86::ROL8ri: NewOpc = X86::ROL8r1; break;
374573471bf0Spatrick case X86::ROL16ri: NewOpc = X86::ROL16r1; break;
374673471bf0Spatrick case X86::ROL32ri: NewOpc = X86::ROL32r1; break;
374773471bf0Spatrick case X86::ROL64ri: NewOpc = X86::ROL64r1; break;
374873471bf0Spatrick case X86::SAR8ri: NewOpc = X86::SAR8r1; break;
374973471bf0Spatrick case X86::SAR16ri: NewOpc = X86::SAR16r1; break;
375073471bf0Spatrick case X86::SAR32ri: NewOpc = X86::SAR32r1; break;
375173471bf0Spatrick case X86::SAR64ri: NewOpc = X86::SAR64r1; break;
375273471bf0Spatrick case X86::SHR8ri: NewOpc = X86::SHR8r1; break;
375373471bf0Spatrick case X86::SHR16ri: NewOpc = X86::SHR16r1; break;
375473471bf0Spatrick case X86::SHR32ri: NewOpc = X86::SHR32r1; break;
375573471bf0Spatrick case X86::SHR64ri: NewOpc = X86::SHR64r1; break;
375673471bf0Spatrick case X86::SHL8ri: NewOpc = X86::SHL8r1; break;
375773471bf0Spatrick case X86::SHL16ri: NewOpc = X86::SHL16r1; break;
375873471bf0Spatrick case X86::SHL32ri: NewOpc = X86::SHL32r1; break;
375973471bf0Spatrick case X86::SHL64ri: NewOpc = X86::SHL64r1; break;
376073471bf0Spatrick }
376173471bf0Spatrick
376273471bf0Spatrick MCInst TmpInst;
376373471bf0Spatrick TmpInst.setOpcode(NewOpc);
376473471bf0Spatrick TmpInst.addOperand(Inst.getOperand(0));
376573471bf0Spatrick TmpInst.addOperand(Inst.getOperand(1));
376673471bf0Spatrick Inst = TmpInst;
376773471bf0Spatrick return true;
376873471bf0Spatrick }
376973471bf0Spatrick case X86::RCR8mi: case X86::RCR16mi: case X86::RCR32mi: case X86::RCR64mi:
377073471bf0Spatrick case X86::RCL8mi: case X86::RCL16mi: case X86::RCL32mi: case X86::RCL64mi:
377173471bf0Spatrick case X86::ROR8mi: case X86::ROR16mi: case X86::ROR32mi: case X86::ROR64mi:
377273471bf0Spatrick case X86::ROL8mi: case X86::ROL16mi: case X86::ROL32mi: case X86::ROL64mi:
377373471bf0Spatrick case X86::SAR8mi: case X86::SAR16mi: case X86::SAR32mi: case X86::SAR64mi:
377473471bf0Spatrick case X86::SHR8mi: case X86::SHR16mi: case X86::SHR32mi: case X86::SHR64mi:
377573471bf0Spatrick case X86::SHL8mi: case X86::SHL16mi: case X86::SHL32mi: case X86::SHL64mi: {
377673471bf0Spatrick // Optimize s{hr,ar,hl} $1, <op> to "shift <op>". Similar for rotate.
377773471bf0Spatrick // FIXME: It would be great if we could just do this with an InstAlias.
377873471bf0Spatrick if (!Inst.getOperand(X86::AddrNumOperands).isImm() ||
377973471bf0Spatrick Inst.getOperand(X86::AddrNumOperands).getImm() != 1)
378073471bf0Spatrick return false;
378173471bf0Spatrick
378273471bf0Spatrick unsigned NewOpc;
378373471bf0Spatrick switch (Inst.getOpcode()) {
378473471bf0Spatrick default: llvm_unreachable("Invalid opcode");
378573471bf0Spatrick case X86::RCR8mi: NewOpc = X86::RCR8m1; break;
378673471bf0Spatrick case X86::RCR16mi: NewOpc = X86::RCR16m1; break;
378773471bf0Spatrick case X86::RCR32mi: NewOpc = X86::RCR32m1; break;
378873471bf0Spatrick case X86::RCR64mi: NewOpc = X86::RCR64m1; break;
378973471bf0Spatrick case X86::RCL8mi: NewOpc = X86::RCL8m1; break;
379073471bf0Spatrick case X86::RCL16mi: NewOpc = X86::RCL16m1; break;
379173471bf0Spatrick case X86::RCL32mi: NewOpc = X86::RCL32m1; break;
379273471bf0Spatrick case X86::RCL64mi: NewOpc = X86::RCL64m1; break;
379373471bf0Spatrick case X86::ROR8mi: NewOpc = X86::ROR8m1; break;
379473471bf0Spatrick case X86::ROR16mi: NewOpc = X86::ROR16m1; break;
379573471bf0Spatrick case X86::ROR32mi: NewOpc = X86::ROR32m1; break;
379673471bf0Spatrick case X86::ROR64mi: NewOpc = X86::ROR64m1; break;
379773471bf0Spatrick case X86::ROL8mi: NewOpc = X86::ROL8m1; break;
379873471bf0Spatrick case X86::ROL16mi: NewOpc = X86::ROL16m1; break;
379973471bf0Spatrick case X86::ROL32mi: NewOpc = X86::ROL32m1; break;
380073471bf0Spatrick case X86::ROL64mi: NewOpc = X86::ROL64m1; break;
380173471bf0Spatrick case X86::SAR8mi: NewOpc = X86::SAR8m1; break;
380273471bf0Spatrick case X86::SAR16mi: NewOpc = X86::SAR16m1; break;
380373471bf0Spatrick case X86::SAR32mi: NewOpc = X86::SAR32m1; break;
380473471bf0Spatrick case X86::SAR64mi: NewOpc = X86::SAR64m1; break;
380573471bf0Spatrick case X86::SHR8mi: NewOpc = X86::SHR8m1; break;
380673471bf0Spatrick case X86::SHR16mi: NewOpc = X86::SHR16m1; break;
380773471bf0Spatrick case X86::SHR32mi: NewOpc = X86::SHR32m1; break;
380873471bf0Spatrick case X86::SHR64mi: NewOpc = X86::SHR64m1; break;
380973471bf0Spatrick case X86::SHL8mi: NewOpc = X86::SHL8m1; break;
381073471bf0Spatrick case X86::SHL16mi: NewOpc = X86::SHL16m1; break;
381173471bf0Spatrick case X86::SHL32mi: NewOpc = X86::SHL32m1; break;
381273471bf0Spatrick case X86::SHL64mi: NewOpc = X86::SHL64m1; break;
381373471bf0Spatrick }
381473471bf0Spatrick
381573471bf0Spatrick MCInst TmpInst;
381673471bf0Spatrick TmpInst.setOpcode(NewOpc);
381773471bf0Spatrick for (int i = 0; i != X86::AddrNumOperands; ++i)
381873471bf0Spatrick TmpInst.addOperand(Inst.getOperand(i));
381973471bf0Spatrick Inst = TmpInst;
382073471bf0Spatrick return true;
382173471bf0Spatrick }
382273471bf0Spatrick case X86::INT: {
382373471bf0Spatrick // Transforms "int $3" into "int3" as a size optimization. We can't write an
382473471bf0Spatrick // instalias with an immediate operand yet.
382573471bf0Spatrick if (!Inst.getOperand(0).isImm() || Inst.getOperand(0).getImm() != 3)
382673471bf0Spatrick return false;
382773471bf0Spatrick
382873471bf0Spatrick MCInst TmpInst;
382973471bf0Spatrick TmpInst.setOpcode(X86::INT3);
383073471bf0Spatrick Inst = TmpInst;
383173471bf0Spatrick return true;
383273471bf0Spatrick }
383309467b48Spatrick }
383409467b48Spatrick }
383509467b48Spatrick
validateInstruction(MCInst & Inst,const OperandVector & Ops)383609467b48Spatrick bool X86AsmParser::validateInstruction(MCInst &Inst, const OperandVector &Ops) {
3837*d415bd75Srobert using namespace X86;
383809467b48Spatrick const MCRegisterInfo *MRI = getContext().getRegisterInfo();
3839*d415bd75Srobert unsigned Opcode = Inst.getOpcode();
3840*d415bd75Srobert uint64_t TSFlags = MII.get(Opcode).TSFlags;
3841*d415bd75Srobert if (isVFCMADDCPH(Opcode) || isVFCMADDCSH(Opcode) || isVFMADDCPH(Opcode) ||
3842*d415bd75Srobert isVFMADDCSH(Opcode)) {
3843*d415bd75Srobert unsigned Dest = Inst.getOperand(0).getReg();
3844*d415bd75Srobert for (unsigned i = 2; i < Inst.getNumOperands(); i++)
3845*d415bd75Srobert if (Inst.getOperand(i).isReg() && Dest == Inst.getOperand(i).getReg())
3846*d415bd75Srobert return Warning(Ops[0]->getStartLoc(), "Destination register should be "
3847*d415bd75Srobert "distinct from source registers");
3848*d415bd75Srobert } else if (isVFCMULCPH(Opcode) || isVFCMULCSH(Opcode) || isVFMULCPH(Opcode) ||
3849*d415bd75Srobert isVFMULCSH(Opcode)) {
3850*d415bd75Srobert unsigned Dest = Inst.getOperand(0).getReg();
3851*d415bd75Srobert // The mask variants have different operand list. Scan from the third
3852*d415bd75Srobert // operand to avoid emitting incorrect warning.
3853*d415bd75Srobert // VFMULCPHZrr Dest, Src1, Src2
3854*d415bd75Srobert // VFMULCPHZrrk Dest, Dest, Mask, Src1, Src2
3855*d415bd75Srobert // VFMULCPHZrrkz Dest, Mask, Src1, Src2
3856*d415bd75Srobert for (unsigned i = TSFlags & X86II::EVEX_K ? 2 : 1;
3857*d415bd75Srobert i < Inst.getNumOperands(); i++)
3858*d415bd75Srobert if (Inst.getOperand(i).isReg() && Dest == Inst.getOperand(i).getReg())
3859*d415bd75Srobert return Warning(Ops[0]->getStartLoc(), "Destination register should be "
3860*d415bd75Srobert "distinct from source registers");
3861*d415bd75Srobert } else if (isV4FMADDPS(Opcode) || isV4FMADDSS(Opcode) ||
3862*d415bd75Srobert isV4FNMADDPS(Opcode) || isV4FNMADDSS(Opcode) ||
3863*d415bd75Srobert isVP4DPWSSDS(Opcode) || isVP4DPWSSD(Opcode)) {
386409467b48Spatrick unsigned Src2 = Inst.getOperand(Inst.getNumOperands() -
386509467b48Spatrick X86::AddrNumOperands - 1).getReg();
386609467b48Spatrick unsigned Src2Enc = MRI->getEncodingValue(Src2);
386709467b48Spatrick if (Src2Enc % 4 != 0) {
386809467b48Spatrick StringRef RegName = X86IntelInstPrinter::getRegisterName(Src2);
386909467b48Spatrick unsigned GroupStart = (Src2Enc / 4) * 4;
387009467b48Spatrick unsigned GroupEnd = GroupStart + 3;
387109467b48Spatrick return Warning(Ops[0]->getStartLoc(),
387209467b48Spatrick "source register '" + RegName + "' implicitly denotes '" +
387309467b48Spatrick RegName.take_front(3) + Twine(GroupStart) + "' to '" +
387409467b48Spatrick RegName.take_front(3) + Twine(GroupEnd) +
387509467b48Spatrick "' source group");
387609467b48Spatrick }
3877*d415bd75Srobert } else if (isVGATHERDPD(Opcode) || isVGATHERDPS(Opcode) ||
3878*d415bd75Srobert isVGATHERQPD(Opcode) || isVGATHERQPS(Opcode) ||
3879*d415bd75Srobert isVPGATHERDD(Opcode) || isVPGATHERDQ(Opcode) ||
3880*d415bd75Srobert isVPGATHERQD(Opcode) || isVPGATHERQQ(Opcode)) {
3881*d415bd75Srobert bool HasEVEX = (TSFlags & X86II::EncodingMask) == X86II::EVEX;
3882*d415bd75Srobert if (HasEVEX) {
3883*d415bd75Srobert unsigned Dest = MRI->getEncodingValue(Inst.getOperand(0).getReg());
3884*d415bd75Srobert unsigned Index = MRI->getEncodingValue(
3885*d415bd75Srobert Inst.getOperand(4 + X86::AddrIndexReg).getReg());
3886*d415bd75Srobert if (Dest == Index)
3887*d415bd75Srobert return Warning(Ops[0]->getStartLoc(), "index and destination registers "
3888*d415bd75Srobert "should be distinct");
3889*d415bd75Srobert } else {
3890*d415bd75Srobert unsigned Dest = MRI->getEncodingValue(Inst.getOperand(0).getReg());
3891*d415bd75Srobert unsigned Mask = MRI->getEncodingValue(Inst.getOperand(1).getReg());
3892*d415bd75Srobert unsigned Index = MRI->getEncodingValue(
3893*d415bd75Srobert Inst.getOperand(3 + X86::AddrIndexReg).getReg());
3894*d415bd75Srobert if (Dest == Mask || Dest == Index || Mask == Index)
3895*d415bd75Srobert return Warning(Ops[0]->getStartLoc(), "mask, index, and destination "
3896*d415bd75Srobert "registers should be distinct");
389709467b48Spatrick }
389809467b48Spatrick }
389909467b48Spatrick
390073471bf0Spatrick // Check that we aren't mixing AH/BH/CH/DH with REX prefix. We only need to
390173471bf0Spatrick // check this with the legacy encoding, VEX/EVEX/XOP don't use REX.
3902*d415bd75Srobert if ((TSFlags & X86II::EncodingMask) == 0) {
390373471bf0Spatrick MCPhysReg HReg = X86::NoRegister;
3904*d415bd75Srobert bool UsesRex = TSFlags & X86II::REX_W;
390573471bf0Spatrick unsigned NumOps = Inst.getNumOperands();
390673471bf0Spatrick for (unsigned i = 0; i != NumOps; ++i) {
390773471bf0Spatrick const MCOperand &MO = Inst.getOperand(i);
390873471bf0Spatrick if (!MO.isReg())
390973471bf0Spatrick continue;
391073471bf0Spatrick unsigned Reg = MO.getReg();
391173471bf0Spatrick if (Reg == X86::AH || Reg == X86::BH || Reg == X86::CH || Reg == X86::DH)
391273471bf0Spatrick HReg = Reg;
391373471bf0Spatrick if (X86II::isX86_64NonExtLowByteReg(Reg) ||
391473471bf0Spatrick X86II::isX86_64ExtendedReg(Reg))
391573471bf0Spatrick UsesRex = true;
391673471bf0Spatrick }
391773471bf0Spatrick
391873471bf0Spatrick if (UsesRex && HReg != X86::NoRegister) {
391973471bf0Spatrick StringRef RegName = X86IntelInstPrinter::getRegisterName(HReg);
392073471bf0Spatrick return Error(Ops[0]->getStartLoc(),
392173471bf0Spatrick "can't encode '" + RegName + "' in an instruction requiring "
392273471bf0Spatrick "REX prefix");
392373471bf0Spatrick }
392473471bf0Spatrick }
392573471bf0Spatrick
392609467b48Spatrick return false;
392709467b48Spatrick }
392809467b48Spatrick
392909467b48Spatrick static const char *getSubtargetFeatureName(uint64_t Val);
393009467b48Spatrick
emitWarningForSpecialLVIInstruction(SMLoc Loc)3931097a140dSpatrick void X86AsmParser::emitWarningForSpecialLVIInstruction(SMLoc Loc) {
3932097a140dSpatrick Warning(Loc, "Instruction may be vulnerable to LVI and "
3933097a140dSpatrick "requires manual mitigation");
3934097a140dSpatrick Note(SMLoc(), "See https://software.intel.com/"
3935097a140dSpatrick "security-software-guidance/insights/"
3936097a140dSpatrick "deep-dive-load-value-injection#specialinstructions"
3937097a140dSpatrick " for more information");
3938097a140dSpatrick }
3939097a140dSpatrick
3940097a140dSpatrick /// RET instructions and also instructions that indirect calls/jumps from memory
3941097a140dSpatrick /// combine a load and a branch within a single instruction. To mitigate these
3942097a140dSpatrick /// instructions against LVI, they must be decomposed into separate load and
3943097a140dSpatrick /// branch instructions, with an LFENCE in between. For more details, see:
3944097a140dSpatrick /// - X86LoadValueInjectionRetHardening.cpp
3945097a140dSpatrick /// - X86LoadValueInjectionIndirectThunks.cpp
3946097a140dSpatrick /// - https://software.intel.com/security-software-guidance/insights/deep-dive-load-value-injection
3947097a140dSpatrick ///
3948097a140dSpatrick /// Returns `true` if a mitigation was applied or warning was emitted.
applyLVICFIMitigation(MCInst & Inst,MCStreamer & Out)3949097a140dSpatrick void X86AsmParser::applyLVICFIMitigation(MCInst &Inst, MCStreamer &Out) {
3950097a140dSpatrick // Information on control-flow instructions that require manual mitigation can
3951097a140dSpatrick // be found here:
3952097a140dSpatrick // https://software.intel.com/security-software-guidance/insights/deep-dive-load-value-injection#specialinstructions
3953097a140dSpatrick switch (Inst.getOpcode()) {
3954*d415bd75Srobert case X86::RET16:
3955*d415bd75Srobert case X86::RET32:
3956*d415bd75Srobert case X86::RET64:
3957*d415bd75Srobert case X86::RETI16:
3958*d415bd75Srobert case X86::RETI32:
3959*d415bd75Srobert case X86::RETI64: {
3960097a140dSpatrick MCInst ShlInst, FenceInst;
3961097a140dSpatrick bool Parse32 = is32BitMode() || Code16GCC;
3962097a140dSpatrick unsigned Basereg =
3963097a140dSpatrick is64BitMode() ? X86::RSP : (Parse32 ? X86::ESP : X86::SP);
3964097a140dSpatrick const MCExpr *Disp = MCConstantExpr::create(0, getContext());
3965097a140dSpatrick auto ShlMemOp = X86Operand::CreateMem(getPointerWidth(), /*SegReg=*/0, Disp,
3966097a140dSpatrick /*BaseReg=*/Basereg, /*IndexReg=*/0,
3967097a140dSpatrick /*Scale=*/1, SMLoc{}, SMLoc{}, 0);
3968097a140dSpatrick ShlInst.setOpcode(X86::SHL64mi);
3969097a140dSpatrick ShlMemOp->addMemOperands(ShlInst, 5);
3970097a140dSpatrick ShlInst.addOperand(MCOperand::createImm(0));
3971097a140dSpatrick FenceInst.setOpcode(X86::LFENCE);
3972097a140dSpatrick Out.emitInstruction(ShlInst, getSTI());
3973097a140dSpatrick Out.emitInstruction(FenceInst, getSTI());
3974097a140dSpatrick return;
3975097a140dSpatrick }
3976097a140dSpatrick case X86::JMP16m:
3977097a140dSpatrick case X86::JMP32m:
3978097a140dSpatrick case X86::JMP64m:
3979097a140dSpatrick case X86::CALL16m:
3980097a140dSpatrick case X86::CALL32m:
3981097a140dSpatrick case X86::CALL64m:
3982097a140dSpatrick emitWarningForSpecialLVIInstruction(Inst.getLoc());
3983097a140dSpatrick return;
3984097a140dSpatrick }
3985097a140dSpatrick }
3986097a140dSpatrick
3987097a140dSpatrick /// To mitigate LVI, every instruction that performs a load can be followed by
3988097a140dSpatrick /// an LFENCE instruction to squash any potential mis-speculation. There are
3989097a140dSpatrick /// some instructions that require additional considerations, and may requre
3990097a140dSpatrick /// manual mitigation. For more details, see:
3991097a140dSpatrick /// https://software.intel.com/security-software-guidance/insights/deep-dive-load-value-injection
3992097a140dSpatrick ///
3993097a140dSpatrick /// Returns `true` if a mitigation was applied or warning was emitted.
applyLVILoadHardeningMitigation(MCInst & Inst,MCStreamer & Out)3994097a140dSpatrick void X86AsmParser::applyLVILoadHardeningMitigation(MCInst &Inst,
399509467b48Spatrick MCStreamer &Out) {
3996097a140dSpatrick auto Opcode = Inst.getOpcode();
3997097a140dSpatrick auto Flags = Inst.getFlags();
3998097a140dSpatrick if ((Flags & X86::IP_HAS_REPEAT) || (Flags & X86::IP_HAS_REPEAT_NE)) {
3999097a140dSpatrick // Information on REP string instructions that require manual mitigation can
4000097a140dSpatrick // be found here:
4001097a140dSpatrick // https://software.intel.com/security-software-guidance/insights/deep-dive-load-value-injection#specialinstructions
4002097a140dSpatrick switch (Opcode) {
4003097a140dSpatrick case X86::CMPSB:
4004097a140dSpatrick case X86::CMPSW:
4005097a140dSpatrick case X86::CMPSL:
4006097a140dSpatrick case X86::CMPSQ:
4007097a140dSpatrick case X86::SCASB:
4008097a140dSpatrick case X86::SCASW:
4009097a140dSpatrick case X86::SCASL:
4010097a140dSpatrick case X86::SCASQ:
4011097a140dSpatrick emitWarningForSpecialLVIInstruction(Inst.getLoc());
4012097a140dSpatrick return;
4013097a140dSpatrick }
4014097a140dSpatrick } else if (Opcode == X86::REP_PREFIX || Opcode == X86::REPNE_PREFIX) {
4015097a140dSpatrick // If a REP instruction is found on its own line, it may or may not be
4016097a140dSpatrick // followed by a vulnerable instruction. Emit a warning just in case.
4017097a140dSpatrick emitWarningForSpecialLVIInstruction(Inst.getLoc());
4018097a140dSpatrick return;
4019097a140dSpatrick }
4020097a140dSpatrick
4021097a140dSpatrick const MCInstrDesc &MCID = MII.get(Inst.getOpcode());
4022097a140dSpatrick
4023097a140dSpatrick // Can't mitigate after terminators or calls. A control flow change may have
4024097a140dSpatrick // already occurred.
4025097a140dSpatrick if (MCID.isTerminator() || MCID.isCall())
4026097a140dSpatrick return;
4027097a140dSpatrick
4028097a140dSpatrick // LFENCE has the mayLoad property, don't double fence.
4029097a140dSpatrick if (MCID.mayLoad() && Inst.getOpcode() != X86::LFENCE) {
4030097a140dSpatrick MCInst FenceInst;
4031097a140dSpatrick FenceInst.setOpcode(X86::LFENCE);
4032097a140dSpatrick Out.emitInstruction(FenceInst, getSTI());
4033097a140dSpatrick }
4034097a140dSpatrick }
4035097a140dSpatrick
emitInstruction(MCInst & Inst,OperandVector & Operands,MCStreamer & Out)4036097a140dSpatrick void X86AsmParser::emitInstruction(MCInst &Inst, OperandVector &Operands,
4037097a140dSpatrick MCStreamer &Out) {
4038097a140dSpatrick if (LVIInlineAsmHardening &&
4039097a140dSpatrick getSTI().getFeatureBits()[X86::FeatureLVIControlFlowIntegrity])
4040097a140dSpatrick applyLVICFIMitigation(Inst, Out);
4041097a140dSpatrick
4042097a140dSpatrick Out.emitInstruction(Inst, getSTI());
4043097a140dSpatrick
4044097a140dSpatrick if (LVIInlineAsmHardening &&
4045097a140dSpatrick getSTI().getFeatureBits()[X86::FeatureLVILoadHardening])
4046097a140dSpatrick applyLVILoadHardeningMitigation(Inst, Out);
404709467b48Spatrick }
404809467b48Spatrick
MatchAndEmitInstruction(SMLoc IDLoc,unsigned & Opcode,OperandVector & Operands,MCStreamer & Out,uint64_t & ErrorInfo,bool MatchingInlineAsm)404909467b48Spatrick bool X86AsmParser::MatchAndEmitInstruction(SMLoc IDLoc, unsigned &Opcode,
405009467b48Spatrick OperandVector &Operands,
405109467b48Spatrick MCStreamer &Out, uint64_t &ErrorInfo,
405209467b48Spatrick bool MatchingInlineAsm) {
405309467b48Spatrick if (isParsingIntelSyntax())
405409467b48Spatrick return MatchAndEmitIntelInstruction(IDLoc, Opcode, Operands, Out, ErrorInfo,
405509467b48Spatrick MatchingInlineAsm);
405609467b48Spatrick return MatchAndEmitATTInstruction(IDLoc, Opcode, Operands, Out, ErrorInfo,
405709467b48Spatrick MatchingInlineAsm);
405809467b48Spatrick }
405909467b48Spatrick
MatchFPUWaitAlias(SMLoc IDLoc,X86Operand & Op,OperandVector & Operands,MCStreamer & Out,bool MatchingInlineAsm)406009467b48Spatrick void X86AsmParser::MatchFPUWaitAlias(SMLoc IDLoc, X86Operand &Op,
406109467b48Spatrick OperandVector &Operands, MCStreamer &Out,
406209467b48Spatrick bool MatchingInlineAsm) {
406309467b48Spatrick // FIXME: This should be replaced with a real .td file alias mechanism.
406409467b48Spatrick // Also, MatchInstructionImpl should actually *do* the EmitInstruction
406509467b48Spatrick // call.
406609467b48Spatrick const char *Repl = StringSwitch<const char *>(Op.getToken())
406709467b48Spatrick .Case("finit", "fninit")
406809467b48Spatrick .Case("fsave", "fnsave")
406909467b48Spatrick .Case("fstcw", "fnstcw")
407009467b48Spatrick .Case("fstcww", "fnstcw")
407109467b48Spatrick .Case("fstenv", "fnstenv")
407209467b48Spatrick .Case("fstsw", "fnstsw")
407309467b48Spatrick .Case("fstsww", "fnstsw")
407409467b48Spatrick .Case("fclex", "fnclex")
407509467b48Spatrick .Default(nullptr);
407609467b48Spatrick if (Repl) {
407709467b48Spatrick MCInst Inst;
407809467b48Spatrick Inst.setOpcode(X86::WAIT);
407909467b48Spatrick Inst.setLoc(IDLoc);
408009467b48Spatrick if (!MatchingInlineAsm)
4081097a140dSpatrick emitInstruction(Inst, Operands, Out);
408209467b48Spatrick Operands[0] = X86Operand::CreateToken(Repl, IDLoc);
408309467b48Spatrick }
408409467b48Spatrick }
408509467b48Spatrick
ErrorMissingFeature(SMLoc IDLoc,const FeatureBitset & MissingFeatures,bool MatchingInlineAsm)408609467b48Spatrick bool X86AsmParser::ErrorMissingFeature(SMLoc IDLoc,
408709467b48Spatrick const FeatureBitset &MissingFeatures,
408809467b48Spatrick bool MatchingInlineAsm) {
408909467b48Spatrick assert(MissingFeatures.any() && "Unknown missing feature!");
409009467b48Spatrick SmallString<126> Msg;
409109467b48Spatrick raw_svector_ostream OS(Msg);
409209467b48Spatrick OS << "instruction requires:";
409309467b48Spatrick for (unsigned i = 0, e = MissingFeatures.size(); i != e; ++i) {
409409467b48Spatrick if (MissingFeatures[i])
409509467b48Spatrick OS << ' ' << getSubtargetFeatureName(i);
409609467b48Spatrick }
409709467b48Spatrick return Error(IDLoc, OS.str(), SMRange(), MatchingInlineAsm);
409809467b48Spatrick }
409909467b48Spatrick
getPrefixes(OperandVector & Operands)410009467b48Spatrick static unsigned getPrefixes(OperandVector &Operands) {
410109467b48Spatrick unsigned Result = 0;
410209467b48Spatrick X86Operand &Prefix = static_cast<X86Operand &>(*Operands.back());
410309467b48Spatrick if (Prefix.isPrefix()) {
410409467b48Spatrick Result = Prefix.getPrefix();
410509467b48Spatrick Operands.pop_back();
410609467b48Spatrick }
410709467b48Spatrick return Result;
410809467b48Spatrick }
410909467b48Spatrick
checkTargetMatchPredicate(MCInst & Inst)411009467b48Spatrick unsigned X86AsmParser::checkTargetMatchPredicate(MCInst &Inst) {
411109467b48Spatrick unsigned Opc = Inst.getOpcode();
411209467b48Spatrick const MCInstrDesc &MCID = MII.get(Opc);
411309467b48Spatrick
411409467b48Spatrick if (ForcedVEXEncoding == VEXEncoding_EVEX &&
411509467b48Spatrick (MCID.TSFlags & X86II::EncodingMask) != X86II::EVEX)
411609467b48Spatrick return Match_Unsupported;
411709467b48Spatrick
4118097a140dSpatrick if ((ForcedVEXEncoding == VEXEncoding_VEX ||
411973471bf0Spatrick ForcedVEXEncoding == VEXEncoding_VEX2 ||
412009467b48Spatrick ForcedVEXEncoding == VEXEncoding_VEX3) &&
412109467b48Spatrick (MCID.TSFlags & X86II::EncodingMask) != X86II::VEX)
412209467b48Spatrick return Match_Unsupported;
412309467b48Spatrick
412473471bf0Spatrick // These instructions are only available with {vex}, {vex2} or {vex3} prefix
412573471bf0Spatrick if (MCID.TSFlags & X86II::ExplicitVEXPrefix &&
412673471bf0Spatrick (ForcedVEXEncoding != VEXEncoding_VEX &&
412773471bf0Spatrick ForcedVEXEncoding != VEXEncoding_VEX2 &&
412873471bf0Spatrick ForcedVEXEncoding != VEXEncoding_VEX3))
412973471bf0Spatrick return Match_Unsupported;
413073471bf0Spatrick
413109467b48Spatrick return Match_Success;
413209467b48Spatrick }
413309467b48Spatrick
MatchAndEmitATTInstruction(SMLoc IDLoc,unsigned & Opcode,OperandVector & Operands,MCStreamer & Out,uint64_t & ErrorInfo,bool MatchingInlineAsm)413409467b48Spatrick bool X86AsmParser::MatchAndEmitATTInstruction(SMLoc IDLoc, unsigned &Opcode,
413509467b48Spatrick OperandVector &Operands,
413609467b48Spatrick MCStreamer &Out,
413709467b48Spatrick uint64_t &ErrorInfo,
413809467b48Spatrick bool MatchingInlineAsm) {
413909467b48Spatrick assert(!Operands.empty() && "Unexpect empty operand list!");
414009467b48Spatrick assert((*Operands[0]).isToken() && "Leading operand should always be a mnemonic!");
4141*d415bd75Srobert SMRange EmptyRange = std::nullopt;
414209467b48Spatrick
414309467b48Spatrick // First, handle aliases that expand to multiple instructions.
414409467b48Spatrick MatchFPUWaitAlias(IDLoc, static_cast<X86Operand &>(*Operands[0]), Operands,
414509467b48Spatrick Out, MatchingInlineAsm);
414609467b48Spatrick X86Operand &Op = static_cast<X86Operand &>(*Operands[0]);
414709467b48Spatrick unsigned Prefixes = getPrefixes(Operands);
414809467b48Spatrick
414909467b48Spatrick MCInst Inst;
415009467b48Spatrick
415173471bf0Spatrick // If VEX/EVEX encoding is forced, we need to pass the USE_* flag to the
415273471bf0Spatrick // encoder and printer.
415373471bf0Spatrick if (ForcedVEXEncoding == VEXEncoding_VEX)
415473471bf0Spatrick Prefixes |= X86::IP_USE_VEX;
415573471bf0Spatrick else if (ForcedVEXEncoding == VEXEncoding_VEX2)
415673471bf0Spatrick Prefixes |= X86::IP_USE_VEX2;
415773471bf0Spatrick else if (ForcedVEXEncoding == VEXEncoding_VEX3)
415809467b48Spatrick Prefixes |= X86::IP_USE_VEX3;
415973471bf0Spatrick else if (ForcedVEXEncoding == VEXEncoding_EVEX)
416073471bf0Spatrick Prefixes |= X86::IP_USE_EVEX;
416173471bf0Spatrick
416273471bf0Spatrick // Set encoded flags for {disp8} and {disp32}.
416373471bf0Spatrick if (ForcedDispEncoding == DispEncoding_Disp8)
416473471bf0Spatrick Prefixes |= X86::IP_USE_DISP8;
416573471bf0Spatrick else if (ForcedDispEncoding == DispEncoding_Disp32)
416673471bf0Spatrick Prefixes |= X86::IP_USE_DISP32;
416709467b48Spatrick
416809467b48Spatrick if (Prefixes)
416909467b48Spatrick Inst.setFlags(Prefixes);
417009467b48Spatrick
417173471bf0Spatrick // In 16-bit mode, if data32 is specified, temporarily switch to 32-bit mode
417273471bf0Spatrick // when matching the instruction.
4173*d415bd75Srobert if (ForcedDataPrefix == X86::Is32Bit)
4174*d415bd75Srobert SwitchMode(X86::Is32Bit);
417509467b48Spatrick // First, try a direct match.
417609467b48Spatrick FeatureBitset MissingFeatures;
417709467b48Spatrick unsigned OriginalError = MatchInstruction(Operands, Inst, ErrorInfo,
417809467b48Spatrick MissingFeatures, MatchingInlineAsm,
417909467b48Spatrick isParsingIntelSyntax());
4180*d415bd75Srobert if (ForcedDataPrefix == X86::Is32Bit) {
4181*d415bd75Srobert SwitchMode(X86::Is16Bit);
418273471bf0Spatrick ForcedDataPrefix = 0;
418373471bf0Spatrick }
418409467b48Spatrick switch (OriginalError) {
418509467b48Spatrick default: llvm_unreachable("Unexpected match result!");
418609467b48Spatrick case Match_Success:
418709467b48Spatrick if (!MatchingInlineAsm && validateInstruction(Inst, Operands))
418809467b48Spatrick return true;
418909467b48Spatrick // Some instructions need post-processing to, for example, tweak which
419009467b48Spatrick // encoding is selected. Loop on it while changes happen so the
419109467b48Spatrick // individual transformations can chain off each other.
419209467b48Spatrick if (!MatchingInlineAsm)
419309467b48Spatrick while (processInstruction(Inst, Operands))
419409467b48Spatrick ;
419509467b48Spatrick
419609467b48Spatrick Inst.setLoc(IDLoc);
419709467b48Spatrick if (!MatchingInlineAsm)
4198097a140dSpatrick emitInstruction(Inst, Operands, Out);
419909467b48Spatrick Opcode = Inst.getOpcode();
420009467b48Spatrick return false;
420109467b48Spatrick case Match_InvalidImmUnsignedi4: {
420209467b48Spatrick SMLoc ErrorLoc = ((X86Operand &)*Operands[ErrorInfo]).getStartLoc();
420309467b48Spatrick if (ErrorLoc == SMLoc())
420409467b48Spatrick ErrorLoc = IDLoc;
420509467b48Spatrick return Error(ErrorLoc, "immediate must be an integer in range [0, 15]",
420609467b48Spatrick EmptyRange, MatchingInlineAsm);
420709467b48Spatrick }
420809467b48Spatrick case Match_MissingFeature:
420909467b48Spatrick return ErrorMissingFeature(IDLoc, MissingFeatures, MatchingInlineAsm);
421009467b48Spatrick case Match_InvalidOperand:
421109467b48Spatrick case Match_MnemonicFail:
421209467b48Spatrick case Match_Unsupported:
421309467b48Spatrick break;
421409467b48Spatrick }
421509467b48Spatrick if (Op.getToken().empty()) {
421609467b48Spatrick Error(IDLoc, "instruction must have size higher than 0", EmptyRange,
421709467b48Spatrick MatchingInlineAsm);
421809467b48Spatrick return true;
421909467b48Spatrick }
422009467b48Spatrick
422109467b48Spatrick // FIXME: Ideally, we would only attempt suffix matches for things which are
422209467b48Spatrick // valid prefixes, and we could just infer the right unambiguous
422309467b48Spatrick // type. However, that requires substantially more matcher support than the
422409467b48Spatrick // following hack.
422509467b48Spatrick
422609467b48Spatrick // Change the operand to point to a temporary token.
422709467b48Spatrick StringRef Base = Op.getToken();
422809467b48Spatrick SmallString<16> Tmp;
422909467b48Spatrick Tmp += Base;
423009467b48Spatrick Tmp += ' ';
423109467b48Spatrick Op.setTokenValue(Tmp);
423209467b48Spatrick
423309467b48Spatrick // If this instruction starts with an 'f', then it is a floating point stack
423409467b48Spatrick // instruction. These come in up to three forms for 32-bit, 64-bit, and
423509467b48Spatrick // 80-bit floating point, which use the suffixes s,l,t respectively.
423609467b48Spatrick //
423709467b48Spatrick // Otherwise, we assume that this may be an integer instruction, which comes
423809467b48Spatrick // in 8/16/32/64-bit forms using the b,w,l,q suffixes respectively.
423909467b48Spatrick const char *Suffixes = Base[0] != 'f' ? "bwlq" : "slt\0";
4240097a140dSpatrick // MemSize corresponding to Suffixes. { 8, 16, 32, 64 } { 32, 64, 80, 0 }
4241097a140dSpatrick const char *MemSize = Base[0] != 'f' ? "\x08\x10\x20\x40" : "\x20\x40\x50\0";
424209467b48Spatrick
424309467b48Spatrick // Check for the various suffix matches.
424409467b48Spatrick uint64_t ErrorInfoIgnore;
424509467b48Spatrick FeatureBitset ErrorInfoMissingFeatures; // Init suppresses compiler warnings.
424609467b48Spatrick unsigned Match[4];
424709467b48Spatrick
4248097a140dSpatrick // Some instruction like VPMULDQ is NOT the variant of VPMULD but a new one.
4249097a140dSpatrick // So we should make sure the suffix matcher only works for memory variant
4250097a140dSpatrick // that has the same size with the suffix.
4251097a140dSpatrick // FIXME: This flag is a workaround for legacy instructions that didn't
4252097a140dSpatrick // declare non suffix variant assembly.
4253097a140dSpatrick bool HasVectorReg = false;
4254097a140dSpatrick X86Operand *MemOp = nullptr;
4255097a140dSpatrick for (const auto &Op : Operands) {
4256097a140dSpatrick X86Operand *X86Op = static_cast<X86Operand *>(Op.get());
4257097a140dSpatrick if (X86Op->isVectorReg())
4258097a140dSpatrick HasVectorReg = true;
4259097a140dSpatrick else if (X86Op->isMem()) {
4260097a140dSpatrick MemOp = X86Op;
4261097a140dSpatrick assert(MemOp->Mem.Size == 0 && "Memory size always 0 under ATT syntax");
4262097a140dSpatrick // Have we found an unqualified memory operand,
4263097a140dSpatrick // break. IA allows only one memory operand.
4264097a140dSpatrick break;
4265097a140dSpatrick }
4266097a140dSpatrick }
4267097a140dSpatrick
4268*d415bd75Srobert for (unsigned I = 0, E = std::size(Match); I != E; ++I) {
426909467b48Spatrick Tmp.back() = Suffixes[I];
4270097a140dSpatrick if (MemOp && HasVectorReg)
4271097a140dSpatrick MemOp->Mem.Size = MemSize[I];
4272097a140dSpatrick Match[I] = Match_MnemonicFail;
4273097a140dSpatrick if (MemOp || !HasVectorReg) {
4274097a140dSpatrick Match[I] =
4275097a140dSpatrick MatchInstruction(Operands, Inst, ErrorInfoIgnore, MissingFeatures,
4276097a140dSpatrick MatchingInlineAsm, isParsingIntelSyntax());
427709467b48Spatrick // If this returned as a missing feature failure, remember that.
427809467b48Spatrick if (Match[I] == Match_MissingFeature)
427909467b48Spatrick ErrorInfoMissingFeatures = MissingFeatures;
428009467b48Spatrick }
4281097a140dSpatrick }
428209467b48Spatrick
428309467b48Spatrick // Restore the old token.
428409467b48Spatrick Op.setTokenValue(Base);
428509467b48Spatrick
428609467b48Spatrick // If exactly one matched, then we treat that as a successful match (and the
428709467b48Spatrick // instruction will already have been filled in correctly, since the failing
428809467b48Spatrick // matches won't have modified it).
4289*d415bd75Srobert unsigned NumSuccessfulMatches = llvm::count(Match, Match_Success);
429009467b48Spatrick if (NumSuccessfulMatches == 1) {
429173471bf0Spatrick if (!MatchingInlineAsm && validateInstruction(Inst, Operands))
429273471bf0Spatrick return true;
429373471bf0Spatrick // Some instructions need post-processing to, for example, tweak which
429473471bf0Spatrick // encoding is selected. Loop on it while changes happen so the
429573471bf0Spatrick // individual transformations can chain off each other.
429673471bf0Spatrick if (!MatchingInlineAsm)
429773471bf0Spatrick while (processInstruction(Inst, Operands))
429873471bf0Spatrick ;
429973471bf0Spatrick
430009467b48Spatrick Inst.setLoc(IDLoc);
430109467b48Spatrick if (!MatchingInlineAsm)
4302097a140dSpatrick emitInstruction(Inst, Operands, Out);
430309467b48Spatrick Opcode = Inst.getOpcode();
430409467b48Spatrick return false;
430509467b48Spatrick }
430609467b48Spatrick
430709467b48Spatrick // Otherwise, the match failed, try to produce a decent error message.
430809467b48Spatrick
430909467b48Spatrick // If we had multiple suffix matches, then identify this as an ambiguous
431009467b48Spatrick // match.
431109467b48Spatrick if (NumSuccessfulMatches > 1) {
431209467b48Spatrick char MatchChars[4];
431309467b48Spatrick unsigned NumMatches = 0;
4314*d415bd75Srobert for (unsigned I = 0, E = std::size(Match); I != E; ++I)
431509467b48Spatrick if (Match[I] == Match_Success)
431609467b48Spatrick MatchChars[NumMatches++] = Suffixes[I];
431709467b48Spatrick
431809467b48Spatrick SmallString<126> Msg;
431909467b48Spatrick raw_svector_ostream OS(Msg);
432009467b48Spatrick OS << "ambiguous instructions require an explicit suffix (could be ";
432109467b48Spatrick for (unsigned i = 0; i != NumMatches; ++i) {
432209467b48Spatrick if (i != 0)
432309467b48Spatrick OS << ", ";
432409467b48Spatrick if (i + 1 == NumMatches)
432509467b48Spatrick OS << "or ";
432609467b48Spatrick OS << "'" << Base << MatchChars[i] << "'";
432709467b48Spatrick }
432809467b48Spatrick OS << ")";
432909467b48Spatrick Error(IDLoc, OS.str(), EmptyRange, MatchingInlineAsm);
433009467b48Spatrick return true;
433109467b48Spatrick }
433209467b48Spatrick
433309467b48Spatrick // Okay, we know that none of the variants matched successfully.
433409467b48Spatrick
433509467b48Spatrick // If all of the instructions reported an invalid mnemonic, then the original
433609467b48Spatrick // mnemonic was invalid.
4337*d415bd75Srobert if (llvm::count(Match, Match_MnemonicFail) == 4) {
433809467b48Spatrick if (OriginalError == Match_MnemonicFail)
433909467b48Spatrick return Error(IDLoc, "invalid instruction mnemonic '" + Base + "'",
434009467b48Spatrick Op.getLocRange(), MatchingInlineAsm);
434109467b48Spatrick
434209467b48Spatrick if (OriginalError == Match_Unsupported)
434309467b48Spatrick return Error(IDLoc, "unsupported instruction", EmptyRange,
434409467b48Spatrick MatchingInlineAsm);
434509467b48Spatrick
434609467b48Spatrick assert(OriginalError == Match_InvalidOperand && "Unexpected error");
434709467b48Spatrick // Recover location info for the operand if we know which was the problem.
434809467b48Spatrick if (ErrorInfo != ~0ULL) {
434909467b48Spatrick if (ErrorInfo >= Operands.size())
435009467b48Spatrick return Error(IDLoc, "too few operands for instruction", EmptyRange,
435109467b48Spatrick MatchingInlineAsm);
435209467b48Spatrick
435309467b48Spatrick X86Operand &Operand = (X86Operand &)*Operands[ErrorInfo];
435409467b48Spatrick if (Operand.getStartLoc().isValid()) {
435509467b48Spatrick SMRange OperandRange = Operand.getLocRange();
435609467b48Spatrick return Error(Operand.getStartLoc(), "invalid operand for instruction",
435709467b48Spatrick OperandRange, MatchingInlineAsm);
435809467b48Spatrick }
435909467b48Spatrick }
436009467b48Spatrick
436109467b48Spatrick return Error(IDLoc, "invalid operand for instruction", EmptyRange,
436209467b48Spatrick MatchingInlineAsm);
436309467b48Spatrick }
436409467b48Spatrick
436509467b48Spatrick // If one instruction matched as unsupported, report this as unsupported.
4366*d415bd75Srobert if (llvm::count(Match, Match_Unsupported) == 1) {
436709467b48Spatrick return Error(IDLoc, "unsupported instruction", EmptyRange,
436809467b48Spatrick MatchingInlineAsm);
436909467b48Spatrick }
437009467b48Spatrick
437109467b48Spatrick // If one instruction matched with a missing feature, report this as a
437209467b48Spatrick // missing feature.
4373*d415bd75Srobert if (llvm::count(Match, Match_MissingFeature) == 1) {
437409467b48Spatrick ErrorInfo = Match_MissingFeature;
437509467b48Spatrick return ErrorMissingFeature(IDLoc, ErrorInfoMissingFeatures,
437609467b48Spatrick MatchingInlineAsm);
437709467b48Spatrick }
437809467b48Spatrick
437909467b48Spatrick // If one instruction matched with an invalid operand, report this as an
438009467b48Spatrick // operand failure.
4381*d415bd75Srobert if (llvm::count(Match, Match_InvalidOperand) == 1) {
438209467b48Spatrick return Error(IDLoc, "invalid operand for instruction", EmptyRange,
438309467b48Spatrick MatchingInlineAsm);
438409467b48Spatrick }
438509467b48Spatrick
438609467b48Spatrick // If all of these were an outright failure, report it in a useless way.
438709467b48Spatrick Error(IDLoc, "unknown use of instruction mnemonic without a size suffix",
438809467b48Spatrick EmptyRange, MatchingInlineAsm);
438909467b48Spatrick return true;
439009467b48Spatrick }
439109467b48Spatrick
MatchAndEmitIntelInstruction(SMLoc IDLoc,unsigned & Opcode,OperandVector & Operands,MCStreamer & Out,uint64_t & ErrorInfo,bool MatchingInlineAsm)439209467b48Spatrick bool X86AsmParser::MatchAndEmitIntelInstruction(SMLoc IDLoc, unsigned &Opcode,
439309467b48Spatrick OperandVector &Operands,
439409467b48Spatrick MCStreamer &Out,
439509467b48Spatrick uint64_t &ErrorInfo,
439609467b48Spatrick bool MatchingInlineAsm) {
439709467b48Spatrick assert(!Operands.empty() && "Unexpect empty operand list!");
439809467b48Spatrick assert((*Operands[0]).isToken() && "Leading operand should always be a mnemonic!");
439909467b48Spatrick StringRef Mnemonic = (static_cast<X86Operand &>(*Operands[0])).getToken();
4400*d415bd75Srobert SMRange EmptyRange = std::nullopt;
440109467b48Spatrick StringRef Base = (static_cast<X86Operand &>(*Operands[0])).getToken();
440209467b48Spatrick unsigned Prefixes = getPrefixes(Operands);
440309467b48Spatrick
440409467b48Spatrick // First, handle aliases that expand to multiple instructions.
440509467b48Spatrick MatchFPUWaitAlias(IDLoc, static_cast<X86Operand &>(*Operands[0]), Operands, Out, MatchingInlineAsm);
440609467b48Spatrick X86Operand &Op = static_cast<X86Operand &>(*Operands[0]);
440709467b48Spatrick
440809467b48Spatrick MCInst Inst;
440909467b48Spatrick
441073471bf0Spatrick // If VEX/EVEX encoding is forced, we need to pass the USE_* flag to the
441173471bf0Spatrick // encoder and printer.
441273471bf0Spatrick if (ForcedVEXEncoding == VEXEncoding_VEX)
441373471bf0Spatrick Prefixes |= X86::IP_USE_VEX;
441473471bf0Spatrick else if (ForcedVEXEncoding == VEXEncoding_VEX2)
441573471bf0Spatrick Prefixes |= X86::IP_USE_VEX2;
441673471bf0Spatrick else if (ForcedVEXEncoding == VEXEncoding_VEX3)
441709467b48Spatrick Prefixes |= X86::IP_USE_VEX3;
441873471bf0Spatrick else if (ForcedVEXEncoding == VEXEncoding_EVEX)
441973471bf0Spatrick Prefixes |= X86::IP_USE_EVEX;
442073471bf0Spatrick
442173471bf0Spatrick // Set encoded flags for {disp8} and {disp32}.
442273471bf0Spatrick if (ForcedDispEncoding == DispEncoding_Disp8)
442373471bf0Spatrick Prefixes |= X86::IP_USE_DISP8;
442473471bf0Spatrick else if (ForcedDispEncoding == DispEncoding_Disp32)
442573471bf0Spatrick Prefixes |= X86::IP_USE_DISP32;
442609467b48Spatrick
442709467b48Spatrick if (Prefixes)
442809467b48Spatrick Inst.setFlags(Prefixes);
442909467b48Spatrick
443009467b48Spatrick // Find one unsized memory operand, if present.
443109467b48Spatrick X86Operand *UnsizedMemOp = nullptr;
443209467b48Spatrick for (const auto &Op : Operands) {
443309467b48Spatrick X86Operand *X86Op = static_cast<X86Operand *>(Op.get());
443409467b48Spatrick if (X86Op->isMemUnsized()) {
443509467b48Spatrick UnsizedMemOp = X86Op;
443609467b48Spatrick // Have we found an unqualified memory operand,
443709467b48Spatrick // break. IA allows only one memory operand.
443809467b48Spatrick break;
443909467b48Spatrick }
444009467b48Spatrick }
444109467b48Spatrick
444209467b48Spatrick // Allow some instructions to have implicitly pointer-sized operands. This is
444309467b48Spatrick // compatible with gas.
444409467b48Spatrick if (UnsizedMemOp) {
444509467b48Spatrick static const char *const PtrSizedInstrs[] = {"call", "jmp", "push"};
444609467b48Spatrick for (const char *Instr : PtrSizedInstrs) {
444709467b48Spatrick if (Mnemonic == Instr) {
444809467b48Spatrick UnsizedMemOp->Mem.Size = getPointerWidth();
444909467b48Spatrick break;
445009467b48Spatrick }
445109467b48Spatrick }
445209467b48Spatrick }
445309467b48Spatrick
445409467b48Spatrick SmallVector<unsigned, 8> Match;
445509467b48Spatrick FeatureBitset ErrorInfoMissingFeatures;
445609467b48Spatrick FeatureBitset MissingFeatures;
445709467b48Spatrick
445809467b48Spatrick // If unsized push has immediate operand we should default the default pointer
445909467b48Spatrick // size for the size.
446009467b48Spatrick if (Mnemonic == "push" && Operands.size() == 2) {
446109467b48Spatrick auto *X86Op = static_cast<X86Operand *>(Operands[1].get());
446209467b48Spatrick if (X86Op->isImm()) {
446309467b48Spatrick // If it's not a constant fall through and let remainder take care of it.
446409467b48Spatrick const auto *CE = dyn_cast<MCConstantExpr>(X86Op->getImm());
446509467b48Spatrick unsigned Size = getPointerWidth();
446609467b48Spatrick if (CE &&
446709467b48Spatrick (isIntN(Size, CE->getValue()) || isUIntN(Size, CE->getValue()))) {
446809467b48Spatrick SmallString<16> Tmp;
446909467b48Spatrick Tmp += Base;
447009467b48Spatrick Tmp += (is64BitMode())
447109467b48Spatrick ? "q"
447209467b48Spatrick : (is32BitMode()) ? "l" : (is16BitMode()) ? "w" : " ";
447309467b48Spatrick Op.setTokenValue(Tmp);
447409467b48Spatrick // Do match in ATT mode to allow explicit suffix usage.
447509467b48Spatrick Match.push_back(MatchInstruction(Operands, Inst, ErrorInfo,
447609467b48Spatrick MissingFeatures, MatchingInlineAsm,
447709467b48Spatrick false /*isParsingIntelSyntax()*/));
447809467b48Spatrick Op.setTokenValue(Base);
447909467b48Spatrick }
448009467b48Spatrick }
448109467b48Spatrick }
448209467b48Spatrick
448309467b48Spatrick // If an unsized memory operand is present, try to match with each memory
448409467b48Spatrick // operand size. In Intel assembly, the size is not part of the instruction
448509467b48Spatrick // mnemonic.
448609467b48Spatrick if (UnsizedMemOp && UnsizedMemOp->isMemUnsized()) {
448709467b48Spatrick static const unsigned MopSizes[] = {8, 16, 32, 64, 80, 128, 256, 512};
448809467b48Spatrick for (unsigned Size : MopSizes) {
448909467b48Spatrick UnsizedMemOp->Mem.Size = Size;
449009467b48Spatrick uint64_t ErrorInfoIgnore;
449109467b48Spatrick unsigned LastOpcode = Inst.getOpcode();
449209467b48Spatrick unsigned M = MatchInstruction(Operands, Inst, ErrorInfoIgnore,
449309467b48Spatrick MissingFeatures, MatchingInlineAsm,
449409467b48Spatrick isParsingIntelSyntax());
449509467b48Spatrick if (Match.empty() || LastOpcode != Inst.getOpcode())
449609467b48Spatrick Match.push_back(M);
449709467b48Spatrick
449809467b48Spatrick // If this returned as a missing feature failure, remember that.
449909467b48Spatrick if (Match.back() == Match_MissingFeature)
450009467b48Spatrick ErrorInfoMissingFeatures = MissingFeatures;
450109467b48Spatrick }
450209467b48Spatrick
450309467b48Spatrick // Restore the size of the unsized memory operand if we modified it.
450409467b48Spatrick UnsizedMemOp->Mem.Size = 0;
450509467b48Spatrick }
450609467b48Spatrick
450709467b48Spatrick // If we haven't matched anything yet, this is not a basic integer or FPU
450809467b48Spatrick // operation. There shouldn't be any ambiguity in our mnemonic table, so try
450909467b48Spatrick // matching with the unsized operand.
451009467b48Spatrick if (Match.empty()) {
451109467b48Spatrick Match.push_back(MatchInstruction(
451209467b48Spatrick Operands, Inst, ErrorInfo, MissingFeatures, MatchingInlineAsm,
451309467b48Spatrick isParsingIntelSyntax()));
451409467b48Spatrick // If this returned as a missing feature failure, remember that.
451509467b48Spatrick if (Match.back() == Match_MissingFeature)
451609467b48Spatrick ErrorInfoMissingFeatures = MissingFeatures;
451709467b48Spatrick }
451809467b48Spatrick
451909467b48Spatrick // Restore the size of the unsized memory operand if we modified it.
452009467b48Spatrick if (UnsizedMemOp)
452109467b48Spatrick UnsizedMemOp->Mem.Size = 0;
452209467b48Spatrick
452309467b48Spatrick // If it's a bad mnemonic, all results will be the same.
452409467b48Spatrick if (Match.back() == Match_MnemonicFail) {
452509467b48Spatrick return Error(IDLoc, "invalid instruction mnemonic '" + Mnemonic + "'",
452609467b48Spatrick Op.getLocRange(), MatchingInlineAsm);
452709467b48Spatrick }
452809467b48Spatrick
4529*d415bd75Srobert unsigned NumSuccessfulMatches = llvm::count(Match, Match_Success);
453009467b48Spatrick
453109467b48Spatrick // If matching was ambiguous and we had size information from the frontend,
453209467b48Spatrick // try again with that. This handles cases like "movxz eax, m8/m16".
453309467b48Spatrick if (UnsizedMemOp && NumSuccessfulMatches > 1 &&
453409467b48Spatrick UnsizedMemOp->getMemFrontendSize()) {
453509467b48Spatrick UnsizedMemOp->Mem.Size = UnsizedMemOp->getMemFrontendSize();
453609467b48Spatrick unsigned M = MatchInstruction(
453709467b48Spatrick Operands, Inst, ErrorInfo, MissingFeatures, MatchingInlineAsm,
453809467b48Spatrick isParsingIntelSyntax());
453909467b48Spatrick if (M == Match_Success)
454009467b48Spatrick NumSuccessfulMatches = 1;
454109467b48Spatrick
454209467b48Spatrick // Add a rewrite that encodes the size information we used from the
454309467b48Spatrick // frontend.
454409467b48Spatrick InstInfo->AsmRewrites->emplace_back(
454509467b48Spatrick AOK_SizeDirective, UnsizedMemOp->getStartLoc(),
454609467b48Spatrick /*Len=*/0, UnsizedMemOp->getMemFrontendSize());
454709467b48Spatrick }
454809467b48Spatrick
454909467b48Spatrick // If exactly one matched, then we treat that as a successful match (and the
455009467b48Spatrick // instruction will already have been filled in correctly, since the failing
455109467b48Spatrick // matches won't have modified it).
455209467b48Spatrick if (NumSuccessfulMatches == 1) {
455309467b48Spatrick if (!MatchingInlineAsm && validateInstruction(Inst, Operands))
455409467b48Spatrick return true;
455509467b48Spatrick // Some instructions need post-processing to, for example, tweak which
455609467b48Spatrick // encoding is selected. Loop on it while changes happen so the individual
455709467b48Spatrick // transformations can chain off each other.
455809467b48Spatrick if (!MatchingInlineAsm)
455909467b48Spatrick while (processInstruction(Inst, Operands))
456009467b48Spatrick ;
456109467b48Spatrick Inst.setLoc(IDLoc);
456209467b48Spatrick if (!MatchingInlineAsm)
4563097a140dSpatrick emitInstruction(Inst, Operands, Out);
456409467b48Spatrick Opcode = Inst.getOpcode();
456509467b48Spatrick return false;
456609467b48Spatrick } else if (NumSuccessfulMatches > 1) {
456709467b48Spatrick assert(UnsizedMemOp &&
456809467b48Spatrick "multiple matches only possible with unsized memory operands");
456909467b48Spatrick return Error(UnsizedMemOp->getStartLoc(),
457009467b48Spatrick "ambiguous operand size for instruction '" + Mnemonic + "\'",
457109467b48Spatrick UnsizedMemOp->getLocRange());
457209467b48Spatrick }
457309467b48Spatrick
457409467b48Spatrick // If one instruction matched as unsupported, report this as unsupported.
4575*d415bd75Srobert if (llvm::count(Match, Match_Unsupported) == 1) {
457609467b48Spatrick return Error(IDLoc, "unsupported instruction", EmptyRange,
457709467b48Spatrick MatchingInlineAsm);
457809467b48Spatrick }
457909467b48Spatrick
458009467b48Spatrick // If one instruction matched with a missing feature, report this as a
458109467b48Spatrick // missing feature.
4582*d415bd75Srobert if (llvm::count(Match, Match_MissingFeature) == 1) {
458309467b48Spatrick ErrorInfo = Match_MissingFeature;
458409467b48Spatrick return ErrorMissingFeature(IDLoc, ErrorInfoMissingFeatures,
458509467b48Spatrick MatchingInlineAsm);
458609467b48Spatrick }
458709467b48Spatrick
458809467b48Spatrick // If one instruction matched with an invalid operand, report this as an
458909467b48Spatrick // operand failure.
4590*d415bd75Srobert if (llvm::count(Match, Match_InvalidOperand) == 1) {
459109467b48Spatrick return Error(IDLoc, "invalid operand for instruction", EmptyRange,
459209467b48Spatrick MatchingInlineAsm);
459309467b48Spatrick }
459409467b48Spatrick
4595*d415bd75Srobert if (llvm::count(Match, Match_InvalidImmUnsignedi4) == 1) {
459609467b48Spatrick SMLoc ErrorLoc = ((X86Operand &)*Operands[ErrorInfo]).getStartLoc();
459709467b48Spatrick if (ErrorLoc == SMLoc())
459809467b48Spatrick ErrorLoc = IDLoc;
459909467b48Spatrick return Error(ErrorLoc, "immediate must be an integer in range [0, 15]",
460009467b48Spatrick EmptyRange, MatchingInlineAsm);
460109467b48Spatrick }
460209467b48Spatrick
460309467b48Spatrick // If all of these were an outright failure, report it in a useless way.
460409467b48Spatrick return Error(IDLoc, "unknown instruction mnemonic", EmptyRange,
460509467b48Spatrick MatchingInlineAsm);
460609467b48Spatrick }
460709467b48Spatrick
OmitRegisterFromClobberLists(unsigned RegNo)460809467b48Spatrick bool X86AsmParser::OmitRegisterFromClobberLists(unsigned RegNo) {
460909467b48Spatrick return X86MCRegisterClasses[X86::SEGMENT_REGRegClassID].contains(RegNo);
461009467b48Spatrick }
461109467b48Spatrick
ParseDirective(AsmToken DirectiveID)461209467b48Spatrick bool X86AsmParser::ParseDirective(AsmToken DirectiveID) {
461309467b48Spatrick MCAsmParser &Parser = getParser();
461409467b48Spatrick StringRef IDVal = DirectiveID.getIdentifier();
461573471bf0Spatrick if (IDVal.startswith(".arch"))
461673471bf0Spatrick return parseDirectiveArch();
461709467b48Spatrick if (IDVal.startswith(".code"))
461809467b48Spatrick return ParseDirectiveCode(IDVal, DirectiveID.getLoc());
461909467b48Spatrick else if (IDVal.startswith(".att_syntax")) {
462009467b48Spatrick if (getLexer().isNot(AsmToken::EndOfStatement)) {
462109467b48Spatrick if (Parser.getTok().getString() == "prefix")
462209467b48Spatrick Parser.Lex();
462309467b48Spatrick else if (Parser.getTok().getString() == "noprefix")
462409467b48Spatrick return Error(DirectiveID.getLoc(), "'.att_syntax noprefix' is not "
462509467b48Spatrick "supported: registers must have a "
462609467b48Spatrick "'%' prefix in .att_syntax");
462709467b48Spatrick }
462809467b48Spatrick getParser().setAssemblerDialect(0);
462909467b48Spatrick return false;
463009467b48Spatrick } else if (IDVal.startswith(".intel_syntax")) {
463109467b48Spatrick getParser().setAssemblerDialect(1);
463209467b48Spatrick if (getLexer().isNot(AsmToken::EndOfStatement)) {
463309467b48Spatrick if (Parser.getTok().getString() == "noprefix")
463409467b48Spatrick Parser.Lex();
463509467b48Spatrick else if (Parser.getTok().getString() == "prefix")
463609467b48Spatrick return Error(DirectiveID.getLoc(), "'.intel_syntax prefix' is not "
463709467b48Spatrick "supported: registers must not have "
463809467b48Spatrick "a '%' prefix in .intel_syntax");
463909467b48Spatrick }
464009467b48Spatrick return false;
464173471bf0Spatrick } else if (IDVal == ".nops")
464273471bf0Spatrick return parseDirectiveNops(DirectiveID.getLoc());
464373471bf0Spatrick else if (IDVal == ".even")
464409467b48Spatrick return parseDirectiveEven(DirectiveID.getLoc());
464509467b48Spatrick else if (IDVal == ".cv_fpo_proc")
464609467b48Spatrick return parseDirectiveFPOProc(DirectiveID.getLoc());
464709467b48Spatrick else if (IDVal == ".cv_fpo_setframe")
464809467b48Spatrick return parseDirectiveFPOSetFrame(DirectiveID.getLoc());
464909467b48Spatrick else if (IDVal == ".cv_fpo_pushreg")
465009467b48Spatrick return parseDirectiveFPOPushReg(DirectiveID.getLoc());
465109467b48Spatrick else if (IDVal == ".cv_fpo_stackalloc")
465209467b48Spatrick return parseDirectiveFPOStackAlloc(DirectiveID.getLoc());
465309467b48Spatrick else if (IDVal == ".cv_fpo_stackalign")
465409467b48Spatrick return parseDirectiveFPOStackAlign(DirectiveID.getLoc());
465509467b48Spatrick else if (IDVal == ".cv_fpo_endprologue")
465609467b48Spatrick return parseDirectiveFPOEndPrologue(DirectiveID.getLoc());
465709467b48Spatrick else if (IDVal == ".cv_fpo_endproc")
465809467b48Spatrick return parseDirectiveFPOEndProc(DirectiveID.getLoc());
465973471bf0Spatrick else if (IDVal == ".seh_pushreg" ||
466073471bf0Spatrick (Parser.isParsingMasm() && IDVal.equals_insensitive(".pushreg")))
466109467b48Spatrick return parseDirectiveSEHPushReg(DirectiveID.getLoc());
466273471bf0Spatrick else if (IDVal == ".seh_setframe" ||
466373471bf0Spatrick (Parser.isParsingMasm() && IDVal.equals_insensitive(".setframe")))
466409467b48Spatrick return parseDirectiveSEHSetFrame(DirectiveID.getLoc());
466573471bf0Spatrick else if (IDVal == ".seh_savereg" ||
466673471bf0Spatrick (Parser.isParsingMasm() && IDVal.equals_insensitive(".savereg")))
466709467b48Spatrick return parseDirectiveSEHSaveReg(DirectiveID.getLoc());
466873471bf0Spatrick else if (IDVal == ".seh_savexmm" ||
466973471bf0Spatrick (Parser.isParsingMasm() && IDVal.equals_insensitive(".savexmm128")))
467009467b48Spatrick return parseDirectiveSEHSaveXMM(DirectiveID.getLoc());
467173471bf0Spatrick else if (IDVal == ".seh_pushframe" ||
467273471bf0Spatrick (Parser.isParsingMasm() && IDVal.equals_insensitive(".pushframe")))
467309467b48Spatrick return parseDirectiveSEHPushFrame(DirectiveID.getLoc());
467409467b48Spatrick
467509467b48Spatrick return true;
467609467b48Spatrick }
467709467b48Spatrick
parseDirectiveArch()467873471bf0Spatrick bool X86AsmParser::parseDirectiveArch() {
467973471bf0Spatrick // Ignore .arch for now.
468073471bf0Spatrick getParser().parseStringToEndOfStatement();
468173471bf0Spatrick return false;
468273471bf0Spatrick }
468373471bf0Spatrick
468473471bf0Spatrick /// parseDirectiveNops
468573471bf0Spatrick /// ::= .nops size[, control]
parseDirectiveNops(SMLoc L)468673471bf0Spatrick bool X86AsmParser::parseDirectiveNops(SMLoc L) {
468773471bf0Spatrick int64_t NumBytes = 0, Control = 0;
468873471bf0Spatrick SMLoc NumBytesLoc, ControlLoc;
4689*d415bd75Srobert const MCSubtargetInfo& STI = getSTI();
469073471bf0Spatrick NumBytesLoc = getTok().getLoc();
469173471bf0Spatrick if (getParser().checkForValidSection() ||
469273471bf0Spatrick getParser().parseAbsoluteExpression(NumBytes))
469373471bf0Spatrick return true;
469473471bf0Spatrick
469573471bf0Spatrick if (parseOptionalToken(AsmToken::Comma)) {
469673471bf0Spatrick ControlLoc = getTok().getLoc();
469773471bf0Spatrick if (getParser().parseAbsoluteExpression(Control))
469873471bf0Spatrick return true;
469973471bf0Spatrick }
4700*d415bd75Srobert if (getParser().parseEOL())
470173471bf0Spatrick return true;
470273471bf0Spatrick
470373471bf0Spatrick if (NumBytes <= 0) {
470473471bf0Spatrick Error(NumBytesLoc, "'.nops' directive with non-positive size");
470573471bf0Spatrick return false;
470673471bf0Spatrick }
470773471bf0Spatrick
470873471bf0Spatrick if (Control < 0) {
470973471bf0Spatrick Error(ControlLoc, "'.nops' directive with negative NOP size");
471073471bf0Spatrick return false;
471173471bf0Spatrick }
471273471bf0Spatrick
471373471bf0Spatrick /// Emit nops
4714*d415bd75Srobert getParser().getStreamer().emitNops(NumBytes, Control, L, STI);
471573471bf0Spatrick
471673471bf0Spatrick return false;
471773471bf0Spatrick }
471873471bf0Spatrick
471909467b48Spatrick /// parseDirectiveEven
472009467b48Spatrick /// ::= .even
parseDirectiveEven(SMLoc L)472109467b48Spatrick bool X86AsmParser::parseDirectiveEven(SMLoc L) {
4722*d415bd75Srobert if (parseEOL())
472309467b48Spatrick return false;
472409467b48Spatrick
472509467b48Spatrick const MCSection *Section = getStreamer().getCurrentSectionOnly();
472609467b48Spatrick if (!Section) {
4727*d415bd75Srobert getStreamer().initSections(false, getSTI());
472809467b48Spatrick Section = getStreamer().getCurrentSectionOnly();
472909467b48Spatrick }
4730*d415bd75Srobert if (Section->useCodeAlign())
4731*d415bd75Srobert getStreamer().emitCodeAlignment(Align(2), &getSTI(), 0);
473209467b48Spatrick else
4733*d415bd75Srobert getStreamer().emitValueToAlignment(Align(2), 0, 1, 0);
473409467b48Spatrick return false;
473509467b48Spatrick }
473609467b48Spatrick
473709467b48Spatrick /// ParseDirectiveCode
473809467b48Spatrick /// ::= .code16 | .code32 | .code64
ParseDirectiveCode(StringRef IDVal,SMLoc L)473909467b48Spatrick bool X86AsmParser::ParseDirectiveCode(StringRef IDVal, SMLoc L) {
474009467b48Spatrick MCAsmParser &Parser = getParser();
474109467b48Spatrick Code16GCC = false;
474209467b48Spatrick if (IDVal == ".code16") {
474309467b48Spatrick Parser.Lex();
474409467b48Spatrick if (!is16BitMode()) {
4745*d415bd75Srobert SwitchMode(X86::Is16Bit);
4746097a140dSpatrick getParser().getStreamer().emitAssemblerFlag(MCAF_Code16);
474709467b48Spatrick }
474809467b48Spatrick } else if (IDVal == ".code16gcc") {
474909467b48Spatrick // .code16gcc parses as if in 32-bit mode, but emits code in 16-bit mode.
475009467b48Spatrick Parser.Lex();
475109467b48Spatrick Code16GCC = true;
475209467b48Spatrick if (!is16BitMode()) {
4753*d415bd75Srobert SwitchMode(X86::Is16Bit);
4754097a140dSpatrick getParser().getStreamer().emitAssemblerFlag(MCAF_Code16);
475509467b48Spatrick }
475609467b48Spatrick } else if (IDVal == ".code32") {
475709467b48Spatrick Parser.Lex();
475809467b48Spatrick if (!is32BitMode()) {
4759*d415bd75Srobert SwitchMode(X86::Is32Bit);
4760097a140dSpatrick getParser().getStreamer().emitAssemblerFlag(MCAF_Code32);
476109467b48Spatrick }
476209467b48Spatrick } else if (IDVal == ".code64") {
476309467b48Spatrick Parser.Lex();
476409467b48Spatrick if (!is64BitMode()) {
4765*d415bd75Srobert SwitchMode(X86::Is64Bit);
4766097a140dSpatrick getParser().getStreamer().emitAssemblerFlag(MCAF_Code64);
476709467b48Spatrick }
476809467b48Spatrick } else {
476909467b48Spatrick Error(L, "unknown directive " + IDVal);
477009467b48Spatrick return false;
477109467b48Spatrick }
477209467b48Spatrick
477309467b48Spatrick return false;
477409467b48Spatrick }
477509467b48Spatrick
477609467b48Spatrick // .cv_fpo_proc foo
parseDirectiveFPOProc(SMLoc L)477709467b48Spatrick bool X86AsmParser::parseDirectiveFPOProc(SMLoc L) {
477809467b48Spatrick MCAsmParser &Parser = getParser();
477909467b48Spatrick StringRef ProcName;
478009467b48Spatrick int64_t ParamsSize;
478109467b48Spatrick if (Parser.parseIdentifier(ProcName))
478209467b48Spatrick return Parser.TokError("expected symbol name");
478309467b48Spatrick if (Parser.parseIntToken(ParamsSize, "expected parameter byte count"))
478409467b48Spatrick return true;
478509467b48Spatrick if (!isUIntN(32, ParamsSize))
478609467b48Spatrick return Parser.TokError("parameters size out of range");
478773471bf0Spatrick if (parseEOL())
478873471bf0Spatrick return true;
478909467b48Spatrick MCSymbol *ProcSym = getContext().getOrCreateSymbol(ProcName);
479009467b48Spatrick return getTargetStreamer().emitFPOProc(ProcSym, ParamsSize, L);
479109467b48Spatrick }
479209467b48Spatrick
479309467b48Spatrick // .cv_fpo_setframe ebp
parseDirectiveFPOSetFrame(SMLoc L)479409467b48Spatrick bool X86AsmParser::parseDirectiveFPOSetFrame(SMLoc L) {
4795*d415bd75Srobert MCRegister Reg;
479609467b48Spatrick SMLoc DummyLoc;
4797*d415bd75Srobert if (parseRegister(Reg, DummyLoc, DummyLoc) || parseEOL())
479873471bf0Spatrick return true;
479909467b48Spatrick return getTargetStreamer().emitFPOSetFrame(Reg, L);
480009467b48Spatrick }
480109467b48Spatrick
480209467b48Spatrick // .cv_fpo_pushreg ebx
parseDirectiveFPOPushReg(SMLoc L)480309467b48Spatrick bool X86AsmParser::parseDirectiveFPOPushReg(SMLoc L) {
4804*d415bd75Srobert MCRegister Reg;
480509467b48Spatrick SMLoc DummyLoc;
4806*d415bd75Srobert if (parseRegister(Reg, DummyLoc, DummyLoc) || parseEOL())
480773471bf0Spatrick return true;
480809467b48Spatrick return getTargetStreamer().emitFPOPushReg(Reg, L);
480909467b48Spatrick }
481009467b48Spatrick
481109467b48Spatrick // .cv_fpo_stackalloc 20
parseDirectiveFPOStackAlloc(SMLoc L)481209467b48Spatrick bool X86AsmParser::parseDirectiveFPOStackAlloc(SMLoc L) {
481309467b48Spatrick MCAsmParser &Parser = getParser();
481409467b48Spatrick int64_t Offset;
481573471bf0Spatrick if (Parser.parseIntToken(Offset, "expected offset") || parseEOL())
481673471bf0Spatrick return true;
481709467b48Spatrick return getTargetStreamer().emitFPOStackAlloc(Offset, L);
481809467b48Spatrick }
481909467b48Spatrick
482009467b48Spatrick // .cv_fpo_stackalign 8
parseDirectiveFPOStackAlign(SMLoc L)482109467b48Spatrick bool X86AsmParser::parseDirectiveFPOStackAlign(SMLoc L) {
482209467b48Spatrick MCAsmParser &Parser = getParser();
482309467b48Spatrick int64_t Offset;
482473471bf0Spatrick if (Parser.parseIntToken(Offset, "expected offset") || parseEOL())
482573471bf0Spatrick return true;
482609467b48Spatrick return getTargetStreamer().emitFPOStackAlign(Offset, L);
482709467b48Spatrick }
482809467b48Spatrick
482909467b48Spatrick // .cv_fpo_endprologue
parseDirectiveFPOEndPrologue(SMLoc L)483009467b48Spatrick bool X86AsmParser::parseDirectiveFPOEndPrologue(SMLoc L) {
483109467b48Spatrick MCAsmParser &Parser = getParser();
483273471bf0Spatrick if (Parser.parseEOL())
483373471bf0Spatrick return true;
483409467b48Spatrick return getTargetStreamer().emitFPOEndPrologue(L);
483509467b48Spatrick }
483609467b48Spatrick
483709467b48Spatrick // .cv_fpo_endproc
parseDirectiveFPOEndProc(SMLoc L)483809467b48Spatrick bool X86AsmParser::parseDirectiveFPOEndProc(SMLoc L) {
483909467b48Spatrick MCAsmParser &Parser = getParser();
484073471bf0Spatrick if (Parser.parseEOL())
484173471bf0Spatrick return true;
484209467b48Spatrick return getTargetStreamer().emitFPOEndProc(L);
484309467b48Spatrick }
484409467b48Spatrick
parseSEHRegisterNumber(unsigned RegClassID,MCRegister & RegNo)484509467b48Spatrick bool X86AsmParser::parseSEHRegisterNumber(unsigned RegClassID,
4846*d415bd75Srobert MCRegister &RegNo) {
484709467b48Spatrick SMLoc startLoc = getLexer().getLoc();
484809467b48Spatrick const MCRegisterInfo *MRI = getContext().getRegisterInfo();
484909467b48Spatrick
485009467b48Spatrick // Try parsing the argument as a register first.
485109467b48Spatrick if (getLexer().getTok().isNot(AsmToken::Integer)) {
485209467b48Spatrick SMLoc endLoc;
4853*d415bd75Srobert if (parseRegister(RegNo, startLoc, endLoc))
485409467b48Spatrick return true;
485509467b48Spatrick
485609467b48Spatrick if (!X86MCRegisterClasses[RegClassID].contains(RegNo)) {
485709467b48Spatrick return Error(startLoc,
485809467b48Spatrick "register is not supported for use with this directive");
485909467b48Spatrick }
486009467b48Spatrick } else {
486109467b48Spatrick // Otherwise, an integer number matching the encoding of the desired
486209467b48Spatrick // register may appear.
486309467b48Spatrick int64_t EncodedReg;
486409467b48Spatrick if (getParser().parseAbsoluteExpression(EncodedReg))
486509467b48Spatrick return true;
486609467b48Spatrick
486709467b48Spatrick // The SEH register number is the same as the encoding register number. Map
486809467b48Spatrick // from the encoding back to the LLVM register number.
486909467b48Spatrick RegNo = 0;
487009467b48Spatrick for (MCPhysReg Reg : X86MCRegisterClasses[RegClassID]) {
487109467b48Spatrick if (MRI->getEncodingValue(Reg) == EncodedReg) {
487209467b48Spatrick RegNo = Reg;
487309467b48Spatrick break;
487409467b48Spatrick }
487509467b48Spatrick }
487609467b48Spatrick if (RegNo == 0) {
487709467b48Spatrick return Error(startLoc,
487809467b48Spatrick "incorrect register number for use with this directive");
487909467b48Spatrick }
488009467b48Spatrick }
488109467b48Spatrick
488209467b48Spatrick return false;
488309467b48Spatrick }
488409467b48Spatrick
parseDirectiveSEHPushReg(SMLoc Loc)488509467b48Spatrick bool X86AsmParser::parseDirectiveSEHPushReg(SMLoc Loc) {
4886*d415bd75Srobert MCRegister Reg;
488709467b48Spatrick if (parseSEHRegisterNumber(X86::GR64RegClassID, Reg))
488809467b48Spatrick return true;
488909467b48Spatrick
489009467b48Spatrick if (getLexer().isNot(AsmToken::EndOfStatement))
4891*d415bd75Srobert return TokError("expected end of directive");
489209467b48Spatrick
489309467b48Spatrick getParser().Lex();
4894*d415bd75Srobert getStreamer().emitWinCFIPushReg(Reg, Loc);
489509467b48Spatrick return false;
489609467b48Spatrick }
489709467b48Spatrick
parseDirectiveSEHSetFrame(SMLoc Loc)489809467b48Spatrick bool X86AsmParser::parseDirectiveSEHSetFrame(SMLoc Loc) {
4899*d415bd75Srobert MCRegister Reg;
490009467b48Spatrick int64_t Off;
490109467b48Spatrick if (parseSEHRegisterNumber(X86::GR64RegClassID, Reg))
490209467b48Spatrick return true;
490309467b48Spatrick if (getLexer().isNot(AsmToken::Comma))
490409467b48Spatrick return TokError("you must specify a stack pointer offset");
490509467b48Spatrick
490609467b48Spatrick getParser().Lex();
490709467b48Spatrick if (getParser().parseAbsoluteExpression(Off))
490809467b48Spatrick return true;
490909467b48Spatrick
491009467b48Spatrick if (getLexer().isNot(AsmToken::EndOfStatement))
4911*d415bd75Srobert return TokError("expected end of directive");
491209467b48Spatrick
491309467b48Spatrick getParser().Lex();
4914*d415bd75Srobert getStreamer().emitWinCFISetFrame(Reg, Off, Loc);
491509467b48Spatrick return false;
491609467b48Spatrick }
491709467b48Spatrick
parseDirectiveSEHSaveReg(SMLoc Loc)491809467b48Spatrick bool X86AsmParser::parseDirectiveSEHSaveReg(SMLoc Loc) {
4919*d415bd75Srobert MCRegister Reg;
492009467b48Spatrick int64_t Off;
492109467b48Spatrick if (parseSEHRegisterNumber(X86::GR64RegClassID, Reg))
492209467b48Spatrick return true;
492309467b48Spatrick if (getLexer().isNot(AsmToken::Comma))
492409467b48Spatrick return TokError("you must specify an offset on the stack");
492509467b48Spatrick
492609467b48Spatrick getParser().Lex();
492709467b48Spatrick if (getParser().parseAbsoluteExpression(Off))
492809467b48Spatrick return true;
492909467b48Spatrick
493009467b48Spatrick if (getLexer().isNot(AsmToken::EndOfStatement))
4931*d415bd75Srobert return TokError("expected end of directive");
493209467b48Spatrick
493309467b48Spatrick getParser().Lex();
4934*d415bd75Srobert getStreamer().emitWinCFISaveReg(Reg, Off, Loc);
493509467b48Spatrick return false;
493609467b48Spatrick }
493709467b48Spatrick
parseDirectiveSEHSaveXMM(SMLoc Loc)493809467b48Spatrick bool X86AsmParser::parseDirectiveSEHSaveXMM(SMLoc Loc) {
4939*d415bd75Srobert MCRegister Reg;
494009467b48Spatrick int64_t Off;
494109467b48Spatrick if (parseSEHRegisterNumber(X86::VR128XRegClassID, Reg))
494209467b48Spatrick return true;
494309467b48Spatrick if (getLexer().isNot(AsmToken::Comma))
494409467b48Spatrick return TokError("you must specify an offset on the stack");
494509467b48Spatrick
494609467b48Spatrick getParser().Lex();
494709467b48Spatrick if (getParser().parseAbsoluteExpression(Off))
494809467b48Spatrick return true;
494909467b48Spatrick
495009467b48Spatrick if (getLexer().isNot(AsmToken::EndOfStatement))
4951*d415bd75Srobert return TokError("expected end of directive");
495209467b48Spatrick
495309467b48Spatrick getParser().Lex();
4954*d415bd75Srobert getStreamer().emitWinCFISaveXMM(Reg, Off, Loc);
495509467b48Spatrick return false;
495609467b48Spatrick }
495709467b48Spatrick
parseDirectiveSEHPushFrame(SMLoc Loc)495809467b48Spatrick bool X86AsmParser::parseDirectiveSEHPushFrame(SMLoc Loc) {
495909467b48Spatrick bool Code = false;
496009467b48Spatrick StringRef CodeID;
496109467b48Spatrick if (getLexer().is(AsmToken::At)) {
496209467b48Spatrick SMLoc startLoc = getLexer().getLoc();
496309467b48Spatrick getParser().Lex();
496409467b48Spatrick if (!getParser().parseIdentifier(CodeID)) {
496509467b48Spatrick if (CodeID != "code")
496609467b48Spatrick return Error(startLoc, "expected @code");
496709467b48Spatrick Code = true;
496809467b48Spatrick }
496909467b48Spatrick }
497009467b48Spatrick
497109467b48Spatrick if (getLexer().isNot(AsmToken::EndOfStatement))
4972*d415bd75Srobert return TokError("expected end of directive");
497309467b48Spatrick
497409467b48Spatrick getParser().Lex();
4975*d415bd75Srobert getStreamer().emitWinCFIPushFrame(Code, Loc);
497609467b48Spatrick return false;
497709467b48Spatrick }
497809467b48Spatrick
497909467b48Spatrick // Force static initialization.
LLVMInitializeX86AsmParser()498009467b48Spatrick extern "C" LLVM_EXTERNAL_VISIBILITY void LLVMInitializeX86AsmParser() {
498109467b48Spatrick RegisterMCAsmParser<X86AsmParser> X(getTheX86_32Target());
498209467b48Spatrick RegisterMCAsmParser<X86AsmParser> Y(getTheX86_64Target());
498309467b48Spatrick }
498409467b48Spatrick
498509467b48Spatrick #define GET_REGISTER_MATCHER
498609467b48Spatrick #define GET_MATCHER_IMPLEMENTATION
498709467b48Spatrick #define GET_SUBTARGET_FEATURE_NAME
498809467b48Spatrick #include "X86GenAsmMatcher.inc"
4989