[llvm-dev] Implementing a VTable in LLVM

David Blaikie via llvm-dev llvm-dev at lists.llvm.org
Wed Jun 10 10:35:43 PDT 2020


I'd bet that CreateLoad is returning non-null but the dyn_cast is returning
null.

llvm::Function represents a specific function known at compile-time. You
have loaded a function pointer (void (%Foo*, i32)*) not a function itself.
You shuold pass that (function pointer) to IRBuilder createCall - no need
for the dyn_cast.

On Wed, Jun 10, 2020 at 10:01 AM Mukul Rathi via llvm-dev <
llvm-dev at lists.llvm.org> wrote:

> Hi all,
>
> I’ve been working on a Java-esque object-oriented language Bolt that
> targets LLVM IR.  I’m agonisingly close to getting a virtual table working,
> and was hoping one of you could point out the gap in my understanding. I’ve
> linked the C++ code snippets relevant to the vtable below.
>
>
> Example IR generated (partially displayed below):
> https://github.com/mukul-rathi/bolt/blob/vtable/examples/vtable/foo.ll
> And the Bolt source code that compiles to it-
> https://github.com/mukul-rathi/bolt/blob/vtable/examples/vtable/foo.bolt
>
>
> I currently have code (
> https://github.com/mukul-rathi/bolt/blob/vtable/src/llvm-backend/llvm_ir_codegen/class_codegen.cc#L57:L77
> )
>  that generates the following global Vtable for a class Foo:
>
> %_VtableFoo = type { void (%Foo*, i32)* }
> %Foo = type { %_VtableFoo*, %pthread_t*, i32, i32, i32, i32 }
>
> @_VtableFoo = common global %_VtableFoo { void (%Foo*, i32)* @_Foo__setgi
> }
>
> The code for instantiating the table seems to generate the correct IR
> (create an object, store a pointer to its vtable) -
> https://github.com/mukul-rathi/bolt/blob/vtable/src/llvm-backend/llvm_ir_codegen/expr_codegen.cc#L66:L89
>
> entry:
> %_var_y0 = alloca %Foo*
> %0 = call i8* @malloc(i64 ptrtoint (%Foo* getelementptr (%Foo, %Foo* null,
> i64 1) to i64))
> %1 = bitcast i8* %0 to %Foo*
> %2 = getelementptr inbounds %Foo, %Foo* %1, i32 0, i32 0
> store %_VtableFoo* @_VtableFoo, %_VtableFoo** %2
>
> The issue is when it comes to actually calling the method. Up to this
> point, the code generates the expected IR (
> https://github.com/mukul-rathi/bolt/blob/vtable/src/llvm-backend/llvm_ir_codegen/expr_codegen.cc#L188:L202
> )
>
>
> %5 = load %Foo*, %Foo** %_var_y0
> %6 = getelementptr inbounds %Foo, %Foo* %5, i32 0, i32 0
> %7 = load %_VtableFoo*, %_VtableFoo** %6
> %8 = getelementptr inbounds %_VtableFoo, %_VtableFoo* %7, i32 0, i32 0
> %9 = load void (%Foo*, i32)*, void (%Foo*, i32)** %8
>
>
> However, the builder->CreateLoad instruction corresponding to the line
> with %9 returns null:
> llvm::Function *calleeMethod = llvm::dyn_cast<llvm::Function>(builder->
> CreateLoad(calleeMethodPtr));
> So if I then try to execute the following builder->CreateCall function I
> end up with a segmentation fault since calleeMethod is null:
>
> builder->CreateCall(calleeMethod, argVals);
>
>
> Under what circumstances would builder->CreateLoad return null?  Is the
> global vTable's memory not allocated correctly? Or have I been approaching
> this incorrectly - is there another method in the C++ API that I should be
> using for indirect function calls?
>
> I’d really appreciate any assistance.
>
> Thanks,
>
> Mukul
>
>
>
>
>
>
> _______________________________________________
> LLVM Developers mailing list
> llvm-dev at lists.llvm.org
> https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-dev
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.llvm.org/pipermail/llvm-dev/attachments/20200610/d9e0a4b7/attachment.html>


More information about the llvm-dev mailing list