13
13
// ===----------------------------------------------------------------------===//
14
14
15
15
#include " CGHLSLRuntime.h"
16
+ #include " Address.h"
16
17
#include " CGDebugInfo.h"
17
18
#include " CodeGenFunction.h"
18
19
#include " CodeGenModule.h"
38
39
#include " llvm/Support/ErrorHandling.h"
39
40
#include " llvm/Support/FormatVariadic.h"
40
41
#include < cstdint>
42
+ #include < optional>
41
43
42
44
using namespace clang ;
43
45
using namespace CodeGen ;
@@ -148,14 +150,22 @@ static Value *buildNameForResource(llvm::StringRef BaseName,
148
150
.getPointer ();
149
151
}
150
152
151
- static void createResourceCtorArgs (CodeGenModule &CGM, CXXConstructorDecl *CD,
152
- llvm::Value *ThisPtr, llvm::Value *Range,
153
- llvm::Value *Index, StringRef Name,
154
- HLSLResourceBindingAttr *RBA,
155
- HLSLVkBindingAttr *VkBinding,
156
- CallArgList &Args) {
153
+ static CXXMethodDecl *lookupMethod (CXXRecordDecl *Record, StringRef Name,
154
+ StorageClass SC = SC_None) {
155
+ for (auto *Method : Record->methods ()) {
156
+ if (Method->getStorageClass () == SC && Method->getName () == Name)
157
+ return Method;
158
+ }
159
+ return nullptr ;
160
+ }
161
+
162
+ static CXXMethodDecl *lookupResourceInitMethodAndSetupArgs (
163
+ CodeGenModule &CGM, CXXRecordDecl *ResourceDecl, llvm::Value *Range,
164
+ llvm::Value *Index, StringRef Name, HLSLResourceBindingAttr *RBA,
165
+ HLSLVkBindingAttr *VkBinding, CallArgList &Args) {
157
166
assert ((VkBinding || RBA) && " at least one a binding attribute expected" );
158
167
168
+ ASTContext &AST = CGM.getContext ();
159
169
std::optional<uint32_t > RegisterSlot;
160
170
uint32_t SpaceNo = 0 ;
161
171
if (VkBinding) {
@@ -167,44 +177,57 @@ static void createResourceCtorArgs(CodeGenModule &CGM, CXXConstructorDecl *CD,
167
177
SpaceNo = RBA->getSpaceNumber ();
168
178
}
169
179
170
- ASTContext &AST = CD-> getASTContext () ;
180
+ CXXMethodDecl *CreateMethod = nullptr ;
171
181
Value *NameStr = buildNameForResource (Name, CGM);
172
182
Value *Space = llvm::ConstantInt::get (CGM.IntTy , SpaceNo);
173
183
174
- Args.add (RValue::get (ThisPtr), CD->getThisType ());
175
184
if (RegisterSlot.has_value ()) {
176
185
// explicit binding
177
186
auto *RegSlot = llvm::ConstantInt::get (CGM.IntTy , RegisterSlot.value ());
178
187
Args.add (RValue::get (RegSlot), AST.UnsignedIntTy );
179
- Args.add (RValue::get (Space), AST.UnsignedIntTy );
180
- Args.add (RValue::get (Range), AST.IntTy );
181
- Args.add (RValue::get (Index), AST.UnsignedIntTy );
182
-
188
+ CreateMethod = lookupMethod (ResourceDecl, " __createFromBinding" , SC_Static);
183
189
} else {
184
190
// implicit binding
185
- assert (RBA && " missing implicit binding attribute" );
186
191
auto *OrderID =
187
192
llvm::ConstantInt::get (CGM.IntTy , RBA->getImplicitBindingOrderID ());
188
- Args.add (RValue::get (Space), AST.UnsignedIntTy );
189
- Args.add (RValue::get (Range), AST.IntTy );
190
- Args.add (RValue::get (Index), AST.UnsignedIntTy );
191
193
Args.add (RValue::get (OrderID), AST.UnsignedIntTy );
194
+ CreateMethod =
195
+ lookupMethod (ResourceDecl, " __createFromImplicitBinding" , SC_Static);
192
196
}
197
+ Args.add (RValue::get (Space), AST.UnsignedIntTy );
198
+ Args.add (RValue::get (Range), AST.IntTy );
199
+ Args.add (RValue::get (Index), AST.UnsignedIntTy );
193
200
Args.add (RValue::get (NameStr), AST.getPointerType (AST.CharTy .withConst ()));
201
+
202
+ return CreateMethod;
203
+ }
204
+
205
+ static void callResourceInitMethod (CodeGenFunction &CGF,
206
+ CXXMethodDecl *CreateMethod,
207
+ CallArgList &Args, Address ReturnAddress) {
208
+ llvm::Constant *CalleeFn = CGF.CGM .GetAddrOfFunction (CreateMethod);
209
+ const FunctionProtoType *Proto =
210
+ CreateMethod->getType ()->getAs <FunctionProtoType>();
211
+ const CGFunctionInfo &FnInfo =
212
+ CGF.CGM .getTypes ().arrangeFreeFunctionCall (Args, Proto, false );
213
+ ReturnValueSlot ReturnValue (ReturnAddress, false );
214
+ CGCallee Callee (CGCalleeInfo (Proto), CalleeFn);
215
+ CGF.EmitCall (FnInfo, Callee, ReturnValue, Args, nullptr );
194
216
}
195
217
196
218
// Initializes local resource array variable. For multi-dimensional arrays it
197
219
// calls itself recursively to initialize its sub-arrays. The Index used in the
198
220
// resource constructor calls will begin at StartIndex and will be incremented
199
221
// for each array element. The last used resource Index is returned to the
200
- // caller.
201
- static Value *initializeLocalResourceArray (
202
- CodeGenFunction &CGF, AggValueSlot &ValueSlot ,
203
- const ConstantArrayType *ArrayTy, CXXConstructorDecl *CD ,
222
+ // caller. If the function returns std::nullopt, it indicates an error.
223
+ static std::optional<llvm:: Value *> initializeLocalResourceArray (
224
+ CodeGenFunction &CGF, CXXRecordDecl *ResourceDecl ,
225
+ const ConstantArrayType *ArrayTy, AggValueSlot &ValueSlot ,
204
226
llvm::Value *Range, llvm::Value *StartIndex, StringRef ResourceName,
205
227
HLSLResourceBindingAttr *RBA, HLSLVkBindingAttr *VkBinding,
206
228
ArrayRef<llvm::Value *> PrevGEPIndices, SourceLocation ArraySubsExprLoc) {
207
229
230
+ ASTContext &AST = CGF.getContext ();
208
231
llvm::IntegerType *IntTy = CGF.CGM .IntTy ;
209
232
llvm::Value *Index = StartIndex;
210
233
llvm::Value *One = llvm::ConstantInt::get (IntTy, 1 );
@@ -225,16 +248,19 @@ static Value *initializeLocalResourceArray(
225
248
Index = CGF.Builder .CreateAdd (Index, One);
226
249
GEPIndices.back () = llvm::ConstantInt::get (IntTy, I);
227
250
}
228
- Index = initializeLocalResourceArray (
229
- CGF, ValueSlot, SubArrayTy, CD, Range, Index, ResourceName, RBA,
230
- VkBinding, GEPIndices, ArraySubsExprLoc);
251
+ std::optional<llvm::Value *> MaybeIndex = initializeLocalResourceArray (
252
+ CGF, ResourceDecl, SubArrayTy, ValueSlot, Range, Index, ResourceName,
253
+ RBA, VkBinding, GEPIndices, ArraySubsExprLoc);
254
+ if (!MaybeIndex)
255
+ return std::nullopt ;
256
+ Index = *MaybeIndex;
231
257
}
232
258
return Index;
233
259
}
234
260
235
261
// For array of resources, initialize each resource in the array.
236
262
llvm::Type *Ty = CGF.ConvertTypeForMem (ElemType);
237
- CharUnits ElemSize = CD-> getASTContext () .getTypeSizeInChars (ElemType);
263
+ CharUnits ElemSize = AST .getTypeSizeInChars (ElemType);
238
264
CharUnits Align =
239
265
TmpArrayAddr.getAlignment ().alignmentOfArrayElement (ElemSize);
240
266
@@ -243,16 +269,18 @@ static Value *initializeLocalResourceArray(
243
269
Index = CGF.Builder .CreateAdd (Index, One);
244
270
GEPIndices.back () = llvm::ConstantInt::get (IntTy, I);
245
271
}
246
- Address ThisAddress =
272
+ Address ReturnAddress =
247
273
CGF.Builder .CreateGEP (TmpArrayAddr, GEPIndices, Ty, Align);
248
- llvm::Value *ThisPtr = CGF.getAsNaturalPointerTo (ThisAddress, ElemType);
249
274
250
275
CallArgList Args;
251
- createResourceCtorArgs (CGF.CGM , CD, ThisPtr, Range, Index, ResourceName,
252
- RBA, VkBinding, Args);
253
- CGF.EmitCXXConstructorCall (CD, Ctor_Complete, false , false , ThisAddress,
254
- Args, ValueSlot.mayOverlap (), ArraySubsExprLoc,
255
- ValueSlot.isSanitizerChecked ());
276
+ CXXMethodDecl *CreateMethod = lookupResourceInitMethodAndSetupArgs (
277
+ CGF.CGM , ResourceDecl, Range, Index, ResourceName, RBA, VkBinding,
278
+ Args);
279
+
280
+ if (!CreateMethod)
281
+ return std::nullopt ;
282
+
283
+ callResourceInitMethod (CGF, CreateMethod, Args, ReturnAddress);
256
284
}
257
285
return Index;
258
286
}
@@ -906,11 +934,6 @@ std::optional<LValue> CGHLSLRuntime::emitResourceArraySubscriptExpr(
906
934
QualType ResourceTy =
907
935
ResultTy->isArrayType () ? AST.getBaseElementType (ResultTy) : ResultTy;
908
936
909
- // Lookup the resource class constructor based on the resource type and
910
- // binding.
911
- CXXConstructorDecl *CD = findResourceConstructorDecl (
912
- AST, ResourceTy, VkBinding || RBA->hasRegisterSlot ());
913
-
914
937
// Create a temporary variable for the result, which is either going
915
938
// to be a single resource instance or a local array of resources (we need to
916
939
// return an LValue).
@@ -923,7 +946,6 @@ std::optional<LValue> CGHLSLRuntime::emitResourceArraySubscriptExpr(
923
946
TmpVar, Qualifiers (), AggValueSlot::IsDestructed_t (true ),
924
947
AggValueSlot::DoesNotNeedGCBarriers, AggValueSlot::IsAliased_t (false ),
925
948
AggValueSlot::DoesNotOverlap);
926
- Address TmpVarAddress = ValueSlot.getAddress ();
927
949
928
950
// Calculate total array size (= range size).
929
951
llvm::Value *Range =
@@ -932,27 +954,27 @@ std::optional<LValue> CGHLSLRuntime::emitResourceArraySubscriptExpr(
932
954
// If the result of the subscript operation is a single resource, call the
933
955
// constructor.
934
956
if (ResultTy == ResourceTy) {
935
- QualType ThisType = CD->getThisType ()->getPointeeType ();
936
- llvm::Value *ThisPtr = CGF.getAsNaturalPointerTo (TmpVarAddress, ThisType);
937
-
938
- // Assemble the constructor parameters.
939
957
CallArgList Args;
940
- createResourceCtorArgs (CGM, CD, ThisPtr, Range, Index, ArrayDecl->getName (),
941
- RBA, VkBinding, Args);
942
- // Call the constructor.
943
- CGF.EmitCXXConstructorCall (CD, Ctor_Complete, false , false , TmpVarAddress,
944
- Args, ValueSlot.mayOverlap (),
945
- ArraySubsExpr->getExprLoc (),
946
- ValueSlot.isSanitizerChecked ());
958
+ CXXMethodDecl *CreateMethod = lookupResourceInitMethodAndSetupArgs (
959
+ CGF.CGM , ResourceTy->getAsCXXRecordDecl (), Range, Index,
960
+ ArrayDecl->getName (), RBA, VkBinding, Args);
961
+
962
+ if (!CreateMethod)
963
+ return std::nullopt ;
964
+
965
+ callResourceInitMethod (CGF, CreateMethod, Args, ValueSlot.getAddress ());
966
+
947
967
} else {
948
968
// The result of the subscript operation is a local resource array which
949
969
// needs to be initialized.
950
970
const ConstantArrayType *ArrayTy =
951
971
cast<ConstantArrayType>(ResultTy.getTypePtr ());
952
- initializeLocalResourceArray (CGF, ValueSlot, ArrayTy, CD, Range, Index,
953
- ArrayDecl->getName (), RBA, VkBinding,
954
- {llvm::ConstantInt::get (CGM.IntTy , 0 )},
955
- ArraySubsExpr->getExprLoc ());
972
+ std::optional<llvm::Value *> EndIndex = initializeLocalResourceArray (
973
+ CGF, ResourceTy->getAsCXXRecordDecl (), ArrayTy, ValueSlot, Range, Index,
974
+ ArrayDecl->getName (), RBA, VkBinding,
975
+ {llvm::ConstantInt::get (CGM.IntTy , 0 )}, ArraySubsExpr->getExprLoc ());
976
+ if (!EndIndex)
977
+ return std::nullopt ;
956
978
}
957
979
return CGF.MakeAddrLValue (TmpVar, ResultTy, AlignmentSource::Decl);
958
980
}
0 commit comments