diff options
Diffstat (limited to 'src/tools/tracegen')
-rw-r--r-- | src/tools/tracegen/CMakeLists.txt | 12 | ||||
-rw-r--r-- | src/tools/tracegen/ctf.cpp | 376 | ||||
-rw-r--r-- | src/tools/tracegen/ctf.h | 12 | ||||
-rw-r--r-- | src/tools/tracegen/etw.cpp | 132 | ||||
-rw-r--r-- | src/tools/tracegen/etw.h | 40 | ||||
-rw-r--r-- | src/tools/tracegen/helpers.cpp | 109 | ||||
-rw-r--r-- | src/tools/tracegen/helpers.h | 60 | ||||
-rw-r--r-- | src/tools/tracegen/lttng.cpp | 202 | ||||
-rw-r--r-- | src/tools/tracegen/lttng.h | 40 | ||||
-rw-r--r-- | src/tools/tracegen/panic.cpp | 53 | ||||
-rw-r--r-- | src/tools/tracegen/panic.h | 41 | ||||
-rw-r--r-- | src/tools/tracegen/provider.cpp | 326 | ||||
-rw-r--r-- | src/tools/tracegen/provider.h | 85 | ||||
-rw-r--r-- | src/tools/tracegen/qtheaders.cpp | 40 | ||||
-rw-r--r-- | src/tools/tracegen/qtheaders.h | 40 | ||||
-rw-r--r-- | src/tools/tracegen/tracegen.cpp | 55 |
16 files changed, 993 insertions, 630 deletions
diff --git a/src/tools/tracegen/CMakeLists.txt b/src/tools/tracegen/CMakeLists.txt index bb45950081..f5f6b2e184 100644 --- a/src/tools/tracegen/CMakeLists.txt +++ b/src/tools/tracegen/CMakeLists.txt @@ -1,4 +1,5 @@ -# Generated from tracegen.pro. +# Copyright (C) 2022 The Qt Company Ltd. +# SPDX-License-Identifier: BSD-3-Clause ##################################################################### ## tracegen Tool: @@ -6,19 +7,18 @@ qt_get_tool_target_name(target_name tracegen) qt_internal_add_tool(${target_name} - BOOTSTRAP + CORE_LIBRARY Bootstrap INSTALL_DIR "${INSTALL_LIBEXECDIR}" - TOOLS_TARGET Core # special case + TOOLS_TARGET Core SOURCES etw.cpp etw.h helpers.cpp helpers.h + ctf.cpp ctf.h lttng.cpp lttng.h panic.cpp panic.h provider.cpp provider.h qtheaders.cpp qtheaders.h tracegen.cpp + NO_UNITY_BUILD ) qt_internal_return_unless_building_tools() - -#### Keys ignored in scope 1:.:.:tracegen.pro:<TRUE>: -# _OPTION = "host_build" diff --git a/src/tools/tracegen/ctf.cpp b/src/tools/tracegen/ctf.cpp new file mode 100644 index 0000000000..95ffcf89cc --- /dev/null +++ b/src/tools/tracegen/ctf.cpp @@ -0,0 +1,376 @@ +// Copyright (C) 2022 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0 + +#include "ctf.h" +#include "provider.h" +#include "helpers.h" +#include "panic.h" +#include "qtheaders.h" + +#include <qfile.h> +#include <qfileinfo.h> +#include <qtextstream.h> +#include <qdebug.h> + + +static void writePrologue(QTextStream &stream, const QString &fileName, const Provider &provider) +{ + writeCommonPrologue(stream); + const QString guard = includeGuard(fileName); + + // include prefix text or qt headers only once + stream << "#if !defined(" << guard << ")\n"; + stream << qtHeaders(); + stream << "\n"; + if (!provider.prefixText.isEmpty()) + stream << provider.prefixText.join(u'\n') << "\n\n"; + stream << "#endif\n\n"; + + /* the first guard is the usual one, the second is required + * by LTTNG to force the re-evaluation of TRACEPOINT_* macros + */ + stream << "#if !defined(" << guard << ") || defined(TRACEPOINT_HEADER_MULTI_READ)\n"; + + stream << "#define " << guard << "\n\n" + << "#undef TRACEPOINT_INCLUDE\n" + << "#define TRACEPOINT_INCLUDE \"" << fileName << "\"\n\n"; + + stream << "#include <private/qctf_p.h>\n\n"; + + const QString namespaceGuard = guard + QStringLiteral("_USE_NAMESPACE"); + stream << "#if !defined(" << namespaceGuard << ")\n" + << "#define " << namespaceGuard << "\n" + << "QT_USE_NAMESPACE\n" + << "#endif // " << namespaceGuard << "\n\n"; + + stream << "TRACEPOINT_PROVIDER(" << provider.name << ");\n\n"; +} + +static void writeEpilogue(QTextStream &stream, const QString &fileName) +{ + stream << "\n"; + stream << "#endif // " << includeGuard(fileName) << "\n" + << "#include <private/qtrace_p.h>\n"; +} + +static void writeWrapper(QTextStream &stream, + const Tracepoint &tracepoint, const Provider &provider) +{ + const QString argList = formatFunctionSignature(tracepoint.args); + const QString paramList = formatParameterList(provider, tracepoint.args, tracepoint.fields, CTF); + const QString &name = tracepoint.name; + const QString includeGuard = QStringLiteral("TP_%1_%2").arg(provider.name).arg(name).toUpper(); + + /* prevents the redefinion of the inline wrapper functions + */ + stream << "\n" + << "#ifndef " << includeGuard << "\n" + << "#define " << includeGuard << "\n" + << "QT_BEGIN_NAMESPACE\n" + << "namespace QtPrivate {\n"; + + stream << "inline void trace_" << name << "(" << argList << ")\n" + << "{\n" + << " tracepoint(" << provider.name << ", " << name << paramList << ");\n" + << "}\n"; + + stream << "inline void do_trace_" << name << "(" << argList << ")\n" + << "{\n" + << " do_tracepoint(" << provider.name << ", " << name << paramList << ");\n" + << "}\n"; + + stream << "inline bool trace_" << name << "_enabled()\n" + << "{\n" + << " return tracepoint_enabled(" << provider.name << ", " << name << ");\n" + << "}\n"; + + stream << "} // namespace QtPrivate\n" + << "QT_END_NAMESPACE\n" + << "#endif // " << includeGuard << "\n\n"; +} + + +static void writeMetadataGenerators(QTextStream &stream) +{ + stream << R"CPP( +template <typename T> +inline QString integerToMetadata(const QString &name) +{ + QString ret; + if (!std::is_signed<T>().value) + ret += QLatin1Char('u'); + if (sizeof(T) == 8) + ret += QStringLiteral("int64_t "); + else if (sizeof(T) == 4) + ret += QStringLiteral("int32_t "); + else if (sizeof(T) == 2) + ret += QStringLiteral("int16_t "); + else if (sizeof(T) == 1) + ret += QStringLiteral("int8_t "); + ret += name + QLatin1Char(';'); + return ret; +} + +template <typename T> +inline QString integerArrayToMetadata(const QString &size, const QString &name) +{ + QString ret; + if (!std::is_signed<T>().value) + ret += QLatin1Char('u'); + if (sizeof(T) == 8) + ret += QStringLiteral("int64_t "); + else if (sizeof(T) == 4) + ret += QStringLiteral("int32_t "); + else if (sizeof(T) == 2) + ret += QStringLiteral("int16_t "); + else if (sizeof(T) == 1) + ret += QStringLiteral("int8_t "); + ret += name + QLatin1Char('[') + size + QStringLiteral("];"); + return ret; +} + +template <typename T> +inline QString floatToMetadata(const QString &name) +{ + QString ret; + if (sizeof(T) == 8) + ret += QStringLiteral("double "); + else if (sizeof(T) == 4) + ret += QStringLiteral("float "); + ret += name + QLatin1Char(';'); + return ret; +} + +template <typename T> +inline QString floatArrayToMetadata(const QString &size, const QString &name) +{ + QString ret; + if (sizeof(T) == 8) + ret += QStringLiteral("double "); + else if (sizeof(T) == 4) + ret += QStringLiteral("float "); + ret += name + QLatin1Char('[') + size + QLatin1Char(']'); + return ret + QLatin1Char(';'); +} + +inline QString pointerToMetadata(const QString &name) +{ + QString ret; + if (QT_POINTER_SIZE == 8) + ret += QStringLiteral("intptr64_t "); + else if (QT_POINTER_SIZE == 4) + ret += QStringLiteral("intptr32_t "); + ret += name + QLatin1Char(';'); + return ret; +} + +)CPP"; +} + +static void writeTracepoint(QTextStream &stream, + const Tracepoint &tracepoint, const QString &providerName) +{ + stream << "TRACEPOINT_EVENT(\n" + << " " << providerName << ",\n" + << " " << tracepoint.name << ",\n"; + + const auto checkUnknownArgs = [](const Tracepoint &tracepoint) { + for (auto &field : tracepoint.fields) { + if (field.backendType == Tracepoint::Field::Unknown) + return true; + } + return false; + }; + + const auto formatType = [](const QString &type) { + QString ret = type; + if (type.endsWith(QLatin1Char('*')) || type.endsWith(QLatin1Char('&'))) + ret = type.left(type.length() - 1).simplified(); + if (ret.startsWith(QStringLiteral("const"))) + ret = ret.right(ret.length() - 6).simplified(); + return typeToTypeName(ret); + }; + QString eventSize; + bool variableSize = false; + const bool emptyMetadata = checkUnknownArgs(tracepoint) || tracepoint.args.size() == 0; + if (!emptyMetadata) { + for (int i = 0; i < tracepoint.args.size(); i++) { + auto &arg = tracepoint.args[i]; + auto &field = tracepoint.fields[i]; + if (i > 0) { + stream << " + QStringLiteral(\"\\n\\\n \") + "; + eventSize += QStringLiteral(" + "); + } + const bool array = field.arrayLen > 0; + switch (field.backendType) { + case Tracepoint::Field::Boolean: { + stream << "QStringLiteral(\"Boolean " << arg.name << ";\")"; + eventSize += QStringLiteral("sizeof(bool)"); + } break; + case Tracepoint::Field::Integer: { + if (array) { + stream << "integerArrayToMetadata<" << formatType(arg.type) + << ">(QStringLiteral(\"" << field.arrayLen << "\"), QStringLiteral(\"" + << arg.name << "\"))"; + } else { + stream << "integerToMetadata<" << formatType(arg.type) << ">(QStringLiteral(\"" + << arg.name << "\"))"; + } + eventSize += QStringLiteral("sizeof(") + formatType(arg.type) + QStringLiteral(")"); + if (array) + eventSize += QStringLiteral(" * ") + QString::number(field.arrayLen); + } break; + case Tracepoint::Field::Pointer: + case Tracepoint::Field::IntegerHex: { + stream << "pointerToMetadata(QStringLiteral(\"" << formatType(arg.type) << "_" + << arg.name << "\"))"; + eventSize += QStringLiteral("QT_POINTER_SIZE"); + } break; + case Tracepoint::Field::Float: { + if (array) { + stream << "floatArrayToMetadata<" << formatType(arg.type) + << ">(QStringLiteral(\"" << field.arrayLen << "\"), QStringLiteral(\"" + << arg.name << "\"))"; + } else { + stream << "floatToMetadata<" << formatType(arg.type) << ">(QStringLiteral(\"" + << arg.name << "\"))"; + } + eventSize += QStringLiteral("sizeof(") + formatType(arg.type) + QStringLiteral(")"); + if (array) + eventSize += QStringLiteral(" * ") + QString::number(field.arrayLen); + } break; + case Tracepoint::Field::QtUrl: + case Tracepoint::Field::QtString: + case Tracepoint::Field::String: { + stream << "QStringLiteral(\"string " << arg.name << ";\")"; + eventSize += QStringLiteral("1"); + variableSize = true; + } break; + case Tracepoint::Field::QtRect: { + stream << "QStringLiteral(\"int32_t QRect_" << arg.name << "_x;\\n\\\n \")"; + stream << " + QStringLiteral(\"int32_t QRect_" << arg.name << "_y;\\n\\\n \")"; + stream << " + QStringLiteral(\"int32_t QRect_" << arg.name << "_width;\\n\\\n \")"; + stream << " + QStringLiteral(\"int32_t QRect_" << arg.name << "_height;\\n\\\n \")"; + eventSize += QStringLiteral("16"); + } break; + case Tracepoint::Field::QtSize: { + stream << "QStringLiteral(\"int32_t QSize_" << arg.name << "_width;\\n\\\n \")"; + stream << " + QStringLiteral(\"int32_t QSize_" << arg.name << "_height;\\n\\\n \")"; + eventSize += QStringLiteral("8"); + } break; + case Tracepoint::Field::QtRectF: { + stream << "QStringLiteral(\"float QRectF_" << arg.name << "_x;\\n\\\n \")"; + stream << " + QStringLiteral(\"float QRectF_" << arg.name << "_y;\\n\\\n \")"; + stream << " + QStringLiteral(\"float QRectF_" << arg.name << "_width;\\n\\\n \")"; + stream << " + QStringLiteral(\"float QRectF_" << arg.name << "_height;\\n\\\n \")"; + eventSize += QStringLiteral("16"); + } break; + case Tracepoint::Field::QtSizeF: { + stream << "QStringLiteral(\"float QSizeF_" << arg.name << "_width;\\n\\\n \")"; + stream << " + QStringLiteral(\"float QSizeF_" << arg.name << "_height;\\n\\\n \")"; + eventSize += QStringLiteral("8"); + } break; + case Tracepoint::Field::Unknown: + break; + case Tracepoint::Field::EnumeratedType: { + stream << "QStringLiteral(\"" << typeToTypeName(arg.type) << " " << arg.name << ";\")"; + eventSize += QString::number(field.enumValueSize / 8); + variableSize = true; + } break; + case Tracepoint::Field::FlagType: { + stream << "QStringLiteral(\"uint8_t " << arg.name << "_length;\\n\\\n "; + stream << typeToTypeName(arg.type) << " " << arg.name << "[" << arg.name << "_length];\")"; + eventSize += QStringLiteral("2"); + variableSize = true; + } break; + case Tracepoint::Field::QtByteArray: + case Tracepoint::Field::Sequence: + panic("Unhandled type '%s %s", qPrintable(arg.type), qPrintable(arg.name)); + break; + } + } + } + + if (emptyMetadata) + stream << "{},\n"; + else + stream << ",\n"; + if (eventSize.length()) + stream << eventSize << ", \n"; + else + stream << "0, \n"; + stream << (variableSize ? "true" : "false") << "\n"; + stream << ")\n\n"; +} + +static void writeTracepoints(QTextStream &stream, const Provider &provider) +{ + for (const Tracepoint &t : provider.tracepoints) { + writeTracepoint(stream, t, provider.name); + writeWrapper(stream, t, provider); + } +} + +static void writeEnums(QTextStream &stream, const Provider &provider) +{ + for (const auto &e : provider.enumerations) { + QString name = e.name; + name.replace(QStringLiteral("::"), QStringLiteral("_")); + stream << "TRACEPOINT_METADATA(" << provider.name << ", " << name << ", \n"; + stream << "QStringLiteral(\"typealias enum : integer { size = " << e.valueSize << "; } {\\n\\\n"; + + const auto values = e.values; + QList<int> handledValues; + + for (const auto &v : values) { + if (handledValues.contains(v.value)) + continue; + if (v.range) { + stream << v.name << " = " << v.value << " ... " << v.range << ", \\n\\\n"; + } else { + const QString names = aggregateListValues(v.value, values); + stream << names << " = " << v.value << ", \\n\\\n"; + handledValues.append(v.value); + } + } + stream << "} := " << name << ";\\n\\n\"));\n\n"; + } + stream << "\n"; +} + +static void writeFlags(QTextStream &stream, const Provider &provider) +{ + for (const auto &e : provider.flags) { + QString name = e.name; + name.replace(QStringLiteral("::"), QStringLiteral("_")); + stream << "TRACEPOINT_METADATA(" << provider.name << ", " << name << ", \n"; + stream << "QStringLiteral(\"typealias enum : integer { size = 8; } {\\n\\\n"; + + const auto values = e.values; + QList<int> handledValues; + + for (const auto &v : values) { + if (handledValues.contains(v.value)) + continue; + const QString names = aggregateListValues(v.value, values); + stream << names << " = " << v.value << ", \\n\\\n"; + handledValues.append(v.value); + } + stream << "} := " << name << ";\\n\\n\"));\n\n"; + } + stream << "\n"; +} + +void writeCtf(QFile &file, const Provider &provider) +{ + QTextStream stream(&file); + + const QString fileName = QFileInfo(file.fileName()).fileName(); + + writePrologue(stream, fileName, provider); + writeMetadataGenerators(stream); + writeEnums(stream, provider); + writeFlags(stream, provider); + writeTracepoints(stream, provider); + writeEpilogue(stream, fileName); +} diff --git a/src/tools/tracegen/ctf.h b/src/tools/tracegen/ctf.h new file mode 100644 index 0000000000..113e30919f --- /dev/null +++ b/src/tools/tracegen/ctf.h @@ -0,0 +1,12 @@ +// Copyright (C) 2022 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0 + +#ifndef CTF_H +#define CTF_H + +struct Provider; +class QFile; + +void writeCtf(QFile &device, const Provider &p); + +#endif // CTF_H diff --git a/src/tools/tracegen/etw.cpp b/src/tools/tracegen/etw.cpp index b17d54bf52..f54a7896ea 100644 --- a/src/tools/tracegen/etw.cpp +++ b/src/tools/tracegen/etw.cpp @@ -1,41 +1,5 @@ -/**************************************************************************** -** -** Copyright (C) 2017 Klarälvdalens Datakonsult AB, a KDAB Group company, info@kdab.com, author Rafael Roquetto <rafael.roquetto@kdab.com> -** Contact: https://www.qt.io/licensing/ -** -** This file is part of the tools applications of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:LGPL$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. For licensing terms -** and conditions see https://www.qt.io/terms-conditions. For further -** information use the contact form at https://www.qt.io/contact-us. -** -** GNU Lesser General Public License Usage -** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 3 as published by the Free Software -** Foundation and appearing in the file LICENSE.LGPL3 included in the -** packaging of this file. Please review the following information to -** ensure the GNU Lesser General Public License version 3 requirements -** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 2.0 or (at your option) the GNU General -** Public license version 3 or any later version approved by the KDE Free -** Qt Foundation. The licenses are as published by the Free Software -** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 -** included in the packaging of this file. Please review the following -** information to ensure the GNU General Public License requirements will -** be met: https://www.gnu.org/licenses/gpl-2.0.html and -** https://www.gnu.org/licenses/gpl-3.0.html. -** -** $QT_END_LICENSE$ -** -****************************************************************************/ +// Copyright (C) 2017 Klarälvdalens Datakonsult AB, a KDAB Group company, info@kdab.com, author Rafael Roquetto <rafael.roquetto@kdab.com> +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0 #include "etw.h" #include "provider.h" @@ -47,15 +11,26 @@ #include <qtextstream.h> #include <quuid.h> +using namespace Qt::StringLiterals; + static inline QString providerVar(const QString &providerName) { - return providerName + QLatin1String("_provider"); + return providerName + "_provider"_L1; } static void writeEtwMacro(QTextStream &stream, const Tracepoint::Field &field) { const QString &name = field.name; + if (field.arrayLen > 0) { + for (int i = 0; i < field.arrayLen; i++) { + stream << "TraceLoggingValue(" << name << "[" << i << "], \"" << name << "[" << i << "]\")"; + if (i + 1 < field.arrayLen) + stream << ",\n "; + } + return; + } + switch (field.backendType) { case Tracepoint::Field::QtString: stream << "TraceLoggingCountedWideString(reinterpret_cast<LPCWSTR>(" @@ -70,11 +45,17 @@ static void writeEtwMacro(QTextStream &stream, const Tracepoint::Field &field) stream << "TraceLoggingValue(" << name << ".toEncoded().constData(), \"" << name << "\")"; return; case Tracepoint::Field::QtRect: + case Tracepoint::Field::QtRectF: stream << "TraceLoggingValue(" << name << ".x(), \"x\"), " << "TraceLoggingValue(" << name << ".y(), \"y\"), " << "TraceLoggingValue(" << name << ".width(), \"width\"), " << "TraceLoggingValue(" << name << ".height(), \"height\")"; return; + case Tracepoint::Field::QtSize: + case Tracepoint::Field::QtSizeF: + stream << "TraceLoggingValue(" << name << ".width(), \"width\"), " + << "TraceLoggingValue(" << name << ".height(), \"height\")"; + return; case Tracepoint::Field::Pointer: stream << "TraceLoggingPointer(" << name << ", \"" << name << "\")"; return; @@ -85,6 +66,10 @@ static void writeEtwMacro(QTextStream &stream, const Tracepoint::Field &field) stream << "TraceLoggingCountedWideString(reinterpret_cast<LPCWSTR>(" << name << "Str.utf16()), static_cast<ULONG>(" << name << "Str.size()), \"" << name << "\")"; return; + case Tracepoint::Field::EnumeratedType: + case Tracepoint::Field::FlagType: + stream << "TraceLoggingString(trace_convert_" << typeToTypeName(field.paramType) << "(" << name << ").toUtf8().constData(), \"" << name << "\")"; + return; default: break; } @@ -119,6 +104,7 @@ static QString createGuid(const QUuid &uuid) static void writePrologue(QTextStream &stream, const QString &fileName, const Provider &provider) { + writeCommonPrologue(stream); QUuid uuid = QUuid::createUuidV5(QUuid(), provider.name.toLocal8Bit()); const QString providerV = providerVar(provider.name); @@ -129,7 +115,7 @@ static void writePrologue(QTextStream &stream, const QString &fileName, const Pr stream << "#ifndef " << guard << "\n" << "#define " << guard << "\n" << "\n" - << "#include <windows.h>\n" + << "#include <qt_windows.h>\n" << "#include <TraceLoggingProvider.h>\n" << "\n"; @@ -146,7 +132,7 @@ static void writePrologue(QTextStream &stream, const QString &fileName, const Pr stream << "\n"; if (!provider.prefixText.isEmpty()) - stream << provider.prefixText.join(QLatin1Char('\n')) << "\n\n"; + stream << provider.prefixText.join(u'\n') << "\n\n"; stream << "#ifdef TRACEPOINT_DEFINE\n" << "/* " << guidString << " */\n" @@ -177,14 +163,14 @@ static void writeEpilogue(QTextStream &stream, const QString &fileName) << "#include <private/qtrace_p.h>\n"; } -static void writeWrapper(QTextStream &stream, const Tracepoint &tracepoint, +static void writeWrapper(QTextStream &stream, const Provider &provider, const Tracepoint &tracepoint, const QString &providerName) { const QString argList = formatFunctionSignature(tracepoint.args); - const QString paramList = formatParameterList(tracepoint.args, ETW); + const QString paramList = formatParameterList(provider, tracepoint.args, tracepoint.fields, ETW); const QString &name = tracepoint.name; const QString includeGuard = QStringLiteral("TP_%1_%2").arg(providerName).arg(name).toUpper(); - const QString provider = providerVar(providerName); + const QString provar = providerVar(providerName); stream << "\n"; @@ -199,7 +185,7 @@ static void writeWrapper(QTextStream &stream, const Tracepoint &tracepoint, << ");\n"; } } - stream << " TraceLoggingWrite(" << provider << ", \"" << name << "\""; + stream << " TraceLoggingWrite(" << provar << ", \"" << name << "\""; for (const Tracepoint::Field &field : tracepoint.fields) { stream << ",\n"; @@ -217,10 +203,56 @@ static void writeWrapper(QTextStream &stream, const Tracepoint &tracepoint, stream << "inline bool trace_" << name << "_enabled()\n" << "{\n" - << " return TraceLoggingProviderEnabled(" << provider << ", 0, 0);\n" + << " return TraceLoggingProviderEnabled(" << provar << ", 0, 0);\n" << "}\n"; } +static void writeEnumConverter(QTextStream &stream, const TraceEnum &enumeration) +{ + stream << "inline QString trace_convert_" << typeToTypeName(enumeration.name) << "(" << enumeration.name << " val)\n"; + stream << "{\n"; + for (const auto &v : enumeration.values) { + if (v.range != 0) { + stream << " if (val >= " << v.value << " && val <= " << v.range << ")\n" + << " return QStringLiteral(\"" << v.name << " + \") + QString::number((int)val - " << v.value << ");\n"; + } + } + stream << "\n QString ret;\n switch (val) {\n"; + + QList<int> handledValues; + for (const auto &v : enumeration.values) { + if (v.range == 0 && !handledValues.contains(v.value)) { + stream << " case " << v.value << ": ret = QStringLiteral(\"" + << aggregateListValues(v.value, enumeration.values) << "\"); break;\n"; + handledValues.append(v.value); + } + } + + stream << " }\n return ret;\n}\n"; +} + +static void writeFlagConverter(QTextStream &stream, const TraceFlags &flag) +{ + stream << "inline QString trace_convert_" << typeToTypeName(flag.name) << "(" << flag.name << " val)\n"; + stream << "{\n QString ret;\n"; + for (const auto &v : flag.values) { + if (v.value == 0) { + stream << " if (val == 0)\n return QStringLiteral(\"" + << aggregateListValues(v.value, flag.values) << "\");\n"; + break; + } + } + QList<int> handledValues; + for (const auto &v : flag.values) { + if (v.value != 0 && !handledValues.contains(v.value)) { + stream << " if (val & " << (1 << (v.value - 1)) + << ") { if (ret.length()) ret += QLatin1Char(\'|\'); ret += QStringLiteral(\"" << v.name << "\"); }\n"; + handledValues.append(v.value); + } + } + stream << " return ret;\n}\n"; +} + static void writeTracepoints(QTextStream &stream, const Provider &provider) { if (provider.tracepoints.isEmpty()) @@ -233,8 +265,14 @@ static void writeTracepoints(QTextStream &stream, const Provider &provider) << "QT_BEGIN_NAMESPACE\n" << "namespace QtPrivate {\n"; + for (const auto &enumeration : provider.enumerations) + writeEnumConverter(stream, enumeration); + + for (const auto &flag : provider.flags) + writeFlagConverter(stream, flag); + for (const Tracepoint &t : provider.tracepoints) - writeWrapper(stream, t, provider.name); + writeWrapper(stream, provider, t, provider.name); stream << "} // namespace QtPrivate\n" << "QT_END_NAMESPACE\n" diff --git a/src/tools/tracegen/etw.h b/src/tools/tracegen/etw.h index 5fc9b57eaa..88508e2034 100644 --- a/src/tools/tracegen/etw.h +++ b/src/tools/tracegen/etw.h @@ -1,41 +1,5 @@ -/**************************************************************************** -** -** Copyright (C) 2017 Klarälvdalens Datakonsult AB, a KDAB Group company, info@kdab.com, author Rafael Roquetto <rafael.roquetto@kdab.com> -** Contact: https://www.qt.io/licensing/ -** -** This file is part of the tools applications of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:LGPL$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. For licensing terms -** and conditions see https://www.qt.io/terms-conditions. For further -** information use the contact form at https://www.qt.io/contact-us. -** -** GNU Lesser General Public License Usage -** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 3 as published by the Free Software -** Foundation and appearing in the file LICENSE.LGPL3 included in the -** packaging of this file. Please review the following information to -** ensure the GNU Lesser General Public License version 3 requirements -** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 2.0 or (at your option) the GNU General -** Public license version 3 or any later version approved by the KDE Free -** Qt Foundation. The licenses are as published by the Free Software -** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 -** included in the packaging of this file. Please review the following -** information to ensure the GNU General Public License requirements will -** be met: https://www.gnu.org/licenses/gpl-2.0.html and -** https://www.gnu.org/licenses/gpl-3.0.html. -** -** $QT_END_LICENSE$ -** -****************************************************************************/ +// Copyright (C) 2017 Klarälvdalens Datakonsult AB, a KDAB Group company, info@kdab.com, author Rafael Roquetto <rafael.roquetto@kdab.com> +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0 #ifndef ETW_H #define ETW_H diff --git a/src/tools/tracegen/helpers.cpp b/src/tools/tracegen/helpers.cpp index 8ffc088fed..0ea5848493 100644 --- a/src/tools/tracegen/helpers.cpp +++ b/src/tools/tracegen/helpers.cpp @@ -1,52 +1,33 @@ -/**************************************************************************** -** -** Copyright (C) 2017 Klarälvdalens Datakonsult AB, a KDAB Group company, info@kdab.com, author Rafael Roquetto <rafael.roquetto@kdab.com> -** Contact: https://www.qt.io/licensing/ -** -** This file is part of the tools applications of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:LGPL$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. For licensing terms -** and conditions see https://www.qt.io/terms-conditions. For further -** information use the contact form at https://www.qt.io/contact-us. -** -** GNU Lesser General Public License Usage -** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 3 as published by the Free Software -** Foundation and appearing in the file LICENSE.LGPL3 included in the -** packaging of this file. Please review the following information to -** ensure the GNU Lesser General Public License version 3 requirements -** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 2.0 or (at your option) the GNU General -** Public license version 3 or any later version approved by the KDE Free -** Qt Foundation. The licenses are as published by the Free Software -** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 -** included in the packaging of this file. Please review the following -** information to ensure the GNU General Public License requirements will -** be met: https://www.gnu.org/licenses/gpl-2.0.html and -** https://www.gnu.org/licenses/gpl-3.0.html. -** -** $QT_END_LICENSE$ -** -****************************************************************************/ +// Copyright (C) 2017 Klarälvdalens Datakonsult AB, a KDAB Group company, info@kdab.com, author Rafael Roquetto <rafael.roquetto@kdab.com> +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0 #include "helpers.h" #include <qdebug.h> +using namespace Qt::StringLiterals; + +void writeCommonPrologue(QTextStream &stream) +{ + stream << R"CPP( +#ifndef Q_TRACEPOINT +#error "Q_TRACEPOINT not set for the module, Q_TRACE not enabled." +#endif +)CPP"; +} + +QString typeToTypeName(const QString &name) +{ + QString ret = name; + return ret.replace(QStringLiteral("::"), QStringLiteral("_")); +} + QString includeGuard(const QString &filename) { QString guard = filename.toUpper(); for (int i = 0; i < guard.size(); ++i) { if (!guard.at(i).isLetterOrNumber()) - guard[i] = QLatin1Char('_'); + guard[i] = u'_'; } return guard; @@ -60,7 +41,7 @@ static QString joinArguments(const QList<Tracepoint::Argument> &args, T joinFunc for (const Tracepoint::Argument &arg : args) { if (!first) - ret += QLatin1String(", "); + ret += ", "_L1; ret += joinFunction(arg); @@ -77,14 +58,56 @@ QString formatFunctionSignature(const QList<Tracepoint::Argument> &args) }); } -QString formatParameterList(const QList<Tracepoint::Argument> &args, ParamType type) +QString formatParameterList(const Provider &provider, const QList<Tracepoint::Argument> &args, const QList<Tracepoint::Field> &fields, ParamType type) { if (type == LTTNG) { QString ret; - for (const Tracepoint::Argument &arg : args) - ret += QLatin1String(", ") + arg.name; + for (int i = 0; i < args.size(); i++) { + const Tracepoint::Argument &arg = args[i]; + const Tracepoint::Field &field = fields[i]; + if (field.backendType == Tracepoint::Field::FlagType) + ret += ", trace_convert_"_L1 + typeToTypeName(arg.type) + "("_L1 + arg.name + ")"_L1; + else + ret += ", "_L1 + arg.name; + } + return ret; + } + + auto findEnumeration = [](const QList<TraceEnum> &enums, const QString &name) { + for (const auto &e : enums) { + if (e.name == name) + return e; + } + return TraceEnum(); + }; + + if (type == CTF) { + QString ret; + for (int i = 0; i < args.size(); i++) { + const Tracepoint::Argument &arg = args[i]; + const Tracepoint::Field &field = fields[i]; + if (arg.arrayLen > 1) { + ret += ", trace::toByteArrayFromArray("_L1 + arg.name + ", "_L1 + QString::number(arg.arrayLen) + ") "_L1; + } else if (field.backendType == Tracepoint::Field::EnumeratedType) { + const TraceEnum &e = findEnumeration(provider.enumerations, arg.type); + QString integerType; + if (e.valueSize == 8) + integerType = QStringLiteral("quint8"); + else if (e.valueSize == 16) + integerType = QStringLiteral("quint16"); + else + integerType = QStringLiteral("quint32"); + ret += ", trace::toByteArrayFromEnum<"_L1 + integerType + ">("_L1 + arg.name + ")"_L1; + } else if (field.backendType == Tracepoint::Field::FlagType) { + ret += ", trace::toByteArrayFromFlags("_L1 + arg.name + ")"_L1; + } else if (field.backendType == Tracepoint::Field::String) { + ret += ", trace::toByteArrayFromCString("_L1 + arg.name + ")"_L1; + } else { + ret += ", "_L1 + arg.name; + } + } return ret; } diff --git a/src/tools/tracegen/helpers.h b/src/tools/tracegen/helpers.h index 8acf6e2292..ea6db016a6 100644 --- a/src/tools/tracegen/helpers.h +++ b/src/tools/tracegen/helpers.h @@ -1,41 +1,5 @@ -/**************************************************************************** -** -** Copyright (C) 2017 Klarälvdalens Datakonsult AB, a KDAB Group company, info@kdab.com, author Rafael Roquetto <rafael.roquetto@kdab.com> -** Contact: https://www.qt.io/licensing/ -** -** This file is part of the tools applications of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:LGPL$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. For licensing terms -** and conditions see https://www.qt.io/terms-conditions. For further -** information use the contact form at https://www.qt.io/contact-us. -** -** GNU Lesser General Public License Usage -** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 3 as published by the Free Software -** Foundation and appearing in the file LICENSE.LGPL3 included in the -** packaging of this file. Please review the following information to -** ensure the GNU Lesser General Public License version 3 requirements -** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 2.0 or (at your option) the GNU General -** Public license version 3 or any later version approved by the KDE Free -** Qt Foundation. The licenses are as published by the Free Software -** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 -** included in the packaging of this file. Please review the following -** information to ensure the GNU General Public License requirements will -** be met: https://www.gnu.org/licenses/gpl-2.0.html and -** https://www.gnu.org/licenses/gpl-3.0.html. -** -** $QT_END_LICENSE$ -** -****************************************************************************/ +// Copyright (C) 2017 Klarälvdalens Datakonsult AB, a KDAB Group company, info@kdab.com, author Rafael Roquetto <rafael.roquetto@kdab.com> +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0 #ifndef HELPERS_H #define HELPERS_H @@ -44,14 +8,30 @@ #include <qlist.h> #include <qstring.h> +#include <qtextstream.h> enum ParamType { LTTNG, - ETW + ETW, + CTF }; +QString typeToTypeName(const QString &type); QString includeGuard(const QString &filename); QString formatFunctionSignature(const QList<Tracepoint::Argument> &args); -QString formatParameterList(const QList<Tracepoint::Argument> &args, ParamType type); +QString formatParameterList(const Provider &provider, const QList<Tracepoint::Argument> &args, const QList<Tracepoint::Field> &fields, ParamType type); + +void writeCommonPrologue(QTextStream &stream); + +template <typename T> +static QString aggregateListValues(int value, const QList<T> &list) +{ + QStringList values; + for (const T &l : list) { + if (l.value == value) + values << l.name; + } + return values.join(QLatin1Char('_')); +} #endif // HELPERS_H diff --git a/src/tools/tracegen/lttng.cpp b/src/tools/tracegen/lttng.cpp index 9a8dfc9f4a..9711570874 100644 --- a/src/tools/tracegen/lttng.cpp +++ b/src/tools/tracegen/lttng.cpp @@ -1,41 +1,5 @@ -/**************************************************************************** -** -** Copyright (C) 2017 Klarälvdalens Datakonsult AB, a KDAB Group company, info@kdab.com, author Rafael Roquetto <rafael.roquetto@kdab.com> -** Contact: https://www.qt.io/licensing/ -** -** This file is part of the tools applications of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:LGPL$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. For licensing terms -** and conditions see https://www.qt.io/terms-conditions. For further -** information use the contact form at https://www.qt.io/contact-us. -** -** GNU Lesser General Public License Usage -** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 3 as published by the Free Software -** Foundation and appearing in the file LICENSE.LGPL3 included in the -** packaging of this file. Please review the following information to -** ensure the GNU Lesser General Public License version 3 requirements -** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 2.0 or (at your option) the GNU General -** Public license version 3 or any later version approved by the KDE Free -** Qt Foundation. The licenses are as published by the Free Software -** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 -** included in the packaging of this file. Please review the following -** information to ensure the GNU General Public License requirements will -** be met: https://www.gnu.org/licenses/gpl-2.0.html and -** https://www.gnu.org/licenses/gpl-3.0.html. -** -** $QT_END_LICENSE$ -** -****************************************************************************/ +// Copyright (C) 2017 Klarälvdalens Datakonsult AB, a KDAB Group company, info@kdab.com, author Rafael Roquetto <rafael.roquetto@kdab.com> +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0 #include "lttng.h" #include "provider.h" @@ -48,23 +12,37 @@ #include <qtextstream.h> #include <qdebug.h> -static void writeCtfMacro(QTextStream &stream, const Tracepoint::Field &field) +static void writeCtfMacro(QTextStream &stream, const Provider &provider, const Tracepoint::Field &field) { const QString ¶mType = field.paramType; const QString &name = field.name; const QString &seqLen = field.seqLen; const int arrayLen = field.arrayLen; - switch (field.backendType) { - case Tracepoint::Field::Array: - stream << "ctf_array(" <<paramType << ", " - << name << ", " << name << ", " << arrayLen << ")"; + if (arrayLen > 0) { + if (paramType == QStringLiteral("double") || paramType == QStringLiteral("float")) { + const char *newline = nullptr; + for (int i = 0; i < arrayLen; i++) { + stream << newline; + stream << "ctf_float(" <<paramType << ", " << name << "_" << QString::number(i) << ", " + << name << "[" << QString::number(i) << "]" << ")"; + newline = "\n "; + } + + } else { + stream << "ctf_array(" <<paramType << ", " + << name << ", " << name << ", " << arrayLen << ")"; + } return; + } + + switch (field.backendType) { case Tracepoint::Field::Sequence: stream << "ctf_sequence(" << paramType << ", " << name << ", " << name << ", unsigned int, " << seqLen << ")"; return; + case Tracepoint::Field::Boolean: case Tracepoint::Field::Integer: stream << "ctf_integer(" << paramType << ", " << name << ", " << name << ")"; return; @@ -79,33 +57,51 @@ static void writeCtfMacro(QTextStream &stream, const Tracepoint::Field &field) stream << "ctf_string(" << name << ", " << name << ")"; return; case Tracepoint::Field::QtString: - stream << "ctf_sequence(const ushort, " << name << ", " - << name << ".utf16(), unsigned int, " << name << ".size())"; + stream << "ctf_string(" << name << ", " << name << ".toUtf8().constData())"; return; case Tracepoint::Field::QtByteArray: stream << "ctf_sequence(const char, " << name << ", " << name << ".constData(), unsigned int, " << name << ".size())"; return; case Tracepoint::Field::QtUrl: - stream << "ctf_sequence(const char, " << name << ", " - << name << ".toEncoded().constData(), unsigned int, " - << name << ".toEncoded().size())"; + stream << "ctf_string(" << name << ", " << name << ".toString().toUtf8().constData())"; return; case Tracepoint::Field::QtRect: - stream << "ctf_integer(int, x, " << name << ".x()) " - << "ctf_integer(int, y, " << name << ".y()) " - << "ctf_integer(int, width, " << name << ".width()) " - << "ctf_integer(int, height, " << name << ".height()) "; + stream << "ctf_integer(int, QRect_" << name << "_x, " << name << ".x()) " + << "ctf_integer(int, QRect_" << name << "_y, " << name << ".y()) " + << "ctf_integer(int, QRect_" << name << "_width, " << name << ".width()) " + << "ctf_integer(int, QRect_" << name << "_height, " << name << ".height()) "; + return; + case Tracepoint::Field::QtSizeF: + stream << "ctf_float(double, QSizeF_" << name << "_width, " << name << ".width()) " + << "ctf_float(double, QSizeF_" << name << "_height, " << name << ".height()) "; + return; + case Tracepoint::Field::QtRectF: + stream << "ctf_float(double, QRectF_" << name << "_x, " << name << ".x()) " + << "ctf_float(double, QRectF_" << name << "_y, " << name << ".y()) " + << "ctf_float(double, QRectF_" << name << "_width, " << name << ".width()) " + << "ctf_float(double, QRectF_" << name << "_height, " << name << ".height()) "; + return; + case Tracepoint::Field::QtSize: + stream << "ctf_integer(int, QSize_" << name << "_width, " << name << ".width()) " + << "ctf_integer(int, QSize_" << name << "_height, " << name << ".height()) "; + return; + case Tracepoint::Field::EnumeratedType: + stream << "ctf_enum(" << provider.name << ", " << typeToTypeName(paramType) << ", int, " << name << ", " << name << ") "; + return; + case Tracepoint::Field::FlagType: + stream << "ctf_sequence(const char , " << name << ", " + << name << ".constData(), unsigned int, " << name << ".size())"; return; case Tracepoint::Field::Unknown: - justified_worry("Cannot deduce CTF type for '%s %s'", qPrintable(paramType), - qPrintable(name)); + panic("Cannot deduce CTF type for '%s %s", qPrintable(paramType), qPrintable(name)); break; } } static void writePrologue(QTextStream &stream, const QString &fileName, const Provider &provider) { + writeCommonPrologue(stream); const QString guard = includeGuard(fileName); stream << "#undef TRACEPOINT_PROVIDER\n"; @@ -117,7 +113,7 @@ static void writePrologue(QTextStream &stream, const QString &fileName, const Pr stream << qtHeaders(); stream << "\n"; if (!provider.prefixText.isEmpty()) - stream << provider.prefixText.join(QLatin1Char('\n')) << "\n\n"; + stream << provider.prefixText.join(u'\n') << "\n\n"; stream << "#endif\n\n"; /* the first guard is the usual one, the second is required @@ -147,12 +143,12 @@ static void writeEpilogue(QTextStream &stream, const QString &fileName) } static void writeWrapper(QTextStream &stream, - const Tracepoint &tracepoint, const QString &providerName) + const Tracepoint &tracepoint, const Provider &provider) { const QString argList = formatFunctionSignature(tracepoint.args); - const QString paramList = formatParameterList(tracepoint.args, LTTNG); + const QString paramList = formatParameterList(provider, tracepoint.args, tracepoint.fields, LTTNG); const QString &name = tracepoint.name; - const QString includeGuard = QStringLiteral("TP_%1_%2").arg(providerName).arg(name).toUpper(); + const QString includeGuard = QStringLiteral("TP_%1_%2").arg(provider.name).arg(name).toUpper(); /* prevents the redefinion of the inline wrapper functions * once LTTNG recursively includes this header file @@ -165,17 +161,17 @@ static void writeWrapper(QTextStream &stream, stream << "inline void trace_" << name << "(" << argList << ")\n" << "{\n" - << " tracepoint(" << providerName << ", " << name << paramList << ");\n" + << " tracepoint(" << provider.name << ", " << name << paramList << ");\n" << "}\n"; stream << "inline void do_trace_" << name << "(" << argList << ")\n" << "{\n" - << " do_tracepoint(" << providerName << ", " << name << paramList << ");\n" + << " do_tracepoint(" << provider.name << ", " << name << paramList << ");\n" << "}\n"; stream << "inline bool trace_" << name << "_enabled()\n" << "{\n" - << " return tracepoint_enabled(" << providerName << ", " << name << ");\n" + << " return tracepoint_enabled(" << provider.name << ", " << name << ");\n" << "}\n"; stream << "} // namespace QtPrivate\n" @@ -183,7 +179,7 @@ static void writeWrapper(QTextStream &stream, << "#endif // " << includeGuard << "\n\n"; } -static void writeTracepoint(QTextStream &stream, +static void writeTracepoint(QTextStream &stream, const Provider &provider, const Tracepoint &tracepoint, const QString &providerName) { stream << "TRACEPOINT_EVENT(\n" @@ -193,8 +189,13 @@ static void writeTracepoint(QTextStream &stream, const char *comma = nullptr; - for (const Tracepoint::Argument &arg : tracepoint.args) { - stream << comma << arg.type << ", " << arg.name; + for (int i = 0; i < tracepoint.args.size(); i++) { + const auto &arg = tracepoint.args[i]; + const auto &field = tracepoint.fields[i]; + if (field.backendType == Tracepoint::Field::FlagType) + stream << comma << "QByteArray, " << arg.name; + else + stream << comma << arg.type << ", " << arg.name; comma = ", "; } @@ -205,18 +206,82 @@ static void writeTracepoint(QTextStream &stream, for (const Tracepoint::Field &f : tracepoint.fields) { stream << newline; - writeCtfMacro(stream, f); + writeCtfMacro(stream, provider, f); newline = "\n "; } stream << ")\n)\n\n"; } +static void writeEnums(QTextStream &stream, const Provider &provider) +{ + for (const auto &e : provider.enumerations) { + stream << "TRACEPOINT_ENUM(\n" + << " " << provider.name << ",\n" + << " " << typeToTypeName(e.name) << ",\n" + << " TP_ENUM_VALUES(\n"; + QList<int> handledValues; + for (const auto &v : e.values) { + if (v.range > 0) { + stream << " ctf_enum_range(\"" << v.name << "\", " << v.value << ", " << v.range << ")\n"; + } else if (!handledValues.contains(v.value)) { + stream << " ctf_enum_value(\"" << aggregateListValues(v.value, e.values) << "\", " << v.value << ")\n"; + handledValues.append(v.value); + } + } + stream << " )\n)\n\n"; + } +} + +static void writeFlags(QTextStream &stream, const Provider &provider) +{ + for (const auto &f : provider.flags) { + stream << "TRACEPOINT_ENUM(\n" + << " " << provider.name << ",\n" + << " " << typeToTypeName(f.name) << ",\n" + << " TP_ENUM_VALUES(\n"; + QList<int> handledValues; + for (const auto &v : f.values) { + if (!handledValues.contains(v.value)) { + stream << " ctf_enum_value(\"" << aggregateListValues(v.value, f.values) << "\", " << v.value << ")\n"; + handledValues.append(v.value); + } + } + stream << " )\n)\n\n"; + } + + // converters + const QString includeGuard = QStringLiteral("TP_%1_CONVERTERS").arg(provider.name).toUpper(); + stream << "\n" + << "#ifndef " << includeGuard << "\n" + << "#define " << includeGuard << "\n"; + stream << "QT_BEGIN_NAMESPACE\n"; + stream << "namespace QtPrivate {\n"; + for (const auto &f : provider.flags) { + stream << "inline QByteArray trace_convert_" << typeToTypeName(f.name) << "(" << f.name << " val)\n"; + stream << "{\n"; + stream << " QByteArray ret;\n"; + stream << " if (val == 0) { ret.append((char)0); return ret; }\n"; + + for (const auto &v : f.values) { + if (!v.value) + continue; + stream << " if (val & " << (1 << (v.value - 1)) << ") { ret.append((char)" << v.value << "); };\n"; + } + stream << " return ret;\n"; + stream << "}\n"; + + } + stream << "} // namespace QtPrivate\n" + << "QT_END_NAMESPACE\n\n" + << "#endif // " << includeGuard << "\n\n"; +} + static void writeTracepoints(QTextStream &stream, const Provider &provider) { for (const Tracepoint &t : provider.tracepoints) { - writeTracepoint(stream, t, provider.name); - writeWrapper(stream, t, provider.name); + writeTracepoint(stream, provider, t, provider.name); + writeWrapper(stream, t, provider); } } @@ -227,6 +292,9 @@ void writeLttng(QFile &file, const Provider &provider) const QString fileName = QFileInfo(file.fileName()).fileName(); writePrologue(stream, fileName, provider); + writeEnums(stream, provider); + writeFlags(stream, provider); writeTracepoints(stream, provider); writeEpilogue(stream, fileName); } + diff --git a/src/tools/tracegen/lttng.h b/src/tools/tracegen/lttng.h index 0307b375bc..c36c70a1d4 100644 --- a/src/tools/tracegen/lttng.h +++ b/src/tools/tracegen/lttng.h @@ -1,41 +1,5 @@ -/**************************************************************************** -** -** Copyright (C) 2017 Klarälvdalens Datakonsult AB, a KDAB Group company, info@kdab.com, author Rafael Roquetto <rafael.roquetto@kdab.com> -** Contact: https://www.qt.io/licensing/ -** -** This file is part of the tools applications of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:LGPL$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. For licensing terms -** and conditions see https://www.qt.io/terms-conditions. For further -** information use the contact form at https://www.qt.io/contact-us. -** -** GNU Lesser General Public License Usage -** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 3 as published by the Free Software -** Foundation and appearing in the file LICENSE.LGPL3 included in the -** packaging of this file. Please review the following information to -** ensure the GNU Lesser General Public License version 3 requirements -** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 2.0 or (at your option) the GNU General -** Public license version 3 or any later version approved by the KDE Free -** Qt Foundation. The licenses are as published by the Free Software -** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 -** included in the packaging of this file. Please review the following -** information to ensure the GNU General Public License requirements will -** be met: https://www.gnu.org/licenses/gpl-2.0.html and -** https://www.gnu.org/licenses/gpl-3.0.html. -** -** $QT_END_LICENSE$ -** -****************************************************************************/ +// Copyright (C) 2017 Klarälvdalens Datakonsult AB, a KDAB Group company, info@kdab.com, author Rafael Roquetto <rafael.roquetto@kdab.com> +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0 #ifndef LTTNG_H #define LTTNG_H diff --git a/src/tools/tracegen/panic.cpp b/src/tools/tracegen/panic.cpp index ac95b2e9e8..fa4e6b3ee3 100644 --- a/src/tools/tracegen/panic.cpp +++ b/src/tools/tracegen/panic.cpp @@ -1,41 +1,5 @@ -/**************************************************************************** -** -** Copyright (C) 2017 Klarälvdalens Datakonsult AB, a KDAB Group company, info@kdab.com, author Rafael Roquetto <rafael.roquetto@kdab.com> -** Contact: https://www.qt.io/licensing/ -** -** This file is part of the tools applications of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:LGPL$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. For licensing terms -** and conditions see https://www.qt.io/terms-conditions. For further -** information use the contact form at https://www.qt.io/contact-us. -** -** GNU Lesser General Public License Usage -** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 3 as published by the Free Software -** Foundation and appearing in the file LICENSE.LGPL3 included in the -** packaging of this file. Please review the following information to -** ensure the GNU Lesser General Public License version 3 requirements -** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 2.0 or (at your option) the GNU General -** Public license version 3 or any later version approved by the KDE Free -** Qt Foundation. The licenses are as published by the Free Software -** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 -** included in the packaging of this file. Please review the following -** information to ensure the GNU General Public License requirements will -** be met: https://www.gnu.org/licenses/gpl-2.0.html and -** https://www.gnu.org/licenses/gpl-3.0.html. -** -** $QT_END_LICENSE$ -** -****************************************************************************/ +// Copyright (C) 2017 Klarälvdalens Datakonsult AB, a KDAB Group company, info@kdab.com, author Rafael Roquetto <rafael.roquetto@kdab.com> +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0 #include "panic.h" @@ -57,16 +21,3 @@ void panic(const char *fmt, ...) exit(EXIT_FAILURE); } - -void justified_worry(const char *fmt, ...) -{ - va_list ap; - - fprintf(stderr, "tracegen: warning: "); - - va_start(ap, fmt); - vfprintf(stderr, fmt, ap); - va_end(ap); - - fputc('\n', stderr); -} diff --git a/src/tools/tracegen/panic.h b/src/tools/tracegen/panic.h index 58e56c0116..ee635a8aeb 100644 --- a/src/tools/tracegen/panic.h +++ b/src/tools/tracegen/panic.h @@ -1,46 +1,9 @@ -/**************************************************************************** -** -** Copyright (C) 2017 Klarälvdalens Datakonsult AB, a KDAB Group company, info@kdab.com, author Rafael Roquetto <rafael.roquetto@kdab.com> -** Contact: https://www.qt.io/licensing/ -** -** This file is part of the tools applications of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:LGPL$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. For licensing terms -** and conditions see https://www.qt.io/terms-conditions. For further -** information use the contact form at https://www.qt.io/contact-us. -** -** GNU Lesser General Public License Usage -** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 3 as published by the Free Software -** Foundation and appearing in the file LICENSE.LGPL3 included in the -** packaging of this file. Please review the following information to -** ensure the GNU Lesser General Public License version 3 requirements -** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 2.0 or (at your option) the GNU General -** Public license version 3 or any later version approved by the KDE Free -** Qt Foundation. The licenses are as published by the Free Software -** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 -** included in the packaging of this file. Please review the following -** information to ensure the GNU General Public License requirements will -** be met: https://www.gnu.org/licenses/gpl-2.0.html and -** https://www.gnu.org/licenses/gpl-3.0.html. -** -** $QT_END_LICENSE$ -** -****************************************************************************/ +// Copyright (C) 2017 Klarälvdalens Datakonsult AB, a KDAB Group company, info@kdab.com, author Rafael Roquetto <rafael.roquetto@kdab.com> +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0 #ifndef PANIC_H #define PANIC_H void panic(const char *fmt, ...); -void justified_worry(const char *fmt, ...); #endif // PANIC_H diff --git a/src/tools/tracegen/provider.cpp b/src/tools/tracegen/provider.cpp index 7984fa12a7..bdd669c9cd 100644 --- a/src/tools/tracegen/provider.cpp +++ b/src/tools/tracegen/provider.cpp @@ -1,41 +1,5 @@ -/**************************************************************************** -** -** Copyright (C) 2017 Klarälvdalens Datakonsult AB, a KDAB Group company, info@kdab.com, author Rafael Roquetto <rafael.roquetto@kdab.com> -** Contact: https://www.qt.io/licensing/ -** -** This file is part of the tools applications of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:LGPL$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. For licensing terms -** and conditions see https://www.qt.io/terms-conditions. For further -** information use the contact form at https://www.qt.io/contact-us. -** -** GNU Lesser General Public License Usage -** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 3 as published by the Free Software -** Foundation and appearing in the file LICENSE.LGPL3 included in the -** packaging of this file. Please review the following information to -** ensure the GNU Lesser General Public License version 3 requirements -** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 2.0 or (at your option) the GNU General -** Public license version 3 or any later version approved by the KDE Free -** Qt Foundation. The licenses are as published by the Free Software -** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 -** included in the packaging of this file. Please review the following -** information to ensure the GNU General Public License requirements will -** be met: https://www.gnu.org/licenses/gpl-2.0.html and -** https://www.gnu.org/licenses/gpl-3.0.html. -** -** $QT_END_LICENSE$ -** -****************************************************************************/ +// Copyright (C) 2017 Klarälvdalens Datakonsult AB, a KDAB Group company, info@kdab.com, author Rafael Roquetto <rafael.roquetto@kdab.com> +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0 #include "provider.h" #include "panic.h" @@ -45,6 +9,9 @@ #include <qtextstream.h> #include <qregularexpression.h> #include <qstring.h> +#include <qtpreprocessorsupport.h> + +using namespace Qt::StringLiterals; #ifdef TRACEGEN_DEBUG #include <qdebug.h> @@ -129,89 +96,115 @@ static QString removeBraces(QString type) return type.remove(rx); } -static Tracepoint::Field::BackendType backendType(QString rawType) +#define TYPEDATA_ENTRY(type, backendType) \ +{ QT_STRINGIFY(type), backendType } + +static Tracepoint::Field::Type backendType(QString rawType) { - static const struct { + static const struct TypeData { const char *type; - Tracepoint::Field::BackendType backendType; + Tracepoint::Field::Type backendType; } typeTable[] = { - { "bool", Tracepoint::Field::Integer }, - { "short_int", Tracepoint::Field::Integer }, - { "signed_short", Tracepoint::Field::Integer }, - { "signed_short_int", Tracepoint::Field::Integer }, - { "unsigned_short", Tracepoint::Field::Integer }, - { "unsigned_short_int", Tracepoint::Field::Integer }, - { "int", Tracepoint::Field::Integer }, - { "signed", Tracepoint::Field::Integer }, - { "signed_int", Tracepoint::Field::Integer }, - { "unsigned", Tracepoint::Field::Integer }, - { "unsigned_int", Tracepoint::Field::Integer }, - { "long", Tracepoint::Field::Integer }, - { "long_int", Tracepoint::Field::Integer }, - { "signed_long", Tracepoint::Field::Integer }, - { "signed_long_int", Tracepoint::Field::Integer }, - { "unsigned_long", Tracepoint::Field::Integer }, - { "unsigned_long_int", Tracepoint::Field::Integer }, - { "long_long", Tracepoint::Field::Integer }, - { "long_long_int", Tracepoint::Field::Integer }, - { "signed_long_long", Tracepoint::Field::Integer }, - { "signed_long_long_int", Tracepoint::Field::Integer }, - { "unsigned_long_long", Tracepoint::Field::Integer }, - { "char", Tracepoint::Field::Integer }, - { "intptr_t", Tracepoint::Field::IntegerHex }, - { "uintptr_t", Tracepoint::Field::IntegerHex }, - { "std::intptr_t", Tracepoint::Field::IntegerHex }, - { "std::uintptr_t", Tracepoint::Field::IntegerHex }, - { "float", Tracepoint::Field::Float }, - { "double", Tracepoint::Field::Float }, - { "long_double", Tracepoint::Field::Float }, - { "QString", Tracepoint::Field::QtString }, - { "QByteArray", Tracepoint::Field::QtByteArray }, - { "QUrl", Tracepoint::Field::QtUrl }, - { "QRect", Tracepoint::Field::QtRect } + TYPEDATA_ENTRY(short_int, Tracepoint::Field::Integer), + TYPEDATA_ENTRY(signed_short, Tracepoint::Field::Integer), + TYPEDATA_ENTRY(signed_short_int, Tracepoint::Field::Integer), + TYPEDATA_ENTRY(unsigned_short, Tracepoint::Field::Integer), + TYPEDATA_ENTRY(unsigned_short_int, Tracepoint::Field::Integer), + TYPEDATA_ENTRY(unsigned_int, Tracepoint::Field::Integer), + TYPEDATA_ENTRY(signed_int, Tracepoint::Field::Integer), + TYPEDATA_ENTRY(long_int, Tracepoint::Field::Integer), + TYPEDATA_ENTRY(signed_long, Tracepoint::Field::Integer), + TYPEDATA_ENTRY(signed_long_int, Tracepoint::Field::Integer), + TYPEDATA_ENTRY(unsigned_long, Tracepoint::Field::Integer), + TYPEDATA_ENTRY(unsigned_long_int, Tracepoint::Field::Integer), + TYPEDATA_ENTRY(long_long, Tracepoint::Field::Integer), + TYPEDATA_ENTRY(long_long_int, Tracepoint::Field::Integer), + TYPEDATA_ENTRY(signed_long_long, Tracepoint::Field::Integer), + TYPEDATA_ENTRY(signed_long_long_int, Tracepoint::Field::Integer), + TYPEDATA_ENTRY(unsigned_long_long, Tracepoint::Field::Integer), + TYPEDATA_ENTRY(bool, Tracepoint::Field::Boolean), + TYPEDATA_ENTRY(int, Tracepoint::Field::Integer), + TYPEDATA_ENTRY(signed, Tracepoint::Field::Integer), + TYPEDATA_ENTRY(unsigned, Tracepoint::Field::Integer), + TYPEDATA_ENTRY(long, Tracepoint::Field::Integer), + TYPEDATA_ENTRY(qint64, Tracepoint::Field::Integer), + TYPEDATA_ENTRY(char, Tracepoint::Field::Integer), + TYPEDATA_ENTRY(intptr_t, Tracepoint::Field::IntegerHex), + TYPEDATA_ENTRY(uintptr_t, Tracepoint::Field::IntegerHex), + TYPEDATA_ENTRY(std::intptr_t, Tracepoint::Field::IntegerHex), + TYPEDATA_ENTRY(std::uintptr_t, Tracepoint::Field::IntegerHex), + TYPEDATA_ENTRY(float, Tracepoint::Field::Float), + TYPEDATA_ENTRY(double, Tracepoint::Field::Float), + TYPEDATA_ENTRY(long double, Tracepoint::Field::Float), + TYPEDATA_ENTRY(QString, Tracepoint::Field::QtString), + TYPEDATA_ENTRY(QByteArray, Tracepoint::Field::QtByteArray), + TYPEDATA_ENTRY(QUrl, Tracepoint::Field::QtUrl), + TYPEDATA_ENTRY(QRect, Tracepoint::Field::QtRect), + TYPEDATA_ENTRY(QSize, Tracepoint::Field::QtSize), + TYPEDATA_ENTRY(QRectF, Tracepoint::Field::QtRectF), + TYPEDATA_ENTRY(QSizeF, Tracepoint::Field::QtSizeF) }; auto backendType = [](const QString &rawType) { static const size_t tableSize = sizeof (typeTable) / sizeof (typeTable[0]); for (size_t i = 0; i < tableSize; ++i) { - if (rawType == QLatin1String(typeTable[i].type)) - return typeTable[i].backendType; + if (rawType == QLatin1StringView(typeTable[i].type)) + return typeTable[i]; } - return Tracepoint::Field::Unknown; + TypeData unknown = { nullptr, Tracepoint::Field::Unknown }; + return unknown; }; - if (arrayLength(rawType) > 0) - return Tracepoint::Field::Array; + int arrayLen = arrayLength(rawType); + if (arrayLen > 0) + rawType = removeBraces(rawType); if (!sequenceLength(rawType).isNull()) return Tracepoint::Field::Sequence; static const QRegularExpression constMatch(QStringLiteral("\\bconst\\b")); rawType.remove(constMatch); - rawType.remove(QLatin1Char('&')); + rawType.remove(u'&'); static const QRegularExpression ptrMatch(QStringLiteral("\\s*\\*\\s*")); rawType.replace(ptrMatch, QStringLiteral("_ptr")); rawType = rawType.trimmed(); rawType.replace(QStringLiteral(" "), QStringLiteral("_")); - if (rawType == QLatin1String("char_ptr")) + if (rawType == "char_ptr"_L1) return Tracepoint::Field::String; - if (rawType.endsWith(QLatin1String("_ptr"))) + if (rawType.endsWith("_ptr"_L1)) return Tracepoint::Field::Pointer; - return backendType(rawType); + TypeData d = backendType(rawType); + return d.backendType; } -static Tracepoint parseTracepoint(const QString &name, const QStringList &args, +static Tracepoint parseTracepoint(const Provider &provider, const QString &name, const QStringList &args, const QString &fileName, const int lineNumber) { Tracepoint t; t.name = name; + auto findEnumeration = [](const QList<TraceEnum> &enums, const QString &name) { + for (const auto &e : enums) { + if (e.name == name) + return e; + } + return TraceEnum(); + }; + auto findFlags = [](const QList<TraceFlags> &flags, const QString &name) { + for (const auto &f : flags) { + if (f.name == name) + return f; + } + return TraceFlags(); + }; + + if (args.isEmpty()) return t; @@ -247,14 +240,23 @@ static Tracepoint parseTracepoint(const QString &name, const QStringList &args, t.args << std::move(a); - Tracepoint::Field f; - f.backendType = backendType(type); - f.paramType = removeBraces(type); - f.name = name; - f.arrayLen = arrayLen; - f.seqLen = sequenceLength(type); + Tracepoint::Field field; + const TraceEnum &e = findEnumeration(provider.enumerations, type); + const TraceFlags &f = findFlags(provider.flags, type); + if (!e.name.isEmpty()) { + field.backendType = Tracepoint::Field::EnumeratedType; + field.enumValueSize = e.valueSize; + } else if (!f.name.isEmpty()) { + field.backendType = Tracepoint::Field::FlagType; + } else { + field.backendType = backendType(type); + } + field.paramType = removeBraces(type); + field.name = name; + field.arrayLen = arrayLen; + field.seqLen = sequenceLength(type); - t.fields << std::move(f); + t.fields << std::move(field); ++i; } @@ -262,6 +264,31 @@ static Tracepoint parseTracepoint(const QString &name, const QStringList &args, return t; } +static int minumumValueSize(int min, int max) +{ + if (min < 0) { + if (min >= std::numeric_limits<char>::min() && max <= std::numeric_limits<char>::max()) + return 8; + if (min >= std::numeric_limits<short>::min() && max <= std::numeric_limits<short>::max()) + return 16; + return 32; + } + if (max <= std::numeric_limits<unsigned char>::max()) + return 8; + if (max <= std::numeric_limits<unsigned short>::max()) + return 16; + return 32; +} + +static bool isPow2OrZero(quint32 value) +{ + return (value & (value - 1)) == 0; +} + +static quint32 pow2Log2(quint32 v) { + return 32 - qCountLeadingZeroBits(v); +} + Provider parseProvider(const QString &filename) { QFile f(filename); @@ -272,35 +299,140 @@ Provider parseProvider(const QString &filename) QTextStream s(&f); static const QRegularExpression tracedef(QStringLiteral("^([A-Za-z][A-Za-z0-9_]*)\\((.*)\\)$")); + static const QRegularExpression enumenddef(QStringLiteral("^} ?([A-Za-z][A-Za-z0-9_:]*);")); + static const QRegularExpression enumdef(QStringLiteral("^([A-Za-z][A-Za-z0-9_]*)( *= *([xabcdef0-9]*))?")); + static const QRegularExpression rangedef(QStringLiteral("^RANGE\\(([A-Za-z][A-Za-z0-9_]*) ?, ?([0-9]*) ?... ?([0-9]*) ?\\)")); Provider provider; provider.name = QFileInfo(filename).baseName(); bool parsingPrefixText = false; + bool parsingEnum = false; + bool parsingFlags = false; + TraceEnum currentEnum; + TraceFlags currentFlags; + int currentEnumValue = 0; + int minEnumValue = std::numeric_limits<int>::max(); + int maxEnumValue = std::numeric_limits<int>::min(); for (int lineNumber = 1; !s.atEnd(); ++lineNumber) { QString line = s.readLine().trimmed(); - if (line == QLatin1String("{")) { + if (line == "{"_L1) { parsingPrefixText = true; continue; - } else if (parsingPrefixText && line == QLatin1String("}")) { + } else if (parsingPrefixText && line == "}"_L1) { parsingPrefixText = false; continue; } else if (parsingPrefixText) { provider.prefixText.append(line); continue; + } else if (line == "ENUM {"_L1) { + parsingEnum = true; + continue; + } else if (line == "FLAGS {"_L1) { + parsingFlags = true; + continue; + } else if (line.startsWith("}"_L1) && (parsingEnum || parsingFlags)) { + auto match = enumenddef.match(line); + if (match.hasMatch()) { + if (parsingEnum) { + currentEnum.name = match.captured(1); + currentEnum.valueSize = minumumValueSize(minEnumValue, maxEnumValue); + provider.enumerations.push_back(currentEnum); + currentEnum = TraceEnum(); + parsingEnum = false; + } else { + currentFlags.name = match.captured(1); + provider.flags.push_back(currentFlags); + currentFlags = TraceFlags(); + parsingFlags = false; + } + + minEnumValue = std::numeric_limits<int>::max(); + maxEnumValue = std::numeric_limits<int>::min(); + } else { + panic("Syntax error while processing '%s' line %d:\n" + " '%s' end of enum/flags does not match", + qPrintable(filename), lineNumber, + qPrintable(line)); + } + + continue; } - if (line.isEmpty() || line.startsWith(QLatin1Char('#'))) + if (line.isEmpty() || line.startsWith(u'#')) continue; + if (parsingEnum || parsingFlags) { + auto m = enumdef.match(line); + if (parsingEnum && line.startsWith(QStringLiteral("RANGE"))) { + auto m = rangedef.match(line); + if (m.hasMatch()) { + TraceEnum::EnumValue value; + value.name = m.captured(1); + value.value = m.captured(2).toInt(); + value.range = m.captured(3).toInt(); + currentEnumValue = value.range + 1; + currentEnum.values.push_back(value); + maxEnumValue = qMax(maxEnumValue, value.range); + minEnumValue = qMin(minEnumValue, value.value); + } + } else if (m.hasMatch()) { + if (m.hasCaptured(3)) { + if (parsingEnum) { + TraceEnum::EnumValue value; + value.name = m.captured(1); + value.value = m.captured(3).toInt(); + value.range = 0; + currentEnumValue = value.value + 1; + currentEnum.values.push_back(value); + maxEnumValue = qMax(maxEnumValue, value.value); + minEnumValue = qMin(minEnumValue, value.value); + } else { + TraceFlags::FlagValue value; + value.name = m.captured(1); + if (m.captured(3).startsWith(QStringLiteral("0x"))) + value.value = m.captured(3).toInt(nullptr, 16); + else + value.value = m.captured(3).toInt(); + if (!isPow2OrZero(value.value)) { + printf("Warning: '%s' line %d:\n" + " '%s' flag value is not power of two.\n", + qPrintable(filename), lineNumber, + qPrintable(line)); + } else { + value.value = pow2Log2(value.value); + currentFlags.values.push_back(value); + } + } + } else { + maxEnumValue = qMax(maxEnumValue, currentEnumValue); + minEnumValue = qMin(minEnumValue, currentEnumValue); + if (parsingEnum) { + currentEnum.values.push_back({m.captured(0), currentEnumValue++, 0}); + } else { + panic("Syntax error while processing '%s' line %d:\n" + " '%s' flags value not set", + qPrintable(filename), lineNumber, + qPrintable(line)); + } + } + } else { + panic("Syntax error while processing '%s' line %d:\n" + " '%s' enum/flags does not match", + qPrintable(filename), lineNumber, + qPrintable(line)); + } + continue; + } + auto match = tracedef.match(line); if (match.hasMatch()) { const QString name = match.captured(1); const QString argsString = match.captured(2); - const QStringList args = argsString.split(QLatin1Char(','), Qt::SkipEmptyParts); + const QStringList args = argsString.split(u',', Qt::SkipEmptyParts); - provider.tracepoints << parseTracepoint(name, args, filename, lineNumber); + provider.tracepoints << parseTracepoint(provider, name, args, filename, lineNumber); } else { panic("Syntax error while processing '%s' line %d:\n" " '%s' does not look like a tracepoint definition", diff --git a/src/tools/tracegen/provider.h b/src/tools/tracegen/provider.h index 99b10b13f1..e5e99b868e 100644 --- a/src/tools/tracegen/provider.h +++ b/src/tools/tracegen/provider.h @@ -1,41 +1,5 @@ -/**************************************************************************** -** -** Copyright (C) 2017 Klarälvdalens Datakonsult AB, a KDAB Group company, info@kdab.com, author Rafael Roquetto <rafael.roquetto@kdab.com> -** Contact: https://www.qt.io/licensing/ -** -** This file is part of the tools applications of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:LGPL$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. For licensing terms -** and conditions see https://www.qt.io/terms-conditions. For further -** information use the contact form at https://www.qt.io/contact-us. -** -** GNU Lesser General Public License Usage -** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 3 as published by the Free Software -** Foundation and appearing in the file LICENSE.LGPL3 included in the -** packaging of this file. Please review the following information to -** ensure the GNU Lesser General Public License version 3 requirements -** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 2.0 or (at your option) the GNU General -** Public license version 3 or any later version approved by the KDE Free -** Qt Foundation. The licenses are as published by the Free Software -** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 -** included in the packaging of this file. Please review the following -** information to ensure the GNU General Public License requirements will -** be met: https://www.gnu.org/licenses/gpl-2.0.html and -** https://www.gnu.org/licenses/gpl-3.0.html. -** -** $QT_END_LICENSE$ -** -****************************************************************************/ +// Copyright (C) 2017 Klarälvdalens Datakonsult AB, a KDAB Group company, info@kdab.com, author Rafael Roquetto <rafael.roquetto@kdab.com> +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0 #ifndef PROVIDER_H #define PROVIDER_H @@ -56,9 +20,9 @@ struct Tracepoint struct Field { - enum BackendType { - Array, + enum Type { Sequence, + Boolean, Integer, IntegerHex, Float, @@ -68,13 +32,18 @@ struct Tracepoint QtByteArray, QtUrl, QtRect, + QtSize, + QtRectF, + QtSizeF, + EnumeratedType, + FlagType, Unknown }; - - BackendType backendType; + Type backendType; QString paramType; QString name; int arrayLen; + int enumValueSize; QString seqLen; }; @@ -83,17 +52,41 @@ struct Tracepoint QList<Field> fields; }; +struct TraceEnum { + QString name; + struct EnumValue { + QString name; + int value; + int range; + }; + QList<EnumValue> values; + int valueSize; +}; + +struct TraceFlags { + QString name; + struct FlagValue { + QString name; + int value; + }; + QList<FlagValue> values; +}; + +Q_DECLARE_TYPEINFO(TraceEnum, Q_RELOCATABLE_TYPE); +Q_DECLARE_TYPEINFO(TraceFlags, Q_RELOCATABLE_TYPE); +Q_DECLARE_TYPEINFO(Tracepoint::Argument, Q_RELOCATABLE_TYPE); +Q_DECLARE_TYPEINFO(Tracepoint::Field, Q_RELOCATABLE_TYPE); +Q_DECLARE_TYPEINFO(Tracepoint, Q_RELOCATABLE_TYPE); + struct Provider { QString name; QList<Tracepoint> tracepoints; QStringList prefixText; + QList<TraceEnum> enumerations; + QList<TraceFlags> flags; }; Provider parseProvider(const QString &filename); -Q_DECLARE_TYPEINFO(Tracepoint::Argument, Q_RELOCATABLE_TYPE); -Q_DECLARE_TYPEINFO(Tracepoint::Field, Q_RELOCATABLE_TYPE); -Q_DECLARE_TYPEINFO(Tracepoint, Q_RELOCATABLE_TYPE); - #endif // PROVIDER_H diff --git a/src/tools/tracegen/qtheaders.cpp b/src/tools/tracegen/qtheaders.cpp index eec3488a6d..237c22b237 100644 --- a/src/tools/tracegen/qtheaders.cpp +++ b/src/tools/tracegen/qtheaders.cpp @@ -1,41 +1,5 @@ -/**************************************************************************** -** -** Copyright (C) 2017 Klarälvdalens Datakonsult AB, a KDAB Group company, info@kdab.com, author Rafael Roquetto <rafael.roquetto@kdab.com> -** Contact: https://www.qt.io/licensing/ -** -** This file is part of the tools applications of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:LGPL$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. For licensing terms -** and conditions see https://www.qt.io/terms-conditions. For further -** information use the contact form at https://www.qt.io/contact-us. -** -** GNU Lesser General Public License Usage -** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 3 as published by the Free Software -** Foundation and appearing in the file LICENSE.LGPL3 included in the -** packaging of this file. Please review the following information to -** ensure the GNU Lesser General Public License version 3 requirements -** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 2.0 or (at your option) the GNU General -** Public license version 3 or any later version approved by the KDE Free -** Qt Foundation. The licenses are as published by the Free Software -** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 -** included in the packaging of this file. Please review the following -** information to ensure the GNU General Public License requirements will -** be met: https://www.gnu.org/licenses/gpl-2.0.html and -** https://www.gnu.org/licenses/gpl-3.0.html. -** -** $QT_END_LICENSE$ -** -****************************************************************************/ +// Copyright (C) 2017 Klarälvdalens Datakonsult AB, a KDAB Group company, info@kdab.com, author Rafael Roquetto <rafael.roquetto@kdab.com> +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0 #include "qtheaders.h" diff --git a/src/tools/tracegen/qtheaders.h b/src/tools/tracegen/qtheaders.h index b80d374ca8..86405c9479 100644 --- a/src/tools/tracegen/qtheaders.h +++ b/src/tools/tracegen/qtheaders.h @@ -1,41 +1,5 @@ -/**************************************************************************** -** -** Copyright (C) 2017 Klarälvdalens Datakonsult AB, a KDAB Group company, info@kdab.com, author Rafael Roquetto <rafael.roquetto@kdab.com> -** Contact: https://www.qt.io/licensing/ -** -** This file is part of the tools applications of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:LGPL$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. For licensing terms -** and conditions see https://www.qt.io/terms-conditions. For further -** information use the contact form at https://www.qt.io/contact-us. -** -** GNU Lesser General Public License Usage -** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 3 as published by the Free Software -** Foundation and appearing in the file LICENSE.LGPL3 included in the -** packaging of this file. Please review the following information to -** ensure the GNU Lesser General Public License version 3 requirements -** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 2.0 or (at your option) the GNU General -** Public license version 3 or any later version approved by the KDE Free -** Qt Foundation. The licenses are as published by the Free Software -** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 -** included in the packaging of this file. Please review the following -** information to ensure the GNU General Public License requirements will -** be met: https://www.gnu.org/licenses/gpl-2.0.html and -** https://www.gnu.org/licenses/gpl-3.0.html. -** -** $QT_END_LICENSE$ -** -****************************************************************************/ +// Copyright (C) 2017 Klarälvdalens Datakonsult AB, a KDAB Group company, info@kdab.com, author Rafael Roquetto <rafael.roquetto@kdab.com> +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0 #ifndef QTHEADERS_H #define QTHEADERS_H diff --git a/src/tools/tracegen/tracegen.cpp b/src/tools/tracegen/tracegen.cpp index 978fe406d0..776d81675d 100644 --- a/src/tools/tracegen/tracegen.cpp +++ b/src/tools/tracegen/tracegen.cpp @@ -1,43 +1,8 @@ -/**************************************************************************** -** -** Copyright (C) 2017 Klarälvdalens Datakonsult AB, a KDAB Group company, info@kdab.com, author Rafael Roquetto <rafael.roquetto@kdab.com> -** Contact: https://www.qt.io/licensing/ -** -** This file is part of the tools applications of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:LGPL$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. For licensing terms -** and conditions see https://www.qt.io/terms-conditions. For further -** information use the contact form at https://www.qt.io/contact-us. -** -** GNU Lesser General Public License Usage -** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 3 as published by the Free Software -** Foundation and appearing in the file LICENSE.LGPL3 included in the -** packaging of this file. Please review the following information to -** ensure the GNU Lesser General Public License version 3 requirements -** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 2.0 or (at your option) the GNU General -** Public license version 3 or any later version approved by the KDE Free -** Qt Foundation. The licenses are as published by the Free Software -** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 -** included in the packaging of this file. Please review the following -** information to ensure the GNU General Public License requirements will -** be met: https://www.gnu.org/licenses/gpl-2.0.html and -** https://www.gnu.org/licenses/gpl-3.0.html. -** -** $QT_END_LICENSE$ -** -****************************************************************************/ +// Copyright (C) 2017 Klarälvdalens Datakonsult AB, a KDAB Group company, info@kdab.com, author Rafael Roquetto <rafael.roquetto@kdab.com> +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0 #include "provider.h" +#include "ctf.h" #include "lttng.h" #include "etw.h" #include "panic.h" @@ -48,12 +13,13 @@ enum class Target { LTTNG, - ETW + ETW, + CTF, }; static inline void usage(int status) { - printf("Usage: tracegen <lttng|etw> <input file> <output file>\n"); + printf("Usage: tracegen <lttng|etw|ctf> <input file> <output file>\n"); exit(status); } @@ -70,13 +36,15 @@ static void parseArgs(int argc, char *argv[], Target *target, QString *inFile, Q *target = Target::LTTNG; } else if (qstrcmp(targetString, "etw") == 0) { *target = Target::ETW; + } else if (qstrcmp(targetString, "ctf") == 0) { + *target = Target::CTF; } else { fprintf(stderr, "Invalid target: %s\n", targetString); usage(EXIT_FAILURE); } - *inFile = QLatin1String(argv[2]); - *outFile = QLatin1String(argv[3]); + *inFile = QLatin1StringView(argv[2]); + *outFile = QLatin1StringView(argv[3]); } int main(int argc, char *argv[]) @@ -97,6 +65,9 @@ int main(int argc, char *argv[]) } switch (target) { + case Target::CTF: + writeCtf(out, p); + break; case Target::LTTNG: writeLttng(out, p); break; |