On Mon, 19 Aug 2024, Pali Rohár wrote:
What about attribute naked? For I386 it is supported since gcc 8.
I think it may be ok. I have very little experience with this attribute myself though.
It seems like Wine are using this attribute, in some setups. And either they use a non-static function declared entirely in assembly, or static functions with the naked attribute.
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=25967 https://gcc.gnu.org/onlinedocs/gcc/x86-Function-Attributes.html#index-naked-function-attribute_002c-x86 Per gcc documentation assembler instructions without operands are supported in naked functions, so something like this could be ok. What do you think? diff --git a/mingw-w64-crt/stdio/_scprintf.c b/mingw-w64-crt/stdio/_scprintf.c index 42f2e5f231a4..fca6f325e13c 100644 --- a/mingw-w64-crt/stdio/_scprintf.c +++ b/mingw-w64-crt/stdio/_scprintf.c @@ -51,9 +51,17 @@ static void resolve_scprintf(void) /* gcc does not provide an easy way to call another variadic function with reusing current arguments * this source file is used only on i386, so do this function redirect via inline i386 assembly */ #define ASM_SYM(sym) __MINGW64_STRINGIFY(__MINGW_USYMBOL(sym)) + +#if !defined(__GNUC__) || __GNUC__ >= 8
Hmm - the !defined(__GNUC__) is a bit odd here... I think the other, existing definition might be more safe if we don't know the compiler. (Our files don't really build with any random compiler anyway, as we pretty much require GCC or Clang in MinGW mode.)
We could check for Clang too (Clang identifies as GCC 4.2, but the Clang version can also be inspected) - it should support the naked attribute as well. I'm not exactly sure for how long it has supported it, but it might be ok to not check (we don't in general support building with as wide range of Clang versions as we do for GCC, I think).
+ __attribute__((naked)) +static int __cdecl init_scprintf(const char * __restrict__ __UNUSED_PARAM(format), ...) +{ +asm ( +#else asm ( ".def\t" ASM_SYM(init_scprintf) ";\t.scl\t3;\t.type\t32;\t.endef\n" ASM_SYM(init_scprintf) ":\n\t" +#endif "pushal\n\t" "call\t" ASM_SYM(resolve_scprintf) "\n\t" "popal\n\t" @@ -63,5 +71,9 @@ ASM_SYM(init_scprintf) ":\n\t" ASM_SYM(_scprintf) ":\n\t" "jmp\t*" ASM_SYM(__MINGW_IMP_SYMBOL(_scprintf)) ); +#if !defined(__GNUC__) || __GNUC__ >= 8 +__builtin_unreachable(); +} +#endif #endif I'm just not sure if is safe to mark format argument as __UNUSED_PARAM, but without it gcc generates warning:
I think it should be safe. There's nothing in that declaration that should be able to affect the code generation here anyway, I think.
mingw-w64-crt/stdio/_scprintf.c: In function ‘init_scprintf’: mingw-w64-crt/stdio/_scprintf.c:57:60: warning: unused parameter ‘format’ [-Wunused-parameter] static int __cdecl init_scprintf(const char * __restrict__ format, ...) ~~~~~~~~~~~~~~~~~~~~~~~~~~^~~~~~
I guess the alternative of using a void cast within the function also might work, but that's probalby a bit ugly in a naked function?
How are supposed to be defined naked functions with parameters which are used in inline assembly by inspecting stack itself (without referencing C parameters)?
Not sure, to be honest. // Martin _______________________________________________ Mingw-w64-public mailing list Mingw-w64-public@lists.sourceforge.net https://lists.sourceforge.net/lists/listinfo/mingw-w64-public