• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 //
2 // Copyright 2017 The ANGLE Project Authors. All rights reserved.
3 // Use of this source code is governed by a BSD-style license that can be
4 // found in the LICENSE file.
5 //
6 
7 #include "compiler/translator/HashNames.h"
8 
9 #include "compiler/translator/ImmutableString.h"
10 #include "compiler/translator/ImmutableStringBuilder.h"
11 #include "compiler/translator/IntermNode.h"
12 #include "compiler/translator/Symbol.h"
13 
14 namespace sh
15 {
16 
17 namespace
18 {
19 constexpr const ImmutableString kHashedNamePrefix("webgl_");
20 
HashName(const ImmutableString & name,ShHashFunction64 hashFunction)21 ImmutableString HashName(const ImmutableString &name, ShHashFunction64 hashFunction)
22 {
23     ASSERT(!name.empty());
24     ASSERT(hashFunction);
25     khronos_uint64_t number = (*hashFunction)(name.data(), name.length());
26 
27     // Build the hashed name in place.
28     static const unsigned int kHexStrMaxLength = sizeof(number) * 2;
29     static const size_t kHashedNameMaxLength   = kHashedNamePrefix.length() + kHexStrMaxLength;
30 
31     ImmutableStringBuilder hashedName(kHashedNameMaxLength);
32     hashedName << kHashedNamePrefix;
33 
34     hashedName.appendHex(number);
35 
36     return hashedName;
37 }
38 
AddToNameMapIfNotMapped(const ImmutableString & name,const ImmutableString & hashedName,NameMap * nameMap)39 void AddToNameMapIfNotMapped(const ImmutableString &name,
40                              const ImmutableString &hashedName,
41                              NameMap *nameMap)
42 {
43     if (nameMap)
44     {
45         NameMap::const_iterator it = nameMap->find(name.data());
46         if (it != nameMap->end())
47         {
48             // (How bout returning?)
49             return;
50         }
51         (*nameMap)[name.data()] = hashedName.data();
52     }
53 }
54 
55 }  // anonymous namespace
56 
HashName(const ImmutableString & name,ShHashFunction64 hashFunction,NameMap * nameMap)57 ImmutableString HashName(const ImmutableString &name,
58                          ShHashFunction64 hashFunction,
59                          NameMap *nameMap)
60 {
61     const ImmutableString kUnhashedNamePrefix(kUserDefinedNamePrefix);
62 
63     if (hashFunction == nullptr)
64     {
65         if (name.length() + kUnhashedNamePrefix.length() > kESSLMaxIdentifierLength)
66         {
67             // If the identifier length is already close to the limit, we can't prefix it. This is
68             // not a problem since there are no builtins or ANGLE's internal variables that would
69             // have as long names and could conflict.
70             return name;
71         }
72         if (name == "gl_ClipDistance")
73         {
74             // NOTE(hqle): When gl_ClipDistance is re-declared, it will become an UserDefined
75             // symbol. Normally, UserDefined symbols will have "_u" prefix added to their names by
76             // ANGLE. However, gl_ClipDistance is an exception. If we add "_u" to its name, the
77             // backend won't be able to handle it properly. So for gl_ClipDistance, we won't add
78             // "_u" prefix, instead we return it original name.
79             //
80             // The other way is treating gl_ClipDistance as an AngleInternal symbol when a
81             // re-declaration occurs. AngleInternal symbols will have their name intact. However,
82             // the issue is that the current code put a lot of restrictions on AngleInternal
83             // symbols. For examples:
84             //  - CollectVariables.cpp will not consider AngleInternal as varying output variales.
85             //  - SymbolTable.cpp will throw an exception if AngleInternal symbols are declared by
86             //  users. In this case, it would be gl_ClipDistance. This is because
87             //  TSymbolTable::declare() only accepts an UserDefined symbol.
88             //  - And potentially many other places that have some assumptions that haven't been
89             //  discovered yet.
90             //
91             // If re-declared gl_ClipDistance was to be an AngleInternal symbol, a special "if (name
92             // == "gl_ClipDistance")" handling would have to be put into all the above mentioned
93             // cases. TParseContext::declareVariable() function would also have to be modified in
94             // order to assign AngleInternal symbol type to the re-declared gl_ClipDistance
95             // variable.
96             // Compare to only this place has to be handled if re-declared gl_ClipDistance is
97             // treated as an UserDefined symbol.
98             //
99             return name;
100         }
101 
102         static const char* coreBuiltinConflictNames[] = {
103             // Keywords in GLSL ES 1.00 but not in GLSL ES 3.00
104             "texture",
105             "textureProj",
106             "textureLod",
107             "textureProjLod",
108             "textureGrad",
109             "textureProjGrad",
110             // Keywords in GLSL ES 3.00 but not in GLSL ES 1.00
111             "resource",
112             "patch",
113             "sample",
114             "subroutine",
115             "common",
116             "partition",
117             "active",
118 
119             "filter",
120             "image1D",
121             "iimage1D",
122             "uimage1D",
123             "image1DArray",
124             "iimage1DArray",
125             "uimage1DArray",
126             "image1DShadow",
127             "image2DShadow",
128             "image1DArrayShadow",
129             "image2DArrayShadow",
130             "imageBuffer",
131             "iimageBuffer",
132             "uimageBuffer",
133 
134             "sampler1DArray",
135             "sampler1DArrayShadow",
136             "isampler1D",
137             "isampler1DArray",
138             "usampler1D",
139             "usampler1DArray",
140             "isampler2DRect",
141             "usampler2DRect",
142             "samplerBuffer",
143             "isamplerBuffer",
144             "usamplerBuffer",
145         };
146 
147         // TODO(lfy): hack that removes the prefixes until emulator can deal with it properly
148 
149         for (uint32_t i = 0; i < sizeof(coreBuiltinConflictNames) / sizeof(const char*); ++i) {
150             if (name == coreBuiltinConflictNames[i]) {
151                 ImmutableStringBuilder prefixedName(kUnhashedNamePrefix.length() + name.length());
152                 prefixedName << kUnhashedNamePrefix << name;
153                 ImmutableString res = prefixedName;
154                 AddToNameMapIfNotMapped(name, res, nameMap);
155                 return res;
156             }
157         }
158 
159         return name;
160     }
161 
162     // Has a hash function
163     ImmutableString hashedName = HashName(name, hashFunction);
164     AddToNameMapIfNotMapped(name, hashedName, nameMap);
165     return hashedName;
166 }
167 
HashName(const TSymbol * symbol,ShHashFunction64 hashFunction,NameMap * nameMap)168 ImmutableString HashName(const TSymbol *symbol, ShHashFunction64 hashFunction, NameMap *nameMap)
169 {
170     if (symbol->symbolType() == SymbolType::Empty)
171     {
172         return kEmptyImmutableString;
173     }
174     if (symbol->symbolType() == SymbolType::AngleInternal ||
175         symbol->symbolType() == SymbolType::BuiltIn)
176     {
177         return symbol->name();
178     }
179     return HashName(symbol->name(), hashFunction, nameMap);
180 }
181 
182 }  // namespace sh
183