summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAntti Määttä <[email protected]>2022-12-13 09:01:13 +0200
committerAntti Määttä <[email protected]>2023-01-14 12:45:47 +0200
commit26c363820b1fcfbc7e7dd820b07f2b08e1ff1731 (patch)
tree498ef2eaf0036f9bd2ed13493d5a43edee26e32a
parentb30fdad16abdcc81546a73716218c30d13eaa64a (diff)
Add metadata support to tracegen and tracepointgen tools
Adds ability to add textual metadata for enumerations and flags to the traces so that they provide more information to the user instead of just numbers. Implement these for both existing backends. Task-number: QTBUG-106399 Change-Id: Ibab00dd370d019891cf9ad6e65e6f9d868e32dce Reviewed-by: Tomi Korpipää <[email protected]> (cherry picked from commit a2bcb7d8adb7bb59087cd2df2396539e2baf5b7d) Reviewed-by: Antti Määttä <[email protected]>
-rw-r--r--src/corelib/global/qtrace_p.h45
-rw-r--r--src/tools/tracegen/etw.cpp58
-rw-r--r--src/tools/tracegen/helpers.cpp22
-rw-r--r--src/tools/tracegen/helpers.h3
-rw-r--r--src/tools/tracegen/lttng.cpp107
-rw-r--r--src/tools/tracegen/provider.cpp266
-rw-r--r--src/tools/tracegen/provider.h44
-rw-r--r--src/tools/tracepointgen/parser.cpp32
-rw-r--r--src/tools/tracepointgen/parser.h5
9 files changed, 490 insertions, 92 deletions
diff --git a/src/corelib/global/qtrace_p.h b/src/corelib/global/qtrace_p.h
index 49810737499..f548afd91c1 100644
--- a/src/corelib/global/qtrace_p.h
+++ b/src/corelib/global/qtrace_p.h
@@ -88,6 +88,37 @@
* class QEvent;
* QT_END_NAMESPACE
* }
+ *
+ * Metadata
+ *
+ * Metadata is used to add textual information for different types such
+ * as enums and flags. How this data is handled depends on the used backend.
+ * For ETW, the values are converted to text, for CTF and LTTNG they are used to add
+ * CTF enumerations, which are converted to text after tracing.
+ *
+ * Enumererations are specified using ENUM:
+ *
+ * ENUM {
+ * Enum0 = 0,
+ * Enum1 = 1,
+ * Enum2,
+ * RANGE(RangeEnum, 3 ... 10),
+ * } Name;
+ *
+ * Name must match to one of the enumerations used in the tracepoints. Range of values
+ * can be provided using RANGE(name, first ... last). All values must be unique.
+ *
+ * Flags are specified using FLAGS:
+ *
+ * FLAGS {
+ * Default = 0,
+ * Flag0 = 1,
+ * Flag1 = 2,
+ * Flag2 = 4,
+ * } Name;
+ *
+ * Name must match to one of the flags used in the tracepoints. Each value must be
+ * power of two and unique.
*/
#include <QtCore/private/qglobal_p.h>
@@ -174,11 +205,25 @@ QT_BEGIN_NAMESPACE
* "QT_BEGIN_NAMESPACE" \
* "class QEvent;" \
* "QT_END_NAMESPACE")
+ *
+ * - Q_TRACE_METADATA(provider, metadata)
+ * Provides metadata for the tracepoint provider.
+ *
+ * Q_TRACE_METADATA(qtgui,
+ * "ENUM {" \
+ * "Format_Invalid," \
+ * "Format_Mono," \
+ * "Format_MonoLSB," \
+ * "Format_Indexed8," \
+ * ...
+ * "} QImage::Format;" \
+ * );
*/
#define Q_TRACE_INSTRUMENT(provider)
#define Q_TRACE_PARAM_REPLACE(in, out)
#define Q_TRACE_POINT(provider, tracepoint, ...)
#define Q_TRACE_PREFIX(provider, prefix)
+#define Q_TRACE_METADATA(provider, metadata)
QT_END_NAMESPACE
diff --git a/src/tools/tracegen/etw.cpp b/src/tools/tracegen/etw.cpp
index 755470af153..c0e13ffb757 100644
--- a/src/tools/tracegen/etw.cpp
+++ b/src/tools/tracegen/etw.cpp
@@ -31,7 +31,7 @@ static void writeEtwMacro(QTextStream &stream, const Tracepoint::Field &field)
return;
}
- switch (field.backendType) {
+ switch (field.backendType.backendType) {
case Tracepoint::Field::QtString:
stream << "TraceLoggingCountedWideString(reinterpret_cast<LPCWSTR>("
<< name << ".utf16()), static_cast<ULONG>(" << name << ".size()), \""
@@ -64,6 +64,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_" << typeToName(field.paramType) << "(" << name << ").toUtf8().constData(), \"" << name << "\")";
+ return;
default:
break;
}
@@ -160,10 +164,10 @@ static void writeWrapper(QTextStream &stream, const Tracepoint &tracepoint,
const QString &providerName)
{
const QString argList = formatFunctionSignature(tracepoint.args);
- const QString paramList = formatParameterList(tracepoint.args, ETW);
+ const QString paramList = formatParameterList(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";
@@ -173,12 +177,12 @@ static void writeWrapper(QTextStream &stream, const Tracepoint &tracepoint,
// Convert all unknown types to QString's using QDebug.
// Note the naming convention: it's field.name##Str
for (const Tracepoint::Field &field : tracepoint.fields) {
- if (field.backendType == Tracepoint::Field::Unknown) {
+ if (field.backendType.backendType == Tracepoint::Field::Unknown) {
stream << " const QString " << field.name << "Str = QDebug::toString(" << field.name
<< ");\n";
}
}
- stream << " TraceLoggingWrite(" << provider << ", \"" << name << "\"";
+ stream << " TraceLoggingWrite(" << provar << ", \"" << name << "\"";
for (const Tracepoint::Field &field : tracepoint.fields) {
stream << ",\n";
@@ -196,10 +200,46 @@ 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_" << typeToName(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";
+ for (const auto &v : enumeration.values) {
+ if (v.range == 0)
+ stream << " case " << v.value << ": ret = QStringLiteral(\"" << v.name << "\"); break;\n";
+ }
+
+ stream << " }\n return ret;\n}\n";
+}
+
+static void writeFlagConverter(QTextStream &stream, const TraceFlags &flag)
+{
+ stream << "inline QString trace_convert_" << typeToName(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(\"" << v.name << "\");\n";
+ break;
+ }
+ }
+ for (const auto &v : flag.values) {
+ if (v.value != 0)
+ stream << " if (val & " << (1 << (v.value - 1)) << ") { if (ret.length()) ret += QLatin1Char(\'|\'); ret += QStringLiteral(\"" << v.name << "\"); }\n";
+ }
+ stream << " return ret;\n}\n";
+}
+
static void writeTracepoints(QTextStream &stream, const Provider &provider)
{
if (provider.tracepoints.isEmpty())
@@ -212,6 +252,12 @@ 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);
diff --git a/src/tools/tracegen/helpers.cpp b/src/tools/tracegen/helpers.cpp
index de523e74a67..6f0c7cb0f2f 100644
--- a/src/tools/tracegen/helpers.cpp
+++ b/src/tools/tracegen/helpers.cpp
@@ -6,6 +6,12 @@
using namespace Qt::StringLiterals;
+QString typeToName(const QString &name)
+{
+ QString ret = name;
+ return ret.replace(QStringLiteral("::"), QStringLiteral("_"));
+}
+
QString includeGuard(const QString &filename)
{
QString guard = filename.toUpper();
@@ -43,11 +49,25 @@ QString formatFunctionSignature(const QList<Tracepoint::Argument> &args)
});
}
-QString formatParameterList(const QList<Tracepoint::Argument> &args, ParamType type)
+QString formatParameterList(const QList<Tracepoint::Argument> &args, const QList<Tracepoint::Field> &fields, ParamType type)
{
if (type == LTTNG) {
QString ret;
+ for (int i = 0; i < args.size(); i++) {
+ const Tracepoint::Argument &arg = args[i];
+ const Tracepoint::Field &field = fields[i];
+ if (field.backendType.backendType == Tracepoint::Field::FlagType)
+ ret += ", trace_convert_"_L1 + typeToName(arg.type) + "("_L1 + arg.name + ")"_L1;
+ else
+ ret += ", "_L1 + arg.name;
+ }
+ return ret;
+ }
+
+ if (type == LTTNG) {
+ QString ret;
+
for (const Tracepoint::Argument &arg : args)
ret += ", "_L1 + arg.name;
diff --git a/src/tools/tracegen/helpers.h b/src/tools/tracegen/helpers.h
index 4c30eaff0d6..45a0383ff96 100644
--- a/src/tools/tracegen/helpers.h
+++ b/src/tools/tracegen/helpers.h
@@ -14,8 +14,9 @@ enum ParamType {
ETW
};
+QString typeToName(const QString &name);
QString includeGuard(const QString &filename);
QString formatFunctionSignature(const QList<Tracepoint::Argument> &args);
-QString formatParameterList(const QList<Tracepoint::Argument> &args, ParamType type);
+QString formatParameterList(const QList<Tracepoint::Argument> &args, const QList<Tracepoint::Field> &fields, ParamType type);
#endif // HELPERS_H
diff --git a/src/tools/tracegen/lttng.cpp b/src/tools/tracegen/lttng.cpp
index d230e024c7f..f9e8ce5c2f7 100644
--- a/src/tools/tracegen/lttng.cpp
+++ b/src/tools/tracegen/lttng.cpp
@@ -12,7 +12,7 @@
#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 &paramType = field.paramType;
const QString &name = field.name;
@@ -25,12 +25,13 @@ static void writeCtfMacro(QTextStream &stream, const Tracepoint::Field &field)
return;
}
- switch (field.backendType) {
+ switch (field.backendType.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;
@@ -45,17 +46,14 @@ 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()) "
@@ -67,6 +65,13 @@ static void writeCtfMacro(QTextStream &stream, const Tracepoint::Field &field)
stream << "ctf_integer(int, width, " << name << ".width()) "
<< "ctf_integer(int, height, " << name << ".height()) ";
return;
+ case Tracepoint::Field::EnumeratedType:
+ stream << "ctf_enum(" << provider.name << ", " << typeToName(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:
panic("Cannot deduce CTF type for '%s %s", qPrintable(paramType), qPrintable(name));
break;
@@ -116,12 +121,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(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
@@ -134,17 +139,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"
@@ -152,7 +157,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"
@@ -162,8 +167,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.backendType == Tracepoint::Field::FlagType)
+ stream << comma << "QByteArray, " << arg.name;
+ else
+ stream << comma << arg.type << ", " << arg.name;
comma = ", ";
}
@@ -174,18 +184,74 @@ 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"
+ << " " << typeToName(e.name) << ",\n"
+ << " TP_ENUM_VALUES(\n";
+ for (const auto &v : e.values) {
+ if (v.range > 0)
+ stream << " ctf_enum_range(\"" << v.name << "\", " << v.value << ", " << v.range << ")\n";
+ else
+ stream << " ctf_enum_value(\"" << v.name << "\", " << v.value << ")\n";
+ }
+ 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"
+ << " " << typeToName(f.name) << ",\n"
+ << " TP_ENUM_VALUES(\n";
+ for (const auto &v : f.values)
+ stream << " ctf_enum_value(\"" << v.name << "\", " << v.value << ")\n";
+ 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_" << typeToName(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);
}
}
@@ -196,6 +262,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/provider.cpp b/src/tools/tracegen/provider.cpp
index 51d0326ecff..10a864f6021 100644
--- a/src/tools/tracegen/provider.cpp
+++ b/src/tools/tracegen/provider.cpp
@@ -9,6 +9,7 @@
#include <qtextstream.h>
#include <qregularexpression.h>
#include <qstring.h>
+#include <qtpreprocessorsupport.h>
using namespace Qt::StringLiterals;
@@ -95,48 +96,55 @@ static QString removeBraces(QString type)
return type.remove(rx);
}
+#define TYPEDATA_ENTRY(type, backendType) \
+{ QT_STRINGIFY(type), backendType, sizeof(type) * 8, std::is_signed<type>::value }
+
static Tracepoint::Field::BackendType backendType(QString rawType)
{
- static const struct {
+ static const struct TypeData {
const char *type;
- Tracepoint::Field::BackendType backendType;
+ Tracepoint::Field::Type backendType;
+ int bits;
+ bool isSigned;
} 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 },
- { "qint64", 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 },
- { "QSize", Tracepoint::Field::QtSize }
+#ifdef UNDERSCORE_TYPES_DEFINED
+ 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),
+#endif
+ 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),
+ { "QString", Tracepoint::Field::QtString , 0, false},
+ { "QByteArray", Tracepoint::Field::QtByteArray , 0, false},
+ { "QUrl", Tracepoint::Field::QtUrl , 0, false},
+ { "QRect", Tracepoint::Field::QtRect , 0, false},
+ { "QSize", Tracepoint::Field::QtSize , 0, false}
};
auto backendType = [](const QString &rawType) {
@@ -144,10 +152,11 @@ static Tracepoint::Field::BackendType backendType(QString rawType)
for (size_t i = 0; i < tableSize; ++i) {
if (rawType == QLatin1StringView(typeTable[i].type))
- return typeTable[i].backendType;
+ return typeTable[i];
}
- return Tracepoint::Field::Unknown;
+ TypeData unknown = { nullptr, Tracepoint::Field::Unknown, 0, false };
+ return unknown;
};
int arrayLen = arrayLength(rawType);
@@ -155,7 +164,7 @@ static Tracepoint::Field::BackendType backendType(QString rawType)
rawType = removeBraces(rawType);
if (!sequenceLength(rawType).isNull())
- return Tracepoint::Field::Sequence;
+ return { Tracepoint::Field::Sequence, 0, false };
static const QRegularExpression constMatch(QStringLiteral("\\bconst\\b"));
rawType.remove(constMatch);
@@ -167,20 +176,37 @@ static Tracepoint::Field::BackendType backendType(QString rawType)
rawType.replace(QStringLiteral(" "), QStringLiteral("_"));
if (rawType == "char_ptr"_L1)
- return Tracepoint::Field::String;
+ return { Tracepoint::Field::String, 0, false };
if (rawType.endsWith("_ptr"_L1))
- return Tracepoint::Field::Pointer;
+ return {Tracepoint::Field::Pointer, QT_POINTER_SIZE, false };
- return backendType(rawType);
+ TypeData d = backendType(rawType);
+ return { d.backendType, d.bits, d.isSigned };
}
-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;
@@ -216,14 +242,22 @@ 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, e.valueSize, false };
+ } else if (!f.name.isEmpty()) {
+ field.backendType = { Tracepoint::Field::FlagType, 0, false };
+ } 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;
}
@@ -231,6 +265,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);
@@ -241,11 +300,21 @@ 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_]*)( ?= ?([0-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();
@@ -258,18 +327,109 @@ Provider parseProvider(const QString &filename)
} 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(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;
+ 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;
+ currentEnum.values.push_back(value);
+ maxEnumValue = qMax(maxEnumValue, value.value);
+ minEnumValue = qMin(minEnumValue, value.value);
+ } else {
+ TraceFlags::FlagValue value;
+ value.name = m.captured(1);
+ value.value = m.captured(3).toInt();
+ if (!isPow2OrZero(value.value)) {
+ panic("Syntax error while processing '%s' line %d:\n"
+ " '%s' flag value is now power of two",
+ qPrintable(filename), lineNumber,
+ qPrintable(line));
+ }
+ 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(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 18392baaef2..72096590334 100644
--- a/src/tools/tracegen/provider.h
+++ b/src/tools/tracegen/provider.h
@@ -20,8 +20,9 @@ struct Tracepoint
struct Field
{
- enum BackendType {
+ enum Type {
Sequence,
+ Boolean,
Integer,
IntegerHex,
Float,
@@ -32,9 +33,15 @@ struct Tracepoint
QtUrl,
QtRect,
QtSize,
+ EnumeratedType,
+ FlagType,
Unknown
};
-
+ struct BackendType {
+ Type backendType;
+ int bits;
+ bool isSigned;
+ };
BackendType backendType;
QString paramType;
QString name;
@@ -47,17 +54,42 @@ 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::BackendType, 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/tracepointgen/parser.cpp b/src/tools/tracepointgen/parser.cpp
index 6199098371e..940e609b44a 100644
--- a/src/tools/tracepointgen/parser.cpp
+++ b/src/tools/tracepointgen/parser.cpp
@@ -78,14 +78,14 @@ static void simplifyData(QString &data, QList<LineNumber> &offsets)
}
}
-static QString preprocessPrefix(const QString &in)
+static QString preprocessMetadata(const QString &in)
{
- DEBUGPRINTF(printf("prefix: %s\n", qPrintable(in)));
+ DEBUGPRINTF(printf("in: %s\n", qPrintable(in)));
QList<QString> lines = in.split(QLatin1Char('\\'));
QString out;
for (int i = 0; i < lines.size(); i++) {
QString l = lines.at(i).simplified();
- DEBUGPRINTF(printf("prefix line: %s\n", qPrintable(l)));
+ DEBUGPRINTF(printf("line: %s\n", qPrintable(l)));
if (l.length() < 2)
continue;
if (l.startsWith(QStringLiteral("\"")))
@@ -100,7 +100,7 @@ static QString preprocessPrefix(const QString &in)
out.append(l);
}
}
- DEBUGPRINTF(printf("prefix out: %s\n", qPrintable(out)));
+ DEBUGPRINTF(printf("out: %s\n", qPrintable(out)));
return out;
}
@@ -207,7 +207,25 @@ void Parser::parsePrefix(const QString &data, qsizetype offset)
DEBUGPRINTF(printf("tracepointgen: prefix: %s\n", qPrintable(prefix)));
if (!m_prefixes.contains(prefix))
- m_prefixes.push_back(preprocessPrefix(prefix));
+ m_prefixes.push_back(preprocessMetadata(prefix));
+}
+
+void Parser::parseMetadata(const QString &data, qsizetype offset)
+{
+ qsizetype beginOfProvider = data.indexOf(QLatin1Char('('), offset);
+ qsizetype endOfProvider = data.indexOf(QLatin1Char(','), beginOfProvider);
+ QString metadata;
+ QString provider = data.mid(beginOfProvider + 1, endOfProvider - beginOfProvider - 1).simplified();
+ if (provider != m_provider)
+ return;
+
+ qsizetype endOfPoint = data.indexOf(QLatin1Char(')'), endOfProvider + 1);
+ metadata = data.mid(endOfProvider + 1, endOfPoint - endOfProvider - 1).simplified();
+
+ DEBUGPRINTF(printf("tracepointgen: metadata: %s", qPrintable(metadata)));
+
+ if (!m_metadata.contains(metadata))
+ m_metadata.push_back(preprocessMetadata(metadata));
}
void Parser::parse(QIODevice &input, const QString &name)
@@ -239,6 +257,8 @@ void Parser::parse(QIODevice &input, const QString &name)
parsePoint(data, match.capturedEnd());
else if (macroType == QStringLiteral("PREFIX"))
parsePrefix(data, match.capturedEnd());
+ else if (macroType == QStringLiteral("METADATA"))
+ parseMetadata(data, match.capturedEnd());
}
for (auto &func : m_functions) {
@@ -256,6 +276,8 @@ void Parser::write(QIODevice &input) const
out << prefix << "\n";
out << QStringLiteral("}\n");
}
+ for (auto m : m_metadata)
+ out << m << "\n";
for (auto func : m_functions) {
out << func.className << "_" << func.functionName << "_entry(" << func.functionParameters << ")\n";
out << func.className << "_" << func.functionName << "_exit()\n";
diff --git a/src/tools/tracepointgen/parser.h b/src/tools/tracepointgen/parser.h
index 1d1fda20682..bc46a4d933b 100644
--- a/src/tools/tracepointgen/parser.h
+++ b/src/tools/tracepointgen/parser.h
@@ -41,10 +41,12 @@ struct Parser
{
}
+
void parseParamReplace(const QString &data, qsizetype offset, const QString &name);
void parseInstrument(const QString &data, qsizetype offset);
void parsePoint(const QString &data, qsizetype offset);
void parsePrefix(const QString &data, qsizetype offset);
+ void parseMetadata(const QString &data, qsizetype offset);
int lineNumber(qsizetype offset) const;
void parse(QIODevice &input, const QString &name);
@@ -58,8 +60,9 @@ struct Parser
QList<Point> m_points;
QList<Replace> m_replaces;
QList<QString> m_prefixes;
- QString m_provider;
+ QList<QString> m_metadata;
QList<LineNumber> m_offsets;
+ QString m_provider;
};
#endif // PARSER_H