[Bitcode] Include indirect users of BlockAddresses in bitcode

The original fix (commit 23ec5782c3) 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: 23ec5782c3 ("[Bitcode] materialize Functions early when BlockAddress taken")

Reviewed By: nickdesaulniers

Differential Revision: https://reviews.llvm.org/D124878
This commit is contained in:
Wende Tan
2022-05-10 15:44:46 -07:00
committed by Nick Desaulniers
parent fc58d7a326
commit 6baaad740a
5 changed files with 174 additions and 6 deletions

View File

@@ -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);
}
}
}
}