[llvm-dev] Suggestions for how coroutines and UBSan codegen can play nice with one another?

Brian Gesiak via llvm-dev llvm-dev at lists.llvm.org
Mon Mar 19 15:44:07 PDT 2018


Hello all!
(+cc Vedant Kumar, who I've been told knows a lot about UBSan!)

I am trying to fix an assert that occurs when the transforms in
llvm/lib/Transforms/Coroutines are applied to LLVM IR that has been
generated with UBSan enabled -- specifically, '-fsanitize=null'.

You can see an example of the assert in this 26-line C++ file here:
https://godbolt.org/g/Gw9UZq

Note that without the '-fsanitize=null' option this compiles fine, but when
that option is used, Clang/LLVM crashes due to "error in backend: cannot
move instruction since its users are not dominated by CoroBegin".

The coroutine pass coro-split is responsible for transforming instructions
within a coroutine function. Because a coroutine function can be suspended
and then resumed much later in a program's execution, accesses to stack
variables much be rewritten so that they access variables stored on the
"coroutine frame," a heap-allocated piece of state that represents the
execution frame of the coroutine. As part of this process, load
instructions, such as the one generated for the '*this' expression in the
source file above, are moved down past a call to the '@llvm.coro.begin'
intrinsic.

However, when UBSan is enabled, the load of '*this' is then immediately
followed by a null check and, in the null case, a conditional branch to a
call to '@ __ubsan_handle_type_mismatch_v1'. The coro-split pass is not
written to move these compare and branch instructions, and instead asserts.

You can see an example of the IR generated with and without
'-fsanitize=null' here:
https://gist.github.com/modocache/54a036c3bf9c06882fe85122e105d153
-- PR36578.ll lines 82 to 104 show the problematic UBSan branches. Note
that PR36578.nosan.ll, which was compiled without '-fsanitize=null', does
not include these branches.

I have several questions:

* What's the best way for the LLVM coroutines transform passes to play
nicely with the code generated with UBSan's '-fsanitize=null'?
* Are there other LLVM passes I could look at, to see examples of how they
were modified to handle UBSan?
* I've seen code in Clang's codebase that adds 'SanitizerKind::Null' to a
set of skipped UBSan checks; should lib/CodeGen/CGCoroutine.cpp also do
something like this, to avoid generating UBSan checks altogether? Would
that be sufficient to avoid the error? Are there downsides to doing this?

Any and all advice is appreciated -- thanks!

- Brian Gesiak
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.llvm.org/pipermail/llvm-dev/attachments/20180319/68847def/attachment.html>


More information about the llvm-dev mailing list