зеркало из https://github.com/microsoft/clang-1.git
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:
Родитель
1baf2f778c
Коммит
4c40d98ab7
|
@ -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()));
|
||||
CanQualType ResTy = Context.VoidTy;
|
||||
|
||||
// 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));
|
||||
TheCXXABI.BuildDestructorSignature(D, Type, ResTy, ArgTys);
|
||||
|
||||
return ::getFunctionInfo(*this, ArgTys, GetFormalType(D));
|
||||
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)
|
||||
|
|
Загрузка…
Ссылка в новой задаче