[CodeGen] Make element type in emitArrayDestroy() predictable

When calling emitArrayDestroy(), the pointer will usually have
ConvertTypeForMem(EltType) as the element type, as one would expect.
However, globals with initializers sometimes don't use the same
types as values normally would, e.g. here the global uses
{ double, i32 } rather than %struct.T as element type.

Add an early cast to the global destruction path to avoid this
special case. The cast would happen lateron anyway, it only gets
moved to an earlier point.

Differential Revision: https://reviews.llvm.org/D116219
This commit is contained in:
Nikita Popov 2022-01-04 15:24:14 +01:00
parent 065e0324e5
commit 2d1b55ebea
3 changed files with 8 additions and 6 deletions

View File

@ -2252,16 +2252,17 @@ void CodeGenFunction::emitArrayDestroy(llvm::Value *begin,
// Shift the address back by one element. // Shift the address back by one element.
llvm::Value *negativeOne = llvm::ConstantInt::get(SizeTy, -1, true); llvm::Value *negativeOne = llvm::ConstantInt::get(SizeTy, -1, true);
llvm::Type *llvmElementType = ConvertTypeForMem(elementType);
llvm::Value *element = Builder.CreateInBoundsGEP( llvm::Value *element = Builder.CreateInBoundsGEP(
elementPast->getType()->getPointerElementType(), elementPast, negativeOne, llvmElementType, elementPast, negativeOne, "arraydestroy.element");
"arraydestroy.element");
if (useEHCleanup) if (useEHCleanup)
pushRegularPartialArrayCleanup(begin, element, elementType, elementAlign, pushRegularPartialArrayCleanup(begin, element, elementType, elementAlign,
destroyer); destroyer);
// Perform the actual destruction there. // Perform the actual destruction there.
destroyer(*this, Address(element, elementAlign), elementType); destroyer(*this, Address(element, llvmElementType, elementAlign),
elementType);
if (useEHCleanup) if (useEHCleanup)
PopCleanupBlock(); PopCleanupBlock();

View File

@ -136,6 +136,7 @@ static void EmitDeclDestroy(CodeGenFunction &CGF, const VarDecl &D,
} }
// Otherwise, the standard logic requires a helper function. // Otherwise, the standard logic requires a helper function.
} else { } else {
Addr = Addr.getElementBitCast(CGF.ConvertTypeForMem(Type));
Func = CodeGenFunction(CGM) Func = CodeGenFunction(CGM)
.generateDestroyHelper(Addr, Type, CGF.getDestroyer(DtorKind), .generateDestroyHelper(Addr, Type, CGF.getDestroyer(DtorKind),
CGF.needsEHCleanup(DtorKind), &D); CGF.needsEHCleanup(DtorKind), &D);

View File

@ -39,7 +39,7 @@ struct T {
T t[2][3] = { 1.0, 2, 3.0, 4, 5.0, 6, 7.0, 8, 9.0, 10, 11.0, 12 }; T t[2][3] = { 1.0, 2, 3.0, 4, 5.0, 6, 7.0, 8, 9.0, 10, 11.0, 12 };
// CHECK: call {{.*}} @__cxa_atexit // CHECK: call {{.*}} @__cxa_atexit
// CHECK: getelementptr inbounds ([2 x [3 x {{.*}}]], [2 x [3 x {{.*}}]]* @t, i64 1, i64 0, i64 0) // CHECK: getelementptr inbounds ([2 x [3 x %struct.T]], [2 x [3 x %struct.T]]* bitcast ([2 x [3 x { double, i32 }]]* @t to [2 x [3 x %struct.T]]*), i64 1, i64 0, i64 0)
// CHECK: call void @_ZN1TD1Ev // CHECK: call void @_ZN1TD1Ev
// CHECK: icmp eq {{.*}} @t // CHECK: icmp eq {{.*}} @t
// CHECK: br i1 {{.*}} // CHECK: br i1 {{.*}}
@ -47,7 +47,7 @@ T t[2][3] = { 1.0, 2, 3.0, 4, 5.0, 6, 7.0, 8, 9.0, 10, 11.0, 12 };
static T t2[2][3] = { 1.0, 2, 3.0, 4, 5.0, 6, 7.0, 8, 9.0, 10, 11.0, 12 }; static T t2[2][3] = { 1.0, 2, 3.0, 4, 5.0, 6, 7.0, 8, 9.0, 10, 11.0, 12 };
// CHECK: call {{.*}} @__cxa_atexit // CHECK: call {{.*}} @__cxa_atexit
// CHECK: getelementptr inbounds ([2 x [3 x {{.*}}]], [2 x [3 x {{.*}}]]* @_ZL2t2, i64 1, i64 0, i64 0) // CHECK: getelementptr inbounds ([2 x [3 x %struct.T]], [2 x [3 x %struct.T]]* bitcast ([2 x [3 x { double, i32 }]]* @_ZL2t2 to [2 x [3 x %struct.T]]*), i64 1, i64 0, i64 0)
// CHECK: call void @_ZN1TD1Ev // CHECK: call void @_ZN1TD1Ev
// CHECK: icmp eq {{.*}} @_ZL2t2 // CHECK: icmp eq {{.*}} @_ZL2t2
// CHECK: br i1 {{.*}} // CHECK: br i1 {{.*}}
@ -56,7 +56,7 @@ using U = T[2][3];
U &&u = U{ {{1.0, 2}, {3.0, 4}, {5.0, 6}}, {{7.0, 8}, {9.0, 10}, {11.0, 12}} }; U &&u = U{ {{1.0, 2}, {3.0, 4}, {5.0, 6}}, {{7.0, 8}, {9.0, 10}, {11.0, 12}} };
// CHECK: call {{.*}} @__cxa_atexit // CHECK: call {{.*}} @__cxa_atexit
// CHECK: getelementptr inbounds ([2 x [3 x {{.*}}]], [2 x [3 x {{.*}}]]* @_ZGR1u_, i64 1, i64 0, i64 0) // CHECK: getelementptr inbounds ([2 x [3 x %struct.T]], [2 x [3 x %struct.T]]* @_ZGR1u_, i64 1, i64 0, i64 0)
// CHECK: call void @_ZN1TD1Ev // CHECK: call void @_ZN1TD1Ev
// CHECK: icmp eq {{.*}} @_ZGR1u_ // CHECK: icmp eq {{.*}} @_ZGR1u_
// CHECK: br i1 {{.*}} // CHECK: br i1 {{.*}}