clang 23.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 "CGRecordLayout.h"
18#include "CodeGenFunction.h"
19#include "CodeGenModule.h"
21#include "TargetInfo.h"
23#include "clang/AST/Attr.h"
24#include "clang/AST/Decl.h"
25#include "clang/AST/Expr.h"
28#include "clang/AST/Type.h"
33#include "llvm/ADT/DenseMap.h"
34#include "llvm/ADT/STLExtras.h"
35#include "llvm/ADT/ScopeExit.h"
36#include "llvm/ADT/SmallString.h"
37#include "llvm/ADT/SmallVector.h"
38#include "llvm/Frontend/HLSL/RootSignatureMetadata.h"
39#include "llvm/IR/Constants.h"
40#include "llvm/IR/DerivedTypes.h"
41#include "llvm/IR/GlobalVariable.h"
42#include "llvm/IR/IntrinsicInst.h"
43#include "llvm/IR/LLVMContext.h"
44#include "llvm/IR/Metadata.h"
45#include "llvm/IR/Module.h"
46#include "llvm/IR/Type.h"
47#include "llvm/IR/Value.h"
48#include "llvm/Support/Alignment.h"
49#include "llvm/Support/ErrorHandling.h"
50#include "llvm/Support/FormatVariadic.h"
51#include "llvm/Support/Path.h"
52#include "llvm/Transforms/Utils/ModuleUtils.h"
53#include <cstdint>
54#include <optional>
55
56using namespace clang;
57using namespace CodeGen;
58using namespace clang::hlsl;
59using namespace llvm;
60
61using llvm::hlsl::CBufferRowSizeInBytes;
62
63namespace {
64
65void addDxilValVersion(StringRef ValVersionStr, llvm::Module &M) {
66 // The validation of ValVersionStr is done at HLSLToolChain::TranslateArgs.
67 // Assume ValVersionStr is legal here.
68 VersionTuple Version;
69 if (Version.tryParse(ValVersionStr) || Version.getBuild() ||
70 Version.getSubminor() || !Version.getMinor()) {
71 return;
72 }
73
74 uint64_t Major = Version.getMajor();
75 uint64_t Minor = *Version.getMinor();
76
77 auto &Ctx = M.getContext();
78 IRBuilder<> B(M.getContext());
79 MDNode *Val = MDNode::get(Ctx, {ConstantAsMetadata::get(B.getInt32(Major)),
80 ConstantAsMetadata::get(B.getInt32(Minor))});
81 StringRef DXILValKey = "dx.valver";
82 auto *DXILValMD = M.getOrInsertNamedMetadata(DXILValKey);
83 DXILValMD->addOperand(Val);
84}
85
86void addRootSignatureMD(llvm::dxbc::RootSignatureVersion RootSigVer,
88 llvm::Function *Fn, llvm::Module &M) {
89 auto &Ctx = M.getContext();
90
91 llvm::hlsl::rootsig::MetadataBuilder RSBuilder(Ctx, Elements);
92 MDNode *RootSignature = RSBuilder.BuildRootSignature();
93
94 ConstantAsMetadata *Version = ConstantAsMetadata::get(ConstantInt::get(
95 llvm::Type::getInt32Ty(Ctx), llvm::to_underlying(RootSigVer)));
96 ValueAsMetadata *EntryFunc = Fn ? ValueAsMetadata::get(Fn) : nullptr;
97 MDNode *MDVals = MDNode::get(Ctx, {EntryFunc, RootSignature, Version});
98
99 StringRef RootSignatureValKey = "dx.rootsignatures";
100 auto *RootSignatureValMD = M.getOrInsertNamedMetadata(RootSignatureValKey);
101 RootSignatureValMD->addOperand(MDVals);
102}
103
104static void copyGlobalResource(CodeGenFunction &CGF, const VarDecl *ResourceVD,
105 AggValueSlot &DestSlot) {
106 GlobalVariable *ResGV =
108 assert(ResGV && "expected valid global variable");
109 CGF.Builder.CreateStore(ResGV, DestSlot.getAddress());
110}
111
112// Given a MemberExpr of a resource or resource array type, find the parent
113// VarDecl of the struct or class instance that contains this resource and
114// build the full resource name based on the member access path.
115//
116// For example, for a member access like "myStructArray[0].memberA",
117// this function will find the VarDecl of "myStructArray" and use the
118// EmbeddedResourceNameBuilder to build the resource name
119// "myStructArray.0.memberA".
120//
121// This also works for a record type expression that has some embedded
122// resources. It finds the parent VarDecl of that record and builds a partial
123// name which is the prefix of the resource globals associated with the
124// declaration.
125static const VarDecl *findStructResourceParentDeclAndBuildName(
126 const Expr *E, EmbeddedResourceNameBuilder &NameBuilder) {
127
129 const VarDecl *VD = nullptr;
130
131 for (;;) {
132 if (const auto *DRE = dyn_cast<DeclRefExpr>(E)) {
133 assert(isa<VarDecl>(DRE->getDecl()) &&
134 "member expr base is not a var decl");
135 VD = cast<VarDecl>(DRE->getDecl());
136 NameBuilder.pushName(VD->getName());
137 break;
138 }
139
140 WorkList.push_back(E);
141 if (const auto *MExp = dyn_cast<MemberExpr>(E))
142 E = MExp->getBase();
143 else if (const auto *ICE = dyn_cast<ImplicitCastExpr>(E))
144 E = ICE->getSubExpr();
145 else if (const auto *ASE = dyn_cast<ArraySubscriptExpr>(E))
146 E = ASE->getBase();
147 else if (isa<CXXThisExpr>(E))
148 // Resource member access on "this" pointer not yet implemented
149 // (llvm/llvm-project#190299)
150 return nullptr;
151 else
152 llvm_unreachable("unexpected expr type in resource member access");
153
154 assert(E && "expected valid expression");
155 }
156
157 while (!WorkList.empty()) {
158 E = WorkList.pop_back_val();
159 if (const auto *ME = dyn_cast<MemberExpr>(E)) {
160 NameBuilder.pushName(
161 ME->getMemberNameInfo().getName().getAsIdentifierInfo()->getName());
162 } else if (const auto *ICE = dyn_cast<ImplicitCastExpr>(E)) {
163 if (ICE->getCastKind() == CK_UncheckedDerivedToBase) {
164 CXXRecordDecl *DerivedRD =
165 ICE->getSubExpr()->getType()->getAsCXXRecordDecl();
166 CXXRecordDecl *BaseRD = ICE->getType()->getAsCXXRecordDecl();
167 NameBuilder.pushBaseNameHierarchy(DerivedRD, BaseRD);
168 }
169 } else if (const auto *ASE = dyn_cast<ArraySubscriptExpr>(E)) {
170 const Expr *IdxExpr = ASE->getIdx();
171 std::optional<llvm::APSInt> Value =
173 assert(Value &&
174 "expected constant index in struct with resource array access");
175 NameBuilder.pushArrayIndex(Value->getZExtValue());
176 } else {
177 llvm_unreachable("unexpected expr type in resource member access");
178 }
179 }
180 return VD;
181}
182
183// Given a MemberExpr of a resource or resource array type, find the
184// corresponding global resource declaration associated with the owning struct
185// or class instance via HLSLAssociatedResourceDeclAttr.
186static const VarDecl *
187findAssociatedResourceDeclForStruct(ASTContext &AST, const MemberExpr *ME) {
188
189 EmbeddedResourceNameBuilder NameBuilder;
190 const VarDecl *ParentVD =
191 findStructResourceParentDeclAndBuildName(ME, NameBuilder);
192 if (!ParentVD)
193 return nullptr;
194
195 if (!ParentVD->hasGlobalStorage())
196 return nullptr;
197
198 IdentifierInfo *II = NameBuilder.getNameAsIdentifier(AST);
199 for (const Attr *A : ParentVD->getAttrs()) {
200 if (const auto *ADA = dyn_cast<HLSLAssociatedResourceDeclAttr>(A)) {
201 VarDecl *AssocResVD = ADA->getResDecl();
202 if (AssocResVD->getIdentifier() == II)
203 return AssocResVD;
204 }
205 }
206 return nullptr;
207}
208
209void addSourceInfo(CodeGenModule &CGM, llvm::Module &M) {
210 auto &SM = CGM.getContext().getSourceManager();
211 auto &Macros = CGM.getPreprocessorOpts().Macros;
212 auto &CodeGenOpts = CGM.getCodeGenOpts();
213 auto &Ctx = M.getContext();
214
215 // Names and content of shader source code files.
216 llvm::NamedMDNode *DXContents =
217 M.getOrInsertNamedMetadata("dx.source.contents");
218 auto addFile = [&](const std::pair<StringRef, StringRef> &NameContent) {
219 llvm::MDTuple *FileInfo =
220 llvm::MDNode::get(Ctx, {llvm::MDString::get(Ctx, NameContent.first),
221 llvm::MDString::get(Ctx, NameContent.second)});
222 DXContents->addOperand(FileInfo);
223 };
224
225 bool Invalid = false;
226 const SrcMgr::SLocEntry *MainLocEntry =
227 &SM.getSLocEntry(SM.getMainFileID(), &Invalid);
228 assert(!Invalid && "Main file SLocEntry must not be invalid!");
229 const SrcMgr::ContentCache &MainCCEntry =
230 MainLocEntry->getFile().getContentCache();
231
233 std::optional<SmallString<256>> MainFileName;
234 Files.reserve(SM.local_sloc_entry_size());
235 for (unsigned I : llvm::seq(SM.local_sloc_entry_size())) {
236 const SrcMgr::SLocEntry &LocEntry = SM.getLocalSLocEntry(I);
237 if (!LocEntry.isFile())
238 continue;
239
240 const SrcMgr::FileInfo &FInfo = LocEntry.getFile();
241 if (isSystem(FInfo.getFileCharacteristic()))
242 continue;
243
244 const SrcMgr::ContentCache &CCEntry = FInfo.getContentCache();
245 OptionalFileEntryRef FEntry = CCEntry.OrigEntry;
246 if (!FEntry)
247 continue;
248
249 llvm::SmallString<256> Path = FEntry->getName();
250 llvm::sys::path::native(Path);
251 std::optional<llvm::MemoryBufferRef> Buffer = CCEntry.getBufferOrNone(
252 SM.getDiagnostics(), SM.getFileManager(), SourceLocation());
253 if (!Buffer) {
254 SM.getDiagnostics().Report(diag::warn_hlsl_failed_to_embed_source)
255 << Path;
256 continue;
257 }
258
259 if (&MainCCEntry != &CCEntry) {
260 Files.emplace_back(Path, Buffer->getBuffer());
261 } else {
262 // Main file should be at first position.
263 addFile(std::make_pair(Path, Buffer->getBuffer()));
264 MainFileName.emplace(Path);
265 }
266 }
267 assert(MainFileName && "Main file not found.");
268
269 // Files other that main one should be sorted by name.
270 llvm::sort(Files);
271#ifndef NDEBUG
272 for (unsigned I = 1; I < Files.size(); ++I)
273 assert((Files[I - 1].first != Files[I].first) &&
274 "duplicate files in dx.source.contents");
275#endif
276 llvm::for_each(Files, addFile);
277
279 Defines.reserve(Macros.size());
280 for (const auto &Macro : Macros) {
281 // Ignore undefs.
282 if (!Macro.second)
283 Defines.emplace_back(llvm::MDString::get(Ctx, Macro.first));
284 }
285 M.getOrInsertNamedMetadata("dx.source.defines")
286 ->addOperand(llvm::MDNode::get(Ctx, Defines));
287
288 if (!CodeGenOpts.MainFileName.empty())
289 llvm::sys::path::native(CodeGenOpts.MainFileName, *MainFileName);
290 M.getOrInsertNamedMetadata("dx.source.mainFileName")
291 ->addOperand(
292 llvm::MDNode::get(Ctx, llvm::MDString::get(Ctx, *MainFileName)));
293
295 Args.reserve(CodeGenOpts.HLSLParsedCommandLine.size());
296 if (!CodeGenOpts.HLSLParsedCommandLine.empty())
297 for (const auto &Arg : llvm::drop_begin(CodeGenOpts.HLSLParsedCommandLine))
298 Args.push_back(llvm::MDString::get(Ctx, Arg));
299 M.getOrInsertNamedMetadata("dx.source.args")
300 ->addOperand(llvm::MDNode::get(Ctx, Args));
301}
302
303// Find array variable declaration from DeclRef expression
304static const ValueDecl *getArrayDecl(ASTContext &AST, const Expr *E) {
305 E = E->IgnoreImpCasts();
306 if (const auto *DRE = dyn_cast_or_null<DeclRefExpr>(E))
307 return DRE->getDecl();
308 if (auto *OVE = dyn_cast<OpaqueValueExpr>(E))
309 E = OVE->getSourceExpr()->IgnoreImpCasts();
310 if (isa<MemberExpr>(E))
311 return findAssociatedResourceDeclForStruct(AST, cast<MemberExpr>(E));
312 return nullptr;
313}
314
315// Find array variable declaration from nested array subscript AST nodes
316static const ValueDecl *getArrayDecl(ASTContext &AST,
317 const ArraySubscriptExpr *ASE) {
318 const Expr *E = nullptr;
319 while (ASE != nullptr) {
320 E = ASE->getBase()->IgnoreImpCasts();
321 if (!E)
322 return nullptr;
323 ASE = dyn_cast<ArraySubscriptExpr>(E);
324 }
325 return getArrayDecl(AST, E);
326}
327
328// Get the total size of the array, or 0 if the array is unbounded.
329static int getTotalArraySize(ASTContext &AST, const clang::Type *Ty) {
331 assert(Ty->isArrayType() && "expected array type");
332 if (Ty->isIncompleteArrayType())
333 return 0;
335}
336
337static Value *buildNameForResource(llvm::StringRef BaseName,
338 CodeGenModule &CGM) {
339 llvm::SmallString<64> GlobalName = {BaseName, ".str"};
340 return CGM.GetAddrOfConstantCString(BaseName.str(), GlobalName.c_str())
341 .getPointer();
342}
343
344static CXXMethodDecl *lookupMethod(CXXRecordDecl *Record, StringRef Name,
345 StorageClass SC = SC_None) {
346 for (auto *Method : Record->methods()) {
347 if (Method->getStorageClass() == SC && Method->getName() == Name)
348 return Method;
349 }
350 return nullptr;
351}
352
353static CXXMethodDecl *lookupResourceInitMethodAndSetupArgs(
354 CodeGenModule &CGM, CXXRecordDecl *ResourceDecl, llvm::Value *Range,
355 llvm::Value *Index, StringRef Name, ResourceBindingAttrs &Binding,
356 CallArgList &Args) {
357 assert(Binding.hasBinding() && "at least one binding attribute expected");
358
359 ASTContext &AST = CGM.getContext();
360 CXXMethodDecl *CreateMethod = nullptr;
361 Value *NameStr = buildNameForResource(Name, CGM);
362 Value *Space = llvm::ConstantInt::get(CGM.IntTy, Binding.getSpace());
363
364 bool HasCounter = hasCounterHandle(ResourceDecl);
365 assert((!HasCounter || Binding.hasCounterImplicitOrderID()) &&
366 "resources with counter handle must have a binding with counter "
367 "implicit order ID");
368 if (Binding.isExplicit()) {
369 // explicit binding
370 auto *RegSlot = llvm::ConstantInt::get(CGM.IntTy, Binding.getSlot());
371 Args.add(RValue::get(RegSlot), AST.UnsignedIntTy);
372 const char *Name = Binding.hasCounterImplicitOrderID()
373 ? "__createFromBindingWithImplicitCounter"
374 : "__createFromBinding";
375 CreateMethod = lookupMethod(ResourceDecl, Name, SC_Static);
376 } else {
377 // implicit binding
378 auto *OrderID =
379 llvm::ConstantInt::get(CGM.IntTy, Binding.getImplicitOrderID());
380 Args.add(RValue::get(OrderID), AST.UnsignedIntTy);
381 const char *Name = Binding.hasCounterImplicitOrderID()
382 ? "__createFromImplicitBindingWithImplicitCounter"
383 : "__createFromImplicitBinding";
384 CreateMethod = lookupMethod(ResourceDecl, Name, SC_Static);
385 }
386 Args.add(RValue::get(Space), AST.UnsignedIntTy);
387 Args.add(RValue::get(Range), AST.IntTy);
388 Args.add(RValue::get(Index), AST.UnsignedIntTy);
389 Args.add(RValue::get(NameStr), AST.getPointerType(AST.CharTy.withConst()));
390 if (HasCounter) {
391 uint32_t CounterBinding = Binding.getCounterImplicitOrderID();
392 auto *CounterOrderID = llvm::ConstantInt::get(CGM.IntTy, CounterBinding);
393 Args.add(RValue::get(CounterOrderID), AST.UnsignedIntTy);
394 }
395
396 return CreateMethod;
397}
398
399static void callResourceInitMethod(CodeGenFunction &CGF,
400 CXXMethodDecl *CreateMethod,
401 CallArgList &Args, Address ReturnAddress) {
402 llvm::Constant *CalleeFn = CGF.CGM.GetAddrOfFunction(CreateMethod);
403 const FunctionProtoType *Proto =
404 CreateMethod->getType()->getAs<FunctionProtoType>();
405 const CGFunctionInfo &FnInfo =
406 CGF.CGM.getTypes().arrangeFreeFunctionCall(Args, Proto, false);
407 ReturnValueSlot ReturnValue(ReturnAddress, false);
408 CGCallee Callee(CGCalleeInfo(Proto), CalleeFn);
409 CGF.EmitCall(FnInfo, Callee, ReturnValue, Args, nullptr);
410}
411
412// Initializes local resource array variable with global resource array
413// elements. For multi-dimensional arrays it calls itself recursively to
414// initialize its sub-arrays. The Index used in the resource constructor calls
415// will begin at StartIndex and will be incremented for each array element. The
416// last used resource Index is returned to the caller. If the function returns
417// std::nullopt, it indicates an error.
418static std::optional<llvm::Value *> initializeResourceArrayFromGlobal(
419 CodeGenFunction &CGF, CXXRecordDecl *ResourceDecl,
420 const ConstantArrayType *ArrayTy, AggValueSlot &ValueSlot,
421 llvm::Value *Range, llvm::Value *StartIndex, StringRef ResourceName,
422 ResourceBindingAttrs &Binding, ArrayRef<llvm::Value *> PrevGEPIndices) {
423
424 ASTContext &AST = CGF.getContext();
425 llvm::IntegerType *IntTy = CGF.CGM.IntTy;
426 llvm::Value *Index = StartIndex;
427 llvm::Value *One = llvm::ConstantInt::get(IntTy, 1);
428 const uint64_t ArraySize = ArrayTy->getSExtSize();
429 QualType ElemType = ArrayTy->getElementType();
430 Address TmpArrayAddr = ValueSlot.getAddress();
431
432 // Add additional index to the getelementptr call indices.
433 // This index will be updated for each array element in the loops below.
434 SmallVector<llvm::Value *> GEPIndices(PrevGEPIndices);
435 GEPIndices.push_back(llvm::ConstantInt::get(IntTy, 0));
436
437 // For array of arrays, recursively initialize the sub-arrays.
438 if (ElemType->isArrayType()) {
439 const ConstantArrayType *SubArrayTy = cast<ConstantArrayType>(ElemType);
440 for (uint64_t I = 0; I < ArraySize; I++) {
441 if (I > 0) {
442 Index = CGF.Builder.CreateAdd(Index, One);
443 GEPIndices.back() = llvm::ConstantInt::get(IntTy, I);
444 }
445 std::optional<llvm::Value *> MaybeIndex =
446 initializeResourceArrayFromGlobal(CGF, ResourceDecl, SubArrayTy,
447 ValueSlot, Range, Index,
448 ResourceName, Binding, GEPIndices);
449 if (!MaybeIndex)
450 return std::nullopt;
451 Index = *MaybeIndex;
452 }
453 return Index;
454 }
455
456 // For array of resources, initialize each resource in the array.
457 llvm::Type *Ty = CGF.ConvertTypeForMem(ElemType);
458 CharUnits ElemSize = AST.getTypeSizeInChars(ElemType);
459 CharUnits Align =
460 TmpArrayAddr.getAlignment().alignmentOfArrayElement(ElemSize);
461
462 for (uint64_t I = 0; I < ArraySize; I++) {
463 if (I > 0) {
464 Index = CGF.Builder.CreateAdd(Index, One);
465 GEPIndices.back() = llvm::ConstantInt::get(IntTy, I);
466 }
467 Address ReturnAddress =
468 CGF.Builder.CreateGEP(TmpArrayAddr, GEPIndices, Ty, Align);
469
470 CallArgList Args;
471 CXXMethodDecl *CreateMethod = lookupResourceInitMethodAndSetupArgs(
472 CGF.CGM, ResourceDecl, Range, Index, ResourceName, Binding, Args);
473
474 if (!CreateMethod)
475 // This can happen if someone creates an array of structs that looks like
476 // an HLSL resource record array but it does not have the required static
477 // create method. No binding will be generated for it.
478 return std::nullopt;
479
480 callResourceInitMethod(CGF, CreateMethod, Args, ReturnAddress);
481 }
482 return Index;
483}
484
485/// Utility for emitting copies following the HLSL buffer layout rules (ie,
486/// copying out of a cbuffer).
487class HLSLBufferCopyEmitter {
488 CodeGenFunction &CGF;
489 Address DstPtr;
490 Address SrcPtr;
491 llvm::Type *LayoutTy = nullptr;
492
493 SmallVector<llvm::Value *> CurStoreIndices;
494 SmallVector<llvm::Value *> CurLoadIndices;
495
496 using EmitResourceFnTy = llvm::function_ref<void(AggValueSlot &)>;
497
498 // Creates & returns either a structured.gep or a ptradd/gep depending on
499 // langopts.
500 llvm::Value *emitAccessChain(llvm::Type *BaseTy, llvm::Value *Base,
501 ArrayRef<llvm::Value *> Indices) {
502 bool EmitLogical = CGF.getLangOpts().EmitLogicalPointer;
503 if (EmitLogical)
504 return CGF.Builder.CreateAccessChain(EmitLogical, BaseTy, Base, Indices);
505
506 llvm::SmallVector<llvm::Value *> GEPIndices;
507 GEPIndices.reserve(Indices.size() + 1);
508 GEPIndices.push_back(llvm::ConstantInt::get(CGF.IntTy, 0));
509 GEPIndices.append(Indices.begin(), Indices.end());
510 return CGF.Builder.CreateAccessChain(EmitLogical, BaseTy, Base, GEPIndices);
511 }
512
513 bool isBufferLayoutArray(llvm::StructType *ST) {
514 // A buffer layout array is a struct with two elements: the padded array,
515 // and the last element. That is, is should look something like this:
516 //
517 // { [%n x { %type, %padding }], %type }
518 //
519 if (!ST || ST->getNumElements() != 2)
520 return false;
521
522 auto *PaddedEltsTy = dyn_cast<llvm::ArrayType>(ST->getElementType(0));
523 if (!PaddedEltsTy)
524 return false;
525
526 auto *PaddedTy = dyn_cast<llvm::StructType>(PaddedEltsTy->getElementType());
527 if (!PaddedTy || PaddedTy->getNumElements() != 2)
528 return false;
529
530 if (!CGF.CGM.getTargetCodeGenInfo().isHLSLPadding(
531 PaddedTy->getElementType(1)))
532 return false;
533
534 llvm::Type *ElementTy = ST->getElementType(1);
535 if (PaddedTy->getElementType(0) != ElementTy)
536 return false;
537 return true;
538 }
539
540 // Returns true if the type is either a struct representing a resource record,
541 // or an array of structs that are resource records. This assumes a struct is
542 // a resource record if the first element is a target type (resource handle).
543 // This is the case for all target types used by HLSL except the padding type
544 // ("{dx|spirv.Padding"), but padding will never be the first element of a
545 // struct.
546 bool isResourceOrResourceArray(llvm::Type *Ty) {
547 while (auto *AT = dyn_cast<llvm::ArrayType>(Ty))
548 Ty = AT->getElementType();
549
550 auto *ST = dyn_cast<llvm::StructType>(Ty);
551 if (!ST || ST->getNumElements() < 1)
552 return false;
553
554 auto *TargetTy = dyn_cast<llvm::TargetExtType>(ST->getElementType(0));
555 return TargetTy != nullptr;
556 }
557
558 void emitResourceOrResourceArray(Value *Dst, llvm::Type *DstTy,
559 EmitResourceFnTy EmitResFn) {
560 CharUnits DstAlign =
561 CharUnits::fromQuantity(CGF.CGM.getDataLayout().getABITypeAlign(DstTy));
562 Address DstAddr(Dst, DstTy, DstAlign);
563 AggValueSlot Slot = AggValueSlot::forAddr(
564 DstAddr, Qualifiers(), AggValueSlot::IsDestructed_t(true),
567
568 EmitResFn(Slot);
569 }
570
571 void emitBufferLayoutCopy(Value *Src, llvm::StructType *SrcTy, Value *Dst,
572 llvm::ArrayType *DstTy,
573 EmitResourceFnTy EmitResFn) {
574 // Those assumptions are checked by isBufferLayoutArray.
575 auto *SrcPaddedArrayTy = cast<llvm::ArrayType>(SrcTy->getElementType(0));
576 assert(SrcPaddedArrayTy->getNumElements() + 1 == DstTy->getNumElements());
577 assert(cast<llvm::StructType>(SrcPaddedArrayTy->getElementType())
578 ->getElementType(0) == SrcTy->getElementType(1));
579
580 auto *SrcDataTy = SrcTy->getElementType(1);
581 auto Zero = llvm::ConstantInt::get(CGF.IntTy, 0);
582
583 for (unsigned I = 0; I < SrcPaddedArrayTy->getNumElements(); ++I) {
584 auto Index = llvm::ConstantInt::get(CGF.IntTy, I);
585 auto *SrcElt = emitAccessChain(SrcTy, Src, {Zero, Index, Zero});
586 auto *DstElt = emitAccessChain(DstTy, Dst, {Index});
587 emitElementCopy(SrcElt, SrcDataTy, DstElt, DstTy->getElementType(),
588 EmitResFn);
589 }
590
591 auto *SrcElt =
592 emitAccessChain(SrcTy, Src, {llvm::ConstantInt::get(CGF.IntTy, 1)});
593 auto *DstElt = emitAccessChain(
594 DstTy, Dst,
595 {llvm::ConstantInt::get(CGF.IntTy, DstTy->getNumElements() - 1)});
596 emitElementCopy(SrcElt, SrcDataTy, DstElt, DstTy->getElementType(),
597 EmitResFn);
598 }
599
600 void emitCopy(Value *Src, llvm::StructType *SrcTy, Value *Dst,
601 llvm::Type *DstTy, EmitResourceFnTy EmitResFn) {
602 assert(!isResourceOrResourceArray(DstTy) &&
603 "direct access to resources or resource arrays should be handled "
604 "separately");
605
606 if (isBufferLayoutArray(SrcTy))
607 return emitBufferLayoutCopy(Src, SrcTy, Dst, cast<llvm::ArrayType>(DstTy),
608 EmitResFn);
609
610 unsigned SrcIndex = 0;
611 unsigned DstIndex = 0;
612
613 // DstTy layout is in default address space and can include resource types.
614 // SrcTy is in cbuffer layout where resources are filtered out, so the
615 // number of elements in SrcTy can be less than the number of elements in
616 // DstTy.
617 auto *DstST = cast<llvm::StructType>(DstTy);
618 while (DstIndex < DstST->getNumElements()) {
619 llvm::Type *DstEltTy = DstST->getElementType(DstIndex);
620 if (CGF.CGM.getTargetCodeGenInfo().isHLSLPadding(DstEltTy)) {
621 DstIndex += 1;
622 continue;
623 }
624 if (isResourceOrResourceArray(DstEltTy)) {
625 auto *DstElt = emitAccessChain(
626 DstTy, Dst, {llvm::ConstantInt::get(CGF.IntTy, DstIndex)});
627 emitResourceOrResourceArray(DstElt, DstEltTy, EmitResFn);
628 DstIndex += 1;
629 continue;
630 }
631
632 assert(SrcIndex < SrcTy->getNumElements());
633 llvm::Type *SrcEltTy = SrcTy->getElementType(SrcIndex);
634 if (CGF.CGM.getTargetCodeGenInfo().isHLSLPadding(SrcEltTy)) {
635 SrcIndex += 1;
636 continue;
637 }
638
639 auto *SrcElt = emitAccessChain(
640 SrcTy, Src, {llvm::ConstantInt::get(CGF.IntTy, SrcIndex)});
641 auto *DstElt = emitAccessChain(
642 DstTy, Dst, {llvm::ConstantInt::get(CGF.IntTy, DstIndex)});
643 emitElementCopy(SrcElt, SrcEltTy, DstElt, DstEltTy, EmitResFn);
644 DstIndex += 1;
645 SrcIndex += 1;
646 }
647 }
648
649 void emitCopy(Value *Src, llvm::ArrayType *SrcTy, Value *Dst,
650 llvm::Type *DstTy, EmitResourceFnTy EmitResFn) {
651 for (unsigned I = 0, E = SrcTy->getNumElements(); I < E; ++I) {
652 auto *SrcElt =
653 emitAccessChain(SrcTy, Src, {llvm::ConstantInt::get(CGF.IntTy, I)});
654 auto *DstElt =
655 emitAccessChain(DstTy, Dst, {llvm::ConstantInt::get(CGF.IntTy, I)});
656 emitElementCopy(SrcElt, SrcTy->getElementType(), DstElt,
657 cast<llvm::ArrayType>(DstTy)->getElementType(),
658 EmitResFn);
659 }
660 }
661
662 void emitElementCopy(Value *Src, llvm::Type *SrcTy, Value *Dst,
663 llvm::Type *DstTy, EmitResourceFnTy EmitResFn) {
664 if (auto *AT = dyn_cast<llvm::ArrayType>(SrcTy))
665 return emitCopy(Src, AT, Dst, DstTy, EmitResFn);
666 if (auto *ST = dyn_cast<llvm::StructType>(SrcTy))
667 return emitCopy(Src, ST, Dst, DstTy, EmitResFn);
668
669 // When we have a scalar or vector element we can emit the copy.
670 CharUnits SrcAlign =
671 CharUnits::fromQuantity(CGF.CGM.getDataLayout().getABITypeAlign(SrcTy));
672 CharUnits DstAlign =
673 CharUnits::fromQuantity(CGF.CGM.getDataLayout().getABITypeAlign(DstTy));
674 Address SrcAddr(Src, SrcTy, SrcAlign);
675 Address DstAddr(Dst, DstTy, DstAlign);
676 llvm::Value *Load = CGF.Builder.CreateLoad(SrcAddr, "cbuf.load");
677 CGF.Builder.CreateStore(Load, DstAddr);
678 }
679
680public:
681 HLSLBufferCopyEmitter(CodeGenFunction &CGF, Address DstPtr, Address SrcPtr)
682 : CGF(CGF), DstPtr(DstPtr), SrcPtr(SrcPtr) {}
683
684 bool emitCopy(QualType CType, EmitResourceFnTy EmitResFn = nullptr) {
685 LayoutTy = HLSLBufferLayoutBuilder(CGF.CGM).layOutType(CType);
686
687 // TODO: We should be able to fall back to a regular memcpy if the layout
688 // type doesn't have any padding, but that runs into issues in the backend
689 // currently.
690 //
691 // See https://github.com/llvm/wg-hlsl/issues/351
692 emitElementCopy(SrcPtr.getBasePointer(), LayoutTy, DstPtr.getBasePointer(),
693 DstPtr.getElementType(), EmitResFn);
694 return true;
695 }
696};
697
698// Represents a list resources associated with a global struct whose name
699// starts with the specified prefix.
700// The order of HLSLAssociatedResourceDeclAttr attributes is identical to the
701// order of the depth-first traversal of the corresponding fields in the struct.
702// The resources are always returned in that order, which is the same order
703// we need when a struct is copied element-by-element.
704class AssociatedResourcesList {
705 // Iterator pointers for the associated resource attributes that match the
706 // prefix. Begin = begin of the range of attributes that match the prefix End
707 // = end of the range of attributes that match the prefix Next = the current
708 // attribute in the iteration to be returned by getNextResource
709 specific_attr_iterator<HLSLAssociatedResourceDeclAttr> Begin, End, Next;
710
711public:
712 AssociatedResourcesList(const VarDecl *StructVD,
713 StringRef ResourceNamePrefix) {
714 auto I = StructVD->specific_attr_begin<HLSLAssociatedResourceDeclAttr>();
715 auto E = StructVD->specific_attr_end<HLSLAssociatedResourceDeclAttr>();
716
717 // Skip over associated resources that don't match the prefix.
718 while (I != E &&
719 !I->getResDecl()->getName().starts_with(ResourceNamePrefix))
720 ++I;
721 assert(I != E && "expected associated resource not found");
722 Begin = End = I;
723
724 // Scan over associated resources that do match the prefix to find the end
725 // of the range.
726 while (I != E && ((HLSLAssociatedResourceDeclAttr *)*I)
727 ->getResDecl()
728 ->getName()
729 .starts_with(ResourceNamePrefix))
730 End = ++I;
731
732 Next = Begin;
733 }
734
735 const VarDecl *getNextResource() {
736 if (Next == End)
737 return nullptr;
738
739 const VarDecl *Res = Next->getResDecl();
740 ++Next;
741 return Res;
742 }
743};
744
745} // namespace
746
747llvm::Type *
749 const CGHLSLOffsetInfo &OffsetInfo) {
750 assert(T->isHLSLSpecificType() && "Not an HLSL specific type!");
751
752 // Check if the target has a specific translation for this type first.
753 if (llvm::Type *TargetTy =
754 CGM.getTargetCodeGenInfo().getHLSLType(CGM, T, OffsetInfo))
755 return TargetTy;
756
757 llvm_unreachable("Generic handling of HLSL types is not supported.");
758}
759
760llvm::Triple::ArchType CGHLSLRuntime::getArch() {
761 return CGM.getTarget().getTriple().getArch();
762}
763
764// Emits constant global variables for buffer constants declarations
765// and creates metadata linking the constant globals with the buffer global.
766void CGHLSLRuntime::emitBufferGlobalsAndMetadata(
767 const HLSLBufferDecl *BufDecl, llvm::GlobalVariable *BufGV,
768 const CGHLSLOffsetInfo &OffsetInfo) {
769 LLVMContext &Ctx = CGM.getLLVMContext();
770
771 // get the layout struct from constant buffer target type
772 llvm::Type *BufType = BufGV->getValueType();
773 llvm::StructType *LayoutStruct = cast<llvm::StructType>(
774 cast<llvm::TargetExtType>(BufType)->getTypeParameter(0));
775
777 size_t OffsetIdx = 0;
778 for (Decl *D : BufDecl->buffer_decls()) {
780 // Nothing to do for this declaration.
781 continue;
782 if (isa<FunctionDecl>(D)) {
783 // A function within an cbuffer is effectively a top-level function.
784 CGM.EmitTopLevelDecl(D);
785 continue;
786 }
787 VarDecl *VD = dyn_cast<VarDecl>(D);
788 if (!VD)
789 continue;
790
791 QualType VDTy = VD->getType();
793 if (VD->getStorageClass() == SC_Static ||
796 // Emit static and groupshared variables and resource classes inside
797 // cbuffer as regular globals
798 CGM.EmitGlobal(VD);
799 }
800 continue;
801 }
802
803 DeclsWithOffset.emplace_back(VD, OffsetInfo[OffsetIdx++]);
804 }
805
806 if (!OffsetInfo.empty())
807 llvm::stable_sort(DeclsWithOffset, [](const auto &LHS, const auto &RHS) {
808 return CGHLSLOffsetInfo::compareOffsets(LHS.second, RHS.second);
809 });
810
811 // Associate the buffer global variable with its constants
812 SmallVector<llvm::Metadata *> BufGlobals;
813 BufGlobals.reserve(DeclsWithOffset.size() + 1);
814 BufGlobals.push_back(ValueAsMetadata::get(BufGV));
815
816 auto ElemIt = LayoutStruct->element_begin();
817 for (auto &[VD, _] : DeclsWithOffset) {
818 if (CGM.getTargetCodeGenInfo().isHLSLPadding(*ElemIt))
819 ++ElemIt;
820
821 assert(ElemIt != LayoutStruct->element_end() &&
822 "number of elements in layout struct does not match");
823 llvm::Type *LayoutType = *ElemIt++;
824
825 GlobalVariable *ElemGV =
826 cast<GlobalVariable>(CGM.GetAddrOfGlobalVar(VD, LayoutType));
827 BufGlobals.push_back(ValueAsMetadata::get(ElemGV));
828 }
829 assert(ElemIt == LayoutStruct->element_end() &&
830 "number of elements in layout struct does not match");
831
832 // add buffer metadata to the module
833 CGM.getModule()
834 .getOrInsertNamedMetadata("hlsl.cbs")
835 ->addOperand(MDNode::get(Ctx, BufGlobals));
836}
837
838// Creates resource handle type for the HLSL buffer declaration
839static const clang::HLSLAttributedResourceType *
841 ASTContext &AST = BufDecl->getASTContext();
843 AST.HLSLResourceTy, AST.getCanonicalTagType(BufDecl->getLayoutStruct()),
844 HLSLAttributedResourceType::Attributes(ResourceClass::CBuffer));
846}
847
850
851 // If we don't have packoffset info, just return an empty result.
852 if (!BufDecl.hasValidPackoffset())
853 return Result;
854
855 for (Decl *D : BufDecl.buffer_decls()) {
857 continue;
858 }
859 VarDecl *VD = dyn_cast<VarDecl>(D);
860 if (!VD || VD->getType().getAddressSpace() != LangAS::hlsl_constant)
861 continue;
862
863 if (!VD->hasAttrs()) {
864 Result.Offsets.push_back(Unspecified);
865 continue;
866 }
867
868 uint32_t Offset = Unspecified;
869 for (auto *Attr : VD->getAttrs()) {
870 if (auto *POA = dyn_cast<HLSLPackOffsetAttr>(Attr)) {
871 Offset = POA->getOffsetInBytes();
872 break;
873 }
874 auto *RBA = dyn_cast<HLSLResourceBindingAttr>(Attr);
875 if (RBA &&
876 RBA->getRegisterType() == HLSLResourceBindingAttr::RegisterType::C) {
877 Offset = RBA->getSlotNumber() * CBufferRowSizeInBytes;
878 break;
879 }
880 }
881 Result.Offsets.push_back(Offset);
882 }
883 return Result;
884}
885
886// Codegen for HLSLBufferDecl
888
889 assert(BufDecl->isCBuffer() && "tbuffer codegen is not supported yet");
890
891 // create resource handle type for the buffer
892 const clang::HLSLAttributedResourceType *ResHandleTy =
893 createBufferHandleType(BufDecl);
894
895 // empty constant buffer is ignored
896 if (ResHandleTy->getContainedType()->getAsCXXRecordDecl()->isEmpty())
897 return;
898
899 // create global variable for the constant buffer
900 CGHLSLOffsetInfo OffsetInfo = CGHLSLOffsetInfo::fromDecl(*BufDecl);
901 llvm::Type *LayoutTy = convertHLSLSpecificType(ResHandleTy, OffsetInfo);
902 llvm::GlobalVariable *BufGV = new GlobalVariable(
903 LayoutTy, /*isConstant*/ false,
904 GlobalValue::LinkageTypes::InternalLinkage, PoisonValue::get(LayoutTy),
905 llvm::formatv("{0}{1}", BufDecl->getName(),
906 BufDecl->isCBuffer() ? ".cb" : ".tb"),
907 GlobalValue::NotThreadLocal);
908
909 llvm::Module &M = CGM.getModule();
910 M.insertGlobalVariable(BufGV);
911
912 // Add the global variable to the compiler used list so it does not
913 // get optimized away by GlobalOptPass before it reaches
914 // {DXIL|SPIRV}CBufferAccess pass.
915 llvm::appendToCompilerUsed(M, {BufGV});
916
917 // Add globals for constant buffer elements and create metadata nodes
918 emitBufferGlobalsAndMetadata(BufDecl, BufGV, OffsetInfo);
919
920 // Initialize cbuffer from binding (implicit or explicit)
921 initializeBufferFromBinding(BufDecl, BufGV);
922}
923
925 const HLSLRootSignatureDecl *SignatureDecl) {
926 llvm::Module &M = CGM.getModule();
927 Triple T(M.getTargetTriple());
928
929 // Generated later with the function decl if not targeting root signature
930 if (T.getEnvironment() != Triple::EnvironmentType::RootSignature)
931 return;
932
933 addRootSignatureMD(SignatureDecl->getVersion(),
934 SignatureDecl->getRootElements(), nullptr, M);
935}
936
937llvm::StructType *
938CGHLSLRuntime::getHLSLBufferLayoutType(const RecordType *StructType) {
939 const auto Entry = LayoutTypes.find(StructType);
940 if (Entry != LayoutTypes.end())
941 return Entry->getSecond();
942 return nullptr;
943}
944
945void CGHLSLRuntime::addHLSLBufferLayoutType(const RecordType *StructType,
946 llvm::StructType *LayoutTy) {
947 assert(getHLSLBufferLayoutType(StructType) == nullptr &&
948 "layout type for this struct already exist");
949 LayoutTypes[StructType] = LayoutTy;
950}
951
953 auto &TargetOpts = CGM.getTarget().getTargetOpts();
954 auto &CodeGenOpts = CGM.getCodeGenOpts();
955 auto &LangOpts = CGM.getLangOpts();
956 llvm::Module &M = CGM.getModule();
957 Triple T(M.getTargetTriple());
958 if (T.getArch() == Triple::ArchType::dxil)
959 addDxilValVersion(TargetOpts.DxilValidatorVersion, M);
960 if (!CodeGenOpts.DisableDXSourceMetadata &&
961 CodeGenOpts.getDebugInfo() >=
962 llvm::codegenoptions::DebugInfoKind::DebugInfoConstructor)
963 addSourceInfo(CGM, M);
964 if (CodeGenOpts.ResMayAlias)
965 M.setModuleFlag(llvm::Module::ModFlagBehavior::Error, "dx.resmayalias", 1);
966 if (CodeGenOpts.AllResourcesBound)
967 M.setModuleFlag(llvm::Module::ModFlagBehavior::Error,
968 "dx.allresourcesbound", 1);
969 if (CodeGenOpts.OptimizationLevel == 0)
970 M.addModuleFlag(llvm::Module::ModFlagBehavior::Override,
971 "dx.disable_optimizations", 1);
972
973 // NativeHalfType corresponds to the -fnative-half-type clang option which is
974 // aliased by clang-dxc's -enable-16bit-types option. This option is used to
975 // set the UseNativeLowPrecision DXIL module flag in the DirectX backend
976 if (LangOpts.NativeHalfType)
977 M.setModuleFlag(llvm::Module::ModFlagBehavior::Error, "dx.nativelowprec",
978 1);
979
980 if (LangOpts.HLSLSpvPreserveInterface && T.isSPIRV()) {
981 // Runs before optimization. Keeps Input/Output globals from GlobalDCE.
982 const ASTContext &Ctx = CGM.getContext();
983 unsigned InputAS = Ctx.getTargetAddressSpace(LangAS::hlsl_input);
984 unsigned OutputAS = Ctx.getTargetAddressSpace(LangAS::hlsl_output);
985 SmallVector<GlobalValue *, 8> InterfaceVars;
986 for (GlobalVariable &GV : M.globals()) {
987 unsigned AS = GV.getAddressSpace();
988 if (AS == InputAS || AS == OutputAS)
989 InterfaceVars.push_back(&GV);
990 }
991 if (!InterfaceVars.empty())
992 appendToCompilerUsed(M, InterfaceVars);
993 }
994
996}
997
999 const FunctionDecl *FD, llvm::Function *Fn) {
1000 const auto *ShaderAttr = FD->getAttr<HLSLShaderAttr>();
1001 assert(ShaderAttr && "All entry functions must have a HLSLShaderAttr");
1002 const StringRef ShaderAttrKindStr = "hlsl.shader";
1003 Fn->addFnAttr(ShaderAttrKindStr,
1004 llvm::Triple::getEnvironmentTypeName(ShaderAttr->getType()));
1005 if (HLSLNumThreadsAttr *NumThreadsAttr = FD->getAttr<HLSLNumThreadsAttr>()) {
1006 const StringRef NumThreadsKindStr = "hlsl.numthreads";
1007 std::string NumThreadsStr =
1008 formatv("{0},{1},{2}", NumThreadsAttr->getX(), NumThreadsAttr->getY(),
1009 NumThreadsAttr->getZ());
1010 Fn->addFnAttr(NumThreadsKindStr, NumThreadsStr);
1011 }
1012 if (HLSLWaveSizeAttr *WaveSizeAttr = FD->getAttr<HLSLWaveSizeAttr>()) {
1013 const StringRef WaveSizeKindStr = "hlsl.wavesize";
1014 std::string WaveSizeStr =
1015 formatv("{0},{1},{2}", WaveSizeAttr->getMin(), WaveSizeAttr->getMax(),
1016 WaveSizeAttr->getPreferred());
1017 Fn->addFnAttr(WaveSizeKindStr, WaveSizeStr);
1018 }
1019 // HLSL entry functions are materialized for module functions with
1020 // HLSLShaderAttr attribute. SetLLVMFunctionAttributesForDefinition called
1021 // later in the compiler-flow for such module functions is not aware of and
1022 // hence not able to set attributes of the newly materialized entry functions.
1023 // So, set attributes of entry function here, as appropriate.
1024 Fn->addFnAttr(llvm::Attribute::NoInline);
1025
1026 if (CGM.getLangOpts().HLSLSpvEnableMaximalReconvergence) {
1027 Fn->addFnAttr("enable-maximal-reconvergence", "true");
1028 }
1029}
1030
1031static Value *buildVectorInput(IRBuilder<> &B, Function *F, llvm::Type *Ty) {
1032 if (const auto *VT = dyn_cast<FixedVectorType>(Ty)) {
1033 Value *Result = PoisonValue::get(Ty);
1034 for (unsigned I = 0; I < VT->getNumElements(); ++I) {
1035 Value *Elt = B.CreateCall(F, {B.getInt32(I)});
1036 Result = B.CreateInsertElement(Result, Elt, I);
1037 }
1038 return Result;
1039 }
1040 return B.CreateCall(F, {B.getInt32(0)});
1041}
1042
1043static void addSPIRVBuiltinDecoration(llvm::GlobalVariable *GV,
1044 unsigned BuiltIn) {
1045 LLVMContext &Ctx = GV->getContext();
1046 IRBuilder<> B(GV->getContext());
1047 MDNode *Operands = MDNode::get(
1048 Ctx,
1049 {ConstantAsMetadata::get(B.getInt32(/* Spirv::Decoration::BuiltIn */ 11)),
1050 ConstantAsMetadata::get(B.getInt32(BuiltIn))});
1051 MDNode *Decoration = MDNode::get(Ctx, {Operands});
1052 GV->addMetadata("spirv.Decorations", *Decoration);
1053}
1054
1055static void addLocationDecoration(llvm::GlobalVariable *GV, unsigned Location) {
1056 LLVMContext &Ctx = GV->getContext();
1057 IRBuilder<> B(GV->getContext());
1058 MDNode *Operands =
1059 MDNode::get(Ctx, {ConstantAsMetadata::get(B.getInt32(/* Location */ 30)),
1060 ConstantAsMetadata::get(B.getInt32(Location))});
1061 MDNode *Decoration = MDNode::get(Ctx, {Operands});
1062 GV->addMetadata("spirv.Decorations", *Decoration);
1063}
1064
1065static llvm::Value *createSPIRVBuiltinLoad(IRBuilder<> &B, llvm::Module &M,
1066 llvm::Type *Ty, const Twine &Name,
1067 unsigned BuiltInID) {
1068 auto *GV = new llvm::GlobalVariable(
1069 M, Ty, /* isConstant= */ true, llvm::GlobalValue::ExternalLinkage,
1070 /* Initializer= */ nullptr, Name, /* insertBefore= */ nullptr,
1071 llvm::GlobalVariable::GeneralDynamicTLSModel,
1072 /* AddressSpace */ 7, /* isExternallyInitialized= */ true);
1073 addSPIRVBuiltinDecoration(GV, BuiltInID);
1074 GV->setVisibility(llvm::GlobalValue::HiddenVisibility);
1075 return B.CreateLoad(Ty, GV);
1076}
1077
1078static llvm::Value *createSPIRVLocationLoad(IRBuilder<> &B, llvm::Module &M,
1079 llvm::Type *Ty, unsigned Location,
1080 StringRef Name) {
1081 auto *GV = new llvm::GlobalVariable(
1082 M, Ty, /* isConstant= */ true, llvm::GlobalValue::ExternalLinkage,
1083 /* Initializer= */ nullptr, /* Name= */ Name, /* insertBefore= */ nullptr,
1084 llvm::GlobalVariable::GeneralDynamicTLSModel,
1085 /* AddressSpace */ 7, /* isExternallyInitialized= */ true);
1086 GV->setVisibility(llvm::GlobalValue::HiddenVisibility);
1087 addLocationDecoration(GV, Location);
1088 return B.CreateLoad(Ty, GV);
1089}
1090
1091llvm::Value *CGHLSLRuntime::emitSPIRVUserSemanticLoad(
1092 llvm::IRBuilder<> &B, llvm::Type *Type, const clang::DeclaratorDecl *Decl,
1093 HLSLAppliedSemanticAttr *Semantic, std::optional<unsigned> Index) {
1094 Twine BaseName = Twine(Semantic->getAttrName()->getName());
1095 Twine VariableName = BaseName.concat(Twine(Index.value_or(0)));
1096
1097 unsigned Location = SPIRVLastAssignedInputSemanticLocation;
1098 if (auto *L = Decl->getAttr<HLSLVkLocationAttr>())
1099 Location = L->getLocation();
1100
1101 // DXC completely ignores the semantic/index pair. Location are assigned from
1102 // the first semantic to the last.
1103 llvm::ArrayType *AT = dyn_cast<llvm::ArrayType>(Type);
1104 unsigned ElementCount = AT ? AT->getNumElements() : 1;
1105 SPIRVLastAssignedInputSemanticLocation += ElementCount;
1106
1107 return createSPIRVLocationLoad(B, CGM.getModule(), Type, Location,
1108 VariableName.str());
1109}
1110
1111static void createSPIRVLocationStore(IRBuilder<> &B, llvm::Module &M,
1112 llvm::Value *Source, unsigned Location,
1113 StringRef Name) {
1114 auto *GV = new llvm::GlobalVariable(
1115 M, Source->getType(), /* isConstant= */ false,
1116 llvm::GlobalValue::ExternalLinkage,
1117 /* Initializer= */ nullptr, /* Name= */ Name, /* insertBefore= */ nullptr,
1118 llvm::GlobalVariable::GeneralDynamicTLSModel,
1119 /* AddressSpace */ 8, /* isExternallyInitialized= */ false);
1120 GV->setVisibility(llvm::GlobalValue::HiddenVisibility);
1121 addLocationDecoration(GV, Location);
1122 B.CreateStore(Source, GV);
1123}
1124
1125void CGHLSLRuntime::emitSPIRVUserSemanticStore(
1126 llvm::IRBuilder<> &B, llvm::Value *Source,
1127 const clang::DeclaratorDecl *Decl, HLSLAppliedSemanticAttr *Semantic,
1128 std::optional<unsigned> Index) {
1129 Twine BaseName = Twine(Semantic->getAttrName()->getName());
1130 Twine VariableName = BaseName.concat(Twine(Index.value_or(0)));
1131
1132 unsigned Location = SPIRVLastAssignedOutputSemanticLocation;
1133 if (auto *L = Decl->getAttr<HLSLVkLocationAttr>())
1134 Location = L->getLocation();
1135
1136 // DXC completely ignores the semantic/index pair. Location are assigned from
1137 // the first semantic to the last.
1138 llvm::ArrayType *AT = dyn_cast<llvm::ArrayType>(Source->getType());
1139 unsigned ElementCount = AT ? AT->getNumElements() : 1;
1140 SPIRVLastAssignedOutputSemanticLocation += ElementCount;
1141 createSPIRVLocationStore(B, CGM.getModule(), Source, Location,
1142 VariableName.str());
1143}
1144
1145llvm::Value *
1146CGHLSLRuntime::emitDXILUserSemanticLoad(llvm::IRBuilder<> &B, llvm::Type *Type,
1147 HLSLAppliedSemanticAttr *Semantic,
1148 std::optional<unsigned> Index) {
1149 Twine BaseName = Twine(Semantic->getAttrName()->getName());
1150 Twine VariableName = BaseName.concat(Twine(Index.value_or(0)));
1151
1152 // DXIL packing rules etc shall be handled here.
1153 // FIXME: generate proper sigpoint, index, col, row values.
1154 // FIXME: also DXIL loads vectors element by element.
1155 SmallVector<Value *> Args{B.getInt32(4), B.getInt32(0), B.getInt32(0),
1156 B.getInt8(0),
1157 llvm::PoisonValue::get(B.getInt32Ty())};
1158
1159 llvm::Intrinsic::ID IntrinsicID = llvm::Intrinsic::dx_load_input;
1160
1161 SmallVector<OperandBundleDef, 1> OB;
1162 if (auto *Token = getConvergenceToken(*B.GetInsertBlock())) {
1163 llvm::Value *bundleArgs[] = {Token};
1164 OB.emplace_back("convergencectrl", bundleArgs);
1165 }
1166
1167 llvm::Function *IntrFn = llvm::Intrinsic::getOrInsertDeclaration(
1168 B.GetInsertBlock()->getModule(), IntrinsicID, {Type});
1169 llvm::Value *Value = B.CreateCall(IntrFn, Args, OB, VariableName);
1170 return Value;
1171}
1172
1173void CGHLSLRuntime::emitDXILUserSemanticStore(llvm::IRBuilder<> &B,
1174 llvm::Value *Source,
1175 HLSLAppliedSemanticAttr *Semantic,
1176 std::optional<unsigned> Index) {
1177 // DXIL packing rules etc shall be handled here.
1178 // FIXME: generate proper sigpoint, index, col, row values.
1179 SmallVector<Value *> Args{B.getInt32(4),
1180 B.getInt32(0),
1181 B.getInt32(0),
1182 B.getInt8(0),
1183 llvm::PoisonValue::get(B.getInt32Ty()),
1184 Source};
1185
1186 llvm::Intrinsic::ID IntrinsicID = llvm::Intrinsic::dx_store_output;
1187
1188 SmallVector<OperandBundleDef, 1> OB;
1189 if (auto *Token = getConvergenceToken(*B.GetInsertBlock())) {
1190 llvm::Value *bundleArgs[] = {Token};
1191 OB.emplace_back("convergencectrl", bundleArgs);
1192 }
1193
1194 llvm::Function *IntrFn = llvm::Intrinsic::getOrInsertDeclaration(
1195 B.GetInsertBlock()->getModule(), IntrinsicID, {Source->getType()});
1196 B.CreateCall(IntrFn, Args, OB);
1197}
1198
1199llvm::Value *CGHLSLRuntime::emitUserSemanticLoad(
1200 IRBuilder<> &B, llvm::Type *Type, const clang::DeclaratorDecl *Decl,
1201 HLSLAppliedSemanticAttr *Semantic, std::optional<unsigned> Index) {
1202 if (CGM.getTarget().getTriple().isSPIRV())
1203 return emitSPIRVUserSemanticLoad(B, Type, Decl, Semantic, Index);
1204
1205 if (CGM.getTarget().getTriple().isDXIL())
1206 return emitDXILUserSemanticLoad(B, Type, Semantic, Index);
1207
1208 llvm_unreachable("Unsupported target for user-semantic load.");
1209}
1210
1211void CGHLSLRuntime::emitUserSemanticStore(IRBuilder<> &B, llvm::Value *Source,
1212 const clang::DeclaratorDecl *Decl,
1213 HLSLAppliedSemanticAttr *Semantic,
1214 std::optional<unsigned> Index) {
1215 if (CGM.getTarget().getTriple().isSPIRV())
1216 return emitSPIRVUserSemanticStore(B, Source, Decl, Semantic, Index);
1217
1218 if (CGM.getTarget().getTriple().isDXIL())
1219 return emitDXILUserSemanticStore(B, Source, Semantic, Index);
1220
1221 llvm_unreachable("Unsupported target for user-semantic load.");
1222}
1223
1225 IRBuilder<> &B, const FunctionDecl *FD, llvm::Type *Type,
1226 const clang::DeclaratorDecl *Decl, HLSLAppliedSemanticAttr *Semantic,
1227 std::optional<unsigned> Index) {
1228
1229 std::string SemanticName = Semantic->getAttrName()->getName().upper();
1230 if (SemanticName == "SV_GROUPINDEX") {
1231 llvm::Function *GroupIndex =
1232 CGM.getIntrinsic(getFlattenedThreadIdInGroupIntrinsic());
1233 return B.CreateCall(FunctionCallee(GroupIndex));
1234 }
1235
1236 if (SemanticName == "SV_DISPATCHTHREADID") {
1237 llvm::Intrinsic::ID IntrinID = getThreadIdIntrinsic();
1238 llvm::Function *ThreadIDIntrinsic =
1239 llvm::Intrinsic::isOverloaded(IntrinID)
1240 ? CGM.getIntrinsic(IntrinID, {CGM.Int32Ty})
1241 : CGM.getIntrinsic(IntrinID);
1242 return buildVectorInput(B, ThreadIDIntrinsic, Type);
1243 }
1244
1245 if (SemanticName == "SV_GROUPTHREADID") {
1246 llvm::Intrinsic::ID IntrinID = getGroupThreadIdIntrinsic();
1247 llvm::Function *GroupThreadIDIntrinsic =
1248 llvm::Intrinsic::isOverloaded(IntrinID)
1249 ? CGM.getIntrinsic(IntrinID, {CGM.Int32Ty})
1250 : CGM.getIntrinsic(IntrinID);
1251 return buildVectorInput(B, GroupThreadIDIntrinsic, Type);
1252 }
1253
1254 if (SemanticName == "SV_GROUPID") {
1255 llvm::Intrinsic::ID IntrinID = getGroupIdIntrinsic();
1256 llvm::Function *GroupIDIntrinsic =
1257 llvm::Intrinsic::isOverloaded(IntrinID)
1258 ? CGM.getIntrinsic(IntrinID, {CGM.Int32Ty})
1259 : CGM.getIntrinsic(IntrinID);
1260 return buildVectorInput(B, GroupIDIntrinsic, Type);
1261 }
1262
1263 const auto *ShaderAttr = FD->getAttr<HLSLShaderAttr>();
1264 assert(ShaderAttr && "Entry point has no shader attribute");
1265 llvm::Triple::EnvironmentType ST = ShaderAttr->getType();
1266
1267 if (SemanticName == "SV_POSITION") {
1268 if (ST == Triple::EnvironmentType::Pixel) {
1269 if (CGM.getTarget().getTriple().isSPIRV())
1270 return createSPIRVBuiltinLoad(B, CGM.getModule(), Type,
1271 Semantic->getAttrName()->getName(),
1272 /* BuiltIn::FragCoord */ 15);
1273 if (CGM.getTarget().getTriple().isDXIL())
1274 return emitDXILUserSemanticLoad(B, Type, Semantic, Index);
1275 }
1276
1277 if (ST == Triple::EnvironmentType::Vertex) {
1278 return emitUserSemanticLoad(B, Type, Decl, Semantic, Index);
1279 }
1280 }
1281
1282 if (SemanticName == "SV_VERTEXID") {
1283 if (ST == Triple::EnvironmentType::Vertex) {
1284 if (CGM.getTarget().getTriple().isSPIRV())
1285 return createSPIRVBuiltinLoad(B, CGM.getModule(), Type,
1286 Semantic->getAttrName()->getName(),
1287 /* BuiltIn::VertexIndex */ 42);
1288 else
1289 return emitDXILUserSemanticLoad(B, Type, Semantic, Index);
1290 }
1291 }
1292
1293 llvm_unreachable(
1294 "Load hasn't been implemented yet for this system semantic. FIXME");
1295}
1296
1297static void createSPIRVBuiltinStore(IRBuilder<> &B, llvm::Module &M,
1298 llvm::Value *Source, const Twine &Name,
1299 unsigned BuiltInID) {
1300 auto *GV = new llvm::GlobalVariable(
1301 M, Source->getType(), /* isConstant= */ false,
1302 llvm::GlobalValue::ExternalLinkage,
1303 /* Initializer= */ nullptr, Name, /* insertBefore= */ nullptr,
1304 llvm::GlobalVariable::GeneralDynamicTLSModel,
1305 /* AddressSpace */ 8, /* isExternallyInitialized= */ false);
1306 addSPIRVBuiltinDecoration(GV, BuiltInID);
1307 GV->setVisibility(llvm::GlobalValue::HiddenVisibility);
1308 B.CreateStore(Source, GV);
1309}
1310
1311void CGHLSLRuntime::emitSystemSemanticStore(IRBuilder<> &B, llvm::Value *Source,
1313 HLSLAppliedSemanticAttr *Semantic,
1314 std::optional<unsigned> Index) {
1315
1316 std::string SemanticName = Semantic->getAttrName()->getName().upper();
1317 if (SemanticName == "SV_POSITION") {
1318 if (CGM.getTarget().getTriple().isDXIL()) {
1319 emitDXILUserSemanticStore(B, Source, Semantic, Index);
1320 return;
1321 }
1322
1323 if (CGM.getTarget().getTriple().isSPIRV()) {
1324 createSPIRVBuiltinStore(B, CGM.getModule(), Source,
1325 Semantic->getAttrName()->getName(),
1326 /* BuiltIn::Position */ 0);
1327 return;
1328 }
1329 }
1330
1331 if (SemanticName == "SV_TARGET") {
1332 emitUserSemanticStore(B, Source, Decl, Semantic, Index);
1333 return;
1334 }
1335
1336 llvm_unreachable(
1337 "Store hasn't been implemented yet for this system semantic. FIXME");
1338}
1339
1341 IRBuilder<> &B, const FunctionDecl *FD, llvm::Type *Type,
1342 const clang::DeclaratorDecl *Decl, HLSLAppliedSemanticAttr *Semantic) {
1343
1344 std::optional<unsigned> Index = Semantic->getSemanticIndex();
1345 if (Semantic->getAttrName()->getName().starts_with_insensitive("SV_"))
1346 return emitSystemSemanticLoad(B, FD, Type, Decl, Semantic, Index);
1347 return emitUserSemanticLoad(B, Type, Decl, Semantic, Index);
1348}
1349
1351 IRBuilder<> &B, const FunctionDecl *FD, llvm::Value *Source,
1352 const clang::DeclaratorDecl *Decl, HLSLAppliedSemanticAttr *Semantic) {
1353 std::optional<unsigned> Index = Semantic->getSemanticIndex();
1354 if (Semantic->getAttrName()->getName().starts_with_insensitive("SV_"))
1355 emitSystemSemanticStore(B, Source, Decl, Semantic, Index);
1356 else
1357 emitUserSemanticStore(B, Source, Decl, Semantic, Index);
1358}
1359
1360std::pair<llvm::Value *, specific_attr_iterator<HLSLAppliedSemanticAttr>>
1362 IRBuilder<> &B, const FunctionDecl *FD, llvm::Type *Type,
1366 const llvm::StructType *ST = cast<StructType>(Type);
1367 const clang::RecordDecl *RD = Decl->getType()->getAsRecordDecl();
1368
1369 assert(RD->getNumFields() == ST->getNumElements());
1370
1371 llvm::Value *Aggregate = llvm::PoisonValue::get(Type);
1372 auto FieldDecl = RD->field_begin();
1373 for (unsigned I = 0; I < ST->getNumElements(); ++I) {
1374 auto [ChildValue, NextAttr] = handleSemanticLoad(
1375 B, FD, ST->getElementType(I), *FieldDecl, AttrBegin, AttrEnd);
1376 AttrBegin = NextAttr;
1377 assert(ChildValue);
1378 Aggregate = B.CreateInsertValue(Aggregate, ChildValue, I);
1379 ++FieldDecl;
1380 }
1381
1382 return std::make_pair(Aggregate, AttrBegin);
1383}
1384
1387 IRBuilder<> &B, const FunctionDecl *FD, llvm::Value *Source,
1391
1392 const llvm::StructType *ST = cast<StructType>(Source->getType());
1393
1394 const clang::RecordDecl *RD = nullptr;
1395 if (const FunctionDecl *FD = dyn_cast<FunctionDecl>(Decl))
1397 else
1398 RD = Decl->getType()->getAsRecordDecl();
1399 assert(RD);
1400
1401 assert(RD->getNumFields() == ST->getNumElements());
1402
1403 auto FieldDecl = RD->field_begin();
1404 for (unsigned I = 0; I < ST->getNumElements(); ++I, ++FieldDecl) {
1405 llvm::Value *Extract = B.CreateExtractValue(Source, I);
1406 AttrBegin =
1407 handleSemanticStore(B, FD, Extract, *FieldDecl, AttrBegin, AttrEnd);
1408 }
1409
1410 return AttrBegin;
1411}
1412
1413std::pair<llvm::Value *, specific_attr_iterator<HLSLAppliedSemanticAttr>>
1415 IRBuilder<> &B, const FunctionDecl *FD, llvm::Type *Type,
1419 assert(AttrBegin != AttrEnd);
1420 if (Type->isStructTy())
1421 return handleStructSemanticLoad(B, FD, Type, Decl, AttrBegin, AttrEnd);
1422
1423 HLSLAppliedSemanticAttr *Attr = *AttrBegin;
1424 ++AttrBegin;
1425 return std::make_pair(handleScalarSemanticLoad(B, FD, Type, Decl, Attr),
1426 AttrBegin);
1427}
1428
1431 IRBuilder<> &B, const FunctionDecl *FD, llvm::Value *Source,
1435 assert(AttrBegin != AttrEnd);
1436 if (Source->getType()->isStructTy())
1437 return handleStructSemanticStore(B, FD, Source, Decl, AttrBegin, AttrEnd);
1438
1439 HLSLAppliedSemanticAttr *Attr = *AttrBegin;
1440 ++AttrBegin;
1441 handleScalarSemanticStore(B, FD, Source, Decl, Attr);
1442 return AttrBegin;
1443}
1444
1446 llvm::Function *Fn) {
1447 llvm::Module &M = CGM.getModule();
1448 llvm::LLVMContext &Ctx = M.getContext();
1449 auto *EntryTy = llvm::FunctionType::get(llvm::Type::getVoidTy(Ctx), false);
1450 Function *EntryFn =
1451 Function::Create(EntryTy, Function::ExternalLinkage, FD->getName(), &M);
1452
1453 // Copy function attributes over, we have no argument or return attributes
1454 // that can be valid on the real entry.
1455 AttributeList NewAttrs = AttributeList::get(Ctx, AttributeList::FunctionIndex,
1456 Fn->getAttributes().getFnAttrs());
1457 EntryFn->setAttributes(NewAttrs);
1458 setHLSLEntryAttributes(FD, EntryFn);
1459
1460 // Set the called function as internal linkage.
1461 Fn->setLinkage(GlobalValue::InternalLinkage);
1462
1463 BasicBlock *BB = BasicBlock::Create(Ctx, "entry", EntryFn);
1464 IRBuilder<> B(BB);
1466
1468 if (CGM.shouldEmitConvergenceTokens()) {
1469 assert(EntryFn->isConvergent());
1470 llvm::Value *I =
1471 B.CreateIntrinsic(llvm::Intrinsic::experimental_convergence_entry, {});
1472 llvm::Value *bundleArgs[] = {I};
1473 OB.emplace_back("convergencectrl", bundleArgs);
1474 }
1475
1477
1478 unsigned SRetOffset = 0;
1479 for (const auto &Param : Fn->args()) {
1480 if (Param.hasStructRetAttr()) {
1481 SRetOffset = 1;
1482 llvm::Type *VarType = Param.getParamStructRetType();
1483 llvm::Value *Var =
1484 CGM.getLangOpts().EmitLogicalPointer
1485 ? cast<Instruction>(B.CreateStructuredAlloca(VarType))
1486 : cast<Instruction>(B.CreateAlloca(VarType));
1487 OutputSemantic.push_back(std::make_pair(Var, VarType));
1488 Args.push_back(Var);
1489 continue;
1490 }
1491
1492 const ParmVarDecl *PD = FD->getParamDecl(Param.getArgNo() - SRetOffset);
1493 llvm::Value *SemanticValue = nullptr;
1494 // FIXME: support inout/out parameters for semantics.
1495 if ([[maybe_unused]] HLSLParamModifierAttr *MA =
1496 PD->getAttr<HLSLParamModifierAttr>()) {
1497 llvm_unreachable("Not handled yet");
1498 } else {
1499 llvm::Type *ParamType = nullptr;
1500 if (Param.hasByValAttr())
1501 ParamType = Param.getParamByValType();
1502 else if (PD->getType()->isRecordType())
1503 ParamType = CGM.getTypes().ConvertType(PD->getType());
1504 else
1505 ParamType = Param.getType();
1506
1507 auto AttrBegin = PD->specific_attr_begin<HLSLAppliedSemanticAttr>();
1508 auto AttrEnd = PD->specific_attr_end<HLSLAppliedSemanticAttr>();
1509 auto Result =
1510 handleSemanticLoad(B, FD, ParamType, PD, AttrBegin, AttrEnd);
1511 SemanticValue = Result.first;
1512 if (!SemanticValue)
1513 return;
1514 if (Param.hasByValAttr() || PD->getType()->isRecordType()) {
1515 llvm::Value *Var =
1516 CGM.getLangOpts().EmitLogicalPointer
1517 ? cast<Instruction>(B.CreateStructuredAlloca(ParamType))
1518 : cast<Instruction>(B.CreateAlloca(ParamType));
1519 B.CreateStore(SemanticValue, Var);
1520 SemanticValue = Var;
1521 }
1522 }
1523
1524 assert(SemanticValue);
1525 Args.push_back(SemanticValue);
1526 }
1527
1528 CallInst *CI = B.CreateCall(FunctionCallee(Fn), Args, OB);
1529 CI->setCallingConv(Fn->getCallingConv());
1530
1531 if (Fn->getReturnType() != CGM.VoidTy)
1532 // Element type is unused, so set to dummy value (NULL).
1533 OutputSemantic.push_back(std::make_pair(CI, nullptr));
1534
1535 for (auto &SourcePair : OutputSemantic) {
1536 llvm::Value *Source = SourcePair.first;
1537 llvm::Type *ElementType = SourcePair.second;
1538 AllocaInst *AI = dyn_cast<AllocaInst>(Source);
1539 llvm::Value *SourceValue = AI ? B.CreateLoad(ElementType, Source) : Source;
1540
1541 auto AttrBegin = FD->specific_attr_begin<HLSLAppliedSemanticAttr>();
1542 auto AttrEnd = FD->specific_attr_end<HLSLAppliedSemanticAttr>();
1543 handleSemanticStore(B, FD, SourceValue, FD, AttrBegin, AttrEnd);
1544 }
1545
1546 B.CreateRetVoid();
1547
1548 // Add and identify root signature to function, if applicable
1549 for (const Attr *Attr : FD->getAttrs()) {
1550 if (const auto *RSAttr = dyn_cast<RootSignatureAttr>(Attr)) {
1551 auto *RSDecl = RSAttr->getSignatureDecl();
1552 addRootSignatureMD(RSDecl->getVersion(), RSDecl->getRootElements(),
1553 EntryFn, M);
1554 }
1555 }
1556}
1557
1558static void gatherFunctions(SmallVectorImpl<Function *> &Fns, llvm::Module &M,
1559 bool CtorOrDtor) {
1560 const auto *GV =
1561 M.getNamedGlobal(CtorOrDtor ? "llvm.global_ctors" : "llvm.global_dtors");
1562 if (!GV)
1563 return;
1564 const auto *CA = dyn_cast<ConstantArray>(GV->getInitializer());
1565 if (!CA)
1566 return;
1567 // The global_ctor array elements are a struct [Priority, Fn *, COMDat].
1568 // HLSL neither supports priorities or COMDat values, so we will check those
1569 // in an assert but not handle them.
1570
1571 for (const auto &Ctor : CA->operands()) {
1573 continue;
1574 ConstantStruct *CS = cast<ConstantStruct>(Ctor);
1575
1576 assert(cast<ConstantInt>(CS->getOperand(0))->getValue() == 65535 &&
1577 "HLSL doesn't support setting priority for global ctors.");
1578 assert(isa<ConstantPointerNull>(CS->getOperand(2)) &&
1579 "HLSL doesn't support COMDat for global ctors.");
1580 Fns.push_back(cast<Function>(CS->getOperand(1)));
1581 }
1582}
1583
1585 llvm::Module &M = CGM.getModule();
1588 gatherFunctions(CtorFns, M, true);
1589 gatherFunctions(DtorFns, M, false);
1590
1591 // Insert a call to the global constructor at the beginning of the entry block
1592 // to externally exported functions. This is a bit of a hack, but HLSL allows
1593 // global constructors, but doesn't support driver initialization of globals.
1594 for (auto &F : M.functions()) {
1595 if (!F.hasFnAttribute("hlsl.shader"))
1596 continue;
1597 auto *Token = getConvergenceToken(F.getEntryBlock());
1598 Instruction *IP = &*F.getEntryBlock().begin();
1600 if (Token) {
1601 llvm::Value *bundleArgs[] = {Token};
1602 OB.emplace_back("convergencectrl", bundleArgs);
1603 IP = Token->getNextNode();
1604 }
1605 IRBuilder<> B(IP);
1606 for (auto *Fn : CtorFns) {
1607 auto CI = B.CreateCall(FunctionCallee(Fn), {}, OB);
1608 CI->setCallingConv(Fn->getCallingConv());
1609 }
1610
1611 // Insert global dtors before the terminator of the last instruction
1612 B.SetInsertPoint(F.back().getTerminator());
1613 for (auto *Fn : DtorFns) {
1614 auto CI = B.CreateCall(FunctionCallee(Fn), {}, OB);
1615 CI->setCallingConv(Fn->getCallingConv());
1616 }
1617 }
1618
1619 // No need to keep global ctors/dtors for non-lib profile after call to
1620 // ctors/dtors added for entry.
1621 Triple T(M.getTargetTriple());
1622 if (T.getEnvironment() != Triple::EnvironmentType::Library) {
1623 if (auto *GV = M.getNamedGlobal("llvm.global_ctors"))
1624 GV->eraseFromParent();
1625 if (auto *GV = M.getNamedGlobal("llvm.global_dtors"))
1626 GV->eraseFromParent();
1627 }
1628}
1629
1630static void initializeBuffer(CodeGenModule &CGM, llvm::GlobalVariable *GV,
1631 Intrinsic::ID IntrID,
1633
1634 LLVMContext &Ctx = CGM.getLLVMContext();
1635 llvm::Function *InitResFunc =
1636 llvm::Function::Create(llvm::FunctionType::get(CGM.VoidTy, false),
1637 llvm::GlobalValue::InternalLinkage,
1638 "_init_buffer_" + GV->getName(), CGM.getModule());
1639 InitResFunc->addFnAttr(llvm::Attribute::AlwaysInline);
1640
1641 llvm::BasicBlock *EntryBB =
1642 llvm::BasicBlock::Create(Ctx, "entry", InitResFunc);
1643 CGBuilderTy Builder(CGM, Ctx);
1644 const DataLayout &DL = CGM.getModule().getDataLayout();
1645 Builder.SetInsertPoint(EntryBB);
1646
1647 // Make sure the global variable is buffer resource handle
1648 llvm::Type *HandleTy = GV->getValueType();
1649 assert(HandleTy->isTargetExtTy() && "unexpected type of the buffer global");
1650
1651 llvm::Value *CreateHandle = Builder.CreateIntrinsic(
1652 /*ReturnType=*/HandleTy, IntrID, Args, nullptr,
1653 Twine(GV->getName()).concat("_h"));
1654
1655 Builder.CreateAlignedStore(CreateHandle, GV, GV->getPointerAlignment(DL));
1656 Builder.CreateRetVoid();
1657
1658 CGM.AddCXXGlobalInit(InitResFunc);
1659}
1660
1661void CGHLSLRuntime::initializeBufferFromBinding(const HLSLBufferDecl *BufDecl,
1662 llvm::GlobalVariable *GV) {
1663 ResourceBindingAttrs Binding(BufDecl);
1664 assert(Binding.hasBinding() &&
1665 "cbuffer/tbuffer should always have resource binding attribute");
1666
1667 auto *Index = llvm::ConstantInt::get(CGM.IntTy, 0);
1668 auto *RangeSize = llvm::ConstantInt::get(CGM.IntTy, 1);
1669 auto *Space = llvm::ConstantInt::get(CGM.IntTy, Binding.getSpace());
1670 Value *Name = buildNameForResource(BufDecl->getName(), CGM);
1671
1672 // buffer with explicit binding
1673 if (Binding.isExplicit()) {
1674 llvm::Intrinsic::ID IntrinsicID =
1675 CGM.getHLSLRuntime().getCreateHandleFromBindingIntrinsic();
1676 auto *RegSlot = llvm::ConstantInt::get(CGM.IntTy, Binding.getSlot());
1677 SmallVector<Value *> Args{Space, RegSlot, RangeSize, Index, Name};
1678 initializeBuffer(CGM, GV, IntrinsicID, Args);
1679 } else {
1680 // buffer with implicit binding
1681 llvm::Intrinsic::ID IntrinsicID =
1682 CGM.getHLSLRuntime().getCreateHandleFromImplicitBindingIntrinsic();
1683 auto *OrderID =
1684 llvm::ConstantInt::get(CGM.IntTy, Binding.getImplicitOrderID());
1685 SmallVector<Value *> Args{OrderID, Space, RangeSize, Index, Name};
1686 initializeBuffer(CGM, GV, IntrinsicID, Args);
1687 }
1688}
1689
1691 llvm::GlobalVariable *GV) {
1692 if (auto Attr = VD->getAttr<HLSLVkExtBuiltinInputAttr>())
1693 addSPIRVBuiltinDecoration(GV, Attr->getBuiltIn());
1694 if (auto Attr = VD->getAttr<HLSLVkExtBuiltinOutputAttr>())
1695 addSPIRVBuiltinDecoration(GV, Attr->getBuiltIn());
1696}
1697
1698llvm::Instruction *CGHLSLRuntime::getConvergenceToken(BasicBlock &BB) {
1699 if (!CGM.shouldEmitConvergenceTokens())
1700 return nullptr;
1701
1702 auto E = BB.end();
1703 for (auto I = BB.begin(); I != E; ++I) {
1704 auto *II = dyn_cast<llvm::IntrinsicInst>(&*I);
1705 if (II && llvm::isConvergenceControlIntrinsic(II->getIntrinsicID())) {
1706 return II;
1707 }
1708 }
1709 llvm_unreachable("Convergence token should have been emitted.");
1710 return nullptr;
1711}
1712
1713class OpaqueValueVisitor : public RecursiveASTVisitor<OpaqueValueVisitor> {
1714public:
1718
1720 // These need to be bound in CodeGenFunction::EmitHLSLOutArgLValues
1721 // or CodeGenFunction::EmitHLSLOutArgExpr. If they are part of this
1722 // traversal, the temporary containing the copy out will not have
1723 // been created yet.
1724 return false;
1725 }
1726
1728 // Traverse the source expression first.
1729 if (E->getSourceExpr())
1731
1732 // Then add this OVE if we haven't seen it before.
1733 if (Visited.insert(E).second)
1734 OVEs.push_back(E);
1735
1736 return true;
1737 }
1738};
1739
1741 InitListExpr *E) {
1742
1743 typedef CodeGenFunction::OpaqueValueMappingData OpaqueValueMappingData;
1744 OpaqueValueVisitor Visitor;
1745 Visitor.TraverseStmt(E);
1746 for (auto *OVE : Visitor.OVEs) {
1747 if (CGF.isOpaqueValueEmitted(OVE))
1748 continue;
1749 if (OpaqueValueMappingData::shouldBindAsLValue(OVE)) {
1750 LValue LV = CGF.EmitLValue(OVE->getSourceExpr());
1751 OpaqueValueMappingData::bind(CGF, OVE, LV);
1752 } else {
1753 RValue RV = CGF.EmitAnyExpr(OVE->getSourceExpr());
1754 OpaqueValueMappingData::bind(CGF, OVE, RV);
1755 }
1756 }
1757}
1758
1760 const ArraySubscriptExpr *ArraySubsExpr, CodeGenFunction &CGF) {
1761 assert((ArraySubsExpr->getType()->isHLSLResourceRecord() ||
1762 ArraySubsExpr->getType()->isHLSLResourceRecordArray()) &&
1763 "expected resource array subscript expression");
1764
1765 // Let clang codegen handle local and static resource array subscripts,
1766 // or when the subscript references on opaque expression (as part of
1767 // ArrayInitLoopExpr AST node).
1768 const VarDecl *ArrayDecl = dyn_cast_or_null<VarDecl>(
1769 getArrayDecl(CGF.CGM.getContext(), ArraySubsExpr));
1770 if (!ArrayDecl || !ArrayDecl->hasGlobalStorage() ||
1771 ArrayDecl->getStorageClass() == SC_Static)
1772 return std::nullopt;
1773
1774 // get the resource array type
1775 ASTContext &AST = ArrayDecl->getASTContext();
1776 const Type *ResArrayTy = ArrayDecl->getType().getTypePtr();
1777 assert(ResArrayTy->isHLSLResourceRecordArray() &&
1778 "expected array of resource classes");
1779
1780 // Iterate through all nested array subscript expressions to calculate
1781 // the index in the flattened resource array (if this is a multi-
1782 // dimensional array). The index is calculated as a sum of all indices
1783 // multiplied by the total size of the array at that level.
1784 Value *Index = nullptr;
1785 const ArraySubscriptExpr *ASE = ArraySubsExpr;
1786 while (ASE != nullptr) {
1787 Value *SubIndex = CGF.EmitScalarExpr(ASE->getIdx());
1788 if (const auto *ArrayTy =
1789 dyn_cast<ConstantArrayType>(ASE->getType().getTypePtr())) {
1790 Value *Multiplier = llvm::ConstantInt::get(
1791 CGM.IntTy, AST.getConstantArrayElementCount(ArrayTy));
1792 SubIndex = CGF.Builder.CreateMul(SubIndex, Multiplier);
1793 }
1794 Index = Index ? CGF.Builder.CreateAdd(Index, SubIndex) : SubIndex;
1795 ASE = dyn_cast<ArraySubscriptExpr>(ASE->getBase()->IgnoreParenImpCasts());
1796 }
1797
1798 // Find binding info for the resource array. For implicit binding
1799 // an HLSLResourceBindingAttr should have been added by SemaHLSL.
1800 ResourceBindingAttrs Binding(ArrayDecl);
1801 assert(Binding.hasBinding() &&
1802 "resource array must have a binding attribute");
1803
1804 // Find the individual resource type.
1805 QualType ResultTy = ArraySubsExpr->getType();
1806 QualType ResourceTy =
1807 ResultTy->isArrayType() ? AST.getBaseElementType(ResultTy) : ResultTy;
1808
1809 // Create a temporary variable for the result, which is either going
1810 // to be a single resource instance or a local array of resources (we need to
1811 // return an LValue).
1812 RawAddress TmpVar = CGF.CreateMemTempWithoutCast(ResultTy);
1813 if (CGF.EmitLifetimeStart(TmpVar.getPointer()))
1815 NormalEHLifetimeMarker, TmpVar);
1816
1821
1822 // Calculate total array size (= range size).
1823 llvm::Value *Range = llvm::ConstantInt::getSigned(
1824 CGM.IntTy, getTotalArraySize(AST, ResArrayTy));
1825
1826 // If the result of the subscript operation is a single resource, call the
1827 // constructor.
1828 if (ResultTy == ResourceTy) {
1829 CallArgList Args;
1830 CXXMethodDecl *CreateMethod = lookupResourceInitMethodAndSetupArgs(
1831 CGF.CGM, ResourceTy->getAsCXXRecordDecl(), Range, Index,
1832 ArrayDecl->getName(), Binding, Args);
1833
1834 if (!CreateMethod) {
1835 // This can happen if someone creates an array of structs that looks like
1836 // an HLSL resource record array but it does not have the required static
1837 // create method. No binding will be generated for it.
1838 assert(!ResourceTy->getAsCXXRecordDecl()->isImplicit() &&
1839 "create method lookup should always succeed for built-in resource "
1840 "records");
1841 return std::nullopt;
1842 }
1843
1844 callResourceInitMethod(CGF, CreateMethod, Args, ValueSlot.getAddress());
1845
1846 } else {
1847 // The result of the subscript operation is a local resource array which
1848 // needs to be initialized.
1849 const ConstantArrayType *ArrayTy =
1851 std::optional<llvm::Value *> EndIndex = initializeResourceArrayFromGlobal(
1852 CGF, ResourceTy->getAsCXXRecordDecl(), ArrayTy, ValueSlot, Range, Index,
1853 ArrayDecl->getName(), Binding, {llvm::ConstantInt::get(CGM.IntTy, 0)});
1854 if (!EndIndex)
1855 return std::nullopt;
1856 }
1857 return CGF.MakeAddrLValue(TmpVar, ResultTy, AlignmentSource::Decl);
1858}
1859
1860// Initialize all resources of a global resource array into provided slot.
1861bool CGHLSLRuntime::initializeGlobalResourceArray(CodeGenFunction &CGF,
1862 const VarDecl *ArrayDecl,
1863 AggValueSlot &DestSlot) {
1864 assert(ArrayDecl->getType()->isHLSLResourceRecordArray() &&
1865 ArrayDecl->hasGlobalStorage() &&
1866 ArrayDecl->getStorageClass() != SC_Static &&
1867 "expected global non-static resource array");
1868
1869 // Find binding info for the resource array. For implicit binding
1870 // the HLSLResourceBindingAttr should have been added by SemaHLSL.
1871 ResourceBindingAttrs Binding(ArrayDecl);
1872 assert(Binding.hasBinding() &&
1873 "resource array must have a binding attribute");
1874
1875 // Find the individual resource type.
1876 ASTContext &AST = ArrayDecl->getASTContext();
1877 QualType ResTy = AST.getBaseElementType(ArrayDecl->getType());
1878 const auto *ResArrayTy =
1880
1881 // Create Value for index and total array size (= range size).
1882 int Size = getTotalArraySize(AST, ResArrayTy);
1883 llvm::Value *Zero = llvm::ConstantInt::get(CGM.IntTy, 0);
1884 llvm::Value *Range = llvm::ConstantInt::get(CGM.IntTy, Size);
1885
1886 // Initialize individual resources in the array into DestSlot.
1887 std::optional<llvm::Value *> EndIndex = initializeResourceArrayFromGlobal(
1888 CGF, ResTy->getAsCXXRecordDecl(), ResArrayTy, DestSlot, Range, Zero,
1889 ArrayDecl->getName(), Binding, {Zero});
1890 return EndIndex.has_value();
1891}
1892
1893// If the expression is a global resource array, initialize all of its resources
1894// into Dest. Returns false if no initialization has been performed and the
1895// array copy should be handled by the default codegen.
1897 AggValueSlot &DestSlot) {
1898 assert(E->getType()->isHLSLResourceRecordArray() &&
1899 "expected resource array");
1900
1901 // Find the array declaration for the expression. Fallback to the default
1902 // handling if it's not a global resource array.
1903 const VarDecl *ArrayDecl =
1904 dyn_cast_or_null<VarDecl>(getArrayDecl(CGF.CGM.getContext(), E));
1905 if (!ArrayDecl || !ArrayDecl->hasGlobalStorage() ||
1906 ArrayDecl->getStorageClass() == SC_Static)
1907 return false;
1908
1909 return initializeGlobalResourceArray(CGF, ArrayDecl, DestSlot);
1910}
1911
1912// If the expression is a global resource array, create a temporary and
1913// initialize all of its resources, and return it as an LValue. Returns nullopt
1914// if no initialization has been performed and the handling should follow the
1915// default path.
1916std::optional<LValue>
1918 const VarDecl *ArrayDecl) {
1919 assert(ArrayDecl->getType()->isHLSLResourceRecordArray() &&
1920 "expected resource array declaration");
1921
1922 if (!ArrayDecl->hasGlobalStorage() ||
1923 ArrayDecl->getStorageClass() == SC_Static)
1924 return std::nullopt;
1925
1926 AggValueSlot TmpArraySlot =
1927 CGF.CreateAggTemp(ArrayDecl->getType(), "tmpResArray");
1928 if (initializeGlobalResourceArray(CGF, ArrayDecl, TmpArraySlot))
1929 return CGF.MakeAddrLValue(TmpArraySlot.getAddress(), ArrayDecl->getType(),
1931 return std::nullopt;
1932}
1933
1935 CodeGenFunction &CGF) {
1936
1937 assert(LV.getType()->isConstantMatrixType() && "expected matrix type");
1939 "expected cbuffer matrix");
1940
1941 QualType MatQualTy = LV.getType();
1942 llvm::Type *LayoutTy = HLSLBufferLayoutBuilder(CGF.CGM).layOutType(MatQualTy);
1943 Address SrcAddr = LV.getAddress();
1944
1945 if (LayoutTy == CGF.ConvertTypeForMem(MatQualTy))
1946 return SrcAddr;
1947
1948 RawAddress DestAlloca =
1949 CGF.CreateMemTempWithoutCast(MatQualTy, "matrix.buf.copy");
1950 HLSLBufferCopyEmitter(CGF, DestAlloca, SrcAddr).emitCopy(MatQualTy);
1951 return DestAlloca;
1952}
1953
1955 const ArraySubscriptExpr *E, CodeGenFunction &CGF,
1956 llvm::function_ref<llvm::Value *(bool Promote)> EmitIdxAfterBase) {
1957 // Find the element type to index by first padding the element type per HLSL
1958 // buffer rules, and then padding out to a 16-byte register boundary if
1959 // necessary.
1960 llvm::Type *LayoutTy =
1962 uint64_t LayoutSizeInBits =
1963 CGM.getDataLayout().getTypeSizeInBits(LayoutTy).getFixedValue();
1964 CharUnits ElementSize = CharUnits::fromQuantity(LayoutSizeInBits / 8);
1965 CharUnits RowAlignedSize = ElementSize.alignTo(CharUnits::fromQuantity(16));
1966 if (RowAlignedSize > ElementSize) {
1967 llvm::Type *Padding = CGM.getTargetCodeGenInfo().getHLSLPadding(
1968 CGM, RowAlignedSize - ElementSize);
1969 assert(Padding && "No padding type for target?");
1970 LayoutTy = llvm::StructType::get(CGF.getLLVMContext(), {LayoutTy, Padding},
1971 /*isPacked=*/true);
1972 }
1973
1974 // If the layout type doesn't introduce any padding, we don't need to do
1975 // anything special.
1976 llvm::Type *OrigTy = CGF.CGM.getTypes().ConvertTypeForMem(E->getType());
1977 if (LayoutTy == OrigTy)
1978 return std::nullopt;
1979
1980 LValueBaseInfo EltBaseInfo;
1981 TBAAAccessInfo EltTBAAInfo;
1982
1983 // Index into the object as-if we have an array of the padded element type,
1984 // and then dereference the element itself to avoid reading padding that may
1985 // be past the end of the in-memory object.
1987 llvm::Value *Idx = EmitIdxAfterBase(/*Promote*/ true);
1988 Indices.push_back(Idx);
1989 Indices.push_back(llvm::ConstantInt::get(CGF.Int32Ty, 0));
1990
1991 if (CGF.getLangOpts().EmitLogicalPointer) {
1992 // The fact that we emit an array-to-pointer decay might be an oversight,
1993 // but for now, we simply ignore it (see #179951).
1994 const CastExpr *CE = cast<CastExpr>(E->getBase());
1995 assert(CE->getCastKind() == CastKind::CK_ArrayToPointerDecay);
1996
1997 LValue LV = CGF.EmitLValue(CE->getSubExpr());
1998 Address Addr = LV.getAddress();
1999 LayoutTy = llvm::ArrayType::get(
2000 LayoutTy,
2001 cast<llvm::ArrayType>(Addr.getElementType())->getNumElements());
2002 auto *GEP = cast<StructuredGEPInst>(CGF.Builder.CreateStructuredGEP(
2003 LayoutTy, Addr.emitRawPointer(CGF), Indices, "cbufferidx"));
2004 Addr =
2005 Address(GEP, GEP->getResultElementType(), RowAlignedSize, KnownNonNull);
2006 return CGF.MakeAddrLValue(Addr, E->getType(), EltBaseInfo, EltTBAAInfo);
2007 }
2008
2009 Address Addr =
2010 CGF.EmitPointerWithAlignment(E->getBase(), &EltBaseInfo, &EltTBAAInfo);
2011 llvm::Value *GEP = CGF.Builder.CreateGEP(LayoutTy, Addr.emitRawPointer(CGF),
2012 Indices, "cbufferidx");
2013 Addr = Address(GEP, Addr.getElementType(), RowAlignedSize, KnownNonNull);
2014 return CGF.MakeAddrLValue(Addr, E->getType(), EltBaseInfo, EltTBAAInfo);
2015}
2016
2017std::optional<LValue>
2019 const MemberExpr *ME) {
2020 assert((ME->getType()->isHLSLResourceRecord() ||
2022 "expected resource member expression");
2023
2024 const VarDecl *ResourceVD =
2025 findAssociatedResourceDeclForStruct(CGF.CGM.getContext(), ME);
2026 if (!ResourceVD)
2027 return std::nullopt;
2028
2029 // Handle member of resource array type.
2030 if (ResourceVD->getType()->isHLSLResourceRecordArray())
2031 return emitGlobalResourceArrayAsLValue(CGF, ResourceVD);
2032
2033 GlobalVariable *ResGV =
2035 const DataLayout &DL = CGM.getDataLayout();
2036 llvm::Type *Ty = ResGV->getValueType();
2037 CharUnits Align = CharUnits::fromQuantity(DL.getABITypeAlign(Ty));
2038 Address Addr = Address(ResGV, Ty, Align);
2039 LValue LV = LValue::MakeAddr(Addr, ME->getType(), CGM.getContext(),
2041 CGM.getTBAAAccessInfo(ME->getType()));
2042 return LV;
2043}
2044
2046 const LValue &SrcLV,
2047 AggValueSlot &DestSlot) {
2049 "expected expression in HLSL constant address space");
2050 assert(!E->getType()->isHLSLResourceRecord() &&
2052 "direct accesses to resource types should be handled separately");
2053
2054 if (DestSlot.isIgnored())
2055 return false;
2056
2057 QualType Ty = E->getType();
2058 Address DstPtr = DestSlot.getAddress();
2059 Address SrcPtr = SrcLV.getAddress();
2060
2061 // If there are no intangible types, we don't need to lookup associated
2062 // resources.
2063 if (!Ty->isHLSLIntangibleType())
2064 return HLSLBufferCopyEmitter(CGF, DstPtr, SrcPtr).emitCopy(Ty);
2065
2066 // Handle structs with intangible types by setting the resource fields
2067 // of the destination struct with the resources associated with the global
2068 // struct.
2069 EmbeddedResourceNameBuilder NameBuilder;
2070 const VarDecl *VD = findStructResourceParentDeclAndBuildName(E, NameBuilder);
2071 AssociatedResourcesList AssociatedResources(VD, NameBuilder.getName());
2072
2073 // Callback to fill in the associated resource.
2074 auto EmitResFn = [&](AggValueSlot &ResSlot) {
2075 const VarDecl *ResDecl = AssociatedResources.getNextResource();
2076 assert(ResDecl && "associated resource declaration not found");
2077
2078 // Check that the resource type of dest and src matches.
2079 [[maybe_unused]] llvm::Type *DestType =
2080 ResSlot.getAddress().getElementType();
2081 [[maybe_unused]] llvm::Type *SrcConvertedType =
2082 CGM.getTypes().ConvertTypeForMem(ResDecl->getType());
2083 assert(DestType == SrcConvertedType && "resource slot type mismatch");
2084
2085 if (ResDecl->getType()->isHLSLResourceRecord())
2086 copyGlobalResource(CGF, ResDecl, ResSlot);
2087 else
2088 initializeGlobalResourceArray(CGF, ResDecl, ResSlot);
2089 };
2090
2091 auto Result =
2092 HLSLBufferCopyEmitter(CGF, DstPtr, SrcPtr).emitCopy(Ty, EmitResFn);
2093 assert(AssociatedResources.getNextResource() == nullptr &&
2094 "expected all associated resources to be processed");
2095 return Result;
2096}
2097
2099 const MemberExpr *E) {
2100 LValue Base =
2102 auto *Field = dyn_cast<FieldDecl>(E->getMemberDecl());
2103 assert(Field && "Unexpected access into HLSL buffer");
2104
2105 const RecordDecl *Rec = Field->getParent();
2106
2107 // Work out the buffer layout type to index into.
2108 QualType RecType = CGM.getContext().getCanonicalTagType(Rec);
2109 assert(RecType->isStructureOrClassType() && "Invalid type in HLSL buffer");
2110 // Since this is a member of an object in the buffer and not the buffer's
2111 // struct/class itself, we shouldn't have any offsets on the members we need
2112 // to contend with.
2113 CGHLSLOffsetInfo EmptyOffsets;
2114 llvm::StructType *LayoutTy = HLSLBufferLayoutBuilder(CGM).layOutStruct(
2115 RecType->getAsCanonical<RecordType>(), EmptyOffsets);
2116
2117 // Get the field index for the layout struct, accounting for padding.
2118 unsigned FieldIdx =
2119 CGM.getTypes().getCGRecordLayout(Rec).getLLVMFieldNo(Field);
2120 assert(FieldIdx < LayoutTy->getNumElements() &&
2121 "Layout struct is smaller than member struct");
2122 unsigned Skipped = 0;
2123 for (unsigned I = 0; I <= FieldIdx;) {
2124 llvm::Type *ElementTy = LayoutTy->getElementType(I + Skipped);
2125 if (CGF.CGM.getTargetCodeGenInfo().isHLSLPadding(ElementTy))
2126 ++Skipped;
2127 else
2128 ++I;
2129 }
2130 FieldIdx += Skipped;
2131 assert(FieldIdx < LayoutTy->getNumElements() && "Access out of bounds");
2132
2133 // Now index into the struct, making sure that the type we return is the
2134 // buffer layout type rather than the original type in the AST.
2135 QualType FieldType = Field->getType();
2136 llvm::Type *FieldLLVMTy = CGM.getTypes().ConvertTypeForMem(FieldType);
2138 CGF.CGM.getDataLayout().getABITypeAlign(FieldLLVMTy));
2139
2140 Value *Ptr = CGF.getLangOpts().EmitLogicalPointer
2141 ? CGF.Builder.CreateStructuredGEP(
2142 LayoutTy, Base.getPointer(CGF),
2143 llvm::ConstantInt::get(CGM.IntTy, FieldIdx))
2144 : CGF.Builder.CreateStructGEP(LayoutTy, Base.getPointer(CGF),
2145 FieldIdx, Field->getName());
2146 Address Addr(Ptr, FieldLLVMTy, Align, KnownNonNull);
2147
2148 LValue LV = LValue::MakeAddr(Addr, FieldType, CGM.getContext(),
2150 CGM.getTBAAAccessInfo(FieldType));
2151 LV.getQuals().addCVRQualifiers(Base.getVRQualifiers());
2152
2153 return LV;
2154}
Defines the clang::ASTContext interface.
static llvm::Value * createSPIRVBuiltinLoad(IRBuilder<> &B, llvm::Module &M, llvm::Type *Ty, const Twine &Name, unsigned BuiltInID)
static void addSPIRVBuiltinDecoration(llvm::GlobalVariable *GV, unsigned BuiltIn)
static void createSPIRVLocationStore(IRBuilder<> &B, llvm::Module &M, llvm::Value *Source, unsigned Location, StringRef Name)
static void gatherFunctions(SmallVectorImpl< Function * > &Fns, llvm::Module &M, bool CtorOrDtor)
static void addLocationDecoration(llvm::GlobalVariable *GV, unsigned Location)
static llvm::Value * createSPIRVLocationLoad(IRBuilder<> &B, llvm::Module &M, llvm::Type *Ty, unsigned Location, StringRef Name)
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)
static void createSPIRVBuiltinStore(IRBuilder<> &B, llvm::Module &M, llvm::Value *Source, const Twine &Name, unsigned BuiltInID)
Result
Implement __builtin_bit_cast and related operations.
llvm::MachO::Record Record
Definition MachO.h:31
#define SM(sm)
Defines the SourceManager interface.
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:223
SourceManager & getSourceManager()
Definition ASTContext.h:866
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
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
unsigned getTargetAddressSpace(LangAS AS) const
ArraySubscriptExpr - [C99 6.5.2.1] Array Subscripting.
Definition Expr.h:2727
QualType getElementType() const
Definition TypeBase.h:3798
Attr - This represents one attribute.
Definition Attr.h:46
Represents a static or instance method of a struct/union/class.
Definition DeclCXX.h:2145
Represents a C++ struct/union/class.
Definition DeclCXX.h:258
QualType withConst() const
Retrieves a version of this type with const applied.
CastExpr - Base class for type casts, including both implicit casts (ImplicitCastExpr) and explicit c...
Definition Expr.h:3682
CastKind getCastKind() const
Definition Expr.h:3726
Expr * getSubExpr()
Definition Expr.h:3732
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
static CharUnits fromQuantity(QuantityType Quantity)
fromQuantity - Construct a CharUnits quantity from a raw integer type.
Definition CharUnits.h:63
CharUnits alignTo(const CharUnits &Align) const
alignTo - Returns the next integer (mod 2**64) that is greater than or equal to this quantity and is ...
Definition CharUnits.h:201
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:551
Address getAddress() const
Definition CGValue.h:691
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:634
llvm::StoreInst * CreateStore(llvm::Value *Val, Address Addr, bool IsVolatile=false)
Definition CGBuilder.h:146
Address CreateGEP(CodeGenFunction &CGF, Address Addr, llvm::Value *Index, const llvm::Twine &Name="")
Definition CGBuilder.h:302
Address CreateStructGEP(Address Addr, unsigned Index, const llvm::Twine &Name="")
Definition CGBuilder.h:229
Abstract information about a function or function prototype.
Definition CGCall.h:43
All available information about a concrete callee.
Definition CGCall.h:65
CGFunctionInfo - Class to encapsulate the information about a function definition.
static const uint32_t Unspecified
static bool compareOffsets(uint32_t LHS, uint32_t RHS)
Comparison function for offsets received from operator[] suitable for use in a stable_sort.
static CGHLSLOffsetInfo fromDecl(const HLSLBufferDecl &BufDecl)
Iterates over all declarations in the HLSL buffer and based on the packoffset or register(c#) annotat...
llvm::Instruction * getConvergenceToken(llvm::BasicBlock &BB)
void setHLSLEntryAttributes(const FunctionDecl *FD, llvm::Function *Fn)
specific_attr_iterator< HLSLAppliedSemanticAttr > handleSemanticStore(llvm::IRBuilder<> &B, const FunctionDecl *FD, llvm::Value *Source, const clang::DeclaratorDecl *Decl, specific_attr_iterator< HLSLAppliedSemanticAttr > AttrBegin, specific_attr_iterator< HLSLAppliedSemanticAttr > AttrEnd)
llvm::StructType * getHLSLBufferLayoutType(const RecordType *LayoutStructTy)
void emitEntryFunction(const FunctionDecl *FD, llvm::Function *Fn)
void handleGlobalVarDefinition(const VarDecl *VD, llvm::GlobalVariable *Var)
void emitSystemSemanticStore(llvm::IRBuilder<> &B, llvm::Value *Source, const clang::DeclaratorDecl *Decl, HLSLAppliedSemanticAttr *Semantic, std::optional< unsigned > Index)
std::pair< llvm::Value *, specific_attr_iterator< HLSLAppliedSemanticAttr > > handleStructSemanticLoad(llvm::IRBuilder<> &B, const FunctionDecl *FD, llvm::Type *Type, const clang::DeclaratorDecl *Decl, specific_attr_iterator< HLSLAppliedSemanticAttr > begin, specific_attr_iterator< HLSLAppliedSemanticAttr > end)
std::optional< LValue > emitResourceMemberExpr(CodeGenFunction &CGF, const MemberExpr *E)
specific_attr_iterator< HLSLAppliedSemanticAttr > handleStructSemanticStore(llvm::IRBuilder<> &B, const FunctionDecl *FD, llvm::Value *Source, const clang::DeclaratorDecl *Decl, specific_attr_iterator< HLSLAppliedSemanticAttr > AttrBegin, specific_attr_iterator< HLSLAppliedSemanticAttr > AttrEnd)
llvm::Value * handleScalarSemanticLoad(llvm::IRBuilder<> &B, const FunctionDecl *FD, llvm::Type *Type, const clang::DeclaratorDecl *Decl, HLSLAppliedSemanticAttr *Semantic)
void addHLSLBufferLayoutType(const RecordType *LayoutStructTy, llvm::StructType *LayoutTy)
std::optional< LValue > emitGlobalResourceArrayAsLValue(CodeGenFunction &CGF, const VarDecl *ArrayDecl)
void handleScalarSemanticStore(llvm::IRBuilder<> &B, const FunctionDecl *FD, llvm::Value *Source, const clang::DeclaratorDecl *Decl, HLSLAppliedSemanticAttr *Semantic)
bool emitBufferCopy(CodeGenFunction &CGF, const Expr *E, const LValue &SrcLV, AggValueSlot &DestSlot)
std::pair< llvm::Value *, specific_attr_iterator< HLSLAppliedSemanticAttr > > handleSemanticLoad(llvm::IRBuilder<> &B, const FunctionDecl *FD, llvm::Type *Type, const clang::DeclaratorDecl *Decl, specific_attr_iterator< HLSLAppliedSemanticAttr > begin, specific_attr_iterator< HLSLAppliedSemanticAttr > end)
std::optional< LValue > emitBufferArraySubscriptExpr(const ArraySubscriptExpr *E, CodeGenFunction &CGF, llvm::function_ref< llvm::Value *(bool Promote)> EmitIdxAfterBase)
std::optional< LValue > emitResourceArraySubscriptExpr(const ArraySubscriptExpr *E, CodeGenFunction &CGF)
void addRootSignature(const HLSLRootSignatureDecl *D)
LValue emitBufferMemberExpr(CodeGenFunction &CGF, const MemberExpr *E)
llvm::Type * convertHLSLSpecificType(const Type *T, const CGHLSLOffsetInfo &OffsetInfo)
RawAddress createBufferMatrixTempAddress(const LValue &LV, CodeGenFunction &CGF)
quad_read_across_diagonal resource_getpointer resource_handlefrombinding resource_nonuniformindex device_memory_barrier_with_group_sync resource_getdimensions_levels_xy GENERATE_HLSL_INTRINSIC_FUNCTION(CalculateLodUnclamped, resource_calculate_lod_unclamped) protected llvm::Value * emitSystemSemanticLoad(llvm::IRBuilder<> &B, const FunctionDecl *FD, llvm::Type *Type, const clang::DeclaratorDecl *Decl, HLSLAppliedSemanticAttr *Semantic, std::optional< unsigned > Index)
void addBuffer(const HLSLBufferDecl *D)
bool emitGlobalResourceArray(CodeGenFunction &CGF, const Expr *E, AggValueSlot &DestSlot)
void emitInitListOpaqueValues(CodeGenFunction &CGF, InitListExpr *E)
unsigned getLLVMFieldNo(const FieldDecl *FD) const
Return llvm::StructType element number that corresponds to the field FD.
CallArgList - Type for representing both the value and type of arguments in a call.
Definition CGCall.h:276
void add(RValue rvalue, QualType type)
Definition CGCall.h:304
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...
const LangOptions & getLangOpts() const
@ TCK_MemberAccess
Checking the object expression in a non-static data member access.
void pushFullExprCleanup(CleanupKind kind, As... A)
pushFullExprCleanup - Push a cleanup to be run at the end of the current full-expression.
AggValueSlot CreateAggTemp(QualType T, const Twine &Name="tmp", RawAddress *Alloca=nullptr)
CreateAggTemp - Create a temporary memory object for the given aggregate type.
bool EmitLifetimeStart(llvm::Value *Addr)
Emit a lifetime.begin marker if some criteria are satisfied.
Definition CGDecl.cpp:1357
RValue EmitCall(const CGFunctionInfo &CallInfo, const CGCallee &Callee, ReturnValueSlot ReturnValue, const CallArgList &Args, llvm::CallBase **CallOrInvoke, bool IsMustTail, SourceLocation Loc, bool IsVirtualFunctionPointerThunk=false)
EmitCall - Generate a call of the given function, expecting the given result type,...
Definition CGCall.cpp:5570
RawAddress CreateMemTempWithoutCast(QualType T, const Twine &Name="tmp")
CreateMemTemp - Create a temporary memory object of the given type, with appropriate alignmen without...
Definition CGExpr.cpp:232
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:281
llvm::Type * ConvertTypeForMem(QualType T)
Address EmitPointerWithAlignment(const Expr *Addr, LValueBaseInfo *BaseInfo=nullptr, TBAAAccessInfo *TBAAInfo=nullptr, KnownNonNull_t IsKnownNonNull=NotKnownNonNull)
EmitPointerWithAlignment - Given an expression with a pointer type, emit the value and compute our be...
Definition CGExpr.cpp:1621
LValue EmitCheckedLValue(const Expr *E, TypeCheckKind TCK)
Same as EmitLValue but additionally we generate checking code to guard against undefined behavior.
Definition CGExpr.cpp:1702
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:1737
bool isOpaqueValueEmitted(const OpaqueValueExpr *E)
isOpaqueValueEmitted - Return true if the opaque value expression has already been emitted.
Definition CGExpr.cpp:6441
llvm::LLVMContext & getLLVMContext()
This class organizes the cross-function state that is used while generating LLVM code.
const PreprocessorOptions & getPreprocessorOpts() const
CGHLSLRuntime & getHLSLRuntime()
Return a reference to the configured HLSL runtime.
llvm::Module & getModule() const
llvm::Constant * GetAddrOfFunction(GlobalDecl GD, llvm::Type *Ty=nullptr, bool ForVTable=false, bool DontDefer=false, ForDefinition_t IsForDefinition=NotForDefinition)
Return the address of the given function.
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::DataLayout & getDataLayout() const
TBAAAccessInfo getTBAAAccessInfo(QualType AccessType)
getTBAAAccessInfo - Get TBAA information that describes an access to an object of the given type.
ASTContext & getContext() 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::Type * ConvertType(QualType T)
ConvertType - Convert type T into a llvm::Type.
const CGRecordLayout & getCGRecordLayout(const RecordDecl *)
getCGRecordLayout - Return record layout info for the given record decl.
llvm::Type * ConvertTypeForMem(QualType T)
ConvertTypeForMem - Convert type T into a llvm::Type.
const CGFunctionInfo & arrangeFreeFunctionCall(const CallArgList &Args, const FunctionType *Ty, bool ChainCall)
Figure out the rules for calling a function with the given formal type using the given arguments.
Definition CGCall.cpp:707
llvm::Constant * getPointer() const
Definition Address.h:308
llvm::StructType * layOutStruct(const RecordType *StructType, const CGHLSLOffsetInfo &OffsetInfo)
Lays out a struct type following HLSL buffer rules and considering any explicit offset information.
llvm::Type * layOutType(QualType Type)
Lays out a type following HLSL buffer rules.
LValue - This represents an lvalue references.
Definition CGValue.h:183
static LValue MakeAddr(Address Addr, QualType type, ASTContext &Context, LValueBaseInfo BaseInfo, TBAAAccessInfo TBAAInfo)
Definition CGValue.h:454
const Qualifiers & getQuals() const
Definition CGValue.h:350
Address getAddress() const
Definition CGValue.h:373
QualType getType() const
Definition CGValue.h:303
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:99
An abstract representation of an aligned address.
Definition Address.h:42
llvm::Value * getPointer() const
Definition Address.h:66
ReturnValueSlot - Contains the address where the return value of a function can be stored,...
Definition CGCall.h:383
virtual bool isHLSLPadding(llvm::Type *Ty) const
Return true if this is an HLSL padding type.
Definition TargetInfo.h:443
virtual llvm::Type * getHLSLPadding(CodeGenModule &CGM, CharUnits NumBytes) const
Return an LLVM type that corresponds to padding in HLSL types.
Definition TargetInfo.h:437
virtual llvm::Type * getHLSLType(CodeGenModule &CGM, const Type *T, const CGHLSLOffsetInfo &OffsetInfo) const
Return an LLVM type that corresponds to a HLSL type.
Definition TargetInfo.h:431
Represents the canonical version of C arrays with a specified constant size.
Definition TypeBase.h:3824
int64_t getSExtSize() const
Return the size sign-extended as a uint64_t.
Definition TypeBase.h:3906
DeclContext * getParent()
getParent - Returns the containing DeclContext.
Definition DeclBase.h:2126
Decl - This represents one declaration (or definition), e.g.
Definition DeclBase.h:86
T * getAttr() const
Definition DeclBase.h:581
bool hasAttrs() const
Definition DeclBase.h:526
ASTContext & getASTContext() const LLVM_READONLY
Definition DeclBase.cpp:547
bool isImplicit() const
isImplicit - Indicates whether the declaration was implicitly generated by the implementation.
Definition DeclBase.h:601
specific_attr_iterator< T > specific_attr_end() const
Definition DeclBase.h:577
specific_attr_iterator< T > specific_attr_begin() const
Definition DeclBase.h:572
AttrVec & getAttrs()
Definition DeclBase.h:532
Represents a ValueDecl that came out of a declarator.
Definition Decl.h:780
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:3099
std::optional< llvm::APSInt > getIntegerConstantExpr(const ASTContext &Ctx) const
isIntegerConstantExpr - Return the value if this expression is a valid integer constant expression.
Expr * IgnoreImpCasts() LLVM_READONLY
Skip past any implicit casts which might surround this expression until reaching a fixed point.
Definition Expr.cpp:3079
QualType getType() const
Definition Expr.h:144
Represents a member of a struct/union/class.
Definition Decl.h:3195
StringRef getName() const
The name of this FileEntry.
Definition FileEntry.h:61
Represents a function declaration or definition.
Definition Decl.h:2027
const ParmVarDecl * getParamDecl(unsigned i) const
Definition Decl.h:2828
QualType getDeclaredReturnType() const
Get the declared return type, which may differ from the actual return type if the return type is dedu...
Definition Decl.h:2893
Represents a prototype with parameter type info, e.g.
Definition TypeBase.h:5371
HLSLBufferDecl - Represent a cbuffer or tbuffer declaration.
Definition Decl.h:5229
bool isCBuffer() const
Definition Decl.h:5273
const CXXRecordDecl * getLayoutStruct() const
Definition Decl.h:5276
bool hasValidPackoffset() const
Definition Decl.h:5275
buffer_decl_range buffer_decls() const
Definition Decl.h:5304
This class represents temporary values used to represent inout and out arguments in HLSL.
Definition Expr.h:7400
ArrayRef< llvm::hlsl::rootsig::RootElement > getRootElements() const
Definition Decl.h:5346
llvm::dxbc::RootSignatureVersion getVersion() const
Definition Decl.h:5344
One of these records is kept for each identifier that is lexed.
Describes an C or C++ initializer list.
Definition Expr.h:5305
MemberExpr - [C99 6.5.2.3] Structure and Union Members.
Definition Expr.h:3370
ValueDecl * getMemberDecl() const
Retrieve the member declaration to which this expression refers.
Definition Expr.h:3453
Expr * getBase() const
Definition Expr.h:3447
IdentifierInfo * getIdentifier() const
Get the identifier that names this declaration, if there is one.
Definition Decl.h:295
StringRef getName() const
Get the name of identifier for this declaration as a StringRef.
Definition Decl.h:301
OpaqueValueExpr - An expression referring to an opaque object of a fixed type and value class.
Definition Expr.h:1184
Expr * getSourceExpr() const
The source expression of an opaque value expression is the expression which originally generated the ...
Definition Expr.h:1234
Represents a parameter to a function.
Definition Decl.h:1817
std::vector< std::pair< std::string, bool > > Macros
A (possibly-)qualified type.
Definition TypeBase.h:937
const Type * getTypePtr() const
Retrieves a pointer to the underlying (unqualified) type.
Definition TypeBase.h:8447
LangAS getAddressSpace() const
Return the address space of this type.
Definition TypeBase.h:8573
The collection of all-type qualifiers we support.
Definition TypeBase.h:331
void addCVRQualifiers(unsigned mask)
Definition TypeBase.h:502
Represents a struct/union/class.
Definition Decl.h:4360
unsigned getNumFields() const
Returns the number of fields (non-static data members) in this record.
Definition Decl.h:4576
field_iterator field_begin() const
Definition Decl.cpp:5272
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.
One instance of this struct is kept for every file loaded or used.
std::optional< llvm::MemoryBufferRef > getBufferOrNone(DiagnosticsEngine &Diag, FileManager &FM, SourceLocation Loc=SourceLocation()) const
Returns the memory buffer for the associated content.
OptionalFileEntryRef OrigEntry
Reference to the file entry representing this ContentCache.
Information about a FileID, basically just the logical file that it represents and include stack info...
const ContentCache & getContentCache() const
CharacteristicKind getFileCharacteristic() const
Return whether this is a system header or not.
This is a discriminated union of FileInfo and ExpansionInfo.
const FileInfo & getFile() const
TargetOptions & getTargetOpts() const
Retrieve the target options.
Definition TargetInfo.h:327
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:1875
bool isIncompleteArrayType() const
Definition TypeBase.h:8791
CXXRecordDecl * getAsCXXRecordDecl() const
Retrieves the CXXRecordDecl that this type refers to, either because the type is a RecordType or beca...
Definition Type.h:26
RecordDecl * getAsRecordDecl() const
Retrieves the RecordDecl this type refers to.
Definition Type.h:41
bool isArrayType() const
Definition TypeBase.h:8783
bool isConstantMatrixType() const
Definition TypeBase.h:8851
bool isHLSLIntangibleType() const
Definition Type.cpp:5527
bool isHLSLResourceRecord() const
Definition Type.cpp:5514
bool isStructureOrClassType() const
Definition Type.cpp:743
const T * getAsCanonical() const
If this type is canonically the specified type, return its canonical type cast to that specified type...
Definition TypeBase.h:2985
const T * getAs() const
Member-template getAs<specific type>'.
Definition TypeBase.h:9277
const Type * getUnqualifiedDesugaredType() const
Return the specified type with any "sugar" removed from the type, removing any typedefs,...
Definition Type.cpp:690
bool isRecordType() const
Definition TypeBase.h:8811
bool isHLSLResourceRecordArray() const
Definition Type.cpp:5518
Represent the declaration of a variable (in which case it is an lvalue) a function (in which case it ...
Definition Decl.h:712
QualType getType() const
Definition Decl.h:723
Represents a variable declaration or definition.
Definition Decl.h:932
bool hasGlobalStorage() const
Returns true for all variables that do not have local storage.
Definition Decl.h:1247
StorageClass getStorageClass() const
Returns the storage class as written in the source.
Definition Decl.h:1174
void pushBaseNameHierarchy(CXXRecordDecl *DerivedRD, CXXRecordDecl *BaseRD)
IdentifierInfo * getNameAsIdentifier(ASTContext &AST) const
specific_attr_iterator - Iterates over a subrange of an AttrVec, only providing attributes that are o...
@ Type
The l-value was considered opaque, so the alignment was determined from a type.
Definition CGValue.h:155
@ Decl
The l-value was an access to a declared entity or something equivalently strong, like the address of ...
Definition CGValue.h:146
bool isSystem(CharacteristicKind CK)
Determine whether a file / directory characteristic is for system code.
bool hasCounterHandle(const CXXRecordDecl *RD)
StringRef getName(const HeaderType T)
Definition HeaderFile.h:38
@ Address
A pointer to a ValueDecl.
Definition Primitives.h:28
bool Load(InterpState &S, CodePtr OpPC)
Definition Interp.h:2221
The JSON file list parser is used to communicate input to InstallAPI.
bool isa(CodeGen::Address addr)
Definition Address.h:330
CustomizableOptional< FileEntryRef > OptionalFileEntryRef
Definition FileEntry.h:196
std::vector< std::string > Macros
A list of macros of the form <definition>=<expansion> .
Definition Format.h:3951
nullptr
This class represents a compute construct, representing a 'Kind' of ‘parallel’, 'serial',...
StorageClass
Storage classes.
Definition Specifiers.h:249
@ SC_Static
Definition Specifiers.h:253
@ SC_None
Definition Specifiers.h:251
@ Result
The result type of a method or function.
Definition TypeBase.h:905
U cast(CodeGen::Address addr)
Definition Address.h:327
Diagnostic wrappers for TextAPI types for error reporting.
Definition Dominators.h:30
__packed_splat4 __packed_splat2 __packed_splat8 __packed_splat4 __packed_splat2 __packed_splat4 __packed_splat2 __packed_splat8 __packed_splat4 uint32_t
unsigned getCounterImplicitOrderID() const