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// Given a MemberExpr of a resource or resource array type, find the parent
100// VarDecl of the struct or class instance that contains this resource and
101// build the full resource name based on the member access path.
102//
103// For example, for a member access like "myStructArray[0].memberA",
104// this function will find the VarDecl of "myStructArray" and use the
105// EmbeddedResourceNameBuilder to build the resource name
106// "myStructArray.0.memberA".
107static const VarDecl *findStructResourceParentDeclAndBuildName(
108 const MemberExpr *ME, EmbeddedResourceNameBuilder &NameBuilder) {
109
111 const VarDecl *VD = nullptr;
112 const Expr *E = ME;
113
114 for (;;) {
115 if (const auto *DRE = dyn_cast<DeclRefExpr>(E)) {
116 assert(isa<VarDecl>(DRE->getDecl()) &&
117 "member expr base is not a var decl");
118 VD = cast<VarDecl>(DRE->getDecl());
119 NameBuilder.pushName(VD->getName());
120 break;
121 }
122
123 WorkList.push_back(E);
124 if (const auto *MExp = dyn_cast<MemberExpr>(E))
125 E = MExp->getBase();
126 else if (const auto *ICE = dyn_cast<ImplicitCastExpr>(E))
127 E = ICE->getSubExpr();
128 else if (const auto *ASE = dyn_cast<ArraySubscriptExpr>(E))
129 E = ASE->getBase();
130 else if (isa<CXXThisExpr>(E))
131 // Resource member access on "this" pointer not yet implemented
132 // (llvm/llvm-project#190299)
133 return nullptr;
134 else
135 llvm_unreachable("unexpected expr type in resource member access");
136
137 assert(E && "expected valid expression");
138 }
139
140 while (!WorkList.empty()) {
141 E = WorkList.pop_back_val();
142 if (const auto *ME = dyn_cast<MemberExpr>(E)) {
143 NameBuilder.pushName(
145 } else if (const auto *ICE = dyn_cast<ImplicitCastExpr>(E)) {
146 if (ICE->getCastKind() == CK_UncheckedDerivedToBase) {
147 CXXRecordDecl *DerivedRD =
148 ICE->getSubExpr()->getType()->getAsCXXRecordDecl();
149 CXXRecordDecl *BaseRD = ICE->getType()->getAsCXXRecordDecl();
150 NameBuilder.pushBaseNameHierarchy(DerivedRD, BaseRD);
151 }
152 } else if (const auto *ASE = dyn_cast<ArraySubscriptExpr>(E)) {
153 const Expr *IdxExpr = ASE->getIdx();
154 std::optional<llvm::APSInt> Value =
156 assert(Value &&
157 "expected constant index in struct with resource array access");
158 NameBuilder.pushArrayIndex(Value->getZExtValue());
159 } else {
160 llvm_unreachable("unexpected expr type in resource member access");
161 }
162 }
163 return VD;
164}
165
166// Given a MemberExpr of a resource or resource array type, find the
167// corresponding global resource declaration associated with the owning struct
168// or class instance via HLSLAssociatedResourceDeclAttr.
169static const VarDecl *
170findAssociatedResourceDeclForStruct(ASTContext &AST, const MemberExpr *ME) {
171
172 EmbeddedResourceNameBuilder NameBuilder;
173 const VarDecl *ParentVD =
174 findStructResourceParentDeclAndBuildName(ME, NameBuilder);
175 if (!ParentVD)
176 return nullptr;
177
178 if (!ParentVD->hasGlobalStorage())
179 return nullptr;
180
181 IdentifierInfo *II = NameBuilder.getNameAsIdentifier(AST);
182 for (const Attr *A : ParentVD->getAttrs()) {
183 if (const auto *ADA = dyn_cast<HLSLAssociatedResourceDeclAttr>(A)) {
184 VarDecl *AssocResVD = ADA->getResDecl();
185 if (AssocResVD->getIdentifier() == II)
186 return AssocResVD;
187 }
188 }
189 return nullptr;
190}
191
192// Find array variable declaration from DeclRef expression
193static const ValueDecl *getArrayDecl(ASTContext &AST, const Expr *E) {
194 E = E->IgnoreImpCasts();
195 if (const auto *DRE = dyn_cast_or_null<DeclRefExpr>(E))
196 return DRE->getDecl();
197 if (auto *OVE = dyn_cast<OpaqueValueExpr>(E))
198 E = OVE->getSourceExpr()->IgnoreImpCasts();
199 if (isa<MemberExpr>(E))
200 return findAssociatedResourceDeclForStruct(AST, cast<MemberExpr>(E));
201 return nullptr;
202}
203
204// Find array variable declaration from nested array subscript AST nodes
205static const ValueDecl *getArrayDecl(ASTContext &AST,
206 const ArraySubscriptExpr *ASE) {
207 const Expr *E = nullptr;
208 while (ASE != nullptr) {
209 E = ASE->getBase()->IgnoreImpCasts();
210 if (!E)
211 return nullptr;
212 ASE = dyn_cast<ArraySubscriptExpr>(E);
213 }
214 return getArrayDecl(AST, E);
215}
216
217// Get the total size of the array, or 0 if the array is unbounded.
218static int getTotalArraySize(ASTContext &AST, const clang::Type *Ty) {
220 assert(Ty->isArrayType() && "expected array type");
221 if (Ty->isIncompleteArrayType())
222 return 0;
224}
225
226static Value *buildNameForResource(llvm::StringRef BaseName,
227 CodeGenModule &CGM) {
228 llvm::SmallString<64> GlobalName = {BaseName, ".str"};
229 return CGM.GetAddrOfConstantCString(BaseName.str(), GlobalName.c_str())
230 .getPointer();
231}
232
233static CXXMethodDecl *lookupMethod(CXXRecordDecl *Record, StringRef Name,
234 StorageClass SC = SC_None) {
235 for (auto *Method : Record->methods()) {
236 if (Method->getStorageClass() == SC && Method->getName() == Name)
237 return Method;
238 }
239 return nullptr;
240}
241
242static CXXMethodDecl *lookupResourceInitMethodAndSetupArgs(
243 CodeGenModule &CGM, CXXRecordDecl *ResourceDecl, llvm::Value *Range,
244 llvm::Value *Index, StringRef Name, ResourceBindingAttrs &Binding,
245 CallArgList &Args) {
246 assert(Binding.hasBinding() && "at least one binding attribute expected");
247
248 ASTContext &AST = CGM.getContext();
249 CXXMethodDecl *CreateMethod = nullptr;
250 Value *NameStr = buildNameForResource(Name, CGM);
251 Value *Space = llvm::ConstantInt::get(CGM.IntTy, Binding.getSpace());
252
253 bool HasCounter = hasCounterHandle(ResourceDecl);
254 assert((!HasCounter || Binding.hasCounterImplicitOrderID()) &&
255 "resources with counter handle must have a binding with counter "
256 "implicit order ID");
257 if (Binding.isExplicit()) {
258 // explicit binding
259 auto *RegSlot = llvm::ConstantInt::get(CGM.IntTy, Binding.getSlot());
260 Args.add(RValue::get(RegSlot), AST.UnsignedIntTy);
261 const char *Name = Binding.hasCounterImplicitOrderID()
262 ? "__createFromBindingWithImplicitCounter"
263 : "__createFromBinding";
264 CreateMethod = lookupMethod(ResourceDecl, Name, SC_Static);
265 } else {
266 // implicit binding
267 auto *OrderID =
268 llvm::ConstantInt::get(CGM.IntTy, Binding.getImplicitOrderID());
269 Args.add(RValue::get(OrderID), AST.UnsignedIntTy);
270 const char *Name = Binding.hasCounterImplicitOrderID()
271 ? "__createFromImplicitBindingWithImplicitCounter"
272 : "__createFromImplicitBinding";
273 CreateMethod = lookupMethod(ResourceDecl, Name, SC_Static);
274 }
275 Args.add(RValue::get(Space), AST.UnsignedIntTy);
276 Args.add(RValue::get(Range), AST.IntTy);
277 Args.add(RValue::get(Index), AST.UnsignedIntTy);
278 Args.add(RValue::get(NameStr), AST.getPointerType(AST.CharTy.withConst()));
279 if (HasCounter) {
280 uint32_t CounterBinding = Binding.getCounterImplicitOrderID();
281 auto *CounterOrderID = llvm::ConstantInt::get(CGM.IntTy, CounterBinding);
282 Args.add(RValue::get(CounterOrderID), AST.UnsignedIntTy);
283 }
284
285 return CreateMethod;
286}
287
288static void callResourceInitMethod(CodeGenFunction &CGF,
289 CXXMethodDecl *CreateMethod,
290 CallArgList &Args, Address ReturnAddress) {
291 llvm::Constant *CalleeFn = CGF.CGM.GetAddrOfFunction(CreateMethod);
292 const FunctionProtoType *Proto =
293 CreateMethod->getType()->getAs<FunctionProtoType>();
294 const CGFunctionInfo &FnInfo =
295 CGF.CGM.getTypes().arrangeFreeFunctionCall(Args, Proto, false);
296 ReturnValueSlot ReturnValue(ReturnAddress, false);
297 CGCallee Callee(CGCalleeInfo(Proto), CalleeFn);
298 CGF.EmitCall(FnInfo, Callee, ReturnValue, Args, nullptr);
299}
300
301// Initializes local resource array variable with global resource array
302// elements. For multi-dimensional arrays it calls itself recursively to
303// initialize its sub-arrays. The Index used in the resource constructor calls
304// will begin at StartIndex and will be incremented for each array element. The
305// last used resource Index is returned to the caller. If the function returns
306// std::nullopt, it indicates an error.
307static std::optional<llvm::Value *> initializeResourceArrayFromGlobal(
308 CodeGenFunction &CGF, CXXRecordDecl *ResourceDecl,
309 const ConstantArrayType *ArrayTy, AggValueSlot &ValueSlot,
310 llvm::Value *Range, llvm::Value *StartIndex, StringRef ResourceName,
311 ResourceBindingAttrs &Binding, ArrayRef<llvm::Value *> PrevGEPIndices,
312 SourceLocation ArraySubsExprLoc) {
313
314 ASTContext &AST = CGF.getContext();
315 llvm::IntegerType *IntTy = CGF.CGM.IntTy;
316 llvm::Value *Index = StartIndex;
317 llvm::Value *One = llvm::ConstantInt::get(IntTy, 1);
318 const uint64_t ArraySize = ArrayTy->getSExtSize();
319 QualType ElemType = ArrayTy->getElementType();
320 Address TmpArrayAddr = ValueSlot.getAddress();
321
322 // Add additional index to the getelementptr call indices.
323 // This index will be updated for each array element in the loops below.
324 SmallVector<llvm::Value *> GEPIndices(PrevGEPIndices);
325 GEPIndices.push_back(llvm::ConstantInt::get(IntTy, 0));
326
327 // For array of arrays, recursively initialize the sub-arrays.
328 if (ElemType->isArrayType()) {
329 const ConstantArrayType *SubArrayTy = cast<ConstantArrayType>(ElemType);
330 for (uint64_t I = 0; I < ArraySize; I++) {
331 if (I > 0) {
332 Index = CGF.Builder.CreateAdd(Index, One);
333 GEPIndices.back() = llvm::ConstantInt::get(IntTy, I);
334 }
335 std::optional<llvm::Value *> MaybeIndex =
336 initializeResourceArrayFromGlobal(
337 CGF, ResourceDecl, SubArrayTy, ValueSlot, Range, Index,
338 ResourceName, Binding, GEPIndices, ArraySubsExprLoc);
339 if (!MaybeIndex)
340 return std::nullopt;
341 Index = *MaybeIndex;
342 }
343 return Index;
344 }
345
346 // For array of resources, initialize each resource in the array.
347 llvm::Type *Ty = CGF.ConvertTypeForMem(ElemType);
348 CharUnits ElemSize = AST.getTypeSizeInChars(ElemType);
349 CharUnits Align =
350 TmpArrayAddr.getAlignment().alignmentOfArrayElement(ElemSize);
351
352 for (uint64_t I = 0; I < ArraySize; I++) {
353 if (I > 0) {
354 Index = CGF.Builder.CreateAdd(Index, One);
355 GEPIndices.back() = llvm::ConstantInt::get(IntTy, I);
356 }
357 Address ReturnAddress =
358 CGF.Builder.CreateGEP(TmpArrayAddr, GEPIndices, Ty, Align);
359
360 CallArgList Args;
361 CXXMethodDecl *CreateMethod = lookupResourceInitMethodAndSetupArgs(
362 CGF.CGM, ResourceDecl, Range, Index, ResourceName, Binding, Args);
363
364 if (!CreateMethod)
365 // This can happen if someone creates an array of structs that looks like
366 // an HLSL resource record array but it does not have the required static
367 // create method. No binding will be generated for it.
368 return std::nullopt;
369
370 callResourceInitMethod(CGF, CreateMethod, Args, ReturnAddress);
371 }
372 return Index;
373}
374
375} // namespace
376
377llvm::Type *
379 const CGHLSLOffsetInfo &OffsetInfo) {
380 assert(T->isHLSLSpecificType() && "Not an HLSL specific type!");
381
382 // Check if the target has a specific translation for this type first.
383 if (llvm::Type *TargetTy =
384 CGM.getTargetCodeGenInfo().getHLSLType(CGM, T, OffsetInfo))
385 return TargetTy;
386
387 llvm_unreachable("Generic handling of HLSL types is not supported.");
388}
389
390llvm::Triple::ArchType CGHLSLRuntime::getArch() {
391 return CGM.getTarget().getTriple().getArch();
392}
393
394// Emits constant global variables for buffer constants declarations
395// and creates metadata linking the constant globals with the buffer global.
396void CGHLSLRuntime::emitBufferGlobalsAndMetadata(
397 const HLSLBufferDecl *BufDecl, llvm::GlobalVariable *BufGV,
398 const CGHLSLOffsetInfo &OffsetInfo) {
399 LLVMContext &Ctx = CGM.getLLVMContext();
400
401 // get the layout struct from constant buffer target type
402 llvm::Type *BufType = BufGV->getValueType();
403 llvm::StructType *LayoutStruct = cast<llvm::StructType>(
404 cast<llvm::TargetExtType>(BufType)->getTypeParameter(0));
405
407 size_t OffsetIdx = 0;
408 for (Decl *D : BufDecl->buffer_decls()) {
410 // Nothing to do for this declaration.
411 continue;
412 if (isa<FunctionDecl>(D)) {
413 // A function within an cbuffer is effectively a top-level function.
415 continue;
416 }
417 VarDecl *VD = dyn_cast<VarDecl>(D);
418 if (!VD)
419 continue;
420
421 QualType VDTy = VD->getType();
423 if (VD->getStorageClass() == SC_Static ||
426 // Emit static and groupshared variables and resource classes inside
427 // cbuffer as regular globals
428 CGM.EmitGlobal(VD);
429 }
430 continue;
431 }
432
433 DeclsWithOffset.emplace_back(VD, OffsetInfo[OffsetIdx++]);
434 }
435
436 if (!OffsetInfo.empty())
437 llvm::stable_sort(DeclsWithOffset, [](const auto &LHS, const auto &RHS) {
438 return CGHLSLOffsetInfo::compareOffsets(LHS.second, RHS.second);
439 });
440
441 // Associate the buffer global variable with its constants
442 SmallVector<llvm::Metadata *> BufGlobals;
443 BufGlobals.reserve(DeclsWithOffset.size() + 1);
444 BufGlobals.push_back(ValueAsMetadata::get(BufGV));
445
446 auto ElemIt = LayoutStruct->element_begin();
447 for (auto &[VD, _] : DeclsWithOffset) {
448 if (CGM.getTargetCodeGenInfo().isHLSLPadding(*ElemIt))
449 ++ElemIt;
450
451 assert(ElemIt != LayoutStruct->element_end() &&
452 "number of elements in layout struct does not match");
453 llvm::Type *LayoutType = *ElemIt++;
454
455 GlobalVariable *ElemGV =
456 cast<GlobalVariable>(CGM.GetAddrOfGlobalVar(VD, LayoutType));
457 BufGlobals.push_back(ValueAsMetadata::get(ElemGV));
458 }
459 assert(ElemIt == LayoutStruct->element_end() &&
460 "number of elements in layout struct does not match");
461
462 // add buffer metadata to the module
463 CGM.getModule()
464 .getOrInsertNamedMetadata("hlsl.cbs")
465 ->addOperand(MDNode::get(Ctx, BufGlobals));
466}
467
468// Creates resource handle type for the HLSL buffer declaration
469static const clang::HLSLAttributedResourceType *
471 ASTContext &AST = BufDecl->getASTContext();
473 AST.HLSLResourceTy, AST.getCanonicalTagType(BufDecl->getLayoutStruct()),
474 HLSLAttributedResourceType::Attributes(ResourceClass::CBuffer));
476}
477
480
481 // If we don't have packoffset info, just return an empty result.
482 if (!BufDecl.hasValidPackoffset())
483 return Result;
484
485 for (Decl *D : BufDecl.buffer_decls()) {
487 continue;
488 }
489 VarDecl *VD = dyn_cast<VarDecl>(D);
490 if (!VD || VD->getType().getAddressSpace() != LangAS::hlsl_constant)
491 continue;
492
493 if (!VD->hasAttrs()) {
494 Result.Offsets.push_back(Unspecified);
495 continue;
496 }
497
498 uint32_t Offset = Unspecified;
499 for (auto *Attr : VD->getAttrs()) {
500 if (auto *POA = dyn_cast<HLSLPackOffsetAttr>(Attr)) {
501 Offset = POA->getOffsetInBytes();
502 break;
503 }
504 auto *RBA = dyn_cast<HLSLResourceBindingAttr>(Attr);
505 if (RBA &&
506 RBA->getRegisterType() == HLSLResourceBindingAttr::RegisterType::C) {
507 Offset = RBA->getSlotNumber() * CBufferRowSizeInBytes;
508 break;
509 }
510 }
511 Result.Offsets.push_back(Offset);
512 }
513 return Result;
514}
515
516// Codegen for HLSLBufferDecl
518
519 assert(BufDecl->isCBuffer() && "tbuffer codegen is not supported yet");
520
521 // create resource handle type for the buffer
522 const clang::HLSLAttributedResourceType *ResHandleTy =
523 createBufferHandleType(BufDecl);
524
525 // empty constant buffer is ignored
526 if (ResHandleTy->getContainedType()->getAsCXXRecordDecl()->isEmpty())
527 return;
528
529 // create global variable for the constant buffer
530 CGHLSLOffsetInfo OffsetInfo = CGHLSLOffsetInfo::fromDecl(*BufDecl);
531 llvm::Type *LayoutTy = convertHLSLSpecificType(ResHandleTy, OffsetInfo);
532 llvm::GlobalVariable *BufGV = new GlobalVariable(
533 LayoutTy, /*isConstant*/ false,
534 GlobalValue::LinkageTypes::ExternalLinkage, PoisonValue::get(LayoutTy),
535 llvm::formatv("{0}{1}", BufDecl->getName(),
536 BufDecl->isCBuffer() ? ".cb" : ".tb"),
537 GlobalValue::NotThreadLocal);
538 CGM.getModule().insertGlobalVariable(BufGV);
539
540 // Add globals for constant buffer elements and create metadata nodes
541 emitBufferGlobalsAndMetadata(BufDecl, BufGV, OffsetInfo);
542
543 // Initialize cbuffer from binding (implicit or explicit)
544 initializeBufferFromBinding(BufDecl, BufGV);
545}
546
548 const HLSLRootSignatureDecl *SignatureDecl) {
549 llvm::Module &M = CGM.getModule();
550 Triple T(M.getTargetTriple());
551
552 // Generated later with the function decl if not targeting root signature
553 if (T.getEnvironment() != Triple::EnvironmentType::RootSignature)
554 return;
555
556 addRootSignatureMD(SignatureDecl->getVersion(),
557 SignatureDecl->getRootElements(), nullptr, M);
558}
559
560llvm::StructType *
561CGHLSLRuntime::getHLSLBufferLayoutType(const RecordType *StructType) {
562 const auto Entry = LayoutTypes.find(StructType);
563 if (Entry != LayoutTypes.end())
564 return Entry->getSecond();
565 return nullptr;
566}
567
568void CGHLSLRuntime::addHLSLBufferLayoutType(const RecordType *StructType,
569 llvm::StructType *LayoutTy) {
570 assert(getHLSLBufferLayoutType(StructType) == nullptr &&
571 "layout type for this struct already exist");
572 LayoutTypes[StructType] = LayoutTy;
573}
574
576 auto &TargetOpts = CGM.getTarget().getTargetOpts();
577 auto &CodeGenOpts = CGM.getCodeGenOpts();
578 auto &LangOpts = CGM.getLangOpts();
579 llvm::Module &M = CGM.getModule();
580 Triple T(M.getTargetTriple());
581 if (T.getArch() == Triple::ArchType::dxil)
582 addDxilValVersion(TargetOpts.DxilValidatorVersion, M);
583 if (CodeGenOpts.ResMayAlias)
584 M.setModuleFlag(llvm::Module::ModFlagBehavior::Error, "dx.resmayalias", 1);
585 if (CodeGenOpts.AllResourcesBound)
586 M.setModuleFlag(llvm::Module::ModFlagBehavior::Error,
587 "dx.allresourcesbound", 1);
588 if (CodeGenOpts.OptimizationLevel == 0)
589 M.addModuleFlag(llvm::Module::ModFlagBehavior::Override,
590 "dx.disable_optimizations", 1);
591
592 // NativeHalfType corresponds to the -fnative-half-type clang option which is
593 // aliased by clang-dxc's -enable-16bit-types option. This option is used to
594 // set the UseNativeLowPrecision DXIL module flag in the DirectX backend
595 if (LangOpts.NativeHalfType)
596 M.setModuleFlag(llvm::Module::ModFlagBehavior::Error, "dx.nativelowprec",
597 1);
598
600}
601
603 const FunctionDecl *FD, llvm::Function *Fn) {
604 const auto *ShaderAttr = FD->getAttr<HLSLShaderAttr>();
605 assert(ShaderAttr && "All entry functions must have a HLSLShaderAttr");
606 const StringRef ShaderAttrKindStr = "hlsl.shader";
607 Fn->addFnAttr(ShaderAttrKindStr,
608 llvm::Triple::getEnvironmentTypeName(ShaderAttr->getType()));
609 if (HLSLNumThreadsAttr *NumThreadsAttr = FD->getAttr<HLSLNumThreadsAttr>()) {
610 const StringRef NumThreadsKindStr = "hlsl.numthreads";
611 std::string NumThreadsStr =
612 formatv("{0},{1},{2}", NumThreadsAttr->getX(), NumThreadsAttr->getY(),
613 NumThreadsAttr->getZ());
614 Fn->addFnAttr(NumThreadsKindStr, NumThreadsStr);
615 }
616 if (HLSLWaveSizeAttr *WaveSizeAttr = FD->getAttr<HLSLWaveSizeAttr>()) {
617 const StringRef WaveSizeKindStr = "hlsl.wavesize";
618 std::string WaveSizeStr =
619 formatv("{0},{1},{2}", WaveSizeAttr->getMin(), WaveSizeAttr->getMax(),
620 WaveSizeAttr->getPreferred());
621 Fn->addFnAttr(WaveSizeKindStr, WaveSizeStr);
622 }
623 // HLSL entry functions are materialized for module functions with
624 // HLSLShaderAttr attribute. SetLLVMFunctionAttributesForDefinition called
625 // later in the compiler-flow for such module functions is not aware of and
626 // hence not able to set attributes of the newly materialized entry functions.
627 // So, set attributes of entry function here, as appropriate.
628 Fn->addFnAttr(llvm::Attribute::NoInline);
629
630 if (CGM.getLangOpts().HLSLSpvEnableMaximalReconvergence) {
631 Fn->addFnAttr("enable-maximal-reconvergence", "true");
632 }
633}
634
635static Value *buildVectorInput(IRBuilder<> &B, Function *F, llvm::Type *Ty) {
636 if (const auto *VT = dyn_cast<FixedVectorType>(Ty)) {
637 Value *Result = PoisonValue::get(Ty);
638 for (unsigned I = 0; I < VT->getNumElements(); ++I) {
639 Value *Elt = B.CreateCall(F, {B.getInt32(I)});
640 Result = B.CreateInsertElement(Result, Elt, I);
641 }
642 return Result;
643 }
644 return B.CreateCall(F, {B.getInt32(0)});
645}
646
647static void addSPIRVBuiltinDecoration(llvm::GlobalVariable *GV,
648 unsigned BuiltIn) {
649 LLVMContext &Ctx = GV->getContext();
650 IRBuilder<> B(GV->getContext());
651 MDNode *Operands = MDNode::get(
652 Ctx,
653 {ConstantAsMetadata::get(B.getInt32(/* Spirv::Decoration::BuiltIn */ 11)),
654 ConstantAsMetadata::get(B.getInt32(BuiltIn))});
655 MDNode *Decoration = MDNode::get(Ctx, {Operands});
656 GV->addMetadata("spirv.Decorations", *Decoration);
657}
658
659static void addLocationDecoration(llvm::GlobalVariable *GV, unsigned Location) {
660 LLVMContext &Ctx = GV->getContext();
661 IRBuilder<> B(GV->getContext());
662 MDNode *Operands =
663 MDNode::get(Ctx, {ConstantAsMetadata::get(B.getInt32(/* Location */ 30)),
664 ConstantAsMetadata::get(B.getInt32(Location))});
665 MDNode *Decoration = MDNode::get(Ctx, {Operands});
666 GV->addMetadata("spirv.Decorations", *Decoration);
667}
668
669static llvm::Value *createSPIRVBuiltinLoad(IRBuilder<> &B, llvm::Module &M,
670 llvm::Type *Ty, const Twine &Name,
671 unsigned BuiltInID) {
672 auto *GV = new llvm::GlobalVariable(
673 M, Ty, /* isConstant= */ true, llvm::GlobalValue::ExternalLinkage,
674 /* Initializer= */ nullptr, Name, /* insertBefore= */ nullptr,
675 llvm::GlobalVariable::GeneralDynamicTLSModel,
676 /* AddressSpace */ 7, /* isExternallyInitialized= */ true);
677 addSPIRVBuiltinDecoration(GV, BuiltInID);
678 GV->setVisibility(llvm::GlobalValue::HiddenVisibility);
679 return B.CreateLoad(Ty, GV);
680}
681
682static llvm::Value *createSPIRVLocationLoad(IRBuilder<> &B, llvm::Module &M,
683 llvm::Type *Ty, unsigned Location,
684 StringRef Name) {
685 auto *GV = new llvm::GlobalVariable(
686 M, Ty, /* isConstant= */ true, llvm::GlobalValue::ExternalLinkage,
687 /* Initializer= */ nullptr, /* Name= */ Name, /* insertBefore= */ nullptr,
688 llvm::GlobalVariable::GeneralDynamicTLSModel,
689 /* AddressSpace */ 7, /* isExternallyInitialized= */ true);
690 GV->setVisibility(llvm::GlobalValue::HiddenVisibility);
691 addLocationDecoration(GV, Location);
692 return B.CreateLoad(Ty, GV);
693}
694
695llvm::Value *CGHLSLRuntime::emitSPIRVUserSemanticLoad(
696 llvm::IRBuilder<> &B, llvm::Type *Type, const clang::DeclaratorDecl *Decl,
697 HLSLAppliedSemanticAttr *Semantic, std::optional<unsigned> Index) {
698 Twine BaseName = Twine(Semantic->getAttrName()->getName());
699 Twine VariableName = BaseName.concat(Twine(Index.value_or(0)));
700
701 unsigned Location = SPIRVLastAssignedInputSemanticLocation;
702 if (auto *L = Decl->getAttr<HLSLVkLocationAttr>())
703 Location = L->getLocation();
704
705 // DXC completely ignores the semantic/index pair. Location are assigned from
706 // the first semantic to the last.
707 llvm::ArrayType *AT = dyn_cast<llvm::ArrayType>(Type);
708 unsigned ElementCount = AT ? AT->getNumElements() : 1;
709 SPIRVLastAssignedInputSemanticLocation += ElementCount;
710
711 return createSPIRVLocationLoad(B, CGM.getModule(), Type, Location,
712 VariableName.str());
713}
714
715static void createSPIRVLocationStore(IRBuilder<> &B, llvm::Module &M,
716 llvm::Value *Source, unsigned Location,
717 StringRef Name) {
718 auto *GV = new llvm::GlobalVariable(
719 M, Source->getType(), /* isConstant= */ false,
720 llvm::GlobalValue::ExternalLinkage,
721 /* Initializer= */ nullptr, /* Name= */ Name, /* insertBefore= */ nullptr,
722 llvm::GlobalVariable::GeneralDynamicTLSModel,
723 /* AddressSpace */ 8, /* isExternallyInitialized= */ false);
724 GV->setVisibility(llvm::GlobalValue::HiddenVisibility);
725 addLocationDecoration(GV, Location);
726 B.CreateStore(Source, GV);
727}
728
729void CGHLSLRuntime::emitSPIRVUserSemanticStore(
730 llvm::IRBuilder<> &B, llvm::Value *Source,
731 const clang::DeclaratorDecl *Decl, HLSLAppliedSemanticAttr *Semantic,
732 std::optional<unsigned> Index) {
733 Twine BaseName = Twine(Semantic->getAttrName()->getName());
734 Twine VariableName = BaseName.concat(Twine(Index.value_or(0)));
735
736 unsigned Location = SPIRVLastAssignedOutputSemanticLocation;
737 if (auto *L = Decl->getAttr<HLSLVkLocationAttr>())
738 Location = L->getLocation();
739
740 // DXC completely ignores the semantic/index pair. Location are assigned from
741 // the first semantic to the last.
742 llvm::ArrayType *AT = dyn_cast<llvm::ArrayType>(Source->getType());
743 unsigned ElementCount = AT ? AT->getNumElements() : 1;
744 SPIRVLastAssignedOutputSemanticLocation += ElementCount;
745 createSPIRVLocationStore(B, CGM.getModule(), Source, Location,
746 VariableName.str());
747}
748
749llvm::Value *
750CGHLSLRuntime::emitDXILUserSemanticLoad(llvm::IRBuilder<> &B, llvm::Type *Type,
751 HLSLAppliedSemanticAttr *Semantic,
752 std::optional<unsigned> Index) {
753 Twine BaseName = Twine(Semantic->getAttrName()->getName());
754 Twine VariableName = BaseName.concat(Twine(Index.value_or(0)));
755
756 // DXIL packing rules etc shall be handled here.
757 // FIXME: generate proper sigpoint, index, col, row values.
758 // FIXME: also DXIL loads vectors element by element.
759 SmallVector<Value *> Args{B.getInt32(4), B.getInt32(0), B.getInt32(0),
760 B.getInt8(0),
761 llvm::PoisonValue::get(B.getInt32Ty())};
762
763 llvm::Intrinsic::ID IntrinsicID = llvm::Intrinsic::dx_load_input;
764
765 SmallVector<OperandBundleDef, 1> OB;
766 if (auto *Token = getConvergenceToken(*B.GetInsertBlock())) {
767 llvm::Value *bundleArgs[] = {Token};
768 OB.emplace_back("convergencectrl", bundleArgs);
769 }
770
771 llvm::Function *IntrFn = llvm::Intrinsic::getOrInsertDeclaration(
772 B.GetInsertBlock()->getModule(), IntrinsicID, {Type});
773 llvm::Value *Value = B.CreateCall(IntrFn, Args, OB, VariableName);
774 return Value;
775}
776
777void CGHLSLRuntime::emitDXILUserSemanticStore(llvm::IRBuilder<> &B,
778 llvm::Value *Source,
779 HLSLAppliedSemanticAttr *Semantic,
780 std::optional<unsigned> Index) {
781 // DXIL packing rules etc shall be handled here.
782 // FIXME: generate proper sigpoint, index, col, row values.
783 SmallVector<Value *> Args{B.getInt32(4),
784 B.getInt32(0),
785 B.getInt32(0),
786 B.getInt8(0),
787 llvm::PoisonValue::get(B.getInt32Ty()),
788 Source};
789
790 llvm::Intrinsic::ID IntrinsicID = llvm::Intrinsic::dx_store_output;
791
792 SmallVector<OperandBundleDef, 1> OB;
793 if (auto *Token = getConvergenceToken(*B.GetInsertBlock())) {
794 llvm::Value *bundleArgs[] = {Token};
795 OB.emplace_back("convergencectrl", bundleArgs);
796 }
797
798 llvm::Function *IntrFn = llvm::Intrinsic::getOrInsertDeclaration(
799 B.GetInsertBlock()->getModule(), IntrinsicID, {Source->getType()});
800 B.CreateCall(IntrFn, Args, OB);
801}
802
803llvm::Value *CGHLSLRuntime::emitUserSemanticLoad(
804 IRBuilder<> &B, llvm::Type *Type, const clang::DeclaratorDecl *Decl,
805 HLSLAppliedSemanticAttr *Semantic, std::optional<unsigned> Index) {
806 if (CGM.getTarget().getTriple().isSPIRV())
807 return emitSPIRVUserSemanticLoad(B, Type, Decl, Semantic, Index);
808
809 if (CGM.getTarget().getTriple().isDXIL())
810 return emitDXILUserSemanticLoad(B, Type, Semantic, Index);
811
812 llvm_unreachable("Unsupported target for user-semantic load.");
813}
814
815void CGHLSLRuntime::emitUserSemanticStore(IRBuilder<> &B, llvm::Value *Source,
816 const clang::DeclaratorDecl *Decl,
817 HLSLAppliedSemanticAttr *Semantic,
818 std::optional<unsigned> Index) {
819 if (CGM.getTarget().getTriple().isSPIRV())
820 return emitSPIRVUserSemanticStore(B, Source, Decl, Semantic, Index);
821
822 if (CGM.getTarget().getTriple().isDXIL())
823 return emitDXILUserSemanticStore(B, Source, Semantic, Index);
824
825 llvm_unreachable("Unsupported target for user-semantic load.");
826}
827
829 IRBuilder<> &B, const FunctionDecl *FD, llvm::Type *Type,
830 const clang::DeclaratorDecl *Decl, HLSLAppliedSemanticAttr *Semantic,
831 std::optional<unsigned> Index) {
832
833 std::string SemanticName = Semantic->getAttrName()->getName().upper();
834 if (SemanticName == "SV_GROUPINDEX") {
835 llvm::Function *GroupIndex =
836 CGM.getIntrinsic(getFlattenedThreadIdInGroupIntrinsic());
837 return B.CreateCall(FunctionCallee(GroupIndex));
838 }
839
840 if (SemanticName == "SV_DISPATCHTHREADID") {
841 llvm::Intrinsic::ID IntrinID = getThreadIdIntrinsic();
842 llvm::Function *ThreadIDIntrinsic =
843 llvm::Intrinsic::isOverloaded(IntrinID)
844 ? CGM.getIntrinsic(IntrinID, {CGM.Int32Ty})
845 : CGM.getIntrinsic(IntrinID);
846 return buildVectorInput(B, ThreadIDIntrinsic, Type);
847 }
848
849 if (SemanticName == "SV_GROUPTHREADID") {
850 llvm::Intrinsic::ID IntrinID = getGroupThreadIdIntrinsic();
851 llvm::Function *GroupThreadIDIntrinsic =
852 llvm::Intrinsic::isOverloaded(IntrinID)
853 ? CGM.getIntrinsic(IntrinID, {CGM.Int32Ty})
854 : CGM.getIntrinsic(IntrinID);
855 return buildVectorInput(B, GroupThreadIDIntrinsic, Type);
856 }
857
858 if (SemanticName == "SV_GROUPID") {
859 llvm::Intrinsic::ID IntrinID = getGroupIdIntrinsic();
860 llvm::Function *GroupIDIntrinsic =
861 llvm::Intrinsic::isOverloaded(IntrinID)
862 ? CGM.getIntrinsic(IntrinID, {CGM.Int32Ty})
863 : CGM.getIntrinsic(IntrinID);
864 return buildVectorInput(B, GroupIDIntrinsic, Type);
865 }
866
867 const auto *ShaderAttr = FD->getAttr<HLSLShaderAttr>();
868 assert(ShaderAttr && "Entry point has no shader attribute");
869 llvm::Triple::EnvironmentType ST = ShaderAttr->getType();
870
871 if (SemanticName == "SV_POSITION") {
872 if (ST == Triple::EnvironmentType::Pixel) {
873 if (CGM.getTarget().getTriple().isSPIRV())
874 return createSPIRVBuiltinLoad(B, CGM.getModule(), Type,
875 Semantic->getAttrName()->getName(),
876 /* BuiltIn::FragCoord */ 15);
877 if (CGM.getTarget().getTriple().isDXIL())
878 return emitDXILUserSemanticLoad(B, Type, Semantic, Index);
879 }
880
881 if (ST == Triple::EnvironmentType::Vertex) {
882 return emitUserSemanticLoad(B, Type, Decl, Semantic, Index);
883 }
884 }
885
886 if (SemanticName == "SV_VERTEXID") {
887 if (ST == Triple::EnvironmentType::Vertex) {
888 if (CGM.getTarget().getTriple().isSPIRV())
889 return createSPIRVBuiltinLoad(B, CGM.getModule(), Type,
890 Semantic->getAttrName()->getName(),
891 /* BuiltIn::VertexIndex */ 42);
892 else
893 return emitDXILUserSemanticLoad(B, Type, Semantic, Index);
894 }
895 }
896
897 llvm_unreachable(
898 "Load hasn't been implemented yet for this system semantic. FIXME");
899}
900
901static void createSPIRVBuiltinStore(IRBuilder<> &B, llvm::Module &M,
902 llvm::Value *Source, const Twine &Name,
903 unsigned BuiltInID) {
904 auto *GV = new llvm::GlobalVariable(
905 M, Source->getType(), /* isConstant= */ false,
906 llvm::GlobalValue::ExternalLinkage,
907 /* Initializer= */ nullptr, Name, /* insertBefore= */ nullptr,
908 llvm::GlobalVariable::GeneralDynamicTLSModel,
909 /* AddressSpace */ 8, /* isExternallyInitialized= */ false);
910 addSPIRVBuiltinDecoration(GV, BuiltInID);
911 GV->setVisibility(llvm::GlobalValue::HiddenVisibility);
912 B.CreateStore(Source, GV);
913}
914
915void CGHLSLRuntime::emitSystemSemanticStore(IRBuilder<> &B, llvm::Value *Source,
917 HLSLAppliedSemanticAttr *Semantic,
918 std::optional<unsigned> Index) {
919
920 std::string SemanticName = Semantic->getAttrName()->getName().upper();
921 if (SemanticName == "SV_POSITION") {
922 if (CGM.getTarget().getTriple().isDXIL()) {
923 emitDXILUserSemanticStore(B, Source, Semantic, Index);
924 return;
925 }
926
927 if (CGM.getTarget().getTriple().isSPIRV()) {
928 createSPIRVBuiltinStore(B, CGM.getModule(), Source,
929 Semantic->getAttrName()->getName(),
930 /* BuiltIn::Position */ 0);
931 return;
932 }
933 }
934
935 if (SemanticName == "SV_TARGET") {
936 emitUserSemanticStore(B, Source, Decl, Semantic, Index);
937 return;
938 }
939
940 llvm_unreachable(
941 "Store hasn't been implemented yet for this system semantic. FIXME");
942}
943
945 IRBuilder<> &B, const FunctionDecl *FD, llvm::Type *Type,
946 const clang::DeclaratorDecl *Decl, HLSLAppliedSemanticAttr *Semantic) {
947
948 std::optional<unsigned> Index = Semantic->getSemanticIndex();
949 if (Semantic->getAttrName()->getName().starts_with_insensitive("SV_"))
950 return emitSystemSemanticLoad(B, FD, Type, Decl, Semantic, Index);
951 return emitUserSemanticLoad(B, Type, Decl, Semantic, Index);
952}
953
955 IRBuilder<> &B, const FunctionDecl *FD, llvm::Value *Source,
956 const clang::DeclaratorDecl *Decl, HLSLAppliedSemanticAttr *Semantic) {
957 std::optional<unsigned> Index = Semantic->getSemanticIndex();
958 if (Semantic->getAttrName()->getName().starts_with_insensitive("SV_"))
959 emitSystemSemanticStore(B, Source, Decl, Semantic, Index);
960 else
961 emitUserSemanticStore(B, Source, Decl, Semantic, Index);
962}
963
964std::pair<llvm::Value *, specific_attr_iterator<HLSLAppliedSemanticAttr>>
966 IRBuilder<> &B, const FunctionDecl *FD, llvm::Type *Type,
970 const llvm::StructType *ST = cast<StructType>(Type);
971 const clang::RecordDecl *RD = Decl->getType()->getAsRecordDecl();
972
973 assert(RD->getNumFields() == ST->getNumElements());
974
975 llvm::Value *Aggregate = llvm::PoisonValue::get(Type);
976 auto FieldDecl = RD->field_begin();
977 for (unsigned I = 0; I < ST->getNumElements(); ++I) {
978 auto [ChildValue, NextAttr] = handleSemanticLoad(
979 B, FD, ST->getElementType(I), *FieldDecl, AttrBegin, AttrEnd);
980 AttrBegin = NextAttr;
981 assert(ChildValue);
982 Aggregate = B.CreateInsertValue(Aggregate, ChildValue, I);
983 ++FieldDecl;
984 }
985
986 return std::make_pair(Aggregate, AttrBegin);
987}
988
991 IRBuilder<> &B, const FunctionDecl *FD, llvm::Value *Source,
995
996 const llvm::StructType *ST = cast<StructType>(Source->getType());
997
998 const clang::RecordDecl *RD = nullptr;
999 if (const FunctionDecl *FD = dyn_cast<FunctionDecl>(Decl))
1001 else
1002 RD = Decl->getType()->getAsRecordDecl();
1003 assert(RD);
1004
1005 assert(RD->getNumFields() == ST->getNumElements());
1006
1007 auto FieldDecl = RD->field_begin();
1008 for (unsigned I = 0; I < ST->getNumElements(); ++I, ++FieldDecl) {
1009 llvm::Value *Extract = B.CreateExtractValue(Source, I);
1010 AttrBegin =
1011 handleSemanticStore(B, FD, Extract, *FieldDecl, AttrBegin, AttrEnd);
1012 }
1013
1014 return AttrBegin;
1015}
1016
1017std::pair<llvm::Value *, specific_attr_iterator<HLSLAppliedSemanticAttr>>
1019 IRBuilder<> &B, const FunctionDecl *FD, llvm::Type *Type,
1023 assert(AttrBegin != AttrEnd);
1024 if (Type->isStructTy())
1025 return handleStructSemanticLoad(B, FD, Type, Decl, AttrBegin, AttrEnd);
1026
1027 HLSLAppliedSemanticAttr *Attr = *AttrBegin;
1028 ++AttrBegin;
1029 return std::make_pair(handleScalarSemanticLoad(B, FD, Type, Decl, Attr),
1030 AttrBegin);
1031}
1032
1035 IRBuilder<> &B, const FunctionDecl *FD, llvm::Value *Source,
1039 assert(AttrBegin != AttrEnd);
1040 if (Source->getType()->isStructTy())
1041 return handleStructSemanticStore(B, FD, Source, Decl, AttrBegin, AttrEnd);
1042
1043 HLSLAppliedSemanticAttr *Attr = *AttrBegin;
1044 ++AttrBegin;
1045 handleScalarSemanticStore(B, FD, Source, Decl, Attr);
1046 return AttrBegin;
1047}
1048
1050 llvm::Function *Fn) {
1051 llvm::Module &M = CGM.getModule();
1052 llvm::LLVMContext &Ctx = M.getContext();
1053 auto *EntryTy = llvm::FunctionType::get(llvm::Type::getVoidTy(Ctx), false);
1054 Function *EntryFn =
1055 Function::Create(EntryTy, Function::ExternalLinkage, FD->getName(), &M);
1056
1057 // Copy function attributes over, we have no argument or return attributes
1058 // that can be valid on the real entry.
1059 AttributeList NewAttrs = AttributeList::get(Ctx, AttributeList::FunctionIndex,
1060 Fn->getAttributes().getFnAttrs());
1061 EntryFn->setAttributes(NewAttrs);
1062 setHLSLEntryAttributes(FD, EntryFn);
1063
1064 // Set the called function as internal linkage.
1065 Fn->setLinkage(GlobalValue::InternalLinkage);
1066
1067 BasicBlock *BB = BasicBlock::Create(Ctx, "entry", EntryFn);
1068 IRBuilder<> B(BB);
1070
1072 if (CGM.shouldEmitConvergenceTokens()) {
1073 assert(EntryFn->isConvergent());
1074 llvm::Value *I =
1075 B.CreateIntrinsic(llvm::Intrinsic::experimental_convergence_entry, {});
1076 llvm::Value *bundleArgs[] = {I};
1077 OB.emplace_back("convergencectrl", bundleArgs);
1078 }
1079
1081
1082 unsigned SRetOffset = 0;
1083 for (const auto &Param : Fn->args()) {
1084 if (Param.hasStructRetAttr()) {
1085 SRetOffset = 1;
1086 llvm::Type *VarType = Param.getParamStructRetType();
1087 llvm::Value *Var =
1088 CGM.getLangOpts().EmitLogicalPointer
1089 ? cast<Instruction>(B.CreateStructuredAlloca(VarType))
1090 : cast<Instruction>(B.CreateAlloca(VarType));
1091 OutputSemantic.push_back(std::make_pair(Var, VarType));
1092 Args.push_back(Var);
1093 continue;
1094 }
1095
1096 const ParmVarDecl *PD = FD->getParamDecl(Param.getArgNo() - SRetOffset);
1097 llvm::Value *SemanticValue = nullptr;
1098 // FIXME: support inout/out parameters for semantics.
1099 if ([[maybe_unused]] HLSLParamModifierAttr *MA =
1100 PD->getAttr<HLSLParamModifierAttr>()) {
1101 llvm_unreachable("Not handled yet");
1102 } else {
1103 llvm::Type *ParamType =
1104 Param.hasByValAttr() ? Param.getParamByValType() : Param.getType();
1105 auto AttrBegin = PD->specific_attr_begin<HLSLAppliedSemanticAttr>();
1106 auto AttrEnd = PD->specific_attr_end<HLSLAppliedSemanticAttr>();
1107 auto Result =
1108 handleSemanticLoad(B, FD, ParamType, PD, AttrBegin, AttrEnd);
1109 SemanticValue = Result.first;
1110 if (!SemanticValue)
1111 return;
1112 if (Param.hasByValAttr()) {
1113 llvm::Value *Var =
1114 CGM.getLangOpts().EmitLogicalPointer
1116 B.CreateStructuredAlloca(Param.getParamByValType()))
1117 : cast<Instruction>(B.CreateAlloca(Param.getParamByValType()));
1118 B.CreateStore(SemanticValue, Var);
1119 SemanticValue = Var;
1120 }
1121 }
1122
1123 assert(SemanticValue);
1124 Args.push_back(SemanticValue);
1125 }
1126
1127 CallInst *CI = B.CreateCall(FunctionCallee(Fn), Args, OB);
1128 CI->setCallingConv(Fn->getCallingConv());
1129
1130 if (Fn->getReturnType() != CGM.VoidTy)
1131 // Element type is unused, so set to dummy value (NULL).
1132 OutputSemantic.push_back(std::make_pair(CI, nullptr));
1133
1134 for (auto &SourcePair : OutputSemantic) {
1135 llvm::Value *Source = SourcePair.first;
1136 llvm::Type *ElementType = SourcePair.second;
1137 AllocaInst *AI = dyn_cast<AllocaInst>(Source);
1138 llvm::Value *SourceValue = AI ? B.CreateLoad(ElementType, Source) : Source;
1139
1140 auto AttrBegin = FD->specific_attr_begin<HLSLAppliedSemanticAttr>();
1141 auto AttrEnd = FD->specific_attr_end<HLSLAppliedSemanticAttr>();
1142 handleSemanticStore(B, FD, SourceValue, FD, AttrBegin, AttrEnd);
1143 }
1144
1145 B.CreateRetVoid();
1146
1147 // Add and identify root signature to function, if applicable
1148 for (const Attr *Attr : FD->getAttrs()) {
1149 if (const auto *RSAttr = dyn_cast<RootSignatureAttr>(Attr)) {
1150 auto *RSDecl = RSAttr->getSignatureDecl();
1151 addRootSignatureMD(RSDecl->getVersion(), RSDecl->getRootElements(),
1152 EntryFn, M);
1153 }
1154 }
1155}
1156
1157static void gatherFunctions(SmallVectorImpl<Function *> &Fns, llvm::Module &M,
1158 bool CtorOrDtor) {
1159 const auto *GV =
1160 M.getNamedGlobal(CtorOrDtor ? "llvm.global_ctors" : "llvm.global_dtors");
1161 if (!GV)
1162 return;
1163 const auto *CA = dyn_cast<ConstantArray>(GV->getInitializer());
1164 if (!CA)
1165 return;
1166 // The global_ctor array elements are a struct [Priority, Fn *, COMDat].
1167 // HLSL neither supports priorities or COMDat values, so we will check those
1168 // in an assert but not handle them.
1169
1170 for (const auto &Ctor : CA->operands()) {
1172 continue;
1173 ConstantStruct *CS = cast<ConstantStruct>(Ctor);
1174
1175 assert(cast<ConstantInt>(CS->getOperand(0))->getValue() == 65535 &&
1176 "HLSL doesn't support setting priority for global ctors.");
1177 assert(isa<ConstantPointerNull>(CS->getOperand(2)) &&
1178 "HLSL doesn't support COMDat for global ctors.");
1179 Fns.push_back(cast<Function>(CS->getOperand(1)));
1180 }
1181}
1182
1184 llvm::Module &M = CGM.getModule();
1187 gatherFunctions(CtorFns, M, true);
1188 gatherFunctions(DtorFns, M, false);
1189
1190 // Insert a call to the global constructor at the beginning of the entry block
1191 // to externally exported functions. This is a bit of a hack, but HLSL allows
1192 // global constructors, but doesn't support driver initialization of globals.
1193 for (auto &F : M.functions()) {
1194 if (!F.hasFnAttribute("hlsl.shader"))
1195 continue;
1196 auto *Token = getConvergenceToken(F.getEntryBlock());
1197 Instruction *IP = &*F.getEntryBlock().begin();
1199 if (Token) {
1200 llvm::Value *bundleArgs[] = {Token};
1201 OB.emplace_back("convergencectrl", bundleArgs);
1202 IP = Token->getNextNode();
1203 }
1204 IRBuilder<> B(IP);
1205 for (auto *Fn : CtorFns) {
1206 auto CI = B.CreateCall(FunctionCallee(Fn), {}, OB);
1207 CI->setCallingConv(Fn->getCallingConv());
1208 }
1209
1210 // Insert global dtors before the terminator of the last instruction
1211 B.SetInsertPoint(F.back().getTerminator());
1212 for (auto *Fn : DtorFns) {
1213 auto CI = B.CreateCall(FunctionCallee(Fn), {}, OB);
1214 CI->setCallingConv(Fn->getCallingConv());
1215 }
1216 }
1217
1218 // No need to keep global ctors/dtors for non-lib profile after call to
1219 // ctors/dtors added for entry.
1220 Triple T(M.getTargetTriple());
1221 if (T.getEnvironment() != Triple::EnvironmentType::Library) {
1222 if (auto *GV = M.getNamedGlobal("llvm.global_ctors"))
1223 GV->eraseFromParent();
1224 if (auto *GV = M.getNamedGlobal("llvm.global_dtors"))
1225 GV->eraseFromParent();
1226 }
1227}
1228
1229static void initializeBuffer(CodeGenModule &CGM, llvm::GlobalVariable *GV,
1230 Intrinsic::ID IntrID,
1232
1233 LLVMContext &Ctx = CGM.getLLVMContext();
1234 llvm::Function *InitResFunc = llvm::Function::Create(
1235 llvm::FunctionType::get(CGM.VoidTy, false),
1236 llvm::GlobalValue::InternalLinkage,
1237 ("_init_buffer_" + GV->getName()).str(), CGM.getModule());
1238 InitResFunc->addFnAttr(llvm::Attribute::AlwaysInline);
1239
1240 llvm::BasicBlock *EntryBB =
1241 llvm::BasicBlock::Create(Ctx, "entry", InitResFunc);
1242 CGBuilderTy Builder(CGM, Ctx);
1243 const DataLayout &DL = CGM.getModule().getDataLayout();
1244 Builder.SetInsertPoint(EntryBB);
1245
1246 // Make sure the global variable is buffer resource handle
1247 llvm::Type *HandleTy = GV->getValueType();
1248 assert(HandleTy->isTargetExtTy() && "unexpected type of the buffer global");
1249
1250 llvm::Value *CreateHandle = Builder.CreateIntrinsic(
1251 /*ReturnType=*/HandleTy, IntrID, Args, nullptr,
1252 Twine(GV->getName()).concat("_h"));
1253
1254 Builder.CreateAlignedStore(CreateHandle, GV, GV->getPointerAlignment(DL));
1255 Builder.CreateRetVoid();
1256
1257 CGM.AddCXXGlobalInit(InitResFunc);
1258}
1259
1260void CGHLSLRuntime::initializeBufferFromBinding(const HLSLBufferDecl *BufDecl,
1261 llvm::GlobalVariable *GV) {
1262 ResourceBindingAttrs Binding(BufDecl);
1263 assert(Binding.hasBinding() &&
1264 "cbuffer/tbuffer should always have resource binding attribute");
1265
1266 auto *Index = llvm::ConstantInt::get(CGM.IntTy, 0);
1267 auto *RangeSize = llvm::ConstantInt::get(CGM.IntTy, 1);
1268 auto *Space = llvm::ConstantInt::get(CGM.IntTy, Binding.getSpace());
1269 Value *Name = buildNameForResource(BufDecl->getName(), CGM);
1270
1271 // buffer with explicit binding
1272 if (Binding.isExplicit()) {
1273 llvm::Intrinsic::ID IntrinsicID =
1274 CGM.getHLSLRuntime().getCreateHandleFromBindingIntrinsic();
1275 auto *RegSlot = llvm::ConstantInt::get(CGM.IntTy, Binding.getSlot());
1276 SmallVector<Value *> Args{Space, RegSlot, RangeSize, Index, Name};
1277 initializeBuffer(CGM, GV, IntrinsicID, Args);
1278 } else {
1279 // buffer with implicit binding
1280 llvm::Intrinsic::ID IntrinsicID =
1281 CGM.getHLSLRuntime().getCreateHandleFromImplicitBindingIntrinsic();
1282 auto *OrderID =
1283 llvm::ConstantInt::get(CGM.IntTy, Binding.getImplicitOrderID());
1284 SmallVector<Value *> Args{OrderID, Space, RangeSize, Index, Name};
1285 initializeBuffer(CGM, GV, IntrinsicID, Args);
1286 }
1287}
1288
1290 llvm::GlobalVariable *GV) {
1291 if (auto Attr = VD->getAttr<HLSLVkExtBuiltinInputAttr>())
1292 addSPIRVBuiltinDecoration(GV, Attr->getBuiltIn());
1293 if (auto Attr = VD->getAttr<HLSLVkExtBuiltinOutputAttr>())
1294 addSPIRVBuiltinDecoration(GV, Attr->getBuiltIn());
1295}
1296
1297llvm::Instruction *CGHLSLRuntime::getConvergenceToken(BasicBlock &BB) {
1298 if (!CGM.shouldEmitConvergenceTokens())
1299 return nullptr;
1300
1301 auto E = BB.end();
1302 for (auto I = BB.begin(); I != E; ++I) {
1303 auto *II = dyn_cast<llvm::IntrinsicInst>(&*I);
1304 if (II && llvm::isConvergenceControlIntrinsic(II->getIntrinsicID())) {
1305 return II;
1306 }
1307 }
1308 llvm_unreachable("Convergence token should have been emitted.");
1309 return nullptr;
1310}
1311
1312class OpaqueValueVisitor : public RecursiveASTVisitor<OpaqueValueVisitor> {
1313public:
1317
1319 // These need to be bound in CodeGenFunction::EmitHLSLOutArgLValues
1320 // or CodeGenFunction::EmitHLSLOutArgExpr. If they are part of this
1321 // traversal, the temporary containing the copy out will not have
1322 // been created yet.
1323 return false;
1324 }
1325
1327 // Traverse the source expression first.
1328 if (E->getSourceExpr())
1330
1331 // Then add this OVE if we haven't seen it before.
1332 if (Visited.insert(E).second)
1333 OVEs.push_back(E);
1334
1335 return true;
1336 }
1337};
1338
1340 InitListExpr *E) {
1341
1342 typedef CodeGenFunction::OpaqueValueMappingData OpaqueValueMappingData;
1343 OpaqueValueVisitor Visitor;
1344 Visitor.TraverseStmt(E);
1345 for (auto *OVE : Visitor.OVEs) {
1346 if (CGF.isOpaqueValueEmitted(OVE))
1347 continue;
1348 if (OpaqueValueMappingData::shouldBindAsLValue(OVE)) {
1349 LValue LV = CGF.EmitLValue(OVE->getSourceExpr());
1350 OpaqueValueMappingData::bind(CGF, OVE, LV);
1351 } else {
1352 RValue RV = CGF.EmitAnyExpr(OVE->getSourceExpr());
1353 OpaqueValueMappingData::bind(CGF, OVE, RV);
1354 }
1355 }
1356}
1357
1359 const ArraySubscriptExpr *ArraySubsExpr, CodeGenFunction &CGF) {
1360 assert((ArraySubsExpr->getType()->isHLSLResourceRecord() ||
1361 ArraySubsExpr->getType()->isHLSLResourceRecordArray()) &&
1362 "expected resource array subscript expression");
1363
1364 // Let clang codegen handle local and static resource array subscripts,
1365 // or when the subscript references on opaque expression (as part of
1366 // ArrayInitLoopExpr AST node).
1367 const VarDecl *ArrayDecl = dyn_cast_or_null<VarDecl>(
1368 getArrayDecl(CGF.CGM.getContext(), ArraySubsExpr));
1369 if (!ArrayDecl || !ArrayDecl->hasGlobalStorage() ||
1370 ArrayDecl->getStorageClass() == SC_Static)
1371 return std::nullopt;
1372
1373 // get the resource array type
1374 ASTContext &AST = ArrayDecl->getASTContext();
1375 const Type *ResArrayTy = ArrayDecl->getType().getTypePtr();
1376 assert(ResArrayTy->isHLSLResourceRecordArray() &&
1377 "expected array of resource classes");
1378
1379 // Iterate through all nested array subscript expressions to calculate
1380 // the index in the flattened resource array (if this is a multi-
1381 // dimensional array). The index is calculated as a sum of all indices
1382 // multiplied by the total size of the array at that level.
1383 Value *Index = nullptr;
1384 const ArraySubscriptExpr *ASE = ArraySubsExpr;
1385 while (ASE != nullptr) {
1386 Value *SubIndex = CGF.EmitScalarExpr(ASE->getIdx());
1387 if (const auto *ArrayTy =
1388 dyn_cast<ConstantArrayType>(ASE->getType().getTypePtr())) {
1389 Value *Multiplier = llvm::ConstantInt::get(
1390 CGM.IntTy, AST.getConstantArrayElementCount(ArrayTy));
1391 SubIndex = CGF.Builder.CreateMul(SubIndex, Multiplier);
1392 }
1393 Index = Index ? CGF.Builder.CreateAdd(Index, SubIndex) : SubIndex;
1394 ASE = dyn_cast<ArraySubscriptExpr>(ASE->getBase()->IgnoreParenImpCasts());
1395 }
1396
1397 // Find binding info for the resource array. For implicit binding
1398 // an HLSLResourceBindingAttr should have been added by SemaHLSL.
1399 ResourceBindingAttrs Binding(ArrayDecl);
1400 assert(Binding.hasBinding() &&
1401 "resource array must have a binding attribute");
1402
1403 // Find the individual resource type.
1404 QualType ResultTy = ArraySubsExpr->getType();
1405 QualType ResourceTy =
1406 ResultTy->isArrayType() ? AST.getBaseElementType(ResultTy) : ResultTy;
1407
1408 // Create a temporary variable for the result, which is either going
1409 // to be a single resource instance or a local array of resources (we need to
1410 // return an LValue).
1411 RawAddress TmpVar = CGF.CreateMemTempWithoutCast(ResultTy);
1412 if (CGF.EmitLifetimeStart(TmpVar.getPointer()))
1414 NormalEHLifetimeMarker, TmpVar);
1415
1420
1421 // Calculate total array size (= range size).
1422 llvm::Value *Range = llvm::ConstantInt::getSigned(
1423 CGM.IntTy, getTotalArraySize(AST, ResArrayTy));
1424
1425 // If the result of the subscript operation is a single resource, call the
1426 // constructor.
1427 if (ResultTy == ResourceTy) {
1428 CallArgList Args;
1429 CXXMethodDecl *CreateMethod = lookupResourceInitMethodAndSetupArgs(
1430 CGF.CGM, ResourceTy->getAsCXXRecordDecl(), Range, Index,
1431 ArrayDecl->getName(), Binding, Args);
1432
1433 if (!CreateMethod) {
1434 // This can happen if someone creates an array of structs that looks like
1435 // an HLSL resource record array but it does not have the required static
1436 // create method. No binding will be generated for it.
1437 assert(!ResourceTy->getAsCXXRecordDecl()->isImplicit() &&
1438 "create method lookup should always succeed for built-in resource "
1439 "records");
1440 return std::nullopt;
1441 }
1442
1443 callResourceInitMethod(CGF, CreateMethod, Args, ValueSlot.getAddress());
1444
1445 } else {
1446 // The result of the subscript operation is a local resource array which
1447 // needs to be initialized.
1448 const ConstantArrayType *ArrayTy =
1450 std::optional<llvm::Value *> EndIndex = initializeResourceArrayFromGlobal(
1451 CGF, ResourceTy->getAsCXXRecordDecl(), ArrayTy, ValueSlot, Range, Index,
1452 ArrayDecl->getName(), Binding, {llvm::ConstantInt::get(CGM.IntTy, 0)},
1453 ArraySubsExpr->getExprLoc());
1454 if (!EndIndex)
1455 return std::nullopt;
1456 }
1457 return CGF.MakeAddrLValue(TmpVar, ResultTy, AlignmentSource::Decl);
1458}
1459
1460// Initialize all resources of a global resource array into provided slot.
1461bool CGHLSLRuntime::initializeGlobalResourceArray(CodeGenFunction &CGF,
1462 const VarDecl *ArrayDecl,
1463 SourceLocation Loc,
1464 AggValueSlot &DestSlot) {
1465 assert(ArrayDecl->getType()->isHLSLResourceRecordArray() &&
1466 ArrayDecl->hasGlobalStorage() &&
1467 ArrayDecl->getStorageClass() != SC_Static &&
1468 "expected global non-static resource array");
1469
1470 // Find binding info for the resource array. For implicit binding
1471 // the HLSLResourceBindingAttr should have been added by SemaHLSL.
1472 ResourceBindingAttrs Binding(ArrayDecl);
1473 assert(Binding.hasBinding() &&
1474 "resource array must have a binding attribute");
1475
1476 // Find the individual resource type.
1477 ASTContext &AST = ArrayDecl->getASTContext();
1478 QualType ResTy = AST.getBaseElementType(ArrayDecl->getType());
1479 const auto *ResArrayTy =
1481
1482 // Create Value for index and total array size (= range size).
1483 int Size = getTotalArraySize(AST, ResArrayTy);
1484 llvm::Value *Zero = llvm::ConstantInt::get(CGM.IntTy, 0);
1485 llvm::Value *Range = llvm::ConstantInt::get(CGM.IntTy, Size);
1486
1487 // Initialize individual resources in the array into DestSlot.
1488 std::optional<llvm::Value *> EndIndex = initializeResourceArrayFromGlobal(
1489 CGF, ResTy->getAsCXXRecordDecl(), ResArrayTy, DestSlot, Range, Zero,
1490 ArrayDecl->getName(), Binding, {Zero}, Loc);
1491 return EndIndex.has_value();
1492}
1493
1494// If the expression is a global resource array, initialize all of its resources
1495// into Dest. Returns false if no initialization has been performed and the
1496// array copy should be handled by the default codegen.
1498 AggValueSlot &DestSlot) {
1499 assert(E->getType()->isHLSLResourceRecordArray() &&
1500 "expected resource array");
1501
1502 // Find the array declaration for the expression. Fallback to the default
1503 // handling if it's not a global resource array.
1504 const VarDecl *ArrayDecl =
1505 dyn_cast_or_null<VarDecl>(getArrayDecl(CGF.CGM.getContext(), E));
1506 if (!ArrayDecl || !ArrayDecl->hasGlobalStorage() ||
1507 ArrayDecl->getStorageClass() == SC_Static)
1508 return false;
1509
1510 return initializeGlobalResourceArray(CGF, ArrayDecl, E->getExprLoc(),
1511 DestSlot);
1512}
1513
1514// If the expression is a global resource array, create a temporary and
1515// initialize all of its resources, and return it as an LValue. Returns nullopt
1516// if no initialization has been performed and the handling should follow the
1517// default path.
1519 CodeGenFunction &CGF, const VarDecl *ArrayDecl, SourceLocation Loc) {
1520 assert(ArrayDecl->getType()->isHLSLResourceRecordArray() &&
1521 "expected resource array declaration");
1522
1523 if (!ArrayDecl->hasGlobalStorage() ||
1524 ArrayDecl->getStorageClass() == SC_Static)
1525 return std::nullopt;
1526
1527 AggValueSlot TmpArraySlot =
1528 CGF.CreateAggTemp(ArrayDecl->getType(), "tmpResArray");
1529 if (initializeGlobalResourceArray(CGF, ArrayDecl, Loc, TmpArraySlot))
1530 return CGF.MakeAddrLValue(TmpArraySlot.getAddress(), ArrayDecl->getType(),
1532 return std::nullopt;
1533}
1534
1536 SourceLocation Loc,
1537 CodeGenFunction &CGF) {
1538
1539 assert(LV.getType()->isConstantMatrixType() && "expected matrix type");
1541 "expected cbuffer matrix");
1542
1543 QualType MatQualTy = LV.getType();
1544 llvm::Type *LayoutTy = HLSLBufferLayoutBuilder(CGF.CGM).layOutType(MatQualTy);
1545 Address SrcAddr = LV.getAddress();
1546
1547 if (LayoutTy == CGF.ConvertTypeForMem(MatQualTy))
1548 return SrcAddr;
1549
1550 RawAddress DestAlloca =
1551 CGF.CreateMemTempWithoutCast(MatQualTy, "matrix.buf.copy");
1552 emitBufferCopy(CGF, DestAlloca, SrcAddr, MatQualTy);
1553 return DestAlloca;
1554}
1555
1557 const ArraySubscriptExpr *E, CodeGenFunction &CGF,
1558 llvm::function_ref<llvm::Value *(bool Promote)> EmitIdxAfterBase) {
1559 // Find the element type to index by first padding the element type per HLSL
1560 // buffer rules, and then padding out to a 16-byte register boundary if
1561 // necessary.
1562 llvm::Type *LayoutTy =
1564 uint64_t LayoutSizeInBits =
1565 CGM.getDataLayout().getTypeSizeInBits(LayoutTy).getFixedValue();
1566 CharUnits ElementSize = CharUnits::fromQuantity(LayoutSizeInBits / 8);
1567 CharUnits RowAlignedSize = ElementSize.alignTo(CharUnits::fromQuantity(16));
1568 if (RowAlignedSize > ElementSize) {
1569 llvm::Type *Padding = CGM.getTargetCodeGenInfo().getHLSLPadding(
1570 CGM, RowAlignedSize - ElementSize);
1571 assert(Padding && "No padding type for target?");
1572 LayoutTy = llvm::StructType::get(CGF.getLLVMContext(), {LayoutTy, Padding},
1573 /*isPacked=*/true);
1574 }
1575
1576 // If the layout type doesn't introduce any padding, we don't need to do
1577 // anything special.
1578 llvm::Type *OrigTy = CGF.CGM.getTypes().ConvertTypeForMem(E->getType());
1579 if (LayoutTy == OrigTy)
1580 return std::nullopt;
1581
1582 LValueBaseInfo EltBaseInfo;
1583 TBAAAccessInfo EltTBAAInfo;
1584
1585 // Index into the object as-if we have an array of the padded element type,
1586 // and then dereference the element itself to avoid reading padding that may
1587 // be past the end of the in-memory object.
1589 llvm::Value *Idx = EmitIdxAfterBase(/*Promote*/ true);
1590 Indices.push_back(Idx);
1591 Indices.push_back(llvm::ConstantInt::get(CGF.Int32Ty, 0));
1592
1593 if (CGF.getLangOpts().EmitLogicalPointer) {
1594 // The fact that we emit an array-to-pointer decay might be an oversight,
1595 // but for now, we simply ignore it (see #179951).
1596 const CastExpr *CE = cast<CastExpr>(E->getBase());
1597 assert(CE->getCastKind() == CastKind::CK_ArrayToPointerDecay);
1598
1599 LValue LV = CGF.EmitLValue(CE->getSubExpr());
1600 Address Addr = LV.getAddress();
1601 LayoutTy = llvm::ArrayType::get(
1602 LayoutTy,
1603 cast<llvm::ArrayType>(Addr.getElementType())->getNumElements());
1604 auto *GEP = cast<StructuredGEPInst>(CGF.Builder.CreateStructuredGEP(
1605 LayoutTy, Addr.emitRawPointer(CGF), Indices, "cbufferidx"));
1606 Addr =
1607 Address(GEP, GEP->getResultElementType(), RowAlignedSize, KnownNonNull);
1608 return CGF.MakeAddrLValue(Addr, E->getType(), EltBaseInfo, EltTBAAInfo);
1609 }
1610
1611 Address Addr =
1612 CGF.EmitPointerWithAlignment(E->getBase(), &EltBaseInfo, &EltTBAAInfo);
1613 llvm::Value *GEP = CGF.Builder.CreateGEP(LayoutTy, Addr.emitRawPointer(CGF),
1614 Indices, "cbufferidx");
1615 Addr = Address(GEP, Addr.getElementType(), RowAlignedSize, KnownNonNull);
1616 return CGF.MakeAddrLValue(Addr, E->getType(), EltBaseInfo, EltTBAAInfo);
1617}
1618
1619std::optional<LValue>
1621 const MemberExpr *ME) {
1622 assert((ME->getType()->isHLSLResourceRecord() ||
1624 "expected resource member expression");
1625
1626 const VarDecl *ResourceVD =
1627 findAssociatedResourceDeclForStruct(CGF.CGM.getContext(), ME);
1628 if (!ResourceVD)
1629 return std::nullopt;
1630
1631 // Handle member of resource array type.
1632 if (ResourceVD->getType()->isHLSLResourceRecordArray())
1633 return emitGlobalResourceArrayAsLValue(CGF, ResourceVD, ME->getExprLoc());
1634
1635 // Handle member that is an individual resource.
1636 GlobalVariable *ResGV =
1637 cast<GlobalVariable>(CGM.GetAddrOfGlobalVar(ResourceVD));
1638 const DataLayout &DL = CGM.getDataLayout();
1639 llvm::Type *Ty = ResGV->getValueType();
1640 CharUnits Align = CharUnits::fromQuantity(DL.getABITypeAlign(Ty));
1641 Address Addr = Address(ResGV, Ty, Align);
1642 LValue LV = LValue::MakeAddr(Addr, ME->getType(), CGM.getContext(),
1644 CGM.getTBAAAccessInfo(ME->getType()));
1645 return LV;
1646}
1647
1648namespace {
1649/// Utility for emitting copies following the HLSL buffer layout rules (ie,
1650/// copying out of a cbuffer).
1651class HLSLBufferCopyEmitter {
1652 CodeGenFunction &CGF;
1653 Address DstPtr;
1654 Address SrcPtr;
1655 llvm::Type *LayoutTy = nullptr;
1656
1657 SmallVector<llvm::Value *> CurStoreIndices;
1658 SmallVector<llvm::Value *> CurLoadIndices;
1659
1660 // Creates & returns either a structured.gep or a ptradd/gep depending on
1661 // langopts.
1662 llvm::Value *emitAccessChain(llvm::Type *BaseTy, llvm::Value *Base,
1663 ArrayRef<llvm::Value *> Indices) {
1664 bool EmitLogical = CGF.getLangOpts().EmitLogicalPointer;
1665 if (EmitLogical)
1666 return CGF.Builder.CreateAccessChain(EmitLogical, BaseTy, Base, Indices);
1667
1669 GEPIndices.reserve(Indices.size() + 1);
1670 GEPIndices.push_back(llvm::ConstantInt::get(CGF.IntTy, 0));
1671 GEPIndices.append(Indices.begin(), Indices.end());
1672 return CGF.Builder.CreateAccessChain(EmitLogical, BaseTy, Base, GEPIndices);
1673 }
1674
1675 bool isBufferLayoutArray(llvm::StructType *ST) {
1676 // A buffer layout array is a struct with two elements: the padded array,
1677 // and the last element. That is, is should look something like this:
1678 //
1679 // { [%n x { %type, %padding }], %type }
1680 //
1681 if (!ST || ST->getNumElements() != 2)
1682 return false;
1683
1684 auto *PaddedEltsTy = dyn_cast<llvm::ArrayType>(ST->getElementType(0));
1685 if (!PaddedEltsTy)
1686 return false;
1687
1688 auto *PaddedTy = dyn_cast<llvm::StructType>(PaddedEltsTy->getElementType());
1689 if (!PaddedTy || PaddedTy->getNumElements() != 2)
1690 return false;
1691
1693 PaddedTy->getElementType(1)))
1694 return false;
1695
1696 llvm::Type *ElementTy = ST->getElementType(1);
1697 if (PaddedTy->getElementType(0) != ElementTy)
1698 return false;
1699 return true;
1700 }
1701
1702 void emitBufferLayoutCopy(Value *Src, llvm::StructType *SrcTy, Value *Dst,
1703 llvm::ArrayType *DstTy) {
1704 // Those assumptions are checked by isBufferLayoutArray.
1705 auto *SrcPaddedArrayTy = cast<llvm::ArrayType>(SrcTy->getElementType(0));
1706 assert(SrcPaddedArrayTy->getNumElements() + 1 == DstTy->getNumElements());
1707 assert(cast<llvm::StructType>(SrcPaddedArrayTy->getElementType())
1708 ->getElementType(0) == SrcTy->getElementType(1));
1709
1710 auto *SrcDataTy = SrcTy->getElementType(1);
1711 auto Zero = llvm::ConstantInt::get(CGF.IntTy, 0);
1712
1713 for (unsigned I = 0; I < SrcPaddedArrayTy->getNumElements(); ++I) {
1714 auto Index = llvm::ConstantInt::get(CGF.IntTy, I);
1715 auto *SrcElt = emitAccessChain(SrcTy, Src, {Zero, Index, Zero});
1716 auto *DstElt = emitAccessChain(DstTy, Dst, {Index});
1717 emitElementCopy(SrcElt, SrcDataTy, DstElt, DstTy->getElementType());
1718 }
1719
1720 auto *SrcElt =
1721 emitAccessChain(SrcTy, Src, {llvm::ConstantInt::get(CGF.IntTy, 1)});
1722 auto *DstElt = emitAccessChain(
1723 DstTy, Dst,
1724 {llvm::ConstantInt::get(CGF.IntTy, DstTy->getNumElements() - 1)});
1725 emitElementCopy(SrcElt, SrcDataTy, DstElt, DstTy->getElementType());
1726 }
1727
1728 void emitCopy(Value *Src, llvm::StructType *SrcTy, Value *Dst,
1729 llvm::Type *DstTy) {
1730 if (isBufferLayoutArray(SrcTy))
1731 return emitBufferLayoutCopy(Src, SrcTy, Dst,
1732 cast<llvm::ArrayType>(DstTy));
1733
1734 unsigned SrcIndex = 0;
1735 unsigned DstIndex = 0;
1736
1737 auto *DstST = cast<llvm::StructType>(DstTy);
1738 while (SrcIndex < SrcTy->getNumElements() &&
1739 DstIndex < DstST->getNumElements()) {
1741 SrcTy->getElementType(SrcIndex))) {
1742 SrcIndex += 1;
1743 continue;
1744 }
1745
1747 DstST->getElementType(DstIndex))) {
1748 DstIndex += 1;
1749 continue;
1750 }
1751
1752 auto *SrcElt = emitAccessChain(
1753 SrcTy, Src, {llvm::ConstantInt::get(CGF.IntTy, SrcIndex)});
1754 auto *DstElt = emitAccessChain(
1755 DstTy, Dst, {llvm::ConstantInt::get(CGF.IntTy, DstIndex)});
1756 emitElementCopy(SrcElt, SrcTy->getElementType(SrcIndex), DstElt,
1757 DstST->getElementType(DstIndex));
1758 DstIndex += 1;
1759 SrcIndex += 1;
1760 }
1761 }
1762
1763 void emitCopy(Value *Src, llvm::ArrayType *SrcTy, Value *Dst,
1764 llvm::Type *DstTy) {
1765 for (unsigned I = 0, E = SrcTy->getNumElements(); I < E; ++I) {
1766 auto *SrcElt =
1767 emitAccessChain(SrcTy, Src, {llvm::ConstantInt::get(CGF.IntTy, I)});
1768 auto *DstElt =
1769 emitAccessChain(DstTy, Dst, {llvm::ConstantInt::get(CGF.IntTy, I)});
1770 emitElementCopy(SrcElt, SrcTy->getElementType(), DstElt,
1771 cast<llvm::ArrayType>(DstTy)->getElementType());
1772 }
1773 }
1774
1775 void emitElementCopy(Value *Src, llvm::Type *SrcTy, Value *Dst,
1776 llvm::Type *DstTy) {
1777 if (auto *AT = dyn_cast<llvm::ArrayType>(SrcTy))
1778 return emitCopy(Src, AT, Dst, DstTy);
1779 if (auto *ST = dyn_cast<llvm::StructType>(SrcTy))
1780 return emitCopy(Src, ST, Dst, DstTy);
1781
1782 // When we have a scalar or vector element we can emit the copy.
1783 CharUnits SrcAlign =
1784 CharUnits::fromQuantity(CGF.CGM.getDataLayout().getABITypeAlign(SrcTy));
1785 CharUnits DstAlign =
1786 CharUnits::fromQuantity(CGF.CGM.getDataLayout().getABITypeAlign(DstTy));
1787 Address SrcAddr(Src, SrcTy, SrcAlign);
1788 Address DstAddr(Dst, DstTy, DstAlign);
1789 llvm::Value *Load = CGF.Builder.CreateLoad(SrcAddr, "cbuf.load");
1790 CGF.Builder.CreateStore(Load, DstAddr);
1791 }
1792
1793public:
1794 HLSLBufferCopyEmitter(CodeGenFunction &CGF, Address DstPtr, Address SrcPtr)
1795 : CGF(CGF), DstPtr(DstPtr), SrcPtr(SrcPtr) {}
1796
1797 bool emitCopy(QualType CType) {
1798 LayoutTy = HLSLBufferLayoutBuilder(CGF.CGM).layOutType(CType);
1799
1800 // TODO: We should be able to fall back to a regular memcpy if the layout
1801 // type doesn't have any padding, but that runs into issues in the backend
1802 // currently.
1803 //
1804 // See https://github.com/llvm/wg-hlsl/issues/351
1805 emitElementCopy(SrcPtr.getBasePointer(), LayoutTy, DstPtr.getBasePointer(),
1806 DstPtr.getElementType());
1807 return true;
1808 }
1809};
1810} // namespace
1811
1813 Address SrcPtr, QualType CType) {
1814 return HLSLBufferCopyEmitter(CGF, DstPtr, SrcPtr).emitCopy(CType);
1815}
1816
1818 const MemberExpr *E) {
1819 LValue Base =
1821 auto *Field = dyn_cast<FieldDecl>(E->getMemberDecl());
1822 assert(Field && "Unexpected access into HLSL buffer");
1823
1824 const RecordDecl *Rec = Field->getParent();
1825
1826 // Work out the buffer layout type to index into.
1827 QualType RecType = CGM.getContext().getCanonicalTagType(Rec);
1828 assert(RecType->isStructureOrClassType() && "Invalid type in HLSL buffer");
1829 // Since this is a member of an object in the buffer and not the buffer's
1830 // struct/class itself, we shouldn't have any offsets on the members we need
1831 // to contend with.
1832 CGHLSLOffsetInfo EmptyOffsets;
1833 llvm::StructType *LayoutTy = HLSLBufferLayoutBuilder(CGM).layOutStruct(
1834 RecType->getAsCanonical<RecordType>(), EmptyOffsets);
1835
1836 // Get the field index for the layout struct, accounting for padding.
1837 unsigned FieldIdx =
1838 CGM.getTypes().getCGRecordLayout(Rec).getLLVMFieldNo(Field);
1839 assert(FieldIdx < LayoutTy->getNumElements() &&
1840 "Layout struct is smaller than member struct");
1841 unsigned Skipped = 0;
1842 for (unsigned I = 0; I <= FieldIdx;) {
1843 llvm::Type *ElementTy = LayoutTy->getElementType(I + Skipped);
1844 if (CGF.CGM.getTargetCodeGenInfo().isHLSLPadding(ElementTy))
1845 ++Skipped;
1846 else
1847 ++I;
1848 }
1849 FieldIdx += Skipped;
1850 assert(FieldIdx < LayoutTy->getNumElements() && "Access out of bounds");
1851
1852 // Now index into the struct, making sure that the type we return is the
1853 // buffer layout type rather than the original type in the AST.
1854 QualType FieldType = Field->getType();
1855 llvm::Type *FieldLLVMTy = CGM.getTypes().ConvertTypeForMem(FieldType);
1857 CGF.CGM.getDataLayout().getABITypeAlign(FieldLLVMTy));
1858
1859 Value *Ptr = CGF.getLangOpts().EmitLogicalPointer
1860 ? CGF.Builder.CreateStructuredGEP(
1861 LayoutTy, Base.getPointer(CGF),
1862 llvm::ConstantInt::get(CGM.IntTy, FieldIdx))
1863 : CGF.Builder.CreateStructGEP(LayoutTy, Base.getPointer(CGF),
1864 FieldIdx, Field->getName());
1865 Address Addr(Ptr, FieldLLVMTy, Align, KnownNonNull);
1866
1867 LValue LV = LValue::MakeAddr(Addr, FieldType, CGM.getContext(),
1869 CGM.getTBAAAccessInfo(FieldType));
1870 LV.getQuals().addCVRQualifiers(Base.getVRQualifiers());
1871
1872 return LV;
1873}
Defines the clang::ASTContext interface.
static llvm::Value * createSPIRVBuiltinLoad(IRBuilder<> &B, llvm::Module &M, llvm::Type *Ty, const Twine &Name, unsigned BuiltInID)
static void addSPIRVBuiltinDecoration(llvm::GlobalVariable *GV, unsigned BuiltIn)
static void createSPIRVLocationStore(IRBuilder<> &B, llvm::Module &M, llvm::Value *Source, unsigned Location, StringRef Name)
static void gatherFunctions(SmallVectorImpl< Function * > &Fns, llvm::Module &M, bool CtorOrDtor)
static void addLocationDecoration(llvm::GlobalVariable *GV, unsigned Location)
static llvm::Value * createSPIRVLocationLoad(IRBuilder<> &B, llvm::Module &M, llvm::Type *Ty, unsigned Location, StringRef Name)
static Value * buildVectorInput(IRBuilder<> &B, Function *F, llvm::Type *Ty)
static void initializeBuffer(CodeGenModule &CGM, llvm::GlobalVariable *GV, Intrinsic::ID IntrID, ArrayRef< llvm::Value * > Args)
static const clang::HLSLAttributedResourceType * createBufferHandleType(const HLSLBufferDecl *BufDecl)
static void createSPIRVBuiltinStore(IRBuilder<> &B, llvm::Module &M, llvm::Value *Source, const Twine &Name, unsigned BuiltInID)
Result
Implement __builtin_bit_cast and related operations.
llvm::MachO::Record Record
Definition MachO.h:31
Defines the clang::TargetOptions class.
C Language Family Type Representation.
bool VisitHLSLOutArgExpr(HLSLOutArgExpr *)
llvm::SmallVector< OpaqueValueExpr *, 8 > OVEs
bool VisitOpaqueValueExpr(OpaqueValueExpr *E)
llvm::SmallPtrSet< OpaqueValueExpr *, 8 > Visited
Holds long-lived AST nodes (such as types and decls) that can be referred to throughout the semantic ...
Definition ASTContext.h:223
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:3796
Attr - This represents one attribute.
Definition Attr.h:46
Represents a static or instance method of a struct/union/class.
Definition DeclCXX.h:2132
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
llvm::Type * getElementType() const
Return the type of the values stored in this address.
Definition Address.h:209
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
llvm::Value * CreateAccessChain(bool Logical, llvm::Type *BaseType, llvm::Value *PtrBase, ArrayRef< llvm::Value * > IdxList, const Twine &Name="")
Definition CGBuilder.h:366
Abstract information about a function or function prototype.
Definition CGCall.h:42
All available information about a concrete callee.
Definition CGCall.h:64
CGFunctionInfo - Class to encapsulate the information about a function definition.
static const uint32_t Unspecified
static bool compareOffsets(uint32_t LHS, uint32_t RHS)
Comparison function for offsets received from operator[] suitable for use in a stable_sort.
static CGHLSLOffsetInfo fromDecl(const HLSLBufferDecl &BufDecl)
Iterates over all declarations in the HLSL buffer and based on the packoffset or register(c#) annotat...
llvm::Instruction * getConvergenceToken(llvm::BasicBlock &BB)
void setHLSLEntryAttributes(const FunctionDecl *FD, llvm::Function *Fn)
specific_attr_iterator< HLSLAppliedSemanticAttr > handleSemanticStore(llvm::IRBuilder<> &B, const FunctionDecl *FD, llvm::Value *Source, const clang::DeclaratorDecl *Decl, specific_attr_iterator< HLSLAppliedSemanticAttr > AttrBegin, specific_attr_iterator< HLSLAppliedSemanticAttr > AttrEnd)
llvm::StructType * getHLSLBufferLayoutType(const RecordType *LayoutStructTy)
void emitEntryFunction(const FunctionDecl *FD, llvm::Function *Fn)
void handleGlobalVarDefinition(const VarDecl *VD, llvm::GlobalVariable *Var)
void emitSystemSemanticStore(llvm::IRBuilder<> &B, llvm::Value *Source, const clang::DeclaratorDecl *Decl, HLSLAppliedSemanticAttr *Semantic, std::optional< unsigned > Index)
std::pair< llvm::Value *, specific_attr_iterator< HLSLAppliedSemanticAttr > > handleStructSemanticLoad(llvm::IRBuilder<> &B, const FunctionDecl *FD, llvm::Type *Type, const clang::DeclaratorDecl *Decl, specific_attr_iterator< HLSLAppliedSemanticAttr > begin, specific_attr_iterator< HLSLAppliedSemanticAttr > end)
std::optional< LValue > emitResourceMemberExpr(CodeGenFunction &CGF, const MemberExpr *E)
specific_attr_iterator< HLSLAppliedSemanticAttr > handleStructSemanticStore(llvm::IRBuilder<> &B, const FunctionDecl *FD, llvm::Value *Source, const clang::DeclaratorDecl *Decl, specific_attr_iterator< HLSLAppliedSemanticAttr > AttrBegin, specific_attr_iterator< HLSLAppliedSemanticAttr > AttrEnd)
llvm::Value * handleScalarSemanticLoad(llvm::IRBuilder<> &B, const FunctionDecl *FD, llvm::Type *Type, const clang::DeclaratorDecl *Decl, HLSLAppliedSemanticAttr *Semantic)
void addHLSLBufferLayoutType(const RecordType *LayoutStructTy, llvm::StructType *LayoutTy)
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)
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)
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)
std::optional< LValue > emitGlobalResourceArrayAsLValue(CodeGenFunction &CGF, const VarDecl *ArrayDecl, SourceLocation Loc)
void addBuffer(const HLSLBufferDecl *D)
bool emitGlobalResourceArray(CodeGenFunction &CGF, const Expr *E, AggValueSlot &DestSlot)
void emitInitListOpaqueValues(CodeGenFunction &CGF, InitListExpr *E)
CallArgList - Type for representing both the value and type of arguments in a call.
Definition CGCall.h:275
void add(RValue rvalue, QualType type)
Definition CGCall.h:303
A non-RAII class containing all the information about a bound opaque value.
CodeGenFunction - This class organizes the per-function state that is used while generating LLVM code...
const LangOptions & getLangOpts() const
@ TCK_MemberAccess
Checking the object expression in a non-static data member access.
void pushFullExprCleanup(CleanupKind kind, As... A)
pushFullExprCleanup - Push a cleanup to be run at the end of the current full-expression.
AggValueSlot CreateAggTemp(QualType T, const Twine &Name="tmp", RawAddress *Alloca=nullptr)
CreateAggTemp - Create a temporary memory object for the given aggregate type.
bool EmitLifetimeStart(llvm::Value *Addr)
Emit a lifetime.begin marker if some criteria are satisfied.
Definition CGDecl.cpp:1357
RValue EmitCall(const CGFunctionInfo &CallInfo, const CGCallee &Callee, ReturnValueSlot ReturnValue, const CallArgList &Args, llvm::CallBase **CallOrInvoke, bool IsMustTail, SourceLocation Loc, bool IsVirtualFunctionPointerThunk=false)
EmitCall - Generate a call of the given function, expecting the given result type,...
Definition CGCall.cpp:5451
RawAddress CreateMemTempWithoutCast(QualType T, const Twine &Name="tmp")
CreateMemTemp - Create a temporary memory object of the given type, with appropriate alignmen without...
Definition CGExpr.cpp:231
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:280
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:1598
LValue EmitCheckedLValue(const Expr *E, TypeCheckKind TCK)
Same as EmitLValue but additionally we generate checking code to guard against undefined behavior.
Definition CGExpr.cpp:1679
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:1714
bool isOpaqueValueEmitted(const OpaqueValueExpr *E)
isOpaqueValueEmitted - Return true if the opaque value expression has already been emitted.
Definition CGExpr.cpp:6419
llvm::LLVMContext & getLLVMContext()
This class organizes the cross-function state that is used while generating LLVM code.
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 TargetInfo & getTarget() const
void EmitGlobal(GlobalDecl D)
Emit code for a single global function or var decl.
const llvm::DataLayout & getDataLayout() const
ASTContext & getContext() const
const TargetCodeGenInfo & getTargetCodeGenInfo()
llvm::LLVMContext & getLLVMContext()
void EmitTopLevelDecl(Decl *D)
Emit code for a single top level declaration.
ConstantAddress GetAddrOfConstantCString(const std::string &Str, StringRef GlobalName=".str")
Returns a pointer to a character array containing the literal and a terminating '\0' character.
llvm::Type * ConvertTypeForMem(QualType T)
ConvertTypeForMem - Convert type T into a llvm::Type.
const CGFunctionInfo & arrangeFreeFunctionCall(const CallArgList &Args, const FunctionType *Ty, bool ChainCall)
Figure out the rules for calling a function with the given formal type using the given arguments.
Definition CGCall.cpp:707
llvm::Constant * getPointer() const
Definition Address.h:308
llvm::StructType * layOutStruct(const RecordType *StructType, const CGHLSLOffsetInfo &OffsetInfo)
Lays out a struct type following HLSL buffer rules and considering any explicit offset information.
llvm::Type * layOutType(QualType Type)
Lays out a type following HLSL buffer rules.
LValue - This represents an lvalue references.
Definition CGValue.h:183
static LValue MakeAddr(Address Addr, QualType type, ASTContext &Context, LValueBaseInfo BaseInfo, TBAAAccessInfo TBAAInfo)
Definition CGValue.h:454
const Qualifiers & getQuals() const
Definition CGValue.h:350
Address getAddress() const
Definition CGValue.h:373
QualType getType() const
Definition CGValue.h:303
RValue - This trivial value class is used to represent the result of an expression that is evaluated.
Definition CGValue.h:42
static RValue get(llvm::Value *V)
Definition CGValue.h:99
An abstract representation of an aligned address.
Definition Address.h:42
llvm::Value * getPointer() const
Definition Address.h:66
ReturnValueSlot - Contains the address where the return value of a function can be stored,...
Definition CGCall.h:382
virtual bool isHLSLPadding(llvm::Type *Ty) const
Return true if this is an HLSL padding type.
Definition TargetInfo.h:443
Represents the canonical version of C arrays with a specified constant size.
Definition TypeBase.h:3822
int64_t getSExtSize() const
Return the size sign-extended as a uint64_t.
Definition TypeBase.h:3904
DeclContext * getParent()
getParent - Returns the containing DeclContext.
Definition DeclBase.h:2122
Decl - This represents one declaration (or definition), e.g.
Definition DeclBase.h:86
T * getAttr() const
Definition DeclBase.h:581
bool hasAttrs() const
Definition DeclBase.h:526
ASTContext & getASTContext() const LLVM_READONLY
Definition DeclBase.cpp:547
bool isImplicit() const
isImplicit - Indicates whether the declaration was implicitly generated by the implementation.
Definition DeclBase.h:601
specific_attr_iterator< T > specific_attr_end() const
Definition DeclBase.h:577
specific_attr_iterator< T > specific_attr_begin() const
Definition DeclBase.h:572
AttrVec & getAttrs()
Definition DeclBase.h:532
IdentifierInfo * getAsIdentifierInfo() const
Retrieve the IdentifierInfo * stored in this declaration name, or null if this declaration name isn't...
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:3098
std::optional< llvm::APSInt > getIntegerConstantExpr(const ASTContext &Ctx) const
isIntegerConstantExpr - Return the value if this expression is a valid integer constant expression.
Expr * IgnoreImpCasts() LLVM_READONLY
Skip past any implicit casts which might surround this expression until reaching a fixed point.
Definition Expr.cpp:3078
SourceLocation getExprLoc() const LLVM_READONLY
getExprLoc - Return the preferred location for the arrow when diagnosing a problem with a generic exp...
Definition Expr.cpp:283
QualType getType() const
Definition Expr.h:144
Represents a member of a struct/union/class.
Definition Decl.h:3166
Represents a function declaration or definition.
Definition Decl.h:2018
const ParmVarDecl * getParamDecl(unsigned i) const
Definition Decl.h:2789
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:2854
Represents a prototype with parameter type info, e.g.
Definition TypeBase.h:5369
HLSLBufferDecl - Represent a cbuffer or tbuffer declaration.
Definition Decl.h:5200
bool isCBuffer() const
Definition Decl.h:5244
const CXXRecordDecl * getLayoutStruct() const
Definition Decl.h:5247
bool hasValidPackoffset() const
Definition Decl.h:5246
buffer_decl_range buffer_decls() const
Definition Decl.h:5275
This class represents temporary values used to represent inout and out arguments in HLSL.
Definition Expr.h:7397
ArrayRef< llvm::hlsl::rootsig::RootElement > getRootElements() const
Definition Decl.h:5317
llvm::dxbc::RootSignatureVersion getVersion() const
Definition Decl.h:5315
One of these records is kept for each identifier that is lexed.
StringRef getName() const
Return the actual identifier string.
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
DeclarationNameInfo getMemberNameInfo() const
Retrieve the member declaration name info.
Definition Expr.h:3544
SourceLocation getExprLoc() const LLVM_READONLY
Definition Expr.h:3562
IdentifierInfo * getIdentifier() const
Get the identifier that names this declaration, if there is one.
Definition Decl.h:295
StringRef getName() const
Get the name of identifier for this declaration as a StringRef.
Definition Decl.h:301
OpaqueValueExpr - An expression referring to an opaque object of a fixed type and value class.
Definition Expr.h: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:1808
A (possibly-)qualified type.
Definition TypeBase.h:937
const Type * getTypePtr() const
Retrieves a pointer to the underlying (unqualified) type.
Definition TypeBase.h:8440
LangAS getAddressSpace() const
Return the address space of this type.
Definition TypeBase.h:8566
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:4331
unsigned getNumFields() const
Returns the number of fields (non-static data members) in this record.
Definition Decl.h:4547
field_iterator field_begin() const
Definition Decl.cpp:5296
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.
const llvm::Triple & getTriple() const
Returns the target triple of the primary target.
Token - This structure provides full information about a lexed token.
Definition Token.h:36
The base class of the type hierarchy.
Definition TypeBase.h:1875
bool isIncompleteArrayType() const
Definition TypeBase.h:8784
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:8776
bool isConstantMatrixType() const
Definition TypeBase.h:8844
bool isHLSLResourceRecord() const
Definition Type.cpp:5507
bool isStructureOrClassType() const
Definition Type.cpp:744
const T * getAsCanonical() const
If this type is canonically the specified type, return its canonical type cast to that specified type...
Definition TypeBase.h:2983
const T * getAs() const
Member-template getAs<specific type>'.
Definition TypeBase.h:9270
const Type * getUnqualifiedDesugaredType() const
Return the specified type with any "sugar" removed from the type, removing any typedefs,...
Definition Type.cpp:691
bool isHLSLResourceRecordArray() const
Definition Type.cpp:5511
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:924
bool hasGlobalStorage() const
Returns true for all variables that do not have local storage.
Definition Decl.h:1239
StorageClass getStorageClass() const
Returns the storage class as written in the source.
Definition Decl.h:1166
void pushBaseNameHierarchy(CXXRecordDecl *DerivedRD, CXXRecordDecl *BaseRD)
IdentifierInfo * getNameAsIdentifier(ASTContext &AST) const
specific_attr_iterator - Iterates over a subrange of an AttrVec, only providing attributes that are o...
@ Type
The l-value was considered opaque, so the alignment was determined from a type.
Definition CGValue.h:155
@ Decl
The l-value was an access to a declared entity or something equivalently strong, like the address of ...
Definition CGValue.h:146
bool hasCounterHandle(const CXXRecordDecl *RD)
@ Address
A pointer to a ValueDecl.
Definition Primitives.h:28
bool Load(InterpState &S, CodePtr OpPC)
Definition Interp.h:2183
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:252
@ SC_Static
Definition Specifiers.h:256
@ SC_None
Definition Specifiers.h:254
@ Result
The result type of a method or function.
Definition TypeBase.h:905
U cast(CodeGen::Address addr)
Definition Address.h:327
Diagnostic wrappers for TextAPI types for error reporting.
Definition Dominators.h:30
__packed_splat4 __packed_splat2 __packed_splat8 __packed_splat4 __packed_splat2 __packed_splat4 __packed_splat2 __packed_splat8 __packed_splat4 uint32_t
DeclarationName getName() const
getName - Returns the embedded declaration name.
unsigned getCounterImplicitOrderID() const