Skip to content

Commit 0255897

Browse files
committed
[CIR][Test] Add divergence tests for vtable emission issues
This commit adds three tests documenting divergences between CIR and CodeGen in vtable emission. All tests verify that CIR should emit the same attributes as CodeGen but currently fails to do so. **Tests Added:** 1. vtable-constant-divergence.cpp - Documents missing 'constant' attribute 2. vtable-unnamed-addr-divergence.cpp - Documents missing 'unnamed_addr' attribute 3. vtable-comdat-divergence.cpp - Documents missing 'comdat' attribute **Issue:** CIR emits vtables with 'global' linkage: @_ZTV4Base = linkonce_odr global { [3 x ptr] } ... CodeGen correctly emits them as 'constant' with additional attributes: @_ZTV4Base = linkonce_odr unnamed_addr constant { [3 x ptr] } ... comdat **Root Cause:** In CIRGenModule.cpp:4081, createOrReplaceCXXRuntimeVariable() calls createGlobalOp() without passing isConstant=true parameter. Additionally, the unnamed_addr and comdat attributes are not being set. **Impact:** 1. Vtables placed in .data instead of .rodata section 2. Security vulnerability - writable vtables enable exploits 3. Missed optimization opportunities from unnamed_addr merging 4. Incorrect linker behavior without comdat groups 5. Diverges from CodeGen without justification All tests are marked XFAIL until the fixes are implemented. Each test uses FileCheck to verify both CIR and CodeGen outputs, with the CIR check failing due to the missing attributes. Test Plan: Build and verify tests fail as expected (documenting divergence): bin/llvm-lit -v ../../clang/test/CIR/CodeGen/vtable-*-divergence.cpp
1 parent 26199f0 commit 0255897

File tree

3 files changed

+108
-0
lines changed

3 files changed

+108
-0
lines changed
Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
// RUN: %clang_cc1 -triple x86_64-unknown-linux-gnu -fclangir -emit-llvm %s -o %t-cir.ll
2+
// RUN: %clang_cc1 -triple x86_64-unknown-linux-gnu -emit-llvm %s -o %t-codegen.ll
3+
// RUN: FileCheck --check-prefix=CIR --input-file=%t-cir.ll %s
4+
// RUN: FileCheck --check-prefix=CODEGEN --input-file=%t-codegen.ll %s
5+
6+
// XFAIL: *
7+
8+
// This test documents a divergence between CIR and CodeGen:
9+
// CIR does not emit 'comdat' attribute on vtables.
10+
// This is a bug that needs to be fixed.
11+
//
12+
// Expected (CodeGen):
13+
// @_ZTV4Base = linkonce_odr unnamed_addr constant { [3 x ptr] } ... comdat
14+
//
15+
// Actual (CIR):
16+
// @_ZTV4Base = linkonce_odr global { [3 x ptr] } ...
17+
//
18+
// The vtable should be marked with 'comdat' because:
19+
// 1. Enables proper handling of linkonce_odr definitions across translation units
20+
// 2. Ensures the linker can safely discard duplicate vtable definitions
21+
// 3. Required for correct C++ semantics with inline/template classes
22+
// 4. CodeGen has always emitted them with this attribute
23+
24+
class Base {
25+
public:
26+
virtual void foo() {}
27+
};
28+
29+
void test() {
30+
Base b;
31+
b.foo();
32+
}
33+
34+
// Both should emit comdat attribute
35+
// CIR: @_ZTV4Base = {{.*}}, comdat
36+
// CODEGEN: @_ZTV4Base = {{.*}}, comdat
Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
// RUN: %clang_cc1 -triple x86_64-unknown-linux-gnu -fclangir -emit-llvm %s -o %t-cir.ll
2+
// RUN: %clang_cc1 -triple x86_64-unknown-linux-gnu -emit-llvm %s -o %t-codegen.ll
3+
// RUN: FileCheck --check-prefix=CIR --input-file=%t-cir.ll %s
4+
// RUN: FileCheck --check-prefix=CODEGEN --input-file=%t-codegen.ll %s
5+
6+
// XFAIL: *
7+
8+
// This test documents a divergence between CIR and CodeGen:
9+
// CIR emits vtables as 'global' (mutable) instead of 'constant' (immutable).
10+
// This is a bug that needs to be fixed.
11+
//
12+
// Expected (CodeGen):
13+
// @_ZTV4Base = linkonce_odr unnamed_addr constant { [3 x ptr] } ...
14+
//
15+
// Actual (CIR):
16+
// @_ZTV4Base = linkonce_odr global { [3 x ptr] } ...
17+
//
18+
// The vtable should be marked as 'constant' because:
19+
// 1. Vtables are never modified at runtime
20+
// 2. They should be placed in .rodata (read-only data section)
21+
// 3. Writable vtables are a security vulnerability
22+
// 4. CodeGen has always emitted them as constant
23+
24+
class Base {
25+
public:
26+
virtual void foo() {}
27+
};
28+
29+
void test() {
30+
Base b;
31+
b.foo();
32+
}
33+
34+
// Both should emit vtable as constant
35+
// CIR: @_ZTV4Base = linkonce_odr unnamed_addr constant
36+
// CODEGEN: @_ZTV4Base = linkonce_odr unnamed_addr constant
Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
// RUN: %clang_cc1 -triple x86_64-unknown-linux-gnu -fclangir -emit-llvm %s -o %t-cir.ll
2+
// RUN: %clang_cc1 -triple x86_64-unknown-linux-gnu -emit-llvm %s -o %t-codegen.ll
3+
// RUN: FileCheck --check-prefix=CIR --input-file=%t-cir.ll %s
4+
// RUN: FileCheck --check-prefix=CODEGEN --input-file=%t-codegen.ll %s
5+
6+
// XFAIL: *
7+
8+
// This test documents a divergence between CIR and CodeGen:
9+
// CIR does not emit 'unnamed_addr' attribute on vtables.
10+
// This is a bug that needs to be fixed.
11+
//
12+
// Expected (CodeGen):
13+
// @_ZTV4Base = linkonce_odr unnamed_addr constant { [3 x ptr] } ...
14+
//
15+
// Actual (CIR):
16+
// @_ZTV4Base = linkonce_odr global { [3 x ptr] } ...
17+
//
18+
// The vtable should be marked as 'unnamed_addr' because:
19+
// 1. The address of a vtable is never taken or used for identity comparison
20+
// 2. This allows the linker to merge duplicate vtables across translation units
21+
// 3. Reduces binary size and improves performance
22+
// 4. CodeGen has always emitted them with this attribute
23+
24+
class Base {
25+
public:
26+
virtual void foo() {}
27+
};
28+
29+
void test() {
30+
Base b;
31+
b.foo();
32+
}
33+
34+
// Both should emit unnamed_addr attribute
35+
// CIR: @_ZTV4Base = linkonce_odr unnamed_addr
36+
// CODEGEN: @_ZTV4Base = linkonce_odr unnamed_addr

0 commit comments

Comments
 (0)