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