Use an unordered map for intrinsics in the IR generator.
Several small tweaks: - Replace std::pair<> with a struct (IRIntrinsic) so we can use names (fIntrinsic/fAlreadyIncluded) instead of .first and .second. - Replace std::map<String, std::pair<...>> with a name (IRIntrinsicMap). - Replace map with unordered_map, since we don't rely on order anywhere. Change-Id: I508eb3cde5bd4fddcc0b3d02d6ce21d33f9a5421 Reviewed-on: https://skia-review.googlesource.com/c/skia/+/313523 Auto-Submit: John Stiles <johnstiles@google.com> Commit-Queue: Ethan Nicholas <ethannicholas@google.com> Reviewed-by: Ethan Nicholas <ethannicholas@google.com>
This commit is contained in:
parent
aba6b93dfb
commit
810c8cf519
@ -70,7 +70,7 @@ static const char SKSL_PIPELINE_INCLUDE[] = "sksl_pipeline.sksl";
|
||||
namespace SkSL {
|
||||
|
||||
static void grab_intrinsics(std::vector<std::unique_ptr<ProgramElement>>* src,
|
||||
std::map<String, std::pair<std::unique_ptr<ProgramElement>, bool>>* target) {
|
||||
IRIntrinsicMap* target) {
|
||||
for (auto iter = src->begin(); iter != src->end(); ) {
|
||||
std::unique_ptr<ProgramElement>& element = *iter;
|
||||
switch (element->fKind) {
|
||||
@ -79,7 +79,7 @@ static void grab_intrinsics(std::vector<std::unique_ptr<ProgramElement>>* src,
|
||||
SkASSERT(f.fDeclaration.fBuiltin);
|
||||
String key = f.fDeclaration.description();
|
||||
SkASSERT(target->find(key) == target->end());
|
||||
(*target)[key] = std::make_pair(std::move(element), false);
|
||||
(*target)[key] = IRIntrinsic{std::move(element), /*fAlreadyIncluded=*/false};
|
||||
iter = src->erase(iter);
|
||||
break;
|
||||
}
|
||||
@ -87,7 +87,7 @@ static void grab_intrinsics(std::vector<std::unique_ptr<ProgramElement>>* src,
|
||||
Enum& e = element->as<Enum>();
|
||||
StringFragment name = e.fTypeName;
|
||||
SkASSERT(target->find(name) == target->end());
|
||||
(*target)[name] = std::make_pair(std::move(element), false);
|
||||
(*target)[name] = IRIntrinsic{std::move(element), /*fAlreadyIncluded=*/false};
|
||||
iter = src->erase(iter);
|
||||
break;
|
||||
}
|
||||
@ -99,8 +99,10 @@ static void grab_intrinsics(std::vector<std::unique_ptr<ProgramElement>>* src,
|
||||
}
|
||||
|
||||
Compiler::Compiler(Flags flags)
|
||||
: fFlags(flags)
|
||||
, fContext(new Context())
|
||||
: fGPUIntrinsics(std::make_unique<IRIntrinsicMap>())
|
||||
, fInterpreterIntrinsics(std::make_unique<IRIntrinsicMap>())
|
||||
, fFlags(flags)
|
||||
, fContext(std::make_shared<Context>())
|
||||
, fErrorCount(0) {
|
||||
auto symbols = std::shared_ptr<SymbolTable>(new SymbolTable(this));
|
||||
fIRGenerator = new IRGenerator(fContext.get(), symbols, *this);
|
||||
@ -236,7 +238,7 @@ Compiler::Compiler(Flags flags)
|
||||
std::make_unique<Variable>(/*offset=*/-1, Modifiers(), skCapsName,
|
||||
*fContext->fSkCaps_Type, Variable::kGlobal_Storage));
|
||||
|
||||
fIRGenerator->fIntrinsics = &fGPUIntrinsics;
|
||||
fIRGenerator->fIntrinsics = fGPUIntrinsics.get();
|
||||
std::vector<std::unique_ptr<ProgramElement>> gpuIntrinsics;
|
||||
std::vector<std::unique_ptr<ProgramElement>> interpIntrinsics;
|
||||
#if SKSL_STANDALONE
|
||||
@ -266,8 +268,8 @@ Compiler::Compiler(Flags flags)
|
||||
fFragmentInclude = rehydrator.elements();
|
||||
}
|
||||
#endif
|
||||
grab_intrinsics(&gpuIntrinsics, &fGPUIntrinsics);
|
||||
grab_intrinsics(&interpIntrinsics, &fInterpreterIntrinsics);
|
||||
grab_intrinsics(&gpuIntrinsics, fGPUIntrinsics.get());
|
||||
grab_intrinsics(&interpIntrinsics, fInterpreterIntrinsics.get());
|
||||
}
|
||||
|
||||
Compiler::~Compiler() {
|
||||
@ -1548,20 +1550,20 @@ std::unique_ptr<Program> Compiler::convertProgram(Program::Kind kind, String tex
|
||||
case Program::kVertex_Kind:
|
||||
inherited = &fVertexInclude;
|
||||
fIRGenerator->fSymbolTable = fVertexSymbolTable;
|
||||
fIRGenerator->fIntrinsics = &fGPUIntrinsics;
|
||||
fIRGenerator->fIntrinsics = fGPUIntrinsics.get();
|
||||
fIRGenerator->start(&settings, inherited);
|
||||
break;
|
||||
case Program::kFragment_Kind:
|
||||
inherited = &fFragmentInclude;
|
||||
fIRGenerator->fSymbolTable = fFragmentSymbolTable;
|
||||
fIRGenerator->fIntrinsics = &fGPUIntrinsics;
|
||||
fIRGenerator->fIntrinsics = fGPUIntrinsics.get();
|
||||
fIRGenerator->start(&settings, inherited);
|
||||
break;
|
||||
case Program::kGeometry_Kind:
|
||||
this->loadGeometryIntrinsics();
|
||||
inherited = &fGeometryInclude;
|
||||
fIRGenerator->fSymbolTable = fGeometrySymbolTable;
|
||||
fIRGenerator->fIntrinsics = &fGPUIntrinsics;
|
||||
fIRGenerator->fIntrinsics = fGPUIntrinsics.get();
|
||||
fIRGenerator->start(&settings, inherited);
|
||||
break;
|
||||
case Program::kFragmentProcessor_Kind: {
|
||||
@ -1575,14 +1577,14 @@ std::unique_ptr<Program> Compiler::convertProgram(Program::Kind kind, String tex
|
||||
}
|
||||
inherited = &fFPInclude;
|
||||
fIRGenerator->fSymbolTable = fFPSymbolTable;
|
||||
fIRGenerator->fIntrinsics = &fGPUIntrinsics;
|
||||
fIRGenerator->fIntrinsics = fGPUIntrinsics.get();
|
||||
fIRGenerator->start(&settings, inherited);
|
||||
break;
|
||||
#else
|
||||
inherited = nullptr;
|
||||
fIRGenerator->fSymbolTable = fGpuSymbolTable;
|
||||
fIRGenerator->start(&settings, /*inherited=*/nullptr, /*builtin=*/true);
|
||||
fIRGenerator->fIntrinsics = &fGPUIntrinsics;
|
||||
fIRGenerator->fIntrinsics = fGPUIntrinsics.get();
|
||||
std::ifstream in(SKSL_FP_INCLUDE);
|
||||
std::string stdText{std::istreambuf_iterator<char>(in),
|
||||
std::istreambuf_iterator<char>()};
|
||||
@ -1601,14 +1603,14 @@ std::unique_ptr<Program> Compiler::convertProgram(Program::Kind kind, String tex
|
||||
this->loadPipelineIntrinsics();
|
||||
inherited = &fPipelineInclude;
|
||||
fIRGenerator->fSymbolTable = fPipelineSymbolTable;
|
||||
fIRGenerator->fIntrinsics = &fGPUIntrinsics;
|
||||
fIRGenerator->fIntrinsics = fGPUIntrinsics.get();
|
||||
fIRGenerator->start(&settings, inherited);
|
||||
break;
|
||||
case Program::kGeneric_Kind:
|
||||
this->loadInterpreterIntrinsics();
|
||||
inherited = &fInterpreterInclude;
|
||||
fIRGenerator->fSymbolTable = fInterpreterSymbolTable;
|
||||
fIRGenerator->fIntrinsics = &fInterpreterIntrinsics;
|
||||
fIRGenerator->fIntrinsics = fInterpreterIntrinsics.get();
|
||||
fIRGenerator->start(&settings, inherited);
|
||||
break;
|
||||
}
|
||||
|
@ -8,8 +8,8 @@
|
||||
#ifndef SKSL_COMPILER
|
||||
#define SKSL_COMPILER
|
||||
|
||||
#include <map>
|
||||
#include <set>
|
||||
#include <unordered_map>
|
||||
#include <unordered_set>
|
||||
#include <vector>
|
||||
#include "src/sksl/SkSLASTFile.h"
|
||||
@ -46,6 +46,8 @@ namespace SkSL {
|
||||
class ByteCode;
|
||||
class ExternalValue;
|
||||
class IRGenerator;
|
||||
struct IRIntrinsic;
|
||||
using IRIntrinsicMap = std::unordered_map<String, IRIntrinsic>;
|
||||
struct PipelineStageArgs;
|
||||
|
||||
/**
|
||||
@ -223,8 +225,8 @@ private:
|
||||
Position position(int offset);
|
||||
|
||||
std::shared_ptr<SymbolTable> fGpuSymbolTable;
|
||||
std::map<String, std::pair<std::unique_ptr<ProgramElement>, bool>> fGPUIntrinsics;
|
||||
std::map<String, std::pair<std::unique_ptr<ProgramElement>, bool>> fInterpreterIntrinsics;
|
||||
std::unique_ptr<IRIntrinsicMap> fGPUIntrinsics;
|
||||
std::unique_ptr<IRIntrinsicMap> fInterpreterIntrinsics;
|
||||
std::unique_ptr<ASTFile> fGpuIncludeSource;
|
||||
std::vector<std::unique_ptr<ProgramElement>> fVertexInclude;
|
||||
std::shared_ptr<SymbolTable> fVertexSymbolTable;
|
||||
|
@ -7,6 +7,8 @@
|
||||
|
||||
#include "src/sksl/SkSLDehydrator.h"
|
||||
|
||||
#include <map>
|
||||
|
||||
#include "src/sksl/SkSLRehydrator.h"
|
||||
#include "src/sksl/ir/SkSLBinaryExpression.h"
|
||||
#include "src/sksl/ir/SkSLBreakStatement.h"
|
||||
|
@ -192,7 +192,7 @@ void IRGenerator::start(const Program::Settings* settings,
|
||||
}
|
||||
SkASSERT(fIntrinsics);
|
||||
for (auto& pair : *fIntrinsics) {
|
||||
pair.second.second = false;
|
||||
pair.second.fAlreadyIncluded = false;
|
||||
}
|
||||
}
|
||||
|
||||
@ -2398,9 +2398,9 @@ std::unique_ptr<Expression> IRGenerator::inlineCall(
|
||||
|
||||
void IRGenerator::copyIntrinsicIfNeeded(const FunctionDeclaration& function) {
|
||||
auto found = fIntrinsics->find(function.description());
|
||||
if (found != fIntrinsics->end() && !found->second.second) {
|
||||
found->second.second = true;
|
||||
FunctionDefinition& original = found->second.first->as<FunctionDefinition>();
|
||||
if (found != fIntrinsics->end() && !found->second.fAlreadyIncluded) {
|
||||
found->second.fAlreadyIncluded = true;
|
||||
FunctionDefinition& original = found->second.fIntrinsic->as<FunctionDefinition>();
|
||||
for (const FunctionDeclaration* f : original.fReferencedIntrinsics) {
|
||||
this->copyIntrinsicIfNeeded(*f);
|
||||
}
|
||||
@ -3061,9 +3061,9 @@ std::unique_ptr<Expression> IRGenerator::convertTypeField(int offset, const Type
|
||||
if (!result) {
|
||||
auto found = fIntrinsics->find(type.fName);
|
||||
if (found != fIntrinsics->end()) {
|
||||
SkASSERT(!found->second.second);
|
||||
found->second.second = true;
|
||||
fProgramElements->push_back(found->second.first->clone());
|
||||
SkASSERT(!found->second.fAlreadyIncluded);
|
||||
found->second.fAlreadyIncluded = true;
|
||||
fProgramElements->push_back(found->second.fIntrinsic->clone());
|
||||
return this->convertTypeField(offset, type, field);
|
||||
}
|
||||
fErrors.error(offset, "type '" + type.fName + "' does not have a field named '" + field +
|
||||
|
@ -8,7 +8,6 @@
|
||||
#ifndef SKSL_IRGENERATOR
|
||||
#define SKSL_IRGENERATOR
|
||||
|
||||
#include <map>
|
||||
#include <unordered_map>
|
||||
#include <unordered_set>
|
||||
|
||||
@ -35,6 +34,15 @@ namespace SkSL {
|
||||
|
||||
struct Swizzle;
|
||||
|
||||
/**
|
||||
* Intrinsics are passed between the Compiler and the IRGenerator using IRIntrinsicMaps.
|
||||
*/
|
||||
struct IRIntrinsic {
|
||||
std::unique_ptr<ProgramElement> fIntrinsic;
|
||||
bool fAlreadyIncluded = false;
|
||||
};
|
||||
using IRIntrinsicMap = std::unordered_map<String, IRIntrinsic>;
|
||||
|
||||
/**
|
||||
* Performs semantic analysis on an abstract syntax tree (AST) and produces the corresponding
|
||||
* (unoptimized) intermediate representation (IR).
|
||||
@ -179,9 +187,8 @@ private:
|
||||
// additional statements that need to be inserted before the one that convertStatement is
|
||||
// currently working on
|
||||
std::vector<std::unique_ptr<Statement>> fExtraStatements;
|
||||
// Symbols which have definitions in the include files. The bool tells us whether this
|
||||
// intrinsic has been included already.
|
||||
std::map<String, std::pair<std::unique_ptr<ProgramElement>, bool>>* fIntrinsics = nullptr;
|
||||
// Symbols which have definitions in the include files.
|
||||
IRIntrinsicMap* fIntrinsics = nullptr;
|
||||
std::unordered_set<const FunctionDeclaration*> fReferencedIntrinsics;
|
||||
int fLoopLevel;
|
||||
int fSwitchLevel;
|
||||
|
Loading…
Reference in New Issue
Block a user