blob: d2440a804a61ef5e97cf2c9e25ef823fa7a89a62 [file] [log] [blame] [edit]
/*
* Copyright (c) 2023 Apple Inc. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
* OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include "config.h"
#include "MangleNames.h"
#include "AST.h"
#include "ASTScopedVisitorInlines.h"
#include "CallGraph.h"
#include "ContextProviderInlines.h"
#include "WGSL.h"
#include "WGSLShaderModule.h"
#include <wtf/HashSet.h>
#include <wtf/text/MakeString.h>
namespace WGSL {
struct MangledName {
enum Kind : uint8_t {
Type,
Local,
Global,
Parameter,
Function,
Field,
};
static constexpr unsigned numberOfKinds = 6;
Kind kind;
uint32_t index;
String originalName;
String toString() const
{
static const auto prefixes = std::to_array<ASCIILiteral>({
"type"_s,
"local"_s,
"global"_s,
"parameter"_s,
"function"_s,
"field"_s,
});
return makeString(prefixes[WTF::enumToUnderlyingType(kind)], String::number(index));
}
};
class NameManglerVisitor : public AST::ScopedVisitor<MangledName> {
using Base = AST::ScopedVisitor<MangledName>;
using Base::visit;
public:
NameManglerVisitor(ShaderModule& shaderModule)
: m_shaderModule(shaderModule)
{
}
void run();
void visit(AST::Function&) override;
void visit(AST::Parameter&) override;
void visit(AST::VariableStatement&) override;
void visit(AST::Structure&) override;
void visit(AST::Variable&) override;
void visit(AST::IdentifierExpression&) override;
void visit(AST::FieldAccessExpression&) override;
private:
using NameMap = ContextProvider::ContextMap;
void introduceVariable(AST::Identifier&, MangledName::Kind);
void readVariable(AST::Identifier&) const;
MangledName makeMangledName(const String&, MangledName::Kind);
void visitVariableDeclaration(AST::Variable&, MangledName::Kind);
ShaderModule& m_shaderModule;
HashMap<AST::Structure*, NameMap> m_structFieldMapping;
std::array<uint32_t, MangledName::numberOfKinds> m_indexPerType { 0 };
};
void NameManglerVisitor::run()
{
Base::visit(m_shaderModule);
}
void NameManglerVisitor::visit(AST::Function& function)
{
String originalName = function.name();
introduceVariable(function.name(), MangledName::Function);
Base::visit(function);
}
void NameManglerVisitor::visit(AST::Parameter& parameter)
{
Base::visit(parameter.typeName());
introduceVariable(parameter.name(), MangledName::Parameter);
}
void NameManglerVisitor::visit(AST::Structure& structure)
{
introduceVariable(structure.name(), MangledName::Type);
NameMap fieldMap;
for (auto& member : structure.members()) {
Base::visit(member.type());
auto mangledName = makeMangledName(member.name(), MangledName::Field);
fieldMap.add(member.name(), mangledName);
m_shaderModule.replace(&member.name(), AST::Identifier::makeWithSpan(member.name().span(), mangledName.toString()));
}
auto result = m_structFieldMapping.add(&structure, WTF::move(fieldMap));
ASSERT_UNUSED(result, result.isNewEntry);
}
void NameManglerVisitor::visit(AST::Variable& variable)
{
visitVariableDeclaration(variable, MangledName::Global);
}
void NameManglerVisitor::visit(AST::VariableStatement& variable)
{
visitVariableDeclaration(variable.variable(), MangledName::Local);
}
void NameManglerVisitor::visitVariableDeclaration(AST::Variable& variable, MangledName::Kind kind)
{
Base::visit(variable);
introduceVariable(variable.name(), kind);
}
void NameManglerVisitor::visit(AST::IdentifierExpression& identifier)
{
readVariable(identifier.identifier());
}
void NameManglerVisitor::visit(AST::FieldAccessExpression& access)
{
Base::visit(access);
auto* baseType = access.base().inferredType();
if (auto* reference = std::get_if<Types::Reference>(baseType))
baseType = reference->element;
if (auto* pointer = std::get_if<Types::Pointer>(baseType))
baseType = pointer->element;
auto* structType = std::get_if<Types::Struct>(baseType);
if (!structType)
return;
auto structMapIt = m_structFieldMapping.find(&structType->structure);
RELEASE_ASSERT(structMapIt != m_structFieldMapping.end());
auto fieldIt = structMapIt->value.find(access.fieldName());
ASSERT(fieldIt != structMapIt->value.end());
m_shaderModule.replace(&access.fieldName(), AST::Identifier::makeWithSpan(access.fieldName().span(), fieldIt->value.toString()));
}
void NameManglerVisitor::introduceVariable(AST::Identifier& name, MangledName::Kind kind)
{
const auto* mangledName = ContextProvider::introduceVariable(name, makeMangledName(name, kind));
ASSERT(mangledName);
m_shaderModule.replace(&name, AST::Identifier::makeWithSpan(name.span(), mangledName->toString()));
}
MangledName NameManglerVisitor::makeMangledName(const String& name, MangledName::Kind kind)
{
return MangledName {
kind,
m_indexPerType[WTF::enumToUnderlyingType(kind)]++,
name
};
}
void NameManglerVisitor::readVariable(AST::Identifier& name) const
{
if (const auto* mangledName = ContextProvider::readVariable(name))
m_shaderModule.replace(&name, AST::Identifier::makeWithSpan(name.span(), mangledName->toString()));
}
void mangleNames(ShaderModule& shaderModule)
{
NameManglerVisitor(shaderModule).run();
}
} // namespace WGSL