Assign unique names to inlined variable declarations.

Change-Id: I6097f50e7be1fa2f7772f6c454410ecbf3470eea
Bug: skia:10722
Reviewed-on: https://skia-review.googlesource.com/c/skia/+/316977
Commit-Queue: John Stiles <johnstiles@google.com>
Auto-Submit: John Stiles <johnstiles@google.com>
Reviewed-by: Brian Osman <brianosman@google.com>
This commit is contained in:
John Stiles 2020-09-14 18:24:12 -04:00 committed by Skia Commit-Bot
parent 8f026259d8
commit c75abb8432
5 changed files with 110 additions and 101 deletions

View File

@ -263,6 +263,28 @@ void Inliner::reset(const Context& context, const Program::Settings& settings) {
fInlineVarCounter = 0;
}
String Inliner::uniqueNameForInlineVar(const String& baseName, SymbolTable* symbolTable) {
// If the base name starts with an underscore, like "_coords", we can't append another
// underscore, because OpenGL disallows two consecutive underscores anywhere in the string. But
// in the general case, using the underscore as a splitter reads nicely enough that it's worth
// putting in this special case.
const char* splitter = baseName.startsWith("_") ? "" : "_";
// Append a unique numeric prefix to avoid name overlap. Check the symbol table to make sure
// we're not reusing an existing name. (Note that within a single compilation pass, this check
// isn't fully comprehensive, as code isn't always generated in top-to-bottom order.)
String uniqueName;
for (;;) {
uniqueName = String::printf("_%d%s%s", fInlineVarCounter++, splitter, baseName.c_str());
StringFragment frag{uniqueName.data(), uniqueName.length()};
if ((*symbolTable)[frag] == nullptr) {
break;
}
}
return uniqueName;
}
std::unique_ptr<Expression> Inliner::inlineExpression(int offset,
VariableRewriteMap* varMap,
const Expression& expression) {
@ -466,9 +488,11 @@ std::unique_ptr<Statement> Inliner::inlineStatement(int offset,
}
std::unique_ptr<Expression> initialValue = expr(decl.fValue);
const Variable* old = decl.fVar;
// need to copy the var name in case the originating function is discarded and we lose
// its symbols
std::unique_ptr<String> name(new String(old->fName));
// We assign unique names to inlined variables--scopes hide most of the problems in this
// regard, but see `InlinerAvoidsVariableNameOverlap` for a counterexample where unique
// names are important.
auto name = std::make_unique<String>(
this->uniqueNameForInlineVar(String(old->fName), symbolTableForStatement));
const String* namePtr = symbolTableForStatement->takeOwnershipOfString(std::move(name));
const Type* typePtr = copy_if_needed(&old->type(), *symbolTableForStatement);
const Variable* clone = symbolTableForStatement->takeOwnershipOfSymbol(
@ -551,25 +575,8 @@ Inliner::InlinedCall Inliner::inlineCall(FunctionCall* call,
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
// a splitter reads nicely enough that it's worth putting in this special case.
const char* splitter = baseName.startsWith("_") ? "_X" : "_";
// Append a unique numeric prefix to avoid name overlap. Check the symbol table to make sure
// we're not reusing an existing name. (Note that within a single compilation pass, this
// check isn't fully comprehensive, as code isn't always generated in top-to-bottom order.)
String uniqueName;
for (;;) {
uniqueName = String::printf("_%d%s%s", fInlineVarCounter++, splitter, baseName.c_str());
StringFragment frag{uniqueName.data(), uniqueName.length()};
if ((*symbolTableForCall)[frag] == nullptr) {
break;
}
}
// Add our new variable's name to the symbol table.
// Provide our new variable with a unique name, and add it to our symbol table.
String uniqueName = this->uniqueNameForInlineVar(baseName, symbolTableForCall);
const String* namePtr = symbolTableForCall->takeOwnershipOfString(
std::make_unique<String>(std::move(uniqueName)));
StringFragment nameFrag{namePtr->c_str(), namePtr->length()};

View File

@ -55,6 +55,8 @@ public:
private:
using VariableRewriteMap = std::unordered_map<const Variable*, const Variable*>;
String uniqueNameForInlineVar(const String& baseName, SymbolTable* symbolTable);
std::unique_ptr<Expression> inlineExpression(int offset,
VariableRewriteMap* varMap,
const Expression& expression);

View File

@ -725,13 +725,13 @@ uniform vec4 color;
void main() {
vec4 _0_switchy;
{
vec4 result;
vec4 _1_result;
switch (int(color.x)) {
case 0:
result = color.yyyy;
_1_result = color.yyyy;
}
result = color.zzzz;
_0_switchy = result;
_1_result = color.zzzz;
_0_switchy = _1_result;
}
sk_FragColor = _0_switchy;
@ -793,16 +793,16 @@ uniform vec4 color;
void main() {
vec4 _0_switchy;
{
vec4 result;
vec4 _1_result;
switch (int(color.x)) {
case 1:
result = color.yyyy;
_1_result = color.yyyy;
break;
default:
result = color.zzzz;
_1_result = color.zzzz;
break;
}
_0_switchy = result;
_0_switchy = _1_result;
}
sk_FragColor = _0_switchy;
@ -834,12 +834,12 @@ uniform vec4 color;
void main() {
vec4 _0_loopy;
{
vec4 pix;
for (int x = 0;x < 5; ++x) {
if (x == int(color.w)) pix = color.yyyy;
vec4 _1_pix;
for (int _2_x = 0;_2_x < 5; ++_2_x) {
if (_2_x == int(color.w)) _1_pix = color.yyyy;
}
pix = color.zzzz;
_0_loopy = pix;
_1_pix = color.zzzz;
_0_loopy = _1_pix;
}
sk_FragColor = _0_loopy;
@ -873,88 +873,88 @@ DEF_TEST(SkSLFPInlinerManglesOverlappingNames, r) {
/*expectedGLSL=*/R"__GLSL__(#version 400
uniform vec4 color;
vec4 main() {
float _2_fma;
float _3_a = color.x;
float _4_b = color.y;
float _5_c = color.z;
float _3_fma;
float _4_a = color.x;
float _5_b = color.y;
float _6_c = color.z;
{
float _0_mul;
float _7_0_mul;
{
_0_mul = _3_a * _4_b;
_7_0_mul = _4_a * _5_b;
}
float _1_add;
float _8_1_add;
{
float c = _0_mul + _5_c;
_1_add = c;
float _9_2_c = _7_0_mul + _6_c;
_8_1_add = _9_2_c;
}
_2_fma = _1_add;
_3_fma = _8_1_add;
}
float a = _2_fma;
float _6_fma;
float _7_a = color.y;
float _8_b = color.z;
float _9_c = color.w;
{
float _0_mul;
{
_0_mul = _7_a * _8_b;
}
float _1_add;
{
float c = _0_mul + _9_c;
_1_add = c;
}
_6_fma = _1_add;
}
float b = _6_fma;
float a = _3_fma;
float _10_fma;
float _11_a = color.z;
float _12_b = color.w;
float _13_c = color.x;
float _11_a = color.y;
float _12_b = color.z;
float _13_c = color.w;
{
float _0_mul;
float _14_0_mul;
{
_0_mul = _11_a * _12_b;
_14_0_mul = _11_a * _12_b;
}
float _1_add;
float _15_1_add;
{
float c = _0_mul + _13_c;
_1_add = c;
float _16_2_c = _14_0_mul + _13_c;
_15_1_add = _16_2_c;
}
_10_fma = _1_add;
_10_fma = _15_1_add;
}
float c = _10_fma;
float b = _10_fma;
float _14_mul;
float _17_fma;
float _18_a = color.z;
float _19_b = color.w;
float _20_c = color.x;
{
_14_mul = c * c;
float _21_0_mul;
{
_21_0_mul = _18_a * _19_b;
}
float _22_1_add;
{
float _23_2_c = _21_0_mul + _20_c;
_22_1_add = _23_2_c;
}
_17_fma = _22_1_add;
}
float _15_mul;
float c = _17_fma;
float _24_mul;
{
_15_mul = b * c;
_24_mul = c * c;
}
float _16_mul;
float _25_mul;
{
_16_mul = a * _15_mul;
_25_mul = b * c;
}
return vec4(a, b, _14_mul, _16_mul);
float _26_mul;
{
_26_mul = a * _25_mul;
}
return vec4(a, b, _24_mul, _26_mul);
}
)__GLSL__");
@ -1108,8 +1108,8 @@ void main() {
{
{
if (color.x > 0.0) {
vec4 d = color * 0.5;
_2_branchyAndBlocky = d.xxxx;
vec4 _3_d = color * 0.5;
_2_branchyAndBlocky = _3_d.xxxx;
} else {
{
{

View File

@ -5,17 +5,17 @@ out mediump vec4 sk_FragColor;
void main() {
highp float x = 10.0;
{
highp float y[2], z;
y[0] = 10.0;
y[1] = 20.0;
highp float _0_foo;
highp float _1_y[2], _2_z;
_1_y[0] = 10.0;
_1_y[1] = 20.0;
highp float _3_0_foo;
{
_0_foo = y[0] * y[1];
_3_0_foo = _1_y[0] * _1_y[1];
}
z = _0_foo;
_2_z = _3_0_foo;
x = z;
x = _2_z;
}

View File

@ -3,19 +3,19 @@ precision mediump float;
precision mediump sampler2D;
in mediump vec2 x;
mediump vec4 main() {
mediump vec2 _1_InlineA;
mediump vec2 _2_InlineA;
{
mediump vec2 reusedName = x + vec2(1.0, 2.0);
mediump vec2 _0_InlineB;
mediump vec2 _3_reusedName = x + vec2(1.0, 2.0);
mediump vec2 _4_0_InlineB;
{
mediump vec2 reusedName = reusedName + vec2(3.0, 4.0);
_0_InlineB = reusedName;
mediump vec2 _5_1_reusedName = _3_reusedName + vec2(3.0, 4.0);
_4_0_InlineB = _5_1_reusedName;
}
_1_InlineA = _0_InlineB;
_2_InlineA = _4_0_InlineB;
}
return _1_InlineA.xyxy;
return _2_InlineA.xyxy;
}