diff options
author | Alex Lorenz <arphaman@gmail.com> | 2018-12-14 01:14:10 +0000 |
---|---|---|
committer | Alex Lorenz <arphaman@gmail.com> | 2018-12-14 01:14:10 +0000 |
commit | afa75d7843c92a7ac9a194f4b1a2396c03e3efd8 (patch) | |
tree | 0b2627d35b4422489fa052fc40254da1fd8f3369 /llvm/lib | |
parent | 4065da29f071f736f8f1314847939e7859942e91 (diff) | |
download | bcm5719-llvm-afa75d7843c92a7ac9a194f4b1a2396c03e3efd8.tar.gz bcm5719-llvm-afa75d7843c92a7ac9a194f4b1a2396c03e3efd8.zip |
[macho] save the SDK version stored in module metadata into the version min and
build version load commands in the object file
This commit introduces a new metadata node called "SDK Version". It will be set
by the frontend to mark the platform SDK (macOS/iOS/etc) version which was used
during that particular compilation.
This node is used when machine code is emitted, by either saving the SDK version
into the appropriate macho load command (version min/build version), or by
emitting the assembly for these load commands with the SDK version specified as
well.
The assembly for both load commands is extended by allowing it to contain the
sdk_version X, Y [, Z] trailing directive to represent the SDK version
respectively.
rdar://45774000
Differential Revision: https://reviews.llvm.org/D55612
llvm-svn: 349119
Diffstat (limited to 'llvm/lib')
-rw-r--r-- | llvm/lib/CodeGen/AsmPrinter/AsmPrinter.cpp | 2 | ||||
-rw-r--r-- | llvm/lib/IR/Module.cpp | 40 | ||||
-rw-r--r-- | llvm/lib/MC/MCAsmStreamer.cpp | 25 | ||||
-rw-r--r-- | llvm/lib/MC/MCAssembler.cpp | 1 | ||||
-rw-r--r-- | llvm/lib/MC/MCMachOStreamer.cpp | 20 | ||||
-rw-r--r-- | llvm/lib/MC/MCParser/DarwinAsmParser.cpp | 107 | ||||
-rw-r--r-- | llvm/lib/MC/MCStreamer.cpp | 5 | ||||
-rw-r--r-- | llvm/lib/MC/MachObjectWriter.cpp | 23 | ||||
-rw-r--r-- | llvm/lib/Object/ModuleSymbolTable.cpp | 1 |
9 files changed, 176 insertions, 48 deletions
diff --git a/llvm/lib/CodeGen/AsmPrinter/AsmPrinter.cpp b/llvm/lib/CodeGen/AsmPrinter/AsmPrinter.cpp index a1622da33a6..c38457ff59e 100644 --- a/llvm/lib/CodeGen/AsmPrinter/AsmPrinter.cpp +++ b/llvm/lib/CodeGen/AsmPrinter/AsmPrinter.cpp @@ -263,7 +263,7 @@ bool AsmPrinter::doInitialization(Module &M) { // use the directive, where it would need the same conditionalization // anyway. const Triple &Target = TM.getTargetTriple(); - OutStreamer->EmitVersionForTarget(Target); + OutStreamer->EmitVersionForTarget(Target, M.getSDKVersion()); // Allow the target to emit any magic that it wants at the start of the file. EmitStartOfAsmFile(M); diff --git a/llvm/lib/IR/Module.cpp b/llvm/lib/IR/Module.cpp index 7d02a3956ff..70a16cbbf24 100644 --- a/llvm/lib/IR/Module.cpp +++ b/llvm/lib/IR/Module.cpp @@ -46,6 +46,7 @@ #include "llvm/Support/MemoryBuffer.h" #include "llvm/Support/Path.h" #include "llvm/Support/RandomNumberGenerator.h" +#include "llvm/Support/VersionTuple.h" #include <algorithm> #include <cassert> #include <cstdint> @@ -547,6 +548,45 @@ void Module::setRtLibUseGOT() { addModuleFlag(ModFlagBehavior::Max, "RtLibUseGOT", 1); } +void Module::setSDKVersion(const VersionTuple &V) { + SmallVector<unsigned, 3> Entries; + Entries.push_back(V.getMajor()); + if (auto Minor = V.getMinor()) { + Entries.push_back(*Minor); + if (auto Subminor = V.getSubminor()) + Entries.push_back(*Subminor); + // Ignore the 'build' component as it can't be represented in the object + // file. + } + addModuleFlag(ModFlagBehavior::Warning, "SDK Version", + ConstantDataArray::get(Context, Entries)); +} + +VersionTuple Module::getSDKVersion() const { + auto *CM = dyn_cast_or_null<ConstantAsMetadata>(getModuleFlag("SDK Version")); + if (!CM) + return {}; + auto *Arr = dyn_cast_or_null<ConstantDataArray>(CM->getValue()); + if (!Arr) + return {}; + auto getVersionComponent = [&](unsigned Index) -> Optional<unsigned> { + if (Index >= Arr->getNumElements()) + return None; + return (unsigned)Arr->getElementAsInteger(Index); + }; + auto Major = getVersionComponent(0); + if (!Major) + return {}; + VersionTuple Result = VersionTuple(*Major); + if (auto Minor = getVersionComponent(1)) { + Result = VersionTuple(*Major, *Minor); + if (auto Subminor = getVersionComponent(2)) { + Result = VersionTuple(*Major, *Minor, *Subminor); + } + } + return Result; +} + GlobalVariable *llvm::collectUsedGlobalVariables( const Module &M, SmallPtrSetImpl<GlobalValue *> &Set, bool CompilerUsed) { const char *Name = CompilerUsed ? "llvm.compiler.used" : "llvm.used"; diff --git a/llvm/lib/MC/MCAsmStreamer.cpp b/llvm/lib/MC/MCAsmStreamer.cpp index 463e9066616..0daec983dfd 100644 --- a/llvm/lib/MC/MCAsmStreamer.cpp +++ b/llvm/lib/MC/MCAsmStreamer.cpp @@ -147,9 +147,9 @@ public: void EmitLinkerOptions(ArrayRef<std::string> Options) override; void EmitDataRegion(MCDataRegionType Kind) override; void EmitVersionMin(MCVersionMinType Kind, unsigned Major, unsigned Minor, - unsigned Update) override; + unsigned Update, VersionTuple SDKVersion) override; void EmitBuildVersion(unsigned Platform, unsigned Major, unsigned Minor, - unsigned Update) override; + unsigned Update, VersionTuple SDKVersion) override; void EmitThumbFunc(MCSymbol *Func) override; void EmitAssignment(MCSymbol *Symbol, const MCExpr *Value) override; @@ -514,11 +514,26 @@ static const char *getVersionMinDirective(MCVersionMinType Type) { llvm_unreachable("Invalid MC version min type"); } +static void EmitSDKVersionSuffix(raw_ostream &OS, + const VersionTuple &SDKVersion) { + if (SDKVersion.empty()) + return; + OS << '\t' << "sdk_version " << SDKVersion.getMajor(); + if (auto Minor = SDKVersion.getMinor()) { + OS << ", " << *Minor; + if (auto Subminor = SDKVersion.getSubminor()) { + OS << ", " << *Subminor; + } + } +} + void MCAsmStreamer::EmitVersionMin(MCVersionMinType Type, unsigned Major, - unsigned Minor, unsigned Update) { + unsigned Minor, unsigned Update, + VersionTuple SDKVersion) { OS << '\t' << getVersionMinDirective(Type) << ' ' << Major << ", " << Minor; if (Update) OS << ", " << Update; + EmitSDKVersionSuffix(OS, SDKVersion); EmitEOL(); } @@ -534,11 +549,13 @@ static const char *getPlatformName(MachO::PlatformType Type) { } void MCAsmStreamer::EmitBuildVersion(unsigned Platform, unsigned Major, - unsigned Minor, unsigned Update) { + unsigned Minor, unsigned Update, + VersionTuple SDKVersion) { const char *PlatformName = getPlatformName((MachO::PlatformType)Platform); OS << "\t.build_version " << PlatformName << ", " << Major << ", " << Minor; if (Update) OS << ", " << Update; + EmitSDKVersionSuffix(OS, SDKVersion); EmitEOL(); } diff --git a/llvm/lib/MC/MCAssembler.cpp b/llvm/lib/MC/MCAssembler.cpp index 1e23b6d816e..cde6a93a164 100644 --- a/llvm/lib/MC/MCAssembler.cpp +++ b/llvm/lib/MC/MCAssembler.cpp @@ -111,6 +111,7 @@ void MCAssembler::reset() { ELFHeaderEFlags = 0; LOHContainer.reset(); VersionInfo.Major = 0; + VersionInfo.SDKVersion = VersionTuple(); // reset objects owned by us if (getBackendPtr()) diff --git a/llvm/lib/MC/MCMachOStreamer.cpp b/llvm/lib/MC/MCMachOStreamer.cpp index 43e69605787..b30317e7467 100644 --- a/llvm/lib/MC/MCMachOStreamer.cpp +++ b/llvm/lib/MC/MCMachOStreamer.cpp @@ -89,10 +89,10 @@ public: void EmitAssemblerFlag(MCAssemblerFlag Flag) override; void EmitLinkerOptions(ArrayRef<std::string> Options) override; void EmitDataRegion(MCDataRegionType Kind) override; - void EmitVersionMin(MCVersionMinType Kind, unsigned Major, - unsigned Minor, unsigned Update) override; - void EmitBuildVersion(unsigned Platform, unsigned Major, - unsigned Minor, unsigned Update) override; + void EmitVersionMin(MCVersionMinType Kind, unsigned Major, unsigned Minor, + unsigned Update, VersionTuple SDKVersion) override; + void EmitBuildVersion(unsigned Platform, unsigned Major, unsigned Minor, + unsigned Update, VersionTuple SDKVersion) override; void EmitThumbFunc(MCSymbol *Func) override; bool EmitSymbolAttribute(MCSymbol *Symbol, MCSymbolAttr Attribute) override; void EmitSymbolDesc(MCSymbol *Symbol, unsigned DescValue) override; @@ -270,14 +270,16 @@ void MCMachOStreamer::EmitDataRegion(MCDataRegionType Kind) { } void MCMachOStreamer::EmitVersionMin(MCVersionMinType Kind, unsigned Major, - unsigned Minor, unsigned Update) { - getAssembler().setVersionMin(Kind, Major, Minor, Update); + unsigned Minor, unsigned Update, + VersionTuple SDKVersion) { + getAssembler().setVersionMin(Kind, Major, Minor, Update, SDKVersion); } void MCMachOStreamer::EmitBuildVersion(unsigned Platform, unsigned Major, - unsigned Minor, unsigned Update) { + unsigned Minor, unsigned Update, + VersionTuple SDKVersion) { getAssembler().setBuildVersion((MachO::PlatformType)Platform, Major, Minor, - Update); + Update, SDKVersion); } void MCMachOStreamer::EmitThumbFunc(MCSymbol *Symbol) { @@ -507,7 +509,7 @@ MCStreamer *llvm::createMachOStreamer(MCContext &Context, new MCMachOStreamer(Context, std::move(MAB), std::move(OW), std::move(CE), DWARFMustBeAtTheEnd, LabelSections); const Triple &Target = Context.getObjectFileInfo()->getTargetTriple(); - S->EmitVersionForTarget(Target); + S->EmitVersionForTarget(Target, Context.getObjectFileInfo()->getSDKVersion()); if (RelaxAll) S->getAssembler().setRelaxAll(true); return S; diff --git a/llvm/lib/MC/MCParser/DarwinAsmParser.cpp b/llvm/lib/MC/MCParser/DarwinAsmParser.cpp index e6fc1fac81b..07926d6c1c9 100644 --- a/llvm/lib/MC/MCParser/DarwinAsmParser.cpp +++ b/llvm/lib/MC/MCParser/DarwinAsmParser.cpp @@ -459,7 +459,12 @@ public: bool parseBuildVersion(StringRef Directive, SMLoc Loc); bool parseVersionMin(StringRef Directive, SMLoc Loc, MCVersionMinType Type); + bool parseMajorMinorVersionComponent(unsigned *Major, unsigned *Minor, + const char *VersionName); + bool parseOptionalTrailingVersionComponent(unsigned *Component, + const char *ComponentName); bool parseVersion(unsigned *Major, unsigned *Minor, unsigned *Update); + bool parseSDKVersion(VersionTuple &SDKVersion); void checkVersion(StringRef Directive, StringRef Arg, SMLoc Loc, Triple::OSType ExpectedOS); }; @@ -1000,43 +1005,89 @@ bool DarwinAsmParser::parseDirectiveDataRegionEnd(StringRef, SMLoc) { return false; } -/// parseVersion ::= major, minor [, update] -bool DarwinAsmParser::parseVersion(unsigned *Major, unsigned *Minor, - unsigned *Update) { +static bool isSDKVersionToken(const AsmToken &Tok) { + return Tok.is(AsmToken::Identifier) && Tok.getIdentifier() == "sdk_version"; +} + +/// parseMajorMinorVersionComponent ::= major, minor +bool DarwinAsmParser::parseMajorMinorVersionComponent(unsigned *Major, + unsigned *Minor, + const char *VersionName) { // Get the major version number. if (getLexer().isNot(AsmToken::Integer)) - return TokError("invalid OS major version number, integer expected"); + return TokError(Twine("invalid ") + VersionName + + " major version number, integer expected"); int64_t MajorVal = getLexer().getTok().getIntVal(); if (MajorVal > 65535 || MajorVal <= 0) - return TokError("invalid OS major version number"); + return TokError(Twine("invalid ") + VersionName + " major version number"); *Major = (unsigned)MajorVal; Lex(); if (getLexer().isNot(AsmToken::Comma)) - return TokError("OS minor version number required, comma expected"); + return TokError(Twine(VersionName) + + " 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"); + return TokError(Twine("invalid ") + VersionName + + " minor version number, integer expected"); int64_t MinorVal = getLexer().getTok().getIntVal(); if (MinorVal > 255 || MinorVal < 0) - return TokError("invalid OS minor version number"); + return TokError(Twine("invalid ") + VersionName + " minor version number"); *Minor = MinorVal; Lex(); + return false; +} + +/// parseOptionalTrailingVersionComponent ::= , version_number +bool DarwinAsmParser::parseOptionalTrailingVersionComponent( + unsigned *Component, const char *ComponentName) { + assert(getLexer().is(AsmToken::Comma) && "comma expected"); + Lex(); + if (getLexer().isNot(AsmToken::Integer)) + return TokError(Twine("invalid ") + ComponentName + + " version number, integer expected"); + int64_t Val = getLexer().getTok().getIntVal(); + if (Val > 255 || Val < 0) + return TokError(Twine("invalid ") + ComponentName + " version number"); + *Component = Val; + Lex(); + return false; +} + +/// parseVersion ::= parseMajorMinorVersionComponent +/// parseOptionalTrailingVersionComponent +bool DarwinAsmParser::parseVersion(unsigned *Major, unsigned *Minor, + unsigned *Update) { + if (parseMajorMinorVersionComponent(Major, Minor, "OS")) + return true; // Get the update level, if specified *Update = 0; - if (getLexer().is(AsmToken::EndOfStatement)) + if (getLexer().is(AsmToken::EndOfStatement) || + isSDKVersionToken(getLexer().getTok())) return false; if (getLexer().isNot(AsmToken::Comma)) return TokError("invalid OS update specifier, comma expected"); + if (parseOptionalTrailingVersionComponent(Update, "OS update")) + return true; + return false; +} + +bool DarwinAsmParser::parseSDKVersion(VersionTuple &SDKVersion) { + assert(isSDKVersionToken(getLexer().getTok()) && "expected sdk_version"); 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(); + unsigned Major, Minor; + if (parseMajorMinorVersionComponent(&Major, &Minor, "SDK")) + return true; + SDKVersion = VersionTuple(Major, Minor); + + // Get the subminor version, if specified. + if (getLexer().is(AsmToken::Comma)) { + unsigned Subminor; + if (parseOptionalTrailingVersionComponent(&Subminor, "SDK subminor")) + return true; + SDKVersion = VersionTuple(Major, Minor, Subminor); + } return false; } @@ -1066,10 +1117,10 @@ static Triple::OSType getOSTypeFromMCVM(MCVersionMinType Type) { } /// parseVersionMin -/// ::= .ios_version_min parseVersion -/// | .macosx_version_min parseVersion -/// | .tvos_version_min parseVersion -/// | .watchos_version_min parseVersion +/// ::= .ios_version_min parseVersion parseSDKVersion +/// | .macosx_version_min parseVersion parseSDKVersion +/// | .tvos_version_min parseVersion parseSDKVersion +/// | .watchos_version_min parseVersion parseSDKVersion bool DarwinAsmParser::parseVersionMin(StringRef Directive, SMLoc Loc, MCVersionMinType Type) { unsigned Major; @@ -1078,13 +1129,16 @@ bool DarwinAsmParser::parseVersionMin(StringRef Directive, SMLoc Loc, if (parseVersion(&Major, &Minor, &Update)) return true; + VersionTuple SDKVersion; + if (isSDKVersionToken(getLexer().getTok()) && parseSDKVersion(SDKVersion)) + 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); + getStreamer().EmitVersionMin(Type, Major, Minor, Update, SDKVersion); return false; } @@ -1100,7 +1154,7 @@ static Triple::OSType getOSTypeFromPlatform(MachO::PlatformType Type) { } /// parseBuildVersion -/// ::= .build_version (macos|ios|tvos|watchos), parseVersion +/// ::= .build_version (macos|ios|tvos|watchos), parseVersion parseSDKVersion bool DarwinAsmParser::parseBuildVersion(StringRef Directive, SMLoc Loc) { StringRef PlatformName; SMLoc PlatformLoc = getTok().getLoc(); @@ -1126,14 +1180,17 @@ bool DarwinAsmParser::parseBuildVersion(StringRef Directive, SMLoc Loc) { if (parseVersion(&Major, &Minor, &Update)) return true; + VersionTuple SDKVersion; + if (isSDKVersionToken(getLexer().getTok()) && parseSDKVersion(SDKVersion)) + 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); + getStreamer().EmitBuildVersion(Platform, Major, Minor, Update, SDKVersion); return false; } diff --git a/llvm/lib/MC/MCStreamer.cpp b/llvm/lib/MC/MCStreamer.cpp index 3722c0ad3c8..733dd4019dc 100644 --- a/llvm/lib/MC/MCStreamer.cpp +++ b/llvm/lib/MC/MCStreamer.cpp @@ -1045,7 +1045,8 @@ MCSymbol *MCStreamer::endSection(MCSection *Section) { return Sym; } -void MCStreamer::EmitVersionForTarget(const Triple &Target) { +void MCStreamer::EmitVersionForTarget(const Triple &Target, + const VersionTuple &SDKVersion) { if (!Target.isOSBinFormatMachO() || !Target.isOSDarwin()) return; // Do we even know the version? @@ -1071,5 +1072,5 @@ void MCStreamer::EmitVersionForTarget(const Triple &Target) { Target.getiOSVersion(Major, Minor, Update); } if (Major != 0) - EmitVersionMin(VersionType, Major, Minor, Update); + EmitVersionMin(VersionType, Major, Minor, Update, SDKVersion); } diff --git a/llvm/lib/MC/MachObjectWriter.cpp b/llvm/lib/MC/MachObjectWriter.cpp index c2e8dc1ef65..2fa65658ccf 100644 --- a/llvm/lib/MC/MachObjectWriter.cpp +++ b/llvm/lib/MC/MachObjectWriter.cpp @@ -846,18 +846,27 @@ uint64_t MachObjectWriter::writeObject(MCAssembler &Asm, // Write out the deployment target information, if it's available. if (VersionInfo.Major != 0) { - assert(VersionInfo.Update < 256 && "unencodable update target version"); - assert(VersionInfo.Minor < 256 && "unencodable minor target version"); - assert(VersionInfo.Major < 65536 && "unencodable major target version"); - uint32_t EncodedVersion = VersionInfo.Update | (VersionInfo.Minor << 8) | - (VersionInfo.Major << 16); + auto EncodeVersion = [](VersionTuple V) -> uint32_t { + assert(!V.empty() && "empty version"); + unsigned Update = V.getSubminor() ? *V.getSubminor() : 0; + unsigned Minor = V.getMinor() ? *V.getMinor() : 0; + assert(Update < 256 && "unencodable update target version"); + assert(Minor < 256 && "unencodable minor target version"); + assert(V.getMajor() < 65536 && "unencodable major target version"); + return Update | (Minor << 8) | (V.getMajor() << 16); + }; + uint32_t EncodedVersion = EncodeVersion( + VersionTuple(VersionInfo.Major, VersionInfo.Minor, VersionInfo.Update)); + uint32_t SDKVersion = !VersionInfo.SDKVersion.empty() + ? EncodeVersion(VersionInfo.SDKVersion) + : 0; if (VersionInfo.EmitBuildVersion) { // FIXME: Currently empty tools. Add clang version in the future. W.write<uint32_t>(MachO::LC_BUILD_VERSION); W.write<uint32_t>(sizeof(MachO::build_version_command)); W.write<uint32_t>(VersionInfo.TypeOrPlatform.Platform); W.write<uint32_t>(EncodedVersion); - W.write<uint32_t>(0); // SDK version. + W.write<uint32_t>(SDKVersion); W.write<uint32_t>(0); // Empty tools list. } else { MachO::LoadCommandType LCType @@ -865,7 +874,7 @@ uint64_t MachObjectWriter::writeObject(MCAssembler &Asm, W.write<uint32_t>(LCType); W.write<uint32_t>(sizeof(MachO::version_min_command)); W.write<uint32_t>(EncodedVersion); - W.write<uint32_t>(0); // reserved. + W.write<uint32_t>(SDKVersion); } } diff --git a/llvm/lib/Object/ModuleSymbolTable.cpp b/llvm/lib/Object/ModuleSymbolTable.cpp index b353ef3c835..33ce7d8109f 100644 --- a/llvm/lib/Object/ModuleSymbolTable.cpp +++ b/llvm/lib/Object/ModuleSymbolTable.cpp @@ -100,6 +100,7 @@ initializeRecordStreamer(const Module &M, MCObjectFileInfo MOFI; MCContext MCCtx(MAI.get(), MRI.get(), &MOFI); MOFI.InitMCObjectFileInfo(TT, /*PIC*/ false, MCCtx); + MOFI.setSDKVersion(M.getSDKVersion()); RecordStreamer Streamer(MCCtx, M); T->createNullTargetStreamer(Streamer); |