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 "constant buffer decl with non-zero sized type outside of "
330 "hlsl_constant address space");
335 DeclsWithOffset.emplace_back(VD, OffsetInfo[OffsetIdx++]);
338 if (!OffsetInfo.
empty())
339 llvm::stable_sort(DeclsWithOffset, [](
const auto &LHS,
const auto &RHS) {
344 SmallVector<llvm::Metadata *> BufGlobals;
345 BufGlobals.reserve(DeclsWithOffset.size() + 1);
346 BufGlobals.push_back(ValueAsMetadata::get(BufGV));
348 auto ElemIt = LayoutStruct->element_begin();
349 for (
auto &[VD, _] : DeclsWithOffset) {
353 assert(ElemIt != LayoutStruct->element_end() &&
354 "number of elements in layout struct does not match");
355 llvm::Type *LayoutType = *ElemIt++;
357 GlobalVariable *ElemGV =
359 BufGlobals.push_back(ValueAsMetadata::get(ElemGV));
361 assert(ElemIt == LayoutStruct->element_end() &&
362 "number of elements in layout struct does not match");
366 .getOrInsertNamedMetadata(
"hlsl.cbs")
367 ->addOperand(MDNode::get(Ctx, BufGlobals));
371static const clang::HLSLAttributedResourceType *
376 HLSLAttributedResourceType::Attributes(ResourceClass::CBuffer));
391 VarDecl *VD = dyn_cast<VarDecl>(D);
402 if (
auto *POA = dyn_cast<HLSLPackOffsetAttr>(
Attr)) {
403 Offset = POA->getOffsetInBytes();
406 auto *RBA = dyn_cast<HLSLResourceBindingAttr>(
Attr);
408 RBA->getRegisterType() == HLSLResourceBindingAttr::RegisterType::C) {
409 Offset = RBA->getSlotNumber() * CBufferRowSizeInBytes;
413 Result.Offsets.push_back(Offset);
421 assert(BufDecl->
isCBuffer() &&
"tbuffer codegen is not supported yet");
424 const clang::HLSLAttributedResourceType *ResHandleTy =
428 if (ResHandleTy->getContainedType()->getAsCXXRecordDecl()->isEmpty())
434 llvm::GlobalVariable *BufGV =
new GlobalVariable(
436 GlobalValue::LinkageTypes::ExternalLinkage, PoisonValue::get(LayoutTy),
437 llvm::formatv(
"{0}{1}", BufDecl->
getName(),
439 GlobalValue::NotThreadLocal);
440 CGM.
getModule().insertGlobalVariable(BufGV);
443 emitBufferGlobalsAndMetadata(BufDecl, BufGV, OffsetInfo);
446 initializeBufferFromBinding(BufDecl, BufGV);
452 Triple T(M.getTargetTriple());
455 if (T.getEnvironment() != Triple::EnvironmentType::RootSignature)
458 addRootSignatureMD(SignatureDecl->
getVersion(),
464 const auto Entry = LayoutTypes.find(StructType);
465 if (Entry != LayoutTypes.end())
466 return Entry->getSecond();
471 llvm::StructType *LayoutTy) {
473 "layout type for this struct already exist");
474 LayoutTypes[StructType] = LayoutTy;
482 Triple T(M.getTargetTriple());
483 if (T.getArch() == Triple::ArchType::dxil)
484 addDxilValVersion(TargetOpts.DxilValidatorVersion, M);
485 if (CodeGenOpts.ResMayAlias)
486 M.setModuleFlag(llvm::Module::ModFlagBehavior::Error,
"dx.resmayalias", 1);
487 if (CodeGenOpts.AllResourcesBound)
488 M.setModuleFlag(llvm::Module::ModFlagBehavior::Error,
489 "dx.allresourcesbound", 1);
490 if (CodeGenOpts.OptimizationLevel == 0)
491 M.addModuleFlag(llvm::Module::ModFlagBehavior::Override,
492 "dx.disable_optimizations", 1);
497 if (LangOpts.NativeHalfType)
498 M.setModuleFlag(llvm::Module::ModFlagBehavior::Error,
"dx.nativelowprec",
506 const auto *ShaderAttr = FD->
getAttr<HLSLShaderAttr>();
507 assert(ShaderAttr &&
"All entry functions must have a HLSLShaderAttr");
508 const StringRef ShaderAttrKindStr =
"hlsl.shader";
509 Fn->addFnAttr(ShaderAttrKindStr,
510 llvm::Triple::getEnvironmentTypeName(ShaderAttr->getType()));
511 if (HLSLNumThreadsAttr *NumThreadsAttr = FD->
getAttr<HLSLNumThreadsAttr>()) {
512 const StringRef NumThreadsKindStr =
"hlsl.numthreads";
513 std::string NumThreadsStr =
514 formatv(
"{0},{1},{2}", NumThreadsAttr->getX(), NumThreadsAttr->getY(),
515 NumThreadsAttr->getZ());
516 Fn->addFnAttr(NumThreadsKindStr, NumThreadsStr);
518 if (HLSLWaveSizeAttr *WaveSizeAttr = FD->
getAttr<HLSLWaveSizeAttr>()) {
519 const StringRef WaveSizeKindStr =
"hlsl.wavesize";
520 std::string WaveSizeStr =
521 formatv(
"{0},{1},{2}", WaveSizeAttr->getMin(), WaveSizeAttr->getMax(),
522 WaveSizeAttr->getPreferred());
523 Fn->addFnAttr(WaveSizeKindStr, WaveSizeStr);
530 Fn->addFnAttr(llvm::Attribute::NoInline);
532 if (CGM.
getLangOpts().HLSLSpvEnableMaximalReconvergence) {
533 Fn->addFnAttr(
"enable-maximal-reconvergence",
"true");
538 if (
const auto *VT = dyn_cast<FixedVectorType>(Ty)) {
539 Value *Result = PoisonValue::get(Ty);
540 for (
unsigned I = 0; I < VT->getNumElements(); ++I) {
541 Value *Elt = B.CreateCall(F, {B.getInt32(I)});
542 Result = B.CreateInsertElement(Result, Elt, I);
546 return B.CreateCall(F, {B.getInt32(0)});
551 LLVMContext &Ctx = GV->getContext();
552 IRBuilder<> B(GV->getContext());
553 MDNode *Operands = MDNode::get(
555 {ConstantAsMetadata::get(B.getInt32( 11)),
556 ConstantAsMetadata::get(B.getInt32(BuiltIn))});
557 MDNode *Decoration = MDNode::get(Ctx, {Operands});
558 GV->addMetadata(
"spirv.Decorations", *Decoration);
562 LLVMContext &Ctx = GV->getContext();
563 IRBuilder<> B(GV->getContext());
565 MDNode::get(Ctx, {ConstantAsMetadata::get(B.getInt32( 30)),
566 ConstantAsMetadata::get(B.getInt32(Location))});
567 MDNode *Decoration = MDNode::get(Ctx, {Operands});
568 GV->addMetadata(
"spirv.Decorations", *Decoration);
572 llvm::Type *Ty,
const Twine &Name,
573 unsigned BuiltInID) {
574 auto *GV =
new llvm::GlobalVariable(
575 M, Ty,
true, llvm::GlobalValue::ExternalLinkage,
576 nullptr, Name,
nullptr,
577 llvm::GlobalVariable::GeneralDynamicTLSModel,
580 GV->setVisibility(llvm::GlobalValue::HiddenVisibility);
581 return B.CreateLoad(Ty, GV);
585 llvm::Type *Ty,
unsigned Location,
587 auto *GV =
new llvm::GlobalVariable(
588 M, Ty,
true, llvm::GlobalValue::ExternalLinkage,
589 nullptr, Name,
nullptr,
590 llvm::GlobalVariable::GeneralDynamicTLSModel,
592 GV->setVisibility(llvm::GlobalValue::HiddenVisibility);
594 return B.CreateLoad(Ty, GV);
597llvm::Value *CGHLSLRuntime::emitSPIRVUserSemanticLoad(
598 llvm::IRBuilder<> &B, llvm::Type *
Type,
const clang::DeclaratorDecl *
Decl,
599 HLSLAppliedSemanticAttr *Semantic, std::optional<unsigned> Index) {
600 Twine BaseName = Twine(Semantic->getAttrName()->getName());
601 Twine VariableName = BaseName.concat(Twine(Index.value_or(0)));
603 unsigned Location = SPIRVLastAssignedInputSemanticLocation;
604 if (
auto *L =
Decl->getAttr<HLSLVkLocationAttr>())
605 Location = L->getLocation();
609 llvm::ArrayType *AT = dyn_cast<llvm::ArrayType>(
Type);
610 unsigned ElementCount = AT ? AT->getNumElements() : 1;
611 SPIRVLastAssignedInputSemanticLocation += ElementCount;
618 llvm::Value *Source,
unsigned Location,
620 auto *GV =
new llvm::GlobalVariable(
621 M, Source->getType(),
false,
622 llvm::GlobalValue::ExternalLinkage,
623 nullptr, Name,
nullptr,
624 llvm::GlobalVariable::GeneralDynamicTLSModel,
626 GV->setVisibility(llvm::GlobalValue::HiddenVisibility);
628 B.CreateStore(Source, GV);
631void CGHLSLRuntime::emitSPIRVUserSemanticStore(
632 llvm::IRBuilder<> &B, llvm::Value *Source,
633 const clang::DeclaratorDecl *
Decl, HLSLAppliedSemanticAttr *Semantic,
634 std::optional<unsigned> Index) {
635 Twine BaseName = Twine(Semantic->getAttrName()->getName());
636 Twine VariableName = BaseName.concat(Twine(Index.value_or(0)));
638 unsigned Location = SPIRVLastAssignedOutputSemanticLocation;
639 if (
auto *L =
Decl->getAttr<HLSLVkLocationAttr>())
640 Location = L->getLocation();
644 llvm::ArrayType *AT = dyn_cast<llvm::ArrayType>(Source->getType());
645 unsigned ElementCount = AT ? AT->getNumElements() : 1;
646 SPIRVLastAssignedOutputSemanticLocation += ElementCount;
652CGHLSLRuntime::emitDXILUserSemanticLoad(llvm::IRBuilder<> &B, llvm::Type *
Type,
653 HLSLAppliedSemanticAttr *Semantic,
654 std::optional<unsigned> Index) {
655 Twine BaseName = Twine(Semantic->getAttrName()->getName());
656 Twine VariableName = BaseName.concat(Twine(Index.value_or(0)));
661 SmallVector<Value *> Args{B.getInt32(4), B.getInt32(0), B.getInt32(0),
663 llvm::PoisonValue::get(B.getInt32Ty())};
665 llvm::Intrinsic::ID IntrinsicID = llvm::Intrinsic::dx_load_input;
666 llvm::Value *
Value = B.CreateIntrinsic(
Type, IntrinsicID, Args,
667 nullptr, VariableName);
671void CGHLSLRuntime::emitDXILUserSemanticStore(llvm::IRBuilder<> &B,
673 HLSLAppliedSemanticAttr *Semantic,
674 std::optional<unsigned> Index) {
677 SmallVector<Value *> Args{B.getInt32(4),
681 llvm::PoisonValue::get(B.getInt32Ty()),
684 llvm::Intrinsic::ID IntrinsicID = llvm::Intrinsic::dx_store_output;
685 B.CreateIntrinsic(CGM.
VoidTy, IntrinsicID, Args,
nullptr);
688llvm::Value *CGHLSLRuntime::emitUserSemanticLoad(
689 IRBuilder<> &B, llvm::Type *
Type,
const clang::DeclaratorDecl *
Decl,
690 HLSLAppliedSemanticAttr *Semantic, std::optional<unsigned> Index) {
692 return emitSPIRVUserSemanticLoad(B,
Type,
Decl, Semantic, Index);
695 return emitDXILUserSemanticLoad(B,
Type, Semantic, Index);
697 llvm_unreachable(
"Unsupported target for user-semantic load.");
700void CGHLSLRuntime::emitUserSemanticStore(IRBuilder<> &B, llvm::Value *Source,
701 const clang::DeclaratorDecl *
Decl,
702 HLSLAppliedSemanticAttr *Semantic,
703 std::optional<unsigned> Index) {
705 return emitSPIRVUserSemanticStore(B, Source,
Decl, Semantic, Index);
708 return emitDXILUserSemanticStore(B, Source, Semantic, Index);
710 llvm_unreachable(
"Unsupported target for user-semantic load.");
716 std::optional<unsigned> Index) {
718 std::string SemanticName = Semantic->getAttrName()->getName().upper();
719 if (SemanticName ==
"SV_GROUPINDEX") {
720 llvm::Function *GroupIndex =
721 CGM.
getIntrinsic(getFlattenedThreadIdInGroupIntrinsic());
722 return B.CreateCall(FunctionCallee(GroupIndex));
725 if (SemanticName ==
"SV_DISPATCHTHREADID") {
726 llvm::Intrinsic::ID IntrinID = getThreadIdIntrinsic();
727 llvm::Function *ThreadIDIntrinsic =
728 llvm::Intrinsic::isOverloaded(IntrinID)
734 if (SemanticName ==
"SV_GROUPTHREADID") {
735 llvm::Intrinsic::ID IntrinID = getGroupThreadIdIntrinsic();
736 llvm::Function *GroupThreadIDIntrinsic =
737 llvm::Intrinsic::isOverloaded(IntrinID)
743 if (SemanticName ==
"SV_GROUPID") {
744 llvm::Intrinsic::ID IntrinID = getGroupIdIntrinsic();
745 llvm::Function *GroupIDIntrinsic =
746 llvm::Intrinsic::isOverloaded(IntrinID)
752 const auto *ShaderAttr = FD->
getAttr<HLSLShaderAttr>();
753 assert(ShaderAttr &&
"Entry point has no shader attribute");
754 llvm::Triple::EnvironmentType ST = ShaderAttr->getType();
756 if (SemanticName ==
"SV_POSITION") {
757 if (ST == Triple::EnvironmentType::Pixel) {
760 Semantic->getAttrName()->getName(),
763 return emitDXILUserSemanticLoad(B,
Type, Semantic, Index);
766 if (ST == Triple::EnvironmentType::Vertex) {
767 return emitUserSemanticLoad(B,
Type,
Decl, Semantic, Index);
772 "Load hasn't been implemented yet for this system semantic. FIXME");
776 llvm::Value *Source,
const Twine &Name,
777 unsigned BuiltInID) {
778 auto *GV =
new llvm::GlobalVariable(
779 M, Source->getType(),
false,
780 llvm::GlobalValue::ExternalLinkage,
781 nullptr, Name,
nullptr,
782 llvm::GlobalVariable::GeneralDynamicTLSModel,
785 GV->setVisibility(llvm::GlobalValue::HiddenVisibility);
786 B.CreateStore(Source, GV);
791 HLSLAppliedSemanticAttr *Semantic,
792 std::optional<unsigned> Index) {
794 std::string SemanticName = Semantic->getAttrName()->getName().upper();
795 if (SemanticName ==
"SV_POSITION") {
797 emitDXILUserSemanticStore(B, Source, Semantic, Index);
803 Semantic->getAttrName()->getName(),
809 if (SemanticName ==
"SV_TARGET") {
810 emitUserSemanticStore(B, Source,
Decl, Semantic, Index);
815 "Store hasn't been implemented yet for this system semantic. FIXME");
822 std::optional<unsigned> Index = Semantic->getSemanticIndex();
823 if (Semantic->getAttrName()->getName().starts_with_insensitive(
"SV_"))
825 return emitUserSemanticLoad(B,
Type,
Decl, Semantic, Index);
829 IRBuilder<> &B,
const FunctionDecl *FD, llvm::Value *Source,
831 std::optional<unsigned> Index = Semantic->getSemanticIndex();
832 if (Semantic->getAttrName()->getName().starts_with_insensitive(
"SV_"))
835 emitUserSemanticStore(B, Source,
Decl, Semantic, Index);
838std::pair<llvm::Value *, specific_attr_iterator<HLSLAppliedSemanticAttr>>
851 for (
unsigned I = 0; I < ST->getNumElements(); ++I) {
853 B, FD, ST->getElementType(I), *
FieldDecl, AttrBegin, AttrEnd);
854 AttrBegin = NextAttr;
860 return std::make_pair(
Aggregate, AttrBegin);
865 IRBuilder<> &B,
const FunctionDecl *FD, llvm::Value *Source,
876 RD =
Decl->getType()->getAsRecordDecl();
882 for (
unsigned I = 0; I < ST->getNumElements(); ++I, ++
FieldDecl) {
883 llvm::Value *Extract = B.CreateExtractValue(Source, I);
891std::pair<llvm::Value *, specific_attr_iterator<HLSLAppliedSemanticAttr>>
897 assert(AttrBegin != AttrEnd);
898 if (
Type->isStructTy())
901 HLSLAppliedSemanticAttr *
Attr = *AttrBegin;
909 IRBuilder<> &B,
const FunctionDecl *FD, llvm::Value *Source,
913 assert(AttrBegin != AttrEnd);
914 if (Source->getType()->isStructTy())
917 HLSLAppliedSemanticAttr *
Attr = *AttrBegin;
924 llvm::Function *Fn) {
926 llvm::LLVMContext &Ctx = M.getContext();
927 auto *EntryTy = llvm::FunctionType::get(llvm::Type::getVoidTy(Ctx),
false);
929 Function::Create(EntryTy, Function::ExternalLinkage, FD->
getName(), &M);
933 AttributeList NewAttrs = AttributeList::get(Ctx, AttributeList::FunctionIndex,
934 Fn->getAttributes().getFnAttrs());
935 EntryFn->setAttributes(NewAttrs);
939 Fn->setLinkage(GlobalValue::InternalLinkage);
941 BasicBlock *BB = BasicBlock::Create(Ctx,
"entry", EntryFn);
947 assert(EntryFn->isConvergent());
949 B.CreateIntrinsic(llvm::Intrinsic::experimental_convergence_entry, {});
950 llvm::Value *bundleArgs[] = {I};
951 OB.emplace_back(
"convergencectrl", bundleArgs);
954 llvm::DenseMap<const DeclaratorDecl *, std::pair<llvm::Value *, llvm::Type *>>
957 unsigned SRetOffset = 0;
958 for (
const auto &Param : Fn->args()) {
959 if (Param.hasStructRetAttr()) {
961 llvm::Type *VarType = Param.getParamStructRetType();
962 llvm::Value *Var = B.CreateAlloca(VarType);
963 OutputSemantic.try_emplace(FD, std::make_pair(Var, VarType));
969 llvm::Value *SemanticValue =
nullptr;
971 if ([[maybe_unused]] HLSLParamModifierAttr *MA =
972 PD->
getAttr<HLSLParamModifierAttr>()) {
973 llvm_unreachable(
"Not handled yet");
975 llvm::Type *ParamType =
976 Param.hasByValAttr() ? Param.getParamByValType() : Param.getType();
981 SemanticValue =
Result.first;
984 if (Param.hasByValAttr()) {
985 llvm::Value *Var = B.CreateAlloca(Param.getParamByValType());
986 B.CreateStore(SemanticValue, Var);
991 assert(SemanticValue);
992 Args.push_back(SemanticValue);
995 CallInst *CI = B.CreateCall(FunctionCallee(Fn), Args, OB);
996 CI->setCallingConv(Fn->getCallingConv());
998 if (Fn->getReturnType() != CGM.
VoidTy)
1000 OutputSemantic.try_emplace(FD, std::make_pair(CI,
nullptr));
1002 for (
auto &[
Decl, SourcePair] : OutputSemantic) {
1003 llvm::Value *Source = SourcePair.first;
1004 llvm::Type *ElementType = SourcePair.second;
1005 AllocaInst *AI = dyn_cast<AllocaInst>(Source);
1006 llvm::Value *SourceValue = AI ? B.CreateLoad(ElementType, Source) : Source;
1008 auto AttrBegin =
Decl->specific_attr_begin<HLSLAppliedSemanticAttr>();
1009 auto AttrEnd =
Decl->specific_attr_end<HLSLAppliedSemanticAttr>();
1017 if (
const auto *RSAttr = dyn_cast<RootSignatureAttr>(
Attr)) {
1018 auto *RSDecl = RSAttr->getSignatureDecl();
1019 addRootSignatureMD(RSDecl->getVersion(), RSDecl->getRootElements(),
1028 M.getNamedGlobal(CtorOrDtor ?
"llvm.global_ctors" :
"llvm.global_dtors");
1031 const auto *CA = dyn_cast<ConstantArray>(GV->getInitializer());
1038 for (
const auto &Ctor : CA->operands()) {
1044 "HLSL doesn't support setting priority for global ctors.");
1046 "HLSL doesn't support COMDat for global ctors.");
1061 for (
auto &F : M.functions()) {
1062 if (!F.hasFnAttribute(
"hlsl.shader"))
1065 Instruction *IP = &*F.getEntryBlock().begin();
1068 llvm::Value *bundleArgs[] = {
Token};
1069 OB.emplace_back(
"convergencectrl", bundleArgs);
1070 IP =
Token->getNextNode();
1073 for (
auto *Fn : CtorFns) {
1074 auto CI = B.CreateCall(FunctionCallee(Fn), {}, OB);
1075 CI->setCallingConv(Fn->getCallingConv());
1079 B.SetInsertPoint(F.back().getTerminator());
1080 for (
auto *Fn : DtorFns) {
1081 auto CI = B.CreateCall(FunctionCallee(Fn), {}, OB);
1082 CI->setCallingConv(Fn->getCallingConv());
1088 Triple T(M.getTargetTriple());
1089 if (T.getEnvironment() != Triple::EnvironmentType::Library) {
1090 if (
auto *GV = M.getNamedGlobal(
"llvm.global_ctors"))
1091 GV->eraseFromParent();
1092 if (
auto *GV = M.getNamedGlobal(
"llvm.global_dtors"))
1093 GV->eraseFromParent();
1098 Intrinsic::ID IntrID,
1102 llvm::Function *InitResFunc = llvm::Function::Create(
1103 llvm::FunctionType::get(CGM.
VoidTy,
false),
1104 llvm::GlobalValue::InternalLinkage,
1105 (
"_init_buffer_" + GV->getName()).str(), CGM.
getModule());
1106 InitResFunc->addFnAttr(llvm::Attribute::AlwaysInline);
1108 llvm::BasicBlock *EntryBB =
1109 llvm::BasicBlock::Create(Ctx,
"entry", InitResFunc);
1111 const DataLayout &DL = CGM.
getModule().getDataLayout();
1112 Builder.SetInsertPoint(EntryBB);
1115 llvm::Type *HandleTy = GV->getValueType();
1116 assert(HandleTy->isTargetExtTy() &&
"unexpected type of the buffer global");
1118 llvm::Value *CreateHandle = Builder.CreateIntrinsic(
1119 HandleTy, IntrID, Args,
nullptr,
1120 Twine(GV->getName()).concat(
"_h"));
1122 Builder.CreateAlignedStore(CreateHandle, GV, GV->getPointerAlignment(DL));
1123 Builder.CreateRetVoid();
1128void CGHLSLRuntime::initializeBufferFromBinding(
const HLSLBufferDecl *BufDecl,
1129 llvm::GlobalVariable *GV) {
1130 ResourceBindingAttrs Binding(BufDecl);
1132 "cbuffer/tbuffer should always have resource binding attribute");
1134 auto *Index = llvm::ConstantInt::get(CGM.
IntTy, 0);
1135 auto *RangeSize = llvm::ConstantInt::get(CGM.
IntTy, 1);
1136 auto *Space = llvm::ConstantInt::get(CGM.
IntTy, Binding.
getSpace());
1137 Value *Name = buildNameForResource(BufDecl->
getName(), CGM);
1141 llvm::Intrinsic::ID IntrinsicID =
1143 auto *RegSlot = llvm::ConstantInt::get(CGM.
IntTy, Binding.
getSlot());
1144 SmallVector<Value *> Args{Space, RegSlot, RangeSize, Index, Name};
1148 llvm::Intrinsic::ID IntrinsicID =
1149 CGM.
getHLSLRuntime().getCreateHandleFromImplicitBindingIntrinsic();
1152 SmallVector<Value *> Args{OrderID, Space, RangeSize, Index, Name};
1158 llvm::GlobalVariable *GV) {
1159 if (
auto Attr = VD->
getAttr<HLSLVkExtBuiltinInputAttr>())
1168 for (
auto I = BB.begin(); I != E; ++I) {
1169 auto *II = dyn_cast<llvm::IntrinsicInst>(&*I);
1170 if (II && llvm::isConvergenceControlIntrinsic(II->getIntrinsicID())) {
1174 llvm_unreachable(
"Convergence token should have been emitted.");
1211 for (
auto *OVE : Visitor.
OVEs) {
1214 if (OpaqueValueMappingData::shouldBindAsLValue(OVE)) {
1216 OpaqueValueMappingData::bind(CGF, OVE, LV);
1219 OpaqueValueMappingData::bind(CGF, OVE, RV);
1228 "expected resource array subscript expression");
1234 dyn_cast_or_null<VarDecl>(getArrayDecl(ArraySubsExpr));
1237 return std::nullopt;
1243 "expected array of resource classes");
1249 Value *Index =
nullptr;
1251 while (ASE !=
nullptr) {
1253 if (
const auto *ArrayTy =
1255 Value *Multiplier = llvm::ConstantInt::get(
1257 SubIndex = CGF.
Builder.CreateMul(SubIndex, Multiplier);
1259 Index = Index ? CGF.
Builder.CreateAdd(Index, SubIndex) : SubIndex;
1267 "resource array must have a binding attribute");
1288 llvm::Value *Range = llvm::ConstantInt::getSigned(
1289 CGM.
IntTy, getTotalArraySize(AST, ResArrayTy));
1293 if (ResultTy == ResourceTy) {
1295 CXXMethodDecl *CreateMethod = lookupResourceInitMethodAndSetupArgs(
1297 ArrayDecl->
getName(), Binding, Args);
1303 return std::nullopt;
1305 callResourceInitMethod(CGF, CreateMethod, Args, ValueSlot.getAddress());
1312 std::optional<llvm::Value *> EndIndex = initializeLocalResourceArray(
1314 ArrayDecl->
getName(), Binding, {llvm::ConstantInt::get(CGM.IntTy, 0)},
1317 return std::nullopt;
1331 const VarDecl *ArrayDecl = dyn_cast_or_null<VarDecl>(getArrayDecl(RHSExpr));
1340 "resource array must have a binding attribute");
1354 int Size = getTotalArraySize(AST, ResArrayTy);
1355 llvm::Value *
Zero = llvm::ConstantInt::get(CGM.
IntTy, 0);
1356 llvm::Value *Range = llvm::ConstantInt::get(CGM.
IntTy, Size);
1359 std::optional<llvm::Value *> EndIndex = initializeLocalResourceArray(
1362 return EndIndex.has_value();
1371 "expected cbuffer matrix");
1377 if (LayoutTy == MemTy)
1393 llvm::function_ref<llvm::Value *(
bool Promote)> EmitIdxAfterBase) {
1397 llvm::Type *LayoutTy =
1399 uint64_t LayoutSizeInBits =
1400 CGM.
getDataLayout().getTypeSizeInBits(LayoutTy).getFixedValue();
1403 if (RowAlignedSize > ElementSize) {
1405 CGM, RowAlignedSize - ElementSize);
1406 assert(Padding &&
"No padding type for target?");
1407 LayoutTy = llvm::StructType::get(CGF.
getLLVMContext(), {LayoutTy, Padding},
1414 if (LayoutTy == OrigTy)
1415 return std::nullopt;
1424 llvm::Value *Idx = EmitIdxAfterBase(
true);
1425 Indices.push_back(Idx);
1426 Indices.push_back(llvm::ConstantInt::get(CGF.
Int32Ty, 0));
1432 assert(CE->
getCastKind() == CastKind::CK_ArrayToPointerDecay);
1436 LayoutTy = llvm::ArrayType::get(
1440 LayoutTy,
Addr.emitRawPointer(CGF), Indices,
"cbufferidx"));
1449 Indices,
"cbufferidx");
1457class HLSLBufferCopyEmitter {
1461 llvm::Type *LayoutTy =
nullptr;
1466 void emitCopyAtIndices(llvm::Type *FieldTy, llvm::ConstantInt *StoreIndex,
1467 llvm::ConstantInt *LoadIndex) {
1468 CurStoreIndices.push_back(StoreIndex);
1469 CurLoadIndices.push_back(LoadIndex);
1470 llvm::scope_exit RestoreIndices([&]() {
1471 CurStoreIndices.pop_back();
1472 CurLoadIndices.pop_back();
1476 if (processArray(FieldTy))
1478 if (processBufferLayoutArray(FieldTy))
1480 if (processStruct(FieldTy))
1488 CurLoadIndices,
"cbuf.src"),
1491 DestPtr, CurStoreIndices, FieldTy, Align,
"cbuf.dest");
1496 bool processArray(llvm::Type *FieldTy) {
1497 auto *AT = dyn_cast<llvm::ArrayType>(FieldTy);
1503 for (
unsigned I = 0, E = AT->getNumElements(); I < E; ++I)
1504 emitCopyAtIndices(AT->getElementType(),
1505 llvm::ConstantInt::get(CGF.
SizeTy, I),
1506 llvm::ConstantInt::get(CGF.
SizeTy, I));
1510 bool processBufferLayoutArray(llvm::Type *FieldTy) {
1516 auto *ST = dyn_cast<llvm::StructType>(FieldTy);
1517 if (!ST || ST->getNumElements() != 2)
1520 auto *PaddedEltsTy = dyn_cast<llvm::ArrayType>(ST->getElementType(0));
1524 auto *PaddedTy = dyn_cast<llvm::StructType>(PaddedEltsTy->getElementType());
1525 if (!PaddedTy || PaddedTy->getNumElements() != 2)
1529 PaddedTy->getElementType(1)))
1532 llvm::Type *ElementTy = ST->getElementType(1);
1533 if (PaddedTy->getElementType(0) != ElementTy)
1537 unsigned NumElts = PaddedEltsTy->getNumElements() + 1;
1541 CurLoadIndices.push_back(llvm::ConstantInt::get(CGF.
Int32Ty, 0));
1542 for (
unsigned I = 0; I < NumElts - 1; ++I) {
1544 CurLoadIndices.push_back(llvm::ConstantInt::get(CGF.
SizeTy, I));
1545 emitCopyAtIndices(ElementTy, llvm::ConstantInt::get(CGF.
SizeTy, I),
1546 llvm::ConstantInt::get(CGF.
Int32Ty, 0));
1547 CurLoadIndices.pop_back();
1549 CurLoadIndices.pop_back();
1552 emitCopyAtIndices(ElementTy,
1553 llvm::ConstantInt::get(CGF.
SizeTy, NumElts - 1),
1554 llvm::ConstantInt::get(CGF.
Int32Ty, 1));
1559 bool processStruct(llvm::Type *FieldTy) {
1560 auto *ST = dyn_cast<llvm::StructType>(FieldTy);
1565 unsigned Skipped = 0;
1566 for (
unsigned I = 0, E = ST->getNumElements(); I < E; ++I) {
1567 llvm::Type *ElementTy = ST->getElementType(I);
1571 emitCopyAtIndices(ElementTy, llvm::ConstantInt::get(CGF.
Int32Ty, I),
1572 llvm::ConstantInt::get(CGF.
Int32Ty, I + Skipped));
1578 HLSLBufferCopyEmitter(CodeGenFunction &CGF, Address DestPtr, Address SrcPtr)
1579 : CGF(CGF), DestPtr(DestPtr), SrcPtr(SrcPtr) {}
1581 bool emitCopy(QualType CType) {
1582 LayoutTy = HLSLBufferLayoutBuilder(CGF.
CGM).layOutType(CType);
1589 emitCopyAtIndices(LayoutTy, llvm::ConstantInt::get(CGF.
SizeTy, 0),
1590 llvm::ConstantInt::get(CGF.
SizeTy, 0));
1598 return HLSLBufferCopyEmitter(CGF, DestPtr, SrcPtr).emitCopy(CType);
1606 assert(Field &&
"Unexpected access into HLSL buffer");
1623 assert(FieldIdx < LayoutTy->getNumElements() &&
1624 "Layout struct is smaller than member struct");
1625 unsigned Skipped = 0;
1626 for (
unsigned I = 0; I <= FieldIdx;) {
1627 llvm::Type *ElementTy = LayoutTy->getElementType(I + Skipped);
1633 FieldIdx += Skipped;
1634 assert(FieldIdx < LayoutTy->getNumElements() &&
"Access out of bounds");
1638 QualType FieldType = Field->getType();
1644 ? CGF.
Builder.CreateStructuredGEP(
1645 LayoutTy,
Base.getPointer(CGF),
1646 llvm::ConstantInt::get(CGM.
IntTy, FieldIdx))
1648 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.
uint64_t getTypeSize(QualType T) const
Return the size of the specified (complete) type T, in bits.
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