blob: f9152db424930a4cf867508099512a7ae177206d [file] [log] [blame]
Charles Davis4e786dd2010-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 McCall86353412010-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 Davis4e786dd2010-05-25 19:52:27 +000019//===----------------------------------------------------------------------===//
20
21#include "CGCXXABI.h"
John McCall475999d2010-08-22 00:05:51 +000022#include "CodeGenFunction.h"
Charles Davis4e786dd2010-05-25 19:52:27 +000023#include "CodeGenModule.h"
24#include "Mangle.h"
John McCall475999d2010-08-22 00:05:51 +000025#include <clang/AST/Type.h>
26#include <llvm/Value.h>
Charles Davis4e786dd2010-05-25 19:52:27 +000027
28using namespace clang;
John McCall475999d2010-08-22 00:05:51 +000029using namespace CodeGen;
Charles Davis4e786dd2010-05-25 19:52:27 +000030
31namespace {
Charles Davis53c59df2010-08-16 03:33:14 +000032class ItaniumCXXABI : public CodeGen::CGCXXABI {
John McCall475999d2010-08-22 00:05:51 +000033protected:
34 CodeGenModule &CGM;
Charles Davis4e786dd2010-05-25 19:52:27 +000035 CodeGen::MangleContext MangleCtx;
36public:
37 ItaniumCXXABI(CodeGen::CodeGenModule &CGM) :
John McCall475999d2010-08-22 00:05:51 +000038 CGM(CGM), MangleCtx(CGM.getContext(), CGM.getDiags()) { }
Charles Davis4e786dd2010-05-25 19:52:27 +000039
40 CodeGen::MangleContext &getMangleContext() {
41 return MangleCtx;
42 }
John McCall475999d2010-08-22 00:05:51 +000043
44 llvm::Value *EmitLoadOfMemberFunctionPointer(CodeGenFunction &CGF,
45 llvm::Value *&This,
46 llvm::Value *MemFnPtr,
47 const MemberPointerType *MPT);
Charles Davis4e786dd2010-05-25 19:52:27 +000048};
John McCall86353412010-08-21 22:46:04 +000049
50class ARMCXXABI : public ItaniumCXXABI {
51public:
52 ARMCXXABI(CodeGen::CodeGenModule &CGM) : ItaniumCXXABI(CGM) {}
53};
Charles Davis4e786dd2010-05-25 19:52:27 +000054}
55
Charles Davis53c59df2010-08-16 03:33:14 +000056CodeGen::CGCXXABI *CodeGen::CreateItaniumCXXABI(CodeGenModule &CGM) {
Charles Davis4e786dd2010-05-25 19:52:27 +000057 return new ItaniumCXXABI(CGM);
58}
59
John McCall86353412010-08-21 22:46:04 +000060CodeGen::CGCXXABI *CodeGen::CreateARMCXXABI(CodeGenModule &CGM) {
61 return new ARMCXXABI(CGM);
62}
63
John McCall475999d2010-08-22 00:05:51 +000064llvm::Value *
65ItaniumCXXABI::EmitLoadOfMemberFunctionPointer(CodeGenFunction &CGF,
66 llvm::Value *&This,
67 llvm::Value *MemFnPtr,
68 const MemberPointerType *MPT) {
69 CGBuilderTy &Builder = CGF.Builder;
70
71 const FunctionProtoType *FPT =
72 MPT->getPointeeType()->getAs<FunctionProtoType>();
73 const CXXRecordDecl *RD =
74 cast<CXXRecordDecl>(MPT->getClass()->getAs<RecordType>()->getDecl());
75
76 const llvm::FunctionType *FTy =
77 CGM.getTypes().GetFunctionType(CGM.getTypes().getFunctionInfo(RD, FPT),
78 FPT->isVariadic());
79
80 llvm::BasicBlock *FnVirtual = CGF.createBasicBlock("fn.virtual");
81 llvm::BasicBlock *FnNonVirtual = CGF.createBasicBlock("fn.nonvirtual");
82 llvm::BasicBlock *FnEnd = CGF.createBasicBlock("fn.end");
83
84 // Load the adjustment, which is in the second field.
85 llvm::Value *Adj = Builder.CreateStructGEP(MemFnPtr, 1);
86 Adj = Builder.CreateLoad(Adj, "mem.fn.adj");
87
88 // Apply the adjustment and cast back to the original struct type
89 // for consistency.
90 llvm::Value *Ptr = Builder.CreateBitCast(This, Builder.getInt8PtrTy(), "ptr");
91 Ptr = Builder.CreateInBoundsGEP(Ptr, Adj, "adj");
92 This = Builder.CreateBitCast(Ptr, This->getType(), "this");
93
94 // Load the function pointer.
95 llvm::Value *FnPtr = Builder.CreateStructGEP(MemFnPtr, 0, "mem.fn.ptr");
96 llvm::Value *FnAsInt = Builder.CreateLoad(FnPtr, "fn");
97
98 // If the LSB in the function pointer is 1, the function pointer points to
99 // a virtual function.
100 llvm::Constant *iptr_1 = llvm::ConstantInt::get(FnAsInt->getType(), 1);
101 llvm::Value *IsVirtual = Builder.CreateAnd(FnAsInt, iptr_1);
102 IsVirtual = Builder.CreateIsNotNull(IsVirtual);
103 Builder.CreateCondBr(IsVirtual, FnVirtual, FnNonVirtual);
104
105 // In the virtual path, the adjustment left 'This' pointing to the
106 // vtable of the correct base subobject. The "function pointer" is an
107 // offset within the vtable (+1 for the virtual flag).
108 CGF.EmitBlock(FnVirtual);
109
110 // Cast the adjusted this to a pointer to vtable pointer and load.
111 const llvm::Type *VTableTy = Builder.getInt8PtrTy();
112 llvm::Value *VTable = Builder.CreateBitCast(This, VTableTy->getPointerTo());
113 VTable = Builder.CreateLoad(VTable);
114
115 // Apply the offset.
116 llvm::Value *VTableOffset = Builder.CreateSub(FnAsInt, iptr_1);
117 VTable = Builder.CreateGEP(VTable, VTableOffset, "fn");
118
119 // Load the virtual function to call.
120 VTable = Builder.CreateBitCast(VTable, FTy->getPointerTo()->getPointerTo());
121 llvm::Value *VirtualFn = Builder.CreateLoad(VTable, "virtualfn");
122 CGF.EmitBranch(FnEnd);
123
124 // In the non-virtual path, the function pointer is actually a
125 // function pointer.
126 CGF.EmitBlock(FnNonVirtual);
127 llvm::Value *NonVirtualFn =
128 Builder.CreateIntToPtr(FnAsInt, FTy->getPointerTo());
129
130 // We're done.
131 CGF.EmitBlock(FnEnd);
132 llvm::PHINode *Callee = Builder.CreatePHI(FTy->getPointerTo());
133 Callee->reserveOperandSpace(2);
134 Callee->addIncoming(VirtualFn, FnVirtual);
135 Callee->addIncoming(NonVirtualFn, FnNonVirtual);
136 return Callee;
137}