diff --git a/llvm/include/llvm/IR/AutoUpgrade.h b/llvm/include/llvm/IR/AutoUpgrade.h --- a/llvm/include/llvm/IR/AutoUpgrade.h +++ b/llvm/include/llvm/IR/AutoUpgrade.h @@ -87,6 +87,10 @@ /// Upgrade the loop attachment metadata node. MDNode *upgradeInstructionLoopAttachment(MDNode &N); + /// Upgrade the datalayout string by adding a section for address space + /// pointers. + std::string UpgradeDataLayoutString(StringRef DL, StringRef Triple); + } // End llvm namespace #endif diff --git a/llvm/include/llvm/Target/TargetMachine.h b/llvm/include/llvm/Target/TargetMachine.h --- a/llvm/include/llvm/Target/TargetMachine.h +++ b/llvm/include/llvm/Target/TargetMachine.h @@ -157,7 +157,7 @@ /// The LLVM Module owns a DataLayout that is used for the target independent /// optimizations and code generation. This hook provides a target specific /// check on the validity of this DataLayout. - virtual bool isCompatibleDataLayout(const DataLayout &Candidate) const { + bool isCompatibleDataLayout(const DataLayout &Candidate) const { return DL == Candidate; } diff --git a/llvm/lib/Bitcode/Reader/BitcodeReader.cpp b/llvm/lib/Bitcode/Reader/BitcodeReader.cpp --- a/llvm/lib/Bitcode/Reader/BitcodeReader.cpp +++ b/llvm/lib/Bitcode/Reader/BitcodeReader.cpp @@ -3648,6 +3648,11 @@ break; } Record.clear(); + + // Upgrade data layout string. + std::string DL = llvm::UpgradeDataLayoutString(TheModule->getDataLayoutStr(), + TheModule->getTargetTriple()); + TheModule->setDataLayout(DL); } } diff --git a/llvm/lib/IR/AutoUpgrade.cpp b/llvm/lib/IR/AutoUpgrade.cpp --- a/llvm/lib/IR/AutoUpgrade.cpp +++ b/llvm/lib/IR/AutoUpgrade.cpp @@ -4113,3 +4113,24 @@ return MDTuple::get(T->getContext(), Ops); } + +std::string llvm::UpgradeDataLayoutString(StringRef DL, StringRef TT) { + std::string AddrSpaces = "-p270:32:32-p271:32:32-p272:64:64"; + + // If X86, and the datalayout matches the expected format, add pointer size + // address spaces to the datalayout. + Triple::ArchType Arch = Triple(TT).getArch(); + if ((Arch != llvm::Triple::x86 && Arch != llvm::Triple::x86_64) || + DL.contains(AddrSpaces)) + return DL; + + SmallVector Groups; + Regex R("(e-m:[a-z](-p:32:32)?)(-[if]64:.*$)"); + if (!R.match(DL, &Groups)) + return DL; + + SmallString<1024> Buf; + std::string Res = + (Groups[1] + AddrSpaces + Groups[3]).toStringRef(Buf).str(); + return Res; +} diff --git a/llvm/lib/Target/X86/X86TargetMachine.h b/llvm/lib/Target/X86/X86TargetMachine.h --- a/llvm/lib/Target/X86/X86TargetMachine.h +++ b/llvm/lib/Target/X86/X86TargetMachine.h @@ -30,7 +30,6 @@ class X86TargetMachine final : public LLVMTargetMachine { std::unique_ptr TLOF; mutable StringMap> SubtargetMap; - const DataLayout DLNoAddrSpaces; public: X86TargetMachine(const Target &T, const Triple &TT, StringRef CPU, @@ -53,8 +52,6 @@ TargetLoweringObjectFile *getObjFileLowering() const override { return TLOF.get(); } - - bool isCompatibleDataLayout(const DataLayout &Candidate) const override; }; } // end namespace llvm diff --git a/llvm/lib/Target/X86/X86TargetMachine.cpp b/llvm/lib/Target/X86/X86TargetMachine.cpp --- a/llvm/lib/Target/X86/X86TargetMachine.cpp +++ b/llvm/lib/Target/X86/X86TargetMachine.cpp @@ -106,8 +106,7 @@ llvm_unreachable("unknown subtarget type"); } -static std::string computeDataLayout(const Triple &TT, - bool AddressSpaces = true) { +static std::string computeDataLayout(const Triple &TT) { // X86 is little endian std::string Ret = "e"; @@ -119,8 +118,7 @@ Ret += "-p:32:32"; // Address spaces for 32 bit signed, 32 bit unsigned, and 64 bit pointers. - if (AddressSpaces) - Ret += "-p270:32:32-p271:32:32-p272:64:64"; + Ret += "-p270:32:32-p271:32:32-p272:64:64"; // Some ABIs align 64 bit integers and doubles to 64 bits, others to 32. if (TT.isArch64Bit() || TT.isOSWindows() || TT.isOSNaCl()) @@ -223,8 +221,7 @@ getEffectiveRelocModel(TT, JIT, RM), getEffectiveX86CodeModel(CM, JIT, TT.getArch() == Triple::x86_64), OL), - TLOF(createTLOF(getTargetTriple())), - DLNoAddrSpaces(computeDataLayout(TT, /*AddressSpaces=*/false)) { + TLOF(createTLOF(getTargetTriple())) { // On PS4, the "return address" of a 'noreturn' call must still be within // the calling function, and TrapUnreachable is an easy way to get that. if (TT.isPS4() || TT.isOSBinFormatMachO()) { @@ -318,13 +315,6 @@ return I.get(); } -bool X86TargetMachine::isCompatibleDataLayout( - const DataLayout &Candidate) const { - // Maintain compatibility with datalayouts that don't have address space - // pointer sizes. - return DL == Candidate || DLNoAddrSpaces == Candidate; -} - //===----------------------------------------------------------------------===// // Command line options for x86 //===----------------------------------------------------------------------===// diff --git a/llvm/test/Bitcode/upgrade-datalayout.ll b/llvm/test/Bitcode/upgrade-datalayout.ll new file mode 100644 --- /dev/null +++ b/llvm/test/Bitcode/upgrade-datalayout.ll @@ -0,0 +1,9 @@ +; Test to make sure datalayout is automatically upgraded. +; +; RUN: llvm-as %s -o - | llvm-dis - | FileCheck %s + +target datalayout = "e-m:e-p:32:32-i64:64-f80:128-n8:16:32:64-S128" +target triple = "x86_64-unknown-linux-gnu" + +; CHECK: target datalayout = "e-m:e-p:32:32-p270:32:32-p271:32:32-p272:64:64-i64:64-f80:128-n8:16:32:64-S128" + diff --git a/llvm/test/Bitcode/upgrade-datalayout2.ll b/llvm/test/Bitcode/upgrade-datalayout2.ll new file mode 100644 --- /dev/null +++ b/llvm/test/Bitcode/upgrade-datalayout2.ll @@ -0,0 +1,10 @@ +; Test to make sure datalayout is not automatically upgraded if it does not +; match a possible x86 datalayout. +; +; RUN: llvm-as %s -o - | llvm-dis - | FileCheck %s + +target datalayout = "e-p:64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-f32:32:32-f64:64:64-v64:64:64-v128:128:128-a0:0:64-s0:64:64-f80:128:128-n8:16:32:64-S128" +target triple = "x86_64-unknown-linux-gnu" + +; CHECK: target datalayout = "e-p:64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-f32:32:32-f64:64:64-v64:64:64-v128:128:128-a0:0:64-s0:64:64-f80:128:128-n8:16:32:64-S128" + diff --git a/llvm/test/Bitcode/upgrade-datalayout3.ll b/llvm/test/Bitcode/upgrade-datalayout3.ll new file mode 100644 --- /dev/null +++ b/llvm/test/Bitcode/upgrade-datalayout3.ll @@ -0,0 +1,8 @@ +; Test to make sure datalayout is automatically upgraded. +; +; RUN: llvm-as %s -o - | llvm-dis - | FileCheck %s + +target datalayout = "e-m:w-p:32:32-i64:64-f80:32-n8:16:32-S32" +target triple = "i686-pc-windows-msvc" + +; CHECK: target datalayout = "e-m:w-p:32:32-p270:32:32-p271:32:32-p272:64:64-i64:64-f80:32-n8:16:32-S32" diff --git a/llvm/unittests/Bitcode/CMakeLists.txt b/llvm/unittests/Bitcode/CMakeLists.txt --- a/llvm/unittests/Bitcode/CMakeLists.txt +++ b/llvm/unittests/Bitcode/CMakeLists.txt @@ -8,4 +8,5 @@ add_llvm_unittest(BitcodeTests BitReaderTest.cpp + DataLayoutUpgradeTest.cpp ) diff --git a/llvm/unittests/Bitcode/DataLayoutUpgradeTest.cpp b/llvm/unittests/Bitcode/DataLayoutUpgradeTest.cpp new file mode 100644 --- /dev/null +++ b/llvm/unittests/Bitcode/DataLayoutUpgradeTest.cpp @@ -0,0 +1,62 @@ +//===- DataLayoutUpgradeTest.cpp - Tests for DataLayout upgrades ----------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#include "llvm/IR/AutoUpgrade.h" +#include "gtest/gtest.h" + +using namespace llvm; + +namespace { + +TEST(DataLayoutUpgradeTest, ValidDataLayoutUpgrade) { + std::string DL1 = UpgradeDataLayoutString( + "e-m:e-p:32:32-i64:64-f80:128-n8:16:32:64-S128", + "x86_64-unknown-linux-gnu"); + std::string DL2 = UpgradeDataLayoutString( + "e-m:w-p:32:32-i64:64-f80:32-n8:16:32-S32", + "i686-pc-windows-msvc"); + std::string DL3 = UpgradeDataLayoutString( + "e-m:o-i64:64-i128:128-n32:64-S128", + "x86_64-apple-macosx"); + EXPECT_EQ(DL1, "e-m:e-p:32:32-p270:32:32-p271:32:32-p272:64:64-i64:64" + "-f80:128-n8:16:32:64-S128"); + EXPECT_EQ(DL2, "e-m:w-p:32:32-p270:32:32-p271:32:32-p272:64:64-i64:64" + "-f80:32-n8:16:32-S32"); + EXPECT_EQ(DL3, "e-m:o-p270:32:32-p271:32:32-p272:64:64-i64:64-i128:128" + "-n32:64-S128"); +} + +TEST(DataLayoutUpgradeTest, NoDataLayoutUpgrade) { + std::string DL1 = UpgradeDataLayoutString( + "e-p:64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-f32:32:32" + "-f64:64:64-v64:64:64-v128:128:128-a0:0:64-s0:64:64-f80:128:128" + "-n8:16:32:64-S128", + "x86_64-unknown-linux-gnu"); + std::string DL2 = UpgradeDataLayoutString("e-p:32:32", "i686-apple-darwin9"); + std::string DL3 = UpgradeDataLayoutString("e-m:e-i64:64-n32:64", + "powerpc64le-unknown-linux-gnu"); + std::string DL4 = UpgradeDataLayoutString("e-m:o-i64:64-i128:128-n32:64-S128", + "aarch64--"); + EXPECT_EQ(DL1, "e-p:64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64" + "-f32:32:32-f64:64:64-v64:64:64-v128:128:128-a0:0:64-s0:64:64" + "-f80:128:128-n8:16:32:64-S128"); + EXPECT_EQ(DL2, "e-p:32:32"); + EXPECT_EQ(DL3, "e-m:e-i64:64-n32:64"); + EXPECT_EQ(DL4, "e-m:o-i64:64-i128:128-n32:64-S128"); +} + +TEST(DataLayoutUpgradeTest, InvalidDataLayout) { + std::string DL1 = UpgradeDataLayoutString("", "x86_64-unknown-linux-gnu"); + std::string DL2 = UpgradeDataLayoutString( + "e-m:e-p:32:32-i64:64-f80:128-n8:16:32:64-S128", ""); + EXPECT_EQ(DL1, ""); + EXPECT_EQ(DL2, "e-m:e-p:32:32-i64:64-f80:128-n8:16:32:64-S128"); + +} + +} // end namespace