@@ -4852,6 +4852,137 @@ Instruction *SPIRVToLLVM::transRelational(SPIRVInstruction *I, BasicBlock *BB) {
48524852 &BtnInfo, &Attrs, /* TakeFuncName=*/ true )));
48534853}
48544854
4855+ llvm::Optional<SPIRVModuleReport> getSpirvReport (std::istream &IS) {
4856+ int IgnoreErrCode;
4857+ return getSpirvReport (IS, IgnoreErrCode);
4858+ }
4859+
4860+ llvm::Optional<SPIRVModuleReport> getSpirvReport (std::istream &IS,
4861+ int &ErrCode) {
4862+ SPIRVWord Word;
4863+ std::string Name;
4864+ std::unique_ptr<SPIRVModule> BM (SPIRVModule::createSPIRVModule ());
4865+ SPIRVDecoder D (IS, *BM);
4866+ D >> Word;
4867+ if (Word != MagicNumber) {
4868+ ErrCode = SPIRVEC_InvalidMagicNumber;
4869+ return {};
4870+ }
4871+ D >> Word;
4872+ if (!isSPIRVVersionKnown (Word)) {
4873+ ErrCode = SPIRVEC_InvalidVersionNumber;
4874+ return {};
4875+ }
4876+ SPIRVModuleReport Report;
4877+ Report.Version = static_cast <SPIRV::VersionNumber>(Word);
4878+ // Skip: Generator’s magic number, Bound and Reserved word
4879+ D.ignore (3 );
4880+
4881+ bool IsReportGenCompleted = false , IsMemoryModelDefined = false ;
4882+ while (!IS.bad () && !IsReportGenCompleted && D.getWordCountAndOpCode ()) {
4883+ switch (D.OpCode ) {
4884+ case OpCapability:
4885+ D >> Word;
4886+ Report.Capabilities .push_back (Word);
4887+ break ;
4888+ case OpExtension:
4889+ Name.clear ();
4890+ D >> Name;
4891+ Report.Extensions .push_back (Name);
4892+ break ;
4893+ case OpExtInstImport:
4894+ Name.clear ();
4895+ D >> Word >> Name;
4896+ Report.ExtendedInstructionSets .push_back (Name);
4897+ break ;
4898+ case OpMemoryModel:
4899+ if (IsMemoryModelDefined) {
4900+ ErrCode = SPIRVEC_RepeatedMemoryModel;
4901+ return {};
4902+ }
4903+ SPIRVAddressingModelKind AddrModel;
4904+ SPIRVMemoryModelKind MemoryModel;
4905+ D >> AddrModel >> MemoryModel;
4906+ if (!isValid (AddrModel)) {
4907+ ErrCode = SPIRVEC_InvalidAddressingModel;
4908+ return {};
4909+ }
4910+ if (!isValid (MemoryModel)) {
4911+ ErrCode = SPIRVEC_InvalidMemoryModel;
4912+ return {};
4913+ }
4914+ Report.MemoryModel = MemoryModel;
4915+ Report.AddrModel = AddrModel;
4916+ IsMemoryModelDefined = true ;
4917+ // In this report we don't analyze instructions after OpMemoryModel
4918+ IsReportGenCompleted = true ;
4919+ break ;
4920+ default :
4921+ // No more instructions to gather information about
4922+ IsReportGenCompleted = true ;
4923+ }
4924+ }
4925+ if (IS.bad ()) {
4926+ ErrCode = SPIRVEC_InvalidModule;
4927+ return {};
4928+ }
4929+ if (!IsMemoryModelDefined) {
4930+ ErrCode = SPIRVEC_UnspecifiedMemoryModel;
4931+ return {};
4932+ }
4933+ ErrCode = SPIRVEC_Success;
4934+ return llvm::Optional<SPIRV::SPIRVModuleReport>(std::move (Report));
4935+ }
4936+
4937+ std::string formatAddressingModel (uint32_t AddrModel) {
4938+ switch (AddrModel) {
4939+ case AddressingModelLogical:
4940+ return " Logical" ;
4941+ case AddressingModelPhysical32:
4942+ return " Physical32" ;
4943+ case AddressingModelPhysical64:
4944+ return " Physical64" ;
4945+ case AddressingModelPhysicalStorageBuffer64:
4946+ return " PhysicalStorageBuffer64" ;
4947+ default :
4948+ return " Unknown" ;
4949+ }
4950+ }
4951+
4952+ std::string formatMemoryModel (uint32_t MemoryModel) {
4953+ switch (MemoryModel) {
4954+ case MemoryModelSimple:
4955+ return " Simple" ;
4956+ case MemoryModelGLSL450:
4957+ return " GLSL450" ;
4958+ case MemoryModelOpenCL:
4959+ return " OpenCL" ;
4960+ case MemoryModelVulkan:
4961+ return " Vulkan" ;
4962+ default :
4963+ return " Unknown" ;
4964+ }
4965+ }
4966+
4967+ SPIRVModuleTextReport formatSpirvReport (const SPIRVModuleReport &Report) {
4968+ SPIRVModuleTextReport TextReport;
4969+ TextReport.Version =
4970+ formatVersionNumber (static_cast <uint32_t >(Report.Version ));
4971+ TextReport.AddrModel = formatAddressingModel (Report.AddrModel );
4972+ TextReport.MemoryModel = formatMemoryModel (Report.MemoryModel );
4973+ // format capability codes as strings
4974+ std::string Name;
4975+ for (auto Capability : Report.Capabilities ) {
4976+ const bool Found = SPIRVCapabilityNameMap::find (
4977+ static_cast <SPIRVCapabilityKind>(Capability), &Name);
4978+ TextReport.Capabilities .push_back (Found ? Name : " Unknown" );
4979+ }
4980+ // other fields with string content can be copied as is
4981+ TextReport.Extensions = Report.Extensions ;
4982+ TextReport.ExtendedInstructionSets = Report.ExtendedInstructionSets ;
4983+ return TextReport;
4984+ }
4985+
48554986std::unique_ptr<SPIRVModule> readSpirvModule (std::istream &IS,
48564987 const SPIRV::TranslatorOpts &Opts,
48574988 std::string &ErrMsg) {
0 commit comments