Extract out function-body code generation into its own method. No functionality

change.

llvm-svn: 96564
This commit is contained in:
John McCall 2010-02-18 03:17:58 +00:00
parent bff31437ef
commit 89b12b34f6
3 changed files with 98 additions and 111 deletions

View File

@ -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.

View File

@ -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());
SourceRange BodyRange;
if (Stmt *Body = FD->getBody()) BodyRange = Body->getSourceRange();
if (const CXXConstructorDecl *CD = dyn_cast<CXXConstructorDecl>(FD)) {
EmitCtorPrologue(CD, GD.getCtorType());
EmitStmt(S);
// Emit the standard function prologue.
StartFunction(GD, FD->getResultType(), Fn, Args, BodyRange.getBegin());
// If any of the member initializers are temporaries bound to references
// make sure to emit their destructors.
EmitCleanupBlocks(0);
// Generate the body of the function.
GenerateBody(GD, Fn, Args);
} else if (const CXXDestructorDecl *DD = dyn_cast<CXXDestructorDecl>(FD)) {
llvm::BasicBlock *DtorEpilogue = createBasicBlock("dtor.epilogue");
PushCleanupBlock(DtorEpilogue);
InitializeVtablePtrs(DD->getParent());
EmitStmt(S);
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);
} 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)

View File

@ -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