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"
27#include "llvm/ADT/SmallString.h"
28#include "llvm/ADT/SmallVector.h"
29#include "llvm/Frontend/HLSL/RootSignatureMetadata.h"
30#include "llvm/IR/Constants.h"
31#include "llvm/IR/DerivedTypes.h"
32#include "llvm/IR/GlobalVariable.h"
33#include "llvm/IR/LLVMContext.h"
34#include "llvm/IR/Metadata.h"
35#include "llvm/IR/Module.h"
36#include "llvm/IR/Type.h"
37#include "llvm/IR/Value.h"
38#include "llvm/Support/Alignment.h"
39#include "llvm/Support/ErrorHandling.h"
40#include "llvm/Support/FormatVariadic.h"
41#include <cstdint>
42
43using namespace clang;
44using namespace CodeGen;
45using namespace clang::hlsl;
46using namespace llvm;
47
48using llvm::hlsl::CBufferRowSizeInBytes;
49
50namespace {
51
52void addDxilValVersion(StringRef ValVersionStr, llvm::Module &M) {
53 // The validation of ValVersionStr is done at HLSLToolChain::TranslateArgs.
54 // Assume ValVersionStr is legal here.
55 VersionTuple Version;
56 if (Version.tryParse(ValVersionStr) || Version.getBuild() ||
57 Version.getSubminor() || !Version.getMinor()) {
58 return;
59 }
60
61 uint64_t Major = Version.getMajor();
62 uint64_t Minor = *Version.getMinor();
63
64 auto &Ctx = M.getContext();
65 IRBuilder<> B(M.getContext());
66 MDNode *Val = MDNode::get(Ctx, {ConstantAsMetadata::get(B.getInt32(Major)),
67 ConstantAsMetadata::get(B.getInt32(Minor))});
68 StringRef DXILValKey = "dx.valver";
69 auto *DXILValMD = M.getOrInsertNamedMetadata(DXILValKey);
70 DXILValMD->addOperand(Val);
71}
72
73void addRootSignatureMD(llvm::dxbc::RootSignatureVersion RootSigVer,
75 llvm::Function *Fn, llvm::Module &M) {
76 auto &Ctx = M.getContext();
77
78 llvm::hlsl::rootsig::MetadataBuilder RSBuilder(Ctx, Elements);
79 MDNode *RootSignature = RSBuilder.BuildRootSignature();
80
81 ConstantAsMetadata *Version = ConstantAsMetadata::get(ConstantInt::get(
82 llvm::Type::getInt32Ty(Ctx), llvm::to_underlying(RootSigVer)));
83 ValueAsMetadata *EntryFunc = Fn ? ValueAsMetadata::get(Fn) : nullptr;
84 MDNode *MDVals = MDNode::get(Ctx, {EntryFunc, RootSignature, Version});
85
86 StringRef RootSignatureValKey = "dx.rootsignatures";
87 auto *RootSignatureValMD = M.getOrInsertNamedMetadata(RootSignatureValKey);
88 RootSignatureValMD->addOperand(MDVals);
89}
90
91// Find array variable declaration from nested array subscript AST nodes
92static const ValueDecl *getArrayDecl(const ArraySubscriptExpr *ASE) {
93 const Expr *E = nullptr;
94 while (ASE != nullptr) {
95 E = ASE->getBase()->IgnoreImpCasts();
96 if (!E)
97 return nullptr;
98 ASE = dyn_cast<ArraySubscriptExpr>(E);
99 }
100 if (const DeclRefExpr *DRE = dyn_cast_or_null<DeclRefExpr>(E))
101 return DRE->getDecl();
102 return nullptr;
103}
104
105// Get the total size of the array, or -1 if the array is unbounded.
106static int getTotalArraySize(ASTContext &AST, const clang::Type *Ty) {
108 assert(Ty->isArrayType() && "expected array type");
109 if (Ty->isIncompleteArrayType())
110 return -1;
112}
113
114// Find constructor decl for a specific resource record type and binding
115// (implicit vs. explicit). The constructor has 5 parameters.
116// For explicit binding the signature is:
117// void(unsigned, unsigned, int, unsigned, const char *).
118// For implicit binding the signature is:
119// void(unsigned, int, unsigned, unsigned, const char *).
120static CXXConstructorDecl *findResourceConstructorDecl(ASTContext &AST,
121 QualType ResTy,
122 bool ExplicitBinding) {
123 std::array<QualType, 5> ExpParmTypes = {
126 ExpParmTypes[ExplicitBinding ? 2 : 1] = AST.IntTy;
127
128 CXXRecordDecl *ResDecl = ResTy->getAsCXXRecordDecl();
129 for (auto *Ctor : ResDecl->ctors()) {
130 if (Ctor->getNumParams() != ExpParmTypes.size())
131 continue;
132 auto *ParmIt = Ctor->param_begin();
133 auto ExpTyIt = ExpParmTypes.begin();
134 for (; ParmIt != Ctor->param_end() && ExpTyIt != ExpParmTypes.end();
135 ++ParmIt, ++ExpTyIt) {
136 if ((*ParmIt)->getType() != *ExpTyIt)
137 break;
138 }
139 if (ParmIt == Ctor->param_end())
140 return Ctor;
141 }
142 llvm_unreachable("did not find constructor for resource class");
143}
144
145static Value *buildNameForResource(llvm::StringRef BaseName,
146 CodeGenModule &CGM) {
147 llvm::SmallString<64> GlobalName = {BaseName, ".str"};
148 return CGM.GetAddrOfConstantCString(BaseName.str(), GlobalName.c_str())
149 .getPointer();
150}
151
152static void createResourceCtorArgs(CodeGenModule &CGM, CXXConstructorDecl *CD,
153 llvm::Value *ThisPtr, llvm::Value *Range,
154 llvm::Value *Index, StringRef Name,
155 HLSLResourceBindingAttr *RBA,
156 HLSLVkBindingAttr *VkBinding,
157 CallArgList &Args) {
158 assert((VkBinding || RBA) && "at least one a binding attribute expected");
159
160 std::optional<uint32_t> RegisterSlot;
161 uint32_t SpaceNo = 0;
162 if (VkBinding) {
163 RegisterSlot = VkBinding->getBinding();
164 SpaceNo = VkBinding->getSet();
165 } else {
166 if (RBA->hasRegisterSlot())
167 RegisterSlot = RBA->getSlotNumber();
168 SpaceNo = RBA->getSpaceNumber();
169 }
170
171 ASTContext &AST = CD->getASTContext();
172 Value *NameStr = buildNameForResource(Name, CGM);
173 Value *Space = llvm::ConstantInt::get(CGM.IntTy, SpaceNo);
174
175 Args.add(RValue::get(ThisPtr), CD->getThisType());
176 if (RegisterSlot.has_value()) {
177 // explicit binding
178 auto *RegSlot = llvm::ConstantInt::get(CGM.IntTy, RegisterSlot.value());
179 Args.add(RValue::get(RegSlot), AST.UnsignedIntTy);
180 Args.add(RValue::get(Space), AST.UnsignedIntTy);
181 Args.add(RValue::get(Range), AST.IntTy);
182 Args.add(RValue::get(Index), AST.UnsignedIntTy);
183
184 } else {
185 // implicit binding
186 assert(RBA && "missing implicit binding attribute");
187 auto *OrderID =
188 llvm::ConstantInt::get(CGM.IntTy, RBA->getImplicitBindingOrderID());
189 Args.add(RValue::get(Space), AST.UnsignedIntTy);
190 Args.add(RValue::get(Range), AST.IntTy);
191 Args.add(RValue::get(Index), AST.UnsignedIntTy);
192 Args.add(RValue::get(OrderID), AST.UnsignedIntTy);
193 }
194 Args.add(RValue::get(NameStr), AST.getPointerType(AST.CharTy.withConst()));
195}
196
197// Initializes local resource array variable. For multi-dimensional arrays it
198// calls itself recursively to initialize its sub-arrays. The Index used in the
199// resource constructor calls will begin at StartIndex and will be incremented
200// for each array element. The last used resource Index is returned to the
201// caller.
202static Value *initializeLocalResourceArray(
203 CodeGenFunction &CGF, AggValueSlot &ValueSlot,
204 const ConstantArrayType *ArrayTy, CXXConstructorDecl *CD,
205 llvm::Value *Range, llvm::Value *StartIndex, StringRef ResourceName,
206 HLSLResourceBindingAttr *RBA, HLSLVkBindingAttr *VkBinding,
207 ArrayRef<llvm::Value *> PrevGEPIndices, SourceLocation ArraySubsExprLoc) {
208
209 llvm::IntegerType *IntTy = CGF.CGM.IntTy;
210 llvm::Value *Index = StartIndex;
211 llvm::Value *One = llvm::ConstantInt::get(IntTy, 1);
212 const uint64_t ArraySize = ArrayTy->getSExtSize();
213 QualType ElemType = ArrayTy->getElementType();
214 Address TmpArrayAddr = ValueSlot.getAddress();
215
216 // Add additional index to the getelementptr call indices.
217 // This index will be updated for each array element in the loops below.
218 SmallVector<llvm::Value *> GEPIndices(PrevGEPIndices);
219 GEPIndices.push_back(llvm::ConstantInt::get(IntTy, 0));
220
221 // For array of arrays, recursively initialize the sub-arrays.
222 if (ElemType->isArrayType()) {
223 const ConstantArrayType *SubArrayTy = cast<ConstantArrayType>(ElemType);
224 for (uint64_t I = 0; I < ArraySize; I++) {
225 if (I > 0) {
226 Index = CGF.Builder.CreateAdd(Index, One);
227 GEPIndices.back() = llvm::ConstantInt::get(IntTy, I);
228 }
229 Index = initializeLocalResourceArray(
230 CGF, ValueSlot, SubArrayTy, CD, Range, Index, ResourceName, RBA,
231 VkBinding, GEPIndices, ArraySubsExprLoc);
232 }
233 return Index;
234 }
235
236 // For array of resources, initialize each resource in the array.
237 llvm::Type *Ty = CGF.ConvertTypeForMem(ElemType);
238 CharUnits ElemSize = CD->getASTContext().getTypeSizeInChars(ElemType);
239 CharUnits Align =
240 TmpArrayAddr.getAlignment().alignmentOfArrayElement(ElemSize);
241
242 for (uint64_t I = 0; I < ArraySize; I++) {
243 if (I > 0) {
244 Index = CGF.Builder.CreateAdd(Index, One);
245 GEPIndices.back() = llvm::ConstantInt::get(IntTy, I);
246 }
247 Address ThisAddress =
248 CGF.Builder.CreateGEP(TmpArrayAddr, GEPIndices, Ty, Align);
249 llvm::Value *ThisPtr = CGF.getAsNaturalPointerTo(ThisAddress, ElemType);
250
251 CallArgList Args;
252 createResourceCtorArgs(CGF.CGM, CD, ThisPtr, Range, Index, ResourceName,
253 RBA, VkBinding, Args);
254 CGF.EmitCXXConstructorCall(CD, Ctor_Complete, false, false, ThisAddress,
255 Args, ValueSlot.mayOverlap(), ArraySubsExprLoc,
256 ValueSlot.isSanitizerChecked());
257 }
258 return Index;
259}
260
261} // namespace
262
263llvm::Type *
265 SmallVector<int32_t> *Packoffsets) {
266 assert(T->isHLSLSpecificType() && "Not an HLSL specific type!");
267
268 // Check if the target has a specific translation for this type first.
269 if (llvm::Type *TargetTy =
270 CGM.getTargetCodeGenInfo().getHLSLType(CGM, T, Packoffsets))
271 return TargetTy;
272
273 llvm_unreachable("Generic handling of HLSL types is not supported.");
274}
275
276llvm::Triple::ArchType CGHLSLRuntime::getArch() {
277 return CGM.getTarget().getTriple().getArch();
278}
279
280// Emits constant global variables for buffer constants declarations
281// and creates metadata linking the constant globals with the buffer global.
282void CGHLSLRuntime::emitBufferGlobalsAndMetadata(const HLSLBufferDecl *BufDecl,
283 llvm::GlobalVariable *BufGV) {
284 LLVMContext &Ctx = CGM.getLLVMContext();
285
286 // get the layout struct from constant buffer target type
287 llvm::Type *BufType = BufGV->getValueType();
288 llvm::Type *BufLayoutType =
289 cast<llvm::TargetExtType>(BufType)->getTypeParameter(0);
290 llvm::StructType *LayoutStruct = cast<llvm::StructType>(
291 cast<llvm::TargetExtType>(BufLayoutType)->getTypeParameter(0));
292
293 // Start metadata list associating the buffer global variable with its
294 // constatns
296 BufGlobals.push_back(ValueAsMetadata::get(BufGV));
297
298 const auto *ElemIt = LayoutStruct->element_begin();
299 for (Decl *D : BufDecl->buffer_decls()) {
301 // Nothing to do for this declaration.
302 continue;
303 if (isa<FunctionDecl>(D)) {
304 // A function within an cbuffer is effectively a top-level function.
305 CGM.EmitTopLevelDecl(D);
306 continue;
307 }
308 VarDecl *VD = dyn_cast<VarDecl>(D);
309 if (!VD)
310 continue;
311
312 QualType VDTy = VD->getType();
314 if (VD->getStorageClass() == SC_Static ||
317 // Emit static and groupshared variables and resource classes inside
318 // cbuffer as regular globals
319 CGM.EmitGlobal(VD);
320 } else {
321 // Anything else that is not in the hlsl_constant address space must be
322 // an empty struct or a zero-sized array and can be ignored
323 assert(BufDecl->getASTContext().getTypeSize(VDTy) == 0 &&
324 "constant buffer decl with non-zero sized type outside of "
325 "hlsl_constant address space");
326 }
327 continue;
328 }
329
330 assert(ElemIt != LayoutStruct->element_end() &&
331 "number of elements in layout struct does not match");
332 llvm::Type *LayoutType = *ElemIt++;
333
334 // FIXME: handle resources inside user defined structs
335 // (llvm/wg-hlsl#175)
336
337 // create global variable for the constant and to metadata list
338 GlobalVariable *ElemGV =
339 cast<GlobalVariable>(CGM.GetAddrOfGlobalVar(VD, LayoutType));
340 BufGlobals.push_back(ValueAsMetadata::get(ElemGV));
341 }
342 assert(ElemIt == LayoutStruct->element_end() &&
343 "number of elements in layout struct does not match");
344
345 // add buffer metadata to the module
346 CGM.getModule()
347 .getOrInsertNamedMetadata("hlsl.cbs")
348 ->addOperand(MDNode::get(Ctx, BufGlobals));
349}
350
351// Creates resource handle type for the HLSL buffer declaration
352static const clang::HLSLAttributedResourceType *
354 ASTContext &AST = BufDecl->getASTContext();
356 AST.HLSLResourceTy, AST.getCanonicalTagType(BufDecl->getLayoutStruct()),
357 HLSLAttributedResourceType::Attributes(ResourceClass::CBuffer));
359}
360
361// Iterates over all declarations in the HLSL buffer and based on the
362// packoffset or register(c#) annotations it fills outs the Layout
363// vector with the user-specified layout offsets.
364// The buffer offsets can be specified 2 ways:
365// 1. declarations in cbuffer {} block can have a packoffset annotation
366// (translates to HLSLPackOffsetAttr)
367// 2. default constant buffer declarations at global scope can have
368// register(c#) annotations (translates to HLSLResourceBindingAttr with
369// RegisterType::C)
370// It is not guaranteed that all declarations in a buffer have an annotation.
371// For those where it is not specified a -1 value is added to the Layout
372// vector. In the final layout these declarations will be placed at the end
373// of the HLSL buffer after all of the elements with specified offset.
374static void fillPackoffsetLayout(const HLSLBufferDecl *BufDecl,
375 SmallVector<int32_t> &Layout) {
376 assert(Layout.empty() && "expected empty vector for layout");
377 assert(BufDecl->hasValidPackoffset());
378
379 for (Decl *D : BufDecl->buffer_decls()) {
381 continue;
382 }
383 VarDecl *VD = dyn_cast<VarDecl>(D);
384 if (!VD || VD->getType().getAddressSpace() != LangAS::hlsl_constant)
385 continue;
386
387 if (!VD->hasAttrs()) {
388 Layout.push_back(-1);
389 continue;
390 }
391
392 int32_t Offset = -1;
393 for (auto *Attr : VD->getAttrs()) {
394 if (auto *POA = dyn_cast<HLSLPackOffsetAttr>(Attr)) {
395 Offset = POA->getOffsetInBytes();
396 break;
397 }
398 auto *RBA = dyn_cast<HLSLResourceBindingAttr>(Attr);
399 if (RBA &&
400 RBA->getRegisterType() == HLSLResourceBindingAttr::RegisterType::C) {
401 Offset = RBA->getSlotNumber() * CBufferRowSizeInBytes;
402 break;
403 }
404 }
405 Layout.push_back(Offset);
406 }
407}
408
409// Codegen for HLSLBufferDecl
411
412 assert(BufDecl->isCBuffer() && "tbuffer codegen is not supported yet");
413
414 // create resource handle type for the buffer
415 const clang::HLSLAttributedResourceType *ResHandleTy =
416 createBufferHandleType(BufDecl);
417
418 // empty constant buffer is ignored
419 if (ResHandleTy->getContainedType()->getAsCXXRecordDecl()->isEmpty())
420 return;
421
422 // create global variable for the constant buffer
424 if (BufDecl->hasValidPackoffset())
425 fillPackoffsetLayout(BufDecl, Layout);
426
427 llvm::TargetExtType *TargetTy =
429 ResHandleTy, BufDecl->hasValidPackoffset() ? &Layout : nullptr));
430 llvm::GlobalVariable *BufGV = new GlobalVariable(
431 TargetTy, /*isConstant*/ false,
432 GlobalValue::LinkageTypes::ExternalLinkage, PoisonValue::get(TargetTy),
433 llvm::formatv("{0}{1}", BufDecl->getName(),
434 BufDecl->isCBuffer() ? ".cb" : ".tb"),
435 GlobalValue::NotThreadLocal);
436 CGM.getModule().insertGlobalVariable(BufGV);
437
438 // Add globals for constant buffer elements and create metadata nodes
439 emitBufferGlobalsAndMetadata(BufDecl, BufGV);
440
441 // Initialize cbuffer from binding (implicit or explicit)
442 if (HLSLVkBindingAttr *VkBinding = BufDecl->getAttr<HLSLVkBindingAttr>()) {
443 initializeBufferFromBinding(BufDecl, BufGV, VkBinding);
444 } else {
445 HLSLResourceBindingAttr *RBA = BufDecl->getAttr<HLSLResourceBindingAttr>();
446 assert(RBA &&
447 "cbuffer/tbuffer should always have resource binding attribute");
448 initializeBufferFromBinding(BufDecl, BufGV, RBA);
449 }
450}
451
453 const HLSLRootSignatureDecl *SignatureDecl) {
454 llvm::Module &M = CGM.getModule();
455 Triple T(M.getTargetTriple());
456
457 // Generated later with the function decl if not targeting root signature
458 if (T.getEnvironment() != Triple::EnvironmentType::RootSignature)
459 return;
460
461 addRootSignatureMD(SignatureDecl->getVersion(),
462 SignatureDecl->getRootElements(), nullptr, M);
463}
464
465llvm::TargetExtType *
466CGHLSLRuntime::getHLSLBufferLayoutType(const RecordType *StructType) {
467 const auto Entry = LayoutTypes.find(StructType);
468 if (Entry != LayoutTypes.end())
469 return Entry->getSecond();
470 return nullptr;
471}
472
473void CGHLSLRuntime::addHLSLBufferLayoutType(const RecordType *StructType,
474 llvm::TargetExtType *LayoutTy) {
475 assert(getHLSLBufferLayoutType(StructType) == nullptr &&
476 "layout type for this struct already exist");
477 LayoutTypes[StructType] = LayoutTy;
478}
479
481 auto &TargetOpts = CGM.getTarget().getTargetOpts();
482 auto &CodeGenOpts = CGM.getCodeGenOpts();
483 auto &LangOpts = CGM.getLangOpts();
484 llvm::Module &M = CGM.getModule();
485 Triple T(M.getTargetTriple());
486 if (T.getArch() == Triple::ArchType::dxil)
487 addDxilValVersion(TargetOpts.DxilValidatorVersion, M);
488 if (CodeGenOpts.ResMayAlias)
489 M.setModuleFlag(llvm::Module::ModFlagBehavior::Error, "dx.resmayalias", 1);
490
491 // NativeHalfType corresponds to the -fnative-half-type clang option which is
492 // aliased by clang-dxc's -enable-16bit-types option. This option is used to
493 // set the UseNativeLowPrecision DXIL module flag in the DirectX backend
494 if (LangOpts.NativeHalfType)
495 M.setModuleFlag(llvm::Module::ModFlagBehavior::Error, "dx.nativelowprec",
496 1);
497
499}
500
502 const FunctionDecl *FD, llvm::Function *Fn) {
503 const auto *ShaderAttr = FD->getAttr<HLSLShaderAttr>();
504 assert(ShaderAttr && "All entry functions must have a HLSLShaderAttr");
505 const StringRef ShaderAttrKindStr = "hlsl.shader";
506 Fn->addFnAttr(ShaderAttrKindStr,
507 llvm::Triple::getEnvironmentTypeName(ShaderAttr->getType()));
508 if (HLSLNumThreadsAttr *NumThreadsAttr = FD->getAttr<HLSLNumThreadsAttr>()) {
509 const StringRef NumThreadsKindStr = "hlsl.numthreads";
510 std::string NumThreadsStr =
511 formatv("{0},{1},{2}", NumThreadsAttr->getX(), NumThreadsAttr->getY(),
512 NumThreadsAttr->getZ());
513 Fn->addFnAttr(NumThreadsKindStr, NumThreadsStr);
514 }
515 if (HLSLWaveSizeAttr *WaveSizeAttr = FD->getAttr<HLSLWaveSizeAttr>()) {
516 const StringRef WaveSizeKindStr = "hlsl.wavesize";
517 std::string WaveSizeStr =
518 formatv("{0},{1},{2}", WaveSizeAttr->getMin(), WaveSizeAttr->getMax(),
519 WaveSizeAttr->getPreferred());
520 Fn->addFnAttr(WaveSizeKindStr, WaveSizeStr);
521 }
522 // HLSL entry functions are materialized for module functions with
523 // HLSLShaderAttr attribute. SetLLVMFunctionAttributesForDefinition called
524 // later in the compiler-flow for such module functions is not aware of and
525 // hence not able to set attributes of the newly materialized entry functions.
526 // So, set attributes of entry function here, as appropriate.
527 if (CGM.getCodeGenOpts().OptimizationLevel == 0)
528 Fn->addFnAttr(llvm::Attribute::OptimizeNone);
529 Fn->addFnAttr(llvm::Attribute::NoInline);
530}
531
532static Value *buildVectorInput(IRBuilder<> &B, Function *F, llvm::Type *Ty) {
533 if (const auto *VT = dyn_cast<FixedVectorType>(Ty)) {
534 Value *Result = PoisonValue::get(Ty);
535 for (unsigned I = 0; I < VT->getNumElements(); ++I) {
536 Value *Elt = B.CreateCall(F, {B.getInt32(I)});
537 Result = B.CreateInsertElement(Result, Elt, I);
538 }
539 return Result;
540 }
541 return B.CreateCall(F, {B.getInt32(0)});
542}
543
544static void addSPIRVBuiltinDecoration(llvm::GlobalVariable *GV,
545 unsigned BuiltIn) {
546 LLVMContext &Ctx = GV->getContext();
547 IRBuilder<> B(GV->getContext());
548 MDNode *Operands = MDNode::get(
549 Ctx,
550 {ConstantAsMetadata::get(B.getInt32(/* Spirv::Decoration::BuiltIn */ 11)),
551 ConstantAsMetadata::get(B.getInt32(BuiltIn))});
552 MDNode *Decoration = MDNode::get(Ctx, {Operands});
553 GV->addMetadata("spirv.Decorations", *Decoration);
554}
555
556static llvm::Value *createSPIRVBuiltinLoad(IRBuilder<> &B, llvm::Module &M,
557 llvm::Type *Ty, const Twine &Name,
558 unsigned BuiltInID) {
559 auto *GV = new llvm::GlobalVariable(
560 M, Ty, /* isConstant= */ true, llvm::GlobalValue::ExternalLinkage,
561 /* Initializer= */ nullptr, Name, /* insertBefore= */ nullptr,
562 llvm::GlobalVariable::GeneralDynamicTLSModel,
563 /* AddressSpace */ 7, /* isExternallyInitialized= */ true);
564 addSPIRVBuiltinDecoration(GV, BuiltInID);
565 GV->setVisibility(llvm::GlobalValue::HiddenVisibility);
566 return B.CreateLoad(Ty, GV);
567}
568
569llvm::Value *
570CGHLSLRuntime::emitSystemSemanticLoad(IRBuilder<> &B, llvm::Type *Type,
572 SemanticInfo &ActiveSemantic) {
573 if (isa<HLSLSV_GroupIndexAttr>(ActiveSemantic.Semantic)) {
574 llvm::Function *GroupIndex =
575 CGM.getIntrinsic(getFlattenedThreadIdInGroupIntrinsic());
576 return B.CreateCall(FunctionCallee(GroupIndex));
577 }
578
579 if (isa<HLSLSV_DispatchThreadIDAttr>(ActiveSemantic.Semantic)) {
580 llvm::Intrinsic::ID IntrinID = getThreadIdIntrinsic();
581 llvm::Function *ThreadIDIntrinsic =
582 llvm::Intrinsic::isOverloaded(IntrinID)
583 ? CGM.getIntrinsic(IntrinID, {CGM.Int32Ty})
584 : CGM.getIntrinsic(IntrinID);
585 return buildVectorInput(B, ThreadIDIntrinsic, Type);
586 }
587
588 if (isa<HLSLSV_GroupThreadIDAttr>(ActiveSemantic.Semantic)) {
589 llvm::Intrinsic::ID IntrinID = getGroupThreadIdIntrinsic();
590 llvm::Function *GroupThreadIDIntrinsic =
591 llvm::Intrinsic::isOverloaded(IntrinID)
592 ? CGM.getIntrinsic(IntrinID, {CGM.Int32Ty})
593 : CGM.getIntrinsic(IntrinID);
594 return buildVectorInput(B, GroupThreadIDIntrinsic, Type);
595 }
596
597 if (isa<HLSLSV_GroupIDAttr>(ActiveSemantic.Semantic)) {
598 llvm::Intrinsic::ID IntrinID = getGroupIdIntrinsic();
599 llvm::Function *GroupIDIntrinsic =
600 llvm::Intrinsic::isOverloaded(IntrinID)
601 ? CGM.getIntrinsic(IntrinID, {CGM.Int32Ty})
602 : CGM.getIntrinsic(IntrinID);
603 return buildVectorInput(B, GroupIDIntrinsic, Type);
604 }
605
606 if (HLSLSV_PositionAttr *S =
607 dyn_cast<HLSLSV_PositionAttr>(ActiveSemantic.Semantic)) {
608 if (CGM.getTriple().getEnvironment() == Triple::EnvironmentType::Pixel)
609 return createSPIRVBuiltinLoad(B, CGM.getModule(), Type,
610 S->getAttrName()->getName(),
611 /* BuiltIn::FragCoord */ 15);
612 }
613
614 llvm_unreachable("non-handled system semantic. FIXME.");
615}
616
617llvm::Value *
620 SemanticInfo &ActiveSemantic) {
621
622 if (!ActiveSemantic.Semantic) {
623 ActiveSemantic.Semantic = Decl->getAttr<HLSLSemanticAttr>();
624 if (!ActiveSemantic.Semantic) {
625 CGM.getDiags().Report(Decl->getInnerLocStart(),
626 diag::err_hlsl_semantic_missing);
627 return nullptr;
628 }
629 ActiveSemantic.Index = ActiveSemantic.Semantic->getSemanticIndex();
630 }
631
632 return emitSystemSemanticLoad(B, Type, Decl, ActiveSemantic);
633}
634
635llvm::Value *
636CGHLSLRuntime::handleSemanticLoad(IRBuilder<> &B, llvm::Type *Type,
638 SemanticInfo &ActiveSemantic) {
639 assert(!Type->isStructTy());
640 return handleScalarSemanticLoad(B, Type, Decl, ActiveSemantic);
641}
642
644 llvm::Function *Fn) {
645 llvm::Module &M = CGM.getModule();
646 llvm::LLVMContext &Ctx = M.getContext();
647 auto *EntryTy = llvm::FunctionType::get(llvm::Type::getVoidTy(Ctx), false);
648 Function *EntryFn =
649 Function::Create(EntryTy, Function::ExternalLinkage, FD->getName(), &M);
650
651 // Copy function attributes over, we have no argument or return attributes
652 // that can be valid on the real entry.
653 AttributeList NewAttrs = AttributeList::get(Ctx, AttributeList::FunctionIndex,
654 Fn->getAttributes().getFnAttrs());
655 EntryFn->setAttributes(NewAttrs);
656 setHLSLEntryAttributes(FD, EntryFn);
657
658 // Set the called function as internal linkage.
659 Fn->setLinkage(GlobalValue::InternalLinkage);
660
661 BasicBlock *BB = BasicBlock::Create(Ctx, "entry", EntryFn);
662 IRBuilder<> B(BB);
664
666 if (CGM.shouldEmitConvergenceTokens()) {
667 assert(EntryFn->isConvergent());
668 llvm::Value *I =
669 B.CreateIntrinsic(llvm::Intrinsic::experimental_convergence_entry, {});
670 llvm::Value *bundleArgs[] = {I};
671 OB.emplace_back("convergencectrl", bundleArgs);
672 }
673
674 // FIXME: support struct parameters where semantics are on members.
675 // See: https://github.com/llvm/llvm-project/issues/57874
676 unsigned SRetOffset = 0;
677 for (const auto &Param : Fn->args()) {
678 if (Param.hasStructRetAttr()) {
679 // FIXME: support output.
680 // See: https://github.com/llvm/llvm-project/issues/57874
681 SRetOffset = 1;
682 Args.emplace_back(PoisonValue::get(Param.getType()));
683 continue;
684 }
685
686 const ParmVarDecl *PD = FD->getParamDecl(Param.getArgNo() - SRetOffset);
687 SemanticInfo ActiveSemantic = {nullptr, 0};
688 Args.push_back(handleSemanticLoad(B, Param.getType(), PD, ActiveSemantic));
689 }
690
691 CallInst *CI = B.CreateCall(FunctionCallee(Fn), Args, OB);
692 CI->setCallingConv(Fn->getCallingConv());
693 // FIXME: Handle codegen for return type semantics.
694 // See: https://github.com/llvm/llvm-project/issues/57875
695 B.CreateRetVoid();
696
697 // Add and identify root signature to function, if applicable
698 for (const Attr *Attr : FD->getAttrs()) {
699 if (const auto *RSAttr = dyn_cast<RootSignatureAttr>(Attr)) {
700 auto *RSDecl = RSAttr->getSignatureDecl();
701 addRootSignatureMD(RSDecl->getVersion(), RSDecl->getRootElements(),
702 EntryFn, M);
703 }
704 }
705}
706
707static void gatherFunctions(SmallVectorImpl<Function *> &Fns, llvm::Module &M,
708 bool CtorOrDtor) {
709 const auto *GV =
710 M.getNamedGlobal(CtorOrDtor ? "llvm.global_ctors" : "llvm.global_dtors");
711 if (!GV)
712 return;
713 const auto *CA = dyn_cast<ConstantArray>(GV->getInitializer());
714 if (!CA)
715 return;
716 // The global_ctor array elements are a struct [Priority, Fn *, COMDat].
717 // HLSL neither supports priorities or COMDat values, so we will check those
718 // in an assert but not handle them.
719
720 for (const auto &Ctor : CA->operands()) {
722 continue;
723 ConstantStruct *CS = cast<ConstantStruct>(Ctor);
724
725 assert(cast<ConstantInt>(CS->getOperand(0))->getValue() == 65535 &&
726 "HLSL doesn't support setting priority for global ctors.");
727 assert(isa<ConstantPointerNull>(CS->getOperand(2)) &&
728 "HLSL doesn't support COMDat for global ctors.");
729 Fns.push_back(cast<Function>(CS->getOperand(1)));
730 }
731}
732
734 llvm::Module &M = CGM.getModule();
737 gatherFunctions(CtorFns, M, true);
738 gatherFunctions(DtorFns, M, false);
739
740 // Insert a call to the global constructor at the beginning of the entry block
741 // to externally exported functions. This is a bit of a hack, but HLSL allows
742 // global constructors, but doesn't support driver initialization of globals.
743 for (auto &F : M.functions()) {
744 if (!F.hasFnAttribute("hlsl.shader"))
745 continue;
746 auto *Token = getConvergenceToken(F.getEntryBlock());
747 Instruction *IP = &*F.getEntryBlock().begin();
749 if (Token) {
750 llvm::Value *bundleArgs[] = {Token};
751 OB.emplace_back("convergencectrl", bundleArgs);
752 IP = Token->getNextNode();
753 }
754 IRBuilder<> B(IP);
755 for (auto *Fn : CtorFns) {
756 auto CI = B.CreateCall(FunctionCallee(Fn), {}, OB);
757 CI->setCallingConv(Fn->getCallingConv());
758 }
759
760 // Insert global dtors before the terminator of the last instruction
761 B.SetInsertPoint(F.back().getTerminator());
762 for (auto *Fn : DtorFns) {
763 auto CI = B.CreateCall(FunctionCallee(Fn), {}, OB);
764 CI->setCallingConv(Fn->getCallingConv());
765 }
766 }
767
768 // No need to keep global ctors/dtors for non-lib profile after call to
769 // ctors/dtors added for entry.
770 Triple T(M.getTargetTriple());
771 if (T.getEnvironment() != Triple::EnvironmentType::Library) {
772 if (auto *GV = M.getNamedGlobal("llvm.global_ctors"))
773 GV->eraseFromParent();
774 if (auto *GV = M.getNamedGlobal("llvm.global_dtors"))
775 GV->eraseFromParent();
776 }
777}
778
779static void initializeBuffer(CodeGenModule &CGM, llvm::GlobalVariable *GV,
780 Intrinsic::ID IntrID,
782
783 LLVMContext &Ctx = CGM.getLLVMContext();
784 llvm::Function *InitResFunc = llvm::Function::Create(
785 llvm::FunctionType::get(CGM.VoidTy, false),
786 llvm::GlobalValue::InternalLinkage,
787 ("_init_buffer_" + GV->getName()).str(), CGM.getModule());
788 InitResFunc->addFnAttr(llvm::Attribute::AlwaysInline);
789
790 llvm::BasicBlock *EntryBB =
791 llvm::BasicBlock::Create(Ctx, "entry", InitResFunc);
792 CGBuilderTy Builder(CGM, Ctx);
793 const DataLayout &DL = CGM.getModule().getDataLayout();
794 Builder.SetInsertPoint(EntryBB);
795
796 // Make sure the global variable is buffer resource handle
797 llvm::Type *HandleTy = GV->getValueType();
798 assert(HandleTy->isTargetExtTy() && "unexpected type of the buffer global");
799
800 llvm::Value *CreateHandle = Builder.CreateIntrinsic(
801 /*ReturnType=*/HandleTy, IntrID, Args, nullptr,
802 Twine(GV->getName()).concat("_h"));
803
804 llvm::Value *HandleRef = Builder.CreateStructGEP(GV->getValueType(), GV, 0);
805 Builder.CreateAlignedStore(CreateHandle, HandleRef,
806 HandleRef->getPointerAlignment(DL));
807 Builder.CreateRetVoid();
808
809 CGM.AddCXXGlobalInit(InitResFunc);
810}
811
812void CGHLSLRuntime::initializeBufferFromBinding(const HLSLBufferDecl *BufDecl,
813 llvm::GlobalVariable *GV,
814 HLSLVkBindingAttr *VkBinding) {
815 assert(VkBinding && "expect a nonnull binding attribute");
816 auto *Index = llvm::ConstantInt::get(CGM.IntTy, 0);
817 auto *RangeSize = llvm::ConstantInt::get(CGM.IntTy, 1);
818 auto *Set = llvm::ConstantInt::get(CGM.IntTy, VkBinding->getSet());
819 auto *Binding = llvm::ConstantInt::get(CGM.IntTy, VkBinding->getBinding());
820 Value *Name = buildNameForResource(BufDecl->getName(), CGM);
821 llvm::Intrinsic::ID IntrinsicID =
822 CGM.getHLSLRuntime().getCreateHandleFromBindingIntrinsic();
823
824 SmallVector<Value *> Args{Set, Binding, RangeSize, Index, Name};
825 initializeBuffer(CGM, GV, IntrinsicID, Args);
826}
827
828void CGHLSLRuntime::initializeBufferFromBinding(const HLSLBufferDecl *BufDecl,
829 llvm::GlobalVariable *GV,
830 HLSLResourceBindingAttr *RBA) {
831 assert(RBA && "expect a nonnull binding attribute");
832 auto *Index = llvm::ConstantInt::get(CGM.IntTy, 0);
833 auto *RangeSize = llvm::ConstantInt::get(CGM.IntTy, 1);
834 auto *Space = llvm::ConstantInt::get(CGM.IntTy, RBA->getSpaceNumber());
835 Value *Name = buildNameForResource(BufDecl->getName(), CGM);
836
837 llvm::Intrinsic::ID IntrinsicID =
838 RBA->hasRegisterSlot()
839 ? CGM.getHLSLRuntime().getCreateHandleFromBindingIntrinsic()
840 : CGM.getHLSLRuntime().getCreateHandleFromImplicitBindingIntrinsic();
841
842 // buffer with explicit binding
843 if (RBA->hasRegisterSlot()) {
844 auto *RegSlot = llvm::ConstantInt::get(CGM.IntTy, RBA->getSlotNumber());
845 SmallVector<Value *> Args{Space, RegSlot, RangeSize, Index, Name};
846 initializeBuffer(CGM, GV, IntrinsicID, Args);
847 } else {
848 // buffer with implicit binding
849 auto *OrderID =
850 llvm::ConstantInt::get(CGM.IntTy, RBA->getImplicitBindingOrderID());
851 SmallVector<Value *> Args{OrderID, Space, RangeSize, Index, Name};
852 initializeBuffer(CGM, GV, IntrinsicID, Args);
853 }
854}
855
857 llvm::GlobalVariable *GV) {
858 if (auto Attr = VD->getAttr<HLSLVkExtBuiltinInputAttr>())
859 addSPIRVBuiltinDecoration(GV, Attr->getBuiltIn());
860}
861
862llvm::Instruction *CGHLSLRuntime::getConvergenceToken(BasicBlock &BB) {
864 return nullptr;
865
866 auto E = BB.end();
867 for (auto I = BB.begin(); I != E; ++I) {
868 auto *II = dyn_cast<llvm::IntrinsicInst>(&*I);
869 if (II && llvm::isConvergenceControlIntrinsic(II->getIntrinsicID())) {
870 return II;
871 }
872 }
873 llvm_unreachable("Convergence token should have been emitted.");
874 return nullptr;
875}
876
877class OpaqueValueVisitor : public RecursiveASTVisitor<OpaqueValueVisitor> {
878public:
882
884 // These need to be bound in CodeGenFunction::EmitHLSLOutArgLValues
885 // or CodeGenFunction::EmitHLSLOutArgExpr. If they are part of this
886 // traversal, the temporary containing the copy out will not have
887 // been created yet.
888 return false;
889 }
890
892 // Traverse the source expression first.
893 if (E->getSourceExpr())
895
896 // Then add this OVE if we haven't seen it before.
897 if (Visited.insert(E).second)
898 OVEs.push_back(E);
899
900 return true;
901 }
902};
903
905 InitListExpr *E) {
906
907 typedef CodeGenFunction::OpaqueValueMappingData OpaqueValueMappingData;
908 OpaqueValueVisitor Visitor;
909 Visitor.TraverseStmt(E);
910 for (auto *OVE : Visitor.OVEs) {
911 if (CGF.isOpaqueValueEmitted(OVE))
912 continue;
913 if (OpaqueValueMappingData::shouldBindAsLValue(OVE)) {
914 LValue LV = CGF.EmitLValue(OVE->getSourceExpr());
915 OpaqueValueMappingData::bind(CGF, OVE, LV);
916 } else {
917 RValue RV = CGF.EmitAnyExpr(OVE->getSourceExpr());
918 OpaqueValueMappingData::bind(CGF, OVE, RV);
919 }
920 }
921}
922
924 const ArraySubscriptExpr *ArraySubsExpr, CodeGenFunction &CGF) {
925 assert(ArraySubsExpr->getType()->isHLSLResourceRecord() ||
926 ArraySubsExpr->getType()->isHLSLResourceRecordArray() &&
927 "expected resource array subscript expression");
928
929 // Let clang codegen handle local resource array subscripts,
930 // or when the subscript references on opaque expression (as part of
931 // ArrayInitLoopExpr AST node).
932 const VarDecl *ArrayDecl =
933 dyn_cast_or_null<VarDecl>(getArrayDecl(ArraySubsExpr));
934 if (!ArrayDecl || !ArrayDecl->hasGlobalStorage())
935 return std::nullopt;
936
937 // get the resource array type
938 ASTContext &AST = ArrayDecl->getASTContext();
939 const Type *ResArrayTy = ArrayDecl->getType().getTypePtr();
940 assert(ResArrayTy->isHLSLResourceRecordArray() &&
941 "expected array of resource classes");
942
943 // Iterate through all nested array subscript expressions to calculate
944 // the index in the flattened resource array (if this is a multi-
945 // dimensional array). The index is calculated as a sum of all indices
946 // multiplied by the total size of the array at that level.
947 Value *Index = nullptr;
948 const ArraySubscriptExpr *ASE = ArraySubsExpr;
949 while (ASE != nullptr) {
950 Value *SubIndex = CGF.EmitScalarExpr(ASE->getIdx());
951 if (const auto *ArrayTy =
952 dyn_cast<ConstantArrayType>(ASE->getType().getTypePtr())) {
953 Value *Multiplier = llvm::ConstantInt::get(
954 CGM.IntTy, AST.getConstantArrayElementCount(ArrayTy));
955 SubIndex = CGF.Builder.CreateMul(SubIndex, Multiplier);
956 }
957 Index = Index ? CGF.Builder.CreateAdd(Index, SubIndex) : SubIndex;
958 ASE = dyn_cast<ArraySubscriptExpr>(ASE->getBase()->IgnoreParenImpCasts());
959 }
960
961 // Find binding info for the resource array. For implicit binding
962 // an HLSLResourceBindingAttr should have been added by SemaHLSL.
963 HLSLVkBindingAttr *VkBinding = ArrayDecl->getAttr<HLSLVkBindingAttr>();
964 HLSLResourceBindingAttr *RBA = ArrayDecl->getAttr<HLSLResourceBindingAttr>();
965 assert((VkBinding || RBA) && "resource array must have a binding attribute");
966
967 // Find the individual resource type.
968 QualType ResultTy = ArraySubsExpr->getType();
969 QualType ResourceTy =
970 ResultTy->isArrayType() ? AST.getBaseElementType(ResultTy) : ResultTy;
971
972 // Lookup the resource class constructor based on the resource type and
973 // binding.
974 CXXConstructorDecl *CD = findResourceConstructorDecl(
975 AST, ResourceTy, VkBinding || RBA->hasRegisterSlot());
976
977 // Create a temporary variable for the result, which is either going
978 // to be a single resource instance or a local array of resources (we need to
979 // return an LValue).
980 RawAddress TmpVar = CGF.CreateMemTemp(ResultTy);
981 if (CGF.EmitLifetimeStart(TmpVar.getPointer()))
983 NormalEHLifetimeMarker, TmpVar);
984
989 Address TmpVarAddress = ValueSlot.getAddress();
990
991 // Calculate total array size (= range size).
992 llvm::Value *Range =
993 llvm::ConstantInt::get(CGM.IntTy, getTotalArraySize(AST, ResArrayTy));
994
995 // If the result of the subscript operation is a single resource, call the
996 // constructor.
997 if (ResultTy == ResourceTy) {
998 QualType ThisType = CD->getThisType()->getPointeeType();
999 llvm::Value *ThisPtr = CGF.getAsNaturalPointerTo(TmpVarAddress, ThisType);
1000
1001 // Assemble the constructor parameters.
1002 CallArgList Args;
1003 createResourceCtorArgs(CGM, CD, ThisPtr, Range, Index, ArrayDecl->getName(),
1004 RBA, VkBinding, Args);
1005 // Call the constructor.
1006 CGF.EmitCXXConstructorCall(CD, Ctor_Complete, false, false, TmpVarAddress,
1007 Args, ValueSlot.mayOverlap(),
1008 ArraySubsExpr->getExprLoc(),
1009 ValueSlot.isSanitizerChecked());
1010 } else {
1011 // The result of the subscript operation is a local resource array which
1012 // needs to be initialized.
1013 const ConstantArrayType *ArrayTy =
1015 initializeLocalResourceArray(CGF, ValueSlot, ArrayTy, CD, Range, Index,
1016 ArrayDecl->getName(), RBA, VkBinding,
1017 {llvm::ConstantInt::get(CGM.IntTy, 0)},
1018 ArraySubsExpr->getExprLoc());
1019 }
1020 return CGF.MakeAddrLValue(TmpVar, ResultTy, AlignmentSource::Decl);
1021}
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)
Defines the clang::TargetOptions class.
C Language Family Type Representation.
bool VisitHLSLOutArgExpr(HLSLOutArgExpr *)
llvm::SmallVector< OpaqueValueExpr *, 8 > OVEs
bool VisitOpaqueValueExpr(OpaqueValueExpr *E)
llvm::SmallPtrSet< OpaqueValueExpr *, 8 > Visited
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
CanQualType IntTy
uint64_t getTypeSize(QualType T) const
Return the size of the specified (complete) type T, in bits.
CharUnits getTypeSizeInChars(QualType T) const
Return the size of the specified (complete) type T, in characters.
CanQualType UnsignedIntTy
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:3732
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
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)
llvm::Value * handleScalarSemanticLoad(llvm::IRBuilder<> &B, llvm::Type *Type, const clang::DeclaratorDecl *Decl, SemanticInfo &ActiveSemantic)
llvm::Value * emitSystemSemanticLoad(llvm::IRBuilder<> &B, llvm::Type *Type, const clang::DeclaratorDecl *Decl, SemanticInfo &ActiveSemantic)
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)
llvm::Type * convertHLSLSpecificType(const Type *T, SmallVector< int32_t > *Packoffsets=nullptr)
llvm::Value * handleSemanticLoad(llvm::IRBuilder<> &B, llvm::Type *Type, const clang::DeclaratorDecl *Decl, SemanticInfo &ActiveSemantic)
std::optional< LValue > emitResourceArraySubscriptExpr(const ArraySubscriptExpr *E, CodeGenFunction &CGF)
void addRootSignature(const HLSLRootSignatureDecl *D)
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:2133
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:5897
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
DiagnosticsEngine & getDiags() 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.
const llvm::Triple & getTriple() 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, StringRef GlobalName=".str")
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:3758
int64_t getSExtSize() const
Return the size sign-extended as a uint64_t.
Definition TypeBase.h:3840
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
Represents a ValueDecl that came out of a declarator.
Definition Decl.h:779
DiagnosticBuilder Report(SourceLocation Loc, unsigned DiagID)
Issue the message to the client.
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
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
This class represents temporary values used to represent inout and out arguments in HLSL.
Definition Expr.h:7258
ArrayRef< llvm::hlsl::rootsig::RootElement > getRootElements() const
Definition Decl.h:5273
llvm::dxbc::RootSignatureVersion getVersion() const
Definition Decl.h:5271
unsigned getSemanticIndex() const
Definition Attr.h:260
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
Expr * getSourceExpr() const
The source expression of an opaque value expression is the expression which originally generated the ...
Definition Expr.h:1230
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:8285
LangAS getAddressSpace() const
Return the address space of this type.
Definition TypeBase.h:8411
The collection of all-type qualifiers we support.
Definition TypeBase.h:331
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)
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.
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:8629
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:8621
QualType getPointeeType() const
If this is a pointer, ObjC object pointer, or block pointer, this returns the respective pointee.
Definition Type.cpp:752
bool isHLSLResourceRecord() const
Definition Type.cpp:5370
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:5374
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
@ Type
The l-value was considered opaque, so the alignment was determined from a type.
Definition CGValue.h:154
@ Decl
The l-value was an access to a declared entity or something equivalently strong, like the address of ...
Definition CGValue.h:145
The JSON file list parser is used to communicate input to InstallAPI.
@ Ctor_Complete
Complete object ctor.
Definition ABI.h:25
bool isa(CodeGen::Address addr)
Definition Address.h:330
nullptr
This class represents a compute construct, representing a 'Kind' of β€˜parallel’, 'serial',...
@ SC_Static
Definition Specifiers.h:252
const FunctionProtoType * T
U cast(CodeGen::Address addr)
Definition Address.h:327
Diagnostic wrappers for TextAPI types for error reporting.
Definition Dominators.h:30