summaryrefslogtreecommitdiffstats
path: root/clang/lib/CodeGen
diff options
context:
space:
mode:
authorRichard Smith <richard-llvm@metafoo.co.uk>2013-11-05 09:12:18 +0000
committerRichard Smith <richard-llvm@metafoo.co.uk>2013-11-05 09:12:18 +0000
commitb47c36f8e113f238124fa00ae7d444d02f5b470e (patch)
tree1403473a0d2940847dbc1f4693828ec093abc1b7 /clang/lib/CodeGen
parent2d1d3ca1cc0255faad99e2eb77cfe4b269410152 (diff)
downloadbcm5719-llvm-b47c36f8e113f238124fa00ae7d444d02f5b470e.tar.gz
bcm5719-llvm-b47c36f8e113f238124fa00ae7d444d02f5b470e.zip
C++1y sized deallocation: if we have a use, but not a definition, of a sized
deallocation function (and the corresponding unsized deallocation function has been declared), emit a weak discardable definition of the function that forwards to the corresponding unsized deallocation. This allows a C++ standard library implementation to provide both a sized and an unsized deallocation function, where the unsized one does not just call the sized one, for instance by putting both in the same object file within an archive. llvm-svn: 194055
Diffstat (limited to 'clang/lib/CodeGen')
-rw-r--r--clang/lib/CodeGen/CGClass.cpp2
-rw-r--r--clang/lib/CodeGen/CGExpr.cpp4
-rw-r--r--clang/lib/CodeGen/CodeGenFunction.cpp32
-rw-r--r--clang/lib/CodeGen/CodeGenFunction.h2
-rw-r--r--clang/lib/CodeGen/CodeGenModule.cpp6
5 files changed, 34 insertions, 12 deletions
diff --git a/clang/lib/CodeGen/CGClass.cpp b/clang/lib/CodeGen/CGClass.cpp
index af8cbbc48c2..4848d7565d4 100644
--- a/clang/lib/CodeGen/CGClass.cpp
+++ b/clang/lib/CodeGen/CGClass.cpp
@@ -2180,7 +2180,7 @@ void CodeGenFunction::EmitLambdaToBlockPointerBody(FunctionArgList &Args) {
return;
}
- EmitFunctionBody(Args);
+ EmitFunctionBody(Args, cast<FunctionDecl>(CurGD.getDecl())->getBody());
}
void CodeGenFunction::EmitLambdaDelegatingInvokeBody(const CXXMethodDecl *MD) {
diff --git a/clang/lib/CodeGen/CGExpr.cpp b/clang/lib/CodeGen/CGExpr.cpp
index 221d132ee0b..4a427d540f6 100644
--- a/clang/lib/CodeGen/CGExpr.cpp
+++ b/clang/lib/CodeGen/CGExpr.cpp
@@ -1824,8 +1824,8 @@ LValue CodeGenFunction::EmitDeclRefLValue(const DeclRefExpr *E) {
return LV;
}
- if (const FunctionDecl *fn = dyn_cast<FunctionDecl>(ND))
- return EmitFunctionDeclLValue(*this, E, fn);
+ if (const FunctionDecl *FD = dyn_cast<FunctionDecl>(ND))
+ return EmitFunctionDeclLValue(*this, E, FD);
llvm_unreachable("Unhandled DeclRefExpr");
}
diff --git a/clang/lib/CodeGen/CodeGenFunction.cpp b/clang/lib/CodeGen/CodeGenFunction.cpp
index 3ec890383c9..ce1b44559dc 100644
--- a/clang/lib/CodeGen/CodeGenFunction.cpp
+++ b/clang/lib/CodeGen/CodeGenFunction.cpp
@@ -643,13 +643,12 @@ void CodeGenFunction::StartFunction(GlobalDecl GD,
DI->EmitLocation(Builder, StartLoc);
}
-void CodeGenFunction::EmitFunctionBody(FunctionArgList &Args) {
- const FunctionDecl *FD = cast<FunctionDecl>(CurGD.getDecl());
- assert(FD->getBody());
- if (const CompoundStmt *S = dyn_cast<CompoundStmt>(FD->getBody()))
+void CodeGenFunction::EmitFunctionBody(FunctionArgList &Args,
+ const Stmt *Body) {
+ if (const CompoundStmt *S = dyn_cast<CompoundStmt>(Body))
EmitCompoundStmtWithoutScope(*S);
else
- EmitStmt(FD->getBody());
+ EmitStmt(Body);
}
/// Tries to mark the given function nounwind based on the
@@ -672,6 +671,17 @@ static void TryMarkNoThrow(llvm::Function *F) {
F->setDoesNotThrow();
}
+static void EmitSizedDeallocationFunction(CodeGenFunction &CGF,
+ const FunctionDecl *UnsizedDealloc) {
+ // This is a weak discardable definition of the sized deallocation function.
+ CGF.CurFn->setLinkage(llvm::Function::LinkOnceAnyLinkage);
+
+ // Call the unsized deallocation function and forward the first argument
+ // unchanged.
+ llvm::Constant *Unsized = CGF.CGM.GetAddrOfFunction(UnsizedDealloc);
+ CGF.Builder.CreateCall(Unsized, &*CGF.CurFn->arg_begin());
+}
+
void CodeGenFunction::GenerateCode(GlobalDecl GD, llvm::Function *Fn,
const CGFunctionInfo &FnInfo) {
const FunctionDecl *FD = cast<FunctionDecl>(GD.getDecl());
@@ -726,9 +736,15 @@ void CodeGenFunction::GenerateCode(GlobalDecl GD, llvm::Function *Fn,
// Implicit copy-assignment gets the same special treatment as implicit
// copy-constructors.
emitImplicitAssignmentOperatorBody(Args);
- }
- else
- EmitFunctionBody(Args);
+ } else if (Stmt *Body = FD->getBody()) {
+ EmitFunctionBody(Args, Body);
+ } else if (FunctionDecl *UnsizedDealloc =
+ FD->getCorrespondingUnsizedGlobalDeallocationFunction()) {
+ // Global sized deallocation functions get an implicit weak definition if
+ // they don't have an explicit definition.
+ EmitSizedDeallocationFunction(*this, UnsizedDealloc);
+ } else
+ llvm_unreachable("no definition for emitted function");
// C++11 [stmt.return]p2:
// Flowing off the end of a function [...] results in undefined behavior in
diff --git a/clang/lib/CodeGen/CodeGenFunction.h b/clang/lib/CodeGen/CodeGenFunction.h
index b07e903b49f..98c090fa149 100644
--- a/clang/lib/CodeGen/CodeGenFunction.h
+++ b/clang/lib/CodeGen/CodeGenFunction.h
@@ -1136,7 +1136,7 @@ public:
void EmitConstructorBody(FunctionArgList &Args);
void EmitDestructorBody(FunctionArgList &Args);
void emitImplicitAssignmentOperatorBody(FunctionArgList &Args);
- void EmitFunctionBody(FunctionArgList &Args);
+ void EmitFunctionBody(FunctionArgList &Args, const Stmt *Body);
void EmitForwardingCallToLambda(const CXXMethodDecl *LambdaCallOperator,
CallArgList &CallArgs);
diff --git a/clang/lib/CodeGen/CodeGenModule.cpp b/clang/lib/CodeGen/CodeGenModule.cpp
index d0f34dddca3..c34f8332699 100644
--- a/clang/lib/CodeGen/CodeGenModule.cpp
+++ b/clang/lib/CodeGen/CodeGenModule.cpp
@@ -1406,6 +1406,12 @@ CodeGenModule::GetOrCreateLLVMFunction(StringRef MangledName,
DeferredDeclsToEmit.push_back(DDI->second);
DeferredDecls.erase(DDI);
+ // Otherwise, if this is a sized deallocation function, emit a weak definition
+ // for it at the end of the translation unit.
+ } else if (D && cast<FunctionDecl>(D)
+ ->getCorrespondingUnsizedGlobalDeallocationFunction()) {
+ DeferredDeclsToEmit.push_back(GD);
+
// Otherwise, there are cases we have to worry about where we're
// using a declaration for which we must emit a definition but where
// we might not find a top-level definition:
OpenPOWER on IntegriCloud