[llvm-branch-commits] [cfe-branch] r114162 - in /cfe/branches/Apple/whitney-IB/src/tools/clang: ./ lib/CodeGen/CGExprCXX.cpp lib/CodeGen/CodeGenFunction.cpp lib/CodeGen/CodeGenFunction.h lib/Sema/SemaTemplateInstantiateDecl.cpp test/CodeGenCXX/exceptions.cpp
Daniel Dunbar
daniel at zuster.org
Thu Sep 16 20:38:15 PDT 2010
Author: ddunbar
Date: Thu Sep 16 22:38:15 2010
New Revision: 114162
URL: http://llvm.org/viewvc/llvm-project?rev=114162&view=rev
Log:
--- Merging r114145 into 'src/tools/clang':
U src/tools/clang/test/CodeGenCXX/exceptions.cpp
U src/tools/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp
U src/tools/clang/lib/CodeGen/CodeGenFunction.cpp
U src/tools/clang/lib/CodeGen/CGExprCXX.cpp
U src/tools/clang/lib/CodeGen/CodeGenFunction.h
Modified:
cfe/branches/Apple/whitney-IB/src/tools/clang/ (props changed)
cfe/branches/Apple/whitney-IB/src/tools/clang/lib/CodeGen/CGExprCXX.cpp
cfe/branches/Apple/whitney-IB/src/tools/clang/lib/CodeGen/CodeGenFunction.cpp
cfe/branches/Apple/whitney-IB/src/tools/clang/lib/CodeGen/CodeGenFunction.h
cfe/branches/Apple/whitney-IB/src/tools/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp
cfe/branches/Apple/whitney-IB/src/tools/clang/test/CodeGenCXX/exceptions.cpp
Propchange: cfe/branches/Apple/whitney-IB/src/tools/clang/
------------------------------------------------------------------------------
--- svn:mergeinfo (original)
+++ svn:mergeinfo Thu Sep 16 22:38:15 2010
@@ -1,2 +1,2 @@
-/cfe/trunk:114070,114075
+/cfe/trunk:114070,114075,114145
/llvm/branches/Apple/Pertwee/tools/clang:110850,110961
Modified: cfe/branches/Apple/whitney-IB/src/tools/clang/lib/CodeGen/CGExprCXX.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/branches/Apple/whitney-IB/src/tools/clang/lib/CodeGen/CGExprCXX.cpp?rev=114162&r1=114161&r2=114162&view=diff
==============================================================================
--- cfe/branches/Apple/whitney-IB/src/tools/clang/lib/CodeGen/CGExprCXX.cpp (original)
+++ cfe/branches/Apple/whitney-IB/src/tools/clang/lib/CodeGen/CGExprCXX.cpp Thu Sep 16 22:38:15 2010
@@ -677,6 +677,105 @@
StoreAnyExprIntoOneUnit(CGF, E, NewPtr);
}
+/// A utility class for saving an rvalue.
+class SavedRValue {
+public:
+ enum Kind { ScalarLiteral, ScalarAddress,
+ AggregateLiteral, AggregateAddress,
+ Complex };
+
+private:
+ llvm::Value *Value;
+ Kind K;
+
+ SavedRValue(llvm::Value *V, Kind K) : Value(V), K(K) {}
+
+public:
+ SavedRValue() {}
+
+ static SavedRValue forScalarLiteral(llvm::Value *V) {
+ return SavedRValue(V, ScalarLiteral);
+ }
+
+ static SavedRValue forScalarAddress(llvm::Value *Addr) {
+ return SavedRValue(Addr, ScalarAddress);
+ }
+
+ static SavedRValue forAggregateLiteral(llvm::Value *V) {
+ return SavedRValue(V, AggregateLiteral);
+ }
+
+ static SavedRValue forAggregateAddress(llvm::Value *Addr) {
+ return SavedRValue(Addr, AggregateAddress);
+ }
+
+ static SavedRValue forComplexAddress(llvm::Value *Addr) {
+ return SavedRValue(Addr, Complex);
+ }
+
+ Kind getKind() const { return K; }
+ llvm::Value *getValue() const { return Value; }
+};
+
+/// Given an r-value, perform the code necessary to make sure that a
+/// future RestoreRValue will be able to load the value without
+/// domination concerns.
+static SavedRValue SaveRValue(CodeGenFunction &CGF, RValue RV) {
+ if (RV.isScalar()) {
+ llvm::Value *V = RV.getScalarVal();
+
+ // These automatically dominate and don't need to be saved.
+ if (isa<llvm::Constant>(V) || isa<llvm::AllocaInst>(V))
+ return SavedRValue::forScalarLiteral(V);
+
+ // Everything else needs an alloca.
+ llvm::Value *Addr = CGF.CreateTempAlloca(V->getType(), "saved-rvalue");
+ CGF.Builder.CreateStore(V, Addr);
+ return SavedRValue::forScalarAddress(Addr);
+ }
+
+ if (RV.isComplex()) {
+ CodeGenFunction::ComplexPairTy V = RV.getComplexVal();
+ const llvm::Type *ComplexTy =
+ llvm::StructType::get(CGF.getLLVMContext(),
+ V.first->getType(), V.second->getType(),
+ (void*) 0);
+ llvm::Value *Addr = CGF.CreateTempAlloca(ComplexTy, "saved-complex");
+ CGF.StoreComplexToAddr(V, Addr, /*volatile*/ false);
+ return SavedRValue::forComplexAddress(Addr);
+ }
+
+ assert(RV.isAggregate());
+ llvm::Value *V = RV.getAggregateAddr(); // TODO: volatile?
+ if (isa<llvm::Constant>(V) || isa<llvm::AllocaInst>(V))
+ return SavedRValue::forAggregateLiteral(V);
+
+ llvm::Value *Addr = CGF.CreateTempAlloca(V->getType(), "saved-rvalue");
+ CGF.Builder.CreateStore(V, Addr);
+ return SavedRValue::forAggregateAddress(Addr);
+}
+
+/// Given a saved r-value produced by SaveRValue, perform the code
+/// necessary to restore it to usability at the current insertion
+/// point.
+static RValue RestoreRValue(CodeGenFunction &CGF, SavedRValue RV) {
+ switch (RV.getKind()) {
+ case SavedRValue::ScalarLiteral:
+ return RValue::get(RV.getValue());
+ case SavedRValue::ScalarAddress:
+ return RValue::get(CGF.Builder.CreateLoad(RV.getValue()));
+ case SavedRValue::AggregateLiteral:
+ return RValue::getAggregate(RV.getValue());
+ case SavedRValue::AggregateAddress:
+ return RValue::getAggregate(CGF.Builder.CreateLoad(RV.getValue()));
+ case SavedRValue::Complex:
+ return RValue::getComplex(CGF.LoadComplexFromAddr(RV.getValue(), false));
+ }
+
+ llvm_unreachable("bad saved r-value kind");
+ return RValue();
+}
+
namespace {
/// A cleanup to call the given 'operator delete' function upon
/// abnormal exit from a new expression.
@@ -731,6 +830,104 @@
ReturnValueSlot(), DeleteArgs, OperatorDelete);
}
};
+
+ /// A cleanup to call the given 'operator delete' function upon
+ /// abnormal exit from a new expression when the new expression is
+ /// conditional.
+ class CallDeleteDuringConditionalNew : public EHScopeStack::Cleanup {
+ size_t NumPlacementArgs;
+ const FunctionDecl *OperatorDelete;
+ SavedRValue Ptr;
+ SavedRValue AllocSize;
+
+ SavedRValue *getPlacementArgs() {
+ return reinterpret_cast<SavedRValue*>(this+1);
+ }
+
+ public:
+ static size_t getExtraSize(size_t NumPlacementArgs) {
+ return NumPlacementArgs * sizeof(SavedRValue);
+ }
+
+ CallDeleteDuringConditionalNew(size_t NumPlacementArgs,
+ const FunctionDecl *OperatorDelete,
+ SavedRValue Ptr,
+ SavedRValue AllocSize)
+ : NumPlacementArgs(NumPlacementArgs), OperatorDelete(OperatorDelete),
+ Ptr(Ptr), AllocSize(AllocSize) {}
+
+ void setPlacementArg(unsigned I, SavedRValue Arg) {
+ assert(I < NumPlacementArgs && "index out of range");
+ getPlacementArgs()[I] = Arg;
+ }
+
+ void Emit(CodeGenFunction &CGF, bool IsForEH) {
+ const FunctionProtoType *FPT
+ = OperatorDelete->getType()->getAs<FunctionProtoType>();
+ assert(FPT->getNumArgs() == NumPlacementArgs + 1 ||
+ (FPT->getNumArgs() == 2 && NumPlacementArgs == 0));
+
+ CallArgList DeleteArgs;
+
+ // The first argument is always a void*.
+ FunctionProtoType::arg_type_iterator AI = FPT->arg_type_begin();
+ DeleteArgs.push_back(std::make_pair(RestoreRValue(CGF, Ptr), *AI++));
+
+ // A member 'operator delete' can take an extra 'size_t' argument.
+ if (FPT->getNumArgs() == NumPlacementArgs + 2) {
+ RValue RV = RestoreRValue(CGF, AllocSize);
+ DeleteArgs.push_back(std::make_pair(RV, *AI++));
+ }
+
+ // Pass the rest of the arguments, which must match exactly.
+ for (unsigned I = 0; I != NumPlacementArgs; ++I) {
+ RValue RV = RestoreRValue(CGF, getPlacementArgs()[I]);
+ DeleteArgs.push_back(std::make_pair(RV, *AI++));
+ }
+
+ // Call 'operator delete'.
+ CGF.EmitCall(CGF.CGM.getTypes().getFunctionInfo(DeleteArgs, FPT),
+ CGF.CGM.GetAddrOfFunction(OperatorDelete),
+ ReturnValueSlot(), DeleteArgs, OperatorDelete);
+ }
+ };
+}
+
+/// Enter a cleanup to call 'operator delete' if the initializer in a
+/// new-expression throws.
+static void EnterNewDeleteCleanup(CodeGenFunction &CGF,
+ const CXXNewExpr *E,
+ llvm::Value *NewPtr,
+ llvm::Value *AllocSize,
+ const CallArgList &NewArgs) {
+ // If we're not inside a conditional branch, then the cleanup will
+ // dominate and we can do the easier (and more efficient) thing.
+ if (!CGF.isInConditionalBranch()) {
+ CallDeleteDuringNew *Cleanup = CGF.EHStack
+ .pushCleanupWithExtra<CallDeleteDuringNew>(EHCleanup,
+ E->getNumPlacementArgs(),
+ E->getOperatorDelete(),
+ NewPtr, AllocSize);
+ for (unsigned I = 0, N = E->getNumPlacementArgs(); I != N; ++I)
+ Cleanup->setPlacementArg(I, NewArgs[I+1].first);
+
+ return;
+ }
+
+ // Otherwise, we need to save all this stuff.
+ SavedRValue SavedNewPtr = SaveRValue(CGF, RValue::get(NewPtr));
+ SavedRValue SavedAllocSize = SaveRValue(CGF, RValue::get(AllocSize));
+
+ CallDeleteDuringConditionalNew *Cleanup = CGF.EHStack
+ .pushCleanupWithExtra<CallDeleteDuringConditionalNew>(InactiveEHCleanup,
+ E->getNumPlacementArgs(),
+ E->getOperatorDelete(),
+ SavedNewPtr,
+ SavedAllocSize);
+ for (unsigned I = 0, N = E->getNumPlacementArgs(); I != N; ++I)
+ Cleanup->setPlacementArg(I, SaveRValue(CGF, NewArgs[I+1].first));
+
+ CGF.ActivateCleanupBlock(CGF.EHStack.stable_begin());
}
llvm::Value *CodeGenFunction::EmitCXXNewExpr(const CXXNewExpr *E) {
@@ -829,13 +1026,7 @@
// exception is thrown.
EHScopeStack::stable_iterator CallOperatorDelete;
if (E->getOperatorDelete()) {
- CallDeleteDuringNew *Cleanup = CGF.EHStack
- .pushCleanupWithExtra<CallDeleteDuringNew>(EHCleanup,
- E->getNumPlacementArgs(),
- E->getOperatorDelete(),
- NewPtr, AllocSize);
- for (unsigned I = 0, N = E->getNumPlacementArgs(); I != N; ++I)
- Cleanup->setPlacementArg(I, NewArgs[I+1].first);
+ EnterNewDeleteCleanup(*this, E, NewPtr, AllocSize, NewArgs);
CallOperatorDelete = EHStack.stable_begin();
}
Modified: cfe/branches/Apple/whitney-IB/src/tools/clang/lib/CodeGen/CodeGenFunction.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/branches/Apple/whitney-IB/src/tools/clang/lib/CodeGen/CodeGenFunction.cpp?rev=114162&r1=114161&r2=114162&view=diff
==============================================================================
--- cfe/branches/Apple/whitney-IB/src/tools/clang/lib/CodeGen/CodeGenFunction.cpp (original)
+++ cfe/branches/Apple/whitney-IB/src/tools/clang/lib/CodeGen/CodeGenFunction.cpp Thu Sep 16 22:38:15 2010
@@ -1431,9 +1431,11 @@
EHScopeStack::stable_iterator C,
ForActivation_t Kind) {
EHCleanupScope &Scope = cast<EHCleanupScope>(*CGF.EHStack.find(C));
- assert(!Scope.getActiveFlag() && "scope already has activation flag");
- bool NeedFlag = false;
+ // We always need the flag if we're activating the cleanup, because
+ // we have to assume that the current location doesn't necessarily
+ // dominate all future uses of the cleanup.
+ bool NeedFlag = (Kind == ForActivation);
// Calculate whether the cleanup was used:
@@ -1452,16 +1454,17 @@
// If it hasn't yet been used as either, we're done.
if (!NeedFlag) return;
- llvm::AllocaInst *Var = CGF.CreateTempAlloca(CGF.Builder.getInt1Ty());
- Scope.setActiveFlag(Var);
-
- if (Kind == ForActivation) {
- CGF.InitTempAlloca(Var, CGF.Builder.getFalse());
- CGF.Builder.CreateStore(CGF.Builder.getTrue(), Var);
- } else {
- CGF.InitTempAlloca(Var, CGF.Builder.getTrue());
- CGF.Builder.CreateStore(CGF.Builder.getFalse(), Var);
+ llvm::AllocaInst *Var = Scope.getActiveFlag();
+ if (!Var) {
+ Var = CGF.CreateTempAlloca(CGF.Builder.getInt1Ty(), "cleanup.isactive");
+ Scope.setActiveFlag(Var);
+
+ // Initialize to true or false depending on whether it was
+ // active up to this point.
+ CGF.InitTempAlloca(Var, CGF.Builder.getInt1(Kind == ForDeactivation));
}
+
+ CGF.Builder.CreateStore(CGF.Builder.getInt1(Kind == ForActivation), Var);
}
/// Activate a cleanup that was created in an inactivated state.
@@ -1479,7 +1482,7 @@
void CodeGenFunction::DeactivateCleanupBlock(EHScopeStack::stable_iterator C) {
assert(C != EHStack.stable_end() && "deactivating bottom of stack?");
EHCleanupScope &Scope = cast<EHCleanupScope>(*EHStack.find(C));
- assert(Scope.isActive() && "double activation");
+ assert(Scope.isActive() && "double deactivation");
// If it's the top of the stack, just pop it.
if (C == EHStack.stable_begin()) {
Modified: cfe/branches/Apple/whitney-IB/src/tools/clang/lib/CodeGen/CodeGenFunction.h
URL: http://llvm.org/viewvc/llvm-project/cfe/branches/Apple/whitney-IB/src/tools/clang/lib/CodeGen/CodeGenFunction.h?rev=114162&r1=114161&r2=114162&view=diff
==============================================================================
--- cfe/branches/Apple/whitney-IB/src/tools/clang/lib/CodeGen/CodeGenFunction.h (original)
+++ cfe/branches/Apple/whitney-IB/src/tools/clang/lib/CodeGen/CodeGenFunction.h Thu Sep 16 22:38:15 2010
@@ -674,6 +674,10 @@
--ConditionalBranchLevel;
}
+ /// isInConditionalBranch - Return true if we're currently emitting
+ /// one branch or the other of a conditional expression.
+ bool isInConditionalBranch() const { return ConditionalBranchLevel != 0; }
+
private:
CGDebugInfo *DebugInfo;
Modified: cfe/branches/Apple/whitney-IB/src/tools/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/branches/Apple/whitney-IB/src/tools/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp?rev=114162&r1=114161&r2=114162&view=diff
==============================================================================
--- cfe/branches/Apple/whitney-IB/src/tools/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp (original)
+++ cfe/branches/Apple/whitney-IB/src/tools/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp Thu Sep 16 22:38:15 2010
@@ -1035,7 +1035,8 @@
// Attach the parameters
for (unsigned P = 0; P < Params.size(); ++P)
- Params[P]->setOwningFunction(Function);
+ if (Params[P])
+ Params[P]->setOwningFunction(Function);
Function->setParams(Params.data(), Params.size());
SourceLocation InstantiateAtPOI;
Modified: cfe/branches/Apple/whitney-IB/src/tools/clang/test/CodeGenCXX/exceptions.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/branches/Apple/whitney-IB/src/tools/clang/test/CodeGenCXX/exceptions.cpp?rev=114162&r1=114161&r2=114162&view=diff
==============================================================================
--- cfe/branches/Apple/whitney-IB/src/tools/clang/test/CodeGenCXX/exceptions.cpp (original)
+++ cfe/branches/Apple/whitney-IB/src/tools/clang/test/CodeGenCXX/exceptions.cpp Thu Sep 16 22:38:15 2010
@@ -164,26 +164,78 @@
namespace test3 {
struct A {
- A(int); A(int, int); ~A();
+ A(int); A(int, int); A(const A&); ~A();
void *p;
- void *operator new(size_t, void*, void*);
- void operator delete(void*, void*, void*);
+ void *operator new(size_t, void*, double);
+ void operator delete(void*, void*, double);
};
+ void *foo();
+ double bar();
+ A makeA(), *makeAPtr();
+
A *a() {
// CHECK: define [[A:%.*]]* @_ZN5test31aEv()
// CHECK: [[FOO:%.*]] = call i8* @_ZN5test33fooEv()
- // CHECK: [[BAR:%.*]] = call i8* @_ZN5test33barEv()
- // CHECK: [[NEW:%.*]] = call i8* @_ZN5test31AnwEmPvS1_(i64 8, i8* [[FOO]], i8* [[BAR]])
+ // CHECK: [[BAR:%.*]] = call double @_ZN5test33barEv()
+ // CHECK: [[NEW:%.*]] = call i8* @_ZN5test31AnwEmPvd(i64 8, i8* [[FOO]], double [[BAR]])
// CHECK-NEXT: [[CAST:%.*]] = bitcast i8* [[NEW]] to [[A]]*
// CHECK-NEXT: invoke void @_ZN5test31AC1Ei([[A]]* [[CAST]], i32 5)
// CHECK: ret [[A]]* [[CAST]]
- // CHECK: invoke void @_ZN5test31AdlEPvS1_S1_(i8* [[NEW]], i8* [[FOO]], i8* [[BAR]])
+ // CHECK: invoke void @_ZN5test31AdlEPvS1_d(i8* [[NEW]], i8* [[FOO]], double [[BAR]])
// CHECK: call void @_ZSt9terminatev()
- extern void *foo(), *bar();
-
return new(foo(),bar()) A(5);
}
+
+ // rdar://problem/8439196
+ A *b(bool cond) {
+
+ // CHECK: define [[A:%.*]]* @_ZN5test31bEb(i1 zeroext
+ // CHECK: [[SAVED0:%.*]] = alloca i8*
+ // CHECK-NEXT: [[SAVED1:%.*]] = alloca i8*
+ // CHECK-NEXT: [[CLEANUPACTIVE:%.*]] = alloca i1
+ // CHECK-NEXT: [[TMP:%.*]] = alloca [[A]], align 8
+ // CHECK: [[TMPACTIVE:%.*]] = alloca i1
+ // CHECK-NEXT: store i1 false, i1* [[TMPACTIVE]]
+ // CHECK-NEXT: store i1 false, i1* [[CLEANUPACTIVE]]
+
+ // CHECK: [[COND:%.*]] = trunc i8 {{.*}} to i1
+ // CHECK-NEXT: br i1 [[COND]]
+ return (cond ?
+
+ // CHECK: [[FOO:%.*]] = call i8* @_ZN5test33fooEv()
+ // CHECK-NEXT: [[NEW:%.*]] = call i8* @_ZN5test31AnwEmPvd(i64 8, i8* [[FOO]], double [[CONST:.*]])
+ // CHECK-NEXT: store i8* [[NEW]], i8** [[SAVED0]]
+ // CHECK-NEXT: store i8* [[FOO]], i8** [[SAVED1]]
+ // CHECK-NEXT: store i1 true, i1* [[CLEANUPACTIVE]]
+ // CHECK-NEXT: [[CAST:%.*]] = bitcast i8* [[NEW]] to [[A]]*
+ // CHECK-NEXT: invoke void @_ZN5test35makeAEv([[A]]* sret [[TMP]])
+ // CHECK: store i1 true, i1* [[TMPACTIVE]]
+ // CHECK-NEXT: invoke void @_ZN5test31AC1ERKS0_([[A]]* [[CAST]], [[A]]* [[TMP]])
+ // CHECK: store i1 false, i1* [[CLEANUPACTIVE]]
+ // CHECK-NEXT: br label
+ // -> cond.end
+ new(foo(),10.0) A(makeA()) :
+
+ // CHECK: [[MAKE:%.*]] = invoke [[A]]* @_ZN5test38makeAPtrEv()
+ // CHECK: br label
+ // -> cond.end
+ makeAPtr());
+
+ // cond.end:
+ // CHECK: [[RESULT:%.*]] = phi [[A]]* {{.*}}[[CAST]]{{.*}}[[MAKE]]
+ // CHECK-NEXT: [[ISACTIVE:%.*]] = load i1* [[TMPACTIVE]]
+ // CHECK-NEXT: br i1 [[ISACTIVE]]
+ // CHECK: invoke void @_ZN5test31AD1Ev
+ // CHECK: ret [[A]]* [[RESULT]]
+
+ // in the EH path:
+ // CHECK: [[ISACTIVE:%.*]] = load i1* [[CLEANUPACTIVE]]
+ // CHECK-NEXT: br i1 [[ISACTIVE]]
+ // CHECK: [[V0:%.*]] = load i8** [[SAVED0]]
+ // CHECK-NEXT: [[V1:%.*]] = load i8** [[SAVED1]]
+ // CHECK-NEXT: invoke void @_ZN5test31AdlEPvS1_d(i8* [[V0]], i8* [[V1]], double [[CONST]])
+ }
}
namespace test4 {
@@ -206,5 +258,4 @@
return new(foo(),bar()) A(5);
}
-
}
More information about the llvm-branch-commits
mailing list