Path: blob/main/contrib/llvm-project/llvm/lib/MC/MCParser/DarwinAsmParser.cpp
35269 views
//===- DarwinAsmParser.cpp - Darwin (Mach-O) Assembly Parser --------------===//1//2// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.3// See https://llvm.org/LICENSE.txt for license information.4// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception5//6//===----------------------------------------------------------------------===//78#include "llvm/ADT/SmallVector.h"9#include "llvm/ADT/StringRef.h"10#include "llvm/ADT/StringSwitch.h"11#include "llvm/ADT/Twine.h"12#include "llvm/BinaryFormat/MachO.h"13#include "llvm/MC/MCContext.h"14#include "llvm/MC/MCDirectives.h"15#include "llvm/MC/MCParser/MCAsmLexer.h"16#include "llvm/MC/MCParser/MCAsmParser.h"17#include "llvm/MC/MCParser/MCAsmParserExtension.h"18#include "llvm/MC/MCSectionMachO.h"19#include "llvm/MC/MCStreamer.h"20#include "llvm/MC/MCSymbol.h"21#include "llvm/MC/SectionKind.h"22#include "llvm/Support/Error.h"23#include "llvm/Support/FileSystem.h"24#include "llvm/Support/MemoryBuffer.h"25#include "llvm/Support/SMLoc.h"26#include "llvm/Support/SourceMgr.h"27#include "llvm/Support/raw_ostream.h"28#include "llvm/TargetParser/Triple.h"29#include <cstddef>30#include <cstdint>31#include <string>32#include <system_error>33#include <utility>3435using namespace llvm;3637namespace {3839/// Implementation of directive handling which is shared across all40/// Darwin targets.41class DarwinAsmParser : public MCAsmParserExtension {42template<bool (DarwinAsmParser::*HandlerMethod)(StringRef, SMLoc)>43void addDirectiveHandler(StringRef Directive) {44MCAsmParser::ExtensionDirectiveHandler Handler = std::make_pair(45this, HandleDirective<DarwinAsmParser, HandlerMethod>);46getParser().addDirectiveHandler(Directive, Handler);47}4849bool parseSectionSwitch(StringRef Segment, StringRef Section,50unsigned TAA = 0, unsigned ImplicitAlign = 0,51unsigned StubSize = 0);5253SMLoc LastVersionDirective;5455public:56DarwinAsmParser() = default;5758void Initialize(MCAsmParser &Parser) override {59// Call the base implementation.60this->MCAsmParserExtension::Initialize(Parser);6162addDirectiveHandler<&DarwinAsmParser::parseDirectiveAltEntry>(".alt_entry");63addDirectiveHandler<&DarwinAsmParser::parseDirectiveDesc>(".desc");64addDirectiveHandler<&DarwinAsmParser::parseDirectiveIndirectSymbol>(65".indirect_symbol");66addDirectiveHandler<&DarwinAsmParser::parseDirectiveLsym>(".lsym");67addDirectiveHandler<&DarwinAsmParser::parseDirectiveSubsectionsViaSymbols>(68".subsections_via_symbols");69addDirectiveHandler<&DarwinAsmParser::parseDirectiveDumpOrLoad>(".dump");70addDirectiveHandler<&DarwinAsmParser::parseDirectiveDumpOrLoad>(".load");71addDirectiveHandler<&DarwinAsmParser::parseDirectiveSection>(".section");72addDirectiveHandler<&DarwinAsmParser::parseDirectivePushSection>(73".pushsection");74addDirectiveHandler<&DarwinAsmParser::parseDirectivePopSection>(75".popsection");76addDirectiveHandler<&DarwinAsmParser::parseDirectivePrevious>(".previous");77addDirectiveHandler<&DarwinAsmParser::parseDirectiveSecureLogUnique>(78".secure_log_unique");79addDirectiveHandler<&DarwinAsmParser::parseDirectiveSecureLogReset>(80".secure_log_reset");81addDirectiveHandler<&DarwinAsmParser::parseDirectiveTBSS>(".tbss");82addDirectiveHandler<&DarwinAsmParser::parseDirectiveZerofill>(".zerofill");8384addDirectiveHandler<&DarwinAsmParser::parseDirectiveDataRegion>(85".data_region");86addDirectiveHandler<&DarwinAsmParser::parseDirectiveDataRegionEnd>(87".end_data_region");8889// Special section directives.90addDirectiveHandler<&DarwinAsmParser::parseSectionDirectiveBss>(".bss");91addDirectiveHandler<&DarwinAsmParser::parseSectionDirectiveConst>(".const");92addDirectiveHandler<&DarwinAsmParser::parseSectionDirectiveConstData>(93".const_data");94addDirectiveHandler<&DarwinAsmParser::parseSectionDirectiveConstructor>(95".constructor");96addDirectiveHandler<&DarwinAsmParser::parseSectionDirectiveCString>(97".cstring");98addDirectiveHandler<&DarwinAsmParser::parseSectionDirectiveData>(".data");99addDirectiveHandler<&DarwinAsmParser::parseSectionDirectiveDestructor>(100".destructor");101addDirectiveHandler<&DarwinAsmParser::parseSectionDirectiveDyld>(".dyld");102addDirectiveHandler<&DarwinAsmParser::parseSectionDirectiveFVMLibInit0>(103".fvmlib_init0");104addDirectiveHandler<&DarwinAsmParser::parseSectionDirectiveFVMLibInit1>(105".fvmlib_init1");106addDirectiveHandler<107&DarwinAsmParser::parseSectionDirectiveLazySymbolPointers>(108".lazy_symbol_pointer");109addDirectiveHandler<&DarwinAsmParser::parseDirectiveLinkerOption>(110".linker_option");111addDirectiveHandler<&DarwinAsmParser::parseSectionDirectiveLiteral16>(112".literal16");113addDirectiveHandler<&DarwinAsmParser::parseSectionDirectiveLiteral4>(114".literal4");115addDirectiveHandler<&DarwinAsmParser::parseSectionDirectiveLiteral8>(116".literal8");117addDirectiveHandler<&DarwinAsmParser::parseSectionDirectiveModInitFunc>(118".mod_init_func");119addDirectiveHandler<&DarwinAsmParser::parseSectionDirectiveModTermFunc>(120".mod_term_func");121addDirectiveHandler<122&DarwinAsmParser::parseSectionDirectiveNonLazySymbolPointers>(123".non_lazy_symbol_pointer");124addDirectiveHandler<125&DarwinAsmParser::parseSectionDirectiveThreadLocalVariablePointers>(126".thread_local_variable_pointer");127addDirectiveHandler<&DarwinAsmParser::parseSectionDirectiveObjCCatClsMeth>(128".objc_cat_cls_meth");129addDirectiveHandler<&DarwinAsmParser::parseSectionDirectiveObjCCatInstMeth>(130".objc_cat_inst_meth");131addDirectiveHandler<&DarwinAsmParser::parseSectionDirectiveObjCCategory>(132".objc_category");133addDirectiveHandler<&DarwinAsmParser::parseSectionDirectiveObjCClass>(134".objc_class");135addDirectiveHandler<&DarwinAsmParser::parseSectionDirectiveObjCClassNames>(136".objc_class_names");137addDirectiveHandler<&DarwinAsmParser::parseSectionDirectiveObjCClassVars>(138".objc_class_vars");139addDirectiveHandler<&DarwinAsmParser::parseSectionDirectiveObjCClsMeth>(140".objc_cls_meth");141addDirectiveHandler<&DarwinAsmParser::parseSectionDirectiveObjCClsRefs>(142".objc_cls_refs");143addDirectiveHandler<&DarwinAsmParser::parseSectionDirectiveObjCInstMeth>(144".objc_inst_meth");145addDirectiveHandler<146&DarwinAsmParser::parseSectionDirectiveObjCInstanceVars>(147".objc_instance_vars");148addDirectiveHandler<&DarwinAsmParser::parseSectionDirectiveObjCMessageRefs>(149".objc_message_refs");150addDirectiveHandler<&DarwinAsmParser::parseSectionDirectiveObjCMetaClass>(151".objc_meta_class");152addDirectiveHandler<153&DarwinAsmParser::parseSectionDirectiveObjCMethVarNames>(154".objc_meth_var_names");155addDirectiveHandler<156&DarwinAsmParser::parseSectionDirectiveObjCMethVarTypes>(157".objc_meth_var_types");158addDirectiveHandler<&DarwinAsmParser::parseSectionDirectiveObjCModuleInfo>(159".objc_module_info");160addDirectiveHandler<&DarwinAsmParser::parseSectionDirectiveObjCProtocol>(161".objc_protocol");162addDirectiveHandler<163&DarwinAsmParser::parseSectionDirectiveObjCSelectorStrs>(164".objc_selector_strs");165addDirectiveHandler<166&DarwinAsmParser::parseSectionDirectiveObjCStringObject>(167".objc_string_object");168addDirectiveHandler<&DarwinAsmParser::parseSectionDirectiveObjCSymbols>(169".objc_symbols");170addDirectiveHandler<&DarwinAsmParser::parseSectionDirectivePICSymbolStub>(171".picsymbol_stub");172addDirectiveHandler<&DarwinAsmParser::parseSectionDirectiveStaticConst>(173".static_const");174addDirectiveHandler<&DarwinAsmParser::parseSectionDirectiveStaticData>(175".static_data");176addDirectiveHandler<&DarwinAsmParser::parseSectionDirectiveSymbolStub>(177".symbol_stub");178addDirectiveHandler<&DarwinAsmParser::parseSectionDirectiveTData>(".tdata");179addDirectiveHandler<&DarwinAsmParser::parseSectionDirectiveText>(".text");180addDirectiveHandler<&DarwinAsmParser::parseSectionDirectiveThreadInitFunc>(181".thread_init_func");182addDirectiveHandler<&DarwinAsmParser::parseSectionDirectiveTLV>(".tlv");183184addDirectiveHandler<&DarwinAsmParser::parseSectionDirectiveIdent>(".ident");185addDirectiveHandler<&DarwinAsmParser::parseWatchOSVersionMin>(186".watchos_version_min");187addDirectiveHandler<&DarwinAsmParser::parseTvOSVersionMin>(188".tvos_version_min");189addDirectiveHandler<&DarwinAsmParser::parseIOSVersionMin>(190".ios_version_min");191addDirectiveHandler<&DarwinAsmParser::parseMacOSXVersionMin>(192".macosx_version_min");193addDirectiveHandler<&DarwinAsmParser::parseBuildVersion>(".build_version");194addDirectiveHandler<&DarwinAsmParser::parseDirectiveCGProfile>(195".cg_profile");196197LastVersionDirective = SMLoc();198}199200bool parseDirectiveAltEntry(StringRef, SMLoc);201bool parseDirectiveDesc(StringRef, SMLoc);202bool parseDirectiveIndirectSymbol(StringRef, SMLoc);203bool parseDirectiveDumpOrLoad(StringRef, SMLoc);204bool parseDirectiveLsym(StringRef, SMLoc);205bool parseDirectiveLinkerOption(StringRef, SMLoc);206bool parseDirectiveSection(StringRef, SMLoc);207bool parseDirectivePushSection(StringRef, SMLoc);208bool parseDirectivePopSection(StringRef, SMLoc);209bool parseDirectivePrevious(StringRef, SMLoc);210bool parseDirectiveSecureLogReset(StringRef, SMLoc);211bool parseDirectiveSecureLogUnique(StringRef, SMLoc);212bool parseDirectiveSubsectionsViaSymbols(StringRef, SMLoc);213bool parseDirectiveTBSS(StringRef, SMLoc);214bool parseDirectiveZerofill(StringRef, SMLoc);215bool parseDirectiveDataRegion(StringRef, SMLoc);216bool parseDirectiveDataRegionEnd(StringRef, SMLoc);217218// Named Section Directive219bool parseSectionDirectiveBss(StringRef, SMLoc) {220return parseSectionSwitch("__DATA", "__bss");221}222223bool parseSectionDirectiveConst(StringRef, SMLoc) {224return parseSectionSwitch("__TEXT", "__const");225}226227bool parseSectionDirectiveStaticConst(StringRef, SMLoc) {228return parseSectionSwitch("__TEXT", "__static_const");229}230231bool parseSectionDirectiveCString(StringRef, SMLoc) {232return parseSectionSwitch("__TEXT","__cstring",233MachO::S_CSTRING_LITERALS);234}235236bool parseSectionDirectiveLiteral4(StringRef, SMLoc) {237return parseSectionSwitch("__TEXT", "__literal4",238MachO::S_4BYTE_LITERALS, 4);239}240241bool parseSectionDirectiveLiteral8(StringRef, SMLoc) {242return parseSectionSwitch("__TEXT", "__literal8",243MachO::S_8BYTE_LITERALS, 8);244}245246bool parseSectionDirectiveLiteral16(StringRef, SMLoc) {247return parseSectionSwitch("__TEXT","__literal16",248MachO::S_16BYTE_LITERALS, 16);249}250251bool parseSectionDirectiveConstructor(StringRef, SMLoc) {252return parseSectionSwitch("__TEXT","__constructor");253}254255bool parseSectionDirectiveDestructor(StringRef, SMLoc) {256return parseSectionSwitch("__TEXT","__destructor");257}258259bool parseSectionDirectiveFVMLibInit0(StringRef, SMLoc) {260return parseSectionSwitch("__TEXT","__fvmlib_init0");261}262263bool parseSectionDirectiveFVMLibInit1(StringRef, SMLoc) {264return parseSectionSwitch("__TEXT","__fvmlib_init1");265}266267bool parseSectionDirectiveSymbolStub(StringRef, SMLoc) {268return parseSectionSwitch("__TEXT","__symbol_stub",269MachO::S_SYMBOL_STUBS |270MachO::S_ATTR_PURE_INSTRUCTIONS,271// FIXME: Different on PPC and ARM.2720, 16);273}274275bool parseSectionDirectivePICSymbolStub(StringRef, SMLoc) {276return parseSectionSwitch("__TEXT","__picsymbol_stub",277MachO::S_SYMBOL_STUBS |278MachO::S_ATTR_PURE_INSTRUCTIONS, 0, 26);279}280281bool parseSectionDirectiveData(StringRef, SMLoc) {282return parseSectionSwitch("__DATA", "__data");283}284285bool parseSectionDirectiveStaticData(StringRef, SMLoc) {286return parseSectionSwitch("__DATA", "__static_data");287}288289bool parseSectionDirectiveNonLazySymbolPointers(StringRef, SMLoc) {290return parseSectionSwitch("__DATA", "__nl_symbol_ptr",291MachO::S_NON_LAZY_SYMBOL_POINTERS, 4);292}293294bool parseSectionDirectiveLazySymbolPointers(StringRef, SMLoc) {295return parseSectionSwitch("__DATA", "__la_symbol_ptr",296MachO::S_LAZY_SYMBOL_POINTERS, 4);297}298299bool parseSectionDirectiveThreadLocalVariablePointers(StringRef, SMLoc) {300return parseSectionSwitch("__DATA", "__thread_ptr",301MachO::S_THREAD_LOCAL_VARIABLE_POINTERS, 4);302}303304bool parseSectionDirectiveDyld(StringRef, SMLoc) {305return parseSectionSwitch("__DATA", "__dyld");306}307308bool parseSectionDirectiveModInitFunc(StringRef, SMLoc) {309return parseSectionSwitch("__DATA", "__mod_init_func",310MachO::S_MOD_INIT_FUNC_POINTERS, 4);311}312313bool parseSectionDirectiveModTermFunc(StringRef, SMLoc) {314return parseSectionSwitch("__DATA", "__mod_term_func",315MachO::S_MOD_TERM_FUNC_POINTERS, 4);316}317318bool parseSectionDirectiveConstData(StringRef, SMLoc) {319return parseSectionSwitch("__DATA", "__const");320}321322bool parseSectionDirectiveObjCClass(StringRef, SMLoc) {323return parseSectionSwitch("__OBJC", "__class",324MachO::S_ATTR_NO_DEAD_STRIP);325}326327bool parseSectionDirectiveObjCMetaClass(StringRef, SMLoc) {328return parseSectionSwitch("__OBJC", "__meta_class",329MachO::S_ATTR_NO_DEAD_STRIP);330}331332bool parseSectionDirectiveObjCCatClsMeth(StringRef, SMLoc) {333return parseSectionSwitch("__OBJC", "__cat_cls_meth",334MachO::S_ATTR_NO_DEAD_STRIP);335}336337bool parseSectionDirectiveObjCCatInstMeth(StringRef, SMLoc) {338return parseSectionSwitch("__OBJC", "__cat_inst_meth",339MachO::S_ATTR_NO_DEAD_STRIP);340}341342bool parseSectionDirectiveObjCProtocol(StringRef, SMLoc) {343return parseSectionSwitch("__OBJC", "__protocol",344MachO::S_ATTR_NO_DEAD_STRIP);345}346347bool parseSectionDirectiveObjCStringObject(StringRef, SMLoc) {348return parseSectionSwitch("__OBJC", "__string_object",349MachO::S_ATTR_NO_DEAD_STRIP);350}351352bool parseSectionDirectiveObjCClsMeth(StringRef, SMLoc) {353return parseSectionSwitch("__OBJC", "__cls_meth",354MachO::S_ATTR_NO_DEAD_STRIP);355}356357bool parseSectionDirectiveObjCInstMeth(StringRef, SMLoc) {358return parseSectionSwitch("__OBJC", "__inst_meth",359MachO::S_ATTR_NO_DEAD_STRIP);360}361362bool parseSectionDirectiveObjCClsRefs(StringRef, SMLoc) {363return parseSectionSwitch("__OBJC", "__cls_refs",364MachO::S_ATTR_NO_DEAD_STRIP |365MachO::S_LITERAL_POINTERS, 4);366}367368bool parseSectionDirectiveObjCMessageRefs(StringRef, SMLoc) {369return parseSectionSwitch("__OBJC", "__message_refs",370MachO::S_ATTR_NO_DEAD_STRIP |371MachO::S_LITERAL_POINTERS, 4);372}373374bool parseSectionDirectiveObjCSymbols(StringRef, SMLoc) {375return parseSectionSwitch("__OBJC", "__symbols",376MachO::S_ATTR_NO_DEAD_STRIP);377}378379bool parseSectionDirectiveObjCCategory(StringRef, SMLoc) {380return parseSectionSwitch("__OBJC", "__category",381MachO::S_ATTR_NO_DEAD_STRIP);382}383384bool parseSectionDirectiveObjCClassVars(StringRef, SMLoc) {385return parseSectionSwitch("__OBJC", "__class_vars",386MachO::S_ATTR_NO_DEAD_STRIP);387}388389bool parseSectionDirectiveObjCInstanceVars(StringRef, SMLoc) {390return parseSectionSwitch("__OBJC", "__instance_vars",391MachO::S_ATTR_NO_DEAD_STRIP);392}393394bool parseSectionDirectiveObjCModuleInfo(StringRef, SMLoc) {395return parseSectionSwitch("__OBJC", "__module_info",396MachO::S_ATTR_NO_DEAD_STRIP);397}398399bool parseSectionDirectiveObjCClassNames(StringRef, SMLoc) {400return parseSectionSwitch("__TEXT", "__cstring",401MachO::S_CSTRING_LITERALS);402}403404bool parseSectionDirectiveObjCMethVarTypes(StringRef, SMLoc) {405return parseSectionSwitch("__TEXT", "__cstring",406MachO::S_CSTRING_LITERALS);407}408409bool parseSectionDirectiveObjCMethVarNames(StringRef, SMLoc) {410return parseSectionSwitch("__TEXT", "__cstring",411MachO::S_CSTRING_LITERALS);412}413414bool parseSectionDirectiveObjCSelectorStrs(StringRef, SMLoc) {415return parseSectionSwitch("__OBJC", "__selector_strs",416MachO::S_CSTRING_LITERALS);417}418419bool parseSectionDirectiveTData(StringRef, SMLoc) {420return parseSectionSwitch("__DATA", "__thread_data",421MachO::S_THREAD_LOCAL_REGULAR);422}423424bool parseSectionDirectiveText(StringRef, SMLoc) {425return parseSectionSwitch("__TEXT", "__text",426MachO::S_ATTR_PURE_INSTRUCTIONS);427}428429bool parseSectionDirectiveTLV(StringRef, SMLoc) {430return parseSectionSwitch("__DATA", "__thread_vars",431MachO::S_THREAD_LOCAL_VARIABLES);432}433434bool parseSectionDirectiveIdent(StringRef, SMLoc) {435// Darwin silently ignores the .ident directive.436getParser().eatToEndOfStatement();437return false;438}439440bool parseSectionDirectiveThreadInitFunc(StringRef, SMLoc) {441return parseSectionSwitch("__DATA", "__thread_init",442MachO::S_THREAD_LOCAL_INIT_FUNCTION_POINTERS);443}444445bool parseWatchOSVersionMin(StringRef Directive, SMLoc Loc) {446return parseVersionMin(Directive, Loc, MCVM_WatchOSVersionMin);447}448bool parseTvOSVersionMin(StringRef Directive, SMLoc Loc) {449return parseVersionMin(Directive, Loc, MCVM_TvOSVersionMin);450}451bool parseIOSVersionMin(StringRef Directive, SMLoc Loc) {452return parseVersionMin(Directive, Loc, MCVM_IOSVersionMin);453}454bool parseMacOSXVersionMin(StringRef Directive, SMLoc Loc) {455return parseVersionMin(Directive, Loc, MCVM_OSXVersionMin);456}457458bool parseBuildVersion(StringRef Directive, SMLoc Loc);459bool parseVersionMin(StringRef Directive, SMLoc Loc, MCVersionMinType Type);460bool parseMajorMinorVersionComponent(unsigned *Major, unsigned *Minor,461const char *VersionName);462bool parseOptionalTrailingVersionComponent(unsigned *Component,463const char *ComponentName);464bool parseVersion(unsigned *Major, unsigned *Minor, unsigned *Update);465bool parseSDKVersion(VersionTuple &SDKVersion);466void checkVersion(StringRef Directive, StringRef Arg, SMLoc Loc,467Triple::OSType ExpectedOS);468bool parseDirectiveCGProfile(StringRef Directive, SMLoc Loc);469};470471} // end anonymous namespace472473bool DarwinAsmParser::parseSectionSwitch(StringRef Segment, StringRef Section,474unsigned TAA, unsigned Alignment,475unsigned StubSize) {476if (getLexer().isNot(AsmToken::EndOfStatement))477return TokError("unexpected token in section switching directive");478Lex();479480// FIXME: Arch specific.481bool isText = TAA & MachO::S_ATTR_PURE_INSTRUCTIONS;482getStreamer().switchSection(getContext().getMachOSection(483Segment, Section, TAA, StubSize,484isText ? SectionKind::getText() : SectionKind::getData()));485486// Set the implicit alignment, if any.487//488// FIXME: This isn't really what 'as' does; I think it just uses the implicit489// alignment on the section (e.g., if one manually inserts bytes into the490// section, then just issuing the section switch directive will not realign491// the section. However, this is arguably more reasonable behavior, and there492// is no good reason for someone to intentionally emit incorrectly sized493// values into the implicitly aligned sections.494if (Alignment)495getStreamer().emitValueToAlignment(Align(Alignment));496497return false;498}499500/// parseDirectiveAltEntry501/// ::= .alt_entry identifier502bool DarwinAsmParser::parseDirectiveAltEntry(StringRef, SMLoc) {503StringRef Name;504if (getParser().parseIdentifier(Name))505return TokError("expected identifier in directive");506507// Look up symbol.508MCSymbol *Sym = getContext().getOrCreateSymbol(Name);509510if (Sym->isDefined())511return TokError(".alt_entry must preceed symbol definition");512513if (!getStreamer().emitSymbolAttribute(Sym, MCSA_AltEntry))514return TokError("unable to emit symbol attribute");515516Lex();517return false;518}519520/// parseDirectiveDesc521/// ::= .desc identifier , expression522bool DarwinAsmParser::parseDirectiveDesc(StringRef, SMLoc) {523StringRef Name;524if (getParser().parseIdentifier(Name))525return TokError("expected identifier in directive");526527// Handle the identifier as the key symbol.528MCSymbol *Sym = getContext().getOrCreateSymbol(Name);529530if (getLexer().isNot(AsmToken::Comma))531return TokError("unexpected token in '.desc' directive");532Lex();533534int64_t DescValue;535if (getParser().parseAbsoluteExpression(DescValue))536return true;537538if (getLexer().isNot(AsmToken::EndOfStatement))539return TokError("unexpected token in '.desc' directive");540541Lex();542543// Set the n_desc field of this Symbol to this DescValue544getStreamer().emitSymbolDesc(Sym, DescValue);545546return false;547}548549/// parseDirectiveIndirectSymbol550/// ::= .indirect_symbol identifier551bool DarwinAsmParser::parseDirectiveIndirectSymbol(StringRef, SMLoc Loc) {552const MCSectionMachO *Current = static_cast<const MCSectionMachO *>(553getStreamer().getCurrentSectionOnly());554MachO::SectionType SectionType = Current->getType();555if (SectionType != MachO::S_NON_LAZY_SYMBOL_POINTERS &&556SectionType != MachO::S_LAZY_SYMBOL_POINTERS &&557SectionType != MachO::S_THREAD_LOCAL_VARIABLE_POINTERS &&558SectionType != MachO::S_SYMBOL_STUBS)559return Error(Loc, "indirect symbol not in a symbol pointer or stub "560"section");561562StringRef Name;563if (getParser().parseIdentifier(Name))564return TokError("expected identifier in .indirect_symbol directive");565566MCSymbol *Sym = getContext().getOrCreateSymbol(Name);567568// Assembler local symbols don't make any sense here. Complain loudly.569if (Sym->isTemporary())570return TokError("non-local symbol required in directive");571572if (!getStreamer().emitSymbolAttribute(Sym, MCSA_IndirectSymbol))573return TokError("unable to emit indirect symbol attribute for: " + Name);574575if (getLexer().isNot(AsmToken::EndOfStatement))576return TokError("unexpected token in '.indirect_symbol' directive");577578Lex();579580return false;581}582583/// parseDirectiveDumpOrLoad584/// ::= ( .dump | .load ) "filename"585bool DarwinAsmParser::parseDirectiveDumpOrLoad(StringRef Directive,586SMLoc IDLoc) {587bool IsDump = Directive == ".dump";588if (getLexer().isNot(AsmToken::String))589return TokError("expected string in '.dump' or '.load' directive");590591Lex();592593if (getLexer().isNot(AsmToken::EndOfStatement))594return TokError("unexpected token in '.dump' or '.load' directive");595596Lex();597598// FIXME: If/when .dump and .load are implemented they will be done in the599// the assembly parser and not have any need for an MCStreamer API.600if (IsDump)601return Warning(IDLoc, "ignoring directive .dump for now");602else603return Warning(IDLoc, "ignoring directive .load for now");604}605606/// ParseDirectiveLinkerOption607/// ::= .linker_option "string" ( , "string" )*608bool DarwinAsmParser::parseDirectiveLinkerOption(StringRef IDVal, SMLoc) {609SmallVector<std::string, 4> Args;610while (true) {611if (getLexer().isNot(AsmToken::String))612return TokError("expected string in '" + Twine(IDVal) + "' directive");613614std::string Data;615if (getParser().parseEscapedString(Data))616return true;617618Args.push_back(Data);619620if (getLexer().is(AsmToken::EndOfStatement))621break;622623if (getLexer().isNot(AsmToken::Comma))624return TokError("unexpected token in '" + Twine(IDVal) + "' directive");625Lex();626}627628getStreamer().emitLinkerOptions(Args);629return false;630}631632/// parseDirectiveLsym633/// ::= .lsym identifier , expression634bool DarwinAsmParser::parseDirectiveLsym(StringRef, SMLoc) {635StringRef Name;636if (getParser().parseIdentifier(Name))637return TokError("expected identifier in directive");638639// Handle the identifier as the key symbol.640MCSymbol *Sym = getContext().getOrCreateSymbol(Name);641642if (getLexer().isNot(AsmToken::Comma))643return TokError("unexpected token in '.lsym' directive");644Lex();645646const MCExpr *Value;647if (getParser().parseExpression(Value))648return true;649650if (getLexer().isNot(AsmToken::EndOfStatement))651return TokError("unexpected token in '.lsym' directive");652653Lex();654655// We don't currently support this directive.656//657// FIXME: Diagnostic location!658(void) Sym;659return TokError("directive '.lsym' is unsupported");660}661662/// parseDirectiveSection:663/// ::= .section identifier (',' identifier)*664bool DarwinAsmParser::parseDirectiveSection(StringRef, SMLoc) {665SMLoc Loc = getLexer().getLoc();666667StringRef SectionName;668if (getParser().parseIdentifier(SectionName))669return Error(Loc, "expected identifier after '.section' directive");670671// Verify there is a following comma.672if (!getLexer().is(AsmToken::Comma))673return TokError("unexpected token in '.section' directive");674675std::string SectionSpec = std::string(SectionName);676SectionSpec += ",";677678// Add all the tokens until the end of the line, ParseSectionSpecifier will679// handle this.680StringRef EOL = getLexer().LexUntilEndOfStatement();681SectionSpec.append(EOL.begin(), EOL.end());682683Lex();684if (getLexer().isNot(AsmToken::EndOfStatement))685return TokError("unexpected token in '.section' directive");686Lex();687688StringRef Segment, Section;689unsigned StubSize;690unsigned TAA;691bool TAAParsed;692if (class Error E = MCSectionMachO::ParseSectionSpecifier(693SectionSpec, Segment, Section, TAA, TAAParsed, StubSize))694return Error(Loc, toString(std::move(E)));695696// Issue a warning if the target is not powerpc and Section is a *coal* section.697Triple TT = getParser().getContext().getTargetTriple();698Triple::ArchType ArchTy = TT.getArch();699700if (ArchTy != Triple::ppc && ArchTy != Triple::ppc64) {701StringRef NonCoalSection = StringSwitch<StringRef>(Section)702.Case("__textcoal_nt", "__text")703.Case("__const_coal", "__const")704.Case("__datacoal_nt", "__data")705.Default(Section);706707if (Section != NonCoalSection) {708StringRef SectionVal(Loc.getPointer());709size_t B = SectionVal.find(',') + 1, E = SectionVal.find(',', B);710SMLoc BLoc = SMLoc::getFromPointer(SectionVal.data() + B);711SMLoc ELoc = SMLoc::getFromPointer(SectionVal.data() + E);712getParser().Warning(Loc, "section \"" + Section + "\" is deprecated",713SMRange(BLoc, ELoc));714getParser().Note(Loc, "change section name to \"" + NonCoalSection +715"\"", SMRange(BLoc, ELoc));716}717}718719// FIXME: Arch specific.720bool isText = Segment == "__TEXT"; // FIXME: Hack.721getStreamer().switchSection(getContext().getMachOSection(722Segment, Section, TAA, StubSize,723isText ? SectionKind::getText() : SectionKind::getData()));724return false;725}726727/// ParseDirectivePushSection:728/// ::= .pushsection identifier (',' identifier)*729bool DarwinAsmParser::parseDirectivePushSection(StringRef S, SMLoc Loc) {730getStreamer().pushSection();731732if (parseDirectiveSection(S, Loc)) {733getStreamer().popSection();734return true;735}736737return false;738}739740/// ParseDirectivePopSection:741/// ::= .popsection742bool DarwinAsmParser::parseDirectivePopSection(StringRef, SMLoc) {743if (!getStreamer().popSection())744return TokError(".popsection without corresponding .pushsection");745return false;746}747748/// ParseDirectivePrevious:749/// ::= .previous750bool DarwinAsmParser::parseDirectivePrevious(StringRef DirName, SMLoc) {751MCSectionSubPair PreviousSection = getStreamer().getPreviousSection();752if (!PreviousSection.first)753return TokError(".previous without corresponding .section");754getStreamer().switchSection(PreviousSection.first, PreviousSection.second);755return false;756}757758/// ParseDirectiveSecureLogUnique759/// ::= .secure_log_unique ... message ...760bool DarwinAsmParser::parseDirectiveSecureLogUnique(StringRef, SMLoc IDLoc) {761StringRef LogMessage = getParser().parseStringToEndOfStatement();762if (getLexer().isNot(AsmToken::EndOfStatement))763return TokError("unexpected token in '.secure_log_unique' directive");764765if (getContext().getSecureLogUsed())766return Error(IDLoc, ".secure_log_unique specified multiple times");767768// Get the secure log path.769StringRef SecureLogFile = getContext().getSecureLogFile();770if (SecureLogFile.empty())771return Error(IDLoc, ".secure_log_unique used but AS_SECURE_LOG_FILE "772"environment variable unset.");773774// Open the secure log file if we haven't already.775raw_fd_ostream *OS = getContext().getSecureLog();776if (!OS) {777std::error_code EC;778auto NewOS = std::make_unique<raw_fd_ostream>(779SecureLogFile, EC, sys::fs::OF_Append | sys::fs::OF_TextWithCRLF);780if (EC)781return Error(IDLoc, Twine("can't open secure log file: ") +782SecureLogFile + " (" + EC.message() + ")");783OS = NewOS.get();784getContext().setSecureLog(std::move(NewOS));785}786787// Write the message.788unsigned CurBuf = getSourceManager().FindBufferContainingLoc(IDLoc);789*OS << getSourceManager().getBufferInfo(CurBuf).Buffer->getBufferIdentifier()790<< ":" << getSourceManager().FindLineNumber(IDLoc, CurBuf) << ":"791<< LogMessage + "\n";792793getContext().setSecureLogUsed(true);794795return false;796}797798/// ParseDirectiveSecureLogReset799/// ::= .secure_log_reset800bool DarwinAsmParser::parseDirectiveSecureLogReset(StringRef, SMLoc IDLoc) {801if (getLexer().isNot(AsmToken::EndOfStatement))802return TokError("unexpected token in '.secure_log_reset' directive");803804Lex();805806getContext().setSecureLogUsed(false);807808return false;809}810811/// parseDirectiveSubsectionsViaSymbols812/// ::= .subsections_via_symbols813bool DarwinAsmParser::parseDirectiveSubsectionsViaSymbols(StringRef, SMLoc) {814if (getLexer().isNot(AsmToken::EndOfStatement))815return TokError("unexpected token in '.subsections_via_symbols' directive");816817Lex();818819getStreamer().emitAssemblerFlag(MCAF_SubsectionsViaSymbols);820821return false;822}823824/// ParseDirectiveTBSS825/// ::= .tbss identifier, size, align826bool DarwinAsmParser::parseDirectiveTBSS(StringRef, SMLoc) {827SMLoc IDLoc = getLexer().getLoc();828StringRef Name;829if (getParser().parseIdentifier(Name))830return TokError("expected identifier in directive");831832// Handle the identifier as the key symbol.833MCSymbol *Sym = getContext().getOrCreateSymbol(Name);834835if (getLexer().isNot(AsmToken::Comma))836return TokError("unexpected token in directive");837Lex();838839int64_t Size;840SMLoc SizeLoc = getLexer().getLoc();841if (getParser().parseAbsoluteExpression(Size))842return true;843844int64_t Pow2Alignment = 0;845SMLoc Pow2AlignmentLoc;846if (getLexer().is(AsmToken::Comma)) {847Lex();848Pow2AlignmentLoc = getLexer().getLoc();849if (getParser().parseAbsoluteExpression(Pow2Alignment))850return true;851}852853if (getLexer().isNot(AsmToken::EndOfStatement))854return TokError("unexpected token in '.tbss' directive");855856Lex();857858if (Size < 0)859return Error(SizeLoc, "invalid '.tbss' directive size, can't be less than"860"zero");861862// FIXME: Diagnose overflow.863if (Pow2Alignment < 0)864return Error(Pow2AlignmentLoc, "invalid '.tbss' alignment, can't be less"865"than zero");866867if (!Sym->isUndefined())868return Error(IDLoc, "invalid symbol redefinition");869870getStreamer().emitTBSSSymbol(871getContext().getMachOSection("__DATA", "__thread_bss",872MachO::S_THREAD_LOCAL_ZEROFILL, 0,873SectionKind::getThreadBSS()),874Sym, Size, Align(1ULL << Pow2Alignment));875876return false;877}878879/// ParseDirectiveZerofill880/// ::= .zerofill segname , sectname [, identifier , size_expression [881/// , align_expression ]]882bool DarwinAsmParser::parseDirectiveZerofill(StringRef, SMLoc) {883StringRef Segment;884if (getParser().parseIdentifier(Segment))885return TokError("expected segment name after '.zerofill' directive");886887if (getLexer().isNot(AsmToken::Comma))888return TokError("unexpected token in directive");889Lex();890891StringRef Section;892SMLoc SectionLoc = getLexer().getLoc();893if (getParser().parseIdentifier(Section))894return TokError("expected section name after comma in '.zerofill' "895"directive");896897// If this is the end of the line all that was wanted was to create the898// the section but with no symbol.899if (getLexer().is(AsmToken::EndOfStatement)) {900// Create the zerofill section but no symbol901getStreamer().emitZerofill(902getContext().getMachOSection(Segment, Section, MachO::S_ZEROFILL, 0,903SectionKind::getBSS()),904/*Symbol=*/nullptr, /*Size=*/0, Align(1), SectionLoc);905return false;906}907908if (getLexer().isNot(AsmToken::Comma))909return TokError("unexpected token in directive");910Lex();911912SMLoc IDLoc = getLexer().getLoc();913StringRef IDStr;914if (getParser().parseIdentifier(IDStr))915return TokError("expected identifier in directive");916917// handle the identifier as the key symbol.918MCSymbol *Sym = getContext().getOrCreateSymbol(IDStr);919920if (getLexer().isNot(AsmToken::Comma))921return TokError("unexpected token in directive");922Lex();923924int64_t Size;925SMLoc SizeLoc = getLexer().getLoc();926if (getParser().parseAbsoluteExpression(Size))927return true;928929int64_t Pow2Alignment = 0;930SMLoc Pow2AlignmentLoc;931if (getLexer().is(AsmToken::Comma)) {932Lex();933Pow2AlignmentLoc = getLexer().getLoc();934if (getParser().parseAbsoluteExpression(Pow2Alignment))935return true;936}937938if (getLexer().isNot(AsmToken::EndOfStatement))939return TokError("unexpected token in '.zerofill' directive");940941Lex();942943if (Size < 0)944return Error(SizeLoc, "invalid '.zerofill' directive size, can't be less "945"than zero");946947// NOTE: The alignment in the directive is a power of 2 value, the assembler948// may internally end up wanting an alignment in bytes.949// FIXME: Diagnose overflow.950if (Pow2Alignment < 0)951return Error(Pow2AlignmentLoc, "invalid '.zerofill' directive alignment, "952"can't be less than zero");953954if (!Sym->isUndefined())955return Error(IDLoc, "invalid symbol redefinition");956957// Create the zerofill Symbol with Size and Pow2Alignment958//959// FIXME: Arch specific.960getStreamer().emitZerofill(961getContext().getMachOSection(Segment, Section, MachO::S_ZEROFILL, 0,962SectionKind::getBSS()),963Sym, Size, Align(1ULL << Pow2Alignment), SectionLoc);964965return false;966}967968/// ParseDirectiveDataRegion969/// ::= .data_region [ ( jt8 | jt16 | jt32 ) ]970bool DarwinAsmParser::parseDirectiveDataRegion(StringRef, SMLoc) {971if (getLexer().is(AsmToken::EndOfStatement)) {972Lex();973getStreamer().emitDataRegion(MCDR_DataRegion);974return false;975}976StringRef RegionType;977SMLoc Loc = getParser().getTok().getLoc();978if (getParser().parseIdentifier(RegionType))979return TokError("expected region type after '.data_region' directive");980int Kind = StringSwitch<int>(RegionType)981.Case("jt8", MCDR_DataRegionJT8)982.Case("jt16", MCDR_DataRegionJT16)983.Case("jt32", MCDR_DataRegionJT32)984.Default(-1);985if (Kind == -1)986return Error(Loc, "unknown region type in '.data_region' directive");987Lex();988989getStreamer().emitDataRegion((MCDataRegionType)Kind);990return false;991}992993/// ParseDirectiveDataRegionEnd994/// ::= .end_data_region995bool DarwinAsmParser::parseDirectiveDataRegionEnd(StringRef, SMLoc) {996if (getLexer().isNot(AsmToken::EndOfStatement))997return TokError("unexpected token in '.end_data_region' directive");998999Lex();1000getStreamer().emitDataRegion(MCDR_DataRegionEnd);1001return false;1002}10031004static bool isSDKVersionToken(const AsmToken &Tok) {1005return Tok.is(AsmToken::Identifier) && Tok.getIdentifier() == "sdk_version";1006}10071008/// parseMajorMinorVersionComponent ::= major, minor1009bool DarwinAsmParser::parseMajorMinorVersionComponent(unsigned *Major,1010unsigned *Minor,1011const char *VersionName) {1012// Get the major version number.1013if (getLexer().isNot(AsmToken::Integer))1014return TokError(Twine("invalid ") + VersionName +1015" major version number, integer expected");1016int64_t MajorVal = getLexer().getTok().getIntVal();1017if (MajorVal > 65535 || MajorVal <= 0)1018return TokError(Twine("invalid ") + VersionName + " major version number");1019*Major = (unsigned)MajorVal;1020Lex();1021if (getLexer().isNot(AsmToken::Comma))1022return TokError(Twine(VersionName) +1023" minor version number required, comma expected");1024Lex();1025// Get the minor version number.1026if (getLexer().isNot(AsmToken::Integer))1027return TokError(Twine("invalid ") + VersionName +1028" minor version number, integer expected");1029int64_t MinorVal = getLexer().getTok().getIntVal();1030if (MinorVal > 255 || MinorVal < 0)1031return TokError(Twine("invalid ") + VersionName + " minor version number");1032*Minor = MinorVal;1033Lex();1034return false;1035}10361037/// parseOptionalTrailingVersionComponent ::= , version_number1038bool DarwinAsmParser::parseOptionalTrailingVersionComponent(1039unsigned *Component, const char *ComponentName) {1040assert(getLexer().is(AsmToken::Comma) && "comma expected");1041Lex();1042if (getLexer().isNot(AsmToken::Integer))1043return TokError(Twine("invalid ") + ComponentName +1044" version number, integer expected");1045int64_t Val = getLexer().getTok().getIntVal();1046if (Val > 255 || Val < 0)1047return TokError(Twine("invalid ") + ComponentName + " version number");1048*Component = Val;1049Lex();1050return false;1051}10521053/// parseVersion ::= parseMajorMinorVersionComponent1054/// parseOptionalTrailingVersionComponent1055bool DarwinAsmParser::parseVersion(unsigned *Major, unsigned *Minor,1056unsigned *Update) {1057if (parseMajorMinorVersionComponent(Major, Minor, "OS"))1058return true;10591060// Get the update level, if specified1061*Update = 0;1062if (getLexer().is(AsmToken::EndOfStatement) ||1063isSDKVersionToken(getLexer().getTok()))1064return false;1065if (getLexer().isNot(AsmToken::Comma))1066return TokError("invalid OS update specifier, comma expected");1067if (parseOptionalTrailingVersionComponent(Update, "OS update"))1068return true;1069return false;1070}10711072bool DarwinAsmParser::parseSDKVersion(VersionTuple &SDKVersion) {1073assert(isSDKVersionToken(getLexer().getTok()) && "expected sdk_version");1074Lex();1075unsigned Major, Minor;1076if (parseMajorMinorVersionComponent(&Major, &Minor, "SDK"))1077return true;1078SDKVersion = VersionTuple(Major, Minor);10791080// Get the subminor version, if specified.1081if (getLexer().is(AsmToken::Comma)) {1082unsigned Subminor;1083if (parseOptionalTrailingVersionComponent(&Subminor, "SDK subminor"))1084return true;1085SDKVersion = VersionTuple(Major, Minor, Subminor);1086}1087return false;1088}10891090void DarwinAsmParser::checkVersion(StringRef Directive, StringRef Arg,1091SMLoc Loc, Triple::OSType ExpectedOS) {1092const Triple &Target = getContext().getTargetTriple();1093if (Target.getOS() != ExpectedOS)1094Warning(Loc, Twine(Directive) +1095(Arg.empty() ? Twine() : Twine(' ') + Arg) +1096" used while targeting " + Target.getOSName());10971098if (LastVersionDirective.isValid()) {1099Warning(Loc, "overriding previous version directive");1100Note(LastVersionDirective, "previous definition is here");1101}1102LastVersionDirective = Loc;1103}11041105static Triple::OSType getOSTypeFromMCVM(MCVersionMinType Type) {1106switch (Type) {1107case MCVM_WatchOSVersionMin: return Triple::WatchOS;1108case MCVM_TvOSVersionMin: return Triple::TvOS;1109case MCVM_IOSVersionMin: return Triple::IOS;1110case MCVM_OSXVersionMin: return Triple::MacOSX;1111}1112llvm_unreachable("Invalid mc version min type");1113}11141115/// parseVersionMin1116/// ::= .ios_version_min parseVersion parseSDKVersion1117/// | .macosx_version_min parseVersion parseSDKVersion1118/// | .tvos_version_min parseVersion parseSDKVersion1119/// | .watchos_version_min parseVersion parseSDKVersion1120bool DarwinAsmParser::parseVersionMin(StringRef Directive, SMLoc Loc,1121MCVersionMinType Type) {1122unsigned Major;1123unsigned Minor;1124unsigned Update;1125if (parseVersion(&Major, &Minor, &Update))1126return true;11271128VersionTuple SDKVersion;1129if (isSDKVersionToken(getLexer().getTok()) && parseSDKVersion(SDKVersion))1130return true;11311132if (parseEOL())1133return addErrorSuffix(Twine(" in '") + Directive + "' directive");11341135Triple::OSType ExpectedOS = getOSTypeFromMCVM(Type);1136checkVersion(Directive, StringRef(), Loc, ExpectedOS);1137getStreamer().emitVersionMin(Type, Major, Minor, Update, SDKVersion);1138return false;1139}11401141static Triple::OSType getOSTypeFromPlatform(MachO::PlatformType Type) {1142switch (Type) {1143case MachO::PLATFORM_UNKNOWN: /* silence warning */1144break;1145case MachO::PLATFORM_MACOS: return Triple::MacOSX;1146case MachO::PLATFORM_IOS: return Triple::IOS;1147case MachO::PLATFORM_TVOS: return Triple::TvOS;1148case MachO::PLATFORM_WATCHOS: return Triple::WatchOS;1149case MachO::PLATFORM_XROS: return Triple::XROS;1150case MachO::PLATFORM_BRIDGEOS: /* silence warning */ break;1151case MachO::PLATFORM_DRIVERKIT:1152return Triple::DriverKit;1153case MachO::PLATFORM_MACCATALYST: return Triple::IOS;1154case MachO::PLATFORM_IOSSIMULATOR: /* silence warning */ break;1155case MachO::PLATFORM_TVOSSIMULATOR: /* silence warning */ break;1156case MachO::PLATFORM_WATCHOSSIMULATOR: /* silence warning */ break;1157case MachO::PLATFORM_XROS_SIMULATOR: /* silence warning */ break;1158}1159llvm_unreachable("Invalid mach-o platform type");1160}11611162/// parseBuildVersion1163/// ::= .build_version (macos|ios|tvos|watchos), parseVersion parseSDKVersion1164bool DarwinAsmParser::parseBuildVersion(StringRef Directive, SMLoc Loc) {1165StringRef PlatformName;1166SMLoc PlatformLoc = getTok().getLoc();1167if (getParser().parseIdentifier(PlatformName))1168return TokError("platform name expected");11691170unsigned Platform = StringSwitch<unsigned>(PlatformName)1171#define PLATFORM(platform, id, name, build_name, target, tapi_target, \1172marketing) \1173.Case(#build_name, MachO::PLATFORM_##platform)1174#include "llvm/BinaryFormat/MachO.def"1175.Default(MachO::PLATFORM_UNKNOWN);11761177if (Platform == MachO::PLATFORM_UNKNOWN)1178return Error(PlatformLoc, "unknown platform name");11791180if (getLexer().isNot(AsmToken::Comma))1181return TokError("version number required, comma expected");1182Lex();11831184unsigned Major;1185unsigned Minor;1186unsigned Update;1187if (parseVersion(&Major, &Minor, &Update))1188return true;11891190VersionTuple SDKVersion;1191if (isSDKVersionToken(getLexer().getTok()) && parseSDKVersion(SDKVersion))1192return true;11931194if (parseEOL())1195return addErrorSuffix(" in '.build_version' directive");11961197Triple::OSType ExpectedOS1198= getOSTypeFromPlatform((MachO::PlatformType)Platform);1199checkVersion(Directive, PlatformName, Loc, ExpectedOS);1200getStreamer().emitBuildVersion(Platform, Major, Minor, Update, SDKVersion);1201return false;1202}12031204/// parseDirectiveCGProfile1205/// ::= .cg_profile from, to, count1206bool DarwinAsmParser::parseDirectiveCGProfile(StringRef S, SMLoc Loc) {1207return MCAsmParserExtension::ParseDirectiveCGProfile(S, Loc);1208}12091210namespace llvm {12111212MCAsmParserExtension *createDarwinAsmParser() {1213return new DarwinAsmParser;1214}12151216} // end llvm namespace121712181219