aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJohn McCall <rjmccall@apple.com>2010-02-18 03:17:58 +0000
committerJohn McCall <rjmccall@apple.com>2010-02-18 03:17:58 +0000
commita355e07454463b19829ac92ffd115a097faff0e0 (patch)
treecb39601140d9cac19861c911455c00ca7451dfef
parente77f443dbca8cdc23e5aa94a2653367e4a7cbe47 (diff)
Extract out function-body code generation into its own method. No functionality
change. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@96564 91177308-0d34-0410-b5e6-96231b3b80d8
-rw-r--r--lib/CodeGen/CGClass.cpp69
-rw-r--r--lib/CodeGen/CodeGenFunction.cpp126
-rw-r--r--lib/CodeGen/CodeGenFunction.h14
3 files changed, 98 insertions, 111 deletions
diff --git a/lib/CodeGen/CGClass.cpp b/lib/CodeGen/CGClass.cpp
index d9051675ba..863b09c86a 100644
--- a/lib/CodeGen/CGClass.cpp
+++ b/lib/CodeGen/CGClass.cpp
@@ -590,17 +590,44 @@ void CodeGenFunction::EmitClassCopyAssignment(
Callee, ReturnValueSlot(), CallArgs, MD);
}
-/// SynthesizeDefaultConstructor - synthesize a default constructor
-void
-CodeGenFunction::SynthesizeDefaultConstructor(const CXXConstructorDecl *Ctor,
- CXXCtorType Type,
- llvm::Function *Fn,
- const FunctionArgList &Args) {
- assert(!Ctor->isTrivial() && "shouldn't need to generate trivial ctor");
- StartFunction(GlobalDecl(Ctor, Type), Ctor->getResultType(), Fn, Args,
- SourceLocation());
- EmitCtorPrologue(Ctor, Type);
- FinishFunction();
+/// Synthesizes an implicit function body. Since these only arise in
+/// C++, we only do them in C++.
+void CodeGenFunction::SynthesizeImplicitFunctionBody(GlobalDecl GD,
+ llvm::Function *Fn,
+ const FunctionArgList &Args) {
+ const FunctionDecl *FD = cast<FunctionDecl>(GD.getDecl());
+
+ // FIXME: this should become isImplicitlyDefined() once we properly
+ // support that for C++0x.
+ assert(FD->isImplicit() && "Cannot synthesize a non-implicit function");
+
+ if (const CXXConstructorDecl *CD = dyn_cast<CXXConstructorDecl>(FD)) {
+ assert(!CD->isTrivial() && "shouldn't need to synthesize a trivial ctor");
+
+ if (CD->isDefaultConstructor()) {
+ // Sema generates base and member initializers as for this, so
+ // the ctor prologue is good enough here.
+ return;
+ } else {
+ assert(CD->isCopyConstructor());
+ return SynthesizeCXXCopyConstructor(CD, GD.getCtorType(), Fn, Args);
+ }
+ }
+
+ if (isa<CXXDestructorDecl>(FD)) {
+ // The dtor epilogue does everything we'd need to do here.
+ return;
+ }
+
+ const CXXMethodDecl *MD = cast<CXXMethodDecl>(FD);
+
+ // FIXME: in C++0x we might have user-declared copy assignment operators
+ // coexisting with implicitly-defined ones.
+ assert(MD->isCopyAssignment() &&
+ !MD->getParent()->hasUserDeclaredCopyAssignment() &&
+ "Cannot synthesize a method that is not an implicitly-defined "
+ "copy constructor");
+ SynthesizeCXXCopyAssignment(MD, Fn, Args);
}
/// SynthesizeCXXCopyConstructor - This routine implicitly defines body of a
@@ -627,8 +654,6 @@ CodeGenFunction::SynthesizeCXXCopyConstructor(const CXXConstructorDecl *Ctor,
assert(!ClassDecl->hasUserDeclaredCopyConstructor() &&
"SynthesizeCXXCopyConstructor - copy constructor has definition already");
assert(!Ctor->isTrivial() && "shouldn't need to generate trivial ctor");
- StartFunction(GlobalDecl(Ctor, Type), Ctor->getResultType(), Fn, Args,
- SourceLocation());
FunctionArgList::const_iterator i = Args.begin();
const VarDecl *ThisArg = i->first;
@@ -698,7 +723,6 @@ CodeGenFunction::SynthesizeCXXCopyConstructor(const CXXConstructorDecl *Ctor,
}
InitializeVtablePtrs(ClassDecl);
- FinishFunction();
}
/// SynthesizeCXXCopyAssignment - Implicitly define copy assignment operator.
@@ -728,7 +752,6 @@ void CodeGenFunction::SynthesizeCXXCopyAssignment(const CXXMethodDecl *CD,
const CXXRecordDecl *ClassDecl = cast<CXXRecordDecl>(CD->getDeclContext());
assert(!ClassDecl->hasUserDeclaredCopyAssignment() &&
"SynthesizeCXXCopyAssignment - copy assignment has user declaration");
- StartFunction(CD, CD->getResultType(), Fn, Args, SourceLocation());
FunctionArgList::const_iterator i = Args.begin();
const VarDecl *ThisArg = i->first;
@@ -796,8 +819,6 @@ void CodeGenFunction::SynthesizeCXXCopyAssignment(const CXXMethodDecl *CD,
// return *this;
Builder.CreateStore(LoadOfThis, ReturnValue);
-
- FinishFunction();
}
static void EmitBaseInitializer(CodeGenFunction &CGF,
@@ -1054,20 +1075,6 @@ void CodeGenFunction::EmitDtorEpilogue(const CXXDestructorDecl *DD,
}
}
-void CodeGenFunction::SynthesizeDefaultDestructor(const CXXDestructorDecl *Dtor,
- CXXDtorType DtorType,
- llvm::Function *Fn,
- const FunctionArgList &Args) {
- assert(!Dtor->getParent()->hasUserDeclaredDestructor() &&
- "SynthesizeDefaultDestructor - destructor has user declaration");
-
- StartFunction(GlobalDecl(Dtor, DtorType), Dtor->getResultType(), Fn, Args,
- SourceLocation());
- InitializeVtablePtrs(Dtor->getParent());
- EmitDtorEpilogue(Dtor, DtorType);
- FinishFunction();
-}
-
/// EmitCXXAggrConstructorCall - This routine essentially creates a (nested)
/// for-loop to call the default constructor on individual members of the
/// array.
diff --git a/lib/CodeGen/CodeGenFunction.cpp b/lib/CodeGen/CodeGenFunction.cpp
index d803a05aa9..ddf4e6431d 100644
--- a/lib/CodeGen/CodeGenFunction.cpp
+++ b/lib/CodeGen/CodeGenFunction.cpp
@@ -241,6 +241,53 @@ void CodeGenFunction::StartFunction(GlobalDecl GD, QualType RetTy,
}
}
+void CodeGenFunction::GenerateBody(GlobalDecl GD, llvm::Function *Fn,
+ FunctionArgList &Args) {
+ const FunctionDecl *FD = cast<FunctionDecl>(GD.getDecl());
+
+ Stmt *Body = FD->getBody();
+ assert((Body || FD->isImplicit()) && "non-implicit function def has no body");
+
+ // Emit special ctor/dtor prologues.
+ llvm::BasicBlock *DtorEpilogue = 0;
+ if (const CXXConstructorDecl *CD = dyn_cast<CXXConstructorDecl>(FD)) {
+ EmitCtorPrologue(CD, GD.getCtorType());
+ } else if (const CXXDestructorDecl *DD = dyn_cast<CXXDestructorDecl>(FD)) {
+ DtorEpilogue = createBasicBlock("dtor.epilogue");
+ PushCleanupBlock(DtorEpilogue);
+
+ InitializeVtablePtrs(DD->getParent());
+ }
+
+ // Emit the body of the function.
+ if (!Body)
+ SynthesizeImplicitFunctionBody(GD, Fn, Args);
+ else {
+ if (isa<CXXTryStmt>(Body))
+ OuterTryBlock = cast<CXXTryStmt>(Body);
+
+ EmitStmt(Body);
+ }
+
+ // Emit special ctor/ctor epilogues.
+ if (isa<CXXConstructorDecl>(FD)) {
+ // If any of the member initializers are temporaries bound to references
+ // make sure to emit their destructors.
+ EmitCleanupBlocks(0);
+ } else if (const CXXDestructorDecl *DD = dyn_cast<CXXDestructorDecl>(FD)) {
+ CleanupBlockInfo Info = PopCleanupBlock();
+ assert(Info.CleanupBlock == DtorEpilogue && "Block mismatch!");
+
+ EmitBlock(DtorEpilogue);
+ EmitDtorEpilogue(DD, GD.getDtorType());
+
+ if (Info.SwitchBlock)
+ EmitBlock(Info.SwitchBlock);
+ if (Info.EndBlock)
+ EmitBlock(Info.EndBlock);
+ }
+}
+
void CodeGenFunction::GenerateCode(GlobalDecl GD, llvm::Function *Fn) {
const FunctionDecl *FD = cast<FunctionDecl>(GD.getDecl());
@@ -284,80 +331,17 @@ void CodeGenFunction::GenerateCode(GlobalDecl GD, llvm::Function *Fn) {
FProto->getArgType(i)));
}
- if (const CompoundStmt *S = FD->getCompoundBody()) {
- StartFunction(GD, FD->getResultType(), Fn, Args, S->getLBracLoc());
-
- if (const CXXConstructorDecl *CD = dyn_cast<CXXConstructorDecl>(FD)) {
- EmitCtorPrologue(CD, GD.getCtorType());
- EmitStmt(S);
-
- // If any of the member initializers are temporaries bound to references
- // make sure to emit their destructors.
- EmitCleanupBlocks(0);
-
- } else if (const CXXDestructorDecl *DD = dyn_cast<CXXDestructorDecl>(FD)) {
- llvm::BasicBlock *DtorEpilogue = createBasicBlock("dtor.epilogue");
- PushCleanupBlock(DtorEpilogue);
+ SourceRange BodyRange;
+ if (Stmt *Body = FD->getBody()) BodyRange = Body->getSourceRange();
- InitializeVtablePtrs(DD->getParent());
+ // Emit the standard function prologue.
+ StartFunction(GD, FD->getResultType(), Fn, Args, BodyRange.getBegin());
- EmitStmt(S);
-
- CleanupBlockInfo Info = PopCleanupBlock();
+ // Generate the body of the function.
+ GenerateBody(GD, Fn, Args);
- assert(Info.CleanupBlock == DtorEpilogue && "Block mismatch!");
- EmitBlock(DtorEpilogue);
- EmitDtorEpilogue(DD, GD.getDtorType());
-
- if (Info.SwitchBlock)
- EmitBlock(Info.SwitchBlock);
- if (Info.EndBlock)
- EmitBlock(Info.EndBlock);
- } else {
- // Just a regular function, emit its body.
- EmitStmt(S);
- }
-
- FinishFunction(S->getRBracLoc());
- } else if (FD->isImplicit()) {
- const CXXRecordDecl *ClassDecl =
- cast<CXXRecordDecl>(FD->getDeclContext());
- (void) ClassDecl;
- if (const CXXConstructorDecl *CD = dyn_cast<CXXConstructorDecl>(FD)) {
- // FIXME: For C++0x, we want to look for implicit *definitions* of
- // these special member functions, rather than implicit *declarations*.
- if (CD->isCopyConstructor()) {
- assert(!ClassDecl->hasUserDeclaredCopyConstructor() &&
- "Cannot synthesize a non-implicit copy constructor");
- SynthesizeCXXCopyConstructor(CD, GD.getCtorType(), Fn, Args);
- } else if (CD->isDefaultConstructor()) {
- assert(!ClassDecl->hasUserDeclaredConstructor() &&
- "Cannot synthesize a non-implicit default constructor.");
- SynthesizeDefaultConstructor(CD, GD.getCtorType(), Fn, Args);
- } else {
- assert(false && "Implicit constructor cannot be synthesized");
- }
- } else if (const CXXDestructorDecl *CD = dyn_cast<CXXDestructorDecl>(FD)) {
- assert(!ClassDecl->hasUserDeclaredDestructor() &&
- "Cannot synthesize a non-implicit destructor");
- SynthesizeDefaultDestructor(CD, GD.getDtorType(), Fn, Args);
- } else if (const CXXMethodDecl *MD = dyn_cast<CXXMethodDecl>(FD)) {
- assert(MD->isCopyAssignment() &&
- !ClassDecl->hasUserDeclaredCopyAssignment() &&
- "Cannot synthesize a method that is not an implicit-defined "
- "copy constructor");
- SynthesizeCXXCopyAssignment(MD, Fn, Args);
- } else {
- assert(false && "Cannot synthesize unknown implicit function");
- }
- } else if (const Stmt *S = FD->getBody()) {
- if (const CXXTryStmt *TS = dyn_cast<CXXTryStmt>(S)) {
- OuterTryBlock = TS;
- StartFunction(GD, FD->getResultType(), Fn, Args, TS->getTryLoc());
- EmitStmt(TS);
- FinishFunction(TS->getEndLoc());
- }
- }
+ // Emit the standard function epilogue.
+ FinishFunction(BodyRange.getEnd());
// Destroy the 'this' declaration.
if (CXXThisDecl)
diff --git a/lib/CodeGen/CodeGenFunction.h b/lib/CodeGen/CodeGenFunction.h
index a694b894df..29c75fdb8e 100644
--- a/lib/CodeGen/CodeGenFunction.h
+++ b/lib/CodeGen/CodeGenFunction.h
@@ -494,6 +494,8 @@ public:
const FunctionArgList &Args,
SourceLocation StartLoc);
+ void GenerateBody(GlobalDecl GD, llvm::Function *Fn, FunctionArgList &Args);
+
/// EmitReturnBlock - Emit the unified return block, trying to avoid its
/// emission when possible.
void EmitReturnBlock();
@@ -536,15 +538,9 @@ public:
llvm::Function *Fn,
const FunctionArgList &Args);
- void SynthesizeDefaultConstructor(const CXXConstructorDecl *Ctor,
- CXXCtorType Type,
- llvm::Function *Fn,
- const FunctionArgList &Args);
-
- void SynthesizeDefaultDestructor(const CXXDestructorDecl *Dtor,
- CXXDtorType Type,
- llvm::Function *Fn,
- const FunctionArgList &Args);
+ void SynthesizeImplicitFunctionBody(GlobalDecl GD,
+ llvm::Function *Fn,
+ const FunctionArgList &Args);
/// EmitDtorEpilogue - Emit all code that comes at the end of class's
/// destructor. This is to call destructors on members and base classes in