class RandomNumberGenerator;
template <class PtrType> 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
/// 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<MemoryBuffer> MB);
#include "llvm/MC/MCFragment.h"
#include "llvm/MC/MCLinkerOptimizationHint.h"
#include "llvm/MC/MCSymbol.h"
+#include "llvm/Support/VersionTuple.h"
#include <cassert>
#include <cstddef>
#include <cstdint>
unsigned Major;
unsigned Minor;
unsigned Update;
+ /// An optional version of the SDK that was used to build the source.
+ VersionTuple SDKVersion;
};
private:
/// 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
#include "llvm/ADT/Triple.h"
#include "llvm/MC/MCSymbol.h"
#include "llvm/Support/CodeGen.h"
+#include "llvm/Support/VersionTuple.h"
namespace llvm {
class MCContext;
bool PositionIndependent;
MCContext *Ctx;
Triple TT;
+ VersionTuple SDKVersion;
void initMachOMCObjectFileInfo(const Triple &T);
void initELFMCObjectFileInfo(const Triple &T, bool Large);
public:
const Triple &getTargetTriple() const { return TT; }
+
+ void setSDKVersion(const VersionTuple &TheSDKVersion) {
+ SDKVersion = TheSDKVersion;
+ }
+
+ const VersionTuple &getSDKVersion() const { return SDKVersion; }
};
} // end namespace llvm
#include "llvm/Support/MD5.h"
#include "llvm/Support/SMLoc.h"
#include "llvm/Support/TargetParser.h"
+#include "llvm/Support/VersionTuple.h"
#include <cassert>
#include <cstdint>
#include <memory>
/// 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).
// 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);
#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>
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";
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;
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();
}
}
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();
}
ELFHeaderEFlags = 0;
LOHContainer.reset();
VersionInfo.Major = 0;
+ VersionInfo.SDKVersion = VersionTuple();
// reset objects owned by us
if (getBackendPtr())
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;
}
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) {
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;
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);
};
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;
}
}
/// 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;
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;
}
}
/// 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();
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;
}
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?
Target.getiOSVersion(Major, Minor, Update);
}
if (Major != 0)
- EmitVersionMin(VersionType, Major, Minor, Update);
+ EmitVersionMin(VersionType, Major, Minor, Update, SDKVersion);
}
// 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
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);
}
}
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);
--- /dev/null
+// 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
--- /dev/null
+// 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
--- /dev/null
+// 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: }
--- /dev/null
+; 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
--- /dev/null
+// 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
--- /dev/null
+// 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: }