33#include "llvm/ADT/DenseMap.h"
34#include "llvm/ADT/STLExtras.h"
35#include "llvm/ADT/ScopeExit.h"
36#include "llvm/ADT/SmallString.h"
37#include "llvm/ADT/SmallVector.h"
38#include "llvm/Frontend/HLSL/RootSignatureMetadata.h"
39#include "llvm/IR/Constants.h"
40#include "llvm/IR/DerivedTypes.h"
41#include "llvm/IR/GlobalVariable.h"
42#include "llvm/IR/IntrinsicInst.h"
43#include "llvm/IR/LLVMContext.h"
44#include "llvm/IR/Metadata.h"
45#include "llvm/IR/Module.h"
46#include "llvm/IR/Type.h"
47#include "llvm/IR/Value.h"
48#include "llvm/Support/Alignment.h"
49#include "llvm/Support/ErrorHandling.h"
50#include "llvm/Support/FormatVariadic.h"
51#include "llvm/Support/Path.h"
52#include "llvm/Transforms/Utils/ModuleUtils.h"
61using llvm::hlsl::CBufferRowSizeInBytes;
65void addDxilValVersion(StringRef ValVersionStr, llvm::Module &M) {
69 if (Version.tryParse(ValVersionStr) || Version.getBuild() ||
70 Version.getSubminor() || !Version.getMinor()) {
74 uint64_t Major = Version.getMajor();
75 uint64_t Minor = *Version.getMinor();
77 auto &Ctx = M.getContext();
78 IRBuilder<> B(M.getContext());
79 MDNode *Val = MDNode::get(Ctx, {ConstantAsMetadata::get(B.getInt32(Major)),
80 ConstantAsMetadata::get(B.getInt32(Minor))});
81 StringRef DXILValKey =
"dx.valver";
82 auto *DXILValMD = M.getOrInsertNamedMetadata(DXILValKey);
83 DXILValMD->addOperand(Val);
86void addRootSignatureMD(llvm::dxbc::RootSignatureVersion RootSigVer,
88 llvm::Function *Fn, llvm::Module &M) {
89 auto &Ctx = M.getContext();
91 llvm::hlsl::rootsig::MetadataBuilder RSBuilder(Ctx, Elements);
92 MDNode *RootSignature = RSBuilder.BuildRootSignature();
94 ConstantAsMetadata *Version = ConstantAsMetadata::get(ConstantInt::get(
95 llvm::Type::getInt32Ty(Ctx), llvm::to_underlying(RootSigVer)));
96 ValueAsMetadata *EntryFunc =
Fn ? ValueAsMetadata::get(Fn) :
nullptr;
97 MDNode *MDVals = MDNode::get(Ctx, {EntryFunc, RootSignature, Version});
99 StringRef RootSignatureValKey =
"dx.rootsignatures";
100 auto *RootSignatureValMD = M.getOrInsertNamedMetadata(RootSignatureValKey);
101 RootSignatureValMD->addOperand(MDVals);
106 GlobalVariable *ResGV =
108 assert(ResGV &&
"expected valid global variable");
125static const VarDecl *findStructResourceParentDeclAndBuildName(
132 if (
const auto *DRE = dyn_cast<DeclRefExpr>(E)) {
134 "member expr base is not a var decl");
140 WorkList.push_back(E);
141 if (
const auto *MExp = dyn_cast<MemberExpr>(E))
143 else if (
const auto *ICE = dyn_cast<ImplicitCastExpr>(E))
144 E = ICE->getSubExpr();
145 else if (
const auto *ASE = dyn_cast<ArraySubscriptExpr>(E))
152 llvm_unreachable(
"unexpected expr type in resource member access");
154 assert(E &&
"expected valid expression");
157 while (!WorkList.empty()) {
158 E = WorkList.pop_back_val();
159 if (
const auto *ME = dyn_cast<MemberExpr>(E)) {
161 ME->getMemberNameInfo().getName().getAsIdentifierInfo()->getName());
162 }
else if (
const auto *ICE = dyn_cast<ImplicitCastExpr>(E)) {
163 if (ICE->getCastKind() == CK_UncheckedDerivedToBase) {
165 ICE->getSubExpr()->getType()->getAsCXXRecordDecl();
166 CXXRecordDecl *BaseRD = ICE->getType()->getAsCXXRecordDecl();
169 }
else if (
const auto *ASE = dyn_cast<ArraySubscriptExpr>(E)) {
170 const Expr *IdxExpr = ASE->getIdx();
171 std::optional<llvm::APSInt>
Value =
174 "expected constant index in struct with resource array access");
177 llvm_unreachable(
"unexpected expr type in resource member access");
191 findStructResourceParentDeclAndBuildName(ME, NameBuilder);
200 if (
const auto *ADA = dyn_cast<HLSLAssociatedResourceDeclAttr>(A)) {
201 VarDecl *AssocResVD = ADA->getResDecl();
213 auto &Ctx = M.getContext();
216 llvm::NamedMDNode *DXContents =
217 M.getOrInsertNamedMetadata(
"dx.source.contents");
218 auto addFile = [&](
const std::pair<StringRef, StringRef> &NameContent) {
219 llvm::MDTuple *FileInfo =
220 llvm::MDNode::get(Ctx, {llvm::MDString::get(Ctx, NameContent.first),
221 llvm::MDString::get(Ctx, NameContent.second)});
222 DXContents->addOperand(FileInfo);
228 assert(!
Invalid &&
"Main file SLocEntry must not be invalid!");
233 std::optional<SmallString<256>> MainFileName;
234 Files.reserve(
SM.local_sloc_entry_size());
235 for (
unsigned I : llvm::seq(
SM.local_sloc_entry_size())) {
250 llvm::sys::path::native(Path);
254 SM.getDiagnostics().Report(diag::warn_hlsl_failed_to_embed_source)
259 if (&MainCCEntry != &CCEntry) {
260 Files.emplace_back(Path, Buffer->getBuffer());
263 addFile(std::make_pair(Path, Buffer->getBuffer()));
264 MainFileName.emplace(Path);
267 assert(MainFileName &&
"Main file not found.");
272 for (
unsigned I = 1; I < Files.size(); ++I)
273 assert((Files[I - 1].first != Files[I].first) &&
274 "duplicate files in dx.source.contents");
276 llvm::for_each(Files, addFile);
279 Defines.reserve(
Macros.size());
283 Defines.emplace_back(llvm::MDString::get(Ctx,
Macro.first));
285 M.getOrInsertNamedMetadata(
"dx.source.defines")
286 ->addOperand(llvm::MDNode::get(Ctx, Defines));
288 if (!CodeGenOpts.MainFileName.empty())
289 llvm::sys::path::native(CodeGenOpts.MainFileName, *MainFileName);
290 M.getOrInsertNamedMetadata(
"dx.source.mainFileName")
292 llvm::MDNode::get(Ctx, llvm::MDString::get(Ctx, *MainFileName)));
295 Args.reserve(CodeGenOpts.HLSLParsedCommandLine.size());
296 if (!CodeGenOpts.HLSLParsedCommandLine.empty())
297 for (
const auto &Arg : llvm::drop_begin(CodeGenOpts.HLSLParsedCommandLine))
298 Args.push_back(llvm::MDString::get(Ctx, Arg));
299 M.getOrInsertNamedMetadata(
"dx.source.args")
300 ->addOperand(llvm::MDNode::get(Ctx, Args));
306 if (
const auto *DRE = dyn_cast_or_null<DeclRefExpr>(E))
307 return DRE->getDecl();
308 if (
auto *OVE = dyn_cast<OpaqueValueExpr>(E))
318 const Expr *E =
nullptr;
319 while (ASE !=
nullptr) {
323 ASE = dyn_cast<ArraySubscriptExpr>(E);
325 return getArrayDecl(AST, E);
331 assert(Ty->
isArrayType() &&
"expected array type");
337static Value *buildNameForResource(llvm::StringRef BaseName,
346 for (
auto *Method :
Record->methods()) {
347 if (Method->getStorageClass() == SC && Method->getName() == Name)
357 assert(Binding.
hasBinding() &&
"at least one binding attribute expected");
361 Value *NameStr = buildNameForResource(Name, CGM);
366 "resources with counter handle must have a binding with counter "
367 "implicit order ID");
370 auto *RegSlot = llvm::ConstantInt::get(CGM.
IntTy, Binding.
getSlot());
373 ?
"__createFromBindingWithImplicitCounter"
374 :
"__createFromBinding";
375 CreateMethod = lookupMethod(ResourceDecl, Name,
SC_Static);
382 ?
"__createFromImplicitBindingWithImplicitCounter"
383 :
"__createFromImplicitBinding";
384 CreateMethod = lookupMethod(ResourceDecl, Name,
SC_Static);
392 auto *CounterOrderID = llvm::ConstantInt::get(CGM.
IntTy, CounterBinding);
408 Args, Proto,
false,
nullptr);
411 CGF.
EmitCall(FnInfo, Callee, ReturnValue, Args,
nullptr);
420static std::optional<llvm::Value *> initializeResourceArrayFromGlobal(
423 llvm::Value *Range, llvm::Value *StartIndex, StringRef ResourceName,
427 llvm::IntegerType *IntTy = CGF.
CGM.
IntTy;
428 llvm::Value *Index = StartIndex;
429 llvm::Value *One = llvm::ConstantInt::get(IntTy, 1);
437 GEPIndices.push_back(llvm::ConstantInt::get(IntTy, 0));
442 for (uint64_t I = 0; I < ArraySize; I++) {
444 Index = CGF.
Builder.CreateAdd(Index, One);
445 GEPIndices.back() = llvm::ConstantInt::get(IntTy, I);
447 std::optional<llvm::Value *> MaybeIndex =
448 initializeResourceArrayFromGlobal(CGF, ResourceDecl, SubArrayTy,
449 ValueSlot, Range, Index,
450 ResourceName, Binding, GEPIndices);
464 for (uint64_t I = 0; I < ArraySize; I++) {
466 Index = CGF.
Builder.CreateAdd(Index, One);
467 GEPIndices.back() = llvm::ConstantInt::get(IntTy, I);
473 CXXMethodDecl *CreateMethod = lookupResourceInitMethodAndSetupArgs(
474 CGF.
CGM, ResourceDecl, Range, Index, ResourceName, Binding, Args);
482 callResourceInitMethod(CGF, CreateMethod, Args, ReturnAddress);
489class HLSLBufferCopyEmitter {
490 CodeGenFunction &CGF;
493 llvm::Type *LayoutTy =
nullptr;
495 SmallVector<llvm::Value *> CurStoreIndices;
496 SmallVector<llvm::Value *> CurLoadIndices;
498 using EmitResourceFnTy = llvm::function_ref<void(AggValueSlot &)>;
502 llvm::Value *emitAccessChain(llvm::Type *BaseTy, llvm::Value *Base,
503 ArrayRef<llvm::Value *> Indices) {
504 bool EmitLogical = CGF.getLangOpts().EmitLogicalPointer;
506 return CGF.Builder.CreateAccessChain(EmitLogical, BaseTy, Base, Indices);
508 llvm::SmallVector<llvm::Value *> GEPIndices;
509 GEPIndices.reserve(Indices.size() + 1);
510 GEPIndices.push_back(llvm::ConstantInt::get(CGF.IntTy, 0));
511 GEPIndices.append(Indices.begin(), Indices.end());
512 return CGF.Builder.CreateAccessChain(EmitLogical, BaseTy, Base, GEPIndices);
515 bool isBufferLayoutArray(llvm::StructType *ST) {
521 if (!ST || ST->getNumElements() != 2)
524 auto *PaddedEltsTy = dyn_cast<llvm::ArrayType>(ST->getElementType(0));
528 auto *PaddedTy = dyn_cast<llvm::StructType>(PaddedEltsTy->getElementType());
529 if (!PaddedTy || PaddedTy->getNumElements() != 2)
532 if (!CGF.CGM.getTargetCodeGenInfo().isHLSLPadding(
533 PaddedTy->getElementType(1)))
536 llvm::Type *ElementTy = ST->getElementType(1);
537 if (PaddedTy->getElementType(0) != ElementTy)
548 bool isResourceOrResourceArray(llvm::Type *Ty) {
549 while (
auto *AT = dyn_cast<llvm::ArrayType>(Ty))
550 Ty = AT->getElementType();
552 auto *ST = dyn_cast<llvm::StructType>(Ty);
553 if (!ST || ST->getNumElements() < 1)
556 auto *TargetTy = dyn_cast<llvm::TargetExtType>(ST->getElementType(0));
557 return TargetTy !=
nullptr;
560 void emitResourceOrResourceArray(
Value *Dst, llvm::Type *DstTy,
561 EmitResourceFnTy EmitResFn) {
564 Address DstAddr(Dst, DstTy, DstAlign);
573 void emitBufferLayoutCopy(
Value *Src, llvm::StructType *SrcTy,
Value *Dst,
574 llvm::ArrayType *DstTy,
575 EmitResourceFnTy EmitResFn) {
578 assert(SrcPaddedArrayTy->getNumElements() + 1 == DstTy->getNumElements());
580 ->getElementType(0) == SrcTy->getElementType(1));
582 auto *SrcDataTy = SrcTy->getElementType(1);
583 auto Zero = llvm::ConstantInt::get(CGF.IntTy, 0);
585 for (
unsigned I = 0; I < SrcPaddedArrayTy->getNumElements(); ++I) {
586 auto Index = llvm::ConstantInt::get(CGF.IntTy, I);
587 auto *SrcElt = emitAccessChain(SrcTy, Src, {
Zero, Index,
Zero});
588 auto *DstElt = emitAccessChain(DstTy, Dst, {Index});
589 emitElementCopy(SrcElt, SrcDataTy, DstElt, DstTy->getElementType(),
594 emitAccessChain(SrcTy, Src, {llvm::ConstantInt::get(CGF.IntTy, 1)});
595 auto *DstElt = emitAccessChain(
597 {llvm::ConstantInt::get(CGF.IntTy, DstTy->getNumElements() - 1)});
598 emitElementCopy(SrcElt, SrcDataTy, DstElt, DstTy->getElementType(),
602 void emitCopy(
Value *Src, llvm::StructType *SrcTy,
Value *Dst,
603 llvm::Type *DstTy, EmitResourceFnTy EmitResFn) {
604 assert(!isResourceOrResourceArray(DstTy) &&
605 "direct access to resources or resource arrays should be handled "
608 if (isBufferLayoutArray(SrcTy))
612 unsigned SrcIndex = 0;
613 unsigned DstIndex = 0;
620 while (DstIndex < DstST->getNumElements()) {
621 llvm::Type *DstEltTy = DstST->getElementType(DstIndex);
622 if (CGF.CGM.getTargetCodeGenInfo().isHLSLPadding(DstEltTy)) {
626 if (isResourceOrResourceArray(DstEltTy)) {
627 auto *DstElt = emitAccessChain(
628 DstTy, Dst, {llvm::ConstantInt::get(CGF.IntTy, DstIndex)});
629 emitResourceOrResourceArray(DstElt, DstEltTy, EmitResFn);
634 assert(SrcIndex < SrcTy->getNumElements());
635 llvm::Type *SrcEltTy = SrcTy->getElementType(SrcIndex);
636 if (CGF.CGM.getTargetCodeGenInfo().isHLSLPadding(SrcEltTy)) {
641 auto *SrcElt = emitAccessChain(
642 SrcTy, Src, {llvm::ConstantInt::get(CGF.IntTy, SrcIndex)});
643 auto *DstElt = emitAccessChain(
644 DstTy, Dst, {llvm::ConstantInt::get(CGF.IntTy, DstIndex)});
645 emitElementCopy(SrcElt, SrcEltTy, DstElt, DstEltTy, EmitResFn);
651 void emitCopy(
Value *Src, llvm::ArrayType *SrcTy,
Value *Dst,
652 llvm::Type *DstTy, EmitResourceFnTy EmitResFn) {
653 for (
unsigned I = 0, E = SrcTy->getNumElements(); I < E; ++I) {
655 emitAccessChain(SrcTy, Src, {llvm::ConstantInt::get(CGF.IntTy, I)});
657 emitAccessChain(DstTy, Dst, {llvm::ConstantInt::get(CGF.IntTy, I)});
658 emitElementCopy(SrcElt, SrcTy->getElementType(), DstElt,
664 void emitElementCopy(
Value *Src, llvm::Type *SrcTy,
Value *Dst,
665 llvm::Type *DstTy, EmitResourceFnTy EmitResFn) {
666 if (
auto *AT = dyn_cast<llvm::ArrayType>(SrcTy))
667 return emitCopy(Src, AT, Dst, DstTy, EmitResFn);
668 if (
auto *ST = dyn_cast<llvm::StructType>(SrcTy))
669 return emitCopy(Src, ST, Dst, DstTy, EmitResFn);
676 Address SrcAddr(Src, SrcTy, SrcAlign);
677 Address DstAddr(Dst, DstTy, DstAlign);
678 llvm::Value *
Load = CGF.Builder.CreateLoad(SrcAddr,
"cbuf.load");
679 CGF.Builder.CreateStore(Load, DstAddr);
683 HLSLBufferCopyEmitter(CodeGenFunction &CGF, Address DstPtr, Address SrcPtr)
684 : CGF(CGF), DstPtr(DstPtr), SrcPtr(SrcPtr) {}
686 bool emitCopy(QualType CType, EmitResourceFnTy EmitResFn =
nullptr) {
687 LayoutTy = HLSLBufferLayoutBuilder(CGF.CGM).layOutType(CType);
694 emitElementCopy(SrcPtr.getBasePointer(), LayoutTy, DstPtr.getBasePointer(),
695 DstPtr.getElementType(), EmitResFn);
706class AssociatedResourcesList {
711 specific_attr_iterator<HLSLAssociatedResourceDeclAttr> Begin, End, Next;
714 AssociatedResourcesList(
const VarDecl *StructVD,
715 StringRef ResourceNamePrefix) {
721 !I->getResDecl()->getName().starts_with(ResourceNamePrefix))
723 assert(I != E &&
"expected associated resource not found");
728 while (I != E && ((HLSLAssociatedResourceDeclAttr *)*I)
731 .starts_with(ResourceNamePrefix))
737 const VarDecl *getNextResource() {
741 const VarDecl *Res = Next->getResDecl();
752 assert(
T->isHLSLSpecificType() &&
"Not an HLSL specific type!");
755 if (llvm::Type *TargetTy =
759 llvm_unreachable(
"Generic handling of HLSL types is not supported.");
762llvm::Triple::ArchType CGHLSLRuntime::getArch() {
768void CGHLSLRuntime::emitBufferGlobalsAndMetadata(
774 llvm::Type *BufType = BufGV->getValueType();
779 size_t OffsetIdx = 0;
789 VarDecl *VD = dyn_cast<VarDecl>(D);
805 DeclsWithOffset.emplace_back(VD, OffsetInfo[OffsetIdx++]);
808 if (!OffsetInfo.
empty())
809 llvm::stable_sort(DeclsWithOffset, [](
const auto &LHS,
const auto &RHS) {
814 SmallVector<llvm::Metadata *> BufGlobals;
815 BufGlobals.reserve(DeclsWithOffset.size() + 1);
816 BufGlobals.push_back(ValueAsMetadata::get(BufGV));
818 auto ElemIt = LayoutStruct->element_begin();
819 for (
auto &[VD, _] : DeclsWithOffset) {
823 assert(ElemIt != LayoutStruct->element_end() &&
824 "number of elements in layout struct does not match");
825 llvm::Type *LayoutType = *ElemIt++;
827 GlobalVariable *ElemGV =
829 BufGlobals.push_back(ValueAsMetadata::get(ElemGV));
831 assert(ElemIt == LayoutStruct->element_end() &&
832 "number of elements in layout struct does not match");
836 .getOrInsertNamedMetadata(
"hlsl.cbs")
837 ->addOperand(MDNode::get(Ctx, BufGlobals));
841static const clang::HLSLAttributedResourceType *
846 HLSLAttributedResourceType::Attributes(ResourceClass::CBuffer));
861 VarDecl *VD = dyn_cast<VarDecl>(D);
872 if (
auto *POA = dyn_cast<HLSLPackOffsetAttr>(
Attr)) {
873 Offset = POA->getOffsetInBytes();
876 auto *RBA = dyn_cast<HLSLResourceBindingAttr>(
Attr);
878 RBA->getRegisterType() == HLSLResourceBindingAttr::RegisterType::C) {
879 Offset = RBA->getSlotNumber() * CBufferRowSizeInBytes;
883 Result.Offsets.push_back(Offset);
891 assert(BufDecl->
isCBuffer() &&
"tbuffer codegen is not supported yet");
894 const clang::HLSLAttributedResourceType *ResHandleTy =
898 if (ResHandleTy->getContainedType()->getAsCXXRecordDecl()->isEmpty())
904 llvm::GlobalVariable *BufGV =
new GlobalVariable(
906 GlobalValue::LinkageTypes::InternalLinkage, PoisonValue::get(LayoutTy),
907 llvm::formatv(
"{0}{1}", BufDecl->
getName(),
909 GlobalValue::NotThreadLocal);
912 M.insertGlobalVariable(BufGV);
917 llvm::appendToCompilerUsed(M, {BufGV});
920 emitBufferGlobalsAndMetadata(BufDecl, BufGV, OffsetInfo);
923 initializeBufferFromBinding(BufDecl, BufGV);
929 Triple
T(M.getTargetTriple());
932 if (
T.getEnvironment() != Triple::EnvironmentType::RootSignature)
935 addRootSignatureMD(SignatureDecl->
getVersion(),
941 const auto Entry = LayoutTypes.find(StructType);
942 if (Entry != LayoutTypes.end())
943 return Entry->getSecond();
948 llvm::StructType *LayoutTy) {
950 "layout type for this struct already exist");
951 LayoutTypes[StructType] = LayoutTy;
959 Triple
T(M.getTargetTriple());
960 if (
T.getArch() == Triple::ArchType::dxil)
961 addDxilValVersion(TargetOpts.DxilValidatorVersion, M);
962 if (!CodeGenOpts.DisableDXSourceMetadata &&
963 CodeGenOpts.getDebugInfo() >=
964 llvm::codegenoptions::DebugInfoKind::DebugInfoConstructor)
965 addSourceInfo(CGM, M);
966 if (CodeGenOpts.ResMayAlias)
967 M.setModuleFlag(llvm::Module::ModFlagBehavior::Error,
"dx.resmayalias", 1);
968 if (CodeGenOpts.AllResourcesBound)
969 M.setModuleFlag(llvm::Module::ModFlagBehavior::Error,
970 "dx.allresourcesbound", 1);
971 if (CodeGenOpts.OptimizationLevel == 0)
972 M.addModuleFlag(llvm::Module::ModFlagBehavior::Override,
973 "dx.disable_optimizations", 1);
978 if (LangOpts.NativeHalfType)
979 M.setModuleFlag(llvm::Module::ModFlagBehavior::Error,
"dx.nativelowprec",
982 if (LangOpts.HLSLSpvPreserveInterface &&
T.isSPIRV()) {
988 for (GlobalVariable &GV : M.globals()) {
989 unsigned AS = GV.getAddressSpace();
990 if (AS == InputAS || AS == OutputAS)
991 InterfaceVars.push_back(&GV);
993 if (!InterfaceVars.empty())
994 appendToCompilerUsed(M, InterfaceVars);
1002 const auto *ShaderAttr = FD->
getAttr<HLSLShaderAttr>();
1003 assert(ShaderAttr &&
"All entry functions must have a HLSLShaderAttr");
1004 const StringRef ShaderAttrKindStr =
"hlsl.shader";
1005 Fn->addFnAttr(ShaderAttrKindStr,
1006 llvm::Triple::getEnvironmentTypeName(ShaderAttr->getType()));
1007 if (HLSLNumThreadsAttr *NumThreadsAttr = FD->
getAttr<HLSLNumThreadsAttr>()) {
1008 const StringRef NumThreadsKindStr =
"hlsl.numthreads";
1009 std::string NumThreadsStr =
1010 formatv(
"{0},{1},{2}", NumThreadsAttr->getX(), NumThreadsAttr->getY(),
1011 NumThreadsAttr->getZ());
1012 Fn->addFnAttr(NumThreadsKindStr, NumThreadsStr);
1014 if (HLSLWaveSizeAttr *WaveSizeAttr = FD->
getAttr<HLSLWaveSizeAttr>()) {
1015 const StringRef WaveSizeKindStr =
"hlsl.wavesize";
1016 std::string WaveSizeStr =
1017 formatv(
"{0},{1},{2}", WaveSizeAttr->getMin(), WaveSizeAttr->getMax(),
1018 WaveSizeAttr->getPreferred());
1019 Fn->addFnAttr(WaveSizeKindStr, WaveSizeStr);
1026 Fn->addFnAttr(llvm::Attribute::NoInline);
1028 if (CGM.
getLangOpts().HLSLSpvEnableMaximalReconvergence) {
1029 Fn->addFnAttr(
"enable-maximal-reconvergence",
"true");
1034 if (
const auto *VT = dyn_cast<FixedVectorType>(Ty)) {
1036 for (
unsigned I = 0; I < VT->getNumElements(); ++I) {
1037 Value *Elt = B.CreateCall(F, {B.getInt32(I)});
1042 return B.CreateCall(F, {B.getInt32(0)});
1047 LLVMContext &Ctx = GV->getContext();
1048 IRBuilder<> B(GV->getContext());
1049 MDNode *Operands = MDNode::get(
1051 {ConstantAsMetadata::get(B.getInt32( 11)),
1052 ConstantAsMetadata::get(B.getInt32(BuiltIn))});
1053 MDNode *Decoration = MDNode::get(Ctx, {Operands});
1054 GV->addMetadata(
"spirv.Decorations", *Decoration);
1058 LLVMContext &Ctx = GV->getContext();
1059 IRBuilder<> B(GV->getContext());
1061 MDNode::get(Ctx, {ConstantAsMetadata::get(B.getInt32( 30)),
1062 ConstantAsMetadata::get(B.getInt32(Location))});
1063 MDNode *Decoration = MDNode::get(Ctx, {Operands});
1064 GV->addMetadata(
"spirv.Decorations", *Decoration);
1074 if (
auto *AT = dyn_cast<llvm::ArrayType>(Ty)) {
1075 Ty = AT->getElementType();
1078 if (
auto *VT = dyn_cast<llvm::FixedVectorType>(Ty)) {
1079 Ty = VT->getElementType();
1084 return Ty->isIntegerTy() || Ty->isDoubleTy();
1088 llvm::Type *Ty,
const Twine &Name,
1089 unsigned BuiltInID) {
1090 auto *GV =
new llvm::GlobalVariable(
1091 M, Ty,
true, llvm::GlobalValue::ExternalLinkage,
1092 nullptr, Name,
nullptr,
1093 llvm::GlobalVariable::GeneralDynamicTLSModel,
1096 GV->setVisibility(llvm::GlobalValue::HiddenVisibility);
1097 return B.CreateLoad(Ty, GV);
1101 llvm::Type *Ty,
unsigned Location,
1102 StringRef Name,
bool NeedsFlat) {
1103 auto *GV =
new llvm::GlobalVariable(
1104 M, Ty,
true, llvm::GlobalValue::ExternalLinkage,
1105 nullptr, Name,
nullptr,
1106 llvm::GlobalVariable::GeneralDynamicTLSModel,
1108 GV->setVisibility(llvm::GlobalValue::HiddenVisibility);
1113 LLVMContext &Ctx = GV->getContext();
1115 Decorations.push_back(
1116 MDNode::get(Ctx, {ConstantAsMetadata::get(
1118 ConstantAsMetadata::get(B.getInt32(Location))}));
1120 Decorations.push_back(
1121 MDNode::get(Ctx, {ConstantAsMetadata::get(
1122 B.getInt32( 14))}));
1123 GV->addMetadata(
"spirv.Decorations", *MDNode::get(Ctx, Decorations));
1125 return B.CreateLoad(Ty, GV);
1128llvm::Value *CGHLSLRuntime::emitSPIRVUserSemanticLoad(
1129 llvm::IRBuilder<> &B,
const FunctionDecl *FD, llvm::Type *
Type,
1130 const clang::DeclaratorDecl *
Decl, HLSLAppliedSemanticAttr *Semantic,
1131 std::optional<unsigned> Index) {
1132 Twine BaseName = Twine(Semantic->getAttrName()->getName());
1133 Twine VariableName = BaseName.concat(Twine(Index.value_or(0)));
1135 unsigned Location = SPIRVLastAssignedInputSemanticLocation;
1136 if (
auto *L =
Decl->getAttr<HLSLVkLocationAttr>())
1137 Location = L->getLocation();
1141 llvm::ArrayType *AT = dyn_cast<llvm::ArrayType>(
Type);
1142 unsigned ElementCount = AT ? AT->getNumElements() : 1;
1143 SPIRVLastAssignedInputSemanticLocation += ElementCount;
1145 const auto *ShaderAttr = FD->
getAttr<HLSLShaderAttr>();
1148 ShaderAttr->getType() == llvm::Triple::EnvironmentType::Pixel &&
1152 VariableName.str(), NeedsFlat);
1156 llvm::Value *Source,
unsigned Location,
1158 auto *GV =
new llvm::GlobalVariable(
1159 M, Source->getType(),
false,
1160 llvm::GlobalValue::ExternalLinkage,
1161 nullptr, Name,
nullptr,
1162 llvm::GlobalVariable::GeneralDynamicTLSModel,
1164 GV->setVisibility(llvm::GlobalValue::HiddenVisibility);
1166 B.CreateStore(Source, GV);
1169void CGHLSLRuntime::emitSPIRVUserSemanticStore(
1170 llvm::IRBuilder<> &B, llvm::Value *Source,
1171 const clang::DeclaratorDecl *
Decl, HLSLAppliedSemanticAttr *Semantic,
1172 std::optional<unsigned> Index) {
1173 Twine BaseName = Twine(Semantic->getAttrName()->getName());
1174 Twine VariableName = BaseName.concat(Twine(Index.value_or(0)));
1176 unsigned Location = SPIRVLastAssignedOutputSemanticLocation;
1177 if (
auto *L =
Decl->getAttr<HLSLVkLocationAttr>())
1178 Location = L->getLocation();
1182 llvm::ArrayType *AT = dyn_cast<llvm::ArrayType>(Source->getType());
1183 unsigned ElementCount = AT ? AT->getNumElements() : 1;
1184 SPIRVLastAssignedOutputSemanticLocation += ElementCount;
1186 VariableName.str());
1190CGHLSLRuntime::emitDXILUserSemanticLoad(llvm::IRBuilder<> &B, llvm::Type *
Type,
1191 HLSLAppliedSemanticAttr *Semantic,
1192 std::optional<unsigned> Index) {
1193 Twine BaseName = Twine(Semantic->getAttrName()->getName());
1194 Twine VariableName = BaseName.concat(Twine(Index.value_or(0)));
1199 SmallVector<Value *> Args{B.getInt32(4), B.getInt32(0), B.getInt32(0),
1201 llvm::PoisonValue::get(B.getInt32Ty())};
1203 llvm::Intrinsic::ID IntrinsicID = llvm::Intrinsic::dx_load_input;
1205 SmallVector<OperandBundleDef, 1> OB;
1207 llvm::Value *bundleArgs[] = {Token};
1208 OB.emplace_back(
"convergencectrl", bundleArgs);
1211 llvm::Function *IntrFn = llvm::Intrinsic::getOrInsertDeclaration(
1212 B.GetInsertBlock()->getModule(), IntrinsicID, {Type});
1213 llvm::Value *
Value = B.CreateCall(IntrFn, Args, OB, VariableName);
1217void CGHLSLRuntime::emitDXILUserSemanticStore(llvm::IRBuilder<> &B,
1218 llvm::Value *Source,
1219 HLSLAppliedSemanticAttr *Semantic,
1220 std::optional<unsigned> Index) {
1223 SmallVector<Value *> Args{B.getInt32(4),
1227 llvm::PoisonValue::get(B.getInt32Ty()),
1230 llvm::Intrinsic::ID IntrinsicID = llvm::Intrinsic::dx_store_output;
1232 SmallVector<OperandBundleDef, 1> OB;
1234 llvm::Value *bundleArgs[] = {Token};
1235 OB.emplace_back(
"convergencectrl", bundleArgs);
1238 llvm::Function *IntrFn = llvm::Intrinsic::getOrInsertDeclaration(
1239 B.GetInsertBlock()->getModule(), IntrinsicID, {Source->getType()});
1240 B.CreateCall(IntrFn, Args, OB);
1243llvm::Value *CGHLSLRuntime::emitUserSemanticLoad(
1244 IRBuilder<> &B,
const FunctionDecl *FD, llvm::Type *
Type,
1245 const clang::DeclaratorDecl *
Decl, HLSLAppliedSemanticAttr *Semantic,
1246 std::optional<unsigned> Index) {
1248 return emitSPIRVUserSemanticLoad(B, FD,
Type,
Decl, Semantic, Index);
1251 return emitDXILUserSemanticLoad(B,
Type, Semantic, Index);
1253 llvm_unreachable(
"Unsupported target for user-semantic load.");
1256void CGHLSLRuntime::emitUserSemanticStore(IRBuilder<> &B, llvm::Value *Source,
1257 const clang::DeclaratorDecl *
Decl,
1258 HLSLAppliedSemanticAttr *Semantic,
1259 std::optional<unsigned> Index) {
1261 return emitSPIRVUserSemanticStore(B, Source,
Decl, Semantic, Index);
1264 return emitDXILUserSemanticStore(B, Source, Semantic, Index);
1266 llvm_unreachable(
"Unsupported target for user-semantic load.");
1272 std::optional<unsigned> Index) {
1274 std::string SemanticName = Semantic->getAttrName()->getName().upper();
1275 if (SemanticName ==
"SV_GROUPINDEX") {
1276 llvm::Function *GroupIndex =
1277 CGM.
getIntrinsic(getFlattenedThreadIdInGroupIntrinsic());
1278 return B.CreateCall(FunctionCallee(GroupIndex));
1281 if (SemanticName ==
"SV_DISPATCHTHREADID") {
1282 llvm::Intrinsic::ID IntrinID = getThreadIdIntrinsic();
1283 llvm::Function *ThreadIDIntrinsic =
1284 llvm::Intrinsic::isOverloaded(IntrinID)
1290 if (SemanticName ==
"SV_GROUPTHREADID") {
1291 llvm::Intrinsic::ID IntrinID = getGroupThreadIdIntrinsic();
1292 llvm::Function *GroupThreadIDIntrinsic =
1293 llvm::Intrinsic::isOverloaded(IntrinID)
1299 if (SemanticName ==
"SV_GROUPID") {
1300 llvm::Intrinsic::ID IntrinID = getGroupIdIntrinsic();
1301 llvm::Function *GroupIDIntrinsic =
1302 llvm::Intrinsic::isOverloaded(IntrinID)
1308 const auto *ShaderAttr = FD->
getAttr<HLSLShaderAttr>();
1309 assert(ShaderAttr &&
"Entry point has no shader attribute");
1310 llvm::Triple::EnvironmentType ST = ShaderAttr->getType();
1312 if (SemanticName ==
"SV_POSITION") {
1313 if (ST == Triple::EnvironmentType::Pixel) {
1316 Semantic->getAttrName()->getName(),
1319 return emitDXILUserSemanticLoad(B,
Type, Semantic, Index);
1322 if (ST == Triple::EnvironmentType::Vertex) {
1323 return emitUserSemanticLoad(B, FD,
Type,
Decl, Semantic, Index);
1327 if (SemanticName ==
"SV_VERTEXID") {
1328 if (ST == Triple::EnvironmentType::Vertex) {
1331 Semantic->getAttrName()->getName(),
1334 return emitDXILUserSemanticLoad(B,
Type, Semantic, Index);
1339 "Load hasn't been implemented yet for this system semantic. FIXME");
1343 llvm::Value *Source,
const Twine &Name,
1344 unsigned BuiltInID) {
1345 auto *GV =
new llvm::GlobalVariable(
1346 M, Source->getType(),
false,
1347 llvm::GlobalValue::ExternalLinkage,
1348 nullptr, Name,
nullptr,
1349 llvm::GlobalVariable::GeneralDynamicTLSModel,
1352 GV->setVisibility(llvm::GlobalValue::HiddenVisibility);
1353 B.CreateStore(Source, GV);
1358 HLSLAppliedSemanticAttr *Semantic,
1359 std::optional<unsigned> Index) {
1361 std::string SemanticName = Semantic->getAttrName()->getName().upper();
1362 if (SemanticName ==
"SV_POSITION") {
1364 emitDXILUserSemanticStore(B, Source, Semantic, Index);
1370 Semantic->getAttrName()->getName(),
1376 if (SemanticName ==
"SV_TARGET") {
1377 emitUserSemanticStore(B, Source,
Decl, Semantic, Index);
1382 "Store hasn't been implemented yet for this system semantic. FIXME");
1389 std::optional<unsigned> Index = Semantic->getSemanticIndex();
1390 if (Semantic->getAttrName()->getName().starts_with_insensitive(
"SV_"))
1392 return emitUserSemanticLoad(B, FD,
Type,
Decl, Semantic, Index);
1396 IRBuilder<> &B,
const FunctionDecl *FD, llvm::Value *Source,
1398 std::optional<unsigned> Index = Semantic->getSemanticIndex();
1399 if (Semantic->getAttrName()->getName().starts_with_insensitive(
"SV_"))
1402 emitUserSemanticStore(B, Source,
Decl, Semantic, Index);
1405std::pair<llvm::Value *, specific_attr_iterator<HLSLAppliedSemanticAttr>>
1418 for (
unsigned I = 0; I < ST->getNumElements(); ++I) {
1420 B, FD, ST->getElementType(I), *
FieldDecl, AttrBegin, AttrEnd);
1421 AttrBegin = NextAttr;
1427 return std::make_pair(
Aggregate, AttrBegin);
1432 IRBuilder<> &B,
const FunctionDecl *FD, llvm::Value *Source,
1443 RD =
Decl->getType()->getAsRecordDecl();
1449 for (
unsigned I = 0; I < ST->getNumElements(); ++I, ++
FieldDecl) {
1450 llvm::Value *Extract = B.CreateExtractValue(Source, I);
1458std::pair<llvm::Value *, specific_attr_iterator<HLSLAppliedSemanticAttr>>
1464 assert(AttrBegin != AttrEnd);
1465 if (
Type->isStructTy())
1468 HLSLAppliedSemanticAttr *
Attr = *AttrBegin;
1476 IRBuilder<> &B,
const FunctionDecl *FD, llvm::Value *Source,
1480 assert(AttrBegin != AttrEnd);
1481 if (Source->getType()->isStructTy())
1484 HLSLAppliedSemanticAttr *
Attr = *AttrBegin;
1491 llvm::Function *Fn) {
1493 llvm::LLVMContext &Ctx = M.getContext();
1494 auto *EntryTy = llvm::FunctionType::get(llvm::Type::getVoidTy(Ctx),
false);
1496 Function::Create(EntryTy, Function::ExternalLinkage, FD->
getName(), &M);
1500 AttributeList NewAttrs = AttributeList::get(Ctx, AttributeList::FunctionIndex,
1501 Fn->getAttributes().getFnAttrs());
1502 EntryFn->setAttributes(NewAttrs);
1506 Fn->setLinkage(GlobalValue::InternalLinkage);
1508 BasicBlock *BB = BasicBlock::Create(Ctx,
"entry", EntryFn);
1514 assert(EntryFn->isConvergent());
1516 B.CreateIntrinsic(llvm::Intrinsic::experimental_convergence_entry, {});
1517 llvm::Value *bundleArgs[] = {I};
1518 OB.emplace_back(
"convergencectrl", bundleArgs);
1523 unsigned SRetOffset = 0;
1524 for (
const auto &Param : Fn->args()) {
1525 if (Param.hasStructRetAttr()) {
1527 llvm::Type *VarType = Param.getParamStructRetType();
1532 OutputSemantic.push_back(std::make_pair(Var, VarType));
1533 Args.push_back(Var);
1538 llvm::Value *SemanticValue =
nullptr;
1540 if ([[maybe_unused]] HLSLParamModifierAttr *MA =
1541 PD->
getAttr<HLSLParamModifierAttr>()) {
1542 llvm_unreachable(
"Not handled yet");
1544 llvm::Type *ParamType =
nullptr;
1545 if (Param.hasByValAttr())
1546 ParamType = Param.getParamByValType();
1550 ParamType = Param.getType();
1556 SemanticValue =
Result.first;
1564 B.CreateStore(SemanticValue, Var);
1565 SemanticValue = Var;
1569 assert(SemanticValue);
1570 Args.push_back(SemanticValue);
1573 CallInst *CI = B.CreateCall(FunctionCallee(Fn), Args, OB);
1574 CI->setCallingConv(Fn->getCallingConv());
1576 if (Fn->getReturnType() != CGM.
VoidTy)
1578 OutputSemantic.push_back(std::make_pair(CI,
nullptr));
1580 for (
auto &SourcePair : OutputSemantic) {
1581 llvm::Value *Source = SourcePair.first;
1582 llvm::Type *ElementType = SourcePair.second;
1583 AllocaInst *AI = dyn_cast<AllocaInst>(Source);
1584 llvm::Value *SourceValue = AI ? B.CreateLoad(ElementType, Source) : Source;
1595 if (
const auto *RSAttr = dyn_cast<RootSignatureAttr>(
Attr)) {
1596 auto *RSDecl = RSAttr->getSignatureDecl();
1597 addRootSignatureMD(RSDecl->getVersion(), RSDecl->getRootElements(),
1606 M.getNamedGlobal(CtorOrDtor ?
"llvm.global_ctors" :
"llvm.global_dtors");
1609 const auto *CA = dyn_cast<ConstantArray>(GV->getInitializer());
1616 for (
const auto &Ctor : CA->operands()) {
1622 "HLSL doesn't support setting priority for global ctors.");
1624 "HLSL doesn't support COMDat for global ctors.");
1639 for (
auto &F : M.functions()) {
1640 if (!F.hasFnAttribute(
"hlsl.shader"))
1643 Instruction *IP = &*F.getEntryBlock().begin();
1646 llvm::Value *bundleArgs[] = {
Token};
1647 OB.emplace_back(
"convergencectrl", bundleArgs);
1648 IP =
Token->getNextNode();
1651 for (
auto *Fn : CtorFns) {
1652 auto CI = B.CreateCall(FunctionCallee(Fn), {}, OB);
1653 CI->setCallingConv(Fn->getCallingConv());
1657 B.SetInsertPoint(F.back().getTerminator());
1658 for (
auto *Fn : DtorFns) {
1659 auto CI = B.CreateCall(FunctionCallee(Fn), {}, OB);
1660 CI->setCallingConv(Fn->getCallingConv());
1666 Triple
T(M.getTargetTriple());
1667 if (
T.getEnvironment() != Triple::EnvironmentType::Library) {
1668 if (
auto *GV = M.getNamedGlobal(
"llvm.global_ctors"))
1669 GV->eraseFromParent();
1670 if (
auto *GV = M.getNamedGlobal(
"llvm.global_dtors"))
1671 GV->eraseFromParent();
1676 Intrinsic::ID IntrID,
1680 llvm::Function *InitResFunc =
1681 llvm::Function::Create(llvm::FunctionType::get(CGM.
VoidTy,
false),
1682 llvm::GlobalValue::InternalLinkage,
1683 "_init_buffer_" + GV->getName(), CGM.
getModule());
1684 InitResFunc->addFnAttr(llvm::Attribute::AlwaysInline);
1686 llvm::BasicBlock *EntryBB =
1687 llvm::BasicBlock::Create(Ctx,
"entry", InitResFunc);
1689 const DataLayout &DL = CGM.
getModule().getDataLayout();
1690 Builder.SetInsertPoint(EntryBB);
1693 llvm::Type *HandleTy = GV->getValueType();
1694 assert(HandleTy->isTargetExtTy() &&
"unexpected type of the buffer global");
1696 llvm::Value *CreateHandle = Builder.CreateIntrinsic(
1697 HandleTy, IntrID, Args,
nullptr,
1698 Twine(GV->getName()).concat(
"_h"));
1700 Builder.CreateAlignedStore(CreateHandle, GV, GV->getPointerAlignment(DL));
1701 Builder.CreateRetVoid();
1706void CGHLSLRuntime::initializeBufferFromBinding(
const HLSLBufferDecl *BufDecl,
1707 llvm::GlobalVariable *GV) {
1708 ResourceBindingAttrs Binding(BufDecl);
1710 "cbuffer/tbuffer should always have resource binding attribute");
1712 auto *Index = llvm::ConstantInt::get(CGM.
IntTy, 0);
1713 auto *RangeSize = llvm::ConstantInt::get(CGM.
IntTy, 1);
1714 auto *Space = llvm::ConstantInt::get(CGM.
IntTy, Binding.
getSpace());
1715 Value *Name = buildNameForResource(BufDecl->
getName(), CGM);
1719 llvm::Intrinsic::ID IntrinsicID =
1721 auto *RegSlot = llvm::ConstantInt::get(CGM.
IntTy, Binding.
getSlot());
1722 SmallVector<Value *> Args{Space, RegSlot, RangeSize, Index, Name};
1726 llvm::Intrinsic::ID IntrinsicID =
1727 CGM.
getHLSLRuntime().getCreateHandleFromImplicitBindingIntrinsic();
1730 SmallVector<Value *> Args{OrderID, Space, RangeSize, Index, Name};
1736 llvm::GlobalVariable *GV) {
1737 if (
auto Attr = VD->
getAttr<HLSLVkExtBuiltinInputAttr>())
1739 if (
auto Attr = VD->
getAttr<HLSLVkExtBuiltinOutputAttr>())
1748 for (
auto I = BB.begin(); I != E; ++I) {
1749 auto *II = dyn_cast<llvm::IntrinsicInst>(&*I);
1750 if (II && llvm::isConvergenceControlIntrinsic(II->getIntrinsicID())) {
1754 llvm_unreachable(
"Convergence token should have been emitted.");
1791 for (
auto *OVE : Visitor.
OVEs) {
1794 if (OpaqueValueMappingData::shouldBindAsLValue(OVE)) {
1796 OpaqueValueMappingData::bind(CGF, OVE, LV);
1799 OpaqueValueMappingData::bind(CGF, OVE, RV);
1808 "expected resource array subscript expression");
1813 const VarDecl *ArrayDecl = dyn_cast_or_null<VarDecl>(
1817 return std::nullopt;
1823 "expected array of resource classes");
1829 Value *Index =
nullptr;
1831 while (ASE !=
nullptr) {
1833 if (
const auto *ArrayTy =
1835 Value *Multiplier = llvm::ConstantInt::get(
1837 SubIndex = CGF.
Builder.CreateMul(SubIndex, Multiplier);
1839 Index = Index ? CGF.
Builder.CreateAdd(Index, SubIndex) : SubIndex;
1847 "resource array must have a binding attribute");
1868 llvm::Value *Range = llvm::ConstantInt::getSigned(
1869 CGM.
IntTy, getTotalArraySize(AST, ResArrayTy));
1873 if (ResultTy == ResourceTy) {
1875 CXXMethodDecl *CreateMethod = lookupResourceInitMethodAndSetupArgs(
1877 ArrayDecl->
getName(), Binding, Args);
1879 if (!CreateMethod) {
1884 "create method lookup should always succeed for built-in resource "
1886 return std::nullopt;
1889 callResourceInitMethod(CGF, CreateMethod, Args, ValueSlot.getAddress());
1896 std::optional<llvm::Value *> EndIndex = initializeResourceArrayFromGlobal(
1898 ArrayDecl->
getName(), Binding, {llvm::ConstantInt::get(CGM.IntTy, 0)});
1900 return std::nullopt;
1906bool CGHLSLRuntime::initializeGlobalResourceArray(
CodeGenFunction &CGF,
1912 "expected global non-static resource array");
1918 "resource array must have a binding attribute");
1923 const auto *ResArrayTy =
1927 int Size = getTotalArraySize(AST, ResArrayTy);
1928 llvm::Value *
Zero = llvm::ConstantInt::get(CGM.
IntTy, 0);
1929 llvm::Value *Range = llvm::ConstantInt::get(CGM.
IntTy, Size);
1932 std::optional<llvm::Value *> EndIndex = initializeResourceArrayFromGlobal(
1934 ArrayDecl->
getName(), Binding, {Zero});
1935 return EndIndex.has_value();
1944 "expected resource array");
1949 dyn_cast_or_null<VarDecl>(getArrayDecl(CGF.
CGM.
getContext(), E));
1954 return initializeGlobalResourceArray(CGF, ArrayDecl, DestSlot);
1961std::optional<LValue>
1965 "expected resource array declaration");
1969 return std::nullopt;
1973 if (initializeGlobalResourceArray(CGF, ArrayDecl, TmpArraySlot))
1976 return std::nullopt;
1984 "expected cbuffer matrix");
1995 HLSLBufferCopyEmitter(CGF, DestAlloca, SrcAddr).emitCopy(MatQualTy);
2001 llvm::function_ref<llvm::Value *(
bool Promote)> EmitIdxAfterBase) {
2005 llvm::Type *LayoutTy =
2007 uint64_t LayoutSizeInBits =
2008 CGM.
getDataLayout().getTypeSizeInBits(LayoutTy).getFixedValue();
2011 if (RowAlignedSize > ElementSize) {
2013 CGM, RowAlignedSize - ElementSize);
2014 assert(Padding &&
"No padding type for target?");
2015 LayoutTy = llvm::StructType::get(CGF.
getLLVMContext(), {LayoutTy, Padding},
2022 if (LayoutTy == OrigTy)
2023 return std::nullopt;
2032 llvm::Value *Idx = EmitIdxAfterBase(
true);
2033 Indices.push_back(Idx);
2034 Indices.push_back(llvm::ConstantInt::get(CGF.
Int32Ty, 0));
2040 assert(CE->
getCastKind() == CastKind::CK_ArrayToPointerDecay);
2044 LayoutTy = llvm::ArrayType::get(
2048 LayoutTy,
Addr.emitRawPointer(CGF), Indices,
"cbufferidx"));
2057 Indices,
"cbufferidx");
2062std::optional<LValue>
2067 "expected resource member expression");
2070 findAssociatedResourceDeclForStruct(CGF.
CGM.
getContext(), ME);
2072 return std::nullopt;
2078 GlobalVariable *ResGV =
2081 llvm::Type *Ty = ResGV->getValueType();
2094 "expected expression in HLSL constant address space");
2097 "direct accesses to resource types should be handled separately");
2109 return HLSLBufferCopyEmitter(CGF, DstPtr, SrcPtr).emitCopy(Ty);
2115 const VarDecl *VD = findStructResourceParentDeclAndBuildName(E, NameBuilder);
2116 AssociatedResourcesList AssociatedResources(VD, NameBuilder.
getName());
2120 const VarDecl *ResDecl = AssociatedResources.getNextResource();
2121 assert(ResDecl &&
"associated resource declaration not found");
2124 [[maybe_unused]] llvm::Type *DestType =
2125 ResSlot.getAddress().getElementType();
2126 [[maybe_unused]] llvm::Type *SrcConvertedType =
2128 assert(DestType == SrcConvertedType &&
"resource slot type mismatch");
2131 copyGlobalResource(CGF, ResDecl, ResSlot);
2133 initializeGlobalResourceArray(CGF, ResDecl, ResSlot);
2137 HLSLBufferCopyEmitter(CGF, DstPtr, SrcPtr).emitCopy(Ty, EmitResFn);
2138 assert(AssociatedResources.getNextResource() ==
nullptr &&
2139 "expected all associated resources to be processed");
2148 assert(Field &&
"Unexpected access into HLSL buffer");
2165 assert(FieldIdx < LayoutTy->getNumElements() &&
2166 "Layout struct is smaller than member struct");
2167 unsigned Skipped = 0;
2168 for (
unsigned I = 0; I <= FieldIdx;) {
2169 llvm::Type *ElementTy = LayoutTy->getElementType(I + Skipped);
2175 FieldIdx += Skipped;
2176 assert(FieldIdx < LayoutTy->getNumElements() &&
"Access out of bounds");
2180 QualType FieldType = Field->getType();
2186 ? CGF.
Builder.CreateStructuredGEP(
2187 LayoutTy,
Base.getPointer(CGF),
2188 llvm::ConstantInt::get(CGM.
IntTy, FieldIdx))
2190 FieldIdx, Field->getName());
Defines the clang::ASTContext interface.
static llvm::Value * createSPIRVBuiltinLoad(IRBuilder<> &B, llvm::Module &M, llvm::Type *Ty, const Twine &Name, unsigned BuiltInID)
static void addSPIRVBuiltinDecoration(llvm::GlobalVariable *GV, unsigned BuiltIn)
static void createSPIRVLocationStore(IRBuilder<> &B, llvm::Module &M, llvm::Value *Source, unsigned Location, StringRef Name)
static void gatherFunctions(SmallVectorImpl< Function * > &Fns, llvm::Module &M, bool CtorOrDtor)
static void addLocationDecoration(llvm::GlobalVariable *GV, unsigned Location)
static llvm::Value * createSPIRVLocationLoad(IRBuilder<> &B, llvm::Module &M, llvm::Type *Ty, unsigned Location, StringRef Name, 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 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()
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.
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) 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
Represent the declaration of a variable (in which case it is an lvalue) a function (in which case it ...
Represents a variable declaration or definition.
bool hasGlobalStorage() const
Returns true for all variables that do not have local storage.
StorageClass getStorageClass() const
Returns the storage class as written in the source.
void pushName(llvm::StringRef N)
void pushArrayIndex(uint64_t Index)
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.
bool hasCounterHandle(const CXXRecordDecl *RD)
StringRef getName(const HeaderType T)
@ Address
A pointer to a ValueDecl.
bool Load(InterpState &S, CodePtr OpPC)
The JSON file list parser is used to communicate input to InstallAPI.
bool isa(CodeGen::Address addr)
CustomizableOptional< FileEntryRef > OptionalFileEntryRef
std::vector< std::string > Macros
A list of macros of the form <definition>=<expansion> .
nullptr
This class represents a compute construct, representing a 'Kind' of ‘parallel’, 'serial',...
StorageClass
Storage classes.
@ Result
The result type of a method or function.
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