From 1e7fe751466ea82665fd21e9162fd7cc9c5f412d Mon Sep 17 00:00:00 2001 From: John McCall Date: Thu, 2 Sep 2010 09:58:18 +0000 Subject: Abstract IR generation of array cookies into the C++ ABI class and implement ARM array cookies. Also fix a few unfortunate bugs: - throwing dtors in deletes prevented the allocation from being deleted - adding the cookie to the new[] size was not being considered for overflow (and, more seriously, was screwing up the earlier checks) - deleting an array via a pointer to array of class type was not causing any destructors to be run and was passing the unadjusted pointer to the deallocator - lots of address-space problems, in case anyone wants to support free store in a variant address space :) git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@112814 91177308-0d34-0410-b5e6-96231b3b80d8 --- test/CodeGenCXX/arm.cpp | 152 ++++++++++++++++++++++++++++++++++++++- test/CodeGenCXX/delete.cpp | 40 ++++++++++- test/CodeGenCXX/new.cpp | 1 + test/CodeGenCXX/operator-new.cpp | 10 +-- 4 files changed, 195 insertions(+), 8 deletions(-) (limited to 'test') diff --git a/test/CodeGenCXX/arm.cpp b/test/CodeGenCXX/arm.cpp index b4c8c835e4..fb962e069d 100644 --- a/test/CodeGenCXX/arm.cpp +++ b/test/CodeGenCXX/arm.cpp @@ -1,4 +1,6 @@ -// RUN: %clang_cc1 %s -triple=thumbv7-apple-darwin3.0.0-iphoneos -fno-use-cxa-atexit -target-abi apcs-gnu -emit-llvm -o - -fexceptions | FileCheck %s +// RUN: %clang_cc1 %s -triple=thumbv7-apple-darwin3.0.0-iphoneos -fno-use-cxa-atexit -target-abi apcs-gnu -emit-llvm -o - -fexceptions | Filecheck %s + +typedef typeof(sizeof(int)) size_t; class foo { public: @@ -88,6 +90,153 @@ namespace test2 { C c = 10; } + // Tests at eof +} + +namespace test3 { + struct A { + int x; + ~A(); + }; + + void a() { + // CHECK: define void @_ZN5test31aEv() + // CHECK: call noalias i8* @_Znam(i32 48) + // CHECK: store i32 4 + // CHECK: store i32 10 + A *x = new A[10]; + } + + void b(int n) { + // CHECK: define void @_ZN5test31bEi( + // CHECK: [[N:%.*]] = load i32* + // CHECK: @llvm.umul.with.overflow.i32(i32 [[N]], i32 4) + // CHECK: @llvm.uadd.with.overflow.i32(i32 {{.*}}, i32 8) + // CHECK: [[SZ:%.*]] = select + // CHECK: call noalias i8* @_Znam(i32 [[SZ]]) + // CHECK: store i32 4 + // CHECK: store i32 [[N]] + A *x = new A[n]; + } + + void c() { + // CHECK: define void @_ZN5test31cEv() + // CHECK: call noalias i8* @_Znam(i32 808) + // CHECK: store i32 4 + // CHECK: store i32 200 + A (*x)[20] = new A[10][20]; + } + + void d(int n) { + // CHECK: define void @_ZN5test31dEi( + // CHECK: [[N:%.*]] = load i32* + // CHECK: [[NE:%.*]] = mul i32 [[N]], 20 + // CHECK: @llvm.umul.with.overflow.i32(i32 [[N]], i32 80) + // CHECK: @llvm.uadd.with.overflow.i32(i32 {{.*}}, i32 8) + // CHECK: [[SZ:%.*]] = select + // CHECK: call noalias i8* @_Znam(i32 [[SZ]]) + // CHECK: store i32 4 + // CHECK: store i32 [[NE]] + A (*x)[20] = new A[n][20]; + } + + void e(A *x) { + // CHECK: define void @_ZN5test31eEPNS_1AE( + // CHECK: icmp eq {{.*}}, null + // CHECK: getelementptr {{.*}}, i64 -8 + // CHECK: getelementptr {{.*}}, i64 4 + // CHECK: bitcast {{.*}} to i32* + // CHECK: load + // CHECK: invoke {{.*}} @_ZN5test31AD1Ev + // CHECK: call void @_ZdaPv + delete [] x; + } + + void f(A (*x)[20]) { + // CHECK: define void @_ZN5test31fEPA20_NS_1AE( + // CHECK: icmp eq {{.*}}, null + // CHECK: getelementptr {{.*}}, i64 -8 + // CHECK: getelementptr {{.*}}, i64 4 + // CHECK: bitcast {{.*}} to i32* + // CHECK: load + // CHECK: invoke {{.*}} @_ZN5test31AD1Ev + // CHECK: call void @_ZdaPv + delete [] x; + } +} + +namespace test4 { + struct A { + int x; + void operator delete[](void *, size_t sz); + }; + + void a() { + // CHECK: define void @_ZN5test41aEv() + // CHECK: call noalias i8* @_Znam(i32 48) + // CHECK: store i32 4 + // CHECK: store i32 10 + A *x = new A[10]; + } + + void b(int n) { + // CHECK: define void @_ZN5test41bEi( + // CHECK: [[N:%.*]] = load i32* + // CHECK: @llvm.umul.with.overflow.i32(i32 [[N]], i32 4) + // CHECK: @llvm.uadd.with.overflow.i32(i32 {{.*}}, i32 8) + // CHECK: [[SZ:%.*]] = select + // CHECK: call noalias i8* @_Znam(i32 [[SZ]]) + // CHECK: store i32 4 + // CHECK: store i32 [[N]] + A *x = new A[n]; + } + + void c() { + // CHECK: define void @_ZN5test41cEv() + // CHECK: call noalias i8* @_Znam(i32 808) + // CHECK: store i32 4 + // CHECK: store i32 200 + A (*x)[20] = new A[10][20]; + } + + void d(int n) { + // CHECK: define void @_ZN5test41dEi( + // CHECK: [[N:%.*]] = load i32* + // CHECK: [[NE:%.*]] = mul i32 [[N]], 20 + // CHECK: @llvm.umul.with.overflow.i32(i32 [[N]], i32 80) + // CHECK: @llvm.uadd.with.overflow.i32(i32 {{.*}}, i32 8) + // CHECK: [[SZ:%.*]] = select + // CHECK: call noalias i8* @_Znam(i32 [[SZ]]) + // CHECK: store i32 4 + // CHECK: store i32 [[NE]] + A (*x)[20] = new A[n][20]; + } + + void e(A *x) { + // CHECK: define void @_ZN5test41eEPNS_1AE( + // CHECK: [[ALLOC:%.*]] = getelementptr inbounds {{.*}}, i64 -8 + // CHECK: getelementptr inbounds {{.*}}, i64 4 + // CHECK: bitcast + // CHECK: [[T0:%.*]] = load i32* + // CHECK: [[T1:%.*]] = mul i32 4, [[T0]] + // CHECK: [[T2:%.*]] = add i32 [[T1]], 8 + // CHECK: call void @_ZN5test41AdaEPvm(i8* [[ALLOC]], i32 [[T2]]) + delete [] x; + } + + void f(A (*x)[20]) { + // CHECK: define void @_ZN5test41fEPA20_NS_1AE( + // CHECK: [[ALLOC:%.*]] = getelementptr inbounds {{.*}}, i64 -8 + // CHECK: getelementptr inbounds {{.*}}, i64 4 + // CHECK: bitcast + // CHECK: [[T0:%.*]] = load i32* + // CHECK: [[T1:%.*]] = mul i32 4, [[T0]] + // CHECK: [[T2:%.*]] = add i32 [[T1]], 8 + // CHECK: call void @_ZN5test41AdaEPvm(i8* [[ALLOC]], i32 [[T2]]) + delete [] x; + } +} + // CHECK: define linkonce_odr [[C:%.*]]* @_ZTv0_n12_N5test21CD1Ev( // CHECK: call [[C]]* @_ZN5test21CD1Ev( // CHECK: ret [[C]]* undef @@ -95,7 +244,6 @@ namespace test2 { // CHECK: define linkonce_odr void @_ZTv0_n12_N5test21CD0Ev( // CHECK: call void @_ZN5test21CD0Ev( // CHECK: ret void -} // CHECK: @_GLOBAL__D_a() // CHECK: call %class.bar* @_ZN3barD1Ev(%class.bar* @baz) diff --git a/test/CodeGenCXX/delete.cpp b/test/CodeGenCXX/delete.cpp index 87f8698b84..ec13d0cc0f 100644 --- a/test/CodeGenCXX/delete.cpp +++ b/test/CodeGenCXX/delete.cpp @@ -1,4 +1,4 @@ -// RUN: %clang_cc1 %s -emit-llvm -o - | FileCheck %s +// RUN: %clang_cc1 -triple x86_64-apple-darwin10 %s -emit-llvm -o - | FileCheck %s void t1(int *a) { delete a; @@ -57,3 +57,41 @@ namespace test0 { // CHECK: define linkonce_odr void @_ZN5test01AD1Ev // CHECK: define linkonce_odr void @_ZN5test01AdlEPv } + +namespace test1 { + struct A { + int x; + ~A(); + }; + + // CHECK: define void @_ZN5test14testEPA10_A20_NS_1AE( + void test(A (*arr)[10][20]) { + delete [] arr; + // CHECK: icmp eq [10 x [20 x [[S:%.*]]]]* [[PTR:%.*]], null + // CHECK-NEXT: br i1 + + // CHECK: [[ARR:%.*]] = getelementptr inbounds [10 x [20 x [[S]]]]* [[PTR]], i32 0, i32 0, i32 0 + // CHECK-NEXT: bitcast {{.*}} to i8* + // CHECK-NEXT: [[ALLOC:%.*]] = getelementptr inbounds {{.*}}, i64 -8 + // CHECK-NEXT: bitcast i8* [[ALLOC]] to i64* + // CHECK-NEXT: load + // CHECK-NEXT: store i64 {{.*}}, i64* [[IDX:%.*]] + + // CHECK: load i64* [[IDX]] + // CHECK-NEXT: icmp ne {{.*}}, 0 + // CHECK-NEXT: br i1 + + // CHECK: load i64* [[IDX]] + // CHECK-NEXT: [[I:%.*]] = sub i64 {{.*}}, 1 + // CHECK-NEXT: getelementptr inbounds [[S]]* [[ARR]], i64 [[I]] + // CHECK-NEXT: call void @_ZN5test11AD1Ev( + // CHECK-NEXT: br label + + // CHECK: load i64* [[IDX]] + // CHECK-NEXT: sub + // CHECK-NEXT: store {{.*}}, i64* [[IDX]] + // CHECK-NEXT: br label + + // CHECK: call void @_ZdaPv(i8* [[ALLOC]]) + } +} diff --git a/test/CodeGenCXX/new.cpp b/test/CodeGenCXX/new.cpp index 42d7c9f1a3..d52ebbe450 100644 --- a/test/CodeGenCXX/new.cpp +++ b/test/CodeGenCXX/new.cpp @@ -155,6 +155,7 @@ struct Alloc{ void f() { // CHECK: call i8* @_ZN5AllocnaEm(i64 808) // CHECK: store i64 200 + // CHECK: call void @_ZN5AllocD1Ev( // CHECK: call void @_ZN5AllocdaEPv(i8* delete[] new Alloc[10][20]; } diff --git a/test/CodeGenCXX/operator-new.cpp b/test/CodeGenCXX/operator-new.cpp index df3c114a14..db56cda6cd 100644 --- a/test/CodeGenCXX/operator-new.cpp +++ b/test/CodeGenCXX/operator-new.cpp @@ -21,9 +21,9 @@ void f1() { void *f2(long N) { return new int[N]; -// SANE: call{{.*}}@llvm.umul.with.overflow -// SANE: extractvalue -// SANE: br i1 -// SANE: = phi {{.*}} [ {{.*}} ], [ -1, -// SANE: call noalias i8* @_Znaj( +// SANE: [[UWO:%.*]] = call {{.*}} @llvm.umul.with.overflow +// SANE-NEXT: [[OVER:%.*]] = extractvalue {{.*}} [[UWO]], 1 +// SANE-NEXT: [[SUM:%.*]] = extractvalue {{.*}} [[UWO]], 0 +// SANE-NEXT: [[RESULT:%.*]] = select i1 [[OVER]], i32 -1, i32 [[SUM]] +// SANE-NEXT: call noalias i8* @_Znaj(i32 [[RESULT]]) } -- cgit v1.2.1