chromium/third_party/angle/src/compiler/translator/tree_util/FindPreciseNodes.cpp

//
// Copyright 2021 The ANGLE Project Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
//
// FindPreciseNodes.cpp: Propagates |precise| to AST nodes.
//
// The high level algorithm is as follows.  For every node that "assigns" to a precise object,
// subobject (a precise struct whose field is being assigned) or superobject (a struct with a
// precise field), two things happen:
//
// - The operation is marked precise if it's an arithmetic operation
// - The right hand side of the assignment is made precise.  If only a subobject is precise, only
//   the corresponding subobject of the right hand side is made precise.
//

#include "compiler/translator/tree_util/FindPreciseNodes.h"

#include "common/hash_containers.h"
#include "common/hash_utils.h"
#include "compiler/translator/Compiler.h"
#include "compiler/translator/IntermNode.h"
#include "compiler/translator/Symbol.h"
#include "compiler/translator/tree_util/IntermTraverse.h"

namespace sh
{

namespace
{

// An access chain applied to a variable.  The |precise|-ness of a node does not change when
// indexing arrays, selecting matrix columns or swizzle vectors.  This access chain thus only
// includes block field selections.  The access chain is used to identify the part of an object
// that is or should be |precise|.  If both a.b.c and a.b are precise, only a.b is every considered.
class AccessChain
{};

bool IsIndexOp(TOperator op)
{}

const TVariable *AccessChain::build(TIntermTyped *lvalue)
{}

void AccessChain::pop_front(size_t n)
{}

bool AccessChain::removePrefix(const AccessChain &other)
{}

AccessChain GetAssignmentAccessChain(TIntermOperator *node)
{}

template <typename Traverser>
void TraverseIndexNodesOnly(TIntermNode *node, Traverser *traverser)
{}

// An object, which could be a sub-object of a variable.
struct ObjectAndAccessChain
{};

bool operator==(const ObjectAndAccessChain &a, const ObjectAndAccessChain &b)
{}

struct ObjectAndAccessChainHash
{};

// A map from variables to AST nodes that modify them (i.e. nodes where IsAssignment(op)).
VariableToAssignmentNodeMap;
// A set of |return| nodes from functions with a |precise| return value.
PreciseReturnNodes;
// A set of precise objects that need processing, or have been processed.
PreciseObjectSet;

struct ASTInfo
{};

int GetObjectPreciseSubChainLength(const ObjectAndAccessChain &object)
{}

void AddPreciseObject(ASTInfo *info, const ObjectAndAccessChain &object)
{}

void AddPreciseSubObjects(ASTInfo *info, const ObjectAndAccessChain &object);

void AddObjectIfPrecise(ASTInfo *info, const ObjectAndAccessChain &object)
{}

void AddPreciseSubObjects(ASTInfo *info, const ObjectAndAccessChain &object)
{}

bool IsArithmeticOp(TOperator op)
{}

// A traverser that gathers the following information, used to kick off processing:
//
// - For each variable, the AST nodes that modify it.
// - The set of |precise| return AST node.
// - The set of |precise| access chains assigned to.
//
class InfoGatherTraverser : public TIntermTraverser
{};

// A traverser that, given an access chain, traverses an expression and marks parts of it |precise|.
// For example, in the expression |Struct1(a, Struct2(b, c), d)|:
//
// - Given access chain [1], both |b| and |c| are marked precise.
// - Given access chain [1, 0], only |b| is marked precise.
//
// When access chain is empty, arithmetic nodes are marked |precise| and any access chains found in
// their children is recursively added for processing.
//
// The access chain given to the traverser is derived from the left hand side of an assignment,
// while the traverser is run on the right hand side.
class PropagatePreciseTraverser : public TIntermTraverser
{};
}  // anonymous namespace

void FindPreciseNodes(TCompiler *compiler, TIntermBlock *root)
{}

}  // namespace sh