1 //===- DarwinAsmParser.cpp - Darwin (Mach-O) Assembly Parser --------------===// 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 #include "llvm/MC/MCParser/MCAsmParserExtension.h" 11 #include "llvm/MC/MCContext.h" 12 #include "llvm/MC/MCSectionMachO.h" 13 #include "llvm/MC/MCStreamer.h" 14 #include "llvm/MC/MCSymbol.h" 15 #include "llvm/MC/MCParser/MCAsmLexer.h" 16 #include "llvm/MC/MCParser/MCAsmParser.h" 17 #include "llvm/ADT/StringSwitch.h" 18 #include "llvm/ADT/StringRef.h" 19 #include "llvm/ADT/Twine.h" 20 #include "llvm/Support/MemoryBuffer.h" 21 #include "llvm/Support/SourceMgr.h" 22 using namespace llvm; 23 24 namespace { 25 26 /// \brief Implementation of directive handling which is shared across all 27 /// Darwin targets. 28 class DarwinAsmParser : public MCAsmParserExtension { 29 template<bool (DarwinAsmParser::*Handler)(StringRef, SMLoc)> 30 void AddDirectiveHandler(StringRef Directive) { 31 getParser().AddDirectiveHandler(this, Directive, 32 HandleDirective<DarwinAsmParser, Handler>); 33 } 34 35 bool ParseSectionSwitch(const char *Segment, const char *Section, 36 unsigned TAA = 0, unsigned ImplicitAlign = 0, 37 unsigned StubSize = 0); 38 39 public: 40 DarwinAsmParser() {} 41 42 virtual void Initialize(MCAsmParser &Parser) { 43 // Call the base implementation. 44 this->MCAsmParserExtension::Initialize(Parser); 45 46 AddDirectiveHandler<&DarwinAsmParser::ParseDirectiveDesc>(".desc"); 47 AddDirectiveHandler<&DarwinAsmParser::ParseDirectiveLsym>(".lsym"); 48 AddDirectiveHandler<&DarwinAsmParser::ParseDirectiveSubsectionsViaSymbols>( 49 ".subsections_via_symbols"); 50 AddDirectiveHandler<&DarwinAsmParser::ParseDirectiveDumpOrLoad>(".dump"); 51 AddDirectiveHandler<&DarwinAsmParser::ParseDirectiveDumpOrLoad>(".load"); 52 AddDirectiveHandler<&DarwinAsmParser::ParseDirectiveSection>(".section"); 53 AddDirectiveHandler<&DarwinAsmParser::ParseDirectivePushSection>(".pushsection"); 54 AddDirectiveHandler<&DarwinAsmParser::ParseDirectivePopSection>(".popsection"); 55 AddDirectiveHandler<&DarwinAsmParser::ParseDirectivePrevious>(".previous"); 56 AddDirectiveHandler<&DarwinAsmParser::ParseDirectiveSecureLogUnique>( 57 ".secure_log_unique"); 58 AddDirectiveHandler<&DarwinAsmParser::ParseDirectiveSecureLogReset>( 59 ".secure_log_reset"); 60 AddDirectiveHandler<&DarwinAsmParser::ParseDirectiveTBSS>(".tbss"); 61 AddDirectiveHandler<&DarwinAsmParser::ParseDirectiveZerofill>(".zerofill"); 62 63 AddDirectiveHandler<&DarwinAsmParser::ParseDirectiveDataRegion>(".data_region"); 64 AddDirectiveHandler<&DarwinAsmParser::ParseDirectiveDataRegionEnd>(".end_data_region"); 65 66 // Special section directives. 67 AddDirectiveHandler<&DarwinAsmParser::ParseSectionDirectiveConst>(".const"); 68 AddDirectiveHandler<&DarwinAsmParser::ParseSectionDirectiveConstData>(".const_data"); 69 AddDirectiveHandler<&DarwinAsmParser::ParseSectionDirectiveConstructor>(".constructor"); 70 AddDirectiveHandler<&DarwinAsmParser::ParseSectionDirectiveCString>(".cstring"); 71 AddDirectiveHandler<&DarwinAsmParser::ParseSectionDirectiveData>(".data"); 72 AddDirectiveHandler<&DarwinAsmParser::ParseSectionDirectiveDestructor>(".destructor"); 73 AddDirectiveHandler<&DarwinAsmParser::ParseSectionDirectiveDyld>(".dyld"); 74 AddDirectiveHandler<&DarwinAsmParser::ParseSectionDirectiveFVMLibInit0>(".fvmlib_init0"); 75 AddDirectiveHandler<&DarwinAsmParser::ParseSectionDirectiveFVMLibInit1>(".fvmlib_init1"); 76 AddDirectiveHandler<&DarwinAsmParser::ParseSectionDirectiveLazySymbolPointers>(".lazy_symbol_pointer"); 77 AddDirectiveHandler<&DarwinAsmParser::ParseSectionDirectiveLiteral16>(".literal16"); 78 AddDirectiveHandler<&DarwinAsmParser::ParseSectionDirectiveLiteral4>(".literal4"); 79 AddDirectiveHandler<&DarwinAsmParser::ParseSectionDirectiveLiteral8>(".literal8"); 80 AddDirectiveHandler<&DarwinAsmParser::ParseSectionDirectiveModInitFunc>(".mod_init_func"); 81 AddDirectiveHandler<&DarwinAsmParser::ParseSectionDirectiveModTermFunc>(".mod_term_func"); 82 AddDirectiveHandler<&DarwinAsmParser::ParseSectionDirectiveNonLazySymbolPointers>(".non_lazy_symbol_pointer"); 83 AddDirectiveHandler<&DarwinAsmParser::ParseSectionDirectiveObjCCatClsMeth>(".objc_cat_cls_meth"); 84 AddDirectiveHandler<&DarwinAsmParser::ParseSectionDirectiveObjCCatInstMeth>(".objc_cat_inst_meth"); 85 AddDirectiveHandler<&DarwinAsmParser::ParseSectionDirectiveObjCCategory>(".objc_category"); 86 AddDirectiveHandler<&DarwinAsmParser::ParseSectionDirectiveObjCClass>(".objc_class"); 87 AddDirectiveHandler<&DarwinAsmParser::ParseSectionDirectiveObjCClassNames>(".objc_class_names"); 88 AddDirectiveHandler<&DarwinAsmParser::ParseSectionDirectiveObjCClassVars>(".objc_class_vars"); 89 AddDirectiveHandler<&DarwinAsmParser::ParseSectionDirectiveObjCClsMeth>(".objc_cls_meth"); 90 AddDirectiveHandler<&DarwinAsmParser::ParseSectionDirectiveObjCClsRefs>(".objc_cls_refs"); 91 AddDirectiveHandler<&DarwinAsmParser::ParseSectionDirectiveObjCInstMeth>(".objc_inst_meth"); 92 AddDirectiveHandler<&DarwinAsmParser::ParseSectionDirectiveObjCInstanceVars>(".objc_instance_vars"); 93 AddDirectiveHandler<&DarwinAsmParser::ParseSectionDirectiveObjCMessageRefs>(".objc_message_refs"); 94 AddDirectiveHandler<&DarwinAsmParser::ParseSectionDirectiveObjCMetaClass>(".objc_meta_class"); 95 AddDirectiveHandler<&DarwinAsmParser::ParseSectionDirectiveObjCMethVarNames>(".objc_meth_var_names"); 96 AddDirectiveHandler<&DarwinAsmParser::ParseSectionDirectiveObjCMethVarTypes>(".objc_meth_var_types"); 97 AddDirectiveHandler<&DarwinAsmParser::ParseSectionDirectiveObjCModuleInfo>(".objc_module_info"); 98 AddDirectiveHandler<&DarwinAsmParser::ParseSectionDirectiveObjCProtocol>(".objc_protocol"); 99 AddDirectiveHandler<&DarwinAsmParser::ParseSectionDirectiveObjCSelectorStrs>(".objc_selector_strs"); 100 AddDirectiveHandler<&DarwinAsmParser::ParseSectionDirectiveObjCStringObject>(".objc_string_object"); 101 AddDirectiveHandler<&DarwinAsmParser::ParseSectionDirectiveObjCSymbols>(".objc_symbols"); 102 AddDirectiveHandler<&DarwinAsmParser::ParseSectionDirectivePICSymbolStub>(".picsymbol_stub"); 103 AddDirectiveHandler<&DarwinAsmParser::ParseSectionDirectiveStaticConst>(".static_const"); 104 AddDirectiveHandler<&DarwinAsmParser::ParseSectionDirectiveStaticData>(".static_data"); 105 AddDirectiveHandler<&DarwinAsmParser::ParseSectionDirectiveSymbolStub>(".symbol_stub"); 106 AddDirectiveHandler<&DarwinAsmParser::ParseSectionDirectiveTData>(".tdata"); 107 AddDirectiveHandler<&DarwinAsmParser::ParseSectionDirectiveText>(".text"); 108 AddDirectiveHandler<&DarwinAsmParser::ParseSectionDirectiveThreadInitFunc>(".thread_init_func"); 109 AddDirectiveHandler<&DarwinAsmParser::ParseSectionDirectiveTLV>(".tlv"); 110 111 AddDirectiveHandler<&DarwinAsmParser::ParseSectionDirectiveIdent>(".ident"); 112 } 113 114 bool ParseDirectiveDesc(StringRef, SMLoc); 115 bool ParseDirectiveDumpOrLoad(StringRef, SMLoc); 116 bool ParseDirectiveLsym(StringRef, SMLoc); 117 bool ParseDirectiveSection(StringRef, SMLoc); 118 bool ParseDirectivePushSection(StringRef, SMLoc); 119 bool ParseDirectivePopSection(StringRef, SMLoc); 120 bool ParseDirectivePrevious(StringRef, SMLoc); 121 bool ParseDirectiveSecureLogReset(StringRef, SMLoc); 122 bool ParseDirectiveSecureLogUnique(StringRef, SMLoc); 123 bool ParseDirectiveSubsectionsViaSymbols(StringRef, SMLoc); 124 bool ParseDirectiveTBSS(StringRef, SMLoc); 125 bool ParseDirectiveZerofill(StringRef, SMLoc); 126 bool ParseDirectiveDataRegion(StringRef, SMLoc); 127 bool ParseDirectiveDataRegionEnd(StringRef, SMLoc); 128 129 // Named Section Directive 130 bool ParseSectionDirectiveConst(StringRef, SMLoc) { 131 return ParseSectionSwitch("__TEXT", "__const"); 132 } 133 bool ParseSectionDirectiveStaticConst(StringRef, SMLoc) { 134 return ParseSectionSwitch("__TEXT", "__static_const"); 135 } 136 bool ParseSectionDirectiveCString(StringRef, SMLoc) { 137 return ParseSectionSwitch("__TEXT","__cstring", 138 MCSectionMachO::S_CSTRING_LITERALS); 139 } 140 bool ParseSectionDirectiveLiteral4(StringRef, SMLoc) { 141 return ParseSectionSwitch("__TEXT", "__literal4", 142 MCSectionMachO::S_4BYTE_LITERALS, 4); 143 } 144 bool ParseSectionDirectiveLiteral8(StringRef, SMLoc) { 145 return ParseSectionSwitch("__TEXT", "__literal8", 146 MCSectionMachO::S_8BYTE_LITERALS, 8); 147 } 148 bool ParseSectionDirectiveLiteral16(StringRef, SMLoc) { 149 return ParseSectionSwitch("__TEXT","__literal16", 150 MCSectionMachO::S_16BYTE_LITERALS, 16); 151 } 152 bool ParseSectionDirectiveConstructor(StringRef, SMLoc) { 153 return ParseSectionSwitch("__TEXT","__constructor"); 154 } 155 bool ParseSectionDirectiveDestructor(StringRef, SMLoc) { 156 return ParseSectionSwitch("__TEXT","__destructor"); 157 } 158 bool ParseSectionDirectiveFVMLibInit0(StringRef, SMLoc) { 159 return ParseSectionSwitch("__TEXT","__fvmlib_init0"); 160 } 161 bool ParseSectionDirectiveFVMLibInit1(StringRef, SMLoc) { 162 return ParseSectionSwitch("__TEXT","__fvmlib_init1"); 163 } 164 bool ParseSectionDirectiveSymbolStub(StringRef, SMLoc) { 165 return ParseSectionSwitch("__TEXT","__symbol_stub", 166 MCSectionMachO::S_SYMBOL_STUBS | 167 MCSectionMachO::S_ATTR_PURE_INSTRUCTIONS, 168 // FIXME: Different on PPC and ARM. 169 0, 16); 170 } 171 bool ParseSectionDirectivePICSymbolStub(StringRef, SMLoc) { 172 return ParseSectionSwitch("__TEXT","__picsymbol_stub", 173 MCSectionMachO::S_SYMBOL_STUBS | 174 MCSectionMachO::S_ATTR_PURE_INSTRUCTIONS, 0, 26); 175 } 176 bool ParseSectionDirectiveData(StringRef, SMLoc) { 177 return ParseSectionSwitch("__DATA", "__data"); 178 } 179 bool ParseSectionDirectiveStaticData(StringRef, SMLoc) { 180 return ParseSectionSwitch("__DATA", "__static_data"); 181 } 182 bool ParseSectionDirectiveNonLazySymbolPointers(StringRef, SMLoc) { 183 return ParseSectionSwitch("__DATA", "__nl_symbol_ptr", 184 MCSectionMachO::S_NON_LAZY_SYMBOL_POINTERS, 4); 185 } 186 bool ParseSectionDirectiveLazySymbolPointers(StringRef, SMLoc) { 187 return ParseSectionSwitch("__DATA", "__la_symbol_ptr", 188 MCSectionMachO::S_LAZY_SYMBOL_POINTERS, 4); 189 } 190 bool ParseSectionDirectiveDyld(StringRef, SMLoc) { 191 return ParseSectionSwitch("__DATA", "__dyld"); 192 } 193 bool ParseSectionDirectiveModInitFunc(StringRef, SMLoc) { 194 return ParseSectionSwitch("__DATA", "__mod_init_func", 195 MCSectionMachO::S_MOD_INIT_FUNC_POINTERS, 4); 196 } 197 bool ParseSectionDirectiveModTermFunc(StringRef, SMLoc) { 198 return ParseSectionSwitch("__DATA", "__mod_term_func", 199 MCSectionMachO::S_MOD_TERM_FUNC_POINTERS, 4); 200 } 201 bool ParseSectionDirectiveConstData(StringRef, SMLoc) { 202 return ParseSectionSwitch("__DATA", "__const"); 203 } 204 bool ParseSectionDirectiveObjCClass(StringRef, SMLoc) { 205 return ParseSectionSwitch("__OBJC", "__class", 206 MCSectionMachO::S_ATTR_NO_DEAD_STRIP); 207 } 208 bool ParseSectionDirectiveObjCMetaClass(StringRef, SMLoc) { 209 return ParseSectionSwitch("__OBJC", "__meta_class", 210 MCSectionMachO::S_ATTR_NO_DEAD_STRIP); 211 } 212 bool ParseSectionDirectiveObjCCatClsMeth(StringRef, SMLoc) { 213 return ParseSectionSwitch("__OBJC", "__cat_cls_meth", 214 MCSectionMachO::S_ATTR_NO_DEAD_STRIP); 215 } 216 bool ParseSectionDirectiveObjCCatInstMeth(StringRef, SMLoc) { 217 return ParseSectionSwitch("__OBJC", "__cat_inst_meth", 218 MCSectionMachO::S_ATTR_NO_DEAD_STRIP); 219 } 220 bool ParseSectionDirectiveObjCProtocol(StringRef, SMLoc) { 221 return ParseSectionSwitch("__OBJC", "__protocol", 222 MCSectionMachO::S_ATTR_NO_DEAD_STRIP); 223 } 224 bool ParseSectionDirectiveObjCStringObject(StringRef, SMLoc) { 225 return ParseSectionSwitch("__OBJC", "__string_object", 226 MCSectionMachO::S_ATTR_NO_DEAD_STRIP); 227 } 228 bool ParseSectionDirectiveObjCClsMeth(StringRef, SMLoc) { 229 return ParseSectionSwitch("__OBJC", "__cls_meth", 230 MCSectionMachO::S_ATTR_NO_DEAD_STRIP); 231 } 232 bool ParseSectionDirectiveObjCInstMeth(StringRef, SMLoc) { 233 return ParseSectionSwitch("__OBJC", "__inst_meth", 234 MCSectionMachO::S_ATTR_NO_DEAD_STRIP); 235 } 236 bool ParseSectionDirectiveObjCClsRefs(StringRef, SMLoc) { 237 return ParseSectionSwitch("__OBJC", "__cls_refs", 238 MCSectionMachO::S_ATTR_NO_DEAD_STRIP | 239 MCSectionMachO::S_LITERAL_POINTERS, 4); 240 } 241 bool ParseSectionDirectiveObjCMessageRefs(StringRef, SMLoc) { 242 return ParseSectionSwitch("__OBJC", "__message_refs", 243 MCSectionMachO::S_ATTR_NO_DEAD_STRIP | 244 MCSectionMachO::S_LITERAL_POINTERS, 4); 245 } 246 bool ParseSectionDirectiveObjCSymbols(StringRef, SMLoc) { 247 return ParseSectionSwitch("__OBJC", "__symbols", 248 MCSectionMachO::S_ATTR_NO_DEAD_STRIP); 249 } 250 bool ParseSectionDirectiveObjCCategory(StringRef, SMLoc) { 251 return ParseSectionSwitch("__OBJC", "__category", 252 MCSectionMachO::S_ATTR_NO_DEAD_STRIP); 253 } 254 bool ParseSectionDirectiveObjCClassVars(StringRef, SMLoc) { 255 return ParseSectionSwitch("__OBJC", "__class_vars", 256 MCSectionMachO::S_ATTR_NO_DEAD_STRIP); 257 } 258 bool ParseSectionDirectiveObjCInstanceVars(StringRef, SMLoc) { 259 return ParseSectionSwitch("__OBJC", "__instance_vars", 260 MCSectionMachO::S_ATTR_NO_DEAD_STRIP); 261 } 262 bool ParseSectionDirectiveObjCModuleInfo(StringRef, SMLoc) { 263 return ParseSectionSwitch("__OBJC", "__module_info", 264 MCSectionMachO::S_ATTR_NO_DEAD_STRIP); 265 } 266 bool ParseSectionDirectiveObjCClassNames(StringRef, SMLoc) { 267 return ParseSectionSwitch("__TEXT", "__cstring", 268 MCSectionMachO::S_CSTRING_LITERALS); 269 } 270 bool ParseSectionDirectiveObjCMethVarTypes(StringRef, SMLoc) { 271 return ParseSectionSwitch("__TEXT", "__cstring", 272 MCSectionMachO::S_CSTRING_LITERALS); 273 } 274 bool ParseSectionDirectiveObjCMethVarNames(StringRef, SMLoc) { 275 return ParseSectionSwitch("__TEXT", "__cstring", 276 MCSectionMachO::S_CSTRING_LITERALS); 277 } 278 bool ParseSectionDirectiveObjCSelectorStrs(StringRef, SMLoc) { 279 return ParseSectionSwitch("__OBJC", "__selector_strs", 280 MCSectionMachO::S_CSTRING_LITERALS); 281 } 282 bool ParseSectionDirectiveTData(StringRef, SMLoc) { 283 return ParseSectionSwitch("__DATA", "__thread_data", 284 MCSectionMachO::S_THREAD_LOCAL_REGULAR); 285 } 286 bool ParseSectionDirectiveText(StringRef, SMLoc) { 287 return ParseSectionSwitch("__TEXT", "__text", 288 MCSectionMachO::S_ATTR_PURE_INSTRUCTIONS); 289 } 290 bool ParseSectionDirectiveTLV(StringRef, SMLoc) { 291 return ParseSectionSwitch("__DATA", "__thread_vars", 292 MCSectionMachO::S_THREAD_LOCAL_VARIABLES); 293 } 294 bool ParseSectionDirectiveIdent(StringRef, SMLoc) { 295 // Darwin silently ignores the .ident directive. 296 getParser().EatToEndOfStatement(); 297 return false; 298 } 299 bool ParseSectionDirectiveThreadInitFunc(StringRef, SMLoc) { 300 return ParseSectionSwitch("__DATA", "__thread_init", 301 MCSectionMachO::S_THREAD_LOCAL_INIT_FUNCTION_POINTERS); 302 } 303 304 }; 305 306 } // end anonymous namespace 307 308 bool DarwinAsmParser::ParseSectionSwitch(const char *Segment, 309 const char *Section, 310 unsigned TAA, unsigned Align, 311 unsigned StubSize) { 312 if (getLexer().isNot(AsmToken::EndOfStatement)) 313 return TokError("unexpected token in section switching directive"); 314 Lex(); 315 316 // FIXME: Arch specific. 317 bool isText = StringRef(Segment) == "__TEXT"; // FIXME: Hack. 318 getStreamer().SwitchSection(getContext().getMachOSection( 319 Segment, Section, TAA, StubSize, 320 isText ? SectionKind::getText() 321 : SectionKind::getDataRel())); 322 323 // Set the implicit alignment, if any. 324 // 325 // FIXME: This isn't really what 'as' does; I think it just uses the implicit 326 // alignment on the section (e.g., if one manually inserts bytes into the 327 // section, then just issuing the section switch directive will not realign 328 // the section. However, this is arguably more reasonable behavior, and there 329 // is no good reason for someone to intentionally emit incorrectly sized 330 // values into the implicitly aligned sections. 331 if (Align) 332 getStreamer().EmitValueToAlignment(Align, 0, 1, 0); 333 334 return false; 335 } 336 337 /// ParseDirectiveDesc 338 /// ::= .desc identifier , expression 339 bool DarwinAsmParser::ParseDirectiveDesc(StringRef, SMLoc) { 340 StringRef Name; 341 if (getParser().ParseIdentifier(Name)) 342 return TokError("expected identifier in directive"); 343 344 // Handle the identifier as the key symbol. 345 MCSymbol *Sym = getContext().GetOrCreateSymbol(Name); 346 347 if (getLexer().isNot(AsmToken::Comma)) 348 return TokError("unexpected token in '.desc' directive"); 349 Lex(); 350 351 int64_t DescValue; 352 if (getParser().ParseAbsoluteExpression(DescValue)) 353 return true; 354 355 if (getLexer().isNot(AsmToken::EndOfStatement)) 356 return TokError("unexpected token in '.desc' directive"); 357 358 Lex(); 359 360 // Set the n_desc field of this Symbol to this DescValue 361 getStreamer().EmitSymbolDesc(Sym, DescValue); 362 363 return false; 364 } 365 366 /// ParseDirectiveDumpOrLoad 367 /// ::= ( .dump | .load ) "filename" 368 bool DarwinAsmParser::ParseDirectiveDumpOrLoad(StringRef Directive, 369 SMLoc IDLoc) { 370 bool IsDump = Directive == ".dump"; 371 if (getLexer().isNot(AsmToken::String)) 372 return TokError("expected string in '.dump' or '.load' directive"); 373 374 Lex(); 375 376 if (getLexer().isNot(AsmToken::EndOfStatement)) 377 return TokError("unexpected token in '.dump' or '.load' directive"); 378 379 Lex(); 380 381 // FIXME: If/when .dump and .load are implemented they will be done in the 382 // the assembly parser and not have any need for an MCStreamer API. 383 if (IsDump) 384 return Warning(IDLoc, "ignoring directive .dump for now"); 385 else 386 return Warning(IDLoc, "ignoring directive .load for now"); 387 } 388 389 /// ParseDirectiveLsym 390 /// ::= .lsym identifier , expression 391 bool DarwinAsmParser::ParseDirectiveLsym(StringRef, SMLoc) { 392 StringRef Name; 393 if (getParser().ParseIdentifier(Name)) 394 return TokError("expected identifier in directive"); 395 396 // Handle the identifier as the key symbol. 397 MCSymbol *Sym = getContext().GetOrCreateSymbol(Name); 398 399 if (getLexer().isNot(AsmToken::Comma)) 400 return TokError("unexpected token in '.lsym' directive"); 401 Lex(); 402 403 const MCExpr *Value; 404 if (getParser().ParseExpression(Value)) 405 return true; 406 407 if (getLexer().isNot(AsmToken::EndOfStatement)) 408 return TokError("unexpected token in '.lsym' directive"); 409 410 Lex(); 411 412 // We don't currently support this directive. 413 // 414 // FIXME: Diagnostic location! 415 (void) Sym; 416 return TokError("directive '.lsym' is unsupported"); 417 } 418 419 /// ParseDirectiveSection: 420 /// ::= .section identifier (',' identifier)* 421 bool DarwinAsmParser::ParseDirectiveSection(StringRef, SMLoc) { 422 SMLoc Loc = getLexer().getLoc(); 423 424 StringRef SectionName; 425 if (getParser().ParseIdentifier(SectionName)) 426 return Error(Loc, "expected identifier after '.section' directive"); 427 428 // Verify there is a following comma. 429 if (!getLexer().is(AsmToken::Comma)) 430 return TokError("unexpected token in '.section' directive"); 431 432 std::string SectionSpec = SectionName; 433 SectionSpec += ","; 434 435 // Add all the tokens until the end of the line, ParseSectionSpecifier will 436 // handle this. 437 StringRef EOL = getLexer().LexUntilEndOfStatement(); 438 SectionSpec.append(EOL.begin(), EOL.end()); 439 440 Lex(); 441 if (getLexer().isNot(AsmToken::EndOfStatement)) 442 return TokError("unexpected token in '.section' directive"); 443 Lex(); 444 445 446 StringRef Segment, Section; 447 unsigned StubSize; 448 unsigned TAA; 449 bool TAAParsed; 450 std::string ErrorStr = 451 MCSectionMachO::ParseSectionSpecifier(SectionSpec, Segment, Section, 452 TAA, TAAParsed, StubSize); 453 454 if (!ErrorStr.empty()) 455 return Error(Loc, ErrorStr.c_str()); 456 457 // FIXME: Arch specific. 458 bool isText = Segment == "__TEXT"; // FIXME: Hack. 459 getStreamer().SwitchSection(getContext().getMachOSection( 460 Segment, Section, TAA, StubSize, 461 isText ? SectionKind::getText() 462 : SectionKind::getDataRel())); 463 return false; 464 } 465 466 /// ParseDirectivePushSection: 467 /// ::= .pushsection identifier (',' identifier)* 468 bool DarwinAsmParser::ParseDirectivePushSection(StringRef S, SMLoc Loc) { 469 getStreamer().PushSection(); 470 471 if (ParseDirectiveSection(S, Loc)) { 472 getStreamer().PopSection(); 473 return true; 474 } 475 476 return false; 477 } 478 479 /// ParseDirectivePopSection: 480 /// ::= .popsection 481 bool DarwinAsmParser::ParseDirectivePopSection(StringRef, SMLoc) { 482 if (!getStreamer().PopSection()) 483 return TokError(".popsection without corresponding .pushsection"); 484 return false; 485 } 486 487 /// ParseDirectivePrevious: 488 /// ::= .previous 489 bool DarwinAsmParser::ParseDirectivePrevious(StringRef DirName, SMLoc) { 490 const MCSection *PreviousSection = getStreamer().getPreviousSection(); 491 if (PreviousSection == NULL) 492 return TokError(".previous without corresponding .section"); 493 getStreamer().SwitchSection(PreviousSection); 494 return false; 495 } 496 497 /// ParseDirectiveSecureLogUnique 498 /// ::= .secure_log_unique ... message ... 499 bool DarwinAsmParser::ParseDirectiveSecureLogUnique(StringRef, SMLoc IDLoc) { 500 StringRef LogMessage = getParser().ParseStringToEndOfStatement(); 501 if (getLexer().isNot(AsmToken::EndOfStatement)) 502 return TokError("unexpected token in '.secure_log_unique' directive"); 503 504 if (getContext().getSecureLogUsed() != false) 505 return Error(IDLoc, ".secure_log_unique specified multiple times"); 506 507 // Get the secure log path. 508 const char *SecureLogFile = getContext().getSecureLogFile(); 509 if (SecureLogFile == NULL) 510 return Error(IDLoc, ".secure_log_unique used but AS_SECURE_LOG_FILE " 511 "environment variable unset."); 512 513 // Open the secure log file if we haven't already. 514 raw_ostream *OS = getContext().getSecureLog(); 515 if (OS == NULL) { 516 std::string Err; 517 OS = new raw_fd_ostream(SecureLogFile, Err, raw_fd_ostream::F_Append); 518 if (!Err.empty()) { 519 delete OS; 520 return Error(IDLoc, Twine("can't open secure log file: ") + 521 SecureLogFile + " (" + Err + ")"); 522 } 523 getContext().setSecureLog(OS); 524 } 525 526 // Write the message. 527 int CurBuf = getSourceManager().FindBufferContainingLoc(IDLoc); 528 *OS << getSourceManager().getBufferInfo(CurBuf).Buffer->getBufferIdentifier() 529 << ":" << getSourceManager().FindLineNumber(IDLoc, CurBuf) << ":" 530 << LogMessage + "\n"; 531 532 getContext().setSecureLogUsed(true); 533 534 return false; 535 } 536 537 /// ParseDirectiveSecureLogReset 538 /// ::= .secure_log_reset 539 bool DarwinAsmParser::ParseDirectiveSecureLogReset(StringRef, SMLoc IDLoc) { 540 if (getLexer().isNot(AsmToken::EndOfStatement)) 541 return TokError("unexpected token in '.secure_log_reset' directive"); 542 543 Lex(); 544 545 getContext().setSecureLogUsed(false); 546 547 return false; 548 } 549 550 /// ParseDirectiveSubsectionsViaSymbols 551 /// ::= .subsections_via_symbols 552 bool DarwinAsmParser::ParseDirectiveSubsectionsViaSymbols(StringRef, SMLoc) { 553 if (getLexer().isNot(AsmToken::EndOfStatement)) 554 return TokError("unexpected token in '.subsections_via_symbols' directive"); 555 556 Lex(); 557 558 getStreamer().EmitAssemblerFlag(MCAF_SubsectionsViaSymbols); 559 560 return false; 561 } 562 563 /// ParseDirectiveTBSS 564 /// ::= .tbss identifier, size, align 565 bool DarwinAsmParser::ParseDirectiveTBSS(StringRef, SMLoc) { 566 SMLoc IDLoc = getLexer().getLoc(); 567 StringRef Name; 568 if (getParser().ParseIdentifier(Name)) 569 return TokError("expected identifier in directive"); 570 571 // Handle the identifier as the key symbol. 572 MCSymbol *Sym = getContext().GetOrCreateSymbol(Name); 573 574 if (getLexer().isNot(AsmToken::Comma)) 575 return TokError("unexpected token in directive"); 576 Lex(); 577 578 int64_t Size; 579 SMLoc SizeLoc = getLexer().getLoc(); 580 if (getParser().ParseAbsoluteExpression(Size)) 581 return true; 582 583 int64_t Pow2Alignment = 0; 584 SMLoc Pow2AlignmentLoc; 585 if (getLexer().is(AsmToken::Comma)) { 586 Lex(); 587 Pow2AlignmentLoc = getLexer().getLoc(); 588 if (getParser().ParseAbsoluteExpression(Pow2Alignment)) 589 return true; 590 } 591 592 if (getLexer().isNot(AsmToken::EndOfStatement)) 593 return TokError("unexpected token in '.tbss' directive"); 594 595 Lex(); 596 597 if (Size < 0) 598 return Error(SizeLoc, "invalid '.tbss' directive size, can't be less than" 599 "zero"); 600 601 // FIXME: Diagnose overflow. 602 if (Pow2Alignment < 0) 603 return Error(Pow2AlignmentLoc, "invalid '.tbss' alignment, can't be less" 604 "than zero"); 605 606 if (!Sym->isUndefined()) 607 return Error(IDLoc, "invalid symbol redefinition"); 608 609 getStreamer().EmitTBSSSymbol(getContext().getMachOSection( 610 "__DATA", "__thread_bss", 611 MCSectionMachO::S_THREAD_LOCAL_ZEROFILL, 612 0, SectionKind::getThreadBSS()), 613 Sym, Size, 1 << Pow2Alignment); 614 615 return false; 616 } 617 618 /// ParseDirectiveZerofill 619 /// ::= .zerofill segname , sectname [, identifier , size_expression [ 620 /// , align_expression ]] 621 bool DarwinAsmParser::ParseDirectiveZerofill(StringRef, SMLoc) { 622 StringRef Segment; 623 if (getParser().ParseIdentifier(Segment)) 624 return TokError("expected segment name after '.zerofill' directive"); 625 626 if (getLexer().isNot(AsmToken::Comma)) 627 return TokError("unexpected token in directive"); 628 Lex(); 629 630 StringRef Section; 631 if (getParser().ParseIdentifier(Section)) 632 return TokError("expected section name after comma in '.zerofill' " 633 "directive"); 634 635 // If this is the end of the line all that was wanted was to create the 636 // the section but with no symbol. 637 if (getLexer().is(AsmToken::EndOfStatement)) { 638 // Create the zerofill section but no symbol 639 getStreamer().EmitZerofill(getContext().getMachOSection( 640 Segment, Section, MCSectionMachO::S_ZEROFILL, 641 0, SectionKind::getBSS())); 642 return false; 643 } 644 645 if (getLexer().isNot(AsmToken::Comma)) 646 return TokError("unexpected token in directive"); 647 Lex(); 648 649 SMLoc IDLoc = getLexer().getLoc(); 650 StringRef IDStr; 651 if (getParser().ParseIdentifier(IDStr)) 652 return TokError("expected identifier in directive"); 653 654 // handle the identifier as the key symbol. 655 MCSymbol *Sym = getContext().GetOrCreateSymbol(IDStr); 656 657 if (getLexer().isNot(AsmToken::Comma)) 658 return TokError("unexpected token in directive"); 659 Lex(); 660 661 int64_t Size; 662 SMLoc SizeLoc = getLexer().getLoc(); 663 if (getParser().ParseAbsoluteExpression(Size)) 664 return true; 665 666 int64_t Pow2Alignment = 0; 667 SMLoc Pow2AlignmentLoc; 668 if (getLexer().is(AsmToken::Comma)) { 669 Lex(); 670 Pow2AlignmentLoc = getLexer().getLoc(); 671 if (getParser().ParseAbsoluteExpression(Pow2Alignment)) 672 return true; 673 } 674 675 if (getLexer().isNot(AsmToken::EndOfStatement)) 676 return TokError("unexpected token in '.zerofill' directive"); 677 678 Lex(); 679 680 if (Size < 0) 681 return Error(SizeLoc, "invalid '.zerofill' directive size, can't be less " 682 "than zero"); 683 684 // NOTE: The alignment in the directive is a power of 2 value, the assembler 685 // may internally end up wanting an alignment in bytes. 686 // FIXME: Diagnose overflow. 687 if (Pow2Alignment < 0) 688 return Error(Pow2AlignmentLoc, "invalid '.zerofill' directive alignment, " 689 "can't be less than zero"); 690 691 if (!Sym->isUndefined()) 692 return Error(IDLoc, "invalid symbol redefinition"); 693 694 // Create the zerofill Symbol with Size and Pow2Alignment 695 // 696 // FIXME: Arch specific. 697 getStreamer().EmitZerofill(getContext().getMachOSection( 698 Segment, Section, MCSectionMachO::S_ZEROFILL, 699 0, SectionKind::getBSS()), 700 Sym, Size, 1 << Pow2Alignment); 701 702 return false; 703 } 704 705 /// ParseDirectiveDataRegion 706 /// ::= .data_region [ ( jt8 | jt16 | jt32 ) ] 707 bool DarwinAsmParser::ParseDirectiveDataRegion(StringRef, SMLoc) { 708 if (getLexer().is(AsmToken::EndOfStatement)) { 709 Lex(); 710 getStreamer().EmitDataRegion(MCDR_DataRegion); 711 return false; 712 } 713 StringRef RegionType; 714 SMLoc Loc = getParser().getTok().getLoc(); 715 if (getParser().ParseIdentifier(RegionType)) 716 return TokError("expected region type after '.data_region' directive"); 717 int Kind = StringSwitch<int>(RegionType) 718 .Case("jt8", MCDR_DataRegionJT8) 719 .Case("jt16", MCDR_DataRegionJT16) 720 .Case("jt32", MCDR_DataRegionJT32) 721 .Default(-1); 722 if (Kind == -1) 723 return Error(Loc, "unknown region type in '.data_region' directive"); 724 Lex(); 725 726 getStreamer().EmitDataRegion((MCDataRegionType)Kind); 727 return false; 728 } 729 730 /// ParseDirectiveDataRegionEnd 731 /// ::= .end_data_region 732 bool DarwinAsmParser::ParseDirectiveDataRegionEnd(StringRef, SMLoc) { 733 if (getLexer().isNot(AsmToken::EndOfStatement)) 734 return TokError("unexpected token in '.end_data_region' directive"); 735 736 Lex(); 737 getStreamer().EmitDataRegion(MCDR_DataRegionEnd); 738 return false; 739 } 740 741 namespace llvm { 742 743 MCAsmParserExtension *createDarwinAsmParser() { 744 return new DarwinAsmParser; 745 } 746 747 } // end llvm namespace 748