@@ -232,6 +232,9 @@ class SPIRVInstructionSelector : public InstructionSelector {
232232
233233 bool selectUnmergeValues (MachineInstr &I) const ;
234234
235+ void selectHandleFromBinding (Register &ResVReg, const SPIRVType *ResType,
236+ MachineInstr &I) const ;
237+
235238 // Utilities
236239 Register buildI32Constant (uint32_t Val, MachineInstr &I,
237240 const SPIRVType *ResType = nullptr ) const ;
@@ -252,6 +255,9 @@ class SPIRVInstructionSelector : public InstructionSelector {
252255 uint32_t Opcode) const ;
253256 MachineInstrBuilder buildConstGenericPtr (MachineInstr &I, Register SrcPtr,
254257 SPIRVType *SrcPtrTy) const ;
258+ Register buildPointerToResource (const SPIRVType *ResType, uint32_t Set,
259+ uint32_t Binding, uint32_t ArraySize,
260+ MachineIRBuilder MIRBuilder) const ;
255261};
256262
257263} // end anonymous namespace
@@ -2549,6 +2555,10 @@ bool SPIRVInstructionSelector::selectIntrinsic(Register ResVReg,
25492555 // Discard internal intrinsics.
25502556 case Intrinsic::spv_value_md:
25512557 break ;
2558+ case Intrinsic::spv_handle_fromBinding: {
2559+ selectHandleFromBinding (ResVReg, ResType, I);
2560+ return true ;
2561+ }
25522562 default : {
25532563 std::string DiagMsg;
25542564 raw_string_ostream OS (DiagMsg);
@@ -2560,6 +2570,34 @@ bool SPIRVInstructionSelector::selectIntrinsic(Register ResVReg,
25602570 return true ;
25612571}
25622572
2573+ void SPIRVInstructionSelector::selectHandleFromBinding (Register &ResVReg,
2574+ const SPIRVType *ResType,
2575+ MachineInstr &I) const {
2576+
2577+ uint32_t Set = foldImm (I.getOperand (2 ), MRI);
2578+ uint32_t Binding = foldImm (I.getOperand (3 ), MRI);
2579+ uint32_t ArraySize = foldImm (I.getOperand (4 ), MRI);
2580+
2581+ MachineIRBuilder MIRBuilder (I);
2582+ Register VarReg =
2583+ buildPointerToResource (ResType, Set, Binding, ArraySize, MIRBuilder);
2584+
2585+ // TODO: For now we assume the resource is an image, which needs to be
2586+ // loaded to get the handle. That will not be true for storage buffers.
2587+ BuildMI (*I.getParent (), I, I.getDebugLoc (), TII.get (SPIRV::OpLoad))
2588+ .addDef (ResVReg)
2589+ .addUse (GR.getSPIRVTypeID (ResType))
2590+ .addUse (VarReg);
2591+ }
2592+
2593+ Register SPIRVInstructionSelector::buildPointerToResource (
2594+ const SPIRVType *ResType, uint32_t Set, uint32_t Binding,
2595+ uint32_t ArraySize, MachineIRBuilder MIRBuilder) const {
2596+ assert (ArraySize == 1 && " Resource arrays are not implemented yet." );
2597+ return GR.getOrCreateGlobalVariableWithBinding (ResType, Set, Binding,
2598+ MIRBuilder);
2599+ }
2600+
25632601bool SPIRVInstructionSelector::selectAllocaArray (Register ResVReg,
25642602 const SPIRVType *ResType,
25652603 MachineInstr &I) const {
@@ -2863,15 +2901,7 @@ bool SPIRVInstructionSelector::selectSpvThreadId(Register ResVReg,
28632901 // Get Thread ID index. Expecting operand is a constant immediate value,
28642902 // wrapped in a type assignment.
28652903 assert (I.getOperand (2 ).isReg ());
2866- Register ThreadIdReg = I.getOperand (2 ).getReg ();
2867- SPIRVType *ConstTy = this ->MRI ->getVRegDef (ThreadIdReg);
2868- assert (ConstTy && ConstTy->getOpcode () == SPIRV::ASSIGN_TYPE &&
2869- ConstTy->getOperand (1 ).isReg ());
2870- Register ConstReg = ConstTy->getOperand (1 ).getReg ();
2871- const MachineInstr *Const = this ->MRI ->getVRegDef (ConstReg);
2872- assert (Const && Const->getOpcode () == TargetOpcode::G_CONSTANT);
2873- const llvm::APInt &Val = Const->getOperand (1 ).getCImm ()->getValue ();
2874- const uint32_t ThreadId = Val.getZExtValue ();
2904+ const uint32_t ThreadId = foldImm (I.getOperand (2 ), MRI);
28752905
28762906 // Extract the thread ID from the loaded vector value.
28772907 MachineBasicBlock &BB = *I.getParent ();
0 commit comments