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
959 llvm::DenseMap<const DeclaratorDecl *, std::pair<llvm::Value *, llvm::Type *>>
960 OutputSemantic;
961
962 unsigned SRetOffset = 0;
963 for (const auto &Param : Fn->args()) {
964 if (Param.hasStructRetAttr()) {
965 SRetOffset = 1;
966 llvm::Type *VarType = Param.getParamStructRetType();
967 llvm::Value *Var = B.CreateAlloca(VarType);
968 OutputSemantic.try_emplace(FD, std::make_pair(Var, VarType));
969 Args.push_back(Var);
970 continue;
971 }
972
973 const ParmVarDecl *PD = FD->getParamDecl(Param.getArgNo() - SRetOffset);
974 llvm::Value *SemanticValue = nullptr;
975 // FIXME: support inout/out parameters for semantics.
976 if ([[maybe_unused]] HLSLParamModifierAttr *MA =
977 PD->getAttr<HLSLParamModifierAttr>()) {
978 llvm_unreachable("Not handled yet");
979 } else {
980 llvm::Type *ParamType =
981 Param.hasByValAttr() ? Param.getParamByValType() : Param.getType();
982 auto AttrBegin = PD->specific_attr_begin<HLSLAppliedSemanticAttr>();
983 auto AttrEnd = PD->specific_attr_end<HLSLAppliedSemanticAttr>();
984 auto Result =
985 handleSemanticLoad(B, FD, ParamType, PD, AttrBegin, AttrEnd);
986 SemanticValue = Result.first;
987 if (!SemanticValue)
988 return;
989 if (Param.hasByValAttr()) {
990 llvm::Value *Var = B.CreateAlloca(Param.getParamByValType());
991 B.CreateStore(SemanticValue, Var);
992 SemanticValue = Var;
993 }
994 }
995
996 assert(SemanticValue);
997 Args.push_back(SemanticValue);
998 }
999
1000 CallInst *CI = B.CreateCall(FunctionCallee(Fn), Args, OB);
1001 CI->setCallingConv(Fn->getCallingConv());
1002
1003 if (Fn->getReturnType() != CGM.VoidTy)
1004 // Element type is unused, so set to dummy value (NULL).
1005 OutputSemantic.try_emplace(FD, std::make_pair(CI, nullptr));
1006
1007 for (auto &[Decl, SourcePair] : OutputSemantic) {
1008 llvm::Value *Source = SourcePair.first;
1009 llvm::Type *ElementType = SourcePair.second;
1010 AllocaInst *AI = dyn_cast<AllocaInst>(Source);
1011 llvm::Value *SourceValue = AI ? B.CreateLoad(ElementType, Source) : Source;
1012
1013 auto AttrBegin = Decl->specific_attr_begin<HLSLAppliedSemanticAttr>();
1014 auto AttrEnd = Decl->specific_attr_end<HLSLAppliedSemanticAttr>();
1015 handleSemanticStore(B, FD, SourceValue, Decl, AttrBegin, AttrEnd);
1016 }
1017
1018 B.CreateRetVoid();
1019
1020 // Add and identify root signature to function, if applicable
1021 for (const Attr *Attr : FD->getAttrs()) {
1022 if (const auto *RSAttr = dyn_cast<RootSignatureAttr>(Attr)) {
1023 auto *RSDecl = RSAttr->getSignatureDecl();
1024 addRootSignatureMD(RSDecl->getVersion(), RSDecl->getRootElements(),
1025 EntryFn, M);
1026 }
1027 }
1028}
1029
1030static void gatherFunctions(SmallVectorImpl<Function *> &Fns, llvm::Module &M,
1031 bool CtorOrDtor) {
1032 const auto *GV =
1033 M.getNamedGlobal(CtorOrDtor ? "llvm.global_ctors" : "llvm.global_dtors");
1034 if (!GV)
1035 return;
1036 const auto *CA = dyn_cast<ConstantArray>(GV->getInitializer());
1037 if (!CA)
1038 return;
1039 // The global_ctor array elements are a struct [Priority, Fn *, COMDat].
1040 // HLSL neither supports priorities or COMDat values, so we will check those
1041 // in an assert but not handle them.
1042
1043 for (const auto &Ctor : CA->operands()) {
1045 continue;
1046 ConstantStruct *CS = cast<ConstantStruct>(Ctor);
1047
1048 assert(cast<ConstantInt>(CS->getOperand(0))->getValue() == 65535 &&
1049 "HLSL doesn't support setting priority for global ctors.");
1050 assert(isa<ConstantPointerNull>(CS->getOperand(2)) &&
1051 "HLSL doesn't support COMDat for global ctors.");
1052 Fns.push_back(cast<Function>(CS->getOperand(1)));
1053 }
1054}
1055
1057 llvm::Module &M = CGM.getModule();
1060 gatherFunctions(CtorFns, M, true);
1061 gatherFunctions(DtorFns, M, false);
1062
1063 // Insert a call to the global constructor at the beginning of the entry block
1064 // to externally exported functions. This is a bit of a hack, but HLSL allows
1065 // global constructors, but doesn't support driver initialization of globals.
1066 for (auto &F : M.functions()) {
1067 if (!F.hasFnAttribute("hlsl.shader"))
1068 continue;
1069 auto *Token = getConvergenceToken(F.getEntryBlock());
1070 Instruction *IP = &*F.getEntryBlock().begin();
1072 if (Token) {
1073 llvm::Value *bundleArgs[] = {Token};
1074 OB.emplace_back("convergencectrl", bundleArgs);
1075 IP = Token->getNextNode();
1076 }
1077 IRBuilder<> B(IP);
1078 for (auto *Fn : CtorFns) {
1079 auto CI = B.CreateCall(FunctionCallee(Fn), {}, OB);
1080 CI->setCallingConv(Fn->getCallingConv());
1081 }
1082
1083 // Insert global dtors before the terminator of the last instruction
1084 B.SetInsertPoint(F.back().getTerminator());
1085 for (auto *Fn : DtorFns) {
1086 auto CI = B.CreateCall(FunctionCallee(Fn), {}, OB);
1087 CI->setCallingConv(Fn->getCallingConv());
1088 }
1089 }
1090
1091 // No need to keep global ctors/dtors for non-lib profile after call to
1092 // ctors/dtors added for entry.
1093 Triple T(M.getTargetTriple());
1094 if (T.getEnvironment() != Triple::EnvironmentType::Library) {
1095 if (auto *GV = M.getNamedGlobal("llvm.global_ctors"))
1096 GV->eraseFromParent();
1097 if (auto *GV = M.getNamedGlobal("llvm.global_dtors"))
1098 GV->eraseFromParent();
1099 }
1100}
1101
1102static void initializeBuffer(CodeGenModule &CGM, llvm::GlobalVariable *GV,
1103 Intrinsic::ID IntrID,
1105
1106 LLVMContext &Ctx = CGM.getLLVMContext();
1107 llvm::Function *InitResFunc = llvm::Function::Create(
1108 llvm::FunctionType::get(CGM.VoidTy, false),
1109 llvm::GlobalValue::InternalLinkage,
1110 ("_init_buffer_" + GV->getName()).str(), CGM.getModule());
1111 InitResFunc->addFnAttr(llvm::Attribute::AlwaysInline);
1112
1113 llvm::BasicBlock *EntryBB =
1114 llvm::BasicBlock::Create(Ctx, "entry", InitResFunc);
1115 CGBuilderTy Builder(CGM, Ctx);
1116 const DataLayout &DL = CGM.getModule().getDataLayout();
1117 Builder.SetInsertPoint(EntryBB);
1118
1119 // Make sure the global variable is buffer resource handle
1120 llvm::Type *HandleTy = GV->getValueType();
1121 assert(HandleTy->isTargetExtTy() && "unexpected type of the buffer global");
1122
1123 llvm::Value *CreateHandle = Builder.CreateIntrinsic(
1124 /*ReturnType=*/HandleTy, IntrID, Args, nullptr,
1125 Twine(GV->getName()).concat("_h"));
1126
1127 Builder.CreateAlignedStore(CreateHandle, GV, GV->getPointerAlignment(DL));
1128 Builder.CreateRetVoid();
1129
1130 CGM.AddCXXGlobalInit(InitResFunc);
1131}
1132
1133void CGHLSLRuntime::initializeBufferFromBinding(const HLSLBufferDecl *BufDecl,
1134 llvm::GlobalVariable *GV) {
1135 ResourceBindingAttrs Binding(BufDecl);
1136 assert(Binding.hasBinding() &&
1137 "cbuffer/tbuffer should always have resource binding attribute");
1138
1139 auto *Index = llvm::ConstantInt::get(CGM.IntTy, 0);
1140 auto *RangeSize = llvm::ConstantInt::get(CGM.IntTy, 1);
1141 auto *Space = llvm::ConstantInt::get(CGM.IntTy, Binding.getSpace());
1142 Value *Name = buildNameForResource(BufDecl->getName(), CGM);
1143
1144 // buffer with explicit binding
1145 if (Binding.isExplicit()) {
1146 llvm::Intrinsic::ID IntrinsicID =
1147 CGM.getHLSLRuntime().getCreateHandleFromBindingIntrinsic();
1148 auto *RegSlot = llvm::ConstantInt::get(CGM.IntTy, Binding.getSlot());
1149 SmallVector<Value *> Args{Space, RegSlot, RangeSize, Index, Name};
1150 initializeBuffer(CGM, GV, IntrinsicID, Args);
1151 } else {
1152 // buffer with implicit binding
1153 llvm::Intrinsic::ID IntrinsicID =
1154 CGM.getHLSLRuntime().getCreateHandleFromImplicitBindingIntrinsic();
1155 auto *OrderID =
1156 llvm::ConstantInt::get(CGM.IntTy, Binding.getImplicitOrderID());
1157 SmallVector<Value *> Args{OrderID, Space, RangeSize, Index, Name};
1158 initializeBuffer(CGM, GV, IntrinsicID, Args);
1159 }
1160}
1161
1163 llvm::GlobalVariable *GV) {
1164 if (auto Attr = VD->getAttr<HLSLVkExtBuiltinInputAttr>())
1165 addSPIRVBuiltinDecoration(GV, Attr->getBuiltIn());
1166 if (auto Attr = VD->getAttr<HLSLVkExtBuiltinOutputAttr>())
1167 addSPIRVBuiltinDecoration(GV, Attr->getBuiltIn());
1168}
1169
1170llvm::Instruction *CGHLSLRuntime::getConvergenceToken(BasicBlock &BB) {
1171 if (!CGM.shouldEmitConvergenceTokens())
1172 return nullptr;
1173
1174 auto E = BB.end();
1175 for (auto I = BB.begin(); I != E; ++I) {
1176 auto *II = dyn_cast<llvm::IntrinsicInst>(&*I);
1177 if (II && llvm::isConvergenceControlIntrinsic(II->getIntrinsicID())) {
1178 return II;
1179 }
1180 }
1181 llvm_unreachable("Convergence token should have been emitted.");
1182 return nullptr;
1183}
1184
1185class OpaqueValueVisitor : public RecursiveASTVisitor<OpaqueValueVisitor> {
1186public:
1190
1192 // These need to be bound in CodeGenFunction::EmitHLSLOutArgLValues
1193 // or CodeGenFunction::EmitHLSLOutArgExpr. If they are part of this
1194 // traversal, the temporary containing the copy out will not have
1195 // been created yet.
1196 return false;
1197 }
1198
1200 // Traverse the source expression first.
1201 if (E->getSourceExpr())
1203
1204 // Then add this OVE if we haven't seen it before.
1205 if (Visited.insert(E).second)
1206 OVEs.push_back(E);
1207
1208 return true;
1209 }
1210};
1211
1213 InitListExpr *E) {
1214
1215 typedef CodeGenFunction::OpaqueValueMappingData OpaqueValueMappingData;
1216 OpaqueValueVisitor Visitor;
1217 Visitor.TraverseStmt(E);
1218 for (auto *OVE : Visitor.OVEs) {
1219 if (CGF.isOpaqueValueEmitted(OVE))
1220 continue;
1221 if (OpaqueValueMappingData::shouldBindAsLValue(OVE)) {
1222 LValue LV = CGF.EmitLValue(OVE->getSourceExpr());
1223 OpaqueValueMappingData::bind(CGF, OVE, LV);
1224 } else {
1225 RValue RV = CGF.EmitAnyExpr(OVE->getSourceExpr());
1226 OpaqueValueMappingData::bind(CGF, OVE, RV);
1227 }
1228 }
1229}
1230
1232 const ArraySubscriptExpr *ArraySubsExpr, CodeGenFunction &CGF) {
1233 assert((ArraySubsExpr->getType()->isHLSLResourceRecord() ||
1234 ArraySubsExpr->getType()->isHLSLResourceRecordArray()) &&
1235 "expected resource array subscript expression");
1236
1237 // Let clang codegen handle local and static resource array subscripts,
1238 // or when the subscript references on opaque expression (as part of
1239 // ArrayInitLoopExpr AST node).
1240 const VarDecl *ArrayDecl =
1241 dyn_cast_or_null<VarDecl>(getArrayDecl(ArraySubsExpr));
1242 if (!ArrayDecl || !ArrayDecl->hasGlobalStorage() ||
1243 ArrayDecl->getStorageClass() == SC_Static)
1244 return std::nullopt;
1245
1246 // get the resource array type
1247 ASTContext &AST = ArrayDecl->getASTContext();
1248 const Type *ResArrayTy = ArrayDecl->getType().getTypePtr();
1249 assert(ResArrayTy->isHLSLResourceRecordArray() &&
1250 "expected array of resource classes");
1251
1252 // Iterate through all nested array subscript expressions to calculate
1253 // the index in the flattened resource array (if this is a multi-
1254 // dimensional array). The index is calculated as a sum of all indices
1255 // multiplied by the total size of the array at that level.
1256 Value *Index = nullptr;
1257 const ArraySubscriptExpr *ASE = ArraySubsExpr;
1258 while (ASE != nullptr) {
1259 Value *SubIndex = CGF.EmitScalarExpr(ASE->getIdx());
1260 if (const auto *ArrayTy =
1261 dyn_cast<ConstantArrayType>(ASE->getType().getTypePtr())) {
1262 Value *Multiplier = llvm::ConstantInt::get(
1263 CGM.IntTy, AST.getConstantArrayElementCount(ArrayTy));
1264 SubIndex = CGF.Builder.CreateMul(SubIndex, Multiplier);
1265 }
1266 Index = Index ? CGF.Builder.CreateAdd(Index, SubIndex) : SubIndex;
1267 ASE = dyn_cast<ArraySubscriptExpr>(ASE->getBase()->IgnoreParenImpCasts());
1268 }
1269
1270 // Find binding info for the resource array. For implicit binding
1271 // an HLSLResourceBindingAttr should have been added by SemaHLSL.
1272 ResourceBindingAttrs Binding(ArrayDecl);
1273 assert(Binding.hasBinding() &&
1274 "resource array must have a binding attribute");
1275
1276 // Find the individual resource type.
1277 QualType ResultTy = ArraySubsExpr->getType();
1278 QualType ResourceTy =
1279 ResultTy->isArrayType() ? AST.getBaseElementType(ResultTy) : ResultTy;
1280
1281 // Create a temporary variable for the result, which is either going
1282 // to be a single resource instance or a local array of resources (we need to
1283 // return an LValue).
1284 RawAddress TmpVar = CGF.CreateMemTemp(ResultTy);
1285 if (CGF.EmitLifetimeStart(TmpVar.getPointer()))
1287 NormalEHLifetimeMarker, TmpVar);
1288
1293
1294 // Calculate total array size (= range size).
1295 llvm::Value *Range = llvm::ConstantInt::getSigned(
1296 CGM.IntTy, getTotalArraySize(AST, ResArrayTy));
1297
1298 // If the result of the subscript operation is a single resource, call the
1299 // constructor.
1300 if (ResultTy == ResourceTy) {
1301 CallArgList Args;
1302 CXXMethodDecl *CreateMethod = lookupResourceInitMethodAndSetupArgs(
1303 CGF.CGM, ResourceTy->getAsCXXRecordDecl(), Range, Index,
1304 ArrayDecl->getName(), Binding, Args);
1305
1306 if (!CreateMethod)
1307 // This can happen if someone creates an array of structs that looks like
1308 // an HLSL resource record array but it does not have the required static
1309 // create method. No binding will be generated for it.
1310 return std::nullopt;
1311
1312 callResourceInitMethod(CGF, CreateMethod, Args, ValueSlot.getAddress());
1313
1314 } else {
1315 // The result of the subscript operation is a local resource array which
1316 // needs to be initialized.
1317 const ConstantArrayType *ArrayTy =
1319 std::optional<llvm::Value *> EndIndex = initializeLocalResourceArray(
1320 CGF, ResourceTy->getAsCXXRecordDecl(), ArrayTy, ValueSlot, Range, Index,
1321 ArrayDecl->getName(), Binding, {llvm::ConstantInt::get(CGM.IntTy, 0)},
1322 ArraySubsExpr->getExprLoc());
1323 if (!EndIndex)
1324 return std::nullopt;
1325 }
1326 return CGF.MakeAddrLValue(TmpVar, ResultTy, AlignmentSource::Decl);
1327}
1328
1329// If RHSExpr is a global resource array, initialize all of its resources and
1330// set them into LHS. Returns false if no copy has been performed and the
1331// array copy should be handled by Clang codegen.
1333 CodeGenFunction &CGF) {
1334 QualType ResultTy = RHSExpr->getType();
1335 assert(ResultTy->isHLSLResourceRecordArray() && "expected resource array");
1336
1337 // Let Clang codegen handle local and static resource array copies.
1338 const VarDecl *ArrayDecl = dyn_cast_or_null<VarDecl>(getArrayDecl(RHSExpr));
1339 if (!ArrayDecl || !ArrayDecl->hasGlobalStorage() ||
1340 ArrayDecl->getStorageClass() == SC_Static)
1341 return false;
1342
1343 // Find binding info for the resource array. For implicit binding
1344 // the HLSLResourceBindingAttr should have been added by SemaHLSL.
1345 ResourceBindingAttrs Binding(ArrayDecl);
1346 assert(Binding.hasBinding() &&
1347 "resource array must have a binding attribute");
1348
1349 // Find the individual resource type.
1350 ASTContext &AST = ArrayDecl->getASTContext();
1351 QualType ResTy = AST.getBaseElementType(ResultTy);
1352 const auto *ResArrayTy = cast<ConstantArrayType>(ResultTy.getTypePtr());
1353
1354 // Use the provided LHS for the result.
1359
1360 // Create Value for index and total array size (= range size).
1361 int Size = getTotalArraySize(AST, ResArrayTy);
1362 llvm::Value *Zero = llvm::ConstantInt::get(CGM.IntTy, 0);
1363 llvm::Value *Range = llvm::ConstantInt::get(CGM.IntTy, Size);
1364
1365 // Initialize individual resources in the array into LHS.
1366 std::optional<llvm::Value *> EndIndex = initializeLocalResourceArray(
1367 CGF, ResTy->getAsCXXRecordDecl(), ResArrayTy, ValueSlot, Range, Zero,
1368 ArrayDecl->getName(), Binding, {Zero}, RHSExpr->getExprLoc());
1369 return EndIndex.has_value();
1370}
1371
1373 SourceLocation Loc,
1374 CodeGenFunction &CGF) {
1375
1376 assert(LV.getType()->isConstantMatrixType() && "expected matrix type");
1378 "expected cbuffer matrix");
1379
1380 QualType MatQualTy = LV.getType();
1381 llvm::Type *MemTy = CGF.ConvertTypeForMem(MatQualTy);
1382 llvm::Type *LayoutTy = HLSLBufferLayoutBuilder(CGF.CGM).layOutType(MatQualTy);
1383
1384 if (LayoutTy == MemTy)
1385 return LV.getAddress();
1386
1387 Address SrcAddr = LV.getAddress();
1388 // NOTE: B\C CreateMemTemp flattens MatrixTypes which causes
1389 // overlapping GEPs in emitBufferCopy. Use CreateTempAlloca with
1390 // the non-padded layout.
1391 CharUnits Align =
1392 CharUnits::fromQuantity(CGF.CGM.getDataLayout().getABITypeAlign(MemTy));
1393 RawAddress DestAlloca = CGF.CreateTempAlloca(MemTy, Align, "matrix.buf.copy");
1394 emitBufferCopy(CGF, DestAlloca, SrcAddr, MatQualTy);
1395 return DestAlloca;
1396}
1397
1399 const ArraySubscriptExpr *E, CodeGenFunction &CGF,
1400 llvm::function_ref<llvm::Value *(bool Promote)> EmitIdxAfterBase) {
1401 // Find the element type to index by first padding the element type per HLSL
1402 // buffer rules, and then padding out to a 16-byte register boundary if
1403 // necessary.
1404 llvm::Type *LayoutTy =
1406 uint64_t LayoutSizeInBits =
1407 CGM.getDataLayout().getTypeSizeInBits(LayoutTy).getFixedValue();
1408 CharUnits ElementSize = CharUnits::fromQuantity(LayoutSizeInBits / 8);
1409 CharUnits RowAlignedSize = ElementSize.alignTo(CharUnits::fromQuantity(16));
1410 if (RowAlignedSize > ElementSize) {
1411 llvm::Type *Padding = CGM.getTargetCodeGenInfo().getHLSLPadding(
1412 CGM, RowAlignedSize - ElementSize);
1413 assert(Padding && "No padding type for target?");
1414 LayoutTy = llvm::StructType::get(CGF.getLLVMContext(), {LayoutTy, Padding},
1415 /*isPacked=*/true);
1416 }
1417
1418 // If the layout type doesn't introduce any padding, we don't need to do
1419 // anything special.
1420 llvm::Type *OrigTy = CGF.CGM.getTypes().ConvertTypeForMem(E->getType());
1421 if (LayoutTy == OrigTy)
1422 return std::nullopt;
1423
1424 LValueBaseInfo EltBaseInfo;
1425 TBAAAccessInfo EltTBAAInfo;
1426
1427 // Index into the object as-if we have an array of the padded element type,
1428 // and then dereference the element itself to avoid reading padding that may
1429 // be past the end of the in-memory object.
1431 llvm::Value *Idx = EmitIdxAfterBase(/*Promote*/ true);
1432 Indices.push_back(Idx);
1433 Indices.push_back(llvm::ConstantInt::get(CGF.Int32Ty, 0));
1434
1435 if (CGF.getLangOpts().EmitStructuredGEP) {
1436 // The fact that we emit an array-to-pointer decay might be an oversight,
1437 // but for now, we simply ignore it (see #179951).
1438 const CastExpr *CE = cast<CastExpr>(E->getBase());
1439 assert(CE->getCastKind() == CastKind::CK_ArrayToPointerDecay);
1440
1441 LValue LV = CGF.EmitLValue(CE->getSubExpr());
1442 Address Addr = LV.getAddress();
1443 LayoutTy = llvm::ArrayType::get(
1444 LayoutTy,
1445 cast<llvm::ArrayType>(Addr.getElementType())->getNumElements());
1446 auto *GEP = cast<StructuredGEPInst>(CGF.Builder.CreateStructuredGEP(
1447 LayoutTy, Addr.emitRawPointer(CGF), Indices, "cbufferidx"));
1448 Addr =
1449 Address(GEP, GEP->getResultElementType(), RowAlignedSize, KnownNonNull);
1450 return CGF.MakeAddrLValue(Addr, E->getType(), EltBaseInfo, EltTBAAInfo);
1451 }
1452
1453 Address Addr =
1454 CGF.EmitPointerWithAlignment(E->getBase(), &EltBaseInfo, &EltTBAAInfo);
1455 llvm::Value *GEP = CGF.Builder.CreateGEP(LayoutTy, Addr.emitRawPointer(CGF),
1456 Indices, "cbufferidx");
1457 Addr = Address(GEP, Addr.getElementType(), RowAlignedSize, KnownNonNull);
1458 return CGF.MakeAddrLValue(Addr, E->getType(), EltBaseInfo, EltTBAAInfo);
1459}
1460
1461namespace {
1462/// Utility for emitting copies following the HLSL buffer layout rules (ie,
1463/// copying out of a cbuffer).
1464class HLSLBufferCopyEmitter {
1465 CodeGenFunction &CGF;
1466 Address DestPtr;
1467 Address SrcPtr;
1468 llvm::Type *LayoutTy = nullptr;
1469
1470 SmallVector<llvm::Value *> CurStoreIndices;
1471 SmallVector<llvm::Value *> CurLoadIndices;
1472
1473 void emitCopyAtIndices(llvm::Type *FieldTy, llvm::ConstantInt *StoreIndex,
1474 llvm::ConstantInt *LoadIndex) {
1475 CurStoreIndices.push_back(StoreIndex);
1476 CurLoadIndices.push_back(LoadIndex);
1477 llvm::scope_exit RestoreIndices([&]() {
1478 CurStoreIndices.pop_back();
1479 CurLoadIndices.pop_back();
1480 });
1481
1482 // First, see if this is some kind of aggregate and recurse.
1483 if (processArray(FieldTy))
1484 return;
1485 if (processBufferLayoutArray(FieldTy))
1486 return;
1487 if (processStruct(FieldTy))
1488 return;
1489
1490 // When we have a scalar or vector element we can emit the copy.
1492 CGF.CGM.getDataLayout().getABITypeAlign(FieldTy));
1493 Address SrcGEP = RawAddress(
1494 CGF.Builder.CreateInBoundsGEP(LayoutTy, SrcPtr.getBasePointer(),
1495 CurLoadIndices, "cbuf.src"),
1496 FieldTy, Align, SrcPtr.isKnownNonNull());
1497 Address DestGEP = CGF.Builder.CreateInBoundsGEP(
1498 DestPtr, CurStoreIndices, FieldTy, Align, "cbuf.dest");
1499 llvm::Value *Load = CGF.Builder.CreateLoad(SrcGEP, "cbuf.load");
1500 CGF.Builder.CreateStore(Load, DestGEP);
1501 }
1502
1503 bool processArray(llvm::Type *FieldTy) {
1504 auto *AT = dyn_cast<llvm::ArrayType>(FieldTy);
1505 if (!AT)
1506 return false;
1507
1508 // If we have an llvm::ArrayType this is just a regular array with no top
1509 // level padding, so all we need to do is copy each member.
1510 for (unsigned I = 0, E = AT->getNumElements(); I < E; ++I)
1511 emitCopyAtIndices(AT->getElementType(),
1512 llvm::ConstantInt::get(CGF.SizeTy, I),
1513 llvm::ConstantInt::get(CGF.SizeTy, I));
1514 return true;
1515 }
1516
1517 bool processBufferLayoutArray(llvm::Type *FieldTy) {
1518 // A buffer layout array is a struct with two elements: the padded array,
1519 // and the last element. That is, is should look something like this:
1520 //
1521 // { [%n x { %type, %padding }], %type }
1522 //
1523 auto *ST = dyn_cast<llvm::StructType>(FieldTy);
1524 if (!ST || ST->getNumElements() != 2)
1525 return false;
1526
1527 auto *PaddedEltsTy = dyn_cast<llvm::ArrayType>(ST->getElementType(0));
1528 if (!PaddedEltsTy)
1529 return false;
1530
1531 auto *PaddedTy = dyn_cast<llvm::StructType>(PaddedEltsTy->getElementType());
1532 if (!PaddedTy || PaddedTy->getNumElements() != 2)
1533 return false;
1534
1536 PaddedTy->getElementType(1)))
1537 return false;
1538
1539 llvm::Type *ElementTy = ST->getElementType(1);
1540 if (PaddedTy->getElementType(0) != ElementTy)
1541 return false;
1542
1543 // All but the last of the logical array elements are in the padded array.
1544 unsigned NumElts = PaddedEltsTy->getNumElements() + 1;
1545
1546 // Add an extra indirection to the load for the struct and walk the
1547 // array prefix.
1548 CurLoadIndices.push_back(llvm::ConstantInt::get(CGF.Int32Ty, 0));
1549 for (unsigned I = 0; I < NumElts - 1; ++I) {
1550 // We need to copy the element itself, without the padding.
1551 CurLoadIndices.push_back(llvm::ConstantInt::get(CGF.SizeTy, I));
1552 emitCopyAtIndices(ElementTy, llvm::ConstantInt::get(CGF.SizeTy, I),
1553 llvm::ConstantInt::get(CGF.Int32Ty, 0));
1554 CurLoadIndices.pop_back();
1555 }
1556 CurLoadIndices.pop_back();
1557
1558 // Now copy the last element.
1559 emitCopyAtIndices(ElementTy,
1560 llvm::ConstantInt::get(CGF.SizeTy, NumElts - 1),
1561 llvm::ConstantInt::get(CGF.Int32Ty, 1));
1562
1563 return true;
1564 }
1565
1566 bool processStruct(llvm::Type *FieldTy) {
1567 auto *ST = dyn_cast<llvm::StructType>(FieldTy);
1568 if (!ST)
1569 return false;
1570
1571 // Copy the struct field by field, but skip any explicit padding.
1572 unsigned Skipped = 0;
1573 for (unsigned I = 0, E = ST->getNumElements(); I < E; ++I) {
1574 llvm::Type *ElementTy = ST->getElementType(I);
1575 if (CGF.CGM.getTargetCodeGenInfo().isHLSLPadding(ElementTy))
1576 ++Skipped;
1577 else
1578 emitCopyAtIndices(ElementTy, llvm::ConstantInt::get(CGF.Int32Ty, I),
1579 llvm::ConstantInt::get(CGF.Int32Ty, I + Skipped));
1580 }
1581 return true;
1582 }
1583
1584public:
1585 HLSLBufferCopyEmitter(CodeGenFunction &CGF, Address DestPtr, Address SrcPtr)
1586 : CGF(CGF), DestPtr(DestPtr), SrcPtr(SrcPtr) {}
1587
1588 bool emitCopy(QualType CType) {
1589 LayoutTy = HLSLBufferLayoutBuilder(CGF.CGM).layOutType(CType);
1590
1591 // TODO: We should be able to fall back to a regular memcpy if the layout
1592 // type doesn't have any padding, but that runs into issues in the backend
1593 // currently.
1594 //
1595 // See https://github.com/llvm/wg-hlsl/issues/351
1596 emitCopyAtIndices(LayoutTy, llvm::ConstantInt::get(CGF.SizeTy, 0),
1597 llvm::ConstantInt::get(CGF.SizeTy, 0));
1598 return true;
1599 }
1600};
1601} // namespace
1602
1604 Address SrcPtr, QualType CType) {
1605 return HLSLBufferCopyEmitter(CGF, DestPtr, SrcPtr).emitCopy(CType);
1606}
1607
1609 const MemberExpr *E) {
1610 LValue Base =
1612 auto *Field = dyn_cast<FieldDecl>(E->getMemberDecl());
1613 assert(Field && "Unexpected access into HLSL buffer");
1614
1615 const RecordDecl *Rec = Field->getParent();
1616
1617 // Work out the buffer layout type to index into.
1618 QualType RecType = CGM.getContext().getCanonicalTagType(Rec);
1619 assert(RecType->isStructureOrClassType() && "Invalid type in HLSL buffer");
1620 // Since this is a member of an object in the buffer and not the buffer's
1621 // struct/class itself, we shouldn't have any offsets on the members we need
1622 // to contend with.
1623 CGHLSLOffsetInfo EmptyOffsets;
1624 llvm::StructType *LayoutTy = HLSLBufferLayoutBuilder(CGM).layOutStruct(
1625 RecType->getAsCanonical<RecordType>(), EmptyOffsets);
1626
1627 // Get the field index for the layout struct, accounting for padding.
1628 unsigned FieldIdx =
1629 CGM.getTypes().getCGRecordLayout(Rec).getLLVMFieldNo(Field);
1630 assert(FieldIdx < LayoutTy->getNumElements() &&
1631 "Layout struct is smaller than member struct");
1632 unsigned Skipped = 0;
1633 for (unsigned I = 0; I <= FieldIdx;) {
1634 llvm::Type *ElementTy = LayoutTy->getElementType(I + Skipped);
1635 if (CGF.CGM.getTargetCodeGenInfo().isHLSLPadding(ElementTy))
1636 ++Skipped;
1637 else
1638 ++I;
1639 }
1640 FieldIdx += Skipped;
1641 assert(FieldIdx < LayoutTy->getNumElements() && "Access out of bounds");
1642
1643 // Now index into the struct, making sure that the type we return is the
1644 // buffer layout type rather than the original type in the AST.
1645 QualType FieldType = Field->getType();
1646 llvm::Type *FieldLLVMTy = CGM.getTypes().ConvertTypeForMem(FieldType);
1648 CGF.CGM.getDataLayout().getABITypeAlign(FieldLLVMTy));
1649
1650 Value *Ptr = CGF.getLangOpts().EmitStructuredGEP
1651 ? CGF.Builder.CreateStructuredGEP(
1652 LayoutTy, Base.getPointer(CGF),
1653 llvm::ConstantInt::get(CGM.IntTy, FieldIdx))
1654 : CGF.Builder.CreateStructGEP(LayoutTy, Base.getPointer(CGF),
1655 FieldIdx, Field->getName());
1656 Address Addr(Ptr, FieldLLVMTy, Align, KnownNonNull);
1657
1658 LValue LV = LValue::MakeAddr(Addr, FieldType, CGM.getContext(),
1660 CGM.getTBAAAccessInfo(FieldType));
1661 LV.getQuals().addCVRQualifiers(Base.getVRQualifiers());
1662
1663 return LV;
1664}
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 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:5340
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: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: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: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: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:5447
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:5451
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: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