diff options
author | Wende Tan <twd2.me@gmail.com> | 2022-05-10 15:44:46 -0700 |
---|---|---|
committer | Nick Desaulniers <ndesaulniers@google.com> | 2022-05-10 16:03:42 -0700 |
commit | 6baaad740a5abb4bfcff022a8114abb4eea66a2d (patch) | |
tree | ce8f1f4676fa2d46d96aa0a194679525ce39e687 /llvm/lib/Bitcode/Writer/BitcodeWriter.cpp | |
parent | fc58d7a3261dc168fc177e54722b5ade1bb8508b (diff) | |
download | llvm-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.cpp | 26 |
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); + } } } } |