Compiler-rt built using MSVC is missing __chkstk

I built compiler-rt 16.0.0 for Windows x86-64 (on Windows x86-64, outside Cygwin), installed it by invoking cmake install-compiler-rt target (outside Cygwin) with the default prefix C:\Program Files (x86)\Runtimes, in that directory ran objdump -t lib/windows/clang_rt.builtins-x86_64.lib | grep -F __chkstk (in Cygwin) and got empty output. Other artifacts there too seem to not have __chkstk. So I don’t know which file with __chkstk to link my program with (I don’t want to use MSVC runtime). How do i use __chkstk with clang++ targeting Windows x86-64 without MSVC runtime?

See this article. __chkstk is a special stack protector: Dealing with __chkstk/__chkstk_ms when Cross-Compiling For Windows | Metric Panda Games

There are some workarounds described as well.

compiler-rt defines __chkstk and __chkstk_ms; I want to use this routine (__chkstk). What I don’t understand is why compiler-rt’s build doesn’t have them, and consequently how to use the routine. Your linked article doesn’t answer this.

@mstorsjo might know more.

I inspected lib/builtins/CMakeLists.txt and found the answer. The routines are built only if NOT MSVC in cmake.

I don’t know whether compiler-rt depends on MSVC runtime if MSVC. I would like to use compiler-rt in my program targeting the MSVC target without MSVC runtime (freestanding). Meanwhile, I’ll compile lib/builtins/x86_64/chkstk2.S by itself.

Does compiler-rt built using clang-cl and targeting MSVC target depend on the MSVC runtime, even if the program does not use that?

After a whole half-day of investigation, I conclude that compiler-rt’s ___chkstk is unsuitable for the code that clang emits for the MSVC target: compiler-rt’s ___chkstk reserves stack space in addition to committing it, but clang expects __chkstk to only commit it. Though, compiler-rt has ___chkstk_ms which does exactly what clang wants __chkstk to do.

One may want to request the correct version of __chkstk in compiler-rt for MSVC target, maybe with another name that clang will use with special configuration to avoid clashing. Meanwhile, the body of ___chkstk_ms works as __chkstk without error.

It looks to me like only the MinGW versions of these functions have ever been used, and seem to be the correct ones. The other ones are entirely unused, and as you note, incorrect.

compiler-rt: add support for mingw-w64 in builtins · llvm/llvm-project@fbfed86 · GitHub and Add missing chkstk.S files from r242539 · llvm/llvm-project@c27de5b · GitHub added ___chkstk_ms for both i386 and x86_64. However nothing ever generates calls to a function ___chkstk_ms on i386. Then later Support for 32-bit mingw-w64 in compiler-rt. · llvm/llvm-project@40eb83b · GitHub added the functions __alloca and ___chkstk (with three underscores) for i386 and for x86_64. Nothing ever calls ___chkstk with three underscores, and AFAIK nothing calls __alloca on x86_64 either.

So to clear this up, I would suggest we should do this:

  • Remove compiler-rt/lib/builtins/i386/chkstk.S entirely
  • In compiler-rt/lib/builtins/i386/chkstk2.S, remove one superfluous leading underscore from ___chkstk (as DEFINE_COMPILERRT_FUNCTION adds one extra leading underscore on i386 here)
  • Maybe rename i386/chkstk2.S to i386/chkstk.S
  • Remove compiler-rt/lib/builtins/x86_64/chkstk2.S
  • Add DEFINE_COMPILERRT_FUNCTION(__chkstk) in x86_64/chkstk.S

Then these implementations should work just as well for both MSVC and MinGW targets. As far as I know, both targets want to have functions that do exactly the same, they just call it with slightly different names.

Would that solve your issue?

The second question is whether these symbols should be included by default in an MSVC mode build of the builtins - I’m less sure about that. Normally in an MSVC build, the MSVC libraries provide these functions, and compiler-rt’s builtins can be used to add extra functions on top of it. In such a case, we wouldn’t want to use compiler-rt’s implementation instead of the MSVC one. (IIRC the MSVC implementation of the functions doesn’t blindly probe the stack but checks StackLimit from the TEB and only probes it if needed.)

I would be happy with a version of __chkstk that clang can use (when generating) on MSVC target when the MSVC runtime is not used (-nostdlib to clang), it may have a different name, like __chkstk_no_msvc or something. Currently, (on MSVC target) clang expects that __chkstk doesn’t change the stack pointer.