20
20
using namespace clang ;
21
21
using namespace clang ::interp;
22
22
23
- Function *ByteCodeEmitter::compileFunc (const FunctionDecl *FuncDecl) {
23
+ void ByteCodeEmitter::compileFunc (const FunctionDecl *FuncDecl,
24
+ Function *Func) {
25
+ assert (FuncDecl);
26
+ assert (Func);
24
27
25
28
// Manually created functions that haven't been assigned proper
26
29
// parameters yet.
27
30
if (!FuncDecl->param_empty () && !FuncDecl->param_begin ())
28
- return nullptr ;
31
+ return ;
32
+
33
+ if (!FuncDecl->isDefined ())
34
+ return ;
29
35
30
- bool IsLambdaStaticInvoker = false ;
36
+ // Set up lambda captures.
31
37
if (const auto *MD = dyn_cast<CXXMethodDecl>(FuncDecl);
32
- MD && MD->isLambdaStaticInvoker ()) {
33
- // For a lambda static invoker, we might have to pick a specialized
34
- // version if the lambda is generic. In that case, the picked function
35
- // will *NOT* be a static invoker anymore. However, it will still
36
- // be a non-static member function, this (usually) requiring an
37
- // instance pointer. We suppress that later in this function.
38
- IsLambdaStaticInvoker = true ;
39
-
40
- const CXXRecordDecl *ClosureClass = MD->getParent ();
41
- assert (ClosureClass->captures_begin () == ClosureClass->captures_end ());
42
- if (ClosureClass->isGenericLambda ()) {
43
- const CXXMethodDecl *LambdaCallOp = ClosureClass->getLambdaCallOperator ();
44
- assert (MD->isFunctionTemplateSpecialization () &&
45
- " A generic lambda's static-invoker function must be a "
46
- " template specialization" );
47
- const TemplateArgumentList *TAL = MD->getTemplateSpecializationArgs ();
48
- FunctionTemplateDecl *CallOpTemplate =
49
- LambdaCallOp->getDescribedFunctionTemplate ();
50
- void *InsertPos = nullptr ;
51
- const FunctionDecl *CorrespondingCallOpSpecialization =
52
- CallOpTemplate->findSpecialization (TAL->asArray (), InsertPos);
53
- assert (CorrespondingCallOpSpecialization);
54
- FuncDecl = cast<CXXMethodDecl>(CorrespondingCallOpSpecialization);
55
- }
56
- }
38
+ MD && isLambdaCallOperator (MD)) {
39
+ // Set up lambda capture to closure record field mapping.
40
+ const Record *R = P.getOrCreateRecord (MD->getParent ());
41
+ assert (R);
42
+ llvm::DenseMap<const ValueDecl *, FieldDecl *> LC;
43
+ FieldDecl *LTC;
57
44
58
- // Set up argument indices.
59
- unsigned ParamOffset = 0 ;
60
- SmallVector<PrimType, 8 > ParamTypes;
61
- SmallVector<unsigned , 8 > ParamOffsets;
62
- llvm::DenseMap<unsigned , Function::ParamDescriptor> ParamDescriptors;
63
-
64
- // If the return is not a primitive, a pointer to the storage where the
65
- // value is initialized in is passed as the first argument. See 'RVO'
66
- // elsewhere in the code.
67
- QualType Ty = FuncDecl->getReturnType ();
68
- bool HasRVO = false ;
69
- if (!Ty->isVoidType () && !Ctx.classify (Ty)) {
70
- HasRVO = true ;
71
- ParamTypes.push_back (PT_Ptr);
72
- ParamOffsets.push_back (ParamOffset);
73
- ParamOffset += align (primSize (PT_Ptr));
74
- }
45
+ MD->getParent ()->getCaptureFields (LC, LTC);
75
46
76
- // If the function decl is a member decl, the next parameter is
77
- // the 'this' pointer. This parameter is pop()ed from the
78
- // InterpStack when calling the function.
79
- bool HasThisPointer = false ;
80
- if (const auto *MD = dyn_cast<CXXMethodDecl>(FuncDecl)) {
81
- if (!IsLambdaStaticInvoker) {
82
- HasThisPointer = MD->isInstance ();
83
- if (MD->isImplicitObjectMemberFunction ()) {
84
- ParamTypes.push_back (PT_Ptr);
85
- ParamOffsets.push_back (ParamOffset);
86
- ParamOffset += align (primSize (PT_Ptr));
87
- }
47
+ for (auto Cap : LC) {
48
+ unsigned Offset = R->getField (Cap.second )->Offset ;
49
+ this ->LambdaCaptures [Cap.first ] = {
50
+ Offset, Cap.second ->getType ()->isReferenceType ()};
88
51
}
89
-
90
- // Set up lambda capture to closure record field mapping.
91
- if (isLambdaCallOperator (MD)) {
92
- // The parent record needs to be complete, we need to know about all
93
- // the lambda captures.
94
- if (!MD->getParent ()->isCompleteDefinition ())
95
- return nullptr ;
96
-
97
- const Record *R = P.getOrCreateRecord (MD->getParent ());
98
- llvm::DenseMap<const ValueDecl *, FieldDecl *> LC;
99
- FieldDecl *LTC;
100
-
101
- MD->getParent ()->getCaptureFields (LC, LTC);
102
-
103
- for (auto Cap : LC) {
104
- // Static lambdas cannot have any captures. If this one does,
105
- // it has already been diagnosed and we can only ignore it.
106
- if (MD->isStatic ())
107
- return nullptr ;
108
-
109
- unsigned Offset = R->getField (Cap.second )->Offset ;
110
- this ->LambdaCaptures [Cap.first ] = {
111
- Offset, Cap.second ->getType ()->isReferenceType ()};
112
- }
113
- if (LTC) {
114
- QualType CaptureType = R->getField (LTC)->Decl ->getType ();
115
- this ->LambdaThisCapture = {R->getField (LTC)->Offset ,
116
- CaptureType->isReferenceType () ||
117
- CaptureType->isPointerType ()};
118
- }
52
+ if (LTC) {
53
+ QualType CaptureType = R->getField (LTC)->Decl ->getType ();
54
+ this ->LambdaThisCapture = {R->getField (LTC)->Offset ,
55
+ CaptureType->isPointerOrReferenceType ()};
119
56
}
120
57
}
121
58
122
- // Assign descriptors to all parameters.
123
- // Composite objects are lowered to pointers.
124
- for (const ParmVarDecl *PD : FuncDecl->parameters ()) {
59
+ // Register parameters with their offset.
60
+ unsigned ParamIndex = 0 ;
61
+ unsigned Drop = Func->hasRVO () +
62
+ (Func->hasThisPointer () && !Func->isThisPointerExplicit ());
63
+ for (auto ParamOffset : llvm::drop_begin (Func->ParamOffsets , Drop)) {
64
+ const ParmVarDecl *PD = FuncDecl->parameters ()[ParamIndex];
125
65
std::optional<PrimType> T = Ctx.classify (PD->getType ());
126
- PrimType PT = T.value_or (PT_Ptr);
127
- Descriptor *Desc = P.createDescriptor (PD, PT);
128
- ParamDescriptors.insert ({ParamOffset, {PT, Desc}});
129
- Params.insert ({PD, {ParamOffset, T != std::nullopt}});
130
- ParamOffsets.push_back (ParamOffset);
131
- ParamOffset += align (primSize (PT));
132
- ParamTypes.push_back (PT);
133
- }
134
-
135
- // Create a handle over the emitted code.
136
- Function *Func = P.getFunction (FuncDecl);
137
- if (!Func) {
138
- Func = P.createFunction (FuncDecl, ParamOffset, std::move (ParamTypes),
139
- std::move (ParamDescriptors),
140
- std::move (ParamOffsets), HasThisPointer, HasRVO);
141
- }
142
-
143
- assert (Func);
144
- // For not-yet-defined functions, we only create a Function instance and
145
- // compile their body later.
146
- if (!FuncDecl->isDefined () ||
147
- (FuncDecl->willHaveBody () && !FuncDecl->hasBody ())) {
148
- Func->setDefined (false );
149
- return Func;
66
+ this ->Params .insert ({PD, {ParamOffset, T != std::nullopt}});
67
+ ++ParamIndex;
150
68
}
151
69
152
70
Func->setDefined (true );
153
71
154
72
// Lambda static invokers are a special case that we emit custom code for.
155
- bool IsEligibleForCompilation = false ;
156
- if (const auto *MD = dyn_cast<CXXMethodDecl>(FuncDecl))
157
- IsEligibleForCompilation = MD->isLambdaStaticInvoker ();
158
- if (!IsEligibleForCompilation)
159
- IsEligibleForCompilation =
160
- FuncDecl->isConstexpr () || FuncDecl->hasAttr <MSConstexprAttr>();
73
+ bool IsEligibleForCompilation = Func->isLambdaStaticInvoker () ||
74
+ FuncDecl->isConstexpr () ||
75
+ FuncDecl->hasAttr <MSConstexprAttr>();
161
76
162
77
// Compile the function body.
163
78
if (!IsEligibleForCompilation || !visitFunc (FuncDecl)) {
164
79
Func->setIsFullyCompiled (true );
165
- return Func ;
80
+ return ;
166
81
}
167
82
168
83
// Create scopes from descriptors.
@@ -175,48 +90,6 @@ Function *ByteCodeEmitter::compileFunc(const FunctionDecl *FuncDecl) {
175
90
Func->setCode (NextLocalOffset, std::move (Code), std::move (SrcMap),
176
91
std::move (Scopes), FuncDecl->hasBody ());
177
92
Func->setIsFullyCompiled (true );
178
- return Func;
179
- }
180
-
181
- // / Compile an ObjC block, i.e. ^(){}, that thing.
182
- // /
183
- // / FIXME: We do not support calling the block though, so we create a function
184
- // / here but do not compile any code for it.
185
- Function *ByteCodeEmitter::compileObjCBlock (const BlockExpr *BE) {
186
- const BlockDecl *BD = BE->getBlockDecl ();
187
- // Set up argument indices.
188
- unsigned ParamOffset = 0 ;
189
- SmallVector<PrimType, 8 > ParamTypes;
190
- SmallVector<unsigned , 8 > ParamOffsets;
191
- llvm::DenseMap<unsigned , Function::ParamDescriptor> ParamDescriptors;
192
-
193
- // Assign descriptors to all parameters.
194
- // Composite objects are lowered to pointers.
195
- for (const ParmVarDecl *PD : BD->parameters ()) {
196
- std::optional<PrimType> T = Ctx.classify (PD->getType ());
197
- PrimType PT = T.value_or (PT_Ptr);
198
- Descriptor *Desc = P.createDescriptor (PD, PT);
199
- ParamDescriptors.insert ({ParamOffset, {PT, Desc}});
200
- Params.insert ({PD, {ParamOffset, T != std::nullopt}});
201
- ParamOffsets.push_back (ParamOffset);
202
- ParamOffset += align (primSize (PT));
203
- ParamTypes.push_back (PT);
204
- }
205
-
206
- if (BD->hasCaptures ())
207
- return nullptr ;
208
-
209
- // Create a handle over the emitted code.
210
- Function *Func =
211
- P.createFunction (BE, ParamOffset, std::move (ParamTypes),
212
- std::move (ParamDescriptors), std::move (ParamOffsets),
213
- /* HasThisPointer=*/ false , /* HasRVO=*/ false );
214
-
215
- assert (Func);
216
- Func->setDefined (true );
217
- // We don't compile the BlockDecl code at all right now.
218
- Func->setIsFullyCompiled (true );
219
- return Func;
220
93
}
221
94
222
95
Scope::Local ByteCodeEmitter::createLocal (Descriptor *D) {
0 commit comments