34#include "llvm/ADT/DenseMap.h"
35#include "llvm/ADT/Enum.h"
36#include "llvm/ADT/STLExtras.h"
37#include "llvm/ADT/ScopeExit.h"
38#include "llvm/ADT/SmallString.h"
39#include "llvm/ADT/SmallVector.h"
40#include "llvm/Frontend/HLSL/HLSLResource.h"
41#include "llvm/Frontend/HLSL/RootSignatureMetadata.h"
42#include "llvm/Frontend/HLSL/SemanticSignaturePacking.h"
43#include "llvm/IR/Constants.h"
44#include "llvm/IR/DerivedTypes.h"
45#include "llvm/IR/GlobalVariable.h"
46#include "llvm/IR/IntrinsicInst.h"
47#include "llvm/IR/LLVMContext.h"
48#include "llvm/IR/Metadata.h"
49#include "llvm/IR/Module.h"
50#include "llvm/IR/Type.h"
51#include "llvm/IR/Value.h"
52#include "llvm/Support/Alignment.h"
53#include "llvm/Support/ErrorHandling.h"
54#include "llvm/Support/FormatVariadic.h"
55#include "llvm/Support/Path.h"
56#include "llvm/Transforms/Utils/ModuleUtils.h"
66using llvm::hlsl::CBufferRowSizeInBytes;
70void addDxilValVersion(StringRef ValVersionStr, llvm::Module &M) {
74 if (Version.tryParse(ValVersionStr) || Version.getBuild() ||
75 Version.getSubminor() || !Version.getMinor()) {
79 uint64_t Major = Version.getMajor();
80 uint64_t Minor = *Version.getMinor();
82 auto &Ctx = M.getContext();
84 MDNode *Val = MDNode::get(Ctx, {ConstantAsMetadata::get(B.getInt32(Major)),
85 ConstantAsMetadata::get(B.getInt32(Minor))});
86 StringRef DXILValKey =
"dx.valver";
87 auto *DXILValMD = M.getOrInsertNamedMetadata(DXILValKey);
88 DXILValMD->addOperand(Val);
91void addRootSignatureMD(llvm::dxbc::RootSignatureVersion RootSigVer,
93 llvm::Function *Fn, llvm::Module &M) {
94 auto &Ctx = M.getContext();
96 llvm::hlsl::rootsig::MetadataBuilder RSBuilder(M, Elements);
97 MDNode *RootSignature = RSBuilder.BuildRootSignature();
99 ConstantAsMetadata *Version = ConstantAsMetadata::get(ConstantInt::get(
100 llvm::Type::getInt32Ty(Ctx), llvm::to_underlying(RootSigVer)));
101 ValueAsMetadata *EntryFunc =
Fn ? ValueAsMetadata::get(Fn) :
nullptr;
102 MDNode *MDVals = MDNode::get(Ctx, {EntryFunc, RootSignature, Version});
104 StringRef RootSignatureValKey =
"dx.rootsignatures";
105 auto *RootSignatureValMD = M.getOrInsertNamedMetadata(RootSignatureValKey);
106 RootSignatureValMD->addOperand(MDVals);
111 llvm::Triple::EnvironmentType Stage, llvm::hlsl::IOType IOTy,
113 bool UseNative16BitTypes) {
114 using namespace llvm::hlsl;
117 if (Stage == llvm::Triple::Vertex && IOTy == IOType::In)
118 return packSignatureStacked(Elements, Stage, IOTy);
119 if (Stage == llvm::Triple::Pixel && IOTy == IOType::Out)
120 return packSignatureIndexed(Elements, Stage, IOTy);
122 return packSignatureOptimized(Elements, Stage, IOTy, UseNative16BitTypes);
123 return packSignaturePrefixStable(Elements, Stage, IOTy, UseNative16BitTypes);
126MDNode *buildSemanticSignatureMD(
128 if (Elements.empty())
132 for (
const llvm::hlsl::SemanticSignatureElement &Element : Elements)
133 ElementMD.push_back(Element.toMetadata(Ctx));
134 return MDNode::get(Ctx, ElementMD);
137void addSemanticSignatureMD(
140 llvm::Function *Fn, llvm::Module &M) {
141 if (InputElements.empty() && OutputElements.empty())
144 LLVMContext &Ctx = M.getContext();
145 MDNode *InputSignature = buildSemanticSignatureMD(InputElements, Ctx);
146 MDNode *OutputSignature = buildSemanticSignatureMD(OutputElements, Ctx);
147 MDNode *MDVals = MDNode::get(
148 Ctx, {ValueAsMetadata::get(Fn), InputSignature, OutputSignature});
150 M.getOrInsertNamedMetadata(
"dx.semantic.signatures")->addOperand(MDVals);
155 GlobalVariable *ResGV =
157 assert(ResGV &&
"expected valid global variable");
174static const VarDecl *findStructResourceParentDeclAndBuildName(
181 if (
const auto *DRE = dyn_cast<DeclRefExpr>(E)) {
183 "member expr base is not a var decl");
189 WorkList.push_back(E);
190 if (
const auto *MExp = dyn_cast<MemberExpr>(E))
192 else if (
const auto *ICE = dyn_cast<ImplicitCastExpr>(E))
193 E = ICE->getSubExpr();
194 else if (
const auto *ASE = dyn_cast<ArraySubscriptExpr>(E))
201 llvm_unreachable(
"unexpected expr type in resource member access");
203 assert(E &&
"expected valid expression");
206 while (!WorkList.empty()) {
207 E = WorkList.pop_back_val();
208 if (
const auto *ME = dyn_cast<MemberExpr>(E)) {
210 ME->getMemberNameInfo().getName().getAsIdentifierInfo()->getName());
211 }
else if (
const auto *ICE = dyn_cast<ImplicitCastExpr>(E)) {
212 if (ICE->getCastKind() == CK_UncheckedDerivedToBase) {
214 ICE->getSubExpr()->getType()->getAsCXXRecordDecl();
215 CXXRecordDecl *BaseRD = ICE->getType()->getAsCXXRecordDecl();
218 }
else if (
const auto *ASE = dyn_cast<ArraySubscriptExpr>(E)) {
219 const Expr *IdxExpr = ASE->getIdx();
220 std::optional<llvm::APSInt>
Value =
223 "expected constant index in struct with resource array access");
226 llvm_unreachable(
"unexpected expr type in resource member access");
240 findStructResourceParentDeclAndBuildName(ME, NameBuilder);
249 if (
const auto *ADA = dyn_cast<HLSLAssociatedResourceDeclAttr>(A)) {
250 VarDecl *AssocResVD = ADA->getResDecl();
262 auto &Ctx = M.getContext();
265 llvm::NamedMDNode *DXContents =
266 M.getOrInsertNamedMetadata(
"dx.source.contents");
267 auto addFile = [&](
const std::pair<StringRef, StringRef> &NameContent) {
268 llvm::MDTuple *FileInfo =
269 llvm::MDNode::get(Ctx, {llvm::MDString::get(Ctx, NameContent.first),
270 llvm::MDString::get(Ctx, NameContent.second)});
271 DXContents->addOperand(FileInfo);
276 &SM.getSLocEntry(SM.getMainFileID(), &
Invalid);
277 assert(!
Invalid &&
"Main file SLocEntry must not be invalid!");
282 std::optional<SmallString<256>> MainFileName;
283 Files.reserve(SM.local_sloc_entry_size());
284 for (
unsigned I : llvm::seq(SM.local_sloc_entry_size())) {
299 llvm::sys::path::native(Path);
303 SM.getDiagnostics().Report(diag::warn_hlsl_failed_to_embed_source)
308 if (&MainCCEntry != &CCEntry) {
309 Files.emplace_back(Path, Buffer->getBuffer());
312 addFile(std::make_pair(Path, Buffer->getBuffer()));
313 MainFileName.emplace(Path);
316 assert(MainFileName &&
"Main file not found.");
321 for (
unsigned I = 1; I < Files.size(); ++I)
322 assert((Files[I - 1].first != Files[I].first) &&
323 "duplicate files in dx.source.contents");
325 llvm::for_each(Files, addFile);
328 Defines.reserve(
Macros.size());
329 for (
const auto &
Macro : Macros) {
332 Defines.emplace_back(llvm::MDString::get(Ctx,
Macro.first));
334 M.getOrInsertNamedMetadata(
"dx.source.defines")
335 ->addOperand(llvm::MDNode::get(Ctx, Defines));
337 if (!CodeGenOpts.MainFileName.empty())
338 llvm::sys::path::native(CodeGenOpts.MainFileName, *MainFileName);
339 M.getOrInsertNamedMetadata(
"dx.source.mainFileName")
341 llvm::MDNode::get(Ctx, llvm::MDString::get(Ctx, *MainFileName)));
344 Args.reserve(CodeGenOpts.HLSLParsedCommandLine.size());
345 if (!CodeGenOpts.HLSLParsedCommandLine.empty())
346 for (
const auto &Arg : llvm::drop_begin(CodeGenOpts.HLSLParsedCommandLine))
347 Args.push_back(llvm::MDString::get(Ctx, Arg));
348 M.getOrInsertNamedMetadata(
"dx.source.args")
349 ->addOperand(llvm::MDNode::get(Ctx, Args));
355 if (
const auto *DRE = dyn_cast_or_null<DeclRefExpr>(E))
356 return DRE->getDecl();
357 if (
auto *OVE = dyn_cast<OpaqueValueExpr>(E))
367 const Expr *E =
nullptr;
368 while (ASE !=
nullptr) {
372 ASE = dyn_cast<ArraySubscriptExpr>(E);
374 return getArrayDecl(AST, E);
380 assert(Ty->
isArrayType() &&
"expected array type");
386static Value *buildNameForResource(llvm::StringRef BaseName,
395 for (
auto *Method :
Record->methods()) {
396 if (Method->getStorageClass() == SC && Method->getName() == Name)
406 assert(Binding.
hasBinding() &&
"at least one binding attribute expected");
410 Value *NameStr = buildNameForResource(Name, CGM);
415 "resources with counter handle must have a binding with counter "
416 "implicit order ID");
419 auto *RegSlot = llvm::ConstantInt::get(CGM.
IntTy, Binding.
getSlot());
422 ?
"__createFromBindingWithImplicitCounter"
423 :
"__createFromBinding";
424 CreateMethod = lookupMethod(ResourceDecl, Name,
SC_Static);
431 ?
"__createFromImplicitBindingWithImplicitCounter"
432 :
"__createFromImplicitBinding";
433 CreateMethod = lookupMethod(ResourceDecl, Name,
SC_Static);
441 auto *CounterOrderID = llvm::ConstantInt::get(CGM.
IntTy, CounterBinding);
457 Args, Proto,
false,
nullptr);
460 CGF.
EmitCall(FnInfo, Callee, ReturnValue, Args,
nullptr);
469static std::optional<llvm::Value *> initializeResourceArrayFromGlobal(
472 llvm::Value *Range, llvm::Value *StartIndex, StringRef ResourceName,
476 llvm::IntegerType *IntTy = CGF.
CGM.
IntTy;
477 llvm::Value *Index = StartIndex;
478 llvm::Value *One = llvm::ConstantInt::get(IntTy, 1);
486 GEPIndices.push_back(llvm::ConstantInt::get(IntTy, 0));
491 for (uint64_t I = 0; I < ArraySize; I++) {
493 Index = CGF.
Builder.CreateAdd(Index, One);
494 GEPIndices.back() = llvm::ConstantInt::get(IntTy, I);
496 std::optional<llvm::Value *> MaybeIndex =
497 initializeResourceArrayFromGlobal(CGF, ResourceDecl, SubArrayTy,
498 ValueSlot, Range, Index,
499 ResourceName, Binding, GEPIndices);
513 for (uint64_t I = 0; I < ArraySize; I++) {
515 Index = CGF.
Builder.CreateAdd(Index, One);
516 GEPIndices.back() = llvm::ConstantInt::get(IntTy, I);
522 CXXMethodDecl *CreateMethod = lookupResourceInitMethodAndSetupArgs(
523 CGF.
CGM, ResourceDecl, Range, Index, ResourceName, Binding, Args);
531 callResourceInitMethod(CGF, CreateMethod, Args, ReturnAddress);
538class HLSLBufferCopyEmitter {
539 CodeGenFunction &CGF;
542 llvm::Type *LayoutTy =
nullptr;
544 SmallVector<llvm::Value *> CurStoreIndices;
545 SmallVector<llvm::Value *> CurLoadIndices;
547 using EmitResourceFnTy = llvm::function_ref<void(AggValueSlot &)>;
551 llvm::Value *emitAccessChain(llvm::Type *BaseTy, llvm::Value *Base,
552 ArrayRef<llvm::Value *> Indices) {
553 bool EmitLogical = CGF.getLangOpts().EmitLogicalPointer;
555 return CGF.Builder.CreateAccessChain(EmitLogical, BaseTy, Base, Indices);
557 llvm::SmallVector<llvm::Value *> GEPIndices;
558 GEPIndices.reserve(Indices.size() + 1);
559 GEPIndices.push_back(llvm::ConstantInt::get(CGF.IntTy, 0));
560 GEPIndices.append(Indices.begin(), Indices.end());
561 return CGF.Builder.CreateAccessChain(EmitLogical, BaseTy, Base, GEPIndices);
564 bool isBufferLayoutArray(llvm::StructType *ST) {
570 if (!ST || ST->getNumElements() != 2)
573 auto *PaddedEltsTy = dyn_cast<llvm::ArrayType>(ST->getElementType(0));
577 auto *PaddedTy = dyn_cast<llvm::StructType>(PaddedEltsTy->getElementType());
578 if (!PaddedTy || PaddedTy->getNumElements() != 2)
581 if (!CGF.CGM.getTargetCodeGenInfo().isHLSLPadding(
582 PaddedTy->getElementType(1)))
585 llvm::Type *ElementTy = ST->getElementType(1);
586 if (PaddedTy->getElementType(0) != ElementTy)
597 bool isResourceOrResourceArray(llvm::Type *Ty) {
598 while (
auto *AT = dyn_cast<llvm::ArrayType>(Ty))
599 Ty = AT->getElementType();
601 auto *ST = dyn_cast<llvm::StructType>(Ty);
602 if (!ST || ST->getNumElements() < 1)
605 auto *TargetTy = dyn_cast<llvm::TargetExtType>(ST->getElementType(0));
606 return TargetTy !=
nullptr;
609 void emitResourceOrResourceArray(
Value *Dst, llvm::Type *DstTy,
610 EmitResourceFnTy EmitResFn) {
613 Address DstAddr(Dst, DstTy, DstAlign);
622 void emitBufferLayoutCopy(
Value *Src, llvm::StructType *SrcTy,
Value *Dst,
623 llvm::ArrayType *DstTy,
624 EmitResourceFnTy EmitResFn) {
627 assert(SrcPaddedArrayTy->getNumElements() + 1 == DstTy->getNumElements());
629 ->getElementType(0) == SrcTy->getElementType(1));
631 auto *SrcDataTy = SrcTy->getElementType(1);
632 auto Zero = llvm::ConstantInt::get(CGF.IntTy, 0);
634 for (
unsigned I = 0; I < SrcPaddedArrayTy->getNumElements(); ++I) {
635 auto Index = llvm::ConstantInt::get(CGF.IntTy, I);
636 auto *SrcElt = emitAccessChain(SrcTy, Src, {
Zero, Index,
Zero});
637 auto *DstElt = emitAccessChain(DstTy, Dst, {Index});
638 emitElementCopy(SrcElt, SrcDataTy, DstElt, DstTy->getElementType(),
643 emitAccessChain(SrcTy, Src, {llvm::ConstantInt::get(CGF.IntTy, 1)});
644 auto *DstElt = emitAccessChain(
646 {llvm::ConstantInt::get(CGF.IntTy, DstTy->getNumElements() - 1)});
647 emitElementCopy(SrcElt, SrcDataTy, DstElt, DstTy->getElementType(),
651 void emitCopy(
Value *Src, llvm::StructType *SrcTy,
Value *Dst,
652 llvm::Type *DstTy, EmitResourceFnTy EmitResFn) {
653 assert(!isResourceOrResourceArray(DstTy) &&
654 "direct access to resources or resource arrays should be handled "
657 if (isBufferLayoutArray(SrcTy))
661 unsigned SrcIndex = 0;
662 unsigned DstIndex = 0;
669 while (DstIndex < DstST->getNumElements()) {
670 llvm::Type *DstEltTy = DstST->getElementType(DstIndex);
671 if (CGF.CGM.getTargetCodeGenInfo().isHLSLPadding(DstEltTy)) {
675 if (isResourceOrResourceArray(DstEltTy)) {
676 auto *DstElt = emitAccessChain(
677 DstTy, Dst, {llvm::ConstantInt::get(CGF.IntTy, DstIndex)});
678 emitResourceOrResourceArray(DstElt, DstEltTy, EmitResFn);
683 assert(SrcIndex < SrcTy->getNumElements());
684 llvm::Type *SrcEltTy = SrcTy->getElementType(SrcIndex);
685 if (CGF.CGM.getTargetCodeGenInfo().isHLSLPadding(SrcEltTy)) {
690 auto *SrcElt = emitAccessChain(
691 SrcTy, Src, {llvm::ConstantInt::get(CGF.IntTy, SrcIndex)});
692 auto *DstElt = emitAccessChain(
693 DstTy, Dst, {llvm::ConstantInt::get(CGF.IntTy, DstIndex)});
694 emitElementCopy(SrcElt, SrcEltTy, DstElt, DstEltTy, EmitResFn);
700 void emitCopy(
Value *Src, llvm::ArrayType *SrcTy,
Value *Dst,
701 llvm::Type *DstTy, EmitResourceFnTy EmitResFn) {
702 for (
unsigned I = 0, E = SrcTy->getNumElements(); I < E; ++I) {
704 emitAccessChain(SrcTy, Src, {llvm::ConstantInt::get(CGF.IntTy, I)});
706 emitAccessChain(DstTy, Dst, {llvm::ConstantInt::get(CGF.IntTy, I)});
707 emitElementCopy(SrcElt, SrcTy->getElementType(), DstElt,
713 void emitElementCopy(
Value *Src, llvm::Type *SrcTy,
Value *Dst,
714 llvm::Type *DstTy, EmitResourceFnTy EmitResFn) {
715 if (
auto *AT = dyn_cast<llvm::ArrayType>(SrcTy))
716 return emitCopy(Src, AT, Dst, DstTy, EmitResFn);
717 if (
auto *ST = dyn_cast<llvm::StructType>(SrcTy))
718 return emitCopy(Src, ST, Dst, DstTy, EmitResFn);
725 Address SrcAddr(Src, SrcTy, SrcAlign);
726 Address DstAddr(Dst, DstTy, DstAlign);
727 llvm::Value *
Load = CGF.Builder.CreateLoad(SrcAddr,
"cbuf.load");
728 CGF.Builder.CreateStore(Load, DstAddr);
732 HLSLBufferCopyEmitter(CodeGenFunction &CGF, Address DstPtr, Address SrcPtr)
733 : CGF(CGF), DstPtr(DstPtr), SrcPtr(SrcPtr) {}
735 bool emitCopy(QualType CType, EmitResourceFnTy EmitResFn =
nullptr) {
736 LayoutTy = HLSLBufferLayoutBuilder(CGF.CGM).layOutType(CType);
743 emitElementCopy(SrcPtr.getBasePointer(), LayoutTy, DstPtr.getBasePointer(),
744 DstPtr.getElementType(), EmitResFn);
755class AssociatedResourcesList {
760 specific_attr_iterator<HLSLAssociatedResourceDeclAttr> Begin, End, Next;
763 AssociatedResourcesList(
const VarDecl *StructVD,
764 StringRef ResourceNamePrefix) {
770 !I->getResDecl()->getName().starts_with(ResourceNamePrefix))
772 assert(I != E &&
"expected associated resource not found");
777 while (I != E && ((HLSLAssociatedResourceDeclAttr *)*I)
780 .starts_with(ResourceNamePrefix))
786 const VarDecl *getNextResource() {
790 const VarDecl *Res = Next->getResDecl();
801 assert(
T->isHLSLSpecificType() &&
"Not an HLSL specific type!");
804 if (llvm::Type *TargetTy =
805 CGM.getTargetCodeGenInfo().getHLSLType(
CGM,
T, OffsetInfo))
808 llvm_unreachable(
"Generic handling of HLSL types is not supported.");
811llvm::Triple::ArchType CGHLSLRuntime::getArch() {
817void CGHLSLRuntime::emitBufferGlobalsAndMetadata(
823 llvm::Type *BufType = BufGV->getValueType();
828 size_t OffsetIdx = 0;
838 VarDecl *VD = dyn_cast<VarDecl>(D);
854 DeclsWithOffset.emplace_back(VD, OffsetInfo[OffsetIdx++]);
857 if (!OffsetInfo.
empty())
858 llvm::stable_sort(DeclsWithOffset, [](
const auto &LHS,
const auto &RHS) {
863 SmallVector<llvm::Metadata *> BufGlobals;
864 BufGlobals.reserve(DeclsWithOffset.size() + 1);
865 BufGlobals.push_back(ValueAsMetadata::get(BufGV));
867 auto ElemIt = LayoutStruct->element_begin();
868 for (
auto &[VD, _] : DeclsWithOffset) {
869 if (
CGM.getTargetCodeGenInfo().isHLSLPadding(*ElemIt))
872 assert(ElemIt != LayoutStruct->element_end() &&
873 "number of elements in layout struct does not match");
874 llvm::Type *LayoutType = *ElemIt++;
876 GlobalVariable *ElemGV =
878 BufGlobals.push_back(ValueAsMetadata::get(ElemGV));
880 assert(ElemIt == LayoutStruct->element_end() &&
881 "number of elements in layout struct does not match");
885 .getOrInsertNamedMetadata(
"hlsl.cbs")
886 ->addOperand(MDNode::get(Ctx, BufGlobals));
890static const clang::HLSLAttributedResourceType *
895 HLSLAttributedResourceType::Attributes(ResourceClass::CBuffer));
910 VarDecl *VD = dyn_cast<VarDecl>(D);
921 if (
auto *POA = dyn_cast<HLSLPackOffsetAttr>(
Attr)) {
922 Offset = POA->getOffsetInBytes();
925 auto *RBA = dyn_cast<HLSLResourceBindingAttr>(
Attr);
927 RBA->getRegisterType() == HLSLResourceBindingAttr::RegisterType::C) {
928 Offset = RBA->getSlotNumber() * CBufferRowSizeInBytes;
932 Result.Offsets.push_back(Offset);
940 assert(BufDecl->
isCBuffer() &&
"tbuffer codegen is not supported yet");
943 const clang::HLSLAttributedResourceType *ResHandleTy =
947 if (ResHandleTy->getContainedType()->getAsCXXRecordDecl()->isEmpty())
953 llvm::GlobalVariable *BufGV =
new GlobalVariable(
955 GlobalValue::LinkageTypes::InternalLinkage, PoisonValue::get(LayoutTy),
956 llvm::formatv(
"{0}{1}", BufDecl->
getName(),
958 GlobalValue::NotThreadLocal);
960 llvm::Module &M =
CGM.getModule();
961 M.insertGlobalVariable(BufGV);
966 llvm::appendToCompilerUsed(M, {BufGV});
969 emitBufferGlobalsAndMetadata(BufDecl, BufGV, OffsetInfo);
972 initializeBufferFromBinding(BufDecl, BufGV);
977 llvm::Module &M =
CGM.getModule();
978 Triple
T(M.getTargetTriple());
981 if (
T.getEnvironment() != Triple::EnvironmentType::RootSignature)
984 addRootSignatureMD(SignatureDecl->
getVersion(),
990 const auto Entry = LayoutTypes.find(StructType);
991 if (Entry != LayoutTypes.end())
992 return Entry->getSecond();
997 llvm::StructType *LayoutTy) {
999 "layout type for this struct already exist");
1000 LayoutTypes[StructType] = LayoutTy;
1004 auto &TargetOpts =
CGM.getTarget().getTargetOpts();
1005 auto &CodeGenOpts =
CGM.getCodeGenOpts();
1006 auto &LangOpts =
CGM.getLangOpts();
1007 llvm::Module &M =
CGM.getModule();
1008 Triple
T(M.getTargetTriple());
1009 if (
T.getArch() == Triple::ArchType::dxil)
1010 addDxilValVersion(TargetOpts.DxilValidatorVersion, M);
1011 if (!CodeGenOpts.DisableDXSourceMetadata &&
1012 CodeGenOpts.getDebugInfo() >=
1013 llvm::codegenoptions::DebugInfoKind::DebugInfoConstructor)
1014 addSourceInfo(
CGM, M);
1015 if (CodeGenOpts.ResMayAlias)
1016 M.setModuleFlag(llvm::Module::ModFlagBehavior::Error,
"dx.resmayalias", 1);
1017 if (CodeGenOpts.AllResourcesBound)
1018 M.setModuleFlag(llvm::Module::ModFlagBehavior::Error,
1019 "dx.allresourcesbound", 1);
1020 if (CodeGenOpts.OptimizationLevel == 0)
1021 M.addModuleFlag(llvm::Module::ModFlagBehavior::Override,
1022 "dx.disable_optimizations", 1);
1027 if (LangOpts.NativeHalfType)
1028 M.setModuleFlag(llvm::Module::ModFlagBehavior::Error,
"dx.nativelowprec",
1031 if (LangOpts.HLSLSpvPreserveInterface &&
T.isSPIRV()) {
1037 for (GlobalVariable &GV : M.globals()) {
1038 unsigned AS = GV.getAddressSpace();
1039 if (AS == InputAS || AS == OutputAS)
1040 InterfaceVars.push_back(&GV);
1042 if (!InterfaceVars.empty())
1043 appendToCompilerUsed(M, InterfaceVars);
1051 const auto *ShaderAttr = FD->
getAttr<HLSLShaderAttr>();
1052 assert(ShaderAttr &&
"All entry functions must have a HLSLShaderAttr");
1053 const StringRef ShaderAttrKindStr =
"hlsl.shader";
1054 Fn->addFnAttr(ShaderAttrKindStr,
1055 llvm::Triple::getEnvironmentTypeName(ShaderAttr->getType()));
1056 if (HLSLNumThreadsAttr *NumThreadsAttr = FD->
getAttr<HLSLNumThreadsAttr>()) {
1057 const StringRef NumThreadsKindStr =
"hlsl.numthreads";
1058 std::string NumThreadsStr =
1059 formatv(
"{0},{1},{2}", NumThreadsAttr->getX(), NumThreadsAttr->getY(),
1060 NumThreadsAttr->getZ());
1061 Fn->addFnAttr(NumThreadsKindStr, NumThreadsStr);
1063 if (HLSLWaveSizeAttr *WaveSizeAttr = FD->
getAttr<HLSLWaveSizeAttr>()) {
1064 const StringRef WaveSizeKindStr =
"hlsl.wavesize";
1065 std::string WaveSizeStr =
1066 formatv(
"{0},{1},{2}", WaveSizeAttr->getMin(), WaveSizeAttr->getMax(),
1067 WaveSizeAttr->getPreferred());
1068 Fn->addFnAttr(WaveSizeKindStr, WaveSizeStr);
1075 Fn->addFnAttr(llvm::Attribute::NoInline);
1077 if (
CGM.getLangOpts().HLSLSpvEnableMaximalReconvergence) {
1078 Fn->addFnAttr(
"enable-maximal-reconvergence",
"true");
1085 if (
const auto *VT = dyn_cast<FixedVectorType>(Ty)) {
1087 for (
unsigned I = 0; I < VT->getNumElements(); ++I) {
1088 Value *Elt = B.CreateCall(F, {B.getInt32(I)});
1089 Elt = B.CreateTrunc(Elt, VT->getElementType());
1094 return B.CreateTrunc(B.CreateCall(F, {B.getInt32(0)}), Ty);
1104 if (
auto *AT = dyn_cast<llvm::ArrayType>(Ty)) {
1105 Ty = AT->getElementType();
1108 if (
auto *VT = dyn_cast<llvm::FixedVectorType>(Ty)) {
1109 Ty = VT->getElementType();
1114 return Ty->isIntegerTy() || Ty->isDoubleTy();
1117static llvm::hlsl::InterpolationMode
1119 llvm::Type *Ty, llvm::Triple::EnvironmentType Stage,
1120 llvm::hlsl::IOType IO) {
1121 using llvm::hlsl::InterpolationMode;
1122 if (!((Stage == llvm::Triple::Pixel && IO == llvm::hlsl::IOType::In) ||
1123 (Stage == llvm::Triple::Vertex && IO == llvm::hlsl::IOType::Out)))
1124 return InterpolationMode::Undefined;
1125 if (InterpMode == InterpolationMode::Undefined &&
1127 return InterpolationMode::Constant;
1133 llvm::hlsl::SPIRVInterfaceDecoration Decoration,
1135 llvm::hlsl::InterpolationMode InterpMode =
1136 llvm::hlsl::InterpolationMode::Undefined) {
1137 using llvm::hlsl::InterpolationMode;
1138 using llvm::hlsl::SPIRVInterpolationMode;
1140 LLVMContext &Ctx = GV->getContext();
1141 IRBuilder<> B(*GV->getParent());
1143 Decorations.push_back(MDNode::get(
1145 {ConstantAsMetadata::get(B.getInt32(llvm::to_underlying(Decoration))),
1146 ConstantAsMetadata::get(B.getInt32(Operand))}));
1147 auto Add = [&](SPIRVInterpolationMode InterpolationDecoration) {
1148 Decorations.push_back(
1149 MDNode::get(Ctx, {ConstantAsMetadata::get(B.getInt32(
1150 llvm::to_underlying(InterpolationDecoration)))}));
1152 switch (InterpMode) {
1153 case InterpolationMode::Undefined:
1154 case InterpolationMode::Linear:
1156 case InterpolationMode::Constant:
1157 Add(SPIRVInterpolationMode::Flat);
1159 case InterpolationMode::LinearNoperspective:
1160 Add(SPIRVInterpolationMode::NoPerspective);
1162 case InterpolationMode::LinearNoperspectiveCentroid:
1163 Add(SPIRVInterpolationMode::NoPerspective);
1165 case InterpolationMode::LinearCentroid:
1166 Add(SPIRVInterpolationMode::Centroid);
1168 case InterpolationMode::LinearNoperspectiveSample:
1169 Add(SPIRVInterpolationMode::NoPerspective);
1171 case InterpolationMode::LinearSample:
1172 Add(SPIRVInterpolationMode::Sample);
1175 llvm_unreachable(
"invalid interpolation mode");
1179 GV->addMetadata(
"spirv.Decorations", *MDNode::get(Ctx, Decorations));
1183 IRBuilder<> &B, llvm::Module &M, llvm::Type *Ty,
const Twine &Name,
1184 llvm::hlsl::SPIRVInterfaceDecoration Decoration,
unsigned Operand,
1185 llvm::hlsl::InterpolationMode InterpMode) {
1188 bool Truncate = Decoration == llvm::hlsl::SPIRVInterfaceDecoration::BuiltIn &&
1189 Ty->isIntegerTy() && Ty->getIntegerBitWidth() < 32;
1190 llvm::Type *LoadTy = Truncate ? B.getInt32Ty() : Ty;
1191 auto *GV =
new llvm::GlobalVariable(
1192 M, LoadTy,
true, llvm::GlobalValue::ExternalLinkage,
1193 nullptr, Name,
nullptr,
1194 llvm::GlobalVariable::GeneralDynamicTLSModel,
1196 GV->setVisibility(llvm::GlobalValue::HiddenVisibility);
1198 llvm::Value *
Value = B.CreateLoad(LoadTy, GV);
1199 return Truncate ? B.CreateTrunc(
Value, Ty) :
Value;
1202llvm::Value *CGHLSLRuntime::emitSPIRVUserSemanticLoad(
1203 llvm::IRBuilder<> &B, llvm::Type *
Type,
const clang::DeclaratorDecl *
Decl,
1204 HLSLAppliedSemanticAttr *Semantic, std::optional<unsigned> Index,
1205 llvm::hlsl::InterpolationMode InterpMode) {
1206 Twine BaseName = Twine(Semantic->getAttrName()->getName());
1207 Twine VariableName = BaseName.concat(Twine(Index.value_or(0)));
1209 unsigned Location = SPIRVLastAssignedInputSemanticLocation;
1210 if (
auto *L =
Decl->getAttr<HLSLVkLocationAttr>())
1211 Location = L->getLocation();
1215 llvm::ArrayType *AT = dyn_cast<llvm::ArrayType>(
Type);
1216 unsigned ElementCount = AT ? AT->getNumElements() : 1;
1217 SPIRVLastAssignedInputSemanticLocation += ElementCount;
1220 llvm::hlsl::SPIRVInterfaceDecoration::Location,
1221 Location, InterpMode);
1225 IRBuilder<> &B, llvm::Module &M, llvm::Value *Source,
const Twine &Name,
1226 llvm::hlsl::SPIRVInterfaceDecoration Decoration,
unsigned Operand,
1227 llvm::hlsl::InterpolationMode InterpMode) {
1228 auto *GV =
new llvm::GlobalVariable(
1229 M, Source->getType(),
false,
1230 llvm::GlobalValue::ExternalLinkage,
1231 nullptr, Name,
nullptr,
1232 llvm::GlobalVariable::GeneralDynamicTLSModel,
1234 GV->setVisibility(llvm::GlobalValue::HiddenVisibility);
1236 B.CreateStore(Source, GV);
1239void CGHLSLRuntime::emitSPIRVUserSemanticStore(
1240 llvm::IRBuilder<> &B, llvm::Value *Source,
1241 const clang::DeclaratorDecl *
Decl, HLSLAppliedSemanticAttr *Semantic,
1242 std::optional<unsigned> Index, llvm::hlsl::InterpolationMode InterpMode) {
1243 Twine BaseName = Twine(Semantic->getAttrName()->getName());
1244 Twine VariableName = BaseName.concat(Twine(Index.value_or(0)));
1246 unsigned Location = SPIRVLastAssignedOutputSemanticLocation;
1247 if (
auto *L =
Decl->getAttr<HLSLVkLocationAttr>())
1248 Location = L->getLocation();
1252 llvm::ArrayType *AT = dyn_cast<llvm::ArrayType>(Source->getType());
1253 unsigned ElementCount = AT ? AT->getNumElements() : 1;
1254 SPIRVLastAssignedOutputSemanticLocation += ElementCount;
1256 llvm::hlsl::SPIRVInterfaceDecoration::Location,
1257 Location, InterpMode);
1262struct SemanticShape {
1264 SmallVector<unsigned> Dimensions;
1267 bool IsMatrix =
false;
1268 bool IsRowMajor =
false;
1272 unsigned getMatrixElementIndex(
unsigned Row,
unsigned Col)
const {
1274 unsigned MatrixRow = Row % Dimensions.back();
1275 return IsRowMajor ? Col * Dimensions.back() + MatrixRow
1276 : MatrixRow * Cols + Col;
1279 unsigned getNumRows()
const {
1281 for (
unsigned Dimension : Dimensions)
1286 SmallVector<unsigned> getArrayIndicesForRow(
unsigned Row)
const {
1287 assert(Row < getNumRows() &&
"row exceeds semantic shape");
1289 SmallVector<unsigned> Indices(Dimensions.size());
1290 for (
auto [Index, Dimension] :
1291 llvm::zip_equal(llvm::reverse(Indices), llvm::reverse(Dimensions))) {
1292 Index = Row % Dimension;
1303 if (
const auto *FD = dyn_cast<clang::FunctionDecl>(
Decl))
1304 return FD->getDeclaredReturnType();
1305 return Decl->getType();
1311 SemanticShape Shape{{}, 1, Ty};
1314 Shape.Dimensions.push_back(CAT->getSize().getZExtValue());
1315 Shape.RowType = CAT->getElementType();
1319 Shape.Cols = VT->getNumElements();
1320 }
else if (
const auto *MT =
1322 Shape.IsMatrix =
true;
1324 Shape.Dimensions.push_back(Shape.IsRowMajor ? MT->getNumRows()
1325 : MT->getNumColumns());
1326 Shape.Cols = Shape.IsRowMajor ? MT->getNumColumns() : MT->getNumRows();
1336 Ty = VT->getElementType();
1340 return llvm::hlsl::getDXILElementType(IRTy, IsSigned);
1345 std::optional<unsigned> Index,
const SemanticShape &Shape) {
1346 StringRef Name = Semantic->getAttrName()->getName();
1350 uint32_t FirstSemanticIndex = Index.value_or(0);
1351 for (
uint32_t I = 0, E = Shape.getNumRows(); I < E; ++I)
1352 SemanticIndices.push_back(FirstSemanticIndex + I);
1354 llvm::dxbc::PSV::SemanticKind Kind = llvm::hlsl::getSemanticKind(Name);
1355 llvm::dxil::ElementType CompType =
1361 if (Kind == llvm::dxbc::PSV::SemanticKind::SampleIndex ||
1362 Kind == llvm::dxbc::PSV::SemanticKind::PrimitiveID) {
1363 if (CompType == llvm::dxil::ElementType::I16)
1364 CompType = llvm::dxil::ElementType::U16;
1365 else if (CompType == llvm::dxil::ElementType::I32)
1366 CompType = llvm::dxil::ElementType::U32;
1372 return llvm::hlsl::SemanticSignatureElement(SigId, Name, CompType, Kind,
1374 static_cast<uint8_t>(Shape.Cols));
1377llvm::Value *CGHLSLRuntime::emitDXILUserSemanticLoad(
1378 llvm::IRBuilder<> &B, llvm::Type *
Type,
const clang::DeclaratorDecl *
Decl,
1379 HLSLAppliedSemanticAttr *Semantic, std::optional<unsigned> Index,
1380 SemanticSignatures &Signature) {
1381 StringRef Name = Semantic->getAttrName()->getName();
1382 SemanticShape Shape =
1386 Signature.push_back(
1389 llvm::Type *RowTy =
CGM.getTypes().ConvertTypeForMem(Shape.RowType);
1391 llvm::Function *IntrFn = llvm::Intrinsic::getOrInsertDeclaration(
1392 B.getModule(), llvm::Intrinsic::dx_load_input, {RowTy});
1394 SmallVector<OperandBundleDef, 1> OB;
1396 llvm::Value *bundleArgs[] = {Token};
1397 OB.emplace_back(
"convergencectrl", bundleArgs);
1400 bool IsMatrixValue = Shape.IsMatrix &&
Type->isVectorTy();
1401 llvm::Type *LeafTy = Shape.IsMatrix && !IsMatrixValue
1403 :
CGM.getTypes().ConvertType(Shape.RowType);
1404 llvm::Value *
Result = llvm::PoisonValue::get(
Type);
1406 const unsigned NumRows = Shape.getNumRows();
1408 for (
unsigned Row = 0; Row < NumRows; ++Row) {
1409 std::array<Value *, 4> Args{
1413 llvm::PoisonValue::get(B.getInt32Ty())};
1414 llvm::Value *
Value =
1415 B.CreateCall(IntrFn, Args, OB, Twine(Name).concat(Twine(Row)));
1418 if (
Value->getType() != LeafTy) {
1420 "unexpected semantic load type mismatch");
1421 Value = B.CreateICmpNE(
1422 Value, llvm::Constant::getNullValue(
Value->getType()),
"loadedv");
1425 if (IsMatrixValue) {
1426 for (
unsigned Col = 0; Col < Shape.Cols; ++Col)
1428 B.CreateInsertElement(
Result, B.CreateExtractElement(
Value, Col),
1429 Shape.getMatrixElementIndex(Row, Col));
1431 SmallVector<unsigned> Indices = Shape.getArrayIndicesForRow(Row);
1439void CGHLSLRuntime::emitDXILUserSemanticStore(llvm::IRBuilder<> &B,
1440 llvm::Value *Source,
1441 const clang::DeclaratorDecl *
Decl,
1442 HLSLAppliedSemanticAttr *Semantic,
1443 std::optional<unsigned> Index,
1444 SemanticSignatures &Signature) {
1445 SemanticShape Shape =
1449 Signature.push_back(
1452 llvm::Type *RowTy =
CGM.getTypes().ConvertTypeForMem(Shape.RowType);
1454 llvm::Function *IntrFn = llvm::Intrinsic::getOrInsertDeclaration(
1455 B.getModule(), llvm::Intrinsic::dx_store_output, {RowTy});
1457 SmallVector<OperandBundleDef, 1> OB;
1459 llvm::Value *bundleArgs[] = {Token};
1460 OB.emplace_back(
"convergencectrl", bundleArgs);
1463 bool IsMatrixValue = Shape.IsMatrix && Source->getType()->isVectorTy();
1464 const unsigned NumRows = Shape.getNumRows();
1465 for (
unsigned Row = 0; Row < NumRows; ++Row) {
1467 if (IsMatrixValue) {
1468 SmallVector<int, 4> Mask;
1469 for (
unsigned Col = 0; Col < Shape.Cols; ++Col)
1470 Mask.push_back(Shape.getMatrixElementIndex(Row, Col));
1471 Val = B.CreateShuffleVector(Source, Mask);
1473 SmallVector<unsigned> Indices = Shape.getArrayIndicesForRow(Row);
1474 Val = Indices.empty() ? Source : B.CreateExtractValue(Source, Indices);
1479 if (Val->getType() != RowTy) {
1481 "unexpected semantic store type mismatch");
1482 Val = B.CreateZExt(Val, RowTy,
"storedv");
1485 std::array<Value *, 4> Args{B.getInt32(SigId),
1488 B.CreateCall(IntrFn, Args, OB);
1492llvm::Value *CGHLSLRuntime::emitUserSemanticLoad(
1493 IRBuilder<> &B, llvm::Type *
Type,
const clang::DeclaratorDecl *
Decl,
1494 HLSLAppliedSemanticAttr *Semantic, std::optional<unsigned> Index,
1495 SemanticSignatures &Signature, llvm::hlsl::InterpolationMode InterpMode) {
1496 if (
CGM.getTarget().getTriple().isSPIRV())
1497 return emitSPIRVUserSemanticLoad(B,
Type,
Decl, Semantic, Index,
1500 if (
CGM.getTarget().getTriple().isDXIL())
1501 return emitDXILUserSemanticLoad(B,
Type,
Decl, Semantic, Index, Signature);
1503 llvm_unreachable(
"Unsupported target for user-semantic load.");
1506void CGHLSLRuntime::emitUserSemanticStore(
1507 IRBuilder<> &B, llvm::Value *Source,
const clang::DeclaratorDecl *
Decl,
1508 HLSLAppliedSemanticAttr *Semantic, std::optional<unsigned> Index,
1509 SemanticSignatures &Signature, llvm::hlsl::InterpolationMode InterpMode) {
1510 if (
CGM.getTarget().getTriple().isSPIRV())
1511 return emitSPIRVUserSemanticStore(B, Source,
Decl, Semantic, Index,
1514 if (
CGM.getTarget().getTriple().isDXIL())
1515 return emitDXILUserSemanticStore(B, Source,
Decl, Semantic, Index,
1518 llvm_unreachable(
"Unsupported target for user-semantic load.");
1523 HLSLAppliedSemanticAttr *Semantic,
1525 llvm::Triple::EnvironmentType Stage, std::optional<unsigned> Index,
1528 case llvm::dxbc::PSV::SemanticKind::Barycentrics:
1529 assert(Stage == llvm::Triple::Pixel &&
1530 "SV_Barycentrics is in an unavailable stage and should have been "
1531 "diagnosed by Sema");
1532 if (
CGM.getTarget().getTriple().isSPIRV()) {
1533 using llvm::hlsl::InterpolationMode;
1536 bool NoPerspective =
false;
1537 switch (InterpMode) {
1538 case InterpolationMode::LinearNoperspective:
1539 NoPerspective =
true;
1540 InterpMode = InterpolationMode::Linear;
1542 case InterpolationMode::LinearNoperspectiveCentroid:
1543 NoPerspective =
true;
1544 InterpMode = InterpolationMode::LinearCentroid;
1546 case InterpolationMode::LinearNoperspectiveSample:
1547 NoPerspective =
true;
1548 InterpMode = InterpolationMode::LinearSample;
1554 llvm::Type *
BuiltinType = llvm::FixedVectorType::get(
CGM.FloatTy, 3);
1557 llvm::hlsl::SPIRVInterfaceDecoration::BuiltIn,
1558 NoPerspective ? 5287
1561 if (
Type->getScalarType()->isHalfTy())
1562 return B.CreateFPTrunc(Barycentrics,
Type);
1563 return Barycentrics;
1565 if (
CGM.getTarget().getTriple().isDXIL())
1566 return emitDXILUserSemanticLoad(B,
Type,
Decl, Semantic, Index,
1569 case llvm::dxbc::PSV::SemanticKind::GroupIndex: {
1570 assert(llvm::is_contained({llvm::Triple::Compute, llvm::Triple::Mesh,
1571 llvm::Triple::Amplification},
1573 "SV_GroupIndex is in an unavailable stage and should have been "
1574 "diagnosed by Sema");
1575 assert(Stage != llvm::Triple::Mesh &&
1576 Stage != llvm::Triple::Amplification &&
1577 "FIXME: SV_GroupIndex is not yet implemented for this shader "
1579 llvm::Function *GroupIndex =
1580 CGM.getIntrinsic(getFlattenedThreadIdInGroupIntrinsic());
1581 return B.CreateCall(FunctionCallee(GroupIndex));
1583 case llvm::dxbc::PSV::SemanticKind::DispatchThreadID: {
1584 assert(llvm::is_contained({llvm::Triple::Compute, llvm::Triple::Mesh,
1585 llvm::Triple::Amplification},
1587 "SV_DispatchThreadID is in an unavailable stage and should have "
1588 "been diagnosed by Sema");
1589 assert(Stage != llvm::Triple::Mesh &&
1590 Stage != llvm::Triple::Amplification &&
1591 "FIXME: SV_DispatchThreadID is not yet implemented for this "
1593 llvm::Intrinsic::ID IntrinID = getThreadIdIntrinsic();
1594 llvm::Function *ThreadIDIntrinsic =
1595 llvm::Intrinsic::isOverloaded(IntrinID)
1596 ?
CGM.getIntrinsic(IntrinID, {
CGM.Int32Ty})
1597 :
CGM.getIntrinsic(IntrinID);
1600 case llvm::dxbc::PSV::SemanticKind::GroupThreadID: {
1601 assert(llvm::is_contained({llvm::Triple::Compute, llvm::Triple::Mesh,
1602 llvm::Triple::Amplification},
1604 "SV_GroupThreadID is in an unavailable stage and should have been "
1605 "diagnosed by Sema");
1606 assert(Stage != llvm::Triple::Mesh &&
1607 Stage != llvm::Triple::Amplification &&
1608 "FIXME: SV_GroupThreadID is not yet implemented for this shader "
1610 llvm::Intrinsic::ID IntrinID = getGroupThreadIdIntrinsic();
1611 llvm::Function *GroupThreadIDIntrinsic =
1612 llvm::Intrinsic::isOverloaded(IntrinID)
1613 ?
CGM.getIntrinsic(IntrinID, {
CGM.Int32Ty})
1614 :
CGM.getIntrinsic(IntrinID);
1617 case llvm::dxbc::PSV::SemanticKind::GroupID: {
1618 assert(llvm::is_contained({llvm::Triple::Compute, llvm::Triple::Mesh,
1619 llvm::Triple::Amplification},
1621 "SV_GroupID is in an unavailable stage and should have been "
1622 "diagnosed by Sema");
1623 assert(Stage != llvm::Triple::Mesh &&
1624 Stage != llvm::Triple::Amplification &&
1625 "FIXME: SV_GroupID is not yet implemented for this shader stage");
1626 llvm::Intrinsic::ID IntrinID = getGroupIdIntrinsic();
1627 llvm::Function *GroupIDIntrinsic =
1628 llvm::Intrinsic::isOverloaded(IntrinID)
1629 ?
CGM.getIntrinsic(IntrinID, {
CGM.Int32Ty})
1630 :
CGM.getIntrinsic(IntrinID);
1633 case llvm::dxbc::PSV::SemanticKind::Position:
1634 assert(llvm::is_contained({llvm::Triple::Hull, llvm::Triple::Domain,
1635 llvm::Triple::Geometry, llvm::Triple::Pixel},
1637 "SV_Position is in an unavailable stage and should have been "
1638 "diagnosed by Sema");
1639 assert(Stage != llvm::Triple::Hull && Stage != llvm::Triple::Domain &&
1640 Stage != llvm::Triple::Geometry &&
1641 "FIXME: loading SV_Position is not yet implemented for this "
1643 if (
CGM.getTarget().getTriple().isSPIRV())
1645 Semantic->getAttrName()->getName(),
1646 llvm::hlsl::SPIRVInterfaceDecoration::BuiltIn,
1648 if (
CGM.getTarget().getTriple().isDXIL())
1649 return emitDXILUserSemanticLoad(B,
Type,
Decl, Semantic, Index,
1652 case llvm::dxbc::PSV::SemanticKind::VertexID:
1653 assert(Stage == llvm::Triple::Vertex &&
1654 "SV_VertexID is in an unavailable stage and should have been "
1655 "diagnosed by Sema");
1656 if (
CGM.getTarget().getTriple().isSPIRV())
1658 Semantic->getAttrName()->getName(),
1659 llvm::hlsl::SPIRVInterfaceDecoration::BuiltIn,
1661 if (
CGM.getTarget().getTriple().isDXIL())
1662 return emitDXILUserSemanticLoad(B,
Type,
Decl, Semantic, Index,
1665 case llvm::dxbc::PSV::SemanticKind::InstanceID:
1666 assert(Stage == llvm::Triple::Vertex &&
1667 "SV_InstanceID is in an unavailable stage and should have been "
1668 "diagnosed by Sema");
1669 if (
CGM.getTarget().getTriple().isSPIRV())
1671 Semantic->getAttrName()->getName(),
1672 llvm::hlsl::SPIRVInterfaceDecoration::BuiltIn,
1674 if (
CGM.getTarget().getTriple().isDXIL())
1675 return emitDXILUserSemanticLoad(B,
Type,
Decl, Semantic, Index,
1678 case llvm::dxbc::PSV::SemanticKind::ShadingRate:
1679 assert(llvm::is_contained({llvm::Triple::Hull, llvm::Triple::Domain,
1680 llvm::Triple::Geometry, llvm::Triple::Pixel},
1682 "SV_ShadingRate is in an unavailable stage and should have been "
1683 "diagnosed by Sema");
1684 assert(Stage != llvm::Triple::Hull && Stage != llvm::Triple::Domain &&
1685 Stage != llvm::Triple::Geometry &&
1686 "FIXME: loading SV_ShadingRate is not yet implemented for this "
1688 if (
CGM.getTarget().getTriple().isSPIRV())
1690 Semantic->getAttrName()->getName(),
1691 llvm::hlsl::SPIRVInterfaceDecoration::BuiltIn,
1693 if (
CGM.getTarget().getTriple().isDXIL())
1694 return emitDXILUserSemanticLoad(B,
Type,
Decl, Semantic, Index,
1697 case llvm::dxbc::PSV::SemanticKind::StartVertexLocation:
1698 assert(Stage == llvm::Triple::Vertex &&
1699 "SV_StartVertexLocation is in an unavailable stage and should have "
1700 "been diagnosed by Sema");
1701 if (
CGM.getTarget().getTriple().isSPIRV())
1703 Semantic->getAttrName()->getName(),
1704 llvm::hlsl::SPIRVInterfaceDecoration::BuiltIn,
1706 if (
CGM.getTarget().getTriple().isDXIL())
1707 return B.CreateCall(
1708 CGM.getIntrinsic(llvm::Intrinsic::dx_start_vertex_location));
1710 case llvm::dxbc::PSV::SemanticKind::PrimitiveID:
1711 assert(Stage == llvm::Triple::Pixel &&
1712 "SV_PrimitiveID is in an unavailable stage and should have been "
1713 "diagnosed by Sema");
1714 if (
CGM.getTarget().getTriple().isSPIRV())
1716 Semantic->getAttrName()->getName(),
1717 llvm::hlsl::SPIRVInterfaceDecoration::BuiltIn,
1721 if (
CGM.getTarget().getTriple().isDXIL())
1722 return emitDXILUserSemanticLoad(B,
Type,
Decl, Semantic, Index,
1725 case llvm::dxbc::PSV::SemanticKind::SampleIndex:
1726 assert(Stage == llvm::Triple::Pixel &&
1727 "SV_SampleIndex is in an unavailable stage and should have been "
1728 "diagnosed by Sema");
1729 if (
CGM.getTarget().getTriple().isSPIRV())
1731 Semantic->getAttrName()->getName(),
1732 llvm::hlsl::SPIRVInterfaceDecoration::BuiltIn,
1734 if (
CGM.getTarget().getTriple().isDXIL()) {
1735 assert(
Type->isIntegerTy() &&
Type->getIntegerBitWidth() <= 32 &&
1736 "SV_SampleIndex must be a 16 or 32 bit scalar integer, as "
1737 "diagnosed by Sema");
1740 SemanticShape Shape =
1743 CGM, Signature.size(), Semantic, Index, Shape));
1744 llvm::Value *SampleIndex =
1745 B.CreateCall(
CGM.getIntrinsic(llvm::Intrinsic::dx_sample_index));
1748 if (
Type->getIntegerBitWidth() < 32)
1749 SampleIndex = B.CreateTrunc(SampleIndex,
Type);
1753 case llvm::dxbc::PSV::SemanticKind::ViewID:
1754 assert(llvm::is_contained({llvm::Triple::Vertex, llvm::Triple::Hull,
1755 llvm::Triple::Domain, llvm::Triple::Geometry,
1756 llvm::Triple::Pixel, llvm::Triple::Mesh},
1758 "SV_ViewID is in an unavailable stage and should have been "
1759 "diagnosed by Sema");
1760 if (
CGM.getTarget().getTriple().isSPIRV())
1762 Semantic->getAttrName()->getName(),
1763 llvm::hlsl::SPIRVInterfaceDecoration::BuiltIn,
1765 if (
CGM.getTarget().getTriple().isDXIL())
1766 return B.CreateCall(
CGM.getIntrinsic(llvm::Intrinsic::dx_view_id));
1768 case llvm::dxbc::PSV::SemanticKind::StartInstanceLocation:
1769 assert(Stage == llvm::Triple::Vertex &&
1770 "SV_StartInstanceLocation is in an unavailable stage and should "
1771 "have been diagnosed by Sema");
1772 if (
CGM.getTarget().getTriple().isSPIRV())
1774 Semantic->getAttrName()->getName(),
1775 llvm::hlsl::SPIRVInterfaceDecoration::BuiltIn,
1777 if (
CGM.getTarget().getTriple().isDXIL())
1778 return B.CreateCall(
1779 CGM.getIntrinsic(llvm::Intrinsic::dx_start_instance_location));
1786 "Load hasn't been implemented yet for this system semantic. FIXME");
1791 HLSLAppliedSemanticAttr *Semantic,
1793 llvm::Triple::EnvironmentType Stage, std::optional<unsigned> Index,
1796 case llvm::dxbc::PSV::SemanticKind::Position:
1797 assert(llvm::is_contained({llvm::Triple::Vertex, llvm::Triple::Hull,
1798 llvm::Triple::Domain, llvm::Triple::Geometry,
1799 llvm::Triple::Mesh},
1801 "SV_Position is in an unavailable stage and should have been "
1802 "diagnosed by Sema");
1803 assert(Stage != llvm::Triple::Hull && Stage != llvm::Triple::Domain &&
1804 Stage != llvm::Triple::Geometry && Stage != llvm::Triple::Mesh &&
1805 "FIXME: storing SV_Position is not yet implemented for this "
1807 if (
CGM.getTarget().getTriple().isDXIL()) {
1808 emitDXILUserSemanticStore(B, Source,
Decl, Semantic, Index, Signature);
1811 if (
CGM.getTarget().getTriple().isSPIRV()) {
1813 Semantic->getAttrName()->getName(),
1814 llvm::hlsl::SPIRVInterfaceDecoration::BuiltIn,
1819 case llvm::dxbc::PSV::SemanticKind::Target:
1820 assert(Stage == llvm::Triple::Pixel &&
1821 "SV_Target is in an unavailable stage and should have been "
1822 "diagnosed by Sema");
1823 emitUserSemanticStore(B, Source,
Decl, Semantic, Index, Signature,
1826 case llvm::dxbc::PSV::SemanticKind::ShadingRate:
1827 assert(llvm::is_contained({llvm::Triple::Vertex, llvm::Triple::Hull,
1828 llvm::Triple::Domain, llvm::Triple::Geometry,
1829 llvm::Triple::Mesh},
1831 "SV_ShadingRate is in an unavailable stage and should have been "
1832 "diagnosed by Sema");
1833 assert(Stage != llvm::Triple::Hull && Stage != llvm::Triple::Domain &&
1834 Stage != llvm::Triple::Geometry && Stage != llvm::Triple::Mesh &&
1835 "FIXME: storing SV_ShadingRate is not yet implemented for this "
1837 if (
CGM.getTarget().getTriple().isDXIL()) {
1838 emitDXILUserSemanticStore(B, Source,
Decl, Semantic, Index, Signature);
1841 if (
CGM.getTarget().getTriple().isSPIRV()) {
1845 Semantic->getAttrName()->getName(),
1846 llvm::hlsl::SPIRVInterfaceDecoration::BuiltIn,
1848 llvm::hlsl::InterpolationMode::Undefined);
1857 "Store hasn't been implemented yet for this system semantic. FIXME");
1865 std::optional<unsigned> Index = Semantic->getSemanticIndex();
1867 llvm::hlsl::getSemanticKind(Semantic->getAttrName()->getName());
1868 const auto *ShaderAttr = FD->
getAttr<HLSLShaderAttr>();
1869 assert(ShaderAttr &&
"Entry point has no shader attribute");
1870 llvm::hlsl::SemanticInterpretation Interpretation =
1871 llvm::hlsl::getInterpretationKind(
SemanticKind, ShaderAttr->getType(),
1872 llvm::hlsl::IOType::In);
1873 assert(Interpretation != llvm::hlsl::SemanticInterpretation::Invalid &&
1874 "invalid semantic should have been diagnosed by Sema");
1875 if (
CGM.getTarget().getTriple().isSPIRV())
1877 InterpMode,
Type, ShaderAttr->getType(), llvm::hlsl::IOType::In);
1878 if (Interpretation == llvm::hlsl::SemanticInterpretation::Arbitrary)
1879 return emitUserSemanticLoad(B,
Type,
Decl, Semantic, Index, Signature,
1882 ShaderAttr->getType(), Index, Signature,
1887 IRBuilder<> &B,
const FunctionDecl *FD, llvm::Value *Source,
1890 std::optional<unsigned> Index = Semantic->getSemanticIndex();
1892 llvm::hlsl::getSemanticKind(Semantic->getAttrName()->getName());
1893 const auto *ShaderAttr = FD->
getAttr<HLSLShaderAttr>();
1894 assert(ShaderAttr &&
"Entry point has no shader attribute");
1896 llvm::hlsl::SemanticInterpretation Interpretation =
1897 llvm::hlsl::getInterpretationKind(
SemanticKind, ShaderAttr->getType(),
1898 llvm::hlsl::IOType::Out);
1899 assert(Interpretation != llvm::hlsl::SemanticInterpretation::Invalid &&
1900 "invalid semantic should have been diagnosed by Sema");
1901 if (
CGM.getTarget().getTriple().isSPIRV())
1903 ShaderAttr->getType(),
1904 llvm::hlsl::IOType::Out);
1906 if (Interpretation == llvm::hlsl::SemanticInterpretation::Arbitrary)
1907 return emitUserSemanticStore(B, Source,
Decl, Semantic, Index, Signature,
1910 ShaderAttr->getType(), Index, Signature, InterpMode);
1913std::pair<llvm::Value *, specific_attr_iterator<HLSLAppliedSemanticAttr>>
1920 llvm::hlsl::InterpolationModifier Modifiers) {
1928 for (
unsigned I = 0; I < ST->getNumElements(); ++I) {
1929 auto [ChildValue, NextAttr] =
1931 AttrEnd, Signature, Modifiers);
1932 AttrBegin = NextAttr;
1938 return std::make_pair(
Aggregate, AttrBegin);
1943 IRBuilder<> &B,
const FunctionDecl *FD, llvm::Value *Source,
1948 llvm::hlsl::InterpolationModifier Modifiers) {
1956 RD =
Decl->getType()->getAsRecordDecl();
1962 for (
unsigned I = 0; I < ST->getNumElements(); ++I, ++
FieldDecl) {
1963 llvm::Value *Extract = B.CreateExtractValue(Source, I);
1965 AttrEnd, Signature, Modifiers);
1971std::pair<llvm::Value *, specific_attr_iterator<HLSLAppliedSemanticAttr>>
1978 llvm::hlsl::InterpolationModifier Modifiers) {
1979 assert(AttrBegin != AttrEnd);
1982 if (
const auto *A =
Decl->getAttr<HLSLInterpolationModifierAttr>())
1984 static_cast<llvm::hlsl::InterpolationModifier
>(A->getModifiers());
1985 if (
Type->isStructTy())
1987 Signature, Modifiers);
1989 HLSLAppliedSemanticAttr *
Attr = *AttrBegin;
1991 size_t PreviousSize = Signature.size();
1992 auto InterpMode = llvm::hlsl::getInterpolationMode(Modifiers);
1993 llvm::Value *
Value =
1997 if (Signature.size() != PreviousSize) {
1998 auto &Element = Signature.back();
1999 Element.InterpMode = llvm::hlsl::normalizeInterpolationMode(
2000 InterpMode, Element.CompType, Element.SemanticKind,
2001 FD->
getAttr<HLSLShaderAttr>()->getType(), llvm::hlsl::IOType::In);
2003 return std::make_pair(
Value, AttrBegin);
2008 IRBuilder<> &B,
const FunctionDecl *FD, llvm::Value *Source,
2013 llvm::hlsl::InterpolationModifier Modifiers) {
2014 assert(AttrBegin != AttrEnd);
2016 if (
const auto *A =
Decl->getAttr<HLSLInterpolationModifierAttr>())
2018 static_cast<llvm::hlsl::InterpolationModifier
>(A->getModifiers());
2019 if (Source->getType()->isStructTy())
2021 Signature, Modifiers);
2023 HLSLAppliedSemanticAttr *
Attr = *AttrBegin;
2025 size_t PreviousSize = Signature.size();
2026 auto InterpMode = llvm::hlsl::getInterpolationMode(Modifiers);
2028 if (Signature.size() != PreviousSize) {
2029 auto &Element = Signature.back();
2030 Element.InterpMode = llvm::hlsl::normalizeInterpolationMode(
2031 InterpMode, Element.CompType, Element.SemanticKind,
2032 FD->
getAttr<HLSLShaderAttr>()->getType(), llvm::hlsl::IOType::Out);
2038 llvm::Function *Fn) {
2042 llvm::Module &M =
CGM.getModule();
2043 llvm::LLVMContext &Ctx = M.getContext();
2044 auto *EntryTy = llvm::FunctionType::get(llvm::Type::getVoidTy(Ctx),
false);
2046 Function::Create(EntryTy, Function::ExternalLinkage, FD->
getName(), &M);
2050 AttributeList NewAttrs = AttributeList::get(Ctx, AttributeList::FunctionIndex,
2051 Fn->getAttributes().getFnAttrs());
2052 EntryFn->setAttributes(NewAttrs);
2056 Fn->setLinkage(GlobalValue::InternalLinkage);
2058 BasicBlock *BB = BasicBlock::Create(Ctx,
"entry", EntryFn);
2063 if (
CGM.shouldEmitConvergenceTokens()) {
2064 assert(EntryFn->isConvergent());
2066 B.CreateIntrinsic(llvm::Intrinsic::experimental_convergence_entry, {});
2067 llvm::Value *bundleArgs[] = {I};
2068 OB.emplace_back(
"convergencectrl", bundleArgs);
2073 unsigned SRetOffset = 0;
2074 for (
const auto &Param : Fn->args()) {
2075 if (Param.hasStructRetAttr()) {
2077 llvm::Type *VarType = Param.getParamStructRetType();
2079 CGM.getLangOpts().EmitLogicalPointer
2082 OutputSemantic.push_back(std::make_pair(Var, VarType));
2083 Args.push_back(Var);
2088 llvm::Value *SemanticValue =
nullptr;
2090 if ([[maybe_unused]] HLSLParamModifierAttr *MA =
2091 PD->
getAttr<HLSLParamModifierAttr>()) {
2092 llvm_unreachable(
"Not handled yet");
2094 llvm::Type *ParamType =
nullptr;
2095 if (Param.hasByValAttr())
2096 ParamType = Param.getParamByValType();
2098 ParamType =
CGM.getTypes().ConvertType(PD->
getType());
2100 ParamType = Param.getType();
2106 SemanticValue =
Result.first;
2111 CGM.getLangOpts().EmitLogicalPointer
2114 B.CreateStore(SemanticValue, Var);
2115 SemanticValue = Var;
2119 assert(SemanticValue);
2120 Args.push_back(SemanticValue);
2123 CallInst *CI = B.CreateCall(FunctionCallee(Fn), Args, OB);
2124 CI->setCallingConv(Fn->getCallingConv());
2126 if (Fn->getReturnType() !=
CGM.VoidTy)
2128 OutputSemantic.push_back(std::make_pair(CI,
nullptr));
2130 for (
auto &SourcePair : OutputSemantic) {
2131 llvm::Value *Source = SourcePair.first;
2132 llvm::Type *ElementType = SourcePair.second;
2133 AllocaInst *AI = dyn_cast<AllocaInst>(Source);
2134 llvm::Value *SourceValue = AI ? B.CreateLoad(ElementType, Source) : Source;
2146 if (
const auto *RSAttr = dyn_cast<RootSignatureAttr>(
Attr)) {
2147 auto *RSDecl = RSAttr->getSignatureDecl();
2148 addRootSignatureMD(RSDecl->getVersion(), RSDecl->getRootElements(),
2153 if (
CGM.getTarget().getTriple().isDXIL()) {
2158 auto Mode =
CGM.getCodeGenOpts().getHLSLSemanticSignaturePacking();
2159 for (
auto IOTy : {llvm::hlsl::IOType::In, llvm::hlsl::IOType::Out}) {
2160 bool IsOutput = IOTy == llvm::hlsl::IOType::Out;
2161 auto &Signature = IsOutput ? OutputSignature : InputSignature;
2162 auto Packed = packSemanticSignature(Signature, Stage, IOTy, Mode,
2163 CGM.getLangOpts().NativeHalfType);
2166 diag::err_hlsl_signature_packing)
2167 << IsOutput << llvm::toString(
Packed.takeError());
2171 if (Mode != PackingMode::Default &&
2172 CGM.getTarget().getTriple().getEnvironment() !=
2173 llvm::Triple::Library &&
2174 ((Stage == llvm::Triple::Vertex && !IsOutput) ||
2175 (Stage == llvm::Triple::Pixel && IsOutput)))
2177 diag::warn_hlsl_signature_packing_ignored)
2178 << (Mode == PackingMode::Optimized ?
"optimized" :
"prefix-stable")
2183 addSemanticSignatureMD(InputSignature, OutputSignature, EntryFn, M);
2189 M.getNamedGlobal(CtorOrDtor ?
"llvm.global_ctors" :
"llvm.global_dtors");
2192 const auto *CA = dyn_cast<ConstantArray>(GV->getInitializer());
2199 for (
const auto &Ctor : CA->operands()) {
2205 "HLSL doesn't support setting priority for global ctors.");
2207 "HLSL doesn't support COMDat for global ctors.");
2213 llvm::Module &M =
CGM.getModule();
2222 for (
auto &F : M.functions()) {
2223 if (!F.hasFnAttribute(
"hlsl.shader"))
2226 Instruction *IP = &*F.getEntryBlock().begin();
2229 llvm::Value *bundleArgs[] = {
Token};
2230 OB.emplace_back(
"convergencectrl", bundleArgs);
2231 IP =
Token->getNextNode();
2234 for (
auto *Fn : CtorFns) {
2235 auto CI = B.CreateCall(FunctionCallee(Fn), {}, OB);
2236 CI->setCallingConv(Fn->getCallingConv());
2240 B.SetInsertPoint(F.back().getTerminator());
2241 for (
auto *Fn : DtorFns) {
2242 auto CI = B.CreateCall(FunctionCallee(Fn), {}, OB);
2243 CI->setCallingConv(Fn->getCallingConv());
2249 Triple
T(M.getTargetTriple());
2250 if (
T.getEnvironment() != Triple::EnvironmentType::Library) {
2251 if (
auto *GV = M.getNamedGlobal(
"llvm.global_ctors"))
2252 GV->eraseFromParent();
2253 if (
auto *GV = M.getNamedGlobal(
"llvm.global_dtors"))
2254 GV->eraseFromParent();
2259 Intrinsic::ID IntrID,
2263 llvm::Function *InitResFunc =
2264 llvm::Function::Create(llvm::FunctionType::get(CGM.
VoidTy,
false),
2265 llvm::GlobalValue::InternalLinkage,
2266 "_init_buffer_" + GV->getName(), CGM.
getModule());
2267 InitResFunc->addFnAttr(llvm::Attribute::AlwaysInline);
2269 llvm::BasicBlock *EntryBB =
2270 llvm::BasicBlock::Create(Ctx,
"entry", InitResFunc);
2272 const DataLayout &DL = CGM.
getModule().getDataLayout();
2273 Builder.SetInsertPoint(EntryBB);
2276 llvm::Type *HandleTy = GV->getValueType();
2277 assert(HandleTy->isTargetExtTy() &&
"unexpected type of the buffer global");
2279 llvm::Value *CreateHandle = Builder.CreateIntrinsic(
2280 HandleTy, IntrID, Args,
nullptr,
2281 Twine(GV->getName()).concat(
"_h"));
2283 Builder.CreateAlignedStore(CreateHandle, GV, GV->getPointerAlignment(DL));
2284 Builder.CreateRetVoid();
2289void CGHLSLRuntime::initializeBufferFromBinding(
const HLSLBufferDecl *BufDecl,
2290 llvm::GlobalVariable *GV) {
2291 ResourceBindingAttrs Binding(BufDecl);
2293 "cbuffer/tbuffer should always have resource binding attribute");
2295 auto *Index = llvm::ConstantInt::get(
CGM.IntTy, 0);
2296 auto *RangeSize = llvm::ConstantInt::get(
CGM.IntTy, 1);
2297 auto *Space = llvm::ConstantInt::get(
CGM.IntTy, Binding.
getSpace());
2302 llvm::Intrinsic::ID IntrinsicID =
2303 CGM.getHLSLRuntime().getCreateHandleFromBindingIntrinsic();
2304 auto *RegSlot = llvm::ConstantInt::get(
CGM.IntTy, Binding.
getSlot());
2305 SmallVector<Value *> Args{Space, RegSlot, RangeSize, Index, Name};
2309 llvm::Intrinsic::ID IntrinsicID =
2310 CGM.getHLSLRuntime().getCreateHandleFromImplicitBindingIntrinsic();
2313 SmallVector<Value *> Args{OrderID, Space, RangeSize, Index, Name};
2319 llvm::GlobalVariable *GV) {
2320 if (
auto Attr = VD->
getAttr<HLSLVkExtBuiltinInputAttr>())
2322 GV, llvm::hlsl::SPIRVInterfaceDecoration::BuiltIn,
Attr->getBuiltIn());
2323 if (
auto Attr = VD->
getAttr<HLSLVkExtBuiltinOutputAttr>())
2325 GV, llvm::hlsl::SPIRVInterfaceDecoration::BuiltIn,
Attr->getBuiltIn());
2329 if (!
CGM.shouldEmitConvergenceTokens())
2333 for (
auto I = BB.begin(); I != E; ++I) {
2334 auto *II = dyn_cast<llvm::IntrinsicInst>(&*I);
2335 if (II && llvm::isConvergenceControlIntrinsic(II->getIntrinsicID())) {
2339 llvm_unreachable(
"Convergence token should have been emitted.");
2376 for (
auto *OVE : Visitor.
OVEs) {
2379 if (OpaqueValueMappingData::shouldBindAsLValue(OVE)) {
2381 OpaqueValueMappingData::bind(CGF, OVE, LV);
2384 OpaqueValueMappingData::bind(CGF, OVE, RV);
2393 "expected resource array subscript expression");
2398 const VarDecl *ArrayDecl = dyn_cast_or_null<VarDecl>(
2402 return std::nullopt;
2408 "expected array of resource classes");
2414 Value *Index =
nullptr;
2416 while (ASE !=
nullptr) {
2418 if (
const auto *ArrayTy =
2420 Value *Multiplier = llvm::ConstantInt::get(
2422 SubIndex = CGF.
Builder.CreateMul(SubIndex, Multiplier);
2424 Index = Index ? CGF.
Builder.CreateAdd(Index, SubIndex) : SubIndex;
2432 "resource array must have a binding attribute");
2453 llvm::Value *Range = llvm::ConstantInt::getSigned(
2454 CGM.IntTy, getTotalArraySize(AST, ResArrayTy));
2458 if (ResultTy == ResourceTy) {
2460 CXXMethodDecl *CreateMethod = lookupResourceInitMethodAndSetupArgs(
2462 ArrayDecl->
getName(), Binding, Args);
2464 if (!CreateMethod) {
2469 "create method lookup should always succeed for built-in resource "
2471 return std::nullopt;
2474 callResourceInitMethod(CGF, CreateMethod, Args, ValueSlot.getAddress());
2481 std::optional<llvm::Value *> EndIndex = initializeResourceArrayFromGlobal(
2483 ArrayDecl->
getName(), Binding, {llvm::ConstantInt::get(CGM.IntTy, 0)});
2485 return std::nullopt;
2491bool CGHLSLRuntime::initializeGlobalResourceArray(
CodeGenFunction &CGF,
2497 "expected global non-static resource array");
2503 "resource array must have a binding attribute");
2508 const auto *ResArrayTy =
2512 int Size = getTotalArraySize(AST, ResArrayTy);
2513 llvm::Value *
Zero = llvm::ConstantInt::get(
CGM.
IntTy, 0);
2514 llvm::Value *Range = llvm::ConstantInt::get(
CGM.
IntTy, Size);
2517 std::optional<llvm::Value *> EndIndex = initializeResourceArrayFromGlobal(
2519 ArrayDecl->
getName(), Binding, {Zero});
2520 return EndIndex.has_value();
2529 "expected resource array");
2534 dyn_cast_or_null<VarDecl>(getArrayDecl(CGF.
CGM.
getContext(), E));
2539 return initializeGlobalResourceArray(CGF, ArrayDecl, DestSlot);
2546std::optional<LValue>
2550 "expected resource array declaration");
2554 return std::nullopt;
2558 if (initializeGlobalResourceArray(CGF, ArrayDecl, TmpArraySlot))
2561 return std::nullopt;
2569 "expected cbuffer matrix");
2580 HLSLBufferCopyEmitter(CGF, DestAlloca, SrcAddr).emitCopy(MatQualTy);
2586 llvm::function_ref<llvm::Value *(
bool Promote)> EmitIdxAfterBase) {
2590 llvm::Type *LayoutTy =
2592 uint64_t LayoutSizeInBits =
2593 CGM.getDataLayout().getTypeSizeInBits(LayoutTy).getFixedValue();
2596 if (RowAlignedSize > ElementSize) {
2597 llvm::Type *Padding =
CGM.getTargetCodeGenInfo().getHLSLPadding(
2598 CGM, RowAlignedSize - ElementSize);
2599 assert(Padding &&
"No padding type for target?");
2600 LayoutTy = llvm::StructType::get(CGF.
getLLVMContext(), {LayoutTy, Padding},
2607 if (LayoutTy == OrigTy)
2608 return std::nullopt;
2617 llvm::Value *Idx = EmitIdxAfterBase(
true);
2618 Indices.push_back(Idx);
2619 Indices.push_back(llvm::ConstantInt::get(CGF.
Int32Ty, 0));
2625 assert(CE->
getCastKind() == CastKind::CK_ArrayToPointerDecay);
2629 LayoutTy = llvm::ArrayType::get(
2633 LayoutTy,
Addr.emitRawPointer(CGF), Indices,
"cbufferidx"));
2642 Indices,
"cbufferidx");
2647std::optional<LValue>
2652 "expected resource member expression");
2655 findAssociatedResourceDeclForStruct(CGF.
CGM.
getContext(), ME);
2657 return std::nullopt;
2663 GlobalVariable *ResGV =
2665 const DataLayout &DL =
CGM.getDataLayout();
2666 llvm::Type *Ty = ResGV->getValueType();
2679 "expected expression in HLSL constant address space");
2682 "direct accesses to resource types should be handled separately");
2694 return HLSLBufferCopyEmitter(CGF, DstPtr, SrcPtr).emitCopy(Ty);
2700 const VarDecl *VD = findStructResourceParentDeclAndBuildName(E, NameBuilder);
2701 AssociatedResourcesList AssociatedResources(VD, NameBuilder.
getName());
2705 const VarDecl *ResDecl = AssociatedResources.getNextResource();
2706 assert(ResDecl &&
"associated resource declaration not found");
2709 [[maybe_unused]] llvm::Type *DestType =
2710 ResSlot.getAddress().getElementType();
2711 [[maybe_unused]] llvm::Type *SrcConvertedType =
2712 CGM.getTypes().ConvertTypeForMem(ResDecl->
getType());
2713 assert(DestType == SrcConvertedType &&
"resource slot type mismatch");
2716 copyGlobalResource(CGF, ResDecl, ResSlot);
2718 initializeGlobalResourceArray(CGF, ResDecl, ResSlot);
2722 HLSLBufferCopyEmitter(CGF, DstPtr, SrcPtr).emitCopy(Ty, EmitResFn);
2723 assert(AssociatedResources.getNextResource() ==
nullptr &&
2724 "expected all associated resources to be processed");
2733 assert(Field &&
"Unexpected access into HLSL buffer");
2738 QualType RecType =
CGM.getContext().getCanonicalTagType(Rec);
2749 CGM.getTypes().getCGRecordLayout(Rec).getLLVMFieldNo(Field);
2750 assert(FieldIdx < LayoutTy->getNumElements() &&
2751 "Layout struct is smaller than member struct");
2752 unsigned Skipped = 0;
2753 for (
unsigned I = 0; I <= FieldIdx;) {
2754 llvm::Type *ElementTy = LayoutTy->getElementType(I + Skipped);
2760 FieldIdx += Skipped;
2761 assert(FieldIdx < LayoutTy->getNumElements() &&
"Access out of bounds");
2765 QualType FieldType = Field->getType();
2766 llvm::Type *FieldLLVMTy =
CGM.getTypes().ConvertTypeForMem(FieldType);
2771 ? CGF.
Builder.CreateStructuredGEP(
2772 LayoutTy,
Base.getPointer(CGF),
2773 llvm::ConstantInt::get(
CGM.IntTy, FieldIdx))
2775 FieldIdx, Field->getName());
2780 CGM.getTBAAAccessInfo(FieldType));
Defines the clang::ASTContext interface.
static bool requiresFlatInterpolation(llvm::Type *Ty)
static llvm::dxil::ElementType getSignatureComponentType(CodeGenModule &CGM, QualType Ty)
static QualType getSemanticLeafType(const clang::DeclaratorDecl *Decl)
static void addSPIRVInterfaceDecorations(llvm::GlobalVariable *GV, llvm::hlsl::SPIRVInterfaceDecoration Decoration, unsigned Operand, llvm::hlsl::InterpolationMode InterpMode=llvm::hlsl::InterpolationMode::Undefined)
static llvm::hlsl::SemanticSignatureElement createSemanticSignatureElement(CodeGenModule &CGM, uint32_t SigId, HLSLAppliedSemanticAttr *Semantic, std::optional< unsigned > Index, const SemanticShape &Shape)
static void gatherFunctions(SmallVectorImpl< Function * > &Fns, llvm::Module &M, bool CtorOrDtor)
static llvm::Value * createSPIRVInputLoad(IRBuilder<> &B, llvm::Module &M, llvm::Type *Ty, const Twine &Name, llvm::hlsl::SPIRVInterfaceDecoration Decoration, unsigned Operand, llvm::hlsl::InterpolationMode InterpMode)
static llvm::hlsl::InterpolationMode getSPIRVInterpolationMode(llvm::hlsl::InterpolationMode InterpMode, llvm::Type *Ty, llvm::Triple::EnvironmentType Stage, llvm::hlsl::IOType IO)
static void createSPIRVOutputStore(IRBuilder<> &B, llvm::Module &M, llvm::Value *Source, const Twine &Name, llvm::hlsl::SPIRVInterfaceDecoration Decoration, unsigned Operand, llvm::hlsl::InterpolationMode InterpMode)
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 SemanticShape getSemanticShape(ASTContext &Ctx, QualType Ty)
Result
Implement __builtin_bit_cast and related operations.
llvm::MachO::Record Record
Defines AST-level helper utilities for matrix types.
llvm::dxbc::PSV::SemanticKind SemanticKind
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()
const ConstantArrayType * getAsConstantArrayType(QualType T) const
QualType getPointerType(QualType T) const
Return the uniqued reference to the type for a pointer to the specified type.
const LangOptions & getLangOpts() const
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
static uint64_t getConstantArrayElementCount(const ConstantArrayType *CA)
Return number of (potentially nested) constant array elements.
QualType getExtVectorType(QualType VectorType, unsigned NumElts) const
Return the unique reference to an extended vector type of the specified element type and size.
QualType getHLSLAttributedResourceType(QualType Wrapped, QualType Contained, const HLSLAttributedResourceType::Attributes &Attrs)
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.
This class is used for builtin types like 'int'.
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
This is an opaque type for sizes expressed in character units.
CharUnits alignTo(CharUnits Align) const
Returns the next integer (mod 2**64) that is greater than or equal to this quantity and is a multiple...
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)
Construct a CharUnits quantity from a raw integer type.
HLSLSemanticSignaturePackingMode
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.
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="")
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)
llvm::Value * handleScalarSemanticLoad(llvm::IRBuilder<> &B, const FunctionDecl *FD, llvm::Type *Type, const clang::DeclaratorDecl *Decl, HLSLAppliedSemanticAttr *Semantic, SemanticSignatures &Signature, llvm::hlsl::InterpolationMode InterpMode)
llvm::StructType * getHLSLBufferLayoutType(const RecordType *LayoutStructTy)
void emitEntryFunction(const FunctionDecl *FD, llvm::Function *Fn)
void handleGlobalVarDefinition(const VarDecl *VD, llvm::GlobalVariable *Var)
void handleScalarSemanticStore(llvm::IRBuilder<> &B, const FunctionDecl *FD, llvm::Value *Source, const clang::DeclaratorDecl *Decl, HLSLAppliedSemanticAttr *Semantic, SemanticSignatures &Signature, llvm::hlsl::InterpolationMode InterpMode)
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, SemanticSignatures &Signature, llvm::hlsl::InterpolationModifier Modifiers)
llvm::SmallVectorImpl< llvm::hlsl::SemanticSignatureElement > SemanticSignatures
void addHLSLBufferLayoutType(const RecordType *LayoutStructTy, llvm::StructType *LayoutTy)
std::optional< LValue > emitGlobalResourceArrayAsLValue(CodeGenFunction &CGF, const VarDecl *ArrayDecl)
void emitSystemSemanticStore(llvm::IRBuilder<> &B, llvm::Value *Source, const clang::DeclaratorDecl *Decl, HLSLAppliedSemanticAttr *Semantic, llvm::dxbc::PSV::SemanticKind SemanticKind, llvm::Triple::EnvironmentType Stage, std::optional< unsigned > Index, SemanticSignatures &Signature, llvm::hlsl::InterpolationMode InterpMode)
bool emitBufferCopy(CodeGenFunction &CGF, const Expr *E, const LValue &SrcLV, AggValueSlot &DestSlot)
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)
llvm::Value * emitSystemSemanticLoad(llvm::IRBuilder<> &B, llvm::Type *Type, const clang::DeclaratorDecl *Decl, HLSLAppliedSemanticAttr *Semantic, llvm::dxbc::PSV::SemanticKind SemanticKind, llvm::Triple::EnvironmentType Stage, std::optional< unsigned > Index, SemanticSignatures &Signature, llvm::hlsl::InterpolationMode InterpMode)
llvm::Type * convertHLSLSpecificType(const Type *T, const CGHLSLOffsetInfo &OffsetInfo)
RawAddress createBufferMatrixTempAddress(const LValue &LV, CodeGenFunction &CGF)
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, SemanticSignatures &Signature, llvm::hlsl::InterpolationModifier Modifiers=llvm::hlsl::InterpolationModifier::None)
void addBuffer(const HLSLBufferDecl *D)
void generateGlobalCtorDtorCalls()
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, SemanticSignatures &Signature, llvm::hlsl::InterpolationModifier Modifiers)
bool emitGlobalResourceArray(CodeGenFunction &CGF, const Expr *E, AggValueSlot &DestSlot)
void emitInitListOpaqueValues(CodeGenFunction &CGF, InitListExpr *E)
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, SemanticSignatures &Signature, llvm::hlsl::InterpolationModifier Modifiers=llvm::hlsl::InterpolationModifier::None)
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
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
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()
void EmitTopLevelDecl(Decl *D)
Emit code for a single top level declaration.
ConstantAddress GetAddrOfConstantCString(const std::string &Str, StringRef GlobalName=".str")
Returns a pointer to a character array containing the literal and a terminating '\0' character.
const CGFunctionInfo & arrangeFreeFunctionCall(const CallArgList &Args, const FunctionType *Ty, bool ChainCall, const FunctionDecl *ABIInfoFD)
Figure out the rules for calling a function with the given formal type using the given arguments.
llvm::Type * ConvertTypeForMem(QualType T)
ConvertTypeForMem - Convert type T into a llvm::Type.
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.
Represents a concrete matrix type with constant number of rows and columns.
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.
SourceLocation getLocation() const
specific_attr_iterator< T > specific_attr_end() const
specific_attr_iterator< T > specific_attr_begin() const
Represents a ValueDecl that came out of a declarator.
This represents one expression.
Expr * IgnoreParenImpCasts() LLVM_READONLY
Skip past any parentheses and implicit casts which might surround this expression until reaching a fi...
std::optional< llvm::APSInt > getIntegerConstantExpr(const ASTContext &Ctx, bool AllowRelaxedEval=false) 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.
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.
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
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 isSignedIntegerOrEnumerationType() const
Determines whether this is an integer type that is signed or an enumeration types whose underlying ty...
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 isHLSLIntangibleType() 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
bool hasBooleanRepresentation() const
Determine whether this type has a boolean representation – i.e., it is a boolean type,...
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.
Represents a GCC generic vector type.
void pushName(llvm::StringRef N)
void pushArrayIndex(uint64_t Index)
llvm::StringRef getName() const
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.
@ Macros
Canonicalize -D and -U options.
bool hasCounterHandle(const CXXRecordDecl *RD)
StringRef getName(const HeaderType T)
@ Address
A pointer to a ValueDecl.
bool Load(InterpState &S, CodePtr OpPC)
Top level wrappers for InstallAPI frontend operations.
bool isa(CodeGen::Address addr)
CustomizableOptional< FileEntryRef > OptionalFileEntryRef
bool isMatrixRowMajor(const LangOptions &LangOpts, QualType T)
Returns true if matrices of T should be laid out in row-major order.
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.
const FunctionProtoType * T
U cast(CodeGen::Address addr)
Diagnostic wrappers for TextAPI types for error reporting.
__builtin_bitreverse32 uint32_t __builtin_riscv_aaddu_u32 __builtin_riscv_asubu_u32 __builtin_elementwise_add_sat __builtin_elementwise_sub_sat int32_t uint32_t uint32_t __builtin_riscv_mhacc_i32 __builtin_riscv_mhaccu_u32 __builtin_riscv_mhaccsu_i32 __builtin_riscv_mulq_i32 __builtin_riscv_mqwacc_i64 uint8_t
llvm::IntegerType * Int32Ty
llvm::IntegerType * IntTy
int
unsigned getImplicitOrderID() const
bool hasCounterImplicitOrderID() const
unsigned getSpace() const
unsigned getCounterImplicitOrderID() const