@@ -572,6 +572,8 @@ class SPIRVModuleImpl : public SPIRVModule {
572572 SPIRVAliasInstMDMap AliasInstMDMap;
573573
574574 void layoutEntry (SPIRVEntry *Entry);
575+ std::istream &parseSPT (std::istream &I);
576+ std::istream &parseSPIRV (std::istream &I);
575577};
576578
577579SPIRVModuleImpl::~SPIRVModuleImpl () {
@@ -2123,70 +2125,273 @@ void SPIRVModuleImpl::addUnknownStructField(SPIRVTypeStruct *Struct, unsigned I,
21232125 UnknownStructFieldMap[Struct].push_back (std::make_pair (I, ID));
21242126}
21252127
2126- std::istream &operator >>(std::istream &I, SPIRVModule &M) {
2127- SPIRVDecoder Decoder (I, M);
2128- SPIRVModuleImpl &MI = *static_cast <SPIRVModuleImpl *>(&M);
2129- // Disable automatic capability filling.
2128+ namespace {
2129+ SPIRVEntry *parseAndCreateSPIRVEntry (SPIRVWord &WordCount, Op &OpCode,
2130+ SPIRVEntry *Scope, SPIRVModuleImpl &M,
2131+ std::istream &IS) {
2132+ if (WordCount == 0 || OpCode == OpNop) {
2133+ return nullptr ;
2134+ }
2135+ SPIRVEntry *Entry = SPIRVEntry::create (OpCode);
2136+ assert (Entry);
2137+ Entry->setModule (&M);
2138+ if (Scope && !isModuleScopeAllowedOpCode (OpCode)) {
2139+ Entry->setScope (Scope);
2140+ }
2141+ Entry->setWordCount (WordCount);
2142+ if (OpCode != OpLine)
2143+ Entry->setLine (M.getCurrentLine ());
2144+ if (!Entry->isExtInst (SPIRVEIS_NonSemantic_Shader_DebugInfo_100,
2145+ SPIRVDebug::DebugLine) &&
2146+ !Entry->isExtInst (SPIRVEIS_NonSemantic_Shader_DebugInfo_200,
2147+ SPIRVDebug::DebugLine)) {
2148+ Entry->setDebugLine (M.getCurrentDebugLine ());
2149+ }
2150+ IS >> *Entry;
2151+ if (Entry->isEndOfBlock () || OpCode == OpNoLine) {
2152+ M.setCurrentLine (nullptr );
2153+ }
2154+ if (Entry->isEndOfBlock () ||
2155+ Entry->isExtInst (SPIRVEIS_NonSemantic_Shader_DebugInfo_100,
2156+ SPIRVDebug::DebugNoLine) ||
2157+ Entry->isExtInst (SPIRVEIS_NonSemantic_Shader_DebugInfo_200,
2158+ SPIRVDebug::DebugNoLine)) {
2159+ M.setCurrentDebugLine (nullptr );
2160+ }
2161+
2162+ if (OpExtension == OpCode) {
2163+ auto *OpExt = static_cast <SPIRVExtension *>(Entry);
2164+ ExtensionID ExtID = {};
2165+ bool ExtIsKnown = SPIRVMap<ExtensionID, std::string>::rfind (
2166+ OpExt->getExtensionName (), &ExtID);
2167+ if (!M.getErrorLog ().checkError (
2168+ ExtIsKnown, SPIRVEC_InvalidModule,
2169+ " input SPIR-V module uses unknown extension '" +
2170+ OpExt->getExtensionName () + " '" )) {
2171+ M.setInvalid ();
2172+ }
2173+
2174+ if (!M.getErrorLog ().checkError (
2175+ M.isAllowedToUseExtension (ExtID), SPIRVEC_InvalidModule,
2176+ " input SPIR-V module uses extension '" + OpExt->getExtensionName () +
2177+ " ' which were disabled by --spirv-ext option" )) {
2178+ M.setInvalid ();
2179+ }
2180+ }
2181+
2182+ if (!M.getErrorLog ().checkError (Entry->isImplemented (),
2183+ SPIRVEC_UnimplementedOpCode,
2184+ std::to_string (Entry->getOpCode ()))) {
2185+ M.setInvalid ();
2186+ }
2187+
2188+ assert (!IS.bad () && !IS.fail () && " SPIRV stream fails" );
2189+ return Entry;
2190+ }
2191+ } // namespace
2192+
2193+ std::istream &SPIRVModuleImpl::parseSPT (std::istream &I) {
2194+ SPIRVModuleImpl &MI = *this ;
21302195 MI.setAutoAddCapability (false );
21312196 MI.setAutoAddExtensions (false );
2197+ auto ReadSPIRVWord = [](std::istream &I) {
2198+ uint32_t W;
2199+ I >> skipcomment >> W;
2200+ SPIRVDBG (spvdbgs () << " Read word: W = " << W << " V = 0\n " );
2201+ return W;
2202+ };
2203+ SPIRVErrorLog ErrorLog = MI.getErrorLog ();
2204+ SPIRVWord Magic = ReadSPIRVWord (I);
2205+
2206+ if (!ErrorLog.checkError (!I.eof (), SPIRVEC_InvalidModule,
2207+ " input file is empty" ) ||
2208+ !ErrorLog.checkError (!I.fail (), SPIRVEC_InvalidModule,
2209+ " header parsing error" )) {
2210+ MI.setInvalid ();
2211+ return I;
2212+ }
21322213
2133- SPIRVWord Magic;
2134- Decoder >> Magic;
2135- if (!M.getErrorLog ().checkError (Magic == MagicNumber, SPIRVEC_InvalidModule,
2136- " invalid magic number" )) {
2137- M.setInvalid ();
2214+ if (!ErrorLog.checkError (Magic == MagicNumber, SPIRVEC_InvalidModule,
2215+ " invalid magic number" )) {
2216+ MI.setInvalid ();
2217+ return I;
2218+ }
2219+
2220+ MI.SPIRVVersion = ReadSPIRVWord (I);
2221+ if (!ErrorLog.checkError (!I.fail (), SPIRVEC_InvalidModule,
2222+ " header parsing error" )) {
2223+ MI.setInvalid ();
21382224 return I;
21392225 }
21402226
2141- Decoder >> MI.SPIRVVersion ;
21422227 bool SPIRVVersionIsKnown = isSPIRVVersionKnown (MI.SPIRVVersion );
2143- if (!M. getErrorLog () .checkError (
2228+ if (!ErrorLog .checkError (
21442229 SPIRVVersionIsKnown, SPIRVEC_InvalidModule,
21452230 " unsupported SPIR-V version number '" + to_string (MI.SPIRVVersion ) +
21462231 " '. Range of supported/known SPIR-V "
21472232 " versions is " +
21482233 to_string (VersionNumber::MinimumVersion) + " - " +
21492234 to_string (VersionNumber::MaximumVersion))) {
2150- M .setInvalid ();
2235+ MI .setInvalid ();
21512236 return I;
21522237 }
21532238
2154- bool SPIRVVersionIsAllowed = M .isAllowedToUseVersion (MI.SPIRVVersion );
2155- if (!M. getErrorLog () .checkError (
2239+ bool SPIRVVersionIsAllowed = MI .isAllowedToUseVersion (MI.SPIRVVersion );
2240+ if (!ErrorLog .checkError (
21562241 SPIRVVersionIsAllowed, SPIRVEC_InvalidModule,
21572242 " incorrect SPIR-V version number " + to_string (MI.SPIRVVersion ) +
21582243 " - it conflicts with maximum allowed version which is set to " +
2159- to_string (M.getMaximumAllowedSPIRVVersion ()))) {
2160- M.setInvalid ();
2244+ to_string (MI.getMaximumAllowedSPIRVVersion ()))) {
2245+ MI.setInvalid ();
2246+ return I;
2247+ }
2248+
2249+ SPIRVWord Generator = ReadSPIRVWord (I);
2250+ if (!ErrorLog.checkError (!I.fail (), SPIRVEC_InvalidModule,
2251+ " header parsing error" )) {
2252+ MI.setInvalid ();
21612253 return I;
21622254 }
21632255
2164- SPIRVWord Generator = 0 ;
2165- Decoder >> Generator;
21662256 MI.GeneratorId = Generator >> 16 ;
21672257 MI.GeneratorVer = Generator & 0xFFFF ;
21682258
21692259 // Bound for Id
2170- Decoder >> MI.NextId ;
2260+ MI.NextId = ReadSPIRVWord (I);
2261+ if (!ErrorLog.checkError (!I.fail (), SPIRVEC_InvalidModule,
2262+ " header parsing error" )) {
2263+ MI.setInvalid ();
2264+ return I;
2265+ }
21712266
2172- Decoder >> MI.InstSchema ;
2173- if (!M. getErrorLog () .checkError (MI.InstSchema == SPIRVISCH_Default,
2174- SPIRVEC_InvalidModule,
2175- " unsupported instruction schema" )) {
2176- M .setInvalid ();
2267+ MI.InstSchema = static_cast <SPIRVInstructionSchemaKind>( ReadSPIRVWord (I)) ;
2268+ if (!ErrorLog .checkError (MI.InstSchema == SPIRVISCH_Default,
2269+ SPIRVEC_InvalidModule,
2270+ " unsupported instruction schema" )) {
2271+ MI .setInvalid ();
21772272 return I;
21782273 }
21792274
2180- while (Decoder.getWordCountAndOpCode () && M.isModuleValid ()) {
2181- SPIRVEntry *Entry = Decoder.getEntry ();
2182- if (Entry != nullptr )
2183- M.add (Entry);
2275+ SPIRVWord WordCount = 0 ;
2276+ Op OpCode = OpNop;
2277+ SPIRVEntry *Scope = nullptr ;
2278+ while (true ) {
2279+ WordCount = ReadSPIRVWord (I);
2280+ if (I.fail ()) {
2281+ SPIRVDBG (spvdbgs () << " getWordCountAndOpCode FAIL 0 0\n " );
2282+ break ;
2283+ }
2284+ std::string RawOp;
2285+ I >> RawOp;
2286+ OpCode = getNameMap (OpCode).rmap (RawOp);
2287+ SPIRVDBG (spvdbgs () << " Read word: W = " << RawOp << " V = " << OpCode
2288+ << ' \n ' );
2289+ if (I.fail ()) {
2290+ SPIRVDBG (spvdbgs () << " getWordCountAndOpCode FAIL 0 0\n " );
2291+ break ;
2292+ }
2293+ SPIRVDBG (spvdbgs () << " getWordCountAndOpCode " << WordCount << " "
2294+ << OpCodeNameMap::map (OpCode) << ' \n ' );
2295+ if (!MI.isModuleValid ()) {
2296+ break ;
2297+ }
2298+
2299+ SPIRVEntry *Entry =
2300+ parseAndCreateSPIRVEntry (WordCount, OpCode, Scope, MI, I);
2301+ if (Entry != nullptr ) {
2302+ MI.add (Entry);
2303+ }
2304+ if (I.eof ()) {
2305+ SPIRVDBG (spvdbgs () << " getWordCountAndOpCode EOF 0 0\n " );
2306+ break ;
2307+ }
21842308 }
21852309
21862310 MI.resolveUnknownStructFields ();
21872311 return I;
21882312}
21892313
2314+ std::istream &SPIRVModuleImpl::parseSPIRV (std::istream &I) {
2315+ SPIRVModuleImpl &MI = *this ;
2316+ MI.setAutoAddCapability (false );
2317+ MI.setAutoAddExtensions (false );
2318+
2319+ SPIRVWord Header[5 ] = {0 };
2320+ I.read (reinterpret_cast <char *>(&Header), sizeof (Header));
2321+
2322+ SPIRVErrorLog ErrorLog = MI.getErrorLog ();
2323+ if (!ErrorLog.checkError (!I.eof (), SPIRVEC_InvalidModule,
2324+ " input file is empty" ) ||
2325+ !ErrorLog.checkError (!I.fail (), SPIRVEC_InvalidModule,
2326+ " header parsing error" ) ||
2327+ !ErrorLog.checkError (Header[0 ] == MagicNumber, SPIRVEC_InvalidModule,
2328+ " invalid magic number" ) ||
2329+ !ErrorLog.checkError (
2330+ isSPIRVVersionKnown (Header[1 ]), SPIRVEC_InvalidModule,
2331+ " unsupported SPIR-V version number '" + to_string (Header[1 ]) +
2332+ " '. Range of supported/known SPIR-V "
2333+ " versions is " +
2334+ to_string (VersionNumber::MinimumVersion) + " - " +
2335+ to_string (VersionNumber::MaximumVersion)) ||
2336+ !ErrorLog.checkError (
2337+ MI.isAllowedToUseVersion (Header[1 ]), SPIRVEC_InvalidModule,
2338+ " incorrect SPIR-V version number " + to_string (Header[1 ]) +
2339+ " - it conflicts with maximum allowed version which is set to " +
2340+ to_string (MI.getMaximumAllowedSPIRVVersion ())) ||
2341+ !ErrorLog.checkError (Header[4 ] == SPIRVISCH_Default,
2342+ SPIRVEC_InvalidModule,
2343+ " unsupported instruction schema" )) {
2344+ MI.setInvalid ();
2345+ return I;
2346+ }
2347+
2348+ MI.SPIRVVersion = Header[1 ];
2349+ MI.GeneratorId = Header[2 ] >> 16 ;
2350+ MI.GeneratorVer = Header[2 ] & 0xFFFF ;
2351+ MI.NextId = Header[3 ];
2352+ MI.InstSchema = static_cast <SPIRVInstructionSchemaKind>(Header[4 ]);
2353+
2354+ SPIRVEntry *Scope = nullptr ;
2355+ while (true ) {
2356+ SPIRVWord WordCountAndOpCode = 0 ;
2357+ I.read (reinterpret_cast <char *>(&WordCountAndOpCode), sizeof (SPIRVWord));
2358+ SPIRVDBG (spvdbgs () << " Read word: W = " << WordCountAndOpCode
2359+ << " V = 0\n " );
2360+ SPIRVWord WordCount = WordCountAndOpCode >> 16 ;
2361+ Op OpCode = static_cast <Op>(WordCountAndOpCode & 0xFFFF );
2362+ if (I.fail ()) {
2363+ SPIRVDBG (spvdbgs () << " getWordCountAndOpCode FAIL 0 0\n " );
2364+ break ;
2365+ }
2366+ SPIRVDBG (spvdbgs () << " getWordCountAndOpCode " << WordCount << " "
2367+ << OpCodeNameMap::map (OpCode) << ' \n ' );
2368+ if (!MI.isModuleValid ()) {
2369+ break ;
2370+ }
2371+ SPIRVEntry *Entry =
2372+ parseAndCreateSPIRVEntry (WordCount, OpCode, Scope, MI, I);
2373+ if (Entry != nullptr ) {
2374+ MI.add (Entry);
2375+ }
2376+ if (I.eof ()) {
2377+ SPIRVDBG (spvdbgs () << " getWordCountAndOpCode EOF 0 0\n " );
2378+ break ;
2379+ }
2380+ }
2381+ MI.resolveUnknownStructFields ();
2382+ return I;
2383+ }
2384+
2385+ std::istream &operator >>(std::istream &I, SPIRVModule &M) {
2386+ SPIRVModuleImpl &MI = *static_cast <SPIRVModuleImpl *>(&M);
2387+ #ifdef _SPIRV_SUPPORT_TEXT_FMT
2388+ if (SPIRVUseTextFormat) {
2389+ return MI.parseSPT (I);
2390+ }
2391+ #endif
2392+ return MI.parseSPIRV (I);
2393+ }
2394+
21902395SPIRVModule *SPIRVModule::createSPIRVModule () { return new SPIRVModuleImpl (); }
21912396
21922397SPIRVModule *SPIRVModule::createSPIRVModule (const SPIRV::TranslatorOpts &Opts) {
0 commit comments