Thanks to visit codestin.com
Credit goes to clang.llvm.org

clang 22.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 "Address.h"
17#include "CGDebugInfo.h"
18#include "CodeGenFunction.h"
19#include "CodeGenModule.h"
20#include "TargetInfo.h"
22#include "clang/AST/Attrs.inc"
23#include "clang/AST/Decl.h"
26#include "clang/AST/Type.h"
29#include "llvm/ADT/SmallString.h"
30#include "llvm/ADT/SmallVector.h"
31#include "llvm/Frontend/HLSL/RootSignatureMetadata.h"
32#include "llvm/IR/Constants.h"
33#include "llvm/IR/DerivedTypes.h"
34#include "llvm/IR/GlobalVariable.h"
35#include "llvm/IR/LLVMContext.h"
36#include "llvm/IR/Metadata.h"
37#include "llvm/IR/Module.h"
38#include "llvm/IR/Type.h"
39#include "llvm/IR/Value.h"
40#include "llvm/Support/Alignment.h"
41#include "llvm/Support/ErrorHandling.h"
42#include "llvm/Support/FormatVariadic.h"
43#include <cstdint>
44#include <optional>
45
46using namespace clang;
47using namespace CodeGen;
48using namespace clang::hlsl;
49using namespace llvm;
50
51using llvm::hlsl::CBufferRowSizeInBytes;
52
53namespace {
54
55void addDxilValVersion(StringRef ValVersionStr, llvm::Module &M) {
56 // The validation of ValVersionStr is done at HLSLToolChain::TranslateArgs.
57 // Assume ValVersionStr is legal here.
58 VersionTuple Version;
59 if (Version.tryParse(ValVersionStr) || Version.getBuild() ||
60 Version.getSubminor() || !Version.getMinor()) {
61 return;
62 }
63
64 uint64_t Major = Version.getMajor();
65 uint64_t Minor = *Version.getMinor();
66
67 auto &Ctx = M.getContext();
68 IRBuilder<> B(M.getContext());
69 MDNode *Val = MDNode::get(Ctx, {ConstantAsMetadata::get(B.getInt32(Major)),
70 ConstantAsMetadata::get(B.getInt32(Minor))});
71 StringRef DXILValKey = "dx.valver";
72 auto *DXILValMD = M.getOrInsertNamedMetadata(DXILValKey);
73 DXILValMD->addOperand(Val);
74}
75
76void addRootSignatureMD(llvm::dxbc::RootSignatureVersion RootSigVer,
78 llvm::Function *Fn, llvm::Module &M) {
79 auto &Ctx = M.getContext();
80
81 llvm::hlsl::rootsig::MetadataBuilder RSBuilder(Ctx, Elements);
82 MDNode *RootSignature = RSBuilder.BuildRootSignature();
83
84 ConstantAsMetadata *Version = ConstantAsMetadata::get(ConstantInt::get(
85 llvm::Type::getInt32Ty(Ctx), llvm::to_underlying(RootSigVer)));
86 ValueAsMetadata *EntryFunc = Fn ? ValueAsMetadata::get(Fn) : nullptr;
87 MDNode *MDVals = MDNode::get(Ctx, {EntryFunc, RootSignature, Version});
88
89 StringRef RootSignatureValKey = "dx.rootsignatures";
90 auto *RootSignatureValMD = M.getOrInsertNamedMetadata(RootSignatureValKey);
91 RootSignatureValMD->addOperand(MDVals);
92}
93
94// Find array variable declaration from nested array subscript AST nodes
95static const ValueDecl *getArrayDecl(const ArraySubscriptExpr *ASE) {
96 const Expr *E = nullptr;
97 while (ASE != nullptr) {
98 E = ASE->getBase()->IgnoreImpCasts();
99 if (!E)
100 return nullptr;
101 ASE = dyn_cast<ArraySubscriptExpr>(E);
102 }
103 if (const DeclRefExpr *DRE = dyn_cast_or_null<DeclRefExpr>(E))
104 return DRE->getDecl();
105 return nullptr;
106}
107
108// Get the total size of the array, or -1 if the array is unbounded.
109static int getTotalArraySize(ASTContext &AST, const clang::Type *Ty) {
111 assert(Ty->isArrayType() && "expected array type");
112 if (Ty->isIncompleteArrayType())
113 return -1;
115}
116
117static Value *buildNameForResource(llvm::StringRef BaseName,
118 CodeGenModule &CGM) {
119 llvm::SmallString<64> GlobalName = {BaseName, ".str"};
120 return CGM.GetAddrOfConstantCString(BaseName.str(), GlobalName.c_str())
121 .getPointer();
122}
123
124static CXXMethodDecl *lookupMethod(CXXRecordDecl *Record, StringRef Name,
125 StorageClass SC = SC_None) {
126 for (auto *Method : Record->methods()) {
127 if (Method->getStorageClass() == SC && Method->getName() == Name)
128 return Method;
129 }
130 return nullptr;
131}
132
133static CXXMethodDecl *lookupResourceInitMethodAndSetupArgs(
134 CodeGenModule &CGM, CXXRecordDecl *ResourceDecl, llvm::Value *Range,
135 llvm::Value *Index, StringRef Name, ResourceBindingAttrs &Binding,
136 CallArgList &Args) {
137 assert(Binding.hasBinding() && "at least one binding attribute expected");
138
139 ASTContext &AST = CGM.getContext();
140 CXXMethodDecl *CreateMethod = nullptr;
141 Value *NameStr = buildNameForResource(Name, CGM);
142 Value *Space = llvm::ConstantInt::get(CGM.IntTy, Binding.getSpace());
143
144 if (Binding.isExplicit()) {
145 // explicit binding
146 auto *RegSlot = llvm::ConstantInt::get(CGM.IntTy, Binding.getSlot());
147 Args.add(RValue::get(RegSlot), AST.UnsignedIntTy);
148 CreateMethod = lookupMethod(ResourceDecl, "__createFromBinding", SC_Static);
149 } else {
150 // implicit binding
151 auto *OrderID =
152 llvm::ConstantInt::get(CGM.IntTy, Binding.getImplicitOrderID());
153 Args.add(RValue::get(OrderID), AST.UnsignedIntTy);
154 CreateMethod =
155 lookupMethod(ResourceDecl, "__createFromImplicitBinding", SC_Static);
156 }
157 Args.add(RValue::get(Space), AST.UnsignedIntTy);
158 Args.add(RValue::get(Range), AST.IntTy);
159 Args.add(RValue::get(Index), AST.UnsignedIntTy);
160 Args.add(RValue::get(NameStr), AST.getPointerType(AST.CharTy.withConst()));
161
162 return CreateMethod;
163}
164
165static void callResourceInitMethod(CodeGenFunction &CGF,
166 CXXMethodDecl *CreateMethod,
167 CallArgList &Args, Address ReturnAddress) {
168 llvm::Constant *CalleeFn = CGF.CGM.GetAddrOfFunction(CreateMethod);
169 const FunctionProtoType *Proto =
170 CreateMethod->getType()->getAs<FunctionProtoType>();
171 const CGFunctionInfo &FnInfo =
172 CGF.CGM.getTypes().arrangeFreeFunctionCall(Args, Proto, false);
173 ReturnValueSlot ReturnValue(ReturnAddress, false);
174 CGCallee Callee(CGCalleeInfo(Proto), CalleeFn);
175 CGF.EmitCall(FnInfo, Callee, ReturnValue, Args, nullptr);
176}
177
178// Initializes local resource array variable. For multi-dimensional arrays it
179// calls itself recursively to initialize its sub-arrays. The Index used in the
180// resource constructor calls will begin at StartIndex and will be incremented
181// for each array element. The last used resource Index is returned to the
182// caller. If the function returns std::nullopt, it indicates an error.
183static std::optional<llvm::Value *> initializeLocalResourceArray(
184 CodeGenFunction &CGF, CXXRecordDecl *ResourceDecl,
185 const ConstantArrayType *ArrayTy, AggValueSlot &ValueSlot,
186 llvm::Value *Range, llvm::Value *StartIndex, StringRef ResourceName,
187 ResourceBindingAttrs &Binding, ArrayRef<llvm::Value *> PrevGEPIndices,
188 SourceLocation ArraySubsExprLoc) {
189
190 ASTContext &AST = CGF.getContext();
191 llvm::IntegerType *IntTy = CGF.CGM.IntTy;
192 llvm::Value *Index = StartIndex;
193 llvm::Value *One = llvm::ConstantInt::get(IntTy, 1);
194 const uint64_t ArraySize = ArrayTy->getSExtSize();
195 QualType ElemType = ArrayTy->getElementType();
196 Address TmpArrayAddr = ValueSlot.getAddress();
197
198 // Add additional index to the getelementptr call indices.
199 // This index will be updated for each array element in the loops below.
200 SmallVector<llvm::Value *> GEPIndices(PrevGEPIndices);
201 GEPIndices.push_back(llvm::ConstantInt::get(IntTy, 0));
202
203 // For array of arrays, recursively initialize the sub-arrays.
204 if (ElemType->isArrayType()) {
205 const ConstantArrayType *SubArrayTy = cast<ConstantArrayType>(ElemType);
206 for (uint64_t I = 0; I < ArraySize; I++) {
207 if (I > 0) {
208 Index = CGF.Builder.CreateAdd(Index, One);
209 GEPIndices.back() = llvm::ConstantInt::get(IntTy, I);
210 }
211 std::optional<llvm::Value *> MaybeIndex = initializeLocalResourceArray(
212 CGF, ResourceDecl, SubArrayTy, ValueSlot, Range, Index, ResourceName,
213 Binding, GEPIndices, ArraySubsExprLoc);
214 if (!MaybeIndex)
215 return std::nullopt;
216 Index = *MaybeIndex;
217 }
218 return Index;
219 }
220
221 // For array of resources, initialize each resource in the array.
222 llvm::Type *Ty = CGF.ConvertTypeForMem(ElemType);
223 CharUnits ElemSize = AST.getTypeSizeInChars(ElemType);
224 CharUnits Align =
225 TmpArrayAddr.getAlignment().alignmentOfArrayElement(ElemSize);
226
227 for (uint64_t I = 0; I < ArraySize; I++) {
228 if (I > 0) {
229 Index = CGF.Builder.CreateAdd(Index, One);
230 GEPIndices.back() = llvm::ConstantInt::get(IntTy, I);
231 }
232 Address ReturnAddress =
233 CGF.Builder.CreateGEP(TmpArrayAddr, GEPIndices, Ty, Align);
234
235 CallArgList Args;
236 CXXMethodDecl *CreateMethod = lookupResourceInitMethodAndSetupArgs(
237 CGF.CGM, ResourceDecl, Range, Index, ResourceName, Binding, Args);
238
239 if (!CreateMethod)
240 // This can happen if someone creates an array of structs that looks like
241 // an HLSL resource record array but it does not have the required static
242 // create method. No binding will be generated for it.
243 return std::nullopt;
244
245 callResourceInitMethod(CGF, CreateMethod, Args, ReturnAddress);
246 }
247 return Index;
248}
249
250} // namespace
251
252llvm::Type *
254 SmallVector<int32_t> *Packoffsets) {
255 assert(T->isHLSLSpecificType() && "Not an HLSL specific type!");
256
257 // Check if the target has a specific translation for this type first.
258 if (llvm::Type *TargetTy =
259 CGM.getTargetCodeGenInfo().getHLSLType(CGM, T, Packoffsets))
260 return TargetTy;
261
262 llvm_unreachable("Generic handling of HLSL types is not supported.");
263}
264
265llvm::Triple::ArchType CGHLSLRuntime::getArch() {
266 return CGM.getTarget().getTriple().getArch();
267}
268
269// Emits constant global variables for buffer constants declarations
270// and creates metadata linking the constant globals with the buffer global.
271void CGHLSLRuntime::emitBufferGlobalsAndMetadata(const HLSLBufferDecl *BufDecl,
272 llvm::GlobalVariable *BufGV) {
273 LLVMContext &Ctx = CGM.getLLVMContext();
274
275 // get the layout struct from constant buffer target type
276 llvm::Type *BufType = BufGV->getValueType();
277 llvm::Type *BufLayoutType =
278 cast<llvm::TargetExtType>(BufType)->getTypeParameter(0);
279 llvm::StructType *LayoutStruct = cast<llvm::StructType>(
280 cast<llvm::TargetExtType>(BufLayoutType)->getTypeParameter(0));
281
282 // Start metadata list associating the buffer global variable with its
283 // constatns
285 BufGlobals.push_back(ValueAsMetadata::get(BufGV));
286
287 const auto *ElemIt = LayoutStruct->element_begin();
288 for (Decl *D : BufDecl->buffer_decls()) {
290 // Nothing to do for this declaration.
291 continue;
292 if (isa<FunctionDecl>(D)) {
293 // A function within an cbuffer is effectively a top-level function.
295 continue;
296 }
297 VarDecl *VD = dyn_cast<VarDecl>(D);
298 if (!VD)
299 continue;
300
301 QualType VDTy = VD->getType();
303 if (VD->getStorageClass() == SC_Static ||
306 // Emit static and groupshared variables and resource classes inside
307 // cbuffer as regular globals
308 CGM.EmitGlobal(VD);
309 } else {
310 // Anything else that is not in the hlsl_constant address space must be
311 // an empty struct or a zero-sized array and can be ignored
312 assert(BufDecl->getASTContext().getTypeSize(VDTy) == 0 &&
313 "constant buffer decl with non-zero sized type outside of "
314 "hlsl_constant address space");
315 }
316 continue;
317 }
318
319 assert(ElemIt != LayoutStruct->element_end() &&
320 "number of elements in layout struct does not match");
321 llvm::Type *LayoutType = *ElemIt++;
322
323 // FIXME: handle resources inside user defined structs
324 // (llvm/wg-hlsl#175)
325
326 // create global variable for the constant and to metadata list
327 GlobalVariable *ElemGV =
328 cast<GlobalVariable>(CGM.GetAddrOfGlobalVar(VD, LayoutType));
329 BufGlobals.push_back(ValueAsMetadata::get(ElemGV));
330 }
331 assert(ElemIt == LayoutStruct->element_end() &&
332 "number of elements in layout struct does not match");
333
334 // add buffer metadata to the module
335 CGM.getModule()
336 .getOrInsertNamedMetadata("hlsl.cbs")
337 ->addOperand(MDNode::get(Ctx, BufGlobals));
338}
339
340// Creates resource handle type for the HLSL buffer declaration
341static const clang::HLSLAttributedResourceType *
343 ASTContext &AST = BufDecl->getASTContext();
345 AST.HLSLResourceTy, AST.getCanonicalTagType(BufDecl->getLayoutStruct()),
346 HLSLAttributedResourceType::Attributes(ResourceClass::CBuffer));
348}
349
350// Iterates over all declarations in the HLSL buffer and based on the
351// packoffset or register(c#) annotations it fills outs the Layout
352// vector with the user-specified layout offsets.
353// The buffer offsets can be specified 2 ways:
354// 1. declarations in cbuffer {} block can have a packoffset annotation
355// (translates to HLSLPackOffsetAttr)
356// 2. default constant buffer declarations at global scope can have
357// register(c#) annotations (translates to HLSLResourceBindingAttr with
358// RegisterType::C)
359// It is not guaranteed that all declarations in a buffer have an annotation.
360// For those where it is not specified a -1 value is added to the Layout
361// vector. In the final layout these declarations will be placed at the end
362// of the HLSL buffer after all of the elements with specified offset.
363static void fillPackoffsetLayout(const HLSLBufferDecl *BufDecl,
364 SmallVector<int32_t> &Layout) {
365 assert(Layout.empty() && "expected empty vector for layout");
366 assert(BufDecl->hasValidPackoffset());
367
368 for (Decl *D : BufDecl->buffer_decls()) {
370 continue;
371 }
372 VarDecl *VD = dyn_cast<VarDecl>(D);
373 if (!VD || VD->getType().getAddressSpace() != LangAS::hlsl_constant)
374 continue;
375
376 if (!VD->hasAttrs()) {
377 Layout.push_back(-1);
378 continue;
379 }
380
381 int32_t Offset = -1;
382 for (auto *Attr : VD->getAttrs()) {
383 if (auto *POA = dyn_cast<HLSLPackOffsetAttr>(Attr)) {
384 Offset = POA->getOffsetInBytes();
385 break;
386 }
387 auto *RBA = dyn_cast<HLSLResourceBindingAttr>(Attr);
388 if (RBA &&
389 RBA->getRegisterType() == HLSLResourceBindingAttr::RegisterType::C) {
390 Offset = RBA->getSlotNumber() * CBufferRowSizeInBytes;
391 break;
392 }
393 }
394 Layout.push_back(Offset);
395 }
396}
397
398// Codegen for HLSLBufferDecl
400
401 assert(BufDecl->isCBuffer() && "tbuffer codegen is not supported yet");
402
403 // create resource handle type for the buffer
404 const clang::HLSLAttributedResourceType *ResHandleTy =
405 createBufferHandleType(BufDecl);
406
407 // empty constant buffer is ignored
408 if (ResHandleTy->getContainedType()->getAsCXXRecordDecl()->isEmpty())
409 return;
410
411 // create global variable for the constant buffer
413 if (BufDecl->hasValidPackoffset())
414 fillPackoffsetLayout(BufDecl, Layout);
415
416 llvm::TargetExtType *TargetTy =
418 ResHandleTy, BufDecl->hasValidPackoffset() ? &Layout : nullptr));
419 llvm::GlobalVariable *BufGV = new GlobalVariable(
420 TargetTy, /*isConstant*/ false,
421 GlobalValue::LinkageTypes::ExternalLinkage, PoisonValue::get(TargetTy),
422 llvm::formatv("{0}{1}", BufDecl->getName(),
423 BufDecl->isCBuffer() ? ".cb" : ".tb"),
424 GlobalValue::NotThreadLocal);
425 CGM.getModule().insertGlobalVariable(BufGV);
426
427 // Add globals for constant buffer elements and create metadata nodes
428 emitBufferGlobalsAndMetadata(BufDecl, BufGV);
429
430 // Initialize cbuffer from binding (implicit or explicit)
431 initializeBufferFromBinding(BufDecl, BufGV);
432}
433
435 const HLSLRootSignatureDecl *SignatureDecl) {
436 llvm::Module &M = CGM.getModule();
437 Triple T(M.getTargetTriple());
438
439 // Generated later with the function decl if not targeting root signature
440 if (T.getEnvironment() != Triple::EnvironmentType::RootSignature)
441 return;
442
443 addRootSignatureMD(SignatureDecl->getVersion(),
444 SignatureDecl->getRootElements(), nullptr, M);
445}
446
447llvm::TargetExtType *
448CGHLSLRuntime::getHLSLBufferLayoutType(const RecordType *StructType) {
449 const auto Entry = LayoutTypes.find(StructType);
450 if (Entry != LayoutTypes.end())
451 return Entry->getSecond();
452 return nullptr;
453}
454
455void CGHLSLRuntime::addHLSLBufferLayoutType(const RecordType *StructType,
456 llvm::TargetExtType *LayoutTy) {
457 assert(getHLSLBufferLayoutType(StructType) == nullptr &&
458 "layout type for this struct already exist");
459 LayoutTypes[StructType] = LayoutTy;
460}
461
463 auto &TargetOpts = CGM.getTarget().getTargetOpts();
464 auto &CodeGenOpts = CGM.getCodeGenOpts();
465 auto &LangOpts = CGM.getLangOpts();
466 llvm::Module &M = CGM.getModule();
467 Triple T(M.getTargetTriple());
468 if (T.getArch() == Triple::ArchType::dxil)
469 addDxilValVersion(TargetOpts.DxilValidatorVersion, M);
470 if (CodeGenOpts.ResMayAlias)
471 M.setModuleFlag(llvm::Module::ModFlagBehavior::Error, "dx.resmayalias", 1);
472
473 // NativeHalfType corresponds to the -fnative-half-type clang option which is
474 // aliased by clang-dxc's -enable-16bit-types option. This option is used to
475 // set the UseNativeLowPrecision DXIL module flag in the DirectX backend
476 if (LangOpts.NativeHalfType)
477 M.setModuleFlag(llvm::Module::ModFlagBehavior::Error, "dx.nativelowprec",
478 1);
479
481}
482
484 const FunctionDecl *FD, llvm::Function *Fn) {
485 const auto *ShaderAttr = FD->getAttr<HLSLShaderAttr>();
486 assert(ShaderAttr && "All entry functions must have a HLSLShaderAttr");
487 const StringRef ShaderAttrKindStr = "hlsl.shader";
488 Fn->addFnAttr(ShaderAttrKindStr,
489 llvm::Triple::getEnvironmentTypeName(ShaderAttr->getType()));
490 if (HLSLNumThreadsAttr *NumThreadsAttr = FD->getAttr<HLSLNumThreadsAttr>()) {
491 const StringRef NumThreadsKindStr = "hlsl.numthreads";
492 std::string NumThreadsStr =
493 formatv("{0},{1},{2}", NumThreadsAttr->getX(), NumThreadsAttr->getY(),
494 NumThreadsAttr->getZ());
495 Fn->addFnAttr(NumThreadsKindStr, NumThreadsStr);
496 }
497 if (HLSLWaveSizeAttr *WaveSizeAttr = FD->getAttr<HLSLWaveSizeAttr>()) {
498 const StringRef WaveSizeKindStr = "hlsl.wavesize";
499 std::string WaveSizeStr =
500 formatv("{0},{1},{2}", WaveSizeAttr->getMin(), WaveSizeAttr->getMax(),
501 WaveSizeAttr->getPreferred());
502 Fn->addFnAttr(WaveSizeKindStr, WaveSizeStr);
503 }
504 // HLSL entry functions are materialized for module functions with
505 // HLSLShaderAttr attribute. SetLLVMFunctionAttributesForDefinition called
506 // later in the compiler-flow for such module functions is not aware of and
507 // hence not able to set attributes of the newly materialized entry functions.
508 // So, set attributes of entry function here, as appropriate.
509 if (CGM.getCodeGenOpts().OptimizationLevel == 0)
510 Fn->addFnAttr(llvm::Attribute::OptimizeNone);
511 Fn->addFnAttr(llvm::Attribute::NoInline);
512}
513
514static Value *buildVectorInput(IRBuilder<> &B, Function *F, llvm::Type *Ty) {
515 if (const auto *VT = dyn_cast<FixedVectorType>(Ty)) {
516 Value *Result = PoisonValue::get(Ty);
517 for (unsigned I = 0; I < VT->getNumElements(); ++I) {
518 Value *Elt = B.CreateCall(F, {B.getInt32(I)});
519 Result = B.CreateInsertElement(Result, Elt, I);
520 }
521 return Result;
522 }
523 return B.CreateCall(F, {B.getInt32(0)});
524}
525
526static void addSPIRVBuiltinDecoration(llvm::GlobalVariable *GV,
527 unsigned BuiltIn) {
528 LLVMContext &Ctx = GV->getContext();
529 IRBuilder<> B(GV->getContext());
530 MDNode *Operands = MDNode::get(
531 Ctx,
532 {ConstantAsMetadata::get(B.getInt32(/* Spirv::Decoration::BuiltIn */ 11)),
533 ConstantAsMetadata::get(B.getInt32(BuiltIn))});
534 MDNode *Decoration = MDNode::get(Ctx, {Operands});
535 GV->addMetadata("spirv.Decorations", *Decoration);
536}
537
538static llvm::Value *createSPIRVBuiltinLoad(IRBuilder<> &B, llvm::Module &M,
539 llvm::Type *Ty, const Twine &Name,
540 unsigned BuiltInID) {
541 auto *GV = new llvm::GlobalVariable(
542 M, Ty, /* isConstant= */ true, llvm::GlobalValue::ExternalLinkage,
543 /* Initializer= */ nullptr, Name, /* insertBefore= */ nullptr,
544 llvm::GlobalVariable::GeneralDynamicTLSModel,
545 /* AddressSpace */ 7, /* isExternallyInitialized= */ true);
546 addSPIRVBuiltinDecoration(GV, BuiltInID);
547 GV->setVisibility(llvm::GlobalValue::HiddenVisibility);
548 return B.CreateLoad(Ty, GV);
549}
550
551llvm::Value *
552CGHLSLRuntime::emitSystemSemanticLoad(IRBuilder<> &B, llvm::Type *Type,
554 SemanticInfo &ActiveSemantic) {
555 if (isa<HLSLSV_GroupIndexAttr>(ActiveSemantic.Semantic)) {
556 llvm::Function *GroupIndex =
557 CGM.getIntrinsic(getFlattenedThreadIdInGroupIntrinsic());
558 return B.CreateCall(FunctionCallee(GroupIndex));
559 }
560
561 if (isa<HLSLSV_DispatchThreadIDAttr>(ActiveSemantic.Semantic)) {
562 llvm::Intrinsic::ID IntrinID = getThreadIdIntrinsic();
563 llvm::Function *ThreadIDIntrinsic =
564 llvm::Intrinsic::isOverloaded(IntrinID)
565 ? CGM.getIntrinsic(IntrinID, {CGM.Int32Ty})
566 : CGM.getIntrinsic(IntrinID);
567 return buildVectorInput(B, ThreadIDIntrinsic, Type);
568 }
569
570 if (isa<HLSLSV_GroupThreadIDAttr>(ActiveSemantic.Semantic)) {
571 llvm::Intrinsic::ID IntrinID = getGroupThreadIdIntrinsic();
572 llvm::Function *GroupThreadIDIntrinsic =
573 llvm::Intrinsic::isOverloaded(IntrinID)
574 ? CGM.getIntrinsic(IntrinID, {CGM.Int32Ty})
575 : CGM.getIntrinsic(IntrinID);
576 return buildVectorInput(B, GroupThreadIDIntrinsic, Type);
577 }
578
579 if (isa<HLSLSV_GroupIDAttr>(ActiveSemantic.Semantic)) {
580 llvm::Intrinsic::ID IntrinID = getGroupIdIntrinsic();
581 llvm::Function *GroupIDIntrinsic =
582 llvm::Intrinsic::isOverloaded(IntrinID)
583 ? CGM.getIntrinsic(IntrinID, {CGM.Int32Ty})
584 : CGM.getIntrinsic(IntrinID);
585 return buildVectorInput(B, GroupIDIntrinsic, Type);
586 }
587
588 if (HLSLSV_PositionAttr *S =
589 dyn_cast<HLSLSV_PositionAttr>(ActiveSemantic.Semantic)) {
590 if (CGM.getTriple().getEnvironment() == Triple::EnvironmentType::Pixel)
591 return createSPIRVBuiltinLoad(B, CGM.getModule(), Type,
592 S->getAttrName()->getName(),
593 /* BuiltIn::FragCoord */ 15);
594 }
595
596 llvm_unreachable("non-handled system semantic. FIXME.");
597}
598
599llvm::Value *
602 SemanticInfo &ActiveSemantic) {
603
604 if (!ActiveSemantic.Semantic) {
605 ActiveSemantic.Semantic = Decl->getAttr<HLSLSemanticAttr>();
606 if (!ActiveSemantic.Semantic) {
607 CGM.getDiags().Report(Decl->getInnerLocStart(),
608 diag::err_hlsl_semantic_missing);
609 return nullptr;
610 }
611 ActiveSemantic.Index = ActiveSemantic.Semantic->getSemanticIndex();
612 }
613
614 return emitSystemSemanticLoad(B, Type, Decl, ActiveSemantic);
615}
616
617llvm::Value *
618CGHLSLRuntime::handleSemanticLoad(IRBuilder<> &B, llvm::Type *Type,
620 SemanticInfo &ActiveSemantic) {
621 assert(!Type->isStructTy());
622 return handleScalarSemanticLoad(B, Type, Decl, ActiveSemantic);
623}
624
626 llvm::Function *Fn) {
627 llvm::Module &M = CGM.getModule();
628 llvm::LLVMContext &Ctx = M.getContext();
629 auto *EntryTy = llvm::FunctionType::get(llvm::Type::getVoidTy(Ctx), false);
630 Function *EntryFn =
631 Function::Create(EntryTy, Function::ExternalLinkage, FD->getName(), &M);
632
633 // Copy function attributes over, we have no argument or return attributes
634 // that can be valid on the real entry.
635 AttributeList NewAttrs = AttributeList::get(Ctx, AttributeList::FunctionIndex,
636 Fn->getAttributes().getFnAttrs());
637 EntryFn->setAttributes(NewAttrs);
638 setHLSLEntryAttributes(FD, EntryFn);
639
640 // Set the called function as internal linkage.
641 Fn->setLinkage(GlobalValue::InternalLinkage);
642
643 BasicBlock *BB = BasicBlock::Create(Ctx, "entry", EntryFn);
644 IRBuilder<> B(BB);
646
648 if (CGM.shouldEmitConvergenceTokens()) {
649 assert(EntryFn->isConvergent());
650 llvm::Value *I =
651 B.CreateIntrinsic(llvm::Intrinsic::experimental_convergence_entry, {});
652 llvm::Value *bundleArgs[] = {I};
653 OB.emplace_back("convergencectrl", bundleArgs);
654 }
655
656 // FIXME: support struct parameters where semantics are on members.
657 // See: https://github.com/llvm/llvm-project/issues/57874
658 unsigned SRetOffset = 0;
659 for (const auto &Param : Fn->args()) {
660 if (Param.hasStructRetAttr()) {
661 // FIXME: support output.
662 // See: https://github.com/llvm/llvm-project/issues/57874
663 SRetOffset = 1;
664 Args.emplace_back(PoisonValue::get(Param.getType()));
665 continue;
666 }
667
668 const ParmVarDecl *PD = FD->getParamDecl(Param.getArgNo() - SRetOffset);
669 SemanticInfo ActiveSemantic = {nullptr, 0};
670 Args.push_back(handleSemanticLoad(B, Param.getType(), PD, ActiveSemantic));
671 }
672
673 CallInst *CI = B.CreateCall(FunctionCallee(Fn), Args, OB);
674 CI->setCallingConv(Fn->getCallingConv());
675 // FIXME: Handle codegen for return type semantics.
676 // See: https://github.com/llvm/llvm-project/issues/57875
677 B.CreateRetVoid();
678
679 // Add and identify root signature to function, if applicable
680 for (const Attr *Attr : FD->getAttrs()) {
681 if (const auto *RSAttr = dyn_cast<RootSignatureAttr>(Attr)) {
682 auto *RSDecl = RSAttr->getSignatureDecl();
683 addRootSignatureMD(RSDecl->getVersion(), RSDecl->getRootElements(),
684 EntryFn, M);
685 }
686 }
687}
688
689static void gatherFunctions(SmallVectorImpl<Function *> &Fns, llvm::Module &M,
690 bool CtorOrDtor) {
691 const auto *GV =
692 M.getNamedGlobal(CtorOrDtor ? "llvm.global_ctors" : "llvm.global_dtors");
693 if (!GV)
694 return;
695 const auto *CA = dyn_cast<ConstantArray>(GV->getInitializer());
696 if (!CA)
697 return;
698 // The global_ctor array elements are a struct [Priority, Fn *, COMDat].
699 // HLSL neither supports priorities or COMDat values, so we will check those
700 // in an assert but not handle them.
701
702 for (const auto &Ctor : CA->operands()) {
704 continue;
705 ConstantStruct *CS = cast<ConstantStruct>(Ctor);
706
707 assert(cast<ConstantInt>(CS->getOperand(0))->getValue() == 65535 &&
708 "HLSL doesn't support setting priority for global ctors.");
709 assert(isa<ConstantPointerNull>(CS->getOperand(2)) &&
710 "HLSL doesn't support COMDat for global ctors.");
711 Fns.push_back(cast<Function>(CS->getOperand(1)));
712 }
713}
714
716 llvm::Module &M = CGM.getModule();
719 gatherFunctions(CtorFns, M, true);
720 gatherFunctions(DtorFns, M, false);
721
722 // Insert a call to the global constructor at the beginning of the entry block
723 // to externally exported functions. This is a bit of a hack, but HLSL allows
724 // global constructors, but doesn't support driver initialization of globals.
725 for (auto &F : M.functions()) {
726 if (!F.hasFnAttribute("hlsl.shader"))
727 continue;
728 auto *Token = getConvergenceToken(F.getEntryBlock());
729 Instruction *IP = &*F.getEntryBlock().begin();
731 if (Token) {
732 llvm::Value *bundleArgs[] = {Token};
733 OB.emplace_back("convergencectrl", bundleArgs);
734 IP = Token->getNextNode();
735 }
736 IRBuilder<> B(IP);
737 for (auto *Fn : CtorFns) {
738 auto CI = B.CreateCall(FunctionCallee(Fn), {}, OB);
739 CI->setCallingConv(Fn->getCallingConv());
740 }
741
742 // Insert global dtors before the terminator of the last instruction
743 B.SetInsertPoint(F.back().getTerminator());
744 for (auto *Fn : DtorFns) {
745 auto CI = B.CreateCall(FunctionCallee(Fn), {}, OB);
746 CI->setCallingConv(Fn->getCallingConv());
747 }
748 }
749
750 // No need to keep global ctors/dtors for non-lib profile after call to
751 // ctors/dtors added for entry.
752 Triple T(M.getTargetTriple());
753 if (T.getEnvironment() != Triple::EnvironmentType::Library) {
754 if (auto *GV = M.getNamedGlobal("llvm.global_ctors"))
755 GV->eraseFromParent();
756 if (auto *GV = M.getNamedGlobal("llvm.global_dtors"))
757 GV->eraseFromParent();
758 }
759}
760
761static void initializeBuffer(CodeGenModule &CGM, llvm::GlobalVariable *GV,
762 Intrinsic::ID IntrID,
764
765 LLVMContext &Ctx = CGM.getLLVMContext();
766 llvm::Function *InitResFunc = llvm::Function::Create(
767 llvm::FunctionType::get(CGM.VoidTy, false),
768 llvm::GlobalValue::InternalLinkage,
769 ("_init_buffer_" + GV->getName()).str(), CGM.getModule());
770 InitResFunc->addFnAttr(llvm::Attribute::AlwaysInline);
771
772 llvm::BasicBlock *EntryBB =
773 llvm::BasicBlock::Create(Ctx, "entry", InitResFunc);
774 CGBuilderTy Builder(CGM, Ctx);
775 const DataLayout &DL = CGM.getModule().getDataLayout();
776 Builder.SetInsertPoint(EntryBB);
777
778 // Make sure the global variable is buffer resource handle
779 llvm::Type *HandleTy = GV->getValueType();
780 assert(HandleTy->isTargetExtTy() && "unexpected type of the buffer global");
781
782 llvm::Value *CreateHandle = Builder.CreateIntrinsic(
783 /*ReturnType=*/HandleTy, IntrID, Args, nullptr,
784 Twine(GV->getName()).concat("_h"));
785
786 llvm::Value *HandleRef = Builder.CreateStructGEP(GV->getValueType(), GV, 0);
787 Builder.CreateAlignedStore(CreateHandle, HandleRef,
788 HandleRef->getPointerAlignment(DL));
789 Builder.CreateRetVoid();
790
791 CGM.AddCXXGlobalInit(InitResFunc);
792}
793
794void CGHLSLRuntime::initializeBufferFromBinding(const HLSLBufferDecl *BufDecl,
795 llvm::GlobalVariable *GV) {
796 ResourceBindingAttrs Binding(BufDecl);
797 assert(Binding.hasBinding() &&
798 "cbuffer/tbuffer should always have resource binding attribute");
799
800 auto *Index = llvm::ConstantInt::get(CGM.IntTy, 0);
801 auto *RangeSize = llvm::ConstantInt::get(CGM.IntTy, 1);
802 auto *Space = llvm::ConstantInt::get(CGM.IntTy, Binding.getSpace());
803 Value *Name = buildNameForResource(BufDecl->getName(), CGM);
804
805 // buffer with explicit binding
806 if (Binding.isExplicit()) {
807 llvm::Intrinsic::ID IntrinsicID =
808 CGM.getHLSLRuntime().getCreateHandleFromBindingIntrinsic();
809 auto *RegSlot = llvm::ConstantInt::get(CGM.IntTy, Binding.getSlot());
810 SmallVector<Value *> Args{Space, RegSlot, RangeSize, Index, Name};
811 initializeBuffer(CGM, GV, IntrinsicID, Args);
812 } else {
813 // buffer with implicit binding
814 llvm::Intrinsic::ID IntrinsicID =
815 CGM.getHLSLRuntime().getCreateHandleFromImplicitBindingIntrinsic();
816 auto *OrderID =
817 llvm::ConstantInt::get(CGM.IntTy, Binding.getImplicitOrderID());
818 SmallVector<Value *> Args{OrderID, Space, RangeSize, Index, Name};
819 initializeBuffer(CGM, GV, IntrinsicID, Args);
820 }
821}
822
824 llvm::GlobalVariable *GV) {
825 if (auto Attr = VD->getAttr<HLSLVkExtBuiltinInputAttr>())
826 addSPIRVBuiltinDecoration(GV, Attr->getBuiltIn());
827}
828
829llvm::Instruction *CGHLSLRuntime::getConvergenceToken(BasicBlock &BB) {
830 if (!CGM.shouldEmitConvergenceTokens())
831 return nullptr;
832
833 auto E = BB.end();
834 for (auto I = BB.begin(); I != E; ++I) {
835 auto *II = dyn_cast<llvm::IntrinsicInst>(&*I);
836 if (II && llvm::isConvergenceControlIntrinsic(II->getIntrinsicID())) {
837 return II;
838 }
839 }
840 llvm_unreachable("Convergence token should have been emitted.");
841 return nullptr;
842}
843
844class OpaqueValueVisitor : public RecursiveASTVisitor<OpaqueValueVisitor> {
845public:
849
851 // These need to be bound in CodeGenFunction::EmitHLSLOutArgLValues
852 // or CodeGenFunction::EmitHLSLOutArgExpr. If they are part of this
853 // traversal, the temporary containing the copy out will not have
854 // been created yet.
855 return false;
856 }
857
859 // Traverse the source expression first.
860 if (E->getSourceExpr())
862
863 // Then add this OVE if we haven't seen it before.
864 if (Visited.insert(E).second)
865 OVEs.push_back(E);
866
867 return true;
868 }
869};
870
872 InitListExpr *E) {
873
874 typedef CodeGenFunction::OpaqueValueMappingData OpaqueValueMappingData;
875 OpaqueValueVisitor Visitor;
876 Visitor.TraverseStmt(E);
877 for (auto *OVE : Visitor.OVEs) {
878 if (CGF.isOpaqueValueEmitted(OVE))
879 continue;
880 if (OpaqueValueMappingData::shouldBindAsLValue(OVE)) {
881 LValue LV = CGF.EmitLValue(OVE->getSourceExpr());
882 OpaqueValueMappingData::bind(CGF, OVE, LV);
883 } else {
884 RValue RV = CGF.EmitAnyExpr(OVE->getSourceExpr());
885 OpaqueValueMappingData::bind(CGF, OVE, RV);
886 }
887 }
888}
889
891 const ArraySubscriptExpr *ArraySubsExpr, CodeGenFunction &CGF) {
892 assert((ArraySubsExpr->getType()->isHLSLResourceRecord() ||
893 ArraySubsExpr->getType()->isHLSLResourceRecordArray()) &&
894 "expected resource array subscript expression");
895
896 // Let clang codegen handle local resource array subscripts,
897 // or when the subscript references on opaque expression (as part of
898 // ArrayInitLoopExpr AST node).
899 const VarDecl *ArrayDecl =
900 dyn_cast_or_null<VarDecl>(getArrayDecl(ArraySubsExpr));
901 if (!ArrayDecl || !ArrayDecl->hasGlobalStorage())
902 return std::nullopt;
903
904 // get the resource array type
905 ASTContext &AST = ArrayDecl->getASTContext();
906 const Type *ResArrayTy = ArrayDecl->getType().getTypePtr();
907 assert(ResArrayTy->isHLSLResourceRecordArray() &&
908 "expected array of resource classes");
909
910 // Iterate through all nested array subscript expressions to calculate
911 // the index in the flattened resource array (if this is a multi-
912 // dimensional array). The index is calculated as a sum of all indices
913 // multiplied by the total size of the array at that level.
914 Value *Index = nullptr;
915 const ArraySubscriptExpr *ASE = ArraySubsExpr;
916 while (ASE != nullptr) {
917 Value *SubIndex = CGF.EmitScalarExpr(ASE->getIdx());
918 if (const auto *ArrayTy =
919 dyn_cast<ConstantArrayType>(ASE->getType().getTypePtr())) {
920 Value *Multiplier = llvm::ConstantInt::get(
921 CGM.IntTy, AST.getConstantArrayElementCount(ArrayTy));
922 SubIndex = CGF.Builder.CreateMul(SubIndex, Multiplier);
923 }
924 Index = Index ? CGF.Builder.CreateAdd(Index, SubIndex) : SubIndex;
925 ASE = dyn_cast<ArraySubscriptExpr>(ASE->getBase()->IgnoreParenImpCasts());
926 }
927
928 // Find binding info for the resource array. For implicit binding
929 // an HLSLResourceBindingAttr should have been added by SemaHLSL.
930 ResourceBindingAttrs Binding(ArrayDecl);
931 assert((Binding.hasBinding()) &&
932 "resource array must have a binding attribute");
933
934 // Find the individual resource type.
935 QualType ResultTy = ArraySubsExpr->getType();
936 QualType ResourceTy =
937 ResultTy->isArrayType() ? AST.getBaseElementType(ResultTy) : ResultTy;
938
939 // Create a temporary variable for the result, which is either going
940 // to be a single resource instance or a local array of resources (we need to
941 // return an LValue).
942 RawAddress TmpVar = CGF.CreateMemTemp(ResultTy);
943 if (CGF.EmitLifetimeStart(TmpVar.getPointer()))
945 NormalEHLifetimeMarker, TmpVar);
946
951
952 // Calculate total array size (= range size).
953 llvm::Value *Range =
954 llvm::ConstantInt::get(CGM.IntTy, getTotalArraySize(AST, ResArrayTy));
955
956 // If the result of the subscript operation is a single resource, call the
957 // constructor.
958 if (ResultTy == ResourceTy) {
959 CallArgList Args;
960 CXXMethodDecl *CreateMethod = lookupResourceInitMethodAndSetupArgs(
961 CGF.CGM, ResourceTy->getAsCXXRecordDecl(), Range, Index,
962 ArrayDecl->getName(), Binding, Args);
963
964 if (!CreateMethod)
965 // This can happen if someone creates an array of structs that looks like
966 // an HLSL resource record array but it does not have the required static
967 // create method. No binding will be generated for it.
968 return std::nullopt;
969
970 callResourceInitMethod(CGF, CreateMethod, Args, ValueSlot.getAddress());
971
972 } else {
973 // The result of the subscript operation is a local resource array which
974 // needs to be initialized.
975 const ConstantArrayType *ArrayTy =
977 std::optional<llvm::Value *> EndIndex = initializeLocalResourceArray(
978 CGF, ResourceTy->getAsCXXRecordDecl(), ArrayTy, ValueSlot, Range, Index,
979 ArrayDecl->getName(), Binding, {llvm::ConstantInt::get(CGM.IntTy, 0)},
980 ArraySubsExpr->getExprLoc());
981 if (!EndIndex)
982 return std::nullopt;
983 }
984 return CGF.MakeAddrLValue(TmpVar, ResultTy, AlignmentSource::Decl);
985}
Defines the clang::ASTContext interface.
static llvm::Value * createSPIRVBuiltinLoad(IRBuilder<> &B, llvm::Module &M, llvm::Type *Ty, const Twine &Name, unsigned BuiltInID)
static void fillPackoffsetLayout(const HLSLBufferDecl *BufDecl, SmallVector< int32_t > &Layout)
static void addSPIRVBuiltinDecoration(llvm::GlobalVariable *GV, unsigned BuiltIn)
static void gatherFunctions(SmallVectorImpl< Function * > &Fns, llvm::Module &M, bool CtorOrDtor)
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)
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:220
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
uint64_t getTypeSize(QualType T) const
Return the size of the specified (complete) type T, in bits.
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:2721
SourceLocation getExprLoc() const LLVM_READONLY
Definition Expr.h:2776
QualType getElementType() const
Definition TypeBase.h:3734
Attr - This represents one attribute.
Definition Attr.h:44
Represents a static or instance method of a struct/union/class.
Definition DeclCXX.h:2129
Represents a C++ struct/union/class.
Definition DeclCXX.h:258
QualType withConst() const
Retrieves a version of this type with const applied.
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
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:504
Address getAddress() const
Definition CGValue.h:644
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:587
Address CreateGEP(CodeGenFunction &CGF, Address Addr, llvm::Value *Index, const llvm::Twine &Name="")
Definition CGBuilder.h:296
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.
llvm::Instruction * getConvergenceToken(llvm::BasicBlock &BB)
void setHLSLEntryAttributes(const FunctionDecl *FD, llvm::Function *Fn)
llvm::Value * handleScalarSemanticLoad(llvm::IRBuilder<> &B, llvm::Type *Type, const clang::DeclaratorDecl *Decl, SemanticInfo &ActiveSemantic)
llvm::Value * emitSystemSemanticLoad(llvm::IRBuilder<> &B, llvm::Type *Type, const clang::DeclaratorDecl *Decl, SemanticInfo &ActiveSemantic)
void addHLSLBufferLayoutType(const RecordType *LayoutStructTy, llvm::TargetExtType *LayoutTy)
void emitEntryFunction(const FunctionDecl *FD, llvm::Function *Fn)
void handleGlobalVarDefinition(const VarDecl *VD, llvm::GlobalVariable *Var)
llvm::TargetExtType * getHLSLBufferLayoutType(const RecordType *LayoutStructTy)
llvm::Type * convertHLSLSpecificType(const Type *T, SmallVector< int32_t > *Packoffsets=nullptr)
llvm::Value * handleSemanticLoad(llvm::IRBuilder<> &B, llvm::Type *Type, const clang::DeclaratorDecl *Decl, SemanticInfo &ActiveSemantic)
std::optional< LValue > emitResourceArraySubscriptExpr(const ArraySubscriptExpr *E, CodeGenFunction &CGF)
void addRootSignature(const HLSLRootSignatureDecl *D)
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...
void pushFullExprCleanup(CleanupKind kind, As... A)
pushFullExprCleanup - Push a cleanup to be run at the end of the current full-expression.
bool EmitLifetimeStart(llvm::Value *Addr)
Emit a lifetime.begin marker if some criteria are satisfied.
Definition CGDecl.cpp:1356
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:5241
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:264
llvm::Type * ConvertTypeForMem(QualType T)
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:186
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:1631
bool isOpaqueValueEmitted(const OpaqueValueExpr *E)
isOpaqueValueEmitted - Return true if the opaque value expression has already been emitted.
Definition CGExpr.cpp:5897
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.
ASTContext & getContext() 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)
Figure out the rules for calling a function with the given formal type using the given arguments.
Definition CGCall.cpp:699
llvm::Constant * getPointer() const
Definition Address.h:308
LValue - This represents an lvalue references.
Definition CGValue.h:182
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:98
An abstract representation of an aligned address.
Definition Address.h:42
llvm::Value * getPointer() const
Definition Address.h:66
ReturnValueSlot - Contains the address where the return value of a function can be stored,...
Definition CGCall.h:379
Represents the canonical version of C arrays with a specified constant size.
Definition TypeBase.h:3760
int64_t getSExtSize() const
Return the size sign-extended as a uint64_t.
Definition TypeBase.h:3842
A reference to a declared variable, function, enum, etc.
Definition Expr.h:1270
Decl - This represents one declaration (or definition), e.g.
Definition DeclBase.h:86
T * getAttr() const
Definition DeclBase.h:573
bool hasAttrs() const
Definition DeclBase.h:518
ASTContext & getASTContext() const LLVM_READONLY
Definition DeclBase.cpp:524
AttrVec & getAttrs()
Definition DeclBase.h:524
Represents a ValueDecl that came out of a declarator.
Definition Decl.h:779
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:3085
Expr * IgnoreImpCasts() LLVM_READONLY
Skip past any implicit casts which might surround this expression until reaching a fixed point.
Definition Expr.cpp:3065
QualType getType() const
Definition Expr.h:144
Represents a function declaration or definition.
Definition Decl.h:1999
const ParmVarDecl * getParamDecl(unsigned i) const
Definition Decl.h:2794
Represents a prototype with parameter type info, e.g.
Definition TypeBase.h:5266
HLSLBufferDecl - Represent a cbuffer or tbuffer declaration.
Definition Decl.h:5173
bool isCBuffer() const
Definition Decl.h:5217
const CXXRecordDecl * getLayoutStruct() const
Definition Decl.h:5220
bool hasValidPackoffset() const
Definition Decl.h:5219
buffer_decl_range buffer_decls() const
Definition Decl.h:5248
This class represents temporary values used to represent inout and out arguments in HLSL.
Definition Expr.h:7271
ArrayRef< llvm::hlsl::rootsig::RootElement > getRootElements() const
Definition Decl.h:5290
llvm::dxbc::RootSignatureVersion getVersion() const
Definition Decl.h:5288
unsigned getSemanticIndex() const
Definition Attr.h:260
Describes an C or C++ initializer list.
Definition Expr.h:5233
StringRef getName() const
Get the name of identifier for this declaration as a StringRef.
Definition Decl.h:300
OpaqueValueExpr - An expression referring to an opaque object of a fixed type and value class.
Definition Expr.h:1178
Expr * getSourceExpr() const
The source expression of an opaque value expression is the expression which originally generated the ...
Definition Expr.h:1228
Represents a parameter to a function.
Definition Decl.h:1789
A (possibly-)qualified type.
Definition TypeBase.h:937
const Type * getTypePtr() const
Retrieves a pointer to the underlying (unqualified) type.
Definition TypeBase.h:8287
LangAS getAddressSpace() const
Return the address space of this type.
Definition TypeBase.h:8413
The collection of all-type qualifiers we support.
Definition TypeBase.h:331
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:1833
bool isIncompleteArrayType() const
Definition TypeBase.h:8631
CXXRecordDecl * getAsCXXRecordDecl() const
Retrieves the CXXRecordDecl that this type refers to, either because the type is a RecordType or beca...
Definition Type.h:26
bool isArrayType() const
Definition TypeBase.h:8623
bool isHLSLResourceRecord() const
Definition Type.cpp:5370
const T * getAs() const
Member-template getAs<specific type>'.
Definition TypeBase.h:9100
const Type * getUnqualifiedDesugaredType() const
Return the specified type with any "sugar" removed from the type, removing any typedefs,...
Definition Type.cpp:653
bool isHLSLResourceRecordArray() const
Definition Type.cpp:5374
Represent the declaration of a variable (in which case it is an lvalue) a function (in which case it ...
Definition Decl.h:711
QualType getType() const
Definition Decl.h:722
Represents a variable declaration or definition.
Definition Decl.h:925
bool hasGlobalStorage() const
Returns true for all variables that do not have local storage.
Definition Decl.h:1225
StorageClass getStorageClass() const
Returns the storage class as written in the source.
Definition Decl.h:1167
@ Type
The l-value was considered opaque, so the alignment was determined from a type.
Definition CGValue.h:154
@ Decl
The l-value was an access to a declared entity or something equivalently strong, like the address of ...
Definition CGValue.h:145
The JSON file list parser is used to communicate input to InstallAPI.
bool isa(CodeGen::Address addr)
Definition Address.h:330
nullptr
This class represents a compute construct, representing a 'Kind' of ‘parallel’, 'serial',...
StorageClass
Storage classes.
Definition Specifiers.h:248
@ SC_Static
Definition Specifiers.h:252
@ SC_None
Definition Specifiers.h:250
const FunctionProtoType * T
U cast(CodeGen::Address addr)
Definition Address.h:327
Diagnostic wrappers for TextAPI types for error reporting.
Definition Dominators.h:30