Skip to content

Analyzer Modules Architecture

Hugo edited this page Sep 25, 2026 · 2 revisions

Analyzer Modules Architecture

This page describes the module split around StackUsageAnalyzer that keeps orchestration concerns separate from pass logic and reporting.


Goals

  • Reduce coupling between CLI/app orchestration and LLVM analysis details.
  • Keep module responsibilities narrow and independently testable.
  • Preserve existing behavior while improving maintainability.

Core Modules

src/analyzer/AnalysisPipeline.cpp

Role:

  • Coordinator for module-level analysis execution.
  • Orders preparation, pass execution, and diagnostic emission.

Pattern:

  • Facade over lower-level analyzer services.

src/analyzer/ModulePreparationService.cpp

Role:

  • Builds prepared module context (PreparedModule).
  • Computes stack metadata, filtered call graph, and recursion state.

Pattern:

  • Application service with deterministic derivation logic.

src/analyzer/LocationResolver.cpp

Role:

  • Resolves source file/line/column from LLVM debug metadata.
  • Provides fallback logic for alloca/debug intrinsics.

Pattern:

  • Stateless domain service.

src/analyzer/DiagnosticEmitter.cpp

Role:

  • Converts analysis findings to final Diagnostic objects.
  • Centralizes severity, rule IDs, message formatting, and CWE enrichment.

Pattern:

  • Adapter between analysis-domain findings and report-domain output.

src/analysis/Reachability.cpp

Role:

  • Classifies findings in statically unreachable code paths.

Pattern:

  • Isolated policy module.

Shared Traversal Modules

These came with the shared-analysis-infrastructure work. They exist so several checks stop walking the same IR independently.

include/analyzer/InstructionSubscriber.hpp

Role:

  • The subscriber interface: a module registers interest in instruction kinds (AllocaInst, CallInst, …) and is called during one traversal.
  • InstructionSubscriberRegistry dispatches to every registered subscriber.

Pattern:

  • Observer over a single IR walk, replacing one walk per check.

src/analyzer/IRFactCollector.cpp

Role:

  • Collects IRFacts for a module in that single traversal, from the registered subscribers.

src/analyzer/PerFunctionInstructionCache.cpp

Role:

  • A subscriber that keeps PerFunctionData — the per-function instruction groupings the checks ask for repeatedly.

include/analyzer/DerivedModuleArtifacts.hpp

Role:

  • Indexes derived once per module and reused: DebugMetadataIndex, FunctionSymbolIndex, TypeFactIndex.

include/analyzer/AnalysisArtifactStore.hpp

Role:

  • Holds the derived artifacts for the run, so a later stage takes them instead of recomputing.

src/analyzer/HotspotProfiler.cpp

Role:

  • HotspotSample, HotspotProfiler and the ScopedHotspot RAII helper behind --timing.
  • Produces the process-level hotspot ranking sorted by cumulative time (CTRACE_HOTSPOT_TOP=<N>, default 20, max 200).

Data Flow

  1. Input loading compiles/parses sources into an LLVM module.
  2. ModulePreparationService derives reusable analysis context.
  3. IRFactCollector walks the module once, feeding every registered InstructionSubscriber; the derived indexes land in the AnalysisArtifactStore.
  4. Analysis modules compute findings from those facts.
  5. Reachability annotates/filters findings where needed.
  6. LocationResolver maps findings to source coordinates.
  7. DiagnosticEmitter emits final diagnostics for human/JSON/SARIF outputs.
  8. Optionally, the SMT layer refines the findings that remain imprecise.

Why This Split

  • Better testability: each module has a narrow API and predictable inputs.
  • Clear evolution path: adding checks does not require touching CLI/app orchestration.
  • Lower regression risk: location/rule formatting logic is centralized.

Related Tests

Fine-grained unit tests:

  • test/unit/analyzer_module_unit_tests.cpp

Covered modules:

  • LocationResolver
  • Reachability
  • ModulePreparationService

Plus the resource ownership engine, in its own suites:

  • test/unit/ownership_engine_unit_tests.cpp
  • test/unit/ownership_collector_input.cpp

Build target:

  • stack_usage_analyzer_unit_tests (enable with -DBUILD_ANALYZER_UNIT_TESTS=ON)

Clone this wiki locally