I am trying to employ the ABCD optimization pass to remove unnecessary
branches in the code my compiler generates. But in its current form
(yesterday's trunk) the pass changes the behavior of the code such
that execution yields invalid results, which is obviously not what I
The switch in the following listing is used to implement a virtual
method call, 99999 and 100000 are type identifiers used for this
To give an example: %6 is an object of type 99999 (the type id is
stored in the aggregate's first field), allocated on a heap that is
emulated on the stack (%3).
Could someone refer me to documentation, or give me a brief explanation as to why the following will not work--with the caveat that I am still new to this, and have not gotten beyond generating and running jitted code via the LLVM libraries:
Imagine three functions fa, fb, fc where fa, and fc are generated and jitted with llvm. Function fb on the other hand has external C linkage and is statically compiled along with the llvm generating code into one executable.
- fc merely executes an unwind.
- fa uses invoke to call fb, passing its own arguments to it, which in turn calls fc.
- At runtime fa is called (after jitting from a main(...) C routine), with a pointer to an ExecutionEngine instance, and a Function pointer to fc, both typed as Type::Int8Ty->getPointerTo() (at code generation time).
- fa takes these arguments and invokes fb with them.
- fb being a non-generated C function, takes the passed in Function pointer and engine instance, retrieves the jitted C pointer, and calls it.
- As this pointer is a pointer to fc, the unwind is then executed.
Basically I have the call stack fa->fb->fc with fa, fc generated and fb not generated. Given that I was using the intuitive model of a setjump, longjump, I thought that fc's unwind would pass through fb and end up at fa's invoke's exception block. However it cores even though I've verified that each function is being executed. So I guess either there is something fundamental I don't understand, or I have another issue.
Although I'm assuming this problem is obvious to those in the know, I can supply test code if desired.
Thanks in advance
- fc merely executes an unwind.
the code generators do not know how to codegen unwind. Only the
interpreter has support for it. Yes, this sucks. You will need
to call the libgcc unwind routine directly.
That's what I get for not doing a simpler pure unwind test.
Really? I thought the JIT supported exceptions via -enable-eh.
The ABCD pass is known not to work at this time. It doesn't pass large swaths of the nightly testsuite.
You mean by lowering to setjmp/longjmp? Maybe, I don't know.
It should be easy to find out by trying it.
No, with DWARF. There's all this code in the JIT
(JITDwarfEmitter.cpp) to register the DWARF with libgcc.
Is it enough to know how to call libgcc's _Unwind_RaiseException, or is the code for invoke's exception block landing pad also not generated? After hacking to force in gcc_personaliy_v0(...) from the compiler-rt project (had to create an external dynamic C library), I'm able to get that called when an LLVM generated function (which was LLVM invoked), calls _Unwind_RaiseException (again via the same dynamic C lib). However as the default version of this personality does not check for handlers (I think this is the reason), the outer invoke's exception block is never entered. For a narrow non-mixed language interoperability focus, am I on the the right track--I don't think I want to use the C++ mechanism at least for learning purposes, or is there more code generation on the invoke side that needs to take place, and I therefore need to understand the likes of JITDwarfEmitter.cpp, and the code generation side of things?
My eventual purpose here is to add exception like behavior to an LLVM generated version of a proprietary language runtime that I have. I guess I could also look at the PyPy project, but the "C++ ABI for Itanium: Exception Handling" implied something simple for just trying to do a simple unwind, as long as the invoke's exception landing pad was properly "registered". Sorry I'm vague here, but my understanding is even more vague at this point.