1cb93a386Sopenharmony_ci/* 2cb93a386Sopenharmony_ci * Copyright 2021 Google LLC. 3cb93a386Sopenharmony_ci * 4cb93a386Sopenharmony_ci * Use of this source code is governed by a BSD-style license that can be 5cb93a386Sopenharmony_ci * found in the LICENSE file. 6cb93a386Sopenharmony_ci */ 7cb93a386Sopenharmony_ci 8cb93a386Sopenharmony_ci#include "src/sksl/SkSLMangler.h" 9cb93a386Sopenharmony_ci#include "src/sksl/ir/SkSLSymbolTable.h" 10cb93a386Sopenharmony_ci 11cb93a386Sopenharmony_cinamespace SkSL { 12cb93a386Sopenharmony_ci 13cb93a386Sopenharmony_ciString Mangler::uniqueName(skstd::string_view baseName, SymbolTable* symbolTable) { 14cb93a386Sopenharmony_ci SkASSERT(symbolTable); 15cb93a386Sopenharmony_ci // The inliner runs more than once, so the base name might already have been mangled and have a 16cb93a386Sopenharmony_ci // prefix like "_123_x". Let's strip that prefix off to make the generated code easier to read. 17cb93a386Sopenharmony_ci if (baseName.starts_with("_")) { 18cb93a386Sopenharmony_ci // Determine if we have a string of digits. 19cb93a386Sopenharmony_ci int offset = 1; 20cb93a386Sopenharmony_ci while (isdigit(baseName[offset])) { 21cb93a386Sopenharmony_ci ++offset; 22cb93a386Sopenharmony_ci } 23cb93a386Sopenharmony_ci // If we found digits, another underscore, and anything else, that's the mangler prefix. 24cb93a386Sopenharmony_ci // Strip it off. 25cb93a386Sopenharmony_ci if (offset > 1 && baseName[offset] == '_' && baseName[offset + 1] != '\0') { 26cb93a386Sopenharmony_ci baseName.remove_prefix(offset + 1); 27cb93a386Sopenharmony_ci } else { 28cb93a386Sopenharmony_ci // This name doesn't contain a mangler prefix, but it does start with an underscore. 29cb93a386Sopenharmony_ci // OpenGL disallows two consecutive underscores anywhere in the string, and we'll be 30cb93a386Sopenharmony_ci // adding one as part of the mangler prefix, so strip the leading underscore. 31cb93a386Sopenharmony_ci baseName.remove_prefix(1); 32cb93a386Sopenharmony_ci } 33cb93a386Sopenharmony_ci } 34cb93a386Sopenharmony_ci 35cb93a386Sopenharmony_ci // Append a unique numeric prefix to avoid name overlap. Check the symbol table to make sure 36cb93a386Sopenharmony_ci // we're not reusing an existing name. (Note that within a single compilation pass, this check 37cb93a386Sopenharmony_ci // isn't fully comprehensive, as code isn't always generated in top-to-bottom order.) 38cb93a386Sopenharmony_ci String uniqueName; 39cb93a386Sopenharmony_ci for (;;) { 40cb93a386Sopenharmony_ci uniqueName = String::printf("_%d_%.*s", fCounter++, (int)baseName.size(), baseName.data()); 41cb93a386Sopenharmony_ci if ((*symbolTable)[uniqueName] == nullptr) { 42cb93a386Sopenharmony_ci break; 43cb93a386Sopenharmony_ci } 44cb93a386Sopenharmony_ci } 45cb93a386Sopenharmony_ci 46cb93a386Sopenharmony_ci return uniqueName; 47cb93a386Sopenharmony_ci} 48cb93a386Sopenharmony_ci 49cb93a386Sopenharmony_ci} // namespace SkSL 50