Revision control
Copy as Markdown
// Copyright (C) 2021 The Qt Company Ltd.
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
// Qt-Security score:significant reason:default
#include "glsltypes_p.h"
#include "glslsymbols_p.h"
#include "glslengine_p.h"
#include "glslparser_p.h"
QT_BEGIN_NAMESPACE
using namespace GLSL;
bool UndefinedType::isEqualTo(const Type *other) const
{
if (other && other->asUndefinedType() != nullptr)
return true;
return false;
}
bool UndefinedType::isLessThan(const Type *other) const
{
Q_UNUSED(other)
Q_ASSERT(other != nullptr);
Q_ASSERT(other->asUndefinedType() != nullptr);
return false;
}
bool VoidType::isEqualTo(const Type *other) const
{
if (other && other->asVoidType() != nullptr)
return true;
return false;
}
bool VoidType::isLessThan(const Type *other) const
{
Q_UNUSED(other)
Q_ASSERT(other != nullptr);
Q_ASSERT(other->asVoidType() != nullptr);
return false;
}
bool BoolType::isEqualTo(const Type *other) const
{
if (other && other->asBoolType() != nullptr)
return true;
return false;
}
bool BoolType::isLessThan(const Type *other) const
{
Q_UNUSED(other)
Q_ASSERT(other != nullptr);
Q_ASSERT(other->asBoolType() != nullptr);
return false;
}
bool IntType::isEqualTo(const Type *other) const
{
if (other && other->asIntType() != nullptr)
return true;
return false;
}
bool IntType::isLessThan(const Type *other) const
{
Q_UNUSED(other)
Q_ASSERT(other != nullptr);
Q_ASSERT(other->asIntType() != nullptr);
return false;
}
bool UIntType::isEqualTo(const Type *other) const
{
if (other && other->asUIntType() != nullptr)
return true;
return false;
}
bool UIntType::isLessThan(const Type *other) const
{
Q_UNUSED(other)
Q_ASSERT(other != nullptr);
Q_ASSERT(other->asUIntType() != nullptr);
return false;
}
bool FloatType::isEqualTo(const Type *other) const
{
if (other && other->asFloatType() != nullptr)
return true;
return false;
}
bool FloatType::isLessThan(const Type *other) const
{
Q_UNUSED(other)
Q_ASSERT(other != nullptr);
Q_ASSERT(other->asFloatType() != nullptr);
return false;
}
bool DoubleType::isEqualTo(const Type *other) const
{
if (other && other->asDoubleType() != nullptr)
return true;
return false;
}
bool DoubleType::isLessThan(const Type *other) const
{
Q_UNUSED(other)
Q_ASSERT(other != nullptr);
Q_ASSERT(other->asDoubleType() != nullptr);
return false;
}
QString VectorType::toString() const
{
const char *prefix = "";
if (elementType()->asBoolType() != nullptr)
prefix = "b";
else if (elementType()->asIntType() != nullptr)
prefix = "i'";
else if (elementType()->asUIntType() != nullptr)
prefix = "u";
else if (elementType()->asDoubleType() != nullptr)
prefix = "d";
return QString::fromLatin1("%1vec%2").arg(QLatin1String(prefix)).arg(_dimension);
}
void VectorType::add(Symbol *symbol)
{
_members.insert(symbol->name(), symbol);
}
Symbol *VectorType::find(const QString &name) const
{
return _members.value(name);
}
void VectorType::populateMembers(Engine *engine)
{
if (_members.isEmpty()) {
populateMembers(engine, "xyzw");
populateMembers(engine, "rgba");
populateMembers(engine, "stpq");
}
}
void VectorType::populateMembers(Engine *engine, const char *components)
{
// Single component swizzles.
for (int x = 0; x < _dimension; ++x) {
const QString *name = engine->identifier(components + x, 1);
add(engine->newVariable(this, *name, elementType()));
}
// Two component swizzles.
const Type *vec2Type;
if (_dimension == 2)
vec2Type = this;
else
vec2Type = engine->vectorType(elementType(), 2);
for (int x = 0; x < _dimension; ++x) {
for (int y = 0; y < _dimension; ++y) {
QString name;
name += QLatin1Char(components[x]);
name += QLatin1Char(components[y]);
add(engine->newVariable
(this, *engine->identifier(name), vec2Type));
}
}
// Three component swizzles.
const Type *vec3Type;
if (_dimension == 3)
vec3Type = this;
else if (_dimension < 3)
return;
else
vec3Type = engine->vectorType(elementType(), 3);
for (int x = 0; x < _dimension; ++x) {
for (int y = 0; y < _dimension; ++y) {
for (int z = 0; z < _dimension; ++z) {
QString name;
name += QLatin1Char(components[x]);
name += QLatin1Char(components[y]);
name += QLatin1Char(components[z]);
add(engine->newVariable
(this, *engine->identifier(name), vec3Type));
}
}
}
// Four component swizzles.
if (_dimension != 4)
return;
for (int x = 0; x < _dimension; ++x) {
for (int y = 0; y < _dimension; ++y) {
for (int z = 0; z < _dimension; ++z) {
for (int w = 0; w < _dimension; ++w) {
QString name;
name += QLatin1Char(components[x]);
name += QLatin1Char(components[y]);
name += QLatin1Char(components[z]);
name += QLatin1Char(components[w]);
add(engine->newVariable
(this, *engine->identifier(name), this));
}
}
}
}
}
bool VectorType::isEqualTo(const Type *other) const
{
if (other) {
if (const VectorType *v = other->asVectorType()) {
if (_dimension != v->dimension())
return false;
else if (elementType() != v->elementType())
return false;
return true;
}
}
return false;
}
bool VectorType::isLessThan(const Type *other) const
{
Q_ASSERT(other != nullptr);
const VectorType *vec = other->asVectorType();
Q_ASSERT(vec != nullptr);
if (_dimension < vec->dimension())
return true;
else if (_dimension == vec->dimension() && elementType() < vec->elementType())
return true;
return false;
}
QString MatrixType::toString() const
{
const char *prefix = "";
if (elementType()->asBoolType() != nullptr)
prefix = "b";
else if (elementType()->asIntType() != nullptr)
prefix = "i";
else if (elementType()->asUIntType() != nullptr)
prefix = "u";
else if (elementType()->asDoubleType() != nullptr)
prefix = "d";
return QString::fromLatin1("%1mat%2x%3").arg(QLatin1String(prefix)).arg(_columns).arg(_rows);
}
bool MatrixType::isEqualTo(const Type *other) const
{
if (other) {
if (const MatrixType *v = other->asMatrixType()) {
if (_columns != v->columns())
return false;
else if (_rows != v->rows())
return false;
else if (_elementType != v->elementType())
return false;
return true;
}
}
return false;
}
bool MatrixType::isLessThan(const Type *other) const
{
Q_ASSERT(other != nullptr);
const MatrixType *mat = other->asMatrixType();
Q_ASSERT(mat != nullptr);
if (_columns < mat->columns()) {
return true;
} else if (_columns == mat->columns()) {
if (_rows < mat->rows())
return true;
else if (_rows == mat->rows() && _elementType < mat->elementType())
return true;
}
return false;
}
QString ArrayType::toString() const
{
return elementType()->toString() + QLatin1String("[]");
}
bool ArrayType::isEqualTo(const Type *other) const
{
if (other) {
if (const ArrayType *array = other->asArrayType())
return elementType()->isEqualTo(array->elementType());
}
return false;
}
bool ArrayType::isLessThan(const Type *other) const
{
Q_ASSERT(other != nullptr);
const ArrayType *array = other->asArrayType();
Q_ASSERT(array != nullptr);
return elementType() < array->elementType();
}
QList<Symbol *> Struct::members() const
{
QList<Symbol *> m;
for (Symbol *s : _members) {
if (! s->name().isEmpty())
m.append(s);
}
return m;
}
void Struct::add(Symbol *member)
{
_members.append(member);
}
Symbol *Struct::find(const QString &name) const
{
for (Symbol *s : _members) {
if (s->name() == name)
return s;
}
return nullptr;
}
bool Struct::isEqualTo(const Type *other) const
{
Q_UNUSED(other)
return false;
}
bool Struct::isLessThan(const Type *other) const
{
Q_UNUSED(other)
return false;
}
QString Function::toString() const
{
return prettyPrint();
}
QString Function::prettyPrint() const
{
QString proto;
proto += _returnType->toString();
proto += QLatin1Char(' ');
proto += name();
proto += QLatin1Char('(');
for (int i = 0; i < _arguments.size(); ++i) {
if (i != 0)
proto += QLatin1String(", ");
Argument *arg = _arguments.at(i);
proto += arg->type()->toString();
proto += QLatin1Char(' ');
proto += arg->name();
}
proto += QLatin1Char(')');
return proto;
}
const Type *Function::returnType() const
{
return _returnType;
}
void Function::setReturnType(const Type *returnType)
{
_returnType = returnType;
}
QVector<Argument *> Function::arguments() const
{
return _arguments;
}
void Function::addArgument(Argument *arg)
{
_arguments.append(arg);
}
int Function::argumentCount() const
{
return _arguments.size();
}
Argument *Function::argumentAt(int index) const
{
return _arguments.at(index);
}
bool Function::isEqualTo(const Type *other) const
{
Q_UNUSED(other)
return false;
}
bool Function::isLessThan(const Type *other) const
{
Q_UNUSED(other)
return false;
}
QList<Symbol *> Function::members() const
{
QList<Symbol *> m;
for (Argument *arg : _arguments) {
if (! arg->name().isEmpty())
m.append(arg);
}
return m;
}
Symbol *Function::find(const QString &name) const
{
for (Argument *arg : _arguments) {
if (arg->name() == name)
return arg;
}
return nullptr;
}
QString SamplerType::toString() const
{
return QLatin1String(Parser::spell[_kind]);
}
bool SamplerType::isEqualTo(const Type *other) const
{
if (other) {
if (const SamplerType *samp = other->asSamplerType())
return _kind == samp->kind();
}
return false;
}
bool SamplerType::isLessThan(const Type *other) const
{
Q_ASSERT(other != nullptr);
const SamplerType *samp = other->asSamplerType();
Q_ASSERT(samp != nullptr);
return _kind < samp->kind();
}
OverloadSet::OverloadSet(Scope *enclosingScope)
: Scope(enclosingScope)
{
}
QVector<Function *> OverloadSet::functions() const
{
return _functions;
}
void OverloadSet::addFunction(Function *function)
{
_functions.append(function);
}
const Type *OverloadSet::type() const
{
return this;
}
Symbol *OverloadSet::find(const QString &) const
{
return nullptr;
}
void OverloadSet::add(Symbol *symbol)
{
if (symbol) {
if (Function *fun = symbol->asFunction())
addFunction(fun);
}
}
bool OverloadSet::isEqualTo(const Type *other) const
{
Q_UNUSED(other)
return false;
}
bool OverloadSet::isLessThan(const Type *other) const
{
Q_UNUSED(other)
return false;
}
QT_END_NAMESPACE