[LLVMdev] Mapping of class derivated and interfaces

David Blaikie dblaikie at gmail.com
Thu Aug 25 23:20:14 PDT 2005


> 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------




More information about the llvm-dev mailing list