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"
62using llvm::hlsl::CBufferRowSizeInBytes;
66void addDxilValVersion(StringRef ValVersionStr, llvm::Module &M) {
70 if (Version.tryParse(ValVersionStr) || Version.getBuild() ||
71 Version.getSubminor() || !Version.getMinor()) {
75 uint64_t Major = Version.getMajor();
76 uint64_t Minor = *Version.getMinor();
78 auto &Ctx = M.getContext();
79 IRBuilder<> B(M.getContext());
80 MDNode *Val = MDNode::get(Ctx, {ConstantAsMetadata::get(B.getInt32(Major)),
81 ConstantAsMetadata::get(B.getInt32(Minor))});
82 StringRef DXILValKey =
"dx.valver";
83 auto *DXILValMD = M.getOrInsertNamedMetadata(DXILValKey);
84 DXILValMD->addOperand(Val);
87void addRootSignatureMD(llvm::dxbc::RootSignatureVersion RootSigVer,
89 llvm::Function *Fn, llvm::Module &M) {
90 auto &Ctx = M.getContext();
92 llvm::hlsl::rootsig::MetadataBuilder RSBuilder(Ctx, Elements);
93 MDNode *RootSignature = RSBuilder.BuildRootSignature();
95 ConstantAsMetadata *Version = ConstantAsMetadata::get(ConstantInt::get(
96 llvm::Type::getInt32Ty(Ctx), llvm::to_underlying(RootSigVer)));
97 ValueAsMetadata *EntryFunc =
Fn ? ValueAsMetadata::get(Fn) :
nullptr;
98 MDNode *MDVals = MDNode::get(Ctx, {EntryFunc, RootSignature, Version});
100 StringRef RootSignatureValKey =
"dx.rootsignatures";
101 auto *RootSignatureValMD = M.getOrInsertNamedMetadata(RootSignatureValKey);
102 RootSignatureValMD->addOperand(MDVals);
107 GlobalVariable *ResGV =
109 assert(ResGV &&
"expected valid global variable");
126static const VarDecl *findStructResourceParentDeclAndBuildName(
133 if (
const auto *DRE = dyn_cast<DeclRefExpr>(E)) {
135 "member expr base is not a var decl");
141 WorkList.push_back(E);
142 if (
const auto *MExp = dyn_cast<MemberExpr>(E))
144 else if (
const auto *ICE = dyn_cast<ImplicitCastExpr>(E))
145 E = ICE->getSubExpr();
146 else if (
const auto *ASE = dyn_cast<ArraySubscriptExpr>(E))
153 llvm_unreachable(
"unexpected expr type in resource member access");
155 assert(E &&
"expected valid expression");
158 while (!WorkList.empty()) {
159 E = WorkList.pop_back_val();
160 if (
const auto *ME = dyn_cast<MemberExpr>(E)) {
162 ME->getMemberNameInfo().getName().getAsIdentifierInfo()->getName());
163 }
else if (
const auto *ICE = dyn_cast<ImplicitCastExpr>(E)) {
164 if (ICE->getCastKind() == CK_UncheckedDerivedToBase) {
166 ICE->getSubExpr()->getType()->getAsCXXRecordDecl();
167 CXXRecordDecl *BaseRD = ICE->getType()->getAsCXXRecordDecl();
170 }
else if (
const auto *ASE = dyn_cast<ArraySubscriptExpr>(E)) {
171 const Expr *IdxExpr = ASE->getIdx();
172 std::optional<llvm::APSInt>
Value =
175 "expected constant index in struct with resource array access");
178 llvm_unreachable(
"unexpected expr type in resource member access");
192 findStructResourceParentDeclAndBuildName(ME, NameBuilder);
201 if (
const auto *ADA = dyn_cast<HLSLAssociatedResourceDeclAttr>(A)) {
202 VarDecl *AssocResVD = ADA->getResDecl();
214 auto &Ctx = M.getContext();
217 llvm::NamedMDNode *DXContents =
218 M.getOrInsertNamedMetadata(
"dx.source.contents");
219 auto addFile = [&](
const std::pair<StringRef, StringRef> &NameContent) {
220 llvm::MDTuple *FileInfo =
221 llvm::MDNode::get(Ctx, {llvm::MDString::get(Ctx, NameContent.first),
222 llvm::MDString::get(Ctx, NameContent.second)});
223 DXContents->addOperand(FileInfo);
228 &SM.getSLocEntry(SM.getMainFileID(), &
Invalid);
229 assert(!
Invalid &&
"Main file SLocEntry must not be invalid!");
234 std::optional<SmallString<256>> MainFileName;
235 Files.reserve(SM.local_sloc_entry_size());
236 for (
unsigned I : llvm::seq(SM.local_sloc_entry_size())) {
251 llvm::sys::path::native(Path);
255 SM.getDiagnostics().Report(diag::warn_hlsl_failed_to_embed_source)
260 if (&MainCCEntry != &CCEntry) {
261 Files.emplace_back(Path, Buffer->getBuffer());
264 addFile(std::make_pair(Path, Buffer->getBuffer()));
265 MainFileName.emplace(Path);
268 assert(MainFileName &&
"Main file not found.");
273 for (
unsigned I = 1; I < Files.size(); ++I)
274 assert((Files[I - 1].first != Files[I].first) &&
275 "duplicate files in dx.source.contents");
277 llvm::for_each(Files, addFile);
280 Defines.reserve(
Macros.size());
281 for (
const auto &
Macro : Macros) {
284 Defines.emplace_back(llvm::MDString::get(Ctx,
Macro.first));
286 M.getOrInsertNamedMetadata(
"dx.source.defines")
287 ->addOperand(llvm::MDNode::get(Ctx, Defines));
289 if (!CodeGenOpts.MainFileName.empty())
290 llvm::sys::path::native(CodeGenOpts.MainFileName, *MainFileName);
291 M.getOrInsertNamedMetadata(
"dx.source.mainFileName")
293 llvm::MDNode::get(Ctx, llvm::MDString::get(Ctx, *MainFileName)));
296 Args.reserve(CodeGenOpts.HLSLParsedCommandLine.size());
297 if (!CodeGenOpts.HLSLParsedCommandLine.empty())
298 for (
const auto &Arg : llvm::drop_begin(CodeGenOpts.HLSLParsedCommandLine))
299 Args.push_back(llvm::MDString::get(Ctx, Arg));
300 M.getOrInsertNamedMetadata(
"dx.source.args")
301 ->addOperand(llvm::MDNode::get(Ctx, Args));
307 if (
const auto *DRE = dyn_cast_or_null<DeclRefExpr>(E))
308 return DRE->getDecl();
309 if (
auto *OVE = dyn_cast<OpaqueValueExpr>(E))
319 const Expr *E =
nullptr;
320 while (ASE !=
nullptr) {
324 ASE = dyn_cast<ArraySubscriptExpr>(E);
326 return getArrayDecl(AST, E);
332 assert(Ty->
isArrayType() &&
"expected array type");
338static Value *buildNameForResource(llvm::StringRef BaseName,
347 for (
auto *Method :
Record->methods()) {
348 if (Method->getStorageClass() == SC && Method->getName() == Name)
358 assert(Binding.
hasBinding() &&
"at least one binding attribute expected");
362 Value *NameStr = buildNameForResource(Name, CGM);
367 "resources with counter handle must have a binding with counter "
368 "implicit order ID");
371 auto *RegSlot = llvm::ConstantInt::get(CGM.
IntTy, Binding.
getSlot());
374 ?
"__createFromBindingWithImplicitCounter"
375 :
"__createFromBinding";
376 CreateMethod = lookupMethod(ResourceDecl, Name,
SC_Static);
383 ?
"__createFromImplicitBindingWithImplicitCounter"
384 :
"__createFromImplicitBinding";
385 CreateMethod = lookupMethod(ResourceDecl, Name,
SC_Static);
393 auto *CounterOrderID = llvm::ConstantInt::get(CGM.
IntTy, CounterBinding);
409 Args, Proto,
false,
nullptr);
412 CGF.
EmitCall(FnInfo, Callee, ReturnValue, Args,
nullptr);
421static std::optional<llvm::Value *> initializeResourceArrayFromGlobal(
424 llvm::Value *Range, llvm::Value *StartIndex, StringRef ResourceName,
428 llvm::IntegerType *IntTy = CGF.
CGM.
IntTy;
429 llvm::Value *Index = StartIndex;
430 llvm::Value *One = llvm::ConstantInt::get(IntTy, 1);
438 GEPIndices.push_back(llvm::ConstantInt::get(IntTy, 0));
443 for (uint64_t I = 0; I < ArraySize; I++) {
445 Index = CGF.
Builder.CreateAdd(Index, One);
446 GEPIndices.back() = llvm::ConstantInt::get(IntTy, I);
448 std::optional<llvm::Value *> MaybeIndex =
449 initializeResourceArrayFromGlobal(CGF, ResourceDecl, SubArrayTy,
450 ValueSlot, Range, Index,
451 ResourceName, Binding, GEPIndices);
465 for (uint64_t I = 0; I < ArraySize; I++) {
467 Index = CGF.
Builder.CreateAdd(Index, One);
468 GEPIndices.back() = llvm::ConstantInt::get(IntTy, I);
474 CXXMethodDecl *CreateMethod = lookupResourceInitMethodAndSetupArgs(
475 CGF.
CGM, ResourceDecl, Range, Index, ResourceName, Binding, Args);
483 callResourceInitMethod(CGF, CreateMethod, Args, ReturnAddress);
490class HLSLBufferCopyEmitter {
491 CodeGenFunction &CGF;
494 llvm::Type *LayoutTy =
nullptr;
496 SmallVector<llvm::Value *> CurStoreIndices;
497 SmallVector<llvm::Value *> CurLoadIndices;
499 using EmitResourceFnTy = llvm::function_ref<void(AggValueSlot &)>;
503 llvm::Value *emitAccessChain(llvm::Type *BaseTy, llvm::Value *Base,
504 ArrayRef<llvm::Value *> Indices) {
505 bool EmitLogical = CGF.getLangOpts().EmitLogicalPointer;
507 return CGF.Builder.CreateAccessChain(EmitLogical, BaseTy, Base, Indices);
509 llvm::SmallVector<llvm::Value *> GEPIndices;
510 GEPIndices.reserve(Indices.size() + 1);
511 GEPIndices.push_back(llvm::ConstantInt::get(CGF.IntTy, 0));
512 GEPIndices.append(Indices.begin(), Indices.end());
513 return CGF.Builder.CreateAccessChain(EmitLogical, BaseTy, Base, GEPIndices);
516 bool isBufferLayoutArray(llvm::StructType *ST) {
522 if (!ST || ST->getNumElements() != 2)
525 auto *PaddedEltsTy = dyn_cast<llvm::ArrayType>(ST->getElementType(0));
529 auto *PaddedTy = dyn_cast<llvm::StructType>(PaddedEltsTy->getElementType());
530 if (!PaddedTy || PaddedTy->getNumElements() != 2)
533 if (!CGF.CGM.getTargetCodeGenInfo().isHLSLPadding(
534 PaddedTy->getElementType(1)))
537 llvm::Type *ElementTy = ST->getElementType(1);
538 if (PaddedTy->getElementType(0) != ElementTy)
549 bool isResourceOrResourceArray(llvm::Type *Ty) {
550 while (
auto *AT = dyn_cast<llvm::ArrayType>(Ty))
551 Ty = AT->getElementType();
553 auto *ST = dyn_cast<llvm::StructType>(Ty);
554 if (!ST || ST->getNumElements() < 1)
557 auto *TargetTy = dyn_cast<llvm::TargetExtType>(ST->getElementType(0));
558 return TargetTy !=
nullptr;
561 void emitResourceOrResourceArray(
Value *Dst, llvm::Type *DstTy,
562 EmitResourceFnTy EmitResFn) {
565 Address DstAddr(Dst, DstTy, DstAlign);
574 void emitBufferLayoutCopy(
Value *Src, llvm::StructType *SrcTy,
Value *Dst,
575 llvm::ArrayType *DstTy,
576 EmitResourceFnTy EmitResFn) {
579 assert(SrcPaddedArrayTy->getNumElements() + 1 == DstTy->getNumElements());
581 ->getElementType(0) == SrcTy->getElementType(1));
583 auto *SrcDataTy = SrcTy->getElementType(1);
584 auto Zero = llvm::ConstantInt::get(CGF.IntTy, 0);
586 for (
unsigned I = 0; I < SrcPaddedArrayTy->getNumElements(); ++I) {
587 auto Index = llvm::ConstantInt::get(CGF.IntTy, I);
588 auto *SrcElt = emitAccessChain(SrcTy, Src, {
Zero, Index,
Zero});
589 auto *DstElt = emitAccessChain(DstTy, Dst, {Index});
590 emitElementCopy(SrcElt, SrcDataTy, DstElt, DstTy->getElementType(),
595 emitAccessChain(SrcTy, Src, {llvm::ConstantInt::get(CGF.IntTy, 1)});
596 auto *DstElt = emitAccessChain(
598 {llvm::ConstantInt::get(CGF.IntTy, DstTy->getNumElements() - 1)});
599 emitElementCopy(SrcElt, SrcDataTy, DstElt, DstTy->getElementType(),
603 void emitCopy(
Value *Src, llvm::StructType *SrcTy,
Value *Dst,
604 llvm::Type *DstTy, EmitResourceFnTy EmitResFn) {
605 assert(!isResourceOrResourceArray(DstTy) &&
606 "direct access to resources or resource arrays should be handled "
609 if (isBufferLayoutArray(SrcTy))
613 unsigned SrcIndex = 0;
614 unsigned DstIndex = 0;
621 while (DstIndex < DstST->getNumElements()) {
622 llvm::Type *DstEltTy = DstST->getElementType(DstIndex);
623 if (CGF.CGM.getTargetCodeGenInfo().isHLSLPadding(DstEltTy)) {
627 if (isResourceOrResourceArray(DstEltTy)) {
628 auto *DstElt = emitAccessChain(
629 DstTy, Dst, {llvm::ConstantInt::get(CGF.IntTy, DstIndex)});
630 emitResourceOrResourceArray(DstElt, DstEltTy, EmitResFn);
635 assert(SrcIndex < SrcTy->getNumElements());
636 llvm::Type *SrcEltTy = SrcTy->getElementType(SrcIndex);
637 if (CGF.CGM.getTargetCodeGenInfo().isHLSLPadding(SrcEltTy)) {
642 auto *SrcElt = emitAccessChain(
643 SrcTy, Src, {llvm::ConstantInt::get(CGF.IntTy, SrcIndex)});
644 auto *DstElt = emitAccessChain(
645 DstTy, Dst, {llvm::ConstantInt::get(CGF.IntTy, DstIndex)});
646 emitElementCopy(SrcElt, SrcEltTy, DstElt, DstEltTy, EmitResFn);
652 void emitCopy(
Value *Src, llvm::ArrayType *SrcTy,
Value *Dst,
653 llvm::Type *DstTy, EmitResourceFnTy EmitResFn) {
654 for (
unsigned I = 0, E = SrcTy->getNumElements(); I < E; ++I) {
656 emitAccessChain(SrcTy, Src, {llvm::ConstantInt::get(CGF.IntTy, I)});
658 emitAccessChain(DstTy, Dst, {llvm::ConstantInt::get(CGF.IntTy, I)});
659 emitElementCopy(SrcElt, SrcTy->getElementType(), DstElt,
665 void emitElementCopy(
Value *Src, llvm::Type *SrcTy,
Value *Dst,
666 llvm::Type *DstTy, EmitResourceFnTy EmitResFn) {
667 if (
auto *AT = dyn_cast<llvm::ArrayType>(SrcTy))
668 return emitCopy(Src, AT, Dst, DstTy, EmitResFn);
669 if (
auto *ST = dyn_cast<llvm::StructType>(SrcTy))
670 return emitCopy(Src, ST, Dst, DstTy, EmitResFn);
677 Address SrcAddr(Src, SrcTy, SrcAlign);
678 Address DstAddr(Dst, DstTy, DstAlign);
679 llvm::Value *
Load = CGF.Builder.CreateLoad(SrcAddr,
"cbuf.load");
680 CGF.Builder.CreateStore(Load, DstAddr);
684 HLSLBufferCopyEmitter(CodeGenFunction &CGF, Address DstPtr, Address SrcPtr)
685 : CGF(CGF), DstPtr(DstPtr), SrcPtr(SrcPtr) {}
687 bool emitCopy(QualType CType, EmitResourceFnTy EmitResFn =
nullptr) {
688 LayoutTy = HLSLBufferLayoutBuilder(CGF.CGM).layOutType(CType);
695 emitElementCopy(SrcPtr.getBasePointer(), LayoutTy, DstPtr.getBasePointer(),
696 DstPtr.getElementType(), EmitResFn);
707class AssociatedResourcesList {
712 specific_attr_iterator<HLSLAssociatedResourceDeclAttr> Begin, End, Next;
715 AssociatedResourcesList(
const VarDecl *StructVD,
716 StringRef ResourceNamePrefix) {
722 !I->getResDecl()->getName().starts_with(ResourceNamePrefix))
724 assert(I != E &&
"expected associated resource not found");
729 while (I != E && ((HLSLAssociatedResourceDeclAttr *)*I)
732 .starts_with(ResourceNamePrefix))
738 const VarDecl *getNextResource() {
742 const VarDecl *Res = Next->getResDecl();
753 assert(
T->isHLSLSpecificType() &&
"Not an HLSL specific type!");
756 if (llvm::Type *TargetTy =
760 llvm_unreachable(
"Generic handling of HLSL types is not supported.");
763llvm::Triple::ArchType CGHLSLRuntime::getArch() {
769void CGHLSLRuntime::emitBufferGlobalsAndMetadata(
775 llvm::Type *BufType = BufGV->getValueType();
780 size_t OffsetIdx = 0;
790 VarDecl *VD = dyn_cast<VarDecl>(D);
806 DeclsWithOffset.emplace_back(VD, OffsetInfo[OffsetIdx++]);
809 if (!OffsetInfo.
empty())
810 llvm::stable_sort(DeclsWithOffset, [](
const auto &LHS,
const auto &RHS) {
815 SmallVector<llvm::Metadata *> BufGlobals;
816 BufGlobals.reserve(DeclsWithOffset.size() + 1);
817 BufGlobals.push_back(ValueAsMetadata::get(BufGV));
819 auto ElemIt = LayoutStruct->element_begin();
820 for (
auto &[VD, _] : DeclsWithOffset) {
824 assert(ElemIt != LayoutStruct->element_end() &&
825 "number of elements in layout struct does not match");
826 llvm::Type *LayoutType = *ElemIt++;
828 GlobalVariable *ElemGV =
830 BufGlobals.push_back(ValueAsMetadata::get(ElemGV));
832 assert(ElemIt == LayoutStruct->element_end() &&
833 "number of elements in layout struct does not match");
837 .getOrInsertNamedMetadata(
"hlsl.cbs")
838 ->addOperand(MDNode::get(Ctx, BufGlobals));
842static const clang::HLSLAttributedResourceType *
847 HLSLAttributedResourceType::Attributes(ResourceClass::CBuffer));
862 VarDecl *VD = dyn_cast<VarDecl>(D);
873 if (
auto *POA = dyn_cast<HLSLPackOffsetAttr>(
Attr)) {
874 Offset = POA->getOffsetInBytes();
877 auto *RBA = dyn_cast<HLSLResourceBindingAttr>(
Attr);
879 RBA->getRegisterType() == HLSLResourceBindingAttr::RegisterType::C) {
880 Offset = RBA->getSlotNumber() * CBufferRowSizeInBytes;
884 Result.Offsets.push_back(Offset);
892 assert(BufDecl->
isCBuffer() &&
"tbuffer codegen is not supported yet");
895 const clang::HLSLAttributedResourceType *ResHandleTy =
899 if (ResHandleTy->getContainedType()->getAsCXXRecordDecl()->isEmpty())
905 llvm::GlobalVariable *BufGV =
new GlobalVariable(
907 GlobalValue::LinkageTypes::InternalLinkage, PoisonValue::get(LayoutTy),
908 llvm::formatv(
"{0}{1}", BufDecl->
getName(),
910 GlobalValue::NotThreadLocal);
913 M.insertGlobalVariable(BufGV);
918 llvm::appendToCompilerUsed(M, {BufGV});
921 emitBufferGlobalsAndMetadata(BufDecl, BufGV, OffsetInfo);
924 initializeBufferFromBinding(BufDecl, BufGV);
930 Triple
T(M.getTargetTriple());
933 if (
T.getEnvironment() != Triple::EnvironmentType::RootSignature)
936 addRootSignatureMD(SignatureDecl->
getVersion(),
942 const auto Entry = LayoutTypes.find(StructType);
943 if (Entry != LayoutTypes.end())
944 return Entry->getSecond();
949 llvm::StructType *LayoutTy) {
951 "layout type for this struct already exist");
952 LayoutTypes[StructType] = LayoutTy;
960 Triple
T(M.getTargetTriple());
961 if (
T.getArch() == Triple::ArchType::dxil)
962 addDxilValVersion(TargetOpts.DxilValidatorVersion, M);
963 if (!CodeGenOpts.DisableDXSourceMetadata &&
964 CodeGenOpts.getDebugInfo() >=
965 llvm::codegenoptions::DebugInfoKind::DebugInfoConstructor)
966 addSourceInfo(CGM, M);
967 if (CodeGenOpts.ResMayAlias)
968 M.setModuleFlag(llvm::Module::ModFlagBehavior::Error,
"dx.resmayalias", 1);
969 if (CodeGenOpts.AllResourcesBound)
970 M.setModuleFlag(llvm::Module::ModFlagBehavior::Error,
971 "dx.allresourcesbound", 1);
972 if (CodeGenOpts.OptimizationLevel == 0)
973 M.addModuleFlag(llvm::Module::ModFlagBehavior::Override,
974 "dx.disable_optimizations", 1);
979 if (LangOpts.NativeHalfType)
980 M.setModuleFlag(llvm::Module::ModFlagBehavior::Error,
"dx.nativelowprec",
983 if (LangOpts.HLSLSpvPreserveInterface &&
T.isSPIRV()) {
989 for (GlobalVariable &GV : M.globals()) {
990 unsigned AS = GV.getAddressSpace();
991 if (AS == InputAS || AS == OutputAS)
992 InterfaceVars.push_back(&GV);
994 if (!InterfaceVars.empty())
995 appendToCompilerUsed(M, InterfaceVars);
1003 const auto *ShaderAttr = FD->
getAttr<HLSLShaderAttr>();
1004 assert(ShaderAttr &&
"All entry functions must have a HLSLShaderAttr");
1005 const StringRef ShaderAttrKindStr =
"hlsl.shader";
1006 Fn->addFnAttr(ShaderAttrKindStr,
1007 llvm::Triple::getEnvironmentTypeName(ShaderAttr->getType()));
1008 if (HLSLNumThreadsAttr *NumThreadsAttr = FD->
getAttr<HLSLNumThreadsAttr>()) {
1009 const StringRef NumThreadsKindStr =
"hlsl.numthreads";
1010 std::string NumThreadsStr =
1011 formatv(
"{0},{1},{2}", NumThreadsAttr->getX(), NumThreadsAttr->getY(),
1012 NumThreadsAttr->getZ());
1013 Fn->addFnAttr(NumThreadsKindStr, NumThreadsStr);
1015 if (HLSLWaveSizeAttr *WaveSizeAttr = FD->
getAttr<HLSLWaveSizeAttr>()) {
1016 const StringRef WaveSizeKindStr =
"hlsl.wavesize";
1017 std::string WaveSizeStr =
1018 formatv(
"{0},{1},{2}", WaveSizeAttr->getMin(), WaveSizeAttr->getMax(),
1019 WaveSizeAttr->getPreferred());
1020 Fn->addFnAttr(WaveSizeKindStr, WaveSizeStr);
1027 Fn->addFnAttr(llvm::Attribute::NoInline);
1029 if (CGM.
getLangOpts().HLSLSpvEnableMaximalReconvergence) {
1030 Fn->addFnAttr(
"enable-maximal-reconvergence",
"true");
1035 if (
const auto *VT = dyn_cast<FixedVectorType>(Ty)) {
1037 for (
unsigned I = 0; I < VT->getNumElements(); ++I) {
1038 Value *Elt = B.CreateCall(F, {B.getInt32(I)});
1043 return B.CreateCall(F, {B.getInt32(0)});
1048 LLVMContext &Ctx = GV->getContext();
1049 IRBuilder<> B(GV->getContext());
1050 MDNode *Operands = MDNode::get(
1052 {ConstantAsMetadata::get(B.getInt32( 11)),
1053 ConstantAsMetadata::get(B.getInt32(BuiltIn))});
1054 MDNode *Decoration = MDNode::get(Ctx, {Operands});
1055 GV->addMetadata(
"spirv.Decorations", *Decoration);
1059 LLVMContext &Ctx = GV->getContext();
1060 IRBuilder<> B(GV->getContext());
1062 MDNode::get(Ctx, {ConstantAsMetadata::get(B.getInt32( 30)),
1063 ConstantAsMetadata::get(B.getInt32(Location))});
1064 MDNode *Decoration = MDNode::get(Ctx, {Operands});
1065 GV->addMetadata(
"spirv.Decorations", *Decoration);
1075 if (
auto *AT = dyn_cast<llvm::ArrayType>(Ty)) {
1076 Ty = AT->getElementType();
1079 if (
auto *VT = dyn_cast<llvm::FixedVectorType>(Ty)) {
1080 Ty = VT->getElementType();
1085 return Ty->isIntegerTy() || Ty->isDoubleTy();
1089 llvm::Type *Ty,
const Twine &Name,
1090 unsigned BuiltInID) {
1091 auto *GV =
new llvm::GlobalVariable(
1092 M, Ty,
true, llvm::GlobalValue::ExternalLinkage,
1093 nullptr, Name,
nullptr,
1094 llvm::GlobalVariable::GeneralDynamicTLSModel,
1097 GV->setVisibility(llvm::GlobalValue::HiddenVisibility);
1098 return B.CreateLoad(Ty, GV);
1102 llvm::Type *Ty,
unsigned Location,
1103 StringRef Name,
bool NeedsFlat) {
1104 auto *GV =
new llvm::GlobalVariable(
1105 M, Ty,
true, llvm::GlobalValue::ExternalLinkage,
1106 nullptr, Name,
nullptr,
1107 llvm::GlobalVariable::GeneralDynamicTLSModel,
1109 GV->setVisibility(llvm::GlobalValue::HiddenVisibility);
1114 LLVMContext &Ctx = GV->getContext();
1116 Decorations.push_back(
1117 MDNode::get(Ctx, {ConstantAsMetadata::get(
1119 ConstantAsMetadata::get(B.getInt32(Location))}));
1121 Decorations.push_back(
1122 MDNode::get(Ctx, {ConstantAsMetadata::get(
1123 B.getInt32( 14))}));
1124 GV->addMetadata(
"spirv.Decorations", *MDNode::get(Ctx, Decorations));
1126 return B.CreateLoad(Ty, GV);
1129llvm::Value *CGHLSLRuntime::emitSPIRVUserSemanticLoad(
1130 llvm::IRBuilder<> &B,
const FunctionDecl *FD, llvm::Type *
Type,
1131 const clang::DeclaratorDecl *
Decl, HLSLAppliedSemanticAttr *Semantic,
1132 std::optional<unsigned> Index) {
1133 Twine BaseName = Twine(Semantic->getAttrName()->getName());
1134 Twine VariableName = BaseName.concat(Twine(Index.value_or(0)));
1136 unsigned Location = SPIRVLastAssignedInputSemanticLocation;
1137 if (
auto *L =
Decl->getAttr<HLSLVkLocationAttr>())
1138 Location = L->getLocation();
1142 llvm::ArrayType *AT = dyn_cast<llvm::ArrayType>(
Type);
1143 unsigned ElementCount = AT ? AT->getNumElements() : 1;
1144 SPIRVLastAssignedInputSemanticLocation += ElementCount;
1146 const auto *ShaderAttr = FD->
getAttr<HLSLShaderAttr>();
1149 ShaderAttr->getType() == llvm::Triple::EnvironmentType::Pixel &&
1153 VariableName.str(), NeedsFlat);
1157 llvm::Value *Source,
unsigned Location,
1159 auto *GV =
new llvm::GlobalVariable(
1160 M, Source->getType(),
false,
1161 llvm::GlobalValue::ExternalLinkage,
1162 nullptr, Name,
nullptr,
1163 llvm::GlobalVariable::GeneralDynamicTLSModel,
1165 GV->setVisibility(llvm::GlobalValue::HiddenVisibility);
1167 B.CreateStore(Source, GV);
1170void CGHLSLRuntime::emitSPIRVUserSemanticStore(
1171 llvm::IRBuilder<> &B, llvm::Value *Source,
1172 const clang::DeclaratorDecl *
Decl, HLSLAppliedSemanticAttr *Semantic,
1173 std::optional<unsigned> Index) {
1174 Twine BaseName = Twine(Semantic->getAttrName()->getName());
1175 Twine VariableName = BaseName.concat(Twine(Index.value_or(0)));
1177 unsigned Location = SPIRVLastAssignedOutputSemanticLocation;
1178 if (
auto *L =
Decl->getAttr<HLSLVkLocationAttr>())
1179 Location = L->getLocation();
1183 llvm::ArrayType *AT = dyn_cast<llvm::ArrayType>(Source->getType());
1184 unsigned ElementCount = AT ? AT->getNumElements() : 1;
1185 SPIRVLastAssignedOutputSemanticLocation += ElementCount;
1187 VariableName.str());
1192struct SemanticShape {
1193 SmallVector<unsigned> Dimensions;
1197 unsigned getNumRows()
const {
1199 for (
unsigned Dimension : Dimensions)
1204 SmallVector<unsigned> getArrayIndicesForRow(
unsigned Row)
const {
1205 assert(Row < getNumRows() &&
"row exceeds semantic shape");
1207 SmallVector<unsigned> Indices(Dimensions.size());
1208 for (
auto [Index, Dimension] :
1209 llvm::zip_equal(llvm::reverse(Indices), llvm::reverse(Dimensions))) {
1210 Index = Row % Dimension;
1221 if (
const auto *FD = dyn_cast<clang::FunctionDecl>(
Decl))
1223 return Decl->getType();
1229 SemanticShape Shape{{}, 1, Ty};
1232 Shape.Dimensions.push_back(CAT->getSize().getZExtValue());
1233 Shape.RowType = CAT->getElementType();
1237 Shape.Cols = VT->getNumElements();
1238 }
else if (
const auto *MT =
1243 Shape.Cols = MT->getNumColumns();
1249llvm::Value *CGHLSLRuntime::emitDXILUserSemanticLoad(
1250 llvm::IRBuilder<> &B, llvm::Type *
Type,
const clang::DeclaratorDecl *
Decl,
1251 HLSLAppliedSemanticAttr *Semantic, std::optional<unsigned> Index) {
1252 StringRef Name = Semantic->getAttrName()->getName();
1253 SemanticShape Shape =
1258 llvm::Function *IntrFn = llvm::Intrinsic::getOrInsertDeclaration(
1259 B.GetInsertBlock()->getModule(), llvm::Intrinsic::dx_load_input, {RowTy});
1261 SmallVector<OperandBundleDef, 1> OB;
1263 llvm::Value *bundleArgs[] = {Token};
1264 OB.emplace_back(
"convergencectrl", bundleArgs);
1267 unsigned SigId = DXILInputSemanticIndex++;
1270 llvm::Value *
Result = llvm::PoisonValue::get(
Type);
1272 const unsigned NumRows = Shape.getNumRows();
1274 for (
unsigned Row = 0; Row < NumRows; ++Row) {
1275 SmallVector<unsigned> Indices = Shape.getArrayIndicesForRow(Row);
1276 std::array<Value *, 4> Args{
1280 llvm::PoisonValue::get(B.getInt32Ty())};
1281 llvm::Value *
Value =
1282 B.CreateCall(IntrFn, Args, OB, Twine(Name).concat(Twine(Row)));
1285 if (
Value->getType() != LeafTy) {
1287 "unexpected semantic load type mismatch");
1288 Value = B.CreateICmpNE(
1289 Value, llvm::Constant::getNullValue(
Value->getType()),
"loadedv");
1298void CGHLSLRuntime::emitDXILUserSemanticStore(llvm::IRBuilder<> &B,
1299 llvm::Value *Source,
1300 const clang::DeclaratorDecl *
Decl,
1301 HLSLAppliedSemanticAttr *Semantic,
1302 std::optional<unsigned> Index) {
1303 SemanticShape Shape =
1307 llvm::Function *IntrFn = llvm::Intrinsic::getOrInsertDeclaration(
1308 B.GetInsertBlock()->getModule(), llvm::Intrinsic::dx_store_output,
1311 SmallVector<OperandBundleDef, 1> OB;
1313 llvm::Value *bundleArgs[] = {Token};
1314 OB.emplace_back(
"convergencectrl", bundleArgs);
1317 unsigned SigId = DXILOutputSemanticIndex++;
1319 const unsigned NumRows = Shape.getNumRows();
1320 for (
unsigned Row = 0; Row < NumRows; ++Row) {
1321 SmallVector<unsigned> Indices = Shape.getArrayIndicesForRow(Row);
1323 Indices.empty() ? Source : B.CreateExtractValue(Source, Indices);
1327 if (Val->getType() != RowTy) {
1329 "unexpected semantic store type mismatch");
1330 Val = B.CreateZExt(Val, RowTy,
"storedv");
1333 std::array<Value *, 4> Args{B.getInt32(SigId),
1336 B.CreateCall(IntrFn, Args, OB);
1340llvm::Value *CGHLSLRuntime::emitUserSemanticLoad(
1341 IRBuilder<> &B,
const FunctionDecl *FD, llvm::Type *
Type,
1342 const clang::DeclaratorDecl *
Decl, HLSLAppliedSemanticAttr *Semantic,
1343 std::optional<unsigned> Index) {
1345 return emitSPIRVUserSemanticLoad(B, FD,
Type,
Decl, Semantic, Index);
1348 return emitDXILUserSemanticLoad(B,
Type,
Decl, Semantic, Index);
1350 llvm_unreachable(
"Unsupported target for user-semantic load.");
1353void CGHLSLRuntime::emitUserSemanticStore(IRBuilder<> &B, llvm::Value *Source,
1354 const clang::DeclaratorDecl *
Decl,
1355 HLSLAppliedSemanticAttr *Semantic,
1356 std::optional<unsigned> Index) {
1358 return emitSPIRVUserSemanticStore(B, Source,
Decl, Semantic, Index);
1361 return emitDXILUserSemanticStore(B, Source,
Decl, Semantic, Index);
1363 llvm_unreachable(
"Unsupported target for user-semantic load.");
1369 std::optional<unsigned> Index) {
1371 std::string SemanticName = Semantic->getAttrName()->getName().upper();
1372 if (SemanticName ==
"SV_GROUPINDEX") {
1373 llvm::Function *GroupIndex =
1374 CGM.
getIntrinsic(getFlattenedThreadIdInGroupIntrinsic());
1375 return B.CreateCall(FunctionCallee(GroupIndex));
1378 if (SemanticName ==
"SV_DISPATCHTHREADID") {
1379 llvm::Intrinsic::ID IntrinID = getThreadIdIntrinsic();
1380 llvm::Function *ThreadIDIntrinsic =
1381 llvm::Intrinsic::isOverloaded(IntrinID)
1387 if (SemanticName ==
"SV_GROUPTHREADID") {
1388 llvm::Intrinsic::ID IntrinID = getGroupThreadIdIntrinsic();
1389 llvm::Function *GroupThreadIDIntrinsic =
1390 llvm::Intrinsic::isOverloaded(IntrinID)
1396 if (SemanticName ==
"SV_GROUPID") {
1397 llvm::Intrinsic::ID IntrinID = getGroupIdIntrinsic();
1398 llvm::Function *GroupIDIntrinsic =
1399 llvm::Intrinsic::isOverloaded(IntrinID)
1405 const auto *ShaderAttr = FD->
getAttr<HLSLShaderAttr>();
1406 assert(ShaderAttr &&
"Entry point has no shader attribute");
1407 llvm::Triple::EnvironmentType ST = ShaderAttr->getType();
1409 if (SemanticName ==
"SV_POSITION") {
1410 if (ST == Triple::EnvironmentType::Pixel) {
1413 Semantic->getAttrName()->getName(),
1416 return emitDXILUserSemanticLoad(B,
Type,
Decl, Semantic, Index);
1419 if (ST == Triple::EnvironmentType::Vertex) {
1420 return emitUserSemanticLoad(B, FD,
Type,
Decl, Semantic, Index);
1424 if (SemanticName ==
"SV_VERTEXID") {
1425 if (ST == Triple::EnvironmentType::Vertex) {
1428 Semantic->getAttrName()->getName(),
1431 return emitDXILUserSemanticLoad(B,
Type,
Decl, Semantic, Index);
1436 "Load hasn't been implemented yet for this system semantic. FIXME");
1440 llvm::Value *Source,
const Twine &Name,
1441 unsigned BuiltInID) {
1442 auto *GV =
new llvm::GlobalVariable(
1443 M, Source->getType(),
false,
1444 llvm::GlobalValue::ExternalLinkage,
1445 nullptr, Name,
nullptr,
1446 llvm::GlobalVariable::GeneralDynamicTLSModel,
1449 GV->setVisibility(llvm::GlobalValue::HiddenVisibility);
1450 B.CreateStore(Source, GV);
1455 HLSLAppliedSemanticAttr *Semantic,
1456 std::optional<unsigned> Index) {
1458 std::string SemanticName = Semantic->getAttrName()->getName().upper();
1459 if (SemanticName ==
"SV_POSITION") {
1461 emitDXILUserSemanticStore(B, Source,
Decl, Semantic, Index);
1467 Semantic->getAttrName()->getName(),
1473 if (SemanticName ==
"SV_TARGET") {
1474 emitUserSemanticStore(B, Source,
Decl, Semantic, Index);
1479 "Store hasn't been implemented yet for this system semantic. FIXME");
1486 std::optional<unsigned> Index = Semantic->getSemanticIndex();
1487 if (Semantic->getAttrName()->getName().starts_with_insensitive(
"SV_"))
1489 return emitUserSemanticLoad(B, FD,
Type,
Decl, Semantic, Index);
1493 IRBuilder<> &B,
const FunctionDecl *FD, llvm::Value *Source,
1495 std::optional<unsigned> Index = Semantic->getSemanticIndex();
1496 if (Semantic->getAttrName()->getName().starts_with_insensitive(
"SV_"))
1499 emitUserSemanticStore(B, Source,
Decl, Semantic, Index);
1502std::pair<llvm::Value *, specific_attr_iterator<HLSLAppliedSemanticAttr>>
1515 for (
unsigned I = 0; I < ST->getNumElements(); ++I) {
1517 B, FD, ST->getElementType(I), *
FieldDecl, AttrBegin, AttrEnd);
1518 AttrBegin = NextAttr;
1524 return std::make_pair(
Aggregate, AttrBegin);
1529 IRBuilder<> &B,
const FunctionDecl *FD, llvm::Value *Source,
1540 RD =
Decl->getType()->getAsRecordDecl();
1546 for (
unsigned I = 0; I < ST->getNumElements(); ++I, ++
FieldDecl) {
1547 llvm::Value *Extract = B.CreateExtractValue(Source, I);
1555std::pair<llvm::Value *, specific_attr_iterator<HLSLAppliedSemanticAttr>>
1561 assert(AttrBegin != AttrEnd);
1562 if (
Type->isStructTy())
1565 HLSLAppliedSemanticAttr *
Attr = *AttrBegin;
1573 IRBuilder<> &B,
const FunctionDecl *FD, llvm::Value *Source,
1577 assert(AttrBegin != AttrEnd);
1578 if (Source->getType()->isStructTy())
1581 HLSLAppliedSemanticAttr *
Attr = *AttrBegin;
1588 llvm::Function *Fn) {
1589 DXILInputSemanticIndex = 0;
1590 DXILOutputSemanticIndex = 0;
1593 llvm::LLVMContext &Ctx = M.getContext();
1594 auto *EntryTy = llvm::FunctionType::get(llvm::Type::getVoidTy(Ctx),
false);
1596 Function::Create(EntryTy, Function::ExternalLinkage, FD->
getName(), &M);
1600 AttributeList NewAttrs = AttributeList::get(Ctx, AttributeList::FunctionIndex,
1601 Fn->getAttributes().getFnAttrs());
1602 EntryFn->setAttributes(NewAttrs);
1606 Fn->setLinkage(GlobalValue::InternalLinkage);
1608 BasicBlock *BB = BasicBlock::Create(Ctx,
"entry", EntryFn);
1614 assert(EntryFn->isConvergent());
1616 B.CreateIntrinsic(llvm::Intrinsic::experimental_convergence_entry, {});
1617 llvm::Value *bundleArgs[] = {I};
1618 OB.emplace_back(
"convergencectrl", bundleArgs);
1623 unsigned SRetOffset = 0;
1624 for (
const auto &Param : Fn->args()) {
1625 if (Param.hasStructRetAttr()) {
1627 llvm::Type *VarType = Param.getParamStructRetType();
1632 OutputSemantic.push_back(std::make_pair(Var, VarType));
1633 Args.push_back(Var);
1638 llvm::Value *SemanticValue =
nullptr;
1640 if ([[maybe_unused]] HLSLParamModifierAttr *MA =
1641 PD->
getAttr<HLSLParamModifierAttr>()) {
1642 llvm_unreachable(
"Not handled yet");
1644 llvm::Type *ParamType =
nullptr;
1645 if (Param.hasByValAttr())
1646 ParamType = Param.getParamByValType();
1650 ParamType = Param.getType();
1656 SemanticValue =
Result.first;
1664 B.CreateStore(SemanticValue, Var);
1665 SemanticValue = Var;
1669 assert(SemanticValue);
1670 Args.push_back(SemanticValue);
1673 CallInst *CI = B.CreateCall(FunctionCallee(Fn), Args, OB);
1674 CI->setCallingConv(Fn->getCallingConv());
1676 if (Fn->getReturnType() != CGM.
VoidTy)
1678 OutputSemantic.push_back(std::make_pair(CI,
nullptr));
1680 for (
auto &SourcePair : OutputSemantic) {
1681 llvm::Value *Source = SourcePair.first;
1682 llvm::Type *ElementType = SourcePair.second;
1683 AllocaInst *AI = dyn_cast<AllocaInst>(Source);
1684 llvm::Value *SourceValue = AI ? B.CreateLoad(ElementType, Source) : Source;
1695 if (
const auto *RSAttr = dyn_cast<RootSignatureAttr>(
Attr)) {
1696 auto *RSDecl = RSAttr->getSignatureDecl();
1697 addRootSignatureMD(RSDecl->getVersion(), RSDecl->getRootElements(),
1706 M.getNamedGlobal(CtorOrDtor ?
"llvm.global_ctors" :
"llvm.global_dtors");
1709 const auto *CA = dyn_cast<ConstantArray>(GV->getInitializer());
1716 for (
const auto &Ctor : CA->operands()) {
1722 "HLSL doesn't support setting priority for global ctors.");
1724 "HLSL doesn't support COMDat for global ctors.");
1739 for (
auto &F : M.functions()) {
1740 if (!F.hasFnAttribute(
"hlsl.shader"))
1743 Instruction *IP = &*F.getEntryBlock().begin();
1746 llvm::Value *bundleArgs[] = {
Token};
1747 OB.emplace_back(
"convergencectrl", bundleArgs);
1748 IP =
Token->getNextNode();
1751 for (
auto *Fn : CtorFns) {
1752 auto CI = B.CreateCall(FunctionCallee(Fn), {}, OB);
1753 CI->setCallingConv(Fn->getCallingConv());
1757 B.SetInsertPoint(F.back().getTerminator());
1758 for (
auto *Fn : DtorFns) {
1759 auto CI = B.CreateCall(FunctionCallee(Fn), {}, OB);
1760 CI->setCallingConv(Fn->getCallingConv());
1766 Triple
T(M.getTargetTriple());
1767 if (
T.getEnvironment() != Triple::EnvironmentType::Library) {
1768 if (
auto *GV = M.getNamedGlobal(
"llvm.global_ctors"))
1769 GV->eraseFromParent();
1770 if (
auto *GV = M.getNamedGlobal(
"llvm.global_dtors"))
1771 GV->eraseFromParent();
1776 Intrinsic::ID IntrID,
1780 llvm::Function *InitResFunc =
1781 llvm::Function::Create(llvm::FunctionType::get(CGM.
VoidTy,
false),
1782 llvm::GlobalValue::InternalLinkage,
1783 "_init_buffer_" + GV->getName(), CGM.
getModule());
1784 InitResFunc->addFnAttr(llvm::Attribute::AlwaysInline);
1786 llvm::BasicBlock *EntryBB =
1787 llvm::BasicBlock::Create(Ctx,
"entry", InitResFunc);
1789 const DataLayout &DL = CGM.
getModule().getDataLayout();
1790 Builder.SetInsertPoint(EntryBB);
1793 llvm::Type *HandleTy = GV->getValueType();
1794 assert(HandleTy->isTargetExtTy() &&
"unexpected type of the buffer global");
1796 llvm::Value *CreateHandle = Builder.CreateIntrinsic(
1797 HandleTy, IntrID, Args,
nullptr,
1798 Twine(GV->getName()).concat(
"_h"));
1800 Builder.CreateAlignedStore(CreateHandle, GV, GV->getPointerAlignment(DL));
1801 Builder.CreateRetVoid();
1806void CGHLSLRuntime::initializeBufferFromBinding(
const HLSLBufferDecl *BufDecl,
1807 llvm::GlobalVariable *GV) {
1808 ResourceBindingAttrs Binding(BufDecl);
1810 "cbuffer/tbuffer should always have resource binding attribute");
1812 auto *Index = llvm::ConstantInt::get(CGM.
IntTy, 0);
1813 auto *RangeSize = llvm::ConstantInt::get(CGM.
IntTy, 1);
1814 auto *Space = llvm::ConstantInt::get(CGM.
IntTy, Binding.
getSpace());
1815 Value *Name = buildNameForResource(BufDecl->
getName(), CGM);
1819 llvm::Intrinsic::ID IntrinsicID =
1821 auto *RegSlot = llvm::ConstantInt::get(CGM.
IntTy, Binding.
getSlot());
1822 SmallVector<Value *> Args{Space, RegSlot, RangeSize, Index, Name};
1826 llvm::Intrinsic::ID IntrinsicID =
1827 CGM.
getHLSLRuntime().getCreateHandleFromImplicitBindingIntrinsic();
1830 SmallVector<Value *> Args{OrderID, Space, RangeSize, Index, Name};
1836 llvm::GlobalVariable *GV) {
1837 if (
auto Attr = VD->
getAttr<HLSLVkExtBuiltinInputAttr>())
1839 if (
auto Attr = VD->
getAttr<HLSLVkExtBuiltinOutputAttr>())
1848 for (
auto I = BB.begin(); I != E; ++I) {
1849 auto *II = dyn_cast<llvm::IntrinsicInst>(&*I);
1850 if (II && llvm::isConvergenceControlIntrinsic(II->getIntrinsicID())) {
1854 llvm_unreachable(
"Convergence token should have been emitted.");
1891 for (
auto *OVE : Visitor.
OVEs) {
1894 if (OpaqueValueMappingData::shouldBindAsLValue(OVE)) {
1896 OpaqueValueMappingData::bind(CGF, OVE, LV);
1899 OpaqueValueMappingData::bind(CGF, OVE, RV);
1908 "expected resource array subscript expression");
1913 const VarDecl *ArrayDecl = dyn_cast_or_null<VarDecl>(
1917 return std::nullopt;
1923 "expected array of resource classes");
1929 Value *Index =
nullptr;
1931 while (ASE !=
nullptr) {
1933 if (
const auto *ArrayTy =
1935 Value *Multiplier = llvm::ConstantInt::get(
1937 SubIndex = CGF.
Builder.CreateMul(SubIndex, Multiplier);
1939 Index = Index ? CGF.
Builder.CreateAdd(Index, SubIndex) : SubIndex;
1947 "resource array must have a binding attribute");
1968 llvm::Value *Range = llvm::ConstantInt::getSigned(
1969 CGM.
IntTy, getTotalArraySize(AST, ResArrayTy));
1973 if (ResultTy == ResourceTy) {
1975 CXXMethodDecl *CreateMethod = lookupResourceInitMethodAndSetupArgs(
1977 ArrayDecl->
getName(), Binding, Args);
1979 if (!CreateMethod) {
1984 "create method lookup should always succeed for built-in resource "
1986 return std::nullopt;
1989 callResourceInitMethod(CGF, CreateMethod, Args, ValueSlot.getAddress());
1996 std::optional<llvm::Value *> EndIndex = initializeResourceArrayFromGlobal(
1998 ArrayDecl->
getName(), Binding, {llvm::ConstantInt::get(CGM.IntTy, 0)});
2000 return std::nullopt;
2006bool CGHLSLRuntime::initializeGlobalResourceArray(
CodeGenFunction &CGF,
2012 "expected global non-static resource array");
2018 "resource array must have a binding attribute");
2023 const auto *ResArrayTy =
2027 int Size = getTotalArraySize(AST, ResArrayTy);
2028 llvm::Value *
Zero = llvm::ConstantInt::get(CGM.
IntTy, 0);
2029 llvm::Value *Range = llvm::ConstantInt::get(CGM.
IntTy, Size);
2032 std::optional<llvm::Value *> EndIndex = initializeResourceArrayFromGlobal(
2034 ArrayDecl->
getName(), Binding, {Zero});
2035 return EndIndex.has_value();
2044 "expected resource array");
2049 dyn_cast_or_null<VarDecl>(getArrayDecl(CGF.
CGM.
getContext(), E));
2054 return initializeGlobalResourceArray(CGF, ArrayDecl, DestSlot);
2061std::optional<LValue>
2065 "expected resource array declaration");
2069 return std::nullopt;
2073 if (initializeGlobalResourceArray(CGF, ArrayDecl, TmpArraySlot))
2076 return std::nullopt;
2084 "expected cbuffer matrix");
2095 HLSLBufferCopyEmitter(CGF, DestAlloca, SrcAddr).emitCopy(MatQualTy);
2101 llvm::function_ref<llvm::Value *(
bool Promote)> EmitIdxAfterBase) {
2105 llvm::Type *LayoutTy =
2107 uint64_t LayoutSizeInBits =
2108 CGM.
getDataLayout().getTypeSizeInBits(LayoutTy).getFixedValue();
2111 if (RowAlignedSize > ElementSize) {
2113 CGM, RowAlignedSize - ElementSize);
2114 assert(Padding &&
"No padding type for target?");
2115 LayoutTy = llvm::StructType::get(CGF.
getLLVMContext(), {LayoutTy, Padding},
2122 if (LayoutTy == OrigTy)
2123 return std::nullopt;
2132 llvm::Value *Idx = EmitIdxAfterBase(
true);
2133 Indices.push_back(Idx);
2134 Indices.push_back(llvm::ConstantInt::get(CGF.
Int32Ty, 0));
2140 assert(CE->
getCastKind() == CastKind::CK_ArrayToPointerDecay);
2144 LayoutTy = llvm::ArrayType::get(
2148 LayoutTy,
Addr.emitRawPointer(CGF), Indices,
"cbufferidx"));
2157 Indices,
"cbufferidx");
2162std::optional<LValue>
2167 "expected resource member expression");
2170 findAssociatedResourceDeclForStruct(CGF.
CGM.
getContext(), ME);
2172 return std::nullopt;
2178 GlobalVariable *ResGV =
2181 llvm::Type *Ty = ResGV->getValueType();
2194 "expected expression in HLSL constant address space");
2197 "direct accesses to resource types should be handled separately");
2209 return HLSLBufferCopyEmitter(CGF, DstPtr, SrcPtr).emitCopy(Ty);
2215 const VarDecl *VD = findStructResourceParentDeclAndBuildName(E, NameBuilder);
2216 AssociatedResourcesList AssociatedResources(VD, NameBuilder.
getName());
2220 const VarDecl *ResDecl = AssociatedResources.getNextResource();
2221 assert(ResDecl &&
"associated resource declaration not found");
2224 [[maybe_unused]] llvm::Type *DestType =
2225 ResSlot.getAddress().getElementType();
2226 [[maybe_unused]] llvm::Type *SrcConvertedType =
2228 assert(DestType == SrcConvertedType &&
"resource slot type mismatch");
2231 copyGlobalResource(CGF, ResDecl, ResSlot);
2233 initializeGlobalResourceArray(CGF, ResDecl, ResSlot);
2237 HLSLBufferCopyEmitter(CGF, DstPtr, SrcPtr).emitCopy(Ty, EmitResFn);
2238 assert(AssociatedResources.getNextResource() ==
nullptr &&
2239 "expected all associated resources to be processed");
2248 assert(Field &&
"Unexpected access into HLSL buffer");
2265 assert(FieldIdx < LayoutTy->getNumElements() &&
2266 "Layout struct is smaller than member struct");
2267 unsigned Skipped = 0;
2268 for (
unsigned I = 0; I <= FieldIdx;) {
2269 llvm::Type *ElementTy = LayoutTy->getElementType(I + Skipped);
2275 FieldIdx += Skipped;
2276 assert(FieldIdx < LayoutTy->getNumElements() &&
"Access out of bounds");
2280 QualType FieldType = Field->getType();
2286 ? CGF.
Builder.CreateStructuredGEP(
2287 LayoutTy,
Base.getPointer(CGF),
2288 llvm::ConstantInt::get(CGM.
IntTy, FieldIdx))
2290 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 QualType getSemanticLeafType(const clang::DeclaratorDecl *Decl)
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, bool NeedsFlat)
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)
static SemanticShape getSemanticShape(ASTContext &Ctx, QualType Ty)
static bool inputRequiresFlatDecoration(llvm::Type *Ty)
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()
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.
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.
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)
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)
bool emitBufferCopy(CodeGenFunction &CGF, const Expr *E, const LValue &SrcLV, AggValueSlot &DestSlot)
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)
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.
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 * 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.
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.
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.
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
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 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
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.
__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
unsigned getImplicitOrderID() const
bool hasCounterImplicitOrderID() const
unsigned getSpace() const
unsigned getCounterImplicitOrderID() const