clang 24.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"
33#include "llvm/ADT/DenseMap.h"
34#include "llvm/ADT/Enum.h"
35#include "llvm/ADT/STLExtras.h"
36#include "llvm/ADT/ScopeExit.h"
37#include "llvm/ADT/SmallString.h"
38#include "llvm/ADT/SmallVector.h"
39#include "llvm/Frontend/HLSL/HLSLResource.h"
40#include "llvm/Frontend/HLSL/RootSignatureMetadata.h"
41#include "llvm/Frontend/HLSL/SemanticSignaturePacking.h"
42#include "llvm/IR/Constants.h"
43#include "llvm/IR/DerivedTypes.h"
44#include "llvm/IR/GlobalVariable.h"
45#include "llvm/IR/IntrinsicInst.h"
46#include "llvm/IR/LLVMContext.h"
47#include "llvm/IR/Metadata.h"
48#include "llvm/IR/Module.h"
49#include "llvm/IR/Type.h"
50#include "llvm/IR/Value.h"
51#include "llvm/Support/Alignment.h"
52#include "llvm/Support/ErrorHandling.h"
53#include "llvm/Support/FormatVariadic.h"
54#include "llvm/Support/Path.h"
55#include "llvm/Transforms/Utils/ModuleUtils.h"
56#include <array>
57#include <cstdint>
58#include <optional>
59
60using namespace clang;
61using namespace CodeGen;
62using namespace clang::hlsl;
63using namespace llvm;
64
65using llvm::hlsl::CBufferRowSizeInBytes;
66
67namespace {
68
69void addDxilValVersion(StringRef ValVersionStr, llvm::Module &M) {
70 // The validation of ValVersionStr is done at HLSLToolChain::TranslateArgs.
71 // Assume ValVersionStr is legal here.
72 VersionTuple Version;
73 if (Version.tryParse(ValVersionStr) || Version.getBuild() ||
74 Version.getSubminor() || !Version.getMinor()) {
75 return;
76 }
77
78 uint64_t Major = Version.getMajor();
79 uint64_t Minor = *Version.getMinor();
80
81 auto &Ctx = M.getContext();
82 IRBuilder<> B(M);
83 MDNode *Val = MDNode::get(Ctx, {ConstantAsMetadata::get(B.getInt32(Major)),
84 ConstantAsMetadata::get(B.getInt32(Minor))});
85 StringRef DXILValKey = "dx.valver";
86 auto *DXILValMD = M.getOrInsertNamedMetadata(DXILValKey);
87 DXILValMD->addOperand(Val);
88}
89
90void addRootSignatureMD(llvm::dxbc::RootSignatureVersion RootSigVer,
92 llvm::Function *Fn, llvm::Module &M) {
93 auto &Ctx = M.getContext();
94
95 llvm::hlsl::rootsig::MetadataBuilder RSBuilder(M, Elements);
96 MDNode *RootSignature = RSBuilder.BuildRootSignature();
97
98 ConstantAsMetadata *Version = ConstantAsMetadata::get(ConstantInt::get(
99 llvm::Type::getInt32Ty(Ctx), llvm::to_underlying(RootSigVer)));
100 ValueAsMetadata *EntryFunc = Fn ? ValueAsMetadata::get(Fn) : nullptr;
101 MDNode *MDVals = MDNode::get(Ctx, {EntryFunc, RootSignature, Version});
102
103 StringRef RootSignatureValKey = "dx.rootsignatures";
104 auto *RootSignatureValMD = M.getOrInsertNamedMetadata(RootSignatureValKey);
105 RootSignatureValMD->addOperand(MDVals);
106}
107
108Expected<unsigned> packSemanticSignature(
110 llvm::Triple::EnvironmentType Stage, llvm::hlsl::IOType IOTy,
112 bool UseNative16BitTypes) {
113 using namespace llvm::hlsl;
114 // Vertex inputs and pixel outputs have fixed packing rules, independent of
115 // the packing mode used between programmable stages.
116 if (Stage == llvm::Triple::Vertex && IOTy == IOType::In)
117 return packSignatureStacked(Elements, Stage, IOTy);
118 if (Stage == llvm::Triple::Pixel && IOTy == IOType::Out)
119 return packSignatureIndexed(Elements, Stage, IOTy);
121 return packSignatureOptimized(Elements, Stage, IOTy, UseNative16BitTypes);
122 return packSignaturePrefixStable(Elements, Stage, IOTy, UseNative16BitTypes);
123}
124
125MDNode *buildSemanticSignatureMD(
126 ArrayRef<llvm::hlsl::SemanticSignatureElement> Elements, LLVMContext &Ctx) {
127 if (Elements.empty())
128 return nullptr;
129
130 SmallVector<Metadata *> ElementMD;
131 for (const llvm::hlsl::SemanticSignatureElement &Element : Elements)
132 ElementMD.push_back(Element.toMetadata(Ctx));
133 return MDNode::get(Ctx, ElementMD);
134}
135
136void addSemanticSignatureMD(
139 llvm::Function *Fn, llvm::Module &M) {
140 if (InputElements.empty() && OutputElements.empty())
141 return;
142
143 LLVMContext &Ctx = M.getContext();
144 MDNode *InputSignature = buildSemanticSignatureMD(InputElements, Ctx);
145 MDNode *OutputSignature = buildSemanticSignatureMD(OutputElements, Ctx);
146 MDNode *MDVals = MDNode::get(
147 Ctx, {ValueAsMetadata::get(Fn), InputSignature, OutputSignature});
148
149 M.getOrInsertNamedMetadata("dx.semantic.signatures")->addOperand(MDVals);
150}
151
152static void copyGlobalResource(CodeGenFunction &CGF, const VarDecl *ResourceVD,
153 AggValueSlot &DestSlot) {
154 GlobalVariable *ResGV =
156 assert(ResGV && "expected valid global variable");
157 CGF.Builder.CreateStore(ResGV, DestSlot.getAddress());
158}
159
160// Given a MemberExpr of a resource or resource array type, find the parent
161// VarDecl of the struct or class instance that contains this resource and
162// build the full resource name based on the member access path.
163//
164// For example, for a member access like "myStructArray[0].memberA",
165// this function will find the VarDecl of "myStructArray" and use the
166// EmbeddedResourceNameBuilder to build the resource name
167// "myStructArray.0.memberA".
168//
169// This also works for a record type expression that has some embedded
170// resources. It finds the parent VarDecl of that record and builds a partial
171// name which is the prefix of the resource globals associated with the
172// declaration.
173static const VarDecl *findStructResourceParentDeclAndBuildName(
174 const Expr *E, EmbeddedResourceNameBuilder &NameBuilder) {
175
177 const VarDecl *VD = nullptr;
178
179 for (;;) {
180 if (const auto *DRE = dyn_cast<DeclRefExpr>(E)) {
181 assert(isa<VarDecl>(DRE->getDecl()) &&
182 "member expr base is not a var decl");
183 VD = cast<VarDecl>(DRE->getDecl());
184 NameBuilder.pushName(VD->getName());
185 break;
186 }
187
188 WorkList.push_back(E);
189 if (const auto *MExp = dyn_cast<MemberExpr>(E))
190 E = MExp->getBase();
191 else if (const auto *ICE = dyn_cast<ImplicitCastExpr>(E))
192 E = ICE->getSubExpr();
193 else if (const auto *ASE = dyn_cast<ArraySubscriptExpr>(E))
194 E = ASE->getBase();
195 else if (isa<CXXThisExpr>(E))
196 // Resource member access on "this" pointer not yet implemented
197 // (llvm/llvm-project#190299)
198 return nullptr;
199 else
200 llvm_unreachable("unexpected expr type in resource member access");
201
202 assert(E && "expected valid expression");
203 }
204
205 while (!WorkList.empty()) {
206 E = WorkList.pop_back_val();
207 if (const auto *ME = dyn_cast<MemberExpr>(E)) {
208 NameBuilder.pushName(
209 ME->getMemberNameInfo().getName().getAsIdentifierInfo()->getName());
210 } else if (const auto *ICE = dyn_cast<ImplicitCastExpr>(E)) {
211 if (ICE->getCastKind() == CK_UncheckedDerivedToBase) {
212 CXXRecordDecl *DerivedRD =
213 ICE->getSubExpr()->getType()->getAsCXXRecordDecl();
214 CXXRecordDecl *BaseRD = ICE->getType()->getAsCXXRecordDecl();
215 NameBuilder.pushBaseNameHierarchy(DerivedRD, BaseRD);
216 }
217 } else if (const auto *ASE = dyn_cast<ArraySubscriptExpr>(E)) {
218 const Expr *IdxExpr = ASE->getIdx();
219 std::optional<llvm::APSInt> Value =
221 assert(Value &&
222 "expected constant index in struct with resource array access");
223 NameBuilder.pushArrayIndex(Value->getZExtValue());
224 } else {
225 llvm_unreachable("unexpected expr type in resource member access");
226 }
227 }
228 return VD;
229}
230
231// Given a MemberExpr of a resource or resource array type, find the
232// corresponding global resource declaration associated with the owning struct
233// or class instance via HLSLAssociatedResourceDeclAttr.
234static const VarDecl *
235findAssociatedResourceDeclForStruct(ASTContext &AST, const MemberExpr *ME) {
236
237 EmbeddedResourceNameBuilder NameBuilder;
238 const VarDecl *ParentVD =
239 findStructResourceParentDeclAndBuildName(ME, NameBuilder);
240 if (!ParentVD)
241 return nullptr;
242
243 if (!ParentVD->hasGlobalStorage())
244 return nullptr;
245
246 IdentifierInfo *II = NameBuilder.getNameAsIdentifier(AST);
247 for (const Attr *A : ParentVD->getAttrs()) {
248 if (const auto *ADA = dyn_cast<HLSLAssociatedResourceDeclAttr>(A)) {
249 VarDecl *AssocResVD = ADA->getResDecl();
250 if (AssocResVD->getIdentifier() == II)
251 return AssocResVD;
252 }
253 }
254 return nullptr;
255}
256
257void addSourceInfo(CodeGenModule &CGM, llvm::Module &M) {
258 auto &SM = CGM.getContext().getSourceManager();
259 auto &Macros = CGM.getPreprocessorOpts().Macros;
260 auto &CodeGenOpts = CGM.getCodeGenOpts();
261 auto &Ctx = M.getContext();
262
263 // Names and content of shader source code files.
264 llvm::NamedMDNode *DXContents =
265 M.getOrInsertNamedMetadata("dx.source.contents");
266 auto addFile = [&](const std::pair<StringRef, StringRef> &NameContent) {
267 llvm::MDTuple *FileInfo =
268 llvm::MDNode::get(Ctx, {llvm::MDString::get(Ctx, NameContent.first),
269 llvm::MDString::get(Ctx, NameContent.second)});
270 DXContents->addOperand(FileInfo);
271 };
272
273 bool Invalid = false;
274 const SrcMgr::SLocEntry *MainLocEntry =
275 &SM.getSLocEntry(SM.getMainFileID(), &Invalid);
276 assert(!Invalid && "Main file SLocEntry must not be invalid!");
277 const SrcMgr::ContentCache &MainCCEntry =
278 MainLocEntry->getFile().getContentCache();
279
281 std::optional<SmallString<256>> MainFileName;
282 Files.reserve(SM.local_sloc_entry_size());
283 for (unsigned I : llvm::seq(SM.local_sloc_entry_size())) {
284 const SrcMgr::SLocEntry &LocEntry = SM.getLocalSLocEntry(I);
285 if (!LocEntry.isFile())
286 continue;
287
288 const SrcMgr::FileInfo &FInfo = LocEntry.getFile();
289 if (isSystem(FInfo.getFileCharacteristic()))
290 continue;
291
292 const SrcMgr::ContentCache &CCEntry = FInfo.getContentCache();
293 OptionalFileEntryRef FEntry = CCEntry.OrigEntry;
294 if (!FEntry)
295 continue;
296
297 llvm::SmallString<256> Path = FEntry->getName();
298 llvm::sys::path::native(Path);
299 std::optional<llvm::MemoryBufferRef> Buffer = CCEntry.getBufferOrNone(
300 SM.getDiagnostics(), SM.getFileManager(), SourceLocation());
301 if (!Buffer) {
302 SM.getDiagnostics().Report(diag::warn_hlsl_failed_to_embed_source)
303 << Path;
304 continue;
305 }
306
307 if (&MainCCEntry != &CCEntry) {
308 Files.emplace_back(Path, Buffer->getBuffer());
309 } else {
310 // Main file should be at first position.
311 addFile(std::make_pair(Path, Buffer->getBuffer()));
312 MainFileName.emplace(Path);
313 }
314 }
315 assert(MainFileName && "Main file not found.");
316
317 // Files other that main one should be sorted by name.
318 llvm::sort(Files);
319#ifndef NDEBUG
320 for (unsigned I = 1; I < Files.size(); ++I)
321 assert((Files[I - 1].first != Files[I].first) &&
322 "duplicate files in dx.source.contents");
323#endif
324 llvm::for_each(Files, addFile);
325
327 Defines.reserve(Macros.size());
328 for (const auto &Macro : Macros) {
329 // Ignore undefs.
330 if (!Macro.second)
331 Defines.emplace_back(llvm::MDString::get(Ctx, Macro.first));
332 }
333 M.getOrInsertNamedMetadata("dx.source.defines")
334 ->addOperand(llvm::MDNode::get(Ctx, Defines));
335
336 if (!CodeGenOpts.MainFileName.empty())
337 llvm::sys::path::native(CodeGenOpts.MainFileName, *MainFileName);
338 M.getOrInsertNamedMetadata("dx.source.mainFileName")
339 ->addOperand(
340 llvm::MDNode::get(Ctx, llvm::MDString::get(Ctx, *MainFileName)));
341
343 Args.reserve(CodeGenOpts.HLSLParsedCommandLine.size());
344 if (!CodeGenOpts.HLSLParsedCommandLine.empty())
345 for (const auto &Arg : llvm::drop_begin(CodeGenOpts.HLSLParsedCommandLine))
346 Args.push_back(llvm::MDString::get(Ctx, Arg));
347 M.getOrInsertNamedMetadata("dx.source.args")
348 ->addOperand(llvm::MDNode::get(Ctx, Args));
349}
350
351// Find array variable declaration from DeclRef expression
352static const ValueDecl *getArrayDecl(ASTContext &AST, const Expr *E) {
353 E = E->IgnoreImpCasts();
354 if (const auto *DRE = dyn_cast_or_null<DeclRefExpr>(E))
355 return DRE->getDecl();
356 if (auto *OVE = dyn_cast<OpaqueValueExpr>(E))
357 E = OVE->getSourceExpr()->IgnoreImpCasts();
358 if (isa<MemberExpr>(E))
359 return findAssociatedResourceDeclForStruct(AST, cast<MemberExpr>(E));
360 return nullptr;
361}
362
363// Find array variable declaration from nested array subscript AST nodes
364static const ValueDecl *getArrayDecl(ASTContext &AST,
365 const ArraySubscriptExpr *ASE) {
366 const Expr *E = nullptr;
367 while (ASE != nullptr) {
368 E = ASE->getBase()->IgnoreImpCasts();
369 if (!E)
370 return nullptr;
371 ASE = dyn_cast<ArraySubscriptExpr>(E);
372 }
373 return getArrayDecl(AST, E);
374}
375
376// Get the total size of the array, or 0 if the array is unbounded.
377static int getTotalArraySize(ASTContext &AST, const clang::Type *Ty) {
379 assert(Ty->isArrayType() && "expected array type");
380 if (Ty->isIncompleteArrayType())
381 return 0;
383}
384
385static Value *buildNameForResource(llvm::StringRef BaseName,
386 CodeGenModule &CGM) {
387 llvm::SmallString<64> GlobalName = {BaseName, ".str"};
388 return CGM.GetAddrOfConstantCString(BaseName.str(), GlobalName.c_str())
389 .getPointer();
390}
391
392static CXXMethodDecl *lookupMethod(CXXRecordDecl *Record, StringRef Name,
393 StorageClass SC = SC_None) {
394 for (auto *Method : Record->methods()) {
395 if (Method->getStorageClass() == SC && Method->getName() == Name)
396 return Method;
397 }
398 return nullptr;
399}
400
401static CXXMethodDecl *lookupResourceInitMethodAndSetupArgs(
402 CodeGenModule &CGM, CXXRecordDecl *ResourceDecl, llvm::Value *Range,
403 llvm::Value *Index, StringRef Name, ResourceBindingAttrs &Binding,
404 CallArgList &Args) {
405 assert(Binding.hasBinding() && "at least one binding attribute expected");
406
407 ASTContext &AST = CGM.getContext();
408 CXXMethodDecl *CreateMethod = nullptr;
409 Value *NameStr = buildNameForResource(Name, CGM);
410 Value *Space = llvm::ConstantInt::get(CGM.IntTy, Binding.getSpace());
411
412 bool HasCounter = hasCounterHandle(ResourceDecl);
413 assert((!HasCounter || Binding.hasCounterImplicitOrderID()) &&
414 "resources with counter handle must have a binding with counter "
415 "implicit order ID");
416 if (Binding.isExplicit()) {
417 // explicit binding
418 auto *RegSlot = llvm::ConstantInt::get(CGM.IntTy, Binding.getSlot());
419 Args.add(RValue::get(RegSlot), AST.UnsignedIntTy);
420 const char *Name = Binding.hasCounterImplicitOrderID()
421 ? "__createFromBindingWithImplicitCounter"
422 : "__createFromBinding";
423 CreateMethod = lookupMethod(ResourceDecl, Name, SC_Static);
424 } else {
425 // implicit binding
426 auto *OrderID =
427 llvm::ConstantInt::get(CGM.IntTy, Binding.getImplicitOrderID());
428 Args.add(RValue::get(OrderID), AST.UnsignedIntTy);
429 const char *Name = Binding.hasCounterImplicitOrderID()
430 ? "__createFromImplicitBindingWithImplicitCounter"
431 : "__createFromImplicitBinding";
432 CreateMethod = lookupMethod(ResourceDecl, Name, SC_Static);
433 }
434 Args.add(RValue::get(Space), AST.UnsignedIntTy);
435 Args.add(RValue::get(Range), AST.IntTy);
436 Args.add(RValue::get(Index), AST.UnsignedIntTy);
437 Args.add(RValue::get(NameStr), AST.getPointerType(AST.CharTy.withConst()));
438 if (HasCounter) {
439 uint32_t CounterBinding = Binding.getCounterImplicitOrderID();
440 auto *CounterOrderID = llvm::ConstantInt::get(CGM.IntTy, CounterBinding);
441 Args.add(RValue::get(CounterOrderID), AST.UnsignedIntTy);
442 }
443
444 return CreateMethod;
445}
446
447static void callResourceInitMethod(CodeGenFunction &CGF,
448 CXXMethodDecl *CreateMethod,
449 CallArgList &Args, Address ReturnAddress) {
450 llvm::Constant *CalleeFn = CGF.CGM.GetAddrOfFunction(CreateMethod);
451 const FunctionProtoType *Proto =
452 CreateMethod->getType()->getAs<FunctionProtoType>();
453 // HLSL code generation is restricted to DXIL and SPIR-V targets, so no
454 // caller declaration is needed for x86 SysV ABI selection.
456 Args, Proto, false, /*ABIInfoFD=*/nullptr);
457 ReturnValueSlot ReturnValue(ReturnAddress, false);
458 CGCallee Callee(CGCalleeInfo(Proto), CalleeFn);
459 CGF.EmitCall(FnInfo, Callee, ReturnValue, Args, nullptr);
460}
461
462// Initializes local resource array variable with global resource array
463// elements. For multi-dimensional arrays it calls itself recursively to
464// initialize its sub-arrays. The Index used in the resource constructor calls
465// will begin at StartIndex and will be incremented for each array element. The
466// last used resource Index is returned to the caller. If the function returns
467// std::nullopt, it indicates an error.
468static std::optional<llvm::Value *> initializeResourceArrayFromGlobal(
469 CodeGenFunction &CGF, CXXRecordDecl *ResourceDecl,
470 const ConstantArrayType *ArrayTy, AggValueSlot &ValueSlot,
471 llvm::Value *Range, llvm::Value *StartIndex, StringRef ResourceName,
472 ResourceBindingAttrs &Binding, ArrayRef<llvm::Value *> PrevGEPIndices) {
473
474 ASTContext &AST = CGF.getContext();
475 llvm::IntegerType *IntTy = CGF.CGM.IntTy;
476 llvm::Value *Index = StartIndex;
477 llvm::Value *One = llvm::ConstantInt::get(IntTy, 1);
478 const uint64_t ArraySize = ArrayTy->getSExtSize();
479 QualType ElemType = ArrayTy->getElementType();
480 Address TmpArrayAddr = ValueSlot.getAddress();
481
482 // Add additional index to the getelementptr call indices.
483 // This index will be updated for each array element in the loops below.
484 SmallVector<llvm::Value *> GEPIndices(PrevGEPIndices);
485 GEPIndices.push_back(llvm::ConstantInt::get(IntTy, 0));
486
487 // For array of arrays, recursively initialize the sub-arrays.
488 if (ElemType->isArrayType()) {
489 const ConstantArrayType *SubArrayTy = cast<ConstantArrayType>(ElemType);
490 for (uint64_t I = 0; I < ArraySize; I++) {
491 if (I > 0) {
492 Index = CGF.Builder.CreateAdd(Index, One);
493 GEPIndices.back() = llvm::ConstantInt::get(IntTy, I);
494 }
495 std::optional<llvm::Value *> MaybeIndex =
496 initializeResourceArrayFromGlobal(CGF, ResourceDecl, SubArrayTy,
497 ValueSlot, Range, Index,
498 ResourceName, Binding, GEPIndices);
499 if (!MaybeIndex)
500 return std::nullopt;
501 Index = *MaybeIndex;
502 }
503 return Index;
504 }
505
506 // For array of resources, initialize each resource in the array.
507 llvm::Type *Ty = CGF.ConvertTypeForMem(ElemType);
508 CharUnits ElemSize = AST.getTypeSizeInChars(ElemType);
509 CharUnits Align =
510 TmpArrayAddr.getAlignment().alignmentOfArrayElement(ElemSize);
511
512 for (uint64_t I = 0; I < ArraySize; I++) {
513 if (I > 0) {
514 Index = CGF.Builder.CreateAdd(Index, One);
515 GEPIndices.back() = llvm::ConstantInt::get(IntTy, I);
516 }
517 Address ReturnAddress =
518 CGF.Builder.CreateGEP(TmpArrayAddr, GEPIndices, Ty, Align);
519
520 CallArgList Args;
521 CXXMethodDecl *CreateMethod = lookupResourceInitMethodAndSetupArgs(
522 CGF.CGM, ResourceDecl, Range, Index, ResourceName, Binding, Args);
523
524 if (!CreateMethod)
525 // This can happen if someone creates an array of structs that looks like
526 // an HLSL resource record array but it does not have the required static
527 // create method. No binding will be generated for it.
528 return std::nullopt;
529
530 callResourceInitMethod(CGF, CreateMethod, Args, ReturnAddress);
531 }
532 return Index;
533}
534
535/// Utility for emitting copies following the HLSL buffer layout rules (ie,
536/// copying out of a cbuffer).
537class HLSLBufferCopyEmitter {
538 CodeGenFunction &CGF;
539 Address DstPtr;
540 Address SrcPtr;
541 llvm::Type *LayoutTy = nullptr;
542
543 SmallVector<llvm::Value *> CurStoreIndices;
544 SmallVector<llvm::Value *> CurLoadIndices;
545
546 using EmitResourceFnTy = llvm::function_ref<void(AggValueSlot &)>;
547
548 // Creates & returns either a structured.gep or a ptradd/gep depending on
549 // langopts.
550 llvm::Value *emitAccessChain(llvm::Type *BaseTy, llvm::Value *Base,
551 ArrayRef<llvm::Value *> Indices) {
552 bool EmitLogical = CGF.getLangOpts().EmitLogicalPointer;
553 if (EmitLogical)
554 return CGF.Builder.CreateAccessChain(EmitLogical, BaseTy, Base, Indices);
555
556 llvm::SmallVector<llvm::Value *> GEPIndices;
557 GEPIndices.reserve(Indices.size() + 1);
558 GEPIndices.push_back(llvm::ConstantInt::get(CGF.IntTy, 0));
559 GEPIndices.append(Indices.begin(), Indices.end());
560 return CGF.Builder.CreateAccessChain(EmitLogical, BaseTy, Base, GEPIndices);
561 }
562
563 bool isBufferLayoutArray(llvm::StructType *ST) {
564 // A buffer layout array is a struct with two elements: the padded array,
565 // and the last element. That is, is should look something like this:
566 //
567 // { [%n x { %type, %padding }], %type }
568 //
569 if (!ST || ST->getNumElements() != 2)
570 return false;
571
572 auto *PaddedEltsTy = dyn_cast<llvm::ArrayType>(ST->getElementType(0));
573 if (!PaddedEltsTy)
574 return false;
575
576 auto *PaddedTy = dyn_cast<llvm::StructType>(PaddedEltsTy->getElementType());
577 if (!PaddedTy || PaddedTy->getNumElements() != 2)
578 return false;
579
580 if (!CGF.CGM.getTargetCodeGenInfo().isHLSLPadding(
581 PaddedTy->getElementType(1)))
582 return false;
583
584 llvm::Type *ElementTy = ST->getElementType(1);
585 if (PaddedTy->getElementType(0) != ElementTy)
586 return false;
587 return true;
588 }
589
590 // Returns true if the type is either a struct representing a resource record,
591 // or an array of structs that are resource records. This assumes a struct is
592 // a resource record if the first element is a target type (resource handle).
593 // This is the case for all target types used by HLSL except the padding type
594 // ("{dx|spirv.Padding"), but padding will never be the first element of a
595 // struct.
596 bool isResourceOrResourceArray(llvm::Type *Ty) {
597 while (auto *AT = dyn_cast<llvm::ArrayType>(Ty))
598 Ty = AT->getElementType();
599
600 auto *ST = dyn_cast<llvm::StructType>(Ty);
601 if (!ST || ST->getNumElements() < 1)
602 return false;
603
604 auto *TargetTy = dyn_cast<llvm::TargetExtType>(ST->getElementType(0));
605 return TargetTy != nullptr;
606 }
607
608 void emitResourceOrResourceArray(Value *Dst, llvm::Type *DstTy,
609 EmitResourceFnTy EmitResFn) {
610 CharUnits DstAlign =
611 CharUnits::fromQuantity(CGF.CGM.getDataLayout().getABITypeAlign(DstTy));
612 Address DstAddr(Dst, DstTy, DstAlign);
613 AggValueSlot Slot = AggValueSlot::forAddr(
614 DstAddr, Qualifiers(), AggValueSlot::IsDestructed_t(true),
617
618 EmitResFn(Slot);
619 }
620
621 void emitBufferLayoutCopy(Value *Src, llvm::StructType *SrcTy, Value *Dst,
622 llvm::ArrayType *DstTy,
623 EmitResourceFnTy EmitResFn) {
624 // Those assumptions are checked by isBufferLayoutArray.
625 auto *SrcPaddedArrayTy = cast<llvm::ArrayType>(SrcTy->getElementType(0));
626 assert(SrcPaddedArrayTy->getNumElements() + 1 == DstTy->getNumElements());
627 assert(cast<llvm::StructType>(SrcPaddedArrayTy->getElementType())
628 ->getElementType(0) == SrcTy->getElementType(1));
629
630 auto *SrcDataTy = SrcTy->getElementType(1);
631 auto Zero = llvm::ConstantInt::get(CGF.IntTy, 0);
632
633 for (unsigned I = 0; I < SrcPaddedArrayTy->getNumElements(); ++I) {
634 auto Index = llvm::ConstantInt::get(CGF.IntTy, I);
635 auto *SrcElt = emitAccessChain(SrcTy, Src, {Zero, Index, Zero});
636 auto *DstElt = emitAccessChain(DstTy, Dst, {Index});
637 emitElementCopy(SrcElt, SrcDataTy, DstElt, DstTy->getElementType(),
638 EmitResFn);
639 }
640
641 auto *SrcElt =
642 emitAccessChain(SrcTy, Src, {llvm::ConstantInt::get(CGF.IntTy, 1)});
643 auto *DstElt = emitAccessChain(
644 DstTy, Dst,
645 {llvm::ConstantInt::get(CGF.IntTy, DstTy->getNumElements() - 1)});
646 emitElementCopy(SrcElt, SrcDataTy, DstElt, DstTy->getElementType(),
647 EmitResFn);
648 }
649
650 void emitCopy(Value *Src, llvm::StructType *SrcTy, Value *Dst,
651 llvm::Type *DstTy, EmitResourceFnTy EmitResFn) {
652 assert(!isResourceOrResourceArray(DstTy) &&
653 "direct access to resources or resource arrays should be handled "
654 "separately");
655
656 if (isBufferLayoutArray(SrcTy))
657 return emitBufferLayoutCopy(Src, SrcTy, Dst, cast<llvm::ArrayType>(DstTy),
658 EmitResFn);
659
660 unsigned SrcIndex = 0;
661 unsigned DstIndex = 0;
662
663 // DstTy layout is in default address space and can include resource types.
664 // SrcTy is in cbuffer layout where resources are filtered out, so the
665 // number of elements in SrcTy can be less than the number of elements in
666 // DstTy.
667 auto *DstST = cast<llvm::StructType>(DstTy);
668 while (DstIndex < DstST->getNumElements()) {
669 llvm::Type *DstEltTy = DstST->getElementType(DstIndex);
670 if (CGF.CGM.getTargetCodeGenInfo().isHLSLPadding(DstEltTy)) {
671 DstIndex += 1;
672 continue;
673 }
674 if (isResourceOrResourceArray(DstEltTy)) {
675 auto *DstElt = emitAccessChain(
676 DstTy, Dst, {llvm::ConstantInt::get(CGF.IntTy, DstIndex)});
677 emitResourceOrResourceArray(DstElt, DstEltTy, EmitResFn);
678 DstIndex += 1;
679 continue;
680 }
681
682 assert(SrcIndex < SrcTy->getNumElements());
683 llvm::Type *SrcEltTy = SrcTy->getElementType(SrcIndex);
684 if (CGF.CGM.getTargetCodeGenInfo().isHLSLPadding(SrcEltTy)) {
685 SrcIndex += 1;
686 continue;
687 }
688
689 auto *SrcElt = emitAccessChain(
690 SrcTy, Src, {llvm::ConstantInt::get(CGF.IntTy, SrcIndex)});
691 auto *DstElt = emitAccessChain(
692 DstTy, Dst, {llvm::ConstantInt::get(CGF.IntTy, DstIndex)});
693 emitElementCopy(SrcElt, SrcEltTy, DstElt, DstEltTy, EmitResFn);
694 DstIndex += 1;
695 SrcIndex += 1;
696 }
697 }
698
699 void emitCopy(Value *Src, llvm::ArrayType *SrcTy, Value *Dst,
700 llvm::Type *DstTy, EmitResourceFnTy EmitResFn) {
701 for (unsigned I = 0, E = SrcTy->getNumElements(); I < E; ++I) {
702 auto *SrcElt =
703 emitAccessChain(SrcTy, Src, {llvm::ConstantInt::get(CGF.IntTy, I)});
704 auto *DstElt =
705 emitAccessChain(DstTy, Dst, {llvm::ConstantInt::get(CGF.IntTy, I)});
706 emitElementCopy(SrcElt, SrcTy->getElementType(), DstElt,
707 cast<llvm::ArrayType>(DstTy)->getElementType(),
708 EmitResFn);
709 }
710 }
711
712 void emitElementCopy(Value *Src, llvm::Type *SrcTy, Value *Dst,
713 llvm::Type *DstTy, EmitResourceFnTy EmitResFn) {
714 if (auto *AT = dyn_cast<llvm::ArrayType>(SrcTy))
715 return emitCopy(Src, AT, Dst, DstTy, EmitResFn);
716 if (auto *ST = dyn_cast<llvm::StructType>(SrcTy))
717 return emitCopy(Src, ST, Dst, DstTy, EmitResFn);
718
719 // When we have a scalar or vector element we can emit the copy.
720 CharUnits SrcAlign =
721 CharUnits::fromQuantity(CGF.CGM.getDataLayout().getABITypeAlign(SrcTy));
722 CharUnits DstAlign =
723 CharUnits::fromQuantity(CGF.CGM.getDataLayout().getABITypeAlign(DstTy));
724 Address SrcAddr(Src, SrcTy, SrcAlign);
725 Address DstAddr(Dst, DstTy, DstAlign);
726 llvm::Value *Load = CGF.Builder.CreateLoad(SrcAddr, "cbuf.load");
727 CGF.Builder.CreateStore(Load, DstAddr);
728 }
729
730public:
731 HLSLBufferCopyEmitter(CodeGenFunction &CGF, Address DstPtr, Address SrcPtr)
732 : CGF(CGF), DstPtr(DstPtr), SrcPtr(SrcPtr) {}
733
734 bool emitCopy(QualType CType, EmitResourceFnTy EmitResFn = nullptr) {
735 LayoutTy = HLSLBufferLayoutBuilder(CGF.CGM).layOutType(CType);
736
737 // TODO: We should be able to fall back to a regular memcpy if the layout
738 // type doesn't have any padding, but that runs into issues in the backend
739 // currently.
740 //
741 // See https://github.com/llvm/wg-hlsl/issues/351
742 emitElementCopy(SrcPtr.getBasePointer(), LayoutTy, DstPtr.getBasePointer(),
743 DstPtr.getElementType(), EmitResFn);
744 return true;
745 }
746};
747
748// Represents a list resources associated with a global struct whose name
749// starts with the specified prefix.
750// The order of HLSLAssociatedResourceDeclAttr attributes is identical to the
751// order of the depth-first traversal of the corresponding fields in the struct.
752// The resources are always returned in that order, which is the same order
753// we need when a struct is copied element-by-element.
754class AssociatedResourcesList {
755 // Iterator pointers for the associated resource attributes that match the
756 // prefix. Begin = begin of the range of attributes that match the prefix End
757 // = end of the range of attributes that match the prefix Next = the current
758 // attribute in the iteration to be returned by getNextResource
759 specific_attr_iterator<HLSLAssociatedResourceDeclAttr> Begin, End, Next;
760
761public:
762 AssociatedResourcesList(const VarDecl *StructVD,
763 StringRef ResourceNamePrefix) {
764 auto I = StructVD->specific_attr_begin<HLSLAssociatedResourceDeclAttr>();
765 auto E = StructVD->specific_attr_end<HLSLAssociatedResourceDeclAttr>();
766
767 // Skip over associated resources that don't match the prefix.
768 while (I != E &&
769 !I->getResDecl()->getName().starts_with(ResourceNamePrefix))
770 ++I;
771 assert(I != E && "expected associated resource not found");
772 Begin = End = I;
773
774 // Scan over associated resources that do match the prefix to find the end
775 // of the range.
776 while (I != E && ((HLSLAssociatedResourceDeclAttr *)*I)
777 ->getResDecl()
778 ->getName()
779 .starts_with(ResourceNamePrefix))
780 End = ++I;
781
782 Next = Begin;
783 }
784
785 const VarDecl *getNextResource() {
786 if (Next == End)
787 return nullptr;
788
789 const VarDecl *Res = Next->getResDecl();
790 ++Next;
791 return Res;
792 }
793};
794
795} // namespace
796
797llvm::Type *
799 const CGHLSLOffsetInfo &OffsetInfo) {
800 assert(T->isHLSLSpecificType() && "Not an HLSL specific type!");
801
802 // Check if the target has a specific translation for this type first.
803 if (llvm::Type *TargetTy =
804 CGM.getTargetCodeGenInfo().getHLSLType(CGM, T, OffsetInfo))
805 return TargetTy;
806
807 llvm_unreachable("Generic handling of HLSL types is not supported.");
808}
809
810llvm::Triple::ArchType CGHLSLRuntime::getArch() {
811 return CGM.getTarget().getTriple().getArch();
812}
813
814// Emits constant global variables for buffer constants declarations
815// and creates metadata linking the constant globals with the buffer global.
816void CGHLSLRuntime::emitBufferGlobalsAndMetadata(
817 const HLSLBufferDecl *BufDecl, llvm::GlobalVariable *BufGV,
818 const CGHLSLOffsetInfo &OffsetInfo) {
819 LLVMContext &Ctx = CGM.getLLVMContext();
820
821 // get the layout struct from constant buffer target type
822 llvm::Type *BufType = BufGV->getValueType();
823 llvm::StructType *LayoutStruct = cast<llvm::StructType>(
824 cast<llvm::TargetExtType>(BufType)->getTypeParameter(0));
825
827 size_t OffsetIdx = 0;
828 for (Decl *D : BufDecl->buffer_decls()) {
830 // Nothing to do for this declaration.
831 continue;
832 if (isa<FunctionDecl>(D)) {
833 // A function within an cbuffer is effectively a top-level function.
835 continue;
836 }
837 VarDecl *VD = dyn_cast<VarDecl>(D);
838 if (!VD)
839 continue;
840
841 QualType VDTy = VD->getType();
843 if (VD->getStorageClass() == SC_Static ||
846 // Emit static and groupshared variables and resource classes inside
847 // cbuffer as regular globals
848 CGM.EmitGlobal(VD);
849 }
850 continue;
851 }
852
853 DeclsWithOffset.emplace_back(VD, OffsetInfo[OffsetIdx++]);
854 }
855
856 if (!OffsetInfo.empty())
857 llvm::stable_sort(DeclsWithOffset, [](const auto &LHS, const auto &RHS) {
858 return CGHLSLOffsetInfo::compareOffsets(LHS.second, RHS.second);
859 });
860
861 // Associate the buffer global variable with its constants
862 SmallVector<llvm::Metadata *> BufGlobals;
863 BufGlobals.reserve(DeclsWithOffset.size() + 1);
864 BufGlobals.push_back(ValueAsMetadata::get(BufGV));
865
866 auto ElemIt = LayoutStruct->element_begin();
867 for (auto &[VD, _] : DeclsWithOffset) {
868 if (CGM.getTargetCodeGenInfo().isHLSLPadding(*ElemIt))
869 ++ElemIt;
870
871 assert(ElemIt != LayoutStruct->element_end() &&
872 "number of elements in layout struct does not match");
873 llvm::Type *LayoutType = *ElemIt++;
874
875 GlobalVariable *ElemGV =
876 cast<GlobalVariable>(CGM.GetAddrOfGlobalVar(VD, LayoutType));
877 BufGlobals.push_back(ValueAsMetadata::get(ElemGV));
878 }
879 assert(ElemIt == LayoutStruct->element_end() &&
880 "number of elements in layout struct does not match");
881
882 // add buffer metadata to the module
883 CGM.getModule()
884 .getOrInsertNamedMetadata("hlsl.cbs")
885 ->addOperand(MDNode::get(Ctx, BufGlobals));
886}
887
888// Creates resource handle type for the HLSL buffer declaration
889static const clang::HLSLAttributedResourceType *
891 ASTContext &AST = BufDecl->getASTContext();
893 AST.HLSLResourceTy, AST.getCanonicalTagType(BufDecl->getLayoutStruct()),
894 HLSLAttributedResourceType::Attributes(ResourceClass::CBuffer));
896}
897
900
901 // If we don't have packoffset info, just return an empty result.
902 if (!BufDecl.hasValidPackoffset())
903 return Result;
904
905 for (Decl *D : BufDecl.buffer_decls()) {
907 continue;
908 }
909 VarDecl *VD = dyn_cast<VarDecl>(D);
910 if (!VD || VD->getType().getAddressSpace() != LangAS::hlsl_constant)
911 continue;
912
913 if (!VD->hasAttrs()) {
914 Result.Offsets.push_back(Unspecified);
915 continue;
916 }
917
918 uint32_t Offset = Unspecified;
919 for (auto *Attr : VD->getAttrs()) {
920 if (auto *POA = dyn_cast<HLSLPackOffsetAttr>(Attr)) {
921 Offset = POA->getOffsetInBytes();
922 break;
923 }
924 auto *RBA = dyn_cast<HLSLResourceBindingAttr>(Attr);
925 if (RBA &&
926 RBA->getRegisterType() == HLSLResourceBindingAttr::RegisterType::C) {
927 Offset = RBA->getSlotNumber() * CBufferRowSizeInBytes;
928 break;
929 }
930 }
931 Result.Offsets.push_back(Offset);
932 }
933 return Result;
934}
935
936// Codegen for HLSLBufferDecl
938
939 assert(BufDecl->isCBuffer() && "tbuffer codegen is not supported yet");
940
941 // create resource handle type for the buffer
942 const clang::HLSLAttributedResourceType *ResHandleTy =
943 createBufferHandleType(BufDecl);
944
945 // empty constant buffer is ignored
946 if (ResHandleTy->getContainedType()->getAsCXXRecordDecl()->isEmpty())
947 return;
948
949 // create global variable for the constant buffer
950 CGHLSLOffsetInfo OffsetInfo = CGHLSLOffsetInfo::fromDecl(*BufDecl);
951 llvm::Type *LayoutTy = convertHLSLSpecificType(ResHandleTy, OffsetInfo);
952 llvm::GlobalVariable *BufGV = new GlobalVariable(
953 LayoutTy, /*isConstant*/ false,
954 GlobalValue::LinkageTypes::InternalLinkage, PoisonValue::get(LayoutTy),
955 llvm::formatv("{0}{1}", BufDecl->getName(),
956 BufDecl->isCBuffer() ? ".cb" : ".tb"),
957 GlobalValue::NotThreadLocal);
958
959 llvm::Module &M = CGM.getModule();
960 M.insertGlobalVariable(BufGV);
961
962 // Add the global variable to the compiler used list so it does not
963 // get optimized away by GlobalOptPass before it reaches
964 // {DXIL|SPIRV}CBufferAccess pass.
965 llvm::appendToCompilerUsed(M, {BufGV});
966
967 // Add globals for constant buffer elements and create metadata nodes
968 emitBufferGlobalsAndMetadata(BufDecl, BufGV, OffsetInfo);
969
970 // Initialize cbuffer from binding (implicit or explicit)
971 initializeBufferFromBinding(BufDecl, BufGV);
972}
973
975 const HLSLRootSignatureDecl *SignatureDecl) {
976 llvm::Module &M = CGM.getModule();
977 Triple T(M.getTargetTriple());
978
979 // Generated later with the function decl if not targeting root signature
980 if (T.getEnvironment() != Triple::EnvironmentType::RootSignature)
981 return;
982
983 addRootSignatureMD(SignatureDecl->getVersion(),
984 SignatureDecl->getRootElements(), nullptr, M);
985}
986
987llvm::StructType *
988CGHLSLRuntime::getHLSLBufferLayoutType(const RecordType *StructType) {
989 const auto Entry = LayoutTypes.find(StructType);
990 if (Entry != LayoutTypes.end())
991 return Entry->getSecond();
992 return nullptr;
993}
994
995void CGHLSLRuntime::addHLSLBufferLayoutType(const RecordType *StructType,
996 llvm::StructType *LayoutTy) {
997 assert(getHLSLBufferLayoutType(StructType) == nullptr &&
998 "layout type for this struct already exist");
999 LayoutTypes[StructType] = LayoutTy;
1000}
1001
1003 auto &TargetOpts = CGM.getTarget().getTargetOpts();
1004 auto &CodeGenOpts = CGM.getCodeGenOpts();
1005 auto &LangOpts = CGM.getLangOpts();
1006 llvm::Module &M = CGM.getModule();
1007 Triple T(M.getTargetTriple());
1008 if (T.getArch() == Triple::ArchType::dxil)
1009 addDxilValVersion(TargetOpts.DxilValidatorVersion, M);
1010 if (!CodeGenOpts.DisableDXSourceMetadata &&
1011 CodeGenOpts.getDebugInfo() >=
1012 llvm::codegenoptions::DebugInfoKind::DebugInfoConstructor)
1013 addSourceInfo(CGM, M);
1014 if (CodeGenOpts.ResMayAlias)
1015 M.setModuleFlag(llvm::Module::ModFlagBehavior::Error, "dx.resmayalias", 1);
1016 if (CodeGenOpts.AllResourcesBound)
1017 M.setModuleFlag(llvm::Module::ModFlagBehavior::Error,
1018 "dx.allresourcesbound", 1);
1019 if (CodeGenOpts.OptimizationLevel == 0)
1020 M.addModuleFlag(llvm::Module::ModFlagBehavior::Override,
1021 "dx.disable_optimizations", 1);
1022
1023 // NativeHalfType corresponds to the -fnative-half-type clang option which is
1024 // aliased by clang-dxc's -enable-16bit-types option. This option is used to
1025 // set the UseNativeLowPrecision DXIL module flag in the DirectX backend
1026 if (LangOpts.NativeHalfType)
1027 M.setModuleFlag(llvm::Module::ModFlagBehavior::Error, "dx.nativelowprec",
1028 1);
1029
1030 if (LangOpts.HLSLSpvPreserveInterface && T.isSPIRV()) {
1031 // Runs before optimization. Keeps Input/Output globals from GlobalDCE.
1032 const ASTContext &Ctx = CGM.getContext();
1033 unsigned InputAS = Ctx.getTargetAddressSpace(LangAS::hlsl_input);
1034 unsigned OutputAS = Ctx.getTargetAddressSpace(LangAS::hlsl_output);
1035 SmallVector<GlobalValue *, 8> InterfaceVars;
1036 for (GlobalVariable &GV : M.globals()) {
1037 unsigned AS = GV.getAddressSpace();
1038 if (AS == InputAS || AS == OutputAS)
1039 InterfaceVars.push_back(&GV);
1040 }
1041 if (!InterfaceVars.empty())
1042 appendToCompilerUsed(M, InterfaceVars);
1043 }
1044
1046}
1047
1049 const FunctionDecl *FD, llvm::Function *Fn) {
1050 const auto *ShaderAttr = FD->getAttr<HLSLShaderAttr>();
1051 assert(ShaderAttr && "All entry functions must have a HLSLShaderAttr");
1052 const StringRef ShaderAttrKindStr = "hlsl.shader";
1053 Fn->addFnAttr(ShaderAttrKindStr,
1054 llvm::Triple::getEnvironmentTypeName(ShaderAttr->getType()));
1055 if (HLSLNumThreadsAttr *NumThreadsAttr = FD->getAttr<HLSLNumThreadsAttr>()) {
1056 const StringRef NumThreadsKindStr = "hlsl.numthreads";
1057 std::string NumThreadsStr =
1058 formatv("{0},{1},{2}", NumThreadsAttr->getX(), NumThreadsAttr->getY(),
1059 NumThreadsAttr->getZ());
1060 Fn->addFnAttr(NumThreadsKindStr, NumThreadsStr);
1061 }
1062 if (HLSLWaveSizeAttr *WaveSizeAttr = FD->getAttr<HLSLWaveSizeAttr>()) {
1063 const StringRef WaveSizeKindStr = "hlsl.wavesize";
1064 std::string WaveSizeStr =
1065 formatv("{0},{1},{2}", WaveSizeAttr->getMin(), WaveSizeAttr->getMax(),
1066 WaveSizeAttr->getPreferred());
1067 Fn->addFnAttr(WaveSizeKindStr, WaveSizeStr);
1068 }
1069 // HLSL entry functions are materialized for module functions with
1070 // HLSLShaderAttr attribute. SetLLVMFunctionAttributesForDefinition called
1071 // later in the compiler-flow for such module functions is not aware of and
1072 // hence not able to set attributes of the newly materialized entry functions.
1073 // So, set attributes of entry function here, as appropriate.
1074 Fn->addFnAttr(llvm::Attribute::NoInline);
1075
1076 if (CGM.getLangOpts().HLSLSpvEnableMaximalReconvergence) {
1077 Fn->addFnAttr("enable-maximal-reconvergence", "true");
1078 }
1079}
1080
1081static Value *buildVectorInput(IRBuilder<> &B, Function *F, llvm::Type *Ty) {
1082 // Compute ID intrinsics return i32 components, but the semantic may use
1083 // 16-bit integers. Narrow each component before assembling the input.
1084 if (const auto *VT = dyn_cast<FixedVectorType>(Ty)) {
1085 Value *Result = PoisonValue::get(Ty);
1086 for (unsigned I = 0; I < VT->getNumElements(); ++I) {
1087 Value *Elt = B.CreateCall(F, {B.getInt32(I)});
1088 Elt = B.CreateTrunc(Elt, VT->getElementType());
1089 Result = B.CreateInsertElement(Result, Elt, I);
1090 }
1091 return Result;
1092 }
1093 return B.CreateTrunc(B.CreateCall(F, {B.getInt32(0)}), Ty);
1094}
1095
1096static void addSPIRVBuiltinDecoration(llvm::GlobalVariable *GV,
1097 unsigned BuiltIn) {
1098 LLVMContext &Ctx = GV->getContext();
1099 IRBuilder<> B(*GV->getParent());
1100 MDNode *Operands = MDNode::get(
1101 Ctx,
1102 {ConstantAsMetadata::get(B.getInt32(/* Spirv::Decoration::BuiltIn */ 11)),
1103 ConstantAsMetadata::get(B.getInt32(BuiltIn))});
1104 MDNode *Decoration = MDNode::get(Ctx, {Operands});
1105 GV->addMetadata("spirv.Decorations", *Decoration);
1106}
1107
1108static void addLocationDecoration(llvm::GlobalVariable *GV, unsigned Location) {
1109 LLVMContext &Ctx = GV->getContext();
1110 IRBuilder<> B(*GV->getParent());
1111 MDNode *Operands =
1112 MDNode::get(Ctx, {ConstantAsMetadata::get(B.getInt32(/* Location */ 30)),
1113 ConstantAsMetadata::get(B.getInt32(Location))});
1114 MDNode *Decoration = MDNode::get(Ctx, {Operands});
1115 GV->addMetadata("spirv.Decorations", *Decoration);
1116}
1117
1118// A fragment shader input interface variable whose base type is an integer or
1119// a 64-bit float (double) cannot be interpolated by the rasterizer. The Vulkan
1120// specification requires these variables to be decorated with Flat (see
1121// VUID-StandaloneSpirv-Flat-04744). Arrays and vectors are unwrapped to inspect
1122// their base scalar type.
1123static bool inputRequiresFlatDecoration(llvm::Type *Ty) {
1124 while (true) {
1125 if (auto *AT = dyn_cast<llvm::ArrayType>(Ty)) {
1126 Ty = AT->getElementType();
1127 continue;
1128 }
1129 if (auto *VT = dyn_cast<llvm::FixedVectorType>(Ty)) {
1130 Ty = VT->getElementType();
1131 continue;
1132 }
1133 break;
1134 }
1135 return Ty->isIntegerTy() || Ty->isDoubleTy();
1136}
1137
1138static llvm::Value *createSPIRVBuiltinLoad(IRBuilder<> &B, llvm::Module &M,
1139 llvm::Type *Ty, const Twine &Name,
1140 unsigned BuiltInID) {
1141 auto *GV = new llvm::GlobalVariable(
1142 M, Ty, /* isConstant= */ true, llvm::GlobalValue::ExternalLinkage,
1143 /* Initializer= */ nullptr, Name, /* insertBefore= */ nullptr,
1144 llvm::GlobalVariable::GeneralDynamicTLSModel,
1145 /* AddressSpace */ 7, /* isExternallyInitialized= */ true);
1146 addSPIRVBuiltinDecoration(GV, BuiltInID);
1147 GV->setVisibility(llvm::GlobalValue::HiddenVisibility);
1148 return B.CreateLoad(Ty, GV);
1149}
1150
1151static llvm::Value *createSPIRVLocationLoad(IRBuilder<> &B, llvm::Module &M,
1152 llvm::Type *Ty, unsigned Location,
1153 StringRef Name, bool NeedsFlat) {
1154 auto *GV = new llvm::GlobalVariable(
1155 M, Ty, /* isConstant= */ true, llvm::GlobalValue::ExternalLinkage,
1156 /* Initializer= */ nullptr, /* Name= */ Name, /* insertBefore= */ nullptr,
1157 llvm::GlobalVariable::GeneralDynamicTLSModel,
1158 /* AddressSpace */ 7, /* isExternallyInitialized= */ true);
1159 GV->setVisibility(llvm::GlobalValue::HiddenVisibility);
1160
1161 // Emit all decorations as a single `spirv.Decorations` node. Attaching
1162 // multiple `spirv.Decorations` metadata nodes to the same global is not
1163 // supported by the SPIR-V backend and results in all but one being dropped.
1164 LLVMContext &Ctx = GV->getContext();
1165 SmallVector<Metadata *, 2> Decorations;
1166 Decorations.push_back(
1167 MDNode::get(Ctx, {ConstantAsMetadata::get(
1168 B.getInt32(/* SPIRV::Decoration::Location */ 30)),
1169 ConstantAsMetadata::get(B.getInt32(Location))}));
1170 if (NeedsFlat)
1171 Decorations.push_back(
1172 MDNode::get(Ctx, {ConstantAsMetadata::get(
1173 B.getInt32(/* SPIRV::Decoration::Flat */ 14))}));
1174 GV->addMetadata("spirv.Decorations", *MDNode::get(Ctx, Decorations));
1175
1176 return B.CreateLoad(Ty, GV);
1177}
1178
1179llvm::Value *CGHLSLRuntime::emitSPIRVUserSemanticLoad(
1180 llvm::IRBuilder<> &B, const FunctionDecl *FD, llvm::Type *Type,
1181 const clang::DeclaratorDecl *Decl, HLSLAppliedSemanticAttr *Semantic,
1182 std::optional<unsigned> Index) {
1183 Twine BaseName = Twine(Semantic->getAttrName()->getName());
1184 Twine VariableName = BaseName.concat(Twine(Index.value_or(0)));
1185
1186 unsigned Location = SPIRVLastAssignedInputSemanticLocation;
1187 if (auto *L = Decl->getAttr<HLSLVkLocationAttr>())
1188 Location = L->getLocation();
1189
1190 // DXC completely ignores the semantic/index pair. Location are assigned from
1191 // the first semantic to the last.
1192 llvm::ArrayType *AT = dyn_cast<llvm::ArrayType>(Type);
1193 unsigned ElementCount = AT ? AT->getNumElements() : 1;
1194 SPIRVLastAssignedInputSemanticLocation += ElementCount;
1195
1196 const auto *ShaderAttr = FD->getAttr<HLSLShaderAttr>();
1197 bool NeedsFlat =
1198 ShaderAttr &&
1199 ShaderAttr->getType() == llvm::Triple::EnvironmentType::Pixel &&
1201
1202 return createSPIRVLocationLoad(B, CGM.getModule(), Type, Location,
1203 VariableName.str(), NeedsFlat);
1204}
1205
1206static void createSPIRVLocationStore(IRBuilder<> &B, llvm::Module &M,
1207 llvm::Value *Source, unsigned Location,
1208 StringRef Name) {
1209 auto *GV = new llvm::GlobalVariable(
1210 M, Source->getType(), /* isConstant= */ false,
1211 llvm::GlobalValue::ExternalLinkage,
1212 /* Initializer= */ nullptr, /* Name= */ Name, /* insertBefore= */ nullptr,
1213 llvm::GlobalVariable::GeneralDynamicTLSModel,
1214 /* AddressSpace */ 8, /* isExternallyInitialized= */ false);
1215 GV->setVisibility(llvm::GlobalValue::HiddenVisibility);
1216 addLocationDecoration(GV, Location);
1217 B.CreateStore(Source, GV);
1218}
1219
1220void CGHLSLRuntime::emitSPIRVUserSemanticStore(
1221 llvm::IRBuilder<> &B, llvm::Value *Source,
1222 const clang::DeclaratorDecl *Decl, HLSLAppliedSemanticAttr *Semantic,
1223 std::optional<unsigned> Index) {
1224 Twine BaseName = Twine(Semantic->getAttrName()->getName());
1225 Twine VariableName = BaseName.concat(Twine(Index.value_or(0)));
1226
1227 unsigned Location = SPIRVLastAssignedOutputSemanticLocation;
1228 if (auto *L = Decl->getAttr<HLSLVkLocationAttr>())
1229 Location = L->getLocation();
1230
1231 // DXC completely ignores the semantic/index pair. Location are assigned from
1232 // the first semantic to the last.
1233 llvm::ArrayType *AT = dyn_cast<llvm::ArrayType>(Source->getType());
1234 unsigned ElementCount = AT ? AT->getNumElements() : 1;
1235 SPIRVLastAssignedOutputSemanticLocation += ElementCount;
1236 createSPIRVLocationStore(B, CGM.getModule(), Source, Location,
1237 VariableName.str());
1238}
1239
1240namespace {
1241// Describes how a semantic leaf lowers to signature rows
1242struct SemanticShape {
1243 SmallVector<unsigned> Dimensions; // Empty dims denotes a scalar
1244 unsigned Cols;
1245 QualType RowType;
1246
1247 unsigned getNumRows() const {
1248 unsigned Rows = 1;
1249 for (unsigned Dimension : Dimensions)
1250 Rows *= Dimension;
1251 return Rows;
1252 }
1253
1254 SmallVector<unsigned> getArrayIndicesForRow(unsigned Row) const {
1255 assert(Row < getNumRows() && "row exceeds semantic shape");
1256
1257 SmallVector<unsigned> Indices(Dimensions.size());
1258 for (auto [Index, Dimension] :
1259 llvm::zip_equal(llvm::reverse(Indices), llvm::reverse(Dimensions))) {
1260 Index = Row % Dimension;
1261 Row /= Dimension;
1262 }
1263 return Indices;
1264 }
1265};
1266} // namespace
1267
1268// Returns the QualType of a semantic leaf declarator. For a function the
1269// declared return type is used, otherwise the declared type.
1271 if (const auto *FD = dyn_cast<clang::FunctionDecl>(Decl))
1272 return FD->getDeclaredReturnType();
1273 return Decl->getType();
1274}
1275
1276// Walks through the surrounding constant array types of \p Ty, collecting their
1277// dimensions until reaching a scalar, vector, or matrix leaf.
1278static SemanticShape getSemanticShape(ASTContext &Ctx, QualType Ty) {
1279 SemanticShape Shape{{}, 1, Ty};
1280 while (const ConstantArrayType *CAT =
1281 Ctx.getAsConstantArrayType(Shape.RowType)) {
1282 Shape.Dimensions.push_back(CAT->getSize().getZExtValue());
1283 Shape.RowType = CAT->getElementType();
1284 }
1285
1286 if (const auto *VT = Shape.RowType->getAs<clang::VectorType>()) {
1287 Shape.Cols = VT->getNumElements();
1288 } else if (const auto *MT =
1289 Shape.RowType->getAs<clang::ConstantMatrixType>()) {
1290 // FIXME: a matrix leaf lowers to one row per matrix row but if column_major
1291 // is specified we transpose the num rows and num cols, this depends on
1292 // #211977 to resolve
1293 Shape.Cols = MT->getNumColumns();
1294 }
1295
1296 return Shape;
1297}
1298
1299static llvm::dxil::ElementType getSignatureComponentType(CodeGenModule &CGM,
1300 QualType Ty) {
1301 if (const auto *VT = Ty->getAs<clang::VectorType>())
1302 Ty = VT->getElementType();
1303 else if (const auto *MT = Ty->getAs<clang::ConstantMatrixType>())
1304 Ty = MT->getElementType();
1305
1306 llvm::Type *IRTy = CGM.getTypes().ConvertTypeForMem(Ty);
1307 bool IsSigned = Ty->isSignedIntegerOrEnumerationType();
1308 return llvm::hlsl::getDXILElementType(IRTy, IsSigned);
1309}
1310
1311static llvm::hlsl::SemanticSignatureElement createSemanticSignatureElement(
1312 CodeGenModule &CGM, uint32_t SigId, HLSLAppliedSemanticAttr *Semantic,
1313 std::optional<unsigned> Index, const SemanticShape &Shape) {
1314 StringRef Name = Semantic->getAttrName()->getName();
1315
1316 // One semantic index per row, starting from the declared index.
1317 SmallVector<uint32_t> SemanticIndices;
1318 uint32_t FirstSemanticIndex = Index.value_or(0);
1319 for (uint32_t I = 0, E = Shape.getNumRows(); I < E; ++I)
1320 SemanticIndices.push_back(FirstSemanticIndex + I);
1321
1322 // The remaining members keep their default value and will be filled at a
1323 // later stage, either during packing or analysis of usage. Interpolation
1324 // is set by the load/store traversal after visiting each leaf.
1325 return llvm::hlsl::SemanticSignatureElement(
1326 SigId, Name, getSignatureComponentType(CGM, Shape.RowType),
1327 llvm::hlsl::getSemanticKind(Name), SemanticIndices,
1328 static_cast<uint8_t>(Shape.Cols));
1329}
1330
1331llvm::Value *CGHLSLRuntime::emitDXILUserSemanticLoad(
1332 llvm::IRBuilder<> &B, llvm::Type *Type, const clang::DeclaratorDecl *Decl,
1333 HLSLAppliedSemanticAttr *Semantic, std::optional<unsigned> Index,
1334 SemanticSignatures &Signature) {
1335 StringRef Name = Semantic->getAttrName()->getName();
1336 SemanticShape Shape =
1338
1339 uint32_t SigId = Signature.size();
1340 Signature.push_back(
1341 createSemanticSignatureElement(CGM, SigId, Semantic, Index, Shape));
1342
1343 llvm::Type *RowTy = CGM.getTypes().ConvertTypeForMem(Shape.RowType);
1344
1345 llvm::Function *IntrFn = llvm::Intrinsic::getOrInsertDeclaration(
1346 B.getModule(), llvm::Intrinsic::dx_load_input, {RowTy});
1347
1348 SmallVector<OperandBundleDef, 1> OB;
1349 if (auto *Token = getConvergenceToken(*B.GetInsertBlock())) {
1350 llvm::Value *bundleArgs[] = {Token};
1351 OB.emplace_back("convergencectrl", bundleArgs);
1352 }
1353
1354 llvm::Type *LeafTy = CGM.getTypes().ConvertType(Shape.RowType);
1355 llvm::Value *Result = llvm::PoisonValue::get(Type);
1356
1357 const unsigned NumRows = Shape.getNumRows();
1358
1359 for (unsigned Row = 0; Row < NumRows; ++Row) {
1360 SmallVector<unsigned> Indices = Shape.getArrayIndicesForRow(Row);
1361 std::array<Value *, 4> Args{
1362 /*SigElementId=*/B.getInt32(SigId),
1363 /*RowIndex=*/B.getInt32(Row),
1364 /*ColIndex=*/B.getInt8(0),
1365 /*GsVertexOrPrimIndex=*/llvm::PoisonValue::get(B.getInt32Ty())};
1366 llvm::Value *Value =
1367 B.CreateCall(IntrFn, Args, OB, Twine(Name).concat(Twine(Row)));
1368 // Booleans use their memory representation in DXIL signatures, but
1369 // function parameters use their value representation.
1370 if (Value->getType() != LeafTy) {
1371 assert(Shape.RowType->hasBooleanRepresentation() &&
1372 "unexpected semantic load type mismatch");
1373 Value = B.CreateICmpNE(
1374 Value, llvm::Constant::getNullValue(Value->getType()), "loadedv");
1375 }
1376
1377 Result =
1378 Indices.empty() ? Value : B.CreateInsertValue(Result, Value, Indices);
1379 }
1380 return Result;
1381}
1382
1383void CGHLSLRuntime::emitDXILUserSemanticStore(llvm::IRBuilder<> &B,
1384 llvm::Value *Source,
1385 const clang::DeclaratorDecl *Decl,
1386 HLSLAppliedSemanticAttr *Semantic,
1387 std::optional<unsigned> Index,
1388 SemanticSignatures &Signature) {
1389 SemanticShape Shape =
1391
1392 uint32_t SigId = Signature.size();
1393 Signature.push_back(
1394 createSemanticSignatureElement(CGM, SigId, Semantic, Index, Shape));
1395
1396 llvm::Type *RowTy = CGM.getTypes().ConvertTypeForMem(Shape.RowType);
1397
1398 llvm::Function *IntrFn = llvm::Intrinsic::getOrInsertDeclaration(
1399 B.getModule(), llvm::Intrinsic::dx_store_output, {RowTy});
1400
1401 SmallVector<OperandBundleDef, 1> OB;
1402 if (auto *Token = getConvergenceToken(*B.GetInsertBlock())) {
1403 llvm::Value *bundleArgs[] = {Token};
1404 OB.emplace_back("convergencectrl", bundleArgs);
1405 }
1406
1407 const unsigned NumRows = Shape.getNumRows();
1408 for (unsigned Row = 0; Row < NumRows; ++Row) {
1409 SmallVector<unsigned> Indices = Shape.getArrayIndicesForRow(Row);
1410 llvm::Value *Val =
1411 Indices.empty() ? Source : B.CreateExtractValue(Source, Indices);
1412
1413 // Booleans use their memory representation in DXIL signatures, but direct
1414 // function results use their value representation.
1415 if (Val->getType() != RowTy) {
1416 assert(Shape.RowType->hasBooleanRepresentation() &&
1417 "unexpected semantic store type mismatch");
1418 Val = B.CreateZExt(Val, RowTy, "storedv");
1419 }
1420
1421 std::array<Value *, 4> Args{/*SigElementId=*/B.getInt32(SigId),
1422 /*RowIndex=*/B.getInt32(Row),
1423 /*ColIndex=*/B.getInt8(0), /*Value=*/Val};
1424 B.CreateCall(IntrFn, Args, OB);
1425 }
1426}
1427
1428llvm::Value *CGHLSLRuntime::emitUserSemanticLoad(
1429 IRBuilder<> &B, const FunctionDecl *FD, llvm::Type *Type,
1430 const clang::DeclaratorDecl *Decl, HLSLAppliedSemanticAttr *Semantic,
1431 std::optional<unsigned> Index, SemanticSignatures &Signature) {
1432 if (CGM.getTarget().getTriple().isSPIRV())
1433 return emitSPIRVUserSemanticLoad(B, FD, Type, Decl, Semantic, Index);
1434
1435 if (CGM.getTarget().getTriple().isDXIL())
1436 return emitDXILUserSemanticLoad(B, Type, Decl, Semantic, Index, Signature);
1437
1438 llvm_unreachable("Unsupported target for user-semantic load.");
1439}
1440
1441void CGHLSLRuntime::emitUserSemanticStore(IRBuilder<> &B, llvm::Value *Source,
1442 const clang::DeclaratorDecl *Decl,
1443 HLSLAppliedSemanticAttr *Semantic,
1444 std::optional<unsigned> Index,
1445 SemanticSignatures &Signature) {
1446 if (CGM.getTarget().getTriple().isSPIRV())
1447 return emitSPIRVUserSemanticStore(B, Source, Decl, Semantic, Index);
1448
1449 if (CGM.getTarget().getTriple().isDXIL())
1450 return emitDXILUserSemanticStore(B, Source, Decl, Semantic, Index,
1451 Signature);
1452
1453 llvm_unreachable("Unsupported target for user-semantic load.");
1454}
1455
1457 IRBuilder<> &B, llvm::Type *Type, const clang::DeclaratorDecl *Decl,
1458 HLSLAppliedSemanticAttr *Semantic,
1459 llvm::dxbc::PSV::SemanticKind SemanticKind,
1460 llvm::Triple::EnvironmentType Stage, std::optional<unsigned> Index,
1461 SemanticSignatures &Signature) {
1462 switch (SemanticKind) {
1463 case llvm::dxbc::PSV::SemanticKind::GroupIndex: {
1464 assert(llvm::is_contained({llvm::Triple::Compute, llvm::Triple::Mesh,
1465 llvm::Triple::Amplification},
1466 Stage) &&
1467 "SV_GroupIndex is in an unavailable stage and should have been "
1468 "diagnosed by Sema");
1469 assert(Stage != llvm::Triple::Mesh &&
1470 Stage != llvm::Triple::Amplification &&
1471 "FIXME: SV_GroupIndex is not yet implemented for this shader "
1472 "stage");
1473 llvm::Function *GroupIndex =
1474 CGM.getIntrinsic(getFlattenedThreadIdInGroupIntrinsic());
1475 return B.CreateCall(FunctionCallee(GroupIndex));
1476 }
1477 case llvm::dxbc::PSV::SemanticKind::DispatchThreadID: {
1478 assert(llvm::is_contained({llvm::Triple::Compute, llvm::Triple::Mesh,
1479 llvm::Triple::Amplification},
1480 Stage) &&
1481 "SV_DispatchThreadID is in an unavailable stage and should have "
1482 "been diagnosed by Sema");
1483 assert(Stage != llvm::Triple::Mesh &&
1484 Stage != llvm::Triple::Amplification &&
1485 "FIXME: SV_DispatchThreadID is not yet implemented for this "
1486 "shader stage");
1487 llvm::Intrinsic::ID IntrinID = getThreadIdIntrinsic();
1488 llvm::Function *ThreadIDIntrinsic =
1489 llvm::Intrinsic::isOverloaded(IntrinID)
1490 ? CGM.getIntrinsic(IntrinID, {CGM.Int32Ty})
1491 : CGM.getIntrinsic(IntrinID);
1492 return buildVectorInput(B, ThreadIDIntrinsic, Type);
1493 }
1494 case llvm::dxbc::PSV::SemanticKind::GroupThreadID: {
1495 assert(llvm::is_contained({llvm::Triple::Compute, llvm::Triple::Mesh,
1496 llvm::Triple::Amplification},
1497 Stage) &&
1498 "SV_GroupThreadID is in an unavailable stage and should have been "
1499 "diagnosed by Sema");
1500 assert(Stage != llvm::Triple::Mesh &&
1501 Stage != llvm::Triple::Amplification &&
1502 "FIXME: SV_GroupThreadID is not yet implemented for this shader "
1503 "stage");
1504 llvm::Intrinsic::ID IntrinID = getGroupThreadIdIntrinsic();
1505 llvm::Function *GroupThreadIDIntrinsic =
1506 llvm::Intrinsic::isOverloaded(IntrinID)
1507 ? CGM.getIntrinsic(IntrinID, {CGM.Int32Ty})
1508 : CGM.getIntrinsic(IntrinID);
1509 return buildVectorInput(B, GroupThreadIDIntrinsic, Type);
1510 }
1511 case llvm::dxbc::PSV::SemanticKind::GroupID: {
1512 assert(llvm::is_contained({llvm::Triple::Compute, llvm::Triple::Mesh,
1513 llvm::Triple::Amplification},
1514 Stage) &&
1515 "SV_GroupID is in an unavailable stage and should have been "
1516 "diagnosed by Sema");
1517 assert(Stage != llvm::Triple::Mesh &&
1518 Stage != llvm::Triple::Amplification &&
1519 "FIXME: SV_GroupID is not yet implemented for this shader stage");
1520 llvm::Intrinsic::ID IntrinID = getGroupIdIntrinsic();
1521 llvm::Function *GroupIDIntrinsic =
1522 llvm::Intrinsic::isOverloaded(IntrinID)
1523 ? CGM.getIntrinsic(IntrinID, {CGM.Int32Ty})
1524 : CGM.getIntrinsic(IntrinID);
1525 return buildVectorInput(B, GroupIDIntrinsic, Type);
1526 }
1527 case llvm::dxbc::PSV::SemanticKind::Position:
1528 assert(llvm::is_contained({llvm::Triple::Hull, llvm::Triple::Domain,
1529 llvm::Triple::Geometry, llvm::Triple::Pixel},
1530 Stage) &&
1531 "SV_Position is in an unavailable stage and should have been "
1532 "diagnosed by Sema");
1533 assert(Stage != llvm::Triple::Hull && Stage != llvm::Triple::Domain &&
1534 Stage != llvm::Triple::Geometry &&
1535 "FIXME: loading SV_Position is not yet implemented for this "
1536 "shader stage");
1537 if (CGM.getTarget().getTriple().isSPIRV())
1538 return createSPIRVBuiltinLoad(B, CGM.getModule(), Type,
1539 Semantic->getAttrName()->getName(),
1540 /* BuiltIn::FragCoord */ 15);
1541 if (CGM.getTarget().getTriple().isDXIL())
1542 return emitDXILUserSemanticLoad(B, Type, Decl, Semantic, Index,
1543 Signature);
1544 break;
1545 case llvm::dxbc::PSV::SemanticKind::VertexID:
1546 assert(Stage == llvm::Triple::Vertex &&
1547 "SV_VertexID is in an unavailable stage and should have been "
1548 "diagnosed by Sema");
1549 if (CGM.getTarget().getTriple().isSPIRV())
1550 return createSPIRVBuiltinLoad(B, CGM.getModule(), Type,
1551 Semantic->getAttrName()->getName(),
1552 /* BuiltIn::VertexIndex */ 42);
1553 if (CGM.getTarget().getTriple().isDXIL())
1554 return emitDXILUserSemanticLoad(B, Type, Decl, Semantic, Index,
1555 Signature);
1556 break;
1557 case llvm::dxbc::PSV::SemanticKind::InstanceID:
1558 assert(Stage == llvm::Triple::Vertex &&
1559 "SV_InstanceID is in an unavailable stage and should have been "
1560 "diagnosed by Sema");
1561 if (CGM.getTarget().getTriple().isSPIRV())
1562 return createSPIRVBuiltinLoad(B, CGM.getModule(), Type,
1563 Semantic->getAttrName()->getName(),
1564 /* BuiltIn::InstanceIndex */ 43);
1565 if (CGM.getTarget().getTriple().isDXIL())
1566 return emitDXILUserSemanticLoad(B, Type, Decl, Semantic, Index,
1567 Signature);
1568 break;
1569 default:
1570 break;
1571 }
1572
1573 llvm_unreachable(
1574 "Load hasn't been implemented yet for this system semantic. FIXME");
1575}
1576
1577static void createSPIRVBuiltinStore(IRBuilder<> &B, llvm::Module &M,
1578 llvm::Value *Source, const Twine &Name,
1579 unsigned BuiltInID) {
1580 auto *GV = new llvm::GlobalVariable(
1581 M, Source->getType(), /* isConstant= */ false,
1582 llvm::GlobalValue::ExternalLinkage,
1583 /* Initializer= */ nullptr, Name, /* insertBefore= */ nullptr,
1584 llvm::GlobalVariable::GeneralDynamicTLSModel,
1585 /* AddressSpace */ 8, /* isExternallyInitialized= */ false);
1586 addSPIRVBuiltinDecoration(GV, BuiltInID);
1587 GV->setVisibility(llvm::GlobalValue::HiddenVisibility);
1588 B.CreateStore(Source, GV);
1589}
1590
1592 IRBuilder<> &B, llvm::Value *Source, const clang::DeclaratorDecl *Decl,
1593 HLSLAppliedSemanticAttr *Semantic,
1594 llvm::dxbc::PSV::SemanticKind SemanticKind,
1595 llvm::Triple::EnvironmentType Stage, std::optional<unsigned> Index,
1596 SemanticSignatures &Signature) {
1597 switch (SemanticKind) {
1598 case llvm::dxbc::PSV::SemanticKind::Position:
1599 assert(llvm::is_contained({llvm::Triple::Vertex, llvm::Triple::Hull,
1600 llvm::Triple::Domain, llvm::Triple::Geometry,
1601 llvm::Triple::Mesh},
1602 Stage) &&
1603 "SV_Position is in an unavailable stage and should have been "
1604 "diagnosed by Sema");
1605 assert(Stage != llvm::Triple::Hull && Stage != llvm::Triple::Domain &&
1606 Stage != llvm::Triple::Geometry && Stage != llvm::Triple::Mesh &&
1607 "FIXME: storing SV_Position is not yet implemented for this "
1608 "shader stage");
1609 if (CGM.getTarget().getTriple().isDXIL()) {
1610 emitDXILUserSemanticStore(B, Source, Decl, Semantic, Index, Signature);
1611 return;
1612 }
1613 if (CGM.getTarget().getTriple().isSPIRV()) {
1614 createSPIRVBuiltinStore(B, CGM.getModule(), Source,
1615 Semantic->getAttrName()->getName(),
1616 /* BuiltIn::Position */ 0);
1617 return;
1618 }
1619 break;
1620 case llvm::dxbc::PSV::SemanticKind::Target:
1621 assert(Stage == llvm::Triple::Pixel &&
1622 "SV_Target is in an unavailable stage and should have been "
1623 "diagnosed by Sema");
1624 emitUserSemanticStore(B, Source, Decl, Semantic, Index, Signature);
1625 return;
1626 default:
1627 break;
1628 }
1629
1630 llvm_unreachable(
1631 "Store hasn't been implemented yet for this system semantic. FIXME");
1632}
1633
1635 IRBuilder<> &B, const FunctionDecl *FD, llvm::Type *Type,
1636 const clang::DeclaratorDecl *Decl, HLSLAppliedSemanticAttr *Semantic,
1637 SemanticSignatures &Signature) {
1638
1639 std::optional<unsigned> Index = Semantic->getSemanticIndex();
1640 llvm::dxbc::PSV::SemanticKind SemanticKind =
1641 llvm::hlsl::getSemanticKind(Semantic->getAttrName()->getName());
1642 const auto *ShaderAttr = FD->getAttr<HLSLShaderAttr>();
1643 assert(ShaderAttr && "Entry point has no shader attribute");
1644 llvm::hlsl::SemanticInterpretation Interpretation =
1645 llvm::hlsl::getInterpretationKind(SemanticKind, ShaderAttr->getType(),
1646 llvm::hlsl::IOType::In);
1647 assert(Interpretation != llvm::hlsl::SemanticInterpretation::Invalid &&
1648 "invalid semantic should have been diagnosed by Sema");
1649 if (Interpretation == llvm::hlsl::SemanticInterpretation::Arbitrary)
1650 return emitUserSemanticLoad(B, FD, Type, Decl, Semantic, Index, Signature);
1651 return emitSystemSemanticLoad(B, Type, Decl, Semantic, SemanticKind,
1652 ShaderAttr->getType(), Index, Signature);
1653}
1654
1656 const FunctionDecl *FD,
1657 llvm::Value *Source,
1659 HLSLAppliedSemanticAttr *Semantic,
1660 SemanticSignatures &Signature) {
1661 std::optional<unsigned> Index = Semantic->getSemanticIndex();
1662 llvm::dxbc::PSV::SemanticKind SemanticKind =
1663 llvm::hlsl::getSemanticKind(Semantic->getAttrName()->getName());
1664 const auto *ShaderAttr = FD->getAttr<HLSLShaderAttr>();
1665 assert(ShaderAttr && "Entry point has no shader attribute");
1666
1667 llvm::hlsl::SemanticInterpretation Interpretation =
1668 llvm::hlsl::getInterpretationKind(SemanticKind, ShaderAttr->getType(),
1669 llvm::hlsl::IOType::Out);
1670 assert(Interpretation != llvm::hlsl::SemanticInterpretation::Invalid &&
1671 "invalid semantic should have been diagnosed by Sema");
1672
1673 if (Interpretation == llvm::hlsl::SemanticInterpretation::Arbitrary)
1674 return emitUserSemanticStore(B, Source, Decl, Semantic, Index, Signature);
1675 emitSystemSemanticStore(B, Source, Decl, Semantic, SemanticKind,
1676 ShaderAttr->getType(), Index, Signature);
1677}
1678
1679std::pair<llvm::Value *, specific_attr_iterator<HLSLAppliedSemanticAttr>>
1681 IRBuilder<> &B, const FunctionDecl *FD, llvm::Type *Type,
1685 SemanticSignatures &Signature,
1686 llvm::hlsl::InterpolationModifier Modifiers) {
1687 const llvm::StructType *ST = cast<StructType>(Type);
1688 const clang::RecordDecl *RD = Decl->getType()->getAsRecordDecl();
1689
1690 assert(RD->getNumFields() == ST->getNumElements());
1691
1692 llvm::Value *Aggregate = llvm::PoisonValue::get(Type);
1693 auto FieldDecl = RD->field_begin();
1694 for (unsigned I = 0; I < ST->getNumElements(); ++I) {
1695 auto [ChildValue, NextAttr] =
1696 handleSemanticLoad(B, FD, ST->getElementType(I), *FieldDecl, AttrBegin,
1697 AttrEnd, Signature, Modifiers);
1698 AttrBegin = NextAttr;
1699 assert(ChildValue);
1700 Aggregate = B.CreateInsertValue(Aggregate, ChildValue, I);
1701 ++FieldDecl;
1702 }
1703
1704 return std::make_pair(Aggregate, AttrBegin);
1705}
1706
1709 IRBuilder<> &B, const FunctionDecl *FD, llvm::Value *Source,
1713 SemanticSignatures &Signature,
1714 llvm::hlsl::InterpolationModifier Modifiers) {
1715
1716 const llvm::StructType *ST = cast<StructType>(Source->getType());
1717
1718 const clang::RecordDecl *RD = nullptr;
1719 if (const FunctionDecl *FD = dyn_cast<FunctionDecl>(Decl))
1721 else
1722 RD = Decl->getType()->getAsRecordDecl();
1723 assert(RD);
1724
1725 assert(RD->getNumFields() == ST->getNumElements());
1726
1727 auto FieldDecl = RD->field_begin();
1728 for (unsigned I = 0; I < ST->getNumElements(); ++I, ++FieldDecl) {
1729 llvm::Value *Extract = B.CreateExtractValue(Source, I);
1730 AttrBegin = handleSemanticStore(B, FD, Extract, *FieldDecl, AttrBegin,
1731 AttrEnd, Signature, Modifiers);
1732 }
1733
1734 return AttrBegin;
1735}
1736
1737std::pair<llvm::Value *, specific_attr_iterator<HLSLAppliedSemanticAttr>>
1739 IRBuilder<> &B, const FunctionDecl *FD, llvm::Type *Type,
1743 SemanticSignatures &Signature,
1744 llvm::hlsl::InterpolationModifier Modifiers) {
1745 assert(AttrBegin != AttrEnd);
1746 // Pass the enclosing declaration's mask down the traversal, replacing (not
1747 // merging) it when an inner field has its own interpolation modifiers.
1748 if (const auto *A = Decl->getAttr<HLSLInterpolationModifierAttr>())
1749 Modifiers =
1750 static_cast<llvm::hlsl::InterpolationModifier>(A->getModifiers());
1751 if (Type->isStructTy())
1752 return handleStructSemanticLoad(B, FD, Type, Decl, AttrBegin, AttrEnd,
1753 Signature, Modifiers);
1754
1755 HLSLAppliedSemanticAttr *Attr = *AttrBegin;
1756 ++AttrBegin;
1757 size_t PreviousSize = Signature.size();
1758 llvm::Value *Value =
1759 handleScalarSemanticLoad(B, FD, Type, Decl, Attr, Signature);
1760 // Intrinsic-only system values and SPIR-V loads do not add DXIL signature
1761 // elements. Non-pixel inputs retain Undefined.
1762 if (Signature.size() != PreviousSize) {
1763 auto &Element = Signature.back();
1764 Element.InterpMode = llvm::hlsl::normalizeInterpolationMode(
1765 llvm::hlsl::getInterpolationMode(Modifiers), Element.CompType,
1766 Element.SemanticKind, FD->getAttr<HLSLShaderAttr>()->getType(),
1767 llvm::hlsl::IOType::In);
1768 }
1769 return std::make_pair(Value, AttrBegin);
1770}
1771
1774 IRBuilder<> &B, const FunctionDecl *FD, llvm::Value *Source,
1778 SemanticSignatures &Signature,
1779 llvm::hlsl::InterpolationModifier Modifiers) {
1780 assert(AttrBegin != AttrEnd);
1781 // An inner field overrides the enclosing return declaration's modifiers.
1782 if (const auto *A = Decl->getAttr<HLSLInterpolationModifierAttr>())
1783 Modifiers =
1784 static_cast<llvm::hlsl::InterpolationModifier>(A->getModifiers());
1785 if (Source->getType()->isStructTy())
1786 return handleStructSemanticStore(B, FD, Source, Decl, AttrBegin, AttrEnd,
1787 Signature, Modifiers);
1788
1789 HLSLAppliedSemanticAttr *Attr = *AttrBegin;
1790 ++AttrBegin;
1791 size_t PreviousSize = Signature.size();
1792 handleScalarSemanticStore(B, FD, Source, Decl, Attr, Signature);
1793 if (Signature.size() != PreviousSize) {
1794 auto &Element = Signature.back();
1795 Element.InterpMode = llvm::hlsl::normalizeInterpolationMode(
1796 llvm::hlsl::getInterpolationMode(Modifiers), Element.CompType,
1797 Element.SemanticKind, FD->getAttr<HLSLShaderAttr>()->getType(),
1798 llvm::hlsl::IOType::Out);
1799 }
1800 return AttrBegin;
1801}
1802
1804 llvm::Function *Fn) {
1807
1808 llvm::Module &M = CGM.getModule();
1809 llvm::LLVMContext &Ctx = M.getContext();
1810 auto *EntryTy = llvm::FunctionType::get(llvm::Type::getVoidTy(Ctx), false);
1811 Function *EntryFn =
1812 Function::Create(EntryTy, Function::ExternalLinkage, FD->getName(), &M);
1813
1814 // Copy function attributes over, we have no argument or return attributes
1815 // that can be valid on the real entry.
1816 AttributeList NewAttrs = AttributeList::get(Ctx, AttributeList::FunctionIndex,
1817 Fn->getAttributes().getFnAttrs());
1818 EntryFn->setAttributes(NewAttrs);
1819 setHLSLEntryAttributes(FD, EntryFn);
1820
1821 // Set the called function as internal linkage.
1822 Fn->setLinkage(GlobalValue::InternalLinkage);
1823
1824 BasicBlock *BB = BasicBlock::Create(Ctx, "entry", EntryFn);
1825 IRBuilder<> B(BB);
1827
1829 if (CGM.shouldEmitConvergenceTokens()) {
1830 assert(EntryFn->isConvergent());
1831 llvm::Value *I =
1832 B.CreateIntrinsic(llvm::Intrinsic::experimental_convergence_entry, {});
1833 llvm::Value *bundleArgs[] = {I};
1834 OB.emplace_back("convergencectrl", bundleArgs);
1835 }
1836
1838
1839 unsigned SRetOffset = 0;
1840 for (const auto &Param : Fn->args()) {
1841 if (Param.hasStructRetAttr()) {
1842 SRetOffset = 1;
1843 llvm::Type *VarType = Param.getParamStructRetType();
1844 llvm::Value *Var =
1845 CGM.getLangOpts().EmitLogicalPointer
1846 ? cast<Instruction>(B.CreateStructuredAlloca(VarType))
1847 : cast<Instruction>(B.CreateAlloca(VarType));
1848 OutputSemantic.push_back(std::make_pair(Var, VarType));
1849 Args.push_back(Var);
1850 continue;
1851 }
1852
1853 const ParmVarDecl *PD = FD->getParamDecl(Param.getArgNo() - SRetOffset);
1854 llvm::Value *SemanticValue = nullptr;
1855 // FIXME: support inout/out parameters for semantics.
1856 if ([[maybe_unused]] HLSLParamModifierAttr *MA =
1857 PD->getAttr<HLSLParamModifierAttr>()) {
1858 llvm_unreachable("Not handled yet");
1859 } else {
1860 llvm::Type *ParamType = nullptr;
1861 if (Param.hasByValAttr())
1862 ParamType = Param.getParamByValType();
1863 else if (PD->getType()->isRecordType())
1864 ParamType = CGM.getTypes().ConvertType(PD->getType());
1865 else
1866 ParamType = Param.getType();
1867
1868 auto AttrBegin = PD->specific_attr_begin<HLSLAppliedSemanticAttr>();
1869 auto AttrEnd = PD->specific_attr_end<HLSLAppliedSemanticAttr>();
1870 auto Result = handleSemanticLoad(B, FD, ParamType, PD, AttrBegin, AttrEnd,
1871 InputSignature);
1872 SemanticValue = Result.first;
1873 if (!SemanticValue)
1874 return;
1875 if (Param.hasByValAttr() || PD->getType()->isRecordType()) {
1876 llvm::Value *Var =
1877 CGM.getLangOpts().EmitLogicalPointer
1878 ? cast<Instruction>(B.CreateStructuredAlloca(ParamType))
1879 : cast<Instruction>(B.CreateAlloca(ParamType));
1880 B.CreateStore(SemanticValue, Var);
1881 SemanticValue = Var;
1882 }
1883 }
1884
1885 assert(SemanticValue);
1886 Args.push_back(SemanticValue);
1887 }
1888
1889 CallInst *CI = B.CreateCall(FunctionCallee(Fn), Args, OB);
1890 CI->setCallingConv(Fn->getCallingConv());
1891
1892 if (Fn->getReturnType() != CGM.VoidTy)
1893 // Element type is unused, so set to dummy value (NULL).
1894 OutputSemantic.push_back(std::make_pair(CI, nullptr));
1895
1896 for (auto &SourcePair : OutputSemantic) {
1897 llvm::Value *Source = SourcePair.first;
1898 llvm::Type *ElementType = SourcePair.second;
1899 AllocaInst *AI = dyn_cast<AllocaInst>(Source);
1900 llvm::Value *SourceValue = AI ? B.CreateLoad(ElementType, Source) : Source;
1901
1902 auto AttrBegin = FD->specific_attr_begin<HLSLAppliedSemanticAttr>();
1903 auto AttrEnd = FD->specific_attr_end<HLSLAppliedSemanticAttr>();
1904 handleSemanticStore(B, FD, SourceValue, FD, AttrBegin, AttrEnd,
1905 OutputSignature);
1906 }
1907
1908 B.CreateRetVoid();
1909
1910 // Add and identify root signature to function, if applicable
1911 for (const Attr *Attr : FD->getAttrs()) {
1912 if (const auto *RSAttr = dyn_cast<RootSignatureAttr>(Attr)) {
1913 auto *RSDecl = RSAttr->getSignatureDecl();
1914 addRootSignatureMD(RSDecl->getVersion(), RSDecl->getRootElements(),
1915 EntryFn, M);
1916 }
1917 }
1918
1919 if (CGM.getTarget().getTriple().isDXIL()) {
1920 // Use the entry's shader stage, not the target environment, which may be
1921 // 'library' when compiling multiple entry points.
1922 auto Stage = FD->getAttr<HLSLShaderAttr>()->getType();
1924 auto Mode = CGM.getCodeGenOpts().getHLSLSemanticSignaturePacking();
1925 for (auto IOTy : {llvm::hlsl::IOType::In, llvm::hlsl::IOType::Out}) {
1926 bool IsOutput = IOTy == llvm::hlsl::IOType::Out;
1927 auto &Signature = IsOutput ? OutputSignature : InputSignature;
1928 auto Packed = packSemanticSignature(Signature, Stage, IOTy, Mode,
1929 CGM.getLangOpts().NativeHalfType);
1930 if (!Packed) {
1931 CGM.getDiags().Report(FD->getLocation(),
1932 diag::err_hlsl_signature_packing)
1933 << IsOutput << llvm::toString(Packed.takeError());
1934 return;
1935 }
1936 // Library entry points retain stage-specific packing without warnings.
1937 if (Mode != PackingMode::Default &&
1938 CGM.getTarget().getTriple().getEnvironment() !=
1939 llvm::Triple::Library &&
1940 ((Stage == llvm::Triple::Vertex && !IsOutput) ||
1941 (Stage == llvm::Triple::Pixel && IsOutput)))
1942 CGM.getDiags().Report(FD->getLocation(),
1943 diag::warn_hlsl_signature_packing_ignored)
1944 << (Mode == PackingMode::Optimized ? "optimized" : "prefix-stable")
1945 << IsOutput;
1946 }
1947 }
1948
1949 addSemanticSignatureMD(InputSignature, OutputSignature, EntryFn, M);
1950}
1951
1952static void gatherFunctions(SmallVectorImpl<Function *> &Fns, llvm::Module &M,
1953 bool CtorOrDtor) {
1954 const auto *GV =
1955 M.getNamedGlobal(CtorOrDtor ? "llvm.global_ctors" : "llvm.global_dtors");
1956 if (!GV)
1957 return;
1958 const auto *CA = dyn_cast<ConstantArray>(GV->getInitializer());
1959 if (!CA)
1960 return;
1961 // The global_ctor array elements are a struct [Priority, Fn *, COMDat].
1962 // HLSL neither supports priorities or COMDat values, so we will check those
1963 // in an assert but not handle them.
1964
1965 for (const auto &Ctor : CA->operands()) {
1967 continue;
1968 ConstantStruct *CS = cast<ConstantStruct>(Ctor);
1969
1970 assert(cast<ConstantInt>(CS->getOperand(0))->getValue() == 65535 &&
1971 "HLSL doesn't support setting priority for global ctors.");
1972 assert(isa<ConstantPointerNull>(CS->getOperand(2)) &&
1973 "HLSL doesn't support COMDat for global ctors.");
1974 Fns.push_back(cast<Function>(CS->getOperand(1)));
1975 }
1976}
1977
1979 llvm::Module &M = CGM.getModule();
1982 gatherFunctions(CtorFns, M, true);
1983 gatherFunctions(DtorFns, M, false);
1984
1985 // Insert a call to the global constructor at the beginning of the entry block
1986 // to externally exported functions. This is a bit of a hack, but HLSL allows
1987 // global constructors, but doesn't support driver initialization of globals.
1988 for (auto &F : M.functions()) {
1989 if (!F.hasFnAttribute("hlsl.shader"))
1990 continue;
1991 auto *Token = getConvergenceToken(F.getEntryBlock());
1992 Instruction *IP = &*F.getEntryBlock().begin();
1994 if (Token) {
1995 llvm::Value *bundleArgs[] = {Token};
1996 OB.emplace_back("convergencectrl", bundleArgs);
1997 IP = Token->getNextNode();
1998 }
1999 IRBuilder<> B(IP);
2000 for (auto *Fn : CtorFns) {
2001 auto CI = B.CreateCall(FunctionCallee(Fn), {}, OB);
2002 CI->setCallingConv(Fn->getCallingConv());
2003 }
2004
2005 // Insert global dtors before the terminator of the last instruction
2006 B.SetInsertPoint(F.back().getTerminator());
2007 for (auto *Fn : DtorFns) {
2008 auto CI = B.CreateCall(FunctionCallee(Fn), {}, OB);
2009 CI->setCallingConv(Fn->getCallingConv());
2010 }
2011 }
2012
2013 // No need to keep global ctors/dtors for non-lib profile after call to
2014 // ctors/dtors added for entry.
2015 Triple T(M.getTargetTriple());
2016 if (T.getEnvironment() != Triple::EnvironmentType::Library) {
2017 if (auto *GV = M.getNamedGlobal("llvm.global_ctors"))
2018 GV->eraseFromParent();
2019 if (auto *GV = M.getNamedGlobal("llvm.global_dtors"))
2020 GV->eraseFromParent();
2021 }
2022}
2023
2024static void initializeBuffer(CodeGenModule &CGM, llvm::GlobalVariable *GV,
2025 Intrinsic::ID IntrID,
2027
2028 LLVMContext &Ctx = CGM.getLLVMContext();
2029 llvm::Function *InitResFunc =
2030 llvm::Function::Create(llvm::FunctionType::get(CGM.VoidTy, false),
2031 llvm::GlobalValue::InternalLinkage,
2032 "_init_buffer_" + GV->getName(), CGM.getModule());
2033 InitResFunc->addFnAttr(llvm::Attribute::AlwaysInline);
2034
2035 llvm::BasicBlock *EntryBB =
2036 llvm::BasicBlock::Create(Ctx, "entry", InitResFunc);
2037 CGBuilderTy Builder(CGM, Ctx);
2038 const DataLayout &DL = CGM.getModule().getDataLayout();
2039 Builder.SetInsertPoint(EntryBB);
2040
2041 // Make sure the global variable is buffer resource handle
2042 llvm::Type *HandleTy = GV->getValueType();
2043 assert(HandleTy->isTargetExtTy() && "unexpected type of the buffer global");
2044
2045 llvm::Value *CreateHandle = Builder.CreateIntrinsic(
2046 /*ReturnType=*/HandleTy, IntrID, Args, nullptr,
2047 Twine(GV->getName()).concat("_h"));
2048
2049 Builder.CreateAlignedStore(CreateHandle, GV, GV->getPointerAlignment(DL));
2050 Builder.CreateRetVoid();
2051
2052 CGM.AddCXXGlobalInit(InitResFunc);
2053}
2054
2055void CGHLSLRuntime::initializeBufferFromBinding(const HLSLBufferDecl *BufDecl,
2056 llvm::GlobalVariable *GV) {
2057 ResourceBindingAttrs Binding(BufDecl);
2058 assert(Binding.hasBinding() &&
2059 "cbuffer/tbuffer should always have resource binding attribute");
2060
2061 auto *Index = llvm::ConstantInt::get(CGM.IntTy, 0);
2062 auto *RangeSize = llvm::ConstantInt::get(CGM.IntTy, 1);
2063 auto *Space = llvm::ConstantInt::get(CGM.IntTy, Binding.getSpace());
2064 Value *Name = buildNameForResource(BufDecl->getName(), CGM);
2065
2066 // buffer with explicit binding
2067 if (Binding.isExplicit()) {
2068 llvm::Intrinsic::ID IntrinsicID =
2069 CGM.getHLSLRuntime().getCreateHandleFromBindingIntrinsic();
2070 auto *RegSlot = llvm::ConstantInt::get(CGM.IntTy, Binding.getSlot());
2071 SmallVector<Value *> Args{Space, RegSlot, RangeSize, Index, Name};
2072 initializeBuffer(CGM, GV, IntrinsicID, Args);
2073 } else {
2074 // buffer with implicit binding
2075 llvm::Intrinsic::ID IntrinsicID =
2076 CGM.getHLSLRuntime().getCreateHandleFromImplicitBindingIntrinsic();
2077 auto *OrderID =
2078 llvm::ConstantInt::get(CGM.IntTy, Binding.getImplicitOrderID());
2079 SmallVector<Value *> Args{OrderID, Space, RangeSize, Index, Name};
2080 initializeBuffer(CGM, GV, IntrinsicID, Args);
2081 }
2082}
2083
2085 llvm::GlobalVariable *GV) {
2086 if (auto Attr = VD->getAttr<HLSLVkExtBuiltinInputAttr>())
2087 addSPIRVBuiltinDecoration(GV, Attr->getBuiltIn());
2088 if (auto Attr = VD->getAttr<HLSLVkExtBuiltinOutputAttr>())
2089 addSPIRVBuiltinDecoration(GV, Attr->getBuiltIn());
2090}
2091
2092llvm::Instruction *CGHLSLRuntime::getConvergenceToken(BasicBlock &BB) {
2093 if (!CGM.shouldEmitConvergenceTokens())
2094 return nullptr;
2095
2096 auto E = BB.end();
2097 for (auto I = BB.begin(); I != E; ++I) {
2098 auto *II = dyn_cast<llvm::IntrinsicInst>(&*I);
2099 if (II && llvm::isConvergenceControlIntrinsic(II->getIntrinsicID())) {
2100 return II;
2101 }
2102 }
2103 llvm_unreachable("Convergence token should have been emitted.");
2104 return nullptr;
2105}
2106
2107class OpaqueValueVisitor : public RecursiveASTVisitor<OpaqueValueVisitor> {
2108public:
2112
2114 // These need to be bound in CodeGenFunction::EmitHLSLOutArgLValues
2115 // or CodeGenFunction::EmitHLSLOutArgExpr. If they are part of this
2116 // traversal, the temporary containing the copy out will not have
2117 // been created yet.
2118 return false;
2119 }
2120
2122 // Traverse the source expression first.
2123 if (E->getSourceExpr())
2125
2126 // Then add this OVE if we haven't seen it before.
2127 if (Visited.insert(E).second)
2128 OVEs.push_back(E);
2129
2130 return true;
2131 }
2132};
2133
2135 InitListExpr *E) {
2136
2137 typedef CodeGenFunction::OpaqueValueMappingData OpaqueValueMappingData;
2138 OpaqueValueVisitor Visitor;
2139 Visitor.TraverseStmt(E);
2140 for (auto *OVE : Visitor.OVEs) {
2141 if (CGF.isOpaqueValueEmitted(OVE))
2142 continue;
2143 if (OpaqueValueMappingData::shouldBindAsLValue(OVE)) {
2144 LValue LV = CGF.EmitLValue(OVE->getSourceExpr());
2145 OpaqueValueMappingData::bind(CGF, OVE, LV);
2146 } else {
2147 RValue RV = CGF.EmitAnyExpr(OVE->getSourceExpr());
2148 OpaqueValueMappingData::bind(CGF, OVE, RV);
2149 }
2150 }
2151}
2152
2154 const ArraySubscriptExpr *ArraySubsExpr, CodeGenFunction &CGF) {
2155 assert((ArraySubsExpr->getType()->isHLSLResourceRecord() ||
2156 ArraySubsExpr->getType()->isHLSLResourceRecordArray()) &&
2157 "expected resource array subscript expression");
2158
2159 // Let clang codegen handle local and static resource array subscripts,
2160 // or when the subscript references on opaque expression (as part of
2161 // ArrayInitLoopExpr AST node).
2162 const VarDecl *ArrayDecl = dyn_cast_or_null<VarDecl>(
2163 getArrayDecl(CGF.CGM.getContext(), ArraySubsExpr));
2164 if (!ArrayDecl || !ArrayDecl->hasGlobalStorage() ||
2165 ArrayDecl->getStorageClass() == SC_Static)
2166 return std::nullopt;
2167
2168 // get the resource array type
2169 ASTContext &AST = ArrayDecl->getASTContext();
2170 const Type *ResArrayTy = ArrayDecl->getType().getTypePtr();
2171 assert(ResArrayTy->isHLSLResourceRecordArray() &&
2172 "expected array of resource classes");
2173
2174 // Iterate through all nested array subscript expressions to calculate
2175 // the index in the flattened resource array (if this is a multi-
2176 // dimensional array). The index is calculated as a sum of all indices
2177 // multiplied by the total size of the array at that level.
2178 Value *Index = nullptr;
2179 const ArraySubscriptExpr *ASE = ArraySubsExpr;
2180 while (ASE != nullptr) {
2181 Value *SubIndex = CGF.EmitScalarExpr(ASE->getIdx());
2182 if (const auto *ArrayTy =
2183 dyn_cast<ConstantArrayType>(ASE->getType().getTypePtr())) {
2184 Value *Multiplier = llvm::ConstantInt::get(
2185 CGM.IntTy, AST.getConstantArrayElementCount(ArrayTy));
2186 SubIndex = CGF.Builder.CreateMul(SubIndex, Multiplier);
2187 }
2188 Index = Index ? CGF.Builder.CreateAdd(Index, SubIndex) : SubIndex;
2189 ASE = dyn_cast<ArraySubscriptExpr>(ASE->getBase()->IgnoreParenImpCasts());
2190 }
2191
2192 // Find binding info for the resource array. For implicit binding
2193 // an HLSLResourceBindingAttr should have been added by SemaHLSL.
2194 ResourceBindingAttrs Binding(ArrayDecl);
2195 assert(Binding.hasBinding() &&
2196 "resource array must have a binding attribute");
2197
2198 // Find the individual resource type.
2199 QualType ResultTy = ArraySubsExpr->getType();
2200 QualType ResourceTy =
2201 ResultTy->isArrayType() ? AST.getBaseElementType(ResultTy) : ResultTy;
2202
2203 // Create a temporary variable for the result, which is either going
2204 // to be a single resource instance or a local array of resources (we need to
2205 // return an LValue).
2206 RawAddress TmpVar = CGF.CreateMemTempWithoutCast(ResultTy);
2207 if (CGF.EmitLifetimeStart(TmpVar.getPointer()))
2209 NormalEHLifetimeMarker, TmpVar);
2210
2215
2216 // Calculate total array size (= range size).
2217 llvm::Value *Range = llvm::ConstantInt::getSigned(
2218 CGM.IntTy, getTotalArraySize(AST, ResArrayTy));
2219
2220 // If the result of the subscript operation is a single resource, call the
2221 // constructor.
2222 if (ResultTy == ResourceTy) {
2223 CallArgList Args;
2224 CXXMethodDecl *CreateMethod = lookupResourceInitMethodAndSetupArgs(
2225 CGF.CGM, ResourceTy->getAsCXXRecordDecl(), Range, Index,
2226 ArrayDecl->getName(), Binding, Args);
2227
2228 if (!CreateMethod) {
2229 // This can happen if someone creates an array of structs that looks like
2230 // an HLSL resource record array but it does not have the required static
2231 // create method. No binding will be generated for it.
2232 assert(!ResourceTy->getAsCXXRecordDecl()->isImplicit() &&
2233 "create method lookup should always succeed for built-in resource "
2234 "records");
2235 return std::nullopt;
2236 }
2237
2238 callResourceInitMethod(CGF, CreateMethod, Args, ValueSlot.getAddress());
2239
2240 } else {
2241 // The result of the subscript operation is a local resource array which
2242 // needs to be initialized.
2243 const ConstantArrayType *ArrayTy =
2245 std::optional<llvm::Value *> EndIndex = initializeResourceArrayFromGlobal(
2246 CGF, ResourceTy->getAsCXXRecordDecl(), ArrayTy, ValueSlot, Range, Index,
2247 ArrayDecl->getName(), Binding, {llvm::ConstantInt::get(CGM.IntTy, 0)});
2248 if (!EndIndex)
2249 return std::nullopt;
2250 }
2251 return CGF.MakeAddrLValue(TmpVar, ResultTy, AlignmentSource::Decl);
2252}
2253
2254// Initialize all resources of a global resource array into provided slot.
2255bool CGHLSLRuntime::initializeGlobalResourceArray(CodeGenFunction &CGF,
2256 const VarDecl *ArrayDecl,
2257 AggValueSlot &DestSlot) {
2258 assert(ArrayDecl->getType()->isHLSLResourceRecordArray() &&
2259 ArrayDecl->hasGlobalStorage() &&
2260 ArrayDecl->getStorageClass() != SC_Static &&
2261 "expected global non-static resource array");
2262
2263 // Find binding info for the resource array. For implicit binding
2264 // the HLSLResourceBindingAttr should have been added by SemaHLSL.
2265 ResourceBindingAttrs Binding(ArrayDecl);
2266 assert(Binding.hasBinding() &&
2267 "resource array must have a binding attribute");
2268
2269 // Find the individual resource type.
2270 ASTContext &AST = ArrayDecl->getASTContext();
2271 QualType ResTy = AST.getBaseElementType(ArrayDecl->getType());
2272 const auto *ResArrayTy =
2274
2275 // Create Value for index and total array size (= range size).
2276 int Size = getTotalArraySize(AST, ResArrayTy);
2277 llvm::Value *Zero = llvm::ConstantInt::get(CGM.IntTy, 0);
2278 llvm::Value *Range = llvm::ConstantInt::get(CGM.IntTy, Size);
2279
2280 // Initialize individual resources in the array into DestSlot.
2281 std::optional<llvm::Value *> EndIndex = initializeResourceArrayFromGlobal(
2282 CGF, ResTy->getAsCXXRecordDecl(), ResArrayTy, DestSlot, Range, Zero,
2283 ArrayDecl->getName(), Binding, {Zero});
2284 return EndIndex.has_value();
2285}
2286
2287// If the expression is a global resource array, initialize all of its resources
2288// into Dest. Returns false if no initialization has been performed and the
2289// array copy should be handled by the default codegen.
2291 AggValueSlot &DestSlot) {
2292 assert(E->getType()->isHLSLResourceRecordArray() &&
2293 "expected resource array");
2294
2295 // Find the array declaration for the expression. Fallback to the default
2296 // handling if it's not a global resource array.
2297 const VarDecl *ArrayDecl =
2298 dyn_cast_or_null<VarDecl>(getArrayDecl(CGF.CGM.getContext(), E));
2299 if (!ArrayDecl || !ArrayDecl->hasGlobalStorage() ||
2300 ArrayDecl->getStorageClass() == SC_Static)
2301 return false;
2302
2303 return initializeGlobalResourceArray(CGF, ArrayDecl, DestSlot);
2304}
2305
2306// If the expression is a global resource array, create a temporary and
2307// initialize all of its resources, and return it as an LValue. Returns nullopt
2308// if no initialization has been performed and the handling should follow the
2309// default path.
2310std::optional<LValue>
2312 const VarDecl *ArrayDecl) {
2313 assert(ArrayDecl->getType()->isHLSLResourceRecordArray() &&
2314 "expected resource array declaration");
2315
2316 if (!ArrayDecl->hasGlobalStorage() ||
2317 ArrayDecl->getStorageClass() == SC_Static)
2318 return std::nullopt;
2319
2320 AggValueSlot TmpArraySlot =
2321 CGF.CreateAggTemp(ArrayDecl->getType(), "tmpResArray");
2322 if (initializeGlobalResourceArray(CGF, ArrayDecl, TmpArraySlot))
2323 return CGF.MakeAddrLValue(TmpArraySlot.getAddress(), ArrayDecl->getType(),
2325 return std::nullopt;
2326}
2327
2329 CodeGenFunction &CGF) {
2330
2331 assert(LV.getType()->isConstantMatrixType() && "expected matrix type");
2333 "expected cbuffer matrix");
2334
2335 QualType MatQualTy = LV.getType();
2336 llvm::Type *LayoutTy = HLSLBufferLayoutBuilder(CGF.CGM).layOutType(MatQualTy);
2337 Address SrcAddr = LV.getAddress();
2338
2339 if (LayoutTy == CGF.ConvertTypeForMem(MatQualTy))
2340 return SrcAddr;
2341
2342 RawAddress DestAlloca =
2343 CGF.CreateMemTempWithoutCast(MatQualTy, "matrix.buf.copy");
2344 HLSLBufferCopyEmitter(CGF, DestAlloca, SrcAddr).emitCopy(MatQualTy);
2345 return DestAlloca;
2346}
2347
2349 const ArraySubscriptExpr *E, CodeGenFunction &CGF,
2350 llvm::function_ref<llvm::Value *(bool Promote)> EmitIdxAfterBase) {
2351 // Find the element type to index by first padding the element type per HLSL
2352 // buffer rules, and then padding out to a 16-byte register boundary if
2353 // necessary.
2354 llvm::Type *LayoutTy =
2356 uint64_t LayoutSizeInBits =
2357 CGM.getDataLayout().getTypeSizeInBits(LayoutTy).getFixedValue();
2358 CharUnits ElementSize = CharUnits::fromQuantity(LayoutSizeInBits / 8);
2359 CharUnits RowAlignedSize = ElementSize.alignTo(CharUnits::fromQuantity(16));
2360 if (RowAlignedSize > ElementSize) {
2361 llvm::Type *Padding = CGM.getTargetCodeGenInfo().getHLSLPadding(
2362 CGM, RowAlignedSize - ElementSize);
2363 assert(Padding && "No padding type for target?");
2364 LayoutTy = llvm::StructType::get(CGF.getLLVMContext(), {LayoutTy, Padding},
2365 /*isPacked=*/true);
2366 }
2367
2368 // If the layout type doesn't introduce any padding, we don't need to do
2369 // anything special.
2370 llvm::Type *OrigTy = CGF.CGM.getTypes().ConvertTypeForMem(E->getType());
2371 if (LayoutTy == OrigTy)
2372 return std::nullopt;
2373
2374 LValueBaseInfo EltBaseInfo;
2375 TBAAAccessInfo EltTBAAInfo;
2376
2377 // Index into the object as-if we have an array of the padded element type,
2378 // and then dereference the element itself to avoid reading padding that may
2379 // be past the end of the in-memory object.
2381 llvm::Value *Idx = EmitIdxAfterBase(/*Promote*/ true);
2382 Indices.push_back(Idx);
2383 Indices.push_back(llvm::ConstantInt::get(CGF.Int32Ty, 0));
2384
2385 if (CGF.getLangOpts().EmitLogicalPointer) {
2386 // The fact that we emit an array-to-pointer decay might be an oversight,
2387 // but for now, we simply ignore it (see #179951).
2388 const CastExpr *CE = cast<CastExpr>(E->getBase());
2389 assert(CE->getCastKind() == CastKind::CK_ArrayToPointerDecay);
2390
2391 LValue LV = CGF.EmitLValue(CE->getSubExpr());
2392 Address Addr = LV.getAddress();
2393 LayoutTy = llvm::ArrayType::get(
2394 LayoutTy,
2395 cast<llvm::ArrayType>(Addr.getElementType())->getNumElements());
2396 auto *GEP = cast<StructuredGEPInst>(CGF.Builder.CreateStructuredGEP(
2397 LayoutTy, Addr.emitRawPointer(CGF), Indices, "cbufferidx"));
2398 Addr =
2399 Address(GEP, GEP->getResultElementType(), RowAlignedSize, KnownNonNull);
2400 return CGF.MakeAddrLValue(Addr, E->getType(), EltBaseInfo, EltTBAAInfo);
2401 }
2402
2403 Address Addr =
2404 CGF.EmitPointerWithAlignment(E->getBase(), &EltBaseInfo, &EltTBAAInfo);
2405 llvm::Value *GEP = CGF.Builder.CreateGEP(LayoutTy, Addr.emitRawPointer(CGF),
2406 Indices, "cbufferidx");
2407 Addr = Address(GEP, Addr.getElementType(), RowAlignedSize, KnownNonNull);
2408 return CGF.MakeAddrLValue(Addr, E->getType(), EltBaseInfo, EltTBAAInfo);
2409}
2410
2411std::optional<LValue>
2413 const MemberExpr *ME) {
2414 assert((ME->getType()->isHLSLResourceRecord() ||
2416 "expected resource member expression");
2417
2418 const VarDecl *ResourceVD =
2419 findAssociatedResourceDeclForStruct(CGF.CGM.getContext(), ME);
2420 if (!ResourceVD)
2421 return std::nullopt;
2422
2423 // Handle member of resource array type.
2424 if (ResourceVD->getType()->isHLSLResourceRecordArray())
2425 return emitGlobalResourceArrayAsLValue(CGF, ResourceVD);
2426
2427 GlobalVariable *ResGV =
2428 cast<GlobalVariable>(CGM.GetAddrOfGlobalVar(ResourceVD));
2429 const DataLayout &DL = CGM.getDataLayout();
2430 llvm::Type *Ty = ResGV->getValueType();
2431 CharUnits Align = CharUnits::fromQuantity(DL.getABITypeAlign(Ty));
2432 Address Addr = Address(ResGV, Ty, Align);
2433 LValue LV = LValue::MakeAddr(Addr, ME->getType(), CGM.getContext(),
2435 CGM.getTBAAAccessInfo(ME->getType()));
2436 return LV;
2437}
2438
2440 const LValue &SrcLV,
2441 AggValueSlot &DestSlot) {
2443 "expected expression in HLSL constant address space");
2444 assert(!E->getType()->isHLSLResourceRecord() &&
2446 "direct accesses to resource types should be handled separately");
2447
2448 if (DestSlot.isIgnored())
2449 return false;
2450
2451 QualType Ty = E->getType();
2452 Address DstPtr = DestSlot.getAddress();
2453 Address SrcPtr = SrcLV.getAddress();
2454
2455 // If there are no intangible types, we don't need to lookup associated
2456 // resources.
2457 if (!Ty->isHLSLIntangibleType())
2458 return HLSLBufferCopyEmitter(CGF, DstPtr, SrcPtr).emitCopy(Ty);
2459
2460 // Handle structs with intangible types by setting the resource fields
2461 // of the destination struct with the resources associated with the global
2462 // struct.
2463 EmbeddedResourceNameBuilder NameBuilder;
2464 const VarDecl *VD = findStructResourceParentDeclAndBuildName(E, NameBuilder);
2465 AssociatedResourcesList AssociatedResources(VD, NameBuilder.getName());
2466
2467 // Callback to fill in the associated resource.
2468 auto EmitResFn = [&](AggValueSlot &ResSlot) {
2469 const VarDecl *ResDecl = AssociatedResources.getNextResource();
2470 assert(ResDecl && "associated resource declaration not found");
2471
2472 // Check that the resource type of dest and src matches.
2473 [[maybe_unused]] llvm::Type *DestType =
2474 ResSlot.getAddress().getElementType();
2475 [[maybe_unused]] llvm::Type *SrcConvertedType =
2476 CGM.getTypes().ConvertTypeForMem(ResDecl->getType());
2477 assert(DestType == SrcConvertedType && "resource slot type mismatch");
2478
2479 if (ResDecl->getType()->isHLSLResourceRecord())
2480 copyGlobalResource(CGF, ResDecl, ResSlot);
2481 else
2482 initializeGlobalResourceArray(CGF, ResDecl, ResSlot);
2483 };
2484
2485 auto Result =
2486 HLSLBufferCopyEmitter(CGF, DstPtr, SrcPtr).emitCopy(Ty, EmitResFn);
2487 assert(AssociatedResources.getNextResource() == nullptr &&
2488 "expected all associated resources to be processed");
2489 return Result;
2490}
2491
2493 const MemberExpr *E) {
2494 LValue Base =
2496 auto *Field = dyn_cast<FieldDecl>(E->getMemberDecl());
2497 assert(Field && "Unexpected access into HLSL buffer");
2498
2499 const RecordDecl *Rec = Field->getParent();
2500
2501 // Work out the buffer layout type to index into.
2502 QualType RecType = CGM.getContext().getCanonicalTagType(Rec);
2503 assert(RecType->isStructureOrClassType() && "Invalid type in HLSL buffer");
2504 // Since this is a member of an object in the buffer and not the buffer's
2505 // struct/class itself, we shouldn't have any offsets on the members we need
2506 // to contend with.
2507 CGHLSLOffsetInfo EmptyOffsets;
2508 llvm::StructType *LayoutTy = HLSLBufferLayoutBuilder(CGM).layOutStruct(
2509 RecType->getAsCanonical<RecordType>(), EmptyOffsets);
2510
2511 // Get the field index for the layout struct, accounting for padding.
2512 unsigned FieldIdx =
2513 CGM.getTypes().getCGRecordLayout(Rec).getLLVMFieldNo(Field);
2514 assert(FieldIdx < LayoutTy->getNumElements() &&
2515 "Layout struct is smaller than member struct");
2516 unsigned Skipped = 0;
2517 for (unsigned I = 0; I <= FieldIdx;) {
2518 llvm::Type *ElementTy = LayoutTy->getElementType(I + Skipped);
2519 if (CGF.CGM.getTargetCodeGenInfo().isHLSLPadding(ElementTy))
2520 ++Skipped;
2521 else
2522 ++I;
2523 }
2524 FieldIdx += Skipped;
2525 assert(FieldIdx < LayoutTy->getNumElements() && "Access out of bounds");
2526
2527 // Now index into the struct, making sure that the type we return is the
2528 // buffer layout type rather than the original type in the AST.
2529 QualType FieldType = Field->getType();
2530 llvm::Type *FieldLLVMTy = CGM.getTypes().ConvertTypeForMem(FieldType);
2532 CGF.CGM.getDataLayout().getABITypeAlign(FieldLLVMTy));
2533
2534 Value *Ptr = CGF.getLangOpts().EmitLogicalPointer
2535 ? CGF.Builder.CreateStructuredGEP(
2536 LayoutTy, Base.getPointer(CGF),
2537 llvm::ConstantInt::get(CGM.IntTy, FieldIdx))
2538 : CGF.Builder.CreateStructGEP(LayoutTy, Base.getPointer(CGF),
2539 FieldIdx, Field->getName());
2540 Address Addr(Ptr, FieldLLVMTy, Align, KnownNonNull);
2541
2542 LValue LV = LValue::MakeAddr(Addr, FieldType, CGM.getContext(),
2544 CGM.getTBAAAccessInfo(FieldType));
2545 LV.getQuals().addCVRQualifiers(Base.getVRQualifiers());
2546
2547 return LV;
2548}
Defines the clang::ASTContext interface.
static llvm::Value * createSPIRVBuiltinLoad(IRBuilder<> &B, llvm::Module &M, llvm::Type *Ty, const Twine &Name, unsigned BuiltInID)
static llvm::dxil::ElementType getSignatureComponentType(CodeGenModule &CGM, QualType Ty)
static QualType getSemanticLeafType(const clang::DeclaratorDecl *Decl)
static void addSPIRVBuiltinDecoration(llvm::GlobalVariable *GV, unsigned BuiltIn)
static llvm::hlsl::SemanticSignatureElement createSemanticSignatureElement(CodeGenModule &CGM, uint32_t SigId, HLSLAppliedSemanticAttr *Semantic, std::optional< unsigned > Index, const SemanticShape &Shape)
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, bool NeedsFlat)
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)
static SemanticShape getSemanticShape(ASTContext &Ctx, QualType Ty)
static bool inputRequiresFlatDecoration(llvm::Type *Ty)
TokenType getType() const
Returns the token's type, e.g.
Result
Implement __builtin_bit_cast and related operations.
llvm::MachO::Record Record
Definition MachO.h:31
llvm::dxbc::PSV::SemanticKind SemanticKind
Definition SemaHLSL.cpp:61
Defines the SourceManager interface.
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:245
SourceManager & getSourceManager()
Definition ASTContext.h:917
const ConstantArrayType * getAsConstantArrayType(QualType T) const
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
static uint64_t getConstantArrayElementCount(const ConstantArrayType *CA)
Return number of (potentially nested) constant array elements.
QualType getHLSLAttributedResourceType(QualType Wrapped, QualType Contained, const HLSLAttributedResourceType::Attributes &Attrs)
CanQualType getCanonicalTagType(const TagDecl *TD) const
unsigned getTargetAddressSpace(LangAS AS) const
ArraySubscriptExpr - [C99 6.5.2.1] Array Subscripting.
Definition Expr.h:2769
QualType getElementType() const
Definition TypeBase.h:3832
Attr - This represents one attribute.
Definition Attr.h:46
Represents a static or instance method of a struct/union/class.
Definition DeclCXX.h:2150
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:3724
CastKind getCastKind() const
Definition Expr.h:3768
Expr * getSubExpr()
Definition Expr.h:3774
This is an opaque type for sizes expressed in character units.
Definition CharUnits.h:38
CharUnits alignTo(CharUnits Align) const
Returns the next integer (mod 2**64) that is greater than or equal to this quantity and is a multiple...
Definition CharUnits.h:171
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:184
static CharUnits fromQuantity(QuantityType Quantity)
Construct a CharUnits quantity from a raw integer type.
Definition CharUnits.h:58
Like RawAddress, an abstract representation of an aligned address, but the pointer contained in this ...
Definition Address.h:128
CharUnits getAlignment() const
Definition Address.h:194
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:148
Address CreateGEP(CodeGenFunction &CGF, Address Addr, llvm::Value *Index, const llvm::Twine &Name="")
Definition CGBuilder.h:304
Address CreateStructGEP(Address Addr, unsigned Index, const llvm::Twine &Name="")
Definition CGBuilder.h:231
Abstract information about a function or function prototype.
Definition CGCall.h:43
All available information about a concrete callee.
Definition CGCall.h:66
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)
llvm::Value * emitSystemSemanticLoad(llvm::IRBuilder<> &B, llvm::Type *Type, const clang::DeclaratorDecl *Decl, HLSLAppliedSemanticAttr *Semantic, llvm::dxbc::PSV::SemanticKind SemanticKind, llvm::Triple::EnvironmentType Stage, std::optional< unsigned > Index, SemanticSignatures &Signature)
void setHLSLEntryAttributes(const FunctionDecl *FD, llvm::Function *Fn)
llvm::StructType * getHLSLBufferLayoutType(const RecordType *LayoutStructTy)
void emitEntryFunction(const FunctionDecl *FD, llvm::Function *Fn)
void handleGlobalVarDefinition(const VarDecl *VD, llvm::GlobalVariable *Var)
std::optional< LValue > emitResourceMemberExpr(CodeGenFunction &CGF, const MemberExpr *E)
void emitSystemSemanticStore(llvm::IRBuilder<> &B, llvm::Value *Source, const clang::DeclaratorDecl *Decl, HLSLAppliedSemanticAttr *Semantic, llvm::dxbc::PSV::SemanticKind SemanticKind, llvm::Triple::EnvironmentType Stage, std::optional< unsigned > Index, SemanticSignatures &Signature)
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, SemanticSignatures &Signature, llvm::hlsl::InterpolationModifier Modifiers)
llvm::SmallVectorImpl< llvm::hlsl::SemanticSignatureElement > SemanticSignatures
void addHLSLBufferLayoutType(const RecordType *LayoutStructTy, llvm::StructType *LayoutTy)
std::optional< LValue > emitGlobalResourceArrayAsLValue(CodeGenFunction &CGF, const VarDecl *ArrayDecl)
llvm::Value * handleScalarSemanticLoad(llvm::IRBuilder<> &B, const FunctionDecl *FD, llvm::Type *Type, const clang::DeclaratorDecl *Decl, HLSLAppliedSemanticAttr *Semantic, SemanticSignatures &Signature)
bool emitBufferCopy(CodeGenFunction &CGF, const Expr *E, const LValue &SrcLV, AggValueSlot &DestSlot)
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)
llvm::Type * convertHLSLSpecificType(const Type *T, const CGHLSLOffsetInfo &OffsetInfo)
RawAddress createBufferMatrixTempAddress(const LValue &LV, CodeGenFunction &CGF)
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, SemanticSignatures &Signature, llvm::hlsl::InterpolationModifier Modifiers=llvm::hlsl::InterpolationModifier::None)
void addBuffer(const HLSLBufferDecl *D)
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, SemanticSignatures &Signature, llvm::hlsl::InterpolationModifier Modifiers)
bool emitGlobalResourceArray(CodeGenFunction &CGF, const Expr *E, AggValueSlot &DestSlot)
void handleScalarSemanticStore(llvm::IRBuilder<> &B, const FunctionDecl *FD, llvm::Value *Source, const clang::DeclaratorDecl *Decl, HLSLAppliedSemanticAttr *Semantic, SemanticSignatures &Signature)
void emitInitListOpaqueValues(CodeGenFunction &CGF, InitListExpr *E)
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, SemanticSignatures &Signature, llvm::hlsl::InterpolationModifier Modifiers=llvm::hlsl::InterpolationModifier::None)
CallArgList - Type for representing both the value and type of arguments in a call.
Definition CGCall.h:277
void add(RValue rvalue, QualType type)
Definition CGCall.h:305
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:1368
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:5693
RawAddress CreateMemTempWithoutCast(QualType T, const Twine &Name="tmp")
CreateMemTemp - Create a temporary memory object of the given type, with appropriate alignmen without...
Definition CGExpr.cpp:235
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:284
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:1660
LValue EmitCheckedLValue(const Expr *E, TypeCheckKind TCK)
Same as EmitLValue but additionally we generate checking code to guard against undefined behavior.
Definition CGExpr.cpp:1741
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:1776
bool isOpaqueValueEmitted(const OpaqueValueExpr *E)
isOpaqueValueEmitted - Return true if the opaque value expression has already been emitted.
Definition CGExpr.cpp:6589
llvm::LLVMContext & getLLVMContext()
This class organizes the cross-function state that is used while generating LLVM code.
const PreprocessorOptions & getPreprocessorOpts() const
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
llvm::Constant * GetAddrOfGlobalVar(const VarDecl *D, llvm::Type *Ty=nullptr, ForDefinition_t IsForDefinition=NotForDefinition)
Return the llvm::Constant for the address of the given global variable.
const TargetCodeGenInfo & getTargetCodeGenInfo()
const CodeGenOptions & getCodeGenOpts() const
llvm::LLVMContext & getLLVMContext()
void EmitTopLevelDecl(Decl *D)
Emit code for a single top level declaration.
ConstantAddress GetAddrOfConstantCString(const std::string &Str, StringRef GlobalName=".str")
Returns a pointer to a character array containing the literal and a terminating '\0' character.
const CGFunctionInfo & arrangeFreeFunctionCall(const CallArgList &Args, const FunctionType *Ty, bool ChainCall, const FunctionDecl *ABIInfoFD)
Figure out the rules for calling a function with the given formal type using the given arguments.
Definition CGCall.cpp:730
llvm::Type * ConvertTypeForMem(QualType T)
ConvertTypeForMem - Convert type T into a llvm::Type.
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:384
virtual bool isHLSLPadding(llvm::Type *Ty) const
Return true if this is an HLSL padding type.
Definition TargetInfo.h:473
Represents the canonical version of C arrays with a specified constant size.
Definition TypeBase.h:3858
int64_t getSExtSize() const
Return the size sign-extended as a uint64_t.
Definition TypeBase.h:3940
Represents a concrete matrix type with constant number of rows and columns.
Definition TypeBase.h:4490
DeclContext * getParent()
getParent - Returns the containing DeclContext.
Definition DeclBase.h:2120
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:550
bool isImplicit() const
isImplicit - Indicates whether the declaration was implicitly generated by the implementation.
Definition DeclBase.h:601
SourceLocation getLocation() const
Definition DeclBase.h:447
specific_attr_iterator< T > specific_attr_end() const
Definition DeclBase.h:577
specific_attr_iterator< T > specific_attr_begin() const
Definition DeclBase.h:572
AttrVec & getAttrs()
Definition DeclBase.h:532
Represents a ValueDecl that came out of a declarator.
Definition Decl.h:781
This represents one expression.
Definition Expr.h:113
Expr * IgnoreParenImpCasts() LLVM_READONLY
Skip past any parentheses and implicit casts which might surround this expression until reaching a fi...
Definition Expr.cpp:3129
std::optional< llvm::APSInt > getIntegerConstantExpr(const ASTContext &Ctx, bool AllowRelaxedEval=false) 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:3109
QualType getType() const
Definition Expr.h:145
Represents a member of a struct/union/class.
Definition Decl.h:3299
StringRef getName() const
The name of this FileEntry.
Definition FileEntry.h:61
Represents a function declaration or definition.
Definition Decl.h:2059
const ParmVarDecl * getParamDecl(unsigned i) const
Definition Decl.h:2932
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:2997
Represents a prototype with parameter type info, e.g.
Definition TypeBase.h:5416
HLSLBufferDecl - Represent a cbuffer or tbuffer declaration.
Definition Decl.h:5336
bool isCBuffer() const
Definition Decl.h:5380
const CXXRecordDecl * getLayoutStruct() const
Definition Decl.h:5383
bool hasValidPackoffset() const
Definition Decl.h:5382
buffer_decl_range buffer_decls() const
Definition Decl.h:5411
This class represents temporary values used to represent inout and out arguments in HLSL.
Definition Expr.h:7451
ArrayRef< llvm::hlsl::rootsig::RootElement > getRootElements() const
Definition Decl.h:5453
llvm::dxbc::RootSignatureVersion getVersion() const
Definition Decl.h:5451
One of these records is kept for each identifier that is lexed.
Describes an C or C++ initializer list.
Definition Expr.h:5356
MemberExpr - [C99 6.5.2.3] Structure and Union Members.
Definition Expr.h:3412
ValueDecl * getMemberDecl() const
Retrieve the member declaration to which this expression refers.
Definition Expr.h:3495
Expr * getBase() const
Definition Expr.h:3489
IdentifierInfo * getIdentifier() const
Get the identifier that names this declaration, if there is one.
Definition Decl.h:296
StringRef getName() const
Get the name of identifier for this declaration as a StringRef.
Definition Decl.h:302
OpaqueValueExpr - An expression referring to an opaque object of a fixed type and value class.
Definition Expr.h:1202
Expr * getSourceExpr() const
The source expression of an opaque value expression is the expression which originally generated the ...
Definition Expr.h:1252
Represents a parameter to a function.
Definition Decl.h:1820
std::vector< std::pair< std::string, bool > > Macros
A (possibly-)qualified type.
Definition TypeBase.h:938
const Type * getTypePtr() const
Retrieves a pointer to the underlying (unqualified) type.
Definition TypeBase.h:8446
LangAS getAddressSpace() const
Return the address space of this type.
Definition TypeBase.h:8572
The collection of all-type qualifiers we support.
Definition TypeBase.h:332
void addCVRQualifiers(unsigned mask)
Definition TypeBase.h:503
Represents a struct/union/class.
Definition Decl.h:4464
unsigned getNumFields() const
Returns the number of fields (non-static data members) in this record.
Definition Decl.h:4680
field_iterator field_begin() const
Definition Decl.cpp:5354
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.
One instance of this struct is kept for every file loaded or used.
std::optional< llvm::MemoryBufferRef > getBufferOrNone(DiagnosticsEngine &Diag, FileManager &FM, SourceLocation Loc=SourceLocation()) const
Returns the memory buffer for the associated content.
OptionalFileEntryRef OrigEntry
Reference to the file entry representing this ContentCache.
Information about a FileID, basically just the logical file that it represents and include stack info...
const ContentCache & getContentCache() const
CharacteristicKind getFileCharacteristic() const
Return whether this is a system header or not.
This is a discriminated union of FileInfo and ExpansionInfo.
const FileInfo & getFile() const
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:1879
bool isSignedIntegerOrEnumerationType() const
Determines whether this is an integer type that is signed or an enumeration types whose underlying ty...
Definition Type.cpp:2415
bool isIncompleteArrayType() const
Definition TypeBase.h:8790
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:8782
bool isConstantMatrixType() const
Definition TypeBase.h:8850
bool isHLSLIntangibleType() const
Definition Type.cpp:5728
bool isHLSLResourceRecord() const
Definition Type.cpp:5715
bool isStructureOrClassType() const
Definition Type.cpp:839
const T * getAsCanonical() const
If this type is canonically the specified type, return its canonical type cast to that specified type...
Definition TypeBase.h:3002
const T * getAs() const
Member-template getAs<specific type>'.
Definition TypeBase.h:9299
const Type * getUnqualifiedDesugaredType() const
Return the specified type with any "sugar" removed from the type, removing any typedefs,...
Definition Type.cpp:786
bool isRecordType() const
Definition TypeBase.h:8810
bool isHLSLResourceRecordArray() const
Definition Type.cpp:5719
bool hasBooleanRepresentation() const
Determine whether this type has a boolean representation – i.e., it is a boolean type,...
Definition Type.cpp:2572
Represent the declaration of a variable (in which case it is an lvalue) a function (in which case it ...
Definition Decl.h:713
QualType getType() const
Definition Decl.h:724
Represents a variable declaration or definition.
Definition Decl.h:933
bool hasGlobalStorage() const
Returns true for all variables that do not have local storage.
Definition Decl.h:1248
StorageClass getStorageClass() const
Returns the storage class as written in the source.
Definition Decl.h:1175
Represents a GCC generic vector type.
Definition TypeBase.h:4273
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 isSystem(CharacteristicKind CK)
Determine whether a file / directory characteristic is for system code.
bool hasCounterHandle(const CXXRecordDecl *RD)
StringRef getName(const HeaderType T)
Definition HeaderFile.h:38
@ Address
A pointer to a ValueDecl.
Definition Primitives.h:28
bool Load(InterpState &S, CodePtr OpPC)
Definition Interp.h:2214
Top level wrappers for InstallAPI frontend operations.
bool isa(CodeGen::Address addr)
Definition Address.h:330
CustomizableOptional< FileEntryRef > OptionalFileEntryRef
Definition FileEntry.h:196
nullptr
This class represents a compute construct, representing a 'Kind' of ‘parallel’, 'serial',...
StorageClass
Storage classes.
Definition Specifiers.h:252
@ SC_Static
Definition Specifiers.h:256
@ SC_None
Definition Specifiers.h:254
@ Result
The result type of a method or function.
Definition TypeBase.h:906
const FunctionProtoType * T
U cast(CodeGen::Address addr)
Definition Address.h:327
Diagnostic wrappers for TextAPI types for error reporting.
Definition Dominators.h:30
__builtin_bitreverse32 uint32_t __builtin_riscv_aaddu_u32 __builtin_riscv_asubu_u32 __builtin_elementwise_add_sat __builtin_elementwise_sub_sat int32_t uint32_t uint32_t __builtin_riscv_mhacc_i32 __builtin_riscv_mhaccu_u32 __builtin_riscv_mhaccsu_i32 __builtin_riscv_mulq_i32 uint8_t
unsigned getCounterImplicitOrderID() const