Coroutines.cpp 20 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600
  1. //===- Coroutines.cpp -----------------------------------------------------===//
  2. //
  3. // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
  4. // See https://llvm.org/LICENSE.txt for license information.
  5. // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
  6. //
  7. //===----------------------------------------------------------------------===//
  8. //
  9. // This file implements the common infrastructure for Coroutine Passes.
  10. //
  11. //===----------------------------------------------------------------------===//
  12. #include "llvm/Transforms/Coroutines.h"
  13. #include "llvm-c/Transforms/Coroutines.h"
  14. #include "CoroInstr.h"
  15. #include "CoroInternal.h"
  16. #include "llvm/ADT/SmallVector.h"
  17. #include "llvm/ADT/StringRef.h"
  18. #include "llvm/Analysis/CallGraph.h"
  19. #include "llvm/Analysis/CallGraphSCCPass.h"
  20. #include "llvm/Transforms/Utils/Local.h"
  21. #include "llvm/IR/Attributes.h"
  22. #include "llvm/IR/CallSite.h"
  23. #include "llvm/IR/Constants.h"
  24. #include "llvm/IR/DerivedTypes.h"
  25. #include "llvm/IR/Function.h"
  26. #include "llvm/IR/InstIterator.h"
  27. #include "llvm/IR/Instructions.h"
  28. #include "llvm/IR/IntrinsicInst.h"
  29. #include "llvm/IR/Intrinsics.h"
  30. #include "llvm/IR/LegacyPassManager.h"
  31. #include "llvm/IR/Module.h"
  32. #include "llvm/IR/Type.h"
  33. #include "llvm/Support/Casting.h"
  34. #include "llvm/Support/ErrorHandling.h"
  35. #include "llvm/Transforms/IPO.h"
  36. #include "llvm/Transforms/IPO/PassManagerBuilder.h"
  37. #include <cassert>
  38. #include <cstddef>
  39. #include <utility>
  40. using namespace llvm;
  41. void llvm::initializeCoroutines(PassRegistry &Registry) {
  42. initializeCoroEarlyPass(Registry);
  43. initializeCoroSplitPass(Registry);
  44. initializeCoroElidePass(Registry);
  45. initializeCoroCleanupPass(Registry);
  46. }
  47. static void addCoroutineOpt0Passes(const PassManagerBuilder &Builder,
  48. legacy::PassManagerBase &PM) {
  49. PM.add(createCoroSplitPass());
  50. PM.add(createCoroElidePass());
  51. PM.add(createBarrierNoopPass());
  52. PM.add(createCoroCleanupPass());
  53. }
  54. static void addCoroutineEarlyPasses(const PassManagerBuilder &Builder,
  55. legacy::PassManagerBase &PM) {
  56. PM.add(createCoroEarlyPass());
  57. }
  58. static void addCoroutineScalarOptimizerPasses(const PassManagerBuilder &Builder,
  59. legacy::PassManagerBase &PM) {
  60. PM.add(createCoroElidePass());
  61. }
  62. static void addCoroutineSCCPasses(const PassManagerBuilder &Builder,
  63. legacy::PassManagerBase &PM) {
  64. PM.add(createCoroSplitPass());
  65. }
  66. static void addCoroutineOptimizerLastPasses(const PassManagerBuilder &Builder,
  67. legacy::PassManagerBase &PM) {
  68. PM.add(createCoroCleanupPass());
  69. }
  70. void llvm::addCoroutinePassesToExtensionPoints(PassManagerBuilder &Builder) {
  71. Builder.addExtension(PassManagerBuilder::EP_EarlyAsPossible,
  72. addCoroutineEarlyPasses);
  73. Builder.addExtension(PassManagerBuilder::EP_EnabledOnOptLevel0,
  74. addCoroutineOpt0Passes);
  75. Builder.addExtension(PassManagerBuilder::EP_CGSCCOptimizerLate,
  76. addCoroutineSCCPasses);
  77. Builder.addExtension(PassManagerBuilder::EP_ScalarOptimizerLate,
  78. addCoroutineScalarOptimizerPasses);
  79. Builder.addExtension(PassManagerBuilder::EP_OptimizerLast,
  80. addCoroutineOptimizerLastPasses);
  81. }
  82. // Construct the lowerer base class and initialize its members.
  83. coro::LowererBase::LowererBase(Module &M)
  84. : TheModule(M), Context(M.getContext()),
  85. Int8Ptr(Type::getInt8PtrTy(Context)),
  86. ResumeFnType(FunctionType::get(Type::getVoidTy(Context), Int8Ptr,
  87. /*isVarArg=*/false)),
  88. NullPtr(ConstantPointerNull::get(Int8Ptr)) {}
  89. // Creates a sequence of instructions to obtain a resume function address using
  90. // llvm.coro.subfn.addr. It generates the following sequence:
  91. //
  92. // call i8* @llvm.coro.subfn.addr(i8* %Arg, i8 %index)
  93. // bitcast i8* %2 to void(i8*)*
  94. Value *coro::LowererBase::makeSubFnCall(Value *Arg, int Index,
  95. Instruction *InsertPt) {
  96. auto *IndexVal = ConstantInt::get(Type::getInt8Ty(Context), Index);
  97. auto *Fn = Intrinsic::getDeclaration(&TheModule, Intrinsic::coro_subfn_addr);
  98. assert(Index >= CoroSubFnInst::IndexFirst &&
  99. Index < CoroSubFnInst::IndexLast &&
  100. "makeSubFnCall: Index value out of range");
  101. auto *Call = CallInst::Create(Fn, {Arg, IndexVal}, "", InsertPt);
  102. auto *Bitcast =
  103. new BitCastInst(Call, ResumeFnType->getPointerTo(), "", InsertPt);
  104. return Bitcast;
  105. }
  106. #ifndef NDEBUG
  107. static bool isCoroutineIntrinsicName(StringRef Name) {
  108. // NOTE: Must be sorted!
  109. static const char *const CoroIntrinsics[] = {
  110. "llvm.coro.alloc",
  111. "llvm.coro.begin",
  112. "llvm.coro.destroy",
  113. "llvm.coro.done",
  114. "llvm.coro.end",
  115. "llvm.coro.frame",
  116. "llvm.coro.free",
  117. "llvm.coro.id",
  118. "llvm.coro.id.retcon",
  119. "llvm.coro.id.retcon.once",
  120. "llvm.coro.noop",
  121. "llvm.coro.param",
  122. "llvm.coro.prepare.retcon",
  123. "llvm.coro.promise",
  124. "llvm.coro.resume",
  125. "llvm.coro.save",
  126. "llvm.coro.size",
  127. "llvm.coro.subfn.addr",
  128. "llvm.coro.suspend",
  129. "llvm.coro.suspend.retcon",
  130. };
  131. return Intrinsic::lookupLLVMIntrinsicByName(CoroIntrinsics, Name) != -1;
  132. }
  133. #endif
  134. // Verifies if a module has named values listed. Also, in debug mode verifies
  135. // that names are intrinsic names.
  136. bool coro::declaresIntrinsics(Module &M,
  137. std::initializer_list<StringRef> List) {
  138. for (StringRef Name : List) {
  139. assert(isCoroutineIntrinsicName(Name) && "not a coroutine intrinsic");
  140. if (M.getNamedValue(Name))
  141. return true;
  142. }
  143. return false;
  144. }
  145. // Replace all coro.frees associated with the provided CoroId either with 'null'
  146. // if Elide is true and with its frame parameter otherwise.
  147. void coro::replaceCoroFree(CoroIdInst *CoroId, bool Elide) {
  148. SmallVector<CoroFreeInst *, 4> CoroFrees;
  149. for (User *U : CoroId->users())
  150. if (auto CF = dyn_cast<CoroFreeInst>(U))
  151. CoroFrees.push_back(CF);
  152. if (CoroFrees.empty())
  153. return;
  154. Value *Replacement =
  155. Elide ? ConstantPointerNull::get(Type::getInt8PtrTy(CoroId->getContext()))
  156. : CoroFrees.front()->getFrame();
  157. for (CoroFreeInst *CF : CoroFrees) {
  158. CF->replaceAllUsesWith(Replacement);
  159. CF->eraseFromParent();
  160. }
  161. }
  162. // FIXME: This code is stolen from CallGraph::addToCallGraph(Function *F), which
  163. // happens to be private. It is better for this functionality exposed by the
  164. // CallGraph.
  165. static void buildCGN(CallGraph &CG, CallGraphNode *Node) {
  166. Function *F = Node->getFunction();
  167. // Look for calls by this function.
  168. for (Instruction &I : instructions(F))
  169. if (auto *Call = dyn_cast<CallBase>(&I)) {
  170. const Function *Callee = Call->getCalledFunction();
  171. if (!Callee || !Intrinsic::isLeaf(Callee->getIntrinsicID()))
  172. // Indirect calls of intrinsics are not allowed so no need to check.
  173. // We can be more precise here by using TargetArg returned by
  174. // Intrinsic::isLeaf.
  175. Node->addCalledFunction(Call, CG.getCallsExternalNode());
  176. else if (!Callee->isIntrinsic())
  177. Node->addCalledFunction(Call, CG.getOrInsertFunction(Callee));
  178. }
  179. }
  180. // Rebuild CGN after we extracted parts of the code from ParentFunc into
  181. // NewFuncs. Builds CGNs for the NewFuncs and adds them to the current SCC.
  182. void coro::updateCallGraph(Function &ParentFunc, ArrayRef<Function *> NewFuncs,
  183. CallGraph &CG, CallGraphSCC &SCC) {
  184. // Rebuild CGN from scratch for the ParentFunc
  185. auto *ParentNode = CG[&ParentFunc];
  186. ParentNode->removeAllCalledFunctions();
  187. buildCGN(CG, ParentNode);
  188. SmallVector<CallGraphNode *, 8> Nodes(SCC.begin(), SCC.end());
  189. for (Function *F : NewFuncs) {
  190. CallGraphNode *Callee = CG.getOrInsertFunction(F);
  191. Nodes.push_back(Callee);
  192. buildCGN(CG, Callee);
  193. }
  194. SCC.initialize(Nodes);
  195. }
  196. static void clear(coro::Shape &Shape) {
  197. Shape.CoroBegin = nullptr;
  198. Shape.CoroEnds.clear();
  199. Shape.CoroSizes.clear();
  200. Shape.CoroSuspends.clear();
  201. Shape.FrameTy = nullptr;
  202. Shape.FramePtr = nullptr;
  203. Shape.AllocaSpillBlock = nullptr;
  204. }
  205. static CoroSaveInst *createCoroSave(CoroBeginInst *CoroBegin,
  206. CoroSuspendInst *SuspendInst) {
  207. Module *M = SuspendInst->getModule();
  208. auto *Fn = Intrinsic::getDeclaration(M, Intrinsic::coro_save);
  209. auto *SaveInst =
  210. cast<CoroSaveInst>(CallInst::Create(Fn, CoroBegin, "", SuspendInst));
  211. assert(!SuspendInst->getCoroSave());
  212. SuspendInst->setArgOperand(0, SaveInst);
  213. return SaveInst;
  214. }
  215. // Collect "interesting" coroutine intrinsics.
  216. void coro::Shape::buildFrom(Function &F) {
  217. bool HasFinalSuspend = false;
  218. size_t FinalSuspendIndex = 0;
  219. clear(*this);
  220. SmallVector<CoroFrameInst *, 8> CoroFrames;
  221. SmallVector<CoroSaveInst *, 2> UnusedCoroSaves;
  222. for (Instruction &I : instructions(F)) {
  223. if (auto II = dyn_cast<IntrinsicInst>(&I)) {
  224. switch (II->getIntrinsicID()) {
  225. default:
  226. continue;
  227. case Intrinsic::coro_size:
  228. CoroSizes.push_back(cast<CoroSizeInst>(II));
  229. break;
  230. case Intrinsic::coro_frame:
  231. CoroFrames.push_back(cast<CoroFrameInst>(II));
  232. break;
  233. case Intrinsic::coro_save:
  234. // After optimizations, coro_suspends using this coro_save might have
  235. // been removed, remember orphaned coro_saves to remove them later.
  236. if (II->use_empty())
  237. UnusedCoroSaves.push_back(cast<CoroSaveInst>(II));
  238. break;
  239. case Intrinsic::coro_suspend_retcon: {
  240. auto Suspend = cast<CoroSuspendRetconInst>(II);
  241. CoroSuspends.push_back(Suspend);
  242. break;
  243. }
  244. case Intrinsic::coro_suspend: {
  245. auto Suspend = cast<CoroSuspendInst>(II);
  246. CoroSuspends.push_back(Suspend);
  247. if (Suspend->isFinal()) {
  248. if (HasFinalSuspend)
  249. report_fatal_error(
  250. "Only one suspend point can be marked as final");
  251. HasFinalSuspend = true;
  252. FinalSuspendIndex = CoroSuspends.size() - 1;
  253. }
  254. break;
  255. }
  256. case Intrinsic::coro_begin: {
  257. auto CB = cast<CoroBeginInst>(II);
  258. // Ignore coro id's that aren't pre-split.
  259. auto Id = dyn_cast<CoroIdInst>(CB->getId());
  260. if (Id && !Id->getInfo().isPreSplit())
  261. break;
  262. if (CoroBegin)
  263. report_fatal_error(
  264. "coroutine should have exactly one defining @llvm.coro.begin");
  265. CB->addAttribute(AttributeList::ReturnIndex, Attribute::NonNull);
  266. CB->addAttribute(AttributeList::ReturnIndex, Attribute::NoAlias);
  267. CB->removeAttribute(AttributeList::FunctionIndex,
  268. Attribute::NoDuplicate);
  269. CoroBegin = CB;
  270. break;
  271. }
  272. case Intrinsic::coro_end:
  273. CoroEnds.push_back(cast<CoroEndInst>(II));
  274. if (CoroEnds.back()->isFallthrough()) {
  275. // Make sure that the fallthrough coro.end is the first element in the
  276. // CoroEnds vector.
  277. if (CoroEnds.size() > 1) {
  278. if (CoroEnds.front()->isFallthrough())
  279. report_fatal_error(
  280. "Only one coro.end can be marked as fallthrough");
  281. std::swap(CoroEnds.front(), CoroEnds.back());
  282. }
  283. }
  284. break;
  285. }
  286. }
  287. }
  288. // If for some reason, we were not able to find coro.begin, bailout.
  289. if (!CoroBegin) {
  290. // Replace coro.frame which are supposed to be lowered to the result of
  291. // coro.begin with undef.
  292. auto *Undef = UndefValue::get(Type::getInt8PtrTy(F.getContext()));
  293. for (CoroFrameInst *CF : CoroFrames) {
  294. CF->replaceAllUsesWith(Undef);
  295. CF->eraseFromParent();
  296. }
  297. // Replace all coro.suspend with undef and remove related coro.saves if
  298. // present.
  299. for (AnyCoroSuspendInst *CS : CoroSuspends) {
  300. CS->replaceAllUsesWith(UndefValue::get(CS->getType()));
  301. CS->eraseFromParent();
  302. if (auto *CoroSave = CS->getCoroSave())
  303. CoroSave->eraseFromParent();
  304. }
  305. // Replace all coro.ends with unreachable instruction.
  306. for (CoroEndInst *CE : CoroEnds)
  307. changeToUnreachable(CE, /*UseLLVMTrap=*/false);
  308. return;
  309. }
  310. auto Id = CoroBegin->getId();
  311. switch (auto IdIntrinsic = Id->getIntrinsicID()) {
  312. case Intrinsic::coro_id: {
  313. auto SwitchId = cast<CoroIdInst>(Id);
  314. this->ABI = coro::ABI::Switch;
  315. this->SwitchLowering.HasFinalSuspend = HasFinalSuspend;
  316. this->SwitchLowering.ResumeSwitch = nullptr;
  317. this->SwitchLowering.PromiseAlloca = SwitchId->getPromise();
  318. this->SwitchLowering.ResumeEntryBlock = nullptr;
  319. for (auto AnySuspend : CoroSuspends) {
  320. auto Suspend = dyn_cast<CoroSuspendInst>(AnySuspend);
  321. if (!Suspend) {
  322. AnySuspend->dump();
  323. report_fatal_error("coro.id must be paired with coro.suspend");
  324. }
  325. if (!Suspend->getCoroSave())
  326. createCoroSave(CoroBegin, Suspend);
  327. }
  328. break;
  329. }
  330. case Intrinsic::coro_id_retcon:
  331. case Intrinsic::coro_id_retcon_once: {
  332. auto ContinuationId = cast<AnyCoroIdRetconInst>(Id);
  333. ContinuationId->checkWellFormed();
  334. this->ABI = (IdIntrinsic == Intrinsic::coro_id_retcon
  335. ? coro::ABI::Retcon
  336. : coro::ABI::RetconOnce);
  337. auto Prototype = ContinuationId->getPrototype();
  338. this->RetconLowering.ResumePrototype = Prototype;
  339. this->RetconLowering.Alloc = ContinuationId->getAllocFunction();
  340. this->RetconLowering.Dealloc = ContinuationId->getDeallocFunction();
  341. this->RetconLowering.ReturnBlock = nullptr;
  342. this->RetconLowering.IsFrameInlineInStorage = false;
  343. // Determine the result value types, and make sure they match up with
  344. // the values passed to the suspends.
  345. auto ResultTys = getRetconResultTypes();
  346. for (auto AnySuspend : CoroSuspends) {
  347. auto Suspend = dyn_cast<CoroSuspendRetconInst>(AnySuspend);
  348. if (!Suspend) {
  349. AnySuspend->dump();
  350. report_fatal_error("coro.id.retcon.* must be paired with "
  351. "coro.suspend.retcon");
  352. }
  353. auto SI = Suspend->value_begin(), SE = Suspend->value_end();
  354. auto RI = ResultTys.begin(), RE = ResultTys.end();
  355. for (; SI != SE && RI != RE; ++SI, ++RI) {
  356. if ((*SI)->getType() != *RI) {
  357. Suspend->dump();
  358. Prototype->getFunctionType()->dump();
  359. report_fatal_error("argument to coro.suspend.retcon does not "
  360. "match corresponding prototype function result");
  361. }
  362. }
  363. if (SI != SE || RI != RE) {
  364. Suspend->dump();
  365. Prototype->getFunctionType()->dump();
  366. report_fatal_error("wrong number of arguments to coro.suspend.retcon");
  367. }
  368. }
  369. break;
  370. }
  371. default:
  372. llvm_unreachable("coro.begin is not dependent on a coro.id call");
  373. }
  374. // The coro.free intrinsic is always lowered to the result of coro.begin.
  375. for (CoroFrameInst *CF : CoroFrames) {
  376. CF->replaceAllUsesWith(CoroBegin);
  377. CF->eraseFromParent();
  378. }
  379. // Move final suspend to be the last element in the CoroSuspends vector.
  380. if (ABI == coro::ABI::Switch &&
  381. SwitchLowering.HasFinalSuspend &&
  382. FinalSuspendIndex != CoroSuspends.size() - 1)
  383. std::swap(CoroSuspends[FinalSuspendIndex], CoroSuspends.back());
  384. // Remove orphaned coro.saves.
  385. for (CoroSaveInst *CoroSave : UnusedCoroSaves)
  386. CoroSave->eraseFromParent();
  387. }
  388. static void propagateCallAttrsFromCallee(CallInst *Call, Function *Callee) {
  389. Call->setCallingConv(Callee->getCallingConv());
  390. // TODO: attributes?
  391. }
  392. static void addCallToCallGraph(CallGraph *CG, CallInst *Call, Function *Callee){
  393. if (CG)
  394. (*CG)[Call->getFunction()]->addCalledFunction(Call, (*CG)[Callee]);
  395. }
  396. Value *coro::Shape::emitAlloc(IRBuilder<> &Builder, Value *Size,
  397. CallGraph *CG) const {
  398. switch (ABI) {
  399. case coro::ABI::Switch:
  400. llvm_unreachable("can't allocate memory in coro switch-lowering");
  401. case coro::ABI::Retcon:
  402. case coro::ABI::RetconOnce: {
  403. auto Alloc = RetconLowering.Alloc;
  404. Size = Builder.CreateIntCast(Size,
  405. Alloc->getFunctionType()->getParamType(0),
  406. /*is signed*/ false);
  407. auto *Call = Builder.CreateCall(Alloc, Size);
  408. propagateCallAttrsFromCallee(Call, Alloc);
  409. addCallToCallGraph(CG, Call, Alloc);
  410. return Call;
  411. }
  412. }
  413. }
  414. void coro::Shape::emitDealloc(IRBuilder<> &Builder, Value *Ptr,
  415. CallGraph *CG) const {
  416. switch (ABI) {
  417. case coro::ABI::Switch:
  418. llvm_unreachable("can't allocate memory in coro switch-lowering");
  419. case coro::ABI::Retcon:
  420. case coro::ABI::RetconOnce: {
  421. auto Dealloc = RetconLowering.Dealloc;
  422. Ptr = Builder.CreateBitCast(Ptr,
  423. Dealloc->getFunctionType()->getParamType(0));
  424. auto *Call = Builder.CreateCall(Dealloc, Ptr);
  425. propagateCallAttrsFromCallee(Call, Dealloc);
  426. addCallToCallGraph(CG, Call, Dealloc);
  427. return;
  428. }
  429. }
  430. }
  431. LLVM_ATTRIBUTE_NORETURN
  432. static void fail(const Instruction *I, const char *Reason, Value *V) {
  433. I->dump();
  434. if (V) {
  435. errs() << " Value: ";
  436. V->printAsOperand(llvm::errs());
  437. errs() << '\n';
  438. }
  439. report_fatal_error(Reason);
  440. }
  441. /// Check that the given value is a well-formed prototype for the
  442. /// llvm.coro.id.retcon.* intrinsics.
  443. static void checkWFRetconPrototype(const AnyCoroIdRetconInst *I, Value *V) {
  444. auto F = dyn_cast<Function>(V->stripPointerCasts());
  445. if (!F)
  446. fail(I, "llvm.coro.retcon.* prototype not a Function", V);
  447. auto FT = F->getFunctionType();
  448. if (isa<CoroIdRetconInst>(I)) {
  449. bool ResultOkay;
  450. if (FT->getReturnType()->isPointerTy()) {
  451. ResultOkay = true;
  452. } else if (auto SRetTy = dyn_cast<StructType>(FT->getReturnType())) {
  453. ResultOkay = (!SRetTy->isOpaque() &&
  454. SRetTy->getNumElements() > 0 &&
  455. SRetTy->getElementType(0)->isPointerTy());
  456. } else {
  457. ResultOkay = false;
  458. }
  459. if (!ResultOkay)
  460. fail(I, "llvm.coro.retcon prototype must return pointer as first result",
  461. F);
  462. if (FT->getReturnType() !=
  463. I->getFunction()->getFunctionType()->getReturnType())
  464. fail(I, "llvm.coro.retcon.* prototype return type must be same as"
  465. "current function return type", F);
  466. } else {
  467. // No meaningful validation to do here for llvm.coro.id.unique.once.
  468. }
  469. if (FT->getNumParams() != 2)
  470. fail(I, "llvm.coro.retcon.* prototype must take exactly two parameters", F);
  471. if (!FT->getParamType(0)->isPointerTy())
  472. fail(I, "llvm.coro.retcon.* prototype must take pointer as 1st param", F);
  473. if (!FT->getParamType(1)->isIntegerTy()) // an i1, but not for abi purposes
  474. fail(I, "llvm.coro.retcon.* prototype must take integer as 2nd param", F);
  475. }
  476. /// Check that the given value is a well-formed allocator.
  477. static void checkWFAlloc(const Instruction *I, Value *V) {
  478. auto F = dyn_cast<Function>(V->stripPointerCasts());
  479. if (!F)
  480. fail(I, "llvm.coro.* allocator not a Function", V);
  481. auto FT = F->getFunctionType();
  482. if (!FT->getReturnType()->isPointerTy())
  483. fail(I, "llvm.coro.* allocator must return a pointer", F);
  484. if (FT->getNumParams() != 1 ||
  485. !FT->getParamType(0)->isIntegerTy())
  486. fail(I, "llvm.coro.* allocator must take integer as only param", F);
  487. }
  488. /// Check that the given value is a well-formed deallocator.
  489. static void checkWFDealloc(const Instruction *I, Value *V) {
  490. auto F = dyn_cast<Function>(V->stripPointerCasts());
  491. if (!F)
  492. fail(I, "llvm.coro.* deallocator not a Function", V);
  493. auto FT = F->getFunctionType();
  494. if (!FT->getReturnType()->isVoidTy())
  495. fail(I, "llvm.coro.* deallocator must return void", F);
  496. if (FT->getNumParams() != 1 ||
  497. !FT->getParamType(0)->isPointerTy())
  498. fail(I, "llvm.coro.* deallocator must take pointer as only param", F);
  499. }
  500. static void checkConstantInt(const Instruction *I, Value *V,
  501. const char *Reason) {
  502. if (!isa<ConstantInt>(V)) {
  503. fail(I, Reason, V);
  504. }
  505. }
  506. void AnyCoroIdRetconInst::checkWellFormed() const {
  507. checkConstantInt(this, getArgOperand(SizeArg),
  508. "size argument to coro.id.retcon.* must be constant");
  509. checkConstantInt(this, getArgOperand(AlignArg),
  510. "alignment argument to coro.id.retcon.* must be constant");
  511. checkWFRetconPrototype(this, getArgOperand(PrototypeArg));
  512. checkWFAlloc(this, getArgOperand(AllocArg));
  513. checkWFDealloc(this, getArgOperand(DeallocArg));
  514. }
  515. void LLVMAddCoroEarlyPass(LLVMPassManagerRef PM) {
  516. unwrap(PM)->add(createCoroEarlyPass());
  517. }
  518. void LLVMAddCoroSplitPass(LLVMPassManagerRef PM) {
  519. unwrap(PM)->add(createCoroSplitPass());
  520. }
  521. void LLVMAddCoroElidePass(LLVMPassManagerRef PM) {
  522. unwrap(PM)->add(createCoroElidePass());
  523. }
  524. void LLVMAddCoroCleanupPass(LLVMPassManagerRef PM) {
  525. unwrap(PM)->add(createCoroCleanupPass());
  526. }