// // Do an actual compile on the given strings. The result is left // in the given compile object. // // Return: The return value of ShCompile is really boolean, indicating // success or failure. // int ShCompile( const ShHandle handle, const char* const shaderStrings[], const int numStrings, const EShOptimizationLevel optLevel, int debugOptions ) { if (!InitThread()) return 0; if (handle == 0) return 0; TShHandleBase* base = reinterpret_cast<TShHandleBase*>(handle); TCompiler* compiler = base->getAsCompiler(); if (compiler == 0) return 0; GlobalPoolAllocator.push(); TInfoSink& infoSink = compiler->getInfoSink(); infoSink.info.erase(); infoSink.debug.erase(); infoSink.obj.erase(); if (numStrings == 0) return 1; TIntermediate intermediate(infoSink); TSymbolTable& symbolTable = compiler->getSymbolTable(); TParseContext parseContext(symbolTable, intermediate, compiler->getLanguage(), compiler->getSpec(), infoSink); parseContext.initializeExtensionBehavior(); GlobalParseContext = &parseContext; setInitialState(); InitPreprocessor(); // // Parse the application's shaders. All the following symbol table // work will be throw-away, so push a new allocation scope that can // be thrown away, then push a scope for the current shader's globals. // bool success = true; symbolTable.push(); if (!symbolTable.atGlobalLevel()) parseContext.infoSink.info.message(EPrefixInternalError, "Wrong symbol table level"); int ret = PaParseStrings(const_cast<char**>(shaderStrings), 0, numStrings, parseContext); if (ret) success = false; if (success && parseContext.treeRoot) { if (optLevel == EShOptNoGeneration) parseContext.infoSink.info.message(EPrefixNone, "No errors. No code generation was requested."); else { success = intermediate.postProcess(parseContext.treeRoot, parseContext.language); if (success) { if (debugOptions & EDebugOpIntermediate) intermediate.outputTree(parseContext.treeRoot); // // Call the machine dependent compiler // if (!compiler->compile(parseContext.treeRoot)) success = false; } } } else if (!success) { parseContext.infoSink.info.prefix(EPrefixError); parseContext.infoSink.info << parseContext.numErrors << " compilation errors. No code generated.\n\n"; success = false; if (debugOptions & EDebugOpIntermediate) intermediate.outputTree(parseContext.treeRoot); } else if (!parseContext.treeRoot) { parseContext.error(1, "Unexpected end of file.", "", ""); parseContext.infoSink.info << parseContext.numErrors << " compilation errors. No code generated.\n\n"; success = false; if (debugOptions & EDebugOpIntermediate) intermediate.outputTree(parseContext.treeRoot); } intermediate.remove(parseContext.treeRoot); // // Ensure symbol table is returned to the built-in level, // throwing away all but the built-ins. // while (!symbolTable.atBuiltInLevel()) symbolTable.pop(); FinalizePreprocessor(); // // Throw away all the temporary memory used by the compilation process. // GlobalPoolAllocator.pop(); return success ? 1 : 0; }
// // Driver calls these to create and destroy compiler objects. // ShHandle ShConstructCompiler(EShLanguage language, EShSpec spec, const TBuiltInResource* resources) { if (!InitThread()) return 0; TShHandleBase* base = static_cast<TShHandleBase*>(ConstructCompiler(language, spec)); TCompiler* compiler = base->getAsCompiler(); if (compiler == 0) return 0; // Generate built-in symbol table. if (!GenerateBuiltInSymbolTable(language, spec, *resources, compiler->getInfoSink(), compiler->getSymbolTable())) { ShDestruct(base); return 0; } return reinterpret_cast<void*>(base); }