blob: 9fc6be179ddec073c3afeee3b97b0f13dbfcfd65 [file] [log] [blame]
Charles Davis3a811f12010-05-25 19:52:27 +00001//===------- ItaniumCXXABI.cpp - Emit LLVM Code from ASTs for a Module ----===//
2//
3// The LLVM Compiler Infrastructure
4//
5// This file is distributed under the University of Illinois Open Source
6// License. See LICENSE.TXT for details.
7//
8//===----------------------------------------------------------------------===//
9//
10// This provides C++ code generation targetting the Itanium C++ ABI. The class
11// in this file generates structures that follow the Itanium C++ ABI, which is
12// documented at:
13// http://www.codesourcery.com/public/cxx-abi/abi.html
14// http://www.codesourcery.com/public/cxx-abi/abi-eh.html
John McCallee79a4c2010-08-21 22:46:04 +000015//
16// It also supports the closely-related ARM ABI, documented at:
17// http://infocenter.arm.com/help/topic/com.arm.doc.ihi0041c/IHI0041C_cppabi.pdf
18//
Charles Davis3a811f12010-05-25 19:52:27 +000019//===----------------------------------------------------------------------===//
20
21#include "CGCXXABI.h"
John McCall93d557b2010-08-22 00:05:51 +000022#include "CodeGenFunction.h"
Charles Davis3a811f12010-05-25 19:52:27 +000023#include "CodeGenModule.h"
24#include "Mangle.h"
John McCall93d557b2010-08-22 00:05:51 +000025#include <clang/AST/Type.h>
26#include <llvm/Value.h>
Charles Davis3a811f12010-05-25 19:52:27 +000027
28using namespace clang;
John McCall93d557b2010-08-22 00:05:51 +000029using namespace CodeGen;
Charles Davis3a811f12010-05-25 19:52:27 +000030
31namespace {
Charles Davis071cc7d2010-08-16 03:33:14 +000032class ItaniumCXXABI : public CodeGen::CGCXXABI {
John McCall93d557b2010-08-22 00:05:51 +000033protected:
34 CodeGenModule &CGM;
Charles Davis3a811f12010-05-25 19:52:27 +000035 CodeGen::MangleContext MangleCtx;
John McCallbabc9a92010-08-22 00:59:17 +000036 bool IsARM;
Charles Davis3a811f12010-05-25 19:52:27 +000037public:
John McCallbabc9a92010-08-22 00:59:17 +000038 ItaniumCXXABI(CodeGen::CodeGenModule &CGM, bool IsARM = false) :
39 CGM(CGM), MangleCtx(CGM.getContext(), CGM.getDiags()), IsARM(IsARM) { }
Charles Davis3a811f12010-05-25 19:52:27 +000040
41 CodeGen::MangleContext &getMangleContext() {
42 return MangleCtx;
43 }
John McCall93d557b2010-08-22 00:05:51 +000044
45 llvm::Value *EmitLoadOfMemberFunctionPointer(CodeGenFunction &CGF,
46 llvm::Value *&This,
47 llvm::Value *MemFnPtr,
48 const MemberPointerType *MPT);
John McCall3023def2010-08-22 03:04:22 +000049
50 void EmitMemberPointerConversion(CodeGenFunction &CGF,
51 const CastExpr *E,
52 llvm::Value *Src,
53 llvm::Value *Dest,
54 bool VolatileDest);
Charles Davis3a811f12010-05-25 19:52:27 +000055};
John McCallee79a4c2010-08-21 22:46:04 +000056
57class ARMCXXABI : public ItaniumCXXABI {
58public:
John McCallbabc9a92010-08-22 00:59:17 +000059 ARMCXXABI(CodeGen::CodeGenModule &CGM) : ItaniumCXXABI(CGM, /*ARM*/ true) {}
John McCallee79a4c2010-08-21 22:46:04 +000060};
Charles Davis3a811f12010-05-25 19:52:27 +000061}
62
Charles Davis071cc7d2010-08-16 03:33:14 +000063CodeGen::CGCXXABI *CodeGen::CreateItaniumCXXABI(CodeGenModule &CGM) {
Charles Davis3a811f12010-05-25 19:52:27 +000064 return new ItaniumCXXABI(CGM);
65}
66
John McCallee79a4c2010-08-21 22:46:04 +000067CodeGen::CGCXXABI *CodeGen::CreateARMCXXABI(CodeGenModule &CGM) {
68 return new ARMCXXABI(CGM);
69}
70
John McCallbabc9a92010-08-22 00:59:17 +000071/// In the Itanium and ARM ABIs, method pointers have the form:
72/// struct { ptrdiff_t ptr; ptrdiff_t adj; } memptr;
73///
74/// In the Itanium ABI:
75/// - method pointers are virtual if (memptr.ptr & 1) is nonzero
76/// - the this-adjustment is (memptr.adj)
77/// - the virtual offset is (memptr.ptr - 1)
78///
79/// In the ARM ABI:
80/// - method pointers are virtual if (memptr.adj & 1) is nonzero
81/// - the this-adjustment is (memptr.adj >> 1)
82/// - the virtual offset is (memptr.ptr)
83/// ARM uses 'adj' for the virtual flag because Thumb functions
84/// may be only single-byte aligned.
85///
86/// If the member is virtual, the adjusted 'this' pointer points
87/// to a vtable pointer from which the virtual offset is applied.
88///
89/// If the member is non-virtual, memptr.ptr is the address of
90/// the function to call.
John McCall93d557b2010-08-22 00:05:51 +000091llvm::Value *
92ItaniumCXXABI::EmitLoadOfMemberFunctionPointer(CodeGenFunction &CGF,
93 llvm::Value *&This,
94 llvm::Value *MemFnPtr,
95 const MemberPointerType *MPT) {
96 CGBuilderTy &Builder = CGF.Builder;
97
98 const FunctionProtoType *FPT =
99 MPT->getPointeeType()->getAs<FunctionProtoType>();
100 const CXXRecordDecl *RD =
101 cast<CXXRecordDecl>(MPT->getClass()->getAs<RecordType>()->getDecl());
102
103 const llvm::FunctionType *FTy =
104 CGM.getTypes().GetFunctionType(CGM.getTypes().getFunctionInfo(RD, FPT),
105 FPT->isVariadic());
106
John McCallbabc9a92010-08-22 00:59:17 +0000107 const llvm::IntegerType *ptrdiff = CGF.IntPtrTy;
108 llvm::Constant *ptrdiff_1 = llvm::ConstantInt::get(ptrdiff, 1);
John McCall93d557b2010-08-22 00:05:51 +0000109
John McCallbabc9a92010-08-22 00:59:17 +0000110 llvm::BasicBlock *FnVirtual = CGF.createBasicBlock("memptr.virtual");
111 llvm::BasicBlock *FnNonVirtual = CGF.createBasicBlock("memptr.nonvirtual");
112 llvm::BasicBlock *FnEnd = CGF.createBasicBlock("memptr.end");
113
114 // Load memptr.adj, which is in the second field.
115 llvm::Value *RawAdj = Builder.CreateStructGEP(MemFnPtr, 1);
116 RawAdj = Builder.CreateLoad(RawAdj, "memptr.adj");
117
118 // Compute the true adjustment.
119 llvm::Value *Adj = RawAdj;
120 if (IsARM)
121 Adj = Builder.CreateAShr(Adj, ptrdiff_1, "memptr.adj.shifted");
John McCall93d557b2010-08-22 00:05:51 +0000122
123 // Apply the adjustment and cast back to the original struct type
124 // for consistency.
John McCallbabc9a92010-08-22 00:59:17 +0000125 llvm::Value *Ptr = Builder.CreateBitCast(This, Builder.getInt8PtrTy());
126 Ptr = Builder.CreateInBoundsGEP(Ptr, Adj);
127 This = Builder.CreateBitCast(Ptr, This->getType(), "this.adjusted");
John McCall93d557b2010-08-22 00:05:51 +0000128
129 // Load the function pointer.
John McCallbabc9a92010-08-22 00:59:17 +0000130 llvm::Value *FnPtr = Builder.CreateStructGEP(MemFnPtr, 0);
131 llvm::Value *FnAsInt = Builder.CreateLoad(FnPtr, "memptr.ptr");
John McCall93d557b2010-08-22 00:05:51 +0000132
133 // If the LSB in the function pointer is 1, the function pointer points to
134 // a virtual function.
John McCallbabc9a92010-08-22 00:59:17 +0000135 llvm::Value *IsVirtual;
136 if (IsARM)
137 IsVirtual = Builder.CreateAnd(RawAdj, ptrdiff_1);
138 else
139 IsVirtual = Builder.CreateAnd(FnAsInt, ptrdiff_1);
140 IsVirtual = Builder.CreateIsNotNull(IsVirtual, "memptr.isvirtual");
John McCall93d557b2010-08-22 00:05:51 +0000141 Builder.CreateCondBr(IsVirtual, FnVirtual, FnNonVirtual);
142
143 // In the virtual path, the adjustment left 'This' pointing to the
144 // vtable of the correct base subobject. The "function pointer" is an
John McCallbabc9a92010-08-22 00:59:17 +0000145 // offset within the vtable (+1 for the virtual flag on non-ARM).
John McCall93d557b2010-08-22 00:05:51 +0000146 CGF.EmitBlock(FnVirtual);
147
148 // Cast the adjusted this to a pointer to vtable pointer and load.
149 const llvm::Type *VTableTy = Builder.getInt8PtrTy();
150 llvm::Value *VTable = Builder.CreateBitCast(This, VTableTy->getPointerTo());
John McCallbabc9a92010-08-22 00:59:17 +0000151 VTable = Builder.CreateLoad(VTable, "memptr.vtable");
John McCall93d557b2010-08-22 00:05:51 +0000152
153 // Apply the offset.
John McCallbabc9a92010-08-22 00:59:17 +0000154 llvm::Value *VTableOffset = FnAsInt;
155 if (!IsARM) VTableOffset = Builder.CreateSub(VTableOffset, ptrdiff_1);
156 VTable = Builder.CreateGEP(VTable, VTableOffset);
John McCall93d557b2010-08-22 00:05:51 +0000157
158 // Load the virtual function to call.
159 VTable = Builder.CreateBitCast(VTable, FTy->getPointerTo()->getPointerTo());
John McCallbabc9a92010-08-22 00:59:17 +0000160 llvm::Value *VirtualFn = Builder.CreateLoad(VTable, "memptr.virtualfn");
John McCall93d557b2010-08-22 00:05:51 +0000161 CGF.EmitBranch(FnEnd);
162
163 // In the non-virtual path, the function pointer is actually a
164 // function pointer.
165 CGF.EmitBlock(FnNonVirtual);
166 llvm::Value *NonVirtualFn =
John McCallbabc9a92010-08-22 00:59:17 +0000167 Builder.CreateIntToPtr(FnAsInt, FTy->getPointerTo(), "memptr.nonvirtualfn");
John McCall93d557b2010-08-22 00:05:51 +0000168
169 // We're done.
170 CGF.EmitBlock(FnEnd);
171 llvm::PHINode *Callee = Builder.CreatePHI(FTy->getPointerTo());
172 Callee->reserveOperandSpace(2);
173 Callee->addIncoming(VirtualFn, FnVirtual);
174 Callee->addIncoming(NonVirtualFn, FnNonVirtual);
175 return Callee;
176}
John McCall3023def2010-08-22 03:04:22 +0000177
178/// Perform a derived-to-base or base-to-derived member pointer conversion.
179void ItaniumCXXABI::EmitMemberPointerConversion(CodeGenFunction &CGF,
180 const CastExpr *E,
181 llvm::Value *Src,
182 llvm::Value *Dest,
183 bool VolatileDest) {
184 assert(E->getCastKind() == CastExpr::CK_DerivedToBaseMemberPointer ||
185 E->getCastKind() == CastExpr::CK_BaseToDerivedMemberPointer);
186
187 CGBuilderTy &Builder = CGF.Builder;
188
189 const MemberPointerType *SrcTy =
190 E->getSubExpr()->getType()->getAs<MemberPointerType>();
191 const MemberPointerType *DestTy = E->getType()->getAs<MemberPointerType>();
192
193 const CXXRecordDecl *SrcDecl = SrcTy->getClass()->getAsCXXRecordDecl();
194 const CXXRecordDecl *DestDecl = DestTy->getClass()->getAsCXXRecordDecl();
195
196 llvm::Value *SrcPtr = Builder.CreateStructGEP(Src, 0, "src.ptr");
197 SrcPtr = Builder.CreateLoad(SrcPtr);
198
199 llvm::Value *SrcAdj = Builder.CreateStructGEP(Src, 1, "src.adj");
200 SrcAdj = Builder.CreateLoad(SrcAdj);
201
202 llvm::Value *DstPtr = Builder.CreateStructGEP(Dest, 0, "dst.ptr");
203 Builder.CreateStore(SrcPtr, DstPtr, VolatileDest);
204
205 llvm::Value *DstAdj = Builder.CreateStructGEP(Dest, 1, "dst.adj");
206
207 bool DerivedToBase =
208 E->getCastKind() == CastExpr::CK_DerivedToBaseMemberPointer;
209
210 const CXXRecordDecl *BaseDecl, *DerivedDecl;
211 if (DerivedToBase)
212 DerivedDecl = SrcDecl, BaseDecl = DestDecl;
213 else
214 BaseDecl = SrcDecl, DerivedDecl = DestDecl;
215
216 if (llvm::Constant *Adj =
217 CGF.CGM.GetNonVirtualBaseClassOffset(DerivedDecl,
218 E->path_begin(),
219 E->path_end())) {
220 if (DerivedToBase)
221 SrcAdj = Builder.CreateSub(SrcAdj, Adj, "adj");
222 else
223 SrcAdj = Builder.CreateAdd(SrcAdj, Adj, "adj");
224 }
225
226 Builder.CreateStore(SrcAdj, DstAdj, VolatileDest);
227}