|
18 | 18 | #include "TargetInfo.h" |
19 | 19 | #include "clang/AST/Decl.h" |
20 | 20 | #include "clang/Basic/TargetOptions.h" |
| 21 | +#include "llvm/IR/GlobalVariable.h" |
| 22 | +#include "llvm/IR/LLVMContext.h" |
21 | 23 | #include "llvm/IR/Metadata.h" |
22 | 24 | #include "llvm/IR/Module.h" |
| 25 | +#include "llvm/IR/Value.h" |
| 26 | +#include "llvm/Support/Alignment.h" |
| 27 | + |
23 | 28 | #include "llvm/Support/FormatVariadic.h" |
24 | 29 |
|
25 | 30 | using namespace clang; |
@@ -489,3 +494,88 @@ void CGHLSLRuntime::generateGlobalCtorDtorCalls() { |
489 | 494 | GV->eraseFromParent(); |
490 | 495 | } |
491 | 496 | } |
| 497 | + |
| 498 | +void CGHLSLRuntime::handleGlobalVarDefinition(const VarDecl *VD, |
| 499 | + llvm::GlobalVariable *GV) { |
| 500 | + // If the global variable has resource binding, add it to the list of globals |
| 501 | + // that need resource binding initialization. |
| 502 | + const HLSLResourceBindingAttr *RBA = VD->getAttr<HLSLResourceBindingAttr>(); |
| 503 | + if (!RBA) |
| 504 | + return; |
| 505 | + |
| 506 | + if (!HLSLAttributedResourceType::findHandleTypeOnResource( |
| 507 | + VD->getType().getTypePtr())) |
| 508 | + // FIXME: Only simple declarations of resources are supported for now. |
| 509 | + // Arrays of resources or resources in user defined classes are |
| 510 | + // not implemented yet. |
| 511 | + return; |
| 512 | + |
| 513 | + ResourcesToBind.emplace_back(VD, GV); |
| 514 | +} |
| 515 | + |
| 516 | +bool CGHLSLRuntime::needsResourceBindingInitFn() { |
| 517 | + return !ResourcesToBind.empty(); |
| 518 | +} |
| 519 | + |
| 520 | +llvm::Function *CGHLSLRuntime::createResourceBindingInitFn() { |
| 521 | + // No resources to bind |
| 522 | + assert(needsResourceBindingInitFn() && "no resources to bind"); |
| 523 | + |
| 524 | + LLVMContext &Ctx = CGM.getLLVMContext(); |
| 525 | + llvm::Type *Int1Ty = llvm::Type::getInt1Ty(Ctx); |
| 526 | + |
| 527 | + llvm::Function *InitResBindingsFunc = |
| 528 | + llvm::Function::Create(llvm::FunctionType::get(CGM.VoidTy, false), |
| 529 | + llvm::GlobalValue::InternalLinkage, |
| 530 | + "_init_resource_bindings", CGM.getModule()); |
| 531 | + |
| 532 | + llvm::BasicBlock *EntryBB = |
| 533 | + llvm::BasicBlock::Create(Ctx, "entry", InitResBindingsFunc); |
| 534 | + CGBuilderTy Builder(CGM, Ctx); |
| 535 | + const DataLayout &DL = CGM.getModule().getDataLayout(); |
| 536 | + Builder.SetInsertPoint(EntryBB); |
| 537 | + |
| 538 | + for (const auto &[VD, GV] : ResourcesToBind) { |
| 539 | + for (Attr *A : VD->getAttrs()) { |
| 540 | + HLSLResourceBindingAttr *RBA = dyn_cast<HLSLResourceBindingAttr>(A); |
| 541 | + if (!RBA) |
| 542 | + continue; |
| 543 | + |
| 544 | + const HLSLAttributedResourceType *AttrResType = |
| 545 | + HLSLAttributedResourceType::findHandleTypeOnResource( |
| 546 | + VD->getType().getTypePtr()); |
| 547 | + |
| 548 | + // FIXME: Only simple declarations of resources are supported for now. |
| 549 | + // Arrays of resources or resources in user defined classes are |
| 550 | + // not implemented yet. |
| 551 | + assert(AttrResType != nullptr && |
| 552 | + "Resource class must have a handle of HLSLAttributedResourceType"); |
| 553 | + |
| 554 | + llvm::Type *TargetTy = |
| 555 | + CGM.getTargetCodeGenInfo().getHLSLType(CGM, AttrResType); |
| 556 | + assert(TargetTy != nullptr && |
| 557 | + "Failed to convert resource handle to target type"); |
| 558 | + |
| 559 | + auto *Space = llvm::ConstantInt::get(CGM.IntTy, RBA->getSpaceNumber()); |
| 560 | + auto *Slot = llvm::ConstantInt::get(CGM.IntTy, RBA->getSlotNumber()); |
| 561 | + // FIXME: resource arrays are not yet implemented |
| 562 | + auto *Range = llvm::ConstantInt::get(CGM.IntTy, 1); |
| 563 | + auto *Index = llvm::ConstantInt::get(CGM.IntTy, 0); |
| 564 | + // FIXME: NonUniformResourceIndex bit is not yet implemented |
| 565 | + auto *NonUniform = llvm::ConstantInt::get(Int1Ty, false); |
| 566 | + llvm::Value *Args[] = {Space, Slot, Range, Index, NonUniform}; |
| 567 | + |
| 568 | + llvm::Value *CreateHandle = Builder.CreateIntrinsic( |
| 569 | + /*ReturnType=*/TargetTy, getCreateHandleFromBindingIntrinsic(), Args, |
| 570 | + nullptr, Twine(VD->getName()).concat("_h")); |
| 571 | + |
| 572 | + llvm::Value *HandleRef = |
| 573 | + Builder.CreateStructGEP(GV->getValueType(), GV, 0); |
| 574 | + Builder.CreateAlignedStore(CreateHandle, HandleRef, |
| 575 | + HandleRef->getPointerAlignment(DL)); |
| 576 | + } |
| 577 | + } |
| 578 | + |
| 579 | + Builder.CreateRetVoid(); |
| 580 | + return InitResBindingsFunc; |
| 581 | +} |
0 commit comments