runtime: give ten more cross-language globals C linkage in main.cpp

Second report on #244: main.cpp references C-defined globals that MSVC
cannot resolve. MSVC mangles namespace-scope variables; the Itanium ABI
does not, so a C++ reference to a C global links on GCC/Clang and fails
under MSVC with an unresolved external.

main.cpp already has the fix pattern -- the file-scope extern "C" block
added by the earlier MSVC pass, with a comment saying exactly this. Ten
globals added since then never made it into the block:

  memory.c            i_stat, i_mask, g_guest_store_count,
                      g_vblank_ack_count
  interrupts.c        g_vblank_raise_count, g_vblank_deliver_count
  dirty_ram_interp.c  g_dirty_ram_blocks_run, g_dirty_pump_count
  overlay_loader.c    g_call_unit_depth
  psx_bios_backend.c  g_psx_dispatch_depth

Each is referenced only through a block-scope `extern` inside a function.
With no namespace-scope declaration in view, that block-scope declaration
gives the entity C++ linkage, which is the failure. Declaring them in the
file-scope extern "C" block fixes it without touching the use sites: the
block-scope redeclarations now inherit C linkage, as the block's comment
already describes for the symbols that were there.

Which ten was measured, not eyeballed. Every block-scope extern in
main.cpp (31 distinct symbols) was probed by appending
`extern "C++" { extern T sym; }` to a copy of the file compiled with the
target's real command line: a conflicting-linkage diagnostic means the
symbol already has C linkage from an extern "C" header, silence means it
does not. 21 came back already-C (declared in psx_cycles.h, cpu_state.h,
debug_server.h and friends, or already in this block); these 10 came back
C++. After the change all 31 probe as C linkage.

Audited beyond main.cpp: it is the only C++ TU in the runtime with this
pattern. beetle_libretro.cpp's `extern PS_GPU GPU` / `extern PS_CDC *PSX_CDC`
are genuine C++ symbols from the Beetle core, correctly left with C++
linkage, and psx-beetle is not built under MSVC in any case.

No behaviour change on the existing toolchains: main.cpp.o is byte-identical
to its origin/master build. Full runtime suite on a clean build dir is 47/48,
the single failure being gte_register_access_test, which fails identically at
origin/master (43/44 there) -- it links gte.cpp + pgxp.cpp but references
gpu_ws_precise_nclip_enabled, defined in gpu.c, which is not in that target.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_014YD7rrVK63Kncki6prB65S
This commit is contained in:
Alex Vanderveen
2026-08-27 16:30:26 -04:00
parent a9a732aae8
commit f74ffcae33
+13
View File
@@ -187,6 +187,19 @@ extern "C" {
extern uint64_t g_dirty_window_dispatches;
extern uint32_t g_slice_exit_pc, g_slice_exit_reason, g_slice_exit_iter;
extern uint32_t g_slice_exit_dispatchable, g_slice_exit_dirty, g_slice_exit_in_text, g_slice_exit_want;
/* memory.c */
extern uint32_t i_stat, i_mask;
extern uint64_t g_guest_store_count;
extern uint64_t g_vblank_ack_count;
/* interrupts.c */
extern uint64_t g_vblank_raise_count, g_vblank_deliver_count;
/* dirty_ram_interp.c */
extern uint64_t g_dirty_ram_blocks_run;
extern uint64_t g_dirty_pump_count;
/* overlay_loader.c */
extern int g_call_unit_depth;
/* psx_bios_backend.c */
extern int g_psx_dispatch_depth;
}
/* memory.c */