AsmParser.cpp revision 202878
1//===- AsmParser.cpp - Parser for Assembly Files --------------------------===// 2// 3// The LLVM Compiler Infrastructure 4// 5// This file is distributed under the University of Illinois Open Source 6// License. See LICENSE.TXT for details. 7// 8//===----------------------------------------------------------------------===// 9// 10// This class implements the parser for assembly files. 11// 12//===----------------------------------------------------------------------===// 13 14#include "llvm/MC/MCParser/AsmParser.h" 15#include "llvm/ADT/SmallString.h" 16#include "llvm/ADT/Twine.h" 17#include "llvm/MC/MCContext.h" 18#include "llvm/MC/MCExpr.h" 19#include "llvm/MC/MCInst.h" 20#include "llvm/MC/MCSectionMachO.h" 21#include "llvm/MC/MCStreamer.h" 22#include "llvm/MC/MCSymbol.h" 23#include "llvm/MC/MCValue.h" 24#include "llvm/MC/MCParser/MCParsedAsmOperand.h" 25#include "llvm/Support/Compiler.h" 26#include "llvm/Support/SourceMgr.h" 27#include "llvm/Support/raw_ostream.h" 28#include "llvm/Target/TargetAsmParser.h" 29using namespace llvm; 30 31 32enum { DEFAULT_ADDRSPACE = 0 }; 33 34// Mach-O section uniquing. 35// 36// FIXME: Figure out where this should live, it should be shared by 37// TargetLoweringObjectFile. 38typedef StringMap<const MCSectionMachO*> MachOUniqueMapTy; 39 40AsmParser::AsmParser(SourceMgr &_SM, MCContext &_Ctx, MCStreamer &_Out, 41 const MCAsmInfo &_MAI) 42 : Lexer(_MAI), Ctx(_Ctx), Out(_Out), SrcMgr(_SM), TargetParser(0), 43 CurBuffer(0), SectionUniquingMap(0) { 44 Lexer.setBuffer(SrcMgr.getMemoryBuffer(CurBuffer)); 45 46 // Debugging directives. 47 AddDirectiveHandler(".file", &AsmParser::ParseDirectiveFile); 48 AddDirectiveHandler(".line", &AsmParser::ParseDirectiveLine); 49 AddDirectiveHandler(".loc", &AsmParser::ParseDirectiveLoc); 50} 51 52 53 54AsmParser::~AsmParser() { 55 // If we have the MachO uniquing map, free it. 56 delete (MachOUniqueMapTy*)SectionUniquingMap; 57} 58 59const MCSection *AsmParser::getMachOSection(const StringRef &Segment, 60 const StringRef &Section, 61 unsigned TypeAndAttributes, 62 unsigned Reserved2, 63 SectionKind Kind) const { 64 // We unique sections by their segment/section pair. The returned section 65 // may not have the same flags as the requested section, if so this should be 66 // diagnosed by the client as an error. 67 68 // Create the map if it doesn't already exist. 69 if (SectionUniquingMap == 0) 70 SectionUniquingMap = new MachOUniqueMapTy(); 71 MachOUniqueMapTy &Map = *(MachOUniqueMapTy*)SectionUniquingMap; 72 73 // Form the name to look up. 74 SmallString<64> Name; 75 Name += Segment; 76 Name.push_back(','); 77 Name += Section; 78 79 // Do the lookup, if we have a hit, return it. 80 const MCSectionMachO *&Entry = Map[Name.str()]; 81 82 // FIXME: This should validate the type and attributes. 83 if (Entry) return Entry; 84 85 // Otherwise, return a new section. 86 return Entry = MCSectionMachO::Create(Segment, Section, TypeAndAttributes, 87 Reserved2, Kind, Ctx); 88} 89 90void AsmParser::Warning(SMLoc L, const Twine &Msg) { 91 PrintMessage(L, Msg.str(), "warning"); 92} 93 94bool AsmParser::Error(SMLoc L, const Twine &Msg) { 95 PrintMessage(L, Msg.str(), "error"); 96 return true; 97} 98 99bool AsmParser::TokError(const char *Msg) { 100 PrintMessage(Lexer.getLoc(), Msg, "error"); 101 return true; 102} 103 104void AsmParser::PrintMessage(SMLoc Loc, const std::string &Msg, 105 const char *Type) const { 106 SrcMgr.PrintMessage(Loc, Msg, Type); 107} 108 109bool AsmParser::EnterIncludeFile(const std::string &Filename) { 110 int NewBuf = SrcMgr.AddIncludeFile(Filename, Lexer.getLoc()); 111 if (NewBuf == -1) 112 return true; 113 114 CurBuffer = NewBuf; 115 116 Lexer.setBuffer(SrcMgr.getMemoryBuffer(CurBuffer)); 117 118 return false; 119} 120 121const AsmToken &AsmParser::Lex() { 122 const AsmToken *tok = &Lexer.Lex(); 123 124 if (tok->is(AsmToken::Eof)) { 125 // If this is the end of an included file, pop the parent file off the 126 // include stack. 127 SMLoc ParentIncludeLoc = SrcMgr.getParentIncludeLoc(CurBuffer); 128 if (ParentIncludeLoc != SMLoc()) { 129 CurBuffer = SrcMgr.FindBufferContainingLoc(ParentIncludeLoc); 130 Lexer.setBuffer(SrcMgr.getMemoryBuffer(CurBuffer), 131 ParentIncludeLoc.getPointer()); 132 tok = &Lexer.Lex(); 133 } 134 } 135 136 if (tok->is(AsmToken::Error)) 137 PrintMessage(Lexer.getErrLoc(), Lexer.getErr(), "error"); 138 139 return *tok; 140} 141 142bool AsmParser::Run() { 143 // Create the initial section. 144 // 145 // FIXME: Support -n. 146 // FIXME: Target hook & command line option for initial section. 147 Out.SwitchSection(getMachOSection("__TEXT", "__text", 148 MCSectionMachO::S_ATTR_PURE_INSTRUCTIONS, 149 0, SectionKind())); 150 151 152 // Prime the lexer. 153 Lex(); 154 155 bool HadError = false; 156 157 AsmCond StartingCondState = TheCondState; 158 159 // While we have input, parse each statement. 160 while (Lexer.isNot(AsmToken::Eof)) { 161 // Handle conditional assembly here before calling ParseStatement() 162 if (Lexer.getKind() == AsmToken::Identifier) { 163 // If we have an identifier, handle it as the key symbol. 164 AsmToken ID = getTok(); 165 SMLoc IDLoc = ID.getLoc(); 166 StringRef IDVal = ID.getString(); 167 168 if (IDVal == ".if" || 169 IDVal == ".elseif" || 170 IDVal == ".else" || 171 IDVal == ".endif") { 172 if (!ParseConditionalAssemblyDirectives(IDVal, IDLoc)) 173 continue; 174 HadError = true; 175 EatToEndOfStatement(); 176 continue; 177 } 178 } 179 if (TheCondState.Ignore) { 180 EatToEndOfStatement(); 181 continue; 182 } 183 184 if (!ParseStatement()) continue; 185 186 // We had an error, remember it and recover by skipping to the next line. 187 HadError = true; 188 EatToEndOfStatement(); 189 } 190 191 if (TheCondState.TheCond != StartingCondState.TheCond || 192 TheCondState.Ignore != StartingCondState.Ignore) 193 return TokError("unmatched .ifs or .elses"); 194 195 if (!HadError) 196 Out.Finish(); 197 198 return HadError; 199} 200 201/// ParseConditionalAssemblyDirectives - parse the conditional assembly 202/// directives 203bool AsmParser::ParseConditionalAssemblyDirectives(StringRef Directive, 204 SMLoc DirectiveLoc) { 205 if (Directive == ".if") 206 return ParseDirectiveIf(DirectiveLoc); 207 if (Directive == ".elseif") 208 return ParseDirectiveElseIf(DirectiveLoc); 209 if (Directive == ".else") 210 return ParseDirectiveElse(DirectiveLoc); 211 if (Directive == ".endif") 212 return ParseDirectiveEndIf(DirectiveLoc); 213 return true; 214} 215 216/// EatToEndOfStatement - Throw away the rest of the line for testing purposes. 217void AsmParser::EatToEndOfStatement() { 218 while (Lexer.isNot(AsmToken::EndOfStatement) && 219 Lexer.isNot(AsmToken::Eof)) 220 Lex(); 221 222 // Eat EOL. 223 if (Lexer.is(AsmToken::EndOfStatement)) 224 Lex(); 225} 226 227 228/// ParseParenExpr - Parse a paren expression and return it. 229/// NOTE: This assumes the leading '(' has already been consumed. 230/// 231/// parenexpr ::= expr) 232/// 233bool AsmParser::ParseParenExpr(const MCExpr *&Res, SMLoc &EndLoc) { 234 if (ParseExpression(Res)) return true; 235 if (Lexer.isNot(AsmToken::RParen)) 236 return TokError("expected ')' in parentheses expression"); 237 EndLoc = Lexer.getLoc(); 238 Lex(); 239 return false; 240} 241 242MCSymbol *AsmParser::CreateSymbol(StringRef Name) { 243 if (MCSymbol *S = Ctx.LookupSymbol(Name)) 244 return S; 245 246 // If the label starts with L it is an assembler temporary label. 247 if (Name.startswith("L")) 248 return Ctx.CreateTemporarySymbol(Name); 249 250 return Ctx.CreateSymbol(Name); 251} 252 253/// ParsePrimaryExpr - Parse a primary expression and return it. 254/// primaryexpr ::= (parenexpr 255/// primaryexpr ::= symbol 256/// primaryexpr ::= number 257/// primaryexpr ::= ~,+,- primaryexpr 258bool AsmParser::ParsePrimaryExpr(const MCExpr *&Res, SMLoc &EndLoc) { 259 switch (Lexer.getKind()) { 260 default: 261 return TokError("unknown token in expression"); 262 case AsmToken::Exclaim: 263 Lex(); // Eat the operator. 264 if (ParsePrimaryExpr(Res, EndLoc)) 265 return true; 266 Res = MCUnaryExpr::CreateLNot(Res, getContext()); 267 return false; 268 case AsmToken::String: 269 case AsmToken::Identifier: { 270 // This is a symbol reference. 271 MCSymbol *Sym = CreateSymbol(getTok().getIdentifier()); 272 EndLoc = Lexer.getLoc(); 273 Lex(); // Eat identifier. 274 275 // If this is an absolute variable reference, substitute it now to preserve 276 // semantics in the face of reassignment. 277 if (Sym->getValue() && isa<MCConstantExpr>(Sym->getValue())) { 278 Res = Sym->getValue(); 279 return false; 280 } 281 282 // Otherwise create a symbol ref. 283 Res = MCSymbolRefExpr::Create(Sym, getContext()); 284 return false; 285 } 286 case AsmToken::Integer: 287 Res = MCConstantExpr::Create(getTok().getIntVal(), getContext()); 288 EndLoc = Lexer.getLoc(); 289 Lex(); // Eat token. 290 return false; 291 case AsmToken::LParen: 292 Lex(); // Eat the '('. 293 return ParseParenExpr(Res, EndLoc); 294 case AsmToken::Minus: 295 Lex(); // Eat the operator. 296 if (ParsePrimaryExpr(Res, EndLoc)) 297 return true; 298 Res = MCUnaryExpr::CreateMinus(Res, getContext()); 299 return false; 300 case AsmToken::Plus: 301 Lex(); // Eat the operator. 302 if (ParsePrimaryExpr(Res, EndLoc)) 303 return true; 304 Res = MCUnaryExpr::CreatePlus(Res, getContext()); 305 return false; 306 case AsmToken::Tilde: 307 Lex(); // Eat the operator. 308 if (ParsePrimaryExpr(Res, EndLoc)) 309 return true; 310 Res = MCUnaryExpr::CreateNot(Res, getContext()); 311 return false; 312 } 313} 314 315bool AsmParser::ParseExpression(const MCExpr *&Res) { 316 SMLoc EndLoc; 317 return ParseExpression(Res, EndLoc); 318} 319 320/// ParseExpression - Parse an expression and return it. 321/// 322/// expr ::= expr +,- expr -> lowest. 323/// expr ::= expr |,^,&,! expr -> middle. 324/// expr ::= expr *,/,%,<<,>> expr -> highest. 325/// expr ::= primaryexpr 326/// 327bool AsmParser::ParseExpression(const MCExpr *&Res, SMLoc &EndLoc) { 328 Res = 0; 329 return ParsePrimaryExpr(Res, EndLoc) || 330 ParseBinOpRHS(1, Res, EndLoc); 331} 332 333bool AsmParser::ParseParenExpression(const MCExpr *&Res, SMLoc &EndLoc) { 334 if (ParseParenExpr(Res, EndLoc)) 335 return true; 336 337 return false; 338} 339 340bool AsmParser::ParseAbsoluteExpression(int64_t &Res) { 341 const MCExpr *Expr; 342 343 SMLoc StartLoc = Lexer.getLoc(); 344 if (ParseExpression(Expr)) 345 return true; 346 347 if (!Expr->EvaluateAsAbsolute(Res)) 348 return Error(StartLoc, "expected absolute expression"); 349 350 return false; 351} 352 353static unsigned getBinOpPrecedence(AsmToken::TokenKind K, 354 MCBinaryExpr::Opcode &Kind) { 355 switch (K) { 356 default: 357 return 0; // not a binop. 358 359 // Lowest Precedence: &&, || 360 case AsmToken::AmpAmp: 361 Kind = MCBinaryExpr::LAnd; 362 return 1; 363 case AsmToken::PipePipe: 364 Kind = MCBinaryExpr::LOr; 365 return 1; 366 367 // Low Precedence: +, -, ==, !=, <>, <, <=, >, >= 368 case AsmToken::Plus: 369 Kind = MCBinaryExpr::Add; 370 return 2; 371 case AsmToken::Minus: 372 Kind = MCBinaryExpr::Sub; 373 return 2; 374 case AsmToken::EqualEqual: 375 Kind = MCBinaryExpr::EQ; 376 return 2; 377 case AsmToken::ExclaimEqual: 378 case AsmToken::LessGreater: 379 Kind = MCBinaryExpr::NE; 380 return 2; 381 case AsmToken::Less: 382 Kind = MCBinaryExpr::LT; 383 return 2; 384 case AsmToken::LessEqual: 385 Kind = MCBinaryExpr::LTE; 386 return 2; 387 case AsmToken::Greater: 388 Kind = MCBinaryExpr::GT; 389 return 2; 390 case AsmToken::GreaterEqual: 391 Kind = MCBinaryExpr::GTE; 392 return 2; 393 394 // Intermediate Precedence: |, &, ^ 395 // 396 // FIXME: gas seems to support '!' as an infix operator? 397 case AsmToken::Pipe: 398 Kind = MCBinaryExpr::Or; 399 return 3; 400 case AsmToken::Caret: 401 Kind = MCBinaryExpr::Xor; 402 return 3; 403 case AsmToken::Amp: 404 Kind = MCBinaryExpr::And; 405 return 3; 406 407 // Highest Precedence: *, /, %, <<, >> 408 case AsmToken::Star: 409 Kind = MCBinaryExpr::Mul; 410 return 4; 411 case AsmToken::Slash: 412 Kind = MCBinaryExpr::Div; 413 return 4; 414 case AsmToken::Percent: 415 Kind = MCBinaryExpr::Mod; 416 return 4; 417 case AsmToken::LessLess: 418 Kind = MCBinaryExpr::Shl; 419 return 4; 420 case AsmToken::GreaterGreater: 421 Kind = MCBinaryExpr::Shr; 422 return 4; 423 } 424} 425 426 427/// ParseBinOpRHS - Parse all binary operators with precedence >= 'Precedence'. 428/// Res contains the LHS of the expression on input. 429bool AsmParser::ParseBinOpRHS(unsigned Precedence, const MCExpr *&Res, 430 SMLoc &EndLoc) { 431 while (1) { 432 MCBinaryExpr::Opcode Kind = MCBinaryExpr::Add; 433 unsigned TokPrec = getBinOpPrecedence(Lexer.getKind(), Kind); 434 435 // If the next token is lower precedence than we are allowed to eat, return 436 // successfully with what we ate already. 437 if (TokPrec < Precedence) 438 return false; 439 440 Lex(); 441 442 // Eat the next primary expression. 443 const MCExpr *RHS; 444 if (ParsePrimaryExpr(RHS, EndLoc)) return true; 445 446 // If BinOp binds less tightly with RHS than the operator after RHS, let 447 // the pending operator take RHS as its LHS. 448 MCBinaryExpr::Opcode Dummy; 449 unsigned NextTokPrec = getBinOpPrecedence(Lexer.getKind(), Dummy); 450 if (TokPrec < NextTokPrec) { 451 if (ParseBinOpRHS(Precedence+1, RHS, EndLoc)) return true; 452 } 453 454 // Merge LHS and RHS according to operator. 455 Res = MCBinaryExpr::Create(Kind, Res, RHS, getContext()); 456 } 457} 458 459 460 461 462/// ParseStatement: 463/// ::= EndOfStatement 464/// ::= Label* Directive ...Operands... EndOfStatement 465/// ::= Label* Identifier OperandList* EndOfStatement 466bool AsmParser::ParseStatement() { 467 if (Lexer.is(AsmToken::EndOfStatement)) { 468 Lex(); 469 return false; 470 } 471 472 // Statements always start with an identifier. 473 AsmToken ID = getTok(); 474 SMLoc IDLoc = ID.getLoc(); 475 StringRef IDVal; 476 if (ParseIdentifier(IDVal)) 477 return TokError("unexpected token at start of statement"); 478 479 // FIXME: Recurse on local labels? 480 481 // See what kind of statement we have. 482 switch (Lexer.getKind()) { 483 case AsmToken::Colon: { 484 // identifier ':' -> Label. 485 Lex(); 486 487 // Diagnose attempt to use a variable as a label. 488 // 489 // FIXME: Diagnostics. Note the location of the definition as a label. 490 // FIXME: This doesn't diagnose assignment to a symbol which has been 491 // implicitly marked as external. 492 MCSymbol *Sym = CreateSymbol(IDVal); 493 if (!Sym->isUndefined()) 494 return Error(IDLoc, "invalid symbol redefinition"); 495 496 // Emit the label. 497 Out.EmitLabel(Sym); 498 499 return ParseStatement(); 500 } 501 502 case AsmToken::Equal: 503 // identifier '=' ... -> assignment statement 504 Lex(); 505 506 return ParseAssignment(IDVal); 507 508 default: // Normal instruction or directive. 509 break; 510 } 511 512 // Otherwise, we have a normal instruction or directive. 513 if (IDVal[0] == '.') { 514 // FIXME: This should be driven based on a hash lookup and callback. 515 if (IDVal == ".section") 516 return ParseDirectiveDarwinSection(); 517 if (IDVal == ".text") 518 // FIXME: This changes behavior based on the -static flag to the 519 // assembler. 520 return ParseDirectiveSectionSwitch("__TEXT", "__text", 521 MCSectionMachO::S_ATTR_PURE_INSTRUCTIONS); 522 if (IDVal == ".const") 523 return ParseDirectiveSectionSwitch("__TEXT", "__const"); 524 if (IDVal == ".static_const") 525 return ParseDirectiveSectionSwitch("__TEXT", "__static_const"); 526 if (IDVal == ".cstring") 527 return ParseDirectiveSectionSwitch("__TEXT","__cstring", 528 MCSectionMachO::S_CSTRING_LITERALS); 529 if (IDVal == ".literal4") 530 return ParseDirectiveSectionSwitch("__TEXT", "__literal4", 531 MCSectionMachO::S_4BYTE_LITERALS, 532 4); 533 if (IDVal == ".literal8") 534 return ParseDirectiveSectionSwitch("__TEXT", "__literal8", 535 MCSectionMachO::S_8BYTE_LITERALS, 536 8); 537 if (IDVal == ".literal16") 538 return ParseDirectiveSectionSwitch("__TEXT","__literal16", 539 MCSectionMachO::S_16BYTE_LITERALS, 540 16); 541 if (IDVal == ".constructor") 542 return ParseDirectiveSectionSwitch("__TEXT","__constructor"); 543 if (IDVal == ".destructor") 544 return ParseDirectiveSectionSwitch("__TEXT","__destructor"); 545 if (IDVal == ".fvmlib_init0") 546 return ParseDirectiveSectionSwitch("__TEXT","__fvmlib_init0"); 547 if (IDVal == ".fvmlib_init1") 548 return ParseDirectiveSectionSwitch("__TEXT","__fvmlib_init1"); 549 550 // FIXME: The assembler manual claims that this has the self modify code 551 // flag, at least on x86-32, but that does not appear to be correct. 552 if (IDVal == ".symbol_stub") 553 return ParseDirectiveSectionSwitch("__TEXT","__symbol_stub", 554 MCSectionMachO::S_SYMBOL_STUBS | 555 MCSectionMachO::S_ATTR_PURE_INSTRUCTIONS, 556 // FIXME: Different on PPC and ARM. 557 0, 16); 558 // FIXME: PowerPC only? 559 if (IDVal == ".picsymbol_stub") 560 return ParseDirectiveSectionSwitch("__TEXT","__picsymbol_stub", 561 MCSectionMachO::S_SYMBOL_STUBS | 562 MCSectionMachO::S_ATTR_PURE_INSTRUCTIONS, 563 0, 26); 564 if (IDVal == ".data") 565 return ParseDirectiveSectionSwitch("__DATA", "__data"); 566 if (IDVal == ".static_data") 567 return ParseDirectiveSectionSwitch("__DATA", "__static_data"); 568 569 // FIXME: The section names of these two are misspelled in the assembler 570 // manual. 571 if (IDVal == ".non_lazy_symbol_pointer") 572 return ParseDirectiveSectionSwitch("__DATA", "__nl_symbol_ptr", 573 MCSectionMachO::S_NON_LAZY_SYMBOL_POINTERS, 574 4); 575 if (IDVal == ".lazy_symbol_pointer") 576 return ParseDirectiveSectionSwitch("__DATA", "__la_symbol_ptr", 577 MCSectionMachO::S_LAZY_SYMBOL_POINTERS, 578 4); 579 580 if (IDVal == ".dyld") 581 return ParseDirectiveSectionSwitch("__DATA", "__dyld"); 582 if (IDVal == ".mod_init_func") 583 return ParseDirectiveSectionSwitch("__DATA", "__mod_init_func", 584 MCSectionMachO::S_MOD_INIT_FUNC_POINTERS, 585 4); 586 if (IDVal == ".mod_term_func") 587 return ParseDirectiveSectionSwitch("__DATA", "__mod_term_func", 588 MCSectionMachO::S_MOD_TERM_FUNC_POINTERS, 589 4); 590 if (IDVal == ".const_data") 591 return ParseDirectiveSectionSwitch("__DATA", "__const"); 592 593 594 if (IDVal == ".objc_class") 595 return ParseDirectiveSectionSwitch("__OBJC", "__class", 596 MCSectionMachO::S_ATTR_NO_DEAD_STRIP); 597 if (IDVal == ".objc_meta_class") 598 return ParseDirectiveSectionSwitch("__OBJC", "__meta_class", 599 MCSectionMachO::S_ATTR_NO_DEAD_STRIP); 600 if (IDVal == ".objc_cat_cls_meth") 601 return ParseDirectiveSectionSwitch("__OBJC", "__cat_cls_meth", 602 MCSectionMachO::S_ATTR_NO_DEAD_STRIP); 603 if (IDVal == ".objc_cat_inst_meth") 604 return ParseDirectiveSectionSwitch("__OBJC", "__cat_inst_meth", 605 MCSectionMachO::S_ATTR_NO_DEAD_STRIP); 606 if (IDVal == ".objc_protocol") 607 return ParseDirectiveSectionSwitch("__OBJC", "__protocol", 608 MCSectionMachO::S_ATTR_NO_DEAD_STRIP); 609 if (IDVal == ".objc_string_object") 610 return ParseDirectiveSectionSwitch("__OBJC", "__string_object", 611 MCSectionMachO::S_ATTR_NO_DEAD_STRIP); 612 if (IDVal == ".objc_cls_meth") 613 return ParseDirectiveSectionSwitch("__OBJC", "__cls_meth", 614 MCSectionMachO::S_ATTR_NO_DEAD_STRIP); 615 if (IDVal == ".objc_inst_meth") 616 return ParseDirectiveSectionSwitch("__OBJC", "__inst_meth", 617 MCSectionMachO::S_ATTR_NO_DEAD_STRIP); 618 if (IDVal == ".objc_cls_refs") 619 return ParseDirectiveSectionSwitch("__OBJC", "__cls_refs", 620 MCSectionMachO::S_ATTR_NO_DEAD_STRIP | 621 MCSectionMachO::S_LITERAL_POINTERS, 622 4); 623 if (IDVal == ".objc_message_refs") 624 return ParseDirectiveSectionSwitch("__OBJC", "__message_refs", 625 MCSectionMachO::S_ATTR_NO_DEAD_STRIP | 626 MCSectionMachO::S_LITERAL_POINTERS, 627 4); 628 if (IDVal == ".objc_symbols") 629 return ParseDirectiveSectionSwitch("__OBJC", "__symbols", 630 MCSectionMachO::S_ATTR_NO_DEAD_STRIP); 631 if (IDVal == ".objc_category") 632 return ParseDirectiveSectionSwitch("__OBJC", "__category", 633 MCSectionMachO::S_ATTR_NO_DEAD_STRIP); 634 if (IDVal == ".objc_class_vars") 635 return ParseDirectiveSectionSwitch("__OBJC", "__class_vars", 636 MCSectionMachO::S_ATTR_NO_DEAD_STRIP); 637 if (IDVal == ".objc_instance_vars") 638 return ParseDirectiveSectionSwitch("__OBJC", "__instance_vars", 639 MCSectionMachO::S_ATTR_NO_DEAD_STRIP); 640 if (IDVal == ".objc_module_info") 641 return ParseDirectiveSectionSwitch("__OBJC", "__module_info", 642 MCSectionMachO::S_ATTR_NO_DEAD_STRIP); 643 if (IDVal == ".objc_class_names") 644 return ParseDirectiveSectionSwitch("__TEXT", "__cstring", 645 MCSectionMachO::S_CSTRING_LITERALS); 646 if (IDVal == ".objc_meth_var_types") 647 return ParseDirectiveSectionSwitch("__TEXT", "__cstring", 648 MCSectionMachO::S_CSTRING_LITERALS); 649 if (IDVal == ".objc_meth_var_names") 650 return ParseDirectiveSectionSwitch("__TEXT", "__cstring", 651 MCSectionMachO::S_CSTRING_LITERALS); 652 if (IDVal == ".objc_selector_strs") 653 return ParseDirectiveSectionSwitch("__OBJC", "__selector_strs", 654 MCSectionMachO::S_CSTRING_LITERALS); 655 656 // Assembler features 657 if (IDVal == ".set") 658 return ParseDirectiveSet(); 659 660 // Data directives 661 662 if (IDVal == ".ascii") 663 return ParseDirectiveAscii(false); 664 if (IDVal == ".asciz") 665 return ParseDirectiveAscii(true); 666 667 if (IDVal == ".byte") 668 return ParseDirectiveValue(1); 669 if (IDVal == ".short") 670 return ParseDirectiveValue(2); 671 if (IDVal == ".long") 672 return ParseDirectiveValue(4); 673 if (IDVal == ".quad") 674 return ParseDirectiveValue(8); 675 676 // FIXME: Target hooks for IsPow2. 677 if (IDVal == ".align") 678 return ParseDirectiveAlign(/*IsPow2=*/true, /*ExprSize=*/1); 679 if (IDVal == ".align32") 680 return ParseDirectiveAlign(/*IsPow2=*/true, /*ExprSize=*/4); 681 if (IDVal == ".balign") 682 return ParseDirectiveAlign(/*IsPow2=*/false, /*ExprSize=*/1); 683 if (IDVal == ".balignw") 684 return ParseDirectiveAlign(/*IsPow2=*/false, /*ExprSize=*/2); 685 if (IDVal == ".balignl") 686 return ParseDirectiveAlign(/*IsPow2=*/false, /*ExprSize=*/4); 687 if (IDVal == ".p2align") 688 return ParseDirectiveAlign(/*IsPow2=*/true, /*ExprSize=*/1); 689 if (IDVal == ".p2alignw") 690 return ParseDirectiveAlign(/*IsPow2=*/true, /*ExprSize=*/2); 691 if (IDVal == ".p2alignl") 692 return ParseDirectiveAlign(/*IsPow2=*/true, /*ExprSize=*/4); 693 694 if (IDVal == ".org") 695 return ParseDirectiveOrg(); 696 697 if (IDVal == ".fill") 698 return ParseDirectiveFill(); 699 if (IDVal == ".space") 700 return ParseDirectiveSpace(); 701 702 // Symbol attribute directives 703 704 if (IDVal == ".globl" || IDVal == ".global") 705 return ParseDirectiveSymbolAttribute(MCSA_Global); 706 if (IDVal == ".hidden") 707 return ParseDirectiveSymbolAttribute(MCSA_Hidden); 708 if (IDVal == ".indirect_symbol") 709 return ParseDirectiveSymbolAttribute(MCSA_IndirectSymbol); 710 if (IDVal == ".internal") 711 return ParseDirectiveSymbolAttribute(MCSA_Internal); 712 if (IDVal == ".lazy_reference") 713 return ParseDirectiveSymbolAttribute(MCSA_LazyReference); 714 if (IDVal == ".no_dead_strip") 715 return ParseDirectiveSymbolAttribute(MCSA_NoDeadStrip); 716 if (IDVal == ".private_extern") 717 return ParseDirectiveSymbolAttribute(MCSA_PrivateExtern); 718 if (IDVal == ".protected") 719 return ParseDirectiveSymbolAttribute(MCSA_Protected); 720 if (IDVal == ".reference") 721 return ParseDirectiveSymbolAttribute(MCSA_Reference); 722 if (IDVal == ".weak") 723 return ParseDirectiveSymbolAttribute(MCSA_Weak); 724 if (IDVal == ".weak_definition") 725 return ParseDirectiveSymbolAttribute(MCSA_WeakDefinition); 726 if (IDVal == ".weak_reference") 727 return ParseDirectiveSymbolAttribute(MCSA_WeakReference); 728 729 if (IDVal == ".comm") 730 return ParseDirectiveComm(/*IsLocal=*/false); 731 if (IDVal == ".lcomm") 732 return ParseDirectiveComm(/*IsLocal=*/true); 733 if (IDVal == ".zerofill") 734 return ParseDirectiveDarwinZerofill(); 735 if (IDVal == ".desc") 736 return ParseDirectiveDarwinSymbolDesc(); 737 if (IDVal == ".lsym") 738 return ParseDirectiveDarwinLsym(); 739 740 if (IDVal == ".subsections_via_symbols") 741 return ParseDirectiveDarwinSubsectionsViaSymbols(); 742 if (IDVal == ".abort") 743 return ParseDirectiveAbort(); 744 if (IDVal == ".include") 745 return ParseDirectiveInclude(); 746 if (IDVal == ".dump") 747 return ParseDirectiveDarwinDumpOrLoad(IDLoc, /*IsDump=*/true); 748 if (IDVal == ".load") 749 return ParseDirectiveDarwinDumpOrLoad(IDLoc, /*IsLoad=*/false); 750 751 // Look up the handler in the handler table, 752 bool(AsmParser::*Handler)(StringRef, SMLoc) = DirectiveMap[IDVal]; 753 if (Handler) 754 return (this->*Handler)(IDVal, IDLoc); 755 756 // Target hook for parsing target specific directives. 757 if (!getTargetParser().ParseDirective(ID)) 758 return false; 759 760 Warning(IDLoc, "ignoring directive for now"); 761 EatToEndOfStatement(); 762 return false; 763 } 764 765 766 SmallVector<MCParsedAsmOperand*, 8> ParsedOperands; 767 if (getTargetParser().ParseInstruction(IDVal, IDLoc, ParsedOperands)) 768 // FIXME: Leaking ParsedOperands on failure. 769 return true; 770 771 if (Lexer.isNot(AsmToken::EndOfStatement)) 772 // FIXME: Leaking ParsedOperands on failure. 773 return TokError("unexpected token in argument list"); 774 775 // Eat the end of statement marker. 776 Lex(); 777 778 779 MCInst Inst; 780 781 bool MatchFail = getTargetParser().MatchInstruction(ParsedOperands, Inst); 782 783 // Free any parsed operands. 784 for (unsigned i = 0, e = ParsedOperands.size(); i != e; ++i) 785 delete ParsedOperands[i]; 786 787 if (MatchFail) { 788 // FIXME: We should give nicer diagnostics about the exact failure. 789 Error(IDLoc, "unrecognized instruction"); 790 return true; 791 } 792 793 // Instruction is good, process it. 794 Out.EmitInstruction(Inst); 795 796 // Skip to end of line for now. 797 return false; 798} 799 800bool AsmParser::ParseAssignment(const StringRef &Name) { 801 // FIXME: Use better location, we should use proper tokens. 802 SMLoc EqualLoc = Lexer.getLoc(); 803 804 const MCExpr *Value; 805 SMLoc StartLoc = Lexer.getLoc(); 806 if (ParseExpression(Value)) 807 return true; 808 809 if (Lexer.isNot(AsmToken::EndOfStatement)) 810 return TokError("unexpected token in assignment"); 811 812 // Eat the end of statement marker. 813 Lex(); 814 815 // Validate that the LHS is allowed to be a variable (either it has not been 816 // used as a symbol, or it is an absolute symbol). 817 MCSymbol *Sym = getContext().LookupSymbol(Name); 818 if (Sym) { 819 // Diagnose assignment to a label. 820 // 821 // FIXME: Diagnostics. Note the location of the definition as a label. 822 // FIXME: Diagnose assignment to protected identifier (e.g., register name). 823 if (!Sym->isUndefined() && !Sym->isAbsolute()) 824 return Error(EqualLoc, "redefinition of '" + Name + "'"); 825 else if (!Sym->isVariable()) 826 return Error(EqualLoc, "invalid assignment to '" + Name + "'"); 827 else if (!isa<MCConstantExpr>(Sym->getValue())) 828 return Error(EqualLoc, "invalid reassignment of non-absolute variable '" + 829 Name + "'"); 830 } else 831 Sym = CreateSymbol(Name); 832 833 // FIXME: Handle '.'. 834 835 // Do the assignment. 836 Out.EmitAssignment(Sym, Value); 837 838 return false; 839} 840 841/// ParseIdentifier: 842/// ::= identifier 843/// ::= string 844bool AsmParser::ParseIdentifier(StringRef &Res) { 845 if (Lexer.isNot(AsmToken::Identifier) && 846 Lexer.isNot(AsmToken::String)) 847 return true; 848 849 Res = getTok().getIdentifier(); 850 851 Lex(); // Consume the identifier token. 852 853 return false; 854} 855 856/// ParseDirectiveSet: 857/// ::= .set identifier ',' expression 858bool AsmParser::ParseDirectiveSet() { 859 StringRef Name; 860 861 if (ParseIdentifier(Name)) 862 return TokError("expected identifier after '.set' directive"); 863 864 if (Lexer.isNot(AsmToken::Comma)) 865 return TokError("unexpected token in '.set'"); 866 Lex(); 867 868 return ParseAssignment(Name); 869} 870 871/// ParseDirectiveSection: 872/// ::= .section identifier (',' identifier)* 873/// FIXME: This should actually parse out the segment, section, attributes and 874/// sizeof_stub fields. 875bool AsmParser::ParseDirectiveDarwinSection() { 876 SMLoc Loc = Lexer.getLoc(); 877 878 StringRef SectionName; 879 if (ParseIdentifier(SectionName)) 880 return Error(Loc, "expected identifier after '.section' directive"); 881 882 // Verify there is a following comma. 883 if (!Lexer.is(AsmToken::Comma)) 884 return TokError("unexpected token in '.section' directive"); 885 886 std::string SectionSpec = SectionName; 887 SectionSpec += ","; 888 889 // Add all the tokens until the end of the line, ParseSectionSpecifier will 890 // handle this. 891 StringRef EOL = Lexer.LexUntilEndOfStatement(); 892 SectionSpec.append(EOL.begin(), EOL.end()); 893 894 Lex(); 895 if (Lexer.isNot(AsmToken::EndOfStatement)) 896 return TokError("unexpected token in '.section' directive"); 897 Lex(); 898 899 900 StringRef Segment, Section; 901 unsigned TAA, StubSize; 902 std::string ErrorStr = 903 MCSectionMachO::ParseSectionSpecifier(SectionSpec, Segment, Section, 904 TAA, StubSize); 905 906 if (!ErrorStr.empty()) 907 return Error(Loc, ErrorStr.c_str()); 908 909 // FIXME: Arch specific. 910 Out.SwitchSection(getMachOSection(Segment, Section, TAA, StubSize, 911 SectionKind())); 912 return false; 913} 914 915/// ParseDirectiveSectionSwitch - 916bool AsmParser::ParseDirectiveSectionSwitch(const char *Segment, 917 const char *Section, 918 unsigned TAA, unsigned Align, 919 unsigned StubSize) { 920 if (Lexer.isNot(AsmToken::EndOfStatement)) 921 return TokError("unexpected token in section switching directive"); 922 Lex(); 923 924 // FIXME: Arch specific. 925 Out.SwitchSection(getMachOSection(Segment, Section, TAA, StubSize, 926 SectionKind())); 927 928 // Set the implicit alignment, if any. 929 // 930 // FIXME: This isn't really what 'as' does; I think it just uses the implicit 931 // alignment on the section (e.g., if one manually inserts bytes into the 932 // section, then just issueing the section switch directive will not realign 933 // the section. However, this is arguably more reasonable behavior, and there 934 // is no good reason for someone to intentionally emit incorrectly sized 935 // values into the implicitly aligned sections. 936 if (Align) 937 Out.EmitValueToAlignment(Align, 0, 1, 0); 938 939 return false; 940} 941 942bool AsmParser::ParseEscapedString(std::string &Data) { 943 assert(Lexer.is(AsmToken::String) && "Unexpected current token!"); 944 945 Data = ""; 946 StringRef Str = getTok().getStringContents(); 947 for (unsigned i = 0, e = Str.size(); i != e; ++i) { 948 if (Str[i] != '\\') { 949 Data += Str[i]; 950 continue; 951 } 952 953 // Recognize escaped characters. Note that this escape semantics currently 954 // loosely follows Darwin 'as'. Notably, it doesn't support hex escapes. 955 ++i; 956 if (i == e) 957 return TokError("unexpected backslash at end of string"); 958 959 // Recognize octal sequences. 960 if ((unsigned) (Str[i] - '0') <= 7) { 961 // Consume up to three octal characters. 962 unsigned Value = Str[i] - '0'; 963 964 if (i + 1 != e && ((unsigned) (Str[i + 1] - '0')) <= 7) { 965 ++i; 966 Value = Value * 8 + (Str[i] - '0'); 967 968 if (i + 1 != e && ((unsigned) (Str[i + 1] - '0')) <= 7) { 969 ++i; 970 Value = Value * 8 + (Str[i] - '0'); 971 } 972 } 973 974 if (Value > 255) 975 return TokError("invalid octal escape sequence (out of range)"); 976 977 Data += (unsigned char) Value; 978 continue; 979 } 980 981 // Otherwise recognize individual escapes. 982 switch (Str[i]) { 983 default: 984 // Just reject invalid escape sequences for now. 985 return TokError("invalid escape sequence (unrecognized character)"); 986 987 case 'b': Data += '\b'; break; 988 case 'f': Data += '\f'; break; 989 case 'n': Data += '\n'; break; 990 case 'r': Data += '\r'; break; 991 case 't': Data += '\t'; break; 992 case '"': Data += '"'; break; 993 case '\\': Data += '\\'; break; 994 } 995 } 996 997 return false; 998} 999 1000/// ParseDirectiveAscii: 1001/// ::= ( .ascii | .asciz ) [ "string" ( , "string" )* ] 1002bool AsmParser::ParseDirectiveAscii(bool ZeroTerminated) { 1003 if (Lexer.isNot(AsmToken::EndOfStatement)) { 1004 for (;;) { 1005 if (Lexer.isNot(AsmToken::String)) 1006 return TokError("expected string in '.ascii' or '.asciz' directive"); 1007 1008 std::string Data; 1009 if (ParseEscapedString(Data)) 1010 return true; 1011 1012 Out.EmitBytes(Data, DEFAULT_ADDRSPACE); 1013 if (ZeroTerminated) 1014 Out.EmitBytes(StringRef("\0", 1), DEFAULT_ADDRSPACE); 1015 1016 Lex(); 1017 1018 if (Lexer.is(AsmToken::EndOfStatement)) 1019 break; 1020 1021 if (Lexer.isNot(AsmToken::Comma)) 1022 return TokError("unexpected token in '.ascii' or '.asciz' directive"); 1023 Lex(); 1024 } 1025 } 1026 1027 Lex(); 1028 return false; 1029} 1030 1031/// ParseDirectiveValue 1032/// ::= (.byte | .short | ... ) [ expression (, expression)* ] 1033bool AsmParser::ParseDirectiveValue(unsigned Size) { 1034 if (Lexer.isNot(AsmToken::EndOfStatement)) { 1035 for (;;) { 1036 const MCExpr *Value; 1037 SMLoc ATTRIBUTE_UNUSED StartLoc = Lexer.getLoc(); 1038 if (ParseExpression(Value)) 1039 return true; 1040 1041 Out.EmitValue(Value, Size, DEFAULT_ADDRSPACE); 1042 1043 if (Lexer.is(AsmToken::EndOfStatement)) 1044 break; 1045 1046 // FIXME: Improve diagnostic. 1047 if (Lexer.isNot(AsmToken::Comma)) 1048 return TokError("unexpected token in directive"); 1049 Lex(); 1050 } 1051 } 1052 1053 Lex(); 1054 return false; 1055} 1056 1057/// ParseDirectiveSpace 1058/// ::= .space expression [ , expression ] 1059bool AsmParser::ParseDirectiveSpace() { 1060 int64_t NumBytes; 1061 if (ParseAbsoluteExpression(NumBytes)) 1062 return true; 1063 1064 int64_t FillExpr = 0; 1065 bool HasFillExpr = false; 1066 if (Lexer.isNot(AsmToken::EndOfStatement)) { 1067 if (Lexer.isNot(AsmToken::Comma)) 1068 return TokError("unexpected token in '.space' directive"); 1069 Lex(); 1070 1071 if (ParseAbsoluteExpression(FillExpr)) 1072 return true; 1073 1074 HasFillExpr = true; 1075 1076 if (Lexer.isNot(AsmToken::EndOfStatement)) 1077 return TokError("unexpected token in '.space' directive"); 1078 } 1079 1080 Lex(); 1081 1082 if (NumBytes <= 0) 1083 return TokError("invalid number of bytes in '.space' directive"); 1084 1085 // FIXME: Sometimes the fill expr is 'nop' if it isn't supplied, instead of 0. 1086 Out.EmitFill(NumBytes, FillExpr, DEFAULT_ADDRSPACE); 1087 1088 return false; 1089} 1090 1091/// ParseDirectiveFill 1092/// ::= .fill expression , expression , expression 1093bool AsmParser::ParseDirectiveFill() { 1094 int64_t NumValues; 1095 if (ParseAbsoluteExpression(NumValues)) 1096 return true; 1097 1098 if (Lexer.isNot(AsmToken::Comma)) 1099 return TokError("unexpected token in '.fill' directive"); 1100 Lex(); 1101 1102 int64_t FillSize; 1103 if (ParseAbsoluteExpression(FillSize)) 1104 return true; 1105 1106 if (Lexer.isNot(AsmToken::Comma)) 1107 return TokError("unexpected token in '.fill' directive"); 1108 Lex(); 1109 1110 int64_t FillExpr; 1111 if (ParseAbsoluteExpression(FillExpr)) 1112 return true; 1113 1114 if (Lexer.isNot(AsmToken::EndOfStatement)) 1115 return TokError("unexpected token in '.fill' directive"); 1116 1117 Lex(); 1118 1119 if (FillSize != 1 && FillSize != 2 && FillSize != 4 && FillSize != 8) 1120 return TokError("invalid '.fill' size, expected 1, 2, 4, or 8"); 1121 1122 for (uint64_t i = 0, e = NumValues; i != e; ++i) 1123 Out.EmitValue(MCConstantExpr::Create(FillExpr, getContext()), FillSize, 1124 DEFAULT_ADDRSPACE); 1125 1126 return false; 1127} 1128 1129/// ParseDirectiveOrg 1130/// ::= .org expression [ , expression ] 1131bool AsmParser::ParseDirectiveOrg() { 1132 const MCExpr *Offset; 1133 SMLoc StartLoc = Lexer.getLoc(); 1134 if (ParseExpression(Offset)) 1135 return true; 1136 1137 // Parse optional fill expression. 1138 int64_t FillExpr = 0; 1139 if (Lexer.isNot(AsmToken::EndOfStatement)) { 1140 if (Lexer.isNot(AsmToken::Comma)) 1141 return TokError("unexpected token in '.org' directive"); 1142 Lex(); 1143 1144 if (ParseAbsoluteExpression(FillExpr)) 1145 return true; 1146 1147 if (Lexer.isNot(AsmToken::EndOfStatement)) 1148 return TokError("unexpected token in '.org' directive"); 1149 } 1150 1151 Lex(); 1152 1153 // FIXME: Only limited forms of relocatable expressions are accepted here, it 1154 // has to be relative to the current section. 1155 Out.EmitValueToOffset(Offset, FillExpr); 1156 1157 return false; 1158} 1159 1160/// ParseDirectiveAlign 1161/// ::= {.align, ...} expression [ , expression [ , expression ]] 1162bool AsmParser::ParseDirectiveAlign(bool IsPow2, unsigned ValueSize) { 1163 SMLoc AlignmentLoc = Lexer.getLoc(); 1164 int64_t Alignment; 1165 if (ParseAbsoluteExpression(Alignment)) 1166 return true; 1167 1168 SMLoc MaxBytesLoc; 1169 bool HasFillExpr = false; 1170 int64_t FillExpr = 0; 1171 int64_t MaxBytesToFill = 0; 1172 if (Lexer.isNot(AsmToken::EndOfStatement)) { 1173 if (Lexer.isNot(AsmToken::Comma)) 1174 return TokError("unexpected token in directive"); 1175 Lex(); 1176 1177 // The fill expression can be omitted while specifying a maximum number of 1178 // alignment bytes, e.g: 1179 // .align 3,,4 1180 if (Lexer.isNot(AsmToken::Comma)) { 1181 HasFillExpr = true; 1182 if (ParseAbsoluteExpression(FillExpr)) 1183 return true; 1184 } 1185 1186 if (Lexer.isNot(AsmToken::EndOfStatement)) { 1187 if (Lexer.isNot(AsmToken::Comma)) 1188 return TokError("unexpected token in directive"); 1189 Lex(); 1190 1191 MaxBytesLoc = Lexer.getLoc(); 1192 if (ParseAbsoluteExpression(MaxBytesToFill)) 1193 return true; 1194 1195 if (Lexer.isNot(AsmToken::EndOfStatement)) 1196 return TokError("unexpected token in directive"); 1197 } 1198 } 1199 1200 Lex(); 1201 1202 if (!HasFillExpr) { 1203 // FIXME: Sometimes fill with nop. 1204 FillExpr = 0; 1205 } 1206 1207 // Compute alignment in bytes. 1208 if (IsPow2) { 1209 // FIXME: Diagnose overflow. 1210 if (Alignment >= 32) { 1211 Error(AlignmentLoc, "invalid alignment value"); 1212 Alignment = 31; 1213 } 1214 1215 Alignment = 1ULL << Alignment; 1216 } 1217 1218 // Diagnose non-sensical max bytes to align. 1219 if (MaxBytesLoc.isValid()) { 1220 if (MaxBytesToFill < 1) { 1221 Error(MaxBytesLoc, "alignment directive can never be satisfied in this " 1222 "many bytes, ignoring maximum bytes expression"); 1223 MaxBytesToFill = 0; 1224 } 1225 1226 if (MaxBytesToFill >= Alignment) { 1227 Warning(MaxBytesLoc, "maximum bytes expression exceeds alignment and " 1228 "has no effect"); 1229 MaxBytesToFill = 0; 1230 } 1231 } 1232 1233 // FIXME: Target specific behavior about how the "extra" bytes are filled. 1234 Out.EmitValueToAlignment(Alignment, FillExpr, ValueSize, MaxBytesToFill); 1235 1236 return false; 1237} 1238 1239/// ParseDirectiveSymbolAttribute 1240/// ::= { ".globl", ".weak", ... } [ identifier ( , identifier )* ] 1241bool AsmParser::ParseDirectiveSymbolAttribute(MCSymbolAttr Attr) { 1242 if (Lexer.isNot(AsmToken::EndOfStatement)) { 1243 for (;;) { 1244 StringRef Name; 1245 1246 if (ParseIdentifier(Name)) 1247 return TokError("expected identifier in directive"); 1248 1249 MCSymbol *Sym = CreateSymbol(Name); 1250 1251 Out.EmitSymbolAttribute(Sym, Attr); 1252 1253 if (Lexer.is(AsmToken::EndOfStatement)) 1254 break; 1255 1256 if (Lexer.isNot(AsmToken::Comma)) 1257 return TokError("unexpected token in directive"); 1258 Lex(); 1259 } 1260 } 1261 1262 Lex(); 1263 return false; 1264} 1265 1266/// ParseDirectiveDarwinSymbolDesc 1267/// ::= .desc identifier , expression 1268bool AsmParser::ParseDirectiveDarwinSymbolDesc() { 1269 StringRef Name; 1270 if (ParseIdentifier(Name)) 1271 return TokError("expected identifier in directive"); 1272 1273 // Handle the identifier as the key symbol. 1274 MCSymbol *Sym = CreateSymbol(Name); 1275 1276 if (Lexer.isNot(AsmToken::Comma)) 1277 return TokError("unexpected token in '.desc' directive"); 1278 Lex(); 1279 1280 SMLoc DescLoc = Lexer.getLoc(); 1281 int64_t DescValue; 1282 if (ParseAbsoluteExpression(DescValue)) 1283 return true; 1284 1285 if (Lexer.isNot(AsmToken::EndOfStatement)) 1286 return TokError("unexpected token in '.desc' directive"); 1287 1288 Lex(); 1289 1290 // Set the n_desc field of this Symbol to this DescValue 1291 Out.EmitSymbolDesc(Sym, DescValue); 1292 1293 return false; 1294} 1295 1296/// ParseDirectiveComm 1297/// ::= ( .comm | .lcomm ) identifier , size_expression [ , align_expression ] 1298bool AsmParser::ParseDirectiveComm(bool IsLocal) { 1299 SMLoc IDLoc = Lexer.getLoc(); 1300 StringRef Name; 1301 if (ParseIdentifier(Name)) 1302 return TokError("expected identifier in directive"); 1303 1304 // Handle the identifier as the key symbol. 1305 MCSymbol *Sym = CreateSymbol(Name); 1306 1307 if (Lexer.isNot(AsmToken::Comma)) 1308 return TokError("unexpected token in directive"); 1309 Lex(); 1310 1311 int64_t Size; 1312 SMLoc SizeLoc = Lexer.getLoc(); 1313 if (ParseAbsoluteExpression(Size)) 1314 return true; 1315 1316 int64_t Pow2Alignment = 0; 1317 SMLoc Pow2AlignmentLoc; 1318 if (Lexer.is(AsmToken::Comma)) { 1319 Lex(); 1320 Pow2AlignmentLoc = Lexer.getLoc(); 1321 if (ParseAbsoluteExpression(Pow2Alignment)) 1322 return true; 1323 1324 // If this target takes alignments in bytes (not log) validate and convert. 1325 if (Lexer.getMAI().getAlignmentIsInBytes()) { 1326 if (!isPowerOf2_64(Pow2Alignment)) 1327 return Error(Pow2AlignmentLoc, "alignment must be a power of 2"); 1328 Pow2Alignment = Log2_64(Pow2Alignment); 1329 } 1330 } 1331 1332 if (Lexer.isNot(AsmToken::EndOfStatement)) 1333 return TokError("unexpected token in '.comm' or '.lcomm' directive"); 1334 1335 Lex(); 1336 1337 // NOTE: a size of zero for a .comm should create a undefined symbol 1338 // but a size of .lcomm creates a bss symbol of size zero. 1339 if (Size < 0) 1340 return Error(SizeLoc, "invalid '.comm' or '.lcomm' directive size, can't " 1341 "be less than zero"); 1342 1343 // NOTE: The alignment in the directive is a power of 2 value, the assember 1344 // may internally end up wanting an alignment in bytes. 1345 // FIXME: Diagnose overflow. 1346 if (Pow2Alignment < 0) 1347 return Error(Pow2AlignmentLoc, "invalid '.comm' or '.lcomm' directive " 1348 "alignment, can't be less than zero"); 1349 1350 if (!Sym->isUndefined()) 1351 return Error(IDLoc, "invalid symbol redefinition"); 1352 1353 // '.lcomm' is equivalent to '.zerofill'. 1354 // Create the Symbol as a common or local common with Size and Pow2Alignment 1355 if (IsLocal) { 1356 Out.EmitZerofill(getMachOSection("__DATA", "__bss", 1357 MCSectionMachO::S_ZEROFILL, 0, 1358 SectionKind()), 1359 Sym, Size, 1 << Pow2Alignment); 1360 return false; 1361 } 1362 1363 Out.EmitCommonSymbol(Sym, Size, 1 << Pow2Alignment); 1364 return false; 1365} 1366 1367/// ParseDirectiveDarwinZerofill 1368/// ::= .zerofill segname , sectname [, identifier , size_expression [ 1369/// , align_expression ]] 1370bool AsmParser::ParseDirectiveDarwinZerofill() { 1371 // FIXME: Handle quoted names here. 1372 1373 if (Lexer.isNot(AsmToken::Identifier)) 1374 return TokError("expected segment name after '.zerofill' directive"); 1375 StringRef Segment = getTok().getString(); 1376 Lex(); 1377 1378 if (Lexer.isNot(AsmToken::Comma)) 1379 return TokError("unexpected token in directive"); 1380 Lex(); 1381 1382 if (Lexer.isNot(AsmToken::Identifier)) 1383 return TokError("expected section name after comma in '.zerofill' " 1384 "directive"); 1385 StringRef Section = getTok().getString(); 1386 Lex(); 1387 1388 // If this is the end of the line all that was wanted was to create the 1389 // the section but with no symbol. 1390 if (Lexer.is(AsmToken::EndOfStatement)) { 1391 // Create the zerofill section but no symbol 1392 Out.EmitZerofill(getMachOSection(Segment, Section, 1393 MCSectionMachO::S_ZEROFILL, 0, 1394 SectionKind())); 1395 return false; 1396 } 1397 1398 if (Lexer.isNot(AsmToken::Comma)) 1399 return TokError("unexpected token in directive"); 1400 Lex(); 1401 1402 if (Lexer.isNot(AsmToken::Identifier)) 1403 return TokError("expected identifier in directive"); 1404 1405 // handle the identifier as the key symbol. 1406 SMLoc IDLoc = Lexer.getLoc(); 1407 MCSymbol *Sym = CreateSymbol(getTok().getString()); 1408 Lex(); 1409 1410 if (Lexer.isNot(AsmToken::Comma)) 1411 return TokError("unexpected token in directive"); 1412 Lex(); 1413 1414 int64_t Size; 1415 SMLoc SizeLoc = Lexer.getLoc(); 1416 if (ParseAbsoluteExpression(Size)) 1417 return true; 1418 1419 int64_t Pow2Alignment = 0; 1420 SMLoc Pow2AlignmentLoc; 1421 if (Lexer.is(AsmToken::Comma)) { 1422 Lex(); 1423 Pow2AlignmentLoc = Lexer.getLoc(); 1424 if (ParseAbsoluteExpression(Pow2Alignment)) 1425 return true; 1426 } 1427 1428 if (Lexer.isNot(AsmToken::EndOfStatement)) 1429 return TokError("unexpected token in '.zerofill' directive"); 1430 1431 Lex(); 1432 1433 if (Size < 0) 1434 return Error(SizeLoc, "invalid '.zerofill' directive size, can't be less " 1435 "than zero"); 1436 1437 // NOTE: The alignment in the directive is a power of 2 value, the assember 1438 // may internally end up wanting an alignment in bytes. 1439 // FIXME: Diagnose overflow. 1440 if (Pow2Alignment < 0) 1441 return Error(Pow2AlignmentLoc, "invalid '.zerofill' directive alignment, " 1442 "can't be less than zero"); 1443 1444 if (!Sym->isUndefined()) 1445 return Error(IDLoc, "invalid symbol redefinition"); 1446 1447 // Create the zerofill Symbol with Size and Pow2Alignment 1448 // 1449 // FIXME: Arch specific. 1450 Out.EmitZerofill(getMachOSection(Segment, Section, 1451 MCSectionMachO::S_ZEROFILL, 0, 1452 SectionKind()), 1453 Sym, Size, 1 << Pow2Alignment); 1454 1455 return false; 1456} 1457 1458/// ParseDirectiveDarwinSubsectionsViaSymbols 1459/// ::= .subsections_via_symbols 1460bool AsmParser::ParseDirectiveDarwinSubsectionsViaSymbols() { 1461 if (Lexer.isNot(AsmToken::EndOfStatement)) 1462 return TokError("unexpected token in '.subsections_via_symbols' directive"); 1463 1464 Lex(); 1465 1466 Out.EmitAssemblerFlag(MCAF_SubsectionsViaSymbols); 1467 1468 return false; 1469} 1470 1471/// ParseDirectiveAbort 1472/// ::= .abort [ "abort_string" ] 1473bool AsmParser::ParseDirectiveAbort() { 1474 // FIXME: Use loc from directive. 1475 SMLoc Loc = Lexer.getLoc(); 1476 1477 StringRef Str = ""; 1478 if (Lexer.isNot(AsmToken::EndOfStatement)) { 1479 if (Lexer.isNot(AsmToken::String)) 1480 return TokError("expected string in '.abort' directive"); 1481 1482 Str = getTok().getString(); 1483 1484 Lex(); 1485 } 1486 1487 if (Lexer.isNot(AsmToken::EndOfStatement)) 1488 return TokError("unexpected token in '.abort' directive"); 1489 1490 Lex(); 1491 1492 // FIXME: Handle here. 1493 if (Str.empty()) 1494 Error(Loc, ".abort detected. Assembly stopping."); 1495 else 1496 Error(Loc, ".abort '" + Str + "' detected. Assembly stopping."); 1497 1498 return false; 1499} 1500 1501/// ParseDirectiveLsym 1502/// ::= .lsym identifier , expression 1503bool AsmParser::ParseDirectiveDarwinLsym() { 1504 StringRef Name; 1505 if (ParseIdentifier(Name)) 1506 return TokError("expected identifier in directive"); 1507 1508 // Handle the identifier as the key symbol. 1509 MCSymbol *Sym = CreateSymbol(Name); 1510 1511 if (Lexer.isNot(AsmToken::Comma)) 1512 return TokError("unexpected token in '.lsym' directive"); 1513 Lex(); 1514 1515 const MCExpr *Value; 1516 SMLoc StartLoc = Lexer.getLoc(); 1517 if (ParseExpression(Value)) 1518 return true; 1519 1520 if (Lexer.isNot(AsmToken::EndOfStatement)) 1521 return TokError("unexpected token in '.lsym' directive"); 1522 1523 Lex(); 1524 1525 // We don't currently support this directive. 1526 // 1527 // FIXME: Diagnostic location! 1528 (void) Sym; 1529 return TokError("directive '.lsym' is unsupported"); 1530} 1531 1532/// ParseDirectiveInclude 1533/// ::= .include "filename" 1534bool AsmParser::ParseDirectiveInclude() { 1535 if (Lexer.isNot(AsmToken::String)) 1536 return TokError("expected string in '.include' directive"); 1537 1538 std::string Filename = getTok().getString(); 1539 SMLoc IncludeLoc = Lexer.getLoc(); 1540 Lex(); 1541 1542 if (Lexer.isNot(AsmToken::EndOfStatement)) 1543 return TokError("unexpected token in '.include' directive"); 1544 1545 // Strip the quotes. 1546 Filename = Filename.substr(1, Filename.size()-2); 1547 1548 // Attempt to switch the lexer to the included file before consuming the end 1549 // of statement to avoid losing it when we switch. 1550 if (EnterIncludeFile(Filename)) { 1551 PrintMessage(IncludeLoc, 1552 "Could not find include file '" + Filename + "'", 1553 "error"); 1554 return true; 1555 } 1556 1557 return false; 1558} 1559 1560/// ParseDirectiveDarwinDumpOrLoad 1561/// ::= ( .dump | .load ) "filename" 1562bool AsmParser::ParseDirectiveDarwinDumpOrLoad(SMLoc IDLoc, bool IsDump) { 1563 if (Lexer.isNot(AsmToken::String)) 1564 return TokError("expected string in '.dump' or '.load' directive"); 1565 1566 Lex(); 1567 1568 if (Lexer.isNot(AsmToken::EndOfStatement)) 1569 return TokError("unexpected token in '.dump' or '.load' directive"); 1570 1571 Lex(); 1572 1573 // FIXME: If/when .dump and .load are implemented they will be done in the 1574 // the assembly parser and not have any need for an MCStreamer API. 1575 if (IsDump) 1576 Warning(IDLoc, "ignoring directive .dump for now"); 1577 else 1578 Warning(IDLoc, "ignoring directive .load for now"); 1579 1580 return false; 1581} 1582 1583/// ParseDirectiveIf 1584/// ::= .if expression 1585bool AsmParser::ParseDirectiveIf(SMLoc DirectiveLoc) { 1586 // Consume the identifier that was the .if directive 1587 Lex(); 1588 1589 TheCondStack.push_back(TheCondState); 1590 TheCondState.TheCond = AsmCond::IfCond; 1591 if(TheCondState.Ignore) { 1592 EatToEndOfStatement(); 1593 } 1594 else { 1595 int64_t ExprValue; 1596 if (ParseAbsoluteExpression(ExprValue)) 1597 return true; 1598 1599 if (Lexer.isNot(AsmToken::EndOfStatement)) 1600 return TokError("unexpected token in '.if' directive"); 1601 1602 Lex(); 1603 1604 TheCondState.CondMet = ExprValue; 1605 TheCondState.Ignore = !TheCondState.CondMet; 1606 } 1607 1608 return false; 1609} 1610 1611/// ParseDirectiveElseIf 1612/// ::= .elseif expression 1613bool AsmParser::ParseDirectiveElseIf(SMLoc DirectiveLoc) { 1614 if (TheCondState.TheCond != AsmCond::IfCond && 1615 TheCondState.TheCond != AsmCond::ElseIfCond) 1616 Error(DirectiveLoc, "Encountered a .elseif that doesn't follow a .if or " 1617 " an .elseif"); 1618 TheCondState.TheCond = AsmCond::ElseIfCond; 1619 1620 // Consume the identifier that was the .elseif directive 1621 Lex(); 1622 1623 bool LastIgnoreState = false; 1624 if (!TheCondStack.empty()) 1625 LastIgnoreState = TheCondStack.back().Ignore; 1626 if (LastIgnoreState || TheCondState.CondMet) { 1627 TheCondState.Ignore = true; 1628 EatToEndOfStatement(); 1629 } 1630 else { 1631 int64_t ExprValue; 1632 if (ParseAbsoluteExpression(ExprValue)) 1633 return true; 1634 1635 if (Lexer.isNot(AsmToken::EndOfStatement)) 1636 return TokError("unexpected token in '.elseif' directive"); 1637 1638 Lex(); 1639 TheCondState.CondMet = ExprValue; 1640 TheCondState.Ignore = !TheCondState.CondMet; 1641 } 1642 1643 return false; 1644} 1645 1646/// ParseDirectiveElse 1647/// ::= .else 1648bool AsmParser::ParseDirectiveElse(SMLoc DirectiveLoc) { 1649 // Consume the identifier that was the .else directive 1650 Lex(); 1651 1652 if (Lexer.isNot(AsmToken::EndOfStatement)) 1653 return TokError("unexpected token in '.else' directive"); 1654 1655 Lex(); 1656 1657 if (TheCondState.TheCond != AsmCond::IfCond && 1658 TheCondState.TheCond != AsmCond::ElseIfCond) 1659 Error(DirectiveLoc, "Encountered a .else that doesn't follow a .if or an " 1660 ".elseif"); 1661 TheCondState.TheCond = AsmCond::ElseCond; 1662 bool LastIgnoreState = false; 1663 if (!TheCondStack.empty()) 1664 LastIgnoreState = TheCondStack.back().Ignore; 1665 if (LastIgnoreState || TheCondState.CondMet) 1666 TheCondState.Ignore = true; 1667 else 1668 TheCondState.Ignore = false; 1669 1670 return false; 1671} 1672 1673/// ParseDirectiveEndIf 1674/// ::= .endif 1675bool AsmParser::ParseDirectiveEndIf(SMLoc DirectiveLoc) { 1676 // Consume the identifier that was the .endif directive 1677 Lex(); 1678 1679 if (Lexer.isNot(AsmToken::EndOfStatement)) 1680 return TokError("unexpected token in '.endif' directive"); 1681 1682 Lex(); 1683 1684 if ((TheCondState.TheCond == AsmCond::NoCond) || 1685 TheCondStack.empty()) 1686 Error(DirectiveLoc, "Encountered a .endif that doesn't follow a .if or " 1687 ".else"); 1688 if (!TheCondStack.empty()) { 1689 TheCondState = TheCondStack.back(); 1690 TheCondStack.pop_back(); 1691 } 1692 1693 return false; 1694} 1695 1696/// ParseDirectiveFile 1697/// ::= .file [number] string 1698bool AsmParser::ParseDirectiveFile(StringRef, SMLoc DirectiveLoc) { 1699 // FIXME: I'm not sure what this is. 1700 int64_t FileNumber = -1; 1701 if (Lexer.is(AsmToken::Integer)) { 1702 FileNumber = getTok().getIntVal(); 1703 Lex(); 1704 1705 if (FileNumber < 1) 1706 return TokError("file number less than one"); 1707 } 1708 1709 if (Lexer.isNot(AsmToken::String)) 1710 return TokError("unexpected token in '.file' directive"); 1711 1712 StringRef ATTRIBUTE_UNUSED FileName = getTok().getString(); 1713 Lex(); 1714 1715 if (Lexer.isNot(AsmToken::EndOfStatement)) 1716 return TokError("unexpected token in '.file' directive"); 1717 1718 // FIXME: Do something with the .file. 1719 1720 return false; 1721} 1722 1723/// ParseDirectiveLine 1724/// ::= .line [number] 1725bool AsmParser::ParseDirectiveLine(StringRef, SMLoc DirectiveLoc) { 1726 if (Lexer.isNot(AsmToken::EndOfStatement)) { 1727 if (Lexer.isNot(AsmToken::Integer)) 1728 return TokError("unexpected token in '.line' directive"); 1729 1730 int64_t LineNumber = getTok().getIntVal(); 1731 (void) LineNumber; 1732 Lex(); 1733 1734 // FIXME: Do something with the .line. 1735 } 1736 1737 if (Lexer.isNot(AsmToken::EndOfStatement)) 1738 return TokError("unexpected token in '.file' directive"); 1739 1740 return false; 1741} 1742 1743 1744/// ParseDirectiveLoc 1745/// ::= .loc number [number [number]] 1746bool AsmParser::ParseDirectiveLoc(StringRef, SMLoc DirectiveLoc) { 1747 if (Lexer.isNot(AsmToken::Integer)) 1748 return TokError("unexpected token in '.loc' directive"); 1749 1750 // FIXME: What are these fields? 1751 int64_t FileNumber = getTok().getIntVal(); 1752 (void) FileNumber; 1753 // FIXME: Validate file. 1754 1755 Lex(); 1756 if (Lexer.isNot(AsmToken::EndOfStatement)) { 1757 if (Lexer.isNot(AsmToken::Integer)) 1758 return TokError("unexpected token in '.loc' directive"); 1759 1760 int64_t Param2 = getTok().getIntVal(); 1761 (void) Param2; 1762 Lex(); 1763 1764 if (Lexer.isNot(AsmToken::EndOfStatement)) { 1765 if (Lexer.isNot(AsmToken::Integer)) 1766 return TokError("unexpected token in '.loc' directive"); 1767 1768 int64_t Param3 = getTok().getIntVal(); 1769 (void) Param3; 1770 Lex(); 1771 1772 // FIXME: Do something with the .loc. 1773 } 1774 } 1775 1776 if (Lexer.isNot(AsmToken::EndOfStatement)) 1777 return TokError("unexpected token in '.file' directive"); 1778 1779 return false; 1780} 1781 1782