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