1 //===- llvm/MC/MCAsmParser.h - Abstract Asm Parser Interface ----*- C++ -*-===//
2 //
3 //                     The LLVM Compiler Infrastructure
4 //
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
7 //
8 //===----------------------------------------------------------------------===//
9 
10 #ifndef LLVM_MC_MCPARSER_MCASMPARSER_H
11 #define LLVM_MC_MCPARSER_MCASMPARSER_H
12 
13 #include "llvm/ADT/None.h"
14 #include "llvm/ADT/STLExtras.h"
15 #include "llvm/ADT/SmallString.h"
16 #include "llvm/ADT/SmallVector.h"
17 #include "llvm/ADT/StringRef.h"
18 #include "llvm/ADT/Twine.h"
19 #include "llvm/MC/MCParser/MCAsmLexer.h"
20 #include "llvm/Support/SMLoc.h"
21 #include <cstdint>
22 #include <string>
23 #include <utility>
24 
25 namespace llvm {
26 
27 class MCAsmInfo;
28 class MCAsmParserExtension;
29 class MCContext;
30 class MCExpr;
31 class MCInstPrinter;
32 class MCInstrInfo;
33 class MCStreamer;
34 class MCTargetAsmParser;
35 class SourceMgr;
36 
37 struct InlineAsmIdentifierInfo {
38   enum IdKind {
39     IK_Invalid,  // Initial state. Unexpected after a successful parsing.
40     IK_Label,    // Function/Label reference.
41     IK_EnumVal,  // Value of enumeration type.
42     IK_Var       // Variable.
43   };
44   // Represents an Enum value
45   struct EnumIdentifier {
46     int64_t EnumVal;
47   };
48   // Represents a label/function reference
49   struct LabelIdentifier {
50     void *Decl;
51   };
52   // Represents a variable
53   struct VariableIdentifier {
54     void *Decl;
55     bool IsGlobalLV;
56     unsigned Length;
57     unsigned Size;
58     unsigned Type;
59   };
60   // An InlineAsm identifier can only be one of those
61   union {
62     EnumIdentifier Enum;
63     LabelIdentifier Label;
64     VariableIdentifier Var;
65   };
isKindInlineAsmIdentifierInfo66   bool isKind(IdKind kind) const { return Kind == kind; }
67   // Initializers
setEnumInlineAsmIdentifierInfo68   void setEnum(int64_t enumVal) {
69     assert(isKind(IK_Invalid) && "should be initialized only once");
70     Kind = IK_EnumVal;
71     Enum.EnumVal = enumVal;
72   }
setLabelInlineAsmIdentifierInfo73   void setLabel(void *decl) {
74     assert(isKind(IK_Invalid) && "should be initialized only once");
75     Kind = IK_Label;
76     Label.Decl = decl;
77   }
setVarInlineAsmIdentifierInfo78   void setVar(void *decl, bool isGlobalLV, unsigned size, unsigned type) {
79     assert(isKind(IK_Invalid) && "should be initialized only once");
80     Kind = IK_Var;
81     Var.Decl = decl;
82     Var.IsGlobalLV = isGlobalLV;
83     Var.Size = size;
84     Var.Type = type;
85     Var.Length = size / type;
86   }
InlineAsmIdentifierInfoInlineAsmIdentifierInfo87   InlineAsmIdentifierInfo() : Kind(IK_Invalid) {}
88 
89 private:
90   // Discriminate using the current kind.
91   IdKind Kind;
92 };
93 
94 /// Generic Sema callback for assembly parser.
95 class MCAsmParserSemaCallback {
96 public:
97   virtual ~MCAsmParserSemaCallback();
98 
99   virtual void LookupInlineAsmIdentifier(StringRef &LineBuf,
100                                          InlineAsmIdentifierInfo &Info,
101                                          bool IsUnevaluatedContext) = 0;
102   virtual StringRef LookupInlineAsmLabel(StringRef Identifier, SourceMgr &SM,
103                                          SMLoc Location, bool Create) = 0;
104   virtual bool LookupInlineAsmField(StringRef Base, StringRef Member,
105                                     unsigned &Offset) = 0;
106 };
107 
108 /// Generic assembler parser interface, for use by target specific
109 /// assembly parsers.
110 class MCAsmParser {
111 public:
112   using DirectiveHandler = bool (*)(MCAsmParserExtension*, StringRef, SMLoc);
113   using ExtensionDirectiveHandler =
114       std::pair<MCAsmParserExtension*, DirectiveHandler>;
115 
116   struct MCPendingError {
117     SMLoc Loc;
118     SmallString<64> Msg;
119     SMRange Range;
120   };
121 
122 private:
123   MCTargetAsmParser *TargetParser = nullptr;
124 
125   unsigned ShowParsedOperands : 1;
126 
127 protected: // Can only create subclasses.
128   MCAsmParser();
129 
130   /// Flag tracking whether any errors have been encountered.
131   bool HadError = false;
132   /// Enable print [latency:throughput] in output file.
133   bool EnablePrintSchedInfo = false;
134 
135   SmallVector<MCPendingError, 1> PendingErrors;
136 
137 public:
138   MCAsmParser(const MCAsmParser &) = delete;
139   MCAsmParser &operator=(const MCAsmParser &) = delete;
140   virtual ~MCAsmParser();
141 
142   virtual void addDirectiveHandler(StringRef Directive,
143                                    ExtensionDirectiveHandler Handler) = 0;
144 
145   virtual void addAliasForDirective(StringRef Directive, StringRef Alias) = 0;
146 
147   virtual SourceMgr &getSourceManager() = 0;
148 
149   virtual MCAsmLexer &getLexer() = 0;
getLexer()150   const MCAsmLexer &getLexer() const {
151     return const_cast<MCAsmParser*>(this)->getLexer();
152   }
153 
154   virtual MCContext &getContext() = 0;
155 
156   /// Return the output streamer for the assembler.
157   virtual MCStreamer &getStreamer() = 0;
158 
getTargetParser()159   MCTargetAsmParser &getTargetParser() const { return *TargetParser; }
160   void setTargetParser(MCTargetAsmParser &P);
161 
getAssemblerDialect()162   virtual unsigned getAssemblerDialect() { return 0;}
setAssemblerDialect(unsigned i)163   virtual void setAssemblerDialect(unsigned i) { }
164 
getShowParsedOperands()165   bool getShowParsedOperands() const { return ShowParsedOperands; }
setShowParsedOperands(bool Value)166   void setShowParsedOperands(bool Value) { ShowParsedOperands = Value; }
167 
setEnablePrintSchedInfo(bool Value)168   void setEnablePrintSchedInfo(bool Value) { EnablePrintSchedInfo = Value; }
shouldPrintSchedInfo()169   bool shouldPrintSchedInfo() { return EnablePrintSchedInfo; }
170 
171   /// Run the parser on the input source buffer.
172   virtual bool Run(bool NoInitialTextSection, bool NoFinalize = false) = 0;
173 
174   virtual void setParsingInlineAsm(bool V) = 0;
175   virtual bool isParsingInlineAsm() = 0;
176 
177   /// Parse MS-style inline assembly.
178   virtual bool parseMSInlineAsm(
179       void *AsmLoc, std::string &AsmString, unsigned &NumOutputs,
180       unsigned &NumInputs, SmallVectorImpl<std::pair<void *, bool>> &OpDecls,
181       SmallVectorImpl<std::string> &Constraints,
182       SmallVectorImpl<std::string> &Clobbers, const MCInstrInfo *MII,
183       const MCInstPrinter *IP, MCAsmParserSemaCallback &SI) = 0;
184 
185   /// Emit a note at the location \p L, with the message \p Msg.
186   virtual void Note(SMLoc L, const Twine &Msg, SMRange Range = None) = 0;
187 
188   /// Emit a warning at the location \p L, with the message \p Msg.
189   ///
190   /// \return The return value is true, if warnings are fatal.
191   virtual bool Warning(SMLoc L, const Twine &Msg, SMRange Range = None) = 0;
192 
193   /// Return an error at the location \p L, with the message \p Msg. This
194   /// may be modified before being emitted.
195   ///
196   /// \return The return value is always true, as an idiomatic convenience to
197   /// clients.
198   bool Error(SMLoc L, const Twine &Msg, SMRange Range = None);
199 
200   /// Emit an error at the location \p L, with the message \p Msg.
201   ///
202   /// \return The return value is always true, as an idiomatic convenience to
203   /// clients.
204   virtual bool printError(SMLoc L, const Twine &Msg, SMRange Range = None) = 0;
205 
hasPendingError()206   bool hasPendingError() { return !PendingErrors.empty(); }
207 
printPendingErrors()208   bool printPendingErrors() {
209     bool rv = !PendingErrors.empty();
210     for (auto Err : PendingErrors) {
211       printError(Err.Loc, Twine(Err.Msg), Err.Range);
212     }
213     PendingErrors.clear();
214     return rv;
215   }
216 
clearPendingErrors()217   void clearPendingErrors() { PendingErrors.clear(); }
218 
219   bool addErrorSuffix(const Twine &Suffix);
220 
221   /// Get the next AsmToken in the stream, possibly handling file
222   /// inclusion first.
223   virtual const AsmToken &Lex() = 0;
224 
225   /// Get the current AsmToken from the stream.
226   const AsmToken &getTok() const;
227 
228   /// Report an error at the current lexer location.
229   bool TokError(const Twine &Msg, SMRange Range = None);
230 
231   bool parseTokenLoc(SMLoc &Loc);
232   bool parseToken(AsmToken::TokenKind T, const Twine &Msg = "unexpected token");
233   /// Attempt to parse and consume token, returning true on
234   /// success.
235   bool parseOptionalToken(AsmToken::TokenKind T);
236 
237   bool parseEOL(const Twine &ErrMsg);
238 
239   bool parseMany(function_ref<bool()> parseOne, bool hasComma = true);
240 
241   bool parseIntToken(int64_t &V, const Twine &ErrMsg);
242 
243   bool check(bool P, const Twine &Msg);
244   bool check(bool P, SMLoc Loc, const Twine &Msg);
245 
246   /// Parse an identifier or string (as a quoted identifier) and set \p
247   /// Res to the identifier contents.
248   virtual bool parseIdentifier(StringRef &Res) = 0;
249 
250   /// Parse up to the end of statement and return the contents from the
251   /// current token until the end of the statement; the current token on exit
252   /// will be either the EndOfStatement or EOF.
253   virtual StringRef parseStringToEndOfStatement() = 0;
254 
255   /// Parse the current token as a string which may include escaped
256   /// characters and return the string contents.
257   virtual bool parseEscapedString(std::string &Data) = 0;
258 
259   /// Skip to the end of the current statement, for error recovery.
260   virtual void eatToEndOfStatement() = 0;
261 
262   /// Parse an arbitrary expression.
263   ///
264   /// \param Res - The value of the expression. The result is undefined
265   /// on error.
266   /// \return - False on success.
267   virtual bool parseExpression(const MCExpr *&Res, SMLoc &EndLoc) = 0;
268   bool parseExpression(const MCExpr *&Res);
269 
270   /// Parse a primary expression.
271   ///
272   /// \param Res - The value of the expression. The result is undefined
273   /// on error.
274   /// \return - False on success.
275   virtual bool parsePrimaryExpr(const MCExpr *&Res, SMLoc &EndLoc) = 0;
276 
277   /// Parse an arbitrary expression, assuming that an initial '(' has
278   /// already been consumed.
279   ///
280   /// \param Res - The value of the expression. The result is undefined
281   /// on error.
282   /// \return - False on success.
283   virtual bool parseParenExpression(const MCExpr *&Res, SMLoc &EndLoc) = 0;
284 
285   /// Parse an expression which must evaluate to an absolute value.
286   ///
287   /// \param Res - The value of the absolute expression. The result is undefined
288   /// on error.
289   /// \return - False on success.
290   virtual bool parseAbsoluteExpression(int64_t &Res) = 0;
291 
292   /// Ensure that we have a valid section set in the streamer. Otherwise,
293   /// report an error and switch to .text.
294   /// \return - False on success.
295   virtual bool checkForValidSection() = 0;
296 
297   /// Parse an arbitrary expression of a specified parenthesis depth,
298   /// assuming that the initial '(' characters have already been consumed.
299   ///
300   /// \param ParenDepth - Specifies how many trailing expressions outside the
301   /// current parentheses we have to parse.
302   /// \param Res - The value of the expression. The result is undefined
303   /// on error.
304   /// \return - False on success.
305   virtual bool parseParenExprOfDepth(unsigned ParenDepth, const MCExpr *&Res,
306                                      SMLoc &EndLoc) = 0;
307 };
308 
309 /// Create an MCAsmParser instance.
310 MCAsmParser *createMCAsmParser(SourceMgr &, MCContext &, MCStreamer &,
311                                const MCAsmInfo &, unsigned CB = 0);
312 
313 } // end namespace llvm
314 
315 #endif // LLVM_MC_MCPARSER_MCASMPARSER_H
316