22#include "clang/AST/Attrs.inc"
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"
51using llvm::hlsl::CBufferRowSizeInBytes;
55void addDxilValVersion(StringRef ValVersionStr, llvm::Module &M) {
59 if (Version.tryParse(ValVersionStr) || Version.getBuild() ||
60 Version.getSubminor() || !Version.getMinor()) {
64 uint64_t Major = Version.getMajor();
65 uint64_t Minor = *Version.getMinor();
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);
76void addRootSignatureMD(llvm::dxbc::RootSignatureVersion RootSigVer,
78 llvm::Function *Fn, llvm::Module &M) {
79 auto &Ctx = M.getContext();
81 llvm::hlsl::rootsig::MetadataBuilder RSBuilder(Ctx, Elements);
82 MDNode *RootSignature = RSBuilder.BuildRootSignature();
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});
89 StringRef RootSignatureValKey =
"dx.rootsignatures";
90 auto *RootSignatureValMD = M.getOrInsertNamedMetadata(RootSignatureValKey);
91 RootSignatureValMD->addOperand(MDVals);
96 const Expr *E =
nullptr;
97 while (ASE !=
nullptr) {
101 ASE = dyn_cast<ArraySubscriptExpr>(E);
103 if (
const DeclRefExpr *DRE = dyn_cast_or_null<DeclRefExpr>(E))
104 return DRE->getDecl();
111 assert(Ty->
isArrayType() &&
"expected array type");
117static Value *buildNameForResource(llvm::StringRef BaseName,
126 for (
auto *Method :
Record->methods()) {
127 if (Method->getStorageClass() == SC && Method->getName() == Name)
137 assert(Binding.
hasBinding() &&
"at least one binding attribute expected");
141 Value *NameStr = buildNameForResource(Name, CGM);
146 auto *RegSlot = llvm::ConstantInt::get(CGM.
IntTy, Binding.
getSlot());
149 ?
"__createFromBindingWithImplicitCounter"
150 :
"__createFromBinding";
151 CreateMethod = lookupMethod(ResourceDecl, Name,
SC_Static);
158 ?
"__createFromImplicitBindingWithImplicitCounter"
159 :
"__createFromImplicitBinding";
160 CreateMethod = lookupMethod(ResourceDecl, Name,
SC_Static);
168 auto *CounterOrderID = llvm::ConstantInt::get(CGM.
IntTy, CounterBinding);
185 CGF.
EmitCall(FnInfo, Callee, ReturnValue, Args,
nullptr);
193static std::optional<llvm::Value *> initializeLocalResourceArray(
196 llvm::Value *Range, llvm::Value *StartIndex, StringRef ResourceName,
201 llvm::IntegerType *IntTy = CGF.
CGM.
IntTy;
202 llvm::Value *Index = StartIndex;
203 llvm::Value *One = llvm::ConstantInt::get(IntTy, 1);
211 GEPIndices.push_back(llvm::ConstantInt::get(IntTy, 0));
216 for (uint64_t I = 0; I < ArraySize; I++) {
218 Index = CGF.
Builder.CreateAdd(Index, One);
219 GEPIndices.back() = llvm::ConstantInt::get(IntTy, I);
221 std::optional<llvm::Value *> MaybeIndex = initializeLocalResourceArray(
222 CGF, ResourceDecl, SubArrayTy, ValueSlot, Range, Index, ResourceName,
223 Binding, GEPIndices, ArraySubsExprLoc);
237 for (uint64_t I = 0; I < ArraySize; I++) {
239 Index = CGF.
Builder.CreateAdd(Index, One);
240 GEPIndices.back() = llvm::ConstantInt::get(IntTy, I);
246 CXXMethodDecl *CreateMethod = lookupResourceInitMethodAndSetupArgs(
247 CGF.
CGM, ResourceDecl, Range, Index, ResourceName, Binding, Args);
255 callResourceInitMethod(CGF, CreateMethod, Args, ReturnAddress);
265 assert(
T->isHLSLSpecificType() &&
"Not an HLSL specific type!");
268 if (llvm::Type *TargetTy =
269 CGM.getTargetCodeGenInfo().getHLSLType(
CGM,
T, Packoffsets))
272 llvm_unreachable(
"Generic handling of HLSL types is not supported.");
275llvm::Triple::ArchType CGHLSLRuntime::getArch() {
281void CGHLSLRuntime::emitBufferGlobalsAndMetadata(
const HLSLBufferDecl *BufDecl,
282 llvm::GlobalVariable *BufGV) {
286 llvm::Type *BufType = BufGV->getValueType();
287 llvm::Type *BufLayoutType =
295 BufGlobals.push_back(ValueAsMetadata::get(BufGV));
297 const auto *ElemIt = LayoutStruct->element_begin();
307 VarDecl *VD = dyn_cast<VarDecl>(D);
323 "constant buffer decl with non-zero sized type outside of "
324 "hlsl_constant address space");
329 assert(ElemIt != LayoutStruct->element_end() &&
330 "number of elements in layout struct does not match");
331 llvm::Type *LayoutType = *ElemIt++;
337 GlobalVariable *ElemGV =
339 BufGlobals.push_back(ValueAsMetadata::get(ElemGV));
341 assert(ElemIt == LayoutStruct->element_end() &&
342 "number of elements in layout struct does not match");
346 .getOrInsertNamedMetadata(
"hlsl.cbs")
347 ->addOperand(MDNode::get(Ctx, BufGlobals));
351static const clang::HLSLAttributedResourceType *
356 HLSLAttributedResourceType::Attributes(ResourceClass::CBuffer));
375 assert(Layout.empty() &&
"expected empty vector for layout");
382 VarDecl *VD = dyn_cast<VarDecl>(D);
387 Layout.push_back(-1);
393 if (
auto *POA = dyn_cast<HLSLPackOffsetAttr>(
Attr)) {
394 Offset = POA->getOffsetInBytes();
397 auto *RBA = dyn_cast<HLSLResourceBindingAttr>(
Attr);
399 RBA->getRegisterType() == HLSLResourceBindingAttr::RegisterType::C) {
400 Offset = RBA->getSlotNumber() * CBufferRowSizeInBytes;
404 Layout.push_back(Offset);
411 assert(BufDecl->
isCBuffer() &&
"tbuffer codegen is not supported yet");
414 const clang::HLSLAttributedResourceType *ResHandleTy =
418 if (ResHandleTy->getContainedType()->getAsCXXRecordDecl()->isEmpty())
426 llvm::TargetExtType *TargetTy =
429 llvm::GlobalVariable *BufGV =
new GlobalVariable(
431 GlobalValue::LinkageTypes::ExternalLinkage, PoisonValue::get(TargetTy),
432 llvm::formatv(
"{0}{1}", BufDecl->
getName(),
434 GlobalValue::NotThreadLocal);
435 CGM.getModule().insertGlobalVariable(BufGV);
438 emitBufferGlobalsAndMetadata(BufDecl, BufGV);
441 initializeBufferFromBinding(BufDecl, BufGV);
446 llvm::Module &M =
CGM.getModule();
447 Triple
T(M.getTargetTriple());
450 if (
T.getEnvironment() != Triple::EnvironmentType::RootSignature)
453 addRootSignatureMD(SignatureDecl->
getVersion(),
459 const auto Entry = LayoutTypes.find(StructType);
460 if (Entry != LayoutTypes.end())
461 return Entry->getSecond();
466 llvm::TargetExtType *LayoutTy) {
468 "layout type for this struct already exist");
469 LayoutTypes[StructType] = LayoutTy;
473 auto &TargetOpts =
CGM.getTarget().getTargetOpts();
474 auto &CodeGenOpts =
CGM.getCodeGenOpts();
475 auto &LangOpts =
CGM.getLangOpts();
476 llvm::Module &M =
CGM.getModule();
477 Triple
T(M.getTargetTriple());
478 if (
T.getArch() == Triple::ArchType::dxil)
479 addDxilValVersion(TargetOpts.DxilValidatorVersion, M);
480 if (CodeGenOpts.ResMayAlias)
481 M.setModuleFlag(llvm::Module::ModFlagBehavior::Error,
"dx.resmayalias", 1);
486 if (LangOpts.NativeHalfType)
487 M.setModuleFlag(llvm::Module::ModFlagBehavior::Error,
"dx.nativelowprec",
495 const auto *ShaderAttr = FD->
getAttr<HLSLShaderAttr>();
496 assert(ShaderAttr &&
"All entry functions must have a HLSLShaderAttr");
497 const StringRef ShaderAttrKindStr =
"hlsl.shader";
498 Fn->addFnAttr(ShaderAttrKindStr,
499 llvm::Triple::getEnvironmentTypeName(ShaderAttr->getType()));
500 if (HLSLNumThreadsAttr *NumThreadsAttr = FD->
getAttr<HLSLNumThreadsAttr>()) {
501 const StringRef NumThreadsKindStr =
"hlsl.numthreads";
502 std::string NumThreadsStr =
503 formatv(
"{0},{1},{2}", NumThreadsAttr->getX(), NumThreadsAttr->getY(),
504 NumThreadsAttr->getZ());
505 Fn->addFnAttr(NumThreadsKindStr, NumThreadsStr);
507 if (HLSLWaveSizeAttr *WaveSizeAttr = FD->
getAttr<HLSLWaveSizeAttr>()) {
508 const StringRef WaveSizeKindStr =
"hlsl.wavesize";
509 std::string WaveSizeStr =
510 formatv(
"{0},{1},{2}", WaveSizeAttr->getMin(), WaveSizeAttr->getMax(),
511 WaveSizeAttr->getPreferred());
512 Fn->addFnAttr(WaveSizeKindStr, WaveSizeStr);
519 if (
CGM.getCodeGenOpts().OptimizationLevel == 0)
520 Fn->addFnAttr(llvm::Attribute::OptimizeNone);
521 Fn->addFnAttr(llvm::Attribute::NoInline);
523 if (
CGM.getLangOpts().HLSLSpvEnableMaximalReconvergence) {
524 Fn->addFnAttr(
"enable-maximal-reconvergence",
"true");
529 if (
const auto *VT = dyn_cast<FixedVectorType>(Ty)) {
530 Value *Result = PoisonValue::get(Ty);
531 for (
unsigned I = 0; I < VT->getNumElements(); ++I) {
532 Value *Elt = B.CreateCall(F, {B.getInt32(I)});
533 Result = B.CreateInsertElement(Result, Elt, I);
537 return B.CreateCall(F, {B.getInt32(0)});
542 LLVMContext &Ctx = GV->getContext();
543 IRBuilder<> B(GV->getContext());
544 MDNode *Operands = MDNode::get(
546 {ConstantAsMetadata::get(B.getInt32( 11)),
547 ConstantAsMetadata::get(B.getInt32(BuiltIn))});
548 MDNode *Decoration = MDNode::get(Ctx, {Operands});
549 GV->addMetadata(
"spirv.Decorations", *Decoration);
553 LLVMContext &Ctx = GV->getContext();
554 IRBuilder<> B(GV->getContext());
556 MDNode::get(Ctx, {ConstantAsMetadata::get(B.getInt32( 30)),
557 ConstantAsMetadata::get(B.getInt32(Location))});
558 MDNode *Decoration = MDNode::get(Ctx, {Operands});
559 GV->addMetadata(
"spirv.Decorations", *Decoration);
563 llvm::Type *Ty,
const Twine &Name,
564 unsigned BuiltInID) {
565 auto *GV =
new llvm::GlobalVariable(
566 M, Ty,
true, llvm::GlobalValue::ExternalLinkage,
567 nullptr, Name,
nullptr,
568 llvm::GlobalVariable::GeneralDynamicTLSModel,
571 GV->setVisibility(llvm::GlobalValue::HiddenVisibility);
572 return B.CreateLoad(Ty, GV);
576 llvm::Type *Ty,
unsigned Location,
578 auto *GV =
new llvm::GlobalVariable(
579 M, Ty,
true, llvm::GlobalValue::ExternalLinkage,
580 nullptr, Name,
nullptr,
581 llvm::GlobalVariable::GeneralDynamicTLSModel,
583 GV->setVisibility(llvm::GlobalValue::HiddenVisibility);
585 return B.CreateLoad(Ty, GV);
589CGHLSLRuntime::emitSPIRVUserSemanticLoad(llvm::IRBuilder<> &B, llvm::Type *
Type,
590 HLSLSemanticAttr *Semantic,
591 std::optional<unsigned> Index) {
593 Twine VariableName = BaseName.concat(Twine(Index.value_or(0)));
595 unsigned Location = SPIRVLastAssignedInputSemanticLocation;
599 llvm::ArrayType *AT = dyn_cast<llvm::ArrayType>(
Type);
600 unsigned ElementCount = AT ? AT->getNumElements() : 1;
601 SPIRVLastAssignedInputSemanticLocation += ElementCount;
607CGHLSLRuntime::emitDXILUserSemanticLoad(llvm::IRBuilder<> &B, llvm::Type *
Type,
608 HLSLSemanticAttr *Semantic,
609 std::optional<unsigned> Index) {
611 Twine VariableName = BaseName.concat(Twine(Index.value_or(0)));
616 SmallVector<Value *> Args{B.getInt32(4), B.getInt32(0), B.getInt32(0),
618 llvm::PoisonValue::get(B.getInt32Ty())};
620 llvm::Intrinsic::ID IntrinsicID = llvm::Intrinsic::dx_load_input;
621 llvm::Value *
Value = B.CreateIntrinsic(
Type, IntrinsicID, Args,
622 nullptr, VariableName);
626llvm::Value *CGHLSLRuntime::emitUserSemanticLoad(
627 IRBuilder<> &B, llvm::Type *
Type,
const clang::DeclaratorDecl *
Decl,
628 HLSLSemanticAttr *Semantic, std::optional<unsigned> Index) {
629 if (
CGM.getTarget().getTriple().isSPIRV())
630 return emitSPIRVUserSemanticLoad(B,
Type, Semantic, Index);
632 if (
CGM.getTarget().getTriple().isDXIL())
633 return emitDXILUserSemanticLoad(B,
Type, Semantic, Index);
635 llvm_unreachable(
"Unsupported target for user-semantic load.");
640 Attr *Semantic, std::optional<unsigned> Index) {
642 llvm::Function *GroupIndex =
643 CGM.getIntrinsic(getFlattenedThreadIdInGroupIntrinsic());
644 return B.CreateCall(FunctionCallee(GroupIndex));
648 llvm::Intrinsic::ID IntrinID = getThreadIdIntrinsic();
649 llvm::Function *ThreadIDIntrinsic =
650 llvm::Intrinsic::isOverloaded(IntrinID)
651 ?
CGM.getIntrinsic(IntrinID, {
CGM.Int32Ty})
652 :
CGM.getIntrinsic(IntrinID);
657 llvm::Intrinsic::ID IntrinID = getGroupThreadIdIntrinsic();
658 llvm::Function *GroupThreadIDIntrinsic =
659 llvm::Intrinsic::isOverloaded(IntrinID)
660 ?
CGM.getIntrinsic(IntrinID, {
CGM.Int32Ty})
661 :
CGM.getIntrinsic(IntrinID);
666 llvm::Intrinsic::ID IntrinID = getGroupIdIntrinsic();
667 llvm::Function *GroupIDIntrinsic =
668 llvm::Intrinsic::isOverloaded(IntrinID)
669 ?
CGM.getIntrinsic(IntrinID, {
CGM.Int32Ty})
670 :
CGM.getIntrinsic(IntrinID);
674 if (HLSLSV_PositionAttr *S = dyn_cast<HLSLSV_PositionAttr>(Semantic)) {
675 if (
CGM.getTriple().getEnvironment() == Triple::EnvironmentType::Pixel)
677 S->getAttrName()->getName(),
681 llvm_unreachable(
"non-handled system semantic. FIXME.");
691 if (Item->getTargetDecl() ==
Decl) {
699 std::optional<unsigned> Index = std::nullopt;
704 return emitUserSemanticLoad(B,
Type,
Decl, Semantic, Index);
716 ST->getNumElements());
720 for (
unsigned I = 0; I < ST->getNumElements(); ++I) {
721 llvm::Value *ChildValue =
735 if (
Type->isStructTy())
741 llvm::Function *Fn) {
742 llvm::Module &M =
CGM.getModule();
743 llvm::LLVMContext &Ctx = M.getContext();
744 auto *EntryTy = llvm::FunctionType::get(llvm::Type::getVoidTy(Ctx),
false);
746 Function::Create(EntryTy, Function::ExternalLinkage, FD->
getName(), &M);
750 AttributeList NewAttrs = AttributeList::get(Ctx, AttributeList::FunctionIndex,
751 Fn->getAttributes().getFnAttrs());
752 EntryFn->setAttributes(NewAttrs);
756 Fn->setLinkage(GlobalValue::InternalLinkage);
758 BasicBlock *BB = BasicBlock::Create(Ctx,
"entry", EntryFn);
763 if (
CGM.shouldEmitConvergenceTokens()) {
764 assert(EntryFn->isConvergent());
766 B.CreateIntrinsic(llvm::Intrinsic::experimental_convergence_entry, {});
767 llvm::Value *bundleArgs[] = {I};
768 OB.emplace_back(
"convergencectrl", bundleArgs);
773 unsigned SRetOffset = 0;
774 for (
const auto &Param : Fn->args()) {
775 if (Param.hasStructRetAttr()) {
779 Args.emplace_back(PoisonValue::get(Param.getType()));
784 llvm::Value *SemanticValue =
nullptr;
785 if ([[maybe_unused]] HLSLParamModifierAttr *MA =
786 PD->
getAttr<HLSLParamModifierAttr>()) {
787 llvm_unreachable(
"Not handled yet");
789 llvm::Type *ParamType =
790 Param.hasByValAttr() ? Param.getParamByValType() : Param.getType();
794 if (Param.hasByValAttr()) {
795 llvm::Value *Var = B.CreateAlloca(Param.getParamByValType());
796 B.CreateStore(SemanticValue, Var);
801 assert(SemanticValue);
802 Args.push_back(SemanticValue);
805 CallInst *CI = B.CreateCall(FunctionCallee(Fn), Args, OB);
806 CI->setCallingConv(Fn->getCallingConv());
813 if (
const auto *RSAttr = dyn_cast<RootSignatureAttr>(
Attr)) {
814 auto *RSDecl = RSAttr->getSignatureDecl();
815 addRootSignatureMD(RSDecl->getVersion(), RSDecl->getRootElements(),
824 M.getNamedGlobal(CtorOrDtor ?
"llvm.global_ctors" :
"llvm.global_dtors");
827 const auto *CA = dyn_cast<ConstantArray>(GV->getInitializer());
834 for (
const auto &Ctor : CA->operands()) {
840 "HLSL doesn't support setting priority for global ctors.");
842 "HLSL doesn't support COMDat for global ctors.");
848 llvm::Module &M =
CGM.getModule();
857 for (
auto &F : M.functions()) {
858 if (!F.hasFnAttribute(
"hlsl.shader"))
861 Instruction *IP = &*F.getEntryBlock().begin();
864 llvm::Value *bundleArgs[] = {
Token};
865 OB.emplace_back(
"convergencectrl", bundleArgs);
866 IP =
Token->getNextNode();
869 for (
auto *Fn : CtorFns) {
870 auto CI = B.CreateCall(FunctionCallee(Fn), {}, OB);
871 CI->setCallingConv(Fn->getCallingConv());
875 B.SetInsertPoint(F.back().getTerminator());
876 for (
auto *Fn : DtorFns) {
877 auto CI = B.CreateCall(FunctionCallee(Fn), {}, OB);
878 CI->setCallingConv(Fn->getCallingConv());
884 Triple
T(M.getTargetTriple());
885 if (
T.getEnvironment() != Triple::EnvironmentType::Library) {
886 if (
auto *GV = M.getNamedGlobal(
"llvm.global_ctors"))
887 GV->eraseFromParent();
888 if (
auto *GV = M.getNamedGlobal(
"llvm.global_dtors"))
889 GV->eraseFromParent();
894 Intrinsic::ID IntrID,
898 llvm::Function *InitResFunc = llvm::Function::Create(
899 llvm::FunctionType::get(CGM.
VoidTy,
false),
900 llvm::GlobalValue::InternalLinkage,
901 (
"_init_buffer_" + GV->getName()).str(), CGM.
getModule());
902 InitResFunc->addFnAttr(llvm::Attribute::AlwaysInline);
904 llvm::BasicBlock *EntryBB =
905 llvm::BasicBlock::Create(Ctx,
"entry", InitResFunc);
907 const DataLayout &DL = CGM.
getModule().getDataLayout();
908 Builder.SetInsertPoint(EntryBB);
911 llvm::Type *HandleTy = GV->getValueType();
912 assert(HandleTy->isTargetExtTy() &&
"unexpected type of the buffer global");
914 llvm::Value *CreateHandle = Builder.CreateIntrinsic(
915 HandleTy, IntrID, Args,
nullptr,
916 Twine(GV->getName()).concat(
"_h"));
918 llvm::Value *HandleRef = Builder.CreateStructGEP(GV->getValueType(), GV, 0);
919 Builder.CreateAlignedStore(CreateHandle, HandleRef,
920 HandleRef->getPointerAlignment(DL));
921 Builder.CreateRetVoid();
926void CGHLSLRuntime::initializeBufferFromBinding(
const HLSLBufferDecl *BufDecl,
927 llvm::GlobalVariable *GV) {
928 ResourceBindingAttrs Binding(BufDecl);
930 "cbuffer/tbuffer should always have resource binding attribute");
932 auto *Index = llvm::ConstantInt::get(
CGM.IntTy, 0);
933 auto *RangeSize = llvm::ConstantInt::get(
CGM.IntTy, 1);
934 auto *Space = llvm::ConstantInt::get(
CGM.IntTy, Binding.
getSpace());
939 llvm::Intrinsic::ID IntrinsicID =
940 CGM.getHLSLRuntime().getCreateHandleFromBindingIntrinsic();
941 auto *RegSlot = llvm::ConstantInt::get(
CGM.IntTy, Binding.
getSlot());
942 SmallVector<Value *> Args{Space, RegSlot, RangeSize, Index, Name};
946 llvm::Intrinsic::ID IntrinsicID =
947 CGM.getHLSLRuntime().getCreateHandleFromImplicitBindingIntrinsic();
950 SmallVector<Value *> Args{OrderID, Space, RangeSize, Index, Name};
956 llvm::GlobalVariable *GV) {
957 if (
auto Attr = VD->
getAttr<HLSLVkExtBuiltinInputAttr>())
962 if (!
CGM.shouldEmitConvergenceTokens())
966 for (
auto I = BB.begin(); I != E; ++I) {
967 auto *II = dyn_cast<llvm::IntrinsicInst>(&*I);
968 if (II && llvm::isConvergenceControlIntrinsic(II->getIntrinsicID())) {
972 llvm_unreachable(
"Convergence token should have been emitted.");
1009 for (
auto *OVE : Visitor.
OVEs) {
1012 if (OpaqueValueMappingData::shouldBindAsLValue(OVE)) {
1014 OpaqueValueMappingData::bind(CGF, OVE, LV);
1017 OpaqueValueMappingData::bind(CGF, OVE, RV);
1026 "expected resource array subscript expression");
1032 dyn_cast_or_null<VarDecl>(getArrayDecl(ArraySubsExpr));
1034 return std::nullopt;
1040 "expected array of resource classes");
1046 Value *Index =
nullptr;
1048 while (ASE !=
nullptr) {
1050 if (
const auto *ArrayTy =
1052 Value *Multiplier = llvm::ConstantInt::get(
1054 SubIndex = CGF.
Builder.CreateMul(SubIndex, Multiplier);
1056 Index = Index ? CGF.
Builder.CreateAdd(Index, SubIndex) : SubIndex;
1064 "resource array must have a binding attribute");
1085 llvm::Value *Range =
1086 llvm::ConstantInt::get(
CGM.IntTy, getTotalArraySize(AST, ResArrayTy));
1090 if (ResultTy == ResourceTy) {
1092 CXXMethodDecl *CreateMethod = lookupResourceInitMethodAndSetupArgs(
1094 ArrayDecl->
getName(), Binding, Args);
1100 return std::nullopt;
1102 callResourceInitMethod(CGF, CreateMethod, Args, ValueSlot.getAddress());
1109 std::optional<llvm::Value *> EndIndex = initializeLocalResourceArray(
1111 ArrayDecl->
getName(), Binding, {llvm::ConstantInt::get(CGM.IntTy, 0)},
1114 return std::nullopt;
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 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)
llvm::MachO::Record Record
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 ...
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.
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.
SourceLocation getExprLoc() const LLVM_READONLY
QualType getElementType() const
Attr - This represents one attribute.
const IdentifierInfo * getAttrName() const
Represents a static or instance method of a struct/union/class.
Represents a C++ struct/union/class.
QualType withConst() const
Retrieves a version of this type with const applied.
CharUnits - This is an opaque type for sizes expressed in character units.
CharUnits alignmentOfArrayElement(CharUnits elementSize) const
Given that this is the alignment of the first element of an array, return the minimum alignment of an...
Like RawAddress, an abstract representation of an aligned address, but the pointer contained in this ...
CharUnits getAlignment() const
Address getAddress() const
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.
Address CreateGEP(CodeGenFunction &CGF, Address Addr, llvm::Value *Index, const llvm::Twine &Name="")
Abstract information about a function or function prototype.
All available information about a concrete callee.
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 * handleStructSemanticLoad(llvm::IRBuilder<> &B, const FunctionDecl *FD, llvm::Type *Type, const clang::DeclaratorDecl *Decl)
void addHLSLBufferLayoutType(const RecordType *LayoutStructTy, llvm::TargetExtType *LayoutTy)
llvm::Value * emitSystemSemanticLoad(llvm::IRBuilder<> &B, llvm::Type *Type, const clang::DeclaratorDecl *Decl, Attr *Semantic, std::optional< unsigned > Index)
void emitEntryFunction(const FunctionDecl *FD, llvm::Function *Fn)
void handleGlobalVarDefinition(const VarDecl *VD, llvm::GlobalVariable *Var)
llvm::TargetExtType * getHLSLBufferLayoutType(const RecordType *LayoutStructTy)
llvm::Value * handleScalarSemanticLoad(llvm::IRBuilder<> &B, const FunctionDecl *FD, llvm::Type *Type, const clang::DeclaratorDecl *Decl)
llvm::Type * convertHLSLSpecificType(const Type *T, SmallVector< int32_t > *Packoffsets=nullptr)
llvm::Value * handleSemanticLoad(llvm::IRBuilder<> &B, const FunctionDecl *FD, llvm::Type *Type, const clang::DeclaratorDecl *Decl)
std::optional< LValue > emitResourceArraySubscriptExpr(const ArraySubscriptExpr *E, CodeGenFunction &CGF)
void addRootSignature(const HLSLRootSignatureDecl *D)
void addBuffer(const HLSLBufferDecl *D)
void generateGlobalCtorDtorCalls()
void emitInitListOpaqueValues(CodeGenFunction &CGF, InitListExpr *E)
CallArgList - Type for representing both the value and type of arguments in a call.
void add(RValue rvalue, QualType type)
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.
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,...
ASTContext & getContext() const
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.
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...
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.
bool isOpaqueValueEmitted(const OpaqueValueExpr *E)
isOpaqueValueEmitted - Return true if the opaque value expression has already been emitted.
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)
CodeGenTypes & getTypes()
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.
llvm::Constant * getPointer() const
LValue - This represents an lvalue references.
RValue - This trivial value class is used to represent the result of an expression that is evaluated.
static RValue get(llvm::Value *V)
An abstract representation of an aligned address.
llvm::Value * getPointer() const
ReturnValueSlot - Contains the address where the return value of a function can be stored,...
Represents the canonical version of C arrays with a specified constant size.
int64_t getSExtSize() const
Return the size sign-extended as a uint64_t.
A reference to a declared variable, function, enum, etc.
Decl - This represents one declaration (or definition), e.g.
ASTContext & getASTContext() const LLVM_READONLY
llvm::iterator_range< specific_attr_iterator< T > > specific_attrs() const
Represents a ValueDecl that came out of a declarator.
This represents one expression.
Expr * IgnoreParenImpCasts() LLVM_READONLY
Skip past any parentheses and implicit casts which might surround this expression until reaching a fi...
Expr * IgnoreImpCasts() LLVM_READONLY
Skip past any implicit casts which might surround this expression until reaching a fixed point.
Represents a member of a struct/union/class.
Represents a function declaration or definition.
const ParmVarDecl * getParamDecl(unsigned i) const
Represents a prototype with parameter type info, e.g.
HLSLBufferDecl - Represent a cbuffer or tbuffer declaration.
const CXXRecordDecl * getLayoutStruct() const
bool hasValidPackoffset() const
buffer_decl_range buffer_decls() const
This class represents temporary values used to represent inout and out arguments in HLSL.
ArrayRef< llvm::hlsl::rootsig::RootElement > getRootElements() const
llvm::dxbc::RootSignatureVersion getVersion() const
bool isSemanticIndexExplicit() const
unsigned getSemanticIndex() const
StringRef getName() const
Return the actual identifier string.
Describes an C or C++ initializer list.
StringRef getName() const
Get the name of identifier for this declaration as a StringRef.
OpaqueValueExpr - An expression referring to an opaque object of a fixed type and value class.
Expr * getSourceExpr() const
The source expression of an opaque value expression is the expression which originally generated the ...
Represents a parameter to a function.
A (possibly-)qualified type.
const Type * getTypePtr() const
Retrieves a pointer to the underlying (unqualified) type.
LangAS getAddressSpace() const
Return the address space of this type.
The collection of all-type qualifiers we support.
Represents a struct/union/class.
field_iterator field_end() const
field_iterator field_begin() const
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.
The base class of the type hierarchy.
bool isIncompleteArrayType() const
CXXRecordDecl * getAsCXXRecordDecl() const
Retrieves the CXXRecordDecl that this type refers to, either because the type is a RecordType or beca...
bool isHLSLResourceRecord() const
const T * getAs() const
Member-template getAs<specific type>'.
const Type * getUnqualifiedDesugaredType() const
Return the specified type with any "sugar" removed from the type, removing any typedefs,...
bool isHLSLResourceRecordArray() const
Represent the declaration of a variable (in which case it is an lvalue) a function (in which case it ...
Represents a variable declaration or definition.
bool hasGlobalStorage() const
Returns true for all variables that do not have local storage.
StorageClass getStorageClass() const
Returns the storage class as written in the source.
@ Type
The l-value was considered opaque, so the alignment was determined from a type.
@ Decl
The l-value was an access to a declared entity or something equivalently strong, like the address of ...
The JSON file list parser is used to communicate input to InstallAPI.
bool isa(CodeGen::Address addr)
nullptr
This class represents a compute construct, representing a 'Kind' of ‘parallel’, 'serial',...
StorageClass
Storage classes.
const FunctionProtoType * T
U cast(CodeGen::Address addr)
Diagnostic wrappers for TextAPI types for error reporting.
llvm::IntegerType * IntTy
int
unsigned getImplicitOrderID() const
bool hasCounterImplicitOrderID() const
unsigned getSpace() const
unsigned getCounterImplicitOrderID() const