Skip to content

Commit

Permalink
[Clang] Directly create opaque pointers
Browse files Browse the repository at this point in the history
In CGTypes, directly create opaque pointers, without computing the
LLVM element type. This is not as straightforward as I though it
would be, because apparently computing the LLVM type also causes a
number of side effects.

In particular, we no longer produce diagnostics like -Wpacked for
typed (only) behind pointers, because we no longer depend on their
layout.

Differential Revision: https://reviews.llvm.org/D152505
  • Loading branch information
nikic committed Jun 15, 2023
1 parent 742040a commit 09d6ee7
Show file tree
Hide file tree
Showing 6 changed files with 55 additions and 83 deletions.
25 changes: 6 additions & 19 deletions clang/lib/CodeGen/CodeGenTypes.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -675,19 +675,15 @@ llvm::Type *CodeGenTypes::ConvertType(QualType T) {
case Type::RValueReference: {
const ReferenceType *RTy = cast<ReferenceType>(Ty);
QualType ETy = RTy->getPointeeType();
llvm::Type *PointeeType = ConvertTypeForMem(ETy);
unsigned AS = getTargetAddressSpace(ETy);
ResultType = llvm::PointerType::get(PointeeType, AS);
ResultType = llvm::PointerType::get(getLLVMContext(), AS);
break;
}
case Type::Pointer: {
const PointerType *PTy = cast<PointerType>(Ty);
QualType ETy = PTy->getPointeeType();
llvm::Type *PointeeType = ConvertTypeForMem(ETy);
if (PointeeType->isVoidTy())
PointeeType = llvm::Type::getInt8Ty(getLLVMContext());
unsigned AS = getTargetAddressSpace(ETy);
ResultType = llvm::PointerType::get(PointeeType, AS);
ResultType = llvm::PointerType::get(getLLVMContext(), AS);
break;
}

Expand Down Expand Up @@ -764,15 +760,9 @@ llvm::Type *CodeGenTypes::ConvertType(QualType T) {
break;
}

case Type::ObjCObjectPointer: {
// Protocol qualifications do not influence the LLVM type, we just return a
// pointer to the underlying interface type. We don't need to worry about
// recursive conversion.
llvm::Type *T =
ConvertTypeForMem(cast<ObjCObjectPointerType>(Ty)->getPointeeType());
ResultType = T->getPointerTo();
case Type::ObjCObjectPointer:
ResultType = llvm::PointerType::getUnqual(getLLVMContext());
break;
}

case Type::Enum: {
const EnumDecl *ED = cast<EnumType>(Ty)->getDecl();
Expand All @@ -786,18 +776,15 @@ llvm::Type *CodeGenTypes::ConvertType(QualType T) {
}

case Type::BlockPointer: {
const QualType FTy = cast<BlockPointerType>(Ty)->getPointeeType();
llvm::Type *PointeeType = CGM.getLangOpts().OpenCL
? CGM.getGenericBlockLiteralType()
: ConvertTypeForMem(FTy);
// Block pointers lower to function type. For function type,
// getTargetAddressSpace() returns default address space for
// function pointer i.e. program address space. Therefore, for block
// pointers, it is important to pass the pointee AST address space when
// calling getTargetAddressSpace(), to ensure that we get the LLVM IR
// address space for data pointers and not function pointers.
const QualType FTy = cast<BlockPointerType>(Ty)->getPointeeType();
unsigned AS = Context.getTargetAddressSpace(FTy.getAddressSpace());
ResultType = llvm::PointerType::get(PointeeType, AS);
ResultType = llvm::PointerType::get(getLLVMContext(), AS);
break;
}

Expand Down
10 changes: 5 additions & 5 deletions clang/test/CodeGenCXX/matrix-type-builtins.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -31,20 +31,20 @@ void test_transpose_template1() {

void test_transpose_template2(MyMatrix<double, 7, 6> &M) {
// CHECK-LABEL: define{{.*}} void @_Z24test_transpose_template2R8MyMatrixIdLj7ELj6EE(
// CHECK: call void @_Z9transposeIdLj7ELj6EE8MyMatrixIT_XT1_EXT0_EERKS0_IS1_XT0_EXT1_EE(ptr sret(%struct.MyMatrix.2) align 8 %ref.tmp1, ptr noundef nonnull align 8 dereferenceable(336) %0)
// CHECK-NEXT: call void @_Z9transposeIdLj6ELj7EE8MyMatrixIT_XT1_EXT0_EERKS0_IS1_XT0_EXT1_EE(ptr sret(%struct.MyMatrix.1) align 8 %ref.tmp, ptr noundef nonnull align 8 dereferenceable(336) %ref.tmp1)
// CHECK-NEXT: call void @_Z9transposeIdLj7ELj6EE8MyMatrixIT_XT1_EXT0_EERKS0_IS1_XT0_EXT1_EE(ptr sret(%struct.MyMatrix.2) align 8 %M2_t, ptr noundef nonnull align 8 dereferenceable(336) %ref.tmp)
// CHECK: call void @_Z9transposeIdLj7ELj6EE8MyMatrixIT_XT1_EXT0_EERKS0_IS1_XT0_EXT1_EE(ptr sret(%struct.MyMatrix.1) align 8 %ref.tmp1, ptr noundef nonnull align 8 dereferenceable(336) %0)
// CHECK-NEXT: call void @_Z9transposeIdLj6ELj7EE8MyMatrixIT_XT1_EXT0_EERKS0_IS1_XT0_EXT1_EE(ptr sret(%struct.MyMatrix.2) align 8 %ref.tmp, ptr noundef nonnull align 8 dereferenceable(336) %ref.tmp1)
// CHECK-NEXT: call void @_Z9transposeIdLj7ELj6EE8MyMatrixIT_XT1_EXT0_EERKS0_IS1_XT0_EXT1_EE(ptr sret(%struct.MyMatrix.1) align 8 %M2_t, ptr noundef nonnull align 8 dereferenceable(336) %ref.tmp)

// CHECK-LABEL: define linkonce_odr void @_Z9transposeIdLj7ELj6EE8MyMatrixIT_XT1_EXT0_EERKS0_IS1_XT0_EXT1_EE(
// CHECK: [[M:%.*]] = load <42 x double>, ptr {{.*}}, align 8
// CHECK-NEXT: [[M_T:%.*]] = call <42 x double> @llvm.matrix.transpose.v42f64(<42 x double> [[M]], i32 7, i32 6)
// CHECK-NEXT: [[RES_ADDR:%.*]] = getelementptr inbounds %struct.MyMatrix.2, ptr %agg.result, i32 0, i32 0
// CHECK-NEXT: [[RES_ADDR:%.*]] = getelementptr inbounds %struct.MyMatrix.1, ptr %agg.result, i32 0, i32 0
// CHECK-NEXT: store <42 x double> [[M_T]], ptr [[RES_ADDR]], align 8

// CHECK-LABEL: define linkonce_odr void @_Z9transposeIdLj6ELj7EE8MyMatrixIT_XT1_EXT0_EERKS0_IS1_XT0_EXT1_EE(
// CHECK: [[M:%.*]] = load <42 x double>, ptr {{.*}}, align 8
// CHECK-NEXT: [[M_T:%.*]] = call <42 x double> @llvm.matrix.transpose.v42f64(<42 x double> [[M]], i32 6, i32 7)
// CHECK-NEXT: [[RES_ADDR:%.*]] = getelementptr inbounds %struct.MyMatrix.1, ptr %agg.result, i32 0, i32 0
// CHECK-NEXT: [[RES_ADDR:%.*]] = getelementptr inbounds %struct.MyMatrix.2, ptr %agg.result, i32 0, i32 0
// CHECK-NEXT: store <42 x double> [[M_T]], ptr [[RES_ADDR]], align 8

MyMatrix<double, 6, 7> M2_t = transpose(transpose(transpose(M)));
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -184,6 +184,6 @@ struct S30_use { // abi15-warning {{packed attribute is unnecessary for 'S30_use
static_assert(sizeof(S30_use) == 3, "");

// The warnings are emitted when the layout of the structs is computed, so we have to use them.
void f(S1*, S2*, S3*, S4*, S5*, S6*, S7*, S8*, S9*, S10*, S11*, S12*, S13*,
S14*, S15*, S16*, S17*, S18*, S19*, S20*, S21*, S22*, S23*, S24*, S25*,
S26*, S27*, S28*, S29*){}
void f(S1, S2, S3, S4, S5, S6, S7, S8, S9, S10, S11, S12, S13,
S14, S15, S16, S17, S18, S19, S20, S21, S22, S23, S24, S25,
S26, S27, S28, S29){}
5 changes: 3 additions & 2 deletions clang/test/Modules/compare-record.c
Original file line number Diff line number Diff line change
Expand Up @@ -423,9 +423,10 @@ struct CompareDifferentFieldInIndirectStruct compareIndirectStruct;
// expected-error@second-nested-struct.h:* {{'IndirectStruct::mismatchingField' from module 'Second' is not present in definition of 'struct IndirectStruct' in module 'First.Hidden'}}
// expected-note@first-nested-struct.h:* {{declaration of 'mismatchingField' does not match}}
#elif defined(CASE3)
// This currently doesn't produce an error, because there is no dependency
// on the layout of DirectStruct.
// expected-no-diagnostics
struct CompareIndirectStructPointer compareIndirectStructPointer;
// expected-error@second-nested-struct.h:* {{'IndirectStruct::mismatchingField' from module 'Second' is not present in definition of 'struct IndirectStruct' in module 'First.Hidden'}}
// expected-note@first-nested-struct.h:* {{declaration of 'mismatchingField' does not match}}
#endif

//--- include/first-anonymous.h
Expand Down
2 changes: 1 addition & 1 deletion clang/test/PCH/headersearch.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@
// RUN: not %clang_cc1 -triple %itanium_abi_triple -DINSTANTIATION -include-pch all.h.pch -I%t_moved -I%t_moved/sub2 -emit-llvm-only %s 2> %t.stderr
// RUN: grep 'orig_sub2_1' %t.stderr

void qq(orig_sub*) {all();}
void qq(orig_sub) {all();}

#ifdef REDECL
float foo() {return 0;}
Expand Down
90 changes: 37 additions & 53 deletions clang/test/Sema/ms_class_layout.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -147,16 +147,16 @@ int main() {
// This avoid "Can't yet mangle constructors!" for MS ABI.
C* c;
c->foo();
DerivedStruct* v;
H* g;
DerivedStruct v;
H g;
BaseStruct* u;
I* i;
N* n;
O* o;
P* p;
R* r;
sd *h;
EV *j;
I i;
N n;
O o;
P p;
R r;
sd h;
EV j;
return 0;
}

Expand Down Expand Up @@ -206,15 +206,6 @@ int main() {
// CHECK-NEXT: sizeof=80, align=8
// CHECK-NEXT: nvsize=64, nvalign=8

// CHECK: %class.D = type { ptr, double }

// CHECK: %class.B = type { ptr, i32 }

// CHECK: %class.A = type { %class.B, i32, i8 }

// CHECK: %class.C = type { %class.D, %class.B, ptr, double, i32, double, i32, [4 x i8], %class.A }
// CHECK: %class.C.base = type { %class.D, %class.B, ptr, double, i32, double, i32 }

// CHECK-LABEL: 0 | struct BaseStruct{{$}}
// CHECK-NEXT: 0 | double v0
// CHECK-NEXT: 8 | float v1
Expand All @@ -239,8 +230,6 @@ int main() {
// CHECK-NEXT: sizeof=96, align=8
// CHECK-NEXT: nvsize=96, nvalign=8

// CHECK: %struct.BaseStruct = type { double, float, %class.C }

// CHECK-LABEL: 0 | struct DerivedStruct{{$}}
// CHECK-NEXT: 0 | struct BaseStruct (base)
// CHECK-NEXT: 0 | double v0
Expand All @@ -267,8 +256,6 @@ int main() {
// CHECK-NEXT: sizeof=104, align=8
// CHECK-NEXT: nvsize=104, nvalign=8

// CHECK: %struct.DerivedStruct = type { %struct.BaseStruct, i32 }

// CHECK-LABEL:0 | struct G
// CHECK-NEXT: 0 | int g_field
// CHECK-NEXT: sizeof=4, align=4
Expand All @@ -284,8 +271,6 @@ int main() {
// CHECK-NEXT: sizeof=24, align=8
// CHECK-NEXT: nvsize=8, nvalign=8

// CHECK: %struct.H = type { %struct.G, ptr, %class.D }

// CHECK-LABEL: 0 | struct I{{$}}
// CHECK-NEXT: 0 | (I vftable pointer)
// CHECK-NEXT: 8 | (I vbtable pointer)
Expand All @@ -296,9 +281,6 @@ int main() {
// CHECK-NEXT: sizeof=40, align=8
// CHECK-NEXT: nvsize=24, nvalign=8

// CHECK: %struct.I = type { ptr, [4 x i8], ptr, double, %class.D }
// CHECK: %struct.I.base = type { ptr, [4 x i8], ptr, double }

// CHECK-LABEL: 0 | struct L{{$}}
// CHECK-NEXT: 0 | int l
// CHECK-NEXT: sizeof=4, align=4
Expand All @@ -316,9 +298,6 @@ int main() {
// CHECK-NEXT: 8 | int k
// CHECK-NEXT: sizeof=12, align=4

//CHECK: %struct.M = type { ptr, i32, %struct.K }
//CHECK: %struct.M.base = type { ptr, i32 }

// CHECK-LABEL: 0 | struct N{{$}}
// CHECK-NEXT: 0 | (N vftable pointer)
// CHECK-NEXT: 4 | struct L (base)
Expand All @@ -331,8 +310,6 @@ int main() {
// CHECK-NEXT: sizeof=20, align=4
// CHECK-NEXT: nvsize=16, nvalign=4

//CHECK: %struct.N = type { ptr, %struct.L, %struct.M.base, %struct.K }

// CHECK-LABEL: 0 | struct O{{$}}
// CHECK-NEXT: 0 | (O vftable pointer)
// CHECK-NEXT: 8 | struct H (base)
Expand All @@ -347,9 +324,6 @@ int main() {
// CHECK-NEXT: | [sizeof=40, align=8
// CHECK-NEXT: | nvsize=24, nvalign=8]

// CHECK: struct.O = type { ptr, [4 x i8], %struct.H.base, %struct.G, %class.D }
// CHECK: struct.O.base = type { ptr, [4 x i8], %struct.H.base, %struct.G, [4 x i8] }

// CHECK-LABEL: 0 | struct P{{$}}
// CHECK-NEXT: 0 | struct M (base)
// CHECK-NEXT: 0 | (M vbtable pointer)
Expand All @@ -362,14 +336,10 @@ int main() {
// CHECK-NEXT: sizeof=20, align=4
// CHECK-NEXT: nvsize=12, nvalign=4

//CHECK: %struct.P = type { %struct.M.base, i32, %struct.K, %struct.L }

// CHECK-LABEL: 0 | struct R (empty){{$}}
// CHECK-NEXT: sizeof=1, align=1
// CHECK-NEXT: nvsize=0, nvalign=1

//CHECK: %struct.R = type { i8 }

// CHECK-LABEL: 0 | struct f{{$}}
// CHECK-NEXT: 0 | (f vftable pointer)
// CHECK-NEXT: sizeof=4, align=4
Expand Down Expand Up @@ -419,12 +389,6 @@ int main() {
// CHECK-NEXT: sizeof=48, align=4
// CHECK-NEXT: nvsize=12, nvalign=4

// CHECK: %struct.f = type { ptr }
// CHECK: %struct.s = type { ptr, ptr, i32, i32, %struct.f }
// CHECK: %class.IA = type { ptr }
// CHECK: %class.ICh = type { ptr, ptr, i32, %class.IA }
// CHECK: %struct.sd = type { ptr, i32, i8, i32, %struct.f, %struct.s.base, i32, %class.IA, %class.ICh.base }

// CHECK-LABEL: 0 | struct AV{{$}}
// CHECK-NEXT: 0 | (AV vftable pointer)
// CHECK-NEXT: sizeof=4, align=4
Expand All @@ -445,20 +409,13 @@ int main() {
// CHECK-NEXT: sizeof=12, align=4
// CHECK-NEXT: nvsize=4, nvalign=4

// CHECK: %struct.AV = type { ptr }
// CHECK: %struct.BV = type { %struct.AV }
// CHECK: %struct.CV = type { ptr, i32, %struct.BV }
// CHECK: %struct.CV.base = type { ptr }

// CHECK-LABEL: 0 | struct DV{{$}}
// CHECK-NEXT: 0 | struct BV (primary base)
// CHECK-NEXT: 0 | struct AV (primary base)
// CHECK-NEXT: 0 | (AV vftable pointer)
// CHECK-NEXT: sizeof=4, align=4
// CHECK-NEXT: nvsize=4, nvalign=4

// CHECK: %struct.DV = type { %struct.BV }

// CHECK-LABEL: 0 | struct EV{{$}}
// CHECK-NEXT: 0 | struct DV (primary base)
// CHECK-NEXT: 0 | struct BV (primary base)
Expand All @@ -473,6 +430,33 @@ int main() {
// CHECK-NEXT: sizeof=16, align=4
// CHECK-NEXT: nvsize=8, nvalign=4

// CHECK: %class.D = type { ptr, double }
// CHECK: %class.B = type { ptr, i32 }
// CHECK: %class.A = type { %class.B, i32, i8 }
// CHECK: %class.C = type { %class.D, %class.B, ptr, double, i32, double, i32, [4 x i8], %class.A }
// CHECK: %class.C.base = type { %class.D, %class.B, ptr, double, i32, double, i32 }
// CHECK: %struct.BaseStruct = type { double, float, %class.C }
// CHECK: %struct.DerivedStruct = type { %struct.BaseStruct, i32 }
// CHECK: %struct.H = type { %struct.G, ptr, %class.D }
// CHECK: %struct.I = type { ptr, [4 x i8], ptr, double, %class.D }
// CHECK: %struct.I.base = type { ptr, [4 x i8], ptr, double }
// CHECK: %struct.M = type { ptr, i32, %struct.K }
// CHECK: %struct.M.base = type { ptr, i32 }
// CHECK: %struct.N = type { ptr, %struct.L, %struct.M.base, %struct.K }
// CHECK: %struct.O = type { ptr, [4 x i8], %struct.H.base, %struct.G, %class.D }
// CHECK: %struct.O.base = type { ptr, [4 x i8], %struct.H.base, %struct.G, [4 x i8] }
// CHECK: %struct.P = type { %struct.M.base, i32, %struct.K, %struct.L }
// CHECK: %struct.R = type { i8 }
// CHECK: %struct.f = type { ptr }
// CHECK: %struct.s = type { ptr, ptr, i32, i32, %struct.f }
// CHECK: %class.IA = type { ptr }
// CHECK: %class.ICh = type { ptr, ptr, i32, %class.IA }
// CHECK: %struct.sd = type { ptr, i32, i8, i32, %struct.f, %struct.s.base, i32, %class.IA, %class.ICh.base }
// CHECK: %struct.AV = type { ptr }
// CHECK: %struct.BV = type { %struct.AV }
// CHECK: %struct.CV = type { ptr, i32, %struct.BV }
// CHECK: %struct.CV.base = type { ptr }
// CHECK: %struct.DV = type { %struct.BV }
// CHECK: %struct.EV = type { %struct.DV, %struct.CV.base, i32, %struct.BV }
// CHECK: %struct.EV.base = type { %struct.DV, %struct.CV.base }

Expand All @@ -482,7 +466,7 @@ namespace test1 {
struct A { virtual void foo(); };
struct B : A {};
struct C : virtual A, virtual B { C(); virtual void foo(); };
void test() { C *c; }
void test() { C c; }

// CHECK-LABEL: 0 | struct test1::C{{$}}
// CHECK-NEXT: 0 | (C vbtable pointer)
Expand Down

0 comments on commit 09d6ee7

Please sign in to comment.