1 //===- AsmParser.cpp - Parser for Assembly Files --------------------------===//
3 // The LLVM Compiler Infrastructure
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
8 //===----------------------------------------------------------------------===//
10 // This class implements the parser for assembly files.
12 //===----------------------------------------------------------------------===//
14 #include "llvm/MC/MCParser/AsmParser.h"
15 #include "llvm/ADT/SmallString.h"
16 #include "llvm/ADT/StringSwitch.h"
17 #include "llvm/ADT/Twine.h"
18 #include "llvm/MC/MCContext.h"
19 #include "llvm/MC/MCExpr.h"
20 #include "llvm/MC/MCInst.h"
21 #include "llvm/MC/MCSectionELF.h"
22 #include "llvm/MC/MCStreamer.h"
23 #include "llvm/MC/MCSymbol.h"
24 #include "llvm/MC/MCParser/MCParsedAsmOperand.h"
25 #include "llvm/Support/Compiler.h"
26 #include "llvm/Support/SourceMgr.h"
27 #include "llvm/Support/MemoryBuffer.h"
28 #include "llvm/Support/raw_ostream.h"
29 #include "llvm/Target/TargetAsmParser.h"
34 /// \brief Generic implementations of directive handling, etc. which is shared
35 /// (or the default, at least) for all assembler parser.
36 class GenericAsmParser : public MCAsmParserExtension {
40 virtual void Initialize(MCAsmParser &Parser) {
41 // Call the base implementation.
42 this->MCAsmParserExtension::Initialize(Parser);
44 // Debugging directives.
45 Parser.AddDirectiveHandler(this, ".file", MCAsmParser::DirectiveHandler(
46 &GenericAsmParser::ParseDirectiveFile));
47 Parser.AddDirectiveHandler(this, ".line", MCAsmParser::DirectiveHandler(
48 &GenericAsmParser::ParseDirectiveLine));
49 Parser.AddDirectiveHandler(this, ".loc", MCAsmParser::DirectiveHandler(
50 &GenericAsmParser::ParseDirectiveLoc));
53 bool ParseDirectiveFile(StringRef, SMLoc DirectiveLoc); // ".file"
54 bool ParseDirectiveLine(StringRef, SMLoc DirectiveLoc); // ".line"
55 bool ParseDirectiveLoc(StringRef, SMLoc DirectiveLoc); // ".loc"
58 class ELFAsmParser : public MCAsmParserExtension {
59 bool ParseSectionSwitch(StringRef Section, unsigned Type,
60 unsigned Flags, SectionKind Kind);
65 virtual void Initialize(MCAsmParser &Parser) {
66 // Call the base implementation.
67 this->MCAsmParserExtension::Initialize(Parser);
69 Parser.AddDirectiveHandler(this, ".data", MCAsmParser::DirectiveHandler(
70 &ELFAsmParser::ParseSectionDirectiveData));
71 Parser.AddDirectiveHandler(this, ".text", MCAsmParser::DirectiveHandler(
72 &ELFAsmParser::ParseSectionDirectiveText));
75 bool ParseSectionDirectiveData(StringRef, SMLoc) {
76 return ParseSectionSwitch(".data", MCSectionELF::SHT_PROGBITS,
77 MCSectionELF::SHF_WRITE |MCSectionELF::SHF_ALLOC,
78 SectionKind::getDataRel());
80 bool ParseSectionDirectiveText(StringRef, SMLoc) {
81 return ParseSectionSwitch(".text", MCSectionELF::SHT_PROGBITS,
82 MCSectionELF::SHF_EXECINSTR |
83 MCSectionELF::SHF_ALLOC, SectionKind::getText());
91 extern MCAsmParserExtension *createDarwinAsmParser();
95 enum { DEFAULT_ADDRSPACE = 0 };
97 AsmParser::AsmParser(const Target &T, SourceMgr &_SM, MCContext &_Ctx,
98 MCStreamer &_Out, const MCAsmInfo &_MAI)
99 : Lexer(_MAI), Ctx(_Ctx), Out(_Out), SrcMgr(_SM),
100 GenericParser(new GenericAsmParser), PlatformParser(0),
101 TargetParser(0), CurBuffer(0) {
102 Lexer.setBuffer(SrcMgr.getMemoryBuffer(CurBuffer));
104 // Initialize the generic parser.
105 GenericParser->Initialize(*this);
107 // Initialize the platform / file format parser.
109 // FIXME: This is a hack, we need to (majorly) cleanup how these objects are
111 if (_MAI.hasSubsectionsViaSymbols()) {
112 PlatformParser = createDarwinAsmParser();
113 PlatformParser->Initialize(*this);
115 PlatformParser = new ELFAsmParser;
116 PlatformParser->Initialize(*this);
120 AsmParser::~AsmParser() {
121 delete PlatformParser;
122 delete GenericParser;
125 void AsmParser::setTargetParser(TargetAsmParser &P) {
126 assert(!TargetParser && "Target parser is already initialized!");
128 TargetParser->Initialize(*this);
131 void AsmParser::Warning(SMLoc L, const Twine &Msg) {
132 PrintMessage(L, Msg.str(), "warning");
135 bool AsmParser::Error(SMLoc L, const Twine &Msg) {
136 PrintMessage(L, Msg.str(), "error");
140 void AsmParser::PrintMessage(SMLoc Loc, const std::string &Msg,
141 const char *Type) const {
142 SrcMgr.PrintMessage(Loc, Msg, Type);
145 bool AsmParser::EnterIncludeFile(const std::string &Filename) {
146 int NewBuf = SrcMgr.AddIncludeFile(Filename, Lexer.getLoc());
152 Lexer.setBuffer(SrcMgr.getMemoryBuffer(CurBuffer));
157 const AsmToken &AsmParser::Lex() {
158 const AsmToken *tok = &Lexer.Lex();
160 if (tok->is(AsmToken::Eof)) {
161 // If this is the end of an included file, pop the parent file off the
163 SMLoc ParentIncludeLoc = SrcMgr.getParentIncludeLoc(CurBuffer);
164 if (ParentIncludeLoc != SMLoc()) {
165 CurBuffer = SrcMgr.FindBufferContainingLoc(ParentIncludeLoc);
166 Lexer.setBuffer(SrcMgr.getMemoryBuffer(CurBuffer),
167 ParentIncludeLoc.getPointer());
172 if (tok->is(AsmToken::Error))
173 PrintMessage(Lexer.getErrLoc(), Lexer.getErr(), "error");
178 bool AsmParser::Run(bool NoInitialTextSection, bool NoFinalize) {
179 // Create the initial section, if requested.
181 // FIXME: Target hook & command line option for initial section.
182 if (!NoInitialTextSection)
183 Out.SwitchSection(Ctx.getMachOSection("__TEXT", "__text",
184 MCSectionMachO::S_ATTR_PURE_INSTRUCTIONS,
185 0, SectionKind::getText()));
190 bool HadError = false;
192 AsmCond StartingCondState = TheCondState;
194 // While we have input, parse each statement.
195 while (Lexer.isNot(AsmToken::Eof)) {
196 if (!ParseStatement()) continue;
198 // We had an error, remember it and recover by skipping to the next line.
200 EatToEndOfStatement();
203 if (TheCondState.TheCond != StartingCondState.TheCond ||
204 TheCondState.Ignore != StartingCondState.Ignore)
205 return TokError("unmatched .ifs or .elses");
207 // Finalize the output stream if there are no errors and if the client wants
209 if (!HadError && !NoFinalize)
215 /// EatToEndOfStatement - Throw away the rest of the line for testing purposes.
216 void AsmParser::EatToEndOfStatement() {
217 while (Lexer.isNot(AsmToken::EndOfStatement) &&
218 Lexer.isNot(AsmToken::Eof))
222 if (Lexer.is(AsmToken::EndOfStatement))
227 /// ParseParenExpr - Parse a paren expression and return it.
228 /// NOTE: This assumes the leading '(' has already been consumed.
230 /// parenexpr ::= expr)
232 bool AsmParser::ParseParenExpr(const MCExpr *&Res, SMLoc &EndLoc) {
233 if (ParseExpression(Res)) return true;
234 if (Lexer.isNot(AsmToken::RParen))
235 return TokError("expected ')' in parentheses expression");
236 EndLoc = Lexer.getLoc();
241 /// ParsePrimaryExpr - Parse a primary expression and return it.
242 /// primaryexpr ::= (parenexpr
243 /// primaryexpr ::= symbol
244 /// primaryexpr ::= number
245 /// primaryexpr ::= '.'
246 /// primaryexpr ::= ~,+,- primaryexpr
247 bool AsmParser::ParsePrimaryExpr(const MCExpr *&Res, SMLoc &EndLoc) {
248 switch (Lexer.getKind()) {
250 return TokError("unknown token in expression");
251 case AsmToken::Exclaim:
252 Lex(); // Eat the operator.
253 if (ParsePrimaryExpr(Res, EndLoc))
255 Res = MCUnaryExpr::CreateLNot(Res, getContext());
257 case AsmToken::String:
258 case AsmToken::Identifier: {
259 // This is a symbol reference.
260 std::pair<StringRef, StringRef> Split = getTok().getIdentifier().split('@');
261 MCSymbol *Sym = getContext().GetOrCreateSymbol(Split.first);
263 // Mark the symbol as used in an expression.
264 Sym->setUsedInExpr(true);
266 // Lookup the symbol variant if used.
267 MCSymbolRefExpr::VariantKind Variant = MCSymbolRefExpr::VK_None;
268 if (Split.first.size() != getTok().getIdentifier().size())
269 Variant = MCSymbolRefExpr::getVariantKindForName(Split.second);
271 EndLoc = Lexer.getLoc();
272 Lex(); // Eat identifier.
274 // If this is an absolute variable reference, substitute it now to preserve
275 // semantics in the face of reassignment.
276 if (Sym->isVariable() && isa<MCConstantExpr>(Sym->getVariableValue())) {
278 return Error(EndLoc, "unexpected modified on variable reference");
280 Res = Sym->getVariableValue();
284 // Otherwise create a symbol ref.
285 Res = MCSymbolRefExpr::Create(Sym, Variant, getContext());
288 case AsmToken::Integer: {
289 SMLoc Loc = getTok().getLoc();
290 int64_t IntVal = getTok().getIntVal();
291 Res = MCConstantExpr::Create(IntVal, getContext());
292 EndLoc = Lexer.getLoc();
294 // Look for 'b' or 'f' following an Integer as a directional label
295 if (Lexer.getKind() == AsmToken::Identifier) {
296 StringRef IDVal = getTok().getString();
297 if (IDVal == "f" || IDVal == "b"){
298 MCSymbol *Sym = Ctx.GetDirectionalLocalSymbol(IntVal,
299 IDVal == "f" ? 1 : 0);
300 Res = MCSymbolRefExpr::Create(Sym, MCSymbolRefExpr::VK_None,
302 if(IDVal == "b" && Sym->isUndefined())
303 return Error(Loc, "invalid reference to undefined symbol");
304 EndLoc = Lexer.getLoc();
305 Lex(); // Eat identifier.
310 case AsmToken::Dot: {
311 // This is a '.' reference, which references the current PC. Emit a
312 // temporary label to the streamer and refer to it.
313 MCSymbol *Sym = Ctx.CreateTempSymbol();
315 Res = MCSymbolRefExpr::Create(Sym, MCSymbolRefExpr::VK_None, getContext());
316 EndLoc = Lexer.getLoc();
317 Lex(); // Eat identifier.
321 case AsmToken::LParen:
322 Lex(); // Eat the '('.
323 return ParseParenExpr(Res, EndLoc);
324 case AsmToken::Minus:
325 Lex(); // Eat the operator.
326 if (ParsePrimaryExpr(Res, EndLoc))
328 Res = MCUnaryExpr::CreateMinus(Res, getContext());
331 Lex(); // Eat the operator.
332 if (ParsePrimaryExpr(Res, EndLoc))
334 Res = MCUnaryExpr::CreatePlus(Res, getContext());
336 case AsmToken::Tilde:
337 Lex(); // Eat the operator.
338 if (ParsePrimaryExpr(Res, EndLoc))
340 Res = MCUnaryExpr::CreateNot(Res, getContext());
345 bool AsmParser::ParseExpression(const MCExpr *&Res) {
347 return ParseExpression(Res, EndLoc);
350 /// ParseExpression - Parse an expression and return it.
352 /// expr ::= expr +,- expr -> lowest.
353 /// expr ::= expr |,^,&,! expr -> middle.
354 /// expr ::= expr *,/,%,<<,>> expr -> highest.
355 /// expr ::= primaryexpr
357 bool AsmParser::ParseExpression(const MCExpr *&Res, SMLoc &EndLoc) {
358 // Parse the expression.
360 if (ParsePrimaryExpr(Res, EndLoc) || ParseBinOpRHS(1, Res, EndLoc))
363 // Try to constant fold it up front, if possible.
365 if (Res->EvaluateAsAbsolute(Value))
366 Res = MCConstantExpr::Create(Value, getContext());
371 bool AsmParser::ParseParenExpression(const MCExpr *&Res, SMLoc &EndLoc) {
373 return ParseParenExpr(Res, EndLoc) ||
374 ParseBinOpRHS(1, Res, EndLoc);
377 bool AsmParser::ParseAbsoluteExpression(int64_t &Res) {
380 SMLoc StartLoc = Lexer.getLoc();
381 if (ParseExpression(Expr))
384 if (!Expr->EvaluateAsAbsolute(Res))
385 return Error(StartLoc, "expected absolute expression");
390 static unsigned getBinOpPrecedence(AsmToken::TokenKind K,
391 MCBinaryExpr::Opcode &Kind) {
394 return 0; // not a binop.
396 // Lowest Precedence: &&, ||
397 case AsmToken::AmpAmp:
398 Kind = MCBinaryExpr::LAnd;
400 case AsmToken::PipePipe:
401 Kind = MCBinaryExpr::LOr;
404 // Low Precedence: +, -, ==, !=, <>, <, <=, >, >=
406 Kind = MCBinaryExpr::Add;
408 case AsmToken::Minus:
409 Kind = MCBinaryExpr::Sub;
411 case AsmToken::EqualEqual:
412 Kind = MCBinaryExpr::EQ;
414 case AsmToken::ExclaimEqual:
415 case AsmToken::LessGreater:
416 Kind = MCBinaryExpr::NE;
419 Kind = MCBinaryExpr::LT;
421 case AsmToken::LessEqual:
422 Kind = MCBinaryExpr::LTE;
424 case AsmToken::Greater:
425 Kind = MCBinaryExpr::GT;
427 case AsmToken::GreaterEqual:
428 Kind = MCBinaryExpr::GTE;
431 // Intermediate Precedence: |, &, ^
433 // FIXME: gas seems to support '!' as an infix operator?
435 Kind = MCBinaryExpr::Or;
437 case AsmToken::Caret:
438 Kind = MCBinaryExpr::Xor;
441 Kind = MCBinaryExpr::And;
444 // Highest Precedence: *, /, %, <<, >>
446 Kind = MCBinaryExpr::Mul;
448 case AsmToken::Slash:
449 Kind = MCBinaryExpr::Div;
451 case AsmToken::Percent:
452 Kind = MCBinaryExpr::Mod;
454 case AsmToken::LessLess:
455 Kind = MCBinaryExpr::Shl;
457 case AsmToken::GreaterGreater:
458 Kind = MCBinaryExpr::Shr;
464 /// ParseBinOpRHS - Parse all binary operators with precedence >= 'Precedence'.
465 /// Res contains the LHS of the expression on input.
466 bool AsmParser::ParseBinOpRHS(unsigned Precedence, const MCExpr *&Res,
469 MCBinaryExpr::Opcode Kind = MCBinaryExpr::Add;
470 unsigned TokPrec = getBinOpPrecedence(Lexer.getKind(), Kind);
472 // If the next token is lower precedence than we are allowed to eat, return
473 // successfully with what we ate already.
474 if (TokPrec < Precedence)
479 // Eat the next primary expression.
481 if (ParsePrimaryExpr(RHS, EndLoc)) return true;
483 // If BinOp binds less tightly with RHS than the operator after RHS, let
484 // the pending operator take RHS as its LHS.
485 MCBinaryExpr::Opcode Dummy;
486 unsigned NextTokPrec = getBinOpPrecedence(Lexer.getKind(), Dummy);
487 if (TokPrec < NextTokPrec) {
488 if (ParseBinOpRHS(Precedence+1, RHS, EndLoc)) return true;
491 // Merge LHS and RHS according to operator.
492 Res = MCBinaryExpr::Create(Kind, Res, RHS, getContext());
500 /// ::= EndOfStatement
501 /// ::= Label* Directive ...Operands... EndOfStatement
502 /// ::= Label* Identifier OperandList* EndOfStatement
503 bool AsmParser::ParseStatement() {
504 if (Lexer.is(AsmToken::EndOfStatement)) {
510 // Statements always start with an identifier.
511 AsmToken ID = getTok();
512 SMLoc IDLoc = ID.getLoc();
514 int64_t LocalLabelVal = -1;
515 // GUESS allow an integer followed by a ':' as a directional local label
516 if (Lexer.is(AsmToken::Integer)) {
517 LocalLabelVal = getTok().getIntVal();
518 if (LocalLabelVal < 0) {
519 if (!TheCondState.Ignore)
520 return TokError("unexpected token at start of statement");
524 IDVal = getTok().getString();
525 Lex(); // Consume the integer token to be used as an identifier token.
526 if (Lexer.getKind() != AsmToken::Colon) {
527 if (!TheCondState.Ignore)
528 return TokError("unexpected token at start of statement");
532 else if (ParseIdentifier(IDVal)) {
533 if (!TheCondState.Ignore)
534 return TokError("unexpected token at start of statement");
538 // Handle conditional assembly here before checking for skipping. We
539 // have to do this so that .endif isn't skipped in a ".if 0" block for
542 return ParseDirectiveIf(IDLoc);
543 if (IDVal == ".elseif")
544 return ParseDirectiveElseIf(IDLoc);
545 if (IDVal == ".else")
546 return ParseDirectiveElse(IDLoc);
547 if (IDVal == ".endif")
548 return ParseDirectiveEndIf(IDLoc);
550 // If we are in a ".if 0" block, ignore this statement.
551 if (TheCondState.Ignore) {
552 EatToEndOfStatement();
556 // FIXME: Recurse on local labels?
558 // See what kind of statement we have.
559 switch (Lexer.getKind()) {
560 case AsmToken::Colon: {
561 // identifier ':' -> Label.
564 // Diagnose attempt to use a variable as a label.
566 // FIXME: Diagnostics. Note the location of the definition as a label.
567 // FIXME: This doesn't diagnose assignment to a symbol which has been
568 // implicitly marked as external.
570 if (LocalLabelVal == -1)
571 Sym = getContext().GetOrCreateSymbol(IDVal);
573 Sym = Ctx.CreateDirectionalLocalSymbol(LocalLabelVal);
574 if (!Sym->isUndefined() || Sym->isVariable())
575 return Error(IDLoc, "invalid symbol redefinition");
580 // Consume any end of statement token, if present, to avoid spurious
581 // AddBlankLine calls().
582 if (Lexer.is(AsmToken::EndOfStatement)) {
584 if (Lexer.is(AsmToken::Eof))
588 return ParseStatement();
591 case AsmToken::Equal:
592 // identifier '=' ... -> assignment statement
595 return ParseAssignment(IDVal);
597 default: // Normal instruction or directive.
601 // Otherwise, we have a normal instruction or directive.
602 if (IDVal[0] == '.') {
603 // Assembler features
605 return ParseDirectiveSet();
609 if (IDVal == ".ascii")
610 return ParseDirectiveAscii(false);
611 if (IDVal == ".asciz")
612 return ParseDirectiveAscii(true);
614 if (IDVal == ".byte")
615 return ParseDirectiveValue(1);
616 if (IDVal == ".short")
617 return ParseDirectiveValue(2);
618 if (IDVal == ".long")
619 return ParseDirectiveValue(4);
620 if (IDVal == ".quad")
621 return ParseDirectiveValue(8);
623 // FIXME: Target hooks for IsPow2.
624 if (IDVal == ".align")
625 return ParseDirectiveAlign(/*IsPow2=*/true, /*ExprSize=*/1);
626 if (IDVal == ".align32")
627 return ParseDirectiveAlign(/*IsPow2=*/true, /*ExprSize=*/4);
628 if (IDVal == ".balign")
629 return ParseDirectiveAlign(/*IsPow2=*/false, /*ExprSize=*/1);
630 if (IDVal == ".balignw")
631 return ParseDirectiveAlign(/*IsPow2=*/false, /*ExprSize=*/2);
632 if (IDVal == ".balignl")
633 return ParseDirectiveAlign(/*IsPow2=*/false, /*ExprSize=*/4);
634 if (IDVal == ".p2align")
635 return ParseDirectiveAlign(/*IsPow2=*/true, /*ExprSize=*/1);
636 if (IDVal == ".p2alignw")
637 return ParseDirectiveAlign(/*IsPow2=*/true, /*ExprSize=*/2);
638 if (IDVal == ".p2alignl")
639 return ParseDirectiveAlign(/*IsPow2=*/true, /*ExprSize=*/4);
642 return ParseDirectiveOrg();
644 if (IDVal == ".fill")
645 return ParseDirectiveFill();
646 if (IDVal == ".space")
647 return ParseDirectiveSpace();
649 // Symbol attribute directives
651 if (IDVal == ".globl" || IDVal == ".global")
652 return ParseDirectiveSymbolAttribute(MCSA_Global);
653 if (IDVal == ".hidden")
654 return ParseDirectiveSymbolAttribute(MCSA_Hidden);
655 if (IDVal == ".indirect_symbol")
656 return ParseDirectiveSymbolAttribute(MCSA_IndirectSymbol);
657 if (IDVal == ".internal")
658 return ParseDirectiveSymbolAttribute(MCSA_Internal);
659 if (IDVal == ".lazy_reference")
660 return ParseDirectiveSymbolAttribute(MCSA_LazyReference);
661 if (IDVal == ".no_dead_strip")
662 return ParseDirectiveSymbolAttribute(MCSA_NoDeadStrip);
663 if (IDVal == ".private_extern")
664 return ParseDirectiveSymbolAttribute(MCSA_PrivateExtern);
665 if (IDVal == ".protected")
666 return ParseDirectiveSymbolAttribute(MCSA_Protected);
667 if (IDVal == ".reference")
668 return ParseDirectiveSymbolAttribute(MCSA_Reference);
669 if (IDVal == ".type")
670 return ParseDirectiveELFType();
671 if (IDVal == ".weak")
672 return ParseDirectiveSymbolAttribute(MCSA_Weak);
673 if (IDVal == ".weak_definition")
674 return ParseDirectiveSymbolAttribute(MCSA_WeakDefinition);
675 if (IDVal == ".weak_reference")
676 return ParseDirectiveSymbolAttribute(MCSA_WeakReference);
677 if (IDVal == ".weak_def_can_be_hidden")
678 return ParseDirectiveSymbolAttribute(MCSA_WeakDefAutoPrivate);
680 if (IDVal == ".comm")
681 return ParseDirectiveComm(/*IsLocal=*/false);
682 if (IDVal == ".lcomm")
683 return ParseDirectiveComm(/*IsLocal=*/true);
685 if (IDVal == ".abort")
686 return ParseDirectiveAbort();
687 if (IDVal == ".include")
688 return ParseDirectiveInclude();
690 // Look up the handler in the handler table.
691 std::pair<MCAsmParserExtension*, DirectiveHandler> Handler =
692 DirectiveMap.lookup(IDVal);
694 return (Handler.first->*Handler.second)(IDVal, IDLoc);
696 // Target hook for parsing target specific directives.
697 if (!getTargetParser().ParseDirective(ID))
700 Warning(IDLoc, "ignoring directive for now");
701 EatToEndOfStatement();
705 // Canonicalize the opcode to lower case.
706 SmallString<128> Opcode;
707 for (unsigned i = 0, e = IDVal.size(); i != e; ++i)
708 Opcode.push_back(tolower(IDVal[i]));
710 SmallVector<MCParsedAsmOperand*, 8> ParsedOperands;
711 bool HadError = getTargetParser().ParseInstruction(Opcode.str(), IDLoc,
713 if (!HadError && Lexer.isNot(AsmToken::EndOfStatement))
714 HadError = TokError("unexpected token in argument list");
716 // If parsing succeeded, match the instruction.
719 if (!getTargetParser().MatchInstruction(ParsedOperands, Inst)) {
720 // Emit the instruction on success.
721 Out.EmitInstruction(Inst);
723 // Otherwise emit a diagnostic about the match failure and set the error
726 // FIXME: We should give nicer diagnostics about the exact failure.
727 Error(IDLoc, "unrecognized instruction");
732 // If there was no error, consume the end-of-statement token. Otherwise this
733 // will be done by our caller.
737 // Free any parsed operands.
738 for (unsigned i = 0, e = ParsedOperands.size(); i != e; ++i)
739 delete ParsedOperands[i];
744 bool AsmParser::ParseAssignment(const StringRef &Name) {
745 // FIXME: Use better location, we should use proper tokens.
746 SMLoc EqualLoc = Lexer.getLoc();
749 if (ParseExpression(Value))
752 if (Lexer.isNot(AsmToken::EndOfStatement))
753 return TokError("unexpected token in assignment");
755 // Eat the end of statement marker.
758 // Validate that the LHS is allowed to be a variable (either it has not been
759 // used as a symbol, or it is an absolute symbol).
760 MCSymbol *Sym = getContext().LookupSymbol(Name);
762 // Diagnose assignment to a label.
764 // FIXME: Diagnostics. Note the location of the definition as a label.
765 // FIXME: Diagnose assignment to protected identifier (e.g., register name).
766 if (Sym->isUndefined() && !Sym->isUsedInExpr())
767 ; // Allow redefinitions of undefined symbols only used in directives.
768 else if (!Sym->isUndefined() && !Sym->isAbsolute())
769 return Error(EqualLoc, "redefinition of '" + Name + "'");
770 else if (!Sym->isVariable())
771 return Error(EqualLoc, "invalid assignment to '" + Name + "'");
772 else if (!isa<MCConstantExpr>(Sym->getVariableValue()))
773 return Error(EqualLoc, "invalid reassignment of non-absolute variable '" +
776 Sym = getContext().GetOrCreateSymbol(Name);
778 // FIXME: Handle '.'.
780 Sym->setUsedInExpr(true);
782 // Do the assignment.
783 Out.EmitAssignment(Sym, Value);
791 bool AsmParser::ParseIdentifier(StringRef &Res) {
792 if (Lexer.isNot(AsmToken::Identifier) &&
793 Lexer.isNot(AsmToken::String))
796 Res = getTok().getIdentifier();
798 Lex(); // Consume the identifier token.
803 /// ParseDirectiveSet:
804 /// ::= .set identifier ',' expression
805 bool AsmParser::ParseDirectiveSet() {
808 if (ParseIdentifier(Name))
809 return TokError("expected identifier after '.set' directive");
811 if (getLexer().isNot(AsmToken::Comma))
812 return TokError("unexpected token in '.set'");
815 return ParseAssignment(Name);
818 bool ELFAsmParser::ParseSectionSwitch(StringRef Section, unsigned Type,
819 unsigned Flags, SectionKind Kind) {
820 if (getLexer().isNot(AsmToken::EndOfStatement))
821 return TokError("unexpected token in section switching directive");
824 getStreamer().SwitchSection(getContext().getELFSection(
825 Section, Type, Flags, Kind));
830 bool AsmParser::ParseEscapedString(std::string &Data) {
831 assert(getLexer().is(AsmToken::String) && "Unexpected current token!");
834 StringRef Str = getTok().getStringContents();
835 for (unsigned i = 0, e = Str.size(); i != e; ++i) {
836 if (Str[i] != '\\') {
841 // Recognize escaped characters. Note that this escape semantics currently
842 // loosely follows Darwin 'as'. Notably, it doesn't support hex escapes.
845 return TokError("unexpected backslash at end of string");
847 // Recognize octal sequences.
848 if ((unsigned) (Str[i] - '0') <= 7) {
849 // Consume up to three octal characters.
850 unsigned Value = Str[i] - '0';
852 if (i + 1 != e && ((unsigned) (Str[i + 1] - '0')) <= 7) {
854 Value = Value * 8 + (Str[i] - '0');
856 if (i + 1 != e && ((unsigned) (Str[i + 1] - '0')) <= 7) {
858 Value = Value * 8 + (Str[i] - '0');
863 return TokError("invalid octal escape sequence (out of range)");
865 Data += (unsigned char) Value;
869 // Otherwise recognize individual escapes.
872 // Just reject invalid escape sequences for now.
873 return TokError("invalid escape sequence (unrecognized character)");
875 case 'b': Data += '\b'; break;
876 case 'f': Data += '\f'; break;
877 case 'n': Data += '\n'; break;
878 case 'r': Data += '\r'; break;
879 case 't': Data += '\t'; break;
880 case '"': Data += '"'; break;
881 case '\\': Data += '\\'; break;
888 /// ParseDirectiveAscii:
889 /// ::= ( .ascii | .asciz ) [ "string" ( , "string" )* ]
890 bool AsmParser::ParseDirectiveAscii(bool ZeroTerminated) {
891 if (getLexer().isNot(AsmToken::EndOfStatement)) {
893 if (getLexer().isNot(AsmToken::String))
894 return TokError("expected string in '.ascii' or '.asciz' directive");
897 if (ParseEscapedString(Data))
900 getStreamer().EmitBytes(Data, DEFAULT_ADDRSPACE);
902 getStreamer().EmitBytes(StringRef("\0", 1), DEFAULT_ADDRSPACE);
906 if (getLexer().is(AsmToken::EndOfStatement))
909 if (getLexer().isNot(AsmToken::Comma))
910 return TokError("unexpected token in '.ascii' or '.asciz' directive");
919 /// ParseDirectiveValue
920 /// ::= (.byte | .short | ... ) [ expression (, expression)* ]
921 bool AsmParser::ParseDirectiveValue(unsigned Size) {
922 if (getLexer().isNot(AsmToken::EndOfStatement)) {
925 SMLoc ATTRIBUTE_UNUSED StartLoc = getLexer().getLoc();
926 if (ParseExpression(Value))
929 // Special case constant expressions to match code generator.
930 if (const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(Value))
931 getStreamer().EmitIntValue(MCE->getValue(), Size, DEFAULT_ADDRSPACE);
933 getStreamer().EmitValue(Value, Size, DEFAULT_ADDRSPACE);
935 if (getLexer().is(AsmToken::EndOfStatement))
938 // FIXME: Improve diagnostic.
939 if (getLexer().isNot(AsmToken::Comma))
940 return TokError("unexpected token in directive");
949 /// ParseDirectiveSpace
950 /// ::= .space expression [ , expression ]
951 bool AsmParser::ParseDirectiveSpace() {
953 if (ParseAbsoluteExpression(NumBytes))
956 int64_t FillExpr = 0;
957 if (getLexer().isNot(AsmToken::EndOfStatement)) {
958 if (getLexer().isNot(AsmToken::Comma))
959 return TokError("unexpected token in '.space' directive");
962 if (ParseAbsoluteExpression(FillExpr))
965 if (getLexer().isNot(AsmToken::EndOfStatement))
966 return TokError("unexpected token in '.space' directive");
972 return TokError("invalid number of bytes in '.space' directive");
974 // FIXME: Sometimes the fill expr is 'nop' if it isn't supplied, instead of 0.
975 getStreamer().EmitFill(NumBytes, FillExpr, DEFAULT_ADDRSPACE);
980 /// ParseDirectiveFill
981 /// ::= .fill expression , expression , expression
982 bool AsmParser::ParseDirectiveFill() {
984 if (ParseAbsoluteExpression(NumValues))
987 if (getLexer().isNot(AsmToken::Comma))
988 return TokError("unexpected token in '.fill' directive");
992 if (ParseAbsoluteExpression(FillSize))
995 if (getLexer().isNot(AsmToken::Comma))
996 return TokError("unexpected token in '.fill' directive");
1000 if (ParseAbsoluteExpression(FillExpr))
1003 if (getLexer().isNot(AsmToken::EndOfStatement))
1004 return TokError("unexpected token in '.fill' directive");
1008 if (FillSize != 1 && FillSize != 2 && FillSize != 4 && FillSize != 8)
1009 return TokError("invalid '.fill' size, expected 1, 2, 4, or 8");
1011 for (uint64_t i = 0, e = NumValues; i != e; ++i)
1012 getStreamer().EmitIntValue(FillExpr, FillSize, DEFAULT_ADDRSPACE);
1017 /// ParseDirectiveOrg
1018 /// ::= .org expression [ , expression ]
1019 bool AsmParser::ParseDirectiveOrg() {
1020 const MCExpr *Offset;
1021 if (ParseExpression(Offset))
1024 // Parse optional fill expression.
1025 int64_t FillExpr = 0;
1026 if (getLexer().isNot(AsmToken::EndOfStatement)) {
1027 if (getLexer().isNot(AsmToken::Comma))
1028 return TokError("unexpected token in '.org' directive");
1031 if (ParseAbsoluteExpression(FillExpr))
1034 if (getLexer().isNot(AsmToken::EndOfStatement))
1035 return TokError("unexpected token in '.org' directive");
1040 // FIXME: Only limited forms of relocatable expressions are accepted here, it
1041 // has to be relative to the current section.
1042 getStreamer().EmitValueToOffset(Offset, FillExpr);
1047 /// ParseDirectiveAlign
1048 /// ::= {.align, ...} expression [ , expression [ , expression ]]
1049 bool AsmParser::ParseDirectiveAlign(bool IsPow2, unsigned ValueSize) {
1050 SMLoc AlignmentLoc = getLexer().getLoc();
1052 if (ParseAbsoluteExpression(Alignment))
1056 bool HasFillExpr = false;
1057 int64_t FillExpr = 0;
1058 int64_t MaxBytesToFill = 0;
1059 if (getLexer().isNot(AsmToken::EndOfStatement)) {
1060 if (getLexer().isNot(AsmToken::Comma))
1061 return TokError("unexpected token in directive");
1064 // The fill expression can be omitted while specifying a maximum number of
1065 // alignment bytes, e.g:
1067 if (getLexer().isNot(AsmToken::Comma)) {
1069 if (ParseAbsoluteExpression(FillExpr))
1073 if (getLexer().isNot(AsmToken::EndOfStatement)) {
1074 if (getLexer().isNot(AsmToken::Comma))
1075 return TokError("unexpected token in directive");
1078 MaxBytesLoc = getLexer().getLoc();
1079 if (ParseAbsoluteExpression(MaxBytesToFill))
1082 if (getLexer().isNot(AsmToken::EndOfStatement))
1083 return TokError("unexpected token in directive");
1092 // Compute alignment in bytes.
1094 // FIXME: Diagnose overflow.
1095 if (Alignment >= 32) {
1096 Error(AlignmentLoc, "invalid alignment value");
1100 Alignment = 1ULL << Alignment;
1103 // Diagnose non-sensical max bytes to align.
1104 if (MaxBytesLoc.isValid()) {
1105 if (MaxBytesToFill < 1) {
1106 Error(MaxBytesLoc, "alignment directive can never be satisfied in this "
1107 "many bytes, ignoring maximum bytes expression");
1111 if (MaxBytesToFill >= Alignment) {
1112 Warning(MaxBytesLoc, "maximum bytes expression exceeds alignment and "
1118 // Check whether we should use optimal code alignment for this .align
1121 // FIXME: This should be using a target hook.
1122 bool UseCodeAlign = false;
1123 if (const MCSectionMachO *S = dyn_cast<MCSectionMachO>(
1124 getStreamer().getCurrentSection()))
1125 UseCodeAlign = S->hasAttribute(MCSectionMachO::S_ATTR_PURE_INSTRUCTIONS);
1126 if ((!HasFillExpr || Lexer.getMAI().getTextAlignFillValue() == FillExpr) &&
1127 ValueSize == 1 && UseCodeAlign) {
1128 getStreamer().EmitCodeAlignment(Alignment, MaxBytesToFill);
1130 // FIXME: Target specific behavior about how the "extra" bytes are filled.
1131 getStreamer().EmitValueToAlignment(Alignment, FillExpr, ValueSize, MaxBytesToFill);
1137 /// ParseDirectiveSymbolAttribute
1138 /// ::= { ".globl", ".weak", ... } [ identifier ( , identifier )* ]
1139 bool AsmParser::ParseDirectiveSymbolAttribute(MCSymbolAttr Attr) {
1140 if (getLexer().isNot(AsmToken::EndOfStatement)) {
1144 if (ParseIdentifier(Name))
1145 return TokError("expected identifier in directive");
1147 MCSymbol *Sym = getContext().GetOrCreateSymbol(Name);
1149 getStreamer().EmitSymbolAttribute(Sym, Attr);
1151 if (getLexer().is(AsmToken::EndOfStatement))
1154 if (getLexer().isNot(AsmToken::Comma))
1155 return TokError("unexpected token in directive");
1164 /// ParseDirectiveELFType
1165 /// ::= .type identifier , @attribute
1166 bool AsmParser::ParseDirectiveELFType() {
1168 if (ParseIdentifier(Name))
1169 return TokError("expected identifier in directive");
1171 // Handle the identifier as the key symbol.
1172 MCSymbol *Sym = getContext().GetOrCreateSymbol(Name);
1174 if (getLexer().isNot(AsmToken::Comma))
1175 return TokError("unexpected token in '.type' directive");
1178 if (getLexer().isNot(AsmToken::At))
1179 return TokError("expected '@' before type");
1185 TypeLoc = getLexer().getLoc();
1186 if (ParseIdentifier(Type))
1187 return TokError("expected symbol type in directive");
1189 MCSymbolAttr Attr = StringSwitch<MCSymbolAttr>(Type)
1190 .Case("function", MCSA_ELF_TypeFunction)
1191 .Case("object", MCSA_ELF_TypeObject)
1192 .Case("tls_object", MCSA_ELF_TypeTLS)
1193 .Case("common", MCSA_ELF_TypeCommon)
1194 .Case("notype", MCSA_ELF_TypeNoType)
1195 .Default(MCSA_Invalid);
1197 if (Attr == MCSA_Invalid)
1198 return Error(TypeLoc, "unsupported attribute in '.type' directive");
1200 if (getLexer().isNot(AsmToken::EndOfStatement))
1201 return TokError("unexpected token in '.type' directive");
1205 getStreamer().EmitSymbolAttribute(Sym, Attr);
1210 /// ParseDirectiveComm
1211 /// ::= ( .comm | .lcomm ) identifier , size_expression [ , align_expression ]
1212 bool AsmParser::ParseDirectiveComm(bool IsLocal) {
1213 SMLoc IDLoc = getLexer().getLoc();
1215 if (ParseIdentifier(Name))
1216 return TokError("expected identifier in directive");
1218 // Handle the identifier as the key symbol.
1219 MCSymbol *Sym = getContext().GetOrCreateSymbol(Name);
1221 if (getLexer().isNot(AsmToken::Comma))
1222 return TokError("unexpected token in directive");
1226 SMLoc SizeLoc = getLexer().getLoc();
1227 if (ParseAbsoluteExpression(Size))
1230 int64_t Pow2Alignment = 0;
1231 SMLoc Pow2AlignmentLoc;
1232 if (getLexer().is(AsmToken::Comma)) {
1234 Pow2AlignmentLoc = getLexer().getLoc();
1235 if (ParseAbsoluteExpression(Pow2Alignment))
1238 // If this target takes alignments in bytes (not log) validate and convert.
1239 if (Lexer.getMAI().getAlignmentIsInBytes()) {
1240 if (!isPowerOf2_64(Pow2Alignment))
1241 return Error(Pow2AlignmentLoc, "alignment must be a power of 2");
1242 Pow2Alignment = Log2_64(Pow2Alignment);
1246 if (getLexer().isNot(AsmToken::EndOfStatement))
1247 return TokError("unexpected token in '.comm' or '.lcomm' directive");
1251 // NOTE: a size of zero for a .comm should create a undefined symbol
1252 // but a size of .lcomm creates a bss symbol of size zero.
1254 return Error(SizeLoc, "invalid '.comm' or '.lcomm' directive size, can't "
1255 "be less than zero");
1257 // NOTE: The alignment in the directive is a power of 2 value, the assembler
1258 // may internally end up wanting an alignment in bytes.
1259 // FIXME: Diagnose overflow.
1260 if (Pow2Alignment < 0)
1261 return Error(Pow2AlignmentLoc, "invalid '.comm' or '.lcomm' directive "
1262 "alignment, can't be less than zero");
1264 if (!Sym->isUndefined())
1265 return Error(IDLoc, "invalid symbol redefinition");
1267 // '.lcomm' is equivalent to '.zerofill'.
1268 // Create the Symbol as a common or local common with Size and Pow2Alignment
1270 getStreamer().EmitZerofill(Ctx.getMachOSection(
1271 "__DATA", "__bss", MCSectionMachO::S_ZEROFILL,
1272 0, SectionKind::getBSS()),
1273 Sym, Size, 1 << Pow2Alignment);
1277 getStreamer().EmitCommonSymbol(Sym, Size, 1 << Pow2Alignment);
1281 /// ParseDirectiveAbort
1282 /// ::= .abort [ "abort_string" ]
1283 bool AsmParser::ParseDirectiveAbort() {
1284 // FIXME: Use loc from directive.
1285 SMLoc Loc = getLexer().getLoc();
1288 if (getLexer().isNot(AsmToken::EndOfStatement)) {
1289 if (getLexer().isNot(AsmToken::String))
1290 return TokError("expected string in '.abort' directive");
1292 Str = getTok().getString();
1297 if (getLexer().isNot(AsmToken::EndOfStatement))
1298 return TokError("unexpected token in '.abort' directive");
1302 // FIXME: Handle here.
1304 Error(Loc, ".abort detected. Assembly stopping.");
1306 Error(Loc, ".abort '" + Str + "' detected. Assembly stopping.");
1311 /// ParseDirectiveInclude
1312 /// ::= .include "filename"
1313 bool AsmParser::ParseDirectiveInclude() {
1314 if (getLexer().isNot(AsmToken::String))
1315 return TokError("expected string in '.include' directive");
1317 std::string Filename = getTok().getString();
1318 SMLoc IncludeLoc = getLexer().getLoc();
1321 if (getLexer().isNot(AsmToken::EndOfStatement))
1322 return TokError("unexpected token in '.include' directive");
1324 // Strip the quotes.
1325 Filename = Filename.substr(1, Filename.size()-2);
1327 // Attempt to switch the lexer to the included file before consuming the end
1328 // of statement to avoid losing it when we switch.
1329 if (EnterIncludeFile(Filename)) {
1330 PrintMessage(IncludeLoc,
1331 "Could not find include file '" + Filename + "'",
1339 /// ParseDirectiveIf
1340 /// ::= .if expression
1341 bool AsmParser::ParseDirectiveIf(SMLoc DirectiveLoc) {
1342 TheCondStack.push_back(TheCondState);
1343 TheCondState.TheCond = AsmCond::IfCond;
1344 if(TheCondState.Ignore) {
1345 EatToEndOfStatement();
1349 if (ParseAbsoluteExpression(ExprValue))
1352 if (getLexer().isNot(AsmToken::EndOfStatement))
1353 return TokError("unexpected token in '.if' directive");
1357 TheCondState.CondMet = ExprValue;
1358 TheCondState.Ignore = !TheCondState.CondMet;
1364 /// ParseDirectiveElseIf
1365 /// ::= .elseif expression
1366 bool AsmParser::ParseDirectiveElseIf(SMLoc DirectiveLoc) {
1367 if (TheCondState.TheCond != AsmCond::IfCond &&
1368 TheCondState.TheCond != AsmCond::ElseIfCond)
1369 Error(DirectiveLoc, "Encountered a .elseif that doesn't follow a .if or "
1371 TheCondState.TheCond = AsmCond::ElseIfCond;
1373 bool LastIgnoreState = false;
1374 if (!TheCondStack.empty())
1375 LastIgnoreState = TheCondStack.back().Ignore;
1376 if (LastIgnoreState || TheCondState.CondMet) {
1377 TheCondState.Ignore = true;
1378 EatToEndOfStatement();
1382 if (ParseAbsoluteExpression(ExprValue))
1385 if (getLexer().isNot(AsmToken::EndOfStatement))
1386 return TokError("unexpected token in '.elseif' directive");
1389 TheCondState.CondMet = ExprValue;
1390 TheCondState.Ignore = !TheCondState.CondMet;
1396 /// ParseDirectiveElse
1398 bool AsmParser::ParseDirectiveElse(SMLoc DirectiveLoc) {
1399 if (getLexer().isNot(AsmToken::EndOfStatement))
1400 return TokError("unexpected token in '.else' directive");
1404 if (TheCondState.TheCond != AsmCond::IfCond &&
1405 TheCondState.TheCond != AsmCond::ElseIfCond)
1406 Error(DirectiveLoc, "Encountered a .else that doesn't follow a .if or an "
1408 TheCondState.TheCond = AsmCond::ElseCond;
1409 bool LastIgnoreState = false;
1410 if (!TheCondStack.empty())
1411 LastIgnoreState = TheCondStack.back().Ignore;
1412 if (LastIgnoreState || TheCondState.CondMet)
1413 TheCondState.Ignore = true;
1415 TheCondState.Ignore = false;
1420 /// ParseDirectiveEndIf
1422 bool AsmParser::ParseDirectiveEndIf(SMLoc DirectiveLoc) {
1423 if (getLexer().isNot(AsmToken::EndOfStatement))
1424 return TokError("unexpected token in '.endif' directive");
1428 if ((TheCondState.TheCond == AsmCond::NoCond) ||
1429 TheCondStack.empty())
1430 Error(DirectiveLoc, "Encountered a .endif that doesn't follow a .if or "
1432 if (!TheCondStack.empty()) {
1433 TheCondState = TheCondStack.back();
1434 TheCondStack.pop_back();
1440 /// ParseDirectiveFile
1441 /// ::= .file [number] string
1442 bool GenericAsmParser::ParseDirectiveFile(StringRef, SMLoc DirectiveLoc) {
1443 // FIXME: I'm not sure what this is.
1444 int64_t FileNumber = -1;
1445 if (getLexer().is(AsmToken::Integer)) {
1446 FileNumber = getTok().getIntVal();
1450 return TokError("file number less than one");
1453 if (getLexer().isNot(AsmToken::String))
1454 return TokError("unexpected token in '.file' directive");
1456 StringRef Filename = getTok().getString();
1457 Filename = Filename.substr(1, Filename.size()-2);
1460 if (getLexer().isNot(AsmToken::EndOfStatement))
1461 return TokError("unexpected token in '.file' directive");
1463 if (FileNumber == -1)
1464 getStreamer().EmitFileDirective(Filename);
1466 getStreamer().EmitDwarfFileDirective(FileNumber, Filename);
1471 /// ParseDirectiveLine
1472 /// ::= .line [number]
1473 bool GenericAsmParser::ParseDirectiveLine(StringRef, SMLoc DirectiveLoc) {
1474 if (getLexer().isNot(AsmToken::EndOfStatement)) {
1475 if (getLexer().isNot(AsmToken::Integer))
1476 return TokError("unexpected token in '.line' directive");
1478 int64_t LineNumber = getTok().getIntVal();
1482 // FIXME: Do something with the .line.
1485 if (getLexer().isNot(AsmToken::EndOfStatement))
1486 return TokError("unexpected token in '.line' directive");
1492 /// ParseDirectiveLoc
1493 /// ::= .loc number [number [number]]
1494 bool GenericAsmParser::ParseDirectiveLoc(StringRef, SMLoc DirectiveLoc) {
1495 if (getLexer().isNot(AsmToken::Integer))
1496 return TokError("unexpected token in '.loc' directive");
1498 // FIXME: What are these fields?
1499 int64_t FileNumber = getTok().getIntVal();
1501 // FIXME: Validate file.
1504 if (getLexer().isNot(AsmToken::EndOfStatement)) {
1505 if (getLexer().isNot(AsmToken::Integer))
1506 return TokError("unexpected token in '.loc' directive");
1508 int64_t Param2 = getTok().getIntVal();
1512 if (getLexer().isNot(AsmToken::EndOfStatement)) {
1513 if (getLexer().isNot(AsmToken::Integer))
1514 return TokError("unexpected token in '.loc' directive");
1516 int64_t Param3 = getTok().getIntVal();
1520 // FIXME: Do something with the .loc.
1524 if (getLexer().isNot(AsmToken::EndOfStatement))
1525 return TokError("unexpected token in '.file' directive");