diff options
| author | Larisse Voufo <lvoufo@google.com> | 2015-02-25 23:48:43 +0000 |
|---|---|---|
| committer | Larisse Voufo <lvoufo@google.com> | 2015-02-25 23:48:43 +0000 |
| commit | 697b32a0cb702f2cc50329e25bfad15abc5beb9b (patch) | |
| tree | 8e114ec40833432cc5c99ed92341e80413d440a5 /clang/lib/CodeGen | |
| parent | 17151eba64be0688d51991321e65addb88910cd9 (diff) | |
| download | bcm5719-llvm-697b32a0cb702f2cc50329e25bfad15abc5beb9b.tar.gz bcm5719-llvm-697b32a0cb702f2cc50329e25bfad15abc5beb9b.zip | |
Improvement on sized deallocation from r230160:
Do not declare sized deallocation functions dependently on whether it is found in global scope. Instead, enforce the branching in emitted code by (1) declaring the functions extern_weak and (2) emitting sized delete expressions as a branching between both forms delete.
llvm-svn: 230580
Diffstat (limited to 'clang/lib/CodeGen')
| -rw-r--r-- | clang/lib/CodeGen/CGExprCXX.cpp | 87 |
1 files changed, 82 insertions, 5 deletions
diff --git a/clang/lib/CodeGen/CGExprCXX.cpp b/clang/lib/CodeGen/CGExprCXX.cpp index 6852d3afc7f..425a968c13a 100644 --- a/clang/lib/CodeGen/CGExprCXX.cpp +++ b/clang/lib/CodeGen/CGExprCXX.cpp @@ -1422,6 +1422,71 @@ CodeGenFunction::pushCallObjectDeleteCleanup(const FunctionDecl *OperatorDelete, OperatorDelete, ElementType); } +static void EmitDelete(CodeGenFunction &CGF, + const CXXDeleteExpr *DE, + llvm::Value *Ptr, + QualType ElementType); + +static void EmitSizedDelete(CodeGenFunction &CGF, + const CXXDeleteExpr *DE, + llvm::Value *Ptr, + QualType ElementType, + FunctionDecl* UnsizedDealloc) { + + if (CGF.getLangOpts().DefineSizedDeallocation) { + // The delete operator in use is fixed. So simply emit the delete expr. + EmitDelete(CGF, DE, Ptr, ElementType); + return; + } + + assert(UnsizedDealloc && "We must be emiting a 'sized' delete expr"); + + // Branch off over the value of operator delete: + // Use the sized form if available, and default on the unsized form otherwise. + llvm::BasicBlock *ThenBlock = CGF.createBasicBlock("if.then"); + llvm::BasicBlock *ContBlock = CGF.createBasicBlock("if.end"); + llvm::BasicBlock *ElseBlock = CGF.createBasicBlock("if.else"); + + // Emit the condition. + const FunctionDecl *OpDelFD = DE->getOperatorDelete(); + llvm::Value *OpDelAddr = CGF.CGM.GetAddrOfFunction(OpDelFD); + //llvm::Function *OpDel = dyn_cast<llvm::Function>(OpDelAddr); + llvm::Value *SDE = CGF.Builder.CreateIsNotNull(OpDelAddr, "sized.del.exists"); + CGF.Builder.CreateCondBr(SDE, ThenBlock, ElseBlock); + + // Emit the 'then' code. + CGF.EmitBlock(ThenBlock); + EmitDelete(CGF, DE, Ptr, ElementType); + CGF.EmitBranch(ContBlock); + + // Compute the 'unsized' delete expr. + CXXDeleteExpr * E = const_cast<CXXDeleteExpr*>(DE); + CXXDeleteExpr *UnsizedDE = + new (CGF.getContext()) CXXDeleteExpr(CGF.getContext().VoidTy, + E->isGlobalDelete(), + E->isArrayForm(), + E->isArrayFormAsWritten(), + E->doesUsualArrayDeleteWantSize(), + UnsizedDealloc, + E->getArgument(), + E->getLocStart()); + // Emit the 'else' code. + { + // There is no need to emit line number for an unconditional branch. + auto NL = ApplyDebugLocation::CreateEmpty(CGF); + CGF.EmitBlock(ElseBlock); + } + EmitDelete(CGF, UnsizedDE, Ptr, ElementType); + { + // There is no need to emit line number for an unconditional branch. + auto NL = ApplyDebugLocation::CreateEmpty(CGF); + CGF.EmitBranch(ContBlock); + } + + // Emit the continuation block for code after the if. + CGF.EmitBlock(ContBlock, true); +} + /// Emit the code for deleting a single object. static void EmitObjectDelete(CodeGenFunction &CGF, const CXXDeleteExpr *DE, @@ -1581,6 +1646,17 @@ static void EmitArrayDelete(CodeGenFunction &CGF, CGF.PopCleanupBlock(); } +static void EmitDelete(CodeGenFunction &CGF, + const CXXDeleteExpr *DE, + llvm::Value *Ptr, + QualType ElementType) { + if (DE->isArrayForm()) { + EmitArrayDelete(CGF, DE, Ptr, ElementType); + } else { + EmitObjectDelete(CGF, DE, Ptr, ElementType); + } +} + void CodeGenFunction::EmitCXXDeleteExpr(const CXXDeleteExpr *E) { const Expr *Arg = E->getArgument(); llvm::Value *Ptr = EmitScalarExpr(Arg); @@ -1620,11 +1696,12 @@ void CodeGenFunction::EmitCXXDeleteExpr(const CXXDeleteExpr *E) { assert(ConvertTypeForMem(DeleteTy) == cast<llvm::PointerType>(Ptr->getType())->getElementType()); - if (E->isArrayForm()) { - EmitArrayDelete(*this, E, Ptr, DeleteTy); - } else { - EmitObjectDelete(*this, E, Ptr, DeleteTy); - } + const FunctionDecl *Dealloc = E->getOperatorDelete(); + if (FunctionDecl* UnsizedDealloc = + Dealloc->getCorrespondingUnsizedGlobalDeallocationFunction()) + EmitSizedDelete(*this, E, Ptr, DeleteTy, UnsizedDealloc); + else + EmitDelete(*this, E, Ptr, DeleteTy); EmitBlock(DeleteEnd); } |

