1 //===- DarwinAsmParser.cpp - Darwin (Mach-O) Assembly Parser --------------===// 2 // 3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4 // See https://llvm.org/LICENSE.txt for license information. 5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6 // 7 //===----------------------------------------------------------------------===// 8 9 #include "llvm/ADT/STLExtras.h" 10 #include "llvm/ADT/SmallVector.h" 11 #include "llvm/ADT/StringRef.h" 12 #include "llvm/ADT/StringSwitch.h" 13 #include "llvm/ADT/Triple.h" 14 #include "llvm/ADT/Twine.h" 15 #include "llvm/BinaryFormat/MachO.h" 16 #include "llvm/MC/MCContext.h" 17 #include "llvm/MC/MCDirectives.h" 18 #include "llvm/MC/MCObjectFileInfo.h" 19 #include "llvm/MC/MCParser/MCAsmLexer.h" 20 #include "llvm/MC/MCParser/MCAsmParser.h" 21 #include "llvm/MC/MCParser/MCAsmParserExtension.h" 22 #include "llvm/MC/MCSectionMachO.h" 23 #include "llvm/MC/MCStreamer.h" 24 #include "llvm/MC/MCSymbol.h" 25 #include "llvm/MC/SectionKind.h" 26 #include "llvm/Support/Error.h" 27 #include "llvm/Support/FileSystem.h" 28 #include "llvm/Support/MemoryBuffer.h" 29 #include "llvm/Support/SMLoc.h" 30 #include "llvm/Support/SourceMgr.h" 31 #include "llvm/Support/raw_ostream.h" 32 #include <algorithm> 33 #include <cstddef> 34 #include <cstdint> 35 #include <string> 36 #include <system_error> 37 #include <utility> 38 39 using namespace llvm; 40 41 namespace { 42 43 /// Implementation of directive handling which is shared across all 44 /// Darwin targets. 45 class DarwinAsmParser : public MCAsmParserExtension { 46 template<bool (DarwinAsmParser::*HandlerMethod)(StringRef, SMLoc)> 47 void addDirectiveHandler(StringRef Directive) { 48 MCAsmParser::ExtensionDirectiveHandler Handler = std::make_pair( 49 this, HandleDirective<DarwinAsmParser, HandlerMethod>); 50 getParser().addDirectiveHandler(Directive, Handler); 51 } 52 53 bool parseSectionSwitch(StringRef Segment, StringRef Section, 54 unsigned TAA = 0, unsigned ImplicitAlign = 0, 55 unsigned StubSize = 0); 56 57 SMLoc LastVersionDirective; 58 59 public: 60 DarwinAsmParser() = default; 61 62 void Initialize(MCAsmParser &Parser) override { 63 // Call the base implementation. 64 this->MCAsmParserExtension::Initialize(Parser); 65 66 addDirectiveHandler<&DarwinAsmParser::parseDirectiveAltEntry>(".alt_entry"); 67 addDirectiveHandler<&DarwinAsmParser::parseDirectiveDesc>(".desc"); 68 addDirectiveHandler<&DarwinAsmParser::parseDirectiveIndirectSymbol>( 69 ".indirect_symbol"); 70 addDirectiveHandler<&DarwinAsmParser::parseDirectiveLsym>(".lsym"); 71 addDirectiveHandler<&DarwinAsmParser::parseDirectiveSubsectionsViaSymbols>( 72 ".subsections_via_symbols"); 73 addDirectiveHandler<&DarwinAsmParser::parseDirectiveDumpOrLoad>(".dump"); 74 addDirectiveHandler<&DarwinAsmParser::parseDirectiveDumpOrLoad>(".load"); 75 addDirectiveHandler<&DarwinAsmParser::parseDirectiveSection>(".section"); 76 addDirectiveHandler<&DarwinAsmParser::parseDirectivePushSection>( 77 ".pushsection"); 78 addDirectiveHandler<&DarwinAsmParser::parseDirectivePopSection>( 79 ".popsection"); 80 addDirectiveHandler<&DarwinAsmParser::parseDirectivePrevious>(".previous"); 81 addDirectiveHandler<&DarwinAsmParser::parseDirectiveSecureLogUnique>( 82 ".secure_log_unique"); 83 addDirectiveHandler<&DarwinAsmParser::parseDirectiveSecureLogReset>( 84 ".secure_log_reset"); 85 addDirectiveHandler<&DarwinAsmParser::parseDirectiveTBSS>(".tbss"); 86 addDirectiveHandler<&DarwinAsmParser::parseDirectiveZerofill>(".zerofill"); 87 88 addDirectiveHandler<&DarwinAsmParser::parseDirectiveDataRegion>( 89 ".data_region"); 90 addDirectiveHandler<&DarwinAsmParser::parseDirectiveDataRegionEnd>( 91 ".end_data_region"); 92 93 // Special section directives. 94 addDirectiveHandler<&DarwinAsmParser::parseSectionDirectiveBss>(".bss"); 95 addDirectiveHandler<&DarwinAsmParser::parseSectionDirectiveConst>(".const"); 96 addDirectiveHandler<&DarwinAsmParser::parseSectionDirectiveConstData>( 97 ".const_data"); 98 addDirectiveHandler<&DarwinAsmParser::parseSectionDirectiveConstructor>( 99 ".constructor"); 100 addDirectiveHandler<&DarwinAsmParser::parseSectionDirectiveCString>( 101 ".cstring"); 102 addDirectiveHandler<&DarwinAsmParser::parseSectionDirectiveData>(".data"); 103 addDirectiveHandler<&DarwinAsmParser::parseSectionDirectiveDestructor>( 104 ".destructor"); 105 addDirectiveHandler<&DarwinAsmParser::parseSectionDirectiveDyld>(".dyld"); 106 addDirectiveHandler<&DarwinAsmParser::parseSectionDirectiveFVMLibInit0>( 107 ".fvmlib_init0"); 108 addDirectiveHandler<&DarwinAsmParser::parseSectionDirectiveFVMLibInit1>( 109 ".fvmlib_init1"); 110 addDirectiveHandler< 111 &DarwinAsmParser::parseSectionDirectiveLazySymbolPointers>( 112 ".lazy_symbol_pointer"); 113 addDirectiveHandler<&DarwinAsmParser::parseDirectiveLinkerOption>( 114 ".linker_option"); 115 addDirectiveHandler<&DarwinAsmParser::parseSectionDirectiveLiteral16>( 116 ".literal16"); 117 addDirectiveHandler<&DarwinAsmParser::parseSectionDirectiveLiteral4>( 118 ".literal4"); 119 addDirectiveHandler<&DarwinAsmParser::parseSectionDirectiveLiteral8>( 120 ".literal8"); 121 addDirectiveHandler<&DarwinAsmParser::parseSectionDirectiveModInitFunc>( 122 ".mod_init_func"); 123 addDirectiveHandler<&DarwinAsmParser::parseSectionDirectiveModTermFunc>( 124 ".mod_term_func"); 125 addDirectiveHandler< 126 &DarwinAsmParser::parseSectionDirectiveNonLazySymbolPointers>( 127 ".non_lazy_symbol_pointer"); 128 addDirectiveHandler< 129 &DarwinAsmParser::parseSectionDirectiveThreadLocalVariablePointers>( 130 ".thread_local_variable_pointer"); 131 addDirectiveHandler<&DarwinAsmParser::parseSectionDirectiveObjCCatClsMeth>( 132 ".objc_cat_cls_meth"); 133 addDirectiveHandler<&DarwinAsmParser::parseSectionDirectiveObjCCatInstMeth>( 134 ".objc_cat_inst_meth"); 135 addDirectiveHandler<&DarwinAsmParser::parseSectionDirectiveObjCCategory>( 136 ".objc_category"); 137 addDirectiveHandler<&DarwinAsmParser::parseSectionDirectiveObjCClass>( 138 ".objc_class"); 139 addDirectiveHandler<&DarwinAsmParser::parseSectionDirectiveObjCClassNames>( 140 ".objc_class_names"); 141 addDirectiveHandler<&DarwinAsmParser::parseSectionDirectiveObjCClassVars>( 142 ".objc_class_vars"); 143 addDirectiveHandler<&DarwinAsmParser::parseSectionDirectiveObjCClsMeth>( 144 ".objc_cls_meth"); 145 addDirectiveHandler<&DarwinAsmParser::parseSectionDirectiveObjCClsRefs>( 146 ".objc_cls_refs"); 147 addDirectiveHandler<&DarwinAsmParser::parseSectionDirectiveObjCInstMeth>( 148 ".objc_inst_meth"); 149 addDirectiveHandler< 150 &DarwinAsmParser::parseSectionDirectiveObjCInstanceVars>( 151 ".objc_instance_vars"); 152 addDirectiveHandler<&DarwinAsmParser::parseSectionDirectiveObjCMessageRefs>( 153 ".objc_message_refs"); 154 addDirectiveHandler<&DarwinAsmParser::parseSectionDirectiveObjCMetaClass>( 155 ".objc_meta_class"); 156 addDirectiveHandler< 157 &DarwinAsmParser::parseSectionDirectiveObjCMethVarNames>( 158 ".objc_meth_var_names"); 159 addDirectiveHandler< 160 &DarwinAsmParser::parseSectionDirectiveObjCMethVarTypes>( 161 ".objc_meth_var_types"); 162 addDirectiveHandler<&DarwinAsmParser::parseSectionDirectiveObjCModuleInfo>( 163 ".objc_module_info"); 164 addDirectiveHandler<&DarwinAsmParser::parseSectionDirectiveObjCProtocol>( 165 ".objc_protocol"); 166 addDirectiveHandler< 167 &DarwinAsmParser::parseSectionDirectiveObjCSelectorStrs>( 168 ".objc_selector_strs"); 169 addDirectiveHandler< 170 &DarwinAsmParser::parseSectionDirectiveObjCStringObject>( 171 ".objc_string_object"); 172 addDirectiveHandler<&DarwinAsmParser::parseSectionDirectiveObjCSymbols>( 173 ".objc_symbols"); 174 addDirectiveHandler<&DarwinAsmParser::parseSectionDirectivePICSymbolStub>( 175 ".picsymbol_stub"); 176 addDirectiveHandler<&DarwinAsmParser::parseSectionDirectiveStaticConst>( 177 ".static_const"); 178 addDirectiveHandler<&DarwinAsmParser::parseSectionDirectiveStaticData>( 179 ".static_data"); 180 addDirectiveHandler<&DarwinAsmParser::parseSectionDirectiveSymbolStub>( 181 ".symbol_stub"); 182 addDirectiveHandler<&DarwinAsmParser::parseSectionDirectiveTData>(".tdata"); 183 addDirectiveHandler<&DarwinAsmParser::parseSectionDirectiveText>(".text"); 184 addDirectiveHandler<&DarwinAsmParser::parseSectionDirectiveThreadInitFunc>( 185 ".thread_init_func"); 186 addDirectiveHandler<&DarwinAsmParser::parseSectionDirectiveTLV>(".tlv"); 187 188 addDirectiveHandler<&DarwinAsmParser::parseSectionDirectiveIdent>(".ident"); 189 addDirectiveHandler<&DarwinAsmParser::parseWatchOSVersionMin>( 190 ".watchos_version_min"); 191 addDirectiveHandler<&DarwinAsmParser::parseTvOSVersionMin>( 192 ".tvos_version_min"); 193 addDirectiveHandler<&DarwinAsmParser::parseIOSVersionMin>( 194 ".ios_version_min"); 195 addDirectiveHandler<&DarwinAsmParser::parseMacOSXVersionMin>( 196 ".macosx_version_min"); 197 addDirectiveHandler<&DarwinAsmParser::parseBuildVersion>(".build_version"); 198 addDirectiveHandler<&DarwinAsmParser::parseDirectiveCGProfile>( 199 ".cg_profile"); 200 201 LastVersionDirective = SMLoc(); 202 } 203 204 bool parseDirectiveAltEntry(StringRef, SMLoc); 205 bool parseDirectiveDesc(StringRef, SMLoc); 206 bool parseDirectiveIndirectSymbol(StringRef, SMLoc); 207 bool parseDirectiveDumpOrLoad(StringRef, SMLoc); 208 bool parseDirectiveLsym(StringRef, SMLoc); 209 bool parseDirectiveLinkerOption(StringRef, SMLoc); 210 bool parseDirectiveSection(StringRef, SMLoc); 211 bool parseDirectivePushSection(StringRef, SMLoc); 212 bool parseDirectivePopSection(StringRef, SMLoc); 213 bool parseDirectivePrevious(StringRef, SMLoc); 214 bool parseDirectiveSecureLogReset(StringRef, SMLoc); 215 bool parseDirectiveSecureLogUnique(StringRef, SMLoc); 216 bool parseDirectiveSubsectionsViaSymbols(StringRef, SMLoc); 217 bool parseDirectiveTBSS(StringRef, SMLoc); 218 bool parseDirectiveZerofill(StringRef, SMLoc); 219 bool parseDirectiveDataRegion(StringRef, SMLoc); 220 bool parseDirectiveDataRegionEnd(StringRef, SMLoc); 221 222 // Named Section Directive 223 bool parseSectionDirectiveBss(StringRef, SMLoc) { 224 return parseSectionSwitch("__DATA", "__bss"); 225 } 226 227 bool parseSectionDirectiveConst(StringRef, SMLoc) { 228 return parseSectionSwitch("__TEXT", "__const"); 229 } 230 231 bool parseSectionDirectiveStaticConst(StringRef, SMLoc) { 232 return parseSectionSwitch("__TEXT", "__static_const"); 233 } 234 235 bool parseSectionDirectiveCString(StringRef, SMLoc) { 236 return parseSectionSwitch("__TEXT","__cstring", 237 MachO::S_CSTRING_LITERALS); 238 } 239 240 bool parseSectionDirectiveLiteral4(StringRef, SMLoc) { 241 return parseSectionSwitch("__TEXT", "__literal4", 242 MachO::S_4BYTE_LITERALS, 4); 243 } 244 245 bool parseSectionDirectiveLiteral8(StringRef, SMLoc) { 246 return parseSectionSwitch("__TEXT", "__literal8", 247 MachO::S_8BYTE_LITERALS, 8); 248 } 249 250 bool parseSectionDirectiveLiteral16(StringRef, SMLoc) { 251 return parseSectionSwitch("__TEXT","__literal16", 252 MachO::S_16BYTE_LITERALS, 16); 253 } 254 255 bool parseSectionDirectiveConstructor(StringRef, SMLoc) { 256 return parseSectionSwitch("__TEXT","__constructor"); 257 } 258 259 bool parseSectionDirectiveDestructor(StringRef, SMLoc) { 260 return parseSectionSwitch("__TEXT","__destructor"); 261 } 262 263 bool parseSectionDirectiveFVMLibInit0(StringRef, SMLoc) { 264 return parseSectionSwitch("__TEXT","__fvmlib_init0"); 265 } 266 267 bool parseSectionDirectiveFVMLibInit1(StringRef, SMLoc) { 268 return parseSectionSwitch("__TEXT","__fvmlib_init1"); 269 } 270 271 bool parseSectionDirectiveSymbolStub(StringRef, SMLoc) { 272 return parseSectionSwitch("__TEXT","__symbol_stub", 273 MachO::S_SYMBOL_STUBS | 274 MachO::S_ATTR_PURE_INSTRUCTIONS, 275 // FIXME: Different on PPC and ARM. 276 0, 16); 277 } 278 279 bool parseSectionDirectivePICSymbolStub(StringRef, SMLoc) { 280 return parseSectionSwitch("__TEXT","__picsymbol_stub", 281 MachO::S_SYMBOL_STUBS | 282 MachO::S_ATTR_PURE_INSTRUCTIONS, 0, 26); 283 } 284 285 bool parseSectionDirectiveData(StringRef, SMLoc) { 286 return parseSectionSwitch("__DATA", "__data"); 287 } 288 289 bool parseSectionDirectiveStaticData(StringRef, SMLoc) { 290 return parseSectionSwitch("__DATA", "__static_data"); 291 } 292 293 bool parseSectionDirectiveNonLazySymbolPointers(StringRef, SMLoc) { 294 return parseSectionSwitch("__DATA", "__nl_symbol_ptr", 295 MachO::S_NON_LAZY_SYMBOL_POINTERS, 4); 296 } 297 298 bool parseSectionDirectiveLazySymbolPointers(StringRef, SMLoc) { 299 return parseSectionSwitch("__DATA", "__la_symbol_ptr", 300 MachO::S_LAZY_SYMBOL_POINTERS, 4); 301 } 302 303 bool parseSectionDirectiveThreadLocalVariablePointers(StringRef, SMLoc) { 304 return parseSectionSwitch("__DATA", "__thread_ptr", 305 MachO::S_THREAD_LOCAL_VARIABLE_POINTERS, 4); 306 } 307 308 bool parseSectionDirectiveDyld(StringRef, SMLoc) { 309 return parseSectionSwitch("__DATA", "__dyld"); 310 } 311 312 bool parseSectionDirectiveModInitFunc(StringRef, SMLoc) { 313 return parseSectionSwitch("__DATA", "__mod_init_func", 314 MachO::S_MOD_INIT_FUNC_POINTERS, 4); 315 } 316 317 bool parseSectionDirectiveModTermFunc(StringRef, SMLoc) { 318 return parseSectionSwitch("__DATA", "__mod_term_func", 319 MachO::S_MOD_TERM_FUNC_POINTERS, 4); 320 } 321 322 bool parseSectionDirectiveConstData(StringRef, SMLoc) { 323 return parseSectionSwitch("__DATA", "__const"); 324 } 325 326 bool parseSectionDirectiveObjCClass(StringRef, SMLoc) { 327 return parseSectionSwitch("__OBJC", "__class", 328 MachO::S_ATTR_NO_DEAD_STRIP); 329 } 330 331 bool parseSectionDirectiveObjCMetaClass(StringRef, SMLoc) { 332 return parseSectionSwitch("__OBJC", "__meta_class", 333 MachO::S_ATTR_NO_DEAD_STRIP); 334 } 335 336 bool parseSectionDirectiveObjCCatClsMeth(StringRef, SMLoc) { 337 return parseSectionSwitch("__OBJC", "__cat_cls_meth", 338 MachO::S_ATTR_NO_DEAD_STRIP); 339 } 340 341 bool parseSectionDirectiveObjCCatInstMeth(StringRef, SMLoc) { 342 return parseSectionSwitch("__OBJC", "__cat_inst_meth", 343 MachO::S_ATTR_NO_DEAD_STRIP); 344 } 345 346 bool parseSectionDirectiveObjCProtocol(StringRef, SMLoc) { 347 return parseSectionSwitch("__OBJC", "__protocol", 348 MachO::S_ATTR_NO_DEAD_STRIP); 349 } 350 351 bool parseSectionDirectiveObjCStringObject(StringRef, SMLoc) { 352 return parseSectionSwitch("__OBJC", "__string_object", 353 MachO::S_ATTR_NO_DEAD_STRIP); 354 } 355 356 bool parseSectionDirectiveObjCClsMeth(StringRef, SMLoc) { 357 return parseSectionSwitch("__OBJC", "__cls_meth", 358 MachO::S_ATTR_NO_DEAD_STRIP); 359 } 360 361 bool parseSectionDirectiveObjCInstMeth(StringRef, SMLoc) { 362 return parseSectionSwitch("__OBJC", "__inst_meth", 363 MachO::S_ATTR_NO_DEAD_STRIP); 364 } 365 366 bool parseSectionDirectiveObjCClsRefs(StringRef, SMLoc) { 367 return parseSectionSwitch("__OBJC", "__cls_refs", 368 MachO::S_ATTR_NO_DEAD_STRIP | 369 MachO::S_LITERAL_POINTERS, 4); 370 } 371 372 bool parseSectionDirectiveObjCMessageRefs(StringRef, SMLoc) { 373 return parseSectionSwitch("__OBJC", "__message_refs", 374 MachO::S_ATTR_NO_DEAD_STRIP | 375 MachO::S_LITERAL_POINTERS, 4); 376 } 377 378 bool parseSectionDirectiveObjCSymbols(StringRef, SMLoc) { 379 return parseSectionSwitch("__OBJC", "__symbols", 380 MachO::S_ATTR_NO_DEAD_STRIP); 381 } 382 383 bool parseSectionDirectiveObjCCategory(StringRef, SMLoc) { 384 return parseSectionSwitch("__OBJC", "__category", 385 MachO::S_ATTR_NO_DEAD_STRIP); 386 } 387 388 bool parseSectionDirectiveObjCClassVars(StringRef, SMLoc) { 389 return parseSectionSwitch("__OBJC", "__class_vars", 390 MachO::S_ATTR_NO_DEAD_STRIP); 391 } 392 393 bool parseSectionDirectiveObjCInstanceVars(StringRef, SMLoc) { 394 return parseSectionSwitch("__OBJC", "__instance_vars", 395 MachO::S_ATTR_NO_DEAD_STRIP); 396 } 397 398 bool parseSectionDirectiveObjCModuleInfo(StringRef, SMLoc) { 399 return parseSectionSwitch("__OBJC", "__module_info", 400 MachO::S_ATTR_NO_DEAD_STRIP); 401 } 402 403 bool parseSectionDirectiveObjCClassNames(StringRef, SMLoc) { 404 return parseSectionSwitch("__TEXT", "__cstring", 405 MachO::S_CSTRING_LITERALS); 406 } 407 408 bool parseSectionDirectiveObjCMethVarTypes(StringRef, SMLoc) { 409 return parseSectionSwitch("__TEXT", "__cstring", 410 MachO::S_CSTRING_LITERALS); 411 } 412 413 bool parseSectionDirectiveObjCMethVarNames(StringRef, SMLoc) { 414 return parseSectionSwitch("__TEXT", "__cstring", 415 MachO::S_CSTRING_LITERALS); 416 } 417 418 bool parseSectionDirectiveObjCSelectorStrs(StringRef, SMLoc) { 419 return parseSectionSwitch("__OBJC", "__selector_strs", 420 MachO::S_CSTRING_LITERALS); 421 } 422 423 bool parseSectionDirectiveTData(StringRef, SMLoc) { 424 return parseSectionSwitch("__DATA", "__thread_data", 425 MachO::S_THREAD_LOCAL_REGULAR); 426 } 427 428 bool parseSectionDirectiveText(StringRef, SMLoc) { 429 return parseSectionSwitch("__TEXT", "__text", 430 MachO::S_ATTR_PURE_INSTRUCTIONS); 431 } 432 433 bool parseSectionDirectiveTLV(StringRef, SMLoc) { 434 return parseSectionSwitch("__DATA", "__thread_vars", 435 MachO::S_THREAD_LOCAL_VARIABLES); 436 } 437 438 bool parseSectionDirectiveIdent(StringRef, SMLoc) { 439 // Darwin silently ignores the .ident directive. 440 getParser().eatToEndOfStatement(); 441 return false; 442 } 443 444 bool parseSectionDirectiveThreadInitFunc(StringRef, SMLoc) { 445 return parseSectionSwitch("__DATA", "__thread_init", 446 MachO::S_THREAD_LOCAL_INIT_FUNCTION_POINTERS); 447 } 448 449 bool parseWatchOSVersionMin(StringRef Directive, SMLoc Loc) { 450 return parseVersionMin(Directive, Loc, MCVM_WatchOSVersionMin); 451 } 452 bool parseTvOSVersionMin(StringRef Directive, SMLoc Loc) { 453 return parseVersionMin(Directive, Loc, MCVM_TvOSVersionMin); 454 } 455 bool parseIOSVersionMin(StringRef Directive, SMLoc Loc) { 456 return parseVersionMin(Directive, Loc, MCVM_IOSVersionMin); 457 } 458 bool parseMacOSXVersionMin(StringRef Directive, SMLoc Loc) { 459 return parseVersionMin(Directive, Loc, MCVM_OSXVersionMin); 460 } 461 462 bool parseBuildVersion(StringRef Directive, SMLoc Loc); 463 bool parseVersionMin(StringRef Directive, SMLoc Loc, MCVersionMinType Type); 464 bool parseMajorMinorVersionComponent(unsigned *Major, unsigned *Minor, 465 const char *VersionName); 466 bool parseOptionalTrailingVersionComponent(unsigned *Component, 467 const char *ComponentName); 468 bool parseVersion(unsigned *Major, unsigned *Minor, unsigned *Update); 469 bool parseSDKVersion(VersionTuple &SDKVersion); 470 void checkVersion(StringRef Directive, StringRef Arg, SMLoc Loc, 471 Triple::OSType ExpectedOS); 472 bool parseDirectiveCGProfile(StringRef Directive, SMLoc Loc); 473 }; 474 475 } // end anonymous namespace 476 477 bool DarwinAsmParser::parseSectionSwitch(StringRef Segment, StringRef Section, 478 unsigned TAA, unsigned Align, 479 unsigned StubSize) { 480 if (getLexer().isNot(AsmToken::EndOfStatement)) 481 return TokError("unexpected token in section switching directive"); 482 Lex(); 483 484 // FIXME: Arch specific. 485 bool isText = TAA & MachO::S_ATTR_PURE_INSTRUCTIONS; 486 getStreamer().SwitchSection(getContext().getMachOSection( 487 Segment, Section, TAA, StubSize, 488 isText ? SectionKind::getText() : SectionKind::getData())); 489 490 // Set the implicit alignment, if any. 491 // 492 // FIXME: This isn't really what 'as' does; I think it just uses the implicit 493 // alignment on the section (e.g., if one manually inserts bytes into the 494 // section, then just issuing the section switch directive will not realign 495 // the section. However, this is arguably more reasonable behavior, and there 496 // is no good reason for someone to intentionally emit incorrectly sized 497 // values into the implicitly aligned sections. 498 if (Align) 499 getStreamer().emitValueToAlignment(Align); 500 501 return false; 502 } 503 504 /// parseDirectiveAltEntry 505 /// ::= .alt_entry identifier 506 bool DarwinAsmParser::parseDirectiveAltEntry(StringRef, SMLoc) { 507 StringRef Name; 508 if (getParser().parseIdentifier(Name)) 509 return TokError("expected identifier in directive"); 510 511 // Look up symbol. 512 MCSymbol *Sym = getContext().getOrCreateSymbol(Name); 513 514 if (Sym->isDefined()) 515 return TokError(".alt_entry must preceed symbol definition"); 516 517 if (!getStreamer().emitSymbolAttribute(Sym, MCSA_AltEntry)) 518 return TokError("unable to emit symbol attribute"); 519 520 Lex(); 521 return false; 522 } 523 524 /// parseDirectiveDesc 525 /// ::= .desc identifier , expression 526 bool DarwinAsmParser::parseDirectiveDesc(StringRef, SMLoc) { 527 StringRef Name; 528 if (getParser().parseIdentifier(Name)) 529 return TokError("expected identifier in directive"); 530 531 // Handle the identifier as the key symbol. 532 MCSymbol *Sym = getContext().getOrCreateSymbol(Name); 533 534 if (getLexer().isNot(AsmToken::Comma)) 535 return TokError("unexpected token in '.desc' directive"); 536 Lex(); 537 538 int64_t DescValue; 539 if (getParser().parseAbsoluteExpression(DescValue)) 540 return true; 541 542 if (getLexer().isNot(AsmToken::EndOfStatement)) 543 return TokError("unexpected token in '.desc' directive"); 544 545 Lex(); 546 547 // Set the n_desc field of this Symbol to this DescValue 548 getStreamer().emitSymbolDesc(Sym, DescValue); 549 550 return false; 551 } 552 553 /// parseDirectiveIndirectSymbol 554 /// ::= .indirect_symbol identifier 555 bool DarwinAsmParser::parseDirectiveIndirectSymbol(StringRef, SMLoc Loc) { 556 const MCSectionMachO *Current = static_cast<const MCSectionMachO *>( 557 getStreamer().getCurrentSectionOnly()); 558 MachO::SectionType SectionType = Current->getType(); 559 if (SectionType != MachO::S_NON_LAZY_SYMBOL_POINTERS && 560 SectionType != MachO::S_LAZY_SYMBOL_POINTERS && 561 SectionType != MachO::S_THREAD_LOCAL_VARIABLE_POINTERS && 562 SectionType != MachO::S_SYMBOL_STUBS) 563 return Error(Loc, "indirect symbol not in a symbol pointer or stub " 564 "section"); 565 566 StringRef Name; 567 if (getParser().parseIdentifier(Name)) 568 return TokError("expected identifier in .indirect_symbol directive"); 569 570 MCSymbol *Sym = getContext().getOrCreateSymbol(Name); 571 572 // Assembler local symbols don't make any sense here. Complain loudly. 573 if (Sym->isTemporary()) 574 return TokError("non-local symbol required in directive"); 575 576 if (!getStreamer().emitSymbolAttribute(Sym, MCSA_IndirectSymbol)) 577 return TokError("unable to emit indirect symbol attribute for: " + Name); 578 579 if (getLexer().isNot(AsmToken::EndOfStatement)) 580 return TokError("unexpected token in '.indirect_symbol' directive"); 581 582 Lex(); 583 584 return false; 585 } 586 587 /// parseDirectiveDumpOrLoad 588 /// ::= ( .dump | .load ) "filename" 589 bool DarwinAsmParser::parseDirectiveDumpOrLoad(StringRef Directive, 590 SMLoc IDLoc) { 591 bool IsDump = Directive == ".dump"; 592 if (getLexer().isNot(AsmToken::String)) 593 return TokError("expected string in '.dump' or '.load' directive"); 594 595 Lex(); 596 597 if (getLexer().isNot(AsmToken::EndOfStatement)) 598 return TokError("unexpected token in '.dump' or '.load' directive"); 599 600 Lex(); 601 602 // FIXME: If/when .dump and .load are implemented they will be done in the 603 // the assembly parser and not have any need for an MCStreamer API. 604 if (IsDump) 605 return Warning(IDLoc, "ignoring directive .dump for now"); 606 else 607 return Warning(IDLoc, "ignoring directive .load for now"); 608 } 609 610 /// ParseDirectiveLinkerOption 611 /// ::= .linker_option "string" ( , "string" )* 612 bool DarwinAsmParser::parseDirectiveLinkerOption(StringRef IDVal, SMLoc) { 613 SmallVector<std::string, 4> Args; 614 while (true) { 615 if (getLexer().isNot(AsmToken::String)) 616 return TokError("expected string in '" + Twine(IDVal) + "' directive"); 617 618 std::string Data; 619 if (getParser().parseEscapedString(Data)) 620 return true; 621 622 Args.push_back(Data); 623 624 if (getLexer().is(AsmToken::EndOfStatement)) 625 break; 626 627 if (getLexer().isNot(AsmToken::Comma)) 628 return TokError("unexpected token in '" + Twine(IDVal) + "' directive"); 629 Lex(); 630 } 631 632 getStreamer().emitLinkerOptions(Args); 633 return false; 634 } 635 636 /// parseDirectiveLsym 637 /// ::= .lsym identifier , expression 638 bool DarwinAsmParser::parseDirectiveLsym(StringRef, SMLoc) { 639 StringRef Name; 640 if (getParser().parseIdentifier(Name)) 641 return TokError("expected identifier in directive"); 642 643 // Handle the identifier as the key symbol. 644 MCSymbol *Sym = getContext().getOrCreateSymbol(Name); 645 646 if (getLexer().isNot(AsmToken::Comma)) 647 return TokError("unexpected token in '.lsym' directive"); 648 Lex(); 649 650 const MCExpr *Value; 651 if (getParser().parseExpression(Value)) 652 return true; 653 654 if (getLexer().isNot(AsmToken::EndOfStatement)) 655 return TokError("unexpected token in '.lsym' directive"); 656 657 Lex(); 658 659 // We don't currently support this directive. 660 // 661 // FIXME: Diagnostic location! 662 (void) Sym; 663 return TokError("directive '.lsym' is unsupported"); 664 } 665 666 /// parseDirectiveSection: 667 /// ::= .section identifier (',' identifier)* 668 bool DarwinAsmParser::parseDirectiveSection(StringRef, SMLoc) { 669 SMLoc Loc = getLexer().getLoc(); 670 671 StringRef SectionName; 672 if (getParser().parseIdentifier(SectionName)) 673 return Error(Loc, "expected identifier after '.section' directive"); 674 675 // Verify there is a following comma. 676 if (!getLexer().is(AsmToken::Comma)) 677 return TokError("unexpected token in '.section' directive"); 678 679 std::string SectionSpec = std::string(SectionName); 680 SectionSpec += ","; 681 682 // Add all the tokens until the end of the line, ParseSectionSpecifier will 683 // handle this. 684 StringRef EOL = getLexer().LexUntilEndOfStatement(); 685 SectionSpec.append(EOL.begin(), EOL.end()); 686 687 Lex(); 688 if (getLexer().isNot(AsmToken::EndOfStatement)) 689 return TokError("unexpected token in '.section' directive"); 690 Lex(); 691 692 StringRef Segment, Section; 693 unsigned StubSize; 694 unsigned TAA; 695 bool TAAParsed; 696 if (class Error E = MCSectionMachO::ParseSectionSpecifier( 697 SectionSpec, Segment, Section, TAA, TAAParsed, StubSize)) 698 return Error(Loc, toString(std::move(E))); 699 700 // Issue a warning if the target is not powerpc and Section is a *coal* section. 701 Triple TT = getParser().getContext().getTargetTriple(); 702 Triple::ArchType ArchTy = TT.getArch(); 703 704 if (ArchTy != Triple::ppc && ArchTy != Triple::ppc64) { 705 StringRef NonCoalSection = StringSwitch<StringRef>(Section) 706 .Case("__textcoal_nt", "__text") 707 .Case("__const_coal", "__const") 708 .Case("__datacoal_nt", "__data") 709 .Default(Section); 710 711 if (!Section.equals(NonCoalSection)) { 712 StringRef SectionVal(Loc.getPointer()); 713 size_t B = SectionVal.find(',') + 1, E = SectionVal.find(',', B); 714 SMLoc BLoc = SMLoc::getFromPointer(SectionVal.data() + B); 715 SMLoc ELoc = SMLoc::getFromPointer(SectionVal.data() + E); 716 getParser().Warning(Loc, "section \"" + Section + "\" is deprecated", 717 SMRange(BLoc, ELoc)); 718 getParser().Note(Loc, "change section name to \"" + NonCoalSection + 719 "\"", SMRange(BLoc, ELoc)); 720 } 721 } 722 723 // FIXME: Arch specific. 724 bool isText = Segment == "__TEXT"; // FIXME: Hack. 725 getStreamer().SwitchSection(getContext().getMachOSection( 726 Segment, Section, TAA, StubSize, 727 isText ? SectionKind::getText() : SectionKind::getData())); 728 return false; 729 } 730 731 /// ParseDirectivePushSection: 732 /// ::= .pushsection identifier (',' identifier)* 733 bool DarwinAsmParser::parseDirectivePushSection(StringRef S, SMLoc Loc) { 734 getStreamer().PushSection(); 735 736 if (parseDirectiveSection(S, Loc)) { 737 getStreamer().PopSection(); 738 return true; 739 } 740 741 return false; 742 } 743 744 /// ParseDirectivePopSection: 745 /// ::= .popsection 746 bool DarwinAsmParser::parseDirectivePopSection(StringRef, SMLoc) { 747 if (!getStreamer().PopSection()) 748 return TokError(".popsection without corresponding .pushsection"); 749 return false; 750 } 751 752 /// ParseDirectivePrevious: 753 /// ::= .previous 754 bool DarwinAsmParser::parseDirectivePrevious(StringRef DirName, SMLoc) { 755 MCSectionSubPair PreviousSection = getStreamer().getPreviousSection(); 756 if (!PreviousSection.first) 757 return TokError(".previous without corresponding .section"); 758 getStreamer().SwitchSection(PreviousSection.first, PreviousSection.second); 759 return false; 760 } 761 762 /// ParseDirectiveSecureLogUnique 763 /// ::= .secure_log_unique ... message ... 764 bool DarwinAsmParser::parseDirectiveSecureLogUnique(StringRef, SMLoc IDLoc) { 765 StringRef LogMessage = getParser().parseStringToEndOfStatement(); 766 if (getLexer().isNot(AsmToken::EndOfStatement)) 767 return TokError("unexpected token in '.secure_log_unique' directive"); 768 769 if (getContext().getSecureLogUsed()) 770 return Error(IDLoc, ".secure_log_unique specified multiple times"); 771 772 // Get the secure log path. 773 const char *SecureLogFile = getContext().getSecureLogFile(); 774 if (!SecureLogFile) 775 return Error(IDLoc, ".secure_log_unique used but AS_SECURE_LOG_FILE " 776 "environment variable unset."); 777 778 // Open the secure log file if we haven't already. 779 raw_fd_ostream *OS = getContext().getSecureLog(); 780 if (!OS) { 781 std::error_code EC; 782 auto NewOS = std::make_unique<raw_fd_ostream>(StringRef(SecureLogFile), EC, 783 sys::fs::OF_Append | 784 sys::fs::OF_TextWithCRLF); 785 if (EC) 786 return Error(IDLoc, Twine("can't open secure log file: ") + 787 SecureLogFile + " (" + EC.message() + ")"); 788 OS = NewOS.get(); 789 getContext().setSecureLog(std::move(NewOS)); 790 } 791 792 // Write the message. 793 unsigned CurBuf = getSourceManager().FindBufferContainingLoc(IDLoc); 794 *OS << getSourceManager().getBufferInfo(CurBuf).Buffer->getBufferIdentifier() 795 << ":" << getSourceManager().FindLineNumber(IDLoc, CurBuf) << ":" 796 << LogMessage + "\n"; 797 798 getContext().setSecureLogUsed(true); 799 800 return false; 801 } 802 803 /// ParseDirectiveSecureLogReset 804 /// ::= .secure_log_reset 805 bool DarwinAsmParser::parseDirectiveSecureLogReset(StringRef, SMLoc IDLoc) { 806 if (getLexer().isNot(AsmToken::EndOfStatement)) 807 return TokError("unexpected token in '.secure_log_reset' directive"); 808 809 Lex(); 810 811 getContext().setSecureLogUsed(false); 812 813 return false; 814 } 815 816 /// parseDirectiveSubsectionsViaSymbols 817 /// ::= .subsections_via_symbols 818 bool DarwinAsmParser::parseDirectiveSubsectionsViaSymbols(StringRef, SMLoc) { 819 if (getLexer().isNot(AsmToken::EndOfStatement)) 820 return TokError("unexpected token in '.subsections_via_symbols' directive"); 821 822 Lex(); 823 824 getStreamer().emitAssemblerFlag(MCAF_SubsectionsViaSymbols); 825 826 return false; 827 } 828 829 /// ParseDirectiveTBSS 830 /// ::= .tbss identifier, size, align 831 bool DarwinAsmParser::parseDirectiveTBSS(StringRef, SMLoc) { 832 SMLoc IDLoc = getLexer().getLoc(); 833 StringRef Name; 834 if (getParser().parseIdentifier(Name)) 835 return TokError("expected identifier in directive"); 836 837 // Handle the identifier as the key symbol. 838 MCSymbol *Sym = getContext().getOrCreateSymbol(Name); 839 840 if (getLexer().isNot(AsmToken::Comma)) 841 return TokError("unexpected token in directive"); 842 Lex(); 843 844 int64_t Size; 845 SMLoc SizeLoc = getLexer().getLoc(); 846 if (getParser().parseAbsoluteExpression(Size)) 847 return true; 848 849 int64_t Pow2Alignment = 0; 850 SMLoc Pow2AlignmentLoc; 851 if (getLexer().is(AsmToken::Comma)) { 852 Lex(); 853 Pow2AlignmentLoc = getLexer().getLoc(); 854 if (getParser().parseAbsoluteExpression(Pow2Alignment)) 855 return true; 856 } 857 858 if (getLexer().isNot(AsmToken::EndOfStatement)) 859 return TokError("unexpected token in '.tbss' directive"); 860 861 Lex(); 862 863 if (Size < 0) 864 return Error(SizeLoc, "invalid '.tbss' directive size, can't be less than" 865 "zero"); 866 867 // FIXME: Diagnose overflow. 868 if (Pow2Alignment < 0) 869 return Error(Pow2AlignmentLoc, "invalid '.tbss' alignment, can't be less" 870 "than zero"); 871 872 if (!Sym->isUndefined()) 873 return Error(IDLoc, "invalid symbol redefinition"); 874 875 getStreamer().emitTBSSSymbol( 876 getContext().getMachOSection("__DATA", "__thread_bss", 877 MachO::S_THREAD_LOCAL_ZEROFILL, 0, 878 SectionKind::getThreadBSS()), 879 Sym, Size, 1 << Pow2Alignment); 880 881 return false; 882 } 883 884 /// ParseDirectiveZerofill 885 /// ::= .zerofill segname , sectname [, identifier , size_expression [ 886 /// , align_expression ]] 887 bool DarwinAsmParser::parseDirectiveZerofill(StringRef, SMLoc) { 888 StringRef Segment; 889 if (getParser().parseIdentifier(Segment)) 890 return TokError("expected segment name after '.zerofill' directive"); 891 892 if (getLexer().isNot(AsmToken::Comma)) 893 return TokError("unexpected token in directive"); 894 Lex(); 895 896 StringRef Section; 897 SMLoc SectionLoc = getLexer().getLoc(); 898 if (getParser().parseIdentifier(Section)) 899 return TokError("expected section name after comma in '.zerofill' " 900 "directive"); 901 902 // If this is the end of the line all that was wanted was to create the 903 // the section but with no symbol. 904 if (getLexer().is(AsmToken::EndOfStatement)) { 905 // Create the zerofill section but no symbol 906 getStreamer().emitZerofill( 907 getContext().getMachOSection(Segment, Section, MachO::S_ZEROFILL, 0, 908 SectionKind::getBSS()), 909 /*Symbol=*/nullptr, /*Size=*/0, /*ByteAlignment=*/0, SectionLoc); 910 return false; 911 } 912 913 if (getLexer().isNot(AsmToken::Comma)) 914 return TokError("unexpected token in directive"); 915 Lex(); 916 917 SMLoc IDLoc = getLexer().getLoc(); 918 StringRef IDStr; 919 if (getParser().parseIdentifier(IDStr)) 920 return TokError("expected identifier in directive"); 921 922 // handle the identifier as the key symbol. 923 MCSymbol *Sym = getContext().getOrCreateSymbol(IDStr); 924 925 if (getLexer().isNot(AsmToken::Comma)) 926 return TokError("unexpected token in directive"); 927 Lex(); 928 929 int64_t Size; 930 SMLoc SizeLoc = getLexer().getLoc(); 931 if (getParser().parseAbsoluteExpression(Size)) 932 return true; 933 934 int64_t Pow2Alignment = 0; 935 SMLoc Pow2AlignmentLoc; 936 if (getLexer().is(AsmToken::Comma)) { 937 Lex(); 938 Pow2AlignmentLoc = getLexer().getLoc(); 939 if (getParser().parseAbsoluteExpression(Pow2Alignment)) 940 return true; 941 } 942 943 if (getLexer().isNot(AsmToken::EndOfStatement)) 944 return TokError("unexpected token in '.zerofill' directive"); 945 946 Lex(); 947 948 if (Size < 0) 949 return Error(SizeLoc, "invalid '.zerofill' directive size, can't be less " 950 "than zero"); 951 952 // NOTE: The alignment in the directive is a power of 2 value, the assembler 953 // may internally end up wanting an alignment in bytes. 954 // FIXME: Diagnose overflow. 955 if (Pow2Alignment < 0) 956 return Error(Pow2AlignmentLoc, "invalid '.zerofill' directive alignment, " 957 "can't be less than zero"); 958 959 if (!Sym->isUndefined()) 960 return Error(IDLoc, "invalid symbol redefinition"); 961 962 // Create the zerofill Symbol with Size and Pow2Alignment 963 // 964 // FIXME: Arch specific. 965 getStreamer().emitZerofill(getContext().getMachOSection( 966 Segment, Section, MachO::S_ZEROFILL, 967 0, SectionKind::getBSS()), 968 Sym, Size, 1 << Pow2Alignment, SectionLoc); 969 970 return false; 971 } 972 973 /// ParseDirectiveDataRegion 974 /// ::= .data_region [ ( jt8 | jt16 | jt32 ) ] 975 bool DarwinAsmParser::parseDirectiveDataRegion(StringRef, SMLoc) { 976 if (getLexer().is(AsmToken::EndOfStatement)) { 977 Lex(); 978 getStreamer().emitDataRegion(MCDR_DataRegion); 979 return false; 980 } 981 StringRef RegionType; 982 SMLoc Loc = getParser().getTok().getLoc(); 983 if (getParser().parseIdentifier(RegionType)) 984 return TokError("expected region type after '.data_region' directive"); 985 int Kind = StringSwitch<int>(RegionType) 986 .Case("jt8", MCDR_DataRegionJT8) 987 .Case("jt16", MCDR_DataRegionJT16) 988 .Case("jt32", MCDR_DataRegionJT32) 989 .Default(-1); 990 if (Kind == -1) 991 return Error(Loc, "unknown region type in '.data_region' directive"); 992 Lex(); 993 994 getStreamer().emitDataRegion((MCDataRegionType)Kind); 995 return false; 996 } 997 998 /// ParseDirectiveDataRegionEnd 999 /// ::= .end_data_region 1000 bool DarwinAsmParser::parseDirectiveDataRegionEnd(StringRef, SMLoc) { 1001 if (getLexer().isNot(AsmToken::EndOfStatement)) 1002 return TokError("unexpected token in '.end_data_region' directive"); 1003 1004 Lex(); 1005 getStreamer().emitDataRegion(MCDR_DataRegionEnd); 1006 return false; 1007 } 1008 1009 static bool isSDKVersionToken(const AsmToken &Tok) { 1010 return Tok.is(AsmToken::Identifier) && Tok.getIdentifier() == "sdk_version"; 1011 } 1012 1013 /// parseMajorMinorVersionComponent ::= major, minor 1014 bool DarwinAsmParser::parseMajorMinorVersionComponent(unsigned *Major, 1015 unsigned *Minor, 1016 const char *VersionName) { 1017 // Get the major version number. 1018 if (getLexer().isNot(AsmToken::Integer)) 1019 return TokError(Twine("invalid ") + VersionName + 1020 " major version number, integer expected"); 1021 int64_t MajorVal = getLexer().getTok().getIntVal(); 1022 if (MajorVal > 65535 || MajorVal <= 0) 1023 return TokError(Twine("invalid ") + VersionName + " major version number"); 1024 *Major = (unsigned)MajorVal; 1025 Lex(); 1026 if (getLexer().isNot(AsmToken::Comma)) 1027 return TokError(Twine(VersionName) + 1028 " minor version number required, comma expected"); 1029 Lex(); 1030 // Get the minor version number. 1031 if (getLexer().isNot(AsmToken::Integer)) 1032 return TokError(Twine("invalid ") + VersionName + 1033 " minor version number, integer expected"); 1034 int64_t MinorVal = getLexer().getTok().getIntVal(); 1035 if (MinorVal > 255 || MinorVal < 0) 1036 return TokError(Twine("invalid ") + VersionName + " minor version number"); 1037 *Minor = MinorVal; 1038 Lex(); 1039 return false; 1040 } 1041 1042 /// parseOptionalTrailingVersionComponent ::= , version_number 1043 bool DarwinAsmParser::parseOptionalTrailingVersionComponent( 1044 unsigned *Component, const char *ComponentName) { 1045 assert(getLexer().is(AsmToken::Comma) && "comma expected"); 1046 Lex(); 1047 if (getLexer().isNot(AsmToken::Integer)) 1048 return TokError(Twine("invalid ") + ComponentName + 1049 " version number, integer expected"); 1050 int64_t Val = getLexer().getTok().getIntVal(); 1051 if (Val > 255 || Val < 0) 1052 return TokError(Twine("invalid ") + ComponentName + " version number"); 1053 *Component = Val; 1054 Lex(); 1055 return false; 1056 } 1057 1058 /// parseVersion ::= parseMajorMinorVersionComponent 1059 /// parseOptionalTrailingVersionComponent 1060 bool DarwinAsmParser::parseVersion(unsigned *Major, unsigned *Minor, 1061 unsigned *Update) { 1062 if (parseMajorMinorVersionComponent(Major, Minor, "OS")) 1063 return true; 1064 1065 // Get the update level, if specified 1066 *Update = 0; 1067 if (getLexer().is(AsmToken::EndOfStatement) || 1068 isSDKVersionToken(getLexer().getTok())) 1069 return false; 1070 if (getLexer().isNot(AsmToken::Comma)) 1071 return TokError("invalid OS update specifier, comma expected"); 1072 if (parseOptionalTrailingVersionComponent(Update, "OS update")) 1073 return true; 1074 return false; 1075 } 1076 1077 bool DarwinAsmParser::parseSDKVersion(VersionTuple &SDKVersion) { 1078 assert(isSDKVersionToken(getLexer().getTok()) && "expected sdk_version"); 1079 Lex(); 1080 unsigned Major, Minor; 1081 if (parseMajorMinorVersionComponent(&Major, &Minor, "SDK")) 1082 return true; 1083 SDKVersion = VersionTuple(Major, Minor); 1084 1085 // Get the subminor version, if specified. 1086 if (getLexer().is(AsmToken::Comma)) { 1087 unsigned Subminor; 1088 if (parseOptionalTrailingVersionComponent(&Subminor, "SDK subminor")) 1089 return true; 1090 SDKVersion = VersionTuple(Major, Minor, Subminor); 1091 } 1092 return false; 1093 } 1094 1095 void DarwinAsmParser::checkVersion(StringRef Directive, StringRef Arg, 1096 SMLoc Loc, Triple::OSType ExpectedOS) { 1097 const Triple &Target = getContext().getTargetTriple(); 1098 if (Target.getOS() != ExpectedOS) 1099 Warning(Loc, Twine(Directive) + 1100 (Arg.empty() ? Twine() : Twine(' ') + Arg) + 1101 " used while targeting " + Target.getOSName()); 1102 1103 if (LastVersionDirective.isValid()) { 1104 Warning(Loc, "overriding previous version directive"); 1105 Note(LastVersionDirective, "previous definition is here"); 1106 } 1107 LastVersionDirective = Loc; 1108 } 1109 1110 static Triple::OSType getOSTypeFromMCVM(MCVersionMinType Type) { 1111 switch (Type) { 1112 case MCVM_WatchOSVersionMin: return Triple::WatchOS; 1113 case MCVM_TvOSVersionMin: return Triple::TvOS; 1114 case MCVM_IOSVersionMin: return Triple::IOS; 1115 case MCVM_OSXVersionMin: return Triple::MacOSX; 1116 } 1117 llvm_unreachable("Invalid mc version min type"); 1118 } 1119 1120 /// parseVersionMin 1121 /// ::= .ios_version_min parseVersion parseSDKVersion 1122 /// | .macosx_version_min parseVersion parseSDKVersion 1123 /// | .tvos_version_min parseVersion parseSDKVersion 1124 /// | .watchos_version_min parseVersion parseSDKVersion 1125 bool DarwinAsmParser::parseVersionMin(StringRef Directive, SMLoc Loc, 1126 MCVersionMinType Type) { 1127 unsigned Major; 1128 unsigned Minor; 1129 unsigned Update; 1130 if (parseVersion(&Major, &Minor, &Update)) 1131 return true; 1132 1133 VersionTuple SDKVersion; 1134 if (isSDKVersionToken(getLexer().getTok()) && parseSDKVersion(SDKVersion)) 1135 return true; 1136 1137 if (parseToken(AsmToken::EndOfStatement)) 1138 return addErrorSuffix(Twine(" in '") + Directive + "' directive"); 1139 1140 Triple::OSType ExpectedOS = getOSTypeFromMCVM(Type); 1141 checkVersion(Directive, StringRef(), Loc, ExpectedOS); 1142 getStreamer().emitVersionMin(Type, Major, Minor, Update, SDKVersion); 1143 return false; 1144 } 1145 1146 static Triple::OSType getOSTypeFromPlatform(MachO::PlatformType Type) { 1147 switch (Type) { 1148 case MachO::PLATFORM_UNKNOWN: /* silence warning */ 1149 break; 1150 case MachO::PLATFORM_MACOS: return Triple::MacOSX; 1151 case MachO::PLATFORM_IOS: return Triple::IOS; 1152 case MachO::PLATFORM_TVOS: return Triple::TvOS; 1153 case MachO::PLATFORM_WATCHOS: return Triple::WatchOS; 1154 case MachO::PLATFORM_BRIDGEOS: /* silence warning */ break; 1155 case MachO::PLATFORM_MACCATALYST: return Triple::IOS; 1156 case MachO::PLATFORM_IOSSIMULATOR: /* silence warning */ break; 1157 case MachO::PLATFORM_TVOSSIMULATOR: /* silence warning */ break; 1158 case MachO::PLATFORM_WATCHOSSIMULATOR: /* silence warning */ break; 1159 case MachO::PLATFORM_DRIVERKIT: /* silence warning */ break; 1160 } 1161 llvm_unreachable("Invalid mach-o platform type"); 1162 } 1163 1164 /// parseBuildVersion 1165 /// ::= .build_version (macos|ios|tvos|watchos), parseVersion parseSDKVersion 1166 bool DarwinAsmParser::parseBuildVersion(StringRef Directive, SMLoc Loc) { 1167 StringRef PlatformName; 1168 SMLoc PlatformLoc = getTok().getLoc(); 1169 if (getParser().parseIdentifier(PlatformName)) 1170 return TokError("platform name expected"); 1171 1172 unsigned Platform = StringSwitch<unsigned>(PlatformName) 1173 .Case("macos", MachO::PLATFORM_MACOS) 1174 .Case("ios", MachO::PLATFORM_IOS) 1175 .Case("tvos", MachO::PLATFORM_TVOS) 1176 .Case("watchos", MachO::PLATFORM_WATCHOS) 1177 .Case("macCatalyst", MachO::PLATFORM_MACCATALYST) 1178 .Default(0); 1179 if (Platform == 0) 1180 return Error(PlatformLoc, "unknown platform name"); 1181 1182 if (getLexer().isNot(AsmToken::Comma)) 1183 return TokError("version number required, comma expected"); 1184 Lex(); 1185 1186 unsigned Major; 1187 unsigned Minor; 1188 unsigned Update; 1189 if (parseVersion(&Major, &Minor, &Update)) 1190 return true; 1191 1192 VersionTuple SDKVersion; 1193 if (isSDKVersionToken(getLexer().getTok()) && parseSDKVersion(SDKVersion)) 1194 return true; 1195 1196 if (parseToken(AsmToken::EndOfStatement)) 1197 return addErrorSuffix(" in '.build_version' directive"); 1198 1199 Triple::OSType ExpectedOS 1200 = getOSTypeFromPlatform((MachO::PlatformType)Platform); 1201 checkVersion(Directive, PlatformName, Loc, ExpectedOS); 1202 getStreamer().emitBuildVersion(Platform, Major, Minor, Update, SDKVersion); 1203 return false; 1204 } 1205 1206 /// parseDirectiveCGProfile 1207 /// ::= .cg_profile from, to, count 1208 bool DarwinAsmParser::parseDirectiveCGProfile(StringRef S, SMLoc Loc) { 1209 return MCAsmParserExtension::ParseDirectiveCGProfile(S, Loc); 1210 } 1211 1212 namespace llvm { 1213 1214 MCAsmParserExtension *createDarwinAsmParser() { 1215 return new DarwinAsmParser; 1216 } 1217 1218 } // end llvm namespace 1219