Skip to content

Commit 5259917

Browse files
apollowwyuxuanchen1997
authored andcommitted
[Asan] Skip pre-split coroutine and noop coroutine frame (#99415)
Summary: CoroSplit expects the second parameter of `llvm.coro.id` to be the promise alloca. Applying Asan on a pre-split coroutine breaks this assumption and causes split to fail. This should be NFC because asan pass happens late in the pipeline where all coroutines are split. This is to prevent crash in case the order of passes are switched. Also `NoopCoro.Frame.Const` is a special coroutine frame that does nothing when resumed or destroyed. There is no point to do instrumentation on it. Test Plan: Reviewers: Subscribers: Tasks: Tags: Differential Revision: https://phabricator.intern.facebook.com/D60251181
1 parent 6106ce4 commit 5259917

File tree

3 files changed

+37
-0
lines changed

3 files changed

+37
-0
lines changed

llvm/lib/Transforms/Coroutines/CoroEarly.cpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -148,6 +148,7 @@ void Lowerer::lowerCoroNoop(IntrinsicInst *II) {
148148
NoopCoro = new GlobalVariable(M, NoopCoroConst->getType(), /*isConstant=*/true,
149149
GlobalVariable::PrivateLinkage, NoopCoroConst,
150150
"NoopCoro.Frame.Const");
151+
cast<GlobalVariable>(NoopCoro)->setNoSanitizeMetadata();
151152
}
152153

153154
Builder.SetInsertPoint(II);

llvm/lib/Transforms/Instrumentation/AddressSanitizer.cpp

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2947,6 +2947,8 @@ bool AddressSanitizer::instrumentFunction(Function &F,
29472947
if (F.getLinkage() == GlobalValue::AvailableExternallyLinkage) return false;
29482948
if (!ClDebugFunc.empty() && ClDebugFunc == F.getName()) return false;
29492949
if (F.getName().starts_with("__asan_")) return false;
2950+
if (F.isPresplitCoroutine())
2951+
return false;
29502952

29512953
bool FunctionModified = false;
29522954

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
; Tests that asan skips pre-split coroutine and NoopCoro.Frame
2+
; RUN: opt < %s -S -passes=coro-early,asan | FileCheck %s
3+
4+
; CHECK: %NoopCoro.Frame = type { ptr, ptr }
5+
; CHECK: @NoopCoro.Frame.Const = private constant %NoopCoro.Frame { ptr @__NoopCoro_ResumeDestroy, ptr @__NoopCoro_ResumeDestroy }
6+
; CHECK-NOT: @0 = private alias { %NoopCoro.Frame,
7+
8+
%struct.Promise = type { %"struct.std::__n4861::coroutine_handle" }
9+
%"struct.std::__n4861::coroutine_handle" = type { ptr }
10+
11+
; CHECK-LABEL: @foo(
12+
define ptr @foo() #0 {
13+
; CHECK-NEXT: entry
14+
; CHECK-NOT: %asan_local_stack_base
15+
entry:
16+
%__promise = alloca %struct.Promise, align 8
17+
%0 = call token @llvm.coro.id(i32 16, ptr nonnull %__promise, ptr null, ptr null)
18+
%1 = call ptr @llvm.coro.noop()
19+
ret ptr %1
20+
}
21+
22+
declare token @llvm.coro.id(i32, ptr readnone, ptr nocapture readonly, ptr)
23+
declare ptr @llvm.coro.noop()
24+
25+
attributes #0 = { sanitize_address presplitcoroutine }
26+
27+
!llvm.dbg.cu = !{!0}
28+
!llvm.module.flags = !{!3, !4}
29+
30+
!0 = distinct !DICompileUnit(language: DW_LANG_C99, file: !1, producer: "hand-written", isOptimized: false, runtimeVersion: 0, emissionKind: FullDebug, enums: !2)
31+
!1 = !DIFile(filename: "<stdin>", directory: "")
32+
!2 = !{}
33+
!3 = !{i32 2, !"Dwarf Version", i32 4}
34+
!4 = !{i32 2, !"Debug Info Version", i32 3}

0 commit comments

Comments
 (0)