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 0 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 0;
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 }
326 continue;
327 }
328
329 DeclsWithOffset.emplace_back(VD, OffsetInfo[OffsetIdx++]);
330 }
331
332 if (!OffsetInfo.empty())
333 llvm::stable_sort(DeclsWithOffset, [](const auto &LHS, const auto &RHS) {
334 return CGHLSLOffsetInfo::compareOffsets(LHS.second, RHS.second);
335 });
336
337 // Associate the buffer global variable with its constants
338 SmallVector<llvm::Metadata *> BufGlobals;
339 BufGlobals.reserve(DeclsWithOffset.size() + 1);
340 BufGlobals.push_back(ValueAsMetadata::get(BufGV));
341
342 auto ElemIt = LayoutStruct->element_begin();
343 for (auto &[VD, _] : DeclsWithOffset) {
344 if (CGM.getTargetCodeGenInfo().isHLSLPadding(*ElemIt))
345 ++ElemIt;
346
347 assert(ElemIt != LayoutStruct->element_end() &&
348 "number of elements in layout struct does not match");
349 llvm::Type *LayoutType = *ElemIt++;
350
351 GlobalVariable *ElemGV =
352 cast<GlobalVariable>(CGM.GetAddrOfGlobalVar(VD, LayoutType));
353 BufGlobals.push_back(ValueAsMetadata::get(ElemGV));
354 }
355 assert(ElemIt == LayoutStruct->element_end() &&
356 "number of elements in layout struct does not match");
357
358 // add buffer metadata to the module
359 CGM.getModule()
360 .getOrInsertNamedMetadata("hlsl.cbs")
361 ->addOperand(MDNode::get(Ctx, BufGlobals));
362}
363
364// Creates resource handle type for the HLSL buffer declaration
365static const clang::HLSLAttributedResourceType *
367 ASTContext &AST = BufDecl->getASTContext();
369 AST.HLSLResourceTy, AST.getCanonicalTagType(BufDecl->getLayoutStruct()),
370 HLSLAttributedResourceType::Attributes(ResourceClass::CBuffer));
372}
373
376
377 // If we don't have packoffset info, just return an empty result.
378 if (!BufDecl.hasValidPackoffset())
379 return Result;
380
381 for (Decl *D : BufDecl.buffer_decls()) {
383 continue;
384 }
385 VarDecl *VD = dyn_cast<VarDecl>(D);
386 if (!VD || VD->getType().getAddressSpace() != LangAS::hlsl_constant)
387 continue;
388
389 if (!VD->hasAttrs()) {
390 Result.Offsets.push_back(Unspecified);
391 continue;
392 }
393
394 uint32_t Offset = Unspecified;
395 for (auto *Attr : VD->getAttrs()) {
396 if (auto *POA = dyn_cast<HLSLPackOffsetAttr>(Attr)) {
397 Offset = POA->getOffsetInBytes();
398 break;
399 }
400 auto *RBA = dyn_cast<HLSLResourceBindingAttr>(Attr);
401 if (RBA &&
402 RBA->getRegisterType() == HLSLResourceBindingAttr::RegisterType::C) {
403 Offset = RBA->getSlotNumber() * CBufferRowSizeInBytes;
404 break;
405 }
406 }
407 Result.Offsets.push_back(Offset);
408 }
409 return Result;
410}
411
412// Codegen for HLSLBufferDecl
414
415 assert(BufDecl->isCBuffer() && "tbuffer codegen is not supported yet");
416
417 // create resource handle type for the buffer
418 const clang::HLSLAttributedResourceType *ResHandleTy =
419 createBufferHandleType(BufDecl);
420
421 // empty constant buffer is ignored
422 if (ResHandleTy->getContainedType()->getAsCXXRecordDecl()->isEmpty())
423 return;
424
425 // create global variable for the constant buffer
426 CGHLSLOffsetInfo OffsetInfo = CGHLSLOffsetInfo::fromDecl(*BufDecl);
427 llvm::Type *LayoutTy = convertHLSLSpecificType(ResHandleTy, OffsetInfo);
428 llvm::GlobalVariable *BufGV = new GlobalVariable(
429 LayoutTy, /*isConstant*/ false,
430 GlobalValue::LinkageTypes::ExternalLinkage, PoisonValue::get(LayoutTy),
431 llvm::formatv("{0}{1}", BufDecl->getName(),
432 BufDecl->isCBuffer() ? ".cb" : ".tb"),
433 GlobalValue::NotThreadLocal);
434 CGM.getModule().insertGlobalVariable(BufGV);
435
436 // Add globals for constant buffer elements and create metadata nodes
437 emitBufferGlobalsAndMetadata(BufDecl, BufGV, OffsetInfo);
438
439 // Initialize cbuffer from binding (implicit or explicit)
440 initializeBufferFromBinding(BufDecl, BufGV);
441}
442
444 const HLSLRootSignatureDecl *SignatureDecl) {
445 llvm::Module &M = CGM.getModule();
446 Triple T(M.getTargetTriple());
447
448 // Generated later with the function decl if not targeting root signature
449 if (T.getEnvironment() != Triple::EnvironmentType::RootSignature)
450 return;
451
452 addRootSignatureMD(SignatureDecl->getVersion(),
453 SignatureDecl->getRootElements(), nullptr, M);
454}
455
456llvm::StructType *
457CGHLSLRuntime::getHLSLBufferLayoutType(const RecordType *StructType) {
458 const auto Entry = LayoutTypes.find(StructType);
459 if (Entry != LayoutTypes.end())
460 return Entry->getSecond();
461 return nullptr;
462}
463
464void CGHLSLRuntime::addHLSLBufferLayoutType(const RecordType *StructType,
465 llvm::StructType *LayoutTy) {
466 assert(getHLSLBufferLayoutType(StructType) == nullptr &&
467 "layout type for this struct already exist");
468 LayoutTypes[StructType] = LayoutTy;
469}
470
472 auto &TargetOpts = CGM.getTarget().getTargetOpts();
473 auto &CodeGenOpts = CGM.getCodeGenOpts();
474 auto &LangOpts = CGM.getLangOpts();
475 llvm::Module &M = CGM.getModule();
476 Triple T(M.getTargetTriple());
477 if (T.getArch() == Triple::ArchType::dxil)
478 addDxilValVersion(TargetOpts.DxilValidatorVersion, M);
479 if (CodeGenOpts.ResMayAlias)
480 M.setModuleFlag(llvm::Module::ModFlagBehavior::Error, "dx.resmayalias", 1);
481 if (CodeGenOpts.AllResourcesBound)
482 M.setModuleFlag(llvm::Module::ModFlagBehavior::Error,
483 "dx.allresourcesbound", 1);
484 if (CodeGenOpts.OptimizationLevel == 0)
485 M.addModuleFlag(llvm::Module::ModFlagBehavior::Override,
486 "dx.disable_optimizations", 1);
487
488 // NativeHalfType corresponds to the -fnative-half-type clang option which is
489 // aliased by clang-dxc's -enable-16bit-types option. This option is used to
490 // set the UseNativeLowPrecision DXIL module flag in the DirectX backend
491 if (LangOpts.NativeHalfType)
492 M.setModuleFlag(llvm::Module::ModFlagBehavior::Error, "dx.nativelowprec",
493 1);
494
496}
497
499 const FunctionDecl *FD, llvm::Function *Fn) {
500 const auto *ShaderAttr = FD->getAttr<HLSLShaderAttr>();
501 assert(ShaderAttr && "All entry functions must have a HLSLShaderAttr");
502 const StringRef ShaderAttrKindStr = "hlsl.shader";
503 Fn->addFnAttr(ShaderAttrKindStr,
504 llvm::Triple::getEnvironmentTypeName(ShaderAttr->getType()));
505 if (HLSLNumThreadsAttr *NumThreadsAttr = FD->getAttr<HLSLNumThreadsAttr>()) {
506 const StringRef NumThreadsKindStr = "hlsl.numthreads";
507 std::string NumThreadsStr =
508 formatv("{0},{1},{2}", NumThreadsAttr->getX(), NumThreadsAttr->getY(),
509 NumThreadsAttr->getZ());
510 Fn->addFnAttr(NumThreadsKindStr, NumThreadsStr);
511 }
512 if (HLSLWaveSizeAttr *WaveSizeAttr = FD->getAttr<HLSLWaveSizeAttr>()) {
513 const StringRef WaveSizeKindStr = "hlsl.wavesize";
514 std::string WaveSizeStr =
515 formatv("{0},{1},{2}", WaveSizeAttr->getMin(), WaveSizeAttr->getMax(),
516 WaveSizeAttr->getPreferred());
517 Fn->addFnAttr(WaveSizeKindStr, WaveSizeStr);
518 }
519 // HLSL entry functions are materialized for module functions with
520 // HLSLShaderAttr attribute. SetLLVMFunctionAttributesForDefinition called
521 // later in the compiler-flow for such module functions is not aware of and
522 // hence not able to set attributes of the newly materialized entry functions.
523 // So, set attributes of entry function here, as appropriate.
524 Fn->addFnAttr(llvm::Attribute::NoInline);
525
526 if (CGM.getLangOpts().HLSLSpvEnableMaximalReconvergence) {
527 Fn->addFnAttr("enable-maximal-reconvergence", "true");
528 }
529}
530
531static Value *buildVectorInput(IRBuilder<> &B, Function *F, llvm::Type *Ty) {
532 if (const auto *VT = dyn_cast<FixedVectorType>(Ty)) {
533 Value *Result = PoisonValue::get(Ty);
534 for (unsigned I = 0; I < VT->getNumElements(); ++I) {
535 Value *Elt = B.CreateCall(F, {B.getInt32(I)});
536 Result = B.CreateInsertElement(Result, Elt, I);
537 }
538 return Result;
539 }
540 return B.CreateCall(F, {B.getInt32(0)});
541}
542
543static void addSPIRVBuiltinDecoration(llvm::GlobalVariable *GV,
544 unsigned BuiltIn) {
545 LLVMContext &Ctx = GV->getContext();
546 IRBuilder<> B(GV->getContext());
547 MDNode *Operands = MDNode::get(
548 Ctx,
549 {ConstantAsMetadata::get(B.getInt32(/* Spirv::Decoration::BuiltIn */ 11)),
550 ConstantAsMetadata::get(B.getInt32(BuiltIn))});
551 MDNode *Decoration = MDNode::get(Ctx, {Operands});
552 GV->addMetadata("spirv.Decorations", *Decoration);
553}
554
555static void addLocationDecoration(llvm::GlobalVariable *GV, unsigned Location) {
556 LLVMContext &Ctx = GV->getContext();
557 IRBuilder<> B(GV->getContext());
558 MDNode *Operands =
559 MDNode::get(Ctx, {ConstantAsMetadata::get(B.getInt32(/* Location */ 30)),
560 ConstantAsMetadata::get(B.getInt32(Location))});
561 MDNode *Decoration = MDNode::get(Ctx, {Operands});
562 GV->addMetadata("spirv.Decorations", *Decoration);
563}
564
565static llvm::Value *createSPIRVBuiltinLoad(IRBuilder<> &B, llvm::Module &M,
566 llvm::Type *Ty, const Twine &Name,
567 unsigned BuiltInID) {
568 auto *GV = new llvm::GlobalVariable(
569 M, Ty, /* isConstant= */ true, llvm::GlobalValue::ExternalLinkage,
570 /* Initializer= */ nullptr, Name, /* insertBefore= */ nullptr,
571 llvm::GlobalVariable::GeneralDynamicTLSModel,
572 /* AddressSpace */ 7, /* isExternallyInitialized= */ true);
573 addSPIRVBuiltinDecoration(GV, BuiltInID);
574 GV->setVisibility(llvm::GlobalValue::HiddenVisibility);
575 return B.CreateLoad(Ty, GV);
576}
577
578static llvm::Value *createSPIRVLocationLoad(IRBuilder<> &B, llvm::Module &M,
579 llvm::Type *Ty, unsigned Location,
580 StringRef Name) {
581 auto *GV = new llvm::GlobalVariable(
582 M, Ty, /* isConstant= */ true, llvm::GlobalValue::ExternalLinkage,
583 /* Initializer= */ nullptr, /* Name= */ Name, /* insertBefore= */ nullptr,
584 llvm::GlobalVariable::GeneralDynamicTLSModel,
585 /* AddressSpace */ 7, /* isExternallyInitialized= */ true);
586 GV->setVisibility(llvm::GlobalValue::HiddenVisibility);
587 addLocationDecoration(GV, Location);
588 return B.CreateLoad(Ty, GV);
589}
590
591llvm::Value *CGHLSLRuntime::emitSPIRVUserSemanticLoad(
592 llvm::IRBuilder<> &B, llvm::Type *Type, const clang::DeclaratorDecl *Decl,
593 HLSLAppliedSemanticAttr *Semantic, std::optional<unsigned> Index) {
594 Twine BaseName = Twine(Semantic->getAttrName()->getName());
595 Twine VariableName = BaseName.concat(Twine(Index.value_or(0)));
596
597 unsigned Location = SPIRVLastAssignedInputSemanticLocation;
598 if (auto *L = Decl->getAttr<HLSLVkLocationAttr>())
599 Location = L->getLocation();
600
601 // DXC completely ignores the semantic/index pair. Location are assigned from
602 // the first semantic to the last.
603 llvm::ArrayType *AT = dyn_cast<llvm::ArrayType>(Type);
604 unsigned ElementCount = AT ? AT->getNumElements() : 1;
605 SPIRVLastAssignedInputSemanticLocation += ElementCount;
606
607 return createSPIRVLocationLoad(B, CGM.getModule(), Type, Location,
608 VariableName.str());
609}
610
611static void createSPIRVLocationStore(IRBuilder<> &B, llvm::Module &M,
612 llvm::Value *Source, unsigned Location,
613 StringRef Name) {
614 auto *GV = new llvm::GlobalVariable(
615 M, Source->getType(), /* isConstant= */ false,
616 llvm::GlobalValue::ExternalLinkage,
617 /* Initializer= */ nullptr, /* Name= */ Name, /* insertBefore= */ nullptr,
618 llvm::GlobalVariable::GeneralDynamicTLSModel,
619 /* AddressSpace */ 8, /* isExternallyInitialized= */ false);
620 GV->setVisibility(llvm::GlobalValue::HiddenVisibility);
621 addLocationDecoration(GV, Location);
622 B.CreateStore(Source, GV);
623}
624
625void CGHLSLRuntime::emitSPIRVUserSemanticStore(
626 llvm::IRBuilder<> &B, llvm::Value *Source,
627 const clang::DeclaratorDecl *Decl, HLSLAppliedSemanticAttr *Semantic,
628 std::optional<unsigned> Index) {
629 Twine BaseName = Twine(Semantic->getAttrName()->getName());
630 Twine VariableName = BaseName.concat(Twine(Index.value_or(0)));
631
632 unsigned Location = SPIRVLastAssignedOutputSemanticLocation;
633 if (auto *L = Decl->getAttr<HLSLVkLocationAttr>())
634 Location = L->getLocation();
635
636 // DXC completely ignores the semantic/index pair. Location are assigned from
637 // the first semantic to the last.
638 llvm::ArrayType *AT = dyn_cast<llvm::ArrayType>(Source->getType());
639 unsigned ElementCount = AT ? AT->getNumElements() : 1;
640 SPIRVLastAssignedOutputSemanticLocation += ElementCount;
641 createSPIRVLocationStore(B, CGM.getModule(), Source, Location,
642 VariableName.str());
643}
644
645llvm::Value *
646CGHLSLRuntime::emitDXILUserSemanticLoad(llvm::IRBuilder<> &B, llvm::Type *Type,
647 HLSLAppliedSemanticAttr *Semantic,
648 std::optional<unsigned> Index) {
649 Twine BaseName = Twine(Semantic->getAttrName()->getName());
650 Twine VariableName = BaseName.concat(Twine(Index.value_or(0)));
651
652 // DXIL packing rules etc shall be handled here.
653 // FIXME: generate proper sigpoint, index, col, row values.
654 // FIXME: also DXIL loads vectors element by element.
655 SmallVector<Value *> Args{B.getInt32(4), B.getInt32(0), B.getInt32(0),
656 B.getInt8(0),
657 llvm::PoisonValue::get(B.getInt32Ty())};
658
659 llvm::Intrinsic::ID IntrinsicID = llvm::Intrinsic::dx_load_input;
660 llvm::Value *Value = B.CreateIntrinsic(/*ReturnType=*/Type, IntrinsicID, Args,
661 nullptr, VariableName);
662 return Value;
663}
664
665void CGHLSLRuntime::emitDXILUserSemanticStore(llvm::IRBuilder<> &B,
666 llvm::Value *Source,
667 HLSLAppliedSemanticAttr *Semantic,
668 std::optional<unsigned> Index) {
669 // DXIL packing rules etc shall be handled here.
670 // FIXME: generate proper sigpoint, index, col, row values.
671 SmallVector<Value *> Args{B.getInt32(4),
672 B.getInt32(0),
673 B.getInt32(0),
674 B.getInt8(0),
675 llvm::PoisonValue::get(B.getInt32Ty()),
676 Source};
677
678 llvm::Intrinsic::ID IntrinsicID = llvm::Intrinsic::dx_store_output;
679 B.CreateIntrinsic(/*ReturnType=*/CGM.VoidTy, IntrinsicID, Args, nullptr);
680}
681
682llvm::Value *CGHLSLRuntime::emitUserSemanticLoad(
683 IRBuilder<> &B, llvm::Type *Type, const clang::DeclaratorDecl *Decl,
684 HLSLAppliedSemanticAttr *Semantic, std::optional<unsigned> Index) {
685 if (CGM.getTarget().getTriple().isSPIRV())
686 return emitSPIRVUserSemanticLoad(B, Type, Decl, Semantic, Index);
687
688 if (CGM.getTarget().getTriple().isDXIL())
689 return emitDXILUserSemanticLoad(B, Type, Semantic, Index);
690
691 llvm_unreachable("Unsupported target for user-semantic load.");
692}
693
694void CGHLSLRuntime::emitUserSemanticStore(IRBuilder<> &B, llvm::Value *Source,
695 const clang::DeclaratorDecl *Decl,
696 HLSLAppliedSemanticAttr *Semantic,
697 std::optional<unsigned> Index) {
698 if (CGM.getTarget().getTriple().isSPIRV())
699 return emitSPIRVUserSemanticStore(B, Source, Decl, Semantic, Index);
700
701 if (CGM.getTarget().getTriple().isDXIL())
702 return emitDXILUserSemanticStore(B, Source, Semantic, Index);
703
704 llvm_unreachable("Unsupported target for user-semantic load.");
705}
706
708 IRBuilder<> &B, const FunctionDecl *FD, llvm::Type *Type,
709 const clang::DeclaratorDecl *Decl, HLSLAppliedSemanticAttr *Semantic,
710 std::optional<unsigned> Index) {
711
712 std::string SemanticName = Semantic->getAttrName()->getName().upper();
713 if (SemanticName == "SV_GROUPINDEX") {
714 llvm::Function *GroupIndex =
715 CGM.getIntrinsic(getFlattenedThreadIdInGroupIntrinsic());
716 return B.CreateCall(FunctionCallee(GroupIndex));
717 }
718
719 if (SemanticName == "SV_DISPATCHTHREADID") {
720 llvm::Intrinsic::ID IntrinID = getThreadIdIntrinsic();
721 llvm::Function *ThreadIDIntrinsic =
722 llvm::Intrinsic::isOverloaded(IntrinID)
723 ? CGM.getIntrinsic(IntrinID, {CGM.Int32Ty})
724 : CGM.getIntrinsic(IntrinID);
725 return buildVectorInput(B, ThreadIDIntrinsic, Type);
726 }
727
728 if (SemanticName == "SV_GROUPTHREADID") {
729 llvm::Intrinsic::ID IntrinID = getGroupThreadIdIntrinsic();
730 llvm::Function *GroupThreadIDIntrinsic =
731 llvm::Intrinsic::isOverloaded(IntrinID)
732 ? CGM.getIntrinsic(IntrinID, {CGM.Int32Ty})
733 : CGM.getIntrinsic(IntrinID);
734 return buildVectorInput(B, GroupThreadIDIntrinsic, Type);
735 }
736
737 if (SemanticName == "SV_GROUPID") {
738 llvm::Intrinsic::ID IntrinID = getGroupIdIntrinsic();
739 llvm::Function *GroupIDIntrinsic =
740 llvm::Intrinsic::isOverloaded(IntrinID)
741 ? CGM.getIntrinsic(IntrinID, {CGM.Int32Ty})
742 : CGM.getIntrinsic(IntrinID);
743 return buildVectorInput(B, GroupIDIntrinsic, Type);
744 }
745
746 const auto *ShaderAttr = FD->getAttr<HLSLShaderAttr>();
747 assert(ShaderAttr && "Entry point has no shader attribute");
748 llvm::Triple::EnvironmentType ST = ShaderAttr->getType();
749
750 if (SemanticName == "SV_POSITION") {
751 if (ST == Triple::EnvironmentType::Pixel) {
752 if (CGM.getTarget().getTriple().isSPIRV())
753 return createSPIRVBuiltinLoad(B, CGM.getModule(), Type,
754 Semantic->getAttrName()->getName(),
755 /* BuiltIn::FragCoord */ 15);
756 if (CGM.getTarget().getTriple().isDXIL())
757 return emitDXILUserSemanticLoad(B, Type, Semantic, Index);
758 }
759
760 if (ST == Triple::EnvironmentType::Vertex) {
761 return emitUserSemanticLoad(B, Type, Decl, Semantic, Index);
762 }
763 }
764
765 if (SemanticName == "SV_VERTEXID") {
766 if (ST == Triple::EnvironmentType::Vertex) {
767 if (CGM.getTarget().getTriple().isSPIRV())
768 return createSPIRVBuiltinLoad(B, CGM.getModule(), Type,
769 Semantic->getAttrName()->getName(),
770 /* BuiltIn::VertexIndex */ 42);
771 else
772 return emitDXILUserSemanticLoad(B, Type, Semantic, Index);
773 }
774 }
775
776 llvm_unreachable(
777 "Load hasn't been implemented yet for this system semantic. FIXME");
778}
779
780static void createSPIRVBuiltinStore(IRBuilder<> &B, llvm::Module &M,
781 llvm::Value *Source, const Twine &Name,
782 unsigned BuiltInID) {
783 auto *GV = new llvm::GlobalVariable(
784 M, Source->getType(), /* isConstant= */ false,
785 llvm::GlobalValue::ExternalLinkage,
786 /* Initializer= */ nullptr, Name, /* insertBefore= */ nullptr,
787 llvm::GlobalVariable::GeneralDynamicTLSModel,
788 /* AddressSpace */ 8, /* isExternallyInitialized= */ false);
789 addSPIRVBuiltinDecoration(GV, BuiltInID);
790 GV->setVisibility(llvm::GlobalValue::HiddenVisibility);
791 B.CreateStore(Source, GV);
792}
793
794void CGHLSLRuntime::emitSystemSemanticStore(IRBuilder<> &B, llvm::Value *Source,
796 HLSLAppliedSemanticAttr *Semantic,
797 std::optional<unsigned> Index) {
798
799 std::string SemanticName = Semantic->getAttrName()->getName().upper();
800 if (SemanticName == "SV_POSITION") {
801 if (CGM.getTarget().getTriple().isDXIL()) {
802 emitDXILUserSemanticStore(B, Source, Semantic, Index);
803 return;
804 }
805
806 if (CGM.getTarget().getTriple().isSPIRV()) {
807 createSPIRVBuiltinStore(B, CGM.getModule(), Source,
808 Semantic->getAttrName()->getName(),
809 /* BuiltIn::Position */ 0);
810 return;
811 }
812 }
813
814 if (SemanticName == "SV_TARGET") {
815 emitUserSemanticStore(B, Source, Decl, Semantic, Index);
816 return;
817 }
818
819 llvm_unreachable(
820 "Store hasn't been implemented yet for this system semantic. FIXME");
821}
822
824 IRBuilder<> &B, const FunctionDecl *FD, llvm::Type *Type,
825 const clang::DeclaratorDecl *Decl, HLSLAppliedSemanticAttr *Semantic) {
826
827 std::optional<unsigned> Index = Semantic->getSemanticIndex();
828 if (Semantic->getAttrName()->getName().starts_with_insensitive("SV_"))
829 return emitSystemSemanticLoad(B, FD, Type, Decl, Semantic, Index);
830 return emitUserSemanticLoad(B, Type, Decl, Semantic, Index);
831}
832
834 IRBuilder<> &B, const FunctionDecl *FD, llvm::Value *Source,
835 const clang::DeclaratorDecl *Decl, HLSLAppliedSemanticAttr *Semantic) {
836 std::optional<unsigned> Index = Semantic->getSemanticIndex();
837 if (Semantic->getAttrName()->getName().starts_with_insensitive("SV_"))
838 emitSystemSemanticStore(B, Source, Decl, Semantic, Index);
839 else
840 emitUserSemanticStore(B, Source, Decl, Semantic, Index);
841}
842
843std::pair<llvm::Value *, specific_attr_iterator<HLSLAppliedSemanticAttr>>
845 IRBuilder<> &B, const FunctionDecl *FD, llvm::Type *Type,
849 const llvm::StructType *ST = cast<StructType>(Type);
850 const clang::RecordDecl *RD = Decl->getType()->getAsRecordDecl();
851
852 assert(RD->getNumFields() == ST->getNumElements());
853
854 llvm::Value *Aggregate = llvm::PoisonValue::get(Type);
855 auto FieldDecl = RD->field_begin();
856 for (unsigned I = 0; I < ST->getNumElements(); ++I) {
857 auto [ChildValue, NextAttr] = handleSemanticLoad(
858 B, FD, ST->getElementType(I), *FieldDecl, AttrBegin, AttrEnd);
859 AttrBegin = NextAttr;
860 assert(ChildValue);
861 Aggregate = B.CreateInsertValue(Aggregate, ChildValue, I);
862 ++FieldDecl;
863 }
864
865 return std::make_pair(Aggregate, AttrBegin);
866}
867
870 IRBuilder<> &B, const FunctionDecl *FD, llvm::Value *Source,
874
875 const llvm::StructType *ST = cast<StructType>(Source->getType());
876
877 const clang::RecordDecl *RD = nullptr;
878 if (const FunctionDecl *FD = dyn_cast<FunctionDecl>(Decl))
880 else
881 RD = Decl->getType()->getAsRecordDecl();
882 assert(RD);
883
884 assert(RD->getNumFields() == ST->getNumElements());
885
886 auto FieldDecl = RD->field_begin();
887 for (unsigned I = 0; I < ST->getNumElements(); ++I, ++FieldDecl) {
888 llvm::Value *Extract = B.CreateExtractValue(Source, I);
889 AttrBegin =
890 handleSemanticStore(B, FD, Extract, *FieldDecl, AttrBegin, AttrEnd);
891 }
892
893 return AttrBegin;
894}
895
896std::pair<llvm::Value *, specific_attr_iterator<HLSLAppliedSemanticAttr>>
898 IRBuilder<> &B, const FunctionDecl *FD, llvm::Type *Type,
902 assert(AttrBegin != AttrEnd);
903 if (Type->isStructTy())
904 return handleStructSemanticLoad(B, FD, Type, Decl, AttrBegin, AttrEnd);
905
906 HLSLAppliedSemanticAttr *Attr = *AttrBegin;
907 ++AttrBegin;
908 return std::make_pair(handleScalarSemanticLoad(B, FD, Type, Decl, Attr),
909 AttrBegin);
910}
911
914 IRBuilder<> &B, const FunctionDecl *FD, llvm::Value *Source,
918 assert(AttrBegin != AttrEnd);
919 if (Source->getType()->isStructTy())
920 return handleStructSemanticStore(B, FD, Source, Decl, AttrBegin, AttrEnd);
921
922 HLSLAppliedSemanticAttr *Attr = *AttrBegin;
923 ++AttrBegin;
924 handleScalarSemanticStore(B, FD, Source, Decl, Attr);
925 return AttrBegin;
926}
927
929 llvm::Function *Fn) {
930 llvm::Module &M = CGM.getModule();
931 llvm::LLVMContext &Ctx = M.getContext();
932 auto *EntryTy = llvm::FunctionType::get(llvm::Type::getVoidTy(Ctx), false);
933 Function *EntryFn =
934 Function::Create(EntryTy, Function::ExternalLinkage, FD->getName(), &M);
935
936 // Copy function attributes over, we have no argument or return attributes
937 // that can be valid on the real entry.
938 AttributeList NewAttrs = AttributeList::get(Ctx, AttributeList::FunctionIndex,
939 Fn->getAttributes().getFnAttrs());
940 EntryFn->setAttributes(NewAttrs);
941 setHLSLEntryAttributes(FD, EntryFn);
942
943 // Set the called function as internal linkage.
944 Fn->setLinkage(GlobalValue::InternalLinkage);
945
946 BasicBlock *BB = BasicBlock::Create(Ctx, "entry", EntryFn);
947 IRBuilder<> B(BB);
949
951 if (CGM.shouldEmitConvergenceTokens()) {
952 assert(EntryFn->isConvergent());
953 llvm::Value *I =
954 B.CreateIntrinsic(llvm::Intrinsic::experimental_convergence_entry, {});
955 llvm::Value *bundleArgs[] = {I};
956 OB.emplace_back("convergencectrl", bundleArgs);
957 }
958
960
961 unsigned SRetOffset = 0;
962 for (const auto &Param : Fn->args()) {
963 if (Param.hasStructRetAttr()) {
964 SRetOffset = 1;
965 llvm::Type *VarType = Param.getParamStructRetType();
966 llvm::Value *Var = B.CreateAlloca(VarType);
967 OutputSemantic.push_back(std::make_pair(Var, VarType));
968 Args.push_back(Var);
969 continue;
970 }
971
972 const ParmVarDecl *PD = FD->getParamDecl(Param.getArgNo() - SRetOffset);
973 llvm::Value *SemanticValue = nullptr;
974 // FIXME: support inout/out parameters for semantics.
975 if ([[maybe_unused]] HLSLParamModifierAttr *MA =
976 PD->getAttr<HLSLParamModifierAttr>()) {
977 llvm_unreachable("Not handled yet");
978 } else {
979 llvm::Type *ParamType =
980 Param.hasByValAttr() ? Param.getParamByValType() : Param.getType();
981 auto AttrBegin = PD->specific_attr_begin<HLSLAppliedSemanticAttr>();
982 auto AttrEnd = PD->specific_attr_end<HLSLAppliedSemanticAttr>();
983 auto Result =
984 handleSemanticLoad(B, FD, ParamType, PD, AttrBegin, AttrEnd);
985 SemanticValue = Result.first;
986 if (!SemanticValue)
987 return;
988 if (Param.hasByValAttr()) {
989 llvm::Value *Var = B.CreateAlloca(Param.getParamByValType());
990 B.CreateStore(SemanticValue, Var);
991 SemanticValue = Var;
992 }
993 }
994
995 assert(SemanticValue);
996 Args.push_back(SemanticValue);
997 }
998
999 CallInst *CI = B.CreateCall(FunctionCallee(Fn), Args, OB);
1000 CI->setCallingConv(Fn->getCallingConv());
1001
1002 if (Fn->getReturnType() != CGM.VoidTy)
1003 // Element type is unused, so set to dummy value (NULL).
1004 OutputSemantic.push_back(std::make_pair(CI, nullptr));
1005
1006 for (auto &SourcePair : OutputSemantic) {
1007 llvm::Value *Source = SourcePair.first;
1008 llvm::Type *ElementType = SourcePair.second;
1009 AllocaInst *AI = dyn_cast<AllocaInst>(Source);
1010 llvm::Value *SourceValue = AI ? B.CreateLoad(ElementType, Source) : Source;
1011
1012 auto AttrBegin = FD->specific_attr_begin<HLSLAppliedSemanticAttr>();
1013 auto AttrEnd = FD->specific_attr_end<HLSLAppliedSemanticAttr>();
1014 handleSemanticStore(B, FD, SourceValue, FD, AttrBegin, AttrEnd);
1015 }
1016
1017 B.CreateRetVoid();
1018
1019 // Add and identify root signature to function, if applicable
1020 for (const Attr *Attr : FD->getAttrs()) {
1021 if (const auto *RSAttr = dyn_cast<RootSignatureAttr>(Attr)) {
1022 auto *RSDecl = RSAttr->getSignatureDecl();
1023 addRootSignatureMD(RSDecl->getVersion(), RSDecl->getRootElements(),
1024 EntryFn, M);
1025 }
1026 }
1027}
1028
1029static void gatherFunctions(SmallVectorImpl<Function *> &Fns, llvm::Module &M,
1030 bool CtorOrDtor) {
1031 const auto *GV =
1032 M.getNamedGlobal(CtorOrDtor ? "llvm.global_ctors" : "llvm.global_dtors");
1033 if (!GV)
1034 return;
1035 const auto *CA = dyn_cast<ConstantArray>(GV->getInitializer());
1036 if (!CA)
1037 return;
1038 // The global_ctor array elements are a struct [Priority, Fn *, COMDat].
1039 // HLSL neither supports priorities or COMDat values, so we will check those
1040 // in an assert but not handle them.
1041
1042 for (const auto &Ctor : CA->operands()) {
1044 continue;
1045 ConstantStruct *CS = cast<ConstantStruct>(Ctor);
1046
1047 assert(cast<ConstantInt>(CS->getOperand(0))->getValue() == 65535 &&
1048 "HLSL doesn't support setting priority for global ctors.");
1049 assert(isa<ConstantPointerNull>(CS->getOperand(2)) &&
1050 "HLSL doesn't support COMDat for global ctors.");
1051 Fns.push_back(cast<Function>(CS->getOperand(1)));
1052 }
1053}
1054
1056 llvm::Module &M = CGM.getModule();
1059 gatherFunctions(CtorFns, M, true);
1060 gatherFunctions(DtorFns, M, false);
1061
1062 // Insert a call to the global constructor at the beginning of the entry block
1063 // to externally exported functions. This is a bit of a hack, but HLSL allows
1064 // global constructors, but doesn't support driver initialization of globals.
1065 for (auto &F : M.functions()) {
1066 if (!F.hasFnAttribute("hlsl.shader"))
1067 continue;
1068 auto *Token = getConvergenceToken(F.getEntryBlock());
1069 Instruction *IP = &*F.getEntryBlock().begin();
1071 if (Token) {
1072 llvm::Value *bundleArgs[] = {Token};
1073 OB.emplace_back("convergencectrl", bundleArgs);
1074 IP = Token->getNextNode();
1075 }
1076 IRBuilder<> B(IP);
1077 for (auto *Fn : CtorFns) {
1078 auto CI = B.CreateCall(FunctionCallee(Fn), {}, OB);
1079 CI->setCallingConv(Fn->getCallingConv());
1080 }
1081
1082 // Insert global dtors before the terminator of the last instruction
1083 B.SetInsertPoint(F.back().getTerminator());
1084 for (auto *Fn : DtorFns) {
1085 auto CI = B.CreateCall(FunctionCallee(Fn), {}, OB);
1086 CI->setCallingConv(Fn->getCallingConv());
1087 }
1088 }
1089
1090 // No need to keep global ctors/dtors for non-lib profile after call to
1091 // ctors/dtors added for entry.
1092 Triple T(M.getTargetTriple());
1093 if (T.getEnvironment() != Triple::EnvironmentType::Library) {
1094 if (auto *GV = M.getNamedGlobal("llvm.global_ctors"))
1095 GV->eraseFromParent();
1096 if (auto *GV = M.getNamedGlobal("llvm.global_dtors"))
1097 GV->eraseFromParent();
1098 }
1099}
1100
1101static void initializeBuffer(CodeGenModule &CGM, llvm::GlobalVariable *GV,
1102 Intrinsic::ID IntrID,
1104
1105 LLVMContext &Ctx = CGM.getLLVMContext();
1106 llvm::Function *InitResFunc = llvm::Function::Create(
1107 llvm::FunctionType::get(CGM.VoidTy, false),
1108 llvm::GlobalValue::InternalLinkage,
1109 ("_init_buffer_" + GV->getName()).str(), CGM.getModule());
1110 InitResFunc->addFnAttr(llvm::Attribute::AlwaysInline);
1111
1112 llvm::BasicBlock *EntryBB =
1113 llvm::BasicBlock::Create(Ctx, "entry", InitResFunc);
1114 CGBuilderTy Builder(CGM, Ctx);
1115 const DataLayout &DL = CGM.getModule().getDataLayout();
1116 Builder.SetInsertPoint(EntryBB);
1117
1118 // Make sure the global variable is buffer resource handle
1119 llvm::Type *HandleTy = GV->getValueType();
1120 assert(HandleTy->isTargetExtTy() && "unexpected type of the buffer global");
1121
1122 llvm::Value *CreateHandle = Builder.CreateIntrinsic(
1123 /*ReturnType=*/HandleTy, IntrID, Args, nullptr,
1124 Twine(GV->getName()).concat("_h"));
1125
1126 Builder.CreateAlignedStore(CreateHandle, GV, GV->getPointerAlignment(DL));
1127 Builder.CreateRetVoid();
1128
1129 CGM.AddCXXGlobalInit(InitResFunc);
1130}
1131
1132void CGHLSLRuntime::initializeBufferFromBinding(const HLSLBufferDecl *BufDecl,
1133 llvm::GlobalVariable *GV) {
1134 ResourceBindingAttrs Binding(BufDecl);
1135 assert(Binding.hasBinding() &&
1136 "cbuffer/tbuffer should always have resource binding attribute");
1137
1138 auto *Index = llvm::ConstantInt::get(CGM.IntTy, 0);
1139 auto *RangeSize = llvm::ConstantInt::get(CGM.IntTy, 1);
1140 auto *Space = llvm::ConstantInt::get(CGM.IntTy, Binding.getSpace());
1141 Value *Name = buildNameForResource(BufDecl->getName(), CGM);
1142
1143 // buffer with explicit binding
1144 if (Binding.isExplicit()) {
1145 llvm::Intrinsic::ID IntrinsicID =
1146 CGM.getHLSLRuntime().getCreateHandleFromBindingIntrinsic();
1147 auto *RegSlot = llvm::ConstantInt::get(CGM.IntTy, Binding.getSlot());
1148 SmallVector<Value *> Args{Space, RegSlot, RangeSize, Index, Name};
1149 initializeBuffer(CGM, GV, IntrinsicID, Args);
1150 } else {
1151 // buffer with implicit binding
1152 llvm::Intrinsic::ID IntrinsicID =
1153 CGM.getHLSLRuntime().getCreateHandleFromImplicitBindingIntrinsic();
1154 auto *OrderID =
1155 llvm::ConstantInt::get(CGM.IntTy, Binding.getImplicitOrderID());
1156 SmallVector<Value *> Args{OrderID, Space, RangeSize, Index, Name};
1157 initializeBuffer(CGM, GV, IntrinsicID, Args);
1158 }
1159}
1160
1162 llvm::GlobalVariable *GV) {
1163 if (auto Attr = VD->getAttr<HLSLVkExtBuiltinInputAttr>())
1164 addSPIRVBuiltinDecoration(GV, Attr->getBuiltIn());
1165 if (auto Attr = VD->getAttr<HLSLVkExtBuiltinOutputAttr>())
1166 addSPIRVBuiltinDecoration(GV, Attr->getBuiltIn());
1167}
1168
1169llvm::Instruction *CGHLSLRuntime::getConvergenceToken(BasicBlock &BB) {
1170 if (!CGM.shouldEmitConvergenceTokens())
1171 return nullptr;
1172
1173 auto E = BB.end();
1174 for (auto I = BB.begin(); I != E; ++I) {
1175 auto *II = dyn_cast<llvm::IntrinsicInst>(&*I);
1176 if (II && llvm::isConvergenceControlIntrinsic(II->getIntrinsicID())) {
1177 return II;
1178 }
1179 }
1180 llvm_unreachable("Convergence token should have been emitted.");
1181 return nullptr;
1182}
1183
1184class OpaqueValueVisitor : public RecursiveASTVisitor<OpaqueValueVisitor> {
1185public:
1189
1191 // These need to be bound in CodeGenFunction::EmitHLSLOutArgLValues
1192 // or CodeGenFunction::EmitHLSLOutArgExpr. If they are part of this
1193 // traversal, the temporary containing the copy out will not have
1194 // been created yet.
1195 return false;
1196 }
1197
1199 // Traverse the source expression first.
1200 if (E->getSourceExpr())
1202
1203 // Then add this OVE if we haven't seen it before.
1204 if (Visited.insert(E).second)
1205 OVEs.push_back(E);
1206
1207 return true;
1208 }
1209};
1210
1212 InitListExpr *E) {
1213
1214 typedef CodeGenFunction::OpaqueValueMappingData OpaqueValueMappingData;
1215 OpaqueValueVisitor Visitor;
1216 Visitor.TraverseStmt(E);
1217 for (auto *OVE : Visitor.OVEs) {
1218 if (CGF.isOpaqueValueEmitted(OVE))
1219 continue;
1220 if (OpaqueValueMappingData::shouldBindAsLValue(OVE)) {
1221 LValue LV = CGF.EmitLValue(OVE->getSourceExpr());
1222 OpaqueValueMappingData::bind(CGF, OVE, LV);
1223 } else {
1224 RValue RV = CGF.EmitAnyExpr(OVE->getSourceExpr());
1225 OpaqueValueMappingData::bind(CGF, OVE, RV);
1226 }
1227 }
1228}
1229
1231 const ArraySubscriptExpr *ArraySubsExpr, CodeGenFunction &CGF) {
1232 assert((ArraySubsExpr->getType()->isHLSLResourceRecord() ||
1233 ArraySubsExpr->getType()->isHLSLResourceRecordArray()) &&
1234 "expected resource array subscript expression");
1235
1236 // Let clang codegen handle local and static resource array subscripts,
1237 // or when the subscript references on opaque expression (as part of
1238 // ArrayInitLoopExpr AST node).
1239 const VarDecl *ArrayDecl =
1240 dyn_cast_or_null<VarDecl>(getArrayDecl(ArraySubsExpr));
1241 if (!ArrayDecl || !ArrayDecl->hasGlobalStorage() ||
1242 ArrayDecl->getStorageClass() == SC_Static)
1243 return std::nullopt;
1244
1245 // get the resource array type
1246 ASTContext &AST = ArrayDecl->getASTContext();
1247 const Type *ResArrayTy = ArrayDecl->getType().getTypePtr();
1248 assert(ResArrayTy->isHLSLResourceRecordArray() &&
1249 "expected array of resource classes");
1250
1251 // Iterate through all nested array subscript expressions to calculate
1252 // the index in the flattened resource array (if this is a multi-
1253 // dimensional array). The index is calculated as a sum of all indices
1254 // multiplied by the total size of the array at that level.
1255 Value *Index = nullptr;
1256 const ArraySubscriptExpr *ASE = ArraySubsExpr;
1257 while (ASE != nullptr) {
1258 Value *SubIndex = CGF.EmitScalarExpr(ASE->getIdx());
1259 if (const auto *ArrayTy =
1260 dyn_cast<ConstantArrayType>(ASE->getType().getTypePtr())) {
1261 Value *Multiplier = llvm::ConstantInt::get(
1262 CGM.IntTy, AST.getConstantArrayElementCount(ArrayTy));
1263 SubIndex = CGF.Builder.CreateMul(SubIndex, Multiplier);
1264 }
1265 Index = Index ? CGF.Builder.CreateAdd(Index, SubIndex) : SubIndex;
1266 ASE = dyn_cast<ArraySubscriptExpr>(ASE->getBase()->IgnoreParenImpCasts());
1267 }
1268
1269 // Find binding info for the resource array. For implicit binding
1270 // an HLSLResourceBindingAttr should have been added by SemaHLSL.
1271 ResourceBindingAttrs Binding(ArrayDecl);
1272 assert(Binding.hasBinding() &&
1273 "resource array must have a binding attribute");
1274
1275 // Find the individual resource type.
1276 QualType ResultTy = ArraySubsExpr->getType();
1277 QualType ResourceTy =
1278 ResultTy->isArrayType() ? AST.getBaseElementType(ResultTy) : ResultTy;
1279
1280 // Create a temporary variable for the result, which is either going
1281 // to be a single resource instance or a local array of resources (we need to
1282 // return an LValue).
1283 RawAddress TmpVar = CGF.CreateMemTemp(ResultTy);
1284 if (CGF.EmitLifetimeStart(TmpVar.getPointer()))
1286 NormalEHLifetimeMarker, TmpVar);
1287
1292
1293 // Calculate total array size (= range size).
1294 llvm::Value *Range = llvm::ConstantInt::getSigned(
1295 CGM.IntTy, getTotalArraySize(AST, ResArrayTy));
1296
1297 // If the result of the subscript operation is a single resource, call the
1298 // constructor.
1299 if (ResultTy == ResourceTy) {
1300 CallArgList Args;
1301 CXXMethodDecl *CreateMethod = lookupResourceInitMethodAndSetupArgs(
1302 CGF.CGM, ResourceTy->getAsCXXRecordDecl(), Range, Index,
1303 ArrayDecl->getName(), Binding, Args);
1304
1305 if (!CreateMethod)
1306 // This can happen if someone creates an array of structs that looks like
1307 // an HLSL resource record array but it does not have the required static
1308 // create method. No binding will be generated for it.
1309 return std::nullopt;
1310
1311 callResourceInitMethod(CGF, CreateMethod, Args, ValueSlot.getAddress());
1312
1313 } else {
1314 // The result of the subscript operation is a local resource array which
1315 // needs to be initialized.
1316 const ConstantArrayType *ArrayTy =
1318 std::optional<llvm::Value *> EndIndex = initializeLocalResourceArray(
1319 CGF, ResourceTy->getAsCXXRecordDecl(), ArrayTy, ValueSlot, Range, Index,
1320 ArrayDecl->getName(), Binding, {llvm::ConstantInt::get(CGM.IntTy, 0)},
1321 ArraySubsExpr->getExprLoc());
1322 if (!EndIndex)
1323 return std::nullopt;
1324 }
1325 return CGF.MakeAddrLValue(TmpVar, ResultTy, AlignmentSource::Decl);
1326}
1327
1328// If RHSExpr is a global resource array, initialize all of its resources and
1329// set them into LHS. Returns false if no copy has been performed and the
1330// array copy should be handled by Clang codegen.
1332 CodeGenFunction &CGF) {
1333 QualType ResultTy = RHSExpr->getType();
1334 assert(ResultTy->isHLSLResourceRecordArray() && "expected resource array");
1335
1336 // Let Clang codegen handle local and static resource array copies.
1337 const VarDecl *ArrayDecl = dyn_cast_or_null<VarDecl>(getArrayDecl(RHSExpr));
1338 if (!ArrayDecl || !ArrayDecl->hasGlobalStorage() ||
1339 ArrayDecl->getStorageClass() == SC_Static)
1340 return false;
1341
1342 // Find binding info for the resource array. For implicit binding
1343 // the HLSLResourceBindingAttr should have been added by SemaHLSL.
1344 ResourceBindingAttrs Binding(ArrayDecl);
1345 assert(Binding.hasBinding() &&
1346 "resource array must have a binding attribute");
1347
1348 // Find the individual resource type.
1349 ASTContext &AST = ArrayDecl->getASTContext();
1350 QualType ResTy = AST.getBaseElementType(ResultTy);
1351 const auto *ResArrayTy = cast<ConstantArrayType>(ResultTy.getTypePtr());
1352
1353 // Use the provided LHS for the result.
1358
1359 // Create Value for index and total array size (= range size).
1360 int Size = getTotalArraySize(AST, ResArrayTy);
1361 llvm::Value *Zero = llvm::ConstantInt::get(CGM.IntTy, 0);
1362 llvm::Value *Range = llvm::ConstantInt::get(CGM.IntTy, Size);
1363
1364 // Initialize individual resources in the array into LHS.
1365 std::optional<llvm::Value *> EndIndex = initializeLocalResourceArray(
1366 CGF, ResTy->getAsCXXRecordDecl(), ResArrayTy, ValueSlot, Range, Zero,
1367 ArrayDecl->getName(), Binding, {Zero}, RHSExpr->getExprLoc());
1368 return EndIndex.has_value();
1369}
1370
1372 SourceLocation Loc,
1373 CodeGenFunction &CGF) {
1374
1375 assert(LV.getType()->isConstantMatrixType() && "expected matrix type");
1377 "expected cbuffer matrix");
1378
1379 QualType MatQualTy = LV.getType();
1380 llvm::Type *MemTy = CGF.ConvertTypeForMem(MatQualTy);
1381 llvm::Type *LayoutTy = HLSLBufferLayoutBuilder(CGF.CGM).layOutType(MatQualTy);
1382
1383 if (LayoutTy == MemTy)
1384 return LV.getAddress();
1385
1386 Address SrcAddr = LV.getAddress();
1387 // NOTE: B\C CreateMemTemp flattens MatrixTypes which causes
1388 // overlapping GEPs in emitBufferCopy. Use CreateTempAlloca with
1389 // the non-padded layout.
1390 CharUnits Align =
1391 CharUnits::fromQuantity(CGF.CGM.getDataLayout().getABITypeAlign(MemTy));
1392 RawAddress DestAlloca = CGF.CreateTempAlloca(MemTy, Align, "matrix.buf.copy");
1393 emitBufferCopy(CGF, DestAlloca, SrcAddr, MatQualTy);
1394 return DestAlloca;
1395}
1396
1398 const ArraySubscriptExpr *E, CodeGenFunction &CGF,
1399 llvm::function_ref<llvm::Value *(bool Promote)> EmitIdxAfterBase) {
1400 // Find the element type to index by first padding the element type per HLSL
1401 // buffer rules, and then padding out to a 16-byte register boundary if
1402 // necessary.
1403 llvm::Type *LayoutTy =
1405 uint64_t LayoutSizeInBits =
1406 CGM.getDataLayout().getTypeSizeInBits(LayoutTy).getFixedValue();
1407 CharUnits ElementSize = CharUnits::fromQuantity(LayoutSizeInBits / 8);
1408 CharUnits RowAlignedSize = ElementSize.alignTo(CharUnits::fromQuantity(16));
1409 if (RowAlignedSize > ElementSize) {
1410 llvm::Type *Padding = CGM.getTargetCodeGenInfo().getHLSLPadding(
1411 CGM, RowAlignedSize - ElementSize);
1412 assert(Padding && "No padding type for target?");
1413 LayoutTy = llvm::StructType::get(CGF.getLLVMContext(), {LayoutTy, Padding},
1414 /*isPacked=*/true);
1415 }
1416
1417 // If the layout type doesn't introduce any padding, we don't need to do
1418 // anything special.
1419 llvm::Type *OrigTy = CGF.CGM.getTypes().ConvertTypeForMem(E->getType());
1420 if (LayoutTy == OrigTy)
1421 return std::nullopt;
1422
1423 LValueBaseInfo EltBaseInfo;
1424 TBAAAccessInfo EltTBAAInfo;
1425
1426 // Index into the object as-if we have an array of the padded element type,
1427 // and then dereference the element itself to avoid reading padding that may
1428 // be past the end of the in-memory object.
1430 llvm::Value *Idx = EmitIdxAfterBase(/*Promote*/ true);
1431 Indices.push_back(Idx);
1432 Indices.push_back(llvm::ConstantInt::get(CGF.Int32Ty, 0));
1433
1434 if (CGF.getLangOpts().EmitStructuredGEP) {
1435 // The fact that we emit an array-to-pointer decay might be an oversight,
1436 // but for now, we simply ignore it (see #179951).
1437 const CastExpr *CE = cast<CastExpr>(E->getBase());
1438 assert(CE->getCastKind() == CastKind::CK_ArrayToPointerDecay);
1439
1440 LValue LV = CGF.EmitLValue(CE->getSubExpr());
1441 Address Addr = LV.getAddress();
1442 LayoutTy = llvm::ArrayType::get(
1443 LayoutTy,
1444 cast<llvm::ArrayType>(Addr.getElementType())->getNumElements());
1445 auto *GEP = cast<StructuredGEPInst>(CGF.Builder.CreateStructuredGEP(
1446 LayoutTy, Addr.emitRawPointer(CGF), Indices, "cbufferidx"));
1447 Addr =
1448 Address(GEP, GEP->getResultElementType(), RowAlignedSize, KnownNonNull);
1449 return CGF.MakeAddrLValue(Addr, E->getType(), EltBaseInfo, EltTBAAInfo);
1450 }
1451
1452 Address Addr =
1453 CGF.EmitPointerWithAlignment(E->getBase(), &EltBaseInfo, &EltTBAAInfo);
1454 llvm::Value *GEP = CGF.Builder.CreateGEP(LayoutTy, Addr.emitRawPointer(CGF),
1455 Indices, "cbufferidx");
1456 Addr = Address(GEP, Addr.getElementType(), RowAlignedSize, KnownNonNull);
1457 return CGF.MakeAddrLValue(Addr, E->getType(), EltBaseInfo, EltTBAAInfo);
1458}
1459
1460namespace {
1461/// Utility for emitting copies following the HLSL buffer layout rules (ie,
1462/// copying out of a cbuffer).
1463class HLSLBufferCopyEmitter {
1464 CodeGenFunction &CGF;
1465 Address DestPtr;
1466 Address SrcPtr;
1467 llvm::Type *LayoutTy = nullptr;
1468
1469 SmallVector<llvm::Value *> CurStoreIndices;
1470 SmallVector<llvm::Value *> CurLoadIndices;
1471
1472 void emitCopyAtIndices(llvm::Type *FieldTy, llvm::ConstantInt *StoreIndex,
1473 llvm::ConstantInt *LoadIndex) {
1474 CurStoreIndices.push_back(StoreIndex);
1475 CurLoadIndices.push_back(LoadIndex);
1476 llvm::scope_exit RestoreIndices([&]() {
1477 CurStoreIndices.pop_back();
1478 CurLoadIndices.pop_back();
1479 });
1480
1481 // First, see if this is some kind of aggregate and recurse.
1482 if (processArray(FieldTy))
1483 return;
1484 if (processBufferLayoutArray(FieldTy))
1485 return;
1486 if (processStruct(FieldTy))
1487 return;
1488
1489 // When we have a scalar or vector element we can emit the copy.
1491 CGF.CGM.getDataLayout().getABITypeAlign(FieldTy));
1492 Address SrcGEP = RawAddress(
1493 CGF.Builder.CreateInBoundsGEP(LayoutTy, SrcPtr.getBasePointer(),
1494 CurLoadIndices, "cbuf.src"),
1495 FieldTy, Align, SrcPtr.isKnownNonNull());
1496 Address DestGEP = CGF.Builder.CreateInBoundsGEP(
1497 DestPtr, CurStoreIndices, FieldTy, Align, "cbuf.dest");
1498 llvm::Value *Load = CGF.Builder.CreateLoad(SrcGEP, "cbuf.load");
1499 CGF.Builder.CreateStore(Load, DestGEP);
1500 }
1501
1502 bool processArray(llvm::Type *FieldTy) {
1503 auto *AT = dyn_cast<llvm::ArrayType>(FieldTy);
1504 if (!AT)
1505 return false;
1506
1507 // If we have an llvm::ArrayType this is just a regular array with no top
1508 // level padding, so all we need to do is copy each member.
1509 for (unsigned I = 0, E = AT->getNumElements(); I < E; ++I)
1510 emitCopyAtIndices(AT->getElementType(),
1511 llvm::ConstantInt::get(CGF.SizeTy, I),
1512 llvm::ConstantInt::get(CGF.SizeTy, I));
1513 return true;
1514 }
1515
1516 bool processBufferLayoutArray(llvm::Type *FieldTy) {
1517 // A buffer layout array is a struct with two elements: the padded array,
1518 // and the last element. That is, is should look something like this:
1519 //
1520 // { [%n x { %type, %padding }], %type }
1521 //
1522 auto *ST = dyn_cast<llvm::StructType>(FieldTy);
1523 if (!ST || ST->getNumElements() != 2)
1524 return false;
1525
1526 auto *PaddedEltsTy = dyn_cast<llvm::ArrayType>(ST->getElementType(0));
1527 if (!PaddedEltsTy)
1528 return false;
1529
1530 auto *PaddedTy = dyn_cast<llvm::StructType>(PaddedEltsTy->getElementType());
1531 if (!PaddedTy || PaddedTy->getNumElements() != 2)
1532 return false;
1533
1535 PaddedTy->getElementType(1)))
1536 return false;
1537
1538 llvm::Type *ElementTy = ST->getElementType(1);
1539 if (PaddedTy->getElementType(0) != ElementTy)
1540 return false;
1541
1542 // All but the last of the logical array elements are in the padded array.
1543 unsigned NumElts = PaddedEltsTy->getNumElements() + 1;
1544
1545 // Add an extra indirection to the load for the struct and walk the
1546 // array prefix.
1547 CurLoadIndices.push_back(llvm::ConstantInt::get(CGF.Int32Ty, 0));
1548 for (unsigned I = 0; I < NumElts - 1; ++I) {
1549 // We need to copy the element itself, without the padding.
1550 CurLoadIndices.push_back(llvm::ConstantInt::get(CGF.SizeTy, I));
1551 emitCopyAtIndices(ElementTy, llvm::ConstantInt::get(CGF.SizeTy, I),
1552 llvm::ConstantInt::get(CGF.Int32Ty, 0));
1553 CurLoadIndices.pop_back();
1554 }
1555 CurLoadIndices.pop_back();
1556
1557 // Now copy the last element.
1558 emitCopyAtIndices(ElementTy,
1559 llvm::ConstantInt::get(CGF.SizeTy, NumElts - 1),
1560 llvm::ConstantInt::get(CGF.Int32Ty, 1));
1561
1562 return true;
1563 }
1564
1565 bool processStruct(llvm::Type *FieldTy) {
1566 auto *ST = dyn_cast<llvm::StructType>(FieldTy);
1567 if (!ST)
1568 return false;
1569
1570 // Copy the struct field by field, but skip any explicit padding.
1571 unsigned Skipped = 0;
1572 for (unsigned I = 0, E = ST->getNumElements(); I < E; ++I) {
1573 llvm::Type *ElementTy = ST->getElementType(I);
1574 if (CGF.CGM.getTargetCodeGenInfo().isHLSLPadding(ElementTy))
1575 ++Skipped;
1576 else
1577 emitCopyAtIndices(ElementTy, llvm::ConstantInt::get(CGF.Int32Ty, I),
1578 llvm::ConstantInt::get(CGF.Int32Ty, I + Skipped));
1579 }
1580 return true;
1581 }
1582
1583public:
1584 HLSLBufferCopyEmitter(CodeGenFunction &CGF, Address DestPtr, Address SrcPtr)
1585 : CGF(CGF), DestPtr(DestPtr), SrcPtr(SrcPtr) {}
1586
1587 bool emitCopy(QualType CType) {
1588 LayoutTy = HLSLBufferLayoutBuilder(CGF.CGM).layOutType(CType);
1589
1590 // TODO: We should be able to fall back to a regular memcpy if the layout
1591 // type doesn't have any padding, but that runs into issues in the backend
1592 // currently.
1593 //
1594 // See https://github.com/llvm/wg-hlsl/issues/351
1595 emitCopyAtIndices(LayoutTy, llvm::ConstantInt::get(CGF.SizeTy, 0),
1596 llvm::ConstantInt::get(CGF.SizeTy, 0));
1597 return true;
1598 }
1599};
1600} // namespace
1601
1603 Address SrcPtr, QualType CType) {
1604 return HLSLBufferCopyEmitter(CGF, DestPtr, SrcPtr).emitCopy(CType);
1605}
1606
1608 const MemberExpr *E) {
1609 LValue Base =
1611 auto *Field = dyn_cast<FieldDecl>(E->getMemberDecl());
1612 assert(Field && "Unexpected access into HLSL buffer");
1613
1614 const RecordDecl *Rec = Field->getParent();
1615
1616 // Work out the buffer layout type to index into.
1617 QualType RecType = CGM.getContext().getCanonicalTagType(Rec);
1618 assert(RecType->isStructureOrClassType() && "Invalid type in HLSL buffer");
1619 // Since this is a member of an object in the buffer and not the buffer's
1620 // struct/class itself, we shouldn't have any offsets on the members we need
1621 // to contend with.
1622 CGHLSLOffsetInfo EmptyOffsets;
1623 llvm::StructType *LayoutTy = HLSLBufferLayoutBuilder(CGM).layOutStruct(
1624 RecType->getAsCanonical<RecordType>(), EmptyOffsets);
1625
1626 // Get the field index for the layout struct, accounting for padding.
1627 unsigned FieldIdx =
1628 CGM.getTypes().getCGRecordLayout(Rec).getLLVMFieldNo(Field);
1629 assert(FieldIdx < LayoutTy->getNumElements() &&
1630 "Layout struct is smaller than member struct");
1631 unsigned Skipped = 0;
1632 for (unsigned I = 0; I <= FieldIdx;) {
1633 llvm::Type *ElementTy = LayoutTy->getElementType(I + Skipped);
1634 if (CGF.CGM.getTargetCodeGenInfo().isHLSLPadding(ElementTy))
1635 ++Skipped;
1636 else
1637 ++I;
1638 }
1639 FieldIdx += Skipped;
1640 assert(FieldIdx < LayoutTy->getNumElements() && "Access out of bounds");
1641
1642 // Now index into the struct, making sure that the type we return is the
1643 // buffer layout type rather than the original type in the AST.
1644 QualType FieldType = Field->getType();
1645 llvm::Type *FieldLLVMTy = CGM.getTypes().ConvertTypeForMem(FieldType);
1647 CGF.CGM.getDataLayout().getABITypeAlign(FieldLLVMTy));
1648
1649 Value *Ptr = CGF.getLangOpts().EmitStructuredGEP
1650 ? CGF.Builder.CreateStructuredGEP(
1651 LayoutTy, Base.getPointer(CGF),
1652 llvm::ConstantInt::get(CGM.IntTy, FieldIdx))
1653 : CGF.Builder.CreateStructGEP(LayoutTy, Base.getPointer(CGF),
1654 FieldIdx, Field->getName());
1655 Address Addr(Ptr, FieldLLVMTy, Align, KnownNonNull);
1656
1657 LValue LV = LValue::MakeAddr(Addr, FieldType, CGM.getContext(),
1659 CGM.getTBAAAccessInfo(FieldType));
1660 LV.getQuals().addCVRQualifiers(Base.getVRQualifiers());
1661
1662 return LV;
1663}
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
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:3784
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 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)
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:5359
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:6372
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:3810
int64_t getSExtSize() const
Return the size sign-extended as a uint64_t.
Definition TypeBase.h:3892
DeclContext * getParent()
getParent - Returns the containing DeclContext.
Definition DeclBase.h:2122
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:581
bool hasAttrs() const
Definition DeclBase.h:526
ASTContext & getASTContext() const LLVM_READONLY
Definition DeclBase.cpp:547
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: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:3175
Represents a function declaration or definition.
Definition Decl.h:2015
const ParmVarDecl * getParamDecl(unsigned i) const
Definition Decl.h:2812
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:2877
Represents a prototype with parameter type info, e.g.
Definition TypeBase.h:5357
HLSLBufferDecl - Represent a cbuffer or tbuffer declaration.
Definition Decl.h:5211
bool isCBuffer() const
Definition Decl.h:5255
const CXXRecordDecl * getLayoutStruct() const
Definition Decl.h:5258
bool hasValidPackoffset() const
Definition Decl.h:5257
buffer_decl_range buffer_decls() const
Definition Decl.h:5286
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:5328
llvm::dxbc::RootSignatureVersion getVersion() const
Definition Decl.h:5326
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:1805
A (possibly-)qualified type.
Definition TypeBase.h:937
const Type * getTypePtr() const
Retrieves a pointer to the underlying (unqualified) type.
Definition TypeBase.h:8431
LangAS getAddressSpace() const
Return the address space of this type.
Definition TypeBase.h:8557
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:4342
unsigned getNumFields() const
Returns the number of fields (non-static data members) in this record.
Definition Decl.h:4558
field_iterator field_begin() const
Definition Decl.cpp:5277
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: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:1866
bool isIncompleteArrayType() const
Definition TypeBase.h:8775
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:8767
bool isConstantMatrixType() const
Definition TypeBase.h:8835
bool isHLSLResourceRecord() const
Definition Type.cpp:5448
bool isStructureOrClassType() const
Definition Type.cpp:708
const T * getAsCanonical() const
If this type is canonically the specified type, return its canonical type cast to that specified type...
Definition TypeBase.h:2971
const T * getAs() const
Member-template getAs<specific type>'.
Definition TypeBase.h:9261
const Type * getUnqualifiedDesugaredType() const
Return the specified type with any "sugar" removed from the type, removing any typedefs,...
Definition Type.cpp:655
bool isHLSLResourceRecordArray() const
Definition Type.cpp:5452
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:1241
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: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
unsigned getCounterImplicitOrderID() const