diff options
author | Uros Bizjak <uros@gcc.gnu.org> | 2008-04-06 08:40:47 +0200 |
---|---|---|
committer | Uros Bizjak <uros@gcc.gnu.org> | 2008-04-06 08:40:47 +0200 |
commit | 27183bba6bc249ae4c73bb799c7df702e98a2467 (patch) | |
tree | fab042be595339e8cc2b6a43e033a7b1e7d24655 /gcc/config | |
parent | 93f14b2fc38a2221142d513151a437ef9f14feb8 (diff) | |
download | gcc-27183bba6bc249ae4c73bb799c7df702e98a2467.zip gcc-27183bba6bc249ae4c73bb799c7df702e98a2467.tar.gz gcc-27183bba6bc249ae4c73bb799c7df702e98a2467.tar.bz2 |
re PR target/12329 (x86: local function declared with attribute((regparm(3))) gets corrupted parent frame pointer)
PR target/12329
* config/i386/i386.c (ix86_function_regparm): Error if regparm(3)
attribute is used for nested functions.
testsuite/ChangeLog:
PR target/12329
* gcc.target/i386/pr12329.c: New test.
From-SVN: r133954
Diffstat (limited to 'gcc/config')
-rw-r--r-- | gcc/config/i386/i386.c | 23 |
1 files changed, 22 insertions, 1 deletions
diff --git a/gcc/config/i386/i386.c b/gcc/config/i386/i386.c index 14aac46..161f9e4 100644 --- a/gcc/config/i386/i386.c +++ b/gcc/config/i386/i386.c @@ -3250,12 +3250,33 @@ ix86_function_regparm (const_tree type, const_tree decl) tree attr; int regparm = ix86_regparm; + static bool error_issued; + if (TARGET_64BIT) return regparm; attr = lookup_attribute ("regparm", TYPE_ATTRIBUTES (type)); if (attr) - return TREE_INT_CST_LOW (TREE_VALUE (TREE_VALUE (attr))); + { + regparm + = TREE_INT_CST_LOW (TREE_VALUE (TREE_VALUE (attr))); + + if (decl && TREE_CODE (decl) == FUNCTION_DECL) + { + /* We can't use regparm(3) for nested functions because + these pass static chain pointer in %ecx register. */ + if (!error_issued && regparm == 3 + && decl_function_context (decl) + && !DECL_NO_STATIC_CHAIN (decl)) + { + error ("nested functions are limited to 2 register parameters"); + error_issued = true; + return 0; + } + } + + return regparm; + } if (lookup_attribute ("fastcall", TYPE_ATTRIBUTES (type))) return 2; |