diff options
-rw-r--r-- | llvm/include/llvm/BinaryFormat/MachO.h | 2 | ||||
-rw-r--r-- | llvm/include/llvm/MC/MCAssembler.h | 34 | ||||
-rw-r--r-- | llvm/include/llvm/MC/MCStreamer.h | 11 | ||||
-rw-r--r-- | llvm/lib/MC/MCAsmStreamer.cpp | 40 | ||||
-rw-r--r-- | llvm/lib/MC/MCAssembler.cpp | 4 | ||||
-rw-r--r-- | llvm/lib/MC/MCMachOStreamer.cpp | 10 | ||||
-rw-r--r-- | llvm/lib/MC/MCParser/DarwinAsmParser.cpp | 194 | ||||
-rw-r--r-- | llvm/lib/MC/MachObjectWriter.cpp | 52 | ||||
-rw-r--r-- | llvm/test/MC/MachO/ARM/build-version-diagnostics.s | 56 | ||||
-rw-r--r-- | llvm/test/MC/MachO/ARM/build-version-encode.s | 10 | ||||
-rw-r--r-- | llvm/test/MC/MachO/ARM/build-version.s | 19 | ||||
-rw-r--r-- | llvm/test/MC/MachO/ARM/version-min-diagnostics.s | 8 | ||||
-rw-r--r-- | llvm/test/MC/MachO/ARM/version-min-diagnostics2.s | 38 |
13 files changed, 360 insertions, 118 deletions
diff --git a/llvm/include/llvm/BinaryFormat/MachO.h b/llvm/include/llvm/BinaryFormat/MachO.h index 7293ed78dfd..060fbe162ad 100644 --- a/llvm/include/llvm/BinaryFormat/MachO.h +++ b/llvm/include/llvm/BinaryFormat/MachO.h @@ -481,7 +481,7 @@ enum RelocationInfoType { enum { VM_PROT_READ = 0x1, VM_PROT_WRITE = 0x2, VM_PROT_EXECUTE = 0x4 }; // Values for platform field in build_version_command. -enum { +enum PlatformType { PLATFORM_MACOS = 1, PLATFORM_IOS = 2, PLATFORM_TVOS = 3, diff --git a/llvm/include/llvm/MC/MCAssembler.h b/llvm/include/llvm/MC/MCAssembler.h index 1ce6b09355d..034605557d4 100644 --- a/llvm/include/llvm/MC/MCAssembler.h +++ b/llvm/include/llvm/MC/MCAssembler.h @@ -16,6 +16,7 @@ #include "llvm/ADT/StringRef.h" #include "llvm/ADT/iterator.h" #include "llvm/ADT/iterator_range.h" +#include "llvm/BinaryFormat/MachO.h" #include "llvm/MC/MCDirectives.h" #include "llvm/MC/MCDwarf.h" #include "llvm/MC/MCFixup.h" @@ -84,8 +85,12 @@ public: /// MachO specific deployment target version info. // A Major version of 0 indicates that no version information was supplied // and so the corresponding load command should not be emitted. - using VersionMinInfoType = struct { - MCVersionMinType Kind; + using VersionInfoType = struct { + bool EmitBuildVersion; + union { + MCVersionMinType Type; ///< Used when EmitBuildVersion==false. + MachO::PlatformType Platform; ///< Used when EmitBuildVersion==true. + } TypeOrPlatform; unsigned Major; unsigned Minor; unsigned Update; @@ -145,7 +150,7 @@ private: /// the Streamer and the .o writer MCLOHContainer LOHContainer; - VersionMinInfoType VersionMinInfo; + VersionInfoType VersionInfo; /// Evaluate a fixup to a relocatable expression and the value which should be /// placed into the fixup. @@ -243,13 +248,22 @@ public: void setELFHeaderEFlags(unsigned Flags) { ELFHeaderEFlags = Flags; } /// MachO deployment target version information. - const VersionMinInfoType &getVersionMinInfo() const { return VersionMinInfo; } - void setVersionMinInfo(MCVersionMinType Kind, unsigned Major, unsigned Minor, - unsigned Update) { - VersionMinInfo.Kind = Kind; - VersionMinInfo.Major = Major; - VersionMinInfo.Minor = Minor; - VersionMinInfo.Update = Update; + const VersionInfoType &getVersionInfo() const { return VersionInfo; } + void setVersionMin(MCVersionMinType Type, unsigned Major, unsigned Minor, + unsigned Update) { + VersionInfo.EmitBuildVersion = false; + VersionInfo.TypeOrPlatform.Type = Type; + VersionInfo.Major = Major; + VersionInfo.Minor = Minor; + VersionInfo.Update = Update; + } + void setBuildVersion(MachO::PlatformType Platform, unsigned Major, + unsigned Minor, unsigned Update) { + VersionInfo.EmitBuildVersion = true; + VersionInfo.TypeOrPlatform.Platform = Platform; + VersionInfo.Major = Major; + VersionInfo.Minor = Minor; + VersionInfo.Update = Update; } /// Reuse an assembler instance diff --git a/llvm/include/llvm/MC/MCStreamer.h b/llvm/include/llvm/MC/MCStreamer.h index 58003d7d596..e4a969e9449 100644 --- a/llvm/include/llvm/MC/MCStreamer.h +++ b/llvm/include/llvm/MC/MCStreamer.h @@ -421,9 +421,14 @@ public: /// \brief Note in the output the specified region \p Kind. virtual void EmitDataRegion(MCDataRegionType Kind) {} - /// \brief Specify the MachO minimum deployment target version. - virtual void EmitVersionMin(MCVersionMinType, unsigned Major, unsigned Minor, - unsigned Update) {} + /// \brief Specify the Mach-O minimum deployment target version. + virtual void EmitVersionMin(MCVersionMinType Type, unsigned Major, + unsigned Minor, unsigned Update) {} + + /// 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) {} /// \brief Note in the output that the specified \p Func is a Thumb mode /// function (ARM target only). diff --git a/llvm/lib/MC/MCAsmStreamer.cpp b/llvm/lib/MC/MCAsmStreamer.cpp index 8f3dccbe441..3357553cf19 100644 --- a/llvm/lib/MC/MCAsmStreamer.cpp +++ b/llvm/lib/MC/MCAsmStreamer.cpp @@ -137,6 +137,8 @@ public: 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 EmitThumbFunc(MCSymbol *Func) override; void EmitAssignment(MCSymbol *Symbol, const MCExpr *Value) override; @@ -471,15 +473,39 @@ void MCAsmStreamer::EmitDataRegion(MCDataRegionType Kind) { EmitEOL(); } -void MCAsmStreamer::EmitVersionMin(MCVersionMinType Kind, unsigned Major, +static const char *getVersionMinDirective(MCVersionMinType Type) { + switch (Type) { + case MCVM_WatchOSVersionMin: return ".watchos_version_min"; + case MCVM_TvOSVersionMin: return ".tvos_version_min"; + case MCVM_IOSVersionMin: return ".ios_version_min"; + case MCVM_OSXVersionMin: return ".macosx_version_min"; + } + llvm_unreachable("Invalid MC version min type"); +} + +void MCAsmStreamer::EmitVersionMin(MCVersionMinType Type, unsigned Major, unsigned Minor, unsigned Update) { - switch (Kind) { - case MCVM_WatchOSVersionMin: OS << "\t.watchos_version_min"; break; - case MCVM_TvOSVersionMin: OS << "\t.tvos_version_min"; break; - case MCVM_IOSVersionMin: OS << "\t.ios_version_min"; break; - case MCVM_OSXVersionMin: OS << "\t.macosx_version_min"; break; + OS << '\t' << getVersionMinDirective(Type) << ' ' << Major << ", " << Minor; + if (Update) + OS << ", " << Update; + EmitEOL(); +} + +static const char *getPlatformName(MachO::PlatformType Type) { + switch (Type) { + case MachO::PLATFORM_MACOS: return "macos"; + case MachO::PLATFORM_IOS: return "ios"; + case MachO::PLATFORM_TVOS: return "tvos"; + case MachO::PLATFORM_WATCHOS: return "watchos"; + case MachO::PLATFORM_BRIDGEOS: return "bridgeos"; } - OS << " " << Major << ", " << Minor; + llvm_unreachable("Invalid Mach-O platform type"); +} + +void MCAsmStreamer::EmitBuildVersion(unsigned Platform, unsigned Major, + unsigned Minor, unsigned Update) { + const char *PlatformName = getPlatformName((MachO::PlatformType)Platform); + OS << "\t.build_version " << PlatformName << ", " << Major << ", " << Minor; if (Update) OS << ", " << Update; EmitEOL(); diff --git a/llvm/lib/MC/MCAssembler.cpp b/llvm/lib/MC/MCAssembler.cpp index 9a23e614f3a..01d165944be 100644 --- a/llvm/lib/MC/MCAssembler.cpp +++ b/llvm/lib/MC/MCAssembler.cpp @@ -88,7 +88,7 @@ MCAssembler::MCAssembler(MCContext &Context, MCAsmBackend &Backend, : Context(Context), Backend(Backend), Emitter(Emitter), Writer(Writer), BundleAlignSize(0), RelaxAll(false), SubsectionsViaSymbols(false), IncrementalLinkerCompatible(false), ELFHeaderEFlags(0) { - VersionMinInfo.Major = 0; // Major version == 0 for "none specified" + VersionInfo.Major = 0; // Major version == 0 for "none specified" } MCAssembler::~MCAssembler() = default; @@ -107,7 +107,7 @@ void MCAssembler::reset() { IncrementalLinkerCompatible = false; ELFHeaderEFlags = 0; LOHContainer.reset(); - VersionMinInfo.Major = 0; + VersionInfo.Major = 0; // reset objects owned by us getBackend().reset(); diff --git a/llvm/lib/MC/MCMachOStreamer.cpp b/llvm/lib/MC/MCMachOStreamer.cpp index a5c1b13df7c..6e1dca82033 100644 --- a/llvm/lib/MC/MCMachOStreamer.cpp +++ b/llvm/lib/MC/MCMachOStreamer.cpp @@ -88,6 +88,8 @@ public: 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 EmitThumbFunc(MCSymbol *Func) override; bool EmitSymbolAttribute(MCSymbol *Symbol, MCSymbolAttr Attribute) override; void EmitSymbolDesc(MCSymbol *Symbol, unsigned DescValue) override; @@ -265,7 +267,13 @@ void MCMachOStreamer::EmitDataRegion(MCDataRegionType Kind) { void MCMachOStreamer::EmitVersionMin(MCVersionMinType Kind, unsigned Major, unsigned Minor, unsigned Update) { - getAssembler().setVersionMinInfo(Kind, Major, Minor, Update); + getAssembler().setVersionMin(Kind, Major, Minor, Update); +} + +void MCMachOStreamer::EmitBuildVersion(unsigned Platform, unsigned Major, + unsigned Minor, unsigned Update) { + getAssembler().setBuildVersion((MachO::PlatformType)Platform, Major, Minor, + Update); } void MCMachOStreamer::EmitThumbFunc(MCSymbol *Symbol) { 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() { diff --git a/llvm/lib/MC/MachObjectWriter.cpp b/llvm/lib/MC/MachObjectWriter.cpp index 7dbb84e166f..c7eaa76ace3 100644 --- a/llvm/lib/MC/MachObjectWriter.cpp +++ b/llvm/lib/MC/MachObjectWriter.cpp @@ -721,6 +721,16 @@ bool MachObjectWriter::isSymbolRefDifferenceFullyResolvedImpl( return false; } +static MachO::LoadCommandType getLCFromMCVM(MCVersionMinType Type) { + switch (Type) { + case MCVM_OSXVersionMin: return MachO::LC_VERSION_MIN_MACOSX; + case MCVM_IOSVersionMin: return MachO::LC_VERSION_MIN_IPHONEOS; + case MCVM_TvOSVersionMin: return MachO::LC_VERSION_MIN_TVOS; + case MCVM_WatchOSVersionMin: return MachO::LC_VERSION_MIN_WATCHOS; + } + llvm_unreachable("Invalid mc version min type"); +} + void MachObjectWriter::writeObject(MCAssembler &Asm, const MCAsmLayout &Layout) { // Compute symbol table information and bind symbol indices. @@ -728,8 +738,8 @@ void MachObjectWriter::writeObject(MCAssembler &Asm, UndefinedSymbolData); unsigned NumSections = Asm.size(); - const MCAssembler::VersionMinInfoType &VersionInfo = - Layout.getAssembler().getVersionMinInfo(); + const MCAssembler::VersionInfoType &VersionInfo = + Layout.getAssembler().getVersionInfo(); // The section data starts after the header, the segment load command (and // section headers) and the symbol table. @@ -741,7 +751,10 @@ void MachObjectWriter::writeObject(MCAssembler &Asm, // Add the deployment target version info load command size, if used. if (VersionInfo.Major != 0) { ++NumLoadCommands; - LoadCommandsSize += sizeof(MachO::version_min_command); + if (VersionInfo.EmitBuildVersion) + LoadCommandsSize += sizeof(MachO::build_version_command); + else + LoadCommandsSize += sizeof(MachO::version_min_command); } // Add the data-in-code load command size, if used. @@ -832,25 +845,22 @@ void MachObjectWriter::writeObject(MCAssembler &Asm, assert(VersionInfo.Major < 65536 && "unencodable major target version"); uint32_t EncodedVersion = VersionInfo.Update | (VersionInfo.Minor << 8) | (VersionInfo.Major << 16); - MachO::LoadCommandType LCType; - switch (VersionInfo.Kind) { - case MCVM_OSXVersionMin: - LCType = MachO::LC_VERSION_MIN_MACOSX; - break; - case MCVM_IOSVersionMin: - LCType = MachO::LC_VERSION_MIN_IPHONEOS; - break; - case MCVM_TvOSVersionMin: - LCType = MachO::LC_VERSION_MIN_TVOS; - break; - case MCVM_WatchOSVersionMin: - LCType = MachO::LC_VERSION_MIN_WATCHOS; - break; + if (VersionInfo.EmitBuildVersion) { + // FIXME: Currently empty tools. Add clang version in the future. + write32(MachO::LC_BUILD_VERSION); + write32(sizeof(MachO::build_version_command)); + write32(VersionInfo.TypeOrPlatform.Platform); + write32(EncodedVersion); + write32(0); // SDK version. + write32(0); // Empty tools list. + } else { + MachO::LoadCommandType LCType + = getLCFromMCVM(VersionInfo.TypeOrPlatform.Type); + write32(LCType); + write32(sizeof(MachO::version_min_command)); + write32(EncodedVersion); + write32(0); // reserved. } - write32(LCType); - write32(sizeof(MachO::version_min_command)); - write32(EncodedVersion); - write32(0); // reserved. } // Write the data-in-code load command, if used. diff --git a/llvm/test/MC/MachO/ARM/build-version-diagnostics.s b/llvm/test/MC/MachO/ARM/build-version-diagnostics.s new file mode 100644 index 00000000000..31aa87add3a --- /dev/null +++ b/llvm/test/MC/MachO/ARM/build-version-diagnostics.s @@ -0,0 +1,56 @@ +// RUN: not llvm-mc -triple x86_64-apple-tvos %s 2>&1 | FileCheck %s + +.build_version tvos,65535,0,255 +// CHECK-NOT: build-version-diagnostics.s:[[@LINE-1]] + +.build_version macos,1,2,3 +// CHECK: build-version-diagnostics.s:[[@LINE-1]]:1: warning: .build_version macos used while targeting tvos +// CHECK: build-version-diagnostics.s:[[@LINE-2]]:1: warning: overriding previous version directive + +.build_version 1,2,3 +// CHECK: build-version-diagnostics.s:[[@LINE-1]]:16: error: platform name expected + +.build_version macos 1,2 +// CHECK: build-version-diagnostics.s:[[@LINE-1]]:22: error: version number required, comma expected + +.build_version noos,1,2 +// CHECK: build-version-diagnostics.s:[[@LINE-1]]:16: error: unknown platform name + +.build_version macos,a +// CHECK: build-version-diagnostics.s:[[@LINE-1]]:22: error: invalid OS major version number, integer expected + +.build_version macos,0,1 +// CHECK: build-version-diagnostics.s:[[@LINE-1]]:22: error: invalid OS major version number + +.build_version macos,-1,1 +// CHECK: build-version-diagnostics.s:[[@LINE-1]]:22: error: invalid OS major version number + +.build_version macos,65536,1 +// CHECK: build-version-diagnostics.s:[[@LINE-1]]:22: error: invalid OS major version number + +.build_version ios,10 0 +// CHECK: build-version-diagnostics.s:[[@LINE-1]]:23: error: OS minor version number required, comma expected + +.build_version ios,10, +// CHECK: build-version-diagnostics.s:[[@LINE-1]]:23: error: invalid OS minor version number, integer expected + +.build_version ios,10,-1 +// CHECK: build-version-diagnostics.s:[[@LINE-1]]:23: error: invalid OS minor version number + +.build_version ios,10,256 +// CHECK: build-version-diagnostics.s:[[@LINE-1]]:23: error: invalid OS minor version number + +.build_version watchos,10,0 a +// CHECK: build-version-diagnostics.s:[[@LINE-1]]:29: error: invalid OS update specifier, comma expected + +.build_version watchos,10,0 , +// CHECK: build-version-diagnostics.s:[[@LINE-1]]:30: error: invalid OS update version number, integer expected + +.build_version ios,10,0,-1 +// CHECK: build-version-diagnostics.s:[[@LINE-1]]:25: error: invalid OS update version number + +.build_version ios,10,0,256 +// CHECK: build-version-diagnostics.s:[[@LINE-1]]:25: error: invalid OS update version number + +.build_version ios,10,0,0, +// CHECK: build-version-diagnostics.s:[[@LINE-1]]:26: error: unexpected token in '.build_version' directive diff --git a/llvm/test/MC/MachO/ARM/build-version-encode.s b/llvm/test/MC/MachO/ARM/build-version-encode.s new file mode 100644 index 00000000000..19e75fafae9 --- /dev/null +++ b/llvm/test/MC/MachO/ARM/build-version-encode.s @@ -0,0 +1,10 @@ +// RUN: llvm-mc %s -triple x86_64-apple-tvos -filetype=obj | llvm-readobj -macho-version-min | FileCheck %s + +.build_version tvos,1,2,3 +// CHECK: MinVersion { +// CHECK: Cmd: LC_BUILD_VERSION +// CHECK: Size: 24 +// CHECK: Platform: tvos +// CHECK: Version: 1.2.3 +// CHECK: SDK: n/a +// CHECK: } diff --git a/llvm/test/MC/MachO/ARM/build-version.s b/llvm/test/MC/MachO/ARM/build-version.s new file mode 100644 index 00000000000..e3e3f14df08 --- /dev/null +++ b/llvm/test/MC/MachO/ARM/build-version.s @@ -0,0 +1,19 @@ +// RUN: llvm-mc -triple x86_64-apple-macos %s | FileCheck %s + +.build_version macos,1,2 +// CHECK: .build_version macos, 1, 2 + +.build_version macos,1,2,0 +// CHECK: .build_version macos, 1, 2 + +.build_version macos,3,4,5 +// CHECK: .build_version macos, 3, 4, 5 + +.build_version ios,6,7 +// CHECK: .build_version ios, 6, 7 + +.build_version tvos,8,9 +// CHECK: .build_version tvos, 8, 9 + +.build_version watchos,10,11 +// CHECK: .build_version watchos, 10, 11 diff --git a/llvm/test/MC/MachO/ARM/version-min-diagnostics.s b/llvm/test/MC/MachO/ARM/version-min-diagnostics.s index 76c3268dafb..786fe6f2ac4 100644 --- a/llvm/test/MC/MachO/ARM/version-min-diagnostics.s +++ b/llvm/test/MC/MachO/ARM/version-min-diagnostics.s @@ -27,7 +27,7 @@ .watchos_version_min 70000,1 -// CHECK: error: invalid OS update number +// CHECK: error: invalid OS update version number // CHECK: .ios_version_min 5,2,257 // CHECK: ^ // CHECK: error: invalid OS minor version number @@ -42,7 +42,7 @@ // CHECK: error: invalid OS major version number // CHECK: .ios_version_min 70000,1 // CHECK: ^ -// CHECK: error: invalid OS update number +// CHECK: error: invalid OS update version number // CHECK: .macosx_version_min 99,2,257 // CHECK: ^ // CHECK: error: invalid OS minor version number @@ -57,7 +57,7 @@ // CHECK: error: invalid OS major version number // CHECK: .macosx_version_min 70000,1 // CHECK: ^ -// CHECK: error: invalid OS update number +// CHECK: error: invalid OS update version number // CHECK: .tvos_version_min 99,2,257 // CHECK: ^ // CHECK: error: invalid OS minor version number @@ -72,7 +72,7 @@ // CHECK: error: invalid OS major version number // CHECK: .tvos_version_min 70000,1 // CHECK: ^ -// CHECK: error: invalid OS update number +// CHECK: error: invalid OS update version number // CHECK: .watchos_version_min 99,2,257 // CHECK: ^ // CHECK: error: invalid OS minor version number diff --git a/llvm/test/MC/MachO/ARM/version-min-diagnostics2.s b/llvm/test/MC/MachO/ARM/version-min-diagnostics2.s index 0689cd41f70..fb984d85b29 100644 --- a/llvm/test/MC/MachO/ARM/version-min-diagnostics2.s +++ b/llvm/test/MC/MachO/ARM/version-min-diagnostics2.s @@ -4,31 +4,31 @@ // RUN: llvm-mc -triple i386-apple-macosx %s 2>&1 | FileCheck %s --check-prefix=CHECK --check-prefix=MACOSX .ios_version_min 1,2,3 -// WATCHOS: version-min-diagnostics2.s:[[@LINE-1]]:1: warning: .ios_version_min should only be used for ios targets -// TVOS: version-min-diagnostics2.s:[[@LINE-2]]:1: warning: .ios_version_min should only be used for ios targets -// MACOSX: version-min-diagnostics2.s:[[@LINE-3]]:1: warning: .ios_version_min should only be used for ios targets -// IOS-NOT: warning: .ios_version_min should only be used for ios targets +// WATCHOS: version-min-diagnostics2.s:[[@LINE-1]]:1: warning: .ios_version_min used while targeting watchos +// TVOS: version-min-diagnostics2.s:[[@LINE-2]]:1: warning: .ios_version_min used while targeting tvos +// MACOSX: version-min-diagnostics2.s:[[@LINE-3]]:1: warning: .ios_version_min used while targeting macos +// IOS-NOT: warning: .ios_version_min used while targeting .macosx_version_min 4,5,6 -// WATCHOS: version-min-diagnostics2.s:[[@LINE-1]]:1: warning: .macosx_version_min should only be used for macosx targets -// TVOS: version-min-diagnostics2.s:[[@LINE-2]]:1: warning: .macosx_version_min should only be used for macosx targets -// IOS: version-min-diagnostics2.s:[[@LINE-3]]:1: warning: .macosx_version_min should only be used for macosx targets -// MACOSX-NOT: warning: .macosx_version_min should only be used for macosx targets -// CHECK: version-min-diagnostics2.s:[[@LINE-5]]:1: warning: overriding previous version_min directive +// WATCHOS: version-min-diagnostics2.s:[[@LINE-1]]:1: warning: .macosx_version_min used while targeting watchos +// TVOS: version-min-diagnostics2.s:[[@LINE-2]]:1: warning: .macosx_version_min used while targeting tvos +// IOS: version-min-diagnostics2.s:[[@LINE-3]]:1: warning: .macosx_version_min used while targeting ios +// MACOSX-NOT: warning: .macosx_version_min used while targeting +// CHECK: version-min-diagnostics2.s:[[@LINE-5]]:1: warning: overriding previous version directive // CHECK: version-min-diagnostics2.s:[[@LINE-12]]:1: note: previous definition is here .tvos_version_min 7,8,9 -// WATCHOS: version-min-diagnostics2.s:[[@LINE-1]]:1: warning: .tvos_version_min should only be used for tvos targets -// MACOSX: version-min-diagnostics2.s:[[@LINE-2]]:1: warning: .tvos_version_min should only be used for tvos targets -// IOS: version-min-diagnostics2.s:[[@LINE-3]]:1: warning: .tvos_version_min should only be used for tvos targets -// TVOS-NOT: warning: .tvos_version_min should only be used for tvos targets -// CHECK: version-min-diagnostics2.s:[[@LINE-5]]:1: warning: overriding previous version_min directive +// WATCHOS: version-min-diagnostics2.s:[[@LINE-1]]:1: warning: .tvos_version_min used while targeting watchos +// MACOSX: version-min-diagnostics2.s:[[@LINE-2]]:1: warning: .tvos_version_min used while targeting macos +// IOS: version-min-diagnostics2.s:[[@LINE-3]]:1: warning: .tvos_version_min used while targeting ios +// TVOS-NOT: warning: .tvos_version_min used while targeting +// CHECK: version-min-diagnostics2.s:[[@LINE-5]]:1: warning: overriding previous version directive // CHECK: version-min-diagnostics2.s:[[@LINE-14]]:1: note: previous definition is here .watchos_version_min 10,11,12 -// MACOSX: version-min-diagnostics2.s:[[@LINE-1]]:1: warning: .watchos_version_min should only be used for watchos targets -// IOS: version-min-diagnostics2.s:[[@LINE-2]]:1: warning: .watchos_version_min should only be used for watchos targets -// TVOS-NOT: warning: .tvos_version_min should only be used for tvos targets -// WATCHOS-NOT: warning: .watchos_version_min should only be used for watchos targets -// CHECK: version-min-diagnostics2.s:[[@LINE-5]]:1: warning: overriding previous version_min directive +// MACOSX: version-min-diagnostics2.s:[[@LINE-1]]:1: warning: .watchos_version_min used while targeting macos +// IOS: version-min-diagnostics2.s:[[@LINE-2]]:1: warning: .watchos_version_min used while targeting ios +// TVOS: version-min-diagnostics2.s:[[@LINE-3]]:1: warning: .watchos_version_min used while targeting tvos +// WATCHOS-NOT: warning: .watchos_version_min used while targeting watchos +// CHECK: version-min-diagnostics2.s:[[@LINE-5]]:1: warning: overriding previous version directive // CHECK: version-min-diagnostics2.s:[[@LINE-14]]:1: note: previous definition is here |