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();
205 const Expr *E =
nullptr;
206 while (ASE !=
nullptr) {
210 ASE = dyn_cast<ArraySubscriptExpr>(E);
212 return getArrayDecl(AST, E);
218 assert(Ty->
isArrayType() &&
"expected array type");
224static Value *buildNameForResource(llvm::StringRef BaseName,
233 for (
auto *Method :
Record->methods()) {
234 if (Method->getStorageClass() == SC && Method->getName() == Name)
244 assert(Binding.
hasBinding() &&
"at least one binding attribute expected");
248 Value *NameStr = buildNameForResource(Name, CGM);
253 "resources with counter handle must have a binding with counter "
254 "implicit order ID");
257 auto *RegSlot = llvm::ConstantInt::get(CGM.
IntTy, Binding.
getSlot());
260 ?
"__createFromBindingWithImplicitCounter"
261 :
"__createFromBinding";
262 CreateMethod = lookupMethod(ResourceDecl, Name,
SC_Static);
269 ?
"__createFromImplicitBindingWithImplicitCounter"
270 :
"__createFromImplicitBinding";
271 CreateMethod = lookupMethod(ResourceDecl, Name,
SC_Static);
279 auto *CounterOrderID = llvm::ConstantInt::get(CGM.
IntTy, CounterBinding);
296 CGF.
EmitCall(FnInfo, Callee, ReturnValue, Args,
nullptr);
304static std::optional<llvm::Value *> initializeLocalResourceArray(
307 llvm::Value *Range, llvm::Value *StartIndex, StringRef ResourceName,
312 llvm::IntegerType *IntTy = CGF.
CGM.
IntTy;
313 llvm::Value *Index = StartIndex;
314 llvm::Value *One = llvm::ConstantInt::get(IntTy, 1);
322 GEPIndices.push_back(llvm::ConstantInt::get(IntTy, 0));
327 for (uint64_t I = 0; I < ArraySize; I++) {
329 Index = CGF.
Builder.CreateAdd(Index, One);
330 GEPIndices.back() = llvm::ConstantInt::get(IntTy, I);
332 std::optional<llvm::Value *> MaybeIndex = initializeLocalResourceArray(
333 CGF, ResourceDecl, SubArrayTy, ValueSlot, Range, Index, ResourceName,
334 Binding, GEPIndices, ArraySubsExprLoc);
348 for (uint64_t I = 0; I < ArraySize; I++) {
350 Index = CGF.
Builder.CreateAdd(Index, One);
351 GEPIndices.back() = llvm::ConstantInt::get(IntTy, I);
357 CXXMethodDecl *CreateMethod = lookupResourceInitMethodAndSetupArgs(
358 CGF.
CGM, ResourceDecl, Range, Index, ResourceName, Binding, Args);
366 callResourceInitMethod(CGF, CreateMethod, Args, ReturnAddress);
376 assert(T->isHLSLSpecificType() &&
"Not an HLSL specific type!");
379 if (llvm::Type *TargetTy =
380 CGM.getTargetCodeGenInfo().getHLSLType(
CGM, T, OffsetInfo))
383 llvm_unreachable(
"Generic handling of HLSL types is not supported.");
386llvm::Triple::ArchType CGHLSLRuntime::getArch() {
392void CGHLSLRuntime::emitBufferGlobalsAndMetadata(
398 llvm::Type *BufType = BufGV->getValueType();
403 size_t OffsetIdx = 0;
413 VarDecl *VD = dyn_cast<VarDecl>(D);
429 DeclsWithOffset.emplace_back(VD, OffsetInfo[OffsetIdx++]);
432 if (!OffsetInfo.
empty())
433 llvm::stable_sort(DeclsWithOffset, [](
const auto &LHS,
const auto &RHS) {
438 SmallVector<llvm::Metadata *> BufGlobals;
439 BufGlobals.reserve(DeclsWithOffset.size() + 1);
440 BufGlobals.push_back(ValueAsMetadata::get(BufGV));
442 auto ElemIt = LayoutStruct->element_begin();
443 for (
auto &[VD, _] : DeclsWithOffset) {
444 if (
CGM.getTargetCodeGenInfo().isHLSLPadding(*ElemIt))
447 assert(ElemIt != LayoutStruct->element_end() &&
448 "number of elements in layout struct does not match");
449 llvm::Type *LayoutType = *ElemIt++;
451 GlobalVariable *ElemGV =
453 BufGlobals.push_back(ValueAsMetadata::get(ElemGV));
455 assert(ElemIt == LayoutStruct->element_end() &&
456 "number of elements in layout struct does not match");
460 .getOrInsertNamedMetadata(
"hlsl.cbs")
461 ->addOperand(MDNode::get(Ctx, BufGlobals));
465static const clang::HLSLAttributedResourceType *
470 HLSLAttributedResourceType::Attributes(ResourceClass::CBuffer));
485 VarDecl *VD = dyn_cast<VarDecl>(D);
496 if (
auto *POA = dyn_cast<HLSLPackOffsetAttr>(
Attr)) {
497 Offset = POA->getOffsetInBytes();
500 auto *RBA = dyn_cast<HLSLResourceBindingAttr>(
Attr);
502 RBA->getRegisterType() == HLSLResourceBindingAttr::RegisterType::C) {
503 Offset = RBA->getSlotNumber() * CBufferRowSizeInBytes;
507 Result.Offsets.push_back(Offset);
515 assert(BufDecl->
isCBuffer() &&
"tbuffer codegen is not supported yet");
518 const clang::HLSLAttributedResourceType *ResHandleTy =
522 if (ResHandleTy->getContainedType()->getAsCXXRecordDecl()->isEmpty())
528 llvm::GlobalVariable *BufGV =
new GlobalVariable(
530 GlobalValue::LinkageTypes::ExternalLinkage, PoisonValue::get(LayoutTy),
531 llvm::formatv(
"{0}{1}", BufDecl->
getName(),
533 GlobalValue::NotThreadLocal);
534 CGM.getModule().insertGlobalVariable(BufGV);
537 emitBufferGlobalsAndMetadata(BufDecl, BufGV, OffsetInfo);
540 initializeBufferFromBinding(BufDecl, BufGV);
545 llvm::Module &M =
CGM.getModule();
546 Triple T(M.getTargetTriple());
549 if (T.getEnvironment() != Triple::EnvironmentType::RootSignature)
552 addRootSignatureMD(SignatureDecl->
getVersion(),
558 const auto Entry = LayoutTypes.find(StructType);
559 if (Entry != LayoutTypes.end())
560 return Entry->getSecond();
565 llvm::StructType *LayoutTy) {
567 "layout type for this struct already exist");
568 LayoutTypes[StructType] = LayoutTy;
572 auto &TargetOpts =
CGM.getTarget().getTargetOpts();
573 auto &CodeGenOpts =
CGM.getCodeGenOpts();
574 auto &LangOpts =
CGM.getLangOpts();
575 llvm::Module &M =
CGM.getModule();
576 Triple T(M.getTargetTriple());
577 if (T.getArch() == Triple::ArchType::dxil)
578 addDxilValVersion(TargetOpts.DxilValidatorVersion, M);
579 if (CodeGenOpts.ResMayAlias)
580 M.setModuleFlag(llvm::Module::ModFlagBehavior::Error,
"dx.resmayalias", 1);
581 if (CodeGenOpts.AllResourcesBound)
582 M.setModuleFlag(llvm::Module::ModFlagBehavior::Error,
583 "dx.allresourcesbound", 1);
584 if (CodeGenOpts.OptimizationLevel == 0)
585 M.addModuleFlag(llvm::Module::ModFlagBehavior::Override,
586 "dx.disable_optimizations", 1);
591 if (LangOpts.NativeHalfType)
592 M.setModuleFlag(llvm::Module::ModFlagBehavior::Error,
"dx.nativelowprec",
600 const auto *ShaderAttr = FD->
getAttr<HLSLShaderAttr>();
601 assert(ShaderAttr &&
"All entry functions must have a HLSLShaderAttr");
602 const StringRef ShaderAttrKindStr =
"hlsl.shader";
603 Fn->addFnAttr(ShaderAttrKindStr,
604 llvm::Triple::getEnvironmentTypeName(ShaderAttr->getType()));
605 if (HLSLNumThreadsAttr *NumThreadsAttr = FD->
getAttr<HLSLNumThreadsAttr>()) {
606 const StringRef NumThreadsKindStr =
"hlsl.numthreads";
607 std::string NumThreadsStr =
608 formatv(
"{0},{1},{2}", NumThreadsAttr->getX(), NumThreadsAttr->getY(),
609 NumThreadsAttr->getZ());
610 Fn->addFnAttr(NumThreadsKindStr, NumThreadsStr);
612 if (HLSLWaveSizeAttr *WaveSizeAttr = FD->
getAttr<HLSLWaveSizeAttr>()) {
613 const StringRef WaveSizeKindStr =
"hlsl.wavesize";
614 std::string WaveSizeStr =
615 formatv(
"{0},{1},{2}", WaveSizeAttr->getMin(), WaveSizeAttr->getMax(),
616 WaveSizeAttr->getPreferred());
617 Fn->addFnAttr(WaveSizeKindStr, WaveSizeStr);
624 Fn->addFnAttr(llvm::Attribute::NoInline);
626 if (
CGM.getLangOpts().HLSLSpvEnableMaximalReconvergence) {
627 Fn->addFnAttr(
"enable-maximal-reconvergence",
"true");
632 if (
const auto *VT = dyn_cast<FixedVectorType>(Ty)) {
634 for (
unsigned I = 0; I < VT->getNumElements(); ++I) {
635 Value *Elt = B.CreateCall(F, {B.getInt32(I)});
640 return B.CreateCall(F, {B.getInt32(0)});
645 LLVMContext &Ctx = GV->getContext();
646 IRBuilder<> B(GV->getContext());
647 MDNode *Operands = MDNode::get(
649 {ConstantAsMetadata::get(B.getInt32( 11)),
650 ConstantAsMetadata::get(B.getInt32(BuiltIn))});
651 MDNode *Decoration = MDNode::get(Ctx, {Operands});
652 GV->addMetadata(
"spirv.Decorations", *Decoration);
656 LLVMContext &Ctx = GV->getContext();
657 IRBuilder<> B(GV->getContext());
659 MDNode::get(Ctx, {ConstantAsMetadata::get(B.getInt32( 30)),
660 ConstantAsMetadata::get(B.getInt32(Location))});
661 MDNode *Decoration = MDNode::get(Ctx, {Operands});
662 GV->addMetadata(
"spirv.Decorations", *Decoration);
666 llvm::Type *Ty,
const Twine &Name,
667 unsigned BuiltInID) {
668 auto *GV =
new llvm::GlobalVariable(
669 M, Ty,
true, llvm::GlobalValue::ExternalLinkage,
670 nullptr, Name,
nullptr,
671 llvm::GlobalVariable::GeneralDynamicTLSModel,
674 GV->setVisibility(llvm::GlobalValue::HiddenVisibility);
675 return B.CreateLoad(Ty, GV);
679 llvm::Type *Ty,
unsigned Location,
681 auto *GV =
new llvm::GlobalVariable(
682 M, Ty,
true, llvm::GlobalValue::ExternalLinkage,
683 nullptr, Name,
nullptr,
684 llvm::GlobalVariable::GeneralDynamicTLSModel,
686 GV->setVisibility(llvm::GlobalValue::HiddenVisibility);
688 return B.CreateLoad(Ty, GV);
691llvm::Value *CGHLSLRuntime::emitSPIRVUserSemanticLoad(
692 llvm::IRBuilder<> &B, llvm::Type *
Type,
const clang::DeclaratorDecl *
Decl,
693 HLSLAppliedSemanticAttr *Semantic, std::optional<unsigned> Index) {
694 Twine BaseName = Twine(Semantic->getAttrName()->getName());
695 Twine VariableName = BaseName.concat(Twine(Index.value_or(0)));
697 unsigned Location = SPIRVLastAssignedInputSemanticLocation;
698 if (
auto *L =
Decl->getAttr<HLSLVkLocationAttr>())
699 Location = L->getLocation();
703 llvm::ArrayType *AT = dyn_cast<llvm::ArrayType>(
Type);
704 unsigned ElementCount = AT ? AT->getNumElements() : 1;
705 SPIRVLastAssignedInputSemanticLocation += ElementCount;
712 llvm::Value *Source,
unsigned Location,
714 auto *GV =
new llvm::GlobalVariable(
715 M, Source->getType(),
false,
716 llvm::GlobalValue::ExternalLinkage,
717 nullptr, Name,
nullptr,
718 llvm::GlobalVariable::GeneralDynamicTLSModel,
720 GV->setVisibility(llvm::GlobalValue::HiddenVisibility);
722 B.CreateStore(Source, GV);
725void CGHLSLRuntime::emitSPIRVUserSemanticStore(
726 llvm::IRBuilder<> &B, llvm::Value *Source,
727 const clang::DeclaratorDecl *
Decl, HLSLAppliedSemanticAttr *Semantic,
728 std::optional<unsigned> Index) {
729 Twine BaseName = Twine(Semantic->getAttrName()->getName());
730 Twine VariableName = BaseName.concat(Twine(Index.value_or(0)));
732 unsigned Location = SPIRVLastAssignedOutputSemanticLocation;
733 if (
auto *L =
Decl->getAttr<HLSLVkLocationAttr>())
734 Location = L->getLocation();
738 llvm::ArrayType *AT = dyn_cast<llvm::ArrayType>(Source->getType());
739 unsigned ElementCount = AT ? AT->getNumElements() : 1;
740 SPIRVLastAssignedOutputSemanticLocation += ElementCount;
746CGHLSLRuntime::emitDXILUserSemanticLoad(llvm::IRBuilder<> &B, llvm::Type *
Type,
747 HLSLAppliedSemanticAttr *Semantic,
748 std::optional<unsigned> Index) {
749 Twine BaseName = Twine(Semantic->getAttrName()->getName());
750 Twine VariableName = BaseName.concat(Twine(Index.value_or(0)));
755 SmallVector<Value *> Args{B.getInt32(4), B.getInt32(0), B.getInt32(0),
757 llvm::PoisonValue::get(B.getInt32Ty())};
759 llvm::Intrinsic::ID IntrinsicID = llvm::Intrinsic::dx_load_input;
760 llvm::Value *
Value = B.CreateIntrinsic(
Type, IntrinsicID, Args,
761 nullptr, VariableName);
765void CGHLSLRuntime::emitDXILUserSemanticStore(llvm::IRBuilder<> &B,
767 HLSLAppliedSemanticAttr *Semantic,
768 std::optional<unsigned> Index) {
771 SmallVector<Value *> Args{B.getInt32(4),
775 llvm::PoisonValue::get(B.getInt32Ty()),
778 llvm::Intrinsic::ID IntrinsicID = llvm::Intrinsic::dx_store_output;
779 B.CreateIntrinsic(
CGM.VoidTy, IntrinsicID, Args,
nullptr);
782llvm::Value *CGHLSLRuntime::emitUserSemanticLoad(
783 IRBuilder<> &B, llvm::Type *
Type,
const clang::DeclaratorDecl *
Decl,
784 HLSLAppliedSemanticAttr *Semantic, std::optional<unsigned> Index) {
785 if (
CGM.getTarget().getTriple().isSPIRV())
786 return emitSPIRVUserSemanticLoad(B,
Type,
Decl, Semantic, Index);
788 if (
CGM.getTarget().getTriple().isDXIL())
789 return emitDXILUserSemanticLoad(B,
Type, Semantic, Index);
791 llvm_unreachable(
"Unsupported target for user-semantic load.");
794void CGHLSLRuntime::emitUserSemanticStore(IRBuilder<> &B, llvm::Value *Source,
795 const clang::DeclaratorDecl *
Decl,
796 HLSLAppliedSemanticAttr *Semantic,
797 std::optional<unsigned> Index) {
798 if (
CGM.getTarget().getTriple().isSPIRV())
799 return emitSPIRVUserSemanticStore(B, Source,
Decl, Semantic, Index);
801 if (
CGM.getTarget().getTriple().isDXIL())
802 return emitDXILUserSemanticStore(B, Source, Semantic, Index);
804 llvm_unreachable(
"Unsupported target for user-semantic load.");
810 std::optional<unsigned> Index) {
812 std::string SemanticName = Semantic->getAttrName()->getName().upper();
813 if (SemanticName ==
"SV_GROUPINDEX") {
814 llvm::Function *GroupIndex =
815 CGM.getIntrinsic(getFlattenedThreadIdInGroupIntrinsic());
816 return B.CreateCall(FunctionCallee(GroupIndex));
819 if (SemanticName ==
"SV_DISPATCHTHREADID") {
820 llvm::Intrinsic::ID IntrinID = getThreadIdIntrinsic();
821 llvm::Function *ThreadIDIntrinsic =
822 llvm::Intrinsic::isOverloaded(IntrinID)
823 ?
CGM.getIntrinsic(IntrinID, {
CGM.Int32Ty})
824 :
CGM.getIntrinsic(IntrinID);
828 if (SemanticName ==
"SV_GROUPTHREADID") {
829 llvm::Intrinsic::ID IntrinID = getGroupThreadIdIntrinsic();
830 llvm::Function *GroupThreadIDIntrinsic =
831 llvm::Intrinsic::isOverloaded(IntrinID)
832 ?
CGM.getIntrinsic(IntrinID, {
CGM.Int32Ty})
833 :
CGM.getIntrinsic(IntrinID);
837 if (SemanticName ==
"SV_GROUPID") {
838 llvm::Intrinsic::ID IntrinID = getGroupIdIntrinsic();
839 llvm::Function *GroupIDIntrinsic =
840 llvm::Intrinsic::isOverloaded(IntrinID)
841 ?
CGM.getIntrinsic(IntrinID, {
CGM.Int32Ty})
842 :
CGM.getIntrinsic(IntrinID);
846 const auto *ShaderAttr = FD->
getAttr<HLSLShaderAttr>();
847 assert(ShaderAttr &&
"Entry point has no shader attribute");
848 llvm::Triple::EnvironmentType ST = ShaderAttr->getType();
850 if (SemanticName ==
"SV_POSITION") {
851 if (ST == Triple::EnvironmentType::Pixel) {
852 if (
CGM.getTarget().getTriple().isSPIRV())
854 Semantic->getAttrName()->getName(),
856 if (
CGM.getTarget().getTriple().isDXIL())
857 return emitDXILUserSemanticLoad(B,
Type, Semantic, Index);
860 if (ST == Triple::EnvironmentType::Vertex) {
861 return emitUserSemanticLoad(B,
Type,
Decl, Semantic, Index);
865 if (SemanticName ==
"SV_VERTEXID") {
866 if (ST == Triple::EnvironmentType::Vertex) {
867 if (
CGM.getTarget().getTriple().isSPIRV())
869 Semantic->getAttrName()->getName(),
872 return emitDXILUserSemanticLoad(B,
Type, Semantic, Index);
877 "Load hasn't been implemented yet for this system semantic. FIXME");
881 llvm::Value *Source,
const Twine &Name,
882 unsigned BuiltInID) {
883 auto *GV =
new llvm::GlobalVariable(
884 M, Source->getType(),
false,
885 llvm::GlobalValue::ExternalLinkage,
886 nullptr, Name,
nullptr,
887 llvm::GlobalVariable::GeneralDynamicTLSModel,
890 GV->setVisibility(llvm::GlobalValue::HiddenVisibility);
891 B.CreateStore(Source, GV);
896 HLSLAppliedSemanticAttr *Semantic,
897 std::optional<unsigned> Index) {
899 std::string SemanticName = Semantic->getAttrName()->getName().upper();
900 if (SemanticName ==
"SV_POSITION") {
901 if (
CGM.getTarget().getTriple().isDXIL()) {
902 emitDXILUserSemanticStore(B, Source, Semantic, Index);
906 if (
CGM.getTarget().getTriple().isSPIRV()) {
908 Semantic->getAttrName()->getName(),
914 if (SemanticName ==
"SV_TARGET") {
915 emitUserSemanticStore(B, Source,
Decl, Semantic, Index);
920 "Store hasn't been implemented yet for this system semantic. FIXME");
927 std::optional<unsigned> Index = Semantic->getSemanticIndex();
928 if (Semantic->getAttrName()->getName().starts_with_insensitive(
"SV_"))
930 return emitUserSemanticLoad(B,
Type,
Decl, Semantic, Index);
934 IRBuilder<> &B,
const FunctionDecl *FD, llvm::Value *Source,
936 std::optional<unsigned> Index = Semantic->getSemanticIndex();
937 if (Semantic->getAttrName()->getName().starts_with_insensitive(
"SV_"))
940 emitUserSemanticStore(B, Source,
Decl, Semantic, Index);
943std::pair<llvm::Value *, specific_attr_iterator<HLSLAppliedSemanticAttr>>
956 for (
unsigned I = 0; I < ST->getNumElements(); ++I) {
958 B, FD, ST->getElementType(I), *
FieldDecl, AttrBegin, AttrEnd);
959 AttrBegin = NextAttr;
965 return std::make_pair(
Aggregate, AttrBegin);
970 IRBuilder<> &B,
const FunctionDecl *FD, llvm::Value *Source,
981 RD =
Decl->getType()->getAsRecordDecl();
987 for (
unsigned I = 0; I < ST->getNumElements(); ++I, ++
FieldDecl) {
988 llvm::Value *Extract = B.CreateExtractValue(Source, I);
996std::pair<llvm::Value *, specific_attr_iterator<HLSLAppliedSemanticAttr>>
1002 assert(AttrBegin != AttrEnd);
1003 if (
Type->isStructTy())
1006 HLSLAppliedSemanticAttr *
Attr = *AttrBegin;
1014 IRBuilder<> &B,
const FunctionDecl *FD, llvm::Value *Source,
1018 assert(AttrBegin != AttrEnd);
1019 if (Source->getType()->isStructTy())
1022 HLSLAppliedSemanticAttr *
Attr = *AttrBegin;
1029 llvm::Function *Fn) {
1030 llvm::Module &M =
CGM.getModule();
1031 llvm::LLVMContext &Ctx = M.getContext();
1032 auto *EntryTy = llvm::FunctionType::get(llvm::Type::getVoidTy(Ctx),
false);
1034 Function::Create(EntryTy, Function::ExternalLinkage, FD->
getName(), &M);
1038 AttributeList NewAttrs = AttributeList::get(Ctx, AttributeList::FunctionIndex,
1039 Fn->getAttributes().getFnAttrs());
1040 EntryFn->setAttributes(NewAttrs);
1044 Fn->setLinkage(GlobalValue::InternalLinkage);
1046 BasicBlock *BB = BasicBlock::Create(Ctx,
"entry", EntryFn);
1051 if (
CGM.shouldEmitConvergenceTokens()) {
1052 assert(EntryFn->isConvergent());
1054 B.CreateIntrinsic(llvm::Intrinsic::experimental_convergence_entry, {});
1055 llvm::Value *bundleArgs[] = {I};
1056 OB.emplace_back(
"convergencectrl", bundleArgs);
1061 unsigned SRetOffset = 0;
1062 for (
const auto &Param : Fn->args()) {
1063 if (Param.hasStructRetAttr()) {
1065 llvm::Type *VarType = Param.getParamStructRetType();
1067 CGM.getLangOpts().EmitLogicalPointer
1070 OutputSemantic.push_back(std::make_pair(Var, VarType));
1071 Args.push_back(Var);
1076 llvm::Value *SemanticValue =
nullptr;
1078 if ([[maybe_unused]] HLSLParamModifierAttr *MA =
1079 PD->
getAttr<HLSLParamModifierAttr>()) {
1080 llvm_unreachable(
"Not handled yet");
1082 llvm::Type *ParamType =
1083 Param.hasByValAttr() ? Param.getParamByValType() : Param.getType();
1088 SemanticValue =
Result.first;
1091 if (Param.hasByValAttr()) {
1093 CGM.getLangOpts().EmitLogicalPointer
1095 B.CreateStructuredAlloca(Param.getParamByValType()))
1097 B.CreateStore(SemanticValue, Var);
1098 SemanticValue = Var;
1102 assert(SemanticValue);
1103 Args.push_back(SemanticValue);
1106 CallInst *CI = B.CreateCall(FunctionCallee(Fn), Args, OB);
1107 CI->setCallingConv(Fn->getCallingConv());
1109 if (Fn->getReturnType() !=
CGM.VoidTy)
1111 OutputSemantic.push_back(std::make_pair(CI,
nullptr));
1113 for (
auto &SourcePair : OutputSemantic) {
1114 llvm::Value *Source = SourcePair.first;
1115 llvm::Type *ElementType = SourcePair.second;
1116 AllocaInst *AI = dyn_cast<AllocaInst>(Source);
1117 llvm::Value *SourceValue = AI ? B.CreateLoad(ElementType, Source) : Source;
1128 if (
const auto *RSAttr = dyn_cast<RootSignatureAttr>(
Attr)) {
1129 auto *RSDecl = RSAttr->getSignatureDecl();
1130 addRootSignatureMD(RSDecl->getVersion(), RSDecl->getRootElements(),
1139 M.getNamedGlobal(CtorOrDtor ?
"llvm.global_ctors" :
"llvm.global_dtors");
1142 const auto *CA = dyn_cast<ConstantArray>(GV->getInitializer());
1149 for (
const auto &Ctor : CA->operands()) {
1155 "HLSL doesn't support setting priority for global ctors.");
1157 "HLSL doesn't support COMDat for global ctors.");
1163 llvm::Module &M =
CGM.getModule();
1172 for (
auto &F : M.functions()) {
1173 if (!F.hasFnAttribute(
"hlsl.shader"))
1176 Instruction *IP = &*F.getEntryBlock().begin();
1179 llvm::Value *bundleArgs[] = {
Token};
1180 OB.emplace_back(
"convergencectrl", bundleArgs);
1181 IP =
Token->getNextNode();
1184 for (
auto *Fn : CtorFns) {
1185 auto CI = B.CreateCall(FunctionCallee(Fn), {}, OB);
1186 CI->setCallingConv(Fn->getCallingConv());
1190 B.SetInsertPoint(F.back().getTerminator());
1191 for (
auto *Fn : DtorFns) {
1192 auto CI = B.CreateCall(FunctionCallee(Fn), {}, OB);
1193 CI->setCallingConv(Fn->getCallingConv());
1199 Triple T(M.getTargetTriple());
1200 if (T.getEnvironment() != Triple::EnvironmentType::Library) {
1201 if (
auto *GV = M.getNamedGlobal(
"llvm.global_ctors"))
1202 GV->eraseFromParent();
1203 if (
auto *GV = M.getNamedGlobal(
"llvm.global_dtors"))
1204 GV->eraseFromParent();
1209 Intrinsic::ID IntrID,
1213 llvm::Function *InitResFunc = llvm::Function::Create(
1214 llvm::FunctionType::get(CGM.
VoidTy,
false),
1215 llvm::GlobalValue::InternalLinkage,
1216 (
"_init_buffer_" + GV->getName()).str(), CGM.
getModule());
1217 InitResFunc->addFnAttr(llvm::Attribute::AlwaysInline);
1219 llvm::BasicBlock *EntryBB =
1220 llvm::BasicBlock::Create(Ctx,
"entry", InitResFunc);
1222 const DataLayout &DL = CGM.
getModule().getDataLayout();
1223 Builder.SetInsertPoint(EntryBB);
1226 llvm::Type *HandleTy = GV->getValueType();
1227 assert(HandleTy->isTargetExtTy() &&
"unexpected type of the buffer global");
1229 llvm::Value *CreateHandle = Builder.CreateIntrinsic(
1230 HandleTy, IntrID, Args,
nullptr,
1231 Twine(GV->getName()).concat(
"_h"));
1233 Builder.CreateAlignedStore(CreateHandle, GV, GV->getPointerAlignment(DL));
1234 Builder.CreateRetVoid();
1239void CGHLSLRuntime::initializeBufferFromBinding(
const HLSLBufferDecl *BufDecl,
1240 llvm::GlobalVariable *GV) {
1241 ResourceBindingAttrs Binding(BufDecl);
1243 "cbuffer/tbuffer should always have resource binding attribute");
1245 auto *Index = llvm::ConstantInt::get(
CGM.IntTy, 0);
1246 auto *RangeSize = llvm::ConstantInt::get(
CGM.IntTy, 1);
1247 auto *Space = llvm::ConstantInt::get(
CGM.IntTy, Binding.
getSpace());
1252 llvm::Intrinsic::ID IntrinsicID =
1253 CGM.getHLSLRuntime().getCreateHandleFromBindingIntrinsic();
1254 auto *RegSlot = llvm::ConstantInt::get(
CGM.IntTy, Binding.
getSlot());
1255 SmallVector<Value *> Args{Space, RegSlot, RangeSize, Index, Name};
1259 llvm::Intrinsic::ID IntrinsicID =
1260 CGM.getHLSLRuntime().getCreateHandleFromImplicitBindingIntrinsic();
1263 SmallVector<Value *> Args{OrderID, Space, RangeSize, Index, Name};
1269 llvm::GlobalVariable *GV) {
1270 if (
auto Attr = VD->
getAttr<HLSLVkExtBuiltinInputAttr>())
1272 if (
auto Attr = VD->
getAttr<HLSLVkExtBuiltinOutputAttr>())
1277 if (!
CGM.shouldEmitConvergenceTokens())
1281 for (
auto I = BB.begin(); I != E; ++I) {
1282 auto *II = dyn_cast<llvm::IntrinsicInst>(&*I);
1283 if (II && llvm::isConvergenceControlIntrinsic(II->getIntrinsicID())) {
1287 llvm_unreachable(
"Convergence token should have been emitted.");
1324 for (
auto *OVE : Visitor.
OVEs) {
1327 if (OpaqueValueMappingData::shouldBindAsLValue(OVE)) {
1329 OpaqueValueMappingData::bind(CGF, OVE, LV);
1332 OpaqueValueMappingData::bind(CGF, OVE, RV);
1341 "expected resource array subscript expression");
1346 const VarDecl *ArrayDecl = dyn_cast_or_null<VarDecl>(
1350 return std::nullopt;
1356 "expected array of resource classes");
1362 Value *Index =
nullptr;
1364 while (ASE !=
nullptr) {
1366 if (
const auto *ArrayTy =
1368 Value *Multiplier = llvm::ConstantInt::get(
1370 SubIndex = CGF.
Builder.CreateMul(SubIndex, Multiplier);
1372 Index = Index ? CGF.
Builder.CreateAdd(Index, SubIndex) : SubIndex;
1380 "resource array must have a binding attribute");
1401 llvm::Value *Range = llvm::ConstantInt::getSigned(
1402 CGM.IntTy, getTotalArraySize(AST, ResArrayTy));
1406 if (ResultTy == ResourceTy) {
1408 CXXMethodDecl *CreateMethod = lookupResourceInitMethodAndSetupArgs(
1410 ArrayDecl->
getName(), Binding, Args);
1412 if (!CreateMethod) {
1417 "create method lookup should always succeed for built-in resource "
1419 return std::nullopt;
1422 callResourceInitMethod(CGF, CreateMethod, Args, ValueSlot.getAddress());
1429 std::optional<llvm::Value *> EndIndex = initializeLocalResourceArray(
1431 ArrayDecl->
getName(), Binding, {llvm::ConstantInt::get(CGM.IntTy, 0)},
1434 return std::nullopt;
1449 dyn_cast_or_null<VarDecl>(getArrayDecl(CGF.
CGM.
getContext(), RHSExpr));
1458 "resource array must have a binding attribute");
1472 int Size = getTotalArraySize(AST, ResArrayTy);
1473 llvm::Value *
Zero = llvm::ConstantInt::get(
CGM.IntTy, 0);
1474 llvm::Value *Range = llvm::ConstantInt::get(
CGM.IntTy, Size);
1477 std::optional<llvm::Value *> EndIndex = initializeLocalResourceArray(
1480 return EndIndex.has_value();
1489 "expected cbuffer matrix");
1495 if (LayoutTy == MemTy)
1511 llvm::function_ref<llvm::Value *(
bool Promote)> EmitIdxAfterBase) {
1515 llvm::Type *LayoutTy =
1517 uint64_t LayoutSizeInBits =
1518 CGM.getDataLayout().getTypeSizeInBits(LayoutTy).getFixedValue();
1521 if (RowAlignedSize > ElementSize) {
1522 llvm::Type *Padding =
CGM.getTargetCodeGenInfo().getHLSLPadding(
1523 CGM, RowAlignedSize - ElementSize);
1524 assert(Padding &&
"No padding type for target?");
1525 LayoutTy = llvm::StructType::get(CGF.
getLLVMContext(), {LayoutTy, Padding},
1532 if (LayoutTy == OrigTy)
1533 return std::nullopt;
1542 llvm::Value *Idx = EmitIdxAfterBase(
true);
1543 Indices.push_back(Idx);
1544 Indices.push_back(llvm::ConstantInt::get(CGF.
Int32Ty, 0));
1550 assert(CE->
getCastKind() == CastKind::CK_ArrayToPointerDecay);
1554 LayoutTy = llvm::ArrayType::get(
1558 LayoutTy,
Addr.emitRawPointer(CGF), Indices,
"cbufferidx"));
1567 Indices,
"cbufferidx");
1572std::optional<LValue>
1577 "expected resource member expression");
1583 return std::nullopt;
1587 findAssociatedResourceDeclForStruct(CGF.
CGM.
getContext(), ME);
1589 return std::nullopt;
1591 GlobalVariable *ResGV =
1593 const DataLayout &DL =
CGM.getDataLayout();
1594 llvm::Type *Ty = ResGV->getValueType();
1606class HLSLBufferCopyEmitter {
1610 llvm::Type *LayoutTy =
nullptr;
1617 llvm::Value *emitAccessChain(llvm::Type *BaseTy, llvm::Value *
Base,
1619 bool EmitLogical = CGF.
getLangOpts().EmitLogicalPointer;
1624 GEPIndices.reserve(Indices.size() + 1);
1625 GEPIndices.push_back(llvm::ConstantInt::get(CGF.
IntTy, 0));
1626 GEPIndices.append(Indices.begin(), Indices.end());
1630 bool isBufferLayoutArray(llvm::StructType *ST) {
1636 if (!ST || ST->getNumElements() != 2)
1639 auto *PaddedEltsTy = dyn_cast<llvm::ArrayType>(ST->getElementType(0));
1643 auto *PaddedTy = dyn_cast<llvm::StructType>(PaddedEltsTy->getElementType());
1644 if (!PaddedTy || PaddedTy->getNumElements() != 2)
1648 PaddedTy->getElementType(1)))
1651 llvm::Type *ElementTy = ST->getElementType(1);
1652 if (PaddedTy->getElementType(0) != ElementTy)
1657 void emitBufferLayoutCopy(
Value *Src, llvm::StructType *SrcTy,
Value *Dst,
1658 llvm::ArrayType *DstTy) {
1661 assert(SrcPaddedArrayTy->getNumElements() + 1 == DstTy->getNumElements());
1663 ->getElementType(0) == SrcTy->getElementType(1));
1665 auto *SrcDataTy = SrcTy->getElementType(1);
1666 auto Zero = llvm::ConstantInt::get(CGF.
IntTy, 0);
1668 for (
unsigned I = 0; I < SrcPaddedArrayTy->getNumElements(); ++I) {
1669 auto Index = llvm::ConstantInt::get(CGF.
IntTy, I);
1670 auto *SrcElt = emitAccessChain(SrcTy, Src, {
Zero, Index,
Zero});
1671 auto *DstElt = emitAccessChain(DstTy, Dst, {Index});
1672 emitElementCopy(SrcElt, SrcDataTy, DstElt, DstTy->getElementType());
1676 emitAccessChain(SrcTy, Src, {llvm::ConstantInt::get(CGF.
IntTy, 1)});
1677 auto *DstElt = emitAccessChain(
1679 {llvm::ConstantInt::get(CGF.
IntTy, DstTy->getNumElements() - 1)});
1680 emitElementCopy(SrcElt, SrcDataTy, DstElt, DstTy->getElementType());
1683 void emitCopy(
Value *Src, llvm::StructType *SrcTy,
Value *Dst,
1684 llvm::Type *DstTy) {
1685 if (isBufferLayoutArray(SrcTy))
1686 return emitBufferLayoutCopy(Src, SrcTy, Dst,
1689 unsigned SrcIndex = 0;
1690 unsigned DstIndex = 0;
1693 while (SrcIndex < SrcTy->getNumElements() &&
1694 DstIndex < DstST->getNumElements()) {
1696 SrcTy->getElementType(SrcIndex))) {
1702 DstST->getElementType(DstIndex))) {
1707 auto *SrcElt = emitAccessChain(
1708 SrcTy, Src, {llvm::ConstantInt::get(CGF.
IntTy, SrcIndex)});
1709 auto *DstElt = emitAccessChain(
1710 DstTy, Dst, {llvm::ConstantInt::get(CGF.
IntTy, DstIndex)});
1711 emitElementCopy(SrcElt, SrcTy->getElementType(SrcIndex), DstElt,
1712 DstST->getElementType(DstIndex));
1718 void emitCopy(
Value *Src, llvm::ArrayType *SrcTy,
Value *Dst,
1719 llvm::Type *DstTy) {
1720 for (
unsigned I = 0, E = SrcTy->getNumElements(); I < E; ++I) {
1722 emitAccessChain(SrcTy, Src, {llvm::ConstantInt::get(CGF.
IntTy, I)});
1724 emitAccessChain(DstTy, Dst, {llvm::ConstantInt::get(CGF.
IntTy, I)});
1725 emitElementCopy(SrcElt, SrcTy->getElementType(), DstElt,
1730 void emitElementCopy(
Value *Src, llvm::Type *SrcTy,
Value *Dst,
1731 llvm::Type *DstTy) {
1732 if (
auto *AT = dyn_cast<llvm::ArrayType>(SrcTy))
1733 return emitCopy(Src, AT, Dst, DstTy);
1734 if (
auto *ST = dyn_cast<llvm::StructType>(SrcTy))
1735 return emitCopy(Src, ST, Dst, DstTy);
1738 CharUnits SrcAlign =
1740 CharUnits DstAlign =
1742 Address SrcAddr(Src, SrcTy, SrcAlign);
1743 Address DstAddr(Dst, DstTy, DstAlign);
1749 HLSLBufferCopyEmitter(CodeGenFunction &CGF, Address DstPtr, Address SrcPtr)
1750 : CGF(CGF), DstPtr(DstPtr), SrcPtr(SrcPtr) {}
1752 bool emitCopy(QualType CType) {
1753 LayoutTy = HLSLBufferLayoutBuilder(CGF.
CGM).layOutType(CType);
1769 return HLSLBufferCopyEmitter(CGF, DstPtr, SrcPtr).emitCopy(CType);
1777 assert(Field &&
"Unexpected access into HLSL buffer");
1782 QualType RecType =
CGM.getContext().getCanonicalTagType(Rec);
1793 CGM.getTypes().getCGRecordLayout(Rec).getLLVMFieldNo(Field);
1794 assert(FieldIdx < LayoutTy->getNumElements() &&
1795 "Layout struct is smaller than member struct");
1796 unsigned Skipped = 0;
1797 for (
unsigned I = 0; I <= FieldIdx;) {
1798 llvm::Type *ElementTy = LayoutTy->getElementType(I + Skipped);
1804 FieldIdx += Skipped;
1805 assert(FieldIdx < LayoutTy->getNumElements() &&
"Access out of bounds");
1809 QualType FieldType = Field->getType();
1810 llvm::Type *FieldLLVMTy =
CGM.getTypes().ConvertTypeForMem(FieldType);
1815 ? CGF.
Builder.CreateStructuredGEP(
1816 LayoutTy,
Base.getPointer(CGF),
1817 llvm::ConstantInt::get(
CGM.IntTy, FieldIdx))
1819 FieldIdx, Field->getName());
1824 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)
bool emitResourceArrayCopy(LValue &LHS, Expr *RHSExpr, CodeGenFunction &CGF)
LValue emitBufferMemberExpr(CodeGenFunction &CGF, const MemberExpr *E)
bool emitBufferCopy(CodeGenFunction &CGF, Address DestPtr, Address SrcPtr, QualType CType)
llvm::Type * convertHLSLSpecificType(const Type *T, const CGHLSLOffsetInfo &OffsetInfo)
llvm::Value * emitSystemSemanticLoad(llvm::IRBuilder<> &B, const FunctionDecl *FD, llvm::Type *Type, const clang::DeclaratorDecl *Decl, HLSLAppliedSemanticAttr *Semantic, std::optional< unsigned > Index)
RawAddress createBufferMatrixTempAddress(const LValue &LV, SourceLocation Loc, CodeGenFunction &CGF)
void addBuffer(const HLSLBufferDecl *D)
void 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...
const LangOptions & getLangOpts() const
@ TCK_MemberAccess
Checking the object expression in a non-static data member access.
void pushFullExprCleanup(CleanupKind kind, As... A)
pushFullExprCleanup - Push a cleanup to be run at the end of the current full-expression.
bool EmitLifetimeStart(llvm::Value *Addr)
Emit a lifetime.begin marker if some criteria are satisfied.
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.
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