; The structure definition for class Foo. %Foo=type { i32 }
; The default constructor for class Foo. define void @Foo_Create_Default(%Foo* %this) nounwind { %1=getelementptr%Foo,%Foo* %this,i320,i320 storei320,i32* %1 ret void }
;; (omitting the initial prologue and setup code) ;; this is the start of the for loop in Screen::run calling the next method ;; on the iterator for the first time and checking whether it is None (or ;; null in llvm here) ;; %5 contains the pointer to the first component in the vector here %6=icmpeqi64* %5,null bri1%6, label %end, label %forloop end:; preds = %forloop, %start ret void forloop:; preds = %start, %forloop %7=phii64* [ %next_component,%forloop ], [ %5,%start ] ;; here the boxed pointer is retrieved and dereferenced to retrieve the ;; vtable pointer %8=bitcasti64* %7to {}** %self_ptr=load {}*, {}** %8 %9=getelementptrinboundsi64,i64* %7,i641 %vtable_ptr=bitcasti64* %9to void ({}*)*** %vtable=load void ({}*)**, void ({}*)*** %vtable_ptr ;; 3 is the index into the vtable struct, which refers to the draw implementation for this particular struct %trait_method_ptr=getelementptrinbounds void ({}*)*, void ({}*)** %vtable,i643 %trait_method=load void ({}*)*, void ({}*)** %vmethod ;; indirect call to trait method call void %trait_method({}* %self_ptr)
;; retrieve the next object %next_component=calli64* @"<core::slice::iter::Iter<T> as core::iter::traits::iterator::Iterator>::next"({ i64*,i64* }* %iter) %14=icmpeqi64* %next_component,null bri1%14, label %end, label %forloop }
@vtable.screen=privateunnamed_addrconstant ;; the Type of the constant vtable structure { void (%SelectBox*)*,i64,i64, void (%SelectBox*)* } { ;; first entry is the function to drop the object void (%SelectBox*)* @"core::ptr::drop_in_place<test::SelectBox>",;; destructor i6432,;; size i648,;; alignment ;; last in the vtable is the pointer to the SelectBox::draw implementation void (%SelectBox*)* @"<test::SelectBox as test::Draw>::draw" }
;; the vtable for Button is structured basically the same @vtable.button=privateunnamed_addrconstant { void (%Button*)*,i64,i64, void (%Button*)* } { void (%Button*)* @"core::ptr::drop_in_place<test::Button>", i6432,i648, void (%Button*)* @"<test::Button as test::Draw>::draw" }
旧版本的 rust 书还对 rust 中的 vtables 如何工作进行了出色的简洁描述。 似乎较新的版本在内部遵循相同的模式,尽管这已从官方 rust book 中删除。
这篇博文更详细地解释了虚函数表和动态调度以及它们在 rust 与 C++ 中的区别。
define void @Integer_Create(%Integer* %this,i32%value) nounwind { ; you might set up a vtable and associated virtual methods here %1=getelementptr%Integer,%Integer* %this,i320,i320 storei32%value,i32* %1 ret void }