Hi! i'm tring to figure out how classes and dependencies can be mapped to llvm. I've read on docs that nesting can be used: class base { int Y; }; class derived : base { short Z; }; becomes: %base = type { int } %derived = type { %base, short } That's ok, but now the question is: how do i encode a function that takes "base" type so that it also takes "derived" ? For example: // simple function that takes a base class function myFunc(base* a) { ... } now, i don't think i can just pass a %derived type class to that function, becouse pointers are of different types. Am i right? And if i could cast it, the "base" member of "derived" class is at right position in memory so that myFunc could work? And doesn't the cast hide important information for the optimizer? In general, how should this thing be mapped on llvm? Another question: What's the best way in general to implement interfaces (like java ones for example)? Any hint ? I'm just in the dark with this. I hope those questions wasn't too stupid. And btw LLVM is really an impressive tool. Great job :)
> Hi! i'm tring to figure out how classes and dependencies > can be mapped to llvm. > [snip] > how do i encode a function that takes "base" type > so that it also takes "derived" ?You'll notice that your function doesn't take an object of type base, but a pointer to it. This is important - in a language such as LLVM where actual structures can be passed it's quite possible to pass the actual object (whereas in a language like Java where one can only work with pointers to objects it's quite impossible). In any case when you want to obtain a base pointer to a "derived" object (where derivation is implemented as you showed - with nesting) it's simply a matter of using getelementptr to obtain a pointer to the nested base object and using that. One of the easiest ways to explore how this can be done (unless you really want to try to invent it for yourself, which is well worth trying to get a better understanding of OOP implementation and LLVM) is to try some simple C++ snippets with LLVM and look at the resulting assembly. For example: struct base { int i; }; struct derived: base { int j; }; int test_derived(int (*func)(base*), derived* d) { return func(d); } Looks like this: %struct.base = type { int } %struct.derived = type { %struct.base, int } int %test_derived(int (*)(base*), derived*)(int (%struct.base*)* %func, %struct.derived* %d) { entry: %tmp.3 = getelementptr %struct.derived* %d, int 0, uint 0 ; <%struct.base*> [#uses=1] %tmp.1 = call int %func( %struct.base* %tmp.3 ) ; <int> [#uses=1] ret int %tmp.1 } A simple call to getelementptr to obtain the first field (uint 0) inside the first element (int 0) in the struct.derived object pointed to by 'd'. That value is then passed to the function. (Note: This specific example uses a function pointer to stop the LLVM optimizer from attempting to inline the function call (if it did, this example would be wholely uninteresting and not demonstrate the issue))> What's the best way in general to implement interfaces (like java ones > for example)? Any hint ? I'm just in the dark with this.Well that's really just a specific manifestation of implementing virtual function calls basically. The key to this issue is virtual function tables or vtables. Again you can explore this by looking at how LLVM compiles some appropriate C++ examples, though it's a little hairier. Try feeding the following example through llvmgcc -S struct base { virtual float foo() = 0; }; struct derived: base { float foo() { return 4.5; } }; float test(base* b) { return b->foo(); } float test_derived() { derived d; return test(&d); } The resulting LLVM assembly is a little more involved so I won't include it here. It does also contain some code that isn't strictly necessary to implement just these virtual calls (C++ requires "type info" (among other things) for any type with at least one virtual function)> And btw LLVM is really an impressive tool.That it is. David -- -----BEGIN GEEK CODE BLOCK----- Version: 3.1 GCS d+@ s++: a-- C++++ ULS++ P L++ !E W++ N+ o? K? w(+) O? M@ V? PS+ PE@ Y+ PGP- t(+) 5 X+ R tv+ b+ DI++ D++ G+ e h! r y-(-) ------END GEEK CODE BLOCK------
> In any case when you > want to obtain a base pointer to a "derived" object (where derivation > is implemented as you showed - with nesting) it's simply a matter of > using getelementptr to obtain a pointer to the nested base object and > using that.Umm ok, but i've the strange feeling that i'm missing something.. First a simple question: getelementptr with index 0 just give me the same pointer, right? Ok, if it's so the example you gave me worked becouse the first element of "derived" is the "base" portion, thus having the same pointer. But what if it was not the first? For example with multiple derivation only one class can be in the first position: %base1 = type { int } %base2 = type { sbyte } %derived = type { %base1, %base2, long } void myProc(base2 obj) { } Now if you use get elementptr to obtain "base2" member of "derived" to pass it to myProc, then you're basically passing a different pointer, breaking instance identity among other things: public Derived global_var = new ....; main() { myProc(d); } void myProc(base2 obj) { boolean b = (global_var == obj); // this would be false! Derived alias = (Derived) obj; // this would break too btw } So what am i missing ? maybe to deal with multiple ereditation one need some more "manadgement" code ? and does the optimizer still "see" all relations and code features? Thank you!
We also have an ongoing project to write a JVM-bytecode-to-LLVM front- end (it already has a lot of working functionality but is missing support for exceptions and JNI). If you're interested in how it lays out Java objects, check out the project "llvm-java" (similar to how you check out "llvm-test"), and see the file "docs/object-layout.txt". --Vikram http://www.cs.uiuc.edu/~vadve http://llvm.cs.uiuc.edu/ On Aug 26, 2005, at 1:20 AM, David Blaikie wrote:>> Hi! i'm tring to figure out how classes and dependencies >> can be mapped to llvm. >> [snip] >> how do i encode a function that takes "base" type >> so that it also takes "derived" ? >> > > You'll notice that your function doesn't take an object of type base, > but a pointer to it. This is important - in a language such as LLVM > where actual structures can be passed it's quite possible to pass the > actual object (whereas in a language like Java where one can only work > with pointers to objects it's quite impossible). In any case when you > want to obtain a base pointer to a "derived" object (where derivation > is implemented as you showed - with nesting) it's simply a matter of > using getelementptr to obtain a pointer to the nested base object and > using that. > > One of the easiest ways to explore how this can be done (unless you > really want to try to invent it for yourself, which is well worth > trying to get a better understanding of OOP implementation and LLVM) > is to try some simple C++ snippets with LLVM and look at the resulting > assembly. > > For example: > > struct base { int i; }; > struct derived: base { int j; }; > int test_derived(int (*func)(base*), derived* d) { > return func(d); > } > > Looks like this: > > %struct.base = type { int } > %struct.derived = type { %struct.base, int } > int %test_derived(int (*)(base*), derived*)(int (%struct.base*)* > %func, %struct.derived* %d) { > entry: > %tmp.3 = getelementptr %struct.derived* %d, int 0, uint 0 ; > <%struct.base*> [#uses=1] > %tmp.1 = call int %func( %struct.base* %tmp.3 ) ; <int> > [#uses=1] > ret int %tmp.1 > } > > A simple call to getelementptr to obtain the first field (uint 0) > inside the first element (int 0) in the struct.derived object pointed > to by 'd'. That value is then passed to the function. > > (Note: This specific example uses a function pointer to stop the LLVM > optimizer from attempting to inline the function call (if it did, this > example would be wholely uninteresting and not demonstrate the issue)) > > >> What's the best way in general to implement interfaces (like java >> ones >> for example)? Any hint ? I'm just in the dark with this. >> > > Well that's really just a specific manifestation of implementing > virtual function calls basically. The key to this issue is virtual > function tables or vtables. > > Again you can explore this by looking at how LLVM compiles some > appropriate C++ examples, though it's a little hairier. Try feeding > the following example through llvmgcc -S > > struct base { > virtual float foo() = 0; > }; > > struct derived: base { > float foo() { return 4.5; } > }; > > float test(base* b) { > return b->foo(); > } > > float test_derived() { > derived d; > return test(&d); > } > > The resulting LLVM assembly is a little more involved so I won't > include it here. It does also contain some code that isn't strictly > necessary to implement just these virtual calls (C++ requires "type > info" (among other things) for any type with at least one virtual > function) > > >> And btw LLVM is really an impressive tool. >> > > That it is. > > David > -- > -----BEGIN GEEK CODE BLOCK----- > Version: 3.1 > GCS d+@ s++: a-- C++++ ULS++ P L++ !E W++ N+ o? K? w(+) O? M@ V? PS > + PE@ > Y+ PGP- t(+) 5 X+ R tv+ b+ DI++ D++ G+ e h! r y-(-) > ------END GEEK CODE BLOCK------ > > _______________________________________________ > LLVM Developers mailing list > LLVMdev at cs.uiuc.edu http://llvm.cs.uiuc.edu > http://lists.cs.uiuc.edu/mailman/listinfo/llvmdev >
On Thu, 25 Aug 2005, Nicola Lugato wrote:> Another question: > What's the best way in general to implement interfaces (like java ones > for example)? Any hint ? I'm just in the dark with this.Along with what the others said, you might find these notes useful: http://nondot.org/sabre/LLVMNotes/MSILObjectModel1.txt http://nondot.org/sabre/LLVMNotes/MSILObjectModel2.txt Which includes interfaces. Alkis may have notes for llvm-java as well. -Chris -- http://nondot.org/sabre/ http://llvm.org/
Alkis Evlogimenos
2005-Aug-28 11:41 UTC
[LLVMdev] Mapping of class derivated and interfaces
On Sat, 2005-08-27 at 17:36 -0500, Chris Lattner wrote:> On Thu, 25 Aug 2005, Nicola Lugato wrote: > > Another question: > > What's the best way in general to implement interfaces (like java ones > > for example)? Any hint ? I'm just in the dark with this. > > Along with what the others said, you might find these notes useful: > http://nondot.org/sabre/LLVMNotes/MSILObjectModel1.txt > http://nondot.org/sabre/LLVMNotes/MSILObjectModel2.txt > > Which includes interfaces. Alkis may have notes for llvm-java as well.Indeed :-) http://illuvium.com/cgi-bin/cvsweb.cgi/llvm-java/docs/object-layout.txt?rev=1.9 -- Alkis