From: Richard Lowe Date: Sat, 27 Oct 2012 02:44:09 +0100 Subject: [PATCH] Implement -fstrict-calling-conventions Stock GCC is overly willing to violate the ABI when calling local functions, such that it passes arguments in registers on i386. This hampers debugging with anything other than a fully-aware DWARF debugger, and is generally not something we desire. Implement a flag which disables this behaviour, enabled by default. The flag is global, though only effective on i386, to more easily allow its globalization later which, given the odds, is likely to be necessary. See http://wiki.illumos.org/display/illumos/GCC+Modifications Index: gcc-9.git/src/gcc/common.opt =================================================================== --- gcc-9.git.orig/src/gcc/common.opt +++ gcc-9.git/src/gcc/common.opt @@ -2499,6 +2499,10 @@ fstrict-aliasing Common Report Var(flag_strict_aliasing) Optimization Assume strict aliasing rules apply. +fstrict-calling-conventions +Common Report Var(flag_strict_calling_conventions) Init(1) +Use strict ABI calling conventions even for static functions + fstrict-overflow Common Report Treat signed overflow as undefined. Negated as -fwrapv -fwrapv-pointer. Index: gcc-9.git/src/gcc/config/i386/i386.c =================================================================== --- gcc-9.git.orig/src/gcc/config/i386/i386.c +++ gcc-9.git/src/gcc/config/i386/i386.c @@ -6608,6 +6608,7 @@ ix86_function_regparm (const_tree type, /* Use register calling convention for local functions when possible. */ if (decl + && (TARGET_64BIT || !flag_strict_calling_conventions) && TREE_CODE (decl) == FUNCTION_DECL) { cgraph_node *target = cgraph_node::get (decl); @@ -6717,6 +6718,7 @@ ix86_function_sseregparm (const_tree typ /* TARGET_SSE_MATH */ && (target_opts_for_fn (target->decl)->x_ix86_fpmath & FPMATH_SSE) && opt_for_fn (target->decl, optimize) + && (TARGET_64BIT || !flag_strict_calling_conventions) && !(profile_flag && !flag_fentry)) { cgraph_local_info *i = &target->local; Index: gcc-9.git/src/gcc/doc/invoke.texi =================================================================== --- gcc-9.git.orig/src/gcc/doc/invoke.texi +++ gcc-9.git/src/gcc/doc/invoke.texi @@ -13756,6 +13756,12 @@ overflow on addition and subtraction wra representation. This flag disables some optimizations which assume pointer overflow is invalid. +@item -fstrict-calling-conventions +@opindex fstrict-calling-conventions +Use strict ABI calling conventions even with local functions. +This disable certain optimizations that may cause GCC to call local +functions in a manner other than that described by the ABI. + @item -fstrict-overflow @opindex fstrict-overflow This option implies @option{-fno-wrapv} @option{-fno-wrapv-pointer} and when Index: gcc-9.git/src/gcc/testsuite/gcc.target/i386/local.c =================================================================== --- gcc-9.git.orig/src/gcc/testsuite/gcc.target/i386/local.c +++ gcc-9.git/src/gcc/testsuite/gcc.target/i386/local.c @@ -1,5 +1,6 @@ /* { dg-do compile } */ -/* { dg-options "-O2 -funit-at-a-time" } */ +/* { dg-options "-O2 -funit-at-a-time -fno-strict-calling-conventions" { target ilp32 } } */ +/* { dg-options "-O2 -funit-at-a-time" { target lp64 } } */ /* { dg-final { scan-assembler "magic\[^\\n\]*eax" { target ia32 } } } */ /* { dg-final { scan-assembler "magic\[^\\n\]*(edi|ecx)" { target { ! ia32 } } } } */ Index: gcc-9.git/src/gcc/testsuite/gcc.target/i386/strict-cc.c =================================================================== --- /dev/null +++ gcc-9.git/src/gcc/testsuite/gcc.target/i386/strict-cc.c @@ -0,0 +1,22 @@ +/* { dg-do compile { target { ilp32 } } } */ +/* { dg-options "-O2 -funit-at-a-time -fstrict-calling-conventions" } */ +/* { dg-final { scan-assembler "pushl.*\\\$1" } } */ +/* { dg-final { scan-assembler "pushl.*\\\$2" } } */ +/* { dg-final { scan-assembler "pushl.*\\\$3" } } */ +/* { dg-final { scan-assembler "pushl.*\\\$4" } } */ +/* { dg-final { scan-assembler "pushl.*\\\$5" } } */ + +#include + +/* Verify that local calling convention is not used if strict conventions. */ +static t(int, int, int, int, int) __attribute__ ((noinline)); + +m() +{ + t(1, 2, 3, 4, 5); +} + +static t(int a, int b, int c, int d, int e) +{ + printf("%d\n", a, b, c, d, e); +}