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