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"
56using llvm::hlsl::CBufferRowSizeInBytes;
60void addDxilValVersion(StringRef ValVersionStr, llvm::Module &M) {
64 if (Version.tryParse(ValVersionStr) || Version.getBuild() ||
65 Version.getSubminor() || !Version.getMinor()) {
69 uint64_t Major = Version.getMajor();
70 uint64_t Minor = *Version.getMinor();
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);
81void addRootSignatureMD(llvm::dxbc::RootSignatureVersion RootSigVer,
83 llvm::Function *Fn, llvm::Module &M) {
84 auto &Ctx = M.getContext();
86 llvm::hlsl::rootsig::MetadataBuilder RSBuilder(Ctx, Elements);
87 MDNode *RootSignature = RSBuilder.BuildRootSignature();
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});
94 StringRef RootSignatureValKey =
"dx.rootsignatures";
95 auto *RootSignatureValMD = M.getOrInsertNamedMetadata(RootSignatureValKey);
96 RootSignatureValMD->addOperand(MDVals);
107static const VarDecl *findStructResourceParentDeclAndBuildName(
115 if (
const auto *DRE = dyn_cast<DeclRefExpr>(E)) {
117 "member expr base is not a var decl");
123 WorkList.push_back(E);
124 if (
const auto *MExp = dyn_cast<MemberExpr>(E))
126 else if (
const auto *ICE = dyn_cast<ImplicitCastExpr>(E))
127 E = ICE->getSubExpr();
128 else if (
const auto *ASE = dyn_cast<ArraySubscriptExpr>(E))
135 llvm_unreachable(
"unexpected expr type in resource member access");
137 assert(E &&
"expected valid expression");
140 while (!WorkList.empty()) {
141 E = WorkList.pop_back_val();
142 if (
const auto *ME = dyn_cast<MemberExpr>(E)) {
145 }
else if (
const auto *ICE = dyn_cast<ImplicitCastExpr>(E)) {
146 if (ICE->getCastKind() == CK_UncheckedDerivedToBase) {
148 ICE->getSubExpr()->getType()->getAsCXXRecordDecl();
149 CXXRecordDecl *BaseRD = ICE->getType()->getAsCXXRecordDecl();
152 }
else if (
const auto *ASE = dyn_cast<ArraySubscriptExpr>(E)) {
153 const Expr *IdxExpr = ASE->getIdx();
154 std::optional<llvm::APSInt>
Value =
157 "expected constant index in struct with resource array access");
160 llvm_unreachable(
"unexpected expr type in resource member access");
174 findStructResourceParentDeclAndBuildName(ME, NameBuilder);
183 if (
const auto *ADA = dyn_cast<HLSLAssociatedResourceDeclAttr>(A)) {
184 VarDecl *AssocResVD = ADA->getResDecl();
195 if (
const auto *DRE = dyn_cast_or_null<DeclRefExpr>(E))
196 return DRE->getDecl();
197 if (
auto *OVE = dyn_cast<OpaqueValueExpr>(E))
207 const Expr *E =
nullptr;
208 while (ASE !=
nullptr) {
212 ASE = dyn_cast<ArraySubscriptExpr>(E);
214 return getArrayDecl(AST, E);
220 assert(Ty->
isArrayType() &&
"expected array type");
226static Value *buildNameForResource(llvm::StringRef BaseName,
235 for (
auto *Method :
Record->methods()) {
236 if (Method->getStorageClass() == SC && Method->getName() == Name)
246 assert(Binding.
hasBinding() &&
"at least one binding attribute expected");
250 Value *NameStr = buildNameForResource(Name, CGM);
255 "resources with counter handle must have a binding with counter "
256 "implicit order ID");
259 auto *RegSlot = llvm::ConstantInt::get(CGM.
IntTy, Binding.
getSlot());
262 ?
"__createFromBindingWithImplicitCounter"
263 :
"__createFromBinding";
264 CreateMethod = lookupMethod(ResourceDecl, Name,
SC_Static);
271 ?
"__createFromImplicitBindingWithImplicitCounter"
272 :
"__createFromImplicitBinding";
273 CreateMethod = lookupMethod(ResourceDecl, Name,
SC_Static);
281 auto *CounterOrderID = llvm::ConstantInt::get(CGM.
IntTy, CounterBinding);
298 CGF.
EmitCall(FnInfo, Callee, ReturnValue, Args,
nullptr);
307static std::optional<llvm::Value *> initializeResourceArrayFromGlobal(
310 llvm::Value *Range, llvm::Value *StartIndex, StringRef ResourceName,
315 llvm::IntegerType *IntTy = CGF.
CGM.
IntTy;
316 llvm::Value *Index = StartIndex;
317 llvm::Value *One = llvm::ConstantInt::get(IntTy, 1);
325 GEPIndices.push_back(llvm::ConstantInt::get(IntTy, 0));
330 for (uint64_t I = 0; I < ArraySize; I++) {
332 Index = CGF.
Builder.CreateAdd(Index, One);
333 GEPIndices.back() = llvm::ConstantInt::get(IntTy, I);
335 std::optional<llvm::Value *> MaybeIndex =
336 initializeResourceArrayFromGlobal(
337 CGF, ResourceDecl, SubArrayTy, ValueSlot, Range, Index,
338 ResourceName, Binding, GEPIndices, ArraySubsExprLoc);
352 for (uint64_t I = 0; I < ArraySize; I++) {
354 Index = CGF.
Builder.CreateAdd(Index, One);
355 GEPIndices.back() = llvm::ConstantInt::get(IntTy, I);
361 CXXMethodDecl *CreateMethod = lookupResourceInitMethodAndSetupArgs(
362 CGF.
CGM, ResourceDecl, Range, Index, ResourceName, Binding, Args);
370 callResourceInitMethod(CGF, CreateMethod, Args, ReturnAddress);
380 assert(T->isHLSLSpecificType() &&
"Not an HLSL specific type!");
383 if (llvm::Type *TargetTy =
384 CGM.getTargetCodeGenInfo().getHLSLType(
CGM, T, OffsetInfo))
387 llvm_unreachable(
"Generic handling of HLSL types is not supported.");
390llvm::Triple::ArchType CGHLSLRuntime::getArch() {
396void CGHLSLRuntime::emitBufferGlobalsAndMetadata(
402 llvm::Type *BufType = BufGV->getValueType();
407 size_t OffsetIdx = 0;
417 VarDecl *VD = dyn_cast<VarDecl>(D);
433 DeclsWithOffset.emplace_back(VD, OffsetInfo[OffsetIdx++]);
436 if (!OffsetInfo.
empty())
437 llvm::stable_sort(DeclsWithOffset, [](
const auto &LHS,
const auto &RHS) {
442 SmallVector<llvm::Metadata *> BufGlobals;
443 BufGlobals.reserve(DeclsWithOffset.size() + 1);
444 BufGlobals.push_back(ValueAsMetadata::get(BufGV));
446 auto ElemIt = LayoutStruct->element_begin();
447 for (
auto &[VD, _] : DeclsWithOffset) {
448 if (
CGM.getTargetCodeGenInfo().isHLSLPadding(*ElemIt))
451 assert(ElemIt != LayoutStruct->element_end() &&
452 "number of elements in layout struct does not match");
453 llvm::Type *LayoutType = *ElemIt++;
455 GlobalVariable *ElemGV =
457 BufGlobals.push_back(ValueAsMetadata::get(ElemGV));
459 assert(ElemIt == LayoutStruct->element_end() &&
460 "number of elements in layout struct does not match");
464 .getOrInsertNamedMetadata(
"hlsl.cbs")
465 ->addOperand(MDNode::get(Ctx, BufGlobals));
469static const clang::HLSLAttributedResourceType *
474 HLSLAttributedResourceType::Attributes(ResourceClass::CBuffer));
489 VarDecl *VD = dyn_cast<VarDecl>(D);
500 if (
auto *POA = dyn_cast<HLSLPackOffsetAttr>(
Attr)) {
501 Offset = POA->getOffsetInBytes();
504 auto *RBA = dyn_cast<HLSLResourceBindingAttr>(
Attr);
506 RBA->getRegisterType() == HLSLResourceBindingAttr::RegisterType::C) {
507 Offset = RBA->getSlotNumber() * CBufferRowSizeInBytes;
511 Result.Offsets.push_back(Offset);
519 assert(BufDecl->
isCBuffer() &&
"tbuffer codegen is not supported yet");
522 const clang::HLSLAttributedResourceType *ResHandleTy =
526 if (ResHandleTy->getContainedType()->getAsCXXRecordDecl()->isEmpty())
532 llvm::GlobalVariable *BufGV =
new GlobalVariable(
534 GlobalValue::LinkageTypes::ExternalLinkage, PoisonValue::get(LayoutTy),
535 llvm::formatv(
"{0}{1}", BufDecl->
getName(),
537 GlobalValue::NotThreadLocal);
538 CGM.getModule().insertGlobalVariable(BufGV);
541 emitBufferGlobalsAndMetadata(BufDecl, BufGV, OffsetInfo);
544 initializeBufferFromBinding(BufDecl, BufGV);
549 llvm::Module &M =
CGM.getModule();
550 Triple T(M.getTargetTriple());
553 if (T.getEnvironment() != Triple::EnvironmentType::RootSignature)
556 addRootSignatureMD(SignatureDecl->
getVersion(),
562 const auto Entry = LayoutTypes.find(StructType);
563 if (Entry != LayoutTypes.end())
564 return Entry->getSecond();
569 llvm::StructType *LayoutTy) {
571 "layout type for this struct already exist");
572 LayoutTypes[StructType] = LayoutTy;
576 auto &TargetOpts =
CGM.getTarget().getTargetOpts();
577 auto &CodeGenOpts =
CGM.getCodeGenOpts();
578 auto &LangOpts =
CGM.getLangOpts();
579 llvm::Module &M =
CGM.getModule();
580 Triple T(M.getTargetTriple());
581 if (T.getArch() == Triple::ArchType::dxil)
582 addDxilValVersion(TargetOpts.DxilValidatorVersion, M);
583 if (CodeGenOpts.ResMayAlias)
584 M.setModuleFlag(llvm::Module::ModFlagBehavior::Error,
"dx.resmayalias", 1);
585 if (CodeGenOpts.AllResourcesBound)
586 M.setModuleFlag(llvm::Module::ModFlagBehavior::Error,
587 "dx.allresourcesbound", 1);
588 if (CodeGenOpts.OptimizationLevel == 0)
589 M.addModuleFlag(llvm::Module::ModFlagBehavior::Override,
590 "dx.disable_optimizations", 1);
595 if (LangOpts.NativeHalfType)
596 M.setModuleFlag(llvm::Module::ModFlagBehavior::Error,
"dx.nativelowprec",
604 const auto *ShaderAttr = FD->
getAttr<HLSLShaderAttr>();
605 assert(ShaderAttr &&
"All entry functions must have a HLSLShaderAttr");
606 const StringRef ShaderAttrKindStr =
"hlsl.shader";
607 Fn->addFnAttr(ShaderAttrKindStr,
608 llvm::Triple::getEnvironmentTypeName(ShaderAttr->getType()));
609 if (HLSLNumThreadsAttr *NumThreadsAttr = FD->
getAttr<HLSLNumThreadsAttr>()) {
610 const StringRef NumThreadsKindStr =
"hlsl.numthreads";
611 std::string NumThreadsStr =
612 formatv(
"{0},{1},{2}", NumThreadsAttr->getX(), NumThreadsAttr->getY(),
613 NumThreadsAttr->getZ());
614 Fn->addFnAttr(NumThreadsKindStr, NumThreadsStr);
616 if (HLSLWaveSizeAttr *WaveSizeAttr = FD->
getAttr<HLSLWaveSizeAttr>()) {
617 const StringRef WaveSizeKindStr =
"hlsl.wavesize";
618 std::string WaveSizeStr =
619 formatv(
"{0},{1},{2}", WaveSizeAttr->getMin(), WaveSizeAttr->getMax(),
620 WaveSizeAttr->getPreferred());
621 Fn->addFnAttr(WaveSizeKindStr, WaveSizeStr);
628 Fn->addFnAttr(llvm::Attribute::NoInline);
630 if (
CGM.getLangOpts().HLSLSpvEnableMaximalReconvergence) {
631 Fn->addFnAttr(
"enable-maximal-reconvergence",
"true");
636 if (
const auto *VT = dyn_cast<FixedVectorType>(Ty)) {
638 for (
unsigned I = 0; I < VT->getNumElements(); ++I) {
639 Value *Elt = B.CreateCall(F, {B.getInt32(I)});
644 return B.CreateCall(F, {B.getInt32(0)});
649 LLVMContext &Ctx = GV->getContext();
650 IRBuilder<> B(GV->getContext());
651 MDNode *Operands = MDNode::get(
653 {ConstantAsMetadata::get(B.getInt32( 11)),
654 ConstantAsMetadata::get(B.getInt32(BuiltIn))});
655 MDNode *Decoration = MDNode::get(Ctx, {Operands});
656 GV->addMetadata(
"spirv.Decorations", *Decoration);
660 LLVMContext &Ctx = GV->getContext();
661 IRBuilder<> B(GV->getContext());
663 MDNode::get(Ctx, {ConstantAsMetadata::get(B.getInt32( 30)),
664 ConstantAsMetadata::get(B.getInt32(Location))});
665 MDNode *Decoration = MDNode::get(Ctx, {Operands});
666 GV->addMetadata(
"spirv.Decorations", *Decoration);
670 llvm::Type *Ty,
const Twine &Name,
671 unsigned BuiltInID) {
672 auto *GV =
new llvm::GlobalVariable(
673 M, Ty,
true, llvm::GlobalValue::ExternalLinkage,
674 nullptr, Name,
nullptr,
675 llvm::GlobalVariable::GeneralDynamicTLSModel,
678 GV->setVisibility(llvm::GlobalValue::HiddenVisibility);
679 return B.CreateLoad(Ty, GV);
683 llvm::Type *Ty,
unsigned Location,
685 auto *GV =
new llvm::GlobalVariable(
686 M, Ty,
true, llvm::GlobalValue::ExternalLinkage,
687 nullptr, Name,
nullptr,
688 llvm::GlobalVariable::GeneralDynamicTLSModel,
690 GV->setVisibility(llvm::GlobalValue::HiddenVisibility);
692 return B.CreateLoad(Ty, GV);
695llvm::Value *CGHLSLRuntime::emitSPIRVUserSemanticLoad(
696 llvm::IRBuilder<> &B, llvm::Type *
Type,
const clang::DeclaratorDecl *
Decl,
697 HLSLAppliedSemanticAttr *Semantic, std::optional<unsigned> Index) {
698 Twine BaseName = Twine(Semantic->getAttrName()->getName());
699 Twine VariableName = BaseName.concat(Twine(Index.value_or(0)));
701 unsigned Location = SPIRVLastAssignedInputSemanticLocation;
702 if (
auto *L =
Decl->getAttr<HLSLVkLocationAttr>())
703 Location = L->getLocation();
707 llvm::ArrayType *AT = dyn_cast<llvm::ArrayType>(
Type);
708 unsigned ElementCount = AT ? AT->getNumElements() : 1;
709 SPIRVLastAssignedInputSemanticLocation += ElementCount;
716 llvm::Value *Source,
unsigned Location,
718 auto *GV =
new llvm::GlobalVariable(
719 M, Source->getType(),
false,
720 llvm::GlobalValue::ExternalLinkage,
721 nullptr, Name,
nullptr,
722 llvm::GlobalVariable::GeneralDynamicTLSModel,
724 GV->setVisibility(llvm::GlobalValue::HiddenVisibility);
726 B.CreateStore(Source, GV);
729void CGHLSLRuntime::emitSPIRVUserSemanticStore(
730 llvm::IRBuilder<> &B, llvm::Value *Source,
731 const clang::DeclaratorDecl *
Decl, HLSLAppliedSemanticAttr *Semantic,
732 std::optional<unsigned> Index) {
733 Twine BaseName = Twine(Semantic->getAttrName()->getName());
734 Twine VariableName = BaseName.concat(Twine(Index.value_or(0)));
736 unsigned Location = SPIRVLastAssignedOutputSemanticLocation;
737 if (
auto *L =
Decl->getAttr<HLSLVkLocationAttr>())
738 Location = L->getLocation();
742 llvm::ArrayType *AT = dyn_cast<llvm::ArrayType>(Source->getType());
743 unsigned ElementCount = AT ? AT->getNumElements() : 1;
744 SPIRVLastAssignedOutputSemanticLocation += ElementCount;
750CGHLSLRuntime::emitDXILUserSemanticLoad(llvm::IRBuilder<> &B, llvm::Type *
Type,
751 HLSLAppliedSemanticAttr *Semantic,
752 std::optional<unsigned> Index) {
753 Twine BaseName = Twine(Semantic->getAttrName()->getName());
754 Twine VariableName = BaseName.concat(Twine(Index.value_or(0)));
759 SmallVector<Value *> Args{B.getInt32(4), B.getInt32(0), B.getInt32(0),
761 llvm::PoisonValue::get(B.getInt32Ty())};
763 llvm::Intrinsic::ID IntrinsicID = llvm::Intrinsic::dx_load_input;
765 SmallVector<OperandBundleDef, 1> OB;
767 llvm::Value *bundleArgs[] = {Token};
768 OB.emplace_back(
"convergencectrl", bundleArgs);
771 llvm::Function *IntrFn = llvm::Intrinsic::getOrInsertDeclaration(
772 B.GetInsertBlock()->getModule(), IntrinsicID, {Type});
773 llvm::Value *
Value = B.CreateCall(IntrFn, Args, OB, VariableName);
777void CGHLSLRuntime::emitDXILUserSemanticStore(llvm::IRBuilder<> &B,
779 HLSLAppliedSemanticAttr *Semantic,
780 std::optional<unsigned> Index) {
783 SmallVector<Value *> Args{B.getInt32(4),
787 llvm::PoisonValue::get(B.getInt32Ty()),
790 llvm::Intrinsic::ID IntrinsicID = llvm::Intrinsic::dx_store_output;
792 SmallVector<OperandBundleDef, 1> OB;
794 llvm::Value *bundleArgs[] = {Token};
795 OB.emplace_back(
"convergencectrl", bundleArgs);
798 llvm::Function *IntrFn = llvm::Intrinsic::getOrInsertDeclaration(
799 B.GetInsertBlock()->getModule(), IntrinsicID, {Source->getType()});
800 B.CreateCall(IntrFn, Args, OB);
803llvm::Value *CGHLSLRuntime::emitUserSemanticLoad(
804 IRBuilder<> &B, llvm::Type *
Type,
const clang::DeclaratorDecl *
Decl,
805 HLSLAppliedSemanticAttr *Semantic, std::optional<unsigned> Index) {
806 if (
CGM.getTarget().getTriple().isSPIRV())
807 return emitSPIRVUserSemanticLoad(B,
Type,
Decl, Semantic, Index);
809 if (
CGM.getTarget().getTriple().isDXIL())
810 return emitDXILUserSemanticLoad(B,
Type, Semantic, Index);
812 llvm_unreachable(
"Unsupported target for user-semantic load.");
815void CGHLSLRuntime::emitUserSemanticStore(IRBuilder<> &B, llvm::Value *Source,
816 const clang::DeclaratorDecl *
Decl,
817 HLSLAppliedSemanticAttr *Semantic,
818 std::optional<unsigned> Index) {
819 if (
CGM.getTarget().getTriple().isSPIRV())
820 return emitSPIRVUserSemanticStore(B, Source,
Decl, Semantic, Index);
822 if (
CGM.getTarget().getTriple().isDXIL())
823 return emitDXILUserSemanticStore(B, Source, Semantic, Index);
825 llvm_unreachable(
"Unsupported target for user-semantic load.");
831 std::optional<unsigned> Index) {
833 std::string SemanticName = Semantic->getAttrName()->getName().upper();
834 if (SemanticName ==
"SV_GROUPINDEX") {
835 llvm::Function *GroupIndex =
836 CGM.getIntrinsic(getFlattenedThreadIdInGroupIntrinsic());
837 return B.CreateCall(FunctionCallee(GroupIndex));
840 if (SemanticName ==
"SV_DISPATCHTHREADID") {
841 llvm::Intrinsic::ID IntrinID = getThreadIdIntrinsic();
842 llvm::Function *ThreadIDIntrinsic =
843 llvm::Intrinsic::isOverloaded(IntrinID)
844 ?
CGM.getIntrinsic(IntrinID, {
CGM.Int32Ty})
845 :
CGM.getIntrinsic(IntrinID);
849 if (SemanticName ==
"SV_GROUPTHREADID") {
850 llvm::Intrinsic::ID IntrinID = getGroupThreadIdIntrinsic();
851 llvm::Function *GroupThreadIDIntrinsic =
852 llvm::Intrinsic::isOverloaded(IntrinID)
853 ?
CGM.getIntrinsic(IntrinID, {
CGM.Int32Ty})
854 :
CGM.getIntrinsic(IntrinID);
858 if (SemanticName ==
"SV_GROUPID") {
859 llvm::Intrinsic::ID IntrinID = getGroupIdIntrinsic();
860 llvm::Function *GroupIDIntrinsic =
861 llvm::Intrinsic::isOverloaded(IntrinID)
862 ?
CGM.getIntrinsic(IntrinID, {
CGM.Int32Ty})
863 :
CGM.getIntrinsic(IntrinID);
867 const auto *ShaderAttr = FD->
getAttr<HLSLShaderAttr>();
868 assert(ShaderAttr &&
"Entry point has no shader attribute");
869 llvm::Triple::EnvironmentType ST = ShaderAttr->getType();
871 if (SemanticName ==
"SV_POSITION") {
872 if (ST == Triple::EnvironmentType::Pixel) {
873 if (
CGM.getTarget().getTriple().isSPIRV())
875 Semantic->getAttrName()->getName(),
877 if (
CGM.getTarget().getTriple().isDXIL())
878 return emitDXILUserSemanticLoad(B,
Type, Semantic, Index);
881 if (ST == Triple::EnvironmentType::Vertex) {
882 return emitUserSemanticLoad(B,
Type,
Decl, Semantic, Index);
886 if (SemanticName ==
"SV_VERTEXID") {
887 if (ST == Triple::EnvironmentType::Vertex) {
888 if (
CGM.getTarget().getTriple().isSPIRV())
890 Semantic->getAttrName()->getName(),
893 return emitDXILUserSemanticLoad(B,
Type, Semantic, Index);
898 "Load hasn't been implemented yet for this system semantic. FIXME");
902 llvm::Value *Source,
const Twine &Name,
903 unsigned BuiltInID) {
904 auto *GV =
new llvm::GlobalVariable(
905 M, Source->getType(),
false,
906 llvm::GlobalValue::ExternalLinkage,
907 nullptr, Name,
nullptr,
908 llvm::GlobalVariable::GeneralDynamicTLSModel,
911 GV->setVisibility(llvm::GlobalValue::HiddenVisibility);
912 B.CreateStore(Source, GV);
917 HLSLAppliedSemanticAttr *Semantic,
918 std::optional<unsigned> Index) {
920 std::string SemanticName = Semantic->getAttrName()->getName().upper();
921 if (SemanticName ==
"SV_POSITION") {
922 if (
CGM.getTarget().getTriple().isDXIL()) {
923 emitDXILUserSemanticStore(B, Source, Semantic, Index);
927 if (
CGM.getTarget().getTriple().isSPIRV()) {
929 Semantic->getAttrName()->getName(),
935 if (SemanticName ==
"SV_TARGET") {
936 emitUserSemanticStore(B, Source,
Decl, Semantic, Index);
941 "Store hasn't been implemented yet for this system semantic. FIXME");
948 std::optional<unsigned> Index = Semantic->getSemanticIndex();
949 if (Semantic->getAttrName()->getName().starts_with_insensitive(
"SV_"))
951 return emitUserSemanticLoad(B,
Type,
Decl, Semantic, Index);
955 IRBuilder<> &B,
const FunctionDecl *FD, llvm::Value *Source,
957 std::optional<unsigned> Index = Semantic->getSemanticIndex();
958 if (Semantic->getAttrName()->getName().starts_with_insensitive(
"SV_"))
961 emitUserSemanticStore(B, Source,
Decl, Semantic, Index);
964std::pair<llvm::Value *, specific_attr_iterator<HLSLAppliedSemanticAttr>>
977 for (
unsigned I = 0; I < ST->getNumElements(); ++I) {
979 B, FD, ST->getElementType(I), *
FieldDecl, AttrBegin, AttrEnd);
980 AttrBegin = NextAttr;
986 return std::make_pair(
Aggregate, AttrBegin);
991 IRBuilder<> &B,
const FunctionDecl *FD, llvm::Value *Source,
1002 RD =
Decl->getType()->getAsRecordDecl();
1008 for (
unsigned I = 0; I < ST->getNumElements(); ++I, ++
FieldDecl) {
1009 llvm::Value *Extract = B.CreateExtractValue(Source, I);
1017std::pair<llvm::Value *, specific_attr_iterator<HLSLAppliedSemanticAttr>>
1023 assert(AttrBegin != AttrEnd);
1024 if (
Type->isStructTy())
1027 HLSLAppliedSemanticAttr *
Attr = *AttrBegin;
1035 IRBuilder<> &B,
const FunctionDecl *FD, llvm::Value *Source,
1039 assert(AttrBegin != AttrEnd);
1040 if (Source->getType()->isStructTy())
1043 HLSLAppliedSemanticAttr *
Attr = *AttrBegin;
1050 llvm::Function *Fn) {
1051 llvm::Module &M =
CGM.getModule();
1052 llvm::LLVMContext &Ctx = M.getContext();
1053 auto *EntryTy = llvm::FunctionType::get(llvm::Type::getVoidTy(Ctx),
false);
1055 Function::Create(EntryTy, Function::ExternalLinkage, FD->
getName(), &M);
1059 AttributeList NewAttrs = AttributeList::get(Ctx, AttributeList::FunctionIndex,
1060 Fn->getAttributes().getFnAttrs());
1061 EntryFn->setAttributes(NewAttrs);
1065 Fn->setLinkage(GlobalValue::InternalLinkage);
1067 BasicBlock *BB = BasicBlock::Create(Ctx,
"entry", EntryFn);
1072 if (
CGM.shouldEmitConvergenceTokens()) {
1073 assert(EntryFn->isConvergent());
1075 B.CreateIntrinsic(llvm::Intrinsic::experimental_convergence_entry, {});
1076 llvm::Value *bundleArgs[] = {I};
1077 OB.emplace_back(
"convergencectrl", bundleArgs);
1082 unsigned SRetOffset = 0;
1083 for (
const auto &Param : Fn->args()) {
1084 if (Param.hasStructRetAttr()) {
1086 llvm::Type *VarType = Param.getParamStructRetType();
1088 CGM.getLangOpts().EmitLogicalPointer
1091 OutputSemantic.push_back(std::make_pair(Var, VarType));
1092 Args.push_back(Var);
1097 llvm::Value *SemanticValue =
nullptr;
1099 if ([[maybe_unused]] HLSLParamModifierAttr *MA =
1100 PD->
getAttr<HLSLParamModifierAttr>()) {
1101 llvm_unreachable(
"Not handled yet");
1103 llvm::Type *ParamType =
1104 Param.hasByValAttr() ? Param.getParamByValType() : Param.getType();
1109 SemanticValue =
Result.first;
1112 if (Param.hasByValAttr()) {
1114 CGM.getLangOpts().EmitLogicalPointer
1116 B.CreateStructuredAlloca(Param.getParamByValType()))
1118 B.CreateStore(SemanticValue, Var);
1119 SemanticValue = Var;
1123 assert(SemanticValue);
1124 Args.push_back(SemanticValue);
1127 CallInst *CI = B.CreateCall(FunctionCallee(Fn), Args, OB);
1128 CI->setCallingConv(Fn->getCallingConv());
1130 if (Fn->getReturnType() !=
CGM.VoidTy)
1132 OutputSemantic.push_back(std::make_pair(CI,
nullptr));
1134 for (
auto &SourcePair : OutputSemantic) {
1135 llvm::Value *Source = SourcePair.first;
1136 llvm::Type *ElementType = SourcePair.second;
1137 AllocaInst *AI = dyn_cast<AllocaInst>(Source);
1138 llvm::Value *SourceValue = AI ? B.CreateLoad(ElementType, Source) : Source;
1149 if (
const auto *RSAttr = dyn_cast<RootSignatureAttr>(
Attr)) {
1150 auto *RSDecl = RSAttr->getSignatureDecl();
1151 addRootSignatureMD(RSDecl->getVersion(), RSDecl->getRootElements(),
1160 M.getNamedGlobal(CtorOrDtor ?
"llvm.global_ctors" :
"llvm.global_dtors");
1163 const auto *CA = dyn_cast<ConstantArray>(GV->getInitializer());
1170 for (
const auto &Ctor : CA->operands()) {
1176 "HLSL doesn't support setting priority for global ctors.");
1178 "HLSL doesn't support COMDat for global ctors.");
1184 llvm::Module &M =
CGM.getModule();
1193 for (
auto &F : M.functions()) {
1194 if (!F.hasFnAttribute(
"hlsl.shader"))
1197 Instruction *IP = &*F.getEntryBlock().begin();
1200 llvm::Value *bundleArgs[] = {
Token};
1201 OB.emplace_back(
"convergencectrl", bundleArgs);
1202 IP =
Token->getNextNode();
1205 for (
auto *Fn : CtorFns) {
1206 auto CI = B.CreateCall(FunctionCallee(Fn), {}, OB);
1207 CI->setCallingConv(Fn->getCallingConv());
1211 B.SetInsertPoint(F.back().getTerminator());
1212 for (
auto *Fn : DtorFns) {
1213 auto CI = B.CreateCall(FunctionCallee(Fn), {}, OB);
1214 CI->setCallingConv(Fn->getCallingConv());
1220 Triple T(M.getTargetTriple());
1221 if (T.getEnvironment() != Triple::EnvironmentType::Library) {
1222 if (
auto *GV = M.getNamedGlobal(
"llvm.global_ctors"))
1223 GV->eraseFromParent();
1224 if (
auto *GV = M.getNamedGlobal(
"llvm.global_dtors"))
1225 GV->eraseFromParent();
1230 Intrinsic::ID IntrID,
1234 llvm::Function *InitResFunc = llvm::Function::Create(
1235 llvm::FunctionType::get(CGM.
VoidTy,
false),
1236 llvm::GlobalValue::InternalLinkage,
1237 (
"_init_buffer_" + GV->getName()).str(), CGM.
getModule());
1238 InitResFunc->addFnAttr(llvm::Attribute::AlwaysInline);
1240 llvm::BasicBlock *EntryBB =
1241 llvm::BasicBlock::Create(Ctx,
"entry", InitResFunc);
1243 const DataLayout &DL = CGM.
getModule().getDataLayout();
1244 Builder.SetInsertPoint(EntryBB);
1247 llvm::Type *HandleTy = GV->getValueType();
1248 assert(HandleTy->isTargetExtTy() &&
"unexpected type of the buffer global");
1250 llvm::Value *CreateHandle = Builder.CreateIntrinsic(
1251 HandleTy, IntrID, Args,
nullptr,
1252 Twine(GV->getName()).concat(
"_h"));
1254 Builder.CreateAlignedStore(CreateHandle, GV, GV->getPointerAlignment(DL));
1255 Builder.CreateRetVoid();
1260void CGHLSLRuntime::initializeBufferFromBinding(
const HLSLBufferDecl *BufDecl,
1261 llvm::GlobalVariable *GV) {
1262 ResourceBindingAttrs Binding(BufDecl);
1264 "cbuffer/tbuffer should always have resource binding attribute");
1266 auto *Index = llvm::ConstantInt::get(
CGM.IntTy, 0);
1267 auto *RangeSize = llvm::ConstantInt::get(
CGM.IntTy, 1);
1268 auto *Space = llvm::ConstantInt::get(
CGM.IntTy, Binding.
getSpace());
1273 llvm::Intrinsic::ID IntrinsicID =
1274 CGM.getHLSLRuntime().getCreateHandleFromBindingIntrinsic();
1275 auto *RegSlot = llvm::ConstantInt::get(
CGM.IntTy, Binding.
getSlot());
1276 SmallVector<Value *> Args{Space, RegSlot, RangeSize, Index, Name};
1280 llvm::Intrinsic::ID IntrinsicID =
1281 CGM.getHLSLRuntime().getCreateHandleFromImplicitBindingIntrinsic();
1284 SmallVector<Value *> Args{OrderID, Space, RangeSize, Index, Name};
1290 llvm::GlobalVariable *GV) {
1291 if (
auto Attr = VD->
getAttr<HLSLVkExtBuiltinInputAttr>())
1293 if (
auto Attr = VD->
getAttr<HLSLVkExtBuiltinOutputAttr>())
1298 if (!
CGM.shouldEmitConvergenceTokens())
1302 for (
auto I = BB.begin(); I != E; ++I) {
1303 auto *II = dyn_cast<llvm::IntrinsicInst>(&*I);
1304 if (II && llvm::isConvergenceControlIntrinsic(II->getIntrinsicID())) {
1308 llvm_unreachable(
"Convergence token should have been emitted.");
1345 for (
auto *OVE : Visitor.
OVEs) {
1348 if (OpaqueValueMappingData::shouldBindAsLValue(OVE)) {
1350 OpaqueValueMappingData::bind(CGF, OVE, LV);
1353 OpaqueValueMappingData::bind(CGF, OVE, RV);
1362 "expected resource array subscript expression");
1367 const VarDecl *ArrayDecl = dyn_cast_or_null<VarDecl>(
1371 return std::nullopt;
1377 "expected array of resource classes");
1383 Value *Index =
nullptr;
1385 while (ASE !=
nullptr) {
1387 if (
const auto *ArrayTy =
1389 Value *Multiplier = llvm::ConstantInt::get(
1391 SubIndex = CGF.
Builder.CreateMul(SubIndex, Multiplier);
1393 Index = Index ? CGF.
Builder.CreateAdd(Index, SubIndex) : SubIndex;
1401 "resource array must have a binding attribute");
1422 llvm::Value *Range = llvm::ConstantInt::getSigned(
1423 CGM.IntTy, getTotalArraySize(AST, ResArrayTy));
1427 if (ResultTy == ResourceTy) {
1429 CXXMethodDecl *CreateMethod = lookupResourceInitMethodAndSetupArgs(
1431 ArrayDecl->
getName(), Binding, Args);
1433 if (!CreateMethod) {
1438 "create method lookup should always succeed for built-in resource "
1440 return std::nullopt;
1443 callResourceInitMethod(CGF, CreateMethod, Args, ValueSlot.getAddress());
1450 std::optional<llvm::Value *> EndIndex = initializeResourceArrayFromGlobal(
1452 ArrayDecl->
getName(), Binding, {llvm::ConstantInt::get(CGM.IntTy, 0)},
1455 return std::nullopt;
1461bool CGHLSLRuntime::initializeGlobalResourceArray(
CodeGenFunction &CGF,
1468 "expected global non-static resource array");
1474 "resource array must have a binding attribute");
1479 const auto *ResArrayTy =
1483 int Size = getTotalArraySize(AST, ResArrayTy);
1484 llvm::Value *
Zero = llvm::ConstantInt::get(
CGM.
IntTy, 0);
1485 llvm::Value *Range = llvm::ConstantInt::get(
CGM.
IntTy, Size);
1488 std::optional<llvm::Value *> EndIndex = initializeResourceArrayFromGlobal(
1490 ArrayDecl->
getName(), Binding, {Zero}, Loc);
1491 return EndIndex.has_value();
1500 "expected resource array");
1505 dyn_cast_or_null<VarDecl>(getArrayDecl(CGF.
CGM.
getContext(), E));
1510 return initializeGlobalResourceArray(CGF, ArrayDecl, E->
getExprLoc(),
1521 "expected resource array declaration");
1525 return std::nullopt;
1529 if (initializeGlobalResourceArray(CGF, ArrayDecl, Loc, TmpArraySlot))
1532 return std::nullopt;
1541 "expected cbuffer matrix");
1547 if (LayoutTy == MemTy)
1563 llvm::function_ref<llvm::Value *(
bool Promote)> EmitIdxAfterBase) {
1567 llvm::Type *LayoutTy =
1569 uint64_t LayoutSizeInBits =
1570 CGM.getDataLayout().getTypeSizeInBits(LayoutTy).getFixedValue();
1573 if (RowAlignedSize > ElementSize) {
1574 llvm::Type *Padding =
CGM.getTargetCodeGenInfo().getHLSLPadding(
1575 CGM, RowAlignedSize - ElementSize);
1576 assert(Padding &&
"No padding type for target?");
1577 LayoutTy = llvm::StructType::get(CGF.
getLLVMContext(), {LayoutTy, Padding},
1584 if (LayoutTy == OrigTy)
1585 return std::nullopt;
1594 llvm::Value *Idx = EmitIdxAfterBase(
true);
1595 Indices.push_back(Idx);
1596 Indices.push_back(llvm::ConstantInt::get(CGF.
Int32Ty, 0));
1602 assert(CE->
getCastKind() == CastKind::CK_ArrayToPointerDecay);
1606 LayoutTy = llvm::ArrayType::get(
1610 LayoutTy,
Addr.emitRawPointer(CGF), Indices,
"cbufferidx"));
1619 Indices,
"cbufferidx");
1624std::optional<LValue>
1629 "expected resource member expression");
1632 findAssociatedResourceDeclForStruct(CGF.
CGM.
getContext(), ME);
1634 return std::nullopt;
1641 GlobalVariable *ResGV =
1643 const DataLayout &DL =
CGM.getDataLayout();
1644 llvm::Type *Ty = ResGV->getValueType();
1656class HLSLBufferCopyEmitter {
1660 llvm::Type *LayoutTy =
nullptr;
1667 llvm::Value *emitAccessChain(llvm::Type *BaseTy, llvm::Value *
Base,
1669 bool EmitLogical = CGF.
getLangOpts().EmitLogicalPointer;
1674 GEPIndices.reserve(Indices.size() + 1);
1675 GEPIndices.push_back(llvm::ConstantInt::get(CGF.
IntTy, 0));
1676 GEPIndices.append(Indices.begin(), Indices.end());
1680 bool isBufferLayoutArray(llvm::StructType *ST) {
1686 if (!ST || ST->getNumElements() != 2)
1689 auto *PaddedEltsTy = dyn_cast<llvm::ArrayType>(ST->getElementType(0));
1693 auto *PaddedTy = dyn_cast<llvm::StructType>(PaddedEltsTy->getElementType());
1694 if (!PaddedTy || PaddedTy->getNumElements() != 2)
1698 PaddedTy->getElementType(1)))
1701 llvm::Type *ElementTy = ST->getElementType(1);
1702 if (PaddedTy->getElementType(0) != ElementTy)
1707 void emitBufferLayoutCopy(
Value *Src, llvm::StructType *SrcTy,
Value *Dst,
1708 llvm::ArrayType *DstTy) {
1711 assert(SrcPaddedArrayTy->getNumElements() + 1 == DstTy->getNumElements());
1713 ->getElementType(0) == SrcTy->getElementType(1));
1715 auto *SrcDataTy = SrcTy->getElementType(1);
1716 auto Zero = llvm::ConstantInt::get(CGF.
IntTy, 0);
1718 for (
unsigned I = 0; I < SrcPaddedArrayTy->getNumElements(); ++I) {
1719 auto Index = llvm::ConstantInt::get(CGF.
IntTy, I);
1720 auto *SrcElt = emitAccessChain(SrcTy, Src, {
Zero, Index,
Zero});
1721 auto *DstElt = emitAccessChain(DstTy, Dst, {Index});
1722 emitElementCopy(SrcElt, SrcDataTy, DstElt, DstTy->getElementType());
1726 emitAccessChain(SrcTy, Src, {llvm::ConstantInt::get(CGF.
IntTy, 1)});
1727 auto *DstElt = emitAccessChain(
1729 {llvm::ConstantInt::get(CGF.
IntTy, DstTy->getNumElements() - 1)});
1730 emitElementCopy(SrcElt, SrcDataTy, DstElt, DstTy->getElementType());
1733 void emitCopy(
Value *Src, llvm::StructType *SrcTy,
Value *Dst,
1734 llvm::Type *DstTy) {
1735 if (isBufferLayoutArray(SrcTy))
1736 return emitBufferLayoutCopy(Src, SrcTy, Dst,
1739 unsigned SrcIndex = 0;
1740 unsigned DstIndex = 0;
1743 while (SrcIndex < SrcTy->getNumElements() &&
1744 DstIndex < DstST->getNumElements()) {
1746 SrcTy->getElementType(SrcIndex))) {
1752 DstST->getElementType(DstIndex))) {
1757 auto *SrcElt = emitAccessChain(
1758 SrcTy, Src, {llvm::ConstantInt::get(CGF.
IntTy, SrcIndex)});
1759 auto *DstElt = emitAccessChain(
1760 DstTy, Dst, {llvm::ConstantInt::get(CGF.
IntTy, DstIndex)});
1761 emitElementCopy(SrcElt, SrcTy->getElementType(SrcIndex), DstElt,
1762 DstST->getElementType(DstIndex));
1768 void emitCopy(
Value *Src, llvm::ArrayType *SrcTy,
Value *Dst,
1769 llvm::Type *DstTy) {
1770 for (
unsigned I = 0, E = SrcTy->getNumElements(); I < E; ++I) {
1772 emitAccessChain(SrcTy, Src, {llvm::ConstantInt::get(CGF.
IntTy, I)});
1774 emitAccessChain(DstTy, Dst, {llvm::ConstantInt::get(CGF.
IntTy, I)});
1775 emitElementCopy(SrcElt, SrcTy->getElementType(), DstElt,
1780 void emitElementCopy(
Value *Src, llvm::Type *SrcTy,
Value *Dst,
1781 llvm::Type *DstTy) {
1782 if (
auto *AT = dyn_cast<llvm::ArrayType>(SrcTy))
1783 return emitCopy(Src, AT, Dst, DstTy);
1784 if (
auto *ST = dyn_cast<llvm::StructType>(SrcTy))
1785 return emitCopy(Src, ST, Dst, DstTy);
1788 CharUnits SrcAlign =
1790 CharUnits DstAlign =
1792 Address SrcAddr(Src, SrcTy, SrcAlign);
1793 Address DstAddr(Dst, DstTy, DstAlign);
1799 HLSLBufferCopyEmitter(CodeGenFunction &CGF, Address DstPtr, Address SrcPtr)
1800 : CGF(CGF), DstPtr(DstPtr), SrcPtr(SrcPtr) {}
1802 bool emitCopy(QualType CType) {
1803 LayoutTy = HLSLBufferLayoutBuilder(CGF.
CGM).layOutType(CType);
1819 return HLSLBufferCopyEmitter(CGF, DstPtr, SrcPtr).emitCopy(CType);
1827 assert(Field &&
"Unexpected access into HLSL buffer");
1832 QualType RecType =
CGM.getContext().getCanonicalTagType(Rec);
1843 CGM.getTypes().getCGRecordLayout(Rec).getLLVMFieldNo(Field);
1844 assert(FieldIdx < LayoutTy->getNumElements() &&
1845 "Layout struct is smaller than member struct");
1846 unsigned Skipped = 0;
1847 for (
unsigned I = 0; I <= FieldIdx;) {
1848 llvm::Type *ElementTy = LayoutTy->getElementType(I + Skipped);
1854 FieldIdx += Skipped;
1855 assert(FieldIdx < LayoutTy->getNumElements() &&
"Access out of bounds");
1859 QualType FieldType = Field->getType();
1860 llvm::Type *FieldLLVMTy =
CGM.getTypes().ConvertTypeForMem(FieldType);
1865 ? CGF.
Builder.CreateStructuredGEP(
1866 LayoutTy,
Base.getPointer(CGF),
1867 llvm::ConstantInt::get(
CGM.IntTy, FieldIdx))
1869 FieldIdx, Field->getName());
1874 CGM.getTBAAAccessInfo(FieldType));
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
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.
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.
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.
CastExpr - Base class for type casts, including both implicit casts (ImplicitCastExpr) and explicit c...
CastKind getCastKind() const
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...
static CharUnits fromQuantity(QuantityType Quantity)
fromQuantity - Construct a CharUnits quantity from a raw integer type.
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 ...
Like RawAddress, an abstract representation of an aligned address, but the pointer contained in this ...
llvm::Value * getBasePointer() const
CharUnits getAlignment() const
llvm::Type * getElementType() const
Return the type of the values stored in this address.
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.
llvm::StoreInst * CreateStore(llvm::Value *Val, Address Addr, bool IsVolatile=false)
Address CreateGEP(CodeGenFunction &CGF, Address Addr, llvm::Value *Index, const llvm::Twine &Name="")
Address CreateStructGEP(Address Addr, unsigned Index, const llvm::Twine &Name="")
llvm::LoadInst * CreateLoad(Address Addr, const llvm::Twine &Name="")
llvm::Value * CreateAccessChain(bool Logical, llvm::Type *BaseType, llvm::Value *PtrBase, ArrayRef< llvm::Value * > IdxList, const 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.
static const uint32_t Unspecified
static bool compareOffsets(uint32_t LHS, uint32_t RHS)
Comparison function for offsets received from operator[] suitable for use in a stable_sort.
static CGHLSLOffsetInfo fromDecl(const HLSLBufferDecl &BufDecl)
Iterates over all declarations in the HLSL buffer and based on the packoffset or register(c#) annotat...
llvm::Instruction * getConvergenceToken(llvm::BasicBlock &BB)
void setHLSLEntryAttributes(const FunctionDecl *FD, llvm::Function *Fn)
specific_attr_iterator< HLSLAppliedSemanticAttr > handleSemanticStore(llvm::IRBuilder<> &B, const FunctionDecl *FD, llvm::Value *Source, const clang::DeclaratorDecl *Decl, specific_attr_iterator< HLSLAppliedSemanticAttr > AttrBegin, specific_attr_iterator< HLSLAppliedSemanticAttr > AttrEnd)
llvm::StructType * getHLSLBufferLayoutType(const RecordType *LayoutStructTy)
void emitEntryFunction(const FunctionDecl *FD, llvm::Function *Fn)
void handleGlobalVarDefinition(const VarDecl *VD, llvm::GlobalVariable *Var)
void emitSystemSemanticStore(llvm::IRBuilder<> &B, llvm::Value *Source, const clang::DeclaratorDecl *Decl, HLSLAppliedSemanticAttr *Semantic, std::optional< unsigned > Index)
std::pair< llvm::Value *, specific_attr_iterator< HLSLAppliedSemanticAttr > > handleStructSemanticLoad(llvm::IRBuilder<> &B, const FunctionDecl *FD, llvm::Type *Type, const clang::DeclaratorDecl *Decl, specific_attr_iterator< HLSLAppliedSemanticAttr > begin, specific_attr_iterator< HLSLAppliedSemanticAttr > end)
std::optional< LValue > emitResourceMemberExpr(CodeGenFunction &CGF, const MemberExpr *E)
specific_attr_iterator< HLSLAppliedSemanticAttr > handleStructSemanticStore(llvm::IRBuilder<> &B, const FunctionDecl *FD, llvm::Value *Source, const clang::DeclaratorDecl *Decl, specific_attr_iterator< HLSLAppliedSemanticAttr > AttrBegin, specific_attr_iterator< HLSLAppliedSemanticAttr > AttrEnd)
llvm::Value * handleScalarSemanticLoad(llvm::IRBuilder<> &B, const FunctionDecl *FD, llvm::Type *Type, const clang::DeclaratorDecl *Decl, HLSLAppliedSemanticAttr *Semantic)
void addHLSLBufferLayoutType(const RecordType *LayoutStructTy, llvm::StructType *LayoutTy)
void handleScalarSemanticStore(llvm::IRBuilder<> &B, const FunctionDecl *FD, llvm::Value *Source, const clang::DeclaratorDecl *Decl, HLSLAppliedSemanticAttr *Semantic)
std::pair< llvm::Value *, specific_attr_iterator< HLSLAppliedSemanticAttr > > handleSemanticLoad(llvm::IRBuilder<> &B, const FunctionDecl *FD, llvm::Type *Type, const clang::DeclaratorDecl *Decl, specific_attr_iterator< HLSLAppliedSemanticAttr > begin, specific_attr_iterator< HLSLAppliedSemanticAttr > end)
std::optional< LValue > emitBufferArraySubscriptExpr(const ArraySubscriptExpr *E, CodeGenFunction &CGF, llvm::function_ref< llvm::Value *(bool Promote)> EmitIdxAfterBase)
std::optional< LValue > emitResourceArraySubscriptExpr(const ArraySubscriptExpr *E, CodeGenFunction &CGF)
void addRootSignature(const HLSLRootSignatureDecl *D)
LValue emitBufferMemberExpr(CodeGenFunction &CGF, const MemberExpr *E)
bool emitBufferCopy(CodeGenFunction &CGF, Address DestPtr, Address SrcPtr, QualType CType)
llvm::Type * convertHLSLSpecificType(const Type *T, const CGHLSLOffsetInfo &OffsetInfo)
llvm::Value * emitSystemSemanticLoad(llvm::IRBuilder<> &B, const FunctionDecl *FD, llvm::Type *Type, const clang::DeclaratorDecl *Decl, HLSLAppliedSemanticAttr *Semantic, std::optional< unsigned > Index)
RawAddress createBufferMatrixTempAddress(const LValue &LV, SourceLocation Loc, CodeGenFunction &CGF)
std::optional< LValue > emitGlobalResourceArrayAsLValue(CodeGenFunction &CGF, const VarDecl *ArrayDecl, SourceLocation Loc)
void addBuffer(const HLSLBufferDecl *D)
void generateGlobalCtorDtorCalls()
bool emitGlobalResourceArray(CodeGenFunction &CGF, const Expr *E, AggValueSlot &DestSlot)
void emitInitListOpaqueValues(CodeGenFunction &CGF, InitListExpr *E)
CallArgList - Type for representing both the value and type of arguments in a call.
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...
const LangOptions & getLangOpts() const
@ TCK_MemberAccess
Checking the object expression in a non-static data member access.
void pushFullExprCleanup(CleanupKind kind, As... A)
pushFullExprCleanup - Push a cleanup to be run at the end of the current full-expression.
AggValueSlot CreateAggTemp(QualType T, const Twine &Name="tmp", RawAddress *Alloca=nullptr)
CreateAggTemp - Create a temporary memory object for the given aggregate type.
bool EmitLifetimeStart(llvm::Value *Addr)
Emit a lifetime.begin marker if some criteria are satisfied.
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...
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)
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...
LValue EmitCheckedLValue(const Expr *E, TypeCheckKind TCK)
Same as EmitLValue but additionally we generate checking code to guard against undefined behavior.
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.
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)
CodeGenTypes & getTypes()
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.
llvm::Constant * getPointer() const
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.
static LValue MakeAddr(Address Addr, QualType type, ASTContext &Context, LValueBaseInfo BaseInfo, TBAAAccessInfo TBAAInfo)
const Qualifiers & getQuals() const
Address getAddress() const
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,...
virtual bool isHLSLPadding(llvm::Type *Ty) const
Return true if this is an HLSL padding type.
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.
DeclContext * getParent()
getParent - Returns the containing DeclContext.
Decl - This represents one declaration (or definition), e.g.
ASTContext & getASTContext() const LLVM_READONLY
bool isImplicit() const
isImplicit - Indicates whether the declaration was implicitly generated by the implementation.
specific_attr_iterator< T > specific_attr_end() const
specific_attr_iterator< T > specific_attr_begin() const
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.
This represents one expression.
Expr * IgnoreParenImpCasts() LLVM_READONLY
Skip past any parentheses and implicit casts which might surround this expression until reaching a fi...
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.
SourceLocation getExprLoc() const LLVM_READONLY
getExprLoc - Return the preferred location for the arrow when diagnosing a problem with a generic exp...
Represents a member of a struct/union/class.
Represents a function declaration or definition.
const ParmVarDecl * getParamDecl(unsigned i) const
QualType getDeclaredReturnType() const
Get the declared return type, which may differ from the actual return type if the return type is dedu...
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
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.
MemberExpr - [C99 6.5.2.3] Structure and Union Members.
ValueDecl * getMemberDecl() const
Retrieve the member declaration to which this expression refers.
DeclarationNameInfo getMemberNameInfo() const
Retrieve the member declaration name info.
SourceLocation getExprLoc() const LLVM_READONLY
IdentifierInfo * getIdentifier() const
Get the identifier that names this declaration, if there is one.
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.
void addCVRQualifiers(unsigned mask)
Represents a struct/union/class.
unsigned getNumFields() const
Returns the number of fields (non-static data members) in this record.
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...
RecordDecl * getAsRecordDecl() const
Retrieves the RecordDecl this type refers to.
bool isConstantMatrixType() const
bool isHLSLResourceRecord() const
bool isStructureOrClassType() const
const T * getAsCanonical() const
If this type is canonically the specified type, return its canonical type cast to that specified type...
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.
void pushName(llvm::StringRef N)
void pushArrayIndex(uint64_t Index)
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.
@ Decl
The l-value was an access to a declared entity or something equivalently strong, like the address of ...
bool hasCounterHandle(const CXXRecordDecl *RD)
@ Address
A pointer to a ValueDecl.
bool Load(InterpState &S, CodePtr OpPC)
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.
@ Result
The result type of a method or function.
U cast(CodeGen::Address addr)
Diagnostic wrappers for TextAPI types for error reporting.
llvm::IntegerType * Int32Ty
llvm::IntegerType * IntTy
int
DeclarationName getName() const
getName - Returns the embedded declaration name.
unsigned getImplicitOrderID() const
bool hasCounterImplicitOrderID() const
unsigned getSpace() const
unsigned getCounterImplicitOrderID() const