23#include "clang/AST/Attrs.inc"
30#include "llvm/ADT/DenseMap.h"
31#include "llvm/ADT/ScopeExit.h"
32#include "llvm/ADT/SmallString.h"
33#include "llvm/ADT/SmallVector.h"
34#include "llvm/Frontend/HLSL/RootSignatureMetadata.h"
35#include "llvm/IR/Constants.h"
36#include "llvm/IR/DerivedTypes.h"
37#include "llvm/IR/GlobalVariable.h"
38#include "llvm/IR/LLVMContext.h"
39#include "llvm/IR/Metadata.h"
40#include "llvm/IR/Module.h"
41#include "llvm/IR/Type.h"
42#include "llvm/IR/Value.h"
43#include "llvm/Support/Alignment.h"
44#include "llvm/Support/ErrorHandling.h"
45#include "llvm/Support/FormatVariadic.h"
54using llvm::hlsl::CBufferRowSizeInBytes;
58void addDxilValVersion(StringRef ValVersionStr, llvm::Module &M) {
62 if (Version.tryParse(ValVersionStr) || Version.getBuild() ||
63 Version.getSubminor() || !Version.getMinor()) {
67 uint64_t Major = Version.getMajor();
68 uint64_t Minor = *Version.getMinor();
70 auto &Ctx = M.getContext();
71 IRBuilder<> B(M.getContext());
72 MDNode *Val = MDNode::get(Ctx, {ConstantAsMetadata::get(B.getInt32(Major)),
73 ConstantAsMetadata::get(B.getInt32(Minor))});
74 StringRef DXILValKey =
"dx.valver";
75 auto *DXILValMD = M.getOrInsertNamedMetadata(DXILValKey);
76 DXILValMD->addOperand(Val);
79void addRootSignatureMD(llvm::dxbc::RootSignatureVersion RootSigVer,
81 llvm::Function *Fn, llvm::Module &M) {
82 auto &Ctx = M.getContext();
84 llvm::hlsl::rootsig::MetadataBuilder RSBuilder(Ctx, Elements);
85 MDNode *RootSignature = RSBuilder.BuildRootSignature();
87 ConstantAsMetadata *Version = ConstantAsMetadata::get(ConstantInt::get(
88 llvm::Type::getInt32Ty(Ctx), llvm::to_underlying(RootSigVer)));
89 ValueAsMetadata *EntryFunc =
Fn ? ValueAsMetadata::get(Fn) :
nullptr;
90 MDNode *MDVals = MDNode::get(Ctx, {EntryFunc, RootSignature, Version});
92 StringRef RootSignatureValKey =
"dx.rootsignatures";
93 auto *RootSignatureValMD = M.getOrInsertNamedMetadata(RootSignatureValKey);
94 RootSignatureValMD->addOperand(MDVals);
99 const Expr *E =
nullptr;
100 while (ASE !=
nullptr) {
104 ASE = dyn_cast<ArraySubscriptExpr>(E);
106 if (
const DeclRefExpr *DRE = dyn_cast_or_null<DeclRefExpr>(E))
107 return DRE->getDecl();
114 assert(Ty->
isArrayType() &&
"expected array type");
120static Value *buildNameForResource(llvm::StringRef BaseName,
129 for (
auto *Method :
Record->methods()) {
130 if (Method->getStorageClass() == SC && Method->getName() == Name)
140 assert(Binding.
hasBinding() &&
"at least one binding attribute expected");
144 Value *NameStr = buildNameForResource(Name, CGM);
149 auto *RegSlot = llvm::ConstantInt::get(CGM.
IntTy, Binding.
getSlot());
152 ?
"__createFromBindingWithImplicitCounter"
153 :
"__createFromBinding";
154 CreateMethod = lookupMethod(ResourceDecl, Name,
SC_Static);
161 ?
"__createFromImplicitBindingWithImplicitCounter"
162 :
"__createFromImplicitBinding";
163 CreateMethod = lookupMethod(ResourceDecl, Name,
SC_Static);
171 auto *CounterOrderID = llvm::ConstantInt::get(CGM.
IntTy, CounterBinding);
188 CGF.
EmitCall(FnInfo, Callee, ReturnValue, Args,
nullptr);
196static std::optional<llvm::Value *> initializeLocalResourceArray(
199 llvm::Value *Range, llvm::Value *StartIndex, StringRef ResourceName,
204 llvm::IntegerType *IntTy = CGF.
CGM.
IntTy;
205 llvm::Value *Index = StartIndex;
206 llvm::Value *One = llvm::ConstantInt::get(IntTy, 1);
214 GEPIndices.push_back(llvm::ConstantInt::get(IntTy, 0));
219 for (uint64_t I = 0; I < ArraySize; I++) {
221 Index = CGF.
Builder.CreateAdd(Index, One);
222 GEPIndices.back() = llvm::ConstantInt::get(IntTy, I);
224 std::optional<llvm::Value *> MaybeIndex = initializeLocalResourceArray(
225 CGF, ResourceDecl, SubArrayTy, ValueSlot, Range, Index, ResourceName,
226 Binding, GEPIndices, ArraySubsExprLoc);
240 for (uint64_t I = 0; I < ArraySize; I++) {
242 Index = CGF.
Builder.CreateAdd(Index, One);
243 GEPIndices.back() = llvm::ConstantInt::get(IntTy, I);
249 CXXMethodDecl *CreateMethod = lookupResourceInitMethodAndSetupArgs(
250 CGF.
CGM, ResourceDecl, Range, Index, ResourceName, Binding, Args);
258 callResourceInitMethod(CGF, CreateMethod, Args, ReturnAddress);
268 assert(
T->isHLSLSpecificType() &&
"Not an HLSL specific type!");
271 if (llvm::Type *TargetTy =
272 CGM.getTargetCodeGenInfo().getHLSLType(
CGM,
T, OffsetInfo))
275 llvm_unreachable(
"Generic handling of HLSL types is not supported.");
278llvm::Triple::ArchType CGHLSLRuntime::getArch() {
284void CGHLSLRuntime::emitBufferGlobalsAndMetadata(
290 llvm::Type *BufType = BufGV->getValueType();
295 size_t OffsetIdx = 0;
305 VarDecl *VD = dyn_cast<VarDecl>(D);
321 "constant buffer decl with non-zero sized type outside of "
322 "hlsl_constant address space");
327 DeclsWithOffset.emplace_back(VD, OffsetInfo[OffsetIdx++]);
330 if (!OffsetInfo.
empty())
331 llvm::stable_sort(DeclsWithOffset, [](
const auto &LHS,
const auto &RHS) {
336 SmallVector<llvm::Metadata *> BufGlobals;
337 BufGlobals.reserve(DeclsWithOffset.size() + 1);
338 BufGlobals.push_back(ValueAsMetadata::get(BufGV));
340 auto ElemIt = LayoutStruct->element_begin();
341 for (
auto &[VD, _] : DeclsWithOffset) {
342 if (
CGM.getTargetCodeGenInfo().isHLSLPadding(*ElemIt))
345 assert(ElemIt != LayoutStruct->element_end() &&
346 "number of elements in layout struct does not match");
347 llvm::Type *LayoutType = *ElemIt++;
349 GlobalVariable *ElemGV =
351 BufGlobals.push_back(ValueAsMetadata::get(ElemGV));
353 assert(ElemIt == LayoutStruct->element_end() &&
354 "number of elements in layout struct does not match");
358 .getOrInsertNamedMetadata(
"hlsl.cbs")
359 ->addOperand(MDNode::get(Ctx, BufGlobals));
363static const clang::HLSLAttributedResourceType *
368 HLSLAttributedResourceType::Attributes(ResourceClass::CBuffer));
383 VarDecl *VD = dyn_cast<VarDecl>(D);
394 if (
auto *POA = dyn_cast<HLSLPackOffsetAttr>(
Attr)) {
395 Offset = POA->getOffsetInBytes();
398 auto *RBA = dyn_cast<HLSLResourceBindingAttr>(
Attr);
400 RBA->getRegisterType() == HLSLResourceBindingAttr::RegisterType::C) {
401 Offset = RBA->getSlotNumber() * CBufferRowSizeInBytes;
405 Result.Offsets.push_back(Offset);
413 assert(BufDecl->
isCBuffer() &&
"tbuffer codegen is not supported yet");
416 const clang::HLSLAttributedResourceType *ResHandleTy =
420 if (ResHandleTy->getContainedType()->getAsCXXRecordDecl()->isEmpty())
426 llvm::GlobalVariable *BufGV =
new GlobalVariable(
428 GlobalValue::LinkageTypes::ExternalLinkage, PoisonValue::get(LayoutTy),
429 llvm::formatv(
"{0}{1}", BufDecl->
getName(),
431 GlobalValue::NotThreadLocal);
432 CGM.getModule().insertGlobalVariable(BufGV);
435 emitBufferGlobalsAndMetadata(BufDecl, BufGV, OffsetInfo);
438 initializeBufferFromBinding(BufDecl, BufGV);
443 llvm::Module &M =
CGM.getModule();
444 Triple
T(M.getTargetTriple());
447 if (
T.getEnvironment() != Triple::EnvironmentType::RootSignature)
450 addRootSignatureMD(SignatureDecl->
getVersion(),
456 const auto Entry = LayoutTypes.find(StructType);
457 if (Entry != LayoutTypes.end())
458 return Entry->getSecond();
463 llvm::StructType *LayoutTy) {
465 "layout type for this struct already exist");
466 LayoutTypes[StructType] = LayoutTy;
470 auto &TargetOpts =
CGM.getTarget().getTargetOpts();
471 auto &CodeGenOpts =
CGM.getCodeGenOpts();
472 auto &LangOpts =
CGM.getLangOpts();
473 llvm::Module &M =
CGM.getModule();
474 Triple
T(M.getTargetTriple());
475 if (
T.getArch() == Triple::ArchType::dxil)
476 addDxilValVersion(TargetOpts.DxilValidatorVersion, M);
477 if (CodeGenOpts.ResMayAlias)
478 M.setModuleFlag(llvm::Module::ModFlagBehavior::Error,
"dx.resmayalias", 1);
483 if (LangOpts.NativeHalfType)
484 M.setModuleFlag(llvm::Module::ModFlagBehavior::Error,
"dx.nativelowprec",
492 const auto *ShaderAttr = FD->
getAttr<HLSLShaderAttr>();
493 assert(ShaderAttr &&
"All entry functions must have a HLSLShaderAttr");
494 const StringRef ShaderAttrKindStr =
"hlsl.shader";
495 Fn->addFnAttr(ShaderAttrKindStr,
496 llvm::Triple::getEnvironmentTypeName(ShaderAttr->getType()));
497 if (HLSLNumThreadsAttr *NumThreadsAttr = FD->
getAttr<HLSLNumThreadsAttr>()) {
498 const StringRef NumThreadsKindStr =
"hlsl.numthreads";
499 std::string NumThreadsStr =
500 formatv(
"{0},{1},{2}", NumThreadsAttr->getX(), NumThreadsAttr->getY(),
501 NumThreadsAttr->getZ());
502 Fn->addFnAttr(NumThreadsKindStr, NumThreadsStr);
504 if (HLSLWaveSizeAttr *WaveSizeAttr = FD->
getAttr<HLSLWaveSizeAttr>()) {
505 const StringRef WaveSizeKindStr =
"hlsl.wavesize";
506 std::string WaveSizeStr =
507 formatv(
"{0},{1},{2}", WaveSizeAttr->getMin(), WaveSizeAttr->getMax(),
508 WaveSizeAttr->getPreferred());
509 Fn->addFnAttr(WaveSizeKindStr, WaveSizeStr);
516 if (
CGM.getCodeGenOpts().OptimizationLevel == 0)
517 Fn->addFnAttr(llvm::Attribute::OptimizeNone);
518 Fn->addFnAttr(llvm::Attribute::NoInline);
520 if (
CGM.getLangOpts().HLSLSpvEnableMaximalReconvergence) {
521 Fn->addFnAttr(
"enable-maximal-reconvergence",
"true");
526 if (
const auto *VT = dyn_cast<FixedVectorType>(Ty)) {
527 Value *Result = PoisonValue::get(Ty);
528 for (
unsigned I = 0; I < VT->getNumElements(); ++I) {
529 Value *Elt = B.CreateCall(F, {B.getInt32(I)});
530 Result = B.CreateInsertElement(Result, Elt, I);
534 return B.CreateCall(F, {B.getInt32(0)});
539 LLVMContext &Ctx = GV->getContext();
540 IRBuilder<> B(GV->getContext());
541 MDNode *Operands = MDNode::get(
543 {ConstantAsMetadata::get(B.getInt32( 11)),
544 ConstantAsMetadata::get(B.getInt32(BuiltIn))});
545 MDNode *Decoration = MDNode::get(Ctx, {Operands});
546 GV->addMetadata(
"spirv.Decorations", *Decoration);
550 LLVMContext &Ctx = GV->getContext();
551 IRBuilder<> B(GV->getContext());
553 MDNode::get(Ctx, {ConstantAsMetadata::get(B.getInt32( 30)),
554 ConstantAsMetadata::get(B.getInt32(Location))});
555 MDNode *Decoration = MDNode::get(Ctx, {Operands});
556 GV->addMetadata(
"spirv.Decorations", *Decoration);
560 llvm::Type *Ty,
const Twine &Name,
561 unsigned BuiltInID) {
562 auto *GV =
new llvm::GlobalVariable(
563 M, Ty,
true, llvm::GlobalValue::ExternalLinkage,
564 nullptr, Name,
nullptr,
565 llvm::GlobalVariable::GeneralDynamicTLSModel,
568 GV->setVisibility(llvm::GlobalValue::HiddenVisibility);
569 return B.CreateLoad(Ty, GV);
573 llvm::Type *Ty,
unsigned Location,
575 auto *GV =
new llvm::GlobalVariable(
576 M, Ty,
true, llvm::GlobalValue::ExternalLinkage,
577 nullptr, Name,
nullptr,
578 llvm::GlobalVariable::GeneralDynamicTLSModel,
580 GV->setVisibility(llvm::GlobalValue::HiddenVisibility);
582 return B.CreateLoad(Ty, GV);
586CGHLSLRuntime::emitSPIRVUserSemanticLoad(llvm::IRBuilder<> &B, llvm::Type *
Type,
587 HLSLAppliedSemanticAttr *Semantic,
588 std::optional<unsigned> Index) {
589 Twine BaseName = Twine(Semantic->getAttrName()->getName());
590 Twine VariableName = BaseName.concat(Twine(Index.value_or(0)));
592 unsigned Location = SPIRVLastAssignedInputSemanticLocation;
596 llvm::ArrayType *AT = dyn_cast<llvm::ArrayType>(
Type);
597 unsigned ElementCount = AT ? AT->getNumElements() : 1;
598 SPIRVLastAssignedInputSemanticLocation += ElementCount;
604 llvm::Value *Source,
unsigned Location,
606 auto *GV =
new llvm::GlobalVariable(
607 M, Source->getType(),
false,
608 llvm::GlobalValue::ExternalLinkage,
609 nullptr, Name,
nullptr,
610 llvm::GlobalVariable::GeneralDynamicTLSModel,
612 GV->setVisibility(llvm::GlobalValue::HiddenVisibility);
614 B.CreateStore(Source, GV);
617void CGHLSLRuntime::emitSPIRVUserSemanticStore(
618 llvm::IRBuilder<> &B, llvm::Value *Source,
619 HLSLAppliedSemanticAttr *Semantic, std::optional<unsigned> Index) {
620 Twine BaseName = Twine(Semantic->getAttrName()->getName());
621 Twine VariableName = BaseName.concat(Twine(Index.value_or(0)));
622 unsigned Location = SPIRVLastAssignedOutputSemanticLocation;
626 llvm::ArrayType *AT = dyn_cast<llvm::ArrayType>(Source->getType());
627 unsigned ElementCount = AT ? AT->getNumElements() : 1;
628 SPIRVLastAssignedOutputSemanticLocation += ElementCount;
634CGHLSLRuntime::emitDXILUserSemanticLoad(llvm::IRBuilder<> &B, llvm::Type *
Type,
635 HLSLAppliedSemanticAttr *Semantic,
636 std::optional<unsigned> Index) {
637 Twine BaseName = Twine(Semantic->getAttrName()->getName());
638 Twine VariableName = BaseName.concat(Twine(Index.value_or(0)));
643 SmallVector<Value *> Args{B.getInt32(4), B.getInt32(0), B.getInt32(0),
645 llvm::PoisonValue::get(B.getInt32Ty())};
647 llvm::Intrinsic::ID IntrinsicID = llvm::Intrinsic::dx_load_input;
648 llvm::Value *
Value = B.CreateIntrinsic(
Type, IntrinsicID, Args,
649 nullptr, VariableName);
653void CGHLSLRuntime::emitDXILUserSemanticStore(llvm::IRBuilder<> &B,
655 HLSLAppliedSemanticAttr *Semantic,
656 std::optional<unsigned> Index) {
659 SmallVector<Value *> Args{B.getInt32(4),
663 llvm::PoisonValue::get(B.getInt32Ty()),
666 llvm::Intrinsic::ID IntrinsicID = llvm::Intrinsic::dx_store_output;
667 B.CreateIntrinsic(
CGM.VoidTy, IntrinsicID, Args,
nullptr);
670llvm::Value *CGHLSLRuntime::emitUserSemanticLoad(
671 IRBuilder<> &B, llvm::Type *
Type,
const clang::DeclaratorDecl *
Decl,
672 HLSLAppliedSemanticAttr *Semantic, std::optional<unsigned> Index) {
673 if (
CGM.getTarget().getTriple().isSPIRV())
674 return emitSPIRVUserSemanticLoad(B,
Type, Semantic, Index);
676 if (
CGM.getTarget().getTriple().isDXIL())
677 return emitDXILUserSemanticLoad(B,
Type, Semantic, Index);
679 llvm_unreachable(
"Unsupported target for user-semantic load.");
682void CGHLSLRuntime::emitUserSemanticStore(IRBuilder<> &B, llvm::Value *Source,
683 const clang::DeclaratorDecl *
Decl,
684 HLSLAppliedSemanticAttr *Semantic,
685 std::optional<unsigned> Index) {
686 if (
CGM.getTarget().getTriple().isSPIRV())
687 return emitSPIRVUserSemanticStore(B, Source, Semantic, Index);
689 if (
CGM.getTarget().getTriple().isDXIL())
690 return emitDXILUserSemanticStore(B, Source, Semantic, Index);
692 llvm_unreachable(
"Unsupported target for user-semantic load.");
697 HLSLAppliedSemanticAttr *Semantic, std::optional<unsigned> Index) {
699 std::string SemanticName = Semantic->getAttrName()->getName().upper();
700 if (SemanticName ==
"SV_GROUPINDEX") {
701 llvm::Function *GroupIndex =
702 CGM.getIntrinsic(getFlattenedThreadIdInGroupIntrinsic());
703 return B.CreateCall(FunctionCallee(GroupIndex));
706 if (SemanticName ==
"SV_DISPATCHTHREADID") {
707 llvm::Intrinsic::ID IntrinID = getThreadIdIntrinsic();
708 llvm::Function *ThreadIDIntrinsic =
709 llvm::Intrinsic::isOverloaded(IntrinID)
710 ?
CGM.getIntrinsic(IntrinID, {
CGM.Int32Ty})
711 :
CGM.getIntrinsic(IntrinID);
715 if (SemanticName ==
"SV_GROUPTHREADID") {
716 llvm::Intrinsic::ID IntrinID = getGroupThreadIdIntrinsic();
717 llvm::Function *GroupThreadIDIntrinsic =
718 llvm::Intrinsic::isOverloaded(IntrinID)
719 ?
CGM.getIntrinsic(IntrinID, {
CGM.Int32Ty})
720 :
CGM.getIntrinsic(IntrinID);
724 if (SemanticName ==
"SV_GROUPID") {
725 llvm::Intrinsic::ID IntrinID = getGroupIdIntrinsic();
726 llvm::Function *GroupIDIntrinsic =
727 llvm::Intrinsic::isOverloaded(IntrinID)
728 ?
CGM.getIntrinsic(IntrinID, {
CGM.Int32Ty})
729 :
CGM.getIntrinsic(IntrinID);
733 if (SemanticName ==
"SV_POSITION") {
734 if (
CGM.getTriple().getEnvironment() == Triple::EnvironmentType::Pixel)
736 Semantic->getAttrName()->getName(),
740 llvm_unreachable(
"non-handled system semantic. FIXME.");
744 llvm::Value *Source,
const Twine &Name,
745 unsigned BuiltInID) {
746 auto *GV =
new llvm::GlobalVariable(
747 M, Source->getType(),
false,
748 llvm::GlobalValue::ExternalLinkage,
749 nullptr, Name,
nullptr,
750 llvm::GlobalVariable::GeneralDynamicTLSModel,
753 GV->setVisibility(llvm::GlobalValue::HiddenVisibility);
754 B.CreateStore(Source, GV);
759 HLSLAppliedSemanticAttr *Semantic,
760 std::optional<unsigned> Index) {
762 std::string SemanticName = Semantic->getAttrName()->getName().upper();
763 if (SemanticName ==
"SV_POSITION")
765 Semantic->getAttrName()->getName(),
768 llvm_unreachable(
"non-handled system semantic. FIXME.");
775 std::optional<unsigned> Index = Semantic->getSemanticIndex();
776 if (Semantic->getAttrName()->getName().starts_with_insensitive(
"SV_"))
778 return emitUserSemanticLoad(B,
Type,
Decl, Semantic, Index);
782 IRBuilder<> &B,
const FunctionDecl *FD, llvm::Value *Source,
784 std::optional<unsigned> Index = Semantic->getSemanticIndex();
785 if (Semantic->getAttrName()->getName().starts_with_insensitive(
"SV_"))
788 emitUserSemanticStore(B, Source,
Decl, Semantic, Index);
791std::pair<llvm::Value *, specific_attr_iterator<HLSLAppliedSemanticAttr>>
801 ST->getNumElements());
805 for (
unsigned I = 0; I < ST->getNumElements(); ++I) {
807 B, FD, ST->getElementType(I), *
FieldDecl, AttrBegin, AttrEnd);
808 AttrBegin = NextAttr;
814 return std::make_pair(
Aggregate, AttrBegin);
819 IRBuilder<> &B,
const FunctionDecl *FD, llvm::Value *Source,
830 RD =
Decl->getType()->getAsRecordDecl();
834 ST->getNumElements());
837 for (
unsigned I = 0; I < ST->getNumElements(); ++I) {
838 llvm::Value *Extract = B.CreateExtractValue(Source, I);
846std::pair<llvm::Value *, specific_attr_iterator<HLSLAppliedSemanticAttr>>
852 assert(AttrBegin != AttrEnd);
853 if (
Type->isStructTy())
856 HLSLAppliedSemanticAttr *
Attr = *AttrBegin;
864 IRBuilder<> &B,
const FunctionDecl *FD, llvm::Value *Source,
868 assert(AttrBegin != AttrEnd);
869 if (Source->getType()->isStructTy())
872 HLSLAppliedSemanticAttr *
Attr = *AttrBegin;
879 llvm::Function *Fn) {
880 llvm::Module &M =
CGM.getModule();
881 llvm::LLVMContext &Ctx = M.getContext();
882 auto *EntryTy = llvm::FunctionType::get(llvm::Type::getVoidTy(Ctx),
false);
884 Function::Create(EntryTy, Function::ExternalLinkage, FD->
getName(), &M);
888 AttributeList NewAttrs = AttributeList::get(Ctx, AttributeList::FunctionIndex,
889 Fn->getAttributes().getFnAttrs());
890 EntryFn->setAttributes(NewAttrs);
894 Fn->setLinkage(GlobalValue::InternalLinkage);
896 BasicBlock *BB = BasicBlock::Create(Ctx,
"entry", EntryFn);
901 if (
CGM.shouldEmitConvergenceTokens()) {
902 assert(EntryFn->isConvergent());
904 B.CreateIntrinsic(llvm::Intrinsic::experimental_convergence_entry, {});
905 llvm::Value *bundleArgs[] = {I};
906 OB.emplace_back(
"convergencectrl", bundleArgs);
909 llvm::DenseMap<const DeclaratorDecl *, llvm::Value *> OutputSemantic;
911 unsigned SRetOffset = 0;
912 for (
const auto &Param : Fn->args()) {
913 if (Param.hasStructRetAttr()) {
915 llvm::Type *VarType = Param.getParamStructRetType();
916 llvm::Value *Var = B.CreateAlloca(VarType);
917 OutputSemantic.try_emplace(FD, Var);
923 llvm::Value *SemanticValue =
nullptr;
925 if ([[maybe_unused]] HLSLParamModifierAttr *MA =
926 PD->
getAttr<HLSLParamModifierAttr>()) {
927 llvm_unreachable(
"Not handled yet");
929 llvm::Type *ParamType =
930 Param.hasByValAttr() ? Param.getParamByValType() : Param.getType();
935 SemanticValue =
Result.first;
938 if (Param.hasByValAttr()) {
939 llvm::Value *Var = B.CreateAlloca(Param.getParamByValType());
940 B.CreateStore(SemanticValue, Var);
945 assert(SemanticValue);
946 Args.push_back(SemanticValue);
949 CallInst *CI = B.CreateCall(FunctionCallee(Fn), Args, OB);
950 CI->setCallingConv(Fn->getCallingConv());
952 if (Fn->getReturnType() !=
CGM.VoidTy)
953 OutputSemantic.try_emplace(FD, CI);
955 for (
auto &[
Decl, Source] : OutputSemantic) {
956 AllocaInst *AI = dyn_cast<AllocaInst>(Source);
957 llvm::Value *SourceValue =
958 AI ? B.CreateLoad(AI->getAllocatedType(), Source) : Source;
960 auto AttrBegin =
Decl->specific_attr_begin<HLSLAppliedSemanticAttr>();
961 auto AttrEnd =
Decl->specific_attr_end<HLSLAppliedSemanticAttr>();
969 if (
const auto *RSAttr = dyn_cast<RootSignatureAttr>(
Attr)) {
970 auto *RSDecl = RSAttr->getSignatureDecl();
971 addRootSignatureMD(RSDecl->getVersion(), RSDecl->getRootElements(),
980 M.getNamedGlobal(CtorOrDtor ?
"llvm.global_ctors" :
"llvm.global_dtors");
983 const auto *CA = dyn_cast<ConstantArray>(GV->getInitializer());
990 for (
const auto &Ctor : CA->operands()) {
996 "HLSL doesn't support setting priority for global ctors.");
998 "HLSL doesn't support COMDat for global ctors.");
1004 llvm::Module &M =
CGM.getModule();
1013 for (
auto &F : M.functions()) {
1014 if (!F.hasFnAttribute(
"hlsl.shader"))
1017 Instruction *IP = &*F.getEntryBlock().begin();
1020 llvm::Value *bundleArgs[] = {
Token};
1021 OB.emplace_back(
"convergencectrl", bundleArgs);
1022 IP =
Token->getNextNode();
1025 for (
auto *Fn : CtorFns) {
1026 auto CI = B.CreateCall(FunctionCallee(Fn), {}, OB);
1027 CI->setCallingConv(Fn->getCallingConv());
1031 B.SetInsertPoint(F.back().getTerminator());
1032 for (
auto *Fn : DtorFns) {
1033 auto CI = B.CreateCall(FunctionCallee(Fn), {}, OB);
1034 CI->setCallingConv(Fn->getCallingConv());
1040 Triple
T(M.getTargetTriple());
1041 if (
T.getEnvironment() != Triple::EnvironmentType::Library) {
1042 if (
auto *GV = M.getNamedGlobal(
"llvm.global_ctors"))
1043 GV->eraseFromParent();
1044 if (
auto *GV = M.getNamedGlobal(
"llvm.global_dtors"))
1045 GV->eraseFromParent();
1050 Intrinsic::ID IntrID,
1054 llvm::Function *InitResFunc = llvm::Function::Create(
1055 llvm::FunctionType::get(CGM.
VoidTy,
false),
1056 llvm::GlobalValue::InternalLinkage,
1057 (
"_init_buffer_" + GV->getName()).str(), CGM.
getModule());
1058 InitResFunc->addFnAttr(llvm::Attribute::AlwaysInline);
1060 llvm::BasicBlock *EntryBB =
1061 llvm::BasicBlock::Create(Ctx,
"entry", InitResFunc);
1063 const DataLayout &DL = CGM.
getModule().getDataLayout();
1064 Builder.SetInsertPoint(EntryBB);
1067 llvm::Type *HandleTy = GV->getValueType();
1068 assert(HandleTy->isTargetExtTy() &&
"unexpected type of the buffer global");
1070 llvm::Value *CreateHandle = Builder.CreateIntrinsic(
1071 HandleTy, IntrID, Args,
nullptr,
1072 Twine(GV->getName()).concat(
"_h"));
1074 llvm::Value *HandleRef = Builder.CreateStructGEP(GV->getValueType(), GV, 0);
1075 Builder.CreateAlignedStore(CreateHandle, HandleRef,
1076 HandleRef->getPointerAlignment(DL));
1077 Builder.CreateRetVoid();
1082void CGHLSLRuntime::initializeBufferFromBinding(
const HLSLBufferDecl *BufDecl,
1083 llvm::GlobalVariable *GV) {
1084 ResourceBindingAttrs Binding(BufDecl);
1086 "cbuffer/tbuffer should always have resource binding attribute");
1088 auto *Index = llvm::ConstantInt::get(
CGM.IntTy, 0);
1089 auto *RangeSize = llvm::ConstantInt::get(
CGM.IntTy, 1);
1090 auto *Space = llvm::ConstantInt::get(
CGM.IntTy, Binding.
getSpace());
1095 llvm::Intrinsic::ID IntrinsicID =
1096 CGM.getHLSLRuntime().getCreateHandleFromBindingIntrinsic();
1097 auto *RegSlot = llvm::ConstantInt::get(
CGM.IntTy, Binding.
getSlot());
1098 SmallVector<Value *> Args{Space, RegSlot, RangeSize, Index, Name};
1102 llvm::Intrinsic::ID IntrinsicID =
1103 CGM.getHLSLRuntime().getCreateHandleFromImplicitBindingIntrinsic();
1106 SmallVector<Value *> Args{OrderID, Space, RangeSize, Index, Name};
1112 llvm::GlobalVariable *GV) {
1113 if (
auto Attr = VD->
getAttr<HLSLVkExtBuiltinInputAttr>())
1118 if (!
CGM.shouldEmitConvergenceTokens())
1122 for (
auto I = BB.begin(); I != E; ++I) {
1123 auto *II = dyn_cast<llvm::IntrinsicInst>(&*I);
1124 if (II && llvm::isConvergenceControlIntrinsic(II->getIntrinsicID())) {
1128 llvm_unreachable(
"Convergence token should have been emitted.");
1165 for (
auto *OVE : Visitor.
OVEs) {
1168 if (OpaqueValueMappingData::shouldBindAsLValue(OVE)) {
1170 OpaqueValueMappingData::bind(CGF, OVE, LV);
1173 OpaqueValueMappingData::bind(CGF, OVE, RV);
1182 "expected resource array subscript expression");
1188 dyn_cast_or_null<VarDecl>(getArrayDecl(ArraySubsExpr));
1190 return std::nullopt;
1196 "expected array of resource classes");
1202 Value *Index =
nullptr;
1204 while (ASE !=
nullptr) {
1206 if (
const auto *ArrayTy =
1208 Value *Multiplier = llvm::ConstantInt::get(
1210 SubIndex = CGF.
Builder.CreateMul(SubIndex, Multiplier);
1212 Index = Index ? CGF.
Builder.CreateAdd(Index, SubIndex) : SubIndex;
1220 "resource array must have a binding attribute");
1241 llvm::Value *Range =
1242 llvm::ConstantInt::get(
CGM.IntTy, getTotalArraySize(AST, ResArrayTy));
1246 if (ResultTy == ResourceTy) {
1248 CXXMethodDecl *CreateMethod = lookupResourceInitMethodAndSetupArgs(
1250 ArrayDecl->
getName(), Binding, Args);
1256 return std::nullopt;
1258 callResourceInitMethod(CGF, CreateMethod, Args, ValueSlot.getAddress());
1265 std::optional<llvm::Value *> EndIndex = initializeLocalResourceArray(
1267 ArrayDecl->
getName(), Binding, {llvm::ConstantInt::get(CGM.IntTy, 0)},
1270 return std::nullopt;
1277 llvm::function_ref<llvm::Value *(
bool Promote)> EmitIdxAfterBase) {
1281 llvm::Type *LayoutTy =
1283 uint64_t LayoutSizeInBits =
1284 CGM.getDataLayout().getTypeSizeInBits(LayoutTy).getFixedValue();
1287 if (RowAlignedSize > ElementSize) {
1288 llvm::Type *Padding =
CGM.getTargetCodeGenInfo().getHLSLPadding(
1289 CGM, RowAlignedSize - ElementSize);
1290 assert(Padding &&
"No padding type for target?");
1291 LayoutTy = llvm::StructType::get(CGF.
getLLVMContext(), {LayoutTy, Padding},
1298 if (LayoutTy == OrigTy)
1299 return std::nullopt;
1305 llvm::Value *Idx = EmitIdxAfterBase(
true);
1311 Indices.push_back(Idx);
1312 Indices.push_back(llvm::ConstantInt::get(CGF.
Int32Ty, 0));
1315 Indices,
"cbufferidx");
1324class HLSLBufferCopyEmitter {
1328 llvm::Type *LayoutTy =
nullptr;
1333 void emitCopyAtIndices(llvm::Type *FieldTy, llvm::ConstantInt *StoreIndex,
1334 llvm::ConstantInt *LoadIndex) {
1335 CurStoreIndices.push_back(StoreIndex);
1336 CurLoadIndices.push_back(LoadIndex);
1337 auto RestoreIndices = llvm::make_scope_exit([&]() {
1338 CurStoreIndices.pop_back();
1339 CurLoadIndices.pop_back();
1343 if (processArray(FieldTy))
1345 if (processBufferLayoutArray(FieldTy))
1347 if (processStruct(FieldTy))
1355 CurLoadIndices,
"cbuf.src"),
1358 DestPtr, CurStoreIndices, FieldTy, Align,
"cbuf.dest");
1363 bool processArray(llvm::Type *FieldTy) {
1364 auto *AT = dyn_cast<llvm::ArrayType>(FieldTy);
1370 for (
unsigned I = 0, E = AT->getNumElements(); I < E; ++I)
1371 emitCopyAtIndices(AT->getElementType(),
1372 llvm::ConstantInt::get(CGF.
SizeTy, I),
1373 llvm::ConstantInt::get(CGF.
SizeTy, I));
1377 bool processBufferLayoutArray(llvm::Type *FieldTy) {
1383 auto *ST = dyn_cast<llvm::StructType>(FieldTy);
1384 if (!ST || ST->getNumElements() != 2)
1387 auto *PaddedEltsTy = dyn_cast<llvm::ArrayType>(ST->getElementType(0));
1391 auto *PaddedTy = dyn_cast<llvm::StructType>(PaddedEltsTy->getElementType());
1392 if (!PaddedTy || PaddedTy->getNumElements() != 2)
1396 PaddedTy->getElementType(1)))
1399 llvm::Type *ElementTy = ST->getElementType(1);
1400 if (PaddedTy->getElementType(0) != ElementTy)
1404 unsigned NumElts = PaddedEltsTy->getNumElements() + 1;
1408 CurLoadIndices.push_back(llvm::ConstantInt::get(CGF.
Int32Ty, 0));
1409 for (
unsigned I = 0; I < NumElts - 1; ++I) {
1411 CurLoadIndices.push_back(llvm::ConstantInt::get(CGF.
SizeTy, I));
1412 emitCopyAtIndices(ElementTy, llvm::ConstantInt::get(CGF.
SizeTy, I),
1413 llvm::ConstantInt::get(CGF.
Int32Ty, 0));
1414 CurLoadIndices.pop_back();
1416 CurLoadIndices.pop_back();
1419 emitCopyAtIndices(ElementTy,
1420 llvm::ConstantInt::get(CGF.
SizeTy, NumElts - 1),
1421 llvm::ConstantInt::get(CGF.
Int32Ty, 1));
1426 bool processStruct(llvm::Type *FieldTy) {
1427 auto *ST = dyn_cast<llvm::StructType>(FieldTy);
1432 unsigned Skipped = 0;
1433 for (
unsigned I = 0, E = ST->getNumElements(); I < E; ++I) {
1434 llvm::Type *ElementTy = ST->getElementType(I);
1438 emitCopyAtIndices(ElementTy, llvm::ConstantInt::get(CGF.
Int32Ty, I),
1439 llvm::ConstantInt::get(CGF.
Int32Ty, I + Skipped));
1445 HLSLBufferCopyEmitter(CodeGenFunction &CGF, Address DestPtr, Address SrcPtr)
1446 : CGF(CGF), DestPtr(DestPtr), SrcPtr(SrcPtr) {}
1448 bool emitCopy(QualType CType) {
1449 LayoutTy = HLSLBufferLayoutBuilder(CGF.
CGM).layOutType(CType);
1456 emitCopyAtIndices(LayoutTy, llvm::ConstantInt::get(CGF.
SizeTy, 0),
1457 llvm::ConstantInt::get(CGF.
SizeTy, 0));
1465 return HLSLBufferCopyEmitter(CGF, DestPtr, SrcPtr).emitCopy(CType);
1473 assert(Field &&
"Unexpected access into HLSL buffer");
1478 CGM.getTypes().getCGRecordLayout(Rec).getLLVMFieldNo(Field);
1481 QualType RecType =
CGM.getContext().getCanonicalTagType(Rec);
1492 QualType FieldType = Field->getType();
1493 llvm::Type *FieldLLVMTy =
CGM.getTypes().ConvertTypeForMem(FieldType);
1497 FieldIdx, Field->getName()),
1502 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)
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)
void addBuffer(const HLSLBufferDecl *D)
void generateGlobalCtorDtorCalls()
llvm::Value * emitSystemSemanticLoad(llvm::IRBuilder<> &B, llvm::Type *Type, const clang::DeclaratorDecl *Decl, HLSLAppliedSemanticAttr *Semantic, std::optional< unsigned > Index)
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
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.
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.
field_iterator field_end() const
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