[llvm-dev] Implementing a VTable in LLVM

Mukul Rathi via llvm-dev llvm-dev at lists.llvm.org
Wed Jun 10 12:12:09 PDT 2020


Thanks David, that makes sense, I’d hadn’t realised the function had to be known at compile-time.

It now works as expected, thank you!

Mukul




> On 10 Jun 2020, at 18:35, David Blaikie <dblaikie at gmail.com> wrote:
> 
> 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 <mailto: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 <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 <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 <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 <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 <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 <mailto:llvm-dev at lists.llvm.org>
> https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-dev <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/7b4654ed/attachment.html>


More information about the llvm-dev mailing list