23#include "clang/AST/Attrs.inc"
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/LLVMContext.h"
40#include "llvm/IR/Metadata.h"
41#include "llvm/IR/Module.h"
42#include "llvm/IR/Type.h"
43#include "llvm/IR/Value.h"
44#include "llvm/Support/Alignment.h"
45#include "llvm/Support/ErrorHandling.h"
46#include "llvm/Support/FormatVariadic.h"
55using llvm::hlsl::CBufferRowSizeInBytes;
59void addDxilValVersion(StringRef ValVersionStr, llvm::Module &M) {
63 if (Version.tryParse(ValVersionStr) || Version.getBuild() ||
64 Version.getSubminor() || !Version.getMinor()) {
68 uint64_t Major = Version.getMajor();
69 uint64_t Minor = *Version.getMinor();
71 auto &Ctx = M.getContext();
72 IRBuilder<> B(M.getContext());
73 MDNode *Val = MDNode::get(Ctx, {ConstantAsMetadata::get(B.getInt32(Major)),
74 ConstantAsMetadata::get(B.getInt32(Minor))});
75 StringRef DXILValKey =
"dx.valver";
76 auto *DXILValMD = M.getOrInsertNamedMetadata(DXILValKey);
77 DXILValMD->addOperand(Val);
80void addRootSignatureMD(llvm::dxbc::RootSignatureVersion RootSigVer,
82 llvm::Function *Fn, llvm::Module &M) {
83 auto &Ctx = M.getContext();
85 llvm::hlsl::rootsig::MetadataBuilder RSBuilder(Ctx, Elements);
86 MDNode *RootSignature = RSBuilder.BuildRootSignature();
88 ConstantAsMetadata *Version = ConstantAsMetadata::get(ConstantInt::get(
89 llvm::Type::getInt32Ty(Ctx), llvm::to_underlying(RootSigVer)));
90 ValueAsMetadata *EntryFunc =
Fn ? ValueAsMetadata::get(Fn) :
nullptr;
91 MDNode *MDVals = MDNode::get(Ctx, {EntryFunc, RootSignature, Version});
93 StringRef RootSignatureValKey =
"dx.rootsignatures";
94 auto *RootSignatureValMD = M.getOrInsertNamedMetadata(RootSignatureValKey);
95 RootSignatureValMD->addOperand(MDVals);
102 return DRE->getDecl();
108 const Expr *E =
nullptr;
109 while (ASE !=
nullptr) {
113 ASE = dyn_cast<ArraySubscriptExpr>(E);
115 return getArrayDecl(E);
121 assert(Ty->
isArrayType() &&
"expected array type");
127static Value *buildNameForResource(llvm::StringRef BaseName,
136 for (
auto *Method :
Record->methods()) {
137 if (Method->getStorageClass() == SC && Method->getName() == Name)
147 assert(Binding.
hasBinding() &&
"at least one binding attribute expected");
151 Value *NameStr = buildNameForResource(Name, CGM);
156 auto *RegSlot = llvm::ConstantInt::get(CGM.
IntTy, Binding.
getSlot());
159 ?
"__createFromBindingWithImplicitCounter"
160 :
"__createFromBinding";
161 CreateMethod = lookupMethod(ResourceDecl, Name,
SC_Static);
168 ?
"__createFromImplicitBindingWithImplicitCounter"
169 :
"__createFromImplicitBinding";
170 CreateMethod = lookupMethod(ResourceDecl, Name,
SC_Static);
178 auto *CounterOrderID = llvm::ConstantInt::get(CGM.
IntTy, CounterBinding);
195 CGF.
EmitCall(FnInfo, Callee, ReturnValue, Args,
nullptr);
203static std::optional<llvm::Value *> initializeLocalResourceArray(
206 llvm::Value *Range, llvm::Value *StartIndex, StringRef ResourceName,
211 llvm::IntegerType *IntTy = CGF.
CGM.
IntTy;
212 llvm::Value *Index = StartIndex;
213 llvm::Value *One = llvm::ConstantInt::get(IntTy, 1);
221 GEPIndices.push_back(llvm::ConstantInt::get(IntTy, 0));
226 for (uint64_t I = 0; I < ArraySize; I++) {
228 Index = CGF.
Builder.CreateAdd(Index, One);
229 GEPIndices.back() = llvm::ConstantInt::get(IntTy, I);
231 std::optional<llvm::Value *> MaybeIndex = initializeLocalResourceArray(
232 CGF, ResourceDecl, SubArrayTy, ValueSlot, Range, Index, ResourceName,
233 Binding, GEPIndices, ArraySubsExprLoc);
247 for (uint64_t I = 0; I < ArraySize; I++) {
249 Index = CGF.
Builder.CreateAdd(Index, One);
250 GEPIndices.back() = llvm::ConstantInt::get(IntTy, I);
256 CXXMethodDecl *CreateMethod = lookupResourceInitMethodAndSetupArgs(
257 CGF.
CGM, ResourceDecl, Range, Index, ResourceName, Binding, Args);
265 callResourceInitMethod(CGF, CreateMethod, Args, ReturnAddress);
275 assert(
T->isHLSLSpecificType() &&
"Not an HLSL specific type!");
278 if (llvm::Type *TargetTy =
279 CGM.getTargetCodeGenInfo().getHLSLType(
CGM,
T, OffsetInfo))
282 llvm_unreachable(
"Generic handling of HLSL types is not supported.");
285llvm::Triple::ArchType CGHLSLRuntime::getArch() {
291void CGHLSLRuntime::emitBufferGlobalsAndMetadata(
297 llvm::Type *BufType = BufGV->getValueType();
302 size_t OffsetIdx = 0;
312 VarDecl *VD = dyn_cast<VarDecl>(D);
328 "constant buffer decl with non-zero sized type outside of "
329 "hlsl_constant address space");
334 DeclsWithOffset.emplace_back(VD, OffsetInfo[OffsetIdx++]);
337 if (!OffsetInfo.
empty())
338 llvm::stable_sort(DeclsWithOffset, [](
const auto &LHS,
const auto &RHS) {
343 SmallVector<llvm::Metadata *> BufGlobals;
344 BufGlobals.reserve(DeclsWithOffset.size() + 1);
345 BufGlobals.push_back(ValueAsMetadata::get(BufGV));
347 auto ElemIt = LayoutStruct->element_begin();
348 for (
auto &[VD, _] : DeclsWithOffset) {
349 if (
CGM.getTargetCodeGenInfo().isHLSLPadding(*ElemIt))
352 assert(ElemIt != LayoutStruct->element_end() &&
353 "number of elements in layout struct does not match");
354 llvm::Type *LayoutType = *ElemIt++;
356 GlobalVariable *ElemGV =
358 BufGlobals.push_back(ValueAsMetadata::get(ElemGV));
360 assert(ElemIt == LayoutStruct->element_end() &&
361 "number of elements in layout struct does not match");
365 .getOrInsertNamedMetadata(
"hlsl.cbs")
366 ->addOperand(MDNode::get(Ctx, BufGlobals));
370static const clang::HLSLAttributedResourceType *
375 HLSLAttributedResourceType::Attributes(ResourceClass::CBuffer));
390 VarDecl *VD = dyn_cast<VarDecl>(D);
401 if (
auto *POA = dyn_cast<HLSLPackOffsetAttr>(
Attr)) {
402 Offset = POA->getOffsetInBytes();
405 auto *RBA = dyn_cast<HLSLResourceBindingAttr>(
Attr);
407 RBA->getRegisterType() == HLSLResourceBindingAttr::RegisterType::C) {
408 Offset = RBA->getSlotNumber() * CBufferRowSizeInBytes;
412 Result.Offsets.push_back(Offset);
420 assert(BufDecl->
isCBuffer() &&
"tbuffer codegen is not supported yet");
423 const clang::HLSLAttributedResourceType *ResHandleTy =
427 if (ResHandleTy->getContainedType()->getAsCXXRecordDecl()->isEmpty())
433 llvm::GlobalVariable *BufGV =
new GlobalVariable(
435 GlobalValue::LinkageTypes::ExternalLinkage, PoisonValue::get(LayoutTy),
436 llvm::formatv(
"{0}{1}", BufDecl->
getName(),
438 GlobalValue::NotThreadLocal);
439 CGM.getModule().insertGlobalVariable(BufGV);
442 emitBufferGlobalsAndMetadata(BufDecl, BufGV, OffsetInfo);
445 initializeBufferFromBinding(BufDecl, BufGV);
450 llvm::Module &M =
CGM.getModule();
451 Triple
T(M.getTargetTriple());
454 if (
T.getEnvironment() != Triple::EnvironmentType::RootSignature)
457 addRootSignatureMD(SignatureDecl->
getVersion(),
463 const auto Entry = LayoutTypes.find(StructType);
464 if (Entry != LayoutTypes.end())
465 return Entry->getSecond();
470 llvm::StructType *LayoutTy) {
472 "layout type for this struct already exist");
473 LayoutTypes[StructType] = LayoutTy;
477 auto &TargetOpts =
CGM.getTarget().getTargetOpts();
478 auto &CodeGenOpts =
CGM.getCodeGenOpts();
479 auto &LangOpts =
CGM.getLangOpts();
480 llvm::Module &M =
CGM.getModule();
481 Triple
T(M.getTargetTriple());
482 if (
T.getArch() == Triple::ArchType::dxil)
483 addDxilValVersion(TargetOpts.DxilValidatorVersion, M);
484 if (CodeGenOpts.ResMayAlias)
485 M.setModuleFlag(llvm::Module::ModFlagBehavior::Error,
"dx.resmayalias", 1);
486 if (CodeGenOpts.AllResourcesBound)
487 M.setModuleFlag(llvm::Module::ModFlagBehavior::Error,
488 "dx.allresourcesbound", 1);
492 if (LangOpts.NativeHalfType)
493 M.setModuleFlag(llvm::Module::ModFlagBehavior::Error,
"dx.nativelowprec",
501 const auto *ShaderAttr = FD->
getAttr<HLSLShaderAttr>();
502 assert(ShaderAttr &&
"All entry functions must have a HLSLShaderAttr");
503 const StringRef ShaderAttrKindStr =
"hlsl.shader";
504 Fn->addFnAttr(ShaderAttrKindStr,
505 llvm::Triple::getEnvironmentTypeName(ShaderAttr->getType()));
506 if (HLSLNumThreadsAttr *NumThreadsAttr = FD->
getAttr<HLSLNumThreadsAttr>()) {
507 const StringRef NumThreadsKindStr =
"hlsl.numthreads";
508 std::string NumThreadsStr =
509 formatv(
"{0},{1},{2}", NumThreadsAttr->getX(), NumThreadsAttr->getY(),
510 NumThreadsAttr->getZ());
511 Fn->addFnAttr(NumThreadsKindStr, NumThreadsStr);
513 if (HLSLWaveSizeAttr *WaveSizeAttr = FD->
getAttr<HLSLWaveSizeAttr>()) {
514 const StringRef WaveSizeKindStr =
"hlsl.wavesize";
515 std::string WaveSizeStr =
516 formatv(
"{0},{1},{2}", WaveSizeAttr->getMin(), WaveSizeAttr->getMax(),
517 WaveSizeAttr->getPreferred());
518 Fn->addFnAttr(WaveSizeKindStr, WaveSizeStr);
525 if (
CGM.getCodeGenOpts().OptimizationLevel == 0)
526 Fn->addFnAttr(llvm::Attribute::OptimizeNone);
527 Fn->addFnAttr(llvm::Attribute::NoInline);
529 if (
CGM.getLangOpts().HLSLSpvEnableMaximalReconvergence) {
530 Fn->addFnAttr(
"enable-maximal-reconvergence",
"true");
535 if (
const auto *VT = dyn_cast<FixedVectorType>(Ty)) {
536 Value *Result = PoisonValue::get(Ty);
537 for (
unsigned I = 0; I < VT->getNumElements(); ++I) {
538 Value *Elt = B.CreateCall(F, {B.getInt32(I)});
539 Result = B.CreateInsertElement(Result, Elt, I);
543 return B.CreateCall(F, {B.getInt32(0)});
548 LLVMContext &Ctx = GV->getContext();
549 IRBuilder<> B(GV->getContext());
550 MDNode *Operands = MDNode::get(
552 {ConstantAsMetadata::get(B.getInt32( 11)),
553 ConstantAsMetadata::get(B.getInt32(BuiltIn))});
554 MDNode *Decoration = MDNode::get(Ctx, {Operands});
555 GV->addMetadata(
"spirv.Decorations", *Decoration);
559 LLVMContext &Ctx = GV->getContext();
560 IRBuilder<> B(GV->getContext());
562 MDNode::get(Ctx, {ConstantAsMetadata::get(B.getInt32( 30)),
563 ConstantAsMetadata::get(B.getInt32(Location))});
564 MDNode *Decoration = MDNode::get(Ctx, {Operands});
565 GV->addMetadata(
"spirv.Decorations", *Decoration);
569 llvm::Type *Ty,
const Twine &Name,
570 unsigned BuiltInID) {
571 auto *GV =
new llvm::GlobalVariable(
572 M, Ty,
true, llvm::GlobalValue::ExternalLinkage,
573 nullptr, Name,
nullptr,
574 llvm::GlobalVariable::GeneralDynamicTLSModel,
577 GV->setVisibility(llvm::GlobalValue::HiddenVisibility);
578 return B.CreateLoad(Ty, GV);
582 llvm::Type *Ty,
unsigned Location,
584 auto *GV =
new llvm::GlobalVariable(
585 M, Ty,
true, llvm::GlobalValue::ExternalLinkage,
586 nullptr, Name,
nullptr,
587 llvm::GlobalVariable::GeneralDynamicTLSModel,
589 GV->setVisibility(llvm::GlobalValue::HiddenVisibility);
591 return B.CreateLoad(Ty, GV);
594llvm::Value *CGHLSLRuntime::emitSPIRVUserSemanticLoad(
595 llvm::IRBuilder<> &B, llvm::Type *
Type,
const clang::DeclaratorDecl *
Decl,
596 HLSLAppliedSemanticAttr *Semantic, std::optional<unsigned> Index) {
597 Twine BaseName = Twine(Semantic->getAttrName()->getName());
598 Twine VariableName = BaseName.concat(Twine(Index.value_or(0)));
600 unsigned Location = SPIRVLastAssignedInputSemanticLocation;
601 if (
auto *L =
Decl->getAttr<HLSLVkLocationAttr>())
602 Location = L->getLocation();
606 llvm::ArrayType *AT = dyn_cast<llvm::ArrayType>(
Type);
607 unsigned ElementCount = AT ? AT->getNumElements() : 1;
608 SPIRVLastAssignedInputSemanticLocation += ElementCount;
615 llvm::Value *Source,
unsigned Location,
617 auto *GV =
new llvm::GlobalVariable(
618 M, Source->getType(),
false,
619 llvm::GlobalValue::ExternalLinkage,
620 nullptr, Name,
nullptr,
621 llvm::GlobalVariable::GeneralDynamicTLSModel,
623 GV->setVisibility(llvm::GlobalValue::HiddenVisibility);
625 B.CreateStore(Source, GV);
628void CGHLSLRuntime::emitSPIRVUserSemanticStore(
629 llvm::IRBuilder<> &B, llvm::Value *Source,
630 const clang::DeclaratorDecl *
Decl, HLSLAppliedSemanticAttr *Semantic,
631 std::optional<unsigned> Index) {
632 Twine BaseName = Twine(Semantic->getAttrName()->getName());
633 Twine VariableName = BaseName.concat(Twine(Index.value_or(0)));
635 unsigned Location = SPIRVLastAssignedOutputSemanticLocation;
636 if (
auto *L =
Decl->getAttr<HLSLVkLocationAttr>())
637 Location = L->getLocation();
641 llvm::ArrayType *AT = dyn_cast<llvm::ArrayType>(Source->getType());
642 unsigned ElementCount = AT ? AT->getNumElements() : 1;
643 SPIRVLastAssignedOutputSemanticLocation += ElementCount;
649CGHLSLRuntime::emitDXILUserSemanticLoad(llvm::IRBuilder<> &B, llvm::Type *
Type,
650 HLSLAppliedSemanticAttr *Semantic,
651 std::optional<unsigned> Index) {
652 Twine BaseName = Twine(Semantic->getAttrName()->getName());
653 Twine VariableName = BaseName.concat(Twine(Index.value_or(0)));
658 SmallVector<Value *> Args{B.getInt32(4), B.getInt32(0), B.getInt32(0),
660 llvm::PoisonValue::get(B.getInt32Ty())};
662 llvm::Intrinsic::ID IntrinsicID = llvm::Intrinsic::dx_load_input;
663 llvm::Value *
Value = B.CreateIntrinsic(
Type, IntrinsicID, Args,
664 nullptr, VariableName);
668void CGHLSLRuntime::emitDXILUserSemanticStore(llvm::IRBuilder<> &B,
670 HLSLAppliedSemanticAttr *Semantic,
671 std::optional<unsigned> Index) {
674 SmallVector<Value *> Args{B.getInt32(4),
678 llvm::PoisonValue::get(B.getInt32Ty()),
681 llvm::Intrinsic::ID IntrinsicID = llvm::Intrinsic::dx_store_output;
682 B.CreateIntrinsic(
CGM.VoidTy, IntrinsicID, Args,
nullptr);
685llvm::Value *CGHLSLRuntime::emitUserSemanticLoad(
686 IRBuilder<> &B, llvm::Type *
Type,
const clang::DeclaratorDecl *
Decl,
687 HLSLAppliedSemanticAttr *Semantic, std::optional<unsigned> Index) {
688 if (
CGM.getTarget().getTriple().isSPIRV())
689 return emitSPIRVUserSemanticLoad(B,
Type,
Decl, Semantic, Index);
691 if (
CGM.getTarget().getTriple().isDXIL())
692 return emitDXILUserSemanticLoad(B,
Type, Semantic, Index);
694 llvm_unreachable(
"Unsupported target for user-semantic load.");
697void CGHLSLRuntime::emitUserSemanticStore(IRBuilder<> &B, llvm::Value *Source,
698 const clang::DeclaratorDecl *
Decl,
699 HLSLAppliedSemanticAttr *Semantic,
700 std::optional<unsigned> Index) {
701 if (
CGM.getTarget().getTriple().isSPIRV())
702 return emitSPIRVUserSemanticStore(B, Source,
Decl, Semantic, Index);
704 if (
CGM.getTarget().getTriple().isDXIL())
705 return emitDXILUserSemanticStore(B, Source, Semantic, Index);
707 llvm_unreachable(
"Unsupported target for user-semantic load.");
713 std::optional<unsigned> Index) {
715 std::string SemanticName = Semantic->getAttrName()->getName().upper();
716 if (SemanticName ==
"SV_GROUPINDEX") {
717 llvm::Function *GroupIndex =
718 CGM.getIntrinsic(getFlattenedThreadIdInGroupIntrinsic());
719 return B.CreateCall(FunctionCallee(GroupIndex));
722 if (SemanticName ==
"SV_DISPATCHTHREADID") {
723 llvm::Intrinsic::ID IntrinID = getThreadIdIntrinsic();
724 llvm::Function *ThreadIDIntrinsic =
725 llvm::Intrinsic::isOverloaded(IntrinID)
726 ?
CGM.getIntrinsic(IntrinID, {
CGM.Int32Ty})
727 :
CGM.getIntrinsic(IntrinID);
731 if (SemanticName ==
"SV_GROUPTHREADID") {
732 llvm::Intrinsic::ID IntrinID = getGroupThreadIdIntrinsic();
733 llvm::Function *GroupThreadIDIntrinsic =
734 llvm::Intrinsic::isOverloaded(IntrinID)
735 ?
CGM.getIntrinsic(IntrinID, {
CGM.Int32Ty})
736 :
CGM.getIntrinsic(IntrinID);
740 if (SemanticName ==
"SV_GROUPID") {
741 llvm::Intrinsic::ID IntrinID = getGroupIdIntrinsic();
742 llvm::Function *GroupIDIntrinsic =
743 llvm::Intrinsic::isOverloaded(IntrinID)
744 ?
CGM.getIntrinsic(IntrinID, {
CGM.Int32Ty})
745 :
CGM.getIntrinsic(IntrinID);
749 const auto *ShaderAttr = FD->
getAttr<HLSLShaderAttr>();
750 assert(ShaderAttr &&
"Entry point has no shader attribute");
751 llvm::Triple::EnvironmentType ST = ShaderAttr->getType();
753 if (SemanticName ==
"SV_POSITION") {
754 if (ST == Triple::EnvironmentType::Pixel) {
755 if (
CGM.getTarget().getTriple().isSPIRV())
757 Semantic->getAttrName()->getName(),
759 if (
CGM.getTarget().getTriple().isDXIL())
760 return emitDXILUserSemanticLoad(B,
Type, Semantic, Index);
763 if (ST == Triple::EnvironmentType::Vertex) {
764 return emitUserSemanticLoad(B,
Type,
Decl, Semantic, Index);
769 "Load hasn't been implemented yet for this system semantic. FIXME");
773 llvm::Value *Source,
const Twine &Name,
774 unsigned BuiltInID) {
775 auto *GV =
new llvm::GlobalVariable(
776 M, Source->getType(),
false,
777 llvm::GlobalValue::ExternalLinkage,
778 nullptr, Name,
nullptr,
779 llvm::GlobalVariable::GeneralDynamicTLSModel,
782 GV->setVisibility(llvm::GlobalValue::HiddenVisibility);
783 B.CreateStore(Source, GV);
788 HLSLAppliedSemanticAttr *Semantic,
789 std::optional<unsigned> Index) {
791 std::string SemanticName = Semantic->getAttrName()->getName().upper();
792 if (SemanticName ==
"SV_POSITION") {
793 if (
CGM.getTarget().getTriple().isDXIL()) {
794 emitDXILUserSemanticStore(B, Source, Semantic, Index);
798 if (
CGM.getTarget().getTriple().isSPIRV()) {
800 Semantic->getAttrName()->getName(),
806 if (SemanticName ==
"SV_TARGET") {
807 emitUserSemanticStore(B, Source,
Decl, Semantic, Index);
812 "Store hasn't been implemented yet for this system semantic. FIXME");
819 std::optional<unsigned> Index = Semantic->getSemanticIndex();
820 if (Semantic->getAttrName()->getName().starts_with_insensitive(
"SV_"))
822 return emitUserSemanticLoad(B,
Type,
Decl, Semantic, Index);
826 IRBuilder<> &B,
const FunctionDecl *FD, llvm::Value *Source,
828 std::optional<unsigned> Index = Semantic->getSemanticIndex();
829 if (Semantic->getAttrName()->getName().starts_with_insensitive(
"SV_"))
832 emitUserSemanticStore(B, Source,
Decl, Semantic, Index);
835std::pair<llvm::Value *, specific_attr_iterator<HLSLAppliedSemanticAttr>>
848 for (
unsigned I = 0; I < ST->getNumElements(); ++I) {
850 B, FD, ST->getElementType(I), *
FieldDecl, AttrBegin, AttrEnd);
851 AttrBegin = NextAttr;
857 return std::make_pair(
Aggregate, AttrBegin);
862 IRBuilder<> &B,
const FunctionDecl *FD, llvm::Value *Source,
873 RD =
Decl->getType()->getAsRecordDecl();
879 for (
unsigned I = 0; I < ST->getNumElements(); ++I) {
880 llvm::Value *Extract = B.CreateExtractValue(Source, I);
888std::pair<llvm::Value *, specific_attr_iterator<HLSLAppliedSemanticAttr>>
894 assert(AttrBegin != AttrEnd);
895 if (
Type->isStructTy())
898 HLSLAppliedSemanticAttr *
Attr = *AttrBegin;
906 IRBuilder<> &B,
const FunctionDecl *FD, llvm::Value *Source,
910 assert(AttrBegin != AttrEnd);
911 if (Source->getType()->isStructTy())
914 HLSLAppliedSemanticAttr *
Attr = *AttrBegin;
921 llvm::Function *Fn) {
922 llvm::Module &M =
CGM.getModule();
923 llvm::LLVMContext &Ctx = M.getContext();
924 auto *EntryTy = llvm::FunctionType::get(llvm::Type::getVoidTy(Ctx),
false);
926 Function::Create(EntryTy, Function::ExternalLinkage, FD->
getName(), &M);
930 AttributeList NewAttrs = AttributeList::get(Ctx, AttributeList::FunctionIndex,
931 Fn->getAttributes().getFnAttrs());
932 EntryFn->setAttributes(NewAttrs);
936 Fn->setLinkage(GlobalValue::InternalLinkage);
938 BasicBlock *BB = BasicBlock::Create(Ctx,
"entry", EntryFn);
943 if (
CGM.shouldEmitConvergenceTokens()) {
944 assert(EntryFn->isConvergent());
946 B.CreateIntrinsic(llvm::Intrinsic::experimental_convergence_entry, {});
947 llvm::Value *bundleArgs[] = {I};
948 OB.emplace_back(
"convergencectrl", bundleArgs);
951 llvm::DenseMap<const DeclaratorDecl *, llvm::Value *> OutputSemantic;
953 unsigned SRetOffset = 0;
954 for (
const auto &Param : Fn->args()) {
955 if (Param.hasStructRetAttr()) {
957 llvm::Type *VarType = Param.getParamStructRetType();
958 llvm::Value *Var = B.CreateAlloca(VarType);
959 OutputSemantic.try_emplace(FD, Var);
965 llvm::Value *SemanticValue =
nullptr;
967 if ([[maybe_unused]] HLSLParamModifierAttr *MA =
968 PD->
getAttr<HLSLParamModifierAttr>()) {
969 llvm_unreachable(
"Not handled yet");
971 llvm::Type *ParamType =
972 Param.hasByValAttr() ? Param.getParamByValType() : Param.getType();
977 SemanticValue =
Result.first;
980 if (Param.hasByValAttr()) {
981 llvm::Value *Var = B.CreateAlloca(Param.getParamByValType());
982 B.CreateStore(SemanticValue, Var);
987 assert(SemanticValue);
988 Args.push_back(SemanticValue);
991 CallInst *CI = B.CreateCall(FunctionCallee(Fn), Args, OB);
992 CI->setCallingConv(Fn->getCallingConv());
994 if (Fn->getReturnType() !=
CGM.VoidTy)
995 OutputSemantic.try_emplace(FD, CI);
997 for (
auto &[
Decl, Source] : OutputSemantic) {
998 AllocaInst *AI = dyn_cast<AllocaInst>(Source);
999 llvm::Value *SourceValue =
1000 AI ? B.CreateLoad(AI->getAllocatedType(), Source) : Source;
1002 auto AttrBegin =
Decl->specific_attr_begin<HLSLAppliedSemanticAttr>();
1003 auto AttrEnd =
Decl->specific_attr_end<HLSLAppliedSemanticAttr>();
1011 if (
const auto *RSAttr = dyn_cast<RootSignatureAttr>(
Attr)) {
1012 auto *RSDecl = RSAttr->getSignatureDecl();
1013 addRootSignatureMD(RSDecl->getVersion(), RSDecl->getRootElements(),
1022 M.getNamedGlobal(CtorOrDtor ?
"llvm.global_ctors" :
"llvm.global_dtors");
1025 const auto *CA = dyn_cast<ConstantArray>(GV->getInitializer());
1032 for (
const auto &Ctor : CA->operands()) {
1038 "HLSL doesn't support setting priority for global ctors.");
1040 "HLSL doesn't support COMDat for global ctors.");
1046 llvm::Module &M =
CGM.getModule();
1055 for (
auto &F : M.functions()) {
1056 if (!F.hasFnAttribute(
"hlsl.shader"))
1059 Instruction *IP = &*F.getEntryBlock().begin();
1062 llvm::Value *bundleArgs[] = {
Token};
1063 OB.emplace_back(
"convergencectrl", bundleArgs);
1064 IP =
Token->getNextNode();
1067 for (
auto *Fn : CtorFns) {
1068 auto CI = B.CreateCall(FunctionCallee(Fn), {}, OB);
1069 CI->setCallingConv(Fn->getCallingConv());
1073 B.SetInsertPoint(F.back().getTerminator());
1074 for (
auto *Fn : DtorFns) {
1075 auto CI = B.CreateCall(FunctionCallee(Fn), {}, OB);
1076 CI->setCallingConv(Fn->getCallingConv());
1082 Triple
T(M.getTargetTriple());
1083 if (
T.getEnvironment() != Triple::EnvironmentType::Library) {
1084 if (
auto *GV = M.getNamedGlobal(
"llvm.global_ctors"))
1085 GV->eraseFromParent();
1086 if (
auto *GV = M.getNamedGlobal(
"llvm.global_dtors"))
1087 GV->eraseFromParent();
1092 Intrinsic::ID IntrID,
1096 llvm::Function *InitResFunc = llvm::Function::Create(
1097 llvm::FunctionType::get(CGM.
VoidTy,
false),
1098 llvm::GlobalValue::InternalLinkage,
1099 (
"_init_buffer_" + GV->getName()).str(), CGM.
getModule());
1100 InitResFunc->addFnAttr(llvm::Attribute::AlwaysInline);
1102 llvm::BasicBlock *EntryBB =
1103 llvm::BasicBlock::Create(Ctx,
"entry", InitResFunc);
1105 const DataLayout &DL = CGM.
getModule().getDataLayout();
1106 Builder.SetInsertPoint(EntryBB);
1109 llvm::Type *HandleTy = GV->getValueType();
1110 assert(HandleTy->isTargetExtTy() &&
"unexpected type of the buffer global");
1112 llvm::Value *CreateHandle = Builder.CreateIntrinsic(
1113 HandleTy, IntrID, Args,
nullptr,
1114 Twine(GV->getName()).concat(
"_h"));
1116 llvm::Value *HandleRef = Builder.CreateStructGEP(GV->getValueType(), GV, 0);
1117 Builder.CreateAlignedStore(CreateHandle, HandleRef,
1118 HandleRef->getPointerAlignment(DL));
1119 Builder.CreateRetVoid();
1124void CGHLSLRuntime::initializeBufferFromBinding(
const HLSLBufferDecl *BufDecl,
1125 llvm::GlobalVariable *GV) {
1126 ResourceBindingAttrs Binding(BufDecl);
1128 "cbuffer/tbuffer should always have resource binding attribute");
1130 auto *Index = llvm::ConstantInt::get(
CGM.IntTy, 0);
1131 auto *RangeSize = llvm::ConstantInt::get(
CGM.IntTy, 1);
1132 auto *Space = llvm::ConstantInt::get(
CGM.IntTy, Binding.
getSpace());
1137 llvm::Intrinsic::ID IntrinsicID =
1138 CGM.getHLSLRuntime().getCreateHandleFromBindingIntrinsic();
1139 auto *RegSlot = llvm::ConstantInt::get(
CGM.IntTy, Binding.
getSlot());
1140 SmallVector<Value *> Args{Space, RegSlot, RangeSize, Index, Name};
1144 llvm::Intrinsic::ID IntrinsicID =
1145 CGM.getHLSLRuntime().getCreateHandleFromImplicitBindingIntrinsic();
1148 SmallVector<Value *> Args{OrderID, Space, RangeSize, Index, Name};
1154 llvm::GlobalVariable *GV) {
1155 if (
auto Attr = VD->
getAttr<HLSLVkExtBuiltinInputAttr>())
1160 if (!
CGM.shouldEmitConvergenceTokens())
1164 for (
auto I = BB.begin(); I != E; ++I) {
1165 auto *II = dyn_cast<llvm::IntrinsicInst>(&*I);
1166 if (II && llvm::isConvergenceControlIntrinsic(II->getIntrinsicID())) {
1170 llvm_unreachable(
"Convergence token should have been emitted.");
1207 for (
auto *OVE : Visitor.
OVEs) {
1210 if (OpaqueValueMappingData::shouldBindAsLValue(OVE)) {
1212 OpaqueValueMappingData::bind(CGF, OVE, LV);
1215 OpaqueValueMappingData::bind(CGF, OVE, RV);
1224 "expected resource array subscript expression");
1230 dyn_cast_or_null<VarDecl>(getArrayDecl(ArraySubsExpr));
1233 return std::nullopt;
1239 "expected array of resource classes");
1245 Value *Index =
nullptr;
1247 while (ASE !=
nullptr) {
1249 if (
const auto *ArrayTy =
1251 Value *Multiplier = llvm::ConstantInt::get(
1253 SubIndex = CGF.
Builder.CreateMul(SubIndex, Multiplier);
1255 Index = Index ? CGF.
Builder.CreateAdd(Index, SubIndex) : SubIndex;
1263 "resource array must have a binding attribute");
1284 llvm::Value *Range = llvm::ConstantInt::getSigned(
1285 CGM.IntTy, getTotalArraySize(AST, ResArrayTy));
1289 if (ResultTy == ResourceTy) {
1291 CXXMethodDecl *CreateMethod = lookupResourceInitMethodAndSetupArgs(
1293 ArrayDecl->
getName(), Binding, Args);
1299 return std::nullopt;
1301 callResourceInitMethod(CGF, CreateMethod, Args, ValueSlot.getAddress());
1308 std::optional<llvm::Value *> EndIndex = initializeLocalResourceArray(
1310 ArrayDecl->
getName(), Binding, {llvm::ConstantInt::get(CGM.IntTy, 0)},
1313 return std::nullopt;
1327 const VarDecl *ArrayDecl = dyn_cast_or_null<VarDecl>(getArrayDecl(RHSExpr));
1336 "resource array must have a binding attribute");
1350 int Size = getTotalArraySize(AST, ResArrayTy);
1351 llvm::Value *
Zero = llvm::ConstantInt::get(
CGM.IntTy, 0);
1352 llvm::Value *Range = llvm::ConstantInt::get(
CGM.IntTy, Size);
1355 std::optional<llvm::Value *> EndIndex = initializeLocalResourceArray(
1358 return EndIndex.has_value();
1363 llvm::function_ref<llvm::Value *(
bool Promote)> EmitIdxAfterBase) {
1367 llvm::Type *LayoutTy =
1369 uint64_t LayoutSizeInBits =
1370 CGM.getDataLayout().getTypeSizeInBits(LayoutTy).getFixedValue();
1373 if (RowAlignedSize > ElementSize) {
1374 llvm::Type *Padding =
CGM.getTargetCodeGenInfo().getHLSLPadding(
1375 CGM, RowAlignedSize - ElementSize);
1376 assert(Padding &&
"No padding type for target?");
1377 LayoutTy = llvm::StructType::get(CGF.
getLLVMContext(), {LayoutTy, Padding},
1384 if (LayoutTy == OrigTy)
1385 return std::nullopt;
1391 llvm::Value *Idx = EmitIdxAfterBase(
true);
1397 Indices.push_back(Idx);
1398 Indices.push_back(llvm::ConstantInt::get(CGF.
Int32Ty, 0));
1401 Indices,
"cbufferidx");
1410class HLSLBufferCopyEmitter {
1414 llvm::Type *LayoutTy =
nullptr;
1419 void emitCopyAtIndices(llvm::Type *FieldTy, llvm::ConstantInt *StoreIndex,
1420 llvm::ConstantInt *LoadIndex) {
1421 CurStoreIndices.push_back(StoreIndex);
1422 CurLoadIndices.push_back(LoadIndex);
1423 llvm::scope_exit RestoreIndices([&]() {
1424 CurStoreIndices.pop_back();
1425 CurLoadIndices.pop_back();
1429 if (processArray(FieldTy))
1431 if (processBufferLayoutArray(FieldTy))
1433 if (processStruct(FieldTy))
1441 CurLoadIndices,
"cbuf.src"),
1444 DestPtr, CurStoreIndices, FieldTy, Align,
"cbuf.dest");
1449 bool processArray(llvm::Type *FieldTy) {
1450 auto *AT = dyn_cast<llvm::ArrayType>(FieldTy);
1456 for (
unsigned I = 0, E = AT->getNumElements(); I < E; ++I)
1457 emitCopyAtIndices(AT->getElementType(),
1458 llvm::ConstantInt::get(CGF.
SizeTy, I),
1459 llvm::ConstantInt::get(CGF.
SizeTy, I));
1463 bool processBufferLayoutArray(llvm::Type *FieldTy) {
1469 auto *ST = dyn_cast<llvm::StructType>(FieldTy);
1470 if (!ST || ST->getNumElements() != 2)
1473 auto *PaddedEltsTy = dyn_cast<llvm::ArrayType>(ST->getElementType(0));
1477 auto *PaddedTy = dyn_cast<llvm::StructType>(PaddedEltsTy->getElementType());
1478 if (!PaddedTy || PaddedTy->getNumElements() != 2)
1482 PaddedTy->getElementType(1)))
1485 llvm::Type *ElementTy = ST->getElementType(1);
1486 if (PaddedTy->getElementType(0) != ElementTy)
1490 unsigned NumElts = PaddedEltsTy->getNumElements() + 1;
1494 CurLoadIndices.push_back(llvm::ConstantInt::get(CGF.
Int32Ty, 0));
1495 for (
unsigned I = 0; I < NumElts - 1; ++I) {
1497 CurLoadIndices.push_back(llvm::ConstantInt::get(CGF.
SizeTy, I));
1498 emitCopyAtIndices(ElementTy, llvm::ConstantInt::get(CGF.
SizeTy, I),
1499 llvm::ConstantInt::get(CGF.
Int32Ty, 0));
1500 CurLoadIndices.pop_back();
1502 CurLoadIndices.pop_back();
1505 emitCopyAtIndices(ElementTy,
1506 llvm::ConstantInt::get(CGF.
SizeTy, NumElts - 1),
1507 llvm::ConstantInt::get(CGF.
Int32Ty, 1));
1512 bool processStruct(llvm::Type *FieldTy) {
1513 auto *ST = dyn_cast<llvm::StructType>(FieldTy);
1518 unsigned Skipped = 0;
1519 for (
unsigned I = 0, E = ST->getNumElements(); I < E; ++I) {
1520 llvm::Type *ElementTy = ST->getElementType(I);
1524 emitCopyAtIndices(ElementTy, llvm::ConstantInt::get(CGF.
Int32Ty, I),
1525 llvm::ConstantInt::get(CGF.
Int32Ty, I + Skipped));
1531 HLSLBufferCopyEmitter(CodeGenFunction &CGF, Address DestPtr, Address SrcPtr)
1532 : CGF(CGF), DestPtr(DestPtr), SrcPtr(SrcPtr) {}
1534 bool emitCopy(QualType CType) {
1535 LayoutTy = HLSLBufferLayoutBuilder(CGF.
CGM).layOutType(CType);
1542 emitCopyAtIndices(LayoutTy, llvm::ConstantInt::get(CGF.
SizeTy, 0),
1543 llvm::ConstantInt::get(CGF.
SizeTy, 0));
1551 return HLSLBufferCopyEmitter(CGF, DestPtr, SrcPtr).emitCopy(CType);
1559 assert(Field &&
"Unexpected access into HLSL buffer");
1564 CGM.getTypes().getCGRecordLayout(Rec).getLLVMFieldNo(Field);
1567 QualType RecType =
CGM.getContext().getCanonicalTagType(Rec);
1578 QualType FieldType = Field->getType();
1579 llvm::Type *FieldLLVMTy =
CGM.getTypes().ConvertTypeForMem(FieldType);
1583 FieldIdx, Field->getName()),
1588 CGM.getTBAAAccessInfo(FieldType));
Defines the clang::ASTContext interface.
static llvm::Value * createSPIRVBuiltinLoad(IRBuilder<> &B, llvm::Module &M, llvm::Type *Ty, const Twine &Name, unsigned BuiltInID)
static 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.
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)
llvm::Value * emitSystemSemanticLoad(llvm::IRBuilder<> &B, const FunctionDecl *FD, llvm::Type *Type, const clang::DeclaratorDecl *Decl, HLSLAppliedSemanticAttr *Semantic, std::optional< unsigned > Index)
void addBuffer(const HLSLBufferDecl *D)
void generateGlobalCtorDtorCalls()
void emitInitListOpaqueValues(CodeGenFunction &CGF, InitListExpr *E)
CallArgList - Type for representing both the value and type of arguments in a call.
void add(RValue rvalue, QualType type)
A non-RAII class containing all the information about a bound opaque value.
CodeGenFunction - This class organizes the per-function state that is used while generating LLVM code...
@ 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.
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.
llvm::Module & getModule() const
llvm::Constant * GetAddrOfFunction(GlobalDecl GD, llvm::Type *Ty=nullptr, bool ForVTable=false, bool DontDefer=false, ForDefinition_t IsForDefinition=NotForDefinition)
Return the address of the given function.
void AddCXXGlobalInit(llvm::Function *F)
CodeGenTypes & getTypes()
const TargetInfo & getTarget() const
void EmitGlobal(GlobalDecl D)
Emit code for a single global function or var decl.
const llvm::DataLayout & getDataLayout() const
ASTContext & getContext() const
const TargetCodeGenInfo & getTargetCodeGenInfo()
llvm::LLVMContext & getLLVMContext()
void EmitTopLevelDecl(Decl *D)
Emit code for a single top level declaration.
ConstantAddress GetAddrOfConstantCString(const std::string &Str, StringRef GlobalName=".str")
Returns a pointer to a character array containing the literal and a terminating '\0' character.
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.
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.
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 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.
const FunctionProtoType * T
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