From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: (qmail 19505 invoked by alias); 4 Sep 2009 12:18:03 -0000 Received: (qmail 19483 invoked by uid 22791); 4 Sep 2009 12:18:00 -0000 X-SWARE-Spam-Status: No, hits=-3.6 required=5.0 tests=AWL,BAYES_00,RCVD_IN_DNSWL_LOW X-Spam-Check-By: sourceware.org Received: from mail.codeweavers.com (HELO mail.codeweavers.com) (216.251.189.131) by sourceware.org (qpsmtpd/0.43rc1) with ESMTP; Fri, 04 Sep 2009 12:17:53 +0000 Received: from chello084112174163.20.11.vie.surfer.at ([84.112.174.163] helo=[192.168.0.2]) by mail.codeweavers.com with esmtpsa (TLS-1.0:DHE_RSA_AES_256_CBC_SHA1:32) (Exim 4.63) (envelope-from ) id 1MjXja-00027u-HI; Fri, 04 Sep 2009 07:17:50 -0500 From: Stefan =?iso-8859-1?q?D=F6singer?= To: gcc@gcc.gnu.org Subject: Re: MSVC hook function prologue Date: Fri, 04 Sep 2009 12:18:00 -0000 User-Agent: KMail/1.9.10 Cc: Paolo Bonzini References: <200909022245.51969.stefan@codeweavers.com> <200909041345.22952.stefan@codeweavers.com> <4AA0FE48.1040303@gnu.org> In-Reply-To: <4AA0FE48.1040303@gnu.org> MIME-Version: 1.0 Content-Type: Multipart/Mixed; boundary="Boundary-00=_dVQoKKzz1eovNFc" Message-Id: <200909041417.33085.stefan@codeweavers.com> X-Spam-Score: -3.9 X-IsSubscribed: yes Mailing-List: contact gcc-help@gcc.gnu.org; run by ezmlm Precedence: bulk List-Id: List-Archive: List-Post: List-Help: Sender: gcc-owner@gcc.gnu.org X-SW-Source: 2009-09/txt/msg00100.txt.bz2 --Boundary-00=_dVQoKKzz1eovNFc Content-Type: text/plain; charset="iso-8859-1" Content-Transfer-Encoding: 7bit Content-Disposition: inline Content-length: 1811 Am Friday 04 September 2009 13:47:20 schrieb Paolo Bonzini: > > I guess the error isn't about the const_int 0, but about operand 0. Any > > ideas? > > Yes, you need this: > > [(set (match_operand:SI 0 "register_operand" "=r") > (match_operand:SI 1 "register_operand" "r")) > (unspec_volatile [(const_int 0)] UNSPECV_VSWAPMOV)] That works, thanks! I just found the "=r" and "r" stuff myself almost at the same time your mail arrived. But what does the "SI" do? I haven't found Now I went a step further, and implemented the suggestion from amylaar in this mail: http://gcc.gnu.org/ml/gcc/2009-01/msg00174.html > If you make it a parallel where the actual oprtation is paired with an > empty unspec, no REG_FRAME_RELATED_EXPR is needed. If the actual operation > is hidden in the RTL, however, you have to add it in a REG_FRAME_RELATED_EXPR. > The latter alternative is more complicated. However, there is a benefit to > choosing this: win the stack realign or !frame_pointer_needed cases, the > (early) move of esp to ebp is not really supposed to establish a frame > pointer, and thus you then don't want any cfi information emitted for it. > Thus, you can then simply leave out the REG_FRAME_RELATED_EXPR note. Now the definition looks like this: (define_insn "vswapmov" [(parallel [(set (match_operand:SI 0 "register_operand" "=r") (match_operand:SI 1 "register_operand" "r")) (unspec_volatile [(const_int 0)] UNSPECV_VSWAPMOV)] )] "" "movl.s\t%1,%0" [(set_attr "length" "2") (set_attr "length_immediate" "0") (set_attr "modrm" "0")]) I am still compiling, so I don't know if it works yet. I attached the current state of the whole patch. I added the attribute to the documentation, and generated the patch with function names this time. --Boundary-00=_dVQoKKzz1eovNFc Content-Type: text/x-diff; charset="iso 8859-15"; name="msvc_prologue.diff" Content-Transfer-Encoding: 7bit Content-Disposition: attachment; filename="msvc_prologue.diff" Content-length: 7709 Index: gcc/doc/extend.texi =================================================================== --- gcc/doc/extend.texi (revision 151419) +++ gcc/doc/extend.texi (working copy) @@ -2672,6 +2672,14 @@ when targeting Windows. On all other systems, the Note, This feature is currently sorried out for Windows targets trying to +@item msvc_prologue +@cindex @code{msvc_prologue} attribute + +On 32 bit x86-*-* targets, you can use this function attribute to make +gcc generate the "hot-patching" function prologue used in Win32 API +functions in Microsoft Windows XP Service Pack 2 and newer. This requires +support for the swap suffix in the assembler. + @item naked @cindex function without a prologue/epilogue code Use this attribute on the ARM, AVR, IP2K and SPU ports to indicate that Index: gcc/configure.ac =================================================================== --- gcc/configure.ac (revision 151419) +++ gcc/configure.ac (working copy) @@ -3035,6 +3035,12 @@ foo: nop [AC_DEFINE(HAVE_AS_IX86_SAHF, 1, [Define if your assembler supports the sahf mnemonic.])]) + gcc_GAS_CHECK_FEATURE([swap suffix], + gcc_cv_as_ix86_swap,,, + [movl.s %esp, %ebp],, + [AC_DEFINE(HAVE_AS_IX86_SWAP, 1, + [Define if your assembler supports the swap suffix.])]) + gcc_GAS_CHECK_FEATURE([different section symbol subtraction], gcc_cv_as_ix86_diff_sect_delta,,, [.section .rodata Index: gcc/config/i386/i386.h =================================================================== --- gcc/config/i386/i386.h (revision 151419) +++ gcc/config/i386/i386.h (working copy) @@ -2388,6 +2388,9 @@ struct GTY(()) machine_function { to be used. MS_ABI means ms abi. Otherwise SYSV_ABI means sysv abi. */ enum calling_abi call_abi; struct machine_cfa_state cfa; + /* This value is used for i386 targets and specifies if the function + * should start with the hooking-friendly Win32 function prologue */ + int msvc_prologue; }; #endif Index: gcc/config/i386/i386.md =================================================================== --- gcc/config/i386/i386.md (revision 151419) +++ gcc/config/i386/i386.md (working copy) @@ -237,6 +237,7 @@ (UNSPECV_RDTSC 18) (UNSPECV_RDTSCP 19) (UNSPECV_RDPMC 20) + (UNSPECV_VSWAPMOV 21) ]) ;; Constants to represent pcomtrue/pcomfalse variants @@ -15747,6 +15748,18 @@ (set_attr "length_immediate" "0") (set_attr "modrm" "0")]) +(define_insn "vswapmov" + [(parallel + [(set (match_operand:SI 0 "register_operand" "=r") + (match_operand:SI 1 "register_operand" "r")) + (unspec_volatile [(const_int 0)] UNSPECV_VSWAPMOV)] + )] + "" + "movl.s\t%1,%0" + [(set_attr "length" "2") + (set_attr "length_immediate" "0") + (set_attr "modrm" "0")]) + ;; Pad to 16-byte boundary, max skip in op0. Used to avoid ;; branch prediction penalty for the third jump in a 16-byte ;; block on K8. Index: gcc/config/i386/i386.c =================================================================== --- gcc/config/i386/i386.c (revision 151419) +++ gcc/config/i386/i386.c (working copy) @@ -4777,6 +4777,19 @@ ix86_function_type_abi (const_tree fntype) return ix86_abi; } +static int +ix86_function_msvc_prologue (const_tree fntype) +{ + if (!TARGET_64BIT && fntype != NULL) + { + if(lookup_attribute ("msvc_prologue", TYPE_ATTRIBUTES (fntype))) + { + return 1; + } + } + return 0; +} + static enum calling_abi ix86_function_abi (const_tree fndecl) { @@ -4808,6 +4821,11 @@ ix86_call_abi_override (const_tree fndecl) cfun->machine->call_abi = ix86_abi; else cfun->machine->call_abi = ix86_function_type_abi (TREE_TYPE (fndecl)); + + if (fndecl == NULL_TREE) + cfun->machine->msvc_prologue = 0; + else + cfun->machine->msvc_prologue = ix86_function_msvc_prologue (TREE_TYPE (fndecl)); } /* MS and SYSV ABI have different set of call used registers. Avoid expensive @@ -8316,6 +8334,7 @@ ix86_expand_prologue (void) bool pic_reg_used; struct ix86_frame frame; HOST_WIDE_INT allocate; + int gen_frame_pointer = frame_pointer_needed; ix86_finalize_stack_realign_flags (); @@ -8328,6 +8347,44 @@ ix86_expand_prologue (void) ix86_compute_frame_layout (&frame); + if(cfun->machine->msvc_prologue) + { + rtx push, mov; + /* Make sure the function starts with + 8b ff movl.s %edi,%edi + 55 push %ebp + 8b ec movl.s %esp,%ebp + + This matches the hookable function prologue in Win32 API functions in Microsoft Windows + XP Service Pack 2 and newer. Wine uses this to enable Windows apps to hook the Win32 API + functions provided by Wine */ + insn = emit_insn(gen_vswapmov(gen_rtx_REG (Pmode, DI_REG), gen_rtx_REG (Pmode, DI_REG))); + push = emit_insn (gen_push (hard_frame_pointer_rtx)); + mov = emit_insn(gen_vswapmov(hard_frame_pointer_rtx, stack_pointer_rtx)); + + if(frame_pointer_needed && !(crtl->drap_reg && crtl->stack_realign_needed)) + { + /* The push %ebp and movl.s %esp, %ebp already set up the frame pointer. No need to do + this again. */ + gen_frame_pointer = 0; + RTX_FRAME_RELATED_P (push) = 1; + RTX_FRAME_RELATED_P (mov) = 1; + if (ix86_cfa_state->reg == stack_pointer_rtx) + ix86_cfa_state->reg = hard_frame_pointer_rtx; + } + else + { + /* If the frame pointer is not needed, pop %ebp again. This could be optimized for cases where + ebp needs to be backed up for some other reason. + + If stack realignment is needed, pop the base pointer again, align the stack, and later + regenerate the frame pointer setup. The frame pointer generated by the msvc prologue + is not aligned, so it can't be used */ + insn = emit_insn ((*ix86_gen_pop1) (hard_frame_pointer_rtx)); + } + } + + /* Emit prologue code to adjust stack alignment and setup DRAP, in case of DRAP is needed and stack realignment is really needed after reload */ if (crtl->drap_reg && crtl->stack_realign_needed) @@ -8377,14 +8434,12 @@ ix86_expand_prologue (void) /* Note: AT&T enter does NOT have reversed args. Enter is probably slower on all targets. Also sdb doesn't like it. */ - if (frame_pointer_needed) + if (gen_frame_pointer) { insn = emit_insn (gen_push (hard_frame_pointer_rtx)); RTX_FRAME_RELATED_P (insn) = 1; - insn = emit_move_insn (hard_frame_pointer_rtx, stack_pointer_rtx); RTX_FRAME_RELATED_P (insn) = 1; - if (ix86_cfa_state->reg == stack_pointer_rtx) ix86_cfa_state->reg = hard_frame_pointer_rtx; } @@ -26067,10 +26122,10 @@ ix86_handle_abi_attribute (tree *node, tree name, *no_add_attrs = true; return NULL_TREE; } - if (!TARGET_64BIT) + if (TARGET_64BIT ? is_attribute_p ("msvc_prologue", name) : !is_attribute_p ("msvc_prologue", name)) { - warning (OPT_Wattributes, "%qE attribute only available for 64-bit", - name); + warning (OPT_Wattributes, "%qE attribute only available for %d-bit", + name, TARGET_64BIT ? 32 : 64); *no_add_attrs = true; return NULL_TREE; } @@ -28983,6 +29038,9 @@ static const struct attribute_spec ix86_attribute_ /* ms_abi and sysv_abi calling convention function attributes. */ { "ms_abi", 0, 0, false, true, true, ix86_handle_abi_attribute }, { "sysv_abi", 0, 0, false, true, true, ix86_handle_abi_attribute }, +#ifdef HAVE_AS_IX86_SWAP + { "msvc_prologue", 0, 0, false, true, true, ix86_handle_abi_attribute }, +#endif /* End element. */ { NULL, 0, 0, false, false, false, NULL } }; --Boundary-00=_dVQoKKzz1eovNFc--