diff options
author | Matthias Braun <matze@braunis.de> | 2017-12-14 00:12:46 +0000 |
---|---|---|
committer | Matthias Braun <matze@braunis.de> | 2017-12-14 00:12:46 +0000 |
commit | 0148c88c080cce52c09bd9bfc4dd2127734a6a9e (patch) | |
tree | 75fe343be05f900e3dc0e5b8aec67e790995e718 /llvm/lib/MC/MCParser/DarwinAsmParser.cpp | |
parent | 2c1fa4feb183b7168d98f5dba8984b9dfde4ab31 (diff) | |
download | bcm5719-llvm-0148c88c080cce52c09bd9bfc4dd2127734a6a9e.tar.gz bcm5719-llvm-0148c88c080cce52c09bd9bfc4dd2127734a6a9e.zip |
MC: Add support for mach-o build_version
LC_BUILD_VERSION is a new load command superseding the previously used
LC_XXX_MIN_VERSION commands. This adds an assembler directive along with
encoding/streaming support.
llvm-svn: 320661
Diffstat (limited to 'llvm/lib/MC/MCParser/DarwinAsmParser.cpp')
-rw-r--r-- | llvm/lib/MC/MCParser/DarwinAsmParser.cpp | 194 |
1 files changed, 144 insertions, 50 deletions
diff --git a/llvm/lib/MC/MCParser/DarwinAsmParser.cpp b/llvm/lib/MC/MCParser/DarwinAsmParser.cpp index f4152a9067a..195ddc78d45 100644 --- a/llvm/lib/MC/MCParser/DarwinAsmParser.cpp +++ b/llvm/lib/MC/MCParser/DarwinAsmParser.cpp @@ -54,7 +54,7 @@ class DarwinAsmParser : public MCAsmParserExtension { unsigned TAA = 0, unsigned ImplicitAlign = 0, unsigned StubSize = 0); - SMLoc LastVersionMinDirective; + SMLoc LastVersionDirective; public: DarwinAsmParser() = default; @@ -186,14 +186,17 @@ public: addDirectiveHandler<&DarwinAsmParser::parseSectionDirectiveTLV>(".tlv"); addDirectiveHandler<&DarwinAsmParser::parseSectionDirectiveIdent>(".ident"); - addDirectiveHandler<&DarwinAsmParser::parseVersionMin>( + addDirectiveHandler<&DarwinAsmParser::parseWatchOSVersionMin>( ".watchos_version_min"); - addDirectiveHandler<&DarwinAsmParser::parseVersionMin>(".tvos_version_min"); - addDirectiveHandler<&DarwinAsmParser::parseVersionMin>(".ios_version_min"); - addDirectiveHandler<&DarwinAsmParser::parseVersionMin>( + addDirectiveHandler<&DarwinAsmParser::parseTvOSVersionMin>( + ".tvos_version_min"); + addDirectiveHandler<&DarwinAsmParser::parseIOSVersionMin>( + ".ios_version_min"); + addDirectiveHandler<&DarwinAsmParser::parseMacOSXVersionMin>( ".macosx_version_min"); + addDirectiveHandler<&DarwinAsmParser::parseBuildVersion>(".build_version"); - LastVersionMinDirective = SMLoc(); + LastVersionDirective = SMLoc(); } bool parseDirectiveAltEntry(StringRef, SMLoc); @@ -441,7 +444,24 @@ public: MachO::S_THREAD_LOCAL_INIT_FUNCTION_POINTERS); } - bool parseVersionMin(StringRef, SMLoc); + bool parseWatchOSVersionMin(StringRef Directive, SMLoc Loc) { + return parseVersionMin(Directive, Loc, MCVM_WatchOSVersionMin); + } + bool parseTvOSVersionMin(StringRef Directive, SMLoc Loc) { + return parseVersionMin(Directive, Loc, MCVM_TvOSVersionMin); + } + bool parseIOSVersionMin(StringRef Directive, SMLoc Loc) { + return parseVersionMin(Directive, Loc, MCVM_IOSVersionMin); + } + bool parseMacOSXVersionMin(StringRef Directive, SMLoc Loc) { + return parseVersionMin(Directive, Loc, MCVM_OSXVersionMin); + } + + bool parseBuildVersion(StringRef Directive, SMLoc Loc); + bool parseVersionMin(StringRef Directive, SMLoc Loc, MCVersionMinType Type); + bool parseVersion(unsigned *Major, unsigned *Minor, unsigned *Update); + void checkVersion(StringRef Directive, StringRef Arg, SMLoc Loc, + Triple::OSType ExpectedOS); }; } // end anonymous namespace @@ -978,70 +998,144 @@ bool DarwinAsmParser::parseDirectiveDataRegionEnd(StringRef, SMLoc) { return false; } -/// parseVersionMin -/// ::= .ios_version_min major,minor[,update] -/// ::= .macosx_version_min major,minor[,update] -bool DarwinAsmParser::parseVersionMin(StringRef Directive, SMLoc Loc) { - int64_t Major = 0, Minor = 0, Update = 0; - int Kind = StringSwitch<int>(Directive) - .Case(".watchos_version_min", MCVM_WatchOSVersionMin) - .Case(".tvos_version_min", MCVM_TvOSVersionMin) - .Case(".ios_version_min", MCVM_IOSVersionMin) - .Case(".macosx_version_min", MCVM_OSXVersionMin); +/// parseVersion ::= major, minor [, update] +bool DarwinAsmParser::parseVersion(unsigned *Major, unsigned *Minor, + unsigned *Update) { // Get the major version number. if (getLexer().isNot(AsmToken::Integer)) + return TokError("invalid OS major version number, integer expected"); + int64_t MajorVal = getLexer().getTok().getIntVal(); + if (MajorVal > 65535 || MajorVal <= 0) return TokError("invalid OS major version number"); - Major = getLexer().getTok().getIntVal(); - if (Major > 65535 || Major <= 0) - return TokError("invalid OS major version number"); + *Major = (unsigned)MajorVal; Lex(); if (getLexer().isNot(AsmToken::Comma)) - return TokError("minor OS version number required, comma expected"); + return TokError("OS minor version number required, comma expected"); Lex(); // Get the minor version number. if (getLexer().isNot(AsmToken::Integer)) + return TokError("invalid OS minor version number, integer expected"); + int64_t MinorVal = getLexer().getTok().getIntVal(); + if (MinorVal > 255 || MinorVal < 0) return TokError("invalid OS minor version number"); - Minor = getLexer().getTok().getIntVal(); - if (Minor > 255 || Minor < 0) - return TokError("invalid OS minor version number"); + *Minor = MinorVal; Lex(); + // Get the update level, if specified - if (getLexer().isNot(AsmToken::EndOfStatement)) { - if (getLexer().isNot(AsmToken::Comma)) - return TokError("invalid update specifier, comma expected"); - Lex(); - if (getLexer().isNot(AsmToken::Integer)) - return TokError("invalid OS update number"); - Update = getLexer().getTok().getIntVal(); - if (Update > 255 || Update < 0) - return TokError("invalid OS update number"); - Lex(); + *Update = 0; + if (getLexer().is(AsmToken::EndOfStatement)) + return false; + if (getLexer().isNot(AsmToken::Comma)) + return TokError("invalid OS update specifier, comma expected"); + Lex(); + if (getLexer().isNot(AsmToken::Integer)) + return TokError("invalid OS update version number, integer expected"); + int64_t UpdateVal = getLexer().getTok().getIntVal(); + if (UpdateVal > 255 || UpdateVal < 0) + return TokError("invalid OS update version number"); + *Update = UpdateVal; + Lex(); + return false; +} + +void DarwinAsmParser::checkVersion(StringRef Directive, StringRef Arg, + SMLoc Loc, Triple::OSType ExpectedOS) { + const Triple &Target = getContext().getObjectFileInfo()->getTargetTriple(); + if (Target.getOS() != ExpectedOS) + Warning(Loc, Twine(Directive) + + (Arg.empty() ? Twine() : Twine(' ') + Arg) + + " used while targeting " + Target.getOSName()); + + if (LastVersionDirective.isValid()) { + Warning(Loc, "overriding previous version directive"); + Note(LastVersionDirective, "previous definition is here"); } + LastVersionDirective = Loc; +} - const Triple &T = getContext().getObjectFileInfo()->getTargetTriple(); - Triple::OSType ExpectedOS = Triple::UnknownOS; - switch ((MCVersionMinType)Kind) { - case MCVM_WatchOSVersionMin: ExpectedOS = Triple::WatchOS; break; - case MCVM_TvOSVersionMin: ExpectedOS = Triple::TvOS; break; - case MCVM_IOSVersionMin: ExpectedOS = Triple::IOS; break; - case MCVM_OSXVersionMin: ExpectedOS = Triple::MacOSX; break; +static Triple::OSType getOSTypeFromMCVM(MCVersionMinType Type) { + switch (Type) { + case MCVM_WatchOSVersionMin: return Triple::WatchOS; + case MCVM_TvOSVersionMin: return Triple::TvOS; + case MCVM_IOSVersionMin: return Triple::IOS; + case MCVM_OSXVersionMin: return Triple::MacOSX; } - if (T.getOS() != ExpectedOS) - Warning(Loc, Directive + " should only be used for " + - Triple::getOSTypeName(ExpectedOS) + " targets"); + llvm_unreachable("Invalid mc version min type"); +} + +/// parseVersionMin +/// ::= .ios_version_min parseVersion +/// | .macosx_version_min parseVersion +/// | .tvos_version_min parseVersion +/// | .watchos_version_min parseVersion +bool DarwinAsmParser::parseVersionMin(StringRef Directive, SMLoc Loc, + MCVersionMinType Type) { + unsigned Major; + unsigned Minor; + unsigned Update; + if (parseVersion(&Major, &Minor, &Update)) + return true; + + if (parseToken(AsmToken::EndOfStatement)) + return addErrorSuffix(Twine(" in '") + Directive + "' directive"); + + Triple::OSType ExpectedOS = getOSTypeFromMCVM(Type); + checkVersion(Directive, StringRef(), Loc, ExpectedOS); + + getStreamer().EmitVersionMin(Type, Major, Minor, Update); + return false; +} - if (LastVersionMinDirective.isValid()) { - Warning(Loc, "overriding previous version_min directive"); - Note(LastVersionMinDirective, "previous definition is here"); +Triple::OSType getOSTypeFromPlatform(MachO::PlatformType Type) { + switch (Type) { + case MachO::PLATFORM_MACOS: return Triple::MacOSX; + case MachO::PLATFORM_IOS: return Triple::IOS; + case MachO::PLATFORM_TVOS: return Triple::TvOS; + case MachO::PLATFORM_WATCHOS: return Triple::WatchOS; + case MachO::PLATFORM_BRIDGEOS: /* silence warning */break; } - LastVersionMinDirective = Loc; + llvm_unreachable("Invalid mach-o platform type"); +} - // We've parsed a correct version specifier, so send it to the streamer. - getStreamer().EmitVersionMin((MCVersionMinType)Kind, Major, Minor, Update); +/// parseBuildVersion +/// ::= .build_version (macos|ios|tvos|watchos), parseVersion +bool DarwinAsmParser::parseBuildVersion(StringRef Directive, SMLoc Loc) { + StringRef PlatformName; + SMLoc PlatformLoc = getTok().getLoc(); + if (getParser().parseIdentifier(PlatformName)) + return TokError("platform name expected"); + + unsigned Platform = StringSwitch<unsigned>(PlatformName) + .Case("macos", MachO::PLATFORM_MACOS) + .Case("ios", MachO::PLATFORM_IOS) + .Case("tvos", MachO::PLATFORM_TVOS) + .Case("watchos", MachO::PLATFORM_WATCHOS) + .Default(0); + if (Platform == 0) + return Error(PlatformLoc, "unknown platform name"); + if (getLexer().isNot(AsmToken::Comma)) + return TokError("version number required, comma expected"); + Lex(); + + unsigned Major; + unsigned Minor; + unsigned Update; + if (parseVersion(&Major, &Minor, &Update)) + return true; + + if (parseToken(AsmToken::EndOfStatement)) + return addErrorSuffix(" in '.build_version' directive"); + + Triple::OSType ExpectedOS + = getOSTypeFromPlatform((MachO::PlatformType)Platform); + checkVersion(Directive, PlatformName, Loc, ExpectedOS); + + getStreamer().EmitBuildVersion(Platform, Major, Minor, Update); return false; } + namespace llvm { MCAsmParserExtension *createDarwinAsmParser() { |