* C++: Letting compiler know asm block can call function that can throw? @ 2012-03-29 7:05 Stephan Bergmann 2012-03-29 7:44 ` Jakub Jelinek 2012-03-29 16:14 ` Richard Henderson 0 siblings, 2 replies; 22+ messages in thread From: Stephan Bergmann @ 2012-03-29 7:05 UTC (permalink / raw) To: gcc Hi all, In LibreOffice's ever-beloved low-level code to synthesize calls to C++ virtual functions, I'm having the following problem (on Linux x86_64). The function callVirtualMethod at <http://cgit.freedesktop.org/libreoffice/core/tree/bridges/source/cpp_uno/gcc3_linux_x86-64/uno2cpp.cxx?id=571876c1234ae55aab0198c7e2caf9049fcd230e#n61> effectively does the following: First, call dummy_can_throw_anything that can potentially throw (see below for why that's there). Second, in an asm block, call some virtual function (that can potentially throw). Third, call x86_64::fill_struct that can potentially throw (it doesn't, but nobody bothered to annotate it as "throw ()"). Now, at least GCC 4.7.0 with -O0 produces a .gcc_except_table section for callVirtualMethod, with two call-site table entries each spanning the first (dummy_can_throw_anything) and third (x86_64::fill_struct) calls, resp., but none spanning the second (asm block) call. These entries are effectively nop, simply calling back into _Unwind_Resume, and compiling at higher optimization levels leaves them out anyway (leading to callVirtualMethod having no corresponding .gcc_except_table section). The problem is that if the virtual function called through the asm block throws an exception, that then immediately leads to std::terminate. My understanding is that because the ip is at the call instruction in the asm block that is between the two call-site table entries, the unwind machinery thinks this cannot happen and bails out. (When compiled -O2, the code happens to work fine, as there is no .gcc_except_table section for this frame at all, so unwinding simply passes through it without calling the personality function.) Making sure that there are no calls to (compiler-visible) functions that can throw within callVirtualMethod would happen to make the code also work with -O0. But that would remain a fragile solution. Is there a way to let the compiler know that the asm block potentially calls functions that can throw? So that it could emit correct code, regardless of whether callVirtualMethod happens to have a corresponding .gcc_except_table section or not. (The call to dummy_can_throw_anything, copied from the corresponding older code for 32-bit x86, is there for the following reason: At least with some compiler version and some optimization level, on x86 it was discovered that the compiler did not emit the .eh_frame data necessary for unwinding to successfully pass through this frame at all. As the corresponding x86 code does not have a call to x86_64::fill_struct, the compiler apparently considered callVirtualMethod a leaf function and optimized accordingly. The dummy_can_throw_anything hack happened to make it do the right thing again, but again this is a fragile solution, anyway, that could be replaced with something robust if there were a way to annotate the asm block as "calls functions that can throw.") Stephan ^ permalink raw reply [flat|nested] 22+ messages in thread
* Re: C++: Letting compiler know asm block can call function that can throw? 2012-03-29 7:05 C++: Letting compiler know asm block can call function that can throw? Stephan Bergmann @ 2012-03-29 7:44 ` Jakub Jelinek 2012-03-29 8:48 ` Stephan Bergmann 2012-03-29 16:14 ` Richard Henderson 1 sibling, 1 reply; 22+ messages in thread From: Jakub Jelinek @ 2012-03-29 7:44 UTC (permalink / raw) To: Stephan Bergmann; +Cc: gcc On Thu, Mar 29, 2012 at 09:05:29AM +0200, Stephan Bergmann wrote: > In LibreOffice's ever-beloved low-level code to synthesize calls to > C++ virtual functions, I'm having the following problem (on Linux > x86_64). The function callVirtualMethod at <http://cgit.freedesktop.org/libreoffice/core/tree/bridges/source/cpp_uno/gcc3_linux_x86-64/uno2cpp.cxx?id=571876c1234ae55aab0198c7e2caf9049fcd230e#n61> > effectively does the following: > > First, call dummy_can_throw_anything that can potentially throw (see > below for why that's there). Second, in an asm block, call some > virtual function (that can potentially throw). Third, call > x86_64::fill_struct that can potentially throw (it doesn't, but > nobody bothered to annotate it as "throw ()"). If the asm isn't in headers, but just in a single short source file or two, you could try compiling that file with -fnon-call-exceptions. It is nothing I'd recommend for the whole codebase though. Jakub ^ permalink raw reply [flat|nested] 22+ messages in thread
* Re: C++: Letting compiler know asm block can call function that can throw? 2012-03-29 7:44 ` Jakub Jelinek @ 2012-03-29 8:48 ` Stephan Bergmann 2012-03-29 9:16 ` Richard Guenther 0 siblings, 1 reply; 22+ messages in thread From: Stephan Bergmann @ 2012-03-29 8:48 UTC (permalink / raw) Cc: gcc On 03/29/2012 09:44 AM, Jakub Jelinek wrote: > On Thu, Mar 29, 2012 at 09:05:29AM +0200, Stephan Bergmann wrote: >> In LibreOffice's ever-beloved low-level code to synthesize calls to >> C++ virtual functions, I'm having the following problem (on Linux >> x86_64). The function callVirtualMethod at<http://cgit.freedesktop.org/libreoffice/core/tree/bridges/source/cpp_uno/gcc3_linux_x86-64/uno2cpp.cxx?id=571876c1234ae55aab0198c7e2caf9049fcd230e#n61> >> effectively does the following: >> >> First, call dummy_can_throw_anything that can potentially throw (see >> below for why that's there). Second, in an asm block, call some >> virtual function (that can potentially throw). Third, call >> x86_64::fill_struct that can potentially throw (it doesn't, but >> nobody bothered to annotate it as "throw ()"). > > If the asm isn't in headers, but just in a single short source file > or two, you could try compiling that file with -fnon-call-exceptions. > It is nothing I'd recommend for the whole codebase though. Turns out I had to move the callVirtualMethod function containing the asm into a source file of its own, anyway. (Otherwise, even if it no longer explicitly called functions that can throw, and thus no longer had corresponding .gcc_except_table entries, exception throwing still lead to std::terminate. There are other functions in the same source file callVirtualMethod was originally in that do have .gcc_except_table entries. Kind of invalidates my previous explanation of why exception handling bailed out to std::terminate. Looks like I haven't groked it yet, anyway.) So an explicit -fnon-call-exceptions on the command line seems to indeed help. Unfortunately, moving that into a #pragma GCC optimize ("non-call-exceptions") at the top of the source file that defines callVirtualMethod (and nothing more) does *not* work. Is that a bug? Anyway, would it be worthwhile filing an RFE for an asm annotation telling the compiler that it contains code that can throw? Thanks, Stephan ^ permalink raw reply [flat|nested] 22+ messages in thread
* Re: C++: Letting compiler know asm block can call function that can throw? 2012-03-29 8:48 ` Stephan Bergmann @ 2012-03-29 9:16 ` Richard Guenther 2012-03-29 12:51 ` Stephan Bergmann 0 siblings, 1 reply; 22+ messages in thread From: Richard Guenther @ 2012-03-29 9:16 UTC (permalink / raw) To: Stephan Bergmann; +Cc: gcc On Thu, Mar 29, 2012 at 10:47 AM, Stephan Bergmann <sbergman@redhat.com> wrote: > On 03/29/2012 09:44 AM, Jakub Jelinek wrote: >> >> On Thu, Mar 29, 2012 at 09:05:29AM +0200, Stephan Bergmann wrote: >>> >>> In LibreOffice's ever-beloved low-level code to synthesize calls to >>> C++ virtual functions, I'm having the following problem (on Linux >>> x86_64). The function callVirtualMethod >>> at<http://cgit.freedesktop.org/libreoffice/core/tree/bridges/source/cpp_uno/gcc3_linux_x86-64/uno2cpp.cxx?id=571876c1234ae55aab0198c7e2caf9049fcd230e#n61> >>> effectively does the following: >>> >>> First, call dummy_can_throw_anything that can potentially throw (see >>> below for why that's there). Second, in an asm block, call some >>> virtual function (that can potentially throw). Third, call >>> x86_64::fill_struct that can potentially throw (it doesn't, but >>> nobody bothered to annotate it as "throw ()"). >> >> >> If the asm isn't in headers, but just in a single short source file >> or two, you could try compiling that file with -fnon-call-exceptions. >> It is nothing I'd recommend for the whole codebase though. > > > Turns out I had to move the callVirtualMethod function containing the asm > into a source file of its own, anyway. (Otherwise, even if it no longer > explicitly called functions that can throw, and thus no longer had > corresponding .gcc_except_table entries, exception throwing still lead to > std::terminate. There are other functions in the same source file > callVirtualMethod was originally in that do have .gcc_except_table entries. > Kind of invalidates my previous explanation of why exception handling > bailed out to std::terminate. Looks like I haven't groked it yet, anyway.) > > So an explicit -fnon-call-exceptions on the command line seems to indeed > help. Unfortunately, moving that into a > > #pragma GCC optimize ("non-call-exceptions") > > at the top of the source file that defines callVirtualMethod (and nothing > more) does *not* work. Is that a bug? The optimize pragma has only very limited support for this kind of options, so yes, it's techincally a bug but don't hold your breath. > Anyway, would it be worthwhile filing an RFE for an asm annotation telling > the compiler that it contains code that can throw? I suppose yes. Richard. > Thanks, > Stephan ^ permalink raw reply [flat|nested] 22+ messages in thread
* Re: C++: Letting compiler know asm block can call function that can throw? 2012-03-29 9:16 ` Richard Guenther @ 2012-03-29 12:51 ` Stephan Bergmann 2012-03-29 13:59 ` Michael Matz 0 siblings, 1 reply; 22+ messages in thread From: Stephan Bergmann @ 2012-03-29 12:51 UTC (permalink / raw) To: gcc On 03/29/2012 11:16 AM, Richard Guenther wrote: > On Thu, Mar 29, 2012 at 10:47 AM, Stephan Bergmann<sbergman@redhat.com> wrote: >> So an explicit -fnon-call-exceptions on the command line seems to indeed >> help. Unfortunately, moving that into a >> >> #pragma GCC optimize ("non-call-exceptions") >> >> at the top of the source file that defines callVirtualMethod (and nothing >> more) does *not* work. Is that a bug? > > The optimize pragma has only very limited support for this kind of options, > so yes, it's techincally a bug but don't hold your breath. OK. (It's just that the way LibreOffice is build, its a PITA to compile a single file with differing options...) >> Anyway, would it be worthwhile filing an RFE for an asm annotation telling >> the compiler that it contains code that can throw? > > I suppose yes. <http://gcc.gnu.org/bugzilla/show_bug.cgi?id=52770> "RFE: Letting compiler know asm block can call function that can throw." Thanks, Stephan ^ permalink raw reply [flat|nested] 22+ messages in thread
* Re: C++: Letting compiler know asm block can call function that can throw? 2012-03-29 12:51 ` Stephan Bergmann @ 2012-03-29 13:59 ` Michael Matz 2012-03-29 14:12 ` Andrew Haley 2012-03-30 8:23 ` Richard Guenther 0 siblings, 2 replies; 22+ messages in thread From: Michael Matz @ 2012-03-29 13:59 UTC (permalink / raw) To: Stephan Bergmann; +Cc: gcc Hi, On Thu, 29 Mar 2012, Stephan Bergmann wrote: > > > Anyway, would it be worthwhile filing an RFE for an asm annotation > > > telling the compiler that it contains code that can throw? > > > > I suppose yes. > > <http://gcc.gnu.org/bugzilla/show_bug.cgi?id=52770> "RFE: Letting > compiler know asm block can call function that can throw." Actually, with -fnon-call-exceptions volatile asms are already supposed to be throwing. It's just that this got lost with tree-ssa. With the patch and -fnon-call-exceptions a simple "__asm__ volatile (...)" is regarded as possibly throwing. Without -fnon-call-exceptions some parser changes would be required. How about "asm throw (...)" ? Ciao, Michael. Index: tree-eh.c =================================================================== --- tree-eh.c (revision 183716) +++ tree-eh.c (working copy) @@ -1959,6 +1959,7 @@ lower_eh_constructs_2 (struct leh_state } /* FALLTHRU */ + case GIMPLE_ASM: case GIMPLE_ASSIGN: /* If the stmt can throw use a new temporary for the assignment to a LHS. This makes sure the old value of the LHS is Index: tree-cfg.c =================================================================== --- tree-cfg.c (revision 183716) +++ tree-cfg.c (working copy) @@ -580,6 +580,8 @@ make_edges (void) case GIMPLE_ASM: make_gimple_asm_edges (bb); + if (is_ctrl_altering_stmt (last)) + make_eh_edges (last); fallthru = true; break; ^ permalink raw reply [flat|nested] 22+ messages in thread
* Re: C++: Letting compiler know asm block can call function that can throw? 2012-03-29 13:59 ` Michael Matz @ 2012-03-29 14:12 ` Andrew Haley 2012-03-29 15:10 ` Stephan Bergmann 2012-03-29 15:43 ` Michael Matz 2012-03-30 8:23 ` Richard Guenther 1 sibling, 2 replies; 22+ messages in thread From: Andrew Haley @ 2012-03-29 14:12 UTC (permalink / raw) To: gcc On 03/29/2012 02:59 PM, Michael Matz wrote: > Actually, with -fnon-call-exceptions volatile asms are already supposed to > be throwing. It's just that this got lost with tree-ssa. With the patch > and -fnon-call-exceptions a simple "__asm__ volatile (...)" is regarded as > possibly throwing. > > Without -fnon-call-exceptions some parser changes would be required. How > about "asm throw (...)" ? Is there any point? I would have thought that -fnon-call-exceptions was exactly what you need. Andrew. ^ permalink raw reply [flat|nested] 22+ messages in thread
* Re: C++: Letting compiler know asm block can call function that can throw? 2012-03-29 14:12 ` Andrew Haley @ 2012-03-29 15:10 ` Stephan Bergmann 2012-03-29 15:43 ` Michael Matz 1 sibling, 0 replies; 22+ messages in thread From: Stephan Bergmann @ 2012-03-29 15:10 UTC (permalink / raw) To: gcc On 03/29/2012 04:12 PM, Andrew Haley wrote: > On 03/29/2012 02:59 PM, Michael Matz wrote: >> Actually, with -fnon-call-exceptions volatile asms are already supposed to >> be throwing. It's just that this got lost with tree-ssa. With the patch >> and -fnon-call-exceptions a simple "__asm__ volatile (...)" is regarded as >> possibly throwing. >> >> Without -fnon-call-exceptions some parser changes would be required. How >> about "asm throw (...)" ? > > Is there any point? I would have thought that -fnon-call-exceptions was > exactly what you need. But it looks wrong to me to have to mark the complete compilation unit for something that should only affect a single asm declaration. (Also, having to specify -fnon-call-exceptions "externally," on the command line, is somewhat awkward.) Stephan ^ permalink raw reply [flat|nested] 22+ messages in thread
* Re: C++: Letting compiler know asm block can call function that can throw? 2012-03-29 14:12 ` Andrew Haley 2012-03-29 15:10 ` Stephan Bergmann @ 2012-03-29 15:43 ` Michael Matz 2012-03-29 20:38 ` Eric Botcazou 1 sibling, 1 reply; 22+ messages in thread From: Michael Matz @ 2012-03-29 15:43 UTC (permalink / raw) To: Andrew Haley; +Cc: gcc Hi, On Thu, 29 Mar 2012, Andrew Haley wrote: > On 03/29/2012 02:59 PM, Michael Matz wrote: > > Actually, with -fnon-call-exceptions volatile asms are already supposed to > > be throwing. It's just that this got lost with tree-ssa. With the patch > > and -fnon-call-exceptions a simple "__asm__ volatile (...)" is regarded as > > possibly throwing. > > > > Without -fnon-call-exceptions some parser changes would be required. How > > about "asm throw (...)" ? > > Is there any point? I would have thought that -fnon-call-exceptions was > exactly what you need. non-call-exceptions is a relatively big hammer. It marks _all_ non-trivial instructions as throwing. Providing an explicit marker would allow for more granularity. Granted, the request didn't come often over the last years, but it seems like a relatively self-contained and useful addition to inline asms. Ciao, Michael. ^ permalink raw reply [flat|nested] 22+ messages in thread
* Re: C++: Letting compiler know asm block can call function that can throw? 2012-03-29 15:43 ` Michael Matz @ 2012-03-29 20:38 ` Eric Botcazou 0 siblings, 0 replies; 22+ messages in thread From: Eric Botcazou @ 2012-03-29 20:38 UTC (permalink / raw) To: Michael Matz; +Cc: gcc, Andrew Haley > non-call-exceptions is a relatively big hammer. It marks _all_ > non-trivial instructions as throwing. The "all" goes against the "relatively" here, and "relatively" is more correct. Not all non-trivial instructions are marked as throwing, e.g. loads and stores from/to the stack aren't. -- Eric Botcazou ^ permalink raw reply [flat|nested] 22+ messages in thread
* Re: C++: Letting compiler know asm block can call function that can throw? 2012-03-29 13:59 ` Michael Matz 2012-03-29 14:12 ` Andrew Haley @ 2012-03-30 8:23 ` Richard Guenther 1 sibling, 0 replies; 22+ messages in thread From: Richard Guenther @ 2012-03-30 8:23 UTC (permalink / raw) To: Michael Matz; +Cc: Stephan Bergmann, gcc On Thu, Mar 29, 2012 at 3:59 PM, Michael Matz <matz@suse.de> wrote: > Hi, > > On Thu, 29 Mar 2012, Stephan Bergmann wrote: > >> > > Anyway, would it be worthwhile filing an RFE for an asm annotation >> > > telling the compiler that it contains code that can throw? >> > >> > I suppose yes. >> >> <http://gcc.gnu.org/bugzilla/show_bug.cgi?id=52770> "RFE: Letting >> compiler know asm block can call function that can throw." > > Actually, with -fnon-call-exceptions volatile asms are already supposed to > be throwing. It's just that this got lost with tree-ssa. With the patch > and -fnon-call-exceptions a simple "__asm__ volatile (...)" is regarded as > possibly throwing. > > Without -fnon-call-exceptions some parser changes would be required. How > about "asm throw (...)" ? > > > Ciao, > Michael. > Index: tree-eh.c > =================================================================== > --- tree-eh.c (revision 183716) > +++ tree-eh.c (working copy) > @@ -1959,6 +1959,7 @@ lower_eh_constructs_2 (struct leh_state > } > /* FALLTHRU */ > > + case GIMPLE_ASM: > case GIMPLE_ASSIGN: > /* If the stmt can throw use a new temporary for the assignment > to a LHS. This makes sure the old value of the LHS is This does not handle using a temporary for all (register) outputs ... I suppose the code should walk all SSA defs instead of looking at the LHS only. > Index: tree-cfg.c > =================================================================== > --- tree-cfg.c (revision 183716) > +++ tree-cfg.c (working copy) > @@ -580,6 +580,8 @@ make_edges (void) > > case GIMPLE_ASM: > make_gimple_asm_edges (bb); > + if (is_ctrl_altering_stmt (last)) > + make_eh_edges (last); > fallthru = true; > break; Otherwise this looks reasonable. With a testcase, I suppose ;) Richard. ^ permalink raw reply [flat|nested] 22+ messages in thread
* Re: C++: Letting compiler know asm block can call function that can throw? 2012-03-29 7:05 C++: Letting compiler know asm block can call function that can throw? Stephan Bergmann 2012-03-29 7:44 ` Jakub Jelinek @ 2012-03-29 16:14 ` Richard Henderson 2012-03-29 17:16 ` Jan Hubicka 1 sibling, 1 reply; 22+ messages in thread From: Richard Henderson @ 2012-03-29 16:14 UTC (permalink / raw) To: Stephan Bergmann; +Cc: gcc On 03/29/2012 03:05 AM, Stephan Bergmann wrote: > Hi all, > > In LibreOffice's ever-beloved low-level code to synthesize calls to > C++ virtual functions, I'm having the following problem (on Linux > x86_64). The function callVirtualMethod at > <http://cgit.freedesktop.org/libreoffice/core/tree/bridges/source/cpp_uno/gcc3_linux_x86-64/uno2cpp.cxx?id=571876c1234ae55aab0198c7e2caf9049fcd230e#n61> > effectively does the following: Quoting: asm volatile ( // Fill the xmm registers "movq %6, %%rax\n\t" "movsd (%%rax), %%xmm0\n\t" "movsd 8(%%rax), %%xmm1\n\t" "movsd 16(%%rax), %%xmm2\n\t" "movsd 24(%%rax), %%xmm3\n\t" "movsd 32(%%rax), %%xmm4\n\t" "movsd 40(%%rax), %%xmm5\n\t" "movsd 48(%%rax), %%xmm6\n\t" "movsd 56(%%rax), %%xmm7\n\t" // Fill the general purpose registers "movq %5, %%rax\n\t" "movq (%%rax), %%rdi\n\t" "movq 8(%%rax), %%rsi\n\t" "movq 16(%%rax), %%rdx\n\t" "movq 24(%%rax), %%rcx\n\t" "movq 32(%%rax), %%r8\n\t" "movq 40(%%rax), %%r9\n\t" // Perform the call "movq %4, %%r11\n\t" "movq %7, %%rax\n\t" "call *%%r11\n\t" // Fill the return values "movq %%rax, %0\n\t" "movq %%rdx, %1\n\t" "movsd %%xmm0, %2\n\t" "movsd %%xmm1, %3\n\t" : "=m" ( rax ), "=m" ( rdx ), "=m" ( xmm0 ), "=m" ( xmm1 ) : "m" ( pMethod ), "m" ( pGPR ), "m" ( pFPR ), "m" ( nFPR ) : "rax", "rdi", "rsi", "rdx", "rcx", "r8", "r9", "r11" ); Semi-off-topic, I think this asm can be better done with only the call inside the asm, and the rest handled by the compiler. { register sal_uInt64 hard_r8 __asm__("rax"); // etc register double hard_xmm0 __asm__("xmm0"); // etc hard_rdi = pGPR[0]; //etc hard_xmm0 = pFPR[0]; //etc hard_rax = nFPR; asm volatile ("call *%[method]" : "+r"(hard_rax), //etc "+x"(hard_xmm0), //etc : "g" [method] (pMethod) : "memory"); rax = hard_rax; rdx = hard_rdx; xmm0 = hard_xmm0; xmm1 = hard_xmm1; } Of course, there's still the problem of getting the unwind data correct at the point of the asm. I commented about that in the PR you filed. r~ ^ permalink raw reply [flat|nested] 22+ messages in thread
* Re: C++: Letting compiler know asm block can call function that can throw? 2012-03-29 16:14 ` Richard Henderson @ 2012-03-29 17:16 ` Jan Hubicka 2012-03-29 18:34 ` Richard Henderson 0 siblings, 1 reply; 22+ messages in thread From: Jan Hubicka @ 2012-03-29 17:16 UTC (permalink / raw) To: Richard Henderson; +Cc: Stephan Bergmann, gcc > On 03/29/2012 03:05 AM, Stephan Bergmann wrote: > > Hi all, > > > > In LibreOffice's ever-beloved low-level code to synthesize calls to > > C++ virtual functions, I'm having the following problem (on Linux > > x86_64). The function callVirtualMethod at > > <http://cgit.freedesktop.org/libreoffice/core/tree/bridges/source/cpp_uno/gcc3_linux_x86-64/uno2cpp.cxx?id=571876c1234ae55aab0198c7e2caf9049fcd230e#n61> > > effectively does the following: > > Quoting: > > asm volatile ( > > // Fill the xmm registers > "movq %6, %%rax\n\t" > > "movsd (%%rax), %%xmm0\n\t" > "movsd 8(%%rax), %%xmm1\n\t" > "movsd 16(%%rax), %%xmm2\n\t" > "movsd 24(%%rax), %%xmm3\n\t" > "movsd 32(%%rax), %%xmm4\n\t" > "movsd 40(%%rax), %%xmm5\n\t" > "movsd 48(%%rax), %%xmm6\n\t" > "movsd 56(%%rax), %%xmm7\n\t" > > // Fill the general purpose registers > "movq %5, %%rax\n\t" > > "movq (%%rax), %%rdi\n\t" > "movq 8(%%rax), %%rsi\n\t" > "movq 16(%%rax), %%rdx\n\t" > "movq 24(%%rax), %%rcx\n\t" > "movq 32(%%rax), %%r8\n\t" > "movq 40(%%rax), %%r9\n\t" > > // Perform the call > "movq %4, %%r11\n\t" > "movq %7, %%rax\n\t" > "call *%%r11\n\t" > > // Fill the return values > "movq %%rax, %0\n\t" > "movq %%rdx, %1\n\t" > "movsd %%xmm0, %2\n\t" > "movsd %%xmm1, %3\n\t" > : "=m" ( rax ), "=m" ( rdx ), "=m" ( xmm0 ), "=m" ( xmm1 ) > : "m" ( pMethod ), "m" ( pGPR ), "m" ( pFPR ), "m" ( nFPR ) > : "rax", "rdi", "rsi", "rdx", "rcx", "r8", "r9", "r11" > ); > > Semi-off-topic, I think this asm can be better done with only the > call inside the asm, and the rest handled by the compiler. > > { > register sal_uInt64 hard_r8 __asm__("rax"); // etc > register double hard_xmm0 __asm__("xmm0"); // etc > > hard_rdi = pGPR[0]; //etc > hard_xmm0 = pFPR[0]; //etc > hard_rax = nFPR; > > asm volatile ("call *%[method]" > : "+r"(hard_rax), //etc > "+x"(hard_xmm0), //etc > : "g" [method] (pMethod) > : "memory"); > > rax = hard_rax; > rdx = hard_rdx; > xmm0 = hard_xmm0; > xmm1 = hard_xmm1; > } > > > Of course, there's still the problem of getting the unwind data correct at > the point of the asm. I commented about that in the PR you filed. I think i386 still has the problem that it is small register class target and if you set rdi/rax and friends as hard registers, you risk reload failures. Do we prevent code motion of hard registers sets i.e. at GIMPLE level? (I know pre-reload scheduler was improved here, but I would not rely on it either). As soon as hard_rdi/hard_rax set is moved upwards or downwards across memset/division or other stuff requiring rax or rdx, reload will ICE. Honza > > > r~ ^ permalink raw reply [flat|nested] 22+ messages in thread
* Re: C++: Letting compiler know asm block can call function that can throw? 2012-03-29 17:16 ` Jan Hubicka @ 2012-03-29 18:34 ` Richard Henderson 2012-03-30 8:19 ` Richard Guenther 0 siblings, 1 reply; 22+ messages in thread From: Richard Henderson @ 2012-03-29 18:34 UTC (permalink / raw) To: Jan Hubicka; +Cc: Stephan Bergmann, gcc On 03/29/2012 01:16 PM, Jan Hubicka wrote: >> Of course, there's still the problem of getting the unwind data correct at >> the point of the asm. I commented about that in the PR you filed. > > I think i386 still has the problem that it is small register class target and if you > set rdi/rax and friends as hard registers, you risk reload failures. True, and if this were i386 code I would certainly recommend using the [acd] constraints instead (for suitible regparm signature). But this is explicitly x86_64 code and the compiler has 8 registers otherwise available. > Do we prevent code motion of hard registers sets i.e. at GIMPLE level? I don't know for positive, but I'd certainly consider it a bug if we don't. There are plenty of targets which have no alternative but to use this style of programming for inline syscalls. r~ ^ permalink raw reply [flat|nested] 22+ messages in thread
* Re: C++: Letting compiler know asm block can call function that can throw? 2012-03-29 18:34 ` Richard Henderson @ 2012-03-30 8:19 ` Richard Guenther 2012-03-30 12:21 ` Jan Hubicka 0 siblings, 1 reply; 22+ messages in thread From: Richard Guenther @ 2012-03-30 8:19 UTC (permalink / raw) To: Richard Henderson; +Cc: Jan Hubicka, Stephan Bergmann, gcc On Thu, Mar 29, 2012 at 8:34 PM, Richard Henderson <rth@redhat.com> wrote: > On 03/29/2012 01:16 PM, Jan Hubicka wrote: >>> Of course, there's still the problem of getting the unwind data correct at >>> the point of the asm. I commented about that in the PR you filed. >> >> I think i386 still has the problem that it is small register class target and if you >> set rdi/rax and friends as hard registers, you risk reload failures. > > True, and if this were i386 code I would certainly recommend using the [acd] > constraints instead (for suitible regparm signature). But this is explicitly > x86_64 code and the compiler has 8 registers otherwise available. > >> Do we prevent code motion of hard registers sets i.e. at GIMPLE level? Yes we do (modulo bugs). > I don't know for positive, but I'd certainly consider it a bug if we don't. > There are plenty of targets which have no alternative but to use this style > of programming for inline syscalls. > > > r~ ^ permalink raw reply [flat|nested] 22+ messages in thread
* Re: C++: Letting compiler know asm block can call function that can throw? 2012-03-30 8:19 ` Richard Guenther @ 2012-03-30 12:21 ` Jan Hubicka 2012-03-30 12:23 ` Richard Guenther 0 siblings, 1 reply; 22+ messages in thread From: Jan Hubicka @ 2012-03-30 12:21 UTC (permalink / raw) To: Richard Guenther; +Cc: Richard Henderson, Jan Hubicka, Stephan Bergmann, gcc > On Thu, Mar 29, 2012 at 8:34 PM, Richard Henderson <rth@redhat.com> wrote: > > On 03/29/2012 01:16 PM, Jan Hubicka wrote: > >>> Of course, there's still the problem of getting the unwind data correct at > >>> the point of the asm. Â I commented about that in the PR you filed. > >> > >> I think i386 still has the problem that it is small register class target and if you > >> set rdi/rax and friends as hard registers, you risk reload failures. > > > > True, and if this were i386 code I would certainly recommend using the [acd] > > constraints instead (for suitible regparm signature). Â But this is explicitly > > x86_64 code and the compiler has 8 registers otherwise available. Sure, still rdi/rax is the only option for some of instructions, so x86-64 doesn't really solve all the problems. > > > >> Do we prevent code motion of hard registers sets i.e. at GIMPLE level? > > Yes we do (modulo bugs). Good. Note that this also include transformations like frward substitution into area where hard register is live (i.e. it is not enough to just not touch hard registers as volatile, but one needs to prevent moving other code in). Honza > > > I don't know for positive, but I'd certainly consider it a bug if we don't. > > There are plenty of targets which have no alternative but to use this style > > of programming for inline syscalls. > > > > > > r~ ^ permalink raw reply [flat|nested] 22+ messages in thread
* Re: C++: Letting compiler know asm block can call function that can throw? 2012-03-30 12:21 ` Jan Hubicka @ 2012-03-30 12:23 ` Richard Guenther 2012-03-30 15:46 ` Jan Hubicka 0 siblings, 1 reply; 22+ messages in thread From: Richard Guenther @ 2012-03-30 12:23 UTC (permalink / raw) To: Jan Hubicka; +Cc: Richard Henderson, Stephan Bergmann, gcc 2012/3/30 Jan Hubicka <hubicka@ucw.cz>: >> On Thu, Mar 29, 2012 at 8:34 PM, Richard Henderson <rth@redhat.com> wrote: >> > On 03/29/2012 01:16 PM, Jan Hubicka wrote: >> >>> Of course, there's still the problem of getting the unwind data correct at >> >>> the point of the asm. I commented about that in the PR you filed. >> >> >> >> I think i386 still has the problem that it is small register class target and if you >> >> set rdi/rax and friends as hard registers, you risk reload failures. >> > >> > True, and if this were i386 code I would certainly recommend using the [acd] >> > constraints instead (for suitible regparm signature). But this is explicitly >> > x86_64 code and the compiler has 8 registers otherwise available. > > Sure, still rdi/rax is the only option for some of instructions, so x86-64 > doesn't really solve all the problems. >> > >> >> Do we prevent code motion of hard registers sets i.e. at GIMPLE level? >> >> Yes we do (modulo bugs). > > Good. Note that this also include transformations like frward substitution into > area where hard register is live (i.e. it is not enough to just not touch hard > registers as volatile, but one needs to prevent moving other code in). Motion across hardreg sets/uses are not restricted. And I would not expect an optimizing compiler to do that (it's your own fault to use hardregs in complex C code). Richard. ^ permalink raw reply [flat|nested] 22+ messages in thread
* Re: C++: Letting compiler know asm block can call function that can throw? 2012-03-30 12:23 ` Richard Guenther @ 2012-03-30 15:46 ` Jan Hubicka 2012-04-02 14:08 ` Michael Matz 0 siblings, 1 reply; 22+ messages in thread From: Jan Hubicka @ 2012-03-30 15:46 UTC (permalink / raw) To: Richard Guenther; +Cc: Jan Hubicka, Richard Henderson, Stephan Bergmann, gcc > > Motion across hardreg sets/uses are not restricted. And I would not expect > an optimizing compiler to do that (it's your own fault to use hardregs in > complex C code). Well, the syscall sequence is an example of somehting that should be inlined into arbitrary code w/o potential risk of ICEs. But I guess if things works in practice (as they seem), we don't need to worry much at the moment. Most of code movement we do is very simple. I don't see how to convince GCC to move memcpy or division into the middle of a basic block containing the libcall sequence.... Even when the basic block can be broken up with -fno-call-exceptions at the asm statement by an EH edge... Honza > > Richard. ^ permalink raw reply [flat|nested] 22+ messages in thread
* Re: C++: Letting compiler know asm block can call function that can throw? 2012-03-30 15:46 ` Jan Hubicka @ 2012-04-02 14:08 ` Michael Matz 2012-04-02 14:17 ` Jakub Jelinek 0 siblings, 1 reply; 22+ messages in thread From: Michael Matz @ 2012-04-02 14:08 UTC (permalink / raw) To: Jan Hubicka; +Cc: Richard Guenther, Richard Henderson, Stephan Bergmann, gcc Hi, On Fri, 30 Mar 2012, Jan Hubicka wrote: > > Motion across hardreg sets/uses are not restricted. And I would not expect > > an optimizing compiler to do that (it's your own fault to use hardregs in > > complex C code). > > Well, the syscall sequence is an example of somehting that should be > inlined into arbitrary code w/o potential risk of ICEs. The syscall sequence doesn't consist of multiple independend instructions, but rather is one asm with the right constraints. So gcc has no chance to move something between the register setup (which only is explicit after reload) and the syscall instruction. If syscall sequences were implemented like this: inline int syscall1(int number, long arg1) { register int ax __asm__("eax"); register long di __asm__("rdi"); ax = number; di = arg1; __asm__ volatile ("syscall"); } _then_ we would probably get miscompilations here and there. Ciao, Michael. ^ permalink raw reply [flat|nested] 22+ messages in thread
* Re: C++: Letting compiler know asm block can call function that can throw? 2012-04-02 14:08 ` Michael Matz @ 2012-04-02 14:17 ` Jakub Jelinek 2012-04-02 16:04 ` Michael Matz 0 siblings, 1 reply; 22+ messages in thread From: Jakub Jelinek @ 2012-04-02 14:17 UTC (permalink / raw) To: Michael Matz Cc: Jan Hubicka, Richard Guenther, Richard Henderson, Stephan Bergmann, gcc On Mon, Apr 02, 2012 at 04:07:59PM +0200, Michael Matz wrote: > On Fri, 30 Mar 2012, Jan Hubicka wrote: > > > > Motion across hardreg sets/uses are not restricted. And I would not expect > > > an optimizing compiler to do that (it's your own fault to use hardregs in > > > complex C code). > > > > Well, the syscall sequence is an example of somehting that should be > > inlined into arbitrary code w/o potential risk of ICEs. > > The syscall sequence doesn't consist of multiple independend instructions, > but rather is one asm with the right constraints. So gcc has no chance to > move something between the register setup (which only is explicit after > reload) and the syscall instruction. If syscall sequences were > implemented like this: > > inline int syscall1(int number, long arg1) { > register int ax __asm__("eax"); > register long di __asm__("rdi"); > ax = number; > di = arg1; > __asm__ volatile ("syscall"); > } > > _then_ we would probably get miscompilations here and there. That is actually what is used on most targets, including x86_64 (i?86 is an exception here, because it has single hard register constraints for most of the interesting registers). Jakub ^ permalink raw reply [flat|nested] 22+ messages in thread
* Re: C++: Letting compiler know asm block can call function that can throw? 2012-04-02 14:17 ` Jakub Jelinek @ 2012-04-02 16:04 ` Michael Matz 2012-04-16 20:01 ` Hans-Peter Nilsson 0 siblings, 1 reply; 22+ messages in thread From: Michael Matz @ 2012-04-02 16:04 UTC (permalink / raw) To: Jakub Jelinek Cc: Jan Hubicka, Richard Guenther, Richard Henderson, Stephan Bergmann, gcc Hi, On Mon, 2 Apr 2012, Jakub Jelinek wrote: > > inline int syscall1(int number, long arg1) { > > register int ax __asm__("eax"); > > register long di __asm__("rdi"); > > ax = number; > > di = arg1; > > __asm__ volatile ("syscall"); > > } > > > > _then_ we would probably get miscompilations here and there. > > That is actually what is used on most targets, including x86_64 Yikes! That's indeed the case. I'll want to retract what I said, concede with Honza that we're lucky and add that we're lucky mostly because register variables are not regarded as gimple registers, hence all stores to such variables are regarded as VDEFs. So there will be VDEF/VUSE chains between initializer and syscall, which prevents most code motion into that chain. That itself doesn't e.g. prevent the load/store disambiguator from disambiguating two such decls, even if they refer to the same hardreg. So we really are merely lucky, with enough effort we probably could create a "miscompiling" testcase. Ciao, Michael. ^ permalink raw reply [flat|nested] 22+ messages in thread
* Re: C++: Letting compiler know asm block can call function that can throw? 2012-04-02 16:04 ` Michael Matz @ 2012-04-16 20:01 ` Hans-Peter Nilsson 0 siblings, 0 replies; 22+ messages in thread From: Hans-Peter Nilsson @ 2012-04-16 20:01 UTC (permalink / raw) To: Michael Matz Cc: Jakub Jelinek, Jan Hubicka, Richard Guenther, Richard Henderson, Stephan Bergmann, gcc On Mon, 2 Apr 2012, Michael Matz wrote: > On Mon, 2 Apr 2012, Jakub Jelinek wrote: > > > > inline int syscall1(int number, long arg1) { > > > register int ax __asm__("eax"); > > > register long di __asm__("rdi"); > > > ax = number; > > > di = arg1; > > > __asm__ volatile ("syscall"); > > > } > > > > > > _then_ we would probably get miscompilations here and there. > > > > That is actually what is used on most targets, including x86_64 > > Yikes! That's indeed the case. I'll want to retract what I said, concede > with Honza that we're lucky and add that we're lucky mostly because > register variables are not regarded as gimple registers, hence all stores > to such variables are regarded as VDEFs. So there will be VDEF/VUSE > chains between initializer and syscall, which prevents most code motion > into that chain. That itself doesn't e.g. prevent the load/store > disambiguator from disambiguating two such decls, even if they refer to > the same hardreg. So we really are merely lucky, with enough effort we > probably could create a "miscompiling" testcase. Lucky perhaps, but documented lucky: this is documented (grep sysint extend.texi) to work, to avoid having talented gcc hackers saying "oh, that worked? You have to _stop doing that_; you've just been lucky in previous versions" rather that "oops, looks like I broke that; I'll fix it post-haste". (There's *one* test-case in gcc.target/cris/asmreg-1.c; this could certainly do with more coverage.) brgds, H-P ^ permalink raw reply [flat|nested] 22+ messages in thread
end of thread, other threads:[~2012-04-16 20:01 UTC | newest] Thread overview: 22+ messages (download: mbox.gz / follow: Atom feed) -- links below jump to the message on this page -- 2012-03-29 7:05 C++: Letting compiler know asm block can call function that can throw? Stephan Bergmann 2012-03-29 7:44 ` Jakub Jelinek 2012-03-29 8:48 ` Stephan Bergmann 2012-03-29 9:16 ` Richard Guenther 2012-03-29 12:51 ` Stephan Bergmann 2012-03-29 13:59 ` Michael Matz 2012-03-29 14:12 ` Andrew Haley 2012-03-29 15:10 ` Stephan Bergmann 2012-03-29 15:43 ` Michael Matz 2012-03-29 20:38 ` Eric Botcazou 2012-03-30 8:23 ` Richard Guenther 2012-03-29 16:14 ` Richard Henderson 2012-03-29 17:16 ` Jan Hubicka 2012-03-29 18:34 ` Richard Henderson 2012-03-30 8:19 ` Richard Guenther 2012-03-30 12:21 ` Jan Hubicka 2012-03-30 12:23 ` Richard Guenther 2012-03-30 15:46 ` Jan Hubicka 2012-04-02 14:08 ` Michael Matz 2012-04-02 14:17 ` Jakub Jelinek 2012-04-02 16:04 ` Michael Matz 2012-04-16 20:01 ` Hans-Peter Nilsson
This is a public inbox, see mirroring instructions for how to clone and mirror all data and code used for this inbox; as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).