i386.md (vswapmov): New.

2009-10-12  Stefan Dösinger  <stefan@codeweavers.com>

	* config/i386/i386.md (vswapmov): New.
	* config/i386/i386.c (ix86_handle_fndecl_attribute): New.
	(ix86_function_ms_hook_prologue): New.
	(ix86_expand_prologue): Handle ms_hook_prologue attribute.
	* configure.ac: Test for swap suffix support in as.
	* configure: Rebuild.

From-SVN: r152670
This commit is contained in:
Stefan Dösinger 2009-10-12 16:36:37 +00:00 committed by Richard Henderson
parent ea1b2f550d
commit afd2c302c6
7 changed files with 158 additions and 1 deletions

View file

@ -1,3 +1,12 @@
2009-10-12 Stefan Dösinger <stefan@codeweavers.com>
* config/i386/i386.md (vswapmov): New.
* config/i386/i386.c (ix86_handle_fndecl_attribute): New.
(ix86_function_ms_hook_prologue): New.
(ix86_expand_prologue): Handle ms_hook_prologue attribute.
* configure.ac: Test for swap suffix support in as.
* configure: Rebuild.
2009-10-12 Jakub Jelinek <jakub@redhat.com>
PR target/41680

View file

@ -4774,6 +4774,25 @@ ix86_function_type_abi (const_tree fntype)
return ix86_abi;
}
static bool
ix86_function_ms_hook_prologue (const_tree fntype)
{
if (!TARGET_64BIT)
{
if (lookup_attribute ("ms_hook_prologue", DECL_ATTRIBUTES (fntype)))
{
if (decl_function_context (fntype) != NULL_TREE)
{
error_at (DECL_SOURCE_LOCATION (fntype),
"ms_hook_prologue is not compatible with nested function");
}
return true;
}
}
return false;
}
static enum calling_abi
ix86_function_abi (const_tree fndecl)
{
@ -8295,6 +8314,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 ();
@ -8307,6 +8327,46 @@ ix86_expand_prologue (void)
ix86_compute_frame_layout (&frame);
if (ix86_function_ms_hook_prologue (current_function_decl))
{
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 (SImode, DI_REG), gen_rtx_REG (SImode, 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 hook prologue
is not aligned, so it can't be used */
insn = emit_insn ((*ix86_gen_pop1) (hard_frame_pointer_rtx));
}
}
/* The first insn of a function that accepts its static chain on the
stack is to push the register that would be filled in by a direct
call. This insn will be skipped by the trampoline. */
@ -8378,7 +8438,7 @@ 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;
@ -26470,6 +26530,35 @@ ix86_handle_struct_attribute (tree *node, tree name,
return NULL_TREE;
}
#include <signal.h>
static tree
ix86_handle_fndecl_attribute (tree *node, tree name,
tree args ATTRIBUTE_UNUSED,
int flags ATTRIBUTE_UNUSED, bool *no_add_attrs)
{
if (TREE_CODE (*node) != FUNCTION_DECL)
{
warning (OPT_Wattributes, "%qE attribute only applies to functions",
name);
*no_add_attrs = true;
return NULL_TREE;
}
if (TARGET_64BIT)
{
warning (OPT_Wattributes, "%qE attribute only available for 32-bit",
name);
return NULL_TREE;
}
#ifndef HAVE_AS_IX86_SWAP
sorry ("ms_hook_prologue attribute needs assembler swap suffix support");
#endif
return NULL_TREE;
}
static bool
ix86_ms_bitfield_layout_p (const_tree record_type)
{
@ -29512,6 +29601,7 @@ static const struct attribute_spec ix86_attribute_table[] =
/* 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 },
{ "ms_hook_prologue", 0, 0, true, false, false, ix86_handle_fndecl_attribute },
/* End element. */
{ NULL, 0, 0, false, false, false, NULL }
};

View file

@ -241,6 +241,7 @@
(UNSPECV_RDTSC 18)
(UNSPECV_RDTSCP 19)
(UNSPECV_RDPMC 20)
(UNSPECV_VSWAPMOV 21)
])
;; Constants to represent pcomtrue/pcomfalse variants
@ -14893,6 +14894,16 @@
(set_attr "length_immediate" "0")
(set_attr "modrm" "0")])
(define_insn "vswapmov"
[(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|%0, %1}"
[(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.

View file

@ -3047,6 +3047,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

View file

@ -2679,6 +2679,14 @@ when targeting Windows. On all other systems, the default is the AMD ABI.
Note, This feature is currently sorried out for Windows targets trying to
@item ms_hook_prologue
@cindex @code{ms_hook_prologue} attribute
On 32 bit i[34567]86-*-* 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. (GNU Binutils 2.19.51 or later)
@item naked
@cindex function without a prologue/epilogue code
Use this attribute on the ARM, AVR, IP2K and SPU ports to indicate that

View file

@ -1,3 +1,7 @@
2009-10-12 Stefan Dösinger <stefan@codeweavers.com>
* gcc.target/i386/ms_hook_prologue.c: New testcase.
2009-10-12 Michael Matz <matz@suse.de>
* gcc.dg/plugin/one_time_plugin.c: Update test to use the cfg

View file

@ -0,0 +1,29 @@
/* Test that the ms_hook_prologue attribute generates the correct code. */
/* { dg-do run } */
/* { dg-require-effective-target ilp32 } */
/* { dg-options "-O2 -fomit-frame-pointer" } */
int __attribute__ ((__ms_hook_prologue__)) foo ()
{
unsigned char *ptr = (unsigned char *) foo;
/* The NOP mov must not be optimized away by optimizations.
The push %ebp, mov %esp, %ebp must not be removed by
-fomit-frame-pointer */
/* movl.s %edi, %edi */
if(*ptr++ != 0x8b) return 1;
if(*ptr++ != 0xff) return 1;
/* push %ebp */
if(*ptr++ != 0x55) return 1;
/* movl.s %esp, %ebp */
if(*ptr++ != 0x8b) return 1;
if(*ptr++ != 0xec) return 1;
return 0;
}
int main ()
{
return foo();
}