//===- CoroAnnotationElide.cpp - Elide attributed safe coroutine calls ----===// // // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. // See https://llvm.org/LICENSE.txt for license information. // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception // //===----------------------------------------------------------------------===// // // \file // This pass transforms all Call or Invoke instructions that are annotated // "coro_elide_safe" to call the `.noalloc` variant of coroutine instead. // The frame of the callee coroutine is allocated inside the caller. A pointer // to the allocated frame will be passed into the `.noalloc` ramp function. // //===----------------------------------------------------------------------===// #include "llvm/Transforms/Coroutines/CoroAnnotationElide.h" #include "llvm/Analysis/LazyCallGraph.h" #include "llvm/Analysis/OptimizationRemarkEmitter.h" #include "llvm/IR/Analysis.h" #include "llvm/IR/IRBuilder.h" #include "llvm/IR/InstIterator.h" #include "llvm/IR/Instruction.h" #include "llvm/IR/Module.h" #include "llvm/IR/PassManager.h" #include "llvm/Transforms/Utils/CallGraphUpdater.h" #include <cassert> usingnamespacellvm; #define DEBUG_TYPE … static Instruction *getFirstNonAllocaInTheEntryBlock(Function *F) { … } // Create an alloca in the caller, using FrameSize and FrameAlign as the callee // coroutine's activation frame. static Value *allocateFrameInCaller(Function *Caller, uint64_t FrameSize, Align FrameAlign) { … } // Given a call or invoke instruction to the elide safe coroutine, this function // does the following: // - Allocate a frame for the callee coroutine in the caller using alloca. // - Replace the old CB with a new Call or Invoke to `NewCallee`, with the // pointer to the frame as an additional argument to NewCallee. static void processCall(CallBase *CB, Function *Caller, Function *NewCallee, uint64_t FrameSize, Align FrameAlign) { … } PreservedAnalyses CoroAnnotationElidePass::run(Function &F, FunctionAnalysisManager &FAM) { … }