33#include "llvm/ADT/DenseMap.h"
34#include "llvm/ADT/Enum.h"
35#include "llvm/ADT/STLExtras.h"
36#include "llvm/ADT/ScopeExit.h"
37#include "llvm/ADT/SmallString.h"
38#include "llvm/ADT/SmallVector.h"
39#include "llvm/Frontend/HLSL/HLSLResource.h"
40#include "llvm/Frontend/HLSL/RootSignatureMetadata.h"
41#include "llvm/Frontend/HLSL/SemanticSignaturePacking.h"
42#include "llvm/IR/Constants.h"
43#include "llvm/IR/DerivedTypes.h"
44#include "llvm/IR/GlobalVariable.h"
45#include "llvm/IR/IntrinsicInst.h"
46#include "llvm/IR/LLVMContext.h"
47#include "llvm/IR/Metadata.h"
48#include "llvm/IR/Module.h"
49#include "llvm/IR/Type.h"
50#include "llvm/IR/Value.h"
51#include "llvm/Support/Alignment.h"
52#include "llvm/Support/ErrorHandling.h"
53#include "llvm/Support/FormatVariadic.h"
54#include "llvm/Support/Path.h"
55#include "llvm/Transforms/Utils/ModuleUtils.h"
65using llvm::hlsl::CBufferRowSizeInBytes;
69void addDxilValVersion(StringRef ValVersionStr, llvm::Module &M) {
73 if (Version.tryParse(ValVersionStr) || Version.getBuild() ||
74 Version.getSubminor() || !Version.getMinor()) {
78 uint64_t Major = Version.getMajor();
79 uint64_t Minor = *Version.getMinor();
81 auto &Ctx = M.getContext();
83 MDNode *Val = MDNode::get(Ctx, {ConstantAsMetadata::get(B.getInt32(Major)),
84 ConstantAsMetadata::get(B.getInt32(Minor))});
85 StringRef DXILValKey =
"dx.valver";
86 auto *DXILValMD = M.getOrInsertNamedMetadata(DXILValKey);
87 DXILValMD->addOperand(Val);
90void addRootSignatureMD(llvm::dxbc::RootSignatureVersion RootSigVer,
92 llvm::Function *Fn, llvm::Module &M) {
93 auto &Ctx = M.getContext();
95 llvm::hlsl::rootsig::MetadataBuilder RSBuilder(M, Elements);
96 MDNode *RootSignature = RSBuilder.BuildRootSignature();
98 ConstantAsMetadata *Version = ConstantAsMetadata::get(ConstantInt::get(
99 llvm::Type::getInt32Ty(Ctx), llvm::to_underlying(RootSigVer)));
100 ValueAsMetadata *EntryFunc =
Fn ? ValueAsMetadata::get(Fn) :
nullptr;
101 MDNode *MDVals = MDNode::get(Ctx, {EntryFunc, RootSignature, Version});
103 StringRef RootSignatureValKey =
"dx.rootsignatures";
104 auto *RootSignatureValMD = M.getOrInsertNamedMetadata(RootSignatureValKey);
105 RootSignatureValMD->addOperand(MDVals);
110 llvm::Triple::EnvironmentType Stage, llvm::hlsl::IOType IOTy,
112 bool UseNative16BitTypes) {
113 using namespace llvm::hlsl;
116 if (Stage == llvm::Triple::Vertex && IOTy == IOType::In)
117 return packSignatureStacked(Elements, Stage, IOTy);
118 if (Stage == llvm::Triple::Pixel && IOTy == IOType::Out)
119 return packSignatureIndexed(Elements, Stage, IOTy);
121 return packSignatureOptimized(Elements, Stage, IOTy, UseNative16BitTypes);
122 return packSignaturePrefixStable(Elements, Stage, IOTy, UseNative16BitTypes);
125MDNode *buildSemanticSignatureMD(
127 if (Elements.empty())
131 for (
const llvm::hlsl::SemanticSignatureElement &Element : Elements)
132 ElementMD.push_back(Element.toMetadata(Ctx));
133 return MDNode::get(Ctx, ElementMD);
136void addSemanticSignatureMD(
139 llvm::Function *Fn, llvm::Module &M) {
140 if (InputElements.empty() && OutputElements.empty())
143 LLVMContext &Ctx = M.getContext();
144 MDNode *InputSignature = buildSemanticSignatureMD(InputElements, Ctx);
145 MDNode *OutputSignature = buildSemanticSignatureMD(OutputElements, Ctx);
146 MDNode *MDVals = MDNode::get(
147 Ctx, {ValueAsMetadata::get(Fn), InputSignature, OutputSignature});
149 M.getOrInsertNamedMetadata(
"dx.semantic.signatures")->addOperand(MDVals);
154 GlobalVariable *ResGV =
156 assert(ResGV &&
"expected valid global variable");
173static const VarDecl *findStructResourceParentDeclAndBuildName(
180 if (
const auto *DRE = dyn_cast<DeclRefExpr>(E)) {
182 "member expr base is not a var decl");
188 WorkList.push_back(E);
189 if (
const auto *MExp = dyn_cast<MemberExpr>(E))
191 else if (
const auto *ICE = dyn_cast<ImplicitCastExpr>(E))
192 E = ICE->getSubExpr();
193 else if (
const auto *ASE = dyn_cast<ArraySubscriptExpr>(E))
200 llvm_unreachable(
"unexpected expr type in resource member access");
202 assert(E &&
"expected valid expression");
205 while (!WorkList.empty()) {
206 E = WorkList.pop_back_val();
207 if (
const auto *ME = dyn_cast<MemberExpr>(E)) {
209 ME->getMemberNameInfo().getName().getAsIdentifierInfo()->getName());
210 }
else if (
const auto *ICE = dyn_cast<ImplicitCastExpr>(E)) {
211 if (ICE->getCastKind() == CK_UncheckedDerivedToBase) {
213 ICE->getSubExpr()->getType()->getAsCXXRecordDecl();
214 CXXRecordDecl *BaseRD = ICE->getType()->getAsCXXRecordDecl();
217 }
else if (
const auto *ASE = dyn_cast<ArraySubscriptExpr>(E)) {
218 const Expr *IdxExpr = ASE->getIdx();
219 std::optional<llvm::APSInt>
Value =
222 "expected constant index in struct with resource array access");
225 llvm_unreachable(
"unexpected expr type in resource member access");
239 findStructResourceParentDeclAndBuildName(ME, NameBuilder);
248 if (
const auto *ADA = dyn_cast<HLSLAssociatedResourceDeclAttr>(A)) {
249 VarDecl *AssocResVD = ADA->getResDecl();
261 auto &Ctx = M.getContext();
264 llvm::NamedMDNode *DXContents =
265 M.getOrInsertNamedMetadata(
"dx.source.contents");
266 auto addFile = [&](
const std::pair<StringRef, StringRef> &NameContent) {
267 llvm::MDTuple *FileInfo =
268 llvm::MDNode::get(Ctx, {llvm::MDString::get(Ctx, NameContent.first),
269 llvm::MDString::get(Ctx, NameContent.second)});
270 DXContents->addOperand(FileInfo);
275 &SM.getSLocEntry(SM.getMainFileID(), &
Invalid);
276 assert(!
Invalid &&
"Main file SLocEntry must not be invalid!");
281 std::optional<SmallString<256>> MainFileName;
282 Files.reserve(SM.local_sloc_entry_size());
283 for (
unsigned I : llvm::seq(SM.local_sloc_entry_size())) {
298 llvm::sys::path::native(Path);
302 SM.getDiagnostics().Report(diag::warn_hlsl_failed_to_embed_source)
307 if (&MainCCEntry != &CCEntry) {
308 Files.emplace_back(Path, Buffer->getBuffer());
311 addFile(std::make_pair(Path, Buffer->getBuffer()));
312 MainFileName.emplace(Path);
315 assert(MainFileName &&
"Main file not found.");
320 for (
unsigned I = 1; I < Files.size(); ++I)
321 assert((Files[I - 1].first != Files[I].first) &&
322 "duplicate files in dx.source.contents");
324 llvm::for_each(Files, addFile);
327 Defines.reserve(
Macros.size());
328 for (
const auto &
Macro : Macros) {
331 Defines.emplace_back(llvm::MDString::get(Ctx,
Macro.first));
333 M.getOrInsertNamedMetadata(
"dx.source.defines")
334 ->addOperand(llvm::MDNode::get(Ctx, Defines));
336 if (!CodeGenOpts.MainFileName.empty())
337 llvm::sys::path::native(CodeGenOpts.MainFileName, *MainFileName);
338 M.getOrInsertNamedMetadata(
"dx.source.mainFileName")
340 llvm::MDNode::get(Ctx, llvm::MDString::get(Ctx, *MainFileName)));
343 Args.reserve(CodeGenOpts.HLSLParsedCommandLine.size());
344 if (!CodeGenOpts.HLSLParsedCommandLine.empty())
345 for (
const auto &Arg : llvm::drop_begin(CodeGenOpts.HLSLParsedCommandLine))
346 Args.push_back(llvm::MDString::get(Ctx, Arg));
347 M.getOrInsertNamedMetadata(
"dx.source.args")
348 ->addOperand(llvm::MDNode::get(Ctx, Args));
354 if (
const auto *DRE = dyn_cast_or_null<DeclRefExpr>(E))
355 return DRE->getDecl();
356 if (
auto *OVE = dyn_cast<OpaqueValueExpr>(E))
366 const Expr *E =
nullptr;
367 while (ASE !=
nullptr) {
371 ASE = dyn_cast<ArraySubscriptExpr>(E);
373 return getArrayDecl(AST, E);
379 assert(Ty->
isArrayType() &&
"expected array type");
385static Value *buildNameForResource(llvm::StringRef BaseName,
394 for (
auto *Method :
Record->methods()) {
395 if (Method->getStorageClass() == SC && Method->getName() == Name)
405 assert(Binding.
hasBinding() &&
"at least one binding attribute expected");
409 Value *NameStr = buildNameForResource(Name, CGM);
414 "resources with counter handle must have a binding with counter "
415 "implicit order ID");
418 auto *RegSlot = llvm::ConstantInt::get(CGM.
IntTy, Binding.
getSlot());
421 ?
"__createFromBindingWithImplicitCounter"
422 :
"__createFromBinding";
423 CreateMethod = lookupMethod(ResourceDecl, Name,
SC_Static);
430 ?
"__createFromImplicitBindingWithImplicitCounter"
431 :
"__createFromImplicitBinding";
432 CreateMethod = lookupMethod(ResourceDecl, Name,
SC_Static);
440 auto *CounterOrderID = llvm::ConstantInt::get(CGM.
IntTy, CounterBinding);
456 Args, Proto,
false,
nullptr);
459 CGF.
EmitCall(FnInfo, Callee, ReturnValue, Args,
nullptr);
468static std::optional<llvm::Value *> initializeResourceArrayFromGlobal(
471 llvm::Value *Range, llvm::Value *StartIndex, StringRef ResourceName,
475 llvm::IntegerType *IntTy = CGF.
CGM.
IntTy;
476 llvm::Value *Index = StartIndex;
477 llvm::Value *One = llvm::ConstantInt::get(IntTy, 1);
485 GEPIndices.push_back(llvm::ConstantInt::get(IntTy, 0));
490 for (uint64_t I = 0; I < ArraySize; I++) {
492 Index = CGF.
Builder.CreateAdd(Index, One);
493 GEPIndices.back() = llvm::ConstantInt::get(IntTy, I);
495 std::optional<llvm::Value *> MaybeIndex =
496 initializeResourceArrayFromGlobal(CGF, ResourceDecl, SubArrayTy,
497 ValueSlot, Range, Index,
498 ResourceName, Binding, GEPIndices);
512 for (uint64_t I = 0; I < ArraySize; I++) {
514 Index = CGF.
Builder.CreateAdd(Index, One);
515 GEPIndices.back() = llvm::ConstantInt::get(IntTy, I);
521 CXXMethodDecl *CreateMethod = lookupResourceInitMethodAndSetupArgs(
522 CGF.
CGM, ResourceDecl, Range, Index, ResourceName, Binding, Args);
530 callResourceInitMethod(CGF, CreateMethod, Args, ReturnAddress);
537class HLSLBufferCopyEmitter {
538 CodeGenFunction &CGF;
541 llvm::Type *LayoutTy =
nullptr;
543 SmallVector<llvm::Value *> CurStoreIndices;
544 SmallVector<llvm::Value *> CurLoadIndices;
546 using EmitResourceFnTy = llvm::function_ref<void(AggValueSlot &)>;
550 llvm::Value *emitAccessChain(llvm::Type *BaseTy, llvm::Value *Base,
551 ArrayRef<llvm::Value *> Indices) {
552 bool EmitLogical = CGF.getLangOpts().EmitLogicalPointer;
554 return CGF.Builder.CreateAccessChain(EmitLogical, BaseTy, Base, Indices);
556 llvm::SmallVector<llvm::Value *> GEPIndices;
557 GEPIndices.reserve(Indices.size() + 1);
558 GEPIndices.push_back(llvm::ConstantInt::get(CGF.IntTy, 0));
559 GEPIndices.append(Indices.begin(), Indices.end());
560 return CGF.Builder.CreateAccessChain(EmitLogical, BaseTy, Base, GEPIndices);
563 bool isBufferLayoutArray(llvm::StructType *ST) {
569 if (!ST || ST->getNumElements() != 2)
572 auto *PaddedEltsTy = dyn_cast<llvm::ArrayType>(ST->getElementType(0));
576 auto *PaddedTy = dyn_cast<llvm::StructType>(PaddedEltsTy->getElementType());
577 if (!PaddedTy || PaddedTy->getNumElements() != 2)
580 if (!CGF.CGM.getTargetCodeGenInfo().isHLSLPadding(
581 PaddedTy->getElementType(1)))
584 llvm::Type *ElementTy = ST->getElementType(1);
585 if (PaddedTy->getElementType(0) != ElementTy)
596 bool isResourceOrResourceArray(llvm::Type *Ty) {
597 while (
auto *AT = dyn_cast<llvm::ArrayType>(Ty))
598 Ty = AT->getElementType();
600 auto *ST = dyn_cast<llvm::StructType>(Ty);
601 if (!ST || ST->getNumElements() < 1)
604 auto *TargetTy = dyn_cast<llvm::TargetExtType>(ST->getElementType(0));
605 return TargetTy !=
nullptr;
608 void emitResourceOrResourceArray(
Value *Dst, llvm::Type *DstTy,
609 EmitResourceFnTy EmitResFn) {
612 Address DstAddr(Dst, DstTy, DstAlign);
621 void emitBufferLayoutCopy(
Value *Src, llvm::StructType *SrcTy,
Value *Dst,
622 llvm::ArrayType *DstTy,
623 EmitResourceFnTy EmitResFn) {
626 assert(SrcPaddedArrayTy->getNumElements() + 1 == DstTy->getNumElements());
628 ->getElementType(0) == SrcTy->getElementType(1));
630 auto *SrcDataTy = SrcTy->getElementType(1);
631 auto Zero = llvm::ConstantInt::get(CGF.IntTy, 0);
633 for (
unsigned I = 0; I < SrcPaddedArrayTy->getNumElements(); ++I) {
634 auto Index = llvm::ConstantInt::get(CGF.IntTy, I);
635 auto *SrcElt = emitAccessChain(SrcTy, Src, {
Zero, Index,
Zero});
636 auto *DstElt = emitAccessChain(DstTy, Dst, {Index});
637 emitElementCopy(SrcElt, SrcDataTy, DstElt, DstTy->getElementType(),
642 emitAccessChain(SrcTy, Src, {llvm::ConstantInt::get(CGF.IntTy, 1)});
643 auto *DstElt = emitAccessChain(
645 {llvm::ConstantInt::get(CGF.IntTy, DstTy->getNumElements() - 1)});
646 emitElementCopy(SrcElt, SrcDataTy, DstElt, DstTy->getElementType(),
650 void emitCopy(
Value *Src, llvm::StructType *SrcTy,
Value *Dst,
651 llvm::Type *DstTy, EmitResourceFnTy EmitResFn) {
652 assert(!isResourceOrResourceArray(DstTy) &&
653 "direct access to resources or resource arrays should be handled "
656 if (isBufferLayoutArray(SrcTy))
660 unsigned SrcIndex = 0;
661 unsigned DstIndex = 0;
668 while (DstIndex < DstST->getNumElements()) {
669 llvm::Type *DstEltTy = DstST->getElementType(DstIndex);
670 if (CGF.CGM.getTargetCodeGenInfo().isHLSLPadding(DstEltTy)) {
674 if (isResourceOrResourceArray(DstEltTy)) {
675 auto *DstElt = emitAccessChain(
676 DstTy, Dst, {llvm::ConstantInt::get(CGF.IntTy, DstIndex)});
677 emitResourceOrResourceArray(DstElt, DstEltTy, EmitResFn);
682 assert(SrcIndex < SrcTy->getNumElements());
683 llvm::Type *SrcEltTy = SrcTy->getElementType(SrcIndex);
684 if (CGF.CGM.getTargetCodeGenInfo().isHLSLPadding(SrcEltTy)) {
689 auto *SrcElt = emitAccessChain(
690 SrcTy, Src, {llvm::ConstantInt::get(CGF.IntTy, SrcIndex)});
691 auto *DstElt = emitAccessChain(
692 DstTy, Dst, {llvm::ConstantInt::get(CGF.IntTy, DstIndex)});
693 emitElementCopy(SrcElt, SrcEltTy, DstElt, DstEltTy, EmitResFn);
699 void emitCopy(
Value *Src, llvm::ArrayType *SrcTy,
Value *Dst,
700 llvm::Type *DstTy, EmitResourceFnTy EmitResFn) {
701 for (
unsigned I = 0, E = SrcTy->getNumElements(); I < E; ++I) {
703 emitAccessChain(SrcTy, Src, {llvm::ConstantInt::get(CGF.IntTy, I)});
705 emitAccessChain(DstTy, Dst, {llvm::ConstantInt::get(CGF.IntTy, I)});
706 emitElementCopy(SrcElt, SrcTy->getElementType(), DstElt,
712 void emitElementCopy(
Value *Src, llvm::Type *SrcTy,
Value *Dst,
713 llvm::Type *DstTy, EmitResourceFnTy EmitResFn) {
714 if (
auto *AT = dyn_cast<llvm::ArrayType>(SrcTy))
715 return emitCopy(Src, AT, Dst, DstTy, EmitResFn);
716 if (
auto *ST = dyn_cast<llvm::StructType>(SrcTy))
717 return emitCopy(Src, ST, Dst, DstTy, EmitResFn);
724 Address SrcAddr(Src, SrcTy, SrcAlign);
725 Address DstAddr(Dst, DstTy, DstAlign);
726 llvm::Value *
Load = CGF.Builder.CreateLoad(SrcAddr,
"cbuf.load");
727 CGF.Builder.CreateStore(Load, DstAddr);
731 HLSLBufferCopyEmitter(CodeGenFunction &CGF, Address DstPtr, Address SrcPtr)
732 : CGF(CGF), DstPtr(DstPtr), SrcPtr(SrcPtr) {}
734 bool emitCopy(QualType CType, EmitResourceFnTy EmitResFn =
nullptr) {
735 LayoutTy = HLSLBufferLayoutBuilder(CGF.CGM).layOutType(CType);
742 emitElementCopy(SrcPtr.getBasePointer(), LayoutTy, DstPtr.getBasePointer(),
743 DstPtr.getElementType(), EmitResFn);
754class AssociatedResourcesList {
759 specific_attr_iterator<HLSLAssociatedResourceDeclAttr> Begin, End, Next;
762 AssociatedResourcesList(
const VarDecl *StructVD,
763 StringRef ResourceNamePrefix) {
769 !I->getResDecl()->getName().starts_with(ResourceNamePrefix))
771 assert(I != E &&
"expected associated resource not found");
776 while (I != E && ((HLSLAssociatedResourceDeclAttr *)*I)
779 .starts_with(ResourceNamePrefix))
785 const VarDecl *getNextResource() {
789 const VarDecl *Res = Next->getResDecl();
800 assert(
T->isHLSLSpecificType() &&
"Not an HLSL specific type!");
803 if (llvm::Type *TargetTy =
804 CGM.getTargetCodeGenInfo().getHLSLType(
CGM,
T, OffsetInfo))
807 llvm_unreachable(
"Generic handling of HLSL types is not supported.");
810llvm::Triple::ArchType CGHLSLRuntime::getArch() {
816void CGHLSLRuntime::emitBufferGlobalsAndMetadata(
822 llvm::Type *BufType = BufGV->getValueType();
827 size_t OffsetIdx = 0;
837 VarDecl *VD = dyn_cast<VarDecl>(D);
853 DeclsWithOffset.emplace_back(VD, OffsetInfo[OffsetIdx++]);
856 if (!OffsetInfo.
empty())
857 llvm::stable_sort(DeclsWithOffset, [](
const auto &LHS,
const auto &RHS) {
862 SmallVector<llvm::Metadata *> BufGlobals;
863 BufGlobals.reserve(DeclsWithOffset.size() + 1);
864 BufGlobals.push_back(ValueAsMetadata::get(BufGV));
866 auto ElemIt = LayoutStruct->element_begin();
867 for (
auto &[VD, _] : DeclsWithOffset) {
868 if (
CGM.getTargetCodeGenInfo().isHLSLPadding(*ElemIt))
871 assert(ElemIt != LayoutStruct->element_end() &&
872 "number of elements in layout struct does not match");
873 llvm::Type *LayoutType = *ElemIt++;
875 GlobalVariable *ElemGV =
877 BufGlobals.push_back(ValueAsMetadata::get(ElemGV));
879 assert(ElemIt == LayoutStruct->element_end() &&
880 "number of elements in layout struct does not match");
884 .getOrInsertNamedMetadata(
"hlsl.cbs")
885 ->addOperand(MDNode::get(Ctx, BufGlobals));
889static const clang::HLSLAttributedResourceType *
894 HLSLAttributedResourceType::Attributes(ResourceClass::CBuffer));
909 VarDecl *VD = dyn_cast<VarDecl>(D);
920 if (
auto *POA = dyn_cast<HLSLPackOffsetAttr>(
Attr)) {
921 Offset = POA->getOffsetInBytes();
924 auto *RBA = dyn_cast<HLSLResourceBindingAttr>(
Attr);
926 RBA->getRegisterType() == HLSLResourceBindingAttr::RegisterType::C) {
927 Offset = RBA->getSlotNumber() * CBufferRowSizeInBytes;
931 Result.Offsets.push_back(Offset);
939 assert(BufDecl->
isCBuffer() &&
"tbuffer codegen is not supported yet");
942 const clang::HLSLAttributedResourceType *ResHandleTy =
946 if (ResHandleTy->getContainedType()->getAsCXXRecordDecl()->isEmpty())
952 llvm::GlobalVariable *BufGV =
new GlobalVariable(
954 GlobalValue::LinkageTypes::InternalLinkage, PoisonValue::get(LayoutTy),
955 llvm::formatv(
"{0}{1}", BufDecl->
getName(),
957 GlobalValue::NotThreadLocal);
959 llvm::Module &M =
CGM.getModule();
960 M.insertGlobalVariable(BufGV);
965 llvm::appendToCompilerUsed(M, {BufGV});
968 emitBufferGlobalsAndMetadata(BufDecl, BufGV, OffsetInfo);
971 initializeBufferFromBinding(BufDecl, BufGV);
976 llvm::Module &M =
CGM.getModule();
977 Triple
T(M.getTargetTriple());
980 if (
T.getEnvironment() != Triple::EnvironmentType::RootSignature)
983 addRootSignatureMD(SignatureDecl->
getVersion(),
989 const auto Entry = LayoutTypes.find(StructType);
990 if (Entry != LayoutTypes.end())
991 return Entry->getSecond();
996 llvm::StructType *LayoutTy) {
998 "layout type for this struct already exist");
999 LayoutTypes[StructType] = LayoutTy;
1003 auto &TargetOpts =
CGM.getTarget().getTargetOpts();
1004 auto &CodeGenOpts =
CGM.getCodeGenOpts();
1005 auto &LangOpts =
CGM.getLangOpts();
1006 llvm::Module &M =
CGM.getModule();
1007 Triple
T(M.getTargetTriple());
1008 if (
T.getArch() == Triple::ArchType::dxil)
1009 addDxilValVersion(TargetOpts.DxilValidatorVersion, M);
1010 if (!CodeGenOpts.DisableDXSourceMetadata &&
1011 CodeGenOpts.getDebugInfo() >=
1012 llvm::codegenoptions::DebugInfoKind::DebugInfoConstructor)
1013 addSourceInfo(
CGM, M);
1014 if (CodeGenOpts.ResMayAlias)
1015 M.setModuleFlag(llvm::Module::ModFlagBehavior::Error,
"dx.resmayalias", 1);
1016 if (CodeGenOpts.AllResourcesBound)
1017 M.setModuleFlag(llvm::Module::ModFlagBehavior::Error,
1018 "dx.allresourcesbound", 1);
1019 if (CodeGenOpts.OptimizationLevel == 0)
1020 M.addModuleFlag(llvm::Module::ModFlagBehavior::Override,
1021 "dx.disable_optimizations", 1);
1026 if (LangOpts.NativeHalfType)
1027 M.setModuleFlag(llvm::Module::ModFlagBehavior::Error,
"dx.nativelowprec",
1030 if (LangOpts.HLSLSpvPreserveInterface &&
T.isSPIRV()) {
1036 for (GlobalVariable &GV : M.globals()) {
1037 unsigned AS = GV.getAddressSpace();
1038 if (AS == InputAS || AS == OutputAS)
1039 InterfaceVars.push_back(&GV);
1041 if (!InterfaceVars.empty())
1042 appendToCompilerUsed(M, InterfaceVars);
1050 const auto *ShaderAttr = FD->
getAttr<HLSLShaderAttr>();
1051 assert(ShaderAttr &&
"All entry functions must have a HLSLShaderAttr");
1052 const StringRef ShaderAttrKindStr =
"hlsl.shader";
1053 Fn->addFnAttr(ShaderAttrKindStr,
1054 llvm::Triple::getEnvironmentTypeName(ShaderAttr->getType()));
1055 if (HLSLNumThreadsAttr *NumThreadsAttr = FD->
getAttr<HLSLNumThreadsAttr>()) {
1056 const StringRef NumThreadsKindStr =
"hlsl.numthreads";
1057 std::string NumThreadsStr =
1058 formatv(
"{0},{1},{2}", NumThreadsAttr->getX(), NumThreadsAttr->getY(),
1059 NumThreadsAttr->getZ());
1060 Fn->addFnAttr(NumThreadsKindStr, NumThreadsStr);
1062 if (HLSLWaveSizeAttr *WaveSizeAttr = FD->
getAttr<HLSLWaveSizeAttr>()) {
1063 const StringRef WaveSizeKindStr =
"hlsl.wavesize";
1064 std::string WaveSizeStr =
1065 formatv(
"{0},{1},{2}", WaveSizeAttr->getMin(), WaveSizeAttr->getMax(),
1066 WaveSizeAttr->getPreferred());
1067 Fn->addFnAttr(WaveSizeKindStr, WaveSizeStr);
1074 Fn->addFnAttr(llvm::Attribute::NoInline);
1076 if (
CGM.getLangOpts().HLSLSpvEnableMaximalReconvergence) {
1077 Fn->addFnAttr(
"enable-maximal-reconvergence",
"true");
1084 if (
const auto *VT = dyn_cast<FixedVectorType>(Ty)) {
1086 for (
unsigned I = 0; I < VT->getNumElements(); ++I) {
1087 Value *Elt = B.CreateCall(F, {B.getInt32(I)});
1088 Elt = B.CreateTrunc(Elt, VT->getElementType());
1093 return B.CreateTrunc(B.CreateCall(F, {B.getInt32(0)}), Ty);
1098 LLVMContext &Ctx = GV->getContext();
1099 IRBuilder<> B(*GV->getParent());
1100 MDNode *Operands = MDNode::get(
1102 {ConstantAsMetadata::get(B.getInt32( 11)),
1103 ConstantAsMetadata::get(B.getInt32(BuiltIn))});
1104 MDNode *Decoration = MDNode::get(Ctx, {Operands});
1105 GV->addMetadata(
"spirv.Decorations", *Decoration);
1109 LLVMContext &Ctx = GV->getContext();
1110 IRBuilder<> B(*GV->getParent());
1112 MDNode::get(Ctx, {ConstantAsMetadata::get(B.getInt32( 30)),
1113 ConstantAsMetadata::get(B.getInt32(Location))});
1114 MDNode *Decoration = MDNode::get(Ctx, {Operands});
1115 GV->addMetadata(
"spirv.Decorations", *Decoration);
1125 if (
auto *AT = dyn_cast<llvm::ArrayType>(Ty)) {
1126 Ty = AT->getElementType();
1129 if (
auto *VT = dyn_cast<llvm::FixedVectorType>(Ty)) {
1130 Ty = VT->getElementType();
1135 return Ty->isIntegerTy() || Ty->isDoubleTy();
1139 llvm::Type *Ty,
const Twine &Name,
1140 unsigned BuiltInID) {
1141 auto *GV =
new llvm::GlobalVariable(
1142 M, Ty,
true, llvm::GlobalValue::ExternalLinkage,
1143 nullptr, Name,
nullptr,
1144 llvm::GlobalVariable::GeneralDynamicTLSModel,
1147 GV->setVisibility(llvm::GlobalValue::HiddenVisibility);
1148 return B.CreateLoad(Ty, GV);
1152 llvm::Type *Ty,
unsigned Location,
1153 StringRef Name,
bool NeedsFlat) {
1154 auto *GV =
new llvm::GlobalVariable(
1155 M, Ty,
true, llvm::GlobalValue::ExternalLinkage,
1156 nullptr, Name,
nullptr,
1157 llvm::GlobalVariable::GeneralDynamicTLSModel,
1159 GV->setVisibility(llvm::GlobalValue::HiddenVisibility);
1164 LLVMContext &Ctx = GV->getContext();
1166 Decorations.push_back(
1167 MDNode::get(Ctx, {ConstantAsMetadata::get(
1169 ConstantAsMetadata::get(B.getInt32(Location))}));
1171 Decorations.push_back(
1172 MDNode::get(Ctx, {ConstantAsMetadata::get(
1173 B.getInt32( 14))}));
1174 GV->addMetadata(
"spirv.Decorations", *MDNode::get(Ctx, Decorations));
1176 return B.CreateLoad(Ty, GV);
1179llvm::Value *CGHLSLRuntime::emitSPIRVUserSemanticLoad(
1180 llvm::IRBuilder<> &B,
const FunctionDecl *FD, llvm::Type *
Type,
1181 const clang::DeclaratorDecl *
Decl, HLSLAppliedSemanticAttr *Semantic,
1182 std::optional<unsigned> Index) {
1183 Twine BaseName = Twine(Semantic->getAttrName()->getName());
1184 Twine VariableName = BaseName.concat(Twine(Index.value_or(0)));
1186 unsigned Location = SPIRVLastAssignedInputSemanticLocation;
1187 if (
auto *L =
Decl->getAttr<HLSLVkLocationAttr>())
1188 Location = L->getLocation();
1192 llvm::ArrayType *AT = dyn_cast<llvm::ArrayType>(
Type);
1193 unsigned ElementCount = AT ? AT->getNumElements() : 1;
1194 SPIRVLastAssignedInputSemanticLocation += ElementCount;
1196 const auto *ShaderAttr = FD->
getAttr<HLSLShaderAttr>();
1199 ShaderAttr->getType() == llvm::Triple::EnvironmentType::Pixel &&
1203 VariableName.str(), NeedsFlat);
1207 llvm::Value *Source,
unsigned Location,
1209 auto *GV =
new llvm::GlobalVariable(
1210 M, Source->getType(),
false,
1211 llvm::GlobalValue::ExternalLinkage,
1212 nullptr, Name,
nullptr,
1213 llvm::GlobalVariable::GeneralDynamicTLSModel,
1215 GV->setVisibility(llvm::GlobalValue::HiddenVisibility);
1217 B.CreateStore(Source, GV);
1220void CGHLSLRuntime::emitSPIRVUserSemanticStore(
1221 llvm::IRBuilder<> &B, llvm::Value *Source,
1222 const clang::DeclaratorDecl *
Decl, HLSLAppliedSemanticAttr *Semantic,
1223 std::optional<unsigned> Index) {
1224 Twine BaseName = Twine(Semantic->getAttrName()->getName());
1225 Twine VariableName = BaseName.concat(Twine(Index.value_or(0)));
1227 unsigned Location = SPIRVLastAssignedOutputSemanticLocation;
1228 if (
auto *L =
Decl->getAttr<HLSLVkLocationAttr>())
1229 Location = L->getLocation();
1233 llvm::ArrayType *AT = dyn_cast<llvm::ArrayType>(Source->getType());
1234 unsigned ElementCount = AT ? AT->getNumElements() : 1;
1235 SPIRVLastAssignedOutputSemanticLocation += ElementCount;
1237 VariableName.str());
1242struct SemanticShape {
1243 SmallVector<unsigned> Dimensions;
1247 unsigned getNumRows()
const {
1249 for (
unsigned Dimension : Dimensions)
1254 SmallVector<unsigned> getArrayIndicesForRow(
unsigned Row)
const {
1255 assert(Row < getNumRows() &&
"row exceeds semantic shape");
1257 SmallVector<unsigned> Indices(Dimensions.size());
1258 for (
auto [Index, Dimension] :
1259 llvm::zip_equal(llvm::reverse(Indices), llvm::reverse(Dimensions))) {
1260 Index = Row % Dimension;
1271 if (
const auto *FD = dyn_cast<clang::FunctionDecl>(
Decl))
1273 return Decl->getType();
1279 SemanticShape Shape{{}, 1, Ty};
1282 Shape.Dimensions.push_back(CAT->getSize().getZExtValue());
1283 Shape.RowType = CAT->getElementType();
1287 Shape.Cols = VT->getNumElements();
1288 }
else if (
const auto *MT =
1293 Shape.Cols = MT->getNumColumns();
1302 Ty = VT->getElementType();
1304 Ty = MT->getElementType();
1308 return llvm::hlsl::getDXILElementType(IRTy, IsSigned);
1313 std::optional<unsigned> Index,
const SemanticShape &Shape) {
1314 StringRef Name = Semantic->getAttrName()->getName();
1318 uint32_t FirstSemanticIndex = Index.value_or(0);
1319 for (
uint32_t I = 0, E = Shape.getNumRows(); I < E; ++I)
1320 SemanticIndices.push_back(FirstSemanticIndex + I);
1325 return llvm::hlsl::SemanticSignatureElement(
1327 llvm::hlsl::getSemanticKind(Name), SemanticIndices,
1328 static_cast<uint8_t>(Shape.Cols));
1331llvm::Value *CGHLSLRuntime::emitDXILUserSemanticLoad(
1332 llvm::IRBuilder<> &B, llvm::Type *
Type,
const clang::DeclaratorDecl *
Decl,
1333 HLSLAppliedSemanticAttr *Semantic, std::optional<unsigned> Index,
1334 SemanticSignatures &Signature) {
1335 StringRef Name = Semantic->getAttrName()->getName();
1336 SemanticShape Shape =
1340 Signature.push_back(
1343 llvm::Type *RowTy =
CGM.getTypes().ConvertTypeForMem(Shape.RowType);
1345 llvm::Function *IntrFn = llvm::Intrinsic::getOrInsertDeclaration(
1346 B.getModule(), llvm::Intrinsic::dx_load_input, {RowTy});
1348 SmallVector<OperandBundleDef, 1> OB;
1350 llvm::Value *bundleArgs[] = {Token};
1351 OB.emplace_back(
"convergencectrl", bundleArgs);
1354 llvm::Type *LeafTy =
CGM.getTypes().ConvertType(Shape.RowType);
1355 llvm::Value *
Result = llvm::PoisonValue::get(
Type);
1357 const unsigned NumRows = Shape.getNumRows();
1359 for (
unsigned Row = 0; Row < NumRows; ++Row) {
1360 SmallVector<unsigned> Indices = Shape.getArrayIndicesForRow(Row);
1361 std::array<Value *, 4> Args{
1365 llvm::PoisonValue::get(B.getInt32Ty())};
1366 llvm::Value *
Value =
1367 B.CreateCall(IntrFn, Args, OB, Twine(Name).concat(Twine(Row)));
1370 if (
Value->getType() != LeafTy) {
1372 "unexpected semantic load type mismatch");
1373 Value = B.CreateICmpNE(
1374 Value, llvm::Constant::getNullValue(
Value->getType()),
"loadedv");
1383void CGHLSLRuntime::emitDXILUserSemanticStore(llvm::IRBuilder<> &B,
1384 llvm::Value *Source,
1385 const clang::DeclaratorDecl *
Decl,
1386 HLSLAppliedSemanticAttr *Semantic,
1387 std::optional<unsigned> Index,
1388 SemanticSignatures &Signature) {
1389 SemanticShape Shape =
1393 Signature.push_back(
1396 llvm::Type *RowTy =
CGM.getTypes().ConvertTypeForMem(Shape.RowType);
1398 llvm::Function *IntrFn = llvm::Intrinsic::getOrInsertDeclaration(
1399 B.getModule(), llvm::Intrinsic::dx_store_output, {RowTy});
1401 SmallVector<OperandBundleDef, 1> OB;
1403 llvm::Value *bundleArgs[] = {Token};
1404 OB.emplace_back(
"convergencectrl", bundleArgs);
1407 const unsigned NumRows = Shape.getNumRows();
1408 for (
unsigned Row = 0; Row < NumRows; ++Row) {
1409 SmallVector<unsigned> Indices = Shape.getArrayIndicesForRow(Row);
1411 Indices.empty() ? Source : B.CreateExtractValue(Source, Indices);
1415 if (Val->getType() != RowTy) {
1417 "unexpected semantic store type mismatch");
1418 Val = B.CreateZExt(Val, RowTy,
"storedv");
1421 std::array<Value *, 4> Args{B.getInt32(SigId),
1424 B.CreateCall(IntrFn, Args, OB);
1428llvm::Value *CGHLSLRuntime::emitUserSemanticLoad(
1429 IRBuilder<> &B,
const FunctionDecl *FD, llvm::Type *
Type,
1430 const clang::DeclaratorDecl *
Decl, HLSLAppliedSemanticAttr *Semantic,
1431 std::optional<unsigned> Index, SemanticSignatures &Signature) {
1432 if (
CGM.getTarget().getTriple().isSPIRV())
1433 return emitSPIRVUserSemanticLoad(B, FD,
Type,
Decl, Semantic, Index);
1435 if (
CGM.getTarget().getTriple().isDXIL())
1436 return emitDXILUserSemanticLoad(B,
Type,
Decl, Semantic, Index, Signature);
1438 llvm_unreachable(
"Unsupported target for user-semantic load.");
1441void CGHLSLRuntime::emitUserSemanticStore(IRBuilder<> &B, llvm::Value *Source,
1442 const clang::DeclaratorDecl *
Decl,
1443 HLSLAppliedSemanticAttr *Semantic,
1444 std::optional<unsigned> Index,
1445 SemanticSignatures &Signature) {
1446 if (
CGM.getTarget().getTriple().isSPIRV())
1447 return emitSPIRVUserSemanticStore(B, Source,
Decl, Semantic, Index);
1449 if (
CGM.getTarget().getTriple().isDXIL())
1450 return emitDXILUserSemanticStore(B, Source,
Decl, Semantic, Index,
1453 llvm_unreachable(
"Unsupported target for user-semantic load.");
1458 HLSLAppliedSemanticAttr *Semantic,
1460 llvm::Triple::EnvironmentType Stage, std::optional<unsigned> Index,
1463 case llvm::dxbc::PSV::SemanticKind::GroupIndex: {
1464 assert(llvm::is_contained({llvm::Triple::Compute, llvm::Triple::Mesh,
1465 llvm::Triple::Amplification},
1467 "SV_GroupIndex is in an unavailable stage and should have been "
1468 "diagnosed by Sema");
1469 assert(Stage != llvm::Triple::Mesh &&
1470 Stage != llvm::Triple::Amplification &&
1471 "FIXME: SV_GroupIndex is not yet implemented for this shader "
1473 llvm::Function *GroupIndex =
1474 CGM.getIntrinsic(getFlattenedThreadIdInGroupIntrinsic());
1475 return B.CreateCall(FunctionCallee(GroupIndex));
1477 case llvm::dxbc::PSV::SemanticKind::DispatchThreadID: {
1478 assert(llvm::is_contained({llvm::Triple::Compute, llvm::Triple::Mesh,
1479 llvm::Triple::Amplification},
1481 "SV_DispatchThreadID is in an unavailable stage and should have "
1482 "been diagnosed by Sema");
1483 assert(Stage != llvm::Triple::Mesh &&
1484 Stage != llvm::Triple::Amplification &&
1485 "FIXME: SV_DispatchThreadID is not yet implemented for this "
1487 llvm::Intrinsic::ID IntrinID = getThreadIdIntrinsic();
1488 llvm::Function *ThreadIDIntrinsic =
1489 llvm::Intrinsic::isOverloaded(IntrinID)
1490 ?
CGM.getIntrinsic(IntrinID, {
CGM.Int32Ty})
1491 :
CGM.getIntrinsic(IntrinID);
1494 case llvm::dxbc::PSV::SemanticKind::GroupThreadID: {
1495 assert(llvm::is_contained({llvm::Triple::Compute, llvm::Triple::Mesh,
1496 llvm::Triple::Amplification},
1498 "SV_GroupThreadID is in an unavailable stage and should have been "
1499 "diagnosed by Sema");
1500 assert(Stage != llvm::Triple::Mesh &&
1501 Stage != llvm::Triple::Amplification &&
1502 "FIXME: SV_GroupThreadID is not yet implemented for this shader "
1504 llvm::Intrinsic::ID IntrinID = getGroupThreadIdIntrinsic();
1505 llvm::Function *GroupThreadIDIntrinsic =
1506 llvm::Intrinsic::isOverloaded(IntrinID)
1507 ?
CGM.getIntrinsic(IntrinID, {
CGM.Int32Ty})
1508 :
CGM.getIntrinsic(IntrinID);
1511 case llvm::dxbc::PSV::SemanticKind::GroupID: {
1512 assert(llvm::is_contained({llvm::Triple::Compute, llvm::Triple::Mesh,
1513 llvm::Triple::Amplification},
1515 "SV_GroupID is in an unavailable stage and should have been "
1516 "diagnosed by Sema");
1517 assert(Stage != llvm::Triple::Mesh &&
1518 Stage != llvm::Triple::Amplification &&
1519 "FIXME: SV_GroupID is not yet implemented for this shader stage");
1520 llvm::Intrinsic::ID IntrinID = getGroupIdIntrinsic();
1521 llvm::Function *GroupIDIntrinsic =
1522 llvm::Intrinsic::isOverloaded(IntrinID)
1523 ?
CGM.getIntrinsic(IntrinID, {
CGM.Int32Ty})
1524 :
CGM.getIntrinsic(IntrinID);
1527 case llvm::dxbc::PSV::SemanticKind::Position:
1528 assert(llvm::is_contained({llvm::Triple::Hull, llvm::Triple::Domain,
1529 llvm::Triple::Geometry, llvm::Triple::Pixel},
1531 "SV_Position is in an unavailable stage and should have been "
1532 "diagnosed by Sema");
1533 assert(Stage != llvm::Triple::Hull && Stage != llvm::Triple::Domain &&
1534 Stage != llvm::Triple::Geometry &&
1535 "FIXME: loading SV_Position is not yet implemented for this "
1537 if (
CGM.getTarget().getTriple().isSPIRV())
1539 Semantic->getAttrName()->getName(),
1541 if (
CGM.getTarget().getTriple().isDXIL())
1542 return emitDXILUserSemanticLoad(B,
Type,
Decl, Semantic, Index,
1545 case llvm::dxbc::PSV::SemanticKind::VertexID:
1546 assert(Stage == llvm::Triple::Vertex &&
1547 "SV_VertexID is in an unavailable stage and should have been "
1548 "diagnosed by Sema");
1549 if (
CGM.getTarget().getTriple().isSPIRV())
1551 Semantic->getAttrName()->getName(),
1553 if (
CGM.getTarget().getTriple().isDXIL())
1554 return emitDXILUserSemanticLoad(B,
Type,
Decl, Semantic, Index,
1557 case llvm::dxbc::PSV::SemanticKind::InstanceID:
1558 assert(Stage == llvm::Triple::Vertex &&
1559 "SV_InstanceID is in an unavailable stage and should have been "
1560 "diagnosed by Sema");
1561 if (
CGM.getTarget().getTriple().isSPIRV())
1563 Semantic->getAttrName()->getName(),
1565 if (
CGM.getTarget().getTriple().isDXIL())
1566 return emitDXILUserSemanticLoad(B,
Type,
Decl, Semantic, Index,
1574 "Load hasn't been implemented yet for this system semantic. FIXME");
1578 llvm::Value *Source,
const Twine &Name,
1579 unsigned BuiltInID) {
1580 auto *GV =
new llvm::GlobalVariable(
1581 M, Source->getType(),
false,
1582 llvm::GlobalValue::ExternalLinkage,
1583 nullptr, Name,
nullptr,
1584 llvm::GlobalVariable::GeneralDynamicTLSModel,
1587 GV->setVisibility(llvm::GlobalValue::HiddenVisibility);
1588 B.CreateStore(Source, GV);
1593 HLSLAppliedSemanticAttr *Semantic,
1595 llvm::Triple::EnvironmentType Stage, std::optional<unsigned> Index,
1598 case llvm::dxbc::PSV::SemanticKind::Position:
1599 assert(llvm::is_contained({llvm::Triple::Vertex, llvm::Triple::Hull,
1600 llvm::Triple::Domain, llvm::Triple::Geometry,
1601 llvm::Triple::Mesh},
1603 "SV_Position is in an unavailable stage and should have been "
1604 "diagnosed by Sema");
1605 assert(Stage != llvm::Triple::Hull && Stage != llvm::Triple::Domain &&
1606 Stage != llvm::Triple::Geometry && Stage != llvm::Triple::Mesh &&
1607 "FIXME: storing SV_Position is not yet implemented for this "
1609 if (
CGM.getTarget().getTriple().isDXIL()) {
1610 emitDXILUserSemanticStore(B, Source,
Decl, Semantic, Index, Signature);
1613 if (
CGM.getTarget().getTriple().isSPIRV()) {
1615 Semantic->getAttrName()->getName(),
1620 case llvm::dxbc::PSV::SemanticKind::Target:
1621 assert(Stage == llvm::Triple::Pixel &&
1622 "SV_Target is in an unavailable stage and should have been "
1623 "diagnosed by Sema");
1624 emitUserSemanticStore(B, Source,
Decl, Semantic, Index, Signature);
1631 "Store hasn't been implemented yet for this system semantic. FIXME");
1639 std::optional<unsigned> Index = Semantic->getSemanticIndex();
1641 llvm::hlsl::getSemanticKind(Semantic->getAttrName()->getName());
1642 const auto *ShaderAttr = FD->
getAttr<HLSLShaderAttr>();
1643 assert(ShaderAttr &&
"Entry point has no shader attribute");
1644 llvm::hlsl::SemanticInterpretation Interpretation =
1645 llvm::hlsl::getInterpretationKind(
SemanticKind, ShaderAttr->getType(),
1646 llvm::hlsl::IOType::In);
1647 assert(Interpretation != llvm::hlsl::SemanticInterpretation::Invalid &&
1648 "invalid semantic should have been diagnosed by Sema");
1649 if (Interpretation == llvm::hlsl::SemanticInterpretation::Arbitrary)
1650 return emitUserSemanticLoad(B, FD,
Type,
Decl, Semantic, Index, Signature);
1652 ShaderAttr->getType(), Index, Signature);
1657 llvm::Value *Source,
1659 HLSLAppliedSemanticAttr *Semantic,
1661 std::optional<unsigned> Index = Semantic->getSemanticIndex();
1663 llvm::hlsl::getSemanticKind(Semantic->getAttrName()->getName());
1664 const auto *ShaderAttr = FD->
getAttr<HLSLShaderAttr>();
1665 assert(ShaderAttr &&
"Entry point has no shader attribute");
1667 llvm::hlsl::SemanticInterpretation Interpretation =
1668 llvm::hlsl::getInterpretationKind(
SemanticKind, ShaderAttr->getType(),
1669 llvm::hlsl::IOType::Out);
1670 assert(Interpretation != llvm::hlsl::SemanticInterpretation::Invalid &&
1671 "invalid semantic should have been diagnosed by Sema");
1673 if (Interpretation == llvm::hlsl::SemanticInterpretation::Arbitrary)
1674 return emitUserSemanticStore(B, Source,
Decl, Semantic, Index, Signature);
1676 ShaderAttr->getType(), Index, Signature);
1679std::pair<llvm::Value *, specific_attr_iterator<HLSLAppliedSemanticAttr>>
1686 llvm::hlsl::InterpolationModifier Modifiers) {
1694 for (
unsigned I = 0; I < ST->getNumElements(); ++I) {
1695 auto [ChildValue, NextAttr] =
1697 AttrEnd, Signature, Modifiers);
1698 AttrBegin = NextAttr;
1704 return std::make_pair(
Aggregate, AttrBegin);
1709 IRBuilder<> &B,
const FunctionDecl *FD, llvm::Value *Source,
1714 llvm::hlsl::InterpolationModifier Modifiers) {
1722 RD =
Decl->getType()->getAsRecordDecl();
1728 for (
unsigned I = 0; I < ST->getNumElements(); ++I, ++
FieldDecl) {
1729 llvm::Value *Extract = B.CreateExtractValue(Source, I);
1731 AttrEnd, Signature, Modifiers);
1737std::pair<llvm::Value *, specific_attr_iterator<HLSLAppliedSemanticAttr>>
1744 llvm::hlsl::InterpolationModifier Modifiers) {
1745 assert(AttrBegin != AttrEnd);
1748 if (
const auto *A =
Decl->getAttr<HLSLInterpolationModifierAttr>())
1750 static_cast<llvm::hlsl::InterpolationModifier
>(A->getModifiers());
1751 if (
Type->isStructTy())
1753 Signature, Modifiers);
1755 HLSLAppliedSemanticAttr *
Attr = *AttrBegin;
1757 size_t PreviousSize = Signature.size();
1758 llvm::Value *
Value =
1762 if (Signature.size() != PreviousSize) {
1763 auto &Element = Signature.back();
1764 Element.InterpMode = llvm::hlsl::normalizeInterpolationMode(
1765 llvm::hlsl::getInterpolationMode(Modifiers), Element.CompType,
1766 Element.SemanticKind, FD->
getAttr<HLSLShaderAttr>()->getType(),
1767 llvm::hlsl::IOType::In);
1769 return std::make_pair(
Value, AttrBegin);
1774 IRBuilder<> &B,
const FunctionDecl *FD, llvm::Value *Source,
1779 llvm::hlsl::InterpolationModifier Modifiers) {
1780 assert(AttrBegin != AttrEnd);
1782 if (
const auto *A =
Decl->getAttr<HLSLInterpolationModifierAttr>())
1784 static_cast<llvm::hlsl::InterpolationModifier
>(A->getModifiers());
1785 if (Source->getType()->isStructTy())
1787 Signature, Modifiers);
1789 HLSLAppliedSemanticAttr *
Attr = *AttrBegin;
1791 size_t PreviousSize = Signature.size();
1793 if (Signature.size() != PreviousSize) {
1794 auto &Element = Signature.back();
1795 Element.InterpMode = llvm::hlsl::normalizeInterpolationMode(
1796 llvm::hlsl::getInterpolationMode(Modifiers), Element.CompType,
1797 Element.SemanticKind, FD->
getAttr<HLSLShaderAttr>()->getType(),
1798 llvm::hlsl::IOType::Out);
1804 llvm::Function *Fn) {
1808 llvm::Module &M =
CGM.getModule();
1809 llvm::LLVMContext &Ctx = M.getContext();
1810 auto *EntryTy = llvm::FunctionType::get(llvm::Type::getVoidTy(Ctx),
false);
1812 Function::Create(EntryTy, Function::ExternalLinkage, FD->
getName(), &M);
1816 AttributeList NewAttrs = AttributeList::get(Ctx, AttributeList::FunctionIndex,
1817 Fn->getAttributes().getFnAttrs());
1818 EntryFn->setAttributes(NewAttrs);
1822 Fn->setLinkage(GlobalValue::InternalLinkage);
1824 BasicBlock *BB = BasicBlock::Create(Ctx,
"entry", EntryFn);
1829 if (
CGM.shouldEmitConvergenceTokens()) {
1830 assert(EntryFn->isConvergent());
1832 B.CreateIntrinsic(llvm::Intrinsic::experimental_convergence_entry, {});
1833 llvm::Value *bundleArgs[] = {I};
1834 OB.emplace_back(
"convergencectrl", bundleArgs);
1839 unsigned SRetOffset = 0;
1840 for (
const auto &Param : Fn->args()) {
1841 if (Param.hasStructRetAttr()) {
1843 llvm::Type *VarType = Param.getParamStructRetType();
1845 CGM.getLangOpts().EmitLogicalPointer
1848 OutputSemantic.push_back(std::make_pair(Var, VarType));
1849 Args.push_back(Var);
1854 llvm::Value *SemanticValue =
nullptr;
1856 if ([[maybe_unused]] HLSLParamModifierAttr *MA =
1857 PD->
getAttr<HLSLParamModifierAttr>()) {
1858 llvm_unreachable(
"Not handled yet");
1860 llvm::Type *ParamType =
nullptr;
1861 if (Param.hasByValAttr())
1862 ParamType = Param.getParamByValType();
1864 ParamType =
CGM.getTypes().ConvertType(PD->
getType());
1866 ParamType = Param.getType();
1872 SemanticValue =
Result.first;
1877 CGM.getLangOpts().EmitLogicalPointer
1880 B.CreateStore(SemanticValue, Var);
1881 SemanticValue = Var;
1885 assert(SemanticValue);
1886 Args.push_back(SemanticValue);
1889 CallInst *CI = B.CreateCall(FunctionCallee(Fn), Args, OB);
1890 CI->setCallingConv(Fn->getCallingConv());
1892 if (Fn->getReturnType() !=
CGM.VoidTy)
1894 OutputSemantic.push_back(std::make_pair(CI,
nullptr));
1896 for (
auto &SourcePair : OutputSemantic) {
1897 llvm::Value *Source = SourcePair.first;
1898 llvm::Type *ElementType = SourcePair.second;
1899 AllocaInst *AI = dyn_cast<AllocaInst>(Source);
1900 llvm::Value *SourceValue = AI ? B.CreateLoad(ElementType, Source) : Source;
1912 if (
const auto *RSAttr = dyn_cast<RootSignatureAttr>(
Attr)) {
1913 auto *RSDecl = RSAttr->getSignatureDecl();
1914 addRootSignatureMD(RSDecl->getVersion(), RSDecl->getRootElements(),
1919 if (
CGM.getTarget().getTriple().isDXIL()) {
1924 auto Mode =
CGM.getCodeGenOpts().getHLSLSemanticSignaturePacking();
1925 for (
auto IOTy : {llvm::hlsl::IOType::In, llvm::hlsl::IOType::Out}) {
1926 bool IsOutput = IOTy == llvm::hlsl::IOType::Out;
1927 auto &Signature = IsOutput ? OutputSignature : InputSignature;
1928 auto Packed = packSemanticSignature(Signature, Stage, IOTy, Mode,
1929 CGM.getLangOpts().NativeHalfType);
1932 diag::err_hlsl_signature_packing)
1933 << IsOutput << llvm::toString(
Packed.takeError());
1937 if (Mode != PackingMode::Default &&
1938 CGM.getTarget().getTriple().getEnvironment() !=
1939 llvm::Triple::Library &&
1940 ((Stage == llvm::Triple::Vertex && !IsOutput) ||
1941 (Stage == llvm::Triple::Pixel && IsOutput)))
1943 diag::warn_hlsl_signature_packing_ignored)
1944 << (Mode == PackingMode::Optimized ?
"optimized" :
"prefix-stable")
1949 addSemanticSignatureMD(InputSignature, OutputSignature, EntryFn, M);
1955 M.getNamedGlobal(CtorOrDtor ?
"llvm.global_ctors" :
"llvm.global_dtors");
1958 const auto *CA = dyn_cast<ConstantArray>(GV->getInitializer());
1965 for (
const auto &Ctor : CA->operands()) {
1971 "HLSL doesn't support setting priority for global ctors.");
1973 "HLSL doesn't support COMDat for global ctors.");
1979 llvm::Module &M =
CGM.getModule();
1988 for (
auto &F : M.functions()) {
1989 if (!F.hasFnAttribute(
"hlsl.shader"))
1992 Instruction *IP = &*F.getEntryBlock().begin();
1995 llvm::Value *bundleArgs[] = {
Token};
1996 OB.emplace_back(
"convergencectrl", bundleArgs);
1997 IP =
Token->getNextNode();
2000 for (
auto *Fn : CtorFns) {
2001 auto CI = B.CreateCall(FunctionCallee(Fn), {}, OB);
2002 CI->setCallingConv(Fn->getCallingConv());
2006 B.SetInsertPoint(F.back().getTerminator());
2007 for (
auto *Fn : DtorFns) {
2008 auto CI = B.CreateCall(FunctionCallee(Fn), {}, OB);
2009 CI->setCallingConv(Fn->getCallingConv());
2015 Triple
T(M.getTargetTriple());
2016 if (
T.getEnvironment() != Triple::EnvironmentType::Library) {
2017 if (
auto *GV = M.getNamedGlobal(
"llvm.global_ctors"))
2018 GV->eraseFromParent();
2019 if (
auto *GV = M.getNamedGlobal(
"llvm.global_dtors"))
2020 GV->eraseFromParent();
2025 Intrinsic::ID IntrID,
2029 llvm::Function *InitResFunc =
2030 llvm::Function::Create(llvm::FunctionType::get(CGM.
VoidTy,
false),
2031 llvm::GlobalValue::InternalLinkage,
2032 "_init_buffer_" + GV->getName(), CGM.
getModule());
2033 InitResFunc->addFnAttr(llvm::Attribute::AlwaysInline);
2035 llvm::BasicBlock *EntryBB =
2036 llvm::BasicBlock::Create(Ctx,
"entry", InitResFunc);
2038 const DataLayout &DL = CGM.
getModule().getDataLayout();
2039 Builder.SetInsertPoint(EntryBB);
2042 llvm::Type *HandleTy = GV->getValueType();
2043 assert(HandleTy->isTargetExtTy() &&
"unexpected type of the buffer global");
2045 llvm::Value *CreateHandle = Builder.CreateIntrinsic(
2046 HandleTy, IntrID, Args,
nullptr,
2047 Twine(GV->getName()).concat(
"_h"));
2049 Builder.CreateAlignedStore(CreateHandle, GV, GV->getPointerAlignment(DL));
2050 Builder.CreateRetVoid();
2055void CGHLSLRuntime::initializeBufferFromBinding(
const HLSLBufferDecl *BufDecl,
2056 llvm::GlobalVariable *GV) {
2057 ResourceBindingAttrs Binding(BufDecl);
2059 "cbuffer/tbuffer should always have resource binding attribute");
2061 auto *Index = llvm::ConstantInt::get(
CGM.IntTy, 0);
2062 auto *RangeSize = llvm::ConstantInt::get(
CGM.IntTy, 1);
2063 auto *Space = llvm::ConstantInt::get(
CGM.IntTy, Binding.
getSpace());
2068 llvm::Intrinsic::ID IntrinsicID =
2069 CGM.getHLSLRuntime().getCreateHandleFromBindingIntrinsic();
2070 auto *RegSlot = llvm::ConstantInt::get(
CGM.IntTy, Binding.
getSlot());
2071 SmallVector<Value *> Args{Space, RegSlot, RangeSize, Index, Name};
2075 llvm::Intrinsic::ID IntrinsicID =
2076 CGM.getHLSLRuntime().getCreateHandleFromImplicitBindingIntrinsic();
2079 SmallVector<Value *> Args{OrderID, Space, RangeSize, Index, Name};
2085 llvm::GlobalVariable *GV) {
2086 if (
auto Attr = VD->
getAttr<HLSLVkExtBuiltinInputAttr>())
2088 if (
auto Attr = VD->
getAttr<HLSLVkExtBuiltinOutputAttr>())
2093 if (!
CGM.shouldEmitConvergenceTokens())
2097 for (
auto I = BB.begin(); I != E; ++I) {
2098 auto *II = dyn_cast<llvm::IntrinsicInst>(&*I);
2099 if (II && llvm::isConvergenceControlIntrinsic(II->getIntrinsicID())) {
2103 llvm_unreachable(
"Convergence token should have been emitted.");
2140 for (
auto *OVE : Visitor.
OVEs) {
2143 if (OpaqueValueMappingData::shouldBindAsLValue(OVE)) {
2145 OpaqueValueMappingData::bind(CGF, OVE, LV);
2148 OpaqueValueMappingData::bind(CGF, OVE, RV);
2157 "expected resource array subscript expression");
2162 const VarDecl *ArrayDecl = dyn_cast_or_null<VarDecl>(
2166 return std::nullopt;
2172 "expected array of resource classes");
2178 Value *Index =
nullptr;
2180 while (ASE !=
nullptr) {
2182 if (
const auto *ArrayTy =
2184 Value *Multiplier = llvm::ConstantInt::get(
2186 SubIndex = CGF.
Builder.CreateMul(SubIndex, Multiplier);
2188 Index = Index ? CGF.
Builder.CreateAdd(Index, SubIndex) : SubIndex;
2196 "resource array must have a binding attribute");
2217 llvm::Value *Range = llvm::ConstantInt::getSigned(
2218 CGM.IntTy, getTotalArraySize(AST, ResArrayTy));
2222 if (ResultTy == ResourceTy) {
2224 CXXMethodDecl *CreateMethod = lookupResourceInitMethodAndSetupArgs(
2226 ArrayDecl->
getName(), Binding, Args);
2228 if (!CreateMethod) {
2233 "create method lookup should always succeed for built-in resource "
2235 return std::nullopt;
2238 callResourceInitMethod(CGF, CreateMethod, Args, ValueSlot.getAddress());
2245 std::optional<llvm::Value *> EndIndex = initializeResourceArrayFromGlobal(
2247 ArrayDecl->
getName(), Binding, {llvm::ConstantInt::get(CGM.IntTy, 0)});
2249 return std::nullopt;
2255bool CGHLSLRuntime::initializeGlobalResourceArray(
CodeGenFunction &CGF,
2261 "expected global non-static resource array");
2267 "resource array must have a binding attribute");
2272 const auto *ResArrayTy =
2276 int Size = getTotalArraySize(AST, ResArrayTy);
2277 llvm::Value *
Zero = llvm::ConstantInt::get(
CGM.
IntTy, 0);
2278 llvm::Value *Range = llvm::ConstantInt::get(
CGM.
IntTy, Size);
2281 std::optional<llvm::Value *> EndIndex = initializeResourceArrayFromGlobal(
2283 ArrayDecl->
getName(), Binding, {Zero});
2284 return EndIndex.has_value();
2293 "expected resource array");
2298 dyn_cast_or_null<VarDecl>(getArrayDecl(CGF.
CGM.
getContext(), E));
2303 return initializeGlobalResourceArray(CGF, ArrayDecl, DestSlot);
2310std::optional<LValue>
2314 "expected resource array declaration");
2318 return std::nullopt;
2322 if (initializeGlobalResourceArray(CGF, ArrayDecl, TmpArraySlot))
2325 return std::nullopt;
2333 "expected cbuffer matrix");
2344 HLSLBufferCopyEmitter(CGF, DestAlloca, SrcAddr).emitCopy(MatQualTy);
2350 llvm::function_ref<llvm::Value *(
bool Promote)> EmitIdxAfterBase) {
2354 llvm::Type *LayoutTy =
2356 uint64_t LayoutSizeInBits =
2357 CGM.getDataLayout().getTypeSizeInBits(LayoutTy).getFixedValue();
2360 if (RowAlignedSize > ElementSize) {
2361 llvm::Type *Padding =
CGM.getTargetCodeGenInfo().getHLSLPadding(
2362 CGM, RowAlignedSize - ElementSize);
2363 assert(Padding &&
"No padding type for target?");
2364 LayoutTy = llvm::StructType::get(CGF.
getLLVMContext(), {LayoutTy, Padding},
2371 if (LayoutTy == OrigTy)
2372 return std::nullopt;
2381 llvm::Value *Idx = EmitIdxAfterBase(
true);
2382 Indices.push_back(Idx);
2383 Indices.push_back(llvm::ConstantInt::get(CGF.
Int32Ty, 0));
2389 assert(CE->
getCastKind() == CastKind::CK_ArrayToPointerDecay);
2393 LayoutTy = llvm::ArrayType::get(
2397 LayoutTy,
Addr.emitRawPointer(CGF), Indices,
"cbufferidx"));
2406 Indices,
"cbufferidx");
2411std::optional<LValue>
2416 "expected resource member expression");
2419 findAssociatedResourceDeclForStruct(CGF.
CGM.
getContext(), ME);
2421 return std::nullopt;
2427 GlobalVariable *ResGV =
2429 const DataLayout &DL =
CGM.getDataLayout();
2430 llvm::Type *Ty = ResGV->getValueType();
2443 "expected expression in HLSL constant address space");
2446 "direct accesses to resource types should be handled separately");
2458 return HLSLBufferCopyEmitter(CGF, DstPtr, SrcPtr).emitCopy(Ty);
2464 const VarDecl *VD = findStructResourceParentDeclAndBuildName(E, NameBuilder);
2465 AssociatedResourcesList AssociatedResources(VD, NameBuilder.
getName());
2469 const VarDecl *ResDecl = AssociatedResources.getNextResource();
2470 assert(ResDecl &&
"associated resource declaration not found");
2473 [[maybe_unused]] llvm::Type *DestType =
2474 ResSlot.getAddress().getElementType();
2475 [[maybe_unused]] llvm::Type *SrcConvertedType =
2476 CGM.getTypes().ConvertTypeForMem(ResDecl->
getType());
2477 assert(DestType == SrcConvertedType &&
"resource slot type mismatch");
2480 copyGlobalResource(CGF, ResDecl, ResSlot);
2482 initializeGlobalResourceArray(CGF, ResDecl, ResSlot);
2486 HLSLBufferCopyEmitter(CGF, DstPtr, SrcPtr).emitCopy(Ty, EmitResFn);
2487 assert(AssociatedResources.getNextResource() ==
nullptr &&
2488 "expected all associated resources to be processed");
2497 assert(Field &&
"Unexpected access into HLSL buffer");
2502 QualType RecType =
CGM.getContext().getCanonicalTagType(Rec);
2513 CGM.getTypes().getCGRecordLayout(Rec).getLLVMFieldNo(Field);
2514 assert(FieldIdx < LayoutTy->getNumElements() &&
2515 "Layout struct is smaller than member struct");
2516 unsigned Skipped = 0;
2517 for (
unsigned I = 0; I <= FieldIdx;) {
2518 llvm::Type *ElementTy = LayoutTy->getElementType(I + Skipped);
2524 FieldIdx += Skipped;
2525 assert(FieldIdx < LayoutTy->getNumElements() &&
"Access out of bounds");
2529 QualType FieldType = Field->getType();
2530 llvm::Type *FieldLLVMTy =
CGM.getTypes().ConvertTypeForMem(FieldType);
2535 ? CGF.
Builder.CreateStructuredGEP(
2536 LayoutTy,
Base.getPointer(CGF),
2537 llvm::ConstantInt::get(
CGM.IntTy, FieldIdx))
2539 FieldIdx, Field->getName());
2544 CGM.getTBAAAccessInfo(FieldType));
Defines the clang::ASTContext interface.
static llvm::Value * createSPIRVBuiltinLoad(IRBuilder<> &B, llvm::Module &M, llvm::Type *Ty, const Twine &Name, unsigned BuiltInID)
static llvm::dxil::ElementType getSignatureComponentType(CodeGenModule &CGM, QualType Ty)
static QualType getSemanticLeafType(const clang::DeclaratorDecl *Decl)
static void addSPIRVBuiltinDecoration(llvm::GlobalVariable *GV, unsigned BuiltIn)
static llvm::hlsl::SemanticSignatureElement createSemanticSignatureElement(CodeGenModule &CGM, uint32_t SigId, HLSLAppliedSemanticAttr *Semantic, std::optional< unsigned > Index, const SemanticShape &Shape)
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
llvm::dxbc::PSV::SemanticKind SemanticKind
Defines the SourceManager interface.
Defines the clang::TargetOptions class.
C Language Family Type Representation.
bool VisitHLSLOutArgExpr(HLSLOutArgExpr *)
llvm::SmallVector< OpaqueValueExpr *, 8 > OVEs
bool VisitOpaqueValueExpr(OpaqueValueExpr *E)
llvm::SmallPtrSet< OpaqueValueExpr *, 8 > Visited
Holds long-lived AST nodes (such as types and decls) that can be referred to throughout the semantic ...
SourceManager & getSourceManager()
const ConstantArrayType * getAsConstantArrayType(QualType T) const
QualType getPointerType(QualType T) const
Return the uniqued reference to the type for a pointer to the specified type.
QualType getBaseElementType(const ArrayType *VAT) const
Return the innermost element type of an array type.
CharUnits getTypeSizeInChars(QualType T) const
Return the size of the specified (complete) type T, in characters.
CanQualType UnsignedIntTy
static uint64_t getConstantArrayElementCount(const ConstantArrayType *CA)
Return number of (potentially nested) constant array elements.
QualType getHLSLAttributedResourceType(QualType Wrapped, QualType Contained, const HLSLAttributedResourceType::Attributes &Attrs)
CanQualType getCanonicalTagType(const TagDecl *TD) const
unsigned getTargetAddressSpace(LangAS AS) const
ArraySubscriptExpr - [C99 6.5.2.1] Array Subscripting.
QualType getElementType() const
Attr - This represents one attribute.
Represents a static or instance method of a struct/union/class.
Represents a C++ struct/union/class.
QualType withConst() const
Retrieves a version of this type with const applied.
CastExpr - Base class for type casts, including both implicit casts (ImplicitCastExpr) and explicit c...
CastKind getCastKind() const
This is an opaque type for sizes expressed in character units.
CharUnits alignTo(CharUnits Align) const
Returns the next integer (mod 2**64) that is greater than or equal to this quantity and is a multiple...
CharUnits alignmentOfArrayElement(CharUnits elementSize) const
Given that this is the alignment of the first element of an array, return the minimum alignment of an...
static CharUnits fromQuantity(QuantityType Quantity)
Construct a CharUnits quantity from a raw integer type.
HLSLSemanticSignaturePackingMode
Like RawAddress, an abstract representation of an aligned address, but the pointer contained in this ...
CharUnits getAlignment() const
Address getAddress() const
static AggValueSlot forAddr(Address addr, Qualifiers quals, IsDestructed_t isDestructed, NeedsGCBarriers_t needsGC, IsAliased_t isAliased, Overlap_t mayOverlap, IsZeroed_t isZeroed=IsNotZeroed, IsSanitizerChecked_t isChecked=IsNotSanitizerChecked)
forAddr - Make a slot for an aggregate value.
llvm::StoreInst * CreateStore(llvm::Value *Val, Address Addr, bool IsVolatile=false)
Address CreateGEP(CodeGenFunction &CGF, Address Addr, llvm::Value *Index, const llvm::Twine &Name="")
Address CreateStructGEP(Address Addr, unsigned Index, const llvm::Twine &Name="")
Abstract information about a function or function prototype.
All available information about a concrete callee.
CGFunctionInfo - Class to encapsulate the information about a function definition.
static const uint32_t Unspecified
static bool compareOffsets(uint32_t LHS, uint32_t RHS)
Comparison function for offsets received from operator[] suitable for use in a stable_sort.
static CGHLSLOffsetInfo fromDecl(const HLSLBufferDecl &BufDecl)
Iterates over all declarations in the HLSL buffer and based on the packoffset or register(c#) annotat...
llvm::Instruction * getConvergenceToken(llvm::BasicBlock &BB)
llvm::Value * emitSystemSemanticLoad(llvm::IRBuilder<> &B, llvm::Type *Type, const clang::DeclaratorDecl *Decl, HLSLAppliedSemanticAttr *Semantic, llvm::dxbc::PSV::SemanticKind SemanticKind, llvm::Triple::EnvironmentType Stage, std::optional< unsigned > Index, SemanticSignatures &Signature)
void setHLSLEntryAttributes(const FunctionDecl *FD, llvm::Function *Fn)
llvm::StructType * getHLSLBufferLayoutType(const RecordType *LayoutStructTy)
void emitEntryFunction(const FunctionDecl *FD, llvm::Function *Fn)
void handleGlobalVarDefinition(const VarDecl *VD, llvm::GlobalVariable *Var)
std::optional< LValue > emitResourceMemberExpr(CodeGenFunction &CGF, const MemberExpr *E)
void emitSystemSemanticStore(llvm::IRBuilder<> &B, llvm::Value *Source, const clang::DeclaratorDecl *Decl, HLSLAppliedSemanticAttr *Semantic, llvm::dxbc::PSV::SemanticKind SemanticKind, llvm::Triple::EnvironmentType Stage, std::optional< unsigned > Index, SemanticSignatures &Signature)
specific_attr_iterator< HLSLAppliedSemanticAttr > handleStructSemanticStore(llvm::IRBuilder<> &B, const FunctionDecl *FD, llvm::Value *Source, const clang::DeclaratorDecl *Decl, specific_attr_iterator< HLSLAppliedSemanticAttr > AttrBegin, specific_attr_iterator< HLSLAppliedSemanticAttr > AttrEnd, SemanticSignatures &Signature, llvm::hlsl::InterpolationModifier Modifiers)
llvm::SmallVectorImpl< llvm::hlsl::SemanticSignatureElement > SemanticSignatures
void addHLSLBufferLayoutType(const RecordType *LayoutStructTy, llvm::StructType *LayoutTy)
std::optional< LValue > emitGlobalResourceArrayAsLValue(CodeGenFunction &CGF, const VarDecl *ArrayDecl)
llvm::Value * handleScalarSemanticLoad(llvm::IRBuilder<> &B, const FunctionDecl *FD, llvm::Type *Type, const clang::DeclaratorDecl *Decl, HLSLAppliedSemanticAttr *Semantic, SemanticSignatures &Signature)
bool emitBufferCopy(CodeGenFunction &CGF, const Expr *E, const LValue &SrcLV, AggValueSlot &DestSlot)
std::optional< LValue > emitBufferArraySubscriptExpr(const ArraySubscriptExpr *E, CodeGenFunction &CGF, llvm::function_ref< llvm::Value *(bool Promote)> EmitIdxAfterBase)
std::optional< LValue > emitResourceArraySubscriptExpr(const ArraySubscriptExpr *E, CodeGenFunction &CGF)
void addRootSignature(const HLSLRootSignatureDecl *D)
LValue emitBufferMemberExpr(CodeGenFunction &CGF, const MemberExpr *E)
llvm::Type * convertHLSLSpecificType(const Type *T, const CGHLSLOffsetInfo &OffsetInfo)
RawAddress createBufferMatrixTempAddress(const LValue &LV, CodeGenFunction &CGF)
specific_attr_iterator< HLSLAppliedSemanticAttr > handleSemanticStore(llvm::IRBuilder<> &B, const FunctionDecl *FD, llvm::Value *Source, const clang::DeclaratorDecl *Decl, specific_attr_iterator< HLSLAppliedSemanticAttr > AttrBegin, specific_attr_iterator< HLSLAppliedSemanticAttr > AttrEnd, SemanticSignatures &Signature, llvm::hlsl::InterpolationModifier Modifiers=llvm::hlsl::InterpolationModifier::None)
void addBuffer(const HLSLBufferDecl *D)
void generateGlobalCtorDtorCalls()
std::pair< llvm::Value *, specific_attr_iterator< HLSLAppliedSemanticAttr > > handleStructSemanticLoad(llvm::IRBuilder<> &B, const FunctionDecl *FD, llvm::Type *Type, const clang::DeclaratorDecl *Decl, specific_attr_iterator< HLSLAppliedSemanticAttr > begin, specific_attr_iterator< HLSLAppliedSemanticAttr > end, SemanticSignatures &Signature, llvm::hlsl::InterpolationModifier Modifiers)
bool emitGlobalResourceArray(CodeGenFunction &CGF, const Expr *E, AggValueSlot &DestSlot)
void handleScalarSemanticStore(llvm::IRBuilder<> &B, const FunctionDecl *FD, llvm::Value *Source, const clang::DeclaratorDecl *Decl, HLSLAppliedSemanticAttr *Semantic, SemanticSignatures &Signature)
void emitInitListOpaqueValues(CodeGenFunction &CGF, InitListExpr *E)
std::pair< llvm::Value *, specific_attr_iterator< HLSLAppliedSemanticAttr > > handleSemanticLoad(llvm::IRBuilder<> &B, const FunctionDecl *FD, llvm::Type *Type, const clang::DeclaratorDecl *Decl, specific_attr_iterator< HLSLAppliedSemanticAttr > begin, specific_attr_iterator< HLSLAppliedSemanticAttr > end, SemanticSignatures &Signature, llvm::hlsl::InterpolationModifier Modifiers=llvm::hlsl::InterpolationModifier::None)
CallArgList - Type for representing both the value and type of arguments in a call.
void add(RValue rvalue, QualType type)
A non-RAII class containing all the information about a bound opaque value.
CodeGenFunction - This class organizes the per-function state that is used while generating LLVM code...
const LangOptions & getLangOpts() const
@ TCK_MemberAccess
Checking the object expression in a non-static data member access.
void pushFullExprCleanup(CleanupKind kind, As... A)
pushFullExprCleanup - Push a cleanup to be run at the end of the current full-expression.
AggValueSlot CreateAggTemp(QualType T, const Twine &Name="tmp", RawAddress *Alloca=nullptr)
CreateAggTemp - Create a temporary memory object for the given aggregate type.
bool EmitLifetimeStart(llvm::Value *Addr)
Emit a lifetime.begin marker if some criteria are satisfied.
RValue EmitCall(const CGFunctionInfo &CallInfo, const CGCallee &Callee, ReturnValueSlot ReturnValue, const CallArgList &Args, llvm::CallBase **CallOrInvoke, bool IsMustTail, SourceLocation Loc, bool IsVirtualFunctionPointerThunk=false)
EmitCall - Generate a call of the given function, expecting the given result type,...
RawAddress CreateMemTempWithoutCast(QualType T, const Twine &Name="tmp")
CreateMemTemp - Create a temporary memory object of the given type, with appropriate alignmen without...
ASTContext & getContext() const
RValue EmitAnyExpr(const Expr *E, AggValueSlot aggSlot=AggValueSlot::ignored(), bool ignoreResult=false)
EmitAnyExpr - Emit code to compute the specified expression which can have any type.
llvm::Type * ConvertTypeForMem(QualType T)
Address EmitPointerWithAlignment(const Expr *Addr, LValueBaseInfo *BaseInfo=nullptr, TBAAAccessInfo *TBAAInfo=nullptr, KnownNonNull_t IsKnownNonNull=NotKnownNonNull)
EmitPointerWithAlignment - Given an expression with a pointer type, emit the value and compute our be...
LValue EmitCheckedLValue(const Expr *E, TypeCheckKind TCK)
Same as EmitLValue but additionally we generate checking code to guard against undefined behavior.
llvm::Value * EmitScalarExpr(const Expr *E, bool IgnoreResultAssign=false)
EmitScalarExpr - Emit the computation of the specified expression of LLVM scalar type,...
LValue MakeAddrLValue(Address Addr, QualType T, AlignmentSource Source=AlignmentSource::Type)
LValue EmitLValue(const Expr *E, KnownNonNull_t IsKnownNonNull=NotKnownNonNull)
EmitLValue - Emit code to compute a designator that specifies the location of the expression.
bool isOpaqueValueEmitted(const OpaqueValueExpr *E)
isOpaqueValueEmitted - Return true if the opaque value expression has already been emitted.
llvm::LLVMContext & getLLVMContext()
This class organizes the cross-function state that is used while generating LLVM code.
const PreprocessorOptions & getPreprocessorOpts() const
llvm::Module & getModule() const
llvm::Constant * GetAddrOfFunction(GlobalDecl GD, llvm::Type *Ty=nullptr, bool ForVTable=false, bool DontDefer=false, ForDefinition_t IsForDefinition=NotForDefinition)
Return the address of the given function.
void AddCXXGlobalInit(llvm::Function *F)
CodeGenTypes & getTypes()
const TargetInfo & getTarget() const
void EmitGlobal(GlobalDecl D)
Emit code for a single global function or var decl.
const llvm::DataLayout & getDataLayout() const
ASTContext & getContext() const
llvm::Constant * GetAddrOfGlobalVar(const VarDecl *D, llvm::Type *Ty=nullptr, ForDefinition_t IsForDefinition=NotForDefinition)
Return the llvm::Constant for the address of the given global variable.
const TargetCodeGenInfo & getTargetCodeGenInfo()
const CodeGenOptions & getCodeGenOpts() const
llvm::LLVMContext & getLLVMContext()
void EmitTopLevelDecl(Decl *D)
Emit code for a single top level declaration.
ConstantAddress GetAddrOfConstantCString(const std::string &Str, StringRef GlobalName=".str")
Returns a pointer to a character array containing the literal and a terminating '\0' character.
const CGFunctionInfo & arrangeFreeFunctionCall(const CallArgList &Args, const FunctionType *Ty, bool ChainCall, const FunctionDecl *ABIInfoFD)
Figure out the rules for calling a function with the given formal type using the given arguments.
llvm::Type * ConvertTypeForMem(QualType T)
ConvertTypeForMem - Convert type T into a llvm::Type.
llvm::Constant * getPointer() const
llvm::StructType * layOutStruct(const RecordType *StructType, const CGHLSLOffsetInfo &OffsetInfo)
Lays out a struct type following HLSL buffer rules and considering any explicit offset information.
llvm::Type * layOutType(QualType Type)
Lays out a type following HLSL buffer rules.
LValue - This represents an lvalue references.
static LValue MakeAddr(Address Addr, QualType type, ASTContext &Context, LValueBaseInfo BaseInfo, TBAAAccessInfo TBAAInfo)
const Qualifiers & getQuals() const
Address getAddress() const
RValue - This trivial value class is used to represent the result of an expression that is evaluated.
static RValue get(llvm::Value *V)
An abstract representation of an aligned address.
llvm::Value * getPointer() const
ReturnValueSlot - Contains the address where the return value of a function can be stored,...
virtual bool isHLSLPadding(llvm::Type *Ty) const
Return true if this is an HLSL padding type.
Represents the canonical version of C arrays with a specified constant size.
int64_t getSExtSize() const
Return the size sign-extended as a uint64_t.
Represents a concrete matrix type with constant number of rows and columns.
DeclContext * getParent()
getParent - Returns the containing DeclContext.
Decl - This represents one declaration (or definition), e.g.
ASTContext & getASTContext() const LLVM_READONLY
bool isImplicit() const
isImplicit - Indicates whether the declaration was implicitly generated by the implementation.
SourceLocation getLocation() const
specific_attr_iterator< T > specific_attr_end() const
specific_attr_iterator< T > specific_attr_begin() const
Represents a ValueDecl that came out of a declarator.
This represents one expression.
Expr * IgnoreParenImpCasts() LLVM_READONLY
Skip past any parentheses and implicit casts which might surround this expression until reaching a fi...
std::optional< llvm::APSInt > getIntegerConstantExpr(const ASTContext &Ctx, bool AllowRelaxedEval=false) const
isIntegerConstantExpr - Return the value if this expression is a valid integer constant expression.
Expr * IgnoreImpCasts() LLVM_READONLY
Skip past any implicit casts which might surround this expression until reaching a fixed point.
Represents a member of a struct/union/class.
StringRef getName() const
The name of this FileEntry.
Represents a function declaration or definition.
const ParmVarDecl * getParamDecl(unsigned i) const
QualType getDeclaredReturnType() const
Get the declared return type, which may differ from the actual return type if the return type is dedu...
Represents a prototype with parameter type info, e.g.
HLSLBufferDecl - Represent a cbuffer or tbuffer declaration.
const CXXRecordDecl * getLayoutStruct() const
bool hasValidPackoffset() const
buffer_decl_range buffer_decls() const
This class represents temporary values used to represent inout and out arguments in HLSL.
ArrayRef< llvm::hlsl::rootsig::RootElement > getRootElements() const
llvm::dxbc::RootSignatureVersion getVersion() const
One of these records is kept for each identifier that is lexed.
Describes an C or C++ initializer list.
MemberExpr - [C99 6.5.2.3] Structure and Union Members.
ValueDecl * getMemberDecl() const
Retrieve the member declaration to which this expression refers.
IdentifierInfo * getIdentifier() const
Get the identifier that names this declaration, if there is one.
StringRef getName() const
Get the name of identifier for this declaration as a StringRef.
OpaqueValueExpr - An expression referring to an opaque object of a fixed type and value class.
Expr * getSourceExpr() const
The source expression of an opaque value expression is the expression which originally generated the ...
Represents a parameter to a function.
std::vector< std::pair< std::string, bool > > Macros
A (possibly-)qualified type.
const Type * getTypePtr() const
Retrieves a pointer to the underlying (unqualified) type.
LangAS getAddressSpace() const
Return the address space of this type.
The collection of all-type qualifiers we support.
void addCVRQualifiers(unsigned mask)
Represents a struct/union/class.
unsigned getNumFields() const
Returns the number of fields (non-static data members) in this record.
field_iterator field_begin() const
A class that does preorder or postorder depth-first traversal on the entire Clang AST and visits each...
bool TraverseStmt(Stmt *S, DataRecursionQueue *Queue=nullptr)
Encodes a location in the source.
One instance of this struct is kept for every file loaded or used.
std::optional< llvm::MemoryBufferRef > getBufferOrNone(DiagnosticsEngine &Diag, FileManager &FM, SourceLocation Loc=SourceLocation()) const
Returns the memory buffer for the associated content.
OptionalFileEntryRef OrigEntry
Reference to the file entry representing this ContentCache.
Information about a FileID, basically just the logical file that it represents and include stack info...
const ContentCache & getContentCache() const
CharacteristicKind getFileCharacteristic() const
Return whether this is a system header or not.
This is a discriminated union of FileInfo and ExpansionInfo.
const FileInfo & getFile() const
const llvm::Triple & getTriple() const
Returns the target triple of the primary target.
Token - This structure provides full information about a lexed token.
The base class of the type hierarchy.
bool isSignedIntegerOrEnumerationType() const
Determines whether this is an integer type that is signed or an enumeration types whose underlying ty...
bool isIncompleteArrayType() const
CXXRecordDecl * getAsCXXRecordDecl() const
Retrieves the CXXRecordDecl that this type refers to, either because the type is a RecordType or beca...
RecordDecl * getAsRecordDecl() const
Retrieves the RecordDecl this type refers to.
bool isConstantMatrixType() const
bool isHLSLIntangibleType() const
bool isHLSLResourceRecord() const
bool isStructureOrClassType() const
const T * getAsCanonical() const
If this type is canonically the specified type, return its canonical type cast to that specified type...
const T * getAs() const
Member-template getAs<specific type>'.
const Type * getUnqualifiedDesugaredType() const
Return the specified type with any "sugar" removed from the type, removing any typedefs,...
bool isRecordType() const
bool isHLSLResourceRecordArray() const
bool hasBooleanRepresentation() const
Determine whether this type has a boolean representation – i.e., it is a boolean type,...
Represent the declaration of a variable (in which case it is an lvalue) a function (in which case it ...
Represents a variable declaration or definition.
bool hasGlobalStorage() const
Returns true for all variables that do not have local storage.
StorageClass getStorageClass() const
Returns the storage class as written in the source.
Represents a GCC generic vector type.
void pushName(llvm::StringRef N)
void pushArrayIndex(uint64_t Index)
llvm::StringRef getName() const
void pushBaseNameHierarchy(CXXRecordDecl *DerivedRD, CXXRecordDecl *BaseRD)
IdentifierInfo * getNameAsIdentifier(ASTContext &AST) const
specific_attr_iterator - Iterates over a subrange of an AttrVec, only providing attributes that are o...
@ Type
The l-value was considered opaque, so the alignment was determined from a type.
@ Decl
The l-value was an access to a declared entity or something equivalently strong, like the address of ...
bool isSystem(CharacteristicKind CK)
Determine whether a file / directory characteristic is for system code.
@ Macros
Canonicalize -D and -U options.
bool hasCounterHandle(const CXXRecordDecl *RD)
StringRef getName(const HeaderType T)
@ Address
A pointer to a ValueDecl.
bool Load(InterpState &S, CodePtr OpPC)
Top level wrappers for InstallAPI frontend operations.
bool isa(CodeGen::Address addr)
CustomizableOptional< FileEntryRef > OptionalFileEntryRef
nullptr
This class represents a compute construct, representing a 'Kind' of ‘parallel’, 'serial',...
StorageClass
Storage classes.
@ Result
The result type of a method or function.
const FunctionProtoType * T
U cast(CodeGen::Address addr)
Diagnostic wrappers for TextAPI types for error reporting.
__builtin_bitreverse32 uint32_t __builtin_riscv_aaddu_u32 __builtin_riscv_asubu_u32 __builtin_elementwise_add_sat __builtin_elementwise_sub_sat int32_t uint32_t uint32_t __builtin_riscv_mhacc_i32 __builtin_riscv_mhaccu_u32 __builtin_riscv_mhaccsu_i32 __builtin_riscv_mulq_i32 uint8_t
llvm::IntegerType * Int32Ty
llvm::IntegerType * IntTy
int
unsigned getImplicitOrderID() const
bool hasCounterImplicitOrderID() const
unsigned getSpace() const
unsigned getCounterImplicitOrderID() const