// cxxProbe.cpp - full C++ ABI validation incl. dtor invocation.
//   $025000 = 0xC0DE  Singleton ctor (1st inst())
//   $025002 = 0x4242  heap value via new + member access
//   $025004 =      1  Singleton ctor count after 3 inst()s (guard works)
//   $025006 = 0x6707  global ctor (init_array)
//   $025008 = 0x900D  end of main
//   $02500A = 0xDEAD  Singleton DTOR ran (via __cxa_atexit walk)
//   $02500C = 0xFEED  Global DTOR ran (via __cxa_atexit walk)
extern "C" {
#include <stdint.h>
}

static int gSingletonCtorCalls = 0;

struct Singleton {
    int n;
    Singleton() : n(0xC0DE) {
        gSingletonCtorCalls++;
        *(volatile uint16_t *)0x025000UL = (uint16_t)n;
    }
    ~Singleton() {
        *(volatile uint16_t *)0x02500AUL = 0xDEAD;
    }
};

static Singleton &inst() {
    static Singleton s;
    return s;
}

struct Heap {
    int v;
    Heap(int x) : v(x) {}
};

struct GlobalCtor {
    GlobalCtor() {
        *(volatile uint16_t *)0x025006UL = 0x6707;
    }
    ~GlobalCtor() {
        *(volatile uint16_t *)0x02500CUL = 0xFEED;
    }
};

static GlobalCtor gGlobal;
static volatile Heap *gHeapEscape = nullptr;

int main(void) {
    inst(); inst();
    Singleton &s = inst();
    (void)s;
    Heap *h = new Heap(0x4242);
    gHeapEscape = h;
    *(volatile uint16_t *)0x025002UL = (uint16_t)gHeapEscape->v;
    gHeapEscape = nullptr;
    delete h;
    *(volatile uint16_t *)0x025004UL = (uint16_t)gSingletonCtorCalls;
    *(volatile uint16_t *)0x025008UL = 0x900D;
    return 0;
}
