[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


git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@349119 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
Alex Lorenz 2018-12-14 01:14:10 +00:00
parent ee2b007283
commit 6592c09789
19 changed files with 297 additions and 53 deletions

View File

@ -49,6 +49,7 @@ class MemoryBuffer;
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
@ -868,6 +869,17 @@ public:
/// 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);

View File

@ -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 <cassert>
#include <cstddef>
#include <cstdint>
@ -94,6 +95,8 @@ public:
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 @@ public:
/// 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

View File

@ -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 @@ private:
bool PositionIndependent;
MCContext *Ctx;
Triple TT;
VersionTuple SDKVersion;
void initMachOMCObjectFileInfo(const Triple &T);
void initELFMCObjectFileInfo(const Triple &T, bool Large);
@ -399,6 +401,12 @@ private:
public:
const Triple &getTargetTriple() const { return TT; }
void setSDKVersion(const VersionTuple &TheSDKVersion) {
SDKVersion = TheSDKVersion;
}
const VersionTuple &getSDKVersion() const { return SDKVersion; }
};
} // end namespace llvm

View File

@ -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 <cassert>
#include <cstdint>
#include <memory>
@ -452,14 +453,17 @@ public:
/// 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).

View File

@ -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);

View File

@ -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";

View File

@ -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();
}

View File

@ -111,6 +111,7 @@ void MCAssembler::reset() {
ELFHeaderEFlags = 0;
LOHContainer.reset();
VersionInfo.Major = 0;
VersionInfo.SDKVersion = VersionTuple();
// reset objects owned by us
if (getBackendPtr())

View File

@ -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;

View File

@ -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;
}

View File

@ -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);
}

View File

@ -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);
}
}

View File

@ -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);

View File

@ -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

View File

@ -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

View File

@ -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: }

View File

@ -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

View File

@ -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

View File

@ -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: }