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, ".lsym", MCAsmParser::DirectiveHandler(
70 &DarwinAsmParser::ParseDirectiveLsym));
71 Parser.AddDirectiveHandler(this, ".subsections_via_symbols",
72 MCAsmParser::DirectiveHandler(
73 &DarwinAsmParser::ParseDirectiveSubsectionsViaSymbols));
74 Parser.AddDirectiveHandler(this, ".dump", MCAsmParser::DirectiveHandler(
75 &DarwinAsmParser::ParseDirectiveDumpOrLoad));
76 Parser.AddDirectiveHandler(this, ".load", MCAsmParser::DirectiveHandler(
77 &DarwinAsmParser::ParseDirectiveDumpOrLoad));
78 Parser.AddDirectiveHandler(this, ".secure_log_unique",
79 MCAsmParser::DirectiveHandler(
80 &DarwinAsmParser::ParseDirectiveSecureLogUnique));
81 Parser.AddDirectiveHandler(this, ".secure_log_reset",
82 MCAsmParser::DirectiveHandler(
83 &DarwinAsmParser::ParseDirectiveSecureLogReset));
86 bool ParseDirectiveDumpOrLoad(StringRef, SMLoc);
87 bool ParseDirectiveLsym(StringRef, SMLoc);
88 bool ParseDirectiveSecureLogReset(StringRef, SMLoc);
89 bool ParseDirectiveSecureLogUnique(StringRef, SMLoc);
90 bool ParseDirectiveSubsectionsViaSymbols(StringRef, SMLoc);
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 = new DarwinAsmParser;
113 PlatformParser->Initialize(*this);
117 AsmParser::~AsmParser() {
118 delete PlatformParser;
119 delete GenericParser;
122 void AsmParser::setTargetParser(TargetAsmParser &P) {
123 assert(!TargetParser && "Target parser is already initialized!");
125 TargetParser->Initialize(*this);
128 void AsmParser::Warning(SMLoc L, const Twine &Msg) {
129 PrintMessage(L, Msg.str(), "warning");
132 bool AsmParser::Error(SMLoc L, const Twine &Msg) {
133 PrintMessage(L, Msg.str(), "error");
137 void AsmParser::PrintMessage(SMLoc Loc, const std::string &Msg,
138 const char *Type) const {
139 SrcMgr.PrintMessage(Loc, Msg, Type);
142 bool AsmParser::EnterIncludeFile(const std::string &Filename) {
143 int NewBuf = SrcMgr.AddIncludeFile(Filename, Lexer.getLoc());
149 Lexer.setBuffer(SrcMgr.getMemoryBuffer(CurBuffer));
154 const AsmToken &AsmParser::Lex() {
155 const AsmToken *tok = &Lexer.Lex();
157 if (tok->is(AsmToken::Eof)) {
158 // If this is the end of an included file, pop the parent file off the
160 SMLoc ParentIncludeLoc = SrcMgr.getParentIncludeLoc(CurBuffer);
161 if (ParentIncludeLoc != SMLoc()) {
162 CurBuffer = SrcMgr.FindBufferContainingLoc(ParentIncludeLoc);
163 Lexer.setBuffer(SrcMgr.getMemoryBuffer(CurBuffer),
164 ParentIncludeLoc.getPointer());
169 if (tok->is(AsmToken::Error))
170 PrintMessage(Lexer.getErrLoc(), Lexer.getErr(), "error");
175 bool AsmParser::Run(bool NoInitialTextSection, bool NoFinalize) {
176 // Create the initial section, if requested.
178 // FIXME: Target hook & command line option for initial section.
179 if (!NoInitialTextSection)
180 Out.SwitchSection(Ctx.getMachOSection("__TEXT", "__text",
181 MCSectionMachO::S_ATTR_PURE_INSTRUCTIONS,
182 0, SectionKind::getText()));
187 bool HadError = false;
189 AsmCond StartingCondState = TheCondState;
191 // While we have input, parse each statement.
192 while (Lexer.isNot(AsmToken::Eof)) {
193 if (!ParseStatement()) continue;
195 // We had an error, remember it and recover by skipping to the next line.
197 EatToEndOfStatement();
200 if (TheCondState.TheCond != StartingCondState.TheCond ||
201 TheCondState.Ignore != StartingCondState.Ignore)
202 return TokError("unmatched .ifs or .elses");
204 // Finalize the output stream if there are no errors and if the client wants
206 if (!HadError && !NoFinalize)
212 /// EatToEndOfStatement - Throw away the rest of the line for testing purposes.
213 void AsmParser::EatToEndOfStatement() {
214 while (Lexer.isNot(AsmToken::EndOfStatement) &&
215 Lexer.isNot(AsmToken::Eof))
219 if (Lexer.is(AsmToken::EndOfStatement))
224 /// ParseParenExpr - Parse a paren expression and return it.
225 /// NOTE: This assumes the leading '(' has already been consumed.
227 /// parenexpr ::= expr)
229 bool AsmParser::ParseParenExpr(const MCExpr *&Res, SMLoc &EndLoc) {
230 if (ParseExpression(Res)) return true;
231 if (Lexer.isNot(AsmToken::RParen))
232 return TokError("expected ')' in parentheses expression");
233 EndLoc = Lexer.getLoc();
238 MCSymbol *AsmParser::CreateSymbol(StringRef Name) {
239 // FIXME: Inline into callers.
240 return Ctx.GetOrCreateSymbol(Name);
243 /// ParsePrimaryExpr - Parse a primary expression and return it.
244 /// primaryexpr ::= (parenexpr
245 /// primaryexpr ::= symbol
246 /// primaryexpr ::= number
247 /// primaryexpr ::= '.'
248 /// primaryexpr ::= ~,+,- primaryexpr
249 bool AsmParser::ParsePrimaryExpr(const MCExpr *&Res, SMLoc &EndLoc) {
250 switch (Lexer.getKind()) {
252 return TokError("unknown token in expression");
253 case AsmToken::Exclaim:
254 Lex(); // Eat the operator.
255 if (ParsePrimaryExpr(Res, EndLoc))
257 Res = MCUnaryExpr::CreateLNot(Res, getContext());
259 case AsmToken::String:
260 case AsmToken::Identifier: {
261 // This is a symbol reference.
262 std::pair<StringRef, StringRef> Split = getTok().getIdentifier().split('@');
263 MCSymbol *Sym = CreateSymbol(Split.first);
265 // Mark the symbol as used in an expression.
266 Sym->setUsedInExpr(true);
268 // Lookup the symbol variant if used.
269 MCSymbolRefExpr::VariantKind Variant = MCSymbolRefExpr::VK_None;
270 if (Split.first.size() != getTok().getIdentifier().size())
271 Variant = MCSymbolRefExpr::getVariantKindForName(Split.second);
273 EndLoc = Lexer.getLoc();
274 Lex(); // Eat identifier.
276 // If this is an absolute variable reference, substitute it now to preserve
277 // semantics in the face of reassignment.
278 if (Sym->isVariable() && isa<MCConstantExpr>(Sym->getVariableValue())) {
280 return Error(EndLoc, "unexpected modified on variable reference");
282 Res = Sym->getVariableValue();
286 // Otherwise create a symbol ref.
287 Res = MCSymbolRefExpr::Create(Sym, Variant, getContext());
290 case AsmToken::Integer: {
291 SMLoc Loc = getTok().getLoc();
292 int64_t IntVal = getTok().getIntVal();
293 Res = MCConstantExpr::Create(IntVal, getContext());
294 EndLoc = Lexer.getLoc();
296 // Look for 'b' or 'f' following an Integer as a directional label
297 if (Lexer.getKind() == AsmToken::Identifier) {
298 StringRef IDVal = getTok().getString();
299 if (IDVal == "f" || IDVal == "b"){
300 MCSymbol *Sym = Ctx.GetDirectionalLocalSymbol(IntVal,
301 IDVal == "f" ? 1 : 0);
302 Res = MCSymbolRefExpr::Create(Sym, MCSymbolRefExpr::VK_None,
304 if(IDVal == "b" && Sym->isUndefined())
305 return Error(Loc, "invalid reference to undefined symbol");
306 EndLoc = Lexer.getLoc();
307 Lex(); // Eat identifier.
312 case AsmToken::Dot: {
313 // This is a '.' reference, which references the current PC. Emit a
314 // temporary label to the streamer and refer to it.
315 MCSymbol *Sym = Ctx.CreateTempSymbol();
317 Res = MCSymbolRefExpr::Create(Sym, MCSymbolRefExpr::VK_None, getContext());
318 EndLoc = Lexer.getLoc();
319 Lex(); // Eat identifier.
323 case AsmToken::LParen:
324 Lex(); // Eat the '('.
325 return ParseParenExpr(Res, EndLoc);
326 case AsmToken::Minus:
327 Lex(); // Eat the operator.
328 if (ParsePrimaryExpr(Res, EndLoc))
330 Res = MCUnaryExpr::CreateMinus(Res, getContext());
333 Lex(); // Eat the operator.
334 if (ParsePrimaryExpr(Res, EndLoc))
336 Res = MCUnaryExpr::CreatePlus(Res, getContext());
338 case AsmToken::Tilde:
339 Lex(); // Eat the operator.
340 if (ParsePrimaryExpr(Res, EndLoc))
342 Res = MCUnaryExpr::CreateNot(Res, getContext());
347 bool AsmParser::ParseExpression(const MCExpr *&Res) {
349 return ParseExpression(Res, EndLoc);
352 /// ParseExpression - Parse an expression and return it.
354 /// expr ::= expr +,- expr -> lowest.
355 /// expr ::= expr |,^,&,! expr -> middle.
356 /// expr ::= expr *,/,%,<<,>> expr -> highest.
357 /// expr ::= primaryexpr
359 bool AsmParser::ParseExpression(const MCExpr *&Res, SMLoc &EndLoc) {
360 // Parse the expression.
362 if (ParsePrimaryExpr(Res, EndLoc) || ParseBinOpRHS(1, Res, EndLoc))
365 // Try to constant fold it up front, if possible.
367 if (Res->EvaluateAsAbsolute(Value))
368 Res = MCConstantExpr::Create(Value, getContext());
373 bool AsmParser::ParseParenExpression(const MCExpr *&Res, SMLoc &EndLoc) {
375 return ParseParenExpr(Res, EndLoc) ||
376 ParseBinOpRHS(1, Res, EndLoc);
379 bool AsmParser::ParseAbsoluteExpression(int64_t &Res) {
382 SMLoc StartLoc = Lexer.getLoc();
383 if (ParseExpression(Expr))
386 if (!Expr->EvaluateAsAbsolute(Res))
387 return Error(StartLoc, "expected absolute expression");
392 static unsigned getBinOpPrecedence(AsmToken::TokenKind K,
393 MCBinaryExpr::Opcode &Kind) {
396 return 0; // not a binop.
398 // Lowest Precedence: &&, ||
399 case AsmToken::AmpAmp:
400 Kind = MCBinaryExpr::LAnd;
402 case AsmToken::PipePipe:
403 Kind = MCBinaryExpr::LOr;
406 // Low Precedence: +, -, ==, !=, <>, <, <=, >, >=
408 Kind = MCBinaryExpr::Add;
410 case AsmToken::Minus:
411 Kind = MCBinaryExpr::Sub;
413 case AsmToken::EqualEqual:
414 Kind = MCBinaryExpr::EQ;
416 case AsmToken::ExclaimEqual:
417 case AsmToken::LessGreater:
418 Kind = MCBinaryExpr::NE;
421 Kind = MCBinaryExpr::LT;
423 case AsmToken::LessEqual:
424 Kind = MCBinaryExpr::LTE;
426 case AsmToken::Greater:
427 Kind = MCBinaryExpr::GT;
429 case AsmToken::GreaterEqual:
430 Kind = MCBinaryExpr::GTE;
433 // Intermediate Precedence: |, &, ^
435 // FIXME: gas seems to support '!' as an infix operator?
437 Kind = MCBinaryExpr::Or;
439 case AsmToken::Caret:
440 Kind = MCBinaryExpr::Xor;
443 Kind = MCBinaryExpr::And;
446 // Highest Precedence: *, /, %, <<, >>
448 Kind = MCBinaryExpr::Mul;
450 case AsmToken::Slash:
451 Kind = MCBinaryExpr::Div;
453 case AsmToken::Percent:
454 Kind = MCBinaryExpr::Mod;
456 case AsmToken::LessLess:
457 Kind = MCBinaryExpr::Shl;
459 case AsmToken::GreaterGreater:
460 Kind = MCBinaryExpr::Shr;
466 /// ParseBinOpRHS - Parse all binary operators with precedence >= 'Precedence'.
467 /// Res contains the LHS of the expression on input.
468 bool AsmParser::ParseBinOpRHS(unsigned Precedence, const MCExpr *&Res,
471 MCBinaryExpr::Opcode Kind = MCBinaryExpr::Add;
472 unsigned TokPrec = getBinOpPrecedence(Lexer.getKind(), Kind);
474 // If the next token is lower precedence than we are allowed to eat, return
475 // successfully with what we ate already.
476 if (TokPrec < Precedence)
481 // Eat the next primary expression.
483 if (ParsePrimaryExpr(RHS, EndLoc)) return true;
485 // If BinOp binds less tightly with RHS than the operator after RHS, let
486 // the pending operator take RHS as its LHS.
487 MCBinaryExpr::Opcode Dummy;
488 unsigned NextTokPrec = getBinOpPrecedence(Lexer.getKind(), Dummy);
489 if (TokPrec < NextTokPrec) {
490 if (ParseBinOpRHS(Precedence+1, RHS, EndLoc)) return true;
493 // Merge LHS and RHS according to operator.
494 Res = MCBinaryExpr::Create(Kind, Res, RHS, getContext());
502 /// ::= EndOfStatement
503 /// ::= Label* Directive ...Operands... EndOfStatement
504 /// ::= Label* Identifier OperandList* EndOfStatement
505 bool AsmParser::ParseStatement() {
506 if (Lexer.is(AsmToken::EndOfStatement)) {
512 // Statements always start with an identifier.
513 AsmToken ID = getTok();
514 SMLoc IDLoc = ID.getLoc();
516 int64_t LocalLabelVal = -1;
517 // GUESS allow an integer followed by a ':' as a directional local label
518 if (Lexer.is(AsmToken::Integer)) {
519 LocalLabelVal = getTok().getIntVal();
520 if (LocalLabelVal < 0) {
521 if (!TheCondState.Ignore)
522 return TokError("unexpected token at start of statement");
526 IDVal = getTok().getString();
527 Lex(); // Consume the integer token to be used as an identifier token.
528 if (Lexer.getKind() != AsmToken::Colon) {
529 if (!TheCondState.Ignore)
530 return TokError("unexpected token at start of statement");
534 else if (ParseIdentifier(IDVal)) {
535 if (!TheCondState.Ignore)
536 return TokError("unexpected token at start of statement");
540 // Handle conditional assembly here before checking for skipping. We
541 // have to do this so that .endif isn't skipped in a ".if 0" block for
544 return ParseDirectiveIf(IDLoc);
545 if (IDVal == ".elseif")
546 return ParseDirectiveElseIf(IDLoc);
547 if (IDVal == ".else")
548 return ParseDirectiveElse(IDLoc);
549 if (IDVal == ".endif")
550 return ParseDirectiveEndIf(IDLoc);
552 // If we are in a ".if 0" block, ignore this statement.
553 if (TheCondState.Ignore) {
554 EatToEndOfStatement();
558 // FIXME: Recurse on local labels?
560 // See what kind of statement we have.
561 switch (Lexer.getKind()) {
562 case AsmToken::Colon: {
563 // identifier ':' -> Label.
566 // Diagnose attempt to use a variable as a label.
568 // FIXME: Diagnostics. Note the location of the definition as a label.
569 // FIXME: This doesn't diagnose assignment to a symbol which has been
570 // implicitly marked as external.
572 if (LocalLabelVal == -1)
573 Sym = CreateSymbol(IDVal);
575 Sym = Ctx.CreateDirectionalLocalSymbol(LocalLabelVal);
576 if (!Sym->isUndefined() || Sym->isVariable())
577 return Error(IDLoc, "invalid symbol redefinition");
582 // Consume any end of statement token, if present, to avoid spurious
583 // AddBlankLine calls().
584 if (Lexer.is(AsmToken::EndOfStatement)) {
586 if (Lexer.is(AsmToken::Eof))
590 return ParseStatement();
593 case AsmToken::Equal:
594 // identifier '=' ... -> assignment statement
597 return ParseAssignment(IDVal);
599 default: // Normal instruction or directive.
603 // Otherwise, we have a normal instruction or directive.
604 if (IDVal[0] == '.') {
605 // FIXME: This should be driven based on a hash lookup and callback.
606 if (IDVal == ".section")
607 return ParseDirectiveDarwinSection();
608 if (IDVal == ".text")
609 // FIXME: This changes behavior based on the -static flag to the
611 return ParseDirectiveSectionSwitch("__TEXT", "__text",
612 MCSectionMachO::S_ATTR_PURE_INSTRUCTIONS);
613 if (IDVal == ".const")
614 return ParseDirectiveSectionSwitch("__TEXT", "__const");
615 if (IDVal == ".static_const")
616 return ParseDirectiveSectionSwitch("__TEXT", "__static_const");
617 if (IDVal == ".cstring")
618 return ParseDirectiveSectionSwitch("__TEXT","__cstring",
619 MCSectionMachO::S_CSTRING_LITERALS);
620 if (IDVal == ".literal4")
621 return ParseDirectiveSectionSwitch("__TEXT", "__literal4",
622 MCSectionMachO::S_4BYTE_LITERALS,
624 if (IDVal == ".literal8")
625 return ParseDirectiveSectionSwitch("__TEXT", "__literal8",
626 MCSectionMachO::S_8BYTE_LITERALS,
628 if (IDVal == ".literal16")
629 return ParseDirectiveSectionSwitch("__TEXT","__literal16",
630 MCSectionMachO::S_16BYTE_LITERALS,
632 if (IDVal == ".constructor")
633 return ParseDirectiveSectionSwitch("__TEXT","__constructor");
634 if (IDVal == ".destructor")
635 return ParseDirectiveSectionSwitch("__TEXT","__destructor");
636 if (IDVal == ".fvmlib_init0")
637 return ParseDirectiveSectionSwitch("__TEXT","__fvmlib_init0");
638 if (IDVal == ".fvmlib_init1")
639 return ParseDirectiveSectionSwitch("__TEXT","__fvmlib_init1");
641 // FIXME: The assembler manual claims that this has the self modify code
642 // flag, at least on x86-32, but that does not appear to be correct.
643 if (IDVal == ".symbol_stub")
644 return ParseDirectiveSectionSwitch("__TEXT","__symbol_stub",
645 MCSectionMachO::S_SYMBOL_STUBS |
646 MCSectionMachO::S_ATTR_PURE_INSTRUCTIONS,
647 // FIXME: Different on PPC and ARM.
649 // FIXME: PowerPC only?
650 if (IDVal == ".picsymbol_stub")
651 return ParseDirectiveSectionSwitch("__TEXT","__picsymbol_stub",
652 MCSectionMachO::S_SYMBOL_STUBS |
653 MCSectionMachO::S_ATTR_PURE_INSTRUCTIONS,
655 if (IDVal == ".data")
656 return ParseDirectiveSectionSwitch("__DATA", "__data");
657 if (IDVal == ".static_data")
658 return ParseDirectiveSectionSwitch("__DATA", "__static_data");
660 // FIXME: The section names of these two are misspelled in the assembler
662 if (IDVal == ".non_lazy_symbol_pointer")
663 return ParseDirectiveSectionSwitch("__DATA", "__nl_symbol_ptr",
664 MCSectionMachO::S_NON_LAZY_SYMBOL_POINTERS,
666 if (IDVal == ".lazy_symbol_pointer")
667 return ParseDirectiveSectionSwitch("__DATA", "__la_symbol_ptr",
668 MCSectionMachO::S_LAZY_SYMBOL_POINTERS,
671 if (IDVal == ".dyld")
672 return ParseDirectiveSectionSwitch("__DATA", "__dyld");
673 if (IDVal == ".mod_init_func")
674 return ParseDirectiveSectionSwitch("__DATA", "__mod_init_func",
675 MCSectionMachO::S_MOD_INIT_FUNC_POINTERS,
677 if (IDVal == ".mod_term_func")
678 return ParseDirectiveSectionSwitch("__DATA", "__mod_term_func",
679 MCSectionMachO::S_MOD_TERM_FUNC_POINTERS,
681 if (IDVal == ".const_data")
682 return ParseDirectiveSectionSwitch("__DATA", "__const");
685 if (IDVal == ".objc_class")
686 return ParseDirectiveSectionSwitch("__OBJC", "__class",
687 MCSectionMachO::S_ATTR_NO_DEAD_STRIP);
688 if (IDVal == ".objc_meta_class")
689 return ParseDirectiveSectionSwitch("__OBJC", "__meta_class",
690 MCSectionMachO::S_ATTR_NO_DEAD_STRIP);
691 if (IDVal == ".objc_cat_cls_meth")
692 return ParseDirectiveSectionSwitch("__OBJC", "__cat_cls_meth",
693 MCSectionMachO::S_ATTR_NO_DEAD_STRIP);
694 if (IDVal == ".objc_cat_inst_meth")
695 return ParseDirectiveSectionSwitch("__OBJC", "__cat_inst_meth",
696 MCSectionMachO::S_ATTR_NO_DEAD_STRIP);
697 if (IDVal == ".objc_protocol")
698 return ParseDirectiveSectionSwitch("__OBJC", "__protocol",
699 MCSectionMachO::S_ATTR_NO_DEAD_STRIP);
700 if (IDVal == ".objc_string_object")
701 return ParseDirectiveSectionSwitch("__OBJC", "__string_object",
702 MCSectionMachO::S_ATTR_NO_DEAD_STRIP);
703 if (IDVal == ".objc_cls_meth")
704 return ParseDirectiveSectionSwitch("__OBJC", "__cls_meth",
705 MCSectionMachO::S_ATTR_NO_DEAD_STRIP);
706 if (IDVal == ".objc_inst_meth")
707 return ParseDirectiveSectionSwitch("__OBJC", "__inst_meth",
708 MCSectionMachO::S_ATTR_NO_DEAD_STRIP);
709 if (IDVal == ".objc_cls_refs")
710 return ParseDirectiveSectionSwitch("__OBJC", "__cls_refs",
711 MCSectionMachO::S_ATTR_NO_DEAD_STRIP |
712 MCSectionMachO::S_LITERAL_POINTERS,
714 if (IDVal == ".objc_message_refs")
715 return ParseDirectiveSectionSwitch("__OBJC", "__message_refs",
716 MCSectionMachO::S_ATTR_NO_DEAD_STRIP |
717 MCSectionMachO::S_LITERAL_POINTERS,
719 if (IDVal == ".objc_symbols")
720 return ParseDirectiveSectionSwitch("__OBJC", "__symbols",
721 MCSectionMachO::S_ATTR_NO_DEAD_STRIP);
722 if (IDVal == ".objc_category")
723 return ParseDirectiveSectionSwitch("__OBJC", "__category",
724 MCSectionMachO::S_ATTR_NO_DEAD_STRIP);
725 if (IDVal == ".objc_class_vars")
726 return ParseDirectiveSectionSwitch("__OBJC", "__class_vars",
727 MCSectionMachO::S_ATTR_NO_DEAD_STRIP);
728 if (IDVal == ".objc_instance_vars")
729 return ParseDirectiveSectionSwitch("__OBJC", "__instance_vars",
730 MCSectionMachO::S_ATTR_NO_DEAD_STRIP);
731 if (IDVal == ".objc_module_info")
732 return ParseDirectiveSectionSwitch("__OBJC", "__module_info",
733 MCSectionMachO::S_ATTR_NO_DEAD_STRIP);
734 if (IDVal == ".objc_class_names")
735 return ParseDirectiveSectionSwitch("__TEXT", "__cstring",
736 MCSectionMachO::S_CSTRING_LITERALS);
737 if (IDVal == ".objc_meth_var_types")
738 return ParseDirectiveSectionSwitch("__TEXT", "__cstring",
739 MCSectionMachO::S_CSTRING_LITERALS);
740 if (IDVal == ".objc_meth_var_names")
741 return ParseDirectiveSectionSwitch("__TEXT", "__cstring",
742 MCSectionMachO::S_CSTRING_LITERALS);
743 if (IDVal == ".objc_selector_strs")
744 return ParseDirectiveSectionSwitch("__OBJC", "__selector_strs",
745 MCSectionMachO::S_CSTRING_LITERALS);
747 if (IDVal == ".tdata")
748 return ParseDirectiveSectionSwitch("__DATA", "__thread_data",
749 MCSectionMachO::S_THREAD_LOCAL_REGULAR);
751 return ParseDirectiveSectionSwitch("__DATA", "__thread_vars",
752 MCSectionMachO::S_THREAD_LOCAL_VARIABLES);
753 if (IDVal == ".thread_init_func")
754 return ParseDirectiveSectionSwitch("__DATA", "__thread_init",
755 MCSectionMachO::S_THREAD_LOCAL_INIT_FUNCTION_POINTERS);
757 // Assembler features
759 return ParseDirectiveSet();
763 if (IDVal == ".ascii")
764 return ParseDirectiveAscii(false);
765 if (IDVal == ".asciz")
766 return ParseDirectiveAscii(true);
768 if (IDVal == ".byte")
769 return ParseDirectiveValue(1);
770 if (IDVal == ".short")
771 return ParseDirectiveValue(2);
772 if (IDVal == ".long")
773 return ParseDirectiveValue(4);
774 if (IDVal == ".quad")
775 return ParseDirectiveValue(8);
777 // FIXME: Target hooks for IsPow2.
778 if (IDVal == ".align")
779 return ParseDirectiveAlign(/*IsPow2=*/true, /*ExprSize=*/1);
780 if (IDVal == ".align32")
781 return ParseDirectiveAlign(/*IsPow2=*/true, /*ExprSize=*/4);
782 if (IDVal == ".balign")
783 return ParseDirectiveAlign(/*IsPow2=*/false, /*ExprSize=*/1);
784 if (IDVal == ".balignw")
785 return ParseDirectiveAlign(/*IsPow2=*/false, /*ExprSize=*/2);
786 if (IDVal == ".balignl")
787 return ParseDirectiveAlign(/*IsPow2=*/false, /*ExprSize=*/4);
788 if (IDVal == ".p2align")
789 return ParseDirectiveAlign(/*IsPow2=*/true, /*ExprSize=*/1);
790 if (IDVal == ".p2alignw")
791 return ParseDirectiveAlign(/*IsPow2=*/true, /*ExprSize=*/2);
792 if (IDVal == ".p2alignl")
793 return ParseDirectiveAlign(/*IsPow2=*/true, /*ExprSize=*/4);
796 return ParseDirectiveOrg();
798 if (IDVal == ".fill")
799 return ParseDirectiveFill();
800 if (IDVal == ".space")
801 return ParseDirectiveSpace();
803 // Symbol attribute directives
805 if (IDVal == ".globl" || IDVal == ".global")
806 return ParseDirectiveSymbolAttribute(MCSA_Global);
807 if (IDVal == ".hidden")
808 return ParseDirectiveSymbolAttribute(MCSA_Hidden);
809 if (IDVal == ".indirect_symbol")
810 return ParseDirectiveSymbolAttribute(MCSA_IndirectSymbol);
811 if (IDVal == ".internal")
812 return ParseDirectiveSymbolAttribute(MCSA_Internal);
813 if (IDVal == ".lazy_reference")
814 return ParseDirectiveSymbolAttribute(MCSA_LazyReference);
815 if (IDVal == ".no_dead_strip")
816 return ParseDirectiveSymbolAttribute(MCSA_NoDeadStrip);
817 if (IDVal == ".private_extern")
818 return ParseDirectiveSymbolAttribute(MCSA_PrivateExtern);
819 if (IDVal == ".protected")
820 return ParseDirectiveSymbolAttribute(MCSA_Protected);
821 if (IDVal == ".reference")
822 return ParseDirectiveSymbolAttribute(MCSA_Reference);
823 if (IDVal == ".type")
824 return ParseDirectiveELFType();
825 if (IDVal == ".weak")
826 return ParseDirectiveSymbolAttribute(MCSA_Weak);
827 if (IDVal == ".weak_definition")
828 return ParseDirectiveSymbolAttribute(MCSA_WeakDefinition);
829 if (IDVal == ".weak_reference")
830 return ParseDirectiveSymbolAttribute(MCSA_WeakReference);
831 if (IDVal == ".weak_def_can_be_hidden")
832 return ParseDirectiveSymbolAttribute(MCSA_WeakDefAutoPrivate);
834 if (IDVal == ".comm")
835 return ParseDirectiveComm(/*IsLocal=*/false);
836 if (IDVal == ".lcomm")
837 return ParseDirectiveComm(/*IsLocal=*/true);
838 if (IDVal == ".zerofill")
839 return ParseDirectiveDarwinZerofill();
840 if (IDVal == ".desc")
841 return ParseDirectiveDarwinSymbolDesc();
842 if (IDVal == ".tbss")
843 return ParseDirectiveDarwinTBSS();
845 if (IDVal == ".abort")
846 return ParseDirectiveAbort();
847 if (IDVal == ".include")
848 return ParseDirectiveInclude();
850 // Look up the handler in the handler table.
851 std::pair<MCAsmParserExtension*, DirectiveHandler> Handler =
852 DirectiveMap.lookup(IDVal);
854 return (Handler.first->*Handler.second)(IDVal, IDLoc);
856 // Target hook for parsing target specific directives.
857 if (!getTargetParser().ParseDirective(ID))
860 Warning(IDLoc, "ignoring directive for now");
861 EatToEndOfStatement();
865 // Canonicalize the opcode to lower case.
866 SmallString<128> Opcode;
867 for (unsigned i = 0, e = IDVal.size(); i != e; ++i)
868 Opcode.push_back(tolower(IDVal[i]));
870 SmallVector<MCParsedAsmOperand*, 8> ParsedOperands;
871 bool HadError = getTargetParser().ParseInstruction(Opcode.str(), IDLoc,
873 if (!HadError && Lexer.isNot(AsmToken::EndOfStatement))
874 HadError = TokError("unexpected token in argument list");
876 // If parsing succeeded, match the instruction.
879 if (!getTargetParser().MatchInstruction(ParsedOperands, Inst)) {
880 // Emit the instruction on success.
881 Out.EmitInstruction(Inst);
883 // Otherwise emit a diagnostic about the match failure and set the error
886 // FIXME: We should give nicer diagnostics about the exact failure.
887 Error(IDLoc, "unrecognized instruction");
892 // If there was no error, consume the end-of-statement token. Otherwise this
893 // will be done by our caller.
897 // Free any parsed operands.
898 for (unsigned i = 0, e = ParsedOperands.size(); i != e; ++i)
899 delete ParsedOperands[i];
904 bool AsmParser::ParseAssignment(const StringRef &Name) {
905 // FIXME: Use better location, we should use proper tokens.
906 SMLoc EqualLoc = Lexer.getLoc();
909 if (ParseExpression(Value))
912 if (Lexer.isNot(AsmToken::EndOfStatement))
913 return TokError("unexpected token in assignment");
915 // Eat the end of statement marker.
918 // Validate that the LHS is allowed to be a variable (either it has not been
919 // used as a symbol, or it is an absolute symbol).
920 MCSymbol *Sym = getContext().LookupSymbol(Name);
922 // Diagnose assignment to a label.
924 // FIXME: Diagnostics. Note the location of the definition as a label.
925 // FIXME: Diagnose assignment to protected identifier (e.g., register name).
926 if (Sym->isUndefined() && !Sym->isUsedInExpr())
927 ; // Allow redefinitions of undefined symbols only used in directives.
928 else if (!Sym->isUndefined() && !Sym->isAbsolute())
929 return Error(EqualLoc, "redefinition of '" + Name + "'");
930 else if (!Sym->isVariable())
931 return Error(EqualLoc, "invalid assignment to '" + Name + "'");
932 else if (!isa<MCConstantExpr>(Sym->getVariableValue()))
933 return Error(EqualLoc, "invalid reassignment of non-absolute variable '" +
936 Sym = CreateSymbol(Name);
938 // FIXME: Handle '.'.
940 Sym->setUsedInExpr(true);
942 // Do the assignment.
943 Out.EmitAssignment(Sym, Value);
951 bool AsmParser::ParseIdentifier(StringRef &Res) {
952 if (Lexer.isNot(AsmToken::Identifier) &&
953 Lexer.isNot(AsmToken::String))
956 Res = getTok().getIdentifier();
958 Lex(); // Consume the identifier token.
963 /// ParseDirectiveSet:
964 /// ::= .set identifier ',' expression
965 bool AsmParser::ParseDirectiveSet() {
968 if (ParseIdentifier(Name))
969 return TokError("expected identifier after '.set' directive");
971 if (getLexer().isNot(AsmToken::Comma))
972 return TokError("unexpected token in '.set'");
975 return ParseAssignment(Name);
978 /// ParseDirectiveSection:
979 /// ::= .section identifier (',' identifier)*
980 /// FIXME: This should actually parse out the segment, section, attributes and
981 /// sizeof_stub fields.
982 bool AsmParser::ParseDirectiveDarwinSection() {
983 SMLoc Loc = getLexer().getLoc();
985 StringRef SectionName;
986 if (ParseIdentifier(SectionName))
987 return Error(Loc, "expected identifier after '.section' directive");
989 // Verify there is a following comma.
990 if (!getLexer().is(AsmToken::Comma))
991 return TokError("unexpected token in '.section' directive");
993 std::string SectionSpec = SectionName;
996 // Add all the tokens until the end of the line, ParseSectionSpecifier will
998 StringRef EOL = Lexer.LexUntilEndOfStatement();
999 SectionSpec.append(EOL.begin(), EOL.end());
1002 if (getLexer().isNot(AsmToken::EndOfStatement))
1003 return TokError("unexpected token in '.section' directive");
1007 StringRef Segment, Section;
1008 unsigned TAA, StubSize;
1009 std::string ErrorStr =
1010 MCSectionMachO::ParseSectionSpecifier(SectionSpec, Segment, Section,
1013 if (!ErrorStr.empty())
1014 return Error(Loc, ErrorStr.c_str());
1016 // FIXME: Arch specific.
1017 bool isText = Segment == "__TEXT"; // FIXME: Hack.
1018 getStreamer().SwitchSection(Ctx.getMachOSection(
1019 Segment, Section, TAA, StubSize,
1020 isText ? SectionKind::getText()
1021 : SectionKind::getDataRel()));
1025 /// ParseDirectiveSectionSwitch -
1026 bool AsmParser::ParseDirectiveSectionSwitch(const char *Segment,
1027 const char *Section,
1028 unsigned TAA, unsigned Align,
1029 unsigned StubSize) {
1030 if (getLexer().isNot(AsmToken::EndOfStatement))
1031 return TokError("unexpected token in section switching directive");
1034 // FIXME: Arch specific.
1035 bool isText = StringRef(Segment) == "__TEXT"; // FIXME: Hack.
1036 getStreamer().SwitchSection(Ctx.getMachOSection(Segment, Section, TAA, StubSize,
1037 isText ? SectionKind::getText()
1038 : SectionKind::getDataRel()));
1040 // Set the implicit alignment, if any.
1042 // FIXME: This isn't really what 'as' does; I think it just uses the implicit
1043 // alignment on the section (e.g., if one manually inserts bytes into the
1044 // section, then just issueing the section switch directive will not realign
1045 // the section. However, this is arguably more reasonable behavior, and there
1046 // is no good reason for someone to intentionally emit incorrectly sized
1047 // values into the implicitly aligned sections.
1049 getStreamer().EmitValueToAlignment(Align, 0, 1, 0);
1054 bool AsmParser::ParseEscapedString(std::string &Data) {
1055 assert(getLexer().is(AsmToken::String) && "Unexpected current token!");
1058 StringRef Str = getTok().getStringContents();
1059 for (unsigned i = 0, e = Str.size(); i != e; ++i) {
1060 if (Str[i] != '\\') {
1065 // Recognize escaped characters. Note that this escape semantics currently
1066 // loosely follows Darwin 'as'. Notably, it doesn't support hex escapes.
1069 return TokError("unexpected backslash at end of string");
1071 // Recognize octal sequences.
1072 if ((unsigned) (Str[i] - '0') <= 7) {
1073 // Consume up to three octal characters.
1074 unsigned Value = Str[i] - '0';
1076 if (i + 1 != e && ((unsigned) (Str[i + 1] - '0')) <= 7) {
1078 Value = Value * 8 + (Str[i] - '0');
1080 if (i + 1 != e && ((unsigned) (Str[i + 1] - '0')) <= 7) {
1082 Value = Value * 8 + (Str[i] - '0');
1087 return TokError("invalid octal escape sequence (out of range)");
1089 Data += (unsigned char) Value;
1093 // Otherwise recognize individual escapes.
1096 // Just reject invalid escape sequences for now.
1097 return TokError("invalid escape sequence (unrecognized character)");
1099 case 'b': Data += '\b'; break;
1100 case 'f': Data += '\f'; break;
1101 case 'n': Data += '\n'; break;
1102 case 'r': Data += '\r'; break;
1103 case 't': Data += '\t'; break;
1104 case '"': Data += '"'; break;
1105 case '\\': Data += '\\'; break;
1112 /// ParseDirectiveAscii:
1113 /// ::= ( .ascii | .asciz ) [ "string" ( , "string" )* ]
1114 bool AsmParser::ParseDirectiveAscii(bool ZeroTerminated) {
1115 if (getLexer().isNot(AsmToken::EndOfStatement)) {
1117 if (getLexer().isNot(AsmToken::String))
1118 return TokError("expected string in '.ascii' or '.asciz' directive");
1121 if (ParseEscapedString(Data))
1124 getStreamer().EmitBytes(Data, DEFAULT_ADDRSPACE);
1126 getStreamer().EmitBytes(StringRef("\0", 1), DEFAULT_ADDRSPACE);
1130 if (getLexer().is(AsmToken::EndOfStatement))
1133 if (getLexer().isNot(AsmToken::Comma))
1134 return TokError("unexpected token in '.ascii' or '.asciz' directive");
1143 /// ParseDirectiveValue
1144 /// ::= (.byte | .short | ... ) [ expression (, expression)* ]
1145 bool AsmParser::ParseDirectiveValue(unsigned Size) {
1146 if (getLexer().isNot(AsmToken::EndOfStatement)) {
1148 const MCExpr *Value;
1149 SMLoc ATTRIBUTE_UNUSED StartLoc = getLexer().getLoc();
1150 if (ParseExpression(Value))
1153 // Special case constant expressions to match code generator.
1154 if (const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(Value))
1155 getStreamer().EmitIntValue(MCE->getValue(), Size, DEFAULT_ADDRSPACE);
1157 getStreamer().EmitValue(Value, Size, DEFAULT_ADDRSPACE);
1159 if (getLexer().is(AsmToken::EndOfStatement))
1162 // FIXME: Improve diagnostic.
1163 if (getLexer().isNot(AsmToken::Comma))
1164 return TokError("unexpected token in directive");
1173 /// ParseDirectiveSpace
1174 /// ::= .space expression [ , expression ]
1175 bool AsmParser::ParseDirectiveSpace() {
1177 if (ParseAbsoluteExpression(NumBytes))
1180 int64_t FillExpr = 0;
1181 if (getLexer().isNot(AsmToken::EndOfStatement)) {
1182 if (getLexer().isNot(AsmToken::Comma))
1183 return TokError("unexpected token in '.space' directive");
1186 if (ParseAbsoluteExpression(FillExpr))
1189 if (getLexer().isNot(AsmToken::EndOfStatement))
1190 return TokError("unexpected token in '.space' directive");
1196 return TokError("invalid number of bytes in '.space' directive");
1198 // FIXME: Sometimes the fill expr is 'nop' if it isn't supplied, instead of 0.
1199 getStreamer().EmitFill(NumBytes, FillExpr, DEFAULT_ADDRSPACE);
1204 /// ParseDirectiveFill
1205 /// ::= .fill expression , expression , expression
1206 bool AsmParser::ParseDirectiveFill() {
1208 if (ParseAbsoluteExpression(NumValues))
1211 if (getLexer().isNot(AsmToken::Comma))
1212 return TokError("unexpected token in '.fill' directive");
1216 if (ParseAbsoluteExpression(FillSize))
1219 if (getLexer().isNot(AsmToken::Comma))
1220 return TokError("unexpected token in '.fill' directive");
1224 if (ParseAbsoluteExpression(FillExpr))
1227 if (getLexer().isNot(AsmToken::EndOfStatement))
1228 return TokError("unexpected token in '.fill' directive");
1232 if (FillSize != 1 && FillSize != 2 && FillSize != 4 && FillSize != 8)
1233 return TokError("invalid '.fill' size, expected 1, 2, 4, or 8");
1235 for (uint64_t i = 0, e = NumValues; i != e; ++i)
1236 getStreamer().EmitIntValue(FillExpr, FillSize, DEFAULT_ADDRSPACE);
1241 /// ParseDirectiveOrg
1242 /// ::= .org expression [ , expression ]
1243 bool AsmParser::ParseDirectiveOrg() {
1244 const MCExpr *Offset;
1245 if (ParseExpression(Offset))
1248 // Parse optional fill expression.
1249 int64_t FillExpr = 0;
1250 if (getLexer().isNot(AsmToken::EndOfStatement)) {
1251 if (getLexer().isNot(AsmToken::Comma))
1252 return TokError("unexpected token in '.org' directive");
1255 if (ParseAbsoluteExpression(FillExpr))
1258 if (getLexer().isNot(AsmToken::EndOfStatement))
1259 return TokError("unexpected token in '.org' directive");
1264 // FIXME: Only limited forms of relocatable expressions are accepted here, it
1265 // has to be relative to the current section.
1266 getStreamer().EmitValueToOffset(Offset, FillExpr);
1271 /// ParseDirectiveAlign
1272 /// ::= {.align, ...} expression [ , expression [ , expression ]]
1273 bool AsmParser::ParseDirectiveAlign(bool IsPow2, unsigned ValueSize) {
1274 SMLoc AlignmentLoc = getLexer().getLoc();
1276 if (ParseAbsoluteExpression(Alignment))
1280 bool HasFillExpr = false;
1281 int64_t FillExpr = 0;
1282 int64_t MaxBytesToFill = 0;
1283 if (getLexer().isNot(AsmToken::EndOfStatement)) {
1284 if (getLexer().isNot(AsmToken::Comma))
1285 return TokError("unexpected token in directive");
1288 // The fill expression can be omitted while specifying a maximum number of
1289 // alignment bytes, e.g:
1291 if (getLexer().isNot(AsmToken::Comma)) {
1293 if (ParseAbsoluteExpression(FillExpr))
1297 if (getLexer().isNot(AsmToken::EndOfStatement)) {
1298 if (getLexer().isNot(AsmToken::Comma))
1299 return TokError("unexpected token in directive");
1302 MaxBytesLoc = getLexer().getLoc();
1303 if (ParseAbsoluteExpression(MaxBytesToFill))
1306 if (getLexer().isNot(AsmToken::EndOfStatement))
1307 return TokError("unexpected token in directive");
1316 // Compute alignment in bytes.
1318 // FIXME: Diagnose overflow.
1319 if (Alignment >= 32) {
1320 Error(AlignmentLoc, "invalid alignment value");
1324 Alignment = 1ULL << Alignment;
1327 // Diagnose non-sensical max bytes to align.
1328 if (MaxBytesLoc.isValid()) {
1329 if (MaxBytesToFill < 1) {
1330 Error(MaxBytesLoc, "alignment directive can never be satisfied in this "
1331 "many bytes, ignoring maximum bytes expression");
1335 if (MaxBytesToFill >= Alignment) {
1336 Warning(MaxBytesLoc, "maximum bytes expression exceeds alignment and "
1342 // Check whether we should use optimal code alignment for this .align
1345 // FIXME: This should be using a target hook.
1346 bool UseCodeAlign = false;
1347 if (const MCSectionMachO *S = dyn_cast<MCSectionMachO>(
1348 getStreamer().getCurrentSection()))
1349 UseCodeAlign = S->hasAttribute(MCSectionMachO::S_ATTR_PURE_INSTRUCTIONS);
1350 if ((!HasFillExpr || Lexer.getMAI().getTextAlignFillValue() == FillExpr) &&
1351 ValueSize == 1 && UseCodeAlign) {
1352 getStreamer().EmitCodeAlignment(Alignment, MaxBytesToFill);
1354 // FIXME: Target specific behavior about how the "extra" bytes are filled.
1355 getStreamer().EmitValueToAlignment(Alignment, FillExpr, ValueSize, MaxBytesToFill);
1361 /// ParseDirectiveSymbolAttribute
1362 /// ::= { ".globl", ".weak", ... } [ identifier ( , identifier )* ]
1363 bool AsmParser::ParseDirectiveSymbolAttribute(MCSymbolAttr Attr) {
1364 if (getLexer().isNot(AsmToken::EndOfStatement)) {
1368 if (ParseIdentifier(Name))
1369 return TokError("expected identifier in directive");
1371 MCSymbol *Sym = CreateSymbol(Name);
1373 getStreamer().EmitSymbolAttribute(Sym, Attr);
1375 if (getLexer().is(AsmToken::EndOfStatement))
1378 if (getLexer().isNot(AsmToken::Comma))
1379 return TokError("unexpected token in directive");
1388 /// ParseDirectiveELFType
1389 /// ::= .type identifier , @attribute
1390 bool AsmParser::ParseDirectiveELFType() {
1392 if (ParseIdentifier(Name))
1393 return TokError("expected identifier in directive");
1395 // Handle the identifier as the key symbol.
1396 MCSymbol *Sym = CreateSymbol(Name);
1398 if (getLexer().isNot(AsmToken::Comma))
1399 return TokError("unexpected token in '.type' directive");
1402 if (getLexer().isNot(AsmToken::At))
1403 return TokError("expected '@' before type");
1409 TypeLoc = getLexer().getLoc();
1410 if (ParseIdentifier(Type))
1411 return TokError("expected symbol type in directive");
1413 MCSymbolAttr Attr = StringSwitch<MCSymbolAttr>(Type)
1414 .Case("function", MCSA_ELF_TypeFunction)
1415 .Case("object", MCSA_ELF_TypeObject)
1416 .Case("tls_object", MCSA_ELF_TypeTLS)
1417 .Case("common", MCSA_ELF_TypeCommon)
1418 .Case("notype", MCSA_ELF_TypeNoType)
1419 .Default(MCSA_Invalid);
1421 if (Attr == MCSA_Invalid)
1422 return Error(TypeLoc, "unsupported attribute in '.type' directive");
1424 if (getLexer().isNot(AsmToken::EndOfStatement))
1425 return TokError("unexpected token in '.type' directive");
1429 getStreamer().EmitSymbolAttribute(Sym, Attr);
1434 /// ParseDirectiveDarwinSymbolDesc
1435 /// ::= .desc identifier , expression
1436 bool AsmParser::ParseDirectiveDarwinSymbolDesc() {
1438 if (ParseIdentifier(Name))
1439 return TokError("expected identifier in directive");
1441 // Handle the identifier as the key symbol.
1442 MCSymbol *Sym = CreateSymbol(Name);
1444 if (getLexer().isNot(AsmToken::Comma))
1445 return TokError("unexpected token in '.desc' directive");
1449 if (ParseAbsoluteExpression(DescValue))
1452 if (getLexer().isNot(AsmToken::EndOfStatement))
1453 return TokError("unexpected token in '.desc' directive");
1457 // Set the n_desc field of this Symbol to this DescValue
1458 getStreamer().EmitSymbolDesc(Sym, DescValue);
1463 /// ParseDirectiveComm
1464 /// ::= ( .comm | .lcomm ) identifier , size_expression [ , align_expression ]
1465 bool AsmParser::ParseDirectiveComm(bool IsLocal) {
1466 SMLoc IDLoc = getLexer().getLoc();
1468 if (ParseIdentifier(Name))
1469 return TokError("expected identifier in directive");
1471 // Handle the identifier as the key symbol.
1472 MCSymbol *Sym = CreateSymbol(Name);
1474 if (getLexer().isNot(AsmToken::Comma))
1475 return TokError("unexpected token in directive");
1479 SMLoc SizeLoc = getLexer().getLoc();
1480 if (ParseAbsoluteExpression(Size))
1483 int64_t Pow2Alignment = 0;
1484 SMLoc Pow2AlignmentLoc;
1485 if (getLexer().is(AsmToken::Comma)) {
1487 Pow2AlignmentLoc = getLexer().getLoc();
1488 if (ParseAbsoluteExpression(Pow2Alignment))
1491 // If this target takes alignments in bytes (not log) validate and convert.
1492 if (Lexer.getMAI().getAlignmentIsInBytes()) {
1493 if (!isPowerOf2_64(Pow2Alignment))
1494 return Error(Pow2AlignmentLoc, "alignment must be a power of 2");
1495 Pow2Alignment = Log2_64(Pow2Alignment);
1499 if (getLexer().isNot(AsmToken::EndOfStatement))
1500 return TokError("unexpected token in '.comm' or '.lcomm' directive");
1504 // NOTE: a size of zero for a .comm should create a undefined symbol
1505 // but a size of .lcomm creates a bss symbol of size zero.
1507 return Error(SizeLoc, "invalid '.comm' or '.lcomm' directive size, can't "
1508 "be less than zero");
1510 // NOTE: The alignment in the directive is a power of 2 value, the assembler
1511 // may internally end up wanting an alignment in bytes.
1512 // FIXME: Diagnose overflow.
1513 if (Pow2Alignment < 0)
1514 return Error(Pow2AlignmentLoc, "invalid '.comm' or '.lcomm' directive "
1515 "alignment, can't be less than zero");
1517 if (!Sym->isUndefined())
1518 return Error(IDLoc, "invalid symbol redefinition");
1520 // '.lcomm' is equivalent to '.zerofill'.
1521 // Create the Symbol as a common or local common with Size and Pow2Alignment
1523 getStreamer().EmitZerofill(Ctx.getMachOSection(
1524 "__DATA", "__bss", MCSectionMachO::S_ZEROFILL,
1525 0, SectionKind::getBSS()),
1526 Sym, Size, 1 << Pow2Alignment);
1530 getStreamer().EmitCommonSymbol(Sym, Size, 1 << Pow2Alignment);
1534 /// ParseDirectiveDarwinZerofill
1535 /// ::= .zerofill segname , sectname [, identifier , size_expression [
1536 /// , align_expression ]]
1537 bool AsmParser::ParseDirectiveDarwinZerofill() {
1539 if (ParseIdentifier(Segment))
1540 return TokError("expected segment name after '.zerofill' directive");
1542 if (getLexer().isNot(AsmToken::Comma))
1543 return TokError("unexpected token in directive");
1547 if (ParseIdentifier(Section))
1548 return TokError("expected section name after comma in '.zerofill' "
1551 // If this is the end of the line all that was wanted was to create the
1552 // the section but with no symbol.
1553 if (getLexer().is(AsmToken::EndOfStatement)) {
1554 // Create the zerofill section but no symbol
1555 getStreamer().EmitZerofill(Ctx.getMachOSection(Segment, Section,
1556 MCSectionMachO::S_ZEROFILL, 0,
1557 SectionKind::getBSS()));
1561 if (getLexer().isNot(AsmToken::Comma))
1562 return TokError("unexpected token in directive");
1565 SMLoc IDLoc = getLexer().getLoc();
1567 if (ParseIdentifier(IDStr))
1568 return TokError("expected identifier in directive");
1570 // handle the identifier as the key symbol.
1571 MCSymbol *Sym = CreateSymbol(IDStr);
1573 if (getLexer().isNot(AsmToken::Comma))
1574 return TokError("unexpected token in directive");
1578 SMLoc SizeLoc = getLexer().getLoc();
1579 if (ParseAbsoluteExpression(Size))
1582 int64_t Pow2Alignment = 0;
1583 SMLoc Pow2AlignmentLoc;
1584 if (getLexer().is(AsmToken::Comma)) {
1586 Pow2AlignmentLoc = getLexer().getLoc();
1587 if (ParseAbsoluteExpression(Pow2Alignment))
1591 if (getLexer().isNot(AsmToken::EndOfStatement))
1592 return TokError("unexpected token in '.zerofill' directive");
1597 return Error(SizeLoc, "invalid '.zerofill' directive size, can't be less "
1600 // NOTE: The alignment in the directive is a power of 2 value, the assembler
1601 // may internally end up wanting an alignment in bytes.
1602 // FIXME: Diagnose overflow.
1603 if (Pow2Alignment < 0)
1604 return Error(Pow2AlignmentLoc, "invalid '.zerofill' directive alignment, "
1605 "can't be less than zero");
1607 if (!Sym->isUndefined())
1608 return Error(IDLoc, "invalid symbol redefinition");
1610 // Create the zerofill Symbol with Size and Pow2Alignment
1612 // FIXME: Arch specific.
1613 getStreamer().EmitZerofill(Ctx.getMachOSection(Segment, Section,
1614 MCSectionMachO::S_ZEROFILL, 0,
1615 SectionKind::getBSS()),
1616 Sym, Size, 1 << Pow2Alignment);
1621 /// ParseDirectiveDarwinTBSS
1622 /// ::= .tbss identifier, size, align
1623 bool AsmParser::ParseDirectiveDarwinTBSS() {
1624 SMLoc IDLoc = getLexer().getLoc();
1626 if (ParseIdentifier(Name))
1627 return TokError("expected identifier in directive");
1629 // Handle the identifier as the key symbol.
1630 MCSymbol *Sym = CreateSymbol(Name);
1632 if (getLexer().isNot(AsmToken::Comma))
1633 return TokError("unexpected token in directive");
1637 SMLoc SizeLoc = getLexer().getLoc();
1638 if (ParseAbsoluteExpression(Size))
1641 int64_t Pow2Alignment = 0;
1642 SMLoc Pow2AlignmentLoc;
1643 if (getLexer().is(AsmToken::Comma)) {
1645 Pow2AlignmentLoc = getLexer().getLoc();
1646 if (ParseAbsoluteExpression(Pow2Alignment))
1650 if (getLexer().isNot(AsmToken::EndOfStatement))
1651 return TokError("unexpected token in '.tbss' directive");
1656 return Error(SizeLoc, "invalid '.tbss' directive size, can't be less than"
1659 // FIXME: Diagnose overflow.
1660 if (Pow2Alignment < 0)
1661 return Error(Pow2AlignmentLoc, "invalid '.tbss' alignment, can't be less"
1664 if (!Sym->isUndefined())
1665 return Error(IDLoc, "invalid symbol redefinition");
1667 getStreamer().EmitTBSSSymbol(Ctx.getMachOSection(
1668 "__DATA", "__thread_bss",
1669 MCSectionMachO::S_THREAD_LOCAL_ZEROFILL,
1670 0, SectionKind::getThreadBSS()),
1671 Sym, Size, 1 << Pow2Alignment);
1676 /// ParseDirectiveSubsectionsViaSymbols
1677 /// ::= .subsections_via_symbols
1678 bool DarwinAsmParser::ParseDirectiveSubsectionsViaSymbols(StringRef, SMLoc) {
1679 if (getLexer().isNot(AsmToken::EndOfStatement))
1680 return TokError("unexpected token in '.subsections_via_symbols' directive");
1684 getStreamer().EmitAssemblerFlag(MCAF_SubsectionsViaSymbols);
1689 /// ParseDirectiveAbort
1690 /// ::= .abort [ "abort_string" ]
1691 bool AsmParser::ParseDirectiveAbort() {
1692 // FIXME: Use loc from directive.
1693 SMLoc Loc = getLexer().getLoc();
1696 if (getLexer().isNot(AsmToken::EndOfStatement)) {
1697 if (getLexer().isNot(AsmToken::String))
1698 return TokError("expected string in '.abort' directive");
1700 Str = getTok().getString();
1705 if (getLexer().isNot(AsmToken::EndOfStatement))
1706 return TokError("unexpected token in '.abort' directive");
1710 // FIXME: Handle here.
1712 Error(Loc, ".abort detected. Assembly stopping.");
1714 Error(Loc, ".abort '" + Str + "' detected. Assembly stopping.");
1719 /// ParseDirectiveLsym
1720 /// ::= .lsym identifier , expression
1721 bool DarwinAsmParser::ParseDirectiveLsym(StringRef, SMLoc) {
1723 if (getParser().ParseIdentifier(Name))
1724 return TokError("expected identifier in directive");
1726 // Handle the identifier as the key symbol.
1727 MCSymbol *Sym = getContext().GetOrCreateSymbol(Name);
1729 if (getLexer().isNot(AsmToken::Comma))
1730 return TokError("unexpected token in '.lsym' directive");
1733 const MCExpr *Value;
1734 if (getParser().ParseExpression(Value))
1737 if (getLexer().isNot(AsmToken::EndOfStatement))
1738 return TokError("unexpected token in '.lsym' directive");
1742 // We don't currently support this directive.
1744 // FIXME: Diagnostic location!
1746 return TokError("directive '.lsym' is unsupported");
1749 /// ParseDirectiveInclude
1750 /// ::= .include "filename"
1751 bool AsmParser::ParseDirectiveInclude() {
1752 if (getLexer().isNot(AsmToken::String))
1753 return TokError("expected string in '.include' directive");
1755 std::string Filename = getTok().getString();
1756 SMLoc IncludeLoc = getLexer().getLoc();
1759 if (getLexer().isNot(AsmToken::EndOfStatement))
1760 return TokError("unexpected token in '.include' directive");
1762 // Strip the quotes.
1763 Filename = Filename.substr(1, Filename.size()-2);
1765 // Attempt to switch the lexer to the included file before consuming the end
1766 // of statement to avoid losing it when we switch.
1767 if (EnterIncludeFile(Filename)) {
1768 PrintMessage(IncludeLoc,
1769 "Could not find include file '" + Filename + "'",
1777 /// ParseDirectiveDumpOrLoad
1778 /// ::= ( .dump | .load ) "filename"
1779 bool DarwinAsmParser::ParseDirectiveDumpOrLoad(StringRef Directive,
1781 bool IsDump = Directive == ".dump";
1782 if (getLexer().isNot(AsmToken::String))
1783 return TokError("expected string in '.dump' or '.load' directive");
1787 if (getLexer().isNot(AsmToken::EndOfStatement))
1788 return TokError("unexpected token in '.dump' or '.load' directive");
1792 // FIXME: If/when .dump and .load are implemented they will be done in the
1793 // the assembly parser and not have any need for an MCStreamer API.
1795 Warning(IDLoc, "ignoring directive .dump for now");
1797 Warning(IDLoc, "ignoring directive .load for now");
1802 /// ParseDirectiveSecureLogUnique
1803 /// ::= .secure_log_unique "log message"
1804 bool DarwinAsmParser::ParseDirectiveSecureLogUnique(StringRef, SMLoc IDLoc) {
1805 std::string LogMessage;
1807 if (getLexer().isNot(AsmToken::String))
1810 LogMessage = getTok().getString();
1814 if (getLexer().isNot(AsmToken::EndOfStatement))
1815 return TokError("unexpected token in '.secure_log_unique' directive");
1817 if (getContext().getSecureLogUsed() != false)
1818 return Error(IDLoc, ".secure_log_unique specified multiple times");
1820 char *SecureLogFile = getContext().getSecureLogFile();
1821 if (SecureLogFile == NULL)
1822 return Error(IDLoc, ".secure_log_unique used but AS_SECURE_LOG_FILE "
1823 "environment variable unset.");
1825 raw_ostream *OS = getContext().getSecureLog();
1828 OS = new raw_fd_ostream(SecureLogFile, Err, raw_fd_ostream::F_Append);
1831 return Error(IDLoc, Twine("can't open secure log file: ") +
1832 SecureLogFile + " (" + Err + ")");
1834 getContext().setSecureLog(OS);
1837 int CurBuf = getSourceManager().FindBufferContainingLoc(IDLoc);
1838 *OS << getSourceManager().getBufferInfo(CurBuf).Buffer->getBufferIdentifier()
1839 << ":" << getSourceManager().FindLineNumber(IDLoc, CurBuf) << ":"
1840 << LogMessage + "\n";
1842 getContext().setSecureLogUsed(true);
1847 /// ParseDirectiveSecureLogReset
1848 /// ::= .secure_log_reset
1849 bool DarwinAsmParser::ParseDirectiveSecureLogReset(StringRef, SMLoc IDLoc) {
1850 if (getLexer().isNot(AsmToken::EndOfStatement))
1851 return TokError("unexpected token in '.secure_log_reset' directive");
1855 getContext().setSecureLogUsed(false);
1860 /// ParseDirectiveIf
1861 /// ::= .if expression
1862 bool AsmParser::ParseDirectiveIf(SMLoc DirectiveLoc) {
1863 TheCondStack.push_back(TheCondState);
1864 TheCondState.TheCond = AsmCond::IfCond;
1865 if(TheCondState.Ignore) {
1866 EatToEndOfStatement();
1870 if (ParseAbsoluteExpression(ExprValue))
1873 if (getLexer().isNot(AsmToken::EndOfStatement))
1874 return TokError("unexpected token in '.if' directive");
1878 TheCondState.CondMet = ExprValue;
1879 TheCondState.Ignore = !TheCondState.CondMet;
1885 /// ParseDirectiveElseIf
1886 /// ::= .elseif expression
1887 bool AsmParser::ParseDirectiveElseIf(SMLoc DirectiveLoc) {
1888 if (TheCondState.TheCond != AsmCond::IfCond &&
1889 TheCondState.TheCond != AsmCond::ElseIfCond)
1890 Error(DirectiveLoc, "Encountered a .elseif that doesn't follow a .if or "
1892 TheCondState.TheCond = AsmCond::ElseIfCond;
1894 bool LastIgnoreState = false;
1895 if (!TheCondStack.empty())
1896 LastIgnoreState = TheCondStack.back().Ignore;
1897 if (LastIgnoreState || TheCondState.CondMet) {
1898 TheCondState.Ignore = true;
1899 EatToEndOfStatement();
1903 if (ParseAbsoluteExpression(ExprValue))
1906 if (getLexer().isNot(AsmToken::EndOfStatement))
1907 return TokError("unexpected token in '.elseif' directive");
1910 TheCondState.CondMet = ExprValue;
1911 TheCondState.Ignore = !TheCondState.CondMet;
1917 /// ParseDirectiveElse
1919 bool AsmParser::ParseDirectiveElse(SMLoc DirectiveLoc) {
1920 if (getLexer().isNot(AsmToken::EndOfStatement))
1921 return TokError("unexpected token in '.else' directive");
1925 if (TheCondState.TheCond != AsmCond::IfCond &&
1926 TheCondState.TheCond != AsmCond::ElseIfCond)
1927 Error(DirectiveLoc, "Encountered a .else that doesn't follow a .if or an "
1929 TheCondState.TheCond = AsmCond::ElseCond;
1930 bool LastIgnoreState = false;
1931 if (!TheCondStack.empty())
1932 LastIgnoreState = TheCondStack.back().Ignore;
1933 if (LastIgnoreState || TheCondState.CondMet)
1934 TheCondState.Ignore = true;
1936 TheCondState.Ignore = false;
1941 /// ParseDirectiveEndIf
1943 bool AsmParser::ParseDirectiveEndIf(SMLoc DirectiveLoc) {
1944 if (getLexer().isNot(AsmToken::EndOfStatement))
1945 return TokError("unexpected token in '.endif' directive");
1949 if ((TheCondState.TheCond == AsmCond::NoCond) ||
1950 TheCondStack.empty())
1951 Error(DirectiveLoc, "Encountered a .endif that doesn't follow a .if or "
1953 if (!TheCondStack.empty()) {
1954 TheCondState = TheCondStack.back();
1955 TheCondStack.pop_back();
1961 /// ParseDirectiveFile
1962 /// ::= .file [number] string
1963 bool GenericAsmParser::ParseDirectiveFile(StringRef, SMLoc DirectiveLoc) {
1964 // FIXME: I'm not sure what this is.
1965 int64_t FileNumber = -1;
1966 if (getLexer().is(AsmToken::Integer)) {
1967 FileNumber = getTok().getIntVal();
1971 return TokError("file number less than one");
1974 if (getLexer().isNot(AsmToken::String))
1975 return TokError("unexpected token in '.file' directive");
1977 StringRef Filename = getTok().getString();
1978 Filename = Filename.substr(1, Filename.size()-2);
1981 if (getLexer().isNot(AsmToken::EndOfStatement))
1982 return TokError("unexpected token in '.file' directive");
1984 if (FileNumber == -1)
1985 getStreamer().EmitFileDirective(Filename);
1987 getStreamer().EmitDwarfFileDirective(FileNumber, Filename);
1992 /// ParseDirectiveLine
1993 /// ::= .line [number]
1994 bool GenericAsmParser::ParseDirectiveLine(StringRef, SMLoc DirectiveLoc) {
1995 if (getLexer().isNot(AsmToken::EndOfStatement)) {
1996 if (getLexer().isNot(AsmToken::Integer))
1997 return TokError("unexpected token in '.line' directive");
1999 int64_t LineNumber = getTok().getIntVal();
2003 // FIXME: Do something with the .line.
2006 if (getLexer().isNot(AsmToken::EndOfStatement))
2007 return TokError("unexpected token in '.line' directive");
2013 /// ParseDirectiveLoc
2014 /// ::= .loc number [number [number]]
2015 bool GenericAsmParser::ParseDirectiveLoc(StringRef, SMLoc DirectiveLoc) {
2016 if (getLexer().isNot(AsmToken::Integer))
2017 return TokError("unexpected token in '.loc' directive");
2019 // FIXME: What are these fields?
2020 int64_t FileNumber = getTok().getIntVal();
2022 // FIXME: Validate file.
2025 if (getLexer().isNot(AsmToken::EndOfStatement)) {
2026 if (getLexer().isNot(AsmToken::Integer))
2027 return TokError("unexpected token in '.loc' directive");
2029 int64_t Param2 = getTok().getIntVal();
2033 if (getLexer().isNot(AsmToken::EndOfStatement)) {
2034 if (getLexer().isNot(AsmToken::Integer))
2035 return TokError("unexpected token in '.loc' directive");
2037 int64_t Param3 = getTok().getIntVal();
2041 // FIXME: Do something with the .loc.
2045 if (getLexer().isNot(AsmToken::EndOfStatement))
2046 return TokError("unexpected token in '.file' directive");