[Help] How can we call an object's virtual function inside IR?

Dear experts,

I am learning llvm by reading documents and have a question to ask.

The following is the example of code generation that I created.

[[a [10.00]] > [3.00]]
; ModuleID = 'ExprF'

define i1 @expr(double* %record) {
entry:
        %0 = getelementptr double* %record, i32 0 ;
<double*> [#uses=1]
        %1 = load double* %0 ; <double> [#uses=1]
        %2 = frem double %1, 1.000000e+01 ; <double> [#uses=1]
        %3 = fcmp ogt double %2, 3.000000e+00 ; <i1> [#uses=1]
        ret i1 %3
}

Now, I would like to change the type of the argument from double * to
a pointer to an object ( C++ class ) like ClassA * %record, and inside
the function body, I would like to call the virtual functions of the
ClassA %record object to get the value
for the evaluation. As far as I understand, we can get the members of
a struct from getElementPtr function, but is it possible
to call a virtual function of an object to get the value?

Could you explain on how to do this?

Thank you very much for your help in advance. :slight_smile:

Best regards,

Gyounghwa Kim

Hi Gyounghwa Kim, try pasting C++ code into http://llvm.org/demo/
in order to see the LLVM IR that llvm-g++ turns it into. That way
you will see how this can be done.

Best wishes,

Duncan.

LLVM has no direct support for class hierarchies, virtual functions,
templates or anything of that support. It is very low-level. The
frontend is responsible for implementing the C++ object model in
terms of LLVM constructs. This the frontend will have to generate
vtables, indirect calls, etc. to implement virtual function calls.

This is all highly compiler-dependent. Everyone does it a little
bit differently. Using the llvm-g++ online demo as Duncan suggests
will show you how g++ implements this stuff.

                               -Dave

Hi Gyounghwa Kim,

First of all, thank you very much for your answer.
I tried your sugestion and found out that it is not what I wanted.
What I have to do is call a native C function from inside this
generated function.
Is there any way that we can find and call native C functions not
created by LLVM IR?

You can insert a declaration of the function into the IR, then call
it. Of course, for this to work you need to link in the native function
when running. If you are building a standalone application then this
is no problem. If you are running the IR using the JIT then it is also
possible, hopefully someone else will explain how.

I am asking this question because I want to fix this example to get a
class member variable (ClassA * %record) and call the member function
of it from inside LLVM IR.

You are allowed to call a pointer, i.e. a function declaration is not
required. So you can just load the pointer out of %record, bitcast it
to the right function type, and call it.

Ciao,

Duncan.

PS: Please reply to the list and not to me personally. That way, others
may answer, and the discussion is archived which may help in the future
if someone else has the same question.

If LLVM IR cannot access the member

If you are running the IR using the JIT:

1. If the function is exported from the executable itself, or if it is
in a static library linked with the executable using the -rdynamic
flag, then you can insert a declaration of the function into the IR
and then call it.

2. Otherwise, you can insert a declaration of the function into the
IR, call ExecutionEngine::addGlobalMapping with the llvm::Function
object and a native function pointer to link the declaration to the
actual function, and then call it.

Dear Duncan,

Thank you very much for your answer.
Actually, I was able to call a C function from LLVM IR, now I try to
call a class member function from inside IR and tried to follow your
instructions.

1. I am trying to create a ConstantInt pointer to the class member function.
2. Covert it to a Function Pointer and call it from IRBuilder.

However, I can't figure out what to pass as the value of the pointer
to the member function.
Could you help me with this?

My code parts are shown below.

using namespace llvm;

class Record
{
        public:
                Record(){value=0;}
                Record(int a){value=a;}
                int getValue(){return value;}
                void setValue(int a){value=a;}
                int addOneToValue(){return value+1;}
        private:
                int value;
};

typedef int (Record::*RecMemFunc)();

int main(int argc, char*args)
{
        Record *rec= new Record(5);
        int y = rec->addOneToValue();
        printf("Hi y = %d\n", y);

        RecMemFunc rp = &Record::addOneToValue;
        y = (rec->*rp)();
        printf("Hi y = %d\n", y);

        Constant* constInt = ConstantInt::get(Type::Int64Ty, (int64)thePointer);
        Value* constPtr = ConstantExpr::getIntToPtr(constInt,
PointerType::getUnqual(Type::Int32Ty));
        //builder.CreateCall(myFunction, constPtr);
:
:
}

What will be the value to pass in instead of thePointer???

Thank you very much for your help in advance. :slight_smile:

- Gyounghwa