clang 22.0.0git
CGHLSLRuntime.cpp
Go to the documentation of this file.
1//===----- CGHLSLRuntime.cpp - Interface to HLSL Runtimes -----------------===//
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 provides an abstract class for HLSL code generation. Concrete
10// subclasses of this implement code generation for specific HLSL
11// runtime libraries.
12//
13//===----------------------------------------------------------------------===//
14
15#include "CGHLSLRuntime.h"
16#include "CGDebugInfo.h"
17#include "CodeGenFunction.h"
18#include "CodeGenModule.h"
19#include "TargetInfo.h"
21#include "clang/AST/Attrs.inc"
22#include "clang/AST/Decl.h"
24#include "clang/AST/Type.h"
26#include "llvm/ADT/SmallString.h"
27#include "llvm/ADT/SmallVector.h"
28#include "llvm/Frontend/HLSL/RootSignatureMetadata.h"
29#include "llvm/IR/Constants.h"
30#include "llvm/IR/DerivedTypes.h"
31#include "llvm/IR/GlobalVariable.h"
32#include "llvm/IR/LLVMContext.h"
33#include "llvm/IR/Metadata.h"
34#include "llvm/IR/Module.h"
35#include "llvm/IR/Type.h"
36#include "llvm/IR/Value.h"
37#include "llvm/Support/Alignment.h"
38#include "llvm/Support/ErrorHandling.h"
39#include "llvm/Support/FormatVariadic.h"
40#include <cstdint>
41
42using namespace clang;
43using namespace CodeGen;
44using namespace clang::hlsl;
45using namespace llvm;
46
47using llvm::hlsl::CBufferRowSizeInBytes;
48
49namespace {
50
51void addDxilValVersion(StringRef ValVersionStr, llvm::Module &M) {
52 // The validation of ValVersionStr is done at HLSLToolChain::TranslateArgs.
53 // Assume ValVersionStr is legal here.
54 VersionTuple Version;
55 if (Version.tryParse(ValVersionStr) || Version.getBuild() ||
56 Version.getSubminor() || !Version.getMinor()) {
57 return;
58 }
59
60 uint64_t Major = Version.getMajor();
61 uint64_t Minor = *Version.getMinor();
62
63 auto &Ctx = M.getContext();
64 IRBuilder<> B(M.getContext());
65 MDNode *Val = MDNode::get(Ctx, {ConstantAsMetadata::get(B.getInt32(Major)),
66 ConstantAsMetadata::get(B.getInt32(Minor))});
67 StringRef DXILValKey = "dx.valver";
68 auto *DXILValMD = M.getOrInsertNamedMetadata(DXILValKey);
69 DXILValMD->addOperand(Val);
70}
71
72void addRootSignature(llvm::dxbc::RootSignatureVersion RootSigVer,
74 llvm::Function *Fn, llvm::Module &M) {
75 auto &Ctx = M.getContext();
76
77 llvm::hlsl::rootsig::MetadataBuilder RSBuilder(Ctx, Elements);
78 MDNode *RootSignature = RSBuilder.BuildRootSignature();
79
80 ConstantAsMetadata *Version = ConstantAsMetadata::get(ConstantInt::get(
81 llvm::Type::getInt32Ty(Ctx), llvm::to_underlying(RootSigVer)));
82 MDNode *MDVals =
83 MDNode::get(Ctx, {ValueAsMetadata::get(Fn), RootSignature, Version});
84
85 StringRef RootSignatureValKey = "dx.rootsignatures";
86 auto *RootSignatureValMD = M.getOrInsertNamedMetadata(RootSignatureValKey);
87 RootSignatureValMD->addOperand(MDVals);
88}
89
90// Find array variable declaration from nested array subscript AST nodes
91static const ValueDecl *getArrayDecl(const ArraySubscriptExpr *ASE) {
92 const Expr *E = nullptr;
93 while (ASE != nullptr) {
94 E = ASE->getBase()->IgnoreImpCasts();
95 if (!E)
96 return nullptr;
97 ASE = dyn_cast<ArraySubscriptExpr>(E);
98 }
99 if (const DeclRefExpr *DRE = dyn_cast_or_null<DeclRefExpr>(E))
100 return DRE->getDecl();
101 return nullptr;
102}
103
104// Get the total size of the array, or -1 if the array is unbounded.
105static int getTotalArraySize(ASTContext &AST, const clang::Type *Ty) {
107 assert(Ty->isArrayType() && "expected array type");
108 if (Ty->isIncompleteArrayType())
109 return -1;
110 return AST.getConstantArrayElementCount(cast<ConstantArrayType>(Ty));
111}
112
113// Find constructor decl for a specific resource record type and binding
114// (implicit vs. explicit). The constructor has 5 parameters.
115// For explicit binding the signature is:
116// void(unsigned, unsigned, int, unsigned, const char *).
117// For implicit binding the signature is:
118// void(unsigned, int, unsigned, unsigned, const char *).
119static CXXConstructorDecl *findResourceConstructorDecl(ASTContext &AST,
120 QualType ResTy,
121 bool ExplicitBinding) {
122 std::array<QualType, 5> ExpParmTypes = {
125 ExpParmTypes[ExplicitBinding ? 2 : 1] = AST.IntTy;
126
127 CXXRecordDecl *ResDecl = ResTy->getAsCXXRecordDecl();
128 for (auto *Ctor : ResDecl->ctors()) {
129 if (Ctor->getNumParams() != ExpParmTypes.size())
130 continue;
131 auto *ParmIt = Ctor->param_begin();
132 auto ExpTyIt = ExpParmTypes.begin();
133 for (; ParmIt != Ctor->param_end() && ExpTyIt != ExpParmTypes.end();
134 ++ParmIt, ++ExpTyIt) {
135 if ((*ParmIt)->getType() != *ExpTyIt)
136 break;
137 }
138 if (ParmIt == Ctor->param_end())
139 return Ctor;
140 }
141 llvm_unreachable("did not find constructor for resource class");
142}
143
144static Value *buildNameForResource(llvm::StringRef BaseName,
145 CodeGenModule &CGM) {
146 llvm::SmallString<64> GlobalName = {BaseName, ".str"};
147 return CGM.GetAddrOfConstantCString(BaseName.str(), GlobalName.c_str())
148 .getPointer();
149}
150
151static 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) {
157 assert((VkBinding || RBA) && "at least one a binding attribute expected");
158
159 std::optional<uint32_t> RegisterSlot;
160 uint32_t SpaceNo = 0;
161 if (VkBinding) {
162 RegisterSlot = VkBinding->getBinding();
163 SpaceNo = VkBinding->getSet();
164 } else {
165 if (RBA->hasRegisterSlot())
166 RegisterSlot = RBA->getSlotNumber();
167 SpaceNo = RBA->getSpaceNumber();
168 }
169
170 ASTContext &AST = CD->getASTContext();
171 Value *NameStr = buildNameForResource(Name, CGM);
172 Value *Space = llvm::ConstantInt::get(CGM.IntTy, SpaceNo);
173
174 Args.add(RValue::get(ThisPtr), CD->getThisType());
175 if (RegisterSlot.has_value()) {
176 // explicit binding
177 auto *RegSlot = llvm::ConstantInt::get(CGM.IntTy, RegisterSlot.value());
178 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
183 } else {
184 // implicit binding
185 auto *OrderID =
186 llvm::ConstantInt::get(CGM.IntTy, RBA->getImplicitBindingOrderID());
187 Args.add(RValue::get(Space), AST.UnsignedIntTy);
188 Args.add(RValue::get(Range), AST.IntTy);
189 Args.add(RValue::get(Index), AST.UnsignedIntTy);
190 Args.add(RValue::get(OrderID), AST.UnsignedIntTy);
191 }
192 Args.add(RValue::get(NameStr), AST.getPointerType(AST.CharTy.withConst()));
193}
194
195// Initializes local resource array variable. For multi-dimensional arrays it
196// calls itself recursively to initialize its sub-arrays. The Index used in the
197// resource constructor calls will begin at StartIndex and will be incremented
198// for each array element. The last used resource Index is returned to the
199// caller.
200static Value *initializeLocalResourceArray(
201 CodeGenFunction &CGF, AggValueSlot &ValueSlot,
202 const ConstantArrayType *ArrayTy, CXXConstructorDecl *CD,
203 llvm::Value *Range, llvm::Value *StartIndex, StringRef ResourceName,
204 HLSLResourceBindingAttr *RBA, HLSLVkBindingAttr *VkBinding,
205 ArrayRef<llvm::Value *> PrevGEPIndices, SourceLocation ArraySubsExprLoc) {
206
207 llvm::IntegerType *IntTy = CGF.CGM.IntTy;
208 llvm::Value *Index = StartIndex;
209 llvm::Value *One = llvm::ConstantInt::get(IntTy, 1);
210 const uint64_t ArraySize = ArrayTy->getSExtSize();
211 QualType ElemType = ArrayTy->getElementType();
212 Address TmpArrayAddr = ValueSlot.getAddress();
213
214 // Add additional index to the getelementptr call indices.
215 // This index will be updated for each array element in the loops below.
216 SmallVector<llvm::Value *> GEPIndices(PrevGEPIndices);
217 GEPIndices.push_back(llvm::ConstantInt::get(IntTy, 0));
218
219 // For array of arrays, recursively initialize the sub-arrays.
220 if (ElemType->isArrayType()) {
221 const ConstantArrayType *SubArrayTy = cast<ConstantArrayType>(ElemType);
222 for (uint64_t I = 0; I < ArraySize; I++) {
223 if (I > 0) {
224 Index = CGF.Builder.CreateAdd(Index, One);
225 GEPIndices.back() = llvm::ConstantInt::get(IntTy, I);
226 }
227 Index = initializeLocalResourceArray(
228 CGF, ValueSlot, SubArrayTy, CD, Range, Index, ResourceName, RBA,
229 VkBinding, GEPIndices, ArraySubsExprLoc);
230 }
231 return Index;
232 }
233
234 // For array of resources, initialize each resource in the array.
235 llvm::Type *Ty = CGF.ConvertTypeForMem(ElemType);
236 CharUnits ElemSize = CD->getASTContext().getTypeSizeInChars(ElemType);
237 CharUnits Align =
238 TmpArrayAddr.getAlignment().alignmentOfArrayElement(ElemSize);
239
240 for (uint64_t I = 0; I < ArraySize; I++) {
241 if (I > 0) {
242 Index = CGF.Builder.CreateAdd(Index, One);
243 GEPIndices.back() = llvm::ConstantInt::get(IntTy, I);
244 }
245 Address ThisAddress =
246 CGF.Builder.CreateGEP(TmpArrayAddr, GEPIndices, Ty, Align);
247 llvm::Value *ThisPtr = CGF.getAsNaturalPointerTo(ThisAddress, ElemType);
248
249 CallArgList Args;
250 createResourceCtorArgs(CGF.CGM, CD, ThisPtr, Range, Index, ResourceName,
251 RBA, VkBinding, Args);
252 CGF.EmitCXXConstructorCall(CD, Ctor_Complete, false, false, ThisAddress,
253 Args, ValueSlot.mayOverlap(), ArraySubsExprLoc,
254 ValueSlot.isSanitizerChecked());
255 }
256 return Index;
257}
258
259} // namespace
260
261llvm::Type *
263 SmallVector<int32_t> *Packoffsets) {
264 assert(T->isHLSLSpecificType() && "Not an HLSL specific type!");
265
266 // Check if the target has a specific translation for this type first.
267 if (llvm::Type *TargetTy =
268 CGM.getTargetCodeGenInfo().getHLSLType(CGM, T, Packoffsets))
269 return TargetTy;
270
271 llvm_unreachable("Generic handling of HLSL types is not supported.");
272}
273
274llvm::Triple::ArchType CGHLSLRuntime::getArch() {
275 return CGM.getTarget().getTriple().getArch();
276}
277
278// Emits constant global variables for buffer constants declarations
279// and creates metadata linking the constant globals with the buffer global.
280void CGHLSLRuntime::emitBufferGlobalsAndMetadata(const HLSLBufferDecl *BufDecl,
281 llvm::GlobalVariable *BufGV) {
282 LLVMContext &Ctx = CGM.getLLVMContext();
283
284 // get the layout struct from constant buffer target type
285 llvm::Type *BufType = BufGV->getValueType();
286 llvm::Type *BufLayoutType =
287 cast<llvm::TargetExtType>(BufType)->getTypeParameter(0);
288 llvm::StructType *LayoutStruct = cast<llvm::StructType>(
289 cast<llvm::TargetExtType>(BufLayoutType)->getTypeParameter(0));
290
291 // Start metadata list associating the buffer global variable with its
292 // constatns
294 BufGlobals.push_back(ValueAsMetadata::get(BufGV));
295
296 const auto *ElemIt = LayoutStruct->element_begin();
297 for (Decl *D : BufDecl->buffer_decls()) {
298 if (isa<CXXRecordDecl, EmptyDecl>(D))
299 // Nothing to do for this declaration.
300 continue;
301 if (isa<FunctionDecl>(D)) {
302 // A function within an cbuffer is effectively a top-level function.
303 CGM.EmitTopLevelDecl(D);
304 continue;
305 }
306 VarDecl *VD = dyn_cast<VarDecl>(D);
307 if (!VD)
308 continue;
309
310 QualType VDTy = VD->getType();
312 if (VD->getStorageClass() == SC_Static ||
315 // Emit static and groupshared variables and resource classes inside
316 // cbuffer as regular globals
317 CGM.EmitGlobal(VD);
318 } else {
319 // Anything else that is not in the hlsl_constant address space must be
320 // an empty struct or a zero-sized array and can be ignored
321 assert(BufDecl->getASTContext().getTypeSize(VDTy) == 0 &&
322 "constant buffer decl with non-zero sized type outside of "
323 "hlsl_constant address space");
324 }
325 continue;
326 }
327
328 assert(ElemIt != LayoutStruct->element_end() &&
329 "number of elements in layout struct does not match");
330 llvm::Type *LayoutType = *ElemIt++;
331
332 // FIXME: handle resources inside user defined structs
333 // (llvm/wg-hlsl#175)
334
335 // create global variable for the constant and to metadata list
336 GlobalVariable *ElemGV =
337 cast<GlobalVariable>(CGM.GetAddrOfGlobalVar(VD, LayoutType));
338 BufGlobals.push_back(ValueAsMetadata::get(ElemGV));
339 }
340 assert(ElemIt == LayoutStruct->element_end() &&
341 "number of elements in layout struct does not match");
342
343 // add buffer metadata to the module
344 CGM.getModule()
345 .getOrInsertNamedMetadata("hlsl.cbs")
346 ->addOperand(MDNode::get(Ctx, BufGlobals));
347}
348
349// Creates resource handle type for the HLSL buffer declaration
352 ASTContext &AST = BufDecl->getASTContext();
354 AST.HLSLResourceTy, AST.getCanonicalTagType(BufDecl->getLayoutStruct()),
355 HLSLAttributedResourceType::Attributes(ResourceClass::CBuffer));
356 return cast<HLSLAttributedResourceType>(QT.getTypePtr());
357}
358
359// Iterates over all declarations in the HLSL buffer and based on the
360// packoffset or register(c#) annotations it fills outs the Layout
361// vector with the user-specified layout offsets.
362// The buffer offsets can be specified 2 ways:
363// 1. declarations in cbuffer {} block can have a packoffset annotation
364// (translates to HLSLPackOffsetAttr)
365// 2. default constant buffer declarations at global scope can have
366// register(c#) annotations (translates to HLSLResourceBindingAttr with
367// RegisterType::C)
368// It is not guaranteed that all declarations in a buffer have an annotation.
369// For those where it is not specified a -1 value is added to the Layout
370// vector. In the final layout these declarations will be placed at the end
371// of the HLSL buffer after all of the elements with specified offset.
372static void fillPackoffsetLayout(const HLSLBufferDecl *BufDecl,
373 SmallVector<int32_t> &Layout) {
374 assert(Layout.empty() && "expected empty vector for layout");
375 assert(BufDecl->hasValidPackoffset());
376
377 for (Decl *D : BufDecl->buffer_decls()) {
378 if (isa<CXXRecordDecl, EmptyDecl>(D) || isa<FunctionDecl>(D)) {
379 continue;
380 }
381 VarDecl *VD = dyn_cast<VarDecl>(D);
382 if (!VD || VD->getType().getAddressSpace() != LangAS::hlsl_constant)
383 continue;
384
385 if (!VD->hasAttrs()) {
386 Layout.push_back(-1);
387 continue;
388 }
389
390 int32_t Offset = -1;
391 for (auto *Attr : VD->getAttrs()) {
392 if (auto *POA = dyn_cast<HLSLPackOffsetAttr>(Attr)) {
393 Offset = POA->getOffsetInBytes();
394 break;
395 }
396 auto *RBA = dyn_cast<HLSLResourceBindingAttr>(Attr);
397 if (RBA &&
398 RBA->getRegisterType() == HLSLResourceBindingAttr::RegisterType::C) {
399 Offset = RBA->getSlotNumber() * CBufferRowSizeInBytes;
400 break;
401 }
402 }
403 Layout.push_back(Offset);
404 }
405}
406
407// Codegen for HLSLBufferDecl
409
410 assert(BufDecl->isCBuffer() && "tbuffer codegen is not supported yet");
411
412 // create resource handle type for the buffer
413 const clang::HLSLAttributedResourceType *ResHandleTy =
414 createBufferHandleType(BufDecl);
415
416 // empty constant buffer is ignored
417 if (ResHandleTy->getContainedType()->getAsCXXRecordDecl()->isEmpty())
418 return;
419
420 // create global variable for the constant buffer
422 if (BufDecl->hasValidPackoffset())
423 fillPackoffsetLayout(BufDecl, Layout);
424
425 llvm::TargetExtType *TargetTy =
426 cast<llvm::TargetExtType>(convertHLSLSpecificType(
427 ResHandleTy, BufDecl->hasValidPackoffset() ? &Layout : nullptr));
428 llvm::GlobalVariable *BufGV = new GlobalVariable(
429 TargetTy, /*isConstant*/ false,
430 GlobalValue::LinkageTypes::ExternalLinkage, PoisonValue::get(TargetTy),
431 llvm::formatv("{0}{1}", BufDecl->getName(),
432 BufDecl->isCBuffer() ? ".cb" : ".tb"),
433 GlobalValue::NotThreadLocal);
434 CGM.getModule().insertGlobalVariable(BufGV);
435
436 // Add globals for constant buffer elements and create metadata nodes
437 emitBufferGlobalsAndMetadata(BufDecl, BufGV);
438
439 // Initialize cbuffer from binding (implicit or explicit)
440 if (HLSLVkBindingAttr *VkBinding = BufDecl->getAttr<HLSLVkBindingAttr>()) {
441 initializeBufferFromBinding(BufDecl, BufGV, VkBinding);
442 } else {
443 HLSLResourceBindingAttr *RBA = BufDecl->getAttr<HLSLResourceBindingAttr>();
444 assert(RBA &&
445 "cbuffer/tbuffer should always have resource binding attribute");
446 initializeBufferFromBinding(BufDecl, BufGV, RBA);
447 }
448}
449
450llvm::TargetExtType *
452 const auto Entry = LayoutTypes.find(StructType);
453 if (Entry != LayoutTypes.end())
454 return Entry->getSecond();
455 return nullptr;
456}
457
459 llvm::TargetExtType *LayoutTy) {
460 assert(getHLSLBufferLayoutType(StructType) == nullptr &&
461 "layout type for this struct already exist");
462 LayoutTypes[StructType] = LayoutTy;
463}
464
466 auto &TargetOpts = CGM.getTarget().getTargetOpts();
467 auto &CodeGenOpts = CGM.getCodeGenOpts();
468 auto &LangOpts = CGM.getLangOpts();
469 llvm::Module &M = CGM.getModule();
470 Triple T(M.getTargetTriple());
471 if (T.getArch() == Triple::ArchType::dxil)
472 addDxilValVersion(TargetOpts.DxilValidatorVersion, M);
473 if (CodeGenOpts.ResMayAlias)
474 M.setModuleFlag(llvm::Module::ModFlagBehavior::Error, "dx.resmayalias", 1);
475
476 // NativeHalfType corresponds to the -fnative-half-type clang option which is
477 // aliased by clang-dxc's -enable-16bit-types option. This option is used to
478 // set the UseNativeLowPrecision DXIL module flag in the DirectX backend
479 if (LangOpts.NativeHalfType)
480 M.setModuleFlag(llvm::Module::ModFlagBehavior::Error, "dx.nativelowprec",
481 1);
482
484}
485
487 const FunctionDecl *FD, llvm::Function *Fn) {
488 const auto *ShaderAttr = FD->getAttr<HLSLShaderAttr>();
489 assert(ShaderAttr && "All entry functions must have a HLSLShaderAttr");
490 const StringRef ShaderAttrKindStr = "hlsl.shader";
491 Fn->addFnAttr(ShaderAttrKindStr,
492 llvm::Triple::getEnvironmentTypeName(ShaderAttr->getType()));
493 if (HLSLNumThreadsAttr *NumThreadsAttr = FD->getAttr<HLSLNumThreadsAttr>()) {
494 const StringRef NumThreadsKindStr = "hlsl.numthreads";
495 std::string NumThreadsStr =
496 formatv("{0},{1},{2}", NumThreadsAttr->getX(), NumThreadsAttr->getY(),
497 NumThreadsAttr->getZ());
498 Fn->addFnAttr(NumThreadsKindStr, NumThreadsStr);
499 }
500 if (HLSLWaveSizeAttr *WaveSizeAttr = FD->getAttr<HLSLWaveSizeAttr>()) {
501 const StringRef WaveSizeKindStr = "hlsl.wavesize";
502 std::string WaveSizeStr =
503 formatv("{0},{1},{2}", WaveSizeAttr->getMin(), WaveSizeAttr->getMax(),
504 WaveSizeAttr->getPreferred());
505 Fn->addFnAttr(WaveSizeKindStr, WaveSizeStr);
506 }
507 // HLSL entry functions are materialized for module functions with
508 // HLSLShaderAttr attribute. SetLLVMFunctionAttributesForDefinition called
509 // later in the compiler-flow for such module functions is not aware of and
510 // hence not able to set attributes of the newly materialized entry functions.
511 // So, set attributes of entry function here, as appropriate.
512 if (CGM.getCodeGenOpts().OptimizationLevel == 0)
513 Fn->addFnAttr(llvm::Attribute::OptimizeNone);
514 Fn->addFnAttr(llvm::Attribute::NoInline);
515}
516
517static Value *buildVectorInput(IRBuilder<> &B, Function *F, llvm::Type *Ty) {
518 if (const auto *VT = dyn_cast<FixedVectorType>(Ty)) {
519 Value *Result = PoisonValue::get(Ty);
520 for (unsigned I = 0; I < VT->getNumElements(); ++I) {
521 Value *Elt = B.CreateCall(F, {B.getInt32(I)});
522 Result = B.CreateInsertElement(Result, Elt, I);
523 }
524 return Result;
525 }
526 return B.CreateCall(F, {B.getInt32(0)});
527}
528
529static void addSPIRVBuiltinDecoration(llvm::GlobalVariable *GV,
530 unsigned BuiltIn) {
531 LLVMContext &Ctx = GV->getContext();
532 IRBuilder<> B(GV->getContext());
533 MDNode *Operands = MDNode::get(
534 Ctx,
535 {ConstantAsMetadata::get(B.getInt32(/* Spirv::Decoration::BuiltIn */ 11)),
536 ConstantAsMetadata::get(B.getInt32(BuiltIn))});
537 MDNode *Decoration = MDNode::get(Ctx, {Operands});
538 GV->addMetadata("spirv.Decorations", *Decoration);
539}
540
541static llvm::Value *createSPIRVBuiltinLoad(IRBuilder<> &B, llvm::Module &M,
542 llvm::Type *Ty, const Twine &Name,
543 unsigned BuiltInID) {
544 auto *GV = new llvm::GlobalVariable(
545 M, Ty, /* isConstant= */ true, llvm::GlobalValue::ExternalLinkage,
546 /* Initializer= */ nullptr, Name, /* insertBefore= */ nullptr,
547 llvm::GlobalVariable::GeneralDynamicTLSModel,
548 /* AddressSpace */ 7, /* isExternallyInitialized= */ true);
549 addSPIRVBuiltinDecoration(GV, BuiltInID);
550 GV->setVisibility(llvm::GlobalValue::HiddenVisibility);
551 return B.CreateLoad(Ty, GV);
552}
553
554llvm::Value *CGHLSLRuntime::emitInputSemantic(IRBuilder<> &B,
555 const ParmVarDecl &D,
556 llvm::Type *Ty) {
557 assert(D.hasAttrs() && "Entry parameter missing annotation attribute!");
558 if (D.hasAttr<HLSLSV_GroupIndexAttr>()) {
559 llvm::Function *GroupIndex =
560 CGM.getIntrinsic(getFlattenedThreadIdInGroupIntrinsic());
561 return B.CreateCall(FunctionCallee(GroupIndex));
562 }
563 if (D.hasAttr<HLSLSV_DispatchThreadIDAttr>()) {
564 llvm::Intrinsic::ID IntrinID = getThreadIdIntrinsic();
565 llvm::Function *ThreadIDIntrinsic =
566 llvm::Intrinsic::isOverloaded(IntrinID)
567 ? CGM.getIntrinsic(IntrinID, {CGM.Int32Ty})
568 : CGM.getIntrinsic(IntrinID);
569 return buildVectorInput(B, ThreadIDIntrinsic, Ty);
570 }
571 if (D.hasAttr<HLSLSV_GroupThreadIDAttr>()) {
572 llvm::Intrinsic::ID IntrinID = getGroupThreadIdIntrinsic();
573 llvm::Function *GroupThreadIDIntrinsic =
574 llvm::Intrinsic::isOverloaded(IntrinID)
575 ? CGM.getIntrinsic(IntrinID, {CGM.Int32Ty})
576 : CGM.getIntrinsic(IntrinID);
577 return buildVectorInput(B, GroupThreadIDIntrinsic, Ty);
578 }
579 if (D.hasAttr<HLSLSV_GroupIDAttr>()) {
580 llvm::Intrinsic::ID IntrinID = getGroupIdIntrinsic();
581 llvm::Function *GroupIDIntrinsic =
582 llvm::Intrinsic::isOverloaded(IntrinID)
583 ? CGM.getIntrinsic(IntrinID, {CGM.Int32Ty})
584 : CGM.getIntrinsic(IntrinID);
585 return buildVectorInput(B, GroupIDIntrinsic, Ty);
586 }
587 if (D.hasAttr<HLSLSV_PositionAttr>()) {
588 if (getArch() == llvm::Triple::spirv)
589 return createSPIRVBuiltinLoad(B, CGM.getModule(), Ty, "sv_position",
590 /* BuiltIn::Position */ 0);
591 llvm_unreachable("SV_Position semantic not implemented for this target.");
592 }
593 assert(false && "Unhandled parameter attribute");
594 return nullptr;
595}
596
598 llvm::Function *Fn) {
599 llvm::Module &M = CGM.getModule();
600 llvm::LLVMContext &Ctx = M.getContext();
601 auto *EntryTy = llvm::FunctionType::get(llvm::Type::getVoidTy(Ctx), false);
602 Function *EntryFn =
603 Function::Create(EntryTy, Function::ExternalLinkage, FD->getName(), &M);
604
605 // Copy function attributes over, we have no argument or return attributes
606 // that can be valid on the real entry.
607 AttributeList NewAttrs = AttributeList::get(Ctx, AttributeList::FunctionIndex,
608 Fn->getAttributes().getFnAttrs());
609 EntryFn->setAttributes(NewAttrs);
610 setHLSLEntryAttributes(FD, EntryFn);
611
612 // Set the called function as internal linkage.
613 Fn->setLinkage(GlobalValue::InternalLinkage);
614
615 BasicBlock *BB = BasicBlock::Create(Ctx, "entry", EntryFn);
616 IRBuilder<> B(BB);
618
620 if (CGM.shouldEmitConvergenceTokens()) {
621 assert(EntryFn->isConvergent());
622 llvm::Value *I =
623 B.CreateIntrinsic(llvm::Intrinsic::experimental_convergence_entry, {});
624 llvm::Value *bundleArgs[] = {I};
625 OB.emplace_back("convergencectrl", bundleArgs);
626 }
627
628 // FIXME: support struct parameters where semantics are on members.
629 // See: https://github.com/llvm/llvm-project/issues/57874
630 unsigned SRetOffset = 0;
631 for (const auto &Param : Fn->args()) {
632 if (Param.hasStructRetAttr()) {
633 // FIXME: support output.
634 // See: https://github.com/llvm/llvm-project/issues/57874
635 SRetOffset = 1;
636 Args.emplace_back(PoisonValue::get(Param.getType()));
637 continue;
638 }
639 const ParmVarDecl *PD = FD->getParamDecl(Param.getArgNo() - SRetOffset);
640 Args.push_back(emitInputSemantic(B, *PD, Param.getType()));
641 }
642
643 CallInst *CI = B.CreateCall(FunctionCallee(Fn), Args, OB);
644 CI->setCallingConv(Fn->getCallingConv());
645 // FIXME: Handle codegen for return type semantics.
646 // See: https://github.com/llvm/llvm-project/issues/57875
647 B.CreateRetVoid();
648
649 // Add and identify root signature to function, if applicable
650 for (const Attr *Attr : FD->getAttrs()) {
651 if (const auto *RSAttr = dyn_cast<RootSignatureAttr>(Attr)) {
652 auto *RSDecl = RSAttr->getSignatureDecl();
653 addRootSignature(RSDecl->getVersion(), RSDecl->getRootElements(), EntryFn,
654 M);
655 }
656 }
657}
658
659static void gatherFunctions(SmallVectorImpl<Function *> &Fns, llvm::Module &M,
660 bool CtorOrDtor) {
661 const auto *GV =
662 M.getNamedGlobal(CtorOrDtor ? "llvm.global_ctors" : "llvm.global_dtors");
663 if (!GV)
664 return;
665 const auto *CA = dyn_cast<ConstantArray>(GV->getInitializer());
666 if (!CA)
667 return;
668 // The global_ctor array elements are a struct [Priority, Fn *, COMDat].
669 // HLSL neither supports priorities or COMDat values, so we will check those
670 // in an assert but not handle them.
671
672 for (const auto &Ctor : CA->operands()) {
673 if (isa<ConstantAggregateZero>(Ctor))
674 continue;
675 ConstantStruct *CS = cast<ConstantStruct>(Ctor);
676
677 assert(cast<ConstantInt>(CS->getOperand(0))->getValue() == 65535 &&
678 "HLSL doesn't support setting priority for global ctors.");
679 assert(isa<ConstantPointerNull>(CS->getOperand(2)) &&
680 "HLSL doesn't support COMDat for global ctors.");
681 Fns.push_back(cast<Function>(CS->getOperand(1)));
682 }
683}
684
686 llvm::Module &M = CGM.getModule();
689 gatherFunctions(CtorFns, M, true);
690 gatherFunctions(DtorFns, M, false);
691
692 // Insert a call to the global constructor at the beginning of the entry block
693 // to externally exported functions. This is a bit of a hack, but HLSL allows
694 // global constructors, but doesn't support driver initialization of globals.
695 for (auto &F : M.functions()) {
696 if (!F.hasFnAttribute("hlsl.shader"))
697 continue;
698 auto *Token = getConvergenceToken(F.getEntryBlock());
699 Instruction *IP = &*F.getEntryBlock().begin();
701 if (Token) {
702 llvm::Value *bundleArgs[] = {Token};
703 OB.emplace_back("convergencectrl", bundleArgs);
704 IP = Token->getNextNode();
705 }
706 IRBuilder<> B(IP);
707 for (auto *Fn : CtorFns) {
708 auto CI = B.CreateCall(FunctionCallee(Fn), {}, OB);
709 CI->setCallingConv(Fn->getCallingConv());
710 }
711
712 // Insert global dtors before the terminator of the last instruction
713 B.SetInsertPoint(F.back().getTerminator());
714 for (auto *Fn : DtorFns) {
715 auto CI = B.CreateCall(FunctionCallee(Fn), {}, OB);
716 CI->setCallingConv(Fn->getCallingConv());
717 }
718 }
719
720 // No need to keep global ctors/dtors for non-lib profile after call to
721 // ctors/dtors added for entry.
722 Triple T(M.getTargetTriple());
723 if (T.getEnvironment() != Triple::EnvironmentType::Library) {
724 if (auto *GV = M.getNamedGlobal("llvm.global_ctors"))
725 GV->eraseFromParent();
726 if (auto *GV = M.getNamedGlobal("llvm.global_dtors"))
727 GV->eraseFromParent();
728 }
729}
730
731static void initializeBuffer(CodeGenModule &CGM, llvm::GlobalVariable *GV,
732 Intrinsic::ID IntrID,
734
735 LLVMContext &Ctx = CGM.getLLVMContext();
736 llvm::Function *InitResFunc = llvm::Function::Create(
737 llvm::FunctionType::get(CGM.VoidTy, false),
738 llvm::GlobalValue::InternalLinkage,
739 ("_init_buffer_" + GV->getName()).str(), CGM.getModule());
740 InitResFunc->addFnAttr(llvm::Attribute::AlwaysInline);
741
742 llvm::BasicBlock *EntryBB =
743 llvm::BasicBlock::Create(Ctx, "entry", InitResFunc);
744 CGBuilderTy Builder(CGM, Ctx);
745 const DataLayout &DL = CGM.getModule().getDataLayout();
746 Builder.SetInsertPoint(EntryBB);
747
748 // Make sure the global variable is buffer resource handle
749 llvm::Type *HandleTy = GV->getValueType();
750 assert(HandleTy->isTargetExtTy() && "unexpected type of the buffer global");
751
752 llvm::Value *CreateHandle = Builder.CreateIntrinsic(
753 /*ReturnType=*/HandleTy, IntrID, Args, nullptr,
754 Twine(GV->getName()).concat("_h"));
755
756 llvm::Value *HandleRef = Builder.CreateStructGEP(GV->getValueType(), GV, 0);
757 Builder.CreateAlignedStore(CreateHandle, HandleRef,
758 HandleRef->getPointerAlignment(DL));
759 Builder.CreateRetVoid();
760
761 CGM.AddCXXGlobalInit(InitResFunc);
762}
763
764void CGHLSLRuntime::initializeBufferFromBinding(const HLSLBufferDecl *BufDecl,
765 llvm::GlobalVariable *GV,
766 HLSLVkBindingAttr *VkBinding) {
767 assert(VkBinding && "expect a nonnull binding attribute");
768 auto *Index = llvm::ConstantInt::get(CGM.IntTy, 0);
769 auto *RangeSize = llvm::ConstantInt::get(CGM.IntTy, 1);
770 auto *Set = llvm::ConstantInt::get(CGM.IntTy, VkBinding->getSet());
771 auto *Binding = llvm::ConstantInt::get(CGM.IntTy, VkBinding->getBinding());
772 Value *Name = buildNameForResource(BufDecl->getName(), CGM);
773 llvm::Intrinsic::ID IntrinsicID =
774 CGM.getHLSLRuntime().getCreateHandleFromBindingIntrinsic();
775
776 SmallVector<Value *> Args{Set, Binding, RangeSize, Index, Name};
777 initializeBuffer(CGM, GV, IntrinsicID, Args);
778}
779
780void CGHLSLRuntime::initializeBufferFromBinding(const HLSLBufferDecl *BufDecl,
781 llvm::GlobalVariable *GV,
782 HLSLResourceBindingAttr *RBA) {
783 assert(RBA && "expect a nonnull binding attribute");
784 auto *Index = llvm::ConstantInt::get(CGM.IntTy, 0);
785 auto *RangeSize = llvm::ConstantInt::get(CGM.IntTy, 1);
786 auto *Space = llvm::ConstantInt::get(CGM.IntTy, RBA->getSpaceNumber());
787 Value *Name = buildNameForResource(BufDecl->getName(), CGM);
788
789 llvm::Intrinsic::ID IntrinsicID =
790 RBA->hasRegisterSlot()
791 ? CGM.getHLSLRuntime().getCreateHandleFromBindingIntrinsic()
792 : CGM.getHLSLRuntime().getCreateHandleFromImplicitBindingIntrinsic();
793
794 // buffer with explicit binding
795 if (RBA->hasRegisterSlot()) {
796 auto *RegSlot = llvm::ConstantInt::get(CGM.IntTy, RBA->getSlotNumber());
797 SmallVector<Value *> Args{Space, RegSlot, RangeSize, Index, Name};
798 initializeBuffer(CGM, GV, IntrinsicID, Args);
799 } else {
800 // buffer with implicit binding
801 auto *OrderID =
802 llvm::ConstantInt::get(CGM.IntTy, RBA->getImplicitBindingOrderID());
803 SmallVector<Value *> Args{OrderID, Space, RangeSize, Index, Name};
804 initializeBuffer(CGM, GV, IntrinsicID, Args);
805 }
806}
807
809 llvm::GlobalVariable *GV) {
810 if (auto Attr = VD->getAttr<HLSLVkExtBuiltinInputAttr>())
811 addSPIRVBuiltinDecoration(GV, Attr->getBuiltIn());
812}
813
814llvm::Instruction *CGHLSLRuntime::getConvergenceToken(BasicBlock &BB) {
816 return nullptr;
817
818 auto E = BB.end();
819 for (auto I = BB.begin(); I != E; ++I) {
820 auto *II = dyn_cast<llvm::IntrinsicInst>(&*I);
821 if (II && llvm::isConvergenceControlIntrinsic(II->getIntrinsicID())) {
822 return II;
823 }
824 }
825 llvm_unreachable("Convergence token should have been emitted.");
826 return nullptr;
827}
828
829class OpaqueValueVisitor : public RecursiveASTVisitor<OpaqueValueVisitor> {
830public:
833
835 OVEs.insert(E);
836 return true;
837 }
838};
839
841 InitListExpr *E) {
842
843 typedef CodeGenFunction::OpaqueValueMappingData OpaqueValueMappingData;
844 OpaqueValueVisitor Visitor;
845 Visitor.TraverseStmt(E);
846 for (auto *OVE : Visitor.OVEs) {
847 if (CGF.isOpaqueValueEmitted(OVE))
848 continue;
849 if (OpaqueValueMappingData::shouldBindAsLValue(OVE)) {
850 LValue LV = CGF.EmitLValue(OVE->getSourceExpr());
851 OpaqueValueMappingData::bind(CGF, OVE, LV);
852 } else {
853 RValue RV = CGF.EmitAnyExpr(OVE->getSourceExpr());
854 OpaqueValueMappingData::bind(CGF, OVE, RV);
855 }
856 }
857}
858
860 const ArraySubscriptExpr *ArraySubsExpr, CodeGenFunction &CGF) {
861 assert(ArraySubsExpr->getType()->isHLSLResourceRecord() ||
862 ArraySubsExpr->getType()->isHLSLResourceRecordArray() &&
863 "expected resource array subscript expression");
864
865 // Let clang codegen handle local resource array subscripts,
866 // or when the subscript references on opaque expression (as part of
867 // ArrayInitLoopExpr AST node).
868 const VarDecl *ArrayDecl =
869 dyn_cast_or_null<VarDecl>(getArrayDecl(ArraySubsExpr));
870 if (!ArrayDecl || !ArrayDecl->hasGlobalStorage())
871 return std::nullopt;
872
873 // get the resource array type
874 ASTContext &AST = ArrayDecl->getASTContext();
875 const Type *ResArrayTy = ArrayDecl->getType().getTypePtr();
876 assert(ResArrayTy->isHLSLResourceRecordArray() &&
877 "expected array of resource classes");
878
879 // Iterate through all nested array subscript expressions to calculate
880 // the index in the flattened resource array (if this is a multi-
881 // dimensional array). The index is calculated as a sum of all indices
882 // multiplied by the total size of the array at that level.
883 Value *Index = nullptr;
884 const ArraySubscriptExpr *ASE = ArraySubsExpr;
885 while (ASE != nullptr) {
886 Value *SubIndex = CGF.EmitScalarExpr(ASE->getIdx());
887 if (const auto *ArrayTy =
888 dyn_cast<ConstantArrayType>(ASE->getType().getTypePtr())) {
889 Value *Multiplier = llvm::ConstantInt::get(
890 CGM.IntTy, AST.getConstantArrayElementCount(ArrayTy));
891 SubIndex = CGF.Builder.CreateMul(SubIndex, Multiplier);
892 }
893 Index = Index ? CGF.Builder.CreateAdd(Index, SubIndex) : SubIndex;
894 ASE = dyn_cast<ArraySubscriptExpr>(ASE->getBase()->IgnoreParenImpCasts());
895 }
896
897 // Find binding info for the resource array. For implicit binding
898 // an HLSLResourceBindingAttr should have been added by SemaHLSL.
899 HLSLVkBindingAttr *VkBinding = ArrayDecl->getAttr<HLSLVkBindingAttr>();
900 HLSLResourceBindingAttr *RBA = ArrayDecl->getAttr<HLSLResourceBindingAttr>();
901 assert((VkBinding || RBA) && "resource array must have a binding attribute");
902
903 // Find the individual resource type.
904 QualType ResultTy = ArraySubsExpr->getType();
905 QualType ResourceTy =
906 ResultTy->isArrayType() ? AST.getBaseElementType(ResultTy) : ResultTy;
907
908 // Lookup the resource class constructor based on the resource type and
909 // binding.
910 CXXConstructorDecl *CD = findResourceConstructorDecl(
911 AST, ResourceTy, VkBinding || RBA->hasRegisterSlot());
912
913 // Create a temporary variable for the result, which is either going
914 // to be a single resource instance or a local array of resources (we need to
915 // return an LValue).
916 RawAddress TmpVar = CGF.CreateMemTemp(ResultTy);
917 if (CGF.EmitLifetimeStart(TmpVar.getPointer()))
919 NormalEHLifetimeMarker, TmpVar);
920
925 Address TmpVarAddress = ValueSlot.getAddress();
926
927 // Calculate total array size (= range size).
928 llvm::Value *Range =
929 llvm::ConstantInt::get(CGM.IntTy, getTotalArraySize(AST, ResArrayTy));
930
931 // If the result of the subscript operation is a single resource, call the
932 // constructor.
933 if (ResultTy == ResourceTy) {
934 QualType ThisType = CD->getThisType()->getPointeeType();
935 llvm::Value *ThisPtr = CGF.getAsNaturalPointerTo(TmpVarAddress, ThisType);
936
937 // Assemble the constructor parameters.
938 CallArgList Args;
939 createResourceCtorArgs(CGM, CD, ThisPtr, Range, Index, ArrayDecl->getName(),
940 RBA, VkBinding, Args);
941 // Call the constructor.
942 CGF.EmitCXXConstructorCall(CD, Ctor_Complete, false, false, TmpVarAddress,
943 Args, ValueSlot.mayOverlap(),
944 ArraySubsExpr->getExprLoc(),
945 ValueSlot.isSanitizerChecked());
946 } else {
947 // The result of the subscript operation is a local resource array which
948 // needs to be initialized.
949 const ConstantArrayType *ArrayTy =
950 cast<ConstantArrayType>(ResultTy.getTypePtr());
951 initializeLocalResourceArray(CGF, ValueSlot, ArrayTy, CD, Range, Index,
952 ArrayDecl->getName(), RBA, VkBinding,
953 {llvm::ConstantInt::get(CGM.IntTy, 0)},
954 ArraySubsExpr->getExprLoc());
955 }
956 return CGF.MakeAddrLValue(TmpVar, ResultTy, AlignmentSource::Decl);
957}
Defines the clang::ASTContext interface.
static llvm::Value * createSPIRVBuiltinLoad(IRBuilder<> &B, llvm::Module &M, llvm::Type *Ty, const Twine &Name, unsigned BuiltInID)
static void fillPackoffsetLayout(const HLSLBufferDecl *BufDecl, SmallVector< int32_t > &Layout)
static void addSPIRVBuiltinDecoration(llvm::GlobalVariable *GV, unsigned BuiltIn)
static void gatherFunctions(SmallVectorImpl< Function * > &Fns, llvm::Module &M, bool CtorOrDtor)
static Value * buildVectorInput(IRBuilder<> &B, Function *F, llvm::Type *Ty)
static void initializeBuffer(CodeGenModule &CGM, llvm::GlobalVariable *GV, Intrinsic::ID IntrID, ArrayRef< llvm::Value * > Args)
static const clang::HLSLAttributedResourceType * createBufferHandleType(const HLSLBufferDecl *BufDecl)
const Decl * D
Expr * E
SourceRange Range
Definition: SemaObjC.cpp:753
Defines the clang::TargetOptions class.
C Language Family Type Representation.
bool VisitOpaqueValueExpr(OpaqueValueExpr *E)
llvm::SmallPtrSet< OpaqueValueExpr *, 8 > OVEs
Holds long-lived AST nodes (such as types and decls) that can be referred to throughout the semantic ...
Definition: ASTContext.h:188
QualType getPointerType(QualType T) const
Return the uniqued reference to the type for a pointer to the specified type.
QualType getBaseElementType(const ArrayType *VAT) const
Return the innermost element type of an array type.
CanQualType CharTy
Definition: ASTContext.h:1224
CanQualType IntTy
Definition: ASTContext.h:1231
uint64_t getTypeSize(QualType T) const
Return the size of the specified (complete) type T, in bits.
Definition: ASTContext.h:2625
CharUnits getTypeSizeInChars(QualType T) const
Return the size of the specified (complete) type T, in characters.
CanQualType UnsignedIntTy
Definition: ASTContext.h:1232
QualType getHLSLAttributedResourceType(QualType Wrapped, QualType Contained, const HLSLAttributedResourceType::Attributes &Attrs)
uint64_t getConstantArrayElementCount(const ConstantArrayType *CA) const
Return number of constant array elements.
CanQualType getCanonicalTagType(const TagDecl *TD) const
ArraySubscriptExpr - [C99 6.5.2.1] Array Subscripting.
Definition: Expr.h:2723
SourceLocation getExprLoc() const LLVM_READONLY
Definition: Expr.h:2778
QualType getElementType() const
Definition: TypeBase.h:3750
Attr - This represents one attribute.
Definition: Attr.h:44
Represents a C++ constructor within a class.
Definition: DeclCXX.h:2604
QualType getThisType() const
Return the type of the this pointer.
Definition: DeclCXX.cpp:2809
Represents a C++ struct/union/class.
Definition: DeclCXX.h:258
ctor_range ctors() const
Definition: DeclCXX.h:670
bool isEmpty() const
Determine whether this is an empty class in the sense of (C++11 [meta.unary.prop]).
Definition: DeclCXX.h:1186
QualType withConst() const
Retrieves a version of this type with const applied.
CharUnits - This is an opaque type for sizes expressed in character units.
Definition: CharUnits.h:38
CharUnits alignmentOfArrayElement(CharUnits elementSize) const
Given that this is the alignment of the first element of an array, return the minimum alignment of an...
Definition: CharUnits.h:214
Like RawAddress, an abstract representation of an aligned address, but the pointer contained in this ...
Definition: Address.h:128
CharUnits getAlignment() const
Definition: Address.h:194
An aggregate value slot.
Definition: CGValue.h:504
bool isSanitizerChecked() const
Definition: CGValue.h:662
Address getAddress() const
Definition: CGValue.h:644
static AggValueSlot forAddr(Address addr, Qualifiers quals, IsDestructed_t isDestructed, NeedsGCBarriers_t needsGC, IsAliased_t isAliased, Overlap_t mayOverlap, IsZeroed_t isZeroed=IsNotZeroed, IsSanitizerChecked_t isChecked=IsNotSanitizerChecked)
forAddr - Make a slot for an aggregate value.
Definition: CGValue.h:587
Overlap_t mayOverlap() const
Definition: CGValue.h:658
Address CreateGEP(CodeGenFunction &CGF, Address Addr, llvm::Value *Index, const llvm::Twine &Name="")
Definition: CGBuilder.h:296
llvm::Instruction * getConvergenceToken(llvm::BasicBlock &BB)
void setHLSLEntryAttributes(const FunctionDecl *FD, llvm::Function *Fn)
void addHLSLBufferLayoutType(const RecordType *LayoutStructTy, llvm::TargetExtType *LayoutTy)
void emitEntryFunction(const FunctionDecl *FD, llvm::Function *Fn)
void handleGlobalVarDefinition(const VarDecl *VD, llvm::GlobalVariable *Var)
llvm::TargetExtType * getHLSLBufferLayoutType(const RecordType *LayoutStructTy)
resource_getpointer resource_handlefromimplicitbinding GENERATE_HLSL_INTRINSIC_FUNCTION(GroupMemoryBarrierWithGroupSync, group_memory_barrier_with_group_sync) protected llvm::Value * emitInputSemantic(llvm::IRBuilder<> &B, const ParmVarDecl &D, llvm::Type *Ty)
llvm::Type * convertHLSLSpecificType(const Type *T, SmallVector< int32_t > *Packoffsets=nullptr)
std::optional< LValue > emitResourceArraySubscriptExpr(const ArraySubscriptExpr *E, CodeGenFunction &CGF)
void addBuffer(const HLSLBufferDecl *D)
void emitInitListOpaqueValues(CodeGenFunction &CGF, InitListExpr *E)
CallArgList - Type for representing both the value and type of arguments in a call.
Definition: CGCall.h:274
void add(RValue rvalue, QualType type)
Definition: CGCall.h:302
A non-RAII class containing all the information about a bound opaque value.
CodeGenFunction - This class organizes the per-function state that is used while generating LLVM code...
llvm::Value * getAsNaturalPointerTo(Address Addr, QualType PointeeType)
void pushFullExprCleanup(CleanupKind kind, As... A)
pushFullExprCleanup - Push a cleanup to be run at the end of the current full-expression.
void EmitCXXConstructorCall(const CXXConstructorDecl *D, CXXCtorType Type, bool ForVirtualBase, bool Delegating, AggValueSlot ThisAVS, const CXXConstructExpr *E)
Definition: CGClass.cpp:2114
bool EmitLifetimeStart(llvm::Value *Addr)
Emit a lifetime.begin marker if some criteria are satisfied.
Definition: CGDecl.cpp:1357
RValue EmitAnyExpr(const Expr *E, AggValueSlot aggSlot=AggValueSlot::ignored(), bool ignoreResult=false)
EmitAnyExpr - Emit code to compute the specified expression which can have any type.
Definition: CGExpr.cpp:264
llvm::Type * ConvertTypeForMem(QualType T)
RawAddress CreateMemTemp(QualType T, const Twine &Name="tmp", RawAddress *Alloca=nullptr)
CreateMemTemp - Create a temporary memory object of the given type, with appropriate alignmen and cas...
Definition: CGExpr.cpp:186
llvm::Value * EmitScalarExpr(const Expr *E, bool IgnoreResultAssign=false)
EmitScalarExpr - Emit the computation of the specified expression of LLVM scalar type,...
LValue MakeAddrLValue(Address Addr, QualType T, AlignmentSource Source=AlignmentSource::Type)
LValue EmitLValue(const Expr *E, KnownNonNull_t IsKnownNonNull=NotKnownNonNull)
EmitLValue - Emit code to compute a designator that specifies the location of the expression.
Definition: CGExpr.cpp:1631
bool isOpaqueValueEmitted(const OpaqueValueExpr *E)
isOpaqueValueEmitted - Return true if the opaque value expression has already been emitted.
Definition: CGExpr.cpp:5898
This class organizes the cross-function state that is used while generating LLVM code.
CGHLSLRuntime & getHLSLRuntime()
Return a reference to the configured HLSL runtime.
llvm::Module & getModule() const
void AddCXXGlobalInit(llvm::Function *F)
const LangOptions & getLangOpts() const
const TargetInfo & getTarget() const
void EmitGlobal(GlobalDecl D)
Emit code for a single global function or var decl.
bool shouldEmitConvergenceTokens() const
llvm::Constant * GetAddrOfGlobalVar(const VarDecl *D, llvm::Type *Ty=nullptr, ForDefinition_t IsForDefinition=NotForDefinition)
Return the llvm::Constant for the address of the given global variable.
const TargetCodeGenInfo & getTargetCodeGenInfo()
const CodeGenOptions & getCodeGenOpts() const
llvm::LLVMContext & getLLVMContext()
llvm::Function * getIntrinsic(unsigned IID, ArrayRef< llvm::Type * > Tys={})
void EmitTopLevelDecl(Decl *D)
Emit code for a single top level declaration.
ConstantAddress GetAddrOfConstantCString(const std::string &Str, const char *GlobalName=nullptr)
Returns a pointer to a character array containing the literal and a terminating '\0' character.
llvm::Constant * getPointer() const
Definition: Address.h:308
LValue - This represents an lvalue references.
Definition: CGValue.h:182
RValue - This trivial value class is used to represent the result of an expression that is evaluated.
Definition: CGValue.h:42
static RValue get(llvm::Value *V)
Definition: CGValue.h:98
An abstract representation of an aligned address.
Definition: Address.h:42
llvm::Value * getPointer() const
Definition: Address.h:66
virtual llvm::Type * getHLSLType(CodeGenModule &CGM, const Type *T, const SmallVector< int32_t > *Packoffsets=nullptr) const
Return an LLVM type that corresponds to a HLSL type.
Definition: TargetInfo.h:446
Represents the canonical version of C arrays with a specified constant size.
Definition: TypeBase.h:3776
int64_t getSExtSize() const
Return the size sign-extended as a uint64_t.
Definition: TypeBase.h:3858
A reference to a declared variable, function, enum, etc.
Definition: Expr.h:1272
Decl - This represents one declaration (or definition), e.g.
Definition: DeclBase.h:86
T * getAttr() const
Definition: DeclBase.h:573
bool hasAttrs() const
Definition: DeclBase.h:518
ASTContext & getASTContext() const LLVM_READONLY
Definition: DeclBase.cpp:524
AttrVec & getAttrs()
Definition: DeclBase.h:524
bool hasAttr() const
Definition: DeclBase.h:577
This represents one expression.
Definition: Expr.h:112
Expr * IgnoreParenImpCasts() LLVM_READONLY
Skip past any parentheses and implicit casts which might surround this expression until reaching a fi...
Definition: Expr.cpp:3073
Expr * IgnoreImpCasts() LLVM_READONLY
Skip past any implicit casts which might surround this expression until reaching a fixed point.
Definition: Expr.cpp:3053
QualType getType() const
Definition: Expr.h:144
Represents a function declaration or definition.
Definition: Decl.h:1999
const ParmVarDecl * getParamDecl(unsigned i) const
Definition: Decl.h:2794
QualType getContainedType() const
Definition: TypeBase.h:6752
HLSLBufferDecl - Represent a cbuffer or tbuffer declaration.
Definition: Decl.h:5156
bool isCBuffer() const
Definition: Decl.h:5200
const CXXRecordDecl * getLayoutStruct() const
Definition: Decl.h:5203
bool hasValidPackoffset() const
Definition: Decl.h:5202
buffer_decl_range buffer_decls() const
Definition: Decl.h:5231
Describes an C or C++ initializer list.
Definition: Expr.h:5235
StringRef getName() const
Get the name of identifier for this declaration as a StringRef.
Definition: Decl.h:300
OpaqueValueExpr - An expression referring to an opaque object of a fixed type and value class.
Definition: Expr.h:1180
Represents a parameter to a function.
Definition: Decl.h:1789
A (possibly-)qualified type.
Definition: TypeBase.h:937
const Type * getTypePtr() const
Retrieves a pointer to the underlying (unqualified) type.
Definition: TypeBase.h:8343
LangAS getAddressSpace() const
Return the address space of this type.
Definition: TypeBase.h:8469
The collection of all-type qualifiers we support.
Definition: TypeBase.h:331
A helper class that allows the use of isa/cast/dyncast to detect TagType objects of structs/unions/cl...
Definition: TypeBase.h:6502
A class that does preorder or postorder depth-first traversal on the entire Clang AST and visits each...
bool TraverseStmt(Stmt *S, DataRecursionQueue *Queue=nullptr)
Recursively visit a statement or expression, by dispatching to Traverse*() based on the argument's dy...
Encodes a location in the source.
TargetOptions & getTargetOpts() const
Retrieve the target options.
Definition: TargetInfo.h:323
const llvm::Triple & getTriple() const
Returns the target triple of the primary target.
Definition: TargetInfo.h:1288
Token - This structure provides full information about a lexed token.
Definition: Token.h:36
The base class of the type hierarchy.
Definition: TypeBase.h:1833
bool isIncompleteArrayType() const
Definition: TypeBase.h:8687
CXXRecordDecl * getAsCXXRecordDecl() const
Retrieves the CXXRecordDecl that this type refers to, either because the type is a RecordType or beca...
Definition: Type.h:26
bool isArrayType() const
Definition: TypeBase.h:8679
QualType getPointeeType() const
If this is a pointer, ObjC object pointer, or block pointer, this returns the respective pointee.
Definition: Type.cpp:752
bool isHLSLSpecificType() const
Definition: TypeBase.h:8888
bool isHLSLResourceRecord() const
Definition: Type.cpp:5415
const Type * getUnqualifiedDesugaredType() const
Return the specified type with any "sugar" removed from the type, removing any typedefs,...
Definition: Type.cpp:653
bool isHLSLResourceRecordArray() const
Definition: Type.cpp:5419
Represent the declaration of a variable (in which case it is an lvalue) a function (in which case it ...
Definition: Decl.h:711
QualType getType() const
Definition: Decl.h:722
Represents a variable declaration or definition.
Definition: Decl.h:925
bool hasGlobalStorage() const
Returns true for all variables that do not have local storage.
Definition: Decl.h:1225
StorageClass getStorageClass() const
Returns the storage class as written in the source.
Definition: Decl.h:1167
@ Decl
The l-value was an access to a declared entity or something equivalently strong, like the address of ...
The JSON file list parser is used to communicate input to InstallAPI.
@ Ctor_Complete
Complete object ctor.
Definition: ABI.h:25
@ SC_Static
Definition: Specifiers.h:252
@ Result
The result type of a method or function.
const FunctionProtoType * T
unsigned long uint64_t
unsigned int uint32_t
Diagnostic wrappers for TextAPI types for error reporting.
Definition: Dominators.h:30
llvm::IntegerType * IntTy
int