forked from OSchip/llvm-project
Extract out function-body code generation into its own method. No functionality
change. llvm-svn: 96564
This commit is contained in:
parent
bff31437ef
commit
89b12b34f6
|
@ -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.
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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
|
||||
|
|
Loading…
Reference in New Issue