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/MCSectionMachO.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"
35 /// \brief Generic implementations of directive handling, etc. which is shared
36 /// (or the default, at least) for all assembler parser.
37 class GenericAsmParser : public MCAsmParserExtension {
41 virtual void Initialize(MCAsmParser &Parser) {
42 // Call the base implementation.
43 this->MCAsmParserExtension::Initialize(Parser);
45 // Debugging directives.
46 Parser.AddDirectiveHandler(this, ".file", MCAsmParser::DirectiveHandler(
47 &GenericAsmParser::ParseDirectiveFile));
48 Parser.AddDirectiveHandler(this, ".line", MCAsmParser::DirectiveHandler(
49 &GenericAsmParser::ParseDirectiveLine));
50 Parser.AddDirectiveHandler(this, ".loc", MCAsmParser::DirectiveHandler(
51 &GenericAsmParser::ParseDirectiveLoc));
54 bool ParseDirectiveFile(StringRef, SMLoc DirectiveLoc); // ".file"
55 bool ParseDirectiveLine(StringRef, SMLoc DirectiveLoc); // ".line"
56 bool ParseDirectiveLoc(StringRef, SMLoc DirectiveLoc); // ".loc"
59 /// \brief Implementation of directive handling which is shared across all
61 class DarwinAsmParser : public MCAsmParserExtension {
65 virtual void Initialize(MCAsmParser &Parser) {
66 // Call the base implementation.
67 this->MCAsmParserExtension::Initialize(Parser);
69 Parser.AddDirectiveHandler(this, ".desc", MCAsmParser::DirectiveHandler(
70 &DarwinAsmParser::ParseDirectiveDesc));
71 Parser.AddDirectiveHandler(this, ".lsym", MCAsmParser::DirectiveHandler(
72 &DarwinAsmParser::ParseDirectiveLsym));
73 Parser.AddDirectiveHandler(this, ".subsections_via_symbols",
74 MCAsmParser::DirectiveHandler(
75 &DarwinAsmParser::ParseDirectiveSubsectionsViaSymbols));
76 Parser.AddDirectiveHandler(this, ".dump", MCAsmParser::DirectiveHandler(
77 &DarwinAsmParser::ParseDirectiveDumpOrLoad));
78 Parser.AddDirectiveHandler(this, ".load", MCAsmParser::DirectiveHandler(
79 &DarwinAsmParser::ParseDirectiveDumpOrLoad));
80 Parser.AddDirectiveHandler(this, ".secure_log_unique",
81 MCAsmParser::DirectiveHandler(
82 &DarwinAsmParser::ParseDirectiveSecureLogUnique));
83 Parser.AddDirectiveHandler(this, ".secure_log_reset",
84 MCAsmParser::DirectiveHandler(
85 &DarwinAsmParser::ParseDirectiveSecureLogReset));
86 Parser.AddDirectiveHandler(this, ".tbss",
87 MCAsmParser::DirectiveHandler(
88 &DarwinAsmParser::ParseDirectiveTBSS));
89 Parser.AddDirectiveHandler(this, ".zerofill",
90 MCAsmParser::DirectiveHandler(
91 &DarwinAsmParser::ParseDirectiveZerofill));
94 bool ParseDirectiveDesc(StringRef, SMLoc);
95 bool ParseDirectiveDumpOrLoad(StringRef, SMLoc);
96 bool ParseDirectiveLsym(StringRef, SMLoc);
97 bool ParseDirectiveSecureLogReset(StringRef, SMLoc);
98 bool ParseDirectiveSecureLogUnique(StringRef, SMLoc);
99 bool ParseDirectiveSubsectionsViaSymbols(StringRef, SMLoc);
100 bool ParseDirectiveTBSS(StringRef, SMLoc);
101 bool ParseDirectiveZerofill(StringRef, SMLoc);
106 enum { DEFAULT_ADDRSPACE = 0 };
108 AsmParser::AsmParser(const Target &T, SourceMgr &_SM, MCContext &_Ctx,
109 MCStreamer &_Out, const MCAsmInfo &_MAI)
110 : Lexer(_MAI), Ctx(_Ctx), Out(_Out), SrcMgr(_SM),
111 GenericParser(new GenericAsmParser), PlatformParser(0),
112 TargetParser(0), CurBuffer(0) {
113 Lexer.setBuffer(SrcMgr.getMemoryBuffer(CurBuffer));
115 // Initialize the generic parser.
116 GenericParser->Initialize(*this);
118 // Initialize the platform / file format parser.
120 // FIXME: This is a hack, we need to (majorly) cleanup how these objects are
122 if (_MAI.hasSubsectionsViaSymbols()) {
123 PlatformParser = new DarwinAsmParser;
124 PlatformParser->Initialize(*this);
128 AsmParser::~AsmParser() {
129 delete PlatformParser;
130 delete GenericParser;
133 void AsmParser::setTargetParser(TargetAsmParser &P) {
134 assert(!TargetParser && "Target parser is already initialized!");
136 TargetParser->Initialize(*this);
139 void AsmParser::Warning(SMLoc L, const Twine &Msg) {
140 PrintMessage(L, Msg.str(), "warning");
143 bool AsmParser::Error(SMLoc L, const Twine &Msg) {
144 PrintMessage(L, Msg.str(), "error");
148 void AsmParser::PrintMessage(SMLoc Loc, const std::string &Msg,
149 const char *Type) const {
150 SrcMgr.PrintMessage(Loc, Msg, Type);
153 bool AsmParser::EnterIncludeFile(const std::string &Filename) {
154 int NewBuf = SrcMgr.AddIncludeFile(Filename, Lexer.getLoc());
160 Lexer.setBuffer(SrcMgr.getMemoryBuffer(CurBuffer));
165 const AsmToken &AsmParser::Lex() {
166 const AsmToken *tok = &Lexer.Lex();
168 if (tok->is(AsmToken::Eof)) {
169 // If this is the end of an included file, pop the parent file off the
171 SMLoc ParentIncludeLoc = SrcMgr.getParentIncludeLoc(CurBuffer);
172 if (ParentIncludeLoc != SMLoc()) {
173 CurBuffer = SrcMgr.FindBufferContainingLoc(ParentIncludeLoc);
174 Lexer.setBuffer(SrcMgr.getMemoryBuffer(CurBuffer),
175 ParentIncludeLoc.getPointer());
180 if (tok->is(AsmToken::Error))
181 PrintMessage(Lexer.getErrLoc(), Lexer.getErr(), "error");
186 bool AsmParser::Run(bool NoInitialTextSection, bool NoFinalize) {
187 // Create the initial section, if requested.
189 // FIXME: Target hook & command line option for initial section.
190 if (!NoInitialTextSection)
191 Out.SwitchSection(Ctx.getMachOSection("__TEXT", "__text",
192 MCSectionMachO::S_ATTR_PURE_INSTRUCTIONS,
193 0, SectionKind::getText()));
198 bool HadError = false;
200 AsmCond StartingCondState = TheCondState;
202 // While we have input, parse each statement.
203 while (Lexer.isNot(AsmToken::Eof)) {
204 if (!ParseStatement()) continue;
206 // We had an error, remember it and recover by skipping to the next line.
208 EatToEndOfStatement();
211 if (TheCondState.TheCond != StartingCondState.TheCond ||
212 TheCondState.Ignore != StartingCondState.Ignore)
213 return TokError("unmatched .ifs or .elses");
215 // Finalize the output stream if there are no errors and if the client wants
217 if (!HadError && !NoFinalize)
223 /// EatToEndOfStatement - Throw away the rest of the line for testing purposes.
224 void AsmParser::EatToEndOfStatement() {
225 while (Lexer.isNot(AsmToken::EndOfStatement) &&
226 Lexer.isNot(AsmToken::Eof))
230 if (Lexer.is(AsmToken::EndOfStatement))
235 /// ParseParenExpr - Parse a paren expression and return it.
236 /// NOTE: This assumes the leading '(' has already been consumed.
238 /// parenexpr ::= expr)
240 bool AsmParser::ParseParenExpr(const MCExpr *&Res, SMLoc &EndLoc) {
241 if (ParseExpression(Res)) return true;
242 if (Lexer.isNot(AsmToken::RParen))
243 return TokError("expected ')' in parentheses expression");
244 EndLoc = Lexer.getLoc();
249 MCSymbol *AsmParser::CreateSymbol(StringRef Name) {
250 // FIXME: Inline into callers.
251 return Ctx.GetOrCreateSymbol(Name);
254 /// ParsePrimaryExpr - Parse a primary expression and return it.
255 /// primaryexpr ::= (parenexpr
256 /// primaryexpr ::= symbol
257 /// primaryexpr ::= number
258 /// primaryexpr ::= '.'
259 /// primaryexpr ::= ~,+,- primaryexpr
260 bool AsmParser::ParsePrimaryExpr(const MCExpr *&Res, SMLoc &EndLoc) {
261 switch (Lexer.getKind()) {
263 return TokError("unknown token in expression");
264 case AsmToken::Exclaim:
265 Lex(); // Eat the operator.
266 if (ParsePrimaryExpr(Res, EndLoc))
268 Res = MCUnaryExpr::CreateLNot(Res, getContext());
270 case AsmToken::String:
271 case AsmToken::Identifier: {
272 // This is a symbol reference.
273 std::pair<StringRef, StringRef> Split = getTok().getIdentifier().split('@');
274 MCSymbol *Sym = CreateSymbol(Split.first);
276 // Mark the symbol as used in an expression.
277 Sym->setUsedInExpr(true);
279 // Lookup the symbol variant if used.
280 MCSymbolRefExpr::VariantKind Variant = MCSymbolRefExpr::VK_None;
281 if (Split.first.size() != getTok().getIdentifier().size())
282 Variant = MCSymbolRefExpr::getVariantKindForName(Split.second);
284 EndLoc = Lexer.getLoc();
285 Lex(); // Eat identifier.
287 // If this is an absolute variable reference, substitute it now to preserve
288 // semantics in the face of reassignment.
289 if (Sym->isVariable() && isa<MCConstantExpr>(Sym->getVariableValue())) {
291 return Error(EndLoc, "unexpected modified on variable reference");
293 Res = Sym->getVariableValue();
297 // Otherwise create a symbol ref.
298 Res = MCSymbolRefExpr::Create(Sym, Variant, getContext());
301 case AsmToken::Integer: {
302 SMLoc Loc = getTok().getLoc();
303 int64_t IntVal = getTok().getIntVal();
304 Res = MCConstantExpr::Create(IntVal, getContext());
305 EndLoc = Lexer.getLoc();
307 // Look for 'b' or 'f' following an Integer as a directional label
308 if (Lexer.getKind() == AsmToken::Identifier) {
309 StringRef IDVal = getTok().getString();
310 if (IDVal == "f" || IDVal == "b"){
311 MCSymbol *Sym = Ctx.GetDirectionalLocalSymbol(IntVal,
312 IDVal == "f" ? 1 : 0);
313 Res = MCSymbolRefExpr::Create(Sym, MCSymbolRefExpr::VK_None,
315 if(IDVal == "b" && Sym->isUndefined())
316 return Error(Loc, "invalid reference to undefined symbol");
317 EndLoc = Lexer.getLoc();
318 Lex(); // Eat identifier.
323 case AsmToken::Dot: {
324 // This is a '.' reference, which references the current PC. Emit a
325 // temporary label to the streamer and refer to it.
326 MCSymbol *Sym = Ctx.CreateTempSymbol();
328 Res = MCSymbolRefExpr::Create(Sym, MCSymbolRefExpr::VK_None, getContext());
329 EndLoc = Lexer.getLoc();
330 Lex(); // Eat identifier.
334 case AsmToken::LParen:
335 Lex(); // Eat the '('.
336 return ParseParenExpr(Res, EndLoc);
337 case AsmToken::Minus:
338 Lex(); // Eat the operator.
339 if (ParsePrimaryExpr(Res, EndLoc))
341 Res = MCUnaryExpr::CreateMinus(Res, getContext());
344 Lex(); // Eat the operator.
345 if (ParsePrimaryExpr(Res, EndLoc))
347 Res = MCUnaryExpr::CreatePlus(Res, getContext());
349 case AsmToken::Tilde:
350 Lex(); // Eat the operator.
351 if (ParsePrimaryExpr(Res, EndLoc))
353 Res = MCUnaryExpr::CreateNot(Res, getContext());
358 bool AsmParser::ParseExpression(const MCExpr *&Res) {
360 return ParseExpression(Res, EndLoc);
363 /// ParseExpression - Parse an expression and return it.
365 /// expr ::= expr +,- expr -> lowest.
366 /// expr ::= expr |,^,&,! expr -> middle.
367 /// expr ::= expr *,/,%,<<,>> expr -> highest.
368 /// expr ::= primaryexpr
370 bool AsmParser::ParseExpression(const MCExpr *&Res, SMLoc &EndLoc) {
371 // Parse the expression.
373 if (ParsePrimaryExpr(Res, EndLoc) || ParseBinOpRHS(1, Res, EndLoc))
376 // Try to constant fold it up front, if possible.
378 if (Res->EvaluateAsAbsolute(Value))
379 Res = MCConstantExpr::Create(Value, getContext());
384 bool AsmParser::ParseParenExpression(const MCExpr *&Res, SMLoc &EndLoc) {
386 return ParseParenExpr(Res, EndLoc) ||
387 ParseBinOpRHS(1, Res, EndLoc);
390 bool AsmParser::ParseAbsoluteExpression(int64_t &Res) {
393 SMLoc StartLoc = Lexer.getLoc();
394 if (ParseExpression(Expr))
397 if (!Expr->EvaluateAsAbsolute(Res))
398 return Error(StartLoc, "expected absolute expression");
403 static unsigned getBinOpPrecedence(AsmToken::TokenKind K,
404 MCBinaryExpr::Opcode &Kind) {
407 return 0; // not a binop.
409 // Lowest Precedence: &&, ||
410 case AsmToken::AmpAmp:
411 Kind = MCBinaryExpr::LAnd;
413 case AsmToken::PipePipe:
414 Kind = MCBinaryExpr::LOr;
417 // Low Precedence: +, -, ==, !=, <>, <, <=, >, >=
419 Kind = MCBinaryExpr::Add;
421 case AsmToken::Minus:
422 Kind = MCBinaryExpr::Sub;
424 case AsmToken::EqualEqual:
425 Kind = MCBinaryExpr::EQ;
427 case AsmToken::ExclaimEqual:
428 case AsmToken::LessGreater:
429 Kind = MCBinaryExpr::NE;
432 Kind = MCBinaryExpr::LT;
434 case AsmToken::LessEqual:
435 Kind = MCBinaryExpr::LTE;
437 case AsmToken::Greater:
438 Kind = MCBinaryExpr::GT;
440 case AsmToken::GreaterEqual:
441 Kind = MCBinaryExpr::GTE;
444 // Intermediate Precedence: |, &, ^
446 // FIXME: gas seems to support '!' as an infix operator?
448 Kind = MCBinaryExpr::Or;
450 case AsmToken::Caret:
451 Kind = MCBinaryExpr::Xor;
454 Kind = MCBinaryExpr::And;
457 // Highest Precedence: *, /, %, <<, >>
459 Kind = MCBinaryExpr::Mul;
461 case AsmToken::Slash:
462 Kind = MCBinaryExpr::Div;
464 case AsmToken::Percent:
465 Kind = MCBinaryExpr::Mod;
467 case AsmToken::LessLess:
468 Kind = MCBinaryExpr::Shl;
470 case AsmToken::GreaterGreater:
471 Kind = MCBinaryExpr::Shr;
477 /// ParseBinOpRHS - Parse all binary operators with precedence >= 'Precedence'.
478 /// Res contains the LHS of the expression on input.
479 bool AsmParser::ParseBinOpRHS(unsigned Precedence, const MCExpr *&Res,
482 MCBinaryExpr::Opcode Kind = MCBinaryExpr::Add;
483 unsigned TokPrec = getBinOpPrecedence(Lexer.getKind(), Kind);
485 // If the next token is lower precedence than we are allowed to eat, return
486 // successfully with what we ate already.
487 if (TokPrec < Precedence)
492 // Eat the next primary expression.
494 if (ParsePrimaryExpr(RHS, EndLoc)) return true;
496 // If BinOp binds less tightly with RHS than the operator after RHS, let
497 // the pending operator take RHS as its LHS.
498 MCBinaryExpr::Opcode Dummy;
499 unsigned NextTokPrec = getBinOpPrecedence(Lexer.getKind(), Dummy);
500 if (TokPrec < NextTokPrec) {
501 if (ParseBinOpRHS(Precedence+1, RHS, EndLoc)) return true;
504 // Merge LHS and RHS according to operator.
505 Res = MCBinaryExpr::Create(Kind, Res, RHS, getContext());
513 /// ::= EndOfStatement
514 /// ::= Label* Directive ...Operands... EndOfStatement
515 /// ::= Label* Identifier OperandList* EndOfStatement
516 bool AsmParser::ParseStatement() {
517 if (Lexer.is(AsmToken::EndOfStatement)) {
523 // Statements always start with an identifier.
524 AsmToken ID = getTok();
525 SMLoc IDLoc = ID.getLoc();
527 int64_t LocalLabelVal = -1;
528 // GUESS allow an integer followed by a ':' as a directional local label
529 if (Lexer.is(AsmToken::Integer)) {
530 LocalLabelVal = getTok().getIntVal();
531 if (LocalLabelVal < 0) {
532 if (!TheCondState.Ignore)
533 return TokError("unexpected token at start of statement");
537 IDVal = getTok().getString();
538 Lex(); // Consume the integer token to be used as an identifier token.
539 if (Lexer.getKind() != AsmToken::Colon) {
540 if (!TheCondState.Ignore)
541 return TokError("unexpected token at start of statement");
545 else if (ParseIdentifier(IDVal)) {
546 if (!TheCondState.Ignore)
547 return TokError("unexpected token at start of statement");
551 // Handle conditional assembly here before checking for skipping. We
552 // have to do this so that .endif isn't skipped in a ".if 0" block for
555 return ParseDirectiveIf(IDLoc);
556 if (IDVal == ".elseif")
557 return ParseDirectiveElseIf(IDLoc);
558 if (IDVal == ".else")
559 return ParseDirectiveElse(IDLoc);
560 if (IDVal == ".endif")
561 return ParseDirectiveEndIf(IDLoc);
563 // If we are in a ".if 0" block, ignore this statement.
564 if (TheCondState.Ignore) {
565 EatToEndOfStatement();
569 // FIXME: Recurse on local labels?
571 // See what kind of statement we have.
572 switch (Lexer.getKind()) {
573 case AsmToken::Colon: {
574 // identifier ':' -> Label.
577 // Diagnose attempt to use a variable as a label.
579 // FIXME: Diagnostics. Note the location of the definition as a label.
580 // FIXME: This doesn't diagnose assignment to a symbol which has been
581 // implicitly marked as external.
583 if (LocalLabelVal == -1)
584 Sym = CreateSymbol(IDVal);
586 Sym = Ctx.CreateDirectionalLocalSymbol(LocalLabelVal);
587 if (!Sym->isUndefined() || Sym->isVariable())
588 return Error(IDLoc, "invalid symbol redefinition");
593 // Consume any end of statement token, if present, to avoid spurious
594 // AddBlankLine calls().
595 if (Lexer.is(AsmToken::EndOfStatement)) {
597 if (Lexer.is(AsmToken::Eof))
601 return ParseStatement();
604 case AsmToken::Equal:
605 // identifier '=' ... -> assignment statement
608 return ParseAssignment(IDVal);
610 default: // Normal instruction or directive.
614 // Otherwise, we have a normal instruction or directive.
615 if (IDVal[0] == '.') {
616 // FIXME: This should be driven based on a hash lookup and callback.
617 if (IDVal == ".section")
618 return ParseDirectiveDarwinSection();
619 if (IDVal == ".text")
620 // FIXME: This changes behavior based on the -static flag to the
622 return ParseDirectiveSectionSwitch("__TEXT", "__text",
623 MCSectionMachO::S_ATTR_PURE_INSTRUCTIONS);
624 if (IDVal == ".const")
625 return ParseDirectiveSectionSwitch("__TEXT", "__const");
626 if (IDVal == ".static_const")
627 return ParseDirectiveSectionSwitch("__TEXT", "__static_const");
628 if (IDVal == ".cstring")
629 return ParseDirectiveSectionSwitch("__TEXT","__cstring",
630 MCSectionMachO::S_CSTRING_LITERALS);
631 if (IDVal == ".literal4")
632 return ParseDirectiveSectionSwitch("__TEXT", "__literal4",
633 MCSectionMachO::S_4BYTE_LITERALS,
635 if (IDVal == ".literal8")
636 return ParseDirectiveSectionSwitch("__TEXT", "__literal8",
637 MCSectionMachO::S_8BYTE_LITERALS,
639 if (IDVal == ".literal16")
640 return ParseDirectiveSectionSwitch("__TEXT","__literal16",
641 MCSectionMachO::S_16BYTE_LITERALS,
643 if (IDVal == ".constructor")
644 return ParseDirectiveSectionSwitch("__TEXT","__constructor");
645 if (IDVal == ".destructor")
646 return ParseDirectiveSectionSwitch("__TEXT","__destructor");
647 if (IDVal == ".fvmlib_init0")
648 return ParseDirectiveSectionSwitch("__TEXT","__fvmlib_init0");
649 if (IDVal == ".fvmlib_init1")
650 return ParseDirectiveSectionSwitch("__TEXT","__fvmlib_init1");
652 // FIXME: The assembler manual claims that this has the self modify code
653 // flag, at least on x86-32, but that does not appear to be correct.
654 if (IDVal == ".symbol_stub")
655 return ParseDirectiveSectionSwitch("__TEXT","__symbol_stub",
656 MCSectionMachO::S_SYMBOL_STUBS |
657 MCSectionMachO::S_ATTR_PURE_INSTRUCTIONS,
658 // FIXME: Different on PPC and ARM.
660 // FIXME: PowerPC only?
661 if (IDVal == ".picsymbol_stub")
662 return ParseDirectiveSectionSwitch("__TEXT","__picsymbol_stub",
663 MCSectionMachO::S_SYMBOL_STUBS |
664 MCSectionMachO::S_ATTR_PURE_INSTRUCTIONS,
666 if (IDVal == ".data")
667 return ParseDirectiveSectionSwitch("__DATA", "__data");
668 if (IDVal == ".static_data")
669 return ParseDirectiveSectionSwitch("__DATA", "__static_data");
671 // FIXME: The section names of these two are misspelled in the assembler
673 if (IDVal == ".non_lazy_symbol_pointer")
674 return ParseDirectiveSectionSwitch("__DATA", "__nl_symbol_ptr",
675 MCSectionMachO::S_NON_LAZY_SYMBOL_POINTERS,
677 if (IDVal == ".lazy_symbol_pointer")
678 return ParseDirectiveSectionSwitch("__DATA", "__la_symbol_ptr",
679 MCSectionMachO::S_LAZY_SYMBOL_POINTERS,
682 if (IDVal == ".dyld")
683 return ParseDirectiveSectionSwitch("__DATA", "__dyld");
684 if (IDVal == ".mod_init_func")
685 return ParseDirectiveSectionSwitch("__DATA", "__mod_init_func",
686 MCSectionMachO::S_MOD_INIT_FUNC_POINTERS,
688 if (IDVal == ".mod_term_func")
689 return ParseDirectiveSectionSwitch("__DATA", "__mod_term_func",
690 MCSectionMachO::S_MOD_TERM_FUNC_POINTERS,
692 if (IDVal == ".const_data")
693 return ParseDirectiveSectionSwitch("__DATA", "__const");
696 if (IDVal == ".objc_class")
697 return ParseDirectiveSectionSwitch("__OBJC", "__class",
698 MCSectionMachO::S_ATTR_NO_DEAD_STRIP);
699 if (IDVal == ".objc_meta_class")
700 return ParseDirectiveSectionSwitch("__OBJC", "__meta_class",
701 MCSectionMachO::S_ATTR_NO_DEAD_STRIP);
702 if (IDVal == ".objc_cat_cls_meth")
703 return ParseDirectiveSectionSwitch("__OBJC", "__cat_cls_meth",
704 MCSectionMachO::S_ATTR_NO_DEAD_STRIP);
705 if (IDVal == ".objc_cat_inst_meth")
706 return ParseDirectiveSectionSwitch("__OBJC", "__cat_inst_meth",
707 MCSectionMachO::S_ATTR_NO_DEAD_STRIP);
708 if (IDVal == ".objc_protocol")
709 return ParseDirectiveSectionSwitch("__OBJC", "__protocol",
710 MCSectionMachO::S_ATTR_NO_DEAD_STRIP);
711 if (IDVal == ".objc_string_object")
712 return ParseDirectiveSectionSwitch("__OBJC", "__string_object",
713 MCSectionMachO::S_ATTR_NO_DEAD_STRIP);
714 if (IDVal == ".objc_cls_meth")
715 return ParseDirectiveSectionSwitch("__OBJC", "__cls_meth",
716 MCSectionMachO::S_ATTR_NO_DEAD_STRIP);
717 if (IDVal == ".objc_inst_meth")
718 return ParseDirectiveSectionSwitch("__OBJC", "__inst_meth",
719 MCSectionMachO::S_ATTR_NO_DEAD_STRIP);
720 if (IDVal == ".objc_cls_refs")
721 return ParseDirectiveSectionSwitch("__OBJC", "__cls_refs",
722 MCSectionMachO::S_ATTR_NO_DEAD_STRIP |
723 MCSectionMachO::S_LITERAL_POINTERS,
725 if (IDVal == ".objc_message_refs")
726 return ParseDirectiveSectionSwitch("__OBJC", "__message_refs",
727 MCSectionMachO::S_ATTR_NO_DEAD_STRIP |
728 MCSectionMachO::S_LITERAL_POINTERS,
730 if (IDVal == ".objc_symbols")
731 return ParseDirectiveSectionSwitch("__OBJC", "__symbols",
732 MCSectionMachO::S_ATTR_NO_DEAD_STRIP);
733 if (IDVal == ".objc_category")
734 return ParseDirectiveSectionSwitch("__OBJC", "__category",
735 MCSectionMachO::S_ATTR_NO_DEAD_STRIP);
736 if (IDVal == ".objc_class_vars")
737 return ParseDirectiveSectionSwitch("__OBJC", "__class_vars",
738 MCSectionMachO::S_ATTR_NO_DEAD_STRIP);
739 if (IDVal == ".objc_instance_vars")
740 return ParseDirectiveSectionSwitch("__OBJC", "__instance_vars",
741 MCSectionMachO::S_ATTR_NO_DEAD_STRIP);
742 if (IDVal == ".objc_module_info")
743 return ParseDirectiveSectionSwitch("__OBJC", "__module_info",
744 MCSectionMachO::S_ATTR_NO_DEAD_STRIP);
745 if (IDVal == ".objc_class_names")
746 return ParseDirectiveSectionSwitch("__TEXT", "__cstring",
747 MCSectionMachO::S_CSTRING_LITERALS);
748 if (IDVal == ".objc_meth_var_types")
749 return ParseDirectiveSectionSwitch("__TEXT", "__cstring",
750 MCSectionMachO::S_CSTRING_LITERALS);
751 if (IDVal == ".objc_meth_var_names")
752 return ParseDirectiveSectionSwitch("__TEXT", "__cstring",
753 MCSectionMachO::S_CSTRING_LITERALS);
754 if (IDVal == ".objc_selector_strs")
755 return ParseDirectiveSectionSwitch("__OBJC", "__selector_strs",
756 MCSectionMachO::S_CSTRING_LITERALS);
758 if (IDVal == ".tdata")
759 return ParseDirectiveSectionSwitch("__DATA", "__thread_data",
760 MCSectionMachO::S_THREAD_LOCAL_REGULAR);
762 return ParseDirectiveSectionSwitch("__DATA", "__thread_vars",
763 MCSectionMachO::S_THREAD_LOCAL_VARIABLES);
764 if (IDVal == ".thread_init_func")
765 return ParseDirectiveSectionSwitch("__DATA", "__thread_init",
766 MCSectionMachO::S_THREAD_LOCAL_INIT_FUNCTION_POINTERS);
768 // Assembler features
770 return ParseDirectiveSet();
774 if (IDVal == ".ascii")
775 return ParseDirectiveAscii(false);
776 if (IDVal == ".asciz")
777 return ParseDirectiveAscii(true);
779 if (IDVal == ".byte")
780 return ParseDirectiveValue(1);
781 if (IDVal == ".short")
782 return ParseDirectiveValue(2);
783 if (IDVal == ".long")
784 return ParseDirectiveValue(4);
785 if (IDVal == ".quad")
786 return ParseDirectiveValue(8);
788 // FIXME: Target hooks for IsPow2.
789 if (IDVal == ".align")
790 return ParseDirectiveAlign(/*IsPow2=*/true, /*ExprSize=*/1);
791 if (IDVal == ".align32")
792 return ParseDirectiveAlign(/*IsPow2=*/true, /*ExprSize=*/4);
793 if (IDVal == ".balign")
794 return ParseDirectiveAlign(/*IsPow2=*/false, /*ExprSize=*/1);
795 if (IDVal == ".balignw")
796 return ParseDirectiveAlign(/*IsPow2=*/false, /*ExprSize=*/2);
797 if (IDVal == ".balignl")
798 return ParseDirectiveAlign(/*IsPow2=*/false, /*ExprSize=*/4);
799 if (IDVal == ".p2align")
800 return ParseDirectiveAlign(/*IsPow2=*/true, /*ExprSize=*/1);
801 if (IDVal == ".p2alignw")
802 return ParseDirectiveAlign(/*IsPow2=*/true, /*ExprSize=*/2);
803 if (IDVal == ".p2alignl")
804 return ParseDirectiveAlign(/*IsPow2=*/true, /*ExprSize=*/4);
807 return ParseDirectiveOrg();
809 if (IDVal == ".fill")
810 return ParseDirectiveFill();
811 if (IDVal == ".space")
812 return ParseDirectiveSpace();
814 // Symbol attribute directives
816 if (IDVal == ".globl" || IDVal == ".global")
817 return ParseDirectiveSymbolAttribute(MCSA_Global);
818 if (IDVal == ".hidden")
819 return ParseDirectiveSymbolAttribute(MCSA_Hidden);
820 if (IDVal == ".indirect_symbol")
821 return ParseDirectiveSymbolAttribute(MCSA_IndirectSymbol);
822 if (IDVal == ".internal")
823 return ParseDirectiveSymbolAttribute(MCSA_Internal);
824 if (IDVal == ".lazy_reference")
825 return ParseDirectiveSymbolAttribute(MCSA_LazyReference);
826 if (IDVal == ".no_dead_strip")
827 return ParseDirectiveSymbolAttribute(MCSA_NoDeadStrip);
828 if (IDVal == ".private_extern")
829 return ParseDirectiveSymbolAttribute(MCSA_PrivateExtern);
830 if (IDVal == ".protected")
831 return ParseDirectiveSymbolAttribute(MCSA_Protected);
832 if (IDVal == ".reference")
833 return ParseDirectiveSymbolAttribute(MCSA_Reference);
834 if (IDVal == ".type")
835 return ParseDirectiveELFType();
836 if (IDVal == ".weak")
837 return ParseDirectiveSymbolAttribute(MCSA_Weak);
838 if (IDVal == ".weak_definition")
839 return ParseDirectiveSymbolAttribute(MCSA_WeakDefinition);
840 if (IDVal == ".weak_reference")
841 return ParseDirectiveSymbolAttribute(MCSA_WeakReference);
842 if (IDVal == ".weak_def_can_be_hidden")
843 return ParseDirectiveSymbolAttribute(MCSA_WeakDefAutoPrivate);
845 if (IDVal == ".comm")
846 return ParseDirectiveComm(/*IsLocal=*/false);
847 if (IDVal == ".lcomm")
848 return ParseDirectiveComm(/*IsLocal=*/true);
850 if (IDVal == ".abort")
851 return ParseDirectiveAbort();
852 if (IDVal == ".include")
853 return ParseDirectiveInclude();
855 // Look up the handler in the handler table.
856 std::pair<MCAsmParserExtension*, DirectiveHandler> Handler =
857 DirectiveMap.lookup(IDVal);
859 return (Handler.first->*Handler.second)(IDVal, IDLoc);
861 // Target hook for parsing target specific directives.
862 if (!getTargetParser().ParseDirective(ID))
865 Warning(IDLoc, "ignoring directive for now");
866 EatToEndOfStatement();
870 // Canonicalize the opcode to lower case.
871 SmallString<128> Opcode;
872 for (unsigned i = 0, e = IDVal.size(); i != e; ++i)
873 Opcode.push_back(tolower(IDVal[i]));
875 SmallVector<MCParsedAsmOperand*, 8> ParsedOperands;
876 bool HadError = getTargetParser().ParseInstruction(Opcode.str(), IDLoc,
878 if (!HadError && Lexer.isNot(AsmToken::EndOfStatement))
879 HadError = TokError("unexpected token in argument list");
881 // If parsing succeeded, match the instruction.
884 if (!getTargetParser().MatchInstruction(ParsedOperands, Inst)) {
885 // Emit the instruction on success.
886 Out.EmitInstruction(Inst);
888 // Otherwise emit a diagnostic about the match failure and set the error
891 // FIXME: We should give nicer diagnostics about the exact failure.
892 Error(IDLoc, "unrecognized instruction");
897 // If there was no error, consume the end-of-statement token. Otherwise this
898 // will be done by our caller.
902 // Free any parsed operands.
903 for (unsigned i = 0, e = ParsedOperands.size(); i != e; ++i)
904 delete ParsedOperands[i];
909 bool AsmParser::ParseAssignment(const StringRef &Name) {
910 // FIXME: Use better location, we should use proper tokens.
911 SMLoc EqualLoc = Lexer.getLoc();
914 if (ParseExpression(Value))
917 if (Lexer.isNot(AsmToken::EndOfStatement))
918 return TokError("unexpected token in assignment");
920 // Eat the end of statement marker.
923 // Validate that the LHS is allowed to be a variable (either it has not been
924 // used as a symbol, or it is an absolute symbol).
925 MCSymbol *Sym = getContext().LookupSymbol(Name);
927 // Diagnose assignment to a label.
929 // FIXME: Diagnostics. Note the location of the definition as a label.
930 // FIXME: Diagnose assignment to protected identifier (e.g., register name).
931 if (Sym->isUndefined() && !Sym->isUsedInExpr())
932 ; // Allow redefinitions of undefined symbols only used in directives.
933 else if (!Sym->isUndefined() && !Sym->isAbsolute())
934 return Error(EqualLoc, "redefinition of '" + Name + "'");
935 else if (!Sym->isVariable())
936 return Error(EqualLoc, "invalid assignment to '" + Name + "'");
937 else if (!isa<MCConstantExpr>(Sym->getVariableValue()))
938 return Error(EqualLoc, "invalid reassignment of non-absolute variable '" +
941 Sym = CreateSymbol(Name);
943 // FIXME: Handle '.'.
945 Sym->setUsedInExpr(true);
947 // Do the assignment.
948 Out.EmitAssignment(Sym, Value);
956 bool AsmParser::ParseIdentifier(StringRef &Res) {
957 if (Lexer.isNot(AsmToken::Identifier) &&
958 Lexer.isNot(AsmToken::String))
961 Res = getTok().getIdentifier();
963 Lex(); // Consume the identifier token.
968 /// ParseDirectiveSet:
969 /// ::= .set identifier ',' expression
970 bool AsmParser::ParseDirectiveSet() {
973 if (ParseIdentifier(Name))
974 return TokError("expected identifier after '.set' directive");
976 if (getLexer().isNot(AsmToken::Comma))
977 return TokError("unexpected token in '.set'");
980 return ParseAssignment(Name);
983 /// ParseDirectiveSection:
984 /// ::= .section identifier (',' identifier)*
985 /// FIXME: This should actually parse out the segment, section, attributes and
986 /// sizeof_stub fields.
987 bool AsmParser::ParseDirectiveDarwinSection() {
988 SMLoc Loc = getLexer().getLoc();
990 StringRef SectionName;
991 if (ParseIdentifier(SectionName))
992 return Error(Loc, "expected identifier after '.section' directive");
994 // Verify there is a following comma.
995 if (!getLexer().is(AsmToken::Comma))
996 return TokError("unexpected token in '.section' directive");
998 std::string SectionSpec = SectionName;
1001 // Add all the tokens until the end of the line, ParseSectionSpecifier will
1003 StringRef EOL = Lexer.LexUntilEndOfStatement();
1004 SectionSpec.append(EOL.begin(), EOL.end());
1007 if (getLexer().isNot(AsmToken::EndOfStatement))
1008 return TokError("unexpected token in '.section' directive");
1012 StringRef Segment, Section;
1013 unsigned TAA, StubSize;
1014 std::string ErrorStr =
1015 MCSectionMachO::ParseSectionSpecifier(SectionSpec, Segment, Section,
1018 if (!ErrorStr.empty())
1019 return Error(Loc, ErrorStr.c_str());
1021 // FIXME: Arch specific.
1022 bool isText = Segment == "__TEXT"; // FIXME: Hack.
1023 getStreamer().SwitchSection(Ctx.getMachOSection(
1024 Segment, Section, TAA, StubSize,
1025 isText ? SectionKind::getText()
1026 : SectionKind::getDataRel()));
1030 /// ParseDirectiveSectionSwitch -
1031 bool AsmParser::ParseDirectiveSectionSwitch(const char *Segment,
1032 const char *Section,
1033 unsigned TAA, unsigned Align,
1034 unsigned StubSize) {
1035 if (getLexer().isNot(AsmToken::EndOfStatement))
1036 return TokError("unexpected token in section switching directive");
1039 // FIXME: Arch specific.
1040 bool isText = StringRef(Segment) == "__TEXT"; // FIXME: Hack.
1041 getStreamer().SwitchSection(Ctx.getMachOSection(Segment, Section, TAA, StubSize,
1042 isText ? SectionKind::getText()
1043 : SectionKind::getDataRel()));
1045 // Set the implicit alignment, if any.
1047 // FIXME: This isn't really what 'as' does; I think it just uses the implicit
1048 // alignment on the section (e.g., if one manually inserts bytes into the
1049 // section, then just issueing the section switch directive will not realign
1050 // the section. However, this is arguably more reasonable behavior, and there
1051 // is no good reason for someone to intentionally emit incorrectly sized
1052 // values into the implicitly aligned sections.
1054 getStreamer().EmitValueToAlignment(Align, 0, 1, 0);
1059 bool AsmParser::ParseEscapedString(std::string &Data) {
1060 assert(getLexer().is(AsmToken::String) && "Unexpected current token!");
1063 StringRef Str = getTok().getStringContents();
1064 for (unsigned i = 0, e = Str.size(); i != e; ++i) {
1065 if (Str[i] != '\\') {
1070 // Recognize escaped characters. Note that this escape semantics currently
1071 // loosely follows Darwin 'as'. Notably, it doesn't support hex escapes.
1074 return TokError("unexpected backslash at end of string");
1076 // Recognize octal sequences.
1077 if ((unsigned) (Str[i] - '0') <= 7) {
1078 // Consume up to three octal characters.
1079 unsigned Value = Str[i] - '0';
1081 if (i + 1 != e && ((unsigned) (Str[i + 1] - '0')) <= 7) {
1083 Value = Value * 8 + (Str[i] - '0');
1085 if (i + 1 != e && ((unsigned) (Str[i + 1] - '0')) <= 7) {
1087 Value = Value * 8 + (Str[i] - '0');
1092 return TokError("invalid octal escape sequence (out of range)");
1094 Data += (unsigned char) Value;
1098 // Otherwise recognize individual escapes.
1101 // Just reject invalid escape sequences for now.
1102 return TokError("invalid escape sequence (unrecognized character)");
1104 case 'b': Data += '\b'; break;
1105 case 'f': Data += '\f'; break;
1106 case 'n': Data += '\n'; break;
1107 case 'r': Data += '\r'; break;
1108 case 't': Data += '\t'; break;
1109 case '"': Data += '"'; break;
1110 case '\\': Data += '\\'; break;
1117 /// ParseDirectiveAscii:
1118 /// ::= ( .ascii | .asciz ) [ "string" ( , "string" )* ]
1119 bool AsmParser::ParseDirectiveAscii(bool ZeroTerminated) {
1120 if (getLexer().isNot(AsmToken::EndOfStatement)) {
1122 if (getLexer().isNot(AsmToken::String))
1123 return TokError("expected string in '.ascii' or '.asciz' directive");
1126 if (ParseEscapedString(Data))
1129 getStreamer().EmitBytes(Data, DEFAULT_ADDRSPACE);
1131 getStreamer().EmitBytes(StringRef("\0", 1), DEFAULT_ADDRSPACE);
1135 if (getLexer().is(AsmToken::EndOfStatement))
1138 if (getLexer().isNot(AsmToken::Comma))
1139 return TokError("unexpected token in '.ascii' or '.asciz' directive");
1148 /// ParseDirectiveValue
1149 /// ::= (.byte | .short | ... ) [ expression (, expression)* ]
1150 bool AsmParser::ParseDirectiveValue(unsigned Size) {
1151 if (getLexer().isNot(AsmToken::EndOfStatement)) {
1153 const MCExpr *Value;
1154 SMLoc ATTRIBUTE_UNUSED StartLoc = getLexer().getLoc();
1155 if (ParseExpression(Value))
1158 // Special case constant expressions to match code generator.
1159 if (const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(Value))
1160 getStreamer().EmitIntValue(MCE->getValue(), Size, DEFAULT_ADDRSPACE);
1162 getStreamer().EmitValue(Value, Size, DEFAULT_ADDRSPACE);
1164 if (getLexer().is(AsmToken::EndOfStatement))
1167 // FIXME: Improve diagnostic.
1168 if (getLexer().isNot(AsmToken::Comma))
1169 return TokError("unexpected token in directive");
1178 /// ParseDirectiveSpace
1179 /// ::= .space expression [ , expression ]
1180 bool AsmParser::ParseDirectiveSpace() {
1182 if (ParseAbsoluteExpression(NumBytes))
1185 int64_t FillExpr = 0;
1186 if (getLexer().isNot(AsmToken::EndOfStatement)) {
1187 if (getLexer().isNot(AsmToken::Comma))
1188 return TokError("unexpected token in '.space' directive");
1191 if (ParseAbsoluteExpression(FillExpr))
1194 if (getLexer().isNot(AsmToken::EndOfStatement))
1195 return TokError("unexpected token in '.space' directive");
1201 return TokError("invalid number of bytes in '.space' directive");
1203 // FIXME: Sometimes the fill expr is 'nop' if it isn't supplied, instead of 0.
1204 getStreamer().EmitFill(NumBytes, FillExpr, DEFAULT_ADDRSPACE);
1209 /// ParseDirectiveFill
1210 /// ::= .fill expression , expression , expression
1211 bool AsmParser::ParseDirectiveFill() {
1213 if (ParseAbsoluteExpression(NumValues))
1216 if (getLexer().isNot(AsmToken::Comma))
1217 return TokError("unexpected token in '.fill' directive");
1221 if (ParseAbsoluteExpression(FillSize))
1224 if (getLexer().isNot(AsmToken::Comma))
1225 return TokError("unexpected token in '.fill' directive");
1229 if (ParseAbsoluteExpression(FillExpr))
1232 if (getLexer().isNot(AsmToken::EndOfStatement))
1233 return TokError("unexpected token in '.fill' directive");
1237 if (FillSize != 1 && FillSize != 2 && FillSize != 4 && FillSize != 8)
1238 return TokError("invalid '.fill' size, expected 1, 2, 4, or 8");
1240 for (uint64_t i = 0, e = NumValues; i != e; ++i)
1241 getStreamer().EmitIntValue(FillExpr, FillSize, DEFAULT_ADDRSPACE);
1246 /// ParseDirectiveOrg
1247 /// ::= .org expression [ , expression ]
1248 bool AsmParser::ParseDirectiveOrg() {
1249 const MCExpr *Offset;
1250 if (ParseExpression(Offset))
1253 // Parse optional fill expression.
1254 int64_t FillExpr = 0;
1255 if (getLexer().isNot(AsmToken::EndOfStatement)) {
1256 if (getLexer().isNot(AsmToken::Comma))
1257 return TokError("unexpected token in '.org' directive");
1260 if (ParseAbsoluteExpression(FillExpr))
1263 if (getLexer().isNot(AsmToken::EndOfStatement))
1264 return TokError("unexpected token in '.org' directive");
1269 // FIXME: Only limited forms of relocatable expressions are accepted here, it
1270 // has to be relative to the current section.
1271 getStreamer().EmitValueToOffset(Offset, FillExpr);
1276 /// ParseDirectiveAlign
1277 /// ::= {.align, ...} expression [ , expression [ , expression ]]
1278 bool AsmParser::ParseDirectiveAlign(bool IsPow2, unsigned ValueSize) {
1279 SMLoc AlignmentLoc = getLexer().getLoc();
1281 if (ParseAbsoluteExpression(Alignment))
1285 bool HasFillExpr = false;
1286 int64_t FillExpr = 0;
1287 int64_t MaxBytesToFill = 0;
1288 if (getLexer().isNot(AsmToken::EndOfStatement)) {
1289 if (getLexer().isNot(AsmToken::Comma))
1290 return TokError("unexpected token in directive");
1293 // The fill expression can be omitted while specifying a maximum number of
1294 // alignment bytes, e.g:
1296 if (getLexer().isNot(AsmToken::Comma)) {
1298 if (ParseAbsoluteExpression(FillExpr))
1302 if (getLexer().isNot(AsmToken::EndOfStatement)) {
1303 if (getLexer().isNot(AsmToken::Comma))
1304 return TokError("unexpected token in directive");
1307 MaxBytesLoc = getLexer().getLoc();
1308 if (ParseAbsoluteExpression(MaxBytesToFill))
1311 if (getLexer().isNot(AsmToken::EndOfStatement))
1312 return TokError("unexpected token in directive");
1321 // Compute alignment in bytes.
1323 // FIXME: Diagnose overflow.
1324 if (Alignment >= 32) {
1325 Error(AlignmentLoc, "invalid alignment value");
1329 Alignment = 1ULL << Alignment;
1332 // Diagnose non-sensical max bytes to align.
1333 if (MaxBytesLoc.isValid()) {
1334 if (MaxBytesToFill < 1) {
1335 Error(MaxBytesLoc, "alignment directive can never be satisfied in this "
1336 "many bytes, ignoring maximum bytes expression");
1340 if (MaxBytesToFill >= Alignment) {
1341 Warning(MaxBytesLoc, "maximum bytes expression exceeds alignment and "
1347 // Check whether we should use optimal code alignment for this .align
1350 // FIXME: This should be using a target hook.
1351 bool UseCodeAlign = false;
1352 if (const MCSectionMachO *S = dyn_cast<MCSectionMachO>(
1353 getStreamer().getCurrentSection()))
1354 UseCodeAlign = S->hasAttribute(MCSectionMachO::S_ATTR_PURE_INSTRUCTIONS);
1355 if ((!HasFillExpr || Lexer.getMAI().getTextAlignFillValue() == FillExpr) &&
1356 ValueSize == 1 && UseCodeAlign) {
1357 getStreamer().EmitCodeAlignment(Alignment, MaxBytesToFill);
1359 // FIXME: Target specific behavior about how the "extra" bytes are filled.
1360 getStreamer().EmitValueToAlignment(Alignment, FillExpr, ValueSize, MaxBytesToFill);
1366 /// ParseDirectiveSymbolAttribute
1367 /// ::= { ".globl", ".weak", ... } [ identifier ( , identifier )* ]
1368 bool AsmParser::ParseDirectiveSymbolAttribute(MCSymbolAttr Attr) {
1369 if (getLexer().isNot(AsmToken::EndOfStatement)) {
1373 if (ParseIdentifier(Name))
1374 return TokError("expected identifier in directive");
1376 MCSymbol *Sym = CreateSymbol(Name);
1378 getStreamer().EmitSymbolAttribute(Sym, Attr);
1380 if (getLexer().is(AsmToken::EndOfStatement))
1383 if (getLexer().isNot(AsmToken::Comma))
1384 return TokError("unexpected token in directive");
1393 /// ParseDirectiveELFType
1394 /// ::= .type identifier , @attribute
1395 bool AsmParser::ParseDirectiveELFType() {
1397 if (ParseIdentifier(Name))
1398 return TokError("expected identifier in directive");
1400 // Handle the identifier as the key symbol.
1401 MCSymbol *Sym = CreateSymbol(Name);
1403 if (getLexer().isNot(AsmToken::Comma))
1404 return TokError("unexpected token in '.type' directive");
1407 if (getLexer().isNot(AsmToken::At))
1408 return TokError("expected '@' before type");
1414 TypeLoc = getLexer().getLoc();
1415 if (ParseIdentifier(Type))
1416 return TokError("expected symbol type in directive");
1418 MCSymbolAttr Attr = StringSwitch<MCSymbolAttr>(Type)
1419 .Case("function", MCSA_ELF_TypeFunction)
1420 .Case("object", MCSA_ELF_TypeObject)
1421 .Case("tls_object", MCSA_ELF_TypeTLS)
1422 .Case("common", MCSA_ELF_TypeCommon)
1423 .Case("notype", MCSA_ELF_TypeNoType)
1424 .Default(MCSA_Invalid);
1426 if (Attr == MCSA_Invalid)
1427 return Error(TypeLoc, "unsupported attribute in '.type' directive");
1429 if (getLexer().isNot(AsmToken::EndOfStatement))
1430 return TokError("unexpected token in '.type' directive");
1434 getStreamer().EmitSymbolAttribute(Sym, Attr);
1439 /// ParseDirectiveDesc
1440 /// ::= .desc identifier , expression
1441 bool DarwinAsmParser::ParseDirectiveDesc(StringRef, SMLoc) {
1443 if (getParser().ParseIdentifier(Name))
1444 return TokError("expected identifier in directive");
1446 // Handle the identifier as the key symbol.
1447 MCSymbol *Sym = getContext().GetOrCreateSymbol(Name);
1449 if (getLexer().isNot(AsmToken::Comma))
1450 return TokError("unexpected token in '.desc' directive");
1454 if (getParser().ParseAbsoluteExpression(DescValue))
1457 if (getLexer().isNot(AsmToken::EndOfStatement))
1458 return TokError("unexpected token in '.desc' directive");
1462 // Set the n_desc field of this Symbol to this DescValue
1463 getStreamer().EmitSymbolDesc(Sym, DescValue);
1468 /// ParseDirectiveComm
1469 /// ::= ( .comm | .lcomm ) identifier , size_expression [ , align_expression ]
1470 bool AsmParser::ParseDirectiveComm(bool IsLocal) {
1471 SMLoc IDLoc = getLexer().getLoc();
1473 if (ParseIdentifier(Name))
1474 return TokError("expected identifier in directive");
1476 // Handle the identifier as the key symbol.
1477 MCSymbol *Sym = CreateSymbol(Name);
1479 if (getLexer().isNot(AsmToken::Comma))
1480 return TokError("unexpected token in directive");
1484 SMLoc SizeLoc = getLexer().getLoc();
1485 if (ParseAbsoluteExpression(Size))
1488 int64_t Pow2Alignment = 0;
1489 SMLoc Pow2AlignmentLoc;
1490 if (getLexer().is(AsmToken::Comma)) {
1492 Pow2AlignmentLoc = getLexer().getLoc();
1493 if (ParseAbsoluteExpression(Pow2Alignment))
1496 // If this target takes alignments in bytes (not log) validate and convert.
1497 if (Lexer.getMAI().getAlignmentIsInBytes()) {
1498 if (!isPowerOf2_64(Pow2Alignment))
1499 return Error(Pow2AlignmentLoc, "alignment must be a power of 2");
1500 Pow2Alignment = Log2_64(Pow2Alignment);
1504 if (getLexer().isNot(AsmToken::EndOfStatement))
1505 return TokError("unexpected token in '.comm' or '.lcomm' directive");
1509 // NOTE: a size of zero for a .comm should create a undefined symbol
1510 // but a size of .lcomm creates a bss symbol of size zero.
1512 return Error(SizeLoc, "invalid '.comm' or '.lcomm' directive size, can't "
1513 "be less than zero");
1515 // NOTE: The alignment in the directive is a power of 2 value, the assembler
1516 // may internally end up wanting an alignment in bytes.
1517 // FIXME: Diagnose overflow.
1518 if (Pow2Alignment < 0)
1519 return Error(Pow2AlignmentLoc, "invalid '.comm' or '.lcomm' directive "
1520 "alignment, can't be less than zero");
1522 if (!Sym->isUndefined())
1523 return Error(IDLoc, "invalid symbol redefinition");
1525 // '.lcomm' is equivalent to '.zerofill'.
1526 // Create the Symbol as a common or local common with Size and Pow2Alignment
1528 getStreamer().EmitZerofill(Ctx.getMachOSection(
1529 "__DATA", "__bss", MCSectionMachO::S_ZEROFILL,
1530 0, SectionKind::getBSS()),
1531 Sym, Size, 1 << Pow2Alignment);
1535 getStreamer().EmitCommonSymbol(Sym, Size, 1 << Pow2Alignment);
1539 /// ParseDirectiveZerofill
1540 /// ::= .zerofill segname , sectname [, identifier , size_expression [
1541 /// , align_expression ]]
1542 bool DarwinAsmParser::ParseDirectiveZerofill(StringRef, SMLoc) {
1544 if (getParser().ParseIdentifier(Segment))
1545 return TokError("expected segment name after '.zerofill' directive");
1547 if (getLexer().isNot(AsmToken::Comma))
1548 return TokError("unexpected token in directive");
1552 if (getParser().ParseIdentifier(Section))
1553 return TokError("expected section name after comma in '.zerofill' "
1556 // If this is the end of the line all that was wanted was to create the
1557 // the section but with no symbol.
1558 if (getLexer().is(AsmToken::EndOfStatement)) {
1559 // Create the zerofill section but no symbol
1560 getStreamer().EmitZerofill(getContext().getMachOSection(
1561 Segment, Section, MCSectionMachO::S_ZEROFILL,
1562 0, SectionKind::getBSS()));
1566 if (getLexer().isNot(AsmToken::Comma))
1567 return TokError("unexpected token in directive");
1570 SMLoc IDLoc = getLexer().getLoc();
1572 if (getParser().ParseIdentifier(IDStr))
1573 return TokError("expected identifier in directive");
1575 // handle the identifier as the key symbol.
1576 MCSymbol *Sym = getContext().GetOrCreateSymbol(IDStr);
1578 if (getLexer().isNot(AsmToken::Comma))
1579 return TokError("unexpected token in directive");
1583 SMLoc SizeLoc = getLexer().getLoc();
1584 if (getParser().ParseAbsoluteExpression(Size))
1587 int64_t Pow2Alignment = 0;
1588 SMLoc Pow2AlignmentLoc;
1589 if (getLexer().is(AsmToken::Comma)) {
1591 Pow2AlignmentLoc = getLexer().getLoc();
1592 if (getParser().ParseAbsoluteExpression(Pow2Alignment))
1596 if (getLexer().isNot(AsmToken::EndOfStatement))
1597 return TokError("unexpected token in '.zerofill' directive");
1602 return Error(SizeLoc, "invalid '.zerofill' directive size, can't be less "
1605 // NOTE: The alignment in the directive is a power of 2 value, the assembler
1606 // may internally end up wanting an alignment in bytes.
1607 // FIXME: Diagnose overflow.
1608 if (Pow2Alignment < 0)
1609 return Error(Pow2AlignmentLoc, "invalid '.zerofill' directive alignment, "
1610 "can't be less than zero");
1612 if (!Sym->isUndefined())
1613 return Error(IDLoc, "invalid symbol redefinition");
1615 // Create the zerofill Symbol with Size and Pow2Alignment
1617 // FIXME: Arch specific.
1618 getStreamer().EmitZerofill(getContext().getMachOSection(
1619 Segment, Section, MCSectionMachO::S_ZEROFILL,
1620 0, SectionKind::getBSS()),
1621 Sym, Size, 1 << Pow2Alignment);
1626 /// ParseDirectiveTBSS
1627 /// ::= .tbss identifier, size, align
1628 bool DarwinAsmParser::ParseDirectiveTBSS(StringRef, SMLoc) {
1629 SMLoc IDLoc = getLexer().getLoc();
1631 if (getParser().ParseIdentifier(Name))
1632 return TokError("expected identifier in directive");
1634 // Handle the identifier as the key symbol.
1635 MCSymbol *Sym = getContext().GetOrCreateSymbol(Name);
1637 if (getLexer().isNot(AsmToken::Comma))
1638 return TokError("unexpected token in directive");
1642 SMLoc SizeLoc = getLexer().getLoc();
1643 if (getParser().ParseAbsoluteExpression(Size))
1646 int64_t Pow2Alignment = 0;
1647 SMLoc Pow2AlignmentLoc;
1648 if (getLexer().is(AsmToken::Comma)) {
1650 Pow2AlignmentLoc = getLexer().getLoc();
1651 if (getParser().ParseAbsoluteExpression(Pow2Alignment))
1655 if (getLexer().isNot(AsmToken::EndOfStatement))
1656 return TokError("unexpected token in '.tbss' directive");
1661 return Error(SizeLoc, "invalid '.tbss' directive size, can't be less than"
1664 // FIXME: Diagnose overflow.
1665 if (Pow2Alignment < 0)
1666 return Error(Pow2AlignmentLoc, "invalid '.tbss' alignment, can't be less"
1669 if (!Sym->isUndefined())
1670 return Error(IDLoc, "invalid symbol redefinition");
1672 getStreamer().EmitTBSSSymbol(getContext().getMachOSection(
1673 "__DATA", "__thread_bss",
1674 MCSectionMachO::S_THREAD_LOCAL_ZEROFILL,
1675 0, SectionKind::getThreadBSS()),
1676 Sym, Size, 1 << Pow2Alignment);
1681 /// ParseDirectiveSubsectionsViaSymbols
1682 /// ::= .subsections_via_symbols
1683 bool DarwinAsmParser::ParseDirectiveSubsectionsViaSymbols(StringRef, SMLoc) {
1684 if (getLexer().isNot(AsmToken::EndOfStatement))
1685 return TokError("unexpected token in '.subsections_via_symbols' directive");
1689 getStreamer().EmitAssemblerFlag(MCAF_SubsectionsViaSymbols);
1694 /// ParseDirectiveAbort
1695 /// ::= .abort [ "abort_string" ]
1696 bool AsmParser::ParseDirectiveAbort() {
1697 // FIXME: Use loc from directive.
1698 SMLoc Loc = getLexer().getLoc();
1701 if (getLexer().isNot(AsmToken::EndOfStatement)) {
1702 if (getLexer().isNot(AsmToken::String))
1703 return TokError("expected string in '.abort' directive");
1705 Str = getTok().getString();
1710 if (getLexer().isNot(AsmToken::EndOfStatement))
1711 return TokError("unexpected token in '.abort' directive");
1715 // FIXME: Handle here.
1717 Error(Loc, ".abort detected. Assembly stopping.");
1719 Error(Loc, ".abort '" + Str + "' detected. Assembly stopping.");
1724 /// ParseDirectiveLsym
1725 /// ::= .lsym identifier , expression
1726 bool DarwinAsmParser::ParseDirectiveLsym(StringRef, SMLoc) {
1728 if (getParser().ParseIdentifier(Name))
1729 return TokError("expected identifier in directive");
1731 // Handle the identifier as the key symbol.
1732 MCSymbol *Sym = getContext().GetOrCreateSymbol(Name);
1734 if (getLexer().isNot(AsmToken::Comma))
1735 return TokError("unexpected token in '.lsym' directive");
1738 const MCExpr *Value;
1739 if (getParser().ParseExpression(Value))
1742 if (getLexer().isNot(AsmToken::EndOfStatement))
1743 return TokError("unexpected token in '.lsym' directive");
1747 // We don't currently support this directive.
1749 // FIXME: Diagnostic location!
1751 return TokError("directive '.lsym' is unsupported");
1754 /// ParseDirectiveInclude
1755 /// ::= .include "filename"
1756 bool AsmParser::ParseDirectiveInclude() {
1757 if (getLexer().isNot(AsmToken::String))
1758 return TokError("expected string in '.include' directive");
1760 std::string Filename = getTok().getString();
1761 SMLoc IncludeLoc = getLexer().getLoc();
1764 if (getLexer().isNot(AsmToken::EndOfStatement))
1765 return TokError("unexpected token in '.include' directive");
1767 // Strip the quotes.
1768 Filename = Filename.substr(1, Filename.size()-2);
1770 // Attempt to switch the lexer to the included file before consuming the end
1771 // of statement to avoid losing it when we switch.
1772 if (EnterIncludeFile(Filename)) {
1773 PrintMessage(IncludeLoc,
1774 "Could not find include file '" + Filename + "'",
1782 /// ParseDirectiveDumpOrLoad
1783 /// ::= ( .dump | .load ) "filename"
1784 bool DarwinAsmParser::ParseDirectiveDumpOrLoad(StringRef Directive,
1786 bool IsDump = Directive == ".dump";
1787 if (getLexer().isNot(AsmToken::String))
1788 return TokError("expected string in '.dump' or '.load' directive");
1792 if (getLexer().isNot(AsmToken::EndOfStatement))
1793 return TokError("unexpected token in '.dump' or '.load' directive");
1797 // FIXME: If/when .dump and .load are implemented they will be done in the
1798 // the assembly parser and not have any need for an MCStreamer API.
1800 Warning(IDLoc, "ignoring directive .dump for now");
1802 Warning(IDLoc, "ignoring directive .load for now");
1807 /// ParseDirectiveSecureLogUnique
1808 /// ::= .secure_log_unique "log message"
1809 bool DarwinAsmParser::ParseDirectiveSecureLogUnique(StringRef, SMLoc IDLoc) {
1810 std::string LogMessage;
1812 if (getLexer().isNot(AsmToken::String))
1815 LogMessage = getTok().getString();
1819 if (getLexer().isNot(AsmToken::EndOfStatement))
1820 return TokError("unexpected token in '.secure_log_unique' directive");
1822 if (getContext().getSecureLogUsed() != false)
1823 return Error(IDLoc, ".secure_log_unique specified multiple times");
1825 char *SecureLogFile = getContext().getSecureLogFile();
1826 if (SecureLogFile == NULL)
1827 return Error(IDLoc, ".secure_log_unique used but AS_SECURE_LOG_FILE "
1828 "environment variable unset.");
1830 raw_ostream *OS = getContext().getSecureLog();
1833 OS = new raw_fd_ostream(SecureLogFile, Err, raw_fd_ostream::F_Append);
1836 return Error(IDLoc, Twine("can't open secure log file: ") +
1837 SecureLogFile + " (" + Err + ")");
1839 getContext().setSecureLog(OS);
1842 int CurBuf = getSourceManager().FindBufferContainingLoc(IDLoc);
1843 *OS << getSourceManager().getBufferInfo(CurBuf).Buffer->getBufferIdentifier()
1844 << ":" << getSourceManager().FindLineNumber(IDLoc, CurBuf) << ":"
1845 << LogMessage + "\n";
1847 getContext().setSecureLogUsed(true);
1852 /// ParseDirectiveSecureLogReset
1853 /// ::= .secure_log_reset
1854 bool DarwinAsmParser::ParseDirectiveSecureLogReset(StringRef, SMLoc IDLoc) {
1855 if (getLexer().isNot(AsmToken::EndOfStatement))
1856 return TokError("unexpected token in '.secure_log_reset' directive");
1860 getContext().setSecureLogUsed(false);
1865 /// ParseDirectiveIf
1866 /// ::= .if expression
1867 bool AsmParser::ParseDirectiveIf(SMLoc DirectiveLoc) {
1868 TheCondStack.push_back(TheCondState);
1869 TheCondState.TheCond = AsmCond::IfCond;
1870 if(TheCondState.Ignore) {
1871 EatToEndOfStatement();
1875 if (ParseAbsoluteExpression(ExprValue))
1878 if (getLexer().isNot(AsmToken::EndOfStatement))
1879 return TokError("unexpected token in '.if' directive");
1883 TheCondState.CondMet = ExprValue;
1884 TheCondState.Ignore = !TheCondState.CondMet;
1890 /// ParseDirectiveElseIf
1891 /// ::= .elseif expression
1892 bool AsmParser::ParseDirectiveElseIf(SMLoc DirectiveLoc) {
1893 if (TheCondState.TheCond != AsmCond::IfCond &&
1894 TheCondState.TheCond != AsmCond::ElseIfCond)
1895 Error(DirectiveLoc, "Encountered a .elseif that doesn't follow a .if or "
1897 TheCondState.TheCond = AsmCond::ElseIfCond;
1899 bool LastIgnoreState = false;
1900 if (!TheCondStack.empty())
1901 LastIgnoreState = TheCondStack.back().Ignore;
1902 if (LastIgnoreState || TheCondState.CondMet) {
1903 TheCondState.Ignore = true;
1904 EatToEndOfStatement();
1908 if (ParseAbsoluteExpression(ExprValue))
1911 if (getLexer().isNot(AsmToken::EndOfStatement))
1912 return TokError("unexpected token in '.elseif' directive");
1915 TheCondState.CondMet = ExprValue;
1916 TheCondState.Ignore = !TheCondState.CondMet;
1922 /// ParseDirectiveElse
1924 bool AsmParser::ParseDirectiveElse(SMLoc DirectiveLoc) {
1925 if (getLexer().isNot(AsmToken::EndOfStatement))
1926 return TokError("unexpected token in '.else' directive");
1930 if (TheCondState.TheCond != AsmCond::IfCond &&
1931 TheCondState.TheCond != AsmCond::ElseIfCond)
1932 Error(DirectiveLoc, "Encountered a .else that doesn't follow a .if or an "
1934 TheCondState.TheCond = AsmCond::ElseCond;
1935 bool LastIgnoreState = false;
1936 if (!TheCondStack.empty())
1937 LastIgnoreState = TheCondStack.back().Ignore;
1938 if (LastIgnoreState || TheCondState.CondMet)
1939 TheCondState.Ignore = true;
1941 TheCondState.Ignore = false;
1946 /// ParseDirectiveEndIf
1948 bool AsmParser::ParseDirectiveEndIf(SMLoc DirectiveLoc) {
1949 if (getLexer().isNot(AsmToken::EndOfStatement))
1950 return TokError("unexpected token in '.endif' directive");
1954 if ((TheCondState.TheCond == AsmCond::NoCond) ||
1955 TheCondStack.empty())
1956 Error(DirectiveLoc, "Encountered a .endif that doesn't follow a .if or "
1958 if (!TheCondStack.empty()) {
1959 TheCondState = TheCondStack.back();
1960 TheCondStack.pop_back();
1966 /// ParseDirectiveFile
1967 /// ::= .file [number] string
1968 bool GenericAsmParser::ParseDirectiveFile(StringRef, SMLoc DirectiveLoc) {
1969 // FIXME: I'm not sure what this is.
1970 int64_t FileNumber = -1;
1971 if (getLexer().is(AsmToken::Integer)) {
1972 FileNumber = getTok().getIntVal();
1976 return TokError("file number less than one");
1979 if (getLexer().isNot(AsmToken::String))
1980 return TokError("unexpected token in '.file' directive");
1982 StringRef Filename = getTok().getString();
1983 Filename = Filename.substr(1, Filename.size()-2);
1986 if (getLexer().isNot(AsmToken::EndOfStatement))
1987 return TokError("unexpected token in '.file' directive");
1989 if (FileNumber == -1)
1990 getStreamer().EmitFileDirective(Filename);
1992 getStreamer().EmitDwarfFileDirective(FileNumber, Filename);
1997 /// ParseDirectiveLine
1998 /// ::= .line [number]
1999 bool GenericAsmParser::ParseDirectiveLine(StringRef, SMLoc DirectiveLoc) {
2000 if (getLexer().isNot(AsmToken::EndOfStatement)) {
2001 if (getLexer().isNot(AsmToken::Integer))
2002 return TokError("unexpected token in '.line' directive");
2004 int64_t LineNumber = getTok().getIntVal();
2008 // FIXME: Do something with the .line.
2011 if (getLexer().isNot(AsmToken::EndOfStatement))
2012 return TokError("unexpected token in '.line' directive");
2018 /// ParseDirectiveLoc
2019 /// ::= .loc number [number [number]]
2020 bool GenericAsmParser::ParseDirectiveLoc(StringRef, SMLoc DirectiveLoc) {
2021 if (getLexer().isNot(AsmToken::Integer))
2022 return TokError("unexpected token in '.loc' directive");
2024 // FIXME: What are these fields?
2025 int64_t FileNumber = getTok().getIntVal();
2027 // FIXME: Validate file.
2030 if (getLexer().isNot(AsmToken::EndOfStatement)) {
2031 if (getLexer().isNot(AsmToken::Integer))
2032 return TokError("unexpected token in '.loc' directive");
2034 int64_t Param2 = getTok().getIntVal();
2038 if (getLexer().isNot(AsmToken::EndOfStatement)) {
2039 if (getLexer().isNot(AsmToken::Integer))
2040 return TokError("unexpected token in '.loc' directive");
2042 int64_t Param3 = getTok().getIntVal();
2046 // FIXME: Do something with the .loc.
2050 if (getLexer().isNot(AsmToken::EndOfStatement))
2051 return TokError("unexpected token in '.file' directive");