llvm-project/clang/test/Modules/cxx-irgen.cpp
David Tenty 196c144d0b [clang][CodeGenCXX] Improve handling of itanium ABI member function alignment requirements
The itanium ABI for certain platforms requires a minimum alignments for
member function pointers to reserve certain bits for distinguishing
virtual and non-virtual functions.

Our implementation of this however depends on the alignment of the
function involved, which may however not reflect the true alignment of
function pointers on certain targets for which the alignment is
independent of the function (e.g. AIX). Worse, the 2-byte alignment
we use may be less than the ABI minimum for the target, and in the case
we are using explicit sections will result in invalid codegen.

This patch attempts to correct this situation by considering the target
alignment of function pointers as part of making the decision about
whether we need to adjust the function alignment to conform to the ABI.
Targets which do not provide the function ptr alignment information
will return a value of 1 when queried and will conservatively retain
the old alignment.

Differential Revision: https://reviews.llvm.org/D147184
2023-07-06 10:35:26 -04:00

78 lines
3.1 KiB
C++

// UNSUPPORTED: target={{.*}}-zos{{.*}}, target={{.*}}-aix{{.*}}
// RUN: rm -rf %t
// RUN: %clang_cc1 -fmodules -fimplicit-module-maps -x objective-c++ -std=c++11 -fmodules-cache-path=%t -I %S/Inputs -triple %itanium_abi_triple -disable-llvm-passes -emit-llvm -o - %s | FileCheck %s
// RUN: %clang_cc1 -fmodules -fimplicit-module-maps -x objective-c++ -std=c++11 -fmodules-cache-path=%t -I %S/Inputs -triple %itanium_abi_triple -disable-llvm-passes -emit-llvm -debug-info-kind=limited -o - %s | FileCheck %s
// FIXME: When we have a syntax for modules in C++, use that.
@import cxx_irgen_top;
CtorInit<int> x;
@import cxx_irgen_left;
@import cxx_irgen_right;
// Keep these two namespace definitions separate; merging them hides the bug.
namespace EmitInlineMethods {
// CHECK-DAG: define linkonce_odr {{(dso_local )?}}[[CC:([0-9_a-z]*cc[ ]+)?]]void @_ZN17EmitInlineMethods1C1fEPNS_1AE(
// CHECK-DAG: declare {{(dso_local )?}}[[CC]]void @_ZN17EmitInlineMethods1A1gEv(
struct C {
__attribute__((used)) void f(A *p) { p->g(); }
};
}
namespace EmitInlineMethods {
// CHECK-DAG: define linkonce_odr {{(dso_local )?}}[[CC]]void @_ZN17EmitInlineMethods1D1fEPNS_1BE(
// CHECK-DAG: define linkonce_odr {{(dso_local )?}}[[CC]]void @_ZN17EmitInlineMethods1B1gEv(
struct D {
__attribute__((used)) void f(B *p) { p->g(); }
};
}
// CHECK-DAG: define available_externally hidden {{.*}}{{signext i32|i32}} @_ZN1SIiE1gEv({{.*}} #[[#ALWAYS_INLINE:]]
int a = S<int>::g();
int b = h();
// CHECK-DAG: define linkonce_odr {{.*}}{{signext i32|i32}} @_Z3minIiET_S0_S0_(i32
int c = min(1, 2);
// CHECK: define available_externally {{.*}}{{signext i32|i32}} @_ZN1SIiE1fEv({{.*}} #[[#ALWAYS_INLINE]]
namespace ImplicitSpecialMembers {
// CHECK-LABEL: define {{.*}} @_ZN22ImplicitSpecialMembers1BC2ERKS0_(
// CHECK: call {{.*}} @_ZN22ImplicitSpecialMembers1AC1ERKS0_(
// CHECK-LABEL: define {{.*}} @_ZN22ImplicitSpecialMembers1BC2EOS0_(
// CHECK: call {{.*}} @_ZN22ImplicitSpecialMembers1AC1ERKS0_(
// CHECK-LABEL: define {{.*}} @_ZN22ImplicitSpecialMembers1CC2ERKS0_(
// CHECK: call {{.*}} @_ZN22ImplicitSpecialMembers1AC1ERKS0_(
// CHECK-LABEL: define {{.*}} @_ZN22ImplicitSpecialMembers1CC2EOS0_(
// CHECK: call {{.*}} @_ZN22ImplicitSpecialMembers1AC1ERKS0_(
// CHECK-LABEL: define {{.*}} @_ZN22ImplicitSpecialMembers1DC2ERKS0_(
// CHECK: call {{.*}} @_ZN22ImplicitSpecialMembers1AC1ERKS0_(
// CHECK-LABEL: define {{.*}} @_ZN22ImplicitSpecialMembers1DC2EOS0_(
// CHECK: call {{.*}} @_ZN22ImplicitSpecialMembers1AC1ERKS0_(
// CHECK-LABEL: define {{.*}} @_ZN20OperatorDeleteLookup1AD0Ev(
// CHECK: call {{.*}}void @_ZN20OperatorDeleteLookup1AdlEPv(
// CHECK-DAG: call {{.*}}i32 @_ZN8CtorInitIiE1fEv(
extern B b1;
B b2(b1);
B b3(static_cast<B&&>(b1));
extern C c1;
C c2(c1);
C c3(static_cast<C&&>(c1));
extern D d1;
D d2(d1);
D d3(static_cast<D&&>(d1));
}
namespace OperatorDeleteLookup {
// Trigger emission of B's vtable and deleting dtor.
// This requires us to know what operator delete was selected.
void g() { f(); }
}
// CHECK: attributes #[[#ALWAYS_INLINE]] = {{.*}} alwaysinline