January 06, 2014
On Mon, Jan 6, 2014 at 3:04 PM, Kai Nacke <kai@redstar.de> wrote:
> Source for __gxx_personality_sj0 is part of gcc. Just download latest gcc source and search for the symbol.

Yes, it's certainly there, although I don't know how recent it is, given that Apple has been trying to get away from GCC for quite some time now. I don't think it's likely that there are a lot of incompatible changes, but to be sure…

David

January 06, 2014
Jacob Carlborg <doob@me.com> writes:

> You could try and compare it with x86 64bit code. C++ code on x86 64bit is using DWARF-based exception handling. You can see if that code contains anything related to SLJL.
>
> Also Objective-C on x86 32bit uses SLJL but on 64bit is uses DWARF.

Yes, I've been studing the assembly from various working triples.
I like that LLVM can have all the targets built in so it can be as simple
as just changing a -target on clang.
January 06, 2014
David Nadlinger <code@klickverbot.at> writes:

> On Mon, Jan 6, 2014 at 3:04 PM, Kai Nacke <kai@redstar.de> wrote:
>> Source for __gxx_personality_sj0 is part of gcc. Just download latest gcc source and search for the symbol.
>
> Yes, it's certainly there, although I don't know how recent it is, given that Apple has been trying to get away from GCC for quite some time now. I don't think it's likely that there are a lot of incompatible changes, but to be sure…
>
> David

I had some old gcc-4.8 source.  I found it in:

libstdc++-v3/libsupc++/eh_personality.cc
January 06, 2014
David Nadlinger <code@klickverbot.at> writes:

> They are for (un)registering the exception handling context with the global table of active handlers. The parameter to _Unwind_SjLj_Register is constructed by the setjmp() part of SJLJ (it's in fact an optimized, inlined version instead of an actual function call).  When an exception is raised, this global linked list is walked, calling the personality functions for the respective entries to determine whether to longjmp to them.
>
>> I read llvm source code for a while yesterday and really haven't wrapped by brain around it yet.
>
> I'd start out by getting a feel for the LLVM IR we need to generate.
> For this, you can have a look at the respective Clang output (-S
> -emit-llvm). The LLVM docs also have a page on the subject, but
> unfortunately, it is rather sparse:
> http://llvm.org/docs/ExceptionHandling.html#setjmp-longjmp-exception-handling
>
> The more involved part will likely be to get the personality function
> right. Fortunately, at least the related parts of libunwind are open
> source: http://www.opensource.apple.com/source/libunwind/libunwind-35.3/src/Unwind-sjlj.c.
> The source for the GCC/Clang personality function
> (__gxx_personality_sj0) is probably available somewhere as well, but I
> don't know where to look right now (libc++, probably).
>
> David

I decided it was time to carefully study what clang is doing. A grep of SjLj in the llvm source and build trees hopefully is showing where I should pay attention to the design.

In ToolChains.cpp I see how sjlj is enabled.

bool Darwin::UseSjLjExceptions() const {
  // Darwin uses SjLj exceptions on ARM.
  return (getTriple().getArch() == llvm::Triple::arm ||
          getTriple().getArch() == llvm::Triple::thumb);
}

And then in CodeGen/Passes.cpp I see that SjLj has to work with dwarf eh.  It is in the SjLjEHPrepare class code that something goes wrong with ldc2.

  switch (TM->getMCAsmInfo()->getExceptionHandlingType()) {
  case ExceptionHandling::SjLj:
    // SjLj piggy-backs on dwarf for this bit. The cleanups done apply to both
    // Dwarf EH prepare needs to be run after SjLj prepare. Otherwise,
    // catch info can get misplaced when a selector ends up more than one block
    // removed from the parent invoke(s). This could happen when a landing
    // pad is shared by multiple invokes and is also a target of a normal
    // edge from elsewhere.
    addPass(createSjLjEHPreparePass(TM->getTargetLowering()));
    // FALLTHROUGH
  case ExceptionHandling::DwarfCFI:
  case ExceptionHandling::ARM:
  case ExceptionHandling::Win64:
    addPass(createDwarfEHPass(TM));
    break;

I'll spend some more time over the next few days and see what clang does to make the sjlj pass happy.

Thanks for all the help so far,
Dan
January 06, 2014
On 2014-01-06 14:06, David Nadlinger wrote:

> Why would you think otherwise, Jacob? Including more context with your
> messages would make a fair amount of them infinitely more useful…

I was basing that on that the Objective-C modern runtime uses DWARF EH [1] and iOS uses the modern runtime [2]. It seems that's only the case on Mac OS X and not iOS. I found this [3] post on stackoverflow saying Apple chose SJLJ on iOS due to reduce binary size. So it seems you were right.

[1] The bottom of: https://developer.apple.com/library/mac/releasenotes/Cocoa/RN-ObjectiveC/#//apple_ref/doc/uid/TP40004309-CH1-DontLinkElementID_11

[2] https://developer.apple.com/library/mac/documentation/Cocoa/Conceptual/ObjCRuntimeGuide/Articles/ocrtVersionsPlatforms.html

[3] http://stackoverflow.com/questions/3683439/what-is-the-cost-of-using-exceptions-in-objective-c

-- 
/Jacob Carlborg
January 06, 2014
On Mon, Jan 6, 2014 at 9:11 PM, Jacob Carlborg <doob@me.com> wrote:
> I was basing that on that the Objective-C modern runtime uses DWARF EH [1] and iOS uses the modern runtime [2]. It seems that's only the case on Mac OS X and not iOS. I found this [3] post on stackoverflow saying Apple chose SJLJ on iOS due to reduce binary size. So it seems you were right.

Thanks, that's good to know!

David
January 08, 2014
Dan Olson <zans.is.for.cans@yahoo.com> writes:

> I'll spend some more time over the next few days and see what clang does to make the sjlj pass happy.
>
> Thanks for all the help so far,

I looked at what clang does different on i686-apple-darwin and arm-apple-darwin and one thing that changed when targeting ios is a bitcast on the personality function.  So I edited the results of ldc2 -output-l:

From:
  %landing_pad = landingpad { i8*, i32 } personality i32 (i32, i32, i64, i8*, i8*)* @_d_eh_personality

To:
  %landing_pad = landingpad { i8*, i32 } personality i8* bitcast (i32 (i32, i32, i64, i8*, i8*)* @_d_eh_personality to i8*)

Then ran llc on the modified file.  No assertion and I get arm assemble code!  And it looks reasonable to my untrained eye.

By the way, llc is very cool.  As I said, I am totally new to llvm internals, so am having fun learning what it has in its magic bag of tricks.

So far I cannot find where clang adds the bitcast thing for sjlj eh personality.  I will keep hunting.  Any ideas where I would do this in ldc?

When it comes to updating the _d_eh_personality for sjlj, I noticed a very small difference in the c++ versions ( _gxx_personality_v0 and _gxx_personality_sj0).  It is actually one funtion body in

gcc-4.8-20121028/libstdc++-v3/libsupc++/eh_personality.cc

with a little extra code in an ifdef _GLIBCXX_SJLJ_EXCEPTIONS conditional.

Dan
January 09, 2014
On Wednesday, 8 January 2014 at 17:39:19 UTC, Dan Olson wrote:
> Dan Olson <zans.is.for.cans@yahoo.com> writes:
>
>> I'll spend some more time over the next few days and see what clang
>> does to make the sjlj pass happy.
>>
>> Thanks for all the help so far,
>
> I looked at what clang does different on i686-apple-darwin and
> arm-apple-darwin and one thing that changed when targeting ios is a
> bitcast on the personality function.  So I edited the results of ldc2
> -output-l:
>
> From:
>   %landing_pad = landingpad { i8*, i32 } personality i32 (i32, i32, i64, i8*, i8*)* @_d_eh_personality
>
> To:
>   %landing_pad = landingpad { i8*, i32 } personality i8* bitcast (i32 (i32, i32, i64, i8*, i8*)* @_d_eh_personality to i8*)
>
> Then ran llc on the modified file.  No assertion and I get arm assemble
> code!  And it looks reasonable to my untrained eye.

Did you get an assertion without the bitcast? This should work, too. If not then it is an LLVM bug.

> By the way, llc is very cool.  As I said, I am totally new to llvm
> internals, so am having fun learning what it has in its magic bag of
> tricks.

:-)

> So far I cannot find where clang adds the bitcast thing for sjlj eh
> personality.  I will keep hunting.  Any ideas where I would do this in
> ldc?
>
> When it comes to updating the _d_eh_personality for sjlj, I noticed a
> very small difference in the c++ versions ( _gxx_personality_v0 and
> _gxx_personality_sj0).  It is actually one funtion body in
>
> gcc-4.8-20121028/libstdc++-v3/libsupc++/eh_personality.cc
>
> with a little extra code in an ifdef _GLIBCXX_SJLJ_EXCEPTIONS
> conditional.
>
> Dan


Regards,
Kai
January 09, 2014
"Kai Nacke" <kai@redstar.de> writes:

> On Wednesday, 8 January 2014 at 17:39:19 UTC, Dan Olson wrote:
>> I looked at what clang does different on i686-apple-darwin and
>> arm-apple-darwin and one thing that changed when targeting ios is a
>> bitcast on the personality function.  So I edited the results of
>> ldc2
>> -output-l:
>>
>> From:
>>   %landing_pad = landingpad { i8*, i32 } personality i32 (i32, i32,
>> i64, i8*, i8*)* @_d_eh_personality
>>
>> To:
>>   %landing_pad = landingpad { i8*, i32 } personality i8* bitcast
>> (i32 (i32, i32, i64, i8*, i8*)* @_d_eh_personality to i8*)
>>
>> Then ran llc on the modified file.  No assertion and I get arm
>> assemble
>> code!  And it looks reasonable to my untrained eye.
>
> Did you get an assertion without the bitcast? This should work, too. If not then it is an LLVM bug.

Yes.  It is this one.

Assertion failed: (getOperand(0)->getType() == cast<PointerType>(getOperand(1)->getType())->getElementType() && "Ptr must be a pointer to Val type!"), function AssertOK, file /Users/dan/projects/ldc/llvm-3.3.src/lib/IR/Instructions.cpp, line 1084.

January 09, 2014
On Thursday, 9 January 2014 at 08:39:26 UTC, Dan Olson wrote:
>
> Yes.  It is this one.
>
> Assertion failed: (getOperand(0)->getType() == cast<PointerType>(getOperand(1)->getType())->getElementType() && "Ptr must be a pointer to Val type!"), function AssertOK, file /Users/dan/projects/ldc/llvm-3.3.src/lib/IR/Instructions.cpp, line 1084.

Hm. Please, could you try it with LLVM 3.4? I am not sure if my fix made it into LLVM 3.3.

Thanks for working on this!!!

Regards,
Kai