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 == NULL)
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();
633 if (SecureLogFile == NULL)
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