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.CreateMemTemp(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 *MemTy = CGF.ConvertTypeForMem(MatQualTy);
1545 llvm::Type *LayoutTy = HLSLBufferLayoutBuilder(CGF.CGM).layOutType(MatQualTy);
1546
1547 if (LayoutTy == MemTy)
1548 return LV.getAddress();
1549
1550 Address SrcAddr = LV.getAddress();
1551 // NOTE: B\C CreateMemTemp flattens MatrixTypes which causes
1552 // overlapping GEPs in emitBufferCopy. Use CreateTempAlloca with
1553 // the non-padded layout.
1554 CharUnits Align =
1555 CharUnits::fromQuantity(CGF.CGM.getDataLayout().getABITypeAlign(MemTy));
1556 RawAddress DestAlloca = CGF.CreateTempAlloca(MemTy, Align, "matrix.buf.copy");
1557 emitBufferCopy(CGF, DestAlloca, SrcAddr, MatQualTy);
1558 return DestAlloca;
1559}
1560
1562 const ArraySubscriptExpr *E, CodeGenFunction &CGF,
1563 llvm::function_ref<llvm::Value *(bool Promote)> EmitIdxAfterBase) {
1564 // Find the element type to index by first padding the element type per HLSL
1565 // buffer rules, and then padding out to a 16-byte register boundary if
1566 // necessary.
1567 llvm::Type *LayoutTy =
1569 uint64_t LayoutSizeInBits =
1570 CGM.getDataLayout().getTypeSizeInBits(LayoutTy).getFixedValue();
1571 CharUnits ElementSize = CharUnits::fromQuantity(LayoutSizeInBits / 8);
1572 CharUnits RowAlignedSize = ElementSize.alignTo(CharUnits::fromQuantity(16));
1573 if (RowAlignedSize > ElementSize) {
1574 llvm::Type *Padding = CGM.getTargetCodeGenInfo().getHLSLPadding(
1575 CGM, RowAlignedSize - ElementSize);
1576 assert(Padding && "No padding type for target?");
1577 LayoutTy = llvm::StructType::get(CGF.getLLVMContext(), {LayoutTy, Padding},
1578 /*isPacked=*/true);
1579 }
1580
1581 // If the layout type doesn't introduce any padding, we don't need to do
1582 // anything special.
1583 llvm::Type *OrigTy = CGF.CGM.getTypes().ConvertTypeForMem(E->getType());
1584 if (LayoutTy == OrigTy)
1585 return std::nullopt;
1586
1587 LValueBaseInfo EltBaseInfo;
1588 TBAAAccessInfo EltTBAAInfo;
1589
1590 // Index into the object as-if we have an array of the padded element type,
1591 // and then dereference the element itself to avoid reading padding that may
1592 // be past the end of the in-memory object.
1594 llvm::Value *Idx = EmitIdxAfterBase(/*Promote*/ true);
1595 Indices.push_back(Idx);
1596 Indices.push_back(llvm::ConstantInt::get(CGF.Int32Ty, 0));
1597
1598 if (CGF.getLangOpts().EmitLogicalPointer) {
1599 // The fact that we emit an array-to-pointer decay might be an oversight,
1600 // but for now, we simply ignore it (see #179951).
1601 const CastExpr *CE = cast<CastExpr>(E->getBase());
1602 assert(CE->getCastKind() == CastKind::CK_ArrayToPointerDecay);
1603
1604 LValue LV = CGF.EmitLValue(CE->getSubExpr());
1605 Address Addr = LV.getAddress();
1606 LayoutTy = llvm::ArrayType::get(
1607 LayoutTy,
1608 cast<llvm::ArrayType>(Addr.getElementType())->getNumElements());
1609 auto *GEP = cast<StructuredGEPInst>(CGF.Builder.CreateStructuredGEP(
1610 LayoutTy, Addr.emitRawPointer(CGF), Indices, "cbufferidx"));
1611 Addr =
1612 Address(GEP, GEP->getResultElementType(), RowAlignedSize, KnownNonNull);
1613 return CGF.MakeAddrLValue(Addr, E->getType(), EltBaseInfo, EltTBAAInfo);
1614 }
1615
1616 Address Addr =
1617 CGF.EmitPointerWithAlignment(E->getBase(), &EltBaseInfo, &EltTBAAInfo);
1618 llvm::Value *GEP = CGF.Builder.CreateGEP(LayoutTy, Addr.emitRawPointer(CGF),
1619 Indices, "cbufferidx");
1620 Addr = Address(GEP, Addr.getElementType(), RowAlignedSize, KnownNonNull);
1621 return CGF.MakeAddrLValue(Addr, E->getType(), EltBaseInfo, EltTBAAInfo);
1622}
1623
1624std::optional<LValue>
1626 const MemberExpr *ME) {
1627 assert((ME->getType()->isHLSLResourceRecord() ||
1629 "expected resource member expression");
1630
1631 const VarDecl *ResourceVD =
1632 findAssociatedResourceDeclForStruct(CGF.CGM.getContext(), ME);
1633 if (!ResourceVD)
1634 return std::nullopt;
1635
1636 // Handle member of resource array type.
1637 if (ResourceVD->getType()->isHLSLResourceRecordArray())
1638 return emitGlobalResourceArrayAsLValue(CGF, ResourceVD, ME->getExprLoc());
1639
1640 // Handle member that is an individual resource.
1641 GlobalVariable *ResGV =
1642 cast<GlobalVariable>(CGM.GetAddrOfGlobalVar(ResourceVD));
1643 const DataLayout &DL = CGM.getDataLayout();
1644 llvm::Type *Ty = ResGV->getValueType();
1645 CharUnits Align = CharUnits::fromQuantity(DL.getABITypeAlign(Ty));
1646 Address Addr = Address(ResGV, Ty, Align);
1647 LValue LV = LValue::MakeAddr(Addr, ME->getType(), CGM.getContext(),
1649 CGM.getTBAAAccessInfo(ME->getType()));
1650 return LV;
1651}
1652
1653namespace {
1654/// Utility for emitting copies following the HLSL buffer layout rules (ie,
1655/// copying out of a cbuffer).
1656class HLSLBufferCopyEmitter {
1657 CodeGenFunction &CGF;
1658 Address DstPtr;
1659 Address SrcPtr;
1660 llvm::Type *LayoutTy = nullptr;
1661
1662 SmallVector<llvm::Value *> CurStoreIndices;
1663 SmallVector<llvm::Value *> CurLoadIndices;
1664
1665 // Creates & returns either a structured.gep or a ptradd/gep depending on
1666 // langopts.
1667 llvm::Value *emitAccessChain(llvm::Type *BaseTy, llvm::Value *Base,
1668 ArrayRef<llvm::Value *> Indices) {
1669 bool EmitLogical = CGF.getLangOpts().EmitLogicalPointer;
1670 if (EmitLogical)
1671 return CGF.Builder.CreateAccessChain(EmitLogical, BaseTy, Base, Indices);
1672
1674 GEPIndices.reserve(Indices.size() + 1);
1675 GEPIndices.push_back(llvm::ConstantInt::get(CGF.IntTy, 0));
1676 GEPIndices.append(Indices.begin(), Indices.end());
1677 return CGF.Builder.CreateAccessChain(EmitLogical, BaseTy, Base, GEPIndices);
1678 }
1679
1680 bool isBufferLayoutArray(llvm::StructType *ST) {
1681 // A buffer layout array is a struct with two elements: the padded array,
1682 // and the last element. That is, is should look something like this:
1683 //
1684 // { [%n x { %type, %padding }], %type }
1685 //
1686 if (!ST || ST->getNumElements() != 2)
1687 return false;
1688
1689 auto *PaddedEltsTy = dyn_cast<llvm::ArrayType>(ST->getElementType(0));
1690 if (!PaddedEltsTy)
1691 return false;
1692
1693 auto *PaddedTy = dyn_cast<llvm::StructType>(PaddedEltsTy->getElementType());
1694 if (!PaddedTy || PaddedTy->getNumElements() != 2)
1695 return false;
1696
1698 PaddedTy->getElementType(1)))
1699 return false;
1700
1701 llvm::Type *ElementTy = ST->getElementType(1);
1702 if (PaddedTy->getElementType(0) != ElementTy)
1703 return false;
1704 return true;
1705 }
1706
1707 void emitBufferLayoutCopy(Value *Src, llvm::StructType *SrcTy, Value *Dst,
1708 llvm::ArrayType *DstTy) {
1709 // Those assumptions are checked by isBufferLayoutArray.
1710 auto *SrcPaddedArrayTy = cast<llvm::ArrayType>(SrcTy->getElementType(0));
1711 assert(SrcPaddedArrayTy->getNumElements() + 1 == DstTy->getNumElements());
1712 assert(cast<llvm::StructType>(SrcPaddedArrayTy->getElementType())
1713 ->getElementType(0) == SrcTy->getElementType(1));
1714
1715 auto *SrcDataTy = SrcTy->getElementType(1);
1716 auto Zero = llvm::ConstantInt::get(CGF.IntTy, 0);
1717
1718 for (unsigned I = 0; I < SrcPaddedArrayTy->getNumElements(); ++I) {
1719 auto Index = llvm::ConstantInt::get(CGF.IntTy, I);
1720 auto *SrcElt = emitAccessChain(SrcTy, Src, {Zero, Index, Zero});
1721 auto *DstElt = emitAccessChain(DstTy, Dst, {Index});
1722 emitElementCopy(SrcElt, SrcDataTy, DstElt, DstTy->getElementType());
1723 }
1724
1725 auto *SrcElt =
1726 emitAccessChain(SrcTy, Src, {llvm::ConstantInt::get(CGF.IntTy, 1)});
1727 auto *DstElt = emitAccessChain(
1728 DstTy, Dst,
1729 {llvm::ConstantInt::get(CGF.IntTy, DstTy->getNumElements() - 1)});
1730 emitElementCopy(SrcElt, SrcDataTy, DstElt, DstTy->getElementType());
1731 }
1732
1733 void emitCopy(Value *Src, llvm::StructType *SrcTy, Value *Dst,
1734 llvm::Type *DstTy) {
1735 if (isBufferLayoutArray(SrcTy))
1736 return emitBufferLayoutCopy(Src, SrcTy, Dst,
1737 cast<llvm::ArrayType>(DstTy));
1738
1739 unsigned SrcIndex = 0;
1740 unsigned DstIndex = 0;
1741
1742 auto *DstST = cast<llvm::StructType>(DstTy);
1743 while (SrcIndex < SrcTy->getNumElements() &&
1744 DstIndex < DstST->getNumElements()) {
1746 SrcTy->getElementType(SrcIndex))) {
1747 SrcIndex += 1;
1748 continue;
1749 }
1750
1752 DstST->getElementType(DstIndex))) {
1753 DstIndex += 1;
1754 continue;
1755 }
1756
1757 auto *SrcElt = emitAccessChain(
1758 SrcTy, Src, {llvm::ConstantInt::get(CGF.IntTy, SrcIndex)});
1759 auto *DstElt = emitAccessChain(
1760 DstTy, Dst, {llvm::ConstantInt::get(CGF.IntTy, DstIndex)});
1761 emitElementCopy(SrcElt, SrcTy->getElementType(SrcIndex), DstElt,
1762 DstST->getElementType(DstIndex));
1763 DstIndex += 1;
1764 SrcIndex += 1;
1765 }
1766 }
1767
1768 void emitCopy(Value *Src, llvm::ArrayType *SrcTy, Value *Dst,
1769 llvm::Type *DstTy) {
1770 for (unsigned I = 0, E = SrcTy->getNumElements(); I < E; ++I) {
1771 auto *SrcElt =
1772 emitAccessChain(SrcTy, Src, {llvm::ConstantInt::get(CGF.IntTy, I)});
1773 auto *DstElt =
1774 emitAccessChain(DstTy, Dst, {llvm::ConstantInt::get(CGF.IntTy, I)});
1775 emitElementCopy(SrcElt, SrcTy->getElementType(), DstElt,
1776 cast<llvm::ArrayType>(DstTy)->getElementType());
1777 }
1778 }
1779
1780 void emitElementCopy(Value *Src, llvm::Type *SrcTy, Value *Dst,
1781 llvm::Type *DstTy) {
1782 if (auto *AT = dyn_cast<llvm::ArrayType>(SrcTy))
1783 return emitCopy(Src, AT, Dst, DstTy);
1784 if (auto *ST = dyn_cast<llvm::StructType>(SrcTy))
1785 return emitCopy(Src, ST, Dst, DstTy);
1786
1787 // When we have a scalar or vector element we can emit the copy.
1788 CharUnits SrcAlign =
1789 CharUnits::fromQuantity(CGF.CGM.getDataLayout().getABITypeAlign(SrcTy));
1790 CharUnits DstAlign =
1791 CharUnits::fromQuantity(CGF.CGM.getDataLayout().getABITypeAlign(DstTy));
1792 Address SrcAddr(Src, SrcTy, SrcAlign);
1793 Address DstAddr(Dst, DstTy, DstAlign);
1794 llvm::Value *Load = CGF.Builder.CreateLoad(SrcAddr, "cbuf.load");
1795 CGF.Builder.CreateStore(Load, DstAddr);
1796 }
1797
1798public:
1799 HLSLBufferCopyEmitter(CodeGenFunction &CGF, Address DstPtr, Address SrcPtr)
1800 : CGF(CGF), DstPtr(DstPtr), SrcPtr(SrcPtr) {}
1801
1802 bool emitCopy(QualType CType) {
1803 LayoutTy = HLSLBufferLayoutBuilder(CGF.CGM).layOutType(CType);
1804
1805 // TODO: We should be able to fall back to a regular memcpy if the layout
1806 // type doesn't have any padding, but that runs into issues in the backend
1807 // currently.
1808 //
1809 // See https://github.com/llvm/wg-hlsl/issues/351
1810 emitElementCopy(SrcPtr.getBasePointer(), LayoutTy, DstPtr.getBasePointer(),
1811 DstPtr.getElementType());
1812 return true;
1813 }
1814};
1815} // namespace
1816
1818 Address SrcPtr, QualType CType) {
1819 return HLSLBufferCopyEmitter(CGF, DstPtr, SrcPtr).emitCopy(CType);
1820}
1821
1823 const MemberExpr *E) {
1824 LValue Base =
1826 auto *Field = dyn_cast<FieldDecl>(E->getMemberDecl());
1827 assert(Field && "Unexpected access into HLSL buffer");
1828
1829 const RecordDecl *Rec = Field->getParent();
1830
1831 // Work out the buffer layout type to index into.
1832 QualType RecType = CGM.getContext().getCanonicalTagType(Rec);
1833 assert(RecType->isStructureOrClassType() && "Invalid type in HLSL buffer");
1834 // Since this is a member of an object in the buffer and not the buffer's
1835 // struct/class itself, we shouldn't have any offsets on the members we need
1836 // to contend with.
1837 CGHLSLOffsetInfo EmptyOffsets;
1838 llvm::StructType *LayoutTy = HLSLBufferLayoutBuilder(CGM).layOutStruct(
1839 RecType->getAsCanonical<RecordType>(), EmptyOffsets);
1840
1841 // Get the field index for the layout struct, accounting for padding.
1842 unsigned FieldIdx =
1843 CGM.getTypes().getCGRecordLayout(Rec).getLLVMFieldNo(Field);
1844 assert(FieldIdx < LayoutTy->getNumElements() &&
1845 "Layout struct is smaller than member struct");
1846 unsigned Skipped = 0;
1847 for (unsigned I = 0; I <= FieldIdx;) {
1848 llvm::Type *ElementTy = LayoutTy->getElementType(I + Skipped);
1849 if (CGF.CGM.getTargetCodeGenInfo().isHLSLPadding(ElementTy))
1850 ++Skipped;
1851 else
1852 ++I;
1853 }
1854 FieldIdx += Skipped;
1855 assert(FieldIdx < LayoutTy->getNumElements() && "Access out of bounds");
1856
1857 // Now index into the struct, making sure that the type we return is the
1858 // buffer layout type rather than the original type in the AST.
1859 QualType FieldType = Field->getType();
1860 llvm::Type *FieldLLVMTy = CGM.getTypes().ConvertTypeForMem(FieldType);
1862 CGF.CGM.getDataLayout().getABITypeAlign(FieldLLVMTy));
1863
1864 Value *Ptr = CGF.getLangOpts().EmitLogicalPointer
1865 ? CGF.Builder.CreateStructuredGEP(
1866 LayoutTy, Base.getPointer(CGF),
1867 llvm::ConstantInt::get(CGM.IntTy, FieldIdx))
1868 : CGF.Builder.CreateStructGEP(LayoutTy, Base.getPointer(CGF),
1869 FieldIdx, Field->getName());
1870 Address Addr(Ptr, FieldLLVMTy, Align, KnownNonNull);
1871
1872 LValue LV = LValue::MakeAddr(Addr, FieldType, CGM.getContext(),
1874 CGM.getTBAAAccessInfo(FieldType));
1875 LV.getQuals().addCVRQualifiers(Base.getVRQualifiers());
1876
1877 return LV;
1878}
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:229
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
llvm::AllocaInst * CreateTempAlloca(llvm::Type *Ty, const Twine &Name="tmp", llvm::Value *ArraySize=nullptr)
CreateTempAlloca - This creates an alloca and inserts it into the entry block if ArraySize is nullptr...
Definition CGExpr.cpp:158
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:5448
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:279
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:1597
LValue EmitCheckedLValue(const Expr *E, TypeCheckKind TCK)
Same as EmitLValue but additionally we generate checking code to guard against undefined behavior.
Definition CGExpr.cpp:1678
RawAddress CreateMemTemp(QualType T, const Twine &Name="tmp", RawAddress *Alloca=nullptr)
CreateMemTemp - Create a temporary memory object of the given type, with appropriate alignmen and cas...
Definition CGExpr.cpp:194
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:1713
bool isOpaqueValueEmitted(const OpaqueValueExpr *E)
isOpaqueValueEmitted - Return true if the opaque value expression has already been emitted.
Definition CGExpr.cpp:6421
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:3097
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:3077
SourceLocation getExprLoc() const LLVM_READONLY
getExprLoc - Return the preferred location for the arrow when diagnosing a problem with a generic exp...
Definition Expr.cpp:282
QualType getType() const
Definition Expr.h:144
Represents a member of a struct/union/class.
Definition Decl.h:3182
Represents a function declaration or definition.
Definition Decl.h:2018
const ParmVarDecl * getParamDecl(unsigned i) const
Definition Decl.h:2815
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:2880
Represents a prototype with parameter type info, e.g.
Definition TypeBase.h:5369
HLSLBufferDecl - Represent a cbuffer or tbuffer declaration.
Definition Decl.h:5216
bool isCBuffer() const
Definition Decl.h:5260
const CXXRecordDecl * getLayoutStruct() const
Definition Decl.h:5263
bool hasValidPackoffset() const
Definition Decl.h:5262
buffer_decl_range buffer_decls() const
Definition Decl.h:5291
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:5333
llvm::dxbc::RootSignatureVersion getVersion() const
Definition Decl.h:5331
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:8445
LangAS getAddressSpace() const
Return the address space of this type.
Definition TypeBase.h:8571
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:4347
unsigned getNumFields() const
Returns the number of fields (non-static data members) in this record.
Definition Decl.h:4563
field_iterator field_begin() const
Definition Decl.cpp:5269
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:8789
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:8781
bool isConstantMatrixType() const
Definition TypeBase.h:8849
bool isHLSLResourceRecord() const
Definition Type.cpp:5496
bool isStructureOrClassType() const
Definition Type.cpp:743
const T * getAsCanonical() const
If this type is canonically the specified type, return its canonical type cast to that specified type...
Definition TypeBase.h:2983
const T * getAs() const
Member-template getAs<specific type>'.
Definition TypeBase.h:9275
const Type * getUnqualifiedDesugaredType() const
Return the specified type with any "sugar" removed from the type, removing any typedefs,...
Definition Type.cpp:690
bool isHLSLResourceRecordArray() const
Definition Type.cpp:5500
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:2157
The JSON file list parser is used to communicate input to InstallAPI.
bool isa(CodeGen::Address addr)
Definition Address.h:330
nullptr
This class represents a compute construct, representing a 'Kind' of ‘parallel’, 'serial',...
StorageClass
Storage classes.
Definition Specifiers.h:249
@ SC_Static
Definition Specifiers.h:253
@ SC_None
Definition Specifiers.h:251
@ Result
The result type of a method or function.
Definition TypeBase.h:905
U cast(CodeGen::Address addr)
Definition Address.h:327
Diagnostic wrappers for TextAPI types for error reporting.
Definition Dominators.h:30
DeclarationName getName() const
getName - Returns the embedded declaration name.
unsigned getCounterImplicitOrderID() const