DarwinAsmParser.cpp revision 36b56886974eae4f9c5ebc96befd3e7bfe5de338
1//===- DarwinAsmParser.cpp - Darwin (Mach-O) Assembly Parser --------------===//
2//
3//                     The LLVM Compiler Infrastructure
4//
5// This file is distributed under the University of Illinois Open Source
6// License. See LICENSE.TXT for details.
7//
8//===----------------------------------------------------------------------===//
9
10#include "llvm/MC/MCParser/MCAsmParserExtension.h"
11#include "llvm/ADT/StringRef.h"
12#include "llvm/ADT/StringSwitch.h"
13#include "llvm/ADT/Twine.h"
14#include "llvm/MC/MCContext.h"
15#include "llvm/MC/MCParser/MCAsmLexer.h"
16#include "llvm/MC/MCParser/MCAsmParser.h"
17#include "llvm/MC/MCSectionMachO.h"
18#include "llvm/MC/MCStreamer.h"
19#include "llvm/MC/MCSymbol.h"
20#include "llvm/Support/MemoryBuffer.h"
21#include "llvm/Support/SourceMgr.h"
22using namespace llvm;
23
24namespace {
25
26/// \brief Implementation of directive handling which is shared across all
27/// Darwin targets.
28class DarwinAsmParser : public MCAsmParserExtension {
29  template<bool (DarwinAsmParser::*HandlerMethod)(StringRef, SMLoc)>
30  void addDirectiveHandler(StringRef Directive) {
31    MCAsmParser::ExtensionDirectiveHandler Handler = std::make_pair(
32        this, HandleDirective<DarwinAsmParser, HandlerMethod>);
33    getParser().addDirectiveHandler(Directive, Handler);
34  }
35
36  bool parseSectionSwitch(const char *Segment, const char *Section,
37                          unsigned TAA = 0, unsigned ImplicitAlign = 0,
38                          unsigned StubSize = 0);
39
40public:
41  DarwinAsmParser() {}
42
43  void Initialize(MCAsmParser &Parser) override {
44    // Call the base implementation.
45    this->MCAsmParserExtension::Initialize(Parser);
46
47    addDirectiveHandler<&DarwinAsmParser::parseDirectiveDesc>(".desc");
48    addDirectiveHandler<&DarwinAsmParser::parseDirectiveIndirectSymbol>(
49      ".indirect_symbol");
50    addDirectiveHandler<&DarwinAsmParser::parseDirectiveLsym>(".lsym");
51    addDirectiveHandler<&DarwinAsmParser::parseDirectiveSubsectionsViaSymbols>(
52      ".subsections_via_symbols");
53    addDirectiveHandler<&DarwinAsmParser::parseDirectiveDumpOrLoad>(".dump");
54    addDirectiveHandler<&DarwinAsmParser::parseDirectiveDumpOrLoad>(".load");
55    addDirectiveHandler<&DarwinAsmParser::parseDirectiveSection>(".section");
56    addDirectiveHandler<&DarwinAsmParser::parseDirectivePushSection>(
57      ".pushsection");
58    addDirectiveHandler<&DarwinAsmParser::parseDirectivePopSection>(
59      ".popsection");
60    addDirectiveHandler<&DarwinAsmParser::parseDirectivePrevious>(".previous");
61    addDirectiveHandler<&DarwinAsmParser::parseDirectiveSecureLogUnique>(
62      ".secure_log_unique");
63    addDirectiveHandler<&DarwinAsmParser::parseDirectiveSecureLogReset>(
64      ".secure_log_reset");
65    addDirectiveHandler<&DarwinAsmParser::parseDirectiveTBSS>(".tbss");
66    addDirectiveHandler<&DarwinAsmParser::parseDirectiveZerofill>(".zerofill");
67
68    addDirectiveHandler<&DarwinAsmParser::parseDirectiveDataRegion>(
69      ".data_region");
70    addDirectiveHandler<&DarwinAsmParser::parseDirectiveDataRegionEnd>(
71      ".end_data_region");
72
73    // Special section directives.
74    addDirectiveHandler<&DarwinAsmParser::parseSectionDirectiveBss>(".bss");
75    addDirectiveHandler<&DarwinAsmParser::parseSectionDirectiveConst>(".const");
76    addDirectiveHandler<&DarwinAsmParser::parseSectionDirectiveConstData>(
77      ".const_data");
78    addDirectiveHandler<&DarwinAsmParser::parseSectionDirectiveConstructor>(
79      ".constructor");
80    addDirectiveHandler<&DarwinAsmParser::parseSectionDirectiveCString>(
81      ".cstring");
82    addDirectiveHandler<&DarwinAsmParser::parseSectionDirectiveData>(".data");
83    addDirectiveHandler<&DarwinAsmParser::parseSectionDirectiveDestructor>(
84      ".destructor");
85    addDirectiveHandler<&DarwinAsmParser::parseSectionDirectiveDyld>(".dyld");
86    addDirectiveHandler<&DarwinAsmParser::parseSectionDirectiveFVMLibInit0>(
87      ".fvmlib_init0");
88    addDirectiveHandler<&DarwinAsmParser::parseSectionDirectiveFVMLibInit1>(
89      ".fvmlib_init1");
90    addDirectiveHandler<
91      &DarwinAsmParser::parseSectionDirectiveLazySymbolPointers>(
92        ".lazy_symbol_pointer");
93    addDirectiveHandler<&DarwinAsmParser::parseDirectiveLinkerOption>(
94      ".linker_option");
95    addDirectiveHandler<&DarwinAsmParser::parseSectionDirectiveLiteral16>(
96      ".literal16");
97    addDirectiveHandler<&DarwinAsmParser::parseSectionDirectiveLiteral4>(
98      ".literal4");
99    addDirectiveHandler<&DarwinAsmParser::parseSectionDirectiveLiteral8>(
100      ".literal8");
101    addDirectiveHandler<&DarwinAsmParser::parseSectionDirectiveModInitFunc>(
102      ".mod_init_func");
103    addDirectiveHandler<&DarwinAsmParser::parseSectionDirectiveModTermFunc>(
104      ".mod_term_func");
105    addDirectiveHandler<
106      &DarwinAsmParser::parseSectionDirectiveNonLazySymbolPointers>(
107        ".non_lazy_symbol_pointer");
108    addDirectiveHandler<&DarwinAsmParser::parseSectionDirectiveObjCCatClsMeth>(
109      ".objc_cat_cls_meth");
110    addDirectiveHandler<&DarwinAsmParser::parseSectionDirectiveObjCCatInstMeth>(
111      ".objc_cat_inst_meth");
112    addDirectiveHandler<&DarwinAsmParser::parseSectionDirectiveObjCCategory>(
113      ".objc_category");
114    addDirectiveHandler<&DarwinAsmParser::parseSectionDirectiveObjCClass>(
115      ".objc_class");
116    addDirectiveHandler<&DarwinAsmParser::parseSectionDirectiveObjCClassNames>(
117      ".objc_class_names");
118    addDirectiveHandler<&DarwinAsmParser::parseSectionDirectiveObjCClassVars>(
119      ".objc_class_vars");
120    addDirectiveHandler<&DarwinAsmParser::parseSectionDirectiveObjCClsMeth>(
121      ".objc_cls_meth");
122    addDirectiveHandler<&DarwinAsmParser::parseSectionDirectiveObjCClsRefs>(
123      ".objc_cls_refs");
124    addDirectiveHandler<&DarwinAsmParser::parseSectionDirectiveObjCInstMeth>(
125      ".objc_inst_meth");
126    addDirectiveHandler<
127      &DarwinAsmParser::parseSectionDirectiveObjCInstanceVars>(
128        ".objc_instance_vars");
129    addDirectiveHandler<&DarwinAsmParser::parseSectionDirectiveObjCMessageRefs>(
130      ".objc_message_refs");
131    addDirectiveHandler<&DarwinAsmParser::parseSectionDirectiveObjCMetaClass>(
132      ".objc_meta_class");
133    addDirectiveHandler<
134      &DarwinAsmParser::parseSectionDirectiveObjCMethVarNames>(
135        ".objc_meth_var_names");
136    addDirectiveHandler<
137      &DarwinAsmParser::parseSectionDirectiveObjCMethVarTypes>(
138        ".objc_meth_var_types");
139    addDirectiveHandler<&DarwinAsmParser::parseSectionDirectiveObjCModuleInfo>(
140      ".objc_module_info");
141    addDirectiveHandler<&DarwinAsmParser::parseSectionDirectiveObjCProtocol>(
142      ".objc_protocol");
143    addDirectiveHandler<
144      &DarwinAsmParser::parseSectionDirectiveObjCSelectorStrs>(
145        ".objc_selector_strs");
146    addDirectiveHandler<
147      &DarwinAsmParser::parseSectionDirectiveObjCStringObject>(
148        ".objc_string_object");
149    addDirectiveHandler<&DarwinAsmParser::parseSectionDirectiveObjCSymbols>(
150      ".objc_symbols");
151    addDirectiveHandler<&DarwinAsmParser::parseSectionDirectivePICSymbolStub>(
152      ".picsymbol_stub");
153    addDirectiveHandler<&DarwinAsmParser::parseSectionDirectiveStaticConst>(
154      ".static_const");
155    addDirectiveHandler<&DarwinAsmParser::parseSectionDirectiveStaticData>(
156      ".static_data");
157    addDirectiveHandler<&DarwinAsmParser::parseSectionDirectiveSymbolStub>(
158      ".symbol_stub");
159    addDirectiveHandler<&DarwinAsmParser::parseSectionDirectiveTData>(".tdata");
160    addDirectiveHandler<&DarwinAsmParser::parseSectionDirectiveText>(".text");
161    addDirectiveHandler<&DarwinAsmParser::parseSectionDirectiveThreadInitFunc>(
162      ".thread_init_func");
163    addDirectiveHandler<&DarwinAsmParser::parseSectionDirectiveTLV>(".tlv");
164
165    addDirectiveHandler<&DarwinAsmParser::parseSectionDirectiveIdent>(".ident");
166    addDirectiveHandler<&DarwinAsmParser::parseVersionMin>(".ios_version_min");
167    addDirectiveHandler<&DarwinAsmParser::parseVersionMin>(
168      ".macosx_version_min");
169  }
170
171  bool parseDirectiveDesc(StringRef, SMLoc);
172  bool parseDirectiveIndirectSymbol(StringRef, SMLoc);
173  bool parseDirectiveDumpOrLoad(StringRef, SMLoc);
174  bool parseDirectiveLsym(StringRef, SMLoc);
175  bool parseDirectiveLinkerOption(StringRef, SMLoc);
176  bool parseDirectiveSection(StringRef, SMLoc);
177  bool parseDirectivePushSection(StringRef, SMLoc);
178  bool parseDirectivePopSection(StringRef, SMLoc);
179  bool parseDirectivePrevious(StringRef, SMLoc);
180  bool parseDirectiveSecureLogReset(StringRef, SMLoc);
181  bool parseDirectiveSecureLogUnique(StringRef, SMLoc);
182  bool parseDirectiveSubsectionsViaSymbols(StringRef, SMLoc);
183  bool parseDirectiveTBSS(StringRef, SMLoc);
184  bool parseDirectiveZerofill(StringRef, SMLoc);
185  bool parseDirectiveDataRegion(StringRef, SMLoc);
186  bool parseDirectiveDataRegionEnd(StringRef, SMLoc);
187
188  // Named Section Directive
189  bool parseSectionDirectiveBss(StringRef, SMLoc) {
190    return parseSectionSwitch("__DATA", "__bss");
191  }
192
193  bool parseSectionDirectiveConst(StringRef, SMLoc) {
194    return parseSectionSwitch("__TEXT", "__const");
195  }
196  bool parseSectionDirectiveStaticConst(StringRef, SMLoc) {
197    return parseSectionSwitch("__TEXT", "__static_const");
198  }
199  bool parseSectionDirectiveCString(StringRef, SMLoc) {
200    return parseSectionSwitch("__TEXT","__cstring",
201                              MachO::S_CSTRING_LITERALS);
202  }
203  bool parseSectionDirectiveLiteral4(StringRef, SMLoc) {
204    return parseSectionSwitch("__TEXT", "__literal4",
205                              MachO::S_4BYTE_LITERALS, 4);
206  }
207  bool parseSectionDirectiveLiteral8(StringRef, SMLoc) {
208    return parseSectionSwitch("__TEXT", "__literal8",
209                              MachO::S_8BYTE_LITERALS, 8);
210  }
211  bool parseSectionDirectiveLiteral16(StringRef, SMLoc) {
212    return parseSectionSwitch("__TEXT","__literal16",
213                              MachO::S_16BYTE_LITERALS, 16);
214  }
215  bool parseSectionDirectiveConstructor(StringRef, SMLoc) {
216    return parseSectionSwitch("__TEXT","__constructor");
217  }
218  bool parseSectionDirectiveDestructor(StringRef, SMLoc) {
219    return parseSectionSwitch("__TEXT","__destructor");
220  }
221  bool parseSectionDirectiveFVMLibInit0(StringRef, SMLoc) {
222    return parseSectionSwitch("__TEXT","__fvmlib_init0");
223  }
224  bool parseSectionDirectiveFVMLibInit1(StringRef, SMLoc) {
225    return parseSectionSwitch("__TEXT","__fvmlib_init1");
226  }
227  bool parseSectionDirectiveSymbolStub(StringRef, SMLoc) {
228    return parseSectionSwitch("__TEXT","__symbol_stub",
229                              MachO::S_SYMBOL_STUBS |
230                              MachO::S_ATTR_PURE_INSTRUCTIONS,
231                              // FIXME: Different on PPC and ARM.
232                              0, 16);
233  }
234  bool parseSectionDirectivePICSymbolStub(StringRef, SMLoc) {
235    return parseSectionSwitch("__TEXT","__picsymbol_stub",
236                              MachO::S_SYMBOL_STUBS |
237                              MachO::S_ATTR_PURE_INSTRUCTIONS, 0, 26);
238  }
239  bool parseSectionDirectiveData(StringRef, SMLoc) {
240    return parseSectionSwitch("__DATA", "__data");
241  }
242  bool parseSectionDirectiveStaticData(StringRef, SMLoc) {
243    return parseSectionSwitch("__DATA", "__static_data");
244  }
245  bool parseSectionDirectiveNonLazySymbolPointers(StringRef, SMLoc) {
246    return parseSectionSwitch("__DATA", "__nl_symbol_ptr",
247                              MachO::S_NON_LAZY_SYMBOL_POINTERS, 4);
248  }
249  bool parseSectionDirectiveLazySymbolPointers(StringRef, SMLoc) {
250    return parseSectionSwitch("__DATA", "__la_symbol_ptr",
251                              MachO::S_LAZY_SYMBOL_POINTERS, 4);
252  }
253  bool parseSectionDirectiveDyld(StringRef, SMLoc) {
254    return parseSectionSwitch("__DATA", "__dyld");
255  }
256  bool parseSectionDirectiveModInitFunc(StringRef, SMLoc) {
257    return parseSectionSwitch("__DATA", "__mod_init_func",
258                              MachO::S_MOD_INIT_FUNC_POINTERS, 4);
259  }
260  bool parseSectionDirectiveModTermFunc(StringRef, SMLoc) {
261    return parseSectionSwitch("__DATA", "__mod_term_func",
262                              MachO::S_MOD_TERM_FUNC_POINTERS, 4);
263  }
264  bool parseSectionDirectiveConstData(StringRef, SMLoc) {
265    return parseSectionSwitch("__DATA", "__const");
266  }
267  bool parseSectionDirectiveObjCClass(StringRef, SMLoc) {
268    return parseSectionSwitch("__OBJC", "__class",
269                              MachO::S_ATTR_NO_DEAD_STRIP);
270  }
271  bool parseSectionDirectiveObjCMetaClass(StringRef, SMLoc) {
272    return parseSectionSwitch("__OBJC", "__meta_class",
273                              MachO::S_ATTR_NO_DEAD_STRIP);
274  }
275  bool parseSectionDirectiveObjCCatClsMeth(StringRef, SMLoc) {
276    return parseSectionSwitch("__OBJC", "__cat_cls_meth",
277                              MachO::S_ATTR_NO_DEAD_STRIP);
278  }
279  bool parseSectionDirectiveObjCCatInstMeth(StringRef, SMLoc) {
280    return parseSectionSwitch("__OBJC", "__cat_inst_meth",
281                              MachO::S_ATTR_NO_DEAD_STRIP);
282  }
283  bool parseSectionDirectiveObjCProtocol(StringRef, SMLoc) {
284    return parseSectionSwitch("__OBJC", "__protocol",
285                              MachO::S_ATTR_NO_DEAD_STRIP);
286  }
287  bool parseSectionDirectiveObjCStringObject(StringRef, SMLoc) {
288    return parseSectionSwitch("__OBJC", "__string_object",
289                              MachO::S_ATTR_NO_DEAD_STRIP);
290  }
291  bool parseSectionDirectiveObjCClsMeth(StringRef, SMLoc) {
292    return parseSectionSwitch("__OBJC", "__cls_meth",
293                              MachO::S_ATTR_NO_DEAD_STRIP);
294  }
295  bool parseSectionDirectiveObjCInstMeth(StringRef, SMLoc) {
296    return parseSectionSwitch("__OBJC", "__inst_meth",
297                              MachO::S_ATTR_NO_DEAD_STRIP);
298  }
299  bool parseSectionDirectiveObjCClsRefs(StringRef, SMLoc) {
300    return parseSectionSwitch("__OBJC", "__cls_refs",
301                              MachO::S_ATTR_NO_DEAD_STRIP |
302                              MachO::S_LITERAL_POINTERS, 4);
303  }
304  bool parseSectionDirectiveObjCMessageRefs(StringRef, SMLoc) {
305    return parseSectionSwitch("__OBJC", "__message_refs",
306                              MachO::S_ATTR_NO_DEAD_STRIP |
307                              MachO::S_LITERAL_POINTERS, 4);
308  }
309  bool parseSectionDirectiveObjCSymbols(StringRef, SMLoc) {
310    return parseSectionSwitch("__OBJC", "__symbols",
311                              MachO::S_ATTR_NO_DEAD_STRIP);
312  }
313  bool parseSectionDirectiveObjCCategory(StringRef, SMLoc) {
314    return parseSectionSwitch("__OBJC", "__category",
315                              MachO::S_ATTR_NO_DEAD_STRIP);
316  }
317  bool parseSectionDirectiveObjCClassVars(StringRef, SMLoc) {
318    return parseSectionSwitch("__OBJC", "__class_vars",
319                              MachO::S_ATTR_NO_DEAD_STRIP);
320  }
321  bool parseSectionDirectiveObjCInstanceVars(StringRef, SMLoc) {
322    return parseSectionSwitch("__OBJC", "__instance_vars",
323                              MachO::S_ATTR_NO_DEAD_STRIP);
324  }
325  bool parseSectionDirectiveObjCModuleInfo(StringRef, SMLoc) {
326    return parseSectionSwitch("__OBJC", "__module_info",
327                              MachO::S_ATTR_NO_DEAD_STRIP);
328  }
329  bool parseSectionDirectiveObjCClassNames(StringRef, SMLoc) {
330    return parseSectionSwitch("__TEXT", "__cstring",
331                              MachO::S_CSTRING_LITERALS);
332  }
333  bool parseSectionDirectiveObjCMethVarTypes(StringRef, SMLoc) {
334    return parseSectionSwitch("__TEXT", "__cstring",
335                              MachO::S_CSTRING_LITERALS);
336  }
337  bool parseSectionDirectiveObjCMethVarNames(StringRef, SMLoc) {
338    return parseSectionSwitch("__TEXT", "__cstring",
339                              MachO::S_CSTRING_LITERALS);
340  }
341  bool parseSectionDirectiveObjCSelectorStrs(StringRef, SMLoc) {
342    return parseSectionSwitch("__OBJC", "__selector_strs",
343                              MachO::S_CSTRING_LITERALS);
344  }
345  bool parseSectionDirectiveTData(StringRef, SMLoc) {
346    return parseSectionSwitch("__DATA", "__thread_data",
347                              MachO::S_THREAD_LOCAL_REGULAR);
348  }
349  bool parseSectionDirectiveText(StringRef, SMLoc) {
350    return parseSectionSwitch("__TEXT", "__text",
351                              MachO::S_ATTR_PURE_INSTRUCTIONS);
352  }
353  bool parseSectionDirectiveTLV(StringRef, SMLoc) {
354    return parseSectionSwitch("__DATA", "__thread_vars",
355                              MachO::S_THREAD_LOCAL_VARIABLES);
356  }
357  bool parseSectionDirectiveIdent(StringRef, SMLoc) {
358    // Darwin silently ignores the .ident directive.
359    getParser().eatToEndOfStatement();
360    return false;
361  }
362  bool parseSectionDirectiveThreadInitFunc(StringRef, SMLoc) {
363    return parseSectionSwitch("__DATA", "__thread_init",
364                         MachO::S_THREAD_LOCAL_INIT_FUNCTION_POINTERS);
365  }
366  bool parseVersionMin(StringRef, SMLoc);
367
368};
369
370} // end anonymous namespace
371
372bool DarwinAsmParser::parseSectionSwitch(const char *Segment,
373                                         const char *Section,
374                                         unsigned TAA, unsigned Align,
375                                         unsigned StubSize) {
376  if (getLexer().isNot(AsmToken::EndOfStatement))
377    return TokError("unexpected token in section switching directive");
378  Lex();
379
380  // FIXME: Arch specific.
381  bool isText = TAA & MachO::S_ATTR_PURE_INSTRUCTIONS;
382  getStreamer().SwitchSection(getContext().getMachOSection(
383                                Segment, Section, TAA, StubSize,
384                                isText ? SectionKind::getText()
385                                       : SectionKind::getDataRel()));
386
387  // Set the implicit alignment, if any.
388  //
389  // FIXME: This isn't really what 'as' does; I think it just uses the implicit
390  // alignment on the section (e.g., if one manually inserts bytes into the
391  // section, then just issuing the section switch directive will not realign
392  // the section. However, this is arguably more reasonable behavior, and there
393  // is no good reason for someone to intentionally emit incorrectly sized
394  // values into the implicitly aligned sections.
395  if (Align)
396    getStreamer().EmitValueToAlignment(Align);
397
398  return false;
399}
400
401/// parseDirectiveDesc
402///  ::= .desc identifier , expression
403bool DarwinAsmParser::parseDirectiveDesc(StringRef, SMLoc) {
404  StringRef Name;
405  if (getParser().parseIdentifier(Name))
406    return TokError("expected identifier in directive");
407
408  // Handle the identifier as the key symbol.
409  MCSymbol *Sym = getContext().GetOrCreateSymbol(Name);
410
411  if (getLexer().isNot(AsmToken::Comma))
412    return TokError("unexpected token in '.desc' directive");
413  Lex();
414
415  int64_t DescValue;
416  if (getParser().parseAbsoluteExpression(DescValue))
417    return true;
418
419  if (getLexer().isNot(AsmToken::EndOfStatement))
420    return TokError("unexpected token in '.desc' directive");
421
422  Lex();
423
424  // Set the n_desc field of this Symbol to this DescValue
425  getStreamer().EmitSymbolDesc(Sym, DescValue);
426
427  return false;
428}
429
430/// parseDirectiveIndirectSymbol
431///  ::= .indirect_symbol identifier
432bool DarwinAsmParser::parseDirectiveIndirectSymbol(StringRef, SMLoc Loc) {
433  const MCSectionMachO *Current = static_cast<const MCSectionMachO*>(
434                                       getStreamer().getCurrentSection().first);
435  MachO::SectionType SectionType = Current->getType();
436  if (SectionType != MachO::S_NON_LAZY_SYMBOL_POINTERS &&
437      SectionType != MachO::S_LAZY_SYMBOL_POINTERS &&
438      SectionType != MachO::S_SYMBOL_STUBS)
439    return Error(Loc, "indirect symbol not in a symbol pointer or stub "
440                      "section");
441
442  StringRef Name;
443  if (getParser().parseIdentifier(Name))
444    return TokError("expected identifier in .indirect_symbol directive");
445
446  MCSymbol *Sym = getContext().GetOrCreateSymbol(Name);
447
448  // Assembler local symbols don't make any sense here. Complain loudly.
449  if (Sym->isTemporary())
450    return TokError("non-local symbol required in directive");
451
452  if (!getStreamer().EmitSymbolAttribute(Sym, MCSA_IndirectSymbol))
453    return TokError("unable to emit indirect symbol attribute for: " + Name);
454
455  if (getLexer().isNot(AsmToken::EndOfStatement))
456    return TokError("unexpected token in '.indirect_symbol' directive");
457
458  Lex();
459
460  return false;
461}
462
463/// parseDirectiveDumpOrLoad
464///  ::= ( .dump | .load ) "filename"
465bool DarwinAsmParser::parseDirectiveDumpOrLoad(StringRef Directive,
466                                               SMLoc IDLoc) {
467  bool IsDump = Directive == ".dump";
468  if (getLexer().isNot(AsmToken::String))
469    return TokError("expected string in '.dump' or '.load' directive");
470
471  Lex();
472
473  if (getLexer().isNot(AsmToken::EndOfStatement))
474    return TokError("unexpected token in '.dump' or '.load' directive");
475
476  Lex();
477
478  // FIXME: If/when .dump and .load are implemented they will be done in the
479  // the assembly parser and not have any need for an MCStreamer API.
480  if (IsDump)
481    return Warning(IDLoc, "ignoring directive .dump for now");
482  else
483    return Warning(IDLoc, "ignoring directive .load for now");
484}
485
486/// ParseDirectiveLinkerOption
487///  ::= .linker_option "string" ( , "string" )*
488bool DarwinAsmParser::parseDirectiveLinkerOption(StringRef IDVal, SMLoc) {
489  SmallVector<std::string, 4> Args;
490  for (;;) {
491    if (getLexer().isNot(AsmToken::String))
492      return TokError("expected string in '" + Twine(IDVal) + "' directive");
493
494    std::string Data;
495    if (getParser().parseEscapedString(Data))
496      return true;
497
498    Args.push_back(Data);
499
500    Lex();
501    if (getLexer().is(AsmToken::EndOfStatement))
502      break;
503
504    if (getLexer().isNot(AsmToken::Comma))
505      return TokError("unexpected token in '" + Twine(IDVal) + "' directive");
506    Lex();
507  }
508
509  getStreamer().EmitLinkerOptions(Args);
510  return false;
511}
512
513/// parseDirectiveLsym
514///  ::= .lsym identifier , expression
515bool DarwinAsmParser::parseDirectiveLsym(StringRef, SMLoc) {
516  StringRef Name;
517  if (getParser().parseIdentifier(Name))
518    return TokError("expected identifier in directive");
519
520  // Handle the identifier as the key symbol.
521  MCSymbol *Sym = getContext().GetOrCreateSymbol(Name);
522
523  if (getLexer().isNot(AsmToken::Comma))
524    return TokError("unexpected token in '.lsym' directive");
525  Lex();
526
527  const MCExpr *Value;
528  if (getParser().parseExpression(Value))
529    return true;
530
531  if (getLexer().isNot(AsmToken::EndOfStatement))
532    return TokError("unexpected token in '.lsym' directive");
533
534  Lex();
535
536  // We don't currently support this directive.
537  //
538  // FIXME: Diagnostic location!
539  (void) Sym;
540  return TokError("directive '.lsym' is unsupported");
541}
542
543/// parseDirectiveSection:
544///   ::= .section identifier (',' identifier)*
545bool DarwinAsmParser::parseDirectiveSection(StringRef, SMLoc) {
546  SMLoc Loc = getLexer().getLoc();
547
548  StringRef SectionName;
549  if (getParser().parseIdentifier(SectionName))
550    return Error(Loc, "expected identifier after '.section' directive");
551
552  // Verify there is a following comma.
553  if (!getLexer().is(AsmToken::Comma))
554    return TokError("unexpected token in '.section' directive");
555
556  std::string SectionSpec = SectionName;
557  SectionSpec += ",";
558
559  // Add all the tokens until the end of the line, ParseSectionSpecifier will
560  // handle this.
561  StringRef EOL = getLexer().LexUntilEndOfStatement();
562  SectionSpec.append(EOL.begin(), EOL.end());
563
564  Lex();
565  if (getLexer().isNot(AsmToken::EndOfStatement))
566    return TokError("unexpected token in '.section' directive");
567  Lex();
568
569
570  StringRef Segment, Section;
571  unsigned StubSize;
572  unsigned TAA;
573  bool TAAParsed;
574  std::string ErrorStr =
575    MCSectionMachO::ParseSectionSpecifier(SectionSpec, Segment, Section,
576                                          TAA, TAAParsed, StubSize);
577
578  if (!ErrorStr.empty())
579    return Error(Loc, ErrorStr.c_str());
580
581  // FIXME: Arch specific.
582  bool isText = Segment == "__TEXT";  // FIXME: Hack.
583  getStreamer().SwitchSection(getContext().getMachOSection(
584                                Segment, Section, TAA, StubSize,
585                                isText ? SectionKind::getText()
586                                : SectionKind::getDataRel()));
587  return false;
588}
589
590/// ParseDirectivePushSection:
591///   ::= .pushsection identifier (',' identifier)*
592bool DarwinAsmParser::parseDirectivePushSection(StringRef S, SMLoc Loc) {
593  getStreamer().PushSection();
594
595  if (parseDirectiveSection(S, Loc)) {
596    getStreamer().PopSection();
597    return true;
598  }
599
600  return false;
601}
602
603/// ParseDirectivePopSection:
604///   ::= .popsection
605bool DarwinAsmParser::parseDirectivePopSection(StringRef, SMLoc) {
606  if (!getStreamer().PopSection())
607    return TokError(".popsection without corresponding .pushsection");
608  return false;
609}
610
611/// ParseDirectivePrevious:
612///   ::= .previous
613bool DarwinAsmParser::parseDirectivePrevious(StringRef DirName, SMLoc) {
614  MCSectionSubPair PreviousSection = getStreamer().getPreviousSection();
615  if (PreviousSection.first == NULL)
616      return TokError(".previous without corresponding .section");
617  getStreamer().SwitchSection(PreviousSection.first, PreviousSection.second);
618  return false;
619}
620
621/// ParseDirectiveSecureLogUnique
622///  ::= .secure_log_unique ... message ...
623bool DarwinAsmParser::parseDirectiveSecureLogUnique(StringRef, SMLoc IDLoc) {
624  StringRef LogMessage = getParser().parseStringToEndOfStatement();
625  if (getLexer().isNot(AsmToken::EndOfStatement))
626    return TokError("unexpected token in '.secure_log_unique' directive");
627
628  if (getContext().getSecureLogUsed() != false)
629    return Error(IDLoc, ".secure_log_unique specified multiple times");
630
631  // Get the secure log path.
632  const char *SecureLogFile = getContext().getSecureLogFile();
633  if (SecureLogFile == NULL)
634    return Error(IDLoc, ".secure_log_unique used but AS_SECURE_LOG_FILE "
635                 "environment variable unset.");
636
637  // Open the secure log file if we haven't already.
638  raw_ostream *OS = getContext().getSecureLog();
639  if (OS == NULL) {
640    std::string Err;
641    OS = new raw_fd_ostream(SecureLogFile, Err,
642                            sys::fs::F_Append | sys::fs::F_Text);
643    if (!Err.empty()) {
644       delete OS;
645       return Error(IDLoc, Twine("can't open secure log file: ") +
646                    SecureLogFile + " (" + Err + ")");
647    }
648    getContext().setSecureLog(OS);
649  }
650
651  // Write the message.
652  int CurBuf = getSourceManager().FindBufferContainingLoc(IDLoc);
653  *OS << getSourceManager().getBufferInfo(CurBuf).Buffer->getBufferIdentifier()
654      << ":" << getSourceManager().FindLineNumber(IDLoc, CurBuf) << ":"
655      << LogMessage + "\n";
656
657  getContext().setSecureLogUsed(true);
658
659  return false;
660}
661
662/// ParseDirectiveSecureLogReset
663///  ::= .secure_log_reset
664bool DarwinAsmParser::parseDirectiveSecureLogReset(StringRef, SMLoc IDLoc) {
665  if (getLexer().isNot(AsmToken::EndOfStatement))
666    return TokError("unexpected token in '.secure_log_reset' directive");
667
668  Lex();
669
670  getContext().setSecureLogUsed(false);
671
672  return false;
673}
674
675/// parseDirectiveSubsectionsViaSymbols
676///  ::= .subsections_via_symbols
677bool DarwinAsmParser::parseDirectiveSubsectionsViaSymbols(StringRef, SMLoc) {
678  if (getLexer().isNot(AsmToken::EndOfStatement))
679    return TokError("unexpected token in '.subsections_via_symbols' directive");
680
681  Lex();
682
683  getStreamer().EmitAssemblerFlag(MCAF_SubsectionsViaSymbols);
684
685  return false;
686}
687
688/// ParseDirectiveTBSS
689///  ::= .tbss identifier, size, align
690bool DarwinAsmParser::parseDirectiveTBSS(StringRef, SMLoc) {
691  SMLoc IDLoc = getLexer().getLoc();
692  StringRef Name;
693  if (getParser().parseIdentifier(Name))
694    return TokError("expected identifier in directive");
695
696  // Handle the identifier as the key symbol.
697  MCSymbol *Sym = getContext().GetOrCreateSymbol(Name);
698
699  if (getLexer().isNot(AsmToken::Comma))
700    return TokError("unexpected token in directive");
701  Lex();
702
703  int64_t Size;
704  SMLoc SizeLoc = getLexer().getLoc();
705  if (getParser().parseAbsoluteExpression(Size))
706    return true;
707
708  int64_t Pow2Alignment = 0;
709  SMLoc Pow2AlignmentLoc;
710  if (getLexer().is(AsmToken::Comma)) {
711    Lex();
712    Pow2AlignmentLoc = getLexer().getLoc();
713    if (getParser().parseAbsoluteExpression(Pow2Alignment))
714      return true;
715  }
716
717  if (getLexer().isNot(AsmToken::EndOfStatement))
718    return TokError("unexpected token in '.tbss' directive");
719
720  Lex();
721
722  if (Size < 0)
723    return Error(SizeLoc, "invalid '.tbss' directive size, can't be less than"
724                 "zero");
725
726  // FIXME: Diagnose overflow.
727  if (Pow2Alignment < 0)
728    return Error(Pow2AlignmentLoc, "invalid '.tbss' alignment, can't be less"
729                 "than zero");
730
731  if (!Sym->isUndefined())
732    return Error(IDLoc, "invalid symbol redefinition");
733
734  getStreamer().EmitTBSSSymbol(getContext().getMachOSection(
735                                 "__DATA", "__thread_bss",
736                                 MachO::S_THREAD_LOCAL_ZEROFILL,
737                                 0, SectionKind::getThreadBSS()),
738                               Sym, Size, 1 << Pow2Alignment);
739
740  return false;
741}
742
743/// ParseDirectiveZerofill
744///  ::= .zerofill segname , sectname [, identifier , size_expression [
745///      , align_expression ]]
746bool DarwinAsmParser::parseDirectiveZerofill(StringRef, SMLoc) {
747  StringRef Segment;
748  if (getParser().parseIdentifier(Segment))
749    return TokError("expected segment name after '.zerofill' directive");
750
751  if (getLexer().isNot(AsmToken::Comma))
752    return TokError("unexpected token in directive");
753  Lex();
754
755  StringRef Section;
756  if (getParser().parseIdentifier(Section))
757    return TokError("expected section name after comma in '.zerofill' "
758                    "directive");
759
760  // If this is the end of the line all that was wanted was to create the
761  // the section but with no symbol.
762  if (getLexer().is(AsmToken::EndOfStatement)) {
763    // Create the zerofill section but no symbol
764    getStreamer().EmitZerofill(getContext().getMachOSection(
765                                 Segment, Section, MachO::S_ZEROFILL,
766                                 0, SectionKind::getBSS()));
767    return false;
768  }
769
770  if (getLexer().isNot(AsmToken::Comma))
771    return TokError("unexpected token in directive");
772  Lex();
773
774  SMLoc IDLoc = getLexer().getLoc();
775  StringRef IDStr;
776  if (getParser().parseIdentifier(IDStr))
777    return TokError("expected identifier in directive");
778
779  // handle the identifier as the key symbol.
780  MCSymbol *Sym = getContext().GetOrCreateSymbol(IDStr);
781
782  if (getLexer().isNot(AsmToken::Comma))
783    return TokError("unexpected token in directive");
784  Lex();
785
786  int64_t Size;
787  SMLoc SizeLoc = getLexer().getLoc();
788  if (getParser().parseAbsoluteExpression(Size))
789    return true;
790
791  int64_t Pow2Alignment = 0;
792  SMLoc Pow2AlignmentLoc;
793  if (getLexer().is(AsmToken::Comma)) {
794    Lex();
795    Pow2AlignmentLoc = getLexer().getLoc();
796    if (getParser().parseAbsoluteExpression(Pow2Alignment))
797      return true;
798  }
799
800  if (getLexer().isNot(AsmToken::EndOfStatement))
801    return TokError("unexpected token in '.zerofill' directive");
802
803  Lex();
804
805  if (Size < 0)
806    return Error(SizeLoc, "invalid '.zerofill' directive size, can't be less "
807                 "than zero");
808
809  // NOTE: The alignment in the directive is a power of 2 value, the assembler
810  // may internally end up wanting an alignment in bytes.
811  // FIXME: Diagnose overflow.
812  if (Pow2Alignment < 0)
813    return Error(Pow2AlignmentLoc, "invalid '.zerofill' directive alignment, "
814                 "can't be less than zero");
815
816  if (!Sym->isUndefined())
817    return Error(IDLoc, "invalid symbol redefinition");
818
819  // Create the zerofill Symbol with Size and Pow2Alignment
820  //
821  // FIXME: Arch specific.
822  getStreamer().EmitZerofill(getContext().getMachOSection(
823                               Segment, Section, MachO::S_ZEROFILL,
824                               0, SectionKind::getBSS()),
825                             Sym, Size, 1 << Pow2Alignment);
826
827  return false;
828}
829
830/// ParseDirectiveDataRegion
831///  ::= .data_region [ ( jt8 | jt16 | jt32 ) ]
832bool DarwinAsmParser::parseDirectiveDataRegion(StringRef, SMLoc) {
833  if (getLexer().is(AsmToken::EndOfStatement)) {
834    Lex();
835    getStreamer().EmitDataRegion(MCDR_DataRegion);
836    return false;
837  }
838  StringRef RegionType;
839  SMLoc Loc = getParser().getTok().getLoc();
840  if (getParser().parseIdentifier(RegionType))
841    return TokError("expected region type after '.data_region' directive");
842  int Kind = StringSwitch<int>(RegionType)
843    .Case("jt8", MCDR_DataRegionJT8)
844    .Case("jt16", MCDR_DataRegionJT16)
845    .Case("jt32", MCDR_DataRegionJT32)
846    .Default(-1);
847  if (Kind == -1)
848    return Error(Loc, "unknown region type in '.data_region' directive");
849  Lex();
850
851  getStreamer().EmitDataRegion((MCDataRegionType)Kind);
852  return false;
853}
854
855/// ParseDirectiveDataRegionEnd
856///  ::= .end_data_region
857bool DarwinAsmParser::parseDirectiveDataRegionEnd(StringRef, SMLoc) {
858  if (getLexer().isNot(AsmToken::EndOfStatement))
859    return TokError("unexpected token in '.end_data_region' directive");
860
861  Lex();
862  getStreamer().EmitDataRegion(MCDR_DataRegionEnd);
863  return false;
864}
865
866/// parseVersionMin
867///  ::= .ios_version_min major,minor[,update]
868///  ::= .macosx_version_min major,minor[,update]
869bool DarwinAsmParser::parseVersionMin(StringRef Directive, SMLoc) {
870  int64_t Major = 0, Minor = 0, Update = 0;
871  int Kind = StringSwitch<int>(Directive)
872    .Case(".ios_version_min", MCVM_IOSVersionMin)
873    .Case(".macosx_version_min", MCVM_OSXVersionMin);
874  // Get the major version number.
875  if (getLexer().isNot(AsmToken::Integer))
876    return TokError("invalid OS major version number");
877  Major = getLexer().getTok().getIntVal();
878  if (Major > 65535 || Major <= 0)
879    return TokError("invalid OS major version number");
880  Lex();
881  if (getLexer().isNot(AsmToken::Comma))
882    return TokError("minor OS version number required, comma expected");
883  Lex();
884  // Get the minor version number.
885  if (getLexer().isNot(AsmToken::Integer))
886    return TokError("invalid OS minor version number");
887  Minor = getLexer().getTok().getIntVal();
888  if (Minor > 255 || Minor < 0)
889    return TokError("invalid OS minor version number");
890  Lex();
891  // Get the update level, if specified
892  if (getLexer().isNot(AsmToken::EndOfStatement)) {
893    if (getLexer().isNot(AsmToken::Comma))
894      return TokError("invalid update specifier, comma expected");
895    Lex();
896    if (getLexer().isNot(AsmToken::Integer))
897      return TokError("invalid OS update number");
898    Update = getLexer().getTok().getIntVal();
899  if (Update > 255 || Update < 0)
900    return TokError("invalid OS update number");
901    Lex();
902  }
903
904  // We've parsed a correct version specifier, so send it to the streamer.
905  getStreamer().EmitVersionMin((MCVersionMinType)Kind, Major, Minor, Update);
906
907  return false;
908}
909
910namespace llvm {
911
912MCAsmParserExtension *createDarwinAsmParser() {
913  return new DarwinAsmParser;
914}
915
916} // end llvm namespace
917