WHLSLStandardLibraryUtilities.cpp [plain text]
#include "config.h"
#include "WHLSLStandardLibraryUtilities.h"
#if ENABLE(WHLSL_COMPILER)
#include "WHLSLCallExpression.h"
#include "WHLSLParser.h"
#include "WHLSLProgram.h"
#include "WHLSLStandardLibrary.h"
#include "WHLSLStandardLibraryFunctionMap.h"
#include "WHLSLVisitor.h"
#include <wtf/DataLog.h>
#include <wtf/HashSet.h>
#include <wtf/NeverDestroyed.h>
#include <pal/Gunzip.h>
namespace WebCore {
namespace WHLSL {
constexpr bool verbose = false;
static String decompressAndDecodeStandardLibrary()
{
auto decompressedStandardLibrary = gunzip(WHLSLStandardLibrary, sizeof(WHLSLStandardLibrary));
return String::fromUTF8(decompressedStandardLibrary.data(), decompressedStandardLibrary.size());
}
class NameFinder : public Visitor {
public:
HashSet<String> takeFunctionNames()
{
HashSet<String> result;
std::swap(result, m_functionNames);
return result;
}
private:
void visit(AST::CallExpression& callExpression) override
{
m_functionNames.add(callExpression.name());
Visitor::visit(callExpression);
}
HashSet<String> m_functionNames;
};
Expected<void, Error> includeStandardLibrary(Program& program, Parser& parser, bool parseFullStandardLibrary)
{
static NeverDestroyed<String> standardLibrary(decompressAndDecodeStandardLibrary());
if (parseFullStandardLibrary) {
auto parseResult = parser.parse(program, standardLibrary.get(), ParsingMode::StandardLibrary, AST::NameSpace::StandardLibrary);
if (!parseResult)
return makeUnexpected(parseResult.error());
return { };
}
static NeverDestroyed<HashMap<String, SubstringLocation>> standardLibraryFunctionMap(computeStandardLibraryFunctionMap());
auto stringView = StringView(standardLibrary.get()).substring(0, firstFunctionOffsetInStandardLibrary());
auto parseResult = parser.parse(program, stringView, ParsingMode::StandardLibrary, AST::NameSpace::StandardLibrary);
if (!parseResult)
return makeUnexpected(parseResult.error());
NameFinder nameFinder;
nameFinder.Visitor::visit(program);
HashSet<String> functionNames = nameFinder.takeFunctionNames();
HashSet<String> allFunctionNames;
functionNames.add("operator cast"_str);
for (auto& functionDefinition : program.functionDefinitions())
functionNames.add(functionDefinition->name());
while (!functionNames.isEmpty()) {
auto nativeFunctionDeclarationsCount = program.nativeFunctionDeclarations().size();
auto functionDefinitionsCount = program.functionDefinitions().size();
for (const auto& name : functionNames) {
if (allFunctionNames.contains(name))
continue;
auto iterator = standardLibraryFunctionMap.get().find(name);
if (iterator == standardLibraryFunctionMap.get().end())
continue;
auto stringView = StringView(standardLibrary.get()).substring(iterator->value.start, iterator->value.end - iterator->value.start);
if (verbose) {
dataLogLn("---------------------------");
dataLogLn(stringView);
dataLogLn("---------------------------");
}
auto start = program.functionDefinitions().size();
auto parseResult = parser.parse(program, stringView, ParsingMode::StandardLibrary, AST::NameSpace::StandardLibrary);
if (!parseResult)
return makeUnexpected(parseResult.error());
if (verbose) {
if (program.functionDefinitions().size() != start)
dataLogLn("non native stdlib function: '", name, "'");
}
allFunctionNames.add(name);
}
for ( ; nativeFunctionDeclarationsCount < program.nativeFunctionDeclarations().size(); ++nativeFunctionDeclarationsCount)
nameFinder.Visitor::visit(program.nativeFunctionDeclarations()[nativeFunctionDeclarationsCount]);
for ( ; functionDefinitionsCount < program.functionDefinitions().size(); ++functionDefinitionsCount)
nameFinder.Visitor::visit(program.functionDefinitions()[functionDefinitionsCount]);
functionNames = nameFinder.takeFunctionNames();
}
return { };
}
}
}
#endif // ENABLE(WHLSL_COMPILER)