[cfe-commits] r82628 - in /cfe/trunk: lib/CodeGen/CGCXXExpr.cpp test/CodeGenCXX/new.cpp
Anders Carlsson
andersca at mac.com
Wed Sep 23 09:07:23 PDT 2009
Author: andersca
Date: Wed Sep 23 11:07:23 2009
New Revision: 82628
URL: http://llvm.org/viewvc/llvm-project?rev=82628&view=rev
Log:
Basic support for new[].
Modified:
cfe/trunk/lib/CodeGen/CGCXXExpr.cpp
cfe/trunk/test/CodeGenCXX/new.cpp
Modified: cfe/trunk/lib/CodeGen/CGCXXExpr.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CGCXXExpr.cpp?rev=82628&r1=82627&r2=82628&view=diff
==============================================================================
--- cfe/trunk/lib/CodeGen/CGCXXExpr.cpp (original)
+++ cfe/trunk/lib/CodeGen/CGCXXExpr.cpp Wed Sep 23 11:07:23 2009
@@ -15,8 +15,107 @@
using namespace clang;
using namespace CodeGen;
+static uint64_t CalculateCookiePadding(ASTContext &Ctx, const CXXNewExpr *E) {
+ QualType T = E->getAllocatedType();
+
+ const RecordType *RT = T->getAs<RecordType>();
+ if (!RT)
+ return 0;
+
+ const CXXRecordDecl *RD = dyn_cast<CXXRecordDecl>(RT->getDecl());
+ if (!RD)
+ return 0;
+
+ // Check if the class has a trivial destructor.
+ if (RD->hasTrivialDestructor()) {
+ // FIXME: Check for a two-argument delete.
+ return 0;
+ }
+
+ // Padding is the maximum of sizeof(size_t) and alignof(T)
+ return std::max(Ctx.getTypeSize(Ctx.getSizeType()),
+ static_cast<uint64_t>(Ctx.getTypeAlign(T)));
+}
+
+static llvm::Value *EmitCXXNewAllocSize(CodeGenFunction &CGF,
+ const CXXNewExpr *E,
+ llvm::Value *& NumElements) {
+ QualType Type = E->getAllocatedType();
+ uint64_t TypeSizeInBytes = CGF.getContext().getTypeSize(Type) / 8;
+ const llvm::Type *SizeTy = CGF.ConvertType(CGF.getContext().getSizeType());
+
+ if (!E->isArray())
+ return llvm::ConstantInt::get(SizeTy, TypeSizeInBytes);
+
+ uint64_t CookiePadding = CalculateCookiePadding(CGF.getContext(), E);
+
+ Expr::EvalResult Result;
+ if (E->getArraySize()->Evaluate(Result, CGF.getContext()) &&
+ !Result.HasSideEffects && Result.Val.isInt()) {
+
+ uint64_t AllocSize =
+ Result.Val.getInt().getZExtValue() * TypeSizeInBytes + CookiePadding;
+
+ NumElements =
+ llvm::ConstantInt::get(SizeTy, Result.Val.getInt().getZExtValue());
+
+ return llvm::ConstantInt::get(SizeTy, AllocSize);
+ }
+
+ // Emit the array size expression.
+ NumElements = CGF.EmitScalarExpr(E->getArraySize());
+
+ // Multiply with the type size.
+ llvm::Value *V =
+ CGF.Builder.CreateMul(NumElements,
+ llvm::ConstantInt::get(SizeTy, TypeSizeInBytes));
+
+ // And add the cookie padding if necessary.
+ if (CookiePadding)
+ V = CGF.Builder.CreateAdd(V, llvm::ConstantInt::get(SizeTy, CookiePadding));
+
+ return V;
+}
+
+static void EmitNewInitializer(CodeGenFunction &CGF, const CXXNewExpr *E,
+ llvm::Value *NewPtr,
+ llvm::Value *NumElements) {
+ QualType AllocType = E->getAllocatedType();
+
+ if (!E->isArray()) {
+ if (CXXConstructorDecl *Ctor = E->getConstructor()) {
+ CGF.EmitCXXConstructorCall(Ctor, Ctor_Complete, NewPtr,
+ E->constructor_arg_begin(),
+ E->constructor_arg_end());
+
+ return;
+ }
+
+ // We have a POD type.
+ if (E->getNumConstructorArgs() == 0)
+ return;
+
+ assert(E->getNumConstructorArgs() == 1 &&
+ "Can only have one argument to initializer of POD type.");
+
+ const Expr *Init = E->getConstructorArg(0);
+
+ if (!CGF.hasAggregateLLVMType(AllocType))
+ CGF.Builder.CreateStore(CGF.EmitScalarExpr(Init), NewPtr);
+ else if (AllocType->isAnyComplexType())
+ CGF.EmitComplexExprIntoAddr(Init, NewPtr,
+ AllocType.isVolatileQualified());
+ else
+ CGF.EmitAggExpr(Init, NewPtr, AllocType.isVolatileQualified());
+ return;
+ }
+
+ if (CXXConstructorDecl *Ctor = E->getConstructor())
+ CGF.EmitCXXAggrConstructorCall(Ctor, NumElements, NewPtr);
+}
+
llvm::Value *CodeGenFunction::EmitCXXNewExpr(const CXXNewExpr *E) {
- if (E->isArray()) {
+ if (E->isArray() && CalculateCookiePadding(getContext(), E)) {
ErrorUnsupported(E, "new[] expression");
return llvm::UndefValue::get(ConvertType(E->getType()));
}
@@ -29,10 +128,10 @@
// The allocation size is the first argument.
QualType SizeTy = getContext().getSizeType();
- llvm::Value *AllocSize =
- llvm::ConstantInt::get(ConvertType(SizeTy),
- getContext().getTypeSize(AllocType) / 8);
+ llvm::Value *NumElements = 0;
+ llvm::Value *AllocSize = EmitCXXNewAllocSize(*this, E, NumElements);
+
NewArgs.push_back(std::make_pair(RValue::get(AllocSize), SizeTy));
// Emit the rest of the arguments.
@@ -102,28 +201,7 @@
NewPtr = Builder.CreateBitCast(NewPtr, ConvertType(E->getType()));
- if (AllocType->isPODType()) {
- if (E->getNumConstructorArgs() > 0) {
- assert(E->getNumConstructorArgs() == 1 &&
- "Can only have one argument to initializer of POD type.");
-
- const Expr *Init = E->getConstructorArg(0);
-
- if (!hasAggregateLLVMType(AllocType))
- Builder.CreateStore(EmitScalarExpr(Init), NewPtr);
- else if (AllocType->isAnyComplexType())
- EmitComplexExprIntoAddr(Init, NewPtr, AllocType.isVolatileQualified());
- else
- EmitAggExpr(Init, NewPtr, AllocType.isVolatileQualified());
- }
- } else {
- // Call the constructor.
- CXXConstructorDecl *Ctor = E->getConstructor();
-
- EmitCXXConstructorCall(Ctor, Ctor_Complete, NewPtr,
- E->constructor_arg_begin(),
- E->constructor_arg_end());
- }
+ EmitNewInitializer(*this, E, NewPtr, NumElements);
if (NullCheckResult) {
Builder.CreateBr(NewEnd);
Modified: cfe/trunk/test/CodeGenCXX/new.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CodeGenCXX/new.cpp?rev=82628&r1=82627&r2=82628&view=diff
==============================================================================
--- cfe/trunk/test/CodeGenCXX/new.cpp (original)
+++ cfe/trunk/test/CodeGenCXX/new.cpp Wed Sep 23 11:07:23 2009
@@ -1,4 +1,4 @@
-// RUN: clang-cc %s -emit-llvm -o %t &&
+// RUN: clang-cc %s -emit-llvm -o - | FileCheck %s
void t1() {
int* a = new int;
@@ -32,7 +32,7 @@
};
void t4() {
- // RUN: grep "call void @_ZN1TC1Ev" %t | count 1 &&
+ // CHECK: call void @_ZN1TC1Ev
T *t = new T;
}
@@ -42,7 +42,7 @@
};
void t5() {
- // RUN: grep "call void @_ZN2T2C1Eii" %t | count 1
+ // CHECK: call void @_ZN2T2C1Eii
T2 *t2 = new T2(10, 10);
}
@@ -54,3 +54,12 @@
void t7() {
new int();
}
+
+void t8(int n) {
+ new int[10];
+ new int[n];
+
+ // Non-POD
+ new T[10];
+ new T[n];
+}
More information about the cfe-commits
mailing list