Hash :
fe8c0390
Author :
Date :
2024-09-25T19:00:34
WGSL: Run SeparateCompoundStructDeclarations to name structs Borrow SeparateCompoundStructDeclarations from the Metal backend to separate struct definitions and name nameless structs. Refactor id generation into a callback. Bug: angleproject:42267100 Change-Id: I8ed6f13113a5d5e450d30ce187ce1df52e572000 Reviewed-on: https://chromium-review.googlesource.com/c/angle/angle/+/5889089 Commit-Queue: Geoff Lang <geofflang@chromium.org> Reviewed-by: Matthew Denton <mpdenton@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 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113
//
// Copyright 2020 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/SeparateCompoundStructDeclarations.h"
#include "compiler/translator/tree_ops/SeparateDeclarations.h"
#include "compiler/translator/tree_util/IntermTraverse.h"
#include "compiler/translator/tree_util/ReplaceVariable.h"
#include "compiler/translator/util.h"
#include <algorithm>
namespace sh
{
namespace
{
class Separator : public TIntermTraverser
{
public:
Separator(TSymbolTable &symbolTable, StructNameGenerator nameGenerator)
: TIntermTraverser(false, false, true, &symbolTable), mNameGenerator(nameGenerator)
{}
bool visitDeclaration(Visit, TIntermDeclaration *declNode) override
{
ASSERT(declNode->getChildCount() == 1);
Declaration declaration = ViewDeclaration(*declNode);
const TVariable &var = declaration.symbol.variable();
const TType &type = var.getType();
const SymbolType symbolType = var.symbolType();
if (type.isStructSpecifier() && symbolType != SymbolType::Empty)
{
const TStructure *structure = type.getStruct();
if (structure->symbolType() == SymbolType::Empty)
{
// Name unnamed inline structs.
structure = new TStructure(mSymbolTable, mNameGenerator(), &structure->fields(),
SymbolType::AngleInternal);
}
TVariable *structVar = new TVariable(mSymbolTable, kEmptyImmutableString,
new TType(structure, true), SymbolType::Empty);
TType *instanceType = new TType(structure, false);
if (type.isArray())
{
instanceType->makeArrays(type.getArraySizes());
}
instanceType->setQualifier(type.getQualifier());
auto *instanceVar =
new TVariable(mSymbolTable, var.name(), instanceType, symbolType, var.extensions());
TIntermSequence replacements;
replacements.push_back(new TIntermDeclaration({structVar}));
TIntermSymbol *instanceSymbol = new TIntermSymbol(instanceVar);
TIntermDeclaration *instanceDecl = new TIntermDeclaration;
if (declaration.initExpr)
{
instanceDecl->appendDeclarator(new TIntermBinary(
TOperator::EOpInitialize, instanceSymbol, declaration.initExpr));
}
else
{
instanceDecl->appendDeclarator(instanceSymbol);
}
replacements.push_back(instanceDecl);
mVariableMap[&declaration.symbol.variable()] = instanceSymbol;
ASSERT(getParentNode() != nullptr);
ASSERT(getParentNode()->getAsBlock() != nullptr);
mMultiReplacements.push_back(NodeReplaceWithMultipleEntry(
getParentNode()->getAsBlock(), declNode, std::move(replacements)));
}
return false;
}
void visitSymbol(TIntermSymbol *symbol) override
{
const TVariable *variable = &symbol->variable();
if (mVariableMap.count(variable) > 0)
{
queueAccessChainReplacement(mVariableMap[variable]->deepCopy());
}
}
StructNameGenerator mNameGenerator;
VariableReplacementMap mVariableMap;
};
} // anonymous namespace
bool SeparateCompoundStructDeclarations(TCompiler &compiler,
StructNameGenerator nameGenerator,
TIntermBlock &root)
{
Separator separator(compiler.getSymbolTable(), nameGenerator);
root.traverse(&separator);
if (!separator.updateTree(&compiler, &root))
{
return false;
}
if (!SeparateDeclarations(compiler, root))
{
return false;
}
return true;
}
} // namespace sh