blob: 0406ff8d446c878afae33460eaaf61aededc3a13 [file] [log] [blame]
Chris Lattner27aa7d22009-06-21 20:16:42 +00001//===- AsmParser.cpp - Parser for Assembly Files --------------------------===//
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// This class implements the parser for assembly files.
11//
12//===----------------------------------------------------------------------===//
13
Daniel Dunbarb95a0792010-09-24 01:59:56 +000014#include "llvm/ADT/APFloat.h"
Daniel Dunbar7c0a3342009-08-26 22:49:51 +000015#include "llvm/ADT/SmallString.h"
Daniel Dunbaraef87e32010-07-18 18:31:38 +000016#include "llvm/ADT/StringMap.h"
Daniel Dunbarf9507ff2009-07-27 23:20:52 +000017#include "llvm/ADT/Twine.h"
Daniel Dunbaraef87e32010-07-18 18:31:38 +000018#include "llvm/MC/MCAsmInfo.h"
Daniel Dunbarecc63f82009-06-23 22:01:43 +000019#include "llvm/MC/MCContext.h"
Evan Cheng94b95502011-07-26 00:24:13 +000020#include "llvm/MC/MCDwarf.h"
Daniel Dunbar28c251b2009-08-31 08:06:59 +000021#include "llvm/MC/MCExpr.h"
Daniel Dunbaraef87e32010-07-18 18:31:38 +000022#include "llvm/MC/MCParser/AsmCond.h"
23#include "llvm/MC/MCParser/AsmLexer.h"
24#include "llvm/MC/MCParser/MCAsmParser.h"
25#include "llvm/MC/MCParser/MCParsedAsmOperand.h"
Evan Chenge76a33b2011-07-20 05:58:47 +000026#include "llvm/MC/MCRegisterInfo.h"
Daniel Dunbaraef87e32010-07-18 18:31:38 +000027#include "llvm/MC/MCSectionMachO.h"
Daniel Dunbarecc63f82009-06-23 22:01:43 +000028#include "llvm/MC/MCStreamer.h"
Daniel Dunbardce0f3c2009-06-29 23:43:14 +000029#include "llvm/MC/MCSymbol.h"
Evan Cheng94b95502011-07-26 00:24:13 +000030#include "llvm/MC/MCTargetAsmParser.h"
Joerg Sonnenbergerf8cd7082011-05-19 18:00:13 +000031#include "llvm/Support/CommandLine.h"
Benjamin Kramer518ff562012-01-28 15:28:41 +000032#include "llvm/Support/ErrorHandling.h"
Jim Grosbach254cf032011-06-29 16:05:14 +000033#include "llvm/Support/MathExtras.h"
Kevin Enderbyf187ac52010-06-28 21:45:58 +000034#include "llvm/Support/MemoryBuffer.h"
Daniel Dunbaraef87e32010-07-18 18:31:38 +000035#include "llvm/Support/SourceMgr.h"
Chris Lattnerb0789ed2009-06-21 20:54:55 +000036#include "llvm/Support/raw_ostream.h"
Nick Lewycky476b2422010-12-19 20:43:38 +000037#include <cctype>
Daniel Dunbaraef87e32010-07-18 18:31:38 +000038#include <vector>
Chris Lattner27aa7d22009-06-21 20:16:42 +000039using namespace llvm;
40
Joerg Sonnenbergerf8cd7082011-05-19 18:00:13 +000041static cl::opt<bool>
42FatalAssemblerWarnings("fatal-assembler-warnings",
43 cl::desc("Consider warnings as error"));
44
Daniel Dunbar81ea00f2010-07-12 17:54:38 +000045namespace {
46
Daniel Dunbar6d8cf082010-07-18 18:47:21 +000047/// \brief Helper class for tracking macro definitions.
Rafael Espindola28c1f6662012-06-03 22:41:23 +000048typedef std::vector<AsmToken> MacroArgument;
Rafael Espindola8a403d32012-08-08 14:51:03 +000049typedef std::vector<MacroArgument> MacroArguments;
Preston Gurd6c9176a2012-09-19 20:29:04 +000050typedef std::pair<StringRef, MacroArgument> MacroParameter;
Rafael Espindola8a403d32012-08-08 14:51:03 +000051typedef std::vector<MacroParameter> MacroParameters;
Rafael Espindola28c1f6662012-06-03 22:41:23 +000052
Daniel Dunbar6d8cf082010-07-18 18:47:21 +000053struct Macro {
54 StringRef Name;
55 StringRef Body;
Rafael Espindola8a403d32012-08-08 14:51:03 +000056 MacroParameters Parameters;
Daniel Dunbar6d8cf082010-07-18 18:47:21 +000057
58public:
Rafael Espindola8a403d32012-08-08 14:51:03 +000059 Macro(StringRef N, StringRef B, const MacroParameters &P) :
Rafael Espindola65366442011-06-05 02:43:45 +000060 Name(N), Body(B), Parameters(P) {}
Daniel Dunbar6d8cf082010-07-18 18:47:21 +000061};
62
Daniel Dunbarc64a0d72010-07-18 18:54:11 +000063/// \brief Helper class for storing information about an active macro
64/// instantiation.
65struct MacroInstantiation {
66 /// The macro being instantiated.
67 const Macro *TheMacro;
68
69 /// The macro instantiation with substitutions.
70 MemoryBuffer *Instantiation;
71
72 /// The location of the instantiation.
73 SMLoc InstantiationLoc;
74
75 /// The location where parsing should resume upon instantiation completion.
76 SMLoc ExitLoc;
77
78public:
Daniel Dunbar7a570d02010-07-18 19:00:10 +000079 MacroInstantiation(const Macro *M, SMLoc IL, SMLoc EL,
Rafael Espindola65366442011-06-05 02:43:45 +000080 MemoryBuffer *I);
Daniel Dunbarc64a0d72010-07-18 18:54:11 +000081};
82
Daniel Dunbaraef87e32010-07-18 18:31:38 +000083/// \brief The concrete assembly parser instance.
84class AsmParser : public MCAsmParser {
Daniel Dunbar3c802de2010-07-18 18:38:02 +000085 friend class GenericAsmParser;
86
Craig Topper85aadc02012-09-15 16:23:52 +000087 AsmParser(const AsmParser &) LLVM_DELETED_FUNCTION;
88 void operator=(const AsmParser &) LLVM_DELETED_FUNCTION;
Daniel Dunbaraef87e32010-07-18 18:31:38 +000089private:
90 AsmLexer Lexer;
91 MCContext &Ctx;
92 MCStreamer &Out;
Jim Grosbache82b8ee2011-06-15 18:33:28 +000093 const MCAsmInfo &MAI;
Daniel Dunbaraef87e32010-07-18 18:31:38 +000094 SourceMgr &SrcMgr;
Benjamin Kramer04a04262011-10-16 10:48:29 +000095 SourceMgr::DiagHandlerTy SavedDiagHandler;
96 void *SavedDiagContext;
Daniel Dunbaraef87e32010-07-18 18:31:38 +000097 MCAsmParserExtension *GenericParser;
98 MCAsmParserExtension *PlatformParser;
Rafael Espindolaa61842b2011-04-11 21:49:50 +000099
Daniel Dunbaraef87e32010-07-18 18:31:38 +0000100 /// This is the current buffer index we're lexing from as managed by the
101 /// SourceMgr object.
102 int CurBuffer;
103
104 AsmCond TheCondState;
105 std::vector<AsmCond> TheCondStack;
106
107 /// DirectiveMap - This is a table handlers for directives. Each handler is
108 /// invoked after the directive identifier is read and is responsible for
109 /// parsing and validating the rest of the directive. The handler is passed
110 /// in the directive name and the location of the directive keyword.
111 StringMap<std::pair<MCAsmParserExtension*, DirectiveHandler> > DirectiveMap;
Daniel Dunbar3c802de2010-07-18 18:38:02 +0000112
Daniel Dunbar6d8cf082010-07-18 18:47:21 +0000113 /// MacroMap - Map of currently defined macros.
114 StringMap<Macro*> MacroMap;
115
Daniel Dunbarc64a0d72010-07-18 18:54:11 +0000116 /// ActiveMacros - Stack of active macro instantiations.
117 std::vector<MacroInstantiation*> ActiveMacros;
118
Daniel Dunbar3c802de2010-07-18 18:38:02 +0000119 /// Boolean tracking whether macro substitution is enabled.
120 unsigned MacrosEnabled : 1;
121
Daniel Dunbar93bd4d12010-09-09 22:42:56 +0000122 /// Flag tracking whether any errors have been encountered.
123 unsigned HadError : 1;
124
Kevin Enderbyacbaecd2011-10-12 21:38:39 +0000125 /// The values from the last parsed cpp hash file line comment if any.
126 StringRef CppHashFilename;
127 int64_t CppHashLineNumber;
128 SMLoc CppHashLoc;
129
Devang Patel0db58bf2012-01-31 18:14:05 +0000130 /// AssemblerDialect. ~OU means unset value and use value provided by MAI.
131 unsigned AssemblerDialect;
132
Preston Gurd7b6f2032012-09-19 20:36:12 +0000133 /// IsDarwin - is Darwin compatibility enabled?
134 bool IsDarwin;
135
Chad Rosier8f138d12012-10-15 17:19:13 +0000136 /// ParsingInlineAsm - Are we parsing ms-style inline assembly?
Chad Rosier84125ca2012-10-13 00:26:04 +0000137 bool ParsingInlineAsm;
138
Chad Rosier8f138d12012-10-15 17:19:13 +0000139 /// ParsedOperands - The parsed operands from the last parsed statement.
140 SmallVector<MCParsedAsmOperand*, 8> ParsedOperands;
141
142 /// Opcode - The opcode from the last parsed instruction.
143 unsigned Opcode;
144
Daniel Dunbaraef87e32010-07-18 18:31:38 +0000145public:
Jim Grosbach1b84cce2011-08-16 18:33:49 +0000146 AsmParser(SourceMgr &SM, MCContext &Ctx, MCStreamer &Out,
Daniel Dunbaraef87e32010-07-18 18:31:38 +0000147 const MCAsmInfo &MAI);
Craig Topper345d16d2012-08-29 05:48:09 +0000148 virtual ~AsmParser();
Daniel Dunbaraef87e32010-07-18 18:31:38 +0000149
150 virtual bool Run(bool NoInitialTextSection, bool NoFinalize = false);
151
Craig Topper345d16d2012-08-29 05:48:09 +0000152 virtual void AddDirectiveHandler(MCAsmParserExtension *Object,
153 StringRef Directive,
154 DirectiveHandler Handler) {
Daniel Dunbaraef87e32010-07-18 18:31:38 +0000155 DirectiveMap[Directive] = std::make_pair(Object, Handler);
156 }
157
158public:
159 /// @name MCAsmParser Interface
160 /// {
161
162 virtual SourceMgr &getSourceManager() { return SrcMgr; }
163 virtual MCAsmLexer &getLexer() { return Lexer; }
164 virtual MCContext &getContext() { return Ctx; }
165 virtual MCStreamer &getStreamer() { return Out; }
Devang Patel0db58bf2012-01-31 18:14:05 +0000166 virtual unsigned getAssemblerDialect() {
167 if (AssemblerDialect == ~0U)
168 return MAI.getAssemblerDialect();
169 else
170 return AssemblerDialect;
171 }
172 virtual void setAssemblerDialect(unsigned i) {
173 AssemblerDialect = i;
174 }
Daniel Dunbaraef87e32010-07-18 18:31:38 +0000175
Chris Lattnerd8b7aa22011-10-16 04:47:35 +0000176 virtual bool Warning(SMLoc L, const Twine &Msg,
177 ArrayRef<SMRange> Ranges = ArrayRef<SMRange>());
178 virtual bool Error(SMLoc L, const Twine &Msg,
179 ArrayRef<SMRange> Ranges = ArrayRef<SMRange>());
Daniel Dunbaraef87e32010-07-18 18:31:38 +0000180
Craig Topper345d16d2012-08-29 05:48:09 +0000181 virtual const AsmToken &Lex();
Daniel Dunbaraef87e32010-07-18 18:31:38 +0000182
Chad Rosier8f138d12012-10-15 17:19:13 +0000183 bool ParseStatement();
Chad Rosier84125ca2012-10-13 00:26:04 +0000184 void setParsingInlineAsm(bool V) { ParsingInlineAsm = V; }
Chad Rosier8f138d12012-10-15 17:19:13 +0000185 unsigned getNumParsedOperands() { return ParsedOperands.size(); }
186 MCParsedAsmOperand &getParsedOperand(unsigned OpNum) {
187 assert (ParsedOperands.size() > OpNum);
188 return *ParsedOperands[OpNum];
189 }
190 void freeParsedOperands() {
191 for (unsigned i = 0, e = ParsedOperands.size(); i != e; ++i)
192 delete ParsedOperands[i];
193 ParsedOperands.clear();
194 }
Chad Rosier127f5ed2012-10-15 19:08:18 +0000195 bool isInstruction() { return Opcode != (unsigned)~0x0; }
Chad Rosier8f138d12012-10-15 17:19:13 +0000196 unsigned getOpcode() { return Opcode; }
Chad Rosier84125ca2012-10-13 00:26:04 +0000197
Daniel Dunbaraef87e32010-07-18 18:31:38 +0000198 bool ParseExpression(const MCExpr *&Res);
199 virtual bool ParseExpression(const MCExpr *&Res, SMLoc &EndLoc);
200 virtual bool ParseParenExpression(const MCExpr *&Res, SMLoc &EndLoc);
201 virtual bool ParseAbsoluteExpression(int64_t &Res);
202
203 /// }
204
205private:
Daniel Dunbar1ab6f2f2010-09-09 22:42:59 +0000206 void CheckForValidSection();
207
Kevin Enderbyf1c21a82011-09-13 23:45:18 +0000208 void EatToEndOfLine();
209 bool ParseCppHashLineFilenameComment(const SMLoc &L);
Daniel Dunbaraef87e32010-07-18 18:31:38 +0000210
Daniel Dunbarc64a0d72010-07-18 18:54:11 +0000211 bool HandleMacroEntry(StringRef Name, SMLoc NameLoc, const Macro *M);
Rafael Espindola761cb062012-06-03 23:57:14 +0000212 bool expandMacro(raw_svector_ostream &OS, StringRef Body,
Rafael Espindola8a403d32012-08-08 14:51:03 +0000213 const MacroParameters &Parameters,
214 const MacroArguments &A,
Rafael Espindola65366442011-06-05 02:43:45 +0000215 const SMLoc &L);
Daniel Dunbarc64a0d72010-07-18 18:54:11 +0000216 void HandleMacroExit();
217
218 void PrintMacroInstantiations();
Chris Lattner3f2d5f62011-10-16 05:43:57 +0000219 void PrintMessage(SMLoc Loc, SourceMgr::DiagKind Kind, const Twine &Msg,
Chris Lattner462b43c2011-10-16 05:47:55 +0000220 ArrayRef<SMRange> Ranges = ArrayRef<SMRange>()) const {
221 SrcMgr.PrintMessage(Loc, Kind, Msg, Ranges);
Benjamin Kramerd1e17032010-09-27 17:42:11 +0000222 }
Kevin Enderbyacbaecd2011-10-12 21:38:39 +0000223 static void DiagHandler(const SMDiagnostic &Diag, void *Context);
Benjamin Kramerd1e17032010-09-27 17:42:11 +0000224
Daniel Dunbaraef87e32010-07-18 18:31:38 +0000225 /// EnterIncludeFile - Enter the specified file. This returns true on failure.
226 bool EnterIncludeFile(const std::string &Filename);
Kevin Enderbyc55acca2011-12-14 21:47:48 +0000227 /// ProcessIncbinFile - Process the specified file for the .incbin directive.
228 /// This returns true on failure.
229 bool ProcessIncbinFile(const std::string &Filename);
Daniel Dunbarc64a0d72010-07-18 18:54:11 +0000230
Dmitri Gribenkoc5252da2012-09-14 14:57:36 +0000231 /// \brief Reset the current lexer position to that given by \p Loc. The
Daniel Dunbarc64a0d72010-07-18 18:54:11 +0000232 /// current token is not set; clients should ensure Lex() is called
233 /// subsequently.
234 void JumpToLoc(SMLoc Loc);
235
Craig Topper345d16d2012-08-29 05:48:09 +0000236 virtual void EatToEndOfStatement();
Daniel Dunbar6a46d572010-07-18 20:15:59 +0000237
Preston Gurd7b6f2032012-09-19 20:36:12 +0000238 bool ParseMacroArgument(MacroArgument &MA,
239 AsmToken::TokenKind &ArgumentDelimiter);
Rafael Espindola8a403d32012-08-08 14:51:03 +0000240 bool ParseMacroArguments(const Macro *M, MacroArguments &A);
Rafael Espindolaaa7a2f22012-06-15 14:02:34 +0000241
Daniel Dunbar6a46d572010-07-18 20:15:59 +0000242 /// \brief Parse up to the end of statement and a return the contents from the
243 /// current token until the end of the statement; the current token on exit
244 /// will be either the EndOfStatement or EOF.
Craig Topper345d16d2012-08-29 05:48:09 +0000245 virtual StringRef ParseStringToEndOfStatement();
Daniel Dunbar6a46d572010-07-18 20:15:59 +0000246
Benjamin Kramerdec06ef2012-05-12 11:18:51 +0000247 /// \brief Parse until the end of a statement or a comma is encountered,
248 /// return the contents from the current token up to the end or comma.
249 StringRef ParseStringToComma();
250
Jim Grosbach3f90a4c2012-09-13 23:11:31 +0000251 bool ParseAssignment(StringRef Name, bool allow_redef,
252 bool NoDeadStrip = false);
Daniel Dunbaraef87e32010-07-18 18:31:38 +0000253
254 bool ParsePrimaryExpr(const MCExpr *&Res, SMLoc &EndLoc);
255 bool ParseBinOpRHS(unsigned Precedence, const MCExpr *&Res, SMLoc &EndLoc);
256 bool ParseParenExpr(const MCExpr *&Res, SMLoc &EndLoc);
Joerg Sonnenberger93c65e62011-02-24 21:59:22 +0000257 bool ParseBracketExpr(const MCExpr *&Res, SMLoc &EndLoc);
Daniel Dunbaraef87e32010-07-18 18:31:38 +0000258
259 /// ParseIdentifier - Parse an identifier or string (as a quoted identifier)
Dmitri Gribenkoc5252da2012-09-14 14:57:36 +0000260 /// and set \p Res to the identifier contents.
Craig Topper345d16d2012-08-29 05:48:09 +0000261 virtual bool ParseIdentifier(StringRef &Res);
Michael J. Spencerc0c8df32010-10-09 11:00:50 +0000262
Daniel Dunbaraef87e32010-07-18 18:31:38 +0000263 // Directive Parsing.
Rafael Espindola787c3372010-10-28 20:02:27 +0000264
265 // ".ascii", ".asciiz", ".string"
266 bool ParseDirectiveAscii(StringRef IDVal, bool ZeroTerminated);
Daniel Dunbaraef87e32010-07-18 18:31:38 +0000267 bool ParseDirectiveValue(unsigned Size); // ".byte", ".long", ...
Daniel Dunbarb95a0792010-09-24 01:59:56 +0000268 bool ParseDirectiveRealValue(const fltSemantics &); // ".single", ...
Daniel Dunbaraef87e32010-07-18 18:31:38 +0000269 bool ParseDirectiveFill(); // ".fill"
270 bool ParseDirectiveSpace(); // ".space"
Rafael Espindola2ea2ac72010-09-16 15:03:59 +0000271 bool ParseDirectiveZero(); // ".zero"
Nico Weber4c4c7322011-01-28 03:04:41 +0000272 bool ParseDirectiveSet(StringRef IDVal, bool allow_redef); // ".set", ".equ", ".equiv"
Daniel Dunbaraef87e32010-07-18 18:31:38 +0000273 bool ParseDirectiveOrg(); // ".org"
274 // ".align{,32}", ".p2align{,w,l}"
275 bool ParseDirectiveAlign(bool IsPow2, unsigned ValueSize);
276
277 /// ParseDirectiveSymbolAttribute - Parse a directive like ".globl" which
278 /// accepts a single symbol (which should be a label or an external).
279 bool ParseDirectiveSymbolAttribute(MCSymbolAttr Attr);
Daniel Dunbaraef87e32010-07-18 18:31:38 +0000280
281 bool ParseDirectiveComm(bool IsLocal); // ".comm" and ".lcomm"
282
283 bool ParseDirectiveAbort(); // ".abort"
284 bool ParseDirectiveInclude(); // ".include"
Kevin Enderbyc55acca2011-12-14 21:47:48 +0000285 bool ParseDirectiveIncbin(); // ".incbin"
Daniel Dunbaraef87e32010-07-18 18:31:38 +0000286
287 bool ParseDirectiveIf(SMLoc DirectiveLoc); // ".if"
Benjamin Kramera3dd0eb2012-05-12 11:18:42 +0000288 // ".ifb" or ".ifnb", depending on ExpectBlank.
289 bool ParseDirectiveIfb(SMLoc DirectiveLoc, bool ExpectBlank);
Benjamin Kramerdec06ef2012-05-12 11:18:51 +0000290 // ".ifc" or ".ifnc", depending on ExpectEqual.
291 bool ParseDirectiveIfc(SMLoc DirectiveLoc, bool ExpectEqual);
Benjamin Kramer0fd90bc2011-02-08 22:29:56 +0000292 // ".ifdef" or ".ifndef", depending on expect_defined
293 bool ParseDirectiveIfdef(SMLoc DirectiveLoc, bool expect_defined);
Daniel Dunbaraef87e32010-07-18 18:31:38 +0000294 bool ParseDirectiveElseIf(SMLoc DirectiveLoc); // ".elseif"
295 bool ParseDirectiveElse(SMLoc DirectiveLoc); // ".else"
296 bool ParseDirectiveEndIf(SMLoc DirectiveLoc); // .endif
297
298 /// ParseEscapedString - Parse the current token as a string which may include
299 /// escaped characters and return the string contents.
300 bool ParseEscapedString(std::string &Data);
Daniel Dunbarcceba832010-09-17 02:47:07 +0000301
302 const MCExpr *ApplyModifierToExpr(const MCExpr *E,
303 MCSymbolRefExpr::VariantKind Variant);
Rafael Espindola2ec304c2012-05-12 16:31:10 +0000304
Rafael Espindola761cb062012-06-03 23:57:14 +0000305 // Macro-like directives
306 Macro *ParseMacroLikeBody(SMLoc DirectiveLoc);
307 void InstantiateMacroLikeBody(Macro *M, SMLoc DirectiveLoc,
308 raw_svector_ostream &OS);
309 bool ParseDirectiveRept(SMLoc DirectiveLoc); // ".rept"
Rafael Espindolaaa7a2f22012-06-15 14:02:34 +0000310 bool ParseDirectiveIrp(SMLoc DirectiveLoc); // ".irp"
Rafael Espindolafc9216e2012-06-16 18:03:25 +0000311 bool ParseDirectiveIrpc(SMLoc DirectiveLoc); // ".irpc"
Rafael Espindola761cb062012-06-03 23:57:14 +0000312 bool ParseDirectiveEndr(SMLoc DirectiveLoc); // ".endr"
Daniel Dunbaraef87e32010-07-18 18:31:38 +0000313};
314
Daniel Dunbar81ea00f2010-07-12 17:54:38 +0000315/// \brief Generic implementations of directive handling, etc. which is shared
316/// (or the default, at least) for all assembler parser.
317class GenericAsmParser : public MCAsmParserExtension {
Daniel Dunbar1edf6ca2010-07-18 22:22:07 +0000318 template<bool (GenericAsmParser::*Handler)(StringRef, SMLoc)>
319 void AddDirectiveHandler(StringRef Directive) {
320 getParser().AddDirectiveHandler(this, Directive,
321 HandleDirective<GenericAsmParser, Handler>);
322 }
Daniel Dunbar81ea00f2010-07-12 17:54:38 +0000323public:
324 GenericAsmParser() {}
325
Daniel Dunbar3c802de2010-07-18 18:38:02 +0000326 AsmParser &getParser() {
327 return (AsmParser&) this->MCAsmParserExtension::getParser();
328 }
329
Daniel Dunbar81ea00f2010-07-12 17:54:38 +0000330 virtual void Initialize(MCAsmParser &Parser) {
331 // Call the base implementation.
332 this->MCAsmParserExtension::Initialize(Parser);
333
334 // Debugging directives.
Daniel Dunbar1edf6ca2010-07-18 22:22:07 +0000335 AddDirectiveHandler<&GenericAsmParser::ParseDirectiveFile>(".file");
336 AddDirectiveHandler<&GenericAsmParser::ParseDirectiveLine>(".line");
337 AddDirectiveHandler<&GenericAsmParser::ParseDirectiveLoc>(".loc");
Daniel Dunbar138abae2010-10-16 04:56:42 +0000338 AddDirectiveHandler<&GenericAsmParser::ParseDirectiveStabs>(".stabs");
Daniel Dunbar3c802de2010-07-18 18:38:02 +0000339
Rafael Espindola1fdfbc42010-11-16 18:34:07 +0000340 // CFI directives.
Rafael Espindolaf9efd832011-05-10 01:10:18 +0000341 AddDirectiveHandler<&GenericAsmParser::ParseDirectiveCFISections>(
342 ".cfi_sections");
Rafael Espindola1fdfbc42010-11-16 18:34:07 +0000343 AddDirectiveHandler<&GenericAsmParser::ParseDirectiveCFIStartProc>(
344 ".cfi_startproc");
345 AddDirectiveHandler<&GenericAsmParser::ParseDirectiveCFIEndProc>(
346 ".cfi_endproc");
Rafael Espindolab40a71f2010-12-29 01:42:56 +0000347 AddDirectiveHandler<&GenericAsmParser::ParseDirectiveCFIDefCfa>(
348 ".cfi_def_cfa");
Rafael Espindola1fdfbc42010-11-16 18:34:07 +0000349 AddDirectiveHandler<&GenericAsmParser::ParseDirectiveCFIDefCfaOffset>(
350 ".cfi_def_cfa_offset");
Rafael Espindola53abbe52011-04-11 20:29:16 +0000351 AddDirectiveHandler<&GenericAsmParser::ParseDirectiveCFIAdjustCfaOffset>(
352 ".cfi_adjust_cfa_offset");
Rafael Espindola1fdfbc42010-11-16 18:34:07 +0000353 AddDirectiveHandler<&GenericAsmParser::ParseDirectiveCFIDefCfaRegister>(
354 ".cfi_def_cfa_register");
355 AddDirectiveHandler<&GenericAsmParser::ParseDirectiveCFIOffset>(
356 ".cfi_offset");
Rafael Espindolaa61842b2011-04-11 21:49:50 +0000357 AddDirectiveHandler<&GenericAsmParser::ParseDirectiveCFIRelOffset>(
358 ".cfi_rel_offset");
Rafael Espindola1fdfbc42010-11-16 18:34:07 +0000359 AddDirectiveHandler<
360 &GenericAsmParser::ParseDirectiveCFIPersonalityOrLsda>(".cfi_personality");
361 AddDirectiveHandler<
362 &GenericAsmParser::ParseDirectiveCFIPersonalityOrLsda>(".cfi_lsda");
Rafael Espindolafe024d02010-12-28 18:36:23 +0000363 AddDirectiveHandler<
364 &GenericAsmParser::ParseDirectiveCFIRememberState>(".cfi_remember_state");
365 AddDirectiveHandler<
366 &GenericAsmParser::ParseDirectiveCFIRestoreState>(".cfi_restore_state");
Rafael Espindolac5754392011-04-12 15:31:05 +0000367 AddDirectiveHandler<
368 &GenericAsmParser::ParseDirectiveCFISameValue>(".cfi_same_value");
Rafael Espindola6f0b1812011-12-29 20:24:47 +0000369 AddDirectiveHandler<
Rafael Espindolaed23bdb2011-12-29 21:43:03 +0000370 &GenericAsmParser::ParseDirectiveCFIRestore>(".cfi_restore");
371 AddDirectiveHandler<
Rafael Espindola6f0b1812011-12-29 20:24:47 +0000372 &GenericAsmParser::ParseDirectiveCFIEscape>(".cfi_escape");
Rafael Espindola16d7d432012-01-23 21:51:52 +0000373 AddDirectiveHandler<
374 &GenericAsmParser::ParseDirectiveCFISignalFrame>(".cfi_signal_frame");
Rafael Espindola1fdfbc42010-11-16 18:34:07 +0000375
Daniel Dunbar3c802de2010-07-18 18:38:02 +0000376 // Macro directives.
Daniel Dunbar1edf6ca2010-07-18 22:22:07 +0000377 AddDirectiveHandler<&GenericAsmParser::ParseDirectiveMacrosOnOff>(
378 ".macros_on");
379 AddDirectiveHandler<&GenericAsmParser::ParseDirectiveMacrosOnOff>(
380 ".macros_off");
381 AddDirectiveHandler<&GenericAsmParser::ParseDirectiveMacro>(".macro");
382 AddDirectiveHandler<&GenericAsmParser::ParseDirectiveEndMacro>(".endm");
383 AddDirectiveHandler<&GenericAsmParser::ParseDirectiveEndMacro>(".endmacro");
Benjamin Kramerbc3b27c2012-05-12 11:21:46 +0000384 AddDirectiveHandler<&GenericAsmParser::ParseDirectivePurgeMacro>(".purgem");
Rafael Espindolab98ac2a2010-09-11 16:45:15 +0000385
386 AddDirectiveHandler<&GenericAsmParser::ParseDirectiveLEB128>(".sleb128");
387 AddDirectiveHandler<&GenericAsmParser::ParseDirectiveLEB128>(".uleb128");
Daniel Dunbar81ea00f2010-07-12 17:54:38 +0000388 }
389
Roman Divacky54b0f4f2011-01-27 17:16:37 +0000390 bool ParseRegisterOrRegisterNumber(int64_t &Register, SMLoc DirectiveLoc);
391
Daniel Dunbar3c802de2010-07-18 18:38:02 +0000392 bool ParseDirectiveFile(StringRef, SMLoc DirectiveLoc);
393 bool ParseDirectiveLine(StringRef, SMLoc DirectiveLoc);
394 bool ParseDirectiveLoc(StringRef, SMLoc DirectiveLoc);
Daniel Dunbar138abae2010-10-16 04:56:42 +0000395 bool ParseDirectiveStabs(StringRef, SMLoc DirectiveLoc);
Rafael Espindolaf9efd832011-05-10 01:10:18 +0000396 bool ParseDirectiveCFISections(StringRef, SMLoc DirectiveLoc);
Rafael Espindola1fdfbc42010-11-16 18:34:07 +0000397 bool ParseDirectiveCFIStartProc(StringRef, SMLoc DirectiveLoc);
398 bool ParseDirectiveCFIEndProc(StringRef, SMLoc DirectiveLoc);
Rafael Espindolab40a71f2010-12-29 01:42:56 +0000399 bool ParseDirectiveCFIDefCfa(StringRef, SMLoc DirectiveLoc);
Rafael Espindola1fdfbc42010-11-16 18:34:07 +0000400 bool ParseDirectiveCFIDefCfaOffset(StringRef, SMLoc DirectiveLoc);
Rafael Espindola53abbe52011-04-11 20:29:16 +0000401 bool ParseDirectiveCFIAdjustCfaOffset(StringRef, SMLoc DirectiveLoc);
Rafael Espindola1fdfbc42010-11-16 18:34:07 +0000402 bool ParseDirectiveCFIDefCfaRegister(StringRef, SMLoc DirectiveLoc);
403 bool ParseDirectiveCFIOffset(StringRef, SMLoc DirectiveLoc);
Rafael Espindolaa61842b2011-04-11 21:49:50 +0000404 bool ParseDirectiveCFIRelOffset(StringRef, SMLoc DirectiveLoc);
Rafael Espindola1fdfbc42010-11-16 18:34:07 +0000405 bool ParseDirectiveCFIPersonalityOrLsda(StringRef, SMLoc DirectiveLoc);
Rafael Espindolafe024d02010-12-28 18:36:23 +0000406 bool ParseDirectiveCFIRememberState(StringRef, SMLoc DirectiveLoc);
407 bool ParseDirectiveCFIRestoreState(StringRef, SMLoc DirectiveLoc);
Rafael Espindolac5754392011-04-12 15:31:05 +0000408 bool ParseDirectiveCFISameValue(StringRef, SMLoc DirectiveLoc);
Rafael Espindolaed23bdb2011-12-29 21:43:03 +0000409 bool ParseDirectiveCFIRestore(StringRef, SMLoc DirectiveLoc);
Rafael Espindola6f0b1812011-12-29 20:24:47 +0000410 bool ParseDirectiveCFIEscape(StringRef, SMLoc DirectiveLoc);
Rafael Espindola16d7d432012-01-23 21:51:52 +0000411 bool ParseDirectiveCFISignalFrame(StringRef, SMLoc DirectiveLoc);
Daniel Dunbar6d8cf082010-07-18 18:47:21 +0000412
Daniel Dunbar3c802de2010-07-18 18:38:02 +0000413 bool ParseDirectiveMacrosOnOff(StringRef, SMLoc DirectiveLoc);
Daniel Dunbar6d8cf082010-07-18 18:47:21 +0000414 bool ParseDirectiveMacro(StringRef, SMLoc DirectiveLoc);
415 bool ParseDirectiveEndMacro(StringRef, SMLoc DirectiveLoc);
Benjamin Kramerbc3b27c2012-05-12 11:21:46 +0000416 bool ParseDirectivePurgeMacro(StringRef, SMLoc DirectiveLoc);
Rafael Espindolab98ac2a2010-09-11 16:45:15 +0000417
Rafael Espindolab98ac2a2010-09-11 16:45:15 +0000418 bool ParseDirectiveLEB128(StringRef, SMLoc);
Daniel Dunbar81ea00f2010-07-12 17:54:38 +0000419};
420
421}
422
Daniel Dunbar9c23d7f2010-07-12 20:51:51 +0000423namespace llvm {
424
425extern MCAsmParserExtension *createDarwinAsmParser();
Daniel Dunbar5146a092010-07-12 21:23:32 +0000426extern MCAsmParserExtension *createELFAsmParser();
Michael J. Spencer7d490042010-10-09 11:01:07 +0000427extern MCAsmParserExtension *createCOFFAsmParser();
Daniel Dunbar9c23d7f2010-07-12 20:51:51 +0000428
429}
430
Chris Lattneraaec2052010-01-19 19:46:13 +0000431enum { DEFAULT_ADDRSPACE = 0 };
432
Jim Grosbach1b84cce2011-08-16 18:33:49 +0000433AsmParser::AsmParser(SourceMgr &_SM, MCContext &_Ctx,
Daniel Dunbar9186fa62010-07-01 20:41:56 +0000434 MCStreamer &_Out, const MCAsmInfo &_MAI)
Jim Grosbache82b8ee2011-06-15 18:33:28 +0000435 : Lexer(_MAI), Ctx(_Ctx), Out(_Out), MAI(_MAI), SrcMgr(_SM),
Rafael Espindola5d7dcd32011-04-12 18:53:30 +0000436 GenericParser(new GenericAsmParser), PlatformParser(0),
Preston Gurd7b6f2032012-09-19 20:36:12 +0000437 CurBuffer(0), MacrosEnabled(true), CppHashLineNumber(0),
Chad Rosier8f138d12012-10-15 17:19:13 +0000438 AssemblerDialect(~0U), IsDarwin(false), ParsingInlineAsm(false),
Chad Rosier127f5ed2012-10-15 19:08:18 +0000439 Opcode(~0x0) {
Benjamin Kramer04a04262011-10-16 10:48:29 +0000440 // Save the old handler.
441 SavedDiagHandler = SrcMgr.getDiagHandler();
442 SavedDiagContext = SrcMgr.getDiagContext();
443 // Set our own handler which calls the saved handler.
Kevin Enderbyacbaecd2011-10-12 21:38:39 +0000444 SrcMgr.setDiagHandler(DiagHandler, this);
Sean Callananfd0b0282010-01-21 00:19:58 +0000445 Lexer.setBuffer(SrcMgr.getMemoryBuffer(CurBuffer));
Daniel Dunbar81ea00f2010-07-12 17:54:38 +0000446
447 // Initialize the generic parser.
448 GenericParser->Initialize(*this);
Daniel Dunbare4749702010-07-12 18:12:02 +0000449
450 // Initialize the platform / file format parser.
451 //
452 // FIXME: This is a hack, we need to (majorly) cleanup how these objects are
453 // created.
Michael J. Spencer7d490042010-10-09 11:01:07 +0000454 if (_MAI.hasMicrosoftFastStdCallMangling()) {
455 PlatformParser = createCOFFAsmParser();
456 PlatformParser->Initialize(*this);
457 } else if (_MAI.hasSubsectionsViaSymbols()) {
Daniel Dunbar9c23d7f2010-07-12 20:51:51 +0000458 PlatformParser = createDarwinAsmParser();
Daniel Dunbare4749702010-07-12 18:12:02 +0000459 PlatformParser->Initialize(*this);
Preston Gurd7b6f2032012-09-19 20:36:12 +0000460 IsDarwin = true;
Daniel Dunbar7a56fc22010-07-12 20:08:04 +0000461 } else {
Daniel Dunbar5146a092010-07-12 21:23:32 +0000462 PlatformParser = createELFAsmParser();
Daniel Dunbar7a56fc22010-07-12 20:08:04 +0000463 PlatformParser->Initialize(*this);
Daniel Dunbare4749702010-07-12 18:12:02 +0000464 }
Chris Lattnerebb89b42009-09-27 21:16:52 +0000465}
466
Daniel Dunbar7c0a3342009-08-26 22:49:51 +0000467AsmParser::~AsmParser() {
Daniel Dunbar56491302010-07-29 01:51:55 +0000468 assert(ActiveMacros.empty() && "Unexpected active macro instantiation!");
469
470 // Destroy any macros.
471 for (StringMap<Macro*>::iterator it = MacroMap.begin(),
472 ie = MacroMap.end(); it != ie; ++it)
473 delete it->getValue();
474
Daniel Dunbare4749702010-07-12 18:12:02 +0000475 delete PlatformParser;
Daniel Dunbar81ea00f2010-07-12 17:54:38 +0000476 delete GenericParser;
Daniel Dunbar7c0a3342009-08-26 22:49:51 +0000477}
478
Daniel Dunbarc64a0d72010-07-18 18:54:11 +0000479void AsmParser::PrintMacroInstantiations() {
480 // Print the active macro instantiation stack.
481 for (std::vector<MacroInstantiation*>::const_reverse_iterator
482 it = ActiveMacros.rbegin(), ie = ActiveMacros.rend(); it != ie; ++it)
Chris Lattner3f2d5f62011-10-16 05:43:57 +0000483 PrintMessage((*it)->InstantiationLoc, SourceMgr::DK_Note,
484 "while in macro instantiation");
Daniel Dunbarc64a0d72010-07-18 18:54:11 +0000485}
486
Chris Lattnerd8b7aa22011-10-16 04:47:35 +0000487bool AsmParser::Warning(SMLoc L, const Twine &Msg, ArrayRef<SMRange> Ranges) {
Joerg Sonnenbergerf8cd7082011-05-19 18:00:13 +0000488 if (FatalAssemblerWarnings)
Chris Lattnerd8b7aa22011-10-16 04:47:35 +0000489 return Error(L, Msg, Ranges);
Chris Lattner3f2d5f62011-10-16 05:43:57 +0000490 PrintMessage(L, SourceMgr::DK_Warning, Msg, Ranges);
Daniel Dunbarc64a0d72010-07-18 18:54:11 +0000491 PrintMacroInstantiations();
Joerg Sonnenbergerf8cd7082011-05-19 18:00:13 +0000492 return false;
Daniel Dunbar3fb76832009-06-30 00:49:23 +0000493}
494
Chris Lattnerd8b7aa22011-10-16 04:47:35 +0000495bool AsmParser::Error(SMLoc L, const Twine &Msg, ArrayRef<SMRange> Ranges) {
Daniel Dunbar93bd4d12010-09-09 22:42:56 +0000496 HadError = true;
Chris Lattner3f2d5f62011-10-16 05:43:57 +0000497 PrintMessage(L, SourceMgr::DK_Error, Msg, Ranges);
Daniel Dunbarc64a0d72010-07-18 18:54:11 +0000498 PrintMacroInstantiations();
Chris Lattner14ee48a2009-06-21 21:22:11 +0000499 return true;
500}
501
Sean Callananfd0b0282010-01-21 00:19:58 +0000502bool AsmParser::EnterIncludeFile(const std::string &Filename) {
Joerg Sonnenbergerdd137902011-06-01 13:10:15 +0000503 std::string IncludedFile;
504 int NewBuf = SrcMgr.AddIncludeFile(Filename, Lexer.getLoc(), IncludedFile);
Sean Callananfd0b0282010-01-21 00:19:58 +0000505 if (NewBuf == -1)
506 return true;
Michael J. Spencerc0c8df32010-10-09 11:00:50 +0000507
Sean Callananfd0b0282010-01-21 00:19:58 +0000508 CurBuffer = NewBuf;
Michael J. Spencerc0c8df32010-10-09 11:00:50 +0000509
Sean Callananfd0b0282010-01-21 00:19:58 +0000510 Lexer.setBuffer(SrcMgr.getMemoryBuffer(CurBuffer));
Michael J. Spencerc0c8df32010-10-09 11:00:50 +0000511
Sean Callananfd0b0282010-01-21 00:19:58 +0000512 return false;
513}
Daniel Dunbarc64a0d72010-07-18 18:54:11 +0000514
Kevin Enderbyc55acca2011-12-14 21:47:48 +0000515/// Process the specified .incbin file by seaching for it in the include paths
Benjamin Kramerd9b0b022012-06-02 10:20:22 +0000516/// then just emitting the byte contents of the file to the streamer. This
Kevin Enderbyc55acca2011-12-14 21:47:48 +0000517/// returns true on failure.
518bool AsmParser::ProcessIncbinFile(const std::string &Filename) {
519 std::string IncludedFile;
520 int NewBuf = SrcMgr.AddIncludeFile(Filename, Lexer.getLoc(), IncludedFile);
521 if (NewBuf == -1)
522 return true;
523
Kevin Enderbyc3fc3132011-12-14 22:34:45 +0000524 // Pick up the bytes from the file and emit them.
Kevin Enderbydac29532011-12-15 00:00:27 +0000525 getStreamer().EmitBytes(SrcMgr.getMemoryBuffer(NewBuf)->getBuffer(),
526 DEFAULT_ADDRSPACE);
Kevin Enderbyc55acca2011-12-14 21:47:48 +0000527 return false;
528}
529
Daniel Dunbarc64a0d72010-07-18 18:54:11 +0000530void AsmParser::JumpToLoc(SMLoc Loc) {
531 CurBuffer = SrcMgr.FindBufferContainingLoc(Loc);
532 Lexer.setBuffer(SrcMgr.getMemoryBuffer(CurBuffer), Loc.getPointer());
533}
534
Sean Callananfd0b0282010-01-21 00:19:58 +0000535const AsmToken &AsmParser::Lex() {
536 const AsmToken *tok = &Lexer.Lex();
Michael J. Spencerc0c8df32010-10-09 11:00:50 +0000537
Sean Callananfd0b0282010-01-21 00:19:58 +0000538 if (tok->is(AsmToken::Eof)) {
539 // If this is the end of an included file, pop the parent file off the
540 // include stack.
541 SMLoc ParentIncludeLoc = SrcMgr.getParentIncludeLoc(CurBuffer);
542 if (ParentIncludeLoc != SMLoc()) {
Daniel Dunbarc64a0d72010-07-18 18:54:11 +0000543 JumpToLoc(ParentIncludeLoc);
Sean Callananfd0b0282010-01-21 00:19:58 +0000544 tok = &Lexer.Lex();
545 }
546 }
Michael J. Spencerc0c8df32010-10-09 11:00:50 +0000547
Sean Callananfd0b0282010-01-21 00:19:58 +0000548 if (tok->is(AsmToken::Error))
Daniel Dunbar275ce392010-07-18 18:31:45 +0000549 Error(Lexer.getErrLoc(), Lexer.getErr());
Michael J. Spencerc0c8df32010-10-09 11:00:50 +0000550
Sean Callananfd0b0282010-01-21 00:19:58 +0000551 return *tok;
Sean Callanan79ed1a82010-01-19 20:22:31 +0000552}
553
Chris Lattner79180e22010-04-05 23:15:42 +0000554bool AsmParser::Run(bool NoInitialTextSection, bool NoFinalize) {
Daniel Dunbar5e6a7a22010-03-13 02:20:57 +0000555 // Create the initial section, if requested.
Daniel Dunbar5e6a7a22010-03-13 02:20:57 +0000556 if (!NoInitialTextSection)
Rafael Espindolad80781b2010-09-15 21:48:40 +0000557 Out.InitSections();
Daniel Dunbar7c0a3342009-08-26 22:49:51 +0000558
Chris Lattnerb0789ed2009-06-21 20:54:55 +0000559 // Prime the lexer.
Sean Callanan79ed1a82010-01-19 20:22:31 +0000560 Lex();
Daniel Dunbar93bd4d12010-09-09 22:42:56 +0000561
562 HadError = false;
Kevin Enderbyc114ed72009-08-07 22:46:00 +0000563 AsmCond StartingCondState = TheCondState;
564
Kevin Enderby613b7572011-11-01 22:27:22 +0000565 // If we are generating dwarf for assembly source files save the initial text
566 // section and generate a .file directive.
567 if (getContext().getGenDwarfForAssembly()) {
568 getContext().setGenDwarfSection(getStreamer().getCurrentSection());
Kevin Enderby94c2e852011-12-09 18:09:40 +0000569 MCSymbol *SectionStartSym = getContext().CreateTempSymbol();
570 getStreamer().EmitLabel(SectionStartSym);
571 getContext().setGenDwarfSectionStartSym(SectionStartSym);
Kevin Enderby613b7572011-11-01 22:27:22 +0000572 getStreamer().EmitDwarfFileDirective(getContext().nextGenDwarfFileNumber(),
573 StringRef(), SrcMgr.getMemoryBuffer(CurBuffer)->getBufferIdentifier());
574 }
575
Chris Lattnerb717fb02009-07-02 21:53:43 +0000576 // While we have input, parse each statement.
Daniel Dunbar3f872332009-07-28 16:08:33 +0000577 while (Lexer.isNot(AsmToken::Eof)) {
Chris Lattnerb717fb02009-07-02 21:53:43 +0000578 if (!ParseStatement()) continue;
Michael J. Spencerc0c8df32010-10-09 11:00:50 +0000579
Daniel Dunbar93bd4d12010-09-09 22:42:56 +0000580 // We had an error, validate that one was emitted and recover by skipping to
581 // the next line.
582 assert(HadError && "Parse statement returned an error, but none emitted!");
Chris Lattnerb717fb02009-07-02 21:53:43 +0000583 EatToEndOfStatement();
584 }
Kevin Enderbyc114ed72009-08-07 22:46:00 +0000585
586 if (TheCondState.TheCond != StartingCondState.TheCond ||
587 TheCondState.Ignore != StartingCondState.Ignore)
588 return TokError("unmatched .ifs or .elses");
Kevin Enderby7cbf73a2010-07-28 20:55:35 +0000589
590 // Check to see there are no empty DwarfFile slots.
591 const std::vector<MCDwarfFile *> &MCDwarfFiles =
592 getContext().getMCDwarfFiles();
593 for (unsigned i = 1; i < MCDwarfFiles.size(); i++) {
Daniel Dunbar93bd4d12010-09-09 22:42:56 +0000594 if (!MCDwarfFiles[i])
Kevin Enderby7cbf73a2010-07-28 20:55:35 +0000595 TokError("unassigned file number: " + Twine(i) + " for .file directives");
Kevin Enderby7cbf73a2010-07-28 20:55:35 +0000596 }
Michael J. Spencerc0c8df32010-10-09 11:00:50 +0000597
Jim Grosbache82b8ee2011-06-15 18:33:28 +0000598 // Check to see that all assembler local symbols were actually defined.
599 // Targets that don't do subsections via symbols may not want this, though,
600 // so conservatively exclude them. Only do this if we're finalizing, though,
601 // as otherwise we won't necessarilly have seen everything yet.
602 if (!NoFinalize && MAI.hasSubsectionsViaSymbols()) {
603 const MCContext::SymbolTable &Symbols = getContext().getSymbols();
604 for (MCContext::SymbolTable::const_iterator i = Symbols.begin(),
605 e = Symbols.end();
606 i != e; ++i) {
607 MCSymbol *Sym = i->getValue();
608 // Variable symbols may not be marked as defined, so check those
609 // explicitly. If we know it's a variable, we have a definition for
610 // the purposes of this check.
611 if (Sym->isTemporary() && !Sym->isVariable() && !Sym->isDefined())
612 // FIXME: We would really like to refer back to where the symbol was
613 // first referenced for a source location. We need to add something
614 // to track that. Currently, we just point to the end of the file.
Chris Lattner3f2d5f62011-10-16 05:43:57 +0000615 PrintMessage(getLexer().getLoc(), SourceMgr::DK_Error,
616 "assembler local symbol '" + Sym->getName() +
617 "' not defined");
Jim Grosbache82b8ee2011-06-15 18:33:28 +0000618 }
619 }
620
621
Chris Lattner79180e22010-04-05 23:15:42 +0000622 // Finalize the output stream if there are no errors and if the client wants
623 // us to.
Michael J. Spencerc0c8df32010-10-09 11:00:50 +0000624 if (!HadError && !NoFinalize)
Daniel Dunbarb3f3c032009-08-21 08:34:18 +0000625 Out.Finish();
626
Chris Lattnerb717fb02009-07-02 21:53:43 +0000627 return HadError;
Chris Lattnerb0789ed2009-06-21 20:54:55 +0000628}
629
Daniel Dunbar1ab6f2f2010-09-09 22:42:59 +0000630void AsmParser::CheckForValidSection() {
Chad Rosier84125ca2012-10-13 00:26:04 +0000631 if (!ParsingInlineAsm && !getStreamer().getCurrentSection()) {
Daniel Dunbar1ab6f2f2010-09-09 22:42:59 +0000632 TokError("expected section directive before assembly directive");
633 Out.SwitchSection(Ctx.getMachOSection(
634 "__TEXT", "__text",
635 MCSectionMachO::S_ATTR_PURE_INSTRUCTIONS,
636 0, SectionKind::getText()));
637 }
638}
639
Chris Lattner2cf5f142009-06-22 01:29:09 +0000640/// EatToEndOfStatement - Throw away the rest of the line for testing purposes.
641void AsmParser::EatToEndOfStatement() {
Daniel Dunbar3f872332009-07-28 16:08:33 +0000642 while (Lexer.isNot(AsmToken::EndOfStatement) &&
643 Lexer.isNot(AsmToken::Eof))
Sean Callanan79ed1a82010-01-19 20:22:31 +0000644 Lex();
Michael J. Spencerc0c8df32010-10-09 11:00:50 +0000645
Chris Lattner2cf5f142009-06-22 01:29:09 +0000646 // Eat EOL.
Daniel Dunbar3f872332009-07-28 16:08:33 +0000647 if (Lexer.is(AsmToken::EndOfStatement))
Sean Callanan79ed1a82010-01-19 20:22:31 +0000648 Lex();
Chris Lattner2cf5f142009-06-22 01:29:09 +0000649}
650
Daniel Dunbar6a46d572010-07-18 20:15:59 +0000651StringRef AsmParser::ParseStringToEndOfStatement() {
652 const char *Start = getTok().getLoc().getPointer();
653
654 while (Lexer.isNot(AsmToken::EndOfStatement) &&
655 Lexer.isNot(AsmToken::Eof))
656 Lex();
657
658 const char *End = getTok().getLoc().getPointer();
659 return StringRef(Start, End - Start);
660}
Chris Lattnerc4193832009-06-22 05:51:26 +0000661
Benjamin Kramerdec06ef2012-05-12 11:18:51 +0000662StringRef AsmParser::ParseStringToComma() {
663 const char *Start = getTok().getLoc().getPointer();
664
665 while (Lexer.isNot(AsmToken::EndOfStatement) &&
666 Lexer.isNot(AsmToken::Comma) &&
667 Lexer.isNot(AsmToken::Eof))
668 Lex();
669
670 const char *End = getTok().getLoc().getPointer();
671 return StringRef(Start, End - Start);
672}
673
Chris Lattner74ec1a32009-06-22 06:32:03 +0000674/// ParseParenExpr - Parse a paren expression and return it.
675/// NOTE: This assumes the leading '(' has already been consumed.
676///
677/// parenexpr ::= expr)
678///
Chris Lattnerb4307b32010-01-15 19:28:38 +0000679bool AsmParser::ParseParenExpr(const MCExpr *&Res, SMLoc &EndLoc) {
Chris Lattner74ec1a32009-06-22 06:32:03 +0000680 if (ParseExpression(Res)) return true;
Daniel Dunbar3f872332009-07-28 16:08:33 +0000681 if (Lexer.isNot(AsmToken::RParen))
Chris Lattner74ec1a32009-06-22 06:32:03 +0000682 return TokError("expected ')' in parentheses expression");
Chris Lattnerb4307b32010-01-15 19:28:38 +0000683 EndLoc = Lexer.getLoc();
Sean Callanan79ed1a82010-01-19 20:22:31 +0000684 Lex();
Chris Lattner74ec1a32009-06-22 06:32:03 +0000685 return false;
686}
Chris Lattnerc4193832009-06-22 05:51:26 +0000687
Joerg Sonnenberger93c65e62011-02-24 21:59:22 +0000688/// ParseBracketExpr - Parse a bracket expression and return it.
689/// NOTE: This assumes the leading '[' has already been consumed.
690///
691/// bracketexpr ::= expr]
692///
693bool AsmParser::ParseBracketExpr(const MCExpr *&Res, SMLoc &EndLoc) {
694 if (ParseExpression(Res)) return true;
695 if (Lexer.isNot(AsmToken::RBrac))
696 return TokError("expected ']' in brackets expression");
697 EndLoc = Lexer.getLoc();
698 Lex();
699 return false;
700}
701
Chris Lattner74ec1a32009-06-22 06:32:03 +0000702/// ParsePrimaryExpr - Parse a primary expression and return it.
703/// primaryexpr ::= (parenexpr
704/// primaryexpr ::= symbol
705/// primaryexpr ::= number
Chris Lattnerd3050352010-04-14 04:40:28 +0000706/// primaryexpr ::= '.'
Chris Lattner74ec1a32009-06-22 06:32:03 +0000707/// primaryexpr ::= ~,+,- primaryexpr
Chris Lattnerb4307b32010-01-15 19:28:38 +0000708bool AsmParser::ParsePrimaryExpr(const MCExpr *&Res, SMLoc &EndLoc) {
Chris Lattnerc4193832009-06-22 05:51:26 +0000709 switch (Lexer.getKind()) {
710 default:
711 return TokError("unknown token in expression");
Eric Christopherf3755b22011-04-12 00:03:13 +0000712 // If we have an error assume that we've already handled it.
713 case AsmToken::Error:
714 return true;
Daniel Dunbar3f872332009-07-28 16:08:33 +0000715 case AsmToken::Exclaim:
Sean Callanan79ed1a82010-01-19 20:22:31 +0000716 Lex(); // Eat the operator.
Chris Lattnerb4307b32010-01-15 19:28:38 +0000717 if (ParsePrimaryExpr(Res, EndLoc))
Daniel Dunbar475839e2009-06-29 20:37:27 +0000718 return true;
Daniel Dunbar6ce004d2009-08-31 08:07:44 +0000719 Res = MCUnaryExpr::CreateLNot(Res, getContext());
Daniel Dunbar475839e2009-06-29 20:37:27 +0000720 return false;
Daniel Dunbare17edff2010-08-24 19:13:42 +0000721 case AsmToken::Dollar:
Daniel Dunbar76c4d762009-07-31 21:55:09 +0000722 case AsmToken::String:
Daniel Dunbarfffff912009-10-16 01:34:54 +0000723 case AsmToken::Identifier: {
Daniel Dunbare17edff2010-08-24 19:13:42 +0000724 EndLoc = Lexer.getLoc();
725
726 StringRef Identifier;
727 if (ParseIdentifier(Identifier))
Jim Grosbach95ae09a2011-05-23 20:36:04 +0000728 return true;
Daniel Dunbare17edff2010-08-24 19:13:42 +0000729
Daniel Dunbarfffff912009-10-16 01:34:54 +0000730 // This is a symbol reference.
Daniel Dunbare17edff2010-08-24 19:13:42 +0000731 std::pair<StringRef, StringRef> Split = Identifier.split('@');
Daniel Dunbar4c7c08b2010-07-12 19:52:10 +0000732 MCSymbol *Sym = getContext().GetOrCreateSymbol(Split.first);
Daniel Dunbar4e815f82010-03-15 23:51:06 +0000733
734 // Lookup the symbol variant if used.
735 MCSymbolRefExpr::VariantKind Variant = MCSymbolRefExpr::VK_None;
Daniel Dunbarcceba832010-09-17 02:47:07 +0000736 if (Split.first.size() != Identifier.size()) {
Daniel Dunbar4e815f82010-03-15 23:51:06 +0000737 Variant = MCSymbolRefExpr::getVariantKindForName(Split.second);
Daniel Dunbarcceba832010-09-17 02:47:07 +0000738 if (Variant == MCSymbolRefExpr::VK_Invalid) {
739 Variant = MCSymbolRefExpr::VK_None;
Jim Grosbach4121e8a2011-01-19 23:06:07 +0000740 return TokError("invalid variant '" + Split.second + "'");
Daniel Dunbarcceba832010-09-17 02:47:07 +0000741 }
742 }
Daniel Dunbar4e815f82010-03-15 23:51:06 +0000743
Daniel Dunbarfffff912009-10-16 01:34:54 +0000744 // If this is an absolute variable reference, substitute it now to preserve
745 // semantics in the face of reassignment.
Daniel Dunbar08a408a2010-05-05 17:41:00 +0000746 if (Sym->isVariable() && isa<MCConstantExpr>(Sym->getVariableValue())) {
Daniel Dunbar4e815f82010-03-15 23:51:06 +0000747 if (Variant)
Daniel Dunbar603abd52010-11-08 17:53:02 +0000748 return Error(EndLoc, "unexpected modifier on variable reference");
Daniel Dunbar4e815f82010-03-15 23:51:06 +0000749
Daniel Dunbar08a408a2010-05-05 17:41:00 +0000750 Res = Sym->getVariableValue();
Daniel Dunbarfffff912009-10-16 01:34:54 +0000751 return false;
752 }
753
754 // Otherwise create a symbol ref.
Daniel Dunbar4e815f82010-03-15 23:51:06 +0000755 Res = MCSymbolRefExpr::Create(Sym, Variant, getContext());
Chris Lattnerc4193832009-06-22 05:51:26 +0000756 return false;
Daniel Dunbarfffff912009-10-16 01:34:54 +0000757 }
Kevin Enderbyebe7fcd2010-05-17 23:08:19 +0000758 case AsmToken::Integer: {
759 SMLoc Loc = getTok().getLoc();
760 int64_t IntVal = getTok().getIntVal();
761 Res = MCConstantExpr::Create(IntVal, getContext());
Chris Lattnerb4307b32010-01-15 19:28:38 +0000762 EndLoc = Lexer.getLoc();
Sean Callanan79ed1a82010-01-19 20:22:31 +0000763 Lex(); // Eat token.
Kevin Enderbyebe7fcd2010-05-17 23:08:19 +0000764 // Look for 'b' or 'f' following an Integer as a directional label
765 if (Lexer.getKind() == AsmToken::Identifier) {
766 StringRef IDVal = getTok().getString();
767 if (IDVal == "f" || IDVal == "b"){
768 MCSymbol *Sym = Ctx.GetDirectionalLocalSymbol(IntVal,
769 IDVal == "f" ? 1 : 0);
770 Res = MCSymbolRefExpr::Create(Sym, MCSymbolRefExpr::VK_None,
771 getContext());
Benjamin Kramer29739e72012-05-12 16:52:21 +0000772 if (IDVal == "b" && Sym->isUndefined())
Kevin Enderbyebe7fcd2010-05-17 23:08:19 +0000773 return Error(Loc, "invalid reference to undefined symbol");
774 EndLoc = Lexer.getLoc();
775 Lex(); // Eat identifier.
776 }
777 }
Chris Lattnerc4193832009-06-22 05:51:26 +0000778 return false;
Kevin Enderbyebe7fcd2010-05-17 23:08:19 +0000779 }
Bill Wendling69c4ef32011-01-25 21:26:41 +0000780 case AsmToken::Real: {
781 APFloat RealVal(APFloat::IEEEdouble, getTok().getString());
Bob Wilson720b9182011-02-03 23:17:47 +0000782 uint64_t IntVal = RealVal.bitcastToAPInt().getZExtValue();
Bill Wendling69c4ef32011-01-25 21:26:41 +0000783 Res = MCConstantExpr::Create(IntVal, getContext());
784 Lex(); // Eat token.
785 return false;
786 }
Chris Lattnerd3050352010-04-14 04:40:28 +0000787 case AsmToken::Dot: {
788 // This is a '.' reference, which references the current PC. Emit a
789 // temporary label to the streamer and refer to it.
790 MCSymbol *Sym = Ctx.CreateTempSymbol();
791 Out.EmitLabel(Sym);
792 Res = MCSymbolRefExpr::Create(Sym, MCSymbolRefExpr::VK_None, getContext());
793 EndLoc = Lexer.getLoc();
794 Lex(); // Eat identifier.
795 return false;
796 }
Daniel Dunbar3f872332009-07-28 16:08:33 +0000797 case AsmToken::LParen:
Sean Callanan79ed1a82010-01-19 20:22:31 +0000798 Lex(); // Eat the '('.
Chris Lattnerb4307b32010-01-15 19:28:38 +0000799 return ParseParenExpr(Res, EndLoc);
Joerg Sonnenberger93c65e62011-02-24 21:59:22 +0000800 case AsmToken::LBrac:
801 if (!PlatformParser->HasBracketExpressions())
802 return TokError("brackets expression not supported on this target");
803 Lex(); // Eat the '['.
804 return ParseBracketExpr(Res, EndLoc);
Daniel Dunbar3f872332009-07-28 16:08:33 +0000805 case AsmToken::Minus:
Sean Callanan79ed1a82010-01-19 20:22:31 +0000806 Lex(); // Eat the operator.
Chris Lattnerb4307b32010-01-15 19:28:38 +0000807 if (ParsePrimaryExpr(Res, EndLoc))
Daniel Dunbar475839e2009-06-29 20:37:27 +0000808 return true;
Daniel Dunbar6ce004d2009-08-31 08:07:44 +0000809 Res = MCUnaryExpr::CreateMinus(Res, getContext());
Daniel Dunbar475839e2009-06-29 20:37:27 +0000810 return false;
Daniel Dunbar3f872332009-07-28 16:08:33 +0000811 case AsmToken::Plus:
Sean Callanan79ed1a82010-01-19 20:22:31 +0000812 Lex(); // Eat the operator.
Chris Lattnerb4307b32010-01-15 19:28:38 +0000813 if (ParsePrimaryExpr(Res, EndLoc))
Daniel Dunbar475839e2009-06-29 20:37:27 +0000814 return true;
Daniel Dunbar6ce004d2009-08-31 08:07:44 +0000815 Res = MCUnaryExpr::CreatePlus(Res, getContext());
Daniel Dunbar475839e2009-06-29 20:37:27 +0000816 return false;
Daniel Dunbar3f872332009-07-28 16:08:33 +0000817 case AsmToken::Tilde:
Sean Callanan79ed1a82010-01-19 20:22:31 +0000818 Lex(); // Eat the operator.
Chris Lattnerb4307b32010-01-15 19:28:38 +0000819 if (ParsePrimaryExpr(Res, EndLoc))
Daniel Dunbar475839e2009-06-29 20:37:27 +0000820 return true;
Daniel Dunbar6ce004d2009-08-31 08:07:44 +0000821 Res = MCUnaryExpr::CreateNot(Res, getContext());
Daniel Dunbar475839e2009-06-29 20:37:27 +0000822 return false;
Chris Lattnerc4193832009-06-22 05:51:26 +0000823 }
824}
Chris Lattner74ec1a32009-06-22 06:32:03 +0000825
Chris Lattnerb4307b32010-01-15 19:28:38 +0000826bool AsmParser::ParseExpression(const MCExpr *&Res) {
Chris Lattner54482b42010-01-15 19:39:23 +0000827 SMLoc EndLoc;
828 return ParseExpression(Res, EndLoc);
Chris Lattnerb4307b32010-01-15 19:28:38 +0000829}
830
Daniel Dunbarcceba832010-09-17 02:47:07 +0000831const MCExpr *
832AsmParser::ApplyModifierToExpr(const MCExpr *E,
833 MCSymbolRefExpr::VariantKind Variant) {
834 // Recurse over the given expression, rebuilding it to apply the given variant
835 // if there is exactly one symbol.
836 switch (E->getKind()) {
837 case MCExpr::Target:
838 case MCExpr::Constant:
839 return 0;
840
841 case MCExpr::SymbolRef: {
842 const MCSymbolRefExpr *SRE = cast<MCSymbolRefExpr>(E);
843
844 if (SRE->getKind() != MCSymbolRefExpr::VK_None) {
845 TokError("invalid variant on expression '" +
846 getTok().getIdentifier() + "' (already modified)");
847 return E;
848 }
849
850 return MCSymbolRefExpr::Create(&SRE->getSymbol(), Variant, getContext());
851 }
852
853 case MCExpr::Unary: {
854 const MCUnaryExpr *UE = cast<MCUnaryExpr>(E);
855 const MCExpr *Sub = ApplyModifierToExpr(UE->getSubExpr(), Variant);
856 if (!Sub)
857 return 0;
858 return MCUnaryExpr::Create(UE->getOpcode(), Sub, getContext());
859 }
860
861 case MCExpr::Binary: {
862 const MCBinaryExpr *BE = cast<MCBinaryExpr>(E);
863 const MCExpr *LHS = ApplyModifierToExpr(BE->getLHS(), Variant);
864 const MCExpr *RHS = ApplyModifierToExpr(BE->getRHS(), Variant);
865
866 if (!LHS && !RHS)
867 return 0;
868
869 if (!LHS) LHS = BE->getLHS();
870 if (!RHS) RHS = BE->getRHS();
871
872 return MCBinaryExpr::Create(BE->getOpcode(), LHS, RHS, getContext());
873 }
874 }
Daniel Dunbarf3f95c92010-09-17 16:34:24 +0000875
Craig Topper85814382012-02-07 05:05:23 +0000876 llvm_unreachable("Invalid expression kind!");
Daniel Dunbarcceba832010-09-17 02:47:07 +0000877}
878
Chris Lattner74ec1a32009-06-22 06:32:03 +0000879/// ParseExpression - Parse an expression and return it.
Michael J. Spencerc0c8df32010-10-09 11:00:50 +0000880///
Jim Grosbachfbe16812011-08-20 16:24:13 +0000881/// expr ::= expr &&,|| expr -> lowest.
882/// expr ::= expr |,^,&,! expr
883/// expr ::= expr ==,!=,<>,<,<=,>,>= expr
884/// expr ::= expr <<,>> expr
885/// expr ::= expr +,- expr
886/// expr ::= expr *,/,% expr -> highest.
Chris Lattner74ec1a32009-06-22 06:32:03 +0000887/// expr ::= primaryexpr
888///
Chris Lattner54482b42010-01-15 19:39:23 +0000889bool AsmParser::ParseExpression(const MCExpr *&Res, SMLoc &EndLoc) {
Daniel Dunbare9a60eb2010-02-13 01:28:07 +0000890 // Parse the expression.
Daniel Dunbar475839e2009-06-29 20:37:27 +0000891 Res = 0;
Daniel Dunbare9a60eb2010-02-13 01:28:07 +0000892 if (ParsePrimaryExpr(Res, EndLoc) || ParseBinOpRHS(1, Res, EndLoc))
893 return true;
894
Daniel Dunbarcceba832010-09-17 02:47:07 +0000895 // As a special case, we support 'a op b @ modifier' by rewriting the
896 // expression to include the modifier. This is inefficient, but in general we
897 // expect users to use 'a@modifier op b'.
898 if (Lexer.getKind() == AsmToken::At) {
899 Lex();
900
901 if (Lexer.isNot(AsmToken::Identifier))
902 return TokError("unexpected symbol modifier following '@'");
903
904 MCSymbolRefExpr::VariantKind Variant =
905 MCSymbolRefExpr::getVariantKindForName(getTok().getIdentifier());
906 if (Variant == MCSymbolRefExpr::VK_Invalid)
907 return TokError("invalid variant '" + getTok().getIdentifier() + "'");
908
909 const MCExpr *ModifiedRes = ApplyModifierToExpr(Res, Variant);
910 if (!ModifiedRes) {
911 return TokError("invalid modifier '" + getTok().getIdentifier() +
912 "' (no symbols present)");
Daniel Dunbarcceba832010-09-17 02:47:07 +0000913 }
Michael J. Spencerc0c8df32010-10-09 11:00:50 +0000914
Daniel Dunbarcceba832010-09-17 02:47:07 +0000915 Res = ModifiedRes;
916 Lex();
917 }
918
Daniel Dunbare9a60eb2010-02-13 01:28:07 +0000919 // Try to constant fold it up front, if possible.
920 int64_t Value;
921 if (Res->EvaluateAsAbsolute(Value))
922 Res = MCConstantExpr::Create(Value, getContext());
923
924 return false;
Chris Lattner74ec1a32009-06-22 06:32:03 +0000925}
Chris Lattner8dfbe6c2009-06-23 05:57:07 +0000926
Chris Lattnerb4307b32010-01-15 19:28:38 +0000927bool AsmParser::ParseParenExpression(const MCExpr *&Res, SMLoc &EndLoc) {
Chris Lattner75f265f2010-01-24 01:07:33 +0000928 Res = 0;
929 return ParseParenExpr(Res, EndLoc) ||
930 ParseBinOpRHS(1, Res, EndLoc);
Daniel Dunbarc18274b2009-08-31 08:08:17 +0000931}
932
Daniel Dunbar475839e2009-06-29 20:37:27 +0000933bool AsmParser::ParseAbsoluteExpression(int64_t &Res) {
Daniel Dunbar9643ac52009-08-31 08:07:22 +0000934 const MCExpr *Expr;
Michael J. Spencerc0c8df32010-10-09 11:00:50 +0000935
Daniel Dunbarf4b830f2009-06-30 02:10:03 +0000936 SMLoc StartLoc = Lexer.getLoc();
Daniel Dunbar475839e2009-06-29 20:37:27 +0000937 if (ParseExpression(Expr))
938 return true;
939
Daniel Dunbare00b0112009-10-16 01:57:52 +0000940 if (!Expr->EvaluateAsAbsolute(Res))
Daniel Dunbarf4b830f2009-06-30 02:10:03 +0000941 return Error(StartLoc, "expected absolute expression");
Daniel Dunbar475839e2009-06-29 20:37:27 +0000942
943 return false;
944}
945
Michael J. Spencerc0c8df32010-10-09 11:00:50 +0000946static unsigned getBinOpPrecedence(AsmToken::TokenKind K,
Daniel Dunbar28c251b2009-08-31 08:06:59 +0000947 MCBinaryExpr::Opcode &Kind) {
Chris Lattner8dfbe6c2009-06-23 05:57:07 +0000948 switch (K) {
Daniel Dunbar6ce004d2009-08-31 08:07:44 +0000949 default:
950 return 0; // not a binop.
Daniel Dunbar475839e2009-06-29 20:37:27 +0000951
Jim Grosbachfbe16812011-08-20 16:24:13 +0000952 // Lowest Precedence: &&, ||
Daniel Dunbar3f872332009-07-28 16:08:33 +0000953 case AsmToken::AmpAmp:
Daniel Dunbar28c251b2009-08-31 08:06:59 +0000954 Kind = MCBinaryExpr::LAnd;
Chris Lattner8dfbe6c2009-06-23 05:57:07 +0000955 return 1;
Daniel Dunbar3f872332009-07-28 16:08:33 +0000956 case AsmToken::PipePipe:
Daniel Dunbar28c251b2009-08-31 08:06:59 +0000957 Kind = MCBinaryExpr::LOr;
Daniel Dunbar475839e2009-06-29 20:37:27 +0000958 return 1;
959
Michael J. Spencerc0c8df32010-10-09 11:00:50 +0000960
Chris Lattnerf7d4da02010-09-22 05:05:16 +0000961 // Low Precedence: |, &, ^
Daniel Dunbar475839e2009-06-29 20:37:27 +0000962 //
963 // FIXME: gas seems to support '!' as an infix operator?
Daniel Dunbar3f872332009-07-28 16:08:33 +0000964 case AsmToken::Pipe:
Daniel Dunbar28c251b2009-08-31 08:06:59 +0000965 Kind = MCBinaryExpr::Or;
Chris Lattnerf7d4da02010-09-22 05:05:16 +0000966 return 2;
Daniel Dunbar3f872332009-07-28 16:08:33 +0000967 case AsmToken::Caret:
Daniel Dunbar28c251b2009-08-31 08:06:59 +0000968 Kind = MCBinaryExpr::Xor;
Chris Lattnerf7d4da02010-09-22 05:05:16 +0000969 return 2;
Daniel Dunbar3f872332009-07-28 16:08:33 +0000970 case AsmToken::Amp:
Daniel Dunbar28c251b2009-08-31 08:06:59 +0000971 Kind = MCBinaryExpr::And;
Chris Lattnerf7d4da02010-09-22 05:05:16 +0000972 return 2;
Michael J. Spencerc0c8df32010-10-09 11:00:50 +0000973
Daniel Dunbarb1e0f762010-10-25 20:18:56 +0000974 // Low Intermediate Precedence: ==, !=, <>, <, <=, >, >=
Chris Lattnerf7d4da02010-09-22 05:05:16 +0000975 case AsmToken::EqualEqual:
976 Kind = MCBinaryExpr::EQ;
977 return 3;
978 case AsmToken::ExclaimEqual:
979 case AsmToken::LessGreater:
980 Kind = MCBinaryExpr::NE;
981 return 3;
982 case AsmToken::Less:
983 Kind = MCBinaryExpr::LT;
984 return 3;
985 case AsmToken::LessEqual:
986 Kind = MCBinaryExpr::LTE;
987 return 3;
988 case AsmToken::Greater:
989 Kind = MCBinaryExpr::GT;
990 return 3;
991 case AsmToken::GreaterEqual:
992 Kind = MCBinaryExpr::GTE;
Daniel Dunbar475839e2009-06-29 20:37:27 +0000993 return 3;
994
Jim Grosbachfbe16812011-08-20 16:24:13 +0000995 // Intermediate Precedence: <<, >>
996 case AsmToken::LessLess:
997 Kind = MCBinaryExpr::Shl;
998 return 4;
999 case AsmToken::GreaterGreater:
1000 Kind = MCBinaryExpr::Shr;
1001 return 4;
1002
Daniel Dunbarb1e0f762010-10-25 20:18:56 +00001003 // High Intermediate Precedence: +, -
1004 case AsmToken::Plus:
1005 Kind = MCBinaryExpr::Add;
Jim Grosbachfbe16812011-08-20 16:24:13 +00001006 return 5;
Daniel Dunbarb1e0f762010-10-25 20:18:56 +00001007 case AsmToken::Minus:
1008 Kind = MCBinaryExpr::Sub;
Jim Grosbachfbe16812011-08-20 16:24:13 +00001009 return 5;
Daniel Dunbarb1e0f762010-10-25 20:18:56 +00001010
Jim Grosbachfbe16812011-08-20 16:24:13 +00001011 // Highest Precedence: *, /, %
Daniel Dunbar3f872332009-07-28 16:08:33 +00001012 case AsmToken::Star:
Daniel Dunbar28c251b2009-08-31 08:06:59 +00001013 Kind = MCBinaryExpr::Mul;
Jim Grosbachfbe16812011-08-20 16:24:13 +00001014 return 6;
Daniel Dunbar3f872332009-07-28 16:08:33 +00001015 case AsmToken::Slash:
Daniel Dunbar28c251b2009-08-31 08:06:59 +00001016 Kind = MCBinaryExpr::Div;
Jim Grosbachfbe16812011-08-20 16:24:13 +00001017 return 6;
Daniel Dunbar3f872332009-07-28 16:08:33 +00001018 case AsmToken::Percent:
Daniel Dunbar28c251b2009-08-31 08:06:59 +00001019 Kind = MCBinaryExpr::Mod;
Jim Grosbachfbe16812011-08-20 16:24:13 +00001020 return 6;
Chris Lattner8dfbe6c2009-06-23 05:57:07 +00001021 }
1022}
1023
1024
1025/// ParseBinOpRHS - Parse all binary operators with precedence >= 'Precedence'.
1026/// Res contains the LHS of the expression on input.
Chris Lattnerb4307b32010-01-15 19:28:38 +00001027bool AsmParser::ParseBinOpRHS(unsigned Precedence, const MCExpr *&Res,
1028 SMLoc &EndLoc) {
Chris Lattner8dfbe6c2009-06-23 05:57:07 +00001029 while (1) {
Daniel Dunbar28c251b2009-08-31 08:06:59 +00001030 MCBinaryExpr::Opcode Kind = MCBinaryExpr::Add;
Daniel Dunbar475839e2009-06-29 20:37:27 +00001031 unsigned TokPrec = getBinOpPrecedence(Lexer.getKind(), Kind);
Michael J. Spencerc0c8df32010-10-09 11:00:50 +00001032
Chris Lattner8dfbe6c2009-06-23 05:57:07 +00001033 // If the next token is lower precedence than we are allowed to eat, return
1034 // successfully with what we ate already.
1035 if (TokPrec < Precedence)
1036 return false;
Michael J. Spencerc0c8df32010-10-09 11:00:50 +00001037
Sean Callanan79ed1a82010-01-19 20:22:31 +00001038 Lex();
Michael J. Spencerc0c8df32010-10-09 11:00:50 +00001039
Chris Lattner8dfbe6c2009-06-23 05:57:07 +00001040 // Eat the next primary expression.
Daniel Dunbar9643ac52009-08-31 08:07:22 +00001041 const MCExpr *RHS;
Chris Lattnerb4307b32010-01-15 19:28:38 +00001042 if (ParsePrimaryExpr(RHS, EndLoc)) return true;
Michael J. Spencerc0c8df32010-10-09 11:00:50 +00001043
Chris Lattner8dfbe6c2009-06-23 05:57:07 +00001044 // If BinOp binds less tightly with RHS than the operator after RHS, let
1045 // the pending operator take RHS as its LHS.
Daniel Dunbar28c251b2009-08-31 08:06:59 +00001046 MCBinaryExpr::Opcode Dummy;
Daniel Dunbar475839e2009-06-29 20:37:27 +00001047 unsigned NextTokPrec = getBinOpPrecedence(Lexer.getKind(), Dummy);
Chris Lattner8dfbe6c2009-06-23 05:57:07 +00001048 if (TokPrec < NextTokPrec) {
Chris Lattnerb4307b32010-01-15 19:28:38 +00001049 if (ParseBinOpRHS(Precedence+1, RHS, EndLoc)) return true;
Chris Lattner8dfbe6c2009-06-23 05:57:07 +00001050 }
1051
Daniel Dunbar475839e2009-06-29 20:37:27 +00001052 // Merge LHS and RHS according to operator.
Daniel Dunbar6ce004d2009-08-31 08:07:44 +00001053 Res = MCBinaryExpr::Create(Kind, Res, RHS, getContext());
Chris Lattner8dfbe6c2009-06-23 05:57:07 +00001054 }
1055}
1056
Chris Lattnerb0789ed2009-06-21 20:54:55 +00001057/// ParseStatement:
1058/// ::= EndOfStatement
Chris Lattner2cf5f142009-06-22 01:29:09 +00001059/// ::= Label* Directive ...Operands... EndOfStatement
1060/// ::= Label* Identifier OperandList* EndOfStatement
Chris Lattnerb0789ed2009-06-21 20:54:55 +00001061bool AsmParser::ParseStatement() {
Daniel Dunbara6b3c5d2009-08-01 00:48:30 +00001062 if (Lexer.is(AsmToken::EndOfStatement)) {
Daniel Dunbar01777ff2010-05-23 18:36:34 +00001063 Out.AddBlankLine();
Sean Callanan79ed1a82010-01-19 20:22:31 +00001064 Lex();
Chris Lattnerb0789ed2009-06-21 20:54:55 +00001065 return false;
Chris Lattnerb0789ed2009-06-21 20:54:55 +00001066 }
Daniel Dunbara6b3c5d2009-08-01 00:48:30 +00001067
Kevin Enderbyd82ed5b2010-12-24 00:12:02 +00001068 // Statements always start with an identifier or are a full line comment.
Sean Callanan18b83232010-01-19 21:44:56 +00001069 AsmToken ID = getTok();
Daniel Dunbar419aded2009-07-28 16:38:40 +00001070 SMLoc IDLoc = ID.getLoc();
Daniel Dunbara6b3c5d2009-08-01 00:48:30 +00001071 StringRef IDVal;
Kevin Enderbyebe7fcd2010-05-17 23:08:19 +00001072 int64_t LocalLabelVal = -1;
Kevin Enderbyd82ed5b2010-12-24 00:12:02 +00001073 // A full line comment is a '#' as the first token.
Kevin Enderbyf1c21a82011-09-13 23:45:18 +00001074 if (Lexer.is(AsmToken::Hash))
1075 return ParseCppHashLineFilenameComment(IDLoc);
Daniel Dunbar0143ac12011-03-25 17:47:14 +00001076
Kevin Enderbyd82ed5b2010-12-24 00:12:02 +00001077 // Allow an integer followed by a ':' as a directional local label.
Kevin Enderbyebe7fcd2010-05-17 23:08:19 +00001078 if (Lexer.is(AsmToken::Integer)) {
1079 LocalLabelVal = getTok().getIntVal();
1080 if (LocalLabelVal < 0) {
1081 if (!TheCondState.Ignore)
1082 return TokError("unexpected token at start of statement");
1083 IDVal = "";
1084 }
1085 else {
1086 IDVal = getTok().getString();
1087 Lex(); // Consume the integer token to be used as an identifier token.
1088 if (Lexer.getKind() != AsmToken::Colon) {
Duncan Sands34727662010-07-12 08:16:59 +00001089 if (!TheCondState.Ignore)
1090 return TokError("unexpected token at start of statement");
Kevin Enderbyebe7fcd2010-05-17 23:08:19 +00001091 }
1092 }
Daniel Dunbar8b2b43c2011-03-25 17:47:17 +00001093
1094 } else if (Lexer.is(AsmToken::Dot)) {
1095 // Treat '.' as a valid identifier in this context.
1096 Lex();
1097 IDVal = ".";
1098
Daniel Dunbar0143ac12011-03-25 17:47:14 +00001099 } else if (ParseIdentifier(IDVal)) {
Chris Lattner7834fac2010-04-17 18:14:27 +00001100 if (!TheCondState.Ignore)
1101 return TokError("unexpected token at start of statement");
1102 IDVal = "";
1103 }
Daniel Dunbara6b3c5d2009-08-01 00:48:30 +00001104
Daniel Dunbar8b2b43c2011-03-25 17:47:17 +00001105
Chris Lattner7834fac2010-04-17 18:14:27 +00001106 // Handle conditional assembly here before checking for skipping. We
1107 // have to do this so that .endif isn't skipped in a ".if 0" block for
1108 // example.
1109 if (IDVal == ".if")
1110 return ParseDirectiveIf(IDLoc);
Benjamin Kramera3dd0eb2012-05-12 11:18:42 +00001111 if (IDVal == ".ifb")
1112 return ParseDirectiveIfb(IDLoc, true);
1113 if (IDVal == ".ifnb")
1114 return ParseDirectiveIfb(IDLoc, false);
Benjamin Kramerdec06ef2012-05-12 11:18:51 +00001115 if (IDVal == ".ifc")
1116 return ParseDirectiveIfc(IDLoc, true);
1117 if (IDVal == ".ifnc")
1118 return ParseDirectiveIfc(IDLoc, false);
Benjamin Kramer0fd90bc2011-02-08 22:29:56 +00001119 if (IDVal == ".ifdef")
1120 return ParseDirectiveIfdef(IDLoc, true);
1121 if (IDVal == ".ifndef" || IDVal == ".ifnotdef")
1122 return ParseDirectiveIfdef(IDLoc, false);
Chris Lattner7834fac2010-04-17 18:14:27 +00001123 if (IDVal == ".elseif")
1124 return ParseDirectiveElseIf(IDLoc);
1125 if (IDVal == ".else")
1126 return ParseDirectiveElse(IDLoc);
1127 if (IDVal == ".endif")
1128 return ParseDirectiveEndIf(IDLoc);
Michael J. Spencerc0c8df32010-10-09 11:00:50 +00001129
Chris Lattner7834fac2010-04-17 18:14:27 +00001130 // If we are in a ".if 0" block, ignore this statement.
1131 if (TheCondState.Ignore) {
1132 EatToEndOfStatement();
1133 return false;
1134 }
Michael J. Spencerc0c8df32010-10-09 11:00:50 +00001135
Daniel Dunbara6b3c5d2009-08-01 00:48:30 +00001136 // FIXME: Recurse on local labels?
1137
1138 // See what kind of statement we have.
1139 switch (Lexer.getKind()) {
Daniel Dunbar3f872332009-07-28 16:08:33 +00001140 case AsmToken::Colon: {
Daniel Dunbar1ab6f2f2010-09-09 22:42:59 +00001141 CheckForValidSection();
1142
Chris Lattnerb0789ed2009-06-21 20:54:55 +00001143 // identifier ':' -> Label.
Sean Callanan79ed1a82010-01-19 20:22:31 +00001144 Lex();
Daniel Dunbardce0f3c2009-06-29 23:43:14 +00001145
Daniel Dunbar8b2b43c2011-03-25 17:47:17 +00001146 // Diagnose attempt to use '.' as a label.
1147 if (IDVal == ".")
1148 return Error(IDLoc, "invalid use of pseudo-symbol '.' as a label");
1149
Daniel Dunbardce0f3c2009-06-29 23:43:14 +00001150 // Diagnose attempt to use a variable as a label.
1151 //
1152 // FIXME: Diagnostics. Note the location of the definition as a label.
1153 // FIXME: This doesn't diagnose assignment to a symbol which has been
1154 // implicitly marked as external.
Kevin Enderbyebe7fcd2010-05-17 23:08:19 +00001155 MCSymbol *Sym;
1156 if (LocalLabelVal == -1)
Daniel Dunbar4c7c08b2010-07-12 19:52:10 +00001157 Sym = getContext().GetOrCreateSymbol(IDVal);
Kevin Enderbyebe7fcd2010-05-17 23:08:19 +00001158 else
1159 Sym = Ctx.CreateDirectionalLocalSymbol(LocalLabelVal);
Daniel Dunbarc3047182010-05-05 19:01:00 +00001160 if (!Sym->isUndefined() || Sym->isVariable())
Daniel Dunbardce0f3c2009-06-29 23:43:14 +00001161 return Error(IDLoc, "invalid symbol redefinition");
Michael J. Spencerc0c8df32010-10-09 11:00:50 +00001162
Daniel Dunbar959fd882009-08-26 22:13:22 +00001163 // Emit the label.
Daniel Dunbardce0f3c2009-06-29 23:43:14 +00001164 Out.EmitLabel(Sym);
Michael J. Spencerc0c8df32010-10-09 11:00:50 +00001165
Kevin Enderby94c2e852011-12-09 18:09:40 +00001166 // If we are generating dwarf for assembly source files then gather the
Kevin Enderby11c2def2012-01-10 21:12:34 +00001167 // info to make a dwarf label entry for this label if needed.
Kevin Enderby94c2e852011-12-09 18:09:40 +00001168 if (getContext().getGenDwarfForAssembly())
Kevin Enderby11c2def2012-01-10 21:12:34 +00001169 MCGenDwarfLabelEntry::Make(Sym, &getStreamer(), getSourceManager(),
1170 IDLoc);
Kevin Enderby94c2e852011-12-09 18:09:40 +00001171
Daniel Dunbar01777ff2010-05-23 18:36:34 +00001172 // Consume any end of statement token, if present, to avoid spurious
1173 // AddBlankLine calls().
1174 if (Lexer.is(AsmToken::EndOfStatement)) {
1175 Lex();
1176 if (Lexer.is(AsmToken::Eof))
1177 return false;
1178 }
1179
Chris Lattnerb0789ed2009-06-21 20:54:55 +00001180 return ParseStatement();
Daniel Dunbardce0f3c2009-06-29 23:43:14 +00001181 }
Daniel Dunbar8f780cd2009-06-25 21:56:11 +00001182
Daniel Dunbar3f872332009-07-28 16:08:33 +00001183 case AsmToken::Equal:
Daniel Dunbar8f780cd2009-06-25 21:56:11 +00001184 // identifier '=' ... -> assignment statement
Sean Callanan79ed1a82010-01-19 20:22:31 +00001185 Lex();
Daniel Dunbar8f780cd2009-06-25 21:56:11 +00001186
Nico Weber4c4c7322011-01-28 03:04:41 +00001187 return ParseAssignment(IDVal, true);
Daniel Dunbar8f780cd2009-06-25 21:56:11 +00001188
1189 default: // Normal instruction or directive.
1190 break;
Chris Lattnerb0789ed2009-06-21 20:54:55 +00001191 }
Daniel Dunbarc64a0d72010-07-18 18:54:11 +00001192
1193 // If macros are enabled, check to see if this is a macro instantiation.
1194 if (MacrosEnabled)
1195 if (const Macro *M = MacroMap.lookup(IDVal))
1196 return HandleMacroEntry(IDVal, IDLoc, M);
1197
Michael J. Spencerc0c8df32010-10-09 11:00:50 +00001198 // Otherwise, we have a normal instruction or directive.
Daniel Dunbar8b2b43c2011-03-25 17:47:17 +00001199 if (IDVal[0] == '.' && IDVal != ".") {
Akira Hatanaka3b02d952012-07-05 19:09:33 +00001200
1201 // Target hook for parsing target specific directives.
1202 if (!getTargetParser().ParseDirective(ID))
1203 return false;
1204
Daniel Dunbar8f780cd2009-06-25 21:56:11 +00001205 // Assembler features
Roman Divacky50e7a782010-10-28 16:22:58 +00001206 if (IDVal == ".set" || IDVal == ".equ")
Nico Weber4c4c7322011-01-28 03:04:41 +00001207 return ParseDirectiveSet(IDVal, true);
1208 if (IDVal == ".equiv")
1209 return ParseDirectiveSet(IDVal, false);
Daniel Dunbar8f780cd2009-06-25 21:56:11 +00001210
Daniel Dunbara0d14262009-06-24 23:30:00 +00001211 // Data directives
1212
Daniel Dunbar9a7e2cc2009-07-27 21:49:56 +00001213 if (IDVal == ".ascii")
Rafael Espindola787c3372010-10-28 20:02:27 +00001214 return ParseDirectiveAscii(IDVal, false);
1215 if (IDVal == ".asciz" || IDVal == ".string")
1216 return ParseDirectiveAscii(IDVal, true);
Daniel Dunbara0d14262009-06-24 23:30:00 +00001217
Daniel Dunbar9a7e2cc2009-07-27 21:49:56 +00001218 if (IDVal == ".byte")
Daniel Dunbara0d14262009-06-24 23:30:00 +00001219 return ParseDirectiveValue(1);
Kevin Enderby9c656452009-09-10 20:51:44 +00001220 if (IDVal == ".short")
Daniel Dunbara0d14262009-06-24 23:30:00 +00001221 return ParseDirectiveValue(2);
Rafael Espindolacc3acee2010-11-01 15:29:07 +00001222 if (IDVal == ".value")
1223 return ParseDirectiveValue(2);
Rafael Espindola110f22a2010-11-17 16:15:42 +00001224 if (IDVal == ".2byte")
1225 return ParseDirectiveValue(2);
Daniel Dunbar9a7e2cc2009-07-27 21:49:56 +00001226 if (IDVal == ".long")
Daniel Dunbara0d14262009-06-24 23:30:00 +00001227 return ParseDirectiveValue(4);
Rafael Espindola435279b2010-11-17 16:24:40 +00001228 if (IDVal == ".int")
1229 return ParseDirectiveValue(4);
Rafael Espindola110f22a2010-11-17 16:15:42 +00001230 if (IDVal == ".4byte")
1231 return ParseDirectiveValue(4);
Daniel Dunbar9a7e2cc2009-07-27 21:49:56 +00001232 if (IDVal == ".quad")
Daniel Dunbara0d14262009-06-24 23:30:00 +00001233 return ParseDirectiveValue(8);
Rafael Espindola110f22a2010-11-17 16:15:42 +00001234 if (IDVal == ".8byte")
1235 return ParseDirectiveValue(8);
Roman Divacky14e66552011-01-28 14:20:32 +00001236 if (IDVal == ".single" || IDVal == ".float")
Daniel Dunbarb95a0792010-09-24 01:59:56 +00001237 return ParseDirectiveRealValue(APFloat::IEEEsingle);
1238 if (IDVal == ".double")
1239 return ParseDirectiveRealValue(APFloat::IEEEdouble);
Daniel Dunbarc29dfa72009-06-29 23:46:59 +00001240
Eli Friedman5d68ec22010-07-19 04:17:25 +00001241 if (IDVal == ".align") {
1242 bool IsPow2 = !getContext().getAsmInfo().getAlignmentIsInBytes();
1243 return ParseDirectiveAlign(IsPow2, /*ExprSize=*/1);
1244 }
1245 if (IDVal == ".align32") {
1246 bool IsPow2 = !getContext().getAsmInfo().getAlignmentIsInBytes();
1247 return ParseDirectiveAlign(IsPow2, /*ExprSize=*/4);
1248 }
Daniel Dunbar9a7e2cc2009-07-27 21:49:56 +00001249 if (IDVal == ".balign")
Daniel Dunbarc29dfa72009-06-29 23:46:59 +00001250 return ParseDirectiveAlign(/*IsPow2=*/false, /*ExprSize=*/1);
Daniel Dunbar9a7e2cc2009-07-27 21:49:56 +00001251 if (IDVal == ".balignw")
Daniel Dunbarc29dfa72009-06-29 23:46:59 +00001252 return ParseDirectiveAlign(/*IsPow2=*/false, /*ExprSize=*/2);
Daniel Dunbar9a7e2cc2009-07-27 21:49:56 +00001253 if (IDVal == ".balignl")
Daniel Dunbarc29dfa72009-06-29 23:46:59 +00001254 return ParseDirectiveAlign(/*IsPow2=*/false, /*ExprSize=*/4);
Daniel Dunbar9a7e2cc2009-07-27 21:49:56 +00001255 if (IDVal == ".p2align")
Daniel Dunbarc29dfa72009-06-29 23:46:59 +00001256 return ParseDirectiveAlign(/*IsPow2=*/true, /*ExprSize=*/1);
Daniel Dunbar9a7e2cc2009-07-27 21:49:56 +00001257 if (IDVal == ".p2alignw")
Daniel Dunbarc29dfa72009-06-29 23:46:59 +00001258 return ParseDirectiveAlign(/*IsPow2=*/true, /*ExprSize=*/2);
Daniel Dunbar9a7e2cc2009-07-27 21:49:56 +00001259 if (IDVal == ".p2alignl")
Daniel Dunbarc29dfa72009-06-29 23:46:59 +00001260 return ParseDirectiveAlign(/*IsPow2=*/true, /*ExprSize=*/4);
1261
Daniel Dunbar9a7e2cc2009-07-27 21:49:56 +00001262 if (IDVal == ".org")
Daniel Dunbarc238b582009-06-25 22:44:51 +00001263 return ParseDirectiveOrg();
Daniel Dunbarc29dfa72009-06-29 23:46:59 +00001264
Daniel Dunbar9a7e2cc2009-07-27 21:49:56 +00001265 if (IDVal == ".fill")
Daniel Dunbarc29dfa72009-06-29 23:46:59 +00001266 return ParseDirectiveFill();
Rafael Espindolace8463f2011-04-07 20:26:23 +00001267 if (IDVal == ".space" || IDVal == ".skip")
Daniel Dunbara0d14262009-06-24 23:30:00 +00001268 return ParseDirectiveSpace();
Rafael Espindola2ea2ac72010-09-16 15:03:59 +00001269 if (IDVal == ".zero")
1270 return ParseDirectiveZero();
Daniel Dunbara0d14262009-06-24 23:30:00 +00001271
Daniel Dunbard7b267b2009-06-30 00:33:19 +00001272 // Symbol attribute directives
Daniel Dunbard0c14d62009-08-11 04:24:50 +00001273
Benjamin Kramere14a3c52012-05-12 11:18:59 +00001274 if (IDVal == ".extern") {
1275 EatToEndOfStatement(); // .extern is the default, ignore it.
1276 return false;
1277 }
Daniel Dunbar9a7e2cc2009-07-27 21:49:56 +00001278 if (IDVal == ".globl" || IDVal == ".global")
Chris Lattnera5ad93a2010-01-23 06:39:22 +00001279 return ParseDirectiveSymbolAttribute(MCSA_Global);
Daniel Dunbar9a7e2cc2009-07-27 21:49:56 +00001280 if (IDVal == ".indirect_symbol")
Chris Lattnera5ad93a2010-01-23 06:39:22 +00001281 return ParseDirectiveSymbolAttribute(MCSA_IndirectSymbol);
Daniel Dunbar9a7e2cc2009-07-27 21:49:56 +00001282 if (IDVal == ".lazy_reference")
Chris Lattnera5ad93a2010-01-23 06:39:22 +00001283 return ParseDirectiveSymbolAttribute(MCSA_LazyReference);
Daniel Dunbar9a7e2cc2009-07-27 21:49:56 +00001284 if (IDVal == ".no_dead_strip")
Chris Lattnera5ad93a2010-01-23 06:39:22 +00001285 return ParseDirectiveSymbolAttribute(MCSA_NoDeadStrip);
Kevin Enderbye8e98d72010-11-19 18:39:33 +00001286 if (IDVal == ".symbol_resolver")
1287 return ParseDirectiveSymbolAttribute(MCSA_SymbolResolver);
Daniel Dunbar9a7e2cc2009-07-27 21:49:56 +00001288 if (IDVal == ".private_extern")
Chris Lattnera5ad93a2010-01-23 06:39:22 +00001289 return ParseDirectiveSymbolAttribute(MCSA_PrivateExtern);
Daniel Dunbar9a7e2cc2009-07-27 21:49:56 +00001290 if (IDVal == ".reference")
Chris Lattnera5ad93a2010-01-23 06:39:22 +00001291 return ParseDirectiveSymbolAttribute(MCSA_Reference);
Daniel Dunbar9a7e2cc2009-07-27 21:49:56 +00001292 if (IDVal == ".weak_definition")
Chris Lattnera5ad93a2010-01-23 06:39:22 +00001293 return ParseDirectiveSymbolAttribute(MCSA_WeakDefinition);
Daniel Dunbar9a7e2cc2009-07-27 21:49:56 +00001294 if (IDVal == ".weak_reference")
Chris Lattnera5ad93a2010-01-23 06:39:22 +00001295 return ParseDirectiveSymbolAttribute(MCSA_WeakReference);
Kevin Enderbyf59cac52010-07-08 17:22:42 +00001296 if (IDVal == ".weak_def_can_be_hidden")
1297 return ParseDirectiveSymbolAttribute(MCSA_WeakDefAutoPrivate);
Daniel Dunbard7b267b2009-06-30 00:33:19 +00001298
Hans Wennborg5cc64912011-06-18 13:51:54 +00001299 if (IDVal == ".comm" || IDVal == ".common")
Chris Lattner1fc3d752009-07-09 17:25:12 +00001300 return ParseDirectiveComm(/*IsLocal=*/false);
Daniel Dunbar9a7e2cc2009-07-27 21:49:56 +00001301 if (IDVal == ".lcomm")
Chris Lattner1fc3d752009-07-09 17:25:12 +00001302 return ParseDirectiveComm(/*IsLocal=*/true);
Chris Lattner4e4db7a2009-07-07 20:30:46 +00001303
Daniel Dunbar9a7e2cc2009-07-27 21:49:56 +00001304 if (IDVal == ".abort")
Kevin Enderby5f1f0b82009-07-13 23:15:14 +00001305 return ParseDirectiveAbort();
Daniel Dunbar9a7e2cc2009-07-27 21:49:56 +00001306 if (IDVal == ".include")
Kevin Enderby1f049b22009-07-14 23:21:55 +00001307 return ParseDirectiveInclude();
Kevin Enderbyc55acca2011-12-14 21:47:48 +00001308 if (IDVal == ".incbin")
1309 return ParseDirectiveIncbin();
Kevin Enderbya5c78322009-07-13 21:03:15 +00001310
Benjamin Kramer5cdf0ad2012-05-12 11:19:04 +00001311 if (IDVal == ".code16" || IDVal == ".code16gcc")
Roman Divackyf6fbd842011-01-31 20:56:49 +00001312 return TokError(Twine(IDVal) + " not supported yet");
Roman Divackycb727802011-01-28 19:29:48 +00001313
Rafael Espindola761cb062012-06-03 23:57:14 +00001314 // Macro-like directives
Rafael Espindola2ec304c2012-05-12 16:31:10 +00001315 if (IDVal == ".rept")
1316 return ParseDirectiveRept(IDLoc);
Rafael Espindolaaa7a2f22012-06-15 14:02:34 +00001317 if (IDVal == ".irp")
1318 return ParseDirectiveIrp(IDLoc);
Rafael Espindolafc9216e2012-06-16 18:03:25 +00001319 if (IDVal == ".irpc")
1320 return ParseDirectiveIrpc(IDLoc);
Rafael Espindola2ec304c2012-05-12 16:31:10 +00001321 if (IDVal == ".endr")
Rafael Espindola761cb062012-06-03 23:57:14 +00001322 return ParseDirectiveEndr(IDLoc);
Rafael Espindola2ec304c2012-05-12 16:31:10 +00001323
Daniel Dunbar81ea00f2010-07-12 17:54:38 +00001324 // Look up the handler in the handler table.
1325 std::pair<MCAsmParserExtension*, DirectiveHandler> Handler =
1326 DirectiveMap.lookup(IDVal);
1327 if (Handler.first)
Daniel Dunbar1edf6ca2010-07-18 22:22:07 +00001328 return (*Handler.second)(Handler.first, IDVal, IDLoc);
Daniel Dunbar81ea00f2010-07-12 17:54:38 +00001329
Kevin Enderby9c656452009-09-10 20:51:44 +00001330
Jim Grosbach686c0182012-05-01 18:38:27 +00001331 return Error(IDLoc, "unknown directive");
Chris Lattner2cf5f142009-06-22 01:29:09 +00001332 }
Chris Lattnerb0789ed2009-06-21 20:54:55 +00001333
Daniel Dunbar1ab6f2f2010-09-09 22:42:59 +00001334 CheckForValidSection();
1335
Chris Lattnera7f13542010-05-19 23:34:33 +00001336 // Canonicalize the opcode to lower case.
Chad Rosier8f138d12012-10-15 17:19:13 +00001337 SmallString<128> OpcodeStr;
Chris Lattnera7f13542010-05-19 23:34:33 +00001338 for (unsigned i = 0, e = IDVal.size(); i != e; ++i)
Chad Rosier8f138d12012-10-15 17:19:13 +00001339 OpcodeStr.push_back(tolower(IDVal[i]));
Michael J. Spencerc0c8df32010-10-09 11:00:50 +00001340
Chad Rosier8f138d12012-10-15 17:19:13 +00001341 bool HadError = getTargetParser().ParseInstruction(OpcodeStr.str(), IDLoc,
Daniel Dunbar31e8e1d2010-05-04 00:33:07 +00001342 ParsedOperands);
Chris Lattner2cf5f142009-06-22 01:29:09 +00001343
Daniel Dunbar3c14ca42010-08-11 06:37:09 +00001344 // Dump the parsed representation, if requested.
1345 if (getShowParsedOperands()) {
1346 SmallString<256> Str;
1347 raw_svector_ostream OS(Str);
1348 OS << "parsed instruction: [";
1349 for (unsigned i = 0; i != ParsedOperands.size(); ++i) {
1350 if (i != 0)
1351 OS << ", ";
Jim Grosbachb7f689b2011-07-13 15:34:57 +00001352 ParsedOperands[i]->print(OS);
Daniel Dunbar3c14ca42010-08-11 06:37:09 +00001353 }
1354 OS << "]";
1355
Chris Lattner3f2d5f62011-10-16 05:43:57 +00001356 PrintMessage(IDLoc, SourceMgr::DK_Note, OS.str());
Daniel Dunbar3c14ca42010-08-11 06:37:09 +00001357 }
1358
Kevin Enderby613b7572011-11-01 22:27:22 +00001359 // If we are generating dwarf for assembly source files and the current
1360 // section is the initial text section then generate a .loc directive for
1361 // the instruction.
1362 if (!HadError && getContext().getGenDwarfForAssembly() &&
1363 getContext().getGenDwarfSection() == getStreamer().getCurrentSection() ) {
1364 getStreamer().EmitDwarfLocDirective(getContext().getGenDwarfFileNumber(),
1365 SrcMgr.FindLineNumber(IDLoc, CurBuffer),
1366 0, DWARF2_LINE_DEFAULT_IS_STMT ?
Kevin Enderbydba9a172011-11-02 17:56:38 +00001367 DWARF2_FLAG_IS_STMT : 0, 0, 0,
Kevin Enderby613b7572011-11-01 22:27:22 +00001368 StringRef());
1369 }
1370
Daniel Dunbar31e8e1d2010-05-04 00:33:07 +00001371 // If parsing succeeded, match the instruction.
Chad Rosier84125ca2012-10-13 00:26:04 +00001372 if (!HadError) {
Chad Rosier84125ca2012-10-13 00:26:04 +00001373 unsigned ErrorInfo;
1374 HadError = getTargetParser().MatchAndEmitInstruction(IDLoc, Opcode,
Chad Rosier8f138d12012-10-15 17:19:13 +00001375 ParsedOperands, Out,
1376 ErrorInfo,
Chad Rosier84125ca2012-10-13 00:26:04 +00001377 ParsingInlineAsm);
1378 }
Chris Lattner98986712010-01-14 22:21:20 +00001379
Chad Rosier8f138d12012-10-15 17:19:13 +00001380 // Free any parsed operands. If parsing ms-style inline assembly it is the
1381 // responsibility of the caller (i.e., clang) to free the parsed operands.
1382 if (!ParsingInlineAsm)
1383 freeParsedOperands();
Chris Lattner98986712010-01-14 22:21:20 +00001384
Chris Lattnercbf8a982010-09-11 16:18:25 +00001385 // Don't skip the rest of the line, the instruction parser is responsible for
1386 // that.
1387 return false;
Chris Lattner27aa7d22009-06-21 20:16:42 +00001388}
Chris Lattner9a023f72009-06-24 04:43:34 +00001389
Kevin Enderbyf1c21a82011-09-13 23:45:18 +00001390/// EatToEndOfLine uses the Lexer to eat the characters to the end of the line
1391/// since they may not be able to be tokenized to get to the end of line token.
1392void AsmParser::EatToEndOfLine() {
Rafael Espindola12ae5272011-10-19 18:48:52 +00001393 if (!Lexer.is(AsmToken::EndOfStatement))
1394 Lexer.LexUntilEndOfLine();
Kevin Enderbyf1c21a82011-09-13 23:45:18 +00001395 // Eat EOL.
1396 Lex();
1397}
1398
1399/// ParseCppHashLineFilenameComment as this:
1400/// ::= # number "filename"
1401/// or just as a full line comment if it doesn't have a number and a string.
1402bool AsmParser::ParseCppHashLineFilenameComment(const SMLoc &L) {
1403 Lex(); // Eat the hash token.
1404
1405 if (getLexer().isNot(AsmToken::Integer)) {
1406 // Consume the line since in cases it is not a well-formed line directive,
1407 // as if were simply a full line comment.
1408 EatToEndOfLine();
1409 return false;
1410 }
1411
1412 int64_t LineNumber = getTok().getIntVal();
Kevin Enderbyf1c21a82011-09-13 23:45:18 +00001413 Lex();
1414
1415 if (getLexer().isNot(AsmToken::String)) {
1416 EatToEndOfLine();
1417 return false;
1418 }
1419
1420 StringRef Filename = getTok().getString();
1421 // Get rid of the enclosing quotes.
1422 Filename = Filename.substr(1, Filename.size()-2);
1423
Kevin Enderbyacbaecd2011-10-12 21:38:39 +00001424 // Save the SMLoc, Filename and LineNumber for later use by diagnostics.
1425 CppHashLoc = L;
1426 CppHashFilename = Filename;
1427 CppHashLineNumber = LineNumber;
Kevin Enderbyf1c21a82011-09-13 23:45:18 +00001428
1429 // Ignore any trailing characters, they're just comment.
1430 EatToEndOfLine();
1431 return false;
1432}
1433
Sylvestre Ledruc8e41c52012-07-23 08:51:15 +00001434/// DiagHandler - will use the last parsed cpp hash line filename comment
Kevin Enderbyacbaecd2011-10-12 21:38:39 +00001435/// for the Filename and LineNo if any in the diagnostic.
1436void AsmParser::DiagHandler(const SMDiagnostic &Diag, void *Context) {
1437 const AsmParser *Parser = static_cast<const AsmParser*>(Context);
1438 raw_ostream &OS = errs();
1439
1440 const SourceMgr &DiagSrcMgr = *Diag.getSourceMgr();
1441 const SMLoc &DiagLoc = Diag.getLoc();
1442 int DiagBuf = DiagSrcMgr.FindBufferContainingLoc(DiagLoc);
1443 int CppHashBuf = Parser->SrcMgr.FindBufferContainingLoc(Parser->CppHashLoc);
1444
1445 // Like SourceMgr::PrintMessage() we need to print the include stack if any
1446 // before printing the message.
1447 int DiagCurBuffer = DiagSrcMgr.FindBufferContainingLoc(DiagLoc);
Benjamin Kramer04a04262011-10-16 10:48:29 +00001448 if (!Parser->SavedDiagHandler && DiagCurBuffer > 0) {
Kevin Enderbyacbaecd2011-10-12 21:38:39 +00001449 SMLoc ParentIncludeLoc = DiagSrcMgr.getParentIncludeLoc(DiagCurBuffer);
1450 DiagSrcMgr.PrintIncludeStack(ParentIncludeLoc, OS);
1451 }
1452
1453 // If we have not parsed a cpp hash line filename comment or the source
1454 // manager changed or buffer changed (like in a nested include) then just
1455 // print the normal diagnostic using its Filename and LineNo.
1456 if (!Parser->CppHashLineNumber ||
1457 &DiagSrcMgr != &Parser->SrcMgr ||
1458 DiagBuf != CppHashBuf) {
Benjamin Kramer04a04262011-10-16 10:48:29 +00001459 if (Parser->SavedDiagHandler)
1460 Parser->SavedDiagHandler(Diag, Parser->SavedDiagContext);
1461 else
1462 Diag.print(0, OS);
Kevin Enderbyacbaecd2011-10-12 21:38:39 +00001463 return;
1464 }
1465
1466 // Use the CppHashFilename and calculate a line number based on the
1467 // CppHashLoc and CppHashLineNumber relative to this Diag's SMLoc for
1468 // the diagnostic.
1469 const std::string Filename = Parser->CppHashFilename;
1470
1471 int DiagLocLineNo = DiagSrcMgr.FindLineNumber(DiagLoc, DiagBuf);
1472 int CppHashLocLineNo =
1473 Parser->SrcMgr.FindLineNumber(Parser->CppHashLoc, CppHashBuf);
1474 int LineNo = Parser->CppHashLineNumber - 1 +
1475 (DiagLocLineNo - CppHashLocLineNo);
1476
Chris Lattnerd8b7aa22011-10-16 04:47:35 +00001477 SMDiagnostic NewDiag(*Diag.getSourceMgr(), Diag.getLoc(),
1478 Filename, LineNo, Diag.getColumnNo(),
Chris Lattner3f2d5f62011-10-16 05:43:57 +00001479 Diag.getKind(), Diag.getMessage(),
Chris Lattner462b43c2011-10-16 05:47:55 +00001480 Diag.getLineContents(), Diag.getRanges());
Kevin Enderbyacbaecd2011-10-12 21:38:39 +00001481
Benjamin Kramer04a04262011-10-16 10:48:29 +00001482 if (Parser->SavedDiagHandler)
1483 Parser->SavedDiagHandler(NewDiag, Parser->SavedDiagContext);
1484 else
1485 NewDiag.print(0, OS);
Kevin Enderbyacbaecd2011-10-12 21:38:39 +00001486}
1487
Rafael Espindola799aacf2012-08-21 18:29:30 +00001488// FIXME: This is mostly duplicated from the function in AsmLexer.cpp. The
1489// difference being that that function accepts '@' as part of identifiers and
1490// we can't do that. AsmLexer.cpp should probably be changed to handle
1491// '@' as a special case when needed.
1492static bool isIdentifierChar(char c) {
1493 return isalnum(c) || c == '_' || c == '$' || c == '.';
1494}
1495
Rafael Espindola761cb062012-06-03 23:57:14 +00001496bool AsmParser::expandMacro(raw_svector_ostream &OS, StringRef Body,
Rafael Espindola8a403d32012-08-08 14:51:03 +00001497 const MacroParameters &Parameters,
1498 const MacroArguments &A,
Rafael Espindola65366442011-06-05 02:43:45 +00001499 const SMLoc &L) {
Rafael Espindola65366442011-06-05 02:43:45 +00001500 unsigned NParameters = Parameters.size();
1501 if (NParameters != 0 && NParameters != A.size())
1502 return Error(L, "Wrong number of arguments");
Daniel Dunbar7a570d02010-07-18 19:00:10 +00001503
Preston Gurd7b6f2032012-09-19 20:36:12 +00001504 // A macro without parameters is handled differently on Darwin:
1505 // gas accepts no arguments and does no substitutions
Daniel Dunbar7a570d02010-07-18 19:00:10 +00001506 while (!Body.empty()) {
1507 // Scan for the next substitution.
1508 std::size_t End = Body.size(), Pos = 0;
1509 for (; Pos != End; ++Pos) {
1510 // Check for a substitution or escape.
Rafael Espindola65366442011-06-05 02:43:45 +00001511 if (!NParameters) {
1512 // This macro has no parameters, look for $0, $1, etc.
1513 if (Body[Pos] != '$' || Pos + 1 == End)
1514 continue;
Daniel Dunbar7a570d02010-07-18 19:00:10 +00001515
Rafael Espindola65366442011-06-05 02:43:45 +00001516 char Next = Body[Pos + 1];
1517 if (Next == '$' || Next == 'n' || isdigit(Next))
1518 break;
1519 } else {
1520 // This macro has parameters, look for \foo, \bar, etc.
1521 if (Body[Pos] == '\\' && Pos + 1 != End)
1522 break;
1523 }
Daniel Dunbar7a570d02010-07-18 19:00:10 +00001524 }
1525
1526 // Add the prefix.
1527 OS << Body.slice(0, Pos);
1528
1529 // Check if we reached the end.
1530 if (Pos == End)
1531 break;
1532
Rafael Espindola65366442011-06-05 02:43:45 +00001533 if (!NParameters) {
1534 switch (Body[Pos+1]) {
1535 // $$ => $
1536 case '$':
1537 OS << '$';
Daniel Dunbar7a570d02010-07-18 19:00:10 +00001538 break;
1539
Rafael Espindola65366442011-06-05 02:43:45 +00001540 // $n => number of arguments
1541 case 'n':
1542 OS << A.size();
1543 break;
1544
1545 // $[0-9] => argument
1546 default: {
1547 // Missing arguments are ignored.
1548 unsigned Index = Body[Pos+1] - '0';
1549 if (Index >= A.size())
1550 break;
1551
1552 // Otherwise substitute with the token values, with spaces eliminated.
Rafael Espindola28c1f6662012-06-03 22:41:23 +00001553 for (MacroArgument::const_iterator it = A[Index].begin(),
Rafael Espindola65366442011-06-05 02:43:45 +00001554 ie = A[Index].end(); it != ie; ++it)
1555 OS << it->getString();
1556 break;
1557 }
1558 }
1559 Pos += 2;
1560 } else {
1561 unsigned I = Pos + 1;
Rafael Espindola799aacf2012-08-21 18:29:30 +00001562 while (isIdentifierChar(Body[I]) && I + 1 != End)
Rafael Espindola65366442011-06-05 02:43:45 +00001563 ++I;
1564
1565 const char *Begin = Body.data() + Pos +1;
1566 StringRef Argument(Begin, I - (Pos +1));
1567 unsigned Index = 0;
1568 for (; Index < NParameters; ++Index)
Preston Gurd6c9176a2012-09-19 20:29:04 +00001569 if (Parameters[Index].first == Argument)
Rafael Espindola65366442011-06-05 02:43:45 +00001570 break;
1571
Preston Gurd7b6f2032012-09-19 20:36:12 +00001572 if (Index == NParameters) {
1573 if (Body[Pos+1] == '(' && Body[Pos+2] == ')')
1574 Pos += 3;
1575 else {
1576 OS << '\\' << Argument;
1577 Pos = I;
1578 }
1579 } else {
1580 for (MacroArgument::const_iterator it = A[Index].begin(),
1581 ie = A[Index].end(); it != ie; ++it)
1582 if (it->getKind() == AsmToken::String)
1583 OS << it->getStringContents();
1584 else
1585 OS << it->getString();
Rafael Espindola65366442011-06-05 02:43:45 +00001586
Preston Gurd7b6f2032012-09-19 20:36:12 +00001587 Pos += 1 + Argument.size();
1588 }
Rafael Espindola65366442011-06-05 02:43:45 +00001589 }
Daniel Dunbar7a570d02010-07-18 19:00:10 +00001590 // Update the scan point.
Rafael Espindola65366442011-06-05 02:43:45 +00001591 Body = Body.substr(Pos);
Daniel Dunbar7a570d02010-07-18 19:00:10 +00001592 }
Daniel Dunbarc64a0d72010-07-18 18:54:11 +00001593
Rafael Espindola65366442011-06-05 02:43:45 +00001594 return false;
1595}
Daniel Dunbarc64a0d72010-07-18 18:54:11 +00001596
Rafael Espindola65366442011-06-05 02:43:45 +00001597MacroInstantiation::MacroInstantiation(const Macro *M, SMLoc IL, SMLoc EL,
1598 MemoryBuffer *I)
1599 : TheMacro(M), Instantiation(I), InstantiationLoc(IL), ExitLoc(EL)
1600{
Daniel Dunbarc64a0d72010-07-18 18:54:11 +00001601}
1602
Preston Gurd7b6f2032012-09-19 20:36:12 +00001603static bool IsOperator(AsmToken::TokenKind kind)
1604{
1605 switch (kind)
1606 {
1607 default:
1608 return false;
1609 case AsmToken::Plus:
1610 case AsmToken::Minus:
1611 case AsmToken::Tilde:
1612 case AsmToken::Slash:
1613 case AsmToken::Star:
1614 case AsmToken::Dot:
1615 case AsmToken::Equal:
1616 case AsmToken::EqualEqual:
1617 case AsmToken::Pipe:
1618 case AsmToken::PipePipe:
1619 case AsmToken::Caret:
1620 case AsmToken::Amp:
1621 case AsmToken::AmpAmp:
1622 case AsmToken::Exclaim:
1623 case AsmToken::ExclaimEqual:
1624 case AsmToken::Percent:
1625 case AsmToken::Less:
1626 case AsmToken::LessEqual:
1627 case AsmToken::LessLess:
1628 case AsmToken::LessGreater:
1629 case AsmToken::Greater:
1630 case AsmToken::GreaterEqual:
1631 case AsmToken::GreaterGreater:
1632 return true;
1633 }
1634}
1635
Rafael Espindolaaa7a2f22012-06-15 14:02:34 +00001636/// ParseMacroArgument - Extract AsmTokens for a macro argument.
1637/// This is used for both default macro parameter values and the
1638/// arguments in macro invocations
Preston Gurd7b6f2032012-09-19 20:36:12 +00001639bool AsmParser::ParseMacroArgument(MacroArgument &MA,
1640 AsmToken::TokenKind &ArgumentDelimiter) {
Rafael Espindolaaa7a2f22012-06-15 14:02:34 +00001641 unsigned ParenLevel = 0;
Preston Gurd7b6f2032012-09-19 20:36:12 +00001642 unsigned AddTokens = 0;
1643
1644 // gas accepts arguments separated by whitespace, except on Darwin
1645 if (!IsDarwin)
1646 Lexer.setSkipSpace(false);
Rafael Espindolaaa7a2f22012-06-15 14:02:34 +00001647
1648 for (;;) {
Preston Gurd7b6f2032012-09-19 20:36:12 +00001649 if (Lexer.is(AsmToken::Eof) || Lexer.is(AsmToken::Equal)) {
1650 Lexer.setSkipSpace(true);
Rafael Espindolaaa7a2f22012-06-15 14:02:34 +00001651 return TokError("unexpected token in macro instantiation");
Preston Gurd7b6f2032012-09-19 20:36:12 +00001652 }
1653
1654 if (ParenLevel == 0 && Lexer.is(AsmToken::Comma)) {
1655 // Spaces and commas cannot be mixed to delimit parameters
1656 if (ArgumentDelimiter == AsmToken::Eof)
1657 ArgumentDelimiter = AsmToken::Comma;
1658 else if (ArgumentDelimiter != AsmToken::Comma) {
1659 Lexer.setSkipSpace(true);
1660 return TokError("expected ' ' for macro argument separator");
1661 }
1662 break;
1663 }
1664
1665 if (Lexer.is(AsmToken::Space)) {
1666 Lex(); // Eat spaces
1667
1668 // Spaces can delimit parameters, but could also be part an expression.
1669 // If the token after a space is an operator, add the token and the next
1670 // one into this argument
1671 if (ArgumentDelimiter == AsmToken::Space ||
1672 ArgumentDelimiter == AsmToken::Eof) {
1673 if (IsOperator(Lexer.getKind())) {
1674 // Check to see whether the token is used as an operator,
1675 // or part of an identifier
1676 const char *NextChar = getTok().getEndLoc().getPointer() + 1;
1677 if (*NextChar == ' ')
1678 AddTokens = 2;
1679 }
1680
1681 if (!AddTokens && ParenLevel == 0) {
1682 if (ArgumentDelimiter == AsmToken::Eof &&
1683 !IsOperator(Lexer.getKind()))
1684 ArgumentDelimiter = AsmToken::Space;
1685 break;
1686 }
1687 }
1688 }
Rafael Espindolaaa7a2f22012-06-15 14:02:34 +00001689
1690 // HandleMacroEntry relies on not advancing the lexer here
1691 // to be able to fill in the remaining default parameter values
1692 if (Lexer.is(AsmToken::EndOfStatement))
1693 break;
Rafael Espindolaaa7a2f22012-06-15 14:02:34 +00001694
1695 // Adjust the current parentheses level.
1696 if (Lexer.is(AsmToken::LParen))
1697 ++ParenLevel;
1698 else if (Lexer.is(AsmToken::RParen) && ParenLevel)
1699 --ParenLevel;
1700
1701 // Append the token to the current argument list.
1702 MA.push_back(getTok());
Preston Gurd7b6f2032012-09-19 20:36:12 +00001703 if (AddTokens)
1704 AddTokens--;
Rafael Espindolaaa7a2f22012-06-15 14:02:34 +00001705 Lex();
1706 }
Preston Gurd7b6f2032012-09-19 20:36:12 +00001707
1708 Lexer.setSkipSpace(true);
Rafael Espindolaaa7a2f22012-06-15 14:02:34 +00001709 if (ParenLevel != 0)
Rafael Espindola76ac2002012-08-21 15:55:04 +00001710 return TokError("unbalanced parentheses in macro argument");
Rafael Espindolaaa7a2f22012-06-15 14:02:34 +00001711 return false;
1712}
1713
1714// Parse the macro instantiation arguments.
Rafael Espindola8a403d32012-08-08 14:51:03 +00001715bool AsmParser::ParseMacroArguments(const Macro *M, MacroArguments &A) {
Rafael Espindolaaa7a2f22012-06-15 14:02:34 +00001716 const unsigned NParameters = M ? M->Parameters.size() : 0;
Preston Gurd7b6f2032012-09-19 20:36:12 +00001717 // Argument delimiter is initially unknown. It will be set by
1718 // ParseMacroArgument()
1719 AsmToken::TokenKind ArgumentDelimiter = AsmToken::Eof;
Rafael Espindolaaa7a2f22012-06-15 14:02:34 +00001720
1721 // Parse two kinds of macro invocations:
1722 // - macros defined without any parameters accept an arbitrary number of them
1723 // - macros defined with parameters accept at most that many of them
1724 for (unsigned Parameter = 0; !NParameters || Parameter < NParameters;
1725 ++Parameter) {
1726 MacroArgument MA;
1727
Preston Gurd7b6f2032012-09-19 20:36:12 +00001728 if (ParseMacroArgument(MA, ArgumentDelimiter))
Rafael Espindolaaa7a2f22012-06-15 14:02:34 +00001729 return true;
1730
Preston Gurd6c9176a2012-09-19 20:29:04 +00001731 if (!MA.empty() || !NParameters)
1732 A.push_back(MA);
1733 else if (NParameters) {
1734 if (!M->Parameters[Parameter].second.empty())
1735 A.push_back(M->Parameters[Parameter].second);
1736 }
Jim Grosbach97146442012-07-30 22:44:17 +00001737
Preston Gurd6c9176a2012-09-19 20:29:04 +00001738 // At the end of the statement, fill in remaining arguments that have
1739 // default values. If there aren't any, then the next argument is
1740 // required but missing
1741 if (Lexer.is(AsmToken::EndOfStatement)) {
1742 if (NParameters && Parameter < NParameters - 1) {
1743 if (M->Parameters[Parameter + 1].second.empty())
1744 return TokError("macro argument '" +
1745 Twine(M->Parameters[Parameter + 1].first) +
1746 "' is missing");
1747 else
1748 continue;
1749 }
Rafael Espindolaaa7a2f22012-06-15 14:02:34 +00001750 return false;
Preston Gurd6c9176a2012-09-19 20:29:04 +00001751 }
Rafael Espindolaaa7a2f22012-06-15 14:02:34 +00001752
1753 if (Lexer.is(AsmToken::Comma))
1754 Lex();
1755 }
1756 return TokError("Too many arguments");
1757}
1758
Daniel Dunbarc64a0d72010-07-18 18:54:11 +00001759bool AsmParser::HandleMacroEntry(StringRef Name, SMLoc NameLoc,
1760 const Macro *M) {
1761 // Arbitrarily limit macro nesting depth, to match 'as'. We can eliminate
1762 // this, although we should protect against infinite loops.
1763 if (ActiveMacros.size() == 20)
1764 return TokError("macros cannot be nested more than 20 levels deep");
1765
Rafael Espindola8a403d32012-08-08 14:51:03 +00001766 MacroArguments A;
1767 if (ParseMacroArguments(M, A))
Rafael Espindolaaa7a2f22012-06-15 14:02:34 +00001768 return true;
Daniel Dunbarc64a0d72010-07-18 18:54:11 +00001769
Jim Grosbach97146442012-07-30 22:44:17 +00001770 // Remove any trailing empty arguments. Do this after-the-fact as we have
1771 // to keep empty arguments in the middle of the list or positionality
1772 // gets off. e.g., "foo 1, , 2" vs. "foo 1, 2,"
Rafael Espindola8a403d32012-08-08 14:51:03 +00001773 while (!A.empty() && A.back().empty())
1774 A.pop_back();
Jim Grosbach97146442012-07-30 22:44:17 +00001775
Rafael Espindola65366442011-06-05 02:43:45 +00001776 // Macro instantiation is lexical, unfortunately. We construct a new buffer
1777 // to hold the macro body with substitutions.
1778 SmallString<256> Buf;
1779 StringRef Body = M->Body;
Rafael Espindola761cb062012-06-03 23:57:14 +00001780 raw_svector_ostream OS(Buf);
Rafael Espindola65366442011-06-05 02:43:45 +00001781
Rafael Espindola8a403d32012-08-08 14:51:03 +00001782 if (expandMacro(OS, Body, M->Parameters, A, getTok().getLoc()))
Rafael Espindola65366442011-06-05 02:43:45 +00001783 return true;
1784
Rafael Espindola761cb062012-06-03 23:57:14 +00001785 // We include the .endmacro in the buffer as our queue to exit the macro
1786 // instantiation.
1787 OS << ".endmacro\n";
1788
Rafael Espindola65366442011-06-05 02:43:45 +00001789 MemoryBuffer *Instantiation =
Rafael Espindola761cb062012-06-03 23:57:14 +00001790 MemoryBuffer::getMemBufferCopy(OS.str(), "<instantiation>");
Rafael Espindola65366442011-06-05 02:43:45 +00001791
Daniel Dunbarc64a0d72010-07-18 18:54:11 +00001792 // Create the macro instantiation object and add to the current macro
1793 // instantiation stack.
1794 MacroInstantiation *MI = new MacroInstantiation(M, NameLoc,
Daniel Dunbar7a570d02010-07-18 19:00:10 +00001795 getTok().getLoc(),
Rafael Espindola65366442011-06-05 02:43:45 +00001796 Instantiation);
Daniel Dunbarc64a0d72010-07-18 18:54:11 +00001797 ActiveMacros.push_back(MI);
1798
1799 // Jump to the macro instantiation and prime the lexer.
1800 CurBuffer = SrcMgr.AddNewSourceBuffer(MI->Instantiation, SMLoc());
1801 Lexer.setBuffer(SrcMgr.getMemoryBuffer(CurBuffer));
1802 Lex();
1803
1804 return false;
1805}
1806
1807void AsmParser::HandleMacroExit() {
1808 // Jump to the EndOfStatement we should return to, and consume it.
1809 JumpToLoc(ActiveMacros.back()->ExitLoc);
1810 Lex();
1811
1812 // Pop the instantiation entry.
1813 delete ActiveMacros.back();
1814 ActiveMacros.pop_back();
1815}
1816
Rafael Espindolae71cc862012-01-28 05:57:00 +00001817static bool IsUsedIn(const MCSymbol *Sym, const MCExpr *Value) {
Rafael Espindoladb9835d2010-11-15 14:40:36 +00001818 switch (Value->getKind()) {
Rafael Espindolae71cc862012-01-28 05:57:00 +00001819 case MCExpr::Binary: {
1820 const MCBinaryExpr *BE = static_cast<const MCBinaryExpr*>(Value);
1821 return IsUsedIn(Sym, BE->getLHS()) || IsUsedIn(Sym, BE->getRHS());
Rafael Espindoladb9835d2010-11-15 14:40:36 +00001822 break;
1823 }
Rafael Espindolae71cc862012-01-28 05:57:00 +00001824 case MCExpr::Target:
1825 case MCExpr::Constant:
1826 return false;
1827 case MCExpr::SymbolRef: {
1828 const MCSymbol &S = static_cast<const MCSymbolRefExpr*>(Value)->getSymbol();
Rafael Espindola8b01c822012-01-28 06:22:14 +00001829 if (S.isVariable())
1830 return IsUsedIn(Sym, S.getVariableValue());
1831 return &S == Sym;
Rafael Espindolae71cc862012-01-28 05:57:00 +00001832 }
Rafael Espindoladb9835d2010-11-15 14:40:36 +00001833 case MCExpr::Unary:
Rafael Espindolae71cc862012-01-28 05:57:00 +00001834 return IsUsedIn(Sym, static_cast<const MCUnaryExpr*>(Value)->getSubExpr());
Rafael Espindoladb9835d2010-11-15 14:40:36 +00001835 }
Benjamin Kramer518ff562012-01-28 15:28:41 +00001836
1837 llvm_unreachable("Unknown expr kind!");
Rafael Espindoladb9835d2010-11-15 14:40:36 +00001838}
1839
Jim Grosbach3f90a4c2012-09-13 23:11:31 +00001840bool AsmParser::ParseAssignment(StringRef Name, bool allow_redef,
1841 bool NoDeadStrip) {
Daniel Dunbardce0f3c2009-06-29 23:43:14 +00001842 // FIXME: Use better location, we should use proper tokens.
1843 SMLoc EqualLoc = Lexer.getLoc();
1844
Daniel Dunbar821e3332009-08-31 08:09:28 +00001845 const MCExpr *Value;
Daniel Dunbar821e3332009-08-31 08:09:28 +00001846 if (ParseExpression(Value))
Daniel Dunbar8f780cd2009-06-25 21:56:11 +00001847 return true;
Michael J. Spencerc0c8df32010-10-09 11:00:50 +00001848
Rafael Espindolae71cc862012-01-28 05:57:00 +00001849 // Note: we don't count b as used in "a = b". This is to allow
1850 // a = b
1851 // b = c
Rafael Espindoladb9835d2010-11-15 14:40:36 +00001852
Daniel Dunbar3f872332009-07-28 16:08:33 +00001853 if (Lexer.isNot(AsmToken::EndOfStatement))
Daniel Dunbar8f780cd2009-06-25 21:56:11 +00001854 return TokError("unexpected token in assignment");
1855
Daniel Dunbar8b2b43c2011-03-25 17:47:17 +00001856 // Error on assignment to '.'.
1857 if (Name == ".") {
1858 return Error(EqualLoc, ("assignment to pseudo-symbol '.' is unsupported "
1859 "(use '.space' or '.org').)"));
1860 }
1861
Daniel Dunbar8f780cd2009-06-25 21:56:11 +00001862 // Eat the end of statement marker.
Sean Callanan79ed1a82010-01-19 20:22:31 +00001863 Lex();
Daniel Dunbar8f780cd2009-06-25 21:56:11 +00001864
Daniel Dunbar75773ff2009-10-16 01:57:39 +00001865 // Validate that the LHS is allowed to be a variable (either it has not been
1866 // used as a symbol, or it is an absolute symbol).
1867 MCSymbol *Sym = getContext().LookupSymbol(Name);
1868 if (Sym) {
1869 // Diagnose assignment to a label.
1870 //
1871 // FIXME: Diagnostics. Note the location of the definition as a label.
1872 // FIXME: Diagnose assignment to protected identifier (e.g., register name).
Rafael Espindolae71cc862012-01-28 05:57:00 +00001873 if (IsUsedIn(Sym, Value))
1874 return Error(EqualLoc, "Recursive use of '" + Name + "'");
1875 else if (Sym->isUndefined() && !Sym->isUsed() && !Sym->isVariable())
Daniel Dunbar525a3a62010-05-17 17:46:23 +00001876 ; // Allow redefinitions of undefined symbols only used in directives.
Jim Grosbach48c95332012-03-20 21:33:21 +00001877 else if (Sym->isVariable() && !Sym->isUsed() && allow_redef)
1878 ; // Allow redefinitions of variables that haven't yet been used.
Daniel Dunbar6db7fe82011-04-29 17:53:11 +00001879 else if (!Sym->isUndefined() && (!Sym->isVariable() || !allow_redef))
Daniel Dunbar75773ff2009-10-16 01:57:39 +00001880 return Error(EqualLoc, "redefinition of '" + Name + "'");
1881 else if (!Sym->isVariable())
1882 return Error(EqualLoc, "invalid assignment to '" + Name + "'");
Daniel Dunbar08a408a2010-05-05 17:41:00 +00001883 else if (!isa<MCConstantExpr>(Sym->getVariableValue()))
Daniel Dunbar75773ff2009-10-16 01:57:39 +00001884 return Error(EqualLoc, "invalid reassignment of non-absolute variable '" +
1885 Name + "'");
Rafael Espindoladb9835d2010-11-15 14:40:36 +00001886
1887 // Don't count these checks as uses.
1888 Sym->setUsed(false);
Daniel Dunbar75773ff2009-10-16 01:57:39 +00001889 } else
Daniel Dunbar4c7c08b2010-07-12 19:52:10 +00001890 Sym = getContext().GetOrCreateSymbol(Name);
Daniel Dunbar75773ff2009-10-16 01:57:39 +00001891
Daniel Dunbar8f780cd2009-06-25 21:56:11 +00001892 // FIXME: Handle '.'.
Daniel Dunbardce0f3c2009-06-29 23:43:14 +00001893
1894 // Do the assignment.
Daniel Dunbare2ace502009-08-31 08:09:09 +00001895 Out.EmitAssignment(Sym, Value);
Jim Grosbach3f90a4c2012-09-13 23:11:31 +00001896 if (NoDeadStrip)
1897 Out.EmitSymbolAttribute(Sym, MCSA_NoDeadStrip);
1898
Daniel Dunbar8f780cd2009-06-25 21:56:11 +00001899
1900 return false;
1901}
1902
Daniel Dunbara6b3c5d2009-08-01 00:48:30 +00001903/// ParseIdentifier:
1904/// ::= identifier
1905/// ::= string
1906bool AsmParser::ParseIdentifier(StringRef &Res) {
Daniel Dunbar1f1b8652010-08-24 18:12:12 +00001907 // The assembler has relaxed rules for accepting identifiers, in particular we
1908 // allow things like '.globl $foo', which would normally be separate
1909 // tokens. At this level, we have already lexed so we cannot (currently)
1910 // handle this as a context dependent token, instead we detect adjacent tokens
1911 // and return the combined identifier.
1912 if (Lexer.is(AsmToken::Dollar)) {
1913 SMLoc DollarLoc = getLexer().getLoc();
1914
1915 // Consume the dollar sign, and check for a following identifier.
1916 Lex();
1917 if (Lexer.isNot(AsmToken::Identifier))
1918 return true;
1919
1920 // We have a '$' followed by an identifier, make sure they are adjacent.
1921 if (DollarLoc.getPointer() + 1 != getTok().getLoc().getPointer())
1922 return true;
1923
1924 // Construct the joined identifier and consume the token.
1925 Res = StringRef(DollarLoc.getPointer(),
1926 getTok().getIdentifier().size() + 1);
1927 Lex();
1928 return false;
1929 }
1930
Daniel Dunbara6b3c5d2009-08-01 00:48:30 +00001931 if (Lexer.isNot(AsmToken::Identifier) &&
1932 Lexer.isNot(AsmToken::String))
1933 return true;
1934
Sean Callanan18b83232010-01-19 21:44:56 +00001935 Res = getTok().getIdentifier();
Daniel Dunbara6b3c5d2009-08-01 00:48:30 +00001936
Sean Callanan79ed1a82010-01-19 20:22:31 +00001937 Lex(); // Consume the identifier token.
Daniel Dunbara6b3c5d2009-08-01 00:48:30 +00001938
1939 return false;
1940}
1941
Daniel Dunbar8f780cd2009-06-25 21:56:11 +00001942/// ParseDirectiveSet:
Nico Weber4c4c7322011-01-28 03:04:41 +00001943/// ::= .equ identifier ',' expression
1944/// ::= .equiv identifier ',' expression
Daniel Dunbar8f780cd2009-06-25 21:56:11 +00001945/// ::= .set identifier ',' expression
Nico Weber4c4c7322011-01-28 03:04:41 +00001946bool AsmParser::ParseDirectiveSet(StringRef IDVal, bool allow_redef) {
Daniel Dunbara6b3c5d2009-08-01 00:48:30 +00001947 StringRef Name;
Daniel Dunbar8f780cd2009-06-25 21:56:11 +00001948
Daniel Dunbara6b3c5d2009-08-01 00:48:30 +00001949 if (ParseIdentifier(Name))
Roman Divackyf9d17522010-10-28 16:57:58 +00001950 return TokError("expected identifier after '" + Twine(IDVal) + "'");
Michael J. Spencerc0c8df32010-10-09 11:00:50 +00001951
Daniel Dunbar8f34bea2010-07-12 18:03:11 +00001952 if (getLexer().isNot(AsmToken::Comma))
Roman Divackyf9d17522010-10-28 16:57:58 +00001953 return TokError("unexpected token in '" + Twine(IDVal) + "'");
Sean Callanan79ed1a82010-01-19 20:22:31 +00001954 Lex();
Daniel Dunbar8f780cd2009-06-25 21:56:11 +00001955
Jim Grosbach3f90a4c2012-09-13 23:11:31 +00001956 return ParseAssignment(Name, allow_redef, true);
Daniel Dunbar8f780cd2009-06-25 21:56:11 +00001957}
1958
Daniel Dunbar1ab75942009-08-14 18:19:52 +00001959bool AsmParser::ParseEscapedString(std::string &Data) {
Daniel Dunbar8f34bea2010-07-12 18:03:11 +00001960 assert(getLexer().is(AsmToken::String) && "Unexpected current token!");
Daniel Dunbar1ab75942009-08-14 18:19:52 +00001961
1962 Data = "";
Sean Callanan18b83232010-01-19 21:44:56 +00001963 StringRef Str = getTok().getStringContents();
Daniel Dunbar1ab75942009-08-14 18:19:52 +00001964 for (unsigned i = 0, e = Str.size(); i != e; ++i) {
1965 if (Str[i] != '\\') {
1966 Data += Str[i];
1967 continue;
1968 }
1969
1970 // Recognize escaped characters. Note that this escape semantics currently
1971 // loosely follows Darwin 'as'. Notably, it doesn't support hex escapes.
1972 ++i;
1973 if (i == e)
1974 return TokError("unexpected backslash at end of string");
1975
1976 // Recognize octal sequences.
1977 if ((unsigned) (Str[i] - '0') <= 7) {
1978 // Consume up to three octal characters.
1979 unsigned Value = Str[i] - '0';
1980
1981 if (i + 1 != e && ((unsigned) (Str[i + 1] - '0')) <= 7) {
1982 ++i;
1983 Value = Value * 8 + (Str[i] - '0');
1984
1985 if (i + 1 != e && ((unsigned) (Str[i + 1] - '0')) <= 7) {
1986 ++i;
1987 Value = Value * 8 + (Str[i] - '0');
1988 }
1989 }
1990
1991 if (Value > 255)
1992 return TokError("invalid octal escape sequence (out of range)");
1993
1994 Data += (unsigned char) Value;
1995 continue;
1996 }
1997
1998 // Otherwise recognize individual escapes.
1999 switch (Str[i]) {
2000 default:
2001 // Just reject invalid escape sequences for now.
2002 return TokError("invalid escape sequence (unrecognized character)");
2003
2004 case 'b': Data += '\b'; break;
2005 case 'f': Data += '\f'; break;
2006 case 'n': Data += '\n'; break;
2007 case 'r': Data += '\r'; break;
2008 case 't': Data += '\t'; break;
2009 case '"': Data += '"'; break;
2010 case '\\': Data += '\\'; break;
2011 }
2012 }
2013
2014 return false;
2015}
2016
Daniel Dunbara0d14262009-06-24 23:30:00 +00002017/// ParseDirectiveAscii:
Rafael Espindola787c3372010-10-28 20:02:27 +00002018/// ::= ( .ascii | .asciz | .string ) [ "string" ( , "string" )* ]
2019bool AsmParser::ParseDirectiveAscii(StringRef IDVal, bool ZeroTerminated) {
Daniel Dunbar8f34bea2010-07-12 18:03:11 +00002020 if (getLexer().isNot(AsmToken::EndOfStatement)) {
Daniel Dunbar1ab6f2f2010-09-09 22:42:59 +00002021 CheckForValidSection();
2022
Daniel Dunbara0d14262009-06-24 23:30:00 +00002023 for (;;) {
Daniel Dunbar8f34bea2010-07-12 18:03:11 +00002024 if (getLexer().isNot(AsmToken::String))
Rafael Espindola787c3372010-10-28 20:02:27 +00002025 return TokError("expected string in '" + Twine(IDVal) + "' directive");
Daniel Dunbar8f34bea2010-07-12 18:03:11 +00002026
Daniel Dunbar1ab75942009-08-14 18:19:52 +00002027 std::string Data;
2028 if (ParseEscapedString(Data))
2029 return true;
Daniel Dunbar8f34bea2010-07-12 18:03:11 +00002030
2031 getStreamer().EmitBytes(Data, DEFAULT_ADDRSPACE);
Daniel Dunbara0d14262009-06-24 23:30:00 +00002032 if (ZeroTerminated)
Daniel Dunbar8f34bea2010-07-12 18:03:11 +00002033 getStreamer().EmitBytes(StringRef("\0", 1), DEFAULT_ADDRSPACE);
2034
Sean Callanan79ed1a82010-01-19 20:22:31 +00002035 Lex();
Daniel Dunbar8f34bea2010-07-12 18:03:11 +00002036
2037 if (getLexer().is(AsmToken::EndOfStatement))
Daniel Dunbara0d14262009-06-24 23:30:00 +00002038 break;
2039
Daniel Dunbar8f34bea2010-07-12 18:03:11 +00002040 if (getLexer().isNot(AsmToken::Comma))
Rafael Espindola787c3372010-10-28 20:02:27 +00002041 return TokError("unexpected token in '" + Twine(IDVal) + "' directive");
Sean Callanan79ed1a82010-01-19 20:22:31 +00002042 Lex();
Daniel Dunbara0d14262009-06-24 23:30:00 +00002043 }
2044 }
2045
Sean Callanan79ed1a82010-01-19 20:22:31 +00002046 Lex();
Daniel Dunbara0d14262009-06-24 23:30:00 +00002047 return false;
2048}
2049
2050/// ParseDirectiveValue
2051/// ::= (.byte | .short | ... ) [ expression (, expression)* ]
2052bool AsmParser::ParseDirectiveValue(unsigned Size) {
Daniel Dunbar8f34bea2010-07-12 18:03:11 +00002053 if (getLexer().isNot(AsmToken::EndOfStatement)) {
Daniel Dunbar1ab6f2f2010-09-09 22:42:59 +00002054 CheckForValidSection();
2055
Daniel Dunbara0d14262009-06-24 23:30:00 +00002056 for (;;) {
Daniel Dunbar821e3332009-08-31 08:09:28 +00002057 const MCExpr *Value;
Jim Grosbach254cf032011-06-29 16:05:14 +00002058 SMLoc ExprLoc = getLexer().getLoc();
Daniel Dunbar821e3332009-08-31 08:09:28 +00002059 if (ParseExpression(Value))
Daniel Dunbara0d14262009-06-24 23:30:00 +00002060 return true;
2061
Daniel Dunbar414c0c42010-05-23 18:36:38 +00002062 // Special case constant expressions to match code generator.
Jim Grosbach254cf032011-06-29 16:05:14 +00002063 if (const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(Value)) {
2064 assert(Size <= 8 && "Invalid size");
2065 uint64_t IntValue = MCE->getValue();
2066 if (!isUIntN(8 * Size, IntValue) && !isIntN(8 * Size, IntValue))
2067 return Error(ExprLoc, "literal value out of range for directive");
2068 getStreamer().EmitIntValue(IntValue, Size, DEFAULT_ADDRSPACE);
2069 } else
Daniel Dunbar8f34bea2010-07-12 18:03:11 +00002070 getStreamer().EmitValue(Value, Size, DEFAULT_ADDRSPACE);
Daniel Dunbara0d14262009-06-24 23:30:00 +00002071
Daniel Dunbar8f34bea2010-07-12 18:03:11 +00002072 if (getLexer().is(AsmToken::EndOfStatement))
Daniel Dunbara0d14262009-06-24 23:30:00 +00002073 break;
Michael J. Spencerc0c8df32010-10-09 11:00:50 +00002074
Daniel Dunbara0d14262009-06-24 23:30:00 +00002075 // FIXME: Improve diagnostic.
Daniel Dunbar8f34bea2010-07-12 18:03:11 +00002076 if (getLexer().isNot(AsmToken::Comma))
Daniel Dunbara0d14262009-06-24 23:30:00 +00002077 return TokError("unexpected token in directive");
Sean Callanan79ed1a82010-01-19 20:22:31 +00002078 Lex();
Daniel Dunbara0d14262009-06-24 23:30:00 +00002079 }
2080 }
2081
Sean Callanan79ed1a82010-01-19 20:22:31 +00002082 Lex();
Daniel Dunbara0d14262009-06-24 23:30:00 +00002083 return false;
2084}
2085
Daniel Dunbarb95a0792010-09-24 01:59:56 +00002086/// ParseDirectiveRealValue
2087/// ::= (.single | .double) [ expression (, expression)* ]
2088bool AsmParser::ParseDirectiveRealValue(const fltSemantics &Semantics) {
2089 if (getLexer().isNot(AsmToken::EndOfStatement)) {
2090 CheckForValidSection();
2091
2092 for (;;) {
2093 // We don't truly support arithmetic on floating point expressions, so we
2094 // have to manually parse unary prefixes.
2095 bool IsNeg = false;
2096 if (getLexer().is(AsmToken::Minus)) {
2097 Lex();
2098 IsNeg = true;
2099 } else if (getLexer().is(AsmToken::Plus))
2100 Lex();
2101
Michael J. Spencerc0c8df32010-10-09 11:00:50 +00002102 if (getLexer().isNot(AsmToken::Integer) &&
Kevin Enderby360d8d72011-03-29 21:11:52 +00002103 getLexer().isNot(AsmToken::Real) &&
2104 getLexer().isNot(AsmToken::Identifier))
Daniel Dunbarb95a0792010-09-24 01:59:56 +00002105 return TokError("unexpected token in directive");
2106
2107 // Convert to an APFloat.
2108 APFloat Value(Semantics);
Kevin Enderby360d8d72011-03-29 21:11:52 +00002109 StringRef IDVal = getTok().getString();
2110 if (getLexer().is(AsmToken::Identifier)) {
2111 if (!IDVal.compare_lower("infinity") || !IDVal.compare_lower("inf"))
2112 Value = APFloat::getInf(Semantics);
2113 else if (!IDVal.compare_lower("nan"))
2114 Value = APFloat::getNaN(Semantics, false, ~0);
2115 else
2116 return TokError("invalid floating point literal");
2117 } else if (Value.convertFromString(IDVal, APFloat::rmNearestTiesToEven) ==
Daniel Dunbarb95a0792010-09-24 01:59:56 +00002118 APFloat::opInvalidOp)
2119 return TokError("invalid floating point literal");
2120 if (IsNeg)
2121 Value.changeSign();
2122
2123 // Consume the numeric token.
2124 Lex();
2125
2126 // Emit the value as an integer.
2127 APInt AsInt = Value.bitcastToAPInt();
2128 getStreamer().EmitIntValue(AsInt.getLimitedValue(),
2129 AsInt.getBitWidth() / 8, DEFAULT_ADDRSPACE);
2130
2131 if (getLexer().is(AsmToken::EndOfStatement))
2132 break;
Michael J. Spencerc0c8df32010-10-09 11:00:50 +00002133
Daniel Dunbarb95a0792010-09-24 01:59:56 +00002134 if (getLexer().isNot(AsmToken::Comma))
2135 return TokError("unexpected token in directive");
2136 Lex();
2137 }
2138 }
2139
2140 Lex();
2141 return false;
2142}
2143
Daniel Dunbara0d14262009-06-24 23:30:00 +00002144/// ParseDirectiveSpace
2145/// ::= .space expression [ , expression ]
2146bool AsmParser::ParseDirectiveSpace() {
Daniel Dunbar1ab6f2f2010-09-09 22:42:59 +00002147 CheckForValidSection();
2148
Daniel Dunbara0d14262009-06-24 23:30:00 +00002149 int64_t NumBytes;
Daniel Dunbar475839e2009-06-29 20:37:27 +00002150 if (ParseAbsoluteExpression(NumBytes))
Daniel Dunbara0d14262009-06-24 23:30:00 +00002151 return true;
2152
2153 int64_t FillExpr = 0;
Daniel Dunbar8f34bea2010-07-12 18:03:11 +00002154 if (getLexer().isNot(AsmToken::EndOfStatement)) {
2155 if (getLexer().isNot(AsmToken::Comma))
Daniel Dunbara0d14262009-06-24 23:30:00 +00002156 return TokError("unexpected token in '.space' directive");
Sean Callanan79ed1a82010-01-19 20:22:31 +00002157 Lex();
Michael J. Spencerc0c8df32010-10-09 11:00:50 +00002158
Daniel Dunbar475839e2009-06-29 20:37:27 +00002159 if (ParseAbsoluteExpression(FillExpr))
Daniel Dunbara0d14262009-06-24 23:30:00 +00002160 return true;
2161
Daniel Dunbar8f34bea2010-07-12 18:03:11 +00002162 if (getLexer().isNot(AsmToken::EndOfStatement))
Daniel Dunbara0d14262009-06-24 23:30:00 +00002163 return TokError("unexpected token in '.space' directive");
2164 }
2165
Sean Callanan79ed1a82010-01-19 20:22:31 +00002166 Lex();
Daniel Dunbara0d14262009-06-24 23:30:00 +00002167
2168 if (NumBytes <= 0)
2169 return TokError("invalid number of bytes in '.space' directive");
2170
2171 // FIXME: Sometimes the fill expr is 'nop' if it isn't supplied, instead of 0.
Daniel Dunbar8f34bea2010-07-12 18:03:11 +00002172 getStreamer().EmitFill(NumBytes, FillExpr, DEFAULT_ADDRSPACE);
Daniel Dunbara0d14262009-06-24 23:30:00 +00002173
2174 return false;
2175}
2176
Rafael Espindola2ea2ac72010-09-16 15:03:59 +00002177/// ParseDirectiveZero
2178/// ::= .zero expression
2179bool AsmParser::ParseDirectiveZero() {
2180 CheckForValidSection();
2181
2182 int64_t NumBytes;
2183 if (ParseAbsoluteExpression(NumBytes))
2184 return true;
2185
Rafael Espindolae452b172010-10-05 19:42:57 +00002186 int64_t Val = 0;
2187 if (getLexer().is(AsmToken::Comma)) {
2188 Lex();
2189 if (ParseAbsoluteExpression(Val))
2190 return true;
2191 }
2192
Rafael Espindola2ea2ac72010-09-16 15:03:59 +00002193 if (getLexer().isNot(AsmToken::EndOfStatement))
2194 return TokError("unexpected token in '.zero' directive");
2195
2196 Lex();
2197
Rafael Espindolae452b172010-10-05 19:42:57 +00002198 getStreamer().EmitFill(NumBytes, Val, DEFAULT_ADDRSPACE);
Rafael Espindola2ea2ac72010-09-16 15:03:59 +00002199
2200 return false;
2201}
2202
Daniel Dunbara0d14262009-06-24 23:30:00 +00002203/// ParseDirectiveFill
2204/// ::= .fill expression , expression , expression
2205bool AsmParser::ParseDirectiveFill() {
Daniel Dunbar1ab6f2f2010-09-09 22:42:59 +00002206 CheckForValidSection();
2207
Daniel Dunbara0d14262009-06-24 23:30:00 +00002208 int64_t NumValues;
Daniel Dunbar475839e2009-06-29 20:37:27 +00002209 if (ParseAbsoluteExpression(NumValues))
Daniel Dunbara0d14262009-06-24 23:30:00 +00002210 return true;
2211
Daniel Dunbar8f34bea2010-07-12 18:03:11 +00002212 if (getLexer().isNot(AsmToken::Comma))
Daniel Dunbara0d14262009-06-24 23:30:00 +00002213 return TokError("unexpected token in '.fill' directive");
Sean Callanan79ed1a82010-01-19 20:22:31 +00002214 Lex();
Michael J. Spencerc0c8df32010-10-09 11:00:50 +00002215
Daniel Dunbara0d14262009-06-24 23:30:00 +00002216 int64_t FillSize;
Daniel Dunbar475839e2009-06-29 20:37:27 +00002217 if (ParseAbsoluteExpression(FillSize))
Daniel Dunbara0d14262009-06-24 23:30:00 +00002218 return true;
2219
Daniel Dunbar8f34bea2010-07-12 18:03:11 +00002220 if (getLexer().isNot(AsmToken::Comma))
Daniel Dunbara0d14262009-06-24 23:30:00 +00002221 return TokError("unexpected token in '.fill' directive");
Sean Callanan79ed1a82010-01-19 20:22:31 +00002222 Lex();
Michael J. Spencerc0c8df32010-10-09 11:00:50 +00002223
Daniel Dunbara0d14262009-06-24 23:30:00 +00002224 int64_t FillExpr;
Daniel Dunbar475839e2009-06-29 20:37:27 +00002225 if (ParseAbsoluteExpression(FillExpr))
Daniel Dunbara0d14262009-06-24 23:30:00 +00002226 return true;
2227
Daniel Dunbar8f34bea2010-07-12 18:03:11 +00002228 if (getLexer().isNot(AsmToken::EndOfStatement))
Daniel Dunbara0d14262009-06-24 23:30:00 +00002229 return TokError("unexpected token in '.fill' directive");
Michael J. Spencerc0c8df32010-10-09 11:00:50 +00002230
Sean Callanan79ed1a82010-01-19 20:22:31 +00002231 Lex();
Daniel Dunbara0d14262009-06-24 23:30:00 +00002232
Daniel Dunbarbc38ca72009-08-21 15:43:35 +00002233 if (FillSize != 1 && FillSize != 2 && FillSize != 4 && FillSize != 8)
2234 return TokError("invalid '.fill' size, expected 1, 2, 4, or 8");
Daniel Dunbara0d14262009-06-24 23:30:00 +00002235
2236 for (uint64_t i = 0, e = NumValues; i != e; ++i)
Daniel Dunbar8f34bea2010-07-12 18:03:11 +00002237 getStreamer().EmitIntValue(FillExpr, FillSize, DEFAULT_ADDRSPACE);
Daniel Dunbara0d14262009-06-24 23:30:00 +00002238
2239 return false;
2240}
Daniel Dunbarc238b582009-06-25 22:44:51 +00002241
2242/// ParseDirectiveOrg
2243/// ::= .org expression [ , expression ]
2244bool AsmParser::ParseDirectiveOrg() {
Daniel Dunbar1ab6f2f2010-09-09 22:42:59 +00002245 CheckForValidSection();
2246
Daniel Dunbar821e3332009-08-31 08:09:28 +00002247 const MCExpr *Offset;
Jim Grosbachebd4c052012-01-27 00:37:08 +00002248 SMLoc Loc = getTok().getLoc();
Daniel Dunbar821e3332009-08-31 08:09:28 +00002249 if (ParseExpression(Offset))
Daniel Dunbarc238b582009-06-25 22:44:51 +00002250 return true;
2251
2252 // Parse optional fill expression.
2253 int64_t FillExpr = 0;
Daniel Dunbar8f34bea2010-07-12 18:03:11 +00002254 if (getLexer().isNot(AsmToken::EndOfStatement)) {
2255 if (getLexer().isNot(AsmToken::Comma))
Daniel Dunbarc238b582009-06-25 22:44:51 +00002256 return TokError("unexpected token in '.org' directive");
Sean Callanan79ed1a82010-01-19 20:22:31 +00002257 Lex();
Michael J. Spencerc0c8df32010-10-09 11:00:50 +00002258
Daniel Dunbar475839e2009-06-29 20:37:27 +00002259 if (ParseAbsoluteExpression(FillExpr))
Daniel Dunbarc238b582009-06-25 22:44:51 +00002260 return true;
2261
Daniel Dunbar8f34bea2010-07-12 18:03:11 +00002262 if (getLexer().isNot(AsmToken::EndOfStatement))
Daniel Dunbarc238b582009-06-25 22:44:51 +00002263 return TokError("unexpected token in '.org' directive");
2264 }
2265
Sean Callanan79ed1a82010-01-19 20:22:31 +00002266 Lex();
Daniel Dunbarf4b830f2009-06-30 02:10:03 +00002267
Jim Grosbachebd4c052012-01-27 00:37:08 +00002268 // Only limited forms of relocatable expressions are accepted here, it
2269 // has to be relative to the current section. The streamer will return
2270 // 'true' if the expression wasn't evaluatable.
2271 if (getStreamer().EmitValueToOffset(Offset, FillExpr))
2272 return Error(Loc, "expected assembly-time absolute expression");
Daniel Dunbarc238b582009-06-25 22:44:51 +00002273
2274 return false;
2275}
Daniel Dunbarc29dfa72009-06-29 23:46:59 +00002276
2277/// ParseDirectiveAlign
2278/// ::= {.align, ...} expression [ , expression [ , expression ]]
2279bool AsmParser::ParseDirectiveAlign(bool IsPow2, unsigned ValueSize) {
Daniel Dunbar1ab6f2f2010-09-09 22:42:59 +00002280 CheckForValidSection();
2281
Daniel Dunbar8f34bea2010-07-12 18:03:11 +00002282 SMLoc AlignmentLoc = getLexer().getLoc();
Daniel Dunbarc29dfa72009-06-29 23:46:59 +00002283 int64_t Alignment;
2284 if (ParseAbsoluteExpression(Alignment))
2285 return true;
2286
2287 SMLoc MaxBytesLoc;
2288 bool HasFillExpr = false;
2289 int64_t FillExpr = 0;
2290 int64_t MaxBytesToFill = 0;
Daniel Dunbar8f34bea2010-07-12 18:03:11 +00002291 if (getLexer().isNot(AsmToken::EndOfStatement)) {
2292 if (getLexer().isNot(AsmToken::Comma))
Daniel Dunbarc29dfa72009-06-29 23:46:59 +00002293 return TokError("unexpected token in directive");
Sean Callanan79ed1a82010-01-19 20:22:31 +00002294 Lex();
Daniel Dunbarc29dfa72009-06-29 23:46:59 +00002295
2296 // The fill expression can be omitted while specifying a maximum number of
2297 // alignment bytes, e.g:
2298 // .align 3,,4
Daniel Dunbar8f34bea2010-07-12 18:03:11 +00002299 if (getLexer().isNot(AsmToken::Comma)) {
Daniel Dunbarc29dfa72009-06-29 23:46:59 +00002300 HasFillExpr = true;
2301 if (ParseAbsoluteExpression(FillExpr))
2302 return true;
2303 }
2304
Daniel Dunbar8f34bea2010-07-12 18:03:11 +00002305 if (getLexer().isNot(AsmToken::EndOfStatement)) {
2306 if (getLexer().isNot(AsmToken::Comma))
Daniel Dunbarc29dfa72009-06-29 23:46:59 +00002307 return TokError("unexpected token in directive");
Sean Callanan79ed1a82010-01-19 20:22:31 +00002308 Lex();
Daniel Dunbarc29dfa72009-06-29 23:46:59 +00002309
Daniel Dunbar8f34bea2010-07-12 18:03:11 +00002310 MaxBytesLoc = getLexer().getLoc();
Daniel Dunbarc29dfa72009-06-29 23:46:59 +00002311 if (ParseAbsoluteExpression(MaxBytesToFill))
2312 return true;
Michael J. Spencerc0c8df32010-10-09 11:00:50 +00002313
Daniel Dunbar8f34bea2010-07-12 18:03:11 +00002314 if (getLexer().isNot(AsmToken::EndOfStatement))
Daniel Dunbarc29dfa72009-06-29 23:46:59 +00002315 return TokError("unexpected token in directive");
2316 }
2317 }
2318
Sean Callanan79ed1a82010-01-19 20:22:31 +00002319 Lex();
Daniel Dunbarc29dfa72009-06-29 23:46:59 +00002320
Daniel Dunbar648ac512010-05-17 21:54:30 +00002321 if (!HasFillExpr)
Daniel Dunbarc29dfa72009-06-29 23:46:59 +00002322 FillExpr = 0;
Daniel Dunbarc29dfa72009-06-29 23:46:59 +00002323
2324 // Compute alignment in bytes.
2325 if (IsPow2) {
2326 // FIXME: Diagnose overflow.
Daniel Dunbarb58a8042009-08-26 09:16:34 +00002327 if (Alignment >= 32) {
2328 Error(AlignmentLoc, "invalid alignment value");
2329 Alignment = 31;
2330 }
2331
Benjamin Kramer12fd7672009-09-06 09:35:10 +00002332 Alignment = 1ULL << Alignment;
Daniel Dunbarc29dfa72009-06-29 23:46:59 +00002333 }
2334
Daniel Dunbarb58a8042009-08-26 09:16:34 +00002335 // Diagnose non-sensical max bytes to align.
Daniel Dunbarc29dfa72009-06-29 23:46:59 +00002336 if (MaxBytesLoc.isValid()) {
2337 if (MaxBytesToFill < 1) {
Daniel Dunbarb58a8042009-08-26 09:16:34 +00002338 Error(MaxBytesLoc, "alignment directive can never be satisfied in this "
2339 "many bytes, ignoring maximum bytes expression");
Daniel Dunbar0afb9f52009-08-21 23:01:53 +00002340 MaxBytesToFill = 0;
Daniel Dunbarc29dfa72009-06-29 23:46:59 +00002341 }
2342
2343 if (MaxBytesToFill >= Alignment) {
Daniel Dunbar3fb76832009-06-30 00:49:23 +00002344 Warning(MaxBytesLoc, "maximum bytes expression exceeds alignment and "
2345 "has no effect");
Daniel Dunbarc29dfa72009-06-29 23:46:59 +00002346 MaxBytesToFill = 0;
2347 }
2348 }
2349
Daniel Dunbar648ac512010-05-17 21:54:30 +00002350 // Check whether we should use optimal code alignment for this .align
2351 // directive.
Jan Wen Voung083cf152010-10-04 17:32:41 +00002352 bool UseCodeAlign = getStreamer().getCurrentSection()->UseCodeAlign();
Daniel Dunbar648ac512010-05-17 21:54:30 +00002353 if ((!HasFillExpr || Lexer.getMAI().getTextAlignFillValue() == FillExpr) &&
2354 ValueSize == 1 && UseCodeAlign) {
Daniel Dunbar8f34bea2010-07-12 18:03:11 +00002355 getStreamer().EmitCodeAlignment(Alignment, MaxBytesToFill);
Daniel Dunbar648ac512010-05-17 21:54:30 +00002356 } else {
Kevin Enderbyd74acb02010-02-25 18:46:04 +00002357 // FIXME: Target specific behavior about how the "extra" bytes are filled.
Chris Lattnera9558532010-07-15 21:19:31 +00002358 getStreamer().EmitValueToAlignment(Alignment, FillExpr, ValueSize,
2359 MaxBytesToFill);
Daniel Dunbar648ac512010-05-17 21:54:30 +00002360 }
Daniel Dunbarc29dfa72009-06-29 23:46:59 +00002361
2362 return false;
2363}
2364
Daniel Dunbard7b267b2009-06-30 00:33:19 +00002365/// ParseDirectiveSymbolAttribute
2366/// ::= { ".globl", ".weak", ... } [ identifier ( , identifier )* ]
Chris Lattnera5ad93a2010-01-23 06:39:22 +00002367bool AsmParser::ParseDirectiveSymbolAttribute(MCSymbolAttr Attr) {
Daniel Dunbar8f34bea2010-07-12 18:03:11 +00002368 if (getLexer().isNot(AsmToken::EndOfStatement)) {
Daniel Dunbard7b267b2009-06-30 00:33:19 +00002369 for (;;) {
Daniel Dunbara6b3c5d2009-08-01 00:48:30 +00002370 StringRef Name;
Jim Grosbach10ec6502011-09-15 17:56:49 +00002371 SMLoc Loc = getTok().getLoc();
Daniel Dunbara6b3c5d2009-08-01 00:48:30 +00002372
2373 if (ParseIdentifier(Name))
Jim Grosbach10ec6502011-09-15 17:56:49 +00002374 return Error(Loc, "expected identifier in directive");
Michael J. Spencerc0c8df32010-10-09 11:00:50 +00002375
Daniel Dunbar4c7c08b2010-07-12 19:52:10 +00002376 MCSymbol *Sym = getContext().GetOrCreateSymbol(Name);
Daniel Dunbard7b267b2009-06-30 00:33:19 +00002377
Jim Grosbach10ec6502011-09-15 17:56:49 +00002378 // Assembler local symbols don't make any sense here. Complain loudly.
2379 if (Sym->isTemporary())
2380 return Error(Loc, "non-local symbol required in directive");
2381
Daniel Dunbar8f34bea2010-07-12 18:03:11 +00002382 getStreamer().EmitSymbolAttribute(Sym, Attr);
Daniel Dunbard7b267b2009-06-30 00:33:19 +00002383
Daniel Dunbar8f34bea2010-07-12 18:03:11 +00002384 if (getLexer().is(AsmToken::EndOfStatement))
Daniel Dunbard7b267b2009-06-30 00:33:19 +00002385 break;
2386
Daniel Dunbar8f34bea2010-07-12 18:03:11 +00002387 if (getLexer().isNot(AsmToken::Comma))
Daniel Dunbard7b267b2009-06-30 00:33:19 +00002388 return TokError("unexpected token in directive");
Sean Callanan79ed1a82010-01-19 20:22:31 +00002389 Lex();
Daniel Dunbard7b267b2009-06-30 00:33:19 +00002390 }
2391 }
2392
Sean Callanan79ed1a82010-01-19 20:22:31 +00002393 Lex();
Jan Wen Vounga854a4b2010-09-30 01:09:20 +00002394 return false;
Daniel Dunbard7b267b2009-06-30 00:33:19 +00002395}
Chris Lattner4e4db7a2009-07-07 20:30:46 +00002396
2397/// ParseDirectiveComm
Chris Lattner1fc3d752009-07-09 17:25:12 +00002398/// ::= ( .comm | .lcomm ) identifier , size_expression [ , align_expression ]
2399bool AsmParser::ParseDirectiveComm(bool IsLocal) {
Daniel Dunbar1ab6f2f2010-09-09 22:42:59 +00002400 CheckForValidSection();
2401
Daniel Dunbar8f34bea2010-07-12 18:03:11 +00002402 SMLoc IDLoc = getLexer().getLoc();
Daniel Dunbara6b3c5d2009-08-01 00:48:30 +00002403 StringRef Name;
2404 if (ParseIdentifier(Name))
Chris Lattner4e4db7a2009-07-07 20:30:46 +00002405 return TokError("expected identifier in directive");
Michael J. Spencerc0c8df32010-10-09 11:00:50 +00002406
Daniel Dunbar76c4d762009-07-31 21:55:09 +00002407 // Handle the identifier as the key symbol.
Daniel Dunbar4c7c08b2010-07-12 19:52:10 +00002408 MCSymbol *Sym = getContext().GetOrCreateSymbol(Name);
Chris Lattner4e4db7a2009-07-07 20:30:46 +00002409
Daniel Dunbar8f34bea2010-07-12 18:03:11 +00002410 if (getLexer().isNot(AsmToken::Comma))
Chris Lattner4e4db7a2009-07-07 20:30:46 +00002411 return TokError("unexpected token in directive");
Sean Callanan79ed1a82010-01-19 20:22:31 +00002412 Lex();
Chris Lattner4e4db7a2009-07-07 20:30:46 +00002413
2414 int64_t Size;
Daniel Dunbar8f34bea2010-07-12 18:03:11 +00002415 SMLoc SizeLoc = getLexer().getLoc();
Chris Lattner4e4db7a2009-07-07 20:30:46 +00002416 if (ParseAbsoluteExpression(Size))
2417 return true;
2418
2419 int64_t Pow2Alignment = 0;
2420 SMLoc Pow2AlignmentLoc;
Daniel Dunbar8f34bea2010-07-12 18:03:11 +00002421 if (getLexer().is(AsmToken::Comma)) {
Sean Callanan79ed1a82010-01-19 20:22:31 +00002422 Lex();
Daniel Dunbar8f34bea2010-07-12 18:03:11 +00002423 Pow2AlignmentLoc = getLexer().getLoc();
Chris Lattner4e4db7a2009-07-07 20:30:46 +00002424 if (ParseAbsoluteExpression(Pow2Alignment))
2425 return true;
Michael J. Spencerc0c8df32010-10-09 11:00:50 +00002426
Benjamin Kramera9e37c52012-09-07 21:08:01 +00002427 LCOMM::LCOMMType LCOMM = Lexer.getMAI().getLCOMMDirectiveAlignmentType();
2428 if (IsLocal && LCOMM == LCOMM::NoAlignment)
Benjamin Kramer39646d92012-09-07 17:25:13 +00002429 return Error(Pow2AlignmentLoc, "alignment not supported on this target");
2430
Chris Lattner258281d2010-01-19 06:22:22 +00002431 // If this target takes alignments in bytes (not log) validate and convert.
Benjamin Kramera9e37c52012-09-07 21:08:01 +00002432 if ((!IsLocal && Lexer.getMAI().getCOMMDirectiveAlignmentIsInBytes()) ||
2433 (IsLocal && LCOMM == LCOMM::ByteAlignment)) {
Chris Lattner258281d2010-01-19 06:22:22 +00002434 if (!isPowerOf2_64(Pow2Alignment))
2435 return Error(Pow2AlignmentLoc, "alignment must be a power of 2");
2436 Pow2Alignment = Log2_64(Pow2Alignment);
2437 }
Chris Lattner4e4db7a2009-07-07 20:30:46 +00002438 }
Michael J. Spencerc0c8df32010-10-09 11:00:50 +00002439
Daniel Dunbar8f34bea2010-07-12 18:03:11 +00002440 if (getLexer().isNot(AsmToken::EndOfStatement))
Chris Lattner1fc3d752009-07-09 17:25:12 +00002441 return TokError("unexpected token in '.comm' or '.lcomm' directive");
Michael J. Spencerc0c8df32010-10-09 11:00:50 +00002442
Sean Callanan79ed1a82010-01-19 20:22:31 +00002443 Lex();
Chris Lattner4e4db7a2009-07-07 20:30:46 +00002444
Chris Lattner1fc3d752009-07-09 17:25:12 +00002445 // NOTE: a size of zero for a .comm should create a undefined symbol
2446 // but a size of .lcomm creates a bss symbol of size zero.
Chris Lattner4e4db7a2009-07-07 20:30:46 +00002447 if (Size < 0)
Chris Lattner1fc3d752009-07-09 17:25:12 +00002448 return Error(SizeLoc, "invalid '.comm' or '.lcomm' directive size, can't "
2449 "be less than zero");
Chris Lattner4e4db7a2009-07-07 20:30:46 +00002450
Eric Christopherc260a3e2010-05-14 01:38:54 +00002451 // NOTE: The alignment in the directive is a power of 2 value, the assembler
Chris Lattner4e4db7a2009-07-07 20:30:46 +00002452 // may internally end up wanting an alignment in bytes.
2453 // FIXME: Diagnose overflow.
2454 if (Pow2Alignment < 0)
Chris Lattner1fc3d752009-07-09 17:25:12 +00002455 return Error(Pow2AlignmentLoc, "invalid '.comm' or '.lcomm' directive "
2456 "alignment, can't be less than zero");
Chris Lattner4e4db7a2009-07-07 20:30:46 +00002457
Daniel Dunbar8906ff12009-08-22 07:22:36 +00002458 if (!Sym->isUndefined())
Chris Lattner4e4db7a2009-07-07 20:30:46 +00002459 return Error(IDLoc, "invalid symbol redefinition");
2460
Chris Lattner1fc3d752009-07-09 17:25:12 +00002461 // Create the Symbol as a common or local common with Size and Pow2Alignment
Daniel Dunbar7092c7e2009-08-30 06:17:16 +00002462 if (IsLocal) {
Benjamin Kramer39646d92012-09-07 17:25:13 +00002463 getStreamer().EmitLocalCommonSymbol(Sym, Size, 1 << Pow2Alignment);
Daniel Dunbar7092c7e2009-08-30 06:17:16 +00002464 return false;
2465 }
Chris Lattner4e4db7a2009-07-07 20:30:46 +00002466
Daniel Dunbar8f34bea2010-07-12 18:03:11 +00002467 getStreamer().EmitCommonSymbol(Sym, Size, 1 << Pow2Alignment);
Chris Lattner4e4db7a2009-07-07 20:30:46 +00002468 return false;
2469}
Chris Lattner9be3fee2009-07-10 22:20:30 +00002470
Kevin Enderby5f1f0b82009-07-13 23:15:14 +00002471/// ParseDirectiveAbort
Daniel Dunbar6a46d572010-07-18 20:15:59 +00002472/// ::= .abort [... message ...]
Kevin Enderby5f1f0b82009-07-13 23:15:14 +00002473bool AsmParser::ParseDirectiveAbort() {
Daniel Dunbarf9507ff2009-07-27 23:20:52 +00002474 // FIXME: Use loc from directive.
Daniel Dunbar8f34bea2010-07-12 18:03:11 +00002475 SMLoc Loc = getLexer().getLoc();
Daniel Dunbarf9507ff2009-07-27 23:20:52 +00002476
Daniel Dunbar6a46d572010-07-18 20:15:59 +00002477 StringRef Str = ParseStringToEndOfStatement();
Daniel Dunbar8f34bea2010-07-12 18:03:11 +00002478 if (getLexer().isNot(AsmToken::EndOfStatement))
Kevin Enderby5f1f0b82009-07-13 23:15:14 +00002479 return TokError("unexpected token in '.abort' directive");
Daniel Dunbar6a46d572010-07-18 20:15:59 +00002480
Sean Callanan79ed1a82010-01-19 20:22:31 +00002481 Lex();
Kevin Enderby5f1f0b82009-07-13 23:15:14 +00002482
Daniel Dunbarf9507ff2009-07-27 23:20:52 +00002483 if (Str.empty())
2484 Error(Loc, ".abort detected. Assembly stopping.");
2485 else
2486 Error(Loc, ".abort '" + Str + "' detected. Assembly stopping.");
Daniel Dunbar6a46d572010-07-18 20:15:59 +00002487 // FIXME: Actually abort assembly here.
Kevin Enderby5f1f0b82009-07-13 23:15:14 +00002488
2489 return false;
2490}
Kevin Enderby71148242009-07-14 21:35:03 +00002491
Kevin Enderby1f049b22009-07-14 23:21:55 +00002492/// ParseDirectiveInclude
2493/// ::= .include "filename"
2494bool AsmParser::ParseDirectiveInclude() {
Daniel Dunbar8f34bea2010-07-12 18:03:11 +00002495 if (getLexer().isNot(AsmToken::String))
Kevin Enderby1f049b22009-07-14 23:21:55 +00002496 return TokError("expected string in '.include' directive");
Michael J. Spencerc0c8df32010-10-09 11:00:50 +00002497
Sean Callanan18b83232010-01-19 21:44:56 +00002498 std::string Filename = getTok().getString();
Daniel Dunbar8f34bea2010-07-12 18:03:11 +00002499 SMLoc IncludeLoc = getLexer().getLoc();
Sean Callanan79ed1a82010-01-19 20:22:31 +00002500 Lex();
Kevin Enderby1f049b22009-07-14 23:21:55 +00002501
Daniel Dunbar8f34bea2010-07-12 18:03:11 +00002502 if (getLexer().isNot(AsmToken::EndOfStatement))
Kevin Enderby1f049b22009-07-14 23:21:55 +00002503 return TokError("unexpected token in '.include' directive");
Michael J. Spencerc0c8df32010-10-09 11:00:50 +00002504
Chris Lattner8e25e2d2009-07-16 06:14:39 +00002505 // Strip the quotes.
2506 Filename = Filename.substr(1, Filename.size()-2);
Michael J. Spencerc0c8df32010-10-09 11:00:50 +00002507
Chris Lattner8e25e2d2009-07-16 06:14:39 +00002508 // Attempt to switch the lexer to the included file before consuming the end
2509 // of statement to avoid losing it when we switch.
Sean Callananfd0b0282010-01-21 00:19:58 +00002510 if (EnterIncludeFile(Filename)) {
Daniel Dunbar275ce392010-07-18 18:31:45 +00002511 Error(IncludeLoc, "Could not find include file '" + Filename + "'");
Chris Lattner8e25e2d2009-07-16 06:14:39 +00002512 return true;
2513 }
Kevin Enderby1f049b22009-07-14 23:21:55 +00002514
2515 return false;
2516}
Kevin Enderby6e68cd92009-07-15 15:30:11 +00002517
Kevin Enderbyc55acca2011-12-14 21:47:48 +00002518/// ParseDirectiveIncbin
2519/// ::= .incbin "filename"
2520bool AsmParser::ParseDirectiveIncbin() {
2521 if (getLexer().isNot(AsmToken::String))
2522 return TokError("expected string in '.incbin' directive");
2523
2524 std::string Filename = getTok().getString();
2525 SMLoc IncbinLoc = getLexer().getLoc();
2526 Lex();
2527
2528 if (getLexer().isNot(AsmToken::EndOfStatement))
2529 return TokError("unexpected token in '.incbin' directive");
2530
2531 // Strip the quotes.
2532 Filename = Filename.substr(1, Filename.size()-2);
2533
2534 // Attempt to process the included file.
2535 if (ProcessIncbinFile(Filename)) {
2536 Error(IncbinLoc, "Could not find incbin file '" + Filename + "'");
2537 return true;
2538 }
2539
2540 return false;
2541}
2542
Kevin Enderbyc114ed72009-08-07 22:46:00 +00002543/// ParseDirectiveIf
2544/// ::= .if expression
2545bool AsmParser::ParseDirectiveIf(SMLoc DirectiveLoc) {
Kevin Enderbyc114ed72009-08-07 22:46:00 +00002546 TheCondStack.push_back(TheCondState);
2547 TheCondState.TheCond = AsmCond::IfCond;
Benjamin Kramer29739e72012-05-12 16:52:21 +00002548 if (TheCondState.Ignore) {
Kevin Enderbyc114ed72009-08-07 22:46:00 +00002549 EatToEndOfStatement();
Benjamin Kramer29739e72012-05-12 16:52:21 +00002550 } else {
Kevin Enderbyc114ed72009-08-07 22:46:00 +00002551 int64_t ExprValue;
2552 if (ParseAbsoluteExpression(ExprValue))
2553 return true;
2554
Daniel Dunbar8f34bea2010-07-12 18:03:11 +00002555 if (getLexer().isNot(AsmToken::EndOfStatement))
Kevin Enderbyc114ed72009-08-07 22:46:00 +00002556 return TokError("unexpected token in '.if' directive");
Michael J. Spencerc0c8df32010-10-09 11:00:50 +00002557
Sean Callanan79ed1a82010-01-19 20:22:31 +00002558 Lex();
Kevin Enderbyc114ed72009-08-07 22:46:00 +00002559
2560 TheCondState.CondMet = ExprValue;
2561 TheCondState.Ignore = !TheCondState.CondMet;
2562 }
2563
2564 return false;
2565}
2566
Benjamin Kramera3dd0eb2012-05-12 11:18:42 +00002567/// ParseDirectiveIfb
2568/// ::= .ifb string
2569bool AsmParser::ParseDirectiveIfb(SMLoc DirectiveLoc, bool ExpectBlank) {
2570 TheCondStack.push_back(TheCondState);
2571 TheCondState.TheCond = AsmCond::IfCond;
2572
Benjamin Kramer29739e72012-05-12 16:52:21 +00002573 if (TheCondState.Ignore) {
Benjamin Kramera3dd0eb2012-05-12 11:18:42 +00002574 EatToEndOfStatement();
2575 } else {
2576 StringRef Str = ParseStringToEndOfStatement();
2577
2578 if (getLexer().isNot(AsmToken::EndOfStatement))
2579 return TokError("unexpected token in '.ifb' directive");
2580
2581 Lex();
2582
2583 TheCondState.CondMet = ExpectBlank == Str.empty();
2584 TheCondState.Ignore = !TheCondState.CondMet;
2585 }
2586
2587 return false;
2588}
2589
Benjamin Kramerdec06ef2012-05-12 11:18:51 +00002590/// ParseDirectiveIfc
2591/// ::= .ifc string1, string2
2592bool AsmParser::ParseDirectiveIfc(SMLoc DirectiveLoc, bool ExpectEqual) {
2593 TheCondStack.push_back(TheCondState);
2594 TheCondState.TheCond = AsmCond::IfCond;
2595
Benjamin Kramer29739e72012-05-12 16:52:21 +00002596 if (TheCondState.Ignore) {
Benjamin Kramerdec06ef2012-05-12 11:18:51 +00002597 EatToEndOfStatement();
2598 } else {
2599 StringRef Str1 = ParseStringToComma();
2600
2601 if (getLexer().isNot(AsmToken::Comma))
2602 return TokError("unexpected token in '.ifc' directive");
2603
2604 Lex();
2605
2606 StringRef Str2 = ParseStringToEndOfStatement();
2607
2608 if (getLexer().isNot(AsmToken::EndOfStatement))
2609 return TokError("unexpected token in '.ifc' directive");
2610
2611 Lex();
2612
2613 TheCondState.CondMet = ExpectEqual == (Str1 == Str2);
2614 TheCondState.Ignore = !TheCondState.CondMet;
2615 }
2616
2617 return false;
2618}
2619
2620/// ParseDirectiveIfdef
2621/// ::= .ifdef symbol
Benjamin Kramer0fd90bc2011-02-08 22:29:56 +00002622bool AsmParser::ParseDirectiveIfdef(SMLoc DirectiveLoc, bool expect_defined) {
2623 StringRef Name;
2624 TheCondStack.push_back(TheCondState);
2625 TheCondState.TheCond = AsmCond::IfCond;
2626
2627 if (TheCondState.Ignore) {
2628 EatToEndOfStatement();
2629 } else {
2630 if (ParseIdentifier(Name))
2631 return TokError("expected identifier after '.ifdef'");
2632
2633 Lex();
2634
2635 MCSymbol *Sym = getContext().LookupSymbol(Name);
2636
2637 if (expect_defined)
2638 TheCondState.CondMet = (Sym != NULL && !Sym->isUndefined());
2639 else
2640 TheCondState.CondMet = (Sym == NULL || Sym->isUndefined());
2641 TheCondState.Ignore = !TheCondState.CondMet;
2642 }
2643
2644 return false;
2645}
2646
Kevin Enderbyc114ed72009-08-07 22:46:00 +00002647/// ParseDirectiveElseIf
2648/// ::= .elseif expression
2649bool AsmParser::ParseDirectiveElseIf(SMLoc DirectiveLoc) {
2650 if (TheCondState.TheCond != AsmCond::IfCond &&
2651 TheCondState.TheCond != AsmCond::ElseIfCond)
2652 Error(DirectiveLoc, "Encountered a .elseif that doesn't follow a .if or "
2653 " an .elseif");
2654 TheCondState.TheCond = AsmCond::ElseIfCond;
2655
Kevin Enderbyc114ed72009-08-07 22:46:00 +00002656 bool LastIgnoreState = false;
2657 if (!TheCondStack.empty())
2658 LastIgnoreState = TheCondStack.back().Ignore;
2659 if (LastIgnoreState || TheCondState.CondMet) {
2660 TheCondState.Ignore = true;
2661 EatToEndOfStatement();
2662 }
2663 else {
2664 int64_t ExprValue;
2665 if (ParseAbsoluteExpression(ExprValue))
2666 return true;
2667
Daniel Dunbar8f34bea2010-07-12 18:03:11 +00002668 if (getLexer().isNot(AsmToken::EndOfStatement))
Kevin Enderbyc114ed72009-08-07 22:46:00 +00002669 return TokError("unexpected token in '.elseif' directive");
Michael J. Spencerc0c8df32010-10-09 11:00:50 +00002670
Sean Callanan79ed1a82010-01-19 20:22:31 +00002671 Lex();
Kevin Enderbyc114ed72009-08-07 22:46:00 +00002672 TheCondState.CondMet = ExprValue;
2673 TheCondState.Ignore = !TheCondState.CondMet;
2674 }
2675
2676 return false;
2677}
2678
2679/// ParseDirectiveElse
2680/// ::= .else
2681bool AsmParser::ParseDirectiveElse(SMLoc DirectiveLoc) {
Daniel Dunbar8f34bea2010-07-12 18:03:11 +00002682 if (getLexer().isNot(AsmToken::EndOfStatement))
Kevin Enderbyc114ed72009-08-07 22:46:00 +00002683 return TokError("unexpected token in '.else' directive");
Michael J. Spencerc0c8df32010-10-09 11:00:50 +00002684
Sean Callanan79ed1a82010-01-19 20:22:31 +00002685 Lex();
Kevin Enderbyc114ed72009-08-07 22:46:00 +00002686
2687 if (TheCondState.TheCond != AsmCond::IfCond &&
2688 TheCondState.TheCond != AsmCond::ElseIfCond)
2689 Error(DirectiveLoc, "Encountered a .else that doesn't follow a .if or an "
2690 ".elseif");
2691 TheCondState.TheCond = AsmCond::ElseCond;
2692 bool LastIgnoreState = false;
2693 if (!TheCondStack.empty())
2694 LastIgnoreState = TheCondStack.back().Ignore;
2695 if (LastIgnoreState || TheCondState.CondMet)
2696 TheCondState.Ignore = true;
2697 else
2698 TheCondState.Ignore = false;
2699
2700 return false;
2701}
2702
2703/// ParseDirectiveEndIf
2704/// ::= .endif
2705bool AsmParser::ParseDirectiveEndIf(SMLoc DirectiveLoc) {
Daniel Dunbar8f34bea2010-07-12 18:03:11 +00002706 if (getLexer().isNot(AsmToken::EndOfStatement))
Kevin Enderbyc114ed72009-08-07 22:46:00 +00002707 return TokError("unexpected token in '.endif' directive");
Michael J. Spencerc0c8df32010-10-09 11:00:50 +00002708
Sean Callanan79ed1a82010-01-19 20:22:31 +00002709 Lex();
Kevin Enderbyc114ed72009-08-07 22:46:00 +00002710
2711 if ((TheCondState.TheCond == AsmCond::NoCond) ||
2712 TheCondStack.empty())
2713 Error(DirectiveLoc, "Encountered a .endif that doesn't follow a .if or "
2714 ".else");
2715 if (!TheCondStack.empty()) {
2716 TheCondState = TheCondStack.back();
2717 TheCondStack.pop_back();
2718 }
2719
2720 return false;
2721}
Daniel Dunbard0c14d62009-08-11 04:24:50 +00002722
2723/// ParseDirectiveFile
Nick Lewycky44d798d2011-10-17 23:05:28 +00002724/// ::= .file [number] filename
2725/// ::= .file number directory filename
Daniel Dunbar81ea00f2010-07-12 17:54:38 +00002726bool GenericAsmParser::ParseDirectiveFile(StringRef, SMLoc DirectiveLoc) {
Daniel Dunbard0c14d62009-08-11 04:24:50 +00002727 // FIXME: I'm not sure what this is.
2728 int64_t FileNumber = -1;
Kevin Enderby7cbf73a2010-07-28 20:55:35 +00002729 SMLoc FileNumberLoc = getLexer().getLoc();
Daniel Dunbareceec052010-07-12 17:45:27 +00002730 if (getLexer().is(AsmToken::Integer)) {
Sean Callanan18b83232010-01-19 21:44:56 +00002731 FileNumber = getTok().getIntVal();
Sean Callanan79ed1a82010-01-19 20:22:31 +00002732 Lex();
Daniel Dunbareceec052010-07-12 17:45:27 +00002733
Daniel Dunbard0c14d62009-08-11 04:24:50 +00002734 if (FileNumber < 1)
2735 return TokError("file number less than one");
2736 }
2737
Daniel Dunbareceec052010-07-12 17:45:27 +00002738 if (getLexer().isNot(AsmToken::String))
Daniel Dunbard0c14d62009-08-11 04:24:50 +00002739 return TokError("unexpected token in '.file' directive");
Daniel Dunbareceec052010-07-12 17:45:27 +00002740
Nick Lewycky44d798d2011-10-17 23:05:28 +00002741 // Usually the directory and filename together, otherwise just the directory.
2742 StringRef Path = getTok().getString();
2743 Path = Path.substr(1, Path.size()-2);
Sean Callanan79ed1a82010-01-19 20:22:31 +00002744 Lex();
Daniel Dunbard0c14d62009-08-11 04:24:50 +00002745
Nick Lewycky44d798d2011-10-17 23:05:28 +00002746 StringRef Directory;
2747 StringRef Filename;
2748 if (getLexer().is(AsmToken::String)) {
2749 if (FileNumber == -1)
2750 return TokError("explicit path specified, but no file number");
2751 Filename = getTok().getString();
2752 Filename = Filename.substr(1, Filename.size()-2);
2753 Directory = Path;
2754 Lex();
2755 } else {
2756 Filename = Path;
2757 }
2758
Daniel Dunbareceec052010-07-12 17:45:27 +00002759 if (getLexer().isNot(AsmToken::EndOfStatement))
Daniel Dunbard0c14d62009-08-11 04:24:50 +00002760 return TokError("unexpected token in '.file' directive");
2761
Chris Lattnerd32e8032010-01-25 19:02:58 +00002762 if (FileNumber == -1)
Daniel Dunbareceec052010-07-12 17:45:27 +00002763 getStreamer().EmitFileDirective(Filename);
Kevin Enderby7cbf73a2010-07-28 20:55:35 +00002764 else {
Kevin Enderby8704b782012-01-11 18:04:47 +00002765 if (getContext().getGenDwarfForAssembly() == true)
2766 Error(DirectiveLoc, "input can't have .file dwarf directives when -g is "
2767 "used to generate dwarf debug info for assembly code");
2768
Nick Lewycky44d798d2011-10-17 23:05:28 +00002769 if (getStreamer().EmitDwarfFileDirective(FileNumber, Directory, Filename))
Michael J. Spencerc0c8df32010-10-09 11:00:50 +00002770 Error(FileNumberLoc, "file number already allocated");
Kevin Enderby7cbf73a2010-07-28 20:55:35 +00002771 }
Daniel Dunbareceec052010-07-12 17:45:27 +00002772
Daniel Dunbard0c14d62009-08-11 04:24:50 +00002773 return false;
2774}
2775
2776/// ParseDirectiveLine
2777/// ::= .line [number]
Daniel Dunbar81ea00f2010-07-12 17:54:38 +00002778bool GenericAsmParser::ParseDirectiveLine(StringRef, SMLoc DirectiveLoc) {
Daniel Dunbareceec052010-07-12 17:45:27 +00002779 if (getLexer().isNot(AsmToken::EndOfStatement)) {
2780 if (getLexer().isNot(AsmToken::Integer))
Daniel Dunbard0c14d62009-08-11 04:24:50 +00002781 return TokError("unexpected token in '.line' directive");
2782
Sean Callanan18b83232010-01-19 21:44:56 +00002783 int64_t LineNumber = getTok().getIntVal();
Daniel Dunbard0c14d62009-08-11 04:24:50 +00002784 (void) LineNumber;
Sean Callanan79ed1a82010-01-19 20:22:31 +00002785 Lex();
Daniel Dunbard0c14d62009-08-11 04:24:50 +00002786
2787 // FIXME: Do something with the .line.
2788 }
2789
Daniel Dunbareceec052010-07-12 17:45:27 +00002790 if (getLexer().isNot(AsmToken::EndOfStatement))
Daniel Dunbar839348a2010-07-01 20:20:01 +00002791 return TokError("unexpected token in '.line' directive");
Daniel Dunbard0c14d62009-08-11 04:24:50 +00002792
2793 return false;
2794}
2795
2796
2797/// ParseDirectiveLoc
Kevin Enderby6d8f1a92010-08-24 21:14:47 +00002798/// ::= .loc FileNumber [LineNumber] [ColumnPos] [basic_block] [prologue_end]
Kevin Enderbyc1840b32010-08-24 20:32:42 +00002799/// [epilogue_begin] [is_stmt VALUE] [isa VALUE]
2800/// The first number is a file number, must have been previously assigned with
2801/// a .file directive, the second number is the line number and optionally the
2802/// third number is a column position (zero if not specified). The remaining
2803/// optional items are .loc sub-directives.
Daniel Dunbar81ea00f2010-07-12 17:54:38 +00002804bool GenericAsmParser::ParseDirectiveLoc(StringRef, SMLoc DirectiveLoc) {
Kevin Enderbyc1840b32010-08-24 20:32:42 +00002805
Daniel Dunbareceec052010-07-12 17:45:27 +00002806 if (getLexer().isNot(AsmToken::Integer))
Daniel Dunbard0c14d62009-08-11 04:24:50 +00002807 return TokError("unexpected token in '.loc' directive");
Sean Callanan18b83232010-01-19 21:44:56 +00002808 int64_t FileNumber = getTok().getIntVal();
Kevin Enderbyc1840b32010-08-24 20:32:42 +00002809 if (FileNumber < 1)
2810 return TokError("file number less than one in '.loc' directive");
Kevin Enderby3f55c242010-10-04 20:17:24 +00002811 if (!getContext().isValidDwarfFileNumber(FileNumber))
Kevin Enderbyc1840b32010-08-24 20:32:42 +00002812 return TokError("unassigned file number in '.loc' directive");
Sean Callanan79ed1a82010-01-19 20:22:31 +00002813 Lex();
Daniel Dunbard0c14d62009-08-11 04:24:50 +00002814
Kevin Enderby6d8f1a92010-08-24 21:14:47 +00002815 int64_t LineNumber = 0;
2816 if (getLexer().is(AsmToken::Integer)) {
2817 LineNumber = getTok().getIntVal();
2818 if (LineNumber < 1)
2819 return TokError("line number less than one in '.loc' directive");
2820 Lex();
2821 }
Kevin Enderbyc1840b32010-08-24 20:32:42 +00002822
2823 int64_t ColumnPos = 0;
2824 if (getLexer().is(AsmToken::Integer)) {
2825 ColumnPos = getTok().getIntVal();
2826 if (ColumnPos < 0)
2827 return TokError("column position less than zero in '.loc' directive");
Sean Callanan79ed1a82010-01-19 20:22:31 +00002828 Lex();
Kevin Enderbyc1840b32010-08-24 20:32:42 +00002829 }
Daniel Dunbard0c14d62009-08-11 04:24:50 +00002830
Kevin Enderbyc0957932010-09-30 16:52:03 +00002831 unsigned Flags = DWARF2_LINE_DEFAULT_IS_STMT ? DWARF2_FLAG_IS_STMT : 0;
Kevin Enderbyc1840b32010-08-24 20:32:42 +00002832 unsigned Isa = 0;
Rafael Espindolac50a0fd2010-11-13 03:18:27 +00002833 int64_t Discriminator = 0;
Kevin Enderbyc1840b32010-08-24 20:32:42 +00002834 if (getLexer().isNot(AsmToken::EndOfStatement)) {
2835 for (;;) {
2836 if (getLexer().is(AsmToken::EndOfStatement))
2837 break;
2838
2839 StringRef Name;
2840 SMLoc Loc = getTok().getLoc();
2841 if (getParser().ParseIdentifier(Name))
Daniel Dunbard0c14d62009-08-11 04:24:50 +00002842 return TokError("unexpected token in '.loc' directive");
2843
Kevin Enderbyc1840b32010-08-24 20:32:42 +00002844 if (Name == "basic_block")
2845 Flags |= DWARF2_FLAG_BASIC_BLOCK;
2846 else if (Name == "prologue_end")
2847 Flags |= DWARF2_FLAG_PROLOGUE_END;
2848 else if (Name == "epilogue_begin")
2849 Flags |= DWARF2_FLAG_EPILOGUE_BEGIN;
2850 else if (Name == "is_stmt") {
2851 SMLoc Loc = getTok().getLoc();
2852 const MCExpr *Value;
2853 if (getParser().ParseExpression(Value))
2854 return true;
2855 // The expression must be the constant 0 or 1.
2856 if (const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(Value)) {
2857 int Value = MCE->getValue();
2858 if (Value == 0)
2859 Flags &= ~DWARF2_FLAG_IS_STMT;
2860 else if (Value == 1)
2861 Flags |= DWARF2_FLAG_IS_STMT;
2862 else
2863 return Error(Loc, "is_stmt value not 0 or 1");
Michael J. Spencerc0c8df32010-10-09 11:00:50 +00002864 }
Kevin Enderbyc1840b32010-08-24 20:32:42 +00002865 else {
2866 return Error(Loc, "is_stmt value not the constant value of 0 or 1");
2867 }
2868 }
2869 else if (Name == "isa") {
2870 SMLoc Loc = getTok().getLoc();
2871 const MCExpr *Value;
2872 if (getParser().ParseExpression(Value))
2873 return true;
2874 // The expression must be a constant greater or equal to 0.
2875 if (const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(Value)) {
2876 int Value = MCE->getValue();
2877 if (Value < 0)
2878 return Error(Loc, "isa number less than zero");
2879 Isa = Value;
Michael J. Spencerc0c8df32010-10-09 11:00:50 +00002880 }
Kevin Enderbyc1840b32010-08-24 20:32:42 +00002881 else {
2882 return Error(Loc, "isa number not a constant value");
2883 }
2884 }
Rafael Espindolac50a0fd2010-11-13 03:18:27 +00002885 else if (Name == "discriminator") {
2886 if (getParser().ParseAbsoluteExpression(Discriminator))
2887 return true;
2888 }
Kevin Enderbyc1840b32010-08-24 20:32:42 +00002889 else {
2890 return Error(Loc, "unknown sub-directive in '.loc' directive");
2891 }
Daniel Dunbard0c14d62009-08-11 04:24:50 +00002892
Kevin Enderbyc1840b32010-08-24 20:32:42 +00002893 if (getLexer().is(AsmToken::EndOfStatement))
2894 break;
Daniel Dunbard0c14d62009-08-11 04:24:50 +00002895 }
2896 }
2897
Rafael Espindolaaf6b58082010-11-16 21:20:32 +00002898 getStreamer().EmitDwarfLocDirective(FileNumber, LineNumber, ColumnPos, Flags,
Devang Patel3f3bf932011-04-18 20:26:49 +00002899 Isa, Discriminator, StringRef());
Daniel Dunbard0c14d62009-08-11 04:24:50 +00002900
2901 return false;
2902}
2903
Daniel Dunbar138abae2010-10-16 04:56:42 +00002904/// ParseDirectiveStabs
2905/// ::= .stabs string, number, number, number
2906bool GenericAsmParser::ParseDirectiveStabs(StringRef Directive,
2907 SMLoc DirectiveLoc) {
2908 return TokError("unsupported directive '" + Directive + "'");
2909}
2910
Rafael Espindolaf9efd832011-05-10 01:10:18 +00002911/// ParseDirectiveCFISections
2912/// ::= .cfi_sections section [, section]
2913bool GenericAsmParser::ParseDirectiveCFISections(StringRef,
2914 SMLoc DirectiveLoc) {
2915 StringRef Name;
2916 bool EH = false;
2917 bool Debug = false;
2918
2919 if (getParser().ParseIdentifier(Name))
2920 return TokError("Expected an identifier");
2921
2922 if (Name == ".eh_frame")
2923 EH = true;
2924 else if (Name == ".debug_frame")
2925 Debug = true;
2926
2927 if (getLexer().is(AsmToken::Comma)) {
2928 Lex();
2929
2930 if (getParser().ParseIdentifier(Name))
2931 return TokError("Expected an identifier");
2932
2933 if (Name == ".eh_frame")
2934 EH = true;
2935 else if (Name == ".debug_frame")
2936 Debug = true;
2937 }
2938
2939 getStreamer().EmitCFISections(EH, Debug);
2940
2941 return false;
2942}
2943
Rafael Espindola1fdfbc42010-11-16 18:34:07 +00002944/// ParseDirectiveCFIStartProc
2945/// ::= .cfi_startproc
2946bool GenericAsmParser::ParseDirectiveCFIStartProc(StringRef,
2947 SMLoc DirectiveLoc) {
Rafael Espindola066c2f42011-04-12 23:59:07 +00002948 getStreamer().EmitCFIStartProc();
2949 return false;
Rafael Espindola1fdfbc42010-11-16 18:34:07 +00002950}
2951
2952/// ParseDirectiveCFIEndProc
2953/// ::= .cfi_endproc
2954bool GenericAsmParser::ParseDirectiveCFIEndProc(StringRef, SMLoc DirectiveLoc) {
Rafael Espindola066c2f42011-04-12 23:59:07 +00002955 getStreamer().EmitCFIEndProc();
2956 return false;
Rafael Espindola1fdfbc42010-11-16 18:34:07 +00002957}
2958
Roman Divacky54b0f4f2011-01-27 17:16:37 +00002959/// ParseRegisterOrRegisterNumber - parse register name or number.
2960bool GenericAsmParser::ParseRegisterOrRegisterNumber(int64_t &Register,
2961 SMLoc DirectiveLoc) {
2962 unsigned RegNo;
2963
Jim Grosbach6f888a82011-06-02 17:14:04 +00002964 if (getLexer().isNot(AsmToken::Integer)) {
Roman Divacky54b0f4f2011-01-27 17:16:37 +00002965 if (getParser().getTargetParser().ParseRegister(RegNo, DirectiveLoc,
2966 DirectiveLoc))
2967 return true;
Evan Cheng0e6a0522011-07-18 20:57:22 +00002968 Register = getContext().getRegisterInfo().getDwarfRegNum(RegNo, true);
Roman Divacky54b0f4f2011-01-27 17:16:37 +00002969 } else
2970 return getParser().ParseAbsoluteExpression(Register);
Jim Grosbachde2f5f42011-02-11 19:05:56 +00002971
Roman Divacky54b0f4f2011-01-27 17:16:37 +00002972 return false;
2973}
2974
Rafael Espindolab40a71f2010-12-29 01:42:56 +00002975/// ParseDirectiveCFIDefCfa
2976/// ::= .cfi_def_cfa register, offset
2977bool GenericAsmParser::ParseDirectiveCFIDefCfa(StringRef,
2978 SMLoc DirectiveLoc) {
2979 int64_t Register = 0;
Roman Divacky54b0f4f2011-01-27 17:16:37 +00002980 if (ParseRegisterOrRegisterNumber(Register, DirectiveLoc))
Rafael Espindolab40a71f2010-12-29 01:42:56 +00002981 return true;
2982
2983 if (getLexer().isNot(AsmToken::Comma))
2984 return TokError("unexpected token in directive");
2985 Lex();
2986
2987 int64_t Offset = 0;
2988 if (getParser().ParseAbsoluteExpression(Offset))
2989 return true;
2990
Rafael Espindola066c2f42011-04-12 23:59:07 +00002991 getStreamer().EmitCFIDefCfa(Register, Offset);
2992 return false;
Rafael Espindolab40a71f2010-12-29 01:42:56 +00002993}
2994
Rafael Espindola1fdfbc42010-11-16 18:34:07 +00002995/// ParseDirectiveCFIDefCfaOffset
2996/// ::= .cfi_def_cfa_offset offset
2997bool GenericAsmParser::ParseDirectiveCFIDefCfaOffset(StringRef,
2998 SMLoc DirectiveLoc) {
2999 int64_t Offset = 0;
3000 if (getParser().ParseAbsoluteExpression(Offset))
3001 return true;
3002
Rafael Espindola066c2f42011-04-12 23:59:07 +00003003 getStreamer().EmitCFIDefCfaOffset(Offset);
3004 return false;
Rafael Espindola53abbe52011-04-11 20:29:16 +00003005}
3006
3007/// ParseDirectiveCFIAdjustCfaOffset
3008/// ::= .cfi_adjust_cfa_offset adjustment
3009bool GenericAsmParser::ParseDirectiveCFIAdjustCfaOffset(StringRef,
3010 SMLoc DirectiveLoc) {
3011 int64_t Adjustment = 0;
3012 if (getParser().ParseAbsoluteExpression(Adjustment))
3013 return true;
3014
Rafael Espindola5d7dcd32011-04-12 18:53:30 +00003015 getStreamer().EmitCFIAdjustCfaOffset(Adjustment);
3016 return false;
Rafael Espindola1fdfbc42010-11-16 18:34:07 +00003017}
3018
3019/// ParseDirectiveCFIDefCfaRegister
3020/// ::= .cfi_def_cfa_register register
3021bool GenericAsmParser::ParseDirectiveCFIDefCfaRegister(StringRef,
3022 SMLoc DirectiveLoc) {
3023 int64_t Register = 0;
Roman Divacky54b0f4f2011-01-27 17:16:37 +00003024 if (ParseRegisterOrRegisterNumber(Register, DirectiveLoc))
Rafael Espindola1fdfbc42010-11-16 18:34:07 +00003025 return true;
Rafael Espindolacdfecc82010-11-22 14:27:24 +00003026
Rafael Espindola066c2f42011-04-12 23:59:07 +00003027 getStreamer().EmitCFIDefCfaRegister(Register);
3028 return false;
Rafael Espindola1fdfbc42010-11-16 18:34:07 +00003029}
3030
3031/// ParseDirectiveCFIOffset
Rafael Espindolaa61842b2011-04-11 21:49:50 +00003032/// ::= .cfi_offset register, offset
Rafael Espindola1fdfbc42010-11-16 18:34:07 +00003033bool GenericAsmParser::ParseDirectiveCFIOffset(StringRef, SMLoc DirectiveLoc) {
3034 int64_t Register = 0;
3035 int64_t Offset = 0;
Roman Divacky54b0f4f2011-01-27 17:16:37 +00003036
3037 if (ParseRegisterOrRegisterNumber(Register, DirectiveLoc))
Rafael Espindola1fdfbc42010-11-16 18:34:07 +00003038 return true;
3039
3040 if (getLexer().isNot(AsmToken::Comma))
3041 return TokError("unexpected token in directive");
3042 Lex();
3043
3044 if (getParser().ParseAbsoluteExpression(Offset))
3045 return true;
3046
Rafael Espindola066c2f42011-04-12 23:59:07 +00003047 getStreamer().EmitCFIOffset(Register, Offset);
3048 return false;
Rafael Espindola1fdfbc42010-11-16 18:34:07 +00003049}
3050
Rafael Espindolaa61842b2011-04-11 21:49:50 +00003051/// ParseDirectiveCFIRelOffset
3052/// ::= .cfi_rel_offset register, offset
3053bool GenericAsmParser::ParseDirectiveCFIRelOffset(StringRef,
3054 SMLoc DirectiveLoc) {
3055 int64_t Register = 0;
3056
3057 if (ParseRegisterOrRegisterNumber(Register, DirectiveLoc))
3058 return true;
3059
3060 if (getLexer().isNot(AsmToken::Comma))
3061 return TokError("unexpected token in directive");
3062 Lex();
3063
3064 int64_t Offset = 0;
3065 if (getParser().ParseAbsoluteExpression(Offset))
3066 return true;
3067
Rafael Espindola25f492e2011-04-12 16:12:03 +00003068 getStreamer().EmitCFIRelOffset(Register, Offset);
3069 return false;
Rafael Espindolaa61842b2011-04-11 21:49:50 +00003070}
3071
Rafael Espindolad7c8cca2010-12-26 20:20:31 +00003072static bool isValidEncoding(int64_t Encoding) {
3073 if (Encoding & ~0xff)
3074 return false;
3075
3076 if (Encoding == dwarf::DW_EH_PE_omit)
3077 return true;
3078
3079 const unsigned Format = Encoding & 0xf;
3080 if (Format != dwarf::DW_EH_PE_absptr && Format != dwarf::DW_EH_PE_udata2 &&
3081 Format != dwarf::DW_EH_PE_udata4 && Format != dwarf::DW_EH_PE_udata8 &&
3082 Format != dwarf::DW_EH_PE_sdata2 && Format != dwarf::DW_EH_PE_sdata4 &&
3083 Format != dwarf::DW_EH_PE_sdata8 && Format != dwarf::DW_EH_PE_signed)
3084 return false;
3085
Rafael Espindolacaf11582010-12-29 04:31:26 +00003086 const unsigned Application = Encoding & 0x70;
Rafael Espindolad7c8cca2010-12-26 20:20:31 +00003087 if (Application != dwarf::DW_EH_PE_absptr &&
Rafael Espindolacaf11582010-12-29 04:31:26 +00003088 Application != dwarf::DW_EH_PE_pcrel)
Rafael Espindolad7c8cca2010-12-26 20:20:31 +00003089 return false;
3090
3091 return true;
3092}
3093
Rafael Espindola1fdfbc42010-11-16 18:34:07 +00003094/// ParseDirectiveCFIPersonalityOrLsda
3095/// ::= .cfi_personality encoding, [symbol_name]
3096/// ::= .cfi_lsda encoding, [symbol_name]
Rafael Espindolacdfecc82010-11-22 14:27:24 +00003097bool GenericAsmParser::ParseDirectiveCFIPersonalityOrLsda(StringRef IDVal,
Rafael Espindola1fdfbc42010-11-16 18:34:07 +00003098 SMLoc DirectiveLoc) {
3099 int64_t Encoding = 0;
3100 if (getParser().ParseAbsoluteExpression(Encoding))
3101 return true;
Rafael Espindolad7c8cca2010-12-26 20:20:31 +00003102 if (Encoding == dwarf::DW_EH_PE_omit)
Rafael Espindola1fdfbc42010-11-16 18:34:07 +00003103 return false;
3104
Rafael Espindolad7c8cca2010-12-26 20:20:31 +00003105 if (!isValidEncoding(Encoding))
Rafael Espindolacdfecc82010-11-22 14:27:24 +00003106 return TokError("unsupported encoding.");
3107
Rafael Espindola1fdfbc42010-11-16 18:34:07 +00003108 if (getLexer().isNot(AsmToken::Comma))
3109 return TokError("unexpected token in directive");
3110 Lex();
3111
3112 StringRef Name;
3113 if (getParser().ParseIdentifier(Name))
3114 return TokError("expected identifier in directive");
Rafael Espindolacdfecc82010-11-22 14:27:24 +00003115
3116 MCSymbol *Sym = getContext().GetOrCreateSymbol(Name);
3117
3118 if (IDVal == ".cfi_personality")
Rafael Espindola066c2f42011-04-12 23:59:07 +00003119 getStreamer().EmitCFIPersonality(Sym, Encoding);
Rafael Espindolacdfecc82010-11-22 14:27:24 +00003120 else {
3121 assert(IDVal == ".cfi_lsda");
Rafael Espindola066c2f42011-04-12 23:59:07 +00003122 getStreamer().EmitCFILsda(Sym, Encoding);
Rafael Espindolacdfecc82010-11-22 14:27:24 +00003123 }
Rafael Espindola066c2f42011-04-12 23:59:07 +00003124 return false;
Rafael Espindola1fdfbc42010-11-16 18:34:07 +00003125}
3126
Rafael Espindolafe024d02010-12-28 18:36:23 +00003127/// ParseDirectiveCFIRememberState
3128/// ::= .cfi_remember_state
3129bool GenericAsmParser::ParseDirectiveCFIRememberState(StringRef IDVal,
3130 SMLoc DirectiveLoc) {
Rafael Espindola066c2f42011-04-12 23:59:07 +00003131 getStreamer().EmitCFIRememberState();
3132 return false;
Rafael Espindolafe024d02010-12-28 18:36:23 +00003133}
3134
3135/// ParseDirectiveCFIRestoreState
3136/// ::= .cfi_remember_state
3137bool GenericAsmParser::ParseDirectiveCFIRestoreState(StringRef IDVal,
3138 SMLoc DirectiveLoc) {
Rafael Espindola066c2f42011-04-12 23:59:07 +00003139 getStreamer().EmitCFIRestoreState();
3140 return false;
Rafael Espindolafe024d02010-12-28 18:36:23 +00003141}
3142
Rafael Espindolac5754392011-04-12 15:31:05 +00003143/// ParseDirectiveCFISameValue
3144/// ::= .cfi_same_value register
3145bool GenericAsmParser::ParseDirectiveCFISameValue(StringRef IDVal,
3146 SMLoc DirectiveLoc) {
3147 int64_t Register = 0;
3148
3149 if (ParseRegisterOrRegisterNumber(Register, DirectiveLoc))
3150 return true;
3151
3152 getStreamer().EmitCFISameValue(Register);
3153
3154 return false;
3155}
3156
Rafael Espindolaed23bdb2011-12-29 21:43:03 +00003157/// ParseDirectiveCFIRestore
3158/// ::= .cfi_restore register
3159bool GenericAsmParser::ParseDirectiveCFIRestore(StringRef IDVal,
Bill Wendling96cb1122012-07-19 00:04:14 +00003160 SMLoc DirectiveLoc) {
Rafael Espindolaed23bdb2011-12-29 21:43:03 +00003161 int64_t Register = 0;
3162 if (ParseRegisterOrRegisterNumber(Register, DirectiveLoc))
3163 return true;
3164
3165 getStreamer().EmitCFIRestore(Register);
3166
3167 return false;
3168}
3169
Rafael Espindola6f0b1812011-12-29 20:24:47 +00003170/// ParseDirectiveCFIEscape
3171/// ::= .cfi_escape expression[,...]
3172bool GenericAsmParser::ParseDirectiveCFIEscape(StringRef IDVal,
Bill Wendling96cb1122012-07-19 00:04:14 +00003173 SMLoc DirectiveLoc) {
Rafael Espindola6f0b1812011-12-29 20:24:47 +00003174 std::string Values;
3175 int64_t CurrValue;
3176 if (getParser().ParseAbsoluteExpression(CurrValue))
3177 return true;
3178
3179 Values.push_back((uint8_t)CurrValue);
3180
3181 while (getLexer().is(AsmToken::Comma)) {
3182 Lex();
3183
3184 if (getParser().ParseAbsoluteExpression(CurrValue))
3185 return true;
3186
3187 Values.push_back((uint8_t)CurrValue);
3188 }
3189
3190 getStreamer().EmitCFIEscape(Values);
3191 return false;
3192}
3193
Rafael Espindola16d7d432012-01-23 21:51:52 +00003194/// ParseDirectiveCFISignalFrame
3195/// ::= .cfi_signal_frame
3196bool GenericAsmParser::ParseDirectiveCFISignalFrame(StringRef Directive,
3197 SMLoc DirectiveLoc) {
3198 if (getLexer().isNot(AsmToken::EndOfStatement))
3199 return Error(getLexer().getLoc(),
3200 "unexpected token in '" + Directive + "' directive");
3201
3202 getStreamer().EmitCFISignalFrame();
3203
3204 return false;
3205}
3206
Daniel Dunbar3c802de2010-07-18 18:38:02 +00003207/// ParseDirectiveMacrosOnOff
3208/// ::= .macros_on
3209/// ::= .macros_off
3210bool GenericAsmParser::ParseDirectiveMacrosOnOff(StringRef Directive,
3211 SMLoc DirectiveLoc) {
3212 if (getLexer().isNot(AsmToken::EndOfStatement))
3213 return Error(getLexer().getLoc(),
3214 "unexpected token in '" + Directive + "' directive");
3215
3216 getParser().MacrosEnabled = Directive == ".macros_on";
3217
3218 return false;
3219}
Daniel Dunbard1e3b442010-07-17 02:26:10 +00003220
Daniel Dunbar6d8cf082010-07-18 18:47:21 +00003221/// ParseDirectiveMacro
Rafael Espindola65366442011-06-05 02:43:45 +00003222/// ::= .macro name [parameters]
Daniel Dunbar6d8cf082010-07-18 18:47:21 +00003223bool GenericAsmParser::ParseDirectiveMacro(StringRef Directive,
3224 SMLoc DirectiveLoc) {
3225 StringRef Name;
3226 if (getParser().ParseIdentifier(Name))
Rafael Espindolad7ae0f12012-08-21 17:12:05 +00003227 return TokError("expected identifier in '.macro' directive");
Daniel Dunbar6d8cf082010-07-18 18:47:21 +00003228
Rafael Espindola8a403d32012-08-08 14:51:03 +00003229 MacroParameters Parameters;
Preston Gurd7b6f2032012-09-19 20:36:12 +00003230 // Argument delimiter is initially unknown. It will be set by
3231 // ParseMacroArgument()
3232 AsmToken::TokenKind ArgumentDelimiter = AsmToken::Eof;
Rafael Espindola65366442011-06-05 02:43:45 +00003233 if (getLexer().isNot(AsmToken::EndOfStatement)) {
Rafael Espindola7996d042012-08-21 16:06:48 +00003234 for (;;) {
3235 MacroParameter Parameter;
Preston Gurd6c9176a2012-09-19 20:29:04 +00003236 if (getParser().ParseIdentifier(Parameter.first))
Rafael Espindolad7ae0f12012-08-21 17:12:05 +00003237 return TokError("expected identifier in '.macro' directive");
Preston Gurd6c9176a2012-09-19 20:29:04 +00003238
3239 if (getLexer().is(AsmToken::Equal)) {
3240 Lex();
Preston Gurd7b6f2032012-09-19 20:36:12 +00003241 if (getParser().ParseMacroArgument(Parameter.second, ArgumentDelimiter))
Preston Gurd6c9176a2012-09-19 20:29:04 +00003242 return true;
3243 }
3244
Rafael Espindola65366442011-06-05 02:43:45 +00003245 Parameters.push_back(Parameter);
3246
Preston Gurd7b6f2032012-09-19 20:36:12 +00003247 if (getLexer().is(AsmToken::Comma))
3248 Lex();
3249 else if (getLexer().is(AsmToken::EndOfStatement))
Rafael Espindola65366442011-06-05 02:43:45 +00003250 break;
Rafael Espindola65366442011-06-05 02:43:45 +00003251 }
3252 }
3253
Daniel Dunbar6d8cf082010-07-18 18:47:21 +00003254 // Eat the end of statement.
3255 Lex();
3256
3257 AsmToken EndToken, StartToken = getTok();
3258
3259 // Lex the macro definition.
3260 for (;;) {
3261 // Check whether we have reached the end of the file.
3262 if (getLexer().is(AsmToken::Eof))
3263 return Error(DirectiveLoc, "no matching '.endmacro' in definition");
3264
3265 // Otherwise, check whether we have reach the .endmacro.
3266 if (getLexer().is(AsmToken::Identifier) &&
3267 (getTok().getIdentifier() == ".endm" ||
3268 getTok().getIdentifier() == ".endmacro")) {
3269 EndToken = getTok();
3270 Lex();
3271 if (getLexer().isNot(AsmToken::EndOfStatement))
3272 return TokError("unexpected token in '" + EndToken.getIdentifier() +
3273 "' directive");
3274 break;
3275 }
3276
3277 // Otherwise, scan til the end of the statement.
3278 getParser().EatToEndOfStatement();
3279 }
3280
3281 if (getParser().MacroMap.lookup(Name)) {
3282 return Error(DirectiveLoc, "macro '" + Name + "' is already defined");
3283 }
3284
3285 const char *BodyStart = StartToken.getLoc().getPointer();
3286 const char *BodyEnd = EndToken.getLoc().getPointer();
3287 StringRef Body = StringRef(BodyStart, BodyEnd - BodyStart);
Rafael Espindola65366442011-06-05 02:43:45 +00003288 getParser().MacroMap[Name] = new Macro(Name, Body, Parameters);
Daniel Dunbar6d8cf082010-07-18 18:47:21 +00003289 return false;
3290}
3291
3292/// ParseDirectiveEndMacro
3293/// ::= .endm
3294/// ::= .endmacro
3295bool GenericAsmParser::ParseDirectiveEndMacro(StringRef Directive,
Rafael Espindola8a403d32012-08-08 14:51:03 +00003296 SMLoc DirectiveLoc) {
Daniel Dunbar6d8cf082010-07-18 18:47:21 +00003297 if (getLexer().isNot(AsmToken::EndOfStatement))
3298 return TokError("unexpected token in '" + Directive + "' directive");
3299
Daniel Dunbarc64a0d72010-07-18 18:54:11 +00003300 // If we are inside a macro instantiation, terminate the current
3301 // instantiation.
3302 if (!getParser().ActiveMacros.empty()) {
3303 getParser().HandleMacroExit();
3304 return false;
3305 }
3306
3307 // Otherwise, this .endmacro is a stray entry in the file; well formed
3308 // .endmacro directives are handled during the macro definition parsing.
Daniel Dunbar6d8cf082010-07-18 18:47:21 +00003309 return TokError("unexpected '" + Directive + "' in file, "
3310 "no current macro definition");
3311}
3312
Benjamin Kramerbc3b27c2012-05-12 11:21:46 +00003313/// ParseDirectivePurgeMacro
3314/// ::= .purgem
3315bool GenericAsmParser::ParseDirectivePurgeMacro(StringRef Directive,
3316 SMLoc DirectiveLoc) {
3317 StringRef Name;
3318 if (getParser().ParseIdentifier(Name))
3319 return TokError("expected identifier in '.purgem' directive");
3320
3321 if (getLexer().isNot(AsmToken::EndOfStatement))
3322 return TokError("unexpected token in '.purgem' directive");
3323
3324 StringMap<Macro*>::iterator I = getParser().MacroMap.find(Name);
3325 if (I == getParser().MacroMap.end())
3326 return Error(DirectiveLoc, "macro '" + Name + "' is not defined");
3327
3328 // Undefine the macro.
3329 delete I->getValue();
3330 getParser().MacroMap.erase(I);
3331 return false;
3332}
3333
Rafael Espindolab98ac2a2010-09-11 16:45:15 +00003334bool GenericAsmParser::ParseDirectiveLEB128(StringRef DirName, SMLoc) {
Rafael Espindola3ff57092010-11-02 17:22:24 +00003335 getParser().CheckForValidSection();
3336
3337 const MCExpr *Value;
3338
3339 if (getParser().ParseExpression(Value))
Rafael Espindolab98ac2a2010-09-11 16:45:15 +00003340 return true;
3341
3342 if (getLexer().isNot(AsmToken::EndOfStatement))
3343 return TokError("unexpected token in directive");
3344
3345 if (DirName[1] == 's')
Rafael Espindola3ff57092010-11-02 17:22:24 +00003346 getStreamer().EmitSLEB128Value(Value);
Rafael Espindolab98ac2a2010-09-11 16:45:15 +00003347 else
Rafael Espindola3ff57092010-11-02 17:22:24 +00003348 getStreamer().EmitULEB128Value(Value);
3349
Rafael Espindolab98ac2a2010-09-11 16:45:15 +00003350 return false;
3351}
3352
Rafael Espindola761cb062012-06-03 23:57:14 +00003353Macro *AsmParser::ParseMacroLikeBody(SMLoc DirectiveLoc) {
Rafael Espindola2ec304c2012-05-12 16:31:10 +00003354 AsmToken EndToken, StartToken = getTok();
Rafael Espindola2ec304c2012-05-12 16:31:10 +00003355
Rafael Espindola761cb062012-06-03 23:57:14 +00003356 unsigned NestLevel = 0;
Rafael Espindola2ec304c2012-05-12 16:31:10 +00003357 for (;;) {
3358 // Check whether we have reached the end of the file.
Rafael Espindola761cb062012-06-03 23:57:14 +00003359 if (getLexer().is(AsmToken::Eof)) {
3360 Error(DirectiveLoc, "no matching '.endr' in definition");
3361 return 0;
Rafael Espindola2ec304c2012-05-12 16:31:10 +00003362 }
3363
Rafael Espindola761cb062012-06-03 23:57:14 +00003364 if (Lexer.is(AsmToken::Identifier) &&
3365 (getTok().getIdentifier() == ".rept")) {
3366 ++NestLevel;
3367 }
3368
3369 // Otherwise, check whether we have reached the .endr.
3370 if (Lexer.is(AsmToken::Identifier) &&
3371 getTok().getIdentifier() == ".endr") {
3372 if (NestLevel == 0) {
Rafael Espindola2ec304c2012-05-12 16:31:10 +00003373 EndToken = getTok();
3374 Lex();
Rafael Espindola761cb062012-06-03 23:57:14 +00003375 if (Lexer.isNot(AsmToken::EndOfStatement)) {
3376 TokError("unexpected token in '.endr' directive");
3377 return 0;
3378 }
Rafael Espindola2ec304c2012-05-12 16:31:10 +00003379 break;
3380 }
Rafael Espindola761cb062012-06-03 23:57:14 +00003381 --NestLevel;
Rafael Espindola2ec304c2012-05-12 16:31:10 +00003382 }
3383
Rafael Espindola761cb062012-06-03 23:57:14 +00003384 // Otherwise, scan till the end of the statement.
Rafael Espindola2ec304c2012-05-12 16:31:10 +00003385 EatToEndOfStatement();
3386 }
3387
3388 const char *BodyStart = StartToken.getLoc().getPointer();
3389 const char *BodyEnd = EndToken.getLoc().getPointer();
3390 StringRef Body = StringRef(BodyStart, BodyEnd - BodyStart);
3391
Rafael Espindola761cb062012-06-03 23:57:14 +00003392 // We Are Anonymous.
3393 StringRef Name;
Rafael Espindola8a403d32012-08-08 14:51:03 +00003394 MacroParameters Parameters;
Rafael Espindola761cb062012-06-03 23:57:14 +00003395 return new Macro(Name, Body, Parameters);
3396}
3397
3398void AsmParser::InstantiateMacroLikeBody(Macro *M, SMLoc DirectiveLoc,
3399 raw_svector_ostream &OS) {
Rafael Espindola2ec304c2012-05-12 16:31:10 +00003400 OS << ".endr\n";
3401
3402 MemoryBuffer *Instantiation =
3403 MemoryBuffer::getMemBufferCopy(OS.str(), "<instantiation>");
3404
Rafael Espindola761cb062012-06-03 23:57:14 +00003405 // Create the macro instantiation object and add to the current macro
3406 // instantiation stack.
3407 MacroInstantiation *MI = new MacroInstantiation(M, DirectiveLoc,
3408 getTok().getLoc(),
3409 Instantiation);
3410 ActiveMacros.push_back(MI);
Rafael Espindola2ec304c2012-05-12 16:31:10 +00003411
Rafael Espindola761cb062012-06-03 23:57:14 +00003412 // Jump to the macro instantiation and prime the lexer.
3413 CurBuffer = SrcMgr.AddNewSourceBuffer(MI->Instantiation, SMLoc());
3414 Lexer.setBuffer(SrcMgr.getMemoryBuffer(CurBuffer));
3415 Lex();
3416}
3417
3418bool AsmParser::ParseDirectiveRept(SMLoc DirectiveLoc) {
3419 int64_t Count;
3420 if (ParseAbsoluteExpression(Count))
3421 return TokError("unexpected token in '.rept' directive");
3422
3423 if (Count < 0)
3424 return TokError("Count is negative");
3425
3426 if (Lexer.isNot(AsmToken::EndOfStatement))
3427 return TokError("unexpected token in '.rept' directive");
3428
3429 // Eat the end of statement.
3430 Lex();
3431
3432 // Lex the rept definition.
3433 Macro *M = ParseMacroLikeBody(DirectiveLoc);
3434 if (!M)
3435 return true;
3436
3437 // Macro instantiation is lexical, unfortunately. We construct a new buffer
3438 // to hold the macro body with substitutions.
3439 SmallString<256> Buf;
Rafael Espindola8a403d32012-08-08 14:51:03 +00003440 MacroParameters Parameters;
3441 MacroArguments A;
Rafael Espindola761cb062012-06-03 23:57:14 +00003442 raw_svector_ostream OS(Buf);
3443 while (Count--) {
3444 if (expandMacro(OS, M->Body, Parameters, A, getTok().getLoc()))
3445 return true;
3446 }
3447 InstantiateMacroLikeBody(M, DirectiveLoc, OS);
Rafael Espindola2ec304c2012-05-12 16:31:10 +00003448
3449 return false;
3450}
3451
Rafael Espindolaaa7a2f22012-06-15 14:02:34 +00003452/// ParseDirectiveIrp
3453/// ::= .irp symbol,values
3454bool AsmParser::ParseDirectiveIrp(SMLoc DirectiveLoc) {
Rafael Espindola8a403d32012-08-08 14:51:03 +00003455 MacroParameters Parameters;
3456 MacroParameter Parameter;
Rafael Espindolaaa7a2f22012-06-15 14:02:34 +00003457
Preston Gurd6c9176a2012-09-19 20:29:04 +00003458 if (ParseIdentifier(Parameter.first))
Rafael Espindolaaa7a2f22012-06-15 14:02:34 +00003459 return TokError("expected identifier in '.irp' directive");
3460
3461 Parameters.push_back(Parameter);
3462
3463 if (Lexer.isNot(AsmToken::Comma))
3464 return TokError("expected comma in '.irp' directive");
3465
3466 Lex();
3467
Rafael Espindola8a403d32012-08-08 14:51:03 +00003468 MacroArguments A;
Rafael Espindolaaa7a2f22012-06-15 14:02:34 +00003469 if (ParseMacroArguments(0, A))
3470 return true;
3471
3472 // Eat the end of statement.
3473 Lex();
3474
3475 // Lex the irp definition.
3476 Macro *M = ParseMacroLikeBody(DirectiveLoc);
3477 if (!M)
3478 return true;
3479
3480 // Macro instantiation is lexical, unfortunately. We construct a new buffer
3481 // to hold the macro body with substitutions.
3482 SmallString<256> Buf;
3483 raw_svector_ostream OS(Buf);
3484
Rafael Espindola7996d042012-08-21 16:06:48 +00003485 for (MacroArguments::iterator i = A.begin(), e = A.end(); i != e; ++i) {
3486 MacroArguments Args;
Rafael Espindolaaa7a2f22012-06-15 14:02:34 +00003487 Args.push_back(*i);
3488
3489 if (expandMacro(OS, M->Body, Parameters, Args, getTok().getLoc()))
3490 return true;
3491 }
3492
3493 InstantiateMacroLikeBody(M, DirectiveLoc, OS);
3494
3495 return false;
3496}
3497
Rafael Espindolafc9216e2012-06-16 18:03:25 +00003498/// ParseDirectiveIrpc
3499/// ::= .irpc symbol,values
3500bool AsmParser::ParseDirectiveIrpc(SMLoc DirectiveLoc) {
Rafael Espindola8a403d32012-08-08 14:51:03 +00003501 MacroParameters Parameters;
3502 MacroParameter Parameter;
Rafael Espindolafc9216e2012-06-16 18:03:25 +00003503
Preston Gurd6c9176a2012-09-19 20:29:04 +00003504 if (ParseIdentifier(Parameter.first))
Rafael Espindolafc9216e2012-06-16 18:03:25 +00003505 return TokError("expected identifier in '.irpc' directive");
3506
3507 Parameters.push_back(Parameter);
3508
3509 if (Lexer.isNot(AsmToken::Comma))
3510 return TokError("expected comma in '.irpc' directive");
3511
3512 Lex();
3513
Rafael Espindola8a403d32012-08-08 14:51:03 +00003514 MacroArguments A;
Rafael Espindolafc9216e2012-06-16 18:03:25 +00003515 if (ParseMacroArguments(0, A))
3516 return true;
3517
3518 if (A.size() != 1 || A.front().size() != 1)
3519 return TokError("unexpected token in '.irpc' directive");
3520
3521 // Eat the end of statement.
3522 Lex();
3523
3524 // Lex the irpc definition.
3525 Macro *M = ParseMacroLikeBody(DirectiveLoc);
3526 if (!M)
3527 return true;
3528
3529 // Macro instantiation is lexical, unfortunately. We construct a new buffer
3530 // to hold the macro body with substitutions.
3531 SmallString<256> Buf;
3532 raw_svector_ostream OS(Buf);
3533
3534 StringRef Values = A.front().front().getString();
3535 std::size_t I, End = Values.size();
3536 for (I = 0; I < End; ++I) {
3537 MacroArgument Arg;
3538 Arg.push_back(AsmToken(AsmToken::Identifier, Values.slice(I, I+1)));
3539
Rafael Espindola8a403d32012-08-08 14:51:03 +00003540 MacroArguments Args;
Rafael Espindolafc9216e2012-06-16 18:03:25 +00003541 Args.push_back(Arg);
3542
3543 if (expandMacro(OS, M->Body, Parameters, Args, getTok().getLoc()))
3544 return true;
3545 }
3546
3547 InstantiateMacroLikeBody(M, DirectiveLoc, OS);
3548
3549 return false;
3550}
3551
Rafael Espindola761cb062012-06-03 23:57:14 +00003552bool AsmParser::ParseDirectiveEndr(SMLoc DirectiveLoc) {
3553 if (ActiveMacros.empty())
Preston Gurd6579eea2012-09-19 20:23:43 +00003554 return TokError("unmatched '.endr' directive");
Rafael Espindola2ec304c2012-05-12 16:31:10 +00003555
3556 // The only .repl that should get here are the ones created by
Rafael Espindola761cb062012-06-03 23:57:14 +00003557 // InstantiateMacroLikeBody.
Rafael Espindola2ec304c2012-05-12 16:31:10 +00003558 assert(getLexer().is(AsmToken::EndOfStatement));
3559
Rafael Espindola761cb062012-06-03 23:57:14 +00003560 HandleMacroExit();
Rafael Espindola2ec304c2012-05-12 16:31:10 +00003561 return false;
3562}
Rafael Espindolab98ac2a2010-09-11 16:45:15 +00003563
Daniel Dunbard1e3b442010-07-17 02:26:10 +00003564/// \brief Create an MCAsmParser instance.
Jim Grosbach1b84cce2011-08-16 18:33:49 +00003565MCAsmParser *llvm::createMCAsmParser(SourceMgr &SM,
Daniel Dunbard1e3b442010-07-17 02:26:10 +00003566 MCContext &C, MCStreamer &Out,
3567 const MCAsmInfo &MAI) {
Jim Grosbach1b84cce2011-08-16 18:33:49 +00003568 return new AsmParser(SM, C, Out, MAI);
Daniel Dunbard1e3b442010-07-17 02:26:10 +00003569}