From d687b83fcbd75b03cf4adaaaf0b5affdeab8b211 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=B3zef=20Kucia?= Date: Fri, 27 Jul 2018 09:40:01 +0200 Subject: [PATCH] vrclient: Generate call_flat_method() functions. In order to remove hardcoded limit for parameter count in C API functions. --- vrclient_x64/flatapi.c | 139 +++++++++++++++++++++++++++++++++++ vrclient_x64/flatapi.h | 13 +--- vrclient_x64/gen_wrapper.py | 83 ++++++++++++++++++++- vrclient_x64/vrclient_main.c | 51 ------------- 4 files changed, 220 insertions(+), 66 deletions(-) create mode 100644 vrclient_x64/flatapi.c diff --git a/vrclient_x64/flatapi.c b/vrclient_x64/flatapi.c new file mode 100644 index 00000000..e3550430 --- /dev/null +++ b/vrclient_x64/flatapi.c @@ -0,0 +1,139 @@ +/* This file is auto-generated, do not edit. */ + +#include + +#include "windef.h" +#include "winbase.h" + +#include "cxx.h" +#include "flatapi.h" + +#ifdef __i386__ +__ASM_GLOBAL_FUNC(call_flat_method, + "popl %eax\n\t" + "pushl %ecx\n\t" + "pushl %eax\n\t" + "jmp *%edx"); +#else +// handles "this" and up to 3 parameters +__ASM_GLOBAL_FUNC(call_flat_method, + "movq %r8, %r9\n\t" // shift over arguments + "movq %rdx, %r8\n\t" + "movq %rcx, %rdx\n\t" + "movq %r10, %rcx\n\t" // add This pointer + "jmp *%r11"); +extern void call_flat_method(void); + +__ASM_GLOBAL_FUNC(call_flat_method4, + "subq $0x28, %rsp\n\t" + "movq %r9, 0x20(%rsp)\n\t" + "movq %r8, %r9\n\t" // shift over arguments + "movq %rdx, %r8\n\t" + "movq %rcx, %rdx\n\t" + "movq %r10, %rcx\n\t" // add This pointer + "call *%r11\n\t" + "addq $0x28, %rsp\n\t" + "ret"); +extern void call_flat_method4(void); + +__ASM_GLOBAL_FUNC(call_flat_method5, + "subq $0x38, %rsp\n\t" + "movq %r9, 0x20(%rsp)\n\t" + "movq 0x60(%rsp), %rax\n\t" // copy parameter + "movq %rax, 0x28(%rsp)\n\t" + "movq %r8, %r9\n\t" // shift over arguments + "movq %rdx, %r8\n\t" + "movq %rcx, %rdx\n\t" + "movq %r10, %rcx\n\t" // add This pointer + "call *%r11\n\t" + "addq $0x38, %rsp\n\t" + "ret"); +extern void call_flat_method5(void); + +__ASM_GLOBAL_FUNC(call_flat_method6, + "subq $0x38, %rsp\n\t" + "movq %r9, 0x20(%rsp)\n\t" + "movq 0x60(%rsp), %rax\n\t" // copy parameter + "movq %rax, 0x28(%rsp)\n\t" + "movq 0x68(%rsp), %rax\n\t" // copy parameter + "movq %rax, 0x30(%rsp)\n\t" + "movq %r8, %r9\n\t" // shift over arguments + "movq %rdx, %r8\n\t" + "movq %rcx, %rdx\n\t" + "movq %r10, %rcx\n\t" // add This pointer + "call *%r11\n\t" + "addq $0x38, %rsp\n\t" + "ret"); +extern void call_flat_method6(void); + +__ASM_GLOBAL_FUNC(call_flat_method7, + "subq $0x48, %rsp\n\t" + "movq %r9, 0x20(%rsp)\n\t" + "movq 0x70(%rsp), %rax\n\t" // copy parameter + "movq %rax, 0x28(%rsp)\n\t" + "movq 0x78(%rsp), %rax\n\t" // copy parameter + "movq %rax, 0x30(%rsp)\n\t" + "movq 0x80(%rsp), %rax\n\t" // copy parameter + "movq %rax, 0x38(%rsp)\n\t" + "movq %r8, %r9\n\t" // shift over arguments + "movq %rdx, %r8\n\t" + "movq %rcx, %rdx\n\t" + "movq %r10, %rcx\n\t" // add This pointer + "call *%r11\n\t" + "addq $0x48, %rsp\n\t" + "ret"); +extern void call_flat_method7(void); + +__ASM_GLOBAL_FUNC(call_flat_method8, + "subq $0x48, %rsp\n\t" + "movq %r9, 0x20(%rsp)\n\t" + "movq 0x70(%rsp), %rax\n\t" // copy parameter + "movq %rax, 0x28(%rsp)\n\t" + "movq 0x78(%rsp), %rax\n\t" // copy parameter + "movq %rax, 0x30(%rsp)\n\t" + "movq 0x80(%rsp), %rax\n\t" // copy parameter + "movq %rax, 0x38(%rsp)\n\t" + "movq 0x88(%rsp), %rax\n\t" // copy parameter + "movq %rax, 0x40(%rsp)\n\t" + "movq %r8, %r9\n\t" // shift over arguments + "movq %rdx, %r8\n\t" + "movq %rcx, %rdx\n\t" + "movq %r10, %rcx\n\t" // add This pointer + "call *%r11\n\t" + "addq $0x48, %rsp\n\t" + "ret"); +extern void call_flat_method8(void); + +__ASM_GLOBAL_FUNC(call_flat_method9, + "subq $0x58, %rsp\n\t" + "movq %r9, 0x20(%rsp)\n\t" + "movq 0x80(%rsp), %rax\n\t" // copy parameter + "movq %rax, 0x28(%rsp)\n\t" + "movq 0x88(%rsp), %rax\n\t" // copy parameter + "movq %rax, 0x30(%rsp)\n\t" + "movq 0x90(%rsp), %rax\n\t" // copy parameter + "movq %rax, 0x38(%rsp)\n\t" + "movq 0x98(%rsp), %rax\n\t" // copy parameter + "movq %rax, 0x40(%rsp)\n\t" + "movq 0xa0(%rsp), %rax\n\t" // copy parameter + "movq %rax, 0x48(%rsp)\n\t" + "movq %r8, %r9\n\t" // shift over arguments + "movq %rdx, %r8\n\t" + "movq %rcx, %rdx\n\t" + "movq %r10, %rcx\n\t" // add This pointer + "call *%r11\n\t" + "addq $0x58, %rsp\n\t" + "ret"); +extern void call_flat_method9(void); + +pfn_call_flat_method get_call_flat_method_pfn( int param_count ) +{ + if (param_count <= 3) return call_flat_method; + if (param_count == 4) return call_flat_method4; + if (param_count == 5) return call_flat_method5; + if (param_count == 6) return call_flat_method6; + if (param_count == 7) return call_flat_method7; + if (param_count == 8) return call_flat_method8; + return call_flat_method9; +} +#endif diff --git a/vrclient_x64/flatapi.h b/vrclient_x64/flatapi.h index a52ed40b..ef2de80e 100644 --- a/vrclient_x64/flatapi.h +++ b/vrclient_x64/flatapi.h @@ -51,18 +51,7 @@ static const struct thunk thunk_template = typedef void (*pfn_call_flat_method)(void); -extern void call_flat_method3(void); -extern void call_flat_method4(void); -extern void call_flat_method9(void); - -static inline pfn_call_flat_method get_call_flat_method_pfn( int param_count ) -{ - if (param_count <= 3) - return call_flat_method3; - if (param_count <= 4) - return call_flat_method4; - return call_flat_method9; -} +extern pfn_call_flat_method get_call_flat_method_pfn( int param_count ); static inline void init_thunk( struct thunk *thunk, void *this, void *proc, int param_count ) { diff --git a/vrclient_x64/gen_wrapper.py b/vrclient_x64/gen_wrapper.py index 74393dd4..4ec016ee 100755 --- a/vrclient_x64/gen_wrapper.py +++ b/vrclient_x64/gen_wrapper.py @@ -400,6 +400,8 @@ def get_iface_version(classname): class_versions[classname].append(ver) return (ver, False) +max_c_api_param_count = 0 + def handle_class(sdkver, classnode): print("handle_class: " + classnode.displayname) children = list(classnode.get_children()) @@ -505,9 +507,8 @@ WINE_DEFAULT_DEBUG_CHANNEL(vrclient); cfile.write(" TRACE(\"-> %p, vtable %p, thunks %p\\n\", r, vtable, thunks);\n") for i in range(len(methods)): param_count = methods_param_count[i] - if param_count > 9: - # Additional call_flat_method() variants are needed to handle more parameters. - sys.exit("Unhandled parameter count %s for method %s" % (param_count, methods[i])) + global max_c_api_param_count + max_c_api_param_count = max(param_count, max_c_api_param_count) cfile.write(" init_thunk(&thunks[%d], r, %s_%s, %s);\n" % (i, winclassname, methods[i], param_count)) cfile.write(" for (i = 0; i < %d; i++)\n" % len(methods)) cfile.write(" vtable[i] = &thunks[i];\n") @@ -629,6 +630,80 @@ def handle_struct(sdkver, struct, which): generated_struct_handlers.append(handler_name) +def generate_x64_call_flat_method(cfile, param_count): + assert param_count >= 4 + def l(line): + cfile.write(line + '\n') + + stack_space = 0x20 # shadow register space + stack_space += 0x8 * (param_count - 3) + stack_space |= 0x8 + src_offset = 0x20 + 0x8 + stack_space # shadow register space + ret + dst_offset = 0x20 + + l(r"__ASM_GLOBAL_FUNC(call_flat_method%s," % param_count) + l(r' "subq $0x%x, %%rsp\n\t"' % stack_space); + + l(r' "movq %%r9, 0x%x(%%rsp)\n\t"' % dst_offset) + dst_offset += 8 + + for i in range(5, param_count + 1): + l(r' "movq 0x%x(%%rsp), %%rax\n\t" // copy parameter' % src_offset) + l(r' "movq %%rax, 0x%x(%%rsp)\n\t"' % dst_offset) + src_offset += 8 + dst_offset += 8 + + l(r' "movq %r8, %r9\n\t" // shift over arguments') + l(r' "movq %rdx, %r8\n\t"') + l(r' "movq %rcx, %rdx\n\t"') + l(r' "movq %r10, %rcx\n\t" // add This pointer') + + l(r' "call *%r11\n\t"') + l(r' "addq $0x%x, %%rsp\n\t"' % stack_space); + l(r' "ret");') + l(r'extern void call_flat_method%s(void);' % param_count); + +def generate_flatapi_c(): + with open("flatapi.c", "w") as f: + f.write(r"""/* This file is auto-generated, do not edit. */ + +#include + +#include "windef.h" +#include "winbase.h" + +#include "cxx.h" +#include "flatapi.h" + +#ifdef __i386__ +__ASM_GLOBAL_FUNC(call_flat_method, + "popl %eax\n\t" + "pushl %ecx\n\t" + "pushl %eax\n\t" + "jmp *%edx"); +#else +// handles "this" and up to 3 parameters +__ASM_GLOBAL_FUNC(call_flat_method, + "movq %r8, %r9\n\t" // shift over arguments + "movq %rdx, %r8\n\t" + "movq %rcx, %rdx\n\t" + "movq %r10, %rcx\n\t" // add This pointer + "jmp *%r11"); +extern void call_flat_method(void); +""") + + for i in range(4, max_c_api_param_count + 1): + f.write("\n") + generate_x64_call_flat_method(f, i) + + f.write('\npfn_call_flat_method get_call_flat_method_pfn( int param_count )\n{\n') + f.write(' if (param_count <= 3) return call_flat_method;\n') + for i in range(4, max_c_api_param_count): + f.write(' if (param_count == %s) return call_flat_method%s;\n' % (i, i)) + f.write(' return call_flat_method%s;\n' % max_c_api_param_count) + f.write('}\n') + + f.write("#endif\n") #clang.cindex.Config.set_library_file("/usr/lib/llvm-3.8/lib/libclang-3.8.so.1"); @@ -678,3 +753,5 @@ for sdkver in sdk_versions: for f in cpp_files_need_close_brace: m = open(f, "a") m.write("\n}\n") + +generate_flatapi_c() diff --git a/vrclient_x64/vrclient_main.c b/vrclient_x64/vrclient_main.c index b17ae5c6..22624cb3 100644 --- a/vrclient_x64/vrclient_main.c +++ b/vrclient_x64/vrclient_main.c @@ -23,7 +23,6 @@ #include "wined3d-interop.h" -#include "cxx.h" #include "flatapi.h" #include "cppIVRClientCore_IVRClientCore_003.h" @@ -910,53 +909,3 @@ void destroy_compositor_data(struct compositor_data *data) wined3d_device->lpVtbl->wait_idle(wined3d_device); } } - -/* call_flat_method() definition */ -#ifdef __i386__ -__ASM_GLOBAL_FUNC(call_flat_method, - "popl %eax\n\t" - "pushl %ecx\n\t" - "pushl %eax\n\t" - "jmp *%edx"); -#else -// handles "this" and up to 3 parameters -__ASM_GLOBAL_FUNC(call_flat_method3, - "movq %r8, %r9\n\t" // shift over arguments - "movq %rdx, %r8\n\t" - "movq %rcx, %rdx\n\t" - "movq %r10, %rcx\n\t" // add This pointer - "jmp *%r11"); - -__ASM_GLOBAL_FUNC(call_flat_method4, - "subq $0x28, %rsp\n\t" // shadow register space and 1 parameter - "movq %r9, 0x20(%rsp)\n\t" - "movq %r8, %r9\n\t" // shift over arguments - "movq %rdx, %r8\n\t" - "movq %rcx, %rdx\n\t" - "movq %r10, %rcx\n\t" // add This pointer - "call *%r11\n\t" - "addq $0x28, %rsp\n\t" - "ret"); - -// handles "this" and up to 9 parameters -__ASM_GLOBAL_FUNC(call_flat_method9, - "subq $0x58, %rsp\n\t" // shadow register space and 6 parameters - "movq %r9, 0x20(%rsp)\n\t" - "movq 0x80(%rsp), %rax\n\t" // copy parameters - "movq %rax, 0x28(%rsp)\n\t" - "movq 0x88(%rsp), %rax\n\t" - "movq %rax, 0x30(%rsp)\n\t" - "movq 0x90(%rsp), %rax\n\t" - "movq %rax, 0x38(%rsp)\n\t" - "movq 0x98(%rsp), %rax\n\t" - "movq %rax, 0x40(%rsp)\n\t" - "movq 0xa0(%rsp), %rax\n\t" - "movq %rax, 0x48(%rsp)\n\t" - "movq %r8, %r9\n\t" // shift over arguments - "movq %rdx, %r8\n\t" - "movq %rcx, %rdx\n\t" - "movq %r10, %rcx\n\t" // add This pointer - "call *%r11\n\t" - "addq $0x58, %rsp\n\t" - "ret"); -#endif