xref: /freebsd/contrib/llvm-project/llvm/lib/Transforms/Coroutines/CoroCloner.h (revision 700637cbb5e582861067a11aaca4d053546871d2)
1 //
2 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
3 // See https://llvm.org/LICENSE.txt for license information.
4 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
5 //
6 //===----------------------------------------------------------------------===//
7 // Helper class for splitting a coroutine into separate functions. For example
8 // the returned-continuation coroutine is split into separate continuation
9 // functions.
10 //===----------------------------------------------------------------------===//
11 
12 #ifndef LLVM_LIB_TRANSFORMS_COROUTINES_COROCLONER_H
13 #define LLVM_LIB_TRANSFORMS_COROUTINES_COROCLONER_H
14 
15 #include "llvm/IR/Function.h"
16 #include "llvm/IR/IRBuilder.h"
17 #include "llvm/Support/TimeProfiler.h"
18 #include "llvm/Transforms/Coroutines/ABI.h"
19 #include "llvm/Transforms/Coroutines/CoroInstr.h"
20 #include "llvm/Transforms/Utils/ValueMapper.h"
21 
22 namespace llvm {
23 
24 namespace coro {
25 
26 enum class CloneKind {
27   /// The shared resume function for a switch lowering.
28   SwitchResume,
29 
30   /// The shared unwind function for a switch lowering.
31   SwitchUnwind,
32 
33   /// The shared cleanup function for a switch lowering.
34   SwitchCleanup,
35 
36   /// An individual continuation function.
37   Continuation,
38 
39   /// An async resume function.
40   Async,
41 };
42 
43 class BaseCloner {
44 protected:
45   Function &OrigF;
46   const Twine &Suffix;
47   coro::Shape &Shape;
48   CloneKind FKind;
49   IRBuilder<> Builder;
50   TargetTransformInfo &TTI;
51 
52   ValueToValueMapTy VMap;
53   Function *NewF = nullptr;
54   Value *NewFramePtr = nullptr;
55 
56   /// The active suspend instruction; meaningful only for continuation and async
57   /// ABIs.
58   AnyCoroSuspendInst *ActiveSuspend = nullptr;
59 
60   /// Create a cloner for a continuation lowering.
BaseCloner(Function & OrigF,const Twine & Suffix,coro::Shape & Shape,Function * NewF,AnyCoroSuspendInst * ActiveSuspend,TargetTransformInfo & TTI)61   BaseCloner(Function &OrigF, const Twine &Suffix, coro::Shape &Shape,
62              Function *NewF, AnyCoroSuspendInst *ActiveSuspend,
63              TargetTransformInfo &TTI)
64       : OrigF(OrigF), Suffix(Suffix), Shape(Shape),
65         FKind(Shape.ABI == ABI::Async ? CloneKind::Async
66                                       : CloneKind::Continuation),
67         Builder(OrigF.getContext()), TTI(TTI), NewF(NewF),
68         ActiveSuspend(ActiveSuspend) {
69     assert(Shape.ABI == ABI::Retcon || Shape.ABI == ABI::RetconOnce ||
70            Shape.ABI == ABI::Async);
71     assert(NewF && "need existing function for continuation");
72     assert(ActiveSuspend && "need active suspend point for continuation");
73   }
74 
75 public:
BaseCloner(Function & OrigF,const Twine & Suffix,coro::Shape & Shape,CloneKind FKind,TargetTransformInfo & TTI)76   BaseCloner(Function &OrigF, const Twine &Suffix, coro::Shape &Shape,
77              CloneKind FKind, TargetTransformInfo &TTI)
78       : OrigF(OrigF), Suffix(Suffix), Shape(Shape), FKind(FKind),
79         Builder(OrigF.getContext()), TTI(TTI) {}
80 
~BaseCloner()81   virtual ~BaseCloner() {}
82 
83   /// Create a clone for a continuation lowering.
createClone(Function & OrigF,const Twine & Suffix,coro::Shape & Shape,Function * NewF,AnyCoroSuspendInst * ActiveSuspend,TargetTransformInfo & TTI)84   static Function *createClone(Function &OrigF, const Twine &Suffix,
85                                coro::Shape &Shape, Function *NewF,
86                                AnyCoroSuspendInst *ActiveSuspend,
87                                TargetTransformInfo &TTI) {
88     assert(Shape.ABI == ABI::Retcon || Shape.ABI == ABI::RetconOnce ||
89            Shape.ABI == ABI::Async);
90     TimeTraceScope FunctionScope("BaseCloner");
91 
92     BaseCloner Cloner(OrigF, Suffix, Shape, NewF, ActiveSuspend, TTI);
93     Cloner.create();
94     return Cloner.getFunction();
95   }
96 
getFunction()97   Function *getFunction() const {
98     assert(NewF != nullptr && "declaration not yet set");
99     return NewF;
100   }
101 
102   virtual void create();
103 
104 protected:
isSwitchDestroyFunction()105   bool isSwitchDestroyFunction() {
106     switch (FKind) {
107     case CloneKind::Async:
108     case CloneKind::Continuation:
109     case CloneKind::SwitchResume:
110       return false;
111     case CloneKind::SwitchUnwind:
112     case CloneKind::SwitchCleanup:
113       return true;
114     }
115     llvm_unreachable("Unknown ClonerKind enum");
116   }
117 
118   void replaceEntryBlock();
119   Value *deriveNewFramePointer();
120   void replaceRetconOrAsyncSuspendUses();
121   void replaceCoroSuspends();
122   void replaceCoroEnds();
123   void replaceSwiftErrorOps();
124   void salvageDebugInfo();
125   void handleFinalSuspend();
126 };
127 
128 class SwitchCloner : public BaseCloner {
129 protected:
130   /// Create a cloner for a switch lowering.
SwitchCloner(Function & OrigF,const Twine & Suffix,coro::Shape & Shape,CloneKind FKind,TargetTransformInfo & TTI)131   SwitchCloner(Function &OrigF, const Twine &Suffix, coro::Shape &Shape,
132                CloneKind FKind, TargetTransformInfo &TTI)
133       : BaseCloner(OrigF, Suffix, Shape, FKind, TTI) {}
134 
135   void create() override;
136 
137 public:
138   /// Create a clone for a switch lowering.
createClone(Function & OrigF,const Twine & Suffix,coro::Shape & Shape,CloneKind FKind,TargetTransformInfo & TTI)139   static Function *createClone(Function &OrigF, const Twine &Suffix,
140                                coro::Shape &Shape, CloneKind FKind,
141                                TargetTransformInfo &TTI) {
142     assert(Shape.ABI == ABI::Switch);
143     TimeTraceScope FunctionScope("SwitchCloner");
144 
145     SwitchCloner Cloner(OrigF, Suffix, Shape, FKind, TTI);
146     Cloner.create();
147     return Cloner.getFunction();
148   }
149 };
150 
151 } // end namespace coro
152 
153 } // end namespace llvm
154 
155 #endif // LLVM_LIB_TRANSFORMS_COROUTINES_COROCLONER_H
156