1//
2// Copyright (c) 2002-2014 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/RegenerateStructNames.h"
8#include "compiler/translator/compilerdebug.h"
9
10void RegenerateStructNames::visitSymbol(TIntermSymbol *symbol)
11{
12    ASSERT(symbol);
13    TType *type = symbol->getTypePointer();
14    ASSERT(type);
15    TStructure *userType = type->getStruct();
16    if (!userType)
17        return;
18
19    if (mSymbolTable.findBuiltIn(userType->name(), mShaderVersion))
20    {
21        // Built-in struct, do not touch it.
22        return;
23    }
24
25    int uniqueId = userType->uniqueId();
26
27    ASSERT(mScopeDepth > 0);
28    if (mScopeDepth == 1)
29    {
30        // If a struct is defined at global scope, we don't map its name.
31        // This is because at global level, the struct might be used to
32        // declare a uniform, so the same name needs to stay the same for
33        // vertex/fragment shaders. However, our mapping uses internal ID,
34        // which will be different for the same struct in vertex/fragment
35        // shaders.
36        // This is OK because names for any structs defined in other scopes
37        // will begin with "_webgl", which is reserved. So there will be
38        // no conflicts among unmapped struct names from global scope and
39        // mapped struct names from other scopes.
40        // However, we need to keep track of these global structs, so if a
41        // variable is used in a local scope, we don't try to modify the
42        // struct name through that variable.
43        mDeclaredGlobalStructs.insert(uniqueId);
44        return;
45    }
46    if (mDeclaredGlobalStructs.count(uniqueId) > 0)
47        return;
48    // Map {name} to _webgl_struct_{uniqueId}_{name}.
49    const char kPrefix[] = "_webgl_struct_";
50    if (userType->name().find(kPrefix) == 0)
51    {
52        // The name has already been regenerated.
53        return;
54    }
55    std::string id = Str(uniqueId);
56    TString tmp = kPrefix + TString(id.c_str());
57    tmp += "_" + userType->name();
58    userType->setName(tmp);
59}
60
61bool RegenerateStructNames::visitAggregate(Visit, TIntermAggregate *aggregate)
62{
63    ASSERT(aggregate);
64    switch (aggregate->getOp())
65    {
66      case EOpSequence:
67        ++mScopeDepth;
68        {
69            TIntermSequence &sequence = *(aggregate->getSequence());
70            for (size_t ii = 0; ii < sequence.size(); ++ii)
71            {
72                TIntermNode *node = sequence[ii];
73                ASSERT(node != NULL);
74                node->traverse(this);
75            }
76        }
77        --mScopeDepth;
78        return false;
79      default:
80        return true;
81    }
82}
83