4 ms·
This approach of using inline asm wrappers around functions which specify exactly the clobbered registers is neat, but... I don't think the approach of making
by BeeOnRope 6y ago
This approach of using inline asm wrappers around functions which specify exactly the clobbered registers is neat, but...
I don't think the approach of making a call from inline asm is safe. In particular, it clobbers the redzone [1], which the compiler may have used and expect to be intact after the call.
In general, at least some compilers (e.g., gcc) assume there are no calls in an inline asm block.
---
[1] https://godbolt.org/z/e4ecKr https://godbolt.org/z/e4ecKr
- ahh 6y agoI can confirm we came up with this optimization inside tcmalloc, and our compiler experts nacked it as unsafe, even only calling tightly controlled code. A pity, as it is really beautiful to see the improved clobbering (and even, in some cases, hacked calling conventions.)
- jart 6y agoCosmopolitan doesn't use the "red zone" because these binaries boot on bare metal and operating system code can't assume a red zone. GCC supports this. Otherwise the Linux Kernel wouldn't work, since it's compiled the same way. So invoking call from inline asm is perfectly safe. The only real issue is that the called function can't assume the stack is 16-byte aligned. But that's fine, since Cosmo only using asm(call) to call functions written in assembly.
- BeeOnRope 6y agoWell you edited the compile command on the page just now to add -mno-red-zone, but it wasn't there before. So do you mean it is safe as long as -mno-red-zone is used? Even then, I am not quite sure: redzone is just an example of one of the assumptions that might be violated when calls are made from an asm block, but at least some gcc devs are on record saying that calls from inline asm are not supported: the main problem is that leaf functions can be compiled differently than non-leaf, and a hidden call breaks this (i.e., a non-leaf function may appear as leaf to the compiler).
- stephencanon 6y agoAgree. This is a great little micro-optimization, but definitely requires some compiler support to do safely (on the other hand, compiler devs should want to support it, because it's a great little micro-optimization, so I don't think that it would be _too_ hard to add). Note that one way to get the code size wins for the caller in a compiler-blessed way is to use an alternative calling convention, like Clang's preserve_most; this isn't as good as explicitly providing a clobber list, but allows a library to provide a stable interface.