1 //===-- MCAsmParser.cpp - Abstract Asm Parser Interface -------------------===// 2 // 3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4 // See https://llvm.org/LICENSE.txt for license information. 5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6 // 7 //===----------------------------------------------------------------------===// 8 9 #include "llvm/MC/MCParser/MCAsmParser.h" 10 #include "llvm/ADT/StringRef.h" 11 #include "llvm/ADT/Twine.h" 12 #include "llvm/Config/llvm-config.h" 13 #include "llvm/MC/MCParser/MCAsmLexer.h" 14 #include "llvm/MC/MCParser/MCParsedAsmOperand.h" 15 #include "llvm/MC/MCParser/MCTargetAsmParser.h" 16 #include "llvm/Support/CommandLine.h" 17 #include "llvm/Support/Debug.h" 18 #include "llvm/Support/SMLoc.h" 19 #include "llvm/Support/raw_ostream.h" 20 #include <cassert> 21 22 using namespace llvm; 23 24 cl::opt<unsigned> AsmMacroMaxNestingDepth( 25 "asm-macro-max-nesting-depth", cl::init(20), cl::Hidden, 26 cl::desc("The maximum nesting depth allowed for assembly macros.")); 27 28 MCAsmParser::MCAsmParser() = default; 29 30 MCAsmParser::~MCAsmParser() = default; 31 32 void MCAsmParser::setTargetParser(MCTargetAsmParser &P) { 33 assert(!TargetParser && "Target parser is already initialized!"); 34 TargetParser = &P; 35 TargetParser->Initialize(*this); 36 } 37 38 const AsmToken &MCAsmParser::getTok() const { 39 return getLexer().getTok(); 40 } 41 42 bool MCAsmParser::parseTokenLoc(SMLoc &Loc) { 43 Loc = getTok().getLoc(); 44 return false; 45 } 46 47 bool MCAsmParser::parseEOL() { 48 if (getTok().getKind() != AsmToken::EndOfStatement) 49 return Error(getTok().getLoc(), "expected newline"); 50 Lex(); 51 return false; 52 } 53 54 bool MCAsmParser::parseEOL(const Twine &Msg) { 55 if (getTok().getKind() != AsmToken::EndOfStatement) 56 return Error(getTok().getLoc(), Msg); 57 Lex(); 58 return false; 59 } 60 61 bool MCAsmParser::parseToken(AsmToken::TokenKind T, const Twine &Msg) { 62 if (T == AsmToken::EndOfStatement) 63 return parseEOL(Msg); 64 if (getTok().getKind() != T) 65 return Error(getTok().getLoc(), Msg); 66 Lex(); 67 return false; 68 } 69 70 bool MCAsmParser::parseIntToken(int64_t &V, const Twine &Msg) { 71 if (getTok().getKind() != AsmToken::Integer) 72 return TokError(Msg); 73 V = getTok().getIntVal(); 74 Lex(); 75 return false; 76 } 77 78 bool MCAsmParser::parseOptionalToken(AsmToken::TokenKind T) { 79 bool Present = (getTok().getKind() == T); 80 if (Present) 81 parseToken(T); 82 return Present; 83 } 84 85 bool MCAsmParser::check(bool P, const Twine &Msg) { 86 return check(P, getTok().getLoc(), Msg); 87 } 88 89 bool MCAsmParser::check(bool P, SMLoc Loc, const Twine &Msg) { 90 if (P) 91 return Error(Loc, Msg); 92 return false; 93 } 94 95 bool MCAsmParser::TokError(const Twine &Msg, SMRange Range) { 96 return Error(getLexer().getLoc(), Msg, Range); 97 } 98 99 bool MCAsmParser::Error(SMLoc L, const Twine &Msg, SMRange Range) { 100 101 MCPendingError PErr; 102 PErr.Loc = L; 103 Msg.toVector(PErr.Msg); 104 PErr.Range = Range; 105 PendingErrors.push_back(PErr); 106 107 // If we threw this parsing error after a lexing error, this should 108 // supercede the lexing error and so we remove it from the Lexer 109 // before it can propagate 110 if (getTok().is(AsmToken::Error)) 111 getLexer().Lex(); 112 return true; 113 } 114 115 bool MCAsmParser::addErrorSuffix(const Twine &Suffix) { 116 // Make sure lexing errors have propagated to the parser. 117 if (getTok().is(AsmToken::Error)) 118 Lex(); 119 for (auto &PErr : PendingErrors) 120 Suffix.toVector(PErr.Msg); 121 return true; 122 } 123 124 bool MCAsmParser::parseMany(function_ref<bool()> parseOne, bool hasComma) { 125 if (parseOptionalToken(AsmToken::EndOfStatement)) 126 return false; 127 while (true) { 128 if (parseOne()) 129 return true; 130 if (parseOptionalToken(AsmToken::EndOfStatement)) 131 return false; 132 if (hasComma && parseToken(AsmToken::Comma)) 133 return true; 134 } 135 return false; 136 } 137 138 bool MCAsmParser::parseExpression(const MCExpr *&Res) { 139 SMLoc L; 140 return parseExpression(Res, L); 141 } 142 143 bool MCAsmParser::parseGNUAttribute(SMLoc L, int64_t &Tag, 144 int64_t &IntegerValue) { 145 // Parse a .gnu_attribute with numerical tag and value. 146 StringRef S(L.getPointer()); 147 SMLoc TagLoc; 148 TagLoc = getTok().getLoc(); 149 const AsmToken &Tok = getTok(); 150 if (Tok.isNot(AsmToken::Integer)) 151 return false; 152 Tag = Tok.getIntVal(); 153 Lex(); // Eat the Tag 154 Lex(); // Eat the comma 155 if (Tok.isNot(AsmToken::Integer)) 156 return false; 157 IntegerValue = Tok.getIntVal(); 158 Lex(); // Eat the IntegerValue 159 return true; 160 } 161 162 void MCParsedAsmOperand::dump() const { 163 // Cannot completely remove virtual function even in release mode. 164 #if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP) 165 dbgs() << " " << *this; 166 #endif 167 } 168