llvm-project/llvm/test/Bitcode/blockaddress-expr-users.ll
Wende Tan 6baaad740a [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
2022-05-10 16:03:42 -07:00

39 lines
1.0 KiB
LLVM

; RUN: llvm-as %s -o %t.bc
; RUN: llvm-bcanalyzer -dump %t.bc | FileCheck %s
; RUN: llvm-dis %t.bc
; There's a curious case where blockaddress constants may refer to functions
; outside of the function they're used in. There's a special bitcode function
; code, FUNC_CODE_BLOCKADDR_USERS, used to signify that this is the case.
; The intent of this test is two-fold:
; 1. Ensure we produce BLOCKADDR_USERS bitcode function code on the first fn,
; @repro, since @fun and @fun2 both refer to @repro via blockaddress
; constants.
; 2. Ensure we can round-trip serializing+desearlizing such case.
; CHECK: <FUNCTION_BLOCK
; CHECK: <BLOCKADDR_USERS op0=2 op1=1
; CHECK: <FUNCTION_BLOCK
; CHECK: <FUNCTION_BLOCK
define void @repro() {
br label %label
label:
call void @fun()
ret void
}
define void @fun() noinline {
call void @f(i64 ptrtoint (i8* blockaddress(@repro, %label) to i64))
ret void
}
define void @fun2() noinline {
call void @f(i64 ptrtoint (i8* blockaddress(@repro, %label) to i64))
ret void
}
declare void @f(i64)