[ASan] Make insertion of version mismatch guard configurable
[llvm-core.git] / lib / Transforms / Coroutines / Coroutines.cpp
blobf39483b275189206c407291722983b5ff6f05b8a
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.
11 //===----------------------------------------------------------------------===//
13 #include "llvm/Transforms/Coroutines.h"
14 #include "llvm-c/Transforms/Coroutines.h"
15 #include "CoroInstr.h"
16 #include "CoroInternal.h"
17 #include "llvm/ADT/SmallVector.h"
18 #include "llvm/ADT/StringRef.h"
19 #include "llvm/Analysis/CallGraph.h"
20 #include "llvm/Analysis/CallGraphSCCPass.h"
21 #include "llvm/Transforms/Utils/Local.h"
22 #include "llvm/IR/Attributes.h"
23 #include "llvm/IR/CallSite.h"
24 #include "llvm/IR/Constants.h"
25 #include "llvm/IR/DerivedTypes.h"
26 #include "llvm/IR/Function.h"
27 #include "llvm/IR/InstIterator.h"
28 #include "llvm/IR/Instructions.h"
29 #include "llvm/IR/IntrinsicInst.h"
30 #include "llvm/IR/Intrinsics.h"
31 #include "llvm/IR/LegacyPassManager.h"
32 #include "llvm/IR/Module.h"
33 #include "llvm/IR/Type.h"
34 #include "llvm/Support/Casting.h"
35 #include "llvm/Support/ErrorHandling.h"
36 #include "llvm/Transforms/IPO.h"
37 #include "llvm/Transforms/IPO/PassManagerBuilder.h"
38 #include <cassert>
39 #include <cstddef>
40 #include <utility>
42 using namespace llvm;
44 void llvm::initializeCoroutines(PassRegistry &Registry) {
45 initializeCoroEarlyPass(Registry);
46 initializeCoroSplitPass(Registry);
47 initializeCoroElidePass(Registry);
48 initializeCoroCleanupPass(Registry);
51 static void addCoroutineOpt0Passes(const PassManagerBuilder &Builder,
52 legacy::PassManagerBase &PM) {
53 PM.add(createCoroSplitPass());
54 PM.add(createCoroElidePass());
56 PM.add(createBarrierNoopPass());
57 PM.add(createCoroCleanupPass());
60 static void addCoroutineEarlyPasses(const PassManagerBuilder &Builder,
61 legacy::PassManagerBase &PM) {
62 PM.add(createCoroEarlyPass());
65 static void addCoroutineScalarOptimizerPasses(const PassManagerBuilder &Builder,
66 legacy::PassManagerBase &PM) {
67 PM.add(createCoroElidePass());
70 static void addCoroutineSCCPasses(const PassManagerBuilder &Builder,
71 legacy::PassManagerBase &PM) {
72 PM.add(createCoroSplitPass());
75 static void addCoroutineOptimizerLastPasses(const PassManagerBuilder &Builder,
76 legacy::PassManagerBase &PM) {
77 PM.add(createCoroCleanupPass());
80 void llvm::addCoroutinePassesToExtensionPoints(PassManagerBuilder &Builder) {
81 Builder.addExtension(PassManagerBuilder::EP_EarlyAsPossible,
82 addCoroutineEarlyPasses);
83 Builder.addExtension(PassManagerBuilder::EP_EnabledOnOptLevel0,
84 addCoroutineOpt0Passes);
85 Builder.addExtension(PassManagerBuilder::EP_CGSCCOptimizerLate,
86 addCoroutineSCCPasses);
87 Builder.addExtension(PassManagerBuilder::EP_ScalarOptimizerLate,
88 addCoroutineScalarOptimizerPasses);
89 Builder.addExtension(PassManagerBuilder::EP_OptimizerLast,
90 addCoroutineOptimizerLastPasses);
93 // Construct the lowerer base class and initialize its members.
94 coro::LowererBase::LowererBase(Module &M)
95 : TheModule(M), Context(M.getContext()),
96 Int8Ptr(Type::getInt8PtrTy(Context)),
97 ResumeFnType(FunctionType::get(Type::getVoidTy(Context), Int8Ptr,
98 /*isVarArg=*/false)),
99 NullPtr(ConstantPointerNull::get(Int8Ptr)) {}
101 // Creates a sequence of instructions to obtain a resume function address using
102 // llvm.coro.subfn.addr. It generates the following sequence:
104 // call i8* @llvm.coro.subfn.addr(i8* %Arg, i8 %index)
105 // bitcast i8* %2 to void(i8*)*
107 Value *coro::LowererBase::makeSubFnCall(Value *Arg, int Index,
108 Instruction *InsertPt) {
109 auto *IndexVal = ConstantInt::get(Type::getInt8Ty(Context), Index);
110 auto *Fn = Intrinsic::getDeclaration(&TheModule, Intrinsic::coro_subfn_addr);
112 assert(Index >= CoroSubFnInst::IndexFirst &&
113 Index < CoroSubFnInst::IndexLast &&
114 "makeSubFnCall: Index value out of range");
115 auto *Call = CallInst::Create(Fn, {Arg, IndexVal}, "", InsertPt);
117 auto *Bitcast =
118 new BitCastInst(Call, ResumeFnType->getPointerTo(), "", InsertPt);
119 return Bitcast;
122 #ifndef NDEBUG
123 static bool isCoroutineIntrinsicName(StringRef Name) {
124 // NOTE: Must be sorted!
125 static const char *const CoroIntrinsics[] = {
126 "llvm.coro.alloc",
127 "llvm.coro.begin",
128 "llvm.coro.destroy",
129 "llvm.coro.done",
130 "llvm.coro.end",
131 "llvm.coro.frame",
132 "llvm.coro.free",
133 "llvm.coro.id",
134 "llvm.coro.id.retcon",
135 "llvm.coro.id.retcon.once",
136 "llvm.coro.noop",
137 "llvm.coro.param",
138 "llvm.coro.prepare.retcon",
139 "llvm.coro.promise",
140 "llvm.coro.resume",
141 "llvm.coro.save",
142 "llvm.coro.size",
143 "llvm.coro.subfn.addr",
144 "llvm.coro.suspend",
145 "llvm.coro.suspend.retcon",
147 return Intrinsic::lookupLLVMIntrinsicByName(CoroIntrinsics, Name) != -1;
149 #endif
151 // Verifies if a module has named values listed. Also, in debug mode verifies
152 // that names are intrinsic names.
153 bool coro::declaresIntrinsics(Module &M,
154 std::initializer_list<StringRef> List) {
155 for (StringRef Name : List) {
156 assert(isCoroutineIntrinsicName(Name) && "not a coroutine intrinsic");
157 if (M.getNamedValue(Name))
158 return true;
161 return false;
164 // Replace all coro.frees associated with the provided CoroId either with 'null'
165 // if Elide is true and with its frame parameter otherwise.
166 void coro::replaceCoroFree(CoroIdInst *CoroId, bool Elide) {
167 SmallVector<CoroFreeInst *, 4> CoroFrees;
168 for (User *U : CoroId->users())
169 if (auto CF = dyn_cast<CoroFreeInst>(U))
170 CoroFrees.push_back(CF);
172 if (CoroFrees.empty())
173 return;
175 Value *Replacement =
176 Elide ? ConstantPointerNull::get(Type::getInt8PtrTy(CoroId->getContext()))
177 : CoroFrees.front()->getFrame();
179 for (CoroFreeInst *CF : CoroFrees) {
180 CF->replaceAllUsesWith(Replacement);
181 CF->eraseFromParent();
185 // FIXME: This code is stolen from CallGraph::addToCallGraph(Function *F), which
186 // happens to be private. It is better for this functionality exposed by the
187 // CallGraph.
188 static void buildCGN(CallGraph &CG, CallGraphNode *Node) {
189 Function *F = Node->getFunction();
191 // Look for calls by this function.
192 for (Instruction &I : instructions(F))
193 if (auto *Call = dyn_cast<CallBase>(&I)) {
194 const Function *Callee = Call->getCalledFunction();
195 if (!Callee || !Intrinsic::isLeaf(Callee->getIntrinsicID()))
196 // Indirect calls of intrinsics are not allowed so no need to check.
197 // We can be more precise here by using TargetArg returned by
198 // Intrinsic::isLeaf.
199 Node->addCalledFunction(Call, CG.getCallsExternalNode());
200 else if (!Callee->isIntrinsic())
201 Node->addCalledFunction(Call, CG.getOrInsertFunction(Callee));
205 // Rebuild CGN after we extracted parts of the code from ParentFunc into
206 // NewFuncs. Builds CGNs for the NewFuncs and adds them to the current SCC.
207 void coro::updateCallGraph(Function &ParentFunc, ArrayRef<Function *> NewFuncs,
208 CallGraph &CG, CallGraphSCC &SCC) {
209 // Rebuild CGN from scratch for the ParentFunc
210 auto *ParentNode = CG[&ParentFunc];
211 ParentNode->removeAllCalledFunctions();
212 buildCGN(CG, ParentNode);
214 SmallVector<CallGraphNode *, 8> Nodes(SCC.begin(), SCC.end());
216 for (Function *F : NewFuncs) {
217 CallGraphNode *Callee = CG.getOrInsertFunction(F);
218 Nodes.push_back(Callee);
219 buildCGN(CG, Callee);
222 SCC.initialize(Nodes);
225 static void clear(coro::Shape &Shape) {
226 Shape.CoroBegin = nullptr;
227 Shape.CoroEnds.clear();
228 Shape.CoroSizes.clear();
229 Shape.CoroSuspends.clear();
231 Shape.FrameTy = nullptr;
232 Shape.FramePtr = nullptr;
233 Shape.AllocaSpillBlock = nullptr;
236 static CoroSaveInst *createCoroSave(CoroBeginInst *CoroBegin,
237 CoroSuspendInst *SuspendInst) {
238 Module *M = SuspendInst->getModule();
239 auto *Fn = Intrinsic::getDeclaration(M, Intrinsic::coro_save);
240 auto *SaveInst =
241 cast<CoroSaveInst>(CallInst::Create(Fn, CoroBegin, "", SuspendInst));
242 assert(!SuspendInst->getCoroSave());
243 SuspendInst->setArgOperand(0, SaveInst);
244 return SaveInst;
247 // Collect "interesting" coroutine intrinsics.
248 void coro::Shape::buildFrom(Function &F) {
249 bool HasFinalSuspend = false;
250 size_t FinalSuspendIndex = 0;
251 clear(*this);
252 SmallVector<CoroFrameInst *, 8> CoroFrames;
253 SmallVector<CoroSaveInst *, 2> UnusedCoroSaves;
255 for (Instruction &I : instructions(F)) {
256 if (auto II = dyn_cast<IntrinsicInst>(&I)) {
257 switch (II->getIntrinsicID()) {
258 default:
259 continue;
260 case Intrinsic::coro_size:
261 CoroSizes.push_back(cast<CoroSizeInst>(II));
262 break;
263 case Intrinsic::coro_frame:
264 CoroFrames.push_back(cast<CoroFrameInst>(II));
265 break;
266 case Intrinsic::coro_save:
267 // After optimizations, coro_suspends using this coro_save might have
268 // been removed, remember orphaned coro_saves to remove them later.
269 if (II->use_empty())
270 UnusedCoroSaves.push_back(cast<CoroSaveInst>(II));
271 break;
272 case Intrinsic::coro_suspend_retcon: {
273 auto Suspend = cast<CoroSuspendRetconInst>(II);
274 CoroSuspends.push_back(Suspend);
275 break;
277 case Intrinsic::coro_suspend: {
278 auto Suspend = cast<CoroSuspendInst>(II);
279 CoroSuspends.push_back(Suspend);
280 if (Suspend->isFinal()) {
281 if (HasFinalSuspend)
282 report_fatal_error(
283 "Only one suspend point can be marked as final");
284 HasFinalSuspend = true;
285 FinalSuspendIndex = CoroSuspends.size() - 1;
287 break;
289 case Intrinsic::coro_begin: {
290 auto CB = cast<CoroBeginInst>(II);
292 // Ignore coro id's that aren't pre-split.
293 auto Id = dyn_cast<CoroIdInst>(CB->getId());
294 if (Id && !Id->getInfo().isPreSplit())
295 break;
297 if (CoroBegin)
298 report_fatal_error(
299 "coroutine should have exactly one defining @llvm.coro.begin");
300 CB->addAttribute(AttributeList::ReturnIndex, Attribute::NonNull);
301 CB->addAttribute(AttributeList::ReturnIndex, Attribute::NoAlias);
302 CB->removeAttribute(AttributeList::FunctionIndex,
303 Attribute::NoDuplicate);
304 CoroBegin = CB;
305 break;
307 case Intrinsic::coro_end:
308 CoroEnds.push_back(cast<CoroEndInst>(II));
309 if (CoroEnds.back()->isFallthrough()) {
310 // Make sure that the fallthrough coro.end is the first element in the
311 // CoroEnds vector.
312 if (CoroEnds.size() > 1) {
313 if (CoroEnds.front()->isFallthrough())
314 report_fatal_error(
315 "Only one coro.end can be marked as fallthrough");
316 std::swap(CoroEnds.front(), CoroEnds.back());
319 break;
324 // If for some reason, we were not able to find coro.begin, bailout.
325 if (!CoroBegin) {
326 // Replace coro.frame which are supposed to be lowered to the result of
327 // coro.begin with undef.
328 auto *Undef = UndefValue::get(Type::getInt8PtrTy(F.getContext()));
329 for (CoroFrameInst *CF : CoroFrames) {
330 CF->replaceAllUsesWith(Undef);
331 CF->eraseFromParent();
334 // Replace all coro.suspend with undef and remove related coro.saves if
335 // present.
336 for (AnyCoroSuspendInst *CS : CoroSuspends) {
337 CS->replaceAllUsesWith(UndefValue::get(CS->getType()));
338 CS->eraseFromParent();
339 if (auto *CoroSave = CS->getCoroSave())
340 CoroSave->eraseFromParent();
343 // Replace all coro.ends with unreachable instruction.
344 for (CoroEndInst *CE : CoroEnds)
345 changeToUnreachable(CE, /*UseLLVMTrap=*/false);
347 return;
350 auto Id = CoroBegin->getId();
351 switch (auto IdIntrinsic = Id->getIntrinsicID()) {
352 case Intrinsic::coro_id: {
353 auto SwitchId = cast<CoroIdInst>(Id);
354 this->ABI = coro::ABI::Switch;
355 this->SwitchLowering.HasFinalSuspend = HasFinalSuspend;
356 this->SwitchLowering.ResumeSwitch = nullptr;
357 this->SwitchLowering.PromiseAlloca = SwitchId->getPromise();
358 this->SwitchLowering.ResumeEntryBlock = nullptr;
360 for (auto AnySuspend : CoroSuspends) {
361 auto Suspend = dyn_cast<CoroSuspendInst>(AnySuspend);
362 if (!Suspend) {
363 #ifndef NDEBUG
364 AnySuspend->dump();
365 #endif
366 report_fatal_error("coro.id must be paired with coro.suspend");
369 if (!Suspend->getCoroSave())
370 createCoroSave(CoroBegin, Suspend);
372 break;
375 case Intrinsic::coro_id_retcon:
376 case Intrinsic::coro_id_retcon_once: {
377 auto ContinuationId = cast<AnyCoroIdRetconInst>(Id);
378 ContinuationId->checkWellFormed();
379 this->ABI = (IdIntrinsic == Intrinsic::coro_id_retcon
380 ? coro::ABI::Retcon
381 : coro::ABI::RetconOnce);
382 auto Prototype = ContinuationId->getPrototype();
383 this->RetconLowering.ResumePrototype = Prototype;
384 this->RetconLowering.Alloc = ContinuationId->getAllocFunction();
385 this->RetconLowering.Dealloc = ContinuationId->getDeallocFunction();
386 this->RetconLowering.ReturnBlock = nullptr;
387 this->RetconLowering.IsFrameInlineInStorage = false;
389 // Determine the result value types, and make sure they match up with
390 // the values passed to the suspends.
391 auto ResultTys = getRetconResultTypes();
392 auto ResumeTys = getRetconResumeTypes();
394 for (auto AnySuspend : CoroSuspends) {
395 auto Suspend = dyn_cast<CoroSuspendRetconInst>(AnySuspend);
396 if (!Suspend) {
397 #ifndef NDEBUG
398 AnySuspend->dump();
399 #endif
400 report_fatal_error("coro.id.retcon.* must be paired with "
401 "coro.suspend.retcon");
404 // Check that the argument types of the suspend match the results.
405 auto SI = Suspend->value_begin(), SE = Suspend->value_end();
406 auto RI = ResultTys.begin(), RE = ResultTys.end();
407 for (; SI != SE && RI != RE; ++SI, ++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;
419 #ifndef NDEBUG
420 Suspend->dump();
421 Prototype->getFunctionType()->dump();
422 #endif
423 report_fatal_error("argument to coro.suspend.retcon does not "
424 "match corresponding prototype function result");
427 if (SI != SE || RI != RE) {
428 #ifndef NDEBUG
429 Suspend->dump();
430 Prototype->getFunctionType()->dump();
431 #endif
432 report_fatal_error("wrong number of arguments to coro.suspend.retcon");
435 // Check that the result type of the suspend matches the resume types.
436 Type *SResultTy = Suspend->getType();
437 ArrayRef<Type*> SuspendResultTys;
438 if (SResultTy->isVoidTy()) {
439 // leave as empty array
440 } else if (auto SResultStructTy = dyn_cast<StructType>(SResultTy)) {
441 SuspendResultTys = SResultStructTy->elements();
442 } else {
443 // forms an ArrayRef using SResultTy, be careful
444 SuspendResultTys = SResultTy;
446 if (SuspendResultTys.size() != ResumeTys.size()) {
447 #ifndef NDEBUG
448 Suspend->dump();
449 Prototype->getFunctionType()->dump();
450 #endif
451 report_fatal_error("wrong number of results from coro.suspend.retcon");
453 for (size_t I = 0, E = ResumeTys.size(); I != E; ++I) {
454 if (SuspendResultTys[I] != ResumeTys[I]) {
455 #ifndef NDEBUG
456 Suspend->dump();
457 Prototype->getFunctionType()->dump();
458 #endif
459 report_fatal_error("result from coro.suspend.retcon does not "
460 "match corresponding prototype function param");
464 break;
467 default:
468 llvm_unreachable("coro.begin is not dependent on a coro.id call");
471 // The coro.free intrinsic is always lowered to the result of coro.begin.
472 for (CoroFrameInst *CF : CoroFrames) {
473 CF->replaceAllUsesWith(CoroBegin);
474 CF->eraseFromParent();
477 // Move final suspend to be the last element in the CoroSuspends vector.
478 if (ABI == coro::ABI::Switch &&
479 SwitchLowering.HasFinalSuspend &&
480 FinalSuspendIndex != CoroSuspends.size() - 1)
481 std::swap(CoroSuspends[FinalSuspendIndex], CoroSuspends.back());
483 // Remove orphaned coro.saves.
484 for (CoroSaveInst *CoroSave : UnusedCoroSaves)
485 CoroSave->eraseFromParent();
488 static void propagateCallAttrsFromCallee(CallInst *Call, Function *Callee) {
489 Call->setCallingConv(Callee->getCallingConv());
490 // TODO: attributes?
493 static void addCallToCallGraph(CallGraph *CG, CallInst *Call, Function *Callee){
494 if (CG)
495 (*CG)[Call->getFunction()]->addCalledFunction(Call, (*CG)[Callee]);
498 Value *coro::Shape::emitAlloc(IRBuilder<> &Builder, Value *Size,
499 CallGraph *CG) const {
500 switch (ABI) {
501 case coro::ABI::Switch:
502 llvm_unreachable("can't allocate memory in coro switch-lowering");
504 case coro::ABI::Retcon:
505 case coro::ABI::RetconOnce: {
506 auto Alloc = RetconLowering.Alloc;
507 Size = Builder.CreateIntCast(Size,
508 Alloc->getFunctionType()->getParamType(0),
509 /*is signed*/ false);
510 auto *Call = Builder.CreateCall(Alloc, Size);
511 propagateCallAttrsFromCallee(Call, Alloc);
512 addCallToCallGraph(CG, Call, Alloc);
513 return Call;
516 llvm_unreachable("Unknown coro::ABI enum");
519 void coro::Shape::emitDealloc(IRBuilder<> &Builder, Value *Ptr,
520 CallGraph *CG) const {
521 switch (ABI) {
522 case coro::ABI::Switch:
523 llvm_unreachable("can't allocate memory in coro switch-lowering");
525 case coro::ABI::Retcon:
526 case coro::ABI::RetconOnce: {
527 auto Dealloc = RetconLowering.Dealloc;
528 Ptr = Builder.CreateBitCast(Ptr,
529 Dealloc->getFunctionType()->getParamType(0));
530 auto *Call = Builder.CreateCall(Dealloc, Ptr);
531 propagateCallAttrsFromCallee(Call, Dealloc);
532 addCallToCallGraph(CG, Call, Dealloc);
533 return;
536 llvm_unreachable("Unknown coro::ABI enum");
539 LLVM_ATTRIBUTE_NORETURN
540 static void fail(const Instruction *I, const char *Reason, Value *V) {
541 #ifndef NDEBUG
542 I->dump();
543 if (V) {
544 errs() << " Value: ";
545 V->printAsOperand(llvm::errs());
546 errs() << '\n';
548 #endif
549 report_fatal_error(Reason);
552 /// Check that the given value is a well-formed prototype for the
553 /// llvm.coro.id.retcon.* intrinsics.
554 static void checkWFRetconPrototype(const AnyCoroIdRetconInst *I, Value *V) {
555 auto F = dyn_cast<Function>(V->stripPointerCasts());
556 if (!F)
557 fail(I, "llvm.coro.id.retcon.* prototype not a Function", V);
559 auto FT = F->getFunctionType();
561 if (isa<CoroIdRetconInst>(I)) {
562 bool ResultOkay;
563 if (FT->getReturnType()->isPointerTy()) {
564 ResultOkay = true;
565 } else if (auto SRetTy = dyn_cast<StructType>(FT->getReturnType())) {
566 ResultOkay = (!SRetTy->isOpaque() &&
567 SRetTy->getNumElements() > 0 &&
568 SRetTy->getElementType(0)->isPointerTy());
569 } else {
570 ResultOkay = false;
572 if (!ResultOkay)
573 fail(I, "llvm.coro.id.retcon prototype must return pointer as first "
574 "result", F);
576 if (FT->getReturnType() !=
577 I->getFunction()->getFunctionType()->getReturnType())
578 fail(I, "llvm.coro.id.retcon prototype return type must be same as"
579 "current function return type", F);
580 } else {
581 // No meaningful validation to do here for llvm.coro.id.unique.once.
584 if (FT->getNumParams() == 0 || !FT->getParamType(0)->isPointerTy())
585 fail(I, "llvm.coro.id.retcon.* prototype must take pointer as "
586 "its first parameter", F);
589 /// Check that the given value is a well-formed allocator.
590 static void checkWFAlloc(const Instruction *I, Value *V) {
591 auto F = dyn_cast<Function>(V->stripPointerCasts());
592 if (!F)
593 fail(I, "llvm.coro.* allocator not a Function", V);
595 auto FT = F->getFunctionType();
596 if (!FT->getReturnType()->isPointerTy())
597 fail(I, "llvm.coro.* allocator must return a pointer", F);
599 if (FT->getNumParams() != 1 ||
600 !FT->getParamType(0)->isIntegerTy())
601 fail(I, "llvm.coro.* allocator must take integer as only param", F);
604 /// Check that the given value is a well-formed deallocator.
605 static void checkWFDealloc(const Instruction *I, Value *V) {
606 auto F = dyn_cast<Function>(V->stripPointerCasts());
607 if (!F)
608 fail(I, "llvm.coro.* deallocator not a Function", V);
610 auto FT = F->getFunctionType();
611 if (!FT->getReturnType()->isVoidTy())
612 fail(I, "llvm.coro.* deallocator must return void", F);
614 if (FT->getNumParams() != 1 ||
615 !FT->getParamType(0)->isPointerTy())
616 fail(I, "llvm.coro.* deallocator must take pointer as only param", F);
619 static void checkConstantInt(const Instruction *I, Value *V,
620 const char *Reason) {
621 if (!isa<ConstantInt>(V)) {
622 fail(I, Reason, V);
626 void AnyCoroIdRetconInst::checkWellFormed() const {
627 checkConstantInt(this, getArgOperand(SizeArg),
628 "size argument to coro.id.retcon.* must be constant");
629 checkConstantInt(this, getArgOperand(AlignArg),
630 "alignment argument to coro.id.retcon.* must be constant");
631 checkWFRetconPrototype(this, getArgOperand(PrototypeArg));
632 checkWFAlloc(this, getArgOperand(AllocArg));
633 checkWFDealloc(this, getArgOperand(DeallocArg));
636 void LLVMAddCoroEarlyPass(LLVMPassManagerRef PM) {
637 unwrap(PM)->add(createCoroEarlyPass());
640 void LLVMAddCoroSplitPass(LLVMPassManagerRef PM) {
641 unwrap(PM)->add(createCoroSplitPass());
644 void LLVMAddCoroElidePass(LLVMPassManagerRef PM) {
645 unwrap(PM)->add(createCoroElidePass());
648 void LLVMAddCoroCleanupPass(LLVMPassManagerRef PM) {
649 unwrap(PM)->add(createCoroCleanupPass());