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"
31#include "llvm/ADT/DenseMap.h"
32#include "llvm/ADT/ScopeExit.h"
33#include "llvm/ADT/SmallString.h"
34#include "llvm/ADT/SmallVector.h"
35#include "llvm/Frontend/HLSL/RootSignatureMetadata.h"
36#include "llvm/IR/Constants.h"
37#include "llvm/IR/DerivedTypes.h"
38#include "llvm/IR/GlobalVariable.h"
39#include "llvm/IR/IntrinsicInst.h"
40#include "llvm/IR/LLVMContext.h"
41#include "llvm/IR/Metadata.h"
42#include "llvm/IR/Module.h"
43#include "llvm/IR/Type.h"
44#include "llvm/IR/Value.h"
45#include "llvm/Support/Alignment.h"
46#include "llvm/Support/ErrorHandling.h"
47#include "llvm/Support/FormatVariadic.h"
48#include <cstdint>
49#include <optional>
50
51using namespace clang;
52using namespace CodeGen;
53using namespace clang::hlsl;
54using namespace llvm;
55
56using llvm::hlsl::CBufferRowSizeInBytes;
57
58namespace {
59
60void addDxilValVersion(StringRef ValVersionStr, llvm::Module &M) {
61 // The validation of ValVersionStr is done at HLSLToolChain::TranslateArgs.
62 // Assume ValVersionStr is legal here.
63 VersionTuple Version;
64 if (Version.tryParse(ValVersionStr) || Version.getBuild() ||
65 Version.getSubminor() || !Version.getMinor()) {
66 return;
67 }
68
69 uint64_t Major = Version.getMajor();
70 uint64_t Minor = *Version.getMinor();
71
72 auto &Ctx = M.getContext();
73 IRBuilder<> B(M.getContext());
74 MDNode *Val = MDNode::get(Ctx, {ConstantAsMetadata::get(B.getInt32(Major)),
75 ConstantAsMetadata::get(B.getInt32(Minor))});
76 StringRef DXILValKey = "dx.valver";
77 auto *DXILValMD = M.getOrInsertNamedMetadata(DXILValKey);
78 DXILValMD->addOperand(Val);
79}
80
81void addRootSignatureMD(llvm::dxbc::RootSignatureVersion RootSigVer,
83 llvm::Function *Fn, llvm::Module &M) {
84 auto &Ctx = M.getContext();
85
86 llvm::hlsl::rootsig::MetadataBuilder RSBuilder(Ctx, Elements);
87 MDNode *RootSignature = RSBuilder.BuildRootSignature();
88
89 ConstantAsMetadata *Version = ConstantAsMetadata::get(ConstantInt::get(
90 llvm::Type::getInt32Ty(Ctx), llvm::to_underlying(RootSigVer)));
91 ValueAsMetadata *EntryFunc = Fn ? ValueAsMetadata::get(Fn) : nullptr;
92 MDNode *MDVals = MDNode::get(Ctx, {EntryFunc, RootSignature, Version});
93
94 StringRef RootSignatureValKey = "dx.rootsignatures";
95 auto *RootSignatureValMD = M.getOrInsertNamedMetadata(RootSignatureValKey);
96 RootSignatureValMD->addOperand(MDVals);
97}
98
99// Find array variable declaration from DeclRef expression
100static const ValueDecl *getArrayDecl(const Expr *E) {
101 if (const DeclRefExpr *DRE =
102 dyn_cast_or_null<DeclRefExpr>(E->IgnoreImpCasts()))
103 return DRE->getDecl();
104 return nullptr;
105}
106
107// Find array variable declaration from nested array subscript AST nodes
108static const ValueDecl *getArrayDecl(const ArraySubscriptExpr *ASE) {
109 const Expr *E = nullptr;
110 while (ASE != nullptr) {
111 E = ASE->getBase()->IgnoreImpCasts();
112 if (!E)
113 return nullptr;
114 ASE = dyn_cast<ArraySubscriptExpr>(E);
115 }
116 return getArrayDecl(E);
117}
118
119// Get the total size of the array, or -1 if the array is unbounded.
120static int getTotalArraySize(ASTContext &AST, const clang::Type *Ty) {
122 assert(Ty->isArrayType() && "expected array type");
123 if (Ty->isIncompleteArrayType())
124 return -1;
126}
127
128static Value *buildNameForResource(llvm::StringRef BaseName,
129 CodeGenModule &CGM) {
130 llvm::SmallString<64> GlobalName = {BaseName, ".str"};
131 return CGM.GetAddrOfConstantCString(BaseName.str(), GlobalName.c_str())
132 .getPointer();
133}
134
135static CXXMethodDecl *lookupMethod(CXXRecordDecl *Record, StringRef Name,
136 StorageClass SC = SC_None) {
137 for (auto *Method : Record->methods()) {
138 if (Method->getStorageClass() == SC && Method->getName() == Name)
139 return Method;
140 }
141 return nullptr;
142}
143
144static CXXMethodDecl *lookupResourceInitMethodAndSetupArgs(
145 CodeGenModule &CGM, CXXRecordDecl *ResourceDecl, llvm::Value *Range,
146 llvm::Value *Index, StringRef Name, ResourceBindingAttrs &Binding,
147 CallArgList &Args) {
148 assert(Binding.hasBinding() && "at least one binding attribute expected");
149
150 ASTContext &AST = CGM.getContext();
151 CXXMethodDecl *CreateMethod = nullptr;
152 Value *NameStr = buildNameForResource(Name, CGM);
153 Value *Space = llvm::ConstantInt::get(CGM.IntTy, Binding.getSpace());
154
155 if (Binding.isExplicit()) {
156 // explicit binding
157 auto *RegSlot = llvm::ConstantInt::get(CGM.IntTy, Binding.getSlot());
158 Args.add(RValue::get(RegSlot), AST.UnsignedIntTy);
159 const char *Name = Binding.hasCounterImplicitOrderID()
160 ? "__createFromBindingWithImplicitCounter"
161 : "__createFromBinding";
162 CreateMethod = lookupMethod(ResourceDecl, Name, SC_Static);
163 } else {
164 // implicit binding
165 auto *OrderID =
166 llvm::ConstantInt::get(CGM.IntTy, Binding.getImplicitOrderID());
167 Args.add(RValue::get(OrderID), AST.UnsignedIntTy);
168 const char *Name = Binding.hasCounterImplicitOrderID()
169 ? "__createFromImplicitBindingWithImplicitCounter"
170 : "__createFromImplicitBinding";
171 CreateMethod = lookupMethod(ResourceDecl, Name, SC_Static);
172 }
173 Args.add(RValue::get(Space), AST.UnsignedIntTy);
174 Args.add(RValue::get(Range), AST.IntTy);
175 Args.add(RValue::get(Index), AST.UnsignedIntTy);
176 Args.add(RValue::get(NameStr), AST.getPointerType(AST.CharTy.withConst()));
177 if (Binding.hasCounterImplicitOrderID()) {
178 uint32_t CounterBinding = Binding.getCounterImplicitOrderID();
179 auto *CounterOrderID = llvm::ConstantInt::get(CGM.IntTy, CounterBinding);
180 Args.add(RValue::get(CounterOrderID), AST.UnsignedIntTy);
181 }
182
183 return CreateMethod;
184}
185
186static void callResourceInitMethod(CodeGenFunction &CGF,
187 CXXMethodDecl *CreateMethod,
188 CallArgList &Args, Address ReturnAddress) {
189 llvm::Constant *CalleeFn = CGF.CGM.GetAddrOfFunction(CreateMethod);
190 const FunctionProtoType *Proto =
191 CreateMethod->getType()->getAs<FunctionProtoType>();
192 const CGFunctionInfo &FnInfo =
193 CGF.CGM.getTypes().arrangeFreeFunctionCall(Args, Proto, false);
194 ReturnValueSlot ReturnValue(ReturnAddress, false);
195 CGCallee Callee(CGCalleeInfo(Proto), CalleeFn);
196 CGF.EmitCall(FnInfo, Callee, ReturnValue, Args, nullptr);
197}
198
199// Initializes local resource array variable. For multi-dimensional arrays it
200// calls itself recursively to initialize its sub-arrays. The Index used in the
201// resource constructor calls will begin at StartIndex and will be incremented
202// for each array element. The last used resource Index is returned to the
203// caller. If the function returns std::nullopt, it indicates an error.
204static std::optional<llvm::Value *> initializeLocalResourceArray(
205 CodeGenFunction &CGF, CXXRecordDecl *ResourceDecl,
206 const ConstantArrayType *ArrayTy, AggValueSlot &ValueSlot,
207 llvm::Value *Range, llvm::Value *StartIndex, StringRef ResourceName,
208 ResourceBindingAttrs &Binding, ArrayRef<llvm::Value *> PrevGEPIndices,
209 SourceLocation ArraySubsExprLoc) {
210
211 ASTContext &AST = CGF.getContext();
212 llvm::IntegerType *IntTy = CGF.CGM.IntTy;
213 llvm::Value *Index = StartIndex;
214 llvm::Value *One = llvm::ConstantInt::get(IntTy, 1);
215 const uint64_t ArraySize = ArrayTy->getSExtSize();
216 QualType ElemType = ArrayTy->getElementType();
217 Address TmpArrayAddr = ValueSlot.getAddress();
218
219 // Add additional index to the getelementptr call indices.
220 // This index will be updated for each array element in the loops below.
221 SmallVector<llvm::Value *> GEPIndices(PrevGEPIndices);
222 GEPIndices.push_back(llvm::ConstantInt::get(IntTy, 0));
223
224 // For array of arrays, recursively initialize the sub-arrays.
225 if (ElemType->isArrayType()) {
226 const ConstantArrayType *SubArrayTy = cast<ConstantArrayType>(ElemType);
227 for (uint64_t I = 0; I < ArraySize; I++) {
228 if (I > 0) {
229 Index = CGF.Builder.CreateAdd(Index, One);
230 GEPIndices.back() = llvm::ConstantInt::get(IntTy, I);
231 }
232 std::optional<llvm::Value *> MaybeIndex = initializeLocalResourceArray(
233 CGF, ResourceDecl, SubArrayTy, ValueSlot, Range, Index, ResourceName,
234 Binding, GEPIndices, ArraySubsExprLoc);
235 if (!MaybeIndex)
236 return std::nullopt;
237 Index = *MaybeIndex;
238 }
239 return Index;
240 }
241
242 // For array of resources, initialize each resource in the array.
243 llvm::Type *Ty = CGF.ConvertTypeForMem(ElemType);
244 CharUnits ElemSize = AST.getTypeSizeInChars(ElemType);
245 CharUnits Align =
246 TmpArrayAddr.getAlignment().alignmentOfArrayElement(ElemSize);
247
248 for (uint64_t I = 0; I < ArraySize; I++) {
249 if (I > 0) {
250 Index = CGF.Builder.CreateAdd(Index, One);
251 GEPIndices.back() = llvm::ConstantInt::get(IntTy, I);
252 }
253 Address ReturnAddress =
254 CGF.Builder.CreateGEP(TmpArrayAddr, GEPIndices, Ty, Align);
255
256 CallArgList Args;
257 CXXMethodDecl *CreateMethod = lookupResourceInitMethodAndSetupArgs(
258 CGF.CGM, ResourceDecl, Range, Index, ResourceName, Binding, Args);
259
260 if (!CreateMethod)
261 // This can happen if someone creates an array of structs that looks like
262 // an HLSL resource record array but it does not have the required static
263 // create method. No binding will be generated for it.
264 return std::nullopt;
265
266 callResourceInitMethod(CGF, CreateMethod, Args, ReturnAddress);
267 }
268 return Index;
269}
270
271} // namespace
272
273llvm::Type *
275 const CGHLSLOffsetInfo &OffsetInfo) {
276 assert(T->isHLSLSpecificType() && "Not an HLSL specific type!");
277
278 // Check if the target has a specific translation for this type first.
279 if (llvm::Type *TargetTy =
280 CGM.getTargetCodeGenInfo().getHLSLType(CGM, T, OffsetInfo))
281 return TargetTy;
282
283 llvm_unreachable("Generic handling of HLSL types is not supported.");
284}
285
286llvm::Triple::ArchType CGHLSLRuntime::getArch() {
287 return CGM.getTarget().getTriple().getArch();
288}
289
290// Emits constant global variables for buffer constants declarations
291// and creates metadata linking the constant globals with the buffer global.
292void CGHLSLRuntime::emitBufferGlobalsAndMetadata(
293 const HLSLBufferDecl *BufDecl, llvm::GlobalVariable *BufGV,
294 const CGHLSLOffsetInfo &OffsetInfo) {
295 LLVMContext &Ctx = CGM.getLLVMContext();
296
297 // get the layout struct from constant buffer target type
298 llvm::Type *BufType = BufGV->getValueType();
299 llvm::StructType *LayoutStruct = cast<llvm::StructType>(
300 cast<llvm::TargetExtType>(BufType)->getTypeParameter(0));
301
303 size_t OffsetIdx = 0;
304 for (Decl *D : BufDecl->buffer_decls()) {
306 // Nothing to do for this declaration.
307 continue;
308 if (isa<FunctionDecl>(D)) {
309 // A function within an cbuffer is effectively a top-level function.
310 CGM.EmitTopLevelDecl(D);
311 continue;
312 }
313 VarDecl *VD = dyn_cast<VarDecl>(D);
314 if (!VD)
315 continue;
316
317 QualType VDTy = VD->getType();
319 if (VD->getStorageClass() == SC_Static ||
322 // Emit static and groupshared variables and resource classes inside
323 // cbuffer as regular globals
324 CGM.EmitGlobal(VD);
325 } else {
326 // Anything else that is not in the hlsl_constant address space must be
327 // an empty struct or a zero-sized array and can be ignored
328 assert(BufDecl->getASTContext().getTypeSize(VDTy) == 0 &&
329 "constant buffer decl with non-zero sized type outside of "
330 "hlsl_constant address space");
331 }
332 continue;
333 }
334
335 DeclsWithOffset.emplace_back(VD, OffsetInfo[OffsetIdx++]);
336 }
337
338 if (!OffsetInfo.empty())
339 llvm::stable_sort(DeclsWithOffset, [](const auto &LHS, const auto &RHS) {
340 return CGHLSLOffsetInfo::compareOffsets(LHS.second, RHS.second);
341 });
342
343 // Associate the buffer global variable with its constants
344 SmallVector<llvm::Metadata *> BufGlobals;
345 BufGlobals.reserve(DeclsWithOffset.size() + 1);
346 BufGlobals.push_back(ValueAsMetadata::get(BufGV));
347
348 auto ElemIt = LayoutStruct->element_begin();
349 for (auto &[VD, _] : DeclsWithOffset) {
350 if (CGM.getTargetCodeGenInfo().isHLSLPadding(*ElemIt))
351 ++ElemIt;
352
353 assert(ElemIt != LayoutStruct->element_end() &&
354 "number of elements in layout struct does not match");
355 llvm::Type *LayoutType = *ElemIt++;
356
357 GlobalVariable *ElemGV =
358 cast<GlobalVariable>(CGM.GetAddrOfGlobalVar(VD, LayoutType));
359 BufGlobals.push_back(ValueAsMetadata::get(ElemGV));
360 }
361 assert(ElemIt == LayoutStruct->element_end() &&
362 "number of elements in layout struct does not match");
363
364 // add buffer metadata to the module
365 CGM.getModule()
366 .getOrInsertNamedMetadata("hlsl.cbs")
367 ->addOperand(MDNode::get(Ctx, BufGlobals));
368}
369
370// Creates resource handle type for the HLSL buffer declaration
371static const clang::HLSLAttributedResourceType *
373 ASTContext &AST = BufDecl->getASTContext();
375 AST.HLSLResourceTy, AST.getCanonicalTagType(BufDecl->getLayoutStruct()),
376 HLSLAttributedResourceType::Attributes(ResourceClass::CBuffer));
378}
379
382
383 // If we don't have packoffset info, just return an empty result.
384 if (!BufDecl.hasValidPackoffset())
385 return Result;
386
387 for (Decl *D : BufDecl.buffer_decls()) {
389 continue;
390 }
391 VarDecl *VD = dyn_cast<VarDecl>(D);
392 if (!VD || VD->getType().getAddressSpace() != LangAS::hlsl_constant)
393 continue;
394
395 if (!VD->hasAttrs()) {
396 Result.Offsets.push_back(Unspecified);
397 continue;
398 }
399
400 uint32_t Offset = Unspecified;
401 for (auto *Attr : VD->getAttrs()) {
402 if (auto *POA = dyn_cast<HLSLPackOffsetAttr>(Attr)) {
403 Offset = POA->getOffsetInBytes();
404 break;
405 }
406 auto *RBA = dyn_cast<HLSLResourceBindingAttr>(Attr);
407 if (RBA &&
408 RBA->getRegisterType() == HLSLResourceBindingAttr::RegisterType::C) {
409 Offset = RBA->getSlotNumber() * CBufferRowSizeInBytes;
410 break;
411 }
412 }
413 Result.Offsets.push_back(Offset);
414 }
415 return Result;
416}
417
418// Codegen for HLSLBufferDecl
420
421 assert(BufDecl->isCBuffer() && "tbuffer codegen is not supported yet");
422
423 // create resource handle type for the buffer
424 const clang::HLSLAttributedResourceType *ResHandleTy =
425 createBufferHandleType(BufDecl);
426
427 // empty constant buffer is ignored
428 if (ResHandleTy->getContainedType()->getAsCXXRecordDecl()->isEmpty())
429 return;
430
431 // create global variable for the constant buffer
432 CGHLSLOffsetInfo OffsetInfo = CGHLSLOffsetInfo::fromDecl(*BufDecl);
433 llvm::Type *LayoutTy = convertHLSLSpecificType(ResHandleTy, OffsetInfo);
434 llvm::GlobalVariable *BufGV = new GlobalVariable(
435 LayoutTy, /*isConstant*/ false,
436 GlobalValue::LinkageTypes::ExternalLinkage, PoisonValue::get(LayoutTy),
437 llvm::formatv("{0}{1}", BufDecl->getName(),
438 BufDecl->isCBuffer() ? ".cb" : ".tb"),
439 GlobalValue::NotThreadLocal);
440 CGM.getModule().insertGlobalVariable(BufGV);
441
442 // Add globals for constant buffer elements and create metadata nodes
443 emitBufferGlobalsAndMetadata(BufDecl, BufGV, OffsetInfo);
444
445 // Initialize cbuffer from binding (implicit or explicit)
446 initializeBufferFromBinding(BufDecl, BufGV);
447}
448
450 const HLSLRootSignatureDecl *SignatureDecl) {
451 llvm::Module &M = CGM.getModule();
452 Triple T(M.getTargetTriple());
453
454 // Generated later with the function decl if not targeting root signature
455 if (T.getEnvironment() != Triple::EnvironmentType::RootSignature)
456 return;
457
458 addRootSignatureMD(SignatureDecl->getVersion(),
459 SignatureDecl->getRootElements(), nullptr, M);
460}
461
462llvm::StructType *
463CGHLSLRuntime::getHLSLBufferLayoutType(const RecordType *StructType) {
464 const auto Entry = LayoutTypes.find(StructType);
465 if (Entry != LayoutTypes.end())
466 return Entry->getSecond();
467 return nullptr;
468}
469
470void CGHLSLRuntime::addHLSLBufferLayoutType(const RecordType *StructType,
471 llvm::StructType *LayoutTy) {
472 assert(getHLSLBufferLayoutType(StructType) == nullptr &&
473 "layout type for this struct already exist");
474 LayoutTypes[StructType] = LayoutTy;
475}
476
478 auto &TargetOpts = CGM.getTarget().getTargetOpts();
479 auto &CodeGenOpts = CGM.getCodeGenOpts();
480 auto &LangOpts = CGM.getLangOpts();
481 llvm::Module &M = CGM.getModule();
482 Triple T(M.getTargetTriple());
483 if (T.getArch() == Triple::ArchType::dxil)
484 addDxilValVersion(TargetOpts.DxilValidatorVersion, M);
485 if (CodeGenOpts.ResMayAlias)
486 M.setModuleFlag(llvm::Module::ModFlagBehavior::Error, "dx.resmayalias", 1);
487 if (CodeGenOpts.AllResourcesBound)
488 M.setModuleFlag(llvm::Module::ModFlagBehavior::Error,
489 "dx.allresourcesbound", 1);
490 if (CodeGenOpts.OptimizationLevel == 0)
491 M.addModuleFlag(llvm::Module::ModFlagBehavior::Override,
492 "dx.disable_optimizations", 1);
493
494 // NativeHalfType corresponds to the -fnative-half-type clang option which is
495 // aliased by clang-dxc's -enable-16bit-types option. This option is used to
496 // set the UseNativeLowPrecision DXIL module flag in the DirectX backend
497 if (LangOpts.NativeHalfType)
498 M.setModuleFlag(llvm::Module::ModFlagBehavior::Error, "dx.nativelowprec",
499 1);
500
502}
503
505 const FunctionDecl *FD, llvm::Function *Fn) {
506 const auto *ShaderAttr = FD->getAttr<HLSLShaderAttr>();
507 assert(ShaderAttr && "All entry functions must have a HLSLShaderAttr");
508 const StringRef ShaderAttrKindStr = "hlsl.shader";
509 Fn->addFnAttr(ShaderAttrKindStr,
510 llvm::Triple::getEnvironmentTypeName(ShaderAttr->getType()));
511 if (HLSLNumThreadsAttr *NumThreadsAttr = FD->getAttr<HLSLNumThreadsAttr>()) {
512 const StringRef NumThreadsKindStr = "hlsl.numthreads";
513 std::string NumThreadsStr =
514 formatv("{0},{1},{2}", NumThreadsAttr->getX(), NumThreadsAttr->getY(),
515 NumThreadsAttr->getZ());
516 Fn->addFnAttr(NumThreadsKindStr, NumThreadsStr);
517 }
518 if (HLSLWaveSizeAttr *WaveSizeAttr = FD->getAttr<HLSLWaveSizeAttr>()) {
519 const StringRef WaveSizeKindStr = "hlsl.wavesize";
520 std::string WaveSizeStr =
521 formatv("{0},{1},{2}", WaveSizeAttr->getMin(), WaveSizeAttr->getMax(),
522 WaveSizeAttr->getPreferred());
523 Fn->addFnAttr(WaveSizeKindStr, WaveSizeStr);
524 }
525 // HLSL entry functions are materialized for module functions with
526 // HLSLShaderAttr attribute. SetLLVMFunctionAttributesForDefinition called
527 // later in the compiler-flow for such module functions is not aware of and
528 // hence not able to set attributes of the newly materialized entry functions.
529 // So, set attributes of entry function here, as appropriate.
530 Fn->addFnAttr(llvm::Attribute::NoInline);
531
532 if (CGM.getLangOpts().HLSLSpvEnableMaximalReconvergence) {
533 Fn->addFnAttr("enable-maximal-reconvergence", "true");
534 }
535}
536
537static Value *buildVectorInput(IRBuilder<> &B, Function *F, llvm::Type *Ty) {
538 if (const auto *VT = dyn_cast<FixedVectorType>(Ty)) {
539 Value *Result = PoisonValue::get(Ty);
540 for (unsigned I = 0; I < VT->getNumElements(); ++I) {
541 Value *Elt = B.CreateCall(F, {B.getInt32(I)});
542 Result = B.CreateInsertElement(Result, Elt, I);
543 }
544 return Result;
545 }
546 return B.CreateCall(F, {B.getInt32(0)});
547}
548
549static void addSPIRVBuiltinDecoration(llvm::GlobalVariable *GV,
550 unsigned BuiltIn) {
551 LLVMContext &Ctx = GV->getContext();
552 IRBuilder<> B(GV->getContext());
553 MDNode *Operands = MDNode::get(
554 Ctx,
555 {ConstantAsMetadata::get(B.getInt32(/* Spirv::Decoration::BuiltIn */ 11)),
556 ConstantAsMetadata::get(B.getInt32(BuiltIn))});
557 MDNode *Decoration = MDNode::get(Ctx, {Operands});
558 GV->addMetadata("spirv.Decorations", *Decoration);
559}
560
561static void addLocationDecoration(llvm::GlobalVariable *GV, unsigned Location) {
562 LLVMContext &Ctx = GV->getContext();
563 IRBuilder<> B(GV->getContext());
564 MDNode *Operands =
565 MDNode::get(Ctx, {ConstantAsMetadata::get(B.getInt32(/* Location */ 30)),
566 ConstantAsMetadata::get(B.getInt32(Location))});
567 MDNode *Decoration = MDNode::get(Ctx, {Operands});
568 GV->addMetadata("spirv.Decorations", *Decoration);
569}
570
571static llvm::Value *createSPIRVBuiltinLoad(IRBuilder<> &B, llvm::Module &M,
572 llvm::Type *Ty, const Twine &Name,
573 unsigned BuiltInID) {
574 auto *GV = new llvm::GlobalVariable(
575 M, Ty, /* isConstant= */ true, llvm::GlobalValue::ExternalLinkage,
576 /* Initializer= */ nullptr, Name, /* insertBefore= */ nullptr,
577 llvm::GlobalVariable::GeneralDynamicTLSModel,
578 /* AddressSpace */ 7, /* isExternallyInitialized= */ true);
579 addSPIRVBuiltinDecoration(GV, BuiltInID);
580 GV->setVisibility(llvm::GlobalValue::HiddenVisibility);
581 return B.CreateLoad(Ty, GV);
582}
583
584static llvm::Value *createSPIRVLocationLoad(IRBuilder<> &B, llvm::Module &M,
585 llvm::Type *Ty, unsigned Location,
586 StringRef Name) {
587 auto *GV = new llvm::GlobalVariable(
588 M, Ty, /* isConstant= */ true, llvm::GlobalValue::ExternalLinkage,
589 /* Initializer= */ nullptr, /* Name= */ Name, /* insertBefore= */ nullptr,
590 llvm::GlobalVariable::GeneralDynamicTLSModel,
591 /* AddressSpace */ 7, /* isExternallyInitialized= */ true);
592 GV->setVisibility(llvm::GlobalValue::HiddenVisibility);
593 addLocationDecoration(GV, Location);
594 return B.CreateLoad(Ty, GV);
595}
596
597llvm::Value *CGHLSLRuntime::emitSPIRVUserSemanticLoad(
598 llvm::IRBuilder<> &B, llvm::Type *Type, const clang::DeclaratorDecl *Decl,
599 HLSLAppliedSemanticAttr *Semantic, std::optional<unsigned> Index) {
600 Twine BaseName = Twine(Semantic->getAttrName()->getName());
601 Twine VariableName = BaseName.concat(Twine(Index.value_or(0)));
602
603 unsigned Location = SPIRVLastAssignedInputSemanticLocation;
604 if (auto *L = Decl->getAttr<HLSLVkLocationAttr>())
605 Location = L->getLocation();
606
607 // DXC completely ignores the semantic/index pair. Location are assigned from
608 // the first semantic to the last.
609 llvm::ArrayType *AT = dyn_cast<llvm::ArrayType>(Type);
610 unsigned ElementCount = AT ? AT->getNumElements() : 1;
611 SPIRVLastAssignedInputSemanticLocation += ElementCount;
612
613 return createSPIRVLocationLoad(B, CGM.getModule(), Type, Location,
614 VariableName.str());
615}
616
617static void createSPIRVLocationStore(IRBuilder<> &B, llvm::Module &M,
618 llvm::Value *Source, unsigned Location,
619 StringRef Name) {
620 auto *GV = new llvm::GlobalVariable(
621 M, Source->getType(), /* isConstant= */ false,
622 llvm::GlobalValue::ExternalLinkage,
623 /* Initializer= */ nullptr, /* Name= */ Name, /* insertBefore= */ nullptr,
624 llvm::GlobalVariable::GeneralDynamicTLSModel,
625 /* AddressSpace */ 8, /* isExternallyInitialized= */ false);
626 GV->setVisibility(llvm::GlobalValue::HiddenVisibility);
627 addLocationDecoration(GV, Location);
628 B.CreateStore(Source, GV);
629}
630
631void CGHLSLRuntime::emitSPIRVUserSemanticStore(
632 llvm::IRBuilder<> &B, llvm::Value *Source,
633 const clang::DeclaratorDecl *Decl, HLSLAppliedSemanticAttr *Semantic,
634 std::optional<unsigned> Index) {
635 Twine BaseName = Twine(Semantic->getAttrName()->getName());
636 Twine VariableName = BaseName.concat(Twine(Index.value_or(0)));
637
638 unsigned Location = SPIRVLastAssignedOutputSemanticLocation;
639 if (auto *L = Decl->getAttr<HLSLVkLocationAttr>())
640 Location = L->getLocation();
641
642 // DXC completely ignores the semantic/index pair. Location are assigned from
643 // the first semantic to the last.
644 llvm::ArrayType *AT = dyn_cast<llvm::ArrayType>(Source->getType());
645 unsigned ElementCount = AT ? AT->getNumElements() : 1;
646 SPIRVLastAssignedOutputSemanticLocation += ElementCount;
647 createSPIRVLocationStore(B, CGM.getModule(), Source, Location,
648 VariableName.str());
649}
650
651llvm::Value *
652CGHLSLRuntime::emitDXILUserSemanticLoad(llvm::IRBuilder<> &B, llvm::Type *Type,
653 HLSLAppliedSemanticAttr *Semantic,
654 std::optional<unsigned> Index) {
655 Twine BaseName = Twine(Semantic->getAttrName()->getName());
656 Twine VariableName = BaseName.concat(Twine(Index.value_or(0)));
657
658 // DXIL packing rules etc shall be handled here.
659 // FIXME: generate proper sigpoint, index, col, row values.
660 // FIXME: also DXIL loads vectors element by element.
661 SmallVector<Value *> Args{B.getInt32(4), B.getInt32(0), B.getInt32(0),
662 B.getInt8(0),
663 llvm::PoisonValue::get(B.getInt32Ty())};
664
665 llvm::Intrinsic::ID IntrinsicID = llvm::Intrinsic::dx_load_input;
666 llvm::Value *Value = B.CreateIntrinsic(/*ReturnType=*/Type, IntrinsicID, Args,
667 nullptr, VariableName);
668 return Value;
669}
670
671void CGHLSLRuntime::emitDXILUserSemanticStore(llvm::IRBuilder<> &B,
672 llvm::Value *Source,
673 HLSLAppliedSemanticAttr *Semantic,
674 std::optional<unsigned> Index) {
675 // DXIL packing rules etc shall be handled here.
676 // FIXME: generate proper sigpoint, index, col, row values.
677 SmallVector<Value *> Args{B.getInt32(4),
678 B.getInt32(0),
679 B.getInt32(0),
680 B.getInt8(0),
681 llvm::PoisonValue::get(B.getInt32Ty()),
682 Source};
683
684 llvm::Intrinsic::ID IntrinsicID = llvm::Intrinsic::dx_store_output;
685 B.CreateIntrinsic(/*ReturnType=*/CGM.VoidTy, IntrinsicID, Args, nullptr);
686}
687
688llvm::Value *CGHLSLRuntime::emitUserSemanticLoad(
689 IRBuilder<> &B, llvm::Type *Type, const clang::DeclaratorDecl *Decl,
690 HLSLAppliedSemanticAttr *Semantic, std::optional<unsigned> Index) {
691 if (CGM.getTarget().getTriple().isSPIRV())
692 return emitSPIRVUserSemanticLoad(B, Type, Decl, Semantic, Index);
693
694 if (CGM.getTarget().getTriple().isDXIL())
695 return emitDXILUserSemanticLoad(B, Type, Semantic, Index);
696
697 llvm_unreachable("Unsupported target for user-semantic load.");
698}
699
700void CGHLSLRuntime::emitUserSemanticStore(IRBuilder<> &B, llvm::Value *Source,
701 const clang::DeclaratorDecl *Decl,
702 HLSLAppliedSemanticAttr *Semantic,
703 std::optional<unsigned> Index) {
704 if (CGM.getTarget().getTriple().isSPIRV())
705 return emitSPIRVUserSemanticStore(B, Source, Decl, Semantic, Index);
706
707 if (CGM.getTarget().getTriple().isDXIL())
708 return emitDXILUserSemanticStore(B, Source, Semantic, Index);
709
710 llvm_unreachable("Unsupported target for user-semantic load.");
711}
712
714 IRBuilder<> &B, const FunctionDecl *FD, llvm::Type *Type,
715 const clang::DeclaratorDecl *Decl, HLSLAppliedSemanticAttr *Semantic,
716 std::optional<unsigned> Index) {
717
718 std::string SemanticName = Semantic->getAttrName()->getName().upper();
719 if (SemanticName == "SV_GROUPINDEX") {
720 llvm::Function *GroupIndex =
721 CGM.getIntrinsic(getFlattenedThreadIdInGroupIntrinsic());
722 return B.CreateCall(FunctionCallee(GroupIndex));
723 }
724
725 if (SemanticName == "SV_DISPATCHTHREADID") {
726 llvm::Intrinsic::ID IntrinID = getThreadIdIntrinsic();
727 llvm::Function *ThreadIDIntrinsic =
728 llvm::Intrinsic::isOverloaded(IntrinID)
729 ? CGM.getIntrinsic(IntrinID, {CGM.Int32Ty})
730 : CGM.getIntrinsic(IntrinID);
731 return buildVectorInput(B, ThreadIDIntrinsic, Type);
732 }
733
734 if (SemanticName == "SV_GROUPTHREADID") {
735 llvm::Intrinsic::ID IntrinID = getGroupThreadIdIntrinsic();
736 llvm::Function *GroupThreadIDIntrinsic =
737 llvm::Intrinsic::isOverloaded(IntrinID)
738 ? CGM.getIntrinsic(IntrinID, {CGM.Int32Ty})
739 : CGM.getIntrinsic(IntrinID);
740 return buildVectorInput(B, GroupThreadIDIntrinsic, Type);
741 }
742
743 if (SemanticName == "SV_GROUPID") {
744 llvm::Intrinsic::ID IntrinID = getGroupIdIntrinsic();
745 llvm::Function *GroupIDIntrinsic =
746 llvm::Intrinsic::isOverloaded(IntrinID)
747 ? CGM.getIntrinsic(IntrinID, {CGM.Int32Ty})
748 : CGM.getIntrinsic(IntrinID);
749 return buildVectorInput(B, GroupIDIntrinsic, Type);
750 }
751
752 const auto *ShaderAttr = FD->getAttr<HLSLShaderAttr>();
753 assert(ShaderAttr && "Entry point has no shader attribute");
754 llvm::Triple::EnvironmentType ST = ShaderAttr->getType();
755
756 if (SemanticName == "SV_POSITION") {
757 if (ST == Triple::EnvironmentType::Pixel) {
758 if (CGM.getTarget().getTriple().isSPIRV())
759 return createSPIRVBuiltinLoad(B, CGM.getModule(), Type,
760 Semantic->getAttrName()->getName(),
761 /* BuiltIn::FragCoord */ 15);
762 if (CGM.getTarget().getTriple().isDXIL())
763 return emitDXILUserSemanticLoad(B, Type, Semantic, Index);
764 }
765
766 if (ST == Triple::EnvironmentType::Vertex) {
767 return emitUserSemanticLoad(B, Type, Decl, Semantic, Index);
768 }
769 }
770
771 llvm_unreachable(
772 "Load hasn't been implemented yet for this system semantic. FIXME");
773}
774
775static void createSPIRVBuiltinStore(IRBuilder<> &B, llvm::Module &M,
776 llvm::Value *Source, const Twine &Name,
777 unsigned BuiltInID) {
778 auto *GV = new llvm::GlobalVariable(
779 M, Source->getType(), /* isConstant= */ false,
780 llvm::GlobalValue::ExternalLinkage,
781 /* Initializer= */ nullptr, Name, /* insertBefore= */ nullptr,
782 llvm::GlobalVariable::GeneralDynamicTLSModel,
783 /* AddressSpace */ 8, /* isExternallyInitialized= */ false);
784 addSPIRVBuiltinDecoration(GV, BuiltInID);
785 GV->setVisibility(llvm::GlobalValue::HiddenVisibility);
786 B.CreateStore(Source, GV);
787}
788
789void CGHLSLRuntime::emitSystemSemanticStore(IRBuilder<> &B, llvm::Value *Source,
791 HLSLAppliedSemanticAttr *Semantic,
792 std::optional<unsigned> Index) {
793
794 std::string SemanticName = Semantic->getAttrName()->getName().upper();
795 if (SemanticName == "SV_POSITION") {
796 if (CGM.getTarget().getTriple().isDXIL()) {
797 emitDXILUserSemanticStore(B, Source, Semantic, Index);
798 return;
799 }
800
801 if (CGM.getTarget().getTriple().isSPIRV()) {
802 createSPIRVBuiltinStore(B, CGM.getModule(), Source,
803 Semantic->getAttrName()->getName(),
804 /* BuiltIn::Position */ 0);
805 return;
806 }
807 }
808
809 if (SemanticName == "SV_TARGET") {
810 emitUserSemanticStore(B, Source, Decl, Semantic, Index);
811 return;
812 }
813
814 llvm_unreachable(
815 "Store hasn't been implemented yet for this system semantic. FIXME");
816}
817
819 IRBuilder<> &B, const FunctionDecl *FD, llvm::Type *Type,
820 const clang::DeclaratorDecl *Decl, HLSLAppliedSemanticAttr *Semantic) {
821
822 std::optional<unsigned> Index = Semantic->getSemanticIndex();
823 if (Semantic->getAttrName()->getName().starts_with_insensitive("SV_"))
824 return emitSystemSemanticLoad(B, FD, Type, Decl, Semantic, Index);
825 return emitUserSemanticLoad(B, Type, Decl, Semantic, Index);
826}
827
829 IRBuilder<> &B, const FunctionDecl *FD, llvm::Value *Source,
830 const clang::DeclaratorDecl *Decl, HLSLAppliedSemanticAttr *Semantic) {
831 std::optional<unsigned> Index = Semantic->getSemanticIndex();
832 if (Semantic->getAttrName()->getName().starts_with_insensitive("SV_"))
833 emitSystemSemanticStore(B, Source, Decl, Semantic, Index);
834 else
835 emitUserSemanticStore(B, Source, Decl, Semantic, Index);
836}
837
838std::pair<llvm::Value *, specific_attr_iterator<HLSLAppliedSemanticAttr>>
840 IRBuilder<> &B, const FunctionDecl *FD, llvm::Type *Type,
844 const llvm::StructType *ST = cast<StructType>(Type);
845 const clang::RecordDecl *RD = Decl->getType()->getAsRecordDecl();
846
847 assert(RD->getNumFields() == ST->getNumElements());
848
849 llvm::Value *Aggregate = llvm::PoisonValue::get(Type);
850 auto FieldDecl = RD->field_begin();
851 for (unsigned I = 0; I < ST->getNumElements(); ++I) {
852 auto [ChildValue, NextAttr] = handleSemanticLoad(
853 B, FD, ST->getElementType(I), *FieldDecl, AttrBegin, AttrEnd);
854 AttrBegin = NextAttr;
855 assert(ChildValue);
856 Aggregate = B.CreateInsertValue(Aggregate, ChildValue, I);
857 ++FieldDecl;
858 }
859
860 return std::make_pair(Aggregate, AttrBegin);
861}
862
865 IRBuilder<> &B, const FunctionDecl *FD, llvm::Value *Source,
869
870 const llvm::StructType *ST = cast<StructType>(Source->getType());
871
872 const clang::RecordDecl *RD = nullptr;
873 if (const FunctionDecl *FD = dyn_cast<FunctionDecl>(Decl))
875 else
876 RD = Decl->getType()->getAsRecordDecl();
877 assert(RD);
878
879 assert(RD->getNumFields() == ST->getNumElements());
880
881 auto FieldDecl = RD->field_begin();
882 for (unsigned I = 0; I < ST->getNumElements(); ++I, ++FieldDecl) {
883 llvm::Value *Extract = B.CreateExtractValue(Source, I);
884 AttrBegin =
885 handleSemanticStore(B, FD, Extract, *FieldDecl, AttrBegin, AttrEnd);
886 }
887
888 return AttrBegin;
889}
890
891std::pair<llvm::Value *, specific_attr_iterator<HLSLAppliedSemanticAttr>>
893 IRBuilder<> &B, const FunctionDecl *FD, llvm::Type *Type,
897 assert(AttrBegin != AttrEnd);
898 if (Type->isStructTy())
899 return handleStructSemanticLoad(B, FD, Type, Decl, AttrBegin, AttrEnd);
900
901 HLSLAppliedSemanticAttr *Attr = *AttrBegin;
902 ++AttrBegin;
903 return std::make_pair(handleScalarSemanticLoad(B, FD, Type, Decl, Attr),
904 AttrBegin);
905}
906
909 IRBuilder<> &B, const FunctionDecl *FD, llvm::Value *Source,
913 assert(AttrBegin != AttrEnd);
914 if (Source->getType()->isStructTy())
915 return handleStructSemanticStore(B, FD, Source, Decl, AttrBegin, AttrEnd);
916
917 HLSLAppliedSemanticAttr *Attr = *AttrBegin;
918 ++AttrBegin;
919 handleScalarSemanticStore(B, FD, Source, Decl, Attr);
920 return AttrBegin;
921}
922
924 llvm::Function *Fn) {
925 llvm::Module &M = CGM.getModule();
926 llvm::LLVMContext &Ctx = M.getContext();
927 auto *EntryTy = llvm::FunctionType::get(llvm::Type::getVoidTy(Ctx), false);
928 Function *EntryFn =
929 Function::Create(EntryTy, Function::ExternalLinkage, FD->getName(), &M);
930
931 // Copy function attributes over, we have no argument or return attributes
932 // that can be valid on the real entry.
933 AttributeList NewAttrs = AttributeList::get(Ctx, AttributeList::FunctionIndex,
934 Fn->getAttributes().getFnAttrs());
935 EntryFn->setAttributes(NewAttrs);
936 setHLSLEntryAttributes(FD, EntryFn);
937
938 // Set the called function as internal linkage.
939 Fn->setLinkage(GlobalValue::InternalLinkage);
940
941 BasicBlock *BB = BasicBlock::Create(Ctx, "entry", EntryFn);
942 IRBuilder<> B(BB);
944
946 if (CGM.shouldEmitConvergenceTokens()) {
947 assert(EntryFn->isConvergent());
948 llvm::Value *I =
949 B.CreateIntrinsic(llvm::Intrinsic::experimental_convergence_entry, {});
950 llvm::Value *bundleArgs[] = {I};
951 OB.emplace_back("convergencectrl", bundleArgs);
952 }
953
954 llvm::DenseMap<const DeclaratorDecl *, std::pair<llvm::Value *, llvm::Type *>>
955 OutputSemantic;
956
957 unsigned SRetOffset = 0;
958 for (const auto &Param : Fn->args()) {
959 if (Param.hasStructRetAttr()) {
960 SRetOffset = 1;
961 llvm::Type *VarType = Param.getParamStructRetType();
962 llvm::Value *Var = B.CreateAlloca(VarType);
963 OutputSemantic.try_emplace(FD, std::make_pair(Var, VarType));
964 Args.push_back(Var);
965 continue;
966 }
967
968 const ParmVarDecl *PD = FD->getParamDecl(Param.getArgNo() - SRetOffset);
969 llvm::Value *SemanticValue = nullptr;
970 // FIXME: support inout/out parameters for semantics.
971 if ([[maybe_unused]] HLSLParamModifierAttr *MA =
972 PD->getAttr<HLSLParamModifierAttr>()) {
973 llvm_unreachable("Not handled yet");
974 } else {
975 llvm::Type *ParamType =
976 Param.hasByValAttr() ? Param.getParamByValType() : Param.getType();
977 auto AttrBegin = PD->specific_attr_begin<HLSLAppliedSemanticAttr>();
978 auto AttrEnd = PD->specific_attr_end<HLSLAppliedSemanticAttr>();
979 auto Result =
980 handleSemanticLoad(B, FD, ParamType, PD, AttrBegin, AttrEnd);
981 SemanticValue = Result.first;
982 if (!SemanticValue)
983 return;
984 if (Param.hasByValAttr()) {
985 llvm::Value *Var = B.CreateAlloca(Param.getParamByValType());
986 B.CreateStore(SemanticValue, Var);
987 SemanticValue = Var;
988 }
989 }
990
991 assert(SemanticValue);
992 Args.push_back(SemanticValue);
993 }
994
995 CallInst *CI = B.CreateCall(FunctionCallee(Fn), Args, OB);
996 CI->setCallingConv(Fn->getCallingConv());
997
998 if (Fn->getReturnType() != CGM.VoidTy)
999 // Element type is unused, so set to dummy value (NULL).
1000 OutputSemantic.try_emplace(FD, std::make_pair(CI, nullptr));
1001
1002 for (auto &[Decl, SourcePair] : OutputSemantic) {
1003 llvm::Value *Source = SourcePair.first;
1004 llvm::Type *ElementType = SourcePair.second;
1005 AllocaInst *AI = dyn_cast<AllocaInst>(Source);
1006 llvm::Value *SourceValue = AI ? B.CreateLoad(ElementType, Source) : Source;
1007
1008 auto AttrBegin = Decl->specific_attr_begin<HLSLAppliedSemanticAttr>();
1009 auto AttrEnd = Decl->specific_attr_end<HLSLAppliedSemanticAttr>();
1010 handleSemanticStore(B, FD, SourceValue, Decl, AttrBegin, AttrEnd);
1011 }
1012
1013 B.CreateRetVoid();
1014
1015 // Add and identify root signature to function, if applicable
1016 for (const Attr *Attr : FD->getAttrs()) {
1017 if (const auto *RSAttr = dyn_cast<RootSignatureAttr>(Attr)) {
1018 auto *RSDecl = RSAttr->getSignatureDecl();
1019 addRootSignatureMD(RSDecl->getVersion(), RSDecl->getRootElements(),
1020 EntryFn, M);
1021 }
1022 }
1023}
1024
1025static void gatherFunctions(SmallVectorImpl<Function *> &Fns, llvm::Module &M,
1026 bool CtorOrDtor) {
1027 const auto *GV =
1028 M.getNamedGlobal(CtorOrDtor ? "llvm.global_ctors" : "llvm.global_dtors");
1029 if (!GV)
1030 return;
1031 const auto *CA = dyn_cast<ConstantArray>(GV->getInitializer());
1032 if (!CA)
1033 return;
1034 // The global_ctor array elements are a struct [Priority, Fn *, COMDat].
1035 // HLSL neither supports priorities or COMDat values, so we will check those
1036 // in an assert but not handle them.
1037
1038 for (const auto &Ctor : CA->operands()) {
1040 continue;
1041 ConstantStruct *CS = cast<ConstantStruct>(Ctor);
1042
1043 assert(cast<ConstantInt>(CS->getOperand(0))->getValue() == 65535 &&
1044 "HLSL doesn't support setting priority for global ctors.");
1045 assert(isa<ConstantPointerNull>(CS->getOperand(2)) &&
1046 "HLSL doesn't support COMDat for global ctors.");
1047 Fns.push_back(cast<Function>(CS->getOperand(1)));
1048 }
1049}
1050
1052 llvm::Module &M = CGM.getModule();
1055 gatherFunctions(CtorFns, M, true);
1056 gatherFunctions(DtorFns, M, false);
1057
1058 // Insert a call to the global constructor at the beginning of the entry block
1059 // to externally exported functions. This is a bit of a hack, but HLSL allows
1060 // global constructors, but doesn't support driver initialization of globals.
1061 for (auto &F : M.functions()) {
1062 if (!F.hasFnAttribute("hlsl.shader"))
1063 continue;
1064 auto *Token = getConvergenceToken(F.getEntryBlock());
1065 Instruction *IP = &*F.getEntryBlock().begin();
1067 if (Token) {
1068 llvm::Value *bundleArgs[] = {Token};
1069 OB.emplace_back("convergencectrl", bundleArgs);
1070 IP = Token->getNextNode();
1071 }
1072 IRBuilder<> B(IP);
1073 for (auto *Fn : CtorFns) {
1074 auto CI = B.CreateCall(FunctionCallee(Fn), {}, OB);
1075 CI->setCallingConv(Fn->getCallingConv());
1076 }
1077
1078 // Insert global dtors before the terminator of the last instruction
1079 B.SetInsertPoint(F.back().getTerminator());
1080 for (auto *Fn : DtorFns) {
1081 auto CI = B.CreateCall(FunctionCallee(Fn), {}, OB);
1082 CI->setCallingConv(Fn->getCallingConv());
1083 }
1084 }
1085
1086 // No need to keep global ctors/dtors for non-lib profile after call to
1087 // ctors/dtors added for entry.
1088 Triple T(M.getTargetTriple());
1089 if (T.getEnvironment() != Triple::EnvironmentType::Library) {
1090 if (auto *GV = M.getNamedGlobal("llvm.global_ctors"))
1091 GV->eraseFromParent();
1092 if (auto *GV = M.getNamedGlobal("llvm.global_dtors"))
1093 GV->eraseFromParent();
1094 }
1095}
1096
1097static void initializeBuffer(CodeGenModule &CGM, llvm::GlobalVariable *GV,
1098 Intrinsic::ID IntrID,
1100
1101 LLVMContext &Ctx = CGM.getLLVMContext();
1102 llvm::Function *InitResFunc = llvm::Function::Create(
1103 llvm::FunctionType::get(CGM.VoidTy, false),
1104 llvm::GlobalValue::InternalLinkage,
1105 ("_init_buffer_" + GV->getName()).str(), CGM.getModule());
1106 InitResFunc->addFnAttr(llvm::Attribute::AlwaysInline);
1107
1108 llvm::BasicBlock *EntryBB =
1109 llvm::BasicBlock::Create(Ctx, "entry", InitResFunc);
1110 CGBuilderTy Builder(CGM, Ctx);
1111 const DataLayout &DL = CGM.getModule().getDataLayout();
1112 Builder.SetInsertPoint(EntryBB);
1113
1114 // Make sure the global variable is buffer resource handle
1115 llvm::Type *HandleTy = GV->getValueType();
1116 assert(HandleTy->isTargetExtTy() && "unexpected type of the buffer global");
1117
1118 llvm::Value *CreateHandle = Builder.CreateIntrinsic(
1119 /*ReturnType=*/HandleTy, IntrID, Args, nullptr,
1120 Twine(GV->getName()).concat("_h"));
1121
1122 Builder.CreateAlignedStore(CreateHandle, GV, GV->getPointerAlignment(DL));
1123 Builder.CreateRetVoid();
1124
1125 CGM.AddCXXGlobalInit(InitResFunc);
1126}
1127
1128void CGHLSLRuntime::initializeBufferFromBinding(const HLSLBufferDecl *BufDecl,
1129 llvm::GlobalVariable *GV) {
1130 ResourceBindingAttrs Binding(BufDecl);
1131 assert(Binding.hasBinding() &&
1132 "cbuffer/tbuffer should always have resource binding attribute");
1133
1134 auto *Index = llvm::ConstantInt::get(CGM.IntTy, 0);
1135 auto *RangeSize = llvm::ConstantInt::get(CGM.IntTy, 1);
1136 auto *Space = llvm::ConstantInt::get(CGM.IntTy, Binding.getSpace());
1137 Value *Name = buildNameForResource(BufDecl->getName(), CGM);
1138
1139 // buffer with explicit binding
1140 if (Binding.isExplicit()) {
1141 llvm::Intrinsic::ID IntrinsicID =
1142 CGM.getHLSLRuntime().getCreateHandleFromBindingIntrinsic();
1143 auto *RegSlot = llvm::ConstantInt::get(CGM.IntTy, Binding.getSlot());
1144 SmallVector<Value *> Args{Space, RegSlot, RangeSize, Index, Name};
1145 initializeBuffer(CGM, GV, IntrinsicID, Args);
1146 } else {
1147 // buffer with implicit binding
1148 llvm::Intrinsic::ID IntrinsicID =
1149 CGM.getHLSLRuntime().getCreateHandleFromImplicitBindingIntrinsic();
1150 auto *OrderID =
1151 llvm::ConstantInt::get(CGM.IntTy, Binding.getImplicitOrderID());
1152 SmallVector<Value *> Args{OrderID, Space, RangeSize, Index, Name};
1153 initializeBuffer(CGM, GV, IntrinsicID, Args);
1154 }
1155}
1156
1158 llvm::GlobalVariable *GV) {
1159 if (auto Attr = VD->getAttr<HLSLVkExtBuiltinInputAttr>())
1160 addSPIRVBuiltinDecoration(GV, Attr->getBuiltIn());
1161}
1162
1163llvm::Instruction *CGHLSLRuntime::getConvergenceToken(BasicBlock &BB) {
1164 if (!CGM.shouldEmitConvergenceTokens())
1165 return nullptr;
1166
1167 auto E = BB.end();
1168 for (auto I = BB.begin(); I != E; ++I) {
1169 auto *II = dyn_cast<llvm::IntrinsicInst>(&*I);
1170 if (II && llvm::isConvergenceControlIntrinsic(II->getIntrinsicID())) {
1171 return II;
1172 }
1173 }
1174 llvm_unreachable("Convergence token should have been emitted.");
1175 return nullptr;
1176}
1177
1178class OpaqueValueVisitor : public RecursiveASTVisitor<OpaqueValueVisitor> {
1179public:
1183
1185 // These need to be bound in CodeGenFunction::EmitHLSLOutArgLValues
1186 // or CodeGenFunction::EmitHLSLOutArgExpr. If they are part of this
1187 // traversal, the temporary containing the copy out will not have
1188 // been created yet.
1189 return false;
1190 }
1191
1193 // Traverse the source expression first.
1194 if (E->getSourceExpr())
1196
1197 // Then add this OVE if we haven't seen it before.
1198 if (Visited.insert(E).second)
1199 OVEs.push_back(E);
1200
1201 return true;
1202 }
1203};
1204
1206 InitListExpr *E) {
1207
1208 typedef CodeGenFunction::OpaqueValueMappingData OpaqueValueMappingData;
1209 OpaqueValueVisitor Visitor;
1210 Visitor.TraverseStmt(E);
1211 for (auto *OVE : Visitor.OVEs) {
1212 if (CGF.isOpaqueValueEmitted(OVE))
1213 continue;
1214 if (OpaqueValueMappingData::shouldBindAsLValue(OVE)) {
1215 LValue LV = CGF.EmitLValue(OVE->getSourceExpr());
1216 OpaqueValueMappingData::bind(CGF, OVE, LV);
1217 } else {
1218 RValue RV = CGF.EmitAnyExpr(OVE->getSourceExpr());
1219 OpaqueValueMappingData::bind(CGF, OVE, RV);
1220 }
1221 }
1222}
1223
1225 const ArraySubscriptExpr *ArraySubsExpr, CodeGenFunction &CGF) {
1226 assert((ArraySubsExpr->getType()->isHLSLResourceRecord() ||
1227 ArraySubsExpr->getType()->isHLSLResourceRecordArray()) &&
1228 "expected resource array subscript expression");
1229
1230 // Let clang codegen handle local and static resource array subscripts,
1231 // or when the subscript references on opaque expression (as part of
1232 // ArrayInitLoopExpr AST node).
1233 const VarDecl *ArrayDecl =
1234 dyn_cast_or_null<VarDecl>(getArrayDecl(ArraySubsExpr));
1235 if (!ArrayDecl || !ArrayDecl->hasGlobalStorage() ||
1236 ArrayDecl->getStorageClass() == SC_Static)
1237 return std::nullopt;
1238
1239 // get the resource array type
1240 ASTContext &AST = ArrayDecl->getASTContext();
1241 const Type *ResArrayTy = ArrayDecl->getType().getTypePtr();
1242 assert(ResArrayTy->isHLSLResourceRecordArray() &&
1243 "expected array of resource classes");
1244
1245 // Iterate through all nested array subscript expressions to calculate
1246 // the index in the flattened resource array (if this is a multi-
1247 // dimensional array). The index is calculated as a sum of all indices
1248 // multiplied by the total size of the array at that level.
1249 Value *Index = nullptr;
1250 const ArraySubscriptExpr *ASE = ArraySubsExpr;
1251 while (ASE != nullptr) {
1252 Value *SubIndex = CGF.EmitScalarExpr(ASE->getIdx());
1253 if (const auto *ArrayTy =
1254 dyn_cast<ConstantArrayType>(ASE->getType().getTypePtr())) {
1255 Value *Multiplier = llvm::ConstantInt::get(
1256 CGM.IntTy, AST.getConstantArrayElementCount(ArrayTy));
1257 SubIndex = CGF.Builder.CreateMul(SubIndex, Multiplier);
1258 }
1259 Index = Index ? CGF.Builder.CreateAdd(Index, SubIndex) : SubIndex;
1260 ASE = dyn_cast<ArraySubscriptExpr>(ASE->getBase()->IgnoreParenImpCasts());
1261 }
1262
1263 // Find binding info for the resource array. For implicit binding
1264 // an HLSLResourceBindingAttr should have been added by SemaHLSL.
1265 ResourceBindingAttrs Binding(ArrayDecl);
1266 assert(Binding.hasBinding() &&
1267 "resource array must have a binding attribute");
1268
1269 // Find the individual resource type.
1270 QualType ResultTy = ArraySubsExpr->getType();
1271 QualType ResourceTy =
1272 ResultTy->isArrayType() ? AST.getBaseElementType(ResultTy) : ResultTy;
1273
1274 // Create a temporary variable for the result, which is either going
1275 // to be a single resource instance or a local array of resources (we need to
1276 // return an LValue).
1277 RawAddress TmpVar = CGF.CreateMemTemp(ResultTy);
1278 if (CGF.EmitLifetimeStart(TmpVar.getPointer()))
1280 NormalEHLifetimeMarker, TmpVar);
1281
1286
1287 // Calculate total array size (= range size).
1288 llvm::Value *Range = llvm::ConstantInt::getSigned(
1289 CGM.IntTy, getTotalArraySize(AST, ResArrayTy));
1290
1291 // If the result of the subscript operation is a single resource, call the
1292 // constructor.
1293 if (ResultTy == ResourceTy) {
1294 CallArgList Args;
1295 CXXMethodDecl *CreateMethod = lookupResourceInitMethodAndSetupArgs(
1296 CGF.CGM, ResourceTy->getAsCXXRecordDecl(), Range, Index,
1297 ArrayDecl->getName(), Binding, Args);
1298
1299 if (!CreateMethod)
1300 // This can happen if someone creates an array of structs that looks like
1301 // an HLSL resource record array but it does not have the required static
1302 // create method. No binding will be generated for it.
1303 return std::nullopt;
1304
1305 callResourceInitMethod(CGF, CreateMethod, Args, ValueSlot.getAddress());
1306
1307 } else {
1308 // The result of the subscript operation is a local resource array which
1309 // needs to be initialized.
1310 const ConstantArrayType *ArrayTy =
1312 std::optional<llvm::Value *> EndIndex = initializeLocalResourceArray(
1313 CGF, ResourceTy->getAsCXXRecordDecl(), ArrayTy, ValueSlot, Range, Index,
1314 ArrayDecl->getName(), Binding, {llvm::ConstantInt::get(CGM.IntTy, 0)},
1315 ArraySubsExpr->getExprLoc());
1316 if (!EndIndex)
1317 return std::nullopt;
1318 }
1319 return CGF.MakeAddrLValue(TmpVar, ResultTy, AlignmentSource::Decl);
1320}
1321
1322// If RHSExpr is a global resource array, initialize all of its resources and
1323// set them into LHS. Returns false if no copy has been performed and the
1324// array copy should be handled by Clang codegen.
1326 CodeGenFunction &CGF) {
1327 QualType ResultTy = RHSExpr->getType();
1328 assert(ResultTy->isHLSLResourceRecordArray() && "expected resource array");
1329
1330 // Let Clang codegen handle local and static resource array copies.
1331 const VarDecl *ArrayDecl = dyn_cast_or_null<VarDecl>(getArrayDecl(RHSExpr));
1332 if (!ArrayDecl || !ArrayDecl->hasGlobalStorage() ||
1333 ArrayDecl->getStorageClass() == SC_Static)
1334 return false;
1335
1336 // Find binding info for the resource array. For implicit binding
1337 // the HLSLResourceBindingAttr should have been added by SemaHLSL.
1338 ResourceBindingAttrs Binding(ArrayDecl);
1339 assert(Binding.hasBinding() &&
1340 "resource array must have a binding attribute");
1341
1342 // Find the individual resource type.
1343 ASTContext &AST = ArrayDecl->getASTContext();
1344 QualType ResTy = AST.getBaseElementType(ResultTy);
1345 const auto *ResArrayTy = cast<ConstantArrayType>(ResultTy.getTypePtr());
1346
1347 // Use the provided LHS for the result.
1352
1353 // Create Value for index and total array size (= range size).
1354 int Size = getTotalArraySize(AST, ResArrayTy);
1355 llvm::Value *Zero = llvm::ConstantInt::get(CGM.IntTy, 0);
1356 llvm::Value *Range = llvm::ConstantInt::get(CGM.IntTy, Size);
1357
1358 // Initialize individual resources in the array into LHS.
1359 std::optional<llvm::Value *> EndIndex = initializeLocalResourceArray(
1360 CGF, ResTy->getAsCXXRecordDecl(), ResArrayTy, ValueSlot, Range, Zero,
1361 ArrayDecl->getName(), Binding, {Zero}, RHSExpr->getExprLoc());
1362 return EndIndex.has_value();
1363}
1364
1366 SourceLocation Loc,
1367 CodeGenFunction &CGF) {
1368
1369 assert(LV.getType()->isConstantMatrixType() && "expected matrix type");
1371 "expected cbuffer matrix");
1372
1373 QualType MatQualTy = LV.getType();
1374 llvm::Type *MemTy = CGF.ConvertTypeForMem(MatQualTy);
1375 llvm::Type *LayoutTy = HLSLBufferLayoutBuilder(CGF.CGM).layOutType(MatQualTy);
1376
1377 if (LayoutTy == MemTy)
1378 return LV.getAddress();
1379
1380 Address SrcAddr = LV.getAddress();
1381 // NOTE: B\C CreateMemTemp flattens MatrixTypes which causes
1382 // overlapping GEPs in emitBufferCopy. Use CreateTempAlloca with
1383 // the non-padded layout.
1384 CharUnits Align =
1385 CharUnits::fromQuantity(CGF.CGM.getDataLayout().getABITypeAlign(MemTy));
1386 RawAddress DestAlloca = CGF.CreateTempAlloca(MemTy, Align, "matrix.buf.copy");
1387 emitBufferCopy(CGF, DestAlloca, SrcAddr, MatQualTy);
1388 return DestAlloca;
1389}
1390
1392 const ArraySubscriptExpr *E, CodeGenFunction &CGF,
1393 llvm::function_ref<llvm::Value *(bool Promote)> EmitIdxAfterBase) {
1394 // Find the element type to index by first padding the element type per HLSL
1395 // buffer rules, and then padding out to a 16-byte register boundary if
1396 // necessary.
1397 llvm::Type *LayoutTy =
1399 uint64_t LayoutSizeInBits =
1400 CGM.getDataLayout().getTypeSizeInBits(LayoutTy).getFixedValue();
1401 CharUnits ElementSize = CharUnits::fromQuantity(LayoutSizeInBits / 8);
1402 CharUnits RowAlignedSize = ElementSize.alignTo(CharUnits::fromQuantity(16));
1403 if (RowAlignedSize > ElementSize) {
1404 llvm::Type *Padding = CGM.getTargetCodeGenInfo().getHLSLPadding(
1405 CGM, RowAlignedSize - ElementSize);
1406 assert(Padding && "No padding type for target?");
1407 LayoutTy = llvm::StructType::get(CGF.getLLVMContext(), {LayoutTy, Padding},
1408 /*isPacked=*/true);
1409 }
1410
1411 // If the layout type doesn't introduce any padding, we don't need to do
1412 // anything special.
1413 llvm::Type *OrigTy = CGF.CGM.getTypes().ConvertTypeForMem(E->getType());
1414 if (LayoutTy == OrigTy)
1415 return std::nullopt;
1416
1417 LValueBaseInfo EltBaseInfo;
1418 TBAAAccessInfo EltTBAAInfo;
1419
1420 // Index into the object as-if we have an array of the padded element type,
1421 // and then dereference the element itself to avoid reading padding that may
1422 // be past the end of the in-memory object.
1424 llvm::Value *Idx = EmitIdxAfterBase(/*Promote*/ true);
1425 Indices.push_back(Idx);
1426 Indices.push_back(llvm::ConstantInt::get(CGF.Int32Ty, 0));
1427
1428 if (CGF.getLangOpts().EmitStructuredGEP) {
1429 // The fact that we emit an array-to-pointer decay might be an oversight,
1430 // but for now, we simply ignore it (see #179951).
1431 const CastExpr *CE = cast<CastExpr>(E->getBase());
1432 assert(CE->getCastKind() == CastKind::CK_ArrayToPointerDecay);
1433
1434 LValue LV = CGF.EmitLValue(CE->getSubExpr());
1435 Address Addr = LV.getAddress();
1436 LayoutTy = llvm::ArrayType::get(
1437 LayoutTy,
1438 cast<llvm::ArrayType>(Addr.getElementType())->getNumElements());
1439 auto *GEP = cast<StructuredGEPInst>(CGF.Builder.CreateStructuredGEP(
1440 LayoutTy, Addr.emitRawPointer(CGF), Indices, "cbufferidx"));
1441 Addr =
1442 Address(GEP, GEP->getResultElementType(), RowAlignedSize, KnownNonNull);
1443 return CGF.MakeAddrLValue(Addr, E->getType(), EltBaseInfo, EltTBAAInfo);
1444 }
1445
1446 Address Addr =
1447 CGF.EmitPointerWithAlignment(E->getBase(), &EltBaseInfo, &EltTBAAInfo);
1448 llvm::Value *GEP = CGF.Builder.CreateGEP(LayoutTy, Addr.emitRawPointer(CGF),
1449 Indices, "cbufferidx");
1450 Addr = Address(GEP, Addr.getElementType(), RowAlignedSize, KnownNonNull);
1451 return CGF.MakeAddrLValue(Addr, E->getType(), EltBaseInfo, EltTBAAInfo);
1452}
1453
1454namespace {
1455/// Utility for emitting copies following the HLSL buffer layout rules (ie,
1456/// copying out of a cbuffer).
1457class HLSLBufferCopyEmitter {
1458 CodeGenFunction &CGF;
1459 Address DestPtr;
1460 Address SrcPtr;
1461 llvm::Type *LayoutTy = nullptr;
1462
1463 SmallVector<llvm::Value *> CurStoreIndices;
1464 SmallVector<llvm::Value *> CurLoadIndices;
1465
1466 void emitCopyAtIndices(llvm::Type *FieldTy, llvm::ConstantInt *StoreIndex,
1467 llvm::ConstantInt *LoadIndex) {
1468 CurStoreIndices.push_back(StoreIndex);
1469 CurLoadIndices.push_back(LoadIndex);
1470 llvm::scope_exit RestoreIndices([&]() {
1471 CurStoreIndices.pop_back();
1472 CurLoadIndices.pop_back();
1473 });
1474
1475 // First, see if this is some kind of aggregate and recurse.
1476 if (processArray(FieldTy))
1477 return;
1478 if (processBufferLayoutArray(FieldTy))
1479 return;
1480 if (processStruct(FieldTy))
1481 return;
1482
1483 // When we have a scalar or vector element we can emit the copy.
1485 CGF.CGM.getDataLayout().getABITypeAlign(FieldTy));
1486 Address SrcGEP = RawAddress(
1487 CGF.Builder.CreateInBoundsGEP(LayoutTy, SrcPtr.getBasePointer(),
1488 CurLoadIndices, "cbuf.src"),
1489 FieldTy, Align, SrcPtr.isKnownNonNull());
1490 Address DestGEP = CGF.Builder.CreateInBoundsGEP(
1491 DestPtr, CurStoreIndices, FieldTy, Align, "cbuf.dest");
1492 llvm::Value *Load = CGF.Builder.CreateLoad(SrcGEP, "cbuf.load");
1493 CGF.Builder.CreateStore(Load, DestGEP);
1494 }
1495
1496 bool processArray(llvm::Type *FieldTy) {
1497 auto *AT = dyn_cast<llvm::ArrayType>(FieldTy);
1498 if (!AT)
1499 return false;
1500
1501 // If we have an llvm::ArrayType this is just a regular array with no top
1502 // level padding, so all we need to do is copy each member.
1503 for (unsigned I = 0, E = AT->getNumElements(); I < E; ++I)
1504 emitCopyAtIndices(AT->getElementType(),
1505 llvm::ConstantInt::get(CGF.SizeTy, I),
1506 llvm::ConstantInt::get(CGF.SizeTy, I));
1507 return true;
1508 }
1509
1510 bool processBufferLayoutArray(llvm::Type *FieldTy) {
1511 // A buffer layout array is a struct with two elements: the padded array,
1512 // and the last element. That is, is should look something like this:
1513 //
1514 // { [%n x { %type, %padding }], %type }
1515 //
1516 auto *ST = dyn_cast<llvm::StructType>(FieldTy);
1517 if (!ST || ST->getNumElements() != 2)
1518 return false;
1519
1520 auto *PaddedEltsTy = dyn_cast<llvm::ArrayType>(ST->getElementType(0));
1521 if (!PaddedEltsTy)
1522 return false;
1523
1524 auto *PaddedTy = dyn_cast<llvm::StructType>(PaddedEltsTy->getElementType());
1525 if (!PaddedTy || PaddedTy->getNumElements() != 2)
1526 return false;
1527
1529 PaddedTy->getElementType(1)))
1530 return false;
1531
1532 llvm::Type *ElementTy = ST->getElementType(1);
1533 if (PaddedTy->getElementType(0) != ElementTy)
1534 return false;
1535
1536 // All but the last of the logical array elements are in the padded array.
1537 unsigned NumElts = PaddedEltsTy->getNumElements() + 1;
1538
1539 // Add an extra indirection to the load for the struct and walk the
1540 // array prefix.
1541 CurLoadIndices.push_back(llvm::ConstantInt::get(CGF.Int32Ty, 0));
1542 for (unsigned I = 0; I < NumElts - 1; ++I) {
1543 // We need to copy the element itself, without the padding.
1544 CurLoadIndices.push_back(llvm::ConstantInt::get(CGF.SizeTy, I));
1545 emitCopyAtIndices(ElementTy, llvm::ConstantInt::get(CGF.SizeTy, I),
1546 llvm::ConstantInt::get(CGF.Int32Ty, 0));
1547 CurLoadIndices.pop_back();
1548 }
1549 CurLoadIndices.pop_back();
1550
1551 // Now copy the last element.
1552 emitCopyAtIndices(ElementTy,
1553 llvm::ConstantInt::get(CGF.SizeTy, NumElts - 1),
1554 llvm::ConstantInt::get(CGF.Int32Ty, 1));
1555
1556 return true;
1557 }
1558
1559 bool processStruct(llvm::Type *FieldTy) {
1560 auto *ST = dyn_cast<llvm::StructType>(FieldTy);
1561 if (!ST)
1562 return false;
1563
1564 // Copy the struct field by field, but skip any explicit padding.
1565 unsigned Skipped = 0;
1566 for (unsigned I = 0, E = ST->getNumElements(); I < E; ++I) {
1567 llvm::Type *ElementTy = ST->getElementType(I);
1568 if (CGF.CGM.getTargetCodeGenInfo().isHLSLPadding(ElementTy))
1569 ++Skipped;
1570 else
1571 emitCopyAtIndices(ElementTy, llvm::ConstantInt::get(CGF.Int32Ty, I),
1572 llvm::ConstantInt::get(CGF.Int32Ty, I + Skipped));
1573 }
1574 return true;
1575 }
1576
1577public:
1578 HLSLBufferCopyEmitter(CodeGenFunction &CGF, Address DestPtr, Address SrcPtr)
1579 : CGF(CGF), DestPtr(DestPtr), SrcPtr(SrcPtr) {}
1580
1581 bool emitCopy(QualType CType) {
1582 LayoutTy = HLSLBufferLayoutBuilder(CGF.CGM).layOutType(CType);
1583
1584 // TODO: We should be able to fall back to a regular memcpy if the layout
1585 // type doesn't have any padding, but that runs into issues in the backend
1586 // currently.
1587 //
1588 // See https://github.com/llvm/wg-hlsl/issues/351
1589 emitCopyAtIndices(LayoutTy, llvm::ConstantInt::get(CGF.SizeTy, 0),
1590 llvm::ConstantInt::get(CGF.SizeTy, 0));
1591 return true;
1592 }
1593};
1594} // namespace
1595
1597 Address SrcPtr, QualType CType) {
1598 return HLSLBufferCopyEmitter(CGF, DestPtr, SrcPtr).emitCopy(CType);
1599}
1600
1602 const MemberExpr *E) {
1603 LValue Base =
1605 auto *Field = dyn_cast<FieldDecl>(E->getMemberDecl());
1606 assert(Field && "Unexpected access into HLSL buffer");
1607
1608 const RecordDecl *Rec = Field->getParent();
1609
1610 // Work out the buffer layout type to index into.
1611 QualType RecType = CGM.getContext().getCanonicalTagType(Rec);
1612 assert(RecType->isStructureOrClassType() && "Invalid type in HLSL buffer");
1613 // Since this is a member of an object in the buffer and not the buffer's
1614 // struct/class itself, we shouldn't have any offsets on the members we need
1615 // to contend with.
1616 CGHLSLOffsetInfo EmptyOffsets;
1617 llvm::StructType *LayoutTy = HLSLBufferLayoutBuilder(CGM).layOutStruct(
1618 RecType->getAsCanonical<RecordType>(), EmptyOffsets);
1619
1620 // Get the field index for the layout struct, accounting for padding.
1621 unsigned FieldIdx =
1622 CGM.getTypes().getCGRecordLayout(Rec).getLLVMFieldNo(Field);
1623 assert(FieldIdx < LayoutTy->getNumElements() &&
1624 "Layout struct is smaller than member struct");
1625 unsigned Skipped = 0;
1626 for (unsigned I = 0; I <= FieldIdx;) {
1627 llvm::Type *ElementTy = LayoutTy->getElementType(I + Skipped);
1628 if (CGF.CGM.getTargetCodeGenInfo().isHLSLPadding(ElementTy))
1629 ++Skipped;
1630 else
1631 ++I;
1632 }
1633 FieldIdx += Skipped;
1634 assert(FieldIdx < LayoutTy->getNumElements() && "Access out of bounds");
1635
1636 // Now index into the struct, making sure that the type we return is the
1637 // buffer layout type rather than the original type in the AST.
1638 QualType FieldType = Field->getType();
1639 llvm::Type *FieldLLVMTy = CGM.getTypes().ConvertTypeForMem(FieldType);
1641 CGF.CGM.getDataLayout().getABITypeAlign(FieldLLVMTy));
1642
1643 Value *Ptr = CGF.getLangOpts().EmitStructuredGEP
1644 ? CGF.Builder.CreateStructuredGEP(
1645 LayoutTy, Base.getPointer(CGF),
1646 llvm::ConstantInt::get(CGM.IntTy, FieldIdx))
1647 : CGF.Builder.CreateStructGEP(LayoutTy, Base.getPointer(CGF),
1648 FieldIdx, Field->getName());
1649 Address Addr(Ptr, FieldLLVMTy, Align, KnownNonNull);
1650
1651 LValue LV = LValue::MakeAddr(Addr, FieldType, CGM.getContext(),
1653 CGM.getTBAAAccessInfo(FieldType));
1654 LV.getQuals().addCVRQualifiers(Base.getVRQualifiers());
1655
1656 return LV;
1657}
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)
llvm::MachO::Record Record
Definition MachO.h:31
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:226
QualType getPointerType(QualType T) const
Return the uniqued reference to the type for a pointer to the specified type.
QualType getBaseElementType(const ArrayType *VAT) const
Return the innermost element type of an array type.
CanQualType CharTy
CanQualType IntTy
uint64_t getTypeSize(QualType T) const
Return the size of the specified (complete) type T, in bits.
CharUnits getTypeSizeInChars(QualType T) const
Return the size of the specified (complete) type T, in characters.
CanQualType UnsignedIntTy
QualType getHLSLAttributedResourceType(QualType Wrapped, QualType Contained, const HLSLAttributedResourceType::Attributes &Attrs)
uint64_t getConstantArrayElementCount(const ConstantArrayType *CA) const
Return number of constant array elements.
CanQualType getCanonicalTagType(const TagDecl *TD) const
ArraySubscriptExpr - [C99 6.5.2.1] Array Subscripting.
Definition Expr.h:2724
SourceLocation getExprLoc() const LLVM_READONLY
Definition Expr.h:2779
QualType getElementType() const
Definition TypeBase.h:3742
Attr - This represents one attribute.
Definition Attr.h:46
Represents a static or instance method of a struct/union/class.
Definition DeclCXX.h:2136
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:3679
CastKind getCastKind() const
Definition Expr.h:3723
Expr * getSubExpr()
Definition Expr.h:3729
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
llvm::Value * getBasePointer() const
Definition Address.h:198
CharUnits getAlignment() const
Definition Address.h:194
KnownNonNull_t isKnownNonNull() const
Whether the pointer is known not to be null.
Definition Address.h:233
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
llvm::LoadInst * CreateLoad(Address Addr, const llvm::Twine &Name="")
Definition CGBuilder.h:118
Address CreateInBoundsGEP(Address Addr, ArrayRef< llvm::Value * > IdxList, llvm::Type *ElementType, CharUnits Align, const Twine &Name="")
Definition CGBuilder.h:356
Abstract information about a function or function prototype.
Definition CGCall.h:41
All available information about a concrete callee.
Definition CGCall.h:63
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)
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)
void handleScalarSemanticStore(llvm::IRBuilder<> &B, const FunctionDecl *FD, llvm::Value *Source, const clang::DeclaratorDecl *Decl, HLSLAppliedSemanticAttr *Semantic)
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)
bool emitResourceArrayCopy(LValue &LHS, Expr *RHSExpr, CodeGenFunction &CGF)
LValue emitBufferMemberExpr(CodeGenFunction &CGF, const MemberExpr *E)
bool emitBufferCopy(CodeGenFunction &CGF, Address DestPtr, Address SrcPtr, QualType CType)
llvm::Type * convertHLSLSpecificType(const Type *T, const CGHLSLOffsetInfo &OffsetInfo)
resource_getpointer resource_handlefrombinding resource_nonuniformindex GENERATE_HLSL_INTRINSIC_FUNCTION(GroupMemoryBarrierWithGroupSync, group_memory_barrier_with_group_sync) protected llvm::Value * emitSystemSemanticLoad(llvm::IRBuilder<> &B, const FunctionDecl *FD, llvm::Type *Type, const clang::DeclaratorDecl *Decl, HLSLAppliedSemanticAttr *Semantic, std::optional< unsigned > Index)
RawAddress createBufferMatrixTempAddress(const LValue &LV, SourceLocation Loc, CodeGenFunction &CGF)
void addBuffer(const HLSLBufferDecl *D)
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:274
void add(RValue rvalue, QualType type)
Definition CGCall.h:302
A non-RAII class containing all the information about a bound opaque value.
CodeGenFunction - This class organizes the per-function state that is used while generating LLVM code...
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.
bool EmitLifetimeStart(llvm::Value *Addr)
Emit a lifetime.begin marker if some criteria are satisfied.
Definition CGDecl.cpp:1356
llvm::AllocaInst * CreateTempAlloca(llvm::Type *Ty, const Twine &Name="tmp", llvm::Value *ArraySize=nullptr)
CreateTempAlloca - This creates an alloca and inserts it into the entry block if ArraySize is nullptr...
Definition CGExpr.cpp:153
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:5342
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:273
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:1591
LValue EmitCheckedLValue(const Expr *E, TypeCheckKind TCK)
Same as EmitLValue but additionally we generate checking code to guard against undefined behavior.
Definition CGExpr.cpp:1672
RawAddress CreateMemTemp(QualType T, const Twine &Name="tmp", RawAddress *Alloca=nullptr)
CreateMemTemp - Create a temporary memory object of the given type, with appropriate alignmen and cas...
Definition CGExpr.cpp:189
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:1707
bool isOpaqueValueEmitted(const OpaqueValueExpr *E)
isOpaqueValueEmitted - Return true if the opaque value expression has already been emitted.
Definition CGExpr.cpp:6333
llvm::LLVMContext & getLLVMContext()
This class organizes the cross-function state that is used while generating LLVM code.
CGHLSLRuntime & getHLSLRuntime()
Return a reference to the configured HLSL runtime.
llvm::Module & getModule() const
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.
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:702
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:379
virtual bool isHLSLPadding(llvm::Type *Ty) const
Return true if this is an HLSL padding type.
Definition TargetInfo.h:439
virtual llvm::Type * getHLSLPadding(CodeGenModule &CGM, CharUnits NumBytes) const
Return an LLVM type that corresponds to padding in HLSL types.
Definition TargetInfo.h:433
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:427
Represents the canonical version of C arrays with a specified constant size.
Definition TypeBase.h:3768
int64_t getSExtSize() const
Return the size sign-extended as a uint64_t.
Definition TypeBase.h:3850
DeclContext * getParent()
getParent - Returns the containing DeclContext.
Definition DeclBase.h:2109
A reference to a declared variable, function, enum, etc.
Definition Expr.h:1273
Decl - This represents one declaration (or definition), e.g.
Definition DeclBase.h:86
T * getAttr() const
Definition DeclBase.h:573
bool hasAttrs() const
Definition DeclBase.h:518
ASTContext & getASTContext() const LLVM_READONLY
Definition DeclBase.cpp:546
specific_attr_iterator< T > specific_attr_end() const
Definition DeclBase.h:569
specific_attr_iterator< T > specific_attr_begin() const
Definition DeclBase.h:564
AttrVec & getAttrs()
Definition DeclBase.h:524
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:3090
Expr * IgnoreImpCasts() LLVM_READONLY
Skip past any implicit casts which might surround this expression until reaching a fixed point.
Definition Expr.cpp:3070
SourceLocation getExprLoc() const LLVM_READONLY
getExprLoc - Return the preferred location for the arrow when diagnosing a problem with a generic exp...
Definition Expr.cpp:277
QualType getType() const
Definition Expr.h:144
Represents a member of a struct/union/class.
Definition Decl.h:3160
Represents a function declaration or definition.
Definition Decl.h:2000
const ParmVarDecl * getParamDecl(unsigned i) const
Definition Decl.h:2797
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:2862
Represents a prototype with parameter type info, e.g.
Definition TypeBase.h:5315
HLSLBufferDecl - Represent a cbuffer or tbuffer declaration.
Definition Decl.h:5196
bool isCBuffer() const
Definition Decl.h:5240
const CXXRecordDecl * getLayoutStruct() const
Definition Decl.h:5243
bool hasValidPackoffset() const
Definition Decl.h:5242
buffer_decl_range buffer_decls() const
Definition Decl.h:5271
This class represents temporary values used to represent inout and out arguments in HLSL.
Definition Expr.h:7396
ArrayRef< llvm::hlsl::rootsig::RootElement > getRootElements() const
Definition Decl.h:5313
llvm::dxbc::RootSignatureVersion getVersion() const
Definition Decl.h:5311
Describes an C or C++ initializer list.
Definition Expr.h:5302
MemberExpr - [C99 6.5.2.3] Structure and Union Members.
Definition Expr.h:3367
ValueDecl * getMemberDecl() const
Retrieve the member declaration to which this expression refers.
Definition Expr.h:3450
Expr * getBase() const
Definition Expr.h:3444
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:1181
Expr * getSourceExpr() const
The source expression of an opaque value expression is the expression which originally generated the ...
Definition Expr.h:1231
Represents a parameter to a function.
Definition Decl.h:1790
A (possibly-)qualified type.
Definition TypeBase.h:937
const Type * getTypePtr() const
Retrieves a pointer to the underlying (unqualified) type.
Definition TypeBase.h:8388
LangAS getAddressSpace() const
Return the address space of this type.
Definition TypeBase.h:8514
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:4327
unsigned getNumFields() const
Returns the number of fields (non-static data members) in this record.
Definition Decl.h:4543
field_iterator field_begin() const
Definition Decl.cpp:5276
A class that does preorder or postorder depth-first traversal on the entire Clang AST and visits each...
bool TraverseStmt(Stmt *S, DataRecursionQueue *Queue=nullptr)
Encodes a location in the source.
TargetOptions & getTargetOpts() const
Retrieve the target options.
Definition TargetInfo.h:326
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:1839
bool isIncompleteArrayType() const
Definition TypeBase.h:8732
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:8724
bool isConstantMatrixType() const
Definition TypeBase.h:8792
bool isHLSLResourceRecord() const
Definition Type.cpp:5443
bool isStructureOrClassType() const
Definition Type.cpp:707
const T * getAsCanonical() const
If this type is canonically the specified type, return its canonical type cast to that specified type...
Definition TypeBase.h:2929
const T * getAs() const
Member-template getAs<specific type>'.
Definition TypeBase.h:9218
const Type * getUnqualifiedDesugaredType() const
Return the specified type with any "sugar" removed from the type, removing any typedefs,...
Definition Type.cpp:654
bool isHLSLResourceRecordArray() const
Definition Type.cpp:5447
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:926
bool hasGlobalStorage() const
Returns true for all variables that do not have local storage.
Definition Decl.h:1226
StorageClass getStorageClass() const
Returns the storage class as written in the source.
Definition Decl.h:1168
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
The JSON file list parser is used to communicate input to InstallAPI.
bool isa(CodeGen::Address addr)
Definition Address.h:330
nullptr
This class represents a compute construct, representing a 'Kind' of ‘parallel’, 'serial',...
StorageClass
Storage classes.
Definition Specifiers.h:248
@ SC_Static
Definition Specifiers.h:252
@ SC_None
Definition Specifiers.h:250
@ 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
unsigned getCounterImplicitOrderID() const