182 lines · cpp
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-exception6//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/MCAsmInfo.h"14#include "llvm/MC/MCParser/AsmLexer.h"15#include "llvm/MC/MCParser/MCParsedAsmOperand.h"16#include "llvm/MC/MCParser/MCTargetAsmParser.h"17#include "llvm/Support/CommandLine.h"18#include "llvm/Support/Debug.h"19#include "llvm/Support/SMLoc.h"20#include "llvm/Support/raw_ostream.h"21#include <cassert>22 23using namespace llvm;24 25namespace llvm {26cl::opt<unsigned> AsmMacroMaxNestingDepth(27 "asm-macro-max-nesting-depth", cl::init(20), cl::Hidden,28 cl::desc("The maximum nesting depth allowed for assembly macros."));29}30 31MCAsmParser::MCAsmParser(MCContext &Ctx, MCStreamer &Out, SourceMgr &SM,32 const MCAsmInfo &MAI)33 : Ctx(Ctx), Out(Out), SrcMgr(SM), MAI(MAI), Lexer(MAI) {}34 35MCAsmParser::~MCAsmParser() = default;36 37void MCAsmParser::setTargetParser(MCTargetAsmParser &P) {38 assert(!TargetParser && "Target parser is already initialized!");39 TargetParser = &P;40 TargetParser->Initialize(*this);41}42 43const AsmToken &MCAsmParser::getTok() const {44 return getLexer().getTok();45}46 47bool MCAsmParser::parseTokenLoc(SMLoc &Loc) {48 Loc = getTok().getLoc();49 return false;50}51 52bool MCAsmParser::parseEOL() {53 if (getTok().getKind() != AsmToken::EndOfStatement)54 return Error(getTok().getLoc(), "expected newline");55 Lex();56 return false;57}58 59bool MCAsmParser::parseEOL(const Twine &Msg) {60 if (getTok().getKind() != AsmToken::EndOfStatement)61 return Error(getTok().getLoc(), Msg);62 Lex();63 return false;64}65 66bool MCAsmParser::parseToken(AsmToken::TokenKind T, const Twine &Msg) {67 if (T == AsmToken::EndOfStatement)68 return parseEOL(Msg);69 if (getTok().getKind() != T)70 return Error(getTok().getLoc(), Msg);71 Lex();72 return false;73}74 75bool MCAsmParser::parseIntToken(int64_t &V, const Twine &Msg) {76 if (getTok().getKind() != AsmToken::Integer)77 return TokError(Msg);78 V = getTok().getIntVal();79 Lex();80 return false;81}82 83bool MCAsmParser::parseOptionalToken(AsmToken::TokenKind T) {84 bool Present = (getTok().getKind() == T);85 if (Present)86 parseToken(T);87 return Present;88}89 90bool MCAsmParser::check(bool P, const Twine &Msg) {91 return check(P, getTok().getLoc(), Msg);92}93 94bool MCAsmParser::check(bool P, SMLoc Loc, const Twine &Msg) {95 if (P)96 return Error(Loc, Msg);97 return false;98}99 100bool MCAsmParser::TokError(const Twine &Msg, SMRange Range) {101 return Error(getLexer().getLoc(), Msg, Range);102}103 104bool MCAsmParser::Error(SMLoc L, const Twine &Msg, SMRange Range) {105 MCPendingError PErr;106 PErr.Loc = L;107 Msg.toVector(PErr.Msg);108 PErr.Range = Range;109 PendingErrors.push_back(PErr);110 111 // If we threw this parsing error after a lexing error, this should112 // supercede the lexing error and so we remove it from the Lexer113 // before it can propagate114 if (getTok().is(AsmToken::Error))115 getLexer().Lex();116 return true;117}118 119bool MCAsmParser::addErrorSuffix(const Twine &Suffix) {120 // Make sure lexing errors have propagated to the parser.121 if (getTok().is(AsmToken::Error))122 Lex();123 for (auto &PErr : PendingErrors)124 Suffix.toVector(PErr.Msg);125 return true;126}127 128bool MCAsmParser::parseMany(function_ref<bool()> parseOne, bool hasComma) {129 if (parseOptionalToken(AsmToken::EndOfStatement))130 return false;131 while (true) {132 if (parseOne())133 return true;134 if (parseOptionalToken(AsmToken::EndOfStatement))135 return false;136 if (hasComma && parseToken(AsmToken::Comma))137 return true;138 }139 return false;140}141 142bool MCAsmParser::parseExpression(const MCExpr *&Res) {143 SMLoc L;144 return parseExpression(Res, L);145}146 147bool MCAsmParser::parseGNUAttribute(SMLoc L, int64_t &Tag,148 int64_t &IntegerValue) {149 // Parse a .gnu_attribute with numerical tag and value.150 StringRef S(L.getPointer());151 SMLoc TagLoc;152 TagLoc = getTok().getLoc();153 const AsmToken &Tok = getTok();154 if (Tok.isNot(AsmToken::Integer))155 return false;156 Tag = Tok.getIntVal();157 Lex(); // Eat the Tag158 Lex(); // Eat the comma159 if (Tok.isNot(AsmToken::Integer))160 return false;161 IntegerValue = Tok.getIntVal();162 Lex(); // Eat the IntegerValue163 return true;164}165 166bool MCAsmParser::parseSymbol(MCSymbol *&Res) {167 StringRef Name;168 if (parseIdentifier(Name))169 return true;170 171 Res = getContext().parseSymbol(Name);172 return false;173}174 175void MCParsedAsmOperand::dump() const {176 // Cannot completely remove virtual function even in release mode.177#if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)178 dbgs() << " ";179 print(dbgs(), MCAsmInfo());180#endif181}182