Index: llvm/trunk/lib/Transforms/Coroutines/CoroCleanup.cpp =================================================================== --- llvm/trunk/lib/Transforms/Coroutines/CoroCleanup.cpp +++ llvm/trunk/lib/Transforms/Coroutines/CoroCleanup.cpp @@ -10,6 +10,7 @@ //===----------------------------------------------------------------------===// #include "CoroInternal.h" +#include "llvm/IR/IRBuilder.h" #include "llvm/IR/InstIterator.h" #include "llvm/IR/LegacyPassManager.h" #include "llvm/Pass.h" @@ -22,7 +23,8 @@ namespace { // Created on demand if CoroCleanup pass has work to do. struct Lowerer : coro::LowererBase { - Lowerer(Module &M) : LowererBase(M) {} + IRBuilder<> Builder; + Lowerer(Module &M) : LowererBase(M), Builder(Context) {} bool lowerRemainingCoroIntrinsics(Function &F); }; } @@ -36,6 +38,23 @@ FPM.doFinalization(); } +static void lowerSubFn(IRBuilder<> &Builder, CoroSubFnInst *SubFn) { + Builder.SetInsertPoint(SubFn); + Value *FrameRaw = SubFn->getFrame(); + int Index = SubFn->getIndex(); + + auto *FrameTy = StructType::get( + SubFn->getContext(), {Builder.getInt8PtrTy(), Builder.getInt8PtrTy()}); + PointerType *FramePtrTy = FrameTy->getPointerTo(); + + Builder.SetInsertPoint(SubFn); + auto *FramePtr = Builder.CreateBitCast(FrameRaw, FramePtrTy); + auto *Gep = Builder.CreateConstInBoundsGEP2_32(FrameTy, FramePtr, 0, Index); + auto *Load = Builder.CreateLoad(Gep); + + SubFn->replaceAllUsesWith(Load); +} + bool Lowerer::lowerRemainingCoroIntrinsics(Function &F) { bool Changed = false; @@ -57,6 +76,9 @@ case Intrinsic::coro_id: II->replaceAllUsesWith(ConstantTokenNone::get(Context)); break; + case Intrinsic::coro_subfn_addr: + lowerSubFn(Builder, cast(II)); + break; } II->eraseFromParent(); Changed = true; @@ -87,7 +109,8 @@ // in the module. bool doInitialization(Module &M) override { if (coro::declaresIntrinsics(M, {"llvm.coro.alloc", "llvm.coro.begin", - "llvm.coro.free", "llvm.coro.id"})) + "llvm.coro.subfn.addr", "llvm.coro.free", + "llvm.coro.id"})) L = llvm::make_unique(M); return false; } Index: llvm/trunk/lib/Transforms/Coroutines/Coroutines.cpp =================================================================== --- llvm/trunk/lib/Transforms/Coroutines/Coroutines.cpp +++ llvm/trunk/lib/Transforms/Coroutines/Coroutines.cpp @@ -107,7 +107,7 @@ "llvm.coro.done", "llvm.coro.end", "llvm.coro.frame", "llvm.coro.free", "llvm.coro.id", "llvm.coro.param", "llvm.coro.promise", "llvm.coro.resume", "llvm.coro.save", - "llvm.coro.size", "llvm.coro.suspend", + "llvm.coro.size", "llvm.coro.subfn.addr", "llvm.coro.suspend", }; return Intrinsic::lookupLLVMIntrinsicByName(CoroIntrinsics, Name) != -1; } Index: llvm/trunk/test/Transforms/Coroutines/coro-cleanup.ll =================================================================== --- llvm/trunk/test/Transforms/Coroutines/coro-cleanup.ll +++ llvm/trunk/test/Transforms/Coroutines/coro-cleanup.ll @@ -0,0 +1,18 @@ +; Make sure that all library helper coro intrinsics are lowered. +; RUN: opt < %s -O0 -enable-coroutines -S | FileCheck %s + +; CHECK-LABEL: @uses_library_support_coro_intrinsics( +; CHECK-NOT: @llvm.coro +; CHECK: ret void +define void @uses_library_support_coro_intrinsics(i8* %hdl) { +entry: + call void @llvm.coro.resume(i8* %hdl) + call void @llvm.coro.destroy(i8* %hdl) + call i1 @llvm.coro.done(i8* %hdl) + ret void +} + +declare void @llvm.coro.resume(i8*) +declare void @llvm.coro.destroy(i8*) +declare i1 @llvm.coro.done(i8*) +