[PATCH] D26177: [tsan] Add support for C++ exceptions into TSan (call __tsan_func_exit during unwinding)
Reid Kleckner via llvm-commits
llvm-commits at lists.llvm.org
Wed Nov 2 10:06:25 PDT 2016
rnk added a comment.
In https://reviews.llvm.org/D26177#585299, @kubabrecka wrote:
> Also note that this change increases the code size of TSanified binaries, roughly by 10-20%.
I don't expect there will be any increase in code size if -fno-exceptions is set, because all functions will be marked nounwind, so we won't do the call-to-invoke transformation.
================
Comment at: include/llvm/Transforms/Utils/EscapeEnumerator.h:30-31
+///
+/// It's wrapped up in a state machine using the same transform C# uses for
+/// 'yield return' enumerators, This transform allows it to be non-allocating.
+class EscapeEnumerator {
----------------
The state machine is superfluous, it only has two real states: 1 (running) and 2 (done). The state 0 logic could be handled in the constructor by setting StateBB and StateE. Mind killing the switch and this comment, assuming we don't implement the code size optimization I described below?
================
Comment at: include/llvm/Transforms/Utils/EscapeEnumerator.h:45
+
+ IRBuilder<> *Next() {
+ switch (State) {
----------------
The implementation of Next should not live in a header.
================
Comment at: include/llvm/Transforms/Utils/EscapeEnumerator.h:54
+ State = 1;
+
+ case 1:
----------------
LLVM_FALLTHROUGH would help me understand what's supposed to happen here.
================
Comment at: include/llvm/Transforms/Utils/EscapeEnumerator.h:74-76
+ for (Function::iterator BB = F.begin(), E = F.end(); BB != E; ++BB)
+ for (BasicBlock::iterator II = BB->begin(), EE = BB->end(); II != EE;
+ ++II)
----------------
Range-based for?
================
Comment at: include/llvm/Transforms/Utils/EscapeEnumerator.h:78-79
+ if (CallInst *CI = dyn_cast<CallInst>(II))
+ if (!CI->getCalledFunction() ||
+ !CI->getCalledFunction()->getIntrinsicID())
+ Calls.push_back(CI);
----------------
The right way to ask this is `!CI->doesNotThrow()`. I'm surprised we don't have a non-virtual override of `Instruction::mayThrow` in `CallInst`, but whatever.
================
Comment at: include/llvm/Transforms/Utils/EscapeEnumerator.h:92
+ Constant *PersFn = F.getParent()->getOrInsertFunction(
+ "__gcc_personality_v0",
+ FunctionType::get(Type::getInt32Ty(C), true));
----------------
This isn't going to be right everywhere. You probably want to add some function to `lib/Analysis/EHPersonalities.cpp` to pick a good default based on the target triple.
================
Comment at: include/llvm/Transforms/Utils/EscapeEnumerator.h:97
+ LandingPadInst *LPad =
+ LandingPadInst::Create(ExnTy, 1, "cleanup.lpad", CleanupBB);
+ LPad->setCleanup(true);
----------------
A landingpad instruction would be wrong on Windows, you would want to insert a cleanuppad that unwinds to the caller. For now I think it would be OK to report_fatal_error if `isFuncletEHPersonality(classifyEHPersonality(PersFn))` is true.
================
Comment at: include/llvm/Transforms/Utils/EscapeEnumerator.h:122
+ InvokeInst *II =
+ InvokeInst::Create(CI->getCalledValue(), NewBB, CleanupBB, Args,
+ CI->getName(), CallBB);
----------------
This fails to handle operand bundles on calls. We should factor this logic out of the inliner, which gets it 100% correct, into `lib/Transforms/Util/Local.cpp` next to changeToCall, and use it from here.
================
Comment at: lib/Transforms/Instrumentation/ThreadSanitizer.cpp:448-449
+ EscapeEnumerator EE(F, "tsan_cleanup");
+ while (IRBuilder<> *AtExit = EE.Next()) {
+ AtExit->CreateCall(TsanFuncExit, {});
}
----------------
This is probably outside the scope of this patch, but is this really what you want to do? Instead of inserting a call before every return, you could create a new single return block with only one call. That might be better for code size. The same is true for resumes: you can make all resumes a jump to the same resume block, and then you only need one exit call, for a total of two calls per function, max.
Actually, this gives me a maybe too clever idea for code size reduction... what if we had __tsan_func_exit check if we are unwinding and call _Unwind_Resume from there? We'd still have binary size increase from the LSDA and we probably couldn't eliminate the landingpad basic block, but it's an interesting idea.
Repository:
rL LLVM
https://reviews.llvm.org/D26177
More information about the llvm-commits
mailing list