Bug 575881 - When using constexpr template recursion and few other features in a obscure way, I can get the indexer to freeze
Summary: When using constexpr template recursion and few other features in a obscure w...
Status: NEW
Alias: None
Product: CDT
Classification: Tools
Component: cdt-indexer (show other bugs)
Version: 10.2.0   Edit
Hardware: PC Windows 10
: P3 normal (vote)
Target Milestone: ---   Edit
Assignee: Project Inbox CLA
QA Contact: Jonah Graham CLA
URL:
Whiteboard:
Keywords:
Depends on:
Blocks:
 
Reported: 2021-09-08 12:07 EDT by Anton Krug CLA
Modified: 2021-09-08 12:09 EDT (History)
2 users (show)

See Also:


Attachments
screenshot showing stm cube 1.7.0 indexer stuck (10.17 KB, image/png)
2021-09-08 12:07 EDT, Anton Krug CLA
no flags Details

Note You need to log in before you can comment on or make changes to this bug.
Description Anton Krug CLA 2021-09-08 12:07:10 EDT
Created attachment 287111 [details]
screenshot showing stm cube 1.7.0 indexer stuck

The code in the project is probably not the best way to do it and the fact that it's confusing the indexer is a sign that it should be rewritten. However, still it's a valid code which compiles and runs correctly.

I'm in process of narrowing it down to the smallest replicator, but couldn't replicate yet when I use a subset of the project.

My suspission was that the recursive invocation of templates is not good:

    template <uint32_t lookupIndex>
    constexpr std::array<commandHandler, 256> populateApiTable() {
        auto result = populateApiTable<lookupIndex + 1>();
        result[lookupIndex] = apiSwitch<lookupIndex>;

        return result;
    }


    template <>
    constexpr std::array<commandHandler, 256> populateApiTable<256>() {
        std::array<commandHandler, 256> lookupTable = { &failure };
        return lookupTable;
    }


    const std::array<commandHandler, 256> handlers = populateApiTable<0>();

However making a smaller replicator around this didn't trigger the problem, it might be related that the apiSwitch which is another constexpr with template argument which is forcing it to be effectively a consteval (compile-time domain). And the idea was optimise the switch-case statement to compile time lookup table. Sometimes toolchains can detect it and do on my behalf, but the triggers/limits when it starts to be happening and when it's too  big to be a lookup table might change depending on the optimization levels and between the toolchains. This way it guaranteed to be optimized even at debug level. One of the API commands is bit more tricky and can evaluate to multiple different function calls depending on some bits, which might be another cause for the indexer to be confused:


        case commandE::scan: {
          // Take the higher 4-bits and calculate what SCAN variation it would be
          const uint32_t scanVariation = COMMAND_ID & 0b1111'0000;

          // Break up the SCAN variation into its components
          const auto isDr           = static_cast<scan::captureE>(     scanVariation & (1u << static_cast<uint8_t>(scanBitsE::isDr)));
          const auto isReadWrite    = static_cast<scan::accessE>(      scanVariation & (1u << static_cast<uint8_t>(scanBitsE::isReadWrite)));
          const auto isLenOpcode    = static_cast<scan::opcodeLengthE>(scanVariation & (1u << static_cast<uint8_t>(scanBitsE::isLenArgument)));
          const auto isLenFitInto32 = static_cast<scan::lenSizeFitsE>( scanVariation & (1u << static_cast<uint8_t>(scanBitsE::isLenOver32)));

          ret = scan::generic<isDr, isReadWrite, scan::endstateE::useGlobal, isLenOpcode, isLenFitInto32>(req, res);
          break;
        }

I'm trying to pinpoint the exact cause and make it replicable on vanilla Eclipse  CDT, but in the meantime, I will use this bug as a placeholder so this issue will not get forgotten.

The full STM Cube 1.7.0 project is located here: 
https://github.com/AntonKrug/akJtagPlusPlus

My biggest suspect for this issue is akJtagPlusPlus\Core\Src\jtag\api.cpp file, but overall a lot of the project is doing fairly dodgy shortcuts, tricks and relying on things a good project shouldn't. The goal with the project was not to do some industry-standard rock-solid code, but experiment with some stuff and see what happens, which in some sense (with this bug) is some success :)

When I wipe/clean the project many of the files get processed/indexed correctly but it will stuck on some eventually. Then restarting, forcing indexing, canceling or anything I could think off will not help. After the restart the indexer stops straight away because it's not processing again files that correctly indexed and it makes an illusion as it's stuck on the very first file it processed, but that's not the case.
Comment 1 Anton Krug CLA 2021-09-08 12:09:33 EDT
For convenience adding a link to one of the suspicious files:

https://github.com/AntonKrug/akJtagPlusPlus/blob/main/Core/Src/jtag/api.cpp