Date: Monday, July 4, 2022 @ 05:56:02 Author: foutrelis Revision: 449853
archrelease: copy trunk to extra-x86_64 Added: llvm13/repos/extra-x86_64/PKGBUILD (from rev 449852, llvm13/trunk/PKGBUILD) llvm13/repos/extra-x86_64/disable-A-B-A-B-and-BSWAP-in-InstCombine.patch (from rev 449852, llvm13/trunk/disable-A-B-A-B-and-BSWAP-in-InstCombine.patch) llvm13/repos/extra-x86_64/disable-DIArgList-in-SPIR-V.patch (from rev 449852, llvm13/trunk/disable-DIArgList-in-SPIR-V.patch) llvm13/repos/extra-x86_64/don-t-accept-nullptr-as-GEP-element-type.patch (from rev 449852, llvm13/trunk/don-t-accept-nullptr-as-GEP-element-type.patch) llvm13/repos/extra-x86_64/don-t-move-DBG_VALUE-instructions.patch (from rev 449852, llvm13/trunk/don-t-move-DBG_VALUE-instructions.patch) llvm13/repos/extra-x86_64/don-t-override-__attribute__-no_stack_protector.patch (from rev 449852, llvm13/trunk/don-t-override-__attribute__-no_stack_protector.patch) llvm13/repos/extra-x86_64/keys/ Deleted: llvm13/repos/extra-x86_64/PKGBUILD llvm13/repos/extra-x86_64/disable-A-B-A-B-and-BSWAP-in-InstCombine.patch llvm13/repos/extra-x86_64/disable-DIArgList-in-SPIR-V.patch llvm13/repos/extra-x86_64/don-t-accept-nullptr-as-GEP-element-type.patch llvm13/repos/extra-x86_64/don-t-move-DBG_VALUE-instructions.patch llvm13/repos/extra-x86_64/don-t-override-__attribute__-no_stack_protector.patch llvm13/repos/extra-x86_64/keys/ -------------------------------------------------------+ PKGBUILD | 211 +-- disable-A-B-A-B-and-BSWAP-in-InstCombine.patch | 104 - disable-DIArgList-in-SPIR-V.patch | 46 don-t-accept-nullptr-as-GEP-element-type.patch | 126 - don-t-move-DBG_VALUE-instructions.patch | 182 +- don-t-override-__attribute__-no_stack_protector.patch | 1080 ++++++++-------- 6 files changed, 875 insertions(+), 874 deletions(-) Deleted: PKGBUILD =================================================================== --- PKGBUILD 2022-07-04 05:55:52 UTC (rev 449852) +++ PKGBUILD 2022-07-04 05:56:02 UTC (rev 449853) @@ -1,105 +0,0 @@ -# Maintainer: Evangelos Foutras <evange...@foutrelis.com> -# Contributor: Jan "heftig" Steffens <jan.steff...@gmail.com> - -pkgname=('llvm13' 'llvm13-libs') -pkgver=13.0.1 -pkgrel=2 -arch=('x86_64') -url="https://llvm.org/" -license=('custom:Apache 2.0 with LLVM Exception') -makedepends=('cmake' 'ninja' 'libffi' 'libedit' 'ncurses' 'libxml2' - 'python') -options=('staticlibs' '!lto') # Getting thousands of test failures with LTO -_source_base=https://github.com/llvm/llvm-project/releases/download/llvmorg-$pkgver -source=($_source_base/llvm-$pkgver.src.tar.xz{,.sig} - don-t-accept-nullptr-as-GEP-element-type.patch - don-t-override-__attribute__-no_stack_protector.patch - don-t-move-DBG_VALUE-instructions.patch - disable-A-B-A-B-and-BSWAP-in-InstCombine.patch - disable-DIArgList-in-SPIR-V.patch) -sha256sums=('ec6b80d82c384acad2dc192903a6cf2cdbaffb889b84bfb98da9d71e630fc834' - 'SKIP' - 'a7e902a7612d0fdabe436a917468b043cc296bc89d8954bfc3126f737beb9ac4' - '9f0a4578b94eb8853b83af2f65e92705254b4b56d96f9a941714d174b932f465' - 'f7d69f84241416398fdb3df8bb44f9fae3c49d89889c7ffa3b37aa2e9d78f708' - '34cc0d79a30599cb2287b47b4e9a1a5bf03d57a1f8bb35be3fe976ffc4a604f6' - '8642da2d556092e4284873ba6ddc6c9a67841f42cc16f923bcd523e4b304a3ff') -validpgpkeys+=('B6C8F98282B944E3B0D5C2530FC3042E345AD05D') # Hans Wennborg <h...@chromium.org> -validpgpkeys+=('474E22316ABF4785A88C6E8EA2C794A986419D8A') # Tom Stellard <tstel...@redhat.com> - -prepare() { - cd llvm-$pkgver.src - mkdir build - - # https://github.com/intel/intel-graphics-compiler/issues/204 - patch -Rp2 -i ../don-t-accept-nullptr-as-GEP-element-type.patch - - # Fixes Chromium error "*** stack smashing detected ***: terminated" - # (which also goes away with "--change-stack-guard-on-fork=disabled") - # https://reviews.llvm.org/D116589 - patch -Np2 -i ../don-t-override-__attribute__-no_stack_protector.patch - - # https://github.com/llvm/llvm-project/issues/53243 - # https://github.com/rust-lang/rust/issues/92869 - patch -Np2 -i ../don-t-move-DBG_VALUE-instructions.patch - - # Patches needed for ISPC for Xe only - patch -Np2 -i ../disable-A-B-A-B-and-BSWAP-in-InstCombine.patch - patch -Np2 -i ../disable-DIArgList-in-SPIR-V.patch -} - -build() { - cd llvm-$pkgver.src/build - - local cmake_args=( - -G Ninja - -DCMAKE_BUILD_TYPE=Release - -DCMAKE_INSTALL_PREFIX=/usr/lib/llvm13 - -DCMAKE_SKIP_RPATH=ON - -DLLVM_BINUTILS_INCDIR=/usr/include - -DLLVM_BUILD_LLVM_DYLIB=ON - -DLLVM_BUILD_TESTS=ON - -DLLVM_ENABLE_BINDINGS=OFF - -DLLVM_ENABLE_FFI=ON - -DLLVM_ENABLE_RTTI=ON - -DLLVM_HOST_TRIPLE=$CHOST - -DLLVM_INSTALL_UTILS=ON - -DLLVM_LINK_LLVM_DYLIB=ON - ) - cmake .. "${cmake_args[@]}" - ninja -} - -check() { - cd llvm-$pkgver.src/build - LD_LIBRARY_PATH=$PWD/lib ninja check -} - -package_llvm13() { - pkgdesc="Compiler infrastructure (LLVM 13)" - depends=('llvm13-libs' 'perl') - - cd llvm-$pkgver.src/build - - DESTDIR="$pkgdir" ninja install - - # The runtime library goes into llvm13-libs - mv -f "$pkgdir"/usr/lib/llvm13/lib/libLLVM-{13,$pkgver}.so "$srcdir/" - - install -Dm644 ../LICENSE.TXT "$pkgdir/usr/share/licenses/$pkgname/LICENSE" -} - -package_llvm13-libs() { - pkgdesc="LLVM 13 runtime libraries" - depends=('gcc-libs' 'zlib' 'libffi' 'libedit' 'ncurses' 'libxml2') - - install -d "$pkgdir/usr/lib/llvm13/lib" - cp -P "$srcdir"/libLLVM-{13,$pkgver}.so "$pkgdir/usr/lib/" - ln -s ../../libLLVM-13.so "$pkgdir/usr/lib/llvm13/lib/libLLVM-13.so" - ln -s ../../libLLVM-13.so "$pkgdir/usr/lib/llvm13/lib/libLLVM-$pkgver.so" - - install -Dm644 "$srcdir/llvm-$pkgver.src/LICENSE.TXT" \ - "$pkgdir/usr/share/licenses/$pkgname/LICENSE" -} - -# vim:set ts=2 sw=2 et: Copied: llvm13/repos/extra-x86_64/PKGBUILD (from rev 449852, llvm13/trunk/PKGBUILD) =================================================================== --- PKGBUILD (rev 0) +++ PKGBUILD 2022-07-04 05:56:02 UTC (rev 449853) @@ -0,0 +1,106 @@ +# Maintainer: Evangelos Foutras <evange...@foutrelis.com> +# Contributor: Jan "heftig" Steffens <jan.steff...@gmail.com> + +pkgname=('llvm13' 'llvm13-libs') +pkgver=13.0.1 +pkgrel=3 +arch=('x86_64') +url="https://llvm.org/" +license=('custom:Apache 2.0 with LLVM Exception') +makedepends=('cmake' 'ninja' 'libffi' 'libedit' 'ncurses' 'libxml2' + 'python') +options=('staticlibs' '!lto') # Getting thousands of test failures with LTO +_source_base=https://github.com/llvm/llvm-project/releases/download/llvmorg-$pkgver +source=($_source_base/llvm-$pkgver.src.tar.xz{,.sig} + don-t-accept-nullptr-as-GEP-element-type.patch + don-t-override-__attribute__-no_stack_protector.patch + don-t-move-DBG_VALUE-instructions.patch + disable-A-B-A-B-and-BSWAP-in-InstCombine.patch + disable-DIArgList-in-SPIR-V.patch) +sha256sums=('ec6b80d82c384acad2dc192903a6cf2cdbaffb889b84bfb98da9d71e630fc834' + 'SKIP' + 'a7e902a7612d0fdabe436a917468b043cc296bc89d8954bfc3126f737beb9ac4' + '9f0a4578b94eb8853b83af2f65e92705254b4b56d96f9a941714d174b932f465' + 'f7d69f84241416398fdb3df8bb44f9fae3c49d89889c7ffa3b37aa2e9d78f708' + '34cc0d79a30599cb2287b47b4e9a1a5bf03d57a1f8bb35be3fe976ffc4a604f6' + '8642da2d556092e4284873ba6ddc6c9a67841f42cc16f923bcd523e4b304a3ff') +validpgpkeys=('474E22316ABF4785A88C6E8EA2C794A986419D8A') # Tom Stellard <tstel...@redhat.com> + +prepare() { + cd llvm-$pkgver.src + mkdir build + + # https://github.com/intel/intel-graphics-compiler/issues/204 + patch -Rp2 -i ../don-t-accept-nullptr-as-GEP-element-type.patch + + # Fixes Chromium error "*** stack smashing detected ***: terminated" + # (which also goes away with "--change-stack-guard-on-fork=disabled") + # https://reviews.llvm.org/D116589 + patch -Np2 -i ../don-t-override-__attribute__-no_stack_protector.patch + + # https://github.com/llvm/llvm-project/issues/53243 + # https://github.com/rust-lang/rust/issues/92869 + patch -Np2 -i ../don-t-move-DBG_VALUE-instructions.patch + + # Patches needed for ISPC for Xe only + patch -Np2 -i ../disable-A-B-A-B-and-BSWAP-in-InstCombine.patch + patch -Np2 -i ../disable-DIArgList-in-SPIR-V.patch +} + +build() { + cd llvm-$pkgver.src/build + + local cmake_args=( + -G Ninja + -DCMAKE_BUILD_TYPE=Release + -DCMAKE_INSTALL_PREFIX=/usr/lib/llvm13 + -DCMAKE_SKIP_RPATH=ON + -DLLVM_BINUTILS_INCDIR=/usr/include + -DLLVM_BUILD_LLVM_DYLIB=ON + -DLLVM_BUILD_TESTS=ON + -DLLVM_ENABLE_BINDINGS=OFF + -DLLVM_ENABLE_FFI=ON + -DLLVM_ENABLE_RTTI=ON + -DLLVM_HOST_TRIPLE=$CHOST + -DLLVM_INSTALL_UTILS=ON + -DLLVM_LINK_LLVM_DYLIB=ON + ) + cmake .. "${cmake_args[@]}" + ninja +} + +check() { + cd llvm-$pkgver.src/build + LD_LIBRARY_PATH=$PWD/lib ninja check +} + +package_llvm13() { + pkgdesc="Compiler infrastructure (LLVM 13)" + depends=('llvm13-libs' 'perl') + + cd llvm-$pkgver.src/build + + DESTDIR="$pkgdir" ninja install + + # The runtime libraries go into llvm13-libs + mv -f "$pkgdir"/usr/lib/llvm13/lib/libLLVM-{13,$pkgver}.so "$srcdir/" + mv -f "$pkgdir"/usr/lib/llvm13/lib/LLVMgold.so "$srcdir/" + + install -Dm644 ../LICENSE.TXT "$pkgdir/usr/share/licenses/$pkgname/LICENSE" +} + +package_llvm13-libs() { + pkgdesc="LLVM 13 runtime libraries" + depends=('gcc-libs' 'zlib' 'libffi' 'libedit' 'ncurses' 'libxml2') + + install -d "$pkgdir/usr/lib/llvm13/lib" + cp -P "$srcdir"/libLLVM-{13,$pkgver}.so "$pkgdir/usr/lib/" + ln -s ../../libLLVM-13.so "$pkgdir/usr/lib/llvm13/lib/libLLVM-13.so" + ln -s ../../libLLVM-13.so "$pkgdir/usr/lib/llvm13/lib/libLLVM-$pkgver.so" + cp -P "$srcdir"/LLVMgold.so "$pkgdir/usr/lib/llvm13/lib/" + + install -Dm644 "$srcdir/llvm-$pkgver.src/LICENSE.TXT" \ + "$pkgdir/usr/share/licenses/$pkgname/LICENSE" +} + +# vim:set ts=2 sw=2 et: Deleted: disable-A-B-A-B-and-BSWAP-in-InstCombine.patch =================================================================== --- disable-A-B-A-B-and-BSWAP-in-InstCombine.patch 2022-07-04 05:55:52 UTC (rev 449852) +++ disable-A-B-A-B-and-BSWAP-in-InstCombine.patch 2022-07-04 05:56:02 UTC (rev 449853) @@ -1,52 +0,0 @@ -# This patch is needed for ISPC for Xe only - -# 1. Transformation of add to or is not safe for VC backend. -# 2. bswap intrinsics is not supported in VC backend yet. -diff --git a/llvm/lib/Transforms/InstCombine/InstCombineAddSub.cpp b/llvm/lib/Transforms/InstCombine/InstCombineAddSub.cpp -index d01a021bf3f4..bccce825a03d 100644 ---- a/llvm/lib/Transforms/InstCombine/InstCombineAddSub.cpp -+++ b/llvm/lib/Transforms/InstCombine/InstCombineAddSub.cpp -@@ -15,6 +15,7 @@ - #include "llvm/ADT/APInt.h" - #include "llvm/ADT/STLExtras.h" - #include "llvm/ADT/SmallVector.h" -+#include "llvm/ADT/Triple.h" - #include "llvm/Analysis/InstructionSimplify.h" - #include "llvm/Analysis/ValueTracking.h" - #include "llvm/IR/Constant.h" -@@ -1369,9 +1370,12 @@ Instruction *InstCombinerImpl::visitAdd(BinaryOperator &I) { - } - } - -- // A+B --> A|B iff A and B have no bits set in common. -- if (haveNoCommonBitsSet(LHS, RHS, DL, &AC, &I, &DT)) -- return BinaryOperator::CreateOr(LHS, RHS); -+ // Disable this transformation for ISPC SPIR-V -+ if (!Triple(I.getModule()->getTargetTriple()).isSPIR()) { -+ // A+B --> A|B iff A and B have no bits set in common. -+ if (haveNoCommonBitsSet(LHS, RHS, DL, &AC, &I, &DT)) -+ return BinaryOperator::CreateOr(LHS, RHS); -+ } - - // add (select X 0 (sub n A)) A --> select X A n - { -diff --git a/llvm/lib/Transforms/InstCombine/InstCombineAndOrXor.cpp b/llvm/lib/Transforms/InstCombine/InstCombineAndOrXor.cpp -index 120852c44474..8de55311ce3e 100644 ---- a/llvm/lib/Transforms/InstCombine/InstCombineAndOrXor.cpp -+++ b/llvm/lib/Transforms/InstCombine/InstCombineAndOrXor.cpp -@@ -2671,9 +2671,12 @@ Instruction *InstCombinerImpl::visitOr(BinaryOperator &I) { - if (Instruction *FoldedLogic = foldBinOpIntoSelectOrPhi(I)) - return FoldedLogic; - -- if (Instruction *BitOp = matchBSwapOrBitReverse(I, /*MatchBSwaps*/ true, -- /*MatchBitReversals*/ true)) -- return BitOp; -+ // Disable this transformation for ISPC SPIR-V -+ if (!Triple(I.getModule()->getTargetTriple()).isSPIR()) { -+ if (Instruction *BitOp = matchBSwapOrBitReverse(I, /*MatchBSwaps*/ true, -+ /*MatchBitReversals*/ true)) -+ return BitOp; -+ } - - if (Instruction *Funnel = matchFunnelShift(I, *this)) - return Funnel; Copied: llvm13/repos/extra-x86_64/disable-A-B-A-B-and-BSWAP-in-InstCombine.patch (from rev 449852, llvm13/trunk/disable-A-B-A-B-and-BSWAP-in-InstCombine.patch) =================================================================== --- disable-A-B-A-B-and-BSWAP-in-InstCombine.patch (rev 0) +++ disable-A-B-A-B-and-BSWAP-in-InstCombine.patch 2022-07-04 05:56:02 UTC (rev 449853) @@ -0,0 +1,52 @@ +# This patch is needed for ISPC for Xe only + +# 1. Transformation of add to or is not safe for VC backend. +# 2. bswap intrinsics is not supported in VC backend yet. +diff --git a/llvm/lib/Transforms/InstCombine/InstCombineAddSub.cpp b/llvm/lib/Transforms/InstCombine/InstCombineAddSub.cpp +index d01a021bf3f4..bccce825a03d 100644 +--- a/llvm/lib/Transforms/InstCombine/InstCombineAddSub.cpp ++++ b/llvm/lib/Transforms/InstCombine/InstCombineAddSub.cpp +@@ -15,6 +15,7 @@ + #include "llvm/ADT/APInt.h" + #include "llvm/ADT/STLExtras.h" + #include "llvm/ADT/SmallVector.h" ++#include "llvm/ADT/Triple.h" + #include "llvm/Analysis/InstructionSimplify.h" + #include "llvm/Analysis/ValueTracking.h" + #include "llvm/IR/Constant.h" +@@ -1369,9 +1370,12 @@ Instruction *InstCombinerImpl::visitAdd(BinaryOperator &I) { + } + } + +- // A+B --> A|B iff A and B have no bits set in common. +- if (haveNoCommonBitsSet(LHS, RHS, DL, &AC, &I, &DT)) +- return BinaryOperator::CreateOr(LHS, RHS); ++ // Disable this transformation for ISPC SPIR-V ++ if (!Triple(I.getModule()->getTargetTriple()).isSPIR()) { ++ // A+B --> A|B iff A and B have no bits set in common. ++ if (haveNoCommonBitsSet(LHS, RHS, DL, &AC, &I, &DT)) ++ return BinaryOperator::CreateOr(LHS, RHS); ++ } + + // add (select X 0 (sub n A)) A --> select X A n + { +diff --git a/llvm/lib/Transforms/InstCombine/InstCombineAndOrXor.cpp b/llvm/lib/Transforms/InstCombine/InstCombineAndOrXor.cpp +index 120852c44474..8de55311ce3e 100644 +--- a/llvm/lib/Transforms/InstCombine/InstCombineAndOrXor.cpp ++++ b/llvm/lib/Transforms/InstCombine/InstCombineAndOrXor.cpp +@@ -2671,9 +2671,12 @@ Instruction *InstCombinerImpl::visitOr(BinaryOperator &I) { + if (Instruction *FoldedLogic = foldBinOpIntoSelectOrPhi(I)) + return FoldedLogic; + +- if (Instruction *BitOp = matchBSwapOrBitReverse(I, /*MatchBSwaps*/ true, +- /*MatchBitReversals*/ true)) +- return BitOp; ++ // Disable this transformation for ISPC SPIR-V ++ if (!Triple(I.getModule()->getTargetTriple()).isSPIR()) { ++ if (Instruction *BitOp = matchBSwapOrBitReverse(I, /*MatchBSwaps*/ true, ++ /*MatchBitReversals*/ true)) ++ return BitOp; ++ } + + if (Instruction *Funnel = matchFunnelShift(I, *this)) + return Funnel; Deleted: disable-DIArgList-in-SPIR-V.patch =================================================================== --- disable-DIArgList-in-SPIR-V.patch 2022-07-04 05:55:52 UTC (rev 449852) +++ disable-DIArgList-in-SPIR-V.patch 2022-07-04 05:56:02 UTC (rev 449853) @@ -1,23 +0,0 @@ -# This patch is needed for ISPC for Xe only -# It disables using of DIArgList for dbg.val if SPIR-V target is used. -# It is needed till DIArgList is supported in SPIR-V Translator. -diff --git a/llvm/lib/Transforms/Utils/Local.cpp b/llvm/lib/Transforms/Utils/Local.cpp -index d03d76f57ca1..0b86e454df57 100644 ---- a/llvm/lib/Transforms/Utils/Local.cpp -+++ b/llvm/lib/Transforms/Utils/Local.cpp -@@ -1771,7 +1771,14 @@ void llvm::salvageDebugInfoForDbgValues( - } else if (isa<DbgValueInst>(DII) && - DII->getNumVariableLocationOps() + AdditionalValues.size() <= - MaxDebugArgs) { -- DII->addVariableLocationOps(AdditionalValues, SalvagedExpr); -+ if (!Triple(I.getModule()->getTargetTriple()).isSPIR()) { -+ DII->addVariableLocationOps(AdditionalValues, SalvagedExpr); -+ } else { -+ // Do not salvage using DIArgList for dbg.val fpr SPIR-V target, as it is -+ // not currently supported by SPIR-V Translator. -+ Value *Undef = UndefValue::get(I.getOperand(0)->getType()); -+ DII->replaceVariableLocationOp(I.getOperand(0), Undef); -+ } - } else { - // Do not salvage using DIArgList for dbg.addr/dbg.declare, as it is - // currently only valid for stack value expressions. Copied: llvm13/repos/extra-x86_64/disable-DIArgList-in-SPIR-V.patch (from rev 449852, llvm13/trunk/disable-DIArgList-in-SPIR-V.patch) =================================================================== --- disable-DIArgList-in-SPIR-V.patch (rev 0) +++ disable-DIArgList-in-SPIR-V.patch 2022-07-04 05:56:02 UTC (rev 449853) @@ -0,0 +1,23 @@ +# This patch is needed for ISPC for Xe only +# It disables using of DIArgList for dbg.val if SPIR-V target is used. +# It is needed till DIArgList is supported in SPIR-V Translator. +diff --git a/llvm/lib/Transforms/Utils/Local.cpp b/llvm/lib/Transforms/Utils/Local.cpp +index d03d76f57ca1..0b86e454df57 100644 +--- a/llvm/lib/Transforms/Utils/Local.cpp ++++ b/llvm/lib/Transforms/Utils/Local.cpp +@@ -1771,7 +1771,14 @@ void llvm::salvageDebugInfoForDbgValues( + } else if (isa<DbgValueInst>(DII) && + DII->getNumVariableLocationOps() + AdditionalValues.size() <= + MaxDebugArgs) { +- DII->addVariableLocationOps(AdditionalValues, SalvagedExpr); ++ if (!Triple(I.getModule()->getTargetTriple()).isSPIR()) { ++ DII->addVariableLocationOps(AdditionalValues, SalvagedExpr); ++ } else { ++ // Do not salvage using DIArgList for dbg.val fpr SPIR-V target, as it is ++ // not currently supported by SPIR-V Translator. ++ Value *Undef = UndefValue::get(I.getOperand(0)->getType()); ++ DII->replaceVariableLocationOp(I.getOperand(0), Undef); ++ } + } else { + // Do not salvage using DIArgList for dbg.addr/dbg.declare, as it is + // currently only valid for stack value expressions. Deleted: don-t-accept-nullptr-as-GEP-element-type.patch =================================================================== --- don-t-accept-nullptr-as-GEP-element-type.patch 2022-07-04 05:55:52 UTC (rev 449852) +++ don-t-accept-nullptr-as-GEP-element-type.patch 2022-07-04 05:56:02 UTC (rev 449853) @@ -1,63 +0,0 @@ -From b00cff56cfb15cbfa74cb512c9cee1c402cce55b Mon Sep 17 00:00:00 2001 -From: Nikita Popov <nikita....@gmail.com> -Date: Thu, 8 Jul 2021 20:56:05 +0200 -Subject: [PATCH] Reapply [IR] Don't accept nullptr as GEP element type - -Reapply after fixing another occurrence in lldb that was relying -on this in the preceding commit. - ------ - -GetElementPtrInst::Create() (and IRBuilder methods based on it) -currently accept nullptr as the element type, and will fetch the -element type from the pointer in that case. Remove this fallback, -as it is incompatible with opaque pointers. I've removed a handful -of leftover calls using this behavior as a preliminary step. - -Out-of-tree code affected by this change should either pass a proper -type, or can temporarily explicitly call getPointerElementType(), -if the newly added assertion is encountered. - -Differential Revision: https://reviews.llvm.org/D105653 ---- - llvm/include/llvm/IR/Instructions.h | 20 ++++++-------------- - 1 file changed, 6 insertions(+), 14 deletions(-) - -diff --git a/llvm/include/llvm/IR/Instructions.h b/llvm/include/llvm/IR/Instructions.h -index a5cebf0a4626..0c43a56daa33 100644 ---- a/llvm/include/llvm/IR/Instructions.h -+++ b/llvm/include/llvm/IR/Instructions.h -@@ -956,13 +956,9 @@ public: - const Twine &NameStr = "", - Instruction *InsertBefore = nullptr) { - unsigned Values = 1 + unsigned(IdxList.size()); -- if (!PointeeType) { -- PointeeType = -- cast<PointerType>(Ptr->getType()->getScalarType())->getElementType(); -- } else { -- assert(cast<PointerType>(Ptr->getType()->getScalarType()) -- ->isOpaqueOrPointeeTypeMatches(PointeeType)); -- } -+ assert(PointeeType && "Must specify element type"); -+ assert(cast<PointerType>(Ptr->getType()->getScalarType()) -+ ->isOpaqueOrPointeeTypeMatches(PointeeType)); - return new (Values) GetElementPtrInst(PointeeType, Ptr, IdxList, Values, - NameStr, InsertBefore); - } -@@ -972,13 +968,9 @@ public: - const Twine &NameStr, - BasicBlock *InsertAtEnd) { - unsigned Values = 1 + unsigned(IdxList.size()); -- if (!PointeeType) { -- PointeeType = -- cast<PointerType>(Ptr->getType()->getScalarType())->getElementType(); -- } else { -- assert(cast<PointerType>(Ptr->getType()->getScalarType()) -- ->isOpaqueOrPointeeTypeMatches(PointeeType)); -- } -+ assert(PointeeType && "Must specify element type"); -+ assert(cast<PointerType>(Ptr->getType()->getScalarType()) -+ ->isOpaqueOrPointeeTypeMatches(PointeeType)); - return new (Values) GetElementPtrInst(PointeeType, Ptr, IdxList, Values, - NameStr, InsertAtEnd); - } Copied: llvm13/repos/extra-x86_64/don-t-accept-nullptr-as-GEP-element-type.patch (from rev 449852, llvm13/trunk/don-t-accept-nullptr-as-GEP-element-type.patch) =================================================================== --- don-t-accept-nullptr-as-GEP-element-type.patch (rev 0) +++ don-t-accept-nullptr-as-GEP-element-type.patch 2022-07-04 05:56:02 UTC (rev 449853) @@ -0,0 +1,63 @@ +From b00cff56cfb15cbfa74cb512c9cee1c402cce55b Mon Sep 17 00:00:00 2001 +From: Nikita Popov <nikita....@gmail.com> +Date: Thu, 8 Jul 2021 20:56:05 +0200 +Subject: [PATCH] Reapply [IR] Don't accept nullptr as GEP element type + +Reapply after fixing another occurrence in lldb that was relying +on this in the preceding commit. + +----- + +GetElementPtrInst::Create() (and IRBuilder methods based on it) +currently accept nullptr as the element type, and will fetch the +element type from the pointer in that case. Remove this fallback, +as it is incompatible with opaque pointers. I've removed a handful +of leftover calls using this behavior as a preliminary step. + +Out-of-tree code affected by this change should either pass a proper +type, or can temporarily explicitly call getPointerElementType(), +if the newly added assertion is encountered. + +Differential Revision: https://reviews.llvm.org/D105653 +--- + llvm/include/llvm/IR/Instructions.h | 20 ++++++-------------- + 1 file changed, 6 insertions(+), 14 deletions(-) + +diff --git a/llvm/include/llvm/IR/Instructions.h b/llvm/include/llvm/IR/Instructions.h +index a5cebf0a4626..0c43a56daa33 100644 +--- a/llvm/include/llvm/IR/Instructions.h ++++ b/llvm/include/llvm/IR/Instructions.h +@@ -956,13 +956,9 @@ public: + const Twine &NameStr = "", + Instruction *InsertBefore = nullptr) { + unsigned Values = 1 + unsigned(IdxList.size()); +- if (!PointeeType) { +- PointeeType = +- cast<PointerType>(Ptr->getType()->getScalarType())->getElementType(); +- } else { +- assert(cast<PointerType>(Ptr->getType()->getScalarType()) +- ->isOpaqueOrPointeeTypeMatches(PointeeType)); +- } ++ assert(PointeeType && "Must specify element type"); ++ assert(cast<PointerType>(Ptr->getType()->getScalarType()) ++ ->isOpaqueOrPointeeTypeMatches(PointeeType)); + return new (Values) GetElementPtrInst(PointeeType, Ptr, IdxList, Values, + NameStr, InsertBefore); + } +@@ -972,13 +968,9 @@ public: + const Twine &NameStr, + BasicBlock *InsertAtEnd) { + unsigned Values = 1 + unsigned(IdxList.size()); +- if (!PointeeType) { +- PointeeType = +- cast<PointerType>(Ptr->getType()->getScalarType())->getElementType(); +- } else { +- assert(cast<PointerType>(Ptr->getType()->getScalarType()) +- ->isOpaqueOrPointeeTypeMatches(PointeeType)); +- } ++ assert(PointeeType && "Must specify element type"); ++ assert(cast<PointerType>(Ptr->getType()->getScalarType()) ++ ->isOpaqueOrPointeeTypeMatches(PointeeType)); + return new (Values) GetElementPtrInst(PointeeType, Ptr, IdxList, Values, + NameStr, InsertAtEnd); + } Deleted: don-t-move-DBG_VALUE-instructions.patch =================================================================== --- don-t-move-DBG_VALUE-instructions.patch 2022-07-04 05:55:52 UTC (rev 449852) +++ don-t-move-DBG_VALUE-instructions.patch 2022-07-04 05:56:02 UTC (rev 449853) @@ -1,91 +0,0 @@ -From e7c9a6cae09d99388d8384ca7c0fb5b24b353975 Mon Sep 17 00:00:00 2001 -From: Nikita Popov <npo...@redhat.com> -Date: Mon, 17 Jan 2022 15:48:01 +0100 -Subject: [PATCH] [SDAG] Don't move DBG_VALUE instructions after insertion - point during scheduling (PR53243) - -EmitSchedule() shouldn't be touching instructions after the provided -insertion point. The change introduced in D83561 performs a scan to -the end of the block, and thus may move unrelated instructions. In -particular, this ends up moving instructions that have been produced -by FastISel and will later be deleted. Moving them means that more -instructions than intended are removed. - -Fix this by stopping the iteration when the insertion point is -reached. - -Fixes https://github.com/llvm/llvm-project/issues/53243. - -Differential Revision: https://reviews.llvm.org/D117489 ---- - .../SelectionDAG/ScheduleDAGSDNodes.cpp | 7 ++-- - .../CodeGen/X86/pr53243-tail-call-fastisel.ll | 39 +++++++++++++++++++ - 2 files changed, 43 insertions(+), 3 deletions(-) - create mode 100644 llvm/test/CodeGen/X86/pr53243-tail-call-fastisel.ll - -diff --git a/llvm/lib/CodeGen/SelectionDAG/ScheduleDAGSDNodes.cpp b/llvm/lib/CodeGen/SelectionDAG/ScheduleDAGSDNodes.cpp -index bec240d6c4d4..403f34573899 100644 ---- a/llvm/lib/CodeGen/SelectionDAG/ScheduleDAGSDNodes.cpp -+++ b/llvm/lib/CodeGen/SelectionDAG/ScheduleDAGSDNodes.cpp -@@ -1057,12 +1057,13 @@ EmitSchedule(MachineBasicBlock::iterator &InsertPos) { - "first terminator cannot be a debug value"); - for (MachineInstr &MI : make_early_inc_range( - make_range(std::next(FirstTerm), InsertBB->end()))) { -+ // Only scan up to insertion point. -+ if (&MI == InsertPos) -+ break; -+ - if (!MI.isDebugValue()) - continue; - -- if (&MI == InsertPos) -- InsertPos = std::prev(InsertPos->getIterator()); -- - // The DBG_VALUE was referencing a value produced by a terminator. By - // moving the DBG_VALUE, the referenced value also needs invalidating. - MI.getOperand(0).ChangeToRegister(0, false); -diff --git a/llvm/test/CodeGen/X86/pr53243-tail-call-fastisel.ll b/llvm/test/CodeGen/X86/pr53243-tail-call-fastisel.ll -new file mode 100644 -index 000000000000..333eff8fb008 ---- /dev/null -+++ b/llvm/test/CodeGen/X86/pr53243-tail-call-fastisel.ll -@@ -0,0 +1,39 @@ -+; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py -+; RUN: llc -O0 -fast-isel -mtriple=x86_64-- < %s | FileCheck %s -+ -+define void @test() { -+; CHECK-LABEL: test: -+; CHECK: # %bb.0: -+; CHECK-NEXT: jmp set_state@PLT # TAILCALL -+ tail call void @set_state() -+ call void @llvm.dbg.value(metadata i64 0, metadata !10, metadata !DIExpression()), !dbg !16 -+ ret void -+} -+ -+declare void @set_state() -+ -+; Function Attrs: nofree nosync nounwind readnone speculatable willreturn -+declare void @llvm.dbg.value(metadata, metadata, metadata) #0 -+ -+attributes #0 = { nofree nosync nounwind readnone speculatable willreturn } -+ -+!llvm.module.flags = !{!0} -+!llvm.dbg.cu = !{!1} -+ -+!0 = !{i32 2, !"Debug Info Version", i32 3} -+!1 = distinct !DICompileUnit(language: DW_LANG_Rust, file: !2, producer: "clang LLVM (rustc version 1.60.0-nightly (ec4bcaac4 2022-01-15))", isOptimized: true, runtimeVersion: 0, emissionKind: FullDebug, enums: !3) -+!2 = !DIFile(filename: "src/lib.rs/@/bug.63e521cd-cgu.0", directory: "/tmp/rust-bug") -+!3 = !{!4} -+!4 = !DICompositeType(tag: DW_TAG_enumeration_type, name: "Option", file: !5, baseType: !6, size: 8, align: 8, flags: DIFlagEnumClass, elements: !7) -+!5 = !DIFile(filename: "<unknown>", directory: "") -+!6 = !DIBasicType(name: "u8", size: 8, encoding: DW_ATE_unsigned) -+!7 = !{!8, !9} -+!8 = !DIEnumerator(name: "None", value: 0) -+!9 = !DIEnumerator(name: "Some", value: 1) -+!10 = !DILocalVariable(name: "msg", arg: 2, scope: !11, file: !12, line: 689, type: !6) -+!11 = distinct !DISubprogram(name: "expect<()>", linkageName: "_ZN4core6option15Option$LT$T$GT$6expect17h9a574c18f194c213E", scope: !4, file: !12, line: 689, type: !13, scopeLine: 689, flags: DIFlagPrototyped, spFlags: DISPFlagLocalToUnit | DISPFlagDefinition | DISPFlagOptimized, unit: !1, templateParams: !15, retainedNodes: !15) -+!12 = !DIFile(filename: "/rustc/ec4bcaac450279b029f3480b8b8f1b82ab36a5eb/library/core/src/option.rs", directory: "", checksumkind: CSK_MD5, checksum: "4120c8557937a0772190a676ec193800") -+!13 = !DISubroutineType(types: !14) -+!14 = !{null, !4} -+!15 = !{} -+!16 = !DILocation(line: 0, scope: !11) Copied: llvm13/repos/extra-x86_64/don-t-move-DBG_VALUE-instructions.patch (from rev 449852, llvm13/trunk/don-t-move-DBG_VALUE-instructions.patch) =================================================================== --- don-t-move-DBG_VALUE-instructions.patch (rev 0) +++ don-t-move-DBG_VALUE-instructions.patch 2022-07-04 05:56:02 UTC (rev 449853) @@ -0,0 +1,91 @@ +From e7c9a6cae09d99388d8384ca7c0fb5b24b353975 Mon Sep 17 00:00:00 2001 +From: Nikita Popov <npo...@redhat.com> +Date: Mon, 17 Jan 2022 15:48:01 +0100 +Subject: [PATCH] [SDAG] Don't move DBG_VALUE instructions after insertion + point during scheduling (PR53243) + +EmitSchedule() shouldn't be touching instructions after the provided +insertion point. The change introduced in D83561 performs a scan to +the end of the block, and thus may move unrelated instructions. In +particular, this ends up moving instructions that have been produced +by FastISel and will later be deleted. Moving them means that more +instructions than intended are removed. + +Fix this by stopping the iteration when the insertion point is +reached. + +Fixes https://github.com/llvm/llvm-project/issues/53243. + +Differential Revision: https://reviews.llvm.org/D117489 +--- + .../SelectionDAG/ScheduleDAGSDNodes.cpp | 7 ++-- + .../CodeGen/X86/pr53243-tail-call-fastisel.ll | 39 +++++++++++++++++++ + 2 files changed, 43 insertions(+), 3 deletions(-) + create mode 100644 llvm/test/CodeGen/X86/pr53243-tail-call-fastisel.ll + +diff --git a/llvm/lib/CodeGen/SelectionDAG/ScheduleDAGSDNodes.cpp b/llvm/lib/CodeGen/SelectionDAG/ScheduleDAGSDNodes.cpp +index bec240d6c4d4..403f34573899 100644 +--- a/llvm/lib/CodeGen/SelectionDAG/ScheduleDAGSDNodes.cpp ++++ b/llvm/lib/CodeGen/SelectionDAG/ScheduleDAGSDNodes.cpp +@@ -1057,12 +1057,13 @@ EmitSchedule(MachineBasicBlock::iterator &InsertPos) { + "first terminator cannot be a debug value"); + for (MachineInstr &MI : make_early_inc_range( + make_range(std::next(FirstTerm), InsertBB->end()))) { ++ // Only scan up to insertion point. ++ if (&MI == InsertPos) ++ break; ++ + if (!MI.isDebugValue()) + continue; + +- if (&MI == InsertPos) +- InsertPos = std::prev(InsertPos->getIterator()); +- + // The DBG_VALUE was referencing a value produced by a terminator. By + // moving the DBG_VALUE, the referenced value also needs invalidating. + MI.getOperand(0).ChangeToRegister(0, false); +diff --git a/llvm/test/CodeGen/X86/pr53243-tail-call-fastisel.ll b/llvm/test/CodeGen/X86/pr53243-tail-call-fastisel.ll +new file mode 100644 +index 000000000000..333eff8fb008 +--- /dev/null ++++ b/llvm/test/CodeGen/X86/pr53243-tail-call-fastisel.ll +@@ -0,0 +1,39 @@ ++; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py ++; RUN: llc -O0 -fast-isel -mtriple=x86_64-- < %s | FileCheck %s ++ ++define void @test() { ++; CHECK-LABEL: test: ++; CHECK: # %bb.0: ++; CHECK-NEXT: jmp set_state@PLT # TAILCALL ++ tail call void @set_state() ++ call void @llvm.dbg.value(metadata i64 0, metadata !10, metadata !DIExpression()), !dbg !16 ++ ret void ++} ++ ++declare void @set_state() ++ ++; Function Attrs: nofree nosync nounwind readnone speculatable willreturn ++declare void @llvm.dbg.value(metadata, metadata, metadata) #0 ++ ++attributes #0 = { nofree nosync nounwind readnone speculatable willreturn } ++ ++!llvm.module.flags = !{!0} ++!llvm.dbg.cu = !{!1} ++ ++!0 = !{i32 2, !"Debug Info Version", i32 3} ++!1 = distinct !DICompileUnit(language: DW_LANG_Rust, file: !2, producer: "clang LLVM (rustc version 1.60.0-nightly (ec4bcaac4 2022-01-15))", isOptimized: true, runtimeVersion: 0, emissionKind: FullDebug, enums: !3) ++!2 = !DIFile(filename: "src/lib.rs/@/bug.63e521cd-cgu.0", directory: "/tmp/rust-bug") ++!3 = !{!4} ++!4 = !DICompositeType(tag: DW_TAG_enumeration_type, name: "Option", file: !5, baseType: !6, size: 8, align: 8, flags: DIFlagEnumClass, elements: !7) ++!5 = !DIFile(filename: "<unknown>", directory: "") ++!6 = !DIBasicType(name: "u8", size: 8, encoding: DW_ATE_unsigned) ++!7 = !{!8, !9} ++!8 = !DIEnumerator(name: "None", value: 0) ++!9 = !DIEnumerator(name: "Some", value: 1) ++!10 = !DILocalVariable(name: "msg", arg: 2, scope: !11, file: !12, line: 689, type: !6) ++!11 = distinct !DISubprogram(name: "expect<()>", linkageName: "_ZN4core6option15Option$LT$T$GT$6expect17h9a574c18f194c213E", scope: !4, file: !12, line: 689, type: !13, scopeLine: 689, flags: DIFlagPrototyped, spFlags: DISPFlagLocalToUnit | DISPFlagDefinition | DISPFlagOptimized, unit: !1, templateParams: !15, retainedNodes: !15) ++!12 = !DIFile(filename: "/rustc/ec4bcaac450279b029f3480b8b8f1b82ab36a5eb/library/core/src/option.rs", directory: "", checksumkind: CSK_MD5, checksum: "4120c8557937a0772190a676ec193800") ++!13 = !DISubroutineType(types: !14) ++!14 = !{null, !4} ++!15 = !{} ++!16 = !DILocation(line: 0, scope: !11) Deleted: don-t-override-__attribute__-no_stack_protector.patch =================================================================== --- don-t-override-__attribute__-no_stack_protector.patch 2022-07-04 05:55:52 UTC (rev 449852) +++ don-t-override-__attribute__-no_stack_protector.patch 2022-07-04 05:56:02 UTC (rev 449853) @@ -1,540 +0,0 @@ -From 4a7c9b7d6f4a183fef8f43aef004ec865c37bbd8 Mon Sep 17 00:00:00 2001 -From: Hans Wennborg <h...@chromium.org> -Date: Thu, 13 Jan 2022 11:31:11 +0100 -Subject: [PATCH 1/2] Simplify llvm/test/Transforms/Inline/inline_ssp.ll (NFC) - -The nounwind and uwtable attributes were just cluttering up the test. -Using regexes to give symbolic names to the attribute lists make the -test more readable. - -This is pre-committing parts of D116589. - -(cherry picked from commit 2eb7d8d749997e5f3048d39201a4d38b6b8d6455) ---- - llvm/test/Transforms/Inline/inline_ssp.ll | 81 +++++++++++------------ - 1 file changed, 40 insertions(+), 41 deletions(-) - -diff --git a/llvm/test/Transforms/Inline/inline_ssp.ll b/llvm/test/Transforms/Inline/inline_ssp.ll -index 2bf93d322842..ccfe93453159 100644 ---- a/llvm/test/Transforms/Inline/inline_ssp.ll -+++ b/llvm/test/Transforms/Inline/inline_ssp.ll -@@ -12,150 +12,149 @@ - ; propagated correctly. The caller should have its SSP attribute set as: - ; strictest(caller-ssp-attr, callee-ssp-attr), where strictness is ordered as: - ; sspreq > sspstrong > ssp > [no ssp] --define internal void @fun_sspreq() nounwind sspreq uwtable { -+define internal void @fun_sspreq() sspreq { - entry: - %call = call i32 (i8*, ...) @printf(i8* getelementptr inbounds ([12 x i8], [12 x i8]* @.str3, i32 0, i32 0)) - ret void - } - --define internal void @fun_sspstrong() nounwind sspstrong uwtable { -+define internal void @fun_sspstrong() sspstrong { - entry: - %call = call i32 (i8*, ...) @printf(i8* getelementptr inbounds ([15 x i8], [15 x i8]* @.str2, i32 0, i32 0)) - ret void - } - --define internal void @fun_ssp() nounwind ssp uwtable { -+define internal void @fun_ssp() ssp { - entry: - %call = call i32 (i8*, ...) @printf(i8* getelementptr inbounds ([9 x i8], [9 x i8]* @.str1, i32 0, i32 0)) - ret void - } - --define internal void @fun_nossp() nounwind uwtable { -+define internal void @fun_nossp() { - entry: - %call = call i32 (i8*, ...) @printf(i8* getelementptr inbounds ([11 x i8], [11 x i8]* @.str, i32 0, i32 0)) - ret void - } - --; Tests start below -+; Tests start below. - --define void @inline_req_req() nounwind sspreq uwtable { -+define void @inline_req_req() sspreq { - entry: --; CHECK: @inline_req_req() #0 -+; CHECK: @inline_req_req() #[[SSPREQ:[0-9]]] - call void @fun_sspreq() - ret void - } - --define void @inline_req_strong() nounwind sspstrong uwtable { -+define void @inline_req_strong() sspstrong { - entry: --; CHECK: @inline_req_strong() #0 -+; CHECK: @inline_req_strong() #[[SSPREQ]] - call void @fun_sspreq() - ret void - } - --define void @inline_req_ssp() nounwind ssp uwtable { -+define void @inline_req_ssp() ssp { - entry: --; CHECK: @inline_req_ssp() #0 -+; CHECK: @inline_req_ssp() #[[SSPREQ]] - call void @fun_sspreq() - ret void - } - --define void @inline_req_nossp() nounwind uwtable { -+define void @inline_req_nossp() { - entry: --; CHECK: @inline_req_nossp() #3 -+; CHECK: @inline_req_nossp() { - call void @fun_sspreq() - ret void - } - --define void @inline_strong_req() nounwind sspreq uwtable { -+define void @inline_strong_req() sspreq { - entry: --; CHECK: @inline_strong_req() #0 -+; CHECK: @inline_strong_req() #[[SSPREQ]] - call void @fun_sspstrong() - ret void - } - - --define void @inline_strong_strong() nounwind sspstrong uwtable { -+define void @inline_strong_strong() sspstrong { - entry: --; CHECK: @inline_strong_strong() #1 -+; CHECK: @inline_strong_strong() #[[SSPSTRONG:[0-9]]] - call void @fun_sspstrong() - ret void - } - --define void @inline_strong_ssp() nounwind ssp uwtable { -+define void @inline_strong_ssp() ssp { - entry: --; CHECK: @inline_strong_ssp() #1 -+; CHECK: @inline_strong_ssp() #[[SSPSTRONG]] - call void @fun_sspstrong() - ret void - } - --define void @inline_strong_nossp() nounwind uwtable { -+define void @inline_strong_nossp() { - entry: --; CHECK: @inline_strong_nossp() #3 -+; CHECK: @inline_strong_nossp() { - call void @fun_sspstrong() - ret void - } - --define void @inline_ssp_req() nounwind sspreq uwtable { -+define void @inline_ssp_req() sspreq { - entry: --; CHECK: @inline_ssp_req() #0 -+; CHECK: @inline_ssp_req() #[[SSPREQ]] - call void @fun_ssp() - ret void - } - - --define void @inline_ssp_strong() nounwind sspstrong uwtable { -+define void @inline_ssp_strong() sspstrong { - entry: --; CHECK: @inline_ssp_strong() #1 -+; CHECK: @inline_ssp_strong() #[[SSPSTRONG]] - call void @fun_ssp() - ret void - } - --define void @inline_ssp_ssp() nounwind ssp uwtable { -+define void @inline_ssp_ssp() ssp { - entry: --; CHECK: @inline_ssp_ssp() #2 -+; CHECK: @inline_ssp_ssp() #[[SSP:[0-9]]] - call void @fun_ssp() - ret void - } - --define void @inline_ssp_nossp() nounwind uwtable { -+define void @inline_ssp_nossp() { - entry: --; CHECK: @inline_ssp_nossp() #3 -+; CHECK: @inline_ssp_nossp() { - call void @fun_ssp() - ret void - } - --define void @inline_nossp_req() nounwind uwtable sspreq { -+define void @inline_nossp_req() sspreq { - entry: --; CHECK: @inline_nossp_req() #0 -+; CHECK: @inline_nossp_req() #[[SSPREQ]] - call void @fun_nossp() - ret void - } - - --define void @inline_nossp_strong() nounwind sspstrong uwtable { -+define void @inline_nossp_strong() sspstrong { - entry: --; CHECK: @inline_nossp_strong() #1 -+; CHECK: @inline_nossp_strong() #[[SSPSTRONG]] - call void @fun_nossp() - ret void - } - --define void @inline_nossp_ssp() nounwind ssp uwtable { -+define void @inline_nossp_ssp() ssp { - entry: --; CHECK: @inline_nossp_ssp() #2 -+; CHECK: @inline_nossp_ssp() #[[SSP]] - call void @fun_nossp() - ret void - } - --define void @inline_nossp_nossp() nounwind uwtable { -+define void @inline_nossp_nossp() { - entry: --; CHECK: @inline_nossp_nossp() #3 -+; CHECK: @inline_nossp_nossp() { - call void @fun_nossp() - ret void - } - - declare i32 @printf(i8*, ...) - --; CHECK: attributes #0 = { nounwind sspreq uwtable } --; CHECK: attributes #1 = { nounwind sspstrong uwtable } --; CHECK: attributes #2 = { nounwind ssp uwtable } --; CHECK: attributes #3 = { nounwind uwtable } -+; CHECK: attributes #[[SSPREQ]] = { sspreq } -+; CHECK: attributes #[[SSPSTRONG]] = { sspstrong } -+; CHECK: attributes #[[SSP]] = { ssp } - -From b52296ecaa3878648ceeb3aa39df05dc71e44597 Mon Sep 17 00:00:00 2001 -From: Hans Wennborg <h...@chromium.org> -Date: Mon, 3 Jan 2022 18:03:43 +0100 -Subject: [PATCH 2/2] Don't override __attribute__((no_stack_protector)) by - inlining (PR52886) - -Since 26c6a3e736d3, LLVM's inliner will "upgrade" the caller's stack protector -attribute based on the callee. This lead to surprising results with Clang's -no_stack_protector attribute added in 4fbf84c1732f (D46300). Consider the -following code compiled with clang -fstack-protector-strong -Os -(https://godbolt.org/z/7s3rW7a1q). - - extern void h(int* p); - - inline __attribute__((always_inline)) int g() { - return 0; - } - - int __attribute__((__no_stack_protector__)) f() { - int a[1]; - h(a); - return g(); - } - -LLVM will inline g() into f(), and f() would get a stack protector, against the -users explicit wishes, potentially breaking the program e.g. if h() changes the -value of the stack cookie. That's a miscompile. - -More recently, bc044a88ee3c (D91816) addressed this problem by preventing -inlining when the stack protector is disabled in the caller and enabled in the -callee or vice versa. However, the problem remained if the callee is marked -always_inline as in the example above. This affected users, see e.g. -http://crbug.com/1274129 and http://llvm.org/pr52886. - -One way to fix this would be to prevent inlining also in the always_inline -case. Despite the name, always_inline does not guarantee inlining, so this -would be legal but potentially surprising to users. - -However, I think the better fix is to not enable the stack protector in a -caller based on the callee. The motivation for the old behaviour is unclear, it -seems counter-intuitive, and causes real problems as we've seen. - -This commit implements that fix, which means in the example above, g() gets -inlined into f() (also without always_inline), and f() is emitted without stack -protector. I think that matches most developers' expectations, and that's also -what GCC does. - -Another effect of this change is that a no_stack_protector function can now be -inlined into a stack protected function, e.g. (https://godbolt.org/z/hafP6W856): - - extern void h(int* p); - - inline int __attribute__((__no_stack_protector__)) __attribute__((always_inline)) g() { - return 0; - } - - int f() { - int a[1]; - h(a); - return g(); - } - -I think that's fine. Such code would be unusual since no_stack_protector is -normally applied to a program entry point which sets up the stack canary. And -even if such code exists, inlining doesn't change the semantics: there is still -no stack cookie setup/check around entry/exit of the g() code region, but there -may be in the surrounding context, as there was before inlining. This also -matches GCC. - -See also the discussion at https://gcc.gnu.org/bugzilla/show_bug.cgi?id=94722 - -Differential revision: https://reviews.llvm.org/D116589 - -(cherry picked from commit 2bc57d85ebf244f19a3046295b58eb8c667f947d) ---- - llvm/docs/LangRef.rst | 26 +++++------ - llvm/lib/Analysis/InlineCost.cpp | 9 ---- - llvm/lib/IR/Attributes.cpp | 6 +++ - llvm/test/ThinLTO/X86/nossp.ll | 23 ++++++---- - llvm/test/Transforms/Inline/inline_nossp.ll | 50 --------------------- - llvm/test/Transforms/Inline/inline_ssp.ll | 19 +++++++- - 6 files changed, 48 insertions(+), 85 deletions(-) - delete mode 100644 llvm/test/Transforms/Inline/inline_nossp.ll - -diff --git a/llvm/docs/LangRef.rst b/llvm/docs/LangRef.rst -index 36e09355e485..69393eba3906 100644 ---- a/llvm/docs/LangRef.rst -+++ b/llvm/docs/LangRef.rst -@@ -1965,11 +1965,9 @@ example: - Variables that are identified as requiring a protector will be arranged - on the stack such that they are adjacent to the stack protector guard. - -- A function with the ``ssp`` attribute but without the ``alwaysinline`` -- attribute cannot be inlined into a function without a -- ``ssp/sspreq/sspstrong`` attribute. If inlined, the caller will get the -- ``ssp`` attribute. ``call``, ``invoke``, and ``callbr`` instructions with -- the ``alwaysinline`` attribute force inlining. -+ If a function with an ``ssp`` attribute is inlined into a calling function, -+ the attribute is not carried over to the calling function. -+ - ``sspstrong`` - This attribute indicates that the function should emit a stack smashing - protector. This attribute causes a strong heuristic to be used when -@@ -1994,12 +1992,10 @@ example: - - This overrides the ``ssp`` function attribute. - -- A function with the ``sspstrong`` attribute but without the -- ``alwaysinline`` attribute cannot be inlined into a function without a -- ``ssp/sspstrong/sspreq`` attribute. If inlined, the caller will get the -- ``sspstrong`` attribute unless the ``sspreq`` attribute exists. ``call``, -- ``invoke``, and ``callbr`` instructions with the ``alwaysinline`` attribute -- force inlining. -+ If a function with an ``sspstrong`` attribute is inlined into a calling -+ function which has an ``ssp`` attribute, the calling function's attribute -+ will be upgraded to ``sspstrong``. -+ - ``sspreq`` - This attribute indicates that the function should *always* emit a stack - smashing protector. This overrides the ``ssp`` and ``sspstrong`` function -@@ -2016,11 +2012,9 @@ example: - #. Variables that have had their address taken are 3rd closest to the - protector. - -- A function with the ``sspreq`` attribute but without the ``alwaysinline`` -- attribute cannot be inlined into a function without a -- ``ssp/sspstrong/sspreq`` attribute. If inlined, the caller will get the -- ``sspreq`` attribute. ``call``, ``invoke``, and ``callbr`` instructions -- with the ``alwaysinline`` attribute force inlining. -+ If a function with an ``sspreq`` attribute is inlined into a calling -+ function which has an ``ssp`` or ``sspstrong`` attribute, the calling -+ function's attribute will be upgraded to ``sspreq``. - - ``strictfp`` - This attribute indicates that the function was called from a scope that -diff --git a/llvm/lib/Analysis/InlineCost.cpp b/llvm/lib/Analysis/InlineCost.cpp -index e8f79a28a8e8..1e68ec8ff7d6 100644 ---- a/llvm/lib/Analysis/InlineCost.cpp -+++ b/llvm/lib/Analysis/InlineCost.cpp -@@ -2823,15 +2823,6 @@ Optional<InlineResult> llvm::getAttributeBasedInliningDecision( - if (Call.isNoInline()) - return InlineResult::failure("noinline call site attribute"); - -- // Don't inline functions if one does not have any stack protector attribute -- // but the other does. -- if (Caller->hasStackProtectorFnAttr() && !Callee->hasStackProtectorFnAttr()) -- return InlineResult::failure( -- "stack protected caller but callee requested no stack protector"); -- if (Callee->hasStackProtectorFnAttr() && !Caller->hasStackProtectorFnAttr()) -- return InlineResult::failure( -- "stack protected callee but caller requested no stack protector"); -- - return None; - } - -diff --git a/llvm/lib/IR/Attributes.cpp b/llvm/lib/IR/Attributes.cpp -index 5cd1bafccc47..eec4629aa725 100644 ---- a/llvm/lib/IR/Attributes.cpp -+++ b/llvm/lib/IR/Attributes.cpp -@@ -1957,6 +1957,12 @@ static void setOR(Function &Caller, const Function &Callee) { - /// If the inlined function had a higher stack protection level than the - /// calling function, then bump up the caller's stack protection level. - static void adjustCallerSSPLevel(Function &Caller, const Function &Callee) { -+ // If the calling function has *no* stack protection level (e.g. it was built -+ // with Clang's -fno-stack-protector or no_stack_protector attribute), don't -+ // change it as that could change the program's semantics. -+ if (!Caller.hasStackProtectorFnAttr()) -+ return; -+ - // If upgrading the SSP attribute, clear out the old SSP Attributes first. - // Having multiple SSP attributes doesn't actually hurt, but it adds useless - // clutter to the IR. -diff --git a/llvm/test/ThinLTO/X86/nossp.ll b/llvm/test/ThinLTO/X86/nossp.ll -index c542a85c6f74..cfc54d595ad7 100644 ---- a/llvm/test/ThinLTO/X86/nossp.ll -+++ b/llvm/test/ThinLTO/X86/nossp.ll -@@ -23,7 +23,8 @@ declare void @ssp_callee() ssp - - ; nossp caller should be able to inline nossp callee. - define void @nossp_caller() { --; CHECK-LABEL: @nossp_caller -+; CHECK-LABEL: define void @nossp_caller() -+; CHECK-NOT: #0 - ; CHECK-NEXT: tail call void @foo - tail call void @nossp_callee() - ret void -@@ -31,28 +32,34 @@ define void @nossp_caller() { - - ; ssp caller should be able to inline ssp callee. - define void @ssp_caller() ssp { --; CHECK-LABEL: @ssp_caller -+; CHECK-LABEL: define void @ssp_caller() -+; CHECK-SAME: #0 - ; CHECK-NEXT: tail call void @foo - tail call void @ssp_callee() - ret void - } - --; nossp caller should *NOT* be able to inline ssp callee. -+; nossp caller should be able to inline ssp callee. -+; the ssp attribute is not propagated. - define void @nossp_caller2() { --; CHECK-LABEL: @nossp_caller2 --; CHECK-NEXT: tail call void @ssp_callee -+; CHECK-LABEL: define void @nossp_caller2() -+; CHECK-NOT: #0 -+; CHECK-NEXT: tail call void @foo - tail call void @ssp_callee() - ret void - } - --; ssp caller should *NOT* be able to inline nossp callee. -+; ssp caller should be able to inline nossp callee. - define void @ssp_caller2() ssp { --; CHECK-LABEL: @ssp_caller2 --; CHECK-NEXT: tail call void @nossp_callee -+; CHECK-LABEL: define void @ssp_caller2() -+; CHECK-SAME: #0 -+; CHECK-NEXT: tail call void @foo - tail call void @nossp_callee() - ret void - } - -+; CHECK: attributes #0 = { ssp } -+ - ;--- b.ll - target datalayout = "e-m:e-p270:32:32-p271:32:32-p272:64:64-i64:64-f80:128-n8:16:32:64-S128" - target triple = "x86_64-pc-linux-gnu" -diff --git a/llvm/test/Transforms/Inline/inline_nossp.ll b/llvm/test/Transforms/Inline/inline_nossp.ll -deleted file mode 100644 -index 24fdab0b9f13..000000000000 ---- a/llvm/test/Transforms/Inline/inline_nossp.ll -+++ /dev/null -@@ -1,50 +0,0 @@ --; NOTE: Assertions have been autogenerated by utils/update_test_checks.py --; RUN: opt -passes='cgscc(inline)' %s -S -pass-remarks-missed=inline 2>&1 | FileCheck --check-prefixes=CHECK,CHECK-INLINE %s --; RUN: opt -passes=always-inline -o - -S %s | FileCheck %s -- --; CHECK-INLINE: ssp not inlined into nossp_caller because it should never be inlined (cost=never): stack protected callee but caller requested no stack protector --; CHECK-INLINE: nossp not inlined into ssp_caller because it should never be inlined (cost=never): stack protected caller but callee requested no stack protector -- --; Not interesting to test. --define i32 @nossp() { ret i32 41 } --define i32 @ssp() sspstrong { ret i32 42 } --define i32 @nossp_alwaysinline() alwaysinline { ret i32 43 } --define i32 @ssp_alwaysinline() sspstrong alwaysinline { ret i32 44 } -- --; @ssp should not be inlined due to mismatch stack protector. --; @ssp_alwaysinline should be inlined due to alwaysinline. --define i32 @nossp_caller() { --; CHECK-LABEL: @nossp_caller( --; CHECK-NEXT: [[TMP1:%.*]] = call i32 @ssp() --; CHECK-NEXT: ret i32 44 --; -- call i32 @ssp() -- %2 = call i32 @ssp_alwaysinline() -- ret i32 %2 --} --; @nossp should not be inlined due to mismatch stack protector. --; @nossp_alwaysinline should be inlined due to alwaysinline. --define i32 @ssp_caller() sspstrong { --; CHECK-LABEL: @ssp_caller( --; CHECK-NEXT: [[TMP1:%.*]] = call i32 @nossp() --; CHECK-NEXT: ret i32 43 --; -- call i32 @nossp() -- %2 = call i32 @nossp_alwaysinline() -- ret i32 %2 --} -- --; The alwaysinline attribute can also appear on the CallBase (ie. the call --; site), ie. when __attribute__((flatten)) is used on the caller. Treat this --; the same as if the caller had the fn attr alwaysinline and permit inline --; substitution, despite the mismatch between caller and callee on ssp attrs. --; --; Curiously, the always_inline attribute on a CallInst is only expanded by the --; inline pass, but not always_inline pass! --define i32 @nossp_alwaysinline_caller() { --; CHECK-INLINE-LABEL: @nossp_alwaysinline_caller( --; CHECK-INLINE-NEXT: ret i32 42 --; -- %1 = call i32 @ssp() alwaysinline -- ret i32 %1 --} -diff --git a/llvm/test/Transforms/Inline/inline_ssp.ll b/llvm/test/Transforms/Inline/inline_ssp.ll -index ccfe93453159..a4f73f4dcd5a 100644 ---- a/llvm/test/Transforms/Inline/inline_ssp.ll -+++ b/llvm/test/Transforms/Inline/inline_ssp.ll -@@ -9,15 +9,23 @@ - - ; These first four functions (@fun_sspreq, @fun_sspstrong, @fun_ssp, @fun_nossp) - ; are used by the remaining functions to ensure that the SSP attributes are --; propagated correctly. The caller should have its SSP attribute set as: -+; propagated correctly. If the caller had an SSP attribute before inlining, it -+; should have its new SSP attribute set as: - ; strictest(caller-ssp-attr, callee-ssp-attr), where strictness is ordered as: --; sspreq > sspstrong > ssp > [no ssp] -+; sspreq > sspstrong > ssp -+ - define internal void @fun_sspreq() sspreq { - entry: - %call = call i32 (i8*, ...) @printf(i8* getelementptr inbounds ([12 x i8], [12 x i8]* @.str3, i32 0, i32 0)) - ret void - } - -+define internal void @fun_sspreq_alwaysinline() sspreq alwaysinline { -+entry: -+ %call = call i32 (i8*, ...) @printf(i8* getelementptr inbounds ([12 x i8], [12 x i8]* @.str3, i32 0, i32 0)) -+ ret void -+} -+ - define internal void @fun_sspstrong() sspstrong { - entry: - %call = call i32 (i8*, ...) @printf(i8* getelementptr inbounds ([15 x i8], [15 x i8]* @.str2, i32 0, i32 0)) -@@ -66,6 +74,13 @@ entry: - ret void - } - -+define void @alwaysinline_req_nossp() { -+entry: -+; CHECK: @alwaysinline_req_nossp() { -+ call void @fun_sspreq_alwaysinline() -+ ret void -+} -+ - define void @inline_strong_req() sspreq { - entry: - ; CHECK: @inline_strong_req() #[[SSPREQ]] Copied: llvm13/repos/extra-x86_64/don-t-override-__attribute__-no_stack_protector.patch (from rev 449852, llvm13/trunk/don-t-override-__attribute__-no_stack_protector.patch) =================================================================== --- don-t-override-__attribute__-no_stack_protector.patch (rev 0) +++ don-t-override-__attribute__-no_stack_protector.patch 2022-07-04 05:56:02 UTC (rev 449853) @@ -0,0 +1,540 @@ +From 4a7c9b7d6f4a183fef8f43aef004ec865c37bbd8 Mon Sep 17 00:00:00 2001 +From: Hans Wennborg <h...@chromium.org> +Date: Thu, 13 Jan 2022 11:31:11 +0100 +Subject: [PATCH 1/2] Simplify llvm/test/Transforms/Inline/inline_ssp.ll (NFC) + +The nounwind and uwtable attributes were just cluttering up the test. +Using regexes to give symbolic names to the attribute lists make the +test more readable. + +This is pre-committing parts of D116589. + +(cherry picked from commit 2eb7d8d749997e5f3048d39201a4d38b6b8d6455) +--- + llvm/test/Transforms/Inline/inline_ssp.ll | 81 +++++++++++------------ + 1 file changed, 40 insertions(+), 41 deletions(-) + +diff --git a/llvm/test/Transforms/Inline/inline_ssp.ll b/llvm/test/Transforms/Inline/inline_ssp.ll +index 2bf93d322842..ccfe93453159 100644 +--- a/llvm/test/Transforms/Inline/inline_ssp.ll ++++ b/llvm/test/Transforms/Inline/inline_ssp.ll +@@ -12,150 +12,149 @@ + ; propagated correctly. The caller should have its SSP attribute set as: + ; strictest(caller-ssp-attr, callee-ssp-attr), where strictness is ordered as: + ; sspreq > sspstrong > ssp > [no ssp] +-define internal void @fun_sspreq() nounwind sspreq uwtable { ++define internal void @fun_sspreq() sspreq { + entry: + %call = call i32 (i8*, ...) @printf(i8* getelementptr inbounds ([12 x i8], [12 x i8]* @.str3, i32 0, i32 0)) + ret void + } + +-define internal void @fun_sspstrong() nounwind sspstrong uwtable { ++define internal void @fun_sspstrong() sspstrong { + entry: + %call = call i32 (i8*, ...) @printf(i8* getelementptr inbounds ([15 x i8], [15 x i8]* @.str2, i32 0, i32 0)) + ret void + } + +-define internal void @fun_ssp() nounwind ssp uwtable { ++define internal void @fun_ssp() ssp { + entry: + %call = call i32 (i8*, ...) @printf(i8* getelementptr inbounds ([9 x i8], [9 x i8]* @.str1, i32 0, i32 0)) + ret void + } + +-define internal void @fun_nossp() nounwind uwtable { ++define internal void @fun_nossp() { + entry: + %call = call i32 (i8*, ...) @printf(i8* getelementptr inbounds ([11 x i8], [11 x i8]* @.str, i32 0, i32 0)) + ret void + } + +-; Tests start below ++; Tests start below. + +-define void @inline_req_req() nounwind sspreq uwtable { ++define void @inline_req_req() sspreq { + entry: +-; CHECK: @inline_req_req() #0 ++; CHECK: @inline_req_req() #[[SSPREQ:[0-9]]] + call void @fun_sspreq() + ret void + } + +-define void @inline_req_strong() nounwind sspstrong uwtable { ++define void @inline_req_strong() sspstrong { + entry: +-; CHECK: @inline_req_strong() #0 ++; CHECK: @inline_req_strong() #[[SSPREQ]] + call void @fun_sspreq() + ret void + } + +-define void @inline_req_ssp() nounwind ssp uwtable { ++define void @inline_req_ssp() ssp { + entry: +-; CHECK: @inline_req_ssp() #0 ++; CHECK: @inline_req_ssp() #[[SSPREQ]] + call void @fun_sspreq() + ret void + } + +-define void @inline_req_nossp() nounwind uwtable { ++define void @inline_req_nossp() { + entry: +-; CHECK: @inline_req_nossp() #3 ++; CHECK: @inline_req_nossp() { + call void @fun_sspreq() + ret void + } + +-define void @inline_strong_req() nounwind sspreq uwtable { ++define void @inline_strong_req() sspreq { + entry: +-; CHECK: @inline_strong_req() #0 ++; CHECK: @inline_strong_req() #[[SSPREQ]] + call void @fun_sspstrong() + ret void + } + + +-define void @inline_strong_strong() nounwind sspstrong uwtable { ++define void @inline_strong_strong() sspstrong { + entry: +-; CHECK: @inline_strong_strong() #1 ++; CHECK: @inline_strong_strong() #[[SSPSTRONG:[0-9]]] + call void @fun_sspstrong() + ret void + } + +-define void @inline_strong_ssp() nounwind ssp uwtable { ++define void @inline_strong_ssp() ssp { + entry: +-; CHECK: @inline_strong_ssp() #1 ++; CHECK: @inline_strong_ssp() #[[SSPSTRONG]] + call void @fun_sspstrong() + ret void + } + +-define void @inline_strong_nossp() nounwind uwtable { ++define void @inline_strong_nossp() { + entry: +-; CHECK: @inline_strong_nossp() #3 ++; CHECK: @inline_strong_nossp() { + call void @fun_sspstrong() + ret void + } + +-define void @inline_ssp_req() nounwind sspreq uwtable { ++define void @inline_ssp_req() sspreq { + entry: +-; CHECK: @inline_ssp_req() #0 ++; CHECK: @inline_ssp_req() #[[SSPREQ]] + call void @fun_ssp() + ret void + } + + +-define void @inline_ssp_strong() nounwind sspstrong uwtable { ++define void @inline_ssp_strong() sspstrong { + entry: +-; CHECK: @inline_ssp_strong() #1 ++; CHECK: @inline_ssp_strong() #[[SSPSTRONG]] + call void @fun_ssp() + ret void + } + +-define void @inline_ssp_ssp() nounwind ssp uwtable { ++define void @inline_ssp_ssp() ssp { + entry: +-; CHECK: @inline_ssp_ssp() #2 ++; CHECK: @inline_ssp_ssp() #[[SSP:[0-9]]] + call void @fun_ssp() + ret void + } + +-define void @inline_ssp_nossp() nounwind uwtable { ++define void @inline_ssp_nossp() { + entry: +-; CHECK: @inline_ssp_nossp() #3 ++; CHECK: @inline_ssp_nossp() { + call void @fun_ssp() + ret void + } + +-define void @inline_nossp_req() nounwind uwtable sspreq { ++define void @inline_nossp_req() sspreq { + entry: +-; CHECK: @inline_nossp_req() #0 ++; CHECK: @inline_nossp_req() #[[SSPREQ]] + call void @fun_nossp() + ret void + } + + +-define void @inline_nossp_strong() nounwind sspstrong uwtable { ++define void @inline_nossp_strong() sspstrong { + entry: +-; CHECK: @inline_nossp_strong() #1 ++; CHECK: @inline_nossp_strong() #[[SSPSTRONG]] + call void @fun_nossp() + ret void + } + +-define void @inline_nossp_ssp() nounwind ssp uwtable { ++define void @inline_nossp_ssp() ssp { + entry: +-; CHECK: @inline_nossp_ssp() #2 ++; CHECK: @inline_nossp_ssp() #[[SSP]] + call void @fun_nossp() + ret void + } + +-define void @inline_nossp_nossp() nounwind uwtable { ++define void @inline_nossp_nossp() { + entry: +-; CHECK: @inline_nossp_nossp() #3 ++; CHECK: @inline_nossp_nossp() { + call void @fun_nossp() + ret void + } + + declare i32 @printf(i8*, ...) + +-; CHECK: attributes #0 = { nounwind sspreq uwtable } +-; CHECK: attributes #1 = { nounwind sspstrong uwtable } +-; CHECK: attributes #2 = { nounwind ssp uwtable } +-; CHECK: attributes #3 = { nounwind uwtable } ++; CHECK: attributes #[[SSPREQ]] = { sspreq } ++; CHECK: attributes #[[SSPSTRONG]] = { sspstrong } ++; CHECK: attributes #[[SSP]] = { ssp } + +From b52296ecaa3878648ceeb3aa39df05dc71e44597 Mon Sep 17 00:00:00 2001 +From: Hans Wennborg <h...@chromium.org> +Date: Mon, 3 Jan 2022 18:03:43 +0100 +Subject: [PATCH 2/2] Don't override __attribute__((no_stack_protector)) by + inlining (PR52886) + +Since 26c6a3e736d3, LLVM's inliner will "upgrade" the caller's stack protector +attribute based on the callee. This lead to surprising results with Clang's +no_stack_protector attribute added in 4fbf84c1732f (D46300). Consider the +following code compiled with clang -fstack-protector-strong -Os +(https://godbolt.org/z/7s3rW7a1q). + + extern void h(int* p); + + inline __attribute__((always_inline)) int g() { + return 0; + } + + int __attribute__((__no_stack_protector__)) f() { + int a[1]; + h(a); + return g(); + } + +LLVM will inline g() into f(), and f() would get a stack protector, against the +users explicit wishes, potentially breaking the program e.g. if h() changes the +value of the stack cookie. That's a miscompile. + +More recently, bc044a88ee3c (D91816) addressed this problem by preventing +inlining when the stack protector is disabled in the caller and enabled in the +callee or vice versa. However, the problem remained if the callee is marked +always_inline as in the example above. This affected users, see e.g. +http://crbug.com/1274129 and http://llvm.org/pr52886. + +One way to fix this would be to prevent inlining also in the always_inline +case. Despite the name, always_inline does not guarantee inlining, so this +would be legal but potentially surprising to users. + +However, I think the better fix is to not enable the stack protector in a +caller based on the callee. The motivation for the old behaviour is unclear, it +seems counter-intuitive, and causes real problems as we've seen. + +This commit implements that fix, which means in the example above, g() gets +inlined into f() (also without always_inline), and f() is emitted without stack +protector. I think that matches most developers' expectations, and that's also +what GCC does. + +Another effect of this change is that a no_stack_protector function can now be +inlined into a stack protected function, e.g. (https://godbolt.org/z/hafP6W856): + + extern void h(int* p); + + inline int __attribute__((__no_stack_protector__)) __attribute__((always_inline)) g() { + return 0; + } + + int f() { + int a[1]; + h(a); + return g(); + } + +I think that's fine. Such code would be unusual since no_stack_protector is +normally applied to a program entry point which sets up the stack canary. And +even if such code exists, inlining doesn't change the semantics: there is still +no stack cookie setup/check around entry/exit of the g() code region, but there +may be in the surrounding context, as there was before inlining. This also +matches GCC. + +See also the discussion at https://gcc.gnu.org/bugzilla/show_bug.cgi?id=94722 + +Differential revision: https://reviews.llvm.org/D116589 + +(cherry picked from commit 2bc57d85ebf244f19a3046295b58eb8c667f947d) +--- + llvm/docs/LangRef.rst | 26 +++++------ + llvm/lib/Analysis/InlineCost.cpp | 9 ---- + llvm/lib/IR/Attributes.cpp | 6 +++ + llvm/test/ThinLTO/X86/nossp.ll | 23 ++++++---- + llvm/test/Transforms/Inline/inline_nossp.ll | 50 --------------------- + llvm/test/Transforms/Inline/inline_ssp.ll | 19 +++++++- + 6 files changed, 48 insertions(+), 85 deletions(-) + delete mode 100644 llvm/test/Transforms/Inline/inline_nossp.ll + +diff --git a/llvm/docs/LangRef.rst b/llvm/docs/LangRef.rst +index 36e09355e485..69393eba3906 100644 +--- a/llvm/docs/LangRef.rst ++++ b/llvm/docs/LangRef.rst +@@ -1965,11 +1965,9 @@ example: + Variables that are identified as requiring a protector will be arranged + on the stack such that they are adjacent to the stack protector guard. + +- A function with the ``ssp`` attribute but without the ``alwaysinline`` +- attribute cannot be inlined into a function without a +- ``ssp/sspreq/sspstrong`` attribute. If inlined, the caller will get the +- ``ssp`` attribute. ``call``, ``invoke``, and ``callbr`` instructions with +- the ``alwaysinline`` attribute force inlining. ++ If a function with an ``ssp`` attribute is inlined into a calling function, ++ the attribute is not carried over to the calling function. ++ + ``sspstrong`` + This attribute indicates that the function should emit a stack smashing + protector. This attribute causes a strong heuristic to be used when +@@ -1994,12 +1992,10 @@ example: + + This overrides the ``ssp`` function attribute. + +- A function with the ``sspstrong`` attribute but without the +- ``alwaysinline`` attribute cannot be inlined into a function without a +- ``ssp/sspstrong/sspreq`` attribute. If inlined, the caller will get the +- ``sspstrong`` attribute unless the ``sspreq`` attribute exists. ``call``, +- ``invoke``, and ``callbr`` instructions with the ``alwaysinline`` attribute +- force inlining. ++ If a function with an ``sspstrong`` attribute is inlined into a calling ++ function which has an ``ssp`` attribute, the calling function's attribute ++ will be upgraded to ``sspstrong``. ++ + ``sspreq`` + This attribute indicates that the function should *always* emit a stack + smashing protector. This overrides the ``ssp`` and ``sspstrong`` function +@@ -2016,11 +2012,9 @@ example: + #. Variables that have had their address taken are 3rd closest to the + protector. + +- A function with the ``sspreq`` attribute but without the ``alwaysinline`` +- attribute cannot be inlined into a function without a +- ``ssp/sspstrong/sspreq`` attribute. If inlined, the caller will get the +- ``sspreq`` attribute. ``call``, ``invoke``, and ``callbr`` instructions +- with the ``alwaysinline`` attribute force inlining. ++ If a function with an ``sspreq`` attribute is inlined into a calling ++ function which has an ``ssp`` or ``sspstrong`` attribute, the calling ++ function's attribute will be upgraded to ``sspreq``. + + ``strictfp`` + This attribute indicates that the function was called from a scope that +diff --git a/llvm/lib/Analysis/InlineCost.cpp b/llvm/lib/Analysis/InlineCost.cpp +index e8f79a28a8e8..1e68ec8ff7d6 100644 +--- a/llvm/lib/Analysis/InlineCost.cpp ++++ b/llvm/lib/Analysis/InlineCost.cpp +@@ -2823,15 +2823,6 @@ Optional<InlineResult> llvm::getAttributeBasedInliningDecision( + if (Call.isNoInline()) + return InlineResult::failure("noinline call site attribute"); + +- // Don't inline functions if one does not have any stack protector attribute +- // but the other does. +- if (Caller->hasStackProtectorFnAttr() && !Callee->hasStackProtectorFnAttr()) +- return InlineResult::failure( +- "stack protected caller but callee requested no stack protector"); +- if (Callee->hasStackProtectorFnAttr() && !Caller->hasStackProtectorFnAttr()) +- return InlineResult::failure( +- "stack protected callee but caller requested no stack protector"); +- + return None; + } + +diff --git a/llvm/lib/IR/Attributes.cpp b/llvm/lib/IR/Attributes.cpp +index 5cd1bafccc47..eec4629aa725 100644 +--- a/llvm/lib/IR/Attributes.cpp ++++ b/llvm/lib/IR/Attributes.cpp +@@ -1957,6 +1957,12 @@ static void setOR(Function &Caller, const Function &Callee) { + /// If the inlined function had a higher stack protection level than the + /// calling function, then bump up the caller's stack protection level. + static void adjustCallerSSPLevel(Function &Caller, const Function &Callee) { ++ // If the calling function has *no* stack protection level (e.g. it was built ++ // with Clang's -fno-stack-protector or no_stack_protector attribute), don't ++ // change it as that could change the program's semantics. ++ if (!Caller.hasStackProtectorFnAttr()) ++ return; ++ + // If upgrading the SSP attribute, clear out the old SSP Attributes first. + // Having multiple SSP attributes doesn't actually hurt, but it adds useless + // clutter to the IR. +diff --git a/llvm/test/ThinLTO/X86/nossp.ll b/llvm/test/ThinLTO/X86/nossp.ll +index c542a85c6f74..cfc54d595ad7 100644 +--- a/llvm/test/ThinLTO/X86/nossp.ll ++++ b/llvm/test/ThinLTO/X86/nossp.ll +@@ -23,7 +23,8 @@ declare void @ssp_callee() ssp + + ; nossp caller should be able to inline nossp callee. + define void @nossp_caller() { +-; CHECK-LABEL: @nossp_caller ++; CHECK-LABEL: define void @nossp_caller() ++; CHECK-NOT: #0 + ; CHECK-NEXT: tail call void @foo + tail call void @nossp_callee() + ret void +@@ -31,28 +32,34 @@ define void @nossp_caller() { + + ; ssp caller should be able to inline ssp callee. + define void @ssp_caller() ssp { +-; CHECK-LABEL: @ssp_caller ++; CHECK-LABEL: define void @ssp_caller() ++; CHECK-SAME: #0 + ; CHECK-NEXT: tail call void @foo + tail call void @ssp_callee() + ret void + } + +-; nossp caller should *NOT* be able to inline ssp callee. ++; nossp caller should be able to inline ssp callee. ++; the ssp attribute is not propagated. + define void @nossp_caller2() { +-; CHECK-LABEL: @nossp_caller2 +-; CHECK-NEXT: tail call void @ssp_callee ++; CHECK-LABEL: define void @nossp_caller2() ++; CHECK-NOT: #0 ++; CHECK-NEXT: tail call void @foo + tail call void @ssp_callee() + ret void + } + +-; ssp caller should *NOT* be able to inline nossp callee. ++; ssp caller should be able to inline nossp callee. + define void @ssp_caller2() ssp { +-; CHECK-LABEL: @ssp_caller2 +-; CHECK-NEXT: tail call void @nossp_callee ++; CHECK-LABEL: define void @ssp_caller2() ++; CHECK-SAME: #0 ++; CHECK-NEXT: tail call void @foo + tail call void @nossp_callee() + ret void + } + ++; CHECK: attributes #0 = { ssp } ++ + ;--- b.ll + target datalayout = "e-m:e-p270:32:32-p271:32:32-p272:64:64-i64:64-f80:128-n8:16:32:64-S128" + target triple = "x86_64-pc-linux-gnu" +diff --git a/llvm/test/Transforms/Inline/inline_nossp.ll b/llvm/test/Transforms/Inline/inline_nossp.ll +deleted file mode 100644 +index 24fdab0b9f13..000000000000 +--- a/llvm/test/Transforms/Inline/inline_nossp.ll ++++ /dev/null +@@ -1,50 +0,0 @@ +-; NOTE: Assertions have been autogenerated by utils/update_test_checks.py +-; RUN: opt -passes='cgscc(inline)' %s -S -pass-remarks-missed=inline 2>&1 | FileCheck --check-prefixes=CHECK,CHECK-INLINE %s +-; RUN: opt -passes=always-inline -o - -S %s | FileCheck %s +- +-; CHECK-INLINE: ssp not inlined into nossp_caller because it should never be inlined (cost=never): stack protected callee but caller requested no stack protector +-; CHECK-INLINE: nossp not inlined into ssp_caller because it should never be inlined (cost=never): stack protected caller but callee requested no stack protector +- +-; Not interesting to test. +-define i32 @nossp() { ret i32 41 } +-define i32 @ssp() sspstrong { ret i32 42 } +-define i32 @nossp_alwaysinline() alwaysinline { ret i32 43 } +-define i32 @ssp_alwaysinline() sspstrong alwaysinline { ret i32 44 } +- +-; @ssp should not be inlined due to mismatch stack protector. +-; @ssp_alwaysinline should be inlined due to alwaysinline. +-define i32 @nossp_caller() { +-; CHECK-LABEL: @nossp_caller( +-; CHECK-NEXT: [[TMP1:%.*]] = call i32 @ssp() +-; CHECK-NEXT: ret i32 44 +-; +- call i32 @ssp() +- %2 = call i32 @ssp_alwaysinline() +- ret i32 %2 +-} +-; @nossp should not be inlined due to mismatch stack protector. +-; @nossp_alwaysinline should be inlined due to alwaysinline. +-define i32 @ssp_caller() sspstrong { +-; CHECK-LABEL: @ssp_caller( +-; CHECK-NEXT: [[TMP1:%.*]] = call i32 @nossp() +-; CHECK-NEXT: ret i32 43 +-; +- call i32 @nossp() +- %2 = call i32 @nossp_alwaysinline() +- ret i32 %2 +-} +- +-; The alwaysinline attribute can also appear on the CallBase (ie. the call +-; site), ie. when __attribute__((flatten)) is used on the caller. Treat this +-; the same as if the caller had the fn attr alwaysinline and permit inline +-; substitution, despite the mismatch between caller and callee on ssp attrs. +-; +-; Curiously, the always_inline attribute on a CallInst is only expanded by the +-; inline pass, but not always_inline pass! +-define i32 @nossp_alwaysinline_caller() { +-; CHECK-INLINE-LABEL: @nossp_alwaysinline_caller( +-; CHECK-INLINE-NEXT: ret i32 42 +-; +- %1 = call i32 @ssp() alwaysinline +- ret i32 %1 +-} +diff --git a/llvm/test/Transforms/Inline/inline_ssp.ll b/llvm/test/Transforms/Inline/inline_ssp.ll +index ccfe93453159..a4f73f4dcd5a 100644 +--- a/llvm/test/Transforms/Inline/inline_ssp.ll ++++ b/llvm/test/Transforms/Inline/inline_ssp.ll +@@ -9,15 +9,23 @@ + + ; These first four functions (@fun_sspreq, @fun_sspstrong, @fun_ssp, @fun_nossp) + ; are used by the remaining functions to ensure that the SSP attributes are +-; propagated correctly. The caller should have its SSP attribute set as: ++; propagated correctly. If the caller had an SSP attribute before inlining, it ++; should have its new SSP attribute set as: + ; strictest(caller-ssp-attr, callee-ssp-attr), where strictness is ordered as: +-; sspreq > sspstrong > ssp > [no ssp] ++; sspreq > sspstrong > ssp ++ + define internal void @fun_sspreq() sspreq { + entry: + %call = call i32 (i8*, ...) @printf(i8* getelementptr inbounds ([12 x i8], [12 x i8]* @.str3, i32 0, i32 0)) + ret void + } + ++define internal void @fun_sspreq_alwaysinline() sspreq alwaysinline { ++entry: ++ %call = call i32 (i8*, ...) @printf(i8* getelementptr inbounds ([12 x i8], [12 x i8]* @.str3, i32 0, i32 0)) ++ ret void ++} ++ + define internal void @fun_sspstrong() sspstrong { + entry: + %call = call i32 (i8*, ...) @printf(i8* getelementptr inbounds ([15 x i8], [15 x i8]* @.str2, i32 0, i32 0)) +@@ -66,6 +74,13 @@ entry: + ret void + } + ++define void @alwaysinline_req_nossp() { ++entry: ++; CHECK: @alwaysinline_req_nossp() { ++ call void @fun_sspreq_alwaysinline() ++ ret void ++} ++ + define void @inline_strong_req() sspreq { + entry: + ; CHECK: @inline_strong_req() #[[SSPREQ]]