blob: 537e4574dd69a6474368367ee9fb4c096405d8ee [file] [log] [blame]
Charles Davis74ce8592010-06-09 23:25:41 +00001//===--- MicrosoftCXXABI.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//
Chris Lattner57540c52011-04-15 05:22:18 +000010// This provides C++ code generation targeting the Microsoft Visual C++ ABI.
Charles Davis74ce8592010-06-09 23:25:41 +000011// The class in this file generates structures that follow the Microsoft
12// Visual C++ ABI, which is actually not very well documented at all outside
13// of Microsoft.
14//
15//===----------------------------------------------------------------------===//
16
17#include "CGCXXABI.h"
18#include "CodeGenModule.h"
Charles Davis74ce8592010-06-09 23:25:41 +000019#include "clang/AST/Decl.h"
20#include "clang/AST/DeclCXX.h"
Charles Davis74ce8592010-06-09 23:25:41 +000021
22using namespace clang;
23using namespace CodeGen;
24
25namespace {
26
Charles Davis53c59df2010-08-16 03:33:14 +000027class MicrosoftCXXABI : public CGCXXABI {
Charles Davis74ce8592010-06-09 23:25:41 +000028public:
Peter Collingbourne0ff0b372011-01-13 18:57:25 +000029 MicrosoftCXXABI(CodeGenModule &CGM) : CGCXXABI(CGM) {}
John McCall5d865c322010-08-31 07:33:07 +000030
Joao Matos2ce88ef2012-07-17 17:10:11 +000031 StringRef GetPureVirtualCallName() { return "_purecall"; }
David Blaikieeb7d5982012-10-16 22:56:05 +000032 // No known support for deleted functions in MSVC yet, so this choice is
33 // arbitrary.
34 StringRef GetDeletedVirtualCallName() { return "_purecall"; }
Joao Matos2ce88ef2012-07-17 17:10:11 +000035
John McCall82fb8922012-09-25 10:10:39 +000036 llvm::Value *adjustToCompleteObject(CodeGenFunction &CGF,
37 llvm::Value *ptr,
38 QualType type);
39
John McCall5d865c322010-08-31 07:33:07 +000040 void BuildConstructorSignature(const CXXConstructorDecl *Ctor,
41 CXXCtorType Type,
42 CanQualType &ResTy,
John McCall0f999f32012-09-25 08:00:39 +000043 SmallVectorImpl<CanQualType> &ArgTys);
John McCall5d865c322010-08-31 07:33:07 +000044
45 void BuildDestructorSignature(const CXXDestructorDecl *Ctor,
46 CXXDtorType Type,
47 CanQualType &ResTy,
Timur Iskhodzhanovee6bc532013-02-13 08:37:51 +000048 SmallVectorImpl<CanQualType> &ArgTys);
John McCall5d865c322010-08-31 07:33:07 +000049
50 void BuildInstanceFunctionParams(CodeGenFunction &CGF,
51 QualType &ResTy,
John McCall0f999f32012-09-25 08:00:39 +000052 FunctionArgList &Params);
John McCall5d865c322010-08-31 07:33:07 +000053
John McCall0f999f32012-09-25 08:00:39 +000054 void EmitInstanceFunctionProlog(CodeGenFunction &CGF);
John McCall29036752011-01-27 02:46:02 +000055
John McCallc84ed6a2012-05-01 06:13:13 +000056 void EmitGuardedInit(CodeGenFunction &CGF, const VarDecl &D,
57 llvm::GlobalVariable *DeclPtr,
58 bool PerformInit);
59
John McCall29036752011-01-27 02:46:02 +000060 // ==== Notes on array cookies =========
61 //
62 // MSVC seems to only use cookies when the class has a destructor; a
63 // two-argument usual array deallocation function isn't sufficient.
64 //
65 // For example, this code prints "100" and "1":
66 // struct A {
67 // char x;
68 // void *operator new[](size_t sz) {
69 // printf("%u\n", sz);
70 // return malloc(sz);
71 // }
72 // void operator delete[](void *p, size_t sz) {
73 // printf("%u\n", sz);
74 // free(p);
75 // }
76 // };
77 // int main() {
78 // A *p = new A[100];
79 // delete[] p;
80 // }
81 // Whereas it prints "104" and "104" if you give A a destructor.
John McCallb91cd662012-05-01 05:23:51 +000082
83 bool requiresArrayCookie(const CXXDeleteExpr *expr, QualType elementType);
84 bool requiresArrayCookie(const CXXNewExpr *expr);
85 CharUnits getArrayCookieSizeImpl(QualType type);
86 llvm::Value *InitializeArrayCookie(CodeGenFunction &CGF,
87 llvm::Value *NewPtr,
88 llvm::Value *NumElements,
89 const CXXNewExpr *expr,
90 QualType ElementType);
91 llvm::Value *readArrayCookieImpl(CodeGenFunction &CGF,
92 llvm::Value *allocPtr,
93 CharUnits cookieSize);
John McCall0f999f32012-09-25 08:00:39 +000094 static bool needThisReturn(GlobalDecl GD);
Charles Davis74ce8592010-06-09 23:25:41 +000095};
96
97}
98
John McCall82fb8922012-09-25 10:10:39 +000099llvm::Value *MicrosoftCXXABI::adjustToCompleteObject(CodeGenFunction &CGF,
100 llvm::Value *ptr,
101 QualType type) {
102 // FIXME: implement
103 return ptr;
104}
105
John McCall0f999f32012-09-25 08:00:39 +0000106bool MicrosoftCXXABI::needThisReturn(GlobalDecl GD) {
107 const CXXMethodDecl* MD = cast<CXXMethodDecl>(GD.getDecl());
108 return isa<CXXConstructorDecl>(MD);
109}
110
111void MicrosoftCXXABI::BuildConstructorSignature(const CXXConstructorDecl *Ctor,
112 CXXCtorType Type,
113 CanQualType &ResTy,
114 SmallVectorImpl<CanQualType> &ArgTys) {
115 // 'this' is already in place
116 // TODO: 'for base' flag
117 // Ctor returns this ptr
118 ResTy = ArgTys[0];
119}
120
Timur Iskhodzhanovee6bc532013-02-13 08:37:51 +0000121void MicrosoftCXXABI::BuildDestructorSignature(const CXXDestructorDecl *Dtor,
122 CXXDtorType Type,
123 CanQualType &ResTy,
124 SmallVectorImpl<CanQualType> &ArgTys) {
125 // 'this' is already in place
126 // TODO: 'for base' flag
127
128 if (Type == Dtor_Deleting) {
129 // The scalar deleting destructor takes an implicit bool parameter.
130 ArgTys.push_back(CGM.getContext().BoolTy);
131 }
132}
133
134static bool IsDeletingDtor(GlobalDecl GD) {
135 const CXXMethodDecl* MD = cast<CXXMethodDecl>(GD.getDecl());
136 if (isa<CXXDestructorDecl>(MD)) {
137 return GD.getDtorType() == Dtor_Deleting;
138 }
139 return false;
140}
141
John McCall0f999f32012-09-25 08:00:39 +0000142void MicrosoftCXXABI::BuildInstanceFunctionParams(CodeGenFunction &CGF,
143 QualType &ResTy,
144 FunctionArgList &Params) {
145 BuildThisParam(CGF, Params);
146 if (needThisReturn(CGF.CurGD)) {
147 ResTy = Params[0]->getType();
148 }
Timur Iskhodzhanovee6bc532013-02-13 08:37:51 +0000149 if (IsDeletingDtor(CGF.CurGD)) {
150 ASTContext &Context = getContext();
151
152 ImplicitParamDecl *ShouldDelete
153 = ImplicitParamDecl::Create(Context, 0,
154 CGF.CurGD.getDecl()->getLocation(),
155 &Context.Idents.get("should_call_delete"),
156 Context.BoolTy);
157 Params.push_back(ShouldDelete);
158 getStructorImplicitParamDecl(CGF) = ShouldDelete;
159 }
John McCall0f999f32012-09-25 08:00:39 +0000160}
161
162void MicrosoftCXXABI::EmitInstanceFunctionProlog(CodeGenFunction &CGF) {
163 EmitThisParam(CGF);
164 if (needThisReturn(CGF.CurGD)) {
165 CGF.Builder.CreateStore(getThisValue(CGF), CGF.ReturnValue);
166 }
Timur Iskhodzhanovee6bc532013-02-13 08:37:51 +0000167 if (IsDeletingDtor(CGF.CurGD)) {
168 assert(getStructorImplicitParamDecl(CGF) &&
169 "no implicit parameter for a deleting destructor?");
170 getStructorImplicitParamValue(CGF)
171 = CGF.Builder.CreateLoad(
172 CGF.GetAddrOfLocalVar(getStructorImplicitParamDecl(CGF)),
173 "should_call_delete");
174 }
John McCall0f999f32012-09-25 08:00:39 +0000175}
176
John McCallb91cd662012-05-01 05:23:51 +0000177bool MicrosoftCXXABI::requiresArrayCookie(const CXXDeleteExpr *expr,
178 QualType elementType) {
179 // Microsoft seems to completely ignore the possibility of a
180 // two-argument usual deallocation function.
181 return elementType.isDestructedType();
182}
183
184bool MicrosoftCXXABI::requiresArrayCookie(const CXXNewExpr *expr) {
185 // Microsoft seems to completely ignore the possibility of a
186 // two-argument usual deallocation function.
187 return expr->getAllocatedType().isDestructedType();
188}
189
190CharUnits MicrosoftCXXABI::getArrayCookieSizeImpl(QualType type) {
191 // The array cookie is always a size_t; we then pad that out to the
192 // alignment of the element type.
193 ASTContext &Ctx = getContext();
194 return std::max(Ctx.getTypeSizeInChars(Ctx.getSizeType()),
195 Ctx.getTypeAlignInChars(type));
196}
197
198llvm::Value *MicrosoftCXXABI::readArrayCookieImpl(CodeGenFunction &CGF,
199 llvm::Value *allocPtr,
200 CharUnits cookieSize) {
Micah Villmowea2fea22012-10-25 15:39:14 +0000201 unsigned AS = allocPtr->getType()->getPointerAddressSpace();
John McCallb91cd662012-05-01 05:23:51 +0000202 llvm::Value *numElementsPtr =
203 CGF.Builder.CreateBitCast(allocPtr, CGF.SizeTy->getPointerTo(AS));
204 return CGF.Builder.CreateLoad(numElementsPtr);
205}
206
207llvm::Value* MicrosoftCXXABI::InitializeArrayCookie(CodeGenFunction &CGF,
208 llvm::Value *newPtr,
209 llvm::Value *numElements,
210 const CXXNewExpr *expr,
211 QualType elementType) {
212 assert(requiresArrayCookie(expr));
213
214 // The size of the cookie.
215 CharUnits cookieSize = getArrayCookieSizeImpl(elementType);
216
217 // Compute an offset to the cookie.
218 llvm::Value *cookiePtr = newPtr;
219
220 // Write the number of elements into the appropriate slot.
Micah Villmowea2fea22012-10-25 15:39:14 +0000221 unsigned AS = newPtr->getType()->getPointerAddressSpace();
John McCallb91cd662012-05-01 05:23:51 +0000222 llvm::Value *numElementsPtr
223 = CGF.Builder.CreateBitCast(cookiePtr, CGF.SizeTy->getPointerTo(AS));
224 CGF.Builder.CreateStore(numElements, numElementsPtr);
225
226 // Finally, compute a pointer to the actual data buffer by skipping
227 // over the cookie completely.
228 return CGF.Builder.CreateConstInBoundsGEP1_64(newPtr,
229 cookieSize.getQuantity());
230}
231
John McCallc84ed6a2012-05-01 06:13:13 +0000232void MicrosoftCXXABI::EmitGuardedInit(CodeGenFunction &CGF, const VarDecl &D,
233 llvm::GlobalVariable *DeclPtr,
234 bool PerformInit) {
235 // FIXME: this code was only tested for global initialization.
236 // Not sure whether we want thread-safe static local variables as VS
237 // doesn't make them thread-safe.
238
239 // Emit the initializer and add a global destructor if appropriate.
240 CGF.EmitCXXGlobalVarDeclInit(D, DeclPtr, PerformInit);
241}
242
Charles Davis53c59df2010-08-16 03:33:14 +0000243CGCXXABI *clang::CodeGen::CreateMicrosoftCXXABI(CodeGenModule &CGM) {
Charles Davis74ce8592010-06-09 23:25:41 +0000244 return new MicrosoftCXXABI(CGM);
245}
246