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/SmallVector.h"
10#include "llvm/ADT/StringRef.h"
11#include "llvm/ADT/StringSwitch.h"
12#include "llvm/ADT/Twine.h"
13#include "llvm/BinaryFormat/MachO.h"
14#include "llvm/MC/MCContext.h"
15#include "llvm/MC/MCDirectives.h"
16#include "llvm/MC/MCParser/MCAsmLexer.h"
17#include "llvm/MC/MCParser/MCAsmParser.h"
18#include "llvm/MC/MCParser/MCAsmParserExtension.h"
19#include "llvm/MC/MCSectionMachO.h"
20#include "llvm/MC/MCStreamer.h"
21#include "llvm/MC/MCSymbol.h"
22#include "llvm/MC/SectionKind.h"
23#include "llvm/Support/Error.h"
24#include "llvm/Support/FileSystem.h"
25#include "llvm/Support/MemoryBuffer.h"
26#include "llvm/Support/SMLoc.h"
27#include "llvm/Support/SourceMgr.h"
28#include "llvm/Support/raw_ostream.h"
29#include "llvm/TargetParser/Triple.h"
30#include <cstddef>
31#include <cstdint>
32#include <string>
33#include <system_error>
34#include <utility>
35
36using namespace llvm;
37
38namespace {
39
40/// Implementation of directive handling which is shared across all
41/// Darwin targets.
42class DarwinAsmParser : public MCAsmParserExtension {
43  template<bool (DarwinAsmParser::*HandlerMethod)(StringRef, SMLoc)>
44  void addDirectiveHandler(StringRef Directive) {
45    MCAsmParser::ExtensionDirectiveHandler Handler = std::make_pair(
46        this, HandleDirective<DarwinAsmParser, HandlerMethod>);
47    getParser().addDirectiveHandler(Directive, Handler);
48  }
49
50  bool parseSectionSwitch(StringRef Segment, StringRef Section,
51                          unsigned TAA = 0, unsigned ImplicitAlign = 0,
52                          unsigned StubSize = 0);
53
54  SMLoc LastVersionDirective;
55
56public:
57  DarwinAsmParser() = default;
58
59  void Initialize(MCAsmParser &Parser) override {
60    // Call the base implementation.
61    this->MCAsmParserExtension::Initialize(Parser);
62
63    addDirectiveHandler<&DarwinAsmParser::parseDirectiveAltEntry>(".alt_entry");
64    addDirectiveHandler<&DarwinAsmParser::parseDirectiveDesc>(".desc");
65    addDirectiveHandler<&DarwinAsmParser::parseDirectiveIndirectSymbol>(
66      ".indirect_symbol");
67    addDirectiveHandler<&DarwinAsmParser::parseDirectiveLsym>(".lsym");
68    addDirectiveHandler<&DarwinAsmParser::parseDirectiveSubsectionsViaSymbols>(
69      ".subsections_via_symbols");
70    addDirectiveHandler<&DarwinAsmParser::parseDirectiveDumpOrLoad>(".dump");
71    addDirectiveHandler<&DarwinAsmParser::parseDirectiveDumpOrLoad>(".load");
72    addDirectiveHandler<&DarwinAsmParser::parseDirectiveSection>(".section");
73    addDirectiveHandler<&DarwinAsmParser::parseDirectivePushSection>(
74      ".pushsection");
75    addDirectiveHandler<&DarwinAsmParser::parseDirectivePopSection>(
76      ".popsection");
77    addDirectiveHandler<&DarwinAsmParser::parseDirectivePrevious>(".previous");
78    addDirectiveHandler<&DarwinAsmParser::parseDirectiveSecureLogUnique>(
79      ".secure_log_unique");
80    addDirectiveHandler<&DarwinAsmParser::parseDirectiveSecureLogReset>(
81      ".secure_log_reset");
82    addDirectiveHandler<&DarwinAsmParser::parseDirectiveTBSS>(".tbss");
83    addDirectiveHandler<&DarwinAsmParser::parseDirectiveZerofill>(".zerofill");
84
85    addDirectiveHandler<&DarwinAsmParser::parseDirectiveDataRegion>(
86      ".data_region");
87    addDirectiveHandler<&DarwinAsmParser::parseDirectiveDataRegionEnd>(
88      ".end_data_region");
89
90    // Special section directives.
91    addDirectiveHandler<&DarwinAsmParser::parseSectionDirectiveBss>(".bss");
92    addDirectiveHandler<&DarwinAsmParser::parseSectionDirectiveConst>(".const");
93    addDirectiveHandler<&DarwinAsmParser::parseSectionDirectiveConstData>(
94      ".const_data");
95    addDirectiveHandler<&DarwinAsmParser::parseSectionDirectiveConstructor>(
96      ".constructor");
97    addDirectiveHandler<&DarwinAsmParser::parseSectionDirectiveCString>(
98      ".cstring");
99    addDirectiveHandler<&DarwinAsmParser::parseSectionDirectiveData>(".data");
100    addDirectiveHandler<&DarwinAsmParser::parseSectionDirectiveDestructor>(
101      ".destructor");
102    addDirectiveHandler<&DarwinAsmParser::parseSectionDirectiveDyld>(".dyld");
103    addDirectiveHandler<&DarwinAsmParser::parseSectionDirectiveFVMLibInit0>(
104      ".fvmlib_init0");
105    addDirectiveHandler<&DarwinAsmParser::parseSectionDirectiveFVMLibInit1>(
106      ".fvmlib_init1");
107    addDirectiveHandler<
108      &DarwinAsmParser::parseSectionDirectiveLazySymbolPointers>(
109        ".lazy_symbol_pointer");
110    addDirectiveHandler<&DarwinAsmParser::parseDirectiveLinkerOption>(
111      ".linker_option");
112    addDirectiveHandler<&DarwinAsmParser::parseSectionDirectiveLiteral16>(
113      ".literal16");
114    addDirectiveHandler<&DarwinAsmParser::parseSectionDirectiveLiteral4>(
115      ".literal4");
116    addDirectiveHandler<&DarwinAsmParser::parseSectionDirectiveLiteral8>(
117      ".literal8");
118    addDirectiveHandler<&DarwinAsmParser::parseSectionDirectiveModInitFunc>(
119      ".mod_init_func");
120    addDirectiveHandler<&DarwinAsmParser::parseSectionDirectiveModTermFunc>(
121      ".mod_term_func");
122    addDirectiveHandler<
123      &DarwinAsmParser::parseSectionDirectiveNonLazySymbolPointers>(
124        ".non_lazy_symbol_pointer");
125    addDirectiveHandler<
126      &DarwinAsmParser::parseSectionDirectiveThreadLocalVariablePointers>(
127        ".thread_local_variable_pointer");
128    addDirectiveHandler<&DarwinAsmParser::parseSectionDirectiveObjCCatClsMeth>(
129      ".objc_cat_cls_meth");
130    addDirectiveHandler<&DarwinAsmParser::parseSectionDirectiveObjCCatInstMeth>(
131      ".objc_cat_inst_meth");
132    addDirectiveHandler<&DarwinAsmParser::parseSectionDirectiveObjCCategory>(
133      ".objc_category");
134    addDirectiveHandler<&DarwinAsmParser::parseSectionDirectiveObjCClass>(
135      ".objc_class");
136    addDirectiveHandler<&DarwinAsmParser::parseSectionDirectiveObjCClassNames>(
137      ".objc_class_names");
138    addDirectiveHandler<&DarwinAsmParser::parseSectionDirectiveObjCClassVars>(
139      ".objc_class_vars");
140    addDirectiveHandler<&DarwinAsmParser::parseSectionDirectiveObjCClsMeth>(
141      ".objc_cls_meth");
142    addDirectiveHandler<&DarwinAsmParser::parseSectionDirectiveObjCClsRefs>(
143      ".objc_cls_refs");
144    addDirectiveHandler<&DarwinAsmParser::parseSectionDirectiveObjCInstMeth>(
145      ".objc_inst_meth");
146    addDirectiveHandler<
147      &DarwinAsmParser::parseSectionDirectiveObjCInstanceVars>(
148        ".objc_instance_vars");
149    addDirectiveHandler<&DarwinAsmParser::parseSectionDirectiveObjCMessageRefs>(
150      ".objc_message_refs");
151    addDirectiveHandler<&DarwinAsmParser::parseSectionDirectiveObjCMetaClass>(
152      ".objc_meta_class");
153    addDirectiveHandler<
154      &DarwinAsmParser::parseSectionDirectiveObjCMethVarNames>(
155        ".objc_meth_var_names");
156    addDirectiveHandler<
157      &DarwinAsmParser::parseSectionDirectiveObjCMethVarTypes>(
158        ".objc_meth_var_types");
159    addDirectiveHandler<&DarwinAsmParser::parseSectionDirectiveObjCModuleInfo>(
160      ".objc_module_info");
161    addDirectiveHandler<&DarwinAsmParser::parseSectionDirectiveObjCProtocol>(
162      ".objc_protocol");
163    addDirectiveHandler<
164      &DarwinAsmParser::parseSectionDirectiveObjCSelectorStrs>(
165        ".objc_selector_strs");
166    addDirectiveHandler<
167      &DarwinAsmParser::parseSectionDirectiveObjCStringObject>(
168        ".objc_string_object");
169    addDirectiveHandler<&DarwinAsmParser::parseSectionDirectiveObjCSymbols>(
170      ".objc_symbols");
171    addDirectiveHandler<&DarwinAsmParser::parseSectionDirectivePICSymbolStub>(
172      ".picsymbol_stub");
173    addDirectiveHandler<&DarwinAsmParser::parseSectionDirectiveStaticConst>(
174      ".static_const");
175    addDirectiveHandler<&DarwinAsmParser::parseSectionDirectiveStaticData>(
176      ".static_data");
177    addDirectiveHandler<&DarwinAsmParser::parseSectionDirectiveSymbolStub>(
178      ".symbol_stub");
179    addDirectiveHandler<&DarwinAsmParser::parseSectionDirectiveTData>(".tdata");
180    addDirectiveHandler<&DarwinAsmParser::parseSectionDirectiveText>(".text");
181    addDirectiveHandler<&DarwinAsmParser::parseSectionDirectiveThreadInitFunc>(
182      ".thread_init_func");
183    addDirectiveHandler<&DarwinAsmParser::parseSectionDirectiveTLV>(".tlv");
184
185    addDirectiveHandler<&DarwinAsmParser::parseSectionDirectiveIdent>(".ident");
186    addDirectiveHandler<&DarwinAsmParser::parseWatchOSVersionMin>(
187      ".watchos_version_min");
188    addDirectiveHandler<&DarwinAsmParser::parseTvOSVersionMin>(
189      ".tvos_version_min");
190    addDirectiveHandler<&DarwinAsmParser::parseIOSVersionMin>(
191      ".ios_version_min");
192    addDirectiveHandler<&DarwinAsmParser::parseMacOSXVersionMin>(
193      ".macosx_version_min");
194    addDirectiveHandler<&DarwinAsmParser::parseBuildVersion>(".build_version");
195    addDirectiveHandler<&DarwinAsmParser::parseDirectiveCGProfile>(
196        ".cg_profile");
197
198    LastVersionDirective = SMLoc();
199  }
200
201  bool parseDirectiveAltEntry(StringRef, SMLoc);
202  bool parseDirectiveDesc(StringRef, SMLoc);
203  bool parseDirectiveIndirectSymbol(StringRef, SMLoc);
204  bool parseDirectiveDumpOrLoad(StringRef, SMLoc);
205  bool parseDirectiveLsym(StringRef, SMLoc);
206  bool parseDirectiveLinkerOption(StringRef, SMLoc);
207  bool parseDirectiveSection(StringRef, SMLoc);
208  bool parseDirectivePushSection(StringRef, SMLoc);
209  bool parseDirectivePopSection(StringRef, SMLoc);
210  bool parseDirectivePrevious(StringRef, SMLoc);
211  bool parseDirectiveSecureLogReset(StringRef, SMLoc);
212  bool parseDirectiveSecureLogUnique(StringRef, SMLoc);
213  bool parseDirectiveSubsectionsViaSymbols(StringRef, SMLoc);
214  bool parseDirectiveTBSS(StringRef, SMLoc);
215  bool parseDirectiveZerofill(StringRef, SMLoc);
216  bool parseDirectiveDataRegion(StringRef, SMLoc);
217  bool parseDirectiveDataRegionEnd(StringRef, SMLoc);
218
219  // Named Section Directive
220  bool parseSectionDirectiveBss(StringRef, SMLoc) {
221    return parseSectionSwitch("__DATA", "__bss");
222  }
223
224  bool parseSectionDirectiveConst(StringRef, SMLoc) {
225    return parseSectionSwitch("__TEXT", "__const");
226  }
227
228  bool parseSectionDirectiveStaticConst(StringRef, SMLoc) {
229    return parseSectionSwitch("__TEXT", "__static_const");
230  }
231
232  bool parseSectionDirectiveCString(StringRef, SMLoc) {
233    return parseSectionSwitch("__TEXT","__cstring",
234                              MachO::S_CSTRING_LITERALS);
235  }
236
237  bool parseSectionDirectiveLiteral4(StringRef, SMLoc) {
238    return parseSectionSwitch("__TEXT", "__literal4",
239                              MachO::S_4BYTE_LITERALS, 4);
240  }
241
242  bool parseSectionDirectiveLiteral8(StringRef, SMLoc) {
243    return parseSectionSwitch("__TEXT", "__literal8",
244                              MachO::S_8BYTE_LITERALS, 8);
245  }
246
247  bool parseSectionDirectiveLiteral16(StringRef, SMLoc) {
248    return parseSectionSwitch("__TEXT","__literal16",
249                              MachO::S_16BYTE_LITERALS, 16);
250  }
251
252  bool parseSectionDirectiveConstructor(StringRef, SMLoc) {
253    return parseSectionSwitch("__TEXT","__constructor");
254  }
255
256  bool parseSectionDirectiveDestructor(StringRef, SMLoc) {
257    return parseSectionSwitch("__TEXT","__destructor");
258  }
259
260  bool parseSectionDirectiveFVMLibInit0(StringRef, SMLoc) {
261    return parseSectionSwitch("__TEXT","__fvmlib_init0");
262  }
263
264  bool parseSectionDirectiveFVMLibInit1(StringRef, SMLoc) {
265    return parseSectionSwitch("__TEXT","__fvmlib_init1");
266  }
267
268  bool parseSectionDirectiveSymbolStub(StringRef, SMLoc) {
269    return parseSectionSwitch("__TEXT","__symbol_stub",
270                              MachO::S_SYMBOL_STUBS |
271                              MachO::S_ATTR_PURE_INSTRUCTIONS,
272                              // FIXME: Different on PPC and ARM.
273                              0, 16);
274  }
275
276  bool parseSectionDirectivePICSymbolStub(StringRef, SMLoc) {
277    return parseSectionSwitch("__TEXT","__picsymbol_stub",
278                              MachO::S_SYMBOL_STUBS |
279                              MachO::S_ATTR_PURE_INSTRUCTIONS, 0, 26);
280  }
281
282  bool parseSectionDirectiveData(StringRef, SMLoc) {
283    return parseSectionSwitch("__DATA", "__data");
284  }
285
286  bool parseSectionDirectiveStaticData(StringRef, SMLoc) {
287    return parseSectionSwitch("__DATA", "__static_data");
288  }
289
290  bool parseSectionDirectiveNonLazySymbolPointers(StringRef, SMLoc) {
291    return parseSectionSwitch("__DATA", "__nl_symbol_ptr",
292                              MachO::S_NON_LAZY_SYMBOL_POINTERS, 4);
293  }
294
295  bool parseSectionDirectiveLazySymbolPointers(StringRef, SMLoc) {
296    return parseSectionSwitch("__DATA", "__la_symbol_ptr",
297                              MachO::S_LAZY_SYMBOL_POINTERS, 4);
298  }
299
300  bool parseSectionDirectiveThreadLocalVariablePointers(StringRef, SMLoc) {
301    return parseSectionSwitch("__DATA", "__thread_ptr",
302                              MachO::S_THREAD_LOCAL_VARIABLE_POINTERS, 4);
303  }
304
305  bool parseSectionDirectiveDyld(StringRef, SMLoc) {
306    return parseSectionSwitch("__DATA", "__dyld");
307  }
308
309  bool parseSectionDirectiveModInitFunc(StringRef, SMLoc) {
310    return parseSectionSwitch("__DATA", "__mod_init_func",
311                              MachO::S_MOD_INIT_FUNC_POINTERS, 4);
312  }
313
314  bool parseSectionDirectiveModTermFunc(StringRef, SMLoc) {
315    return parseSectionSwitch("__DATA", "__mod_term_func",
316                              MachO::S_MOD_TERM_FUNC_POINTERS, 4);
317  }
318
319  bool parseSectionDirectiveConstData(StringRef, SMLoc) {
320    return parseSectionSwitch("__DATA", "__const");
321  }
322
323  bool parseSectionDirectiveObjCClass(StringRef, SMLoc) {
324    return parseSectionSwitch("__OBJC", "__class",
325                              MachO::S_ATTR_NO_DEAD_STRIP);
326  }
327
328  bool parseSectionDirectiveObjCMetaClass(StringRef, SMLoc) {
329    return parseSectionSwitch("__OBJC", "__meta_class",
330                              MachO::S_ATTR_NO_DEAD_STRIP);
331  }
332
333  bool parseSectionDirectiveObjCCatClsMeth(StringRef, SMLoc) {
334    return parseSectionSwitch("__OBJC", "__cat_cls_meth",
335                              MachO::S_ATTR_NO_DEAD_STRIP);
336  }
337
338  bool parseSectionDirectiveObjCCatInstMeth(StringRef, SMLoc) {
339    return parseSectionSwitch("__OBJC", "__cat_inst_meth",
340                              MachO::S_ATTR_NO_DEAD_STRIP);
341  }
342
343  bool parseSectionDirectiveObjCProtocol(StringRef, SMLoc) {
344    return parseSectionSwitch("__OBJC", "__protocol",
345                              MachO::S_ATTR_NO_DEAD_STRIP);
346  }
347
348  bool parseSectionDirectiveObjCStringObject(StringRef, SMLoc) {
349    return parseSectionSwitch("__OBJC", "__string_object",
350                              MachO::S_ATTR_NO_DEAD_STRIP);
351  }
352
353  bool parseSectionDirectiveObjCClsMeth(StringRef, SMLoc) {
354    return parseSectionSwitch("__OBJC", "__cls_meth",
355                              MachO::S_ATTR_NO_DEAD_STRIP);
356  }
357
358  bool parseSectionDirectiveObjCInstMeth(StringRef, SMLoc) {
359    return parseSectionSwitch("__OBJC", "__inst_meth",
360                              MachO::S_ATTR_NO_DEAD_STRIP);
361  }
362
363  bool parseSectionDirectiveObjCClsRefs(StringRef, SMLoc) {
364    return parseSectionSwitch("__OBJC", "__cls_refs",
365                              MachO::S_ATTR_NO_DEAD_STRIP |
366                              MachO::S_LITERAL_POINTERS, 4);
367  }
368
369  bool parseSectionDirectiveObjCMessageRefs(StringRef, SMLoc) {
370    return parseSectionSwitch("__OBJC", "__message_refs",
371                              MachO::S_ATTR_NO_DEAD_STRIP |
372                              MachO::S_LITERAL_POINTERS, 4);
373  }
374
375  bool parseSectionDirectiveObjCSymbols(StringRef, SMLoc) {
376    return parseSectionSwitch("__OBJC", "__symbols",
377                              MachO::S_ATTR_NO_DEAD_STRIP);
378  }
379
380  bool parseSectionDirectiveObjCCategory(StringRef, SMLoc) {
381    return parseSectionSwitch("__OBJC", "__category",
382                              MachO::S_ATTR_NO_DEAD_STRIP);
383  }
384
385  bool parseSectionDirectiveObjCClassVars(StringRef, SMLoc) {
386    return parseSectionSwitch("__OBJC", "__class_vars",
387                              MachO::S_ATTR_NO_DEAD_STRIP);
388  }
389
390  bool parseSectionDirectiveObjCInstanceVars(StringRef, SMLoc) {
391    return parseSectionSwitch("__OBJC", "__instance_vars",
392                              MachO::S_ATTR_NO_DEAD_STRIP);
393  }
394
395  bool parseSectionDirectiveObjCModuleInfo(StringRef, SMLoc) {
396    return parseSectionSwitch("__OBJC", "__module_info",
397                              MachO::S_ATTR_NO_DEAD_STRIP);
398  }
399
400  bool parseSectionDirectiveObjCClassNames(StringRef, SMLoc) {
401    return parseSectionSwitch("__TEXT", "__cstring",
402                              MachO::S_CSTRING_LITERALS);
403  }
404
405  bool parseSectionDirectiveObjCMethVarTypes(StringRef, SMLoc) {
406    return parseSectionSwitch("__TEXT", "__cstring",
407                              MachO::S_CSTRING_LITERALS);
408  }
409
410  bool parseSectionDirectiveObjCMethVarNames(StringRef, SMLoc) {
411    return parseSectionSwitch("__TEXT", "__cstring",
412                              MachO::S_CSTRING_LITERALS);
413  }
414
415  bool parseSectionDirectiveObjCSelectorStrs(StringRef, SMLoc) {
416    return parseSectionSwitch("__OBJC", "__selector_strs",
417                              MachO::S_CSTRING_LITERALS);
418  }
419
420  bool parseSectionDirectiveTData(StringRef, SMLoc) {
421    return parseSectionSwitch("__DATA", "__thread_data",
422                              MachO::S_THREAD_LOCAL_REGULAR);
423  }
424
425  bool parseSectionDirectiveText(StringRef, SMLoc) {
426    return parseSectionSwitch("__TEXT", "__text",
427                              MachO::S_ATTR_PURE_INSTRUCTIONS);
428  }
429
430  bool parseSectionDirectiveTLV(StringRef, SMLoc) {
431    return parseSectionSwitch("__DATA", "__thread_vars",
432                              MachO::S_THREAD_LOCAL_VARIABLES);
433  }
434
435  bool parseSectionDirectiveIdent(StringRef, SMLoc) {
436    // Darwin silently ignores the .ident directive.
437    getParser().eatToEndOfStatement();
438    return false;
439  }
440
441  bool parseSectionDirectiveThreadInitFunc(StringRef, SMLoc) {
442    return parseSectionSwitch("__DATA", "__thread_init",
443                         MachO::S_THREAD_LOCAL_INIT_FUNCTION_POINTERS);
444  }
445
446  bool parseWatchOSVersionMin(StringRef Directive, SMLoc Loc) {
447    return parseVersionMin(Directive, Loc, MCVM_WatchOSVersionMin);
448  }
449  bool parseTvOSVersionMin(StringRef Directive, SMLoc Loc) {
450    return parseVersionMin(Directive, Loc, MCVM_TvOSVersionMin);
451  }
452  bool parseIOSVersionMin(StringRef Directive, SMLoc Loc) {
453    return parseVersionMin(Directive, Loc, MCVM_IOSVersionMin);
454  }
455  bool parseMacOSXVersionMin(StringRef Directive, SMLoc Loc) {
456    return parseVersionMin(Directive, Loc, MCVM_OSXVersionMin);
457  }
458
459  bool parseBuildVersion(StringRef Directive, SMLoc Loc);
460  bool parseVersionMin(StringRef Directive, SMLoc Loc, MCVersionMinType Type);
461  bool parseMajorMinorVersionComponent(unsigned *Major, unsigned *Minor,
462                                       const char *VersionName);
463  bool parseOptionalTrailingVersionComponent(unsigned *Component,
464                                             const char *ComponentName);
465  bool parseVersion(unsigned *Major, unsigned *Minor, unsigned *Update);
466  bool parseSDKVersion(VersionTuple &SDKVersion);
467  void checkVersion(StringRef Directive, StringRef Arg, SMLoc Loc,
468                    Triple::OSType ExpectedOS);
469  bool parseDirectiveCGProfile(StringRef Directive, SMLoc Loc);
470};
471
472} // end anonymous namespace
473
474bool DarwinAsmParser::parseSectionSwitch(StringRef Segment, StringRef Section,
475                                         unsigned TAA, unsigned Alignment,
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 (Alignment)
496    getStreamer().emitValueToAlignment(Align(Alignment));
497
498  return false;
499}
500
501/// parseDirectiveAltEntry
502///  ::= .alt_entry identifier
503bool 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
523bool 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
552bool 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"
586bool 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" )*
609bool 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
635bool 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)*
665bool 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)*
730bool 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
743bool DarwinAsmParser::parseDirectivePopSection(StringRef, SMLoc) {
744  if (!getStreamer().popSection())
745    return TokError(".popsection without corresponding .pushsection");
746  return false;
747}
748
749/// ParseDirectivePrevious:
750///   ::= .previous
751bool 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 ...
761bool 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  StringRef SecureLogFile = getContext().getSecureLogFile();
771  if (SecureLogFile.empty())
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>(
780        SecureLogFile, EC, sys::fs::OF_Append | sys::fs::OF_TextWithCRLF);
781    if (EC)
782       return Error(IDLoc, Twine("can't open secure log file: ") +
783                               SecureLogFile + " (" + EC.message() + ")");
784    OS = NewOS.get();
785    getContext().setSecureLog(std::move(NewOS));
786  }
787
788  // Write the message.
789  unsigned CurBuf = getSourceManager().FindBufferContainingLoc(IDLoc);
790  *OS << getSourceManager().getBufferInfo(CurBuf).Buffer->getBufferIdentifier()
791      << ":" << getSourceManager().FindLineNumber(IDLoc, CurBuf) << ":"
792      << LogMessage + "\n";
793
794  getContext().setSecureLogUsed(true);
795
796  return false;
797}
798
799/// ParseDirectiveSecureLogReset
800///  ::= .secure_log_reset
801bool DarwinAsmParser::parseDirectiveSecureLogReset(StringRef, SMLoc IDLoc) {
802  if (getLexer().isNot(AsmToken::EndOfStatement))
803    return TokError("unexpected token in '.secure_log_reset' directive");
804
805  Lex();
806
807  getContext().setSecureLogUsed(false);
808
809  return false;
810}
811
812/// parseDirectiveSubsectionsViaSymbols
813///  ::= .subsections_via_symbols
814bool DarwinAsmParser::parseDirectiveSubsectionsViaSymbols(StringRef, SMLoc) {
815  if (getLexer().isNot(AsmToken::EndOfStatement))
816    return TokError("unexpected token in '.subsections_via_symbols' directive");
817
818  Lex();
819
820  getStreamer().emitAssemblerFlag(MCAF_SubsectionsViaSymbols);
821
822  return false;
823}
824
825/// ParseDirectiveTBSS
826///  ::= .tbss identifier, size, align
827bool DarwinAsmParser::parseDirectiveTBSS(StringRef, SMLoc) {
828  SMLoc IDLoc = getLexer().getLoc();
829  StringRef Name;
830  if (getParser().parseIdentifier(Name))
831    return TokError("expected identifier in directive");
832
833  // Handle the identifier as the key symbol.
834  MCSymbol *Sym = getContext().getOrCreateSymbol(Name);
835
836  if (getLexer().isNot(AsmToken::Comma))
837    return TokError("unexpected token in directive");
838  Lex();
839
840  int64_t Size;
841  SMLoc SizeLoc = getLexer().getLoc();
842  if (getParser().parseAbsoluteExpression(Size))
843    return true;
844
845  int64_t Pow2Alignment = 0;
846  SMLoc Pow2AlignmentLoc;
847  if (getLexer().is(AsmToken::Comma)) {
848    Lex();
849    Pow2AlignmentLoc = getLexer().getLoc();
850    if (getParser().parseAbsoluteExpression(Pow2Alignment))
851      return true;
852  }
853
854  if (getLexer().isNot(AsmToken::EndOfStatement))
855    return TokError("unexpected token in '.tbss' directive");
856
857  Lex();
858
859  if (Size < 0)
860    return Error(SizeLoc, "invalid '.tbss' directive size, can't be less than"
861                 "zero");
862
863  // FIXME: Diagnose overflow.
864  if (Pow2Alignment < 0)
865    return Error(Pow2AlignmentLoc, "invalid '.tbss' alignment, can't be less"
866                 "than zero");
867
868  if (!Sym->isUndefined())
869    return Error(IDLoc, "invalid symbol redefinition");
870
871  getStreamer().emitTBSSSymbol(
872      getContext().getMachOSection("__DATA", "__thread_bss",
873                                   MachO::S_THREAD_LOCAL_ZEROFILL, 0,
874                                   SectionKind::getThreadBSS()),
875      Sym, Size, Align(1ULL << Pow2Alignment));
876
877  return false;
878}
879
880/// ParseDirectiveZerofill
881///  ::= .zerofill segname , sectname [, identifier , size_expression [
882///      , align_expression ]]
883bool DarwinAsmParser::parseDirectiveZerofill(StringRef, SMLoc) {
884  StringRef Segment;
885  if (getParser().parseIdentifier(Segment))
886    return TokError("expected segment name after '.zerofill' directive");
887
888  if (getLexer().isNot(AsmToken::Comma))
889    return TokError("unexpected token in directive");
890  Lex();
891
892  StringRef Section;
893  SMLoc SectionLoc = getLexer().getLoc();
894  if (getParser().parseIdentifier(Section))
895    return TokError("expected section name after comma in '.zerofill' "
896                    "directive");
897
898  // If this is the end of the line all that was wanted was to create the
899  // the section but with no symbol.
900  if (getLexer().is(AsmToken::EndOfStatement)) {
901    // Create the zerofill section but no symbol
902    getStreamer().emitZerofill(
903        getContext().getMachOSection(Segment, Section, MachO::S_ZEROFILL, 0,
904                                     SectionKind::getBSS()),
905        /*Symbol=*/nullptr, /*Size=*/0, Align(1), SectionLoc);
906    return false;
907  }
908
909  if (getLexer().isNot(AsmToken::Comma))
910    return TokError("unexpected token in directive");
911  Lex();
912
913  SMLoc IDLoc = getLexer().getLoc();
914  StringRef IDStr;
915  if (getParser().parseIdentifier(IDStr))
916    return TokError("expected identifier in directive");
917
918  // handle the identifier as the key symbol.
919  MCSymbol *Sym = getContext().getOrCreateSymbol(IDStr);
920
921  if (getLexer().isNot(AsmToken::Comma))
922    return TokError("unexpected token in directive");
923  Lex();
924
925  int64_t Size;
926  SMLoc SizeLoc = getLexer().getLoc();
927  if (getParser().parseAbsoluteExpression(Size))
928    return true;
929
930  int64_t Pow2Alignment = 0;
931  SMLoc Pow2AlignmentLoc;
932  if (getLexer().is(AsmToken::Comma)) {
933    Lex();
934    Pow2AlignmentLoc = getLexer().getLoc();
935    if (getParser().parseAbsoluteExpression(Pow2Alignment))
936      return true;
937  }
938
939  if (getLexer().isNot(AsmToken::EndOfStatement))
940    return TokError("unexpected token in '.zerofill' directive");
941
942  Lex();
943
944  if (Size < 0)
945    return Error(SizeLoc, "invalid '.zerofill' directive size, can't be less "
946                 "than zero");
947
948  // NOTE: The alignment in the directive is a power of 2 value, the assembler
949  // may internally end up wanting an alignment in bytes.
950  // FIXME: Diagnose overflow.
951  if (Pow2Alignment < 0)
952    return Error(Pow2AlignmentLoc, "invalid '.zerofill' directive alignment, "
953                 "can't be less than zero");
954
955  if (!Sym->isUndefined())
956    return Error(IDLoc, "invalid symbol redefinition");
957
958  // Create the zerofill Symbol with Size and Pow2Alignment
959  //
960  // FIXME: Arch specific.
961  getStreamer().emitZerofill(
962      getContext().getMachOSection(Segment, Section, MachO::S_ZEROFILL, 0,
963                                   SectionKind::getBSS()),
964      Sym, Size, Align(1ULL << Pow2Alignment), SectionLoc);
965
966  return false;
967}
968
969/// ParseDirectiveDataRegion
970///  ::= .data_region [ ( jt8 | jt16 | jt32 ) ]
971bool DarwinAsmParser::parseDirectiveDataRegion(StringRef, SMLoc) {
972  if (getLexer().is(AsmToken::EndOfStatement)) {
973    Lex();
974    getStreamer().emitDataRegion(MCDR_DataRegion);
975    return false;
976  }
977  StringRef RegionType;
978  SMLoc Loc = getParser().getTok().getLoc();
979  if (getParser().parseIdentifier(RegionType))
980    return TokError("expected region type after '.data_region' directive");
981  int Kind = StringSwitch<int>(RegionType)
982    .Case("jt8", MCDR_DataRegionJT8)
983    .Case("jt16", MCDR_DataRegionJT16)
984    .Case("jt32", MCDR_DataRegionJT32)
985    .Default(-1);
986  if (Kind == -1)
987    return Error(Loc, "unknown region type in '.data_region' directive");
988  Lex();
989
990  getStreamer().emitDataRegion((MCDataRegionType)Kind);
991  return false;
992}
993
994/// ParseDirectiveDataRegionEnd
995///  ::= .end_data_region
996bool DarwinAsmParser::parseDirectiveDataRegionEnd(StringRef, SMLoc) {
997  if (getLexer().isNot(AsmToken::EndOfStatement))
998    return TokError("unexpected token in '.end_data_region' directive");
999
1000  Lex();
1001  getStreamer().emitDataRegion(MCDR_DataRegionEnd);
1002  return false;
1003}
1004
1005static bool isSDKVersionToken(const AsmToken &Tok) {
1006  return Tok.is(AsmToken::Identifier) && Tok.getIdentifier() == "sdk_version";
1007}
1008
1009/// parseMajorMinorVersionComponent ::= major, minor
1010bool DarwinAsmParser::parseMajorMinorVersionComponent(unsigned *Major,
1011                                                      unsigned *Minor,
1012                                                      const char *VersionName) {
1013  // Get the major version number.
1014  if (getLexer().isNot(AsmToken::Integer))
1015    return TokError(Twine("invalid ") + VersionName +
1016                    " major version number, integer expected");
1017  int64_t MajorVal = getLexer().getTok().getIntVal();
1018  if (MajorVal > 65535 || MajorVal <= 0)
1019    return TokError(Twine("invalid ") + VersionName + " major version number");
1020  *Major = (unsigned)MajorVal;
1021  Lex();
1022  if (getLexer().isNot(AsmToken::Comma))
1023    return TokError(Twine(VersionName) +
1024                    " minor version number required, comma expected");
1025  Lex();
1026  // Get the minor version number.
1027  if (getLexer().isNot(AsmToken::Integer))
1028    return TokError(Twine("invalid ") + VersionName +
1029                    " minor version number, integer expected");
1030  int64_t MinorVal = getLexer().getTok().getIntVal();
1031  if (MinorVal > 255 || MinorVal < 0)
1032    return TokError(Twine("invalid ") + VersionName + " minor version number");
1033  *Minor = MinorVal;
1034  Lex();
1035  return false;
1036}
1037
1038/// parseOptionalTrailingVersionComponent ::= , version_number
1039bool DarwinAsmParser::parseOptionalTrailingVersionComponent(
1040    unsigned *Component, const char *ComponentName) {
1041  assert(getLexer().is(AsmToken::Comma) && "comma expected");
1042  Lex();
1043  if (getLexer().isNot(AsmToken::Integer))
1044    return TokError(Twine("invalid ") + ComponentName +
1045                    " version number, integer expected");
1046  int64_t Val = getLexer().getTok().getIntVal();
1047  if (Val > 255 || Val < 0)
1048    return TokError(Twine("invalid ") + ComponentName + " version number");
1049  *Component = Val;
1050  Lex();
1051  return false;
1052}
1053
1054/// parseVersion ::= parseMajorMinorVersionComponent
1055///                      parseOptionalTrailingVersionComponent
1056bool DarwinAsmParser::parseVersion(unsigned *Major, unsigned *Minor,
1057                                   unsigned *Update) {
1058  if (parseMajorMinorVersionComponent(Major, Minor, "OS"))
1059    return true;
1060
1061  // Get the update level, if specified
1062  *Update = 0;
1063  if (getLexer().is(AsmToken::EndOfStatement) ||
1064      isSDKVersionToken(getLexer().getTok()))
1065    return false;
1066  if (getLexer().isNot(AsmToken::Comma))
1067    return TokError("invalid OS update specifier, comma expected");
1068  if (parseOptionalTrailingVersionComponent(Update, "OS update"))
1069    return true;
1070  return false;
1071}
1072
1073bool DarwinAsmParser::parseSDKVersion(VersionTuple &SDKVersion) {
1074  assert(isSDKVersionToken(getLexer().getTok()) && "expected sdk_version");
1075  Lex();
1076  unsigned Major, Minor;
1077  if (parseMajorMinorVersionComponent(&Major, &Minor, "SDK"))
1078    return true;
1079  SDKVersion = VersionTuple(Major, Minor);
1080
1081  // Get the subminor version, if specified.
1082  if (getLexer().is(AsmToken::Comma)) {
1083    unsigned Subminor;
1084    if (parseOptionalTrailingVersionComponent(&Subminor, "SDK subminor"))
1085      return true;
1086    SDKVersion = VersionTuple(Major, Minor, Subminor);
1087  }
1088  return false;
1089}
1090
1091void DarwinAsmParser::checkVersion(StringRef Directive, StringRef Arg,
1092                                   SMLoc Loc, Triple::OSType ExpectedOS) {
1093  const Triple &Target = getContext().getTargetTriple();
1094  if (Target.getOS() != ExpectedOS)
1095    Warning(Loc, Twine(Directive) +
1096            (Arg.empty() ? Twine() : Twine(' ') + Arg) +
1097            " used while targeting " + Target.getOSName());
1098
1099  if (LastVersionDirective.isValid()) {
1100    Warning(Loc, "overriding previous version directive");
1101    Note(LastVersionDirective, "previous definition is here");
1102  }
1103  LastVersionDirective = Loc;
1104}
1105
1106static Triple::OSType getOSTypeFromMCVM(MCVersionMinType Type) {
1107  switch (Type) {
1108  case MCVM_WatchOSVersionMin: return Triple::WatchOS;
1109  case MCVM_TvOSVersionMin:    return Triple::TvOS;
1110  case MCVM_IOSVersionMin:     return Triple::IOS;
1111  case MCVM_OSXVersionMin:     return Triple::MacOSX;
1112  }
1113  llvm_unreachable("Invalid mc version min type");
1114}
1115
1116/// parseVersionMin
1117///   ::= .ios_version_min parseVersion parseSDKVersion
1118///   |   .macosx_version_min parseVersion parseSDKVersion
1119///   |   .tvos_version_min parseVersion parseSDKVersion
1120///   |   .watchos_version_min parseVersion parseSDKVersion
1121bool DarwinAsmParser::parseVersionMin(StringRef Directive, SMLoc Loc,
1122                                      MCVersionMinType Type) {
1123  unsigned Major;
1124  unsigned Minor;
1125  unsigned Update;
1126  if (parseVersion(&Major, &Minor, &Update))
1127    return true;
1128
1129  VersionTuple SDKVersion;
1130  if (isSDKVersionToken(getLexer().getTok()) && parseSDKVersion(SDKVersion))
1131    return true;
1132
1133  if (parseEOL())
1134    return addErrorSuffix(Twine(" in '") + Directive + "' directive");
1135
1136  Triple::OSType ExpectedOS = getOSTypeFromMCVM(Type);
1137  checkVersion(Directive, StringRef(), Loc, ExpectedOS);
1138  getStreamer().emitVersionMin(Type, Major, Minor, Update, SDKVersion);
1139  return false;
1140}
1141
1142static Triple::OSType getOSTypeFromPlatform(MachO::PlatformType Type) {
1143  switch (Type) {
1144  case MachO::PLATFORM_UNKNOWN: /* silence warning */
1145    break;
1146  case MachO::PLATFORM_MACOS:   return Triple::MacOSX;
1147  case MachO::PLATFORM_IOS:     return Triple::IOS;
1148  case MachO::PLATFORM_TVOS:    return Triple::TvOS;
1149  case MachO::PLATFORM_WATCHOS: return Triple::WatchOS;
1150  case MachO::PLATFORM_XROS:    return Triple::XROS;
1151  case MachO::PLATFORM_BRIDGEOS:         /* silence warning */ break;
1152  case MachO::PLATFORM_DRIVERKIT:
1153    return Triple::DriverKit;
1154  case MachO::PLATFORM_MACCATALYST: return Triple::IOS;
1155  case MachO::PLATFORM_IOSSIMULATOR:     /* silence warning */ break;
1156  case MachO::PLATFORM_TVOSSIMULATOR:    /* silence warning */ break;
1157  case MachO::PLATFORM_WATCHOSSIMULATOR: /* silence warning */ break;
1158  case MachO::PLATFORM_XROS_SIMULATOR:   /* silence warning */ break;
1159  }
1160  llvm_unreachable("Invalid mach-o platform type");
1161}
1162
1163/// parseBuildVersion
1164///   ::= .build_version (macos|ios|tvos|watchos), parseVersion parseSDKVersion
1165bool DarwinAsmParser::parseBuildVersion(StringRef Directive, SMLoc Loc) {
1166  StringRef PlatformName;
1167  SMLoc PlatformLoc = getTok().getLoc();
1168  if (getParser().parseIdentifier(PlatformName))
1169    return TokError("platform name expected");
1170
1171  unsigned Platform = StringSwitch<unsigned>(PlatformName)
1172#define PLATFORM(platform, id, name, build_name, target, tapi_target,          \
1173                 marketing)                                                    \
1174  .Case(#build_name, MachO::PLATFORM_##platform)
1175#include "llvm/BinaryFormat/MachO.def"
1176                          .Default(MachO::PLATFORM_UNKNOWN);
1177
1178  if (Platform == MachO::PLATFORM_UNKNOWN)
1179    return Error(PlatformLoc, "unknown platform name");
1180
1181  if (getLexer().isNot(AsmToken::Comma))
1182    return TokError("version number required, comma expected");
1183  Lex();
1184
1185  unsigned Major;
1186  unsigned Minor;
1187  unsigned Update;
1188  if (parseVersion(&Major, &Minor, &Update))
1189    return true;
1190
1191  VersionTuple SDKVersion;
1192  if (isSDKVersionToken(getLexer().getTok()) && parseSDKVersion(SDKVersion))
1193    return true;
1194
1195  if (parseEOL())
1196    return addErrorSuffix(" in '.build_version' directive");
1197
1198  Triple::OSType ExpectedOS
1199    = getOSTypeFromPlatform((MachO::PlatformType)Platform);
1200  checkVersion(Directive, PlatformName, Loc, ExpectedOS);
1201  getStreamer().emitBuildVersion(Platform, Major, Minor, Update, SDKVersion);
1202  return false;
1203}
1204
1205/// parseDirectiveCGProfile
1206///   ::= .cg_profile from, to, count
1207bool DarwinAsmParser::parseDirectiveCGProfile(StringRef S, SMLoc Loc) {
1208  return MCAsmParserExtension::ParseDirectiveCGProfile(S, Loc);
1209}
1210
1211namespace llvm {
1212
1213MCAsmParserExtension *createDarwinAsmParser() {
1214  return new DarwinAsmParser;
1215}
1216
1217} // end llvm namespace
1218