aboutsummaryrefslogtreecommitdiffstats
path: root/tools/qmlcachegen/qmlcachegen.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'tools/qmlcachegen/qmlcachegen.cpp')
-rw-r--r--tools/qmlcachegen/qmlcachegen.cpp89
1 files changed, 73 insertions, 16 deletions
diff --git a/tools/qmlcachegen/qmlcachegen.cpp b/tools/qmlcachegen/qmlcachegen.cpp
index 977c5b6ff1..9a68e2ac97 100644
--- a/tools/qmlcachegen/qmlcachegen.cpp
+++ b/tools/qmlcachegen/qmlcachegen.cpp
@@ -80,7 +80,40 @@ QString diagnosticErrorMessage(const QString &fileName, const QQmlJS::Diagnostic
return message;
}
-static bool compileQmlFile(const QString &inputFileName, QV4::EvalISelFactory *iselFactory, Error *error)
+// Ensure that ListElement objects keep all property assignments in their string form
+static void annotateListElements(QmlIR::Document *document)
+{
+ QStringList listElementNames;
+
+ foreach (const QV4::CompiledData::Import *import, document->imports) {
+ const QString uri = document->stringAt(import->uriIndex);
+ if (uri != QStringLiteral("QtQml.Models") && uri != QStringLiteral("QtQuick"))
+ continue;
+
+ QString listElementName = QStringLiteral("ListElement");
+ const QString qualifier = document->stringAt(import->qualifierIndex);
+ if (!qualifier.isEmpty()) {
+ listElementName.prepend(QLatin1Char('.'));
+ listElementName.prepend(qualifier);
+ }
+ listElementNames.append(listElementName);
+ }
+
+ if (listElementNames.isEmpty())
+ return;
+
+ foreach (QmlIR::Object *object, document->objects) {
+ if (!listElementNames.contains(document->stringAt(object->inheritedTypeNameIndex)))
+ continue;
+ for (QmlIR::Binding *binding = object->firstBinding(); binding; binding = binding->next) {
+ if (binding->type != QV4::CompiledData::Binding::Type_Script)
+ continue;
+ binding->stringIndex = document->registerString(object->bindingAsString(document, binding->value.compiledScriptIndex));
+ }
+ }
+}
+
+static bool compileQmlFile(const QString &inputFileName, const QString &outputFileName, QV4::EvalISelFactory *iselFactory, Error *error)
{
QmlIR::Document irDocument(/*debugMode*/false);
@@ -96,7 +129,6 @@ static bool compileQmlFile(const QString &inputFileName, QV4::EvalISelFactory *i
error->message = QLatin1String("Error reading from ") + inputFileName + QLatin1Char(':') + f.errorString();
return false;
}
- irDocument.jsModule.sourceTimeStamp = QFileInfo(f).lastModified().toMSecsSinceEpoch();
}
{
@@ -112,8 +144,10 @@ static bool compileQmlFile(const QString &inputFileName, QV4::EvalISelFactory *i
}
}
+ annotateListElements(&irDocument);
+
{
- QmlIR::JSCodeGen v4CodeGen(inputFileName, irDocument.code, &irDocument.jsModule, &irDocument.jsParserEngine, irDocument.program, /*import cache*/0, &irDocument.jsGenerator.stringTable);
+ QmlIR::JSCodeGen v4CodeGen(/*empty input file name*/QString(), irDocument.code, &irDocument.jsModule, &irDocument.jsParserEngine, irDocument.program, /*import cache*/0, &irDocument.jsGenerator.stringTable);
for (QmlIR::Object *object: qAsConst(irDocument.objects)) {
if (object->functionsAndExpressions->count == 0)
continue;
@@ -153,7 +187,7 @@ static bool compileQmlFile(const QString &inputFileName, QV4::EvalISelFactory *i
unit->flags |= QV4::CompiledData::Unit::PendingTypeCompilation;
irDocument.javaScriptCompilationUnit->data = unit;
- if (!irDocument.javaScriptCompilationUnit->saveToDisk(inputFileName, &error->message))
+ if (!irDocument.javaScriptCompilationUnit->saveToDisk(outputFileName, &error->message))
return false;
free(unit);
@@ -161,7 +195,7 @@ static bool compileQmlFile(const QString &inputFileName, QV4::EvalISelFactory *i
return true;
}
-static bool compileJSFile(const QString &inputFileName, QV4::EvalISelFactory *iselFactory, Error *error)
+static bool compileJSFile(const QString &inputFileName, const QString &outputFileName, QV4::EvalISelFactory *iselFactory, Error *error)
{
QmlIR::Document irDocument(/*debugMode*/false);
@@ -177,7 +211,6 @@ static bool compileJSFile(const QString &inputFileName, QV4::EvalISelFactory *is
error->message = QLatin1String("Error reading from ") + inputFileName + QLatin1Char(':') + f.errorString();
return false;
}
- irDocument.jsModule.sourceTimeStamp = QFileInfo(f).lastModified().toMSecsSinceEpoch();
}
QQmlJS::Engine *engine = &irDocument.jsParserEngine;
@@ -217,7 +250,7 @@ static bool compileJSFile(const QString &inputFileName, QV4::EvalISelFactory *is
{
QmlIR::JSCodeGen v4CodeGen(inputFileName, irDocument.code, &irDocument.jsModule, &irDocument.jsParserEngine, irDocument.program, /*import cache*/0, &irDocument.jsGenerator.stringTable);
- v4CodeGen.generateFromProgram(inputFileName, sourceCode, program, &irDocument.jsModule, QQmlJS::Codegen::GlobalCode);
+ v4CodeGen.generateFromProgram(/*empty input file name*/QString(), sourceCode, program, &irDocument.jsModule, QQmlJS::Codegen::GlobalCode);
QList<QQmlJS::DiagnosticMessage> jsErrors = v4CodeGen.errors();
if (!jsErrors.isEmpty()) {
for (const QQmlJS::DiagnosticMessage &e: qAsConst(jsErrors)) {
@@ -233,7 +266,8 @@ static bool compileJSFile(const QString &inputFileName, QV4::EvalISelFactory *is
// ### translation binding simplification
- QScopedPointer<QV4::EvalInstructionSelection> isel(iselFactory->create(/*engine*/nullptr, /*executable allocator*/nullptr, &irDocument.jsModule, &irDocument.jsGenerator));
+ QV4::ExecutableAllocator allocator;
+ QScopedPointer<QV4::EvalInstructionSelection> isel(iselFactory->create(/*engine*/nullptr, &allocator, &irDocument.jsModule, &irDocument.jsGenerator));
// Disable lookups in non-standalone (aka QML) mode
isel->setUseFastLookups(false);
irDocument.javaScriptCompilationUnit = isel->compile(/*generate unit*/false);
@@ -243,7 +277,7 @@ static bool compileJSFile(const QString &inputFileName, QV4::EvalISelFactory *is
unit->flags |= QV4::CompiledData::Unit::StaticData;
irDocument.javaScriptCompilationUnit->data = unit;
- if (!irDocument.javaScriptCompilationUnit->saveToDisk(inputFileName, &error->message)) {
+ if (!irDocument.javaScriptCompilationUnit->saveToDisk(outputFileName, &error->message)) {
engine->setDirectives(oldDirs);
return false;
}
@@ -270,37 +304,60 @@ int main(int argc, char **argv)
QCommandLineOption targetArchitectureOption(QStringLiteral("target-architecture"), QCoreApplication::translate("main", "Target architecture"), QCoreApplication::translate("main", "architecture"));
parser.addOption(targetArchitectureOption);
+ QCommandLineOption outputFileOption(QStringLiteral("o"), QCoreApplication::translate("main", "Output file name"), QCoreApplication::translate("main", "file name"));
+ parser.addOption(outputFileOption);
+
+ QCommandLineOption checkIfSupportedOption(QStringLiteral("check-if-supported"), QCoreApplication::translate("main", "Check if cache generate is supported on the specified target architecture"));
+ parser.addOption(checkIfSupportedOption);
+
parser.addPositionalArgument(QStringLiteral("[qml file]"),
QStringLiteral("QML source file to generate cache for."));
parser.process(app);
- const QStringList sources = parser.positionalArguments();
- if (sources.isEmpty()){
+ if (!parser.isSet(targetArchitectureOption)) {
+ fprintf(stderr, "Target architecture not specified. Please specify with --target-architecture=<arch>\n");
parser.showHelp();
- } else if (sources.count() > 1) {
- fprintf(stderr, "%s\n", qPrintable(QStringLiteral("Too many input files specified: '") + sources.join(QStringLiteral("' '")) + QLatin1Char('\'')));
return EXIT_FAILURE;
}
- const QString inputFile = sources.first();
QScopedPointer<QV4::EvalISelFactory> isel;
const QString targetArchitecture = parser.value(targetArchitectureOption);
isel.reset(QV4::JIT::createISelForArchitecture(targetArchitecture));
+ if (parser.isSet(checkIfSupportedOption)) {
+ if (isel.isNull())
+ return EXIT_FAILURE;
+ else
+ return EXIT_SUCCESS;
+ }
+
+ const QStringList sources = parser.positionalArguments();
+ if (sources.isEmpty()){
+ parser.showHelp();
+ } else if (sources.count() > 1) {
+ fprintf(stderr, "%s\n", qPrintable(QStringLiteral("Too many input files specified: '") + sources.join(QStringLiteral("' '")) + QLatin1Char('\'')));
+ return EXIT_FAILURE;
+ }
+ const QString inputFile = sources.first();
+
if (!isel)
isel.reset(new QV4::Moth::ISelFactory);
Error error;
+ QString outputFileName = inputFile + QLatin1Char('c');
+ if (parser.isSet(outputFileOption))
+ outputFileName = parser.value(outputFileOption);
+
if (inputFile.endsWith(QLatin1String(".qml"))) {
- if (!compileQmlFile(inputFile, isel.data(), &error)) {
+ if (!compileQmlFile(inputFile, outputFileName, isel.data(), &error)) {
error.augment(QLatin1String("Error compiling qml file: ")).print();
return EXIT_FAILURE;
}
} else if (inputFile.endsWith(QLatin1String(".js"))) {
- if (!compileJSFile(inputFile, isel.data(), &error)) {
+ if (!compileJSFile(inputFile, outputFileName, isel.data(), &error)) {
error.augment(QLatin1String("Error compiling qml file: ")).print();
return EXIT_FAILURE;
}