Mailing-List: contact cygwin-help AT cygwin DOT com; run by ezmlm List-Subscribe: List-Archive: List-Post: List-Help: , Sender: cygwin-owner AT cygwin DOT com Mail-Followup-To: cygwin AT cygwin DOT com Delivered-To: mailing list cygwin AT cygwin DOT com Reply-To: From: "Fish" To: "Cygwin" Subject: cygwin gcc bug: stack-arg-probe (alloca) logic clobbers regparm Date: Mon, 3 Jun 2002 19:39:52 -0700 Message-ID: <000901c20b71$1aa5f910$0100a8c0@asswipe> MIME-Version: 1.0 Content-Type: text/plain; charset="iso-8859-1" Content-Transfer-Encoding: 7bit X-Priority: 3 (Normal) X-MSMail-Priority: Normal X-MimeOLE: Produced By Microsoft MimeOLE V5.50.4910.0300 Importance: Normal Hello. I believe I have stumbled across what appears to be a serious(?) gcc compiler bug with the "cygwin special" version of gcc. Whenever I define a function with the regparm(n) attribute it appears gcc prologue code sometimes clobbers one of my parameter registers producing incorrect results. This only occurs if: a) more than 4000 bytes are needed for local variable storage, and b) if -mstack-arg-probe is specified (which appears to be the default). If less than 4000 bytes *OR* -mno-stack-arg-probe is used, the problem does NOT occur. If more than 4000 bytes *AND* -mstack-arg-probe is used, the problem DOES occur. The 'eax' register -- which is one of the (the first?) regparm(n) parameter registers used to pass parameter values to my function -- appears to be getting clobbered by the prologue code that calls the __alloca function to reserve stack space for local variables (i.e. the "stack probe" logic?). A very small and simple test case is included below that tends to confirm the incorrect (buggy) behavior of the "cygwin special" version of gcc. It should, when run, display "compress: a=1, b=2, c=3" but instead displays "compress: a=4198609, b=2, c=3" when the conditions mentioned earlier exist (more than 4000 bytes of local variables *AND* -mstack-arg-probe specified). Some questions: 1. Could someone please confirm whether or not this is indeed a bug in the "cygwin special" version of gcc for me? (Or am I perhaps not doing something correctly?) Thanks. 2. What is the "cygwin special" part of gcc? That is to say, why is there a special version? Not important; just curious. :) 3. Assuming the answer to #1 is 'yes' (i.e. that this is indeed a bug), could someone give a rough estimate as to when it might be fixed? NOTE! I'm *not* in any real hurry for an immediate fix or anything! Take your time and look into it properly so you can be confident in your fix, by all means! Once again, I'm just curious, that's all. I do have a workable work-around for the time being: always use "-mno-stack-arg-probe" whenever using regparm(n). 4. Regarding the overall bug itself (assuming of course it is one): could someone please explain *why* _alloca is being called in the first place? Once again, I'm just curious. It seems to me that the -mno-stack-arg-probe behavior (emitting a simple subtract instruction ("subl $4052,%esp")) to reserve stack space for the local variables should be just as good or even better than having to call _alloca to do it, or am I missing something? Does it have to do with automatic cleanup/deallocation of local variable storage in case a longjmp is done? Is that it? (Once again, I'm just curious). That's it. Just wanted to report what appears to be a bug. Test case follows my signature below. Thanks. -- "Fish" (David B. Trout) fish AT infidels DOT org ============================================== $ gcc -v Reading specs from /usr/lib/gcc-lib/i686-pc-cygwin/2.95.3-5/specs gcc version 2.95.3-5 (cygwin special) ================( fishtest.c )================ #include #include #define uint8_t u_int8_t typedef uint8_t BYTE; typedef struct _REGS { int a, b, c, d; BYTE me[4000]; } REGS; #define ATTR_REGPARM(n) __attribute__ ((regparm(n))) #define DEF_INST(_name) \ ATTR_REGPARM(3) void _name (int a, int b, int c, REGS *regs) #define ARCH_DEP(_name) \ _name DEF_INST(compress); DEF_INST(compression_call); int main ( int argc, char *argv[] ) { REGS* regs = 0; ARCH_DEP (compression_call) (1, 2, 3, regs); return 0; } DEF_INST(compress) { printf("compress: a=%d, b=%d, c=%d\n",a,b,c); } DEF_INST(compression_call) { REGS iregs; ARCH_DEP (compress) (a, b, c, &iregs); } ============================================== gcc -DWIN32 -D_WIN32 -Wall -malign-double -mno-stack-arg-probe -DDEBUG -D_DEBUG -g -o fishtest.o -c fishtest.c -Wa,-adhln=fishtest.c.listing.txt gcc -Xlinker -Map -Xlinker fishtest.linkmap.txt -o fishtest fishtest.o ============================================== 234 .align 4 240 .globl _compression_call 242 _compression_call: 243 0080 55 pushl %ebp 244 0081 89E5 movl %esp,%ebp 245 0083 81ECD40F subl $4052,%esp 245 0000 246 0089 53 pushl %ebx 180:fishtest.c **** 181:fishtest.c **** /////////////////////////////////////////////////////// 182:fishtest.c **** 183:fishtest.c **** DEF_INST(compression_call) 184:fishtest.c **** { 248 LM10: 249 008a 8945FC movl %eax,-4(%ebp) 250 008d 8955F8 movl %edx,-8(%ebp) 251 0090 894DF4 movl %ecx,-12(%ebp) 185:fishtest.c **** REGS iregs; 253 LM11: 254 LBB3: 186:fishtest.c **** ARCH_DEP (compress) (a, b, c, &iregs); 256 LM12: 257 0093 83C4F4 addl $-12,%esp 258 0096 8B4DF4 movl -12(%ebp),%ecx 259 0099 8B55F8 movl -8(%ebp),%edx 260 009c 8B45FC movl -4(%ebp),%eax 261 009f 8D9D40F0 leal -4032(%ebp),%ebx 261 FFFF 262 00a5 53 pushl %ebx 263 00a6 89C9 movl %ecx,%ecx 264 00a8 89D2 movl %edx,%edx 265 00aa 89C0 movl %eax,%eax 266 00ac E8A3FFFF call _compress 266 FF 267 00b1 83C410 addl $16,%esp 187:fishtest.c **** } 269 LM13: 270 LBE3: 272 LM14: 273 L12: 274 00b4 8B9D28F0 movl -4056(%ebp),%ebx 274 FFFF 275 00ba 89EC movl %ebp,%esp 276 00bc 5D popl %ebp 277 00bd C3 ret ============================================== $ fishtest compress: a=1, b=2, c=3 ============================================== gcc -DWIN32 -D_WIN32 -Wall -malign-double -mstack-arg-probe -DDEBUG -D_DEBUG -g -o fishtest.o -c fishtest.c -Wa,-adhln=fishtest.c.listing.txt gcc -Xlinker -Map -Xlinker fishtest.linkmap.txt -o fishtest fishtest.o ============================================== 234 .align 4 240 .globl _compression_call 242 _compression_call: 243 0080 55 pushl %ebp 244 0081 89E5 movl %esp,%ebp 245 0083 B8D40F00 movl $4052,%eax 245 00 246 0088 E8000000 call __alloca 246 00 247 008d 53 pushl %ebx 180:fishtest.c **** 181:fishtest.c **** /////////////////////////////////////////////////////// 182:fishtest.c **** 183:fishtest.c **** DEF_INST(compression_call) 184:fishtest.c **** { 249 LM10: 250 008e 8945FC movl %eax,-4(%ebp) 251 0091 8955F8 movl %edx,-8(%ebp) 252 0094 894DF4 movl %ecx,-12(%ebp) 185:fishtest.c **** REGS iregs; 254 LM11: 255 LBB3: 186:fishtest.c **** ARCH_DEP (compress) (a, b, c, &iregs); 257 LM12: 258 0097 83C4F4 addl $-12,%esp 259 009a 8B4DF4 movl -12(%ebp),%ecx 260 009d 8B55F8 movl -8(%ebp),%edx 261 00a0 8B45FC movl -4(%ebp),%eax 262 00a3 8D9D40F0 leal -4032(%ebp),%ebx 262 FFFF 263 00a9 53 pushl %ebx 264 00aa 89C9 movl %ecx,%ecx 265 00ac 89D2 movl %edx,%edx 266 00ae 89C0 movl %eax,%eax 267 00b0 E89FFFFF call _compress 267 FF 268 00b5 83C410 addl $16,%esp 187:fishtest.c **** } 270 LM13: 271 LBE3: 273 LM14: 274 L12: 275 00b8 8B9D28F0 movl -4056(%ebp),%ebx 275 FFFF 276 00be 89EC movl %ebp,%esp 277 00c0 5D popl %ebp 278 00c1 C3 ret ============================================== $ fishtest compress: a=4198609, b=2, c=3 ============================================== -- Unsubscribe info: http://cygwin.com/ml/#unsubscribe-simple Bug reporting: http://cygwin.com/bugs.html Documentation: http://cygwin.com/docs.html FAQ: http://cygwin.com/faq/