clang: lib/CodeGen/CGHLSLRuntime.cpp Source File (original) (raw)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
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"
47#include
48#include
49
50using namespace clang;
53using namespace llvm;
54
55using llvm::hlsl::CBufferRowSizeInBytes;
56
57namespace {
58
59void addDxilValVersion(StringRef ValVersionStr, llvm::Module &M) {
60
61
62 VersionTuple Version;
63 if (Version.tryParse(ValVersionStr) || Version.getBuild() ||
64 Version.getSubminor() || !Version.getMinor()) {
65 return;
66 }
67
68 uint64_t Major = Version.getMajor();
69 uint64_t Minor = *Version.getMinor();
70
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);
78}
79
80void addRootSignatureMD(llvm::dxbc::RootSignatureVersion RootSigVer,
82 llvm::Function *Fn, llvm::Module &M) {
83 auto &Ctx = M.getContext();
84
85 llvm::hlsl::rootsig::MetadataBuilder RSBuilder(Ctx, Elements);
86 MDNode *RootSignature = RSBuilder.BuildRootSignature();
87
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});
92
93 StringRef RootSignatureValKey = "dx.rootsignatures";
94 auto *RootSignatureValMD = M.getOrInsertNamedMetadata(RootSignatureValKey);
95 RootSignatureValMD->addOperand(MDVals);
96}
97
98
99static const ValueDecl *getArrayDecl(const Expr *E) {
102 return DRE->getDecl();
103 return nullptr;
104}
105
106
108 const Expr *E = nullptr;
109 while (ASE != nullptr) {
111 if (!E)
112 return nullptr;
113 ASE = dyn_cast(E);
114 }
115 return getArrayDecl(E);
116}
117
118
121 assert(Ty->isArrayType() && "expected array type");
123 return -1;
125}
126
127static Value *buildNameForResource(llvm::StringRef BaseName,
132}
133
136 for (auto *Method : Record->methods()) {
137 if (Method->getStorageClass() == SC && Method->getName() == Name)
138 return Method;
139 }
140 return nullptr;
141}
142
143static CXXMethodDecl *lookupResourceInitMethodAndSetupArgs(
147 assert(Binding.hasBinding() && "at least one binding attribute expected");
148
151 Value *NameStr = buildNameForResource(Name, CGM);
152 Value *Space = llvm::ConstantInt::get(CGM.IntTy, Binding.getSpace());
153
155
156 auto *RegSlot = llvm::ConstantInt::get(CGM.IntTy, Binding.getSlot());
159 ? "__createFromBindingWithImplicitCounter"
160 : "__createFromBinding";
161 CreateMethod = lookupMethod(ResourceDecl, Name, SC_Static);
162 } else {
163
164 auto *OrderID =
168 ? "__createFromImplicitBindingWithImplicitCounter"
169 : "__createFromImplicitBinding";
170 CreateMethod = lookupMethod(ResourceDecl, Name, SC_Static);
171 }
178 auto *CounterOrderID = llvm::ConstantInt::get(CGM.IntTy, CounterBinding);
180 }
181
182 return CreateMethod;
183}
184
195 CGF.EmitCall(FnInfo, Callee, ReturnValue, Args, nullptr);
196}
197
198
199
200
201
202
203static std::optional<llvm::Value *> initializeLocalResourceArray(
206 llvm::Value *Range, llvm::Value *StartIndex, StringRef ResourceName,
209
211 llvm::IntegerType *IntTy = CGF.CGM.IntTy;
212 llvm::Value *Index = StartIndex;
213 llvm::Value *One = llvm::ConstantInt::get(IntTy, 1);
214 const uint64_t ArraySize = ArrayTy->getSExtSize();
217
218
219
221 GEPIndices.push_back(llvm::ConstantInt::get(IntTy, 0));
222
223
226 for (uint64_t I = 0; I < ArraySize; I++) {
227 if (I > 0) {
228 Index = CGF.Builder.CreateAdd(Index, One);
229 GEPIndices.back() = llvm::ConstantInt::get(IntTy, I);
230 }
231 std::optional<llvm::Value *> MaybeIndex = initializeLocalResourceArray(
232 CGF, ResourceDecl, SubArrayTy, ValueSlot, Range, Index, ResourceName,
233 Binding, GEPIndices, ArraySubsExprLoc);
234 if (!MaybeIndex)
235 return std::nullopt;
236 Index = *MaybeIndex;
237 }
238 return Index;
239 }
240
241
246
247 for (uint64_t I = 0; I < ArraySize; I++) {
248 if (I > 0) {
249 Index = CGF.Builder.CreateAdd(Index, One);
250 GEPIndices.back() = llvm::ConstantInt::get(IntTy, I);
251 }
254
256 CXXMethodDecl *CreateMethod = lookupResourceInitMethodAndSetupArgs(
257 CGF.CGM, ResourceDecl, Range, Index, ResourceName, Binding, Args);
258
259 if (!CreateMethod)
260
261
262
263 return std::nullopt;
264
265 callResourceInitMethod(CGF, CreateMethod, Args, ReturnAddress);
266 }
267 return Index;
268}
269
270}
271
272llvm::Type *
275 assert(T->isHLSLSpecificType() && "Not an HLSL specific type!");
276
277
278 if (llvm::Type *TargetTy =
279 CGM.getTargetCodeGenInfo().getHLSLType(CGM, T, OffsetInfo))
280 return TargetTy;
281
282 llvm_unreachable("Generic handling of HLSL types is not supported.");
283}
284
285llvm::Triple::ArchType CGHLSLRuntime::getArch() {
287}
288
289
290
291void CGHLSLRuntime::emitBufferGlobalsAndMetadata(
292 const HLSLBufferDecl *BufDecl, llvm::GlobalVariable *BufGV,
295
296
297 llvm::Type *BufType = BufGV->getValueType();
300
302 size_t OffsetIdx = 0;
305
306 continue;
308
310 continue;
311 }
312 VarDecl *VD = dyn_cast(D);
313 if (!VD)
314 continue;
315
321
322
324 } else {
325
326
328 "constant buffer decl with non-zero sized type outside of "
329 "hlsl_constant address space");
330 }
331 continue;
332 }
333
334 DeclsWithOffset.emplace_back(VD, OffsetInfo[OffsetIdx++]);
335 }
336
337 if (!OffsetInfo.empty())
338 llvm::stable_sort(DeclsWithOffset, [](const auto &LHS, const auto &RHS) {
340 });
341
342
343 SmallVector<llvm::Metadata *> BufGlobals;
344 BufGlobals.reserve(DeclsWithOffset.size() + 1);
345 BufGlobals.push_back(ValueAsMetadata::get(BufGV));
346
347 auto ElemIt = LayoutStruct->element_begin();
348 for (auto &[VD, _] : DeclsWithOffset) {
349 if (CGM.getTargetCodeGenInfo().isHLSLPadding(*ElemIt))
350 ++ElemIt;
351
352 assert(ElemIt != LayoutStruct->element_end() &&
353 "number of elements in layout struct does not match");
354 llvm::Type *LayoutType = *ElemIt++;
355
356 GlobalVariable *ElemGV =
358 BufGlobals.push_back(ValueAsMetadata::get(ElemGV));
359 }
360 assert(ElemIt == LayoutStruct->element_end() &&
361 "number of elements in layout struct does not match");
362
363
364 CGM.getModule()
365 .getOrInsertNamedMetadata("hlsl.cbs")
366 ->addOperand(MDNode::get(Ctx, BufGlobals));
367}
368
369
370static const clang::HLSLAttributedResourceType *
375 HLSLAttributedResourceType::Attributes(ResourceClass::CBuffer));
377}
378
381
382
385
388 continue;
389 }
390 VarDecl *VD = dyn_cast(D);
392 continue;
393
396 continue;
397 }
398
401 if (auto *POA = dyn_cast(Attr)) {
402 Offset = POA->getOffsetInBytes();
403 break;
404 }
405 auto *RBA = dyn_cast(Attr);
406 if (RBA &&
407 RBA->getRegisterType() == HLSLResourceBindingAttr::RegisterType::C) {
408 Offset = RBA->getSlotNumber() * CBufferRowSizeInBytes;
409 break;
410 }
411 }
412 Result.Offsets.push_back(Offset);
413 }
415}
416
417
419
420 assert(BufDecl->isCBuffer() && "tbuffer codegen is not supported yet");
421
422
423 const clang::HLSLAttributedResourceType *ResHandleTy =
425
426
427 if (ResHandleTy->getContainedType()->getAsCXXRecordDecl()->isEmpty())
428 return;
429
430
433 llvm::GlobalVariable *BufGV = new GlobalVariable(
434 LayoutTy, false,
435 GlobalValue::LinkageTypes::ExternalLinkage, PoisonValue::get(LayoutTy),
436 llvm::formatv("{0}{1}", BufDecl->getName(),
437 BufDecl->isCBuffer() ? ".cb" : ".tb"),
438 GlobalValue::NotThreadLocal);
439 CGM.getModule().insertGlobalVariable(BufGV);
440
441
442 emitBufferGlobalsAndMetadata(BufDecl, BufGV, OffsetInfo);
443
444
445 initializeBufferFromBinding(BufDecl, BufGV);
446}
447
450 llvm::Module &M = CGM.getModule();
451 Triple T(M.getTargetTriple());
452
453
454 if (T.getEnvironment() != Triple::EnvironmentType::RootSignature)
455 return;
456
457 addRootSignatureMD(SignatureDecl->getVersion(),
459}
460
461llvm::StructType *
463 const auto Entry = LayoutTypes.find(StructType);
464 if (Entry != LayoutTypes.end())
465 return Entry->getSecond();
466 return nullptr;
467}
468
470 llvm::StructType *LayoutTy) {
472 "layout type for this struct already exist");
473 LayoutTypes[StructType] = LayoutTy;
474}
475
477 auto &TargetOpts = CGM.getTarget().getTargetOpts();
478 auto &CodeGenOpts = CGM.getCodeGenOpts();
479 auto &LangOpts = CGM.getLangOpts();
480 llvm::Module &M = CGM.getModule();
481 Triple T(M.getTargetTriple());
482 if (T.getArch() == Triple::ArchType::dxil)
483 addDxilValVersion(TargetOpts.DxilValidatorVersion, M);
484 if (CodeGenOpts.ResMayAlias)
485 M.setModuleFlag(llvm::Module::ModFlagBehavior::Error, "dx.resmayalias", 1);
486
487
488
489
490 if (LangOpts.NativeHalfType)
491 M.setModuleFlag(llvm::Module::ModFlagBehavior::Error, "dx.nativelowprec",
492 1);
493
495}
496
498 const FunctionDecl *FD, llvm::Function *Fn) {
499 const auto *ShaderAttr = FD->getAttr();
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()) {
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);
510 }
511 if (HLSLWaveSizeAttr *WaveSizeAttr = FD->getAttr()) {
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);
517 }
518
519
520
521
522
523 if (CGM.getCodeGenOpts().OptimizationLevel == 0)
524 Fn->addFnAttr(llvm::Attribute::OptimizeNone);
525 Fn->addFnAttr(llvm::Attribute::NoInline);
526
527 if (CGM.getLangOpts().HLSLSpvEnableMaximalReconvergence) {
528 Fn->addFnAttr("enable-maximal-reconvergence", "true");
529 }
530}
531
533 if (const auto *VT = dyn_cast(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);
538 }
539 return Result;
540 }
541 return B.CreateCall(F, {B.getInt32(0)});
542}
543
545 unsigned BuiltIn) {
546 LLVMContext &Ctx = GV->getContext();
547 IRBuilder<> B(GV->getContext());
548 MDNode *Operands = MDNode::get(
549 Ctx,
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);
554}
555
557 LLVMContext &Ctx = GV->getContext();
558 IRBuilder<> B(GV->getContext());
559 MDNode *Operands =
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);
564}
565
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,
573 7, true);
575 GV->setVisibility(llvm::GlobalValue::HiddenVisibility);
576 return B.CreateLoad(Ty, GV);
577}
578
580 llvm::Type *Ty, unsigned Location,
581 StringRef Name) {
582 auto *GV = new llvm::GlobalVariable(
583 M, Ty, true, llvm::GlobalValue::ExternalLinkage,
584 nullptr, Name, nullptr,
585 llvm::GlobalVariable::GeneralDynamicTLSModel,
586 7, true);
587 GV->setVisibility(llvm::GlobalValue::HiddenVisibility);
589 return B.CreateLoad(Ty, GV);
590}
591
592llvm::Value *CGHLSLRuntime::emitSPIRVUserSemanticLoad(
593 llvm::IRBuilder<> &B, llvm::Type *Type, const clang::DeclaratorDecl *Decl,
594 HLSLAppliedSemanticAttr *Semantic, std::optional Index) {
595 Twine BaseName = Twine(Semantic->getAttrName()->getName());
596 Twine VariableName = BaseName.concat(Twine(Index.value_or(0)));
597
598 unsigned Location = SPIRVLastAssignedInputSemanticLocation;
599 if (auto *L = Decl->getAttr())
600 Location = L->getLocation();
601
602
603
604 llvm::ArrayType *AT = dyn_castllvm::ArrayType(Type);
605 unsigned ElementCount = AT ? AT->getNumElements() : 1;
606 SPIRVLastAssignedInputSemanticLocation += ElementCount;
607
609 VariableName.str());
610}
611
613 llvm::Value *Source, unsigned Location,
614 StringRef Name) {
615 auto *GV = new llvm::GlobalVariable(
616 M, Source->getType(), false,
617 llvm::GlobalValue::ExternalLinkage,
618 nullptr, Name, nullptr,
619 llvm::GlobalVariable::GeneralDynamicTLSModel,
620 8, false);
621 GV->setVisibility(llvm::GlobalValue::HiddenVisibility);
623 B.CreateStore(Source, GV);
624}
625
626void CGHLSLRuntime::emitSPIRVUserSemanticStore(
627 llvm::IRBuilder<> &B, llvm::Value *Source,
628 const clang::DeclaratorDecl *Decl, HLSLAppliedSemanticAttr *Semantic,
629 std::optional Index) {
630 Twine BaseName = Twine(Semantic->getAttrName()->getName());
631 Twine VariableName = BaseName.concat(Twine(Index.value_or(0)));
632
633 unsigned Location = SPIRVLastAssignedOutputSemanticLocation;
634 if (auto *L = Decl->getAttr())
635 Location = L->getLocation();
636
637
638
639 llvm::ArrayType *AT = dyn_castllvm::ArrayType(Source->getType());
640 unsigned ElementCount = AT ? AT->getNumElements() : 1;
641 SPIRVLastAssignedOutputSemanticLocation += ElementCount;
643 VariableName.str());
644}
645
646llvm::Value *
647CGHLSLRuntime::emitDXILUserSemanticLoad(llvm::IRBuilder<> &B, llvm::Type *Type,
648 HLSLAppliedSemanticAttr *Semantic,
649 std::optional Index) {
650 Twine BaseName = Twine(Semantic->getAttrName()->getName());
651 Twine VariableName = BaseName.concat(Twine(Index.value_or(0)));
652
653
654
655
656 SmallVector<Value *> Args{B.getInt32(4), B.getInt32(0), B.getInt32(0),
657 B.getInt8(0),
658 llvm::PoisonValue::get(B.getInt32Ty())};
659
660 llvm::Intrinsic::ID IntrinsicID = llvm::Intrinsic::dx_load_input;
661 llvm::Value *Value = B.CreateIntrinsic(Type, IntrinsicID, Args,
662 nullptr, VariableName);
664}
665
666void CGHLSLRuntime::emitDXILUserSemanticStore(llvm::IRBuilder<> &B,
667 llvm::Value *Source,
668 HLSLAppliedSemanticAttr *Semantic,
669 std::optional Index) {
670
671
672 SmallVector<Value *> Args{B.getInt32(4),
673 B.getInt32(0),
674 B.getInt32(0),
675 B.getInt8(0),
676 llvm::PoisonValue::get(B.getInt32Ty()),
677 Source};
678
679 llvm::Intrinsic::ID IntrinsicID = llvm::Intrinsic::dx_store_output;
680 B.CreateIntrinsic(CGM.VoidTy, IntrinsicID, Args, nullptr);
681}
682
683llvm::Value *CGHLSLRuntime::emitUserSemanticLoad(
684 IRBuilder<> &B, llvm::Type *Type, const clang::DeclaratorDecl *Decl,
685 HLSLAppliedSemanticAttr *Semantic, std::optional Index) {
686 if (CGM.getTarget().getTriple().isSPIRV())
687 return emitSPIRVUserSemanticLoad(B, Type, Decl, Semantic, Index);
688
689 if (CGM.getTarget().getTriple().isDXIL())
690 return emitDXILUserSemanticLoad(B, Type, Semantic, Index);
691
692 llvm_unreachable("Unsupported target for user-semantic load.");
693}
694
695void CGHLSLRuntime::emitUserSemanticStore(IRBuilder<> &B, llvm::Value *Source,
696 const clang::DeclaratorDecl *Decl,
697 HLSLAppliedSemanticAttr *Semantic,
698 std::optional Index) {
699 if (CGM.getTarget().getTriple().isSPIRV())
700 return emitSPIRVUserSemanticStore(B, Source, Decl, Semantic, Index);
701
702 if (CGM.getTarget().getTriple().isDXIL())
703 return emitDXILUserSemanticStore(B, Source, Semantic, Index);
704
705 llvm_unreachable("Unsupported target for user-semantic load.");
706}
707
711 std::optional Index) {
712
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));
718 }
719
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);
727 }
728
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);
736 }
737
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);
745 }
746
747 const auto *ShaderAttr = FD->getAttr();
748 assert(ShaderAttr && "Entry point has no shader attribute");
749 llvm::Triple::EnvironmentType ST = ShaderAttr->getType();
750
751 if (SemanticName == "SV_POSITION") {
752 if (ST == Triple::EnvironmentType::Pixel) {
753 if (CGM.getTarget().getTriple().isSPIRV())
755 Semantic->getAttrName()->getName(),
756 15);
757 if (CGM.getTarget().getTriple().isDXIL())
758 return emitDXILUserSemanticLoad(B, Type, Semantic, Index);
759 }
760
761 if (ST == Triple::EnvironmentType::Vertex) {
762 return emitUserSemanticLoad(B, Type, Decl, Semantic, Index);
763 }
764 }
765
766 llvm_unreachable(
767 "Load hasn't been implemented yet for this system semantic. FIXME");
768}
769
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,
778 8, false);
780 GV->setVisibility(llvm::GlobalValue::HiddenVisibility);
781 B.CreateStore(Source, GV);
782}
783
786 HLSLAppliedSemanticAttr *Semantic,
787 std::optional Index) {
788
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);
793 return;
794 }
795
796 if (CGM.getTarget().getTriple().isSPIRV()) {
798 Semantic->getAttrName()->getName(),
799 0);
800 return;
801 }
802 }
803
804 if (SemanticName == "SV_TARGET") {
805 emitUserSemanticStore(B, Source, Decl, Semantic, Index);
806 return;
807 }
808
809 llvm_unreachable(
810 "Store hasn't been implemented yet for this system semantic. FIXME");
811}
812
816
817 std::optional Index = Semantic->getSemanticIndex();
818 if (Semantic->getAttrName()->getName().starts_with_insensitive("SV_"))
820 return emitUserSemanticLoad(B, Type, Decl, Semantic, Index);
821}
822
824 IRBuilder<> &B, const FunctionDecl *FD, llvm::Value *Source,
826 std::optional Index = Semantic->getSemanticIndex();
827 if (Semantic->getAttrName()->getName().starts_with_insensitive("SV_"))
829 else
830 emitUserSemanticStore(B, Source, Decl, Semantic, Index);
831}
832
833std::pair<llvm::Value *, specific_attr_iterator>
841
842 assert(RD->getNumFields() == ST->getNumElements());
843
844 llvm::Value *Aggregate = llvm::PoisonValue::get(Type);
846 for (unsigned I = 0; I < ST->getNumElements(); ++I) {
848 B, FD, ST->getElementType(I), *FieldDecl, AttrBegin, AttrEnd);
849 AttrBegin = NextAttr;
850 assert(ChildValue);
853 }
854
855 return std::make_pair(Aggregate, AttrBegin);
856}
857
860 IRBuilder<> &B, const FunctionDecl *FD, llvm::Value *Source,
864
865 const llvm::StructType *ST = cast(Source->getType());
866
870 else
871 RD = Decl->getType()->getAsRecordDecl();
872 assert(RD);
873
874 assert(RD->getNumFields() == ST->getNumElements());
875
877 for (unsigned I = 0; I < ST->getNumElements(); ++I) {
878 llvm::Value *Extract = B.CreateExtractValue(Source, I);
879 AttrBegin =
881 }
882
883 return AttrBegin;
884}
885
886std::pair<llvm::Value *, specific_attr_iterator>
892 assert(AttrBegin != AttrEnd);
893 if (Type->isStructTy())
895
896 HLSLAppliedSemanticAttr *Attr = *AttrBegin;
897 ++AttrBegin;
899 AttrBegin);
900}
901
904 IRBuilder<> &B, const FunctionDecl *FD, llvm::Value *Source,
908 assert(AttrBegin != AttrEnd);
909 if (Source->getType()->isStructTy())
911
912 HLSLAppliedSemanticAttr *Attr = *AttrBegin;
913 ++AttrBegin;
915 return AttrBegin;
916}
917
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);
925
926
927
928 AttributeList NewAttrs = AttributeList::get(Ctx, AttributeList::FunctionIndex,
929 Fn->getAttributes().getFnAttrs());
930 EntryFn->setAttributes(NewAttrs);
932
933
934 Fn->setLinkage(GlobalValue::InternalLinkage);
935
936 BasicBlock *BB = BasicBlock::Create(Ctx, "entry", EntryFn);
937 IRBuilder<> B(BB);
939
941 if (CGM.shouldEmitConvergenceTokens()) {
942 assert(EntryFn->isConvergent());
943 llvm::Value *I =
944 B.CreateIntrinsic(llvm::Intrinsic::experimental_convergence_entry, {});
945 llvm::Value *bundleArgs[] = {I};
946 OB.emplace_back("convergencectrl", bundleArgs);
947 }
948
949 llvm::DenseMap<const DeclaratorDecl *, llvm::Value *> OutputSemantic;
950
951 unsigned SRetOffset = 0;
952 for (const auto &Param : Fn->args()) {
953 if (Param.hasStructRetAttr()) {
954 SRetOffset = 1;
955 llvm::Type *VarType = Param.getParamStructRetType();
956 llvm::Value *Var = B.CreateAlloca(VarType);
957 OutputSemantic.try_emplace(FD, Var);
958 Args.push_back(Var);
959 continue;
960 }
961
963 llvm::Value *SemanticValue = nullptr;
964
965 if ([[maybe_unused]] HLSLParamModifierAttr *MA =
966 PD->getAttr()) {
967 llvm_unreachable("Not handled yet");
968 } else {
969 llvm::Type *ParamType =
970 Param.hasByValAttr() ? Param.getParamByValType() : Param.getType();
975 SemanticValue = Result.first;
976 if (!SemanticValue)
977 return;
978 if (Param.hasByValAttr()) {
979 llvm::Value *Var = B.CreateAlloca(Param.getParamByValType());
980 B.CreateStore(SemanticValue, Var);
981 SemanticValue = Var;
982 }
983 }
984
985 assert(SemanticValue);
986 Args.push_back(SemanticValue);
987 }
988
989 CallInst *CI = B.CreateCall(FunctionCallee(Fn), Args, OB);
990 CI->setCallingConv(Fn->getCallingConv());
991
992 if (Fn->getReturnType() != CGM.VoidTy)
993 OutputSemantic.try_emplace(FD, CI);
994
995 for (auto &[Decl, Source] : OutputSemantic) {
996 AllocaInst *AI = dyn_cast(Source);
997 llvm::Value *SourceValue =
998 AI ? B.CreateLoad(AI->getAllocatedType(), Source) : Source;
999
1000 auto AttrBegin = Decl->specific_attr_begin();
1001 auto AttrEnd = Decl->specific_attr_end();
1003 }
1004
1005 B.CreateRetVoid();
1006
1007
1009 if (const auto *RSAttr = dyn_cast(Attr)) {
1010 auto *RSDecl = RSAttr->getSignatureDecl();
1011 addRootSignatureMD(RSDecl->getVersion(), RSDecl->getRootElements(),
1012 EntryFn, M);
1013 }
1014 }
1015}
1016
1018 bool CtorOrDtor) {
1019 const auto *GV =
1020 M.getNamedGlobal(CtorOrDtor ? "llvm.global_ctors" : "llvm.global_dtors");
1021 if (!GV)
1022 return;
1023 const auto *CA = dyn_cast(GV->getInitializer());
1024 if (!CA)
1025 return;
1026
1027
1028
1029
1030 for (const auto &Ctor : CA->operands()) {
1032 continue;
1034
1035 assert(cast(CS->getOperand(0))->getValue() == 65535 &&
1036 "HLSL doesn't support setting priority for global ctors.");
1038 "HLSL doesn't support COMDat for global ctors.");
1040 }
1041}
1042
1044 llvm::Module &M = CGM.getModule();
1049
1050
1051
1052
1053 for (auto &F : M.functions()) {
1054 if (!F.hasFnAttribute("hlsl.shader"))
1055 continue;
1057 Instruction *IP = &*F.getEntryBlock().begin();
1060 llvm::Value *bundleArgs[] = {Token};
1061 OB.emplace_back("convergencectrl", bundleArgs);
1062 IP = Token->getNextNode();
1063 }
1064 IRBuilder<> B(IP);
1065 for (auto *Fn : CtorFns) {
1066 auto CI = B.CreateCall(FunctionCallee(Fn), {}, OB);
1067 CI->setCallingConv(Fn->getCallingConv());
1068 }
1069
1070
1071 B.SetInsertPoint(F.back().getTerminator());
1072 for (auto *Fn : DtorFns) {
1073 auto CI = B.CreateCall(FunctionCallee(Fn), {}, OB);
1074 CI->setCallingConv(Fn->getCallingConv());
1075 }
1076 }
1077
1078
1079
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();
1086 }
1087}
1088
1090 Intrinsic::ID IntrID,
1092
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);
1099
1100 llvm::BasicBlock *EntryBB =
1101 llvm::BasicBlock::Create(Ctx, "entry", InitResFunc);
1103 const DataLayout &DL = CGM.getModule().getDataLayout();
1104 Builder.SetInsertPoint(EntryBB);
1105
1106
1107 llvm::Type *HandleTy = GV->getValueType();
1108 assert(HandleTy->isTargetExtTy() && "unexpected type of the buffer global");
1109
1110 llvm::Value *CreateHandle = Builder.CreateIntrinsic(
1111 HandleTy, IntrID, Args, nullptr,
1112 Twine(GV->getName()).concat("_h"));
1113
1114 llvm::Value *HandleRef = Builder.CreateStructGEP(GV->getValueType(), GV, 0);
1115 Builder.CreateAlignedStore(CreateHandle, HandleRef,
1116 HandleRef->getPointerAlignment(DL));
1117 Builder.CreateRetVoid();
1118
1120}
1121
1122void CGHLSLRuntime::initializeBufferFromBinding(const HLSLBufferDecl *BufDecl,
1123 llvm::GlobalVariable *GV) {
1124 ResourceBindingAttrs Binding(BufDecl);
1126 "cbuffer/tbuffer should always have resource binding attribute");
1127
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());
1131 Value *Name = buildNameForResource(BufDecl->getName(), CGM);
1132
1133
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};
1140 } else {
1141
1142 llvm::Intrinsic::ID IntrinsicID =
1143 CGM.getHLSLRuntime().getCreateHandleFromImplicitBindingIntrinsic();
1144 auto *OrderID =
1146 SmallVector<Value *> Args{OrderID, Space, RangeSize, Index, Name};
1148 }
1149}
1150
1152 llvm::GlobalVariable *GV) {
1153 if (auto Attr = VD->getAttr())
1155}
1156
1158 if (.shouldEmitConvergenceTokens())
1159 return nullptr;
1160
1161 auto E = BB.end();
1162 for (auto I = BB.begin(); I != E; ++I) {
1163 auto *II = dyn_castllvm::IntrinsicInst(&*I);
1164 if (II && llvm::isConvergenceControlIntrinsic(II->getIntrinsicID())) {
1165 return II;
1166 }
1167 }
1168 llvm_unreachable("Convergence token should have been emitted.");
1169 return nullptr;
1170}
1171
1173public:
1177
1179
1180
1181
1182
1183 return false;
1184 }
1185
1187
1190
1191
1192 if (Visited.insert(E).second)
1193 OVEs.push_back(E);
1194
1195 return true;
1196 }
1197};
1198
1201
1205 for (auto *OVE : Visitor.OVEs) {
1207 continue;
1208 if (OpaqueValueMappingData::shouldBindAsLValue(OVE)) {
1210 OpaqueValueMappingData::bind(CGF, OVE, LV);
1211 } else {
1213 OpaqueValueMappingData::bind(CGF, OVE, RV);
1214 }
1215 }
1216}
1217
1222 "expected resource array subscript expression");
1223
1224
1225
1226
1227 const VarDecl *ArrayDecl =
1228 dyn_cast_or_null(getArrayDecl(ArraySubsExpr));
1231 return std::nullopt;
1232
1233
1237 "expected array of resource classes");
1238
1239
1240
1241
1242
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);
1252 }
1253 Index = Index ? CGF.Builder.CreateAdd(Index, SubIndex) : SubIndex;
1255 }
1256
1257
1258
1261 "resource array must have a binding attribute");
1262
1263
1267
1268
1269
1270
1275
1280
1281
1282 llvm::Value *Range =
1283 llvm::ConstantInt::get(CGM.IntTy, getTotalArraySize(AST, ResArrayTy));
1284
1285
1286
1287 if (ResultTy == ResourceTy) {
1289 CXXMethodDecl *CreateMethod = lookupResourceInitMethodAndSetupArgs(
1291 ArrayDecl->getName(), Binding, Args);
1292
1293 if (!CreateMethod)
1294
1295
1296
1297 return std::nullopt;
1298
1299 callResourceInitMethod(CGF, CreateMethod, Args, ValueSlot.getAddress());
1300
1301 } else {
1302
1303
1306 std::optional<llvm::Value *> EndIndex = initializeLocalResourceArray(
1307 CGF, ResourceTy->getAsCXXRecordDecl(), ArrayTy, ValueSlot, Range, Index,
1308 ArrayDecl->getName(), Binding, {llvm::ConstantInt::get(CGM.IntTy, 0)},
1310 if (!EndIndex)
1311 return std::nullopt;
1312 }
1314}
1315
1316
1317
1318
1323
1324
1325 const VarDecl *ArrayDecl = dyn_cast_or_null(getArrayDecl(RHSExpr));
1328 return false;
1329
1330
1331
1334 "resource array must have a binding attribute");
1335
1336
1340
1341
1346
1347
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);
1351
1352
1353 std::optional<llvm::Value *> EndIndex = initializeLocalResourceArray(
1356 return EndIndex.has_value();
1357}
1358
1361 llvm::function_ref<llvm::Value *(bool Promote)> EmitIdxAfterBase) {
1362
1363
1364
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},
1376 true);
1377 }
1378
1379
1380
1382 if (LayoutTy == OrigTy)
1383 return std::nullopt;
1384
1389 llvm::Value *Idx = EmitIdxAfterBase( true);
1390
1391
1392
1393
1395 Indices.push_back(Idx);
1396 Indices.push_back(llvm::ConstantInt::get(CGF.Int32Ty, 0));
1397
1398 llvm::Value *GEP = CGF.Builder.CreateGEP(LayoutTy, Addr.emitRawPointer(CGF),
1399 Indices, "cbufferidx");
1401
1403}
1404
1405namespace {
1406
1407
1408class HLSLBufferCopyEmitter {
1412 llvm::Type *LayoutTy = nullptr;
1413
1416
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();
1424 });
1425
1426
1427 if (processArray(FieldTy))
1428 return;
1429 if (processBufferLayoutArray(FieldTy))
1430 return;
1431 if (processStruct(FieldTy))
1432 return;
1433
1434
1439 CurLoadIndices, "cbuf.src"),
1442 DestPtr, CurStoreIndices, FieldTy, Align, "cbuf.dest");
1443 llvm::Value *Load = CGF.Builder.CreateLoad(SrcGEP, "cbuf.load");
1445 }
1446
1447 bool processArray(llvm::Type *FieldTy) {
1448 auto *AT = dyn_castllvm::ArrayType(FieldTy);
1449 if (!AT)
1450 return false;
1451
1452
1453
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));
1458 return true;
1459 }
1460
1461 bool processBufferLayoutArray(llvm::Type *FieldTy) {
1462
1463
1464
1465
1466
1467 auto *ST = dyn_castllvm::StructType(FieldTy);
1468 if (!ST || ST->getNumElements() != 2)
1469 return false;
1470
1471 auto *PaddedEltsTy = dyn_castllvm::ArrayType(ST->getElementType(0));
1472 if (!PaddedEltsTy)
1473 return false;
1474
1475 auto *PaddedTy = dyn_castllvm::StructType(PaddedEltsTy->getElementType());
1476 if (!PaddedTy || PaddedTy->getNumElements() != 2)
1477 return false;
1478
1480 PaddedTy->getElementType(1)))
1481 return false;
1482
1483 llvm::Type *ElementTy = ST->getElementType(1);
1484 if (PaddedTy->getElementType(0) != ElementTy)
1485 return false;
1486
1487
1488 unsigned NumElts = PaddedEltsTy->getNumElements() + 1;
1489
1490
1491
1492 CurLoadIndices.push_back(llvm::ConstantInt::get(CGF.Int32Ty, 0));
1493 for (unsigned I = 0; I < NumElts - 1; ++I) {
1494
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();
1499 }
1500 CurLoadIndices.pop_back();
1501
1502
1503 emitCopyAtIndices(ElementTy,
1504 llvm::ConstantInt::get(CGF.SizeTy, NumElts - 1),
1505 llvm::ConstantInt::get(CGF.Int32Ty, 1));
1506
1507 return true;
1508 }
1509
1510 bool processStruct(llvm::Type *FieldTy) {
1511 auto *ST = dyn_castllvm::StructType(FieldTy);
1512 if (!ST)
1513 return false;
1514
1515
1516 unsigned Skipped = 0;
1517 for (unsigned I = 0, E = ST->getNumElements(); I < E; ++I) {
1518 llvm::Type *ElementTy = ST->getElementType(I);
1520 ++Skipped;
1521 else
1522 emitCopyAtIndices(ElementTy, llvm::ConstantInt::get(CGF.Int32Ty, I),
1523 llvm::ConstantInt::get(CGF.Int32Ty, I + Skipped));
1524 }
1525 return true;
1526 }
1527
1528public:
1529 HLSLBufferCopyEmitter(CodeGenFunction &CGF, Address DestPtr, Address SrcPtr)
1530 : CGF(CGF), DestPtr(DestPtr), SrcPtr(SrcPtr) {}
1531
1532 bool emitCopy(QualType CType) {
1533 LayoutTy = HLSLBufferLayoutBuilder(CGF.CGM).layOutType(CType);
1534
1535
1536
1537
1538
1539
1540 emitCopyAtIndices(LayoutTy, llvm::ConstantInt::get(CGF.SizeTy, 0),
1541 llvm::ConstantInt::get(CGF.SizeTy, 0));
1542 return true;
1543 }
1544};
1545}
1546
1549 return HLSLBufferCopyEmitter(CGF, DestPtr, SrcPtr).emitCopy(CType);
1550}
1551
1556 auto *Field = dyn_cast(E->getMemberDecl());
1557 assert(Field && "Unexpected access into HLSL buffer");
1558
1559
1561 unsigned FieldIdx =
1562 CGM.getTypes().getCGRecordLayout(Rec).getLLVMFieldNo(Field);
1563
1564
1565 QualType RecType = CGM.getContext().getCanonicalTagType(Rec);
1567
1568
1569
1572 RecType->getAsCanonical(), EmptyOffsets);
1573
1574
1575
1576 QualType FieldType = Field->getType();
1577 llvm::Type *FieldLLVMTy = CGM.getTypes().ConvertTypeForMem(FieldType);
1581 FieldIdx, Field->getName()),
1583
1586 CGM.getTBAAAccessInfo(FieldType));
1588
1589 return LV;
1590}
Defines the clang::ASTContext interface.
static llvm::Value * createSPIRVBuiltinLoad(IRBuilder<> &B, llvm::Module &M, llvm::Type *Ty, const Twine &Name, unsigned BuiltInID)
Definition CGHLSLRuntime.cpp:566
static void addSPIRVBuiltinDecoration(llvm::GlobalVariable *GV, unsigned BuiltIn)
Definition CGHLSLRuntime.cpp:544
static void createSPIRVLocationStore(IRBuilder<> &B, llvm::Module &M, llvm::Value *Source, unsigned Location, StringRef Name)
Definition CGHLSLRuntime.cpp:612
static void gatherFunctions(SmallVectorImpl< Function * > &Fns, llvm::Module &M, bool CtorOrDtor)
Definition CGHLSLRuntime.cpp:1017
static void addLocationDecoration(llvm::GlobalVariable *GV, unsigned Location)
Definition CGHLSLRuntime.cpp:556
static llvm::Value * createSPIRVLocationLoad(IRBuilder<> &B, llvm::Module &M, llvm::Type *Ty, unsigned Location, StringRef Name)
Definition CGHLSLRuntime.cpp:579
static Value * buildVectorInput(IRBuilder<> &B, Function *F, llvm::Type *Ty)
Definition CGHLSLRuntime.cpp:532
static void initializeBuffer(CodeGenModule &CGM, llvm::GlobalVariable *GV, Intrinsic::ID IntrID, ArrayRef< llvm::Value * > Args)
Definition CGHLSLRuntime.cpp:1089
static const clang::HLSLAttributedResourceType * createBufferHandleType(const HLSLBufferDecl *BufDecl)
Definition CGHLSLRuntime.cpp:371
static void createSPIRVBuiltinStore(IRBuilder<> &B, llvm::Module &M, llvm::Value *Source, const Twine &Name, unsigned BuiltInID)
Definition CGHLSLRuntime.cpp:770
llvm::MachO::Record Record
Defines the clang::TargetOptions class.
C Language Family Type Representation.
Definition CGHLSLRuntime.cpp:1172
bool VisitHLSLOutArgExpr(HLSLOutArgExpr *)
Definition CGHLSLRuntime.cpp:1178
llvm::SmallVector< OpaqueValueExpr *, 8 > OVEs
Definition CGHLSLRuntime.cpp:1174
bool VisitOpaqueValueExpr(OpaqueValueExpr *E)
Definition CGHLSLRuntime.cpp:1186
OpaqueValueVisitor()
Definition CGHLSLRuntime.cpp:1176
llvm::SmallPtrSet< OpaqueValueExpr *, 8 > Visited
Definition CGHLSLRuntime.cpp:1175
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...
Definition CGHLSLRuntime.cpp:379
llvm::Instruction * getConvergenceToken(llvm::BasicBlock &BB)
Definition CGHLSLRuntime.cpp:1157
void setHLSLEntryAttributes(const FunctionDecl *FD, llvm::Function *Fn)
Definition CGHLSLRuntime.cpp:497
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)
Definition CGHLSLRuntime.cpp:903
llvm::StructType * getHLSLBufferLayoutType(const RecordType *LayoutStructTy)
Definition CGHLSLRuntime.cpp:462
void emitEntryFunction(const FunctionDecl *FD, llvm::Function *Fn)
Definition CGHLSLRuntime.cpp:918
void handleGlobalVarDefinition(const VarDecl *VD, llvm::GlobalVariable *Var)
Definition CGHLSLRuntime.cpp:1151
void emitSystemSemanticStore(llvm::IRBuilder<> &B, llvm::Value *Source, const clang::DeclaratorDecl *Decl, HLSLAppliedSemanticAttr *Semantic, std::optional< unsigned > Index)
Definition CGHLSLRuntime.cpp:784
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)
Definition CGHLSLRuntime.cpp:834
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)
Definition CGHLSLRuntime.cpp:859
llvm::Value * handleScalarSemanticLoad(llvm::IRBuilder<> &B, const FunctionDecl *FD, llvm::Type *Type, const clang::DeclaratorDecl *Decl, HLSLAppliedSemanticAttr *Semantic)
Definition CGHLSLRuntime.cpp:813
void addHLSLBufferLayoutType(const RecordType *LayoutStructTy, llvm::StructType *LayoutTy)
Definition CGHLSLRuntime.cpp:469
void finishCodeGen()
Definition CGHLSLRuntime.cpp:476
void handleScalarSemanticStore(llvm::IRBuilder<> &B, const FunctionDecl *FD, llvm::Value *Source, const clang::DeclaratorDecl *Decl, HLSLAppliedSemanticAttr *Semantic)
Definition CGHLSLRuntime.cpp:823
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)
Definition CGHLSLRuntime.cpp:887
std::optional< LValue > emitBufferArraySubscriptExpr(const ArraySubscriptExpr *E, CodeGenFunction &CGF, llvm::function_ref< llvm::Value *(bool Promote)> EmitIdxAfterBase)
Definition CGHLSLRuntime.cpp:1359
std::optional< LValue > emitResourceArraySubscriptExpr(const ArraySubscriptExpr *E, CodeGenFunction &CGF)
Definition CGHLSLRuntime.cpp:1218
void addRootSignature(const HLSLRootSignatureDecl *D)
Definition CGHLSLRuntime.cpp:448
bool emitResourceArrayCopy(LValue &LHS, Expr *RHSExpr, CodeGenFunction &CGF)
Definition CGHLSLRuntime.cpp:1319
LValue emitBufferMemberExpr(CodeGenFunction &CGF, const MemberExpr *E)
Definition CGHLSLRuntime.cpp:1552
bool emitBufferCopy(CodeGenFunction &CGF, Address DestPtr, Address SrcPtr, QualType CType)
Definition CGHLSLRuntime.cpp:1547
llvm::Type * convertHLSLSpecificType(const Type *T, const CGHLSLOffsetInfo &OffsetInfo)
Definition CGHLSLRuntime.cpp:273
llvm::Value * emitSystemSemanticLoad(llvm::IRBuilder<> &B, const FunctionDecl *FD, llvm::Type *Type, const clang::DeclaratorDecl *Decl, HLSLAppliedSemanticAttr *Semantic, std::optional< unsigned > Index)
Definition CGHLSLRuntime.cpp:708
void addBuffer(const HLSLBufferDecl *D)
Definition CGHLSLRuntime.cpp:418
void generateGlobalCtorDtorCalls()
Definition CGHLSLRuntime.cpp:1043
void emitInitListOpaqueValues(CodeGenFunction &CGF, InitListExpr *E)
Definition CGHLSLRuntime.cpp:1199
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'.
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