[llvm] r320661 - MC: Add support for mach-o build_version

Matthias Braun via llvm-commits llvm-commits at lists.llvm.org
Wed Dec 13 16:12:46 PST 2017


Author: matze
Date: Wed Dec 13 16:12:46 2017
New Revision: 320661

URL: http://llvm.org/viewvc/llvm-project?rev=320661&view=rev
Log:
MC: Add support for mach-o build_version

LC_BUILD_VERSION is a new load command superseding the previously used
LC_XXX_MIN_VERSION commands. This adds an assembler directive along with
encoding/streaming support.

Added:
    llvm/trunk/test/MC/MachO/ARM/build-version-diagnostics.s
    llvm/trunk/test/MC/MachO/ARM/build-version-encode.s
    llvm/trunk/test/MC/MachO/ARM/build-version.s
Modified:
    llvm/trunk/include/llvm/BinaryFormat/MachO.h
    llvm/trunk/include/llvm/MC/MCAssembler.h
    llvm/trunk/include/llvm/MC/MCStreamer.h
    llvm/trunk/lib/MC/MCAsmStreamer.cpp
    llvm/trunk/lib/MC/MCAssembler.cpp
    llvm/trunk/lib/MC/MCMachOStreamer.cpp
    llvm/trunk/lib/MC/MCParser/DarwinAsmParser.cpp
    llvm/trunk/lib/MC/MachObjectWriter.cpp
    llvm/trunk/test/MC/MachO/ARM/version-min-diagnostics.s
    llvm/trunk/test/MC/MachO/ARM/version-min-diagnostics2.s

Modified: llvm/trunk/include/llvm/BinaryFormat/MachO.h
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/BinaryFormat/MachO.h?rev=320661&r1=320660&r2=320661&view=diff
==============================================================================
--- llvm/trunk/include/llvm/BinaryFormat/MachO.h (original)
+++ llvm/trunk/include/llvm/BinaryFormat/MachO.h Wed Dec 13 16:12:46 2017
@@ -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,

Modified: llvm/trunk/include/llvm/MC/MCAssembler.h
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/MC/MCAssembler.h?rev=320661&r1=320660&r2=320661&view=diff
==============================================================================
--- llvm/trunk/include/llvm/MC/MCAssembler.h (original)
+++ llvm/trunk/include/llvm/MC/MCAssembler.h Wed Dec 13 16:12:46 2017
@@ -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

Modified: llvm/trunk/include/llvm/MC/MCStreamer.h
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/MC/MCStreamer.h?rev=320661&r1=320660&r2=320661&view=diff
==============================================================================
--- llvm/trunk/include/llvm/MC/MCStreamer.h (original)
+++ llvm/trunk/include/llvm/MC/MCStreamer.h Wed Dec 13 16:12:46 2017
@@ -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).

Modified: llvm/trunk/lib/MC/MCAsmStreamer.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/MC/MCAsmStreamer.cpp?rev=320661&r1=320660&r2=320661&view=diff
==============================================================================
--- llvm/trunk/lib/MC/MCAsmStreamer.cpp (original)
+++ llvm/trunk/lib/MC/MCAsmStreamer.cpp Wed Dec 13 16:12:46 2017
@@ -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(MCDat
   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();

Modified: llvm/trunk/lib/MC/MCAssembler.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/MC/MCAssembler.cpp?rev=320661&r1=320660&r2=320661&view=diff
==============================================================================
--- llvm/trunk/lib/MC/MCAssembler.cpp (original)
+++ llvm/trunk/lib/MC/MCAssembler.cpp Wed Dec 13 16:12:46 2017
@@ -88,7 +88,7 @@ MCAssembler::MCAssembler(MCContext &Cont
     : 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();

Modified: llvm/trunk/lib/MC/MCMachOStreamer.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/MC/MCMachOStreamer.cpp?rev=320661&r1=320660&r2=320661&view=diff
==============================================================================
--- llvm/trunk/lib/MC/MCMachOStreamer.cpp (original)
+++ llvm/trunk/lib/MC/MCMachOStreamer.cpp Wed Dec 13 16:12:46 2017
@@ -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(MCD
 
 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) {

Modified: llvm/trunk/lib/MC/MCParser/DarwinAsmParser.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/MC/MCParser/DarwinAsmParser.cpp?rev=320661&r1=320660&r2=320661&view=diff
==============================================================================
--- llvm/trunk/lib/MC/MCParser/DarwinAsmParser.cpp (original)
+++ llvm/trunk/lib/MC/MCParser/DarwinAsmParser.cpp Wed Dec 13 16:12:46 2017
@@ -54,7 +54,7 @@ class DarwinAsmParser : public MCAsmPars
                           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::parseDirectiveData
   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;
-  }
-  if (T.getOS() != ExpectedOS)
-    Warning(Loc, Directive + " should only be used for " +
-            Triple::getOSTypeName(ExpectedOS) + " targets");
-
-  if (LastVersionMinDirective.isValid()) {
-    Warning(Loc, "overriding previous version_min directive");
-    Note(LastVersionMinDirective, "previous definition is here");
+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;
   }
-  LastVersionMinDirective = Loc;
+  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;
+}
+
+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;
+  }
+  llvm_unreachable("Invalid mach-o platform type");
+}
+
+/// 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;
 
-  // We've parsed a correct version specifier, so send it to the streamer.
-  getStreamer().EmitVersionMin((MCVersionMinType)Kind, Major, Minor, Update);
+  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() {

Modified: llvm/trunk/lib/MC/MachObjectWriter.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/MC/MachObjectWriter.cpp?rev=320661&r1=320660&r2=320661&view=diff
==============================================================================
--- llvm/trunk/lib/MC/MachObjectWriter.cpp (original)
+++ llvm/trunk/lib/MC/MachObjectWriter.cpp Wed Dec 13 16:12:46 2017
@@ -721,6 +721,16 @@ bool MachObjectWriter::isSymbolRefDiffer
   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(MCAss
                      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(MCAss
   // 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(MCAss
     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.

Added: llvm/trunk/test/MC/MachO/ARM/build-version-diagnostics.s
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/MC/MachO/ARM/build-version-diagnostics.s?rev=320661&view=auto
==============================================================================
--- llvm/trunk/test/MC/MachO/ARM/build-version-diagnostics.s (added)
+++ llvm/trunk/test/MC/MachO/ARM/build-version-diagnostics.s Wed Dec 13 16:12:46 2017
@@ -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

Added: llvm/trunk/test/MC/MachO/ARM/build-version-encode.s
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/MC/MachO/ARM/build-version-encode.s?rev=320661&view=auto
==============================================================================
--- llvm/trunk/test/MC/MachO/ARM/build-version-encode.s (added)
+++ llvm/trunk/test/MC/MachO/ARM/build-version-encode.s Wed Dec 13 16:12:46 2017
@@ -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: }

Added: llvm/trunk/test/MC/MachO/ARM/build-version.s
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/MC/MachO/ARM/build-version.s?rev=320661&view=auto
==============================================================================
--- llvm/trunk/test/MC/MachO/ARM/build-version.s (added)
+++ llvm/trunk/test/MC/MachO/ARM/build-version.s Wed Dec 13 16:12:46 2017
@@ -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

Modified: llvm/trunk/test/MC/MachO/ARM/version-min-diagnostics.s
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/MC/MachO/ARM/version-min-diagnostics.s?rev=320661&r1=320660&r2=320661&view=diff
==============================================================================
--- llvm/trunk/test/MC/MachO/ARM/version-min-diagnostics.s (original)
+++ llvm/trunk/test/MC/MachO/ARM/version-min-diagnostics.s Wed Dec 13 16:12:46 2017
@@ -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

Modified: llvm/trunk/test/MC/MachO/ARM/version-min-diagnostics2.s
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/MC/MachO/ARM/version-min-diagnostics2.s?rev=320661&r1=320660&r2=320661&view=diff
==============================================================================
--- llvm/trunk/test/MC/MachO/ARM/version-min-diagnostics2.s (original)
+++ llvm/trunk/test/MC/MachO/ARM/version-min-diagnostics2.s Wed Dec 13 16:12:46 2017
@@ -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




More information about the llvm-commits mailing list