aboutsummaryrefslogtreecommitdiff
path: root/llvm/lib/Bitcode/Writer/BitcodeWriter.cpp
diff options
context:
space:
mode:
authorWende Tan <twd2.me@gmail.com>2022-05-10 15:44:46 -0700
committerNick Desaulniers <ndesaulniers@google.com>2022-05-10 16:03:42 -0700
commit6baaad740a5abb4bfcff022a8114abb4eea66a2d (patch)
treece8f1f4676fa2d46d96aa0a194679525ce39e687 /llvm/lib/Bitcode/Writer/BitcodeWriter.cpp
parentfc58d7a3261dc168fc177e54722b5ade1bb8508b (diff)
downloadllvm-6baaad740a5abb4bfcff022a8114abb4eea66a2d.zip
llvm-6baaad740a5abb4bfcff022a8114abb4eea66a2d.tar.gz
llvm-6baaad740a5abb4bfcff022a8114abb4eea66a2d.tar.bz2
[Bitcode] Include indirect users of BlockAddresses in bitcode
The original fix (commit 23ec5782c3cc) of https://github.com/llvm/llvm-project/issues/52787 only adds `Function`s that have `Instruction`s that directly use `BlockAddress`es into the bitcode (`FUNC_CODE_BLOCKADDR_USERS`). However, in either @rickyz's original reproducing code: ``` void f(long); __attribute__((noinline)) static void fun(long x) { f(x + 1); } void repro(void) { fun(({ label: (long)&&label; })); } ``` ``` ... define dso_local void @repro() #0 { entry: br label %label label: ; preds = %entry tail call fastcc void @fun() ret void } define internal fastcc void @fun() unnamed_addr #1 { entry: tail call void @f(i64 add (i64 ptrtoint (i8* blockaddress(@repro, %label) to i64), i64 1)) #3 ret void } ... ``` or the xfs and overlayfs in the Linux kernel, `BlockAddress`es (e.g., `i8* blockaddress(@repro, %label)`) may first compose `ConstantExpr`s (e.g., `i64 ptrtoint (i8* blockaddress(@repro, %label) to i64)`) and then used by `Instruction`s. This case is not handled by the original fix. This patch adds *indirect* users of `BlockAddress`es, i.e., the `Instruction`s using some `Constant`s which further use the `BlockAddress`es, into the bitcode as well, by doing depth-first searches. Fixes: https://github.com/llvm/llvm-project/issues/52787 Fixes: 23ec5782c3cc ("[Bitcode] materialize Functions early when BlockAddress taken") Reviewed By: nickdesaulniers Differential Revision: https://reviews.llvm.org/D124878
Diffstat (limited to 'llvm/lib/Bitcode/Writer/BitcodeWriter.cpp')
-rw-r--r--llvm/lib/Bitcode/Writer/BitcodeWriter.cpp26
1 files changed, 20 insertions, 6 deletions
diff --git a/llvm/lib/Bitcode/Writer/BitcodeWriter.cpp b/llvm/lib/Bitcode/Writer/BitcodeWriter.cpp
index dcfe12a..1288c91 100644
--- a/llvm/lib/Bitcode/Writer/BitcodeWriter.cpp
+++ b/llvm/lib/Bitcode/Writer/BitcodeWriter.cpp
@@ -19,6 +19,7 @@
#include "llvm/ADT/None.h"
#include "llvm/ADT/Optional.h"
#include "llvm/ADT/STLExtras.h"
+#include "llvm/ADT/SetVector.h"
#include "llvm/ADT/SmallPtrSet.h"
#include "llvm/ADT/SmallString.h"
#include "llvm/ADT/SmallVector.h"
@@ -3365,7 +3366,7 @@ void ModuleBitcodeWriter::writeFunction(
bool NeedsMetadataAttachment = F.hasMetadata();
DILocation *LastDL = nullptr;
- SmallPtrSet<Function *, 4> BlockAddressUsers;
+ SmallSetVector<Function *, 4> BlockAddressUsers;
// Finally, emit all the instructions, in order.
for (const BasicBlock &BB : F) {
@@ -3401,11 +3402,24 @@ void ModuleBitcodeWriter::writeFunction(
}
if (BlockAddress *BA = BlockAddress::lookup(&BB)) {
- for (User *U : BA->users()) {
- if (auto *I = dyn_cast<Instruction>(U)) {
- Function *P = I->getParent()->getParent();
- if (P != &F)
- BlockAddressUsers.insert(P);
+ SmallVector<Value *, 16> BlockAddressUsersStack { BA };
+ SmallPtrSet<Value *, 16> BlockAddressUsersVisited { BA };
+
+ while (!BlockAddressUsersStack.empty()) {
+ Value *V = BlockAddressUsersStack.pop_back_val();
+
+ for (User *U : V->users()) {
+ if ((isa<ConstantAggregate>(U) || isa<ConstantExpr>(U)) &&
+ !BlockAddressUsersVisited.contains(U)) {
+ BlockAddressUsersStack.push_back(U);
+ BlockAddressUsersVisited.insert(U);
+ }
+
+ if (auto *I = dyn_cast<Instruction>(U)) {
+ Function *P = I->getParent()->getParent();
+ if (P != &F)
+ BlockAddressUsers.insert(P);
+ }
}
}
}