Teach IR generation to return 'this' from constructors and destructors

under the ARM ABI.



git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@112588 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
John McCall 2010-08-31 07:33:07 +00:00
Родитель 1baf2f778c
Коммит 4c40d98ab7
19 изменённых файлов: 455 добавлений и 102 удалений

Просмотреть файл

@ -410,3 +410,29 @@ bool CGCXXABI::isZeroInitializable(const MemberPointerType *MPT) {
// Fake answer.
return true;
}
void CGCXXABI::BuildThisParam(CodeGenFunction &CGF, FunctionArgList &Params) {
const CXXMethodDecl *MD = cast<CXXMethodDecl>(CGF.CurGD.getDecl());
// FIXME: I'm not entirely sure I like using a fake decl just for code
// generation. Maybe we can come up with a better way?
ImplicitParamDecl *ThisDecl
= ImplicitParamDecl::Create(CGM.getContext(), 0, MD->getLocation(),
&CGM.getContext().Idents.get("this"),
MD->getThisType(CGM.getContext()));
Params.push_back(std::make_pair(ThisDecl, ThisDecl->getType()));
getThisDecl(CGF) = ThisDecl;
}
void CGCXXABI::EmitThisParam(CodeGenFunction &CGF) {
/// Initialize the 'this' slot.
assert(getThisDecl(CGF) && "no 'this' variable for function");
getThisValue(CGF)
= CGF.Builder.CreateLoad(CGF.GetAddrOfLocalVar(getThisDecl(CGF)),
"this");
}
void CGCXXABI::EmitReturnFromThunk(CodeGenFunction &CGF,
RValue RV, QualType ResultType) {
CGF.EmitReturnOfRValue(RV, ResultType);
}

Просмотреть файл

@ -15,19 +15,23 @@
#ifndef CLANG_CODEGEN_CXXABI_H
#define CLANG_CODEGEN_CXXABI_H
#include "CodeGenFunction.h"
namespace llvm {
class Constant;
class Type;
class Value;
template <class T> class SmallVectorImpl;
}
namespace clang {
class CastExpr;
class CXXConstructorDecl;
class CXXDestructorDecl;
class CXXMethodDecl;
class CXXRecordDecl;
class FieldDecl;
class MemberPointerType;
class QualType;
namespace CodeGen {
class CodeGenFunction;
@ -41,6 +45,28 @@ protected:
CGCXXABI(CodeGenModule &CGM) : CGM(CGM) {}
protected:
ImplicitParamDecl *&getThisDecl(CodeGenFunction &CGF) {
return CGF.CXXThisDecl;
}
llvm::Value *&getThisValue(CodeGenFunction &CGF) {
return CGF.CXXThisValue;
}
ImplicitParamDecl *&getVTTDecl(CodeGenFunction &CGF) {
return CGF.CXXVTTDecl;
}
llvm::Value *&getVTTValue(CodeGenFunction &CGF) {
return CGF.CXXVTTValue;
}
/// Build a parameter variable suitable for 'this'.
void BuildThisParam(CodeGenFunction &CGF, FunctionArgList &Params);
/// Perform prolog initialization of the parameter variable suitable
/// for 'this' emitted by BuildThisParam.
void EmitThisParam(CodeGenFunction &CGF);
public:
virtual ~CGCXXABI();
@ -99,6 +125,45 @@ public:
EmitMemberPointerIsNotNull(CodeGenFunction &CGF,
llvm::Value *MemPtr,
const MemberPointerType *MPT);
/// Build the signature of the given constructor variant by adding
/// any required parameters. For convenience, ResTy has been
/// initialized to 'void', and ArgTys has been initialized with the
/// type of 'this' (although this may be changed by the ABI) and
/// will have the formal parameters added to it afterwards.
///
/// If there are ever any ABIs where the implicit parameters are
/// intermixed with the formal parameters, we can address those
/// then.
virtual void BuildConstructorSignature(const CXXConstructorDecl *Ctor,
CXXCtorType T,
CanQualType &ResTy,
llvm::SmallVectorImpl<CanQualType> &ArgTys) = 0;
/// Build the signature of the given destructor variant by adding
/// any required parameters. For convenience, ResTy has been
/// initialized to 'void' and ArgTys has been initialized with the
/// type of 'this' (although this may be changed by the ABI).
virtual void BuildDestructorSignature(const CXXDestructorDecl *Dtor,
CXXDtorType T,
CanQualType &ResTy,
llvm::SmallVectorImpl<CanQualType> &ArgTys) = 0;
/// Build the ABI-specific portion of the parameter list for a
/// function. This generally involves a 'this' parameter and
/// possibly some extra data for constructors and destructors.
///
/// ABIs may also choose to override the return type, which has been
/// initialized with the formal return type of the function.
virtual void BuildInstanceFunctionParams(CodeGenFunction &CGF,
QualType &ResTy,
FunctionArgList &Params) = 0;
/// Emit the ABI-specific prolog for the function.
virtual void EmitInstanceFunctionProlog(CodeGenFunction &CGF) = 0;
virtual void EmitReturnFromThunk(CodeGenFunction &CGF,
RValue RV, QualType ResultType);
};
/// Creates an instance of a C++ ABI class.

Просмотреть файл

@ -13,6 +13,7 @@
//===----------------------------------------------------------------------===//
#include "CGCall.h"
#include "CGCXXABI.h"
#include "ABIInfo.h"
#include "CodeGenFunction.h"
#include "CodeGenModule.h"
@ -126,29 +127,32 @@ const CGFunctionInfo &CodeGenTypes::getFunctionInfo(const CXXMethodDecl *MD) {
const CGFunctionInfo &CodeGenTypes::getFunctionInfo(const CXXConstructorDecl *D,
CXXCtorType Type) {
llvm::SmallVector<CanQualType, 16> ArgTys;
// Add the 'this' pointer.
ArgTys.push_back(GetThisType(Context, D->getParent()));
CanQualType ResTy = Context.VoidTy;
// Check if we need to add a VTT parameter (which has type void **).
if (Type == Ctor_Base && D->getParent()->getNumVBases() != 0)
ArgTys.push_back(Context.getPointerType(Context.VoidPtrTy));
TheCXXABI.BuildConstructorSignature(D, Type, ResTy, ArgTys);
return ::getFunctionInfo(*this, ArgTys, GetFormalType(D));
CanQual<FunctionProtoType> FTP = GetFormalType(D);
// Add the formal parameters.
for (unsigned i = 0, e = FTP->getNumArgs(); i != e; ++i)
ArgTys.push_back(FTP->getArgType(i));
return getFunctionInfo(ResTy, ArgTys, FTP->getExtInfo());
}
const CGFunctionInfo &CodeGenTypes::getFunctionInfo(const CXXDestructorDecl *D,
CXXDtorType Type) {
llvm::SmallVector<CanQualType, 16> ArgTys;
// Add the 'this' pointer.
llvm::SmallVector<CanQualType, 2> ArgTys;
ArgTys.push_back(GetThisType(Context, D->getParent()));
// Check if we need to add a VTT parameter (which has type void **).
if (Type == Dtor_Base && D->getParent()->getNumVBases() != 0)
ArgTys.push_back(Context.getPointerType(Context.VoidPtrTy));
CanQualType ResTy = Context.VoidTy;
return ::getFunctionInfo(*this, ArgTys, GetFormalType(D));
TheCXXABI.BuildDestructorSignature(D, Type, ResTy, ArgTys);
CanQual<FunctionProtoType> FTP = GetFormalType(D);
assert(FTP->getNumArgs() == 0 && "dtor with formal parameters");
return getFunctionInfo(ResTy, ArgTys, FTP->getExtInfo());
}
const CGFunctionInfo &CodeGenTypes::getFunctionInfo(const FunctionDecl *FD) {
@ -659,12 +663,18 @@ CodeGenTypes::GetFunctionType(const CGFunctionInfo &FI, bool IsVariadic,
return llvm::FunctionType::get(ResultType, ArgTys, IsVariadic);
}
const llvm::Type *
CodeGenTypes::GetFunctionTypeForVTable(const CXXMethodDecl *MD) {
const llvm::Type *CodeGenTypes::GetFunctionTypeForVTable(GlobalDecl GD) {
const CXXMethodDecl *MD = cast<CXXMethodDecl>(GD.getDecl());
const FunctionProtoType *FPT = MD->getType()->getAs<FunctionProtoType>();
if (!VerifyFuncTypeComplete(FPT))
return GetFunctionType(getFunctionInfo(MD), FPT->isVariadic(), false);
if (!VerifyFuncTypeComplete(FPT)) {
const CGFunctionInfo *Info;
if (isa<CXXDestructorDecl>(MD))
Info = &getFunctionInfo(cast<CXXDestructorDecl>(MD), GD.getDtorType());
else
Info = &getFunctionInfo(MD);
return GetFunctionType(*Info, FPT->isVariadic(), false);
}
return llvm::OpaqueType::get(getLLVMContext());
}

Просмотреть файл

@ -12,6 +12,7 @@
//===----------------------------------------------------------------------===//
#include "CodeGenFunction.h"
#include "CGCXXABI.h"
#include "clang/Frontend/CodeGenOptions.h"
#include "llvm/Intrinsics.h"
@ -350,7 +351,7 @@ CodeGenFunction::EmitStaticCXXBlockVarDeclInit(const VarDecl &D,
bool ThreadsafeStatics = getContext().getLangOptions().ThreadsafeStatics;
llvm::SmallString<256> GuardVName;
CGM.getMangleContext().mangleGuardVariable(&D, GuardVName);
CGM.getCXXABI().getMangleContext().mangleGuardVariable(&D, GuardVName);
// Create the guard variable.
llvm::GlobalVariable *GuardVariable =

Просмотреть файл

@ -14,6 +14,7 @@
#include "CodeGenFunction.h"
#include "CodeGenModule.h"
#include "CGCall.h"
#include "CGCXXABI.h"
#include "CGRecordLayout.h"
#include "CGObjCRuntime.h"
#include "clang/AST/ASTContext.h"
@ -160,7 +161,7 @@ CreateReferenceTemporary(CodeGenFunction& CGF, QualType Type,
if (const VarDecl *VD = dyn_cast_or_null<VarDecl>(InitializedDecl)) {
if (VD->hasGlobalStorage()) {
llvm::SmallString<256> Name;
CGF.CGM.getMangleContext().mangleReferenceTemporary(VD, Name);
CGF.CGM.getCXXABI().getMangleContext().mangleReferenceTemporary(VD, Name);
const llvm::Type *RefTempTy = CGF.ConvertTypeForMem(Type);

Просмотреть файл

@ -12,6 +12,7 @@
//===----------------------------------------------------------------------===//
#include "CodeGenFunction.h"
#include "CGCXXABI.h"
#include "CGObjCRuntime.h"
#include "llvm/Intrinsics.h"
using namespace clang;

Просмотреть файл

@ -13,6 +13,7 @@
#include "CodeGenFunction.h"
#include "CodeGenModule.h"
#include "CGCXXABI.h"
#include "CGObjCRuntime.h"
#include "CGRecordLayout.h"
#include "clang/AST/APValue.h"

Просмотреть файл

@ -12,6 +12,7 @@
//===----------------------------------------------------------------------===//
#include "CodeGenFunction.h"
#include "CGCXXABI.h"
#include "CGObjCRuntime.h"
#include "CodeGenModule.h"
#include "clang/AST/ASTContext.h"

Просмотреть файл

@ -12,6 +12,7 @@
//===----------------------------------------------------------------------===//
#include "CodeGenModule.h"
#include "CGCXXABI.h"
#include "clang/AST/RecordLayout.h"
#include "clang/AST/Type.h"
#include "clang/Frontend/CodeGenOptions.h"
@ -65,7 +66,7 @@ public:
llvm::Constant *BuildName(QualType Ty, bool Hidden,
llvm::GlobalVariable::LinkageTypes Linkage) {
llvm::SmallString<256> OutName;
CGM.getMangleContext().mangleCXXRTTIName(Ty, OutName);
CGM.getCXXABI().getMangleContext().mangleCXXRTTIName(Ty, OutName);
llvm::StringRef Name = OutName.str();
llvm::GlobalVariable *OGV = CGM.getModule().getNamedGlobal(Name);
@ -164,7 +165,7 @@ public:
llvm::Constant *RTTIBuilder::GetAddrOfExternalRTTIDescriptor(QualType Ty) {
// Mangle the RTTI name.
llvm::SmallString<256> OutName;
CGM.getMangleContext().mangleCXXRTTI(Ty, OutName);
CGM.getCXXABI().getMangleContext().mangleCXXRTTI(Ty, OutName);
llvm::StringRef Name = OutName.str();
// Look for an existing global.
@ -518,7 +519,7 @@ llvm::Constant *RTTIBuilder::BuildTypeInfo(QualType Ty, bool Force) {
// Check if we've already emitted an RTTI descriptor for this type.
llvm::SmallString<256> OutName;
CGM.getMangleContext().mangleCXXRTTI(Ty, OutName);
CGM.getCXXABI().getMangleContext().mangleCXXRTTI(Ty, OutName);
llvm::StringRef Name = OutName.str();
llvm::GlobalVariable *OldGV = CGM.getModule().getNamedGlobal(Name);

Просмотреть файл

@ -12,6 +12,7 @@
//===----------------------------------------------------------------------===//
#include "CodeGenModule.h"
#include "CGCXXABI.h"
#include "clang/AST/RecordLayout.h"
using namespace clang;
using namespace CodeGen;
@ -373,7 +374,7 @@ CodeGenVTables::GenerateVTT(llvm::GlobalVariable::LinkageTypes Linkage,
return 0;
llvm::SmallString<256> OutName;
CGM.getMangleContext().mangleCXXVTT(RD, OutName);
CGM.getCXXABI().getMangleContext().mangleCXXVTT(RD, OutName);
llvm::StringRef Name = OutName.str();
D1(printf("vtt %s\n", RD->getNameAsCString()));

Просмотреть файл

@ -13,6 +13,7 @@
#include "CodeGenModule.h"
#include "CodeGenFunction.h"
#include "CGCXXABI.h"
#include "clang/AST/CXXInheritance.h"
#include "clang/AST/RecordLayout.h"
#include "clang/Frontend/CodeGenOptions.h"
@ -2409,12 +2410,12 @@ llvm::Constant *CodeGenModule::GetAddrOfThunk(GlobalDecl GD,
// Compute the mangled name.
llvm::SmallString<256> Name;
if (const CXXDestructorDecl* DD = dyn_cast<CXXDestructorDecl>(MD))
getMangleContext().mangleCXXDtorThunk(DD, GD.getDtorType(), Thunk.This,
Name);
getCXXABI().getMangleContext().mangleCXXDtorThunk(DD, GD.getDtorType(),
Thunk.This, Name);
else
getMangleContext().mangleThunk(MD, Thunk, Name);
getCXXABI().getMangleContext().mangleThunk(MD, Thunk, Name);
const llvm::Type *Ty = getTypes().GetFunctionTypeForVTable(MD);
const llvm::Type *Ty = getTypes().GetFunctionTypeForVTable(GD);
return GetOrCreateLLVMFunction(Name, Ty, GD);
}
@ -2522,13 +2523,8 @@ void CodeGenFunction::GenerateThunk(llvm::Function *Fn, GlobalDecl GD,
// CodeGenFunction::GenerateCode.
// Create the implicit 'this' parameter declaration.
CXXThisDecl = ImplicitParamDecl::Create(getContext(), 0,
MD->getLocation(),
&getContext().Idents.get("this"),
ThisType);
// Add the 'this' parameter.
FunctionArgs.push_back(std::make_pair(CXXThisDecl, CXXThisDecl->getType()));
CurGD = GD;
CGM.getCXXABI().BuildInstanceFunctionParams(*this, ResultType, FunctionArgs);
// Add the rest of the parameters.
for (FunctionDecl::param_const_iterator I = MD->param_begin(),
@ -2540,6 +2536,8 @@ void CodeGenFunction::GenerateThunk(llvm::Function *Fn, GlobalDecl GD,
StartFunction(GlobalDecl(), ResultType, Fn, FunctionArgs, SourceLocation());
CGM.getCXXABI().EmitInstanceFunctionProlog(*this);
// Adjust the 'this' pointer if necessary.
llvm::Value *AdjustedThisPtr =
PerformTypeAdjustment(*this, LoadCXXThis(),
@ -2563,7 +2561,7 @@ void CodeGenFunction::GenerateThunk(llvm::Function *Fn, GlobalDecl GD,
// Get our callee.
const llvm::Type *Ty =
CGM.getTypes().GetFunctionType(CGM.getTypes().getFunctionInfo(MD),
CGM.getTypes().GetFunctionType(CGM.getTypes().getFunctionInfo(GD),
FPT->isVariadic());
llvm::Value *Callee = CGM.GetAddrOfFunction(GD, Ty);
@ -2623,7 +2621,7 @@ void CodeGenFunction::GenerateThunk(llvm::Function *Fn, GlobalDecl GD,
}
if (!ResultType->isVoidType() && Slot.isNull())
EmitReturnOfRValue(RV, ResultType);
CGM.getCXXABI().EmitReturnFromThunk(CGF, RV, ResultType);
FinishFunction();
@ -2637,7 +2635,6 @@ void CodeGenFunction::GenerateThunk(llvm::Function *Fn, GlobalDecl GD,
void CodeGenVTables::EmitThunk(GlobalDecl GD, const ThunkInfo &Thunk)
{
llvm::Constant *Entry = CGM.GetAddrOfThunk(GD, Thunk);
const CXXMethodDecl *MD = cast<CXXMethodDecl>(GD.getDecl());
// Strip off a bitcast if we got one back.
if (llvm::ConstantExpr *CE = dyn_cast<llvm::ConstantExpr>(Entry)) {
@ -2648,7 +2645,7 @@ void CodeGenVTables::EmitThunk(GlobalDecl GD, const ThunkInfo &Thunk)
// There's already a declaration with the same name, check if it has the same
// type or if we need to replace it.
if (cast<llvm::GlobalValue>(Entry)->getType()->getElementType() !=
CGM.getTypes().GetFunctionTypeForVTable(MD)) {
CGM.getTypes().GetFunctionTypeForVTable(GD)) {
llvm::GlobalValue *OldThunkFn = cast<llvm::GlobalValue>(Entry);
// If the types mismatch then we have to rewrite the definition.
@ -2867,8 +2864,7 @@ CodeGenVTables::CreateVTableInitializer(const CXXRecordDecl *RD,
NextVTableThunkIndex++;
} else {
const CXXMethodDecl *MD = cast<CXXMethodDecl>(GD.getDecl());
const llvm::Type *Ty = CGM.getTypes().GetFunctionTypeForVTable(MD);
const llvm::Type *Ty = CGM.getTypes().GetFunctionTypeForVTable(GD);
Init = CGM.GetAddrOfFunction(GD, Ty);
}
@ -2935,7 +2931,7 @@ GetGlobalVariable(llvm::Module &Module, llvm::StringRef Name,
llvm::GlobalVariable *CodeGenVTables::GetAddrOfVTable(const CXXRecordDecl *RD) {
llvm::SmallString<256> OutName;
CGM.getMangleContext().mangleCXXVTable(RD, OutName);
CGM.getCXXABI().getMangleContext().mangleCXXVTable(RD, OutName);
llvm::StringRef Name = OutName.str();
ComputeVTableRelatedInformation(RD, true);
@ -2995,8 +2991,8 @@ CodeGenVTables::GenerateConstructionVTable(const CXXRecordDecl *RD,
// Get the mangled construction vtable name.
llvm::SmallString<256> OutName;
CGM.getMangleContext().mangleCXXCtorVTable(RD, Base.getBaseOffset() / 8,
Base.getBase(), OutName);
CGM.getCXXABI().getMangleContext().
mangleCXXCtorVTable(RD, Base.getBaseOffset() / 8, Base.getBase(), OutName);
llvm::StringRef Name = OutName.str();
const llvm::Type *Int8PtrTy = llvm::Type::getInt8PtrTy(CGM.getLLVMContext());

Просмотреть файл

@ -13,6 +13,7 @@
#include "CodeGenFunction.h"
#include "CodeGenModule.h"
#include "CGCXXABI.h"
#include "CGDebugInfo.h"
#include "CGException.h"
#include "clang/Basic/TargetInfo.h"
@ -48,7 +49,7 @@ CodeGenFunction::CodeGenFunction(CodeGenModule &cgm)
Exceptions = getContext().getLangOptions().Exceptions;
CatchUndefined = getContext().getLangOptions().CatchUndefined;
CGM.getMangleContext().startNewFunction();
CGM.getCXXABI().getMangleContext().startNewFunction();
}
ASTContext &CodeGenFunction::getContext() const {
@ -56,17 +57,6 @@ ASTContext &CodeGenFunction::getContext() const {
}
llvm::Value *CodeGenFunction::GetAddrOfLocalVar(const VarDecl *VD) {
llvm::Value *Res = LocalDeclMap[VD];
assert(Res && "Invalid argument to GetAddrOfLocalVar(), no decl!");
return Res;
}
llvm::Constant *
CodeGenFunction::GetAddrOfStaticLocalVar(const VarDecl *BVD) {
return cast<llvm::Constant>(GetAddrOfLocalVar(BVD));
}
const llvm::Type *CodeGenFunction::ConvertTypeForMem(QualType T) {
return CGM.getTypes().ConvertTypeForMem(T);
}
@ -289,10 +279,8 @@ void CodeGenFunction::StartFunction(GlobalDecl GD, QualType RetTy,
EmitStartEHSpec(CurCodeDecl);
EmitFunctionProlog(*CurFnInfo, CurFn, Args);
if (CXXThisDecl)
CXXThisValue = Builder.CreateLoad(LocalDeclMap[CXXThisDecl], "this");
if (CXXVTTDecl)
CXXVTTValue = Builder.CreateLoad(LocalDeclMap[CXXVTTDecl], "vtt");
if (D && isa<CXXMethodDecl>(D) && cast<CXXMethodDecl>(D)->isInstance())
CGM.getCXXABI().EmitInstanceFunctionProlog(*this);
// If any of the arguments have a variably modified type, make sure to
// emit the type size.
@ -336,30 +324,11 @@ void CodeGenFunction::GenerateCode(GlobalDecl GD, llvm::Function *Fn) {
DebugInfo = CGM.getDebugInfo();
FunctionArgList Args;
QualType ResTy = FD->getResultType();
CurGD = GD;
if (const CXXMethodDecl *MD = dyn_cast<CXXMethodDecl>(FD)) {
if (MD->isInstance()) {
// Create the implicit 'this' decl.
// FIXME: I'm not entirely sure I like using a fake decl just for code
// generation. Maybe we can come up with a better way?
CXXThisDecl = ImplicitParamDecl::Create(getContext(), 0,
FD->getLocation(),
&getContext().Idents.get("this"),
MD->getThisType(getContext()));
Args.push_back(std::make_pair(CXXThisDecl, CXXThisDecl->getType()));
// Check if we need a VTT parameter as well.
if (CodeGenVTables::needsVTTParameter(GD)) {
// FIXME: The comment about using a fake decl above applies here too.
QualType T = getContext().getPointerType(getContext().VoidPtrTy);
CXXVTTDecl =
ImplicitParamDecl::Create(getContext(), 0, FD->getLocation(),
&getContext().Idents.get("vtt"), T);
Args.push_back(std::make_pair(CXXVTTDecl, CXXVTTDecl->getType()));
}
}
}
if (isa<CXXMethodDecl>(FD) && cast<CXXMethodDecl>(FD)->isInstance())
CGM.getCXXABI().BuildInstanceFunctionParams(*this, ResTy, Args);
if (FD->getNumParams()) {
const FunctionProtoType* FProto = FD->getType()->getAs<FunctionProtoType>();
@ -374,7 +343,7 @@ void CodeGenFunction::GenerateCode(GlobalDecl GD, llvm::Function *Fn) {
if (Stmt *Body = FD->getBody()) BodyRange = Body->getSourceRange();
// Emit the standard function prologue.
StartFunction(GD, FD->getResultType(), Fn, Args, BodyRange.getBegin());
StartFunction(GD, ResTy, Fn, Args, BodyRange.getBegin());
// Generate the body of the function.
if (isa<CXXDestructorDecl>(FD))

Просмотреть файл

@ -70,6 +70,7 @@ namespace CodeGen {
class CGFunctionInfo;
class CGRecordLayout;
class CGBlockInfo;
class CGCXXABI;
/// A branch fixup. These are required when emitting a goto to a
/// label which hasn't been emitted yet. The goto is optimistically
@ -406,6 +407,8 @@ public:
class CodeGenFunction : public BlockFunction {
CodeGenFunction(const CodeGenFunction&); // DO NOT IMPLEMENT
void operator=(const CodeGenFunction&); // DO NOT IMPLEMENT
friend class CGCXXABI;
public:
/// A jump destination is an abstract label, branching to which may
/// require a jump out through normal cleanups.
@ -1034,10 +1037,16 @@ public:
void StartBlock(const char *N);
/// GetAddrOfStaticLocalVar - Return the address of a static local variable.
llvm::Constant *GetAddrOfStaticLocalVar(const VarDecl *BVD);
llvm::Constant *GetAddrOfStaticLocalVar(const VarDecl *BVD) {
return cast<llvm::Constant>(GetAddrOfLocalVar(BVD));
}
/// GetAddrOfLocalVar - Return the address of a local variable.
llvm::Value *GetAddrOfLocalVar(const VarDecl *VD);
llvm::Value *GetAddrOfLocalVar(const VarDecl *VD) {
llvm::Value *Res = LocalDeclMap[VD];
assert(Res && "Invalid argument to GetAddrOfLocalVar(), no decl!");
return Res;
}
/// getAccessedFieldNo - Given an encoded value and a result number, return
/// the input field number being accessed.

Просмотреть файл

@ -15,6 +15,7 @@
#include "CGDebugInfo.h"
#include "CodeGenFunction.h"
#include "CGCall.h"
#include "CGCXXABI.h"
#include "CGObjCRuntime.h"
#include "Mangle.h"
#include "TargetInfo.h"
@ -287,7 +288,7 @@ llvm::StringRef CodeGenModule::getMangledName(GlobalDecl GD) {
if (!Str.empty())
return Str;
if (!getMangleContext().shouldMangleDeclName(ND)) {
if (!getCXXABI().getMangleContext().shouldMangleDeclName(ND)) {
IdentifierInfo *II = ND->getIdentifier();
assert(II && "Attempt to mangle unnamed decl.");
@ -297,13 +298,13 @@ llvm::StringRef CodeGenModule::getMangledName(GlobalDecl GD) {
llvm::SmallString<256> Buffer;
if (const CXXConstructorDecl *D = dyn_cast<CXXConstructorDecl>(ND))
getMangleContext().mangleCXXCtor(D, GD.getCtorType(), Buffer);
getCXXABI().getMangleContext().mangleCXXCtor(D, GD.getCtorType(), Buffer);
else if (const CXXDestructorDecl *D = dyn_cast<CXXDestructorDecl>(ND))
getMangleContext().mangleCXXDtor(D, GD.getDtorType(), Buffer);
getCXXABI().getMangleContext().mangleCXXDtor(D, GD.getDtorType(), Buffer);
else if (const BlockDecl *BD = dyn_cast<BlockDecl>(ND))
getMangleContext().mangleBlock(GD, BD, Buffer);
getCXXABI().getMangleContext().mangleBlock(GD, BD, Buffer);
else
getMangleContext().mangleName(ND, Buffer);
getCXXABI().getMangleContext().mangleName(ND, Buffer);
// Allocate space for the mangled name.
size_t Length = Buffer.size();
@ -317,7 +318,7 @@ llvm::StringRef CodeGenModule::getMangledName(GlobalDecl GD) {
void CodeGenModule::getMangledName(GlobalDecl GD, MangleBuffer &Buffer,
const BlockDecl *BD) {
getMangleContext().mangleBlock(GD, BD, Buffer.getBuffer());
getCXXABI().getMangleContext().mangleBlock(GD, BD, Buffer.getBuffer());
}
llvm::GlobalValue *CodeGenModule::GetGlobalValue(llvm::StringRef Name) {
@ -1294,7 +1295,7 @@ static void ReplaceUsesOfNonProtoTypeWithRealFunction(llvm::GlobalValue *Old,
void CodeGenModule::EmitGlobalFunctionDefinition(GlobalDecl GD) {
const FunctionDecl *D = cast<FunctionDecl>(GD.getDecl());
const llvm::FunctionType *Ty = getTypes().GetFunctionType(GD);
getMangleContext().mangleInitDiscriminator();
getCXXABI().getMangleContext().mangleInitDiscriminator();
// Get or create the prototype for the function.
llvm::Constant *Entry = GetAddrOfFunction(GD, Ty);

Просмотреть файл

@ -22,7 +22,6 @@
#include "CGCall.h"
#include "CGCXX.h"
#include "CGVTables.h"
#include "CGCXXABI.h"
#include "CodeGenTypes.h"
#include "GlobalDecl.h"
#include "Mangle.h"
@ -71,6 +70,7 @@ namespace clang {
namespace CodeGen {
class CodeGenFunction;
class CGCXXABI;
class CGDebugInfo;
class CGObjCRuntime;
class MangleBuffer;
@ -243,9 +243,6 @@ public:
const LangOptions &getLangOptions() const { return Features; }
llvm::Module &getModule() const { return TheModule; }
CodeGenTypes &getTypes() { return Types; }
MangleContext &getMangleContext() {
return ABI.getMangleContext();
}
CodeGenVTables &getVTables() { return VTables; }
Diagnostic &getDiags() const { return Diags; }
const llvm::TargetData &getTargetData() const { return TheTargetData; }

Просмотреть файл

@ -141,7 +141,7 @@ public:
/// GetFunctionTypeForVTable - Get the LLVM function type for use in a vtable,
/// given a CXXMethodDecl. If the method to has an incomplete return type,
/// and/or incomplete argument types, this will return the opaque type.
const llvm::Type *GetFunctionTypeForVTable(const CXXMethodDecl *MD);
const llvm::Type *GetFunctionTypeForVTable(GlobalDecl GD);
const CGRecordLayout &getCGRecordLayout(const RecordDecl*) const;
@ -171,7 +171,9 @@ public:
const CGFunctionInfo &getFunctionInfo(CanQual<FunctionNoProtoType> Ty,
bool IsRecursive = false);
// getFunctionInfo - Get the function info for a member function.
/// getFunctionInfo - Get the function info for a member function of
/// the given type. This is used for calls through member function
/// pointers.
const CGFunctionInfo &getFunctionInfo(const CXXRecordDecl *RD,
const FunctionProtoType *FTP);

Просмотреть файл

@ -87,11 +87,55 @@ public:
llvm::Value *EmitMemberPointerIsNotNull(CodeGenFunction &CGF,
llvm::Value *Addr,
const MemberPointerType *MPT);
void BuildConstructorSignature(const CXXConstructorDecl *Ctor,
CXXCtorType T,
CanQualType &ResTy,
llvm::SmallVectorImpl<CanQualType> &ArgTys);
void BuildDestructorSignature(const CXXDestructorDecl *Dtor,
CXXDtorType T,
CanQualType &ResTy,
llvm::SmallVectorImpl<CanQualType> &ArgTys);
void BuildInstanceFunctionParams(CodeGenFunction &CGF,
QualType &ResTy,
FunctionArgList &Params);
void EmitInstanceFunctionProlog(CodeGenFunction &CGF);
};
class ARMCXXABI : public ItaniumCXXABI {
public:
ARMCXXABI(CodeGen::CodeGenModule &CGM) : ItaniumCXXABI(CGM, /*ARM*/ true) {}
void BuildConstructorSignature(const CXXConstructorDecl *Ctor,
CXXCtorType T,
CanQualType &ResTy,
llvm::SmallVectorImpl<CanQualType> &ArgTys);
void BuildDestructorSignature(const CXXDestructorDecl *Dtor,
CXXDtorType T,
CanQualType &ResTy,
llvm::SmallVectorImpl<CanQualType> &ArgTys);
void BuildInstanceFunctionParams(CodeGenFunction &CGF,
QualType &ResTy,
FunctionArgList &Params);
void EmitInstanceFunctionProlog(CodeGenFunction &CGF);
void EmitReturnFromThunk(CodeGenFunction &CGF, RValue RV, QualType ResTy);
private:
/// \brief Returns true if the given instance method is one of the
/// kinds that the ARM ABI says returns 'this'.
static bool HasThisReturn(GlobalDecl GD) {
const CXXMethodDecl *MD = cast<CXXMethodDecl>(GD.getDecl());
return ((isa<CXXDestructorDecl>(MD) && GD.getDtorType() != Dtor_Deleting) ||
(isa<CXXConstructorDecl>(MD)));
}
};
}
@ -586,3 +630,120 @@ ItaniumCXXABI::EmitMemberPointerIsNotNull(CodeGenFunction &CGF,
bool ItaniumCXXABI::isZeroInitializable(const MemberPointerType *MPT) {
return MPT->getPointeeType()->isFunctionType();
}
/// The generic ABI passes 'this', plus a VTT if it's initializing a
/// base subobject.
void ItaniumCXXABI::BuildConstructorSignature(const CXXConstructorDecl *Ctor,
CXXCtorType Type,
CanQualType &ResTy,
llvm::SmallVectorImpl<CanQualType> &ArgTys) {
ASTContext &Context = CGM.getContext();
// 'this' is already there.
// Check if we need to add a VTT parameter (which has type void **).
if (Type == Ctor_Base && Ctor->getParent()->getNumVBases() != 0)
ArgTys.push_back(Context.getPointerType(Context.VoidPtrTy));
}
/// The ARM ABI does the same as the Itanium ABI, but returns 'this'.
void ARMCXXABI::BuildConstructorSignature(const CXXConstructorDecl *Ctor,
CXXCtorType Type,
CanQualType &ResTy,
llvm::SmallVectorImpl<CanQualType> &ArgTys) {
ItaniumCXXABI::BuildConstructorSignature(Ctor, Type, ResTy, ArgTys);
ResTy = ArgTys[0];
}
/// The generic ABI passes 'this', plus a VTT if it's destroying a
/// base subobject.
void ItaniumCXXABI::BuildDestructorSignature(const CXXDestructorDecl *Dtor,
CXXDtorType Type,
CanQualType &ResTy,
llvm::SmallVectorImpl<CanQualType> &ArgTys) {
ASTContext &Context = CGM.getContext();
// 'this' is already there.
// Check if we need to add a VTT parameter (which has type void **).
if (Type == Dtor_Base && Dtor->getParent()->getNumVBases() != 0)
ArgTys.push_back(Context.getPointerType(Context.VoidPtrTy));
}
/// The ARM ABI does the same as the Itanium ABI, but returns 'this'
/// for non-deleting destructors.
void ARMCXXABI::BuildDestructorSignature(const CXXDestructorDecl *Dtor,
CXXDtorType Type,
CanQualType &ResTy,
llvm::SmallVectorImpl<CanQualType> &ArgTys) {
ItaniumCXXABI::BuildDestructorSignature(Dtor, Type, ResTy, ArgTys);
if (Type != Dtor_Deleting)
ResTy = ArgTys[0];
}
void ItaniumCXXABI::BuildInstanceFunctionParams(CodeGenFunction &CGF,
QualType &ResTy,
FunctionArgList &Params) {
/// Create the 'this' variable.
BuildThisParam(CGF, Params);
const CXXMethodDecl *MD = cast<CXXMethodDecl>(CGF.CurGD.getDecl());
assert(MD->isInstance());
// Check if we need a VTT parameter as well.
if (CodeGenVTables::needsVTTParameter(CGF.CurGD)) {
ASTContext &Context = CGF.getContext();
// FIXME: avoid the fake decl
QualType T = Context.getPointerType(Context.VoidPtrTy);
ImplicitParamDecl *VTTDecl
= ImplicitParamDecl::Create(Context, 0, MD->getLocation(),
&Context.Idents.get("vtt"), T);
Params.push_back(std::make_pair(VTTDecl, VTTDecl->getType()));
getVTTDecl(CGF) = VTTDecl;
}
}
void ARMCXXABI::BuildInstanceFunctionParams(CodeGenFunction &CGF,
QualType &ResTy,
FunctionArgList &Params) {
ItaniumCXXABI::BuildInstanceFunctionParams(CGF, ResTy, Params);
// Return 'this' from certain constructors and destructors.
if (HasThisReturn(CGF.CurGD))
ResTy = Params[0].second;
}
void ItaniumCXXABI::EmitInstanceFunctionProlog(CodeGenFunction &CGF) {
/// Initialize the 'this' slot.
EmitThisParam(CGF);
/// Initialize the 'vtt' slot if needed.
if (getVTTDecl(CGF)) {
getVTTValue(CGF)
= CGF.Builder.CreateLoad(CGF.GetAddrOfLocalVar(getVTTDecl(CGF)),
"vtt");
}
}
void ARMCXXABI::EmitInstanceFunctionProlog(CodeGenFunction &CGF) {
ItaniumCXXABI::EmitInstanceFunctionProlog(CGF);
/// Initialize the return slot to 'this' at the start of the
/// function.
if (HasThisReturn(CGF.CurGD))
CGF.Builder.CreateStore(CGF.LoadCXXThis(), CGF.ReturnValue);
}
void ARMCXXABI::EmitReturnFromThunk(CodeGenFunction &CGF,
RValue RV, QualType ResultType) {
if (!isa<CXXDestructorDecl>(CGF.CurGD.getDecl()))
return ItaniumCXXABI::EmitReturnFromThunk(CGF, RV, ResultType);
// Destructor thunks in the ARM ABI have indeterminate results.
const llvm::Type *T =
cast<llvm::PointerType>(CGF.ReturnValue->getType())->getElementType();
RValue Undef = RValue::get(llvm::UndefValue::get(T));
return ItaniumCXXABI::EmitReturnFromThunk(CGF, Undef, ResultType);
}

Просмотреть файл

@ -117,6 +117,34 @@ public:
MicrosoftMangleContext &getMangleContext() {
return MangleCtx;
}
void BuildConstructorSignature(const CXXConstructorDecl *Ctor,
CXXCtorType Type,
CanQualType &ResTy,
llvm::SmallVectorImpl<CanQualType> &ArgTys) {
// 'this' is already in place
// TODO: 'for base' flag
}
void BuildDestructorSignature(const CXXDestructorDecl *Ctor,
CXXDtorType Type,
CanQualType &ResTy,
llvm::SmallVectorImpl<CanQualType> &ArgTys) {
// 'this' is already in place
// TODO: 'for base' flag
}
void BuildInstanceFunctionParams(CodeGenFunction &CGF,
QualType &ResTy,
FunctionArgList &Params) {
BuildThisParam(CGF, Params);
// TODO: 'for base' flag
}
void EmitInstanceFunctionProlog(CodeGenFunction &CGF) {
EmitThisParam(CGF);
// TODO: 'for base' flag
}
};
}

Просмотреть файл

@ -1,4 +1,4 @@
// RUN: %clang_cc1 %s -triple=thumbv7-apple-darwin3.0.0-iphoneos -fno-use-cxa-atexit -target-abi apcs-gnu -emit-llvm -o - | FileCheck %s
// RUN: %clang_cc1 %s -triple=thumbv7-apple-darwin3.0.0-iphoneos -fno-use-cxa-atexit -target-abi apcs-gnu -emit-llvm -o - -fexceptions | FileCheck %s
class foo {
public:
@ -13,7 +13,89 @@ public:
// The global dtor needs the right calling conv with -fno-use-cxa-atexit
// rdar://7817590
// Checked at end of file.
bar baz;
// Destructors and constructors must return this.
namespace test1 {
void foo();
struct A {
A(int i) { foo(); }
~A() { foo(); }
void bar() { foo(); }
};
// CHECK: define void @_ZN5test14testEv()
void test() {
// CHECK: [[AV:%.*]] = alloca [[A:%.*]], align 1
// CHECK: call [[A]]* @_ZN5test11AC1Ei([[A]]* [[AV]], i32 10)
// CHECK: invoke void @_ZN5test11A3barEv([[A]]* [[AV]])
// CHECK: call [[A]]* @_ZN5test11AD1Ev([[A]]* [[AV]])
// CHECK: ret void
A a = 10;
a.bar();
}
// CHECK: define linkonce_odr [[A]]* @_ZN5test11AC1Ei([[A]]*
// CHECK: [[RET:%.*]] = alloca [[A]]*, align 4
// CHECK: [[THIS:%.*]] = alloca [[A]]*, align 4
// CHECK: store [[A]]* {{.*}}, [[A]]** [[THIS]]
// CHECK: [[THIS1:%.*]] = load [[A]]** [[THIS]]
// CHECK: store [[A]]* [[THIS1]], [[A]]** [[RET]]
// CHECK: call [[A]]* @_ZN5test11AC2Ei(
// CHECK: [[THIS2:%.*]] = load [[A]]** [[RET]]
// CHECK: ret [[A]]* [[THIS2]]
// CHECK: define linkonce_odr [[A]]* @_ZN5test11AD1Ev([[A]]*
// CHECK: [[RET:%.*]] = alloca [[A]]*, align 4
// CHECK: [[THIS:%.*]] = alloca [[A]]*, align 4
// CHECK: store [[A]]* {{.*}}, [[A]]** [[THIS]]
// CHECK: [[THIS1:%.*]] = load [[A]]** [[THIS]]
// CHECK: store [[A]]* [[THIS1]], [[A]]** [[RET]]
// CHECK: call [[A]]* @_ZN5test11AD2Ev(
// CHECK: [[THIS2:%.*]] = load [[A]]** [[RET]]
// CHECK: ret [[A]]* [[THIS2]]
}
// Awkward virtual cases.
namespace test2 {
void foo();
struct A {
int x;
A(int);
virtual ~A() { foo(); }
};
struct B {
int y;
int z;
B(int);
virtual ~B() { foo(); }
};
struct C : A, virtual B {
int q;
C(int i) : A(i), B(i) { foo(); }
~C() { foo(); }
};
void test() {
C c = 10;
}
// CHECK: define linkonce_odr [[C:%.*]]* @_ZTv0_n12_N5test21CD1Ev(
// CHECK: call [[C]]* @_ZN5test21CD1Ev(
// CHECK: ret [[C]]* undef
// CHECK: define linkonce_odr void @_ZTv0_n12_N5test21CD0Ev(
// CHECK: call void @_ZN5test21CD0Ev(
// CHECK: ret void
}
// CHECK: @_GLOBAL__D_a()
// CHECK: call void @_ZN3barD1Ev(%class.bar* @baz)
// CHECK: call %class.bar* @_ZN3barD1Ev(%class.bar* @baz)