michael@0: // michael@0: // Copyright (c) 2002-2012 The ANGLE Project Authors. All rights reserved. michael@0: // Use of this source code is governed by a BSD-style license that can be michael@0: // found in the LICENSE file. michael@0: // michael@0: michael@0: #include "compiler/MapLongVariableNames.h" michael@0: michael@0: #include "third_party/murmurhash/MurmurHash3.h" michael@0: michael@0: namespace { michael@0: michael@0: TString mapLongName(size_t id, const TString& name, bool isGlobal) michael@0: { michael@0: ASSERT(name.size() > MAX_SHORTENED_IDENTIFIER_SIZE); michael@0: TStringStream stream; michael@0: michael@0: uint64_t hash[2] = {0, 0}; michael@0: MurmurHash3_x64_128(name.data(), name.length(), 0, hash); michael@0: michael@0: // We want to avoid producing a string with a double underscore, michael@0: // which would be an illegal GLSL identifier. We can assume that the michael@0: // original identifier doesn't have a double underscore, otherwise michael@0: // it's illegal anyway. michael@0: stream << (name[0] == '_' ? "webgl" : "webgl_") michael@0: << name.substr(0, 9) michael@0: << (name[8] == '_' ? "" : "_") michael@0: << std::hex michael@0: << hash[0]; michael@0: ASSERT(stream.str().length() <= MAX_SHORTENED_IDENTIFIER_SIZE); michael@0: ASSERT(stream.str().length() >= MAX_SHORTENED_IDENTIFIER_SIZE - 2); michael@0: return stream.str(); michael@0: } michael@0: michael@0: LongNameMap* gLongNameMapInstance = NULL; michael@0: michael@0: } // anonymous namespace michael@0: michael@0: LongNameMap::LongNameMap() michael@0: : refCount(0) michael@0: { michael@0: } michael@0: michael@0: LongNameMap::~LongNameMap() michael@0: { michael@0: } michael@0: michael@0: // static michael@0: LongNameMap* LongNameMap::GetInstance() michael@0: { michael@0: if (gLongNameMapInstance == NULL) michael@0: gLongNameMapInstance = new LongNameMap; michael@0: gLongNameMapInstance->refCount++; michael@0: return gLongNameMapInstance; michael@0: } michael@0: michael@0: void LongNameMap::Release() michael@0: { michael@0: ASSERT(gLongNameMapInstance == this); michael@0: ASSERT(refCount > 0); michael@0: refCount--; michael@0: if (refCount == 0) { michael@0: delete gLongNameMapInstance; michael@0: gLongNameMapInstance = NULL; michael@0: } michael@0: } michael@0: michael@0: const char* LongNameMap::Find(const char* originalName) const michael@0: { michael@0: std::map::const_iterator it = mLongNameMap.find( michael@0: originalName); michael@0: if (it != mLongNameMap.end()) michael@0: return (*it).second.c_str(); michael@0: return NULL; michael@0: } michael@0: michael@0: void LongNameMap::Insert(const char* originalName, const char* mappedName) michael@0: { michael@0: mLongNameMap.insert(std::map::value_type( michael@0: originalName, mappedName)); michael@0: } michael@0: michael@0: size_t LongNameMap::Size() const michael@0: { michael@0: return mLongNameMap.size(); michael@0: } michael@0: michael@0: MapLongVariableNames::MapLongVariableNames(LongNameMap* globalMap) michael@0: { michael@0: ASSERT(globalMap); michael@0: mGlobalMap = globalMap; michael@0: } michael@0: michael@0: void MapLongVariableNames::visitSymbol(TIntermSymbol* symbol) michael@0: { michael@0: ASSERT(symbol != NULL); michael@0: if (symbol->getSymbol().size() > MAX_SHORTENED_IDENTIFIER_SIZE) { michael@0: switch (symbol->getQualifier()) { michael@0: case EvqVaryingIn: michael@0: case EvqVaryingOut: michael@0: case EvqInvariantVaryingIn: michael@0: case EvqInvariantVaryingOut: michael@0: case EvqUniform: michael@0: symbol->setSymbol( michael@0: mapGlobalLongName(symbol->getSymbol())); michael@0: break; michael@0: default: michael@0: symbol->setSymbol( michael@0: mapLongName(symbol->getId(), symbol->getSymbol(), false)); michael@0: break; michael@0: }; michael@0: } michael@0: } michael@0: michael@0: bool MapLongVariableNames::visitLoop(Visit, TIntermLoop* node) michael@0: { michael@0: if (node->getInit()) michael@0: node->getInit()->traverse(this); michael@0: return true; michael@0: } michael@0: michael@0: TString MapLongVariableNames::mapGlobalLongName(const TString& name) michael@0: { michael@0: ASSERT(mGlobalMap); michael@0: const char* mappedName = mGlobalMap->Find(name.c_str()); michael@0: if (mappedName != NULL) michael@0: return mappedName; michael@0: size_t id = mGlobalMap->Size(); michael@0: TString rt = mapLongName(id, name, true); michael@0: mGlobalMap->Insert(name.c_str(), rt.c_str()); michael@0: return rt; michael@0: }