1 //===- DarwinAsmParser.cpp - Darwin (Mach-O) Assembly Parser --------------===//
3 // The LLVM Compiler Infrastructure
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
8 //===----------------------------------------------------------------------===//
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"
26 /// \brief Implementation of directive handling which is shared across all
28 class 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);
36 bool parseSectionSwitch(const char *Segment, const char *Section,
37 unsigned TAA = 0, unsigned ImplicitAlign = 0,
38 unsigned StubSize = 0);
43 void Initialize(MCAsmParser &Parser) override {
44 // Call the base implementation.
45 this->MCAsmParserExtension::Initialize(Parser);
47 addDirectiveHandler<&DarwinAsmParser::parseDirectiveDesc>(".desc");
48 addDirectiveHandler<&DarwinAsmParser::parseDirectiveIndirectSymbol>(
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>(
58 addDirectiveHandler<&DarwinAsmParser::parseDirectivePopSection>(
60 addDirectiveHandler<&DarwinAsmParser::parseDirectivePrevious>(".previous");
61 addDirectiveHandler<&DarwinAsmParser::parseDirectiveSecureLogUnique>(
62 ".secure_log_unique");
63 addDirectiveHandler<&DarwinAsmParser::parseDirectiveSecureLogReset>(
65 addDirectiveHandler<&DarwinAsmParser::parseDirectiveTBSS>(".tbss");
66 addDirectiveHandler<&DarwinAsmParser::parseDirectiveZerofill>(".zerofill");
68 addDirectiveHandler<&DarwinAsmParser::parseDirectiveDataRegion>(
70 addDirectiveHandler<&DarwinAsmParser::parseDirectiveDataRegionEnd>(
73 // Special section directives.
74 addDirectiveHandler<&DarwinAsmParser::parseSectionDirectiveBss>(".bss");
75 addDirectiveHandler<&DarwinAsmParser::parseSectionDirectiveConst>(".const");
76 addDirectiveHandler<&DarwinAsmParser::parseSectionDirectiveConstData>(
78 addDirectiveHandler<&DarwinAsmParser::parseSectionDirectiveConstructor>(
80 addDirectiveHandler<&DarwinAsmParser::parseSectionDirectiveCString>(
82 addDirectiveHandler<&DarwinAsmParser::parseSectionDirectiveData>(".data");
83 addDirectiveHandler<&DarwinAsmParser::parseSectionDirectiveDestructor>(
85 addDirectiveHandler<&DarwinAsmParser::parseSectionDirectiveDyld>(".dyld");
86 addDirectiveHandler<&DarwinAsmParser::parseSectionDirectiveFVMLibInit0>(
88 addDirectiveHandler<&DarwinAsmParser::parseSectionDirectiveFVMLibInit1>(
91 &DarwinAsmParser::parseSectionDirectiveLazySymbolPointers>(
92 ".lazy_symbol_pointer");
93 addDirectiveHandler<&DarwinAsmParser::parseDirectiveLinkerOption>(
95 addDirectiveHandler<&DarwinAsmParser::parseSectionDirectiveLiteral16>(
97 addDirectiveHandler<&DarwinAsmParser::parseSectionDirectiveLiteral4>(
99 addDirectiveHandler<&DarwinAsmParser::parseSectionDirectiveLiteral8>(
101 addDirectiveHandler<&DarwinAsmParser::parseSectionDirectiveModInitFunc>(
103 addDirectiveHandler<&DarwinAsmParser::parseSectionDirectiveModTermFunc>(
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>(
114 addDirectiveHandler<&DarwinAsmParser::parseSectionDirectiveObjCClass>(
116 addDirectiveHandler<&DarwinAsmParser::parseSectionDirectiveObjCClassNames>(
117 ".objc_class_names");
118 addDirectiveHandler<&DarwinAsmParser::parseSectionDirectiveObjCClassVars>(
120 addDirectiveHandler<&DarwinAsmParser::parseSectionDirectiveObjCClsMeth>(
122 addDirectiveHandler<&DarwinAsmParser::parseSectionDirectiveObjCClsRefs>(
124 addDirectiveHandler<&DarwinAsmParser::parseSectionDirectiveObjCInstMeth>(
127 &DarwinAsmParser::parseSectionDirectiveObjCInstanceVars>(
128 ".objc_instance_vars");
129 addDirectiveHandler<&DarwinAsmParser::parseSectionDirectiveObjCMessageRefs>(
130 ".objc_message_refs");
131 addDirectiveHandler<&DarwinAsmParser::parseSectionDirectiveObjCMetaClass>(
134 &DarwinAsmParser::parseSectionDirectiveObjCMethVarNames>(
135 ".objc_meth_var_names");
137 &DarwinAsmParser::parseSectionDirectiveObjCMethVarTypes>(
138 ".objc_meth_var_types");
139 addDirectiveHandler<&DarwinAsmParser::parseSectionDirectiveObjCModuleInfo>(
140 ".objc_module_info");
141 addDirectiveHandler<&DarwinAsmParser::parseSectionDirectiveObjCProtocol>(
144 &DarwinAsmParser::parseSectionDirectiveObjCSelectorStrs>(
145 ".objc_selector_strs");
147 &DarwinAsmParser::parseSectionDirectiveObjCStringObject>(
148 ".objc_string_object");
149 addDirectiveHandler<&DarwinAsmParser::parseSectionDirectiveObjCSymbols>(
151 addDirectiveHandler<&DarwinAsmParser::parseSectionDirectivePICSymbolStub>(
153 addDirectiveHandler<&DarwinAsmParser::parseSectionDirectiveStaticConst>(
155 addDirectiveHandler<&DarwinAsmParser::parseSectionDirectiveStaticData>(
157 addDirectiveHandler<&DarwinAsmParser::parseSectionDirectiveSymbolStub>(
159 addDirectiveHandler<&DarwinAsmParser::parseSectionDirectiveTData>(".tdata");
160 addDirectiveHandler<&DarwinAsmParser::parseSectionDirectiveText>(".text");
161 addDirectiveHandler<&DarwinAsmParser::parseSectionDirectiveThreadInitFunc>(
162 ".thread_init_func");
163 addDirectiveHandler<&DarwinAsmParser::parseSectionDirectiveTLV>(".tlv");
165 addDirectiveHandler<&DarwinAsmParser::parseSectionDirectiveIdent>(".ident");
166 addDirectiveHandler<&DarwinAsmParser::parseVersionMin>(".ios_version_min");
167 addDirectiveHandler<&DarwinAsmParser::parseVersionMin>(
168 ".macosx_version_min");
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);
188 // Named Section Directive
189 bool parseSectionDirectiveBss(StringRef, SMLoc) {
190 return parseSectionSwitch("__DATA", "__bss");
193 bool parseSectionDirectiveConst(StringRef, SMLoc) {
194 return parseSectionSwitch("__TEXT", "__const");
196 bool parseSectionDirectiveStaticConst(StringRef, SMLoc) {
197 return parseSectionSwitch("__TEXT", "__static_const");
199 bool parseSectionDirectiveCString(StringRef, SMLoc) {
200 return parseSectionSwitch("__TEXT","__cstring",
201 MachO::S_CSTRING_LITERALS);
203 bool parseSectionDirectiveLiteral4(StringRef, SMLoc) {
204 return parseSectionSwitch("__TEXT", "__literal4",
205 MachO::S_4BYTE_LITERALS, 4);
207 bool parseSectionDirectiveLiteral8(StringRef, SMLoc) {
208 return parseSectionSwitch("__TEXT", "__literal8",
209 MachO::S_8BYTE_LITERALS, 8);
211 bool parseSectionDirectiveLiteral16(StringRef, SMLoc) {
212 return parseSectionSwitch("__TEXT","__literal16",
213 MachO::S_16BYTE_LITERALS, 16);
215 bool parseSectionDirectiveConstructor(StringRef, SMLoc) {
216 return parseSectionSwitch("__TEXT","__constructor");
218 bool parseSectionDirectiveDestructor(StringRef, SMLoc) {
219 return parseSectionSwitch("__TEXT","__destructor");
221 bool parseSectionDirectiveFVMLibInit0(StringRef, SMLoc) {
222 return parseSectionSwitch("__TEXT","__fvmlib_init0");
224 bool parseSectionDirectiveFVMLibInit1(StringRef, SMLoc) {
225 return parseSectionSwitch("__TEXT","__fvmlib_init1");
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.
234 bool parseSectionDirectivePICSymbolStub(StringRef, SMLoc) {
235 return parseSectionSwitch("__TEXT","__picsymbol_stub",
236 MachO::S_SYMBOL_STUBS |
237 MachO::S_ATTR_PURE_INSTRUCTIONS, 0, 26);
239 bool parseSectionDirectiveData(StringRef, SMLoc) {
240 return parseSectionSwitch("__DATA", "__data");
242 bool parseSectionDirectiveStaticData(StringRef, SMLoc) {
243 return parseSectionSwitch("__DATA", "__static_data");
245 bool parseSectionDirectiveNonLazySymbolPointers(StringRef, SMLoc) {
246 return parseSectionSwitch("__DATA", "__nl_symbol_ptr",
247 MachO::S_NON_LAZY_SYMBOL_POINTERS, 4);
249 bool parseSectionDirectiveLazySymbolPointers(StringRef, SMLoc) {
250 return parseSectionSwitch("__DATA", "__la_symbol_ptr",
251 MachO::S_LAZY_SYMBOL_POINTERS, 4);
253 bool parseSectionDirectiveDyld(StringRef, SMLoc) {
254 return parseSectionSwitch("__DATA", "__dyld");
256 bool parseSectionDirectiveModInitFunc(StringRef, SMLoc) {
257 return parseSectionSwitch("__DATA", "__mod_init_func",
258 MachO::S_MOD_INIT_FUNC_POINTERS, 4);
260 bool parseSectionDirectiveModTermFunc(StringRef, SMLoc) {
261 return parseSectionSwitch("__DATA", "__mod_term_func",
262 MachO::S_MOD_TERM_FUNC_POINTERS, 4);
264 bool parseSectionDirectiveConstData(StringRef, SMLoc) {
265 return parseSectionSwitch("__DATA", "__const");
267 bool parseSectionDirectiveObjCClass(StringRef, SMLoc) {
268 return parseSectionSwitch("__OBJC", "__class",
269 MachO::S_ATTR_NO_DEAD_STRIP);
271 bool parseSectionDirectiveObjCMetaClass(StringRef, SMLoc) {
272 return parseSectionSwitch("__OBJC", "__meta_class",
273 MachO::S_ATTR_NO_DEAD_STRIP);
275 bool parseSectionDirectiveObjCCatClsMeth(StringRef, SMLoc) {
276 return parseSectionSwitch("__OBJC", "__cat_cls_meth",
277 MachO::S_ATTR_NO_DEAD_STRIP);
279 bool parseSectionDirectiveObjCCatInstMeth(StringRef, SMLoc) {
280 return parseSectionSwitch("__OBJC", "__cat_inst_meth",
281 MachO::S_ATTR_NO_DEAD_STRIP);
283 bool parseSectionDirectiveObjCProtocol(StringRef, SMLoc) {
284 return parseSectionSwitch("__OBJC", "__protocol",
285 MachO::S_ATTR_NO_DEAD_STRIP);
287 bool parseSectionDirectiveObjCStringObject(StringRef, SMLoc) {
288 return parseSectionSwitch("__OBJC", "__string_object",
289 MachO::S_ATTR_NO_DEAD_STRIP);
291 bool parseSectionDirectiveObjCClsMeth(StringRef, SMLoc) {
292 return parseSectionSwitch("__OBJC", "__cls_meth",
293 MachO::S_ATTR_NO_DEAD_STRIP);
295 bool parseSectionDirectiveObjCInstMeth(StringRef, SMLoc) {
296 return parseSectionSwitch("__OBJC", "__inst_meth",
297 MachO::S_ATTR_NO_DEAD_STRIP);
299 bool parseSectionDirectiveObjCClsRefs(StringRef, SMLoc) {
300 return parseSectionSwitch("__OBJC", "__cls_refs",
301 MachO::S_ATTR_NO_DEAD_STRIP |
302 MachO::S_LITERAL_POINTERS, 4);
304 bool parseSectionDirectiveObjCMessageRefs(StringRef, SMLoc) {
305 return parseSectionSwitch("__OBJC", "__message_refs",
306 MachO::S_ATTR_NO_DEAD_STRIP |
307 MachO::S_LITERAL_POINTERS, 4);
309 bool parseSectionDirectiveObjCSymbols(StringRef, SMLoc) {
310 return parseSectionSwitch("__OBJC", "__symbols",
311 MachO::S_ATTR_NO_DEAD_STRIP);
313 bool parseSectionDirectiveObjCCategory(StringRef, SMLoc) {
314 return parseSectionSwitch("__OBJC", "__category",
315 MachO::S_ATTR_NO_DEAD_STRIP);
317 bool parseSectionDirectiveObjCClassVars(StringRef, SMLoc) {
318 return parseSectionSwitch("__OBJC", "__class_vars",
319 MachO::S_ATTR_NO_DEAD_STRIP);
321 bool parseSectionDirectiveObjCInstanceVars(StringRef, SMLoc) {
322 return parseSectionSwitch("__OBJC", "__instance_vars",
323 MachO::S_ATTR_NO_DEAD_STRIP);
325 bool parseSectionDirectiveObjCModuleInfo(StringRef, SMLoc) {
326 return parseSectionSwitch("__OBJC", "__module_info",
327 MachO::S_ATTR_NO_DEAD_STRIP);
329 bool parseSectionDirectiveObjCClassNames(StringRef, SMLoc) {
330 return parseSectionSwitch("__TEXT", "__cstring",
331 MachO::S_CSTRING_LITERALS);
333 bool parseSectionDirectiveObjCMethVarTypes(StringRef, SMLoc) {
334 return parseSectionSwitch("__TEXT", "__cstring",
335 MachO::S_CSTRING_LITERALS);
337 bool parseSectionDirectiveObjCMethVarNames(StringRef, SMLoc) {
338 return parseSectionSwitch("__TEXT", "__cstring",
339 MachO::S_CSTRING_LITERALS);
341 bool parseSectionDirectiveObjCSelectorStrs(StringRef, SMLoc) {
342 return parseSectionSwitch("__OBJC", "__selector_strs",
343 MachO::S_CSTRING_LITERALS);
345 bool parseSectionDirectiveTData(StringRef, SMLoc) {
346 return parseSectionSwitch("__DATA", "__thread_data",
347 MachO::S_THREAD_LOCAL_REGULAR);
349 bool parseSectionDirectiveText(StringRef, SMLoc) {
350 return parseSectionSwitch("__TEXT", "__text",
351 MachO::S_ATTR_PURE_INSTRUCTIONS);
353 bool parseSectionDirectiveTLV(StringRef, SMLoc) {
354 return parseSectionSwitch("__DATA", "__thread_vars",
355 MachO::S_THREAD_LOCAL_VARIABLES);
357 bool parseSectionDirectiveIdent(StringRef, SMLoc) {
358 // Darwin silently ignores the .ident directive.
359 getParser().eatToEndOfStatement();
362 bool parseSectionDirectiveThreadInitFunc(StringRef, SMLoc) {
363 return parseSectionSwitch("__DATA", "__thread_init",
364 MachO::S_THREAD_LOCAL_INIT_FUNCTION_POINTERS);
366 bool parseVersionMin(StringRef, SMLoc);
370 } // end anonymous namespace
372 bool DarwinAsmParser::parseSectionSwitch(const char *Segment,
374 unsigned TAA, unsigned Align,
376 if (getLexer().isNot(AsmToken::EndOfStatement))
377 return TokError("unexpected token in section switching directive");
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()));
387 // Set the implicit alignment, if any.
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.
396 getStreamer().EmitValueToAlignment(Align);
401 /// parseDirectiveDesc
402 /// ::= .desc identifier , expression
403 bool DarwinAsmParser::parseDirectiveDesc(StringRef, SMLoc) {
405 if (getParser().parseIdentifier(Name))
406 return TokError("expected identifier in directive");
408 // Handle the identifier as the key symbol.
409 MCSymbol *Sym = getContext().GetOrCreateSymbol(Name);
411 if (getLexer().isNot(AsmToken::Comma))
412 return TokError("unexpected token in '.desc' directive");
416 if (getParser().parseAbsoluteExpression(DescValue))
419 if (getLexer().isNot(AsmToken::EndOfStatement))
420 return TokError("unexpected token in '.desc' directive");
424 // Set the n_desc field of this Symbol to this DescValue
425 getStreamer().EmitSymbolDesc(Sym, DescValue);
430 /// parseDirectiveIndirectSymbol
431 /// ::= .indirect_symbol identifier
432 bool 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 "
443 if (getParser().parseIdentifier(Name))
444 return TokError("expected identifier in .indirect_symbol directive");
446 MCSymbol *Sym = getContext().GetOrCreateSymbol(Name);
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");
452 if (!getStreamer().EmitSymbolAttribute(Sym, MCSA_IndirectSymbol))
453 return TokError("unable to emit indirect symbol attribute for: " + Name);
455 if (getLexer().isNot(AsmToken::EndOfStatement))
456 return TokError("unexpected token in '.indirect_symbol' directive");
463 /// parseDirectiveDumpOrLoad
464 /// ::= ( .dump | .load ) "filename"
465 bool DarwinAsmParser::parseDirectiveDumpOrLoad(StringRef Directive,
467 bool IsDump = Directive == ".dump";
468 if (getLexer().isNot(AsmToken::String))
469 return TokError("expected string in '.dump' or '.load' directive");
473 if (getLexer().isNot(AsmToken::EndOfStatement))
474 return TokError("unexpected token in '.dump' or '.load' directive");
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.
481 return Warning(IDLoc, "ignoring directive .dump for now");
483 return Warning(IDLoc, "ignoring directive .load for now");
486 /// ParseDirectiveLinkerOption
487 /// ::= .linker_option "string" ( , "string" )*
488 bool DarwinAsmParser::parseDirectiveLinkerOption(StringRef IDVal, SMLoc) {
489 SmallVector<std::string, 4> Args;
491 if (getLexer().isNot(AsmToken::String))
492 return TokError("expected string in '" + Twine(IDVal) + "' directive");
495 if (getParser().parseEscapedString(Data))
498 Args.push_back(Data);
501 if (getLexer().is(AsmToken::EndOfStatement))
504 if (getLexer().isNot(AsmToken::Comma))
505 return TokError("unexpected token in '" + Twine(IDVal) + "' directive");
509 getStreamer().EmitLinkerOptions(Args);
513 /// parseDirectiveLsym
514 /// ::= .lsym identifier , expression
515 bool DarwinAsmParser::parseDirectiveLsym(StringRef, SMLoc) {
517 if (getParser().parseIdentifier(Name))
518 return TokError("expected identifier in directive");
520 // Handle the identifier as the key symbol.
521 MCSymbol *Sym = getContext().GetOrCreateSymbol(Name);
523 if (getLexer().isNot(AsmToken::Comma))
524 return TokError("unexpected token in '.lsym' directive");
528 if (getParser().parseExpression(Value))
531 if (getLexer().isNot(AsmToken::EndOfStatement))
532 return TokError("unexpected token in '.lsym' directive");
536 // We don't currently support this directive.
538 // FIXME: Diagnostic location!
540 return TokError("directive '.lsym' is unsupported");
543 /// parseDirectiveSection:
544 /// ::= .section identifier (',' identifier)*
545 bool DarwinAsmParser::parseDirectiveSection(StringRef, SMLoc) {
546 SMLoc Loc = getLexer().getLoc();
548 StringRef SectionName;
549 if (getParser().parseIdentifier(SectionName))
550 return Error(Loc, "expected identifier after '.section' directive");
552 // Verify there is a following comma.
553 if (!getLexer().is(AsmToken::Comma))
554 return TokError("unexpected token in '.section' directive");
556 std::string SectionSpec = SectionName;
559 // Add all the tokens until the end of the line, ParseSectionSpecifier will
561 StringRef EOL = getLexer().LexUntilEndOfStatement();
562 SectionSpec.append(EOL.begin(), EOL.end());
565 if (getLexer().isNot(AsmToken::EndOfStatement))
566 return TokError("unexpected token in '.section' directive");
570 StringRef Segment, Section;
574 std::string ErrorStr =
575 MCSectionMachO::ParseSectionSpecifier(SectionSpec, Segment, Section,
576 TAA, TAAParsed, StubSize);
578 if (!ErrorStr.empty())
579 return Error(Loc, ErrorStr.c_str());
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()));
590 /// ParseDirectivePushSection:
591 /// ::= .pushsection identifier (',' identifier)*
592 bool DarwinAsmParser::parseDirectivePushSection(StringRef S, SMLoc Loc) {
593 getStreamer().PushSection();
595 if (parseDirectiveSection(S, Loc)) {
596 getStreamer().PopSection();
603 /// ParseDirectivePopSection:
605 bool DarwinAsmParser::parseDirectivePopSection(StringRef, SMLoc) {
606 if (!getStreamer().PopSection())
607 return TokError(".popsection without corresponding .pushsection");
611 /// ParseDirectivePrevious:
613 bool DarwinAsmParser::parseDirectivePrevious(StringRef DirName, SMLoc) {
614 MCSectionSubPair PreviousSection = getStreamer().getPreviousSection();
615 if (!PreviousSection.first)
616 return TokError(".previous without corresponding .section");
617 getStreamer().SwitchSection(PreviousSection.first, PreviousSection.second);
621 /// ParseDirectiveSecureLogUnique
622 /// ::= .secure_log_unique ... message ...
623 bool 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");
628 if (getContext().getSecureLogUsed() != false)
629 return Error(IDLoc, ".secure_log_unique specified multiple times");
631 // Get the secure log path.
632 const char *SecureLogFile = getContext().getSecureLogFile();
634 return Error(IDLoc, ".secure_log_unique used but AS_SECURE_LOG_FILE "
635 "environment variable unset.");
637 // Open the secure log file if we haven't already.
638 raw_ostream *OS = getContext().getSecureLog();
641 OS = new raw_fd_ostream(SecureLogFile, Err,
642 sys::fs::F_Append | sys::fs::F_Text);
645 return Error(IDLoc, Twine("can't open secure log file: ") +
646 SecureLogFile + " (" + Err + ")");
648 getContext().setSecureLog(OS);
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";
657 getContext().setSecureLogUsed(true);
662 /// ParseDirectiveSecureLogReset
663 /// ::= .secure_log_reset
664 bool DarwinAsmParser::parseDirectiveSecureLogReset(StringRef, SMLoc IDLoc) {
665 if (getLexer().isNot(AsmToken::EndOfStatement))
666 return TokError("unexpected token in '.secure_log_reset' directive");
670 getContext().setSecureLogUsed(false);
675 /// parseDirectiveSubsectionsViaSymbols
676 /// ::= .subsections_via_symbols
677 bool DarwinAsmParser::parseDirectiveSubsectionsViaSymbols(StringRef, SMLoc) {
678 if (getLexer().isNot(AsmToken::EndOfStatement))
679 return TokError("unexpected token in '.subsections_via_symbols' directive");
683 getStreamer().EmitAssemblerFlag(MCAF_SubsectionsViaSymbols);
688 /// ParseDirectiveTBSS
689 /// ::= .tbss identifier, size, align
690 bool DarwinAsmParser::parseDirectiveTBSS(StringRef, SMLoc) {
691 SMLoc IDLoc = getLexer().getLoc();
693 if (getParser().parseIdentifier(Name))
694 return TokError("expected identifier in directive");
696 // Handle the identifier as the key symbol.
697 MCSymbol *Sym = getContext().GetOrCreateSymbol(Name);
699 if (getLexer().isNot(AsmToken::Comma))
700 return TokError("unexpected token in directive");
704 SMLoc SizeLoc = getLexer().getLoc();
705 if (getParser().parseAbsoluteExpression(Size))
708 int64_t Pow2Alignment = 0;
709 SMLoc Pow2AlignmentLoc;
710 if (getLexer().is(AsmToken::Comma)) {
712 Pow2AlignmentLoc = getLexer().getLoc();
713 if (getParser().parseAbsoluteExpression(Pow2Alignment))
717 if (getLexer().isNot(AsmToken::EndOfStatement))
718 return TokError("unexpected token in '.tbss' directive");
723 return Error(SizeLoc, "invalid '.tbss' directive size, can't be less than"
726 // FIXME: Diagnose overflow.
727 if (Pow2Alignment < 0)
728 return Error(Pow2AlignmentLoc, "invalid '.tbss' alignment, can't be less"
731 if (!Sym->isUndefined())
732 return Error(IDLoc, "invalid symbol redefinition");
734 getStreamer().EmitTBSSSymbol(getContext().getMachOSection(
735 "__DATA", "__thread_bss",
736 MachO::S_THREAD_LOCAL_ZEROFILL,
737 0, SectionKind::getThreadBSS()),
738 Sym, Size, 1 << Pow2Alignment);
743 /// ParseDirectiveZerofill
744 /// ::= .zerofill segname , sectname [, identifier , size_expression [
745 /// , align_expression ]]
746 bool DarwinAsmParser::parseDirectiveZerofill(StringRef, SMLoc) {
748 if (getParser().parseIdentifier(Segment))
749 return TokError("expected segment name after '.zerofill' directive");
751 if (getLexer().isNot(AsmToken::Comma))
752 return TokError("unexpected token in directive");
756 if (getParser().parseIdentifier(Section))
757 return TokError("expected section name after comma in '.zerofill' "
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()));
770 if (getLexer().isNot(AsmToken::Comma))
771 return TokError("unexpected token in directive");
774 SMLoc IDLoc = getLexer().getLoc();
776 if (getParser().parseIdentifier(IDStr))
777 return TokError("expected identifier in directive");
779 // handle the identifier as the key symbol.
780 MCSymbol *Sym = getContext().GetOrCreateSymbol(IDStr);
782 if (getLexer().isNot(AsmToken::Comma))
783 return TokError("unexpected token in directive");
787 SMLoc SizeLoc = getLexer().getLoc();
788 if (getParser().parseAbsoluteExpression(Size))
791 int64_t Pow2Alignment = 0;
792 SMLoc Pow2AlignmentLoc;
793 if (getLexer().is(AsmToken::Comma)) {
795 Pow2AlignmentLoc = getLexer().getLoc();
796 if (getParser().parseAbsoluteExpression(Pow2Alignment))
800 if (getLexer().isNot(AsmToken::EndOfStatement))
801 return TokError("unexpected token in '.zerofill' directive");
806 return Error(SizeLoc, "invalid '.zerofill' directive size, can't be less "
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");
816 if (!Sym->isUndefined())
817 return Error(IDLoc, "invalid symbol redefinition");
819 // Create the zerofill Symbol with Size and Pow2Alignment
821 // FIXME: Arch specific.
822 getStreamer().EmitZerofill(getContext().getMachOSection(
823 Segment, Section, MachO::S_ZEROFILL,
824 0, SectionKind::getBSS()),
825 Sym, Size, 1 << Pow2Alignment);
830 /// ParseDirectiveDataRegion
831 /// ::= .data_region [ ( jt8 | jt16 | jt32 ) ]
832 bool DarwinAsmParser::parseDirectiveDataRegion(StringRef, SMLoc) {
833 if (getLexer().is(AsmToken::EndOfStatement)) {
835 getStreamer().EmitDataRegion(MCDR_DataRegion);
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)
848 return Error(Loc, "unknown region type in '.data_region' directive");
851 getStreamer().EmitDataRegion((MCDataRegionType)Kind);
855 /// ParseDirectiveDataRegionEnd
856 /// ::= .end_data_region
857 bool DarwinAsmParser::parseDirectiveDataRegionEnd(StringRef, SMLoc) {
858 if (getLexer().isNot(AsmToken::EndOfStatement))
859 return TokError("unexpected token in '.end_data_region' directive");
862 getStreamer().EmitDataRegion(MCDR_DataRegionEnd);
867 /// ::= .ios_version_min major,minor[,update]
868 /// ::= .macosx_version_min major,minor[,update]
869 bool 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");
881 if (getLexer().isNot(AsmToken::Comma))
882 return TokError("minor OS version number required, comma expected");
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");
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");
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");
904 // We've parsed a correct version specifier, so send it to the streamer.
905 getStreamer().EmitVersionMin((MCVersionMinType)Kind, Major, Minor, Update);
912 MCAsmParserExtension *createDarwinAsmParser() {
913 return new DarwinAsmParser;
916 } // end llvm namespace