Index: include/llvm/IR/Module.h =================================================================== --- include/llvm/IR/Module.h +++ include/llvm/IR/Module.h @@ -49,6 +49,7 @@ class RandomNumberGenerator; template class SmallPtrSetImpl; class StructType; +class VersionTuple; /// A Module instance is used to store all the information related to an /// LLVM module. Modules are the top level container of all other LLVM @@ -868,6 +869,17 @@ /// Set that PLT should be avoid for RTLib calls. void setRtLibUseGOT(); + /// @name Utility functions for querying and setting the build SDK version + /// @{ + + /// Attach a build SDK version metadata to this module. + void setSDKVersion(const VersionTuple &V); + + /// Get the build SDK version metadata. + /// + /// An empty version is returned if no such metadata is attached. + VersionTuple getSDKVersion() const; + /// @} /// Take ownership of the given memory buffer. void setOwnedMemoryBuffer(std::unique_ptr MB); Index: include/llvm/MC/MCAssembler.h =================================================================== --- include/llvm/MC/MCAssembler.h +++ include/llvm/MC/MCAssembler.h @@ -23,6 +23,7 @@ #include "llvm/MC/MCFragment.h" #include "llvm/MC/MCLinkerOptimizationHint.h" #include "llvm/MC/MCSymbol.h" +#include "llvm/Support/VersionTuple.h" #include #include #include @@ -94,6 +95,8 @@ unsigned Major; unsigned Minor; unsigned Update; + /// An optional version of the SDK that was used to build the source. + VersionTuple SDKVersion; }; private: @@ -255,20 +258,24 @@ /// MachO deployment target version information. const VersionInfoType &getVersionInfo() const { return VersionInfo; } void setVersionMin(MCVersionMinType Type, unsigned Major, unsigned Minor, - unsigned Update) { + unsigned Update, + VersionTuple SDKVersion = VersionTuple()) { VersionInfo.EmitBuildVersion = false; VersionInfo.TypeOrPlatform.Type = Type; VersionInfo.Major = Major; VersionInfo.Minor = Minor; VersionInfo.Update = Update; + VersionInfo.SDKVersion = SDKVersion; } void setBuildVersion(MachO::PlatformType Platform, unsigned Major, - unsigned Minor, unsigned Update) { + unsigned Minor, unsigned Update, + VersionTuple SDKVersion = VersionTuple()) { VersionInfo.EmitBuildVersion = true; VersionInfo.TypeOrPlatform.Platform = Platform; VersionInfo.Major = Major; VersionInfo.Minor = Minor; VersionInfo.Update = Update; + VersionInfo.SDKVersion = SDKVersion; } /// Reuse an assembler instance Index: include/llvm/MC/MCObjectFileInfo.h =================================================================== --- include/llvm/MC/MCObjectFileInfo.h +++ include/llvm/MC/MCObjectFileInfo.h @@ -18,6 +18,7 @@ #include "llvm/ADT/Triple.h" #include "llvm/MC/MCSymbol.h" #include "llvm/Support/CodeGen.h" +#include "llvm/Support/VersionTuple.h" namespace llvm { class MCContext; @@ -390,6 +391,7 @@ bool PositionIndependent; MCContext *Ctx; Triple TT; + VersionTuple SDKVersion; void initMachOMCObjectFileInfo(const Triple &T); void initELFMCObjectFileInfo(const Triple &T, bool Large); @@ -399,6 +401,12 @@ public: const Triple &getTargetTriple() const { return TT; } + + void setSDKVersion(const VersionTuple &TheSDKVersion) { + SDKVersion = TheSDKVersion; + } + + const VersionTuple &getSDKVersion() const { return SDKVersion; } }; } // end namespace llvm Index: include/llvm/MC/MCStreamer.h =================================================================== --- include/llvm/MC/MCStreamer.h +++ include/llvm/MC/MCStreamer.h @@ -28,6 +28,7 @@ #include "llvm/Support/MD5.h" #include "llvm/Support/SMLoc.h" #include "llvm/Support/TargetParser.h" +#include "llvm/Support/VersionTuple.h" #include #include #include @@ -452,14 +453,17 @@ /// Specify the Mach-O minimum deployment target version. virtual void EmitVersionMin(MCVersionMinType Type, unsigned Major, - unsigned Minor, unsigned Update) {} + unsigned Minor, unsigned Update, + VersionTuple SDKVersion) {} /// Emit/Specify Mach-O build version command. /// \p Platform should be one of MachO::PlatformType. virtual void EmitBuildVersion(unsigned Platform, unsigned Major, - unsigned Minor, unsigned Update) {} + unsigned Minor, unsigned Update, + VersionTuple SDKVersion) {} - void EmitVersionForTarget(const Triple &Target); + void EmitVersionForTarget(const Triple &Target, + const VersionTuple &SDKVersion); /// Note in the output that the specified \p Func is a Thumb mode /// function (ARM target only). Index: lib/CodeGen/AsmPrinter/AsmPrinter.cpp =================================================================== --- lib/CodeGen/AsmPrinter/AsmPrinter.cpp +++ lib/CodeGen/AsmPrinter/AsmPrinter.cpp @@ -263,7 +263,7 @@ // 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); Index: lib/IR/Module.cpp =================================================================== --- lib/IR/Module.cpp +++ 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 #include #include @@ -547,6 +548,45 @@ addModuleFlag(ModFlagBehavior::Max, "RtLibUseGOT", 1); } +void Module::setSDKVersion(const VersionTuple &V) { + SmallVector 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(getModuleFlag("SDK Version")); + if (!CM) + return {}; + auto *Arr = dyn_cast_or_null(CM->getValue()); + if (!Arr) + return {}; + auto getVersionComponent = [&](unsigned Index) -> Optional { + 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 &Set, bool CompilerUsed) { const char *Name = CompilerUsed ? "llvm.compiler.used" : "llvm.used"; Index: lib/MC/MCAsmStreamer.cpp =================================================================== --- lib/MC/MCAsmStreamer.cpp +++ lib/MC/MCAsmStreamer.cpp @@ -147,9 +147,9 @@ void EmitLinkerOptions(ArrayRef 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 @@ 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 @@ } 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(); } Index: lib/MC/MCAssembler.cpp =================================================================== --- lib/MC/MCAssembler.cpp +++ lib/MC/MCAssembler.cpp @@ -111,6 +111,7 @@ ELFHeaderEFlags = 0; LOHContainer.reset(); VersionInfo.Major = 0; + VersionInfo.SDKVersion = VersionTuple(); // reset objects owned by us if (getBackendPtr()) Index: lib/MC/MCMachOStreamer.cpp =================================================================== --- lib/MC/MCMachOStreamer.cpp +++ lib/MC/MCMachOStreamer.cpp @@ -89,10 +89,10 @@ void EmitAssemblerFlag(MCAssemblerFlag Flag) override; void EmitLinkerOptions(ArrayRef 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::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 @@ 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; Index: lib/MC/MCParser/DarwinAsmParser.cpp =================================================================== --- lib/MC/MCParser/DarwinAsmParser.cpp +++ lib/MC/MCParser/DarwinAsmParser.cpp @@ -459,7 +459,12 @@ 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 @@ 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 @@ } /// 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 @@ 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 @@ } /// 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 @@ 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; } Index: lib/MC/MCStreamer.cpp =================================================================== --- lib/MC/MCStreamer.cpp +++ lib/MC/MCStreamer.cpp @@ -1045,7 +1045,8 @@ 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 @@ Target.getiOSVersion(Major, Minor, Update); } if (Major != 0) - EmitVersionMin(VersionType, Major, Minor, Update); + EmitVersionMin(VersionType, Major, Minor, Update, SDKVersion); } Index: lib/MC/MachObjectWriter.cpp =================================================================== --- lib/MC/MachObjectWriter.cpp +++ lib/MC/MachObjectWriter.cpp @@ -846,18 +846,27 @@ // 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(MachO::LC_BUILD_VERSION); W.write(sizeof(MachO::build_version_command)); W.write(VersionInfo.TypeOrPlatform.Platform); W.write(EncodedVersion); - W.write(0); // SDK version. + W.write(SDKVersion); W.write(0); // Empty tools list. } else { MachO::LoadCommandType LCType @@ -865,7 +874,7 @@ W.write(LCType); W.write(sizeof(MachO::version_min_command)); W.write(EncodedVersion); - W.write(0); // reserved. + W.write(SDKVersion); } } Index: lib/Object/ModuleSymbolTable.cpp =================================================================== --- lib/Object/ModuleSymbolTable.cpp +++ lib/Object/ModuleSymbolTable.cpp @@ -100,6 +100,7 @@ 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); Index: test/MC/MachO/ARM/build-version-sdk-version-errors.c =================================================================== --- /dev/null +++ test/MC/MachO/ARM/build-version-sdk-version-errors.c @@ -0,0 +1,19 @@ +// RUN: not llvm-mc -triple x86_64-apple-macos %s 2>&1 | FileCheck %s + +.build_version macos,3,4,5 sdk_version +// CHECK: invalid SDK major version number, integer expected + +.build_version macos,3,4,5 sdk_version 10 +// CHECK: SDK minor version number required, comma expected + +.build_version macos,3,4,5 sdk_version 10, +// CHECK: invalid SDK minor version number, integer expected + +.build_version macos,3,4,5 sdk_version 10,1, +// CHECK: invalid SDK subminor version number, integer expected + +.build_version macos,3,4,5 sdk_version 10,10000 +// CHECK: invalid SDK minor version number + +.build_version macos,3,4,5 sdk_version 10,255,10000 +// CHECK: invalid SDK subminor version number Index: test/MC/MachO/ARM/build-version-sdk-version.s =================================================================== --- /dev/null +++ test/MC/MachO/ARM/build-version-sdk-version.s @@ -0,0 +1,13 @@ +// RUN: llvm-mc -triple x86_64-apple-macos %s | FileCheck %s + +.build_version macos,3,4,5 sdk_version 10,14 +// CHECK: .build_version macos, 3, 4, 5 sdk_version 10, 14 + +.build_version ios,6,7 sdk_version 6,1,0 +// CHECK: .build_version ios, 6, 7 sdk_version 6, 1, 0 + +.build_version tvos,8,9 sdk_version 9,0,10 +// CHECK: .build_version tvos, 8, 9 sdk_version 9, 0, 10 + +.build_version watchos,10,11 sdk_version 10,11 +// CHECK: .build_version watchos, 10, 11 sdk_version 10, 11 Index: test/MC/MachO/build-version-with-sdk-version.s =================================================================== --- /dev/null +++ test/MC/MachO/build-version-with-sdk-version.s @@ -0,0 +1,13 @@ +// RUN: llvm-mc -triple x86_64-apple-macos %s -filetype=obj -o - | llvm-readobj --macho-version-min | FileCheck %s + +// Test the formation of the sdk_version component of the version load +// command in the MachO. +.build_version macos, 10,13,2 sdk_version 10,14,1 + +// CHECK: MinVersion { +// CHECK: Cmd: LC_BUILD_VERSION +// CHECK: Size: 24 +// CHECK: Platform: macos +// CHECK: Version: 10.13.2 +// CHECK: SDK: 10.14.1 +// CHECK: } Index: test/MC/MachO/darwin-sdk-version.ll =================================================================== --- /dev/null +++ test/MC/MachO/darwin-sdk-version.ll @@ -0,0 +1,18 @@ +; RUN: llc %s -filetype=obj -o - | llvm-objdump -macho -private-headers - | FileCheck %s +; RUN: llc %s -filetype=asm -o - | FileCheck --check-prefix=ASM %s + +target triple = "x86_64-apple-macos10.14"; +!llvm.module.flags = !{!0}; +!0 = !{i32 2, !"SDK Version", [3 x i32] [ i32 10, i32 14, i32 2 ] }; + +define void @foo() { +entry: + ret void +} + +; CHECK: cmd LC_VERSION_MIN_MACOSX +; CHECK-NEXT: cmdsize 16 +; CHECK-NEXT: version 10.14 +; CHECK-NEXT: sdk 10.14.2 + +; ASM: .macosx_version_min 10, 14 sdk_version 10, 14, 2 Index: test/MC/MachO/osx-version-min-load-command-with-sdk-errors.s =================================================================== --- /dev/null +++ test/MC/MachO/osx-version-min-load-command-with-sdk-errors.s @@ -0,0 +1,10 @@ +// RUN: not llvm-mc -triple x86_64-apple-macos %s -o - 2>&1 | FileCheck %s + +.macosx_version_min 10,13,2 sdk_version 10 +// CHECK: SDK minor version number required, comma expected + +.macosx_version_min 10,13,2 sdk_version 10, +// CHECK: invalid SDK minor version number, integer expected + +.macosx_version_min 10,13,2 sdk_version 10 +// CHECK: SDK minor version number required, comma expected Index: test/MC/MachO/osx-version-min-load-command-with-sdk.s =================================================================== --- /dev/null +++ test/MC/MachO/osx-version-min-load-command-with-sdk.s @@ -0,0 +1,12 @@ +// RUN: llvm-mc -triple x86_64-apple-macos %s -filetype=obj -o - | llvm-readobj --macho-version-min | FileCheck %s + +// Test the formation of the sdk_version component of the version load +// command in the MachO. +.macosx_version_min 10,13,2 sdk_version 10,14 + +// CHECK: MinVersion { +// CHECK: Cmd: LC_VERSION_MIN_MACOSX +// CHECK: Size: 16 +// CHECK: Version: 10.13.2 +// CHECK: SDK: 10.14 +// CHECK: }