f31522130f
Build system (5 gaps hardened): - COOKBOOK_OFFLINE defaults to true (fork-mode) - normalize_patch handles diff -ruN format - New 'repo validate-patches' command (25/25 relibc patches) - 14 patched Qt/Wayland/display recipes added to protected list - relibc archive regenerated with current patch chain Boot fixes (fixable): - Full ISO EFI partition: 16 MiB → 1 MiB (matches mini, BIOS hardcoded 2 MiB offset) - D-Bus system bus: absolute /usr/bin/dbus-daemon path (was skipped) - redbear-sessiond: absolute /usr/bin/redbear-sessiond path (was skipped) - daemon framework: silenced spurious INIT_NOTIFY warnings for oneshot_async services (P0-daemon-silence-init-notify.patch) - udev-shim: demoted INIT_NOTIFY warning to INFO (expected for oneshot_async) - relibc: comprehensive named semaphores (sem_open/close/unlink) replacing upstream todo!() stubs - greeterd: Wayland socket timeout 15s → 30s (compositor DRM wait) - greeter-ui: built and linked (header guard unification, sem_compat stubs removed) - mc: un-ignored in both configs, fixed glib/libiconv/pcre2 transitive deps - greeter config: removed stale keymapd dependency from display/greeter services - prefix toolchain: relibc headers synced, _RELIBC_STDLIB_H guard unified Unfixable (diagnosed, upstream): - i2c-hidd: abort on no-I2C-hardware (QEMU) — process::exit → relibc abort - kded6/greeter-ui: page fault 0x8 — Qt library null deref - Thread panics fd != -1 — Rust std library on Redox - DHCP timeout / eth0 MAC — QEMU user-mode networking - hwrngd/thermald — no hardware RNG/thermal in VM - live preload allocation — BIOS memory fragmentation, continues on demand
217 lines
8.4 KiB
C++
217 lines
8.4 KiB
C++
// Copyright (C) 2021 The Qt Company Ltd.
|
|
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
|
|
|
|
#ifndef QMLTCCOMPILER_H
|
|
#define QMLTCCOMPILER_H
|
|
|
|
#include "qmltctyperesolver.h"
|
|
#include "qmltcvisitor.h"
|
|
#include "qmltcoutputir.h"
|
|
|
|
#include <QtCore/qcommandlineparser.h>
|
|
#include <QtCore/qcoreapplication.h>
|
|
#include <QtCore/qstring.h>
|
|
#include <QtCore/qhash.h>
|
|
|
|
#include <private/qqmljslogger_p.h>
|
|
|
|
#include <memory>
|
|
|
|
QT_BEGIN_NAMESPACE
|
|
|
|
struct QmltcCompilerInfo
|
|
{
|
|
QString outputCppFile;
|
|
QString outputHFile;
|
|
QString outputNamespace;
|
|
QString resourcePath;
|
|
QString exportMacro;
|
|
QString exportInclude;
|
|
};
|
|
|
|
class QmltcCompiler
|
|
{
|
|
using InlineComponentOrDocumentRootName = QQmlJSScope::InlineComponentOrDocumentRootName;
|
|
using InlineComponentNameType = QQmlJSScope::InlineComponentNameType;
|
|
using RootDocumentNameType = QQmlJSScope::RootDocumentNameType;
|
|
|
|
public:
|
|
QmltcCompiler(const QString &url, QmltcTypeResolver *resolver, QmltcVisitor *visitor,
|
|
QQmlJSLogger *logger);
|
|
void compile(const QmltcCompilerInfo &info);
|
|
|
|
~QmltcCompiler();
|
|
|
|
/*! \internal
|
|
|
|
Returns \c true if \a binding is considered complex by the compiler
|
|
(requires special code generation)
|
|
*/
|
|
static bool isComplexBinding(const QQmlJSMetaPropertyBinding &binding)
|
|
{
|
|
// TODO: translation bindings (once supported) are also complex?
|
|
return binding.bindingType() == QQmlSA::BindingType::Script;
|
|
}
|
|
|
|
private:
|
|
QString m_url; // QML input file url
|
|
QmltcTypeResolver *m_typeResolver = nullptr;
|
|
QmltcVisitor *m_visitor = nullptr;
|
|
QQmlJSLogger *m_logger = nullptr;
|
|
QmltcCompilerInfo m_info {}; // miscellaneous input/output information
|
|
QString m_urlMethodName;
|
|
uint m_currentVariableNumber = 0;
|
|
|
|
struct UniqueStringId;
|
|
struct QmltcTypeLocalData;
|
|
// per-type, per-property code generation cache of created symbols
|
|
QHash<UniqueStringId, QmltcTypeLocalData> m_uniques;
|
|
|
|
void compileUrlMethod(QmltcMethod &urlMethod, const QString &urlMethodName);
|
|
void
|
|
compileType(QmltcType ¤t, const QQmlJSScope::ConstPtr &type,
|
|
std::function<void(QmltcType &, const QQmlJSScope::ConstPtr &)> compileElements);
|
|
void compileTypeElements(QmltcType ¤t, const QQmlJSScope::ConstPtr &type);
|
|
void compileEnum(QmltcType ¤t, const QQmlJSMetaEnum &e);
|
|
void compileMethod(QmltcType ¤t, const QQmlJSMetaMethod &m,
|
|
const QQmlJSScope::ConstPtr &owner);
|
|
void compileProperty(QmltcType ¤t, const QQmlJSMetaProperty &p,
|
|
const QQmlJSScope::ConstPtr &owner);
|
|
void compileAlias(QmltcType ¤t, const QQmlJSMetaProperty &alias,
|
|
const QQmlJSScope::ConstPtr &owner);
|
|
void compileExtraListMethods(QmltcType ¤t, const QQmlJSMetaProperty &p);
|
|
|
|
QString uniqueVariableName(const QString &qmlName)
|
|
{
|
|
QString result = u"m_"_s + QString::number(++m_currentVariableNumber) + qmlName;
|
|
result.replace(u'.', u'_');
|
|
return result;
|
|
}
|
|
|
|
/*!
|
|
\internal
|
|
|
|
Helper structure that holds the information necessary for most bindings,
|
|
such as accessor name, which is used to reference the properties. For
|
|
example:
|
|
> (accessor.name)->(propertyName) results in "this->myProperty"
|
|
|
|
This data is also used in more advanced scenarios by attached and
|
|
grouped properties
|
|
*/
|
|
struct BindingAccessorData
|
|
{
|
|
QQmlJSScope::ConstPtr scope; // usually the current type
|
|
QString name = QStringLiteral("this");
|
|
QString propertyName = QString();
|
|
bool isValueType = false;
|
|
};
|
|
|
|
QStringList unprocessedListBindings;
|
|
QQmlJSMetaProperty unprocessedListProperty;
|
|
|
|
void processLastListBindings(QmltcType ¤t, const QQmlJSScope::ConstPtr &type,
|
|
const BindingAccessorData &accessor);
|
|
|
|
void compileBinding(QmltcType ¤t, QList<QQmlJSMetaPropertyBinding>::iterator bindingStart,
|
|
QList<QQmlJSMetaPropertyBinding>::iterator bindingEnd,
|
|
const QQmlJSScope::ConstPtr &type, const BindingAccessorData &accessor);
|
|
|
|
void compileBindingByType(QmltcType ¤t, const QQmlJSMetaPropertyBinding &binding,
|
|
const QQmlJSScope::ConstPtr &type,
|
|
const BindingAccessorData &accessor);
|
|
|
|
void compileObjectBinding(QmltcType ¤t, const QQmlJSMetaPropertyBinding &binding,
|
|
const QQmlJSScope::ConstPtr &type,
|
|
const BindingAccessorData &accessor);
|
|
|
|
void compileValueSourceOrInterceptorBinding(QmltcType ¤t,
|
|
const QQmlJSMetaPropertyBinding &binding,
|
|
const QQmlJSScope::ConstPtr &type,
|
|
const BindingAccessorData &accessor);
|
|
|
|
void compileAttachedPropertyBinding(QmltcType ¤t,
|
|
const QQmlJSMetaPropertyBinding &binding,
|
|
const QQmlJSScope::ConstPtr &type,
|
|
const BindingAccessorData &accessor);
|
|
|
|
void compileGroupPropertyBinding(QmltcType ¤t, const QQmlJSMetaPropertyBinding &binding,
|
|
const QQmlJSScope::ConstPtr &type,
|
|
const BindingAccessorData &accessor);
|
|
|
|
void compileTranslationBinding(QmltcType ¤t, const QQmlJSMetaPropertyBinding &binding,
|
|
const QQmlJSScope::ConstPtr &type,
|
|
const BindingAccessorData &accessor);
|
|
|
|
// special case (for simplicity)
|
|
void compileScriptBinding(QmltcType ¤t, const QQmlJSMetaPropertyBinding &binding,
|
|
const QString &bindingSymbolName, const QQmlJSScope::ConstPtr &type,
|
|
const QString &propertyName,
|
|
const QQmlJSScope::ConstPtr &propertyType,
|
|
const BindingAccessorData &accessor);
|
|
|
|
void compilePropertyInitializer(QmltcType ¤t, const QQmlJSScope::ConstPtr &type);
|
|
|
|
/*!
|
|
\internal
|
|
Helper structure that acts as a key in a hash-table of
|
|
QmltcType-specific data (such as local variable names). Using a
|
|
hash-table allows to avoid creating the same variables multiple times
|
|
during binding compilation, which leads to better code generation and
|
|
faster object creation. This is really something that the QML optimizer
|
|
should do, but we have only this home-grown alternative at the moment
|
|
*/
|
|
struct UniqueStringId
|
|
{
|
|
QString unique;
|
|
UniqueStringId(const QmltcType &context, const QString &property)
|
|
: unique(context.cppType + u"_" + property) // this is unique enough
|
|
{
|
|
Q_ASSERT(!context.cppType.isEmpty());
|
|
Q_ASSERT(!property.isEmpty());
|
|
}
|
|
friend bool operator==(const UniqueStringId &x, const UniqueStringId &y)
|
|
{
|
|
return x.unique == y.unique;
|
|
}
|
|
friend bool operator!=(const UniqueStringId &x, const UniqueStringId &y)
|
|
{
|
|
return !(x == y);
|
|
}
|
|
friend size_t qHash(const UniqueStringId &x, size_t seed = 0)
|
|
{
|
|
return qHash(x.unique, seed);
|
|
}
|
|
};
|
|
|
|
struct QmltcTypeLocalData
|
|
{
|
|
// empty QString() means that the local data is not present (yet)
|
|
QString qmlListVariableName;
|
|
QString onAssignmentObjectName;
|
|
QString attachedVariableName;
|
|
};
|
|
|
|
QHash<QString, qsizetype> m_symbols;
|
|
QString newSymbol(const QString &base);
|
|
|
|
bool hasErrors() const { return m_logger->hasErrors(); }
|
|
void recordError(const QQmlJS::SourceLocation &location, const QString &message,
|
|
QQmlJS::LoggerWarningId id = qmlCompiler)
|
|
{
|
|
// pretty much any compiler error is a critical error (we cannot
|
|
// generate code - compilation fails)
|
|
m_logger->log(message, id, location);
|
|
}
|
|
void recordError(const QV4::CompiledData::Location &location, const QString &message,
|
|
QQmlJS::LoggerWarningId id = qmlCompiler)
|
|
{
|
|
recordError(QQmlJS::SourceLocation { 0, 0, location.line(), location.column() }, message,
|
|
id);
|
|
}
|
|
};
|
|
|
|
QT_END_NAMESPACE
|
|
|
|
#endif // QMLTCCOMPILER_H
|