10b57cec5SDimitry Andric //===- llvm/MC/MCTargetAsmParser.h - Target Assembly Parser -----*- C++ -*-===// 20b57cec5SDimitry Andric // 30b57cec5SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 40b57cec5SDimitry Andric // See https://llvm.org/LICENSE.txt for license information. 50b57cec5SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 60b57cec5SDimitry Andric // 70b57cec5SDimitry Andric //===----------------------------------------------------------------------===// 80b57cec5SDimitry Andric 90b57cec5SDimitry Andric #ifndef LLVM_MC_MCPARSER_MCTARGETASMPARSER_H 100b57cec5SDimitry Andric #define LLVM_MC_MCPARSER_MCTARGETASMPARSER_H 110b57cec5SDimitry Andric 120b57cec5SDimitry Andric #include "llvm/ADT/StringRef.h" 130b57cec5SDimitry Andric #include "llvm/MC/MCExpr.h" 140b57cec5SDimitry Andric #include "llvm/MC/MCParser/MCAsmParserExtension.h" 1581ad6265SDimitry Andric #include "llvm/MC/MCParser/MCParsedAsmOperand.h" 160b57cec5SDimitry Andric #include "llvm/MC/MCTargetOptions.h" 170b57cec5SDimitry Andric #include "llvm/Support/SMLoc.h" 1806c3fb27SDimitry Andric #include "llvm/TargetParser/SubtargetFeature.h" 190b57cec5SDimitry Andric #include <cstdint> 200b57cec5SDimitry Andric #include <memory> 210b57cec5SDimitry Andric 220b57cec5SDimitry Andric namespace llvm { 230b57cec5SDimitry Andric 2481ad6265SDimitry Andric class MCContext; 250b57cec5SDimitry Andric class MCInst; 2681ad6265SDimitry Andric class MCInstrInfo; 27bdd1243dSDimitry Andric class MCRegister; 280b57cec5SDimitry Andric class MCStreamer; 290b57cec5SDimitry Andric class MCSubtargetInfo; 3081ad6265SDimitry Andric class MCSymbol; 310b57cec5SDimitry Andric template <typename T> class SmallVectorImpl; 320b57cec5SDimitry Andric 330b57cec5SDimitry Andric using OperandVector = SmallVectorImpl<std::unique_ptr<MCParsedAsmOperand>>; 340b57cec5SDimitry Andric 350b57cec5SDimitry Andric enum AsmRewriteKind { 360b57cec5SDimitry Andric AOK_Align, // Rewrite align as .align. 370b57cec5SDimitry Andric AOK_EVEN, // Rewrite even as .even. 380b57cec5SDimitry Andric AOK_Emit, // Rewrite _emit as .byte. 39480093f4SDimitry Andric AOK_CallInput, // Rewrite in terms of ${N:P}. 400b57cec5SDimitry Andric AOK_Input, // Rewrite in terms of $N. 410b57cec5SDimitry Andric AOK_Output, // Rewrite in terms of $N. 420b57cec5SDimitry Andric AOK_SizeDirective, // Add a sizing directive (e.g., dword ptr). 430b57cec5SDimitry Andric AOK_Label, // Rewrite local labels. 440b57cec5SDimitry Andric AOK_EndOfStatement, // Add EndOfStatement (e.g., "\n\t"). 450b57cec5SDimitry Andric AOK_Skip, // Skip emission (e.g., offset/type operators). 460b57cec5SDimitry Andric AOK_IntelExpr // SizeDirective SymDisp [BaseReg + IndexReg * Scale + ImmDisp] 470b57cec5SDimitry Andric }; 480b57cec5SDimitry Andric 490b57cec5SDimitry Andric const char AsmRewritePrecedence [] = { 500b57cec5SDimitry Andric 2, // AOK_Align 510b57cec5SDimitry Andric 2, // AOK_EVEN 520b57cec5SDimitry Andric 2, // AOK_Emit 530b57cec5SDimitry Andric 3, // AOK_Input 54480093f4SDimitry Andric 3, // AOK_CallInput 550b57cec5SDimitry Andric 3, // AOK_Output 560b57cec5SDimitry Andric 5, // AOK_SizeDirective 570b57cec5SDimitry Andric 1, // AOK_Label 580b57cec5SDimitry Andric 5, // AOK_EndOfStatement 590b57cec5SDimitry Andric 2, // AOK_Skip 600b57cec5SDimitry Andric 2 // AOK_IntelExpr 610b57cec5SDimitry Andric }; 620b57cec5SDimitry Andric 6306c3fb27SDimitry Andric // Represent the various parts which make up an intel expression, 640b57cec5SDimitry Andric // used for emitting compound intel expressions 650b57cec5SDimitry Andric struct IntelExpr { 6606c3fb27SDimitry Andric bool NeedBracs = false; 6706c3fb27SDimitry Andric int64_t Imm = 0; 680b57cec5SDimitry Andric StringRef BaseReg; 690b57cec5SDimitry Andric StringRef IndexReg; 70480093f4SDimitry Andric StringRef OffsetName; 7106c3fb27SDimitry Andric unsigned Scale = 1; 720b57cec5SDimitry Andric 7306c3fb27SDimitry Andric IntelExpr() = default; 74480093f4SDimitry Andric // [BaseReg + IndexReg * ScaleExpression + OFFSET name + ImmediateExpression] IntelExprIntelExpr75480093f4SDimitry Andric IntelExpr(StringRef baseReg, StringRef indexReg, unsigned scale, 76480093f4SDimitry Andric StringRef offsetName, int64_t imm, bool needBracs) 77480093f4SDimitry Andric : NeedBracs(needBracs), Imm(imm), BaseReg(baseReg), IndexReg(indexReg), 78480093f4SDimitry Andric OffsetName(offsetName), Scale(1) { 790b57cec5SDimitry Andric if (scale) 800b57cec5SDimitry Andric Scale = scale; 810b57cec5SDimitry Andric } hasBaseRegIntelExpr82480093f4SDimitry Andric bool hasBaseReg() const { return !BaseReg.empty(); } hasIndexRegIntelExpr83480093f4SDimitry Andric bool hasIndexReg() const { return !IndexReg.empty(); } hasRegsIntelExpr84480093f4SDimitry Andric bool hasRegs() const { return hasBaseReg() || hasIndexReg(); } hasOffsetIntelExpr85480093f4SDimitry Andric bool hasOffset() const { return !OffsetName.empty(); } 86480093f4SDimitry Andric // Normally we won't emit immediates unconditionally, 87480093f4SDimitry Andric // unless we've got no other components emitImmIntelExpr88480093f4SDimitry Andric bool emitImm() const { return !(hasRegs() || hasOffset()); } isValidIntelExpr890b57cec5SDimitry Andric bool isValid() const { 900b57cec5SDimitry Andric return (Scale == 1) || 910b57cec5SDimitry Andric (hasIndexReg() && (Scale == 2 || Scale == 4 || Scale == 8)); 920b57cec5SDimitry Andric } 930b57cec5SDimitry Andric }; 940b57cec5SDimitry Andric 950b57cec5SDimitry Andric struct AsmRewrite { 960b57cec5SDimitry Andric AsmRewriteKind Kind; 970b57cec5SDimitry Andric SMLoc Loc; 980b57cec5SDimitry Andric unsigned Len; 99480093f4SDimitry Andric bool Done; 1000b57cec5SDimitry Andric int64_t Val; 1010b57cec5SDimitry Andric StringRef Label; 1020b57cec5SDimitry Andric IntelExpr IntelExp; 10381ad6265SDimitry Andric bool IntelExpRestricted; 1040b57cec5SDimitry Andric 1050b57cec5SDimitry Andric public: 10681ad6265SDimitry Andric AsmRewrite(AsmRewriteKind kind, SMLoc loc, unsigned len = 0, int64_t val = 0, 10781ad6265SDimitry Andric bool Restricted = false) KindAsmRewrite10881ad6265SDimitry Andric : Kind(kind), Loc(loc), Len(len), Done(false), Val(val) { 10981ad6265SDimitry Andric IntelExpRestricted = Restricted; 11081ad6265SDimitry Andric } AsmRewriteAsmRewrite1110b57cec5SDimitry Andric AsmRewrite(AsmRewriteKind kind, SMLoc loc, unsigned len, StringRef label) 1120b57cec5SDimitry Andric : AsmRewrite(kind, loc, len) { Label = label; } AsmRewriteAsmRewrite1130b57cec5SDimitry Andric AsmRewrite(SMLoc loc, unsigned len, IntelExpr exp) 1140b57cec5SDimitry Andric : AsmRewrite(AOK_IntelExpr, loc, len) { IntelExp = exp; } 1150b57cec5SDimitry Andric }; 1160b57cec5SDimitry Andric 1170b57cec5SDimitry Andric struct ParseInstructionInfo { 1180b57cec5SDimitry Andric SmallVectorImpl<AsmRewrite> *AsmRewrites = nullptr; 1190b57cec5SDimitry Andric 1200b57cec5SDimitry Andric ParseInstructionInfo() = default; ParseInstructionInfoParseInstructionInfo1210b57cec5SDimitry Andric ParseInstructionInfo(SmallVectorImpl<AsmRewrite> *rewrites) 1220b57cec5SDimitry Andric : AsmRewrites(rewrites) {} 1230b57cec5SDimitry Andric }; 1240b57cec5SDimitry Andric 1250b57cec5SDimitry Andric enum OperandMatchResultTy { 1260b57cec5SDimitry Andric MatchOperand_Success, // operand matched successfully 1270b57cec5SDimitry Andric MatchOperand_NoMatch, // operand did not match 1280b57cec5SDimitry Andric MatchOperand_ParseFail // operand matched but had errors 1290b57cec5SDimitry Andric }; 1300b57cec5SDimitry Andric 13106c3fb27SDimitry Andric /// Ternary parse status returned by various parse* methods. 13206c3fb27SDimitry Andric class ParseStatus { 13306c3fb27SDimitry Andric enum class StatusTy { Success, Failure, NoMatch } Status; 13406c3fb27SDimitry Andric 13506c3fb27SDimitry Andric public: 13606c3fb27SDimitry Andric #if __cplusplus >= 202002L 13706c3fb27SDimitry Andric using enum StatusTy; 13806c3fb27SDimitry Andric #else 13906c3fb27SDimitry Andric static constexpr StatusTy Success = StatusTy::Success; 14006c3fb27SDimitry Andric static constexpr StatusTy Failure = StatusTy::Failure; 14106c3fb27SDimitry Andric static constexpr StatusTy NoMatch = StatusTy::NoMatch; 14206c3fb27SDimitry Andric #endif 14306c3fb27SDimitry Andric ParseStatus()14406c3fb27SDimitry Andric constexpr ParseStatus() : Status(NoMatch) {} 14506c3fb27SDimitry Andric ParseStatus(StatusTy Status)14606c3fb27SDimitry Andric constexpr ParseStatus(StatusTy Status) : Status(Status) {} 14706c3fb27SDimitry Andric ParseStatus(bool Error)14806c3fb27SDimitry Andric constexpr ParseStatus(bool Error) : Status(Error ? Failure : Success) {} 14906c3fb27SDimitry Andric 15006c3fb27SDimitry Andric template <typename T> constexpr ParseStatus(T) = delete; 15106c3fb27SDimitry Andric isSuccess()15206c3fb27SDimitry Andric constexpr bool isSuccess() const { return Status == StatusTy::Success; } isFailure()15306c3fb27SDimitry Andric constexpr bool isFailure() const { return Status == StatusTy::Failure; } isNoMatch()15406c3fb27SDimitry Andric constexpr bool isNoMatch() const { return Status == StatusTy::NoMatch; } 15506c3fb27SDimitry Andric 15606c3fb27SDimitry Andric // Allow implicit conversions to / from OperandMatchResultTy. 1575f757f3fSDimitry Andric LLVM_DEPRECATED("Migrate to ParseStatus", "") ParseStatus(OperandMatchResultTy R)15806c3fb27SDimitry Andric constexpr ParseStatus(OperandMatchResultTy R) 15906c3fb27SDimitry Andric : Status(R == MatchOperand_Success ? Success 16006c3fb27SDimitry Andric : R == MatchOperand_ParseFail ? Failure 16106c3fb27SDimitry Andric : NoMatch) {} 1625f757f3fSDimitry Andric LLVM_DEPRECATED("Migrate to ParseStatus", "") OperandMatchResultTy()16306c3fb27SDimitry Andric constexpr operator OperandMatchResultTy() const { 16406c3fb27SDimitry Andric return isSuccess() ? MatchOperand_Success 16506c3fb27SDimitry Andric : isFailure() ? MatchOperand_ParseFail 16606c3fb27SDimitry Andric : MatchOperand_NoMatch; 16706c3fb27SDimitry Andric } 16806c3fb27SDimitry Andric }; 16906c3fb27SDimitry Andric 1700b57cec5SDimitry Andric enum class DiagnosticPredicateTy { 1710b57cec5SDimitry Andric Match, 1720b57cec5SDimitry Andric NearMatch, 1730b57cec5SDimitry Andric NoMatch, 1740b57cec5SDimitry Andric }; 1750b57cec5SDimitry Andric 1760b57cec5SDimitry Andric // When an operand is parsed, the assembler will try to iterate through a set of 1770b57cec5SDimitry Andric // possible operand classes that the operand might match and call the 1780b57cec5SDimitry Andric // corresponding PredicateMethod to determine that. 1790b57cec5SDimitry Andric // 1800b57cec5SDimitry Andric // If there are two AsmOperands that would give a specific diagnostic if there 1810b57cec5SDimitry Andric // is no match, there is currently no mechanism to distinguish which operand is 1820b57cec5SDimitry Andric // a closer match. The DiagnosticPredicate distinguishes between 'completely 1830b57cec5SDimitry Andric // no match' and 'near match', so the assembler can decide whether to give a 1840b57cec5SDimitry Andric // specific diagnostic, or use 'InvalidOperand' and continue to find a 1850b57cec5SDimitry Andric // 'better matching' diagnostic. 1860b57cec5SDimitry Andric // 1870b57cec5SDimitry Andric // For example: 1880b57cec5SDimitry Andric // opcode opnd0, onpd1, opnd2 1890b57cec5SDimitry Andric // 1900b57cec5SDimitry Andric // where: 1910b57cec5SDimitry Andric // opnd2 could be an 'immediate of range [-8, 7]' 1920b57cec5SDimitry Andric // opnd2 could be a 'register + shift/extend'. 1930b57cec5SDimitry Andric // 1940b57cec5SDimitry Andric // If opnd2 is a valid register, but with a wrong shift/extend suffix, it makes 1950b57cec5SDimitry Andric // little sense to give a diagnostic that the operand should be an immediate 1960b57cec5SDimitry Andric // in range [-8, 7]. 1970b57cec5SDimitry Andric // 1980b57cec5SDimitry Andric // This is a light-weight alternative to the 'NearMissInfo' approach 1990b57cec5SDimitry Andric // below which collects *all* possible diagnostics. This alternative 2000b57cec5SDimitry Andric // is optional and fully backward compatible with existing 2010b57cec5SDimitry Andric // PredicateMethods that return a 'bool' (match or no match). 2020b57cec5SDimitry Andric struct DiagnosticPredicate { 2030b57cec5SDimitry Andric DiagnosticPredicateTy Type; 2040b57cec5SDimitry Andric DiagnosticPredicateDiagnosticPredicate2050b57cec5SDimitry Andric explicit DiagnosticPredicate(bool Match) 2060b57cec5SDimitry Andric : Type(Match ? DiagnosticPredicateTy::Match 2070b57cec5SDimitry Andric : DiagnosticPredicateTy::NearMatch) {} DiagnosticPredicateDiagnosticPredicate2080b57cec5SDimitry Andric DiagnosticPredicate(DiagnosticPredicateTy T) : Type(T) {} 2090b57cec5SDimitry Andric DiagnosticPredicate(const DiagnosticPredicate &) = default; 210480093f4SDimitry Andric DiagnosticPredicate& operator=(const DiagnosticPredicate &) = default; 2110b57cec5SDimitry Andric 2120b57cec5SDimitry Andric operator bool() const { return Type == DiagnosticPredicateTy::Match; } isMatchDiagnosticPredicate2130b57cec5SDimitry Andric bool isMatch() const { return Type == DiagnosticPredicateTy::Match; } isNearMatchDiagnosticPredicate2140b57cec5SDimitry Andric bool isNearMatch() const { return Type == DiagnosticPredicateTy::NearMatch; } isNoMatchDiagnosticPredicate2150b57cec5SDimitry Andric bool isNoMatch() const { return Type == DiagnosticPredicateTy::NoMatch; } 2160b57cec5SDimitry Andric }; 2170b57cec5SDimitry Andric 2180b57cec5SDimitry Andric // When matching of an assembly instruction fails, there may be multiple 2190b57cec5SDimitry Andric // encodings that are close to being a match. It's often ambiguous which one 2200b57cec5SDimitry Andric // the programmer intended to use, so we want to report an error which mentions 2210b57cec5SDimitry Andric // each of these "near-miss" encodings. This struct contains information about 2220b57cec5SDimitry Andric // one such encoding, and why it did not match the parsed instruction. 2230b57cec5SDimitry Andric class NearMissInfo { 2240b57cec5SDimitry Andric public: 2250b57cec5SDimitry Andric enum NearMissKind { 2260b57cec5SDimitry Andric NoNearMiss, 2270b57cec5SDimitry Andric NearMissOperand, 2280b57cec5SDimitry Andric NearMissFeature, 2290b57cec5SDimitry Andric NearMissPredicate, 2300b57cec5SDimitry Andric NearMissTooFewOperands, 2310b57cec5SDimitry Andric }; 2320b57cec5SDimitry Andric 2330b57cec5SDimitry Andric // The encoding is valid for the parsed assembly string. This is only used 2340b57cec5SDimitry Andric // internally to the table-generated assembly matcher. getSuccess()2350b57cec5SDimitry Andric static NearMissInfo getSuccess() { return NearMissInfo(); } 2360b57cec5SDimitry Andric 2370b57cec5SDimitry Andric // The instruction encoding is not valid because it requires some target 2380b57cec5SDimitry Andric // features that are not currently enabled. MissingFeatures has a bit set for 2390b57cec5SDimitry Andric // each feature that the encoding needs but which is not enabled. getMissedFeature(const FeatureBitset & MissingFeatures)2400b57cec5SDimitry Andric static NearMissInfo getMissedFeature(const FeatureBitset &MissingFeatures) { 2410b57cec5SDimitry Andric NearMissInfo Result; 2420b57cec5SDimitry Andric Result.Kind = NearMissFeature; 2430b57cec5SDimitry Andric Result.Features = MissingFeatures; 2440b57cec5SDimitry Andric return Result; 2450b57cec5SDimitry Andric } 2460b57cec5SDimitry Andric 2470b57cec5SDimitry Andric // The instruction encoding is not valid because the target-specific 2480b57cec5SDimitry Andric // predicate function returned an error code. FailureCode is the 2490b57cec5SDimitry Andric // target-specific error code returned by the predicate. getMissedPredicate(unsigned FailureCode)2500b57cec5SDimitry Andric static NearMissInfo getMissedPredicate(unsigned FailureCode) { 2510b57cec5SDimitry Andric NearMissInfo Result; 2520b57cec5SDimitry Andric Result.Kind = NearMissPredicate; 2530b57cec5SDimitry Andric Result.PredicateError = FailureCode; 2540b57cec5SDimitry Andric return Result; 2550b57cec5SDimitry Andric } 2560b57cec5SDimitry Andric 2570b57cec5SDimitry Andric // The instruction encoding is not valid because one (and only one) parsed 2580b57cec5SDimitry Andric // operand is not of the correct type. OperandError is the error code 2590b57cec5SDimitry Andric // relating to the operand class expected by the encoding. OperandClass is 2600b57cec5SDimitry Andric // the type of the expected operand. Opcode is the opcode of the encoding. 2610b57cec5SDimitry Andric // OperandIndex is the index into the parsed operand list. getMissedOperand(unsigned OperandError,unsigned OperandClass,unsigned Opcode,unsigned OperandIndex)2620b57cec5SDimitry Andric static NearMissInfo getMissedOperand(unsigned OperandError, 2630b57cec5SDimitry Andric unsigned OperandClass, unsigned Opcode, 2640b57cec5SDimitry Andric unsigned OperandIndex) { 2650b57cec5SDimitry Andric NearMissInfo Result; 2660b57cec5SDimitry Andric Result.Kind = NearMissOperand; 2670b57cec5SDimitry Andric Result.MissedOperand.Error = OperandError; 2680b57cec5SDimitry Andric Result.MissedOperand.Class = OperandClass; 2690b57cec5SDimitry Andric Result.MissedOperand.Opcode = Opcode; 2700b57cec5SDimitry Andric Result.MissedOperand.Index = OperandIndex; 2710b57cec5SDimitry Andric return Result; 2720b57cec5SDimitry Andric } 2730b57cec5SDimitry Andric 2740b57cec5SDimitry Andric // The instruction encoding is not valid because it expects more operands 2750b57cec5SDimitry Andric // than were parsed. OperandClass is the class of the expected operand that 2760b57cec5SDimitry Andric // was not provided. Opcode is the instruction encoding. getTooFewOperands(unsigned OperandClass,unsigned Opcode)2770b57cec5SDimitry Andric static NearMissInfo getTooFewOperands(unsigned OperandClass, 2780b57cec5SDimitry Andric unsigned Opcode) { 2790b57cec5SDimitry Andric NearMissInfo Result; 2800b57cec5SDimitry Andric Result.Kind = NearMissTooFewOperands; 2810b57cec5SDimitry Andric Result.TooFewOperands.Class = OperandClass; 2820b57cec5SDimitry Andric Result.TooFewOperands.Opcode = Opcode; 2830b57cec5SDimitry Andric return Result; 2840b57cec5SDimitry Andric } 2850b57cec5SDimitry Andric 2860b57cec5SDimitry Andric operator bool() const { return Kind != NoNearMiss; } 2870b57cec5SDimitry Andric getKind()2880b57cec5SDimitry Andric NearMissKind getKind() const { return Kind; } 2890b57cec5SDimitry Andric 2900b57cec5SDimitry Andric // Feature flags required by the instruction, that the current target does 2910b57cec5SDimitry Andric // not have. getFeatures()2920b57cec5SDimitry Andric const FeatureBitset& getFeatures() const { 2930b57cec5SDimitry Andric assert(Kind == NearMissFeature); 2940b57cec5SDimitry Andric return Features; 2950b57cec5SDimitry Andric } 2960b57cec5SDimitry Andric // Error code returned by the target predicate when validating this 2970b57cec5SDimitry Andric // instruction encoding. getPredicateError()2980b57cec5SDimitry Andric unsigned getPredicateError() const { 2990b57cec5SDimitry Andric assert(Kind == NearMissPredicate); 3000b57cec5SDimitry Andric return PredicateError; 3010b57cec5SDimitry Andric } 3020b57cec5SDimitry Andric // MatchClassKind of the operand that we expected to see. getOperandClass()3030b57cec5SDimitry Andric unsigned getOperandClass() const { 3040b57cec5SDimitry Andric assert(Kind == NearMissOperand || Kind == NearMissTooFewOperands); 3050b57cec5SDimitry Andric return MissedOperand.Class; 3060b57cec5SDimitry Andric } 3070b57cec5SDimitry Andric // Opcode of the encoding we were trying to match. getOpcode()3080b57cec5SDimitry Andric unsigned getOpcode() const { 3090b57cec5SDimitry Andric assert(Kind == NearMissOperand || Kind == NearMissTooFewOperands); 3100b57cec5SDimitry Andric return MissedOperand.Opcode; 3110b57cec5SDimitry Andric } 3120b57cec5SDimitry Andric // Error code returned when validating the operand. getOperandError()3130b57cec5SDimitry Andric unsigned getOperandError() const { 3140b57cec5SDimitry Andric assert(Kind == NearMissOperand); 3150b57cec5SDimitry Andric return MissedOperand.Error; 3160b57cec5SDimitry Andric } 3170b57cec5SDimitry Andric // Index of the actual operand we were trying to match in the list of parsed 3180b57cec5SDimitry Andric // operands. getOperandIndex()3190b57cec5SDimitry Andric unsigned getOperandIndex() const { 3200b57cec5SDimitry Andric assert(Kind == NearMissOperand); 3210b57cec5SDimitry Andric return MissedOperand.Index; 3220b57cec5SDimitry Andric } 3230b57cec5SDimitry Andric 3240b57cec5SDimitry Andric private: 3250b57cec5SDimitry Andric NearMissKind Kind; 3260b57cec5SDimitry Andric 3270b57cec5SDimitry Andric // These two structs share a common prefix, so we can safely rely on the fact 3280b57cec5SDimitry Andric // that they overlap in the union. 3290b57cec5SDimitry Andric struct MissedOpInfo { 3300b57cec5SDimitry Andric unsigned Class; 3310b57cec5SDimitry Andric unsigned Opcode; 3320b57cec5SDimitry Andric unsigned Error; 3330b57cec5SDimitry Andric unsigned Index; 3340b57cec5SDimitry Andric }; 3350b57cec5SDimitry Andric 3360b57cec5SDimitry Andric struct TooFewOperandsInfo { 3370b57cec5SDimitry Andric unsigned Class; 3380b57cec5SDimitry Andric unsigned Opcode; 3390b57cec5SDimitry Andric }; 3400b57cec5SDimitry Andric 3410b57cec5SDimitry Andric union { 3420b57cec5SDimitry Andric FeatureBitset Features; 3430b57cec5SDimitry Andric unsigned PredicateError; 3440b57cec5SDimitry Andric MissedOpInfo MissedOperand; 3450b57cec5SDimitry Andric TooFewOperandsInfo TooFewOperands; 3460b57cec5SDimitry Andric }; 3470b57cec5SDimitry Andric NearMissInfo()3480b57cec5SDimitry Andric NearMissInfo() : Kind(NoNearMiss) {} 3490b57cec5SDimitry Andric }; 3500b57cec5SDimitry Andric 3510b57cec5SDimitry Andric /// MCTargetAsmParser - Generic interface to target specific assembly parsers. 3520b57cec5SDimitry Andric class MCTargetAsmParser : public MCAsmParserExtension { 3530b57cec5SDimitry Andric public: 3540b57cec5SDimitry Andric enum MatchResultTy { 3550b57cec5SDimitry Andric Match_InvalidOperand, 3560b57cec5SDimitry Andric Match_InvalidTiedOperand, 3570b57cec5SDimitry Andric Match_MissingFeature, 3580b57cec5SDimitry Andric Match_MnemonicFail, 3590b57cec5SDimitry Andric Match_Success, 3600b57cec5SDimitry Andric Match_NearMisses, 3610b57cec5SDimitry Andric FIRST_TARGET_MATCH_RESULT_TY 3620b57cec5SDimitry Andric }; 3630b57cec5SDimitry Andric 3640b57cec5SDimitry Andric protected: // Can only create subclasses. 3650b57cec5SDimitry Andric MCTargetAsmParser(MCTargetOptions const &, const MCSubtargetInfo &STI, 3660b57cec5SDimitry Andric const MCInstrInfo &MII); 3670b57cec5SDimitry Andric 3680b57cec5SDimitry Andric /// Create a copy of STI and return a non-const reference to it. 3690b57cec5SDimitry Andric MCSubtargetInfo ©STI(); 3700b57cec5SDimitry Andric 3710b57cec5SDimitry Andric /// AvailableFeatures - The current set of available features. 3720b57cec5SDimitry Andric FeatureBitset AvailableFeatures; 3730b57cec5SDimitry Andric 3745ffd83dbSDimitry Andric /// ParsingMSInlineAsm - Are we parsing ms-style inline assembly? 3755ffd83dbSDimitry Andric bool ParsingMSInlineAsm = false; 3760b57cec5SDimitry Andric 3770b57cec5SDimitry Andric /// SemaCallback - The Sema callback implementation. Must be set when parsing 3780b57cec5SDimitry Andric /// ms-style inline assembly. 3795ffd83dbSDimitry Andric MCAsmParserSemaCallback *SemaCallback = nullptr; 3800b57cec5SDimitry Andric 3810b57cec5SDimitry Andric /// Set of options which affects instrumentation of inline assembly. 3820b57cec5SDimitry Andric MCTargetOptions MCOptions; 3830b57cec5SDimitry Andric 3840b57cec5SDimitry Andric /// Current STI. 3850b57cec5SDimitry Andric const MCSubtargetInfo *STI; 3860b57cec5SDimitry Andric 3870b57cec5SDimitry Andric const MCInstrInfo &MII; 3880b57cec5SDimitry Andric 3890b57cec5SDimitry Andric public: 3900b57cec5SDimitry Andric MCTargetAsmParser(const MCTargetAsmParser &) = delete; 3910b57cec5SDimitry Andric MCTargetAsmParser &operator=(const MCTargetAsmParser &) = delete; 3920b57cec5SDimitry Andric 3930b57cec5SDimitry Andric ~MCTargetAsmParser() override; 3940b57cec5SDimitry Andric 3950b57cec5SDimitry Andric const MCSubtargetInfo &getSTI() const; 3960b57cec5SDimitry Andric getAvailableFeatures()3970b57cec5SDimitry Andric const FeatureBitset& getAvailableFeatures() const { 3980b57cec5SDimitry Andric return AvailableFeatures; 3990b57cec5SDimitry Andric } setAvailableFeatures(const FeatureBitset & Value)4000b57cec5SDimitry Andric void setAvailableFeatures(const FeatureBitset& Value) { 4010b57cec5SDimitry Andric AvailableFeatures = Value; 4020b57cec5SDimitry Andric } 4030b57cec5SDimitry Andric isParsingMSInlineAsm()4045ffd83dbSDimitry Andric bool isParsingMSInlineAsm () { return ParsingMSInlineAsm; } setParsingMSInlineAsm(bool Value)4055ffd83dbSDimitry Andric void setParsingMSInlineAsm (bool Value) { ParsingMSInlineAsm = Value; } 4060b57cec5SDimitry Andric getTargetOptions()4070b57cec5SDimitry Andric MCTargetOptions getTargetOptions() const { return MCOptions; } 4080b57cec5SDimitry Andric setSemaCallback(MCAsmParserSemaCallback * Callback)4090b57cec5SDimitry Andric void setSemaCallback(MCAsmParserSemaCallback *Callback) { 4100b57cec5SDimitry Andric SemaCallback = Callback; 4110b57cec5SDimitry Andric } 4120b57cec5SDimitry Andric 4130b57cec5SDimitry Andric // Target-specific parsing of expression. parsePrimaryExpr(const MCExpr * & Res,SMLoc & EndLoc)4140b57cec5SDimitry Andric virtual bool parsePrimaryExpr(const MCExpr *&Res, SMLoc &EndLoc) { 415e8d8bef9SDimitry Andric return getParser().parsePrimaryExpr(Res, EndLoc, nullptr); 4160b57cec5SDimitry Andric } 4170b57cec5SDimitry Andric 418bdd1243dSDimitry Andric virtual bool parseRegister(MCRegister &Reg, SMLoc &StartLoc, 4190b57cec5SDimitry Andric SMLoc &EndLoc) = 0; 4200b57cec5SDimitry Andric 4215ffd83dbSDimitry Andric /// tryParseRegister - parse one register if possible 4225ffd83dbSDimitry Andric /// 4235ffd83dbSDimitry Andric /// Check whether a register specification can be parsed at the current 4245ffd83dbSDimitry Andric /// location, without failing the entire parse if it can't. Must not consume 4255ffd83dbSDimitry Andric /// tokens if the parse fails. 4265f757f3fSDimitry Andric virtual ParseStatus tryParseRegister(MCRegister &Reg, SMLoc &StartLoc, 4275f757f3fSDimitry Andric SMLoc &EndLoc) = 0; 4285ffd83dbSDimitry Andric 4290b57cec5SDimitry Andric /// ParseInstruction - Parse one assembly instruction. 4300b57cec5SDimitry Andric /// 4310b57cec5SDimitry Andric /// The parser is positioned following the instruction name. The target 4320b57cec5SDimitry Andric /// specific instruction parser should parse the entire instruction and 4330b57cec5SDimitry Andric /// construct the appropriate MCInst, or emit an error. On success, the entire 4340b57cec5SDimitry Andric /// line should be parsed up to and including the end-of-statement token. On 4350b57cec5SDimitry Andric /// failure, the parser is not required to read to the end of the line. 4360b57cec5SDimitry Andric // 4370b57cec5SDimitry Andric /// \param Name - The instruction name. 4380b57cec5SDimitry Andric /// \param NameLoc - The source location of the name. 4390b57cec5SDimitry Andric /// \param Operands [out] - The list of parsed operands, this returns 4400b57cec5SDimitry Andric /// ownership of them to the caller. 4410b57cec5SDimitry Andric /// \return True on failure. 4420b57cec5SDimitry Andric virtual bool ParseInstruction(ParseInstructionInfo &Info, StringRef Name, 4430b57cec5SDimitry Andric SMLoc NameLoc, OperandVector &Operands) = 0; ParseInstruction(ParseInstructionInfo & Info,StringRef Name,AsmToken Token,OperandVector & Operands)4440b57cec5SDimitry Andric virtual bool ParseInstruction(ParseInstructionInfo &Info, StringRef Name, 4450b57cec5SDimitry Andric AsmToken Token, OperandVector &Operands) { 4460b57cec5SDimitry Andric return ParseInstruction(Info, Name, Token.getLoc(), Operands); 4470b57cec5SDimitry Andric } 4480b57cec5SDimitry Andric 4490b57cec5SDimitry Andric /// ParseDirective - Parse a target specific assembler directive 45006c3fb27SDimitry Andric /// This method is deprecated, use 'parseDirective' instead. 4510b57cec5SDimitry Andric /// 4520b57cec5SDimitry Andric /// The parser is positioned following the directive name. The target 4530b57cec5SDimitry Andric /// specific directive parser should parse the entire directive doing or 4540b57cec5SDimitry Andric /// recording any target specific work, or return true and do nothing if the 4550b57cec5SDimitry Andric /// directive is not target specific. If the directive is specific for 4560b57cec5SDimitry Andric /// the target, the entire line is parsed up to and including the 4570b57cec5SDimitry Andric /// end-of-statement token and false is returned. 4580b57cec5SDimitry Andric /// 4590b57cec5SDimitry Andric /// \param DirectiveID - the identifier token of the directive. ParseDirective(AsmToken DirectiveID)46006c3fb27SDimitry Andric virtual bool ParseDirective(AsmToken DirectiveID) { return true; } 46106c3fb27SDimitry Andric 46206c3fb27SDimitry Andric /// Parses a target-specific assembler directive. 46306c3fb27SDimitry Andric /// 46406c3fb27SDimitry Andric /// The parser is positioned following the directive name. The target-specific 46506c3fb27SDimitry Andric /// directive parser should parse the entire directive doing or recording any 46606c3fb27SDimitry Andric /// target-specific work, or emit an error. On success, the entire line should 46706c3fb27SDimitry Andric /// be parsed up to and including the end-of-statement token. On failure, the 46806c3fb27SDimitry Andric /// parser is not required to read to the end of the line. If the directive is 46906c3fb27SDimitry Andric /// not target-specific, no tokens should be consumed and NoMatch is returned. 47006c3fb27SDimitry Andric /// 47106c3fb27SDimitry Andric /// \param DirectiveID - The token identifying the directive. 47206c3fb27SDimitry Andric virtual ParseStatus parseDirective(AsmToken DirectiveID); 4730b57cec5SDimitry Andric 4740b57cec5SDimitry Andric /// MatchAndEmitInstruction - Recognize a series of operands of a parsed 4750b57cec5SDimitry Andric /// instruction as an actual MCInst and emit it to the specified MCStreamer. 4760b57cec5SDimitry Andric /// This returns false on success and returns true on failure to match. 4770b57cec5SDimitry Andric /// 4780b57cec5SDimitry Andric /// On failure, the target parser is responsible for emitting a diagnostic 4790b57cec5SDimitry Andric /// explaining the match failure. 4800b57cec5SDimitry Andric virtual bool MatchAndEmitInstruction(SMLoc IDLoc, unsigned &Opcode, 4810b57cec5SDimitry Andric OperandVector &Operands, MCStreamer &Out, 4820b57cec5SDimitry Andric uint64_t &ErrorInfo, 4830b57cec5SDimitry Andric bool MatchingInlineAsm) = 0; 4840b57cec5SDimitry Andric 4850b57cec5SDimitry Andric /// Allows targets to let registers opt out of clobber lists. OmitRegisterFromClobberLists(unsigned RegNo)4860b57cec5SDimitry Andric virtual bool OmitRegisterFromClobberLists(unsigned RegNo) { return false; } 4870b57cec5SDimitry Andric 4880b57cec5SDimitry Andric /// Allow a target to add special case operand matching for things that 4890b57cec5SDimitry Andric /// tblgen doesn't/can't handle effectively. For example, literal 4900b57cec5SDimitry Andric /// immediates on ARM. TableGen expects a token operand, but the parser 4910b57cec5SDimitry Andric /// will recognize them as immediates. validateTargetOperandClass(MCParsedAsmOperand & Op,unsigned Kind)4920b57cec5SDimitry Andric virtual unsigned validateTargetOperandClass(MCParsedAsmOperand &Op, 4930b57cec5SDimitry Andric unsigned Kind) { 4940b57cec5SDimitry Andric return Match_InvalidOperand; 4950b57cec5SDimitry Andric } 4960b57cec5SDimitry Andric 4970b57cec5SDimitry Andric /// Validate the instruction match against any complex target predicates 4980b57cec5SDimitry Andric /// before rendering any operands to it. 4990b57cec5SDimitry Andric virtual unsigned checkEarlyTargetMatchPredicate(MCInst & Inst,const OperandVector & Operands)5000b57cec5SDimitry Andric checkEarlyTargetMatchPredicate(MCInst &Inst, const OperandVector &Operands) { 5010b57cec5SDimitry Andric return Match_Success; 5020b57cec5SDimitry Andric } 5030b57cec5SDimitry Andric 5040b57cec5SDimitry Andric /// checkTargetMatchPredicate - Validate the instruction match against 5050b57cec5SDimitry Andric /// any complex target predicates not expressible via match classes. checkTargetMatchPredicate(MCInst & Inst)5060b57cec5SDimitry Andric virtual unsigned checkTargetMatchPredicate(MCInst &Inst) { 5070b57cec5SDimitry Andric return Match_Success; 5080b57cec5SDimitry Andric } 5090b57cec5SDimitry Andric 5100b57cec5SDimitry Andric virtual void convertToMapAndConstraints(unsigned Kind, 5110b57cec5SDimitry Andric const OperandVector &Operands) = 0; 5120b57cec5SDimitry Andric 513bdd1243dSDimitry Andric /// Returns whether two operands are registers and are equal. This is used 514bdd1243dSDimitry Andric /// by the tied-operands checks in the AsmMatcher. This method can be 515bdd1243dSDimitry Andric /// overridden to allow e.g. a sub- or super-register as the tied operand. areEqualRegs(const MCParsedAsmOperand & Op1,const MCParsedAsmOperand & Op2)516bdd1243dSDimitry Andric virtual bool areEqualRegs(const MCParsedAsmOperand &Op1, 5170b57cec5SDimitry Andric const MCParsedAsmOperand &Op2) const { 518bdd1243dSDimitry Andric return Op1.isReg() && Op2.isReg() && Op1.getReg() == Op2.getReg(); 5190b57cec5SDimitry Andric } 5200b57cec5SDimitry Andric 5210b57cec5SDimitry Andric // Return whether this parser uses assignment statements with equals tokens equalIsAsmAssignment()5220b57cec5SDimitry Andric virtual bool equalIsAsmAssignment() { return true; }; 5230b57cec5SDimitry Andric // Return whether this start of statement identifier is a label isLabel(AsmToken & Token)5240b57cec5SDimitry Andric virtual bool isLabel(AsmToken &Token) { return true; }; 5250b57cec5SDimitry Andric // Return whether this parser accept star as start of statement starIsStartOfStatement()5260b57cec5SDimitry Andric virtual bool starIsStartOfStatement() { return false; }; 5270b57cec5SDimitry Andric applyModifierToExpr(const MCExpr * E,MCSymbolRefExpr::VariantKind,MCContext & Ctx)5280b57cec5SDimitry Andric virtual const MCExpr *applyModifierToExpr(const MCExpr *E, 5290b57cec5SDimitry Andric MCSymbolRefExpr::VariantKind, 5300b57cec5SDimitry Andric MCContext &Ctx) { 5310b57cec5SDimitry Andric return nullptr; 5320b57cec5SDimitry Andric } 5330b57cec5SDimitry Andric 5340b57cec5SDimitry Andric // For actions that have to be performed before a label is emitted doBeforeLabelEmit(MCSymbol * Symbol,SMLoc IDLoc)535bdd1243dSDimitry Andric virtual void doBeforeLabelEmit(MCSymbol *Symbol, SMLoc IDLoc) {} 5360b57cec5SDimitry Andric onLabelParsed(MCSymbol * Symbol)5370b57cec5SDimitry Andric virtual void onLabelParsed(MCSymbol *Symbol) {} 5380b57cec5SDimitry Andric 5390b57cec5SDimitry Andric /// Ensure that all previously parsed instructions have been emitted to the 5400b57cec5SDimitry Andric /// output streamer, if the target does not emit them immediately. flushPendingInstructions(MCStreamer & Out)5410b57cec5SDimitry Andric virtual void flushPendingInstructions(MCStreamer &Out) {} 5420b57cec5SDimitry Andric createTargetUnaryExpr(const MCExpr * E,AsmToken::TokenKind OperatorToken,MCContext & Ctx)5430b57cec5SDimitry Andric virtual const MCExpr *createTargetUnaryExpr(const MCExpr *E, 5440b57cec5SDimitry Andric AsmToken::TokenKind OperatorToken, 5450b57cec5SDimitry Andric MCContext &Ctx) { 5460b57cec5SDimitry Andric return nullptr; 5470b57cec5SDimitry Andric } 5480b57cec5SDimitry Andric 549fe6060f1SDimitry Andric // For any initialization at the beginning of parsing. onBeginOfFile()550fe6060f1SDimitry Andric virtual void onBeginOfFile() {} 551fe6060f1SDimitry Andric 5520b57cec5SDimitry Andric // For any checks or cleanups at the end of parsing. onEndOfFile()5530b57cec5SDimitry Andric virtual void onEndOfFile() {} 5540b57cec5SDimitry Andric }; 5550b57cec5SDimitry Andric 5560b57cec5SDimitry Andric } // end namespace llvm 5570b57cec5SDimitry Andric 5580b57cec5SDimitry Andric #endif // LLVM_MC_MCPARSER_MCTARGETASMPARSER_H 559