Skip to content

Commit d47801e

Browse files
committed
In coro.retcon lowering, don't explode if the optimizer messes around with the linkage of the prototype or the exact types of the yielded values.
llvm-svn: 368793
1 parent ac40483 commit d47801e

File tree

3 files changed

+48
-1
lines changed

3 files changed

+48
-1
lines changed

llvm/lib/Transforms/Coroutines/CoroSplit.cpp

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -585,8 +585,25 @@ void CoroCloner::create() {
585585

586586
SmallVector<ReturnInst *, 4> Returns;
587587

588+
// Ignore attempts to change certain attributes of the function.
589+
// TODO: maybe there should be a way to suppress this during cloning?
590+
auto savedVisibility = NewF->getVisibility();
591+
auto savedUnnamedAddr = NewF->getUnnamedAddr();
592+
auto savedDLLStorageClass = NewF->getDLLStorageClass();
593+
594+
// NewF's linkage (which CloneFunctionInto does *not* change) might not
595+
// be compatible with the visibility of OrigF (which it *does* change),
596+
// so protect against that.
597+
auto savedLinkage = NewF->getLinkage();
598+
NewF->setLinkage(llvm::GlobalValue::ExternalLinkage);
599+
588600
CloneFunctionInto(NewF, &OrigF, VMap, /*ModuleLevelChanges=*/true, Returns);
589601

602+
NewF->setLinkage(savedLinkage);
603+
NewF->setVisibility(savedVisibility);
604+
NewF->setUnnamedAddr(savedUnnamedAddr);
605+
NewF->setDLLStorageClass(savedDLLStorageClass);
606+
590607
auto &Context = NewF->getContext();
591608

592609
// Replace the attributes of the new function:

llvm/lib/Transforms/Coroutines/Coroutines.cpp

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -405,7 +405,17 @@ void coro::Shape::buildFrom(Function &F) {
405405
auto SI = Suspend->value_begin(), SE = Suspend->value_end();
406406
auto RI = ResultTys.begin(), RE = ResultTys.end();
407407
for (; SI != SE && RI != RE; ++SI, ++RI) {
408-
if ((*SI)->getType() != *RI) {
408+
auto SrcTy = (*SI)->getType();
409+
if (SrcTy != *RI) {
410+
// The optimizer likes to eliminate bitcasts leading into variadic
411+
// calls, but that messes with our invariants. Re-insert the
412+
// bitcast and ignore this type mismatch.
413+
if (CastInst::isBitCastable(SrcTy, *RI)) {
414+
auto BCI = new BitCastInst(*SI, *RI, "", Suspend);
415+
SI->set(BCI);
416+
continue;
417+
}
418+
409419
#ifndef NDEBUG
410420
Suspend->dump();
411421
Prototype->getFunctionType()->dump();

llvm/test/Transforms/Coroutines/coro-retcon.ll

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -78,13 +78,33 @@ entry:
7878
; CHECK-NEXT: call void @print(i32 [[INC]])
7979
; CHECK-NEXT: ret i32 0
8080

81+
define hidden { i8*, i8* } @g(i8* %buffer, i16* %ptr) {
82+
entry:
83+
%id = call token @llvm.coro.id.retcon(i32 8, i32 4, i8* %buffer, i8* bitcast ({ i8*, i8* } (i8*, i1)* @g_prototype to i8*), i8* bitcast (i8* (i32)* @allocate to i8*), i8* bitcast (void (i8*)* @deallocate to i8*))
84+
%hdl = call i8* @llvm.coro.begin(token %id, i8* null)
85+
br label %loop
86+
87+
loop:
88+
%ptr2 = bitcast i16* %ptr to i8*
89+
%unwind0 = call i1 (...) @llvm.coro.suspend.retcon.i1(i8* %ptr2)
90+
br i1 %unwind0, label %cleanup, label %resume
91+
92+
resume:
93+
br label %loop
94+
95+
cleanup:
96+
call i1 @llvm.coro.end(i8* %hdl, i1 0)
97+
unreachable
98+
}
99+
81100
declare token @llvm.coro.id.retcon(i32, i32, i8*, i8*, i8*, i8*)
82101
declare i8* @llvm.coro.begin(token, i8*)
83102
declare i1 @llvm.coro.suspend.retcon.i1(...)
84103
declare i1 @llvm.coro.end(i8*, i1)
85104
declare i8* @llvm.coro.prepare.retcon(i8*)
86105

87106
declare i8* @prototype(i8*, i1 zeroext)
107+
declare {i8*,i8*} @g_prototype(i8*, i1 zeroext)
88108

89109
declare noalias i8* @allocate(i32 %size)
90110
declare void @deallocate(i8* %ptr)

0 commit comments

Comments
 (0)