<div dir="ltr"><div dir="ltr"><div dir="ltr">Hi Stanislav,<div><br></div><div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left-width:1px;border-left-style:solid;border-left-color:rgb(204,204,204);padding-left:1ex">Since the last letter in May, I have done more testing of the solution based on objc_readClassPair/objc_registerClassPair and I can confirm that I didn't encounter any major issues related to Objective-C or Swift.</blockquote><div><br></div><div>Congratulations!</div><div><br></div><div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left-width:1px;border-left-style:solid;border-left-color:rgb(204,204,204);padding-left:1ex">It turns out that I no longer have enough of my spare time to invest into this Objective-C/Swift branch of our work on Mull,</blockquote></div><div><br></div><div>I am sorry to hear, but thank you so much for documenting your experience. I am definitely still interested in getting Objective C support working, and this will be a huge help once I can turn my attention to that.</div><div><br></div><div>Cheers,</div><div>Lang.</div><div><br></div><div><br></div><div><br></div><div><br></div><div><br></div><div> </div></div></div></div></div><br><div class="gmail_quote"><div dir="ltr">On Mon, Sep 3, 2018 at 12:13 PM Stanislav Pankevich <<a href="mailto:s.pankevich@gmail.com">s.pankevich@gmail.com</a>> wrote:<br></div><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">Hi Lang,<br>
<br>
Since the last letter in May, I have done more testing of the solution<br>
based on objc_readClassPair/objc_registerClassPair and I can confirm<br>
that I didn't encounter any major issues related to Objective-C or<br>
Swift. We have also connected my prototype code to our mutation<br>
testing tool and got some first mutation testing reports. We have<br>
tested it on Swift code that contains Objective-C classes (a few small<br>
projects randomly taken from Github, for example,<br>
raywenderlich/swift-algorithm-club).<br>
<br>
It turns out that I no longer have enough of my spare time to invest<br>
into this Objective-C/Swift branch of our work on Mull, the mutation<br>
testing tool. I have written a post where I share what I learned while<br>
trying to make LLVM JIT run Objective-C and Swift. I have also tried<br>
to make it friendly to beginners in case if anyone would want to build<br>
something on top of this prototype. The post is called "LLVM JIT,<br>
Objective-C, and Swift on macOS: knowledge dump" and can be found<br>
here: <a href="https://stanislaw.github.io/2018/09/03/llvm-jit-objc-and-swift-knowledge-dump.html" rel="noreferrer" target="_blank">https://stanislaw.github.io/2018/09/03/llvm-jit-objc-and-swift-knowledge-dump.html</a>.<br>
<br>
Another part of the story about Mull, Swift, and Objective-C is that<br>
now we are having another task but it is not related to LLVM JIT but<br>
rather requires a good knowledge of the Swift compiler. I have also<br>
written a post about this issue and also on our progress on mutation<br>
testing for Swift: "Mutation testing for Swift with Mull: how it could<br>
work. Looking for contributors.",<br>
<a href="https://stanislaw.github.io/2018/09/03/mull-and-swift-how-it-almost-works.html" rel="noreferrer" target="_blank">https://stanislaw.github.io/2018/09/03/mull-and-swift-how-it-almost-works.html</a>.<br>
<br>
It is sad that this ObjC code for LLVM JIT is still only a prototype<br>
but I hope that my post might help someone to make a further progress<br>
(be it mutation testing or any other tool that requires LLVM JIT to<br>
run Swift/ObjC).<br>
<br>
On a positive note, Alex has been working on great performance<br>
improvements in Mull: instead of recompiling the whole Modules with<br>
mutated LLVM IR, mutated functions are precompiled along with the<br>
non-mutated functions. No overhead on recompilation and re-linkage of<br>
mutated clones of the program and Mull is now running on C/C++<br>
programs faster than ever before.<br>
<br>
Thanks for attention,<br>
Stanislav<br>
On Sun, May 13, 2018 at 8:38 PM Stanislav Pankevich<br>
<<a href="mailto:s.pankevich@gmail.com" target="_blank">s.pankevich@gmail.com</a>> wrote:<br>
><br>
> Hi Lang,<br>
><br>
> Thank you very much for the answer. It turns out that, within my code,<br>
> objc_readClassPair works much better than my previous attempts to use<br>
> allocateClassPair/registerClassPair. My conclusion is that<br>
> allocate/registerClassPair could work for Objective-C code but<br>
> definitely not for Swift code.<br>
><br>
> With objc_readClassPair it is all much better. I use my own XCTest<br>
> runner and I am able to run various parts of Swift projects from<br>
> Github without any issues: SwiftGraph,<br>
> raywenderlich/swift-algorithm-club, VectorMath - they all have<br>
> XCTest-based test suites so I am running their code using their tests<br>
> inside JIT.<br>
><br>
> The only minor issue that I am having is a funny warning familiar to<br>
> every Mac/iOS developer: when one loads two classes with the same name<br>
> in Runtime:<br>
><br>
> objc[7620]: Class TestCase is implemented in both ?? (0x105ff8270) and<br>
> ?? (0x105ff8270). One of the two will be used. Which one is undefined.<br>
><br>
> However, looking at the reason for this warning in libobjc, it seems<br>
> to me that it just does not implement the slightly different case of<br>
> the classes registered via objc_readClassPair so it is harmless in<br>
> this custom case and can be ignored (for now). I have verified that<br>
> only a single instance of each class is registered.<br>
><br>
> I am still missing many test cases so I want to ask if you can point<br>
> me to those Non-Trivial Test Cases that you mentioned. I am happy to<br>
> try my code on those to see if I would hit the same issues as you did.<br>
><br>
> Meanwhile I am going to add more complex test cases and run some more<br>
> real-world Swift projects.<br>
><br>
> Thanks again for the pointer,<br>
><br>
> Stanislav<br>
><br>
> On Fri, May 4, 2018 at 1:44 AM, Lang Hames <<a href="mailto:lhames@gmail.com" target="_blank">lhames@gmail.com</a>> wrote:<br>
> > Hi Stanislav,<br>
> ><br>
> > Sorry -- I am not much help here. I would like to get ObjC runtime support<br>
> > for the JIT, but have not had time to look in to it closely. When I last<br>
> > tested the idea (a couple of years ago now) we used selector registration<br>
> > and objc_readClassPair to get basic test cases working as you have, but ran<br>
> > into (possibly similar) failures on non-trivial test cases. I think the<br>
> > interpretation (and possibly the layout?) of some runtime metadata varies<br>
> > between relocatable objects and linked images. The advice we got at the time<br>
> > was that we would be better off parsing the metadata in the object file and<br>
> > calling the runtime registration methods in objc/runtime.h, rather than<br>
> > fixing up the metadata ourselves. That might be worth investigating.<br>
> ><br>
> > If you are not worried about performance at the moment, another option may<br>
> > be to ditch RuntimeDyld entirely. ORC is now decoupled from RuntimeDyld, so<br>
> > you are free to substitute your own linking layer. Last year I hacked up an<br>
> > alternative linking layer that dumps objects to disk and links them into<br>
> > dylibs, then dlopens them. The performance is obviously terrible, but this<br>
> > punts all the ObjC/Swift metadata parsing to ld64 and dyld (and you get<br>
> > debug info for free!) so it is handy for prototyping. Let me know if you<br>
> > would like me to share the code for that.<br>
> ><br>
> > Cheers,<br>
> > Lang.<br>
> ><br>
> > On Fri, Apr 6, 2018 at 12:19 PM, Stanislav Pankevich <<a href="mailto:s.pankevich@gmail.com" target="_blank">s.pankevich@gmail.com</a>><br>
> > wrote:<br>
> >><br>
> >> Hi again,<br>
> >><br>
> >> I had tried to follow David's suggestion to take a step back and look<br>
> >> into codegen instead of hacking on RuntimeDyld but then I quickly<br>
> >> realized that I don't understand what exactly needs to be done to<br>
> >> fully register Objective-C runtime. I decided to iterate on JIT code<br>
> >> again and somehow I found that I can hook into SectionMemory by<br>
> >> subclassing it and working with its allocateDataSection method:<br>
> >><br>
> >> 1) I collect pointers to objc-related sections for which the memory is<br>
> >> allocated. Before SectionMemoryManager::finalizeMemory() method is<br>
> >> called I register the ObjC runtime classes.<br>
> >> 2) I iterate over __objc_selrefs sections and fixup selectors. This<br>
> >> does fix the original crash of this thread.<br>
> >> 3) I iterate over __objc_classlist sections and register the new<br>
> >> classes using objc_allocateClassPair function, register the properties<br>
> >> and ivars to these new classes, run objc_registerClassPair to complete<br>
> >> the registration. (I still have to implement the protocol<br>
> >> registration)<br>
> >> 4) I iterate over __objc_classrefs and __objc_superrefs and fix up the<br>
> >> class pointers with the new classes created at step 2.<br>
> >> 5) I iterate over __objc_classlist and fix up its classes with the new<br>
> >> classes created at step 2.<br>
> >><br>
> >> The very basic Objective-C code seems to work now without any issues,<br>
> >> however when I switch to mixed Objective-C/Swift code I start getting<br>
> >> some crashes which I don't fully understand. In particular I am trying<br>
> >> to run a simple XCTestCase test written in Swift and my code crashes<br>
> >> when I access the property of this Swift's ObjC-based class.<br>
> >><br>
> >> My questions are:<br>
> >><br>
> >> 1) Should I do anything else to properly register Objective-C besides<br>
> >> what I am doing at steps 1-5?<br>
> >><br>
> >> 2) Do I have to do anything additionally to make run Swift code with<br>
> >> LLVM JIT? On of the attached files show that the object I am working<br>
> >> with has sections like: __swift3_* or __swift2_*. Should I do anything<br>
> >> about this sections or they are irrelevant?<br>
> >><br>
> >> 3) Anything that I am missing / should know about if I want to run<br>
> >> mixed Objective-C/Swift code via LLVM JIT?<br>
> >><br>
> >> My very hacky code is located here [1]. If needed I can also share the<br>
> >> code of my latest attempts to run the combined ObjC/Swift code.<br>
> >><br>
> >><br>
> >> <a href="https://github.com/mull-project/mull-jit-lab/tree/master/lab-jit-objc/llvm-jit-lab/src" rel="noreferrer" target="_blank">https://github.com/mull-project/mull-jit-lab/tree/master/lab-jit-objc/llvm-jit-lab/src</a><br>
> >><br>
> >> Any help very much appreciated.<br>
> >><br>
> >> Stanislav<br>
> >><br>
> >><br>
> >> On Thu, Feb 15, 2018 at 2:33 AM, Lang Hames <<a href="mailto:lhames@gmail.com" target="_blank">lhames@gmail.com</a>> wrote:<br>
> >> > Hi David, Stanislav,<br>
> >> ><br>
> >> > Sorry for the delayed reply.<br>
> >> ><br>
> >> > Short version: There hasn't been any progress on this just yet, as I<br>
> >> > have<br>
> >> > been busy with an overhaul of the underlying ORC APIs.<br>
> >> ><br>
> >> >> 1) Hack up something in RuntimeDyldMachO to handle the data structures<br>
> >> >> currently generated by clang.  This is fragile, because the interface<br>
> >> >> between the compiler and the runtime is not documented, and is unique<br>
> >> >> to<br>
> >> >> each runtime.  This code will be different on i386 and ARM, for<br>
> >> >> example.<br>
> >> >><br>
> >> >><br>
> >> >><br>
> >> >> 2) Create a new CGObjCRuntime subclass that creates a module init<br>
> >> >> function<br>
> >> >> that constructs all of the classes using the public APIs, by adding<br>
> >> >> something like -fobjc-runtime=jit to the clang flags.  This is not<br>
> >> >> particularly difficult and means that the same code can be used with<br>
> >> >> any<br>
> >> >> Objective-C runtime.<br>
> >> ><br>
> >> ><br>
> >> > (1) is the preferred long-term solution as we want to minimize<br>
> >> > differences<br>
> >> > between generated code in the JIT'd and non-JIT'd cases. (2) seems like<br>
> >> > a<br>
> >> > reasonable interim solution if it is easier to implement.<br>
> >> ><br>
> >> > Steven -- what is the status of the ObjC parsing code these days?<br>
> >> ><br>
> >> > -- Lang.<br>
> >> ><br>
> >> ><br>
> >> > On Wed, Feb 14, 2018 at 3:08 AM, David Chisnall via llvm-dev<br>
> >> > <<a href="mailto:llvm-dev@lists.llvm.org" target="_blank">llvm-dev@lists.llvm.org</a>> wrote:<br>
> >> >><br>
> >> >><br>
> >> >> > On 13 Feb 2018, at 17:42, Stanislav Pankevich <<a href="mailto:s.pankevich@gmail.com" target="_blank">s.pankevich@gmail.com</a>><br>
> >> >> > wrote:<br>
> >> >> ><br>
> >> >> > On Tue, Feb 13, 2018 at 12:18 PM, David Chisnall<br>
> >> >> > <<a href="mailto:David.Chisnall@cl.cam.ac.uk" target="_blank">David.Chisnall@cl.cam.ac.uk</a>> wrote:<br>
> >> >> >> On 12 Feb 2018, at 22:31, Stanislav Pankevich via llvm-dev<br>
> >> >> >> <<a href="mailto:llvm-dev@lists.llvm.org" target="_blank">llvm-dev@lists.llvm.org</a>> wrote:<br>
> >> >> >>><br>
> >> >> >>> Specifically I explored the latest objc4-723<br>
> >> >> >>> from Apple Open Source and it looks like all of the APIs that allow<br>
> >> >> >>> the registration of Objective-C classes, selectors, etc. are all<br>
> >> >> >>> very<br>
> >> >> >>> private.<br>
> >> >> >><br>
> >> >> >> The Objective-C runtime provides public APIs for doing all of this.<br>
> >> >> >> They’re even documented.  They are also more or less standard and so<br>
> >> >> >> work<br>
> >> >> >> with all runtime implementations, not just the Apple one.  I was<br>
> >> >> >> using them<br>
> >> >> >> for JIT’d code on macOS and FreeBSD 10 years ago.<br>
> >> >> ><br>
> >> >> > Which methods are you referring to? For example of class<br>
> >> >> > registration,<br>
> >> >> > do you mean objc_allocateClassPair/objc_registerClassPair or<br>
> >> >> > something<br>
> >> >> > else?<br>
> >> >><br>
> >> >> Yes, those set of APIs.  They provide an interface for building<br>
> >> >> classes,<br>
> >> >> protocols, and so on.<br>
> >> >><br>
> >> >> >>> One year ago you said you could help anyone interested in working<br>
> >> >> >>> on<br>
> >> >> >>> this. Let me check here again as a volunteer (if this work can ever<br>
> >> >> >>> be<br>
> >> >> >>> accomplished by someone outside Apple).<br>
> >> >> >><br>
> >> >> >> As I said in the earlier thread, the best way of doing this is to<br>
> >> >> >> add a<br>
> >> >> >> new subclass of CGObjCRuntime that generates the code using the<br>
> >> >> >> public APIs.<br>
> >> >> ><br>
> >> >> > Let me get this right. What clang::CodeGen:: CGObjCRuntime has to do<br>
> >> >> > with this? My understanding of Lang's hint was that one has to extend<br>
> >> >> > llvm's classes like RuntimeDyldMachO to parse Mach-O, find classes,<br>
> >> >> > selectors, categories etc and register them all manually. Are you<br>
> >> >> > saying that something has to be be added to CodeGen/*?<br>
> >> >><br>
> >> >> You have two options:<br>
> >> >><br>
> >> >> 1) Hack up something in RuntimeDyldMachO to handle the data structures<br>
> >> >> currently generated by clang.  This is fragile, because the interface<br>
> >> >> between the compiler and the runtime is not documented, and is unique<br>
> >> >> to<br>
> >> >> each runtime.  This code will be different on i386 and ARM, for<br>
> >> >> example.<br>
> >> >><br>
> >> >> 2) Create a new CGObjCRuntime subclass that creates a module init<br>
> >> >> function<br>
> >> >> that constructs all of the classes using the public APIs, by adding<br>
> >> >> something like -fobjc-runtime=jit to the clang flags.  This is not<br>
> >> >> particularly difficult and means that the same code can be used with<br>
> >> >> any<br>
> >> >> Objective-C runtime.<br>
> >> >><br>
> >> >> >> If you’re running in the same process as the JIT, you could register<br>
> >> >> >> the selectors in the host environment and just inject the values as<br>
> >> >> >> symbols<br>
> >> >> >> (this is what I did).  I’d be happy to help out someone who wants to<br>
> >> >> >> do<br>
> >> >> >> this.<br>
> >> >> ><br>
> >> >> > It would be nice to get this working without embedding any of<br>
> >> >> > Objective-C to the host process this is<br>
> >> >><br>
> >> >> It’s an optimisation, not a compulsory part of the process.<br>
> >> >><br>
> >> >> > why I am particularly<br>
> >> >> > interested in knowing how to do the work that objc4 does in the<br>
> >> >> > methods such as: objc4/_objc_init, objc4/map_images_nolock and<br>
> >> >> > objc4/_read_images.<br>
> >> >> ><br>
> >> >> > My understanding of the goal is to make the lli example from this<br>
> >> >> > thread working:<br>
> >> >> ><br>
> >> >> ><br>
> >> >> > <a href="https://stackoverflow.com/questions/10375324/all-selectors-unrecognised-when-invoking-objective-c-methods-using-the-llvm-exec" rel="noreferrer" target="_blank">https://stackoverflow.com/questions/10375324/all-selectors-unrecognised-when-invoking-objective-c-methods-using-the-llvm-exec</a>.<br>
> >> >> ><br>
> >> >> > I would be happy to get a hint on which functions of Objective-C<br>
> >> >> > Runtime's public API should I use to get that simple example working<br>
> >> >> > in a quick and dirty way.<br>
> >> >><br>
> >> >> You seem to have decided that you want to use unmodified IR from a<br>
> >> >> specific version of Apple's Objective-C implementation.  I can’t help<br>
> >> >> you<br>
> >> >> there.<br>
> >> >><br>
> >> >> David<br>
> >> >><br>
> >> >> _______________________________________________<br>
> >> >> LLVM Developers mailing list<br>
> >> >> <a href="mailto:llvm-dev@lists.llvm.org" target="_blank">llvm-dev@lists.llvm.org</a><br>
> >> >> <a href="http://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-dev" rel="noreferrer" target="_blank">http://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-dev</a><br>
> >> ><br>
> >> ><br>
> ><br>
> ><br>
</blockquote></div>