Index: include/llvm/ADT/Triple.h =================================================================== --- include/llvm/ADT/Triple.h +++ include/llvm/ADT/Triple.h @@ -339,6 +339,12 @@ 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: lib/Linker/LinkModules.cpp =================================================================== --- lib/Linker/LinkModules.cpp +++ 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,16 @@ return HasErr; } +// This function returns true if the triples match. +static bool triplesMatch(const Triple &T0, const Triple &T1) { + if (T0.getVendor() != Triple::Apple) + return T0.str() == T1.str(); + + // If vendor is apple, ignore the version number. + return T0.getArch() == T1.getArch() && T0.getSubArch() == T1.getSubArch() && + T0.getVendor() == T1.getVendor() && T0.getOS() == T1.getOS(); +} + bool ModuleLinker::run() { assert(DstM && "Null destination module"); assert(SrcM && "Null source module"); @@ -1466,10 +1477,6 @@ 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 +1485,24 @@ 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"); - } + + // If vendor is apple, pick the triple with the larger version number. + if (SrcTriple.getVendor() == Triple::Apple) + if (DstTriple.isOSVersionLT(SrcTriple)) + DstM->setTargetTriple(SrcM->getTargetTriple()); // Append the module inline asm string. if (!SrcM->getModuleInlineAsm().empty()) { Index: test/Linker/apple-version0.ll =================================================================== --- /dev/null +++ test/Linker/apple-version0.ll @@ -0,0 +1,17 @@ +; RUN: llvm-link %s %p/apple-version1.ll -S -o - 2>%t.err | FileCheck %s -check-prefix=CHECK1 +; RUN: (echo foo ;cat %t.err) | FileCheck --check-prefix=WARN1 %s +; RUN: llvm-link %s %p/apple-version2.ll -S -o - 2>%t.err | FileCheck %s -check-prefix=CHECK2 +; RUN: (echo foo ;cat %t.err) | FileCheck --check-prefix=WARN2 %s +; RUN: llvm-link %s %p/apple-version3.ll -S -o /dev/null 2>%t.err +; RUN: cat %t.err | FileCheck --check-prefix=WARN3 %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 +; WARN3: WARNING: Linking two modules of different target triples + +target triple = "x86_64-apple-macosx10.9.0" Index: test/Linker/apple-version1.ll =================================================================== --- /dev/null +++ test/Linker/apple-version1.ll @@ -0,0 +1,4 @@ +; This file is used with apple-version0.ll +; RUN: true + +target triple = "x86_64-apple-macosx10.10.0" Index: test/Linker/apple-version2.ll =================================================================== --- /dev/null +++ test/Linker/apple-version2.ll @@ -0,0 +1,4 @@ +; This file is used with apple-version0.ll +; RUN: true + +target triple = "x86_64-apple-macosx10.8.0" Index: test/Linker/apple-version3.ll =================================================================== --- /dev/null +++ test/Linker/apple-version3.ll @@ -0,0 +1,4 @@ +; This file is used with apple-version0.ll +; RUN: true + +target triple = "x86-apple-macosx10.9.0"