spv_result_t AggregateStats(const spv_context_t& context, const uint32_t* words, const size_t num_words, spv_diagnostic* pDiagnostic, SpirvStats* stats) { spv_const_binary_t binary = {words, num_words}; spv_endianness_t endian; spv_position_t position = {}; if (spvBinaryEndianness(&binary, &endian)) { return libspirv::DiagnosticStream(position, context.consumer, SPV_ERROR_INVALID_BINARY) << "Invalid SPIR-V magic number."; } spv_header_t header; if (spvBinaryHeaderGet(&binary, endian, &header)) { return libspirv::DiagnosticStream(position, context.consumer, SPV_ERROR_INVALID_BINARY) << "Invalid SPIR-V header."; } StatsAggregator stats_aggregator(stats, &context); return spvBinaryParse(&context, &stats_aggregator, words, num_words, ProcessHeader, ProcessInstruction, pDiagnostic); }
spv_result_t spvBinaryToText(const spv_const_context context, const uint32_t* code, const size_t wordCount, const uint32_t options, spv_text* pText, spv_diagnostic* pDiagnostic) { // Invalid arguments return error codes, but don't necessarily generate // diagnostics. These are programmer errors, not user errors. if (!pDiagnostic) return SPV_ERROR_INVALID_DIAGNOSTIC; const libspirv::AssemblyGrammar grammar(context); if (!grammar.isValid()) return SPV_ERROR_INVALID_TABLE; // Generate friendly names for Ids if requested. std::unique_ptr<libspirv::FriendlyNameMapper> friendly_mapper; libspirv::NameMapper name_mapper = libspirv::GetTrivialNameMapper(); if (options & SPV_BINARY_TO_TEXT_OPTION_FRIENDLY_NAMES) { friendly_mapper.reset( new libspirv::FriendlyNameMapper(context, code, wordCount)); name_mapper = friendly_mapper->GetNameMapper(); } // Now disassemble! Disassembler disassembler(grammar, options, name_mapper); if (auto error = spvBinaryParse(context, &disassembler, code, wordCount, DisassembleHeader, DisassembleInstruction, pDiagnostic)) { return error; } return disassembler.SaveTextResult(pText); }
FriendlyNameMapper::FriendlyNameMapper(const spv_const_context context, const uint32_t* code, const size_t wordCount) : grammar_(libspirv::AssemblyGrammar(context)) { spv_diagnostic diag = nullptr; // We don't care if the parse fails. spvBinaryParse(context, this, code, wordCount, nullptr, ParseInstructionForwarder, &diag); spvDiagnosticDestroy(diag); }
intermediate_type parse_intermediate(std::istream &stream) { std::shared_ptr<spv_context_t> context( spvContextCreate(SPV_ENV_VULKAN_1_0), spvContextDestroy); assert(context); const std::string content(std::istreambuf_iterator<char>(stream.rdbuf()), std::istreambuf_iterator<char>()); intermediate_type intermediate; spv_diagnostic diagnostic; spvBinaryParse(context.get(), &intermediate, (uint32_t *) content.c_str(), content.size() / sizeof(uint32_t), &parsed_header, &parsed_instruction, &diagnostic); return intermediate; }
std::unique_ptr<ir::IRContext> BuildModule(spv_target_env env, MessageConsumer consumer, const uint32_t* binary, const size_t size) { auto context = spvContextCreate(env); libspirv::SetContextMessageConsumer(context, consumer); auto irContext = MakeUnique<ir::IRContext>(env, consumer); ir::IrLoader loader(consumer, irContext->module()); spv_result_t status = spvBinaryParse(context, &loader, binary, size, SetSpvHeader, SetSpvInst, nullptr); loader.EndModule(); spvContextDestroy(context); return status == SPV_SUCCESS ? std::move(irContext) : nullptr; }
spv_result_t spvBinaryToText(const spv_const_context context, const uint32_t* code, const size_t wordCount, const uint32_t options, spv_text* pText, spv_diagnostic* pDiagnostic) { // Invalid arguments return error codes, but don't necessarily generate // diagnostics. These are programmer errors, not user errors. if (!pDiagnostic) return SPV_ERROR_INVALID_DIAGNOSTIC; const libspirv::AssemblyGrammar grammar(context); if (!grammar.isValid()) return SPV_ERROR_INVALID_TABLE; Disassembler disassembler(grammar, options); if (auto error = spvBinaryParse(context, &disassembler, code, wordCount, DisassembleHeader, DisassembleInstruction, pDiagnostic)) { return error; } return disassembler.SaveTextResult(pText); }