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 Builder.CreateAlignedStore(CreateHandle, GV, GV->getPointerAlignment(DL));
1117 Builder.CreateRetVoid();
1122void CGHLSLRuntime::initializeBufferFromBinding(
const HLSLBufferDecl *BufDecl,
1123 llvm::GlobalVariable *GV) {
1124 ResourceBindingAttrs Binding(BufDecl);
1126 "cbuffer/tbuffer should always have resource binding attribute");
1128 auto *Index = llvm::ConstantInt::get(
CGM.IntTy, 0);
1129 auto *RangeSize = llvm::ConstantInt::get(
CGM.IntTy, 1);
1130 auto *Space = llvm::ConstantInt::get(
CGM.IntTy, Binding.
getSpace());
1135 llvm::Intrinsic::ID IntrinsicID =
1136 CGM.getHLSLRuntime().getCreateHandleFromBindingIntrinsic();
1137 auto *RegSlot = llvm::ConstantInt::get(
CGM.IntTy, Binding.
getSlot());
1138 SmallVector<Value *> Args{Space, RegSlot, RangeSize, Index, Name};
1142 llvm::Intrinsic::ID IntrinsicID =
1143 CGM.getHLSLRuntime().getCreateHandleFromImplicitBindingIntrinsic();
1146 SmallVector<Value *> Args{OrderID, Space, RangeSize, Index, Name};
1152 llvm::GlobalVariable *GV) {
1153 if (
auto Attr = VD->
getAttr<HLSLVkExtBuiltinInputAttr>())
1158 if (!
CGM.shouldEmitConvergenceTokens())
1162 for (
auto I = BB.begin(); I != E; ++I) {
1163 auto *II = dyn_cast<llvm::IntrinsicInst>(&*I);
1164 if (II && llvm::isConvergenceControlIntrinsic(II->getIntrinsicID())) {
1168 llvm_unreachable(
"Convergence token should have been emitted.");
1205 for (
auto *OVE : Visitor.
OVEs) {
1208 if (OpaqueValueMappingData::shouldBindAsLValue(OVE)) {
1210 OpaqueValueMappingData::bind(CGF, OVE, LV);
1213 OpaqueValueMappingData::bind(CGF, OVE, RV);
1222 "expected resource array subscript expression");
1228 dyn_cast_or_null<VarDecl>(getArrayDecl(ArraySubsExpr));
1231 return std::nullopt;
1237 "expected array of resource classes");
1243 Value *Index =
nullptr;
1245 while (ASE !=
nullptr) {
1247 if (
const auto *ArrayTy =
1249 Value *Multiplier = llvm::ConstantInt::get(
1251 SubIndex = CGF.
Builder.CreateMul(SubIndex, Multiplier);
1253 Index = Index ? CGF.
Builder.CreateAdd(Index, SubIndex) : SubIndex;
1261 "resource array must have a binding attribute");
1282 llvm::Value *Range = llvm::ConstantInt::getSigned(
1283 CGM.IntTy, getTotalArraySize(AST, ResArrayTy));
1287 if (ResultTy == ResourceTy) {
1289 CXXMethodDecl *CreateMethod = lookupResourceInitMethodAndSetupArgs(
1291 ArrayDecl->
getName(), Binding, Args);
1297 return std::nullopt;
1299 callResourceInitMethod(CGF, CreateMethod, Args, ValueSlot.getAddress());
1306 std::optional<llvm::Value *> EndIndex = initializeLocalResourceArray(
1308 ArrayDecl->
getName(), Binding, {llvm::ConstantInt::get(CGM.IntTy, 0)},
1311 return std::nullopt;
1325 const VarDecl *ArrayDecl = dyn_cast_or_null<VarDecl>(getArrayDecl(RHSExpr));
1334 "resource array must have a binding attribute");
1348 int Size = getTotalArraySize(AST, ResArrayTy);
1349 llvm::Value *
Zero = llvm::ConstantInt::get(
CGM.IntTy, 0);
1350 llvm::Value *Range = llvm::ConstantInt::get(
CGM.IntTy, Size);
1353 std::optional<llvm::Value *> EndIndex = initializeLocalResourceArray(
1356 return EndIndex.has_value();
1361 llvm::function_ref<llvm::Value *(
bool Promote)> EmitIdxAfterBase) {
1365 llvm::Type *LayoutTy =
1367 uint64_t LayoutSizeInBits =
1368 CGM.getDataLayout().getTypeSizeInBits(LayoutTy).getFixedValue();
1371 if (RowAlignedSize > ElementSize) {
1372 llvm::Type *Padding =
CGM.getTargetCodeGenInfo().getHLSLPadding(
1373 CGM, RowAlignedSize - ElementSize);
1374 assert(Padding &&
"No padding type for target?");
1375 LayoutTy = llvm::StructType::get(CGF.
getLLVMContext(), {LayoutTy, Padding},
1382 if (LayoutTy == OrigTy)
1383 return std::nullopt;
1389 llvm::Value *Idx = EmitIdxAfterBase(
true);
1395 Indices.push_back(Idx);
1396 Indices.push_back(llvm::ConstantInt::get(CGF.
Int32Ty, 0));
1399 Indices,
"cbufferidx");
1408class HLSLBufferCopyEmitter {
1412 llvm::Type *LayoutTy =
nullptr;
1417 void emitCopyAtIndices(llvm::Type *FieldTy, llvm::ConstantInt *StoreIndex,
1418 llvm::ConstantInt *LoadIndex) {
1419 CurStoreIndices.push_back(StoreIndex);
1420 CurLoadIndices.push_back(LoadIndex);
1421 llvm::scope_exit RestoreIndices([&]() {
1422 CurStoreIndices.pop_back();
1423 CurLoadIndices.pop_back();
1427 if (processArray(FieldTy))
1429 if (processBufferLayoutArray(FieldTy))
1431 if (processStruct(FieldTy))
1439 CurLoadIndices,
"cbuf.src"),
1442 DestPtr, CurStoreIndices, FieldTy, Align,
"cbuf.dest");
1447 bool processArray(llvm::Type *FieldTy) {
1448 auto *AT = dyn_cast<llvm::ArrayType>(FieldTy);
1454 for (
unsigned I = 0, E = AT->getNumElements(); I < E; ++I)
1455 emitCopyAtIndices(AT->getElementType(),
1456 llvm::ConstantInt::get(CGF.
SizeTy, I),
1457 llvm::ConstantInt::get(CGF.
SizeTy, I));
1461 bool processBufferLayoutArray(llvm::Type *FieldTy) {
1467 auto *ST = dyn_cast<llvm::StructType>(FieldTy);
1468 if (!ST || ST->getNumElements() != 2)
1471 auto *PaddedEltsTy = dyn_cast<llvm::ArrayType>(ST->getElementType(0));
1475 auto *PaddedTy = dyn_cast<llvm::StructType>(PaddedEltsTy->getElementType());
1476 if (!PaddedTy || PaddedTy->getNumElements() != 2)
1480 PaddedTy->getElementType(1)))
1483 llvm::Type *ElementTy = ST->getElementType(1);
1484 if (PaddedTy->getElementType(0) != ElementTy)
1488 unsigned NumElts = PaddedEltsTy->getNumElements() + 1;
1492 CurLoadIndices.push_back(llvm::ConstantInt::get(CGF.
Int32Ty, 0));
1493 for (
unsigned I = 0; I < NumElts - 1; ++I) {
1495 CurLoadIndices.push_back(llvm::ConstantInt::get(CGF.
SizeTy, I));
1496 emitCopyAtIndices(ElementTy, llvm::ConstantInt::get(CGF.
SizeTy, I),
1497 llvm::ConstantInt::get(CGF.
Int32Ty, 0));
1498 CurLoadIndices.pop_back();
1500 CurLoadIndices.pop_back();
1503 emitCopyAtIndices(ElementTy,
1504 llvm::ConstantInt::get(CGF.
SizeTy, NumElts - 1),
1505 llvm::ConstantInt::get(CGF.
Int32Ty, 1));
1510 bool processStruct(llvm::Type *FieldTy) {
1511 auto *ST = dyn_cast<llvm::StructType>(FieldTy);
1516 unsigned Skipped = 0;
1517 for (
unsigned I = 0, E = ST->getNumElements(); I < E; ++I) {
1518 llvm::Type *ElementTy = ST->getElementType(I);
1522 emitCopyAtIndices(ElementTy, llvm::ConstantInt::get(CGF.
Int32Ty, I),
1523 llvm::ConstantInt::get(CGF.
Int32Ty, I + Skipped));
1529 HLSLBufferCopyEmitter(CodeGenFunction &CGF, Address DestPtr, Address SrcPtr)
1530 : CGF(CGF), DestPtr(DestPtr), SrcPtr(SrcPtr) {}
1532 bool emitCopy(QualType CType) {
1533 LayoutTy = HLSLBufferLayoutBuilder(CGF.
CGM).layOutType(CType);
1540 emitCopyAtIndices(LayoutTy, llvm::ConstantInt::get(CGF.
SizeTy, 0),
1541 llvm::ConstantInt::get(CGF.
SizeTy, 0));
1549 return HLSLBufferCopyEmitter(CGF, DestPtr, SrcPtr).emitCopy(CType);
1557 assert(Field &&
"Unexpected access into HLSL buffer");
1562 CGM.getTypes().getCGRecordLayout(Rec).getLLVMFieldNo(Field);
1565 QualType RecType =
CGM.getContext().getCanonicalTagType(Rec);
1576 QualType FieldType = Field->getType();
1577 llvm::Type *FieldLLVMTy =
CGM.getTypes().ConvertTypeForMem(FieldType);
1581 FieldIdx, Field->getName()),
1586 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