@@ -42,6 +42,8 @@ class OffloadSanitizerImpl final {
4242 bool shouldInstrumentFunction (Function &Fn);
4343 bool instrumentFunction (Function &Fn);
4444 bool instrumentTrapInstructions (SmallVectorImpl<IntrinsicInst *> &TrapCalls);
45+ bool instrumentUnreachableInstructions (
46+ SmallVectorImpl<UnreachableInst *> &UnreachableInsts);
4547
4648 FunctionCallee getOrCreateFn (FunctionCallee &FC, StringRef Name, Type *RetTy,
4749 ArrayRef<Type *> ArgTys) {
@@ -59,6 +61,13 @@ class OffloadSanitizerImpl final {
5961 {/* PC*/ Int64Ty});
6062 }
6163
64+ // / void __offload_san_unreachable_info(Int64Ty);
65+ FunctionCallee UnreachableInfoFn;
66+ FunctionCallee getUnreachableInfoFn () {
67+ return getOrCreateFn (UnreachableInfoFn, " __offload_san_unreachable_info" ,
68+ VoidTy, {/* PC*/ Int64Ty});
69+ }
70+
6271 CallInst *createCall (IRBuilder<> &IRB, FunctionCallee Callee,
6372 ArrayRef<Value *> Args = std::nullopt ,
6473 const Twine &Name = " " ) {
@@ -107,15 +116,34 @@ bool OffloadSanitizerImpl::instrumentTrapInstructions(
107116 return Changed;
108117}
109118
119+ bool OffloadSanitizerImpl::instrumentUnreachableInstructions (
120+ SmallVectorImpl<UnreachableInst *> &UnreachableInsts) {
121+ bool Changed = false ;
122+ for (auto *II : UnreachableInsts) {
123+ // Skip unreachables after traps since we instrument those as well.
124+ if (&II->getParent ()->front () != II)
125+ if (auto *CI = dyn_cast<CallInst>(II->getPrevNode ()))
126+ if (CI->getIntrinsicID () == Intrinsic::trap)
127+ continue ;
128+ IRBuilder<> IRB (II);
129+ createCall (IRB, getUnreachableInfoFn (), {getPC (IRB)});
130+ }
131+ return Changed;
132+ }
133+
110134bool OffloadSanitizerImpl::instrumentFunction (Function &Fn) {
111135 if (!shouldInstrumentFunction (Fn))
112136 return false ;
113137
138+ SmallVector<UnreachableInst *> UnreachableInsts;
114139 SmallVector<IntrinsicInst *> TrapCalls;
115140
116141 bool Changed = false ;
117142 for (auto &I : instructions (Fn)) {
118143 switch (I.getOpcode ()) {
144+ case Instruction::Unreachable:
145+ UnreachableInsts.push_back (cast<UnreachableInst>(&I));
146+ break ;
119147 case Instruction::Call: {
120148 auto &CI = cast<CallInst>(I);
121149 if (auto *II = dyn_cast<IntrinsicInst>(&CI))
@@ -129,6 +157,7 @@ bool OffloadSanitizerImpl::instrumentFunction(Function &Fn) {
129157 }
130158
131159 Changed |= instrumentTrapInstructions (TrapCalls);
160+ Changed |= instrumentUnreachableInstructions (UnreachableInsts);
132161
133162 return Changed;
134163}
0 commit comments