diff --git a/llvm/lib/Transforms/Instrumentation/RealtimeSanitizer.cpp b/llvm/lib/Transforms/Instrumentation/RealtimeSanitizer.cpp index 7854cf4f2c625..b977badc9d6c1 100644 --- a/llvm/lib/Transforms/Instrumentation/RealtimeSanitizer.cpp +++ b/llvm/lib/Transforms/Instrumentation/RealtimeSanitizer.cpp @@ -45,6 +45,26 @@ static void insertCallAtAllFunctionExitPoints(Function &Fn, insertCallBeforeInstruction(Fn, I, InsertFnName); } +static PreservedAnalyses rtsanPreservedCFGAnalyses() { + PreservedAnalyses PA; + PA.preserveSet(); + return PA; +} + +static void insertExpectNotRealtimeAtFunctionEntryPoint(Function &F) { + IRBuilder<> Builder(&F.front().front()); + Value *NameArg = Builder.CreateGlobalString(F.getName()); + + FunctionType *FuncType = + FunctionType::get(Type::getVoidTy(F.getContext()), + {PointerType::getUnqual(F.getContext())}, false); + + FunctionCallee Func = F.getParent()->getOrInsertFunction( + "__rtsan_expect_not_realtime", FuncType); + + Builder.CreateCall(Func, {NameArg}); +} + RealtimeSanitizerPass::RealtimeSanitizerPass( const RealtimeSanitizerOptions &Options) {} @@ -53,10 +73,12 @@ PreservedAnalyses RealtimeSanitizerPass::run(Function &F, if (F.hasFnAttribute(Attribute::SanitizeRealtime)) { insertCallAtFunctionEntryPoint(F, "__rtsan_realtime_enter"); insertCallAtAllFunctionExitPoints(F, "__rtsan_realtime_exit"); + return rtsanPreservedCFGAnalyses(); + } - PreservedAnalyses PA; - PA.preserveSet(); - return PA; + if (F.hasFnAttribute(Attribute::SanitizeRealtimeUnsafe)) { + insertExpectNotRealtimeAtFunctionEntryPoint(F); + return rtsanPreservedCFGAnalyses(); } return PreservedAnalyses::all(); diff --git a/llvm/test/Instrumentation/RealtimeSanitizer/rtsan_unsafe.ll b/llvm/test/Instrumentation/RealtimeSanitizer/rtsan_unsafe.ll new file mode 100644 index 0000000000000..646a9a0e22e21 --- /dev/null +++ b/llvm/test/Instrumentation/RealtimeSanitizer/rtsan_unsafe.ll @@ -0,0 +1,16 @@ +; RUN: opt < %s -passes=rtsan -S | FileCheck %s + +define void @blocking_function() #0 { + ret void +} + +define noundef i32 @main() #2 { + call void @blocking_function() #4 + ret i32 0 +} + +attributes #0 = { mustprogress noinline sanitize_realtime_unsafe optnone ssp uwtable(sync) } + +; RealtimeSanitizer pass should insert __rtsan_expect_not_realtime at function entrypoint +; CHECK-LABEL: @blocking_function() +; CHECK-NEXT: call{{.*}}@__rtsan_expect_not_realtime({{ptr .*}})