Fix inline code generation when literals appear in the argument list.

We don't expect raw literals to ever appear here; this is a defensive
maneuver. See http://review.skia.org/316440 for an example case where
raw literals accidentally made it all the way to the inlining pass, due
to a missing `coerce`.

Change-Id: I80198f2f135791931aa53e0d6d92f1edfe4fb3b5
Reviewed-on: https://skia-review.googlesource.com/c/skia/+/315970
Reviewed-by: Ethan Nicholas <ethannicholas@google.com>
Commit-Queue: John Stiles <johnstiles@google.com>
Auto-Submit: John Stiles <johnstiles@google.com>
This commit is contained in:
John Stiles 2020-09-11 09:43:49 -04:00 committed by Skia Commit-Bot
parent 66b45a7f40
commit a003e8184e
2 changed files with 126 additions and 6 deletions

View File

@ -484,8 +484,19 @@ Inliner::InlinedCall Inliner::inlineCall(FunctionCall* call,
inlinedBody.push_back(std::make_unique<InlineMarker>(call->fFunction));
auto makeInlineVar = [&](const String& baseName, const Type& type, Modifiers modifiers,
auto makeInlineVar = [&](const String& baseName, const Type* type, Modifiers modifiers,
std::unique_ptr<Expression>* initialValue) -> const Variable* {
// $floatLiteral or $intLiteral aren't real types that we can use for scratch variables, so
// replace them if they ever appear here. If this happens, we likely forgot to coerce a type
// somewhere during compilation.
if (type == fContext->fFloatLiteral_Type.get()) {
SkASSERT(!"found a $floatLiteral type while inlining");
type = fContext->fFloat_Type.get();
} else if (type == fContext->fIntLiteral_Type.get()) {
SkASSERT(!"found an $intLiteral type while inlining");
type = fContext->fInt_Type.get();
}
// If the base name starts with an underscore, like "_coords", we can't append another
// underscore, because some OpenGL platforms error out when they see two consecutive
// underscores (anywhere in the string!). But in the general case, using the underscore as
@ -510,7 +521,7 @@ Inliner::InlinedCall Inliner::inlineCall(FunctionCall* call,
StringFragment nameFrag{namePtr->c_str(), namePtr->length()};
// Add our new variable to the symbol table.
auto newVar = std::make_unique<Variable>(/*offset=*/-1, Modifiers(), nameFrag, type,
auto newVar = std::make_unique<Variable>(/*offset=*/-1, Modifiers(), nameFrag, *type,
Variable::kLocal_Storage, initialValue->get());
const Variable* variableSymbol = symbolTableForCall->add(nameFrag, std::move(newVar));
@ -529,7 +540,7 @@ Inliner::InlinedCall Inliner::inlineCall(FunctionCall* call,
// Add the new variable-declaration statement to our block of extra statements.
inlinedBody.push_back(std::make_unique<VarDeclarationsStatement>(
std::make_unique<VarDeclarations>(offset, &type, std::move(variables))));
std::make_unique<VarDeclarations>(offset, type, std::move(variables))));
return variableSymbol;
};
@ -539,7 +550,7 @@ Inliner::InlinedCall Inliner::inlineCall(FunctionCall* call,
if (function.fDeclaration.fReturnType != *fContext->fVoid_Type) {
std::unique_ptr<Expression> noInitialValue;
resultVar = makeInlineVar(String(function.fDeclaration.fName),
function.fDeclaration.fReturnType, Modifiers{}, &noInitialValue);
&function.fDeclaration.fReturnType, Modifiers{}, &noInitialValue);
}
// Create variables in the extra statements to hold the arguments, and assign the arguments to
@ -548,7 +559,7 @@ Inliner::InlinedCall Inliner::inlineCall(FunctionCall* call,
for (int i = 0; i < (int) arguments.size(); ++i) {
const Variable* param = function.fDeclaration.fParameters[i];
if (arguments[i]->kind() == Expression::Kind::kVariableReference) {
if (arguments[i]->is<VariableReference>()) {
// The argument is just a variable, so we only need to copy it if it's an out parameter
// or it's written to within the function.
if ((param->fModifiers.fFlags & Modifiers::kOut_Flag) ||
@ -558,7 +569,7 @@ Inliner::InlinedCall Inliner::inlineCall(FunctionCall* call,
}
}
varMap[param] = makeInlineVar(String(param->fName), arguments[i]->fType, param->fModifiers,
varMap[param] = makeInlineVar(String(param->fName), &arguments[i]->fType, param->fModifiers,
&arguments[i]);
}

View File

@ -1129,3 +1129,112 @@ void main() {
}
)__GLSL__");
}
DEF_TEST(SkSLFunctionMultipleInlinesOnOneLine, r) {
test(r,
*SkSL::ShaderCapsFactory::Default(),
R"__SkSL__(
uniform half val;
inline half BigX(half x) {
++x; ++x; ++x; ++x; ++x; ++x; ++x; ++x; ++x; ++x; ++x; ++x; ++x; ++x; ++x; ++x; ++x;
--x; --x; --x; --x; --x; --x; --x; --x; --x; --x; --x; --x; --x; --x; --x; --x; --x;
x = 123;
return x;
}
inline half BigY(half x) {
++x; ++x; ++x; ++x; ++x; ++x; ++x; ++x; ++x; ++x; ++x; ++x; ++x; ++x; ++x; ++x; ++x;
--x; --x; --x; --x; --x; --x; --x; --x; --x; --x; --x; --x; --x; --x; --x; --x; --x;
x = 456;
return x;
}
void main() {
sk_FragColor = BigX(BigY(val)).xxxx;
}
)__SkSL__",
R"__GLSL__(#version 400
out vec4 sk_FragColor;
uniform float val;
void main() {
float _1_x = val;
{
++_1_x;
++_1_x;
++_1_x;
++_1_x;
++_1_x;
++_1_x;
++_1_x;
++_1_x;
++_1_x;
++_1_x;
++_1_x;
++_1_x;
++_1_x;
++_1_x;
++_1_x;
++_1_x;
++_1_x;
--_1_x;
--_1_x;
--_1_x;
--_1_x;
--_1_x;
--_1_x;
--_1_x;
--_1_x;
--_1_x;
--_1_x;
--_1_x;
--_1_x;
--_1_x;
--_1_x;
--_1_x;
--_1_x;
--_1_x;
_1_x = 456.0;
}
float _3_x = 456.0;
{
++_3_x;
++_3_x;
++_3_x;
++_3_x;
++_3_x;
++_3_x;
++_3_x;
++_3_x;
++_3_x;
++_3_x;
++_3_x;
++_3_x;
++_3_x;
++_3_x;
++_3_x;
++_3_x;
++_3_x;
--_3_x;
--_3_x;
--_3_x;
--_3_x;
--_3_x;
--_3_x;
--_3_x;
--_3_x;
--_3_x;
--_3_x;
--_3_x;
--_3_x;
--_3_x;
--_3_x;
--_3_x;
--_3_x;
--_3_x;
_3_x = 123.0;
}
sk_FragColor = vec4(123.0);
}
)__GLSL__");
}