diff options
| author | Olivier De Cannière <olivier.decanniere@qt.io> | 2023-07-11 15:01:10 +0200 |
|---|---|---|
| committer | Olivier De Cannière <olivier.decanniere@qt.io> | 2023-08-04 09:34:09 +0200 |
| commit | 2cf9aeccddbd06a66df94bd27916714c4a5c7e24 (patch) | |
| tree | f147cabe8e7f8d3dfcf1b02cf8d730e851fcc0a6 /tests/auto/qml/qmlcppcodegen/tst_qmlcppcodegen.cpp | |
| parent | 0667e68e7715f60916ee91189925855e1dcf5f0e (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 'tests/auto/qml/qmlcppcodegen/tst_qmlcppcodegen.cpp')
| -rw-r--r-- | tests/auto/qml/qmlcppcodegen/tst_qmlcppcodegen.cpp | 39 |
1 files changed, 39 insertions, 0 deletions
diff --git a/tests/auto/qml/qmlcppcodegen/tst_qmlcppcodegen.cpp b/tests/auto/qml/qmlcppcodegen/tst_qmlcppcodegen.cpp index 0c9648a19d..db1ae4f08b 100644 --- a/tests/auto/qml/qmlcppcodegen/tst_qmlcppcodegen.cpp +++ b/tests/auto/qml/qmlcppcodegen/tst_qmlcppcodegen.cpp @@ -30,6 +30,7 @@ class tst_QmlCppCodegen : public QObject Q_OBJECT private slots: void initTestCase(); + void cleanupTestCase(); void accessModelMethodFromOutSide(); void aliasLookup(); void ambiguousAs(); @@ -43,6 +44,7 @@ private slots: void attachedType(); void badSequence(); void basicBlocksWithBackJump(); + void basicBlocksWithBackJump_infinite(); void basicDTZ(); void bindToValueType(); void bindingExpression(); @@ -458,6 +460,34 @@ void tst_QmlCppCodegen::initTestCase() #endif } +void tst_QmlCppCodegen::cleanupTestCase() +{ + // This code checks for basic blocks validation failures in the tests + QStringList expectedFailures = { + "codegen_test_module_basicBlocksWithBackJump_infinite_qml.cpp", + "codegen_test_module_verify_basicBlocksWithBackJump_infinite_qml.cpp", + }; + + QString generatedCppFolder = GENERATED_CPP_FOLDER; + QDirIterator dirIterator(generatedCppFolder, { "*.cpp" }, QDir::Files); + while (dirIterator.hasNext()) { + QFile file(dirIterator.next()); + if (!file.open(QIODeviceBase::ReadOnly | QIODeviceBase::Text)) { + qDebug() << "Couldn't open generated file"; + continue; + } + + const auto content = file.readAll(); + if (bool validationFailed = content.contains("// QV4_BASIC_BLOCK_VALIDATION_FAILED:"_L1)) { + if (expectedFailures.contains(dirIterator.fileInfo().fileName())) { + QEXPECT_FAIL("", "Expected failure", Continue); + } + const auto message = file.fileName() + ": Basic blocks validation failed."; + QVERIFY2(!validationFailed, message.toStdString().c_str()); + } + } +} + void tst_QmlCppCodegen::accessModelMethodFromOutSide() { QQmlEngine engine; @@ -744,6 +774,15 @@ void tst_QmlCppCodegen::basicBlocksWithBackJump() QVERIFY(!expectingMessage); } +void tst_QmlCppCodegen::basicBlocksWithBackJump_infinite() +{ + QQmlEngine engine; + QQmlComponent component(&engine, QUrl(u"qrc:/qt/qml/TestTypes/basicBlocksWithBackJump_infinite.qml"_s)); + QVERIFY2(component.isReady(), qPrintable(component.errorString())); + QScopedPointer<QObject> o(component.create()); + QVERIFY(!o.isNull()); +} + void tst_QmlCppCodegen::basicDTZ() { QQmlEngine engine; |
