From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: (qmail 30314 invoked by alias); 26 Mar 2003 23:06:01 -0000 Mailing-List: contact gcc-prs-help@gcc.gnu.org; run by ezmlm Precedence: bulk List-Archive: List-Post: List-Help: Sender: gcc-prs-owner@gcc.gnu.org Received: (qmail 30299 invoked by uid 71); 26 Mar 2003 23:06:01 -0000 Date: Wed, 26 Mar 2003 23:16:00 -0000 Message-ID: <20030326230601.30298.qmail@sources.redhat.com> To: nobody@gcc.gnu.org Cc: gcc-prs@gcc.gnu.org, From: Archie Cobbs Subject: Re: c/10231: Request a "reachable" attribute for labels. Reply-To: Archie Cobbs X-SW-Source: 2003-03/txt/msg01856.txt.bz2 List-Id: The following reply was made to PR c/10231; it has been noted by GNATS. From: Archie Cobbs To: Zack Weinberg Cc: archie@dellroad.org, gcc-gnats@gcc.gnu.org Subject: Re: c/10231: Request a "reachable" attribute for labels. Date: Wed, 26 Mar 2003 14:47:41 -0800 (PST) Zack Weinberg wrote: > > goto label3; > > label2: > > printf("don't eliminate me\n"); > > label3: > > printf("ok I'm here now\n"); > > > > When optimizing -O2 GCC will eliminate the code between > > label2 and label3. However I have an application where > > I need this code to remain, because I've made the address > > of label2 available (via "&&label2") and also have some > > asm() statements that are used to jump to label2 that > > GCC doesn't know about. > > Go up a level and tell us what you're really trying to do. The > odds are that you can do it without needing to play games with > asm statements jumping to labels. That has never been supported, > as you will discover if you look at the manual. OK... This is for an application that implements a higher layer language by automatically generating C code. The higher layer language includes support for throwing and catching exceptions, very similar to how Java works (unfortunately, generating C++ instead of C is not an option). I could use setjmp/longjmp; however, because of the way the code is generated all pre-existing local variables used in the 'catch' block are volatile, so I don't need to save and restore registers, so setjmp/longjmp is too heavyweight for this purpose. Another problem with setjmp/longjmp is that you pay the price for every try/catch block whether or not any exception is thrown; I only want to pay the price if the exception is actually thrown, as they are relatively rare in my application. Instead, I have a small function implemented with asm() that "throws" the exception (this is the x86 version): // "frame" points to the saved bp of the target stack frame // "psize" is the number of bytes of pushed arguments to the // frame above (the function called by the target frame) // "pc" is the destination address in the function corresponding // to "frame" void _jc_restore_stack_frame(_jc_stack_frame *frame, int psize, const void *pc) { asm volatile ( "movl %2,%%ebx\n" /* %ebx = pc */ "movl %1,%%eax\n" /* %eax = psize */ "movl %0,%%ebp\n" /* %ebp = frame */ "leave\n" /* pop off stack frames */ "popl %%ecx\n" /* pop off saved pc */ "addl %%eax,%%esp\n" /* pop off parameters */ "jmp *%%ebx\n" /* continue */ : : "g" (frame), "g" (psize), "g" (pc) : "memory"); } The 'pc' is obtained by (admittedly questionably) relying on the fact that the .data section is layed out consecutively, and interspersing "location" structures in the target code, e.g.: struct location { const void *pc; int tag; } #define LOCATION(tag) \ { \ __label__ here; \ static struct location dummy = { &&here, (tag) }; \ here: \ } struct location func_locations[] = { }; func() { //start of "try" block //do something //end of "try" block goto label1; LOCATION(tag); //start of "catch" block //do something //end of "catch" block label1: // continue doing stuff } This works great except that sometimes GCC eliminates the "catch" code because it appears unreachable. So instead I have to do this: func() { // prevent gcc from eliminating code after 'label2' static const void *const reachables[] = { &&lable2 }: if (func == strcmp) goto *reachables[0]; //start of "try" block //do something //end of "try" block goto label2; label2: LOCATION(tag); // start of "catch" block //do something //end of "catch" block label2: // continue doing stuff } An "__attribute__ ((reachable))" could fix this.. of course what I'd really like is a built-in, efficient and more reliable way to throw and catch exceptions from within C (my trick won't work on some architectures)... any suggestions from GCC/ELF wizards along these lines are greatly appreciated. Thanks, -Archie __________________________________________________________________________ Archie Cobbs * Precision I/O * http://www.precisionio.com