digitalmars.D - Use C++ exception model in D
- Jacob Carlborg (13/13) Apr 07 2014 How feasible would it be if D moved to using the same exception model as...
- Iain Buclaw (5/15) Apr 08 2014 We use libunwind, which is the same as what the C++ exception model
- Jacob Carlborg (5/9) Apr 08 2014 Is there a reason to not use the same model, or what's required to be
- Iain Buclaw (7/14) Apr 08 2014 Yes, D exceptions are not packed in the same way as C++. Go and Java
- Jacob Carlborg (5/8) Apr 08 2014 I do understand that they are different, but why design them like that
- David Nadlinger (29/31) Apr 08 2014 In short, the reason not to use the same "model" (you could argue
- Brad Roberts (7/28) Apr 08 2014 I think, for a mixed language application, that the important part is pr...
- David Nadlinger (23/31) Apr 08 2014 I haven't actually tried to do this, but in theory, this should
- Brad Roberts (5/26) Apr 08 2014 Most of the areas where DMD is 'odd' are a case of "I can't figure out t...
- David Nadlinger (18/24) Apr 09 2014 The problem is that there are only very few people who are
- Daniel Murphy (4/9) Apr 09 2014 You could always go the other way and change GDC and LDC to match what D...
- Marco Leise (15/26) Apr 09 2014 a=20
- Iain Buclaw (10/30) Apr 09 2014 It *does* pose trouble. I've just never pointed it out before because
- Marco Leise (16/34) Apr 09 2014 That slipped my mind, possibly because I still think of D as
- Iain Buclaw (17/44) Apr 08 2014 Worse, there's even work that is complete for GDC that is critical for
- David Nadlinger (3/9) Apr 09 2014 What are you referring to here specifically?
- Iain Buclaw (2/8) Apr 09 2014 LTR side effects on array ops. :o)
- Iain Buclaw (2/55) Apr 08 2014 Hopefully I've convinced Daniel to fix the va_args at least.
- Dan Olson (9/20) Apr 09 2014 I tried handling foreign exceptions back in Feb with the sjlj
- Jacob Carlborg (23/50) Apr 09 2014 A middle ground would help. In the D/Objective-C implementation there is...
- David Nadlinger (4/12) Apr 09 2014 So, in the last paragraph, you are specifically referring to DMD
- Jacob Carlborg (9/10) Apr 09 2014 x86_64 yes, not necessarily only for DMD. I thought if DMD, LDC and GDC
- David Nadlinger (9/14) Apr 09 2014 They don't. GDC and LDC use libunwind, whereas DMD uses its own
- Jacob Carlborg (5/11) Apr 09 2014 That's what I was hoping.
- Michel Fortin (30/44) Apr 09 2014 Maybe the right course of action would be to just ignore Objective-C
- Marco Leise (7/9) Apr 09 2014 Is libunwind somehow copied verbatim in the GDC/LDC sources?
- David Nadlinger (4/11) Apr 09 2014 The implementation is part of the runtime libraries shipped by
-
Iain Buclaw
(3/17)
Apr 09 2014
Just look for something like /usr/lib/gcc/
/ /include if - deadalnix (4/19) Apr 09 2014 The C++ personality function from GCC does not catch, but do the
- Jacob Carlborg (12/14) Apr 10 2014 As far as I understand the cleaning is only a part of what personality
- deadalnix (8/24) Apr 10 2014 You want to look at libstdc++-v3/libsupc++/eh_personality.cc in
- Jacob Carlborg (5/11) Apr 10 2014 Why is the filter part irrelevant?
- deadalnix (3/4) Apr 12 2014 filter is "catch everything but.." kind of clause. The semantic
- Iain Buclaw (3/40) Apr 09 2014 The "middle-ground" would be us handling Objective-C foreign
- Jacob Carlborg (4/6) Apr 09 2014 Yes, exactly.
How feasible would it be if D moved to using the same exception model as C++? The advantage of this would be that D exceptions would become compatible with C++ exceptions. It would also mean that D exceptions would become compatible with Objective-C exceptions on OS X 64bit, since they use the same exception model as C++. I'm not sure, but if GDC and LDC already use the C++ exception model it would probably make their lives easier as well. The disadvantages are that someone needs to implement it. I'm not sure, but it may also break existing code. Note, I'm mostly interested in Posix 64bit. -- /Jacob Carlborg
Apr 07 2014
On 8 April 2014 07:36, Jacob Carlborg <doob me.com> wrote:How feasible would it be if D moved to using the same exception model as C++? The advantage of this would be that D exceptions would become compatible with C++ exceptions. It would also mean that D exceptions would become compatible with Objective-C exceptions on OS X 64bit, since they use the same exception model as C++. I'm not sure, but if GDC and LDC already use the C++ exception model it would probably make their lives easier as well. The disadvantages are that someone needs to implement it. I'm not sure, but it may also break existing code. Note, I'm mostly interested in Posix 64bit.We use libunwind, which is the same as what the C++ exception model uses, but we implement our own EH routines on-top of that to handle D exceptions specifically. This is typically what all gcc languages with EH do.
Apr 08 2014
On 08/04/14 09:51, Iain Buclaw wrote:We use libunwind, which is the same as what the C++ exception model uses, but we implement our own EH routines on-top of that to handle D exceptions specifically. This is typically what all gcc languages with EH do.Is there a reason to not use the same model, or what's required to be compatible? -- /Jacob Carlborg
Apr 08 2014
On 8 April 2014 11:08, Jacob Carlborg <doob me.com> wrote:On 08/04/14 09:51, Iain Buclaw wrote:Yes, D exceptions are not packed in the same way as C++. Go and Java also have subtly different ways of passing language-specific data to libunwind. The closest language D is to is Java, in that they both put in the Object being thrown immediately before the generic libunwind exception header. That's where the similarities end. :)We use libunwind, which is the same as what the C++ exception model uses, but we implement our own EH routines on-top of that to handle D exceptions specifically. This is typically what all gcc languages with EH do.Is there a reason to not use the same model, or what's required to be compatible?
Apr 08 2014
On 08/04/14 12:19, Iain Buclaw wrote:Yes, D exceptions are not packed in the same way as C++. Go and Java also have subtly different ways of passing language-specific data to libunwind.I do understand that they are different, but why design them like that from the beginning? -- /Jacob Carlborg
Apr 08 2014
On Tuesday, 8 April 2014 at 10:08:24 UTC, Jacob Carlborg wrote:Is there a reason to not use the same model, or what's required to be compatible?In short, the reason not to use the same "model" (you could argue that the model is the same, as only the personality functions differ) is that the exception unwinder is intimately tied to both the target language ABI and semantics. For example, all unwinders need to handle the run-time type information for the exception object to correctly dispatch it. And while e.g. the GNU C++ unwinding implementation needs to pull shenanigans to implement the crazy C++ exception lifetime model (cf. catching by reference vs. by value) and enforce throws(...) specifications, the D unwinder needs to understand the difference between Exception and Error and correctly implement exception chaining. Now, of course, it is possible to find a middle ground that works as a basis for virtually all languages. In fact, I'd argue that SEH for Windows actually provides such a layer, and libunwind does too. For example, a proper implementation of a libunwind personality function allows you to check whether a given exception originated in your own language, and just pass it on otherwise (such that e.g. C++ exception just bubble through a layer of D code). In theory, it would e.g. also be possible to wrap foreign exceptions in e.g. D Throwable objects to make them catchable in D code. But the lifetime of the foreign object is virtually impossible to get right in the general case, and the benefits of wrapping exceptions like this have turned out not to be worth it, because it is hard to handle them in a sensible way in the receiving language (DMD actually does – did? – something like this on Win32). David
Apr 08 2014
On 4/8/14, 5:03 AM, David Nadlinger wrote:On Tuesday, 8 April 2014 at 10:08:24 UTC, Jacob Carlborg wrote:I think, for a mixed language application, that the important part is proper object lifetime management more than being able to catch exceptions from different languages. When unwinding a c++ exception that has stack frames intermixed with D, destructors need to be executed appropriately, and vice versa. This is also an important part of having abi compatibility between D compilers, something which we don't have today but really must have eventually.. hopefully not years away.Is there a reason to not use the same model, or what's required to be compatible?In short, the reason not to use the same "model" (you could argue that the model is the same, as only the personality functions differ) is that the exception unwinder is intimately tied to both the target language ABI and semantics. For example, all unwinders need to handle the run-time type information for the exception object to correctly dispatch it. And while e.g. the GNU C++ unwinding implementation needs to pull shenanigans to implement the crazy C++ exception lifetime model (cf. catching by reference vs. by value) and enforce throws(...) specifications, the D unwinder needs to understand the difference between Exception and Error and correctly implement exception chaining. Now, of course, it is possible to find a middle ground that works as a basis for virtually all languages. In fact, I'd argue that SEH for Windows actually provides such a layer, and libunwind does too. For example, a proper implementation of a libunwind personality function allows you to check whether a given exception originated in your own language, and just pass it on otherwise (such that e.g. C++ exception just bubble through a layer of D code). In theory, it would e.g. also be possible to wrap foreign exceptions in e.g. D Throwable objects to make them catchable in D code. But the lifetime of the foreign object is virtually impossible to get right in the general case, and the benefits of wrapping exceptions like this have turned out not to be worth it, because it is hard to handle them in a sensible way in the receiving language (DMD actually does – did? – something like this on Win32). David
Apr 08 2014
On Tuesday, 8 April 2014 at 18:55:35 UTC, Brad Roberts wrote:I think, for a mixed language application, that the important part is proper object lifetime management more than being able to catch exceptions from different languages. When unwinding a c++ exception that has stack frames intermixed with D, destructors need to be executed appropriately, and vice versa.I haven't actually tried to do this, but in theory, this should be the easy part with libunwind. You just ignore foreign exceptions during the search phase (i.e. not catch them), and during the unwind phase, your own personality function is called again for cleanup regardless of the handler the stack actually unwinds to.This is also an important part of having abi compatibility between D compilers, something which we don't have today but really must have eventually.. hopefully not years away.This really depends on somebody familiar with the DMD backend committing to going through with it. I think both on the GDC and LDC sides, there is agreement that we need to work on a common ABI. However, the whole thing would be somewhat of a futile effort without DMD on board as well. On x86_64, ABI compatibility is not an unreasonable goal at all (and a very important one, in my opinion). There are some areas that will need a lot of careful spec'ing and likely entail changes in all three compilers, such as the construction of nested scopes. However, in some cases, e.g. exception unwinding, or proper variadic arguments, it's definitely the case that GDC and LDC would be easy to align, whereas DMD would have to give up its own bespoke solution. Does DMD still do things like magically accessing the scope of the parent function in in/out contract calls? David
Apr 08 2014
On 4/8/14, 12:56 PM, David Nadlinger wrote:On Tuesday, 8 April 2014 at 18:55:35 UTC, Brad Roberts wrote:Most of the areas where DMD is 'odd' are a case of "I can't figure out the right way, so any way is better than no way". That's particularly true for var args and eh. I'm confident that pulls that fix these issues can and will be accepted. I'm less confident that someone will volunteer to fix it, but it's something I care about.I think, for a mixed language application, that the important part is proper object lifetime management more than being able to catch exceptions from different languages. When unwinding a c++ exception that has stack frames intermixed with D, destructors need to be executed appropriately, and vice versa.I haven't actually tried to do this, but in theory, this should be the easy part with libunwind. You just ignore foreign exceptions during the search phase (i.e. not catch them), and during the unwind phase, your own personality function is called again for cleanup regardless of the handler the stack actually unwinds to.This is also an important part of having abi compatibility between D compilers, something which we don't have today but really must have eventually.. hopefully not years away.This really depends on somebody familiar with the DMD backend committing to going through with it. I think both on the GDC and LDC sides, there is agreement that we need to work on a common ABI. However, the whole thing would be somewhat of a futile effort without DMD on board as well. On x86_64, ABI compatibility is not an unreasonable goal at all (and a very important one, in my opinion). There are some areas that will need a lot of careful spec'ing and likely entail changes in all three compilers, such as the construction of nested scopes. However, in some cases, e.g. exception unwinding, or proper variadic arguments, it's definitely the case that GDC and LDC would be easy to align, whereas DMD would have to give up its own bespoke solution. Does DMD still do things like magically accessing the scope of the parent function in in/out contract calls? David
Apr 08 2014
On Tuesday, 8 April 2014 at 20:07:09 UTC, Brad Roberts wrote:Most of the areas where DMD is 'odd' are a case of "I can't figure out the right way, so any way is better than no way". That's particularly true for var args and eh. I'm confident that pulls that fix these issues can and will be accepted. I'm less confident that someone will volunteer to fix it, but it's something I care about.The problem is that there are only very few people who are familiar enough with the DMD backend to work on such changes. And quite understandably so – to be quite honest, I myself am not particularly interested in spending a nontrivial amount of time to get acquainted with a dated, sparsely documented codebase that I will not be able to use in other projects. It certainly is an interesting piece of software and getting acquainted with its internals is probably a nice intellectual exercise, but so far, most people interested in tackling the ABI situation are already busy with another backend. Sure, one way to go about this would be to just sit down and implement a common ABI in GDC and LDC (hackathon at London/Zürich/… anyone?) and then hope that some random contributor turns up later on and fixes DMD to conform to the standard we agreed on. But this does not necessarily strike me as a productive gamble… David
Apr 09 2014
"David Nadlinger" wrote in message news:bivyxqzewidjylastzbs forum.dlang.org...Sure, one way to go about this would be to just sit down and implement a common ABI in GDC and LDC (hackathon at London/Zürich/… anyone?) and then hope that some random contributor turns up later on and fixes DMD to conform to the standard we agreed on. But this does not necessarily strike me as a productive gamble…You could always go the other way and change GDC and LDC to match what DMD does. :)
Apr 09 2014
Am Wed, 9 Apr 2014 23:11:08 +1000 schrieb "Daniel Murphy" <yebbliesnospam gmail.com>:"David Nadlinger" wrote in message=20 news:bivyxqzewidjylastzbs forum.dlang.org... =20a=20Sure, one way to go about this would be to just sit down and implement =yone?) and then=20common ABI in GDC and LDC (hackathon at London/Z=C3=BCrich/=E2=80=A6 an=ike=20hope that some random contributor turns up later on and fixes DMD to=20 conform to the standard we agreed on. But this does not necessarily str=D=20me as a productive gamble=E2=80=A6=20 You could always go the other way and change GDC and LDC to match what DM=does. :)=20And precisely that is not always possible. E.g. GCC developers have decided against "naked" asm functions. And this out-contract-accessing-caller-scope thing that David mentioned looks like it could pose trouble with LLVM and/or GCC. A common ground has to be found that likely changes the ABI in all 3 compilers. DMD is actually least restricted by the lack of vetoing "upstream" developers :) --=20 Marco
Apr 09 2014
On 9 April 2014 14:54, Marco Leise <Marco.Leise gmx.de> wrote:Am Wed, 9 Apr 2014 23:11:08 +1000 schrieb "Daniel Murphy" <yebbliesnospam gmail.com>:Naked exists, just not for x86. :o)"David Nadlinger" wrote in message news:bivyxqzewidjylastzbs forum.dlang.org...And precisely that is not always possible. E.g. GCC developers have decided against "naked" asm functions. And thisSure, one way to go about this would be to just sit down and implement a common ABI in GDC and LDC (hackathon at London/Zürich/... anyone?) and then hope that some random contributor turns up later on and fixes DMD to conform to the standard we agreed on. But this does not necessarily strike me as a productive gamble...You could always go the other way and change GDC and LDC to match what DMD does. :)out-contract-accessing-caller-scope thing that David mentioned looks like it could pose trouble with LLVM and/or GCC.It *does* pose trouble. I've just never pointed it out before because GDC builds the stack frame in the front-end (the middle end never got it right anyway because of delegates). The one thing we *do* rely on is that the D front-end marks all closure vars correctly, even if a closure is not required for the function.A common ground has to be found that likely changes the ABI in all 3 compilers. DMD is actually least restricted by the lack of vetoing "upstream" developers :)I have only vetoed features that are tied to a specific architecture. This is not unreasonable in my eyes.
Apr 09 2014
Am Wed, 9 Apr 2014 15:32:56 +0100 schrieb Iain Buclaw <ibuclaw gdcproject.org>:On 9 April 2014 14:54, Marco Leise <Marco.Leise gmx.de> wrote:That slipped my mind, possibly because I still think of D as a programming language for x86 (like Delphi).Am Wed, 9 Apr 2014 23:11:08 +1000 schrieb "Daniel Murphy" <yebbliesnospam gmail.com>:Naked exists, just not for x86. :o)You could always go the other way and change GDC and LDC to match what DMD does. :)And precisely that is not always possible. E.g. GCC developers have decided against "naked" asm functions. And thisI meant upstream more literally than I made it look. I.e. even if everyone involved with D found some ABI detail a good idea, it could be that the required changes to the backend, like naked asm for x86 cannot be made by you or David, but require the good will of the core team of the respective backend. And yes, it is good to now and then look beyond x86. The developments were in favour of D it seems. 16-bit chips dimish, TLS became available on Mac OS X. Possibly later Walter's "better C" will be discussed again to not overload simple platforms with GC, exceptions and TLS :) -- MarcoA common ground has to be found that likely changes the ABI in all 3 compilers. DMD is actually least restricted by the lack of vetoing "upstream" developers :)I have only vetoed features that are tied to a specific architecture. This is not unreasonable in my eyes.
Apr 09 2014
On 8 April 2014 20:56, David Nadlinger <code klickverbot.at> wrote:On Tuesday, 8 April 2014 at 18:55:35 UTC, Brad Roberts wrote:Worse, there's even work that is complete for GDC that is critical for ARM support, but breaks ABI - in a positive way that means all targets behave as expected. However DMD is impeding progress of this work. The work I'm doing on GDB is somewhat similar in this regards in that what I initially thought would be a walk in the park for GDC turned out to be an almost re-think/write of the situation. How you emit modules (we didn't), how you emit imported modules, selective imports, renamed imports, enums, methods, vtable layouts in debug, classifying structs, locations, locations, locations, special cases for _Dmain, symbol scope lookup hierachy, function overloading... Most of which DMD programs may not see all benefits of because they emit debug info as if is C.I think, for a mixed language application, that the important part is proper object lifetime management more than being able to catch exceptions from different languages. When unwinding a c++ exception that has stack frames intermixed with D, destructors need to be executed appropriately, and vice versa.I haven't actually tried to do this, but in theory, this should be the easy part with libunwind. You just ignore foreign exceptions during the search phase (i.e. not catch them), and during the unwind phase, your own personality function is called again for cleanup regardless of the handler the stack actually unwinds to.This is also an important part of having abi compatibility between D compilers, something which we don't have today but really must have eventually.. hopefully not years away.This really depends on somebody familiar with the DMD backend committing to going through with it. I think both on the GDC and LDC sides, there is agreement that we need to work on a common ABI. However, the whole thing would be somewhat of a futile effort without DMD on board as well.On x86_64, ABI compatibility is not an unreasonable goal at all (and a very important one, in my opinion). There are some areas that will need a lot of careful spec'ing and likely entail changes in all three compilers, such as the construction of nested scopes. However, in some cases, e.g. exception unwinding, or proper variadic arguments, it's definitely the case that GDC and LDC would be easy to align, whereas DMD would have to give up its own bespoke solution. Does DMD still do things like magically accessing the scope of the parent function in in/out contract calls?That magic is still there as I recall that the hacks for GDC custom static chains are still in place. Regards Iain
Apr 08 2014
On Tuesday, 8 April 2014 at 22:19:06 UTC, Iain Buclaw wrote:Worse, there's even work that is complete for GDC that is critical for ARM support, but breaks ABI - in a positive way that means all targets behave as expected. However DMD is impeding progress of this work.What are you referring to here specifically? David
Apr 09 2014
On 9 April 2014 09:23, David Nadlinger <code klickverbot.at> wrote:On Tuesday, 8 April 2014 at 22:19:06 UTC, Iain Buclaw wrote:LTR side effects on array ops. :o)Worse, there's even work that is complete for GDC that is critical for ARM support, but breaks ABI - in a positive way that means all targets behave as expected. However DMD is impeding progress of this work.What are you referring to here specifically?
Apr 09 2014
On 8 April 2014 21:06, Brad Roberts <braddr puremagic.com> wrote:On 4/8/14, 12:56 PM, David Nadlinger wrote:Hopefully I've convinced Daniel to fix the va_args at least.On Tuesday, 8 April 2014 at 18:55:35 UTC, Brad Roberts wrote:Most of the areas where DMD is 'odd' are a case of "I can't figure out the right way, so any way is better than no way". That's particularly true for var args and eh. I'm confident that pulls that fix these issues can and will be accepted. I'm less confident that someone will volunteer to fix it, but it's something I care about.I think, for a mixed language application, that the important part is proper object lifetime management more than being able to catch exceptions from different languages. When unwinding a c++ exception that has stack frames intermixed with D, destructors need to be executed appropriately, and vice versa.I haven't actually tried to do this, but in theory, this should be the easy part with libunwind. You just ignore foreign exceptions during the search phase (i.e. not catch them), and during the unwind phase, your own personality function is called again for cleanup regardless of the handler the stack actually unwinds to.This is also an important part of having abi compatibility between D compilers, something which we don't have today but really must have eventually.. hopefully not years away.This really depends on somebody familiar with the DMD backend committing to going through with it. I think both on the GDC and LDC sides, there is agreement that we need to work on a common ABI. However, the whole thing would be somewhat of a futile effort without DMD on board as well. On x86_64, ABI compatibility is not an unreasonable goal at all (and a very important one, in my opinion). There are some areas that will need a lot of careful spec'ing and likely entail changes in all three compilers, such as the construction of nested scopes. However, in some cases, e.g. exception unwinding, or proper variadic arguments, it's definitely the case that GDC and LDC would be easy to align, whereas DMD would have to give up its own bespoke solution. Does DMD still do things like magically accessing the scope of the parent function in in/out contract calls? David
Apr 08 2014
"David Nadlinger" <code klickverbot.at> writes:On Tuesday, 8 April 2014 at 18:55:35 UTC, Brad Roberts wrote:I tried handling foreign exceptions back in Feb with the sjlj personality function I am using in LDC for iOS. Well, at least doing cleanups so that a objc/c++ exception could bubble up and D could call dtors and finally blocks. It was mostly working but I wanted to make progress on other stuff so shelved it since I had normal D sjlj eh working. -- DanI think, for a mixed language application, that the important part is proper object lifetime management more than being able to catch exceptions from different languages. When unwinding a c++ exception that has stack frames intermixed with D, destructors need to be executed appropriately, and vice versa.I haven't actually tried to do this, but in theory, this should be the easy part with libunwind. You just ignore foreign exceptions during the search phase (i.e. not catch them), and during the unwind phase, your own personality function is called again for cleanup regardless of the handler the stack actually unwinds to.
Apr 09 2014
On 08/04/14 14:03, David Nadlinger wrote:On Tuesday, 8 April 2014 at 10:08:24 UTC, Jacob Carlborg wrote:A middle ground would help. In the D/Objective-C implementation there is already an exception bridge for 32bit. The 32bit implementation uses setjmp and longjmp. For transferring D exceptions to Objective-C the compiler sets up a try-catch. Then there's a subclass of NSException (the root exception class in Objective-C) which wraps a D Throwable. This NSException is then thrown using the Objective-C runtime function for throwing exceptions. For transferring exceptions in the other direction bascilly the same thing happens. The compiler uses setjmp and longjmp to catch the Objective-C exception. This is then wrapped as a D exception, a subclass of Throwable, and thrown using the D runtime function for throwing exceptions. For 64bit, Objective-C uses the same exception handling as C++. So I need to somehow be able to catch Objective-C exceptions and Objective-C need to be able to catch D exceptions. Although I still expect to need to wrap the exceptions, since D code won't be expecting to catch instances of NSException, which doesn't inherit from Throwable. Same on the Objective-C side. If D would use the C++ exception handling model I hope that the implementation would be a lot simpler. -- /Jacob CarlborgIs there a reason to not use the same model, or what's required to be compatible?In short, the reason not to use the same "model" (you could argue that the model is the same, as only the personality functions differ) is that the exception unwinder is intimately tied to both the target language ABI and semantics. For example, all unwinders need to handle the run-time type information for the exception object to correctly dispatch it. And while e.g. the GNU C++ unwinding implementation needs to pull shenanigans to implement the crazy C++ exception lifetime model (cf. catching by reference vs. by value) and enforce throws(...) specifications, the D unwinder needs to understand the difference between Exception and Error and correctly implement exception chaining. Now, of course, it is possible to find a middle ground that works as a basis for virtually all languages. In fact, I'd argue that SEH for Windows actually provides such a layer, and libunwind does too. For example, a proper implementation of a libunwind personality function allows you to check whether a given exception originated in your own language, and just pass it on otherwise (such that e.g. C++ exception just bubble through a layer of D code). In theory, it would e.g. also be possible to wrap foreign exceptions in e.g. D Throwable objects to make them catchable in D code. But the lifetime of the foreign object is virtually impossible to get right in the general case, and the benefits of wrapping exceptions like this have turned out not to be worth it, because it is hard to handle them in a sensible way in the receiving language (DMD actually does – did? – something like this on Win32).
Apr 09 2014
On Wednesday, 9 April 2014 at 07:19:54 UTC, Jacob Carlborg wrote:For 64bit, Objective-C uses the same exception handling as C++. So I need to somehow be able to catch Objective-C exceptions and Objective-C need to be able to catch D exceptions. Although I still expect to need to wrap the exceptions, since D code won't be expecting to catch instances of NSException, which doesn't inherit from Throwable. Same on the Objective-C side. If D would use the C++ exception handling model I hope that the implementation would be a lot simpler.So, in the last paragraph, you are specifically referring to DMD on x86_64? David
Apr 09 2014
On 2014-04-09 10:27, David Nadlinger wrote:So, in the last paragraph, you are specifically referring to DMD on x86_64?x86_64 yes, not necessarily only for DMD. I thought if DMD, LDC and GDC all used the same exception handling model and the same as C++ it would be easier. Especially for implementing support for Objective-C exceptions, which is why initially started this thread. I don't know which exception model iOS 64bit uses for Objective-C. If it uses the C++ exception model it would apply for that platform as well. -- /Jacob Carlborg
Apr 09 2014
On Wednesday, 9 April 2014 at 16:48:54 UTC, Jacob Carlborg wrote:x86_64 yes, not necessarily only for DMD. I thought if DMD, LDC and GDC all used the same exception handling model and the same as C++ it would be easier. Especially for implementing support for Objective-C exceptions, which is why initially started this thread.They don't. GDC and LDC use libunwind, whereas DMD uses its own custom EH implementation. With GDC and LDC, you'd just need to add your code to handle Objective-C exceptions to the personality functions. libunwind exceptions have a "type"/"source language" field, and by default most implementations either ignore unknown exception types or abort on encountering them. David
Apr 09 2014
On 2014-04-09 19:27, David Nadlinger wrote:They don't. GDC and LDC use libunwind, whereas DMD uses its own custom EH implementation.That's what I want then, for all implementations to use libunwind.With GDC and LDC, you'd just need to add your code to handle Objective-C exceptions to the personality functions. libunwind exceptions have a "type"/"source language" field, and by default most implementations either ignore unknown exception types or abort on encountering them.That's what I was hoping. -- /Jacob Carlborg
Apr 09 2014
On 2014-04-09 17:27:55 +0000, "David Nadlinger" <code klickverbot.at> said:On Wednesday, 9 April 2014 at 16:48:54 UTC, Jacob Carlborg wrote:Maybe the right course of action would be to just ignore Objective-C exceptions in 64-bit DMD and finish the rest of D/Objective-C. The day D/Objective-C is ported to GDC and LDC, it should be much easier to make exceptions work there. The funny thing is that within Cocoa exceptions are usually reserved for logic errors (array out of bound, method calls with unknown selector, assertion errors, etc.). That's the kind of error we consider unrecoverable when they happen in D code. So I think people can manage without Objective-C exceptions for some time. Given what I wrote above, I'll also argue that it's not a wise move to support exceptions in D/Objective-C with the legacy runtime even though I implemented it. Because the legacy runtime uses setjmp/longjmp for exceptions, try blocks in a function that calls extern(Objective-C) functions are costly. And the compiler has to implicitly add those costly try blocks to wrap/unwrap exception objects to prevent unwinding of the wrong kind from leaving the current function. It was fun to implement, but it's also the most intrusive changes D/Objective-C makes to the frontend, and a big parts of the additions to druntime. If we plan to support mixed unwind mechanisms some day it might be useful to keep, because the logic for bridging between two or more unwinding systems is all there. Otherwise I'd probably scrap the whole exception wrapping/unwrapping thing. I doubt the performance cost is worth it, and I doubt the maintenance cost for the additional complexity is worth it. The legacy Objective-C runtime is mostly gone from Apple's ecosystem anyway. -- Michel Fortin michel.fortin michelf.ca http://michelf.cax86_64 yes, not necessarily only for DMD. I thought if DMD, LDC and GDC all used the same exception handling model and the same as C++ it would be easier. Especially for implementing support for Objective-C exceptions, which is why initially started this thread.They don't. GDC and LDC use libunwind, whereas DMD uses its own custom EH implementation. With GDC and LDC, you'd just need to add your code to handle Objective-C exceptions to the personality functions. libunwind exceptions have a "type"/"source language" field, and by default most implementations either ignore unknown exception types or abort on encountering them.
Apr 09 2014
Am Wed, 09 Apr 2014 17:27:55 +0000 schrieb "David Nadlinger" <code klickverbot.at>:They don't. GDC and LDC use libunwind, whereas DMD uses its own custom EH implementation.Is libunwind somehow copied verbatim in the GDC/LDC sources? Because I'm pretty sure I only installed it 2 weeks ago when some benchmark tool from Google asked me to install it. -- Marco
Apr 09 2014
On Wednesday, 9 April 2014 at 21:19:46 UTC, Marco Leise wrote:Am Wed, 09 Apr 2014 17:27:55 +0000 schrieb "David Nadlinger" <code klickverbot.at>:The implementation is part of the runtime libraries shipped by GCC (and installed by default on every system). DavidThey don't. GDC and LDC use libunwind, whereas DMD uses its own custom EH implementation.Is libunwind somehow copied verbatim in the GDC/LDC sources? Because I'm pretty sure I only installed it 2 weeks ago when some benchmark tool from Google asked me to install it.
Apr 09 2014
On 9 April 2014 23:55, David Nadlinger <code klickverbot.at> wrote:On Wednesday, 9 April 2014 at 21:19:46 UTC, Marco Leise wrote:Just look for something like /usr/lib/gcc/<xxx>/<x.x>/include if you've installed the libgcc-dev files.Am Wed, 09 Apr 2014 17:27:55 +0000 schrieb "David Nadlinger" <code klickverbot.at>:The implementation is part of the runtime libraries shipped by GCC (and installed by default on every system).They don't. GDC and LDC use libunwind, whereas DMD uses its own custom EH implementation.Is libunwind somehow copied verbatim in the GDC/LDC sources? Because I'm pretty sure I only installed it 2 weeks ago when some benchmark tool from Google asked me to install it.
Apr 09 2014
On Wednesday, 9 April 2014 at 17:27:56 UTC, David Nadlinger wrote:On Wednesday, 9 April 2014 at 16:48:54 UTC, Jacob Carlborg wrote:The C++ personality function from GCC does not catch, but do the cleanup on foreign exceptions. That sound like the right behavior to me.x86_64 yes, not necessarily only for DMD. I thought if DMD, LDC and GDC all used the same exception handling model and the same as C++ it would be easier. Especially for implementing support for Objective-C exceptions, which is why initially started this thread.They don't. GDC and LDC use libunwind, whereas DMD uses its own custom EH implementation. With GDC and LDC, you'd just need to add your code to handle Objective-C exceptions to the personality functions. libunwind exceptions have a "type"/"source language" field, and by default most implementations either ignore unknown exception types or abort on encountering them. David
Apr 09 2014
On 2014-04-10 08:53, deadalnix wrote:The C++ personality function from GCC does not catch, but do the cleanup on foreign exceptions. That sound like the right behavior to me.As far as I understand the cleaning is only a part of what personality function does. The first thing it does is check if the thrown exception can be handled. Like determine if it's a C++ exception or some other exception. If I recall correctly, it also determines if and where to resume unwinding, where to find catch blocks and so on. This [1] series of blog posts gives a pretty good understanding of how C++ exceptions work under the hood, for those that don't want to read the ABI documentation. [1] http://monoinfinito.wordpress.com/series/exception-handling-in-c/ -- /Jacob Carlborg
Apr 10 2014
On Thursday, 10 April 2014 at 19:23:12 UTC, Jacob Carlborg wrote:On 2014-04-10 08:53, deadalnix wrote:You want to look at libstdc++-v3/libsupc++/eh_personality.cc in gcc's source code. The personality function test if the exception is a C++ exception, in which case the regular flow apply. If not, the foreign_exception flag is set, and some behavior are altered. Basically, for what we are concerned with D, only cleanup will be executed (the filter part is irrelevant to D).The C++ personality function from GCC does not catch, but do the cleanup on foreign exceptions. That sound like the right behavior to me.As far as I understand the cleaning is only a part of what personality function does. The first thing it does is check if the thrown exception can be handled. Like determine if it's a C++ exception or some other exception. If I recall correctly, it also determines if and where to resume unwinding, where to find catch blocks and so on. This [1] series of blog posts gives a pretty good understanding of how C++ exceptions work under the hood, for those that don't want to read the ABI documentation. [1] http://monoinfinito.wordpress.com/series/exception-handling-in-c/
Apr 10 2014
On 11/04/14 00:05, deadalnix wrote:You want to look at libstdc++-v3/libsupc++/eh_personality.cc in gcc's source code.If I'm to look at some source code I rather look at libc++abi from LLVM.The personality function test if the exception is a C++ exception, in which case the regular flow apply. If not, the foreign_exception flag is set, and some behavior are altered. Basically, for what we are concerned with D, only cleanup will be executed (the filter part is irrelevant to D).Why is the filter part irrelevant? -- /Jacob Carlborg
Apr 10 2014
On Friday, 11 April 2014 at 06:29:37 UTC, Jacob Carlborg wrote:Why is the filter part irrelevant?filter is "catch everything but.." kind of clause. The semantic do not exists in D, so we don't really care.
Apr 12 2014
On 9 April 2014 08:19, Jacob Carlborg <doob me.com> wrote:On 08/04/14 14:03, David Nadlinger wrote:The "middle-ground" would be us handling Objective-C foreign exceptions in our EH personality function.On Tuesday, 8 April 2014 at 10:08:24 UTC, Jacob Carlborg wrote:A middle ground would help. In the D/Objective-C implementation there is already an exception bridge for 32bit. The 32bit implementation uses setjmp and longjmp.Is there a reason to not use the same model, or what's required to be compatible?In short, the reason not to use the same "model" (you could argue that the model is the same, as only the personality functions differ) is that the exception unwinder is intimately tied to both the target language ABI and semantics. For example, all unwinders need to handle the run-time type information for the exception object to correctly dispatch it. And while e.g. the GNU C++ unwinding implementation needs to pull shenanigans to implement the crazy C++ exception lifetime model (cf. catching by reference vs. by value) and enforce throws(...) specifications, the D unwinder needs to understand the difference between Exception and Error and correctly implement exception chaining. Now, of course, it is possible to find a middle ground that works as a basis for virtually all languages. In fact, I'd argue that SEH for Windows actually provides such a layer, and libunwind does too. For example, a proper implementation of a libunwind personality function allows you to check whether a given exception originated in your own language, and just pass it on otherwise (such that e.g. C++ exception just bubble through a layer of D code). In theory, it would e.g. also be possible to wrap foreign exceptions in e.g. D Throwable objects to make them catchable in D code. But the lifetime of the foreign object is virtually impossible to get right in the general case, and the benefits of wrapping exceptions like this have turned out not to be worth it, because it is hard to handle them in a sensible way in the receiving language (DMD actually does - did? - something like this on Win32).
Apr 09 2014
On 2014-04-09 11:52, Iain Buclaw wrote:The "middle-ground" would be us handling Objective-C foreign exceptions in our EH personality function.Yes, exactly. -- /Jacob Carlborg
Apr 09 2014