33#include "llvm/ADT/DenseMap.h"
34#include "llvm/ADT/STLExtras.h"
35#include "llvm/ADT/ScopeExit.h"
36#include "llvm/ADT/SmallString.h"
37#include "llvm/ADT/SmallVector.h"
38#include "llvm/Frontend/HLSL/RootSignatureMetadata.h"
39#include "llvm/IR/Constants.h"
40#include "llvm/IR/DerivedTypes.h"
41#include "llvm/IR/GlobalVariable.h"
42#include "llvm/IR/IntrinsicInst.h"
43#include "llvm/IR/LLVMContext.h"
44#include "llvm/IR/Metadata.h"
45#include "llvm/IR/Module.h"
46#include "llvm/IR/Type.h"
47#include "llvm/IR/Value.h"
48#include "llvm/Support/Alignment.h"
49#include "llvm/Support/ErrorHandling.h"
50#include "llvm/Support/FormatVariadic.h"
51#include "llvm/Support/Path.h"
52#include "llvm/Transforms/Utils/ModuleUtils.h"
61using llvm::hlsl::CBufferRowSizeInBytes;
65void addDxilValVersion(StringRef ValVersionStr, llvm::Module &M) {
69 if (Version.tryParse(ValVersionStr) || Version.getBuild() ||
70 Version.getSubminor() || !Version.getMinor()) {
74 uint64_t Major = Version.getMajor();
75 uint64_t Minor = *Version.getMinor();
77 auto &Ctx = M.getContext();
78 IRBuilder<> B(M.getContext());
79 MDNode *Val = MDNode::get(Ctx, {ConstantAsMetadata::get(B.getInt32(Major)),
80 ConstantAsMetadata::get(B.getInt32(Minor))});
81 StringRef DXILValKey =
"dx.valver";
82 auto *DXILValMD = M.getOrInsertNamedMetadata(DXILValKey);
83 DXILValMD->addOperand(Val);
86void addRootSignatureMD(llvm::dxbc::RootSignatureVersion RootSigVer,
88 llvm::Function *Fn, llvm::Module &M) {
89 auto &Ctx = M.getContext();
91 llvm::hlsl::rootsig::MetadataBuilder RSBuilder(Ctx, Elements);
92 MDNode *RootSignature = RSBuilder.BuildRootSignature();
94 ConstantAsMetadata *Version = ConstantAsMetadata::get(ConstantInt::get(
95 llvm::Type::getInt32Ty(Ctx), llvm::to_underlying(RootSigVer)));
96 ValueAsMetadata *EntryFunc =
Fn ? ValueAsMetadata::get(Fn) :
nullptr;
97 MDNode *MDVals = MDNode::get(Ctx, {EntryFunc, RootSignature, Version});
99 StringRef RootSignatureValKey =
"dx.rootsignatures";
100 auto *RootSignatureValMD = M.getOrInsertNamedMetadata(RootSignatureValKey);
101 RootSignatureValMD->addOperand(MDVals);
112static const VarDecl *findStructResourceParentDeclAndBuildName(
120 if (
const auto *DRE = dyn_cast<DeclRefExpr>(E)) {
122 "member expr base is not a var decl");
128 WorkList.push_back(E);
129 if (
const auto *MExp = dyn_cast<MemberExpr>(E))
131 else if (
const auto *ICE = dyn_cast<ImplicitCastExpr>(E))
132 E = ICE->getSubExpr();
133 else if (
const auto *ASE = dyn_cast<ArraySubscriptExpr>(E))
140 llvm_unreachable(
"unexpected expr type in resource member access");
142 assert(E &&
"expected valid expression");
145 while (!WorkList.empty()) {
146 E = WorkList.pop_back_val();
147 if (
const auto *ME = dyn_cast<MemberExpr>(E)) {
150 }
else if (
const auto *ICE = dyn_cast<ImplicitCastExpr>(E)) {
151 if (ICE->getCastKind() == CK_UncheckedDerivedToBase) {
153 ICE->getSubExpr()->getType()->getAsCXXRecordDecl();
154 CXXRecordDecl *BaseRD = ICE->getType()->getAsCXXRecordDecl();
157 }
else if (
const auto *ASE = dyn_cast<ArraySubscriptExpr>(E)) {
158 const Expr *IdxExpr = ASE->getIdx();
159 std::optional<llvm::APSInt>
Value =
162 "expected constant index in struct with resource array access");
165 llvm_unreachable(
"unexpected expr type in resource member access");
179 findStructResourceParentDeclAndBuildName(ME, NameBuilder);
188 if (
const auto *ADA = dyn_cast<HLSLAssociatedResourceDeclAttr>(A)) {
189 VarDecl *AssocResVD = ADA->getResDecl();
201 auto &Ctx = M.getContext();
204 llvm::NamedMDNode *DXContents =
205 M.getOrInsertNamedMetadata(
"dx.source.contents");
206 auto addFile = [&](
const std::pair<StringRef, StringRef> &NameContent) {
207 llvm::MDTuple *FileInfo =
208 llvm::MDNode::get(Ctx, {llvm::MDString::get(Ctx, NameContent.first),
209 llvm::MDString::get(Ctx, NameContent.second)});
210 DXContents->addOperand(FileInfo);
216 assert(!
Invalid &&
"Main file SLocEntry must not be invalid!");
221 std::optional<SmallString<256>> MainFileName;
222 Files.reserve(
SM.local_sloc_entry_size());
223 for (
unsigned I : llvm::seq(
SM.local_sloc_entry_size())) {
238 llvm::sys::path::native(Path);
242 SM.getDiagnostics().Report(diag::warn_hlsl_failed_to_embed_source)
247 if (&MainCCEntry != &CCEntry) {
248 Files.emplace_back(Path, Buffer->getBuffer());
251 addFile(std::make_pair(Path, Buffer->getBuffer()));
252 MainFileName.emplace(Path);
255 assert(MainFileName &&
"Main file not found.");
260 for (
unsigned I = 1; I < Files.size(); ++I)
261 assert((Files[I - 1].first != Files[I].first) &&
262 "duplicate files in dx.source.contents");
264 llvm::for_each(Files, addFile);
267 Defines.reserve(
Macros.size());
271 Defines.emplace_back(llvm::MDString::get(Ctx,
Macro.first));
273 M.getOrInsertNamedMetadata(
"dx.source.defines")
274 ->addOperand(llvm::MDNode::get(Ctx, Defines));
276 if (!CodeGenOpts.MainFileName.empty())
277 llvm::sys::path::native(CodeGenOpts.MainFileName, *MainFileName);
278 M.getOrInsertNamedMetadata(
"dx.source.mainFileName")
280 llvm::MDNode::get(Ctx, llvm::MDString::get(Ctx, *MainFileName)));
283 Args.reserve(CodeGenOpts.HLSLParsedCommandLine.size());
284 if (!CodeGenOpts.HLSLParsedCommandLine.empty())
285 for (
const auto &Arg : llvm::drop_begin(CodeGenOpts.HLSLParsedCommandLine))
286 Args.push_back(llvm::MDString::get(Ctx, Arg));
287 M.getOrInsertNamedMetadata(
"dx.source.args")
288 ->addOperand(llvm::MDNode::get(Ctx, Args));
294 if (
const auto *DRE = dyn_cast_or_null<DeclRefExpr>(E))
295 return DRE->getDecl();
296 if (
auto *OVE = dyn_cast<OpaqueValueExpr>(E))
306 const Expr *E =
nullptr;
307 while (ASE !=
nullptr) {
311 ASE = dyn_cast<ArraySubscriptExpr>(E);
313 return getArrayDecl(AST, E);
319 assert(Ty->
isArrayType() &&
"expected array type");
325static Value *buildNameForResource(llvm::StringRef BaseName,
334 for (
auto *Method :
Record->methods()) {
335 if (Method->getStorageClass() == SC && Method->getName() == Name)
345 assert(Binding.
hasBinding() &&
"at least one binding attribute expected");
349 Value *NameStr = buildNameForResource(Name, CGM);
354 "resources with counter handle must have a binding with counter "
355 "implicit order ID");
358 auto *RegSlot = llvm::ConstantInt::get(CGM.
IntTy, Binding.
getSlot());
361 ?
"__createFromBindingWithImplicitCounter"
362 :
"__createFromBinding";
363 CreateMethod = lookupMethod(ResourceDecl, Name,
SC_Static);
370 ?
"__createFromImplicitBindingWithImplicitCounter"
371 :
"__createFromImplicitBinding";
372 CreateMethod = lookupMethod(ResourceDecl, Name,
SC_Static);
380 auto *CounterOrderID = llvm::ConstantInt::get(CGM.
IntTy, CounterBinding);
397 CGF.
EmitCall(FnInfo, Callee, ReturnValue, Args,
nullptr);
406static std::optional<llvm::Value *> initializeResourceArrayFromGlobal(
409 llvm::Value *Range, llvm::Value *StartIndex, StringRef ResourceName,
413 llvm::IntegerType *IntTy = CGF.
CGM.
IntTy;
414 llvm::Value *Index = StartIndex;
415 llvm::Value *One = llvm::ConstantInt::get(IntTy, 1);
423 GEPIndices.push_back(llvm::ConstantInt::get(IntTy, 0));
428 for (uint64_t I = 0; I < ArraySize; I++) {
430 Index = CGF.
Builder.CreateAdd(Index, One);
431 GEPIndices.back() = llvm::ConstantInt::get(IntTy, I);
433 std::optional<llvm::Value *> MaybeIndex =
434 initializeResourceArrayFromGlobal(CGF, ResourceDecl, SubArrayTy,
435 ValueSlot, Range, Index,
436 ResourceName, Binding, GEPIndices);
450 for (uint64_t I = 0; I < ArraySize; I++) {
452 Index = CGF.
Builder.CreateAdd(Index, One);
453 GEPIndices.back() = llvm::ConstantInt::get(IntTy, I);
459 CXXMethodDecl *CreateMethod = lookupResourceInitMethodAndSetupArgs(
460 CGF.
CGM, ResourceDecl, Range, Index, ResourceName, Binding, Args);
468 callResourceInitMethod(CGF, CreateMethod, Args, ReturnAddress);
475class HLSLBufferCopyEmitter {
476 CodeGenFunction &CGF;
479 llvm::Type *LayoutTy =
nullptr;
481 SmallVector<llvm::Value *> CurStoreIndices;
482 SmallVector<llvm::Value *> CurLoadIndices;
486 llvm::Value *emitAccessChain(llvm::Type *BaseTy, llvm::Value *Base,
487 ArrayRef<llvm::Value *> Indices) {
488 bool EmitLogical = CGF.getLangOpts().EmitLogicalPointer;
490 return CGF.Builder.CreateAccessChain(EmitLogical, BaseTy, Base, Indices);
492 llvm::SmallVector<llvm::Value *> GEPIndices;
493 GEPIndices.reserve(Indices.size() + 1);
494 GEPIndices.push_back(llvm::ConstantInt::get(CGF.IntTy, 0));
495 GEPIndices.append(Indices.begin(), Indices.end());
496 return CGF.Builder.CreateAccessChain(EmitLogical, BaseTy, Base, GEPIndices);
499 bool isBufferLayoutArray(llvm::StructType *ST) {
505 if (!ST || ST->getNumElements() != 2)
508 auto *PaddedEltsTy = dyn_cast<llvm::ArrayType>(ST->getElementType(0));
512 auto *PaddedTy = dyn_cast<llvm::StructType>(PaddedEltsTy->getElementType());
513 if (!PaddedTy || PaddedTy->getNumElements() != 2)
516 if (!CGF.CGM.getTargetCodeGenInfo().isHLSLPadding(
517 PaddedTy->getElementType(1)))
520 llvm::Type *ElementTy = ST->getElementType(1);
521 if (PaddedTy->getElementType(0) != ElementTy)
526 void emitBufferLayoutCopy(
Value *Src, llvm::StructType *SrcTy,
Value *Dst,
527 llvm::ArrayType *DstTy) {
530 assert(SrcPaddedArrayTy->getNumElements() + 1 == DstTy->getNumElements());
532 ->getElementType(0) == SrcTy->getElementType(1));
534 auto *SrcDataTy = SrcTy->getElementType(1);
535 auto Zero = llvm::ConstantInt::get(CGF.IntTy, 0);
537 for (
unsigned I = 0; I < SrcPaddedArrayTy->getNumElements(); ++I) {
538 auto Index = llvm::ConstantInt::get(CGF.IntTy, I);
539 auto *SrcElt = emitAccessChain(SrcTy, Src, {
Zero, Index,
Zero});
540 auto *DstElt = emitAccessChain(DstTy, Dst, {Index});
541 emitElementCopy(SrcElt, SrcDataTy, DstElt, DstTy->getElementType());
545 emitAccessChain(SrcTy, Src, {llvm::ConstantInt::get(CGF.IntTy, 1)});
546 auto *DstElt = emitAccessChain(
548 {llvm::ConstantInt::get(CGF.IntTy, DstTy->getNumElements() - 1)});
549 emitElementCopy(SrcElt, SrcDataTy, DstElt, DstTy->getElementType());
552 void emitCopy(
Value *Src, llvm::StructType *SrcTy,
Value *Dst,
554 if (isBufferLayoutArray(SrcTy))
555 return emitBufferLayoutCopy(Src, SrcTy, Dst,
558 unsigned SrcIndex = 0;
559 unsigned DstIndex = 0;
562 while (SrcIndex < SrcTy->getNumElements() &&
563 DstIndex < DstST->getNumElements()) {
564 if (CGF.CGM.getTargetCodeGenInfo().isHLSLPadding(
565 SrcTy->getElementType(SrcIndex))) {
570 if (CGF.CGM.getTargetCodeGenInfo().isHLSLPadding(
571 DstST->getElementType(DstIndex))) {
576 auto *SrcElt = emitAccessChain(
577 SrcTy, Src, {llvm::ConstantInt::get(CGF.IntTy, SrcIndex)});
578 auto *DstElt = emitAccessChain(
579 DstTy, Dst, {llvm::ConstantInt::get(CGF.IntTy, DstIndex)});
580 emitElementCopy(SrcElt, SrcTy->getElementType(SrcIndex), DstElt,
581 DstST->getElementType(DstIndex));
587 void emitCopy(
Value *Src, llvm::ArrayType *SrcTy,
Value *Dst,
589 for (
unsigned I = 0, E = SrcTy->getNumElements(); I < E; ++I) {
591 emitAccessChain(SrcTy, Src, {llvm::ConstantInt::get(CGF.IntTy, I)});
593 emitAccessChain(DstTy, Dst, {llvm::ConstantInt::get(CGF.IntTy, I)});
594 emitElementCopy(SrcElt, SrcTy->getElementType(), DstElt,
599 void emitElementCopy(
Value *Src, llvm::Type *SrcTy,
Value *Dst,
601 if (
auto *AT = dyn_cast<llvm::ArrayType>(SrcTy))
602 return emitCopy(Src, AT, Dst, DstTy);
603 if (
auto *ST = dyn_cast<llvm::StructType>(SrcTy))
604 return emitCopy(Src, ST, Dst, DstTy);
611 Address SrcAddr(Src, SrcTy, SrcAlign);
612 Address DstAddr(Dst, DstTy, DstAlign);
613 llvm::Value *
Load = CGF.Builder.CreateLoad(SrcAddr,
"cbuf.load");
614 CGF.Builder.CreateStore(Load, DstAddr);
618 HLSLBufferCopyEmitter(CodeGenFunction &CGF, Address DstPtr, Address SrcPtr)
619 : CGF(CGF), DstPtr(DstPtr), SrcPtr(SrcPtr) {}
621 bool emitCopy(QualType CType) {
622 LayoutTy = HLSLBufferLayoutBuilder(CGF.CGM).layOutType(CType);
629 emitElementCopy(SrcPtr.getBasePointer(), LayoutTy, DstPtr.getBasePointer(),
630 DstPtr.getElementType());
640 assert(T->isHLSLSpecificType() &&
"Not an HLSL specific type!");
643 if (llvm::Type *TargetTy =
647 llvm_unreachable(
"Generic handling of HLSL types is not supported.");
650llvm::Triple::ArchType CGHLSLRuntime::getArch() {
656void CGHLSLRuntime::emitBufferGlobalsAndMetadata(
662 llvm::Type *BufType = BufGV->getValueType();
667 size_t OffsetIdx = 0;
677 VarDecl *VD = dyn_cast<VarDecl>(D);
693 DeclsWithOffset.emplace_back(VD, OffsetInfo[OffsetIdx++]);
696 if (!OffsetInfo.
empty())
697 llvm::stable_sort(DeclsWithOffset, [](
const auto &LHS,
const auto &RHS) {
702 SmallVector<llvm::Metadata *> BufGlobals;
703 BufGlobals.reserve(DeclsWithOffset.size() + 1);
704 BufGlobals.push_back(ValueAsMetadata::get(BufGV));
706 auto ElemIt = LayoutStruct->element_begin();
707 for (
auto &[VD, _] : DeclsWithOffset) {
711 assert(ElemIt != LayoutStruct->element_end() &&
712 "number of elements in layout struct does not match");
713 llvm::Type *LayoutType = *ElemIt++;
715 GlobalVariable *ElemGV =
717 BufGlobals.push_back(ValueAsMetadata::get(ElemGV));
719 assert(ElemIt == LayoutStruct->element_end() &&
720 "number of elements in layout struct does not match");
724 .getOrInsertNamedMetadata(
"hlsl.cbs")
725 ->addOperand(MDNode::get(Ctx, BufGlobals));
729static const clang::HLSLAttributedResourceType *
734 HLSLAttributedResourceType::Attributes(ResourceClass::CBuffer));
749 VarDecl *VD = dyn_cast<VarDecl>(D);
760 if (
auto *POA = dyn_cast<HLSLPackOffsetAttr>(
Attr)) {
761 Offset = POA->getOffsetInBytes();
764 auto *RBA = dyn_cast<HLSLResourceBindingAttr>(
Attr);
766 RBA->getRegisterType() == HLSLResourceBindingAttr::RegisterType::C) {
767 Offset = RBA->getSlotNumber() * CBufferRowSizeInBytes;
771 Result.Offsets.push_back(Offset);
779 assert(BufDecl->
isCBuffer() &&
"tbuffer codegen is not supported yet");
782 const clang::HLSLAttributedResourceType *ResHandleTy =
786 if (ResHandleTy->getContainedType()->getAsCXXRecordDecl()->isEmpty())
792 llvm::GlobalVariable *BufGV =
new GlobalVariable(
794 GlobalValue::LinkageTypes::InternalLinkage, PoisonValue::get(LayoutTy),
795 llvm::formatv(
"{0}{1}", BufDecl->
getName(),
797 GlobalValue::NotThreadLocal);
800 M.insertGlobalVariable(BufGV);
805 llvm::appendToCompilerUsed(M, {BufGV});
808 emitBufferGlobalsAndMetadata(BufDecl, BufGV, OffsetInfo);
811 initializeBufferFromBinding(BufDecl, BufGV);
817 Triple T(M.getTargetTriple());
820 if (T.getEnvironment() != Triple::EnvironmentType::RootSignature)
823 addRootSignatureMD(SignatureDecl->
getVersion(),
829 const auto Entry = LayoutTypes.find(StructType);
830 if (Entry != LayoutTypes.end())
831 return Entry->getSecond();
836 llvm::StructType *LayoutTy) {
838 "layout type for this struct already exist");
839 LayoutTypes[StructType] = LayoutTy;
847 Triple T(M.getTargetTriple());
848 if (T.getArch() == Triple::ArchType::dxil)
849 addDxilValVersion(TargetOpts.DxilValidatorVersion, M);
850 if (!CodeGenOpts.DisableDXSourceMetadata &&
851 CodeGenOpts.getDebugInfo() >=
852 llvm::codegenoptions::DebugInfoKind::DebugInfoConstructor)
853 addSourceInfo(CGM, M);
854 if (CodeGenOpts.ResMayAlias)
855 M.setModuleFlag(llvm::Module::ModFlagBehavior::Error,
"dx.resmayalias", 1);
856 if (CodeGenOpts.AllResourcesBound)
857 M.setModuleFlag(llvm::Module::ModFlagBehavior::Error,
858 "dx.allresourcesbound", 1);
859 if (CodeGenOpts.OptimizationLevel == 0)
860 M.addModuleFlag(llvm::Module::ModFlagBehavior::Override,
861 "dx.disable_optimizations", 1);
866 if (LangOpts.NativeHalfType)
867 M.setModuleFlag(llvm::Module::ModFlagBehavior::Error,
"dx.nativelowprec",
870 if (LangOpts.HLSLSpvPreserveInterface && T.isSPIRV()) {
876 for (GlobalVariable &GV : M.globals()) {
877 unsigned AS = GV.getAddressSpace();
878 if (AS == InputAS || AS == OutputAS)
879 InterfaceVars.push_back(&GV);
881 if (!InterfaceVars.empty())
882 appendToCompilerUsed(M, InterfaceVars);
890 const auto *ShaderAttr = FD->
getAttr<HLSLShaderAttr>();
891 assert(ShaderAttr &&
"All entry functions must have a HLSLShaderAttr");
892 const StringRef ShaderAttrKindStr =
"hlsl.shader";
893 Fn->addFnAttr(ShaderAttrKindStr,
894 llvm::Triple::getEnvironmentTypeName(ShaderAttr->getType()));
895 if (HLSLNumThreadsAttr *NumThreadsAttr = FD->
getAttr<HLSLNumThreadsAttr>()) {
896 const StringRef NumThreadsKindStr =
"hlsl.numthreads";
897 std::string NumThreadsStr =
898 formatv(
"{0},{1},{2}", NumThreadsAttr->getX(), NumThreadsAttr->getY(),
899 NumThreadsAttr->getZ());
900 Fn->addFnAttr(NumThreadsKindStr, NumThreadsStr);
902 if (HLSLWaveSizeAttr *WaveSizeAttr = FD->
getAttr<HLSLWaveSizeAttr>()) {
903 const StringRef WaveSizeKindStr =
"hlsl.wavesize";
904 std::string WaveSizeStr =
905 formatv(
"{0},{1},{2}", WaveSizeAttr->getMin(), WaveSizeAttr->getMax(),
906 WaveSizeAttr->getPreferred());
907 Fn->addFnAttr(WaveSizeKindStr, WaveSizeStr);
914 Fn->addFnAttr(llvm::Attribute::NoInline);
916 if (CGM.
getLangOpts().HLSLSpvEnableMaximalReconvergence) {
917 Fn->addFnAttr(
"enable-maximal-reconvergence",
"true");
922 if (
const auto *VT = dyn_cast<FixedVectorType>(Ty)) {
924 for (
unsigned I = 0; I < VT->getNumElements(); ++I) {
925 Value *Elt = B.CreateCall(F, {B.getInt32(I)});
930 return B.CreateCall(F, {B.getInt32(0)});
935 LLVMContext &Ctx = GV->getContext();
936 IRBuilder<> B(GV->getContext());
937 MDNode *Operands = MDNode::get(
939 {ConstantAsMetadata::get(B.getInt32( 11)),
940 ConstantAsMetadata::get(B.getInt32(BuiltIn))});
941 MDNode *Decoration = MDNode::get(Ctx, {Operands});
942 GV->addMetadata(
"spirv.Decorations", *Decoration);
946 LLVMContext &Ctx = GV->getContext();
947 IRBuilder<> B(GV->getContext());
949 MDNode::get(Ctx, {ConstantAsMetadata::get(B.getInt32( 30)),
950 ConstantAsMetadata::get(B.getInt32(Location))});
951 MDNode *Decoration = MDNode::get(Ctx, {Operands});
952 GV->addMetadata(
"spirv.Decorations", *Decoration);
956 llvm::Type *Ty,
const Twine &Name,
957 unsigned BuiltInID) {
958 auto *GV =
new llvm::GlobalVariable(
959 M, Ty,
true, llvm::GlobalValue::ExternalLinkage,
960 nullptr, Name,
nullptr,
961 llvm::GlobalVariable::GeneralDynamicTLSModel,
964 GV->setVisibility(llvm::GlobalValue::HiddenVisibility);
965 return B.CreateLoad(Ty, GV);
969 llvm::Type *Ty,
unsigned Location,
971 auto *GV =
new llvm::GlobalVariable(
972 M, Ty,
true, llvm::GlobalValue::ExternalLinkage,
973 nullptr, Name,
nullptr,
974 llvm::GlobalVariable::GeneralDynamicTLSModel,
976 GV->setVisibility(llvm::GlobalValue::HiddenVisibility);
978 return B.CreateLoad(Ty, GV);
981llvm::Value *CGHLSLRuntime::emitSPIRVUserSemanticLoad(
982 llvm::IRBuilder<> &B, llvm::Type *
Type,
const clang::DeclaratorDecl *
Decl,
983 HLSLAppliedSemanticAttr *Semantic, std::optional<unsigned> Index) {
984 Twine BaseName = Twine(Semantic->getAttrName()->getName());
985 Twine VariableName = BaseName.concat(Twine(Index.value_or(0)));
987 unsigned Location = SPIRVLastAssignedInputSemanticLocation;
988 if (
auto *L =
Decl->getAttr<HLSLVkLocationAttr>())
989 Location = L->getLocation();
993 llvm::ArrayType *AT = dyn_cast<llvm::ArrayType>(
Type);
994 unsigned ElementCount = AT ? AT->getNumElements() : 1;
995 SPIRVLastAssignedInputSemanticLocation += ElementCount;
1002 llvm::Value *Source,
unsigned Location,
1004 auto *GV =
new llvm::GlobalVariable(
1005 M, Source->getType(),
false,
1006 llvm::GlobalValue::ExternalLinkage,
1007 nullptr, Name,
nullptr,
1008 llvm::GlobalVariable::GeneralDynamicTLSModel,
1010 GV->setVisibility(llvm::GlobalValue::HiddenVisibility);
1012 B.CreateStore(Source, GV);
1015void CGHLSLRuntime::emitSPIRVUserSemanticStore(
1016 llvm::IRBuilder<> &B, llvm::Value *Source,
1017 const clang::DeclaratorDecl *
Decl, HLSLAppliedSemanticAttr *Semantic,
1018 std::optional<unsigned> Index) {
1019 Twine BaseName = Twine(Semantic->getAttrName()->getName());
1020 Twine VariableName = BaseName.concat(Twine(Index.value_or(0)));
1022 unsigned Location = SPIRVLastAssignedOutputSemanticLocation;
1023 if (
auto *L =
Decl->getAttr<HLSLVkLocationAttr>())
1024 Location = L->getLocation();
1028 llvm::ArrayType *AT = dyn_cast<llvm::ArrayType>(Source->getType());
1029 unsigned ElementCount = AT ? AT->getNumElements() : 1;
1030 SPIRVLastAssignedOutputSemanticLocation += ElementCount;
1032 VariableName.str());
1036CGHLSLRuntime::emitDXILUserSemanticLoad(llvm::IRBuilder<> &B, llvm::Type *
Type,
1037 HLSLAppliedSemanticAttr *Semantic,
1038 std::optional<unsigned> Index) {
1039 Twine BaseName = Twine(Semantic->getAttrName()->getName());
1040 Twine VariableName = BaseName.concat(Twine(Index.value_or(0)));
1045 SmallVector<Value *> Args{B.getInt32(4), B.getInt32(0), B.getInt32(0),
1047 llvm::PoisonValue::get(B.getInt32Ty())};
1049 llvm::Intrinsic::ID IntrinsicID = llvm::Intrinsic::dx_load_input;
1051 SmallVector<OperandBundleDef, 1> OB;
1053 llvm::Value *bundleArgs[] = {Token};
1054 OB.emplace_back(
"convergencectrl", bundleArgs);
1057 llvm::Function *IntrFn = llvm::Intrinsic::getOrInsertDeclaration(
1058 B.GetInsertBlock()->getModule(), IntrinsicID, {Type});
1059 llvm::Value *
Value = B.CreateCall(IntrFn, Args, OB, VariableName);
1063void CGHLSLRuntime::emitDXILUserSemanticStore(llvm::IRBuilder<> &B,
1064 llvm::Value *Source,
1065 HLSLAppliedSemanticAttr *Semantic,
1066 std::optional<unsigned> Index) {
1069 SmallVector<Value *> Args{B.getInt32(4),
1073 llvm::PoisonValue::get(B.getInt32Ty()),
1076 llvm::Intrinsic::ID IntrinsicID = llvm::Intrinsic::dx_store_output;
1078 SmallVector<OperandBundleDef, 1> OB;
1080 llvm::Value *bundleArgs[] = {Token};
1081 OB.emplace_back(
"convergencectrl", bundleArgs);
1084 llvm::Function *IntrFn = llvm::Intrinsic::getOrInsertDeclaration(
1085 B.GetInsertBlock()->getModule(), IntrinsicID, {Source->getType()});
1086 B.CreateCall(IntrFn, Args, OB);
1089llvm::Value *CGHLSLRuntime::emitUserSemanticLoad(
1090 IRBuilder<> &B, llvm::Type *
Type,
const clang::DeclaratorDecl *
Decl,
1091 HLSLAppliedSemanticAttr *Semantic, std::optional<unsigned> Index) {
1093 return emitSPIRVUserSemanticLoad(B,
Type,
Decl, Semantic, Index);
1096 return emitDXILUserSemanticLoad(B,
Type, Semantic, Index);
1098 llvm_unreachable(
"Unsupported target for user-semantic load.");
1101void CGHLSLRuntime::emitUserSemanticStore(IRBuilder<> &B, llvm::Value *Source,
1102 const clang::DeclaratorDecl *
Decl,
1103 HLSLAppliedSemanticAttr *Semantic,
1104 std::optional<unsigned> Index) {
1106 return emitSPIRVUserSemanticStore(B, Source,
Decl, Semantic, Index);
1109 return emitDXILUserSemanticStore(B, Source, Semantic, Index);
1111 llvm_unreachable(
"Unsupported target for user-semantic load.");
1117 std::optional<unsigned> Index) {
1119 std::string SemanticName = Semantic->getAttrName()->getName().upper();
1120 if (SemanticName ==
"SV_GROUPINDEX") {
1121 llvm::Function *GroupIndex =
1122 CGM.
getIntrinsic(getFlattenedThreadIdInGroupIntrinsic());
1123 return B.CreateCall(FunctionCallee(GroupIndex));
1126 if (SemanticName ==
"SV_DISPATCHTHREADID") {
1127 llvm::Intrinsic::ID IntrinID = getThreadIdIntrinsic();
1128 llvm::Function *ThreadIDIntrinsic =
1129 llvm::Intrinsic::isOverloaded(IntrinID)
1135 if (SemanticName ==
"SV_GROUPTHREADID") {
1136 llvm::Intrinsic::ID IntrinID = getGroupThreadIdIntrinsic();
1137 llvm::Function *GroupThreadIDIntrinsic =
1138 llvm::Intrinsic::isOverloaded(IntrinID)
1144 if (SemanticName ==
"SV_GROUPID") {
1145 llvm::Intrinsic::ID IntrinID = getGroupIdIntrinsic();
1146 llvm::Function *GroupIDIntrinsic =
1147 llvm::Intrinsic::isOverloaded(IntrinID)
1153 const auto *ShaderAttr = FD->
getAttr<HLSLShaderAttr>();
1154 assert(ShaderAttr &&
"Entry point has no shader attribute");
1155 llvm::Triple::EnvironmentType ST = ShaderAttr->getType();
1157 if (SemanticName ==
"SV_POSITION") {
1158 if (ST == Triple::EnvironmentType::Pixel) {
1161 Semantic->getAttrName()->getName(),
1164 return emitDXILUserSemanticLoad(B,
Type, Semantic, Index);
1167 if (ST == Triple::EnvironmentType::Vertex) {
1168 return emitUserSemanticLoad(B,
Type,
Decl, Semantic, Index);
1172 if (SemanticName ==
"SV_VERTEXID") {
1173 if (ST == Triple::EnvironmentType::Vertex) {
1176 Semantic->getAttrName()->getName(),
1179 return emitDXILUserSemanticLoad(B,
Type, Semantic, Index);
1184 "Load hasn't been implemented yet for this system semantic. FIXME");
1188 llvm::Value *Source,
const Twine &Name,
1189 unsigned BuiltInID) {
1190 auto *GV =
new llvm::GlobalVariable(
1191 M, Source->getType(),
false,
1192 llvm::GlobalValue::ExternalLinkage,
1193 nullptr, Name,
nullptr,
1194 llvm::GlobalVariable::GeneralDynamicTLSModel,
1197 GV->setVisibility(llvm::GlobalValue::HiddenVisibility);
1198 B.CreateStore(Source, GV);
1203 HLSLAppliedSemanticAttr *Semantic,
1204 std::optional<unsigned> Index) {
1206 std::string SemanticName = Semantic->getAttrName()->getName().upper();
1207 if (SemanticName ==
"SV_POSITION") {
1209 emitDXILUserSemanticStore(B, Source, Semantic, Index);
1215 Semantic->getAttrName()->getName(),
1221 if (SemanticName ==
"SV_TARGET") {
1222 emitUserSemanticStore(B, Source,
Decl, Semantic, Index);
1227 "Store hasn't been implemented yet for this system semantic. FIXME");
1234 std::optional<unsigned> Index = Semantic->getSemanticIndex();
1235 if (Semantic->getAttrName()->getName().starts_with_insensitive(
"SV_"))
1237 return emitUserSemanticLoad(B,
Type,
Decl, Semantic, Index);
1241 IRBuilder<> &B,
const FunctionDecl *FD, llvm::Value *Source,
1243 std::optional<unsigned> Index = Semantic->getSemanticIndex();
1244 if (Semantic->getAttrName()->getName().starts_with_insensitive(
"SV_"))
1247 emitUserSemanticStore(B, Source,
Decl, Semantic, Index);
1250std::pair<llvm::Value *, specific_attr_iterator<HLSLAppliedSemanticAttr>>
1263 for (
unsigned I = 0; I < ST->getNumElements(); ++I) {
1265 B, FD, ST->getElementType(I), *
FieldDecl, AttrBegin, AttrEnd);
1266 AttrBegin = NextAttr;
1272 return std::make_pair(
Aggregate, AttrBegin);
1277 IRBuilder<> &B,
const FunctionDecl *FD, llvm::Value *Source,
1288 RD =
Decl->getType()->getAsRecordDecl();
1294 for (
unsigned I = 0; I < ST->getNumElements(); ++I, ++
FieldDecl) {
1295 llvm::Value *Extract = B.CreateExtractValue(Source, I);
1303std::pair<llvm::Value *, specific_attr_iterator<HLSLAppliedSemanticAttr>>
1309 assert(AttrBegin != AttrEnd);
1310 if (
Type->isStructTy())
1313 HLSLAppliedSemanticAttr *
Attr = *AttrBegin;
1321 IRBuilder<> &B,
const FunctionDecl *FD, llvm::Value *Source,
1325 assert(AttrBegin != AttrEnd);
1326 if (Source->getType()->isStructTy())
1329 HLSLAppliedSemanticAttr *
Attr = *AttrBegin;
1336 llvm::Function *Fn) {
1338 llvm::LLVMContext &Ctx = M.getContext();
1339 auto *EntryTy = llvm::FunctionType::get(llvm::Type::getVoidTy(Ctx),
false);
1341 Function::Create(EntryTy, Function::ExternalLinkage, FD->
getName(), &M);
1345 AttributeList NewAttrs = AttributeList::get(Ctx, AttributeList::FunctionIndex,
1346 Fn->getAttributes().getFnAttrs());
1347 EntryFn->setAttributes(NewAttrs);
1351 Fn->setLinkage(GlobalValue::InternalLinkage);
1353 BasicBlock *BB = BasicBlock::Create(Ctx,
"entry", EntryFn);
1359 assert(EntryFn->isConvergent());
1361 B.CreateIntrinsic(llvm::Intrinsic::experimental_convergence_entry, {});
1362 llvm::Value *bundleArgs[] = {I};
1363 OB.emplace_back(
"convergencectrl", bundleArgs);
1368 unsigned SRetOffset = 0;
1369 for (
const auto &Param : Fn->args()) {
1370 if (Param.hasStructRetAttr()) {
1372 llvm::Type *VarType = Param.getParamStructRetType();
1377 OutputSemantic.push_back(std::make_pair(Var, VarType));
1378 Args.push_back(Var);
1383 llvm::Value *SemanticValue =
nullptr;
1385 if ([[maybe_unused]] HLSLParamModifierAttr *MA =
1386 PD->
getAttr<HLSLParamModifierAttr>()) {
1387 llvm_unreachable(
"Not handled yet");
1389 llvm::Type *ParamType =
nullptr;
1390 if (Param.hasByValAttr())
1391 ParamType = Param.getParamByValType();
1395 ParamType = Param.getType();
1401 SemanticValue =
Result.first;
1409 B.CreateStore(SemanticValue, Var);
1410 SemanticValue = Var;
1414 assert(SemanticValue);
1415 Args.push_back(SemanticValue);
1418 CallInst *CI = B.CreateCall(FunctionCallee(Fn), Args, OB);
1419 CI->setCallingConv(Fn->getCallingConv());
1421 if (Fn->getReturnType() != CGM.
VoidTy)
1423 OutputSemantic.push_back(std::make_pair(CI,
nullptr));
1425 for (
auto &SourcePair : OutputSemantic) {
1426 llvm::Value *Source = SourcePair.first;
1427 llvm::Type *ElementType = SourcePair.second;
1428 AllocaInst *AI = dyn_cast<AllocaInst>(Source);
1429 llvm::Value *SourceValue = AI ? B.CreateLoad(ElementType, Source) : Source;
1440 if (
const auto *RSAttr = dyn_cast<RootSignatureAttr>(
Attr)) {
1441 auto *RSDecl = RSAttr->getSignatureDecl();
1442 addRootSignatureMD(RSDecl->getVersion(), RSDecl->getRootElements(),
1451 M.getNamedGlobal(CtorOrDtor ?
"llvm.global_ctors" :
"llvm.global_dtors");
1454 const auto *CA = dyn_cast<ConstantArray>(GV->getInitializer());
1461 for (
const auto &Ctor : CA->operands()) {
1467 "HLSL doesn't support setting priority for global ctors.");
1469 "HLSL doesn't support COMDat for global ctors.");
1484 for (
auto &F : M.functions()) {
1485 if (!F.hasFnAttribute(
"hlsl.shader"))
1488 Instruction *IP = &*F.getEntryBlock().begin();
1491 llvm::Value *bundleArgs[] = {
Token};
1492 OB.emplace_back(
"convergencectrl", bundleArgs);
1493 IP =
Token->getNextNode();
1496 for (
auto *Fn : CtorFns) {
1497 auto CI = B.CreateCall(FunctionCallee(Fn), {}, OB);
1498 CI->setCallingConv(Fn->getCallingConv());
1502 B.SetInsertPoint(F.back().getTerminator());
1503 for (
auto *Fn : DtorFns) {
1504 auto CI = B.CreateCall(FunctionCallee(Fn), {}, OB);
1505 CI->setCallingConv(Fn->getCallingConv());
1511 Triple T(M.getTargetTriple());
1512 if (T.getEnvironment() != Triple::EnvironmentType::Library) {
1513 if (
auto *GV = M.getNamedGlobal(
"llvm.global_ctors"))
1514 GV->eraseFromParent();
1515 if (
auto *GV = M.getNamedGlobal(
"llvm.global_dtors"))
1516 GV->eraseFromParent();
1521 Intrinsic::ID IntrID,
1525 llvm::Function *InitResFunc =
1526 llvm::Function::Create(llvm::FunctionType::get(CGM.
VoidTy,
false),
1527 llvm::GlobalValue::InternalLinkage,
1528 "_init_buffer_" + GV->getName(), CGM.
getModule());
1529 InitResFunc->addFnAttr(llvm::Attribute::AlwaysInline);
1531 llvm::BasicBlock *EntryBB =
1532 llvm::BasicBlock::Create(Ctx,
"entry", InitResFunc);
1534 const DataLayout &DL = CGM.
getModule().getDataLayout();
1535 Builder.SetInsertPoint(EntryBB);
1538 llvm::Type *HandleTy = GV->getValueType();
1539 assert(HandleTy->isTargetExtTy() &&
"unexpected type of the buffer global");
1541 llvm::Value *CreateHandle = Builder.CreateIntrinsic(
1542 HandleTy, IntrID, Args,
nullptr,
1543 Twine(GV->getName()).concat(
"_h"));
1545 Builder.CreateAlignedStore(CreateHandle, GV, GV->getPointerAlignment(DL));
1546 Builder.CreateRetVoid();
1551void CGHLSLRuntime::initializeBufferFromBinding(
const HLSLBufferDecl *BufDecl,
1552 llvm::GlobalVariable *GV) {
1553 ResourceBindingAttrs Binding(BufDecl);
1555 "cbuffer/tbuffer should always have resource binding attribute");
1557 auto *Index = llvm::ConstantInt::get(CGM.
IntTy, 0);
1558 auto *RangeSize = llvm::ConstantInt::get(CGM.
IntTy, 1);
1559 auto *Space = llvm::ConstantInt::get(CGM.
IntTy, Binding.
getSpace());
1560 Value *Name = buildNameForResource(BufDecl->
getName(), CGM);
1564 llvm::Intrinsic::ID IntrinsicID =
1566 auto *RegSlot = llvm::ConstantInt::get(CGM.
IntTy, Binding.
getSlot());
1567 SmallVector<Value *> Args{Space, RegSlot, RangeSize, Index, Name};
1571 llvm::Intrinsic::ID IntrinsicID =
1572 CGM.
getHLSLRuntime().getCreateHandleFromImplicitBindingIntrinsic();
1575 SmallVector<Value *> Args{OrderID, Space, RangeSize, Index, Name};
1581 llvm::GlobalVariable *GV) {
1582 if (
auto Attr = VD->
getAttr<HLSLVkExtBuiltinInputAttr>())
1584 if (
auto Attr = VD->
getAttr<HLSLVkExtBuiltinOutputAttr>())
1593 for (
auto I = BB.begin(); I != E; ++I) {
1594 auto *II = dyn_cast<llvm::IntrinsicInst>(&*I);
1595 if (II && llvm::isConvergenceControlIntrinsic(II->getIntrinsicID())) {
1599 llvm_unreachable(
"Convergence token should have been emitted.");
1636 for (
auto *OVE : Visitor.
OVEs) {
1639 if (OpaqueValueMappingData::shouldBindAsLValue(OVE)) {
1641 OpaqueValueMappingData::bind(CGF, OVE, LV);
1644 OpaqueValueMappingData::bind(CGF, OVE, RV);
1653 "expected resource array subscript expression");
1658 const VarDecl *ArrayDecl = dyn_cast_or_null<VarDecl>(
1662 return std::nullopt;
1668 "expected array of resource classes");
1674 Value *Index =
nullptr;
1676 while (ASE !=
nullptr) {
1678 if (
const auto *ArrayTy =
1680 Value *Multiplier = llvm::ConstantInt::get(
1682 SubIndex = CGF.
Builder.CreateMul(SubIndex, Multiplier);
1684 Index = Index ? CGF.
Builder.CreateAdd(Index, SubIndex) : SubIndex;
1692 "resource array must have a binding attribute");
1713 llvm::Value *Range = llvm::ConstantInt::getSigned(
1714 CGM.
IntTy, getTotalArraySize(AST, ResArrayTy));
1718 if (ResultTy == ResourceTy) {
1720 CXXMethodDecl *CreateMethod = lookupResourceInitMethodAndSetupArgs(
1722 ArrayDecl->
getName(), Binding, Args);
1724 if (!CreateMethod) {
1729 "create method lookup should always succeed for built-in resource "
1731 return std::nullopt;
1734 callResourceInitMethod(CGF, CreateMethod, Args, ValueSlot.getAddress());
1741 std::optional<llvm::Value *> EndIndex = initializeResourceArrayFromGlobal(
1743 ArrayDecl->
getName(), Binding, {llvm::ConstantInt::get(CGM.IntTy, 0)});
1745 return std::nullopt;
1751bool CGHLSLRuntime::initializeGlobalResourceArray(
CodeGenFunction &CGF,
1757 "expected global non-static resource array");
1763 "resource array must have a binding attribute");
1768 const auto *ResArrayTy =
1772 int Size = getTotalArraySize(AST, ResArrayTy);
1773 llvm::Value *
Zero = llvm::ConstantInt::get(CGM.
IntTy, 0);
1774 llvm::Value *Range = llvm::ConstantInt::get(CGM.
IntTy, Size);
1777 std::optional<llvm::Value *> EndIndex = initializeResourceArrayFromGlobal(
1779 ArrayDecl->
getName(), Binding, {Zero});
1780 return EndIndex.has_value();
1789 "expected resource array");
1794 dyn_cast_or_null<VarDecl>(getArrayDecl(CGF.
CGM.
getContext(), E));
1799 return initializeGlobalResourceArray(CGF, ArrayDecl, DestSlot);
1806std::optional<LValue>
1810 "expected resource array declaration");
1814 return std::nullopt;
1818 if (initializeGlobalResourceArray(CGF, ArrayDecl, TmpArraySlot))
1821 return std::nullopt;
1829 "expected cbuffer matrix");
1840 HLSLBufferCopyEmitter(CGF, DestAlloca, SrcAddr).emitCopy(MatQualTy);
1846 llvm::function_ref<llvm::Value *(
bool Promote)> EmitIdxAfterBase) {
1850 llvm::Type *LayoutTy =
1852 uint64_t LayoutSizeInBits =
1853 CGM.
getDataLayout().getTypeSizeInBits(LayoutTy).getFixedValue();
1856 if (RowAlignedSize > ElementSize) {
1858 CGM, RowAlignedSize - ElementSize);
1859 assert(Padding &&
"No padding type for target?");
1860 LayoutTy = llvm::StructType::get(CGF.
getLLVMContext(), {LayoutTy, Padding},
1867 if (LayoutTy == OrigTy)
1868 return std::nullopt;
1877 llvm::Value *Idx = EmitIdxAfterBase(
true);
1878 Indices.push_back(Idx);
1879 Indices.push_back(llvm::ConstantInt::get(CGF.
Int32Ty, 0));
1885 assert(CE->
getCastKind() == CastKind::CK_ArrayToPointerDecay);
1889 LayoutTy = llvm::ArrayType::get(
1893 LayoutTy,
Addr.emitRawPointer(CGF), Indices,
"cbufferidx"));
1902 Indices,
"cbufferidx");
1907std::optional<LValue>
1912 "expected resource member expression");
1915 findAssociatedResourceDeclForStruct(CGF.
CGM.
getContext(), ME);
1917 return std::nullopt;
1923 GlobalVariable *ResGV =
1926 llvm::Type *Ty = ResGV->getValueType();
1937 return HLSLBufferCopyEmitter(CGF, DstPtr, SrcPtr).emitCopy(CType);
1945 assert(Field &&
"Unexpected access into HLSL buffer");
1962 assert(FieldIdx < LayoutTy->getNumElements() &&
1963 "Layout struct is smaller than member struct");
1964 unsigned Skipped = 0;
1965 for (
unsigned I = 0; I <= FieldIdx;) {
1966 llvm::Type *ElementTy = LayoutTy->getElementType(I + Skipped);
1972 FieldIdx += Skipped;
1973 assert(FieldIdx < LayoutTy->getNumElements() &&
"Access out of bounds");
1977 QualType FieldType = Field->getType();
1983 ? CGF.
Builder.CreateStructuredGEP(
1984 LayoutTy,
Base.getPointer(CGF),
1985 llvm::ConstantInt::get(CGM.
IntTy, FieldIdx))
1987 FieldIdx, Field->getName());
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 SourceManager interface.
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 ...
SourceManager & getSourceManager()
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
unsigned getTargetAddressSpace(LangAS AS) const
ArraySubscriptExpr - [C99 6.5.2.1] Array Subscripting.
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 ...
CharUnits getAlignment() const
Address getAddress() const
static AggValueSlot forAddr(Address addr, Qualifiers quals, IsDestructed_t isDestructed, NeedsGCBarriers_t needsGC, IsAliased_t isAliased, Overlap_t mayOverlap, IsZeroed_t isZeroed=IsNotZeroed, IsSanitizerChecked_t isChecked=IsNotSanitizerChecked)
forAddr - Make a slot for an aggregate value.
Address CreateGEP(CodeGenFunction &CGF, Address Addr, llvm::Value *Index, const llvm::Twine &Name="")
Address CreateStructGEP(Address Addr, unsigned Index, const llvm::Twine &Name="")
Abstract information about a function or function prototype.
All available information about a concrete callee.
CGFunctionInfo - Class to encapsulate the information about a function definition.
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)
std::optional< LValue > emitGlobalResourceArrayAsLValue(CodeGenFunction &CGF, const VarDecl *ArrayDecl)
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)
RawAddress createBufferMatrixTempAddress(const LValue &LV, CodeGenFunction &CGF)
quad_read_across_diagonal resource_getpointer resource_handlefrombinding resource_nonuniformindex device_memory_barrier_with_group_sync resource_getdimensions_levels_xy GENERATE_HLSL_INTRINSIC_FUNCTION(CalculateLodUnclamped, resource_calculate_lod_unclamped) protected llvm::Value * emitSystemSemanticLoad(llvm::IRBuilder<> &B, const FunctionDecl *FD, llvm::Type *Type, const clang::DeclaratorDecl *Decl, HLSLAppliedSemanticAttr *Semantic, std::optional< unsigned > Index)
void addBuffer(const HLSLBufferDecl *D)
void generateGlobalCtorDtorCalls()
bool emitGlobalResourceArray(CodeGenFunction &CGF, const Expr *E, AggValueSlot &DestSlot)
void emitInitListOpaqueValues(CodeGenFunction &CGF, InitListExpr *E)
unsigned getLLVMFieldNo(const FieldDecl *FD) const
Return llvm::StructType element number that corresponds to the field FD.
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.
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,...
RawAddress CreateMemTempWithoutCast(QualType T, const Twine &Name="tmp")
CreateMemTemp - Create a temporary memory object of the given type, with appropriate alignmen without...
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.
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.
const PreprocessorOptions & getPreprocessorOpts() const
CGHLSLRuntime & getHLSLRuntime()
Return a reference to the configured HLSL runtime.
llvm::Module & getModule() const
llvm::Constant * GetAddrOfFunction(GlobalDecl GD, llvm::Type *Ty=nullptr, bool ForVTable=false, bool DontDefer=false, ForDefinition_t IsForDefinition=NotForDefinition)
Return the address of the given function.
void AddCXXGlobalInit(llvm::Function *F)
const LangOptions & getLangOpts() const
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
bool shouldEmitConvergenceTokens() const
TBAAAccessInfo getTBAAAccessInfo(QualType AccessType)
getTBAAAccessInfo - Get TBAA information that describes an access to an object of the given type.
ASTContext & getContext() const
llvm::Constant * GetAddrOfGlobalVar(const VarDecl *D, llvm::Type *Ty=nullptr, ForDefinition_t IsForDefinition=NotForDefinition)
Return the llvm::Constant for the address of the given global variable.
const TargetCodeGenInfo & getTargetCodeGenInfo()
const CodeGenOptions & getCodeGenOpts() const
llvm::LLVMContext & getLLVMContext()
llvm::Function * getIntrinsic(unsigned IID, ArrayRef< llvm::Type * > Tys={})
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 * ConvertType(QualType T)
ConvertType - Convert type T into a llvm::Type.
const CGRecordLayout & getCGRecordLayout(const RecordDecl *)
getCGRecordLayout - Return record layout info for the given record decl.
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.
virtual llvm::Type * getHLSLPadding(CodeGenModule &CGM, CharUnits NumBytes) const
Return an LLVM type that corresponds to padding in HLSL types.
virtual llvm::Type * getHLSLType(CodeGenModule &CGM, const Type *T, const CGHLSLOffsetInfo &OffsetInfo) const
Return an LLVM type that corresponds to a HLSL 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.
Represents a member of a struct/union/class.
StringRef getName() const
The name of this FileEntry.
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.
std::vector< std::pair< std::string, bool > > Macros
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.
One instance of this struct is kept for every file loaded or used.
std::optional< llvm::MemoryBufferRef > getBufferOrNone(DiagnosticsEngine &Diag, FileManager &FM, SourceLocation Loc=SourceLocation()) const
Returns the memory buffer for the associated content.
OptionalFileEntryRef OrigEntry
Reference to the file entry representing this ContentCache.
Information about a FileID, basically just the logical file that it represents and include stack info...
const ContentCache & getContentCache() const
CharacteristicKind getFileCharacteristic() const
Return whether this is a system header or not.
This is a discriminated union of FileInfo and ExpansionInfo.
const FileInfo & getFile() const
TargetOptions & getTargetOpts() const
Retrieve the target options.
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 isRecordType() const
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 isSystem(CharacteristicKind CK)
Determine whether a file / directory characteristic is for system code.
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)
CustomizableOptional< FileEntryRef > OptionalFileEntryRef
std::vector< std::string > Macros
A list of macros of the form <definition>=<expansion> .
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.
__packed_splat4 __packed_splat2 __packed_splat8 __packed_splat4 __packed_splat2 __packed_splat4 __packed_splat2 __packed_splat8 __packed_splat4 uint32_t
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