Signed-off-by: Rémi Bernon rbernon@codeweavers.com ---
This is a little bit ugly, but I don't think there is any other way.
The idea here is that we need .file and .loc pseudo-op be generated for the assembly functions. We cannot output them ourselves, as .file op requires a uniquely increasing file number, which varies depending on what has been previously emitted already.
We use the dummy wrapper to benefit from its automatically emitted instructions, however even when using naked function, GCC still emits cfi/seh pseudo-ops too, and it gets confused with our own. The trick here is to fake the function end before emitting our assembly, and fake another function start before ending the dummy wrapper.
include/wine/asm.h | 25 ++++++++++++++++++++++--- 1 file changed, 22 insertions(+), 3 deletions(-)
diff --git a/include/wine/asm.h b/include/wine/asm.h index 7975e377341..f1e358f13d8 100644 --- a/include/wine/asm.h +++ b/include/wine/asm.h @@ -21,6 +21,12 @@ #ifndef __WINE_WINE_ASM_H #define __WINE_WINE_ASM_H
+#define __ASM_STR_I(x) #x +#define __ASM_STR(x) __ASM_STR_I(x) + +#define __ASM_CAT_I(x,y) x ## y +#define __ASM_CAT(x,y) __ASM_CAT_I(x, y) + #if defined(__APPLE__) || (defined(_WIN32) && defined(__i386__)) # define __ASM_NAME(name) "_" name #else @@ -74,18 +80,31 @@ #endif
#if !defined(__GNUC__) && !defined(__clang__) -# define __ASM_BLOCK_BEGIN(name) void __asm_dummy_##name(void) { +# define __ASM_BLOCK_BEGIN(name) void __ASM_CAT(__asm_dummy_,name)(void) { # define __ASM_BLOCK_END } #else # define __ASM_BLOCK_BEGIN(name) # define __ASM_BLOCK_END #endif
+#if !defined(__GNUC__) +# define __ASM_FUNC_BEGIN(line) __ASM_BLOCK_BEGIN(line) +# define __ASM_FUNC_END(line) __ASM_BLOCK_END +#else +# define __ASM_FUNC_BEGIN(line) \ + static void __attribute__((naked,used)) __ASM_CAT(__asm_dummy_,line)(void) { \ + asm(__ASM_CFI("\n\t.cfi_endproc") __ASM_SEH("\n\t.seh_endproc")); +# define __ASM_FUNC_END(line) \ + asm(__ASM_SEH("\n\t.seh_proc .L__asm_dummy_" __ASM_STR(line) "\n.L__asm_dummy_" __ASM_STR(line) ":") \ + __ASM_CFI("\n\t.cfi_startproc")); \ + } +#endif + #define __ASM_DEFINE_FUNC(name,code) \ - __ASM_BLOCK_BEGIN(__LINE__) \ + __ASM_FUNC_BEGIN(__LINE__) \ asm(".text\n\t.align 4\n\t.globl " name "\n\t" __ASM_FUNC_TYPE(name) __ASM_SEH("\n\t.seh_proc " name) "\n" name ":\n\t" \ __ASM_CFI(".cfi_startproc\n\t") code __ASM_CFI("\n\t.cfi_endproc") __ASM_SEH("\n\t.seh_endproc") "\n\t" __ASM_FUNC_SIZE(name) "\n" ); \ - __ASM_BLOCK_END + __ASM_FUNC_END(__LINE__)
#define __ASM_GLOBAL_FUNC(name,code) __ASM_DEFINE_FUNC(__ASM_NAME(#name),code) #define __ASM_STDCALL_FUNC(name,args,code) __ASM_DEFINE_FUNC(__ASM_STDCALL(#name,args),code)