tor-browser

The Tor Browser
git clone https://git.dasho.dev/tor-browser.git
Log | Files | Refs | README | LICENSE

BuiltInFunctionEmulator.cpp (4352B)


      1 //
      2 // Copyright 2002 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/BuiltInFunctionEmulator.h"
      8 #include "angle_gl.h"
      9 #include "compiler/translator/Symbol.h"
     10 #include "compiler/translator/tree_util/IntermTraverse.h"
     11 
     12 namespace sh
     13 {
     14 
     15 class BuiltInFunctionEmulator::BuiltInFunctionEmulationMarker : public TIntermTraverser
     16 {
     17  public:
     18    BuiltInFunctionEmulationMarker(BuiltInFunctionEmulator &emulator)
     19        : TIntermTraverser(true, false, false), mEmulator(emulator)
     20    {}
     21 
     22    bool visitUnary(Visit visit, TIntermUnary *node) override
     23    {
     24        if (node->getFunction())
     25        {
     26            bool needToEmulate = mEmulator.setFunctionCalled(node->getFunction());
     27            if (needToEmulate)
     28                node->setUseEmulatedFunction();
     29        }
     30        return true;
     31    }
     32 
     33    bool visitAggregate(Visit visit, TIntermAggregate *node) override
     34    {
     35        // Here we handle all the math built-in functions, not just the ones that are currently
     36        // identified as problematic.
     37        if (!BuiltInGroup::IsMath(node->getOp()))
     38        {
     39            return true;
     40        }
     41        bool needToEmulate = mEmulator.setFunctionCalled(node->getFunction());
     42        if (needToEmulate)
     43            node->setUseEmulatedFunction();
     44        return true;
     45    }
     46 
     47  private:
     48    BuiltInFunctionEmulator &mEmulator;
     49 };
     50 
     51 BuiltInFunctionEmulator::BuiltInFunctionEmulator() {}
     52 
     53 void BuiltInFunctionEmulator::addEmulatedFunction(const TSymbolUniqueId &uniqueId,
     54                                                  const char *emulatedFunctionDefinition)
     55 {
     56    mEmulatedFunctions[uniqueId.get()] = std::string(emulatedFunctionDefinition);
     57 }
     58 
     59 void BuiltInFunctionEmulator::addEmulatedFunctionWithDependency(
     60    const TSymbolUniqueId &dependency,
     61    const TSymbolUniqueId &uniqueId,
     62    const char *emulatedFunctionDefinition)
     63 {
     64    mEmulatedFunctions[uniqueId.get()]    = std::string(emulatedFunctionDefinition);
     65    mFunctionDependencies[uniqueId.get()] = dependency.get();
     66 }
     67 
     68 bool BuiltInFunctionEmulator::isOutputEmpty() const
     69 {
     70    return (mFunctions.size() == 0);
     71 }
     72 
     73 void BuiltInFunctionEmulator::outputEmulatedFunctions(TInfoSinkBase &out) const
     74 {
     75    for (const auto &function : mFunctions)
     76    {
     77        const char *body = findEmulatedFunction(function);
     78        ASSERT(body);
     79        out << body;
     80        out << "\n\n";
     81    }
     82 }
     83 
     84 const char *BuiltInFunctionEmulator::findEmulatedFunction(int uniqueId) const
     85 {
     86    for (const auto &queryFunction : mQueryFunctions)
     87    {
     88        const char *result = queryFunction(uniqueId);
     89        if (result)
     90        {
     91            return result;
     92        }
     93    }
     94 
     95    const auto &result = mEmulatedFunctions.find(uniqueId);
     96    if (result != mEmulatedFunctions.end())
     97    {
     98        return result->second.c_str();
     99    }
    100 
    101    return nullptr;
    102 }
    103 
    104 bool BuiltInFunctionEmulator::setFunctionCalled(const TFunction *function)
    105 {
    106    ASSERT(function != nullptr);
    107    return setFunctionCalled(function->uniqueId().get());
    108 }
    109 
    110 bool BuiltInFunctionEmulator::setFunctionCalled(int uniqueId)
    111 {
    112    if (!findEmulatedFunction(uniqueId))
    113    {
    114        return false;
    115    }
    116 
    117    for (size_t i = 0; i < mFunctions.size(); ++i)
    118    {
    119        if (mFunctions[i] == uniqueId)
    120            return true;
    121    }
    122    // If the function depends on another, mark the dependency as called.
    123    auto dependency = mFunctionDependencies.find(uniqueId);
    124    if (dependency != mFunctionDependencies.end())
    125    {
    126        setFunctionCalled((*dependency).second);
    127    }
    128    mFunctions.push_back(uniqueId);
    129    return true;
    130 }
    131 
    132 void BuiltInFunctionEmulator::markBuiltInFunctionsForEmulation(TIntermNode *root)
    133 {
    134    ASSERT(root);
    135 
    136    if (mEmulatedFunctions.empty() && mQueryFunctions.empty())
    137        return;
    138 
    139    BuiltInFunctionEmulationMarker marker(*this);
    140    root->traverse(&marker);
    141 }
    142 
    143 void BuiltInFunctionEmulator::cleanup()
    144 {
    145    mFunctions.clear();
    146    mFunctionDependencies.clear();
    147 }
    148 
    149 void BuiltInFunctionEmulator::addFunctionMap(BuiltinQueryFunc queryFunc)
    150 {
    151    mQueryFunctions.push_back(queryFunc);
    152 }
    153 
    154 // static
    155 void BuiltInFunctionEmulator::WriteEmulatedFunctionName(TInfoSinkBase &out, const char *name)
    156 {
    157    ASSERT(name[strlen(name) - 1] != '(');
    158    out << name << "_emu";
    159 }
    160 
    161 }  // namespace sh