higan-emu / libco

libco is a cooperative multithreading library written in C89.
Other
128 stars 24 forks source link

Consider removing LIBCO_NO_SSE, or adding louder warnings #43

Open Alcaro opened 1 year ago

Alcaro commented 1 year ago

LIBCO_NO_SSE makes libco clobber the SSE registers, contrary to the win64 ABI.

Intuitively, you'd think that's safe if you don't use any floating-point types, but no - the compiler can invent use of SIMD regs from integer operations, and expect them to stay alive across function calls. https://godbolt.org/z/hbr8aaeK4

Even more insidiously, even if there's nothing to vectorize, compilers can spill %rax to %xmm0 instead of to stack. https://godbolt.org/z/dz5f3a36o I wasn't able to convince GCC to spill xmm6 to stack then spill anything else to xmm6, and Clang seems disinclined to spill to xmm at all, but that promises nothing about newer compilers.

The only safe way to use LIBCO_NO_SSE is compiling large parts of your program with -ffixed-xmm6 -ffixed-xmm7 -ffixed-xmm8 -ffixed-xmm9 -ffixed-xmm10 -ffixed-xmm11 -ffixed-xmm12 -ffixed-xmm13 -ffixed-xmm14 -ffixed-xmm15. And for extra fun, Clang and MSVC don't support those options. (More specifically, on entry to co_switch inside a coroutine, every function on the current stack must have those flags. It's fine to call external code, as long as no callbacks can call co_switch.)