1f4a2713aSLionel Sambuc //===----- CGCXXABI.cpp - Interface to C++ ABIs ---------------------------===//
2f4a2713aSLionel Sambuc //
3f4a2713aSLionel Sambuc // The LLVM Compiler Infrastructure
4f4a2713aSLionel Sambuc //
5f4a2713aSLionel Sambuc // This file is distributed under the University of Illinois Open Source
6f4a2713aSLionel Sambuc // License. See LICENSE.TXT for details.
7f4a2713aSLionel Sambuc //
8f4a2713aSLionel Sambuc //===----------------------------------------------------------------------===//
9f4a2713aSLionel Sambuc //
10f4a2713aSLionel Sambuc // This provides an abstract class for C++ code generation. Concrete subclasses
11f4a2713aSLionel Sambuc // of this implement code generation for specific C++ ABIs.
12f4a2713aSLionel Sambuc //
13f4a2713aSLionel Sambuc //===----------------------------------------------------------------------===//
14f4a2713aSLionel Sambuc
15f4a2713aSLionel Sambuc #include "CGCXXABI.h"
16f4a2713aSLionel Sambuc
17f4a2713aSLionel Sambuc using namespace clang;
18f4a2713aSLionel Sambuc using namespace CodeGen;
19f4a2713aSLionel Sambuc
~CGCXXABI()20f4a2713aSLionel Sambuc CGCXXABI::~CGCXXABI() { }
21f4a2713aSLionel Sambuc
ErrorUnsupportedABI(CodeGenFunction & CGF,StringRef S)22f4a2713aSLionel Sambuc void CGCXXABI::ErrorUnsupportedABI(CodeGenFunction &CGF, StringRef S) {
23f4a2713aSLionel Sambuc DiagnosticsEngine &Diags = CGF.CGM.getDiags();
24f4a2713aSLionel Sambuc unsigned DiagID = Diags.getCustomDiagID(DiagnosticsEngine::Error,
25f4a2713aSLionel Sambuc "cannot yet compile %0 in this ABI");
26f4a2713aSLionel Sambuc Diags.Report(CGF.getContext().getFullLoc(CGF.CurCodeDecl->getLocation()),
27f4a2713aSLionel Sambuc DiagID)
28f4a2713aSLionel Sambuc << S;
29f4a2713aSLionel Sambuc }
30f4a2713aSLionel Sambuc
canCopyArgument(const CXXRecordDecl * RD) const31*0a6a1f1dSLionel Sambuc bool CGCXXABI::canCopyArgument(const CXXRecordDecl *RD) const {
32*0a6a1f1dSLionel Sambuc // If RD has a non-trivial move or copy constructor, we cannot copy the
33*0a6a1f1dSLionel Sambuc // argument.
34*0a6a1f1dSLionel Sambuc if (RD->hasNonTrivialCopyConstructor() || RD->hasNonTrivialMoveConstructor())
35*0a6a1f1dSLionel Sambuc return false;
36*0a6a1f1dSLionel Sambuc
37*0a6a1f1dSLionel Sambuc // If RD has a non-trivial destructor, we cannot copy the argument.
38*0a6a1f1dSLionel Sambuc if (RD->hasNonTrivialDestructor())
39*0a6a1f1dSLionel Sambuc return false;
40*0a6a1f1dSLionel Sambuc
41*0a6a1f1dSLionel Sambuc // We can only copy the argument if there exists at least one trivial,
42*0a6a1f1dSLionel Sambuc // non-deleted copy or move constructor.
43*0a6a1f1dSLionel Sambuc // FIXME: This assumes that all lazily declared copy and move constructors are
44*0a6a1f1dSLionel Sambuc // not deleted. This assumption might not be true in some corner cases.
45*0a6a1f1dSLionel Sambuc bool CopyDeleted = false;
46*0a6a1f1dSLionel Sambuc bool MoveDeleted = false;
47*0a6a1f1dSLionel Sambuc for (const CXXConstructorDecl *CD : RD->ctors()) {
48*0a6a1f1dSLionel Sambuc if (CD->isCopyConstructor() || CD->isMoveConstructor()) {
49*0a6a1f1dSLionel Sambuc assert(CD->isTrivial());
50*0a6a1f1dSLionel Sambuc // We had at least one undeleted trivial copy or move ctor. Return
51*0a6a1f1dSLionel Sambuc // directly.
52*0a6a1f1dSLionel Sambuc if (!CD->isDeleted())
53*0a6a1f1dSLionel Sambuc return true;
54*0a6a1f1dSLionel Sambuc if (CD->isCopyConstructor())
55*0a6a1f1dSLionel Sambuc CopyDeleted = true;
56*0a6a1f1dSLionel Sambuc else
57*0a6a1f1dSLionel Sambuc MoveDeleted = true;
58*0a6a1f1dSLionel Sambuc }
59*0a6a1f1dSLionel Sambuc }
60*0a6a1f1dSLionel Sambuc
61*0a6a1f1dSLionel Sambuc // If all trivial copy and move constructors are deleted, we cannot copy the
62*0a6a1f1dSLionel Sambuc // argument.
63*0a6a1f1dSLionel Sambuc return !(CopyDeleted && MoveDeleted);
64*0a6a1f1dSLionel Sambuc }
65*0a6a1f1dSLionel Sambuc
GetBogusMemberPointer(QualType T)66f4a2713aSLionel Sambuc llvm::Constant *CGCXXABI::GetBogusMemberPointer(QualType T) {
67f4a2713aSLionel Sambuc return llvm::Constant::getNullValue(CGM.getTypes().ConvertType(T));
68f4a2713aSLionel Sambuc }
69f4a2713aSLionel Sambuc
70f4a2713aSLionel Sambuc llvm::Type *
ConvertMemberPointerType(const MemberPointerType * MPT)71f4a2713aSLionel Sambuc CGCXXABI::ConvertMemberPointerType(const MemberPointerType *MPT) {
72f4a2713aSLionel Sambuc return CGM.getTypes().ConvertType(CGM.getContext().getPointerDiffType());
73f4a2713aSLionel Sambuc }
74f4a2713aSLionel Sambuc
EmitLoadOfMemberFunctionPointer(CodeGenFunction & CGF,const Expr * E,llvm::Value * & This,llvm::Value * MemPtr,const MemberPointerType * MPT)75*0a6a1f1dSLionel Sambuc llvm::Value *CGCXXABI::EmitLoadOfMemberFunctionPointer(
76*0a6a1f1dSLionel Sambuc CodeGenFunction &CGF, const Expr *E, llvm::Value *&This,
77*0a6a1f1dSLionel Sambuc llvm::Value *MemPtr, const MemberPointerType *MPT) {
78f4a2713aSLionel Sambuc ErrorUnsupportedABI(CGF, "calls through member pointers");
79f4a2713aSLionel Sambuc
80f4a2713aSLionel Sambuc const FunctionProtoType *FPT =
81f4a2713aSLionel Sambuc MPT->getPointeeType()->getAs<FunctionProtoType>();
82f4a2713aSLionel Sambuc const CXXRecordDecl *RD =
83f4a2713aSLionel Sambuc cast<CXXRecordDecl>(MPT->getClass()->getAs<RecordType>()->getDecl());
84f4a2713aSLionel Sambuc llvm::FunctionType *FTy = CGM.getTypes().GetFunctionType(
85f4a2713aSLionel Sambuc CGM.getTypes().arrangeCXXMethodType(RD, FPT));
86f4a2713aSLionel Sambuc return llvm::Constant::getNullValue(FTy->getPointerTo());
87f4a2713aSLionel Sambuc }
88f4a2713aSLionel Sambuc
89*0a6a1f1dSLionel Sambuc llvm::Value *
EmitMemberDataPointerAddress(CodeGenFunction & CGF,const Expr * E,llvm::Value * Base,llvm::Value * MemPtr,const MemberPointerType * MPT)90*0a6a1f1dSLionel Sambuc CGCXXABI::EmitMemberDataPointerAddress(CodeGenFunction &CGF, const Expr *E,
91*0a6a1f1dSLionel Sambuc llvm::Value *Base, llvm::Value *MemPtr,
92f4a2713aSLionel Sambuc const MemberPointerType *MPT) {
93f4a2713aSLionel Sambuc ErrorUnsupportedABI(CGF, "loads of member pointers");
94f4a2713aSLionel Sambuc llvm::Type *Ty = CGF.ConvertType(MPT->getPointeeType())->getPointerTo();
95f4a2713aSLionel Sambuc return llvm::Constant::getNullValue(Ty);
96f4a2713aSLionel Sambuc }
97f4a2713aSLionel Sambuc
EmitMemberPointerConversion(CodeGenFunction & CGF,const CastExpr * E,llvm::Value * Src)98f4a2713aSLionel Sambuc llvm::Value *CGCXXABI::EmitMemberPointerConversion(CodeGenFunction &CGF,
99f4a2713aSLionel Sambuc const CastExpr *E,
100f4a2713aSLionel Sambuc llvm::Value *Src) {
101f4a2713aSLionel Sambuc ErrorUnsupportedABI(CGF, "member function pointer conversions");
102f4a2713aSLionel Sambuc return GetBogusMemberPointer(E->getType());
103f4a2713aSLionel Sambuc }
104f4a2713aSLionel Sambuc
EmitMemberPointerConversion(const CastExpr * E,llvm::Constant * Src)105f4a2713aSLionel Sambuc llvm::Constant *CGCXXABI::EmitMemberPointerConversion(const CastExpr *E,
106f4a2713aSLionel Sambuc llvm::Constant *Src) {
107f4a2713aSLionel Sambuc return GetBogusMemberPointer(E->getType());
108f4a2713aSLionel Sambuc }
109f4a2713aSLionel Sambuc
110f4a2713aSLionel Sambuc llvm::Value *
EmitMemberPointerComparison(CodeGenFunction & CGF,llvm::Value * L,llvm::Value * R,const MemberPointerType * MPT,bool Inequality)111f4a2713aSLionel Sambuc CGCXXABI::EmitMemberPointerComparison(CodeGenFunction &CGF,
112f4a2713aSLionel Sambuc llvm::Value *L,
113f4a2713aSLionel Sambuc llvm::Value *R,
114f4a2713aSLionel Sambuc const MemberPointerType *MPT,
115f4a2713aSLionel Sambuc bool Inequality) {
116f4a2713aSLionel Sambuc ErrorUnsupportedABI(CGF, "member function pointer comparison");
117f4a2713aSLionel Sambuc return CGF.Builder.getFalse();
118f4a2713aSLionel Sambuc }
119f4a2713aSLionel Sambuc
120f4a2713aSLionel Sambuc llvm::Value *
EmitMemberPointerIsNotNull(CodeGenFunction & CGF,llvm::Value * MemPtr,const MemberPointerType * MPT)121f4a2713aSLionel Sambuc CGCXXABI::EmitMemberPointerIsNotNull(CodeGenFunction &CGF,
122f4a2713aSLionel Sambuc llvm::Value *MemPtr,
123f4a2713aSLionel Sambuc const MemberPointerType *MPT) {
124f4a2713aSLionel Sambuc ErrorUnsupportedABI(CGF, "member function pointer null testing");
125f4a2713aSLionel Sambuc return CGF.Builder.getFalse();
126f4a2713aSLionel Sambuc }
127f4a2713aSLionel Sambuc
128f4a2713aSLionel Sambuc llvm::Constant *
EmitNullMemberPointer(const MemberPointerType * MPT)129f4a2713aSLionel Sambuc CGCXXABI::EmitNullMemberPointer(const MemberPointerType *MPT) {
130f4a2713aSLionel Sambuc return GetBogusMemberPointer(QualType(MPT, 0));
131f4a2713aSLionel Sambuc }
132f4a2713aSLionel Sambuc
EmitMemberPointer(const CXXMethodDecl * MD)133f4a2713aSLionel Sambuc llvm::Constant *CGCXXABI::EmitMemberPointer(const CXXMethodDecl *MD) {
134f4a2713aSLionel Sambuc return GetBogusMemberPointer(
135f4a2713aSLionel Sambuc CGM.getContext().getMemberPointerType(MD->getType(),
136f4a2713aSLionel Sambuc MD->getParent()->getTypeForDecl()));
137f4a2713aSLionel Sambuc }
138f4a2713aSLionel Sambuc
EmitMemberDataPointer(const MemberPointerType * MPT,CharUnits offset)139f4a2713aSLionel Sambuc llvm::Constant *CGCXXABI::EmitMemberDataPointer(const MemberPointerType *MPT,
140f4a2713aSLionel Sambuc CharUnits offset) {
141f4a2713aSLionel Sambuc return GetBogusMemberPointer(QualType(MPT, 0));
142f4a2713aSLionel Sambuc }
143f4a2713aSLionel Sambuc
EmitMemberPointer(const APValue & MP,QualType MPT)144f4a2713aSLionel Sambuc llvm::Constant *CGCXXABI::EmitMemberPointer(const APValue &MP, QualType MPT) {
145f4a2713aSLionel Sambuc return GetBogusMemberPointer(MPT);
146f4a2713aSLionel Sambuc }
147f4a2713aSLionel Sambuc
isZeroInitializable(const MemberPointerType * MPT)148f4a2713aSLionel Sambuc bool CGCXXABI::isZeroInitializable(const MemberPointerType *MPT) {
149f4a2713aSLionel Sambuc // Fake answer.
150f4a2713aSLionel Sambuc return true;
151f4a2713aSLionel Sambuc }
152f4a2713aSLionel Sambuc
buildThisParam(CodeGenFunction & CGF,FunctionArgList & params)153*0a6a1f1dSLionel Sambuc void CGCXXABI::buildThisParam(CodeGenFunction &CGF, FunctionArgList ¶ms) {
154f4a2713aSLionel Sambuc const CXXMethodDecl *MD = cast<CXXMethodDecl>(CGF.CurGD.getDecl());
155f4a2713aSLionel Sambuc
156f4a2713aSLionel Sambuc // FIXME: I'm not entirely sure I like using a fake decl just for code
157f4a2713aSLionel Sambuc // generation. Maybe we can come up with a better way?
158f4a2713aSLionel Sambuc ImplicitParamDecl *ThisDecl
159*0a6a1f1dSLionel Sambuc = ImplicitParamDecl::Create(CGM.getContext(), nullptr, MD->getLocation(),
160f4a2713aSLionel Sambuc &CGM.getContext().Idents.get("this"),
161f4a2713aSLionel Sambuc MD->getThisType(CGM.getContext()));
162f4a2713aSLionel Sambuc params.push_back(ThisDecl);
163f4a2713aSLionel Sambuc getThisDecl(CGF) = ThisDecl;
164f4a2713aSLionel Sambuc }
165f4a2713aSLionel Sambuc
EmitThisParam(CodeGenFunction & CGF)166f4a2713aSLionel Sambuc void CGCXXABI::EmitThisParam(CodeGenFunction &CGF) {
167f4a2713aSLionel Sambuc /// Initialize the 'this' slot.
168f4a2713aSLionel Sambuc assert(getThisDecl(CGF) && "no 'this' variable for function");
169f4a2713aSLionel Sambuc getThisValue(CGF)
170f4a2713aSLionel Sambuc = CGF.Builder.CreateLoad(CGF.GetAddrOfLocalVar(getThisDecl(CGF)),
171f4a2713aSLionel Sambuc "this");
172f4a2713aSLionel Sambuc }
173f4a2713aSLionel Sambuc
EmitReturnFromThunk(CodeGenFunction & CGF,RValue RV,QualType ResultType)174f4a2713aSLionel Sambuc void CGCXXABI::EmitReturnFromThunk(CodeGenFunction &CGF,
175f4a2713aSLionel Sambuc RValue RV, QualType ResultType) {
176f4a2713aSLionel Sambuc CGF.EmitReturnOfRValue(RV, ResultType);
177f4a2713aSLionel Sambuc }
178f4a2713aSLionel Sambuc
GetArrayCookieSize(const CXXNewExpr * expr)179f4a2713aSLionel Sambuc CharUnits CGCXXABI::GetArrayCookieSize(const CXXNewExpr *expr) {
180f4a2713aSLionel Sambuc if (!requiresArrayCookie(expr))
181f4a2713aSLionel Sambuc return CharUnits::Zero();
182f4a2713aSLionel Sambuc return getArrayCookieSizeImpl(expr->getAllocatedType());
183f4a2713aSLionel Sambuc }
184f4a2713aSLionel Sambuc
getArrayCookieSizeImpl(QualType elementType)185f4a2713aSLionel Sambuc CharUnits CGCXXABI::getArrayCookieSizeImpl(QualType elementType) {
186f4a2713aSLionel Sambuc // BOGUS
187f4a2713aSLionel Sambuc return CharUnits::Zero();
188f4a2713aSLionel Sambuc }
189f4a2713aSLionel Sambuc
InitializeArrayCookie(CodeGenFunction & CGF,llvm::Value * NewPtr,llvm::Value * NumElements,const CXXNewExpr * expr,QualType ElementType)190f4a2713aSLionel Sambuc llvm::Value *CGCXXABI::InitializeArrayCookie(CodeGenFunction &CGF,
191f4a2713aSLionel Sambuc llvm::Value *NewPtr,
192f4a2713aSLionel Sambuc llvm::Value *NumElements,
193f4a2713aSLionel Sambuc const CXXNewExpr *expr,
194f4a2713aSLionel Sambuc QualType ElementType) {
195f4a2713aSLionel Sambuc // Should never be called.
196f4a2713aSLionel Sambuc ErrorUnsupportedABI(CGF, "array cookie initialization");
197*0a6a1f1dSLionel Sambuc return nullptr;
198f4a2713aSLionel Sambuc }
199f4a2713aSLionel Sambuc
requiresArrayCookie(const CXXDeleteExpr * expr,QualType elementType)200f4a2713aSLionel Sambuc bool CGCXXABI::requiresArrayCookie(const CXXDeleteExpr *expr,
201f4a2713aSLionel Sambuc QualType elementType) {
202f4a2713aSLionel Sambuc // If the class's usual deallocation function takes two arguments,
203f4a2713aSLionel Sambuc // it needs a cookie.
204f4a2713aSLionel Sambuc if (expr->doesUsualArrayDeleteWantSize())
205f4a2713aSLionel Sambuc return true;
206f4a2713aSLionel Sambuc
207f4a2713aSLionel Sambuc return elementType.isDestructedType();
208f4a2713aSLionel Sambuc }
209f4a2713aSLionel Sambuc
requiresArrayCookie(const CXXNewExpr * expr)210f4a2713aSLionel Sambuc bool CGCXXABI::requiresArrayCookie(const CXXNewExpr *expr) {
211f4a2713aSLionel Sambuc // If the class's usual deallocation function takes two arguments,
212f4a2713aSLionel Sambuc // it needs a cookie.
213f4a2713aSLionel Sambuc if (expr->doesUsualArrayDeleteWantSize())
214f4a2713aSLionel Sambuc return true;
215f4a2713aSLionel Sambuc
216f4a2713aSLionel Sambuc return expr->getAllocatedType().isDestructedType();
217f4a2713aSLionel Sambuc }
218f4a2713aSLionel Sambuc
ReadArrayCookie(CodeGenFunction & CGF,llvm::Value * ptr,const CXXDeleteExpr * expr,QualType eltTy,llvm::Value * & numElements,llvm::Value * & allocPtr,CharUnits & cookieSize)219f4a2713aSLionel Sambuc void CGCXXABI::ReadArrayCookie(CodeGenFunction &CGF, llvm::Value *ptr,
220f4a2713aSLionel Sambuc const CXXDeleteExpr *expr, QualType eltTy,
221f4a2713aSLionel Sambuc llvm::Value *&numElements,
222f4a2713aSLionel Sambuc llvm::Value *&allocPtr, CharUnits &cookieSize) {
223f4a2713aSLionel Sambuc // Derive a char* in the same address space as the pointer.
224f4a2713aSLionel Sambuc unsigned AS = ptr->getType()->getPointerAddressSpace();
225f4a2713aSLionel Sambuc llvm::Type *charPtrTy = CGF.Int8Ty->getPointerTo(AS);
226f4a2713aSLionel Sambuc ptr = CGF.Builder.CreateBitCast(ptr, charPtrTy);
227f4a2713aSLionel Sambuc
228f4a2713aSLionel Sambuc // If we don't need an array cookie, bail out early.
229f4a2713aSLionel Sambuc if (!requiresArrayCookie(expr, eltTy)) {
230f4a2713aSLionel Sambuc allocPtr = ptr;
231*0a6a1f1dSLionel Sambuc numElements = nullptr;
232f4a2713aSLionel Sambuc cookieSize = CharUnits::Zero();
233f4a2713aSLionel Sambuc return;
234f4a2713aSLionel Sambuc }
235f4a2713aSLionel Sambuc
236f4a2713aSLionel Sambuc cookieSize = getArrayCookieSizeImpl(eltTy);
237f4a2713aSLionel Sambuc allocPtr = CGF.Builder.CreateConstInBoundsGEP1_64(ptr,
238f4a2713aSLionel Sambuc -cookieSize.getQuantity());
239f4a2713aSLionel Sambuc numElements = readArrayCookieImpl(CGF, allocPtr, cookieSize);
240f4a2713aSLionel Sambuc }
241f4a2713aSLionel Sambuc
readArrayCookieImpl(CodeGenFunction & CGF,llvm::Value * ptr,CharUnits cookieSize)242f4a2713aSLionel Sambuc llvm::Value *CGCXXABI::readArrayCookieImpl(CodeGenFunction &CGF,
243f4a2713aSLionel Sambuc llvm::Value *ptr,
244f4a2713aSLionel Sambuc CharUnits cookieSize) {
245f4a2713aSLionel Sambuc ErrorUnsupportedABI(CGF, "reading a new[] cookie");
246f4a2713aSLionel Sambuc return llvm::ConstantInt::get(CGF.SizeTy, 0);
247f4a2713aSLionel Sambuc }
248f4a2713aSLionel Sambuc
249f4a2713aSLionel Sambuc /// Returns the adjustment, in bytes, required for the given
250f4a2713aSLionel Sambuc /// member-pointer operation. Returns null if no adjustment is
251f4a2713aSLionel Sambuc /// required.
getMemberPointerAdjustment(const CastExpr * E)252f4a2713aSLionel Sambuc llvm::Constant *CGCXXABI::getMemberPointerAdjustment(const CastExpr *E) {
253f4a2713aSLionel Sambuc assert(E->getCastKind() == CK_DerivedToBaseMemberPointer ||
254f4a2713aSLionel Sambuc E->getCastKind() == CK_BaseToDerivedMemberPointer);
255f4a2713aSLionel Sambuc
256f4a2713aSLionel Sambuc QualType derivedType;
257f4a2713aSLionel Sambuc if (E->getCastKind() == CK_DerivedToBaseMemberPointer)
258f4a2713aSLionel Sambuc derivedType = E->getSubExpr()->getType();
259f4a2713aSLionel Sambuc else
260f4a2713aSLionel Sambuc derivedType = E->getType();
261f4a2713aSLionel Sambuc
262f4a2713aSLionel Sambuc const CXXRecordDecl *derivedClass =
263f4a2713aSLionel Sambuc derivedType->castAs<MemberPointerType>()->getClass()->getAsCXXRecordDecl();
264f4a2713aSLionel Sambuc
265f4a2713aSLionel Sambuc return CGM.GetNonVirtualBaseClassOffset(derivedClass,
266f4a2713aSLionel Sambuc E->path_begin(),
267f4a2713aSLionel Sambuc E->path_end());
268f4a2713aSLionel Sambuc }
269f4a2713aSLionel Sambuc
getMemberPointerPathAdjustment(const APValue & MP)270f4a2713aSLionel Sambuc CharUnits CGCXXABI::getMemberPointerPathAdjustment(const APValue &MP) {
271f4a2713aSLionel Sambuc // TODO: Store base specifiers in APValue member pointer paths so we can
272f4a2713aSLionel Sambuc // easily reuse CGM.GetNonVirtualBaseClassOffset().
273f4a2713aSLionel Sambuc const ValueDecl *MPD = MP.getMemberPointerDecl();
274f4a2713aSLionel Sambuc CharUnits ThisAdjustment = CharUnits::Zero();
275f4a2713aSLionel Sambuc ArrayRef<const CXXRecordDecl*> Path = MP.getMemberPointerPath();
276f4a2713aSLionel Sambuc bool DerivedMember = MP.isMemberPointerToDerivedMember();
277f4a2713aSLionel Sambuc const CXXRecordDecl *RD = cast<CXXRecordDecl>(MPD->getDeclContext());
278f4a2713aSLionel Sambuc for (unsigned I = 0, N = Path.size(); I != N; ++I) {
279f4a2713aSLionel Sambuc const CXXRecordDecl *Base = RD;
280f4a2713aSLionel Sambuc const CXXRecordDecl *Derived = Path[I];
281f4a2713aSLionel Sambuc if (DerivedMember)
282f4a2713aSLionel Sambuc std::swap(Base, Derived);
283f4a2713aSLionel Sambuc ThisAdjustment +=
284f4a2713aSLionel Sambuc getContext().getASTRecordLayout(Derived).getBaseClassOffset(Base);
285f4a2713aSLionel Sambuc RD = Path[I];
286f4a2713aSLionel Sambuc }
287f4a2713aSLionel Sambuc if (DerivedMember)
288f4a2713aSLionel Sambuc ThisAdjustment = -ThisAdjustment;
289f4a2713aSLionel Sambuc return ThisAdjustment;
290f4a2713aSLionel Sambuc }
291f4a2713aSLionel Sambuc
292f4a2713aSLionel Sambuc llvm::BasicBlock *
EmitCtorCompleteObjectHandler(CodeGenFunction & CGF,const CXXRecordDecl * RD)293f4a2713aSLionel Sambuc CGCXXABI::EmitCtorCompleteObjectHandler(CodeGenFunction &CGF,
294f4a2713aSLionel Sambuc const CXXRecordDecl *RD) {
295f4a2713aSLionel Sambuc if (CGM.getTarget().getCXXABI().hasConstructorVariants())
296f4a2713aSLionel Sambuc llvm_unreachable("shouldn't be called in this ABI");
297f4a2713aSLionel Sambuc
298f4a2713aSLionel Sambuc ErrorUnsupportedABI(CGF, "complete object detection in ctor");
299*0a6a1f1dSLionel Sambuc return nullptr;
300f4a2713aSLionel Sambuc }
301f4a2713aSLionel Sambuc
NeedsVTTParameter(GlobalDecl GD)302f4a2713aSLionel Sambuc bool CGCXXABI::NeedsVTTParameter(GlobalDecl GD) {
303f4a2713aSLionel Sambuc return false;
304f4a2713aSLionel Sambuc }
305