[LLVMdev] Parametric polymorphism

DeLesley SpamBox delesley.spambox at googlemail.com
Wed Feb 18 09:32:39 PST 2009


> I think the problem is deeper than that, in that LLVM has no official
> concept of a subtype, so I don't see how the idea of polymorphism
> could be defined in it.

Parametric polymorphism is different from subtype polymorphism; you
can have one without the other.  Parametric polymorphism just means
that you can use type variables (like T) in the IR, which are later
instantiated
to actual types.

>> max <T extends Comparable>(T a, T b) {
>>  if (a > b) return a; else return b;
>> }
>>
>
> Also, "Comparable" implies some kind of function associated with the
> type in order to actually perform it...

True, but I'm not worried about that; method tables are easy to add once type
substitutions are allowed.  Dropping down to a mythical low-level language
that I call template C, we would have:

  struct ComparableDict<T> {
    bool (*equals)(T a, T b);
    bool (*leq)(T a, T b);
    bool (*geq)(T a, T b);
  }

  T max<T>(ComparableDict<T>* dict, T a, T b) {
    if ((*dict->geq)(a,b)) return a; else return b;
  }

This mechanism duplicates the dictionary-passing used in Haskell type classes.
The correct dictionary for any given type is inferred by the
high-level language, but
it is passed as an argument at the llvm level.

Notice that there is no subtyping.  The only things I need from llvm are:

(1) The ability to define a parameterized type, e.g. ComparableDict<T>.
(2) The ability to define a function that is parameterized by a type,
e.g. max<T>.
(3) The ability to substitute a type for a type variable, e.g. specialize max
     to max<int>.

In order to get good performance, you will need to instantiate max
with both a type
T, and the dictionary for T.  In other words, max must be partially
evaluated with
respect to a given type -and- a given dictionary.  While this is
obviously a complication,
partial evaluation with respect to constant arguments is something that llvm is
already quite capable of.  If there is not a pass that does it
already, I could easily write
one.  The problem is that I have no way of declaring a parameterized type or a
parameterized function within the llvm IR.

Note also that when I talk about ``types'', I am referring to
low-level llvm types --
scalars, records, pointers, etc.  I'm not referring to complex
functional types with pattern
matching as found in Haskell, or complex OOP classes as found in JVM
or .NET with
constructors, methods, and all that jazz.

  -DeLesley



More information about the llvm-dev mailing list