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/IR/Constants.h"
42#include "llvm/IR/DerivedTypes.h"
43#include "llvm/IR/GlobalVariable.h"
44#include "llvm/IR/IntrinsicInst.h"
45#include "llvm/IR/LLVMContext.h"
46#include "llvm/IR/Metadata.h"
47#include "llvm/IR/Module.h"
48#include "llvm/IR/Type.h"
49#include "llvm/IR/Value.h"
50#include "llvm/Support/Alignment.h"
51#include "llvm/Support/ErrorHandling.h"
52#include "llvm/Support/FormatVariadic.h"
53#include "llvm/Support/Path.h"
54#include "llvm/Transforms/Utils/ModuleUtils.h"
64using llvm::hlsl::CBufferRowSizeInBytes;
68void addDxilValVersion(StringRef ValVersionStr, llvm::Module &M) {
72 if (Version.tryParse(ValVersionStr) || Version.getBuild() ||
73 Version.getSubminor() || !Version.getMinor()) {
77 uint64_t Major = Version.getMajor();
78 uint64_t Minor = *Version.getMinor();
80 auto &Ctx = M.getContext();
81 IRBuilder<> B(M.getContext());
82 MDNode *Val = MDNode::get(Ctx, {ConstantAsMetadata::get(B.getInt32(Major)),
83 ConstantAsMetadata::get(B.getInt32(Minor))});
84 StringRef DXILValKey =
"dx.valver";
85 auto *DXILValMD = M.getOrInsertNamedMetadata(DXILValKey);
86 DXILValMD->addOperand(Val);
89void addRootSignatureMD(llvm::dxbc::RootSignatureVersion RootSigVer,
91 llvm::Function *Fn, llvm::Module &M) {
92 auto &Ctx = M.getContext();
94 llvm::hlsl::rootsig::MetadataBuilder RSBuilder(Ctx, Elements);
95 MDNode *RootSignature = RSBuilder.BuildRootSignature();
97 ConstantAsMetadata *Version = ConstantAsMetadata::get(ConstantInt::get(
98 llvm::Type::getInt32Ty(Ctx), llvm::to_underlying(RootSigVer)));
99 ValueAsMetadata *EntryFunc =
Fn ? ValueAsMetadata::get(Fn) :
nullptr;
100 MDNode *MDVals = MDNode::get(Ctx, {EntryFunc, RootSignature, Version});
102 StringRef RootSignatureValKey =
"dx.rootsignatures";
103 auto *RootSignatureValMD = M.getOrInsertNamedMetadata(RootSignatureValKey);
104 RootSignatureValMD->addOperand(MDVals);
107MDNode *buildSemanticSignatureMD(
109 if (Elements.empty())
113 for (
const llvm::hlsl::SemanticSignatureElement &Element : Elements)
114 ElementMD.push_back(Element.toMetadata(Ctx));
115 return MDNode::get(Ctx, ElementMD);
118void addSemanticSignatureMD(
121 llvm::Function *Fn, llvm::Module &M) {
122 if (InputElements.empty() && OutputElements.empty())
125 LLVMContext &Ctx = M.getContext();
126 MDNode *InputSignature = buildSemanticSignatureMD(InputElements, Ctx);
127 MDNode *OutputSignature = buildSemanticSignatureMD(OutputElements, Ctx);
128 MDNode *MDVals = MDNode::get(
129 Ctx, {ValueAsMetadata::get(Fn), InputSignature, OutputSignature});
131 M.getOrInsertNamedMetadata(
"dx.semantic.signatures")->addOperand(MDVals);
136 GlobalVariable *ResGV =
138 assert(ResGV &&
"expected valid global variable");
155static const VarDecl *findStructResourceParentDeclAndBuildName(
162 if (
const auto *DRE = dyn_cast<DeclRefExpr>(E)) {
164 "member expr base is not a var decl");
170 WorkList.push_back(E);
171 if (
const auto *MExp = dyn_cast<MemberExpr>(E))
173 else if (
const auto *ICE = dyn_cast<ImplicitCastExpr>(E))
174 E = ICE->getSubExpr();
175 else if (
const auto *ASE = dyn_cast<ArraySubscriptExpr>(E))
182 llvm_unreachable(
"unexpected expr type in resource member access");
184 assert(E &&
"expected valid expression");
187 while (!WorkList.empty()) {
188 E = WorkList.pop_back_val();
189 if (
const auto *ME = dyn_cast<MemberExpr>(E)) {
191 ME->getMemberNameInfo().getName().getAsIdentifierInfo()->getName());
192 }
else if (
const auto *ICE = dyn_cast<ImplicitCastExpr>(E)) {
193 if (ICE->getCastKind() == CK_UncheckedDerivedToBase) {
195 ICE->getSubExpr()->getType()->getAsCXXRecordDecl();
196 CXXRecordDecl *BaseRD = ICE->getType()->getAsCXXRecordDecl();
199 }
else if (
const auto *ASE = dyn_cast<ArraySubscriptExpr>(E)) {
200 const Expr *IdxExpr = ASE->getIdx();
201 std::optional<llvm::APSInt>
Value =
204 "expected constant index in struct with resource array access");
207 llvm_unreachable(
"unexpected expr type in resource member access");
221 findStructResourceParentDeclAndBuildName(ME, NameBuilder);
230 if (
const auto *ADA = dyn_cast<HLSLAssociatedResourceDeclAttr>(A)) {
231 VarDecl *AssocResVD = ADA->getResDecl();
243 auto &Ctx = M.getContext();
246 llvm::NamedMDNode *DXContents =
247 M.getOrInsertNamedMetadata(
"dx.source.contents");
248 auto addFile = [&](
const std::pair<StringRef, StringRef> &NameContent) {
249 llvm::MDTuple *FileInfo =
250 llvm::MDNode::get(Ctx, {llvm::MDString::get(Ctx, NameContent.first),
251 llvm::MDString::get(Ctx, NameContent.second)});
252 DXContents->addOperand(FileInfo);
257 &SM.getSLocEntry(SM.getMainFileID(), &
Invalid);
258 assert(!
Invalid &&
"Main file SLocEntry must not be invalid!");
263 std::optional<SmallString<256>> MainFileName;
264 Files.reserve(SM.local_sloc_entry_size());
265 for (
unsigned I : llvm::seq(SM.local_sloc_entry_size())) {
280 llvm::sys::path::native(Path);
284 SM.getDiagnostics().Report(diag::warn_hlsl_failed_to_embed_source)
289 if (&MainCCEntry != &CCEntry) {
290 Files.emplace_back(Path, Buffer->getBuffer());
293 addFile(std::make_pair(Path, Buffer->getBuffer()));
294 MainFileName.emplace(Path);
297 assert(MainFileName &&
"Main file not found.");
302 for (
unsigned I = 1; I < Files.size(); ++I)
303 assert((Files[I - 1].first != Files[I].first) &&
304 "duplicate files in dx.source.contents");
306 llvm::for_each(Files, addFile);
309 Defines.reserve(
Macros.size());
310 for (
const auto &
Macro : Macros) {
313 Defines.emplace_back(llvm::MDString::get(Ctx,
Macro.first));
315 M.getOrInsertNamedMetadata(
"dx.source.defines")
316 ->addOperand(llvm::MDNode::get(Ctx, Defines));
318 if (!CodeGenOpts.MainFileName.empty())
319 llvm::sys::path::native(CodeGenOpts.MainFileName, *MainFileName);
320 M.getOrInsertNamedMetadata(
"dx.source.mainFileName")
322 llvm::MDNode::get(Ctx, llvm::MDString::get(Ctx, *MainFileName)));
325 Args.reserve(CodeGenOpts.HLSLParsedCommandLine.size());
326 if (!CodeGenOpts.HLSLParsedCommandLine.empty())
327 for (
const auto &Arg : llvm::drop_begin(CodeGenOpts.HLSLParsedCommandLine))
328 Args.push_back(llvm::MDString::get(Ctx, Arg));
329 M.getOrInsertNamedMetadata(
"dx.source.args")
330 ->addOperand(llvm::MDNode::get(Ctx, Args));
336 if (
const auto *DRE = dyn_cast_or_null<DeclRefExpr>(E))
337 return DRE->getDecl();
338 if (
auto *OVE = dyn_cast<OpaqueValueExpr>(E))
348 const Expr *E =
nullptr;
349 while (ASE !=
nullptr) {
353 ASE = dyn_cast<ArraySubscriptExpr>(E);
355 return getArrayDecl(AST, E);
361 assert(Ty->
isArrayType() &&
"expected array type");
367static Value *buildNameForResource(llvm::StringRef BaseName,
376 for (
auto *Method :
Record->methods()) {
377 if (Method->getStorageClass() == SC && Method->getName() == Name)
387 assert(Binding.
hasBinding() &&
"at least one binding attribute expected");
391 Value *NameStr = buildNameForResource(Name, CGM);
396 "resources with counter handle must have a binding with counter "
397 "implicit order ID");
400 auto *RegSlot = llvm::ConstantInt::get(CGM.
IntTy, Binding.
getSlot());
403 ?
"__createFromBindingWithImplicitCounter"
404 :
"__createFromBinding";
405 CreateMethod = lookupMethod(ResourceDecl, Name,
SC_Static);
412 ?
"__createFromImplicitBindingWithImplicitCounter"
413 :
"__createFromImplicitBinding";
414 CreateMethod = lookupMethod(ResourceDecl, Name,
SC_Static);
422 auto *CounterOrderID = llvm::ConstantInt::get(CGM.
IntTy, CounterBinding);
438 Args, Proto,
false,
nullptr);
441 CGF.
EmitCall(FnInfo, Callee, ReturnValue, Args,
nullptr);
450static std::optional<llvm::Value *> initializeResourceArrayFromGlobal(
453 llvm::Value *Range, llvm::Value *StartIndex, StringRef ResourceName,
457 llvm::IntegerType *IntTy = CGF.
CGM.
IntTy;
458 llvm::Value *Index = StartIndex;
459 llvm::Value *One = llvm::ConstantInt::get(IntTy, 1);
467 GEPIndices.push_back(llvm::ConstantInt::get(IntTy, 0));
472 for (uint64_t I = 0; I < ArraySize; I++) {
474 Index = CGF.
Builder.CreateAdd(Index, One);
475 GEPIndices.back() = llvm::ConstantInt::get(IntTy, I);
477 std::optional<llvm::Value *> MaybeIndex =
478 initializeResourceArrayFromGlobal(CGF, ResourceDecl, SubArrayTy,
479 ValueSlot, Range, Index,
480 ResourceName, Binding, GEPIndices);
494 for (uint64_t I = 0; I < ArraySize; I++) {
496 Index = CGF.
Builder.CreateAdd(Index, One);
497 GEPIndices.back() = llvm::ConstantInt::get(IntTy, I);
503 CXXMethodDecl *CreateMethod = lookupResourceInitMethodAndSetupArgs(
504 CGF.
CGM, ResourceDecl, Range, Index, ResourceName, Binding, Args);
512 callResourceInitMethod(CGF, CreateMethod, Args, ReturnAddress);
519class HLSLBufferCopyEmitter {
520 CodeGenFunction &CGF;
523 llvm::Type *LayoutTy =
nullptr;
525 SmallVector<llvm::Value *> CurStoreIndices;
526 SmallVector<llvm::Value *> CurLoadIndices;
528 using EmitResourceFnTy = llvm::function_ref<void(AggValueSlot &)>;
532 llvm::Value *emitAccessChain(llvm::Type *BaseTy, llvm::Value *Base,
533 ArrayRef<llvm::Value *> Indices) {
534 bool EmitLogical = CGF.getLangOpts().EmitLogicalPointer;
536 return CGF.Builder.CreateAccessChain(EmitLogical, BaseTy, Base, Indices);
538 llvm::SmallVector<llvm::Value *> GEPIndices;
539 GEPIndices.reserve(Indices.size() + 1);
540 GEPIndices.push_back(llvm::ConstantInt::get(CGF.IntTy, 0));
541 GEPIndices.append(Indices.begin(), Indices.end());
542 return CGF.Builder.CreateAccessChain(EmitLogical, BaseTy, Base, GEPIndices);
545 bool isBufferLayoutArray(llvm::StructType *ST) {
551 if (!ST || ST->getNumElements() != 2)
554 auto *PaddedEltsTy = dyn_cast<llvm::ArrayType>(ST->getElementType(0));
558 auto *PaddedTy = dyn_cast<llvm::StructType>(PaddedEltsTy->getElementType());
559 if (!PaddedTy || PaddedTy->getNumElements() != 2)
562 if (!CGF.CGM.getTargetCodeGenInfo().isHLSLPadding(
563 PaddedTy->getElementType(1)))
566 llvm::Type *ElementTy = ST->getElementType(1);
567 if (PaddedTy->getElementType(0) != ElementTy)
578 bool isResourceOrResourceArray(llvm::Type *Ty) {
579 while (
auto *AT = dyn_cast<llvm::ArrayType>(Ty))
580 Ty = AT->getElementType();
582 auto *ST = dyn_cast<llvm::StructType>(Ty);
583 if (!ST || ST->getNumElements() < 1)
586 auto *TargetTy = dyn_cast<llvm::TargetExtType>(ST->getElementType(0));
587 return TargetTy !=
nullptr;
590 void emitResourceOrResourceArray(
Value *Dst, llvm::Type *DstTy,
591 EmitResourceFnTy EmitResFn) {
594 Address DstAddr(Dst, DstTy, DstAlign);
603 void emitBufferLayoutCopy(
Value *Src, llvm::StructType *SrcTy,
Value *Dst,
604 llvm::ArrayType *DstTy,
605 EmitResourceFnTy EmitResFn) {
608 assert(SrcPaddedArrayTy->getNumElements() + 1 == DstTy->getNumElements());
610 ->getElementType(0) == SrcTy->getElementType(1));
612 auto *SrcDataTy = SrcTy->getElementType(1);
613 auto Zero = llvm::ConstantInt::get(CGF.IntTy, 0);
615 for (
unsigned I = 0; I < SrcPaddedArrayTy->getNumElements(); ++I) {
616 auto Index = llvm::ConstantInt::get(CGF.IntTy, I);
617 auto *SrcElt = emitAccessChain(SrcTy, Src, {
Zero, Index,
Zero});
618 auto *DstElt = emitAccessChain(DstTy, Dst, {Index});
619 emitElementCopy(SrcElt, SrcDataTy, DstElt, DstTy->getElementType(),
624 emitAccessChain(SrcTy, Src, {llvm::ConstantInt::get(CGF.IntTy, 1)});
625 auto *DstElt = emitAccessChain(
627 {llvm::ConstantInt::get(CGF.IntTy, DstTy->getNumElements() - 1)});
628 emitElementCopy(SrcElt, SrcDataTy, DstElt, DstTy->getElementType(),
632 void emitCopy(
Value *Src, llvm::StructType *SrcTy,
Value *Dst,
633 llvm::Type *DstTy, EmitResourceFnTy EmitResFn) {
634 assert(!isResourceOrResourceArray(DstTy) &&
635 "direct access to resources or resource arrays should be handled "
638 if (isBufferLayoutArray(SrcTy))
642 unsigned SrcIndex = 0;
643 unsigned DstIndex = 0;
650 while (DstIndex < DstST->getNumElements()) {
651 llvm::Type *DstEltTy = DstST->getElementType(DstIndex);
652 if (CGF.CGM.getTargetCodeGenInfo().isHLSLPadding(DstEltTy)) {
656 if (isResourceOrResourceArray(DstEltTy)) {
657 auto *DstElt = emitAccessChain(
658 DstTy, Dst, {llvm::ConstantInt::get(CGF.IntTy, DstIndex)});
659 emitResourceOrResourceArray(DstElt, DstEltTy, EmitResFn);
664 assert(SrcIndex < SrcTy->getNumElements());
665 llvm::Type *SrcEltTy = SrcTy->getElementType(SrcIndex);
666 if (CGF.CGM.getTargetCodeGenInfo().isHLSLPadding(SrcEltTy)) {
671 auto *SrcElt = emitAccessChain(
672 SrcTy, Src, {llvm::ConstantInt::get(CGF.IntTy, SrcIndex)});
673 auto *DstElt = emitAccessChain(
674 DstTy, Dst, {llvm::ConstantInt::get(CGF.IntTy, DstIndex)});
675 emitElementCopy(SrcElt, SrcEltTy, DstElt, DstEltTy, EmitResFn);
681 void emitCopy(
Value *Src, llvm::ArrayType *SrcTy,
Value *Dst,
682 llvm::Type *DstTy, EmitResourceFnTy EmitResFn) {
683 for (
unsigned I = 0, E = SrcTy->getNumElements(); I < E; ++I) {
685 emitAccessChain(SrcTy, Src, {llvm::ConstantInt::get(CGF.IntTy, I)});
687 emitAccessChain(DstTy, Dst, {llvm::ConstantInt::get(CGF.IntTy, I)});
688 emitElementCopy(SrcElt, SrcTy->getElementType(), DstElt,
694 void emitElementCopy(
Value *Src, llvm::Type *SrcTy,
Value *Dst,
695 llvm::Type *DstTy, EmitResourceFnTy EmitResFn) {
696 if (
auto *AT = dyn_cast<llvm::ArrayType>(SrcTy))
697 return emitCopy(Src, AT, Dst, DstTy, EmitResFn);
698 if (
auto *ST = dyn_cast<llvm::StructType>(SrcTy))
699 return emitCopy(Src, ST, Dst, DstTy, EmitResFn);
706 Address SrcAddr(Src, SrcTy, SrcAlign);
707 Address DstAddr(Dst, DstTy, DstAlign);
708 llvm::Value *
Load = CGF.Builder.CreateLoad(SrcAddr,
"cbuf.load");
709 CGF.Builder.CreateStore(Load, DstAddr);
713 HLSLBufferCopyEmitter(CodeGenFunction &CGF, Address DstPtr, Address SrcPtr)
714 : CGF(CGF), DstPtr(DstPtr), SrcPtr(SrcPtr) {}
716 bool emitCopy(QualType CType, EmitResourceFnTy EmitResFn =
nullptr) {
717 LayoutTy = HLSLBufferLayoutBuilder(CGF.CGM).layOutType(CType);
724 emitElementCopy(SrcPtr.getBasePointer(), LayoutTy, DstPtr.getBasePointer(),
725 DstPtr.getElementType(), EmitResFn);
736class AssociatedResourcesList {
741 specific_attr_iterator<HLSLAssociatedResourceDeclAttr> Begin, End, Next;
744 AssociatedResourcesList(
const VarDecl *StructVD,
745 StringRef ResourceNamePrefix) {
751 !I->getResDecl()->getName().starts_with(ResourceNamePrefix))
753 assert(I != E &&
"expected associated resource not found");
758 while (I != E && ((HLSLAssociatedResourceDeclAttr *)*I)
761 .starts_with(ResourceNamePrefix))
767 const VarDecl *getNextResource() {
771 const VarDecl *Res = Next->getResDecl();
782 assert(
T->isHLSLSpecificType() &&
"Not an HLSL specific type!");
785 if (llvm::Type *TargetTy =
786 CGM.getTargetCodeGenInfo().getHLSLType(
CGM,
T, OffsetInfo))
789 llvm_unreachable(
"Generic handling of HLSL types is not supported.");
792llvm::Triple::ArchType CGHLSLRuntime::getArch() {
798void CGHLSLRuntime::emitBufferGlobalsAndMetadata(
804 llvm::Type *BufType = BufGV->getValueType();
809 size_t OffsetIdx = 0;
819 VarDecl *VD = dyn_cast<VarDecl>(D);
835 DeclsWithOffset.emplace_back(VD, OffsetInfo[OffsetIdx++]);
838 if (!OffsetInfo.
empty())
839 llvm::stable_sort(DeclsWithOffset, [](
const auto &LHS,
const auto &RHS) {
844 SmallVector<llvm::Metadata *> BufGlobals;
845 BufGlobals.reserve(DeclsWithOffset.size() + 1);
846 BufGlobals.push_back(ValueAsMetadata::get(BufGV));
848 auto ElemIt = LayoutStruct->element_begin();
849 for (
auto &[VD, _] : DeclsWithOffset) {
850 if (
CGM.getTargetCodeGenInfo().isHLSLPadding(*ElemIt))
853 assert(ElemIt != LayoutStruct->element_end() &&
854 "number of elements in layout struct does not match");
855 llvm::Type *LayoutType = *ElemIt++;
857 GlobalVariable *ElemGV =
859 BufGlobals.push_back(ValueAsMetadata::get(ElemGV));
861 assert(ElemIt == LayoutStruct->element_end() &&
862 "number of elements in layout struct does not match");
866 .getOrInsertNamedMetadata(
"hlsl.cbs")
867 ->addOperand(MDNode::get(Ctx, BufGlobals));
871static const clang::HLSLAttributedResourceType *
876 HLSLAttributedResourceType::Attributes(ResourceClass::CBuffer));
891 VarDecl *VD = dyn_cast<VarDecl>(D);
902 if (
auto *POA = dyn_cast<HLSLPackOffsetAttr>(
Attr)) {
903 Offset = POA->getOffsetInBytes();
906 auto *RBA = dyn_cast<HLSLResourceBindingAttr>(
Attr);
908 RBA->getRegisterType() == HLSLResourceBindingAttr::RegisterType::C) {
909 Offset = RBA->getSlotNumber() * CBufferRowSizeInBytes;
913 Result.Offsets.push_back(Offset);
921 assert(BufDecl->
isCBuffer() &&
"tbuffer codegen is not supported yet");
924 const clang::HLSLAttributedResourceType *ResHandleTy =
928 if (ResHandleTy->getContainedType()->getAsCXXRecordDecl()->isEmpty())
934 llvm::GlobalVariable *BufGV =
new GlobalVariable(
936 GlobalValue::LinkageTypes::InternalLinkage, PoisonValue::get(LayoutTy),
937 llvm::formatv(
"{0}{1}", BufDecl->
getName(),
939 GlobalValue::NotThreadLocal);
941 llvm::Module &M =
CGM.getModule();
942 M.insertGlobalVariable(BufGV);
947 llvm::appendToCompilerUsed(M, {BufGV});
950 emitBufferGlobalsAndMetadata(BufDecl, BufGV, OffsetInfo);
953 initializeBufferFromBinding(BufDecl, BufGV);
958 llvm::Module &M =
CGM.getModule();
959 Triple
T(M.getTargetTriple());
962 if (
T.getEnvironment() != Triple::EnvironmentType::RootSignature)
965 addRootSignatureMD(SignatureDecl->
getVersion(),
971 const auto Entry = LayoutTypes.find(StructType);
972 if (Entry != LayoutTypes.end())
973 return Entry->getSecond();
978 llvm::StructType *LayoutTy) {
980 "layout type for this struct already exist");
981 LayoutTypes[StructType] = LayoutTy;
985 auto &TargetOpts =
CGM.getTarget().getTargetOpts();
986 auto &CodeGenOpts =
CGM.getCodeGenOpts();
987 auto &LangOpts =
CGM.getLangOpts();
988 llvm::Module &M =
CGM.getModule();
989 Triple
T(M.getTargetTriple());
990 if (
T.getArch() == Triple::ArchType::dxil)
991 addDxilValVersion(TargetOpts.DxilValidatorVersion, M);
992 if (!CodeGenOpts.DisableDXSourceMetadata &&
993 CodeGenOpts.getDebugInfo() >=
994 llvm::codegenoptions::DebugInfoKind::DebugInfoConstructor)
995 addSourceInfo(
CGM, M);
996 if (CodeGenOpts.ResMayAlias)
997 M.setModuleFlag(llvm::Module::ModFlagBehavior::Error,
"dx.resmayalias", 1);
998 if (CodeGenOpts.AllResourcesBound)
999 M.setModuleFlag(llvm::Module::ModFlagBehavior::Error,
1000 "dx.allresourcesbound", 1);
1001 if (CodeGenOpts.OptimizationLevel == 0)
1002 M.addModuleFlag(llvm::Module::ModFlagBehavior::Override,
1003 "dx.disable_optimizations", 1);
1008 if (LangOpts.NativeHalfType)
1009 M.setModuleFlag(llvm::Module::ModFlagBehavior::Error,
"dx.nativelowprec",
1012 if (LangOpts.HLSLSpvPreserveInterface &&
T.isSPIRV()) {
1018 for (GlobalVariable &GV : M.globals()) {
1019 unsigned AS = GV.getAddressSpace();
1020 if (AS == InputAS || AS == OutputAS)
1021 InterfaceVars.push_back(&GV);
1023 if (!InterfaceVars.empty())
1024 appendToCompilerUsed(M, InterfaceVars);
1032 const auto *ShaderAttr = FD->
getAttr<HLSLShaderAttr>();
1033 assert(ShaderAttr &&
"All entry functions must have a HLSLShaderAttr");
1034 const StringRef ShaderAttrKindStr =
"hlsl.shader";
1035 Fn->addFnAttr(ShaderAttrKindStr,
1036 llvm::Triple::getEnvironmentTypeName(ShaderAttr->getType()));
1037 if (HLSLNumThreadsAttr *NumThreadsAttr = FD->
getAttr<HLSLNumThreadsAttr>()) {
1038 const StringRef NumThreadsKindStr =
"hlsl.numthreads";
1039 std::string NumThreadsStr =
1040 formatv(
"{0},{1},{2}", NumThreadsAttr->getX(), NumThreadsAttr->getY(),
1041 NumThreadsAttr->getZ());
1042 Fn->addFnAttr(NumThreadsKindStr, NumThreadsStr);
1044 if (HLSLWaveSizeAttr *WaveSizeAttr = FD->
getAttr<HLSLWaveSizeAttr>()) {
1045 const StringRef WaveSizeKindStr =
"hlsl.wavesize";
1046 std::string WaveSizeStr =
1047 formatv(
"{0},{1},{2}", WaveSizeAttr->getMin(), WaveSizeAttr->getMax(),
1048 WaveSizeAttr->getPreferred());
1049 Fn->addFnAttr(WaveSizeKindStr, WaveSizeStr);
1056 Fn->addFnAttr(llvm::Attribute::NoInline);
1058 if (
CGM.getLangOpts().HLSLSpvEnableMaximalReconvergence) {
1059 Fn->addFnAttr(
"enable-maximal-reconvergence",
"true");
1064 if (
const auto *VT = dyn_cast<FixedVectorType>(Ty)) {
1066 for (
unsigned I = 0; I < VT->getNumElements(); ++I) {
1067 Value *Elt = B.CreateCall(F, {B.getInt32(I)});
1072 return B.CreateCall(F, {B.getInt32(0)});
1077 LLVMContext &Ctx = GV->getContext();
1078 IRBuilder<> B(GV->getContext());
1079 MDNode *Operands = MDNode::get(
1081 {ConstantAsMetadata::get(B.getInt32( 11)),
1082 ConstantAsMetadata::get(B.getInt32(BuiltIn))});
1083 MDNode *Decoration = MDNode::get(Ctx, {Operands});
1084 GV->addMetadata(
"spirv.Decorations", *Decoration);
1088 LLVMContext &Ctx = GV->getContext();
1089 IRBuilder<> B(GV->getContext());
1091 MDNode::get(Ctx, {ConstantAsMetadata::get(B.getInt32( 30)),
1092 ConstantAsMetadata::get(B.getInt32(Location))});
1093 MDNode *Decoration = MDNode::get(Ctx, {Operands});
1094 GV->addMetadata(
"spirv.Decorations", *Decoration);
1104 if (
auto *AT = dyn_cast<llvm::ArrayType>(Ty)) {
1105 Ty = AT->getElementType();
1108 if (
auto *VT = dyn_cast<llvm::FixedVectorType>(Ty)) {
1109 Ty = VT->getElementType();
1114 return Ty->isIntegerTy() || Ty->isDoubleTy();
1118 llvm::Type *Ty,
const Twine &Name,
1119 unsigned BuiltInID) {
1120 auto *GV =
new llvm::GlobalVariable(
1121 M, Ty,
true, llvm::GlobalValue::ExternalLinkage,
1122 nullptr, Name,
nullptr,
1123 llvm::GlobalVariable::GeneralDynamicTLSModel,
1126 GV->setVisibility(llvm::GlobalValue::HiddenVisibility);
1127 return B.CreateLoad(Ty, GV);
1131 llvm::Type *Ty,
unsigned Location,
1132 StringRef Name,
bool NeedsFlat) {
1133 auto *GV =
new llvm::GlobalVariable(
1134 M, Ty,
true, llvm::GlobalValue::ExternalLinkage,
1135 nullptr, Name,
nullptr,
1136 llvm::GlobalVariable::GeneralDynamicTLSModel,
1138 GV->setVisibility(llvm::GlobalValue::HiddenVisibility);
1143 LLVMContext &Ctx = GV->getContext();
1145 Decorations.push_back(
1146 MDNode::get(Ctx, {ConstantAsMetadata::get(
1148 ConstantAsMetadata::get(B.getInt32(Location))}));
1150 Decorations.push_back(
1151 MDNode::get(Ctx, {ConstantAsMetadata::get(
1152 B.getInt32( 14))}));
1153 GV->addMetadata(
"spirv.Decorations", *MDNode::get(Ctx, Decorations));
1155 return B.CreateLoad(Ty, GV);
1158llvm::Value *CGHLSLRuntime::emitSPIRVUserSemanticLoad(
1159 llvm::IRBuilder<> &B,
const FunctionDecl *FD, llvm::Type *
Type,
1160 const clang::DeclaratorDecl *
Decl, HLSLAppliedSemanticAttr *Semantic,
1161 std::optional<unsigned> Index) {
1162 Twine BaseName = Twine(Semantic->getAttrName()->getName());
1163 Twine VariableName = BaseName.concat(Twine(Index.value_or(0)));
1165 unsigned Location = SPIRVLastAssignedInputSemanticLocation;
1166 if (
auto *L =
Decl->getAttr<HLSLVkLocationAttr>())
1167 Location = L->getLocation();
1171 llvm::ArrayType *AT = dyn_cast<llvm::ArrayType>(
Type);
1172 unsigned ElementCount = AT ? AT->getNumElements() : 1;
1173 SPIRVLastAssignedInputSemanticLocation += ElementCount;
1175 const auto *ShaderAttr = FD->
getAttr<HLSLShaderAttr>();
1178 ShaderAttr->getType() == llvm::Triple::EnvironmentType::Pixel &&
1182 VariableName.str(), NeedsFlat);
1186 llvm::Value *Source,
unsigned Location,
1188 auto *GV =
new llvm::GlobalVariable(
1189 M, Source->getType(),
false,
1190 llvm::GlobalValue::ExternalLinkage,
1191 nullptr, Name,
nullptr,
1192 llvm::GlobalVariable::GeneralDynamicTLSModel,
1194 GV->setVisibility(llvm::GlobalValue::HiddenVisibility);
1196 B.CreateStore(Source, GV);
1199void CGHLSLRuntime::emitSPIRVUserSemanticStore(
1200 llvm::IRBuilder<> &B, llvm::Value *Source,
1201 const clang::DeclaratorDecl *
Decl, HLSLAppliedSemanticAttr *Semantic,
1202 std::optional<unsigned> Index) {
1203 Twine BaseName = Twine(Semantic->getAttrName()->getName());
1204 Twine VariableName = BaseName.concat(Twine(Index.value_or(0)));
1206 unsigned Location = SPIRVLastAssignedOutputSemanticLocation;
1207 if (
auto *L =
Decl->getAttr<HLSLVkLocationAttr>())
1208 Location = L->getLocation();
1212 llvm::ArrayType *AT = dyn_cast<llvm::ArrayType>(Source->getType());
1213 unsigned ElementCount = AT ? AT->getNumElements() : 1;
1214 SPIRVLastAssignedOutputSemanticLocation += ElementCount;
1216 VariableName.str());
1221struct SemanticShape {
1222 SmallVector<unsigned> Dimensions;
1226 unsigned getNumRows()
const {
1228 for (
unsigned Dimension : Dimensions)
1233 SmallVector<unsigned> getArrayIndicesForRow(
unsigned Row)
const {
1234 assert(Row < getNumRows() &&
"row exceeds semantic shape");
1236 SmallVector<unsigned> Indices(Dimensions.size());
1237 for (
auto [Index, Dimension] :
1238 llvm::zip_equal(llvm::reverse(Indices), llvm::reverse(Dimensions))) {
1239 Index = Row % Dimension;
1250 if (
const auto *FD = dyn_cast<clang::FunctionDecl>(
Decl))
1252 return Decl->getType();
1258 SemanticShape Shape{{}, 1, Ty};
1261 Shape.Dimensions.push_back(CAT->getSize().getZExtValue());
1262 Shape.RowType = CAT->getElementType();
1266 Shape.Cols = VT->getNumElements();
1267 }
else if (
const auto *MT =
1272 Shape.Cols = MT->getNumColumns();
1281 Ty = VT->getElementType();
1283 Ty = MT->getElementType();
1287 return llvm::hlsl::getDXILElementType(IRTy, IsSigned);
1292 std::optional<unsigned> Index,
const SemanticShape &Shape) {
1293 StringRef Name = Semantic->getAttrName()->getName();
1297 uint32_t FirstSemanticIndex = Index.value_or(0);
1298 for (
uint32_t I = 0, E = Shape.getNumRows(); I < E; ++I)
1299 SemanticIndices.push_back(FirstSemanticIndex + I);
1305 return llvm::hlsl::SemanticSignatureElement(
1307 llvm::hlsl::getSemanticKind(Name), SemanticIndices,
1308 static_cast<uint8_t>(Shape.Cols));
1311llvm::Value *CGHLSLRuntime::emitDXILUserSemanticLoad(
1312 llvm::IRBuilder<> &B, llvm::Type *
Type,
const clang::DeclaratorDecl *
Decl,
1313 HLSLAppliedSemanticAttr *Semantic, std::optional<unsigned> Index,
1314 SemanticSignatures &Signature) {
1315 StringRef Name = Semantic->getAttrName()->getName();
1316 SemanticShape Shape =
1320 Signature.push_back(
1323 llvm::Type *RowTy =
CGM.getTypes().ConvertTypeForMem(Shape.RowType);
1325 llvm::Function *IntrFn = llvm::Intrinsic::getOrInsertDeclaration(
1326 B.GetInsertBlock()->getModule(), llvm::Intrinsic::dx_load_input, {RowTy});
1328 SmallVector<OperandBundleDef, 1> OB;
1330 llvm::Value *bundleArgs[] = {Token};
1331 OB.emplace_back(
"convergencectrl", bundleArgs);
1334 llvm::Type *LeafTy =
CGM.getTypes().ConvertType(Shape.RowType);
1335 llvm::Value *
Result = llvm::PoisonValue::get(
Type);
1337 const unsigned NumRows = Shape.getNumRows();
1339 for (
unsigned Row = 0; Row < NumRows; ++Row) {
1340 SmallVector<unsigned> Indices = Shape.getArrayIndicesForRow(Row);
1341 std::array<Value *, 4> Args{
1345 llvm::PoisonValue::get(B.getInt32Ty())};
1346 llvm::Value *
Value =
1347 B.CreateCall(IntrFn, Args, OB, Twine(Name).concat(Twine(Row)));
1350 if (
Value->getType() != LeafTy) {
1352 "unexpected semantic load type mismatch");
1353 Value = B.CreateICmpNE(
1354 Value, llvm::Constant::getNullValue(
Value->getType()),
"loadedv");
1363void CGHLSLRuntime::emitDXILUserSemanticStore(llvm::IRBuilder<> &B,
1364 llvm::Value *Source,
1365 const clang::DeclaratorDecl *
Decl,
1366 HLSLAppliedSemanticAttr *Semantic,
1367 std::optional<unsigned> Index,
1368 SemanticSignatures &Signature) {
1369 SemanticShape Shape =
1373 Signature.push_back(
1376 llvm::Type *RowTy =
CGM.getTypes().ConvertTypeForMem(Shape.RowType);
1378 llvm::Function *IntrFn = llvm::Intrinsic::getOrInsertDeclaration(
1379 B.GetInsertBlock()->getModule(), llvm::Intrinsic::dx_store_output,
1382 SmallVector<OperandBundleDef, 1> OB;
1384 llvm::Value *bundleArgs[] = {Token};
1385 OB.emplace_back(
"convergencectrl", bundleArgs);
1388 const unsigned NumRows = Shape.getNumRows();
1389 for (
unsigned Row = 0; Row < NumRows; ++Row) {
1390 SmallVector<unsigned> Indices = Shape.getArrayIndicesForRow(Row);
1392 Indices.empty() ? Source : B.CreateExtractValue(Source, Indices);
1396 if (Val->getType() != RowTy) {
1398 "unexpected semantic store type mismatch");
1399 Val = B.CreateZExt(Val, RowTy,
"storedv");
1402 std::array<Value *, 4> Args{B.getInt32(SigId),
1405 B.CreateCall(IntrFn, Args, OB);
1409llvm::Value *CGHLSLRuntime::emitUserSemanticLoad(
1410 IRBuilder<> &B,
const FunctionDecl *FD, llvm::Type *
Type,
1411 const clang::DeclaratorDecl *
Decl, HLSLAppliedSemanticAttr *Semantic,
1412 std::optional<unsigned> Index, SemanticSignatures &Signature) {
1413 if (
CGM.getTarget().getTriple().isSPIRV())
1414 return emitSPIRVUserSemanticLoad(B, FD,
Type,
Decl, Semantic, Index);
1416 if (
CGM.getTarget().getTriple().isDXIL())
1417 return emitDXILUserSemanticLoad(B,
Type,
Decl, Semantic, Index, Signature);
1419 llvm_unreachable(
"Unsupported target for user-semantic load.");
1422void CGHLSLRuntime::emitUserSemanticStore(IRBuilder<> &B, llvm::Value *Source,
1423 const clang::DeclaratorDecl *
Decl,
1424 HLSLAppliedSemanticAttr *Semantic,
1425 std::optional<unsigned> Index,
1426 SemanticSignatures &Signature) {
1427 if (
CGM.getTarget().getTriple().isSPIRV())
1428 return emitSPIRVUserSemanticStore(B, Source,
Decl, Semantic, Index);
1430 if (
CGM.getTarget().getTriple().isDXIL())
1431 return emitDXILUserSemanticStore(B, Source,
Decl, Semantic, Index,
1434 llvm_unreachable(
"Unsupported target for user-semantic load.");
1439 HLSLAppliedSemanticAttr *Semantic,
1441 llvm::Triple::EnvironmentType Stage, std::optional<unsigned> Index,
1442 SemanticSignatures &Signature) {
1444 case llvm::dxbc::PSV::SemanticKind::GroupIndex: {
1445 assert(llvm::is_contained({llvm::Triple::Compute, llvm::Triple::Mesh,
1446 llvm::Triple::Amplification},
1448 "SV_GroupIndex is in an unavailable stage and should have been "
1449 "diagnosed by Sema");
1450 assert(Stage != llvm::Triple::Mesh &&
1451 Stage != llvm::Triple::Amplification &&
1452 "FIXME: SV_GroupIndex is not yet implemented for this shader "
1454 llvm::Function *GroupIndex =
1455 CGM.getIntrinsic(getFlattenedThreadIdInGroupIntrinsic());
1456 return B.CreateCall(FunctionCallee(GroupIndex));
1458 case llvm::dxbc::PSV::SemanticKind::DispatchThreadID: {
1459 assert(llvm::is_contained({llvm::Triple::Compute, llvm::Triple::Mesh,
1460 llvm::Triple::Amplification},
1462 "SV_DispatchThreadID is in an unavailable stage and should have "
1463 "been diagnosed by Sema");
1464 assert(Stage != llvm::Triple::Mesh &&
1465 Stage != llvm::Triple::Amplification &&
1466 "FIXME: SV_DispatchThreadID is not yet implemented for this "
1468 llvm::Intrinsic::ID IntrinID = getThreadIdIntrinsic();
1469 llvm::Function *ThreadIDIntrinsic =
1470 llvm::Intrinsic::isOverloaded(IntrinID)
1471 ?
CGM.getIntrinsic(IntrinID, {
CGM.Int32Ty})
1472 :
CGM.getIntrinsic(IntrinID);
1475 case llvm::dxbc::PSV::SemanticKind::GroupThreadID: {
1476 assert(llvm::is_contained({llvm::Triple::Compute, llvm::Triple::Mesh,
1477 llvm::Triple::Amplification},
1479 "SV_GroupThreadID is in an unavailable stage and should have been "
1480 "diagnosed by Sema");
1481 assert(Stage != llvm::Triple::Mesh &&
1482 Stage != llvm::Triple::Amplification &&
1483 "FIXME: SV_GroupThreadID is not yet implemented for this shader "
1485 llvm::Intrinsic::ID IntrinID = getGroupThreadIdIntrinsic();
1486 llvm::Function *GroupThreadIDIntrinsic =
1487 llvm::Intrinsic::isOverloaded(IntrinID)
1488 ?
CGM.getIntrinsic(IntrinID, {
CGM.Int32Ty})
1489 :
CGM.getIntrinsic(IntrinID);
1492 case llvm::dxbc::PSV::SemanticKind::GroupID: {
1493 assert(llvm::is_contained({llvm::Triple::Compute, llvm::Triple::Mesh,
1494 llvm::Triple::Amplification},
1496 "SV_GroupID is in an unavailable stage and should have been "
1497 "diagnosed by Sema");
1498 assert(Stage != llvm::Triple::Mesh &&
1499 Stage != llvm::Triple::Amplification &&
1500 "FIXME: SV_GroupID is not yet implemented for this shader stage");
1501 llvm::Intrinsic::ID IntrinID = getGroupIdIntrinsic();
1502 llvm::Function *GroupIDIntrinsic =
1503 llvm::Intrinsic::isOverloaded(IntrinID)
1504 ?
CGM.getIntrinsic(IntrinID, {
CGM.Int32Ty})
1505 :
CGM.getIntrinsic(IntrinID);
1508 case llvm::dxbc::PSV::SemanticKind::Position:
1509 assert(llvm::is_contained({llvm::Triple::Hull, llvm::Triple::Domain,
1510 llvm::Triple::Geometry, llvm::Triple::Pixel},
1512 "SV_Position is in an unavailable stage and should have been "
1513 "diagnosed by Sema");
1514 assert(Stage != llvm::Triple::Hull && Stage != llvm::Triple::Domain &&
1515 Stage != llvm::Triple::Geometry &&
1516 "FIXME: loading SV_Position is not yet implemented for this "
1518 if (
CGM.getTarget().getTriple().isSPIRV())
1520 Semantic->getAttrName()->getName(),
1522 if (
CGM.getTarget().getTriple().isDXIL())
1523 return emitDXILUserSemanticLoad(B,
Type,
Decl, Semantic, Index,
1526 case llvm::dxbc::PSV::SemanticKind::VertexID:
1527 assert(Stage == llvm::Triple::Vertex &&
1528 "SV_VertexID is in an unavailable stage and should have been "
1529 "diagnosed by Sema");
1530 if (
CGM.getTarget().getTriple().isSPIRV())
1532 Semantic->getAttrName()->getName(),
1534 if (
CGM.getTarget().getTriple().isDXIL())
1535 return emitDXILUserSemanticLoad(B,
Type,
Decl, Semantic, Index,
1543 "Load hasn't been implemented yet for this system semantic. FIXME");
1547 llvm::Value *Source,
const Twine &Name,
1548 unsigned BuiltInID) {
1549 auto *GV =
new llvm::GlobalVariable(
1550 M, Source->getType(),
false,
1551 llvm::GlobalValue::ExternalLinkage,
1552 nullptr, Name,
nullptr,
1553 llvm::GlobalVariable::GeneralDynamicTLSModel,
1556 GV->setVisibility(llvm::GlobalValue::HiddenVisibility);
1557 B.CreateStore(Source, GV);
1562 HLSLAppliedSemanticAttr *Semantic,
1564 llvm::Triple::EnvironmentType Stage, std::optional<unsigned> Index,
1565 SemanticSignatures &Signature) {
1567 case llvm::dxbc::PSV::SemanticKind::Position:
1568 assert(llvm::is_contained({llvm::Triple::Vertex, llvm::Triple::Hull,
1569 llvm::Triple::Domain, llvm::Triple::Geometry,
1570 llvm::Triple::Mesh},
1572 "SV_Position is in an unavailable stage and should have been "
1573 "diagnosed by Sema");
1574 assert(Stage != llvm::Triple::Hull && Stage != llvm::Triple::Domain &&
1575 Stage != llvm::Triple::Geometry && Stage != llvm::Triple::Mesh &&
1576 "FIXME: storing SV_Position is not yet implemented for this "
1578 if (
CGM.getTarget().getTriple().isDXIL()) {
1579 emitDXILUserSemanticStore(B, Source,
Decl, Semantic, Index, Signature);
1582 if (
CGM.getTarget().getTriple().isSPIRV()) {
1584 Semantic->getAttrName()->getName(),
1589 case llvm::dxbc::PSV::SemanticKind::Target:
1590 assert(Stage == llvm::Triple::Pixel &&
1591 "SV_Target is in an unavailable stage and should have been "
1592 "diagnosed by Sema");
1593 emitUserSemanticStore(B, Source,
Decl, Semantic, Index, Signature);
1600 "Store hasn't been implemented yet for this system semantic. FIXME");
1606 SemanticSignatures &Signature) {
1608 std::optional<unsigned> Index = Semantic->getSemanticIndex();
1610 llvm::hlsl::getSemanticKind(Semantic->getAttrName()->getName());
1611 const auto *ShaderAttr = FD->
getAttr<HLSLShaderAttr>();
1612 assert(ShaderAttr &&
"Entry point has no shader attribute");
1613 llvm::hlsl::SemanticInterpretation Interpretation =
1614 llvm::hlsl::getInterpretationKind(
SemanticKind, ShaderAttr->getType(),
1615 llvm::hlsl::IOType::In);
1616 assert(Interpretation != llvm::hlsl::SemanticInterpretation::Invalid &&
1617 "invalid semantic should have been diagnosed by Sema");
1618 if (Interpretation == llvm::hlsl::SemanticInterpretation::Arbitrary)
1619 return emitUserSemanticLoad(B, FD,
Type,
Decl, Semantic, Index, Signature);
1621 ShaderAttr->getType(), Index, Signature);
1626 llvm::Value *Source,
1628 HLSLAppliedSemanticAttr *Semantic,
1629 SemanticSignatures &Signature) {
1630 std::optional<unsigned> Index = Semantic->getSemanticIndex();
1632 llvm::hlsl::getSemanticKind(Semantic->getAttrName()->getName());
1633 const auto *ShaderAttr = FD->
getAttr<HLSLShaderAttr>();
1634 assert(ShaderAttr &&
"Entry point has no shader attribute");
1636 llvm::hlsl::SemanticInterpretation Interpretation =
1637 llvm::hlsl::getInterpretationKind(
SemanticKind, ShaderAttr->getType(),
1638 llvm::hlsl::IOType::Out);
1639 assert(Interpretation != llvm::hlsl::SemanticInterpretation::Invalid &&
1640 "invalid semantic should have been diagnosed by Sema");
1642 if (Interpretation == llvm::hlsl::SemanticInterpretation::Arbitrary)
1643 return emitUserSemanticStore(B, Source,
Decl, Semantic, Index, Signature);
1645 ShaderAttr->getType(), Index, Signature);
1648std::pair<llvm::Value *, specific_attr_iterator<HLSLAppliedSemanticAttr>>
1654 SemanticSignatures &Signature) {
1662 for (
unsigned I = 0; I < ST->getNumElements(); ++I) {
1663 auto [ChildValue, NextAttr] =
1665 AttrEnd, Signature);
1666 AttrBegin = NextAttr;
1672 return std::make_pair(
Aggregate, AttrBegin);
1677 IRBuilder<> &B,
const FunctionDecl *FD, llvm::Value *Source,
1681 SemanticSignatures &Signature) {
1689 RD =
Decl->getType()->getAsRecordDecl();
1695 for (
unsigned I = 0; I < ST->getNumElements(); ++I, ++
FieldDecl) {
1696 llvm::Value *Extract = B.CreateExtractValue(Source, I);
1698 AttrEnd, Signature);
1704std::pair<llvm::Value *, specific_attr_iterator<HLSLAppliedSemanticAttr>>
1710 SemanticSignatures &Signature) {
1711 assert(AttrBegin != AttrEnd);
1712 if (
Type->isStructTy())
1716 HLSLAppliedSemanticAttr *
Attr = *AttrBegin;
1718 return std::make_pair(
1724 IRBuilder<> &B,
const FunctionDecl *FD, llvm::Value *Source,
1728 SemanticSignatures &Signature) {
1729 assert(AttrBegin != AttrEnd);
1730 if (Source->getType()->isStructTy())
1734 HLSLAppliedSemanticAttr *
Attr = *AttrBegin;
1741 llvm::Function *Fn) {
1745 llvm::Module &M =
CGM.getModule();
1746 llvm::LLVMContext &Ctx = M.getContext();
1747 auto *EntryTy = llvm::FunctionType::get(llvm::Type::getVoidTy(Ctx),
false);
1749 Function::Create(EntryTy, Function::ExternalLinkage, FD->
getName(), &M);
1753 AttributeList NewAttrs = AttributeList::get(Ctx, AttributeList::FunctionIndex,
1754 Fn->getAttributes().getFnAttrs());
1755 EntryFn->setAttributes(NewAttrs);
1759 Fn->setLinkage(GlobalValue::InternalLinkage);
1761 BasicBlock *BB = BasicBlock::Create(Ctx,
"entry", EntryFn);
1766 if (
CGM.shouldEmitConvergenceTokens()) {
1767 assert(EntryFn->isConvergent());
1769 B.CreateIntrinsic(llvm::Intrinsic::experimental_convergence_entry, {});
1770 llvm::Value *bundleArgs[] = {I};
1771 OB.emplace_back(
"convergencectrl", bundleArgs);
1776 unsigned SRetOffset = 0;
1777 for (
const auto &Param : Fn->args()) {
1778 if (Param.hasStructRetAttr()) {
1780 llvm::Type *VarType = Param.getParamStructRetType();
1782 CGM.getLangOpts().EmitLogicalPointer
1785 OutputSemantic.push_back(std::make_pair(Var, VarType));
1786 Args.push_back(Var);
1791 llvm::Value *SemanticValue =
nullptr;
1793 if ([[maybe_unused]] HLSLParamModifierAttr *MA =
1794 PD->
getAttr<HLSLParamModifierAttr>()) {
1795 llvm_unreachable(
"Not handled yet");
1797 llvm::Type *ParamType =
nullptr;
1798 if (Param.hasByValAttr())
1799 ParamType = Param.getParamByValType();
1801 ParamType =
CGM.getTypes().ConvertType(PD->
getType());
1803 ParamType = Param.getType();
1809 SemanticValue =
Result.first;
1814 CGM.getLangOpts().EmitLogicalPointer
1817 B.CreateStore(SemanticValue, Var);
1818 SemanticValue = Var;
1822 assert(SemanticValue);
1823 Args.push_back(SemanticValue);
1826 CallInst *CI = B.CreateCall(FunctionCallee(Fn), Args, OB);
1827 CI->setCallingConv(Fn->getCallingConv());
1829 if (Fn->getReturnType() !=
CGM.VoidTy)
1831 OutputSemantic.push_back(std::make_pair(CI,
nullptr));
1833 for (
auto &SourcePair : OutputSemantic) {
1834 llvm::Value *Source = SourcePair.first;
1835 llvm::Type *ElementType = SourcePair.second;
1836 AllocaInst *AI = dyn_cast<AllocaInst>(Source);
1837 llvm::Value *SourceValue = AI ? B.CreateLoad(ElementType, Source) : Source;
1849 if (
const auto *RSAttr = dyn_cast<RootSignatureAttr>(
Attr)) {
1850 auto *RSDecl = RSAttr->getSignatureDecl();
1851 addRootSignatureMD(RSDecl->getVersion(), RSDecl->getRootElements(),
1856 addSemanticSignatureMD(InputSignature, OutputSignature, EntryFn, M);
1862 M.getNamedGlobal(CtorOrDtor ?
"llvm.global_ctors" :
"llvm.global_dtors");
1865 const auto *CA = dyn_cast<ConstantArray>(GV->getInitializer());
1872 for (
const auto &Ctor : CA->operands()) {
1878 "HLSL doesn't support setting priority for global ctors.");
1880 "HLSL doesn't support COMDat for global ctors.");
1886 llvm::Module &M =
CGM.getModule();
1895 for (
auto &F : M.functions()) {
1896 if (!F.hasFnAttribute(
"hlsl.shader"))
1899 Instruction *IP = &*F.getEntryBlock().begin();
1902 llvm::Value *bundleArgs[] = {
Token};
1903 OB.emplace_back(
"convergencectrl", bundleArgs);
1904 IP =
Token->getNextNode();
1907 for (
auto *Fn : CtorFns) {
1908 auto CI = B.CreateCall(FunctionCallee(Fn), {}, OB);
1909 CI->setCallingConv(Fn->getCallingConv());
1913 B.SetInsertPoint(F.back().getTerminator());
1914 for (
auto *Fn : DtorFns) {
1915 auto CI = B.CreateCall(FunctionCallee(Fn), {}, OB);
1916 CI->setCallingConv(Fn->getCallingConv());
1922 Triple
T(M.getTargetTriple());
1923 if (
T.getEnvironment() != Triple::EnvironmentType::Library) {
1924 if (
auto *GV = M.getNamedGlobal(
"llvm.global_ctors"))
1925 GV->eraseFromParent();
1926 if (
auto *GV = M.getNamedGlobal(
"llvm.global_dtors"))
1927 GV->eraseFromParent();
1932 Intrinsic::ID IntrID,
1936 llvm::Function *InitResFunc =
1937 llvm::Function::Create(llvm::FunctionType::get(CGM.
VoidTy,
false),
1938 llvm::GlobalValue::InternalLinkage,
1939 "_init_buffer_" + GV->getName(), CGM.
getModule());
1940 InitResFunc->addFnAttr(llvm::Attribute::AlwaysInline);
1942 llvm::BasicBlock *EntryBB =
1943 llvm::BasicBlock::Create(Ctx,
"entry", InitResFunc);
1945 const DataLayout &DL = CGM.
getModule().getDataLayout();
1946 Builder.SetInsertPoint(EntryBB);
1949 llvm::Type *HandleTy = GV->getValueType();
1950 assert(HandleTy->isTargetExtTy() &&
"unexpected type of the buffer global");
1952 llvm::Value *CreateHandle = Builder.CreateIntrinsic(
1953 HandleTy, IntrID, Args,
nullptr,
1954 Twine(GV->getName()).concat(
"_h"));
1956 Builder.CreateAlignedStore(CreateHandle, GV, GV->getPointerAlignment(DL));
1957 Builder.CreateRetVoid();
1962void CGHLSLRuntime::initializeBufferFromBinding(
const HLSLBufferDecl *BufDecl,
1963 llvm::GlobalVariable *GV) {
1964 ResourceBindingAttrs Binding(BufDecl);
1966 "cbuffer/tbuffer should always have resource binding attribute");
1968 auto *Index = llvm::ConstantInt::get(
CGM.IntTy, 0);
1969 auto *RangeSize = llvm::ConstantInt::get(
CGM.IntTy, 1);
1970 auto *Space = llvm::ConstantInt::get(
CGM.IntTy, Binding.
getSpace());
1975 llvm::Intrinsic::ID IntrinsicID =
1976 CGM.getHLSLRuntime().getCreateHandleFromBindingIntrinsic();
1977 auto *RegSlot = llvm::ConstantInt::get(
CGM.IntTy, Binding.
getSlot());
1978 SmallVector<Value *> Args{Space, RegSlot, RangeSize, Index, Name};
1982 llvm::Intrinsic::ID IntrinsicID =
1983 CGM.getHLSLRuntime().getCreateHandleFromImplicitBindingIntrinsic();
1986 SmallVector<Value *> Args{OrderID, Space, RangeSize, Index, Name};
1992 llvm::GlobalVariable *GV) {
1993 if (
auto Attr = VD->
getAttr<HLSLVkExtBuiltinInputAttr>())
1995 if (
auto Attr = VD->
getAttr<HLSLVkExtBuiltinOutputAttr>())
2000 if (!
CGM.shouldEmitConvergenceTokens())
2004 for (
auto I = BB.begin(); I != E; ++I) {
2005 auto *II = dyn_cast<llvm::IntrinsicInst>(&*I);
2006 if (II && llvm::isConvergenceControlIntrinsic(II->getIntrinsicID())) {
2010 llvm_unreachable(
"Convergence token should have been emitted.");
2047 for (
auto *OVE : Visitor.
OVEs) {
2050 if (OpaqueValueMappingData::shouldBindAsLValue(OVE)) {
2052 OpaqueValueMappingData::bind(CGF, OVE, LV);
2055 OpaqueValueMappingData::bind(CGF, OVE, RV);
2064 "expected resource array subscript expression");
2069 const VarDecl *ArrayDecl = dyn_cast_or_null<VarDecl>(
2073 return std::nullopt;
2079 "expected array of resource classes");
2085 Value *Index =
nullptr;
2087 while (ASE !=
nullptr) {
2089 if (
const auto *ArrayTy =
2091 Value *Multiplier = llvm::ConstantInt::get(
2093 SubIndex = CGF.
Builder.CreateMul(SubIndex, Multiplier);
2095 Index = Index ? CGF.
Builder.CreateAdd(Index, SubIndex) : SubIndex;
2103 "resource array must have a binding attribute");
2124 llvm::Value *Range = llvm::ConstantInt::getSigned(
2125 CGM.IntTy, getTotalArraySize(AST, ResArrayTy));
2129 if (ResultTy == ResourceTy) {
2131 CXXMethodDecl *CreateMethod = lookupResourceInitMethodAndSetupArgs(
2133 ArrayDecl->
getName(), Binding, Args);
2135 if (!CreateMethod) {
2140 "create method lookup should always succeed for built-in resource "
2142 return std::nullopt;
2145 callResourceInitMethod(CGF, CreateMethod, Args, ValueSlot.getAddress());
2152 std::optional<llvm::Value *> EndIndex = initializeResourceArrayFromGlobal(
2154 ArrayDecl->
getName(), Binding, {llvm::ConstantInt::get(CGM.IntTy, 0)});
2156 return std::nullopt;
2162bool CGHLSLRuntime::initializeGlobalResourceArray(
CodeGenFunction &CGF,
2168 "expected global non-static resource array");
2174 "resource array must have a binding attribute");
2179 const auto *ResArrayTy =
2183 int Size = getTotalArraySize(AST, ResArrayTy);
2184 llvm::Value *
Zero = llvm::ConstantInt::get(
CGM.
IntTy, 0);
2185 llvm::Value *Range = llvm::ConstantInt::get(
CGM.
IntTy, Size);
2188 std::optional<llvm::Value *> EndIndex = initializeResourceArrayFromGlobal(
2190 ArrayDecl->
getName(), Binding, {Zero});
2191 return EndIndex.has_value();
2200 "expected resource array");
2205 dyn_cast_or_null<VarDecl>(getArrayDecl(CGF.
CGM.
getContext(), E));
2210 return initializeGlobalResourceArray(CGF, ArrayDecl, DestSlot);
2217std::optional<LValue>
2221 "expected resource array declaration");
2225 return std::nullopt;
2229 if (initializeGlobalResourceArray(CGF, ArrayDecl, TmpArraySlot))
2232 return std::nullopt;
2240 "expected cbuffer matrix");
2251 HLSLBufferCopyEmitter(CGF, DestAlloca, SrcAddr).emitCopy(MatQualTy);
2257 llvm::function_ref<llvm::Value *(
bool Promote)> EmitIdxAfterBase) {
2261 llvm::Type *LayoutTy =
2263 uint64_t LayoutSizeInBits =
2264 CGM.getDataLayout().getTypeSizeInBits(LayoutTy).getFixedValue();
2267 if (RowAlignedSize > ElementSize) {
2268 llvm::Type *Padding =
CGM.getTargetCodeGenInfo().getHLSLPadding(
2269 CGM, RowAlignedSize - ElementSize);
2270 assert(Padding &&
"No padding type for target?");
2271 LayoutTy = llvm::StructType::get(CGF.
getLLVMContext(), {LayoutTy, Padding},
2278 if (LayoutTy == OrigTy)
2279 return std::nullopt;
2288 llvm::Value *Idx = EmitIdxAfterBase(
true);
2289 Indices.push_back(Idx);
2290 Indices.push_back(llvm::ConstantInt::get(CGF.
Int32Ty, 0));
2296 assert(CE->
getCastKind() == CastKind::CK_ArrayToPointerDecay);
2300 LayoutTy = llvm::ArrayType::get(
2304 LayoutTy,
Addr.emitRawPointer(CGF), Indices,
"cbufferidx"));
2313 Indices,
"cbufferidx");
2318std::optional<LValue>
2323 "expected resource member expression");
2326 findAssociatedResourceDeclForStruct(CGF.
CGM.
getContext(), ME);
2328 return std::nullopt;
2334 GlobalVariable *ResGV =
2336 const DataLayout &DL =
CGM.getDataLayout();
2337 llvm::Type *Ty = ResGV->getValueType();
2350 "expected expression in HLSL constant address space");
2353 "direct accesses to resource types should be handled separately");
2365 return HLSLBufferCopyEmitter(CGF, DstPtr, SrcPtr).emitCopy(Ty);
2371 const VarDecl *VD = findStructResourceParentDeclAndBuildName(E, NameBuilder);
2372 AssociatedResourcesList AssociatedResources(VD, NameBuilder.
getName());
2376 const VarDecl *ResDecl = AssociatedResources.getNextResource();
2377 assert(ResDecl &&
"associated resource declaration not found");
2380 [[maybe_unused]] llvm::Type *DestType =
2381 ResSlot.getAddress().getElementType();
2382 [[maybe_unused]] llvm::Type *SrcConvertedType =
2383 CGM.getTypes().ConvertTypeForMem(ResDecl->
getType());
2384 assert(DestType == SrcConvertedType &&
"resource slot type mismatch");
2387 copyGlobalResource(CGF, ResDecl, ResSlot);
2389 initializeGlobalResourceArray(CGF, ResDecl, ResSlot);
2393 HLSLBufferCopyEmitter(CGF, DstPtr, SrcPtr).emitCopy(Ty, EmitResFn);
2394 assert(AssociatedResources.getNextResource() ==
nullptr &&
2395 "expected all associated resources to be processed");
2404 assert(Field &&
"Unexpected access into HLSL buffer");
2409 QualType RecType =
CGM.getContext().getCanonicalTagType(Rec);
2420 CGM.getTypes().getCGRecordLayout(Rec).getLLVMFieldNo(Field);
2421 assert(FieldIdx < LayoutTy->getNumElements() &&
2422 "Layout struct is smaller than member struct");
2423 unsigned Skipped = 0;
2424 for (
unsigned I = 0; I <= FieldIdx;) {
2425 llvm::Type *ElementTy = LayoutTy->getElementType(I + Skipped);
2431 FieldIdx += Skipped;
2432 assert(FieldIdx < LayoutTy->getNumElements() &&
"Access out of bounds");
2436 QualType FieldType = Field->getType();
2437 llvm::Type *FieldLLVMTy =
CGM.getTypes().ConvertTypeForMem(FieldType);
2442 ? CGF.
Builder.CreateStructuredGEP(
2443 LayoutTy,
Base.getPointer(CGF),
2444 llvm::ConstantInt::get(
CGM.IntTy, FieldIdx))
2446 FieldIdx, Field->getName());
2451 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
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)
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)
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::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)
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)
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 CodeGenModule & CGM
bool emitBufferCopy(CodeGenFunction &CGF, const Expr *E, const LValue &SrcLV, AggValueSlot &DestSlot)
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)
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)
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)
void addBuffer(const HLSLBufferDecl *D)
void generateGlobalCtorDtorCalls()
bool emitGlobalResourceArray(CodeGenFunction &CGF, const Expr *E, 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, SemanticSignatures &Signature)
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)
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.
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.
__packed_splat4 __packed_splat2 __packed_splat8 __packed_splat4 __packed_splat2 uint8_t
__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