diff --git a/llvm/include/llvm/ADT/Triple.h b/llvm/include/llvm/ADT/Triple.h index bc91188b8640..886f6fb2924a 100644 --- a/llvm/include/llvm/ADT/Triple.h +++ b/llvm/include/llvm/ADT/Triple.h @@ -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. diff --git a/llvm/lib/Linker/LinkModules.cpp b/llvm/lib/Linker/LinkModules.cpp index dc002d8a5766..9585fba6e4f1 100644 --- a/llvm/lib/Linker/LinkModules.cpp +++ b/llvm/lib/Linker/LinkModules.cpp @@ -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/llvm/test/Linker/Inputs/apple-version/1.ll b/llvm/test/Linker/Inputs/apple-version/1.ll new file mode 100644 index 000000000000..5cafa5ecc1fe --- /dev/null +++ b/llvm/test/Linker/Inputs/apple-version/1.ll @@ -0,0 +1 @@ +target triple = "x86_64-apple-macosx10.10.0" diff --git a/llvm/test/Linker/Inputs/apple-version/2.ll b/llvm/test/Linker/Inputs/apple-version/2.ll new file mode 100644 index 000000000000..b63ea1f8b233 --- /dev/null +++ b/llvm/test/Linker/Inputs/apple-version/2.ll @@ -0,0 +1 @@ +target triple = "x86_64-apple-macosx10.8.0" diff --git a/llvm/test/Linker/Inputs/apple-version/3.ll b/llvm/test/Linker/Inputs/apple-version/3.ll new file mode 100644 index 000000000000..68e58caead9c --- /dev/null +++ b/llvm/test/Linker/Inputs/apple-version/3.ll @@ -0,0 +1 @@ +target triple = "i386-apple-macosx10.9.0" diff --git a/llvm/test/Linker/Inputs/apple-version/4.ll b/llvm/test/Linker/Inputs/apple-version/4.ll new file mode 100644 index 000000000000..467a634a32bd --- /dev/null +++ b/llvm/test/Linker/Inputs/apple-version/4.ll @@ -0,0 +1 @@ +target triple = "x86_64h-apple-macosx10.9.0" diff --git a/llvm/test/Linker/Inputs/targettriple-a.ll b/llvm/test/Linker/Inputs/targettriple-a.ll index 296d2df3ab6a..b8c7901d3177 100644 --- a/llvm/test/Linker/Inputs/targettriple-a.ll +++ b/llvm/test/Linker/Inputs/targettriple-a.ll @@ -1 +1 @@ -target triple = "e" +target triple = "x86_64-unknown-linux-gnu" diff --git a/llvm/test/Linker/Inputs/targettriple-b.ll b/llvm/test/Linker/Inputs/targettriple-b.ll index cca872ec9662..0122b4ac56d9 100644 --- a/llvm/test/Linker/Inputs/targettriple-b.ll +++ b/llvm/test/Linker/Inputs/targettriple-b.ll @@ -1 +1 @@ -target triple = "E" +target triple = "i386-unknown-linux-gnu" diff --git a/llvm/test/Linker/Inputs/targettriple-c.ll b/llvm/test/Linker/Inputs/targettriple-c.ll new file mode 100644 index 000000000000..e669a4c40ea0 --- /dev/null +++ b/llvm/test/Linker/Inputs/targettriple-c.ll @@ -0,0 +1 @@ +target triple = "x86_64h-unknown-linux-gnu" diff --git a/llvm/test/Linker/apple-version.ll b/llvm/test/Linker/apple-version.ll new file mode 100644 index 000000000000..4dbc866ac3d7 --- /dev/null +++ b/llvm/test/Linker/apple-version.ll @@ -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" diff --git a/llvm/test/Linker/targettriple.ll b/llvm/test/Linker/targettriple.ll index c544a14a19d3..1a93b6008924 100644 --- a/llvm/test/Linker/targettriple.ll +++ b/llvm/test/Linker/targettriple.ll @@ -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