Skip to content

Recognize and simplify atomic reference counting patterns #163

Description

@kumarak

Problem

Qt/STL atomic reference counting operations expand into verbose inline code in decompiled output:

iVar3 = ((log_path.d)->super_QArrayData).ref.atomic._q_value.super___atomic_base<int>._M_i;
if ((iVar3 == 0) ||
   ((iVar3 != -1 && (iVar3 = __aarch64_ldadd4_acq_rel(-1, (int *)log_path.d), iVar3 == 1)))) {
    _ZN10QArrayData10deallocateEPS_mm(log_path.d, 2, 8);
}

This is a Qt `QAtomicInt::deref()` pattern (atomic decrement + check if last reference) followed by deallocation. It repeats 5-6 times in a single function.

Ideal output:

if (QAtomicInt_deref(&log_path.d->ref)) {
    QArrayData_deallocate(log_path.d, 2, 8);
}

Root Cause

  1. `__aarch64_ldadd4_acq_rel` is an architecture-specific atomic intrinsic — no platform-independent abstraction exists
  2. The surrounding if/else pattern is a standard Qt refcount idiom but the pipeline has no pattern recognition for it
  3. The deep struct access chain (separate issue Flatten super_BaseClass inheritance chains in struct member access #159) makes the pattern even harder to read

Proposed Fix

This is a longer-term improvement that could be addressed via:

  1. Intrinsic mapping: Map `__aarch64_ldadd4_acq_rel` to a platform-generic `atomic_fetch_add` name
  2. Pattern recognition pass: Detect the "load atomic → compare 0/-1 → conditional dealloc" idiom and collapse to a single function call
  3. Library-aware simplification: When Qt/STL types are detected, apply known patterns

Files

  • `lib/patchestry/AST/OperationStmt.cpp` — CALL/CALLOTHER handling
  • `scripts/ghidra/util/PcodeSerializer.java` — intrinsic name resolution

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Fields

    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions