31#include "llvm/ADT/DenseMap.h"
32#include "llvm/ADT/ScopeExit.h"
33#include "llvm/ADT/SmallString.h"
34#include "llvm/ADT/SmallVector.h"
35#include "llvm/Frontend/HLSL/RootSignatureMetadata.h"
36#include "llvm/IR/Constants.h"
37#include "llvm/IR/DerivedTypes.h"
38#include "llvm/IR/GlobalVariable.h"
39#include "llvm/IR/IntrinsicInst.h"
40#include "llvm/IR/LLVMContext.h"
41#include "llvm/IR/Metadata.h"
42#include "llvm/IR/Module.h"
43#include "llvm/IR/Type.h"
44#include "llvm/IR/Value.h"
45#include "llvm/Support/Alignment.h"
46#include "llvm/Support/ErrorHandling.h"
47#include "llvm/Support/FormatVariadic.h"
56using llvm::hlsl::CBufferRowSizeInBytes;
60void addDxilValVersion(StringRef ValVersionStr, llvm::Module &M) {
64 if (Version.tryParse(ValVersionStr) || Version.getBuild() ||
65 Version.getSubminor() || !Version.getMinor()) {
69 uint64_t Major = Version.getMajor();
70 uint64_t Minor = *Version.getMinor();
72 auto &Ctx = M.getContext();
73 IRBuilder<> B(M.getContext());
74 MDNode *Val = MDNode::get(Ctx, {ConstantAsMetadata::get(B.getInt32(Major)),
75 ConstantAsMetadata::get(B.getInt32(Minor))});
76 StringRef DXILValKey =
"dx.valver";
77 auto *DXILValMD = M.getOrInsertNamedMetadata(DXILValKey);
78 DXILValMD->addOperand(Val);
81void addRootSignatureMD(llvm::dxbc::RootSignatureVersion RootSigVer,
83 llvm::Function *Fn, llvm::Module &M) {
84 auto &Ctx = M.getContext();
86 llvm::hlsl::rootsig::MetadataBuilder RSBuilder(Ctx, Elements);
87 MDNode *RootSignature = RSBuilder.BuildRootSignature();
89 ConstantAsMetadata *Version = ConstantAsMetadata::get(ConstantInt::get(
90 llvm::Type::getInt32Ty(Ctx), llvm::to_underlying(RootSigVer)));
91 ValueAsMetadata *EntryFunc =
Fn ? ValueAsMetadata::get(Fn) :
nullptr;
92 MDNode *MDVals = MDNode::get(Ctx, {EntryFunc, RootSignature, Version});
94 StringRef RootSignatureValKey =
"dx.rootsignatures";
95 auto *RootSignatureValMD = M.getOrInsertNamedMetadata(RootSignatureValKey);
96 RootSignatureValMD->addOperand(MDVals);
103 return DRE->getDecl();
109 const Expr *E =
nullptr;
110 while (ASE !=
nullptr) {
114 ASE = dyn_cast<ArraySubscriptExpr>(E);
116 return getArrayDecl(E);
122 assert(Ty->
isArrayType() &&
"expected array type");
128static Value *buildNameForResource(llvm::StringRef BaseName,
137 for (
auto *Method :
Record->methods()) {
138 if (Method->getStorageClass() == SC && Method->getName() == Name)
148 assert(Binding.
hasBinding() &&
"at least one binding attribute expected");
152 Value *NameStr = buildNameForResource(Name, CGM);
157 auto *RegSlot = llvm::ConstantInt::get(CGM.
IntTy, Binding.
getSlot());
160 ?
"__createFromBindingWithImplicitCounter"
161 :
"__createFromBinding";
162 CreateMethod = lookupMethod(ResourceDecl, Name,
SC_Static);
169 ?
"__createFromImplicitBindingWithImplicitCounter"
170 :
"__createFromImplicitBinding";
171 CreateMethod = lookupMethod(ResourceDecl, Name,
SC_Static);
179 auto *CounterOrderID = llvm::ConstantInt::get(CGM.
IntTy, CounterBinding);
196 CGF.
EmitCall(FnInfo, Callee, ReturnValue, Args,
nullptr);
204static std::optional<llvm::Value *> initializeLocalResourceArray(
207 llvm::Value *Range, llvm::Value *StartIndex, StringRef ResourceName,
212 llvm::IntegerType *IntTy = CGF.
CGM.
IntTy;
213 llvm::Value *Index = StartIndex;
214 llvm::Value *One = llvm::ConstantInt::get(IntTy, 1);
222 GEPIndices.push_back(llvm::ConstantInt::get(IntTy, 0));
227 for (uint64_t I = 0; I < ArraySize; I++) {
229 Index = CGF.
Builder.CreateAdd(Index, One);
230 GEPIndices.back() = llvm::ConstantInt::get(IntTy, I);
232 std::optional<llvm::Value *> MaybeIndex = initializeLocalResourceArray(
233 CGF, ResourceDecl, SubArrayTy, ValueSlot, Range, Index, ResourceName,
234 Binding, GEPIndices, ArraySubsExprLoc);
248 for (uint64_t I = 0; I < ArraySize; I++) {
250 Index = CGF.
Builder.CreateAdd(Index, One);
251 GEPIndices.back() = llvm::ConstantInt::get(IntTy, I);
257 CXXMethodDecl *CreateMethod = lookupResourceInitMethodAndSetupArgs(
258 CGF.
CGM, ResourceDecl, Range, Index, ResourceName, Binding, Args);
266 callResourceInitMethod(CGF, CreateMethod, Args, ReturnAddress);
276 assert(T->isHLSLSpecificType() &&
"Not an HLSL specific type!");
279 if (llvm::Type *TargetTy =
283 llvm_unreachable(
"Generic handling of HLSL types is not supported.");
286llvm::Triple::ArchType CGHLSLRuntime::getArch() {
292void CGHLSLRuntime::emitBufferGlobalsAndMetadata(
298 llvm::Type *BufType = BufGV->getValueType();
303 size_t OffsetIdx = 0;
313 VarDecl *VD = dyn_cast<VarDecl>(D);
329 DeclsWithOffset.emplace_back(VD, OffsetInfo[OffsetIdx++]);
332 if (!OffsetInfo.
empty())
333 llvm::stable_sort(DeclsWithOffset, [](
const auto &LHS,
const auto &RHS) {
338 SmallVector<llvm::Metadata *> BufGlobals;
339 BufGlobals.reserve(DeclsWithOffset.size() + 1);
340 BufGlobals.push_back(ValueAsMetadata::get(BufGV));
342 auto ElemIt = LayoutStruct->element_begin();
343 for (
auto &[VD, _] : DeclsWithOffset) {
347 assert(ElemIt != LayoutStruct->element_end() &&
348 "number of elements in layout struct does not match");
349 llvm::Type *LayoutType = *ElemIt++;
351 GlobalVariable *ElemGV =
353 BufGlobals.push_back(ValueAsMetadata::get(ElemGV));
355 assert(ElemIt == LayoutStruct->element_end() &&
356 "number of elements in layout struct does not match");
360 .getOrInsertNamedMetadata(
"hlsl.cbs")
361 ->addOperand(MDNode::get(Ctx, BufGlobals));
365static const clang::HLSLAttributedResourceType *
370 HLSLAttributedResourceType::Attributes(ResourceClass::CBuffer));
385 VarDecl *VD = dyn_cast<VarDecl>(D);
396 if (
auto *POA = dyn_cast<HLSLPackOffsetAttr>(
Attr)) {
397 Offset = POA->getOffsetInBytes();
400 auto *RBA = dyn_cast<HLSLResourceBindingAttr>(
Attr);
402 RBA->getRegisterType() == HLSLResourceBindingAttr::RegisterType::C) {
403 Offset = RBA->getSlotNumber() * CBufferRowSizeInBytes;
407 Result.Offsets.push_back(Offset);
415 assert(BufDecl->
isCBuffer() &&
"tbuffer codegen is not supported yet");
418 const clang::HLSLAttributedResourceType *ResHandleTy =
422 if (ResHandleTy->getContainedType()->getAsCXXRecordDecl()->isEmpty())
428 llvm::GlobalVariable *BufGV =
new GlobalVariable(
430 GlobalValue::LinkageTypes::ExternalLinkage, PoisonValue::get(LayoutTy),
431 llvm::formatv(
"{0}{1}", BufDecl->
getName(),
433 GlobalValue::NotThreadLocal);
434 CGM.
getModule().insertGlobalVariable(BufGV);
437 emitBufferGlobalsAndMetadata(BufDecl, BufGV, OffsetInfo);
440 initializeBufferFromBinding(BufDecl, BufGV);
446 Triple T(M.getTargetTriple());
449 if (T.getEnvironment() != Triple::EnvironmentType::RootSignature)
452 addRootSignatureMD(SignatureDecl->
getVersion(),
458 const auto Entry = LayoutTypes.find(StructType);
459 if (Entry != LayoutTypes.end())
460 return Entry->getSecond();
465 llvm::StructType *LayoutTy) {
467 "layout type for this struct already exist");
468 LayoutTypes[StructType] = LayoutTy;
476 Triple T(M.getTargetTriple());
477 if (T.getArch() == Triple::ArchType::dxil)
478 addDxilValVersion(TargetOpts.DxilValidatorVersion, M);
479 if (CodeGenOpts.ResMayAlias)
480 M.setModuleFlag(llvm::Module::ModFlagBehavior::Error,
"dx.resmayalias", 1);
481 if (CodeGenOpts.AllResourcesBound)
482 M.setModuleFlag(llvm::Module::ModFlagBehavior::Error,
483 "dx.allresourcesbound", 1);
484 if (CodeGenOpts.OptimizationLevel == 0)
485 M.addModuleFlag(llvm::Module::ModFlagBehavior::Override,
486 "dx.disable_optimizations", 1);
491 if (LangOpts.NativeHalfType)
492 M.setModuleFlag(llvm::Module::ModFlagBehavior::Error,
"dx.nativelowprec",
500 const auto *ShaderAttr = FD->
getAttr<HLSLShaderAttr>();
501 assert(ShaderAttr &&
"All entry functions must have a HLSLShaderAttr");
502 const StringRef ShaderAttrKindStr =
"hlsl.shader";
503 Fn->addFnAttr(ShaderAttrKindStr,
504 llvm::Triple::getEnvironmentTypeName(ShaderAttr->getType()));
505 if (HLSLNumThreadsAttr *NumThreadsAttr = FD->
getAttr<HLSLNumThreadsAttr>()) {
506 const StringRef NumThreadsKindStr =
"hlsl.numthreads";
507 std::string NumThreadsStr =
508 formatv(
"{0},{1},{2}", NumThreadsAttr->getX(), NumThreadsAttr->getY(),
509 NumThreadsAttr->getZ());
510 Fn->addFnAttr(NumThreadsKindStr, NumThreadsStr);
512 if (HLSLWaveSizeAttr *WaveSizeAttr = FD->
getAttr<HLSLWaveSizeAttr>()) {
513 const StringRef WaveSizeKindStr =
"hlsl.wavesize";
514 std::string WaveSizeStr =
515 formatv(
"{0},{1},{2}", WaveSizeAttr->getMin(), WaveSizeAttr->getMax(),
516 WaveSizeAttr->getPreferred());
517 Fn->addFnAttr(WaveSizeKindStr, WaveSizeStr);
524 Fn->addFnAttr(llvm::Attribute::NoInline);
526 if (CGM.
getLangOpts().HLSLSpvEnableMaximalReconvergence) {
527 Fn->addFnAttr(
"enable-maximal-reconvergence",
"true");
532 if (
const auto *VT = dyn_cast<FixedVectorType>(Ty)) {
533 Value *Result = PoisonValue::get(Ty);
534 for (
unsigned I = 0; I < VT->getNumElements(); ++I) {
535 Value *Elt = B.CreateCall(F, {B.getInt32(I)});
536 Result = B.CreateInsertElement(Result, Elt, I);
540 return B.CreateCall(F, {B.getInt32(0)});
545 LLVMContext &Ctx = GV->getContext();
546 IRBuilder<> B(GV->getContext());
547 MDNode *Operands = MDNode::get(
549 {ConstantAsMetadata::get(B.getInt32( 11)),
550 ConstantAsMetadata::get(B.getInt32(BuiltIn))});
551 MDNode *Decoration = MDNode::get(Ctx, {Operands});
552 GV->addMetadata(
"spirv.Decorations", *Decoration);
556 LLVMContext &Ctx = GV->getContext();
557 IRBuilder<> B(GV->getContext());
559 MDNode::get(Ctx, {ConstantAsMetadata::get(B.getInt32( 30)),
560 ConstantAsMetadata::get(B.getInt32(Location))});
561 MDNode *Decoration = MDNode::get(Ctx, {Operands});
562 GV->addMetadata(
"spirv.Decorations", *Decoration);
566 llvm::Type *Ty,
const Twine &Name,
567 unsigned BuiltInID) {
568 auto *GV =
new llvm::GlobalVariable(
569 M, Ty,
true, llvm::GlobalValue::ExternalLinkage,
570 nullptr, Name,
nullptr,
571 llvm::GlobalVariable::GeneralDynamicTLSModel,
574 GV->setVisibility(llvm::GlobalValue::HiddenVisibility);
575 return B.CreateLoad(Ty, GV);
579 llvm::Type *Ty,
unsigned Location,
581 auto *GV =
new llvm::GlobalVariable(
582 M, Ty,
true, llvm::GlobalValue::ExternalLinkage,
583 nullptr, Name,
nullptr,
584 llvm::GlobalVariable::GeneralDynamicTLSModel,
586 GV->setVisibility(llvm::GlobalValue::HiddenVisibility);
588 return B.CreateLoad(Ty, GV);
591llvm::Value *CGHLSLRuntime::emitSPIRVUserSemanticLoad(
592 llvm::IRBuilder<> &B, llvm::Type *
Type,
const clang::DeclaratorDecl *
Decl,
593 HLSLAppliedSemanticAttr *Semantic, std::optional<unsigned> Index) {
594 Twine BaseName = Twine(Semantic->getAttrName()->getName());
595 Twine VariableName = BaseName.concat(Twine(Index.value_or(0)));
597 unsigned Location = SPIRVLastAssignedInputSemanticLocation;
598 if (
auto *L =
Decl->getAttr<HLSLVkLocationAttr>())
599 Location = L->getLocation();
603 llvm::ArrayType *AT = dyn_cast<llvm::ArrayType>(
Type);
604 unsigned ElementCount = AT ? AT->getNumElements() : 1;
605 SPIRVLastAssignedInputSemanticLocation += ElementCount;
612 llvm::Value *Source,
unsigned Location,
614 auto *GV =
new llvm::GlobalVariable(
615 M, Source->getType(),
false,
616 llvm::GlobalValue::ExternalLinkage,
617 nullptr, Name,
nullptr,
618 llvm::GlobalVariable::GeneralDynamicTLSModel,
620 GV->setVisibility(llvm::GlobalValue::HiddenVisibility);
622 B.CreateStore(Source, GV);
625void CGHLSLRuntime::emitSPIRVUserSemanticStore(
626 llvm::IRBuilder<> &B, llvm::Value *Source,
627 const clang::DeclaratorDecl *
Decl, HLSLAppliedSemanticAttr *Semantic,
628 std::optional<unsigned> Index) {
629 Twine BaseName = Twine(Semantic->getAttrName()->getName());
630 Twine VariableName = BaseName.concat(Twine(Index.value_or(0)));
632 unsigned Location = SPIRVLastAssignedOutputSemanticLocation;
633 if (
auto *L =
Decl->getAttr<HLSLVkLocationAttr>())
634 Location = L->getLocation();
638 llvm::ArrayType *AT = dyn_cast<llvm::ArrayType>(Source->getType());
639 unsigned ElementCount = AT ? AT->getNumElements() : 1;
640 SPIRVLastAssignedOutputSemanticLocation += ElementCount;
646CGHLSLRuntime::emitDXILUserSemanticLoad(llvm::IRBuilder<> &B, llvm::Type *
Type,
647 HLSLAppliedSemanticAttr *Semantic,
648 std::optional<unsigned> Index) {
649 Twine BaseName = Twine(Semantic->getAttrName()->getName());
650 Twine VariableName = BaseName.concat(Twine(Index.value_or(0)));
655 SmallVector<Value *> Args{B.getInt32(4), B.getInt32(0), B.getInt32(0),
657 llvm::PoisonValue::get(B.getInt32Ty())};
659 llvm::Intrinsic::ID IntrinsicID = llvm::Intrinsic::dx_load_input;
660 llvm::Value *
Value = B.CreateIntrinsic(
Type, IntrinsicID, Args,
661 nullptr, VariableName);
665void CGHLSLRuntime::emitDXILUserSemanticStore(llvm::IRBuilder<> &B,
667 HLSLAppliedSemanticAttr *Semantic,
668 std::optional<unsigned> Index) {
671 SmallVector<Value *> Args{B.getInt32(4),
675 llvm::PoisonValue::get(B.getInt32Ty()),
678 llvm::Intrinsic::ID IntrinsicID = llvm::Intrinsic::dx_store_output;
679 B.CreateIntrinsic(CGM.
VoidTy, IntrinsicID, Args,
nullptr);
682llvm::Value *CGHLSLRuntime::emitUserSemanticLoad(
683 IRBuilder<> &B, llvm::Type *
Type,
const clang::DeclaratorDecl *
Decl,
684 HLSLAppliedSemanticAttr *Semantic, std::optional<unsigned> Index) {
686 return emitSPIRVUserSemanticLoad(B,
Type,
Decl, Semantic, Index);
689 return emitDXILUserSemanticLoad(B,
Type, Semantic, Index);
691 llvm_unreachable(
"Unsupported target for user-semantic load.");
694void CGHLSLRuntime::emitUserSemanticStore(IRBuilder<> &B, llvm::Value *Source,
695 const clang::DeclaratorDecl *
Decl,
696 HLSLAppliedSemanticAttr *Semantic,
697 std::optional<unsigned> Index) {
699 return emitSPIRVUserSemanticStore(B, Source,
Decl, Semantic, Index);
702 return emitDXILUserSemanticStore(B, Source, Semantic, Index);
704 llvm_unreachable(
"Unsupported target for user-semantic load.");
710 std::optional<unsigned> Index) {
712 std::string SemanticName = Semantic->getAttrName()->getName().upper();
713 if (SemanticName ==
"SV_GROUPINDEX") {
714 llvm::Function *GroupIndex =
715 CGM.
getIntrinsic(getFlattenedThreadIdInGroupIntrinsic());
716 return B.CreateCall(FunctionCallee(GroupIndex));
719 if (SemanticName ==
"SV_DISPATCHTHREADID") {
720 llvm::Intrinsic::ID IntrinID = getThreadIdIntrinsic();
721 llvm::Function *ThreadIDIntrinsic =
722 llvm::Intrinsic::isOverloaded(IntrinID)
728 if (SemanticName ==
"SV_GROUPTHREADID") {
729 llvm::Intrinsic::ID IntrinID = getGroupThreadIdIntrinsic();
730 llvm::Function *GroupThreadIDIntrinsic =
731 llvm::Intrinsic::isOverloaded(IntrinID)
737 if (SemanticName ==
"SV_GROUPID") {
738 llvm::Intrinsic::ID IntrinID = getGroupIdIntrinsic();
739 llvm::Function *GroupIDIntrinsic =
740 llvm::Intrinsic::isOverloaded(IntrinID)
746 const auto *ShaderAttr = FD->
getAttr<HLSLShaderAttr>();
747 assert(ShaderAttr &&
"Entry point has no shader attribute");
748 llvm::Triple::EnvironmentType ST = ShaderAttr->getType();
750 if (SemanticName ==
"SV_POSITION") {
751 if (ST == Triple::EnvironmentType::Pixel) {
754 Semantic->getAttrName()->getName(),
757 return emitDXILUserSemanticLoad(B,
Type, Semantic, Index);
760 if (ST == Triple::EnvironmentType::Vertex) {
761 return emitUserSemanticLoad(B,
Type,
Decl, Semantic, Index);
765 if (SemanticName ==
"SV_VERTEXID") {
766 if (ST == Triple::EnvironmentType::Vertex) {
769 Semantic->getAttrName()->getName(),
772 return emitDXILUserSemanticLoad(B,
Type, Semantic, Index);
777 "Load hasn't been implemented yet for this system semantic. FIXME");
781 llvm::Value *Source,
const Twine &Name,
782 unsigned BuiltInID) {
783 auto *GV =
new llvm::GlobalVariable(
784 M, Source->getType(),
false,
785 llvm::GlobalValue::ExternalLinkage,
786 nullptr, Name,
nullptr,
787 llvm::GlobalVariable::GeneralDynamicTLSModel,
790 GV->setVisibility(llvm::GlobalValue::HiddenVisibility);
791 B.CreateStore(Source, GV);
796 HLSLAppliedSemanticAttr *Semantic,
797 std::optional<unsigned> Index) {
799 std::string SemanticName = Semantic->getAttrName()->getName().upper();
800 if (SemanticName ==
"SV_POSITION") {
802 emitDXILUserSemanticStore(B, Source, Semantic, Index);
808 Semantic->getAttrName()->getName(),
814 if (SemanticName ==
"SV_TARGET") {
815 emitUserSemanticStore(B, Source,
Decl, Semantic, Index);
820 "Store hasn't been implemented yet for this system semantic. FIXME");
827 std::optional<unsigned> Index = Semantic->getSemanticIndex();
828 if (Semantic->getAttrName()->getName().starts_with_insensitive(
"SV_"))
830 return emitUserSemanticLoad(B,
Type,
Decl, Semantic, Index);
834 IRBuilder<> &B,
const FunctionDecl *FD, llvm::Value *Source,
836 std::optional<unsigned> Index = Semantic->getSemanticIndex();
837 if (Semantic->getAttrName()->getName().starts_with_insensitive(
"SV_"))
840 emitUserSemanticStore(B, Source,
Decl, Semantic, Index);
843std::pair<llvm::Value *, specific_attr_iterator<HLSLAppliedSemanticAttr>>
856 for (
unsigned I = 0; I < ST->getNumElements(); ++I) {
858 B, FD, ST->getElementType(I), *
FieldDecl, AttrBegin, AttrEnd);
859 AttrBegin = NextAttr;
865 return std::make_pair(
Aggregate, AttrBegin);
870 IRBuilder<> &B,
const FunctionDecl *FD, llvm::Value *Source,
881 RD =
Decl->getType()->getAsRecordDecl();
887 for (
unsigned I = 0; I < ST->getNumElements(); ++I, ++
FieldDecl) {
888 llvm::Value *Extract = B.CreateExtractValue(Source, I);
896std::pair<llvm::Value *, specific_attr_iterator<HLSLAppliedSemanticAttr>>
902 assert(AttrBegin != AttrEnd);
903 if (
Type->isStructTy())
906 HLSLAppliedSemanticAttr *
Attr = *AttrBegin;
914 IRBuilder<> &B,
const FunctionDecl *FD, llvm::Value *Source,
918 assert(AttrBegin != AttrEnd);
919 if (Source->getType()->isStructTy())
922 HLSLAppliedSemanticAttr *
Attr = *AttrBegin;
929 llvm::Function *Fn) {
931 llvm::LLVMContext &Ctx = M.getContext();
932 auto *EntryTy = llvm::FunctionType::get(llvm::Type::getVoidTy(Ctx),
false);
934 Function::Create(EntryTy, Function::ExternalLinkage, FD->
getName(), &M);
938 AttributeList NewAttrs = AttributeList::get(Ctx, AttributeList::FunctionIndex,
939 Fn->getAttributes().getFnAttrs());
940 EntryFn->setAttributes(NewAttrs);
944 Fn->setLinkage(GlobalValue::InternalLinkage);
946 BasicBlock *BB = BasicBlock::Create(Ctx,
"entry", EntryFn);
952 assert(EntryFn->isConvergent());
954 B.CreateIntrinsic(llvm::Intrinsic::experimental_convergence_entry, {});
955 llvm::Value *bundleArgs[] = {I};
956 OB.emplace_back(
"convergencectrl", bundleArgs);
959 llvm::DenseMap<const DeclaratorDecl *, std::pair<llvm::Value *, llvm::Type *>>
962 unsigned SRetOffset = 0;
963 for (
const auto &Param : Fn->args()) {
964 if (Param.hasStructRetAttr()) {
966 llvm::Type *VarType = Param.getParamStructRetType();
967 llvm::Value *Var = B.CreateAlloca(VarType);
968 OutputSemantic.try_emplace(FD, std::make_pair(Var, VarType));
974 llvm::Value *SemanticValue =
nullptr;
976 if ([[maybe_unused]] HLSLParamModifierAttr *MA =
977 PD->
getAttr<HLSLParamModifierAttr>()) {
978 llvm_unreachable(
"Not handled yet");
980 llvm::Type *ParamType =
981 Param.hasByValAttr() ? Param.getParamByValType() : Param.getType();
986 SemanticValue =
Result.first;
989 if (Param.hasByValAttr()) {
990 llvm::Value *Var = B.CreateAlloca(Param.getParamByValType());
991 B.CreateStore(SemanticValue, Var);
996 assert(SemanticValue);
997 Args.push_back(SemanticValue);
1000 CallInst *CI = B.CreateCall(FunctionCallee(Fn), Args, OB);
1001 CI->setCallingConv(Fn->getCallingConv());
1003 if (Fn->getReturnType() != CGM.
VoidTy)
1005 OutputSemantic.try_emplace(FD, std::make_pair(CI,
nullptr));
1007 for (
auto &[
Decl, SourcePair] : OutputSemantic) {
1008 llvm::Value *Source = SourcePair.first;
1009 llvm::Type *ElementType = SourcePair.second;
1010 AllocaInst *AI = dyn_cast<AllocaInst>(Source);
1011 llvm::Value *SourceValue = AI ? B.CreateLoad(ElementType, Source) : Source;
1013 auto AttrBegin =
Decl->specific_attr_begin<HLSLAppliedSemanticAttr>();
1014 auto AttrEnd =
Decl->specific_attr_end<HLSLAppliedSemanticAttr>();
1022 if (
const auto *RSAttr = dyn_cast<RootSignatureAttr>(
Attr)) {
1023 auto *RSDecl = RSAttr->getSignatureDecl();
1024 addRootSignatureMD(RSDecl->getVersion(), RSDecl->getRootElements(),
1033 M.getNamedGlobal(CtorOrDtor ?
"llvm.global_ctors" :
"llvm.global_dtors");
1036 const auto *CA = dyn_cast<ConstantArray>(GV->getInitializer());
1043 for (
const auto &Ctor : CA->operands()) {
1049 "HLSL doesn't support setting priority for global ctors.");
1051 "HLSL doesn't support COMDat for global ctors.");
1066 for (
auto &F : M.functions()) {
1067 if (!F.hasFnAttribute(
"hlsl.shader"))
1070 Instruction *IP = &*F.getEntryBlock().begin();
1073 llvm::Value *bundleArgs[] = {
Token};
1074 OB.emplace_back(
"convergencectrl", bundleArgs);
1075 IP =
Token->getNextNode();
1078 for (
auto *Fn : CtorFns) {
1079 auto CI = B.CreateCall(FunctionCallee(Fn), {}, OB);
1080 CI->setCallingConv(Fn->getCallingConv());
1084 B.SetInsertPoint(F.back().getTerminator());
1085 for (
auto *Fn : DtorFns) {
1086 auto CI = B.CreateCall(FunctionCallee(Fn), {}, OB);
1087 CI->setCallingConv(Fn->getCallingConv());
1093 Triple T(M.getTargetTriple());
1094 if (T.getEnvironment() != Triple::EnvironmentType::Library) {
1095 if (
auto *GV = M.getNamedGlobal(
"llvm.global_ctors"))
1096 GV->eraseFromParent();
1097 if (
auto *GV = M.getNamedGlobal(
"llvm.global_dtors"))
1098 GV->eraseFromParent();
1103 Intrinsic::ID IntrID,
1107 llvm::Function *InitResFunc = llvm::Function::Create(
1108 llvm::FunctionType::get(CGM.
VoidTy,
false),
1109 llvm::GlobalValue::InternalLinkage,
1110 (
"_init_buffer_" + GV->getName()).str(), CGM.
getModule());
1111 InitResFunc->addFnAttr(llvm::Attribute::AlwaysInline);
1113 llvm::BasicBlock *EntryBB =
1114 llvm::BasicBlock::Create(Ctx,
"entry", InitResFunc);
1116 const DataLayout &DL = CGM.
getModule().getDataLayout();
1117 Builder.SetInsertPoint(EntryBB);
1120 llvm::Type *HandleTy = GV->getValueType();
1121 assert(HandleTy->isTargetExtTy() &&
"unexpected type of the buffer global");
1123 llvm::Value *CreateHandle = Builder.CreateIntrinsic(
1124 HandleTy, IntrID, Args,
nullptr,
1125 Twine(GV->getName()).concat(
"_h"));
1127 Builder.CreateAlignedStore(CreateHandle, GV, GV->getPointerAlignment(DL));
1128 Builder.CreateRetVoid();
1133void CGHLSLRuntime::initializeBufferFromBinding(
const HLSLBufferDecl *BufDecl,
1134 llvm::GlobalVariable *GV) {
1135 ResourceBindingAttrs Binding(BufDecl);
1137 "cbuffer/tbuffer should always have resource binding attribute");
1139 auto *Index = llvm::ConstantInt::get(CGM.
IntTy, 0);
1140 auto *RangeSize = llvm::ConstantInt::get(CGM.
IntTy, 1);
1141 auto *Space = llvm::ConstantInt::get(CGM.
IntTy, Binding.
getSpace());
1142 Value *Name = buildNameForResource(BufDecl->
getName(), CGM);
1146 llvm::Intrinsic::ID IntrinsicID =
1148 auto *RegSlot = llvm::ConstantInt::get(CGM.
IntTy, Binding.
getSlot());
1149 SmallVector<Value *> Args{Space, RegSlot, RangeSize, Index, Name};
1153 llvm::Intrinsic::ID IntrinsicID =
1154 CGM.
getHLSLRuntime().getCreateHandleFromImplicitBindingIntrinsic();
1157 SmallVector<Value *> Args{OrderID, Space, RangeSize, Index, Name};
1163 llvm::GlobalVariable *GV) {
1164 if (
auto Attr = VD->
getAttr<HLSLVkExtBuiltinInputAttr>())
1166 if (
auto Attr = VD->
getAttr<HLSLVkExtBuiltinOutputAttr>())
1175 for (
auto I = BB.begin(); I != E; ++I) {
1176 auto *II = dyn_cast<llvm::IntrinsicInst>(&*I);
1177 if (II && llvm::isConvergenceControlIntrinsic(II->getIntrinsicID())) {
1181 llvm_unreachable(
"Convergence token should have been emitted.");
1218 for (
auto *OVE : Visitor.
OVEs) {
1221 if (OpaqueValueMappingData::shouldBindAsLValue(OVE)) {
1223 OpaqueValueMappingData::bind(CGF, OVE, LV);
1226 OpaqueValueMappingData::bind(CGF, OVE, RV);
1235 "expected resource array subscript expression");
1241 dyn_cast_or_null<VarDecl>(getArrayDecl(ArraySubsExpr));
1244 return std::nullopt;
1250 "expected array of resource classes");
1256 Value *Index =
nullptr;
1258 while (ASE !=
nullptr) {
1260 if (
const auto *ArrayTy =
1262 Value *Multiplier = llvm::ConstantInt::get(
1264 SubIndex = CGF.
Builder.CreateMul(SubIndex, Multiplier);
1266 Index = Index ? CGF.
Builder.CreateAdd(Index, SubIndex) : SubIndex;
1274 "resource array must have a binding attribute");
1295 llvm::Value *Range = llvm::ConstantInt::getSigned(
1296 CGM.
IntTy, getTotalArraySize(AST, ResArrayTy));
1300 if (ResultTy == ResourceTy) {
1302 CXXMethodDecl *CreateMethod = lookupResourceInitMethodAndSetupArgs(
1304 ArrayDecl->
getName(), Binding, Args);
1310 return std::nullopt;
1312 callResourceInitMethod(CGF, CreateMethod, Args, ValueSlot.getAddress());
1319 std::optional<llvm::Value *> EndIndex = initializeLocalResourceArray(
1321 ArrayDecl->
getName(), Binding, {llvm::ConstantInt::get(CGM.IntTy, 0)},
1324 return std::nullopt;
1338 const VarDecl *ArrayDecl = dyn_cast_or_null<VarDecl>(getArrayDecl(RHSExpr));
1347 "resource array must have a binding attribute");
1361 int Size = getTotalArraySize(AST, ResArrayTy);
1362 llvm::Value *
Zero = llvm::ConstantInt::get(CGM.
IntTy, 0);
1363 llvm::Value *Range = llvm::ConstantInt::get(CGM.
IntTy, Size);
1366 std::optional<llvm::Value *> EndIndex = initializeLocalResourceArray(
1369 return EndIndex.has_value();
1378 "expected cbuffer matrix");
1384 if (LayoutTy == MemTy)
1400 llvm::function_ref<llvm::Value *(
bool Promote)> EmitIdxAfterBase) {
1404 llvm::Type *LayoutTy =
1406 uint64_t LayoutSizeInBits =
1407 CGM.
getDataLayout().getTypeSizeInBits(LayoutTy).getFixedValue();
1410 if (RowAlignedSize > ElementSize) {
1412 CGM, RowAlignedSize - ElementSize);
1413 assert(Padding &&
"No padding type for target?");
1414 LayoutTy = llvm::StructType::get(CGF.
getLLVMContext(), {LayoutTy, Padding},
1421 if (LayoutTy == OrigTy)
1422 return std::nullopt;
1431 llvm::Value *Idx = EmitIdxAfterBase(
true);
1432 Indices.push_back(Idx);
1433 Indices.push_back(llvm::ConstantInt::get(CGF.
Int32Ty, 0));
1439 assert(CE->
getCastKind() == CastKind::CK_ArrayToPointerDecay);
1443 LayoutTy = llvm::ArrayType::get(
1447 LayoutTy,
Addr.emitRawPointer(CGF), Indices,
"cbufferidx"));
1456 Indices,
"cbufferidx");
1464class HLSLBufferCopyEmitter {
1468 llvm::Type *LayoutTy =
nullptr;
1473 void emitCopyAtIndices(llvm::Type *FieldTy, llvm::ConstantInt *StoreIndex,
1474 llvm::ConstantInt *LoadIndex) {
1475 CurStoreIndices.push_back(StoreIndex);
1476 CurLoadIndices.push_back(LoadIndex);
1477 llvm::scope_exit RestoreIndices([&]() {
1478 CurStoreIndices.pop_back();
1479 CurLoadIndices.pop_back();
1483 if (processArray(FieldTy))
1485 if (processBufferLayoutArray(FieldTy))
1487 if (processStruct(FieldTy))
1495 CurLoadIndices,
"cbuf.src"),
1498 DestPtr, CurStoreIndices, FieldTy, Align,
"cbuf.dest");
1503 bool processArray(llvm::Type *FieldTy) {
1504 auto *AT = dyn_cast<llvm::ArrayType>(FieldTy);
1510 for (
unsigned I = 0, E = AT->getNumElements(); I < E; ++I)
1511 emitCopyAtIndices(AT->getElementType(),
1512 llvm::ConstantInt::get(CGF.
SizeTy, I),
1513 llvm::ConstantInt::get(CGF.
SizeTy, I));
1517 bool processBufferLayoutArray(llvm::Type *FieldTy) {
1523 auto *ST = dyn_cast<llvm::StructType>(FieldTy);
1524 if (!ST || ST->getNumElements() != 2)
1527 auto *PaddedEltsTy = dyn_cast<llvm::ArrayType>(ST->getElementType(0));
1531 auto *PaddedTy = dyn_cast<llvm::StructType>(PaddedEltsTy->getElementType());
1532 if (!PaddedTy || PaddedTy->getNumElements() != 2)
1536 PaddedTy->getElementType(1)))
1539 llvm::Type *ElementTy = ST->getElementType(1);
1540 if (PaddedTy->getElementType(0) != ElementTy)
1544 unsigned NumElts = PaddedEltsTy->getNumElements() + 1;
1548 CurLoadIndices.push_back(llvm::ConstantInt::get(CGF.
Int32Ty, 0));
1549 for (
unsigned I = 0; I < NumElts - 1; ++I) {
1551 CurLoadIndices.push_back(llvm::ConstantInt::get(CGF.
SizeTy, I));
1552 emitCopyAtIndices(ElementTy, llvm::ConstantInt::get(CGF.
SizeTy, I),
1553 llvm::ConstantInt::get(CGF.
Int32Ty, 0));
1554 CurLoadIndices.pop_back();
1556 CurLoadIndices.pop_back();
1559 emitCopyAtIndices(ElementTy,
1560 llvm::ConstantInt::get(CGF.
SizeTy, NumElts - 1),
1561 llvm::ConstantInt::get(CGF.
Int32Ty, 1));
1566 bool processStruct(llvm::Type *FieldTy) {
1567 auto *ST = dyn_cast<llvm::StructType>(FieldTy);
1572 unsigned Skipped = 0;
1573 for (
unsigned I = 0, E = ST->getNumElements(); I < E; ++I) {
1574 llvm::Type *ElementTy = ST->getElementType(I);
1578 emitCopyAtIndices(ElementTy, llvm::ConstantInt::get(CGF.
Int32Ty, I),
1579 llvm::ConstantInt::get(CGF.
Int32Ty, I + Skipped));
1585 HLSLBufferCopyEmitter(CodeGenFunction &CGF, Address DestPtr, Address SrcPtr)
1586 : CGF(CGF), DestPtr(DestPtr), SrcPtr(SrcPtr) {}
1588 bool emitCopy(QualType CType) {
1589 LayoutTy = HLSLBufferLayoutBuilder(CGF.
CGM).layOutType(CType);
1596 emitCopyAtIndices(LayoutTy, llvm::ConstantInt::get(CGF.
SizeTy, 0),
1597 llvm::ConstantInt::get(CGF.
SizeTy, 0));
1605 return HLSLBufferCopyEmitter(CGF, DestPtr, SrcPtr).emitCopy(CType);
1613 assert(Field &&
"Unexpected access into HLSL buffer");
1630 assert(FieldIdx < LayoutTy->getNumElements() &&
1631 "Layout struct is smaller than member struct");
1632 unsigned Skipped = 0;
1633 for (
unsigned I = 0; I <= FieldIdx;) {
1634 llvm::Type *ElementTy = LayoutTy->getElementType(I + Skipped);
1640 FieldIdx += Skipped;
1641 assert(FieldIdx < LayoutTy->getNumElements() &&
"Access out of bounds");
1645 QualType FieldType = Field->getType();
1651 ? CGF.
Builder.CreateStructuredGEP(
1652 LayoutTy,
Base.getPointer(CGF),
1653 llvm::ConstantInt::get(CGM.
IntTy, FieldIdx))
1655 FieldIdx, Field->getName());
Defines the clang::ASTContext interface.
static llvm::Value * createSPIRVBuiltinLoad(IRBuilder<> &B, llvm::Module &M, llvm::Type *Ty, const Twine &Name, unsigned BuiltInID)
static void addSPIRVBuiltinDecoration(llvm::GlobalVariable *GV, unsigned BuiltIn)
static void createSPIRVLocationStore(IRBuilder<> &B, llvm::Module &M, llvm::Value *Source, unsigned Location, StringRef Name)
static void gatherFunctions(SmallVectorImpl< Function * > &Fns, llvm::Module &M, bool CtorOrDtor)
static void addLocationDecoration(llvm::GlobalVariable *GV, unsigned Location)
static llvm::Value * createSPIRVLocationLoad(IRBuilder<> &B, llvm::Module &M, llvm::Type *Ty, unsigned Location, StringRef Name)
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)
llvm::MachO::Record Record
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 ...
QualType getPointerType(QualType T) const
Return the uniqued reference to the type for a pointer to the specified type.
QualType getBaseElementType(const ArrayType *VAT) const
Return the innermost element type of an array type.
CharUnits getTypeSizeInChars(QualType T) const
Return the size of the specified (complete) type T, in characters.
CanQualType UnsignedIntTy
QualType getHLSLAttributedResourceType(QualType Wrapped, QualType Contained, const HLSLAttributedResourceType::Attributes &Attrs)
uint64_t getConstantArrayElementCount(const ConstantArrayType *CA) const
Return number of constant array elements.
CanQualType getCanonicalTagType(const TagDecl *TD) const
ArraySubscriptExpr - [C99 6.5.2.1] Array Subscripting.
SourceLocation getExprLoc() const LLVM_READONLY
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 ...
llvm::Value * getBasePointer() const
CharUnits getAlignment() const
KnownNonNull_t isKnownNonNull() const
Whether the pointer is known not to be null.
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="")
llvm::LoadInst * CreateLoad(Address Addr, const llvm::Twine &Name="")
Address CreateInBoundsGEP(Address Addr, ArrayRef< llvm::Value * > IdxList, llvm::Type *ElementType, CharUnits Align, const Twine &Name="")
Abstract information about a function or function prototype.
All available information about a concrete callee.
CGFunctionInfo - Class to encapsulate the information about a function definition.
static const uint32_t Unspecified
static bool compareOffsets(uint32_t LHS, uint32_t RHS)
Comparison function for offsets received from operator[] suitable for use in a stable_sort.
static CGHLSLOffsetInfo fromDecl(const HLSLBufferDecl &BufDecl)
Iterates over all declarations in the HLSL buffer and based on the packoffset or register(c#) annotat...
llvm::Instruction * getConvergenceToken(llvm::BasicBlock &BB)
void setHLSLEntryAttributes(const FunctionDecl *FD, llvm::Function *Fn)
specific_attr_iterator< HLSLAppliedSemanticAttr > handleSemanticStore(llvm::IRBuilder<> &B, const FunctionDecl *FD, llvm::Value *Source, const clang::DeclaratorDecl *Decl, specific_attr_iterator< HLSLAppliedSemanticAttr > AttrBegin, specific_attr_iterator< HLSLAppliedSemanticAttr > AttrEnd)
llvm::StructType * getHLSLBufferLayoutType(const RecordType *LayoutStructTy)
void emitEntryFunction(const FunctionDecl *FD, llvm::Function *Fn)
void handleGlobalVarDefinition(const VarDecl *VD, llvm::GlobalVariable *Var)
void emitSystemSemanticStore(llvm::IRBuilder<> &B, llvm::Value *Source, const clang::DeclaratorDecl *Decl, HLSLAppliedSemanticAttr *Semantic, std::optional< unsigned > Index)
std::pair< llvm::Value *, specific_attr_iterator< HLSLAppliedSemanticAttr > > handleStructSemanticLoad(llvm::IRBuilder<> &B, const FunctionDecl *FD, llvm::Type *Type, const clang::DeclaratorDecl *Decl, specific_attr_iterator< HLSLAppliedSemanticAttr > begin, specific_attr_iterator< HLSLAppliedSemanticAttr > end)
specific_attr_iterator< HLSLAppliedSemanticAttr > handleStructSemanticStore(llvm::IRBuilder<> &B, const FunctionDecl *FD, llvm::Value *Source, const clang::DeclaratorDecl *Decl, specific_attr_iterator< HLSLAppliedSemanticAttr > AttrBegin, specific_attr_iterator< HLSLAppliedSemanticAttr > AttrEnd)
llvm::Value * handleScalarSemanticLoad(llvm::IRBuilder<> &B, const FunctionDecl *FD, llvm::Type *Type, const clang::DeclaratorDecl *Decl, HLSLAppliedSemanticAttr *Semantic)
void addHLSLBufferLayoutType(const RecordType *LayoutStructTy, llvm::StructType *LayoutTy)
void handleScalarSemanticStore(llvm::IRBuilder<> &B, const FunctionDecl *FD, llvm::Value *Source, const clang::DeclaratorDecl *Decl, HLSLAppliedSemanticAttr *Semantic)
std::pair< llvm::Value *, specific_attr_iterator< HLSLAppliedSemanticAttr > > handleSemanticLoad(llvm::IRBuilder<> &B, const FunctionDecl *FD, llvm::Type *Type, const clang::DeclaratorDecl *Decl, specific_attr_iterator< HLSLAppliedSemanticAttr > begin, specific_attr_iterator< HLSLAppliedSemanticAttr > end)
std::optional< LValue > emitBufferArraySubscriptExpr(const ArraySubscriptExpr *E, CodeGenFunction &CGF, llvm::function_ref< llvm::Value *(bool Promote)> EmitIdxAfterBase)
std::optional< LValue > emitResourceArraySubscriptExpr(const ArraySubscriptExpr *E, CodeGenFunction &CGF)
void addRootSignature(const HLSLRootSignatureDecl *D)
bool emitResourceArrayCopy(LValue &LHS, Expr *RHSExpr, CodeGenFunction &CGF)
LValue emitBufferMemberExpr(CodeGenFunction &CGF, const MemberExpr *E)
bool emitBufferCopy(CodeGenFunction &CGF, Address DestPtr, Address SrcPtr, QualType CType)
llvm::Type * convertHLSLSpecificType(const Type *T, const CGHLSLOffsetInfo &OffsetInfo)
resource_getpointer resource_handlefrombinding resource_nonuniformindex GENERATE_HLSL_INTRINSIC_FUNCTION(GroupMemoryBarrierWithGroupSync, group_memory_barrier_with_group_sync) protected llvm::Value * emitSystemSemanticLoad(llvm::IRBuilder<> &B, const FunctionDecl *FD, llvm::Type *Type, const clang::DeclaratorDecl *Decl, HLSLAppliedSemanticAttr *Semantic, std::optional< unsigned > Index)
RawAddress createBufferMatrixTempAddress(const LValue &LV, SourceLocation Loc, CodeGenFunction &CGF)
void addBuffer(const HLSLBufferDecl *D)
void generateGlobalCtorDtorCalls()
void emitInitListOpaqueValues(CodeGenFunction &CGF, InitListExpr *E)
unsigned getLLVMFieldNo(const FieldDecl *FD) const
Return llvm::StructType element number that corresponds to the field FD.
CallArgList - Type for representing both the value and type of arguments in a call.
void add(RValue rvalue, QualType type)
A non-RAII class containing all the information about a bound opaque value.
CodeGenFunction - This class organizes the per-function state that is used while generating LLVM code...
const LangOptions & getLangOpts() const
@ TCK_MemberAccess
Checking the object expression in a non-static data member access.
void pushFullExprCleanup(CleanupKind kind, As... A)
pushFullExprCleanup - Push a cleanup to be run at the end of the current full-expression.
bool EmitLifetimeStart(llvm::Value *Addr)
Emit a lifetime.begin marker if some criteria are satisfied.
llvm::AllocaInst * CreateTempAlloca(llvm::Type *Ty, const Twine &Name="tmp", llvm::Value *ArraySize=nullptr)
CreateTempAlloca - This creates an alloca and inserts it into the entry block if ArraySize is nullptr...
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,...
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.
RawAddress CreateMemTemp(QualType T, const Twine &Name="tmp", RawAddress *Alloca=nullptr)
CreateMemTemp - Create a temporary memory object of the given type, with appropriate alignmen and cas...
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.
CGHLSLRuntime & getHLSLRuntime()
Return a reference to the configured HLSL runtime.
llvm::Module & getModule() const
llvm::Constant * GetAddrOfFunction(GlobalDecl GD, llvm::Type *Ty=nullptr, bool ForVTable=false, bool DontDefer=false, ForDefinition_t IsForDefinition=NotForDefinition)
Return the address of the given function.
void AddCXXGlobalInit(llvm::Function *F)
const LangOptions & getLangOpts() const
CodeGenTypes & getTypes()
const TargetInfo & getTarget() const
void EmitGlobal(GlobalDecl D)
Emit code for a single global function or var decl.
const llvm::DataLayout & getDataLayout() const
bool shouldEmitConvergenceTokens() const
TBAAAccessInfo getTBAAAccessInfo(QualType AccessType)
getTBAAAccessInfo - Get TBAA information that describes an access to an object of the given type.
ASTContext & getContext() const
llvm::Constant * GetAddrOfGlobalVar(const VarDecl *D, llvm::Type *Ty=nullptr, ForDefinition_t IsForDefinition=NotForDefinition)
Return the llvm::Constant for the address of the given global variable.
const TargetCodeGenInfo & getTargetCodeGenInfo()
const CodeGenOptions & getCodeGenOpts() const
llvm::LLVMContext & getLLVMContext()
llvm::Function * getIntrinsic(unsigned IID, ArrayRef< llvm::Type * > Tys={})
void EmitTopLevelDecl(Decl *D)
Emit code for a single top level declaration.
ConstantAddress GetAddrOfConstantCString(const std::string &Str, StringRef GlobalName=".str")
Returns a pointer to a character array containing the literal and a terminating '\0' character.
const CGRecordLayout & getCGRecordLayout(const RecordDecl *)
getCGRecordLayout - Return record layout info for the given record decl.
llvm::Type * ConvertTypeForMem(QualType T)
ConvertTypeForMem - Convert type T into a llvm::Type.
const CGFunctionInfo & arrangeFreeFunctionCall(const CallArgList &Args, const FunctionType *Ty, bool ChainCall)
Figure out the rules for calling a function with the given formal type using the given arguments.
llvm::Constant * getPointer() const
llvm::StructType * layOutStruct(const RecordType *StructType, const CGHLSLOffsetInfo &OffsetInfo)
Lays out a struct type following HLSL buffer rules and considering any explicit offset information.
llvm::Type * layOutType(QualType Type)
Lays out a type following HLSL buffer rules.
LValue - This represents an lvalue references.
static LValue MakeAddr(Address Addr, QualType type, ASTContext &Context, LValueBaseInfo BaseInfo, TBAAAccessInfo TBAAInfo)
const Qualifiers & getQuals() const
Address getAddress() const
RValue - This trivial value class is used to represent the result of an expression that is evaluated.
static RValue get(llvm::Value *V)
An abstract representation of an aligned address.
llvm::Value * getPointer() const
ReturnValueSlot - Contains the address where the return value of a function can be stored,...
virtual bool isHLSLPadding(llvm::Type *Ty) const
Return true if this is an HLSL padding type.
virtual llvm::Type * getHLSLPadding(CodeGenModule &CGM, CharUnits NumBytes) const
Return an LLVM type that corresponds to padding in HLSL types.
virtual llvm::Type * getHLSLType(CodeGenModule &CGM, const Type *T, const CGHLSLOffsetInfo &OffsetInfo) const
Return an LLVM type that corresponds to a HLSL type.
Represents the canonical version of C arrays with a specified constant size.
int64_t getSExtSize() const
Return the size sign-extended as a uint64_t.
DeclContext * getParent()
getParent - Returns the containing DeclContext.
A reference to a declared variable, function, enum, etc.
Decl - This represents one declaration (or definition), e.g.
ASTContext & getASTContext() const LLVM_READONLY
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...
Expr * IgnoreImpCasts() LLVM_READONLY
Skip past any implicit casts which might surround this expression until reaching a fixed point.
SourceLocation getExprLoc() const LLVM_READONLY
getExprLoc - Return the preferred location for the arrow when diagnosing a problem with a generic exp...
Represents a member of a struct/union/class.
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
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.
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.
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.
TargetOptions & getTargetOpts() const
Retrieve the target options.
const llvm::Triple & getTriple() const
Returns the target triple of the primary target.
Token - This structure provides full information about a lexed token.
The base class of the type hierarchy.
bool isIncompleteArrayType() const
CXXRecordDecl * getAsCXXRecordDecl() const
Retrieves the CXXRecordDecl that this type refers to, either because the type is a RecordType or beca...
RecordDecl * getAsRecordDecl() const
Retrieves the RecordDecl this type refers to.
bool isConstantMatrixType() const
bool 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 isHLSLResourceRecordArray() const
Represent the declaration of a variable (in which case it is an lvalue) a function (in which case it ...
Represents a variable declaration or definition.
bool hasGlobalStorage() const
Returns true for all variables that do not have local storage.
StorageClass getStorageClass() const
Returns the storage class as written in the source.
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 ...
The JSON file list parser is used to communicate input to InstallAPI.
bool isa(CodeGen::Address addr)
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.
U cast(CodeGen::Address addr)
Diagnostic wrappers for TextAPI types for error reporting.
llvm::IntegerType * SizeTy
llvm::IntegerType * Int32Ty
llvm::IntegerType * IntTy
int
unsigned getImplicitOrderID() const
bool hasCounterImplicitOrderID() const
unsigned getSpace() const
unsigned getCounterImplicitOrderID() const