Hash :
197beb4d
Author :
Date :
2024-02-13T15:47:32
Metal: Crash if for loop body is optimized away Loops might have their bodies optimized away. For case like `for(;;) if(false);` the constant pruning happens at parse phase. The else branch (e.e. no else branch, nullptr) would be selected as the body. Some code treated the body as optional, some code treated it as required. Define it as required, and remove all conditional code related to the loop body. Bug: angleproject:8532 Change-Id: Ic35f1bf78e63ceb2cee7b96ba99e788efc282e6f Reviewed-on: https://chromium-review.googlesource.com/c/angle/angle/+/5291554 Auto-Submit: Kimmo Kinnunen <kkinnunen@apple.com> Commit-Queue: Kimmo Kinnunen <kkinnunen@apple.com> Reviewed-by: Kenneth Russell <kbr@chromium.org>
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
//
// Copyright 2022 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.
//
#include "compiler/translator/tree_ops/hlsl/AggregateAssignArraysInSSBOs.h"
#include "compiler/translator/StaticType.h"
#include "compiler/translator/Symbol.h"
#include "compiler/translator/tree_util/IntermNode_util.h"
#include "compiler/translator/tree_util/IntermTraverse.h"
#include "compiler/translator/util.h"
namespace sh
{
namespace
{
class AggregateAssignArraysInSSBOsTraverser : public TIntermTraverser
{
public:
AggregateAssignArraysInSSBOsTraverser(TSymbolTable *symbolTable)
: TIntermTraverser(true, false, false, symbolTable)
{}
protected:
bool visitBinary(Visit visit, TIntermBinary *node) override
{
// Replace all aggregate assignments to arrays in SSBOs with element-by-element assignments.
// TODO(anglebug.com/7363): this implementation only works for the simple case (assignment
// statement), not more complex cases such as assignment-as-expression or functions with
// side effects in the RHS.
if (node->getOp() != EOpAssign)
{
return true;
}
else if (!node->getLeft()->getType().isArray())
{
return true;
}
else if (!IsInShaderStorageBlock(node->getLeft()))
{
return true;
}
const TType *mediumpIndexType = StaticType::Get<EbtInt, EbpMedium, EvqTemporary, 1, 1>();
auto *indexVariable = CreateTempVariable(mSymbolTable, mediumpIndexType);
auto *indexInit =
CreateTempInitDeclarationNode(indexVariable, CreateZeroNode(indexVariable->getType()));
auto *arraySizeNode = CreateIndexNode(node->getOutermostArraySize());
auto *indexSymbolNode = CreateTempSymbolNode(indexVariable);
auto *cond = new TIntermBinary(EOpLessThan, indexSymbolNode->deepCopy(), arraySizeNode);
auto *indexIncrement =
new TIntermUnary(EOpPreIncrement, indexSymbolNode->deepCopy(), nullptr);
auto *forLoopBody = new TIntermBlock();
auto *indexedLeft =
new TIntermBinary(EOpIndexDirect, node->getLeft(), indexSymbolNode->deepCopy());
auto *indexedRight =
new TIntermBinary(EOpIndexDirect, node->getRight(), indexSymbolNode->deepCopy());
auto *assign = new TIntermBinary(TOperator::EOpAssign, indexedLeft, indexedRight);
forLoopBody->appendStatement(assign);
auto *forLoop = new TIntermLoop(ELoopFor, indexInit, cond, indexIncrement, forLoopBody);
queueReplacement(forLoop, OriginalNode::IS_DROPPED);
return false;
}
};
} // namespace
bool AggregateAssignArraysInSSBOs(TCompiler *compiler,
TIntermBlock *root,
TSymbolTable *symbolTable)
{
AggregateAssignArraysInSSBOsTraverser traverser(symbolTable);
root->traverse(&traverser);
return traverser.updateTree(compiler, root);
}
} // namespace sh