Skip to content

gcc 16#375

Merged
skeeto merged 1 commit intoskeeto:masterfrom
Peter0x44:gcc16
May 2, 2026
Merged

gcc 16#375
skeeto merged 1 commit intoskeeto:masterfrom
Peter0x44:gcc16

Conversation

@Peter0x44
Copy link
Copy Markdown
Collaborator

No description provided.

@Peter0x44
Copy link
Copy Markdown
Collaborator Author

Peter0x44 commented May 1, 2026

Improved support for C++20, including:
The C++20 implementation is no longer experimental.
Working std::chrono::current_zone() on Windows (thanks to Björn Schäpers).

#44 115.2 /dl/gcc/libstdc++-v3/src/c++20/tzdb.cc: In function 'std::string_view std::chrono::{anonymous}::detect_windows_zone()':
#44 115.2 /dl/gcc/libstdc++-v3/src/c++20/tzdb.cc:1790:11: error: 'GetDynamicTimeZoneInformation' was not declared in this scope; did you mean 'GetTimeZoneInformation'?
#44 115.2  1790 |       if (GetDynamicTimeZoneInformation(&information) == TIME_ZONE_ID_INVALID)
#44 115.2       |           ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~
#44 115.2       |           GetTimeZoneInformation

Hmm. I feel, could be related to _WIN32_WINNT.

Minimum supported client | Windows Vista [desktop apps \| UWP apps]
-- | --
Minimum supported server | Windows Server 2008 [desktop apps \| UWP apps]

https://learn.microsoft.com/en-us/windows/win32/api/timezoneapi/nf-timezoneapi-getdynamictimezoneinformation

(note that these minimums are frequently wrong)
I will test out the x64 before I go back to look at this.

@Peter0x44
Copy link
Copy Markdown
Collaborator Author

c++ -o vulkan-shaders-gen.exe ggml/src/ggml-vulkan/vulkan-shaders/vulkan-shaders-gen.cpp.gen.o
C:/programming/toolchains/w64devkit/bin/ld.exe: ggml/src/ggml-vulkan/vulkan-shaders/vulkan-shaders-gen.cpp.gen.o:vulkan-shaders-gen.cpp:(.rdata$.refptr.__emutls_v._ZSt11__once_call[.refptr.__emutls_v._ZSt11__once_call]+0x0): undefined reference to `__emutls_v._ZSt11__once_call'
C:/programming/toolchains/w64devkit/bin/ld.exe: ggml/src/ggml-vulkan/vulkan-shaders/vulkan-shaders-gen.cpp.gen.o:vulkan-shaders-gen.cpp:(.rdata$.refptr.__emutls_v._ZSt15__once_callable[.refptr.__emutls_v._ZSt15__once_callable]+0x0): undefined reference to `__emutls_v._ZSt15__once_callable'
collect2.exe: error: ld returned 1 exit status

Turns out llama.mak's clean rule is a little buggy, this was caused by ggml/src/ggml-vulkan/vulkan-shaders/vulkan-shaders-gen.cpp.gen.o being stale. Native TLS is a total ABI-break, all old object files are incompatible. Which I did expect, and is OK, but worth putting on the release note.

@Peter0x44 Peter0x44 mentioned this pull request May 1, 2026
@Peter0x44
Copy link
Copy Markdown
Collaborator Author

Peter0x44 commented May 1, 2026

Looks like @CyanoHao already made a patch for the tzdb issue.
https://github.com/redpanda-cpp/mingw-lite/blob/master/patch/gcc/dynamic-load-tzdb.patch

I will import that one.

@CyanoHao
Copy link
Copy Markdown

CyanoHao commented May 1, 2026

@Peter0x44 oops I made a mistake. The function pointer should be static.

static const auto *GetDynamicTimeZoneInformation =
  reinterpret_cast(
    GetProcAddress(kernel32, "GetDynamicTimeZoneInformation"));

Update: static auto *const GetDynamicTimeZoneInformation (or whatever equivalent). I realized why I made that mistake... 🤦

@Peter0x44 Peter0x44 force-pushed the gcc16 branch 2 times, most recently from 6d31c4b to 6928ac0 Compare May 1, 2026 09:31
@Peter0x44
Copy link
Copy Markdown
Collaborator Author

Peter0x44 commented May 1, 2026

I checked out std::breakpoint, and probably it's just doing int3 and not int3;nop (I remember reviewing the WIP patch for it and raising the concern - it was dismissed and I didn't want to back up my claim further)

I haven't looked close, from what I can see, that problem likely still applies. So we might need to patch it to work around that long-standing GDB bug.

Looking at preprocessed source for:

#include <debugging>

int main(void)
{
  std::breakpoint();
}

I notice that mingw-w64's __debugbreak doesn't do this either. So it may be something we want to patch, too.

# 604 "C:/programming/toolchains/w64devkit/include/_mingw.h" 3
void __attribute__((__cdecl__)) __debugbreak(void);
extern __inline__ __attribute__((__always_inline__,__gnu_inline__)) void __attribute__((__cdecl__)) __debugbreak(void)
{
  __asm__ __volatile__("int {$}3":);
}
# 625 "C:/programming/toolchains/w64devkit/include/_mingw.h" 3
void __attribute__((__cdecl__)) __attribute__ ((__noreturn__)) __fastfail(unsigned int code);
extern __inline__ __attribute__((__always_inline__,__gnu_inline__)) void __attribute__((__cdecl__)) __attribute__ ((__noreturn__)) __fastfail(unsign
ed int code)
{
 __asm__ __volatile__("int {$}0x29"::"c"(code));
  __builtin_unreachable();
}

__fastfail is also not something I have seen before.
https://learn.microsoft.com/en-us/cpp/intrinsics/fastfail
Good to know...

None of this is major enough to hold up the switch though, IMO. It can be fixed later. And of course, this feature is experimental. Just pointing it as something to review.

@Peter0x44
Copy link
Copy Markdown
Collaborator Author

The x86 build still fails, I struggled to see this one on a skim (it's almost 1000 lines from the end of the log). Now it's a failure with libgfortran.

17294 2026-05-01T11:05:16.1343220Z #44 72.05 /dl/gcc/libgfortran/caf/shmem/shared_memory.c: In function 'shared_memory_init':
17295 2026-05-01T11:05:16.1344652Z #44 72.05 /dl/gcc/libgfortran/caf/shmem/shared_memory.c:173:35: warning: right shift count >= width of type [-Wsh
      ift-count-overflow]
17296 2026-05-01T11:05:16.1345686Z #44 72.05   173 |                              size >> (sizeof (DWORD) * 8),
17297 2026-05-01T11:05:16.1346400Z #44 72.05       |                                   ^~
17298 2026-05-01T11:05:16.1347923Z #44 72.10 /dl/gcc/libgfortran/caf/shmem/shared_memory.c:237:16: error: implicit declaration of function 'MapViewO
      fFileExNuma'; did you mean 'MapViewOfFileEx'? [-Wimplicit-function-declaration]
17299 2026-05-01T11:05:16.1349561Z #44 72.10   237 |     = (LPTSTR) MapViewOfFileExNuma (mem->shm_fd, FILE_MAP_ALL_ACCESS, 0, 0,
17300 2026-05-01T11:05:16.1350397Z #44 72.10       |                ^~~~~~~~~~~~~~~~~~~
17301 2026-05-01T11:05:16.1351229Z #44 72.10       |                MapViewOfFileEx
17302 2026-05-01T11:05:16.1352025Z #44 72.11 make[3]: *** [Makefile:4689: caf/shmem/libcaf_shmem_la-shared_memory.lo] Error 1

Will investigate further.

@Peter0x44
Copy link
Copy Markdown
Collaborator Author

The responsible commit is gnutools/gcc@efb497c23a6f

@Peter0x44
Copy link
Copy Markdown
Collaborator Author

Peter0x44 commented May 1, 2026

it's passing NUMA_NO_PREFERRED_NODE, which makes me question why it's even needed to call MapViewOfFileExNuma instead of MapViewOfFileEx. Seems unneeded. Will patch it to MapViewOfFileEx.

Value Meaning
NUMA_NO_PREFERRED_NODE 0xffffffff No NUMA node is preferred. This is the same as calling the MapViewOfFileEx function.

@skeeto
Copy link
Copy Markdown
Owner

skeeto commented May 2, 2026

Thanks for doing all this, @Peter0x44. Everything works fine for me so far. Is there anything remaining? (I'd like to squash all this before merging.)

@Peter0x44
Copy link
Copy Markdown
Collaborator Author

No, nothing left to do.

@skeeto
Copy link
Copy Markdown
Owner

skeeto commented May 2, 2026

I just looked more into std::breakpoint and it's even worse than not having nop. It calls DebugBreak and your stack trace ends up:

kernelbase!DebugBreak()
std::breakpoint()
actual_func()

Two junk stack frames: lots of friction and GDB display doesn't work. While libstdc++ could do this a little better, it seems to be impossible for GCC to address on its own anyway. To use std::breakpoint effectively in GDB you need the nop outside the call:

    std::breakpoint();
    asm("nop");

So that the stack frame instruction pointer lands on the nop rather than potentially in the wrong basic block, confusing GDB. If std::breakpoint were (somehow) instead a macro containing nop this would work. Otherwise this requires fixing GDB. There are two parts:

  1. GDB should have the ability to (and default to) ignore/hide known implementation stack frames (abort, raise, __asan_..., std::breakpoint, etc.). This would make working with sanitizers more effective, too. The only debugger I'm aware of that can do this is Visual Studio, and I'm surprised nobody's copied the behavior in their own debuggers.
  2. When GDB constructs backtraces it needs to use the instruction before the return address, not the return address. GDB is the only debugger I'm aware of that gets this wrong. This means going up from std::breakpoint would treat the line containing call as the "current" line rather than the line containing the instruction following call. This is ambiguous (think: tail calls), and so there's potentially a heuristic to making this work well, but never perfectly, particularly at higher optimiation levels (even -Og), but at -O0 it will be fine.

Ultimately none of this could ever work as well as the new classic macro:

#define breakpoint() asm("int3;nop")

Because only a macro has the semantics necessary for perfection. But, yes, that's not something to address right now. std::breakpoint is just disappointing, that's all. Though we could turn __debugbreak into a macro and make it perfect.

__fastfail is also not something I have seen before.

I'm a little surprised! If you ever see "The system detected an overrun of a stack-based buffer in this application. This overrun could potentially allow a malicious user to gain control of this application." the message is 99.9% bogus and it's just a __fastfail abort. (Some more discussion on #215).

@Peter0x44
Copy link
Copy Markdown
Collaborator Author

Peter0x44 commented May 2, 2026

That's sad. It's a shame std::breakpoint is currently unfit for purpose.

@skeeto
Copy link
Copy Markdown
Owner

skeeto commented May 2, 2026

Would you like to squash these, with a nice commit explaining the changes? Then go ahead and merge. If not, I can do it, but I'll leave you as commit author (and I didn't want to put words in your mouth).

@Peter0x44
Copy link
Copy Markdown
Collaborator Author

I don't care. Just do it.

Bumps GCC from 15.2.0 and adjusts the build for the new release:

- Drop the obsolete stdcall-align patch, no longer needed.

- Configure with --enable-tls so libstdc++ uses native Windows TLS
  rather than emutls. This is an ABI break: object files built with
  earlier w64devkit releases cannot be linked against new builds.

- Import gcc-dynamic-load-tzdb.patch (originally from
  redpanda-cpp/mingw-lite, by CyanoHao) so that libstdc++'s C++20
  std::chrono::current_zone() Windows backend resolves
  GetDynamicTimeZoneInformation at runtime via LoadLibrary/
  GetProcAddress. Without this, _WIN32_WINNT < 0x0600 builds fail
  to compile tzdb.cc.

- Add gcc-libgfortran-mapview.patch to replace the new
  MapViewOfFileExNuma call in libgfortran's caf_shmem with
  MapViewOfFileEx, which mingw-w64 declares for older Windows
  targets. NUMA_NO_PREFERRED_NODE makes the two calls equivalent,
  so no functional change.
@skeeto skeeto merged commit 18e17fd into skeeto:master May 2, 2026
2 checks passed
@Peter0x44 Peter0x44 deleted the gcc16 branch May 2, 2026 18:00
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants