blob: 9ab7591ca2c4206236739681b36e8efa3b394e0c [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);
Charles Davis3a811f12010-05-25 19:52:27 +000049};
John McCallee79a4c2010-08-21 22:46:04 +000050
51class ARMCXXABI : public ItaniumCXXABI {
52public:
John McCallbabc9a92010-08-22 00:59:17 +000053 ARMCXXABI(CodeGen::CodeGenModule &CGM) : ItaniumCXXABI(CGM, /*ARM*/ true) {}
John McCallee79a4c2010-08-21 22:46:04 +000054};
Charles Davis3a811f12010-05-25 19:52:27 +000055}
56
Charles Davis071cc7d2010-08-16 03:33:14 +000057CodeGen::CGCXXABI *CodeGen::CreateItaniumCXXABI(CodeGenModule &CGM) {
Charles Davis3a811f12010-05-25 19:52:27 +000058 return new ItaniumCXXABI(CGM);
59}
60
John McCallee79a4c2010-08-21 22:46:04 +000061CodeGen::CGCXXABI *CodeGen::CreateARMCXXABI(CodeGenModule &CGM) {
62 return new ARMCXXABI(CGM);
63}
64
John McCallbabc9a92010-08-22 00:59:17 +000065/// In the Itanium and ARM ABIs, method pointers have the form:
66/// struct { ptrdiff_t ptr; ptrdiff_t adj; } memptr;
67///
68/// In the Itanium ABI:
69/// - method pointers are virtual if (memptr.ptr & 1) is nonzero
70/// - the this-adjustment is (memptr.adj)
71/// - the virtual offset is (memptr.ptr - 1)
72///
73/// In the ARM ABI:
74/// - method pointers are virtual if (memptr.adj & 1) is nonzero
75/// - the this-adjustment is (memptr.adj >> 1)
76/// - the virtual offset is (memptr.ptr)
77/// ARM uses 'adj' for the virtual flag because Thumb functions
78/// may be only single-byte aligned.
79///
80/// If the member is virtual, the adjusted 'this' pointer points
81/// to a vtable pointer from which the virtual offset is applied.
82///
83/// If the member is non-virtual, memptr.ptr is the address of
84/// the function to call.
John McCall93d557b2010-08-22 00:05:51 +000085llvm::Value *
86ItaniumCXXABI::EmitLoadOfMemberFunctionPointer(CodeGenFunction &CGF,
87 llvm::Value *&This,
88 llvm::Value *MemFnPtr,
89 const MemberPointerType *MPT) {
90 CGBuilderTy &Builder = CGF.Builder;
91
92 const FunctionProtoType *FPT =
93 MPT->getPointeeType()->getAs<FunctionProtoType>();
94 const CXXRecordDecl *RD =
95 cast<CXXRecordDecl>(MPT->getClass()->getAs<RecordType>()->getDecl());
96
97 const llvm::FunctionType *FTy =
98 CGM.getTypes().GetFunctionType(CGM.getTypes().getFunctionInfo(RD, FPT),
99 FPT->isVariadic());
100
John McCallbabc9a92010-08-22 00:59:17 +0000101 const llvm::IntegerType *ptrdiff = CGF.IntPtrTy;
102 llvm::Constant *ptrdiff_1 = llvm::ConstantInt::get(ptrdiff, 1);
John McCall93d557b2010-08-22 00:05:51 +0000103
John McCallbabc9a92010-08-22 00:59:17 +0000104 llvm::BasicBlock *FnVirtual = CGF.createBasicBlock("memptr.virtual");
105 llvm::BasicBlock *FnNonVirtual = CGF.createBasicBlock("memptr.nonvirtual");
106 llvm::BasicBlock *FnEnd = CGF.createBasicBlock("memptr.end");
107
108 // Load memptr.adj, which is in the second field.
109 llvm::Value *RawAdj = Builder.CreateStructGEP(MemFnPtr, 1);
110 RawAdj = Builder.CreateLoad(RawAdj, "memptr.adj");
111
112 // Compute the true adjustment.
113 llvm::Value *Adj = RawAdj;
114 if (IsARM)
115 Adj = Builder.CreateAShr(Adj, ptrdiff_1, "memptr.adj.shifted");
John McCall93d557b2010-08-22 00:05:51 +0000116
117 // Apply the adjustment and cast back to the original struct type
118 // for consistency.
John McCallbabc9a92010-08-22 00:59:17 +0000119 llvm::Value *Ptr = Builder.CreateBitCast(This, Builder.getInt8PtrTy());
120 Ptr = Builder.CreateInBoundsGEP(Ptr, Adj);
121 This = Builder.CreateBitCast(Ptr, This->getType(), "this.adjusted");
John McCall93d557b2010-08-22 00:05:51 +0000122
123 // Load the function pointer.
John McCallbabc9a92010-08-22 00:59:17 +0000124 llvm::Value *FnPtr = Builder.CreateStructGEP(MemFnPtr, 0);
125 llvm::Value *FnAsInt = Builder.CreateLoad(FnPtr, "memptr.ptr");
John McCall93d557b2010-08-22 00:05:51 +0000126
127 // If the LSB in the function pointer is 1, the function pointer points to
128 // a virtual function.
John McCallbabc9a92010-08-22 00:59:17 +0000129 llvm::Value *IsVirtual;
130 if (IsARM)
131 IsVirtual = Builder.CreateAnd(RawAdj, ptrdiff_1);
132 else
133 IsVirtual = Builder.CreateAnd(FnAsInt, ptrdiff_1);
134 IsVirtual = Builder.CreateIsNotNull(IsVirtual, "memptr.isvirtual");
John McCall93d557b2010-08-22 00:05:51 +0000135 Builder.CreateCondBr(IsVirtual, FnVirtual, FnNonVirtual);
136
137 // In the virtual path, the adjustment left 'This' pointing to the
138 // vtable of the correct base subobject. The "function pointer" is an
John McCallbabc9a92010-08-22 00:59:17 +0000139 // offset within the vtable (+1 for the virtual flag on non-ARM).
John McCall93d557b2010-08-22 00:05:51 +0000140 CGF.EmitBlock(FnVirtual);
141
142 // Cast the adjusted this to a pointer to vtable pointer and load.
143 const llvm::Type *VTableTy = Builder.getInt8PtrTy();
144 llvm::Value *VTable = Builder.CreateBitCast(This, VTableTy->getPointerTo());
John McCallbabc9a92010-08-22 00:59:17 +0000145 VTable = Builder.CreateLoad(VTable, "memptr.vtable");
John McCall93d557b2010-08-22 00:05:51 +0000146
147 // Apply the offset.
John McCallbabc9a92010-08-22 00:59:17 +0000148 llvm::Value *VTableOffset = FnAsInt;
149 if (!IsARM) VTableOffset = Builder.CreateSub(VTableOffset, ptrdiff_1);
150 VTable = Builder.CreateGEP(VTable, VTableOffset);
John McCall93d557b2010-08-22 00:05:51 +0000151
152 // Load the virtual function to call.
153 VTable = Builder.CreateBitCast(VTable, FTy->getPointerTo()->getPointerTo());
John McCallbabc9a92010-08-22 00:59:17 +0000154 llvm::Value *VirtualFn = Builder.CreateLoad(VTable, "memptr.virtualfn");
John McCall93d557b2010-08-22 00:05:51 +0000155 CGF.EmitBranch(FnEnd);
156
157 // In the non-virtual path, the function pointer is actually a
158 // function pointer.
159 CGF.EmitBlock(FnNonVirtual);
160 llvm::Value *NonVirtualFn =
John McCallbabc9a92010-08-22 00:59:17 +0000161 Builder.CreateIntToPtr(FnAsInt, FTy->getPointerTo(), "memptr.nonvirtualfn");
John McCall93d557b2010-08-22 00:05:51 +0000162
163 // We're done.
164 CGF.EmitBlock(FnEnd);
165 llvm::PHINode *Callee = Builder.CreatePHI(FTy->getPointerTo());
166 Callee->reserveOperandSpace(2);
167 Callee->addIncoming(VirtualFn, FnVirtual);
168 Callee->addIncoming(NonVirtualFn, FnNonVirtual);
169 return Callee;
170}