]> granicus.if.org Git - llvm/commitdiff
In coro.retcon lowering, don't explode if the optimizer messes around with the linkag...
authorJohn McCall <rjmccall@apple.com>
Wed, 14 Aug 2019 03:53:52 +0000 (03:53 +0000)
committerJohn McCall <rjmccall@apple.com>
Wed, 14 Aug 2019 03:53:52 +0000 (03:53 +0000)
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@368793 91177308-0d34-0410-b5e6-96231b3b80d8

lib/Transforms/Coroutines/CoroSplit.cpp
lib/Transforms/Coroutines/Coroutines.cpp
test/Transforms/Coroutines/coro-retcon.ll

index 318a012b6a74f981a05e12f47ed578135d2a23cd..1183352271c2b9e1dd517443a394288b7290a174 100644 (file)
@@ -585,8 +585,25 @@ void CoroCloner::create() {
 
   SmallVector<ReturnInst *, 4> Returns;
 
+  // Ignore attempts to change certain attributes of the function.
+  // TODO: maybe there should be a way to suppress this during cloning?
+  auto savedVisibility = NewF->getVisibility();
+  auto savedUnnamedAddr = NewF->getUnnamedAddr();
+  auto savedDLLStorageClass = NewF->getDLLStorageClass();
+
+  // NewF's linkage (which CloneFunctionInto does *not* change) might not
+  // be compatible with the visibility of OrigF (which it *does* change),
+  // so protect against that.
+  auto savedLinkage = NewF->getLinkage();
+  NewF->setLinkage(llvm::GlobalValue::ExternalLinkage);
+
   CloneFunctionInto(NewF, &OrigF, VMap, /*ModuleLevelChanges=*/true, Returns);
 
+  NewF->setLinkage(savedLinkage);
+  NewF->setVisibility(savedVisibility);
+  NewF->setUnnamedAddr(savedUnnamedAddr);
+  NewF->setDLLStorageClass(savedDLLStorageClass);
+
   auto &Context = NewF->getContext();
 
   // Replace the attributes of the new function:
index b81a08557b4746304733d9ce7285bdf80a87b6bb..12176570b7ab1d662946c3f76954e16b21fbd8f8 100644 (file)
@@ -405,7 +405,17 @@ void coro::Shape::buildFrom(Function &F) {
       auto SI = Suspend->value_begin(), SE = Suspend->value_end();
       auto RI = ResultTys.begin(), RE = ResultTys.end();
       for (; SI != SE && RI != RE; ++SI, ++RI) {
-        if ((*SI)->getType() != *RI) {
+        auto SrcTy = (*SI)->getType();
+        if (SrcTy != *RI) {
+          // The optimizer likes to eliminate bitcasts leading into variadic
+          // calls, but that messes with our invariants.  Re-insert the
+          // bitcast and ignore this type mismatch.
+          if (CastInst::isBitCastable(SrcTy, *RI)) {
+            auto BCI = new BitCastInst(*SI, *RI, "", Suspend);
+            SI->set(BCI);
+            continue;
+          }
+
 #ifndef NDEBUG
           Suspend->dump();
           Prototype->getFunctionType()->dump();
index 298ce579578f40007390d849c6b286365361644d..5cd4cb61d94cc08083ec2350429127478c6b1ce1 100644 (file)
@@ -78,6 +78,25 @@ entry:
 ; CHECK-NEXT:    call void @print(i32 [[INC]])
 ; CHECK-NEXT:    ret i32 0
 
+define hidden { i8*, i8* } @g(i8* %buffer, i16* %ptr) {
+entry:
+  %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*))
+  %hdl = call i8* @llvm.coro.begin(token %id, i8* null)
+  br label %loop
+
+loop:
+  %ptr2 = bitcast i16* %ptr to i8*
+  %unwind0 = call i1 (...) @llvm.coro.suspend.retcon.i1(i8* %ptr2)
+  br i1 %unwind0, label %cleanup, label %resume
+
+resume:
+  br label %loop
+
+cleanup:
+  call i1 @llvm.coro.end(i8* %hdl, i1 0)
+  unreachable
+}
+
 declare token @llvm.coro.id.retcon(i32, i32, i8*, i8*, i8*, i8*)
 declare i8* @llvm.coro.begin(token, i8*)
 declare i1 @llvm.coro.suspend.retcon.i1(...)
@@ -85,6 +104,7 @@ declare i1 @llvm.coro.end(i8*, i1)
 declare i8* @llvm.coro.prepare.retcon(i8*)
 
 declare i8* @prototype(i8*, i1 zeroext)
+declare {i8*,i8*} @g_prototype(i8*, i1 zeroext)
 
 declare noalias i8* @allocate(i32 %size)
 declare void @deallocate(i8* %ptr)