summaryrefslogtreecommitdiffstats
path: root/gfx/angle/checkout/src/compiler/translator/tree_ops/d3d/SeparateArrayConstructorStatements.cpp
blob: 170b29acd77181044155ade153f255eca35f31bd (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
//
// Copyright 2018 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.
//
// SeparateArrayConstructorStatements splits statements that are array constructors and drops all of
// their constant arguments. For example, a statement like:
//   int[2](0, i++);
// Will be changed to:
//   i++;

#include "compiler/translator/tree_ops/d3d/SeparateArrayConstructorStatements.h"

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

namespace sh
{

namespace
{

void SplitConstructorArgs(const TIntermSequence &originalArgs, TIntermSequence *argsOut)
{
    for (TIntermNode *arg : originalArgs)
    {
        TIntermTyped *argTyped = arg->getAsTyped();
        if (argTyped->hasSideEffects())
        {
            TIntermAggregate *argAggregate = argTyped->getAsAggregate();
            if (argTyped->isArray() && argAggregate && argAggregate->isConstructor())
            {
                SplitConstructorArgs(*argAggregate->getSequence(), argsOut);
            }
            else
            {
                argsOut->push_back(argTyped);
            }
        }
    }
}

class SeparateArrayConstructorStatementsTraverser : public TIntermTraverser
{
  public:
    SeparateArrayConstructorStatementsTraverser();

    bool visitAggregate(Visit visit, TIntermAggregate *node) override;
};

SeparateArrayConstructorStatementsTraverser::SeparateArrayConstructorStatementsTraverser()
    : TIntermTraverser(true, false, false)
{}

bool SeparateArrayConstructorStatementsTraverser::visitAggregate(Visit visit,
                                                                 TIntermAggregate *node)
{
    TIntermBlock *parentAsBlock = getParentNode()->getAsBlock();
    if (!parentAsBlock)
    {
        return false;
    }
    if (!node->isArray() || !node->isConstructor())
    {
        return false;
    }

    TIntermSequence constructorArgs;
    SplitConstructorArgs(*node->getSequence(), &constructorArgs);
    mMultiReplacements.emplace_back(parentAsBlock, node, std::move(constructorArgs));

    return false;
}

}  // namespace

bool SeparateArrayConstructorStatements(TCompiler *compiler, TIntermBlock *root)
{
    SeparateArrayConstructorStatementsTraverser traverser;
    root->traverse(&traverser);
    return traverser.updateTree(compiler, root);
}

}  // namespace sh