about summary refs log tree commit diff
path: root/compiler/rustc_llvm/llvm-wrapper/RustWrapper.cpp
diff options
context:
space:
mode:
authorflip1995 <philipp.krones@embecosm.com>2022-04-21 14:02:54 +0100
committerPhilipp Krones <hello@philkrones.com>2022-06-14 14:50:52 +0200
commite96e6e2c89265613e136369ccf314c408e1eb002 (patch)
treea393d89ac7cc97ad83826dba9c84586f1d22fdac /compiler/rustc_llvm/llvm-wrapper/RustWrapper.cpp
parente1c1d0f8c2fde787e346420b47c9205f52dc04d6 (diff)
downloadrust-e96e6e2c89265613e136369ccf314c408e1eb002.tar.gz
rust-e96e6e2c89265613e136369ccf314c408e1eb002.zip
Add metadata generation for vtables when using VFE
This adds the typeid and `vcall_visibility` metadata to vtables when the
-Cvirtual-function-elimination flag is set.

The typeid is generated in the same way as for the
`llvm.type.checked.load` intrinsic from the trait_ref.

The offset that is added to the typeid is always 0. This is because LLVM
assumes that vtables are constructed according to the definition in the
Itanium ABI. This includes an "address point" of the vtable. In C++ this
is the offset in the vtable where information for RTTI is placed. Since
there is no RTTI information in Rust's vtables, this "address point" is
always 0. This "address point" in combination with the offset passed to
the `llvm.type.checked.load` intrinsic determines the final function
that should be loaded from the vtable in the
`WholeProgramDevirtualization` pass in LLVM. That's why the
`llvm.type.checked.load` intrinsics are generated with the typeid of the
trait, rather than with that of the function that is called. This
matches what `clang` does for C++.

The vcall_visibility metadata depends on three factors:

1. LTO level: Currently this is always fat LTO, because LLVM only
   supports this optimization with fat LTO.
2. Visibility of the trait: If the trait is publicly visible, VFE
   can only act on its vtables after linking.
3. Number of CGUs: if there is more than one CGU, also vtables with
   restricted visibility could be seen outside of the CGU, so VFE can
   only act on them after linking.

To reflect this, there are three visibility levels: Public, LinkageUnit,
and TranslationUnit.
Diffstat (limited to 'compiler/rustc_llvm/llvm-wrapper/RustWrapper.cpp')
-rw-r--r--compiler/rustc_llvm/llvm-wrapper/RustWrapper.cpp5
1 files changed, 5 insertions, 0 deletions
diff --git a/compiler/rustc_llvm/llvm-wrapper/RustWrapper.cpp b/compiler/rustc_llvm/llvm-wrapper/RustWrapper.cpp
index a2dd0a7bcdc..a52d5340242 100644
--- a/compiler/rustc_llvm/llvm-wrapper/RustWrapper.cpp
+++ b/compiler/rustc_llvm/llvm-wrapper/RustWrapper.cpp
@@ -681,6 +681,11 @@ extern "C" LLVMValueRef LLVMRustMetadataAsValue(LLVMContextRef C, LLVMMetadataRe
   return wrap(MetadataAsValue::get(*unwrap(C), unwrap(MD)));
 }
 
+extern "C" void LLVMRustGlobalAddMetadata(
+    LLVMValueRef Global, unsigned Kind, LLVMMetadataRef MD) {
+  unwrap<GlobalObject>(Global)->addMetadata(Kind, *unwrap<MDNode>(MD));
+}
+
 extern "C" LLVMRustDIBuilderRef LLVMRustDIBuilderCreate(LLVMModuleRef M) {
   return new DIBuilder(*unwrap(M));
 }