llvm / llvm/llvm-project

[CIR] Upstream missing support for vtables and virtual bases

Open
#192,330 5 comments 0 reactions 0 assignees View on GitHub
ClangIR
Dominant language
LLVM
Stars
40.5k
Forks
18.7k
PR merge metrics
PR metrics pending

Description

### Overview

Upstream code from the incubator project to replace errorNYI calls in the
CIR codegen implementation related to vtable and virtual base class handling
in the Itanium C++ ABI:
- **Relative vtable layout for virtual base offset**: loading a 32-bit signed
offset (`SInt32Ty` with 4-byte alignment) for relative layout vs
pointer-sized offset for absolute layout in `getVirtualBaseClassOffset`
- **WholeProgramVTables metadata**: calling
`emitVTableTypeMetadata(RD, VTable, VTLayout)` for non-`available_externally`
vtable definitions
- **Explicit instantiation declaration linkage**: checking Microsoft ABI for
`DiscardableODRLinkage`, and for non-MSVC checking
`shouldEmitAvailableExternallyVTable` to choose between
`AvailableExternallyLinkage` and `ExternalLinkage`
- **Combined virtual + non-virtual base offset**: computing a combined offset
by adding the non-virtual offset constant to the virtual offset, casting to
byte pointer, applying `PtrStrideOp`, and casting back
- **Devirtualized destructor calls**: using
`CIRGenCallee::forDirect(CGM.GetAddrOfFunction(...))` to call the devirtualized
destructor directly instead of going through the vtable

Upstream NYI locations:
- `CIRGenItaniumCXXABI.cpp` — `getVirtualBaseClassOffset`: relative layout
- `CIRGenItaniumCXXABI.cpp` — `emitVTableDefinitions`: WholeProgramVTables
- `CIRGenVTables.cpp` — `getVTableLinkage`: explicit instantiation declaration
- `CIRGenClass.cpp` — `applyNonVirtualAndVirtualOffset`: both virtual and
non-virtual offset present
- `CIRGenExprCXX.cpp` — `emitCXXMemberOrOperatorMemberCallExpr`: devirtualized
destructor call

### Suggested minimal test case

```cpp
struct VBase { virtual ~VBase() {} int vb; };
struct Middle : virtual VBase { int m; };
struct Derived : Middle { int d; };

void test_virtual_base_cast(Derived *d) {
VBase *vb = d;
vb->vb = 42;
}

struct Final final : VBase {
~Final() override {}
};

void test_devirtualized_dtor(Final *f) {
delete f;
}
```

### Existing incubator tests

- `clang/test/CIR/CodeGen/virtual-base-cast.cpp`
- `clang/test/CIR/CodeGen/vbase.cpp`
- `clang/test/CIR/CodeGen/vtable-available-externally.cpp`
- `clang/test/CIR/CodeGen/vtable-thunk-virtual-inheritance.cpp`
- `clang/test/CIR/CodeGen/virtual-destructor-calls.cpp`
- `clang/test/CIR/CodeGen/dynamic-cast-relative-layout.cpp`

Contributor guide

Open the contributing guide

Research direction

Start by reading the five named CIR files at their listed NYI locations and run the existing incubator tests, especially virtual-base-cast.cpp and virtual-destructor-calls.cpp. Compare the upstream implementations for each case and verify that the listed vtable, virtual-base-offset, linkage, and devirtualized-destructor tests pass when all five locations are supported.

Written by the indexing model from the issue text.

Assessment

Tech stack
cpp
Domain
compilers
Issue type
Feature
Difficulty
4/5
Estimated time
3-5 days
Activity status
Quiet
Clarity
Mostly clear
Newbie friendliness
52/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.