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 (CGM.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