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);
490 if (LangOpts.NativeHalfType)
491 M.setModuleFlag(llvm::Module::ModFlagBehavior::Error,
"dx.nativelowprec",
499 const auto *ShaderAttr = FD->
getAttr<HLSLShaderAttr>();
500 assert(ShaderAttr &&
"All entry functions must have a HLSLShaderAttr");
501 const StringRef ShaderAttrKindStr =
"hlsl.shader";
502 Fn->addFnAttr(ShaderAttrKindStr,
503 llvm::Triple::getEnvironmentTypeName(ShaderAttr->getType()));
504 if (HLSLNumThreadsAttr *NumThreadsAttr = FD->
getAttr<HLSLNumThreadsAttr>()) {
505 const StringRef NumThreadsKindStr =
"hlsl.numthreads";
506 std::string NumThreadsStr =
507 formatv(
"{0},{1},{2}", NumThreadsAttr->getX(), NumThreadsAttr->getY(),
508 NumThreadsAttr->getZ());
509 Fn->addFnAttr(NumThreadsKindStr, NumThreadsStr);
511 if (HLSLWaveSizeAttr *WaveSizeAttr = FD->
getAttr<HLSLWaveSizeAttr>()) {
512 const StringRef WaveSizeKindStr =
"hlsl.wavesize";
513 std::string WaveSizeStr =
514 formatv(
"{0},{1},{2}", WaveSizeAttr->getMin(), WaveSizeAttr->getMax(),
515 WaveSizeAttr->getPreferred());
516 Fn->addFnAttr(WaveSizeKindStr, WaveSizeStr);
523 if (
CGM.getCodeGenOpts().OptimizationLevel == 0)
524 Fn->addFnAttr(llvm::Attribute::OptimizeNone);
525 Fn->addFnAttr(llvm::Attribute::NoInline);
527 if (
CGM.getLangOpts().HLSLSpvEnableMaximalReconvergence) {
528 Fn->addFnAttr(
"enable-maximal-reconvergence",
"true");
533 if (
const auto *VT = dyn_cast<FixedVectorType>(Ty)) {
534 Value *Result = PoisonValue::get(Ty);
535 for (
unsigned I = 0; I < VT->getNumElements(); ++I) {
536 Value *Elt = B.CreateCall(F, {B.getInt32(I)});
537 Result = B.CreateInsertElement(Result, Elt, I);
541 return B.CreateCall(F, {B.getInt32(0)});
546 LLVMContext &Ctx = GV->getContext();
547 IRBuilder<> B(GV->getContext());
548 MDNode *Operands = MDNode::get(
550 {ConstantAsMetadata::get(B.getInt32( 11)),
551 ConstantAsMetadata::get(B.getInt32(BuiltIn))});
552 MDNode *Decoration = MDNode::get(Ctx, {Operands});
553 GV->addMetadata(
"spirv.Decorations", *Decoration);
557 LLVMContext &Ctx = GV->getContext();
558 IRBuilder<> B(GV->getContext());
560 MDNode::get(Ctx, {ConstantAsMetadata::get(B.getInt32( 30)),
561 ConstantAsMetadata::get(B.getInt32(Location))});
562 MDNode *Decoration = MDNode::get(Ctx, {Operands});
563 GV->addMetadata(
"spirv.Decorations", *Decoration);
567 llvm::Type *Ty,
const Twine &Name,
568 unsigned BuiltInID) {
569 auto *GV =
new llvm::GlobalVariable(
570 M, Ty,
true, llvm::GlobalValue::ExternalLinkage,
571 nullptr, Name,
nullptr,
572 llvm::GlobalVariable::GeneralDynamicTLSModel,
575 GV->setVisibility(llvm::GlobalValue::HiddenVisibility);
576 return B.CreateLoad(Ty, GV);
580 llvm::Type *Ty,
unsigned Location,
582 auto *GV =
new llvm::GlobalVariable(
583 M, Ty,
true, llvm::GlobalValue::ExternalLinkage,
584 nullptr, Name,
nullptr,
585 llvm::GlobalVariable::GeneralDynamicTLSModel,
587 GV->setVisibility(llvm::GlobalValue::HiddenVisibility);
589 return B.CreateLoad(Ty, GV);
592llvm::Value *CGHLSLRuntime::emitSPIRVUserSemanticLoad(
593 llvm::IRBuilder<> &B, llvm::Type *
Type,
const clang::DeclaratorDecl *
Decl,
594 HLSLAppliedSemanticAttr *Semantic, std::optional<unsigned> Index) {
595 Twine BaseName = Twine(Semantic->getAttrName()->getName());
596 Twine VariableName = BaseName.concat(Twine(Index.value_or(0)));
598 unsigned Location = SPIRVLastAssignedInputSemanticLocation;
599 if (
auto *L =
Decl->getAttr<HLSLVkLocationAttr>())
600 Location = L->getLocation();
604 llvm::ArrayType *AT = dyn_cast<llvm::ArrayType>(
Type);
605 unsigned ElementCount = AT ? AT->getNumElements() : 1;
606 SPIRVLastAssignedInputSemanticLocation += ElementCount;
613 llvm::Value *Source,
unsigned Location,
615 auto *GV =
new llvm::GlobalVariable(
616 M, Source->getType(),
false,
617 llvm::GlobalValue::ExternalLinkage,
618 nullptr, Name,
nullptr,
619 llvm::GlobalVariable::GeneralDynamicTLSModel,
621 GV->setVisibility(llvm::GlobalValue::HiddenVisibility);
623 B.CreateStore(Source, GV);
626void CGHLSLRuntime::emitSPIRVUserSemanticStore(
627 llvm::IRBuilder<> &B, llvm::Value *Source,
628 const clang::DeclaratorDecl *
Decl, HLSLAppliedSemanticAttr *Semantic,
629 std::optional<unsigned> Index) {
630 Twine BaseName = Twine(Semantic->getAttrName()->getName());
631 Twine VariableName = BaseName.concat(Twine(Index.value_or(0)));
633 unsigned Location = SPIRVLastAssignedOutputSemanticLocation;
634 if (
auto *L =
Decl->getAttr<HLSLVkLocationAttr>())
635 Location = L->getLocation();
639 llvm::ArrayType *AT = dyn_cast<llvm::ArrayType>(Source->getType());
640 unsigned ElementCount = AT ? AT->getNumElements() : 1;
641 SPIRVLastAssignedOutputSemanticLocation += ElementCount;
647CGHLSLRuntime::emitDXILUserSemanticLoad(llvm::IRBuilder<> &B, llvm::Type *
Type,
648 HLSLAppliedSemanticAttr *Semantic,
649 std::optional<unsigned> Index) {
650 Twine BaseName = Twine(Semantic->getAttrName()->getName());
651 Twine VariableName = BaseName.concat(Twine(Index.value_or(0)));
656 SmallVector<Value *> Args{B.getInt32(4), B.getInt32(0), B.getInt32(0),
658 llvm::PoisonValue::get(B.getInt32Ty())};
660 llvm::Intrinsic::ID IntrinsicID = llvm::Intrinsic::dx_load_input;
661 llvm::Value *
Value = B.CreateIntrinsic(
Type, IntrinsicID, Args,
662 nullptr, VariableName);
666void CGHLSLRuntime::emitDXILUserSemanticStore(llvm::IRBuilder<> &B,
668 HLSLAppliedSemanticAttr *Semantic,
669 std::optional<unsigned> Index) {
672 SmallVector<Value *> Args{B.getInt32(4),
676 llvm::PoisonValue::get(B.getInt32Ty()),
679 llvm::Intrinsic::ID IntrinsicID = llvm::Intrinsic::dx_store_output;
680 B.CreateIntrinsic(
CGM.VoidTy, IntrinsicID, Args,
nullptr);
683llvm::Value *CGHLSLRuntime::emitUserSemanticLoad(
684 IRBuilder<> &B, llvm::Type *
Type,
const clang::DeclaratorDecl *
Decl,
685 HLSLAppliedSemanticAttr *Semantic, std::optional<unsigned> Index) {
686 if (
CGM.getTarget().getTriple().isSPIRV())
687 return emitSPIRVUserSemanticLoad(B,
Type,
Decl, Semantic, Index);
689 if (
CGM.getTarget().getTriple().isDXIL())
690 return emitDXILUserSemanticLoad(B,
Type, Semantic, Index);
692 llvm_unreachable(
"Unsupported target for user-semantic load.");
695void CGHLSLRuntime::emitUserSemanticStore(IRBuilder<> &B, llvm::Value *Source,
696 const clang::DeclaratorDecl *
Decl,
697 HLSLAppliedSemanticAttr *Semantic,
698 std::optional<unsigned> Index) {
699 if (
CGM.getTarget().getTriple().isSPIRV())
700 return emitSPIRVUserSemanticStore(B, Source,
Decl, Semantic, Index);
702 if (
CGM.getTarget().getTriple().isDXIL())
703 return emitDXILUserSemanticStore(B, Source, Semantic, Index);
705 llvm_unreachable(
"Unsupported target for user-semantic load.");
711 std::optional<unsigned> Index) {
713 std::string SemanticName = Semantic->getAttrName()->getName().upper();
714 if (SemanticName ==
"SV_GROUPINDEX") {
715 llvm::Function *GroupIndex =
716 CGM.getIntrinsic(getFlattenedThreadIdInGroupIntrinsic());
717 return B.CreateCall(FunctionCallee(GroupIndex));
720 if (SemanticName ==
"SV_DISPATCHTHREADID") {
721 llvm::Intrinsic::ID IntrinID = getThreadIdIntrinsic();
722 llvm::Function *ThreadIDIntrinsic =
723 llvm::Intrinsic::isOverloaded(IntrinID)
724 ?
CGM.getIntrinsic(IntrinID, {
CGM.Int32Ty})
725 :
CGM.getIntrinsic(IntrinID);
729 if (SemanticName ==
"SV_GROUPTHREADID") {
730 llvm::Intrinsic::ID IntrinID = getGroupThreadIdIntrinsic();
731 llvm::Function *GroupThreadIDIntrinsic =
732 llvm::Intrinsic::isOverloaded(IntrinID)
733 ?
CGM.getIntrinsic(IntrinID, {
CGM.Int32Ty})
734 :
CGM.getIntrinsic(IntrinID);
738 if (SemanticName ==
"SV_GROUPID") {
739 llvm::Intrinsic::ID IntrinID = getGroupIdIntrinsic();
740 llvm::Function *GroupIDIntrinsic =
741 llvm::Intrinsic::isOverloaded(IntrinID)
742 ?
CGM.getIntrinsic(IntrinID, {
CGM.Int32Ty})
743 :
CGM.getIntrinsic(IntrinID);
747 const auto *ShaderAttr = FD->
getAttr<HLSLShaderAttr>();
748 assert(ShaderAttr &&
"Entry point has no shader attribute");
749 llvm::Triple::EnvironmentType ST = ShaderAttr->getType();
751 if (SemanticName ==
"SV_POSITION") {
752 if (ST == Triple::EnvironmentType::Pixel) {
753 if (
CGM.getTarget().getTriple().isSPIRV())
755 Semantic->getAttrName()->getName(),
757 if (
CGM.getTarget().getTriple().isDXIL())
758 return emitDXILUserSemanticLoad(B,
Type, Semantic, Index);
761 if (ST == Triple::EnvironmentType::Vertex) {
762 return emitUserSemanticLoad(B,
Type,
Decl, Semantic, Index);
767 "Load hasn't been implemented yet for this system semantic. FIXME");
771 llvm::Value *Source,
const Twine &Name,
772 unsigned BuiltInID) {
773 auto *GV =
new llvm::GlobalVariable(
774 M, Source->getType(),
false,
775 llvm::GlobalValue::ExternalLinkage,
776 nullptr, Name,
nullptr,
777 llvm::GlobalVariable::GeneralDynamicTLSModel,
780 GV->setVisibility(llvm::GlobalValue::HiddenVisibility);
781 B.CreateStore(Source, GV);
786 HLSLAppliedSemanticAttr *Semantic,
787 std::optional<unsigned> Index) {
789 std::string SemanticName = Semantic->getAttrName()->getName().upper();
790 if (SemanticName ==
"SV_POSITION") {
791 if (
CGM.getTarget().getTriple().isDXIL()) {
792 emitDXILUserSemanticStore(B, Source, Semantic, Index);
796 if (
CGM.getTarget().getTriple().isSPIRV()) {
798 Semantic->getAttrName()->getName(),
804 if (SemanticName ==
"SV_TARGET") {
805 emitUserSemanticStore(B, Source,
Decl, Semantic, Index);
810 "Store hasn't been implemented yet for this system semantic. FIXME");
817 std::optional<unsigned> Index = Semantic->getSemanticIndex();
818 if (Semantic->getAttrName()->getName().starts_with_insensitive(
"SV_"))
820 return emitUserSemanticLoad(B,
Type,
Decl, Semantic, Index);
824 IRBuilder<> &B,
const FunctionDecl *FD, llvm::Value *Source,
826 std::optional<unsigned> Index = Semantic->getSemanticIndex();
827 if (Semantic->getAttrName()->getName().starts_with_insensitive(
"SV_"))
830 emitUserSemanticStore(B, Source,
Decl, Semantic, Index);
833std::pair<llvm::Value *, specific_attr_iterator<HLSLAppliedSemanticAttr>>
846 for (
unsigned I = 0; I < ST->getNumElements(); ++I) {
848 B, FD, ST->getElementType(I), *
FieldDecl, AttrBegin, AttrEnd);
849 AttrBegin = NextAttr;
855 return std::make_pair(
Aggregate, AttrBegin);
860 IRBuilder<> &B,
const FunctionDecl *FD, llvm::Value *Source,
871 RD =
Decl->getType()->getAsRecordDecl();
877 for (
unsigned I = 0; I < ST->getNumElements(); ++I) {
878 llvm::Value *Extract = B.CreateExtractValue(Source, I);
886std::pair<llvm::Value *, specific_attr_iterator<HLSLAppliedSemanticAttr>>
892 assert(AttrBegin != AttrEnd);
893 if (
Type->isStructTy())
896 HLSLAppliedSemanticAttr *
Attr = *AttrBegin;
904 IRBuilder<> &B,
const FunctionDecl *FD, llvm::Value *Source,
908 assert(AttrBegin != AttrEnd);
909 if (Source->getType()->isStructTy())
912 HLSLAppliedSemanticAttr *
Attr = *AttrBegin;
919 llvm::Function *Fn) {
920 llvm::Module &M =
CGM.getModule();
921 llvm::LLVMContext &Ctx = M.getContext();
922 auto *EntryTy = llvm::FunctionType::get(llvm::Type::getVoidTy(Ctx),
false);
924 Function::Create(EntryTy, Function::ExternalLinkage, FD->
getName(), &M);
928 AttributeList NewAttrs = AttributeList::get(Ctx, AttributeList::FunctionIndex,
929 Fn->getAttributes().getFnAttrs());
930 EntryFn->setAttributes(NewAttrs);
934 Fn->setLinkage(GlobalValue::InternalLinkage);
936 BasicBlock *BB = BasicBlock::Create(Ctx,
"entry", EntryFn);
941 if (
CGM.shouldEmitConvergenceTokens()) {
942 assert(EntryFn->isConvergent());
944 B.CreateIntrinsic(llvm::Intrinsic::experimental_convergence_entry, {});
945 llvm::Value *bundleArgs[] = {I};
946 OB.emplace_back(
"convergencectrl", bundleArgs);
949 llvm::DenseMap<const DeclaratorDecl *, llvm::Value *> OutputSemantic;
951 unsigned SRetOffset = 0;
952 for (
const auto &Param : Fn->args()) {
953 if (Param.hasStructRetAttr()) {
955 llvm::Type *VarType = Param.getParamStructRetType();
956 llvm::Value *Var = B.CreateAlloca(VarType);
957 OutputSemantic.try_emplace(FD, Var);
963 llvm::Value *SemanticValue =
nullptr;
965 if ([[maybe_unused]] HLSLParamModifierAttr *MA =
966 PD->
getAttr<HLSLParamModifierAttr>()) {
967 llvm_unreachable(
"Not handled yet");
969 llvm::Type *ParamType =
970 Param.hasByValAttr() ? Param.getParamByValType() : Param.getType();
975 SemanticValue =
Result.first;
978 if (Param.hasByValAttr()) {
979 llvm::Value *Var = B.CreateAlloca(Param.getParamByValType());
980 B.CreateStore(SemanticValue, Var);
985 assert(SemanticValue);
986 Args.push_back(SemanticValue);
989 CallInst *CI = B.CreateCall(FunctionCallee(Fn), Args, OB);
990 CI->setCallingConv(Fn->getCallingConv());
992 if (Fn->getReturnType() !=
CGM.VoidTy)
993 OutputSemantic.try_emplace(FD, CI);
995 for (
auto &[
Decl, Source] : OutputSemantic) {
996 AllocaInst *AI = dyn_cast<AllocaInst>(Source);
997 llvm::Value *SourceValue =
998 AI ? B.CreateLoad(AI->getAllocatedType(), Source) : Source;
1000 auto AttrBegin =
Decl->specific_attr_begin<HLSLAppliedSemanticAttr>();
1001 auto AttrEnd =
Decl->specific_attr_end<HLSLAppliedSemanticAttr>();
1009 if (
const auto *RSAttr = dyn_cast<RootSignatureAttr>(
Attr)) {
1010 auto *RSDecl = RSAttr->getSignatureDecl();
1011 addRootSignatureMD(RSDecl->getVersion(), RSDecl->getRootElements(),
1020 M.getNamedGlobal(CtorOrDtor ?
"llvm.global_ctors" :
"llvm.global_dtors");
1023 const auto *CA = dyn_cast<ConstantArray>(GV->getInitializer());
1030 for (
const auto &Ctor : CA->operands()) {
1036 "HLSL doesn't support setting priority for global ctors.");
1038 "HLSL doesn't support COMDat for global ctors.");
1044 llvm::Module &M =
CGM.getModule();
1053 for (
auto &F : M.functions()) {
1054 if (!F.hasFnAttribute(
"hlsl.shader"))
1057 Instruction *IP = &*F.getEntryBlock().begin();
1060 llvm::Value *bundleArgs[] = {
Token};
1061 OB.emplace_back(
"convergencectrl", bundleArgs);
1062 IP =
Token->getNextNode();
1065 for (
auto *Fn : CtorFns) {
1066 auto CI = B.CreateCall(FunctionCallee(Fn), {}, OB);
1067 CI->setCallingConv(Fn->getCallingConv());
1071 B.SetInsertPoint(F.back().getTerminator());
1072 for (
auto *Fn : DtorFns) {
1073 auto CI = B.CreateCall(FunctionCallee(Fn), {}, OB);
1074 CI->setCallingConv(Fn->getCallingConv());
1080 Triple
T(M.getTargetTriple());
1081 if (
T.getEnvironment() != Triple::EnvironmentType::Library) {
1082 if (
auto *GV = M.getNamedGlobal(
"llvm.global_ctors"))
1083 GV->eraseFromParent();
1084 if (
auto *GV = M.getNamedGlobal(
"llvm.global_dtors"))
1085 GV->eraseFromParent();
1090 Intrinsic::ID IntrID,
1094 llvm::Function *InitResFunc = llvm::Function::Create(
1095 llvm::FunctionType::get(CGM.
VoidTy,
false),
1096 llvm::GlobalValue::InternalLinkage,
1097 (
"_init_buffer_" + GV->getName()).str(), CGM.
getModule());
1098 InitResFunc->addFnAttr(llvm::Attribute::AlwaysInline);
1100 llvm::BasicBlock *EntryBB =
1101 llvm::BasicBlock::Create(Ctx,
"entry", InitResFunc);
1103 const DataLayout &DL = CGM.
getModule().getDataLayout();
1104 Builder.SetInsertPoint(EntryBB);
1107 llvm::Type *HandleTy = GV->getValueType();
1108 assert(HandleTy->isTargetExtTy() &&
"unexpected type of the buffer global");
1110 llvm::Value *CreateHandle = Builder.CreateIntrinsic(
1111 HandleTy, IntrID, Args,
nullptr,
1112 Twine(GV->getName()).concat(
"_h"));
1114 llvm::Value *HandleRef = Builder.CreateStructGEP(GV->getValueType(), GV, 0);
1115 Builder.CreateAlignedStore(CreateHandle, HandleRef,
1116 HandleRef->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 =
1283 llvm::ConstantInt::get(
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 auto RestoreIndices = llvm::make_scope_exit([&]() {
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