On Apr 12, 2011, at 3:15 PM, Jim Grosbach wrote:> If you want an automated method, then using the source code re-writer interfaces in clang is probably a reasonable starting place. Just modifying the source code manually is probably easier, though, to be honest. > > As a moderate caveat to all of this, there are some bits of code out there that use these builtins that are very tightly coupled to the compiler (the Linux kernel used to do this, I think, and maybe still does). Those sorts of situations are unlikely to be solved satisfactorily by moving to library calls (performance reasons, usually). The appropriate solution there will be very situation specific and will likely involve refactoring the implementations in question to some degree.Are these intrinsics really prohibitively difficult to implement? I'm not suggesting that you (or anyone else) particularly needs to do them, but is there more to them than clobbering all registers and then lowering to a quick series of instructions which save/restore the current IP, SP, and (maybe?) FP? Something seems very wrong if rewriting a custom refactoring tool to turn builtin_setjmp/longjmp into library calls could possibly be simpler than just adding support for these intrinsics to one or two more targets. John.
It seems straightforward to implement, if it just needs to be functionally correct. I have another question about setjmp/longjmp. When the following program is compiled and run with argument 10 (./a.out 10), should it print 10 or 23? I am asking this question because it prints 23 when compiled with gcc and prints 10 when compiled with clang. If it is supposed to return 23, it seems to me that saving and clobbering registers is not enough to guarantee correctness of the compiled program. #include <stdio.h> #include <stdlib.h> #include <setjmp.h> jmp_buf buf; void __attribute__((noinline)) sub2 (void) { longjmp (buf, 1); } int main (int argc, char** argv) { int n = atoi(argv[1]), r; if ((r = setjmp (buf))) { printf("n = %d\n", n); return 0; } n += 13; sub2 (); return n; } On Tue, Apr 12, 2011 at 5:51 PM, John McCall <rjmccall at apple.com> wrote:> On Apr 12, 2011, at 3:15 PM, Jim Grosbach wrote: > > If you want an automated method, then using the source code re-writer > interfaces in clang is probably a reasonable starting place. Just modifying > the source code manually is probably easier, though, to be honest. > > > > As a moderate caveat to all of this, there are some bits of code out > there that use these builtins that are very tightly coupled to the compiler > (the Linux kernel used to do this, I think, and maybe still does). Those > sorts of situations are unlikely to be solved satisfactorily by moving to > library calls (performance reasons, usually). The appropriate solution there > will be very situation specific and will likely involve refactoring the > implementations in question to some degree. > > Are these intrinsics really prohibitively difficult to implement? I'm not > suggesting that you (or anyone else) particularly needs to do them, but is > there more to them than clobbering all registers and then lowering to a > quick series of instructions which save/restore the current IP, SP, and > (maybe?) FP? Something seems very wrong if rewriting a custom refactoring > tool to turn builtin_setjmp/longjmp into library calls could possibly be > simpler than just adding support for these intrinsics to one or two more > targets. > > John. >-------------- next part -------------- An HTML attachment was scrubbed... URL: <http://lists.llvm.org/pipermail/llvm-dev/attachments/20110413/59083db1/attachment.html>
After further investigation, I found that it prints 10 when it is compiled with gcc with option -O3. On Wed, Apr 13, 2011 at 9:51 AM, Akira Hatanaka <ahatanak at gmail.com> wrote:> It seems straightforward to implement, if it just needs to be functionally > correct. > > I have another question about setjmp/longjmp. When the following program is > compiled and run with argument 10 (./a.out 10), should it print 10 or 23? I > am asking this question because it prints 23 when compiled with gcc and > prints 10 when compiled with clang. If it is supposed to return 23, it seems > to me that saving and clobbering registers is not enough to guarantee > correctness of the compiled program. > > #include <stdio.h> > #include <stdlib.h> > #include <setjmp.h> > > jmp_buf buf; > > void __attribute__((noinline)) > sub2 (void) > { > > longjmp (buf, 1); > } > > int > main (int argc, char** argv) > { > int n = atoi(argv[1]), r; > > if ((r = setjmp (buf))) > { > printf("n = %d\n", n); > return 0; > } > > n += 13; > sub2 (); > > return n; > > } > > > On Tue, Apr 12, 2011 at 5:51 PM, John McCall <rjmccall at apple.com> wrote: > >> On Apr 12, 2011, at 3:15 PM, Jim Grosbach wrote: >> > If you want an automated method, then using the source code re-writer >> interfaces in clang is probably a reasonable starting place. Just modifying >> the source code manually is probably easier, though, to be honest. >> > >> > As a moderate caveat to all of this, there are some bits of code out >> there that use these builtins that are very tightly coupled to the compiler >> (the Linux kernel used to do this, I think, and maybe still does). Those >> sorts of situations are unlikely to be solved satisfactorily by moving to >> library calls (performance reasons, usually). The appropriate solution there >> will be very situation specific and will likely involve refactoring the >> implementations in question to some degree. >> >> Are these intrinsics really prohibitively difficult to implement? I'm not >> suggesting that you (or anyone else) particularly needs to do them, but is >> there more to them than clobbering all registers and then lowering to a >> quick series of instructions which save/restore the current IP, SP, and >> (maybe?) FP? Something seems very wrong if rewriting a custom refactoring >> tool to turn builtin_setjmp/longjmp into library calls could possibly be >> simpler than just adding support for these intrinsics to one or two more >> targets. >> >> John. >> > >-------------- next part -------------- An HTML attachment was scrubbed... URL: <http://lists.llvm.org/pipermail/llvm-dev/attachments/20110413/20f6601f/attachment.html>
On Apr 13, 2011, at 9:51 AM, Akira Hatanaka wrote:> int > main (int argc, char** argv) > { > int n = atoi(argv[1]), r; > > if ((r = setjmp (buf))) > { > printf("n = %d\n", n); > return 0; > }Non-volatile local variables are not preserved by setjmp(), so this program can print whatever it wants. /jakob
On Wed, Apr 13, 2011 at 9:51 AM, Akira Hatanaka <ahatanak at gmail.com> wrote:> It seems straightforward to implement, if it just needs to be functionally > correct. > > I have another question about setjmp/longjmp. When the following program is > compiled and run with argument 10 (./a.out 10), should it print 10 or 23? I > am asking this question because it prints 23 when compiled with gcc and > prints 10 when compiled with clang. If it is supposed to return 23, it seems > to me that saving and clobbering registers is not enough to guarantee > correctness of the compiled program. > > #include <stdio.h> > #include <stdlib.h> > #include <setjmp.h> > > jmp_buf buf; > > void __attribute__((noinline)) > sub2 (void) > { > longjmp (buf, 1); > } > > int > main (int argc, char** argv) > { > int n = atoi(argv[1]), r; > > if ((r = setjmp (buf))) > { > printf("n = %d\n", n); > return 0; > } > > n += 13; > sub2 (); > > return n; > }Neither output is wrong. C99 7.13.2.1p3: All accessible objects have values, and all other components of the abstract machine212) have state, as of the time the longjmp function was called, except that the values of objects of automatic storage duration that are local to the function containing the invocation of the corresponding setjmp macro that do not have volatile-qualified type and have been changed between the setjmp invocation and longjmp call are indeterminate. -Eli