@@ -4759,6 +4759,137 @@ Instruction *SPIRVToLLVM::transRelational(SPIRVInstruction *I, BasicBlock *BB) {
47594759 return cast<Instruction>(Mutator.getMutated ());
47604760}
47614761
4762+ std::optional<SPIRVModuleReport> getSpirvReport (std::istream &IS) {
4763+ int IgnoreErrCode;
4764+ return getSpirvReport (IS, IgnoreErrCode);
4765+ }
4766+
4767+ std::optional<SPIRVModuleReport> getSpirvReport (std::istream &IS,
4768+ int &ErrCode) {
4769+ SPIRVWord Word;
4770+ std::string Name;
4771+ std::unique_ptr<SPIRVModule> BM (SPIRVModule::createSPIRVModule ());
4772+ SPIRVDecoder D (IS, *BM);
4773+ D >> Word;
4774+ if (Word != MagicNumber) {
4775+ ErrCode = SPIRVEC_InvalidMagicNumber;
4776+ return {};
4777+ }
4778+ D >> Word;
4779+ if (!isSPIRVVersionKnown (Word)) {
4780+ ErrCode = SPIRVEC_InvalidVersionNumber;
4781+ return {};
4782+ }
4783+ SPIRVModuleReport Report;
4784+ Report.Version = static_cast <SPIRV::VersionNumber>(Word);
4785+ // Skip: Generator’s magic number, Bound and Reserved word
4786+ D.ignore (3 );
4787+
4788+ bool IsReportGenCompleted = false , IsMemoryModelDefined = false ;
4789+ while (!IS.bad () && !IsReportGenCompleted && D.getWordCountAndOpCode ()) {
4790+ switch (D.OpCode ) {
4791+ case OpCapability:
4792+ D >> Word;
4793+ Report.Capabilities .push_back (Word);
4794+ break ;
4795+ case OpExtension:
4796+ Name.clear ();
4797+ D >> Name;
4798+ Report.Extensions .push_back (Name);
4799+ break ;
4800+ case OpExtInstImport:
4801+ Name.clear ();
4802+ D >> Word >> Name;
4803+ Report.ExtendedInstructionSets .push_back (Name);
4804+ break ;
4805+ case OpMemoryModel:
4806+ if (IsMemoryModelDefined) {
4807+ ErrCode = SPIRVEC_RepeatedMemoryModel;
4808+ return {};
4809+ }
4810+ SPIRVAddressingModelKind AddrModel;
4811+ SPIRVMemoryModelKind MemoryModel;
4812+ D >> AddrModel >> MemoryModel;
4813+ if (!isValid (AddrModel)) {
4814+ ErrCode = SPIRVEC_InvalidAddressingModel;
4815+ return {};
4816+ }
4817+ if (!isValid (MemoryModel)) {
4818+ ErrCode = SPIRVEC_InvalidMemoryModel;
4819+ return {};
4820+ }
4821+ Report.MemoryModel = MemoryModel;
4822+ Report.AddrModel = AddrModel;
4823+ IsMemoryModelDefined = true ;
4824+ // In this report we don't analyze instructions after OpMemoryModel
4825+ IsReportGenCompleted = true ;
4826+ break ;
4827+ default :
4828+ // No more instructions to gather information about
4829+ IsReportGenCompleted = true ;
4830+ }
4831+ }
4832+ if (IS.bad ()) {
4833+ ErrCode = SPIRVEC_InvalidModule;
4834+ return {};
4835+ }
4836+ if (!IsMemoryModelDefined) {
4837+ ErrCode = SPIRVEC_UnspecifiedMemoryModel;
4838+ return {};
4839+ }
4840+ ErrCode = SPIRVEC_Success;
4841+ return std::make_optional (std::move (Report));
4842+ }
4843+
4844+ constexpr std::string_view formatAddressingModel (uint32_t AddrModel) {
4845+ switch (AddrModel) {
4846+ case AddressingModelLogical:
4847+ return " Logical" ;
4848+ case AddressingModelPhysical32:
4849+ return " Physical32" ;
4850+ case AddressingModelPhysical64:
4851+ return " Physical64" ;
4852+ case AddressingModelPhysicalStorageBuffer64:
4853+ return " PhysicalStorageBuffer64" ;
4854+ default :
4855+ return " Unknown" ;
4856+ }
4857+ }
4858+
4859+ constexpr std::string_view formatMemoryModel (uint32_t MemoryModel) {
4860+ switch (MemoryModel) {
4861+ case MemoryModelSimple:
4862+ return " Simple" ;
4863+ case MemoryModelGLSL450:
4864+ return " GLSL450" ;
4865+ case MemoryModelOpenCL:
4866+ return " OpenCL" ;
4867+ case MemoryModelVulkan:
4868+ return " Vulkan" ;
4869+ default :
4870+ return " Unknown" ;
4871+ }
4872+ }
4873+
4874+ SPIRVModuleTextReport formatSpirvReport (const SPIRVModuleReport &Report) {
4875+ SPIRVModuleTextReport TextReport;
4876+ TextReport.Version =
4877+ formatVersionNumber (static_cast <uint32_t >(Report.Version ));
4878+ TextReport.AddrModel = formatAddressingModel (Report.AddrModel );
4879+ TextReport.MemoryModel = formatMemoryModel (Report.MemoryModel );
4880+ // format capability codes as strings
4881+ std::string Name;
4882+ for (auto Capability : Report.Capabilities ) {
4883+ bool Found = SPIRVCapabilityNameMap::find (
4884+ static_cast <SPIRVCapabilityKind>(Capability), &Name);
4885+ TextReport.Capabilities .push_back (Found ? Name : " Unknown" );
4886+ }
4887+ // other fields with string content can be copied as is
4888+ TextReport.Extensions = Report.Extensions ;
4889+ TextReport.ExtendedInstructionSets = Report.ExtendedInstructionSets ;
4890+ return TextReport;
4891+ }
4892+
47624893std::unique_ptr<SPIRVModule> readSpirvModule (std::istream &IS,
47634894 const SPIRV::TranslatorOpts &Opts,
47644895 std::string &ErrMsg) {
0 commit comments