Hi Matt, Philip, You could get the data you want by recording the addresses returned by the allocateCodeSection and allocateDataSection methods on your RTDyldMemoryManager, then disassembling those sections after you've called resolveRelocations. That's a little unsatisfying though. For one thing, unless you very carefully maintain the association with the original object via back-channels there will be no way of knowing which section belongs to which object file. With a bit of cleanup though, we could do something more like this: const RuntimeDyld::JITObject& JO = RTDyld.loadObject(Object); // ... RTDyld.resolveRelocations(); DEBUG( for (const RuntimeDyld::JITObject::Section& S : JO.sections()) if (S.isText()) Disassemble(S.getAddr(), S.getSize()); ); How does that look? Cheers, Lang. On Wed, Sep 17, 2014 at 3:08 PM, Philip Reames <listmail at philipreames.com> wrote:> > On 09/17/2014 12:45 PM, Matt Godbolt wrote: > >> Great stuff; thanks both! >> >> I'm also looking to turn my MCJIT conversion spike into our main use >> case. The only thing I'm missing is the ability to get a post-linked >> copy of the generated assembly. >> >> In JIT I used JITEventListener's NotifyFunctionEmitted and used a >> MCDisassembler to disassemble the stream (with my own custom >> annotators), and redirected the output to the relevant place for >> auditing of our app. >> >> With MCJIT I notice that NotifyFunctionEmitted is gone >> (understandably) and so I hook NotifyObjectEmitted. I then run through >> all the function symbols and dump them as before. Yay. Except that in >> MCJIT terms the linking hasn't happened, so all the globals and >> external functions are all zeros at this point. (If I hackily observe >> the same code later on I see the linker has appropriately populated >> these addresses). This makes my nicely annotated code a little >> unreadable, unfortunately. >> >> Does anyone have any suggestions as to how I might get to disassemble >> the post-linked code? >> > my 2 cents: It seems like we need a different event type. Having access > to the object before linking (and relocation?) seems useful, but I suspect > most users (myself included) want the final object after everything is done. > > Philip > > > On Wed, Sep 17, 2014 at 2:35 PM, Yaron Keren <yaron.keren at gmail.com> > wrote: > >> Hi, >>> >>> You need to call llvm::sys::getHostCPUName() and pass the result to >>> createTargetMachine() passed to the JIT. This patch should be applied: >>> >>> http://llvm.org/bugs/show_bug.cgi?id=17422 >>> >>> Anyhow, the JIT was removed from current code and will not be in next >>> LLVM >>> release. >>> >>> Yaron >>> >>> >>> 2014-09-17 22:27 GMT+03:00 Matt Godbolt <matt at godbolt.org>: >>> >>>> Hi Jim, >>>> >>>> Thanks for a very quick reply! That indeed does the trick! >>>> >>>> Presumably the default has changed in 3.5 to be a "generic" CPU >>>> instead of the native one? If that's the case I wonder why: especially >>>> when JITting it really only makes sense to target the actual CPU - >>>> unless I'm missing something? :) >>>> >>>> Thanks again, >>>> >>>> Matt >>>> >>>> On Wed, Sep 17, 2014 at 2:16 PM, Jim Grosbach <grosbach at apple.com> >>>> wrote: >>>> >>>>> Hi Matt, >>>>> >>>>> I suspect you need to specify the target CPU when you create the JIT. >>>>> It’s just a method on the builder (e.g., builder.setMCPU(MCPU)). If >>>>> you want >>>>> auto-detection based on the host CPU, sys::getHostCPUName() returns a >>>>> value >>>>> suitable to be passed directly into the builder. >>>>> >>>>> -Jim >>>>> >>>>> On Sep 17, 2014, at 11:44 AM, Matt Godbolt <matt at godbolt.org> wrote: >>>>>> >>>>>> Hi guys, >>>>>> >>>>>> I just upgraded our JIT system to use llvm 3.5 and noticed one big >>>>>> change in our generated code: we don't see any non-destructive VEX >>>>>> prefix instructions being emitted any more (vmulsd xmm0, xmm1, blah) >>>>>> etc. >>>>>> >>>>>> It's long been on my list of things to investigate anyway as I noticed >>>>>> llvm didn't emit VZEROUPPER calls either, so I supposed it might not >>>>>> be a bad thing to disable vex. >>>>>> >>>>>> That being said, try as I might I can't force avx on >>>>>> (builder.setMCPU("core-avx-i") and/or >>>>>> builder.setMAttrs(vector<string>{"+avx"});). We're still using the >>>>>> old >>>>>> JIT but I just spiked out a move to MCJIT and I still don't see the >>>>>> VEX instructions. >>>>>> >>>>>> Was there a deliberate change on the llvm-side to discourage VEX >>>>>> instructions unless they make a big enough difference (and/or is >>>>>> VZEROUPPER now emitted?). >>>>>> >>>>>> If not, how might I go about digging further into this? >>>>>> >>>>>> Many thanks in advance, Matt >>>>>> >>>>>> -- >>>>>> Matt >>>>>> _______________________________________________ >>>>>> LLVM Developers mailing list >>>>>> LLVMdev at cs.uiuc.edu http://llvm.cs.uiuc.edu >>>>>> http://lists.cs.uiuc.edu/mailman/listinfo/llvmdev >>>>>> >>>>> >>>> >>>> -- >>>> Matt >>>> >>>> _______________________________________________ >>>> LLVM Developers mailing list >>>> LLVMdev at cs.uiuc.edu http://llvm.cs.uiuc.edu >>>> http://lists.cs.uiuc.edu/mailman/listinfo/llvmdev >>>> >>> >>> >> >> > _______________________________________________ > LLVM Developers mailing list > LLVMdev at cs.uiuc.edu http://llvm.cs.uiuc.edu > http://lists.cs.uiuc.edu/mailman/listinfo/llvmdev >-------------- next part -------------- An HTML attachment was scrubbed... URL: <http://lists.llvm.org/pipermail/llvm-dev/attachments/20140918/82175fd4/attachment.html>
Hi Lang, Thanks for the reply, I'm glad it sounds like you have a fairly simple suggested improvement. I'm not too familiar with the inner workings of llvm, so apologies if this is a dumb question; what's the "Disassemble" and DEBUG() parts doing here? Are these the in the user code? I don't interact with the RuntimeDyld directly anywhere in my code, so I'm not sure where this code would go. If it's user code and I can somehow get hold of a RuntimeDyld then this seems like a good match, as it seems pretty much what I'm doing in NotifyObjectEmitted already. Cheers, Matt :) On Thu, Sep 18, 2014 at 12:17 PM, Lang Hames <lhames at gmail.com> wrote:> Hi Matt, Philip, > > You could get the data you want by recording the addresses returned by the > allocateCodeSection and allocateDataSection methods on your > RTDyldMemoryManager, then disassembling those sections after you've called > resolveRelocations. That's a little unsatisfying though. For one thing, > unless you very carefully maintain the association with the original object > via back-channels there will be no way of knowing which section belongs to > which object file. > > With a bit of cleanup though, we could do something more like this: > > const RuntimeDyld::JITObject& JO = RTDyld.loadObject(Object); > // ... > RTDyld.resolveRelocations(); > > DEBUG( > for (const RuntimeDyld::JITObject::Section& S : JO.sections()) > if (S.isText()) > Disassemble(S.getAddr(), S.getSize()); > ); > > How does that look? > > Cheers, > Lang. > > > On Wed, Sep 17, 2014 at 3:08 PM, Philip Reames <listmail at philipreames.com> > wrote: >> >> >> On 09/17/2014 12:45 PM, Matt Godbolt wrote: >>> >>> Great stuff; thanks both! >>> >>> I'm also looking to turn my MCJIT conversion spike into our main use >>> case. The only thing I'm missing is the ability to get a post-linked >>> copy of the generated assembly. >>> >>> In JIT I used JITEventListener's NotifyFunctionEmitted and used a >>> MCDisassembler to disassemble the stream (with my own custom >>> annotators), and redirected the output to the relevant place for >>> auditing of our app. >>> >>> With MCJIT I notice that NotifyFunctionEmitted is gone >>> (understandably) and so I hook NotifyObjectEmitted. I then run through >>> all the function symbols and dump them as before. Yay. Except that in >>> MCJIT terms the linking hasn't happened, so all the globals and >>> external functions are all zeros at this point. (If I hackily observe >>> the same code later on I see the linker has appropriately populated >>> these addresses). This makes my nicely annotated code a little >>> unreadable, unfortunately. >>> >>> Does anyone have any suggestions as to how I might get to disassemble >>> the post-linked code? >> >> my 2 cents: It seems like we need a different event type. Having access >> to the object before linking (and relocation?) seems useful, but I suspect >> most users (myself included) want the final object after everything is done. >> >> Philip >> >> >> On Wed, Sep 17, 2014 at 2:35 PM, Yaron Keren <yaron.keren at gmail.com> >> wrote: >>>> >>>> Hi, >>>> >>>> You need to call llvm::sys::getHostCPUName() and pass the result to >>>> createTargetMachine() passed to the JIT. This patch should be applied: >>>> >>>> http://llvm.org/bugs/show_bug.cgi?id=17422 >>>> >>>> Anyhow, the JIT was removed from current code and will not be in next >>>> LLVM >>>> release. >>>> >>>> Yaron >>>> >>>> >>>> 2014-09-17 22:27 GMT+03:00 Matt Godbolt <matt at godbolt.org>: >>>>> >>>>> Hi Jim, >>>>> >>>>> Thanks for a very quick reply! That indeed does the trick! >>>>> >>>>> Presumably the default has changed in 3.5 to be a "generic" CPU >>>>> instead of the native one? If that's the case I wonder why: especially >>>>> when JITting it really only makes sense to target the actual CPU - >>>>> unless I'm missing something? :) >>>>> >>>>> Thanks again, >>>>> >>>>> Matt >>>>> >>>>> On Wed, Sep 17, 2014 at 2:16 PM, Jim Grosbach <grosbach at apple.com> >>>>> wrote: >>>>>> >>>>>> Hi Matt, >>>>>> >>>>>> I suspect you need to specify the target CPU when you create the JIT. >>>>>> It’s just a method on the builder (e.g., builder.setMCPU(MCPU)). If >>>>>> you want >>>>>> auto-detection based on the host CPU, sys::getHostCPUName() returns a >>>>>> value >>>>>> suitable to be passed directly into the builder. >>>>>> >>>>>> -Jim >>>>>> >>>>>>> On Sep 17, 2014, at 11:44 AM, Matt Godbolt <matt at godbolt.org> wrote: >>>>>>> >>>>>>> Hi guys, >>>>>>> >>>>>>> I just upgraded our JIT system to use llvm 3.5 and noticed one big >>>>>>> change in our generated code: we don't see any non-destructive VEX >>>>>>> prefix instructions being emitted any more (vmulsd xmm0, xmm1, blah) >>>>>>> etc. >>>>>>> >>>>>>> It's long been on my list of things to investigate anyway as I >>>>>>> noticed >>>>>>> llvm didn't emit VZEROUPPER calls either, so I supposed it might not >>>>>>> be a bad thing to disable vex. >>>>>>> >>>>>>> That being said, try as I might I can't force avx on >>>>>>> (builder.setMCPU("core-avx-i") and/or >>>>>>> builder.setMAttrs(vector<string>{"+avx"});). We're still using the >>>>>>> old >>>>>>> JIT but I just spiked out a move to MCJIT and I still don't see the >>>>>>> VEX instructions. >>>>>>> >>>>>>> Was there a deliberate change on the llvm-side to discourage VEX >>>>>>> instructions unless they make a big enough difference (and/or is >>>>>>> VZEROUPPER now emitted?). >>>>>>> >>>>>>> If not, how might I go about digging further into this? >>>>>>> >>>>>>> Many thanks in advance, Matt >>>>>>> >>>>>>> -- >>>>>>> Matt >>>>>>> _______________________________________________ >>>>>>> LLVM Developers mailing list >>>>>>> LLVMdev at cs.uiuc.edu http://llvm.cs.uiuc.edu >>>>>>> http://lists.cs.uiuc.edu/mailman/listinfo/llvmdev >>>>> >>>>> >>>>> >>>>> -- >>>>> Matt >>>>> >>>>> _______________________________________________ >>>>> LLVM Developers mailing list >>>>> LLVMdev at cs.uiuc.edu http://llvm.cs.uiuc.edu >>>>> http://lists.cs.uiuc.edu/mailman/listinfo/llvmdev >>>> >>>> >>> >>> >> >> _______________________________________________ >> LLVM Developers mailing list >> LLVMdev at cs.uiuc.edu http://llvm.cs.uiuc.edu >> http://lists.cs.uiuc.edu/mailman/listinfo/llvmdev > >-- Matt
On 09/18/2014 10:17 AM, Lang Hames wrote:> Hi Matt, Philip, > > You could get the data you want by recording the addresses returned by > the allocateCodeSection and allocateDataSection methods on your > RTDyldMemoryManager, then disassembling those sections after you've > called resolveRelocations. That's a little unsatisfying though. For > one thing, unless you very carefully maintain the association with the > original object via back-channels there will be no way of knowing > which section belongs to which object file.I know. This is what I'm actually doing today. :)> > With a bit of cleanup though, we could do something more like this: > > const RuntimeDyld::JITObject& JO = RTDyld.loadObject(Object); > // ... > RTDyld.resolveRelocations(); > > DEBUG( > for (const RuntimeDyld::JITObject::Section& S : JO.sections()) > if (S.isText()) > Disassemble(S.getAddr(), S.getSize()); > ); > > How does that look?I'm not using the loadObject interface today. On the surface, this looks ideal, but I don't have any practical experience to confirm. I'm currently using the interfaces on ExecutionEngine (i.e. generateCodeForModule, mapSectionAddress, finalizeObject, then getPointerToFunction)> > Cheers, > Lang. > > > On Wed, Sep 17, 2014 at 3:08 PM, Philip Reames > <listmail at philipreames.com <mailto:listmail at philipreames.com>> wrote: > > > On 09/17/2014 12:45 PM, Matt Godbolt wrote: > > Great stuff; thanks both! > > I'm also looking to turn my MCJIT conversion spike into our > main use > case. The only thing I'm missing is the ability to get a > post-linked > copy of the generated assembly. > > In JIT I used JITEventListener's NotifyFunctionEmitted and used a > MCDisassembler to disassemble the stream (with my own custom > annotators), and redirected the output to the relevant place for > auditing of our app. > > With MCJIT I notice that NotifyFunctionEmitted is gone > (understandably) and so I hook NotifyObjectEmitted. I then run > through > all the function symbols and dump them as before. Yay. Except > that in > MCJIT terms the linking hasn't happened, so all the globals and > external functions are all zeros at this point. (If I hackily > observe > the same code later on I see the linker has appropriately > populated > these addresses). This makes my nicely annotated code a little > unreadable, unfortunately. > > Does anyone have any suggestions as to how I might get to > disassemble > the post-linked code? > > my 2 cents: It seems like we need a different event type. Having > access to the object before linking (and relocation?) seems > useful, but I suspect most users (myself included) want the final > object after everything is done. > > Philip > > > On Wed, Sep 17, 2014 at 2:35 PM, Yaron Keren > <yaron.keren at gmail.com <mailto:yaron.keren at gmail.com>> wrote: > > Hi, > > You need to call llvm::sys::getHostCPUName() and pass the > result to > createTargetMachine() passed to the JIT. This patch should > be applied: > > http://llvm.org/bugs/show_bug.cgi?id=17422 > > Anyhow, the JIT was removed from current code and will not > be in next LLVM > release. > > Yaron > > > 2014-09-17 22:27 GMT+03:00 Matt Godbolt <matt at godbolt.org > <mailto:matt at godbolt.org>>: > > Hi Jim, > > Thanks for a very quick reply! That indeed does the trick! > > Presumably the default has changed in 3.5 to be a > "generic" CPU > instead of the native one? If that's the case I wonder > why: especially > when JITting it really only makes sense to target the > actual CPU - > unless I'm missing something? :) > > Thanks again, > > Matt > > On Wed, Sep 17, 2014 at 2:16 PM, Jim Grosbach > <grosbach at apple.com <mailto:grosbach at apple.com>> wrote: > > Hi Matt, > > I suspect you need to specify the target CPU when > you create the JIT. > It’s just a method on the builder (e.g., > builder.setMCPU(MCPU)). If you want > auto-detection based on the host CPU, > sys::getHostCPUName() returns a value > suitable to be passed directly into the builder. > > -Jim > > On Sep 17, 2014, at 11:44 AM, Matt Godbolt > <matt at godbolt.org <mailto:matt at godbolt.org>> > wrote: > > Hi guys, > > I just upgraded our JIT system to use llvm 3.5 > and noticed one big > change in our generated code: we don't see any > non-destructive VEX > prefix instructions being emitted any more > (vmulsd xmm0, xmm1, blah) > etc. > > It's long been on my list of things to > investigate anyway as I noticed > llvm didn't emit VZEROUPPER calls either, so I > supposed it might not > be a bad thing to disable vex. > > That being said, try as I might I can't force > avx on > (builder.setMCPU("core-avx-i") and/or > builder.setMAttrs(vector<string>{"+avx"});). > We're still using the old > JIT but I just spiked out a move to MCJIT and > I still don't see the > VEX instructions. > > Was there a deliberate change on the llvm-side > to discourage VEX > instructions unless they make a big enough > difference (and/or is > VZEROUPPER now emitted?). > > If not, how might I go about digging further > into this? > > Many thanks in advance, Matt > > -- > Matt > _______________________________________________ > LLVM Developers mailing list > LLVMdev at cs.uiuc.edu > <mailto:LLVMdev at cs.uiuc.edu> > http://llvm.cs.uiuc.edu > http://lists.cs.uiuc.edu/mailman/listinfo/llvmdev > > > > -- > Matt > > _______________________________________________ > LLVM Developers mailing list > LLVMdev at cs.uiuc.edu <mailto:LLVMdev at cs.uiuc.edu> > http://llvm.cs.uiuc.edu > http://lists.cs.uiuc.edu/mailman/listinfo/llvmdev > > > > > > _______________________________________________ > LLVM Developers mailing list > LLVMdev at cs.uiuc.edu <mailto:LLVMdev at cs.uiuc.edu> > http://llvm.cs.uiuc.edu > http://lists.cs.uiuc.edu/mailman/listinfo/llvmdev > >-------------- next part -------------- An HTML attachment was scrubbed... URL: <http://lists.llvm.org/pipermail/llvm-dev/attachments/20140918/42eeddbe/attachment.html>
Hi Philip, Ahh. Sorry to hear. The good news is that I have a plan to make it better. The bad news is that I don't have a timeline. I'm trying to squash a few critical bugs in the infrastructure at the moment and then I'll start putting out proposals and asking for volunteers. :) - Lang. On Thu, Sep 18, 2014 at 11:01 AM, Philip Reames <listmail at philipreames.com> wrote:> > On 09/18/2014 10:17 AM, Lang Hames wrote: > > Hi Matt, Philip, > > You could get the data you want by recording the addresses returned by > the allocateCodeSection and allocateDataSection methods on your > RTDyldMemoryManager, then disassembling those sections after you've called > resolveRelocations. That's a little unsatisfying though. For one thing, > unless you very carefully maintain the association with the original object > via back-channels there will be no way of knowing which section belongs to > which object file. > > I know. This is what I'm actually doing today. :) > > > With a bit of cleanup though, we could do something more like this: > > const RuntimeDyld::JITObject& JO = RTDyld.loadObject(Object); > // ... > RTDyld.resolveRelocations(); > > DEBUG( > for (const RuntimeDyld::JITObject::Section& S : JO.sections()) > if (S.isText()) > Disassemble(S.getAddr(), S.getSize()); > ); > > How does that look? > > I'm not using the loadObject interface today. On the surface, this looks > ideal, but I don't have any practical experience to confirm. I'm currently > using the interfaces on ExecutionEngine (i.e. generateCodeForModule, > mapSectionAddress, finalizeObject, then getPointerToFunction) > > > Cheers, > Lang. > > > On Wed, Sep 17, 2014 at 3:08 PM, Philip Reames <listmail at philipreames.com> > wrote: > >> >> On 09/17/2014 12:45 PM, Matt Godbolt wrote: >> >>> Great stuff; thanks both! >>> >>> I'm also looking to turn my MCJIT conversion spike into our main use >>> case. The only thing I'm missing is the ability to get a post-linked >>> copy of the generated assembly. >>> >>> In JIT I used JITEventListener's NotifyFunctionEmitted and used a >>> MCDisassembler to disassemble the stream (with my own custom >>> annotators), and redirected the output to the relevant place for >>> auditing of our app. >>> >>> With MCJIT I notice that NotifyFunctionEmitted is gone >>> (understandably) and so I hook NotifyObjectEmitted. I then run through >>> all the function symbols and dump them as before. Yay. Except that in >>> MCJIT terms the linking hasn't happened, so all the globals and >>> external functions are all zeros at this point. (If I hackily observe >>> the same code later on I see the linker has appropriately populated >>> these addresses). This makes my nicely annotated code a little >>> unreadable, unfortunately. >>> >>> Does anyone have any suggestions as to how I might get to disassemble >>> the post-linked code? >>> >> my 2 cents: It seems like we need a different event type. Having access >> to the object before linking (and relocation?) seems useful, but I suspect >> most users (myself included) want the final object after everything is done. >> >> Philip >> >> >> On Wed, Sep 17, 2014 at 2:35 PM, Yaron Keren <yaron.keren at gmail.com> >> wrote: >> >>> Hi, >>>> >>>> You need to call llvm::sys::getHostCPUName() and pass the result to >>>> createTargetMachine() passed to the JIT. This patch should be applied: >>>> >>>> http://llvm.org/bugs/show_bug.cgi?id=17422 >>>> >>>> Anyhow, the JIT was removed from current code and will not be in next >>>> LLVM >>>> release. >>>> >>>> Yaron >>>> >>>> >>>> 2014-09-17 22:27 GMT+03:00 Matt Godbolt <matt at godbolt.org>: >>>> >>>>> Hi Jim, >>>>> >>>>> Thanks for a very quick reply! That indeed does the trick! >>>>> >>>>> Presumably the default has changed in 3.5 to be a "generic" CPU >>>>> instead of the native one? If that's the case I wonder why: especially >>>>> when JITting it really only makes sense to target the actual CPU - >>>>> unless I'm missing something? :) >>>>> >>>>> Thanks again, >>>>> >>>>> Matt >>>>> >>>>> On Wed, Sep 17, 2014 at 2:16 PM, Jim Grosbach <grosbach at apple.com> >>>>> wrote: >>>>> >>>>>> Hi Matt, >>>>>> >>>>>> I suspect you need to specify the target CPU when you create the JIT. >>>>>> It’s just a method on the builder (e.g., builder.setMCPU(MCPU)). If >>>>>> you want >>>>>> auto-detection based on the host CPU, sys::getHostCPUName() returns a >>>>>> value >>>>>> suitable to be passed directly into the builder. >>>>>> >>>>>> -Jim >>>>>> >>>>>> On Sep 17, 2014, at 11:44 AM, Matt Godbolt <matt at godbolt.org> wrote: >>>>>>> >>>>>>> Hi guys, >>>>>>> >>>>>>> I just upgraded our JIT system to use llvm 3.5 and noticed one big >>>>>>> change in our generated code: we don't see any non-destructive VEX >>>>>>> prefix instructions being emitted any more (vmulsd xmm0, xmm1, blah) >>>>>>> etc. >>>>>>> >>>>>>> It's long been on my list of things to investigate anyway as I >>>>>>> noticed >>>>>>> llvm didn't emit VZEROUPPER calls either, so I supposed it might not >>>>>>> be a bad thing to disable vex. >>>>>>> >>>>>>> That being said, try as I might I can't force avx on >>>>>>> (builder.setMCPU("core-avx-i") and/or >>>>>>> builder.setMAttrs(vector<string>{"+avx"});). We're still using the >>>>>>> old >>>>>>> JIT but I just spiked out a move to MCJIT and I still don't see the >>>>>>> VEX instructions. >>>>>>> >>>>>>> Was there a deliberate change on the llvm-side to discourage VEX >>>>>>> instructions unless they make a big enough difference (and/or is >>>>>>> VZEROUPPER now emitted?). >>>>>>> >>>>>>> If not, how might I go about digging further into this? >>>>>>> >>>>>>> Many thanks in advance, Matt >>>>>>> >>>>>>> -- >>>>>>> Matt >>>>>>> _______________________________________________ >>>>>>> LLVM Developers mailing list >>>>>>> LLVMdev at cs.uiuc.edu http://llvm.cs.uiuc.edu >>>>>>> http://lists.cs.uiuc.edu/mailman/listinfo/llvmdev >>>>>>> >>>>>> >>>>> >>>>> -- >>>>> Matt >>>>> >>>>> _______________________________________________ >>>>> LLVM Developers mailing list >>>>> LLVMdev at cs.uiuc.edu http://llvm.cs.uiuc.edu >>>>> http://lists.cs.uiuc.edu/mailman/listinfo/llvmdev >>>>> >>>> >>>> >>> >>> >> _______________________________________________ >> LLVM Developers mailing list >> LLVMdev at cs.uiuc.edu http://llvm.cs.uiuc.edu >> http://lists.cs.uiuc.edu/mailman/listinfo/llvmdev >> > > >-------------- next part -------------- An HTML attachment was scrubbed... URL: <http://lists.llvm.org/pipermail/llvm-dev/attachments/20140918/7db12bd4/attachment.html>
Hi Matt, CCing the Dev list, as I accidentally dropped them off my last reply. Regarding loadObject, that API is very much hypothetical at the moment (there is a RuntimeDyld::loadObject, but it returns something else). Some background may make it clearer where I'm thinking of going with this though: MCJIT builds on RuntimeDyld. RuntimeDyld is responsible for making object files in memory (instances of llvm::object::ObjectFile) runnable. It does this by allocating memory for the sections, applying relocations, and providing symbol lookup. To a very rough approximation, MCJIT is just: class MCJIT { private: RuntimeDyld Dyld; public: void* getSymbolAddress(StringRef Name) { return Dyld.getSymbolAddress(Name); } void addModule(Module *M) { Dyld.loadObject(CodeGenIRToObject(M)); } }; All the interesting parts of MCJIT have to do with module ownership, setting up the CodeGen pipeline, etc. If you're happy to handle codegen and module ownership yourself, you could actually talk to RuntimeDyld directly, rather than going through MCJIT. That's what I'm doing in that example, just for the sake of simplicity. For clients who want to keep using MCJIT we just need to add an API to get at the underlying Dyld state so that, if they want to, clients can inspect RuntimeDyld::JITObjects (these don't exist yet either, but are easy to add). Exactly what that API will look like I'm not sure yet. It may be as simple as 'RuntimeDyld::JITObject getJITObject(Module *M)' in the end. So short version: The loadObject API in the example above doesn't exist yet, and even if it did you probably wouldn't want to use it. However, there's a plan to get this kind of information to JIT clients in the future. On a related note, the demand for this kind of API usually comes from a desire to debug either the JIT or the JIT'd code. If we had a proper debugger registration system (i.e. a way to get relocated Dwarf to JIT clients and system debuggers), that could be used to find out most of the interesting things about relocated sections (including their, size, address, etc). This is also on the drawing board, but waiting for me to find time to do it. Cheers, Lang. On Thu, Sep 18, 2014 at 1:11 PM, Matt Godbolt <matt at godbolt.org> wrote:> Thanks Lang, I guessed as much. I already have the MCDisassembler > stuff all sorted (we're using it already with the JIT callback > NotifyFunctionEmitted) and we do in fact use it for non-debug too > (it's a one-time startup cost for us and it's useful to log to disc > all this stuff to spot regressions etc). > > I really appreciate you taking the time to have a think about this for us > :) > > I realise you're busy but if you have a second or two it seems both > Philip and I are unaware of the loadObject() style way of JITting. > We're also using the ExecutionEngine to build our code - can you point > us both in the direction of how one might use the loadObject style, > should you think it worthwhile? > > Cheers, Matt :) > > On Thu, Sep 18, 2014 at 1:46 PM, Lang Hames <lhames at gmail.com> wrote: > > Hi Matt, > > > > "Disassemble" is just pseudocode there, but the MCDisassembler in LLVM > does > > have a reasonably friendly interface. You can look at the code in > > tools/llvm-mc to see how it's used. > > > > DEBUG is just a macro to wrap code so that it only executes for Debug > > builds. My assumption was that you were disassembling for some sort of > debug > > dump (I've written things like that in the past for debugging the JIT > > infrastructure). If this is functionality that you want to be compiled > into > > your project all the time you can just drop the reference to DEBUG. > > > > - Lang. > > > > On Thu, Sep 18, 2014 at 11:00 AM, Matt Godbolt <matt at godbolt.org> wrote: > >> > >> Hi Lang, > >> > >> Thanks for the reply, I'm glad it sounds like you have a fairly simple > >> suggested improvement. > >> > >> I'm not too familiar with the inner workings of llvm, so apologies if > >> this is a dumb question; what's the "Disassemble" and DEBUG() parts > >> doing here? Are these the in the user code? I don't interact with the > >> RuntimeDyld directly anywhere in my code, so I'm not sure where this > >> code would go. If it's user code and I can somehow get hold of a > >> RuntimeDyld then this seems like a good match, as it seems pretty much > >> what I'm doing in NotifyObjectEmitted already. > >> > >> Cheers, Matt :) > >> > >> On Thu, Sep 18, 2014 at 12:17 PM, Lang Hames <lhames at gmail.com> wrote: > >> > Hi Matt, Philip, > >> > > >> > You could get the data you want by recording the addresses returned by > >> > the > >> > allocateCodeSection and allocateDataSection methods on your > >> > RTDyldMemoryManager, then disassembling those sections after you've > >> > called > >> > resolveRelocations. That's a little unsatisfying though. For one > thing, > >> > unless you very carefully maintain the association with the original > >> > object > >> > via back-channels there will be no way of knowing which section > belongs > >> > to > >> > which object file. > >> > > >> > With a bit of cleanup though, we could do something more like this: > >> > > >> > const RuntimeDyld::JITObject& JO = RTDyld.loadObject(Object); > >> > // ... > >> > RTDyld.resolveRelocations(); > >> > > >> > DEBUG( > >> > for (const RuntimeDyld::JITObject::Section& S : JO.sections()) > >> > if (S.isText()) > >> > Disassemble(S.getAddr(), S.getSize()); > >> > ); > >> > > >> > How does that look? > >> > > >> > Cheers, > >> > Lang. > >> > > >> > > >> > On Wed, Sep 17, 2014 at 3:08 PM, Philip Reames > >> > <listmail at philipreames.com> > >> > wrote: > >> >> > >> >> > >> >> On 09/17/2014 12:45 PM, Matt Godbolt wrote: > >> >>> > >> >>> Great stuff; thanks both! > >> >>> > >> >>> I'm also looking to turn my MCJIT conversion spike into our main use > >> >>> case. The only thing I'm missing is the ability to get a post-linked > >> >>> copy of the generated assembly. > >> >>> > >> >>> In JIT I used JITEventListener's NotifyFunctionEmitted and used a > >> >>> MCDisassembler to disassemble the stream (with my own custom > >> >>> annotators), and redirected the output to the relevant place for > >> >>> auditing of our app. > >> >>> > >> >>> With MCJIT I notice that NotifyFunctionEmitted is gone > >> >>> (understandably) and so I hook NotifyObjectEmitted. I then run > through > >> >>> all the function symbols and dump them as before. Yay. Except that > in > >> >>> MCJIT terms the linking hasn't happened, so all the globals and > >> >>> external functions are all zeros at this point. (If I hackily > observe > >> >>> the same code later on I see the linker has appropriately populated > >> >>> these addresses). This makes my nicely annotated code a little > >> >>> unreadable, unfortunately. > >> >>> > >> >>> Does anyone have any suggestions as to how I might get to > disassemble > >> >>> the post-linked code? > >> >> > >> >> my 2 cents: It seems like we need a different event type. Having > >> >> access > >> >> to the object before linking (and relocation?) seems useful, but I > >> >> suspect > >> >> most users (myself included) want the final object after everything > is > >> >> done. > >> >> > >> >> Philip > >> >> > >> >> > >> >> On Wed, Sep 17, 2014 at 2:35 PM, Yaron Keren <yaron.keren at gmail.com> > >> >> wrote: > >> >>>> > >> >>>> Hi, > >> >>>> > >> >>>> You need to call llvm::sys::getHostCPUName() and pass the result to > >> >>>> createTargetMachine() passed to the JIT. This patch should be > >> >>>> applied: > >> >>>> > >> >>>> http://llvm.org/bugs/show_bug.cgi?id=17422 > >> >>>> > >> >>>> Anyhow, the JIT was removed from current code and will not be in > next > >> >>>> LLVM > >> >>>> release. > >> >>>> > >> >>>> Yaron > >> >>>> > >> >>>> > >> >>>> 2014-09-17 22:27 GMT+03:00 Matt Godbolt <matt at godbolt.org>: > >> >>>>> > >> >>>>> Hi Jim, > >> >>>>> > >> >>>>> Thanks for a very quick reply! That indeed does the trick! > >> >>>>> > >> >>>>> Presumably the default has changed in 3.5 to be a "generic" CPU > >> >>>>> instead of the native one? If that's the case I wonder why: > >> >>>>> especially > >> >>>>> when JITting it really only makes sense to target the actual CPU - > >> >>>>> unless I'm missing something? :) > >> >>>>> > >> >>>>> Thanks again, > >> >>>>> > >> >>>>> Matt > >> >>>>> > >> >>>>> On Wed, Sep 17, 2014 at 2:16 PM, Jim Grosbach <grosbach at apple.com > > > >> >>>>> wrote: > >> >>>>>> > >> >>>>>> Hi Matt, > >> >>>>>> > >> >>>>>> I suspect you need to specify the target CPU when you create the > >> >>>>>> JIT. > >> >>>>>> It’s just a method on the builder (e.g., builder.setMCPU(MCPU)). > If > >> >>>>>> you want > >> >>>>>> auto-detection based on the host CPU, sys::getHostCPUName() > returns > >> >>>>>> a > >> >>>>>> value > >> >>>>>> suitable to be passed directly into the builder. > >> >>>>>> > >> >>>>>> -Jim > >> >>>>>> > >> >>>>>>> On Sep 17, 2014, at 11:44 AM, Matt Godbolt <matt at godbolt.org> > >> >>>>>>> wrote: > >> >>>>>>> > >> >>>>>>> Hi guys, > >> >>>>>>> > >> >>>>>>> I just upgraded our JIT system to use llvm 3.5 and noticed one > big > >> >>>>>>> change in our generated code: we don't see any non-destructive > VEX > >> >>>>>>> prefix instructions being emitted any more (vmulsd xmm0, xmm1, > >> >>>>>>> blah) > >> >>>>>>> etc. > >> >>>>>>> > >> >>>>>>> It's long been on my list of things to investigate anyway as I > >> >>>>>>> noticed > >> >>>>>>> llvm didn't emit VZEROUPPER calls either, so I supposed it might > >> >>>>>>> not > >> >>>>>>> be a bad thing to disable vex. > >> >>>>>>> > >> >>>>>>> That being said, try as I might I can't force avx on > >> >>>>>>> (builder.setMCPU("core-avx-i") and/or > >> >>>>>>> builder.setMAttrs(vector<string>{"+avx"});). We're still using > the > >> >>>>>>> old > >> >>>>>>> JIT but I just spiked out a move to MCJIT and I still don't see > >> >>>>>>> the > >> >>>>>>> VEX instructions. > >> >>>>>>> > >> >>>>>>> Was there a deliberate change on the llvm-side to discourage VEX > >> >>>>>>> instructions unless they make a big enough difference (and/or is > >> >>>>>>> VZEROUPPER now emitted?). > >> >>>>>>> > >> >>>>>>> If not, how might I go about digging further into this? > >> >>>>>>> > >> >>>>>>> Many thanks in advance, Matt > >> >>>>>>> > >> >>>>>>> -- > >> >>>>>>> Matt > >> >>>>>>> _______________________________________________ > >> >>>>>>> LLVM Developers mailing list > >> >>>>>>> LLVMdev at cs.uiuc.edu http://llvm.cs.uiuc.edu > >> >>>>>>> http://lists.cs.uiuc.edu/mailman/listinfo/llvmdev > >> >>>>> > >> >>>>> > >> >>>>> > >> >>>>> -- > >> >>>>> Matt > >> >>>>> > >> >>>>> _______________________________________________ > >> >>>>> LLVM Developers mailing list > >> >>>>> LLVMdev at cs.uiuc.edu http://llvm.cs.uiuc.edu > >> >>>>> http://lists.cs.uiuc.edu/mailman/listinfo/llvmdev > >> >>>> > >> >>>> > >> >>> > >> >>> > >> >> > >> >> _______________________________________________ > >> >> LLVM Developers mailing list > >> >> LLVMdev at cs.uiuc.edu http://llvm.cs.uiuc.edu > >> >> http://lists.cs.uiuc.edu/mailman/listinfo/llvmdev > >> > > >> > > >> > >> > >> > >> -- > >> Matt > > > > > > > > -- > Matt >-------------- next part -------------- An HTML attachment was scrubbed... URL: <http://lists.llvm.org/pipermail/llvm-dev/attachments/20140918/c12b7c15/attachment.html>
Thanks again Lang, that all makes sense. In my case the debugabbility is not the primary desire (although it's definitely a nice bonus!). I'm mainly after logging to disc what got compiled and executed for auditing purposes. Much appreciated, Matt :) On Thu, Sep 18, 2014 at 4:15 PM, Lang Hames <lhames at gmail.com> wrote:> Hi Matt, > > CCing the Dev list, as I accidentally dropped them off my last reply. > > Regarding loadObject, that API is very much hypothetical at the moment > (there is a RuntimeDyld::loadObject, but it returns something else). Some > background may make it clearer where I'm thinking of going with this though: > > MCJIT builds on RuntimeDyld. RuntimeDyld is responsible for making object > files in memory (instances of llvm::object::ObjectFile) runnable. It does > this by allocating memory for the sections, applying relocations, and > providing symbol lookup. To a very rough approximation, MCJIT is just: > > class MCJIT { > private: > RuntimeDyld Dyld; > public: > void* getSymbolAddress(StringRef Name) { return > Dyld.getSymbolAddress(Name); } > void addModule(Module *M) { Dyld.loadObject(CodeGenIRToObject(M)); } > }; > > All the interesting parts of MCJIT have to do with module ownership, setting > up the CodeGen pipeline, etc. > > If you're happy to handle codegen and module ownership yourself, you could > actually talk to RuntimeDyld directly, rather than going through MCJIT. > That's what I'm doing in that example, just for the sake of simplicity. For > clients who want to keep using MCJIT we just need to add an API to get at > the underlying Dyld state so that, if they want to, clients can inspect > RuntimeDyld::JITObjects (these don't exist yet either, but are easy to add). > Exactly what that API will look like I'm not sure yet. It may be as simple > as 'RuntimeDyld::JITObject getJITObject(Module *M)' in the end. > > So short version: The loadObject API in the example above doesn't exist yet, > and even if it did you probably wouldn't want to use it. However, there's a > plan to get this kind of information to JIT clients in the future. > > On a related note, the demand for this kind of API usually comes from a > desire to debug either the JIT or the JIT'd code. If we had a proper > debugger registration system (i.e. a way to get relocated Dwarf to JIT > clients and system debuggers), that could be used to find out most of the > interesting things about relocated sections (including their, size, address, > etc). This is also on the drawing board, but waiting for me to find time to > do it. > > Cheers, > Lang. > > On Thu, Sep 18, 2014 at 1:11 PM, Matt Godbolt <matt at godbolt.org> wrote: >> >> Thanks Lang, I guessed as much. I already have the MCDisassembler >> stuff all sorted (we're using it already with the JIT callback >> NotifyFunctionEmitted) and we do in fact use it for non-debug too >> (it's a one-time startup cost for us and it's useful to log to disc >> all this stuff to spot regressions etc). >> >> I really appreciate you taking the time to have a think about this for us >> :) >> >> I realise you're busy but if you have a second or two it seems both >> Philip and I are unaware of the loadObject() style way of JITting. >> We're also using the ExecutionEngine to build our code - can you point >> us both in the direction of how one might use the loadObject style, >> should you think it worthwhile? >> >> Cheers, Matt :) >> >> On Thu, Sep 18, 2014 at 1:46 PM, Lang Hames <lhames at gmail.com> wrote: >> > Hi Matt, >> > >> > "Disassemble" is just pseudocode there, but the MCDisassembler in LLVM >> > does >> > have a reasonably friendly interface. You can look at the code in >> > tools/llvm-mc to see how it's used. >> > >> > DEBUG is just a macro to wrap code so that it only executes for Debug >> > builds. My assumption was that you were disassembling for some sort of >> > debug >> > dump (I've written things like that in the past for debugging the JIT >> > infrastructure). If this is functionality that you want to be compiled >> > into >> > your project all the time you can just drop the reference to DEBUG. >> > >> > - Lang. >> > >> > On Thu, Sep 18, 2014 at 11:00 AM, Matt Godbolt <matt at godbolt.org> wrote: >> >> >> >> Hi Lang, >> >> >> >> Thanks for the reply, I'm glad it sounds like you have a fairly simple >> >> suggested improvement. >> >> >> >> I'm not too familiar with the inner workings of llvm, so apologies if >> >> this is a dumb question; what's the "Disassemble" and DEBUG() parts >> >> doing here? Are these the in the user code? I don't interact with the >> >> RuntimeDyld directly anywhere in my code, so I'm not sure where this >> >> code would go. If it's user code and I can somehow get hold of a >> >> RuntimeDyld then this seems like a good match, as it seems pretty much >> >> what I'm doing in NotifyObjectEmitted already. >> >> >> >> Cheers, Matt :) >> >> >> >> On Thu, Sep 18, 2014 at 12:17 PM, Lang Hames <lhames at gmail.com> wrote: >> >> > Hi Matt, Philip, >> >> > >> >> > You could get the data you want by recording the addresses returned >> >> > by >> >> > the >> >> > allocateCodeSection and allocateDataSection methods on your >> >> > RTDyldMemoryManager, then disassembling those sections after you've >> >> > called >> >> > resolveRelocations. That's a little unsatisfying though. For one >> >> > thing, >> >> > unless you very carefully maintain the association with the original >> >> > object >> >> > via back-channels there will be no way of knowing which section >> >> > belongs >> >> > to >> >> > which object file. >> >> > >> >> > With a bit of cleanup though, we could do something more like this: >> >> > >> >> > const RuntimeDyld::JITObject& JO = RTDyld.loadObject(Object); >> >> > // ... >> >> > RTDyld.resolveRelocations(); >> >> > >> >> > DEBUG( >> >> > for (const RuntimeDyld::JITObject::Section& S : JO.sections()) >> >> > if (S.isText()) >> >> > Disassemble(S.getAddr(), S.getSize()); >> >> > ); >> >> > >> >> > How does that look? >> >> > >> >> > Cheers, >> >> > Lang. >> >> > >> >> > >> >> > On Wed, Sep 17, 2014 at 3:08 PM, Philip Reames >> >> > <listmail at philipreames.com> >> >> > wrote: >> >> >> >> >> >> >> >> >> On 09/17/2014 12:45 PM, Matt Godbolt wrote: >> >> >>> >> >> >>> Great stuff; thanks both! >> >> >>> >> >> >>> I'm also looking to turn my MCJIT conversion spike into our main >> >> >>> use >> >> >>> case. The only thing I'm missing is the ability to get a >> >> >>> post-linked >> >> >>> copy of the generated assembly. >> >> >>> >> >> >>> In JIT I used JITEventListener's NotifyFunctionEmitted and used a >> >> >>> MCDisassembler to disassemble the stream (with my own custom >> >> >>> annotators), and redirected the output to the relevant place for >> >> >>> auditing of our app. >> >> >>> >> >> >>> With MCJIT I notice that NotifyFunctionEmitted is gone >> >> >>> (understandably) and so I hook NotifyObjectEmitted. I then run >> >> >>> through >> >> >>> all the function symbols and dump them as before. Yay. Except that >> >> >>> in >> >> >>> MCJIT terms the linking hasn't happened, so all the globals and >> >> >>> external functions are all zeros at this point. (If I hackily >> >> >>> observe >> >> >>> the same code later on I see the linker has appropriately populated >> >> >>> these addresses). This makes my nicely annotated code a little >> >> >>> unreadable, unfortunately. >> >> >>> >> >> >>> Does anyone have any suggestions as to how I might get to >> >> >>> disassemble >> >> >>> the post-linked code? >> >> >> >> >> >> my 2 cents: It seems like we need a different event type. Having >> >> >> access >> >> >> to the object before linking (and relocation?) seems useful, but I >> >> >> suspect >> >> >> most users (myself included) want the final object after everything >> >> >> is >> >> >> done. >> >> >> >> >> >> Philip >> >> >> >> >> >> >> >> >> On Wed, Sep 17, 2014 at 2:35 PM, Yaron Keren <yaron.keren at gmail.com> >> >> >> wrote: >> >> >>>> >> >> >>>> Hi, >> >> >>>> >> >> >>>> You need to call llvm::sys::getHostCPUName() and pass the result >> >> >>>> to >> >> >>>> createTargetMachine() passed to the JIT. This patch should be >> >> >>>> applied: >> >> >>>> >> >> >>>> http://llvm.org/bugs/show_bug.cgi?id=17422 >> >> >>>> >> >> >>>> Anyhow, the JIT was removed from current code and will not be in >> >> >>>> next >> >> >>>> LLVM >> >> >>>> release. >> >> >>>> >> >> >>>> Yaron >> >> >>>> >> >> >>>> >> >> >>>> 2014-09-17 22:27 GMT+03:00 Matt Godbolt <matt at godbolt.org>: >> >> >>>>> >> >> >>>>> Hi Jim, >> >> >>>>> >> >> >>>>> Thanks for a very quick reply! That indeed does the trick! >> >> >>>>> >> >> >>>>> Presumably the default has changed in 3.5 to be a "generic" CPU >> >> >>>>> instead of the native one? If that's the case I wonder why: >> >> >>>>> especially >> >> >>>>> when JITting it really only makes sense to target the actual CPU >> >> >>>>> - >> >> >>>>> unless I'm missing something? :) >> >> >>>>> >> >> >>>>> Thanks again, >> >> >>>>> >> >> >>>>> Matt >> >> >>>>> >> >> >>>>> On Wed, Sep 17, 2014 at 2:16 PM, Jim Grosbach >> >> >>>>> <grosbach at apple.com> >> >> >>>>> wrote: >> >> >>>>>> >> >> >>>>>> Hi Matt, >> >> >>>>>> >> >> >>>>>> I suspect you need to specify the target CPU when you create the >> >> >>>>>> JIT. >> >> >>>>>> It’s just a method on the builder (e.g., builder.setMCPU(MCPU)). >> >> >>>>>> If >> >> >>>>>> you want >> >> >>>>>> auto-detection based on the host CPU, sys::getHostCPUName() >> >> >>>>>> returns >> >> >>>>>> a >> >> >>>>>> value >> >> >>>>>> suitable to be passed directly into the builder. >> >> >>>>>> >> >> >>>>>> -Jim >> >> >>>>>> >> >> >>>>>>> On Sep 17, 2014, at 11:44 AM, Matt Godbolt <matt at godbolt.org> >> >> >>>>>>> wrote: >> >> >>>>>>> >> >> >>>>>>> Hi guys, >> >> >>>>>>> >> >> >>>>>>> I just upgraded our JIT system to use llvm 3.5 and noticed one >> >> >>>>>>> big >> >> >>>>>>> change in our generated code: we don't see any non-destructive >> >> >>>>>>> VEX >> >> >>>>>>> prefix instructions being emitted any more (vmulsd xmm0, xmm1, >> >> >>>>>>> blah) >> >> >>>>>>> etc. >> >> >>>>>>> >> >> >>>>>>> It's long been on my list of things to investigate anyway as I >> >> >>>>>>> noticed >> >> >>>>>>> llvm didn't emit VZEROUPPER calls either, so I supposed it >> >> >>>>>>> might >> >> >>>>>>> not >> >> >>>>>>> be a bad thing to disable vex. >> >> >>>>>>> >> >> >>>>>>> That being said, try as I might I can't force avx on >> >> >>>>>>> (builder.setMCPU("core-avx-i") and/or >> >> >>>>>>> builder.setMAttrs(vector<string>{"+avx"});). We're still using >> >> >>>>>>> the >> >> >>>>>>> old >> >> >>>>>>> JIT but I just spiked out a move to MCJIT and I still don't see >> >> >>>>>>> the >> >> >>>>>>> VEX instructions. >> >> >>>>>>> >> >> >>>>>>> Was there a deliberate change on the llvm-side to discourage >> >> >>>>>>> VEX >> >> >>>>>>> instructions unless they make a big enough difference (and/or >> >> >>>>>>> is >> >> >>>>>>> VZEROUPPER now emitted?). >> >> >>>>>>> >> >> >>>>>>> If not, how might I go about digging further into this? >> >> >>>>>>> >> >> >>>>>>> Many thanks in advance, Matt >> >> >>>>>>> >> >> >>>>>>> -- >> >> >>>>>>> Matt >> >> >>>>>>> _______________________________________________ >> >> >>>>>>> LLVM Developers mailing list >> >> >>>>>>> LLVMdev at cs.uiuc.edu http://llvm.cs.uiuc.edu >> >> >>>>>>> http://lists.cs.uiuc.edu/mailman/listinfo/llvmdev >> >> >>>>> >> >> >>>>> >> >> >>>>> >> >> >>>>> -- >> >> >>>>> Matt >> >> >>>>> >> >> >>>>> _______________________________________________ >> >> >>>>> LLVM Developers mailing list >> >> >>>>> LLVMdev at cs.uiuc.edu http://llvm.cs.uiuc.edu >> >> >>>>> http://lists.cs.uiuc.edu/mailman/listinfo/llvmdev >> >> >>>> >> >> >>>> >> >> >>> >> >> >>> >> >> >> >> >> >> _______________________________________________ >> >> >> LLVM Developers mailing list >> >> >> LLVMdev at cs.uiuc.edu http://llvm.cs.uiuc.edu >> >> >> http://lists.cs.uiuc.edu/mailman/listinfo/llvmdev >> >> > >> >> > >> >> >> >> >> >> >> >> -- >> >> Matt >> > >> > >> >> >> >> -- >> Matt > >-- Matt