moved SkSL FunctionDeclaration data into IRNode
Change-Id: I97a59563914c4f75f8cfdc2bd5a9ae430de9bb3c Reviewed-on: https://skia-review.googlesource.com/c/skia/+/323881 Commit-Queue: Ethan Nicholas <ethannicholas@google.com> Reviewed-by: Brian Osman <brianosman@google.com>
This commit is contained in:
parent
9eaca48f46
commit
ed84b73797
@ -65,7 +65,7 @@ namespace {
|
||||
|
||||
static bool is_sample_call_to_fp(const FunctionCall& fc, const Variable& fp) {
|
||||
const FunctionDeclaration& f = fc.function();
|
||||
return f.fBuiltin && f.name() == "sample" && fc.arguments().size() >= 1 &&
|
||||
return f.isBuiltin() && f.name() == "sample" && fc.arguments().size() >= 1 &&
|
||||
fc.arguments()[0]->is<VariableReference>() &&
|
||||
fc.arguments()[0]->as<VariableReference>().variable() == &fp;
|
||||
}
|
||||
|
@ -17,7 +17,7 @@
|
||||
namespace SkSL {
|
||||
|
||||
class ExternalValue;
|
||||
struct FunctionDeclaration;
|
||||
class FunctionDeclaration;
|
||||
|
||||
enum class ByteCodeInstruction : uint8_t {
|
||||
// B = bool, F = float, I = int, S = signed, U = unsigned
|
||||
|
@ -204,7 +204,7 @@ std::unique_ptr<ByteCodeFunction> ByteCodeGenerator::writeFunction(const Functio
|
||||
result->fLoopCount = fMaxLoopCount;
|
||||
result->fStackCount = fMaxStackCount;
|
||||
|
||||
const Type& returnType = f.fDeclaration.fReturnType;
|
||||
const Type& returnType = f.fDeclaration.returnType();
|
||||
if (returnType != *fContext.fVoid_Type) {
|
||||
result->fReturnCount = SlotCount(returnType);
|
||||
}
|
||||
@ -441,7 +441,7 @@ ByteCodeGenerator::Location ByteCodeGenerator::getLocation(const Variable& var)
|
||||
}
|
||||
case Variable::kParameter_Storage: {
|
||||
int offset = 0;
|
||||
for (const auto& p : fFunction->fDeclaration.fParameters) {
|
||||
for (const auto& p : fFunction->fDeclaration.parameters()) {
|
||||
if (p == &var) {
|
||||
SkASSERT(offset <= 255);
|
||||
return { offset, Storage::kLocal };
|
||||
@ -1263,7 +1263,7 @@ void ByteCodeGenerator::writeFunctionCall(const FunctionCall& f) {
|
||||
int argCount = f.arguments().size();
|
||||
std::vector<std::unique_ptr<LValue>> lvalues;
|
||||
for (int i = 0; i < argCount; ++i) {
|
||||
const auto& param = f.function().fParameters[i];
|
||||
const auto& param = f.function().parameters()[i];
|
||||
const auto& arg = f.arguments()[i];
|
||||
if (param->modifiers().fFlags & Modifiers::kOut_Flag) {
|
||||
lvalues.emplace_back(this->getLValue(*arg));
|
||||
@ -1296,7 +1296,7 @@ void ByteCodeGenerator::writeFunctionCall(const FunctionCall& f) {
|
||||
};
|
||||
|
||||
for (int i = argCount - 1; i >= 0; --i) {
|
||||
const auto& param = f.function().fParameters[i];
|
||||
const auto& param = f.function().parameters()[i];
|
||||
const auto& arg = f.arguments()[i];
|
||||
if (param->modifiers().fFlags & Modifiers::kOut_Flag) {
|
||||
pop();
|
||||
@ -1832,7 +1832,7 @@ void ByteCodeGenerator::writeStatement(const Statement& s) {
|
||||
ByteCodeFunction::ByteCodeFunction(const FunctionDeclaration* declaration)
|
||||
: fName(declaration->name()) {
|
||||
fParameterCount = 0;
|
||||
for (const auto& p : declaration->fParameters) {
|
||||
for (const auto& p : declaration->parameters()) {
|
||||
int slots = ByteCodeGenerator::SlotCount(p->type());
|
||||
fParameters.push_back({ slots, (bool)(p->modifiers().fFlags & Modifiers::kOut_Flag) });
|
||||
fParameterCount += slots;
|
||||
|
@ -429,7 +429,7 @@ int CPPCodeGenerator::getChildFPIndex(const Variable& var) const {
|
||||
void CPPCodeGenerator::writeFunctionCall(const FunctionCall& c) {
|
||||
const FunctionDeclaration& function = c.function();
|
||||
const std::vector<std::unique_ptr<Expression>>& arguments = c.arguments();
|
||||
if (function.fBuiltin && function.name() == "sample" &&
|
||||
if (function.isBuiltin() && function.name() == "sample" &&
|
||||
arguments[0]->type().typeKind() != Type::TypeKind::kSampler) {
|
||||
// Validity checks that are detected by function definition in sksl_fp.inc
|
||||
SkASSERT(arguments.size() >= 1 && arguments.size() <= 3);
|
||||
@ -495,7 +495,7 @@ void CPPCodeGenerator::writeFunctionCall(const FunctionCall& c) {
|
||||
fFormatArgs.push_back(childName + ".c_str()");
|
||||
return;
|
||||
}
|
||||
if (function.fBuiltin) {
|
||||
if (function.isBuiltin()) {
|
||||
INHERITED::writeFunctionCall(c);
|
||||
} else {
|
||||
this->write("%s");
|
||||
@ -509,7 +509,7 @@ void CPPCodeGenerator::writeFunctionCall(const FunctionCall& c) {
|
||||
}
|
||||
this->write(")");
|
||||
}
|
||||
if (function.fBuiltin && function.name() == "sample") {
|
||||
if (function.isBuiltin() && function.name() == "sample") {
|
||||
this->write(".%s");
|
||||
SkASSERT(arguments.size() >= 1);
|
||||
SkASSERT(arguments[0]->is<VariableReference>());
|
||||
@ -594,7 +594,7 @@ static const char* glsltype_string(const Context& context, const Type& type) {
|
||||
|
||||
void CPPCodeGenerator::writeFunction(const FunctionDefinition& f) {
|
||||
const FunctionDeclaration& decl = f.fDeclaration;
|
||||
if (decl.fBuiltin) {
|
||||
if (decl.isBuiltin()) {
|
||||
return;
|
||||
}
|
||||
fFunctionHeader = "";
|
||||
@ -616,7 +616,7 @@ void CPPCodeGenerator::writeFunction(const FunctionDefinition& f) {
|
||||
this->addExtraEmitCodeLine("SkString " + decl.name() + "_name;");
|
||||
String args = "const GrShaderVar " + decl.name() + "_args[] = { ";
|
||||
const char* separator = "";
|
||||
for (const Variable* param : decl.fParameters) {
|
||||
for (const Variable* param : decl.parameters()) {
|
||||
args += String(separator) + "GrShaderVar(\"" + param->name() + "\", " +
|
||||
glsltype_string(fContext, param->type()) + ")";
|
||||
separator = ", ";
|
||||
@ -630,9 +630,9 @@ void CPPCodeGenerator::writeFunction(const FunctionDefinition& f) {
|
||||
|
||||
fOut = oldOut;
|
||||
String emit = "fragBuilder->emitFunction(";
|
||||
emit += glsltype_string(fContext, decl.fReturnType);
|
||||
emit += glsltype_string(fContext, decl.returnType());
|
||||
emit += ", \"" + decl.name() + "\"";
|
||||
emit += ", " + to_string((int64_t) decl.fParameters.size());
|
||||
emit += ", " + to_string((int64_t) decl.parameters().size());
|
||||
emit += ", " + decl.name() + "_args";
|
||||
emit += ",\nR\"SkSL(" + buffer.str() + ")SkSL\"";
|
||||
emit += ", &" + decl.name() + "_name);";
|
||||
|
@ -77,7 +77,7 @@ static void grab_intrinsics(std::vector<std::unique_ptr<ProgramElement>>* src,
|
||||
switch (element->kind()) {
|
||||
case ProgramElement::Kind::kFunction: {
|
||||
const FunctionDefinition& f = element->as<FunctionDefinition>();
|
||||
SkASSERT(f.fDeclaration.fBuiltin);
|
||||
SkASSERT(f.fDeclaration.isBuiltin());
|
||||
target->insertOrDie(f.fDeclaration.description(), std::move(element));
|
||||
break;
|
||||
}
|
||||
@ -111,7 +111,7 @@ static void reset_call_counts(std::vector<std::unique_ptr<ProgramElement>>* src)
|
||||
for (std::unique_ptr<ProgramElement>& element : *src) {
|
||||
if (element->is<FunctionDefinition>()) {
|
||||
const FunctionDeclaration& fnDecl = element->as<FunctionDefinition>().fDeclaration;
|
||||
fnDecl.fCallCount = 0;
|
||||
fnDecl.callCount() = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -512,8 +512,9 @@ void Compiler::addDefinitions(const BasicBlock::Node& node,
|
||||
}
|
||||
case Expression::Kind::kFunctionCall: {
|
||||
const FunctionCall& c = expr->as<FunctionCall>();
|
||||
for (size_t i = 0; i < c.function().fParameters.size(); ++i) {
|
||||
if (c.function().fParameters[i]->modifiers().fFlags & Modifiers::kOut_Flag) {
|
||||
const std::vector<Variable*>& parameters = c.function().parameters();
|
||||
for (size_t i = 0; i < parameters.size(); ++i) {
|
||||
if (parameters[i]->modifiers().fFlags & Modifiers::kOut_Flag) {
|
||||
this->addDefinition(
|
||||
c.arguments()[i].get(),
|
||||
(std::unique_ptr<Expression>*) &fContext->fDefined_Expression,
|
||||
@ -1572,7 +1573,7 @@ bool Compiler::scanCFG(FunctionDefinition& f) {
|
||||
}
|
||||
|
||||
// check for missing return
|
||||
if (f.fDeclaration.fReturnType != *fContext->fVoid_Type) {
|
||||
if (f.fDeclaration.returnType() != *fContext->fVoid_Type) {
|
||||
if (cfg.fBlocks[cfg.fExit].fIsReachable) {
|
||||
this->error(f.fOffset, String("function '" + String(f.fDeclaration.name()) +
|
||||
"' can exit without returning a value"));
|
||||
@ -1680,7 +1681,7 @@ bool Compiler::optimize(Program& program) {
|
||||
return false;
|
||||
}
|
||||
const auto& fn = element->as<FunctionDefinition>();
|
||||
bool dead = fn.fDeclaration.fCallCount == 0 &&
|
||||
bool dead = fn.fDeclaration.callCount() == 0 &&
|
||||
fn.fDeclaration.name() != "main";
|
||||
madeChanges |= dead;
|
||||
return dead;
|
||||
|
@ -148,13 +148,13 @@ void Dehydrator::write(const Symbol& s) {
|
||||
const FunctionDeclaration& f = s.as<FunctionDeclaration>();
|
||||
this->writeU8(Rehydrator::kFunctionDeclaration_Command);
|
||||
this->writeId(&f);
|
||||
this->write(f.fModifiers);
|
||||
this->write(f.modifiers());
|
||||
this->write(f.name());
|
||||
this->writeU8(f.fParameters.size());
|
||||
for (const Variable* p : f.fParameters) {
|
||||
this->writeU8(f.parameters().size());
|
||||
for (const Variable* p : f.parameters()) {
|
||||
this->writeU16(this->symbolId(p));
|
||||
}
|
||||
this->write(f.fReturnType);
|
||||
this->write(f.returnType());
|
||||
break;
|
||||
}
|
||||
case Symbol::Kind::kSymbolAlias: {
|
||||
|
@ -482,8 +482,8 @@ void GLSLCodeGenerator::writeFunctionCall(const FunctionCall& c) {
|
||||
#ifndef SKSL_STANDALONE
|
||||
);
|
||||
#endif
|
||||
const auto found = function.fBuiltin ? fFunctionClasses->find(function.name()) :
|
||||
fFunctionClasses->end();
|
||||
const auto found = function.isBuiltin() ? fFunctionClasses->find(function.name()) :
|
||||
fFunctionClasses->end();
|
||||
bool isTextureFunctionWithBias = false;
|
||||
bool nameWritten = false;
|
||||
if (found != fFunctionClasses->end()) {
|
||||
@ -1043,11 +1043,11 @@ void GLSLCodeGenerator::writeFunction(const FunctionDefinition& f) {
|
||||
// accidentally end up here.
|
||||
SkASSERT(fProgramKind != Program::kPipelineStage_Kind);
|
||||
|
||||
this->writeTypePrecision(f.fDeclaration.fReturnType);
|
||||
this->writeType(f.fDeclaration.fReturnType);
|
||||
this->writeTypePrecision(f.fDeclaration.returnType());
|
||||
this->writeType(f.fDeclaration.returnType());
|
||||
this->write(" " + f.fDeclaration.name() + "(");
|
||||
const char* separator = "";
|
||||
for (const auto& param : f.fDeclaration.fParameters) {
|
||||
for (const auto& param : f.fDeclaration.parameters()) {
|
||||
this->write(separator);
|
||||
separator = ", ";
|
||||
this->writeModifiers(param->modifiers(), false);
|
||||
|
@ -246,7 +246,7 @@ std::unique_ptr<Statement> IRGenerator::convertSingleStatement(const ASTNode& st
|
||||
Expression& expr = *result->as<ExpressionStatement>().expression();
|
||||
if (expr.kind() == Expression::Kind::kFunctionCall) {
|
||||
FunctionCall& fc = expr.as<FunctionCall>();
|
||||
if (fc.function().fBuiltin && fc.function().name() == "EmitVertex") {
|
||||
if (fc.function().isBuiltin() && fc.function().name() == "EmitVertex") {
|
||||
std::vector<std::unique_ptr<Statement>> statements;
|
||||
statements.push_back(getNormalizeSkPositionCode());
|
||||
statements.push_back(std::move(result));
|
||||
@ -718,20 +718,20 @@ std::unique_ptr<Statement> IRGenerator::convertReturn(const ASTNode& r) {
|
||||
if (!result) {
|
||||
return nullptr;
|
||||
}
|
||||
if (fCurrentFunction->fReturnType == *fContext.fVoid_Type) {
|
||||
if (fCurrentFunction->returnType() == *fContext.fVoid_Type) {
|
||||
fErrors.error(result->fOffset, "may not return a value from a void function");
|
||||
return nullptr;
|
||||
} else {
|
||||
result = this->coerce(std::move(result), fCurrentFunction->fReturnType);
|
||||
result = this->coerce(std::move(result), fCurrentFunction->returnType());
|
||||
if (!result) {
|
||||
return nullptr;
|
||||
}
|
||||
}
|
||||
return std::unique_ptr<Statement>(new ReturnStatement(std::move(result)));
|
||||
} else {
|
||||
if (fCurrentFunction->fReturnType != *fContext.fVoid_Type) {
|
||||
if (fCurrentFunction->returnType() != *fContext.fVoid_Type) {
|
||||
fErrors.error(r.fOffset, "expected function to return '" +
|
||||
fCurrentFunction->fReturnType.displayName() + "'");
|
||||
fCurrentFunction->returnType().displayName() + "'");
|
||||
}
|
||||
return std::unique_ptr<Statement>(new ReturnStatement(r.fOffset));
|
||||
}
|
||||
@ -766,12 +766,13 @@ std::unique_ptr<Block> IRGenerator::applyInvocationIDWorkaround(std::unique_ptr<
|
||||
Layout invokeLayout;
|
||||
Modifiers invokeModifiers(invokeLayout, Modifiers::kHasSideEffects_Flag);
|
||||
const FunctionDeclaration* invokeDecl =
|
||||
fSymbolTable->add(std::make_unique<FunctionDeclaration>(/*offset=*/-1,
|
||||
invokeModifiers,
|
||||
"_invoke",
|
||||
std::vector<Variable*>(),
|
||||
*fContext.fVoid_Type,
|
||||
/*builtin=*/false));
|
||||
fSymbolTable->add(std::make_unique<FunctionDeclaration>(
|
||||
/*offset=*/-1,
|
||||
fModifiers->handle(invokeModifiers),
|
||||
"_invoke",
|
||||
std::vector<Variable*>(),
|
||||
fContext.fVoid_Type.get(),
|
||||
/*builtin=*/false));
|
||||
fProgramElements->push_back(std::make_unique<FunctionDefinition>(/*offset=*/-1,
|
||||
*invokeDecl,
|
||||
std::move(main)));
|
||||
@ -1019,18 +1020,22 @@ void IRGenerator::convertFunction(const ASTNode& f) {
|
||||
}
|
||||
for (const FunctionDeclaration* other : functions) {
|
||||
SkASSERT(other->name() == funcData.fName);
|
||||
if (parameters.size() == other->fParameters.size()) {
|
||||
if (parameters.size() == other->parameters().size()) {
|
||||
bool match = true;
|
||||
for (size_t i = 0; i < parameters.size(); i++) {
|
||||
if (parameters[i]->type() != other->fParameters[i]->type()) {
|
||||
if (parameters[i]->type() != other->parameters()[i]->type()) {
|
||||
match = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (match) {
|
||||
if (*returnType != other->fReturnType) {
|
||||
FunctionDeclaration newDecl(f.fOffset, funcData.fModifiers, funcData.fName,
|
||||
parameters, *returnType, fIsBuiltinCode);
|
||||
if (*returnType != other->returnType()) {
|
||||
FunctionDeclaration newDecl(f.fOffset,
|
||||
fModifiers->handle(funcData.fModifiers),
|
||||
funcData.fName,
|
||||
parameters,
|
||||
returnType,
|
||||
fIsBuiltinCode);
|
||||
fErrors.error(f.fOffset, "functions '" + newDecl.description() +
|
||||
"' and '" + other->description() +
|
||||
"' differ only in return type");
|
||||
@ -1038,14 +1043,14 @@ void IRGenerator::convertFunction(const ASTNode& f) {
|
||||
}
|
||||
decl = other;
|
||||
for (size_t i = 0; i < parameters.size(); i++) {
|
||||
if (parameters[i]->modifiers() != other->fParameters[i]->modifiers()) {
|
||||
if (parameters[i]->modifiers() != other->parameters()[i]->modifiers()) {
|
||||
fErrors.error(f.fOffset, "modifiers on parameter " +
|
||||
to_string((uint64_t) i + 1) +
|
||||
" differ between declaration and definition");
|
||||
return;
|
||||
}
|
||||
}
|
||||
if (other->fDefinition && !other->fBuiltin) {
|
||||
if (other->definition() && !other->isBuiltin()) {
|
||||
fErrors.error(f.fOffset, "duplicate definition of " + other->description());
|
||||
}
|
||||
break;
|
||||
@ -1061,12 +1066,13 @@ void IRGenerator::convertFunction(const ASTNode& f) {
|
||||
}
|
||||
|
||||
// Create a new declaration.
|
||||
decl = fSymbolTable->add(std::make_unique<FunctionDeclaration>(f.fOffset,
|
||||
declModifiers,
|
||||
funcData.fName,
|
||||
parameters,
|
||||
*returnType,
|
||||
fIsBuiltinCode));
|
||||
decl = fSymbolTable->add(std::make_unique<FunctionDeclaration>(
|
||||
f.fOffset,
|
||||
fModifiers->handle(declModifiers),
|
||||
funcData.fName,
|
||||
parameters,
|
||||
returnType,
|
||||
fIsBuiltinCode));
|
||||
}
|
||||
if (iter != f.end()) {
|
||||
// compile body
|
||||
@ -1083,8 +1089,9 @@ void IRGenerator::convertFunction(const ASTNode& f) {
|
||||
parameters[0]->setModifiersHandle(fModifiers->handle(m));
|
||||
}
|
||||
}
|
||||
const std::vector<Variable*>& declParameters = decl->parameters();
|
||||
for (size_t i = 0; i < parameters.size(); i++) {
|
||||
fSymbolTable->addWithoutOwnership(decl->fParameters[i]);
|
||||
fSymbolTable->addWithoutOwnership(declParameters[i]);
|
||||
}
|
||||
bool needInvocationIDWorkaround = fInvocations != -1 && funcData.fName == "main" &&
|
||||
fSettings->fCaps &&
|
||||
@ -1102,7 +1109,7 @@ void IRGenerator::convertFunction(const ASTNode& f) {
|
||||
}
|
||||
auto result = std::make_unique<FunctionDefinition>(f.fOffset, *decl, std::move(body),
|
||||
std::move(fReferencedIntrinsics));
|
||||
decl->fDefinition = result.get();
|
||||
decl->setDefinition(result.get());
|
||||
result->fSource = &f;
|
||||
fProgramElements->push_back(std::move(result));
|
||||
}
|
||||
@ -2045,8 +2052,8 @@ void IRGenerator::copyIntrinsicIfNeeded(const FunctionDeclaration& function) {
|
||||
original.fReferencedIntrinsics.end());
|
||||
std::sort(intrinsics.begin(), intrinsics.end(),
|
||||
[](const FunctionDeclaration* a, const FunctionDeclaration* b) {
|
||||
if (a->fBuiltin != b->fBuiltin) {
|
||||
return a->fBuiltin < b->fBuiltin;
|
||||
if (a->isBuiltin() != b->isBuiltin()) {
|
||||
return a->isBuiltin() < b->isBuiltin();
|
||||
}
|
||||
if (a->fOffset != b->fOffset) {
|
||||
return a->fOffset < b->fOffset;
|
||||
@ -2066,26 +2073,26 @@ void IRGenerator::copyIntrinsicIfNeeded(const FunctionDeclaration& function) {
|
||||
std::unique_ptr<Expression> IRGenerator::call(int offset,
|
||||
const FunctionDeclaration& function,
|
||||
std::vector<std::unique_ptr<Expression>> arguments) {
|
||||
if (function.fBuiltin) {
|
||||
if (function.fDefinition) {
|
||||
if (function.isBuiltin()) {
|
||||
if (function.definition()) {
|
||||
fReferencedIntrinsics.insert(&function);
|
||||
}
|
||||
if (!fIsBuiltinCode && fIntrinsics) {
|
||||
this->copyIntrinsicIfNeeded(function);
|
||||
}
|
||||
}
|
||||
if (function.fParameters.size() != arguments.size()) {
|
||||
if (function.parameters().size() != arguments.size()) {
|
||||
String msg = "call to '" + function.name() + "' expected " +
|
||||
to_string((uint64_t) function.fParameters.size()) +
|
||||
to_string((uint64_t) function.parameters().size()) +
|
||||
" argument";
|
||||
if (function.fParameters.size() != 1) {
|
||||
if (function.parameters().size() != 1) {
|
||||
msg += "s";
|
||||
}
|
||||
msg += ", but found " + to_string((uint64_t) arguments.size());
|
||||
fErrors.error(offset, msg);
|
||||
return nullptr;
|
||||
}
|
||||
if (fKind == Program::kPipelineStage_Kind && !function.fDefinition && !function.fBuiltin) {
|
||||
if (fKind == Program::kPipelineStage_Kind && !function.definition() && !function.isBuiltin()) {
|
||||
String msg = "call to undefined function '" + function.name() + "'";
|
||||
fErrors.error(offset, msg);
|
||||
return nullptr;
|
||||
@ -2109,7 +2116,7 @@ std::unique_ptr<Expression> IRGenerator::call(int offset,
|
||||
if (!arguments[i]) {
|
||||
return nullptr;
|
||||
}
|
||||
const Modifiers& paramModifiers = function.fParameters[i]->modifiers();
|
||||
const Modifiers& paramModifiers = function.parameters()[i]->modifiers();
|
||||
if (paramModifiers.fFlags & Modifiers::kOut_Flag) {
|
||||
if (!this->setRefKind(*arguments[i], paramModifiers.fFlags & Modifiers::kIn_Flag
|
||||
? VariableReference::kReadWrite_RefKind
|
||||
@ -2122,8 +2129,8 @@ std::unique_ptr<Expression> IRGenerator::call(int offset,
|
||||
auto funcCall = std::make_unique<FunctionCall>(offset, returnType, &function,
|
||||
std::move(arguments));
|
||||
if (fCanInline &&
|
||||
fInliner->isSafeToInline(funcCall->function().fDefinition) &&
|
||||
!fInliner->isLargeFunction(funcCall->function().fDefinition)) {
|
||||
fInliner->isSafeToInline(funcCall->function().definition()) &&
|
||||
!fInliner->isLargeFunction(funcCall->function().definition())) {
|
||||
Inliner::InlinedCall inlinedCall = fInliner->inlineCall(funcCall.get(), fSymbolTable.get(),
|
||||
fCurrentFunction);
|
||||
if (inlinedCall.fInlinedBody) {
|
||||
@ -2142,7 +2149,7 @@ std::unique_ptr<Expression> IRGenerator::call(int offset,
|
||||
*/
|
||||
CoercionCost IRGenerator::callCost(const FunctionDeclaration& function,
|
||||
const std::vector<std::unique_ptr<Expression>>& arguments) {
|
||||
if (function.fParameters.size() != arguments.size()) {
|
||||
if (function.parameters().size() != arguments.size()) {
|
||||
return CoercionCost::Impossible();
|
||||
}
|
||||
std::vector<const Type*> types;
|
||||
|
@ -166,8 +166,8 @@ static bool contains_recursive_call(const FunctionDeclaration& funcDecl) {
|
||||
public:
|
||||
bool visit(const FunctionDeclaration& funcDecl) {
|
||||
fFuncDecl = &funcDecl;
|
||||
return funcDecl.fDefinition ? this->visitProgramElement(*funcDecl.fDefinition)
|
||||
: false;
|
||||
return funcDecl.definition() ? this->visitProgramElement(*funcDecl.definition())
|
||||
: false;
|
||||
}
|
||||
|
||||
bool visitExpression(const Expression& expr) override {
|
||||
@ -587,11 +587,11 @@ Inliner::InlinedCall Inliner::inlineCall(FunctionCall* call,
|
||||
SkASSERT(fSettings);
|
||||
SkASSERT(fContext);
|
||||
SkASSERT(call);
|
||||
SkASSERT(this->isSafeToInline(call->function().fDefinition));
|
||||
SkASSERT(this->isSafeToInline(call->function().definition()));
|
||||
|
||||
std::vector<std::unique_ptr<Expression>>& arguments = call->arguments();
|
||||
const int offset = call->fOffset;
|
||||
const FunctionDefinition& function = *call->function().fDefinition;
|
||||
const FunctionDefinition& function = *call->function().definition();
|
||||
const bool hasEarlyReturn = has_early_return(function);
|
||||
|
||||
InlinedCall inlinedCall;
|
||||
@ -632,7 +632,7 @@ Inliner::InlinedCall Inliner::inlineCall(FunctionCall* call,
|
||||
// Add our new variable to the symbol table.
|
||||
const Variable* variableSymbol = symbolTableForCall->add(std::make_unique<Variable>(
|
||||
/*offset=*/-1, fModifiers->handle(Modifiers()),
|
||||
nameFrag, type, caller->fBuiltin,
|
||||
nameFrag, type, caller->isBuiltin(),
|
||||
Variable::kLocal_Storage, initialValue->get()));
|
||||
|
||||
// Prepare the variable declaration (taking extra care with `out` params to not clobber any
|
||||
@ -656,10 +656,10 @@ Inliner::InlinedCall Inliner::inlineCall(FunctionCall* call,
|
||||
|
||||
// Create a variable to hold the result in the extra statements (excepting void).
|
||||
std::unique_ptr<Expression> resultExpr;
|
||||
if (function.fDeclaration.fReturnType != *fContext->fVoid_Type) {
|
||||
if (function.fDeclaration.returnType() != *fContext->fVoid_Type) {
|
||||
std::unique_ptr<Expression> noInitialValue;
|
||||
resultExpr = makeInlineVar(String(function.fDeclaration.name()),
|
||||
&function.fDeclaration.fReturnType,
|
||||
&function.fDeclaration.returnType(),
|
||||
Modifiers{}, &noInitialValue);
|
||||
}
|
||||
|
||||
@ -668,7 +668,7 @@ Inliner::InlinedCall Inliner::inlineCall(FunctionCall* call,
|
||||
VariableRewriteMap varMap;
|
||||
std::vector<int> argsToCopyBack;
|
||||
for (int i = 0; i < (int) arguments.size(); ++i) {
|
||||
const Variable* param = function.fDeclaration.fParameters[i];
|
||||
const Variable* param = function.fDeclaration.parameters()[i];
|
||||
bool isOutParam = param->modifiers().fFlags & Modifiers::kOut_Flag;
|
||||
|
||||
// If this argument can be inlined trivially (e.g. a swizzle, or a constant array index)...
|
||||
@ -695,7 +695,7 @@ Inliner::InlinedCall Inliner::inlineCall(FunctionCall* call,
|
||||
for (const std::unique_ptr<Statement>& stmt : body.children()) {
|
||||
inlineBlock->children().push_back(this->inlineStatement(offset, &varMap, symbolTableForCall,
|
||||
resultExpr.get(), hasEarlyReturn,
|
||||
*stmt, caller->fBuiltin));
|
||||
*stmt, caller->isBuiltin()));
|
||||
}
|
||||
if (hasEarlyReturn) {
|
||||
// Since we output to backends that don't have a goto statement (which would normally be
|
||||
@ -714,7 +714,7 @@ Inliner::InlinedCall Inliner::inlineCall(FunctionCall* call,
|
||||
|
||||
// Copy back the values of `out` parameters into their real destinations.
|
||||
for (int i : argsToCopyBack) {
|
||||
const Variable* p = function.fDeclaration.fParameters[i];
|
||||
const Variable* p = function.fDeclaration.parameters()[i];
|
||||
SkASSERT(varMap.find(p) != varMap.end());
|
||||
inlinedBody.children().push_back(
|
||||
std::make_unique<ExpressionStatement>(std::make_unique<BinaryExpression>(
|
||||
@ -1071,7 +1071,7 @@ bool Inliner::candidateCanBeInlined(const InlineCandidate& candidate, Inlinabili
|
||||
auto [iter, wasInserted] = cache->insert({&funcDecl, false});
|
||||
if (wasInserted) {
|
||||
// Recursion is forbidden here to avoid an infinite death spiral of inlining.
|
||||
iter->second = this->isSafeToInline(funcDecl.fDefinition) &&
|
||||
iter->second = this->isSafeToInline(funcDecl.definition()) &&
|
||||
!contains_recursive_call(funcDecl);
|
||||
}
|
||||
|
||||
@ -1088,7 +1088,7 @@ bool Inliner::isLargeFunction(const InlineCandidate& candidate, LargeFunctionCac
|
||||
|
||||
auto [iter, wasInserted] = cache->insert({&funcDecl, false});
|
||||
if (wasInserted) {
|
||||
iter->second = this->isLargeFunction(funcDecl.fDefinition);
|
||||
iter->second = this->isLargeFunction(funcDecl.definition());
|
||||
}
|
||||
|
||||
return iter->second;
|
||||
@ -1135,8 +1135,8 @@ bool Inliner::analyze(Program& program) {
|
||||
// If the function is large, not marked `inline`, and is called more than once, it's a bad
|
||||
// idea to inline it.
|
||||
if (candidate.fIsLargeFunction &&
|
||||
!(funcDecl->fModifiers.fFlags & Modifiers::kInline_Flag) &&
|
||||
funcDecl->fCallCount.load() > 1) {
|
||||
!(funcDecl->modifiers().fFlags & Modifiers::kInline_Flag) &&
|
||||
funcDecl->callCount() > 1) {
|
||||
continue;
|
||||
}
|
||||
|
||||
|
@ -220,16 +220,17 @@ void MetalCodeGenerator::writeFunctionCall(const FunctionCall& c) {
|
||||
return;
|
||||
}
|
||||
const StringFragment& name = function.name();
|
||||
if (function.fBuiltin && name == "atan" && arguments.size() == 2) {
|
||||
bool builtin = function.isBuiltin();
|
||||
if (builtin && name == "atan" && arguments.size() == 2) {
|
||||
this->write("atan2");
|
||||
} else if (function.fBuiltin && name == "inversesqrt") {
|
||||
} else if (builtin && name == "inversesqrt") {
|
||||
this->write("rsqrt");
|
||||
} else if (function.fBuiltin && name == "inverse") {
|
||||
} else if (builtin && name == "inverse") {
|
||||
SkASSERT(arguments.size() == 1);
|
||||
this->writeInverseHack(*arguments[0]);
|
||||
} else if (function.fBuiltin && name == "dFdx") {
|
||||
} else if (builtin && name == "dFdx") {
|
||||
this->write("dfdx");
|
||||
} else if (function.fBuiltin && name == "dFdy") {
|
||||
} else if (builtin && name == "dFdy") {
|
||||
// Flipping Y also negates the Y derivatives.
|
||||
this->write((fProgram.fSettings.fFlipY) ? "-dfdy" : "dfdy");
|
||||
} else {
|
||||
@ -261,11 +262,12 @@ void MetalCodeGenerator::writeFunctionCall(const FunctionCall& c) {
|
||||
this->write("_fragCoord");
|
||||
separator = ", ";
|
||||
}
|
||||
const std::vector<Variable*>& parameters = function.parameters();
|
||||
for (size_t i = 0; i < arguments.size(); ++i) {
|
||||
const Expression& arg = *arguments[i];
|
||||
this->write(separator);
|
||||
separator = ", ";
|
||||
if (function.fParameters[i]->modifiers().fFlags & Modifiers::kOut_Flag) {
|
||||
if (parameters[i]->modifiers().fFlags & Modifiers::kOut_Flag) {
|
||||
this->write("&");
|
||||
}
|
||||
this->writeExpression(arg, kSequence_Precedence);
|
||||
@ -1004,7 +1006,7 @@ void MetalCodeGenerator::writeFunction(const FunctionDefinition& f) {
|
||||
}
|
||||
separator = ", ";
|
||||
} else {
|
||||
this->writeType(f.fDeclaration.fReturnType);
|
||||
this->writeType(f.fDeclaration.returnType());
|
||||
this->write(" ");
|
||||
this->writeName(f.fDeclaration.name());
|
||||
this->write("(");
|
||||
@ -1034,7 +1036,7 @@ void MetalCodeGenerator::writeFunction(const FunctionDefinition& f) {
|
||||
separator = ", ";
|
||||
}
|
||||
}
|
||||
for (const auto& param : f.fDeclaration.fParameters) {
|
||||
for (const auto& param : f.fDeclaration.parameters()) {
|
||||
this->write(separator);
|
||||
separator = ", ";
|
||||
this->writeModifiers(param->modifiers(), false);
|
||||
@ -1801,7 +1803,7 @@ MetalCodeGenerator::Requirements MetalCodeGenerator::requirements(const Statemen
|
||||
}
|
||||
|
||||
MetalCodeGenerator::Requirements MetalCodeGenerator::requirements(const FunctionDeclaration& f) {
|
||||
if (f.fBuiltin) {
|
||||
if (f.isBuiltin()) {
|
||||
return kNo_Requirements;
|
||||
}
|
||||
auto found = fRequirements.find(&f);
|
||||
|
@ -35,7 +35,7 @@ String PipelineStageCodeGenerator::getTypeName(const Type& type) {
|
||||
void PipelineStageCodeGenerator::writeFunctionCall(const FunctionCall& c) {
|
||||
const FunctionDeclaration& function = c.function();
|
||||
const std::vector<std::unique_ptr<Expression>>& arguments = c.arguments();
|
||||
if (function.fBuiltin && function.name() == "sample" &&
|
||||
if (function.isBuiltin() && function.name() == "sample" &&
|
||||
arguments[0]->type().typeKind() != Type::TypeKind::kSampler) {
|
||||
SkASSERT(arguments.size() <= 2);
|
||||
SkDEBUGCODE(const Type& arg0Type = arguments[0]->type());
|
||||
@ -76,7 +76,7 @@ void PipelineStageCodeGenerator::writeFunctionCall(const FunctionCall& c) {
|
||||
}
|
||||
return;
|
||||
}
|
||||
if (function.fBuiltin) {
|
||||
if (function.isBuiltin()) {
|
||||
INHERITED::writeFunctionCall(c);
|
||||
} else {
|
||||
int index = 0;
|
||||
@ -184,12 +184,12 @@ void PipelineStageCodeGenerator::writeFunction(const FunctionDefinition& f) {
|
||||
} else {
|
||||
const FunctionDeclaration& decl = f.fDeclaration;
|
||||
Compiler::GLSLFunction result;
|
||||
if (!type_to_grsltype(fContext, decl.fReturnType, &result.fReturnType)) {
|
||||
if (!type_to_grsltype(fContext, decl.returnType(), &result.fReturnType)) {
|
||||
fErrors.error(f.fOffset, "unsupported return type");
|
||||
return;
|
||||
}
|
||||
result.fName = decl.name();
|
||||
for (const Variable* v : decl.fParameters) {
|
||||
for (const Variable* v : decl.parameters()) {
|
||||
GrSLType paramSLType;
|
||||
if (!type_to_grsltype(fContext, v->type(), ¶mSLType)) {
|
||||
fErrors.error(v->fOffset, "unsupported parameter type");
|
||||
|
@ -165,8 +165,8 @@ Symbol* Rehydrator::symbol() {
|
||||
const Type* returnType = this->type();
|
||||
FunctionDeclaration* result =
|
||||
fSymbolTable->takeOwnershipOfSymbol(std::make_unique<FunctionDeclaration>(
|
||||
/*offset=*/-1, modifiers, name, std::move(parameters), *returnType,
|
||||
/*builtin=*/true));
|
||||
/*offset=*/-1, fModifiers.handle(modifiers), name,
|
||||
std::move(parameters), returnType, /*builtin=*/true));
|
||||
this->addSymbol(id, result);
|
||||
return result;
|
||||
}
|
||||
@ -302,7 +302,7 @@ std::unique_ptr<ProgramElement> Rehydrator::element() {
|
||||
}
|
||||
FunctionDefinition* result = new FunctionDefinition(-1, *decl, std::move(body),
|
||||
std::move(refs));
|
||||
decl->fDefinition = result;
|
||||
decl->setDefinition(result);
|
||||
return std::unique_ptr<ProgramElement>(result);
|
||||
}
|
||||
case Rehydrator::kInterfaceBlock_Command: {
|
||||
|
@ -578,21 +578,22 @@ SpvId SPIRVCodeGenerator::getImageType(const Type& type) {
|
||||
}
|
||||
|
||||
SpvId SPIRVCodeGenerator::getFunctionType(const FunctionDeclaration& function) {
|
||||
String key = to_string(this->getType(function.fReturnType)) + "(";
|
||||
String key = to_string(this->getType(function.returnType())) + "(";
|
||||
String separator;
|
||||
for (size_t i = 0; i < function.fParameters.size(); i++) {
|
||||
const std::vector<Variable*>& parameters = function.parameters();
|
||||
for (size_t i = 0; i < parameters.size(); i++) {
|
||||
key += separator;
|
||||
separator = ", ";
|
||||
key += to_string(this->getType(function.fParameters[i]->type()));
|
||||
key += to_string(this->getType(parameters[i]->type()));
|
||||
}
|
||||
key += ")";
|
||||
auto entry = fTypeMap.find(key);
|
||||
if (entry == fTypeMap.end()) {
|
||||
SpvId result = this->nextId();
|
||||
int32_t length = 3 + (int32_t) function.fParameters.size();
|
||||
SpvId returnType = this->getType(function.fReturnType);
|
||||
int32_t length = 3 + (int32_t) parameters.size();
|
||||
SpvId returnType = this->getType(function.returnType());
|
||||
std::vector<SpvId> parameterTypes;
|
||||
for (size_t i = 0; i < function.fParameters.size(); i++) {
|
||||
for (size_t i = 0; i < parameters.size(); i++) {
|
||||
// glslang seems to treat all function arguments as pointers whether they need to be or
|
||||
// not. I was initially puzzled by this until I ran bizarre failures with certain
|
||||
// patterns of function calls and control constructs, as exemplified by this minimal
|
||||
@ -616,7 +617,7 @@ SpvId SPIRVCodeGenerator::getFunctionType(const FunctionDeclaration& function) {
|
||||
// as glslang does, fixes it. It's entirely possible I simply missed whichever part of
|
||||
// the spec makes this make sense.
|
||||
// if (is_out(function->fParameters[i])) {
|
||||
parameterTypes.push_back(this->getPointerType(function.fParameters[i]->type(),
|
||||
parameterTypes.push_back(this->getPointerType(parameters[i]->type(),
|
||||
SpvStorageClassFunction));
|
||||
// } else {
|
||||
// parameterTypes.push_back(this->getType(function.fParameters[i]->fType));
|
||||
@ -717,7 +718,7 @@ SpvId SPIRVCodeGenerator::writeIntrinsicCall(const FunctionCall& c, OutputStream
|
||||
SpvId result = this->nextId();
|
||||
std::vector<SpvId> argumentIds;
|
||||
for (size_t i = 0; i < arguments.size(); i++) {
|
||||
if (function.fParameters[i]->modifiers().fFlags & Modifiers::kOut_Flag) {
|
||||
if (function.parameters()[i]->modifiers().fFlags & Modifiers::kOut_Flag) {
|
||||
argumentIds.push_back(this->getLValue(*arguments[i], out)->getPointer());
|
||||
} else {
|
||||
argumentIds.push_back(this->writeExpression(*arguments[i], out));
|
||||
@ -737,7 +738,7 @@ SpvId SPIRVCodeGenerator::writeIntrinsicCall(const FunctionCall& c, OutputStream
|
||||
SpvId result = this->nextId();
|
||||
std::vector<SpvId> argumentIds;
|
||||
for (size_t i = 0; i < arguments.size(); i++) {
|
||||
if (function.fParameters[i]->modifiers().fFlags & Modifiers::kOut_Flag) {
|
||||
if (function.parameters()[i]->modifiers().fFlags & Modifiers::kOut_Flag) {
|
||||
argumentIds.push_back(this->getLValue(*arguments[i], out)->getPointer());
|
||||
} else {
|
||||
argumentIds.push_back(this->writeExpression(*arguments[i], out));
|
||||
@ -1032,7 +1033,7 @@ SpvId SPIRVCodeGenerator::writeFunctionCall(const FunctionCall& c, OutputStream&
|
||||
SpvId tmpVar;
|
||||
// if we need a temporary var to store this argument, this is the value to store in the var
|
||||
SpvId tmpValueId;
|
||||
if (is_out(*function.fParameters[i])) {
|
||||
if (is_out(*function.parameters()[i])) {
|
||||
std::unique_ptr<LValue> lv = this->getLValue(*arguments[i], out);
|
||||
SpvId ptr = lv->getPointer();
|
||||
if (ptr) {
|
||||
@ -2579,14 +2580,15 @@ SpvId SPIRVCodeGenerator::writeFloatLiteral(const FloatLiteral& f) {
|
||||
|
||||
SpvId SPIRVCodeGenerator::writeFunctionStart(const FunctionDeclaration& f, OutputStream& out) {
|
||||
SpvId result = fFunctionMap[&f];
|
||||
this->writeInstruction(SpvOpFunction, this->getType(f.fReturnType), result,
|
||||
this->writeInstruction(SpvOpFunction, this->getType(f.returnType()), result,
|
||||
SpvFunctionControlMaskNone, this->getFunctionType(f), out);
|
||||
this->writeInstruction(SpvOpName, result, f.name(), fNameBuffer);
|
||||
for (size_t i = 0; i < f.fParameters.size(); i++) {
|
||||
const std::vector<Variable*>& parameters = f.parameters();
|
||||
for (size_t i = 0; i < parameters.size(); i++) {
|
||||
SpvId id = this->nextId();
|
||||
fVariableMap[f.fParameters[i]] = id;
|
||||
fVariableMap[parameters[i]] = id;
|
||||
SpvId type;
|
||||
type = this->getPointerType(f.fParameters[i]->type(), SpvStorageClassFunction);
|
||||
type = this->getPointerType(parameters[i]->type(), SpvStorageClassFunction);
|
||||
this->writeInstruction(SpvOpFunctionParameter, type, id, out);
|
||||
}
|
||||
return result;
|
||||
@ -2604,7 +2606,7 @@ SpvId SPIRVCodeGenerator::writeFunction(const FunctionDefinition& f, OutputStrea
|
||||
}
|
||||
write_stringstream(bodyBuffer, out);
|
||||
if (fCurrentBlock) {
|
||||
if (f.fDeclaration.fReturnType == *fContext.fVoid_Type) {
|
||||
if (f.fDeclaration.returnType() == *fContext.fVoid_Type) {
|
||||
this->writeInstruction(SpvOpReturn, out);
|
||||
} else {
|
||||
this->writeInstruction(SpvOpUnreachable, out);
|
||||
|
@ -24,11 +24,11 @@ public:
|
||||
std::vector<std::unique_ptr<Expression>> arguments)
|
||||
: INHERITED(offset, FunctionCallData{type, function}) {
|
||||
fExpressionChildren = std::move(arguments);
|
||||
++this->function().fCallCount;
|
||||
++this->function().callCount();
|
||||
}
|
||||
|
||||
~FunctionCall() override {
|
||||
--this->function().fCallCount;
|
||||
--this->function().callCount();
|
||||
}
|
||||
|
||||
const Type& type() const override {
|
||||
@ -48,7 +48,7 @@ public:
|
||||
}
|
||||
|
||||
bool hasProperty(Property property) const override {
|
||||
if (property == Property::kSideEffects && (this->function().fModifiers.fFlags &
|
||||
if (property == Property::kSideEffects && (this->function().modifiers().fFlags &
|
||||
Modifiers::kHasSideEffects_Flag)) {
|
||||
return true;
|
||||
}
|
||||
|
@ -24,23 +24,53 @@ struct FunctionDefinition;
|
||||
/**
|
||||
* A function declaration (not a definition -- does not contain a body).
|
||||
*/
|
||||
struct FunctionDeclaration : public Symbol {
|
||||
class FunctionDeclaration : public Symbol {
|
||||
public:
|
||||
static constexpr Kind kSymbolKind = Kind::kFunctionDeclaration;
|
||||
|
||||
FunctionDeclaration(int offset, Modifiers modifiers, StringFragment name,
|
||||
std::vector<Variable*> parameters, const Type& returnType,
|
||||
FunctionDeclaration(int offset, ModifiersPool::Handle modifiers, StringFragment name,
|
||||
std::vector<Variable*> parameters, const Type* returnType,
|
||||
bool builtin)
|
||||
: INHERITED(offset, kSymbolKind, std::move(name))
|
||||
, fDefinition(nullptr)
|
||||
, fBuiltin(builtin)
|
||||
, fModifiers(modifiers)
|
||||
, fParameters(std::move(parameters))
|
||||
, fReturnType(returnType) {}
|
||||
: INHERITED(offset, FunctionDeclarationData{name, /*fDefiniition=*/nullptr, modifiers,
|
||||
std::move(parameters), returnType,
|
||||
/*fCallCount=*/0, builtin}) {}
|
||||
|
||||
const Modifiers& modifiers() const {
|
||||
return *this->functionDeclarationData().fModifiersHandle;
|
||||
}
|
||||
|
||||
StringFragment name() const override {
|
||||
return this->functionDeclarationData().fName;
|
||||
}
|
||||
|
||||
const FunctionDefinition* definition() const {
|
||||
return this->functionDeclarationData().fDefinition;
|
||||
}
|
||||
|
||||
void setDefinition(const FunctionDefinition* definition) const {
|
||||
this->functionDeclarationData().fDefinition = definition;
|
||||
}
|
||||
|
||||
const std::vector<Variable*>& parameters() const {
|
||||
return this->functionDeclarationData().fParameters;
|
||||
}
|
||||
|
||||
const Type& returnType() const {
|
||||
return *this->functionDeclarationData().fReturnType;
|
||||
}
|
||||
|
||||
bool isBuiltin() const {
|
||||
return this->functionDeclarationData().fBuiltin;
|
||||
}
|
||||
|
||||
std::atomic<int>& callCount() const {
|
||||
return this->functionDeclarationData().fCallCount;
|
||||
}
|
||||
|
||||
String description() const override {
|
||||
String result = fReturnType.displayName() + " " + this->name() + "(";
|
||||
String result = this->returnType().displayName() + " " + this->name() + "(";
|
||||
String separator;
|
||||
for (auto p : fParameters) {
|
||||
for (auto p : this->parameters()) {
|
||||
result += separator;
|
||||
separator = ", ";
|
||||
result += p->type().displayName();
|
||||
@ -53,11 +83,13 @@ struct FunctionDeclaration : public Symbol {
|
||||
if (this->name() != f.name()) {
|
||||
return false;
|
||||
}
|
||||
if (fParameters.size() != f.fParameters.size()) {
|
||||
const std::vector<Variable*>& parameters = this->parameters();
|
||||
const std::vector<Variable*>& otherParameters = f.parameters();
|
||||
if (parameters.size() != otherParameters.size()) {
|
||||
return false;
|
||||
}
|
||||
for (size_t i = 0; i < fParameters.size(); i++) {
|
||||
if (fParameters[i]->type() != f.fParameters[i]->type()) {
|
||||
for (size_t i = 0; i < parameters.size(); i++) {
|
||||
if (parameters[i]->type() != otherParameters[i]->type()) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
@ -82,10 +114,11 @@ struct FunctionDeclaration : public Symbol {
|
||||
bool determineFinalTypes(const std::vector<std::unique_ptr<Expression>>& arguments,
|
||||
std::vector<const Type*>* outParameterTypes,
|
||||
const Type** outReturnType) const {
|
||||
SkASSERT(arguments.size() == fParameters.size());
|
||||
const std::vector<Variable*>& parameters = this->parameters();
|
||||
SkASSERT(arguments.size() == parameters.size());
|
||||
int genericIndex = -1;
|
||||
for (size_t i = 0; i < arguments.size(); i++) {
|
||||
const Type& parameterType = fParameters[i]->type();
|
||||
const Type& parameterType = parameters[i]->type();
|
||||
if (parameterType.typeKind() == Type::TypeKind::kGeneric) {
|
||||
std::vector<const Type*> types = parameterType.coercibleTypes();
|
||||
if (genericIndex == -1) {
|
||||
@ -104,24 +137,19 @@ struct FunctionDeclaration : public Symbol {
|
||||
outParameterTypes->push_back(¶meterType);
|
||||
}
|
||||
}
|
||||
if (fReturnType.typeKind() == Type::TypeKind::kGeneric) {
|
||||
const Type& returnType = this->returnType();
|
||||
if (returnType.typeKind() == Type::TypeKind::kGeneric) {
|
||||
if (genericIndex == -1) {
|
||||
return false;
|
||||
}
|
||||
*outReturnType = fReturnType.coercibleTypes()[genericIndex];
|
||||
*outReturnType = returnType.coercibleTypes()[genericIndex];
|
||||
} else {
|
||||
*outReturnType = &fReturnType;
|
||||
*outReturnType = &returnType;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
mutable FunctionDefinition* fDefinition;
|
||||
bool fBuiltin;
|
||||
Modifiers fModifiers;
|
||||
const std::vector<Variable*> fParameters;
|
||||
const Type& fReturnType;
|
||||
mutable std::atomic<int> fCallCount = 0;
|
||||
|
||||
private:
|
||||
using INHERITED = Symbol;
|
||||
};
|
||||
|
||||
|
@ -48,6 +48,11 @@ IRNode::IRNode(int offset, int kind, const FunctionCallData& data)
|
||||
, fKind(kind)
|
||||
, fData(data) {}
|
||||
|
||||
IRNode::IRNode(int offset, int kind, const FunctionDeclarationData& data)
|
||||
: fOffset(offset)
|
||||
, fKind(kind)
|
||||
, fData(data) {}
|
||||
|
||||
IRNode::IRNode(int offset, int kind, const IfStatementData& data)
|
||||
: fOffset(offset)
|
||||
, fKind(kind)
|
||||
|
@ -20,7 +20,8 @@ namespace SkSL {
|
||||
|
||||
class Expression;
|
||||
class ExternalValue;
|
||||
struct FunctionDeclaration;
|
||||
class FunctionDeclaration;
|
||||
struct FunctionDefinition;
|
||||
class Statement;
|
||||
class Symbol;
|
||||
class SymbolTable;
|
||||
@ -100,6 +101,29 @@ protected:
|
||||
const FunctionDeclaration* fFunction;
|
||||
};
|
||||
|
||||
struct FunctionDeclarationData {
|
||||
StringFragment fName;
|
||||
mutable const FunctionDefinition* fDefinition;
|
||||
ModifiersPool::Handle fModifiersHandle;
|
||||
// FIXME after killing fExpressionChildren / fStatementChildren in favor of just fChildren,
|
||||
// the parameters should move into that vector
|
||||
std::vector<Variable*> fParameters;
|
||||
const Type* fReturnType;
|
||||
mutable std::atomic<int> fCallCount;
|
||||
bool fBuiltin;
|
||||
|
||||
FunctionDeclarationData& operator=(const FunctionDeclarationData& other) {
|
||||
fName = other.fName;
|
||||
fDefinition = other.fDefinition;
|
||||
fModifiersHandle = other.fModifiersHandle;
|
||||
fParameters = other.fParameters;
|
||||
fReturnType = other.fReturnType;
|
||||
fCallCount = other.fCallCount.load();
|
||||
fBuiltin = other.fBuiltin;
|
||||
return *this;
|
||||
}
|
||||
};
|
||||
|
||||
struct IfStatementData {
|
||||
bool fIsStatic;
|
||||
};
|
||||
@ -154,6 +178,7 @@ protected:
|
||||
kFloatLiteral,
|
||||
kForStatement,
|
||||
kFunctionCall,
|
||||
kFunctionDeclaration,
|
||||
kIfStatement,
|
||||
kIntLiteral,
|
||||
kString,
|
||||
@ -175,6 +200,7 @@ protected:
|
||||
FloatLiteralData fFloatLiteral;
|
||||
ForStatementData fForStatement;
|
||||
FunctionCallData fFunctionCall;
|
||||
FunctionDeclarationData fFunctionDeclaration;
|
||||
IfStatementData fIfStatement;
|
||||
IntLiteralData fIntLiteral;
|
||||
String fString;
|
||||
@ -230,6 +256,11 @@ protected:
|
||||
*(new(&fContents) FunctionCallData) = data;
|
||||
}
|
||||
|
||||
NodeData(const FunctionDeclarationData& data)
|
||||
: fKind(Kind::kFunctionDeclaration) {
|
||||
*(new(&fContents) FunctionDeclarationData) = data;
|
||||
}
|
||||
|
||||
NodeData(IfStatementData data)
|
||||
: fKind(Kind::kIfStatement) {
|
||||
*(new(&fContents) IfStatementData) = data;
|
||||
@ -307,6 +338,10 @@ protected:
|
||||
case Kind::kFunctionCall:
|
||||
*(new(&fContents) FunctionCallData) = other.fContents.fFunctionCall;
|
||||
break;
|
||||
case Kind::kFunctionDeclaration:
|
||||
*(new(&fContents) FunctionDeclarationData) =
|
||||
other.fContents.fFunctionDeclaration;
|
||||
break;
|
||||
case Kind::kIfStatement:
|
||||
*(new(&fContents) IfStatementData) = other.fContents.fIfStatement;
|
||||
break;
|
||||
@ -372,6 +407,9 @@ protected:
|
||||
case Kind::kIfStatement:
|
||||
fContents.fIfStatement.~IfStatementData();
|
||||
break;
|
||||
case Kind::kFunctionDeclaration:
|
||||
fContents.fFunctionDeclaration.~FunctionDeclarationData();
|
||||
break;
|
||||
case Kind::kIntLiteral:
|
||||
fContents.fIntLiteral.~IntLiteralData();
|
||||
break;
|
||||
@ -418,6 +456,8 @@ protected:
|
||||
|
||||
IRNode(int offset, int kind, const IfStatementData& data);
|
||||
|
||||
IRNode(int offset, int kind, const FunctionDeclarationData& data);
|
||||
|
||||
IRNode(int offset, int kind, const IntLiteralData& data);
|
||||
|
||||
IRNode(int offset, int kind, const String& data);
|
||||
@ -518,11 +558,21 @@ protected:
|
||||
return fData.fContents.fFunctionCall;
|
||||
}
|
||||
|
||||
FunctionDeclarationData& functionDeclarationData() {
|
||||
SkASSERT(fData.fKind == NodeData::Kind::kFunctionDeclaration);
|
||||
return fData.fContents.fFunctionDeclaration;
|
||||
}
|
||||
|
||||
const IfStatementData& ifStatementData() const {
|
||||
SkASSERT(fData.fKind == NodeData::Kind::kIfStatement);
|
||||
return fData.fContents.fIfStatement;
|
||||
}
|
||||
|
||||
const FunctionDeclarationData& functionDeclarationData() const {
|
||||
SkASSERT(fData.fKind == NodeData::Kind::kFunctionDeclaration);
|
||||
return fData.fContents.fFunctionDeclaration;
|
||||
}
|
||||
|
||||
const IntLiteralData& intLiteralData() const {
|
||||
SkASSERT(fData.fKind == NodeData::Kind::kIntLiteral);
|
||||
return fData.fContents.fIntLiteral;
|
||||
|
@ -39,6 +39,9 @@ public:
|
||||
Symbol(int offset, const FieldData& data)
|
||||
: INHERITED(offset, (int) Kind::kField, data) {}
|
||||
|
||||
Symbol(int offset, const FunctionDeclarationData& data)
|
||||
: INHERITED(offset, (int) Kind::kFunctionDeclaration, data) {}
|
||||
|
||||
Symbol(int offset, const SymbolAliasData& data)
|
||||
: INHERITED(offset, (int) Kind::kSymbolAlias, data) {}
|
||||
|
||||
|
@ -16,7 +16,7 @@
|
||||
|
||||
namespace SkSL {
|
||||
|
||||
struct FunctionDeclaration;
|
||||
class FunctionDeclaration;
|
||||
|
||||
/**
|
||||
* Maps identifiers to symbols. Functions, in particular, are mapped to either FunctionDeclaration
|
||||
|
Loading…
Reference in New Issue
Block a user