[LinkModules] Change the way ModuleLinker merges triples.
authorAkira Hatanaka <ahatanaka@apple.com>
Fri, 13 Feb 2015 00:40:41 +0000 (00:40 +0000)
committerAkira Hatanaka <ahatanaka@apple.com>
Fri, 13 Feb 2015 00:40:41 +0000 (00:40 +0000)
This commit makes the following changes:

- Stop issuing a warning when the triples' string representations do not match
  exactly if the Triple objects generated from the strings compare equal.

- On Apple platforms, choose the triple that has the larger minimum version
  number.

rdar://problem/16743513

Differential Revision: http://reviews.llvm.org/D7591

git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@228999 91177308-0d34-0410-b5e6-96231b3b80d8

include/llvm/ADT/Triple.h
lib/Linker/LinkModules.cpp
test/Linker/Inputs/apple-version/1.ll [new file with mode: 0644]
test/Linker/Inputs/apple-version/2.ll [new file with mode: 0644]
test/Linker/Inputs/apple-version/3.ll [new file with mode: 0644]
test/Linker/Inputs/apple-version/4.ll [new file with mode: 0644]
test/Linker/Inputs/targettriple-a.ll
test/Linker/Inputs/targettriple-b.ll
test/Linker/Inputs/targettriple-c.ll [new file with mode: 0644]
test/Linker/apple-version.ll [new file with mode: 0644]
test/Linker/targettriple.ll

index bc91188b864011e572b76abdbfe22bef59e792ab..886f6fb2924ab1dc9dd8fb0b9cf871b307ab1501 100644 (file)
@@ -202,6 +202,13 @@ public:
   Triple(const Twine &ArchStr, const Twine &VendorStr, const Twine &OSStr,
          const Twine &EnvironmentStr);
 
+  bool operator==(const Triple &Other) const {
+    return Arch == Other.Arch && SubArch == Other.SubArch &&
+           Vendor == Other.Vendor && OS == Other.OS &&
+           Environment == Other.Environment &&
+           ObjectFormat == Other.ObjectFormat;
+  }
+
   /// @}
   /// @name Normalization
   /// @{
@@ -339,6 +346,12 @@ public:
     return false;
   }
 
+  bool isOSVersionLT(const Triple &Other) const {
+    unsigned RHS[3];
+    Other.getOSVersion(RHS[0], RHS[1], RHS[2]);
+    return isOSVersionLT(RHS[0], RHS[1], RHS[2]);
+  }
+
   /// isMacOSXVersionLT - Comparison function for checking OS X version
   /// compatibility, which handles supporting skewed version numbering schemes
   /// used by the "darwin" triples.
index dc002d8a5766fbcb6e028834bb32a39465b4628c..9585fba6e4f1d6d40d195d09cec1669158432fee 100644 (file)
@@ -18,6 +18,7 @@
 #include "llvm/ADT/SetVector.h"
 #include "llvm/ADT/SmallString.h"
 #include "llvm/ADT/Statistic.h"
+#include "llvm/ADT/Triple.h"
 #include "llvm/IR/Constants.h"
 #include "llvm/IR/DebugInfo.h"
 #include "llvm/IR/DiagnosticInfo.h"
@@ -1457,6 +1458,28 @@ bool ModuleLinker::linkModuleFlagsMetadata() {
   return HasErr;
 }
 
+// This function returns true if the triples match.
+static bool triplesMatch(const Triple &T0, const Triple &T1) {
+  // If vendor is apple, ignore the version number.
+  if (T0.getVendor() == Triple::Apple)
+    return T0.getArch() == T1.getArch() &&
+           T0.getSubArch() == T1.getSubArch() &&
+           T0.getVendor() == T1.getVendor() &&
+           T0.getOS() == T1.getOS();
+
+  return T0 == T1;
+}
+
+// This function returns the merged triple.
+static std::string mergeTriples(const Triple &SrcTriple, const Triple &DstTriple) {
+  // If vendor is apple, pick the triple with the larger version number.
+  if (SrcTriple.getVendor() == Triple::Apple)
+    if (DstTriple.isOSVersionLT(SrcTriple))
+      return SrcTriple.str();
+
+  return DstTriple.str();
+}
+
 bool ModuleLinker::run() {
   assert(DstM && "Null destination module");
   assert(SrcM && "Null source module");
@@ -1466,10 +1489,6 @@ bool ModuleLinker::run() {
   if (!DstM->getDataLayout() && SrcM->getDataLayout())
     DstM->setDataLayout(SrcM->getDataLayout());
 
-  // Copy the target triple from the source to dest if the dest's is empty.
-  if (DstM->getTargetTriple().empty() && !SrcM->getTargetTriple().empty())
-    DstM->setTargetTriple(SrcM->getTargetTriple());
-
   if (SrcM->getDataLayout() && DstM->getDataLayout() &&
       *SrcM->getDataLayout() != *DstM->getDataLayout()) {
     emitWarning("Linking two modules of different data layouts: '" +
@@ -1478,14 +1497,21 @@ bool ModuleLinker::run() {
                 DstM->getModuleIdentifier() + "' is '" +
                 DstM->getDataLayoutStr() + "'\n");
   }
-  if (!SrcM->getTargetTriple().empty() &&
-      DstM->getTargetTriple() != SrcM->getTargetTriple()) {
+
+  // Copy the target triple from the source to dest if the dest's is empty.
+  if (DstM->getTargetTriple().empty() && !SrcM->getTargetTriple().empty())
+    DstM->setTargetTriple(SrcM->getTargetTriple());
+
+  Triple SrcTriple(SrcM->getTargetTriple()), DstTriple(DstM->getTargetTriple());
+
+  if (!SrcM->getTargetTriple().empty() && !triplesMatch(SrcTriple, DstTriple))
     emitWarning("Linking two modules of different target triples: " +
                 SrcM->getModuleIdentifier() + "' is '" +
                 SrcM->getTargetTriple() + "' whereas '" +
                 DstM->getModuleIdentifier() + "' is '" +
                 DstM->getTargetTriple() + "'\n");
-  }
+
+  DstM->setTargetTriple(mergeTriples(SrcTriple, DstTriple));
 
   // Append the module inline asm string.
   if (!SrcM->getModuleInlineAsm().empty()) {
diff --git a/test/Linker/Inputs/apple-version/1.ll b/test/Linker/Inputs/apple-version/1.ll
new file mode 100644 (file)
index 0000000..5cafa5e
--- /dev/null
@@ -0,0 +1 @@
+target triple = "x86_64-apple-macosx10.10.0"
diff --git a/test/Linker/Inputs/apple-version/2.ll b/test/Linker/Inputs/apple-version/2.ll
new file mode 100644 (file)
index 0000000..b63ea1f
--- /dev/null
@@ -0,0 +1 @@
+target triple = "x86_64-apple-macosx10.8.0"
diff --git a/test/Linker/Inputs/apple-version/3.ll b/test/Linker/Inputs/apple-version/3.ll
new file mode 100644 (file)
index 0000000..68e58ca
--- /dev/null
@@ -0,0 +1 @@
+target triple = "i386-apple-macosx10.9.0"
diff --git a/test/Linker/Inputs/apple-version/4.ll b/test/Linker/Inputs/apple-version/4.ll
new file mode 100644 (file)
index 0000000..467a634
--- /dev/null
@@ -0,0 +1 @@
+target triple = "x86_64h-apple-macosx10.9.0"
index 296d2df3ab6afca7c68754ac56cdf51de38df9d2..b8c7901d3177630a0a6a87522368da12484d9bfe 100644 (file)
@@ -1 +1 @@
-target triple = "e"
+target triple = "x86_64-unknown-linux-gnu"
index cca872ec9662622fd423506267465cb2b989ddcd..0122b4ac56d94fe102e3eb0ea7012b27c8b89ea5 100644 (file)
@@ -1 +1 @@
-target triple = "E"
+target triple = "i386-unknown-linux-gnu"
diff --git a/test/Linker/Inputs/targettriple-c.ll b/test/Linker/Inputs/targettriple-c.ll
new file mode 100644 (file)
index 0000000..e669a4c
--- /dev/null
@@ -0,0 +1 @@
+target triple = "x86_64h-unknown-linux-gnu"
diff --git a/test/Linker/apple-version.ll b/test/Linker/apple-version.ll
new file mode 100644 (file)
index 0000000..4dbc866
--- /dev/null
@@ -0,0 +1,24 @@
+; RUN: llvm-link %s %S/Inputs/apple-version/1.ll -S -o - 2>%t.err | FileCheck %s -check-prefix=CHECK1
+; RUN: cat %t.err | FileCheck --check-prefix=WARN1 --allow-empty %s
+; RUN: llvm-link %s %S/Inputs/apple-version/2.ll -S -o - 2>%t.err | FileCheck %s -check-prefix=CHECK2
+; RUN: cat %t.err | FileCheck --check-prefix=WARN2 --allow-empty %s
+; RUN: llvm-link %s %S/Inputs/apple-version/3.ll -S -o /dev/null 2>%t.err
+; RUN: cat %t.err | FileCheck --check-prefix=WARN3 %s
+; RUN: llvm-link %s %S/Inputs/apple-version/4.ll -S -o /dev/null 2>%t.err
+; RUN: cat %t.err | FileCheck --check-prefix=WARN4 --allow-empty %s
+
+; Check that the triple that has the larger version number is chosen and no
+; warnings are issued when the Triples differ only in version numbers.
+
+; CHECK1: target triple = "x86_64-apple-macosx10.10.0"
+; WARN1-NOT: WARNING
+; CHECK2: target triple = "x86_64-apple-macosx10.9.0"
+; WARN2-NOT: WARNING
+
+; i386 and x86_64 map to different ArchType enums.
+; WARN3: WARNING: Linking two modules of different target triples
+
+; x86_64h and x86_64 map to the same ArchType enum.
+; WARN4-NOT: WARNING
+
+target triple = "x86_64-apple-macosx10.9.0"
index c544a14a19d366e949748ffef39abb733ea45c80..1a93b60089247c704f8cea3e5cca0aca9e8ab603 100644 (file)
@@ -8,10 +8,14 @@
 ; RUN: llvm-link -suppress-warnings %s %S/Inputs/targettriple-b.ll -S -o - 2>%t.no-warn.err | FileCheck %s
 ; RUN: (echo foo ;cat %t.no-warn.err) | FileCheck --check-prefix=WARN-A %s
 
-target triple = "e"
+target triple = "x86_64-unknown-linux-gnu"
 
-; CHECK: target triple = "e"
+; CHECK: target triple = "x86_64-unknown-linux-gnu"
 
 ; WARN-A-NOT: WARNING
 
+; i386 and x86_64 map to different ArchType enums.
 ; WARN-B: WARNING: Linking two modules of different target triples:
+
+; x86_64h and x86_64 map to the same ArchType enum.
+; WARN-C-NOT: WARNING