aboutsummaryrefslogtreecommitdiffstats
path: root/tools/qmlcachegen/qmlcachegen.cpp
diff options
context:
space:
mode:
authorOlivier De Cannière <olivier.decanniere@qt.io>2023-07-11 15:01:10 +0200
committerOlivier De Cannière <olivier.decanniere@qt.io>2023-08-04 09:34:09 +0200
commit2cf9aeccddbd06a66df94bd27916714c4a5c7e24 (patch)
treef147cabe8e7f8d3dfcf1b02cf8d730e851fcc0a6 /tools/qmlcachegen/qmlcachegen.cpp
parent0667e68e7715f60916ee91189925855e1dcf5f0e (diff)
Compiler: Separate function prolog block and add validation of blocks
The function prolog logic is now separated in its own basic block. The first "real" block with user code starts at offset 0. Having the function prolog as a hidden part of the first block caused some inconsistencies in block generation and would create empty blocks. This happened for example when a back edge of a loop would target offset 0 in code where a loop condition is the very first set of instructions that are run. This is because the target block offset didn't exist due to it being part of the hidden prolog block. Validation for the basic blocks was also added. This checks for three things at the moment: 1. That return and throw blocks don't have jump targets. 2. That the basic blocks graph is connected. 3. That jump targets are the first offset of a block. Test tst_QmlCppCodegen::basicBlocksWithBackJump_infinite() is expected to fail because it contains an infinite loop and the basic blocks that are generated for it are inconsistent due to dead-code elimination happening earlier in compilation. Debug outputs for dumping basic blocks were also adapted to reflect these changes. Change-Id: I513f73856412d488d443c2b47a052b0023d45496 Reviewed-by: Qt CI Bot <qt_ci_bot@qt-project.org> Reviewed-by: Fabian Kosmale <fabian.kosmale@qt.io>
Diffstat (limited to 'tools/qmlcachegen/qmlcachegen.cpp')
-rw-r--r--tools/qmlcachegen/qmlcachegen.cpp84
1 files changed, 38 insertions, 46 deletions
diff --git a/tools/qmlcachegen/qmlcachegen.cpp b/tools/qmlcachegen/qmlcachegen.cpp
index 2836e41a00..da30307466 100644
--- a/tools/qmlcachegen/qmlcachegen.cpp
+++ b/tools/qmlcachegen/qmlcachegen.cpp
@@ -24,12 +24,14 @@
#include <algorithm>
+using namespace Qt::Literals::StringLiterals;
+
static bool argumentsFromCommandLineAndFile(QStringList& allArguments, const QStringList &arguments)
{
allArguments.reserve(arguments.size());
for (const QString &argument : arguments) {
// "@file" doesn't start with a '-' so we can't use QCommandLineParser for it
- if (argument.startsWith(QLatin1Char('@'))) {
+ if (argument.startsWith(u'@')) {
QString optionsFile = argument;
optionsFile.remove(0, 1);
if (optionsFile.isEmpty()) {
@@ -59,55 +61,43 @@ int main(int argc, char **argv)
QHashSeed::setDeterministicGlobalSeed();
QCoreApplication app(argc, argv);
- QCoreApplication::setApplicationName(QStringLiteral("qmlcachegen"));
+ QCoreApplication::setApplicationName("qmlcachegen"_L1);
QCoreApplication::setApplicationVersion(QLatin1String(QT_VERSION_STR));
QCommandLineParser parser;
parser.addHelpOption();
parser.addVersionOption();
- QCommandLineOption bareOption(QStringLiteral("bare"), QCoreApplication::translate("main", "Do not include default import directories. This may be used to run qmlcachegen on a project using a different Qt version."));
+ QCommandLineOption bareOption("bare"_L1, QCoreApplication::translate("main", "Do not include default import directories. This may be used to run qmlcachegen on a project using a different Qt version."));
parser.addOption(bareOption);
- QCommandLineOption filterResourceFileOption(QStringLiteral("filter-resource-file"), QCoreApplication::translate("main", "Filter out QML/JS files from a resource file that can be cached ahead of time instead"));
+ QCommandLineOption filterResourceFileOption("filter-resource-file"_L1, QCoreApplication::translate("main", "Filter out QML/JS files from a resource file that can be cached ahead of time instead"));
parser.addOption(filterResourceFileOption);
- QCommandLineOption resourceFileMappingOption(QStringLiteral("resource-file-mapping"), QCoreApplication::translate("main", "Path from original resource file to new one"), QCoreApplication::translate("main", "old-name=new-name"));
+ QCommandLineOption resourceFileMappingOption("resource-file-mapping"_L1, QCoreApplication::translate("main", "Path from original resource file to new one"), QCoreApplication::translate("main", "old-name=new-name"));
parser.addOption(resourceFileMappingOption);
- QCommandLineOption resourceOption(QStringLiteral("resource"), QCoreApplication::translate("main", "Qt resource file that might later contain one of the compiled files"), QCoreApplication::translate("main", "resource-file-name"));
+ QCommandLineOption resourceOption("resource"_L1, QCoreApplication::translate("main", "Qt resource file that might later contain one of the compiled files"), QCoreApplication::translate("main", "resource-file-name"));
parser.addOption(resourceOption);
- QCommandLineOption resourcePathOption(QStringLiteral("resource-path"), QCoreApplication::translate("main", "Qt resource file path corresponding to the file being compiled"), QCoreApplication::translate("main", "resource-path"));
+ QCommandLineOption resourcePathOption("resource-path"_L1, QCoreApplication::translate("main", "Qt resource file path corresponding to the file being compiled"), QCoreApplication::translate("main", "resource-path"));
parser.addOption(resourcePathOption);
- QCommandLineOption resourceNameOption(QStringLiteral("resource-name"),
- QCoreApplication::translate("main", "Required to generate qmlcache_loader without qrc files. This is the name of the Qt resource the input files belong to."),
- QCoreApplication::translate("main", "compiled-file-list"));
+ QCommandLineOption resourceNameOption("resource-name"_L1, QCoreApplication::translate("main", "Required to generate qmlcache_loader without qrc files. This is the name of the Qt resource the input files belong to."), QCoreApplication::translate("main", "compiled-file-list"));
parser.addOption(resourceNameOption);
- QCommandLineOption directCallsOption(QStringLiteral("direct-calls"), QCoreApplication::translate("main", "This option is ignored."));
+ QCommandLineOption directCallsOption("direct-calls"_L1, QCoreApplication::translate("main", "This option is ignored."));
directCallsOption.setFlags(QCommandLineOption::HiddenFromHelp);
parser.addOption(directCallsOption);
- QCommandLineOption importsOption(
- QStringLiteral("i"),
- QCoreApplication::translate("main", "Import extra qmldir"),
- QCoreApplication::translate("main", "qmldir file"));
+ QCommandLineOption importsOption("i"_L1, QCoreApplication::translate("main", "Import extra qmldir"), QCoreApplication::translate("main", "qmldir file"));
parser.addOption(importsOption);
- QCommandLineOption importPathOption(
- QStringLiteral("I"),
- QCoreApplication::translate("main", "Look for QML modules in specified directory"),
- QCoreApplication::translate("main", "import directory"));
+ QCommandLineOption importPathOption("I"_L1, QCoreApplication::translate("main", "Look for QML modules in specified directory"), QCoreApplication::translate("main", "import directory"));
parser.addOption(importPathOption);
- QCommandLineOption onlyBytecode(
- QStringLiteral("only-bytecode"),
- QCoreApplication::translate(
- "main", "Generate only byte code for bindings and functions, no C++ code"));
+ QCommandLineOption onlyBytecode("only-bytecode"_L1, QCoreApplication::translate("main", "Generate only byte code for bindings and functions, no C++ code"));
parser.addOption(onlyBytecode);
- QCommandLineOption verboseOption(
- QStringLiteral("verbose"),
- QCoreApplication::translate("main", "Output compile warnings"));
+ QCommandLineOption verboseOption("verbose"_L1, QCoreApplication::translate("main", "Output compile warnings"));
parser.addOption(verboseOption);
+ QCommandLineOption validateBasicBlocksOption("validate-basic-blocks"_L1, QCoreApplication::translate("main", "Performs checks on the basic blocks of a function compiled ahead of time to validate its structure and coherence"));
+ parser.addOption(validateBasicBlocksOption);
- QCommandLineOption outputFileOption(QStringLiteral("o"), QCoreApplication::translate("main", "Output file name"), QCoreApplication::translate("main", "file name"));
+ QCommandLineOption outputFileOption("o"_L1, QCoreApplication::translate("main", "Output file name"), QCoreApplication::translate("main", "file name"));
parser.addOption(outputFileOption);
- parser.addPositionalArgument(QStringLiteral("[qml file]"),
- QStringLiteral("QML source file to generate cache for."));
+ parser.addPositionalArgument("[qml file]"_L1, "QML source file to generate cache for."_L1);
parser.setSingleDashWordOptionMode(QCommandLineParser::ParseAsLongOptions);
@@ -129,9 +119,9 @@ int main(int argc, char **argv)
if (parser.isSet(outputFileOption))
outputFileName = parser.value(outputFileOption);
- if (outputFileName.endsWith(QLatin1String(".cpp"))) {
+ if (outputFileName.endsWith(".cpp"_L1)) {
target = GenerateCpp;
- if (outputFileName.endsWith(QLatin1String("qmlcache_loader.cpp")))
+ if (outputFileName.endsWith("qmlcache_loader.cpp"_L1))
target = GenerateLoader;
}
@@ -142,13 +132,13 @@ int main(int argc, char **argv)
if (sources.isEmpty()){
parser.showHelp();
} else if (sources.size() > 1 && (target != GenerateLoader && target != GenerateLoaderStandAlone)) {
- fprintf(stderr, "%s\n", qPrintable(QStringLiteral("Too many input files specified: '") + sources.join(QStringLiteral("' '")) + QLatin1Char('\'')));
+ fprintf(stderr, "%s\n", qPrintable("Too many input files specified: '"_L1 + sources.join("' '"_L1) + u'\''));
return EXIT_FAILURE;
}
const QString inputFile = !sources.isEmpty() ? sources.first() : QString();
if (outputFileName.isEmpty())
- outputFileName = inputFile + QLatin1Char('c');
+ outputFileName = inputFile + u'c';
if (parser.isSet(filterResourceFileOption))
return qRelocateResourceFile(inputFile, outputFileName);
@@ -160,7 +150,7 @@ int main(int argc, char **argv)
if (!qQmlJSGenerateLoader(
mapper.resourcePaths(QQmlJSResourceFileMapper::allQmlJSFilter()),
outputFileName, parser.values(resourceFileMappingOption), &error.message)) {
- error.augment(QLatin1String("Error generating loader stub: ")).print();
+ error.augment("Error generating loader stub: "_L1).print();
return EXIT_FAILURE;
}
return EXIT_SUCCESS;
@@ -170,7 +160,7 @@ int main(int argc, char **argv)
QQmlJSCompileError error;
if (!qQmlJSGenerateLoader(sources, outputFileName,
parser.values(resourceNameOption), &error.message)) {
- error.augment(QLatin1String("Error generating loader stub: ")).print();
+ error.augment("Error generating loader stub: "_L1).print();
return EXIT_FAILURE;
}
return EXIT_SUCCESS;
@@ -205,13 +195,12 @@ int main(int argc, char **argv)
}
if (target == GenerateCpp) {
- inputFileUrl = QStringLiteral("qrc://") + inputResourcePath;
+ inputFileUrl = "qrc://"_L1 + inputResourcePath;
saveFunction = [inputResourcePath, outputFileName](
const QV4::CompiledData::SaveableUnitPointer &unit,
const QQmlJSAotFunctionMap &aotFunctions,
QString *errorString) {
- return qSaveQmlJSUnitAsCpp(inputResourcePath, outputFileName, unit, aotFunctions,
- errorString);
+ return qSaveQmlJSUnitAsCpp(inputResourcePath, outputFileName, unit, aotFunctions, errorString);
};
} else {
@@ -227,20 +216,20 @@ int main(int argc, char **argv)
};
}
- if (inputFile.endsWith(QLatin1String(".qml"))) {
+ if (inputFile.endsWith(".qml"_L1)) {
QQmlJSCompileError error;
if (target != GenerateCpp || inputResourcePath.isEmpty() || parser.isSet(onlyBytecode)) {
if (!qCompileQmlFile(inputFile, saveFunction, nullptr, &error,
/* storeSourceLocation */ false)) {
- error.augment(QStringLiteral("Error compiling qml file: ")).print();
+ error.augment("Error compiling qml file: "_L1).print();
return EXIT_FAILURE;
}
} else {
QStringList importPaths;
if (parser.isSet(resourceOption)) {
- importPaths.append(QLatin1String(":/qt-project.org/imports"));
- importPaths.append(QLatin1String(":/qt/qml"));
+ importPaths.append("qt-project.org/imports"_L1);
+ importPaths.append("qt/qml"_L1);
};
if (parser.isSet(importPathOption))
@@ -264,24 +253,27 @@ int main(int argc, char **argv)
QQmlJSAotCompiler cppCodeGen(
&importer, u':' + inputResourcePath, parser.values(importsOption), &logger);
+ if (parser.isSet(validateBasicBlocksOption))
+ cppCodeGen.m_flags.setFlag(QQmlJSAotCompiler::ValidateBasicBlocks);
+
if (!qCompileQmlFile(inputFile, saveFunction, &cppCodeGen, &error,
/* storeSourceLocation */ true)) {
- error.augment(QStringLiteral("Error compiling qml file: ")).print();
+ error.augment("Error compiling qml file: "_L1).print();
return EXIT_FAILURE;
}
QList<QQmlJS::DiagnosticMessage> warnings = importer.takeGlobalWarnings();
if (!warnings.isEmpty()) {
- logger.log(QStringLiteral("Type warnings occurred while compiling file:"),
+ logger.log("Type warnings occurred while compiling file:"_L1,
qmlImport, QQmlJS::SourceLocation());
logger.processMessages(warnings, qmlImport);
}
}
- } else if (inputFile.endsWith(QLatin1String(".js")) || inputFile.endsWith(QLatin1String(".mjs"))) {
+ } else if (inputFile.endsWith(".js"_L1) || inputFile.endsWith(".mjs"_L1)) {
QQmlJSCompileError error;
if (!qCompileJSFile(inputFile, inputFileUrl, saveFunction, &error)) {
- error.augment(QLatin1String("Error compiling js file: ")).print();
+ error.augment("Error compiling js file: "_L1).print();
return EXIT_FAILURE;
}
} else {