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);
|
Callee, ReturnValueSlot(), CallArgs, MD);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// SynthesizeDefaultConstructor - synthesize a default constructor
|
/// Synthesizes an implicit function body. Since these only arise in
|
||||||
void
|
/// C++, we only do them in C++.
|
||||||
CodeGenFunction::SynthesizeDefaultConstructor(const CXXConstructorDecl *Ctor,
|
void CodeGenFunction::SynthesizeImplicitFunctionBody(GlobalDecl GD,
|
||||||
CXXCtorType Type,
|
llvm::Function *Fn,
|
||||||
llvm::Function *Fn,
|
const FunctionArgList &Args) {
|
||||||
const FunctionArgList &Args) {
|
const FunctionDecl *FD = cast<FunctionDecl>(GD.getDecl());
|
||||||
assert(!Ctor->isTrivial() && "shouldn't need to generate trivial ctor");
|
|
||||||
StartFunction(GlobalDecl(Ctor, Type), Ctor->getResultType(), Fn, Args,
|
// FIXME: this should become isImplicitlyDefined() once we properly
|
||||||
SourceLocation());
|
// support that for C++0x.
|
||||||
EmitCtorPrologue(Ctor, Type);
|
assert(FD->isImplicit() && "Cannot synthesize a non-implicit function");
|
||||||
FinishFunction();
|
|
||||||
|
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
|
/// SynthesizeCXXCopyConstructor - This routine implicitly defines body of a
|
||||||
|
@ -627,8 +654,6 @@ CodeGenFunction::SynthesizeCXXCopyConstructor(const CXXConstructorDecl *Ctor,
|
||||||
assert(!ClassDecl->hasUserDeclaredCopyConstructor() &&
|
assert(!ClassDecl->hasUserDeclaredCopyConstructor() &&
|
||||||
"SynthesizeCXXCopyConstructor - copy constructor has definition already");
|
"SynthesizeCXXCopyConstructor - copy constructor has definition already");
|
||||||
assert(!Ctor->isTrivial() && "shouldn't need to generate trivial ctor");
|
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();
|
FunctionArgList::const_iterator i = Args.begin();
|
||||||
const VarDecl *ThisArg = i->first;
|
const VarDecl *ThisArg = i->first;
|
||||||
|
@ -698,7 +723,6 @@ CodeGenFunction::SynthesizeCXXCopyConstructor(const CXXConstructorDecl *Ctor,
|
||||||
}
|
}
|
||||||
|
|
||||||
InitializeVtablePtrs(ClassDecl);
|
InitializeVtablePtrs(ClassDecl);
|
||||||
FinishFunction();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// SynthesizeCXXCopyAssignment - Implicitly define copy assignment operator.
|
/// SynthesizeCXXCopyAssignment - Implicitly define copy assignment operator.
|
||||||
|
@ -728,7 +752,6 @@ void CodeGenFunction::SynthesizeCXXCopyAssignment(const CXXMethodDecl *CD,
|
||||||
const CXXRecordDecl *ClassDecl = cast<CXXRecordDecl>(CD->getDeclContext());
|
const CXXRecordDecl *ClassDecl = cast<CXXRecordDecl>(CD->getDeclContext());
|
||||||
assert(!ClassDecl->hasUserDeclaredCopyAssignment() &&
|
assert(!ClassDecl->hasUserDeclaredCopyAssignment() &&
|
||||||
"SynthesizeCXXCopyAssignment - copy assignment has user declaration");
|
"SynthesizeCXXCopyAssignment - copy assignment has user declaration");
|
||||||
StartFunction(CD, CD->getResultType(), Fn, Args, SourceLocation());
|
|
||||||
|
|
||||||
FunctionArgList::const_iterator i = Args.begin();
|
FunctionArgList::const_iterator i = Args.begin();
|
||||||
const VarDecl *ThisArg = i->first;
|
const VarDecl *ThisArg = i->first;
|
||||||
|
@ -796,8 +819,6 @@ void CodeGenFunction::SynthesizeCXXCopyAssignment(const CXXMethodDecl *CD,
|
||||||
|
|
||||||
// return *this;
|
// return *this;
|
||||||
Builder.CreateStore(LoadOfThis, ReturnValue);
|
Builder.CreateStore(LoadOfThis, ReturnValue);
|
||||||
|
|
||||||
FinishFunction();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void EmitBaseInitializer(CodeGenFunction &CGF,
|
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)
|
/// EmitCXXAggrConstructorCall - This routine essentially creates a (nested)
|
||||||
/// for-loop to call the default constructor on individual members of the
|
/// for-loop to call the default constructor on individual members of the
|
||||||
/// array.
|
/// 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) {
|
void CodeGenFunction::GenerateCode(GlobalDecl GD, llvm::Function *Fn) {
|
||||||
const FunctionDecl *FD = cast<FunctionDecl>(GD.getDecl());
|
const FunctionDecl *FD = cast<FunctionDecl>(GD.getDecl());
|
||||||
|
|
||||||
|
@ -284,80 +331,17 @@ void CodeGenFunction::GenerateCode(GlobalDecl GD, llvm::Function *Fn) {
|
||||||
FProto->getArgType(i)));
|
FProto->getArgType(i)));
|
||||||
}
|
}
|
||||||
|
|
||||||
if (const CompoundStmt *S = FD->getCompoundBody()) {
|
SourceRange BodyRange;
|
||||||
StartFunction(GD, FD->getResultType(), Fn, Args, S->getLBracLoc());
|
if (Stmt *Body = FD->getBody()) BodyRange = Body->getSourceRange();
|
||||||
|
|
||||||
if (const CXXConstructorDecl *CD = dyn_cast<CXXConstructorDecl>(FD)) {
|
// Emit the standard function prologue.
|
||||||
EmitCtorPrologue(CD, GD.getCtorType());
|
StartFunction(GD, FD->getResultType(), Fn, Args, BodyRange.getBegin());
|
||||||
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);
|
|
||||||
|
|
||||||
InitializeVtablePtrs(DD->getParent());
|
// Generate the body of the function.
|
||||||
|
GenerateBody(GD, Fn, Args);
|
||||||
|
|
||||||
EmitStmt(S);
|
// Emit the standard function epilogue.
|
||||||
|
FinishFunction(BodyRange.getEnd());
|
||||||
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());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Destroy the 'this' declaration.
|
// Destroy the 'this' declaration.
|
||||||
if (CXXThisDecl)
|
if (CXXThisDecl)
|
||||||
|
|
|
@ -494,6 +494,8 @@ public:
|
||||||
const FunctionArgList &Args,
|
const FunctionArgList &Args,
|
||||||
SourceLocation StartLoc);
|
SourceLocation StartLoc);
|
||||||
|
|
||||||
|
void GenerateBody(GlobalDecl GD, llvm::Function *Fn, FunctionArgList &Args);
|
||||||
|
|
||||||
/// EmitReturnBlock - Emit the unified return block, trying to avoid its
|
/// EmitReturnBlock - Emit the unified return block, trying to avoid its
|
||||||
/// emission when possible.
|
/// emission when possible.
|
||||||
void EmitReturnBlock();
|
void EmitReturnBlock();
|
||||||
|
@ -536,15 +538,9 @@ public:
|
||||||
llvm::Function *Fn,
|
llvm::Function *Fn,
|
||||||
const FunctionArgList &Args);
|
const FunctionArgList &Args);
|
||||||
|
|
||||||
void SynthesizeDefaultConstructor(const CXXConstructorDecl *Ctor,
|
void SynthesizeImplicitFunctionBody(GlobalDecl GD,
|
||||||
CXXCtorType Type,
|
llvm::Function *Fn,
|
||||||
llvm::Function *Fn,
|
const FunctionArgList &Args);
|
||||||
const FunctionArgList &Args);
|
|
||||||
|
|
||||||
void SynthesizeDefaultDestructor(const CXXDestructorDecl *Dtor,
|
|
||||||
CXXDtorType Type,
|
|
||||||
llvm::Function *Fn,
|
|
||||||
const FunctionArgList &Args);
|
|
||||||
|
|
||||||
/// EmitDtorEpilogue - Emit all code that comes at the end of class's
|
/// EmitDtorEpilogue - Emit all code that comes at the end of class's
|
||||||
/// destructor. This is to call destructors on members and base classes in
|
/// destructor. This is to call destructors on members and base classes in
|
||||||
|
|
Loading…
Reference in New Issue